diff --git a/Changelog b/Changelog index 85a971acb..07cf1cf7a 100644 --- a/Changelog +++ b/Changelog @@ -1,7 +1,45 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. +version 2.3: +- AC3 fixed-point decoding +- shuffleplanes filter +- subfile protocol +- Phantom Cine demuxer +- replaygain data export +- VP7 video decoder +- Alias PIX image encoder and decoder +- Improvements to the BRender PIX image decoder +- Improvements to the XBM decoder +- QTKit input device +- improvements to OpenEXR image decoder +- support decoding 16-bit RLE SGI images +- GDI screen grabbing for Windows +- alternative rendition support for HTTP Live Streaming +- AVFoundation input device +- Direct Stream Digital (DSD) decoder +- Magic Lantern Video (MLV) demuxer +- On2 AVC (Audio for Video) decoder +- support for decoding through DXVA2 in ffmpeg +- libbs2b-based stereo-to-binaural audio filter +- libx264 reference frames count limiting depending on level +- native Opus decoder +- display matrix export and rotation api +- WebVTT encoder +- showcqt multimedia filter +- zoompan filter +- signalstats filter +- hqx filter (hq2x, hq3x, hq4x) +- flanger filter +- Image format auto-detection +- LRC demuxer and muxer +- Samba protocol (via libsmbclient) +- WebM DASH Manifest muxer +- libfribidi support in drawtext + + version 2.2: + - HNM version 4 demuxer and video decoder - Live HDS muxer - setsar/setdar filters now support variables in ratio expressions @@ -215,7 +253,7 @@ version 1.1: - JSON captions for TED talks decoding support - SOX Resampler support in libswresample - aselect filter -- SGI RLE 8-bit decoder +- SGI RLE 8-bit / Silicon Graphics RLE 8-bit video decoder - Silicon Graphics Motion Video Compressor 1 & 2 decoder - Silicon Graphics Movie demuxer - apad filter @@ -259,7 +297,9 @@ version 1.0: - RTMPE protocol support - RTMPTE protocol support - showwaves and showspectrum filter -- LucasArts SMUSH playback support +- LucasArts SMUSH SANM playback support +- LucasArts SMUSH VIMA audio decoder (ADPCM) +- LucasArts SMUSH demuxer - SAMI, RealText and SubViewer demuxers and decoders - Heart Of Darkness PAF playback support - iec61883 device @@ -383,6 +423,7 @@ version 0.10: - ffwavesynth decoder - aviocat tool - ffeval tool +- support encoding and decoding 4-channel SGI images version 0.9: diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 954934630..000000000 --- a/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ - -1) Type './configure' to create the configuration. A list of configure -options is printed by running 'configure --help'. - -'configure' can be launched from a directory different from the FFmpeg -sources to build the objects out of tree. To do this, use an absolute -path when launching 'configure', e.g. '/ffmpegdir/ffmpeg/configure'. - -2) Then type 'make' to build FFmpeg. GNU Make 3.81 or later is required. - -3) Type 'make install' to install all binaries and libraries you built. - -NOTICE - - - Non system dependencies (e.g. libx264, libvpx) are disabled by default. diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 000000000..5db912231 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,17 @@ +#Installing FFmpeg: + +1. Type `./configure` to create the configuration. A list of configure +options is printed by running `configure --help`. + + `configure` can be launched from a directory different from the FFmpeg +sources to build the objects out of tree. To do this, use an absolute +path when launching `configure`, e.g. `/ffmpegdir/ffmpeg/configure`. + +2. Then type `make` to build FFmpeg. GNU Make 3.81 or later is required. + +3. Type `make install` to install all binaries and libraries you built. + +NOTICE +------ + + - Non system dependencies (e.g. libx264, libvpx) are disabled by default. diff --git a/LICENSE b/LICENSE.md similarity index 98% rename from LICENSE rename to LICENSE.md index 1f757aa78..04decbf46 100644 --- a/LICENSE +++ b/LICENSE.md @@ -1,4 +1,4 @@ -FFmpeg: +#FFmpeg: Most files in FFmpeg are under the GNU Lesser General Public License version 2.1 or later (LGPL v2.1+). Read the file COPYING.LGPLv2.1 for details. Some other @@ -10,7 +10,7 @@ version 2 or later (GPL v2+). See the file COPYING.GPLv2 for details. None of these parts are used by default, you have to explicitly pass --enable-gpl to configure to activate them. In this case, FFmpeg's license changes to GPL v2+. -Specifically, the GPL parts of FFmpeg are +Specifically, the GPL parts of FFmpeg are: - libpostproc - libmpcodecs diff --git a/MAINTAINERS b/MAINTAINERS index 6a61ebae9..38437725f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -44,8 +44,8 @@ Miscellaneous Areas =================== documentation Stefano Sabatini, Mike Melanson, Timothy Gu -build system (configure,Makefiles) Diego Biurrun, Mans Rullgard -project server Árpád Gereöffy, Michael Niedermayer, Reimar Döffinger, Alexander Strasser +build system (configure, makefiles) Diego Biurrun, Mans Rullgard +project server Árpád Gereöffy, Michael Niedermayer, Reimar Doeffinger, Alexander Strasser presets Robert Swain metadata subsystem Aurelien Jacobs release management Michael Niedermayer @@ -54,8 +54,10 @@ release management Michael Niedermayer Communication ============= -website Robert Swain, Lou Logan -mailinglists Michael Niedermayer, Baptiste Coudurier, Lou Logan +website Robert Swain +fate.ffmpeg.org Timothy Gu +Trac bug tracker Alexander Strasser, Michael Niedermayer, Carl Eugen Hoyos, Lou Logan +mailing lists Michael Niedermayer, Baptiste Coudurier, Lou Logan Google+ Paul B Mahol, Michael Niedermayer, Alexander Strasser Twitter Lou Logan Launchpad Timothy Gu @@ -73,6 +75,7 @@ Other: bprint Nicolas George bswap.h des Reimar Doeffinger + dynarray.h Nicolas George eval.c, eval.h Michael Niedermayer float_dsp Loren Merritt hash Reimar Doeffinger @@ -129,6 +132,7 @@ Generic Parts: tableprint.c, tableprint.h Reimar Doeffinger fixed point FFT: fft* Zeljko Lukac + Text Subtitles Clément Bœsch Codecs: 4xm.c Michael Niedermayer @@ -162,11 +166,13 @@ Codecs: dnxhd* Baptiste Coudurier dpcm.c Mike Melanson dv.c Roman Shaposhnik + dvbsubdec.c Anshul Maheshwari dxa.c Kostya Shishkov eacmv*, eaidct*, eat* Peter Ross exif.c, exif.h Thilo Borgmann - ffv1.c Michael Niedermayer + ffv1* Michael Niedermayer ffwavesynth.c Nicolas George + fic.c Derek Buitenhuis flac* Justin Ruggles flashsv* Benjamin Larsson flicvideo.c Mike Melanson @@ -176,7 +182,7 @@ Codecs: h261* Michael Niedermayer h263* Michael Niedermayer h264* Loren Merritt, Michael Niedermayer - huffyuv.c Michael Niedermayer + huffyuv* Michael Niedermayer, Christophe Gisquet idcinvideo.c Mike Melanson imc* Benjamin Larsson indeo2* Kostya Shishkov @@ -236,12 +242,12 @@ Codecs: rtjpeg.c, rtjpeg.h Reimar Doeffinger rv10.c Michael Niedermayer rv3* Kostya Shishkov - rv4* Kostya Shishkov + rv4* Kostya Shishkov, Christophe Gisquet s3tc* Ivo van Poorten smacker.c Kostya Shishkov smc.c Mike Melanson smvjpegdec.c Ash Hughes - snow.c Michael Niedermayer, Loren Merritt + snow* Michael Niedermayer, Loren Merritt sonic.c Alex Beregszaszi srt* Aurelien Jacobs sunrast.c Ivo van Poorten @@ -260,13 +266,13 @@ Codecs: v410*.c Derek Buitenhuis vb.c Kostya Shishkov vble.c Derek Buitenhuis - vc1* Kostya Shishkov + vc1* Kostya Shishkov, Christophe Gisquet vcr1.c Michael Niedermayer vda_h264_dec.c Xidorn Quan vima.c Paul B Mahol vmnc.c Kostya Shishkov - vorbis_dec.c Denes Balatoni, David Conrad - vorbis_enc.c Oded Shimon + vorbisdec.c Denes Balatoni, David Conrad + vorbisenc.c Oded Shimon vp3* Mike Melanson vp5 Aurelien Jacobs vp6 Aurelien Jacobs @@ -302,16 +308,20 @@ libavdevice libavdevice/avdevice.h - dshow.c Roger Pack + avfoundation.m Thilo Borgmann + dshow.c Roger Pack (CC rogerdpack@gmail.com) fbdev_enc.c Lukasz Marek + gdigrab.c Roger Pack (CC rogerdpack@gmail.com) iec61883.c Georg Lippitsch lavfi Stefano Sabatini libdc1394.c Roman Shaposhnik opengl_enc.c Lukasz Marek pulse_audio_enc.c Lukasz Marek + qtkit.m Thilo Borgmann sdl Stefano Sabatini v4l2.c Luca Abeni vfwcap.c Ramiro Polla + xv.c Lukasz Marek libavfilter =========== @@ -334,6 +344,7 @@ Filters: af_ladspa.c Paul B Mahol af_pan.c Nicolas George avf_avectorscope.c Paul B Mahol + avf_showcqt.c Muhammad Faiz vf_blend.c Paul B Mahol vf_colorbalance.c Paul B Mahol vf_dejudder.c Nicholas Robbins @@ -341,6 +352,7 @@ Filters: vf_drawbox.c/drawgrid Andrey Utkin vf_extractplanes.c Paul B Mahol vf_histogram.c Paul B Mahol + vf_hqx.c Clément Bœsch vf_il.c Paul B Mahol vf_mergeplanes.c Paul B Mahol vf_psnr.c Paul B Mahol @@ -411,6 +423,7 @@ Muxers/Demuxers: matroska.c Aurelien Jacobs matroskadec.c Aurelien Jacobs matroskaenc.c David Conrad + matroska subtitles (matroskaenc.c) John Peebles metadata* Aurelien Jacobs mgsts.c Paul B Mahol microdvd* Aurelien Jacobs @@ -420,14 +433,15 @@ Muxers/Demuxers: mpc.c Kostya Shishkov mpeg.c Michael Niedermayer mpegenc.c Michael Niedermayer - mpegts* Baptiste Coudurier + mpegts.c Marton Balint + mpegtsenc.c Baptiste Coudurier msnwc_tcp.c Ramiro Polla mtv.c Reynaldo H. Verdejo Pinochet mxf* Baptiste Coudurier mxfdec.c Tomas Härdin nistspheredec.c Paul B Mahol nsvdec.c Francois Revol - nut.c Michael Niedermayer + nut* Michael Niedermayer nuv.c Reimar Doeffinger oggdec.c, oggdec.h David Conrad oggenc.c Baptiste Coudurier @@ -462,6 +476,7 @@ Muxers/Demuxers: voc.c Aurelien Jacobs wav.c Michael Niedermayer wc3movie.c Mike Melanson + webm dash (matroskaenc.c) Vignesh Venkatasubramanian webvtt* Matthew J Heaney westwood.c Mike Melanson wtv.c Peter Ross @@ -503,6 +518,8 @@ Amiga / PowerPC Colin Ward Linux / PowerPC Luca Barbato Windows MinGW Alex Beregszaszi, Ramiro Polla Windows Cygwin Victor Paesa +Windows MSVC Matthew Oliver +Windows ICL Matthew Oliver ADI/Blackfin DSP Marc Hoffman Sparc Roman Shaposhnik x86 Michael Niedermayer @@ -529,7 +546,7 @@ Attila Kinali 11F0 F9A6 A1D2 11F6 C745 D10C 6520 BCDD F2DF E765 Baptiste Coudurier 8D77 134D 20CC 9220 201F C5DB 0AC9 325C 5C1A BAAA Ben Littler 3EE3 3723 E560 3214 A8CD 4DEB 2CDB FCE7 768C 8D2C Benoit Fouet B22A 4F4F 43EF 636B BB66 FCDC 0023 AE1E 2985 49C8 -Bœsch Clément 52D0 3A82 D445 F194 DB8B 2B16 87EE 2CB8 F4B8 FCF9 +Clément Bœsch 52D0 3A82 D445 F194 DB8B 2B16 87EE 2CB8 F4B8 FCF9 Daniel Verkamp 78A6 07ED 782C 653E C628 B8B9 F0EB 8DD8 2F0E 21C7 Diego Biurrun 8227 1E31 B6D9 4994 7427 E220 9CAE D6CC 4757 FCC5 FFmpeg release signing key FCF9 86EA 15E6 E293 A564 4F10 B432 2F04 D676 58D8 @@ -544,12 +561,14 @@ Michael Niedermayer 9FF2 128B 147E F673 0BAD F133 611E C787 040B 0FAB Nicolas George 24CE 01CE 9ACC 5CEB 74D8 8D9D B063 D997 36E5 4C93 Panagiotis Issaris 6571 13A3 33D9 3726 F728 AA98 F643 B12E ECF3 E029 Peter Ross A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B -Reimar Döffinger C61D 16E5 9E2C D10C 8958 38A4 0899 A2B9 06D4 D9C7 +Reimar Doeffinger C61D 16E5 9E2C D10C 8958 38A4 0899 A2B9 06D4 D9C7 Reinhard Tartler 9300 5DC2 7E87 6C37 ED7B CA9A 9808 3544 9453 48A4 Reynaldo H. Verdejo Pinochet 6E27 CD34 170C C78E 4D4F 5F40 C18E 077F 3114 452A Robert Swain EE7A 56EA 4A81 A7B5 2001 A521 67FA 362D A2FC 3E71 Sascha Sommer 38A0 F88B 868E 9D3A 97D4 D6A0 E823 706F 1E07 0D3C Stefano Sabatini 0D0B AD6B 5330 BBAD D3D6 6A0C 719C 2839 FC43 2D5F Stephan Hilb 4F38 0B3A 5F39 B99B F505 E562 8D5C 5554 4E17 8863 +Tiancheng "Timothy" Gu 9456 AFC0 814A 8139 E994 8351 7FE6 B095 B582 B0D4 +Tim Nicholson 38CF DB09 3ED0 F607 8B67 6CED 0C0B FC44 8B0B FC83 Tomas Härdin A79D 4E3D F38F 763F 91F5 8B33 A01E 8AE0 41BB 2551 Wei Gao 4269 7741 857A 0E60 9EC5 08D2 4744 4EFA 62C1 87B9 diff --git a/Makefile b/Makefile index 5437c0bea..86b350842 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ include config.mak vpath %.c $(SRC_PATH) vpath %.cpp $(SRC_PATH) vpath %.h $(SRC_PATH) +vpath %.m $(SRC_PATH) vpath %.S $(SRC_PATH) vpath %.asm $(SRC_PATH) vpath %.rc $(SRC_PATH) @@ -29,19 +30,23 @@ $(foreach prog,$(AVBASENAMES),$(eval OBJS-$(prog)-$(CONFIG_OPENCL) += cmdutils_o OBJS-ffmpeg += ffmpeg_opt.o ffmpeg_filter.o OBJS-ffmpeg-$(HAVE_VDPAU_X11) += ffmpeg_vdpau.o +OBJS-ffmpeg-$(HAVE_DXVA2_LIB) += ffmpeg_dxva2.o +OBJS-ffmpeg-$(CONFIG_VDA) += ffmpeg_vda.o + TESTTOOLS = audiogen videogen rotozoom tiny_psnr tiny_ssim base64 HOSTPROGS := $(TESTTOOLS:%=tests/%) doc/print_options TOOLS = qt-faststart trasher uncoded_frame TOOLS-$(CONFIG_ZLIB) += cws2fws -FFLIBS-$(CONFIG_AVDEVICE) += avdevice -FFLIBS-$(CONFIG_AVFILTER) += avfilter -FFLIBS-$(CONFIG_AVFORMAT) += avformat +# $(FFLIBS-yes) needs to be in linking order +FFLIBS-$(CONFIG_AVDEVICE) += avdevice +FFLIBS-$(CONFIG_AVFILTER) += avfilter +FFLIBS-$(CONFIG_AVFORMAT) += avformat +FFLIBS-$(CONFIG_AVCODEC) += avcodec FFLIBS-$(CONFIG_AVRESAMPLE) += avresample -FFLIBS-$(CONFIG_AVCODEC) += avcodec -FFLIBS-$(CONFIG_POSTPROC) += postproc -FFLIBS-$(CONFIG_SWRESAMPLE)+= swresample -FFLIBS-$(CONFIG_SWSCALE) += swscale +FFLIBS-$(CONFIG_POSTPROC) += postproc +FFLIBS-$(CONFIG_SWRESAMPLE) += swresample +FFLIBS-$(CONFIG_SWSCALE) += swscale FFLIBS := avutil @@ -72,9 +77,8 @@ config.h: .config SUBDIR_VARS := CLEANFILES EXAMPLES FFLIBS HOSTPROGS TESTPROGS TOOLS \ HEADERS ARCH_HEADERS BUILT_HEADERS SKIPHEADERS \ - ARMV5TE-OBJS ARMV6-OBJS VFP-OBJS NEON-OBJS \ - ALTIVEC-OBJS VIS-OBJS \ - MMX-OBJS YASM-OBJS \ + ARMV5TE-OBJS ARMV6-OBJS ARMV8-OBJS VFP-OBJS NEON-OBJS \ + ALTIVEC-OBJS MMX-OBJS YASM-OBJS \ MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSPR1-OBJS MIPS32R2-OBJS \ OBJS SLIBOBJS HOSTOBJS TESTOBJS diff --git a/README b/README.md similarity index 95% rename from README rename to README.md index ae007bccc..c8da82079 100644 --- a/README +++ b/README.md @@ -1,10 +1,11 @@ FFmpeg README -------------- +============= 1) Documentation ---------------- * Read the documentation in the doc/ directory in git. + You can also view it online at http://ffmpeg.org/documentation.html 2) Licensing diff --git a/RELEASE b/RELEASE index 21bb5e156..bb576dbde 100644 --- a/RELEASE +++ b/RELEASE @@ -1 +1 @@ -2.2.5 +2.3 diff --git a/RELEASE_NOTES b/RELEASE_NOTES new file mode 100644 index 000000000..07805951c --- /dev/null +++ b/RELEASE_NOTES @@ -0,0 +1,177 @@ + ┌───────────────────────────────────────────┐ + │ RELEASE NOTES for FFmpeg 2.3 "Mandelbrot" │ + └───────────────────────────────────────────┘ + + The FFmpeg Project proudly presents FFmpeg 2.3 "Mandelbrot", a major + release with all the great features committed during the three-month period + since the release of FFmpeg 2.2. + + In this release, there are lots of internal overhauls that make FFmpeg a + more accessible project for new developers. Many important new + optimizations and features like QTKit and AVFoundation input devices are + committed. Contributions done by Libav such as a new native Opus decoder + are also merged. + + Because of the increasing difficulty to maintain and lack of maintainers, + we are very sorry to say that we have removed all Blackfin and SPARC + architecture assembly optimizations with the cleanups done. If you are + interested in maintaining optimization for these two architecture, feel + free to contact us and we will restore the code! + + Oh, and since this release, this modern-looking release note is provided in + addition to the old-style Changelog file, to make it easier for you to + focus on the most important features in this release. + + Enjoy! + + ┌────────────────────────────┐ + │ * API Information │ + └────────────────────────────┘ + + FFmpeg 2.3 is completely source-compatible to the FFmpeg 2.2 series. There + are however some API deprecations that you need to take care of. Use `git + diff n2.2 n2.3 doc/APIchanges` to show the list of added and deprecated + APIs. FFmpeg 2.3 includes the following library versions: + + • libavutil 52.92.100 + • libavcodec 55.69.100 + • libavformat 55.48.100 + • libavdevice 55.13.102 + • libavfilter 4.11.100 + • libswscale 2. 6.100 + • libswresample 0.19.100 + • libpostproc 52. 3.100 + + Please refer to the doc/APIChanges file for more information. + + ┌────────────────────────────┐ + │ New Optimization │ + └────────────────────────────┘ + + We are excited to announce that we have committed new x86 assembly + optimization for HEVC, and FFmpeg's audio resampler libswresample. ARM + users will get a boost in MLP/TrueHD decoding thanks to new optimization. + Decoding Huffyuv also got a major boost from optimization on the C code. + + Of special interest for Microsoft Visual Studio users, we have also + converted some preexisting x86 assembly to NASM/Yasm format compatible + with MSVC setup, especially in the area of audio resampling. + + Another major feature in this release is the introduction of AArch64 + (ARMv8) assembly optimization. AArch64 is another name for the first + 64-bit ARM architecture, used by Apple A7 SoC inside iPhone 5S. Some + 32-bit ARM assembly has already been ported to AArch64, but more work is + underway. + + ┌────────────────────────────┐ + │ Native Opus decoder │ + └────────────────────────────┘ + + Opus is an open audio format jointly developed by Xiph.Org, Mozilla, + Skype/Microsoft, and Broadcom. It combines the features of the Skype Cilk + speech codec and the Xiph.Org CELT music codec into one low-latency + codec. Decoding Opus is already possible since FFmpeg 1.0 using the + libopus library, but the new Opus native decoder brings a higher level of + stability and speed. + + ┌────────────────────────────┐ + │ QTKit and AVFoundation │ + └────────────────────────────┘ + + For OS X users, the new QTKit and AVFoundation devices allow you to use + the integrated camera on Macs. AVFoundation is a newer API only available + on OS X 10.7 "Lion" or newer. For users with older OS X systems, the + QTKit device using the older OS X API is for you. + + ┌────────────────────────────┐ + │ API Additions │ + └────────────────────────────┘ + + In this release, stream side data are introduced as AVStream.side_data as + a way to store miscellaneous stream-wide information. The format is + similar to the previously anonymous structure AVPacket.side_data (now + named as AVPacketSideData). With this change, audio ReplayGain + information and video rotation matrix are now exported through this API, + if available in the demuxer. + + We also have improved libswresample's Doxygen API documentation, so new + developers wishing to use FFmpeg's excellent libraries can get started + more easily and faster. + + ┌────────────────────────────┐ + │ Last But Not Least │ + └────────────────────────────┘ + + Other interesting new features including hqx video filter, a pixel art + scaling filter; a fixed-point AC-3 decoder contributed by Imagination + Technologies; an On2 TrueMotion VP7 video decoder; an HTML5 WebVTT + subtitle decoder that allows creation of WebVTT from any text-based + subtitles; and an 1-bit Direct Stream Digital audio decoder. + + ┌────────────────────────────┐ + │ ★ List of New Features │ + └────────────────────────────┘ + + ┌────────────────────────────┐ + │ Command line tools │ + └────────────────────────────┘ + + • Support for decoding through DXVA2 in ffmpeg + + ┌────────────────────────────┐ + │ libavcodec │ + └────────────────────────────┘ + + • AC3 fixed-point decoding + • VP7 video decoder + • Alias PIX image encoder and decoder + • Improvements to the BRender PIX image decoder + • Improvements to the XBM decoder + • Improvements to OpenEXR image decoder + • Support decoding 16-bit RLE SGI images + • Direct Stream Digital (DSD) decoder + • On2 AVC (Audio for Video) decoder + • Native Opus decoder + • WebVTT encoder + + ┌────────────────────────────┐ + │ libavdevice │ + └────────────────────────────┘ + + • QTKit input device + • GDI screen grabbing for Windows + • AVFoundation input device + + ┌────────────────────────────┐ + │ libavformat │ + └────────────────────────────┘ + + • subfile protocol + • Phantom Cine demuxer + • Alternative rendition support for HTTP Live Streaming + • Magic Lantern Video (MLV) demuxer + • Image format auto-detection + • LRC lyric file demuxer and muxer + • Samba protocol (via libsmbclient) + • WebM DASH Manifest muxer + + ┌────────────────────────────┐ + │ libavfilter │ + └────────────────────────────┘ + + • shuffleplanes filter + • libbs2b-based stereo-to-binaural audio filter + • showcqt multimedia filter + • zoompan filter + • signalstats filter + • hqx filter (hq2x, hq3x, hq4x) + • flanger filter + • libfribidi support in drawtext + + ┌────────────────────────────┐ + │ ⚠ Behaviour changes │ + └────────────────────────────┘ + + • libx264 reference frames count is now limited depending on level chosen + • Because of the new image format auto-detection feature, you don't need to + specify image format when decoding an image with no extension. diff --git a/VERSION b/VERSION index 21bb5e156..bb576dbde 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.5 +2.3 diff --git a/arch.mak b/arch.mak index b71c8e51f..0e866d862 100644 --- a/arch.mak +++ b/arch.mak @@ -1,5 +1,6 @@ OBJS-$(HAVE_ARMV5TE) += $(ARMV5TE-OBJS) $(ARMV5TE-OBJS-yes) OBJS-$(HAVE_ARMV6) += $(ARMV6-OBJS) $(ARMV6-OBJS-yes) +OBJS-$(HAVE_ARMV8) += $(ARMV8-OBJS) $(ARMV8-OBJS-yes) OBJS-$(HAVE_VFP) += $(VFP-OBJS) $(VFP-OBJS-yes) OBJS-$(HAVE_NEON) += $(NEON-OBJS) $(NEON-OBJS-yes) @@ -10,7 +11,5 @@ OBJS-$(HAVE_MIPSDSPR2) += $(MIPSDSPR2-OBJS) $(MIPSDSPR2-OBJS-yes) OBJS-$(HAVE_ALTIVEC) += $(ALTIVEC-OBJS) $(ALTIVEC-OBJS-yes) -OBJS-$(HAVE_VIS) += $(VIS-OBJS) $(VIS-OBJS-yes) - OBJS-$(HAVE_MMX) += $(MMX-OBJS) $(MMX-OBJS-yes) OBJS-$(HAVE_YASM) += $(YASM-OBJS) $(YASM-OBJS-yes) diff --git a/cmdutils.c b/cmdutils.c index dc9bd2cc0..67bb66e9b 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -66,6 +66,7 @@ AVDictionary *swr_opts; AVDictionary *format_opts, *codec_opts, *resample_opts; static FILE *report_file; +static int report_file_level = AV_LOG_DEBUG; int hide_banner = 0; void init_opts(void) @@ -104,8 +105,10 @@ static void log_callback_report(void *ptr, int level, const char *fmt, va_list v av_log_default_callback(ptr, level, fmt, vl); av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix); va_end(vl2); - fputs(line, report_file); - fflush(report_file); + if (report_file_level >= level) { + fputs(line, report_file); + fflush(report_file); + } } static void (*program_exit)(int ret); @@ -552,6 +555,11 @@ int opt_default(void *optctx, const char *opt, const char *arg) } consumed = 1; } +#else + if (!consumed && !strcmp(opt, "sws_flags")) { + av_log(NULL, AV_LOG_WARNING, "Ignoring %s %s, due to disabled swscale\n", opt, arg); + consumed = 1; + } #endif #if CONFIG_SWRESAMPLE swr_class = swr_get_class(); @@ -662,7 +670,7 @@ static void init_parse_context(OptionParseContext *octx, memset(octx, 0, sizeof(*octx)); octx->nb_groups = nb_groups; - octx->groups = av_mallocz(sizeof(*octx->groups) * octx->nb_groups); + octx->groups = av_mallocz_array(octx->nb_groups, sizeof(*octx->groups)); if (!octx->groups) exit_program(1); @@ -834,10 +842,17 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) }; char *tail; int level; + int flags; int i; + flags = av_log_get_flags(); tail = strstr(arg, "repeat"); - av_log_set_flags(tail ? 0 : AV_LOG_SKIP_REPEATED); + if (tail) + flags &= ~AV_LOG_SKIP_REPEATED; + else + flags |= AV_LOG_SKIP_REPEATED; + + av_log_set_flags(flags); if (tail == arg) arg += 6 + (arg[6]=='+'); if(tail && !*arg) @@ -919,6 +934,13 @@ static int init_report(const char *env) av_free(filename_template); filename_template = val; val = NULL; + } else if (!strcmp(key, "level")) { + char *tail; + report_file_level = strtol(val, &tail, 10); + if (*tail) { + av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n"); + exit_program(1); + } } else { av_log(NULL, AV_LOG_ERROR, "Unknown key '%s' in FFREPORT\n", key); } @@ -1098,7 +1120,7 @@ void show_banner(int argc, char **argv, const OptionDef *options) int show_version(void *optctx, const char *opt, const char *arg) { av_log_set_callback(log_callback_help); - print_program_info (0 , AV_LOG_INFO); + print_program_info (SHOW_COPYRIGHT, AV_LOG_INFO); print_all_libs_info(SHOW_VERSION, AV_LOG_INFO); return 0; @@ -1186,16 +1208,29 @@ int show_license(void *optctx, const char *opt, const char *arg) return 0; } -int show_formats(void *optctx, const char *opt, const char *arg) +static int is_device(const AVClass *avclass) +{ + if (!avclass) + return 0; + return avclass->category == AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT || + avclass->category == AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT || + avclass->category == AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT || + avclass->category == AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT || + avclass->category == AV_CLASS_CATEGORY_DEVICE_OUTPUT || + avclass->category == AV_CLASS_CATEGORY_DEVICE_INPUT; +} + +static int show_formats_devices(void *optctx, const char *opt, const char *arg, int device_only) { AVInputFormat *ifmt = NULL; AVOutputFormat *ofmt = NULL; const char *last_name; + int is_dev; - printf("File formats:\n" + printf("%s\n" " D. = Demuxing supported\n" " .E = Muxing supported\n" - " --\n"); + " --\n", device_only ? "Devices:" : "File formats:"); last_name = "000"; for (;;) { int decode = 0; @@ -1204,6 +1239,9 @@ int show_formats(void *optctx, const char *opt, const char *arg) const char *long_name = NULL; while ((ofmt = av_oformat_next(ofmt))) { + is_dev = is_device(ofmt->priv_class); + if (!is_dev && device_only) + continue; if ((name == NULL || strcmp(ofmt->name, name) < 0) && strcmp(ofmt->name, last_name) > 0) { name = ofmt->name; @@ -1212,6 +1250,9 @@ int show_formats(void *optctx, const char *opt, const char *arg) } } while ((ifmt = av_iformat_next(ifmt))) { + is_dev = is_device(ifmt->priv_class); + if (!is_dev && device_only) + continue; if ((name == NULL || strcmp(ifmt->name, name) < 0) && strcmp(ifmt->name, last_name) > 0) { name = ifmt->name; @@ -1234,6 +1275,16 @@ int show_formats(void *optctx, const char *opt, const char *arg) return 0; } +int show_formats(void *optctx, const char *opt, const char *arg) +{ + return show_formats_devices(optctx, opt, arg, 0); +} + +int show_devices(void *optctx, const char *opt, const char *arg) +{ + return show_formats_devices(optctx, opt, arg, 1); +} + #define PRINT_CODEC_SUPPORTED(codec, field, type, list_name, term, get_name) \ if (codec->field) { \ const type *p = codec->field; \ @@ -1378,6 +1429,9 @@ int show_codecs(void *optctx, const char *opt, const char *arg) const AVCodecDescriptor *desc = codecs[i]; const AVCodec *codec = NULL; + if (strstr(desc->name, "_deprecated")) + continue; + printf(" "); printf(avcodec_find_decoder(desc->id) ? "D" : "."); printf(avcodec_find_encoder(desc->id) ? "E" : "."); @@ -1942,7 +1996,8 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, } if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) || - (codec && codec->priv_class && + !codec || + (codec->priv_class && av_opt_find(&codec->priv_class, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ))) av_dict_set(&ret, t->key, t->value, 0); @@ -1965,7 +2020,7 @@ AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, if (!s->nb_streams) return NULL; - opts = av_mallocz(s->nb_streams * sizeof(*opts)); + opts = av_mallocz_array(s->nb_streams, sizeof(*opts)); if (!opts) { av_log(NULL, AV_LOG_ERROR, "Could not alloc memory for stream options.\n"); diff --git a/cmdutils.h b/cmdutils.h index d1e1ecbe7..76d11a598 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -24,12 +24,13 @@ #include +#include "config.h" #include "libavcodec/avcodec.h" #include "libavfilter/avfilter.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" -#ifdef __MINGW32__ +#ifdef _WIN32 #undef main /* We don't want SDL to override our main() */ #endif @@ -58,7 +59,7 @@ void register_exit(void (*cb)(int ret)); /** * Wraps exit with a program-specific cleanup routine. */ -void exit_program(int ret); +void exit_program(int ret) av_noreturn; /** * Initialize the cmdutils option system, in particular @@ -430,11 +431,18 @@ int show_license(void *optctx, const char *opt, const char *arg); /** * Print a listing containing all the formats supported by the - * program. + * program (including devices). * This option processing function does not utilize the arguments. */ int show_formats(void *optctx, const char *opt, const char *arg); +/** + * Print a listing containing all the devices supported by the + * program. + * This option processing function does not utilize the arguments. + */ +int show_devices(void *optctx, const char *opt, const char *arg); + /** * Print a listing containing all the codecs supported by the * program. diff --git a/cmdutils_common_opts.h b/cmdutils_common_opts.h index 190dba674..49b5180e3 100644 --- a/cmdutils_common_opts.h +++ b/cmdutils_common_opts.h @@ -6,6 +6,7 @@ { "version" , OPT_EXIT, {.func_arg = show_version}, "show version" }, { "buildconf" , OPT_EXIT, {.func_arg = show_buildconf}, "show build configuration" }, { "formats" , OPT_EXIT, {.func_arg = show_formats }, "show available formats" }, + { "devices" , OPT_EXIT, {.func_arg = show_devices }, "show available devices" }, { "codecs" , OPT_EXIT, {.func_arg = show_codecs }, "show available codecs" }, { "decoders" , OPT_EXIT, {.func_arg = show_decoders }, "show available decoders" }, { "encoders" , OPT_EXIT, {.func_arg = show_encoders }, "show available encoders" }, diff --git a/cmdutils_opencl.c b/cmdutils_opencl.c index d7e3287e4..3dfd15619 100644 --- a/cmdutils_opencl.c +++ b/cmdutils_opencl.c @@ -181,12 +181,12 @@ static int64_t run_opencl_bench(AVOpenCLExternalEnv *ext_opencl_env) OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_int), &width); OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_int), &height); - start = av_gettime(); + start = av_gettime_relative(); for (i = 0; i < OPENCL_NB_ITER; i++) OCLCHECK(clEnqueueNDRangeKernel, ext_opencl_env->command_queue, kernel, 2, NULL, global_work_size_2d, local_work_size_2d, 0, NULL, NULL); clFinish(ext_opencl_env->command_queue); - ret = (av_gettime() - start)/OPENCL_NB_ITER; + ret = (av_gettime_relative() - start)/OPENCL_NB_ITER; end: if (kernel) clReleaseKernel(kernel); diff --git a/common.mak b/common.mak index b557dff30..a49379265 100644 --- a/common.mak +++ b/common.mak @@ -51,6 +51,9 @@ COMPILE_HOSTC = $(call COMPILE,HOSTCC) %.o: %.cpp $(COMPILE_CXX) +%.o: %.m + $(COMPILE_C) + %.s: %.c $(CC) $(CPPFLAGS) $(CFLAGS) -S -o $@ $< @@ -90,7 +93,7 @@ include $(SRC_PATH)/arch.mak OBJS += $(OBJS-yes) SLIBOBJS += $(SLIBOBJS-yes) -FFLIBS := $(FFLIBS-yes) $(FFLIBS) +FFLIBS := $($(NAME)_FFLIBS) $(FFLIBS-yes) $(FFLIBS) TESTPROGS += $(TESTPROGS-yes) LDLIBS = $(FFLIBS:%=%$(BUILDSUF)) diff --git a/libavcodec/x86/rnd_mmx.c b/compat/float/float.h similarity index 65% rename from libavcodec/x86/rnd_mmx.c rename to compat/float/float.h index 326e2f395..1f0d3ab4b 100644 --- a/libavcodec/x86/rnd_mmx.c +++ b/compat/float/float.h @@ -1,4 +1,6 @@ /* + * Work around broken floating point limits on some systems. + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -16,20 +18,18 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "config.h" -#include "dsputil_x86.h" +#include_next -#if HAVE_INLINE_ASM +#ifdef FLT_MAX +#undef FLT_MAX +#define FLT_MAX 3.40282346638528859812e+38F -#define DEF(x, y) ff_ ## x ## _ ## y ## _mmx -#define SET_RND MOVQ_WTWO -#define PAVGBP(a, b, c, d, e, f) PAVGBP_MMX(a, b, c, d, e, f) -#define PAVGB(a, b, c, e) PAVGB_MMX(a, b, c, e) -#define STATIC +#undef FLT_MIN +#define FLT_MIN 1.17549435082228750797e-38F -#include "rnd_template.c" +#undef DBL_MAX +#define DBL_MAX ((double)1.79769313486231570815e+308L) -PIXELS16(, ff_avg, , _xy2, _mmx) -PIXELS16(, ff_put, , _xy2, _mmx) - -#endif /* HAVE_INLINE_ASM */ +#undef DBL_MIN +#define DBL_MIN ((double)2.22507385850720138309e-308L) +#endif diff --git a/compat/float/limits.h b/compat/float/limits.h new file mode 100644 index 000000000..7ea374a8b --- /dev/null +++ b/compat/float/limits.h @@ -0,0 +1,22 @@ +/* + * Work around broken floating point limits on some systems. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include_next +#include diff --git a/compat/w32pthreads.h b/compat/w32pthreads.h index 7b51c2584..cfb8f6471 100644 --- a/compat/w32pthreads.h +++ b/compat/w32pthreads.h @@ -134,28 +134,29 @@ typedef struct win32_cond_t { volatile int is_broadcast; } win32_cond_t; -static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr) +static int pthread_cond_init(pthread_cond_t *cond, const void *unused_attr) { win32_cond_t *win32_cond = NULL; if (cond_init) { cond_init(cond); - return; + return 0; } /* non native condition variables */ win32_cond = av_mallocz(sizeof(win32_cond_t)); if (!win32_cond) - return; + return ENOMEM; cond->ptr = win32_cond; win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); if (!win32_cond->semaphore) - return; + return ENOMEM; win32_cond->waiters_done = CreateEvent(NULL, TRUE, FALSE, NULL); if (!win32_cond->waiters_done) - return; + return ENOMEM; pthread_mutex_init(&win32_cond->mtx_waiter_count, NULL); pthread_mutex_init(&win32_cond->mtx_broadcast, NULL); + return 0; } static void pthread_cond_destroy(pthread_cond_t *cond) diff --git a/configure b/configure index f9dce4ed9..4ed43a0fd 100755 --- a/configure +++ b/configure @@ -106,7 +106,6 @@ Configuration options: --disable-swscale-alpha disable alpha channel support in swscale --disable-all disable building components, libraries and programs --enable-incompatible-libav-abi enable incompatible Libav fork ABI [no] - --enable-incompatible-fork-abi enable incompatible Libav fork ABI (deprecated) [no] --enable-raise-major increase major version numbers in sonames [no] Program options: @@ -200,6 +199,7 @@ External library support: --enable-libaacplus enable AAC+ encoding via libaacplus [no] --enable-libass enable libass subtitles rendering [no] --enable-libbluray enable BluRay reading using libbluray [no] + --enable-libbs2b enable bs2b DSP library [no] --enable-libcaca enable textual display using libcaca --enable-libcelt enable CELT decoding via libcelt [no] --enable-libcdio enable audio CD grabbing with libcdio @@ -209,6 +209,7 @@ External library support: --enable-libfdk-aac enable AAC de/encoding via libfdk-aac [no] --enable-libflite enable flite (voice synthesis) support via libflite [no] --enable-libfreetype enable libfreetype [no] + --enable-libfribidi enable libfribidi [no] --enable-libgme enable Game Music Emu via libgme [no] --enable-libgsm enable GSM de/encoding via libgsm [no] --enable-libiec61883 enable iec61883 via libiec61883 [no] @@ -221,12 +222,13 @@ External library support: --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 decoding via libopus [no] + --enable-libopus enable Opus de/encoding via libopus [no] --enable-libpulse enable Pulseaudio input via libpulse [no] --enable-libquvi enable quvi input via libquvi [no] --enable-librtmp enable RTMP[E] support via librtmp [no] --enable-libschroedinger enable Dirac de/encoding via libschroedinger [no] --enable-libshine enable fixed-point MP3 encoding via libshine [no] + --enable-libsmbclient enable Samba protocol via libsmbclient [no] --enable-libsoxr enable Include libsoxr resampling [no] --enable-libspeex enable Speex de/encoding via libspeex [no] --enable-libssh enable SFTP protocol via libssh [no] @@ -256,10 +258,15 @@ External library support: --enable-opengl enable OpenGL rendering [no] --enable-openssl enable openssl [no] --enable-x11grab enable X11 grabbing [no] + --disable-xlib disable xlib [autodetect] --disable-zlib disable zlib [autodetect] -Advanced options (experts only): +Toolchain options: + --arch=ARCH select architecture [$arch] + --cpu=CPU select the minimum required CPU (affects + instruction selection, may crash on older CPUs) --cross-prefix=PREFIX use PREFIX for compilation tools [$cross_prefix] + --progs-suffix=SUFFIX program name suffix [] --enable-cross-compile assume a cross-compiler is used --sysroot=PATH root of cross-build tree --sysinclude=PATH location of cross-build system headers @@ -278,6 +285,10 @@ Advanced options (experts only): --cxx=CXX use C compiler CXX [$cxx_default] --dep-cc=DEPCC use dependency generator DEPCC [$cc_default] --ld=LD use linker LD [$ld_default] + --pkg-config=PKGCONFIG use pkg-config tool PKGCONFIG [$pkg_config_default] + --pkg-config-flags=FLAGS pass additional flags to pkgconf [] + --ranlib=RANLIB use ranlib RANLIB [$ranlib_default] + --doxygen=DOXYGEN use DOXYGEN to generate API doc [$doxygen_default] --host-cc=HOSTCC use host C compiler HOSTCC --host-cflags=HCFLAGS use HCFLAGS when compiling for host --host-cppflags=HCPPFLAGS use HCPPFLAGS when compiling for host @@ -292,24 +303,23 @@ Advanced options (experts only): --extra-version=STRING version string suffix [] --optflags=OPTFLAGS override optimization-related compiler flags --build-suffix=SUFFIX library name suffix [] - --malloc-prefix=PREFIX prefix malloc and related names with PREFIX - --progs-suffix=SUFFIX program name suffix [] - --arch=ARCH select architecture [$arch] - --cpu=CPU select the minimum required CPU (affects - instruction selection, may crash on older CPUs) --enable-pic build position-independent code - --enable-sram allow use of on-chip SRAM --enable-thumb compile for Thumb instruction set + --enable-lto use link-time optimization + +Advanced options (experts only): + --malloc-prefix=PREFIX prefix malloc and related names with PREFIX --disable-symver disable symbol versioning --enable-hardcoded-tables use hardcoded tables instead of runtime generation --disable-safe-bitstream-reader disable buffer boundary checking in bitreaders (faster, but may crash) --enable-memalign-hack emulate memalign, interferes with memory debuggers - --enable-lto use link-time optimization + --enable-sram allow use of on-chip SRAM + --sws-max-filter-size=N the max filter size swscale uses [$sws_max_filter_size_default] Optimization options (experts only): - --disable-asm disable all assembler optimizations + --disable-asm disable all assembly optimizations --disable-altivec disable AltiVec optimizations --disable-amd3dnow disable 3DNow! optimizations --disable-amd3dnowext disable 3DNow! extended optimizations @@ -331,9 +341,8 @@ Optimization options (experts only): --disable-armv6t2 disable armv6t2 optimizations --disable-vfp disable VFP optimizations --disable-neon disable NEON optimizations - --disable-vis disable VIS optimizations - --disable-inline-asm disable use of inline assembler - --disable-yasm disable use of yasm assembler + --disable-inline-asm disable use of inline assembly + --disable-yasm disable use of nasm/yasm assembly --disable-mips32r2 disable MIPS32R2 optimizations --disable-mipsdspr1 disable MIPS DSP ASE R1 optimizations --disable-mipsdspr2 disable MIPS DSP ASE R2 optimizations @@ -411,7 +420,7 @@ EOF else cat <> $logfile 2>&1 } +check_stat(){ + log check_stat "$@" + stat "$1" >> $logfile 2>&1 +} + cc_o(){ eval printf '%s\\n' $CC_O } @@ -793,6 +816,13 @@ check_cxx(){ check_cmd $cxx $CPPFLAGS $CFLAGS $CXXFLAGS "$@" $CXX_C -o $TMPO $TMPCPP } +check_oc(){ + log check_oc "$@" + cat > $TMPM + log_file $TMPM + check_cmd $cc -Werror=missing-prototypes $CPPFLAGS $CFLAGS "$@" $CC_C $(cc_o $TMPO) $TMPM +} + check_cpp(){ log check_cpp "$@" cat > $TMPC @@ -938,6 +968,18 @@ int x; EOF } +check_header_oc(){ + log check_header_oc "$@" + rm -f -- "$TMPO" + header=$1 + shift + disable_safe $header + { + echo "#include <$header>" + echo "int main(void) { return 0; }" + } | check_oc && check_stat "$TMPO" && enable_safe $headers +} + check_func(){ log check_func "$@" func=$1 @@ -1043,8 +1085,8 @@ check_pkg_config(){ funcs="$3" shift 3 check_cmd $pkg_config --exists --print-errors $pkgandversion || return - pkg_cflags=$($pkg_config --cflags $pkg) - pkg_libs=$($pkg_config --libs $pkg) + pkg_cflags=$($pkg_config --cflags $pkg_config_flags $pkg) + pkg_libs=$($pkg_config --libs $pkg_config_flags $pkg) check_func_headers "$headers" "$funcs" $pkg_cflags $pkg_libs "$@" && set_safe ${pkg}_cflags $pkg_cflags && set_safe ${pkg}_libs $pkg_libs @@ -1114,6 +1156,16 @@ check_builtin(){ check_code ld "$headers" "$builtin" "cc" "$@" && enable "$name" } +check_compile_assert(){ + log check_compile_assert "$@" + name=$1 + headers=$2 + condition=$3 + shift 3 + disable "$name" + check_code cc "$headers" "char c[2 * !!($condition) - 1]" "$@" && enable "$name" +} + require(){ name="$1" header="$2" @@ -1150,8 +1202,8 @@ require_libfreetype(){ pkg="freetype2" check_cmd $pkg_config --exists --print-errors $pkg \ || die "ERROR: $pkg not found" - pkg_cflags=$($pkg_config --cflags $pkg) - pkg_libs=$($pkg_config --libs $pkg) + pkg_cflags=$($pkg_config --cflags $pkg_config_flags $pkg) + pkg_libs=$($pkg_config --libs $pkg_config_flags $pkg) { echo "#include " echo "#include FT_FREETYPE_H" @@ -1246,7 +1298,7 @@ COMPONENT_LIST=" EXAMPLE_LIST=" avio_reading_example - avcodec_example + decoding_encoding_example demuxing_decoding_example filter_audio_example filtering_audio_example @@ -1257,6 +1309,7 @@ EXAMPLE_LIST=" resampling_audio_example scaling_video_example transcode_aac_example + transcoding_example " EXTERNAL_LIBRARY_LIST=" @@ -1264,7 +1317,6 @@ EXTERNAL_LIBRARY_LIST=" bzlib crystalhd decklink - fontconfig frei0r gnutls iconv @@ -1272,6 +1324,7 @@ EXTERNAL_LIBRARY_LIST=" libaacplus libass libbluray + libbs2b libcaca libcdio libcelt @@ -1279,7 +1332,9 @@ EXTERNAL_LIBRARY_LIST=" libfaac libfdk_aac libflite + libfontconfig libfreetype + libfribidi libgme libgsm libiec61883 @@ -1297,6 +1352,7 @@ EXTERNAL_LIBRARY_LIST=" librtmp libschroedinger libshine + libsmbclient libsoxr libspeex libssh @@ -1323,6 +1379,7 @@ EXTERNAL_LIBRARY_LIST=" opengl openssl x11grab + xlib zlib " @@ -1334,6 +1391,19 @@ DOCUMENT_LIST=" txtpages " +FEATURE_LIST=" + ftrapv + gray + hardcoded_tables + runtime_cpudetect + safe_bitstream_reader + shared + small + sram + static + swscale_alpha +" + HWACCEL_LIST=" dxva2 vaapi @@ -1354,6 +1424,12 @@ LIBRARY_LIST=" swscale " +LICENSE_LIST=" + gpl + nonfree + version3 +" + PROGRAM_LIST=" ffplay ffprobe @@ -1361,61 +1437,55 @@ PROGRAM_LIST=" ffmpeg " -CONFIG_LIST=" - $COMPONENT_LIST - $DOCUMENT_LIST - $EXAMPLE_LIST - $EXTERNAL_LIBRARY_LIST - $HWACCEL_LIST - $LIBRARY_LIST - $PROGRAM_LIST +SUBSYSTEM_LIST=" dct dwt error_resilience fast_unaligned fft - ftrapv - gpl - gray - hardcoded_tables - incompatible_libav_abi - incompatible_fork_abi lsp lzo mdct + network + rdft +" + +CONFIG_LIST=" + $COMPONENT_LIST + $DOCUMENT_LIST + $EXAMPLE_LIST + $EXTERNAL_LIBRARY_LIST + $FEATURE_LIST + $HWACCEL_LIST + $LICENSE_LIST + $LIBRARY_LIST + $PROGRAM_LIST + $SUBSYSTEM_LIST + fontconfig + incompatible_libav_abi memalign_hack memory_poisoning neon_clobber_test - network - nonfree pic + pod2man raise_major - rdft - runtime_cpudetect - safe_bitstream_reader - shared - small - sram - static - swscale_alpha thumb - version3 xmm_clobber_test " -THREADS_LIST=' +THREADS_LIST=" pthreads - w32threads os2threads -' + w32threads +" -ATOMICS_LIST=' +ATOMICS_LIST=" atomics_gcc atomics_suncc atomics_win32 -' +" -ARCH_LIST=' +ARCH_LIST=" aarch64 alpha arm @@ -1440,26 +1510,32 @@ ARCH_LIST=' x86 x86_32 x86_64 -' +" -ARCH_EXT_LIST_ARM=' +ARCH_EXT_LIST_ARM=" armv5te armv6 armv6t2 + armv8 neon vfp vfpv3 -' +" -ARCH_EXT_LIST_X86=' +ARCH_EXT_LIST_MIPS=" + mipsfpu + mips32r2 + mipsdspr1 + mipsdspr2 +" + +ARCH_EXT_LIST_X86_SIMD=" amd3dnow amd3dnowext avx avx2 - cpunop fma3 fma4 - i686 mmx mmxext sse @@ -1469,32 +1545,102 @@ ARCH_EXT_LIST_X86=' sse42 ssse3 xop -' +" + +ARCH_EXT_LIST_PPC=" + altivec + dcbzl + ldbrx + ppc4xx + vsx +" + +ARCH_EXT_LIST_X86=" + $ARCH_EXT_LIST_X86_SIMD + cpunop + i686 +" ARCH_EXT_LIST=" $ARCH_EXT_LIST_ARM + $ARCH_EXT_LIST_PPC $ARCH_EXT_LIST_X86 - altivec - ppc4xx - vis - mipsfpu - mips32r2 - mipsdspr1 - mipsdspr2 + $ARCH_EXT_LIST_MIPS + loongson " -HAVE_LIST_CMDLINE=' +ARCH_FEATURES=" + aligned_stack + fast_64bit + fast_clz + fast_cmov + local_aligned_8 + local_aligned_16 + local_aligned_32 +" + +BUILTIN_LIST=" + atomic_cas_ptr + machine_rw_barrier + MemoryBarrier + mm_empty + rdtsc + sarestart + sync_val_compare_and_swap +" +HAVE_LIST_CMDLINE=" inline_asm symver yasm -' +" -HAVE_LIST_PUB=' +HAVE_LIST_PUB=" bigendian fast_unaligned incompatible_libav_abi - incompatible_fork_abi -' +" + +HEADERS_LIST=" + alsa_asoundlib_h + altivec_h + arpa_inet_h + asm_types_h + cdio_paranoia_h + cdio_paranoia_paranoia_h + CL_cl_h + dev_bktr_ioctl_bt848_h + dev_bktr_ioctl_meteor_h + dev_ic_bt8xx_h + dev_video_bktr_ioctl_bt848_h + dev_video_meteor_ioctl_meteor_h + direct_h + dlfcn_h + dxva_h + ES2_gl_h + gsm_h + io_h + mach_mach_time_h + machine_ioctl_bt848_h + machine_ioctl_meteor_h + malloc_h + openjpeg_1_5_openjpeg_h + OpenGL_gl3_h + poll_h + sndio_h + soundcard_h + sys_mman_h + sys_param_h + sys_resource_h + sys_select_h + sys_soundcard_h + sys_time_h + sys_un_h + sys_videoio_h + termios_h + unistd_h + windows_h + winsock2_h +" MATH_FUNCS=" atanf @@ -1505,6 +1651,7 @@ MATH_FUNCS=" exp2 exp2f expf + fminf isinf isnan ldexpf @@ -1524,52 +1671,17 @@ MATH_FUNCS=" truncf " -HAVE_LIST=" - $ARCH_EXT_LIST - $(add_suffix _external $ARCH_EXT_LIST) - $(add_suffix _inline $ARCH_EXT_LIST) - $HAVE_LIST_CMDLINE - $HAVE_LIST_PUB - $THREADS_LIST - $ATOMICS_LIST - $MATH_FUNCS +SYSTEM_FUNCS=" access aligned_malloc - aligned_stack - alsa_asoundlib_h - altivec_h - arpa_inet_h - asm_mod_q - asm_types_h - atomic_cas_ptr - atomics_native - attribute_may_alias - attribute_packed - cdio_paranoia_h - cdio_paranoia_paranoia_h - CL_cl_h clock_gettime closesocket CommandLineToArgvW + CoTaskMemFree CryptGenRandom - dcbzl - dev_bktr_ioctl_bt848_h - dev_bktr_ioctl_meteor_h - dev_ic_bt8xx_h - dev_video_bktr_ioctl_bt848_h - dev_video_meteor_ioctl_meteor_h - direct_h - dlfcn_h dlopen - dos_paths - dxva_h - ebp_available - ebx_available - ES2_gl_h - fast_64bit - fast_clz - fast_cmov fcntl + flt_lim fork getaddrinfo gethrtime @@ -1577,66 +1689,66 @@ HAVE_LIST=" GetProcessAffinityMask GetProcessMemoryInfo GetProcessTimes - GetSystemTimeAsFileTime getrusage getservbyport + GetSystemTimeAsFileTime gettimeofday glob glXGetProcAddress - gnu_as - gnu_windres - gsm_h - ibm_asm inet_aton - io_h - inline_asm_labels isatty jack_port_get_latency_range kbhit - ldbrx - libc_msvcrt - libdc1394_1 - libdc1394_2 - local_aligned_16 - local_aligned_8 localtime_r - loongson lzo1x_999_compress - machine_ioctl_bt848_h - machine_ioctl_meteor_h - machine_rw_barrier - makeinfo - malloc_h + mach_absolute_time MapViewOfFile memalign - MemoryBarrier mkstemp - mm_empty mmap mprotect nanosleep - openjpeg_1_5_openjpeg_h - OpenGL_gl3_h PeekNamedPipe - perl - pod2man - poll_h posix_memalign - pragma_deprecated pthread_cancel - rdtsc - rsync_contimeout - sarestart sched_getaffinity - sdl SetConsoleTextAttribute setmode setrlimit Sleep - sndio_h - socklen_t - soundcard_h strerror_r + sysconf + sysctl + usleep + VirtualAlloc + wglGetProcAddress +" + +TOOLCHAIN_FEATURES=" + as_dn_directive + as_func + asm_mod_q + attribute_may_alias + attribute_packed + ebp_available + ebx_available + gnu_as + gnu_windres + ibm_asm + inline_asm_labels + inline_asm_nonlocal_labels + inline_asm_direct_symbol_refs + pragma_deprecated + rsync_contimeout + symver_asm_label + symver_gnu_asm + vfp_args + xform_asm + xmm_clobbers +" + +TYPES_LIST=" + socklen_t struct_addrinfo struct_group_source_req struct_ip_mreq_source @@ -1649,33 +1761,38 @@ HAVE_LIST=" struct_sockaddr_storage struct_stat_st_mtim_tv_nsec struct_v4l2_frmivalenum_discrete - symver_asm_label - symver_gnu_asm - sync_val_compare_and_swap - sysconf - sysctl - sys_mman_h - sys_param_h - sys_resource_h - sys_select_h - sys_soundcard_h - sys_time_h - sys_un_h - sys_videoio_h - termios_h +" + +HAVE_LIST=" + $ARCH_EXT_LIST + $(add_suffix _external $ARCH_EXT_LIST) + $(add_suffix _inline $ARCH_EXT_LIST) + $ARCH_FEATURES + $ATOMICS_LIST + $BUILTIN_LIST + $HAVE_LIST_CMDLINE + $HAVE_LIST_PUB + $HEADERS_LIST + $MATH_FUNCS + $SYSTEM_FUNCS + $THREADS_LIST + $TOOLCHAIN_FEATURES + $TYPES_LIST + atomics_native + dos_paths + dxva2api_cobj + dxva2_lib + libc_msvcrt + libdc1394_1 + libdc1394_2 + makeinfo + perl + pod2man + sdl texi2html threads - unistd_h - usleep vdpau_x11 - vfp_args - VirtualAlloc - wglGetProcAddress - windows_h - winsock2_h - xform_asm xlib - xmm_clobbers " # options emitted with CONFIG_ prefix but not available on the command line @@ -1683,8 +1800,14 @@ CONFIG_EXTRA=" aandcttables ac3dsp audio_frame_queue + audiodsp + blockdsp + bswapdsp + cabac dsputil + dvprofile exif + fdctdsp frame_thread_encoder gcrypt golomb @@ -1696,21 +1819,29 @@ CONFIG_EXTRA=" h264qpel hpeldsp huffman + huffyuvdsp + huffyuvencdsp + idctdsp intrax8 lgplv3 + llauddsp llviddsp lpc + mpeg_er mpegaudio mpegaudiodsp mpegvideo mpegvideoenc nettle + pixblockdsp + qpeldsp rangecoder riffdec riffenc rtpdec rtpenc_chain sinewin + tpeldsp videodsp vp3dsp " @@ -1731,7 +1862,7 @@ CMDLINE_SELECT=" stripping " -PATHS_LIST=' +PATHS_LIST=" bindir datadir docdir @@ -1740,7 +1871,7 @@ PATHS_LIST=' mandir prefix shlibdir -' +" CMDLINE_SET=" $PATHS_LIST @@ -1754,7 +1885,9 @@ CMDLINE_SET=" cross_prefix cxx dep_cc + doxygen extra_version + gas host_cc host_cflags host_ld @@ -1768,10 +1901,13 @@ CMDLINE_SET=" nm optflags pkg_config + pkg_config_flags progs_suffix random_seed + ranlib samples strip + sws_max_filter_size sysinclude sysroot target_exec @@ -1797,6 +1933,7 @@ CMDLINE_APPEND=" armv5te_deps="arm" armv6_deps="arm" armv6t2_deps="arm" +armv8_deps="aarch64" neon_deps_any="aarch64 arm" vfp_deps_any="aarch64 arm" vfpv3_deps="vfp" @@ -1810,8 +1947,7 @@ mipsdspr2_deps="mips" altivec_deps="ppc" ppc4xx_deps="ppc" - -vis_deps="sparc" +vsx_deps="ppc" cpunop_deps="i686" x86_64_select="i686" @@ -1838,7 +1974,7 @@ mmx_external_deps="yasm" mmx_inline_deps="inline_asm" mmx_suggest="mmx_external mmx_inline" -for ext in $(filter_out mmx $ARCH_EXT_LIST_X86); do +for ext in $(filter_out mmx $ARCH_EXT_LIST_X86_SIMD); do eval dep=\$${ext}_deps eval ${ext}_external_deps='"${dep}_external"' eval ${ext}_inline_deps='"${dep}_inline"' @@ -1853,7 +1989,6 @@ fast_unaligned_if_any="aarch64 ppc x86" need_memalign="altivec neon sse" # system capabilities -log2_deps="!libc_msvcrt" symver_if_any="symver_asm_label symver_gnu_asm" @@ -1867,107 +2002,110 @@ threads_if_any="$THREADS_LIST" # subsystems dct_select="rdft" +dsputil_select="fdctdsp idctdsp pixblockdsp" error_resilience_select="dsputil" frame_thread_encoder_deps="encoders threads" -lpc_select="dsputil" +intrax8_select="error_resilience" mdct_select="fft" rdft_select="fft" +mpeg_er_select="error_resilience" mpegaudio_select="mpegaudiodsp" mpegaudiodsp_select="dct" -mpegvideo_select="dsputil h264chroma hpeldsp videodsp" -mpegvideoenc_select="mpegvideo" +mpegvideo_select="blockdsp dsputil h264chroma hpeldsp idctdsp videodsp" +mpegvideoenc_select="dsputil mpegvideo pixblockdsp qpeldsp" # decoders / encoders aac_decoder_select="mdct sinewin" aac_encoder_select="audio_frame_queue mdct sinewin" aac_latm_decoder_select="aac_decoder aac_latm_parser" -ac3_decoder_select="mdct ac3dsp ac3_parser dsputil" -ac3_encoder_select="mdct ac3dsp dsputil" -ac3_fixed_encoder_select="mdct ac3dsp dsputil" -aic_decoder_select="dsputil golomb" +ac3_decoder_select="ac3_parser ac3dsp bswapdsp mdct" +ac3_fixed_decoder_select="ac3_parser ac3dsp bswapdsp mdct" +ac3_encoder_select="ac3dsp audiodsp dsputil mdct" +ac3_fixed_encoder_select="ac3dsp audiodsp dsputil mdct" +aic_decoder_select="golomb idctdsp" alac_encoder_select="lpc" -als_decoder_select="dsputil" +als_decoder_select="bswapdsp" amrnb_decoder_select="lsp" amrwb_decoder_select="lsp" -amv_decoder_select="dsputil hpeldsp exif" -amv_encoder_select="aandcttables" -ape_decoder_select="dsputil" -asv1_decoder_select="dsputil" -asv1_encoder_select="dsputil" -asv2_decoder_select="dsputil" -asv2_encoder_select="dsputil" +amv_decoder_select="sp5x_decoder exif" +amv_encoder_select="aandcttables mpegvideoenc" +ape_decoder_select="bswapdsp llauddsp" +asv1_decoder_select="blockdsp bswapdsp idctdsp" +asv1_encoder_select="bswapdsp fdctdsp pixblockdsp" +asv2_decoder_select="blockdsp bswapdsp idctdsp" +asv2_encoder_select="bswapdsp fdctdsp pixblockdsp" atrac1_decoder_select="mdct sinewin" atrac3_decoder_select="mdct" atrac3p_decoder_select="mdct sinewin" avrn_decoder_select="exif" -bink_decoder_select="dsputil hpeldsp" +bink_decoder_select="blockdsp hpeldsp" binkaudio_dct_decoder_select="mdct rdft dct sinewin" binkaudio_rdft_decoder_select="mdct rdft sinewin" -cavs_decoder_select="dsputil golomb h264chroma videodsp" -cllc_decoder_select="dsputil" +cavs_decoder_select="blockdsp golomb h264chroma idctdsp qpeldsp videodsp" +cllc_decoder_select="bswapdsp" comfortnoise_encoder_select="lpc" -cook_decoder_select="dsputil mdct sinewin" +cook_decoder_select="audiodsp mdct sinewin" cscd_decoder_select="lzo" cscd_decoder_suggest="zlib" dca_decoder_select="mdct" -dirac_decoder_select="dsputil dwt golomb videodsp" -dnxhd_decoder_select="dsputil" -dnxhd_encoder_select="aandcttables dsputil mpegvideoenc" -dvvideo_decoder_select="dsputil" -dvvideo_encoder_select="dsputil" +dirac_decoder_select="dsputil dwt golomb videodsp mpegvideoenc" +dnxhd_decoder_select="blockdsp idctdsp" +dnxhd_encoder_select="aandcttables blockdsp fdctdsp idctdsp mpegvideoenc pixblockdsp" +dvvideo_decoder_select="dvprofile idctdsp" +dvvideo_encoder_select="dsputil dvprofile fdctdsp pixblockdsp" dxa_decoder_select="zlib" eac3_decoder_select="ac3_decoder" eac3_encoder_select="ac3_encoder" -eamad_decoder_select="aandcttables dsputil mpegvideo" +eamad_decoder_select="aandcttables blockdsp bswapdsp idctdsp mpegvideo" eatgq_decoder_select="aandcttables" -eatqi_decoder_select="aandcttables error_resilience mpegvideo" +eatqi_decoder_select="aandcttables blockdsp bswapdsp idctdsp mpeg1video_decoder" exr_decoder_select="zlib" -ffv1_decoder_select="dsputil golomb rangecoder" -ffv1_encoder_select="dsputil rangecoder" -ffvhuff_decoder_select="dsputil llviddsp" -ffvhuff_encoder_select="dsputil huffman llviddsp" -fic_decoder_select="dsputil golomb" +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="dsputil golomb lpc" +flac_encoder_select="bswapdsp golomb lpc" flashsv_decoder_select="zlib" flashsv_encoder_select="zlib" flashsv2_encoder_select="zlib" flashsv2_decoder_select="zlib" flv_decoder_select="h263_decoder" flv_encoder_select="h263_encoder" -fourxm_decoder_select="dsputil" -fraps_decoder_select="dsputil huffman" -g2m_decoder_select="dsputil zlib" -g729_decoder_select="dsputil" -h261_decoder_select="error_resilience mpegvideo" +fourxm_decoder_select="blockdsp bswapdsp" +fraps_decoder_select="bswapdsp huffman" +g2m_decoder_select="blockdsp idctdsp zlib" +g729_decoder_select="audiodsp" +h261_decoder_select="mpeg_er mpegvideo" h261_encoder_select="aandcttables mpegvideoenc" -h263_decoder_select="error_resilience h263_parser h263dsp mpegvideo" +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="golomb h264chroma h264dsp h264pred h264qpel videodsp" +h264_decoder_select="cabac golomb h264chroma h264dsp h264pred h264qpel videodsp" h264_decoder_suggest="error_resilience" -hevc_decoder_select="dsputil golomb videodsp" -huffyuv_decoder_select="dsputil llviddsp" -huffyuv_encoder_select="dsputil huffman llviddsp" -iac_decoder_select="dsputil fft mdct sinewin" -imc_decoder_select="dsputil fft mdct sinewin" +hevc_decoder_select="bswapdsp cabac golomb videodsp" +huffyuv_decoder_select="bswapdsp huffyuvdsp llviddsp" +huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp llviddsp" +iac_decoder_select="imc_decoder" +imc_decoder_select="bswapdsp fft mdct sinewin" indeo3_decoder_select="hpeldsp" interplay_video_decoder_select="hpeldsp" -jpegls_decoder_select="dsputil golomb hpeldsp exif" +jpegls_decoder_select="golomb mjpeg_decoder" jpegls_encoder_select="golomb" -jv_decoder_select="dsputil" -lagarith_decoder_select="dsputil" -ljpeg_encoder_select="aandcttables mpegvideoenc" +jv_decoder_select="blockdsp" +lagarith_decoder_select="huffyuvdsp" +ljpeg_encoder_select="aandcttables idctdsp" loco_decoder_select="golomb" -mdec_decoder_select="dsputil error_resilience mpegvideo" +mdec_decoder_select="blockdsp idctdsp mpegvideo" metasound_decoder_select="lsp mdct sinewin" -mimic_decoder_select="dsputil hpeldsp" -mjpeg_decoder_select="dsputil hpeldsp exif" -mjpegb_decoder_select="dsputil hpeldsp exif" -mjpeg_encoder_select="aandcttables dsputil mpegvideoenc" -mlp_decoder_select="dsputil mlp_parser" -motionpixels_decoder_select="dsputil" +mimic_decoder_select="blockdsp bswapdsp hpeldsp idctdsp" +mjpeg_decoder_select="blockdsp hpeldsp exif idctdsp" +mjpeg_encoder_select="aandcttables mpegvideoenc" +mjpegb_decoder_select="mjpeg_decoder" +mlp_decoder_select="mlp_parser" +motionpixels_decoder_select="bswapdsp" mp1_decoder_select="mpegaudio" mp1float_decoder_select="mpegaudio" mp2_decoder_select="mpegaudio" @@ -1978,13 +2116,13 @@ mp3adufloat_decoder_select="mpegaudio" mp3float_decoder_select="mpegaudio" mp3on4_decoder_select="mpegaudio" mp3on4float_decoder_select="mpegaudio" -mpc7_decoder_select="dsputil mpegaudiodsp" -mpc8_decoder_select="dsputil mpegaudiodsp" +mpc7_decoder_select="bswapdsp mpegaudiodsp" +mpc8_decoder_select="mpegaudiodsp" mpeg_xvmc_decoder_deps="X11_extensions_XvMClib_h" mpeg_xvmc_decoder_select="mpeg2video_decoder" -mpeg1video_decoder_select="error_resilience mpegvideo" +mpeg1video_decoder_select="error_resilience mpeg_er mpegvideo" mpeg1video_encoder_select="aandcttables mpegvideoenc h263dsp" -mpeg2video_decoder_select="error_resilience mpegvideo" +mpeg2video_decoder_select="error_resilience mpeg_er mpegvideo" mpeg2video_encoder_select="aandcttables mpegvideoenc h263dsp" mpeg4_decoder_select="h263_decoder mpeg4video_parser" mpeg4_encoder_select="h263_encoder" @@ -1993,52 +2131,56 @@ 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 vc1_decoder" -mxpeg_decoder_select="dsputil hpeldsp exif" +mss2_decoder_select="error_resilience mpeg_er qpeldsp vc1_decoder" +mxpeg_decoder_select="mjpeg_decoder" nellymoser_decoder_select="mdct sinewin" nellymoser_encoder_select="audio_frame_queue mdct sinewin" -nuv_decoder_select="dsputil lzo" +nuv_decoder_select="idctdsp lzo" +on2avc_decoder_select="mdct" +opus_decoder_deps="swresample" png_decoder_select="zlib" -png_encoder_select="dsputil zlib" -prores_decoder_select="dsputil" -prores_encoder_select="dsputil" +png_encoder_select="huffyuvencdsp zlib" +prores_decoder_select="blockdsp idctdsp" +prores_encoder_select="fdctdsp" qcelp_decoder_select="lsp" qdm2_decoder_select="mdct rdft mpegaudiodsp" -ra_144_encoder_select="audio_frame_queue lpc" +ra_144_encoder_select="audio_frame_queue lpc audiodsp" +ra_144_decoder_select="audiodsp" ralf_decoder_select="golomb" +rawvideo_decoder_select="dsputil bswapdsp" rtjpeg_decoder_select="dsputil" -rv10_decoder_select="error_resilience h263_decoder h263dsp" +rv10_decoder_select="error_resilience h263_decoder h263dsp mpeg_er" rv10_encoder_select="h263_encoder" -rv20_decoder_select="error_resilience h263_decoder h263dsp" +rv20_decoder_select="error_resilience h263_decoder h263dsp mpeg_er" rv20_encoder_select="h263_encoder" -rv30_decoder_select="error_resilience golomb h264chroma h264pred h264qpel mpegvideo videodsp" -rv40_decoder_select="error_resilience golomb h264chroma h264pred h264qpel mpegvideo videodsp" +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" shorten_decoder_select="golomb" sipr_decoder_select="lsp" -snow_decoder_select="dsputil dwt h264qpel hpeldsp rangecoder" +snow_decoder_select="dsputil dwt h264qpel hpeldsp rangecoder mpegvideoenc" snow_encoder_select="aandcttables dsputil dwt h264qpel hpeldsp mpegvideoenc rangecoder" sonic_decoder_select="golomb rangecoder" sonic_encoder_select="golomb rangecoder" -sonic_ls_encoder_select="golomb" -sp5x_decoder_select="dsputil hpeldsp exif" +sonic_ls_encoder_select="golomb rangecoder" +sp5x_decoder_select="mjpeg_decoder" svq1_decoder_select="hpeldsp" svq1_encoder_select="aandcttables dsputil hpeldsp mpegvideoenc" -svq3_decoder_select="golomb h264chroma h264dsp h264pred h264qpel hpeldsp mpegvideo videodsp" -svq3_decoder_suggest="error_resilience zlib" -tak_decoder_select="dsputil" +svq3_decoder_select="h264_decoder hpeldsp tpeldsp" +svq3_decoder_suggest="zlib" +tak_decoder_select="audiodsp" theora_decoder_select="vp3_decoder" +thp_decoder_select="mjpeg_decoder" tiff_decoder_suggest="zlib" tiff_encoder_suggest="zlib" -thp_decoder_select="dsputil hpeldsp exif" truehd_decoder_select="mlp_parser" -truemotion2_decoder_select="dsputil" -truespeech_decoder_select="dsputil" +truemotion2_decoder_select="bswapdsp" +truespeech_decoder_select="bswapdsp" tscc_decoder_select="zlib" twinvq_decoder_select="mdct lsp sinewin" -utvideo_decoder_select="dsputil" -utvideo_encoder_select="dsputil huffman" -vble_decoder_select="dsputil" -vc1_decoder_select="error_resilience h263_decoder h264chroma h264qpel intrax8" +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" vc1image_decoder_select="vc1_decoder" vorbis_decoder_select="mdct" vorbis_encoder_select="mdct" @@ -2047,9 +2189,11 @@ vp5_decoder_select="h264chroma hpeldsp videodsp vp3dsp" vp6_decoder_select="h264chroma hpeldsp huffman videodsp vp3dsp" vp6a_decoder_select="vp6_decoder" vp6f_decoder_select="vp6_decoder" +vp7_decoder_select="h264pred videodsp" vp8_decoder_select="h264pred videodsp" -vp9_decoder_select="videodsp" +vp9_decoder_select="videodsp vp9_parser" webp_decoder_select="vp8_decoder" +wmalossless_decoder_select="llauddsp" wmapro_decoder_select="mdct sinewin" wmav1_decoder_select="mdct sinewin" wmav1_encoder_select="mdct sinewin" @@ -2058,7 +2202,7 @@ wmav2_encoder_select="mdct sinewin" wmavoice_decoder_select="lsp rdft dct mdct sinewin" wmv1_decoder_select="h263_decoder" wmv1_encoder_select="h263_encoder" -wmv2_decoder_select="h263_decoder intrax8 videodsp" +wmv2_decoder_select="blockdsp h263_decoder idctdsp intrax8 videodsp" wmv2_encoder_select="h263_encoder" wmv3_decoder_select="vc1_decoder" wmv3image_decoder_select="wmv3_decoder" @@ -2090,6 +2234,8 @@ h264_vda_decoder_deps="vda" h264_vda_decoder_select="h264_decoder" h264_vda_hwaccel_deps="vda" h264_vda_hwaccel_select="h264_decoder" +h264_vda_old_hwaccel_deps="vda" +h264_vda_old_hwaccel_select="h264_decoder" h264_vdpau_decoder_deps="vdpau" h264_vdpau_decoder_select="h264_decoder" h264_vdpau_hwaccel_deps="vdpau" @@ -2137,11 +2283,11 @@ wmv3_vdpau_decoder_select="vc1_vdpau_decoder" wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" # parsers -h264_parser_select="golomb h264chroma h264dsp h264pred h264qpel videodsp" +h264_parser_select="h264_decoder" hevc_parser_select="hevc_decoder" -mpeg4video_parser_select="error_resilience h263dsp mpegvideo" -mpegvideo_parser_select="error_resilience mpegvideo" -vc1_parser_select="mpegvideo" +mpegvideo_parser_select="mpegvideo" +mpeg4video_parser_select="error_resilience h263dsp mpeg_er mpegvideo qpeldsp" +vc1_parser_select="mpegvideo vc1_decoder" # external libraries libaacplus_encoder_deps="libaacplus" @@ -2207,7 +2353,7 @@ 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="riffdec exif" avi_muxer_select="riffenc" avisynth_demuxer_deps="avisynth" avisynth_demuxer_select="riffdec" @@ -2215,12 +2361,16 @@ caf_demuxer_select="riffdec" dirac_demuxer_select="dirac_parser" dts_demuxer_select="dca_parser" dtshd_demuxer_select="dca_parser" +dv_demuxer_select="dvprofile" +dv_muxer_select="dvprofile" dxa_demuxer_select="riffdec" eac3_demuxer_select="ac3_parser" f4v_muxer_select="mov_muxer" flac_demuxer_select="flac_parser" hds_muxer_select="flv_muxer" hls_muxer_select="mpegts_muxer" +image2_alias_pix_demuxer_select="image2_demuxer" +image2_brender_pix_demuxer_select="image2_demuxer" ipod_muxer_select="mov_muxer" ismv_muxer_select="mov_muxer" libnut_demuxer_deps="libnut" @@ -2268,6 +2418,8 @@ xwma_demuxer_select="riffdec" # indevs / outdevs alsa_indev_deps="alsa_asoundlib_h snd_pcm_htimestamp" alsa_outdev_deps="alsa_asoundlib_h" +avfoundation_indev_extralibs="-framework CoreVideo -framework Foundation -framework AVFoundation -framework CoreMedia" +avfoundation_indev_select="avfoundation" bktr_indev_deps_any="dev_bktr_ioctl_bt848_h machine_ioctl_bt848_h dev_video_bktr_ioctl_bt848_h dev_ic_bt8xx_h" caca_outdev_deps="libcaca" decklink_outdev_deps="decklink pthreads" @@ -2278,6 +2430,9 @@ dv1394_indev_deps="dv1394" dv1394_indev_select="dv_demuxer" fbdev_indev_deps="linux_fb_h" fbdev_outdev_deps="linux_fb_h" +gdigrab_indev_deps="CreateDIBSection" +gdigrab_indev_extralibs="-lgdi32" +gdigrab_indev_select="bmp_decoder" iec61883_indev_deps="libiec61883" jack_indev_deps="jack_jack_h sem_timedwait" lavfi_indev_deps="avfilter" @@ -2290,6 +2445,8 @@ oss_indev_deps_any="soundcard_h sys_soundcard_h" oss_outdev_deps_any="soundcard_h sys_soundcard_h" pulse_indev_deps="libpulse" pulse_outdev_deps="libpulse" +qtkit_indev_extralibs="-framework QTKit -framework Foundation -framework QuartzCore" +qtkit_indev_select="qtkit" sdl_outdev_deps="sdl" sndio_indev_deps="sndio_h" sndio_outdev_deps="sndio_h" @@ -2311,14 +2468,15 @@ ffrtmphttp_protocol_deps="!librtmp_protocol" ffrtmphttp_protocol_select="http_protocol" ftp_protocol_select="tcp_protocol" gopher_protocol_select="network" -httpproxy_protocol_select="tcp_protocol" http_protocol_select="tcp_protocol" +httpproxy_protocol_select="tcp_protocol" https_protocol_select="tls_protocol" librtmp_protocol_deps="librtmp" librtmpe_protocol_deps="librtmp" librtmps_protocol_deps="librtmp" librtmpt_protocol_deps="librtmp" librtmpte_protocol_deps="librtmp" +libsmbclient_protocol_deps="libsmbclient gplv3" libssh_protocol_deps="libssh" mmsh_protocol_select="http_protocol" mmst_protocol_select="network" @@ -2352,6 +2510,7 @@ atempo_filter_select="rdft" azmq_filter_deps="libzmq" blackframe_filter_deps="gpl" boxblur_filter_deps="gpl" +bs2b_filter_deps="libbs2b" colormatrix_filter_deps="gpl" cropdetect_filter_deps="gpl" dctdnoiz_filter_deps="avcodec" @@ -2372,14 +2531,15 @@ hqdn3d_filter_deps="gpl" interlace_filter_deps="gpl" kerndeint_filter_deps="gpl" ladspa_filter_deps="ladspa dlopen" +ladspa_filter_extralibs='$ldl' mcdeint_filter_deps="avcodec gpl" movie_filter_deps="avcodec avformat" mp_filter_deps="gpl avcodec swscale inline_asm" mpdecimate_filter_deps="gpl avcodec" +mpdecimate_filter_select="dsputil pixblockdsp" mptestsrc_filter_deps="gpl" negate_filter_deps="lut_filter" perspective_filter_deps="gpl" -resample_filter_deps="avresample" ocv_filter_deps="libopencv" owdenoise_filter_deps="gpl" pan_filter_deps="swresample" @@ -2387,13 +2547,14 @@ phase_filter_deps="gpl" pp_filter_deps="gpl postproc" pullup_filter_deps="gpl" removelogo_filter_deps="avcodec avformat swscale" +resample_filter_deps="avresample" sab_filter_deps="gpl swscale" scale_filter_deps="swscale" smartblur_filter_deps="gpl swscale" showspectrum_filter_deps="avcodec" showspectrum_filter_select="rdft" spp_filter_deps="gpl avcodec" -spp_filter_select="fft" +spp_filter_select="dsputil fft idctdsp fdctdsp pixblockdsp" stereo3d_filter_deps="gpl" subtitles_filter_deps="avformat avcodec libass" super2xsai_filter_deps="gpl" @@ -2404,6 +2565,7 @@ pixfmts_super2xsai_test_deps="super2xsai_filter" tinterlace_merge_test_deps="tinterlace_filter" tinterlace_pad_test_deps="tinterlace_filter" zmq_filter_deps="libzmq" +zoompan_filter_deps="swscale" # examples avio_reading="avformat avcodec avutil" @@ -2418,14 +2580,16 @@ remuxing_example_deps="avcodec avformat avutil" resampling_audio_example_deps="avutil swresample" scaling_video_example_deps="avutil swscale" transcode_aac_example_deps="avcodec avformat swresample" +transcoding_example_deps="avfilter avcodec avformat avutil" -# libraries +# libraries, in linking order avcodec_deps="avutil" -avdevice_deps="avutil avcodec avformat" +avdevice_deps="avformat avcodec avutil" avfilter_deps="avutil" -avformat_deps="avutil avcodec" +avformat_deps="avcodec avutil" avresample_deps="avutil" postproc_deps="avutil gpl" +swresample_deps="avutil" swscale_deps="avutil" # programs @@ -2435,7 +2599,7 @@ ffmpeg_select="aformat_filter anull_filter atrim_filter format_filter setpts_filter trim_filter" ffplay_deps="avcodec avformat swscale swresample sdl" ffplay_libs='$sdl_libs' -ffplay_select="rdft crop_filter" +ffplay_select="rdft crop_filter transpose_filter hflip_filter vflip_filter rotate_filter" ffprobe_deps="avcodec avformat" ffserver_deps="avformat fork sarestart" ffserver_select="ffm_muxer rtp_protocol rtsp_demuxer" @@ -2467,26 +2631,32 @@ cc_default="gcc" cxx_default="g++" host_cc_default="gcc" cp_f="cp -f" +doxygen_default="doxygen" install="install" ln_s="ln -s -f" nm_default="nm -g" objformat="elf" pkg_config_default=pkg-config -ranlib="ranlib" +ranlib_default="ranlib" strip_default="strip" yasmexe_default="yasm" windres_default="windres" nogas=":" -# machine -arch_default=$(uname -m) -cpu="generic" - # OS target_os_default=$(tolower $(uname -s)) host_os=$target_os_default +# machine +if test "$target_os_default" = aix; then + arch_default=$(uname -p) + strip_default="strip -X32_64" +else + arch_default=$(uname -m) +fi +cpu="generic" + # configurable options enable $PROGRAM_LIST enable $DOCUMENT_LIST @@ -2503,8 +2673,12 @@ enable safe_bitstream_reader enable static enable swscale_alpha +sws_max_filter_size_default=256 +set_default sws_max_filter_size + # Enable hwaccels by default. enable dxva2 vaapi vda vdpau xvmc +enable xlib # build settings SHFLAGS='-shared -Wl,-soname,$$(@F)' @@ -2743,7 +2917,7 @@ cc_default="${cross_prefix}${cc_default}" cxx_default="${cross_prefix}${cxx_default}" nm_default="${cross_prefix}${nm_default}" pkg_config_default="${cross_prefix}${pkg_config_default}" -ranlib="${cross_prefix}${ranlib}" +ranlib_default="${cross_prefix}${ranlib_default}" strip_default="${cross_prefix}${strip_default}" windres_default="${cross_prefix}${windres_default}" @@ -2826,7 +3000,7 @@ case "$toolchain" in add_ldflags -fprofile-arcs -ftest-coverage ;; hardened) - add_cflags -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fstack-protector-all + add_cflags -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fstack-protector-all add_ldflags -Wl,-z,relro -Wl,-z,now ;; ?*) @@ -2834,7 +3008,8 @@ case "$toolchain" in ;; esac -set_default arch cc cxx pkg_config strip sysinclude target_exec target_os yasmexe +set_default arch cc cxx doxygen pkg_config ranlib strip sysinclude \ + target_exec target_os yasmexe enabled cross_compile || host_cc_default=$cc set_default host_cc @@ -2843,6 +3018,11 @@ if ! $pkg_config --version >/dev/null 2>&1; then pkg_config=false fi +if test $doxygen != $doxygen_default && \ + ! $doxygen --version >/dev/null 2>&1; then + warn "Specified doxygen \"$doxygen\" not found, API documentation will fail to build." +fi + exesuf() { case $1 in mingw32*|win32|win64|cygwin*|*-dos|freedos|opendos|os/2*|symbian) echo .exe ;; @@ -2884,6 +3064,7 @@ tmpfile TMPC .c tmpfile TMPCPP .cpp tmpfile TMPE $EXESUF tmpfile TMPH .h +tmpfile TMPM .m tmpfile TMPO .o tmpfile TMPS .S tmpfile TMPSH .sh @@ -2983,6 +3164,16 @@ icl_flags(){ # on Windows, does enable remarks so disable them here. -Wall) echo $flag -Qdiag-disable:remark ;; -std=c99) echo -Qstd=c99 ;; + -flto) echo -ipo ;; + esac + done +} + +icc_flags(){ + for flag; do + case $flag in + -flto) echo -ipo ;; + *) echo $flag ;; esac done } @@ -3015,10 +3206,16 @@ suncc_flags(){ prescott|nocona) echo -xarch=sse3 -xchip=pentium4 ;; *-sse3) echo -xarch=sse3 ;; core2) echo -xarch=ssse3 -xchip=core2 ;; - corei7) echo -xarch=sse4_2 -xchip=nehalem ;; - corei7-avx) echo -xarch=avx -xchip=sandybridge ;; + bonnell) echo -xarch=ssse3 ;; + corei7|nehalem) echo -xtarget=nehalem ;; + westmere) echo -xtarget=westmere ;; + silvermont) echo -xarch=sse4_2 ;; + corei7-avx|sandybridge) echo -xtarget=sandybridge ;; + core-avx*|ivybridge|haswell|broadwell) + echo -xarch=avx ;; amdfam10|barcelona) echo -xtarget=barcelona ;; - bdver*) echo -xarch=avx ;; + btver1) echo -xarch=amdsse4a ;; + btver2|bdver*) echo -xarch=avx ;; athlon-4|athlon-[mx]p) echo -xarch=ssea ;; k8|opteron|athlon64|athlon-fx) echo -xarch=sse2a ;; @@ -3102,6 +3299,7 @@ probe_cc(){ _cflags_speed='-O3' _cflags_size='-Os' _cflags_noopt='-O1' + _flags_filter=icc_flags elif $_cc -v 2>&1 | grep -q xlc; then _type=xlc _ident=$($_cc -qversion 2>/dev/null | head -n1) @@ -3114,10 +3312,10 @@ probe_cc(){ _cflags_speed='-fast' _cflags_size='-O1' _flags_filter=ccc_flags - elif $_cc --vsn 2>/dev/null | grep -q "ARM C/C++ Compiler"; then + elif $_cc --vsn 2>/dev/null | grep -Eq "ARM (C/C\+\+ )?Compiler"; then test -d "$sysroot" || die "No valid sysroot specified." _type=armcc - _ident=$($_cc --vsn | head -n1) + _ident=$($_cc --vsn | head -n1 | sed 's/.*: //') armcc_conf="$PWD/armcc.conf" $_cc --arm_linux_configure \ --arm_linux_config_file="$armcc_conf" \ @@ -3220,9 +3418,9 @@ probe_cc(){ _ld_path='-libpath:' # -Qdiag-error to make icl error when seeing certain unknown arguments _flags='-nologo -Qdiag-error:4044,10157' - # -Qvec- -Qsimd- to prevent miscompilation, -GS for consistency + # -Qvec- -Qsimd- to prevent miscompilation, -GS, fp:precise for consistency # with MSVC which enables it by default. - _cflags='-D_USE_MATH_DEFINES -FIstdlib.h -Dstrtoll=_strtoi64 -Qms0 -Qvec- -Qsimd- -GS' + _cflags='-D_USE_MATH_DEFINES -FIstdlib.h -Dstrtoll=_strtoi64 -Qms0 -Qvec- -Qsimd- -GS -fp:precise' if [ $pfx = hostcc ]; then append _cflags -Dsnprintf=_snprintf fi @@ -3464,7 +3662,10 @@ elif enabled arm; then case "$subarch" in armv5t*) enable fast_clz ;; - armv[6-8]*) enable fast_clz fast_unaligned ;; + armv[6-8]*) + enable fast_clz + disabled fast_unaligned || enable fast_unaligned + ;; esac elif enabled avr32; then @@ -3520,6 +3721,9 @@ elif enabled mips; then elif enabled ppc; then + disable ldbrx + disable vsx + case $(tolower $cpu) in 601|ppc601|powerpc601) cpuflags="-mcpu=601" @@ -3546,7 +3750,7 @@ elif enabled ppc; then g5|970|ppc970|powerpc970) cpuflags="-mcpu=970" ;; - power[3-7]*) + power[3-8]*) cpuflags="-mcpu=$cpu" ;; cell) @@ -3560,10 +3764,12 @@ elif enabled ppc; then e500v2) cpuflags="-mcpu=8548 -mhard-float -mfloat-gprs=double" disable altivec + disable dcbzl ;; e500) cpuflags="-mcpu=8540 -mhard-float" disable altivec + disable dcbzl ;; esac @@ -3572,7 +3778,6 @@ elif enabled sparc; then case $cpu in cypress|f93[04]|tsc701|sparcl*|supersparc|hypersparc|niagara|v[789]) cpuflags="-mcpu=$cpu" - disable vis ;; ultrasparc*|niagara[234]) cpuflags="-mcpu=$cpu" @@ -3592,7 +3797,8 @@ elif enabled x86; then disable i686 ;; # targets that do support nopl and conditional mov (cmov) - i686|pentiumpro|pentium[23]|pentium-m|athlon|athlon-tbird|athlon-4|athlon-[mx]p|athlon64*|k8*|opteron*|athlon-fx|core2|corei7*|amdfam10|barcelona|atom|bdver*) + i686|pentiumpro|pentium[23]|pentium-m|athlon|athlon-tbird|athlon-4|athlon-[mx]p|athlon64*|k8*|opteron*|athlon-fx\ + |core*|atom|bonnell|nehalem|westmere|silvermont|sandybridge|ivybridge|haswell|broadwell|amdfam10|barcelona|b[dt]ver*) cpuflags="-march=$cpu" enable i686 enable fast_cmov @@ -3695,6 +3901,13 @@ case $target_os in add_cppflags '-I\$(SRC_PATH)/compat/aix' enabled shared && add_ldflags -Wl,-brtl ;; + android) + disable symver + SLIB_INSTALL_NAME='$(SLIBNAME)' + SLIB_INSTALL_LINKS= + # soname not set on purpose + SHFLAGS=-shared + ;; haiku) prefix_default="/boot/common" network_extralibs="-lnetwork" @@ -3738,7 +3951,7 @@ case $target_os in strip="strip -d" ;; darwin) - gas="gas-preprocessor.pl $cc" + test "${as#*gas-preprocessor.pl}" != "$as" || gas="${gas:=gas-preprocessor.pl} ${as:=$cc}" enabled ppc && add_asflags -force_cpusubtype_ALL SHFLAGS='-dynamiclib -Wl,-single_module -Wl,-install_name,$(SHLIBDIR)/$(SLIBNAME_WITH_MAJOR),-current_version,$(LIBVERSION),-compatibility_version,$(LIBMAJOR)' enabled x86_32 && append SHFLAGS -Wl,-read_only_relocs,suppress @@ -3997,6 +4210,9 @@ if enabled_all ccc libc_glibc; then add_ldflags -Wl,-z,now # calls to libots crash without this fi +check_compile_assert flt_lim "float.h limits.h" "DBL_MAX == (double)DBL_MAX" || + add_cppflags '-I\$(SRC_PATH)/compat/float' + esc(){ echo "$*" | sed 's/%/%25/g;s/:/%3a/g' } @@ -4019,10 +4235,6 @@ EOF exit 1; fi -# backward compatibility layer for incompatible_libav/fork_abi -enabled incompatible_fork_abi && enable incompatible_libav_abi -enabled incompatible_libav_abi && enable incompatible_fork_abi - die_license_disabled() { enabled $1 || { enabled $2 && die "$2 is $1 and --enable-$1 is not specified."; } } @@ -4033,6 +4245,7 @@ die_license_disabled_gpl() { die_license_disabled gpl frei0r die_license_disabled gpl libcdio +die_license_disabled gpl libsmbclient die_license_disabled gpl libutvideo die_license_disabled gpl libvidstab die_license_disabled gpl libx264 @@ -4049,6 +4262,7 @@ enabled gpl && die_license_disabled_gpl nonfree openssl die_license_disabled version3 libopencore_amrnb die_license_disabled version3 libopencore_amrwb +die_license_disabled version3 libsmbclient die_license_disabled version3 libvo_aacenc die_license_disabled version3 libvo_amrwbenc @@ -4106,9 +4320,41 @@ unsigned int endian = 'B' << 24 | 'I' << 16 | 'G' << 8 | 'E'; EOF od -t x1 $TMPO | grep -q '42 *49 *47 *45' && enable bigendian +if [ "$cpu" = "power7" ] || [ "$cpu" = "power8" ] ;then + if ! enabled bigendian ;then + enable vsx + fi +fi + + +if enabled asm; then + enabled arm && nogas=die + enabled_all ppc altivec && [ $target_os_default != aix ] && nogas=warn + as=${gas:=$as} + check_as <= 2.0.0" aacplus.h aacplusEncOpen -laacplus enabled libass && require_pkg_config libass ass/ass.h ass_library_init enabled libbluray && require_pkg_config libbluray libbluray/bluray.h bd_open +enabled libbs2b && require_pkg_config libbs2b bs2b.h bs2b_open enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && { check_lib celt/celt.h celt_decoder_create_custom -lcelt0 || die "ERROR: libcelt must be installed and version must be >= 0.11.0."; } @@ -4477,7 +4728,10 @@ enabled libfaac && require2 libfaac "stdint.h faac.h" faacEncGetVersio enabled libfdk_aac && require libfdk_aac fdk-aac/aacenc_lib.h aacEncOpen -lfdk-aac flite_libs="-lflite_cmu_time_awb -lflite_cmu_us_awb -lflite_cmu_us_kal -lflite_cmu_us_kal16 -lflite_cmu_us_rms -lflite_cmu_us_slt -lflite_usenglish -lflite_cmulex -lflite" enabled libflite && require2 libflite "flite/flite.h" flite_init $flite_libs +enabled fontconfig && enable libfontconfig +enabled libfontconfig && require_pkg_config fontconfig "fontconfig/fontconfig.h" FcInit enabled libfreetype && require_libfreetype +enabled libfribidi && require_pkg_config fribidi fribidi.h fribidi_version_info enabled libgme && require libgme gme/gme.h gme_new_emu -lgme -lstdc++ enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do check_lib "${gsm_hdr}" gsm_create -lgsm && break; @@ -4489,8 +4743,8 @@ enabled libnut && require libnut libnut.h nut_demuxer_init -lnut 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/cxcore.h cvCreateImageHeader -enabled libopenjpeg && { check_lib openjpeg-1.5/openjpeg.h opj_version -lopenjpeg || - check_lib openjpeg.h opj_version -lopenjpeg || +enabled libopenjpeg && { check_lib openjpeg-1.5/openjpeg.h opj_version -lopenjpeg -DOPJ_STATIC || + check_lib openjpeg.h opj_version -lopenjpeg -DOPJ_STATIC || die "ERROR: libopenjpeg not found"; } 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 @@ -4498,6 +4752,9 @@ enabled libquvi && require_pkg_config libquvi quvi/quvi.h quvi_init 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 libshine && require_pkg_config shine shine/layer3.h shine_encode_buffer +enabled libsmbclient && { { check_pkg_config smbclient libsmbclient.h smbc_init && + require_pkg_config smbclient libsmbclient.h smbc_init; } || + require smbclient libsmbclient.h smbc_init -lsmbclient; } enabled libsoxr && require libsoxr soxr.h soxr_create -lsoxr enabled libssh && require_pkg_config libssh libssh/sftp.h sftp_init enabled libspeex && require libspeex speex/speex.h speex_decoder_init -lspeex @@ -4527,8 +4784,8 @@ enabled libx264 && require libx264 x264.h x264_encoder_encode -lx264 & { check_cpp_condition x264.h "X264_BUILD >= 118" || die "ERROR: libx264 must be installed and version must be >= 0.118."; } enabled libx265 && require_pkg_config x265 x265.h x265_encoder_encode && - { check_cpp_condition x265.h "X265_BUILD >= 7" || - die "ERROR: libx265 version must be >= 7."; } + { check_cpp_condition x265.h "X265_BUILD >= 17" || + die "ERROR: libx265 version must be >= 17."; } enabled libxavs && require libxavs xavs.h xavs_encoder_encode -lxavs enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore enabled libzmq && require_pkg_config libzmq zmq.h zmq_ctx_new @@ -4541,8 +4798,6 @@ enabled openal && { { for al_libs in "${OPENAL_LIBS}" "-lopenal" "-lO enabled opencl && { check_lib2 OpenCL/cl.h clEnqueueNDRangeKernel -Wl,-framework,OpenCL || check_lib2 CL/cl.h clEnqueueNDRangeKernel -lOpenCL || die "ERROR: opencl not found"; } && - { ! enabled_any w32threads os2threads || - die "opencl currently needs --enable-pthreads or --disable-w32threads"; } && { check_cpp_condition "OpenCL/cl.h" "defined(CL_VERSION_1_2)" || check_cpp_condition "CL/cl.h" "defined(CL_VERSION_1_2)" || die "ERROR: opencl must be installed and version must be 1.2 or compatible"; } @@ -4556,6 +4811,7 @@ enabled openssl && { check_lib openssl/ssl.h SSL_library_init -lssl -l 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"; } +enabled qtkit_indev && { check_header_oc QTKit/QTKit.h || disable qtkit_indev; } if enabled gnutls; then { check_lib nettle/bignum.h nettle_mpz_get_str_256 -lnettle -lhogweed -lgmp && enable nettle; } || @@ -4642,13 +4898,26 @@ if enabled libcdio; then die "ERROR: libcdio-paranoia not found" fi -check_lib X11/Xlib.h XOpenDisplay -lX11 && enable xlib +enabled xlib && + check_lib X11/Xlib.h XOpenDisplay -lX11 || disable 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"; } +check_func_headers "windows.h" CreateDIBSection "$gdigrab_indev_extralibs" + +enabled dxva2api_h && + check_cc < +#include +#include +int main(void) { IDirectXVideoDecoder *o = NULL; IDirectXVideoDecoder_Release(o); return 0; } +EOF + enabled vaapi && check_lib va/va.h vaInitialize -lva || disable vaapi @@ -4679,6 +4948,7 @@ check_cflags -Wundef check_cflags -Wmissing-prototypes check_cflags -Wno-pointer-to-int-cast check_cflags -Wstrict-prototypes +check_cflags -Wempty-body enabled extra_warnings && check_cflags -Winline check_disable_warning(){ @@ -4694,7 +4964,7 @@ check_disable_warning -Wno-pointer-sign # add some linker flags check_ldflags -Wl,--warn-common check_ldflags -Wl,-rpath-link=libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample -enabled rpath && add_ldflags -Wl,-rpath=$libdir +enabled rpath && add_ldflags -Wl,-rpath,$libdir test_ldflags -Wl,-Bsymbolic && append SHFLAGS -Wl,-Bsymbolic # add some strip flags @@ -4760,6 +5030,7 @@ if enabled lto; then test "$cc_type" != "$ld_type" && die "LTO requires same compiler and linker" check_cflags -flto check_ldflags -flto $cpuflags + disable inline_asm_direct_symbol_refs fi check_optflags $optflags @@ -4790,6 +5061,8 @@ if enabled icc; then check_ldflags -wd10156,11030 # icc 11.0 and 11.1 work with ebp_available, but don't pass the test enable ebp_available + # The test above does not test linking + enabled lto && disable symver_asm_label if enabled x86_32; then icc_version=$($cc -dumpversion) test ${icc_version%%.*} -ge 11 && @@ -4804,10 +5077,12 @@ elif enabled ccc; then add_cflags -msg_disable unsupieee elif enabled gcc; then check_optflags -fno-tree-vectorize + check_cflags -Werror=format-security check_cflags -Werror=implicit-function-declaration check_cflags -Werror=missing-prototypes check_cflags -Werror=return-type check_cflags -Werror=vla + check_cflags -Wformat enabled extra_warnings || check_disable_warning -Wno-maybe-uninitialized elif enabled llvm_gcc; then check_cflags -mllvm -stack-alignment=16 @@ -4821,7 +5096,9 @@ elif enabled cparser; then add_cflags -Wno-missing-variable-declarations add_cflags -Wno-empty-statement elif enabled armcc; then - # 2523: use of inline assembler is deprecated + add_cflags -W${armcc_opt},--diag_suppress=4343 # hardfp compat + add_cflags -W${armcc_opt},--diag_suppress=3036 # using . as system include dir + # 2523: use of inline assembly is deprecated add_cflags -W${armcc_opt},--diag_suppress=2523 add_cflags -W${armcc_opt},--diag_suppress=1207 add_cflags -W${armcc_opt},--diag_suppress=1293 # assignment in condition @@ -4843,11 +5120,14 @@ elif enabled_any msvc icl; then # (correctly) on icl 13.x. check_cpp_condition "windows.h" "__ICL < 1300 || __ICL >= 1400" && add_cflags -Qansi-alias - # icl will pass the inline asm tests but inline asm is currently - # not supported (build will fail) - disabled inline_asm || warn "inline asm disabled due to issues with it in ICL" - disable inline_asm + # Some inline asm is not compilable in debug + if enabled debug; then + disable ebp_available + disable ebx_available + fi fi + # msvcrt10 x64 incorrectly enables log2, only msvcrt12 onwards actually has log2. + check_cpp_condition crtversion.h "_VC_CRT_MAJOR_VERSION >= 12" || disable log2 fi case $as_type in @@ -4888,6 +5168,10 @@ if test $target_os = "haiku"; then disable posix_memalign fi +enabled_all dxva2 dxva2api_cobj CoTaskMemFree && + prepend ffmpeg_libs $($ldflags_filter "-lole32") && + enable dxva2_lib + ! enabled_any memalign posix_memalign aligned_malloc && enabled_any $need_memalign && enable memalign_hack @@ -4918,6 +5202,53 @@ merge_deps() { merge_deps libavfilter $FILTER_LIST +for thread in $THREADS_LIST; do + if enabled $thread; then + test -n "$thread_type" && + die "ERROR: Only one thread type must be selected." || + thread_type="$thread" + fi +done + +# conditional library dependencies, in linking order +enabled aconvert_filter && prepend avfilter_deps "swresample" +enabled amovie_filter && prepend avfilter_deps "avformat avcodec" +enabled aresample_filter && prepend avfilter_deps "swresample" +enabled asyncts_filter && prepend avfilter_deps "avresample" +enabled atempo_filter && prepend avfilter_deps "avcodec" +enabled decimate_filter && prepend avfilter_deps "avcodec" +enabled deshake_filter && prepend avfilter_deps "avcodec" +enabled ebur128_filter && enabled swresample && prepend avfilter_deps "swresample" +enabled elbg_filter && prepend avfilter_deps "avcodec" +enabled mcdeint_filter && prepend avfilter_deps "avcodec" +enabled movie_filter && prepend avfilter_deps "avformat avcodec" +enabled mp_filter && prepend avfilter_deps "avcodec" +enabled pan_filter && prepend avfilter_deps "swresample" +enabled pp_filter && prepend avfilter_deps "postproc" +enabled removelogo_filter && prepend avfilter_deps "avformat avcodec swscale" +enabled resample_filter && prepend avfilter_deps "avresample" +enabled sab_filter && prepend avfilter_deps "swscale" +enabled scale_filter && prepend avfilter_deps "swscale" +enabled showspectrum_filter && prepend avfilter_deps "avcodec" +enabled smartblur_filter && prepend avfilter_deps "swscale" +enabled subtitles_filter && prepend avfilter_deps "avformat avcodec" + +enabled lavfi_indev && prepend avdevice_deps "avfilter" + +enabled opus_decoder && prepend avcodec_deps "swresample" + +expand_deps(){ + lib_deps=${1}_deps + eval "deps=\$$lib_deps" + append $lib_deps $(map 'eval echo \$${v}_deps' $deps) + unique $lib_deps +} + +#we have to remove gpl from the deps here as some code assumes all lib deps are libs +postproc_deps="$(filter_out 'gpl' $postproc_deps)" + +map 'expand_deps $v' $LIBRARY_LIST + echo "install prefix $prefix" echo "source path $source_path" echo "C compiler $cc" @@ -4976,11 +5307,9 @@ fi if enabled ppc; then echo "AltiVec enabled ${altivec-no}" echo "PPC 4xx optimizations ${ppc4xx-no}" + echo "PPC VSX optimizations ${vsx-no}" echo "dcbzl available ${dcbzl-no}" fi -if enabled sparc; then - echo "VIS enabled ${vis-no}" -fi echo "debug symbols ${debug-no}" echo "strip symbols ${stripping-no}" echo "optimize for size ${small-no}" @@ -4994,7 +5323,6 @@ echo "threading support ${thread_type-no}" echo "safe bitstream reader ${safe_bitstream_reader-no}" echo "SDL support ${sdl-no}" echo "opencl enabled ${opencl-no}" -echo "libzvbi enabled ${libzvbi-no}" echo "texi2html enabled ${texi2html-no}" echo "perl enabled ${perl-no}" echo "pod2man enabled ${pod2man-no}" @@ -5088,6 +5416,7 @@ LD_PATH=$LD_PATH DLLTOOL=$dlltool WINDRES=$windres DEPWINDRES=$dep_cc +DOXYGEN=$doxygen LDFLAGS=$LDFLAGS SHFLAGS=$(echo $($ldflags_filter $SHFLAGS)) ASMSTRIPFLAGS=$ASMSTRIPFLAGS @@ -5162,6 +5491,8 @@ get_version(){ map 'get_version $v' $LIBRARY_LIST +map 'eval echo "${v}_FFLIBS=\$${v}_deps" >> config.mak' $LIBRARY_LIST + print_program_libs(){ eval "program_libs=\$${1}_libs" eval echo "LIBS-${1}=${program_libs}" >> config.mak @@ -5185,6 +5516,7 @@ cat > $TMPH <= \$LIB$(toupper ${1})_VERSION, \"" +} + pkgconfig_generate(){ name=$1 shortname=${name#lib}${build_suffix} comment=$2 version=$3 libs=$4 - requires=$5 + requires=$(map 'lib_version $v' $(eval echo \$${name#lib}_deps)) + requires=${requires%, } enabled ${name#lib} || return 0 mkdir -p $name cat < $name/$name${build_suffix}.pc @@ -5283,24 +5620,12 @@ Cflags: -I\${includedir} EOF } -lavfi_libs="libavutil${build_suffix} = $LIBAVUTIL_VERSION" -enabled libavfilter_deps_avcodec && prepend lavfi_libs "libavcodec${build_suffix} = $LIBAVCODEC_VERSION," -enabled libavfilter_deps_avformat && prepend lavfi_libs "libavformat${build_suffix} = $LIBAVFORMAT_VERSION," -enabled libavfilter_deps_avresample && prepend lavfi_libs "libavresample${build_suffix} = $LIBAVRESAMPLE_VERSION," -enabled libavfilter_deps_swscale && prepend lavfi_libs "libswscale${build_suffix} = $LIBSWSCALE_VERSION," -enabled libavfilter_deps_swresample && prepend lavfi_libs "libswresample${build_suffix} = $LIBSWRESAMPLE_VERSION," -enabled libavfilter_deps_postproc && prepend lavfi_libs "libpostproc${build_suffix} = $LIBPOSTPROC_VERSION," -lavfi_libs=${lavfi_libs%, } - -lavd_libs="libavformat${build_suffix} = $LIBAVFORMAT_VERSION" -enabled lavfi_indev && prepend lavd_libs "libavfilter${build_suffix} = $LIBAVFILTER_VERSION," - pkgconfig_generate libavutil "FFmpeg utility library" "$LIBAVUTIL_VERSION" "$LIBM" -pkgconfig_generate libavcodec "FFmpeg codec library" "$LIBAVCODEC_VERSION" "$extralibs" "libavutil${build_suffix} = $LIBAVUTIL_VERSION" -pkgconfig_generate libavformat "FFmpeg container format library" "$LIBAVFORMAT_VERSION" "$extralibs" "libavcodec${build_suffix} = $LIBAVCODEC_VERSION" -pkgconfig_generate libavdevice "FFmpeg device handling library" "$LIBAVDEVICE_VERSION" "$extralibs" "$lavd_libs" -pkgconfig_generate libavfilter "FFmpeg audio/video filtering library" "$LIBAVFILTER_VERSION" "$extralibs" "$lavfi_libs" -pkgconfig_generate libpostproc "FFmpeg postprocessing library" "$LIBPOSTPROC_VERSION" "" "libavutil${build_suffix} = $LIBAVUTIL_VERSION" -pkgconfig_generate libavresample "Libav audio resampling library" "$LIBAVRESAMPLE_VERSION" "$extralibs" "libavutil${build_suffix} = $LIBAVUTIL_VERSION" -pkgconfig_generate libswscale "FFmpeg image rescaling library" "$LIBSWSCALE_VERSION" "$LIBM" "libavutil${build_suffix} = $LIBAVUTIL_VERSION" -pkgconfig_generate libswresample "FFmpeg audio resampling library" "$LIBSWRESAMPLE_VERSION" "$LIBM" "libavutil${build_suffix} = $LIBAVUTIL_VERSION" +pkgconfig_generate libavcodec "FFmpeg codec library" "$LIBAVCODEC_VERSION" "$extralibs" +pkgconfig_generate libavformat "FFmpeg container format library" "$LIBAVFORMAT_VERSION" "$extralibs" +pkgconfig_generate libavdevice "FFmpeg device handling library" "$LIBAVDEVICE_VERSION" "$extralibs" +pkgconfig_generate libavfilter "FFmpeg audio/video filtering library" "$LIBAVFILTER_VERSION" "$extralibs" +pkgconfig_generate libpostproc "FFmpeg postprocessing library" "$LIBPOSTPROC_VERSION" "" +pkgconfig_generate libavresample "Libav audio resampling library" "$LIBAVRESAMPLE_VERSION" "$extralibs" +pkgconfig_generate libswscale "FFmpeg image rescaling library" "$LIBSWSCALE_VERSION" "$LIBM" +pkgconfig_generate libswresample "FFmpeg audio resampling library" "$LIBSWRESAMPLE_VERSION" "$LIBM" diff --git a/doc/APIchanges b/doc/APIchanges index 8a3778838..c0486f240 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,23 +15,204 @@ libavutil: 2012-10-22 API changes, most recent first: -2014-03-18 - e9c8a9a - lsws 2.5.102 +2014-07-14 - 62227a7 - lavf 55.47.100 - avformat.h + Add av_stream_get_parser() + +2014-07-09 - c67690f / a54f03b - lavu 52.92.100 / 53.18.0 - display.h + Add av_display_matrix_flip() to flip the transformation matrix. + +2014-07-09 - 1b58f13 / f6ee61f - lavc 55.69.100 / 55.56.0 - dv_profile.h + Add a public API for DV profile handling. + +2014-06-20 - 0dceefc / 9e500ef - lavu 52.90.100 / 53.17.0 - imgutils.h + Add av_image_check_sar(). + +2014-06-20 - 4a99333 / 874390e - lavc 55.68.100 / 55.55.0 - avcodec.h + Add av_packet_rescale_ts() to simplify timestamp conversion. + +2014-06-18 - ac293b6 / 194be1f - lavf 55.44.100 / 55.20.0 - avformat.h + The proper way for providing a hint about the desired timebase to the muxers + is now setting AVStream.time_base, instead of AVStream.codec.time_base as was + done previously. The old method is now deprecated. + +2014-06-10 - xxxxxxx - lavf 55.43.100 - avformat.h + New field int64_t max_analyze_duration2 instead of deprecated + int max_analyze_duration. + +2014-05-30 - 00759d7 - lavu 52.89.100 - opt.h + Add av_opt_copy() + +2014-06-01 - 03bb99a / 0957b27 - lavc 55.66.100 / 55.54.0 - avcodec.h + Add AVCodecContext.side_data_only_packets to allow encoders to output packets + with only side data. This option may become mandatory in the future, so all + users are recommended to update their code and enable this option. + +2014-06-01 - 6e8e9f1 / 8c02adc - lavu 52.88.100 / 53.16.0 - frame.h, pixfmt.h + Move all color-related enums (AVColorPrimaries, AVColorSpace, AVColorRange, + AVColorTransferCharacteristic, and AVChromaLocation) inside lavu. + And add AVFrame fields for them. + +2014-05-29 - bdb2e80 / b2d4565 - lavr 1.3.0 - avresample.h + Add avresample_max_output_samples + +2014-05-24 - d858ee7 / 6d21259 - lavf 55.42.100 / 55.19.0 - avformat.h + Add strict_std_compliance and related AVOptions to support experimental + muxing. + +2014-05-26 - xxxxxxx - lavu 52.87.100 - threadmessage.h + Add thread message queue API. + +2014-05-26 - c37d179 - lavf 55.41.100 - avformat.h + Add format_probesize to AVFormatContext. + +2014-05-19 - 7d25af1 / c23c96b - lavf 55.39.100 / 55.18.0 - avformat.h + Add av_stream_get_side_data() to access stream-level side data + in the same way as av_packet_get_side_data(). + +2014-05-xx - xxxxxxx - lavu 52.86.100 - fifo.h + Add av_fifo_alloc_array() function. + +2014-05-19 - ef1d4ee / bddd8cb - lavu 52.85.100 / 53.15.0 - frame.h, display.h + Add AV_FRAME_DATA_DISPLAYMATRIX for exporting frame-level + spatial rendering on video frames for proper display. + +2014-05-xx - xxxxxxx - lavc 55.64.100 / 55.53.0 - avcodec.h + Add AV_PKT_DATA_DISPLAYMATRIX for exporting packet-level + spatial rendering on video frames for proper display. + +2014-05-19 - 999a99c / a312f71 - lavf 55.38.101 / 55.17.1 - avformat.h + Deprecate AVStream.pts and the AVFrac struct, which was its only use case. + See use av_stream_get_end_pts() + +2014-05-18 - 68c0518 / fd05602 - lavc 55.63.100 / 55.52.0 - avcodec.h + Add avcodec_free_context(). From now on it should be used for freeing + AVCodecContext. + +2014-05-17 - 0eec06e - lavu 52.84.100 - time.h + Add av_gettime_relative() av_gettime_relative_is_monotonic() + +2014-05-15 - eacf7d6 / 0c1959b - lavf 55.38.100 / 55.17.0 - avformat.h + Add AVMFT_FLAG_BITEXACT flag. Muxers now use it instead of checking + CODEC_FLAG_BITEXACT on the first stream. + +2014-05-15 - 96cb4c8 - lswr 0.19.100 - swresample.h + Add swr_close() + +2014-05-11 - 14aef38 / 66e6c8a - lavu 52.83.100 / 53.14.0 - pixfmt.h + Add AV_PIX_FMT_VDA for new-style VDA acceleration. + +2014-05-xx - xxxxxxx - lavu 52.82.0 - fifo.h + Add av_fifo_freep() function. + +2014-05-02 - ba52fb11 - lavu 52.81.0 - opt.h + Add av_opt_set_dict2() function. + +2014-05-01 - e77b985 / a2941c8 - lavc 55.60.103 / 55.50.3 - avcodec.h + Deprecate CODEC_FLAG_MV0. It is replaced by the flag "mv0" in the + "mpv_flags" private option of the mpegvideo encoders. + +2014-05-01 - e40ae8c / 6484149 - lavc 55.60.102 / 55.50.2 - avcodec.h + Deprecate CODEC_FLAG_GMC. It is replaced by the "gmc" private option of the + libxvid encoder. + +2014-05-01 - 1851643 / b2c3171 - lavc 55.60.101 / 55.50.1 - avcodec.h + Deprecate CODEC_FLAG_NORMALIZE_AQP. It is replaced by the flag "naq" in the + "mpv_flags" private option of the mpegvideo encoders. + +2014-05-01 - cac07d0 / 5fcceda - avcodec.h + Deprecate CODEC_FLAG_INPUT_PRESERVED. Its functionality is replaced by passing + reference-counted frames to encoders. + +2014-04-29 - 1bf6396 - lavc 55.60.100 - avcodec.h + Add AVCodecDescriptor.mime_types field. + +2014-04-29 - xxxxxxx - lavu 52.80.0 - hash.h + Add av_hash_final_bin(), av_hash_final_hex() and av_hash_final_b64(). + +2014-03-07 - 8b2a130 - lavc 55.50.0 / 55.53.100 - dxva2.h + Add FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO for old Intel GPUs. + +2014-04-22 - 502512e /dac7e8a - lavu 53.13.0 / 52.78.100 - avutil.h + Add av_get_time_base_q(). + +2014-04-17 - a8d01a7 / 0983d48 - lavu 53.12.0 / 52.77.100 - crc.h + Add AV_CRC_16_ANSI_LE crc variant. + +2014-04-XX - xxxxxxx - lavf xx.xx.1xx - avformat.h + Add av_format_inject_global_side_data() + +2014-04-12 - 4f698be - lavu 52.76.100 - log.h + Add av_log_get_flags() + +2014-04-11 - 6db42a2b - lavd 55.12.100 - avdevice.h + Add avdevice_capabilities_create() function. + Add avdevice_capabilities_free() function. + +2014-04-07 - 0a1cc04 / 8b17243 - lavu 52.75.100 / 53.11.0 - pixfmt.h + Add AV_PIX_FMT_YVYU422 pixel format. + +2014-04-04 - c1d0536 / 8542f9c - lavu 52.74.100 / 53.10.0 - replaygain.h + Full scale for peak values is now 100000 (instead of UINT32_MAX) and values + may overflow. + +2014-04-03 - c16e006 / 7763118 - lavu 52.73.100 / 53.9.0 - log.h + Add AV_LOG(c) macro to have 256 color debug messages. + +2014-04-03 - eaed4da9 - lavu 52.72.100 - opt.h + Add AV_OPT_MULTI_COMPONENT_RANGE define to allow return + multi-component option ranges. + +2014-03-29 - cd50a44b - lavu 52.70.100 - mem.h + Add av_dynarray_add_nofree() function. + +2014-02-24 - 3e1f241 / d161ae0 - lavu 52.69.100 / 53.8.0 - frame.h + Add av_frame_remove_side_data() for removing a single side data + instance from a frame. + +2014-03-24 - 83e8978 / 5a7e35d - lavu 52.68.100 / 53.7.0 - frame.h, replaygain.h + Add AV_FRAME_DATA_REPLAYGAIN for exporting replaygain tags. + Add a new header replaygain.h with the AVReplayGain struct. + +2014-03-24 - 83e8978 / 5a7e35d - lavc 55.54.100 / 55.36.0 - avcodec.h + Add AV_PKT_DATA_REPLAYGAIN for exporting replaygain tags. + +2014-03-24 - 595ba3b / 25b3258 - lavf 55.35.100 / 55.13.0 - avformat.h + Add AVStream.side_data and AVStream.nb_side_data for exporting stream-global + side data (e.g. replaygain tags, video rotation) + +2014-03-24 - bd34e26 / 0e2c3ee - lavc 55.53.100 / 55.35.0 - avcodec.h + Give the name AVPacketSideData to the previously anonymous struct used for + AVPacket.side_data. + +2014-03-18 - 37c07d4 - lsws 2.5.102 Make gray16 full-scale. -2014-xx-xx - xxxxxxx - lavu 53.05.0 - frame.h +2014-03-16 - 6b1ca17 / 1481d24 - lavu 52.67.100 / 53.6.0 - pixfmt.h + Add RGBA64_LIBAV pixel format and variants for compatibility + +2014-03-11 - 3f3229c - lavf 55.34.101 - avformat.h + Set AVFormatContext.start_time_realtime when demuxing. + +2014-03-03 - 06fed440 - lavd 55.11.100 - avdevice.h + Add av_input_audio_device_next(). + Add av_input_video_device_next(). + Add av_output_audio_device_next(). + Add av_output_video_device_next(). + +2014-02-24 - fff5262 / 1155fd0 - lavu 52.66.100 / 53.5.0 - frame.h Add av_frame_copy() for copying the frame data. -2014-02-xx - xxxxxxx - lswr 0.18.100 - swresample.h +2014-02-24 - a66be60 - lswr 0.18.100 - swresample.h Add swr_is_initialized() for checking whether a resample context is initialized. -2014-02-xx - xxxxxxx - lavr 1.2.0 - avresample.h +2014-02-22 - 5367c0b / 7e86c27 - lavr 1.2.0 - avresample.h Add avresample_is_open() for checking whether a resample context is open. -2014-xx-xx - xxxxxxx - lavu 53.04.0 - opt.h +2014-02-19 - 6a24d77 / c3ecd96 - lavu 52.65.100 / 53.4.0 - opt.h Add AV_OPT_FLAG_EXPORT and AV_OPT_FLAG_READONLY to mark options meant (only) for reading. -2014-xx-xx - xxxxxxx - lavu 53.03.01 - opt.h +2014-02-19 - f4c8d00 / 6bb8720 - lavu 52.64.101 / 53.3.1 - opt.h Deprecate unused AV_OPT_FLAG_METADATA. 2014-02-xx - xxxxxxx - lavd 55.10.100 - avdevice.h @@ -41,7 +222,7 @@ API changes, most recent first: Add avio_find_protocol_name() to find out the name of the protocol that would be selected for a given URL. -2014-02-xx - xxxxxxx - lavu 53.3.0 - frame.h +2014-02-15 - a2bc6c1 / c98f316 - lavu 52.64.100 / 53.3.0 - frame.h Add AV_FRAME_DATA_DOWNMIX_INFO value to the AVFrameSideDataType enum and downmix_info.h API, which identify downmix-related metadata. @@ -52,7 +233,7 @@ API changes, most recent first: Add AVFormatContext.max_interleave_delta for controlling amount of buffering when interleaving. -2014-02-02 - xxxxxxx - lavf 55.29.100 - avformat.h +2014-02-02 - 5871ee5 - lavf 55.29.100 - avformat.h Add output_ts_offset muxing option to AVFormatContext. 2014-01-27 - 102bd64 - lavd 55.7.100 - avdevice.h @@ -72,7 +253,7 @@ API changes, most recent first: (i.e. as if the CODEC_FLAG_EMU_EDGE flag was always on). Deprecate CODEC_FLAG_EMU_EDGE and avcodec_get_edge_width(). -2014-01-19 - xxxxxxx - lavf 55.25.100 - avformat.h +2014-01-19 - 1a193c4 - lavf 55.25.100 - avformat.h Add avformat_get_mov_video_tags() and avformat_get_mov_audio_tags(). 2014-01-19 - xxxxxxx - lavu 52.63.100 - rational.h @@ -85,16 +266,16 @@ API changes, most recent first: 2014-01-05 - 751385f / 5c437fb - lavu 52.61.100 / 53.1.0 - channel_layout.h Add values for various Dolby flags to the AVMatrixEncoding enum. -2014-01-04 - xxxxxxx - lavu 52.60.100 - mathematics.h +2014-01-04 - b317f94 - lavu 52.60.100 - mathematics.h Add av_add_stable() function. -2013-12-22 - xxxxxxx - lavu 52.59.100 - avstring.h +2013-12-22 - 911676c - lavu 52.59.100 - avstring.h Add av_strnlen() function. -2013-12-xx - xxxxxxx - lavu 52.57.100 - opencl.h +2013-12-09 - 64f73ac - lavu 52.57.100 - opencl.h Add av_opencl_benchmark() function. -2013-11-xx - xxxxxxx - lavu 52.56.100 - ffversion.h +2013-11-30 - 82b2e9c - lavu 52.56.100 - ffversion.h Moves version.h to libavutil/ffversion.h. Install ffversion.h and make it public. @@ -111,13 +292,13 @@ API changes, most recent first: Add AV_FRAME_DATA_A53_CC value to the AVFrameSideDataType enum, which identifies ATSC A53 Part 4 Closed Captions data. -2013-11-XX - xxxxxxx - lavu 52.54.100 - avstring.h +2013-11-22 - 6859065 - lavu 52.54.100 - avstring.h Add av_utf8_decode() function. 2013-11-22 - fb7d70c - lavc 55.44.100 - avcodec.h Add HEVC profiles -2013-11-xx - xxxxxxx - lavc 55.44.100 - avcodec.h +2013-11-20 - c28b61c - lavc 55.44.100 - avcodec.h Add av_packet_{un,}pack_dictionary() Add AV_PKT_METADATA_UPDATE side data type, used to transmit key/value strings between a stream and the application. @@ -129,7 +310,7 @@ API changes, most recent first: Deprecate AVCodecContext.error_rate, it is replaced by the 'error_rate' private option of the mpegvideo encoder family. -2013-11-14 - 31c09b7 / 728c465 - lavc 55.26.0 - vdpau.h +2013-11-14 - 31c09b7 / 728c465 - lavc 55.42.100 / 55.26.0 - vdpau.h Add av_vdpau_get_profile(). Add av_vdpau_alloc_context(). This function must from now on be used for allocating AVVDPAUContext. @@ -139,29 +320,29 @@ API changes, most recent first: Add ITU-R BT.2020 and other not yet included values to color primaries, transfer characteristics and colorspaces. -2013-11-04 - xxxxxxx - lavu 52.50.100 - avutil.h +2013-11-04 - 85cabf1 - lavu 52.50.100 - avutil.h Add av_fopen_utf8() 2013-10-31 - 78265fc / 28096e0 - lavu 52.49.100 / 52.17.0 - frame.h Add AVFrame.flags and AV_FRAME_FLAG_CORRUPT. -2013-10-27 - xxxxxxx - lavc 55.39.100 - avcodec.h +2013-10-27 - dbe6f9f - lavc 55.39.100 - avcodec.h Add CODEC_CAP_DELAY support to avcodec_decode_subtitle2. -2013-10-27 - xxxxxxx - lavu 52.48.100 - parseutils.h +2013-10-27 - d61617a - lavu 52.48.100 - parseutils.h Add av_get_known_color_name(). -2013-10-17 - xxxxxxx - lavu 52.47.100 - opt.h +2013-10-17 - 8696e51 - lavu 52.47.100 - opt.h Add AV_OPT_TYPE_CHANNEL_LAYOUT and channel layout option handlers av_opt_get_channel_layout() and av_opt_set_channel_layout(). -2013-10-xx - xxxxxxx -libswscale 2.5.101 - options.c +2013-10-06 - ccf96f8 -libswscale 2.5.101 - options.c Change default scaler to bicubic -2013-10-03 - xxxxxxx - lavc 55.34.100 - avcodec.h +2013-10-03 - e57dba0 - lavc 55.34.100 - avcodec.h Add av_codec_get_max_lowres() -2013-10-02 - xxxxxxx - lavf 55.19.100 - avformat.h +2013-10-02 - 5082fcc - lavf 55.19.100 - avformat.h Add audio/video/subtitle AVCodec fields to AVFormatContext to force specific decoders @@ -179,7 +360,7 @@ API changes, most recent first: 2013-09-04 - 3e1f507 - lavc 55.31.101 - avcodec.h avcodec_close() argument can be NULL. -2013-09-04 - 36cd017 - lavf 55.16.101 - avformat.h +2013-09-04 - 36cd017a - lavf 55.16.101 - avformat.h avformat_close_input() argument can be NULL and point on NULL. 2013-08-29 - e31db62 - lavf 55.15.100 - avformat.h @@ -188,10 +369,10 @@ API changes, most recent first: 2013-08-15 - 1e0e193 - lsws 2.5.100 - Add a sws_dither AVOption, allowing to set the dither algorithm used -2013-08-xx - xxxxxxx - lavc 55.27.100 - vdpau.h +2013-08-11 - d404fe35 - lavc 55.27.100 - vdpau.h Add a render2 alternative to the render callback function. -2013-08-xx - xxxxxxx - lavc 55.26.100 - vdpau.h +2013-08-11 - af05edc - lavc 55.26.100 - vdpau.h Add allocation function for AVVDPAUContext, allowing to extend it in the future without breaking ABI/API. @@ -201,7 +382,7 @@ API changes, most recent first: 2013-08-05 - 9547e3e / f824535 - lavc 55.22.100 / 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 - 3b805dc / 549294f - lavc 55.21.100 / 55.12.0 - avcodec.h Deprecate the CODEC_CAP_HWACCEL_VDPAU codec capability. Use CODEC_CAP_HWACCEL @@ -792,6 +973,9 @@ lavd 54.4.100 / 54.0.0, lavfi 3.5.0 Add avformat_close_input(). Deprecate av_close_input_file() and av_close_input_stream(). +2011-12-09 - c59b80c / b2890f5 - lavu 51.32.0 / 51.20.0 - audioconvert.h + Expand the channel layout list. + 2011-12-02 - e4de716 / 0eea212 - lavc 53.40.0 / 53.25.0 Add nb_samples and extended_data fields to AVFrame. Deprecate AVCODEC_MAX_AUDIO_FRAME_SIZE. @@ -805,6 +989,10 @@ lavd 54.4.100 / 54.0.0, lavfi 3.5.0 Change AVCodecContext.error[4] to [8] at next major bump. Add AV_NUM_DATA_POINTERS to simplify the bump transition. +2011-11-24 - lavu 51.29.0 / 51.19.0 + 92afb43 / bd97b2e - add planar RGB pixel formats + 92afb43 / 6b0768e - add PIX_FMT_PLANAR and PIX_FMT_RGB pixel descriptions + 2011-11-23 - 8e576d5 / bbb46f3 - lavu 51.27.0 / 51.18.0 Add av_samples_get_buffer_size(), av_samples_fill_arrays(), and av_samples_alloc(), to samplefmt.h. diff --git a/doc/Doxyfile b/doc/Doxyfile index 6f19b103b..7b2a785ae 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = FFmpeg # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 2.2.5 +PROJECT_NUMBER = 2.3 # With the PROJECT_LOGO tag one can specify a logo or icon that is included # in the documentation. The maximum height of the logo should not exceed 55 @@ -759,7 +759,7 @@ ALPHABETICAL_INDEX = YES # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) -COLS_IN_ALPHA_INDEX = 2 +COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. @@ -1056,7 +1056,7 @@ FORMULA_TRANSPARENT = YES # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. -SEARCHENGINE = NO +SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client @@ -1359,6 +1359,8 @@ PREDEFINED = "__attribute__(x)=" \ "DECLARE_ALIGNED(a,t,n)=t n" \ "offsetof(x,y)=0x42" \ av_alloc_size \ + AV_GCC_VERSION_AT_LEAST(x,y)=1 \ + __GNUC__=1 \ # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. diff --git a/doc/Makefile b/doc/Makefile index 44049c4d7..99f588ac0 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -48,6 +48,7 @@ DOC_EXAMPLES-$(CONFIG_REMUXING_EXAMPLE) += remuxing DOC_EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE) += resampling_audio DOC_EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video DOC_EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac +DOC_EXAMPLES-$(CONFIG_TRANSCODING_EXAMPLE) += transcoding ALL_DOC_EXAMPLES_LIST = $(DOC_EXAMPLES-) $(DOC_EXAMPLES-yes) DOC_EXAMPLES := $(DOC_EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)$(EXESUF)) @@ -110,8 +111,9 @@ OBJDIRS += doc/examples DOXY_INPUT = $(addprefix $(SRC_PATH)/, $(INSTHEADERS) $(DOC_EXAMPLES:%$(EXESUF)=%.c) $(LIB_EXAMPLES:%$(EXESUF)=%.c)) -doc/doxy/html: $(SRC_PATH)/doc/Doxyfile $(DOXY_INPUT) - $(M)$(SRC_PATH)/doc/doxy-wrapper.sh $(SRC_PATH) $< $(DOXY_INPUT) +doc/doxy/html: TAG = DOXY +doc/doxy/html: $(SRC_PATH)/doc/Doxyfile $(SRC_PATH)/doc/doxy-wrapper.sh $(DOXY_INPUT) + $(M)$(SRC_PATH)/doc/doxy-wrapper.sh $(SRC_PATH) $< $(DOXYGEN) $(DOXY_INPUT) install-doc: install-html install-man diff --git a/doc/RELEASE_NOTES b/doc/RELEASE_NOTES deleted file mode 100644 index b3338b9fe..000000000 --- a/doc/RELEASE_NOTES +++ /dev/null @@ -1,16 +0,0 @@ -Release Notes -============= - -* 2.2 "Muybridge" March, 2014 - - -General notes -------------- -See the Changelog file for a list of significant changes. Note, there -are many more new features and bugfixes than whats listed there. - -Bugreports against FFmpeg git master or the most recent FFmpeg release are -accepted. If you are experiencing issues with any formally released version of -FFmpeg, please try git master to check if the issue still exists. If it does, -make your report against the development code following the usual bug reporting -guidelines. diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 9bcb12c73..58ebddd42 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -74,7 +74,18 @@ format with @command{ffmpeg}, you can use the command: ffmpeg -i INPUT.mp4 -codec copy -bsf:v h264_mp4toannexb OUTPUT.ts @end example -@section imx_dump_header +@section imxdump + +Modifies the bitstream to fit in MOV and to be usable by the Final Cut +Pro decoder. This filter only applies to the mpeg2video codec, and is +likely not needed for Final Cut Pro 7 and newer with the appropriate +@option{-tag:v}. + +For example, to remux 30 MB/sec NTSC IMX to MOV: + +@example +ffmpeg -i input.mxf -c copy -bsf:v imxdump -tag:v mx3n output.mov +@end example @section mjpeg2jpeg @@ -121,6 +132,13 @@ ffmpeg -i frame_%d.jpg -c:v copy rotated.avi @section noise +Damages the contents of packets without damaging the container. Can be +used for fuzzing or testing error resilience/concealment. + +@example +ffmpeg -i INPUT -c copy -bsf noise output.mkv +@end example + @section remove_extra @c man end BITSTREAM FILTERS diff --git a/doc/build_system.txt b/doc/build_system.txt index 36c141e9e..2efde5ce0 100644 --- a/doc/build_system.txt +++ b/doc/build_system.txt @@ -25,6 +25,9 @@ fate-list install Install headers, libraries and programs. +examples + Build all examples located in doc/examples. + libavformat/output-example Build the libavformat basic example. @@ -34,6 +37,9 @@ libavcodec/api-example libswscale/swscale-test Build the swscale self-test (useful also as example). +config + Reconfigure the project with current configuration. + Useful standard make commands: make -t diff --git a/doc/codecs.texi b/doc/codecs.texi index fadcf249a..1160e5d80 100644 --- a/doc/codecs.texi +++ b/doc/codecs.texi @@ -285,6 +285,11 @@ detect bitstream specification deviations detect improper bitstream length @item explode abort decoding on minor error detection +@item ignore_err +ignore decoding errors, and continue decoding. +This is useful if you want to analyze the content of a video and thus want +everything to be decoded no matter what. This option will not result in a video +that is pleasing to watch in case of errors. @item careful consider things that violate the spec and have not been seen in the wild as errors @item compliant @@ -389,6 +394,9 @@ Possible values: @item simplemmx +@item simpleauto +Automatically pick a IDCT compatible with the simple one + @item arm @item altivec @@ -424,6 +432,8 @@ Possible values: iterative motion vector (MV) search (slow) @item deblock use strong deblock filter for damaged MBs +@item favor_inter +favor predicting from the previous frame instead of the current @end table @item bits_per_coded_sample @var{integer} @@ -879,7 +889,7 @@ Set frame skip factor. Set frame skip exponent. Negative values behave identical to the corresponding positive ones, except that the score is normalized. -Positive values exist primarly for compatibility reasons and are not so useful. +Positive values exist primarily for compatibility reasons and are not so useful. @item skipcmp @var{integer} (@emph{encoding,video}) Set frame skip compare function. @@ -1025,15 +1035,26 @@ Set the log level offset. Number of slices, used in parallelized encoding. @item thread_type @var{flags} (@emph{decoding/encoding,video}) -Select multithreading type. +Select which multithreading methods to use. + +Use of @samp{frame} will increase decoding delay by one frame per +thread, so clients which cannot provide future frames should not use +it. Possible values: @table @samp @item slice +Decode more than one part of a single frame at once. + +Multithreading using slices works only when the video was encoded with +slices. @item frame - +Decode more than one frame at once. @end table + +Default value is @samp{slice+frame}. + @item audio_service_type @var{integer} (@emph{encoding,audio}) Set audio service type. diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 1ea796bfc..d51b9d074 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -74,7 +74,7 @@ following directive is recognized: Path to a file to read; special characters and spaces must be escaped with backslash or single quotes. -All subsequent directives apply to that file. +All subsequent file-related directives apply to that file. @item @code{ffconcat version 1.0} Identify the script type and version. It also sets the @option{safe} option @@ -92,6 +92,22 @@ file is not available or accurate. If the duration is set for all files, then it is possible to seek in the whole concatenated video. +@item @code{stream} +Introduce a stream in the virtual file. +All subsequent stream-related directives apply to the last introduced +stream. +Some streams properties must be set in order to allow identifying the +matching streams in the subfiles. +If no streams are defined in the script, the streams from the first file are +copied. + +@item @code{exact_stream_id @var{id}} +Set the id of the stream. +If this directive is given, the string with the corresponding id in the +subfiles will be used. +This is especially useful for MPEG-PS (VOB) files, where the order of the +streams is not reliable. + @end table @subsection Options @@ -112,6 +128,14 @@ If set to 0, any file name is accepted. The default is -1, it is equivalent to 1 if the format was automatically probed and 0 otherwise. +@item auto_convert +If set to 1, try to perform automatic conversions on packet data to make the +streams concatenable. + +Currently, the only conversion is adding the h264_mp4toannexb bitstream +filter to H.264 streams in MP4 format. This is necessary in particular if +there are resolution changes. + @end table @section flv @@ -249,6 +273,8 @@ is 5. If set to 1, will set frame timestamp to modification time of image file. Note that monotonity of timestamps is not provided: images go in the same order as without this option. Default value is 0. +If set to 2, will set frame timestamp to the modification time of the image file in +nanosecond precision. @item video_size Set the video size of the images to read. If not specified the video size is guessed from the first image file in the sequence. diff --git a/doc/doxy-wrapper.sh b/doc/doxy-wrapper.sh index 13be8cb95..d88f60e55 100755 --- a/doc/doxy-wrapper.sh +++ b/doc/doxy-wrapper.sh @@ -2,10 +2,11 @@ SRC_PATH="${1}" DOXYFILE="${2}" +DOXYGEN="${3}" -shift 2 +shift 3 -doxygen - <height = 288; /* frames per second */ c->time_base = (AVRational){1,25}; - c->gop_size = 10; /* emit one intra frame every ten frames */ + /* emit one intra frame every ten frames + * check frame pict_type before passing frame + * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I + * then gop_size is ignored and the output of encoder + * will always be I frame irrespective to gop_size + */ + c->gop_size = 10; c->max_b_frames = 1; c->pix_fmt = AV_PIX_FMT_YUV420P; @@ -634,7 +640,7 @@ int main(int argc, char **argv) "This program generates a synthetic stream and encodes it to a file\n" "named test.h264, test.mp2 or test.mpg depending on output_type.\n" "The encoded stream is then decoded and written to a raw data output.\n" - "output_type must be choosen between 'h264', 'mp2', 'mpg'.\n", + "output_type must be chosen between 'h264', 'mp2', 'mpg'.\n", argv[0]); return 1; } diff --git a/doc/examples/demuxing_decoding.c b/doc/examples/demuxing_decoding.c index 077fc87b5..2ce4018c7 100644 --- a/doc/examples/demuxing_decoding.c +++ b/doc/examples/demuxing_decoding.c @@ -279,7 +279,7 @@ int main (int argc, char **argv) audio_dec_ctx = audio_stream->codec; audio_dst_file = fopen(audio_dst_filename, "wb"); if (!audio_dst_file) { - fprintf(stderr, "Could not open destination file %s\n", video_dst_filename); + fprintf(stderr, "Could not open destination file %s\n", audio_dst_filename); ret = 1; goto end; } diff --git a/doc/examples/muxing.c b/doc/examples/muxing.c index ad8e02714..ea5c78e28 100644 --- a/doc/examples/muxing.c +++ b/doc/examples/muxing.c @@ -34,6 +34,8 @@ #include #include +#include +#include #include #include #include @@ -41,13 +43,26 @@ #include #include -static int audio_is_eof, video_is_eof; - #define STREAM_DURATION 10.0 #define STREAM_FRAME_RATE 25 /* 25 images/s */ #define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */ -static int sws_flags = SWS_BICUBIC; +#define SCALE_FLAGS SWS_BICUBIC + +// a wrapper around a single output AVStream +typedef struct OutputStream { + AVStream *st; + + /* pts of the next frame that will be generated */ + int64_t next_pts; + + AVFrame *frame; + AVFrame *tmp_frame; + + float t, tincr, tincr2; + + struct SwsContext *sws_ctx; +} OutputStream; static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt) { @@ -63,9 +78,7 @@ static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt) static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt) { /* rescale output packet timestamp values from codec to stream timebase */ - pkt->pts = av_rescale_q_rnd(pkt->pts, *time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); - pkt->dts = av_rescale_q_rnd(pkt->dts, *time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); - pkt->duration = av_rescale_q(pkt->duration, *time_base, st->time_base); + av_packet_rescale_ts(pkt, *time_base, st->time_base); pkt->stream_index = st->index; /* Write the compressed frame to the media file. */ @@ -74,11 +87,11 @@ static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AV } /* Add an output stream. */ -static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec, - enum AVCodecID codec_id) +static void add_stream(OutputStream *ost, AVFormatContext *oc, + AVCodec **codec, + enum AVCodecID codec_id) { AVCodecContext *c; - AVStream *st; /* find the encoder */ *codec = avcodec_find_encoder(codec_id); @@ -88,13 +101,13 @@ static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec, exit(1); } - st = avformat_new_stream(oc, *codec); - if (!st) { + ost->st = avformat_new_stream(oc, *codec); + if (!ost->st) { fprintf(stderr, "Could not allocate stream\n"); exit(1); } - st->id = oc->nb_streams-1; - c = st->codec; + ost->st->id = oc->nb_streams-1; + c = ost->st->codec; switch ((*codec)->type) { case AVMEDIA_TYPE_AUDIO: @@ -103,6 +116,7 @@ static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec, c->bit_rate = 64000; c->sample_rate = 44100; c->channels = 2; + c->channel_layout = AV_CH_LAYOUT_STEREO; break; case AVMEDIA_TYPE_VIDEO: @@ -139,41 +153,21 @@ static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec, /* Some formats want stream headers to be separate. */ if (oc->oformat->flags & AVFMT_GLOBALHEADER) c->flags |= CODEC_FLAG_GLOBAL_HEADER; - - return st; } /**************************************************************/ /* audio output */ -static float t, tincr, tincr2; - -AVFrame *audio_frame; -static uint8_t **src_samples_data; -static int src_samples_linesize; -static int src_nb_samples; - -static int max_dst_nb_samples; -uint8_t **dst_samples_data; -int dst_samples_linesize; -int dst_samples_size; int samples_count; struct SwrContext *swr_ctx = NULL; -static void open_audio(AVFormatContext *oc, AVCodec *codec, AVStream *st) +static void open_audio(AVFormatContext *oc, AVCodec *codec, OutputStream *ost) { AVCodecContext *c; int ret; - c = st->codec; - - /* allocate and init a re-usable frame */ - audio_frame = av_frame_alloc(); - if (!audio_frame) { - fprintf(stderr, "Could not allocate audio frame\n"); - exit(1); - } + c = ost->st->codec; /* open it */ ret = avcodec_open2(c, codec, NULL); @@ -183,25 +177,32 @@ static void open_audio(AVFormatContext *oc, AVCodec *codec, AVStream *st) } /* init signal generator */ - t = 0; - tincr = 2 * M_PI * 110.0 / c->sample_rate; + ost->t = 0; + ost->tincr = 2 * M_PI * 110.0 / c->sample_rate; /* increment frequency by 110 Hz per second */ - tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate; + ost->tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate; - src_nb_samples = c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE ? - 10000 : c->frame_size; - - ret = av_samples_alloc_array_and_samples(&src_samples_data, &src_samples_linesize, c->channels, - src_nb_samples, AV_SAMPLE_FMT_S16, 0); - if (ret < 0) { - fprintf(stderr, "Could not allocate source samples\n"); + ost->frame = av_frame_alloc(); + if (!ost->frame) exit(1); - } - /* compute the number of converted samples: buffering is avoided - * ensuring that the output buffer will contain at least all the - * converted input samples */ - max_dst_nb_samples = src_nb_samples; + ost->frame->sample_rate = c->sample_rate; + ost->frame->format = AV_SAMPLE_FMT_S16; + ost->frame->channel_layout = c->channel_layout; + + if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) + ost->frame->nb_samples = 10000; + else + ost->frame->nb_samples = c->frame_size; + + ost->tmp_frame = av_frame_alloc(); + if (!ost->frame) + exit(1); + + ost->tmp_frame->sample_rate = c->sample_rate; + ost->tmp_frame->format = c->sample_fmt; + ost->tmp_frame->channel_layout = c->channel_layout; + ost->tmp_frame->nb_samples = ost->frame->nb_samples; /* create resampler context */ if (c->sample_fmt != AV_SAMPLE_FMT_S16) { @@ -224,127 +225,145 @@ static void open_audio(AVFormatContext *oc, AVCodec *codec, AVStream *st) fprintf(stderr, "Failed to initialize the resampling context\n"); exit(1); } - - ret = av_samples_alloc_array_and_samples(&dst_samples_data, &dst_samples_linesize, c->channels, - max_dst_nb_samples, c->sample_fmt, 0); - if (ret < 0) { - fprintf(stderr, "Could not allocate destination samples\n"); - exit(1); - } - } else { - dst_samples_data = src_samples_data; } - dst_samples_size = av_samples_get_buffer_size(NULL, c->channels, max_dst_nb_samples, - c->sample_fmt, 0); + + ret = av_frame_get_buffer(ost->frame, 0); + if (ret < 0) { + fprintf(stderr, "Could not allocate an audio frame.\n"); + exit(1); + } + ret = av_frame_get_buffer(ost->tmp_frame, 0); + if (ret < 0) { + fprintf(stderr, "Could not allocate an audio frame.\n"); + exit(1); + } } /* Prepare a 16 bit dummy audio frame of 'frame_size' samples and * 'nb_channels' channels. */ -static void get_audio_frame(int16_t *samples, int frame_size, int nb_channels) +static AVFrame *get_audio_frame(OutputStream *ost) { - int j, i, v; - int16_t *q; + int j, i, v, ret; + int16_t *q = (int16_t*)ost->frame->data[0]; - q = samples; - for (j = 0; j < frame_size; j++) { - v = (int)(sin(t) * 10000); - for (i = 0; i < nb_channels; i++) + /* check if we want to generate more frames */ + if (av_compare_ts(ost->next_pts, ost->st->codec->time_base, + STREAM_DURATION, (AVRational){ 1, 1 }) >= 0) + return NULL; + + /* when we pass a frame to the encoder, it may keep a reference to it + * internally; + * make sure we do not overwrite it here + */ + ret = av_frame_make_writable(ost->frame); + if (ret < 0) + exit(1); + + for (j = 0; j < ost->frame->nb_samples; j++) { + v = (int)(sin(ost->t) * 10000); + for (i = 0; i < ost->st->codec->channels; i++) *q++ = v; - t += tincr; - tincr += tincr2; + ost->t += ost->tincr; + ost->tincr += ost->tincr2; } + + ost->frame->pts = ost->next_pts; + ost->next_pts += ost->frame->nb_samples; + + return ost->frame; } -static void write_audio_frame(AVFormatContext *oc, AVStream *st, int flush) +/* + * encode one audio frame and send it to the muxer + * return 1 when encoding is finished, 0 otherwise + */ +static int write_audio_frame(AVFormatContext *oc, OutputStream *ost) { AVCodecContext *c; AVPacket pkt = { 0 }; // data and size must be 0; - int got_packet, ret, dst_nb_samples; + AVFrame *frame; + int ret; + int got_packet; + int dst_nb_samples; av_init_packet(&pkt); - c = st->codec; + c = ost->st->codec; - if (!flush) { - get_audio_frame((int16_t *)src_samples_data[0], src_nb_samples, c->channels); + frame = get_audio_frame(ost); + if (frame) { /* convert samples from native format to destination codec format, using the resampler */ if (swr_ctx) { /* compute destination number of samples */ - dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, c->sample_rate) + src_nb_samples, + dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, c->sample_rate) + frame->nb_samples, c->sample_rate, c->sample_rate, AV_ROUND_UP); - if (dst_nb_samples > max_dst_nb_samples) { - av_free(dst_samples_data[0]); - ret = av_samples_alloc(dst_samples_data, &dst_samples_linesize, c->channels, - dst_nb_samples, c->sample_fmt, 0); - if (ret < 0) - exit(1); - max_dst_nb_samples = dst_nb_samples; - dst_samples_size = av_samples_get_buffer_size(NULL, c->channels, dst_nb_samples, - c->sample_fmt, 0); - } + av_assert0(dst_nb_samples == frame->nb_samples); /* convert to destination format */ ret = swr_convert(swr_ctx, - dst_samples_data, dst_nb_samples, - (const uint8_t **)src_samples_data, src_nb_samples); + ost->tmp_frame->data, dst_nb_samples, + (const uint8_t **)frame->data, frame->nb_samples); if (ret < 0) { fprintf(stderr, "Error while converting\n"); exit(1); } + frame = ost->tmp_frame; } else { - dst_nb_samples = src_nb_samples; + dst_nb_samples = frame->nb_samples; } - audio_frame->nb_samples = dst_nb_samples; - audio_frame->pts = av_rescale_q(samples_count, (AVRational){1, c->sample_rate}, c->time_base); - avcodec_fill_audio_frame(audio_frame, c->channels, c->sample_fmt, - dst_samples_data[0], dst_samples_size, 0); + frame->pts = av_rescale_q(samples_count, (AVRational){1, c->sample_rate}, c->time_base); samples_count += dst_nb_samples; } - ret = avcodec_encode_audio2(c, &pkt, flush ? NULL : audio_frame, &got_packet); + ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet); if (ret < 0) { fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret)); exit(1); } - if (!got_packet) { - if (flush) - audio_is_eof = 1; - return; + if (got_packet) { + ret = write_frame(oc, &c->time_base, ost->st, &pkt); + if (ret < 0) { + fprintf(stderr, "Error while writing audio frame: %s\n", + av_err2str(ret)); + exit(1); + } } - ret = write_frame(oc, &c->time_base, st, &pkt); - if (ret < 0) { - fprintf(stderr, "Error while writing audio frame: %s\n", - av_err2str(ret)); - exit(1); - } -} - -static void close_audio(AVFormatContext *oc, AVStream *st) -{ - avcodec_close(st->codec); - if (dst_samples_data != src_samples_data) { - av_free(dst_samples_data[0]); - av_free(dst_samples_data); - } - av_free(src_samples_data[0]); - av_free(src_samples_data); - av_frame_free(&audio_frame); + return (frame || got_packet) ? 0 : 1; } /**************************************************************/ /* video output */ -static AVFrame *frame; -static AVPicture src_picture, dst_picture; -static int frame_count; +static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height) +{ + AVFrame *picture; + int ret; -static void open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st) + picture = av_frame_alloc(); + if (!picture) + return NULL; + + picture->format = pix_fmt; + picture->width = width; + picture->height = height; + + /* allocate the buffers for the frame data */ + ret = av_frame_get_buffer(picture, 32); + if (ret < 0) { + fprintf(stderr, "Could not allocate frame data.\n"); + exit(1); + } + + return picture; +} + +static void open_video(AVFormatContext *oc, AVCodec *codec, OutputStream *ost) { int ret; - AVCodecContext *c = st->codec; + AVCodecContext *c = ost->st->codec; /* open the codec */ ret = avcodec_open2(c, codec, NULL); @@ -354,43 +373,38 @@ static void open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st) } /* allocate and init a re-usable frame */ - frame = av_frame_alloc(); - if (!frame) { + ost->frame = alloc_picture(c->pix_fmt, c->width, c->height); + if (!ost->frame) { fprintf(stderr, "Could not allocate video frame\n"); exit(1); } - frame->format = c->pix_fmt; - frame->width = c->width; - frame->height = c->height; - - /* Allocate the encoded raw picture. */ - ret = avpicture_alloc(&dst_picture, c->pix_fmt, c->width, c->height); - if (ret < 0) { - fprintf(stderr, "Could not allocate picture: %s\n", av_err2str(ret)); - exit(1); - } /* If the output format is not YUV420P, then a temporary YUV420P * picture is needed too. It is then converted to the required * output format. */ + ost->tmp_frame = NULL; if (c->pix_fmt != AV_PIX_FMT_YUV420P) { - ret = avpicture_alloc(&src_picture, AV_PIX_FMT_YUV420P, c->width, c->height); - if (ret < 0) { - fprintf(stderr, "Could not allocate temporary picture: %s\n", - av_err2str(ret)); + ost->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, c->width, c->height); + if (!ost->tmp_frame) { + fprintf(stderr, "Could not allocate temporary picture\n"); exit(1); } } - - /* copy data and linesize picture pointers to frame */ - *((AVPicture *)frame) = dst_picture; } /* Prepare a dummy image. */ -static void fill_yuv_image(AVPicture *pict, int frame_index, +static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height) { - int x, y, i; + int x, y, i, ret; + + /* when we pass a frame to the encoder, it may keep a reference to it + * internally; + * make sure we do not overwrite it here + */ + ret = av_frame_make_writable(pict); + if (ret < 0) + exit(1); i = frame_index; @@ -408,65 +422,89 @@ static void fill_yuv_image(AVPicture *pict, int frame_index, } } -static void write_video_frame(AVFormatContext *oc, AVStream *st, int flush) +static AVFrame *get_video_frame(OutputStream *ost) { - int ret; - static struct SwsContext *sws_ctx; - AVCodecContext *c = st->codec; + AVCodecContext *c = ost->st->codec; - if (!flush) { - if (c->pix_fmt != AV_PIX_FMT_YUV420P) { - /* as we only generate a YUV420P picture, we must convert it - * to the codec pixel format if needed */ - if (!sws_ctx) { - sws_ctx = sws_getContext(c->width, c->height, AV_PIX_FMT_YUV420P, - c->width, c->height, c->pix_fmt, - sws_flags, NULL, NULL, NULL); - if (!sws_ctx) { - fprintf(stderr, - "Could not initialize the conversion context\n"); - exit(1); - } + /* check if we want to generate more frames */ + if (av_compare_ts(ost->next_pts, ost->st->codec->time_base, + STREAM_DURATION, (AVRational){ 1, 1 }) >= 0) + return NULL; + + if (c->pix_fmt != AV_PIX_FMT_YUV420P) { + /* as we only generate a YUV420P picture, we must convert it + * to the codec pixel format if needed */ + if (!ost->sws_ctx) { + ost->sws_ctx = sws_getContext(c->width, c->height, + AV_PIX_FMT_YUV420P, + c->width, c->height, + c->pix_fmt, + SCALE_FLAGS, NULL, NULL, NULL); + if (!ost->sws_ctx) { + fprintf(stderr, + "Could not initialize the conversion context\n"); + exit(1); } - fill_yuv_image(&src_picture, frame_count, c->width, c->height); - sws_scale(sws_ctx, - (const uint8_t * const *)src_picture.data, src_picture.linesize, - 0, c->height, dst_picture.data, dst_picture.linesize); - } else { - fill_yuv_image(&dst_picture, frame_count, c->width, c->height); } + fill_yuv_image(ost->tmp_frame, ost->next_pts, c->width, c->height); + sws_scale(ost->sws_ctx, + (const uint8_t * const *)ost->tmp_frame->data, ost->tmp_frame->linesize, + 0, c->height, ost->frame->data, ost->frame->linesize); + } else { + fill_yuv_image(ost->frame, ost->next_pts, c->width, c->height); } - if (oc->oformat->flags & AVFMT_RAWPICTURE && !flush) { - /* Raw video case - directly store the picture in the packet */ + ost->frame->pts = ost->next_pts++; + + return ost->frame; +} + +/* + * encode one video frame and send it to the muxer + * return 1 when encoding is finished, 0 otherwise + */ +static int write_video_frame(AVFormatContext *oc, OutputStream *ost) +{ + int ret; + AVCodecContext *c; + AVFrame *frame; + int got_packet = 0; + + c = ost->st->codec; + + 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; + pkt.flags |= AV_PKT_FLAG_KEY; - pkt.stream_index = st->index; - pkt.data = dst_picture.data[0]; + pkt.stream_index = ost->st->index; + pkt.data = (uint8_t *)frame; pkt.size = sizeof(AVPicture); + pkt.pts = pkt.dts = frame->pts; + av_packet_rescale_ts(&pkt, c->time_base, ost->st->time_base); + ret = av_interleaved_write_frame(oc, &pkt); } else { AVPacket pkt = { 0 }; - int got_packet; av_init_packet(&pkt); /* encode the image */ - frame->pts = frame_count; - ret = avcodec_encode_video2(c, &pkt, flush ? NULL : frame, &got_packet); + ret = avcodec_encode_video2(c, &pkt, frame, &got_packet); if (ret < 0) { fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret)); exit(1); } - /* If size is zero, it means the image was buffered. */ if (got_packet) { - ret = write_frame(oc, &c->time_base, st, &pkt); + ret = write_frame(oc, &c->time_base, ost->st, &pkt); } else { - if (flush) - video_is_eof = 1; ret = 0; } } @@ -475,15 +513,16 @@ static void write_video_frame(AVFormatContext *oc, AVStream *st, int flush) fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret)); exit(1); } - frame_count++; + + return (frame || got_packet) ? 0 : 1; } -static void close_video(AVFormatContext *oc, AVStream *st) +static void close_stream(AVFormatContext *oc, OutputStream *ost) { - avcodec_close(st->codec); - av_free(src_picture.data[0]); - av_free(dst_picture.data[0]); - av_frame_free(&frame); + avcodec_close(ost->st->codec); + av_frame_free(&ost->frame); + av_frame_free(&ost->tmp_frame); + sws_freeContext(ost->sws_ctx); } /**************************************************************/ @@ -491,13 +530,14 @@ static void close_video(AVFormatContext *oc, AVStream *st) int main(int argc, char **argv) { + OutputStream video_st = { 0 }, audio_st = { 0 }; const char *filename; AVOutputFormat *fmt; AVFormatContext *oc; - AVStream *audio_st, *video_st; AVCodec *audio_codec, *video_codec; - double audio_time, video_time; - int flush, ret; + int ret; + int have_video = 0, have_audio = 0; + int encode_video = 0, encode_audio = 0; /* Initialize libavcodec, and register all codecs and formats. */ av_register_all(); @@ -528,20 +568,24 @@ int main(int argc, char **argv) /* Add the audio and video streams using the default format codecs * and initialize the codecs. */ - video_st = NULL; - audio_st = NULL; - - if (fmt->video_codec != AV_CODEC_ID_NONE) - video_st = add_stream(oc, &video_codec, fmt->video_codec); - if (fmt->audio_codec != AV_CODEC_ID_NONE) - audio_st = add_stream(oc, &audio_codec, fmt->audio_codec); + if (fmt->video_codec != AV_CODEC_ID_NONE) { + add_stream(&video_st, oc, &video_codec, fmt->video_codec); + have_video = 1; + encode_video = 1; + } + if (fmt->audio_codec != AV_CODEC_ID_NONE) { + add_stream(&audio_st, oc, &audio_codec, fmt->audio_codec); + have_audio = 1; + encode_audio = 1; + } /* Now that all the parameters are set, we can open the audio and * video codecs and allocate the necessary encode buffers. */ - if (video_st) - open_video(oc, video_codec, video_st); - if (audio_st) - open_audio(oc, audio_codec, audio_st); + if (have_video) + open_video(oc, video_codec, &video_st); + + if (have_audio) + open_audio(oc, audio_codec, &audio_st); av_dump_format(oc, 0, filename, 1); @@ -563,23 +607,14 @@ int main(int argc, char **argv) return 1; } - flush = 0; - while ((video_st && !video_is_eof) || (audio_st && !audio_is_eof)) { - /* Compute current audio and video time. */ - audio_time = (audio_st && !audio_is_eof) ? audio_st->pts.val * av_q2d(audio_st->time_base) : INFINITY; - video_time = (video_st && !video_is_eof) ? video_st->pts.val * av_q2d(video_st->time_base) : INFINITY; - - if (!flush && - (!audio_st || audio_time >= STREAM_DURATION) && - (!video_st || video_time >= STREAM_DURATION)) { - flush = 1; - } - - /* write interleaved audio and video frames */ - if (audio_st && !audio_is_eof && audio_time <= video_time) { - write_audio_frame(oc, audio_st, flush); - } else if (video_st && !video_is_eof && video_time < audio_time) { - write_video_frame(oc, video_st, flush); + 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_video = !write_video_frame(oc, &video_st); + } else { + encode_audio = !write_audio_frame(oc, &audio_st); } } @@ -590,10 +625,10 @@ int main(int argc, char **argv) av_write_trailer(oc); /* Close each codec. */ - if (video_st) - close_video(oc, video_st); - if (audio_st) - close_audio(oc, audio_st); + if (have_video) + close_stream(oc, &video_st); + if (have_audio) + close_stream(oc, &audio_st); if (!(fmt->flags & AVFMT_NOFILE)) /* Close the output file. */ diff --git a/doc/examples/remuxing.c b/doc/examples/remuxing.c index cdb2f6b32..39d9dee86 100644 --- a/doc/examples/remuxing.c +++ b/doc/examples/remuxing.c @@ -99,6 +99,7 @@ int main(int argc, char **argv) fprintf(stderr, "Failed to copy context from input to output stream codec context\n"); goto end; } + out_stream->codec->codec_tag = 0; if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; } diff --git a/doc/examples/resampling_audio.c b/doc/examples/resampling_audio.c index f743cbe55..8a43b0903 100644 --- a/doc/examples/resampling_audio.c +++ b/doc/examples/resampling_audio.c @@ -168,7 +168,7 @@ int main(int argc, char **argv) dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) + src_nb_samples, dst_rate, src_rate, AV_ROUND_UP); if (dst_nb_samples > max_dst_nb_samples) { - av_free(dst_data[0]); + av_freep(&dst_data[0]); ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_sample_fmt, 1); if (ret < 0) diff --git a/doc/examples/transcoding.c b/doc/examples/transcoding.c new file mode 100644 index 000000000..a8f4210e6 --- /dev/null +++ b/doc/examples/transcoding.c @@ -0,0 +1,597 @@ +/* + * Copyright (c) 2010 Nicolas George + * Copyright (c) 2011 Stefano Sabatini + * Copyright (c) 2014 Andrey Utkin + * + * 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 + * API example for demuxing, decoding, filtering, encoding and muxing + * @example transcoding.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static AVFormatContext *ifmt_ctx; +static AVFormatContext *ofmt_ctx; +typedef struct FilteringContext { + AVFilterContext *buffersink_ctx; + AVFilterContext *buffersrc_ctx; + AVFilterGraph *filter_graph; +} FilteringContext; +static FilteringContext *filter_ctx; + +static int open_input_file(const char *filename) +{ + int ret; + unsigned int i; + + ifmt_ctx = NULL; + if ((ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL)) < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n"); + return ret; + } + + if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n"); + return ret; + } + + for (i = 0; i < ifmt_ctx->nb_streams; i++) { + AVStream *stream; + AVCodecContext *codec_ctx; + stream = ifmt_ctx->streams[i]; + codec_ctx = stream->codec; + /* Reencode video & audio and remux subtitles etc. */ + if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO + || codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { + /* Open decoder */ + ret = avcodec_open2(codec_ctx, + avcodec_find_decoder(codec_ctx->codec_id), NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i); + return ret; + } + } + } + + av_dump_format(ifmt_ctx, 0, filename, 0); + return 0; +} + +static int open_output_file(const char *filename) +{ + AVStream *out_stream; + AVStream *in_stream; + AVCodecContext *dec_ctx, *enc_ctx; + AVCodec *encoder; + int ret; + unsigned int i; + + ofmt_ctx = NULL; + avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename); + if (!ofmt_ctx) { + av_log(NULL, AV_LOG_ERROR, "Could not create output context\n"); + return AVERROR_UNKNOWN; + } + + + for (i = 0; i < ifmt_ctx->nb_streams; i++) { + out_stream = avformat_new_stream(ofmt_ctx, NULL); + if (!out_stream) { + av_log(NULL, AV_LOG_ERROR, "Failed allocating output stream\n"); + return AVERROR_UNKNOWN; + } + + in_stream = ifmt_ctx->streams[i]; + dec_ctx = in_stream->codec; + enc_ctx = out_stream->codec; + + if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO + || dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { + /* in this example, we choose transcoding to same codec */ + encoder = avcodec_find_encoder(dec_ctx->codec_id); + + /* In this example, we transcode to same properties (picture size, + * sample rate etc.). These properties can be changed for output + * streams easily using filters */ + if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { + enc_ctx->height = dec_ctx->height; + enc_ctx->width = dec_ctx->width; + enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio; + /* take first format from list of supported formats */ + enc_ctx->pix_fmt = encoder->pix_fmts[0]; + /* video time_base can be set to whatever is handy and supported by encoder */ + enc_ctx->time_base = dec_ctx->time_base; + } else { + enc_ctx->sample_rate = dec_ctx->sample_rate; + enc_ctx->channel_layout = dec_ctx->channel_layout; + enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout); + /* take first format from list of supported formats */ + enc_ctx->sample_fmt = encoder->sample_fmts[0]; + enc_ctx->time_base = (AVRational){1, enc_ctx->sample_rate}; + } + + /* Third parameter can be used to pass settings to encoder */ + ret = avcodec_open2(enc_ctx, encoder, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i); + return ret; + } + } else if (dec_ctx->codec_type == AVMEDIA_TYPE_UNKNOWN) { + av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n", i); + return AVERROR_INVALIDDATA; + } else { + /* if this stream must be remuxed */ + ret = avcodec_copy_context(ofmt_ctx->streams[i]->codec, + ifmt_ctx->streams[i]->codec); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Copying stream context failed\n"); + return ret; + } + } + + if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) + enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; + + } + av_dump_format(ofmt_ctx, 0, filename, 1); + + if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) { + ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Could not open output file '%s'", filename); + return ret; + } + } + + /* init muxer, write output file header */ + ret = avformat_write_header(ofmt_ctx, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error occurred when opening output file\n"); + return ret; + } + + return 0; +} + +static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, + AVCodecContext *enc_ctx, const char *filter_spec) +{ + char args[512]; + int ret = 0; + AVFilter *buffersrc = NULL; + AVFilter *buffersink = NULL; + AVFilterContext *buffersrc_ctx = NULL; + AVFilterContext *buffersink_ctx = NULL; + AVFilterInOut *outputs = avfilter_inout_alloc(); + AVFilterInOut *inputs = avfilter_inout_alloc(); + AVFilterGraph *filter_graph = avfilter_graph_alloc(); + + if (!outputs || !inputs || !filter_graph) { + ret = AVERROR(ENOMEM); + goto end; + } + + if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { + buffersrc = avfilter_get_by_name("buffer"); + buffersink = avfilter_get_by_name("buffersink"); + if (!buffersrc || !buffersink) { + av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n"); + ret = AVERROR_UNKNOWN; + goto end; + } + + snprintf(args, sizeof(args), + "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", + dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt, + dec_ctx->time_base.num, dec_ctx->time_base.den, + dec_ctx->sample_aspect_ratio.num, + dec_ctx->sample_aspect_ratio.den); + + ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", + args, NULL, filter_graph); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n"); + goto end; + } + + ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", + NULL, NULL, filter_graph); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n"); + goto end; + } + + ret = av_opt_set_bin(buffersink_ctx, "pix_fmts", + (uint8_t*)&enc_ctx->pix_fmt, sizeof(enc_ctx->pix_fmt), + AV_OPT_SEARCH_CHILDREN); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n"); + goto end; + } + } else if (dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { + buffersrc = avfilter_get_by_name("abuffer"); + buffersink = avfilter_get_by_name("abuffersink"); + if (!buffersrc || !buffersink) { + av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n"); + ret = AVERROR_UNKNOWN; + goto end; + } + + if (!dec_ctx->channel_layout) + dec_ctx->channel_layout = + av_get_default_channel_layout(dec_ctx->channels); + snprintf(args, sizeof(args), + "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64, + dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate, + av_get_sample_fmt_name(dec_ctx->sample_fmt), + dec_ctx->channel_layout); + ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", + args, NULL, filter_graph); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n"); + goto end; + } + + ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", + NULL, NULL, filter_graph); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n"); + goto end; + } + + ret = av_opt_set_bin(buffersink_ctx, "sample_fmts", + (uint8_t*)&enc_ctx->sample_fmt, sizeof(enc_ctx->sample_fmt), + AV_OPT_SEARCH_CHILDREN); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n"); + goto end; + } + + ret = av_opt_set_bin(buffersink_ctx, "channel_layouts", + (uint8_t*)&enc_ctx->channel_layout, + sizeof(enc_ctx->channel_layout), AV_OPT_SEARCH_CHILDREN); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n"); + goto end; + } + + ret = av_opt_set_bin(buffersink_ctx, "sample_rates", + (uint8_t*)&enc_ctx->sample_rate, sizeof(enc_ctx->sample_rate), + AV_OPT_SEARCH_CHILDREN); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n"); + goto end; + } + } else { + ret = AVERROR_UNKNOWN; + goto end; + } + + /* Endpoints for the filter graph. */ + outputs->name = av_strdup("in"); + outputs->filter_ctx = buffersrc_ctx; + outputs->pad_idx = 0; + outputs->next = NULL; + + inputs->name = av_strdup("out"); + inputs->filter_ctx = buffersink_ctx; + inputs->pad_idx = 0; + inputs->next = NULL; + + if (!outputs->name || !inputs->name) { + ret = AVERROR(ENOMEM); + goto end; + } + + if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_spec, + &inputs, &outputs, NULL)) < 0) + goto end; + + if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) + goto end; + + /* Fill FilteringContext */ + fctx->buffersrc_ctx = buffersrc_ctx; + fctx->buffersink_ctx = buffersink_ctx; + fctx->filter_graph = filter_graph; + +end: + avfilter_inout_free(&inputs); + avfilter_inout_free(&outputs); + + return ret; +} + +static int init_filters(void) +{ + const char *filter_spec; + unsigned int i; + int ret; + filter_ctx = av_malloc_array(ifmt_ctx->nb_streams, sizeof(*filter_ctx)); + if (!filter_ctx) + return AVERROR(ENOMEM); + + for (i = 0; i < ifmt_ctx->nb_streams; i++) { + filter_ctx[i].buffersrc_ctx = NULL; + filter_ctx[i].buffersink_ctx = NULL; + filter_ctx[i].filter_graph = NULL; + if (!(ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO + || ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)) + continue; + + + if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) + filter_spec = "null"; /* passthrough (dummy) filter for video */ + else + filter_spec = "anull"; /* passthrough (dummy) filter for audio */ + ret = init_filter(&filter_ctx[i], ifmt_ctx->streams[i]->codec, + ofmt_ctx->streams[i]->codec, filter_spec); + if (ret) + return ret; + } + return 0; +} + +static int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame) { + int ret; + int got_frame_local; + AVPacket enc_pkt; + int (*enc_func)(AVCodecContext *, AVPacket *, const AVFrame *, int *) = + (ifmt_ctx->streams[stream_index]->codec->codec_type == + AVMEDIA_TYPE_VIDEO) ? avcodec_encode_video2 : avcodec_encode_audio2; + + if (!got_frame) + got_frame = &got_frame_local; + + av_log(NULL, AV_LOG_INFO, "Encoding frame\n"); + /* encode filtered frame */ + enc_pkt.data = NULL; + enc_pkt.size = 0; + av_init_packet(&enc_pkt); + ret = enc_func(ofmt_ctx->streams[stream_index]->codec, &enc_pkt, + filt_frame, got_frame); + av_frame_free(&filt_frame); + if (ret < 0) + return ret; + if (!(*got_frame)) + return 0; + + /* prepare packet for muxing */ + enc_pkt.stream_index = stream_index; + enc_pkt.dts = av_rescale_q_rnd(enc_pkt.dts, + ofmt_ctx->streams[stream_index]->codec->time_base, + ofmt_ctx->streams[stream_index]->time_base, + AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + enc_pkt.pts = av_rescale_q_rnd(enc_pkt.pts, + ofmt_ctx->streams[stream_index]->codec->time_base, + ofmt_ctx->streams[stream_index]->time_base, + AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + enc_pkt.duration = av_rescale_q(enc_pkt.duration, + ofmt_ctx->streams[stream_index]->codec->time_base, + ofmt_ctx->streams[stream_index]->time_base); + + av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n"); + /* mux encoded frame */ + ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt); + return ret; +} + +static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index) +{ + int ret; + AVFrame *filt_frame; + + av_log(NULL, AV_LOG_INFO, "Pushing decoded frame to filters\n"); + /* push the decoded frame into the filtergraph */ + ret = av_buffersrc_add_frame_flags(filter_ctx[stream_index].buffersrc_ctx, + frame, 0); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n"); + return ret; + } + + /* pull filtered frames from the filtergraph */ + while (1) { + filt_frame = av_frame_alloc(); + if (!filt_frame) { + ret = AVERROR(ENOMEM); + break; + } + av_log(NULL, AV_LOG_INFO, "Pulling filtered frame from filters\n"); + ret = av_buffersink_get_frame(filter_ctx[stream_index].buffersink_ctx, + filt_frame); + if (ret < 0) { + /* if no more frames for output - returns AVERROR(EAGAIN) + * if flushed and no more frames for output - returns AVERROR_EOF + * rewrite retcode to 0 to show it as normal procedure completion + */ + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + ret = 0; + av_frame_free(&filt_frame); + break; + } + + filt_frame->pict_type = AV_PICTURE_TYPE_NONE; + ret = encode_write_frame(filt_frame, stream_index, NULL); + if (ret < 0) + break; + } + + return ret; +} + +static int flush_encoder(unsigned int stream_index) +{ + int ret; + int got_frame; + + if (!(ofmt_ctx->streams[stream_index]->codec->codec->capabilities & + CODEC_CAP_DELAY)) + return 0; + + while (1) { + av_log(NULL, AV_LOG_INFO, "Flushing stream #%u encoder\n", stream_index); + ret = encode_write_frame(NULL, stream_index, &got_frame); + if (ret < 0) + break; + if (!got_frame) + return 0; + } + return ret; +} + +int main(int argc, char **argv) +{ + int ret; + AVPacket packet = { .data = NULL, .size = 0 }; + AVFrame *frame = NULL; + enum AVMediaType type; + unsigned int stream_index; + unsigned int i; + int got_frame; + int (*dec_func)(AVCodecContext *, AVFrame *, int *, const AVPacket *); + + if (argc != 3) { + av_log(NULL, AV_LOG_ERROR, "Usage: %s \n", argv[0]); + return 1; + } + + av_register_all(); + avfilter_register_all(); + + if ((ret = open_input_file(argv[1])) < 0) + goto end; + if ((ret = open_output_file(argv[2])) < 0) + goto end; + if ((ret = init_filters()) < 0) + goto end; + + /* read all packets */ + while (1) { + if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0) + break; + stream_index = packet.stream_index; + type = ifmt_ctx->streams[packet.stream_index]->codec->codec_type; + av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n", + stream_index); + + if (filter_ctx[stream_index].filter_graph) { + av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n"); + frame = av_frame_alloc(); + if (!frame) { + ret = AVERROR(ENOMEM); + break; + } + packet.dts = av_rescale_q_rnd(packet.dts, + ifmt_ctx->streams[stream_index]->time_base, + ifmt_ctx->streams[stream_index]->codec->time_base, + AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + packet.pts = av_rescale_q_rnd(packet.pts, + ifmt_ctx->streams[stream_index]->time_base, + ifmt_ctx->streams[stream_index]->codec->time_base, + AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + dec_func = (type == AVMEDIA_TYPE_VIDEO) ? avcodec_decode_video2 : + avcodec_decode_audio4; + ret = dec_func(ifmt_ctx->streams[stream_index]->codec, frame, + &got_frame, &packet); + if (ret < 0) { + av_frame_free(&frame); + av_log(NULL, AV_LOG_ERROR, "Decoding failed\n"); + break; + } + + if (got_frame) { + frame->pts = av_frame_get_best_effort_timestamp(frame); + ret = filter_encode_write_frame(frame, stream_index); + av_frame_free(&frame); + if (ret < 0) + goto end; + } else { + av_frame_free(&frame); + } + } else { + /* remux this frame without reencoding */ + packet.dts = av_rescale_q_rnd(packet.dts, + ifmt_ctx->streams[stream_index]->time_base, + ofmt_ctx->streams[stream_index]->time_base, + AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + packet.pts = av_rescale_q_rnd(packet.pts, + ifmt_ctx->streams[stream_index]->time_base, + ofmt_ctx->streams[stream_index]->time_base, + AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + + ret = av_interleaved_write_frame(ofmt_ctx, &packet); + if (ret < 0) + goto end; + } + av_free_packet(&packet); + } + + /* flush filters and encoders */ + for (i = 0; i < ifmt_ctx->nb_streams; i++) { + /* flush filter */ + if (!filter_ctx[i].filter_graph) + continue; + ret = filter_encode_write_frame(NULL, i); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Flushing filter failed\n"); + goto end; + } + + /* flush encoder */ + ret = flush_encoder(i); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Flushing encoder failed\n"); + goto end; + } + } + + av_write_trailer(ofmt_ctx); +end: + av_free_packet(&packet); + av_frame_free(&frame); + for (i = 0; i < ifmt_ctx->nb_streams; i++) { + avcodec_close(ifmt_ctx->streams[i]->codec); + if (ofmt_ctx && ofmt_ctx->nb_streams > i && ofmt_ctx->streams[i] && ofmt_ctx->streams[i]->codec) + avcodec_close(ofmt_ctx->streams[i]->codec); + if (filter_ctx && filter_ctx[i].filter_graph) + avfilter_graph_free(&filter_ctx[i].filter_graph); + } + av_free(filter_ctx); + avformat_close_input(&ifmt_ctx); + if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) + avio_close(ofmt_ctx->pb); + avformat_free_context(ofmt_ctx); + + if (ret < 0) + av_log(NULL, AV_LOG_ERROR, "Error occurred: %s\n", av_err2str(ret)); + + return ret ? 1 : 0; +} diff --git a/doc/faq.texi b/doc/faq.texi index 74c259f2b..fdcb46d33 100644 --- a/doc/faq.texi +++ b/doc/faq.texi @@ -392,7 +392,7 @@ VOB and a few other formats do not have a global header that describes everything present in the file. Instead, applications are supposed to scan the file to see what it contains. Since VOB files are frequently large, only the beginning is scanned. If the subtitles happen only later in the file, -they will not be initally detected. +they will not be initially detected. Some applications, including the @code{ffmpeg} command-line tool, can only work with streams that were detected during the initial scan; streams that diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index c0a81c811..f741a053f 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -90,7 +90,8 @@ the following diagram: | | | decoded | | frames | - ________ ______________ |_________| + |_________| + ________ ______________ | | | | | | | output | <-------- | encoded data | <----+ | file | muxer | packets | encoder @@ -123,11 +124,16 @@ the same type. In the above diagram they can be represented by simply inserting an additional step between decoding and encoding: @example - _________ __________ ______________ -| | simple | | | | -| decoded | fltrgrph | filtered | encoder | encoded data | -| frames | ----------> | frames | ---------> | packets | -|_________| |__________| |______________| + _________ ______________ +| | | | +| decoded | | encoded data | +| frames |\ _ | packets | +|_________| \ /||______________| + \ __________ / + simple _\|| | / encoder + filtergraph | filtered |/ + | frames | + |__________| @end example @@ -266,8 +272,13 @@ ffmpeg -i INPUT -map 0 -c copy -c:v:1 libx264 -c:a:137 libvorbis OUTPUT will copy all the streams except the second video, which will be encoded with libx264, and the 138th audio, which will be encoded with libvorbis. -@item -t @var{duration} (@emph{output}) -Stop writing the output after its duration reaches @var{duration}. +@item -t @var{duration} (@emph{input/output}) +When used as an input option (before @code{-i}), limit the @var{duration} of +data read from the input file. + +When used as an output option (before an output filename), stop writing the +output after its duration reaches @var{duration}. + @var{duration} may be a number in seconds, or in @code{hh:mm:ss[.xxx]} form. -to and -t are mutually exclusive and -t has priority. @@ -523,7 +534,7 @@ filter the stream. This is an alias for @code{-filter:v}, see the @ref{filter_option,,-filter option}. @end table -@section Advanced Video Options +@section Advanced Video options @table @option @item -pix_fmt[:@var{stream_specifier}] @var{format} (@emph{input/output,per-stream}) @@ -637,8 +648,14 @@ Do not use any hardware acceleration (the default). @item auto Automatically select the hardware acceleration method. +@item vda +Use Apple VDA hardware acceleration. + @item vdpau Use VDPAU (Video Decode and Presentation API for Unix) hardware acceleration. + +@item dxva2 +Use DXVA2 (DirectX Video Acceleration) hardware acceleration. @end table This option has no effect if the selected hwaccel is not available or not @@ -661,6 +678,10 @@ method chosen. @item vdpau For VDPAU, this option specifies the X11 display/screen to use. If this option 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. @end table @end table @@ -696,7 +717,7 @@ filter the stream. This is an alias for @code{-filter:a}, see the @ref{filter_option,,-filter option}. @end table -@section Advanced Audio options: +@section Advanced Audio options @table @option @item -atag @var{fourcc/tag} (@emph{output}) @@ -711,7 +732,7 @@ stereo but not 6 channels as 5.1. The default is to always try to guess. Use 0 to disable all guessing. @end table -@section Subtitle options: +@section Subtitle options @table @option @item -scodec @var{codec} (@emph{input/output}) @@ -722,7 +743,7 @@ Disable subtitle recording. Deprecated, see -bsf @end table -@section Advanced Subtitle options: +@section Advanced Subtitle options @table @option @@ -1125,6 +1146,30 @@ requested by @command{ffserver}. The option is intended for cases where features are needed that cannot be specified to @command{ffserver} but can be to @command{ffmpeg}. +@item -discard (@emph{input}) +Allows discarding specific streams or frames of streams at the demuxer. +Not all demuxers support this. + +@table @option +@item none +Discard no frame. + +@item default +Default, which discards no frames. + +@item noref +Discard all non-reference frames. + +@item bidir +Discard all bidirectional frames. + +@item nokey +Discard all frames excepts keyframes. + +@item all +Discard all frames. +@end table + @end table As a special exception, you can use a bitmap subtitle stream as input: it diff --git a/doc/ffplay.texi b/doc/ffplay.texi index c26c68da5..203085c16 100644 --- a/doc/ffplay.texi +++ b/doc/ffplay.texi @@ -84,6 +84,9 @@ output. In the filtergraph, the input is associated to the label ffmpeg-filters manual for more information about the filtergraph syntax. +You can specify this parameter multiple times and cycle through the specified +filtergraphs along with the show modes by pressing the key @key{w}. + @item -af @var{filtergraph} @var{filtergraph} is a description of the filtergraph to apply to the input audio. @@ -159,6 +162,10 @@ Force a specific video decoder. @item -scodec @var{codec_name} Force a specific subtitle decoder. + +@item -autorotate +Automatically rotate the video according to presentation metadata. Set by +default, use -noautorotate to disable. @end table @section While playing @@ -174,7 +181,7 @@ Toggle full screen. Pause. @item a -Cycle audio channel in the curret program. +Cycle audio channel in the current program. @item v Cycle video channel. @@ -186,7 +193,7 @@ Cycle subtitle channel in the current program. Cycle program. @item w -Show audio waves. +Cycle video filters or show modes. @item s Step to the next frame. diff --git a/doc/ffprobe.xsd b/doc/ffprobe.xsd index 1bc1fb5bb..9ef9ecbdc 100644 --- a/doc/ffprobe.xsd +++ b/doc/ffprobe.xsd @@ -8,15 +8,15 @@ + + - + - - @@ -53,6 +53,10 @@ + + + + @@ -147,6 +151,8 @@ + + @@ -165,6 +171,7 @@ + @@ -219,8 +226,7 @@ - - + diff --git a/doc/fftools-common-opts.texi b/doc/fftools-common-opts.texi index dcfe9b5a3..ab627ca4a 100644 --- a/doc/fftools-common-opts.texi +++ b/doc/fftools-common-opts.texi @@ -44,8 +44,8 @@ streams of this type. If @var{stream_index} is given, then it matches the stream with number @var{stream_index} in the program with the id @var{program_id}. Otherwise, it matches all streams in the program. -@item #@var{stream_id} -Matches the stream by a format-specific ID. +@item #@var{stream_id} or i:@var{stream_id} +Match the stream by stream id (e.g. PID in MPEG-TS container). @end table @section Generic options @@ -189,6 +189,8 @@ following option is recognized: set the file name to use for the report; @code{%p} is expanded to the name of the program, @code{%t} is expanded to a timestamp, @code{%%} is expanded to a plain @code{%} +@item level +set the log level @end table Errors in parsing the environment variable are not fatal, and will not diff --git a/doc/filters.texi b/doc/filters.texi index 8bf29ec04..0f73314a1 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16,8 +16,8 @@ input --> split ---------------------> overlay --> output +-----> crop --> vflip -------+ @end example -This filtergraph splits the input stream in two streams, sends one -stream through the crop filter and the vflip filter before merging it +This filtergraph splits the input stream in two streams, then sends one +stream through the crop filter and the vflip filter, before merging it back with the other stream by overlaying it on top. You can use the following command to achieve this: @@ -25,8 +25,8 @@ following command to achieve this: ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT @end example -The result will be that in output the top half of the video is mirrored -onto the bottom half. +The result will be that the top half of the video is mirrored +onto the bottom half of the output video. Filters in the same linear chain are separated by commas, and distinct linear chains of filters are separated by semicolons. In our example, @@ -102,22 +102,22 @@ A filtergraph is a directed graph of connected filters. It can contain cycles, and there can be multiple links between a pair of filters. Each link has one input pad on one side connecting it to one filter from which it takes its input, and one output pad on the other -side connecting it to the one filter accepting its output. +side connecting it to one filter accepting its output. Each filter in a filtergraph is an instance of a filter class registered in the application, which defines the features and the number of input and output pads of the filter. -A filter with no input pads is called a "source", a filter with no +A filter with no input pads is called a "source", and a filter with no output pads is called a "sink". @anchor{Filtergraph syntax} @section Filtergraph syntax -A filtergraph can be represented using a textual representation, which is +A filtergraph has a textual representation, which is recognized by the @option{-filter}/@option{-vf} and @option{-filter_complex} options in @command{ffmpeg} and @option{-vf} in @command{ffplay}, and by the -@code{avfilter_graph_parse()}/@code{avfilter_graph_parse2()} function defined in +@code{avfilter_graph_parse()}/@code{avfilter_graph_parse2()} functions defined in @file{libavfilter/avfilter.h}. A filterchain consists of a sequence of connected filters, each one @@ -138,7 +138,7 @@ The name of the filter class is optionally followed by a string "=@var{arguments}". @var{arguments} is a string which contains the parameters used to -initialize the filter instance. It may have one of the following forms: +initialize the filter instance. It may have one of two forms: @itemize @item @@ -184,7 +184,7 @@ created. If an output pad is not labelled, it is linked by default to the first unlabelled input pad of the next filter in the filterchain. -For example in the filterchain: +For example in the filterchain @example nullsrc, split[L1], [L2]overlay, nullsink @end example @@ -204,12 +204,12 @@ for those automatically inserted scalers by prepending @code{sws_flags=@var{flags};} to the filtergraph description. -Follows a BNF description for the filtergraph syntax: +Here is a BNF description of the filtergraph syntax: @example @var{NAME} ::= sequence of alphanumeric characters and '_' @var{LINKLABEL} ::= "[" @var{NAME} "]" @var{LINKLABELS} ::= @var{LINKLABEL} [@var{LINKLABELS}] -@var{FILTER_ARGUMENTS} ::= sequence of chars (eventually quoted) +@var{FILTER_ARGUMENTS} ::= sequence of chars (possibly quoted) @var{FILTER} ::= [@var{LINKLABELS}] @var{NAME} ["=" @var{FILTER_ARGUMENTS}] [@var{LINKLABELS}] @var{FILTERCHAIN} ::= @var{FILTER} [,@var{FILTERCHAIN}] @var{FILTERGRAPH} ::= [sws_flags=@var{flags};] @var{FILTERCHAIN} [;@var{FILTERGRAPH}] @@ -438,7 +438,7 @@ Modify an audio signal according to the specified expressions. This filter accepts one or more expressions (one for each channel), which are evaluated and used to modify a corresponding audio signal. -This filter accepts the following options: +It accepts the following parameters: @table @option @item exprs @@ -589,7 +589,7 @@ afade=t=out:st=875:d=25 Set output format constraints for the input audio. The framework will negotiate the most appropriate format to minimize conversions. -The filter accepts the following named parameters: +It accepts the following parameters: @table @option @item sample_fmts @@ -607,7 +607,7 @@ for the required syntax. If a parameter is omitted, all values are allowed. -For example to force the output to either unsigned 8-bit or signed 16-bit stereo: +Force the output to either unsigned 8-bit or signed 16-bit stereo @example aformat=sample_fmts=u8|s16:channel_layouts=stereo @end example @@ -697,6 +697,11 @@ ffmpeg -i input.mkv -filter_complex "[0:1][0:2][0:3][0:4][0:5][0:6] amerge=input Mixes multiple audio inputs into a single output. +Note that this filter only supports float samples (the @var{amerge} +and @var{pan} audio filters support many formats). If the @var{amix} +input has integer samples then @ref{aresample} will be automatically +inserted to perform the conversion to float samples. + For example @example ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex amix=inputs=3:duration=first:dropout_transition=3 OUTPUT @@ -704,29 +709,29 @@ ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex amix=inputs=3:duration=firs will mix 3 input audio streams to a single output with the same duration as the first input and a dropout transition time of 3 seconds. -The filter accepts the following named parameters: +It accepts the following parameters: @table @option @item inputs -Number of inputs. If unspecified, it defaults to 2. +The number of inputs. If unspecified, it defaults to 2. @item duration How to determine the end-of-stream. @table @option @item longest -Duration of longest input. (default) +The duration of the longest input. (default) @item shortest -Duration of shortest input. +The duration of the shortest input. @item first -Duration of first input. +The duration of the first input. @end table @item dropout_transition -Transition time, in seconds, for volume renormalization when an input +The transition time, in seconds, for volume renormalization when an input stream ends. The default value is 2 seconds. @end table @@ -857,38 +862,38 @@ The input audio is not modified. The shown line contains a sequence of key/value pairs of the form @var{key}:@var{value}. -A description of each shown parameter follows: +It accepts the following parameters: @table @option @item n -sequential number of the input frame, starting from 0 +The (sequential) number of the input frame, starting from 0. @item pts -Presentation timestamp of the input frame, in time base units; the time base +The presentation timestamp of the input frame, in time base units; the time base depends on the filter input pad, and is usually 1/@var{sample_rate}. @item pts_time -presentation timestamp of the input frame in seconds +The presentation timestamp of the input frame in seconds. @item pos position of the frame in the input stream, -1 if this information in unavailable and/or meaningless (for example in case of synthetic audio) @item fmt -sample format +The sample format. @item chlayout -channel layout +The channel layout. @item rate -sample rate for the audio frame +The sample rate for the audio frame. @item nb_samples -number of samples (per channel) in the frame +The number of samples (per channel) in the frame. @item checksum -Adler-32 checksum (printed in hexadecimal) of the audio data. For planar audio -the data is treated as if all the planes were concatenated. +The Adler-32 checksum (printed in hexadecimal) of the audio data. For planar +audio, the data is treated as if all the planes were concatenated. @item plane_checksums A list of Adler-32 checksums for each data plane. @@ -900,7 +905,7 @@ Display time domain statistical information about the audio channels. Statistics are calculated and displayed for each audio channel and, where applicable, an overall figure is also given. -The filter accepts the following option: +It accepts the following option: @table @option @item length Short window length in seconds, used for peak and trough RMS measurement. @@ -982,7 +987,7 @@ dropping samples/adding silence when needed. This filter is not built by default, please use @ref{aresample} to do squeezing/stretching. -The filter accepts the following named parameters: +It accepts the following parameters: @table @option @item compensate @@ -990,21 +995,21 @@ Enable stretching/squeezing the data to make it match the timestamps. Disabled by default. When disabled, time gaps are covered with silence. @item min_delta -Minimum difference between timestamps and audio data (in seconds) to trigger -adding/dropping samples. Default value is 0.1. If you get non-perfect sync with -this filter, try setting this parameter to 0. +The minimum difference between timestamps and audio data (in seconds) to trigger +adding/dropping samples. The default value is 0.1. If you get an imperfect +sync with this filter, try setting this parameter to 0. @item max_comp -Maximum compensation in samples per second. Relevant only with compensate=1. -Default value 500. +The maximum compensation in samples per second. Only relevant with compensate=1. +The default value is 500. @item first_pts -Assume the first pts should be this value. The time base is 1 / sample rate. -This allows for padding/trimming at the start of stream. By default, no -assumption is made about the first frame's expected pts, so no padding or +Assume that the first PTS should be this value. The time base is 1 / sample +rate. This allows for padding/trimming at the start of the stream. By default, +no assumption is made about the first frame's expected PTS, so no padding or trimming is done. For example, this could be set to 0 to pad the beginning with silence if an audio stream starts after the video stream or to trim any samples -with a negative pts due to encoder delay. +with a negative PTS due to encoder delay. @end table @@ -1036,11 +1041,11 @@ atempo=1.25 Trim the input so that the output contains one continuous subpart of the input. -This filter accepts the following options: +It accepts the following parameters: @table @option @item start -Specify time of the start of the kept section, i.e. the audio sample -with the timestamp @var{start} will be the first sample in the output. +Timestamp (in seconds) of the start of the section to keep. I.e. the audio +sample with the timestamp @var{start} will be the first sample in the output. @item end Specify time of the first audio sample that will be dropped, i.e. the @@ -1056,13 +1061,13 @@ Same as @var{end}, except this option sets the end timestamp in samples instead of seconds. @item duration -Specify maximum duration of the output. +The maximum duration of the output in seconds. @item start_sample -Number of the first sample that should be passed to output. +The number of the first sample that should be output. @item end_sample -Number of the first sample that should be dropped. +The number of the first sample that should be dropped. @end table @option{start}, @option{end}, @option{duration} are expressed as time @@ -1074,7 +1079,7 @@ option look at the frame timestamp, while the _sample options simply count the samples that pass through the filter. So start/end_pts and start/end_sample will give different results when the timestamps are wrong, inexact or do not start at zero. Also note that this filter does not modify the timestamps. If you wish -that the output timestamps start at zero, insert the asetpts filter after the +to have the output timestamps start at zero, insert the asetpts filter after the atrim filter. If multiple start or end options are set, this filter tries to be greedy and @@ -1088,13 +1093,13 @@ just the end values to keep everything before the specified time. Examples: @itemize @item -drop everything except the second minute of input +Drop everything except the second minute of input: @example ffmpeg -i INPUT -af atrim=60:120 @end example @item -keep only the first 1000 samples +Keep only the first 1000 samples: @example ffmpeg -i INPUT -af atrim=end_sample=1000 @end example @@ -1206,14 +1211,44 @@ Apply a biquad IIR filter with the given coefficients. Where @var{b0}, @var{b1}, @var{b2} and @var{a0}, @var{a1}, @var{a2} are the numerator and denominator coefficients respectively. +@section bs2b +Bauer stereo to binaural transformation, which improves headphone listening of +stereo audio records. + +It accepts the following parameters: +@table @option + +@item profile +Pre-defined crossfeed level. +@table @option + +@item default +Default level (fcut=700, feed=50). + +@item cmoy +Chu Moy circuit (fcut=700, feed=60). + +@item jmeier +Jan Meier circuit (fcut=650, feed=95). + +@end table + +@item fcut +Cut frequency (in Hz). + +@item feed +Feed level (in Hz). + +@end table + @section channelmap Remap input channels to new locations. -This filter accepts the following named parameters: +It accepts the following parameters: @table @option @item channel_layout -Channel layout of the output stream. +The channel layout of the output stream. @item map Map channels from input to output. The argument is a '|'-separated list of @@ -1226,9 +1261,9 @@ index, starting with zero and increasing by one for each mapping. @end table If no mapping is present, the filter will implicitly map input channels to -output channels preserving index. +output channels, preserving indices. -For example, assuming a 5.1+downmix input MOV file +For example, assuming a 5.1+downmix input MOV file, @example ffmpeg -i in.mov -filter 'channelmap=map=DL-FL|DR-FR' out.wav @end example @@ -1242,22 +1277,22 @@ ffmpeg -i in.wav -filter 'channelmap=1|2|0|5|3|4:channel_layout=5.1' out.wav @section channelsplit -Split each channel in input audio stream into a separate output stream. +Split each channel from an input audio stream into a separate output stream. -This filter accepts the following named parameters: +It accepts the following parameters: @table @option @item channel_layout -Channel layout of the input stream. Default is "stereo". +The channel layout of the input stream. The default is "stereo". @end table -For example, assuming a stereo input MP3 file +For example, assuming a stereo input MP3 file, @example ffmpeg -i in.mp3 -filter_complex channelsplit out.mkv @end example will create an output Matroska file with two audio streams, one containing only the left channel and the other the right channel. -To split a 5.1 WAV file into per-channel files +Split a 5.1 WAV file into per-channel files: @example ffmpeg -i in.wav -filter_complex 'channelsplit=channel_layout=5.1[FL][FR][FC][LFE][SL][SR]' @@ -1267,24 +1302,24 @@ side_right.wav @end example @section compand -Compress or expand audio dynamic range. +Compress or expand the audio's dynamic range. -A description of the accepted options follows. +It accepts the following parameters: @table @option @item attacks @item decays -Set list of times in seconds for each channel over which the instantaneous level +A list of times in seconds for each channel over which the instantaneous level of the input signal is averaged to determine its volume. @var{attacks} refers to increase of volume and @var{decays} refers to decrease of volume. For most situations, the attack time (response to the audio getting louder) should be -shorter than the decay time because the human ear is more sensitive to sudden +shorter than the decay time, because the human ear is more sensitive to sudden loud audio than sudden soft audio. A typical value for attack is 0.3 seconds and a typical value for decay is 0.8 seconds. @item points -Set list of points for the transfer function, specified in dB relative to the +A list of points for the transfer function, specified in dB relative to the maximum possible signal amplitude. Each key points list must be defined using the following syntax: @code{x0/y0|x1/y1|x2/y2|....} or @code{x0/y0 x1/y1 x2/y2 ....} @@ -1295,24 +1330,25 @@ may be overridden (by @code{0/out-dBn}). Typical values for the transfer function are @code{-70/-70|-60/-20}. @item soft-knee -Set the curve radius in dB for all joints. Defaults to 0.01. +Set the curve radius in dB for all joints. It defaults to 0.01. @item gain -Set additional gain in dB to be applied at all points on the transfer function. -This allows easy adjustment of the overall gain. Defaults to 0. +Set the additional gain in dB to be applied at all points on the transfer +function. This allows for easy adjustment of the overall gain. +It defaults to 0. @item volume -Set initial volume in dB to be assumed for each channel when filtering starts. -This permits the user to supply a nominal level initially, so that, for +Set an initial volume, in dB, to be assumed for each channel when filtering +starts. This permits the user to supply a nominal level initially, so that, for example, a very large gain is not applied to initial signal levels before the companding has begun to operate. A typical value for audio which is initially -quiet is -90 dB. Defaults to 0. +quiet is -90 dB. It defaults to 0. @item delay -Set delay in seconds. The input audio is analyzed immediately, but audio is +Set a delay, in seconds. The input audio is analyzed immediately, but audio is delayed before being fed to the volume adjuster. Specifying a delay approximately equal to the attack/decay times allows the filter to effectively -operate in predictive rather than reactive mode. Defaults to 0. +operate in predictive rather than reactive mode. It defaults to 0. @end table @@ -1320,14 +1356,14 @@ operate in predictive rather than reactive mode. Defaults to 0. @itemize @item -Make music with both quiet and loud passages suitable for listening in a noisy -environment: +Make music with both quiet and loud passages suitable for listening to in a +noisy environment: @example compand=.3|.3:1|1:-90/-60|-60/-40|-40/-30|-20/-20:6:0:-90:0.2 @end example @item -Noise gate for when the noise is at a lower level than the signal: +A noise gate for when the noise is at a lower level than the signal: @example compand=.1|.1:.2|.2:-900/-900|-50.1/-900|-50/-50:.01:0:-90:.1 @end example @@ -1403,6 +1439,42 @@ equalizer=f=1000:width_type=q:width=1:g=2,equalizer=f=100:width_type=q:width=2:g @end example @end itemize +@section flanger +Apply a flanging effect to the audio. + +The filter accepts the following options: + +@table @option +@item delay +Set base delay in milliseconds. Range from 0 to 30. Default value is 0. + +@item depth +Set added swep delay in milliseconds. Range from 0 to 10. Default value is 2. + +@item regen +Set percentage regeneneration (delayed signal feedback). Range from -95 to 95. +Default value is 0. + +@item width +Set percentage of delayed signal mixed with original. Range from 0 to 100. +Default valu is 71. + +@item speed +Set sweeps per second (Hz). Range from 0.1 to 10. Default value is 0.5. + +@item shape +Set swept wave shape, can be @var{triangular} or @var{sinusoidal}. +Default value is @var{sinusoidal}. + +@item phase +Set swept wave percentage-shift for multi channel. Range from 0 to 100. +Default value is 25. + +@item interp +Set delay-line interpolation, @var{linear} or @var{quadratic}. +Default is @var{linear}. +@end table + @section highpass Apply a high-pass filter with 3dB point frequency. @@ -1441,14 +1513,14 @@ The default is 0.707q and gives a Butterworth response. Join multiple input streams into one multi-channel stream. -The filter accepts the following named parameters: +It accepts the following parameters: @table @option @item inputs -Number of input streams. Defaults to 2. +The number of input streams. It defaults to 2. @item channel_layout -Desired output channel layout. Defaults to stereo. +The desired output channel layout. It defaults to stereo. @item map Map channels from inputs to output. The argument is a '|'-separated list of @@ -1459,16 +1531,16 @@ index in the specified input stream. @var{out_channel} is the name of the output channel. @end table -The filter will attempt to guess the mappings when those are not specified +The filter will attempt to guess the mappings when they are not specified explicitly. It does so by first trying to find an unused matching input channel and if that fails it picks the first unused input channel. -E.g. to join 3 inputs (with properly set channel layouts) +Join 3 inputs (with properly set channel layouts): @example ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex join=inputs=3 OUTPUT @end example -To build a 5.1 output from 6 single-channel streams: +Build a 5.1 output from 6 single-channel streams: @example ffmpeg -i fl -i fr -i fc -i sl -i sr -i lfe -filter_complex 'join=inputs=6:channel_layout=5.1:map=0.0-FL|1.0-FR|2.0-FC|3.0-SL|4.0-SR|5.0-LFE' @@ -1718,7 +1790,7 @@ At end of filtering it displays @code{track_gain} and @code{track_peak}. @section resample -Convert the audio sample format, sample rate and channel layout. This filter is +Convert the audio sample format, sample rate and channel layout. It is not meant to be used directly. @section silencedetect @@ -1799,8 +1871,7 @@ Determine how steep is the filter's shelf transition. Adjust the input audio volume. -The filter accepts the following options: - +It accepts the following parameters: @table @option @item volume @@ -1813,23 +1884,45 @@ The output audio volume is given by the relation: @var{output_volume} = @var{volume} * @var{input_volume} @end example -Default value for @var{volume} is "1.0". +The default value for @var{volume} is "1.0". @item precision -Set the mathematical precision. +This parameter represents the mathematical precision. -This determines which input sample formats will be allowed, which affects the +It determines which input sample formats will be allowed, which affects the precision of the volume scaling. @table @option @item fixed -8-bit fixed-point; limits input sample format to U8, S16, and S32. +8-bit fixed-point; this limits input sample format to U8, S16, and S32. @item float -32-bit floating-point; limits input sample format to FLT. (default) +32-bit floating-point; this limits input sample format to FLT. (default) @item double -64-bit floating-point; limits input sample format to DBL. +64-bit floating-point; this limits input sample format to DBL. @end table +@item replaygain +Choose the behaviour on encountering ReplayGain side data in input frames. + +@table @option +@item drop +Remove ReplayGain side data, ignoring its contents (the default). + +@item ignore +Ignore ReplayGain side data, but leave it in the frame. + +@item track +Prefer the track gain, if present. + +@item album +Prefer the album gain, if present. +@end table + +@item replaygain_preamp +Pre-amplification gain in dB to apply to the selected replaygain gain. + +Default value for @var{replaygain_preamp} is 0.0. + @item eval Set when the volume expression is evaluated. @@ -1889,6 +1982,11 @@ The command accepts the same syntax of the corresponding option. If the specified expression is not valid, it is kept at its current value. +@item replaygain_noclip +Prevent clipping by limiting the gain applied. + +Default value for @var{replaygain_noclip} is 1. + @end table @subsection Examples @@ -1977,12 +2075,11 @@ Buffer audio frames, and make them available to the filter chain. This source is mainly intended for a programmatic use, in particular through the interface defined in @file{libavfilter/asrc_abuffer.h}. -It accepts the following named parameters: - +It accepts the following parameters: @table @option @item time_base -Timebase which will be used for timestamps of submitted frames. It must be +The timebase which will be used for timestamps of submitted frames. It must be either a floating-point number or in @var{numerator}/@var{denominator} form. @item sample_rate @@ -2118,7 +2215,7 @@ aevalsrc="0.1*sin(2*PI*(360-2.5/2)*t) | 0.1*sin(2*PI*(360+2.5/2)*t)" @section anullsrc -Null audio source, return unprocessed audio frames. It is mainly useful +The null audio source, return unprocessed audio frames. It is mainly useful as a template and to be employed in analysis / debugging tools, or as the source for filters which ignore the input data (for example the sox synth filter). @@ -2129,7 +2226,7 @@ This source accepts the following options: @item channel_layout, cl -Specify the channel layout, and can be either an integer or a string +Specifies the channel layout, and can be either an integer or a string representing a channel layout. The default value of @var{channel_layout} is "stereo". @@ -2138,7 +2235,7 @@ Check the channel_layout_map definition in channel layout values. @item sample_rate, r -Specify the sample rate, and defaults to 44100. +Specifies the sample rate, and defaults to 44100. @item nb_samples, n Set the number of samples per requested frames. @@ -2292,11 +2389,10 @@ or the options system. It accepts a pointer to an AVABufferSinkContext structure, which defines the incoming buffers' formats, to be passed as the opaque parameter to @code{avfilter_init_filter} for initialization. - @section anullsink -Null audio sink, do absolutely nothing with the input audio. It is -mainly useful as a template and to be employed in analysis / debugging +Null audio sink; do absolutely nothing with the input audio. It is +mainly useful as a template and for use in analysis / debugging tools. @c man end AUDIO SINKS @@ -2421,16 +2517,16 @@ the position in the file if known or -1 and the timestamp in seconds. In order to display the output lines, you need to set the loglevel at least to the AV_LOG_INFO value. -The filter accepts the following options: +It accepts the following parameters: @table @option @item amount -Set the percentage of the pixels that have to be below the threshold, defaults -to @code{98}. +The percentage of the pixels that have to be below the threshold; it defaults to +@code{98}. @item threshold, thresh -Set the threshold below which a pixel value is considered black, defaults to +The threshold below which a pixel value is considered black; it defaults to @code{32}. @end table @@ -2573,9 +2669,9 @@ blend=all_expr='if(gte(T*SH*40+Y,H)*gte((T*40*SW+X)*W/H,W),A,B)' @section boxblur -Apply boxblur algorithm to the input video. +Apply a boxblur algorithm to the input video. -The filter accepts the following options: +It accepts the following parameters: @table @option @@ -2610,16 +2706,16 @@ The expressions can contain the following constants: @table @option @item w @item h -the input width and height in pixels +The input width and height in pixels. @item cw @item ch -the input chroma image width and height in pixels +The input chroma image width and height in pixels. @item hsub @item vsub -horizontal and vertical chroma subsample values. For example for the -pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1. +The horizontal and vertical chroma subsample values. For example, for the +pixel format "yuv422p", @var{hsub} is 2 and @var{vsub} is 1. @end table @item luma_power, lp @@ -2639,7 +2735,7 @@ A value of 0 will disable the effect. @itemize @item -Apply a boxblur filter with luma, chroma, and alpha radius +Apply a boxblur filter with the luma, chroma, and alpha radii set to 2: @example boxblur=luma_radius=2:luma_power=1 @@ -2647,13 +2743,13 @@ boxblur=2:1 @end example @item -Set luma radius to 2, alpha and chroma radius to 0: +Set the luma radius to 2, and alpha and chroma radius to 0: @example boxblur=2:1:cr=0:ar=0 @end example @item -Set luma and chroma radius to a fraction of the video dimension: +Set the luma and chroma radii to a fraction of the video dimension: @example boxblur=luma_radius=min(h\,w)/10:luma_power=1:chroma_radius=min(cw\,ch)/10:chroma_power=1 @end example @@ -2794,33 +2890,33 @@ colormatrix=bt601:smpte240m @section copy -Copy the input source unchanged to the output. Mainly useful for +Copy the input source unchanged to the output. This is mainly useful for testing purposes. @section crop Crop the input video to given dimensions. -The filter accepts the following options: +It accepts the following parameters: @table @option @item w, out_w -Width of the output video. It defaults to @code{iw}. +The width of the output video. It defaults to @code{iw}. This expression is evaluated only once during the filter configuration. @item h, out_h -Height of the output video. It defaults to @code{ih}. +The height of the output video. It defaults to @code{ih}. This expression is evaluated only once during the filter configuration. @item x -Horizontal position, in the input video, of the left edge of the output video. -It defaults to @code{(in_w-out_w)/2}. +The horizontal position, in the input video, of the left edge of the output +video. It defaults to @code{(in_w-out_w)/2}. This expression is evaluated per-frame. @item y -Vertical position, in the input video, of the top edge of the output video. +The vertical position, in the input video, of the top edge of the output video. It defaults to @code{(in_h-out_h)/2}. This expression is evaluated per-frame. @@ -2836,24 +2932,24 @@ expressions containing the following constants: @table @option @item x @item y -the computed values for @var{x} and @var{y}. They are evaluated for +The computed values for @var{x} and @var{y}. They are evaluated for each new frame. @item in_w @item in_h -the input width and height +The input width and height. @item iw @item ih -same as @var{in_w} and @var{in_h} +These are the same as @var{in_w} and @var{in_h}. @item out_w @item out_h -the output (cropped) width and height +The output (cropped) width and height. @item ow @item oh -same as @var{out_w} and @var{out_h} +These are the same as @var{out_w} and @var{out_h}. @item a same as @var{iw} / @var{ih} @@ -2870,13 +2966,13 @@ horizontal and vertical chroma subsample values. For example for the pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1. @item n -the number of input frame, starting from 0 +The number of the input frame, starting from 0. @item pos the position in the file of the input frame, NAN if unknown @item t -timestamp expressed in seconds, NAN if the input timestamp is unknown +The timestamp expressed in seconds. It's NAN if the input timestamp is unknown. @end table @@ -2929,7 +3025,7 @@ crop=in_h @item Delimit the rectangle with the top-left corner placed at position 100:100 and the right-bottom corner corresponding to the right-bottom -corner of the input image: +corner of the input image. @example crop=in_w-100:in_h-100:100:100 @end example @@ -2974,26 +3070,26 @@ crop=in_w/2:in_h/2:y:10+10*sin(n/10) @section cropdetect -Auto-detect crop size. +Auto-detect the crop size. -Calculate necessary cropping parameters and prints the recommended -parameters through the logging system. The detected dimensions +It calculates the necessary cropping parameters and prints the +recommended parameters via the logging system. The detected dimensions correspond to the non-black area of the input video. -The filter accepts the following options: +It accepts the following parameters: @table @option @item limit Set higher black value threshold, which can be optionally specified from nothing (0) to everything (255). An intensity value greater -to the set value is considered non-black. Default value is 24. +to the set value is considered non-black. It defaults to 24. @item round -Set the value for which the width/height should be divisible by. The -offset is automatically adjusted to center the video. Use 2 to get -only even dimensions (needed for 4:2:2 video). 16 is best when -encoding to most video codecs. Default value is 16. +The value which the width/height should be divisible by. It defaults to +16. The offset is automatically adjusted to center the video. Use 2 to +get only even dimensions (needed for 4:2:2 video). 16 is best when +encoding to most video codecs. @item reset_count, reset Set the counter that determines after how many frames cropdetect will @@ -3001,7 +3097,7 @@ reset the previously detected largest video area and start over to detect the current optimal crop area. Default value is 0. This can be useful when channel logos distort the video area. 0 -indicates never reset and return the largest area encountered during +indicates 'never reset', and returns the largest area encountered during playback. @end table @@ -3228,7 +3324,7 @@ The option available in this filter is: @item cycle Specify the length of the window over which the judder repeats. -Accepts any interger greater than 1. Useful values are: +Accepts any integer greater than 1. Useful values are: @table @samp @item 4 @@ -3250,7 +3346,7 @@ Suppress a TV station logo by a simple interpolation of the surrounding pixels. Just set a rectangle covering the logo and watch it disappear (and sometimes something even uglier appear - your mileage may vary). -This filter accepts the following options: +It accepts the following parameters: @table @option @item x @@ -3284,7 +3380,7 @@ compute the interpolated pixel values inside the rectangle. @itemize @item Set a rectangle covering the area with top left corner coordinates 0,0 -and size 100x77, setting a band of size 10: +and size 100x77, and a band of size 10: @example delogo=x=0:y=0:w=100:h=77:band=10 @end example @@ -3375,17 +3471,17 @@ FFmpeg was configured with @code{--enable-opencl}. Default value is 0. Draw a colored box on the input image. -This filter accepts the following options: +It accepts the following parameters: @table @option @item x @item y -The expressions which specify the top left corner coordinates of the box. Default to 0. +The expressions which specify the top left corner coordinates of the box. It defaults to 0. @item width, w @item height, h -The expressions which specify the width and height of the box, if 0 they are interpreted as -the input width and height. Default to 0. +The expressions which specify the width and height of the box; if 0 they are interpreted as +the input width and height. It defaults to 0. @item color, c Specify the color of the box to write. For the general syntax of this option, @@ -3471,7 +3567,7 @@ drawbox=x=-t:y=0.5*(ih-iw/2.4)-t:w=iw+t*2:h=iw/2.4+t*2:t=2:c=red Draw a grid on the input image. -This filter accepts the following options: +It accepts the following parameters: @table @option @item x @@ -3550,21 +3646,25 @@ drawgrid=w=iw/3:h=ih/3:t=2:c=white@@0.5 @anchor{drawtext} @section drawtext -Draw text string or text from specified file on top of video using the +Draw a text string or text from a specified file on top of a video, using the libfreetype library. -To enable compilation of this filter you need to configure FFmpeg with +To enable compilation of this filter, you need to configure FFmpeg with @code{--enable-libfreetype}. +To enable default font fallback and the @var{font} option you need to +configure FFmpeg with @code{--enable-libfontconfig}. +To enable the @var{text_shaping} option, you need to configure FFmpeg with +@code{--enable-libfribidi}. @subsection Syntax -The description of the accepted parameters follows. +It accepts the following parameters: @table @option @item box -Used to draw a box around text using background color. -Value should be either 1 (enable) or 0 (disable). +Used to draw a box around text using the background color. +The value must be either 1 (enable) or 0 (disable). The default value of @var{box} is 0. @item boxcolor @@ -3598,16 +3698,25 @@ the "Color" section in the ffmpeg-utils manual. The default value of @var{fontcolor} is "black". +@item font +The font family to be used for drawing text. By default Sans. + @item fontfile -The font file to be used for drawing text. Path must be included. -This parameter is mandatory. +The font file to be used for drawing text. The path must be included. +This parameter is mandatory if the fontconfig support is disabled. @item fontsize The font size to be used for drawing text. The default value of @var{fontsize} is 16. +@item text_shaping +If set to 1, attempt to shape the text (for example, reverse the order of +right-to-left text and join Arabic characters) before drawing it. +Otherwise, just draw the text exactly as given. +By default 1 (if supported). + @item ft_load_flags -Flags to be used for loading the fonts. +The flags to be used for loading the fonts. The flags map the corresponding flags supported by libfreetype, and are a combination of the following values: @@ -3644,7 +3753,7 @@ The default value of @var{shadowcolor} is "black". @item shadowy The x and y offsets for the text shadow position with respect to the position of the text. They can be either positive or negative -values. Default value for both is "0". +values. The default value for both is "0". @item start_number The starting frame number for the n/frame_num variable. The default value @@ -3742,7 +3851,7 @@ the number of input frame, starting from 0 return a random number included between @var{min} and @var{max} @item sar -input sample aspect ratio +The input sample aspect ratio. @item t timestamp expressed in seconds, NAN if the input timestamp is unknown @@ -3761,9 +3870,6 @@ These parameters allow the @var{x} and @var{y} expressions to refer each other, so you can for example specify @code{y=x/dar}. @end table -If libavfilter was built with @code{--enable-fontconfig}, then -@option{fontfile} can be a fontconfig pattern or omitted. - @anchor{drawtext_expansion} @subsection Text expansion @@ -3823,7 +3929,14 @@ The frame number, starting from 0. A 1 character description of the current picture type. @item pts -The timestamp of the current frame, in seconds, with microsecond accuracy. +The timestamp of the current frame. +It can take up to two arguments. + +The first argument is the format of the timestamp; it defaults to @code{flt} +for seconds as a decimal number with microsecond accuracy; @code{hms} stands +for a formatted @var{[-]HH:MM:SS.mmm} timestamp with millisecond accuracy. + +The second argument is an offset added to the timestamp. @end table @@ -3905,6 +4018,9 @@ For more information about libfreetype, check: For more information about fontconfig, check: @url{http://freedesktop.org/software/fontconfig/fontconfig-user.html}. +For more information about libfribidi, check: +@url{http://fribidi.org/}. + @section edgedetect Detect and draw edges. The filter uses the Canny Edge Detection algorithm. @@ -3926,13 +4042,37 @@ by the low threshold. Default value for @var{low} is @code{20/255}, and default value for @var{high} is @code{50/255}. + +@item mode +Define the drawing mode. + +@table @samp +@item wires +Draw white/gray wires on black background. + +@item colormix +Mix the colors to create a paint/cartoon effect. @end table -Example: +Default value is @var{wires}. +@end table + +@subsection Examples + +@itemize +@item +Standard edge detection with custom values for the hysteresis thresholding: @example edgedetect=low=0.1:high=0.4 @end example +@item +Painting effect without thresholding: +@example +edgedetect=mode=colormix:high=0 +@end example +@end itemize + @section extractplanes Extract color channel components from input video stream into @@ -3999,24 +4139,24 @@ will try to use a good random seed on a best effort basis. @section fade -Apply fade-in/out effect to input video. +Apply a fade-in/out effect to the input video. -This filter accepts the following options: +It accepts the following parameters: @table @option @item type, t -The effect type -- can be either "in" for fade-in, or "out" for a fade-out +The effect type can be either "in" for a fade-in, or "out" for a fade-out effect. Default is @code{in}. @item start_frame, s -Specify the number of the start frame for starting to apply the fade -effect. Default is 0. +Specify the number of the frame to start applying the fade +effect at. Default is 0. @item nb_frames, n -The number of frames for which the fade effect has to last. At the end of the -fade-in effect the output video will have the same intensity as the input video, -at the end of the fade-out transition the output video will be filled with the +The number of frames that the fade effect lasts. At the end of the +fade-in effect, the output video will have the same intensity as the input video. +At the end of the fade-out transition, the output video will be filled with the selected @option{color}. Default is 25. @@ -4044,7 +4184,7 @@ Specify the color of the fade. Default is "black". @itemize @item -Fade in first 30 frames of video: +Fade in the first 30 frames of video: @example fade=in:0:30 @end example @@ -4055,20 +4195,20 @@ fade=t=in:s=0:n=30 @end example @item -Fade out last 45 frames of a 200-frame video: +Fade out the last 45 frames of a 200-frame video: @example fade=out:155:45 fade=type=out:start_frame=155:nb_frames=45 @end example @item -Fade in first 25 frames and fade out last 25 frames of a 1000-frame video: +Fade in the first 25 frames and fade out the last 25 frames of a 1000-frame video: @example fade=in:0:25, fade=out:975:25 @end example @item -Make first 5 frames yellow, then fade in from frame 5-24: +Make the first 5 frames yellow, then fade in from frame 5-24: @example fade=in:5:20:color=yellow @end example @@ -4080,7 +4220,7 @@ fade=in:0:25:alpha=1 @end example @item -Make first 5.5 seconds black, then fade in for 0.5 seconds: +Make the first 5.5 seconds black, then fade in for 0.5 seconds: @example fade=t=in:st=5.5:d=0.5 @end example @@ -4428,26 +4568,26 @@ fieldmatch=order=tff:combmatch=full, yadif=deint=interlaced, decimate Transform the field order of the input video. -This filter accepts the following options: +It accepts the following parameters: @table @option @item order -Output field order. Valid values are @var{tff} for top field first or @var{bff} +The output field order. Valid values are @var{tff} for top field first or @var{bff} for bottom field first. @end table -Default value is @samp{tff}. +The default value is @samp{tff}. -Transformation is achieved by shifting the picture content up or down +The transformation is done by shifting the picture content up or down by one line, and filling the remaining line with appropriate picture content. This method is consistent with most broadcast field order converters. If the input video is not flagged as being interlaced, or it is already -flagged as being of the required output field order then this filter does +flagged as being of the required output field order, then this filter does not alter the incoming video. -This filter is very useful when converting to or from PAL DV material, +It is very useful when converting to or from PAL DV material, which is bottom field first. For example: @@ -4459,23 +4599,23 @@ ffmpeg -i in.vob -vf "fieldorder=bff" out.dv Buffer input images and send them when they are requested. -This filter is mainly useful when auto-inserted by the libavfilter +It is mainly useful when auto-inserted by the libavfilter framework. -The filter does not take parameters. +It does not take parameters. @anchor{format} @section format Convert the input video to one of the specified pixel formats. -Libavfilter will try to pick one that is supported for the input to +Libavfilter will try to pick one that is suitable as input to the next filter. -This filter accepts the following parameters: +It accepts the following parameters: @table @option @item pix_fmts -A '|'-separated list of pixel format names, for example +A '|'-separated list of pixel format names, such as "pix_fmts=yuv420p|monow|rgb24". @end table @@ -4484,7 +4624,7 @@ A '|'-separated list of pixel format names, for example @itemize @item -Convert the input video to the format @var{yuv420p} +Convert the input video to the @var{yuv420p} format @example format=pix_fmts=yuv420p @end example @@ -4501,11 +4641,11 @@ format=pix_fmts=yuv420p|yuv444p|yuv410p Convert the video to specified constant frame rate by duplicating or dropping frames as necessary. -This filter accepts the following named parameters: +It accepts the following parameters: @table @option @item fps -Desired output frame rate. The default is @code{25}. +The desired output frame rate. The default is @code{25}. @item round Rounding method. @@ -4564,40 +4704,40 @@ framerate and processing will stop when the shorter video ends. Please note that you may conveniently adjust view properties with the @ref{scale} and @ref{fps} filters. -This filter accepts the following named parameters: +It accepts the following parameters: @table @option @item format -Desired packing format. Supported values are: +The desired packing format. Supported values are: @table @option @item sbs -Views are next to each other (default). +The views are next to each other (default). @item tab -Views are on top of each other. +The views are on top of each other. @item lines -Views are packed by line. +The views are packed by line. @item columns -Views are eacked by column. +The views are packed by column. @item frameseq -Views are temporally interleaved. +The views are temporally interleaved. @end table @end table -Some examples follow: +Some examples: @example -# Convert left and right views into a frame sequential video. +# Convert left and right views into a frame-sequential video ffmpeg -i LEFT -i RIGHT -filter_complex framepack=frameseq OUTPUT -# Convert views into a side-by-side video with the same output resolution as the input. +# Convert views into a side-by-side video with the same output resolution as the input ffmpeg -i LEFT -i RIGHT -filter_complex [0:v]scale=w=iw/2[left],[1:v]scale=w=iw/2[right],[left][right]framepack=sbs OUTPUT @end example @@ -4617,18 +4757,18 @@ Allowed values are positive integers higher than 0. Default value is @code{1}. Apply a frei0r effect to the input video. -To enable compilation of this filter you need to install the frei0r +To enable the compilation of this filter, you need to install the frei0r header and configure FFmpeg with @code{--enable-frei0r}. -This filter accepts the following options: +It accepts the following parameters: @table @option @item filter_name -The name to the frei0r effect to load. If the environment variable -@env{FREI0R_PATH} is defined, the frei0r effect is searched in each one of the -directories specified by the colon separated list in @env{FREIOR_PATH}, -otherwise in the standard frei0r paths, which are in this order: +The name of the frei0r effect to load. If the environment variable +@env{FREI0R_PATH} is defined, the frei0r effect is searched for in each of the +directories specified by the colon-separated list in @env{FREIOR_PATH}. +Otherwise, the standard frei0r paths are searched, in this order: @file{HOME/.frei0r-1/lib/}, @file{/usr/local/lib/frei0r-1/}, @file{/usr/lib/frei0r-1/}. @@ -4637,27 +4777,27 @@ A '|'-separated list of parameters to pass to the frei0r effect. @end table -A frei0r effect parameter can be a boolean (whose values are specified -with "y" and "n"), a double, a color (specified by the syntax -@var{R}/@var{G}/@var{B}, (@var{R}, @var{G}, and @var{B} being float -numbers from 0.0 to 1.0) or by a color description specified in the "Color" -section in the ffmpeg-utils manual), a position (specified by the syntax @var{X}/@var{Y}, -@var{X} and @var{Y} being float numbers) and a string. +A frei0r effect parameter can be a boolean (its value is either +"y" or "n"), a double, a color (specified as +@var{R}/@var{G}/@var{B}, where @var{R}, @var{G}, and @var{B} are floating point +numbers between 0.0 and 1.0, inclusive) or by a color description specified in the "Color" +section in the ffmpeg-utils manual), a position (specified as @var{X}/@var{Y}, where +@var{X} and @var{Y} are floating point numbers) and/or a string. -The number and kind of parameters depend on the loaded effect. If an -effect parameter is not specified the default value is set. +The number and types of parameters depend on the loaded effect. If an +effect parameter is not specified, the default value is set. @subsection Examples @itemize @item -Apply the distort0r effect, set the first two double parameters: +Apply the distort0r effect, setting the first two double parameters: @example frei0r=filter_name=distort0r:filter_params=0.5|0.01 @end example @item -Apply the colordistance effect, take a color as first parameter: +Apply the colordistance effect, taking a color as the first parameter: @example frei0r=colordistance:0.2/0.3/0.4 frei0r=colordistance:violet @@ -4665,14 +4805,14 @@ frei0r=colordistance:0x112233 @end example @item -Apply the perspective effect, specify the top left and top right image +Apply the perspective effect, specifying the top left and top right image positions: @example frei0r=perspective:0.2/0.2|0.8/0.2 @end example @end itemize -For more information see: +For more information, see @url{http://frei0r.dyne.org} @section geq @@ -4804,25 +4944,25 @@ regions by truncation to 8bit color depth. Interpolate the gradients that should go where the bands are, and dither them. -This filter is designed for playback only. Do not use it prior to +It is designed for playback only. Do not use it prior to lossy compression, because compression tends to lose the dither and bring back the bands. -This filter accepts the following options: +It accepts the following parameters: @table @option @item strength -The maximum amount by which the filter will change any one pixel. Also the -threshold for detecting nearly flat regions. Acceptable values range from .51 to -64, default value is 1.2, out-of-range values will be clipped to the valid -range. +The maximum amount by which the filter will change any one pixel. This is also +the threshold for detecting nearly flat regions. Acceptable values range from +.51 to 64; the default value is 1.2. Out-of-range values will be clipped to the +valid range. @item radius The neighborhood to fit the gradient to. A larger radius makes for smoother gradients, but also prevents the filter from modifying the pixels near detailed -regions. Acceptable values are 8-32, default value is 16, out-of-range values -will be clipped to the valid range. +regions. Acceptable values are 8-32; the default value is 16. Out-of-range +values will be clipped to the valid range. @end table @@ -4924,7 +5064,7 @@ ffplay input.mkv -vf "movie=clut.png, [in] haldclut" Flip the input video horizontally. -For example to horizontally flip the input video with @command{ffmpeg}: +For example, to horizontally flip the input video with @command{ffmpeg}: @example ffmpeg -i in.avi -vf "hflip" out.avi @end example @@ -5086,35 +5226,49 @@ ffplay -i input -vf histogram @anchor{hqdn3d} @section hqdn3d -High precision/quality 3d denoise filter. This filter aims to reduce -image noise producing smooth images and making still images really +This is a high precision/quality 3d denoise filter. It aims to reduce +image noise, producing smooth images and making still images really still. It should enhance compressibility. It accepts the following optional parameters: @table @option @item luma_spatial -a non-negative float number which specifies spatial luma strength, -defaults to 4.0 +A non-negative floating point number which specifies spatial luma strength. +It defaults to 4.0. @item chroma_spatial -a non-negative float number which specifies spatial chroma strength, -defaults to 3.0*@var{luma_spatial}/4.0 +A non-negative floating point number which specifies spatial chroma strength. +It defaults to 3.0*@var{luma_spatial}/4.0. @item luma_tmp -a float number which specifies luma temporal strength, defaults to -6.0*@var{luma_spatial}/4.0 +A floating point number which specifies luma temporal strength. It defaults to +6.0*@var{luma_spatial}/4.0. @item chroma_tmp -a float number which specifies chroma temporal strength, defaults to -@var{luma_tmp}*@var{chroma_spatial}/@var{luma_spatial} +A floating point number which specifies chroma temporal strength. It defaults to +@var{luma_tmp}*@var{chroma_spatial}/@var{luma_spatial}. +@end table + +@section hqx + +Apply a high-quality magnification filter designed for pixel art. This filter +was originally created by Maxim Stepin. + +It accepts the following option: + +@table @option +@item n +Set the scaling dimension: @code{2} for @code{hq2x}, @code{3} for +@code{hq3x} and @code{4} for @code{hq4x}. +Default is @code{3}. @end table @section hue Modify the hue and/or the saturation of the input. -This filter accepts the following options: +It accepts the following parameters: @table @option @item h @@ -5294,8 +5448,8 @@ It accepts the following optional parameters: @table @option @item scan -determines whether the interlaced frame is taken from the even (tff - default) -or odd (bff) lines of the progressive frame. +This determines whether the interlaced frame is taken from the even +(tff - default) or odd (bff) lines of the progressive frame. @end table @section kerndeint @@ -5390,12 +5544,12 @@ Interpolate values using a tetrahedron. @section lut, lutrgb, lutyuv Compute a look-up table for binding each pixel component input value -to an output value, and apply it to input video. +to an output value, and apply it to the input video. @var{lutyuv} applies a lookup table to a YUV input video, @var{lutrgb} to an RGB input video. -These filters accept the following options: +These filters accept the following parameters: @table @option @item c0 set first pixel component expression @@ -5437,32 +5591,32 @@ The expressions can contain the following constants and functions: @table @option @item w @item h -the input width and height +The input width and height. @item val -input value for the pixel component +The input value for the pixel component. @item clipval -the input value clipped in the @var{minval}-@var{maxval} range +The input value, clipped to the @var{minval}-@var{maxval} range. @item maxval -maximum value for the pixel component +The maximum value for the pixel component. @item minval -minimum value for the pixel component +The minimum value for the pixel component. @item negval -the negated value for the pixel component value clipped in the -@var{minval}-@var{maxval} range , it corresponds to the expression -"maxval-clipval+minval" +The negated value for the pixel component value, clipped to the +@var{minval}-@var{maxval} range; it corresponds to the expression +"maxval-clipval+minval". @item clip(val) -the computed value in @var{val} clipped in the -@var{minval}-@var{maxval} range +The computed value in @var{val}, clipped to the +@var{minval}-@var{maxval} range. @item gammaval(gamma) -the computed gamma correction value of the pixel component value -clipped in the @var{minval}-@var{maxval} range, corresponds to the +The computed gamma correction value of the pixel component value, +clipped to the @var{minval}-@var{maxval} range. It corresponds to the expression "pow((clipval-minval)/(maxval-minval)\,@var{gamma})*(maxval-minval)+minval" @@ -5493,7 +5647,7 @@ lutyuv=y=negval @end example @item -Remove chroma components, turns the video into a graytone image: +Remove chroma components, turning the video into a graytone image: @example lutyuv="u=128:v=128" @end example @@ -5517,7 +5671,7 @@ format=rgba,lutrgb=a="maxval-minval/2" @end example @item -Correct luminance gamma by a 0.5 factor: +Correct luminance gamma by a factor of 0.5: @example lutyuv=y=gammaval(0.5) @end example @@ -5721,7 +5875,7 @@ Default value for @option{hi} is 64*12, default value for @option{lo} is Negate input video. -This filter accepts an integer in input, if non-zero it negates the +It accepts an integer in input; if non-zero it negates the alpha component (if available). The default value in input is 0. @section noformat @@ -5729,12 +5883,12 @@ alpha component (if available). The default value in input is 0. Force libavfilter not to use any of the specified pixel formats for the input to the next filter. -This filter accepts the following parameters: +It accepts the following parameters: @table @option @item pix_fmts -A '|'-separated list of pixel format names, for example -"pix_fmts=yuv420p|monow|rgb24". +A '|'-separated list of pixel format names, such as +apix_fmts=yuv420p|monow|rgb24". @end table @@ -5810,12 +5964,12 @@ Pass the video source unchanged to the output. @section ocv -Apply video transform using libopencv. +Apply a video transform using libopencv. -To enable this filter install libopencv library and headers and +To enable this filter, install the libopencv library and headers and configure FFmpeg with @code{--enable-libopencv}. -This filter accepts the following parameters: +It accepts the following parameters: @table @option @@ -5823,7 +5977,7 @@ This filter accepts the following parameters: The name of the libopencv filter to apply. @item filter_params -The parameters to pass to the libopencv filter. If not specified the default +The parameters to pass to the libopencv filter. If not specified, the default values are assumed. @end table @@ -5832,13 +5986,13 @@ Refer to the official libopencv documentation for more precise information: @url{http://opencv.willowgarage.com/documentation/c/image_filtering.html} -Follows the list of supported libopencv filters. +Several libopencv filters are supported; see the following subsections. @anchor{dilate} @subsection dilate Dilate an image by using a specific structuring element. -This filter corresponds to the libopencv function @code{cvDilate}. +It corresponds to the libopencv function @code{cvDilate}. It accepts the parameters: @var{struct_el}|@var{nb_iterations}. @@ -5847,8 +6001,8 @@ It accepts the parameters: @var{struct_el}|@var{nb_iterations}. @var{cols} and @var{rows} represent the number of columns and rows of the structuring element, @var{anchor_x} and @var{anchor_y} the anchor -point, and @var{shape} the shape for the structuring element, and -can be one of the values "rect", "cross", "ellipse", "custom". +point, and @var{shape} the shape for the structuring element. @var{shape} +must be "rect", "cross", "ellipse", or "custom". If the value for @var{shape} is "custom", it must be followed by a string of the form "=@var{filename}". The file with name @@ -5862,31 +6016,32 @@ The default value for @var{struct_el} is "3x3+0x0/rect". @var{nb_iterations} specifies the number of times the transform is applied to the image, and defaults to 1. -Follow some example: +Some examples: @example -# use the default values +# Use the default values ocv=dilate -# dilate using a structuring element with a 5x5 cross, iterate two times +# Dilate using a structuring element with a 5x5 cross, iterating two times ocv=filter_name=dilate:filter_params=5x5+2x2/cross|2 -# read the shape from the file diamond.shape, iterate two times -# the file diamond.shape may contain a pattern of characters like this: +# Read the shape from the file diamond.shape, iterating two times. +# The file diamond.shape may contain a pattern of characters like this # * # *** # ***** # *** # * -# the specified cols and rows are ignored (but not the anchor point coordinates) +# The specified columns and rows are ignored +# but the anchor point coordinates are not ocv=dilate:0x0+2x2/custom=diamond.shape|2 @end example @subsection erode Erode an image by using a specific structuring element. -This filter corresponds to the libopencv function @code{cvErode}. +It corresponds to the libopencv function @code{cvErode}. -The filter accepts the parameters: @var{struct_el}:@var{nb_iterations}, +It accepts the parameters: @var{struct_el}:@var{nb_iterations}, with the same syntax and semantics as the @ref{dilate} filter. @subsection smooth @@ -5896,16 +6051,16 @@ Smooth the input video. The filter takes the following parameters: @var{type}|@var{param1}|@var{param2}|@var{param3}|@var{param4}. -@var{type} is the type of smooth filter to apply, and can be one of +@var{type} is the type of smooth filter to apply, and must be one of the following values: "blur", "blur_no_scale", "median", "gaussian", -"bilateral". The default value is "gaussian". +or "bilateral". The default value is "gaussian". -@var{param1}, @var{param2}, @var{param3}, and @var{param4} are -parameters whose meanings depend on smooth type. @var{param1} and -@var{param2} accept integer positive values or 0, @var{param3} and -@var{param4} accept float values. +The meaning of @var{param1}, @var{param2}, @var{param3}, and @var{param4} +depend on the smooth type. @var{param1} and +@var{param2} accept integer positive values or 0. @var{param3} and +@var{param4} accept floating point values. -The default value for @var{param1} is 3, the default value for the +The default value for @var{param1} is 3. The default value for the other parameters is 0. These parameters correspond to the parameters assigned to the @@ -5916,10 +6071,10 @@ libopencv function @code{cvSmooth}. Overlay one video on top of another. -It takes two inputs and one output, the first input is the "main" +It takes two inputs and has one output. The first input is the "main" video on which the second input is overlayed. -This filter accepts the following parameters: +It accepts the following parameters: A description of the accepted options follows. @@ -5932,16 +6087,16 @@ the expression is invalid, it is set to a huge value (meaning that the overlay will not be displayed within the output visible area). @item eof_action -The action to take when EOF is encountered on the secondary input, accepts one -of the following values: +The action to take when EOF is encountered on the secondary input; it accepts +one of the following values: @table @option @item repeat -repeat the last frame (the default) +Repeat the last frame (the default). @item endall -end both streams +End both streams. @item pass -pass through the main input +Pass the main input through. @end table @item eval @@ -6000,15 +6155,15 @@ parameters. @table @option @item main_w, W @item main_h, H -main input width and height +The main input width and height. @item overlay_w, w @item overlay_h, h -overlay input width and height +The overlay input width and height. @item x @item y -the computed values for @var{x} and @var{y}. They are evaluated for +The computed values for @var{x} and @var{y}. They are evaluated for each new frame. @item hsub @@ -6024,7 +6179,7 @@ the number of input frame, starting from 0 the position in the file of the input frame, NAN if unknown @item t -timestamp expressed in seconds, NAN if the input timestamp is unknown +The timestamp, expressed in seconds. It's NAN if the input timestamp is unknown. @end table @@ -6035,8 +6190,8 @@ when @option{eval} is set to @samp{init}. Be aware that frames are taken from each input video in timestamp order, hence, if their initial timestamps differ, it is a good idea to pass the two inputs through a @var{setpts=PTS-STARTPTS} filter to -have them begin in the same zero timestamp, as it does the example for -the @var{movie} filter. +have them begin in the same zero timestamp, as the example for +the @var{movie} filter does. You can chain together more overlays but you should test the efficiency of such approach. @@ -6084,7 +6239,7 @@ ffmpeg -i input -i logo1 -i logo2 -filter_complex 'overlay=x=10:y=H-h-10,overlay @end example @item -Add a transparent color layer on top of the main video, @code{WxH} +Add a transparent color layer on top of the main video; @code{WxH} must specify the size of the main input to the overlay filter: @example color=color=red@@.3:size=WxH [over]; [in][over] overlay [out] @@ -6122,7 +6277,7 @@ nullsrc=size=200x100 [background]; @end example @item -mask 10-20 seconds of a video by applying the delogo filter to a section +Mask 10-20 seconds of a video by applying the delogo filter to a section @example ffmpeg -i test.avi -codec:v:0 wmv2 -ar 11025 -b:v 9000k -vf '[in]split[split_main][split_delogo];[split_delogo]trim=start=360:end=371,delogo=0:0:640:480[delogoed];[split_main][delogoed]overlay=eof_action=pass[out]' @@ -6171,9 +6326,9 @@ Must be a double value in the range 0-1000, default is @code{1.0}. @section pad Add paddings to the input image, and place the original input at the -given coordinates @var{x}, @var{y}. +provided @var{x}, @var{y} coordinates. -This filter accepts the following parameters: +It accepts the following parameters: @table @option @item width, w @@ -6189,9 +6344,8 @@ The default value of @var{width} and @var{height} is 0. @item x @item y -Specify an expression for the offsets where to place the input image -in the padded area with respect to the top/left border of the output -image. +Specify the offsets to place the input image at within the padded area, +with respect to the top/left border of the output image. The @var{x} expression can reference the value set by the @var{y} expression, and vice versa. @@ -6211,25 +6365,25 @@ options are expressions containing the following constants: @table @option @item in_w @item in_h -the input video width and height +The input video width and height. @item iw @item ih -same as @var{in_w} and @var{in_h} +These are the same as @var{in_w} and @var{in_h}. @item out_w @item out_h -the output width and height, that is the size of the padded area as -specified by the @var{width} and @var{height} expressions +The output width and height (the size of the padded area), as +specified by the @var{width} and @var{height} expressions. @item ow @item oh -same as @var{out_w} and @var{out_h} +These are the same as @var{out_w} and @var{out_h}. @item x @item y -x and y offsets as specified by the @var{x} and @var{y} -expressions, or NAN if not yet specified +The x and y offsets as specified by the @var{x} and @var{y} +expressions, or NAN if not yet specified. @item a same as @var{iw} / @var{ih} @@ -6242,7 +6396,7 @@ input display aspect ratio, it is the same as (@var{iw} / @var{ih}) * @var{sar} @item hsub @item vsub -horizontal and vertical chroma subsample values. For example for the +The horizontal and vertical chroma subsample values. For example for the pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1. @end table @@ -6250,9 +6404,9 @@ pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1. @itemize @item -Add paddings with color "violet" to the input video. Output video -size is 640x480, the top-left corner of the input video is placed at -column 0, row 40: +Add paddings with the color "violet" to the input video. The output video +size is 640x480, and the top-left corner of the input video is placed at +column 0, row 40 @example pad=640:480:0:40:violet @end example @@ -6298,7 +6452,7 @@ pad="ih*16/9/sar:ih:(ow-iw)/2:(oh-ih)/2" @end example @item -Double output size and put the input video in the bottom-right +Double the output size and put the input video in the bottom-right corner of the output padded area: @example pad="2*iw:2*ih:ow-iw:oh-ih" @@ -7086,28 +7240,28 @@ containing the following constants: @table @var @item in_w @item in_h -the input width and height +The input width and height @item iw @item ih -same as @var{in_w} and @var{in_h} +These are the same as @var{in_w} and @var{in_h}. @item out_w @item out_h -the output (scaled) width and height +The output (scaled) width and height @item ow @item oh -same as @var{out_w} and @var{out_h} +These are the same as @var{out_w} and @var{out_h} @item a -same as @var{iw} / @var{ih} +The same as @var{iw} / @var{ih} @item sar input sample aspect ratio @item dar -input display aspect ratio. Calculated from @code{(iw / ih) * sar}. +The input display aspect ratio. Calculated from @code{(iw / ih) * sar}. @item hsub @item vsub @@ -7124,7 +7278,7 @@ pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1. @itemize @item -Scale the input video to a size of 200x100: +Scale the input video to a size of 200x100 @example scale=w=200:h=100 @end example @@ -7181,7 +7335,7 @@ scale=3/2*iw:ow @end example @item -Seek for Greek harmony: +Seek Greek harmony: @example scale=iw:1/PHI*iw scale=ih*PHI:ih @@ -7194,15 +7348,15 @@ scale=w=3/2*oh:h=3/5*ih @end example @item -Increase the size, but make the size a multiple of the chroma +Increase the size, making the size a multiple of the chroma subsample values: @example scale="trunc(3/2*iw/hsub)*hsub:trunc(3/2*ih/vsub)*vsub" @end example @item -Increase the width to a maximum of 500 pixels, keep the same input -aspect ratio: +Increase the width to a maximum of 500 pixels, +keeping the same aspect ratio as the input: @example scale=w='min(500\, iw*3/2):h=-1' @end example @@ -7230,7 +7384,7 @@ Ratio, according to the following equation: @end example Keep in mind that the @code{setdar} filter does not modify the pixel -dimensions of the video frame. Also the display aspect ratio set by +dimensions of the video frame. Also, the display aspect ratio set by this filter may be changed by later filters in the filterchain, e.g. in case of scaling or if another "setdar" or a "setsar" filter is applied. @@ -7246,7 +7400,7 @@ Keep in mind that the sample aspect ratio set by the @code{setsar} filter may be changed by later filters in the filterchain, e.g. if another "setsar" or a "setdar" filter is applied. -The filters accept the following options: +It accepts the following parameters: @table @option @item r, ratio, dar (@code{setdar} only), sar (@code{setsar} only) @@ -7271,23 +7425,24 @@ the following constants: @table @option @item E, PI, PHI -the corresponding mathematical approximated values for e -(euler number), pi (greek PI), phi (golden ratio) +These are approximated values for the mathematical constants e +(Euler's number), pi (Greek pi), and phi (the golden ratio). @item w, h -the input width and height +The input width and height. @item a -same as @var{w} / @var{h} +These are the same as @var{w} / @var{h}. @item sar -input sample aspect ratio +The input sample aspect ratio. @item dar -input display aspect ratio, it is the same as (@var{w} / @var{h}) * @var{sar} +The input display aspect ratio. It is the same as +(@var{w} / @var{h}) * @var{sar}. @item hsub, vsub -horizontal and vertical chroma subsample values. For example for the +Horizontal and vertical chroma subsample values. For example, for the pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1. @end table @@ -7358,63 +7513,274 @@ The input video is not modified. The shown line contains a sequence of key/value pairs of the form @var{key}:@var{value}. -A description of each shown parameter follows: +It accepts the following parameters: @table @option @item n -sequential number of the input frame, starting from 0 +The (sequential) number of the input frame, starting from 0. @item pts -Presentation TimeStamp of the input frame, expressed as a number of +The Presentation TimeStamp of the input frame, expressed as a number of time base units. The time base unit depends on the filter input pad. @item pts_time -Presentation TimeStamp of the input frame, expressed as a number of -seconds +The Presentation TimeStamp of the input frame, expressed as a number of +seconds. @item pos -position of the frame in the input stream, -1 if this information in -unavailable and/or meaningless (for example in case of synthetic video) +The position of the frame in the input stream, or -1 if this information is +unavailable and/or meaningless (for example in case of synthetic video). @item fmt -pixel format name +The pixel format name. @item sar -sample aspect ratio of the input frame, expressed in the form -@var{num}/@var{den} +The sample aspect ratio of the input frame, expressed in the form +@var{num}/@var{den}. @item s -size of the input frame. For the syntax of this option, check the "Video size" +The size of the input frame. For the syntax of this option, check the "Video size" section in the ffmpeg-utils manual. @item i -interlaced mode ("P" for "progressive", "T" for top field first, "B" -for bottom field first) +The type of interlaced mode ("P" for "progressive", "T" for top field first, "B" +for bottom field first). @item iskey -1 if the frame is a key frame, 0 otherwise +This is 1 if the frame is a key frame, 0 otherwise. @item type -picture type of the input frame ("I" for an I-frame, "P" for a -P-frame, "B" for a B-frame, "?" for unknown type). -Check also the documentation of the @code{AVPictureType} enum and of +The picture type of the input frame ("I" for an I-frame, "P" for a +P-frame, "B" for a B-frame, or "?" for an unknown type). +Also refer to the documentation of the @code{AVPictureType} enum and of the @code{av_get_picture_type_char} function defined in @file{libavutil/avutil.h}. @item checksum -Adler-32 checksum (printed in hexadecimal) of all the planes of the input frame +The Adler-32 checksum (printed in hexadecimal) of all the planes of the input frame. @item plane_checksum -Adler-32 checksum (printed in hexadecimal) of each plane of the input frame, -expressed in the form "[@var{c0} @var{c1} @var{c2} @var{c3}]" +The Adler-32 checksum (printed in hexadecimal) of each plane of the input frame, +expressed in the form "[@var{c0} @var{c1} @var{c2} @var{c3}]". @end table +@section shuffleplanes + +Reorder and/or duplicate video planes. + +It accepts the following parameters: + +@table @option + +@item map0 +The index of the input plane to be used as the first output plane. + +@item map1 +The index of the input plane to be used as the second output plane. + +@item map2 +The index of the input plane to be used as the third output plane. + +@item map3 +The index of the input plane to be used as the fourth output plane. + +@end table + +The first plane has the index 0. The default is to keep the input unchanged. + +Swap the second and third planes of the input: +@example +ffmpeg -i INPUT -vf shuffleplanes=0:2:1:3 OUTPUT +@end example + +@section signalstats +Evaluate various visual metrics that assist in determining issues associated +with the digitization of analog video media. + +By default the filter will log these metadata values: + +@table @option +@item YMIN +Display the minimal Y value contained within the input frame. Expressed in +range of [0-255]. + +@item YLOW +Display the Y value at the 10% percentile within the input frame. Expressed in +range of [0-255]. + +@item YAVG +Display the average Y value within the input frame. Expressed in range of +[0-255]. + +@item YHIGH +Display the Y value at the 90% percentile within the input frame. Expressed in +range of [0-255]. + +@item YMAX +Display the maximum Y value contained within the input frame. Expressed in +range of [0-255]. + +@item UMIN +Display the minimal U value contained within the input frame. Expressed in +range of [0-255]. + +@item ULOW +Display the U value at the 10% percentile within the input frame. Expressed in +range of [0-255]. + +@item UAVG +Display the average U value within the input frame. Expressed in range of +[0-255]. + +@item UHIGH +Display the U value at the 90% percentile within the input frame. Expressed in +range of [0-255]. + +@item UMAX +Display the maximum U value contained within the input frame. Expressed in +range of [0-255]. + +@item VMIN +Display the minimal V value contained within the input frame. Expressed in +range of [0-255]. + +@item VLOW +Display the V value at the 10% percentile within the input frame. Expressed in +range of [0-255]. + +@item VAVG +Display the average V value within the input frame. Expressed in range of +[0-255]. + +@item VHIGH +Display the V value at the 90% percentile within the input frame. Expressed in +range of [0-255]. + +@item VMAX +Display the maximum V value contained within the input frame. Expressed in +range of [0-255]. + +@item SATMIN +Display the minimal saturation value contained within the input frame. +Expressed in range of [0-~181.02]. + +@item SATLOW +Display the saturation value at the 10% percentile within the input frame. +Expressed in range of [0-~181.02]. + +@item SATAVG +Display the average saturation value within the input frame. Expressed in range +of [0-~181.02]. + +@item SATHIGH +Display the saturation value at the 90% percentile within the input frame. +Expressed in range of [0-~181.02]. + +@item SATMAX +Display the maximum saturation value contained within the input frame. +Expressed in range of [0-~181.02]. + +@item HUEMED +Display the median value for hue within the input frame. Expressed in range of +[0-360]. + +@item HUEAVG +Display the average value for hue within the input frame. Expressed in range of +[0-360]. + +@item YDIF +Display the average of sample value difference between all values of the Y +plane in the current frame and corresponding values of the previous input frame. +Expressed in range of [0-255]. + +@item UDIF +Display the average of sample value difference between all values of the U +plane in the current frame and corresponding values of the previous input frame. +Expressed in range of [0-255]. + +@item VDIF +Display the average of sample value difference between all values of the V +plane in the current frame and corresponding values of the previous input frame. +Expressed in range of [0-255]. +@end table + +The filter accepts the following options: + +@table @option +@item stat +@item out + +@option{stat} specify an additional form of image analysis. +@option{out} output video with the specified type of pixel highlighted. + +Both options accept the following values: + +@table @samp +@item tout +Identify @var{temporal outliers} pixels. A @var{temporal outlier} is a pixel +unlike the neighboring pixels of the same field. Examples of temporal outliers +include the results of video dropouts, head clogs, or tape tracking issues. + +@item vrep +Identify @var{vertical line repetition}. Vertical line repetition includes +similar rows of pixels within a frame. In born-digital video vertical line +repetition is common, but this pattern is uncommon in video digitized from an +analog source. When it occurs in video that results from the digitization of an +analog source it can indicate concealment from a dropout compensator. + +@item brng +Identify pixels that fall outside of legal broadcast range. +@end table + +@item color, c +Set the highlight color for the @option{out} option. The default color is +yellow. +@end table + +@subsection Examples + +@itemize +@item +Output data of various video metrics: +@example +ffprobe -f lavfi movie=example.mov,signalstats="stat=tout+vrep+brng" -show_frames +@end example + +@item +Output specific data about the minimum and maximum values of the Y plane per frame: +@example +ffprobe -f lavfi movie=example.mov,signalstats -show_entries frame_tags=lavfi.signalstats.YMAX,lavfi.signalstats.YMIN +@end example + +@item +Playback video while highlighting pixels that are outside of broadcast range in red. +@example +ffplay example.mov -vf signalstats="out=brng:color=red" +@end example + +@item +Playback video with signalstats metadata drawn over the frame. +@example +ffplay example.mov -vf signalstats=stat=brng+vrep+tout,drawtext=fontfile=FreeSerif.ttf:textfile=signalstat_drawtext.txt +@end example + +The contents of signalstat_drawtext.txt used in the command are: +@example +time %@{pts:hms@} +Y (%@{metadata:lavfi.signalstats.YMIN@}-%@{metadata:lavfi.signalstats.YMAX@}) +U (%@{metadata:lavfi.signalstats.UMIN@}-%@{metadata:lavfi.signalstats.UMAX@}) +V (%@{metadata:lavfi.signalstats.VMIN@}-%@{metadata:lavfi.signalstats.VMAX@}) +saturation maximum: %@{metadata:lavfi.signalstats.SATMAX@} + +@end example +@end itemize + @anchor{smartblur} @section smartblur Blur the input video without impacting the outlines. -The filter accepts the following options: +It accepts the following options: @table @option @item luma_radius, lr @@ -7661,6 +8027,9 @@ changed. @item charenc Set subtitles input character encoding. @code{subtitles} filter only. Only useful if not UTF-8. + +@item stream_index, si +Set subtitles stream index. @code{subtitles} filter only. @end table If the first key is not specified, it is assumed that the first value @@ -7677,6 +8046,16 @@ which is equivalent to: subtitles=filename=sub.srt @end example +To render the default subtitles stream from file @file{video.mkv}, use: +@example +subtitles=video.mkv +@end example + +To render the second subtitles stream from that file, use: +@example +subtitles=video.mkv:si=1 +@end example + @section super2xsai Scale the input by 2x and smooth using the Super2xSaI (Scale and @@ -7887,7 +8266,7 @@ Vertical low-pass filtering can only be enabled for @option{mode} Transpose rows with columns in the input video and optionally flip it. -This filter accepts the following options: +It accepts the following parameters: @table @option @@ -7965,33 +8344,33 @@ transpose=1:portrait @section trim Trim the input so that the output contains one continuous subpart of the input. -This filter accepts the following options: +It accepts the following parameters: @table @option @item start -Specify time of the start of the kept section, i.e. the frame with the +Specify the time of the start of the kept section, i.e. the frame with the timestamp @var{start} will be the first frame in the output. @item end -Specify time of the first frame that will be dropped, i.e. the frame +Specify the time of the first frame that will be dropped, i.e. the frame immediately preceding the one with the timestamp @var{end} will be the last frame in the output. @item start_pts -Same as @var{start}, except this option sets the start timestamp in timebase -units instead of seconds. +This is the same as @var{start}, except this option sets the start timestamp +in timebase units instead of seconds. @item end_pts -Same as @var{end}, except this option sets the end timestamp in timebase units -instead of seconds. +This is the same as @var{end}, except this option sets the end timestamp +in timebase units instead of seconds. @item duration -Specify maximum duration of the output. +The maximum duration of the output in seconds. @item start_frame -Number of the first frame that should be passed to output. +The number of the first frame that should be passed to the output. @item end_frame -Number of the first frame that should be dropped. +The number of the first frame that should be dropped. @end table @option{start}, @option{end}, @option{duration} are expressed as time @@ -8001,7 +8380,7 @@ ffmpeg-utils manual. Note that the first two sets of the start/end options and the @option{duration} option look at the frame timestamp, while the _frame variants simply count the frames that pass through the filter. Also note that this filter does not modify -the timestamps. If you wish that the output timestamps start at zero, insert a +the timestamps. If you wish for the output timestamps to start at zero, insert a setpts filter after the trim filter. If multiple start or end options are set, this filter tries to be greedy and @@ -8015,13 +8394,13 @@ just the end values to keep everything before the specified time. Examples: @itemize @item -drop everything except the second minute of input +Drop everything except the second minute of input: @example ffmpeg -i INPUT -vf trim=60:120 @end example @item -keep only the first second +Keep only the first second: @example ffmpeg -i INPUT -vf trim=duration=1 @end example @@ -8038,14 +8417,14 @@ It accepts the following parameters: @table @option @item luma_msize_x, lx Set the luma matrix horizontal size. It must be an odd integer between -3 and 63, default value is 5. +3 and 63. The default value is 5. @item luma_msize_y, ly Set the luma matrix vertical size. It must be an odd integer between 3 -and 63, default value is 5. +and 63. The default value is 5. @item luma_amount, la -Set the luma effect strength. It can be a float number, reasonable +Set the luma effect strength. It must be a floating point number, reasonable values lay between -1.5 and 1.5. Negative values will blur the input video, while positive values will @@ -8055,14 +8434,14 @@ Default value is 1.0. @item chroma_msize_x, cx Set the chroma matrix horizontal size. It must be an odd integer -between 3 and 63, default value is 5. +between 3 and 63. The default value is 5. @item chroma_msize_y, cy Set the chroma matrix vertical size. It must be an odd integer -between 3 and 63, default value is 5. +between 3 and 63. The default value is 5. @item chroma_amount, ca -Set the chroma effect strength. It can be a float number, reasonable +Set the chroma effect strength. It must be a floating point number, reasonable values lay between -1.5 and 1.5. Negative values will blur the input video, while positive values will @@ -8089,7 +8468,7 @@ unsharp=luma_msize_x=7:luma_msize_y=7:luma_amount=2.5 @end example @item -Apply strong blur of both luma and chroma parameters: +Apply a strong blur of both luma and chroma parameters: @example unsharp=7:7:-2:7:7:-2 @end example @@ -8492,42 +8871,42 @@ Default value is @samp{all}. Deinterlace the input video ("yadif" means "yet another deinterlacing filter"). -This filter accepts the following options: +It accepts the following parameters: @table @option @item mode -The interlacing mode to adopt, accepts one of the following values: +The interlacing mode to adopt. It accepts one of the following values: @table @option @item 0, send_frame -output 1 frame for each frame +Output one frame for each frame. @item 1, send_field -output 1 frame for each field +Output one frame for each field. @item 2, send_frame_nospatial -like @code{send_frame} but skip spatial interlacing check +Like @code{send_frame}, but it skips the spatial interlacing check. @item 3, send_field_nospatial -like @code{send_field} but skip spatial interlacing check +Like @code{send_field}, but it skips the spatial interlacing check. @end table -Default value is @code{send_frame}. +The default value is @code{send_frame}. @item parity -The picture field parity assumed for the input interlaced video, accepts one of -the following values: +The picture field parity assumed for the input interlaced video. It accepts one +of the following values: @table @option @item 0, tff -assume top field first +Assume the top field is first. @item 1, bff -assume bottom field first +Assume the bottom field is first. @item -1, auto -enable automatic detection +Enable automatic detection of field parity. @end table -Default value is @code{auto}. -If interlacing is unknown or decoder does not export this information, +The default value is @code{auto}. +If the interlacing is unknown or the decoder does not export this information, top field first will be assumed. @item deint @@ -8536,14 +8915,102 @@ values: @table @option @item 0, all -deinterlace all frames +Deinterlace all frames. @item 1, interlaced -only deinterlace frames marked as interlaced +Only deinterlace frames marked as interlaced. @end table -Default value is @code{all}. +The default value is @code{all}. @end table +@section zoompan + +Apply Zoom & Pan effect. + +This filter accepts the following options: + +@table @option +@item zoom, z +Set the zoom expression. Default is 1. + +@item x +@item y +Set the x and y expression. Default is 0. + +@item d +Set the duration expression in number of frames. +This sets for how many number of frames effect will last for +single input image. + +@item s +Set the output image size, default is 'hd720'. +@end table + +Each expression can contain the following constants: + +@table @option +@item in_w, iw +Input width. + +@item in_h, ih +Input height. + +@item out_w, ow +Output width. + +@item out_h, oh +Output height. + +@item in +Input frame count. + +@item on +Output frame count. + +@item x +@item y +Last calculated 'x' and 'y' position from 'x' and 'y' expression +for current input frame. + +@item px +@item py +'x' and 'y' of last output frame of previous input frame or 0 when there was +not yet such frame (first input frame). + +@item zoom +Last calculated zoom from 'z' expression for current input frame. + +@item pzoom +Last calculated zoom of last output frame of previous input frame. + +@item duration +Number of output frames for current input frame. Calculated from 'd' expression +for each input frame. + +@item pduration +number of output frames created for previous input frame + +@item a +Rational number: input width / input height + +@item sar +sample aspect ratio + +@item dar +display aspect ratio + +@end table + +@subsection Examples + +@itemize +@item +Zoom-in up to 1.5 and pan at same time to some spot near center of picture: +@example +zoompan=z='min(zoom+0.0015,1.5)':d=700:x='if(gte(zoom,1.5),x,x+1/a)':y='if(gte(zoom,1.5),y,y+1)':s=640x360 +@end example +@end itemize + @c man end VIDEO FILTERS @chapter Video Sources @@ -8558,7 +9025,7 @@ Buffer video frames, and make them available to the filter chain. This source is mainly intended for a programmatic use, in particular through the interface defined in @file{libavfilter/vsrc_buffer.h}. -This source accepts the following options: +It accepts the following parameters: @table @option @@ -8568,10 +9035,10 @@ syntax of this option, check the "Video size" section in the ffmpeg-utils manual. @item width -Input video width. +The input video width. @item height -Input video height. +The input video height. @item pix_fmt A string representing the pixel format of the buffered video frames. @@ -8585,7 +9052,7 @@ Specify the timebase assumed by the timestamps of the buffered frames. Specify the frame rate expected for the video stream. @item pixel_aspect, sar -Specify the sample aspect ratio assumed by the video frames. +The sample (pixel) aspect ratio of the input video. @item sws_param Specify the optional parameters to be used for the scale filter which @@ -8813,7 +9280,7 @@ This source accepts the following options: @item rate, r Specify the frame rate of the sourced video, as the number of frames generated per second. It has to be a string in the format -@var{frame_rate_num}/@var{frame_rate_den}, an integer number, a float +@var{frame_rate_num}/@var{frame_rate_den}, an integer number, a floating point number or a valid video frame rate abbreviation. The default value is "25". @@ -8843,12 +9310,13 @@ Set the number or the name of the test to perform. Supported tests are: @item ring1 @item ring2 @item all + @end table Default value is "all", which will cycle through the list of all tests. @end table -For example the following: +Some examples: @example testsrc=t=dc_luma @end example @@ -8862,7 +9330,7 @@ Provide a frei0r source. To enable compilation of this filter you need to install the frei0r header and configure FFmpeg with @code{--enable-frei0r}. -This source accepts the following options: +This source accepts the following parameters: @table @option @@ -8871,13 +9339,13 @@ The size of the video to generate. For the syntax of this option, check the "Video size" section in the ffmpeg-utils manual. @item framerate -Framerate of the generated video, may be a string of the form +The framerate of the generated video. It may be a string of the form @var{num}/@var{den} or a frame rate abbreviation. @item filter_name The name to the frei0r source to load. For more information regarding frei0r and -how to set the parameters read the section @ref{frei0r} in the description of -the video filters. +how to set the parameters, read the @ref{frei0r} section in the video filters +documentation. @item filter_params A '|'-separated list of parameters to pass to the frei0r source. @@ -9051,7 +9519,7 @@ The @code{testsrc} source generates a test video pattern, showing a color pattern, a scrolling gradient and a timestamp. This is mainly intended for testing purposes. -The sources accept the following options: +The sources accept the following parameters: @table @option @@ -9076,7 +9544,7 @@ This option is not available with the @code{haldclutsrc} filter. @item rate, r Specify the frame rate of the sourced video, as the number of frames generated per second. It has to be a string in the format -@var{frame_rate_num}/@var{frame_rate_den}, an integer number, a float +@var{frame_rate_num}/@var{frame_rate_den}, an integer number, a floating point number or a valid video frame rate abbreviation. The default value is "25". @@ -9089,7 +9557,7 @@ Set the video duration of the sourced video. The accepted syntax is: [-]HH[:MM[:SS[.m...]]] [-]S+[.m...] @end example -See also the function @code{av_parse_time()}. +Also see the the @code{av_parse_time()} function. If not specified, or the expressed duration is negative, the video is supposed to be generated forever. @@ -9147,7 +9615,7 @@ Below is a description of the currently available video sinks. Buffer video frames, and make them available to the end of the filter graph. -This sink is mainly intended for a programmatic use, in particular +This sink is mainly intended for programmatic use, in particular through the interface defined in @file{libavfilter/buffersink.h} or the options system. @@ -9157,8 +9625,8 @@ parameter to @code{avfilter_init_filter} for initialization. @section nullsink -Null video sink, do absolutely nothing with the input video. It is -mainly useful as a template and to be employed in analysis / debugging +Null video sink: do absolutely nothing with the input video. It is +mainly useful as a template and for use in analysis / debugging tools. @c man end VIDEO SINKS @@ -9252,7 +9720,7 @@ Set the number of output video streams, that is also the number of video streams in each segment. Default is 1. @item a -Set the number of output audio streams, that is also the number of video +Set the number of output audio streams, that is also the number of audio streams in each segment. Default is 0. @item unsafe @@ -9524,42 +9992,42 @@ The expression can contain the following constants: @table @option @item n -the sequential number of the filtered frame, starting from 0 +The (sequential) number of the filtered frame, starting from 0. @item selected_n -the sequential number of the selected frame, starting from 0 +The (sequential) number of the selected frame, starting from 0. @item prev_selected_n -the sequential number of the last selected frame, NAN if undefined +The sequential number of the last selected frame. It's NAN if undefined. @item TB -timebase of the input timestamps +The timebase of the input timestamps. @item pts -the PTS (Presentation TimeStamp) of the filtered video frame, -expressed in @var{TB} units, NAN if undefined +The PTS (Presentation TimeStamp) of the filtered video frame, +expressed in @var{TB} units. It's NAN if undefined. @item t -the PTS (Presentation TimeStamp) of the filtered video frame, -expressed in seconds, NAN if undefined +The PTS of the filtered video frame, +expressed in seconds. It's NAN if undefined. @item prev_pts -the PTS of the previously filtered video frame, NAN if undefined +The PTS of the previously filtered video frame. It's NAN if undefined. @item prev_selected_pts -the PTS of the last previously filtered video frame, NAN if undefined +The PTS of the last previously filtered video frame. It's NAN if undefined. @item prev_selected_t -the PTS of the last previously selected video frame, NAN if undefined +The PTS of the last previously selected video frame. It's NAN if undefined. @item start_pts -the PTS of the first video frame in the video, NAN if undefined +The PTS of the first video frame in the video. It's NAN if undefined. @item start_t -the time of the first video frame in the video, NAN if undefined +The time of the first video frame in the video. It's NAN if undefined. @item pict_type @emph{(video only)} -the type of the filtered frame, can assume one of the following +The type of the filtered frame. It can assume one of the following values: @table @option @item I @@ -9572,14 +10040,14 @@ values: @end table @item interlace_type @emph{(video only)} -the frame interlace type, can assume one of the following values: +The frame interlace type. It can assume one of the following values: @table @option @item PROGRESSIVE -the frame is progressive (not interlaced) +The frame is progressive (not interlaced). @item TOPFIRST -the frame is top-field-first +The frame is top-field-first. @item BOTTOMFIRST -the frame is bottom-field-first +The frame is bottom-field-first. @end table @item consumed_sample_n @emph{(audio only)} @@ -9592,7 +10060,7 @@ the number of samples in the current frame the input sample rate @item key -1 if the filtered frame is a key-frame, 0 otherwise +This is 1 if the filtered frame is a key-frame, 0 otherwise. @item pos the position in the file of the filtered frame, -1 if the information @@ -9834,30 +10302,30 @@ constants: frame rate, only defined for constant frame-rate video @item PTS -the presentation timestamp in input +The presentation timestamp in input @item N -the count of the input frame for video or the number of consumed samples, +The count of the input frame for video or the number of consumed samples, not including the current frame for audio, starting from 0. @item NB_CONSUMED_SAMPLES -the number of consumed samples, not including the current frame (only +The number of consumed samples, not including the current frame (only audio) @item NB_SAMPLES, S -the number of samples in the current frame (only audio) +The number of samples in the current frame (only audio) @item SAMPLE_RATE, SR -audio sample rate +The audio sample rate. @item STARTPTS -the PTS of the first frame +The PTS of the first frame. @item STARTT the time in seconds of the first frame @item INTERLACED -tell if the current frame is interlaced +State whether the current frame is interlaced. @item T the time in seconds of the current frame @@ -9867,26 +10335,26 @@ original position in the file of the frame, or undefined if undefined for the current frame @item PREV_INPTS -previous input PTS +The previous input PTS. @item PREV_INT previous input time in seconds @item PREV_OUTPTS -previous output PTS +The previous output PTS. @item PREV_OUTT previous output time in seconds @item RTCTIME -wallclock (RTC) time in microseconds. This is deprecated, use time(0) +The wallclock (RTC) time in microseconds.. This is deprecated, use time(0) instead. @item RTCSTART -wallclock (RTC) time at the start of the movie in microseconds +The wallclock (RTC) time at the start of the movie in microseconds. @item TB -timebase of the input timestamps +The timebase of the input timestamps. @end table @@ -9948,7 +10416,7 @@ asetpts=N/SR/TB Set the timebase to use for the output frames timestamps. It is mainly useful for testing timebase configuration. -This filter accepts the following options: +It accepts the following parameters: @table @option @@ -9996,6 +10464,89 @@ settb=AVTB @end example @end itemize +@section showcqt +Convert input audio to a video output representing +frequency spectrum logarithmically (using constant Q transform with +Brown-Puckette algorithm), with musical tone scale, from E0 to D#10 (10 octaves). + +The filter accepts the following options: + +@table @option +@item volume +Specify the transform volume (multiplier). Acceptable value is [1.0, 100.0]. +Default value is @code{16.0}. + +@item timeclamp +Specify the transform timeclamp. At low frequency, there is trade-off between +accuracy in time domain and frequency domain. If timeclamp is lower, +event in time domain is represented more accurately (such as fast bass drum), +otherwise event in frequency domain is represented more accurately +(such as bass guitar). Acceptable value is [0.1, 1.0]. Default value is @code{0.17}. + +@item coeffclamp +Specify the transform coeffclamp. If coeffclamp is lower, transform is +more accurate, otherwise transform is faster. Acceptable value is [0.1, 10.0]. +Default value is @code{1.0}. + +@item gamma +Specify gamma. Lower gamma makes the spectrum more contrast, higher gamma +makes the spectrum having more range. Acceptable value is [1.0, 7.0]. +Default value is @code{3.0}. + +@item fontfile +Specify font file for use with freetype. If not specified, use embedded font. + +@item fullhd +If set to 1 (the default), the video size is 1920x1080 (full HD), +if set to 0, the video size is 960x540. Use this option to make CPU usage lower. + +@item fps +Specify video fps. Default value is @code{25}. + +@item count +Specify number of transform per frame, so there are fps*count transforms +per second. Note that audio data rate must be divisible by fps*count. +Default value is @code{6}. + +@end table + +@subsection Examples + +@itemize +@item +Playing audio while showing the spectrum: +@example +ffplay -f lavfi 'amovie=a.mp3, asplit [a][out1]; [a] showcqt [out0]' +@end example + +@item +Same as above, but with frame rate 30 fps: +@example +ffplay -f lavfi 'amovie=a.mp3, asplit [a][out1]; [a] showcqt=fps=30:count=5 [out0]' +@end example + +@item +Playing at 960x540 and lower CPU usage: +@example +ffplay -f lavfi 'amovie=a.mp3, asplit [a][out1]; [a] showcqt=fullhd=0:count=3 [out0]' +@end example + +@item +A1 and its harmonics: A1, A2, (near)E3, A3: +@example +ffplay -f lavfi 'aevalsrc=0.1*sin(2*PI*55*t)+0.1*sin(4*PI*55*t)+0.1*sin(6*PI*55*t)+0.1*sin(8*PI*55*t), + asplit[a][out1]; [a] showcqt [out0]' +@end example + +@item +Same as above, but with more accuracy in frequency domain (and slower): +@example +ffplay -f lavfi 'aevalsrc=0.1*sin(2*PI*55*t)+0.1*sin(4*PI*55*t)+0.1*sin(6*PI*55*t)+0.1*sin(8*PI*55*t), + asplit[a][out1]; [a] showcqt=timeclamp=0.5 [out0]' +@end example + +@end itemize + @section showspectrum Convert input audio to a video output, representing the audio frequency @@ -10282,23 +10833,23 @@ stream by default. Read audio and/or video stream(s) from a movie container. -This filter accepts the following options: +It accepts the following parameters: @table @option @item filename -The name of the resource to read (not necessarily a file but also a device or a -stream accessed through some protocol). +The name of the resource to read (not necessarily a file; it can also be a +device or a stream accessed through some protocol). @item format_name, f Specifies the format assumed for the movie to read, and can be either -the name of a container or an input device. If not specified the +the name of a container or an input device. If not specified, the format is guessed from @var{movie_name} or by probing. @item seek_point, sp -Specifies the seek point in seconds, the frames will be output -starting from this seek point, the parameter is evaluated with -@code{av_strtod} so the numerical value may be suffixed by an IS -postfix. Default value is "0". +Specifies the seek point in seconds. The frames will be output +starting from this seek point. The parameter is evaluated with +@code{av_strtod}, so the numerical value may be suffixed by an IS +postfix. The default value is "0". @item streams, s Specifies the streams to read. Several streams can be specified, @@ -10310,7 +10861,7 @@ is "dv", or "da" if the filter is called as "amovie". @item stream_index, si Specifies the index of the video stream to read. If the value is -1, -the best suited video stream will be automatically selected. Default +the most suitable video stream will be automatically selected. The default value is "-1". Deprecated. If the filter is called "amovie", it will select audio instead of video. @@ -10323,21 +10874,20 @@ Note that when the movie is looped the source timestamps are not changed, so it will generate non monotonically increasing timestamps. @end table -This filter allows one to overlay a second video on top of main input of -a filtergraph as shown in this graph: +It allows overlaying a second video on top of the main input of +a filtergraph, as shown in this graph: @example input -----------> deltapts0 --> overlay --> output ^ | movie --> scale--> deltapts1 -------+ @end example - @subsection Examples @itemize @item -Skip 3.2 seconds from the start of the avi file in.avi, and overlay it -on top of the input labelled as "in": +Skip 3.2 seconds from the start of the AVI file in.avi, and overlay it +on top of the input labelled "in": @example movie=in.avi:seek_point=3.2, scale=180:-1, setpts=PTS-STARTPTS [over]; [in] setpts=PTS-STARTPTS [main]; @@ -10346,7 +10896,7 @@ movie=in.avi:seek_point=3.2, scale=180:-1, setpts=PTS-STARTPTS [over]; @item Read from a video4linux2 device, and overlay it on top of the input -labelled as "in": +labelled "in": @example movie=/dev/video0:f=video4linux2, scale=180:-1, setpts=PTS-STARTPTS [over]; [in] setpts=PTS-STARTPTS [main]; diff --git a/doc/general.texi b/doc/general.texi index 98d06c731..35db91746 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -205,7 +205,7 @@ library: @item American Laser Games MM @tab @tab X @tab Multimedia format used in games like Mad Dog McCree. @item 3GPP AMR @tab X @tab X -@item Amazing Studio Packed Animation File @tab @tab X +@item Amazing Studio Packed Animation File @tab @tab X @tab Multimedia format used in game Heart Of Darkness. @item Apple HTTP Live Streaming @tab @tab X @item Artworx Data Format @tab @tab X @@ -245,6 +245,7 @@ library: @tab Multimedia format used by Delphine Software games. @item CD+G @tab @tab X @tab Video format used by CD+G karaoke disks +@item Phantom Cine @tab @tab X @item Commodore CDXL @tab @tab X @tab Amiga CD video format @item Core Audio Format @tab X @tab X @@ -258,6 +259,7 @@ library: @item Deluxe Paint Animation @tab @tab X @item DFA @tab @tab X @tab This format is used in Chronomaster game +@item DSD Stream File (DSF) @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 @@ -308,9 +310,11 @@ library: @tab Used by Linux Media Labs MPEG-4 PCI boards @item LOAS @tab @tab X @tab contains LATM multiplexed AAC audio +@item LRC @tab X @tab X @item LVF @tab @tab X @item LXF @tab @tab X @tab VR native stream format, used by Leitch/Harris' video servers. +@item Magic Lantern Video (MLV) @tab @tab X @item Matroska @tab X @tab X @item Matroska audio @tab X @tab @item FFmpeg metadata @tab X @tab X @@ -488,11 +492,13 @@ following image formats are supported: @item Name @tab Encoding @tab Decoding @tab Comments @item .Y.U.V @tab X @tab X @tab one raw file per component +@item Alias PIX @tab X @tab X + @tab Alias/Wavefront PIX image format @item animated GIF @tab X @tab X @item BMP @tab X @tab X @tab Microsoft BMP image -@item PIX @tab @tab X - @tab PIX is an image format used in the Argonaut BRender engine. +@item BRender PIX @tab @tab X + @tab Argonaut BRender 3D engine image format. @item DPX @tab X @tab X @tab Digital Picture Exchange @item EXR @tab @tab X @@ -680,8 +686,8 @@ following image formats are supported: @item LCL (LossLess Codec Library) MSZH @tab @tab X @item LCL (LossLess Codec Library) ZLIB @tab E @tab E @item LOCO @tab @tab X -@item LucasArts Smush @tab @tab X - @tab Used in LucasArts games. +@item LucasArts SANM/Smush @tab @tab X + @tab Used in LucasArts games / SMUSH animations. @item lossless MJPEG @tab X @tab X @item Microsoft ATC Screen @tab @tab X @tab Also known as Microsoft Screen 3. @@ -716,6 +722,8 @@ following image formats are supported: @tab fourcc: VP50 @item On2 VP6 @tab @tab X @tab fourcc: VP60,VP61,VP62 +@item On2 VP7 @tab @tab X + @tab fourcc: VP70,VP71 @item VP8 @tab E @tab X @tab fourcc: VP80, encoding supported through external library libvpx @item VP9 @tab E @tab X @@ -745,11 +753,11 @@ following image formats are supported: @tab Texture dictionaries used by the Renderware Engine. @item RL2 video @tab @tab X @tab used in some games by Entertainment Software Partners -@item SGI RLE 8-bit @tab @tab X @item Sierra VMD video @tab @tab X @tab Used in Sierra VMD files. @item Silicon Graphics Motion Video Compressor 1 (MVC1) @tab @tab X @item Silicon Graphics Motion Video Compressor 2 (MVC2) @tab @tab X +@item Silicon Graphics RLE 8-bit video @tab @tab X @item Smacker video @tab @tab X @tab Video encoding used in Smacker. @item SMPTE VC-1 @tab @tab X @@ -815,7 +823,7 @@ following image formats are supported: @tab encoding supported through external library libaacplus @item AAC @tab E @tab X @tab encoding supported through external library libfaac and libvo-aacenc -@item AC-3 @tab IX @tab X +@item AC-3 @tab IX @tab IX @item ADPCM 4X Movie @tab @tab X @item ADPCM CDROM XA @tab @tab X @item ADPCM Creative Technology @tab @tab X @@ -859,6 +867,8 @@ following image formats are supported: @item ADPCM Sound Blaster Pro 2-bit @tab @tab X @item ADPCM Sound Blaster Pro 2.6-bit @tab @tab X @item ADPCM Sound Blaster Pro 4-bit @tab @tab X +@item ADPCM VIMA + @tab Used in LucasArts SMUSH animations. @item ADPCM Westwood Studios IMA @tab @tab X @tab Used in Westwood Studios games like Command and Conquer. @item ADPCM Yamaha @tab X @tab X @@ -891,6 +901,10 @@ following image formats are supported: @item DPCM Sol @tab @tab X @item DPCM Xan @tab @tab X @tab Used in Origin's Wing Commander IV AVI files. +@item DSD (Direct Stream Digitial), least significant bit first @tab @tab X +@item DSD (Direct Stream Digitial), most significant bit first @tab @tab X +@item DSD (Direct Stream Digitial), least significant bit first, planar @tab @tab X +@item DSD (Direct Stream Digitial), most significant bit first, planar @tab @tab X @item DSP Group TrueSpeech @tab @tab X @item DV audio @tab @tab X @item Enhanced AC-3 @tab X @tab X @@ -913,13 +927,14 @@ following image formats are supported: @item Monkey's Audio @tab @tab X @item MP1 (MPEG audio layer 1) @tab @tab IX @item MP2 (MPEG audio layer 2) @tab IX @tab IX - @tab libtwolame can be used alternatively for encoding. + @tab encoding supported also through external library TwoLAME @item MP3 (MPEG audio layer 3) @tab E @tab IX @tab encoding supported through external library LAME, ADU MP3 and MP3onMP4 also supported @item MPEG-4 Audio Lossless Coding (ALS) @tab @tab X @item Musepack SV7 @tab @tab X @item Musepack SV8 @tab @tab X @item Nellymoser Asao @tab X @tab X +@item On2 AVC (Audio for Video Codec) @tab @tab X @item Opus @tab E @tab E @tab supported through external library libopus @item PCM A-law @tab X @tab X @@ -1022,7 +1037,7 @@ performance on systems without hardware floating point support). @item TED Talks captions @tab @tab X @tab @tab X @item VobSub (IDX+SUB) @tab @tab X @tab @tab X @item VPlayer @tab @tab X @tab @tab X -@item WebVTT @tab X @tab X @tab @tab X +@item WebVTT @tab X @tab X @tab X @tab X @item XSUB @tab @tab @tab X @tab X @end multitable @@ -1050,6 +1065,7 @@ performance on systems without hardware floating point support). @item RTMPTE @tab X @item RTMPTS @tab X @item RTP @tab X +@item SAMBA @tab E @item SCTP @tab X @item SFTP @tab E @item TCP @tab X @@ -1083,6 +1099,7 @@ performance on systems without hardware floating point support). @item Video4Linux2 @tab X @tab X @item VfW capture @tab X @tab @item X11 grabbing @tab X @tab +@item Win32 grabbing @tab X @tab @end multitable @code{X} means that input/output is supported. diff --git a/doc/indevs.texi b/doc/indevs.texi index 93fbbe822..420580877 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -13,8 +13,8 @@ You can disable all the input devices using the configure option option "--enable-indev=@var{INDEV}", or you can disable a particular input device using the option "--disable-indev=@var{INDEV}". -The option "-formats" of the ff* tools will display the list of -supported input devices (amongst the demuxers). +The option "-devices" of the ff* tools will display the list of +supported input devices. A description of the currently available input devices follows. @@ -51,6 +51,41 @@ ffmpeg -f alsa -i hw:0 alsaout.wav For more information see: @url{http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html} +@section avfoundation + +AVFoundation input device. + +AVFoundation is the currently recommended framework by Apple for streamgrabbing on OSX >= 10.7 as well as on iOS. +The older QTKit framework has been marked deprecated since OSX version 10.7. + +The filename passed as input is parsed to contain either a device name or index. +The device index can also be given by using -video_device_index. +A given device index will override any given device name. +If the desired device consists of numbers only, use -video_device_index to identify it. +The default device will be chosen if an empty string or the device name "default" is given. +The available devices can be enumerated by using -list_devices. +The pixel format can be set using -pixel_format. +Available formats: + monob, rgb555be, rgb555le, rgb565be, rgb565le, rgb24, bgr24, 0rgb, bgr0, 0bgr, rgb0, + bgr48be, uyvy422, yuva444p, yuva444p16le, yuv444p, yuv422p16, yuv422p10, yuv444p10, + yuv420p, nv12, yuyv422, gray + +@example +ffmpeg -f avfoundation -i "0" out.mpg +@end example + +@example +ffmpeg -f avfoundation -video_device_index 0 -i "" out.mpg +@end example + +@example +ffmpeg -f avfoundation -pixel_format bgr0 -i "default" out.mpg +@end example + +@example +ffmpeg -f avfoundation -list_devices true -i "" +@end example + @section bktr BSD video input device. @@ -192,6 +227,81 @@ ffmpeg -f fbdev -frames:v 1 -r 1 -i /dev/fb0 screenshot.jpeg See also @url{http://linux-fbdev.sourceforge.net/}, and fbset(1). +@section gdigrab + +Win32 GDI-based screen capture device. + +This device allows you to capture a region of the display on Windows. + +There are two options for the input filename: +@example +desktop +@end example +or +@example +title=@var{window_title} +@end example + +The first option will capture the entire desktop, or a fixed region of the +desktop. The second option will instead capture the contents of a single +window, regardless of its position on the screen. + +For example, to grab the entire desktop using @command{ffmpeg}: +@example +ffmpeg -f gdigrab -framerate 6 -i desktop out.mpg +@end example + +Grab a 640x480 region at position @code{10,20}: +@example +ffmpeg -f gdigrab -framerate 6 -offset_x 10 -offset_y 20 -video_size vga -i desktop out.mpg +@end example + +Grab the contents of the window named "Calculator" +@example +ffmpeg -f gdigrab -framerate 6 -i title=Calculator out.mpg +@end example + +@subsection Options + +@table @option +@item draw_mouse +Specify whether to draw the mouse pointer. Use the value @code{0} to +not draw the pointer. Default value is @code{1}. + +@item framerate +Set the grabbing frame rate. Default value is @code{ntsc}, +corresponding to a frame rate of @code{30000/1001}. + +@item show_region +Show grabbed region on screen. + +If @var{show_region} is specified with @code{1}, then the grabbing +region will be indicated on screen. With this option, it is easy to +know what is being grabbed if only a portion of the screen is grabbed. + +Note that @var{show_region} is incompatible with grabbing the contents +of a single window. + +For example: +@example +ffmpeg -f gdigrab -show_region 1 -framerate 6 -video_size cif -offset_x 10 -offset_y 20 -i desktop out.mpg +@end example + +@item video_size +Set the video frame size. The default is to capture the full screen if @file{desktop} is selected, or the full window size if @file{title=@var{window_title}} is selected. + +@item offset_x +When capturing a region with @var{video_size}, set the distance from the left edge of the screen or desktop. + +Note that the offset calculation is from the top left corner of the primary monitor on Windows. If you have a monitor positioned to the left of your primary monitor, you will need to use a negative @var{offset_x} value to move the region to that monitor. + +@item offset_y +When capturing a region with @var{video_size}, set the distance from the top edge of the screen or desktop. + +Note that the offset calculation is from the top left corner of the primary monitor on Windows. If you have a monitor positioned above your primary monitor, you will need to use a negative @var{offset_y} value to move the region to that monitor. + +@end table + @section iec61883 FireWire DV/HDV input device using libiec61883. @@ -531,6 +641,33 @@ Record a stream from default device: ffmpeg -f pulse -i default /tmp/pulse.wav @end example +@section qtkit + +QTKit input device. + +The filename passed as input is parsed to contain either a device name or index. +The device index can also be given by using -video_device_index. +A given device index will override any given device name. +If the desired device consists of numbers only, use -video_device_index to identify it. +The default device will be chosen if an empty string or the device name "default" is given. +The available devices can be enumerated by using -list_devices. + +@example +ffmpeg -f qtkit -i "0" out.mpg +@end example + +@example +ffmpeg -f qtkit -video_device_index 0 -i "" out.mpg +@end example + +@example +ffmpeg -f qtkit -i "default" out.mpg +@end example + +@example +ffmpeg -f qtkit -list_devices true -i "" +@end example + @section sndio sndio input device. diff --git a/doc/muxers.texi b/doc/muxers.texi index d9596ebce..55e06a343 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -233,6 +233,10 @@ to @var{wrap}. Start the playlist sequence number from @var{number}. Default value is 0. +@item hls_base_url @var{baseurl} +Append @var{baseurl} to every entry in the playlist. +Useful to generate playlists with absolute paths. + Note that the playlist sequence number must be unique for each segment and it is not to be confused with the segment filename sequence number which can be cyclic, for example if the @option{wrap} option is @@ -633,7 +637,10 @@ Set the first PID for data packets (default 0x0100, max 0x0f00). @item -mpegts_m2ts_mode @var{number} Enable m2ts mode if set to 1. Default value is -1 which disables m2ts mode. @item -muxrate @var{number} -Set muxrate. +Set a constant muxrate (default VBR). +@item -pcr_period @var{numer} +Override the default PCR retransmission time (default 20ms), ignored +if variable muxrate is selected. @item -pes_payload_size @var{number} Set minimum PES packet payload in bytes. @item -mpegts_flags @var{flags} @@ -702,6 +709,30 @@ Alternatively you can write the command as: ffmpeg -benchmark -i INPUT -f null - @end example +@section nut + +@table @option +@item -syncpoints @var{flags} +Change the syncpoint usage in nut: +@table @option +@item @var{default} use the normal low-overhead seeking aids. +@item @var{none} do not use the syncpoints at all, reducing the overhead but making the stream non-seekable; + Use of this option is not recommended, as the resulting files are very damage + sensitive and seeking is not possible. Also in general the overhead from + syncpoints is negligible. Note, -@code{write_index} 0 can be used to disable + all growing data tables, allowing to mux endless streams with limited memory + and wihout these disadvantages. +@item @var{timestamped} extend the syncpoint with a wallclock field. +@end table +The @var{none} and @var{timestamped} flags are experimental. +@item -write_index @var{bool} +Write index at the end, the default is to write an index. +@end table + +@example +ffmpeg -i INPUT -f_strict experimental -syncpoints none - | processor +@end example + @section ogg Ogg container muxer. @@ -783,17 +814,21 @@ Allow caching (only affects M3U8 list files). Allow live-friendly file generation. @end table +@item segment_list_type @var{type} +Select the listing format. +@table @option +@item @var{flat} use a simple flat list of entries. +@item @var{hls} use a m3u8-like structure. +@end table + @item segment_list_size @var{size} Update the list file so that it contains at most the last @var{size} segments. If 0 the list file will contain all the segments. Default value is 0. @item segment_list_entry_prefix @var{prefix} -Set @var{prefix} to prepend to the name of each entry filename. By -default no prefix is applied. - -@item segment_list_type @var{type} -Specify the format for the segment list file. +Prepend @var{prefix} to each entry. Useful to generate absolute paths. +By default no prefix is applied. The following values are recognized: @table @samp @@ -844,6 +879,16 @@ Note that splitting may not be accurate, unless you force the reference stream key-frames at the given time. See the introductory notice and the examples below. +@item segment_atclocktime @var{1|0} +If set to "1" split at regular clock time intervals starting from 00:00 +o'clock. The @var{time} value specified in @option{segment_time} is +used for setting the length of the splitting interval. + +For example with @option{segment_time} set to "900" this makes it possible +to create files at 12:00 o'clock, 12:15, 12:30, etc. + +Default value is "0". + @item segment_time_delta @var{delta} Specify the accuracy time when selecting the start time for a segment, expressed as a duration specification. Default value is "0". @@ -949,6 +994,28 @@ ffmpeg -re -i in.mkv -codec copy -map 0 -f segment -segment_list playlist.m3u8 \ @end example @end itemize +@section smoothstreaming + +Smooth Streaming muxer generates a set of files (Manifest, chunks) suitable for serving with conventional web server. + +@table @option +@item window_size +Specify the number of fragments kept in the manifest. Default 0 (keep all). + +@item extra_window_size +Specify the number of fragments kept outside of the manifest before removing from disk. Default 5. + +@item lookahead_count +Specify the number of lookahead fragments. Default 2. + +@item min_frag_duration +Specify the minimum fragment duration (in microseconds). Default 5000000. + +@item remove_at_exit +Specify whether to remove all fragments when finished. Default 0 (do not remove). + +@end table + @section tee The tee muxer can be used to write the same data to several files or any @@ -986,7 +1053,7 @@ It is possible to specify to which streams a given bitstream filter applies, by appending a stream specifier to the option separated by @code{/}. @var{spec} must be a stream specifier (see @ref{Format stream specifiers}). If the stream specifier is not specified, the -bistream filters will be applied to all streams in the output. +bitstream filters will be applied to all streams in the output. Several bitstream filters can be specified, separated by ",". @@ -1033,4 +1100,34 @@ Note: some codecs may need different options depending on the output format; the auto-detection of this can not work with the tee muxer. The main example is the @option{global_header} flag. +@section webm_dash_manifest + +WebM DASH Manifest muxer. + +This muxer implements the WebM DASH Manifest specification to generate the DASH manifest XML. + +@subsection Options + +This muxer supports the following options: + +@table @option +@item adaptation_sets +This option has the following syntax: "id=x,streams=a,b,c id=y,streams=d,e" where x and y are the +unique identifiers of the adaptation sets and a,b,c,d and e are the indices of the corresponding +audio and video streams. Any number of adaptation sets can be added using this option. +@end table + +@subsection Example +@example +ffmpeg -f webm_dash_manifest -i video1.webm \ + -f webm_dash_manifest -i video2.webm \ + -f webm_dash_manifest -i audio1.webm \ + -f webm_dash_manifest -i audio2.webm \ + -map 0 -map 1 -map 2 -map 3 \ + -c copy \ + -f webm_dash_manifest \ + -adaptation_sets "id=0,streams=0,1 id=1,streams=2,3" \ + manifest.xml +@end example + @c man end MUXERS diff --git a/doc/nut.texi b/doc/nut.texi index 0026a121b..fee12da9e 100644 --- a/doc/nut.texi +++ b/doc/nut.texi @@ -21,6 +21,27 @@ The official nut specification is at svn://svn.mplayerhq.hu/nut In case of any differences between this text and the official specification, the official specification shall prevail. +@chapter Modes +NUT has some variants signaled by using the flags field in its main header. + +@multitable @columnfractions .4 .4 +@item BROADCAST @tab Extend the syncpoint to report the sender wallclock +@item PIPE @tab Omit completely the syncpoint +@end multitable + +@section BROADCAST + +The BROADCAST variant provides a secondary time reference to facilitate +detecting endpoint latency and network delays. +It assumes all the endpoint clocks are syncronized. +To be used in real-time scenarios. + +@section PIPE + +The PIPE variant assumes NUT is used as non-seekable intermediate container, +by not using syncpoint removes unneeded overhead and reduces the overall +memory usage. + @chapter Container-specific codec tags @section Generic raw YUVA formats diff --git a/doc/optimization.txt b/doc/optimization.txt index 5a66d6bb3..94a427732 100644 --- a/doc/optimization.txt +++ b/doc/optimization.txt @@ -79,9 +79,6 @@ qpel{8,16}_mc??_old_c / *pixels{8,16}_l4 Just used to work around a bug in an old libavcodec encoder version. Don't optimize them. -tpel_mc_func {put,avg}_tpel_pixels_tab - Used only for SVQ3, so only optimize them if you need fast SVQ3 decoding. - add_bytes/diff_bytes For huffyuv only, optimize if you want a faster ffhuffyuv codec. @@ -139,9 +136,6 @@ dct_unquantize_mpeg2 dct_unquantize_h263 Used in MPEG-4/H.263 en/decoding. -FIXME remaining functions? -BTW, most of these functions are in dsputil.c/.h, some are in mpegvideo.c/.h. - Alignment: @@ -268,17 +262,6 @@ CELL/SPU: http://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/30B3520C93F437AB87257060006FFE5E/$file/Language_Extensions_for_CBEA_2.4.pdf http://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/9F820A5FFA3ECE8C8725716A0062585F/$file/CBE_Handbook_v1.1_24APR2007_pub.pdf -SPARC-specific: ---------------- -SPARC Joint Programming Specification (JPS1): Commonality -http://www.fujitsu.com/downloads/PRMPWR/JPS1-R1.0.4-Common-pub.pdf - -UltraSPARC III Processor User's Manual (contains instruction timings) -http://www.sun.com/processors/manuals/USIIIv2.pdf - -VIS Whitepaper (contains optimization guidelines) -http://www.sun.com/processors/vis/download/vis/vis_whitepaper.pdf - GCC asm links: -------------- official doc but quite ugly diff --git a/doc/outdevs.texi b/doc/outdevs.texi index bc94b9ed0..e68653fd7 100644 --- a/doc/outdevs.texi +++ b/doc/outdevs.texi @@ -13,8 +13,8 @@ You can disable all the output devices using the configure option option "--enable-outdev=@var{OUTDEV}", or you can disable a particular input device using the option "--disable-outdev=@var{OUTDEV}". -The option "-formats" of the ff* tools will display the list of -enabled output devices (amongst the muxers). +The option "-devices" of the ff* tools will display the list of +enabled output devices. A description of the currently available output devices follows. @@ -220,11 +220,11 @@ This output device allows one to render to OpenGL context. Context may be provided by application or default SDL window is created. When device renders to external context, application must implement handlers for following messages: -@code{AV_CTL_MESSAGE_CREATE_WINDOW_BUFFER} - create OpenGL context on current thread. -@code{AV_CTL_MESSAGE_PREPARE_WINDOW_BUFFER} - make OpenGL context current. -@code{AV_CTL_MESSAGE_DISPLAY_WINDOW_BUFFER} - swap buffers. -@code{AV_CTL_MESSAGE_DESTROY_WINDOW_BUFFER} - destroy OpenGL context. -Application is also required to inform a device about current resolution by sending @code{AV_DEVICE_WINDOW_RESIZED} message. +@code{AV_DEV_TO_APP_CREATE_WINDOW_BUFFER} - create OpenGL context on current thread. +@code{AV_DEV_TO_APP_PREPARE_WINDOW_BUFFER} - make OpenGL context current. +@code{AV_DEV_TO_APP_DISPLAY_WINDOW_BUFFER} - swap buffers. +@code{AV_DEV_TO_APP_DESTROY_WINDOW_BUFFER} - destroy OpenGL context. +Application is also required to inform a device about current resolution by sending @code{AV_APP_TO_DEV_WINDOW_SIZE} message. @subsection Options @table @option @@ -237,6 +237,10 @@ Application must provide OpenGL context and both @code{window_size_cb} and @code @item window_title Set the SDL window title, if not specified default to the filename specified for the output device. Ignored when @option{no_window} is set. +@item window_size +Set preferred window size, can be a string of the form widthxheight or a video size abbreviation. +If not specified it defaults to the size of the input video, downscaled according to the aspect ratio. +Mostly usable when @option{no_window} is not set. @end table @@ -290,6 +294,20 @@ When both options are provided then the highest value is used are set to 0 (which is default), the device will use the default PulseAudio duration value. By default PulseAudio set buffer duration to around 2 seconds. + +@item prebuf +Specify pre-buffering size in bytes. The server does not start with +playback before at least @option{prebuf} bytes are available in the +buffer. By default this option is initialized to the same value as +@option{buffer_size} or @option{buffer_duration} (whichever is bigger). + +@item minreq +Specify minimum request size in bytes. The server does not request less +than @option{minreq} bytes from the client, instead waits until the buffer +is free enough to request more bytes at once. It is recommended to not set +this option, which will initialize this to a value that is deemed sensible +by the server. + @end table @subsection Examples @@ -388,19 +406,26 @@ For example, @code{dual-headed:0.1} would specify screen 1 of display Check the X11 specification for more detailed information about the display name format. +@item window_id +When set to non-zero value then device doesn't create new window, +but uses existing one with provided @var{window_id}. By default +this options is set to zero and device creates its own window. + @item window_size Set the created window size, can be a string of the form @var{width}x@var{height} or a video size abbreviation. If not specified it defaults to the size of the input video. +Ignored when @var{window_id} is set. @item window_x @item window_y Set the X and Y window offsets for the created window. They are both set to 0 by default. The values may be ignored by the window manager. +Ignored when @var{window_id} is set. @item window_title Set the window title, if not specified default to the filename -specified for the output device. +specified for the output device. Ignored when @var{window_id} is set. @end table For more information about XVideo see @url{http://www.x.org/}. diff --git a/doc/platform.texi b/doc/platform.texi index f5bfd256c..c71121fc1 100644 --- a/doc/platform.texi +++ b/doc/platform.texi @@ -24,6 +24,17 @@ If not, then you should install a different compiler that has no hard-coded path to gas. In the worst case pass @code{--disable-asm} to configure. +@section Advanced linking configuration + +If you compiled FFmpeg libraries statically and you want to use them to +build your own shared library, you may need to force PIC support (with +@code{--enable-pic} during FFmpeg configure) and add the following option +to your project LDFLAGS: + +@example +-Wl,-Bsymbolic +@end example + @section BSD BSD make will not build FFmpeg, you need to install and use GNU Make @@ -52,14 +63,14 @@ unacelerated code. Mac OS X on PowerPC or ARM (iPhone) requires a preprocessor from @url{https://github.com/FFmpeg/gas-preprocessor} or -@url{http://github.com/yuvi/gas-preprocessor} to build the optimized -assembler functions. Put the Perl script somewhere +@url{https://github.com/yuvi/gas-preprocessor}(currently outdated) to build the optimized +assembly functions. Put the Perl script somewhere in your PATH, FFmpeg's configure will pick it up automatically. Mac OS X on amd64 and x86 requires @command{yasm} to build most of the -optimized assembler functions. @uref{http://www.finkproject.org/, Fink}, +optimized assembly functions. @uref{http://www.finkproject.org/, Fink}, @uref{http://www.gentoo.org/proj/en/gentoo-alt/prefix/bootstrap-macos.xml, Gentoo Prefix}, -@uref{http://mxcl.github.com/homebrew/, Homebrew} +@uref{https://mxcl.github.com/homebrew/, Homebrew} or @uref{http://www.macports.org, MacPorts} can easily provide it. diff --git a/doc/protocols.texi b/doc/protocols.texi index 91b824430..a8898d38e 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -166,7 +166,7 @@ This protocol accepts the following options. @table @option @item timeout -Set timeout of socket I/O operations used by the underlying low level +Set timeout in microseconds of socket I/O operations used by the underlying low level operation. By default it is set to -1, which means that the timeout is not specified. @@ -244,7 +244,7 @@ Override the User-Agent header. If not specified the protocol will use a string describing the libavformat build. ("Lavf/") @item timeout -Set timeout of socket I/O operations used by the underlying low level +Set timeout in microseconds of socket I/O operations used by the underlying low level operation. By default it is set to -1, which means that the timeout is not specified. @@ -537,6 +537,35 @@ The Real-Time Messaging Protocol tunneled through HTTPS (RTMPTS) is used for streaming multimedia content within HTTPS requests to traverse firewalls. +@section libsmbclient + +libsmbclient permits to manipulate CIFS/SMB network resources. + +Following syntax is required. + +@example +smb://[[domain:]user[:password@@]]server[/share[/path[/file]]] +@end example + +This protocol accepts the following options. + +@table @option +@item timeout +Set timeout in miliseconds of socket I/O operations used by the underlying +low level operation. By default it is set to -1, which means that the timeout +is not specified. + +@item truncate +Truncate existing files on write, if set to 1. A value of 0 prevents +truncating. Default value is 1. + +@item workgroup +Set the workgroup used for making connections. By default workgroup is not specified. + +@end table + +For more information see: @url{http://www.samba.org/}. + @section libssh Secure File Transfer Protocol via libssh @@ -691,7 +720,7 @@ data transferred over RDT). The muxer can be used to send a stream using RTSP ANNOUNCE to a server supporting it (currently Darwin Streaming Server and Mischa Spiegelmock's -@uref{http://github.com/revmischa/rtsp-server, RTSP server}). +@uref{https://github.com/revmischa/rtsp-server, RTSP server}). The required syntax for a RTSP url is: @example @@ -710,7 +739,7 @@ Do not start playing the stream immediately if set to 1. Default value is 0. @item rtsp_transport -Set RTSP trasport protocols. +Set RTSP transport protocols. It accepts the following values: @table @samp @@ -742,6 +771,8 @@ The following values are accepted: Accept packets only from negotiated peer address and port. @item listen Act as a server, listening for an incoming connection. +@item prefer_tcp +Try TCP for RTP transport first, if TCP is available as RTSP RTP transport. @end table Default value is @samp{none}. @@ -767,17 +798,17 @@ Set maximum local UDP port. Default value is 65000. @item timeout Set maximum timeout (in seconds) to wait for incoming connections. -A value of -1 mean infinite (default). This option implies the +A value of -1 means infinite (default). This option implies the @option{rtsp_flags} set to @samp{listen}. @item reorder_queue_size Set number of packets to buffer for handling of reordered packets. @item stimeout -Set socket TCP I/O timeout in micro seconds. +Set socket TCP I/O timeout in microseconds. @item user-agent -Override User-Agent header. If not specified, it default to the +Override User-Agent header. If not specified, it defaults to the libavformat identifier string. @end table @@ -958,6 +989,30 @@ this binary block are used as master key, the following 14 bytes are used as master salt. @end table +@section subfile + +Virtually extract a segment of a file or another stream. +The underlying stream must be seekable. + +Accepted options: +@table @option +@item start +Start offset of the extracted segment, in bytes. +@item end +End offset of the extracted segment, in bytes. +@end table + +Examples: + +Extract a chapter from a DVD VOB file (start and end sectors obtained +externally and multiplied by 2048): +@example +subfile,,start,153391104,end,268142592,,:/media/dvd/VIDEO_TS/VTS_08_1.VOB +@end example + +Play an AVI file directly from a TAR archive: +subfile,,start,183241728,end,366490624,,:archive.tar + @section tcp Transmission Control Protocol. @@ -1074,8 +1129,9 @@ The list of supported options follows. @table @option @item buffer_size=@var{size} -Set the UDP socket buffer size in bytes. This is used both for the -receiving and the sending buffer size. +Set the UDP maximum socket buffer size in bytes. This is used to set either +the receive or send buffer size, depending on what the socket is used for. +Default is 64KB. See also @var{fifo_size}. @item localport=@var{port} Override the local UDP port to bind with. @@ -1126,6 +1182,12 @@ Set raise error timeout, expressed in microseconds. This option is only relevant in read mode: if no data arrived in more than this time interval, raise error. + +@item broadcast=@var{1|0} +Explicitly allow or disallow UDP broadcasting. + +Note that broadcasting may not work properly on networks having +a broadcast storm protection. @end table @subsection Examples diff --git a/doc/scaler.texi b/doc/scaler.texi index f043ffd5f..23d639388 100644 --- a/doc/scaler.texi +++ b/doc/scaler.texi @@ -112,6 +112,14 @@ bayer dither @item ed error diffusion dither + +@item a_dither +arithmetic dither, based using addition + +@item x_dither +arithmetic dither, based using xor (more random/less apparent patterning that +a_dither). + @end table @end table diff --git a/doc/texi2pod.pl b/doc/texi2pod.pl index b825fdc24..94e011e42 100644 --- a/doc/texi2pod.pl +++ b/doc/texi2pod.pl @@ -282,6 +282,14 @@ INF: while(<$inf>) { $_ = "\n=over 4\n"; }; + /^\@(multitable)\s+{.*/ and do { + push @endwstack, $endw; + push @icstack, $ic; + $endw = $1; + $ic = ""; + $_ = "\n=over 4\n"; + }; + /^\@((?:small)?example|display)/ and do { push @endwstack, $endw; $endw = $1; @@ -298,10 +306,10 @@ INF: while(<$inf>) { /^\@tab\s+(.*\S)\s*$/ and $endw eq "multitable" and do { my $columns = $1; - $columns =~ s/\@tab/ : /; + $columns =~ s/\@tab//; - $_ = " : ". $columns; - $chapter =~ s/\n+\s+$//; + $_ = $columns; + $chapter =~ s/$//; }; /^\@itemx?\s*(.+)?$/ and do { diff --git a/doc/utils.texi b/doc/utils.texi index 5abfb0ccc..c46ad4523 100644 --- a/doc/utils.texi +++ b/doc/utils.texi @@ -1031,7 +1031,7 @@ indication of the corresponding powers of 10 and of 2. 10^24 / 2^70 @end table -@c man end +@c man end EXPRESSION EVALUATION @chapter OpenCL Options @c man begin OPENCL OPTIONS diff --git a/doc/writing_filters.txt b/doc/writing_filters.txt new file mode 100644 index 000000000..c7923e884 --- /dev/null +++ b/doc/writing_filters.txt @@ -0,0 +1,424 @@ +This document is a tutorial/initiation for writing simple filters in +libavfilter. + +Foreword: just like everything else in FFmpeg, libavfilter is monolithic, which +means that it is highly recommended that you submit your filters to the FFmpeg +development mailing-list and make sure it is applied. Otherwise, your filter is +likely to have a very short lifetime due to more a less regular internal API +changes, and a limited distribution, review, and testing. + +Bootstrap +========= + +Let's say you want to write a new simple video filter called "foobar" which +takes one frame in input, changes the pixels in whatever fashion you fancy, and +outputs the modified frame. The most simple way of doing this is to take a +similar filter. We'll pick edgedetect, but any other should do. You can look +for others using the `./ffmpeg -v 0 -filters|grep ' V->V '` command. + + - cp libavfilter/vf_{edgedetect,foobar}.c + - sed -i s/edgedetect/foobar/g -i libavfilter/vf_foobar.c + - sed -i s/EdgeDetect/Foobar/g -i libavfilter/vf_foobar.c + - edit libavfilter/Makefile, and add an entry for "foobar" following the + pattern of the other filters. + - edit libavfilter/allfilters.c, and add an entry for "foobar" following the + pattern of the other filters. + - ./configure ... + - make -j ffmpeg + - ./ffmpeg -i tests/lena.pnm -vf foobar foobar.png + +If everything went right, you should get a foobar.png with Lena edge-detected. + +That's it, your new playground is ready. + +Some little details about what's going on: +libavfilter/allfilters.c:avfilter_register_all() is called at runtime to create +a list of the available filters, but it's important to know that this file is +also parsed by the configure script, which in turn will define variables for +the build system and the C: + + --- after running configure --- + + $ grep FOOBAR config.mak + CONFIG_FOOBAR_FILTER=yes + $ grep FOOBAR config.h + #define CONFIG_FOOBAR_FILTER 1 + +CONFIG_FOOBAR_FILTER=yes from the config.mak is later used to enable the filter in +libavfilter/Makefile and CONFIG_FOOBAR_FILTER=1 from the config.h will be used +for registering the filter in libavfilter/allfilters.c. + +Filter code layout +================== + +You now need some theory about the general code layout of a filter. Open your +libavfilter/vf_foobar.c. This section will detail the important parts of the +code you need to understand before messing with it. + +Copyright +--------- + +First chunk is the copyright. Most filters are LGPL, and we are assuming +vf_foobar is as well. We are also assuming vf_foobar is not an edge detector +filter, so you can update the boilerplate with your credits. + +Doxy +---- + +Next chunk is the Doxygen about the file. See http://ffmpeg.org/doxygen/trunk/. +Detail here what the filter is, does, and add some references if you feel like +it. + +Context +------- + +Skip the headers and scroll down to the definition of FoobarContext. This is +your local state context. It is already filled with 0 when you get it so do not +worry about uninitialized read into this context. This is where you put every +"global" information you need, typically the variable storing the user options. +You'll notice the first field "const AVClass *class"; it's the only field you +need to keep assuming you have a context. There are some magic you don't care +about around this field, just let it be (in first position) for now. + +Options +------- + +Then comes the options array. This is what will define the user accessible +options. For example, -vf foobar=mode=colormix:high=0.4:low=0.1. Most options +have the following pattern: + name, description, offset, type, default value, minimum value, maximum value, flags + + - name is the option name, keep it simple, lowercase + - description are short, in lowercase, without period, and describe what they + do, for example "set the foo of the bar" + - offset is the offset of the field in your local context, see the OFFSET() + macro; the option parser will use that information to fill the fields + according to the user input + - type is any of AV_OPT_TYPE_* defined in libavutil/opt.h + - default value is an union where you pick the appropriate type; "{.dbl=0.3}", + "{.i64=0x234}", "{.str=NULL}", ... + - min and max values define the range of available values, inclusive + - flags are AVOption generic flags. See AV_OPT_FLAG_* definitions + +In doubt, just look at the other AVOption definitions all around the codebase, +there are tons of examples. + +Class +----- + +AVFILTER_DEFINE_CLASS(foobar) will define a unique foobar_class with some kind +of signature referencing the options, etc. which will be referenced in the +definition of the AVFilter. + +Filter definition +----------------- + +At the end of the file, you will find foobar_inputs, foobar_outputs and +the AVFilter ff_vf_foobar. Don't forget to update the AVFilter.description with +a description of what the filter does, starting with a capitalized letter and +ending with a period. You'd better drop the AVFilter.flags entry for now, and +re-add them later depending on the capabilities of your filter. + +Callbacks +--------- + +Let's now study the common callbacks. Before going into details, note that all +these callbacks are explained in details in libavfilter/avfilter.h, so in +doubt, refer to the doxy in that file. + +init() +~~~~~~ + +First one to be called is init(). It's flagged as cold because not called +often. Look for "cold" on +http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html for more +information. + +As the name suggests, init() is where you eventually initialize and allocate +your buffers, pre-compute your data, etc. Note that at this point, your local +context already has the user options initialized, but you still haven't any +clue about the kind of data input you will get, so this function is often +mainly used to sanitize the user options. + +Some init()s will also define the number of inputs or outputs dynamically +according to the user options. A good example of this is the split filter, but +we won't cover this here since vf_foobar is just a simple 1:1 filter. + +uninit() +~~~~~~~~ + +Similarly, there is the uninit() callback, doing what the name suggest. Free +everything you allocated here. + +query_formats() +~~~~~~~~~~~~~~~ + +This is following the init() and is used for the format negotiation, basically +where you say what pixel format(s) (gray, rgb 32, yuv 4:2:0, ...) you accept +for your inputs, and what you can output. All pixel formats are defined in +libavutil/pixfmt.h. If you don't change the pixel format between the input and +the output, you just have to define a pixel formats array and call +ff_set_common_formats(). For more complex negotiation, you can refer to other +filters such as vf_scale. + +config_props() +~~~~~~~~~~~~~~ + +This callback is not necessary, but you will probably have one or more +config_props() anyway. It's not a callback for the filter itself but for its +inputs or outputs (they're called "pads" - AVFilterPad - in libavfilter's +lexicon). + +Inside the input config_props(), you are at a point where you know which pixel +format has been picked after query_formats(), and more information such as the +video width and height (inlink->{w,h}). So if you need to update your internal +context state depending on your input you can do it here. In edgedetect you can +see that this callback is used to allocate buffers depending on these +information. They will be destroyed in uninit(). + +Inside the output config_props(), you can define what you want to change in the +output. Typically, if your filter is going to double the size of the video, you +will update outlink->w and outlink->h. + +filter_frame() +~~~~~~~~~~~~~~ + +This is the callback you are waiting from the beginning: it is where you +process the received frames. Along with the frame, you get the input link from +where the frame comes from. + + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { ... } + +You can get the filter context through that input link: + + AVFilterContext *ctx = inlink->dst; + +Then access your internal state context: + + FoobarContext *foobar = ctx->priv; + +And also the output link where you will send your frame when you are done: + + AVFilterLink *outlink = ctx->outputs[0]; + +Here, we are picking the first output. You can have several, but in our case we +only have one since we are in a 1:1 input-output situation. + +If you want to define a simple pass-through filter, you can just do: + + return ff_filter_frame(outlink, in); + +But of course, you probably want to change the data of that frame. + +This can be done by accessing frame->data[] and frame->linesize[]. Important +note here: the width does NOT match the linesize. The linesize is always +greater or equal to the width. The padding created should not be changed or +even read. Typically, keep in mind that a previous filter in your chain might +have altered the frame dimension but not the linesize. Imagine a crop filter +that halves the video size: the linesizes won't be changed, just the width. + + <-------------- linesize ------------------------> + +-------------------------------+----------------+ ^ + | | | | + | | | | + | picture | padding | | height + | | | | + | | | | + +-------------------------------+----------------+ v + <----------- width -------------> + +Before modifying the "in" frame, you have to make sure it is writable, or get a +new one. Multiple scenarios are possible here depending on the kind of +processing you are doing. + +Let's say you want to change one pixel depending on multiple pixels (typically +the surrounding ones) of the input. In that case, you can't do an in-place +processing of the input so you will need to allocate a new frame, with the same +properties as the input one, and send that new frame to the next filter: + + AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + + // out->data[...] = foobar(in->data[...]) + + av_frame_free(&in); + return ff_filter_frame(outlink, out); + +In-place processing +~~~~~~~~~~~~~~~~~~~ + +If you can just alter the input frame, you probably just want to do that +instead: + + av_frame_make_writable(in); + // in->data[...] = foobar(in->data[...]) + return ff_filter_frame(outlink, in); + +You may wonder why a frame might not be writable. The answer is that for +example a previous filter might still own the frame data: imagine a filter +prior to yours in the filtergraph that needs to cache the frame. You must not +alter that frame, otherwise it will make that previous filter buggy. This is +where av_frame_make_writable() helps (it won't have any effect if the frame +already is writable). + +The problem with using av_frame_make_writable() is that in the worst case it +will copy the whole input frame before you change it all over again with your +filter: if the frame is not writable, av_frame_make_writable() will allocate +new buffers, and copy the input frame data. You don't want that, and you can +avoid it by just allocating a new buffer if necessary, and process from in to +out in your filter, saving the memcpy. Generally, this is done following this +scheme: + + int direct = 0; + AVFrame *out; + + if (av_frame_is_writable(in)) { + direct = 1; + out = in; + } else { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + // out->data[...] = foobar(in->data[...]) + + if (!direct) + av_frame_free(&in); + return ff_filter_frame(outlink, out); + +Of course, this will only work if you can do in-place processing. To test if +your filter handles well the permissions, you can use the perms filter. For +example with: + + -vf perms=random,foobar + +Make sure no automatic pixel conversion is inserted between perms and foobar, +otherwise the frames permissions might change again and the test will be +meaningless: add av_log(0,0,"direct=%d\n",direct) in your code to check that. +You can avoid the issue with something like: + + -vf format=rgb24,perms=random,foobar + +...assuming your filter accepts rgb24 of course. This will make sure the +necessary conversion is inserted before the perms filter. + +Timeline +~~~~~~~~ + +Adding timeline support +(http://ffmpeg.org/ffmpeg-filters.html#Timeline-editing) is often an easy +feature to add. In the most simple case, you just have to add +AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC to the AVFilter.flags. You can typically +do this when your filter does not need to save the previous context frames, or +basically if your filter just alter whatever goes in and doesn't need +previous/future information. See for instance commit 86cb986ce that adds +timeline support to the fieldorder filter. + +In some cases, you might need to reset your context somehow. This is handled by +the AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL flag which is used if the filter +must not process the frames but still wants to keep track of the frames going +through (to keep them in cache for when it's enabled again). See for example +commit 69d72140a that adds timeline support to the phase filter. + +Threading +~~~~~~~~~ + +libavfilter does not yet support frame threading, but you can add slice +threading to your filters. + +Let's say the foobar filter has the following frame processing function: + + dst = out->data[0]; + src = in ->data[0]; + + for (y = 0; y < inlink->h; y++) { + for (x = 0; x < inlink->w; x++) + dst[x] = foobar(src[x]); + dst += out->linesize[0]; + src += in ->linesize[0]; + } + +The first thing is to make this function work into slices. The new code will +look like this: + + for (y = slice_start; y < slice_end; y++) { + for (x = 0; x < inlink->w; x++) + dst[x] = foobar(src[x]); + dst += out->linesize[0]; + src += in ->linesize[0]; + } + +The source and destination pointers, and slice_start/slice_end will be defined +according to the number of jobs. Generally, it looks like this: + + const int slice_start = (in->height * jobnr ) / nb_jobs; + const int slice_end = (in->height * (jobnr+1)) / nb_jobs; + uint8_t *dst = out->data[0] + slice_start * out->linesize[0]; + const uint8_t *src = in->data[0] + slice_start * in->linesize[0]; + +This new code will be isolated in a new filter_slice(): + + static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ... } + +Note that we need our input and output frame to define slice_{start,end} and +dst/src, which are not available in that callback. They will be transmitted +through the opaque void *arg. You have to define a structure which contains +everything you need: + + typedef struct ThreadData { + AVFrame *in, *out; + } ThreadData; + +If you need some more information from your local context, put them here. + +In you filter_slice function, you access it like that: + + const ThreadData *td = arg; + +Then in your filter_frame() callback, you need to call the threading +distributor with something like this: + + ThreadData td; + + // ... + + td.in = in; + td.out = out; + ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(outlink->h, ctx->graph->nb_threads)); + + // ... + + return ff_filter_frame(outlink, out); + +Last step is to add AVFILTER_FLAG_SLICE_THREADS flag to AVFilter.flags. + +For more example of slice threading additions, you can try to run git log -p +--grep 'slice threading' libavfilter/ + +Finalization +~~~~~~~~~~~~ + +When your awesome filter is finished, you have a few more steps before you're +done: + + - write its documentation in doc/filters.texi, and test the output with make + doc/ffmpeg-filters.html. + - add a FATE test, generally by adding an entry in + tests/fate/filter-video.mak, add running make fate-filter-foobar GEN=1 to + generate the data. + - add an entry in the Changelog + - edit libavfilter/version.h and increase LIBAVFILTER_VERSION_MINOR by one + (and reset LIBAVFILTER_VERSION_MICRO to 100) + - git add ... && git commit -m "avfilter: add foobar filter." && git format-patch -1 + +When all of this is done, you can submit your patch to the ffmpeg-devel +mailing-list for review. If you need any help, feel free to come on our IRC +channel, #ffmpeg-devel on irc.freenode.net. diff --git a/ffmpeg.c b/ffmpeg.c index a906186b1..1c1a5599d 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -59,6 +59,7 @@ #include "libavutil/timestamp.h" #include "libavutil/bprint.h" #include "libavutil/time.h" +#include "libavutil/threadmessage.h" #include "libavformat/os_support.h" #include "libavformat/ffm.h" // not public API @@ -123,11 +124,6 @@ static int64_t getutime(void); static int64_t getmaxrss(void); static int run_as_daemon = 0; -static int64_t video_size = 0; -static int64_t audio_size = 0; -static int64_t data_size = 0; -static int64_t subtitle_size = 0; -static int64_t extra_size = 0; static int nb_frames_dup = 0; static int nb_frames_drop = 0; static int64_t decode_error_stat[2]; @@ -137,11 +133,6 @@ AVIOContext *progress_avio = NULL; static uint8_t *subtitle_out; -#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 "ffmpeg2pass" InputStream **input_streams = NULL; @@ -241,9 +232,9 @@ static void sub2video_update(InputStream *ist, AVSubtitle *sub) if (!frame) return; if (sub) { - pts = av_rescale_q(sub->pts + sub->start_display_time * 1000, + pts = av_rescale_q(sub->pts + sub->start_display_time * 1000LL, AV_TIME_BASE_Q, ist->st->time_base); - end_pts = av_rescale_q(sub->pts + sub->end_display_time * 1000, + end_pts = av_rescale_q(sub->pts + sub->end_display_time * 1000LL, AV_TIME_BASE_Q, ist->st->time_base); num_rects = sub->num_rects; } else { @@ -252,7 +243,7 @@ static void sub2video_update(InputStream *ist, AVSubtitle *sub) num_rects = 0; } if (sub2video_get_blank_frame(ist) < 0) { - av_log(ist->st->codec, AV_LOG_ERROR, + av_log(ist->dec_ctx, AV_LOG_ERROR, "Impossible to get a blank canvas.\n"); return; } @@ -279,7 +270,7 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts) if (!ist2->sub2video.frame) continue; /* subtitles seem to be usually muxed ahead of other streams; - if not, substracting a larger time here is necessary */ + if not, subtracting a larger time here is necessary */ pts2 = av_rescale_q(pts, ist->st->time_base, ist2->st->time_base) - 1; /* do not send the heartbeat frame if the subtitle is already ahead */ if (pts2 <= ist2->sub2video.last_pts) @@ -297,23 +288,31 @@ static void sub2video_flush(InputStream *ist) { int i; + if (ist->sub2video.end_pts < INT64_MAX) + sub2video_update(ist, NULL); for (i = 0; i < ist->nb_filters; i++) av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0); } /* end of sub2video hack */ -void term_exit(void) +static void term_exit_sigsafe(void) { - av_log(NULL, AV_LOG_QUIET, "%s", ""); #if HAVE_TERMIOS_H if(restore_tty) tcsetattr (0, TCSANOW, &oldtty); #endif } +void term_exit(void) +{ + av_log(NULL, AV_LOG_QUIET, "%s", ""); + term_exit_sigsafe(); +} + static volatile int received_sigterm = 0; static volatile int received_nb_signals = 0; +static volatile int transcode_init_done = 0; static int main_return_code = 0; static void @@ -321,7 +320,7 @@ sigterm_handler(int sig) { received_sigterm = sig; received_nb_signals++; - term_exit(); + term_exit_sigsafe(); if(received_nb_signals > 3) exit(123); } @@ -420,7 +419,7 @@ static int read_key(void) static int decode_interrupt_cb(void *ctx) { - return received_nb_signals > 1; + return received_nb_signals > transcode_init_done; } const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL }; @@ -435,18 +434,20 @@ static void ffmpeg_cleanup(int ret) } for (i = 0; i < nb_filtergraphs; i++) { - avfilter_graph_free(&filtergraphs[i]->graph); - for (j = 0; j < filtergraphs[i]->nb_inputs; j++) { - av_freep(&filtergraphs[i]->inputs[j]->name); - av_freep(&filtergraphs[i]->inputs[j]); + FilterGraph *fg = filtergraphs[i]; + avfilter_graph_free(&fg->graph); + for (j = 0; j < fg->nb_inputs; j++) { + av_freep(&fg->inputs[j]->name); + av_freep(&fg->inputs[j]); } - av_freep(&filtergraphs[i]->inputs); - for (j = 0; j < filtergraphs[i]->nb_outputs; j++) { - av_freep(&filtergraphs[i]->outputs[j]->name); - av_freep(&filtergraphs[i]->outputs[j]); + av_freep(&fg->inputs); + for (j = 0; j < fg->nb_outputs; j++) { + av_freep(&fg->outputs[j]->name); + av_freep(&fg->outputs[j]); } - av_freep(&filtergraphs[i]->outputs); - av_freep(&filtergraphs[i]->graph_desc); + av_freep(&fg->outputs); + av_freep(&fg->graph_desc); + av_freep(&filtergraphs[i]); } av_freep(&filtergraphs); @@ -455,29 +456,35 @@ static void ffmpeg_cleanup(int ret) /* close files */ for (i = 0; i < nb_output_files; i++) { - AVFormatContext *s = output_files[i]->ctx; + OutputFile *of = output_files[i]; + AVFormatContext *s = of->ctx; if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE) && s->pb) avio_close(s->pb); avformat_free_context(s); - av_dict_free(&output_files[i]->opts); + av_dict_free(&of->opts); + av_freep(&output_files[i]); } for (i = 0; i < nb_output_streams; i++) { - AVBitStreamFilterContext *bsfc = output_streams[i]->bitstream_filters; + OutputStream *ost = output_streams[i]; + AVBitStreamFilterContext *bsfc = ost->bitstream_filters; while (bsfc) { AVBitStreamFilterContext *next = bsfc->next; av_bitstream_filter_close(bsfc); bsfc = next; } - output_streams[i]->bitstream_filters = NULL; - av_frame_free(&output_streams[i]->filtered_frame); + ost->bitstream_filters = NULL; + av_frame_free(&ost->filtered_frame); - av_parser_close(output_streams[i]->parser); + av_parser_close(ost->parser); + + av_freep(&ost->forced_keyframes); + av_expr_free(ost->forced_keyframes_pexpr); + av_freep(&ost->avfilter); + av_freep(&ost->logfile_prefix); + + avcodec_free_context(&ost->enc_ctx); - av_freep(&output_streams[i]->forced_keyframes); - av_expr_free(output_streams[i]->forced_keyframes_pexpr); - av_freep(&output_streams[i]->avfilter); - av_freep(&output_streams[i]->logfile_prefix); av_freep(&output_streams[i]); } #if HAVE_PTHREADS @@ -488,13 +495,18 @@ static void ffmpeg_cleanup(int ret) av_freep(&input_files[i]); } for (i = 0; i < nb_input_streams; i++) { - av_frame_free(&input_streams[i]->decoded_frame); - av_frame_free(&input_streams[i]->filter_frame); - av_dict_free(&input_streams[i]->opts); - avsubtitle_free(&input_streams[i]->prev_sub.subtitle); - av_frame_free(&input_streams[i]->sub2video.frame); - av_freep(&input_streams[i]->filters); - av_freep(&input_streams[i]->hwaccel_device); + InputStream *ist = input_streams[i]; + + av_frame_free(&ist->decoded_frame); + av_frame_free(&ist->filter_frame); + av_dict_free(&ist->decoder_opts); + avsubtitle_free(&ist->prev_sub.subtitle); + av_frame_free(&ist->sub2video.frame); + av_freep(&ist->filters); + av_freep(&ist->hwaccel_device); + + avcodec_free_context(&ist->dec_ctx); + av_freep(&input_streams[i]); } @@ -514,7 +526,7 @@ static void ffmpeg_cleanup(int ret) if (received_sigterm) { av_log(NULL, AV_LOG_INFO, "Received signal %d: terminating.\n", (int) received_sigterm); - } else if (ret) { + } else if (ret && transcode_init_done) { av_log(NULL, AV_LOG_INFO, "Conversion failed!\n"); } term_exit(); @@ -585,6 +597,9 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) ost->frame_number++; } + if (bsfc) + av_packet_split_side_data(pkt); + while (bsfc) { AVPacket new_pkt = *pkt; int a = av_bitstream_filter_filter(bsfc, avctx, NULL, @@ -656,12 +671,15 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) } ost->last_mux_dts = pkt->dts; + ost->data_size += pkt->size; + ost->packets_written++; + pkt->stream_index = ost->index; if (debug_ts) { av_log(NULL, AV_LOG_INFO, "muxer <- type:%s " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s size:%d\n", - av_get_media_type_string(ost->st->codec->codec_type), + av_get_media_type_string(ost->enc_ctx->codec_type), av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base), av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base), pkt->size @@ -674,6 +692,7 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) main_return_code = 1; close_all_output_streams(ost, MUXER_FINISHED | ENCODER_FINISHED, ENCODER_FINISHED); } + av_free_packet(pkt); } static void close_output_stream(OutputStream *ost) @@ -682,7 +701,7 @@ static void close_output_stream(OutputStream *ost) ost->finished |= ENCODER_FINISHED; if (of->shortest) { - int64_t end = av_rescale_q(ost->sync_opts - ost->first_pts, ost->st->codec->time_base, AV_TIME_BASE_Q); + int64_t end = av_rescale_q(ost->sync_opts - ost->first_pts, ost->enc_ctx->time_base, AV_TIME_BASE_Q); of->recording_time = FFMIN(of->recording_time, end); } } @@ -692,7 +711,7 @@ static int check_recording_time(OutputStream *ost) OutputFile *of = output_files[ost->file_index]; if (of->recording_time != INT64_MAX && - av_compare_ts(ost->sync_opts - ost->first_pts, ost->st->codec->time_base, of->recording_time, + av_compare_ts(ost->sync_opts - ost->first_pts, ost->enc_ctx->time_base, of->recording_time, AV_TIME_BASE_Q) >= 0) { close_output_stream(ost); return 0; @@ -703,7 +722,7 @@ static int check_recording_time(OutputStream *ost) static void do_audio_out(AVFormatContext *s, OutputStream *ost, AVFrame *frame) { - AVCodecContext *enc = ost->st->codec; + AVCodecContext *enc = ost->enc_ctx; AVPacket pkt; int got_packet = 0; @@ -717,6 +736,8 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, if (frame->pts == AV_NOPTS_VALUE || audio_sync_method < 0) frame->pts = ost->sync_opts; ost->sync_opts = frame->pts + frame->nb_samples; + ost->samples_encoded += frame->nb_samples; + ost->frames_encoded++; av_assert0(pkt.size || !pkt.data); update_benchmark(NULL); @@ -726,6 +747,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base), enc->time_base.num, enc->time_base.den); } + if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) { av_log(NULL, AV_LOG_FATAL, "Audio encoding failed (avcodec_encode_audio2)\n"); exit_program(1); @@ -733,12 +755,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, update_benchmark("encode_audio %d.%d", ost->file_index, ost->index); if (got_packet) { - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base); - if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base); - if (pkt.duration > 0) - pkt.duration = av_rescale_q(pkt.duration, enc->time_base, ost->st->time_base); + av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:audio " @@ -747,10 +764,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base)); } - audio_size += pkt.size; write_frame(s, &pkt, ost); - - av_free_packet(&pkt); } } @@ -772,7 +786,7 @@ static void do_subtitle_out(AVFormatContext *s, return; } - enc = ost->st->codec; + enc = ost->enc_ctx; if (!subtitle_out) { subtitle_out = av_malloc(subtitle_out_max_size); @@ -791,6 +805,8 @@ static void do_subtitle_out(AVFormatContext *s, if (output_files[ost->file_index]->start_time != AV_NOPTS_VALUE) pts -= output_files[ost->file_index]->start_time; for (i = 0; i < nb; i++) { + unsigned save_num_rects = sub->num_rects; + ost->sync_opts = av_rescale_q(pts, AV_TIME_BASE_Q, enc->time_base); if (!check_recording_time(ost)) return; @@ -802,8 +818,13 @@ static void do_subtitle_out(AVFormatContext *s, sub->start_display_time = 0; if (i == 1) sub->num_rects = 0; + + ost->frames_encoded++; + subtitle_out_size = avcodec_encode_subtitle(enc, subtitle_out, subtitle_out_max_size, sub); + if (i == 1) + sub->num_rects = save_num_rects; if (subtitle_out_size < 0) { av_log(NULL, AV_LOG_FATAL, "Subtitle encoding failed\n"); exit_program(1); @@ -822,7 +843,7 @@ static void do_subtitle_out(AVFormatContext *s, else pkt.pts += 90 * sub->end_display_time; } - subtitle_size += pkt.size; + pkt.dts = pkt.pts; write_frame(s, &pkt, ost); } } @@ -833,7 +854,8 @@ static void do_video_out(AVFormatContext *s, { int ret, format_video_sync; AVPacket pkt; - AVCodecContext *enc = ost->st->codec; + AVCodecContext *enc = ost->enc_ctx; + AVCodecContext *mux_enc = ost->st->codec; int nb_frames, i; double sync_ipts, delta; double duration = 0; @@ -900,7 +922,9 @@ static void do_video_out(AVFormatContext *s, nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number); if (nb_frames == 0) { nb_frames_drop++; - av_log(NULL, AV_LOG_VERBOSE, "*** drop!\n"); + av_log(NULL, AV_LOG_VERBOSE, + "*** dropping frame %d from stream %d at ts %"PRId64"\n", + ost->frame_number, ost->st->index, in_picture->pts); return; } else if (nb_frames > 1) { if (nb_frames > dts_error_threshold * 30) { @@ -932,36 +956,35 @@ static void do_video_out(AVFormatContext *s, /* 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; - if (enc->coded_frame->interlaced_frame) - enc->field_order = enc->coded_frame->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; + mux_enc->coded_frame->interlaced_frame = in_picture->interlaced_frame; + mux_enc->coded_frame->top_field_first = in_picture->top_field_first; + if (mux_enc->coded_frame->interlaced_frame) + mux_enc->field_order = mux_enc->coded_frame->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; else - enc->field_order = AV_FIELD_PROGRESSIVE; + mux_enc->field_order = AV_FIELD_PROGRESSIVE; 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; - video_size += pkt.size; write_frame(s, &pkt, ost); } else { int got_packet, forced_keyframe = 0; double pts_time; - if (ost->st->codec->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME) && + 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; if (in_picture->interlaced_frame) { if (enc->codec->id == AV_CODEC_ID_MJPEG) - enc->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; + mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; else - enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; + mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; } else - enc->field_order = AV_FIELD_PROGRESSIVE; + mux_enc->field_order = AV_FIELD_PROGRESSIVE; - in_picture->quality = ost->st->codec->global_quality; + in_picture->quality = enc->global_quality; if (!enc->me_threshold) in_picture->pict_type = 0; @@ -994,6 +1017,7 @@ static void do_video_out(AVFormatContext *s, ost->forced_keyframes_expr_const_values[FKF_N] += 1; } + if (forced_keyframe) { in_picture->pict_type = AV_PICTURE_TYPE_I; av_log(NULL, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time); @@ -1007,6 +1031,8 @@ static void do_video_out(AVFormatContext *s, enc->time_base.num, enc->time_base.den); } + ost->frames_encoded++; + ret = avcodec_encode_video2(enc, &pkt, in_picture, &got_packet); update_benchmark("encode_video %d.%d", ost->file_index, ost->index); if (ret < 0) { @@ -1025,10 +1051,7 @@ static void do_video_out(AVFormatContext *s, if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & CODEC_CAP_DELAY)) pkt.pts = ost->sync_opts; - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base); - if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base); + av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:video " @@ -1038,9 +1061,7 @@ static void do_video_out(AVFormatContext *s, } frame_size = pkt.size; - video_size += pkt.size; write_frame(s, &pkt, ost); - av_free_packet(&pkt); /* if two pass, output log */ if (ost->logfile && enc->stats_out) { @@ -1081,7 +1102,7 @@ static void do_video_stats(OutputStream *ost, int frame_size) } } - enc = ost->st->codec; + enc = ost->enc_ctx; if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { frame_number = ost->st->nb_frames; fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, enc->coded_frame->quality / (float)FF_QP2LAMBDA); @@ -1090,14 +1111,14 @@ static void do_video_stats(OutputStream *ost, int frame_size) fprintf(vstats_file,"f_size= %6d ", frame_size); /* compute pts value */ - ti1 = ost->st->pts.val * av_q2d(enc->time_base); + ti1 = av_stream_get_end_pts(ost->st) * av_q2d(ost->st->time_base); if (ti1 < 0.01) ti1 = 0.01; bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0; - avg_bitrate = (double)(video_size * 8) / ti1 / 1000.0; + 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)video_size / 1024, ti1, bitrate, avg_bitrate); + (double)ost->data_size / 1024, ti1, bitrate, avg_bitrate); fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(enc->coded_frame->pict_type)); } } @@ -1132,7 +1153,7 @@ static int reap_filters(void) OutputStream *ost = output_streams[i]; OutputFile *of = output_files[ost->file_index]; AVFilterContext *filter; - AVCodecContext *enc = ost->st->codec; + AVCodecContext *enc = ost->enc_ctx; int ret = 0; if (!ost->filter) @@ -1204,6 +1225,115 @@ static int reap_filters(void) return 0; } +static void print_final_stats(int64_t total_size) +{ + uint64_t video_size = 0, audio_size = 0, extra_size = 0, other_size = 0; + uint64_t subtitle_size = 0; + uint64_t data_size = 0; + float percent = -1.0; + int i, j; + + for (i = 0; i < nb_output_streams; i++) { + OutputStream *ost = output_streams[i]; + switch (ost->enc_ctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: video_size += ost->data_size; break; + case AVMEDIA_TYPE_AUDIO: audio_size += ost->data_size; break; + case AVMEDIA_TYPE_SUBTITLE: subtitle_size += ost->data_size; break; + default: other_size += ost->data_size; break; + } + extra_size += ost->enc_ctx->extradata_size; + data_size += ost->data_size; + } + + if (data_size && total_size>0 && total_size >= data_size) + percent = 100.0 * (total_size - data_size) / data_size; + + av_log(NULL, AV_LOG_INFO, "\n"); + av_log(NULL, AV_LOG_INFO, "video:%1.0fkB audio:%1.0fkB subtitle:%1.0fkB other streams:%1.0fkB global headers:%1.0fkB muxing overhead: ", + video_size / 1024.0, + audio_size / 1024.0, + subtitle_size / 1024.0, + other_size / 1024.0, + extra_size / 1024.0); + if (percent >= 0.0) + av_log(NULL, AV_LOG_INFO, "%f%%", percent); + else + av_log(NULL, AV_LOG_INFO, "unknown"); + av_log(NULL, AV_LOG_INFO, "\n"); + + /* print verbose per-stream stats */ + for (i = 0; i < nb_input_files; i++) { + InputFile *f = input_files[i]; + uint64_t total_packets = 0, total_size = 0; + + av_log(NULL, AV_LOG_VERBOSE, "Input file #%d (%s):\n", + i, f->ctx->filename); + + for (j = 0; j < f->nb_streams; j++) { + InputStream *ist = input_streams[f->ist_index + j]; + enum AVMediaType type = ist->dec_ctx->codec_type; + + total_size += ist->data_size; + total_packets += ist->nb_packets; + + av_log(NULL, AV_LOG_VERBOSE, " Input stream #%d:%d (%s): ", + i, j, media_type_string(type)); + av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets read (%"PRIu64" bytes); ", + ist->nb_packets, ist->data_size); + + if (ist->decoding_needed) { + av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames decoded", + ist->frames_decoded); + if (type == AVMEDIA_TYPE_AUDIO) + av_log(NULL, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ist->samples_decoded); + av_log(NULL, AV_LOG_VERBOSE, "; "); + } + + av_log(NULL, AV_LOG_VERBOSE, "\n"); + } + + av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) demuxed\n", + total_packets, total_size); + } + + for (i = 0; i < nb_output_files; i++) { + OutputFile *of = output_files[i]; + uint64_t total_packets = 0, total_size = 0; + + av_log(NULL, AV_LOG_VERBOSE, "Output file #%d (%s):\n", + i, of->ctx->filename); + + for (j = 0; j < of->ctx->nb_streams; j++) { + OutputStream *ost = output_streams[of->ost_index + j]; + enum AVMediaType type = ost->enc_ctx->codec_type; + + total_size += ost->data_size; + total_packets += ost->packets_written; + + av_log(NULL, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", + i, j, media_type_string(type)); + if (ost->encoding_needed) { + av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", + ost->frames_encoded); + if (type == AVMEDIA_TYPE_AUDIO) + av_log(NULL, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->samples_encoded); + av_log(NULL, AV_LOG_VERBOSE, "; "); + } + + av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ", + ost->packets_written, ost->data_size); + + av_log(NULL, AV_LOG_VERBOSE, "\n"); + } + + av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n", + total_packets, total_size); + } + if(video_size + data_size + audio_size + subtitle_size + extra_size == 0){ + av_log(NULL, AV_LOG_WARNING, "Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)\n"); + } +} + static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time) { char buf[1024]; @@ -1245,7 +1375,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti for (i = 0; i < nb_output_streams; i++) { float q = -1; ost = output_streams[i]; - enc = ost->st->codec; + enc = ost->enc_ctx; if (!ost->stream_copy && enc->coded_frame) q = enc->coded_frame->quality / (float)FF_QP2LAMBDA; if (vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -1306,8 +1436,8 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti vid = 1; } /* compute min output value */ - if ((is_last_report || !ost->finished) && ost->st->pts.val != AV_NOPTS_VALUE) - pts = FFMAX(pts, av_rescale_q(ost->st->pts.val, + if (av_stream_get_end_pts(ost->st) != AV_NOPTS_VALUE) + pts = FFMAX(pts, av_rescale_q(av_stream_get_end_pts(ost->st), ost->st->time_base, AV_TIME_BASE_Q)); } @@ -1365,25 +1495,8 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti } } - if (is_last_report) { - int64_t raw = audio_size + video_size + data_size + subtitle_size + extra_size; - float percent = 0.0; - - if (raw) - percent = 100.0 * (total_size - raw) / raw; - - av_log(NULL, AV_LOG_INFO, "\n"); - av_log(NULL, AV_LOG_INFO, "video:%1.0fkB audio:%1.0fkB subtitle:%1.0f data:%1.0f global headers:%1.0fkB muxing overhead %f%%\n", - video_size / 1024.0, - audio_size / 1024.0, - subtitle_size / 1024.0, - data_size / 1024.0, - extra_size / 1024.0, - percent); - if(video_size + data_size + audio_size + subtitle_size + extra_size == 0){ - av_log(NULL, AV_LOG_WARNING, "Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)\n"); - } - } + if (is_last_report) + print_final_stats(total_size); } static void flush_encoders(void) @@ -1392,33 +1505,30 @@ static void flush_encoders(void) for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; - AVCodecContext *enc = ost->st->codec; + AVCodecContext *enc = ost->enc_ctx; AVFormatContext *os = output_files[ost->file_index]->ctx; int stop_encoding = 0; if (!ost->encoding_needed) continue; - if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1) + if (enc->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1) continue; - if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == AV_CODEC_ID_RAWVIDEO) + if (enc->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == AV_CODEC_ID_RAWVIDEO) continue; for (;;) { int (*encode)(AVCodecContext*, AVPacket*, const AVFrame*, int*) = NULL; const char *desc; - int64_t *size; - switch (ost->st->codec->codec_type) { + switch (enc->codec_type) { case AVMEDIA_TYPE_AUDIO: encode = avcodec_encode_audio2; desc = "Audio"; - size = &audio_size; break; case AVMEDIA_TYPE_VIDEO: encode = avcodec_encode_video2; desc = "Video"; - size = &video_size; break; default: stop_encoding = 1; @@ -1450,16 +1560,10 @@ static void flush_encoders(void) av_free_packet(&pkt); continue; } - *size += pkt.size; - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base); - if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base); - if (pkt.duration > 0) - pkt.duration = av_rescale_q(pkt.duration, enc->time_base, ost->st->time_base); + av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base); pkt_size = pkt.size; write_frame(os, &pkt, ost); - if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) { + if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) { do_video_stats(ost, pkt_size); } } @@ -1533,16 +1637,8 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p } /* force the input stream PTS */ - if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) - audio_size += pkt->size; - else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - video_size += pkt->size; + if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) ost->sync_opts++; - } else if (ost->st->codec->codec_type == AVMEDIA_TYPE_DATA) { - data_size += pkt->size; - } else if (ost->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { - subtitle_size += pkt->size; - } 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; @@ -1556,11 +1652,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt.dts -= ost_tb_start_time; if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) { - int duration = av_get_audio_frame_duration(ist->st->codec, pkt->size); + int duration = av_get_audio_frame_duration(ist->dec_ctx, pkt->size); if(!duration) - duration = ist->st->codec->frame_size; + duration = ist->dec_ctx->frame_size; opkt.dts = opkt.pts = av_rescale_delta(ist->st->time_base, pkt->dts, - (AVRational){1, ist->st->codec->sample_rate}, duration, &ist->filter_in_rescale_delta_last, + (AVRational){1, ist->dec_ctx->sample_rate}, duration, &ist->filter_in_rescale_delta_last, ost->st->time_base) - ost_tb_start_time; } @@ -1568,10 +1664,10 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt.flags = pkt->flags; // FIXME remove the following 2 lines they shall be replaced by the bitstream filters - if ( ost->st->codec->codec_id != AV_CODEC_ID_H264 - && ost->st->codec->codec_id != AV_CODEC_ID_MPEG1VIDEO - && ost->st->codec->codec_id != AV_CODEC_ID_MPEG2VIDEO - && ost->st->codec->codec_id != AV_CODEC_ID_VC1 + if ( ost->enc_ctx->codec_id != AV_CODEC_ID_H264 + && ost->enc_ctx->codec_id != AV_CODEC_ID_MPEG1VIDEO + && 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, &opkt.data, &opkt.size, @@ -1596,12 +1692,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p } write_frame(of->ctx, &opkt, ost); - ost->st->codec->frame_number++; } int guess_input_channel_layout(InputStream *ist) { - AVCodecContext *dec = ist->st->codec; + AVCodecContext *dec = ist->dec_ctx; if (!dec->channel_layout) { char layout_name[256]; @@ -1622,7 +1717,7 @@ int guess_input_channel_layout(InputStream *ist) static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) { AVFrame *decoded_frame, *f; - AVCodecContext *avctx = ist->st->codec; + AVCodecContext *avctx = ist->dec_ctx; int i, ret, err = 0, resample_changed; AVRational decoded_frame_tb; @@ -1656,6 +1751,9 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) return ret; } + ist->samples_decoded += decoded_frame->nb_samples; + ist->frames_decoded++; + #if 1 /* increment next_dts to use for the case where the input stream does not have timestamps or there are multiple frames in the packet */ @@ -1711,7 +1809,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) if (ost->enc->type == AVMEDIA_TYPE_AUDIO && !(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) av_buffersink_set_frame_size(ost->filter->filter, - ost->st->codec->frame_size); + ost->enc_ctx->frame_size); } } } @@ -1723,20 +1821,19 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) decoded_frame_tb = avctx->time_base; } else if (decoded_frame->pkt_pts != AV_NOPTS_VALUE) { decoded_frame->pts = decoded_frame->pkt_pts; - pkt->pts = AV_NOPTS_VALUE; decoded_frame_tb = ist->st->time_base; } else if (pkt->pts != AV_NOPTS_VALUE) { decoded_frame->pts = pkt->pts; - pkt->pts = AV_NOPTS_VALUE; decoded_frame_tb = ist->st->time_base; }else { decoded_frame->pts = ist->dts; decoded_frame_tb = AV_TIME_BASE_Q; } + pkt->pts = AV_NOPTS_VALUE; if (decoded_frame->pts != AV_NOPTS_VALUE) decoded_frame->pts = av_rescale_delta(decoded_frame_tb, decoded_frame->pts, - (AVRational){1, ist->st->codec->sample_rate}, decoded_frame->nb_samples, &ist->filter_in_rescale_delta_last, - (AVRational){1, ist->st->codec->sample_rate}); + (AVRational){1, avctx->sample_rate}, decoded_frame->nb_samples, &ist->filter_in_rescale_delta_last, + (AVRational){1, avctx->sample_rate}); for (i = 0; i < ist->nb_filters; i++) { if (i < ist->nb_filters - 1) { f = ist->filter_frame; @@ -1774,10 +1871,24 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) pkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base); update_benchmark(NULL); - ret = avcodec_decode_video2(ist->st->codec, + ret = avcodec_decode_video2(ist->dec_ctx, decoded_frame, got_output, pkt); update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index); + // The following line may be required in some cases where there is no parser + // or the parser does not has_b_frames correctly + if (ist->st->codec->has_b_frames < ist->dec_ctx->has_b_frames) { + if (ist->dec_ctx->codec_id == AV_CODEC_ID_H264) { + ist->st->codec->has_b_frames = ist->dec_ctx->has_b_frames; + } else + av_log_ask_for_sample( + ist->dec_ctx, + "has_b_frames is larger in decoder than demuxer %d > %d ", + ist->dec_ctx->has_b_frames, + ist->st->codec->has_b_frames + ); + } + if (*got_output || ret<0 || pkt->size) decode_error_stat[ret<0] ++; @@ -1796,8 +1907,10 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) if(ist->top_field_first>=0) decoded_frame->top_field_first = ist->top_field_first; + ist->frames_decoded++; + if (ist->hwaccel_retrieve_data && decoded_frame->format == ist->hwaccel_pix_fmt) { - err = ist->hwaccel_retrieve_data(ist->st->codec, decoded_frame); + err = ist->hwaccel_retrieve_data(ist->dec_ctx, decoded_frame); if (err < 0) goto fail; } @@ -1877,7 +1990,7 @@ fail: static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) { AVSubtitle subtitle; - int i, ret = avcodec_decode_subtitle2(ist->st->codec, + int i, ret = avcodec_decode_subtitle2(ist->dec_ctx, &subtitle, got_output, pkt); if (*got_output || ret<0 || pkt->size) @@ -1895,7 +2008,7 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) end = av_rescale(subtitle.pts - ist->prev_sub.subtitle.pts, 1000, AV_TIME_BASE); if (end < ist->prev_sub.subtitle.end_display_time) { - av_log(ist->st->codec, AV_LOG_DEBUG, + av_log(ist->dec_ctx, AV_LOG_DEBUG, "Subtitle duration reduced from %d to %d%s\n", ist->prev_sub.subtitle.end_display_time, end, end <= 0 ? ", dropping it" : ""); @@ -1917,10 +2030,13 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) if (!subtitle.num_rects) goto out; + ist->frames_decoded++; + for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; - if (!check_output_constraints(ist, ost) || !ost->encoding_needed) + if (!check_output_constraints(ist, ost) || !ost->encoding_needed + || ost->enc->type != AVMEDIA_TYPE_SUBTITLE) continue; do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle); @@ -1939,7 +2055,7 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) AVPacket avpkt; if (!ist->saw_first_ts) { - ist->dts = ist->st->avg_frame_rate.num ? - ist->st->codec->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; + ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; ist->pts = 0; if (pkt != NULL && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) { ist->dts += av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q); @@ -1965,7 +2081,7 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) if (pkt->dts != AV_NOPTS_VALUE) { ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); - if (ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed) + if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed) ist->next_pts = ist->pts = ist->dts; } @@ -1977,13 +2093,14 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) ist->pts = ist->next_pts; ist->dts = ist->next_dts; - if (avpkt.size && avpkt.size != pkt->size) { + 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; } - switch (ist->st->codec->codec_type) { + switch (ist->dec_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: ret = decode_audio (ist, &avpkt, &got_output); break; @@ -1991,11 +2108,11 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) ret = decode_video (ist, &avpkt, &got_output); if (avpkt.duration) { duration = av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q); - } else if(ist->st->codec->time_base.num != 0 && ist->st->codec->time_base.den != 0) { - int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict+1 : ist->st->codec->ticks_per_frame; + } else if(ist->dec_ctx->time_base.num != 0 && ist->dec_ctx->time_base.den != 0) { + int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict+1 : ist->dec_ctx->ticks_per_frame; duration = ((int64_t)AV_TIME_BASE * - ist->st->codec->time_base.num * ticks) / - ist->st->codec->time_base.den; + ist->dec_ctx->time_base.num * ticks) / + ist->dec_ctx->time_base.den; } else duration = 0; @@ -2022,7 +2139,7 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) // touch data and size only if not EOF if (pkt) { - if(ist->st->codec->codec_type != AVMEDIA_TYPE_AUDIO) + if(ist->dec_ctx->codec_type != AVMEDIA_TYPE_AUDIO) ret = avpkt.size; avpkt.data += ret; avpkt.size -= ret; @@ -2030,15 +2147,17 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) if (!got_output) { continue; } + if (got_output && !pkt) + break; } /* handle stream copy */ if (!ist->decoding_needed) { ist->dts = ist->next_dts; - switch (ist->st->codec->codec_type) { + switch (ist->dec_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: - ist->next_dts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) / - ist->st->codec->sample_rate; + ist->next_dts += ((int64_t)AV_TIME_BASE * ist->dec_ctx->frame_size) / + ist->dec_ctx->sample_rate; break; case AVMEDIA_TYPE_VIDEO: if (ist->framerate.num) { @@ -2048,11 +2167,11 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); } else if (pkt->duration) { ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q); - } else if(ist->st->codec->time_base.num != 0) { - int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict + 1 : ist->st->codec->ticks_per_frame; + } else if(ist->dec_ctx->time_base.num != 0) { + int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict + 1 : ist->dec_ctx->ticks_per_frame; ist->next_dts += ((int64_t)AV_TIME_BASE * - ist->st->codec->time_base.num * ticks) / - ist->st->codec->time_base.den; + ist->dec_ctx->time_base.num * ticks) / + ist->dec_ctx->time_base.den; } break; } @@ -2068,14 +2187,14 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) do_streamcopy(ist, ost, pkt); } - return 0; + return got_output; } static void print_sdp(void) { char sdp[16384]; int i; - AVFormatContext **avc = av_malloc(sizeof(*avc) * nb_output_files); + AVFormatContext **avc = av_malloc_array(nb_output_files, sizeof(*avc)); if (!avc) exit_program(1); @@ -2154,20 +2273,22 @@ static int init_input_stream(int ist_index, char *error, int error_len) AVCodec *codec = ist->dec; if (!codec) { snprintf(error, error_len, "Decoder (codec %s) not found for input stream #%d:%d", - avcodec_get_name(ist->st->codec->codec_id), ist->file_index, ist->st->index); + avcodec_get_name(ist->dec_ctx->codec_id), ist->file_index, ist->st->index); return AVERROR(EINVAL); } - ist->st->codec->opaque = ist; - ist->st->codec->get_format = get_format; - ist->st->codec->get_buffer2 = get_buffer; - ist->st->codec->thread_safe_callbacks = 1; + ist->dec_ctx->opaque = ist; + ist->dec_ctx->get_format = get_format; + ist->dec_ctx->get_buffer2 = get_buffer; + ist->dec_ctx->thread_safe_callbacks = 1; - av_opt_set_int(ist->st->codec, "refcounted_frames", 1, 0); + av_opt_set_int(ist->dec_ctx, "refcounted_frames", 1, 0); + if(ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE) + av_dict_set(&ist->decoder_opts, "compute_edt", "1", 0); - if (!av_dict_get(ist->opts, "threads", NULL, 0)) - av_dict_set(&ist->opts, "threads", "auto", 0); - if ((ret = avcodec_open2(ist->st->codec, codec, &ist->opts)) < 0) { + if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0)) + av_dict_set(&ist->decoder_opts, "threads", "auto", 0); + if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) { if (ret == AVERROR_EXPERIMENTAL) abort_codec_experimental(codec, 0); @@ -2177,7 +2298,7 @@ static int init_input_stream(int ist_index, char *error, int error_len) ist->file_index, ist->st->index, av_err2str(ret)); return ret; } - assert_avoptions(ist->opts); + assert_avoptions(ist->decoder_opts); } ist->next_pts = AV_NOPTS_VALUE; @@ -2210,7 +2331,7 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost, if (*p == ',') n++; size = n; - pts = av_malloc(sizeof(*pts) * size); + pts = av_malloc_array(size, sizeof(*pts)); if (!pts) { av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n"); exit_program(1); @@ -2277,11 +2398,51 @@ static void report_new_stream(int input_index, AVPacket *pkt) file->nb_streams_warn = pkt->stream_index + 1; } +static void set_encoder_id(OutputFile *of, OutputStream *ost) +{ + AVDictionaryEntry *e; + + uint8_t *encoder_string; + int encoder_string_len; + int format_flags = 0; + int codec_flags = 0; + + if (av_dict_get(ost->st->metadata, "encoder", NULL, 0)) + return; + + e = av_dict_get(of->opts, "fflags", NULL, 0); + if (e) { + const AVOption *o = av_opt_find(of->ctx, "fflags", NULL, 0, 0); + if (!o) + return; + av_opt_eval_flags(of->ctx, o, e->value, &format_flags); + } + e = av_dict_get(ost->encoder_opts, "flags", NULL, 0); + if (e) { + const AVOption *o = av_opt_find(ost->enc_ctx, "flags", NULL, 0, 0); + if (!o) + return; + av_opt_eval_flags(ost->enc_ctx, o, e->value, &codec_flags); + } + + encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(ost->enc->name) + 2; + encoder_string = av_mallocz(encoder_string_len); + if (!encoder_string) + exit_program(1); + + if (!(format_flags & AVFMT_FLAG_BITEXACT) && !(codec_flags & CODEC_FLAG_BITEXACT)) + av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len); + else + av_strlcpy(encoder_string, "Lavc ", encoder_string_len); + av_strlcat(encoder_string, ost->enc->name, encoder_string_len); + av_dict_set(&ost->st->metadata, "encoder", encoder_string, + AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE); +} + static int transcode_init(void) { int ret = 0, i, j, k; AVFormatContext *oc; - AVCodecContext *codec; OutputStream *ost; InputStream *ist; char error[1024]; @@ -2307,7 +2468,7 @@ static int transcode_init(void) 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(); + input_streams[j + ifile->ist_index]->start = av_gettime_relative(); } /* output stream init */ @@ -2327,7 +2488,8 @@ static int transcode_init(void) /* for each output stream, we compute the right encoding parameters */ for (i = 0; i < nb_output_streams; i++) { - AVCodecContext *icodec = NULL; + AVCodecContext *enc_ctx; + AVCodecContext *dec_ctx = NULL; ost = output_streams[i]; oc = output_files[ost->file_index]->ctx; ist = get_input_stream(ost); @@ -2335,22 +2497,22 @@ static int transcode_init(void) if (ost->attachment_filename) continue; - codec = ost->st->codec; + enc_ctx = ost->enc_ctx; if (ist) { - icodec = ist->st->codec; + dec_ctx = ist->dec_ctx; ost->st->disposition = ist->st->disposition; - codec->bits_per_raw_sample = icodec->bits_per_raw_sample; - codec->chroma_sample_location = icodec->chroma_sample_location; + enc_ctx->bits_per_raw_sample = dec_ctx->bits_per_raw_sample; + enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location; } else { for (j=0; jnb_streams; j++) { AVStream *st = oc->streams[j]; - if (st != ost->st && st->codec->codec_type == codec->codec_type) + if (st != ost->st && st->codec->codec_type == enc_ctx->codec_type) break; } if (j == oc->nb_streams) - if (codec->codec_type == AVMEDIA_TYPE_AUDIO || codec->codec_type == AVMEDIA_TYPE_VIDEO) + if (enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO || enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) ost->st->disposition = AV_DISPOSITION_DEFAULT; } @@ -2360,37 +2522,37 @@ static int transcode_init(void) av_assert0(ist && !ost->filter); - extra_size = (uint64_t)icodec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE; + extra_size = (uint64_t)dec_ctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE; if (extra_size > INT_MAX) { return AVERROR(EINVAL); } /* if stream_copy is selected, no need to decode or encode */ - codec->codec_id = icodec->codec_id; - codec->codec_type = icodec->codec_type; + enc_ctx->codec_id = dec_ctx->codec_id; + enc_ctx->codec_type = dec_ctx->codec_type; - if (!codec->codec_tag) { + if (!enc_ctx->codec_tag) { unsigned int codec_tag; if (!oc->oformat->codec_tag || - av_codec_get_id (oc->oformat->codec_tag, icodec->codec_tag) == codec->codec_id || - !av_codec_get_tag2(oc->oformat->codec_tag, icodec->codec_id, &codec_tag)) - codec->codec_tag = icodec->codec_tag; + av_codec_get_id (oc->oformat->codec_tag, dec_ctx->codec_tag) == enc_ctx->codec_id || + !av_codec_get_tag2(oc->oformat->codec_tag, dec_ctx->codec_id, &codec_tag)) + enc_ctx->codec_tag = dec_ctx->codec_tag; } - codec->bit_rate = icodec->bit_rate; - codec->rc_max_rate = icodec->rc_max_rate; - codec->rc_buffer_size = icodec->rc_buffer_size; - codec->field_order = icodec->field_order; - codec->extradata = av_mallocz(extra_size); - if (!codec->extradata) { + 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) { return AVERROR(ENOMEM); } - memcpy(codec->extradata, icodec->extradata, icodec->extradata_size); - codec->extradata_size= icodec->extradata_size; - codec->bits_per_coded_sample = icodec->bits_per_coded_sample; + memcpy(enc_ctx->extradata, dec_ctx->extradata, dec_ctx->extradata_size); + enc_ctx->extradata_size= dec_ctx->extradata_size; + enc_ctx->bits_per_coded_sample = dec_ctx->bits_per_coded_sample; - codec->time_base = ist->st->time_base; + enc_ctx->time_base = ist->st->time_base; /* * Avi is a special case here because it supports variable fps but * having the fps and timebase differe significantly adds quite some @@ -2399,90 +2561,90 @@ static int transcode_init(void) if(!strcmp(oc->oformat->name, "avi")) { if ( copy_tb<0 && av_q2d(ist->st->r_frame_rate) >= av_q2d(ist->st->avg_frame_rate) && 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(ist->st->time_base) - && 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(icodec->time_base) - && av_q2d(ist->st->time_base) < 1.0/500 && av_q2d(icodec->time_base) < 1.0/500 + && 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(dec_ctx->time_base) + && av_q2d(ist->st->time_base) < 1.0/500 && av_q2d(dec_ctx->time_base) < 1.0/500 || copy_tb==2){ - codec->time_base.num = ist->st->r_frame_rate.den; - codec->time_base.den = 2*ist->st->r_frame_rate.num; - codec->ticks_per_frame = 2; - } else if ( copy_tb<0 && av_q2d(icodec->time_base)*icodec->ticks_per_frame > 2*av_q2d(ist->st->time_base) + enc_ctx->time_base.num = ist->st->r_frame_rate.den; + enc_ctx->time_base.den = 2*ist->st->r_frame_rate.num; + enc_ctx->ticks_per_frame = 2; + } else if ( copy_tb<0 && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > 2*av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/500 || copy_tb==0){ - codec->time_base = icodec->time_base; - codec->time_base.num *= icodec->ticks_per_frame; - codec->time_base.den *= 2; - codec->ticks_per_frame = 2; + enc_ctx->time_base = dec_ctx->time_base; + enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; + enc_ctx->time_base.den *= 2; + enc_ctx->ticks_per_frame = 2; } } else if(!(oc->oformat->flags & AVFMT_VARIABLE_FPS) && strcmp(oc->oformat->name, "mov") && strcmp(oc->oformat->name, "mp4") && strcmp(oc->oformat->name, "3gp") && strcmp(oc->oformat->name, "3g2") && strcmp(oc->oformat->name, "psp") && strcmp(oc->oformat->name, "ipod") && strcmp(oc->oformat->name, "f4v") ) { - if( copy_tb<0 && icodec->time_base.den - && av_q2d(icodec->time_base)*icodec->ticks_per_frame > av_q2d(ist->st->time_base) + if( copy_tb<0 && dec_ctx->time_base.den + && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/500 || copy_tb==0){ - codec->time_base = icodec->time_base; - codec->time_base.num *= icodec->ticks_per_frame; + enc_ctx->time_base = dec_ctx->time_base; + enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; } } - if ( codec->codec_tag == AV_RL32("tmcd") - && icodec->time_base.num < icodec->time_base.den - && icodec->time_base.num > 0 - && 121LL*icodec->time_base.num > icodec->time_base.den) { - codec->time_base = icodec->time_base; + if ( enc_ctx->codec_tag == AV_RL32("tmcd") + && dec_ctx->time_base.num < dec_ctx->time_base.den + && dec_ctx->time_base.num > 0 + && 121LL*dec_ctx->time_base.num > dec_ctx->time_base.den) { + enc_ctx->time_base = dec_ctx->time_base; } if (ist && !ost->frame_rate.num) ost->frame_rate = ist->framerate; if(ost->frame_rate.num) - codec->time_base = av_inv_q(ost->frame_rate); + enc_ctx->time_base = av_inv_q(ost->frame_rate); - av_reduce(&codec->time_base.num, &codec->time_base.den, - codec->time_base.num, codec->time_base.den, INT_MAX); + av_reduce(&enc_ctx->time_base.num, &enc_ctx->time_base.den, + enc_ctx->time_base.num, enc_ctx->time_base.den, INT_MAX); - ost->parser = av_parser_init(codec->codec_id); + ost->parser = av_parser_init(enc_ctx->codec_id); - switch (codec->codec_type) { + 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); } - codec->channel_layout = icodec->channel_layout; - codec->sample_rate = icodec->sample_rate; - codec->channels = icodec->channels; - codec->frame_size = icodec->frame_size; - codec->audio_service_type = icodec->audio_service_type; - codec->block_align = icodec->block_align; - codec->delay = icodec->delay; - if((codec->block_align == 1 || codec->block_align == 1152 || codec->block_align == 576) && codec->codec_id == AV_CODEC_ID_MP3) - codec->block_align= 0; - if(codec->codec_id == AV_CODEC_ID_AC3) - codec->block_align= 0; + 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; + enc_ctx->delay = dec_ctx->delay; + if((enc_ctx->block_align == 1 || enc_ctx->block_align == 1152 || enc_ctx->block_align == 576) && enc_ctx->codec_id == AV_CODEC_ID_MP3) + enc_ctx->block_align= 0; + if(enc_ctx->codec_id == AV_CODEC_ID_AC3) + enc_ctx->block_align= 0; break; case AVMEDIA_TYPE_VIDEO: - codec->pix_fmt = icodec->pix_fmt; - codec->width = icodec->width; - codec->height = icodec->height; - codec->has_b_frames = icodec->has_b_frames; + 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.num) { // overridden by the -aspect cli option sar = av_mul_q(ost->frame_aspect_ratio, - (AVRational){ codec->height, codec->width }); + (AVRational){ enc_ctx->height, enc_ctx->width }); av_log(NULL, AV_LOG_WARNING, "Overriding aspect ratio " "with stream copy may produce invalid files\n"); } else if (ist->st->sample_aspect_ratio.num) sar = ist->st->sample_aspect_ratio; else - sar = icodec->sample_aspect_ratio; - ost->st->sample_aspect_ratio = codec->sample_aspect_ratio = sar; + sar = dec_ctx->sample_aspect_ratio; + ost->st->sample_aspect_ratio = enc_ctx->sample_aspect_ratio = sar; ost->st->avg_frame_rate = ist->st->avg_frame_rate; break; case AVMEDIA_TYPE_SUBTITLE: - codec->width = icodec->width; - codec->height = icodec->height; + enc_ctx->width = dec_ctx->width; + enc_ctx->height = dec_ctx->height; break; case AVMEDIA_TYPE_DATA: case AVMEDIA_TYPE_ATTACHMENT: @@ -2492,7 +2654,7 @@ static int transcode_init(void) } } else { if (!ost->enc) - ost->enc = avcodec_find_encoder(codec->codec_id); + ost->enc = avcodec_find_encoder(enc_ctx->codec_id); if (!ost->enc) { /* should only happen when a default codec is not present. */ snprintf(error, sizeof(error), "Encoder (codec %s) not found for output stream #%d:%d", @@ -2505,9 +2667,11 @@ static int transcode_init(void) ist->decoding_needed++; ost->encoding_needed = 1; + set_encoder_id(output_files[ost->file_index], ost); + if (!ost->filter && - (codec->codec_type == AVMEDIA_TYPE_VIDEO || - codec->codec_type == AVMEDIA_TYPE_AUDIO)) { + (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)) { @@ -2516,7 +2680,7 @@ static int transcode_init(void) } } - if (codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { if (ost->filter && !ost->frame_rate.num) ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter); if (ist && !ost->frame_rate.num) @@ -2537,25 +2701,25 @@ static int transcode_init(void) int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates); ost->frame_rate = ost->enc->supported_framerates[idx]; } - if (codec->codec_id == AV_CODEC_ID_MPEG4) { + if (enc_ctx->codec_id == AV_CODEC_ID_MPEG4) { av_reduce(&ost->frame_rate.num, &ost->frame_rate.den, ost->frame_rate.num, ost->frame_rate.den, 65535); } } - switch (codec->codec_type) { + switch (enc_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: - codec->sample_fmt = ost->filter->filter->inputs[0]->format; - codec->sample_rate = ost->filter->filter->inputs[0]->sample_rate; - codec->channel_layout = ost->filter->filter->inputs[0]->channel_layout; - codec->channels = avfilter_link_get_channels(ost->filter->filter->inputs[0]); - codec->time_base = (AVRational){ 1, codec->sample_rate }; + 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 = avfilter_link_get_channels(ost->filter->filter->inputs[0]); + enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate }; break; case AVMEDIA_TYPE_VIDEO: - codec->time_base = av_inv_q(ost->frame_rate); - if (ost->filter && !(codec->time_base.num && codec->time_base.den)) - codec->time_base = ost->filter->filter->inputs[0]->time_base; - if ( av_q2d(codec->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH + enc_ctx->time_base = av_inv_q(ost->frame_rate); + if (ost->filter && !(enc_ctx->time_base.num && enc_ctx->time_base.den)) + enc_ctx->time_base = ost->filter->filter->inputs[0]->time_base; + if ( av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH && (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){ av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n" "Please consider specifying a lower framerate, a different muxer or -vsync 2\n"); @@ -2563,35 +2727,37 @@ static int transcode_init(void) for (j = 0; j < ost->forced_kf_count; j++) ost->forced_kf_pts[j] = av_rescale_q(ost->forced_kf_pts[j], AV_TIME_BASE_Q, - codec->time_base); + enc_ctx->time_base); - codec->width = ost->filter->filter->inputs[0]->w; - codec->height = ost->filter->filter->inputs[0]->h; - codec->sample_aspect_ratio = ost->st->sample_aspect_ratio = + 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.num ? // overridden by the -aspect cli option - av_mul_q(ost->frame_aspect_ratio, (AVRational){ codec->height, codec->width }) : + av_mul_q(ost->frame_aspect_ratio, (AVRational){ enc_ctx->height, enc_ctx->width }) : ost->filter->filter->inputs[0]->sample_aspect_ratio; if (!strncmp(ost->enc->name, "libx264", 7) && - codec->pix_fmt == AV_PIX_FMT_NONE && + enc_ctx->pix_fmt == AV_PIX_FMT_NONE && ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P) av_log(NULL, AV_LOG_WARNING, "No pixel format specified, %s for H.264 encoding chosen.\n" "Use -pix_fmt yuv420p for compatibility with outdated media players.\n", av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format)); if (!strncmp(ost->enc->name, "mpeg2video", 10) && - codec->pix_fmt == AV_PIX_FMT_NONE && + enc_ctx->pix_fmt == AV_PIX_FMT_NONE && ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P) av_log(NULL, AV_LOG_WARNING, "No pixel format specified, %s for MPEG-2 encoding chosen.\n" "Use -pix_fmt yuv420p for compatibility with outdated media players.\n", av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format)); - codec->pix_fmt = ost->filter->filter->inputs[0]->format; + enc_ctx->pix_fmt = ost->filter->filter->inputs[0]->format; - if (!icodec || - codec->width != icodec->width || - codec->height != icodec->height || - codec->pix_fmt != icodec->pix_fmt) { - codec->bits_per_raw_sample = frame_bits_per_raw_sample; + 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 = frame_bits_per_raw_sample; } if (ost->forced_keyframes) { @@ -2608,15 +2774,15 @@ static int transcode_init(void) ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N] = NAN; ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T] = NAN; } else { - parse_forced_key_frames(ost->forced_keyframes, ost, ost->st->codec); + parse_forced_key_frames(ost->forced_keyframes, ost, ost->enc_ctx); } } break; case AVMEDIA_TYPE_SUBTITLE: - codec->time_base = (AVRational){1, 1000}; - if (!codec->width) { - codec->width = input_streams[ost->source_index]->st->codec->width; - codec->height = input_streams[ost->source_index]->st->codec->height; + enc_ctx->time_base = (AVRational){1, 1000}; + if (!enc_ctx->width) { + enc_ctx->width = input_streams[ost->source_index]->st->codec->width; + enc_ctx->height = input_streams[ost->source_index]->st->codec->height; } break; default: @@ -2624,7 +2790,7 @@ static int transcode_init(void) break; } /* two pass mode */ - if (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2)) { + if (enc_ctx->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2)) { char logfilename[1024]; FILE *f; @@ -2633,9 +2799,9 @@ static int transcode_init(void) DEFAULT_PASS_LOGFILENAME_PREFIX, i); if (!strcmp(ost->enc->name, "libx264")) { - av_dict_set(&ost->opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE); + av_dict_set(&ost->encoder_opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE); } else { - if (codec->flags & CODEC_FLAG_PASS2) { + if (enc_ctx->flags & CODEC_FLAG_PASS2) { char *logbuffer; size_t logbuffer_size; if (cmdutils_read_file(logfilename, &logbuffer, &logbuffer_size) < 0) { @@ -2643,9 +2809,9 @@ static int transcode_init(void) logfilename); exit_program(1); } - codec->stats_in = logbuffer; + enc_ctx->stats_in = logbuffer; } - if (codec->flags & CODEC_FLAG_PASS1) { + if (enc_ctx->flags & CODEC_FLAG_PASS1) { f = av_fopen_utf8(logfilename, "wb"); if (!f) { av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n", @@ -2667,20 +2833,22 @@ static int transcode_init(void) AVCodecContext *dec = NULL; if ((ist = get_input_stream(ost))) - dec = ist->st->codec; + dec = ist->dec_ctx; if (dec && dec->subtitle_header) { /* ASS code assumes this buffer is null terminated so add extra byte. */ - ost->st->codec->subtitle_header = av_mallocz(dec->subtitle_header_size + 1); - if (!ost->st->codec->subtitle_header) { + ost->enc_ctx->subtitle_header = av_mallocz(dec->subtitle_header_size + 1); + if (!ost->enc_ctx->subtitle_header) { ret = AVERROR(ENOMEM); goto dump_format; } - memcpy(ost->st->codec->subtitle_header, dec->subtitle_header, dec->subtitle_header_size); - ost->st->codec->subtitle_header_size = dec->subtitle_header_size; + 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->opts, "threads", NULL, 0)) - av_dict_set(&ost->opts, "threads", "auto", 0); - if ((ret = avcodec_open2(ost->st->codec, codec, &ost->opts)) < 0) { + 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", @@ -2690,15 +2858,29 @@ static int transcode_init(void) if (ost->enc->type == AVMEDIA_TYPE_AUDIO && !(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) av_buffersink_set_frame_size(ost->filter->filter, - ost->st->codec->frame_size); - assert_avoptions(ost->opts); - if (ost->st->codec->bit_rate && ost->st->codec->bit_rate < 1000) + ost->enc_ctx->frame_size); + 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"); - extra_size += ost->st->codec->extradata_size; } else { - av_opt_set_dict(ost->st->codec, &ost->opts); + if (av_opt_set_dict(ost->enc_ctx, &ost->encoder_opts) < 0) { + av_log(NULL, AV_LOG_FATAL, + "Error setting up codec context options.\n"); + exit_program(1); + } } + + 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->st->codec->codec= ost->enc_ctx->codec; + + // copy timebase while removing common factors + ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1}); } /* init input streams */ @@ -2706,7 +2888,7 @@ static int transcode_init(void) if ((ret = init_input_stream(i, error, sizeof(error))) < 0) { for (i = 0; i < nb_output_streams; i++) { ost = output_streams[i]; - avcodec_close(ost->st->codec); + avcodec_close(ost->enc_ctx); } goto dump_format; } @@ -2801,10 +2983,32 @@ static int transcode_init(void) ost->sync_ist->st->index); if (ost->stream_copy) av_log(NULL, AV_LOG_INFO, " (copy)"); - else - av_log(NULL, AV_LOG_INFO, " (%s -> %s)", input_streams[ost->source_index]->dec ? - input_streams[ost->source_index]->dec->name : "?", - ost->enc ? ost->enc->name : "?"); + else { + const AVCodec *in_codec = input_streams[ost->source_index]->dec; + const AVCodec *out_codec = ost->enc; + const char *decoder_name = "?"; + const char *in_codec_name = "?"; + const char *encoder_name = "?"; + const char *out_codec_name = "?"; + + if (in_codec) { + decoder_name = in_codec->name; + in_codec_name = avcodec_descriptor_get(in_codec->id)->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; + if (!strcmp(encoder_name, out_codec_name)) + encoder_name = "native"; + } + + av_log(NULL, AV_LOG_INFO, " (%s (%s) -> %s (%s))", + in_codec_name, decoder_name, + out_codec_name, encoder_name); + } av_log(NULL, AV_LOG_INFO, "\n"); } @@ -2817,6 +3021,8 @@ static int transcode_init(void) print_sdp(); } + transcode_init_done = 1; + return 0; } @@ -2945,7 +3151,7 @@ static int check_keyboard_interaction(int64_t cur_time) } for(i=0;ist->codec->debug = debug; + ost->enc_ctx->debug = debug; } if(debug) av_log_set_level(AV_LOG_DEBUG); fprintf(stderr,"debug=%d\n", debug); @@ -2972,32 +3178,31 @@ static void *input_thread(void *arg) InputFile *f = arg; int ret = 0; - while (!transcoding_finished && ret >= 0) { + while (1) { AVPacket pkt; ret = av_read_frame(f->ctx, &pkt); if (ret == AVERROR(EAGAIN)) { av_usleep(10000); - ret = 0; continue; - } else if (ret < 0) + } + if (ret < 0) { + av_thread_message_queue_set_err_recv(f->in_thread_queue, ret); break; - - pthread_mutex_lock(&f->fifo_lock); - 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_cond_signal(&f->fifo_cond); - - pthread_mutex_unlock(&f->fifo_lock); + ret = av_thread_message_queue_send(f->in_thread_queue, &pkt, 0); + if (ret < 0) { + if (ret != AVERROR_EOF) + av_log(f->ctx, AV_LOG_ERROR, + "Unable to send packet to main thread: %s\n", + av_err2str(ret)); + av_free_packet(&pkt); + av_thread_message_queue_set_err_recv(f->in_thread_queue, ret); + break; + } } - pthread_mutex_lock(&f->fifo_lock); - f->finished = 1; - pthread_cond_signal(&f->fifo_cond); - pthread_mutex_unlock(&f->fifo_lock); return NULL; } @@ -3005,34 +3210,19 @@ static void free_input_threads(void) { int i; - if (nb_input_files == 1) - return; - - transcoding_finished = 1; - for (i = 0; i < nb_input_files; i++) { InputFile *f = input_files[i]; AVPacket pkt; - if (!f->fifo || f->joined) + if (!f->in_thread_queue) continue; - - pthread_mutex_lock(&f->fifo_lock); - while (av_fifo_size(f->fifo)) { - av_fifo_generic_read(f->fifo, &pkt, sizeof(pkt), NULL); + av_thread_message_queue_set_err_send(f->in_thread_queue, AVERROR_EOF); + while (av_thread_message_queue_recv(f->in_thread_queue, &pkt, 0) >= 0) av_free_packet(&pkt); - } - pthread_cond_signal(&f->fifo_cond); - pthread_mutex_unlock(&f->fifo_lock); pthread_join(f->thread, NULL); f->joined = 1; - - while (av_fifo_size(f->fifo)) { - av_fifo_generic_read(f->fifo, &pkt, sizeof(pkt), NULL); - av_free_packet(&pkt); - } - av_fifo_free(f->fifo); + av_thread_message_queue_free(&f->in_thread_queue); } } @@ -3046,49 +3236,28 @@ static int init_input_threads(void) for (i = 0; i < nb_input_files; i++) { InputFile *f = input_files[i]; - if (!(f->fifo = av_fifo_alloc(8*sizeof(AVPacket)))) - return AVERROR(ENOMEM); - if (f->ctx->pb ? !f->ctx->pb->seekable : strcmp(f->ctx->iformat->name, "lavfi")) f->non_blocking = 1; + ret = av_thread_message_queue_alloc(&f->in_thread_queue, + 8, sizeof(AVPacket)); + if (ret < 0) + return ret; - pthread_mutex_init(&f->fifo_lock, NULL); - pthread_cond_init (&f->fifo_cond, NULL); - - if ((ret = pthread_create(&f->thread, NULL, input_thread, f))) + if ((ret = pthread_create(&f->thread, NULL, input_thread, f))) { + av_log(NULL, AV_LOG_ERROR, "pthread_create failed: %s. Try to increase `ulimit -v` or decrease `ulimit -s`.\n", strerror(ret)); + av_thread_message_queue_free(&f->in_thread_queue); return AVERROR(ret); + } } return 0; } static int get_input_packet_mt(InputFile *f, AVPacket *pkt) { - int ret = 0; - - pthread_mutex_lock(&f->fifo_lock); - - while (1) { - if (av_fifo_size(f->fifo)) { - av_fifo_generic_read(f->fifo, pkt, sizeof(*pkt), NULL); - pthread_cond_signal(&f->fifo_cond); - break; - } else { - if (f->finished) { - ret = AVERROR_EOF; - break; - } - if (f->non_blocking) { - ret = AVERROR(EAGAIN); - break; - } - pthread_cond_wait(&f->fifo_cond, &f->fifo_lock); - } - } - - pthread_mutex_unlock(&f->fifo_lock); - - return ret; + return av_thread_message_queue_recv(f->in_thread_queue, pkt, + f->non_blocking ? + AV_THREAD_MESSAGE_NONBLOCK : 0); } #endif @@ -3099,7 +3268,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->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); } @@ -3158,12 +3327,14 @@ static int process_input(int file_index) if (exit_on_error) exit_program(1); } - ifile->eof_reached = 1; for (i = 0; i < ifile->nb_streams; i++) { ist = input_streams[ifile->ist_index + i]; - if (ist->decoding_needed) - output_packet(ist, NULL); + if (ist->decoding_needed) { + ret = output_packet(ist, NULL); + if (ret>0) + return 0; + } /* mark all outputs that don't go through lavfi as finished */ for (j = 0; j < nb_output_streams; j++) { @@ -3175,6 +3346,7 @@ static int process_input(int file_index) } } + ifile->eof_reached = 1; return AVERROR(EAGAIN); } @@ -3192,13 +3364,17 @@ static int process_input(int file_index) } ist = input_streams[ifile->ist_index + pkt.stream_index]; + + ist->data_size += pkt.size; + ist->nb_packets++; + if (ist->discard) goto discard_packet; if (debug_ts) { av_log(NULL, AV_LOG_INFO, "demuxer -> ist_index:%d type:%s " "next_dts:%s next_dts_time:%s next_pts:%s next_pts_time:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n", - ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->st->codec->codec_type), + ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), av_ts2str(ist->next_dts), av_ts2timestr(ist->next_dts, &AV_TIME_BASE_Q), av_ts2str(ist->next_pts), av_ts2timestr(ist->next_pts, &AV_TIME_BASE_Q), av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base), @@ -3242,6 +3418,24 @@ static int process_input(int file_index) } } + /* add the stream-global side data to the first packet */ + if (ist->nb_packets == 1) + if (ist->st->nb_side_data) + av_packet_split_side_data(&pkt); + for (i = 0; i < ist->st->nb_side_data; i++) { + AVPacketSideData *src_sd = &ist->st->side_data[i]; + uint8_t *dst_data; + + if (av_packet_get_side_data(&pkt, src_sd->type, NULL)) + continue; + + dst_data = av_packet_new_side_data(&pkt, src_sd->type, src_sd->size); + if (!dst_data) + exit_program(1); + + memcpy(dst_data, src_sd->data, src_sd->size); + } + if (pkt.dts != AV_NOPTS_VALUE) pkt.dts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); if (pkt.pts != AV_NOPTS_VALUE) @@ -3258,7 +3452,7 @@ static int process_input(int file_index) int64_t delta = pkt_dts - ifile->last_ts; if(delta < -1LL*dts_delta_threshold*AV_TIME_BASE || (delta > 1LL*dts_delta_threshold*AV_TIME_BASE && - ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE)){ + ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE)){ ifile->ts_offset -= delta; av_log(NULL, AV_LOG_DEBUG, "Inter stream timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", @@ -3276,7 +3470,7 @@ static int process_input(int file_index) if (is->iformat->flags & AVFMT_TS_DISCONT) { if (delta < -1LL*dts_delta_threshold*AV_TIME_BASE || (delta > 1LL*dts_delta_threshold*AV_TIME_BASE && - ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) || + ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) || pkt_dts + AV_TIME_BASE/10 < FFMAX(ist->pts, ist->dts)) { ifile->ts_offset -= delta; av_log(NULL, AV_LOG_DEBUG, @@ -3288,7 +3482,7 @@ static int process_input(int file_index) } } else { if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || - (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE)) { + (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE)) { av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt.dts, ist->next_dts, pkt.stream_index); pkt.dts = AV_NOPTS_VALUE; } @@ -3296,7 +3490,7 @@ static int process_input(int file_index) int64_t pkt_pts = av_rescale_q(pkt.pts, ist->st->time_base, AV_TIME_BASE_Q); delta = pkt_pts - ist->next_dts; if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || - (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE)) { + (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE)) { av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt.pts, ist->next_dts, pkt.stream_index); pkt.pts = AV_NOPTS_VALUE; } @@ -3309,7 +3503,7 @@ static int process_input(int file_index) if (debug_ts) { av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n", - ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->st->codec->codec_type), + ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base), av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base), av_ts2str(input_files[ist->file_index]->ts_offset), @@ -3443,7 +3637,7 @@ static int transcode(void) av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n"); } - timer_start = av_gettime(); + timer_start = av_gettime_relative(); #if HAVE_PTHREADS if ((ret = init_input_threads()) < 0) @@ -3451,7 +3645,7 @@ static int transcode(void) #endif while (!received_sigterm) { - int64_t cur_time= av_gettime(); + int64_t cur_time= av_gettime_relative(); /* if 'q' pressed, exits */ if (stdin_interaction) @@ -3498,14 +3692,13 @@ static int transcode(void) } /* dump report by using the first video and audio streams */ - print_report(1, timer_start, av_gettime()); + print_report(1, timer_start, av_gettime_relative()); /* close each encoder */ for (i = 0; i < nb_output_streams; i++) { ost = output_streams[i]; if (ost->encoding_needed) { - av_freep(&ost->st->codec->stats_in); - avcodec_close(ost->st->codec); + av_freep(&ost->enc_ctx->stats_in); } } @@ -3513,9 +3706,9 @@ static int transcode(void) for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; if (ist->decoding_needed) { - avcodec_close(ist->st->codec); + avcodec_close(ist->dec_ctx); if (ist->hwaccel_uninit) - ist->hwaccel_uninit(ist->st->codec); + ist->hwaccel_uninit(ist->dec_ctx); } } @@ -3531,16 +3724,13 @@ static int transcode(void) for (i = 0; i < nb_output_streams; i++) { ost = output_streams[i]; if (ost) { - if (ost->stream_copy) - av_freep(&ost->st->codec->extradata); if (ost->logfile) { fclose(ost->logfile); ost->logfile = NULL; } - av_freep(&ost->st->codec->subtitle_header); av_freep(&ost->forced_kf_pts); av_freep(&ost->apad); - av_dict_free(&ost->opts); + av_dict_free(&ost->encoder_opts); av_dict_free(&ost->swr_opts); av_dict_free(&ost->resample_opts); } diff --git a/ffmpeg.h b/ffmpeg.h index 4fc1e18e3..30890a0ee 100644 --- a/ffmpeg.h +++ b/ffmpeg.h @@ -44,6 +44,7 @@ #include "libavutil/fifo.h" #include "libavutil/pixfmt.h" #include "libavutil/rational.h" +#include "libavutil/threadmessage.h" #include "libswresample/swresample.h" @@ -60,6 +61,8 @@ enum HWAccelID { HWACCEL_NONE = 0, HWACCEL_AUTO, HWACCEL_VDPAU, + HWACCEL_DXVA2, + HWACCEL_VDA, }; typedef struct HWAccel { @@ -201,6 +204,8 @@ typedef struct OptionsContext { int nb_guess_layout_max; SpecifierOpt *apad; int nb_apad; + SpecifierOpt *discard; + int nb_discard; } OptionsContext; typedef struct InputFilter { @@ -237,7 +242,9 @@ typedef struct InputStream { int file_index; AVStream *st; int discard; /* true if stream data should be discarded */ + int user_set_discard; int decoding_needed; /* true if the packets must be decoded in 'raw_fifo' */ + AVCodecContext *dec_ctx; AVCodec *dec; AVFrame *decoded_frame; AVFrame *filter_frame; /* a ref of decoded_frame, to be sent to filters */ @@ -257,7 +264,7 @@ typedef struct InputStream { double ts_scale; int saw_first_ts; int showed_multi_packet_warning; - AVDictionary *opts; + AVDictionary *decoder_opts; AVRational framerate; /* framerate forced with -r */ int top_field_first; int guess_layout_max; @@ -306,6 +313,15 @@ typedef struct InputStream { int (*hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame); enum AVPixelFormat hwaccel_pix_fmt; enum AVPixelFormat hwaccel_retrieved_pix_fmt; + + /* stats */ + // combined size of all the packets read + uint64_t data_size; + /* number of packets successfully read for this stream */ + uint64_t nb_packets; + // number of frames/samples retrieved from the decoder + uint64_t frames_decoded; + uint64_t samples_decoded; } InputStream; typedef struct InputFile { @@ -325,13 +341,10 @@ typedef struct InputFile { int accurate_seek; #if HAVE_PTHREADS + AVThreadMessageQueue *in_thread_queue; pthread_t thread; /* thread reading from this file */ int non_blocking; /* reading packets from the thread should not block */ - int finished; /* the thread has exited */ int joined; /* the thread has been joined */ - pthread_mutex_t fifo_lock; /* lock for access to fifo */ - pthread_cond_t fifo_cond; /* the main thread will signal on this cond after reading from fifo */ - AVFifoBuffer *fifo; /* demuxed packets are stored here; freed by the main thread */ #endif } InputFile; @@ -368,6 +381,7 @@ typedef struct OutputStream { /* dts of the last packet sent to the muxer */ int64_t last_mux_dts; AVBitStreamFilterContext *bitstream_filters; + AVCodecContext *enc_ctx; AVCodec *enc; int64_t max_frames; AVFrame *filtered_frame; @@ -400,7 +414,7 @@ typedef struct OutputStream { char *filters_script; ///< filtergraph script associated to the -filter_script option int64_t sws_flags; - AVDictionary *opts; + AVDictionary *encoder_opts; AVDictionary *swr_opts; AVDictionary *resample_opts; char *apad; @@ -414,6 +428,15 @@ typedef struct OutputStream { int keep_pix_fmt; AVCodecParserContext *parser; + + /* stats */ + // combined size of all the packets written + uint64_t data_size; + // number of packets send to the muxer + uint64_t packets_written; + // number of frames/samples sent to the encoder + uint64_t frames_encoded; + uint64_t samples_encoded; } OutputStream; typedef struct OutputFile { @@ -483,7 +506,7 @@ void assert_avoptions(AVDictionary *m); int guess_input_channel_layout(InputStream *ist); -enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodec *codec, enum AVPixelFormat target); +enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *avctx, AVCodec *codec, enum AVPixelFormat target); void choose_sample_fmt(AVStream *st, AVCodec *codec); int configure_filtergraph(FilterGraph *fg); @@ -494,5 +517,7 @@ FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost); int ffmpeg_parse_options(int argc, char **argv); int vdpau_init(AVCodecContext *s); +int dxva2_init(AVCodecContext *s); +int vda_init(AVCodecContext *s); #endif /* FFMPEG_H */ diff --git a/ffmpeg_dxva2.c b/ffmpeg_dxva2.c new file mode 100644 index 000000000..3c91d26f3 --- /dev/null +++ b/ffmpeg_dxva2.c @@ -0,0 +1,620 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 +#define DXVA2API_USE_BITFIELDS +#define COBJMACROS + +#include + +#include +#include + +#include "ffmpeg.h" + +#include "libavcodec/dxva2.h" + +#include "libavutil/avassert.h" +#include "libavutil/buffer.h" +#include "libavutil/frame.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixfmt.h" + +/* define all the GUIDs used directly here, + to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */ +#include +DEFINE_GUID(IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02); + +DEFINE_GUID(DXVA2_ModeMPEG2_VLD, 0xee27417f, 0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9); +DEFINE_GUID(DXVA2_ModeMPEG2and1_VLD, 0x86695f12, 0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60); +DEFINE_GUID(DXVA2_ModeH264_E, 0x1b81be68, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); +DEFINE_GUID(DXVA2_ModeH264_F, 0x1b81be69, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); +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_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; +} dxva2_mode; + +static const dxva2_mode dxva2_modes[] = { + /* MPEG-2 */ + { &DXVA2_ModeMPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO }, + { &DXVA2_ModeMPEG2and1_VLD, AV_CODEC_ID_MPEG2VIDEO }, + + /* H.264 */ + { &DXVA2_ModeH264_F, AV_CODEC_ID_H264 }, + { &DXVA2_ModeH264_E, AV_CODEC_ID_H264 }, + /* Intel specific H.264 mode */ + { &DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264 }, + + /* VC-1 / WMV3 */ + { &DXVA2_ModeVC1_D2010, AV_CODEC_ID_VC1 }, + { &DXVA2_ModeVC1_D2010, AV_CODEC_ID_WMV3 }, + { &DXVA2_ModeVC1_D, AV_CODEC_ID_VC1 }, + { &DXVA2_ModeVC1_D, AV_CODEC_ID_WMV3 }, + + { 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; + + 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; + int i; + + if (ctx->surfaces) { + for (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; + } +} + +static void dxva2_uninit(AVCodecContext *s) +{ + InputStream *ist = s->opaque; + DXVA2Context *ctx = ist->hwaccel_ctx; + + ist->hwaccel_uninit = NULL; + 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_frame_free(&ctx->tmp_frame); + + av_freep(&ist->hwaccel_ctx); + 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; +} + +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); + 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; + + 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) +{ + 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; + HRESULT hr; + D3DPRESENT_PARAMETERS d3dpp = {0}; + D3DDISPLAYMODE d3ddm; + unsigned resetToken = 0; + UINT adapter = D3DADAPTER_DEFAULT; + + 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"); + goto fail; + } + + hr = IDirect3DDeviceManager9_OpenDeviceHandle(ctx->d3d9devmgr, &ctx->deviceHandle); + if (FAILED(hr)) { + av_log(NULL, loglevel, "Failed to open device handle\n"); + goto fail; + } + + hr = IDirect3DDeviceManager9_GetVideoService(ctx->d3d9devmgr, ctx->deviceHandle, &IID_IDirectXVideoDecoderService, (void **)&ctx->decoder_service); + if (FAILED(hr)) { + av_log(NULL, loglevel, "Failed to create IDirectXVideoDecoderService\n"); + goto fail; + } + + ctx->tmp_frame = av_frame_alloc(); + if (!ctx->tmp_frame) + goto fail; + + s->hwaccel_context = av_mallocz(sizeof(struct dxva_context)); + if (!s->hwaccel_context) + goto fail; + + return 0; +fail: + dxva2_uninit(s); + return AVERROR(EINVAL); +} + +static int dxva2_get_decoder_configuration(AVCodecContext *s, const GUID *device_guid, + const DXVA2_VideoDesc *desc, + DXVA2_ConfigPictureDecode *config) +{ + InputStream *ist = s->opaque; + int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; + DXVA2Context *ctx = ist->hwaccel_ctx; + unsigned cfg_count = 0, best_score = 0; + DXVA2_ConfigPictureDecode *cfg_list = NULL; + DXVA2_ConfigPictureDecode best_cfg = {{0}}; + HRESULT hr; + int i; + + hr = IDirectXVideoDecoderService_GetDecoderConfigurations(ctx->decoder_service, device_guid, desc, NULL, &cfg_count, &cfg_list); + if (FAILED(hr)) { + av_log(NULL, loglevel, "Unable to retrieve decoder configurations\n"); + return AVERROR(EINVAL); + } + + for (i = 0; i < cfg_count; i++) { + DXVA2_ConfigPictureDecode *cfg = &cfg_list[i]; + + unsigned score; + if (cfg->ConfigBitstreamRaw == 1) + score = 1; + else if (s->codec_id == AV_CODEC_ID_H264 && cfg->ConfigBitstreamRaw == 2) + score = 2; + else + continue; + if (IsEqualGUID(&cfg->guidConfigBitstreamEncryption, &DXVA2_NoEncrypt)) + score += 16; + if (score > best_score) { + best_score = score; + best_cfg = *cfg; + } + } + CoTaskMemFree(cfg_list); + + if (!best_score) { + av_log(NULL, loglevel, "No valid decoder configuration available\n"); + return AVERROR(EINVAL); + } + + *config = best_cfg; + return 0; +} + +static int dxva2_create_decoder(AVCodecContext *s) +{ + InputStream *ist = s->opaque; + int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; + DXVA2Context *ctx = ist->hwaccel_ctx; + struct dxva_context *dxva_ctx = s->hwaccel_context; + GUID *guid_list = NULL; + unsigned guid_count = 0, i, j; + GUID device_guid = GUID_NULL; + D3DFORMAT target_format = 0; + DXVA2_VideoDesc desc = { 0 }; + DXVA2_ConfigPictureDecode config; + HRESULT hr; + int surface_alignment; + int ret; + + hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(ctx->decoder_service, &guid_count, &guid_list); + if (FAILED(hr)) { + av_log(NULL, loglevel, "Failed to retrieve decoder device GUIDs\n"); + goto fail; + } + + for (i = 0; dxva2_modes[i].guid; i++) { + D3DFORMAT *target_list = NULL; + unsigned target_count = 0; + const dxva2_mode *mode = &dxva2_modes[i]; + if (mode->codec != s->codec_id) + continue; + + for (j = 0; j < guid_count; j++) { + if (IsEqualGUID(mode->guid, &guid_list[j])) + break; + } + if (j == guid_count) + continue; + + hr = IDirectXVideoDecoderService_GetDecoderRenderTargets(ctx->decoder_service, mode->guid, &target_count, &target_list); + if (FAILED(hr)) { + continue; + } + for (j = 0; j < target_count; j++) { + const D3DFORMAT format = target_list[j]; + if (format == MKTAG('N','V','1','2')) { + target_format = format; + break; + } + } + CoTaskMemFree(target_list); + if (target_format) { + device_guid = *mode->guid; + break; + } + } + CoTaskMemFree(guid_list); + + if (IsEqualGUID(&device_guid, &GUID_NULL)) { + av_log(NULL, loglevel, "No decoder device for codec found\n"); + goto fail; + } + + desc.SampleWidth = s->coded_width; + desc.SampleHeight = s->coded_height; + desc.Format = target_format; + + ret = dxva2_get_decoder_configuration(s, &device_guid, &desc, &config); + if (ret < 0) { + goto fail; + } + + /* decoding MPEG-2 requires additional alignment on some Intel GPUs, + but it causes issues for H.264 on certain AMD GPUs..... */ + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) + surface_alignment = 32; + else + surface_alignment = 16; + + /* 4 base work surfaces */ + ctx->num_surfaces = 4; + + /* add surfaces based on number of possible refs */ + if (s->codec_id == AV_CODEC_ID_H264) + ctx->num_surfaces += 16; + else + ctx->num_surfaces += 2; + + /* add extra surfaces for frame threading */ + if (s->active_thread_type & FF_THREAD_FRAME) + ctx->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"); + goto fail; + } + + 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); + goto fail; + } + + hr = IDirectXVideoDecoderService_CreateVideoDecoder(ctx->decoder_service, &device_guid, + &desc, &config, ctx->surfaces, + ctx->num_surfaces, &ctx->decoder); + if (FAILED(hr)) { + av_log(NULL, loglevel, "Failed to create DXVA2 video decoder\n"); + goto fail; + } + + ctx->decoder_guid = device_guid; + 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; + + if (IsEqualGUID(&ctx->decoder_guid, &DXVADDI_Intel_ModeH264_E)) + dxva_ctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO; + + return 0; +fail: + dxva2_destroy_decoder(s); + return AVERROR(EINVAL); +} + +int dxva2_init(AVCodecContext *s) +{ + InputStream *ist = s->opaque; + int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; + DXVA2Context *ctx; + int ret; + + if (!ist->hwaccel_ctx) { + ret = dxva2_alloc(s); + if (ret < 0) + return ret; + } + ctx = ist->hwaccel_ctx; + + if (s->codec_id == AV_CODEC_ID_H264 && + (s->profile & ~FF_PROFILE_H264_CONSTRAINED) > FF_PROFILE_H264_HIGH) { + av_log(NULL, loglevel, "Unsupported H.264 profile for DXVA2 HWAccel: %d\n", s->profile); + return AVERROR(EINVAL); + } + + if (ctx->decoder) + dxva2_destroy_decoder(s); + + ret = dxva2_create_decoder(s); + if (ret < 0) { + av_log(NULL, loglevel, "Error creating the DXVA2 decoder\n"); + return ret; + } + + return 0; +} diff --git a/ffmpeg_filter.c b/ffmpeg_filter.c index 582c66183..50ee422c6 100644 --- a/ffmpeg_filter.c +++ b/ffmpeg_filter.c @@ -37,21 +37,23 @@ #include "libavutil/imgutils.h" #include "libavutil/samplefmt.h" -enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodec *codec, enum AVPixelFormat target) +enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *enc_ctx, AVCodec *codec, enum AVPixelFormat target) { if (codec && codec->pix_fmts) { const enum AVPixelFormat *p = codec->pix_fmts; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(target); int has_alpha = desc ? desc->nb_components % 2 == 0 : 0; enum AVPixelFormat best= AV_PIX_FMT_NONE; - const enum AVPixelFormat mjpeg_formats[] = { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }; - const enum AVPixelFormat ljpeg_formats[] = { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P, - AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_BGRA, AV_PIX_FMT_NONE }; + static const enum AVPixelFormat mjpeg_formats[] = + { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }; + static const enum AVPixelFormat ljpeg_formats[] = + { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_BGRA, AV_PIX_FMT_NONE }; - if (st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) { - if (st->codec->codec_id == AV_CODEC_ID_MJPEG) { + if (enc_ctx->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) { + if (enc_ctx->codec_id == AV_CODEC_ID_MJPEG) { p = mjpeg_formats; - } else if (st->codec->codec_id == AV_CODEC_ID_LJPEG) { + } else if (enc_ctx->codec_id == AV_CODEC_ID_LJPEG) { p =ljpeg_formats; } } @@ -97,21 +99,21 @@ void choose_sample_fmt(AVStream *st, AVCodec *codec) static char *choose_pix_fmts(OutputStream *ost) { - AVDictionaryEntry *strict_dict = av_dict_get(ost->opts, "strict", NULL, 0); + AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0); if (strict_dict) // used by choose_pixel_fmt() and below - av_opt_set(ost->st->codec, "strict", strict_dict->value, 0); + av_opt_set(ost->enc_ctx, "strict", strict_dict->value, 0); if (ost->keep_pix_fmt) { if (ost->filter) avfilter_graph_set_auto_convert(ost->filter->graph->graph, AVFILTER_AUTO_CONVERT_NONE); - if (ost->st->codec->pix_fmt == AV_PIX_FMT_NONE) + if (ost->enc_ctx->pix_fmt == AV_PIX_FMT_NONE) return NULL; - return av_strdup(av_get_pix_fmt_name(ost->st->codec->pix_fmt)); + return av_strdup(av_get_pix_fmt_name(ost->enc_ctx->pix_fmt)); } - if (ost->st->codec->pix_fmt != AV_PIX_FMT_NONE) { - return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc, ost->st->codec->pix_fmt))); + if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { + return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->pix_fmt))); } else if (ost->enc && ost->enc->pix_fmts) { const enum AVPixelFormat *p; AVIOContext *s = NULL; @@ -122,10 +124,10 @@ static char *choose_pix_fmts(OutputStream *ost) exit_program(1); p = ost->enc->pix_fmts; - if (ost->st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) { - if (ost->st->codec->codec_id == AV_CODEC_ID_MJPEG) { + if (ost->enc_ctx->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) { + if (ost->enc_ctx->codec_id == AV_CODEC_ID_MJPEG) { p = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }; - } else if (ost->st->codec->codec_id == AV_CODEC_ID_LJPEG) { + } else if (ost->enc_ctx->codec_id == AV_CODEC_ID_LJPEG) { p = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_BGRA, AV_PIX_FMT_NONE }; } @@ -147,8 +149,8 @@ static char *choose_pix_fmts(OutputStream *ost) #define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name) \ static char *choose_ ## var ## s(OutputStream *ost) \ { \ - if (ost->st->codec->var != none) { \ - get_name(ost->st->codec->var); \ + if (ost->enc_ctx->var != none) { \ + get_name(ost->enc_ctx->var); \ return av_strdup(name); \ } else if (ost->enc && ost->enc->supported_list) { \ const type *p; \ @@ -260,7 +262,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) /* find the first unused stream of corresponding type */ for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; - if (ist->st->codec->codec_type == type && ist->discard) + if (ist->dec_ctx->codec_type == type && ist->discard) break; } if (i == nb_input_streams) { @@ -342,7 +344,7 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, char *pix_fmts; OutputStream *ost = ofilter->ost; OutputFile *of = output_files[ost->file_index]; - AVCodecContext *codec = ost->st->codec; + AVCodecContext *codec = ost->enc_ctx; AVFilterContext *last_filter = out->filter_ctx; int pad_idx = out->pad_idx; int ret; @@ -432,7 +434,7 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, { OutputStream *ost = ofilter->ost; OutputFile *of = output_files[ost->file_index]; - AVCodecContext *codec = ost->st->codec; + AVCodecContext *codec = ost->enc_ctx; AVFilterContext *last_filter = out->filter_ctx; int pad_idx = out->pad_idx; char *sample_fmts, *sample_rates, *channel_layouts; @@ -593,8 +595,8 @@ static int sub2video_prepare(InputStream *ist) /* Compute the size of the canvas for the subtitles stream. If the subtitles codec has set a size, use it. Otherwise use the maximum dimensions of the video streams in the same file. */ - w = ist->st->codec->width; - h = ist->st->codec->height; + w = ist->dec_ctx->width; + h = ist->dec_ctx->height; if (!(w && h)) { for (i = 0; i < avf->nb_streams; i++) { if (avf->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -608,12 +610,12 @@ static int sub2video_prepare(InputStream *ist) } av_log(avf, AV_LOG_INFO, "sub2video: using %dx%d canvas\n", w, h); } - ist->sub2video.w = ist->st->codec->width = ist->resample_width = w; - ist->sub2video.h = ist->st->codec->height = ist->resample_height = h; + ist->sub2video.w = ist->dec_ctx->width = ist->resample_width = w; + ist->sub2video.h = ist->dec_ctx->height = ist->resample_height = h; /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the palettes for all rectangles are identical or compatible */ - ist->resample_pix_fmt = ist->st->codec->pix_fmt = AV_PIX_FMT_RGB32; + ist->resample_pix_fmt = ist->dec_ctx->pix_fmt = AV_PIX_FMT_RGB32; ist->sub2video.frame = av_frame_alloc(); if (!ist->sub2video.frame) @@ -636,7 +638,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, char name[255]; int ret, pad_idx = 0; - if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { av_log(NULL, AV_LOG_ERROR, "Cannot connect video filter to audio input\n"); return AVERROR(EINVAL); } @@ -644,7 +646,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, if (!fr.num) fr = av_guess_frame_rate(input_files[ist->file_index]->ctx, ist->st, NULL); - if (ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { + if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { ret = sub2video_prepare(ist); if (ret < 0) return ret; @@ -652,7 +654,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, sar = ist->st->sample_aspect_ratio.num ? ist->st->sample_aspect_ratio : - ist->st->codec->sample_aspect_ratio; + ist->dec_ctx->sample_aspect_ratio; if(!sar.den) sar = (AVRational){0,1}; av_bprint_init(&args, 0, 1); @@ -662,7 +664,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, ist->resample_height, ist->hwaccel_retrieve_data ? ist->hwaccel_retrieved_pix_fmt : ist->resample_pix_fmt, tb.num, tb.den, sar.num, sar.den, - SWS_BILINEAR + ((ist->st->codec->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0)); + SWS_BILINEAR + ((ist->dec_ctx->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0)); if (fr.num && fr.den) av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den); snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, @@ -730,21 +732,21 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, char name[255]; int ret, pad_idx = 0; - if (ist->st->codec->codec_type != AVMEDIA_TYPE_AUDIO) { + if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_AUDIO) { av_log(NULL, AV_LOG_ERROR, "Cannot connect audio filter to non audio input\n"); return AVERROR(EINVAL); } av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC); av_bprintf(&args, "time_base=%d/%d:sample_rate=%d:sample_fmt=%s", - 1, ist->st->codec->sample_rate, - ist->st->codec->sample_rate, - av_get_sample_fmt_name(ist->st->codec->sample_fmt)); - if (ist->st->codec->channel_layout) + 1, ist->dec_ctx->sample_rate, + ist->dec_ctx->sample_rate, + av_get_sample_fmt_name(ist->dec_ctx->sample_fmt)); + if (ist->dec_ctx->channel_layout) av_bprintf(&args, ":channel_layout=0x%"PRIx64, - ist->st->codec->channel_layout); + ist->dec_ctx->channel_layout); else - av_bprintf(&args, ":channels=%d", ist->st->codec->channels); + av_bprintf(&args, ":channels=%d", ist->dec_ctx->channels); snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, ist->file_index, ist->st->index); @@ -872,7 +874,7 @@ int configure_filtergraph(FilterGraph *fg) args[strlen(args) - 1] = '\0'; fg->graph->resample_lavr_opts = av_strdup(args); - e = av_dict_get(ost->opts, "threads", NULL, 0); + e = av_dict_get(ost->encoder_opts, "threads", NULL, 0); if (e) av_opt_set(fg->graph, "threads", e->value, 0); } diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c index ba2df02e4..ab13d3cf1 100644 --- a/ffmpeg_opt.c +++ b/ffmpeg_opt.c @@ -66,6 +66,12 @@ const HWAccel hwaccels[] = { #if HAVE_VDPAU_X11 { "vdpau", vdpau_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU }, +#endif +#if HAVE_DXVA2_LIB + { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD }, +#endif +#if CONFIG_VDA + { "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA }, #endif { 0 }, }; @@ -98,8 +104,6 @@ float max_error_rate = 2.0/3; static int intra_only = 0; static int file_overwrite = 0; static int no_file_overwrite = 0; -static int video_discard = 0; -static int intra_dc_precision = 8; static int do_psnr = 0; static int input_sync; static int override_ffserver = 0; @@ -558,7 +562,7 @@ static AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream * * list of input streams. */ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) { - int i; + int i, ret; for (i = 0; i < ic->nb_streams; i++) { AVStream *st = ic->streams[i]; @@ -567,6 +571,8 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) char *framerate = NULL, *hwaccel = NULL, *hwaccel_device = NULL; char *codec_tag = NULL; char *next; + char *discard_str = NULL; + const AVOption *discard_opt = av_opt_find(dec, "skip_frame", NULL, 0, 0); if (!ist) exit_program(1); @@ -591,13 +597,33 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) } ist->dec = choose_decoder(o, ic, st); - ist->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, ist->st->codec->codec_id, ic, st, ist->dec); ist->reinit_filters = -1; MATCH_PER_STREAM_OPT(reinit_filters, i, ist->reinit_filters, ic, st); + MATCH_PER_STREAM_OPT(discard, str, discard_str, ic, st); + ist->user_set_discard = AVDISCARD_NONE; + if (discard_str && av_opt_eval_int(dec, discard_opt, discard_str, &ist->user_set_discard) < 0) { + av_log(NULL, AV_LOG_ERROR, "Error parsing discard %s.\n", + discard_str); + exit_program(1); + } + ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE; + ist->dec_ctx = avcodec_alloc_context3(ist->dec); + if (!ist->dec_ctx) { + av_log(NULL, AV_LOG_ERROR, "Error allocating the decoder context.\n"); + exit_program(1); + } + + ret = avcodec_copy_context(ist->dec_ctx, dec); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n"); + exit_program(1); + } + switch (dec->codec_type) { case AVMEDIA_TYPE_VIDEO: if(!ist->dec) @@ -606,9 +632,9 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) dec->flags |= CODEC_FLAG_EMU_EDGE; } - ist->resample_height = dec->height; - ist->resample_width = dec->width; - ist->resample_pix_fmt = dec->pix_fmt; + 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, @@ -662,10 +688,10 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) MATCH_PER_STREAM_OPT(guess_layout_max, i, ist->guess_layout_max, ic, st); guess_input_channel_layout(ist); - ist->resample_sample_fmt = dec->sample_fmt; - ist->resample_sample_rate = dec->sample_rate; - ist->resample_channels = dec->channels; - ist->resample_channel_layout = dec->channel_layout; + 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: @@ -861,8 +887,10 @@ static int open_input_file(OptionsContext *o, const char *filename) ret = avformat_find_stream_info(ic, opts); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename); - avformat_close_input(&ic); - exit_program(1); + if (ic->nb_streams == 0) { + avformat_close_input(&ic); + exit_program(1); + } } timestamp = (o->start_time == AV_NOPTS_VALUE) ? 0 : o->start_time; @@ -905,7 +933,7 @@ static int open_input_file(OptionsContext *o, const char *filename) unused_opts = strip_specifiers(o->g->codec_opts); for (i = f->ist_index; i < nb_input_streams; i++) { e = NULL; - while ((e = av_dict_get(input_streams[i]->opts, "", e, + while ((e = av_dict_get(input_streams[i]->decoder_opts, "", e, AV_DICT_IGNORE_SUFFIX))) av_dict_set(&unused_opts, e->key, NULL, 0); } @@ -1047,11 +1075,19 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->st = st; st->codec->codec_type = type; choose_encoder(o, oc, ost); + + ost->enc_ctx = avcodec_alloc_context3(ost->enc); + if (!ost->enc_ctx) { + av_log(NULL, AV_LOG_ERROR, "Error allocating the encoding context.\n"); + exit_program(1); + } + ost->enc_ctx->codec_type = type; + if (ost->enc) { AVIOContext *s = NULL; char *buf = NULL, *arg = NULL, *preset = NULL; - ost->opts = filter_codec_opts(o->g->codec_opts, ost->enc->id, oc, st, ost->enc); + ost->encoder_opts = filter_codec_opts(o->g->codec_opts, ost->enc->id, oc, st, ost->enc); MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); if (preset && (!(ret = get_preset_file_2(preset, ost->enc->name, &s)))) { @@ -1066,7 +1102,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e exit_program(1); } *arg++ = 0; - av_dict_set(&ost->opts, buf, arg, AV_DICT_DONT_OVERWRITE); + av_dict_set(&ost->encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE); av_free(buf); } while (!s->eof_reached); avio_close(s); @@ -1078,12 +1114,9 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e exit_program(1); } } else { - ost->opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); + ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); } - avcodec_get_context_defaults3(st->codec, ost->enc); - st->codec->codec_type = type; // XXX hack, avcodec_get_context_defaults2() sets type to unknown for stream copy - ost->max_frames = INT64_MAX; MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st); for (i = 0; inb_max_frames; i++) { @@ -1119,17 +1152,17 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e uint32_t tag = strtol(codec_tag, &next, 0); if (*next) tag = AV_RL32(codec_tag); - st->codec->codec_tag = tag; + ost->enc_ctx->codec_tag = tag; } MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st); if (qscale >= 0) { - st->codec->flags |= CODEC_FLAG_QSCALE; - st->codec->global_quality = FF_QP2LAMBDA * qscale; + ost->enc_ctx->flags |= CODEC_FLAG_QSCALE; + ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale; } if (oc->oformat->flags & AVFMT_GLOBALHEADER) - st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; + ost->enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; av_opt_get_int(o->g->sws_opts, "sws_flags", 0, &ost->sws_flags); @@ -1143,7 +1176,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e if (source_index >= 0) { ost->sync_ist = input_streams[source_index]; input_streams[source_index]->discard = 0; - input_streams[source_index]->st->discard = AVDISCARD_NONE; + input_streams[source_index]->st->discard = input_streams[source_index]->user_set_discard; } ost->last_mux_dts = AV_NOPTS_VALUE; @@ -1239,7 +1272,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO, source_index); st = ost->st; - video_enc = st->codec; + video_enc = ost->enc_ctx; MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) { @@ -1344,7 +1377,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in if (p) p++; } video_enc->rc_override_count = i; - video_enc->intra_dc_precision = intra_dc_precision - 8; if (do_psnr) video_enc->flags|= CODEC_FLAG_PSNR; @@ -1354,11 +1386,11 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in if (do_pass) { if (do_pass & 1) { video_enc->flags |= CODEC_FLAG_PASS1; - av_dict_set(&ost->opts, "flags", "+pass1", AV_DICT_APPEND); + av_dict_set(&ost->encoder_opts, "flags", "+pass1", AV_DICT_APPEND); } if (do_pass & 2) { video_enc->flags |= CODEC_FLAG_PASS2; - av_dict_set(&ost->opts, "flags", "+pass2", AV_DICT_APPEND); + av_dict_set(&ost->encoder_opts, "flags", "+pass2", AV_DICT_APPEND); } } @@ -1400,7 +1432,7 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in ost = new_output_stream(o, oc, AVMEDIA_TYPE_AUDIO, source_index); st = ost->st; - audio_enc = st->codec; + audio_enc = ost->enc_ctx; audio_enc->codec_type = AVMEDIA_TYPE_AUDIO; MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); @@ -1430,15 +1462,27 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in /* check for channel mapping for this audio stream */ for (n = 0; n < o->nb_audio_channel_maps; n++) { AudioChannelMap *map = &o->audio_channel_maps[n]; - InputStream *ist = input_streams[ost->source_index]; - if ((map->channel_idx == -1 || (ist->file_index == map->file_idx && ist->st->index == map->stream_idx)) && - (map->ofile_idx == -1 || ost->file_index == map->ofile_idx) && + if ((map->ofile_idx == -1 || ost->file_index == map->ofile_idx) && (map->ostream_idx == -1 || ost->st->index == map->ostream_idx)) { - if (ost->audio_channels_mapped < FF_ARRAY_ELEMS(ost->audio_channels_map)) - ost->audio_channels_map[ost->audio_channels_mapped++] = map->channel_idx; - else - av_log(NULL, AV_LOG_FATAL, "Max channel mapping for output %d.%d reached\n", + InputStream *ist; + + if (map->channel_idx == -1) { + ist = NULL; + } else if (ost->source_index < 0) { + av_log(NULL, AV_LOG_FATAL, "Cannot determine input stream for channel mapping %d.%d\n", ost->file_index, ost->st->index); + continue; + } else { + ist = input_streams[ost->source_index]; + } + + if (!ist || (ist->file_index == map->file_idx && ist->st->index == map->stream_idx)) { + if (ost->audio_channels_mapped < FF_ARRAY_ELEMS(ost->audio_channels_map)) + ost->audio_channels_map[ost->audio_channels_mapped++] = map->channel_idx; + else + av_log(NULL, AV_LOG_FATAL, "Max channel mapping for output %d.%d reached\n", + ost->file_index, ost->st->index); + } } } } @@ -1478,7 +1522,7 @@ static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc, ost = new_output_stream(o, oc, AVMEDIA_TYPE_SUBTITLE, source_index); st = ost->st; - subtitle_enc = st->codec; + subtitle_enc = ost->enc_ctx; subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE; @@ -1596,7 +1640,8 @@ static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy) choose_sample_fmt(st, codec); else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy) - choose_pixel_fmt(st, codec, st->codec->pix_fmt); + choose_pixel_fmt(st, st->codec, codec, st->codec->pix_fmt); + avcodec_copy_context(ost->enc_ctx, st->codec); } avformat_close_input(&ic); @@ -1769,7 +1814,7 @@ static int open_output_file(OptionsContext *o, const char *filename) if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) ost->avfilter = av_strdup("anull"); if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ost->avfilter = av_strdup("null"); ist->discard = 0; - ist->st->discard = AVDISCARD_NONE; + ist->st->discard = ist->user_set_discard; break; } } @@ -1914,8 +1959,8 @@ loop_end: ost->stream_copy = 0; ost->attachment_filename = o->attachments[i]; ost->finished = 1; - ost->st->codec->extradata = attachment; - ost->st->codec->extradata_size = len; + ost->enc_ctx->extradata = attachment; + ost->enc_ctx->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); @@ -1937,7 +1982,7 @@ loop_end: unused_opts = strip_specifiers(o->g->codec_opts); for (i = of->ost_index; i < nb_output_streams; i++) { e = NULL; - while ((e = av_dict_get(output_streams[i]->opts, "", e, + while ((e = av_dict_get(output_streams[i]->encoder_opts, "", e, AV_DICT_IGNORE_SUFFIX))) av_dict_set(&unused_opts, e->key, NULL, 0); } @@ -2048,6 +2093,8 @@ loop_end: continue; ist = input_streams[output_streams[i]->source_index]; av_dict_copy(&output_streams[i]->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE); + if (!output_streams[i]->stream_copy) + av_dict_set(&output_streams[i]->st->metadata, "encoder", NULL, 0); } /* process manually set metadata */ @@ -2351,7 +2398,11 @@ static int opt_old2new(void *optctx, const char *opt, const char *arg) static int opt_bitrate(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; - if(!strcmp(opt, "b")){ + + if(!strcmp(opt, "ab")){ + av_dict_set(&o->g->codec_opts, "b:a", arg, 0); + return 0; + } else if(!strcmp(opt, "b")){ av_log(NULL, AV_LOG_WARNING, "Please use -b:a or -b:v, -b is ambiguous\n"); av_dict_set(&o->g->codec_opts, "b:v", arg, 0); return 0; @@ -2815,6 +2866,9 @@ const OptionDef options[] = { "print timestamp debugging info" }, { "max_error_rate", HAS_ARG | OPT_FLOAT, { &max_error_rate }, "maximum error rate", "ratio of errors (0.0: no errors, 1.0: 100% errors) above which ffmpeg returns an error instead of success." }, + { "discard", OPT_STRING | HAS_ARG | OPT_SPEC | + OPT_INPUT, { .off = OFFSET(discard) }, + "discard", "" }, /* video options */ { "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames }, @@ -2837,8 +2891,6 @@ const OptionDef options[] = { "deprecated use -g 1" }, { "vn", OPT_VIDEO | OPT_BOOL | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT,{ .off = OFFSET(video_disable) }, "disable video" }, - { "vdt", OPT_VIDEO | OPT_INT | HAS_ARG | OPT_EXPERT , { &video_discard }, - "discard threshold", "n" }, { "rc_override", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(rc_overrides) }, "rate control override for specific intervals", "override" }, @@ -2878,8 +2930,6 @@ const OptionDef options[] = { { "top", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_INT| OPT_SPEC | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(top_field_first) }, "top=1/bottom=0/auto=-1 field first", "" }, - { "dc", OPT_VIDEO | OPT_INT | HAS_ARG | OPT_EXPERT , { &intra_dc_precision }, - "intra_dc_precision", "precision" }, { "vtag", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_old2new }, "force video tag/fourcc", "fourcc/tag" }, @@ -2894,6 +2944,8 @@ const OptionDef options[] = { { "force_key_frames", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(forced_key_frames) }, "force key frames at specified timestamps", "timestamps" }, + { "ab", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_bitrate }, + "audio bitrate (please use -b:a)", "bitrate" }, { "b", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_bitrate }, "video bitrate (please use -b:v)", "bitrate" }, { "hwaccel", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | diff --git a/ffmpeg_vda.c b/ffmpeg_vda.c new file mode 100644 index 000000000..b9f0975f5 --- /dev/null +++ b/ffmpeg_vda.c @@ -0,0 +1,134 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/avcodec.h" +#include "libavcodec/vda.h" +#include "libavutil/imgutils.h" + +#include "ffmpeg.h" + +typedef struct VDAContext { + AVFrame *tmp_frame; +} VDAContext; + +static int vda_retrieve_data(AVCodecContext *s, AVFrame *frame) +{ + InputStream *ist = s->opaque; + VDAContext *vda = ist->hwaccel_ctx; + CVPixelBufferRef pixbuf = (CVPixelBufferRef)frame->data[3]; + OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf); + CVReturn err; + uint8_t *data[4] = { 0 }; + int linesize[4] = { 0 }; + int planes, ret, i; + + av_frame_unref(vda->tmp_frame); + + switch (pixel_format) { + case kCVPixelFormatType_420YpCbCr8Planar: vda->tmp_frame->format = AV_PIX_FMT_YUV420P; break; + case kCVPixelFormatType_422YpCbCr8: vda->tmp_frame->format = AV_PIX_FMT_UYVY422; break; + default: + av_log(NULL, AV_LOG_ERROR, + "Unsupported pixel format: %u\n", pixel_format); + return AVERROR(ENOSYS); + } + + vda->tmp_frame->width = frame->width; + vda->tmp_frame->height = frame->height; + ret = av_frame_get_buffer(vda->tmp_frame, 32); + if (ret < 0) + return ret; + + err = CVPixelBufferLockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly); + if (err != kCVReturnSuccess) { + av_log(NULL, AV_LOG_ERROR, "Error locking the pixel buffer.\n"); + return AVERROR_UNKNOWN; + } + + if (CVPixelBufferIsPlanar(pixbuf)) { + + planes = CVPixelBufferGetPlaneCount(pixbuf); + for (i = 0; i < planes; i++) { + data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i); + linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i); + } + } else { + data[0] = CVPixelBufferGetBaseAddress(pixbuf); + linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf); + } + + av_image_copy(vda->tmp_frame->data, vda->tmp_frame->linesize, + data, linesize, vda->tmp_frame->format, + frame->width, frame->height); + + ret = av_frame_copy_props(vda->tmp_frame, frame); + if (ret < 0) + return ret; + + av_frame_unref(frame); + av_frame_move_ref(frame, vda->tmp_frame); + + return 0; +} + +static void vda_uninit(AVCodecContext *s) +{ + InputStream *ist = s->opaque; + VDAContext *vda = ist->hwaccel_ctx; + + ist->hwaccel_uninit = NULL; + ist->hwaccel_retrieve_data = NULL; + + av_frame_free(&vda->tmp_frame); + + av_vda_default_free(s); + av_freep(&ist->hwaccel_ctx); +} + +int vda_init(AVCodecContext *s) +{ + InputStream *ist = s->opaque; + int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; + VDAContext *vda; + int ret; + + vda = av_mallocz(sizeof(*vda)); + if (!vda) + return AVERROR(ENOMEM); + + ist->hwaccel_ctx = vda; + ist->hwaccel_uninit = vda_uninit; + ist->hwaccel_retrieve_data = vda_retrieve_data; + + vda->tmp_frame = av_frame_alloc(); + if (!vda->tmp_frame) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = av_vda_default_init(s); + if (ret < 0) { + av_log(NULL, loglevel, "Error creating VDA decoder.\n"); + goto fail; + } + + return 0; +fail: + vda_uninit(s); + return ret; +} diff --git a/ffplay.c b/ffplay.c index ed7f180eb..af0e199f8 100644 --- a/ffplay.c +++ b/ffplay.c @@ -67,12 +67,13 @@ const int program_birth_year = 2003; #define MAX_QUEUE_SIZE (15 * 1024 * 1024) #define MIN_FRAMES 5 -/* SDL audio buffer size, in samples. Should be small to have precise - A/V sync as SDL does not have hardware buffer fullness info. */ -#define SDL_AUDIO_BUFFER_SIZE 1024 +/* Minimum SDL audio buffer size, in samples. */ +#define SDL_AUDIO_MIN_BUFFER_SIZE 512 +/* Calculate actual buffer size keeping in mind not cause too frequent audio callbacks */ +#define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30 /* no AV sync correction is done if below the minimum AV sync threshold */ -#define AV_SYNC_THRESHOLD_MIN 0.01 +#define AV_SYNC_THRESHOLD_MIN 0.04 /* AV sync correction is done if above the maximum AV sync threshold */ #define AV_SYNC_THRESHOLD_MAX 0.1 /* If a frame duration is longer than this, it will not be duplicated to compensate AV sync */ @@ -119,7 +120,7 @@ typedef struct PacketQueue { } PacketQueue; #define VIDEO_PICTURE_QUEUE_SIZE 3 -#define SUBPICTURE_QUEUE_SIZE 4 +#define SUBPICTURE_QUEUE_SIZE 16 typedef struct VideoPicture { double pts; // presentation timestamp for this picture @@ -202,7 +203,7 @@ typedef struct VideoState { AVStream *audio_st; PacketQueue audioq; int audio_hw_buf_size; - uint8_t silence_buf[SDL_AUDIO_BUFFER_SIZE]; + uint8_t silence_buf[SDL_AUDIO_MIN_BUFFER_SIZE]; uint8_t *audio_buf; uint8_t *audio_buf1; unsigned int audio_buf_size; /* in bytes */ @@ -255,7 +256,7 @@ typedef struct VideoState { int64_t video_current_pos; // current displayed file pos double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE]; - int pictq_size, pictq_rindex, pictq_windex; + int pictq_size, pictq_rindex, pictq_windex, pictq_rindex_shown; SDL_mutex *pictq_mutex; SDL_cond *pictq_cond; #if !CONFIG_AVFILTER @@ -268,6 +269,7 @@ typedef struct VideoState { int step; #if CONFIG_AVFILTER + int vfilter_idx; AVFilterContext *in_video_filter; // the first filter in the video chain AVFilterContext *out_video_filter; // the last filter in the video chain AVFilterContext *in_audio_filter; // the first filter in the audio chain @@ -308,7 +310,6 @@ static int workaround_bugs = 1; static int fast = 0; static int genpts = 0; static int lowres = 0; -static int error_concealment = 3; static int decoder_reorder_pts = -1; static int autoexit; static int exit_on_keydown; @@ -324,9 +325,11 @@ double rdftspeed = 0.02; static int64_t cursor_last_shown; static int cursor_hidden = 0; #if CONFIG_AVFILTER -static char *vfilters = NULL; +static const char **vfilters_list = NULL; +static int nb_vfilters = 0; static char *afilters = NULL; #endif +static int autorotate = 1; /* current context */ static int is_full_screen; @@ -339,6 +342,15 @@ static AVPacket flush_pkt; static SDL_Surface *screen; +#if CONFIG_AVFILTER +static int opt_add_vfilter(void *optctx, const char *opt, const char *arg) +{ + GROW_ARRAY(vfilters_list, nb_vfilters); + vfilters_list[nb_vfilters - 1] = arg; + return 0; +} +#endif + static inline int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1, enum AVSampleFormat fmt2, int64_t channel_count2) @@ -796,19 +808,21 @@ static void free_subpicture(SubPicture *sp) avsubtitle_free(&sp->sub); } -static void calculate_display_rect(SDL_Rect *rect, int scr_xleft, int scr_ytop, int scr_width, int scr_height, VideoPicture *vp) +static void calculate_display_rect(SDL_Rect *rect, + int scr_xleft, int scr_ytop, int scr_width, int scr_height, + int pic_width, int pic_height, AVRational pic_sar) { float aspect_ratio; int width, height, x, y; - if (vp->sar.num == 0) + if (pic_sar.num == 0) aspect_ratio = 0; else - aspect_ratio = av_q2d(vp->sar); + aspect_ratio = av_q2d(pic_sar); if (aspect_ratio <= 0.0) aspect_ratio = 1.0; - aspect_ratio *= (float)vp->width / (float)vp->height; + aspect_ratio *= (float)pic_width / (float)pic_height; /* XXX: we suppose the screen has a 1.0 pixel ratio */ height = scr_height; @@ -833,7 +847,7 @@ static void video_image_display(VideoState *is) SDL_Rect rect; int i; - vp = &is->pictq[is->pictq_rindex]; + vp = &is->pictq[(is->pictq_rindex + is->pictq_rindex_shown) % VIDEO_PICTURE_QUEUE_SIZE]; if (vp->bmp) { if (is->subtitle_st) { if (is->subpq_size > 0) { @@ -859,7 +873,7 @@ static void video_image_display(VideoState *is) } } - calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp); + calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar); SDL_DisplayYUVOverlay(vp->bmp, &rect); @@ -899,7 +913,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->audio_tgt.freq) / 1000000; } @@ -1051,7 +1065,7 @@ static void do_exit(VideoState *is) av_lockmgr_register(NULL); uninit_opts(); #if CONFIG_AVFILTER - av_freep(&vfilters); + av_freep(&vfilters_list); #endif avformat_network_deinit(); if (show_status) @@ -1066,10 +1080,10 @@ static void sigterm_handler(int sig) exit(123); } -static void set_default_window_size(VideoPicture *vp) +static void set_default_window_size(int width, int height, AVRational sar) { SDL_Rect rect; - calculate_display_rect(&rect, 0, 0, INT_MAX, vp->height, vp); + calculate_display_rect(&rect, 0, 0, INT_MAX, height, width, height, sar); default_width = rect.w; default_height = rect.h; } @@ -1083,7 +1097,7 @@ static int video_open(VideoState *is, int force_set_video_mode, VideoPicture *vp else flags |= SDL_RESIZABLE; if (vp && vp->width) - set_default_window_size(vp); + set_default_window_size(vp->width, vp->height, vp->sar); if (is_full_screen && fs_screen_width) { w = fs_screen_width; @@ -1132,7 +1146,7 @@ static double get_clock(Clock *c) if (c->paused) { return c->pts; } else { - double time = av_gettime() / 1000000.0; + double time = av_gettime_relative() / 1000000.0; return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed); } } @@ -1147,7 +1161,7 @@ static void set_clock_at(Clock *c, double pts, int serial, double time) static void set_clock(Clock *c, double pts, int serial) { - double time = av_gettime() / 1000000.0; + double time = av_gettime_relative() / 1000000.0; set_clock_at(c, pts, serial, time); } @@ -1240,7 +1254,7 @@ static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_by static void stream_toggle_pause(VideoState *is) { if (is->paused) { - is->frame_timer += av_gettime() / 1000000.0 + is->vidclk.pts_drift - is->vidclk.pts; + is->frame_timer += av_gettime_relative() / 1000000.0 + is->vidclk.pts_drift - is->vidclk.pts; if (is->read_pause_return != AVERROR(ENOSYS)) { is->vidclk.paused = 0; } @@ -1306,7 +1320,23 @@ static double vp_duration(VideoState *is, VideoPicture *vp, VideoPicture *nextvp } } +/* return the number of undisplayed pictures in the queue */ +static int pictq_nb_remaining(VideoState *is) { + return is->pictq_size - is->pictq_rindex_shown; +} + +/* jump back to the previous picture if available by resetting rindex_shown */ +static int pictq_prev_picture(VideoState *is) { + int ret = is->pictq_rindex_shown; + is->pictq_rindex_shown = 0; + return ret; +} + static void pictq_next_picture(VideoState *is) { + if (!is->pictq_rindex_shown) { + is->pictq_rindex_shown = 1; + return; + } /* update queue size and signal for next picture */ if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE) is->pictq_rindex = 0; @@ -1317,25 +1347,6 @@ static void pictq_next_picture(VideoState *is) { SDL_UnlockMutex(is->pictq_mutex); } -static int pictq_prev_picture(VideoState *is) { - VideoPicture *prevvp; - int ret = 0; - /* update queue size and signal for the previous picture */ - prevvp = &is->pictq[(is->pictq_rindex + VIDEO_PICTURE_QUEUE_SIZE - 1) % VIDEO_PICTURE_QUEUE_SIZE]; - if (prevvp->allocated && prevvp->serial == is->videoq.serial) { - SDL_LockMutex(is->pictq_mutex); - if (is->pictq_size < VIDEO_PICTURE_QUEUE_SIZE) { - if (--is->pictq_rindex == -1) - is->pictq_rindex = VIDEO_PICTURE_QUEUE_SIZE - 1; - is->pictq_size++; - ret = 1; - } - SDL_CondSignal(is->pictq_cond); - SDL_UnlockMutex(is->pictq_mutex); - } - return ret; -} - static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial) { /* update current video pts */ set_clock(&is->vidclk, pts, serial); @@ -1355,7 +1366,7 @@ static void video_refresh(void *opaque, double *remaining_time) check_external_clock_speed(is); if (!display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st) { - time = av_gettime() / 1000000.0; + time = av_gettime_relative() / 1000000.0; if (is->force_refresh || is->last_vis_time + rdftspeed < time) { video_display(is); is->last_vis_time = time; @@ -1368,15 +1379,15 @@ static void video_refresh(void *opaque, double *remaining_time) if (is->force_refresh) redisplay = pictq_prev_picture(is); retry: - if (is->pictq_size == 0) { + if (pictq_nb_remaining(is) == 0) { // nothing to do, no picture to display in the queue } else { double last_duration, duration, delay; VideoPicture *vp, *lastvp; /* dequeue the picture */ - vp = &is->pictq[is->pictq_rindex]; - lastvp = &is->pictq[(is->pictq_rindex + VIDEO_PICTURE_QUEUE_SIZE - 1) % VIDEO_PICTURE_QUEUE_SIZE]; + lastvp = &is->pictq[is->pictq_rindex]; + vp = &is->pictq[(is->pictq_rindex + is->pictq_rindex_shown) % VIDEO_PICTURE_QUEUE_SIZE]; if (vp->serial != is->videoq.serial) { pictq_next_picture(is); @@ -1386,7 +1397,7 @@ retry: } if (lastvp->serial != vp->serial && !redisplay) - is->frame_timer = av_gettime() / 1000000.0; + is->frame_timer = av_gettime_relative() / 1000000.0; if (is->paused) goto display; @@ -1398,7 +1409,7 @@ retry: else delay = compute_target_delay(last_duration, is); - time= av_gettime()/1000000.0; + time= av_gettime_relative()/1000000.0; if (time < is->frame_timer + delay && !redisplay) { *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time); return; @@ -1413,8 +1424,8 @@ retry: update_video_pts(is, vp->pts, vp->pos, vp->serial); SDL_UnlockMutex(is->pictq_mutex); - if (is->pictq_size > 1) { - VideoPicture *nextvp = &is->pictq[(is->pictq_rindex + 1) % VIDEO_PICTURE_QUEUE_SIZE]; + if (pictq_nb_remaining(is) > 1) { + VideoPicture *nextvp = &is->pictq[(is->pictq_rindex + is->pictq_rindex_shown + 1) % VIDEO_PICTURE_QUEUE_SIZE]; duration = vp_duration(is, vp, nextvp); if(!is->step && (redisplay || framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) && time > is->frame_timer + duration){ if (!redisplay) @@ -1472,7 +1483,7 @@ display: 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; @@ -1570,8 +1581,7 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double /* wait until we have space to put a new picture */ SDL_LockMutex(is->pictq_mutex); - /* keep the last already displayed picture in the queue */ - while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE - 1 && + while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !is->videoq.abort_request) { SDL_CondWait(is->pictq_cond, is->pictq_mutex); } @@ -1773,7 +1783,7 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c char sws_flags_str[128]; char buffersrc_args[256]; int ret; - AVFilterContext *filt_src = NULL, *filt_out = NULL, *filt_crop; + AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter = NULL; AVCodecContext *codec = is->video_st->codec; AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL); @@ -1804,16 +1814,49 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c if ((ret = av_opt_set_int_list(filt_out, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0) goto fail; + 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), \ + "ffplay_" name, arg, NULL, graph); \ + if (ret < 0) \ + goto fail; \ + \ + ret = avfilter_link(filt_ctx, 0, last_filter, 0); \ + if (ret < 0) \ + goto fail; \ + \ + last_filter = filt_ctx; \ +} while (0) + /* SDL YUV code is not handling odd width/height for some driver * combinations, therefore we crop the picture to an even width/height. */ - if ((ret = avfilter_graph_create_filter(&filt_crop, - avfilter_get_by_name("crop"), - "ffplay_crop", "floor(in_w/2)*2:floor(in_h/2)*2", NULL, graph)) < 0) - goto fail; - if ((ret = avfilter_link(filt_crop, 0, filt_out, 0)) < 0) - goto fail; + INSERT_FILT("crop", "floor(in_w/2)*2:floor(in_h/2)*2"); - if ((ret = configure_filtergraph(graph, vfilters, filt_src, filt_crop)) < 0) + if (autorotate) { + AVDictionaryEntry *rotate_tag = av_dict_get(is->video_st->metadata, "rotate", NULL, 0); + if (rotate_tag && *rotate_tag->value && strcmp(rotate_tag->value, "0")) { + if (!strcmp(rotate_tag->value, "90")) { + INSERT_FILT("transpose", "clock"); + } else if (!strcmp(rotate_tag->value, "180")) { + INSERT_FILT("hflip", NULL); + INSERT_FILT("vflip", NULL); + } else if (!strcmp(rotate_tag->value, "270")) { + INSERT_FILT("transpose", "cclock"); + } else { + char rotate_buf[64]; + snprintf(rotate_buf, sizeof(rotate_buf), "%s*PI/180", rotate_tag->value); + INSERT_FILT("rotate", rotate_buf); + } + } + } + + if ((ret = configure_filtergraph(graph, vfilters, filt_src, last_filter)) < 0) goto fail; is->in_video_filter = filt_src; @@ -1919,6 +1962,7 @@ static int video_thread(void *arg) int last_h = 0; enum AVPixelFormat last_format = -2; int last_serial = -1; + int last_vfilter_idx = 0; #endif for (;;) { @@ -1937,7 +1981,8 @@ static int video_thread(void *arg) if ( last_w != frame->width || last_h != frame->height || last_format != frame->format - || last_serial != serial) { + || last_serial != serial + || last_vfilter_idx != is->vfilter_idx) { av_log(NULL, AV_LOG_DEBUG, "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n", last_w, last_h, @@ -1946,7 +1991,7 @@ static int video_thread(void *arg) (const char *)av_x_if_null(av_get_pix_fmt_name(frame->format), "none"), serial); avfilter_graph_free(&graph); graph = avfilter_graph_alloc(); - if ((ret = configure_video_filters(graph, is, vfilters, frame)) < 0) { + if ((ret = configure_video_filters(graph, is, vfilters_list ? vfilters_list[is->vfilter_idx] : NULL, frame)) < 0) { SDL_Event event; event.type = FF_QUIT_EVENT; event.user.data1 = is; @@ -1959,6 +2004,7 @@ static int video_thread(void *arg) last_h = frame->height; last_format = frame->format; last_serial = serial; + last_vfilter_idx = is->vfilter_idx; frame_rate = filt_out->inputs[0]->frame_rate; } @@ -1967,7 +2013,7 @@ static int video_thread(void *arg) goto the_end; while (ret >= 0) { - is->frame_last_returned_time = av_gettime() / 1000000.0; + is->frame_last_returned_time = av_gettime_relative() / 1000000.0; ret = av_buffersink_get_frame_flags(filt_out, frame, 0); if (ret < 0) { @@ -1977,7 +2023,7 @@ static int video_thread(void *arg) break; } - is->frame_last_filter_delay = av_gettime() / 1000000.0 - is->frame_last_returned_time; + is->frame_last_filter_delay = av_gettime_relative() / 1000000.0 - is->frame_last_returned_time; if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0) is->frame_last_filter_delay = 0; tb = filt_out->inputs[0]->time_base; @@ -2378,7 +2424,7 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) VideoState *is = opaque; int audio_size, len1; - audio_callback_time = av_gettime(); + audio_callback_time = av_gettime_relative(); while (len > 0) { if (is->audio_buf_index >= is->audio_buf_size) { @@ -2415,6 +2461,8 @@ static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb SDL_AudioSpec wanted_spec, spec; const char *env; static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6}; + static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000}; + int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1; env = SDL_getenv("SDL_AUDIO_CHANNELS"); if (env) { @@ -2425,24 +2473,32 @@ static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels); wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX; } - wanted_spec.channels = av_get_channel_layout_nb_channels(wanted_channel_layout); + wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout); + wanted_spec.channels = wanted_nb_channels; wanted_spec.freq = wanted_sample_rate; if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) { av_log(NULL, AV_LOG_ERROR, "Invalid sample rate or channel count!\n"); return -1; } + while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq) + next_sample_rate_idx--; wanted_spec.format = AUDIO_S16SYS; wanted_spec.silence = 0; - wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE; + wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC)); wanted_spec.callback = sdl_audio_callback; wanted_spec.userdata = opaque; while (SDL_OpenAudio(&wanted_spec, &spec) < 0) { - av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels): %s\n", wanted_spec.channels, SDL_GetError()); + av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n", + wanted_spec.channels, wanted_spec.freq, SDL_GetError()); wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)]; if (!wanted_spec.channels) { - av_log(NULL, AV_LOG_ERROR, - "No more channel combinations to try, audio open failed\n"); - return -1; + wanted_spec.freq = next_sample_rates[next_sample_rate_idx--]; + wanted_spec.channels = wanted_nb_channels; + if (!wanted_spec.freq) { + av_log(NULL, AV_LOG_ERROR, + "No more combinations to try, audio open failed\n"); + return -1; + } } wanted_channel_layout = av_get_default_channel_layout(wanted_spec.channels); } @@ -2516,7 +2572,6 @@ static int stream_component_open(VideoState *is, int stream_index) stream_lowres = av_codec_get_max_lowres(codec); } av_codec_set_lowres(avctx, stream_lowres); - avctx->error_concealment = error_concealment; if(stream_lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE; if (fast) avctx->flags2 |= CODEC_FLAG2_FAST; @@ -2574,7 +2629,7 @@ static int stream_component_open(VideoState *is, int stream_index) is->audio_diff_avg_count = 0; /* since we do not have a precise anough audio fifo fullness, we correct audio sync only if larger than this threshold */ - is->audio_diff_threshold = 2.0 * is->audio_hw_buf_size / is->audio_tgt.bytes_per_sec; + is->audio_diff_threshold = (double)(is->audio_hw_buf_size) / is->audio_tgt.bytes_per_sec; memset(&is->audio_pkt, 0, sizeof(is->audio_pkt)); memset(&is->audio_pkt_temp, 0, sizeof(is->audio_pkt_temp)); @@ -2752,6 +2807,8 @@ static int read_thread(void *arg) if (genpts) ic->flags |= AVFMT_FLAG_GENPTS; + av_format_inject_global_side_data(ic); + opts = setup_find_stream_info_opts(ic, codec_opts); orig_nb_streams = ic->nb_streams; @@ -2822,9 +2879,9 @@ static int read_thread(void *arg) if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) { AVStream *st = ic->streams[st_index[AVMEDIA_TYPE_VIDEO]]; AVCodecContext *avctx = st->codec; - VideoPicture vp = {.width = avctx->width, .height = avctx->height, .sar = av_guess_sample_aspect_ratio(ic, st, NULL)}; - if (vp.width) - set_default_window_size(&vp); + AVRational sar = av_guess_sample_aspect_ratio(ic, st, NULL); + if (avctx->width) + set_default_window_size(avctx->width, avctx->height, sar); } /* open the streams */ @@ -2935,7 +2992,7 @@ static int read_thread(void *arg) } if (!is->paused && (!is->audio_st || is->audio_finished == is->audioq.serial) && - (!is->video_st || (is->video_finished == is->videoq.serial && is->pictq_size == 0))) { + (!is->video_st || (is->video_finished == is->videoq.serial && pictq_nb_remaining(is) == 0))) { if (loop != 1 && (!loop || --loop)) { stream_seek(is, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0); } else if (autoexit) { @@ -3120,6 +3177,11 @@ static void stream_cycle_channel(VideoState *is, int codec_type) the_end: if (p && stream_index != -1) stream_index = p->stream_index[stream_index]; + av_log(NULL, AV_LOG_INFO, "Switch %s stream from #%d to #%d\n", + av_get_media_type_string(codec_type), + old_index, + stream_index); + stream_component_close(is, old_index); stream_component_open(is, stream_index); } @@ -3157,7 +3219,7 @@ static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) { double remaining_time = 0.0; SDL_PumpEvents(); while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS)) { - if (!cursor_hidden && av_gettime() - cursor_last_shown > CURSOR_HIDE_DELAY) { + if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) { SDL_ShowCursor(0); cursor_hidden = 1; } @@ -3243,7 +3305,17 @@ static void event_loop(VideoState *cur_stream) stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE); break; case SDLK_w: +#if CONFIG_AVFILTER + if (cur_stream->show_mode == SHOW_MODE_VIDEO && cur_stream->vfilter_idx < nb_vfilters - 1) { + if (++cur_stream->vfilter_idx >= nb_vfilters) + cur_stream->vfilter_idx = 0; + } else { + cur_stream->vfilter_idx = 0; + toggle_audio_display(cur_stream); + } +#else toggle_audio_display(cur_stream); +#endif break; case SDLK_PAGEUP: if (cur_stream->ic->nb_chapters <= 1) { @@ -3311,7 +3383,7 @@ static void event_loop(VideoState *cur_stream) SDL_ShowCursor(1); cursor_hidden = 0; } - cursor_last_shown = av_gettime(); + cursor_last_shown = av_gettime_relative(); if (event.type == SDL_MOUSEBUTTONDOWN) { x = event.button.x; } else { @@ -3499,7 +3571,6 @@ static const OptionDef options[] = { { "genpts", OPT_BOOL | OPT_EXPERT, { &genpts }, "generate pts", "" }, { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, { &decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""}, { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, { &lowres }, "", "" }, - { "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", "" }, { "exitonkeydown", OPT_BOOL | OPT_EXPERT, { &exit_on_keydown }, "exit on key down", "" }, @@ -3509,7 +3580,7 @@ static const OptionDef options[] = { { "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 }, "set video filters", "filter_graph" }, + { "vf", OPT_EXPERT | HAS_ARG, { .func_arg = opt_add_vfilter }, "set video filters", "filter_graph" }, { "af", OPT_STRING | HAS_ARG, { &afilters }, "set audio filters", "filter_graph" }, #endif { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" }, @@ -3520,6 +3591,7 @@ static const OptionDef options[] = { { "acodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &audio_codec_name }, "force audio decoder", "decoder_name" }, { "scodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &subtitle_codec_name }, "force subtitle decoder", "decoder_name" }, { "vcodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &video_codec_name }, "force video decoder", "decoder_name" }, + { "autorotate", OPT_BOOL, { &autorotate }, "automatically rotate video", "" }, { NULL, }, }; @@ -3552,7 +3624,7 @@ void show_help_default(const char *opt, const char *arg) "v cycle video channel\n" "t cycle subtitle channel in the current program\n" "c cycle program\n" - "w show audio waves\n" + "w cycle video filters or show modes\n" "s activate frame-step mode\n" "left/right seek backward/forward 10 seconds\n" "down/up seek backward/forward 1 minute\n" @@ -3625,7 +3697,7 @@ int main(int argc, char **argv) flags &= ~SDL_INIT_AUDIO; if (display_disable) SDL_putenv(dummy_videodriver); /* For the event queue, we always need a video driver. */ -#if !defined(__MINGW32__) && !defined(__APPLE__) +#if !defined(_WIN32) && !defined(__APPLE__) flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */ #endif if (SDL_Init (flags)) { diff --git a/ffprobe.c b/ffprobe.c index 4ca181f90..1329466fb 100644 --- a/ffprobe.c +++ b/ffprobe.c @@ -1991,6 +1991,7 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id const char *s; AVRational sar, dar; AVBPrint pbuf; + const AVCodecDescriptor *cd; int ret = 0; av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED); @@ -2008,6 +2009,12 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id if (dec->long_name) print_str ("codec_long_name", dec->long_name); else print_str_opt("codec_long_name", "unknown"); } + } else if ((cd = avcodec_descriptor_get(stream->codec->codec_id))) { + print_str_opt("codec_name", cd->name); + if (!do_bitexact) { + print_str_opt("codec_long_name", + cd->long_name ? cd->long_name : "unknown"); + } } else { print_str_opt("codec_name", "unknown"); if (!do_bitexact) { @@ -2051,6 +2058,13 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id if (s) print_str ("pix_fmt", s); else print_str_opt("pix_fmt", "unknown"); print_int("level", dec_ctx->level); + if (dec_ctx->color_range != AVCOL_RANGE_UNSPECIFIED) + print_str ("color_range", dec_ctx->color_range == AVCOL_RANGE_MPEG ? "tv": "pc"); + else + print_str_opt("color_range", "N/A"); + s = av_get_colorspace_name(dec_ctx->colorspace); + if (s) print_str ("color_space", s); + else print_str_opt("color_space", "unknown"); if (dec_ctx->timecode_frame_start >= 0) { char tcbuf[AV_TIMECODE_STR_SIZE]; av_timecode_make_mpeg_tc_string(tcbuf, dec_ctx->timecode_frame_start); @@ -2115,6 +2129,8 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id print_time("duration", stream->duration, &stream->time_base); if (dec_ctx->bit_rate > 0) print_val ("bit_rate", dec_ctx->bit_rate, unit_bit_per_second_str); else print_str_opt("bit_rate", "N/A"); + if (dec_ctx->rc_max_rate > 0) print_val ("max_bit_rate", dec_ctx->rc_max_rate, unit_bit_per_second_str); + else print_str_opt("max_bit_rate", "N/A"); if (stream->nb_frames) print_fmt ("nb_frames", "%"PRId64, stream->nb_frames); else print_str_opt("nb_frames", "N/A"); if (nb_streams_frames[stream_idx]) print_fmt ("nb_read_frames", "%"PRIu64, nb_streams_frames[stream_idx]); @@ -2733,7 +2749,7 @@ static int parse_read_intervals(const char *intervals_spec) n++; n++; - read_intervals = av_malloc(n * sizeof(*read_intervals)); + read_intervals = av_malloc_array(n, sizeof(*read_intervals)); if (!read_intervals) { ret = AVERROR(ENOMEM); goto end; diff --git a/ffserver.c b/ffserver.c index c2d2180e8..08f787854 100644 --- a/ffserver.c +++ b/ffserver.c @@ -38,6 +38,7 @@ #include "libavformat/rtpdec.h" #include "libavformat/rtpproto.h" #include "libavformat/rtsp.h" +#include "libavformat/rtspcodes.h" #include "libavformat/avio_internal.h" #include "libavformat/internal.h" #include "libavformat/url.h" @@ -55,7 +56,9 @@ #include "libavutil/time.h" #include +#if HAVE_UNISTD_H #include +#endif #include #include #if HAVE_POLL_H @@ -222,7 +225,7 @@ typedef struct FFStream { IPAddressACL *acl; char dynamic_acl[1024]; int nb_streams; - int prebuffer; /* Number of millseconds early to start */ + int prebuffer; /* Number of milliseconds early to start */ int64_t max_time; /* Number of milliseconds to run */ int send_on_key; AVStream *streams[MAX_STREAMS]; @@ -555,7 +558,8 @@ static int socket_open_listen(struct sockaddr_in *my_addr) } tmp = 1; - setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp)); + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp))) + av_log(NULL, AV_LOG_WARNING, "setsockopt SO_REUSEADDR failed\n"); my_addr->sin_family = AF_INET; if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) { @@ -571,7 +575,9 @@ static int socket_open_listen(struct sockaddr_in *my_addr) closesocket(server_fd); return -1; } - ff_socket_nonblock(server_fd, 1); + + if (ff_socket_nonblock(server_fd, 1) < 0) + av_log(NULL, AV_LOG_WARNING, "ff_socket_nonblock failed\n"); return server_fd; } @@ -647,18 +653,24 @@ static int http_server(void) if (my_http_addr.sin_port) { server_fd = socket_open_listen(&my_http_addr); - if (server_fd < 0) + if (server_fd < 0) { + av_free(poll_table); return -1; + } } if (my_rtsp_addr.sin_port) { rtsp_server_fd = socket_open_listen(&my_rtsp_addr); - if (rtsp_server_fd < 0) + if (rtsp_server_fd < 0) { + av_free(poll_table); + closesocket(server_fd); return -1; + } } if (!rtsp_server_fd && !server_fd) { http_log("HTTP and RTSP disabled.\n"); + av_free(poll_table); return -1; } @@ -737,8 +749,10 @@ static int http_server(void) do { ret = poll(poll_table, poll_entry - poll_table, delay); if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) && - ff_neterrno() != AVERROR(EINTR)) + ff_neterrno() != AVERROR(EINTR)) { + av_free(poll_table); return -1; + } } while (ret < 0); cur_time = av_gettime() / 1000; @@ -801,7 +815,8 @@ static void http_send_too_busy_reply(int fd) "\r\n", nb_connections, nb_max_connections); av_assert0(len < sizeof(buffer)); - send(fd, buffer, len, 0); + if (send(fd, buffer, len, 0) < len) + av_log(NULL, AV_LOG_WARNING, "Could not send too-busy reply, send() failed\n"); } @@ -819,7 +834,8 @@ static void new_connection(int server_fd, int is_rtsp) http_log("error during accept %s\n", strerror(errno)); return; } - ff_socket_nonblock(fd, 1); + if (ff_socket_nonblock(fd, 1) < 0) + av_log(NULL, AV_LOG_WARNING, "ff_socket_nonblock failed\n"); if (nb_connections >= nb_max_connections) { http_send_too_busy_reply(fd); @@ -1324,7 +1340,7 @@ static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_ac get_arg(arg, sizeof(arg), &p); if (resolve_host(&acl.first, arg) != 0) { - fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n", + fprintf(stderr, "%s:%d: ACL refers to invalid host or IP address '%s'\n", filename, line_num, arg); errors++; } else @@ -1334,7 +1350,7 @@ static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_ac if (arg[0]) { if (resolve_host(&acl.last, arg) != 0) { - fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n", + fprintf(stderr, "%s:%d: ACL refers to invalid host or IP address '%s'\n", filename, line_num, arg); errors++; } @@ -1364,7 +1380,8 @@ static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_ac naclp = &(*naclp)->next; *naclp = nacl; - } + } else + av_free(nacl); } } @@ -1725,7 +1742,7 @@ static int http_parse_request(HTTPContext *c) *p = '\0'; snprintf(q, c->buffer_size, "HTTP/1.0 200 RTSP Redirect follows\r\n" - /* XXX: incorrect mime type ? */ + /* XXX: incorrect MIME type ? */ "Content-type: application/x-rtsp\r\n" "\r\n" "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename); @@ -1746,7 +1763,10 @@ static int http_parse_request(HTTPContext *c) q += strlen(q); len = sizeof(my_addr); - getsockname(c->fd, (struct sockaddr *)&my_addr, &len); + + /* XXX: Should probably fail? */ + if (getsockname(c->fd, (struct sockaddr *)&my_addr, &len)) + http_log("getsockname() failed\n"); /* XXX: should use a dynamic buffer */ sdp_data_size = prepare_sdp_description(stream, @@ -1786,7 +1806,7 @@ static int http_parse_request(HTTPContext *c) /* if post, it means a feed is being sent */ if (!stream->is_feed) { /* However it might be a status report from WMP! Let us log the - * data as it might come in handy one day. */ + * data as it might come handy one day. */ const char *logline = 0; int client_id = 0; @@ -2308,7 +2328,7 @@ static int http_prepare_data(HTTPContext *c) c->fmt_ctx.pb->seekable = 0; /* - * HACK to avoid mpeg ps muxer to spit many underflow errors + * HACK to avoid MPEG-PS muxer to spit many underflow errors * Default value from FFmpeg * Try to set it using configuration option */ @@ -2739,8 +2759,11 @@ static int http_receive_data(HTTPContext *c) /* a packet has been received : write it in the store, except if header */ if (c->data_count > FFM_PACKET_SIZE) { - /* XXX: use llseek or url_seek */ - lseek(c->feed_fd, feed->feed_write_index, SEEK_SET); + /* XXX: use llseek or url_seek + * XXX: Should probably fail? */ + if (lseek(c->feed_fd, feed->feed_write_index, SEEK_SET) == -1) + http_log("Seek to %"PRId64" failed\n", feed->feed_write_index); + if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) { http_log("Error writing to feed file: %s\n", strerror(errno)); goto fail; @@ -2836,44 +2859,9 @@ static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number) struct tm *tm; char buf2[32]; - switch(error_number) { - case RTSP_STATUS_OK: - str = "OK"; - break; - case RTSP_STATUS_METHOD: - str = "Method Not Allowed"; - break; - case RTSP_STATUS_BANDWIDTH: - str = "Not Enough Bandwidth"; - break; - case RTSP_STATUS_SESSION: - str = "Session Not Found"; - break; - case RTSP_STATUS_STATE: - str = "Method Not Valid in This State"; - break; - case RTSP_STATUS_AGGREGATE: - str = "Aggregate operation not allowed"; - break; - case RTSP_STATUS_ONLY_AGGREGATE: - str = "Only aggregate operation allowed"; - break; - case RTSP_STATUS_TRANSPORT: - str = "Unsupported transport"; - break; - case RTSP_STATUS_INTERNAL: - str = "Internal Server Error"; - break; - case RTSP_STATUS_SERVICE: - str = "Service Unavailable"; - break; - case RTSP_STATUS_VERSION: - str = "RTSP Version not supported"; - break; - default: + str = RTSP_STATUS_CODE2STRING(error_number); + if (!str) str = "Unknown Error"; - break; - } avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str); avio_printf(c->pb, "CSeq: %d\r\n", c->seq); @@ -3047,7 +3035,7 @@ static void rtsp_cmd_describe(HTTPContext *c, const char *url) socklen_t len; struct sockaddr_in my_addr; - /* find which url is asked */ + /* find which URL is asked */ av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); path = path1; if (*path == '/') @@ -3065,7 +3053,7 @@ static void rtsp_cmd_describe(HTTPContext *c, const char *url) return; found: - /* prepare the media description in sdp format */ + /* prepare the media description in SDP format */ /* get the host IP */ len = sizeof(my_addr); @@ -3124,7 +3112,7 @@ static void rtsp_cmd_setup(HTTPContext *c, const char *url, struct sockaddr_in dest_addr; RTSPActionServerSetup setup; - /* find which url is asked */ + /* find which URL is asked */ av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); path = path1; if (*path == '/') @@ -3166,7 +3154,7 @@ static void rtsp_cmd_setup(HTTPContext *c, const char *url, random0, random1); } - /* find rtp session, and create it if none found */ + /* find RTP session, and create it if none found */ rtp_c = find_rtp_session(h->session_id); if (!rtp_c) { /* always prefer UDP */ @@ -3255,7 +3243,7 @@ static void rtsp_cmd_setup(HTTPContext *c, const char *url, } -/* find an rtp connection by using the session ID. Check consistency +/* find an RTP connection by using the session ID. Check consistency with filename */ static HTTPContext *find_rtp_session_with_url(const char *url, const char *session_id) @@ -3270,7 +3258,7 @@ static HTTPContext *find_rtp_session_with_url(const char *url, if (!rtp_c) return NULL; - /* find which url is asked */ + /* find which URL is asked */ av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); path = path1; if (*path == '/') @@ -3501,6 +3489,7 @@ static int rtp_new_av_stream(HTTPContext *c, fail: if (h) ffurl_close(h); + av_free(st); av_free(ctx); return -1; } @@ -3599,7 +3588,7 @@ static void remove_stream(FFStream *stream) } } -/* specific mpeg4 handling : we extract the raw parameters */ +/* specific MPEG4 handling : we extract the raw parameters */ static void extract_mpeg4_header(AVFormatContext *infile) { int mpeg4_count, i, size; @@ -3824,7 +3813,7 @@ static void build_feed_streams(void) http_log("Container doesn't support the required parameters\n"); exit(1); } - /* XXX: need better api */ + /* XXX: need better API */ av_freep(&s->priv_data); avio_close(s->pb); s->streams = NULL; @@ -4321,7 +4310,7 @@ static int parse_ffconfig(const char *filename) stream->fmt = NULL; } else { stream->stream_type = STREAM_TYPE_LIVE; - /* jpeg cannot be used here, so use single frame jpeg */ + /* JPEG cannot be used here, so use single frame MJPEG */ if (!strcmp(arg, "jpeg")) strcpy(arg, "mjpeg"); stream->fmt = ffserver_guess_format(arg, NULL, NULL); diff --git a/libavcodec/4xm.c b/libavcodec/4xm.c index 4add46fe4..3d3bc5621 100644 --- a/libavcodec/4xm.c +++ b/libavcodec/4xm.c @@ -24,13 +24,16 @@ * 4XM codec. */ +#include + #include "libavutil/avassert.h" #include "libavutil/frame.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "blockdsp.h" +#include "bswapdsp.h" #include "bytestream.h" -#include "dsputil.h" #include "get_bits.h" #include "internal.h" @@ -131,7 +134,8 @@ typedef struct CFrameBuffer { typedef struct FourXContext { AVCodecContext *avctx; - DSPContext dsp; + BlockDSPContext bdsp; + BswapDSPContext bbdsp; uint16_t *frame_buffer; uint16_t *last_frame_buffer; GetBitContext pre_gb; ///< ac/dc prefix @@ -456,8 +460,8 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length) bitstream_size); if (!f->bitstream_buffer) return AVERROR(ENOMEM); - f->dsp.bswap_buf(f->bitstream_buffer, (const uint32_t*)(buf + extra), - bitstream_size / 4); + f->bbdsp.bswap_buf(f->bitstream_buffer, (const uint32_t *) (buf + extra), + bitstream_size / 4); init_get_bits(&f->gb, f->bitstream_buffer, 8 * bitstream_size); wordstream_offset = extra + bitstream_size; @@ -590,7 +594,7 @@ static int decode_i_mb(FourXContext *f) int ret; int i; - f->dsp.clear_blocks(f->block[0]); + f->bdsp.clear_blocks(f->block[0]); for (i = 0; i < 6; i++) if ((ret = decode_i_block(f, f->block[i])) < 0) @@ -795,8 +799,8 @@ static int decode_i_frame(FourXContext *f, const uint8_t *buf, int length) prestream_size); if (!f->bitstream_buffer) return AVERROR(ENOMEM); - f->dsp.bswap_buf(f->bitstream_buffer, (const uint32_t*)prestream, - prestream_size / 4); + f->bbdsp.bswap_buf(f->bitstream_buffer, (const uint32_t *) prestream, + prestream_size / 4); init_get_bits(&f->pre_gb, f->bitstream_buffer, 8 * prestream_size); f->last_dc = 0 * 128 * 8 * 8; @@ -831,7 +835,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, av_assert0(avctx->width % 16 == 0 && avctx->height % 16 == 0); if (buf_size < AV_RL32(buf + 4) + 8) { - av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d\n", + av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %"PRIu32"\n", buf_size, AV_RL32(buf + 4)); return AVERROR_INVALIDDATA; } @@ -996,7 +1000,8 @@ static av_cold int decode_init(AVCodecContext *avctx) } f->version = AV_RL32(avctx->extradata) >> 16; - ff_dsputil_init(&f->dsp, avctx); + ff_blockdsp_init(&f->bdsp, avctx); + ff_bswapdsp_init(&f->bbdsp); f->avctx = avctx; init_vlcs(f); diff --git a/libavcodec/8bps.c b/libavcodec/8bps.c index d01ef924c..e00bdfc80 100644 --- a/libavcodec/8bps.c +++ b/libavcodec/8bps.c @@ -150,7 +150,7 @@ static av_cold int decode_init(AVCodecContext *avctx) c->planemap[0] = 0; // 1st plane is palette indexes break; case 24: - avctx->pix_fmt = avctx->get_format(avctx, pixfmt_rgb24); + avctx->pix_fmt = ff_get_format(avctx, pixfmt_rgb24); c->planes = 3; c->planemap[0] = 2; // 1st plane is red c->planemap[1] = 1; // 2nd plane is green diff --git a/libavcodec/Makefile b/libavcodec/Makefile index b56ecd197..0bbfa27e4 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1,10 +1,10 @@ include $(SUBDIR)../config.mak NAME = avcodec -FFLIBS = avutil HEADERS = avcodec.h \ avfft.h \ + dv_profile.h \ dxva2.h \ old_codec_ids.h \ vaapi.h \ @@ -20,6 +20,7 @@ OBJS = allcodecs.o \ bitstream.o \ bitstream_filter.o \ codec_desc.o \ + dv_profile.o \ fmtconvert.o \ imgconvert.o \ mathtables.o \ @@ -34,14 +35,18 @@ OBJS = allcodecs.o \ OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o OBJS-$(CONFIG_AC3DSP) += ac3dsp.o OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o +OBJS-$(CONFIG_AUDIODSP) += audiodsp.o +OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o +OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o +OBJS-$(CONFIG_CABAC) += cabac.o OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o +OBJS-$(CONFIG_DSPUTIL) += dsputil.o OBJS-$(CONFIG_DXVA2) += dxva2.o -OBJS-$(CONFIG_DSPUTIL) += dsputil.o faanidct.o \ - simple_idct.o jrevdct.o -OBJS-$(CONFIG_ENCODERS) += faandct.o jfdctfst.o jfdctint.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o OBJS-$(CONFIG_EXIF) += exif.o tiff_common.o +OBJS-$(CONFIG_FDCTDSP) += fdctdsp.o faandct.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_fixed_32.o fft_init_table.o \ @@ -49,32 +54,44 @@ OBJS-$(CONFIG_FFT) += avfft.o fft_fixed.o fft_float.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_H264DSP) += h264dsp.o h264idct.o startcode.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_INTRAX8) += intrax8.o intrax8dsp.o OBJS-$(CONFIG_LIBXVID) += libxvid_rc.o +OBJS-$(CONFIG_LLAUDDSP) += lossless_audiodsp.o OBJS-$(CONFIG_LLVIDDSP) += lossless_videodsp.o OBJS-$(CONFIG_LPC) += lpc.o OBJS-$(CONFIG_LSP) += lsp.o OBJS-$(CONFIG_MDCT) += mdct_fixed.o mdct_float.o mdct_fixed_32.o +OBJS-$(CONFIG_MPEG_ER) += mpeg_er.o OBJS-$(CONFIG_MPEGAUDIO) += mpegaudio.o mpegaudiodata.o \ mpegaudiodecheader.o OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_data.o \ mpegaudiodsp_fixed.o \ mpegaudiodsp_float.o -OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideo_motion.o +OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o \ + mpegvideo_motion.o mpegutils.o OBJS-$(CONFIG_MPEGVIDEOENC) += mpegvideo_enc.o mpeg12data.o \ - motion_est.o ratecontrol.o + motion_est.o ratecontrol.o \ + mpegvideoencdsp.o +OBJS-$(CONFIG_PIXBLOCKDSP) += pixblockdsp.o +OBJS-$(CONFIG_QPELDSP) += qpeldsp.o OBJS-$(CONFIG_RANGECODER) += rangecoder.o RDFT-OBJS-$(CONFIG_HARDCODED_TABLES) += sin_tables.o OBJS-$(CONFIG_RDFT) += rdft.o $(RDFT-OBJS-yes) OBJS-$(CONFIG_SHARED) += log2_tab.o OBJS-$(CONFIG_SINEWIN) += sinewin.o +OBJS-$(CONFIG_TPELDSP) += tpeldsp.o OBJS-$(CONFIG_VAAPI) += vaapi.o +OBJS-$(CONFIG_VDA) += vda.o OBJS-$(CONFIG_VDPAU) += vdpau.o OBJS-$(CONFIG_VIDEODSP) += videodsp.o OBJS-$(CONFIG_VP3DSP) += vp3dsp.o @@ -91,13 +108,16 @@ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o \ psymodel.o iirfilter.o \ mpeg4audio.o kbdwin.o OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o -OBJS-$(CONFIG_AC3_DECODER) += ac3dec.o ac3dec_data.o ac3.o kbdwin.o +OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o kbdwin.o +OBJS-$(CONFIG_AC3_FIXED_DECODER) += ac3dec_fixed.o ac3dec_data.o ac3.o kbdwin.o OBJS-$(CONFIG_AC3_ENCODER) += ac3enc_float.o ac3enc.o ac3tab.o \ ac3.o kbdwin.o OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o OBJS-$(CONFIG_AIC_DECODER) += aic.o OBJS-$(CONFIG_ALAC_DECODER) += alac.o alac_data.o OBJS-$(CONFIG_ALAC_ENCODER) += alacenc.o alac_data.o +OBJS-$(CONFIG_ALIAS_PIX_DECODER) += aliaspixdec.o +OBJS-$(CONFIG_ALIAS_PIX_ENCODER) += aliaspixenc.o OBJS-$(CONFIG_ALS_DECODER) += alsdec.o bgmc.o mpeg4audio.o OBJS-$(CONFIG_AMRNB_DECODER) += amrnbdec.o celp_filters.o \ celp_math.o acelp_filters.o \ @@ -107,8 +127,7 @@ OBJS-$(CONFIG_AMRWB_DECODER) += amrwbdec.o celp_filters.o \ celp_math.o acelp_filters.o \ acelp_vectors.o \ acelp_pitch_delay.o -OBJS-$(CONFIG_AMV_DECODER) += sp5xdec.o mjpegdec.o mjpeg.o -OBJS-$(CONFIG_AMV_ENCODER) += mjpegenc.o mjpeg.o \ +OBJS-$(CONFIG_AMV_ENCODER) += mjpegenc.o mjpeg.o mjpegenc_common.o \ mpegvideo_enc.o motion_est.o \ ratecontrol.o mpeg12data.o \ mpegvideo.o @@ -145,9 +164,9 @@ OBJS-$(CONFIG_BINKAUDIO_RDFT_DECODER) += binkaudio.o wma.o wma_common.o OBJS-$(CONFIG_BINTEXT_DECODER) += bintext.o cga_data.o OBJS-$(CONFIG_BMP_DECODER) += bmp.o msrledec.o OBJS-$(CONFIG_BMP_ENCODER) += bmpenc.o -OBJS-$(CONFIG_BMV_VIDEO_DECODER) += bmv.o -OBJS-$(CONFIG_BMV_AUDIO_DECODER) += bmv.o -OBJS-$(CONFIG_BRENDER_PIX_DECODER) += brender_pix.o +OBJS-$(CONFIG_BMV_AUDIO_DECODER) += bmvaudio.o +OBJS-$(CONFIG_BMV_VIDEO_DECODER) += bmvvideo.o +OBJS-$(CONFIG_BRENDER_PIX_DECODER) += brenderpix.o OBJS-$(CONFIG_C93_DECODER) += c93.o OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ cavsdata.o mpeg12data.o @@ -155,8 +174,8 @@ OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o OBJS-$(CONFIG_CINEPAK_ENCODER) += cinepakenc.o elbg.o -OBJS-$(CONFIG_CLJR_DECODER) += cljr.o -OBJS-$(CONFIG_CLJR_ENCODER) += cljr.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_COMFORTNOISE_DECODER) += cngdec.o celp_filters.o @@ -174,14 +193,18 @@ OBJS-$(CONFIG_DNXHD_DECODER) += dnxhddec.o dnxhddata.o OBJS-$(CONFIG_DNXHD_ENCODER) += dnxhdenc.o dnxhddata.o OBJS-$(CONFIG_DPX_DECODER) += dpx.o OBJS-$(CONFIG_DPX_ENCODER) += dpxenc.o -OBJS-$(CONFIG_DSICINAUDIO_DECODER) += dsicinav.o -OBJS-$(CONFIG_DSICINVIDEO_DECODER) += dsicinav.o +OBJS-$(CONFIG_DSD_LSBF_DECODER) += dsddec.o +OBJS-$(CONFIG_DSD_MSBF_DECODER) += dsddec.o +OBJS-$(CONFIG_DSD_LSBF_PLANAR_DECODER) += dsddec.o +OBJS-$(CONFIG_DSD_MSBF_PLANAR_DECODER) += dsddec.o +OBJS-$(CONFIG_DSICINAUDIO_DECODER) += dsicinaudio.o +OBJS-$(CONFIG_DSICINVIDEO_DECODER) += dsicinvideo.o OBJS-$(CONFIG_DVBSUB_DECODER) += dvbsubdec.o OBJS-$(CONFIG_DVBSUB_ENCODER) += dvbsub.o OBJS-$(CONFIG_DVDSUB_DECODER) += dvdsubdec.o OBJS-$(CONFIG_DVDSUB_ENCODER) += dvdsubenc.o -OBJS-$(CONFIG_DVVIDEO_DECODER) += dvdec.o dv.o dvdata.o dv_profile.o -OBJS-$(CONFIG_DVVIDEO_ENCODER) += dvenc.o dv.o dvdata.o dv_profile.o +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_EAC3_DECODER) += eac3dec.o eac3_data.o @@ -191,8 +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 mpeg12dec.o \ - mpeg12.o mpeg12data.o +OBJS-$(CONFIG_EATQI_DECODER) += eatqi.o eaidct.o OBJS-$(CONFIG_EIGHTBPS_DECODER) += 8bps.o OBJS-$(CONFIG_EIGHTSVX_EXP_DECODER) += 8svx.o OBJS-$(CONFIG_EIGHTSVX_FIB_DECODER) += 8svx.o @@ -202,8 +224,6 @@ OBJS-$(CONFIG_EVRC_DECODER) += evrcdec.o acelp_vectors.o lsp.o OBJS-$(CONFIG_EXR_DECODER) += exr.o OBJS-$(CONFIG_FFV1_DECODER) += ffv1dec.o ffv1.o OBJS-$(CONFIG_FFV1_ENCODER) += ffv1enc.o ffv1.o -OBJS-$(CONFIG_FFVHUFF_DECODER) += huffyuv.o huffyuvdec.o -OBJS-$(CONFIG_FFVHUFF_ENCODER) += huffyuv.o huffyuvenc.o OBJS-$(CONFIG_FFWAVESYNTH_DECODER) += ffwavesynth.o OBJS-$(CONFIG_FIC_DECODER) += fic.o OBJS-$(CONFIG_FLAC_DECODER) += flacdec.o flacdata.o flac.o flacdsp.o @@ -232,18 +252,17 @@ OBJS-$(CONFIG_H263_DECODER) += h263dec.o h263.o ituh263dec.o \ intelh263dec.o OBJS-$(CONFIG_H263_ENCODER) += mpeg4videoenc.o mpeg4video.o \ h263.o ituh263enc.o flvenc.o -OBJS-$(CONFIG_H264_DECODER) += h264.o \ - h264_loopfilter.o h264_direct.o \ - cabac.o h264_sei.o h264_ps.o \ - h264_refs.o h264_cavlc.o h264_cabac.o +OBJS-$(CONFIG_H264_DECODER) += h264.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 OBJS-$(CONFIG_H264_VDA_DECODER) += vda_h264_dec.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 cabac.o + hevcdsp.o hevc_filter.o OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o huffyuvdec.o OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o huffyuvenc.o -OBJS-$(CONFIG_IAC_DECODER) += imc.o OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o OBJS-$(CONFIG_IDF_DECODER) += bintext.o cga_data.o OBJS-$(CONFIG_IFF_BYTERUN1_DECODER) += iff.o @@ -260,14 +279,13 @@ OBJS-$(CONFIG_JPEG2000_ENCODER) += j2kenc.o mqcenc.o mqc.o jpeg2000.o \ jpeg2000dwt.o OBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dec.o jpeg2000.o \ jpeg2000dwt.o mqcdec.o mqc.o -OBJS-$(CONFIG_JPEGLS_DECODER) += jpeglsdec.o jpegls.o \ - mjpegdec.o mjpeg.o +OBJS-$(CONFIG_JPEGLS_DECODER) += jpeglsdec.o jpegls.o OBJS-$(CONFIG_JPEGLS_ENCODER) += jpeglsenc.o jpegls.o OBJS-$(CONFIG_JV_DECODER) += jvdec.o OBJS-$(CONFIG_KGV1_DECODER) += kgv1dec.o OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o -OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc.o mjpeg.o +OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpeg.o mjpegenc_common.o OBJS-$(CONFIG_LOCO_DECODER) += loco.o OBJS-$(CONFIG_MACE3_DECODER) += mace.o OBJS-$(CONFIG_MACE6_DECODER) += mace.o @@ -277,8 +295,8 @@ OBJS-$(CONFIG_METASOUND_DECODER) += metasound.o metasound_data.o \ OBJS-$(CONFIG_MICRODVD_DECODER) += microdvddec.o ass.o OBJS-$(CONFIG_MIMIC_DECODER) += mimic.o OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o mjpeg.o -OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpeg.o -OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o mjpegdec.o mjpeg.o +OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpeg.o mjpegenc_common.o +OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o OBJS-$(CONFIG_MOTIONPIXELS_DECODER) += motionpixels.o @@ -322,12 +340,16 @@ OBJS-$(CONFIG_MSZH_DECODER) += lcldec.o OBJS-$(CONFIG_MTS2_DECODER) += mss4.o mss34dsp.o OBJS-$(CONFIG_MVC1_DECODER) += mvcdec.o OBJS-$(CONFIG_MVC2_DECODER) += mvcdec.o -OBJS-$(CONFIG_MXPEG_DECODER) += mxpegdec.o mjpegdec.o mjpeg.o +OBJS-$(CONFIG_MXPEG_DECODER) += mxpegdec.o OBJS-$(CONFIG_NELLYMOSER_DECODER) += nellymoserdec.o nellymoser.o OBJS-$(CONFIG_NELLYMOSER_ENCODER) += nellymoserenc.o nellymoser.o OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o -OBJS-$(CONFIG_PAF_VIDEO_DECODER) += paf.o -OBJS-$(CONFIG_PAF_AUDIO_DECODER) += paf.o +OBJS-$(CONFIG_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 +OBJS-$(CONFIG_PAF_AUDIO_DECODER) += pafaudio.o +OBJS-$(CONFIG_PAF_VIDEO_DECODER) += pafvideo.o OBJS-$(CONFIG_PAM_DECODER) += pnmdec.o pnm.o OBJS-$(CONFIG_PAM_ENCODER) += pamenc.o OBJS-$(CONFIG_PBM_DECODER) += pnmdec.o pnm.o @@ -405,7 +427,7 @@ OBJS-$(CONFIG_SOL_DPCM_DECODER) += dpcm.o OBJS-$(CONFIG_SONIC_DECODER) += sonic.o OBJS-$(CONFIG_SONIC_ENCODER) += sonic.o OBJS-$(CONFIG_SONIC_LS_ENCODER) += sonic.o -OBJS-$(CONFIG_SP5X_DECODER) += sp5xdec.o mjpegdec.o mjpeg.o +OBJS-$(CONFIG_SP5X_DECODER) += sp5xdec.o OBJS-$(CONFIG_SRT_DECODER) += srtdec.o ass.o OBJS-$(CONFIG_SRT_ENCODER) += srtenc.o ass_split.o OBJS-$(CONFIG_SUBRIP_DECODER) += srtdec.o ass.o @@ -417,17 +439,13 @@ OBJS-$(CONFIG_SUNRAST_ENCODER) += sunrastenc.o OBJS-$(CONFIG_SVQ1_DECODER) += svq1dec.o svq1.o svq13.o h263.o OBJS-$(CONFIG_SVQ1_ENCODER) += svq1enc.o svq1.o \ h263.o ituh263enc.o -OBJS-$(CONFIG_SVQ3_DECODER) += svq3.o svq13.o h263.o h264.o \ - h264_loopfilter.o h264_direct.o \ - h264_sei.o h264_ps.o h264_refs.o \ - h264_cavlc.o h264_cabac.o cabac.o +OBJS-$(CONFIG_SVQ3_DECODER) += svq3.o svq13.o mpegutils.o OBJS-$(CONFIG_TEXT_DECODER) += textdec.o ass.o OBJS-$(CONFIG_TAK_DECODER) += takdec.o tak.o OBJS-$(CONFIG_TARGA_DECODER) += targa.o OBJS-$(CONFIG_TARGA_ENCODER) += targaenc.o rle.o OBJS-$(CONFIG_TARGA_Y216_DECODER) += targa_y216dec.o OBJS-$(CONFIG_THEORA_DECODER) += xiph.o -OBJS-$(CONFIG_THP_DECODER) += mjpegdec.o mjpeg.o OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o OBJS-$(CONFIG_TIFF_DECODER) += tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o OBJS-$(CONFIG_TIFF_ENCODER) += tiffenc.o rle.o lzwenc.o tiff_data.o @@ -458,10 +476,10 @@ 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 \ - wmv2dsp.o + wmv2dsp.o startcode.o OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o -OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o -OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdav.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 @@ -472,6 +490,7 @@ OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o vp56dsp.o \ vp56rac.o OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o vp56dsp.o \ vp6dsp.o vp56rac.o +OBJS-$(CONFIG_VP7_DECODER) += vp8.o vp8dsp.o vp56rac.o OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp8dsp.o vp56rac.o OBJS-$(CONFIG_VP9_DECODER) += vp9.o vp9dsp.o vp56rac.o OBJS-$(CONFIG_VPLAYER_DECODER) += textdec.o ass.o @@ -481,6 +500,7 @@ OBJS-$(CONFIG_WAVPACK_ENCODER) += wavpackenc.o OBJS-$(CONFIG_WEBP_DECODER) += vp8.o vp8dsp.o vp56rac.o OBJS-$(CONFIG_WEBP_DECODER) += webp.o exif.o tiff_common.o OBJS-$(CONFIG_WEBVTT_DECODER) += webvttdec.o +OBJS-$(CONFIG_WEBVTT_ENCODER) += webvttenc.o ass_split.o OBJS-$(CONFIG_WMALOSSLESS_DECODER) += wmalosslessdec.o wma_common.o OBJS-$(CONFIG_WMAPRO_DECODER) += wmaprodec.o wma.o wma_common.o OBJS-$(CONFIG_WMAV1_DECODER) += wmadec.o wma.o wma_common.o aactab.o @@ -491,6 +511,7 @@ 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_WMV1_ENCODER) += msmpeg4enc.o OBJS-$(CONFIG_WMV2_DECODER) += wmv2dec.o wmv2.o wmv2dsp.o \ msmpeg4dec.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_WMV2_ENCODER) += wmv2enc.o wmv2.o wmv2dsp.o \ @@ -619,6 +640,7 @@ OBJS-$(CONFIG_ADPCM_SBPRO_4_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_SWF_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_SWF_ENCODER) += adpcmenc.o adpcm_data.o OBJS-$(CONFIG_ADPCM_THP_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_VIMA_DECODER) += vima.o adpcm_data.o OBJS-$(CONFIG_ADPCM_XA_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o @@ -645,11 +667,8 @@ OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o # libavformat dependencies OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_ADX_DEMUXER) += adx.o OBJS-$(CONFIG_CAF_DEMUXER) += mpeg4audio.o mpegaudiodata.o \ ac3tab.o -OBJS-$(CONFIG_DV_DEMUXER) += dv_profile.o -OBJS-$(CONFIG_DV_MUXER) += dv_profile.o OBJS-$(CONFIG_FLAC_DEMUXER) += flac.o flacdata.o vorbis_data.o \ vorbis_parser.o xiph.o OBJS-$(CONFIG_FLAC_MUXER) += flac.o flacdata.o vorbis_data.o @@ -660,7 +679,8 @@ OBJS-$(CONFIG_ISMV_MUXER) += mpeg4audio.o mpegaudiodata.o OBJS-$(CONFIG_LATM_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += xiph.o mpeg4audio.o vorbis_data.o \ flac.o flacdata.o -OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o mpegaudiodata.o +OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o mpegaudiodata.o \ + vorbis_parser.o xiph.o OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o mpegaudiodata.o \ flac.o flacdata.o vorbis_data.o xiph.o OBJS-$(CONFIG_MP2_MUXER) += mpegaudiodata.o mpegaudiodecheader.o @@ -671,6 +691,7 @@ OBJS-$(CONFIG_MPEGTS_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpeg4audio.o mpegaudiodata.o OBJS-$(CONFIG_MXF_MUXER) += dnxhddata.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o +OBJS-$(CONFIG_OGA_MUXER) += xiph.o flac.o flacdata.o OBJS-$(CONFIG_OGG_DEMUXER) += xiph.o flac.o flacdata.o \ mpeg12data.o vorbis_parser.o \ dirac.o vorbis_data.o @@ -762,11 +783,7 @@ 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 h264.o \ - cabac.o \ - h264_refs.o h264_sei.o h264_direct.o \ - h264_loopfilter.o h264_cabac.o \ - h264_cavlc.o h264_ps.o +OBJS-$(CONFIG_H264_PARSER) += h264_parser.o OBJS-$(CONFIG_HEVC_PARSER) += hevc_parser.o OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o OBJS-$(CONFIG_MLP_PARSER) += mlp_parser.o mlp.o @@ -778,14 +795,15 @@ OBJS-$(CONFIG_MPEGAUDIO_PARSER) += mpegaudio_parser.o \ mpegaudiodecheader.o mpegaudiodata.o OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o \ mpeg12.o mpeg12data.o +OBJS-$(CONFIG_OPUS_PARSER) += opus_parser.o opus.o vorbis_data.o OBJS-$(CONFIG_PNG_PARSER) += png_parser.o OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o OBJS-$(CONFIG_RV40_PARSER) += rv34_parser.o OBJS-$(CONFIG_TAK_PARSER) += tak_parser.o tak.o -OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o \ +OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o vc1dsp.o \ msmpeg4.o msmpeg4data.o mpeg4video.o \ - h263.o + h263.o startcode.o OBJS-$(CONFIG_VORBIS_PARSER) += vorbis_parser.o xiph.o OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o OBJS-$(CONFIG_VP8_PARSER) += vp8_parser.o @@ -820,6 +838,7 @@ SKIPHEADERS += %_tablegen.h \ %_tables.h \ aac_tablegen_decl.h \ fft-internal.h \ + libutvideo.h \ old_codec_ids.h \ tableprint.h \ $(ARCH)/vp56_arith.h \ @@ -829,7 +848,7 @@ SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h SKIPHEADERS-$(CONFIG_LIBUTVIDEO) += libutvideo.h SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h -SKIPHEADERS-$(CONFIG_VDA) += vda.h +SKIPHEADERS-$(CONFIG_VDA) += vda.h vda_internal.h SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h vdpau_internal.h TESTPROGS = cabac \ @@ -852,6 +871,7 @@ HOSTPROGS = aac_tablegen \ aacps_tablegen \ cbrt_tablegen \ cos_tablegen \ + dsd_tablegen \ dv_tablegen \ motionpixels_tablegen \ mpegaudio_tablegen \ @@ -876,7 +896,7 @@ else $(SUBDIR)%_tablegen$(HOSTEXESUF): HOSTCFLAGS += -DCONFIG_SMALL=0 endif -GEN_HEADERS = cbrt_tables.h aacps_tables.h aac_tables.h dv_tables.h \ +GEN_HEADERS = cbrt_tables.h aacps_tables.h aac_tables.h dsd_tables.h dv_tables.h \ sinewin_tables.h mpegaudio_tables.h motionpixels_tables.h \ pcm_tables.h qdm2_tables.h GEN_HEADERS := $(addprefix $(SUBDIR), $(GEN_HEADERS)) @@ -888,6 +908,7 @@ ifdef CONFIG_HARDCODED_TABLES $(SUBDIR)aacdec.o: $(SUBDIR)cbrt_tables.h $(SUBDIR)aacps.o: $(SUBDIR)aacps_tables.h $(SUBDIR)aactab.o: $(SUBDIR)aac_tables.h +$(SUBDIR)dsddec.o: $(SUBDIR)dsd_tables.h $(SUBDIR)dvenc.o: $(SUBDIR)dv_tables.h $(SUBDIR)sinewin.o: $(SUBDIR)sinewin_tables.h $(SUBDIR)mpegaudiodec_fixed.o: $(SUBDIR)mpegaudio_tables.h diff --git a/libavcodec/a64multienc.c b/libavcodec/a64multienc.c index af3f96521..306777418 100644 --- a/libavcodec/a64multienc.c +++ b/libavcodec/a64multienc.c @@ -220,9 +220,9 @@ static av_cold int a64multi_encode_init(AVCodecContext *avctx) a64_palette[mc_colors[a]][2] * 0.11; } - if (!(c->mc_meta_charset = av_malloc(32000 * c->mc_lifetime * sizeof(int))) || + if (!(c->mc_meta_charset = av_malloc_array(c->mc_lifetime, 32000 * sizeof(int))) || !(c->mc_best_cb = av_malloc(CHARSET_CHARS * 32 * sizeof(int))) || - !(c->mc_charmap = av_mallocz(1000 * c->mc_lifetime * sizeof(int))) || + !(c->mc_charmap = av_mallocz_array(c->mc_lifetime, 1000 * sizeof(int))) || !(c->mc_colram = av_mallocz(CHARSET_CHARS * sizeof(uint8_t))) || !(c->mc_charset = av_malloc(0x800 * (INTERLACED+1) * sizeof(uint8_t)))) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate buffer memory.\n"); diff --git a/libavcodec/aacadtsdec.c b/libavcodec/aacadtsdec.c index c9718c459..d0814ac27 100644 --- a/libavcodec/aacadtsdec.c +++ b/libavcodec/aacadtsdec.c @@ -31,7 +31,7 @@ int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr) int size, rdb, ch, sr; int aot, crc_abs; - if(get_bits(gbc, 12) != 0xfff) + if (get_bits(gbc, 12) != 0xfff) return AAC_AC3_PARSE_ERROR_SYNC; skip_bits1(gbc); /* id */ @@ -39,10 +39,10 @@ int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr) crc_abs = get_bits1(gbc); /* protection_absent */ aot = get_bits(gbc, 2); /* profile_objecttype */ sr = get_bits(gbc, 4); /* sample_frequency_index */ - if(!avpriv_mpeg4audio_sample_rates[sr]) + if (!avpriv_mpeg4audio_sample_rates[sr]) return AAC_AC3_PARSE_ERROR_SAMPLE_RATE; skip_bits1(gbc); /* private_bit */ - ch = get_bits(gbc, 3); /* channel_configuration */ + ch = get_bits(gbc, 3); /* channel_configuration */ skip_bits1(gbc); /* original/copy */ skip_bits1(gbc); /* home */ @@ -50,8 +50,8 @@ int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr) /* adts_variable_header */ skip_bits1(gbc); /* copyright_identification_bit */ skip_bits1(gbc); /* copyright_identification_start */ - size = get_bits(gbc, 13); /* aac_frame_length */ - if(size < AAC_ADTS_HEADER_SIZE) + size = get_bits(gbc, 13); /* aac_frame_length */ + if (size < AAC_ADTS_HEADER_SIZE) return AAC_AC3_PARSE_ERROR_FRAME_SIZE; skip_bits(gbc, 11); /* adts_buffer_fullness */ diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c index 3586aabbe..10c509be8 100644 --- a/libavcodec/aacdec.c +++ b/libavcodec/aacdec.c @@ -1946,7 +1946,7 @@ 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 + // I see no textual basis in the spec for this occurring after SSR gain // control, but this is what both reference and real implmentations do if (tns->present && er_syntax) if (decode_tns(ac, tns, gb, ics) < 0) @@ -2631,7 +2631,7 @@ static void apply_dependent_coupling(AACContext *ac, const float gain = cce->coup.gain[index][idx]; for (group = 0; group < ics->group_len[g]; group++) { for (k = offsets[i]; k < offsets[i + 1]; k++) { - // XXX dsputil-ize + // FIXME: SIMDify dest[group * 128 + k] += gain * src[group * 128 + k]; } } diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index 5596b4bfa..499aefb9f 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -769,7 +769,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) if (HAVE_MIPSDSPR1) ff_aac_coder_init_mips(s); - s->lambda = avctx->global_quality ? avctx->global_quality : 120; + s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120; ff_aac_tableinit(); diff --git a/libavcodec/aacpsy.c b/libavcodec/aacpsy.c index d2a782e8d..9eeb83652 100644 --- a/libavcodec/aacpsy.c +++ b/libavcodec/aacpsy.c @@ -354,7 +354,7 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) { } } - pctx->ch = av_mallocz(sizeof(AacPsyChannel) * ctx->avctx->channels); + pctx->ch = av_mallocz_array(ctx->avctx->channels, sizeof(AacPsyChannel)); lame_window_init(pctx, ctx->avctx); diff --git a/libavcodec/aandcttab.c b/libavcodec/aandcttab.c index 87c50b37c..97013d2b5 100644 --- a/libavcodec/aandcttab.c +++ b/libavcodec/aandcttab.c @@ -18,7 +18,7 @@ /** * @file - * AAN (Arai Agui Aakajima) (I)DCT tables + * AAN (Arai, Agui and Nakajima) (I)DCT tables */ #include diff --git a/libavcodec/aandcttab.h b/libavcodec/aandcttab.h index d774828a4..b0a2f44ec 100644 --- a/libavcodec/aandcttab.h +++ b/libavcodec/aandcttab.h @@ -18,7 +18,7 @@ /** * @file - * AAN (Arai Agui Nakajima) (I)DCT tables + * AAN (Arai, Agui and Nakajima) (I)DCT tables */ #ifndef AVCODEC_AANDCTTAB_H diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile index af89f93ac..964428e35 100644 --- a/libavcodec/aarch64/Makefile +++ b/libavcodec/aarch64/Makefile @@ -1,14 +1,28 @@ +OBJS-$(CONFIG_FFT) += aarch64/fft_init_aarch64.o OBJS-$(CONFIG_H264CHROMA) += aarch64/h264chroma_init_aarch64.o OBJS-$(CONFIG_H264DSP) += aarch64/h264dsp_init_aarch64.o OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_init_aarch64.o OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_init_aarch64.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 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-OBJS-$(CONFIG_VIDEODSP) += aarch64/videodsp.o + +NEON-OBJS-$(CONFIG_FFT) += aarch64/fft_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_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_MDCT) += aarch64/mdct_neon.o + +NEON-OBJS-$(CONFIG_OPUS_DECODER) += aarch64/opus_imdct_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 new file mode 100644 index 000000000..8defd7c9e --- /dev/null +++ b/libavcodec/aarch64/asm-offsets.h @@ -0,0 +1,30 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AARCH64_ASM_OFFSETS_H +#define AVCODEC_AARCH64_ASM_OFFSETS_H + +/* CeltIMDCTContext */ +#define CELT_EXPTAB 0x20 +#define CELT_FFT_N 0x00 +#define CELT_LEN2 0x04 +#define CELT_LEN4 (CELT_LEN2 + 0x4) // loaded as pair +#define CELT_TMP 0x10 +#define CELT_TWIDDLE (CELT_TMP + 0x8) // loaded as pair + +#endif /* AVCODEC_AARCH64_ASM_OFFSETS_H */ diff --git a/libavcodec/aarch64/cabac.h b/libavcodec/aarch64/cabac.h new file mode 100644 index 000000000..6b9b77eb3 --- /dev/null +++ b/libavcodec/aarch64/cabac.h @@ -0,0 +1,104 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AARCH64_CABAC_H +#define AVCODEC_AARCH64_CABAC_H + +#include "config.h" +#if HAVE_INLINE_ASM + +#include "libavutil/attributes.h" +#include "libavutil/internal.h" +#include "libavcodec/cabac.h" + +#define get_cabac_inline get_cabac_inline_aarch64 +static av_always_inline int get_cabac_inline_aarch64(CABACContext *c, + uint8_t *const state) +{ + int bit; + void *reg_a, *reg_b, *reg_c, *tmp; + + __asm__ volatile( + "ldrb %w[bit] , [%[state]] \n\t" + "add %[r_b] , %[tables] , %[lps_off] \n\t" + "mov %w[tmp] , %w[range] \n\t" + "and %w[range] , %w[range] , #0xC0 \n\t" + "lsl %w[r_c] , %w[range] , #1 \n\t" + "add %[r_b] , %[r_b] , %w[bit], UXTW \n\t" + "ldrb %w[range] , [%[r_b], %w[r_c], SXTW] \n\t" + "sub %w[r_c] , %w[tmp] , %w[range] \n\t" + "lsl %w[tmp] , %w[r_c] , #17 \n\t" + "cmp %w[tmp] , %w[low] \n\t" + "csel %w[tmp] , %w[tmp] , wzr , cc \n\t" + "csel %w[range] , %w[r_c] , %w[range], gt \n\t" + "cinv %w[bit] , %w[bit] , cc \n\t" + "sub %w[low] , %w[low] , %w[tmp] \n\t" + "add %[r_b] , %[tables] , %[norm_off] \n\t" + "add %[r_a] , %[tables] , %[mlps_off] \n\t" + "ldrb %w[tmp] , [%[r_b], %w[range], SXTW] \n\t" + "ldrb %w[r_a] , [%[r_a], %w[bit], SXTW] \n\t" + "lsl %w[low] , %w[low] , %w[tmp] \n\t" + "lsl %w[range] , %w[range] , %w[tmp] \n\t" + "uxth %w[r_c] , %w[low] \n\t" + "strb %w[r_a] , [%[state]] \n\t" + "cbnz %w[r_c] , 2f \n\t" + "ldr %[r_c] , [%[c], %[byte]] \n\t" + "ldr %[r_a] , [%[c], %[end]] \n\t" + "ldrh %w[tmp] , [%[r_c]] \n\t" + "cmp %[r_c] , %[r_a] \n\t" + "b.ge 1f \n\t" + "add %[r_a] , %[r_c] , #2 \n\t" + "str %[r_a] , [%[c], %[byte]] \n\t" + "1: \n\t" + "sub %w[r_c] , %w[low] , #1 \n\t" + "eor %w[r_c] , %w[r_c] , %w[low] \n\t" + "rev %w[tmp] , %w[tmp] \n\t" + "lsr %w[r_c] , %w[r_c] , #15 \n\t" + "lsr %w[tmp] , %w[tmp] , #15 \n\t" + "ldrb %w[r_c] , [%[r_b], %w[r_c], SXTW] \n\t" + "mov %w[r_b] , #0xFFFF \n\t" + "mov %w[r_a] , #7 \n\t" + "sub %w[tmp] , %w[tmp] , %w[r_b] \n\t" + "sub %w[r_c] , %w[r_a] , %w[r_c] \n\t" + "lsl %w[tmp] , %w[tmp] , %w[r_c] \n\t" + "add %w[low] , %w[low] , %w[tmp] \n\t" + "2: \n\t" + : [bit]"=&r"(bit), + [low]"+&r"(c->low), + [range]"+&r"(c->range), + [r_a]"=&r"(reg_a), + [r_b]"=&r"(reg_b), + [r_c]"=&r"(reg_c), + [tmp]"=&r"(tmp) + : [c]"r"(c), + [state]"r"(state), + [tables]"r"(ff_h264_cabac_tables), + [byte]"i"(offsetof(CABACContext, bytestream)), + [end]"i"(offsetof(CABACContext, bytestream_end)), + [norm_off]"I"(H264_NORM_SHIFT_OFFSET), + [lps_off]"I"(H264_LPS_RANGE_OFFSET), + [mlps_off]"I"(H264_MLPS_STATE_OFFSET + 128) + : "memory", "cc" + ); + + return bit & 1; +} + +#endif /* HAVE_INLINE_ASM */ + +#endif /* AVCODEC_AARCH64_CABAC_H */ diff --git a/libavcodec/aarch64/fft_init_aarch64.c b/libavcodec/aarch64/fft_init_aarch64.c new file mode 100644 index 000000000..8514d3b07 --- /dev/null +++ b/libavcodec/aarch64/fft_init_aarch64.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.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(); + + 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 new file mode 100644 index 000000000..70365d4f6 --- /dev/null +++ b/libavcodec/aarch64/fft_neon.S @@ -0,0 +1,442 @@ +/* + * ARM NEON optimised FFT + * + * Copyright (c) 2009 Mans Rullgard + * Copyright (c) 2009 Naotoshi Nojiri + * Copyright (c) 2014 Janne Grunau + * + * This algorithm (though not any of the implementation details) is + * based on libdjbfft by D. J. Bernstein. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +#define M_SQRT1_2 0.70710678118654752440 + +.macro transpose d0, d1, s0, s1 + trn1 \d0, \s0, \s1 + trn2 \d1, \s0, \s1 +.endm + + +function fft4_neon + ld1 {v0.2s,v1.2s,v2.2s,v3.2s}, [x0] + + fadd v4.2s, v0.2s, v1.2s // r0+r1,i0+i1 + fsub v6.2s, v0.2s, v1.2s // r0-r1,i0-i1 + + ext v16.8b, v2.8b, v3.8b, #4 + ext v17.8b, v3.8b, v2.8b, #4 + + fadd v5.2s, v2.2s, v3.2s // i2+i3,r2+r3 + fsub v7.2s, v16.2s, v17.2s // r3-r2,i2-i3 + + fadd v0.2s, v4.2s, v5.2s + fsub v2.2s, v4.2s, v5.2s + fadd v1.2s, v6.2s, v7.2s + fsub v3.2s, v6.2s, v7.2s + + st1 {v0.2s,v1.2s,v2.2s,v3.2s}, [x0] + + ret +endfunc + +function fft8_neon + mov x1, x0 + ld1 {v0.2s, v1.2s, v2.2s, v3.2s}, [x0], #32 + ld1 {v16.2s,v17.2s,v18.2s,v19.2s}, [x0] + ext v22.8b, v2.8b, v3.8b, #4 + ext v23.8b, v3.8b, v2.8b, #4 + fadd v4.2s, v16.2s, v17.2s // r4+r5,i4+i5 + fadd v5.2s, v18.2s, v19.2s // r6+r7,i6+i7 + fsub v17.2s, v16.2s, v17.2s // r4-r5,i4-i5 + fsub v19.2s, v18.2s, v19.2s // r6-r7,i6-i7 + rev64 v27.2s, v28.2s // ??? + fadd v20.2s, v0.2s, v1.2s // r0+r1,i0+i1 + fadd v21.2s, v2.2s, v3.2s // r2+r3,i2+i3 + fmul v26.2s, v17.2s, v28.2s // -a2r*w,a2i*w + ext v6.8b, v4.8b, v5.8b, #4 + ext v7.8b, v5.8b, v4.8b, #4 + fmul v27.2s, v19.2s, v27.2s // a3r*w,-a3i*w + fsub v23.2s, v22.2s, v23.2s // i2-i3,r3-r2 + fsub v22.2s, v0.2s, v1.2s // r0-r1,i0-i1 + fmul v24.2s, v17.2s, v28.s[1] // a2r*w,a2i*w + fmul v25.2s, v19.2s, v28.s[1] // a3r*w,a3i*w + fadd v0.2s, v20.2s, v21.2s + fsub v2.2s, v20.2s, v21.2s + fadd v1.2s, v22.2s, v23.2s + rev64 v26.2s, v26.2s + rev64 v27.2s, v27.2s + fsub v3.2s, v22.2s, v23.2s + fsub v6.2s, v6.2s, v7.2s + fadd v24.2s, v24.2s, v26.2s // a2r+a2i,a2i-a2r t1,t2 + fadd v25.2s, v25.2s, v27.2s // a3r-a3i,a3i+a3r t5,t6 + fadd v7.2s, v4.2s, v5.2s + fsub v18.2s, v2.2s, v6.2s + ext v26.8b, v24.8b, v25.8b, #4 + ext v27.8b, v25.8b, v24.8b, #4 + fadd v2.2s, v2.2s, v6.2s + fsub v16.2s, v0.2s, v7.2s + fadd v5.2s, v25.2s, v24.2s + fsub v4.2s, v26.2s, v27.2s + fadd v0.2s, v0.2s, v7.2s + fsub v17.2s, v1.2s, v5.2s + fsub v19.2s, v3.2s, v4.2s + fadd v3.2s, v3.2s, v4.2s + fadd v1.2s, v1.2s, v5.2s + + st1 {v16.2s,v17.2s,v18.2s,v19.2s}, [x0] + st1 {v0.2s, v1.2s, v2.2s, v3.2s}, [x1] + + ret +endfunc + +function fft16_neon + mov x1, x0 + ld1 {v0.2s, v1.2s, v2.2s, v3.2s}, [x0], #32 + ld1 {v16.2s,v17.2s,v18.2s,v19.2s}, [x0], #32 + ext v22.8b, v2.8b, v3.8b, #4 + ext v23.8b, v3.8b, v2.8b, #4 + fadd v4.2s, v16.2s, v17.2s // r4+r5,i4+i5 + fadd v5.2s, v18.2s, v19.2s // r6+r7,i6+i7 + fsub v17.2s, v16.2s, v17.2s // r4-r5,i4-i5 + fsub v19.2s, v18.2s, v19.2s // r6-r7,i6-i7 + rev64 v27.2s, v28.2s // ??? + fadd v20.2s, v0.2s, v1.2s // r0+r1,i0+i1 + fadd v21.2s, v2.2s, v3.2s // r2+r3,i2+i3 + fmul v26.2s, v17.2s, v28.2s // -a2r*w,a2i*w + ext v6.8b, v4.8b, v5.8b, #4 + ext v7.8b, v5.8b, v4.8b, #4 + fmul v27.2s, v19.2s, v27.2s // a3r*w,-a3i*w + fsub v23.2s, v22.2s, v23.2s // i2-i3,r3-r2 + fsub v22.2s, v0.2s, v1.2s // r0-r1,i0-i1 + fmul v24.2s, v17.2s, v28.s[1] // a2r*w,a2i*w + fmul v25.2s, v19.2s, v28.s[1] // a3r*w,a3i*w + fadd v0.2s, v20.2s, v21.2s + fsub v2.2s, v20.2s, v21.2s + fadd v1.2s, v22.2s, v23.2s + rev64 v26.2s, v26.2s + rev64 v27.2s, v27.2s + fsub v3.2s, v22.2s, v23.2s + fsub v6.2s, v6.2s, v7.2s + fadd v24.2s, v24.2s, v26.2s // a2r+a2i,a2i-a2r t1,t2 + fadd v25.2s, v25.2s, v27.2s // a3r-a3i,a3i+a3r t5,t6 + fadd v7.2s, v4.2s, v5.2s + fsub v18.2s, v2.2s, v6.2s + ld1 {v20.4s,v21.4s}, [x0], #32 + ld1 {v22.4s,v23.4s}, [x0], #32 + ext v26.8b, v24.8b, v25.8b, #4 + ext v27.8b, v25.8b, v24.8b, #4 + fadd v2.2s, v2.2s, v6.2s + fsub v16.2s, v0.2s, v7.2s + fadd v5.2s, v25.2s, v24.2s + fsub v4.2s, v26.2s, v27.2s + transpose v24.2d, v25.2d, v20.2d, v22.2d + transpose v26.2d, v27.2d, v21.2d, v23.2d + fadd v0.2s, v0.2s, v7.2s + fsub v17.2s, v1.2s, v5.2s + fsub v19.2s, v3.2s, v4.2s + fadd v3.2s, v3.2s, v4.2s + fadd v1.2s, v1.2s, v5.2s + ext v20.16b, v21.16b, v21.16b, #4 + ext v21.16b, v23.16b, v23.16b, #4 + + zip1 v0.2d, v0.2d, v1.2d // {z[0], z[1]} + zip1 v1.2d, v2.2d, v3.2d // {z[2], z[3]} + zip1 v2.2d, v16.2d, v17.2d // {z[o1], z[o1+1]} + zip1 v3.2d, v18.2d, v19.2d // {z[o1+2],z[o1+3]} + + // 2 x fft4 + transpose v22.2d, v23.2d, v20.2d, v21.2d + + fadd v4.4s, v24.4s, v25.4s + fadd v5.4s, v26.4s, v27.4s + fsub v6.4s, v24.4s, v25.4s + fsub v7.4s, v22.4s, v23.4s + + ld1 {v23.4s}, [x14] + + fadd v24.4s, v4.4s, v5.4s // {z[o2+0],z[o2+1]} + fsub v26.4s, v4.4s, v5.4s // {z[o2+2],z[o2+3]} + fadd v25.4s, v6.4s, v7.4s // {z[o3+0],z[o3+1]} + fsub v27.4s, v6.4s, v7.4s // {z[o3+2],z[o3+3]} + + //fft_pass_neon_16 + rev64 v7.4s, v25.4s + fmul v25.4s, v25.4s, v23.s[1] + fmul v7.4s, v7.4s, v29.4s + fmla v25.4s, v7.4s, v23.s[3] // {t1a,t2a,t5a,t6a} + + zip1 v20.4s, v24.4s, v25.4s + zip2 v21.4s, v24.4s, v25.4s + fneg v22.4s, v20.4s + fadd v4.4s, v21.4s, v20.4s + fsub v6.4s, v20.4s, v21.4s // just the second half + fadd v5.4s, v21.4s, v22.4s // just the first half + + tbl v4.16b, {v4.16b}, v30.16b // trans4_float + tbl v5.16b, {v5.16b,v6.16b}, v31.16b // trans8_float + + fsub v20.4s, v0.4s, v4.4s // {z[o2],z[o2+1]} + fadd v16.4s, v0.4s, v4.4s // {z[0], z[1]} + fsub v22.4s, v2.4s, v5.4s // {z[o3],z[o3+1]} + fadd v18.4s, v2.4s, v5.4s // {z[o1],z[o1+1]} + +//second half + rev64 v6.4s, v26.4s + fmul v26.4s, v26.4s, v23.s[2] + rev64 v7.4s, v27.4s + fmul v27.4s, v27.4s, v23.s[3] + fmul v6.4s, v6.4s, v29.4s + fmul v7.4s, v7.4s, v29.4s + fmla v26.4s, v6.4s, v23.s[2] // {t1,t2,t5,t6} + fmla v27.4s, v7.4s, v23.s[1] // {t1a,t2a,t5a,t6a} + + zip1 v24.4s, v26.4s, v27.4s + zip2 v25.4s, v26.4s, v27.4s + fneg v26.4s, v24.4s + fadd v4.4s, v25.4s, v24.4s + fsub v6.4s, v24.4s, v25.4s // just the second half + fadd v5.4s, v25.4s, v26.4s // just the first half + + tbl v4.16b, {v4.16b}, v30.16b // trans4_float + tbl v5.16b, {v5.16b,v6.16b}, v31.16b // trans8_float + + fadd v17.4s, v1.4s, v4.4s // {z[2], z[3]} + fsub v21.4s, v1.4s, v4.4s // {z[o2+2],z[o2+3]} + fadd v19.4s, v3.4s, v5.4s // {z[o1+2],z[o1+3]} + fsub v23.4s, v3.4s, v5.4s // {z[o3+2],z[o3+3]} + + st1 {v16.4s,v17.4s}, [x1], #32 + st1 {v18.4s,v19.4s}, [x1], #32 + st1 {v20.4s,v21.4s}, [x1], #32 + st1 {v22.4s,v23.4s}, [x1], #32 + + ret +endfunc + + +const trans4_float, align=4 + .byte 0, 1, 2, 3 + .byte 8, 9, 10, 11 + .byte 4, 5, 6, 7 + .byte 12, 13, 14, 15 +endconst + +const trans8_float, align=4 + .byte 24, 25, 26, 27 + .byte 0, 1, 2, 3 + .byte 28, 29, 30, 31 + .byte 4, 5, 6, 7 +endconst + +function fft_pass_neon + sub x6, x2, #1 // n - 1, loop counter + lsl x5, x2, #3 // 2 * n * sizeof FFTSample + lsl x1, x2, #4 // 2 * n * sizeof FFTComplex + add x5, x4, x5 // wim + add x3, x1, x2, lsl #5 // 4 * n * sizeof FFTComplex + add x2, x0, x2, lsl #5 // &z[o2] + add x3, x0, x3 // &z[o3] + add x1, x0, x1 // &z[o1] + ld1 {v20.4s},[x2] // {z[o2],z[o2+1]} + ld1 {v22.4s},[x3] // {z[o3],z[o3+1]} + ld1 {v4.2s}, [x4], #8 // {wre[0],wre[1]} + trn2 v25.2d, v20.2d, v22.2d + sub x5, x5, #4 // wim-- + trn1 v24.2d, v20.2d, v22.2d + ld1 {v5.s}[0], [x5], x7 // d5[0] = wim[-1] + rev64 v7.4s, v25.4s + fmul v25.4s, v25.4s, v4.s[1] + ld1 {v16.4s}, [x0] // {z[0],z[1]} + fmul v7.4s, v7.4s, v29.4s + ld1 {v17.4s}, [x1] // {z[o1],z[o1+1]} + prfm pldl1keep, [x2, #16] + prfm pldl1keep, [x3, #16] + fmla v25.4s, v7.4s, v5.s[0] // {t1a,t2a,t5a,t6a} + prfm pldl1keep, [x0, #16] + prfm pldl1keep, [x1, #16] + + zip1 v20.4s, v24.4s, v25.4s + zip2 v21.4s, v24.4s, v25.4s + fneg v22.4s, v20.4s + fadd v4.4s, v21.4s, v20.4s + fsub v6.4s, v20.4s, v21.4s // just the second half + fadd v5.4s, v21.4s, v22.4s // just the first half + + tbl v4.16b, {v4.16b}, v30.16b // trans4_float + tbl v5.16b, {v5.16b,v6.16b}, v31.16b // trans8_float + + fadd v20.4s, v16.4s, v4.4s + fsub v22.4s, v16.4s, v4.4s + fadd v21.4s, v17.4s, v5.4s + st1 {v20.4s}, [x0], #16 // {z[0], z[1]} + fsub v23.4s, v17.4s, v5.4s + + st1 {v21.4s}, [x1], #16 // {z[o1],z[o1+1]} + st1 {v22.4s}, [x2], #16 // {z[o2],z[o2+1]} + st1 {v23.4s}, [x3], #16 // {z[o3],z[o3+1]} +1: + ld1 {v20.4s},[x2] // {z[o2],z[o2+1]} + ld1 {v22.4s},[x3] // {z[o3],z[o3+1]} + ld1 {v4.2s}, [x4], #8 // {wre[0],wre[1]} + transpose v26.2d, v27.2d, v20.2d, v22.2d + ld1 {v5.2s}, [x5], x7 // {wim[-1],wim[0]} + rev64 v6.4s, v26.4s + fmul v26.4s, v26.4s, v4.s[0] + rev64 v7.4s, v27.4s + fmul v27.4s, v27.4s, v4.s[1] + fmul v6.4s, v6.4s, v29.4s + fmul v7.4s, v7.4s, v29.4s + ld1 {v16.4s},[x0] // {z[0],z[1]} + fmla v26.4s, v6.4s, v5.s[1] // {t1,t2,t5,t6} + fmla v27.4s, v7.4s, v5.s[0] // {t1a,t2a,t5a,t6a} + ld1 {v17.4s},[x1] // {z[o1],z[o1+1]} + + subs x6, x6, #1 // n-- + + zip1 v20.4s, v26.4s, v27.4s + zip2 v21.4s, v26.4s, v27.4s + fneg v22.4s, v20.4s + fadd v4.4s, v21.4s, v20.4s + fsub v6.4s, v20.4s, v21.4s // just the second half + fadd v5.4s, v21.4s, v22.4s // just the first half + + tbl v4.16b, {v4.16b}, v30.16b // trans4_float + tbl v5.16b, {v5.16b,v6.16b}, v31.16b // trans8_float + + fadd v20.4s, v16.4s, v4.4s + fsub v22.4s, v16.4s, v4.4s + fadd v21.4s, v17.4s, v5.4s + st1 {v20.4s}, [x0], #16 // {z[0], z[1]} + fsub v23.4s, v17.4s, v5.4s + + st1 {v21.4s}, [x1], #16 // {z[o1],z[o1+1]} + st1 {v22.4s}, [x2], #16 // {z[o2],z[o2+1]} + st1 {v23.4s}, [x3], #16 // {z[o3],z[o3+1]} + b.ne 1b + + ret +endfunc + +.macro def_fft n, n2, n4 +function fft\n\()_neon align=6 + sub sp, sp, #16 + stp x28, x30, [sp] + add x28, x0, #\n4*2*8 + bl fft\n2\()_neon + mov x0, x28 + bl fft\n4\()_neon + add x0, x28, #\n4*1*8 + bl fft\n4\()_neon + sub x0, x28, #\n4*2*8 + ldp x28, x30, [sp], #16 + movrel x4, X(ff_cos_\n) + mov x2, #\n4>>1 + b fft_pass_neon +endfunc +.endm + + def_fft 32, 16, 8 + def_fft 64, 32, 16 + def_fft 128, 64, 32 + def_fft 256, 128, 64 + def_fft 512, 256, 128 + def_fft 1024, 512, 256 + def_fft 2048, 1024, 512 + def_fft 4096, 2048, 1024 + def_fft 8192, 4096, 2048 + def_fft 16384, 8192, 4096 + def_fft 32768, 16384, 8192 + def_fft 65536, 32768, 16384 + +function ff_fft_calc_neon, export=1 + prfm pldl1keep, [x1] + movrel x10, trans4_float + ldr w2, [x0] + movrel x11, trans8_float + sub w2, w2, #2 + movrel x3, fft_tab_neon + ld1 {v30.16b}, [x10] + mov x7, #-8 + movrel x12, pmmp + ldr x3, [x3, x2, lsl #3] + movrel x13, mppm + movrel x14, X(ff_cos_16) + ld1 {v31.16b}, [x11] + mov x0, x1 + ld1 {v29.4s}, [x12] // pmmp + ld1 {v28.4s}, [x13] + br x3 +endfunc + +function ff_fft_permute_neon, export=1 + mov x6, #1 + ldr w2, [x0] // nbits + ldr x3, [x0, #16] // tmp_buf + ldr x0, [x0, #8] // revtab + lsl x6, x6, x2 + mov x2, x6 +1: + ld1 {v0.2s,v1.2s}, [x1], #16 + ldr w4, [x0], #4 + uxth w5, w4 + lsr w4, w4, #16 + add x5, x3, x5, lsl #3 + add x4, x3, x4, lsl #3 + st1 {v0.2s}, [x5] + st1 {v1.2s}, [x4] + subs x6, x6, #2 + b.gt 1b + + sub x1, x1, x2, lsl #3 +1: + ld1 {v0.4s,v1.4s}, [x3], #32 + st1 {v0.4s,v1.4s}, [x1], #32 + subs x2, x2, #4 + b.gt 1b + + ret +endfunc + +const fft_tab_neon + .quad fft4_neon + .quad fft8_neon + .quad fft16_neon + .quad fft32_neon + .quad fft64_neon + .quad fft128_neon + .quad fft256_neon + .quad fft512_neon + .quad fft1024_neon + .quad fft2048_neon + .quad fft4096_neon + .quad fft8192_neon + .quad fft16384_neon + .quad fft32768_neon + .quad fft65536_neon +endconst + +const pmmp, align=4 + .float +1.0, -1.0, -1.0, +1.0 +endconst + +const mppm, align=4 + .float -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2 +endconst diff --git a/libavcodec/aarch64/h264cmc_neon.S b/libavcodec/aarch64/h264cmc_neon.S index a6ed877f2..486079f87 100644 --- a/libavcodec/aarch64/h264cmc_neon.S +++ b/libavcodec/aarch64/h264cmc_neon.S @@ -95,9 +95,10 @@ function ff_\type\()_\codec\()_chroma_mc8_neon, export=1 b.gt 1b ret -2: tst w6, w6 - add w12, w12, w6 +2: adds w12, w12, w6 dup v0.8B, w4 + b.eq 5f + tst w6, w6 dup v1.8B, w12 b.eq 4f @@ -161,6 +162,33 @@ function ff_\type\()_\codec\()_chroma_mc8_neon, export=1 st1 {v17.8B}, [x0], x2 b.gt 4b ret + +5: ld1 {v4.8B}, [x1], x2 + ld1 {v5.8B}, [x1], x2 + prfm pldl1strm, [x1] + subs w3, w3, #2 + umull v16.8H, v4.8B, v0.8B + umull v17.8H, v5.8B, v0.8B + prfm pldl1strm, [x1, x2] + .ifc \codec,h264 + rshrn v16.8B, v16.8H, #6 + rshrn v17.8B, v17.8H, #6 + .else + add v16.8H, v16.8H, v22.8H + add v17.8H, v17.8H, v22.8H + shrn v16.8B, v16.8H, #6 + shrn v17.8B, v17.8H, #6 + .endif + .ifc \type,avg + ld1 {v20.8B}, [x8], x2 + ld1 {v21.8B}, [x8], x2 + urhadd v16.8B, v16.8B, v20.8B + urhadd v17.8B, v17.8B, v21.8B + .endif + st1 {v16.8B}, [x0], x2 + st1 {v17.8B}, [x0], x2 + b.gt 5b + ret endfunc .endm @@ -238,9 +266,10 @@ function ff_\type\()_\codec\()_chroma_mc4_neon, export=1 b.gt 1b ret -2: tst w6, w6 - add w12, w12, w6 +2: adds w12, w12, w6 dup v30.8B, w4 + b.eq 5f + tst w6, w6 dup v31.8B, w12 trn1 v0.2S, v30.2S, v31.2S trn2 v1.2S, v30.2S, v31.2S @@ -303,6 +332,28 @@ function ff_\type\()_\codec\()_chroma_mc4_neon, export=1 st1 {v16.S}[1], [x0], x2 b.gt 4b ret + +5: ld1 {v4.S}[0], [x1], x2 + ld1 {v4.S}[1], [x1], x2 + umull v18.8H, v4.8B, v30.8B + subs w3, w3, #2 + prfm pldl1strm, [x1] + .ifc \codec,h264 + rshrn v16.8B, v18.8H, #6 + .else + add v18.8H, v18.8H, v22.8H + shrn v16.8B, v18.8H, #6 + .endif + .ifc \type,avg + ld1 {v20.S}[0], [x8], x2 + ld1 {v20.S}[1], [x8], x2 + urhadd v16.8B, v16.8B, v20.8B + .endif + prfm pldl1strm, [x1] + st1 {v16.S}[0], [x0], x2 + st1 {v16.S}[1], [x0], x2 + b.gt 5b + ret endfunc .endm diff --git a/libavcodec/aarch64/mdct_neon.S b/libavcodec/aarch64/mdct_neon.S new file mode 100644 index 000000000..1fd199c97 --- /dev/null +++ b/libavcodec/aarch64/mdct_neon.S @@ -0,0 +1,323 @@ +/* + * AArch64 NEON optimised MDCT + * Copyright (c) 2009 Mans Rullgard + * Copyright (c) 2014 Janne Grunau + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +function ff_imdct_half_neon, export=1 + sub sp, sp, #32 + stp x19, x20, [sp] + str x30, [sp, #16] + mov x12, #1 + ldr w14, [x0, #28] // mdct_bits + ldr x4, [x0, #32] // tcos + ldr x3, [x0, #8] // revtab + lsl x12, x12, x14 // n = 1 << nbits + lsr x14, x12, #2 // n4 = n >> 2 + add x7, x2, x12, lsl #1 + mov x12, #-16 + sub x7, x7, #16 + + ld2 {v16.2s,v17.2s}, [x7], x12 // d16=x,n1 d17=x,n0 + ld2 {v0.2s,v1.2s}, [x2], #16 // d0 =m0,x d1 =m1,x + rev64 v17.2s, v17.2s + ld2 {v2.2s,v3.2s}, [x4], #16 // d2=c0,c1 d3=s0,s2 + fmul v6.2s, v17.2s, v2.2s + fmul v7.2s, v0.2s, v2.2s +1: + subs x14, x14, #2 + ldr w6, [x3], #4 + fmul v4.2s, v0.2s, v3.2s + fmul v5.2s, v17.2s, v3.2s + fsub v4.2s, v6.2s, v4.2s + fadd v5.2s, v5.2s, v7.2s + ubfm x8, x6, #16, #31 + ubfm x6, x6, #0, #15 + add x8, x1, x8, lsl #3 + add x6, x1, x6, lsl #3 + b.eq 2f + ld2 {v16.2s,v17.2s}, [x7], x12 + ld2 {v0.2s,v1.2s}, [x2], #16 + rev64 v17.2s, v17.2s + ld2 {v2.2s,v3.2s}, [x4], #16 // d2=c0,c1 d3=s0,s2 + fmul v6.2s, v17.2s, v2.2s + fmul v7.2s, v0.2s, v2.2s + st2 {v4.s,v5.s}[0], [x6] + st2 {v4.s,v5.s}[1], [x8] + b 1b +2: + st2 {v4.s,v5.s}[0], [x6] + st2 {v4.s,v5.s}[1], [x8] + + mov x19, x0 + mov x20, x1 + bl X(ff_fft_calc_neon) + + mov x12, #1 + ldr w14, [x19, #28] // mdct_bits + ldr x4, [x19, #32] // tcos + lsl x12, x12, x14 // n = 1 << nbits + lsr x14, x12, #3 // n8 = n >> 3 + + add x4, x4, x14, lsl #3 + add x6, x20, x14, lsl #3 + sub x1, x4, #16 + sub x3, x6, #16 + + mov x7, #-16 + mov x8, x6 + mov x0, x3 + + ld2 {v0.2s,v1.2s}, [x3], x7 // d0 =i1,r1 d1 =i0,r0 + ld2 {v20.2s,v21.2s},[x6], #16 // d20=i2,r2 d21=i3,r3 + ld2 {v16.2s,v17.2s},[x1], x7 // d16=c1,c0 d18=s1,s0 +3: + subs x14, x14, #2 + fmul v7.2s, v0.2s, v17.2s + ld2 {v18.2s,v19.2s},[x4], #16 // d17=c2,c3 d19=s2,s3 + fmul v4.2s, v1.2s, v17.2s + fmul v6.2s, v21.2s, v19.2s + fmul v5.2s, v20.2s, v19.2s + fmul v22.2s, v1.2s, v16.2s + fmul v23.2s, v21.2s, v18.2s + fmul v24.2s, v0.2s, v16.2s + fmul v25.2s, v20.2s, v18.2s + fadd v7.2s, v7.2s, v22.2s + fadd v5.2s, v5.2s, v23.2s + fsub v4.2s, v4.2s, v24.2s + fsub v6.2s, v6.2s, v25.2s + b.eq 4f + ld2 {v0.2s,v1.2s}, [x3], x7 + ld2 {v20.2s,v21.2s},[x6], #16 + ld2 {v16.2s,v17.2s},[x1], x7 // d16=c1,c0 d18=s1,s0 + rev64 v5.2s, v5.2s + rev64 v7.2s, v7.2s + st2 {v4.2s,v5.2s}, [x0], x7 + st2 {v6.2s,v7.2s}, [x8], #16 + b 3b +4: + rev64 v5.2s, v5.2s + rev64 v7.2s, v7.2s + st2 {v4.2s,v5.2s}, [x0] + st2 {v6.2s,v7.2s}, [x8] + + ldp x19, x20, [sp] + ldr x30, [sp, #16] + add sp, sp, #32 + + ret +endfunc + +function ff_imdct_calc_neon, export=1 + sub sp, sp, #32 + stp x19, x20, [sp] + str x30, [sp, #16] + ldr w3, [x0, #28] // mdct_bits + mov x19, #1 + mov x20, x1 + lsl x19, x19, x3 + add x1, x1, x19 + + bl X(ff_imdct_half_neon) + + add x0, x20, x19, lsl #2 + add x1, x20, x19, lsl #1 + sub x0, x0, #8 + sub x2, x1, #16 + mov x3, #-16 + mov x6, #-8 +1: + ld1 {v0.4s}, [x2], x3 + prfum pldl1keep, [x0, #-16] + rev64 v0.4s, v0.4s + ld1 {v2.2s,v3.2s}, [x1], #16 + fneg v4.4s, v0.4s + prfum pldl1keep, [x2, #-16] + rev64 v2.2s, v2.2s + rev64 v3.2s, v3.2s + ext v4.16b, v4.16b, v4.16b, #8 + st1 {v2.2s}, [x0], x6 + st1 {v3.2s}, [x0], x6 + st1 {v4.4s}, [x20], #16 + subs x19, x19, #16 + b.gt 1b + + ldp x19, x20, [sp], #16 + ldr x30, [sp], #16 + + ret +endfunc + + +function ff_mdct_calc_neon, export=1 + sub sp, sp, #32 + stp x19, x20, [sp] + str x30, [sp, #16] + + mov x12, #1 + ldr w14, [x0, #28] // mdct_bits + ldr x4, [x0, #32] // tcos + ldr x3, [x0, #8] // revtab + lsl x14, x12, x14 // n = 1 << nbits + add x7, x2, x14 // in4u + sub x9, x7, #16 // in4d + add x2, x7, x14, lsl #1 // in3u + add x8, x9, x14, lsl #1 // in3d + add x5, x4, x14, lsl #1 + sub x5, x5, #16 + sub x3, x3, #4 + mov x12, #-16 + lsr x13, x14, #1 + + ld2 {v16.2s,v17.2s}, [x9], x12 // in0u0,in0u1 in4d1,in4d0 + ld2 {v18.2s,v19.2s}, [x8], x12 // in2u0,in2u1 in3d1,in3d0 + ld2 {v0.2s, v1.2s}, [x7], #16 // in4u0,in4u1 in2d1,in2d0 + rev64 v17.2s, v17.2s // in4d0,in4d1 in3d0,in3d1 + rev64 v19.2s, v19.2s // in4d0,in4d1 in3d0,in3d1 + ld2 {v2.2s, v3.2s}, [x2], #16 // in3u0,in3u1 in1d1,in1d0 + fsub v0.2s, v17.2s, v0.2s // in4d-in4u I + ld2 {v20.2s,v21.2s}, [x4], #16 // c0,c1 s0,s1 + rev64 v1.2s, v1.2s // in2d0,in2d1 in1d0,in1d1 + rev64 v3.2s, v3.2s // in2d0,in2d1 in1d0,in1d1 + ld2 {v30.2s,v31.2s}, [x5], x12 // c2,c3 s2,s3 + fadd v2.2s, v2.2s, v19.2s // in3u+in3d -R + fsub v16.2s, v16.2s, v1.2s // in0u-in2d R + fadd v18.2s, v18.2s, v3.2s // in2u+in1d -I +1: + fmul v7.2s, v0.2s, v21.2s // I*s + ldr w10, [x3, x13] + fmul v6.2s, v2.2s, v20.2s // -R*c + ldr w6, [x3, #4]! + fmul v4.2s, v2.2s, v21.2s // -R*s + fmul v5.2s, v0.2s, v20.2s // I*c + fmul v24.2s, v16.2s, v30.2s // R*c + fmul v25.2s, v18.2s, v31.2s // -I*s + fmul v22.2s, v16.2s, v31.2s // R*s + fmul v23.2s, v18.2s, v30.2s // I*c + subs x14, x14, #16 + subs x13, x13, #8 + fsub v6.2s, v6.2s, v7.2s // -R*c-I*s + fadd v7.2s, v4.2s, v5.2s // -R*s+I*c + fsub v24.2s, v25.2s, v24.2s // I*s-R*c + fadd v25.2s, v22.2s, v23.2s // R*s-I*c + b.eq 1f + mov x12, #-16 + ld2 {v16.2s,v17.2s}, [x9], x12 // in0u0,in0u1 in4d1,in4d0 + ld2 {v18.2s,v19.2s}, [x8], x12 // in2u0,in2u1 in3d1,in3d0 + fneg v7.2s, v7.2s // R*s-I*c + ld2 {v0.2s, v1.2s}, [x7], #16 // in4u0,in4u1 in2d1,in2d0 + rev64 v17.2s, v17.2s // in4d0,in4d1 in3d0,in3d1 + rev64 v19.2s, v19.2s // in4d0,in4d1 in3d0,in3d1 + ld2 {v2.2s, v3.2s}, [x2], #16 // in3u0,in3u1 in1d1,in1d0 + fsub v0.2s, v17.2s, v0.2s // in4d-in4u I + ld2 {v20.2s,v21.2s}, [x4], #16 // c0,c1 s0,s1 + rev64 v1.2s, v1.2s // in2d0,in2d1 in1d0,in1d1 + rev64 v3.2s, v3.2s // in2d0,in2d1 in1d0,in1d1 + ld2 {v30.2s,v31.2s}, [x5], x12 // c2,c3 s2,s3 + fadd v2.2s, v2.2s, v19.2s // in3u+in3d -R + fsub v16.2s, v16.2s, v1.2s // in0u-in2d R + fadd v18.2s, v18.2s, v3.2s // in2u+in1d -I + ubfm x12, x6, #16, #31 + ubfm x6, x6, #0, #15 + add x12, x1, x12, lsl #3 + add x6, x1, x6, lsl #3 + st2 {v6.s,v7.s}[0], [x6] + st2 {v6.s,v7.s}[1], [x12] + ubfm x6, x10, #16, #31 + ubfm x10, x10, #0, #15 + add x6 , x1, x6, lsl #3 + add x10, x1, x10, lsl #3 + st2 {v24.s,v25.s}[0], [x10] + st2 {v24.s,v25.s}[1], [x6] + b 1b +1: + fneg v7.2s, v7.2s // R*s-I*c + ubfm x12, x6, #16, #31 + ubfm x6, x6, #0, #15 + add x12, x1, x12, lsl #3 + add x6, x1, x6, lsl #3 + st2 {v6.s,v7.s}[0], [x6] + st2 {v6.s,v7.s}[1], [x12] + ubfm x6, x10, #16, #31 + ubfm x10, x10, #0, #15 + add x6 , x1, x6, lsl #3 + add x10, x1, x10, lsl #3 + st2 {v24.s,v25.s}[0], [x10] + st2 {v24.s,v25.s}[1], [x6] + + mov x19, x0 + mov x20, x1 + bl X(ff_fft_calc_neon) + + mov x12, #1 + ldr w14, [x19, #28] // mdct_bits + ldr x4, [x19, #32] // tcos + lsl x12, x12, x14 // n = 1 << nbits + lsr x14, x12, #3 // n8 = n >> 3 + + add x4, x4, x14, lsl #3 + add x6, x20, x14, lsl #3 + sub x1, x4, #16 + sub x3, x6, #16 + + mov x7, #-16 + mov x8, x6 + mov x0, x3 + + ld2 {v0.2s,v1.2s}, [x3], x7 // d0 =r1,i1 d1 =r0,i0 + ld2 {v20.2s,v21.2s}, [x6], #16 // d20=r2,i2 d21=r3,i3 + ld2 {v16.2s,v17.2s}, [x1], x7 // c1,c0 s1,s0 +1: + subs x14, x14, #2 + fmul v7.2s, v0.2s, v17.2s // r1*s1,r0*s0 + ld2 {v18.2s,v19.2s}, [x4], #16 // c2,c3 s2,s3 + fmul v4.2s, v1.2s, v17.2s // i1*s1,i0*s0 + fmul v6.2s, v21.2s, v19.2s // i2*s2,i3*s3 + fmul v5.2s, v20.2s, v19.2s // r2*s2,r3*s3 + fmul v24.2s, v0.2s, v16.2s // r1*c1,r0*c0 + fmul v25.2s, v20.2s, v18.2s // r2*c2,r3*c3 + fmul v22.2s, v21.2s, v18.2s // i2*c2,i3*c3 + fmul v23.2s, v1.2s, v16.2s // i1*c1,i0*c0 + fadd v4.2s, v4.2s, v24.2s // i1*s1+r1*c1,i0*s0+r0*c0 + fadd v6.2s, v6.2s, v25.2s // i2*s2+r2*c2,i3*s3+r3*c3 + fsub v5.2s, v22.2s, v5.2s // i2*c2-r2*s2,i3*c3-r3*s3 + fsub v7.2s, v23.2s, v7.2s // i1*c1-r1*s1,i0*c0-r0*s0 + fneg v4.2s, v4.2s + fneg v6.2s, v6.2s + b.eq 1f + ld2 {v0.2s, v1.2s}, [x3], x7 + ld2 {v20.2s,v21.2s}, [x6], #16 + ld2 {v16.2s,v17.2s}, [x1], x7 // c1,c0 s1,s0 + rev64 v5.2s, v5.2s + rev64 v7.2s, v7.2s + st2 {v4.2s,v5.2s}, [x0], x7 + st2 {v6.2s,v7.2s}, [x8], #16 + b 1b +1: + rev64 v5.2s, v5.2s + rev64 v7.2s, v7.2s + st2 {v4.2s,v5.2s}, [x0] + st2 {v6.2s,v7.2s}, [x8] + + ldp x19, x20, [sp], #16 + ldr x30, [sp], #16 + ret +endfunc diff --git a/libavcodec/aarch64/mpegaudiodsp_init.c b/libavcodec/aarch64/mpegaudiodsp_init.c new file mode 100644 index 000000000..b94514645 --- /dev/null +++ b/libavcodec/aarch64/mpegaudiodsp_init.c @@ -0,0 +1,39 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/aarch64/cpu.h" +#include "libavcodec/mpegaudiodsp.h" +#include "config.h" + +void ff_mpadsp_apply_window_fixed_neon(int32_t *synth_buf, int32_t *window, + int *dither, int16_t *samples, int incr); +void ff_mpadsp_apply_window_float_neon(float *synth_buf, float *window, + int *dither, float *samples, int incr); + +av_cold void ff_mpadsp_init_aarch64(MPADSPContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + s->apply_window_fixed = ff_mpadsp_apply_window_fixed_neon; + s->apply_window_float = ff_mpadsp_apply_window_float_neon; + } +} diff --git a/libavcodec/aarch64/mpegaudiodsp_neon.S b/libavcodec/aarch64/mpegaudiodsp_neon.S new file mode 100644 index 000000000..e540eb8c0 --- /dev/null +++ b/libavcodec/aarch64/mpegaudiodsp_neon.S @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2014 Janne Grunau + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +#define FRAC_BITS 23 // fractional bits for sb_samples and dct +#define WFRAC_BITS 16 // fractional bits for window +#define OUT_SHIFT (WFRAC_BITS + FRAC_BITS - 15) + +const tbl_rev128.s align=4 + .byte 12, 13, 14, 15 + .byte 8, 9, 10, 11 + .byte 4, 5, 6, 7 + .byte 0, 1, 2, 3 +endconst + +.macro apply_window type, st +function ff_mpadsp_apply_window_\type\()_neon, export=1 + mov x7, x0 + sxtw x4, w4 // incr + add x8, x0, #512<<2 + ld1 {v0.4s,v1.4s,v2.4s,v3.4s}, [x7], #64 + ld1 {v4.4s,v5.4s,v6.4s,v7.4s}, [x7], #64 + st1 {v0.4s,v1.4s,v2.4s,v3.4s}, [x8], #64 + st1 {v4.4s,v5.4s,v6.4s,v7.4s}, [x8], #64 + movrel x15, tbl_rev128.s + ld1 {v27.4s}, [x15] +.ifc \type, fixed + lsl x4, x4, #1 +.else + lsl x4, x4, #2 +.endif + add x10, x0, #45<<2 + add x0, x0, #16<<2 + add x1, x1, #16<<2 + add x5, x3, x4, lsl #5 + sub x5, x5, x4 // samples2 + neg x13, x4 // -incr + mov x9, #64<<2 +.ifc \type, fixed + ld1r {v16.2s}, [x2] // dither_state + sxtl v16.2d, v16.2s + movi v29.2d, #0 + movi v30.2d, #(1< + +#include "libavutil/cpu.h" +#include "libavutil/aarch64/cpu.h" +#include "libavutil/internal.h" +#include "libavcodec/opus_imdct.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); + +void ff_celt_imdct_half_neon(CeltIMDCTContext *s, float *dst, const float *src, + ptrdiff_t stride, float scale); + +void ff_celt_imdct_init_aarch64(CeltIMDCTContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + s->imdct_half = ff_celt_imdct_half_neon; + } +} diff --git a/libavcodec/aarch64/opus_imdct_neon.S b/libavcodec/aarch64/opus_imdct_neon.S new file mode 100644 index 000000000..ff1f7054a --- /dev/null +++ b/libavcodec/aarch64/opus_imdct_neon.S @@ -0,0 +1,647 @@ +/* + * Copyright (c) 2014 Janne Grunau + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +#include "asm-offsets.h" + +.macro shuffle a, b, c, d +const shuffle_\a\b\c\d align=4 + .byte (\a * 4), (\a * 4 + 1), (\a * 4 + 2), (\a * 4 + 3) + .byte (\b * 4), (\b * 4 + 1), (\b * 4 + 2), (\b * 4 + 3) + .byte (\c * 4), (\c * 4 + 1), (\c * 4 + 2), (\c * 4 + 3) + .byte (\d * 4), (\d * 4 + 1), (\d * 4 + 2), (\d * 4 + 3) +endconst +.endm + +shuffle 0, 2, 1, 3 +shuffle 1, 0, 3, 2 +shuffle 2, 3, 0, 1 +shuffle 3, 1, 2, 0 + + +function fft5_neon + lsl x2, x2, #3 + ld1 {v24.2s}, [x1], x2 + ld2 {v25.s,v26.s}[0], [x1], x2 + ld2 {v25.s,v26.s}[1], [x1], x2 + ld2 {v25.s,v26.s}[2], [x1], x2 + ld2 {v25.s,v26.s}[3], [x1] + dup v6.4s, v24.s[0] + dup v7.4s, v24.s[1] + + faddp v0.4s, v25.4s, v26.4s + // z[][0], z[][3] + fmul v16.4s, v25.4s, v15.s[0] // rr + fmul v17.4s, v25.4s, v15.s[1] // ri + fmul v18.4s, v26.4s, v15.s[0] // ir + fmul v19.4s, v26.4s, v15.s[1] // ii + faddp v0.4s, v0.4s, v0.4s + // z[][1], z[][2] + fmul v20.4s, v25.4s, v15.s[2] // rr + fmul v21.4s, v25.4s, v15.s[3] // ri + fmul v22.4s, v26.4s, v15.s[2] // ir + fmul v23.4s, v26.4s, v15.s[3] // ii + fadd v0.2s, v24.2s, v0.2s // out[0] + + // z[0123][0], z[0123][3] + fsub v24.4s, v16.4s, v19.4s // (c).re = rr - ii; + fadd v27.4s, v16.4s, v19.4s // (d).re = rr + ii; + ld1 {v16.16b}, [x11] + ld1 {v19.16b}, [x14] + fadd v28.4s, v17.4s, v18.4s // (c).im = ri + ir; + fsub v31.4s, v18.4s, v17.4s // (d).im = -ri + ir; + ld1 {v17.16b}, [x12] + // z[0123][1], z[0123][2] + fsub v25.4s, v20.4s, v23.4s // (c).re = rr - ii; + fadd v26.4s, v20.4s, v23.4s // (d).re = rr + ii; + ld1 {v18.16b}, [x13] + fadd v29.4s, v21.4s, v22.4s // (c).im = ri + ir; + fsub v30.4s, v22.4s, v21.4s // (d).im = -ri + ir; + + //real + tbl v20.16b, {v24.16b}, v16.16b + tbl v21.16b, {v25.16b}, v17.16b + tbl v22.16b, {v26.16b}, v18.16b + tbl v23.16b, {v27.16b}, v19.16b + //imag + tbl v16.16b, {v28.16b}, v16.16b + tbl v17.16b, {v29.16b}, v17.16b + tbl v18.16b, {v30.16b}, v18.16b + tbl v19.16b, {v31.16b}, v19.16b + + fadd v6.4s, v6.4s, v20.4s + fadd v22.4s, v22.4s, v23.4s + fadd v7.4s, v7.4s, v16.4s + fadd v18.4s, v18.4s, v19.4s + + fadd v21.4s, v21.4s, v22.4s + fadd v17.4s, v17.4s, v18.4s + fadd v6.4s, v6.4s, v21.4s + fadd v7.4s, v7.4s, v17.4s + + ret +endfunc + +function fft15_neon + mov x8, x1 + mov x9, x30 + add x2, x3, x3, lsl #1 // 3 * stride + + add x1, x8, x3, lsl #3 // in + 1 * stride + bl fft5_neon + mov v1.8b, v0.8b + mov v2.16b, v6.16b + mov v3.16b, v7.16b + + add x1, x8, x3, lsl #4 // in + 2 * stride + add x2, x3, x3, lsl #1 // 3 * stride + bl fft5_neon + zip1 v1.4s, v1.4s, v0.4s + mov v4.16b, v6.16b + mov v5.16b, v7.16b + + mov x1, x8 // in + 0 * stride + add x2, x3, x3, lsl #1 // 3 * stride + bl fft5_neon + + faddp v20.4s, v1.4s, v1.4s + + ext v18.16b, v8.16b, v8.16b, #4 + ext v19.16b, v9.16b, v9.16b, #4 + mov v16.16b, v6.16b + mov v17.16b, v7.16b + fadd v20.2s, v20.2s, v0.2s + + uzp1 v18.4s, v18.4s, v10.4s // exp[2,4,6,8].re + uzp1 v19.4s, v19.4s, v11.4s // exp[2,4,6,8].im + + st1 {v20.2s}, [x0], #8 // out[0] + + fmla v16.4s, v2.4s, v8.4s + fmls v16.4s, v3.4s, v9.4s + + fmla v17.4s, v2.4s, v9.4s + fmla v17.4s, v3.4s, v8.4s + + fmla v16.4s, v4.4s, v18.4s + fmls v16.4s, v5.4s, v19.4s + + fmla v17.4s, v4.4s, v19.4s + fmla v17.4s, v5.4s, v18.4s + + zip1 v18.4s, v16.4s, v17.4s + zip2 v19.4s, v16.4s, v17.4s + + rev64 v31.4s, v14.4s + trn1 v28.2d, v1.2d, v1.2d + trn2 v29.2d, v1.2d, v1.2d + zip1 v30.2d, v14.2d, v31.2d + zip2 v31.2d, v14.2d, v31.2d + + st1 {v18.4s,v19.4s}, [x0], #32 // out[1-4] + + fmul v16.4s, v28.4s, v30.4s + fmul v17.4s, v29.4s, v30.4s + fmls v16.4s, v29.4s, v31.4s + fmla v17.4s, v28.4s, v31.4s + faddp v16.4s, v16.4s, v16.4s + faddp v17.4s, v17.4s, v17.4s + zip1 v18.2s, v16.2s, v17.2s + zip2 v19.2s, v16.2s, v17.2s + + fadd v18.2s, v18.2s, v0.2s + fadd v0.2s, v19.2s, v0.2s + + ext v30.16b, v12.16b, v12.16b, #4 + ext v31.16b, v13.16b, v13.16b, #4 + mov v16.16b, v6.16b + mov v17.16b, v7.16b + + uzp1 v30.4s, v30.4s, v8.4s + uzp1 v31.4s, v31.4s, v9.4s + + st1 {v18.2s}, [x0], #8 // out[5] + + fmla v16.4s, v2.4s, v10.4s + fmls v16.4s, v3.4s, v11.4s + + fmla v17.4s, v2.4s, v11.4s + fmla v17.4s, v3.4s, v10.4s + + fmla v16.4s, v4.4s, v30.4s + fmls v16.4s, v5.4s, v31.4s + + fmla v17.4s, v4.4s, v31.4s + fmla v17.4s, v5.4s, v30.4s + + zip1 v18.4s, v16.4s, v17.4s + zip2 v19.4s, v16.4s, v17.4s + + ext v30.16b, v10.16b, v10.16b, #4 + ext v31.16b, v11.16b, v11.16b, #4 + + fmla v6.4s, v2.4s, v12.4s + fmls v6.4s, v3.4s, v13.4s + + st1 {v18.4s,v19.4s}, [x0], #32 // out[6-9] + + uzp1 v30.4s, v30.4s, v12.4s + uzp1 v31.4s, v31.4s, v13.4s + + fmla v7.4s, v2.4s, v13.4s + fmla v7.4s, v3.4s, v12.4s + + st1 {v0.2s}, [x0], #8 // out[10] + + fmla v6.4s, v4.4s, v30.4s + fmls v6.4s, v5.4s, v31.4s + + fmla v7.4s, v4.4s, v31.4s + fmla v7.4s, v5.4s, v30.4s + + zip1 v18.4s, v6.4s, v7.4s + zip2 v19.4s, v6.4s, v7.4s + + st1 {v18.4s,v19.4s}, [x0], #32 // out[11-14] + + ret x9 +endfunc + +// x0: out, x1: out+len2, x2: exptab, x3: len2 +function fft15_pass + ands x6, x3, #3 + mov x4, x0 + mov x5, x1 + b.eq 9f + ld1 {v0.2s}, [x0], #8 + ld1 {v1.2s}, [x1], #8 + sub x3, x3, x6 + subs x6, x6, #1 + fadd v2.2s, v0.2s, v1.2s + fsub v3.2s, v0.2s, v1.2s + add x2, x2, #8 + st1 {v2.2s}, [x4], #8 + st1 {v3.2s}, [x5], #8 + b.eq 9f +1: + subs x6, x6, #1 + ldp s4, s5, [x2], #8 + ldp s2, s3, [x1], #8 + ldp s0, s1, [x0], #8 + + fmul s6, s2, s4 + fmul s7, s2, s5 + fmls s6, s3, v5.s[0] + fmla s7, s3, v4.s[0] + + fsub s2, s0, s6 + fsub s3, s1, s7 + fadd s0, s0, s6 + fadd s1, s1, s7 + + stp s2, s3, [x5], #8 + stp s0, s1, [x4], #8 + b.gt 1b +9: + ld1 {v4.4s,v5.4s}, [x2], #32 + ld2 {v2.4s,v3.4s}, [x1], #32 + uzp1 v6.4s, v4.4s, v5.4s + uzp2 v7.4s, v4.4s, v5.4s + ld2 {v0.4s,v1.4s}, [x0], #32 +8: + subs x3, x3, #8 + + fmul v4.4s, v2.4s, v6.4s + fmul v5.4s, v2.4s, v7.4s + b.lt 4f + + ld1 {v18.4s,v19.4s}, [x2], #32 + + fmls v4.4s, v3.4s, v7.4s + fmla v5.4s, v3.4s, v6.4s + + ld2 {v22.4s,v23.4s}, [x1], #32 + + fsub v2.4s, v0.4s, v4.4s + fadd v0.4s, v0.4s, v4.4s + fsub v3.4s, v1.4s, v5.4s + fadd v1.4s, v1.4s, v5.4s + + uzp1 v16.4s, v18.4s, v19.4s + uzp2 v17.4s, v18.4s, v19.4s + + st2 {v2.4s,v3.4s}, [x5], #32 + st2 {v0.4s,v1.4s}, [x4], #32 + ld2 {v20.4s,v21.4s}, [x0], #32 + + fmul v18.4s, v22.4s, v16.4s + fmul v19.4s, v22.4s, v17.4s + b.eq 0f + + ld1 {v4.4s,v5.4s}, [x2], #32 + + fmls v18.4s, v23.4s, v17.4s + fmla v19.4s, v23.4s, v16.4s + + ld2 {v2.4s,v3.4s}, [x1], #32 + + fsub v22.4s, v20.4s, v18.4s + fadd v20.4s, v20.4s, v18.4s + fsub v23.4s, v21.4s, v19.4s + fadd v21.4s, v21.4s, v19.4s + + uzp1 v6.4s, v4.4s, v5.4s + uzp2 v7.4s, v4.4s, v5.4s + + st2 {v22.4s,v23.4s}, [x5], #32 + st2 {v20.4s,v21.4s}, [x4], #32 + ld2 {v0.4s,v1.4s}, [x0], #32 + + b 8b +4: + fmls v4.4s, v3.4s, v7.4s + fmla v5.4s, v3.4s, v6.4s + + fsub v2.4s, v0.4s, v4.4s + fadd v0.4s, v0.4s, v4.4s + fsub v3.4s, v1.4s, v5.4s + fadd v1.4s, v1.4s, v5.4s + + st2 {v2.4s,v3.4s}, [x5], #32 + st2 {v0.4s,v1.4s}, [x4], #32 + + ret +0: + fmls v18.4s, v23.4s, v17.4s + fmla v19.4s, v23.4s, v16.4s + + fsub v22.4s, v20.4s, v18.4s + fadd v20.4s, v20.4s, v18.4s + fsub v23.4s, v21.4s, v19.4s + fadd v21.4s, v21.4s, v19.4s + + st2 {v22.4s,v23.4s}, [x5], #32 + st2 {v20.4s,v21.4s}, [x4], #32 + + ret +endfunc + +function fft30_neon align=6 + sub sp, sp, #0x20 + stp x20, x21, [sp] + stp x22, x30, [sp, #0x10] + mov x21, x1 + mov x22, x2 + mov x20, x4 + mov x0, x21 + mov x1, x22 + lsl x3, x20, #1 + bl fft15_neon + + add x0, x21, #15*8 + add x1, x22, x20, lsl #3 + lsl x3, x20, #1 + bl fft15_neon + + ldr x2, [x10, #(CELT_EXPTAB + 8)] // s->exptab[1] + add x0, x21, #0 + add x1, x21, #15*8 + mov x3, #15 + ldp x20, x21, [sp] + ldp x22, x30, [sp, #0x10] + add sp, sp, #0x20 + b fft15_pass +endfunc + +.macro def_fft n, n2 +function fft\n\()_neon align=6 + sub sp, sp, #0x30 + stp x20, x21, [sp] + stp x22, x30, [sp, #0x10] + stp x23, x24, [sp, #0x20] + mov x21, x1 + mov x22, x2 + mov x23, x3 + mov x20, x4 + sub x3, x3, #1 + lsl x4, x4, #1 + bl fft\n2\()_neon + + add x1, x21, #(\n2 * 8) + add x2, x22, x20, lsl #3 + sub x3, x23, #1 + lsl x4, x20, #1 + bl fft\n2\()_neon + + add x5, x10, #CELT_EXPTAB + mov x0, x21 + ldr x2, [x5, x23, lsl #3] // s->exptab[N] + add x1, x21, #(\n2 * 8) + mov x3, #\n2 + ldp x20, x21, [sp] + ldp x22, x30, [sp, #0x10] + ldp x23, x24, [sp, #0x20] + add sp, sp, #0x30 + b fft15_pass +endfunc +.endm + + def_fft 60, 30 + def_fft 120, 60 + def_fft 240, 120 + def_fft 480, 240 + def_fft 960, 480 + +function fft_b15_calc_neon + sub sp, sp, #0x50 + ldr x8, [x0, #CELT_EXPTAB] // s->exptab[0] + movrel x6, fact5 + movrel x11, shuffle_0213 + movrel x12, shuffle_1032 + movrel x13, shuffle_2301 + movrel x14, shuffle_3120 + add x8, x8, #8 + movrel x5, fft_tab_neon + stp x20, x30, [sp] + stp d8, d9, [sp, #0x10] + stp d10, d11, [sp, #0x20] + stp d12, d13, [sp, #0x30] + stp d14, d15, [sp, #0x40] + ld1 {v15.4s}, [x6] + ld1 {v0.4s,v1.4s}, [x8], #32 + ld1 {v6.2s}, [x8], #8 + ld1 {v2.4s,v3.4s}, [x8], #32 + ld1 {v7.2s}, [x8], #8 + ld1 {v4.4s,v5.4s}, [x8], #32 + uzp1 v8.4s, v0.4s, v1.4s // exp[ 1 - 4].re + uzp2 v9.4s, v0.4s, v1.4s // exp[ 1 - 4].im + uzp1 v10.4s, v2.4s, v3.4s // exp[ 6 - 9].re + uzp2 v11.4s, v2.4s, v3.4s // exp[ 6 - 9].im + uzp1 v12.4s, v4.4s, v5.4s // exp[11 - 14].re + uzp2 v13.4s, v4.4s, v5.4s // exp[11 - 14].im + zip1 v14.4s, v6.4s, v7.4s // exp[5,10].re/exp[5,10].im + add x5, x5, x3, lsl #3 + ldr x5, [x5] + mov x10, x0 + blr x5 + ldp x20, x30, [sp] + ldp d8, d9, [sp, #0x10] + ldp d10, d11, [sp, #0x20] + ldp d12, d13, [sp, #0x30] + ldp d14, d15, [sp, #0x40] + add sp, sp, #0x50 + ret +endfunc + +const fft_tab_neon + .quad fft15_neon + .quad fft30_neon + .quad fft60_neon + .quad fft120_neon + .quad fft240_neon + .quad fft480_neon + .quad fft960_neon +endconst + +function ff_celt_imdct_half_neon, export=1 + sub sp, sp, #0x20 + stp x21, x30, [sp] + str s0, [sp, #0x10] + + ldp w5, w6, [x0, #CELT_LEN2] // CELT_LEN4 + mov x10, x0 + mov x21, x1 + sub w5, w5, #1 + lsl x7, x3, #3 // 2 * stride * sizeof(float) + sub x8, xzr, x3, lsl #3 // -2 * stride * sizeof(float) + mul x5, x5, x3 + ldp x9, x10, [x0, #CELT_TMP] // CELT_TWIDDLE + ldr w3, [x0, #CELT_FFT_N] + add x5, x2, x5, lsl #2 + mov x11, x9 + + sub w6, w6, #4 + ld1 {v0.s}[0], [x5], x8 + ld1 {v1.s}[0], [x2], x7 + ld1 {v4.4s,v5.4s}, [x10], #32 + ld1 {v0.s}[1], [x5], x8 + ld1 {v1.s}[1], [x2], x7 + uzp1 v2.4s, v4.4s, v5.4s + ld1 {v0.s}[2], [x5], x8 + ld1 {v1.s}[2], [x2], x7 + uzp2 v3.4s, v4.4s, v5.4s + ld1 {v0.s}[3], [x5], x8 + ld1 {v1.s}[3], [x2], x7 +1: + subs w6, w6, #4 + + ld1 {v20.s}[0], [x5], x8 + ld1 {v21.s}[0], [x2], x7 + ld1 {v4.4s,v5.4s}, [x10], #32 + + fmul v6.4s, v0.4s, v2.4s + fmul v7.4s, v0.4s, v3.4s + + ld1 {v20.s}[1], [x5], x8 + ld1 {v21.s}[1], [x2], x7 + + fmls v6.4s, v1.4s, v3.4s + fmla v7.4s, v1.4s, v2.4s + + ld1 {v20.s}[2], [x5], x8 + ld1 {v21.s}[2], [x2], x7 + + uzp1 v2.4s, v4.4s, v5.4s + uzp2 v3.4s, v4.4s, v5.4s + ld1 {v20.s}[3], [x5], x8 + ld1 {v21.s}[3], [x2], x7 + + zip1 v4.4s, v6.4s, v7.4s + zip2 v5.4s, v6.4s, v7.4s + + fmul v6.4s, v20.4s, v2.4s + fmul v7.4s, v20.4s, v3.4s + + st1 {v4.4s,v5.4s}, [x9], #32 + + fmls v6.4s, v21.4s, v3.4s + fmla v7.4s, v21.4s, v2.4s + + b.eq 3f + + subs w6, w6, #4 + ld1 {v4.4s,v5.4s}, [x10], #32 + ld1 {v0.s}[0], [x5], x8 + ld1 {v1.s}[0], [x2], x7 + uzp1 v2.4s, v4.4s, v5.4s + ld1 {v0.s}[1], [x5], x8 + ld1 {v1.s}[1], [x2], x7 + uzp2 v3.4s, v4.4s, v5.4s + ld1 {v0.s}[2], [x5], x8 + ld1 {v1.s}[2], [x2], x7 + zip1 v4.4s, v6.4s, v7.4s + zip2 v5.4s, v6.4s, v7.4s + ld1 {v0.s}[3], [x5], x8 + ld1 {v1.s}[3], [x2], x7 + + st1 {v4.4s,v5.4s}, [x9], #32 + + b.gt 1b + + fmul v6.4s, v0.4s, v2.4s + fmul v7.4s, v0.4s, v3.4s + fmls v6.4s, v1.4s, v3.4s + fmla v7.4s, v1.4s, v2.4s +3: + zip1 v4.4s, v6.4s, v7.4s + zip2 v5.4s, v6.4s, v7.4s + st1 {v4.4s,v5.4s}, [x9], #32 + + mov x2, x11 + mov x4, #1 + + bl fft_b15_calc_neon + + ldr w5, [x10, #CELT_LEN4] + ldr x6, [x10, #CELT_TWIDDLE] + ldr s31, [sp, #0x10] + + add x1, x21, x5, lsl #2 + add x3, x6, x5, lsl #2 + sub x0, x1, #16 + sub x2, x3, #16 + mov x8, #-16 + mov x7, #16 + mov x10, x0 + mov x11, x1 + + sub w5, w5, #4 + + ld1 {v0.4s}, [x0], x8 + ld1 {v1.4s}, [x1], x7 + ld1 {v2.4s}, [x2], x8 + ld1 {v3.4s}, [x3], x7 + + uzp1 v4.4s, v0.4s, v1.4s // z[-i-2, -i-1, +i, i+1].re + uzp2 v6.4s, v0.4s, v1.4s // z[-i-2, -i-1, +i, i+1].im + + uzp1 v5.4s, v2.4s, v3.4s // twidlle_exptab[-i-2, -i-1, +i, i+1].re + uzp2 v7.4s, v2.4s, v3.4s // twidlle_exptab[-i-2, -i-1, +i, i+1].im + + fmul v1.4s, v6.4s, v5.4s + fmul v0.4s, v6.4s, v7.4s +2: + subs w5, w5, #4 + + ld1 {v20.4s}, [x0], x8 + + fmla v1.4s, v4.4s, v7.4s + fmls v0.4s, v4.4s, v5.4s + + ld1 {v21.4s}, [x1], x7 + + ext v1.16b, v1.16b, v1.16b, #8 + fmul v0.4s, v0.4s, v31.s[0] + + ld1 {v2.4s}, [x2], x8 + + rev64 v1.4s, v1.4s + fmul v1.4s, v1.4s, v31.s[0] + + ld1 {v3.4s}, [x3], x7 + + zip1 v5.4s, v0.4s, v1.4s + zip2 v7.4s, v0.4s, v1.4s + + uzp1 v4.4s, v20.4s, v21.4s // z[-i-2, -i-1, +i, i+1].re + uzp2 v6.4s, v20.4s, v21.4s // z[-i-2, -i-1, +i, i+1].im + + st1 {v5.4s}, [x10], x8 + st1 {v7.4s}, [x11], x7 + + uzp1 v5.4s, v2.4s, v3.4s // twidlle_exptab[-i-2, -i-1, +i, i+1].re + uzp2 v7.4s, v2.4s, v3.4s // twidlle_exptab[-i-2, -i-1, +i, i+1].im + + fmul v1.4s, v6.4s, v5.4s + fmul v0.4s, v6.4s, v7.4s + b.gt 2b + + fmla v1.4s, v4.4s, v7.4s + fmls v0.4s, v4.4s, v5.4s + ext v1.16b, v1.16b, v1.16b, #8 + fmul v0.4s, v0.4s, v31.s[0] + rev64 v1.4s, v1.4s + fmul v1.4s, v1.4s, v31.s[0] + zip1 v5.4s, v0.4s, v1.4s + zip2 v7.4s, v0.4s, v1.4s + st1 {v5.4s}, [x10], x8 + st1 {v7.4s}, [x11], x7 + + ldp x21, x30, [sp] + add sp, sp, #0x20 + ret +endfunc + +// [0] = exp(2 * i * pi / 5), [1] = exp(2 * i * pi * 2 / 5) +const fact5 align=4 + .float 0.30901699437494745, 0.95105651629515353 + .float -0.80901699437494734, 0.58778525229247325 +endconst diff --git a/libavcodec/aarch64/videodsp.S b/libavcodec/aarch64/videodsp.S new file mode 100644 index 000000000..24067cc2a --- /dev/null +++ b/libavcodec/aarch64/videodsp.S @@ -0,0 +1,28 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +function ff_prefetch_aarch64, export=1 + subs w2, w2, #2 + prfm pldl1strm, [x0] + prfm pldl1strm, [x0, x1] + add x0, x0, x1, lsl #1 + b.gt X(ff_prefetch_aarch64) + ret +endfunc diff --git a/libavcodec/aarch64/videodsp_init.c b/libavcodec/aarch64/videodsp_init.c new file mode 100644 index 000000000..6f667a6d3 --- /dev/null +++ b/libavcodec/aarch64/videodsp_init.c @@ -0,0 +1,32 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/aarch64/cpu.h" +#include "libavcodec/videodsp.h" + +void ff_prefetch_aarch64(uint8_t *mem, ptrdiff_t stride, int h); + +av_cold void ff_videodsp_init_aarch64(VideoDSPContext *ctx, int bpc) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_armv8(cpu_flags)) + ctx->prefetch = ff_prefetch_aarch64; +} diff --git a/libavcodec/aarch64/vorbisdsp_init.c b/libavcodec/aarch64/vorbisdsp_init.c new file mode 100644 index 000000000..c796f95e6 --- /dev/null +++ b/libavcodec/aarch64/vorbisdsp_init.c @@ -0,0 +1,34 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/aarch64/cpu.h" +#include "libavcodec/vorbisdsp.h" + +void ff_vorbis_inverse_coupling_neon(float *mag, float *ang, + intptr_t blocksize); + +av_cold void ff_vorbisdsp_init_aarch64(VorbisDSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + c->vorbis_inverse_coupling = ff_vorbis_inverse_coupling_neon; + } +} diff --git a/libavcodec/aarch64/vorbisdsp_neon.S b/libavcodec/aarch64/vorbisdsp_neon.S new file mode 100644 index 000000000..e76feebc5 --- /dev/null +++ b/libavcodec/aarch64/vorbisdsp_neon.S @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2008 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +function ff_vorbis_inverse_coupling_neon, export=1 + movi v20.4s, #1<<7, lsl #24 + subs x2, x2, #4 + mov x3, x0 + mov x4, x1 + b.eq 3f + + ld1 {v7.4s}, [x1], #16 + ld1 {v6.4s}, [x0], #16 + cmle v4.4s, v7.4s, #0 + and v5.16b, v6.16b, v20.16b + eor v7.16b, v7.16b, v5.16b + and v2.16b, v7.16b, v4.16b + bic v3.16b, v7.16b, v4.16b + fadd v7.4s, v6.4s, v2.4s + fsub v6.4s, v6.4s, v3.4s +1: ld1 {v1.4s}, [x1], #16 + ld1 {v0.4s}, [x0], #16 + cmle v4.4s, v1.4s, #0 + and v5.16b, v0.16b, v20.16b + eor v1.16b, v1.16b, v5.16b + st1 {v7.4s}, [x3], #16 + st1 {v6.4s}, [x4], #16 + and v2.16b, v1.16b, v4.16b + bic v3.16b, v1.16b, v4.16b + fadd v1.4s, v0.4s, v2.4s + fsub v0.4s, v0.4s, v3.4s + subs x2, x2, #8 + b.le 2f + ld1 {v7.4s}, [x1], #16 + ld1 {v6.4s}, [x0], #16 + cmle v4.4s, v7.4s, #0 + and v5.16b, v6.16b, v20.16b + eor v7.16b, v7.16b, v5.16b + st1 {v1.4s}, [x3], #16 + st1 {v0.4s}, [x4], #16 + and v2.16b, v7.16b, v4.16b + bic v3.16b, v7.16b, v4.16b + fadd v7.4s, v6.4s, v2.4s + fsub v6.4s, v6.4s, v3.4s + b 1b + +2: st1 {v1.4s}, [x3], #16 + st1 {v0.4s}, [x4], #16 + b.lt ret + +3: ld1 {v1.4s}, [x1] + ld1 {v0.4s}, [x0] + cmle v4.4s, v1.4s, #0 + and v5.16b, v0.16b, v20.16b + eor v1.16b, v1.16b, v5.16b + and v2.16b, v1.16b, v4.16b + bic v3.16b, v1.16b, v4.16b + fadd v1.4s, v0.4s, v2.4s + fsub v0.4s, v0.4s, v3.4s + st1 {v1.4s}, [x0], #16 + st1 {v0.4s}, [x1], #16 +ret: + ret +endfunc diff --git a/libavcodec/ac3.h b/libavcodec/ac3.h index 0cc9e2c98..542f79d71 100644 --- a/libavcodec/ac3.h +++ b/libavcodec/ac3.h @@ -51,6 +51,52 @@ #define EXP_D25 2 #define EXP_D45 3 +#ifndef USE_FIXED +#define USE_FIXED 0 +#endif + +#if USE_FIXED + +#define FFT_FLOAT 0 + +#define FIXR(a) ((int)((a) * 0 + 0.5)) +#define FIXR12(a) ((int)((a) * 4096 + 0.5)) +#define FIXR15(a) ((int)((a) * 32768 + 0.5)) +#define ROUND15(x) ((x) + 16384) >> 15 + +#define AC3_RENAME(x) x ## _fixed +#define AC3_NORM(norm) (1<<24)/(norm) +#define AC3_MUL(a,b) ((((int64_t) (a)) * (b))>>12) +#define AC3_RANGE(x) (x) +#define AC3_DYNAMIC_RANGE(x) (x) +#define AC3_SPX_BLEND(x) (x) +#define AC3_DYNAMIC_RANGE1 0 + +#define INTFLOAT int +#define SHORTFLOAT int16_t + +#else /* USE_FIXED */ + +#define FIXR(x) ((float)(x)) +#define FIXR12(x) ((float)(x)) +#define FIXR15(x) ((float)(x)) +#define ROUND15(x) (x) + +#define AC3_RENAME(x) x +#define AC3_NORM(norm) (1.0f/(norm)) +#define AC3_MUL(a,b) ((a) * (b)) +#define AC3_RANGE(x) (dynamic_range_tab[(x)]) +#define AC3_DYNAMIC_RANGE(x) (powf(x, s->drc_scale)) +#define AC3_SPX_BLEND(x) (x)* (1.0f/32) +#define AC3_DYNAMIC_RANGE1 1.0f + +#define INTFLOAT float +#define SHORTFLOAT float + +#endif /* USE_FIXED */ + +#define AC3_LEVEL(x) ROUND15((x) * FIXR15(0.7071067811865476)) + /* pre-defined gain values */ #define LEVEL_PLUS_3DB 1.4142135623730950 #define LEVEL_PLUS_1POINT5DB 1.1892071150027209 diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index 3a6a7ad5a..72c41850c 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -33,6 +33,7 @@ #include "libavutil/crc.h" #include "libavutil/downmix_info.h" #include "libavutil/opt.h" +#include "bswapdsp.h" #include "internal.h" #include "aac_ac3_parser.h" #include "ac3_parser.h" @@ -179,14 +180,23 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx) ac3_tables_init(); ff_mdct_init(&s->imdct_256, 8, 1, 1.0); ff_mdct_init(&s->imdct_512, 9, 1, 1.0); - ff_kbd_window_init(s->window, 5.0, 256); - ff_dsputil_init(&s->dsp, avctx); + AC3_RENAME(ff_kbd_window_init)(s->window, 5.0, 256); + ff_bswapdsp_init(&s->bdsp); + +#if (USE_FIXED) + s->fdsp = avpriv_alloc_fixed_dsp(avctx->flags & CODEC_FLAG_BITEXACT); +#else avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); +#endif + ff_ac3dsp_init(&s->ac3dsp, avctx->flags & CODEC_FLAG_BITEXACT); ff_fmt_convert_init(&s->fmt_conv, avctx); av_lfg_init(&s->dith_state, 0); - avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + if (USE_FIXED) + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + else + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; /* allow downmixing to stereo or mono */ #if FF_API_REQUEST_CHANNELS @@ -345,40 +355,45 @@ static void set_downmix_coeffs(AC3DecodeContext *s) float cmix = gain_levels[s-> center_mix_level]; float smix = gain_levels[s->surround_mix_level]; float norm0, norm1; + float downmix_coeffs[AC3_MAX_CHANNELS][2]; for (i = 0; i < s->fbw_channels; i++) { - s->downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]]; - s->downmix_coeffs[i][1] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]]; + downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]]; + downmix_coeffs[i][1] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]]; } if (s->channel_mode > 1 && s->channel_mode & 1) { - s->downmix_coeffs[1][0] = s->downmix_coeffs[1][1] = cmix; + downmix_coeffs[1][0] = downmix_coeffs[1][1] = cmix; } if (s->channel_mode == AC3_CHMODE_2F1R || s->channel_mode == AC3_CHMODE_3F1R) { int nf = s->channel_mode - 2; - s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf][1] = smix * LEVEL_MINUS_3DB; + downmix_coeffs[nf][0] = downmix_coeffs[nf][1] = smix * LEVEL_MINUS_3DB; } if (s->channel_mode == AC3_CHMODE_2F2R || s->channel_mode == AC3_CHMODE_3F2R) { int nf = s->channel_mode - 4; - s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf+1][1] = smix; + downmix_coeffs[nf][0] = downmix_coeffs[nf+1][1] = smix; } /* renormalize */ norm0 = norm1 = 0.0; for (i = 0; i < s->fbw_channels; i++) { - norm0 += s->downmix_coeffs[i][0]; - norm1 += s->downmix_coeffs[i][1]; + norm0 += downmix_coeffs[i][0]; + norm1 += downmix_coeffs[i][1]; } norm0 = 1.0f / norm0; norm1 = 1.0f / norm1; for (i = 0; i < s->fbw_channels; i++) { - s->downmix_coeffs[i][0] *= norm0; - s->downmix_coeffs[i][1] *= norm1; + downmix_coeffs[i][0] *= norm0; + downmix_coeffs[i][1] *= norm1; } if (s->output_mode == AC3_CHMODE_MONO) { for (i = 0; i < s->fbw_channels; i++) - s->downmix_coeffs[i][0] = (s->downmix_coeffs[i][0] + - s->downmix_coeffs[i][1]) * LEVEL_MINUS_3DB; + downmix_coeffs[i][0] = (downmix_coeffs[i][0] + + downmix_coeffs[i][1]) * LEVEL_MINUS_3DB; + } + for (i = 0; i < s->fbw_channels; i++) { + s->downmix_coeffs[i][0] = FIXR12(downmix_coeffs[i][0]); + s->downmix_coeffs[i][1] = FIXR12(downmix_coeffs[i][1]); } } @@ -646,20 +661,30 @@ static inline void do_imdct(AC3DecodeContext *s, int channels) for (ch = 1; ch <= channels; ch++) { if (s->block_switch[ch]) { int i; - float *x = s->tmp_output + 128; + FFTSample *x = s->tmp_output + 128; for (i = 0; i < 128; i++) x[i] = s->transform_coeffs[ch][2 * i]; s->imdct_256.imdct_half(&s->imdct_256, s->tmp_output, x); +#if USE_FIXED + s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1], + s->tmp_output, s->window, 128, 8); +#else s->fdsp.vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1], s->tmp_output, s->window, 128); +#endif for (i = 0; i < 128; i++) x[i] = s->transform_coeffs[ch][2 * i + 1]; s->imdct_256.imdct_half(&s->imdct_256, s->delay[ch - 1], x); } else { s->imdct_512.imdct_half(&s->imdct_512, s->tmp_output, s->transform_coeffs[ch]); +#if USE_FIXED + s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1], + s->tmp_output, s->window, 128, 8); +#else s->fdsp.vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1], s->tmp_output, s->window, 128); - memcpy(s->delay[ch - 1], s->tmp_output + 128, 128 * sizeof(float)); +#endif + memcpy(s->delay[ch - 1], s->tmp_output + 128, 128 * sizeof(FFTSample)); } } } @@ -794,13 +819,13 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) if (get_bits1(gbc)) { /* Allow asymmetric application of DRC when drc_scale > 1. Amplification of quiet sounds is enhanced */ - float range = dynamic_range_tab[get_bits(gbc, 8)]; + INTFLOAT range = AC3_RANGE(get_bits(gbc, 8)); if (range > 1.0 || s->drc_scale <= 1.0) - s->dynamic_range[i] = powf(range, s->drc_scale); + s->dynamic_range[i] = AC3_DYNAMIC_RANGE(range); else s->dynamic_range[i] = range; } else if (blk == 0) { - s->dynamic_range[i] = 1.0f; + s->dynamic_range[i] = AC3_DYNAMIC_RANGE1; } } while (i--); @@ -826,6 +851,9 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) if (start_subband > 7) start_subband += start_subband - 7; end_subband = get_bits(gbc, 3) + 5; +#if USE_FIXED + s->spx_dst_end_freq = end_freq_inv_tab[end_subband]; +#endif if (end_subband > 7) end_subband += end_subband - 7; dst_start_freq = dst_start_freq * 12 + 25; @@ -846,7 +874,8 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) s->spx_dst_start_freq = dst_start_freq; s->spx_src_start_freq = src_start_freq; - s->spx_dst_end_freq = dst_end_freq; + if (!USE_FIXED) + s->spx_dst_end_freq = dst_end_freq; decode_band_structure(gbc, blk, s->eac3, 0, start_subband, end_subband, @@ -866,18 +895,40 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) 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; + INTFLOAT spx_blend; int bin, master_spx_coord; s->first_spx_coords[ch] = 0; - spx_blend = get_bits(gbc, 5) * (1.0f/32); + spx_blend = AC3_SPX_BLEND(get_bits(gbc, 5)); 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; + INTFLOAT nratio, sblend, nblend; +#if USE_FIXED + int64_t accu; + /* calculate blending factors */ + bandsize = s->spx_band_sizes[bnd]; + accu = (int64_t)((bin << 23) + (bandsize << 22)) * s->spx_dst_end_freq; + nratio = (int)(accu >> 32); + nratio -= spx_blend << 18; + + if (nratio < 0) { + nblend = 0; + sblend = 0x800000; + } else if (nratio > 0x7fffff) { + nblend = 0x800000; + sblend = 0; + } else { + nblend = fixed_sqrt(nratio, 23); + accu = (int64_t)nblend * 1859775393; + nblend = (int)((accu + (1<<29)) >> 30); + sblend = fixed_sqrt(0x800000 - nratio, 23); + } +#else + float spx_coord; /* calculate blending factors */ bandsize = s->spx_band_sizes[bnd]; @@ -886,6 +937,7 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) nblend = sqrtf(3.0f * nratio); // noise is scaled by sqrt(3) // to give unity variance sblend = sqrtf(1.0f - nratio); +#endif bin += bandsize; /* decode spx coordinates */ @@ -894,11 +946,18 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) 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 */ +#if USE_FIXED + accu = (int64_t)nblend * spx_coord_mant; + s->spx_noise_blend[ch][bnd] = (int)((accu + (1<<22)) >> 23); + accu = (int64_t)sblend * spx_coord_mant; + s->spx_signal_blend[ch][bnd] = (int)((accu + (1<<22)) >> 23); +#else + spx_coord = spx_coord_mant * (1.0f / (1 << 23)); s->spx_noise_blend [ch][bnd] = nblend * spx_coord; s->spx_signal_blend[ch][bnd] = sblend * spx_coord; +#endif } } } else { @@ -1255,14 +1314,19 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) /* apply scaling to coefficients (headroom, dynrng) */ for (ch = 1; ch <= s->channels; ch++) { - float gain = 1.0 / 4194304.0f; - if (s->channel_mode == AC3_CHMODE_DUALMONO) { - gain *= s->dynamic_range[2 - ch]; + INTFLOAT gain; + if(s->channel_mode == AC3_CHMODE_DUALMONO) { + gain = s->dynamic_range[2-ch]; } else { - gain *= s->dynamic_range[0]; + gain = s->dynamic_range[0]; } +#if USE_FIXED + scale_coefs(s->transform_coeffs[ch], s->fixed_coeffs[ch], gain, 256); +#else + gain *= 1.0 / 4194304.0f; s->fmt_conv.int32_to_float_fmul_scalar(s->transform_coeffs[ch], s->fixed_coeffs[ch], gain, 256); +#endif } /* apply spectral extension to high frequency bins */ @@ -1287,19 +1351,24 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) do_imdct(s, s->channels); if (downmix_output) { +#if USE_FIXED + ac3_downmix_c_fixed16(s->outptr, s->downmix_coeffs, + s->out_channels, s->fbw_channels, 256); +#else s->ac3dsp.downmix(s->outptr, s->downmix_coeffs, s->out_channels, s->fbw_channels, 256); +#endif } } else { if (downmix_output) { - s->ac3dsp.downmix(s->xcfptr + 1, s->downmix_coeffs, - s->out_channels, s->fbw_channels, 256); + s->ac3dsp.AC3_RENAME(downmix)(s->xcfptr + 1, s->downmix_coeffs, + s->out_channels, s->fbw_channels, 256); } if (downmix_output && !s->downmixed) { s->downmixed = 1; - s->ac3dsp.downmix(s->dlyptr, s->downmix_coeffs, s->out_channels, - s->fbw_channels, 128); + s->ac3dsp.AC3_RENAME(downmix)(s->dlyptr, s->downmix_coeffs, + s->out_channels, s->fbw_channels, 128); } do_imdct(s, s->out_channels); @@ -1320,7 +1389,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, AC3DecodeContext *s = avctx->priv_data; int blk, ch, err, ret; const uint8_t *channel_map; - const float *output[AC3_MAX_CHANNELS]; + const SHORTFLOAT *output[AC3_MAX_CHANNELS]; enum AVMatrixEncoding matrix_encoding; AVDownmixInfo *downmix_info; @@ -1329,7 +1398,8 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, if (buf_size >= 2 && AV_RB16(buf) == 0x770B) { // seems to be byte-swapped AC-3 int cnt = FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE) >> 1; - s->dsp.bswap16_buf((uint16_t *)s->input_buffer, (const uint16_t *)buf, cnt); + s->bdsp.bswap16_buf((uint16_t *) s->input_buffer, + (const uint16_t *) buf, cnt); } else memcpy(s->input_buffer, buf, FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE)); buf = s->input_buffer; @@ -1447,7 +1517,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, } for (ch = 0; ch < s->channels; ch++) { if (ch < s->out_channels) - s->outptr[channel_map[ch]] = (float *)frame->data[ch]; + s->outptr[channel_map[ch]] = (SHORTFLOAT *)frame->data[ch]; } for (blk = 0; blk < s->num_blocks; blk++) { if (!err && decode_audio_block(s, blk)) { @@ -1456,7 +1526,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, } if (err) for (ch = 0; ch < s->out_channels; ch++) - memcpy(((float*)frame->data[ch]) + AC3_BLOCK_SIZE*blk, output[ch], sizeof(**output) * AC3_BLOCK_SIZE); + memcpy(((SHORTFLOAT*)frame->data[ch]) + AC3_BLOCK_SIZE*blk, output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT)); for (ch = 0; ch < s->out_channels; ch++) output[ch] = s->outptr[channel_map[ch]]; for (ch = 0; ch < s->out_channels; ch++) { @@ -1469,7 +1539,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, /* keep last block for error concealment in next frame */ for (ch = 0; ch < s->out_channels; ch++) - memcpy(s->output[ch], output[ch], sizeof(**output) * AC3_BLOCK_SIZE); + memcpy(s->output[ch], output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT)); /* * AVMatrixEncoding @@ -1540,66 +1610,12 @@ static av_cold int ac3_decode_end(AVCodecContext *avctx) AC3DecodeContext *s = avctx->priv_data; ff_mdct_end(&s->imdct_512); ff_mdct_end(&s->imdct_256); +#if (USE_FIXED) + av_freep(&s->fdsp); +#endif return 0; } #define OFFSET(x) offsetof(AC3DecodeContext, x) #define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM) -static const AVOption options[] = { - { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR }, - -{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 2, 0, "dmix_mode"}, -{"ltrt_cmixlev", "Lt/Rt Center Mix Level", OFFSET(ltrt_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, -{"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, -{"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, -{"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, - - { NULL}, -}; - -static const AVClass ac3_decoder_class = { - .class_name = "AC3 decoder", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVCodec ff_ac3_decoder = { - .name = "ac3", - .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AC3, - .priv_data_size = sizeof (AC3DecodeContext), - .init = ac3_decode_init, - .close = ac3_decode_end, - .decode = ac3_decode_frame, - .capabilities = CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, - AV_SAMPLE_FMT_NONE }, - .priv_class = &ac3_decoder_class, -}; - -#if CONFIG_EAC3_DECODER -static const AVClass eac3_decoder_class = { - .class_name = "E-AC3 decoder", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVCodec ff_eac3_decoder = { - .name = "eac3", - .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_EAC3, - .priv_data_size = sizeof (AC3DecodeContext), - .init = ac3_decode_init, - .close = ac3_decode_end, - .decode = ac3_decode_frame, - .capabilities = CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, - AV_SAMPLE_FMT_NONE }, - .priv_class = &eac3_decoder_class, -}; -#endif diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h index 58d8ee69b..3ac44ee17 100644 --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@ -51,11 +51,12 @@ #define AVCODEC_AC3DEC_H #include "libavutil/float_dsp.h" +#include "libavutil/fixed_dsp.h" #include "libavutil/lfg.h" #include "ac3.h" #include "ac3dsp.h" +#include "bswapdsp.h" #include "get_bits.h" -#include "dsputil.h" #include "fft.h" #include "fmtconvert.h" @@ -138,8 +139,8 @@ typedef struct AC3DecodeContext { int num_spx_bands; ///< number of spx bands (nspxbnds) uint8_t spx_band_sizes[SPX_MAX_BANDS]; ///< number of bins in each spx band uint8_t first_spx_coords[AC3_MAX_CHANNELS]; ///< first spx coordinates states (firstspxcos) - float spx_noise_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS]; ///< spx noise blending factor (nblendfact) - float spx_signal_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS];///< spx signal blending factor (sblendfact) + INTFLOAT spx_noise_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS]; ///< spx noise blending factor (nblendfact) + INTFLOAT spx_signal_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS];///< spx signal blending factor (sblendfact) ///@} ///@name Adaptive hybrid transform @@ -151,15 +152,15 @@ typedef struct AC3DecodeContext { int fbw_channels; ///< number of full-bandwidth channels int channels; ///< number of total channels int lfe_ch; ///< index of LFE channel - float downmix_coeffs[AC3_MAX_CHANNELS][2]; ///< stereo downmix coefficients + SHORTFLOAT downmix_coeffs[AC3_MAX_CHANNELS][2]; ///< stereo downmix coefficients int downmixed; ///< indicates if coeffs are currently downmixed int output_mode; ///< output channel configuration int out_channels; ///< number of output channels ///@} ///@name Dynamic range - float dynamic_range[2]; ///< dynamic range - float drc_scale; ///< percentage of dynamic range compression to be applied + INTFLOAT dynamic_range[2]; ///< dynamic range + INTFLOAT drc_scale; ///< percentage of dynamic range compression to be applied ///@} ///@name Bandwidth @@ -206,23 +207,27 @@ typedef struct AC3DecodeContext { ///@} ///@name Optimization - DSPContext dsp; ///< for optimization + BswapDSPContext bdsp; +#if USE_FIXED + AVFixedDSPContext *fdsp; +#else AVFloatDSPContext fdsp; +#endif AC3DSPContext ac3dsp; FmtConvertContext fmt_conv; ///< optimized conversion functions ///@} - float *outptr[AC3_MAX_CHANNELS]; - float *xcfptr[AC3_MAX_CHANNELS]; - float *dlyptr[AC3_MAX_CHANNELS]; + SHORTFLOAT *outptr[AC3_MAX_CHANNELS]; + INTFLOAT *xcfptr[AC3_MAX_CHANNELS]; + INTFLOAT *dlyptr[AC3_MAX_CHANNELS]; ///@name Aligned arrays - DECLARE_ALIGNED(16, int32_t, fixed_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< fixed-point transform coefficients - DECLARE_ALIGNED(32, float, transform_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< transform coefficients - DECLARE_ALIGNED(32, float, delay)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< delay - added to the next block - DECLARE_ALIGNED(32, float, window)[AC3_BLOCK_SIZE]; ///< window coefficients - DECLARE_ALIGNED(32, float, tmp_output)[AC3_BLOCK_SIZE]; ///< temporary storage for output before windowing - DECLARE_ALIGNED(32, float, output)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing + DECLARE_ALIGNED(16, int, fixed_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< fixed-point transform coefficients + DECLARE_ALIGNED(32, INTFLOAT, transform_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< transform coefficients + DECLARE_ALIGNED(32, INTFLOAT, delay)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< delay - added to the next block + DECLARE_ALIGNED(32, INTFLOAT, window)[AC3_BLOCK_SIZE]; ///< window coefficients + DECLARE_ALIGNED(32, INTFLOAT, tmp_output)[AC3_BLOCK_SIZE]; ///< temporary storage for output before windowing + DECLARE_ALIGNED(32, SHORTFLOAT, output)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing DECLARE_ALIGNED(32, uint8_t, input_buffer)[AC3_FRAME_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; ///< temp buffer to prevent overread ///@} } AC3DecodeContext; diff --git a/libavcodec/ac3dec_fixed.c b/libavcodec/ac3dec_fixed.c new file mode 100644 index 000000000..c6cbeb9b2 --- /dev/null +++ b/libavcodec/ac3dec_fixed.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Stanislav Ocovaj (socovaj@mips.com) + * + * AC3 fixed-point decoder for MIPS platforms + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define FFT_FLOAT 0 +#define USE_FIXED 1 +#define FFT_FIXED_32 1 +#include "ac3dec.h" + + +/** + * Table for center mix levels + * reference: Section 5.4.2.4 cmixlev + */ +static const uint8_t center_levels[4] = { 4, 5, 6, 5 }; + +/** + * Table for surround mix levels + * reference: Section 5.4.2.5 surmixlev + */ +static const uint8_t surround_levels[4] = { 4, 6, 7, 6 }; + +int end_freq_inv_tab[8] = +{ + 50529027, 44278013, 39403370, 32292987, 27356480, 23729101, 20951060, 18755316 +}; + +static void scale_coefs ( + int32_t *dst, + const int32_t *src, + int dynrng, + int len) +{ + int i, shift, round; + int16_t mul; + int temp, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + mul = (dynrng & 0x1f) + 0x20; + shift = 4 - ((dynrng << 24) >> 29); + round = 1 << (shift-1); + for (i=0; i> shift; + temp3 = src[i+3] * mul; + temp2 = temp2 + round; + + dst[i+1] = temp1 >> shift; + temp4 = src[i + 4] * mul; + temp3 = temp3 + round; + dst[i+2] = temp2 >> shift; + + temp5 = src[i+5] * mul; + temp4 = temp4 + round; + dst[i+3] = temp3 >> shift; + temp6 = src[i+6] * mul; + + dst[i+4] = temp4 >> shift; + temp5 = temp5 + round; + temp7 = src[i+7] * mul; + temp6 = temp6 + round; + + dst[i+5] = temp5 >> shift; + temp7 = temp7 + round; + dst[i+6] = temp6 >> shift; + dst[i+7] = temp7 >> shift; + + } +} + +/** + * Downmix samples from original signal to stereo or mono (this is for 16-bit samples + * and fixed point decoder - original (for 32-bit samples) is in ac3dsp.c). + */ +static void ac3_downmix_c_fixed16(int16_t **samples, int16_t (*matrix)[2], + int out_ch, int in_ch, int len) +{ + int i, j; + int v0, v1; + if (out_ch == 2) { + for (i = 0; i < len; i++) { + v0 = v1 = 0; + for (j = 0; j < in_ch; j++) { + v0 += samples[j][i] * matrix[j][0]; + v1 += samples[j][i] * matrix[j][1]; + } + samples[0][i] = (v0+2048)>>12; + samples[1][i] = (v1+2048)>>12; + } + } else if (out_ch == 1) { + for (i = 0; i < len; i++) { + v0 = 0; + for (j = 0; j < in_ch; j++) + v0 += samples[j][i] * matrix[j][0]; + samples[0][i] = (v0+2048)>>12; + } + } +} + +#include "ac3dec.c" + +static const AVOption options[] = { + { NULL}, +}; + +static const AVClass ac3_decoder_class = { + .class_name = "Fixed-Point AC-3 Decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_ac3_fixed_decoder = { + .name = "ac3_fixed", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AC3, + .priv_data_size = sizeof (AC3DecodeContext), + .init = ac3_decode_init, + .close = ac3_decode_end, + .decode = ac3_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, + .priv_class = &ac3_decoder_class, +}; diff --git a/libavcodec/ac3dec_float.c b/libavcodec/ac3dec_float.c new file mode 100644 index 000000000..710892170 --- /dev/null +++ b/libavcodec/ac3dec_float.c @@ -0,0 +1,89 @@ +/* + * AC-3 Audio Decoder + * This code was developed as part of Google Summer of Code 2006. + * E-AC-3 support was added as part of Google Summer of Code 2007. + * + * Copyright (c) 2006 Kartikey Mahendra BHATT (bhattkm at gmail dot com) + * Copyright (c) 2007-2008 Bartlomiej Wolowiec + * Copyright (c) 2007 Justin Ruggles + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * Upmix delay samples from stereo to original channel layout. + */ +#include "ac3dec.h" +#include "ac3dec.c" + +static const AVOption options[] = { + { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR }, + +{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 2, 0, "dmix_mode"}, +{"ltrt_cmixlev", "Lt/Rt Center Mix Level", OFFSET(ltrt_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, +{"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, +{"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, +{"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, + + { NULL}, +}; + +static const AVClass ac3_decoder_class = { + .class_name = "AC3 decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_ac3_decoder = { + .name = "ac3", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AC3, + .priv_data_size = sizeof (AC3DecodeContext), + .init = ac3_decode_init, + .close = ac3_decode_end, + .decode = ac3_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, + .priv_class = &ac3_decoder_class, +}; + +#if CONFIG_EAC3_DECODER +static const AVClass eac3_decoder_class = { + .class_name = "E-AC3 decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_eac3_decoder = { + .name = "eac3", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_EAC3, + .priv_data_size = sizeof (AC3DecodeContext), + .init = ac3_decode_init, + .close = ac3_decode_end, + .decode = ac3_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, + .priv_class = &eac3_decoder_class, +}; +#endif diff --git a/libavcodec/ac3dsp.c b/libavcodec/ac3dsp.c index feda6ddc6..b746817c9 100644 --- a/libavcodec/ac3dsp.c +++ b/libavcodec/ac3dsp.c @@ -1,5 +1,5 @@ /* - * AC-3 DSP utils + * AC-3 DSP functions * Copyright (c) 2011 Justin Ruggles * * This file is part of FFmpeg. @@ -239,6 +239,31 @@ static void ac3_downmix_c(float **samples, float (*matrix)[2], } } +static void ac3_downmix_c_fixed(int32_t **samples, int16_t (*matrix)[2], + int out_ch, int in_ch, int len) +{ + int i, j; + int64_t v0, v1; + if (out_ch == 2) { + for (i = 0; i < len; i++) { + v0 = v1 = 0; + for (j = 0; j < in_ch; j++) { + v0 += (int64_t)samples[j][i] * matrix[j][0]; + v1 += (int64_t)samples[j][i] * matrix[j][1]; + } + samples[0][i] = (v0+2048)>>12; + samples[1][i] = (v1+2048)>>12; + } + } else if (out_ch == 1) { + for (i = 0; i < len; i++) { + v0 = 0; + for (j = 0; j < in_ch; j++) + v0 += (int64_t)samples[j][i] * matrix[j][0]; + samples[0][i] = (v0+2048)>>12; + } + } +} + static void apply_window_int16_c(int16_t *output, const int16_t *input, const int16_t *window, unsigned int len) { @@ -266,6 +291,7 @@ av_cold void ff_ac3dsp_init(AC3DSPContext *c, int bit_exact) c->sum_square_butterfly_int32 = ac3_sum_square_butterfly_int32_c; c->sum_square_butterfly_float = ac3_sum_square_butterfly_float_c; c->downmix = ac3_downmix_c; + c->downmix_fixed = ac3_downmix_c_fixed; c->apply_window_int16 = apply_window_int16_c; if (ARCH_ARM) diff --git a/libavcodec/ac3dsp.h b/libavcodec/ac3dsp.h index bced5974e..ed98c8ce6 100644 --- a/libavcodec/ac3dsp.h +++ b/libavcodec/ac3dsp.h @@ -1,5 +1,5 @@ /* - * AC-3 DSP utils + * AC-3 DSP functions * Copyright (c) 2011 Justin Ruggles * * This file is part of FFmpeg. @@ -135,6 +135,9 @@ typedef struct AC3DSPContext { void (*downmix)(float **samples, float (*matrix)[2], int out_ch, int in_ch, int len); + void (*downmix_fixed)(int32_t **samples, int16_t (*matrix)[2], int out_ch, + int in_ch, int len); + /** * Apply symmetric window in 16-bit fixed-point. * @param output destination array diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 37c496cd1..dc974702d 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -37,6 +37,7 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "put_bits.h" +#include "audiodsp.h" #include "ac3dsp.h" #include "ac3.h" #include "fft.h" @@ -1381,7 +1382,7 @@ static void ac3_output_frame_header(AC3EncodeContext *s) */ static void output_audio_block(AC3EncodeContext *s, int blk) { - int ch, i, baie, bnd, got_cpl, ch0; + int ch, i, baie, bnd, got_cpl, av_uninit(ch0); AC3Block *block = &s->blocks[blk]; /* block switching */ @@ -2246,7 +2247,7 @@ static av_cold int validate_options(AC3EncodeContext *s) */ static av_cold void set_bandwidth(AC3EncodeContext *s) { - int blk, ch, cpl_start; + int blk, ch, av_uninit(cpl_start); if (s->cutoff) { /* calculate bandwidth based on user-specified cutoff frequency */ @@ -2478,8 +2479,8 @@ av_cold int ff_ac3_encode_init(AVCodecContext *avctx) if (ret) goto init_fail; + ff_audiodsp_init(&s->adsp); ff_dsputil_init(&s->dsp, avctx); - avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); ff_ac3dsp_init(&s->ac3dsp, avctx->flags & CODEC_FLAG_BITEXACT); dprint_options(s); diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h index a04e704d9..0ce44bab1 100644 --- a/libavcodec/ac3enc.h +++ b/libavcodec/ac3enc.h @@ -31,12 +31,15 @@ #include #include "libavutil/float_dsp.h" + #include "ac3.h" #include "ac3dsp.h" #include "avcodec.h" #include "dsputil.h" -#include "put_bits.h" #include "fft.h" +#include "mathops.h" +#include "put_bits.h" +#include "audiodsp.h" #ifndef CONFIG_AC3ENC_FLOAT #define CONFIG_AC3ENC_FLOAT 0 @@ -160,6 +163,7 @@ typedef struct AC3EncodeContext { AVCodecContext *avctx; ///< parent AVCodecContext PutBitContext pb; ///< bitstream writer context DSPContext dsp; + AudioDSPContext adsp; AVFloatDSPContext fdsp; AC3DSPContext ac3dsp; ///< AC-3 optimized functions FFTContext mdct; ///< FFT context for MDCT calculation @@ -264,6 +268,7 @@ typedef struct AC3EncodeContext { extern const uint64_t ff_ac3_channel_layouts[19]; int ff_ac3_encode_init(AVCodecContext *avctx); +int ff_ac3_float_encode_init(AVCodecContext *avctx); int ff_ac3_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c index 3994c17d3..9d39026dd 100644 --- a/libavcodec/ac3enc_fixed.c +++ b/libavcodec/ac3enc_fixed.c @@ -29,6 +29,7 @@ #define FFT_FLOAT 0 #undef CONFIG_AC3ENC_FLOAT #include "internal.h" +#include "audiodsp.h" #include "ac3enc.h" #include "eac3enc.h" @@ -111,9 +112,10 @@ static void sum_square_butterfly(AC3EncodeContext *s, int64_t sum[4], /* * Clip MDCT coefficients to allowable range. */ -static void clip_coefficients(DSPContext *dsp, int32_t *coef, unsigned int len) +static void clip_coefficients(AudioDSPContext *adsp, int32_t *coef, + unsigned int len) { - dsp->vector_clip_int32(coef, coef, COEF_MIN, COEF_MAX, len); + adsp->vector_clip_int32(coef, coef, COEF_MIN, COEF_MAX, len); } diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c index 35fb4189c..fa6e50981 100644 --- a/libavcodec/ac3enc_float.c +++ b/libavcodec/ac3enc_float.c @@ -28,12 +28,12 @@ #define CONFIG_AC3ENC_FLOAT 1 #include "internal.h" +#include "audiodsp.h" #include "ac3enc.h" #include "eac3enc.h" #include "kbdwin.h" -#if CONFIG_AC3_ENCODER #define AC3ENC_TYPE AC3ENC_TYPE_AC3 #include "ac3enc_opts_template.c" static const AVClass ac3enc_class = { @@ -42,7 +42,6 @@ static const AVClass ac3enc_class = { .option = ac3_options, .version = LIBAVUTIL_VERSION_INT, }; -#endif #include "ac3enc_template.c" @@ -73,7 +72,7 @@ av_cold int ff_ac3_float_mdct_init(AC3EncodeContext *s) n = 1 << 9; n2 = n >> 1; - window = av_malloc(n * sizeof(*window)); + window = av_malloc_array(n, sizeof(*window)); if (!window) { av_log(s->avctx, AV_LOG_ERROR, "Cannot allocate memory.\n"); return AVERROR(ENOMEM); @@ -119,9 +118,10 @@ static void sum_square_butterfly(AC3EncodeContext *s, float sum[4], /* * Clip MDCT coefficients to allowable range. */ -static void clip_coefficients(DSPContext *dsp, float *coef, unsigned int len) +static void clip_coefficients(AudioDSPContext *adsp, float *coef, + unsigned int len) { - dsp->vector_clipf(coef, coef, COEF_MIN, COEF_MAX, len); + adsp->vector_clipf(coef, coef, COEF_MIN, COEF_MAX, len); } @@ -136,15 +136,20 @@ static CoefType calc_cpl_coord(CoefSumType energy_ch, CoefSumType energy_cpl) return FFMIN(coord, COEF_MAX); } +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); + return ff_ac3_encode_init(avctx); +} -#if CONFIG_AC3_ENCODER AVCodec ff_ac3_encoder = { .name = "ac3", .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_AC3, .priv_data_size = sizeof(AC3EncodeContext), - .init = ff_ac3_encode_init, + .init = ff_ac3_float_encode_init, .encode2 = ff_ac3_float_encode_frame, .close = ff_ac3_encode_close, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, @@ -153,4 +158,3 @@ AVCodec ff_ac3_encoder = { .channel_layouts = ff_ac3_channel_layouts, .defaults = ac3_defaults, }; -#endif diff --git a/libavcodec/ac3enc_template.c b/libavcodec/ac3enc_template.c index 4689f7020..192d16f57 100644 --- a/libavcodec/ac3enc_template.c +++ b/libavcodec/ac3enc_template.c @@ -28,15 +28,22 @@ #include +#include "libavutil/attributes.h" #include "libavutil/internal.h" +#include "audiodsp.h" +#include "internal.h" +#include "ac3enc.h" +#include "eac3enc.h" + /* prototypes for static functions in ac3enc_fixed.c and ac3enc_float.c */ static void scale_coefficients(AC3EncodeContext *s); static int normalize_samples(AC3EncodeContext *s); -static void clip_coefficients(DSPContext *dsp, CoefType *coef, unsigned int len); +static void clip_coefficients(AudioDSPContext *adsp, CoefType *coef, + unsigned int len); static CoefType calc_cpl_coord(CoefSumType energy_ch, CoefSumType energy_cpl); @@ -160,7 +167,7 @@ static void apply_channel_coupling(AC3EncodeContext *s) } /* coefficients must be clipped in order to be encoded */ - clip_coefficients(&s->dsp, cpl_coef, num_cpl_coefs); + clip_coefficients(&s->adsp, cpl_coef, num_cpl_coefs); } /* calculate energy in each band in coupling channel and each fbw channel */ @@ -403,7 +410,7 @@ int AC3_NAME(encode_frame)(AVCodecContext *avctx, AVPacket *avpkt, if (s->fixed_point) scale_coefficients(s); - clip_coefficients(&s->dsp, s->blocks[0].mdct_coef[1], + clip_coefficients(&s->adsp, s->blocks[0].mdct_coef[1], AC3_MAX_COEFS * s->num_blocks * s->channels); s->cpl_on = s->cpl_enabled; diff --git a/libavcodec/ac3tab.c b/libavcodec/ac3tab.c index 1ae7ddf2a..d62d8bfbf 100644 --- a/libavcodec/ac3tab.c +++ b/libavcodec/ac3tab.c @@ -25,6 +25,8 @@ */ #include "libavutil/channel_layout.h" +#include "libavutil/mem.h" + #include "avcodec.h" #include "ac3tab.h" diff --git a/libavcodec/acelp_pitch_delay.c b/libavcodec/acelp_pitch_delay.c index c005c4b4e..3ecec01cb 100644 --- a/libavcodec/acelp_pitch_delay.c +++ b/libavcodec/acelp_pitch_delay.c @@ -27,6 +27,7 @@ #include "avcodec.h" #include "acelp_pitch_delay.h" #include "celp_math.h" +#include "audiodsp.h" int ff_acelp_decode_8bit_to_1st_delay3(int ac_index) { @@ -91,7 +92,7 @@ void ff_acelp_update_past_gain( } int16_t ff_acelp_decode_gain_code( - DSPContext *dsp, + AudioDSPContext *adsp, int gain_corr_factor, const int16_t* fc_v, int mr_energy, @@ -118,7 +119,7 @@ int16_t ff_acelp_decode_gain_code( ); #else mr_energy = gain_corr_factor * exp(M_LN10 / (20 << 23) * mr_energy) / - sqrt(dsp->scalarproduct_int16(fc_v, fc_v, subframe_size)); + sqrt(adsp->scalarproduct_int16(fc_v, fc_v, subframe_size)); return mr_energy >> 12; #endif } diff --git a/libavcodec/acelp_pitch_delay.h b/libavcodec/acelp_pitch_delay.h index 72977f1f4..2aade2f22 100644 --- a/libavcodec/acelp_pitch_delay.h +++ b/libavcodec/acelp_pitch_delay.h @@ -24,7 +24,8 @@ #define AVCODEC_ACELP_PITCH_DELAY_H #include -#include "dsputil.h" + +#include "audiodsp.h" #define PITCH_DELAY_MIN 20 #define PITCH_DELAY_MAX 143 @@ -139,7 +140,7 @@ void ff_acelp_update_past_gain( /** * @brief Decode the adaptive codebook gain and add * correction (4.1.5 and 3.9.1 of G.729). - * @param dsp initialized dsputil context + * @param adsp initialized audio DSP context * @param gain_corr_factor gain correction factor (2.13) * @param fc_v fixed-codebook vector (2.13) * @param mr_energy mean innovation energy and fixed-point correction (7.13) @@ -208,7 +209,7 @@ void ff_acelp_update_past_gain( * @remark The routine is used in G.729 and AMR (all modes). */ int16_t ff_acelp_decode_gain_code( - DSPContext *dsp, + AudioDSPContext *adsp, int gain_corr_factor, const int16_t* fc_v, int mr_energy, diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index f7f82599b..e31242f02 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -555,17 +555,16 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, case AV_CODEC_ID_ADPCM_EA_R2: header_size = 4 + 5 * ch; *coded_samples = bytestream2_get_le32(gb); - *approx_nb_samples = 1; break; case AV_CODEC_ID_ADPCM_EA_R3: header_size = 4 + 5 * ch; *coded_samples = bytestream2_get_be32(gb); - *approx_nb_samples = 1; break; } *coded_samples -= *coded_samples % 28; nb_samples = (buf_size - header_size) * 2 / ch; nb_samples -= nb_samples % 28; + *approx_nb_samples = 1; break; case AV_CODEC_ID_ADPCM_IMA_DK3: if (avctx->block_align > 0) diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c index da149a396..c3e4d0fdf 100644 --- a/libavcodec/adpcmenc.c +++ b/libavcodec/adpcmenc.c @@ -332,7 +332,7 @@ static void adpcm_compress_trellis(AVCodecContext *avctx, uint8_t *h;\ dec_sample = av_clip_int16(dec_sample);\ d = sample - dec_sample;\ - ssd = nodes[j]->ssd + d*d;\ + ssd = nodes[j]->ssd + d*(unsigned)d;\ /* Check for wraparound, skip such samples completely. \ * Note, changing ssd to a 64 bit variable would be \ * simpler, avoiding this check, but it's slower on \ diff --git a/libavcodec/adx.c b/libavcodec/adx.c index 30e13c0c1..9c5bedc23 100644 --- a/libavcodec/adx.c +++ b/libavcodec/adx.c @@ -35,8 +35,8 @@ void ff_adx_calculate_coeffs(int cutoff, int sample_rate, int bits, int *coeff) coeff[1] = lrintf(-(c * c) * (1 << bits)); } -int avpriv_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, - int bufsize, int *header_size, int *coeff) +int ff_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, + int bufsize, int *header_size, int *coeff) { int offset, cutoff; @@ -80,3 +80,11 @@ int avpriv_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, *header_size = offset; return 0; } + +#if LIBAVCODEC_VERSION_MAJOR < 56 +int avpriv_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, + int bufsize, int *header_size, int *coeff) +{ + return ff_adx_decode_header(avctx, buf, bufsize, header_size, coeff); +} +#endif diff --git a/libavcodec/adx.h b/libavcodec/adx.h index b28d09a32..ca59a2dcc 100644 --- a/libavcodec/adx.h +++ b/libavcodec/adx.h @@ -74,7 +74,12 @@ void ff_adx_calculate_coeffs(int cutoff, int sample_rate, int bits, int *coeff); * @param[out] coeff 2 LPC coefficients, can be NULL * @return data offset or negative error code if header is invalid */ +int ff_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, + int bufsize, int *header_size, int *coeff); + +#if LIBAVCODEC_VERSION_MAJOR < 56 int avpriv_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, int bufsize, int *header_size, int *coeff); +#endif #endif /* AVCODEC_ADX_H */ diff --git a/libavcodec/adxdec.c b/libavcodec/adxdec.c index ec33e7354..5115cede6 100644 --- a/libavcodec/adxdec.c +++ b/libavcodec/adxdec.c @@ -40,9 +40,9 @@ static av_cold int adx_decode_init(AVCodecContext *avctx) int ret, header_size; if (avctx->extradata_size >= 24) { - if ((ret = avpriv_adx_decode_header(avctx, avctx->extradata, - avctx->extradata_size, &header_size, - c->coeff)) < 0) { + if ((ret = ff_adx_decode_header(avctx, avctx->extradata, + avctx->extradata_size, &header_size, + c->coeff)) < 0) { av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n"); return AVERROR_INVALIDDATA; } @@ -111,8 +111,8 @@ static int adx_decode_frame(AVCodecContext *avctx, void *data, if (!c->header_parsed && buf_size >= 2 && AV_RB16(buf) == 0x8000) { int header_size; - if ((ret = avpriv_adx_decode_header(avctx, buf, buf_size, &header_size, - c->coeff)) < 0) { + if ((ret = ff_adx_decode_header(avctx, buf, buf_size, &header_size, + c->coeff)) < 0) { av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n"); return AVERROR_INVALIDDATA; } diff --git a/libavcodec/aic.c b/libavcodec/aic.c index 396364219..00be08bf2 100644 --- a/libavcodec/aic.c +++ b/libavcodec/aic.c @@ -20,12 +20,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "avcodec.h" #include "bytestream.h" -#include "dsputil.h" #include "internal.h" #include "get_bits.h" #include "golomb.h" +#include "idctdsp.h" #include "unary.h" #define AIC_HDR_SIZE 24 @@ -137,7 +139,7 @@ static const uint8_t *aic_scan[NUM_BANDS] = { typedef struct AICContext { AVCodecContext *avctx; AVFrame *frame; - DSPContext dsp; + IDCTDSPContext idsp; ScanTable scantable; int num_x_slices; @@ -170,7 +172,7 @@ static int aic_decode_header(AICContext *ctx, const uint8_t *src, int size) width = AV_RB16(src + 6); height = AV_RB16(src + 8); if (frame_size > size) { - av_log(ctx->avctx, AV_LOG_ERROR, "Frame size should be %d got %d\n", + av_log(ctx->avctx, AV_LOG_ERROR, "Frame size should be %"PRIu32" got %d\n", frame_size, size); return AVERROR_INVALIDDATA; } @@ -336,16 +338,15 @@ static int aic_decode_slice(AICContext *ctx, int mb_x, int mb_y, recombine_block_il(ctx->block, ctx->scantable.permutated, &base_y, &ext_y, blk); unquant_block(ctx->block, ctx->quant, ctx->quant_matrix); - ctx->dsp.idct(ctx->block); + ctx->idsp.idct(ctx->block); if (!ctx->interlaced) { dst = Y + (blk >> 1) * 8 * ystride + (blk & 1) * 8; - ctx->dsp.put_signed_pixels_clamped(ctx->block, dst, - ystride); + ctx->idsp.put_signed_pixels_clamped(ctx->block, dst, ystride); } else { dst = Y + (blk & 1) * 8 + (blk >> 1) * ystride; - ctx->dsp.put_signed_pixels_clamped(ctx->block, dst, - ystride * 2); + ctx->idsp.put_signed_pixels_clamped(ctx->block, dst, + ystride * 2); } } Y += 16; @@ -354,9 +355,9 @@ static int aic_decode_slice(AICContext *ctx, int mb_x, int mb_y, recombine_block(ctx->block, ctx->scantable.permutated, &base_c, &ext_c); unquant_block(ctx->block, ctx->quant, ctx->quant_matrix); - ctx->dsp.idct(ctx->block); - ctx->dsp.put_signed_pixels_clamped(ctx->block, C[blk], - ctx->frame->linesize[blk + 1]); + ctx->idsp.idct(ctx->block); + ctx->idsp.put_signed_pixels_clamped(ctx->block, C[blk], + ctx->frame->linesize[blk + 1]); C[blk] += 8; } } @@ -426,13 +427,13 @@ static av_cold int aic_decode_init(AVCodecContext *avctx) avctx->pix_fmt = AV_PIX_FMT_YUV420P; - ff_dsputil_init(&ctx->dsp, avctx); + ff_idctdsp_init(&ctx->idsp, avctx); for (i = 0; i < 64; i++) scan[i] = i; - ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, scan); + ff_init_scantable(ctx->idsp.idct_permutation, &ctx->scantable, scan); for (i = 0; i < 64; i++) - ctx->quant_matrix[ctx->dsp.idct_permutation[i]] = aic_quant_matrix[i]; + ctx->quant_matrix[ctx->idsp.idct_permutation[i]] = aic_quant_matrix[i]; ctx->mb_width = FFALIGN(avctx->width, 16) >> 4; ctx->mb_height = FFALIGN(avctx->height, 16) >> 4; diff --git a/libavcodec/alac.c b/libavcodec/alac.c index 1e28efd71..103d14ead 100644 --- a/libavcodec/alac.c +++ b/libavcodec/alac.c @@ -45,6 +45,8 @@ * 32bit samplerate */ +#include + #include "libavutil/channel_layout.h" #include "avcodec.h" #include "get_bits.h" @@ -283,7 +285,7 @@ static int decode_element(AVCodecContext *avctx, AVFrame *frame, int ch_index, else output_samples = alac->max_samples_per_frame; if (!output_samples || output_samples > alac->max_samples_per_frame) { - av_log(avctx, AV_LOG_ERROR, "invalid samples per frame: %d\n", + av_log(avctx, AV_LOG_ERROR, "invalid samples per frame: %"PRIu32"\n", output_samples); return AVERROR_INVALIDDATA; } @@ -294,7 +296,7 @@ static int decode_element(AVCodecContext *avctx, AVFrame *frame, int ch_index, if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) return ret; } else if (output_samples != alac->nb_samples) { - av_log(avctx, AV_LOG_ERROR, "sample count mismatch: %u != %d\n", + av_log(avctx, AV_LOG_ERROR, "sample count mismatch: %"PRIu32" != %d\n", output_samples, alac->nb_samples); return AVERROR_INVALIDDATA; } @@ -549,7 +551,8 @@ static int alac_set_info(ALACContext *alac) alac->max_samples_per_frame = bytestream2_get_be32u(&gb); if (!alac->max_samples_per_frame || alac->max_samples_per_frame > INT_MAX / sizeof(int32_t)) { - av_log(alac->avctx, AV_LOG_ERROR, "max samples per frame invalid: %u\n", + av_log(alac->avctx, AV_LOG_ERROR, + "max samples per frame invalid: %"PRIu32"\n", alac->max_samples_per_frame); return AVERROR_INVALIDDATA; } diff --git a/libavcodec/aliaspixdec.c b/libavcodec/aliaspixdec.c new file mode 100644 index 000000000..bdc4c72c2 --- /dev/null +++ b/libavcodec/aliaspixdec.c @@ -0,0 +1,128 @@ +/* + * Alias PIX image decoder + * Copyright (C) 2014 Vittorio Giovara + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#define ALIAS_HEADER_SIZE 10 + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + AVFrame *f = data; + GetByteContext gb; + int width, height, ret, bits_pixel, pixel; + uint8_t *out_buf; + uint8_t count; + int x, y; + + bytestream2_init(&gb, avpkt->data, avpkt->size); + + if (bytestream2_get_bytes_left(&gb) < ALIAS_HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Header too small %d.\n", avpkt->size); + return AVERROR_INVALIDDATA; + } + + width = bytestream2_get_be16u(&gb); + height = bytestream2_get_be16u(&gb); + bytestream2_skipu(&gb, 4); // obsolete X, Y offset + bits_pixel = bytestream2_get_be16u(&gb); + + if (bits_pixel == 24) + avctx->pix_fmt = AV_PIX_FMT_BGR24; + else if (bits_pixel == 8) + avctx->pix_fmt = AV_PIX_FMT_GRAY8; + else { + av_log(avctx, AV_LOG_ERROR, "Invalid pixel format.\n"); + return AVERROR_INVALIDDATA; + } + + ret = ff_set_dimensions(avctx, width, height); + if (ret < 0) + return ret; + + ret = ff_get_buffer(avctx, f, 0); + if (ret < 0) + return ret; + + f->pict_type = AV_PICTURE_TYPE_I; + f->key_frame = 1; + + x = 0; + y = 1; + out_buf = f->data[0]; + while (bytestream2_get_bytes_left(&gb) > 0) { + int i; + + /* set buffer at the right position at every new line */ + if (x == avctx->width) { + x = 0; + out_buf = f->data[0] + f->linesize[0] * y++; + if (y > avctx->height) { + av_log(avctx, AV_LOG_ERROR, + "Ended frame decoding with %d bytes left.\n", + bytestream2_get_bytes_left(&gb)); + return AVERROR_INVALIDDATA; + } + } + + /* read packet and copy data */ + count = bytestream2_get_byteu(&gb); + if (!count || x + count > avctx->width) { + av_log(avctx, AV_LOG_ERROR, "Invalid run length %d.\n", count); + return AVERROR_INVALIDDATA; + } + + if (avctx->pix_fmt == AV_PIX_FMT_BGR24) { + pixel = bytestream2_get_be24(&gb); + for (i = 0; i < count; i++) { + AV_WB24(out_buf, pixel); + out_buf += 3; + } + } else { // AV_PIX_FMT_GRAY8 + pixel = bytestream2_get_byte(&gb); + for (i = 0; i < count; i++) + *out_buf++ = pixel; + } + + x += i; + } + + if (x != width || y != height) { + av_log(avctx, AV_LOG_ERROR, "Picture stopped at %d,%d.\n", x, y); + return AVERROR_INVALIDDATA; + } + + *got_frame = 1; + return avpkt->size; +} + +AVCodec ff_alias_pix_decoder = { + .name = "alias_pix", + .long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ALIAS_PIX, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, +}; diff --git a/libavcodec/aliaspixenc.c b/libavcodec/aliaspixenc.c new file mode 100644 index 000000000..1fcea0841 --- /dev/null +++ b/libavcodec/aliaspixenc.c @@ -0,0 +1,134 @@ +/* + * Alias PIX image encoder + * Copyright (C) 2014 Vittorio Giovara + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#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; + + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + avctx->coded_frame->key_frame = 1; + + width = avctx->width; + height = avctx->height; + + if (width > 65535 || height > 65535 || + width * height >= INT_MAX / 4 - ALIAS_HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n", width, height); + return AVERROR_INVALIDDATA; + } + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_GRAY8: + bits_pixel = 8; + break; + case AV_PIX_FMT_BGR24: + bits_pixel = 24; + break; + default: + return AVERROR(EINVAL); + } + + length = ALIAS_HEADER_SIZE + 4 * width * height; // max possible + if ((ret = ff_alloc_packet(pkt, length)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", length); + return ret; + } + + buf = pkt->data; + + /* Encode header. */ + bytestream_put_be16(&buf, width); + bytestream_put_be16(&buf, height); + bytestream_put_be32(&buf, 0); /* X, Y offset */ + bytestream_put_be16(&buf, bits_pixel); + + for (j = 0; j < height; j++) { + in_buf = frame->data[0] + frame->linesize[0] * j; + for (i = 0; i < width; ) { + int count = 0; + int pixel; + + if (avctx->pix_fmt == AV_PIX_FMT_GRAY8) { + pixel = *in_buf; + while (count < 255 && count + i < width && pixel == *in_buf) { + count++; + in_buf++; + } + bytestream_put_byte(&buf, count); + bytestream_put_byte(&buf, pixel); + } else { /* AV_PIX_FMT_BGR24 */ + pixel = AV_RB24(in_buf); + while (count < 255 && count + i < width && + pixel == AV_RB24(in_buf)) { + count++; + in_buf += 3; + } + bytestream_put_byte(&buf, count); + bytestream_put_be24(&buf, pixel); + } + i += count; + } + } + + /* Total length */ + av_shrink_packet(pkt, buf - pkt->data); + 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; +} + +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 715837ec3..7650543ac 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -79,6 +79,7 @@ void avcodec_register_all(void) REGISTER_HWACCEL(H264_DXVA2, h264_dxva2); 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(MPEG1_XVMC, mpeg1_xvmc); REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau); @@ -100,6 +101,7 @@ void avcodec_register_all(void) REGISTER_ENCODER(A64MULTI5, a64multi5); REGISTER_DECODER(AASC, aasc); REGISTER_DECODER(AIC, aic); + REGISTER_ENCDEC (ALIAS_PIX, alias_pix); REGISTER_ENCDEC (AMV, amv); REGISTER_DECODER(ANM, anm); REGISTER_DECODER(ANSI, ansi); @@ -292,6 +294,7 @@ void avcodec_register_all(void) REGISTER_DECODER(VP6, vp6); REGISTER_DECODER(VP6A, vp6a); REGISTER_DECODER(VP6F, vp6f); + REGISTER_DECODER(VP7, vp7); REGISTER_DECODER(VP8, vp8); REGISTER_DECODER(VP9, vp9); REGISTER_DECODER(VQA, vqa); @@ -321,7 +324,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (AAC, aac); REGISTER_DECODER(AAC_LATM, aac_latm); REGISTER_ENCDEC (AC3, ac3); - REGISTER_ENCODER(AC3_FIXED, ac3_fixed); + REGISTER_ENCDEC (AC3_FIXED, ac3_fixed); REGISTER_ENCDEC (ALAC, alac); REGISTER_DECODER(ALS, als); REGISTER_DECODER(AMRNB, amrnb); @@ -335,6 +338,10 @@ void avcodec_register_all(void) REGISTER_DECODER(BMV_AUDIO, bmv_audio); REGISTER_DECODER(COOK, cook); REGISTER_ENCDEC (DCA, dca); + REGISTER_DECODER(DSD_LSBF, dsd_lsbf); + REGISTER_DECODER(DSD_MSBF, dsd_msbf); + REGISTER_DECODER(DSD_LSBF_PLANAR, dsd_lsbf_planar); + REGISTER_DECODER(DSD_MSBF_PLANAR, dsd_msbf_planar); REGISTER_DECODER(DSICINAUDIO, dsicinaudio); REGISTER_ENCDEC (EAC3, eac3); REGISTER_DECODER(EVRC, evrc); @@ -364,6 +371,8 @@ void avcodec_register_all(void) REGISTER_DECODER(MPC7, mpc7); REGISTER_DECODER(MPC8, mpc8); REGISTER_ENCDEC (NELLYMOSER, nellymoser); + REGISTER_DECODER(ON2AVC, on2avc); + REGISTER_DECODER(OPUS, opus); REGISTER_DECODER(PAF_AUDIO, paf_audio); REGISTER_DECODER(QCELP, qcelp); REGISTER_DECODER(QDM2, qdm2); @@ -462,6 +471,7 @@ void avcodec_register_all(void) REGISTER_DECODER(ADPCM_SBPRO_4, adpcm_sbpro_4); REGISTER_ENCDEC (ADPCM_SWF, adpcm_swf); REGISTER_DECODER(ADPCM_THP, adpcm_thp); + REGISTER_DECODER(ADPCM_VIMA, adpcm_vima); REGISTER_DECODER(ADPCM_XA, adpcm_xa); REGISTER_ENCDEC (ADPCM_YAMAHA, adpcm_yamaha); REGISTER_DECODER(VIMA, vima); @@ -485,7 +495,7 @@ void avcodec_register_all(void) REGISTER_DECODER(SUBVIEWER1, subviewer1); REGISTER_DECODER(TEXT, text); REGISTER_DECODER(VPLAYER, vplayer); - REGISTER_DECODER(WEBVTT, webvtt); + REGISTER_ENCDEC (WEBVTT, webvtt); REGISTER_ENCDEC (XSUB, xsub); /* external libraries */ @@ -553,6 +563,7 @@ void avcodec_register_all(void) REGISTER_PARSER(MPEG4VIDEO, mpeg4video); REGISTER_PARSER(MPEGAUDIO, mpegaudio); REGISTER_PARSER(MPEGVIDEO, mpegvideo); + REGISTER_PARSER(OPUS, opus); REGISTER_PARSER(PNG, png); REGISTER_PARSER(PNM, pnm); REGISTER_PARSER(RV30, rv30); diff --git a/libavcodec/alpha/Makefile b/libavcodec/alpha/Makefile index 6f2213716..42cabfe49 100644 --- a/libavcodec/alpha/Makefile +++ b/libavcodec/alpha/Makefile @@ -1,9 +1,11 @@ -OBJS += alpha/dsputil_alpha.o \ - alpha/dsputil_alpha_asm.o \ - alpha/motion_est_alpha.o \ - alpha/motion_est_mvi_asm.o \ - alpha/simple_idct_alpha.o \ - +OBJS-$(CONFIG_BLOCKDSP) += alpha/blockdsp_alpha.o +OBJS-$(CONFIG_DSPUTIL) += alpha/dsputil_alpha.o \ + alpha/motion_est_alpha.o \ + alpha/motion_est_mvi_asm.o OBJS-$(CONFIG_HPELDSP) += alpha/hpeldsp_alpha.o \ alpha/hpeldsp_alpha_asm.o +OBJS-$(CONFIG_IDCTDSP) += alpha/idctdsp_alpha.o \ + alpha/idctdsp_alpha_asm.o \ + alpha/simple_idct_alpha.o OBJS-$(CONFIG_MPEGVIDEO) += alpha/mpegvideo_alpha.o +OBJS-$(CONFIG_PIXBLOCKDSP) += alpha/pixblockdsp_alpha.o diff --git a/libavcodec/alpha/blockdsp_alpha.c b/libavcodec/alpha/blockdsp_alpha.c new file mode 100644 index 000000000..ded439d84 --- /dev/null +++ b/libavcodec/alpha/blockdsp_alpha.c @@ -0,0 +1,51 @@ +/* + * Alpha optimised block operations + * Copyright (c) 2002 Falk Hueffner + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavcodec/blockdsp.h" +#include "asm.h" + +static void clear_blocks_axp(int16_t *blocks) { + uint64_t *p = (uint64_t *) blocks; + int n = sizeof(int16_t) * 6 * 64; + + do { + p[0] = 0; + p[1] = 0; + p[2] = 0; + p[3] = 0; + p[4] = 0; + p[5] = 0; + p[6] = 0; + p[7] = 0; + p += 8; + n -= 8 * 8; + } while (n); +} + +av_cold void ff_blockdsp_init_alpha(BlockDSPContext *c, unsigned high_bit_depth) +{ + if (!high_bit_depth) { + c->clear_blocks = clear_blocks_axp; + } +} diff --git a/libavcodec/alpha/dsputil_alpha.c b/libavcodec/alpha/dsputil_alpha.c index 03ba0a888..d99a74bec 100644 --- a/libavcodec/alpha/dsputil_alpha.c +++ b/libavcodec/alpha/dsputil_alpha.c @@ -24,11 +24,6 @@ #include "dsputil_alpha.h" #include "asm.h" -void (*put_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels, - int line_size); -void (*add_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels, - int line_size); - #if 0 /* These functions were the base for the optimized assembler routines, and remain here for documentation purposes. */ @@ -101,40 +96,10 @@ void add_pixels_clamped_mvi(const int16_t *block, uint8_t *pixels, } #endif -static void clear_blocks_axp(int16_t *blocks) { - uint64_t *p = (uint64_t *) blocks; - int n = sizeof(int16_t) * 6 * 64; - - do { - p[0] = 0; - p[1] = 0; - p[2] = 0; - p[3] = 0; - p[4] = 0; - p[5] = 0; - p[6] = 0; - p[7] = 0; - p += 8; - n -= 8 * 8; - } while (n); -} - av_cold void ff_dsputil_init_alpha(DSPContext *c, AVCodecContext *avctx) { - const int high_bit_depth = avctx->bits_per_raw_sample > 8; - - if (!high_bit_depth) { - c->clear_blocks = clear_blocks_axp; - } - /* amask clears all bits that correspond to present features. */ if (amask(AMASK_MVI) == 0) { - c->put_pixels_clamped = put_pixels_clamped_mvi_asm; - c->add_pixels_clamped = add_pixels_clamped_mvi_asm; - - if (!high_bit_depth) - c->get_pixels = get_pixels_mvi; - c->diff_pixels = diff_pixels_mvi; c->sad[0] = pix_abs16x16_mvi_asm; c->sad[1] = pix_abs8x8_mvi; c->pix_abs[0][0] = pix_abs16x16_mvi_asm; @@ -144,14 +109,4 @@ av_cold void ff_dsputil_init_alpha(DSPContext *c, AVCodecContext *avctx) c->pix_abs[0][3] = pix_abs16x16_xy2_mvi; } - put_pixels_clamped_axp_p = c->put_pixels_clamped; - add_pixels_clamped_axp_p = c->add_pixels_clamped; - - if (!avctx->lowres && avctx->bits_per_raw_sample <= 8 && - (avctx->idct_algo == FF_IDCT_AUTO || - avctx->idct_algo == FF_IDCT_SIMPLEALPHA)) { - c->idct_put = ff_simple_idct_put_axp; - c->idct_add = ff_simple_idct_add_axp; - c->idct = ff_simple_idct_axp; - } } diff --git a/libavcodec/alpha/dsputil_alpha.h b/libavcodec/alpha/dsputil_alpha.h index 828cd167c..a48765f9f 100644 --- a/libavcodec/alpha/dsputil_alpha.h +++ b/libavcodec/alpha/dsputil_alpha.h @@ -22,23 +22,6 @@ #include #include -void ff_simple_idct_axp(int16_t *block); -void ff_simple_idct_put_axp(uint8_t *dest, int line_size, int16_t *block); -void ff_simple_idct_add_axp(uint8_t *dest, int line_size, int16_t *block); - -void put_pixels_clamped_mvi_asm(const int16_t *block, uint8_t *pixels, - int line_size); -void add_pixels_clamped_mvi_asm(const int16_t *block, uint8_t *pixels, - int line_size); -extern void (*put_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels, - int line_size); -extern void (*add_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels, - int line_size); - -void get_pixels_mvi(int16_t *restrict block, - const uint8_t *restrict pixels, int line_size); -void diff_pixels_mvi(int16_t *block, const uint8_t *s1, const uint8_t *s2, - int stride); int pix_abs8x8_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); int pix_abs16x16_mvi_asm(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); int pix_abs16x16_x2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); diff --git a/libavcodec/alpha/idctdsp_alpha.c b/libavcodec/alpha/idctdsp_alpha.c new file mode 100644 index 000000000..73f48210c --- /dev/null +++ b/libavcodec/alpha/idctdsp_alpha.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2002 Falk Hueffner + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavcodec/idctdsp.h" +#include "idctdsp_alpha.h" +#include "asm.h" + +void put_pixels_clamped_mvi_asm(const int16_t *block, uint8_t *pixels, + int line_size); +void add_pixels_clamped_mvi_asm(const int16_t *block, uint8_t *pixels, + int line_size); + +void (*put_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels, + int line_size); +void (*add_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels, + int line_size); + +av_cold void ff_idctdsp_init_alpha(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) +{ + /* amask clears all bits that correspond to present features. */ + if (amask(AMASK_MVI) == 0) { + c->put_pixels_clamped = put_pixels_clamped_mvi_asm; + c->add_pixels_clamped = add_pixels_clamped_mvi_asm; + } + + put_pixels_clamped_axp_p = c->put_pixels_clamped; + add_pixels_clamped_axp_p = c->add_pixels_clamped; + + if (!high_bit_depth && !avctx->lowres && + (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_SIMPLEALPHA)) { + c->idct_put = ff_simple_idct_put_axp; + c->idct_add = ff_simple_idct_add_axp; + c->idct = ff_simple_idct_axp; + } +} diff --git a/libavcodec/alpha/idctdsp_alpha.h b/libavcodec/alpha/idctdsp_alpha.h new file mode 100644 index 000000000..e52cd8004 --- /dev/null +++ b/libavcodec/alpha/idctdsp_alpha.h @@ -0,0 +1,34 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_ALPHA_IDCTDSP_ALPHA_H +#define AVCODEC_ALPHA_IDCTDSP_ALPHA_H + +#include +#include + +extern void (*put_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels, + int line_size); +extern void (*add_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels, + int line_size); + +void ff_simple_idct_axp(int16_t *block); +void ff_simple_idct_put_axp(uint8_t *dest, int line_size, int16_t *block); +void ff_simple_idct_add_axp(uint8_t *dest, int line_size, int16_t *block); + +#endif /* AVCODEC_ALPHA_IDCTDSP_ALPHA_H */ diff --git a/libavcodec/alpha/dsputil_alpha_asm.S b/libavcodec/alpha/idctdsp_alpha_asm.S similarity index 99% rename from libavcodec/alpha/dsputil_alpha_asm.S rename to libavcodec/alpha/idctdsp_alpha_asm.S index d801bcf5c..e3a8364a4 100644 --- a/libavcodec/alpha/dsputil_alpha_asm.S +++ b/libavcodec/alpha/idctdsp_alpha_asm.S @@ -1,5 +1,5 @@ /* - * Alpha optimized DSP utils + * Alpha optimized IDCT-related routines * Copyright (c) 2002 Falk Hueffner * * This file is part of FFmpeg. diff --git a/libavcodec/alpha/motion_est_alpha.c b/libavcodec/alpha/motion_est_alpha.c index a7c33e490..246b4a759 100644 --- a/libavcodec/alpha/motion_est_alpha.c +++ b/libavcodec/alpha/motion_est_alpha.c @@ -22,51 +22,6 @@ #include "dsputil_alpha.h" #include "asm.h" -void get_pixels_mvi(int16_t *restrict block, - const uint8_t *restrict pixels, int line_size) -{ - int h = 8; - - do { - uint64_t p; - - p = ldq(pixels); - stq(unpkbw(p), block); - stq(unpkbw(p >> 32), block + 4); - - pixels += line_size; - block += 8; - } while (--h); -} - -void diff_pixels_mvi(int16_t *block, const uint8_t *s1, const uint8_t *s2, - int stride) { - int h = 8; - uint64_t mask = 0x4040; - - mask |= mask << 16; - mask |= mask << 32; - do { - uint64_t x, y, c, d, a; - uint64_t signs; - - x = ldq(s1); - y = ldq(s2); - c = cmpbge(x, y); - d = x - y; - a = zap(mask, c); /* We use 0x4040404040404040 here... */ - d += 4 * a; /* ...so we can use s4addq here. */ - signs = zap(-1, c); - - stq(unpkbw(d) | (unpkbw(signs) << 8), block); - stq(unpkbw(d >> 32) | (unpkbw(signs >> 32) << 8), block + 4); - - s1 += stride; - s2 += stride; - block += 8; - } while (--h); -} - static inline uint64_t avg2(uint64_t a, uint64_t b) { return (a | b) - (((a ^ b) & BYTE_VEC(0xfe)) >> 1); diff --git a/libavcodec/alpha/pixblockdsp_alpha.c b/libavcodec/alpha/pixblockdsp_alpha.c new file mode 100644 index 000000000..c9295e671 --- /dev/null +++ b/libavcodec/alpha/pixblockdsp_alpha.c @@ -0,0 +1,79 @@ +/* + * SIMD-optimized pixel operations + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavcodec/dsputil.h" +#include "libavcodec/pixblockdsp.h" +#include "asm.h" + +static void get_pixels_mvi(int16_t *restrict block, + const uint8_t *restrict pixels, int line_size) +{ + int h = 8; + + do { + uint64_t p; + + p = ldq(pixels); + stq(unpkbw(p), block); + stq(unpkbw(p >> 32), block + 4); + + pixels += line_size; + block += 8; + } while (--h); +} + +static void diff_pixels_mvi(int16_t *block, const uint8_t *s1, const uint8_t *s2, + int stride) { + int h = 8; + uint64_t mask = 0x4040; + + mask |= mask << 16; + mask |= mask << 32; + do { + uint64_t x, y, c, d, a; + uint64_t signs; + + x = ldq(s1); + y = ldq(s2); + c = cmpbge(x, y); + d = x - y; + a = zap(mask, c); /* We use 0x4040404040404040 here... */ + d += 4 * a; /* ...so we can use s4addq here. */ + signs = zap(-1, c); + + stq(unpkbw(d) | (unpkbw(signs) << 8), block); + stq(unpkbw(d >> 32) | (unpkbw(signs >> 32) << 8), block + 4); + + s1 += stride; + s2 += stride; + block += 8; + } while (--h); +} + +av_cold void ff_pixblockdsp_init_alpha(PixblockDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) +{ + if (amask(AMASK_MVI) == 0) { + if (!high_bit_depth) + c->get_pixels = get_pixels_mvi; + c->diff_pixels = diff_pixels_mvi; + } +} diff --git a/libavcodec/alpha/simple_idct_alpha.c b/libavcodec/alpha/simple_idct_alpha.c index 3bd1b336f..04be0cef0 100644 --- a/libavcodec/alpha/simple_idct_alpha.c +++ b/libavcodec/alpha/simple_idct_alpha.c @@ -26,7 +26,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "dsputil_alpha.h" +#include "idctdsp_alpha.h" #include "asm.h" // cos(i * M_PI / 16) * sqrt(2) * (1 << 14) diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c index 89cc8a623..cfece4428 100644 --- a/libavcodec/alsdec.c +++ b/libavcodec/alsdec.c @@ -25,13 +25,15 @@ * @author Thilo Borgmann */ +#include + #include "avcodec.h" #include "get_bits.h" #include "unary.h" #include "mpeg4audio.h" #include "bytestream.h" #include "bgmc.h" -#include "dsputil.h" +#include "bswapdsp.h" #include "internal.h" #include "libavutil/samplefmt.h" #include "libavutil/crc.h" @@ -190,7 +192,7 @@ typedef struct { AVCodecContext *avctx; ALSSpecificConfig sconf; GetBitContext gb; - DSPContext dsp; + BswapDSPContext bdsp; const AVCRC *crc_table; uint32_t crc_org; ///< CRC value of the original input data uint32_t crc; ///< CRC value calculated from decoded data @@ -722,7 +724,9 @@ static int read_var_block_data(ALSDecContext *ctx, ALSBlockData *bd) int offset = parcor_rice_table[sconf->coef_table][k][0]; quant_cof[k] = decode_rice(gb, rice_param) + offset; if (quant_cof[k] < -64 || quant_cof[k] > 63) { - av_log(avctx, AV_LOG_ERROR, "quant_cof %d is out of range.\n", quant_cof[k]); + av_log(avctx, AV_LOG_ERROR, + "quant_cof %"PRIu32" is out of range.\n", + quant_cof[k]); return AVERROR_INVALIDDATA; } } @@ -1397,7 +1401,8 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) bd.block_length = div_blocks[b]; if (bd.block_length <= 0) { av_log(ctx->avctx, AV_LOG_WARNING, - "Invalid block length %d in channel data!\n", bd.block_length); + "Invalid block length %u in channel data!\n", + bd.block_length); continue; } @@ -1555,9 +1560,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, sample++) *dest++ = av_bswap16(src[sample]); } else { - ctx->dsp.bswap_buf((uint32_t*)ctx->crc_buffer, - (uint32_t *)frame->data[0], - ctx->cur_frame_length * avctx->channels); + ctx->bdsp.bswap_buf((uint32_t *) ctx->crc_buffer, + (uint32_t *) frame->data[0], + ctx->cur_frame_length * avctx->channels); } crc_source = ctx->crc_buffer; } else { @@ -1775,7 +1780,7 @@ static av_cold int decode_init(AVCodecContext *avctx) } } - ff_dsputil_init(&ctx->dsp, avctx); + ff_bswapdsp_init(&ctx->bdsp); return 0; diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c index 58072d49b..383b7fe66 100644 --- a/libavcodec/apedec.c +++ b/libavcodec/apedec.c @@ -20,11 +20,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "libavutil/opt.h" +#include "lossless_audiodsp.h" #include "avcodec.h" -#include "dsputil.h" +#include "bswapdsp.h" #include "bytestream.h" #include "internal.h" #include "get_bits.h" @@ -133,7 +136,8 @@ typedef struct APEPredictor { typedef struct APEContext { AVClass *class; ///< class for AVOptions AVCodecContext *avctx; - DSPContext dsp; + BswapDSPContext bdsp; + LLAudDSPContext adsp; int channels; int samples; ///< samples left to decode in current frame int bps; @@ -193,8 +197,6 @@ static void predictor_decode_stereo_3930(APEContext *ctx, int count); static void predictor_decode_mono_3950(APEContext *ctx, int count); static void predictor_decode_stereo_3950(APEContext *ctx, int count); -// TODO: dsputilize - static av_cold int ape_decode_close(AVCodecContext *avctx) { APEContext *s = avctx->priv_data; @@ -291,7 +293,8 @@ static av_cold int ape_decode_init(AVCodecContext *avctx) s->predictor_decode_stereo = predictor_decode_stereo_3950; } - ff_dsputil_init(&s->dsp, avctx); + ff_bswapdsp_init(&s->bdsp); + ff_llauddsp_init(&s->adsp); avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; return 0; @@ -527,7 +530,7 @@ static inline int ape_decode_value_3900(APEContext *ctx, APERice *rice) return AVERROR_INVALIDDATA; } x = range_decode_bits(ctx, tmpk); - } else if (tmpk <= 32) { + } else if (tmpk <= 31) { x = range_decode_bits(ctx, 16); x |= (range_decode_bits(ctx, tmpk - 16) << 16); } else { @@ -910,7 +913,7 @@ static void long_filter_high_3800(int32_t *buffer, int order, int shift, sign = APESIGN(buffer[i]); for (j = 0; j < order; j++) { dotprod += delay[j] * coeffs[j]; - coeffs[j] -= (((delay[j] >> 30) & 2) - 1) * sign; + coeffs[j] += ((delay[j] >> 31) | 1) * sign; } buffer[i] -= dotprod >> shift; for (j = 0; j < order - 1; j++) @@ -923,16 +926,14 @@ static void long_filter_ehigh_3830(int32_t *buffer, int length) { int i, j; int32_t dotprod, sign; - int32_t coeffs[8], delay[8]; + int32_t coeffs[8] = { 0 }, delay[8] = { 0 }; - memset(coeffs, 0, sizeof(coeffs)); - memset(delay, 0, sizeof(delay)); for (i = 0; i < length; i++) { dotprod = 0; sign = APESIGN(buffer[i]); for (j = 7; j >= 0; j--) { dotprod += delay[j] * coeffs[j]; - coeffs[j] -= (((delay[j] >> 30) & 2) - 1) * sign; + coeffs[j] += ((delay[j] >> 31) | 1) * sign; } for (j = 7; j > 0; j--) delay[j] = delay[j - 1]; @@ -1273,9 +1274,10 @@ static void do_apply_filter(APEContext *ctx, int version, APEFilter *f, while (count--) { /* round fixedpoint scalar product */ - res = ctx->dsp.scalarproduct_and_madd_int16(f->coeffs, f->delay - order, - f->adaptcoeffs - order, - order, APESIGN(*data)); + res = ctx->adsp.scalarproduct_and_madd_int16(f->coeffs, + f->delay - order, + f->adaptcoeffs - order, + order, APESIGN(*data)); res = (res + (1 << (fracbits - 1))) >> fracbits; res += *data; *data++ = res; @@ -1441,7 +1443,8 @@ static int ape_decode_frame(AVCodecContext *avctx, void *data, av_fast_padded_malloc(&s->data, &s->data_size, buf_size); if (!s->data) return AVERROR(ENOMEM); - s->dsp.bswap_buf((uint32_t*)s->data, (const uint32_t*)buf, buf_size >> 2); + s->bdsp.bswap_buf((uint32_t *) s->data, (const uint32_t *) buf, + buf_size >> 2); memset(s->data + (buf_size & ~3), 0, buf_size & 3); s->ptr = s->data; s->data_end = s->data + buf_size; @@ -1469,7 +1472,8 @@ static int ape_decode_frame(AVCodecContext *avctx, void *data, } if (!nblocks || nblocks > INT_MAX) { - av_log(avctx, AV_LOG_ERROR, "Invalid sample count: %u.\n", nblocks); + av_log(avctx, AV_LOG_ERROR, "Invalid sample count: %"PRIu32".\n", + nblocks); return AVERROR_INVALIDDATA; } s->samples = nblocks; diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile index a8446b253..6b80de8a2 100644 --- a/libavcodec/arm/Makefile +++ b/libavcodec/arm/Makefile @@ -2,78 +2,97 @@ ARCH_HEADERS = mathops.h OBJS += arm/fmtconvert_init_arm.o -OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_init_arm.o \ - arm/sbrdsp_init_arm.o OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_init_arm.o \ arm/ac3dsp_arm.o -OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_init_arm.o -OBJS-$(CONFIG_DSPUTIL) += arm/dsputil_init_arm.o \ - arm/dsputil_arm.o \ - arm/jrevdct_arm.o \ - arm/simple_idct_arm.o +OBJS-$(CONFIG_AUDIODSP) += arm/audiodsp_init_arm.o +OBJS-$(CONFIG_BLOCKDSP) += arm/blockdsp_init_arm.o +OBJS-$(CONFIG_DSPUTIL) += arm/dsputil_init_arm.o OBJS-$(CONFIG_FFT) += arm/fft_init_arm.o \ arm/fft_fixed_init_arm.o -OBJS-$(CONFIG_FLAC_DECODER) += arm/flacdsp_init_arm.o \ - arm/flacdsp_arm.o -OBJS-$(CONFIG_FLAC_ENCODER) += arm/flacdsp_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 OBJS-$(CONFIG_H264QPEL) += arm/h264qpel_init_arm.o OBJS-$(CONFIG_HPELDSP) += arm/hpeldsp_init_arm.o \ arm/hpeldsp_arm.o +OBJS-$(CONFIG_IDCTDSP) += arm/idctdsp_init_arm.o \ + arm/idctdsp_arm.o \ + arm/jrevdct_arm.o \ + arm/simple_idct_arm.o +OBJS-$(CONFIG_LLAUDDSP) += arm/lossless_audiodsp_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_VIDEODSP) += arm/videodsp_init_arm.o +OBJS-$(CONFIG_VP3DSP) += arm/vp3dsp_init_arm.o + +OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_init_arm.o \ + arm/sbrdsp_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_FLAC_ENCODER) += arm/flacdsp_init_arm.o +OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_init_arm.o OBJS-$(CONFIG_VC1_DECODER) += arm/vc1dsp_init_arm.o OBJS-$(CONFIG_VORBIS_DECODER) += arm/vorbisdsp_init_arm.o -OBJS-$(CONFIG_VP3DSP) += arm/vp3dsp_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 -OBJS-$(CONFIG_VIDEODSP) += arm/videodsp_init_arm.o \ -ARMV5TE-OBJS-$(CONFIG_DSPUTIL) += arm/dsputil_init_armv5te.o \ +ARMV5TE-OBJS-$(CONFIG_IDCTDSP) += arm/idctdsp_init_armv5te.o \ arm/simple_idct_armv5te.o ARMV5TE-OBJS-$(CONFIG_MPEGVIDEO) += arm/mpegvideo_armv5te.o \ arm/mpegvideo_armv5te_s.o ARMV5TE-OBJS-$(CONFIG_VIDEODSP) += arm/videodsp_init_armv5te.o \ arm/videodsp_armv5te.o -ARMV6-OBJS-$(CONFIG_DSPUTIL) += arm/dsputil_init_armv6.o \ - arm/dsputil_armv6.o \ - arm/simple_idct_armv6.o \ +ARMV5TE-OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_armv5te.o ARMV6-OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_armv6.o -ARMV6-OBJS-$(CONFIG_H264DSP) += arm/h264dsp_armv6.o +ARMV6-OBJS-$(CONFIG_DSPUTIL) += arm/dsputil_init_armv6.o \ + arm/dsputil_armv6.o +ARMV6-OBJS-$(CONFIG_H264DSP) += arm/startcode_armv6.o ARMV6-OBJS-$(CONFIG_HPELDSP) += arm/hpeldsp_init_armv6.o \ arm/hpeldsp_armv6.o +ARMV6-OBJS-$(CONFIG_IDCTDSP) += arm/idctdsp_init_armv6.o \ + arm/idctdsp_armv6.o \ + arm/simple_idct_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 + +ARMV6-OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_armv6.o +ARMV6-OBJS-$(CONFIG_VC1_DECODER) += arm/startcode_armv6.o +ARMV6-OBJS-$(CONFIG_VC1_PARSER) += 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 \ arm/vp8dsp_init_armv6.o \ arm/vp8dsp_armv6.o VFP-OBJS += arm/fmtconvert_vfp.o -VFP-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_vfp.o \ - arm/synth_filter_vfp.o VFP-OBJS-$(CONFIG_FFT) += arm/fft_vfp.o VFP-OBJS-$(CONFIG_MDCT) += arm/mdct_vfp.o VFP-OBJS-$(HAVE_ARMV6) += arm/fmtconvert_vfp_armv6.o +VFP-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_vfp.o \ + arm/synth_filter_vfp.o + NEON-OBJS += arm/fmtconvert_neon.o NEON-OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_neon.o -NEON-OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_neon.o \ - arm/sbrdsp_neon.o -NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_neon.o \ - arm/synth_filter_neon.o -NEON-OBJS-$(CONFIG_DSPUTIL) += arm/dsputil_init_neon.o \ - arm/dsputil_neon.o \ - arm/int_neon.o \ - arm/simple_idct_neon.o +NEON-OBJS-$(CONFIG_AUDIODSP) += arm/audiodsp_init_neon.o \ + arm/audiodsp_neon.o \ + arm/int_neon.o +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_H264CHROMA) += arm/h264cmc_neon.o @@ -84,17 +103,28 @@ NEON-OBJS-$(CONFIG_H264QPEL) += arm/h264qpel_neon.o \ arm/hpeldsp_neon.o NEON-OBJS-$(CONFIG_HPELDSP) += arm/hpeldsp_init_neon.o \ arm/hpeldsp_neon.o +NEON-OBJS-$(CONFIG_IDCTDSP) += arm/idctdsp_init_neon.o \ + arm/idctdsp_neon.o \ + arm/simple_idct_neon.o 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_VP3DSP) += arm/vp3dsp_neon.o + +NEON-OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_neon.o \ + arm/sbrdsp_neon.o +NEON-OBJS-$(CONFIG_LLAUDDSP) += arm/lossless_audiodsp_neon.o +NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_neon.o \ + arm/synth_filter_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_VP3DSP) += arm/vp3dsp_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/asm-offsets.h b/libavcodec/arm/asm-offsets.h index 5cfc5cb10..a2174b0a0 100644 --- a/libavcodec/arm/asm-offsets.h +++ b/libavcodec/arm/asm-offsets.h @@ -21,19 +21,12 @@ #ifndef AVCODEC_ARM_ASM_OFFSETS_H #define AVCODEC_ARM_ASM_OFFSETS_H -#ifndef __ASSEMBLER__ -#include -#define CHK_OFFS(s, m, o) struct check_##o { \ - int x_##o[offsetof(s, m) == o? 1: -1]; \ - } -#endif - /* MpegEncContext */ -#define Y_DC_SCALE 0xa8 -#define C_DC_SCALE 0xac -#define AC_PRED 0xb0 -#define BLOCK_LAST_INDEX 0xb4 -#define H263_AIC 0xe4 -#define INTER_SCANTAB_RASTER_END 0x12c +#define Y_DC_SCALE 0x04 +#define C_DC_SCALE 0x08 +#define AC_PRED 0x0c +#define BLOCK_LAST_INDEX 0x10 +#define H263_AIC 0x40 +#define INTER_SCANTAB_RASTER_END 0x88 #endif /* AVCODEC_ARM_ASM_OFFSETS_H */ diff --git a/libavcodec/sh4/dsputil_sh4.h b/libavcodec/arm/audiodsp_arm.h similarity index 76% rename from libavcodec/sh4/dsputil_sh4.h rename to libavcodec/arm/audiodsp_arm.h index 2ba93549f..213660dae 100644 --- a/libavcodec/sh4/dsputil_sh4.h +++ b/libavcodec/arm/audiodsp_arm.h @@ -16,13 +16,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVCODEC_SH4_DSPUTIL_SH4_H -#define AVCODEC_SH4_DSPUTIL_SH4_H +#ifndef AVCODEC_ARM_AUDIODSP_ARM_H +#define AVCODEC_ARM_AUDIODSP_ARM_H -#include "libavcodec/avcodec.h" -#include "libavcodec/dsputil.h" -#include "libavcodec/hpeldsp.h" +#include "libavcodec/audiodsp.h" -void ff_idct_sh4(int16_t *block); +void ff_audiodsp_init_neon(AudioDSPContext *c); -#endif /* AVCODEC_SH4_DSPUTIL_SH4_H */ +#endif /* AVCODEC_ARM_AUDIODSP_ARM_H */ diff --git a/libavcodec/arm/audiodsp_init_arm.c b/libavcodec/arm/audiodsp_init_arm.c new file mode 100644 index 000000000..74aa52a4e --- /dev/null +++ b/libavcodec/arm/audiodsp_init_arm.c @@ -0,0 +1,33 @@ +/* + * ARM optimized audio functions + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/audiodsp.h" +#include "audiodsp_arm.h" + +av_cold void ff_audiodsp_init_arm(AudioDSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) + ff_audiodsp_init_neon(c); +} diff --git a/libavcodec/arm/audiodsp_init_neon.c b/libavcodec/arm/audiodsp_init_neon.c new file mode 100644 index 000000000..f7bd16248 --- /dev/null +++ b/libavcodec/arm/audiodsp_init_neon.c @@ -0,0 +1,41 @@ +/* + * ARM NEON optimised audio functions + * Copyright (c) 2008 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavcodec/audiodsp.h" +#include "audiodsp_arm.h" + +void ff_vector_clipf_neon(float *dst, const float *src, float min, float max, + int len); +void ff_vector_clip_int32_neon(int32_t *dst, const int32_t *src, int32_t min, + int32_t max, unsigned int len); + +int32_t ff_scalarproduct_int16_neon(const int16_t *v1, const int16_t *v2, int len); + +av_cold void ff_audiodsp_init_neon(AudioDSPContext *c) +{ + c->vector_clip_int32 = ff_vector_clip_int32_neon; + c->vector_clipf = ff_vector_clipf_neon; + + c->scalarproduct_int16 = ff_scalarproduct_int16_neon; +} diff --git a/libavcodec/arm/audiodsp_neon.S b/libavcodec/arm/audiodsp_neon.S new file mode 100644 index 000000000..ab32cef7a --- /dev/null +++ b/libavcodec/arm/audiodsp_neon.S @@ -0,0 +1,64 @@ +/* + * ARM NEON optimised audio functions + * Copyright (c) 2008 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +function ff_vector_clipf_neon, export=1 +VFP vdup.32 q1, d0[1] +VFP vdup.32 q0, d0[0] +NOVFP vdup.32 q0, r2 +NOVFP vdup.32 q1, r3 +NOVFP ldr r2, [sp] + vld1.f32 {q2},[r1,:128]! + vmin.f32 q10, q2, q1 + vld1.f32 {q3},[r1,:128]! + vmin.f32 q11, q3, q1 +1: vmax.f32 q8, q10, q0 + vmax.f32 q9, q11, q0 + subs r2, r2, #8 + beq 2f + vld1.f32 {q2},[r1,:128]! + vmin.f32 q10, q2, q1 + vld1.f32 {q3},[r1,:128]! + vmin.f32 q11, q3, q1 + vst1.f32 {q8},[r0,:128]! + vst1.f32 {q9},[r0,:128]! + b 1b +2: vst1.f32 {q8},[r0,:128]! + vst1.f32 {q9},[r0,:128]! + bx lr +endfunc + +function ff_vector_clip_int32_neon, export=1 + vdup.32 q0, r2 + vdup.32 q1, r3 + ldr r2, [sp] +1: + vld1.32 {q2-q3}, [r1,:128]! + vmin.s32 q2, q2, q1 + vmin.s32 q3, q3, q1 + vmax.s32 q2, q2, q0 + vmax.s32 q3, q3, q0 + vst1.32 {q2-q3}, [r0,:128]! + subs r2, r2, #8 + bgt 1b + bx lr +endfunc diff --git a/libavcodec/sparc/dsputil_vis.h b/libavcodec/arm/blockdsp_arm.h similarity index 70% rename from libavcodec/sparc/dsputil_vis.h rename to libavcodec/arm/blockdsp_arm.h index d7e2e63ab..2688d3625 100644 --- a/libavcodec/sparc/dsputil_vis.h +++ b/libavcodec/arm/blockdsp_arm.h @@ -16,13 +16,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVCODEC_SPARC_DSPUTIL_VIS_H -#define AVCODEC_SPARC_DSPUTIL_VIS_H +#ifndef AVCODEC_ARM_BLOCKDSP_ARM_H +#define AVCODEC_ARM_BLOCKDSP_ARM_H -#include +#include "libavcodec/blockdsp.h" -void ff_simple_idct_put_vis(uint8_t *dest, int line_size, int16_t *data); -void ff_simple_idct_add_vis(uint8_t *dest, int line_size, int16_t *data); -void ff_simple_idct_vis(int16_t *data); +void ff_blockdsp_init_neon(BlockDSPContext *c, unsigned high_bit_depth); -#endif /* AVCODEC_SPARC_DSPUTIL_VIS_H */ +#endif /* AVCODEC_ARM_BLOCKDSP_ARM_H */ diff --git a/libavcodec/arm/blockdsp_init_arm.c b/libavcodec/arm/blockdsp_init_arm.c new file mode 100644 index 000000000..3b86a7109 --- /dev/null +++ b/libavcodec/arm/blockdsp_init_arm.c @@ -0,0 +1,33 @@ +/* + * ARM optimized block operations + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/blockdsp.h" +#include "blockdsp_arm.h" + +av_cold void ff_blockdsp_init_arm(BlockDSPContext *c, unsigned high_bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) + ff_blockdsp_init_neon(c, high_bit_depth); +} diff --git a/libavcodec/arm/blockdsp_init_neon.c b/libavcodec/arm/blockdsp_init_neon.c new file mode 100644 index 000000000..62b51fc78 --- /dev/null +++ b/libavcodec/arm/blockdsp_init_neon.c @@ -0,0 +1,37 @@ +/* + * ARM NEON optimised block operations + * Copyright (c) 2008 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavcodec/blockdsp.h" +#include "blockdsp_arm.h" + +void ff_clear_block_neon(int16_t *block); +void ff_clear_blocks_neon(int16_t *blocks); + +av_cold void ff_blockdsp_init_neon(BlockDSPContext *c, unsigned high_bit_depth) +{ + if (!high_bit_depth) { + c->clear_block = ff_clear_block_neon; + c->clear_blocks = ff_clear_blocks_neon; + } +} diff --git a/libavcodec/arm/blockdsp_neon.S b/libavcodec/arm/blockdsp_neon.S new file mode 100644 index 000000000..9fc63cba5 --- /dev/null +++ b/libavcodec/arm/blockdsp_neon.S @@ -0,0 +1,38 @@ +/* + * ARM NEON optimised block functions + * Copyright (c) 2008 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +function ff_clear_block_neon, export=1 + vmov.i16 q0, #0 + .rept 8 + vst1.16 {q0}, [r0,:128]! + .endr + bx lr +endfunc + +function ff_clear_blocks_neon, export=1 + vmov.i16 q0, #0 + .rept 8*6 + vst1.16 {q0}, [r0,:128]! + .endr + bx lr +endfunc diff --git a/libavcodec/arm/cabac.h b/libavcodec/arm/cabac.h new file mode 100644 index 000000000..fdbf86b45 --- /dev/null +++ b/libavcodec/arm/cabac.h @@ -0,0 +1,108 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_ARM_CABAC_H +#define AVCODEC_ARM_CABAC_H + +#include "config.h" +#if HAVE_ARMV6T2_INLINE + +#include "libavutil/attributes.h" +#include "libavutil/internal.h" +#include "libavcodec/cabac.h" + +#define get_cabac_inline get_cabac_inline_arm +static av_always_inline int get_cabac_inline_arm(CABACContext *c, + uint8_t *const state) +{ + int bit; + void *reg_b, *reg_c, *tmp; + + __asm__ volatile( + "ldrb %[bit] , [%[state]] \n\t" + "add %[r_b] , %[tables] , %[lps_off] \n\t" + "mov %[tmp] , %[range] \n\t" + "and %[range] , %[range] , #0xC0 \n\t" + "add %[r_b] , %[r_b] , %[bit] \n\t" + "ldrb %[range] , [%[r_b], %[range], lsl #1] \n\t" + "add %[r_b] , %[tables] , %[norm_off] \n\t" + "sub %[r_c] , %[tmp] , %[range] \n\t" + "lsl %[tmp] , %[r_c] , #17 \n\t" + "cmp %[tmp] , %[low] \n\t" + "it gt \n\t" + "movgt %[range] , %[r_c] \n\t" + "itt cc \n\t" + "mvncc %[bit] , %[bit] \n\t" + "subcc %[low] , %[low] , %[tmp] \n\t" + "add %[r_c] , %[tables] , %[mlps_off] \n\t" + "ldrb %[tmp] , [%[r_b], %[range]] \n\t" + "ldrb %[r_b] , [%[r_c], %[bit]] \n\t" + "lsl %[low] , %[low] , %[tmp] \n\t" + "lsl %[range] , %[range] , %[tmp] \n\t" + "uxth %[r_c] , %[low] \n\t" + "strb %[r_b] , [%[state]] \n\t" + "tst %[r_c] , %[r_c] \n\t" + "bne 2f \n\t" + "ldr %[r_c] , [%[c], %[byte]] \n\t" +#if UNCHECKED_BITSTREAM_READER + "ldrh %[tmp] , [%[r_c]] \n\t" + "add %[r_c] , %[r_c] , #2 \n\t" + "str %[r_c] , [%[c], %[byte]] \n\t" +#else + "ldr %[r_b] , [%[c], %[end]] \n\t" + "ldrh %[tmp] , [%[r_c]] \n\t" + "cmp %[r_c] , %[r_b] \n\t" + "itt lt \n\t" + "addlt %[r_c] , %[r_c] , #2 \n\t" + "strlt %[r_c] , [%[c], %[byte]] \n\t" +#endif + "sub %[r_c] , %[low] , #1 \n\t" + "add %[r_b] , %[tables] , %[norm_off] \n\t" + "eor %[r_c] , %[low] , %[r_c] \n\t" + "rev %[tmp] , %[tmp] \n\t" + "lsr %[r_c] , %[r_c] , #15 \n\t" + "lsr %[tmp] , %[tmp] , #15 \n\t" + "ldrb %[r_c] , [%[r_b], %[r_c]] \n\t" + "movw %[r_b] , #0xFFFF \n\t" + "sub %[tmp] , %[tmp] , %[r_b] \n\t" + "rsb %[r_c] , %[r_c] , #7 \n\t" + "lsl %[tmp] , %[tmp] , %[r_c] \n\t" + "add %[low] , %[low] , %[tmp] \n\t" + "2: \n\t" + : [bit]"=&r"(bit), + [low]"+&r"(c->low), + [range]"+&r"(c->range), + [r_b]"=&r"(reg_b), + [r_c]"=&r"(reg_c), + [tmp]"=&r"(tmp) + : [c]"r"(c), + [state]"r"(state), + [tables]"r"(ff_h264_cabac_tables), + [byte]"M"(offsetof(CABACContext, bytestream)), + [end]"M"(offsetof(CABACContext, bytestream_end)), + [norm_off]"I"(H264_NORM_SHIFT_OFFSET), + [lps_off]"I"(H264_LPS_RANGE_OFFSET), + [mlps_off]"I"(H264_MLPS_STATE_OFFSET + 128) + : "memory", "cc" + ); + + return bit & 1; +} +#endif /* HAVE_ARMV6T2_INLINE */ + +#endif /* AVCODEC_ARM_CABAC_H */ diff --git a/libavcodec/arm/dsputil_arm.h b/libavcodec/arm/dsputil_arm.h index dfa01ba80..2d258682a 100644 --- a/libavcodec/arm/dsputil_arm.h +++ b/libavcodec/arm/dsputil_arm.h @@ -24,9 +24,6 @@ #include "libavcodec/avcodec.h" #include "libavcodec/dsputil.h" -void ff_dsputil_init_armv5te(DSPContext* c, AVCodecContext *avctx); -void ff_dsputil_init_armv6(DSPContext* c, AVCodecContext *avctx); -void ff_dsputil_init_vfp(DSPContext* c, AVCodecContext *avctx); -void ff_dsputil_init_neon(DSPContext *c, AVCodecContext *avctx); +void ff_dsputil_init_armv6(DSPContext *c, AVCodecContext *avctx); #endif /* AVCODEC_ARM_DSPUTIL_ARM_H */ diff --git a/libavcodec/arm/dsputil_armv6.S b/libavcodec/arm/dsputil_armv6.S index 6ec238b8b..fa5a82301 100644 --- a/libavcodec/arm/dsputil_armv6.S +++ b/libavcodec/arm/dsputil_armv6.S @@ -20,88 +20,6 @@ #include "libavutil/arm/asm.S" -function ff_add_pixels_clamped_armv6, export=1 - push {r4-r8,lr} - mov r3, #8 -1: - ldm r0!, {r4,r5,r12,lr} - ldrd r6, r7, [r1] - pkhbt r8, r4, r5, lsl #16 - pkhtb r5, r5, r4, asr #16 - pkhbt r4, r12, lr, lsl #16 - pkhtb lr, lr, r12, asr #16 - pld [r1, r2] - uxtab16 r8, r8, r6 - uxtab16 r5, r5, r6, ror #8 - uxtab16 r4, r4, r7 - uxtab16 lr, lr, r7, ror #8 - usat16 r8, #8, r8 - usat16 r5, #8, r5 - usat16 r4, #8, r4 - usat16 lr, #8, lr - orr r6, r8, r5, lsl #8 - orr r7, r4, lr, lsl #8 - subs r3, r3, #1 - strd_post r6, r7, r1, r2 - bgt 1b - pop {r4-r8,pc} -endfunc - -function ff_get_pixels_armv6, export=1 - pld [r1, r2] - push {r4-r8, lr} - mov lr, #8 -1: - ldrd_post r4, r5, r1, r2 - subs lr, lr, #1 - uxtb16 r6, r4 - uxtb16 r4, r4, ror #8 - uxtb16 r12, r5 - uxtb16 r8, r5, ror #8 - pld [r1, r2] - pkhbt r5, r6, r4, lsl #16 - pkhtb r6, r4, r6, asr #16 - pkhbt r7, r12, r8, lsl #16 - pkhtb r12, r8, r12, asr #16 - stm r0!, {r5,r6,r7,r12} - bgt 1b - - pop {r4-r8, pc} -endfunc - -function ff_diff_pixels_armv6, export=1 - pld [r1, r3] - pld [r2, r3] - push {r4-r9, lr} - mov lr, #8 -1: - ldrd_post r4, r5, r1, r3 - ldrd_post r6, r7, r2, r3 - uxtb16 r8, r4 - uxtb16 r4, r4, ror #8 - uxtb16 r9, r6 - uxtb16 r6, r6, ror #8 - pld [r1, r3] - ssub16 r9, r8, r9 - ssub16 r6, r4, r6 - uxtb16 r8, r5 - uxtb16 r5, r5, ror #8 - pld [r2, r3] - pkhbt r4, r9, r6, lsl #16 - pkhtb r6, r6, r9, asr #16 - uxtb16 r9, r7 - uxtb16 r7, r7, ror #8 - ssub16 r9, r8, r9 - ssub16 r5, r5, r7 - subs lr, lr, #1 - pkhbt r8, r9, r5, lsl #16 - pkhtb r9, r5, r9, asr #16 - stm r0!, {r4,r6,r8,r9} - bgt 1b - - pop {r4-r9, pc} -endfunc - function ff_pix_abs16_armv6, export=1 ldr r0, [sp] push {r4-r9, lr} @@ -324,58 +242,3 @@ function ff_sse16_armv6, export=1 pop {r4-r9, pc} endfunc - -function ff_pix_norm1_armv6, export=1 - push {r4-r6, lr} - mov r12, #16 - mov lr, #0 -1: - ldm r0, {r2-r5} - uxtb16 r6, r2 - uxtb16 r2, r2, ror #8 - smlad lr, r6, r6, lr - uxtb16 r6, r3 - smlad lr, r2, r2, lr - uxtb16 r3, r3, ror #8 - smlad lr, r6, r6, lr - uxtb16 r6, r4 - smlad lr, r3, r3, lr - uxtb16 r4, r4, ror #8 - smlad lr, r6, r6, lr - uxtb16 r6, r5 - smlad lr, r4, r4, lr - uxtb16 r5, r5, ror #8 - smlad lr, r6, r6, lr - subs r12, r12, #1 - add r0, r0, r1 - smlad lr, r5, r5, lr - bgt 1b - - mov r0, lr - pop {r4-r6, pc} -endfunc - -function ff_pix_sum_armv6, export=1 - push {r4-r7, lr} - mov r12, #16 - mov r2, #0 - mov r3, #0 - mov lr, #0 - ldr r4, [r0] -1: - subs r12, r12, #1 - ldr r5, [r0, #4] - usada8 r2, r4, lr, r2 - ldr r6, [r0, #8] - usada8 r3, r5, lr, r3 - ldr r7, [r0, #12] - usada8 r2, r6, lr, r2 - beq 2f - ldr_pre r4, r0, r1 - usada8 r3, r7, lr, r3 - bgt 1b -2: - usada8 r3, r7, lr, r3 - add r0, r2, r3 - pop {r4-r7, pc} -endfunc diff --git a/libavcodec/arm/dsputil_init_arm.c b/libavcodec/arm/dsputil_init_arm.c index 68991fa9c..7b56dbad3 100644 --- a/libavcodec/arm/dsputil_init_arm.c +++ b/libavcodec/arm/dsputil_init_arm.c @@ -19,68 +19,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/attributes.h" +#include "libavutil/cpu.h" #include "libavutil/arm/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/dsputil.h" #include "dsputil_arm.h" -void ff_j_rev_dct_arm(int16_t *data); -void ff_simple_idct_arm(int16_t *data); - -/* XXX: local hack */ -static void (*ff_put_pixels_clamped)(const int16_t *block, uint8_t *pixels, int line_size); -static void (*ff_add_pixels_clamped)(const int16_t *block, uint8_t *pixels, int line_size); - -void ff_add_pixels_clamped_arm(const int16_t *block, uint8_t *dest, - int line_size); - -/* XXX: those functions should be suppressed ASAP when all IDCTs are - converted */ -static void j_rev_dct_arm_put(uint8_t *dest, int line_size, int16_t *block) -{ - ff_j_rev_dct_arm (block); - ff_put_pixels_clamped(block, dest, line_size); -} -static void j_rev_dct_arm_add(uint8_t *dest, int line_size, int16_t *block) -{ - ff_j_rev_dct_arm (block); - ff_add_pixels_clamped(block, dest, line_size); -} -static void simple_idct_arm_put(uint8_t *dest, int line_size, int16_t *block) -{ - ff_simple_idct_arm (block); - ff_put_pixels_clamped(block, dest, line_size); -} -static void simple_idct_arm_add(uint8_t *dest, int line_size, int16_t *block) -{ - ff_simple_idct_arm (block); - ff_add_pixels_clamped(block, dest, line_size); -} - av_cold void ff_dsputil_init_arm(DSPContext *c, AVCodecContext *avctx) { int cpu_flags = av_get_cpu_flags(); - ff_put_pixels_clamped = c->put_pixels_clamped; - ff_add_pixels_clamped = c->add_pixels_clamped; - - if (!avctx->lowres && avctx->bits_per_raw_sample <= 8) { - if(avctx->idct_algo == FF_IDCT_AUTO || - avctx->idct_algo == FF_IDCT_ARM){ - c->idct_put = j_rev_dct_arm_put; - c->idct_add = j_rev_dct_arm_add; - c->idct = ff_j_rev_dct_arm; - c->idct_permutation_type = FF_LIBMPEG2_IDCT_PERM; - } else if (avctx->idct_algo == FF_IDCT_SIMPLEARM){ - c->idct_put = simple_idct_arm_put; - c->idct_add = simple_idct_arm_add; - c->idct = ff_simple_idct_arm; - c->idct_permutation_type = FF_NO_IDCT_PERM; - } - } - - c->add_pixels_clamped = ff_add_pixels_clamped_arm; - - if (have_armv5te(cpu_flags)) ff_dsputil_init_armv5te(c, avctx); - if (have_armv6(cpu_flags)) ff_dsputil_init_armv6(c, avctx); - if (have_neon(cpu_flags)) ff_dsputil_init_neon(c, avctx); + if (have_armv6(cpu_flags)) + ff_dsputil_init_armv6(c, avctx); } diff --git a/libavcodec/arm/dsputil_init_armv6.c b/libavcodec/arm/dsputil_init_armv6.c index 8f383025a..edd0a64df 100644 --- a/libavcodec/arm/dsputil_init_armv6.c +++ b/libavcodec/arm/dsputil_init_armv6.c @@ -20,55 +20,27 @@ #include +#include "libavutil/attributes.h" #include "libavcodec/avcodec.h" +#include "libavcodec/dsputil.h" +#include "libavcodec/mpegvideo.h" #include "dsputil_arm.h" -void ff_simple_idct_armv6(int16_t *data); -void ff_simple_idct_put_armv6(uint8_t *dest, int line_size, int16_t *data); -void ff_simple_idct_add_armv6(uint8_t *dest, int line_size, int16_t *data); - -void ff_add_pixels_clamped_armv6(const int16_t *block, - uint8_t *restrict pixels, - int line_size); - -void ff_get_pixels_armv6(int16_t *block, const uint8_t *pixels, int stride); -void ff_diff_pixels_armv6(int16_t *block, const uint8_t *s1, - const uint8_t *s2, int stride); - -int ff_pix_abs16_armv6(void *s, uint8_t *blk1, uint8_t *blk2, +int ff_pix_abs16_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2, int line_size, int h); -int ff_pix_abs16_x2_armv6(void *s, uint8_t *blk1, uint8_t *blk2, +int ff_pix_abs16_x2_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2, int line_size, int h); -int ff_pix_abs16_y2_armv6(void *s, uint8_t *blk1, uint8_t *blk2, +int ff_pix_abs16_y2_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2, int line_size, int h); -int ff_pix_abs8_armv6(void *s, uint8_t *blk1, uint8_t *blk2, - int line_size, int h); +int ff_pix_abs8_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2, + int line_size, int h); -int ff_sse16_armv6(void *s, uint8_t *blk1, uint8_t *blk2, +int ff_sse16_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2, int line_size, int h); -int ff_pix_norm1_armv6(uint8_t *pix, int line_size); -int ff_pix_sum_armv6(uint8_t *pix, int line_size); - av_cold void ff_dsputil_init_armv6(DSPContext *c, AVCodecContext *avctx) { - const int high_bit_depth = avctx->bits_per_raw_sample > 8; - - if (!avctx->lowres && avctx->bits_per_raw_sample <= 8 && - (avctx->idct_algo == FF_IDCT_AUTO || - avctx->idct_algo == FF_IDCT_SIMPLEARMV6)) { - c->idct_put = ff_simple_idct_put_armv6; - c->idct_add = ff_simple_idct_add_armv6; - c->idct = ff_simple_idct_armv6; - c->idct_permutation_type = FF_LIBMPEG2_IDCT_PERM; - } - - if (!high_bit_depth) - c->get_pixels = ff_get_pixels_armv6; - c->add_pixels_clamped = ff_add_pixels_clamped_armv6; - c->diff_pixels = ff_diff_pixels_armv6; - c->pix_abs[0][0] = ff_pix_abs16_armv6; c->pix_abs[0][1] = ff_pix_abs16_x2_armv6; c->pix_abs[0][2] = ff_pix_abs16_y2_armv6; @@ -79,7 +51,4 @@ av_cold void ff_dsputil_init_armv6(DSPContext *c, AVCodecContext *avctx) c->sad[1] = ff_pix_abs8_armv6; c->sse[0] = ff_sse16_armv6; - - c->pix_norm1 = ff_pix_norm1_armv6; - c->pix_sum = ff_pix_sum_armv6; } diff --git a/libavcodec/arm/fft_fixed_neon.S b/libavcodec/arm/fft_fixed_neon.S index d4a38a2b9..57a8cfb55 100644 --- a/libavcodec/arm/fft_fixed_neon.S +++ b/libavcodec/arm/fft_fixed_neon.S @@ -122,7 +122,7 @@ endfunc function fft_pass_neon push {r4,lr} - movrel lr, coefs+24 + movrel lr, coefs + 24 vld1.16 {d30}, [lr,:64] lsl r12, r2, #3 vmov d31, d30 diff --git a/libavcodec/arm/h264cmc_neon.S b/libavcodec/arm/h264cmc_neon.S index 0bcae1120..77ed3c0da 100644 --- a/libavcodec/arm/h264cmc_neon.S +++ b/libavcodec/arm/h264cmc_neon.S @@ -96,9 +96,10 @@ T cmp r7, #0 pop {r4-r7, pc} -2: tst r6, r6 - add r12, r12, r6 +2: adds r12, r12, r6 vdup.8 d0, r4 + beq 5f + tst r6, r6 vdup.8 d1, r12 beq 4f @@ -163,6 +164,33 @@ T cmp r7, #0 vst1.8 {d17}, [r0,:64], r2 bgt 4b + pop {r4-r7, pc} + +5: vld1.8 {d4}, [r1], r2 + vld1.8 {d5}, [r1], r2 + pld [r1] + subs r3, r3, #2 + vmull.u8 q8, d4, d0 + vmull.u8 q9, d5, d0 + pld [r1, r2] + .ifc \codec,h264 + vrshrn.u16 d16, q8, #6 + vrshrn.u16 d17, q9, #6 + .else + vadd.u16 q8, q8, q11 + vadd.u16 q9, q9, q11 + vshrn.u16 d16, q8, #6 + vshrn.u16 d17, q9, #6 + .endif + .ifc \type,avg + vld1.8 {d20}, [lr,:64], r2 + vld1.8 {d21}, [lr,:64], r2 + vrhadd.u8 q8, q8, q10 + .endif + vst1.8 {d16}, [r0,:64], r2 + vst1.8 {d17}, [r0,:64], r2 + bgt 5b + pop {r4-r7, pc} endfunc .endm @@ -245,9 +273,10 @@ T cmp r7, #0 pop {r4-r7, pc} -2: tst r6, r6 - add r12, r12, r6 +2: adds r12, r12, r6 vdup.8 d0, r4 + beq 5f + tst r6, r6 vdup.8 d1, r12 vtrn.32 d0, d1 @@ -310,6 +339,29 @@ T cmp r7, #0 vst1.32 {d16[1]}, [r0,:32], r2 bgt 4b + pop {r4-r7, pc} + +5: vld1.32 {d4[0]}, [r1], r2 + vld1.32 {d4[1]}, [r1], r2 + vmull.u8 q8, d4, d0 + subs r3, r3, #2 + pld [r1] + .ifc \codec,h264 + vrshrn.u16 d16, q8, #6 + .else + vadd.u16 q8, q8, q11 + vshrn.u16 d16, q8, #6 + .endif + .ifc \type,avg + vld1.32 {d20[0]}, [lr,:32], r2 + vld1.32 {d20[1]}, [lr,:32], r2 + vrhadd.u8 d16, d16, d20 + .endif + pld [r1] + vst1.32 {d16[0]}, [r0,:32], r2 + vst1.32 {d16[1]}, [r0,:32], r2 + bgt 5b + pop {r4-r7, pc} endfunc .endm diff --git a/libavcodec/arm/h264dsp_init_arm.c b/libavcodec/arm/h264dsp_init_arm.c index a0418fd5c..3999e993a 100644 --- a/libavcodec/arm/h264dsp_init_arm.c +++ b/libavcodec/arm/h264dsp_init_arm.c @@ -24,7 +24,7 @@ #include "libavutil/arm/cpu.h" #include "libavcodec/h264dsp.h" -int ff_h264_find_start_code_candidate_armv6(const uint8_t *buf, int size); +int ff_startcode_find_candidate_armv6(const uint8_t *buf, int size); void ff_h264_v_loop_filter_luma_neon(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0); @@ -108,8 +108,12 @@ av_cold void ff_h264dsp_init_arm(H264DSPContext *c, const int bit_depth, { int cpu_flags = av_get_cpu_flags(); - if (have_armv6(cpu_flags)) - c->h264_find_start_code_candidate = ff_h264_find_start_code_candidate_armv6; + if (have_armv6(cpu_flags) && !(have_vfpv3(cpu_flags) || have_neon(cpu_flags))) { + // This function uses the 'setend' instruction which is deprecated + // on ARMv8. This instruction is serializing on some ARMv7 cores as + // well. Therefore, only use the function on ARMv6. + c->h264_find_start_code_candidate = ff_startcode_find_candidate_armv6; + } if (have_neon(cpu_flags)) h264dsp_init_neon(c, bit_depth, chroma_format_idc); } diff --git a/libavcodec/arm/h264pred_init_arm.c b/libavcodec/arm/h264pred_init_arm.c index 1562f0bcb..6ba7592fe 100644 --- a/libavcodec/arm/h264pred_init_arm.c +++ b/libavcodec/arm/h264pred_init_arm.c @@ -57,10 +57,11 @@ static av_cold void h264_pred_init_neon(H264PredContext *h, int codec_id, if(chroma_format_idc == 1){ h->pred8x8[VERT_PRED8x8 ] = ff_pred8x8_vert_neon; h->pred8x8[HOR_PRED8x8 ] = ff_pred8x8_hor_neon; - if (codec_id != AV_CODEC_ID_VP8) + 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_VP8) { + 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; @@ -77,7 +78,8 @@ static av_cold void h264_pred_init_neon(H264PredContext *h, int codec_id, h->pred16x16[LEFT_DC_PRED8x8] = ff_pred16x16_left_dc_neon; h->pred16x16[TOP_DC_PRED8x8 ] = ff_pred16x16_top_dc_neon; h->pred16x16[DC_128_PRED8x8 ] = ff_pred16x16_128_dc_neon; - if (codec_id != AV_CODEC_ID_SVQ3 && codec_id != AV_CODEC_ID_RV40 && codec_id != AV_CODEC_ID_VP8) + 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; #endif // HAVE_NEON } diff --git a/libavcodec/arm/hpeldsp_arm.S b/libavcodec/arm/hpeldsp_arm.S index 429c3ea02..219f793d9 100644 --- a/libavcodec/arm/hpeldsp_arm.S +++ b/libavcodec/arm/hpeldsp_arm.S @@ -1,5 +1,5 @@ @ -@ ARMv4 optimized DSP utils +@ ARMv4-optimized halfpel functions @ Copyright (c) 2004 AGAWA Koji @ @ This file is part of FFmpeg. diff --git a/libavcodec/arm/hpeldsp_init_arm.c b/libavcodec/arm/hpeldsp_init_arm.c index 2cc2b782b..1977b1379 100644 --- a/libavcodec/arm/hpeldsp_init_arm.c +++ b/libavcodec/arm/hpeldsp_init_arm.c @@ -1,5 +1,5 @@ /* - * ARM optimized DSP utils + * ARM-optimized halfpel functions * Copyright (c) 2001 Lionel Ulmer * * This file is part of FFmpeg. @@ -21,8 +21,7 @@ #include "libavutil/arm/cpu.h" #include "libavutil/attributes.h" -#include "libavcodec/bit_depth_template.c" // for CALL_2X_PIXELS -#include "libavcodec/rnd_avg.h" +#include "libavcodec/pixels.h" #include "hpeldsp_arm.h" void ff_put_pixels8_arm(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); diff --git a/libavcodec/arm/dsputil_arm.S b/libavcodec/arm/idctdsp_arm.S similarity index 99% rename from libavcodec/arm/dsputil_arm.S rename to libavcodec/arm/idctdsp_arm.S index e0a8a2e97..e8333c4b7 100644 --- a/libavcodec/arm/dsputil_arm.S +++ b/libavcodec/arm/idctdsp_arm.S @@ -1,5 +1,5 @@ @ -@ ARMv4 optimized DSP utils +@ ARMv4-optimized IDCT functions @ Copyright (c) 2004 AGAWA Koji @ @ This file is part of FFmpeg. diff --git a/libavcodec/arm/idctdsp_arm.h b/libavcodec/arm/idctdsp_arm.h new file mode 100644 index 000000000..d7bc5cd02 --- /dev/null +++ b/libavcodec/arm/idctdsp_arm.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_ARM_IDCTDSP_ARM_H +#define AVCODEC_ARM_IDCTDSP_ARM_H + +#include "libavcodec/avcodec.h" +#include "libavcodec/idctdsp.h" + +void ff_idctdsp_init_armv5te(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); +void ff_idctdsp_init_armv6(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); +void ff_idctdsp_init_neon(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); + +#endif /* AVCODEC_ARM_IDCTDSP_ARM_H */ diff --git a/libavcodec/arm/idctdsp_armv6.S b/libavcodec/arm/idctdsp_armv6.S new file mode 100644 index 000000000..a6e77d6da --- /dev/null +++ b/libavcodec/arm/idctdsp_armv6.S @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +function ff_add_pixels_clamped_armv6, export=1 + push {r4-r8,lr} + mov r3, #8 +1: + ldm r0!, {r4,r5,r12,lr} + ldrd r6, r7, [r1] + pkhbt r8, r4, r5, lsl #16 + pkhtb r5, r5, r4, asr #16 + pkhbt r4, r12, lr, lsl #16 + pkhtb lr, lr, r12, asr #16 + pld [r1, r2] + uxtab16 r8, r8, r6 + uxtab16 r5, r5, r6, ror #8 + uxtab16 r4, r4, r7 + uxtab16 lr, lr, r7, ror #8 + usat16 r8, #8, r8 + usat16 r5, #8, r5 + usat16 r4, #8, r4 + usat16 lr, #8, lr + orr r6, r8, r5, lsl #8 + orr r7, r4, lr, lsl #8 + subs r3, r3, #1 + strd_post r6, r7, r1, r2 + bgt 1b + pop {r4-r8,pc} +endfunc diff --git a/libavcodec/arm/idctdsp_init_arm.c b/libavcodec/arm/idctdsp_init_arm.c new file mode 100644 index 000000000..cc5e11676 --- /dev/null +++ b/libavcodec/arm/idctdsp_init_arm.c @@ -0,0 +1,98 @@ +/* + * ARM-optimized IDCT functions + * Copyright (c) 2001 Lionel Ulmer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/idctdsp.h" +#include "idctdsp_arm.h" + +void ff_j_rev_dct_arm(int16_t *data); +void ff_simple_idct_arm(int16_t *data); + +/* XXX: local hack */ +static void (*ff_put_pixels_clamped)(const int16_t *block, uint8_t *pixels, int line_size); +static void (*ff_add_pixels_clamped)(const int16_t *block, uint8_t *pixels, int line_size); + +void ff_add_pixels_clamped_arm(const int16_t *block, uint8_t *dest, + int line_size); + +/* XXX: those functions should be suppressed ASAP when all IDCTs are + * converted */ +static void j_rev_dct_arm_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct_arm(block); + ff_put_pixels_clamped(block, dest, line_size); +} + +static void j_rev_dct_arm_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct_arm(block); + ff_add_pixels_clamped(block, dest, line_size); +} + +static void simple_idct_arm_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_simple_idct_arm(block); + ff_put_pixels_clamped(block, dest, line_size); +} + +static void simple_idct_arm_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_simple_idct_arm(block); + ff_add_pixels_clamped(block, dest, line_size); +} + +av_cold void ff_idctdsp_init_arm(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + + ff_put_pixels_clamped = c->put_pixels_clamped; + ff_add_pixels_clamped = c->add_pixels_clamped; + + if (!avctx->lowres && !high_bit_depth) { + if (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_ARM) { + c->idct_put = j_rev_dct_arm_put; + c->idct_add = j_rev_dct_arm_add; + c->idct = ff_j_rev_dct_arm; + c->idct_permutation_type = FF_LIBMPEG2_IDCT_PERM; + } else if (avctx->idct_algo == FF_IDCT_SIMPLEARM) { + c->idct_put = simple_idct_arm_put; + c->idct_add = simple_idct_arm_add; + c->idct = ff_simple_idct_arm; + c->idct_permutation_type = FF_NO_IDCT_PERM; + } + } + + c->add_pixels_clamped = ff_add_pixels_clamped_arm; + + if (have_armv5te(cpu_flags)) + ff_idctdsp_init_armv5te(c, avctx, high_bit_depth); + if (have_armv6(cpu_flags)) + ff_idctdsp_init_armv6(c, avctx, high_bit_depth); + if (have_neon(cpu_flags)) + ff_idctdsp_init_neon(c, avctx, high_bit_depth); +} diff --git a/libavcodec/arm/dsputil_init_armv5te.c b/libavcodec/arm/idctdsp_init_armv5te.c similarity index 78% rename from libavcodec/arm/dsputil_init_armv5te.c rename to libavcodec/arm/idctdsp_init_armv5te.c index 841fbfadc..9ca36879d 100644 --- a/libavcodec/arm/dsputil_init_armv5te.c +++ b/libavcodec/arm/idctdsp_init_armv5te.c @@ -18,16 +18,23 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "dsputil_arm.h" +#include + +#include "libavutil/attributes.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/idctdsp.h" +#include "idctdsp_arm.h" void ff_simple_idct_armv5te(int16_t *data); void ff_simple_idct_put_armv5te(uint8_t *dest, int line_size, int16_t *data); void ff_simple_idct_add_armv5te(uint8_t *dest, int line_size, int16_t *data); -av_cold void ff_dsputil_init_armv5te(DSPContext *c, AVCodecContext *avctx) +av_cold void ff_idctdsp_init_armv5te(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) { - if (!avctx->lowres && avctx->bits_per_raw_sample <= 8 && + if (!avctx->lowres && !high_bit_depth && (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_SIMPLEAUTO || avctx->idct_algo == FF_IDCT_SIMPLEARMV5TE)) { c->idct_put = ff_simple_idct_put_armv5te; c->idct_add = ff_simple_idct_add_armv5te; diff --git a/libavcodec/arm/idctdsp_init_armv6.c b/libavcodec/arm/idctdsp_init_armv6.c new file mode 100644 index 000000000..27ca6cedb --- /dev/null +++ b/libavcodec/arm/idctdsp_init_armv6.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/idctdsp.h" +#include "idctdsp_arm.h" + +void ff_simple_idct_armv6(int16_t *data); +void ff_simple_idct_put_armv6(uint8_t *dest, int line_size, int16_t *data); +void ff_simple_idct_add_armv6(uint8_t *dest, int line_size, int16_t *data); + +void ff_add_pixels_clamped_armv6(const int16_t *block, uint8_t *pixels, + int line_size); + +av_cold void ff_idctdsp_init_armv6(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) +{ + if (!avctx->lowres && !high_bit_depth) { + if (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_SIMPLEARMV6) { + c->idct_put = ff_simple_idct_put_armv6; + c->idct_add = ff_simple_idct_add_armv6; + c->idct = ff_simple_idct_armv6; + c->idct_permutation_type = FF_LIBMPEG2_IDCT_PERM; + } + } + c->add_pixels_clamped = ff_add_pixels_clamped_armv6; +} diff --git a/libavcodec/arm/dsputil_init_neon.c b/libavcodec/arm/idctdsp_init_neon.c similarity index 56% rename from libavcodec/arm/dsputil_init_neon.c rename to libavcodec/arm/idctdsp_init_neon.c index c1f250acb..d8684e701 100644 --- a/libavcodec/arm/dsputil_init_neon.c +++ b/libavcodec/arm/idctdsp_init_neon.c @@ -1,5 +1,5 @@ /* - * ARM NEON optimised DSP functions + * ARM-NEON-optimized IDCT functions * Copyright (c) 2008 Mans Rullgard * * This file is part of FFmpeg. @@ -23,34 +23,23 @@ #include "libavutil/attributes.h" #include "libavcodec/avcodec.h" -#include "dsputil_arm.h" +#include "libavcodec/idctdsp.h" +#include "idctdsp_arm.h" void ff_simple_idct_neon(int16_t *data); void ff_simple_idct_put_neon(uint8_t *dest, int line_size, int16_t *data); void ff_simple_idct_add_neon(uint8_t *dest, int line_size, int16_t *data); -void ff_clear_block_neon(int16_t *block); -void ff_clear_blocks_neon(int16_t *blocks); - void ff_add_pixels_clamped_neon(const int16_t *, uint8_t *, int); void ff_put_pixels_clamped_neon(const int16_t *, uint8_t *, int); void ff_put_signed_pixels_clamped_neon(const int16_t *, uint8_t *, int); -void ff_vector_clipf_neon(float *dst, const float *src, float min, float max, - int len); -void ff_vector_clip_int32_neon(int32_t *dst, const int32_t *src, int32_t min, - int32_t max, unsigned int len); - -int32_t ff_scalarproduct_int16_neon(const int16_t *v1, const int16_t *v2, int len); -int32_t ff_scalarproduct_and_madd_int16_neon(int16_t *v1, const int16_t *v2, - const int16_t *v3, int len, int mul); - -av_cold void ff_dsputil_init_neon(DSPContext *c, AVCodecContext *avctx) +av_cold void ff_idctdsp_init_neon(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) { - const int high_bit_depth = avctx->bits_per_raw_sample > 8; - - if (!avctx->lowres && avctx->bits_per_raw_sample <= 8) { + if (!avctx->lowres && !high_bit_depth) { if (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_SIMPLEAUTO || avctx->idct_algo == FF_IDCT_SIMPLENEON) { c->idct_put = ff_simple_idct_put_neon; c->idct_add = ff_simple_idct_add_neon; @@ -59,18 +48,7 @@ av_cold void ff_dsputil_init_neon(DSPContext *c, AVCodecContext *avctx) } } - if (!high_bit_depth) { - c->clear_block = ff_clear_block_neon; - c->clear_blocks = ff_clear_blocks_neon; - } - - c->add_pixels_clamped = ff_add_pixels_clamped_neon; - c->put_pixels_clamped = ff_put_pixels_clamped_neon; + c->add_pixels_clamped = ff_add_pixels_clamped_neon; + c->put_pixels_clamped = ff_put_pixels_clamped_neon; c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_neon; - - c->vector_clipf = ff_vector_clipf_neon; - c->vector_clip_int32 = ff_vector_clip_int32_neon; - - c->scalarproduct_int16 = ff_scalarproduct_int16_neon; - c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_neon; } diff --git a/libavcodec/arm/dsputil_neon.S b/libavcodec/arm/idctdsp_neon.S similarity index 73% rename from libavcodec/arm/dsputil_neon.S rename to libavcodec/arm/idctdsp_neon.S index 6c8231efa..1911a3346 100644 --- a/libavcodec/arm/dsputil_neon.S +++ b/libavcodec/arm/idctdsp_neon.S @@ -1,5 +1,5 @@ /* - * ARM NEON optimised DSP functions + * ARM-NEON-optimized IDCT functions * Copyright (c) 2008 Mans Rullgard * * This file is part of FFmpeg. @@ -21,22 +21,6 @@ #include "libavutil/arm/asm.S" -function ff_clear_block_neon, export=1 - vmov.i16 q0, #0 - .rept 8 - vst1.16 {q0}, [r0,:128]! - .endr - bx lr -endfunc - -function ff_clear_blocks_neon, export=1 - vmov.i16 q0, #0 - .rept 8*6 - vst1.16 {q0}, [r0,:128]! - .endr - bx lr -endfunc - function ff_put_pixels_clamped_neon, export=1 vld1.16 {d16-d19}, [r0,:128]! vqmovun.s16 d0, q8 @@ -142,45 +126,3 @@ function ff_add_pixels_clamped_neon, export=1 vst1.8 {d6}, [r3,:64], r2 bx lr endfunc - -function ff_vector_clipf_neon, export=1 -VFP vdup.32 q1, d0[1] -VFP vdup.32 q0, d0[0] -NOVFP vdup.32 q0, r2 -NOVFP vdup.32 q1, r3 -NOVFP ldr r2, [sp] - vld1.f32 {q2},[r1,:128]! - vmin.f32 q10, q2, q1 - vld1.f32 {q3},[r1,:128]! - vmin.f32 q11, q3, q1 -1: vmax.f32 q8, q10, q0 - vmax.f32 q9, q11, q0 - subs r2, r2, #8 - beq 2f - vld1.f32 {q2},[r1,:128]! - vmin.f32 q10, q2, q1 - vld1.f32 {q3},[r1,:128]! - vmin.f32 q11, q3, q1 - vst1.f32 {q8},[r0,:128]! - vst1.f32 {q9},[r0,:128]! - b 1b -2: vst1.f32 {q8},[r0,:128]! - vst1.f32 {q9},[r0,:128]! - bx lr -endfunc - -function ff_vector_clip_int32_neon, export=1 - vdup.32 q0, r2 - vdup.32 q1, r3 - ldr r2, [sp] -1: - vld1.32 {q2-q3}, [r1,:128]! - vmin.s32 q2, q2, q1 - vmin.s32 q3, q3, q1 - vmax.s32 q2, q2, q0 - vmax.s32 q3, q3, q0 - vst1.32 {q2-q3}, [r0,:128]! - subs r2, r2, #8 - bgt 1b - bx lr -endfunc diff --git a/libavcodec/arm/int_neon.S b/libavcodec/arm/int_neon.S index ba840656f..72c4c77c4 100644 --- a/libavcodec/arm/int_neon.S +++ b/libavcodec/arm/int_neon.S @@ -49,42 +49,3 @@ function ff_scalarproduct_int16_neon, export=1 bx lr endfunc -@ scalarproduct_and_madd_int16(/*aligned*/v0,v1,v2,order,mul) -function ff_scalarproduct_and_madd_int16_neon, export=1 - vld1.16 {d28[],d29[]}, [sp] - vmov.i16 q0, #0 - vmov.i16 q1, #0 - vmov.i16 q2, #0 - vmov.i16 q3, #0 - mov r12, r0 - -1: vld1.16 {d16-d17}, [r0,:128]! - vld1.16 {d18-d19}, [r1]! - vld1.16 {d20-d21}, [r2]! - vld1.16 {d22-d23}, [r0,:128]! - vld1.16 {d24-d25}, [r1]! - vld1.16 {d26-d27}, [r2]! - vmul.s16 q10, q10, q14 - vmul.s16 q13, q13, q14 - vmlal.s16 q0, d16, d18 - vmlal.s16 q1, d17, d19 - vadd.s16 q10, q8, q10 - vadd.s16 q13, q11, q13 - vmlal.s16 q2, d22, d24 - vmlal.s16 q3, d23, d25 - vst1.16 {q10}, [r12,:128]! - subs r3, r3, #16 - vst1.16 {q13}, [r12,:128]! - bgt 1b - - vpadd.s32 d16, d0, d1 - vpadd.s32 d17, d2, d3 - vpadd.s32 d18, d4, d5 - vpadd.s32 d19, d6, d7 - vpadd.s32 d0, d16, d17 - vpadd.s32 d1, d18, d19 - vpadd.s32 d2, d0, d1 - vpaddl.s32 d3, d2 - vmov.32 r0, d3[0] - bx lr -endfunc diff --git a/libavcodec/arm/lossless_audiodsp_init_arm.c b/libavcodec/arm/lossless_audiodsp_init_arm.c new file mode 100644 index 000000000..981a39aff --- /dev/null +++ b/libavcodec/arm/lossless_audiodsp_init_arm.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/lossless_audiodsp.h" + +int32_t ff_scalarproduct_and_madd_int16_neon(int16_t *v1, const int16_t *v2, + const int16_t *v3, int len, int mul); + +av_cold void ff_llauddsp_init_arm(LLAudDSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_neon; + } +} diff --git a/libavcodec/arm/lossless_audiodsp_neon.S b/libavcodec/arm/lossless_audiodsp_neon.S new file mode 100644 index 000000000..ba7c45fce --- /dev/null +++ b/libavcodec/arm/lossless_audiodsp_neon.S @@ -0,0 +1,62 @@ +/* + * ARM NEON optimised integer operations + * Copyright (c) 2009 Kostya Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +@ scalarproduct_and_madd_int16(/*aligned*/v0,v1,v2,order,mul) +function ff_scalarproduct_and_madd_int16_neon, export=1 + vld1.16 {d28[],d29[]}, [sp] + vmov.i16 q0, #0 + vmov.i16 q1, #0 + vmov.i16 q2, #0 + vmov.i16 q3, #0 + mov r12, r0 + +1: vld1.16 {d16-d17}, [r0,:128]! + vld1.16 {d18-d19}, [r1]! + vld1.16 {d20-d21}, [r2]! + vld1.16 {d22-d23}, [r0,:128]! + vld1.16 {d24-d25}, [r1]! + vld1.16 {d26-d27}, [r2]! + vmul.s16 q10, q10, q14 + vmul.s16 q13, q13, q14 + vmlal.s16 q0, d16, d18 + vmlal.s16 q1, d17, d19 + vadd.s16 q10, q8, q10 + vadd.s16 q13, q11, q13 + vmlal.s16 q2, d22, d24 + vmlal.s16 q3, d23, d25 + vst1.16 {q10}, [r12,:128]! + subs r3, r3, #16 + vst1.16 {q13}, [r12,:128]! + bgt 1b + + vpadd.s32 d16, d0, d1 + vpadd.s32 d17, d2, d3 + vpadd.s32 d18, d4, d5 + vpadd.s32 d19, d6, d7 + vpadd.s32 d0, d16, d17 + vpadd.s32 d1, d18, d19 + vpadd.s32 d2, d0, d1 + vpaddl.s32 d3, d2 + vmov.32 r0, d3[0] + bx lr +endfunc diff --git a/libavcodec/arm/mdct_vfp.S b/libavcodec/arm/mdct_vfp.S index ee3984c6c..43f6d14c0 100644 --- a/libavcodec/arm/mdct_vfp.S +++ b/libavcodec/arm/mdct_vfp.S @@ -33,6 +33,11 @@ J0 .req a2 J1 .req a4 J2 .req ip J3 .req lr +REVTAB_HI .req v5 +IN_HI .req v6 +OUT_HI .req v6 +TCOS_HI .req sl +TSIN_HI .req fp .macro prerotation_innerloop .set trig_lo, k @@ -76,6 +81,43 @@ J3 .req lr .set k, k + 2 .endm +.macro prerotation_innerloop_rolled + vldmia TCOS!, {s16,s17} + vldmdb TCOS_HI!, {s18,s19} + vldr s0, [IN_HI, #-4] + vldr s1, [IN_HI, #-12] + vldr s2, [IN, #12] + vldr s3, [IN, #4] + vmul.f s8, s0, s16 @ vector operation + vldmia TSIN!, {s20,s21} + vldmdb TSIN_HI!, {s22,s23} + vldr s4, [IN] + vldr s5, [IN, #8] + vldr s6, [IN_HI, #-16] + vldr s7, [IN_HI, #-8] + vmul.f s12, s0, s20 @ vector operation + add IN, IN, #16 + sub IN_HI, IN_HI, #16 + ldrh J0, [REVTAB], #2 + ldrh J1, [REVTAB], #2 + vmls.f s8, s4, s20 @ vector operation + ldrh J3, [REVTAB_HI, #-2]! + ldrh J2, [REVTAB_HI, #-2]! + add J0, OUT, J0, lsl #3 + vmla.f s12, s4, s16 @ vector operation + add J1, OUT, J1, lsl #3 + add J2, OUT, J2, lsl #3 + add J3, OUT, J3, lsl #3 + vstr s8, [J0] + vstr s9, [J1] + vstr s10, [J2] + vstr s11, [J3] + vstr s12, [J0, #4] + vstr s13, [J1, #4] + vstr s14, [J2, #4] + vstr s15, [J3, #4] +.endm + .macro postrotation_innerloop tail, head .set trig_lo_head, n8 - k - 2 .set trig_hi_head, n8 + k @@ -142,6 +184,49 @@ J3 .req lr .endif .endm +.macro postrotation_innerloop_rolled tail, head, tcos_s0_head, tcos_s1_head, tcos_s2_head, tcos_s3_head, tcos_s0_tail, out_offset_head, out_offset_tail + .ifnc "\tail","" + vmls.f s8, s0, \tcos_s0_tail @ vector operation + .endif + .ifnc "\head","" + vldmia TSIN!, {s16,s17} + vldmdb TSIN_HI!, {s18,s19} + vldmia TCOS!, {\tcos_s0_head,\tcos_s1_head} + .endif + .ifnc "\tail","" + vmla.f s12, s4, \tcos_s0_tail @ vector operation + .endif + .ifnc "\head","" + vldr s0, [OUT, #+\out_offset_head+0] + vldr s1, [OUT, #+\out_offset_head+8] + vldr s2, [OUT_HI, #-\out_offset_head-16] + vldr s3, [OUT_HI, #-\out_offset_head-8] + vldr s4, [OUT, #+\out_offset_head+4] + vldr s5, [OUT, #+\out_offset_head+12] + vldr s6, [OUT_HI, #-\out_offset_head-12] + vldr s7, [OUT_HI, #-\out_offset_head-4] + .endif + .ifnc "\tail","" + vstr s8, [OUT, #+\out_offset_tail+0] + vstr s9, [OUT, #+\out_offset_tail+8] + vstr s10, [OUT_HI, #-\out_offset_tail-16] + vstr s11, [OUT_HI, #-\out_offset_tail-8] + .endif + .ifnc "\head","" + vmul.f s8, s4, s16 @ vector operation + .endif + .ifnc "\tail","" + vstr s12, [OUT_HI, #-\out_offset_tail-4] + vstr s13, [OUT_HI, #-\out_offset_tail-12] + vstr s14, [OUT, #+\out_offset_tail+12] + vstr s15, [OUT, #+\out_offset_tail+4] + .endif + .ifnc "\head","" + vmul.f s12, s0, s16 @ vector operation + vldmdb TCOS_HI!, {\tcos_s2_head,\tcos_s3_head} + .endif +.endm + /* void ff_imdct_half_vfp(FFTContext *s, * FFTSample *output, @@ -150,8 +235,7 @@ J3 .req lr function ff_imdct_half_vfp, export=1 ldr ip, [CONTEXT, #5*4] @ mdct_bits teq ip, #6 - it ne - bne X(ff_imdct_half_c) @ only case currently accelerated is the one used by DCA + bne 10f .set n, 1<<6 .set n2, n/2 @@ -189,6 +273,59 @@ function ff_imdct_half_vfp, export=1 fmxr FPSCR, OLDFPSCR vpop {s16-s27} pop {v1-v5,pc} + +10: + push {v1-v6,sl,fp,lr} + vpush {s16-s27} + fmrx OLDFPSCR, FPSCR + ldr lr, =0x03030000 @ RunFast mode, short vectors of length 4, stride 1 + fmxr FPSCR, lr + mov lr, #1 + mov OUT, ORIGOUT + ldr REVTAB, [CONTEXT, #2*4] + ldr TCOS, [CONTEXT, #6*4] + ldr TSIN, [CONTEXT, #7*4] + mov lr, lr, lsl ip + + push {CONTEXT,OLDFPSCR} + add IN_HI, IN, lr, lsl #1 + add REVTAB_HI, REVTAB, lr, lsr #1 + add TCOS_HI, TCOS, lr + add TSIN_HI, TSIN, lr +0: prerotation_innerloop_rolled + teq IN, IN_HI + bne 0b + ldmia sp, {CONTEXT,OLDFPSCR} + + mov ORIGOUT, OUT + fmxr FPSCR, OLDFPSCR + ldr ip, [CONTEXT, #9*4] + blx ip @ s->fft_calc(s, output) + + pop {CONTEXT,OLDFPSCR} + ldr lr, =0x03030000 @ RunFast mode, short vectors of length 4, stride 1 + ldr ip, [CONTEXT, #5*4] @ mdct_bits + fmxr FPSCR, lr + mov lr, #1 + mov lr, lr, lsl ip + sub TCOS, TCOS, lr, lsr #1 + sub TSIN, TSIN, lr, lsr #1 + add OUT_HI, OUT, lr, lsl #1 + add TCOS_HI, TCOS, lr + add TSIN_HI, TSIN, lr + postrotation_innerloop_rolled , head, s20, s21, s22, s23,, 0 + b 1f +0: add OUT, OUT, #32 + sub OUT_HI, OUT_HI, #32 + postrotation_innerloop_rolled tail, head, s20, s21, s22, s23, s24, 0, -16 +1: postrotation_innerloop_rolled tail, head, s24, s25, s26, s27, s20, 16, 0 + teq TSIN, TSIN_HI + bne 0b + postrotation_innerloop_rolled tail,,,,,, s24,, 16 + + fmxr FPSCR, OLDFPSCR + vpop {s16-s27} + pop {v1-v6,sl,fp,pc} endfunc .unreq CONTEXT @@ -203,3 +340,8 @@ endfunc .unreq J1 .unreq J2 .unreq J3 + .unreq REVTAB_HI + .unreq IN_HI + .unreq OUT_HI + .unreq TCOS_HI + .unreq TSIN_HI diff --git a/libavcodec/arm/mlpdsp_armv5te.S b/libavcodec/arm/mlpdsp_armv5te.S new file mode 100644 index 000000000..8355cdf3a --- /dev/null +++ b/libavcodec/arm/mlpdsp_armv5te.S @@ -0,0 +1,655 @@ +/* + * Copyright (c) 2014 RISC OS Open Ltd + * Author: Ben Avison + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +#define MAX_CHANNELS 8 +#define MAX_FIR_ORDER 8 +#define MAX_IIR_ORDER 4 +#define MAX_RATEFACTOR 4 +#define MAX_BLOCKSIZE (40 * MAX_RATEFACTOR) + +PST .req a1 +PCO .req a2 +AC0 .req a3 +AC1 .req a4 +CO0 .req v1 +CO1 .req v2 +CO2 .req v3 +CO3 .req v4 +ST0 .req v5 +ST1 .req v6 +ST2 .req sl +ST3 .req fp +I .req ip +PSAMP .req lr + + +// Some macros that do loads/multiplies where the register number is determined +// from an assembly-time expression. Boy is GNU assembler's syntax ugly... + +.macro load group, index, base, offset + .altmacro + load_ \group, %(\index), \base, \offset + .noaltmacro +.endm + +.macro load_ group, index, base, offset + ldr \group\index, [\base, #\offset] +.endm + +.macro loadd group, index, base, offset + .altmacro + loadd_ \group, %(\index), %(\index+1), \base, \offset + .noaltmacro +.endm + +.macro loadd_ group, index0, index1, base, offset +A .if \offset >= 256 +A ldr \group\index0, [\base, #\offset] +A ldr \group\index1, [\base, #(\offset) + 4] +A .else + ldrd \group\index0, \group\index1, [\base, #\offset] +A .endif +.endm + +.macro multiply index, accumulate, long + .altmacro + multiply_ %(\index), \accumulate, \long + .noaltmacro +.endm + +.macro multiply_ index, accumulate, long + .if \long + .if \accumulate + smlal AC0, AC1, CO\index, ST\index + .else + smull AC0, AC1, CO\index, ST\index + .endif + .else + .if \accumulate + mla AC0, CO\index, ST\index, AC0 + .else + mul AC0, CO\index, ST\index + .endif + .endif +.endm + +// A macro to update the load register number and load offsets + +.macro inc howmany + .set LOAD_REG, (LOAD_REG + \howmany) & 3 + .set OFFSET_CO, OFFSET_CO + 4 * \howmany + .set OFFSET_ST, OFFSET_ST + 4 * \howmany + .if FIR_REMAIN > 0 + .set FIR_REMAIN, FIR_REMAIN - \howmany + .if FIR_REMAIN == 0 + .set OFFSET_CO, 4 * MAX_FIR_ORDER + .set OFFSET_ST, 4 * (MAX_BLOCKSIZE + MAX_FIR_ORDER) + .endif + .elseif IIR_REMAIN > 0 + .set IIR_REMAIN, IIR_REMAIN - \howmany + .endif +.endm + +// Macro to implement the inner loop for one specific combination of parameters + +.macro implement_filter mask_minus1, shift_0, shift_8, iir_taps, fir_taps + .set TOTAL_TAPS, \iir_taps + \fir_taps + + // Deal with register allocation... + .set DEFINED_SHIFT, 0 + .set DEFINED_MASK, 0 + .set SHUFFLE_SHIFT, 0 + .set SHUFFLE_MASK, 0 + .set SPILL_SHIFT, 0 + .set SPILL_MASK, 0 + .if TOTAL_TAPS == 0 + // Little register pressure in this case - just keep MASK where it was + .if !\mask_minus1 + MASK .req ST1 + .set DEFINED_MASK, 1 + .endif + .else + .if \shift_0 + .if !\mask_minus1 + // AC1 is unused with shift 0 + MASK .req AC1 + .set DEFINED_MASK, 1 + .set SHUFFLE_MASK, 1 + .endif + .elseif \shift_8 + .if !\mask_minus1 + .if TOTAL_TAPS <= 4 + // All coefficients are preloaded (so pointer not needed) + MASK .req PCO + .set DEFINED_MASK, 1 + .set SHUFFLE_MASK, 1 + .else + .set SPILL_MASK, 1 + .endif + .endif + .else // shift not 0 or 8 + .if TOTAL_TAPS <= 3 + // All coefficients are preloaded, and at least one CO register is unused + .if \fir_taps & 1 + SHIFT .req CO0 + .set DEFINED_SHIFT, 1 + .set SHUFFLE_SHIFT, 1 + .else + SHIFT .req CO3 + .set DEFINED_SHIFT, 1 + .set SHUFFLE_SHIFT, 1 + .endif + .if !\mask_minus1 + MASK .req PCO + .set DEFINED_MASK, 1 + .set SHUFFLE_MASK, 1 + .endif + .elseif TOTAL_TAPS == 4 + // All coefficients are preloaded + SHIFT .req PCO + .set DEFINED_SHIFT, 1 + .set SHUFFLE_SHIFT, 1 + .if !\mask_minus1 + .set SPILL_MASK, 1 + .endif + .else + .set SPILL_SHIFT, 1 + .if !\mask_minus1 + .set SPILL_MASK, 1 + .endif + .endif + .endif + .endif + .if SPILL_SHIFT + SHIFT .req ST0 + .set DEFINED_SHIFT, 1 + .endif + .if SPILL_MASK + MASK .req ST1 + .set DEFINED_MASK, 1 + .endif + + // Preload coefficients if possible + .if TOTAL_TAPS <= 4 + .set OFFSET_CO, 0 + .if \fir_taps & 1 + .set LOAD_REG, 1 + .else + .set LOAD_REG, 0 + .endif + .rept \fir_taps + load CO, LOAD_REG, PCO, OFFSET_CO + .set LOAD_REG, (LOAD_REG + 1) & 3 + .set OFFSET_CO, OFFSET_CO + 4 + .endr + .set OFFSET_CO, 4 * MAX_FIR_ORDER + .rept \iir_taps + load CO, LOAD_REG, PCO, OFFSET_CO + .set LOAD_REG, (LOAD_REG + 1) & 3 + .set OFFSET_CO, OFFSET_CO + 4 + .endr + .endif + + // Move mask/shift to final positions if necessary + // Need to do this after preloading, because in some cases we + // reuse the coefficient pointer register + .if SHUFFLE_SHIFT + mov SHIFT, ST0 + .endif + .if SHUFFLE_MASK + mov MASK, ST1 + .endif + + // Begin loop +01: + .if TOTAL_TAPS == 0 + // Things simplify a lot in this case + // In fact this could be pipelined further if it's worth it... + ldr ST0, [PSAMP] + subs I, I, #1 + .if !\mask_minus1 + and ST0, ST0, MASK + .endif + str ST0, [PST, #-4]! + str ST0, [PST, #4 * (MAX_BLOCKSIZE + MAX_FIR_ORDER)] + str ST0, [PSAMP], #4 * MAX_CHANNELS + bne 01b + .else + .if \fir_taps & 1 + .set LOAD_REG, 1 + .else + .set LOAD_REG, 0 + .endif + .set LOAD_BANK, 0 + .set FIR_REMAIN, \fir_taps + .set IIR_REMAIN, \iir_taps + .if FIR_REMAIN == 0 // only IIR terms + .set OFFSET_CO, 4 * MAX_FIR_ORDER + .set OFFSET_ST, 4 * (MAX_BLOCKSIZE + MAX_FIR_ORDER) + .else + .set OFFSET_CO, 0 + .set OFFSET_ST, 0 + .endif + .set MUL_REG, LOAD_REG + .set COUNTER, 0 + .rept TOTAL_TAPS + 2 + // Do load(s) + .if FIR_REMAIN != 0 || IIR_REMAIN != 0 + .if COUNTER == 0 + .if TOTAL_TAPS > 4 + load CO, LOAD_REG, PCO, OFFSET_CO + .endif + load ST, LOAD_REG, PST, OFFSET_ST + inc 1 + .elseif COUNTER == 1 && (\fir_taps & 1) == 0 + .if TOTAL_TAPS > 4 + load CO, LOAD_REG, PCO, OFFSET_CO + .endif + load ST, LOAD_REG, PST, OFFSET_ST + inc 1 + .elseif LOAD_BANK == 0 + .if TOTAL_TAPS > 4 + .if FIR_REMAIN == 0 && IIR_REMAIN == 1 + load CO, LOAD_REG, PCO, OFFSET_CO + .else + loadd CO, LOAD_REG, PCO, OFFSET_CO + .endif + .endif + .set LOAD_BANK, 1 + .else + .if FIR_REMAIN == 0 && IIR_REMAIN == 1 + load ST, LOAD_REG, PST, OFFSET_ST + inc 1 + .else + loadd ST, LOAD_REG, PST, OFFSET_ST + inc 2 + .endif + .set LOAD_BANK, 0 + .endif + .endif + + // Do interleaved multiplies, slightly delayed + .if COUNTER >= 2 + multiply MUL_REG, COUNTER > 2, !\shift_0 + .set MUL_REG, (MUL_REG + 1) & 3 + .endif + .set COUNTER, COUNTER + 1 + .endr + + // Post-process the result of the multiplies + .if SPILL_SHIFT + ldr SHIFT, [sp, #9*4 + 0*4] + .endif + .if SPILL_MASK + ldr MASK, [sp, #9*4 + 1*4] + .endif + ldr ST2, [PSAMP] + subs I, I, #1 + .if \shift_8 + mov AC0, AC0, lsr #8 + orr AC0, AC0, AC1, lsl #24 + .elseif !\shift_0 + rsb ST3, SHIFT, #32 + mov AC0, AC0, lsr SHIFT +A orr AC0, AC0, AC1, lsl ST3 +T mov AC1, AC1, lsl ST3 +T orr AC0, AC0, AC1 + .endif + .if \mask_minus1 + add ST3, ST2, AC0 + .else + add ST2, ST2, AC0 + and ST3, ST2, MASK + sub ST2, ST3, AC0 + .endif + str ST3, [PST, #-4]! + str ST2, [PST, #4 * (MAX_BLOCKSIZE + MAX_FIR_ORDER)] + str ST3, [PSAMP], #4 * MAX_CHANNELS + bne 01b + .endif + b 99f + + .if DEFINED_SHIFT + .unreq SHIFT + .endif + .if DEFINED_MASK + .unreq MASK + .endif +.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) +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 + .if \iir_taps <= 3 +A .word 75f +T .hword (75f - 0b) / 2 + .if \iir_taps <= 2 +A .word 76f +T .hword (76f - 0b) / 2 + .if \iir_taps <= 1 +A .word 77f +T .hword (77f - 0b) / 2 + .if \iir_taps == 0 +A .word 78f +T .hword (78f - 0b) / 2 + .endif + .endif + .endif + .endif +70: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 0 +71: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 1 +72: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 2 +73: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 3 +74: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 4 + .if \iir_taps <= 3 +75: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 5 + .if \iir_taps <= 2 +76: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 6 + .if \iir_taps <= 1 +77: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 7 + .if \iir_taps == 0 +78: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 8 + .endif + .endif + .endif + .endif +.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 +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 +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 +63: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 3 +64: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 4 +.endm + +/* void ff_mlp_filter_channel_arm(int32_t *state, const int32_t *coeff, + * int firorder, int iirorder, + * unsigned int filter_shift, int32_t mask, + * int blocksize, int32_t *sample_buffer); + */ +function ff_mlp_filter_channel_arm, export=1 + push {v1-fp,lr} + add v1, sp, #9*4 // point at arguments on stack + ldm v1, {ST0,ST1,I,PSAMP} + cmp ST1, #-1 + bne 30f + movs ST2, ST0, lsl #29 // shift is in range 0-15; we want to special-case 0 and 8 + bne 20f + bcs 10f + switch_on_iir_taps 1, 1, 0 +10: switch_on_iir_taps 1, 0, 1 +20: switch_on_iir_taps 1, 0, 0 +30: movs ST2, ST0, lsl #29 // shift is in range 0-15; we want to special-case 0 and 8 + bne 50f + bcs 40f + switch_on_iir_taps 0, 1, 0 +40: switch_on_iir_taps 0, 0, 1 +50: switch_on_iir_taps 0, 0, 0 +99: pop {v1-fp,pc} +endfunc + + .unreq PST + .unreq PCO + .unreq AC0 + .unreq AC1 + .unreq CO0 + .unreq CO1 + .unreq CO2 + .unreq CO3 + .unreq ST0 + .unreq ST1 + .unreq ST2 + .unreq ST3 + .unreq I + .unreq PSAMP + +/********************************************************************/ + +PSA .req a1 // samples +PCO .req a2 // coeffs +PBL .req a3 // bypassed_lsbs +INDEX .req a4 +CO0 .req v1 +CO1 .req v2 +CO2 .req v3 +CO3 .req v4 +SA0 .req v5 +SA1 .req v6 +SA2 .req sl +SA3 .req fp +AC0 .req ip +AC1 .req lr +NOISE .req SA0 +LSB .req SA1 +DCH .req SA2 // dest_ch +MASK .req SA3 + + // INDEX is used as follows: + // bits 0..6 index2 (values up to 17, but wider so that we can + // add to index field without needing to mask) + // bits 7..14 i (values up to 160) + // bit 15 underflow detect for i + // bits 25..31 (if access_unit_size_pow2 == 128) \ index + // bits 26..31 (if access_unit_size_pow2 == 64) / + +.macro implement_rematrix shift, index_mask, mask_minus1, maxchan + .if \maxchan == 1 + // We can just leave the coefficients in registers in this case + ldrd CO0, CO1, [PCO] + .endif +1: + .if \maxchan == 1 + ldrd SA0, SA1, [PSA] + smull AC0, AC1, CO0, SA0 + .elseif \maxchan == 5 + ldr CO0, [PCO, #0] + ldr SA0, [PSA, #0] + ldr CO1, [PCO, #4] + ldr SA1, [PSA, #4] + ldrd CO2, CO3, [PCO, #8] + smull AC0, AC1, CO0, SA0 + ldrd SA2, SA3, [PSA, #8] + smlal AC0, AC1, CO1, SA1 + ldrd CO0, CO1, [PCO, #16] + smlal AC0, AC1, CO2, SA2 + ldrd SA0, SA1, [PSA, #16] + smlal AC0, AC1, CO3, SA3 + smlal AC0, AC1, CO0, SA0 + .else // \maxchan == 7 + ldr CO2, [PCO, #0] + ldr SA2, [PSA, #0] + ldr CO3, [PCO, #4] + ldr SA3, [PSA, #4] + ldrd CO0, CO1, [PCO, #8] + smull AC0, AC1, CO2, SA2 + ldrd SA0, SA1, [PSA, #8] + smlal AC0, AC1, CO3, SA3 + ldrd CO2, CO3, [PCO, #16] + smlal AC0, AC1, CO0, SA0 + ldrd SA2, SA3, [PSA, #16] + smlal AC0, AC1, CO1, SA1 + ldrd CO0, CO1, [PCO, #24] + smlal AC0, AC1, CO2, SA2 + ldrd SA0, SA1, [PSA, #24] + smlal AC0, AC1, CO3, SA3 + smlal AC0, AC1, CO0, SA0 + .endif + ldm sp, {NOISE, DCH, MASK} + smlal AC0, AC1, CO1, SA1 + .if \shift != 0 + .if \index_mask == 63 + add NOISE, NOISE, INDEX, lsr #32-6 + ldrb LSB, [PBL], #MAX_CHANNELS + ldrsb NOISE, [NOISE] + add INDEX, INDEX, INDEX, lsl #32-6 + .else // \index_mask == 127 + add NOISE, NOISE, INDEX, lsr #32-7 + ldrb LSB, [PBL], #MAX_CHANNELS + ldrsb NOISE, [NOISE] + add INDEX, INDEX, INDEX, lsl #32-7 + .endif + sub INDEX, INDEX, #1<<7 + adds AC0, AC0, NOISE, lsl #\shift + 7 + adc AC1, AC1, NOISE, asr #31 + .else + ldrb LSB, [PBL], #MAX_CHANNELS + sub INDEX, INDEX, #1<<7 + .endif + add PSA, PSA, #MAX_CHANNELS*4 + mov AC0, AC0, lsr #14 + orr AC0, AC0, AC1, lsl #18 + .if !\mask_minus1 + and AC0, AC0, MASK + .endif + add AC0, AC0, LSB + tst INDEX, #1<<15 + str AC0, [PSA, DCH, lsl #2] // DCH is precompensated for the early increment of PSA + beq 1b + b 98f +.endm + +.macro switch_on_maxchan shift, index_mask, mask_minus1 + cmp v4, #5 + blo 51f + beq 50f + implement_rematrix \shift, \index_mask, \mask_minus1, 7 +50: implement_rematrix \shift, \index_mask, \mask_minus1, 5 +51: implement_rematrix \shift, \index_mask, \mask_minus1, 1 +.endm + +.macro switch_on_mask shift, index_mask + cmp sl, #-1 + bne 40f + switch_on_maxchan \shift, \index_mask, 1 +40: switch_on_maxchan \shift, \index_mask, 0 +.endm + +.macro switch_on_au_size shift + .if \shift == 0 + switch_on_mask \shift, undefined + .else + teq v6, #64 + bne 30f + orr INDEX, INDEX, v1, lsl #32-6 + switch_on_mask \shift, 63 +30: orr INDEX, INDEX, v1, lsl #32-7 + switch_on_mask \shift, 127 + .endif +.endm + +/* void ff_mlp_rematrix_channel_arm(int32_t *samples, + * const int32_t *coeffs, + * const uint8_t *bypassed_lsbs, + * const int8_t *noise_buffer, + * int index, + * unsigned int dest_ch, + * uint16_t blockpos, + * unsigned int maxchan, + * int matrix_noise_shift, + * int access_unit_size_pow2, + * int32_t mask); + */ +function ff_mlp_rematrix_channel_arm, export=1 + push {v1-fp,lr} + add v1, sp, #9*4 // point at arguments on stack + ldm v1, {v1-sl} + teq v4, #1 + itt ne + teqne v4, #5 + teqne v4, #7 + bne 99f + teq v6, #64 + it ne + teqne v6, #128 + bne 99f + sub v2, v2, #MAX_CHANNELS + push {a4,v2,sl} // initialise NOISE,DCH,MASK; make sp dword-aligned + movs INDEX, v3, lsl #7 + beq 98f // just in case, do nothing if blockpos = 0 + subs INDEX, INDEX, #1<<7 // offset by 1 so we borrow at the right time + adc lr, v1, v1 // calculate index2 (C was set by preceding subs) + orr INDEX, INDEX, lr + // Switch on matrix_noise_shift: values 0 and 1 are + // disproportionately common so do those in a form the branch + // predictor can accelerate. Values can only go up to 15. + cmp v5, #1 + beq 11f + blo 10f +A ldr pc, [pc, v5, lsl #2] +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 +10: switch_on_au_size 0 +11: switch_on_au_size 1 +12: switch_on_au_size 2 +13: switch_on_au_size 3 +14: switch_on_au_size 4 +15: switch_on_au_size 5 +16: switch_on_au_size 6 +17: switch_on_au_size 7 +18: switch_on_au_size 8 +19: switch_on_au_size 9 +20: switch_on_au_size 10 +21: switch_on_au_size 11 +22: switch_on_au_size 12 +23: switch_on_au_size 13 +24: switch_on_au_size 14 +25: switch_on_au_size 15 + +98: add sp, sp, #3*4 + pop {v1-fp,pc} +99: // Can't handle these parameters, drop back to C + pop {v1-fp,lr} + b X(ff_mlp_rematrix_channel) +endfunc + + .unreq PSA + .unreq PCO + .unreq PBL + .unreq INDEX + .unreq CO0 + .unreq CO1 + .unreq CO2 + .unreq CO3 + .unreq SA0 + .unreq SA1 + .unreq SA2 + .unreq SA3 + .unreq AC0 + .unreq AC1 + .unreq NOISE + .unreq LSB + .unreq DCH + .unreq MASK diff --git a/libavcodec/arm/mlpdsp_armv6.S b/libavcodec/arm/mlpdsp_armv6.S new file mode 100644 index 000000000..d98f80755 --- /dev/null +++ b/libavcodec/arm/mlpdsp_armv6.S @@ -0,0 +1,533 @@ +/* + * Copyright (c) 2014 RISC OS Open Ltd + * Author: Ben Avison + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +.macro loadregoffsh2 group, index, base, offgroup, offindex + .altmacro + loadregoffsh2_ \group, %(\index), \base, \offgroup, %(\offindex) + .noaltmacro +.endm + +.macro loadregoffsh2_ group, index, base, offgroup, offindex + ldr \group\index, [\base, \offgroup\offindex, lsl #2] +.endm + +.macro eorlslreg check, data, group, index + .altmacro + eorlslreg_ \check, \data, \group, %(\index) + .noaltmacro +.endm + +.macro eorlslreg_ check, data, group, index + eor \check, \check, \data, lsl \group\index +.endm + +.macro decr_modulo var, by, modulus + .set \var, \var - \by + .if \var == 0 + .set \var, \modulus + .endif +.endm + + .macro load_group1 size, channels, r0, r1, r2, r3, pointer_dead=0 + .if \size == 2 + ldrd \r0, \r1, [IN], #(\size + 8 - \channels) * 4 + .else // size == 4 + .if IDX1 > 4 || \channels==8 + ldm IN!, {\r0, \r1, \r2, \r3} + .else + ldm IN, {\r0, \r1, \r2, \r3} + .if !\pointer_dead + add IN, IN, #(4 + 8 - \channels) * 4 + .endif + .endif + .endif + decr_modulo IDX1, \size, \channels + .endm + + .macro load_group2 size, channels, r0, r1, r2, r3, pointer_dead=0 + .if \size == 2 + .if IDX1 > 2 + ldm IN!, {\r2, \r3} + .else +//A .ifc \r2, ip +//A .if \pointer_dead +//A ldm IN, {\r2, \r3} +//A .else +//A ldr \r2, [IN], #4 +//A ldr \r3, [IN], #(\size - 1 + 8 - \channels) * 4 +//A .endif +//A .else + ldrd \r2, \r3, [IN], #(\size + 8 - \channels) * 4 +//A .endif + .endif + .endif + decr_modulo IDX1, \size, \channels + .endm + +.macro implement_pack inorder, channels, shift +.if \inorder +.ifc \shift, mixed + +CHECK .req a1 +COUNT .req a2 +IN .req a3 +OUT .req a4 +DAT0 .req v1 +DAT1 .req v2 +DAT2 .req v3 +DAT3 .req v4 +SHIFT0 .req v5 +SHIFT1 .req v6 +SHIFT2 .req sl +SHIFT3 .req fp +SHIFT4 .req ip +SHIFT5 .req lr + + .macro output4words + .set SIZE_GROUP1, IDX1 + .if SIZE_GROUP1 > 4 + .set SIZE_GROUP1, 4 + .endif + .set SIZE_GROUP2, 4 - SIZE_GROUP1 + load_group1 SIZE_GROUP1, \channels, DAT0, DAT1, DAT2, DAT3 + load_group2 SIZE_GROUP2, \channels, DAT0, DAT1, DAT2, DAT3 + .if \channels == 2 + lsl DAT0, SHIFT0 + lsl DAT1, SHIFT1 + lsl DAT2, SHIFT0 + lsl DAT3, SHIFT1 + .elseif \channels == 6 + .if IDX2 == 6 + lsl DAT0, SHIFT0 + lsl DAT1, SHIFT1 + lsl DAT2, SHIFT2 + lsl DAT3, SHIFT3 + .elseif IDX2 == 2 + lsl DAT0, SHIFT4 + lsl DAT1, SHIFT5 + lsl DAT2, SHIFT0 + lsl DAT3, SHIFT1 + .else // IDX2 == 4 + lsl DAT0, SHIFT2 + lsl DAT1, SHIFT3 + lsl DAT2, SHIFT4 + lsl DAT3, SHIFT5 + .endif + .elseif \channels == 8 + .if IDX2 == 8 + uxtb SHIFT0, SHIFT4, ror #0 + uxtb SHIFT1, SHIFT4, ror #8 + uxtb SHIFT2, SHIFT4, ror #16 + uxtb SHIFT3, SHIFT4, ror #24 + .else + uxtb SHIFT0, SHIFT5, ror #0 + uxtb SHIFT1, SHIFT5, ror #8 + uxtb SHIFT2, SHIFT5, ror #16 + uxtb SHIFT3, SHIFT5, ror #24 + .endif + lsl DAT0, SHIFT0 + lsl DAT1, SHIFT1 + lsl DAT2, SHIFT2 + lsl DAT3, SHIFT3 + .endif + eor CHECK, CHECK, DAT0, lsr #8 - (\channels - IDX2) + eor CHECK, CHECK, DAT1, lsr #7 - (\channels - IDX2) + decr_modulo IDX2, 2, \channels + eor CHECK, CHECK, DAT2, lsr #8 - (\channels - IDX2) + eor CHECK, CHECK, DAT3, lsr #7 - (\channels - IDX2) + decr_modulo IDX2, 2, \channels + stm OUT!, {DAT0 - DAT3} + .endm + + .set WORDS_PER_LOOP, \channels // calculate LCM (channels, 4) + .if (WORDS_PER_LOOP % 2) == 0 + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 + .endif + .if (WORDS_PER_LOOP % 2) == 0 + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 + .endif + .set WORDS_PER_LOOP, WORDS_PER_LOOP * 4 + .set SAMPLES_PER_LOOP, WORDS_PER_LOOP / \channels + +function ff_mlp_pack_output_inorder_\channels\()ch_mixedshift_armv6, export=1 + .if SAMPLES_PER_LOOP > 1 + tst COUNT, #SAMPLES_PER_LOOP - 1 // always seems to be in practice + it ne + bne X(ff_mlp_pack_output) // but just in case, branch to C implementation if not + .endif + teq COUNT, #0 + it eq + bxeq lr + push {v1-v6,sl,fp,lr} + ldr SHIFT0, [sp, #(9+1)*4] // get output_shift from stack + ldr SHIFT1, =0x08080808 + ldr SHIFT4, [SHIFT0] + .if \channels == 2 + uadd8 SHIFT4, SHIFT4, SHIFT1 // increase all shifts by 8 + uxtb SHIFT0, SHIFT4, ror #0 + uxtb SHIFT1, SHIFT4, ror #8 + .else + ldr SHIFT5, [SHIFT0, #4] + uadd8 SHIFT4, SHIFT4, SHIFT1 // increase all shifts by 8 + uadd8 SHIFT5, SHIFT5, SHIFT1 + .if \channels == 6 + uxtb SHIFT0, SHIFT4, ror #0 + uxtb SHIFT1, SHIFT4, ror #8 + uxtb SHIFT2, SHIFT4, ror #16 + uxtb SHIFT3, SHIFT4, ror #24 + uxtb SHIFT4, SHIFT5, ror #0 + uxtb SHIFT5, SHIFT5, ror #8 + .endif + .endif + .set IDX1, \channels + .set IDX2, \channels +0: + .rept WORDS_PER_LOOP / 4 + output4words + .endr + subs COUNT, COUNT, #SAMPLES_PER_LOOP + bne 0b + pop {v1-v6,sl,fp,pc} + .ltorg +endfunc + .purgem output4words + + .unreq CHECK + .unreq COUNT + .unreq IN + .unreq OUT + .unreq DAT0 + .unreq DAT1 + .unreq DAT2 + .unreq DAT3 + .unreq SHIFT0 + .unreq SHIFT1 + .unreq SHIFT2 + .unreq SHIFT3 + .unreq SHIFT4 + .unreq SHIFT5 + +.else // not mixed + +CHECK .req a1 +COUNT .req a2 +IN .req a3 +OUT .req a4 +DAT0 .req v1 +DAT1 .req v2 +DAT2 .req v3 +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 + + .macro output4words tail, head, r0, r1, r2, r3, r4, r5, r6, r7, pointer_dead=0 + .if \head + .set SIZE_GROUP1, IDX1 + .if SIZE_GROUP1 > 4 + .set SIZE_GROUP1, 4 + .endif + .set SIZE_GROUP2, 4 - SIZE_GROUP1 + load_group1 SIZE_GROUP1, \channels, \r0, \r1, \r2, \r3, \pointer_dead + .endif + .if \tail + eor CHECK, CHECK, \r4, lsr #8 - (\channels - IDX2) + eor CHECK, CHECK, \r5, lsr #7 - (\channels - IDX2) + decr_modulo IDX2, 2, \channels + .endif + .if \head + load_group2 SIZE_GROUP2, \channels, \r0, \r1, \r2, \r3, \pointer_dead + .endif + .if \tail + eor CHECK, CHECK, \r6, lsr #8 - (\channels - IDX2) + eor CHECK, CHECK, \r7, lsr #7 - (\channels - IDX2) + decr_modulo IDX2, 2, \channels + stm OUT!, {\r4, \r5, \r6, \r7} + .endif + .if \head + lsl \r0, #8 + \shift + lsl \r1, #8 + \shift + lsl \r2, #8 + \shift + lsl \r3, #8 + \shift + .endif + .endm + + .set WORDS_PER_LOOP, \channels // calculate LCM (channels, 8) + .if (WORDS_PER_LOOP % 2) == 0 + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 + .endif + .if (WORDS_PER_LOOP % 2) == 0 + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 + .endif + .if (WORDS_PER_LOOP % 2) == 0 + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 + .endif + .set WORDS_PER_LOOP, WORDS_PER_LOOP * 8 + .set SAMPLES_PER_LOOP, WORDS_PER_LOOP / \channels + +function ff_mlp_pack_output_inorder_\channels\()ch_\shift\()shift_armv6, export=1 + .if SAMPLES_PER_LOOP > 1 + tst COUNT, #SAMPLES_PER_LOOP - 1 // always seems to be in practice + it ne + bne X(ff_mlp_pack_output) // but just in case, branch to C implementation if not + .endif + subs COUNT, COUNT, #SAMPLES_PER_LOOP + it lo + bxlo lr + push {v1-v6,sl,fp,lr} + .set IDX1, \channels + .set IDX2, \channels + output4words 0, 1, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7 +0: beq 1f + .rept WORDS_PER_LOOP / 8 + output4words 1, 1, DAT4, DAT5, DAT6, DAT7, DAT0, DAT1, DAT2, DAT3 + output4words 1, 1, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7 + .endr + subs COUNT, COUNT, #SAMPLES_PER_LOOP + bne 0b +1: + .rept WORDS_PER_LOOP / 8 - 1 + output4words 1, 1, DAT4, DAT5, DAT6, DAT7, DAT0, DAT1, DAT2, DAT3 + output4words 1, 1, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7 + .endr + output4words 1, 1, DAT4, DAT5, DAT6, DAT7, DAT0, DAT1, DAT2, DAT3, pointer_dead=1 + output4words 1, 0, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7 + pop {v1-v6,sl,fp,pc} +endfunc + .purgem output4words + + .unreq CHECK + .unreq COUNT + .unreq IN + .unreq OUT + .unreq DAT0 + .unreq DAT1 + .unreq DAT2 + .unreq DAT3 + .unreq DAT4 + .unreq DAT5 + .unreq DAT6 + .unreq DAT7 + +.endif // mixed +.else // not inorder +.ifc \shift, mixed + +// This case not currently handled + +.else // not mixed + +#if !CONFIG_THUMB + +CHECK .req a1 +COUNT .req a2 +IN .req a3 +OUT .req a4 +DAT0 .req v1 +DAT1 .req v2 +DAT2 .req v3 +DAT3 .req v4 +CHAN0 .req v5 +CHAN1 .req v6 +CHAN2 .req sl +CHAN3 .req fp +CHAN4 .req ip +CHAN5 .req lr + + .macro output4words + .if \channels == 8 + .if IDX1 == 8 + uxtb CHAN0, CHAN4, ror #0 + uxtb CHAN1, CHAN4, ror #8 + uxtb CHAN2, CHAN4, ror #16 + uxtb CHAN3, CHAN4, ror #24 + .else + uxtb CHAN0, CHAN5, ror #0 + uxtb CHAN1, CHAN5, ror #8 + uxtb CHAN2, CHAN5, ror #16 + uxtb CHAN3, CHAN5, ror #24 + .endif + ldr DAT0, [IN, CHAN0, lsl #2] + ldr DAT1, [IN, CHAN1, lsl #2] + ldr DAT2, [IN, CHAN2, lsl #2] + ldr DAT3, [IN, CHAN3, lsl #2] + .if IDX1 == 4 + add IN, IN, #8*4 + .endif + decr_modulo IDX1, 4, \channels + .else + .set SIZE_GROUP1, IDX1 + .if SIZE_GROUP1 > 4 + .set SIZE_GROUP1, 4 + .endif + .set SIZE_GROUP2, 4 - SIZE_GROUP1 + .if SIZE_GROUP1 == 2 + loadregoffsh2 DAT, 0, IN, CHAN, 0 + (\channels - IDX1) + loadregoffsh2 DAT, 1, IN, CHAN, 1 + (\channels - IDX1) + add IN, IN, #8*4 + .else // SIZE_GROUP1 == 4 + loadregoffsh2 DAT, 0, IN, CHAN, 0 + (\channels - IDX1) + loadregoffsh2 DAT, 1, IN, CHAN, 1 + (\channels - IDX1) + loadregoffsh2 DAT, 2, IN, CHAN, 2 + (\channels - IDX1) + loadregoffsh2 DAT, 3, IN, CHAN, 3 + (\channels - IDX1) + .if IDX1 == 4 + add IN, IN, #8*4 + .endif + .endif + decr_modulo IDX1, SIZE_GROUP1, \channels + .if SIZE_GROUP2 == 2 + loadregoffsh2 DAT, 2, IN, CHAN, 0 + (\channels - IDX1) + loadregoffsh2 DAT, 3, IN, CHAN, 1 + (\channels - IDX1) + .if IDX1 == 2 + add IN, IN, #8*4 + .endif + .endif + decr_modulo IDX1, SIZE_GROUP2, \channels + .endif + .if \channels == 8 // in this case we can corrupt CHAN0-3 + rsb CHAN0, CHAN0, #8 + rsb CHAN1, CHAN1, #8 + rsb CHAN2, CHAN2, #8 + rsb CHAN3, CHAN3, #8 + lsl DAT0, #8 + \shift + lsl DAT1, #8 + \shift + lsl DAT2, #8 + \shift + lsl DAT3, #8 + \shift + eor CHECK, CHECK, DAT0, lsr CHAN0 + eor CHECK, CHECK, DAT1, lsr CHAN1 + eor CHECK, CHECK, DAT2, lsr CHAN2 + eor CHECK, CHECK, DAT3, lsr CHAN3 + .else + .if \shift != 0 + lsl DAT0, #\shift + lsl DAT1, #\shift + lsl DAT2, #\shift + lsl DAT3, #\shift + .endif + bic DAT0, DAT0, #0xff000000 + bic DAT1, DAT1, #0xff000000 + bic DAT2, DAT2, #0xff000000 + bic DAT3, DAT3, #0xff000000 + eorlslreg CHECK, DAT0, CHAN, 0 + (\channels - IDX2) + eorlslreg CHECK, DAT1, CHAN, 1 + (\channels - IDX2) + decr_modulo IDX2, 2, \channels + eorlslreg CHECK, DAT2, CHAN, 0 + (\channels - IDX2) + eorlslreg CHECK, DAT3, CHAN, 1 + (\channels - IDX2) + decr_modulo IDX2, 2, \channels + lsl DAT0, #8 + lsl DAT1, #8 + lsl DAT2, #8 + lsl DAT3, #8 + .endif + stm OUT!, {DAT0 - DAT3} + .endm + + .set WORDS_PER_LOOP, \channels // calculate LCM (channels, 4) + .if (WORDS_PER_LOOP % 2) == 0 + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 + .endif + .if (WORDS_PER_LOOP % 2) == 0 + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 + .endif + .set WORDS_PER_LOOP, WORDS_PER_LOOP * 4 + .set SAMPLES_PER_LOOP, WORDS_PER_LOOP / \channels + +function ff_mlp_pack_output_outoforder_\channels\()ch_\shift\()shift_armv6, export=1 + .if SAMPLES_PER_LOOP > 1 + tst COUNT, #SAMPLES_PER_LOOP - 1 // always seems to be in practice + it ne + bne X(ff_mlp_pack_output) // but just in case, branch to C implementation if not + .endif + teq COUNT, #0 + it eq + bxeq lr + push {v1-v6,sl,fp,lr} + ldr CHAN0, [sp, #(9+0)*4] // get ch_assign from stack + ldr CHAN4, [CHAN0] + .if \channels == 2 + uxtb CHAN0, CHAN4, ror #0 + uxtb CHAN1, CHAN4, ror #8 + .else + ldr CHAN5, [CHAN0, #4] + .if \channels == 6 + uxtb CHAN0, CHAN4, ror #0 + uxtb CHAN1, CHAN4, ror #8 + uxtb CHAN2, CHAN4, ror #16 + uxtb CHAN3, CHAN4, ror #24 + uxtb CHAN4, CHAN5, ror #0 + uxtb CHAN5, CHAN5, ror #8 + .endif + .endif + .set IDX1, \channels + .set IDX2, \channels +0: + .rept WORDS_PER_LOOP / 4 + output4words + .endr + subs COUNT, COUNT, #SAMPLES_PER_LOOP + bne 0b + pop {v1-v6,sl,fp,pc} + .ltorg +endfunc + .purgem output4words + + .unreq CHECK + .unreq COUNT + .unreq IN + .unreq OUT + .unreq DAT0 + .unreq DAT1 + .unreq DAT2 + .unreq DAT3 + .unreq CHAN0 + .unreq CHAN1 + .unreq CHAN2 + .unreq CHAN3 + .unreq CHAN4 + .unreq CHAN5 + +#endif // !CONFIG_THUMB + +.endif // mixed +.endif // inorder +.endm // implement_pack + +.macro pack_channels inorder, channels + implement_pack \inorder, \channels, 0 + implement_pack \inorder, \channels, 1 + implement_pack \inorder, \channels, 2 + implement_pack \inorder, \channels, 3 + implement_pack \inorder, \channels, 4 + implement_pack \inorder, \channels, 5 + implement_pack \inorder, \channels, mixed +.endm + +.macro pack_order inorder + pack_channels \inorder, 2 + pack_channels \inorder, 6 + pack_channels \inorder, 8 +.endm + + pack_order 0 + pack_order 1 diff --git a/libavcodec/arm/mlpdsp_init_arm.c b/libavcodec/arm/mlpdsp_init_arm.c new file mode 100644 index 000000000..34a5f61e1 --- /dev/null +++ b/libavcodec/arm/mlpdsp_init_arm.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2014 RISC OS Open Ltd + * Author: Ben Avison + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/arm/cpu.h" +#include "libavutil/attributes.h" +#include "libavcodec/mlpdsp.h" + +void ff_mlp_filter_channel_arm(int32_t *state, const int32_t *coeff, + int firorder, int iirorder, + unsigned int filter_shift, int32_t mask, + int blocksize, int32_t *sample_buffer); +void ff_mlp_rematrix_channel_arm(int32_t *samples, + const int32_t *coeffs, + const uint8_t *bypassed_lsbs, + const int8_t *noise_buffer, + int index, + unsigned int dest_ch, + uint16_t blockpos, + unsigned int maxchan, + int matrix_noise_shift, + int access_unit_size_pow2, + int32_t mask); + +#define DECLARE_PACK(order,channels,shift) \ + int32_t ff_mlp_pack_output_##order##order_##channels##ch_##shift##shift_armv6(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int); +#define ENUMERATE_PACK(order,channels,shift) \ + ff_mlp_pack_output_##order##order_##channels##ch_##shift##shift_armv6, +#define PACK_CHANNELS(macro,order,channels) \ + macro(order,channels,0) \ + macro(order,channels,1) \ + macro(order,channels,2) \ + macro(order,channels,3) \ + macro(order,channels,4) \ + macro(order,channels,5) \ + macro(order,channels,mixed) +#define PACK_ORDER(macro,order) \ + PACK_CHANNELS(macro,order,2) \ + PACK_CHANNELS(macro,order,6) \ + PACK_CHANNELS(macro,order,8) +#define PACK_ALL(macro) \ + PACK_ORDER(macro,outof) \ + PACK_ORDER(macro,in) +PACK_ALL(DECLARE_PACK) + +#define ff_mlp_pack_output_outoforder_2ch_mixedshift_armv6 0 +#define ff_mlp_pack_output_outoforder_6ch_mixedshift_armv6 0 +#define ff_mlp_pack_output_outoforder_8ch_mixedshift_armv6 0 +#if CONFIG_THUMB +#define ff_mlp_pack_output_outoforder_2ch_0shift_armv6 0 +#define ff_mlp_pack_output_outoforder_2ch_1shift_armv6 0 +#define ff_mlp_pack_output_outoforder_2ch_2shift_armv6 0 +#define ff_mlp_pack_output_outoforder_2ch_3shift_armv6 0 +#define ff_mlp_pack_output_outoforder_2ch_4shift_armv6 0 +#define ff_mlp_pack_output_outoforder_2ch_5shift_armv6 0 +#define ff_mlp_pack_output_outoforder_6ch_0shift_armv6 0 +#define ff_mlp_pack_output_outoforder_6ch_1shift_armv6 0 +#define ff_mlp_pack_output_outoforder_6ch_2shift_armv6 0 +#define ff_mlp_pack_output_outoforder_6ch_3shift_armv6 0 +#define ff_mlp_pack_output_outoforder_6ch_4shift_armv6 0 +#define ff_mlp_pack_output_outoforder_6ch_5shift_armv6 0 +#define ff_mlp_pack_output_outoforder_8ch_0shift_armv6 0 +#define ff_mlp_pack_output_outoforder_8ch_1shift_armv6 0 +#define ff_mlp_pack_output_outoforder_8ch_2shift_armv6 0 +#define ff_mlp_pack_output_outoforder_8ch_3shift_armv6 0 +#define ff_mlp_pack_output_outoforder_8ch_4shift_armv6 0 +#define ff_mlp_pack_output_outoforder_8ch_5shift_armv6 0 +#endif + +static int32_t (*mlp_select_pack_output_armv6(uint8_t *ch_assign, + int8_t *output_shift, + uint8_t max_matrix_channel, + int is32))(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int) +{ + int ch_index; + int shift = output_shift[0] < 0 || output_shift[0] > 5 ? 6 : output_shift[0]; + int inorder = 1; + static int32_t (*const routine[2*3*7])(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int) = { + PACK_ALL(ENUMERATE_PACK) + }; + int i; + + if (!is32) // don't support 16-bit output (it's not used by TrueHD) + return ff_mlp_pack_output; + + switch (max_matrix_channel) { + case 1: + ch_index = 0; + break; + case 5: + ch_index = 1; + break; + case 7: + ch_index = 2; + break; + default: + return ff_mlp_pack_output; + } + + for (i = 0; i <= max_matrix_channel; i++) { + if (shift != 6 && output_shift[i] != shift) + shift = 6; // indicate mixed shifts + if (ch_assign[i] != i) + inorder = 0; + } +#if CONFIG_THUMB + if (!inorder) + return ff_mlp_pack_output; // can't currently handle an order array except in ARM mode +#else + if (shift == 6 && !inorder) + return ff_mlp_pack_output; // can't currently handle both an order array and a shift array +#endif + + return routine[(inorder*3+ch_index)*7+shift]; +} + +av_cold void ff_mlpdsp_init_arm(MLPDSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_armv5te(cpu_flags)) { + c->mlp_filter_channel = ff_mlp_filter_channel_arm; + c->mlp_rematrix_channel = ff_mlp_rematrix_channel_arm; + } + if (have_armv6(cpu_flags)) + c->mlp_select_pack_output = mlp_select_pack_output_armv6; +} diff --git a/libavcodec/arm/mpegvideo_arm.c b/libavcodec/arm/mpegvideo_arm.c index 656679809..5f5473d28 100644 --- a/libavcodec/arm/mpegvideo_arm.c +++ b/libavcodec/arm/mpegvideo_arm.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/internal.h" #include "libavutil/arm/cpu.h" #include "libavcodec/avcodec.h" #include "libavcodec/mpegvideo.h" @@ -25,12 +26,13 @@ #include "asm-offsets.h" #if HAVE_NEON -CHK_OFFS(MpegEncContext, y_dc_scale, Y_DC_SCALE); -CHK_OFFS(MpegEncContext, c_dc_scale, C_DC_SCALE); -CHK_OFFS(MpegEncContext, ac_pred, AC_PRED); -CHK_OFFS(MpegEncContext, block_last_index, BLOCK_LAST_INDEX); -CHK_OFFS(MpegEncContext, inter_scantable.raster_end, INTER_SCANTAB_RASTER_END); -CHK_OFFS(MpegEncContext, h263_aic, H263_AIC); +AV_CHECK_OFFSET(MpegEncContext, y_dc_scale, Y_DC_SCALE); +AV_CHECK_OFFSET(MpegEncContext, c_dc_scale, C_DC_SCALE); +AV_CHECK_OFFSET(MpegEncContext, ac_pred, AC_PRED); +AV_CHECK_OFFSET(MpegEncContext, block_last_index, BLOCK_LAST_INDEX); +AV_CHECK_OFFSET(MpegEncContext, inter_scantable.raster_end, + INTER_SCANTAB_RASTER_END); +AV_CHECK_OFFSET(MpegEncContext, h263_aic, H263_AIC); #endif void ff_dct_unquantize_h263_inter_neon(MpegEncContext *s, int16_t *block, diff --git a/libavcodec/arm/mpegvideoencdsp_armv6.S b/libavcodec/arm/mpegvideoencdsp_armv6.S new file mode 100644 index 000000000..ab0dad7b1 --- /dev/null +++ b/libavcodec/arm/mpegvideoencdsp_armv6.S @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +function ff_pix_norm1_armv6, export=1 + push {r4-r6, lr} + mov r12, #16 + mov lr, #0 +1: + ldm r0, {r2-r5} + uxtb16 r6, r2 + uxtb16 r2, r2, ror #8 + smlad lr, r6, r6, lr + uxtb16 r6, r3 + smlad lr, r2, r2, lr + uxtb16 r3, r3, ror #8 + smlad lr, r6, r6, lr + uxtb16 r6, r4 + smlad lr, r3, r3, lr + uxtb16 r4, r4, ror #8 + smlad lr, r6, r6, lr + uxtb16 r6, r5 + smlad lr, r4, r4, lr + uxtb16 r5, r5, ror #8 + smlad lr, r6, r6, lr + subs r12, r12, #1 + add r0, r0, r1 + smlad lr, r5, r5, lr + bgt 1b + + mov r0, lr + pop {r4-r6, pc} +endfunc + +function ff_pix_sum_armv6, export=1 + push {r4-r7, lr} + mov r12, #16 + mov r2, #0 + mov r3, #0 + mov lr, #0 + ldr r4, [r0] +1: + subs r12, r12, #1 + ldr r5, [r0, #4] + usada8 r2, r4, lr, r2 + ldr r6, [r0, #8] + usada8 r3, r5, lr, r3 + ldr r7, [r0, #12] + usada8 r2, r6, lr, r2 + beq 2f + ldr_pre r4, r0, r1 + usada8 r3, r7, lr, r3 + bgt 1b +2: + usada8 r3, r7, lr, r3 + add r0, r2, r3 + pop {r4-r7, pc} +endfunc diff --git a/libavcodec/arm/mpegvideoencdsp_init_arm.c b/libavcodec/arm/mpegvideoencdsp_init_arm.c new file mode 100644 index 000000000..4bfe83568 --- /dev/null +++ b/libavcodec/arm/mpegvideoencdsp_init_arm.c @@ -0,0 +1,38 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/mpegvideoencdsp.h" + +int ff_pix_norm1_armv6(uint8_t *pix, int line_size); +int ff_pix_sum_armv6(uint8_t *pix, int line_size); + +av_cold void ff_mpegvideoencdsp_init_arm(MpegvideoEncDSPContext *c, + AVCodecContext *avctx) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_armv6(cpu_flags)) { + c->pix_norm1 = ff_pix_norm1_armv6; + c->pix_sum = ff_pix_sum_armv6; + } +} diff --git a/libavcodec/arm/pixblockdsp_armv6.S b/libavcodec/arm/pixblockdsp_armv6.S new file mode 100644 index 000000000..b10ea78e8 --- /dev/null +++ b/libavcodec/arm/pixblockdsp_armv6.S @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +function ff_get_pixels_armv6, export=1 + pld [r1, r2] + push {r4-r8, lr} + mov lr, #8 +1: + ldrd_post r4, r5, r1, r2 + subs lr, lr, #1 + uxtb16 r6, r4 + uxtb16 r4, r4, ror #8 + uxtb16 r12, r5 + uxtb16 r8, r5, ror #8 + pld [r1, r2] + pkhbt r5, r6, r4, lsl #16 + pkhtb r6, r4, r6, asr #16 + pkhbt r7, r12, r8, lsl #16 + pkhtb r12, r8, r12, asr #16 + stm r0!, {r5,r6,r7,r12} + bgt 1b + + pop {r4-r8, pc} +endfunc + +function ff_diff_pixels_armv6, export=1 + pld [r1, r3] + pld [r2, r3] + push {r4-r9, lr} + mov lr, #8 +1: + ldrd_post r4, r5, r1, r3 + ldrd_post r6, r7, r2, r3 + uxtb16 r8, r4 + uxtb16 r4, r4, ror #8 + uxtb16 r9, r6 + uxtb16 r6, r6, ror #8 + pld [r1, r3] + ssub16 r9, r8, r9 + ssub16 r6, r4, r6 + uxtb16 r8, r5 + uxtb16 r5, r5, ror #8 + pld [r2, r3] + pkhbt r4, r9, r6, lsl #16 + pkhtb r6, r6, r9, asr #16 + uxtb16 r9, r7 + uxtb16 r7, r7, ror #8 + ssub16 r9, r8, r9 + ssub16 r5, r5, r7 + subs lr, lr, #1 + pkhbt r8, r9, r5, lsl #16 + pkhtb r9, r5, r9, asr #16 + stm r0!, {r4,r6,r8,r9} + bgt 1b + + pop {r4-r9, pc} +endfunc diff --git a/libavcodec/arm/pixblockdsp_init_arm.c b/libavcodec/arm/pixblockdsp_init_arm.c new file mode 100644 index 000000000..b77c523a6 --- /dev/null +++ b/libavcodec/arm/pixblockdsp_init_arm.c @@ -0,0 +1,42 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/pixblockdsp.h" + +void ff_get_pixels_armv6(int16_t *block, const uint8_t *pixels, int stride); +void ff_diff_pixels_armv6(int16_t *block, const uint8_t *s1, + const uint8_t *s2, int stride); + +av_cold void ff_pixblockdsp_init_arm(PixblockDSPContext *c, + AVCodecContext *avctx, + unsigned high_bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_armv6(cpu_flags)) { + if (!high_bit_depth) + c->get_pixels = ff_get_pixels_armv6; + c->diff_pixels = ff_diff_pixels_armv6; + } +} diff --git a/libavcodec/arm/h264dsp_armv6.S b/libavcodec/arm/startcode_armv6.S similarity index 98% rename from libavcodec/arm/h264dsp_armv6.S rename to libavcodec/arm/startcode_armv6.S index 2758262c8..a46f00937 100644 --- a/libavcodec/arm/h264dsp_armv6.S +++ b/libavcodec/arm/startcode_armv6.S @@ -69,8 +69,8 @@ TMP3 .req lr andseq TMP3, TMP3, PATTERN .endm -/* int ff_h264_find_start_code_candidate_armv6(const uint8_t *buf, int size) */ -function ff_h264_find_start_code_candidate_armv6, export=1 +/* int ff_startcode_find_candidate_armv6(const uint8_t *buf, int size) */ +function ff_startcode_find_candidate_armv6, export=1 push {v1-v6,lr} mov PTR, BUF @ Ensure there are at least (PRELOAD_DISTANCE+2) complete cachelines to go diff --git a/libavcodec/arm/vc1dsp_init_arm.c b/libavcodec/arm/vc1dsp_init_arm.c index 47d412674..4a8484846 100644 --- a/libavcodec/arm/vc1dsp_init_arm.c +++ b/libavcodec/arm/vc1dsp_init_arm.c @@ -23,10 +23,14 @@ #include "libavcodec/vc1dsp.h" #include "vc1dsp.h" +int ff_startcode_find_candidate_armv6(const uint8_t *buf, int size); + av_cold void ff_vc1dsp_init_arm(VC1DSPContext *dsp) { int cpu_flags = av_get_cpu_flags(); + if (have_armv6(cpu_flags)) + dsp->vc1_find_start_code_candidate = ff_startcode_find_candidate_armv6; if (have_neon(cpu_flags)) ff_vc1dsp_init_neon(dsp); } diff --git a/libavcodec/arm/vc1dsp_init_neon.c b/libavcodec/arm/vc1dsp_init_neon.c index f562344b8..bb873e687 100644 --- a/libavcodec/arm/vc1dsp_init_neon.c +++ b/libavcodec/arm/vc1dsp_init_neon.c @@ -22,6 +22,8 @@ #include "libavcodec/vc1dsp.h" #include "vc1dsp.h" +#include "config.h" + void ff_vc1_inv_trans_8x8_neon(int16_t *block); void ff_vc1_inv_trans_4x8_neon(uint8_t *dest, int linesize, int16_t *block); void ff_vc1_inv_trans_8x4_neon(uint8_t *dest, int linesize, int16_t *block); @@ -35,40 +37,38 @@ void ff_vc1_inv_trans_4x4_dc_neon(uint8_t *dest, int linesize, int16_t *block); void ff_put_pixels8x8_neon(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int rnd); -void ff_put_vc1_mspel_mc10_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); -void ff_put_vc1_mspel_mc20_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); -void ff_put_vc1_mspel_mc30_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); +#define DECL_PUT(X, Y) \ +void ff_put_vc1_mspel_mc##X##Y##_neon(uint8_t *dst, const uint8_t *src, \ + ptrdiff_t stride, int rnd); \ +static void ff_put_vc1_mspel_mc##X##Y##_16_neon(uint8_t *dst, const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + ff_put_vc1_mspel_mc##X##Y##_neon(dst+0, src+0, stride, rnd); \ + ff_put_vc1_mspel_mc##X##Y##_neon(dst+8, src+8, stride, rnd); \ + dst += 8*stride; src += 8*stride; \ + ff_put_vc1_mspel_mc##X##Y##_neon(dst+0, src+0, stride, rnd); \ + ff_put_vc1_mspel_mc##X##Y##_neon(dst+8, src+8, stride, rnd); \ +} -void ff_put_vc1_mspel_mc01_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); -void ff_put_vc1_mspel_mc02_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); -void ff_put_vc1_mspel_mc03_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); +DECL_PUT(1, 0) +DECL_PUT(2, 0) +DECL_PUT(3, 0) -void ff_put_vc1_mspel_mc11_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); -void ff_put_vc1_mspel_mc12_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); -void ff_put_vc1_mspel_mc13_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); +DECL_PUT(0, 1) +DECL_PUT(0, 2) +DECL_PUT(0, 3) -void ff_put_vc1_mspel_mc21_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); -void ff_put_vc1_mspel_mc22_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); -void ff_put_vc1_mspel_mc23_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); +DECL_PUT(1, 1) +DECL_PUT(1, 2) +DECL_PUT(1, 3) -void ff_put_vc1_mspel_mc31_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); -void ff_put_vc1_mspel_mc32_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); -void ff_put_vc1_mspel_mc33_neon(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride, int rnd); +DECL_PUT(2, 1) +DECL_PUT(2, 2) +DECL_PUT(2, 3) + +DECL_PUT(3, 1) +DECL_PUT(3, 2) +DECL_PUT(3, 3) void ff_put_vc1_chroma_mc8_neon(uint8_t *dst, uint8_t *src, int stride, int h, int x, int y); @@ -79,6 +79,10 @@ void ff_put_vc1_chroma_mc4_neon(uint8_t *dst, uint8_t *src, int stride, int h, void ff_avg_vc1_chroma_mc4_neon(uint8_t *dst, uint8_t *src, int stride, int h, int x, int y); +#define FN_ASSIGN(X, Y) \ + dsp->put_vc1_mspel_pixels_tab[0][X+4*Y] = ff_put_vc1_mspel_mc##X##Y##_16_neon; \ + dsp->put_vc1_mspel_pixels_tab[1][X+4*Y] = ff_put_vc1_mspel_mc##X##Y##_neon + av_cold void ff_vc1dsp_init_neon(VC1DSPContext *dsp) { dsp->vc1_inv_trans_8x8 = ff_vc1_inv_trans_8x8_neon; @@ -90,22 +94,27 @@ av_cold void ff_vc1dsp_init_neon(VC1DSPContext *dsp) dsp->vc1_inv_trans_8x4_dc = ff_vc1_inv_trans_8x4_dc_neon; dsp->vc1_inv_trans_4x4_dc = ff_vc1_inv_trans_4x4_dc_neon; - dsp->put_vc1_mspel_pixels_tab[ 0] = ff_put_pixels8x8_neon; - dsp->put_vc1_mspel_pixels_tab[ 1] = ff_put_vc1_mspel_mc10_neon; - dsp->put_vc1_mspel_pixels_tab[ 2] = ff_put_vc1_mspel_mc20_neon; - dsp->put_vc1_mspel_pixels_tab[ 3] = ff_put_vc1_mspel_mc30_neon; - dsp->put_vc1_mspel_pixels_tab[ 4] = ff_put_vc1_mspel_mc01_neon; - dsp->put_vc1_mspel_pixels_tab[ 5] = ff_put_vc1_mspel_mc11_neon; - dsp->put_vc1_mspel_pixels_tab[ 6] = ff_put_vc1_mspel_mc21_neon; - dsp->put_vc1_mspel_pixels_tab[ 7] = ff_put_vc1_mspel_mc31_neon; - dsp->put_vc1_mspel_pixels_tab[ 8] = ff_put_vc1_mspel_mc02_neon; - dsp->put_vc1_mspel_pixels_tab[ 9] = ff_put_vc1_mspel_mc12_neon; - dsp->put_vc1_mspel_pixels_tab[10] = ff_put_vc1_mspel_mc22_neon; - dsp->put_vc1_mspel_pixels_tab[11] = ff_put_vc1_mspel_mc32_neon; - dsp->put_vc1_mspel_pixels_tab[12] = ff_put_vc1_mspel_mc03_neon; - dsp->put_vc1_mspel_pixels_tab[13] = ff_put_vc1_mspel_mc13_neon; - dsp->put_vc1_mspel_pixels_tab[14] = ff_put_vc1_mspel_mc23_neon; - dsp->put_vc1_mspel_pixels_tab[15] = ff_put_vc1_mspel_mc33_neon; + dsp->put_vc1_mspel_pixels_tab[1][ 0] = ff_put_pixels8x8_neon; + if (HAVE_AS_DN_DIRECTIVE) { + FN_ASSIGN(1, 0); + FN_ASSIGN(2, 0); + FN_ASSIGN(3, 0); + + FN_ASSIGN(0, 1); + FN_ASSIGN(1, 1); + FN_ASSIGN(2, 1); + FN_ASSIGN(3, 1); + + FN_ASSIGN(0, 2); + FN_ASSIGN(1, 2); + FN_ASSIGN(2, 2); + FN_ASSIGN(3, 2); + + FN_ASSIGN(0, 3); + FN_ASSIGN(1, 3); + FN_ASSIGN(2, 3); + FN_ASSIGN(3, 3); + } dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_vc1_chroma_mc8_neon; dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_neon; diff --git a/libavcodec/arm/vc1dsp_neon.S b/libavcodec/arm/vc1dsp_neon.S index 3fba41fa6..c4f4db9c8 100644 --- a/libavcodec/arm/vc1dsp_neon.S +++ b/libavcodec/arm/vc1dsp_neon.S @@ -24,6 +24,8 @@ #include "libavutil/arm/asm.S" #include "neon.S" +#include "config.h" + @ Transpose rows into columns of a matrix of 16-bit elements. For 4x4, pass @ double-word registers, for 8x4, pass quad-word registers. .macro transpose16 r0, r1, r2, r3 @@ -661,6 +663,7 @@ function ff_vc1_inv_trans_4x4_neon, export=1 bx lr endfunc +#if HAVE_AS_DN_DIRECTIVE @ The absolute value of multiplication constants from vc1_mspel_filter and vc1_mspel_{ver,hor}_filter_16bits. @ The sign is embedded in the code below that carries out the multiplication (mspel_filter{,.16}). #define MSPEL_MODE_1_MUL_CONSTANTS 4 53 18 3 @@ -984,6 +987,7 @@ PUT_VC1_MSPEL_MC_V_ONLY(2) PUT_VC1_MSPEL_MC_V_ONLY(3) #undef PUT_VC1_MSPEL_MC_V_ONLY +#endif function ff_put_pixels8x8_neon, export=1 vld1.64 {d0}, [r1], r2 diff --git a/libavcodec/arm/videodsp_armv5te.S b/libavcodec/arm/videodsp_armv5te.S index 4bd365a33..55bcce5cb 100644 --- a/libavcodec/arm/videodsp_armv5te.S +++ b/libavcodec/arm/videodsp_armv5te.S @@ -1,5 +1,5 @@ @ -@ ARMv5te optimized DSP utils +@ ARMv5te-optimized core video DSP functions @ Copyright (c) 2004 AGAWA Koji @ @ This file is part of FFmpeg diff --git a/libavcodec/arm/vp3dsp_init_arm.c b/libavcodec/arm/vp3dsp_init_arm.c index c8888edc8..d9246365d 100644 --- a/libavcodec/arm/vp3dsp_init_arm.c +++ b/libavcodec/arm/vp3dsp_init_arm.c @@ -21,7 +21,6 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/arm/cpu.h" -#include "libavcodec/dsputil.h" #include "libavcodec/vp3dsp.h" void ff_vp3_idct_put_neon(uint8_t *dest, int line_size, int16_t *data); diff --git a/libavcodec/arm/vp8.h b/libavcodec/arm/vp8.h index ddaa1203f..965342d93 100644 --- a/libavcodec/arm/vp8.h +++ b/libavcodec/arm/vp8.h @@ -26,7 +26,7 @@ #include "libavcodec/vp8.h" #if HAVE_ARMV6_EXTERNAL -#define decode_block_coeffs_internal ff_decode_block_coeffs_armv6 +#define vp8_decode_block_coeffs_internal ff_decode_block_coeffs_armv6 int ff_decode_block_coeffs_armv6(VP56RangeCoder *rc, int16_t block[16], uint8_t probs[8][3][NUM_DCT_TOKENS-1], int i, uint8_t *token_prob, int16_t qmul[2]); diff --git a/libavcodec/arm/vp8dsp.h b/libavcodec/arm/vp8dsp.h index 786741e2e..7281d0bfb 100644 --- a/libavcodec/arm/vp8dsp.h +++ b/libavcodec/arm/vp8dsp.h @@ -21,8 +21,10 @@ #include "libavcodec/vp8dsp.h" -void ff_vp8dsp_init_armv6(VP8DSPContext *dsp, int vp7); -void ff_vp8dsp_init_neon(VP8DSPContext *dsp, int vp7); +void ff_vp78dsp_init_armv6(VP8DSPContext *dsp); +void ff_vp78dsp_init_neon(VP8DSPContext *dsp); +void ff_vp8dsp_init_armv6(VP8DSPContext *dsp); +void ff_vp8dsp_init_neon(VP8DSPContext *dsp); #define VP8_LF_Y(hv, inner, opt) \ void ff_vp8_##hv##_loop_filter16##inner##_##opt(uint8_t *dst, \ diff --git a/libavcodec/arm/vp8dsp_init_arm.c b/libavcodec/arm/vp8dsp_init_arm.c index b684e9b43..8b801766d 100644 --- a/libavcodec/arm/vp8dsp_init_arm.c +++ b/libavcodec/arm/vp8dsp_init_arm.c @@ -23,12 +23,22 @@ #include "libavcodec/vp8dsp.h" #include "vp8dsp.h" -av_cold void ff_vp8dsp_init_arm(VP8DSPContext *dsp, int vp7) +av_cold void ff_vp78dsp_init_arm(VP8DSPContext *dsp) { int cpu_flags = av_get_cpu_flags(); if (have_armv6(cpu_flags)) - ff_vp8dsp_init_armv6(dsp, vp7); + ff_vp78dsp_init_armv6(dsp); if (have_neon(cpu_flags)) - ff_vp8dsp_init_neon(dsp, vp7); + ff_vp78dsp_init_neon(dsp); +} + +av_cold void ff_vp8dsp_init_arm(VP8DSPContext *dsp) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_armv6(cpu_flags)) + ff_vp8dsp_init_armv6(dsp); + if (have_neon(cpu_flags)) + ff_vp8dsp_init_neon(dsp); } diff --git a/libavcodec/arm/vp8dsp_init_armv6.c b/libavcodec/arm/vp8dsp_init_armv6.c index d8197e7f9..a5bcd733e 100644 --- a/libavcodec/arm/vp8dsp_init_armv6.c +++ b/libavcodec/arm/vp8dsp_init_armv6.c @@ -40,31 +40,8 @@ VP8_BILIN(16, armv6); VP8_BILIN(8, armv6); VP8_BILIN(4, armv6); -av_cold void ff_vp8dsp_init_armv6(VP8DSPContext *dsp, int vp7) +av_cold void ff_vp78dsp_init_armv6(VP8DSPContext *dsp) { - if (!vp7) { - dsp->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_armv6; - dsp->vp8_luma_dc_wht_dc = ff_vp8_luma_dc_wht_dc_armv6; - - dsp->vp8_idct_add = ff_vp8_idct_add_armv6; - dsp->vp8_idct_dc_add = ff_vp8_idct_dc_add_armv6; - dsp->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_armv6; - dsp->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_armv6; - - dsp->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16_armv6; - dsp->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16_armv6; - dsp->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_armv6; - dsp->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_armv6; - - dsp->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16_inner_armv6; - dsp->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16_inner_armv6; - dsp->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_armv6; - dsp->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_armv6; - - dsp->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter16_simple_armv6; - dsp->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter16_simple_armv6; - } - dsp->put_vp8_epel_pixels_tab[0][0][0] = ff_put_vp8_pixels16_armv6; dsp->put_vp8_epel_pixels_tab[0][0][2] = ff_put_vp8_epel16_h6_armv6; dsp->put_vp8_epel_pixels_tab[0][2][0] = ff_put_vp8_epel16_v6_armv6; @@ -120,3 +97,27 @@ av_cold void ff_vp8dsp_init_armv6(VP8DSPContext *dsp, int vp7) dsp->put_vp8_bilinear_pixels_tab[2][2][1] = ff_put_vp8_bilin4_hv_armv6; dsp->put_vp8_bilinear_pixels_tab[2][2][2] = ff_put_vp8_bilin4_hv_armv6; } + +av_cold void ff_vp8dsp_init_armv6(VP8DSPContext *dsp) +{ + dsp->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_armv6; + dsp->vp8_luma_dc_wht_dc = ff_vp8_luma_dc_wht_dc_armv6; + + dsp->vp8_idct_add = ff_vp8_idct_add_armv6; + dsp->vp8_idct_dc_add = ff_vp8_idct_dc_add_armv6; + dsp->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_armv6; + dsp->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_armv6; + + dsp->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16_armv6; + dsp->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16_armv6; + dsp->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_armv6; + dsp->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_armv6; + + dsp->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16_inner_armv6; + dsp->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16_inner_armv6; + dsp->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_armv6; + dsp->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_armv6; + + dsp->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter16_simple_armv6; + dsp->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter16_simple_armv6; +} diff --git a/libavcodec/arm/vp8dsp_init_neon.c b/libavcodec/arm/vp8dsp_init_neon.c index 400ef2d2c..53f1f2338 100644 --- a/libavcodec/arm/vp8dsp_init_neon.c +++ b/libavcodec/arm/vp8dsp_init_neon.c @@ -39,30 +39,8 @@ VP8_BILIN(16, neon); VP8_BILIN(8, neon); VP8_BILIN(4, neon); -av_cold void ff_vp8dsp_init_neon(VP8DSPContext *dsp, int vp7) +av_cold void ff_vp78dsp_init_neon(VP8DSPContext *dsp) { - if (!vp7) { - dsp->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_neon; - - dsp->vp8_idct_add = ff_vp8_idct_add_neon; - dsp->vp8_idct_dc_add = ff_vp8_idct_dc_add_neon; - dsp->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_neon; - dsp->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_neon; - - dsp->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16_neon; - dsp->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16_neon; - dsp->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_neon; - dsp->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_neon; - - dsp->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16_inner_neon; - dsp->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16_inner_neon; - dsp->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_neon; - dsp->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_neon; - - dsp->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter16_simple_neon; - dsp->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter16_simple_neon; - } - dsp->put_vp8_epel_pixels_tab[0][0][0] = ff_put_vp8_pixels16_neon; dsp->put_vp8_epel_pixels_tab[0][0][2] = ff_put_vp8_epel16_h6_neon; dsp->put_vp8_epel_pixels_tab[0][2][0] = ff_put_vp8_epel16_v6_neon; @@ -116,3 +94,26 @@ av_cold void ff_vp8dsp_init_neon(VP8DSPContext *dsp, int vp7) dsp->put_vp8_bilinear_pixels_tab[2][2][1] = ff_put_vp8_bilin4_hv_neon; dsp->put_vp8_bilinear_pixels_tab[2][2][2] = ff_put_vp8_bilin4_hv_neon; } + +av_cold void ff_vp8dsp_init_neon(VP8DSPContext *dsp) +{ + dsp->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_neon; + + dsp->vp8_idct_add = ff_vp8_idct_add_neon; + dsp->vp8_idct_dc_add = ff_vp8_idct_dc_add_neon; + dsp->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_neon; + dsp->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_neon; + + dsp->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16_neon; + dsp->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16_neon; + dsp->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_neon; + dsp->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_neon; + + dsp->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16_inner_neon; + dsp->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16_inner_neon; + dsp->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_neon; + dsp->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_neon; + + dsp->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter16_simple_neon; + dsp->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter16_simple_neon; +} diff --git a/libavcodec/ass.c b/libavcodec/ass.c index ccc957065..a5b5ae5fb 100644 --- a/libavcodec/ass.c +++ b/libavcodec/ass.c @@ -35,6 +35,8 @@ int ff_ass_subtitle_header(AVCodecContext *avctx, avctx->subtitle_header = av_asprintf( "[Script Info]\r\n" "ScriptType: v4.00+\r\n" + "PlayResX: 384\r\n" + "PlayResY: 288\r\n" "\r\n" "[V4+ Styles]\r\n" "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding\r\n" diff --git a/libavcodec/asv.c b/libavcodec/asv.c index 58d2a895a..e5999c9db 100644 --- a/libavcodec/asv.c +++ b/libavcodec/asv.c @@ -27,6 +27,7 @@ #include "asv.h" #include "avcodec.h" +#include "bswapdsp.h" const uint8_t ff_asv_scantab[64] = { 0x00,0x08,0x01,0x09,0x10,0x18,0x11,0x19, @@ -82,7 +83,7 @@ const uint8_t ff_asv2_level_tab[63][2] = { av_cold void ff_asv_common_init(AVCodecContext *avctx) { ASV1Context * const a = avctx->priv_data; - ff_dsputil_init(&a->dsp, avctx); + ff_bswapdsp_init(&a->bbdsp); a->mb_width = (avctx->width + 15) / 16; a->mb_height = (avctx->height + 15) / 16; diff --git a/libavcodec/asv.h b/libavcodec/asv.h index ce3c73aba..a0e8fef70 100644 --- a/libavcodec/asv.h +++ b/libavcodec/asv.h @@ -31,13 +31,21 @@ #include "libavutil/mem.h" #include "avcodec.h" -#include "dsputil.h" +#include "blockdsp.h" +#include "bswapdsp.h" +#include "fdctdsp.h" +#include "idctdsp.h" #include "get_bits.h" +#include "pixblockdsp.h" #include "put_bits.h" typedef struct ASV1Context{ AVCodecContext *avctx; - DSPContext dsp; + BlockDSPContext bdsp; + BswapDSPContext bbdsp; + FDCTDSPContext fdsp; + IDCTDSPContext idsp; + PixblockDSPContext pdsp; PutBitContext pb; GetBitContext gb; ScanTable scantable; diff --git a/libavcodec/asvdec.c b/libavcodec/asvdec.c index 038b461db..23298757b 100644 --- a/libavcodec/asvdec.c +++ b/libavcodec/asvdec.c @@ -28,6 +28,8 @@ #include "asv.h" #include "avcodec.h" +#include "blockdsp.h" +#include "idctdsp.h" #include "internal.h" #include "mathops.h" #include "mpeg12data.h" @@ -163,7 +165,7 @@ static inline int decode_mb(ASV1Context *a, int16_t block[6][64]) { int i; - a->dsp.clear_blocks(block[0]); + a->bdsp.clear_blocks(block[0]); if (a->avctx->codec_id == AV_CODEC_ID_ASV1) { for (i = 0; i < 6; i++) { @@ -188,14 +190,14 @@ static inline void idct_put(ASV1Context *a, AVFrame *frame, int mb_x, int mb_y) uint8_t *dest_cb = frame->data[1] + (mb_y * 8 * frame->linesize[1]) + mb_x * 8; uint8_t *dest_cr = frame->data[2] + (mb_y * 8 * frame->linesize[2]) + mb_x * 8; - a->dsp.idct_put(dest_y , linesize, block[0]); - a->dsp.idct_put(dest_y + 8, linesize, block[1]); - a->dsp.idct_put(dest_y + 8*linesize , linesize, block[2]); - a->dsp.idct_put(dest_y + 8*linesize + 8, linesize, block[3]); + 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)) { - a->dsp.idct_put(dest_cb, frame->linesize[1], block[4]); - a->dsp.idct_put(dest_cr, frame->linesize[2], block[5]); + a->idsp.idct_put(dest_cb, frame->linesize[1], block[4]); + a->idsp.idct_put(dest_cr, frame->linesize[2], block[5]); } } @@ -220,7 +222,8 @@ static int decode_frame(AVCodecContext *avctx, return AVERROR(ENOMEM); if (avctx->codec_id == AV_CODEC_ID_ASV1) - a->dsp.bswap_buf((uint32_t*)a->bitstream_buffer, (const uint32_t*)buf, buf_size/4); + a->bbdsp.bswap_buf((uint32_t *) a->bitstream_buffer, + (const uint32_t *) buf, buf_size / 4); else { int i; for (i = 0; i < buf_size; i++) @@ -276,8 +279,10 @@ static av_cold int decode_init(AVCodecContext *avctx) } ff_asv_common_init(avctx); + ff_blockdsp_init(&a->bdsp, avctx); + ff_idctdsp_init(&a->idsp, avctx); init_vlcs(a); - ff_init_scantable(a->dsp.idct_permutation, &a->scantable, ff_asv_scantab); + ff_init_scantable(a->idsp.idct_permutation, &a->scantable, ff_asv_scantab); avctx->pix_fmt = AV_PIX_FMT_YUV420P; if (avctx->extradata_size < 1 || (a->inv_qscale = avctx->extradata[0]) == 0) { diff --git a/libavcodec/asvenc.c b/libavcodec/asvenc.c index dd3d4f5a5..02cf2db99 100644 --- a/libavcodec/asvenc.c +++ b/libavcodec/asvenc.c @@ -28,6 +28,7 @@ #include "asv.h" #include "avcodec.h" +#include "fdctdsp.h" #include "internal.h" #include "mathops.h" #include "mpeg12data.h" @@ -159,18 +160,18 @@ static inline void dct_get(ASV1Context *a, const AVFrame *frame, 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->dsp.get_pixels(block[0], ptr_y , linesize); - a->dsp.get_pixels(block[1], ptr_y + 8, linesize); - a->dsp.get_pixels(block[2], ptr_y + 8*linesize , linesize); - a->dsp.get_pixels(block[3], ptr_y + 8*linesize + 8, linesize); + 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++) - a->dsp.fdct(block[i]); + a->fdsp.fdct(block[i]); if(!(a->avctx->flags&CODEC_FLAG_GRAY)){ - a->dsp.get_pixels(block[4], ptr_cb, frame->linesize[1]); - a->dsp.get_pixels(block[5], ptr_cr, frame->linesize[2]); + 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++) - a->dsp.fdct(block[i]); + a->fdsp.fdct(block[i]); } } @@ -181,6 +182,48 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, int size, ret; int mb_x, mb_y; + if (pict->width % 16 || pict->height % 16) { + AVFrame *clone = av_frame_alloc(); + int i; + + if (!clone) + return AVERROR(ENOMEM); + clone->format = pict->format; + clone->width = FFALIGN(pict->width, 16); + clone->height = FFALIGN(pict->height, 16); + ret = av_frame_get_buffer(clone, 32); + if (ret < 0) { + av_frame_free(&clone); + return ret; + } + + ret = av_frame_copy(clone, pict); + if (ret < 0) { + av_frame_free(&clone); + return ret; + } + + for (i = 0; i<3; i++) { + int x, y; + int w = FF_CEIL_RSHIFT(pict->width, !!i); + int h = FF_CEIL_RSHIFT(pict->height, !!i); + int w2 = FF_CEIL_RSHIFT(clone->width, !!i); + int h2 = FF_CEIL_RSHIFT(clone->height, !!i); + for (y=0; ydata[i][x + y*clone->linesize[i]] = + clone->data[i][w - 1 + y*clone->linesize[i]]; + for (y=h; ydata[i][x + y*clone->linesize[i]] = + clone->data[i][x + (h-1)*clone->linesize[i]]; + } + ret = encode_frame(avctx, pkt, clone, got_packet); + + av_frame_free(&clone); + return ret; + } + if ((ret = ff_alloc_packet2(avctx, pkt, a->mb_height*a->mb_width*MAX_MB_SIZE + FF_MIN_BUFFER_SIZE)) < 0) return ret; @@ -218,7 +261,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, size= put_bits_count(&a->pb)/32; if(avctx->codec_id == AV_CODEC_ID_ASV1) - a->dsp.bswap_buf((uint32_t*)pkt->data, (uint32_t*)pkt->data, size); + a->bbdsp.bswap_buf((uint32_t *) pkt->data, + (uint32_t *) pkt->data, size); else{ int i; for(i=0; i<4*size; i++) @@ -238,8 +282,10 @@ static av_cold int encode_init(AVCodecContext *avctx){ const int scale= avctx->codec_id == AV_CODEC_ID_ASV1 ? 1 : 2; 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; diff --git a/libavcodec/atrac1data.h b/libavcodec/atrac1data.h index 08f835747..62c218b79 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 fc3b2fd57..435f1ac99 100644 --- a/libavcodec/atrac3.c +++ b/libavcodec/atrac3.c @@ -918,7 +918,7 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) avpriv_float_dsp_init(&q->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); ff_fmt_convert_init(&q->fmt_conv, avctx); - q->units = av_mallocz(sizeof(*q->units) * avctx->channels); + q->units = av_mallocz_array(avctx->channels, sizeof(*q->units)); if (!q->units) { atrac3_decode_close(avctx); return AVERROR(ENOMEM); diff --git a/libavcodec/atrac3plusdec.c b/libavcodec/atrac3plusdec.c index 652bd7890..3a6b3cfa2 100644 --- a/libavcodec/atrac3plusdec.c +++ b/libavcodec/atrac3plusdec.c @@ -166,8 +166,8 @@ static av_cold int atrac3p_decode_init(AVCodecContext *avctx) ctx->my_channel_layout = avctx->channel_layout; - ctx->ch_units = av_mallocz(sizeof(*ctx->ch_units) * - ctx->num_channel_blocks); + ctx->ch_units = av_mallocz_array(ctx->num_channel_blocks, sizeof(*ctx->ch_units)); + if (!ctx->ch_units) { atrac3p_decode_close(avctx); return AVERROR(ENOMEM); diff --git a/libavcodec/audiodsp.c b/libavcodec/audiodsp.c new file mode 100644 index 000000000..85b5a7494 --- /dev/null +++ b/libavcodec/audiodsp.c @@ -0,0 +1,118 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "audiodsp.h" + +static inline uint32_t clipf_c_one(uint32_t a, uint32_t mini, + uint32_t maxi, uint32_t maxisign) +{ + if (a > mini) + return mini; + else if ((a ^ (1U << 31)) > maxisign) + return maxi; + else + return a; +} + +static void vector_clipf_c_opposite_sign(float *dst, const float *src, + float *min, float *max, int len) +{ + int i; + uint32_t mini = *(uint32_t *) min; + uint32_t maxi = *(uint32_t *) max; + uint32_t maxisign = maxi ^ (1U << 31); + uint32_t *dsti = (uint32_t *) dst; + const uint32_t *srci = (const uint32_t *) src; + + for (i = 0; i < len; i += 8) { + dsti[i + 0] = clipf_c_one(srci[i + 0], mini, maxi, maxisign); + dsti[i + 1] = clipf_c_one(srci[i + 1], mini, maxi, maxisign); + dsti[i + 2] = clipf_c_one(srci[i + 2], mini, maxi, maxisign); + dsti[i + 3] = clipf_c_one(srci[i + 3], mini, maxi, maxisign); + dsti[i + 4] = clipf_c_one(srci[i + 4], mini, maxi, maxisign); + dsti[i + 5] = clipf_c_one(srci[i + 5], mini, maxi, maxisign); + dsti[i + 6] = clipf_c_one(srci[i + 6], mini, maxi, maxisign); + dsti[i + 7] = clipf_c_one(srci[i + 7], mini, maxi, maxisign); + } +} + +static void vector_clipf_c(float *dst, const float *src, + float min, float max, int len) +{ + int i; + + if (min < 0 && max > 0) { + vector_clipf_c_opposite_sign(dst, src, &min, &max, len); + } else { + for (i = 0; i < len; i += 8) { + dst[i] = av_clipf(src[i], min, max); + dst[i + 1] = av_clipf(src[i + 1], min, max); + dst[i + 2] = av_clipf(src[i + 2], min, max); + dst[i + 3] = av_clipf(src[i + 3], min, max); + dst[i + 4] = av_clipf(src[i + 4], min, max); + dst[i + 5] = av_clipf(src[i + 5], min, max); + dst[i + 6] = av_clipf(src[i + 6], min, max); + dst[i + 7] = av_clipf(src[i + 7], min, max); + } + } +} + +static int32_t scalarproduct_int16_c(const int16_t *v1, const int16_t *v2, + int order) +{ + int res = 0; + + while (order--) + res += *v1++ **v2++; + + return res; +} + +static void vector_clip_int32_c(int32_t *dst, const int32_t *src, int32_t min, + int32_t max, unsigned int len) +{ + do { + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + len -= 8; + } while (len > 0); +} + +av_cold void ff_audiodsp_init(AudioDSPContext *c) +{ + c->scalarproduct_int16 = scalarproduct_int16_c; + c->vector_clip_int32 = vector_clip_int32_c; + c->vector_clipf = vector_clipf_c; + + if (ARCH_ARM) + ff_audiodsp_init_arm(c); + if (ARCH_PPC) + ff_audiodsp_init_ppc(c); + if (ARCH_X86) + ff_audiodsp_init_x86(c); +} diff --git a/libavcodec/audiodsp.h b/libavcodec/audiodsp.h new file mode 100644 index 000000000..b55bf858e --- /dev/null +++ b/libavcodec/audiodsp.h @@ -0,0 +1,59 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AUDIODSP_H +#define AVCODEC_AUDIODSP_H + +#include + +typedef struct AudioDSPContext { + /** + * Calculate scalar product of two vectors. + * @param len length of vectors, should be multiple of 16 + */ + int32_t (*scalarproduct_int16)(const int16_t *v1, + const int16_t *v2 /* align 16 */, int len); + + /** + * Clip each element in an array of int32_t to a given minimum and + * maximum value. + * @param dst destination array + * constraints: 16-byte aligned + * @param src source array + * constraints: 16-byte aligned + * @param min minimum value + * constraints: must be in the range [-(1 << 24), 1 << 24] + * @param max maximum value + * constraints: must be in the range [-(1 << 24), 1 << 24] + * @param len number of elements in the array + * constraints: multiple of 32 greater than zero + */ + void (*vector_clip_int32)(int32_t *dst, const int32_t *src, int32_t min, + int32_t max, unsigned int len); + /* assume len is a multiple of 8, and arrays are 16-byte aligned */ + void (*vector_clipf)(float *dst /* align 16 */, + const float *src /* align 16 */, + float min, float max, int len /* align 16 */); +} AudioDSPContext; + +void ff_audiodsp_init(AudioDSPContext *c); +void ff_audiodsp_init_arm(AudioDSPContext *c); +void ff_audiodsp_init_ppc(AudioDSPContext *c); +void ff_audiodsp_init_x86(AudioDSPContext *c); + +#endif /* AVCODEC_AUDIODSP_H */ diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 5df717cae..93ba4d087 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -286,6 +286,15 @@ enum AVCodecID { AV_CODEC_ID_HNM4_VIDEO, AV_CODEC_ID_HEVC_DEPRECATED, AV_CODEC_ID_FIC, + AV_CODEC_ID_ALIAS_PIX, + AV_CODEC_ID_BRENDER_PIX_DEPRECATED, + AV_CODEC_ID_PAF_VIDEO_DEPRECATED, + AV_CODEC_ID_EXR_DEPRECATED, + AV_CODEC_ID_VP7_DEPRECATED, + AV_CODEC_ID_SANM_DEPRECATED, + AV_CODEC_ID_SGIRLE_DEPRECATED, + AV_CODEC_ID_MVC1_DEPRECATED, + AV_CODEC_ID_MVC2_DEPRECATED, AV_CODEC_ID_BRENDER_PIX= MKBETAG('B','P','I','X'), AV_CODEC_ID_Y41P = MKBETAG('Y','4','1','P'), @@ -314,6 +323,7 @@ enum AVCodecID { AV_CODEC_ID_SMVJPEG = MKBETAG('S','M','V','J'), AV_CODEC_ID_HEVC = MKBETAG('H','2','6','5'), #define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC + AV_CODEC_ID_VP7 = MKBETAG('V','P','7','0'), /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs @@ -382,6 +392,8 @@ enum AVCodecID { AV_CODEC_ID_ADPCM_IMA_ISS, AV_CODEC_ID_ADPCM_G722, AV_CODEC_ID_ADPCM_IMA_APC, + AV_CODEC_ID_ADPCM_VIMA_DEPRECATED, + AV_CODEC_ID_ADPCM_VIMA = MKBETAG('V','I','M','A'), AV_CODEC_ID_VIMA = MKBETAG('V','I','M','A'), AV_CODEC_ID_ADPCM_AFC = MKBETAG('A','F','C',' '), AV_CODEC_ID_ADPCM_IMA_OKI = MKBETAG('O','K','I',' '), @@ -471,6 +483,8 @@ enum AVCodecID { AV_CODEC_ID_COMFORT_NOISE, AV_CODEC_ID_TAK_DEPRECATED, AV_CODEC_ID_METASOUND, + AV_CODEC_ID_PAF_AUDIO_DEPRECATED, + AV_CODEC_ID_ON2AVC, AV_CODEC_ID_FFWAVESYNTH = MKBETAG('F','F','W','S'), AV_CODEC_ID_SONIC = MKBETAG('S','O','N','C'), AV_CODEC_ID_SONIC_LS = MKBETAG('S','O','N','L'), @@ -479,6 +493,10 @@ enum AVCodecID { AV_CODEC_ID_TAK = MKBETAG('t','B','a','K'), AV_CODEC_ID_EVRC = MKBETAG('s','e','v','c'), AV_CODEC_ID_SMV = MKBETAG('s','s','m','v'), + AV_CODEC_ID_DSD_LSBF = MKBETAG('D','S','D','L'), + AV_CODEC_ID_DSD_MSBF = MKBETAG('D','S','D','M'), + AV_CODEC_ID_DSD_LSBF_PLANAR = MKBETAG('D','S','D','1'), + AV_CODEC_ID_DSD_MSBF_PLANAR = MKBETAG('D','S','D','8'), /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. @@ -515,6 +533,7 @@ enum AVCodecID { AV_CODEC_ID_SMPTE_KLV = MKBETAG('K','L','V','A'), AV_CODEC_ID_DVD_NAV = MKBETAG('D','N','A','V'), AV_CODEC_ID_TIMED_ID3 = MKBETAG('T','I','D','3'), + AV_CODEC_ID_BIN_DATA = MKBETAG('D','A','T','A'), AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it @@ -552,6 +571,13 @@ typedef struct AVCodecDescriptor { * Codec properties, a combination of AV_CODEC_PROP_* flags. */ int props; + + /** + * MIME type(s) associated with the codec. + * May be NULL; if not, a NULL-terminated array of MIME types. + * The first item is always non-NULL and is the preferred MIME type. + */ + const char *const *mime_types; } AVCodecDescriptor; /** @@ -588,7 +614,7 @@ 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 16 +#define FF_INPUT_BUFFER_PADDING_SIZE 32 /** * @ingroup lavc_encoding @@ -625,56 +651,11 @@ enum AVDiscard{ AVDISCARD_DEFAULT = 0, ///< discard useless packets like 0 size packets in avi AVDISCARD_NONREF = 8, ///< discard all non reference AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames + AVDISCARD_NONINTRA= 24, ///< discard all non intra frames AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes AVDISCARD_ALL = 48, ///< discard all }; -enum AVColorPrimaries{ - AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B - AVCOL_PRI_UNSPECIFIED = 2, - AVCOL_PRI_BT470M = 4, - AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM - AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC - AVCOL_PRI_SMPTE240M = 7, ///< functionally identical to above - AVCOL_PRI_FILM = 8, - AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020 - AVCOL_PRI_NB , ///< Not part of ABI -}; - -enum AVColorTransferCharacteristic{ - AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361 - AVCOL_TRC_UNSPECIFIED = 2, - AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM - AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG - AVCOL_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC - AVCOL_TRC_SMPTE240M = 7, - AVCOL_TRC_LINEAR = 8, ///< "Linear transfer characteristics" - AVCOL_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)" - AVCOL_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt( 10 ) : 1 range)" - 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_NB , ///< Not part of ABI -}; - -/** - * X X 3 4 X X are luma samples, - * 1 2 1-6 are possible chroma positions - * X X 5 6 X 0 is undefined/unknown position - */ -enum AVChromaLocation{ - AVCHROMA_LOC_UNSPECIFIED = 0, - AVCHROMA_LOC_LEFT = 1, ///< mpeg2/4, h264 default - AVCHROMA_LOC_CENTER = 2, ///< mpeg1, jpeg, h263 - AVCHROMA_LOC_TOPLEFT = 3, ///< DV - AVCHROMA_LOC_TOP = 4, - AVCHROMA_LOC_BOTTOMLEFT = 5, - AVCHROMA_LOC_BOTTOM = 6, - AVCHROMA_LOC_NB , ///< Not part of ABI -}; - enum AVAudioServiceType { AV_AUDIO_SERVICE_TYPE_MAIN = 0, AV_AUDIO_SERVICE_TYPE_EFFECTS = 1, @@ -719,14 +700,26 @@ typedef struct RcOverride{ #define CODEC_FLAG_4MV 0x0004 ///< 4 MV per MB allowed / advanced prediction for H.263. #define CODEC_FLAG_OUTPUT_CORRUPT 0x0008 ///< Output even those frames that might be corrupted #define CODEC_FLAG_QPEL 0x0010 ///< Use qpel MC. -#define CODEC_FLAG_GMC 0x0020 ///< Use GMC. -#define CODEC_FLAG_MV0 0x0040 ///< Always try a MB with MV=<0,0>. +#if FF_API_GMC /** - * The parent program guarantees that the input for B-frames containing - * streams is not written to for at least s->max_b_frames+1 frames, if - * this is not set the input will be copied. + * @deprecated use the "gmc" private option of the libxvid encoder + */ +#define CODEC_FLAG_GMC 0x0020 ///< Use GMC. +#endif +#if FF_API_MV0 +/** + * @deprecated use the flag "mv0" in the "mpv_flags" private option of the + * mpegvideo encoders + */ +#define CODEC_FLAG_MV0 0x0040 +#endif +#if FF_API_INPUT_PRESERVED +/** + * @deprecated passing reference-counted frames to the encoders replaces this + * flag */ #define CODEC_FLAG_INPUT_PRESERVED 0x0100 +#endif #define CODEC_FLAG_PASS1 0x0200 ///< Use internal 2pass ratecontrol in first pass mode. #define CODEC_FLAG_PASS2 0x0400 ///< Use internal 2pass ratecontrol in second pass mode. #define CODEC_FLAG_GRAY 0x2000 ///< Only decode/encode grayscale. @@ -740,7 +733,13 @@ typedef struct RcOverride{ #define CODEC_FLAG_PSNR 0x8000 ///< error[?] variables will be set during encoding. #define CODEC_FLAG_TRUNCATED 0x00010000 /** Input bitstream might be truncated at a random location instead of only at frame boundaries. */ -#define CODEC_FLAG_NORMALIZE_AQP 0x00020000 ///< Normalize adaptive quantization. +#if FF_API_NORMALIZE_AQP +/** + * @deprecated use the flag "naq" in the "mpv_flags" private option of the + * mpegvideo encoders + */ +#define CODEC_FLAG_NORMALIZE_AQP 0x00020000 +#endif #define CODEC_FLAG_INTERLACED_DCT 0x00040000 ///< Use interlaced DCT. #define CODEC_FLAG_LOW_DELAY 0x00080000 ///< Force low delay. #define CODEC_FLAG_GLOBAL_HEADER 0x00400000 ///< Place global headers in extradata instead of every keyframe. @@ -1002,6 +1001,21 @@ enum AVPacketSideDataType { */ AV_PKT_DATA_H263_MB_INFO, + /** + * This side data should be associated with an audio stream and contains + * ReplayGain information in form of the AVReplayGain struct. + */ + AV_PKT_DATA_REPLAYGAIN, + + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the decoded video frames for + * correct presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_PKT_DATA_DISPLAYMATRIX, + /** * Recommmends skipping the specified number of samples * @code @@ -1067,6 +1081,12 @@ enum AVPacketSideDataType { AV_PKT_DATA_METADATA_UPDATE, }; +typedef struct AVPacketSideData { + uint8_t *data; + int size; + enum AVPacketSideDataType type; +} AVPacketSideData; + /** * This structure stores compressed data. It is typically exported by demuxers * and then passed as input to decoders, or received as output from encoders and @@ -1123,11 +1143,7 @@ typedef struct AVPacket { * Additional packet data that can be provided by the container. * Packet can contain several types of side information. */ - struct { - uint8_t *data; - int size; - enum AVPacketSideDataType type; - } *side_data; + AVPacketSideData *side_data; int side_data_elems; /** @@ -1205,7 +1221,13 @@ typedef struct AVCodecContext { enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ const struct AVCodec *codec; +#if FF_API_CODEC_NAME + /** + * @deprecated this field is not used for anything in libavcodec + */ + attribute_deprecated char codec_name[32]; +#endif enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ /** @@ -1338,12 +1360,17 @@ typedef struct AVCodecContext { * encoded input. * * Audio: - * For encoding, this is the number of "priming" samples added to the - * beginning of the stream. The decoded output will be delayed by this - * many samples relative to the input to the encoder. Note that this - * field is purely informational and does not directly affect the pts - * output by the encoder, which should always be based on the actual - * presentation time, including any delay. + * For 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 decoding, this is the number of samples the decoder needs to * output before the decoder's output is valid. When seeking, you should * start decoding this many samples prior to your desired seek point. @@ -2230,7 +2257,7 @@ typedef struct AVCodecContext { /** * ratecontrol qmin qmax limiting method - * 0-> clipping, 1-> use a nice continuous function to limit qscale wthin qmin/qmax. + * 0-> clipping, 1-> use a nice continuous function to limit qscale within qmin/qmax. * - encoding: Set by user. * - decoding: unused */ @@ -2264,7 +2291,7 @@ typedef struct AVCodecContext { /** * maximum bitrate * - encoding: Set by user. - * - decoding: unused + * - decoding: Set by libavcodec. */ int rc_max_rate; @@ -2325,14 +2352,14 @@ typedef struct AVCodecContext { int context_model; /** - * minimum Lagrange multipler + * minimum Lagrange multiplier * - encoding: Set by user. * - decoding: unused */ int lmin; /** - * maximum Lagrange multipler + * maximum Lagrange multiplier * - encoding: Set by user. * - decoding: unused */ @@ -2493,6 +2520,7 @@ typedef struct AVCodecContext { int error_concealment; #define FF_EC_GUESS_MVS 1 #define FF_EC_DEBLOCK 2 +#define FF_EC_FAVOR_INTER 256 /** * debug @@ -2524,6 +2552,7 @@ typedef struct AVCodecContext { #endif #define FF_DEBUG_BUFFERS 0x00008000 #define FF_DEBUG_THREADS 0x00010000 +#define FF_DEBUG_NOMC 0x01000000 #if FF_API_DEBUG_MV /** @@ -2556,8 +2585,9 @@ typedef struct AVCodecContext { #define AV_EF_BUFFER (1<<2) ///< detect improper bitstream length #define AV_EF_EXPLODE (1<<3) ///< abort decoding on minor error detection +#define AV_EF_IGNORE_ERR (1<<15) ///< ignore errors and continue #define AV_EF_CAREFUL (1<<16) ///< consider things that violate the spec, are fast to calculate and have not been seen in the wild as errors -#define AV_EF_COMPLIANT (1<<17) ///< consider all spec non compliancies as errors +#define AV_EF_COMPLIANT (1<<17) ///< consider all spec non compliances as errors #define AV_EF_AGGRESSIVE (1<<18) ///< consider things that a sane encoder should not do as an error @@ -2621,18 +2651,23 @@ typedef struct AVCodecContext { #define FF_IDCT_SIMPLEMMX 3 #define FF_IDCT_ARM 7 #define FF_IDCT_ALTIVEC 8 +#if FF_API_ARCH_SH4 #define FF_IDCT_SH4 9 +#endif #define FF_IDCT_SIMPLEARM 10 #define FF_IDCT_IPP 13 #define FF_IDCT_XVIDMMX 14 #define FF_IDCT_SIMPLEARMV5TE 16 #define FF_IDCT_SIMPLEARMV6 17 +#if FF_API_ARCH_SPARC #define FF_IDCT_SIMPLEVIS 18 +#endif #define FF_IDCT_FAAN 20 #define FF_IDCT_SIMPLENEON 22 #if FF_API_ARCH_ALPHA #define FF_IDCT_SIMPLEALPHA 23 #endif +#define FF_IDCT_SIMPLEAUTO 128 /** * bits per sample/pixel from the demuxer (needed for huffyuv). @@ -2743,7 +2778,7 @@ typedef struct AVCodecContext { #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 */ @@ -2831,6 +2866,7 @@ typedef struct AVCodecContext { #define FF_PROFILE_HEVC_MAIN 1 #define FF_PROFILE_HEVC_MAIN_10 2 #define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 +#define FF_PROFILE_HEVC_REXT 4 /** * level @@ -2897,6 +2933,21 @@ typedef struct AVCodecContext { */ uint64_t vbv_delay; + /** + * Encoding only. 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. + */ + int side_data_only_packets; + /** * Timebase in which pkt_dts/pts and AVPacket.dts/pts are. * Code outside libavcodec should access this field using: @@ -3164,8 +3215,20 @@ typedef struct AVHWAccel { */ int capabilities; + /***************************************************************** + * 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. + ***************************************************************** + */ struct AVHWAccel *next; + /** + * Allocate a custom buffer + */ + int (*alloc_frame)(AVCodecContext *avctx, AVFrame *frame); + /** * Called at the beginning of each frame or field picture. * @@ -3208,13 +3271,13 @@ typedef struct AVHWAccel { int (*end_frame)(AVCodecContext *avctx); /** - * Size of HW accelerator private data. + * Size of per-frame hardware accelerator private data. * * Private data is allocated with av_mallocz() before * AVCodecContext.get_buffer() and deallocated after * AVCodecContext.release_buffer(). */ - int priv_data_size; + int frame_priv_data_size; /** * Called for every Macroblock in a slice. @@ -3226,6 +3289,29 @@ typedef struct AVHWAccel { * @param s the mpeg context */ void (*decode_mb)(struct MpegEncContext *s); + + /** + * Initialize the hwaccel private data. + * + * This will be called from ff_get_format(), after hwaccel and + * hwaccel_context are set and the hwaccel private data in AVCodecInternal + * is allocated. + */ + int (*init)(AVCodecContext *avctx); + + /** + * Uninitialize the hwaccel private data. + * + * This will be called from get_format() or avcodec_close(), after hwaccel + * and hwaccel_context are already uninitialized. + */ + int (*uninit)(AVCodecContext *avctx); + + /** + * Size of the private data to allocate in + * AVCodecInternal.hwaccel_priv_data. + */ + int priv_data_size; } AVHWAccel; /** @@ -3350,9 +3436,8 @@ void avcodec_register(AVCodec *codec); void avcodec_register_all(void); /** - * Allocate an AVCodecContext and set its fields to default values. The - * resulting struct can be deallocated by calling avcodec_close() on it followed - * by av_free(). + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct should be freed with avcodec_free_context(). * * @param codec if non-NULL, allocate private data and initialize defaults * for the given codec. It is illegal to then call avcodec_open2() @@ -3366,6 +3451,12 @@ void avcodec_register_all(void); */ AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); +/** + * Free the codec context and everything associated with it and write NULL to + * the provided pointer. + */ +void avcodec_free_context(AVCodecContext **avctx); + /** * Set the fields of the given AVCodecContext to default values corresponding * to the given codec (defaults may be codec-dependent). @@ -3583,14 +3674,14 @@ int av_dup_packet(AVPacket *pkt); * * @return 0 on success, negative AVERROR on fail */ -int av_copy_packet(AVPacket *dst, AVPacket *src); +int av_copy_packet(AVPacket *dst, const AVPacket *src); /** * Copy packet side data * * @return 0 on success, negative AVERROR on fail */ -int av_copy_packet_side_data(AVPacket *dst, AVPacket *src); +int av_copy_packet_side_data(AVPacket *dst, const AVPacket *src); /** * Free a packet. @@ -3679,7 +3770,7 @@ void av_packet_free_side_data(AVPacket *pkt); * * @return 0 on success, a negative AVERROR on error. */ -int av_packet_ref(AVPacket *dst, AVPacket *src); +int av_packet_ref(AVPacket *dst, const AVPacket *src); /** * Wipe the packet. @@ -3715,6 +3806,19 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src); */ int av_packet_copy_props(AVPacket *dst, const AVPacket *src); +/** + * Convert valid timing fields (timestamps / durations) in a packet from one + * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be + * ignored. + * + * @param pkt packet on which the conversion will be performed + * @param tb_src source timebase, in which the timing fields in pkt are + * expressed + * @param tb_dst destination timebase, to which the timing fields will be + * converted + */ +void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst); + /** * @} */ @@ -3983,8 +4087,8 @@ int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, * marked with CODEC_CAP_DELAY, then no subtitles will be returned. * * @param avctx the codec context - * @param[out] sub The AVSubtitle in which the decoded subtitle will be stored, must be - freed with avsubtitle_free if *got_sub_ptr is set. + * @param[out] sub The Preallocated AVSubtitle in which the decoded subtitle will be stored, + * must be freed with avsubtitle_free if *got_sub_ptr is set. * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. * @param[in] avpkt The input AVPacket containing the input buffer. */ @@ -4647,30 +4751,8 @@ void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int */ unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt); -#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ -#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ -#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ -#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ -#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ -#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ - /** - * Compute what kind of losses will occur when converting from one specific - * pixel format to another. - * When converting from one pixel format to another, information loss may occur. - * For example, when converting from RGB24 to GRAY, the color information will - * be lost. Similarly, other losses occur when converting from some formats to - * other formats. These losses can involve loss of chroma, but also loss of - * resolution, loss of color depth, loss due to the color space conversion, loss - * of the alpha bits or loss due to color quantization. - * avcodec_get_fix_fmt_loss() informs you about the various types of losses - * which will occur when converting from one pixel format to another. - * - * @param[in] dst_pix_fmt destination pixel format - * @param[in] src_pix_fmt source pixel format - * @param[in] has_alpha Whether the source pixel format alpha channel is used. - * @return Combination of flags informing you what kind of losses will occur - * (maximum loss for an invalid dst_pix_fmt). + * @deprecated see av_get_pix_fmt_loss() */ int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt, int has_alpha); @@ -4697,34 +4779,7 @@ enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *p int has_alpha, int *loss_ptr); /** - * Find the best pixel format to convert to given a certain source pixel - * format and a selection of two destination pixel formats. When converting from - * one pixel format to another, information loss may occur. For example, when converting - * from RGB24 to GRAY, the color information will be lost. Similarly, other losses occur when - * converting from some formats to other formats. avcodec_find_best_pix_fmt_of_2() selects which of - * the given pixel formats should be used to suffer the least amount of loss. - * - * If one of the destination formats is AV_PIX_FMT_NONE the other pixel format (if valid) will be - * returned. - * - * @code - * src_pix_fmt = AV_PIX_FMT_YUV420P; - * dst_pix_fmt1= AV_PIX_FMT_RGB24; - * dst_pix_fmt2= AV_PIX_FMT_GRAY8; - * dst_pix_fmt3= AV_PIX_FMT_RGB8; - * loss= FF_LOSS_CHROMA; // don't care about chroma loss, so chroma loss will be ignored. - * dst_pix_fmt = avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, alpha, &loss); - * dst_pix_fmt = avcodec_find_best_pix_fmt_of_2(dst_pix_fmt, dst_pix_fmt3, src_pix_fmt, alpha, &loss); - * @endcode - * - * @param[in] dst_pix_fmt1 One of the two destination pixel formats to choose from - * @param[in] dst_pix_fmt2 The other of the two destination pixel formats to choose from - * @param[in] src_pix_fmt Source pixel format - * @param[in] has_alpha Whether the source pixel format alpha channel is used. - * @param[in, out] loss_ptr Combination of loss flags. In: selects which of the losses to ignore, i.e. - * NULL or value of zero means we care about all losses. Out: the loss - * that occurs when converting from src to selected dst pixel format. - * @return The best pixel format to convert to or -1 if none was found. + * @deprecated see av_find_best_pix_fmt_of_2() */ enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); @@ -4918,7 +4973,7 @@ AVBitStreamFilterContext *av_bitstream_filter_init(const char *name); * @return >= 0 in case of success, or a negative error code in case of failure * * If the return value is positive, an output buffer is allocated and - * is availble in *poutbuf, and is distinct from the input buffer. + * is available in *poutbuf, and is distinct from the input buffer. * * If the return value is 0, the output buffer is not allocated and * should be considered identical to the input buffer, or in case diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index 3d05dff56..a87e8e3ea 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -24,6 +24,7 @@ #include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/internal.h" +#include "libavutil/mathematics.h" #include "libavutil/mem.h" #include "avcodec.h" #include "bytestream.h" @@ -190,7 +191,7 @@ do { \ } while (0) /* Makes duplicates of data, side_data, but does not copy any other fields */ -static int copy_packet_data(AVPacket *pkt, AVPacket *src, int dup) +static int copy_packet_data(AVPacket *pkt, const AVPacket *src, int dup) { pkt->data = NULL; pkt->side_data = NULL; @@ -220,7 +221,7 @@ failed_alloc: return AVERROR(ENOMEM); } -int av_copy_packet_side_data(AVPacket *pkt, AVPacket *src) +int av_copy_packet_side_data(AVPacket *pkt, const AVPacket *src) { if (src->side_data_elems) { int i; @@ -262,7 +263,7 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } -int av_copy_packet(AVPacket *dst, AVPacket *src) +int av_copy_packet(AVPacket *dst, const AVPacket *src) { *dst = *src; return copy_packet_data(dst, src, 0); @@ -394,7 +395,7 @@ int av_packet_split_side_data(AVPacket *pkt){ p-= size+5; } - pkt->side_data = av_malloc(i * sizeof(*pkt->side_data)); + pkt->side_data = av_malloc_array(i, sizeof(*pkt->side_data)); if (!pkt->side_data) return AVERROR(ENOMEM); @@ -533,7 +534,7 @@ void av_packet_unref(AVPacket *pkt) pkt->size = 0; } -int av_packet_ref(AVPacket *dst, AVPacket *src) +int av_packet_ref(AVPacket *dst, const AVPacket *src) { int ret; @@ -562,3 +563,15 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src) *dst = *src; av_init_packet(src); } + +void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) +{ + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb); + if (pkt->dts != AV_NOPTS_VALUE) + 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 (pkt->convergence_duration > 0) + pkt->convergence_duration = av_rescale_q(pkt->convergence_duration, src_tb, dst_tb); +} diff --git a/libavcodec/bfin/Makefile b/libavcodec/bfin/Makefile deleted file mode 100644 index fc5f50665..000000000 --- a/libavcodec/bfin/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -OBJS += bfin/dsputil_bfin.o \ - bfin/fdct_bfin.o \ - bfin/idct_bfin.o \ - bfin/pixels_bfin.o \ - -OBJS-$(CONFIG_HPELDSP) += bfin/hpeldsp_bfin.o \ - bfin/hpel_pixels_bfin.o -OBJS-$(CONFIG_VP3DSP) += bfin/vp3_bfin.o \ - bfin/vp3_idct_bfin.o diff --git a/libavcodec/bfin/README b/libavcodec/bfin/README new file mode 100644 index 000000000..afb3461b7 --- /dev/null +++ b/libavcodec/bfin/README @@ -0,0 +1,6 @@ +BFIN optimizations have been removed in +commit 880e2aa23645ed9871c66ee1cbd00f93c72d2d73 +The last revission with the optimizations is fa4e17c14035ebf43130fb369e1728cdd98d0b72 + +If you want to maintain these (or other) BFIN optimizations in ffmpeg, then please +contact ffmpeg-devel@ffmpeg.org diff --git a/libavcodec/bfin/config_bfin.h b/libavcodec/bfin/config_bfin.h deleted file mode 100644 index 36439530e..000000000 --- a/libavcodec/bfin/config_bfin.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2007 Marc Hoffman - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -/* - low level assembler interface wrapper - -DEFUN(put_pixels_clamped,mL1, - (int16_t *block, uint8_t *dest, int line_size)): - - body - - rts; -*/ - -#ifndef AVCODEC_BFIN_CONFIG_BFIN_H -#define AVCODEC_BFIN_CONFIG_BFIN_H - -#include "config.h" - -#ifndef DEFUN - -#define mL3 .text -#ifndef mL1 -#if defined(__FDPIC__) && CONFIG_SRAM -#define mL1 .l1.text -#else -#define mL1 mL3 -#endif -#endif - -#define DEFUN(fname,where,interface) \ - .section where; \ - .global _ff_bfin_ ## fname ; \ - .type _ff_bfin_ ## fname, STT_FUNC; \ - .align 8; \ - _ff_bfin_ ## fname - -#define DEFUN_END(fname) \ - .size _ff_bfin_ ## fname, . - _ff_bfin_ ## fname - -#ifdef __FDPIC__ -#define RELOC(reg,got,obj) reg = [got + obj@GOT17M4] -#else -#define RELOC(reg,got,obj) reg.L = obj; reg.H = obj -#endif - -#endif - -#endif /* AVCODEC_BFIN_CONFIG_BFIN_H */ diff --git a/libavcodec/bfin/dsputil_bfin.c b/libavcodec/bfin/dsputil_bfin.c deleted file mode 100644 index a95fd6b62..000000000 --- a/libavcodec/bfin/dsputil_bfin.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * BlackFin DSPUTILS - * - * Copyright (C) 2007 Marc Hoffman - * Copyright (c) 2006 Michael Benjamin - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/attributes.h" -#include "libavcodec/avcodec.h" -#include "libavcodec/dsputil.h" -#include "dsputil_bfin.h" - -int off; - -static void bfin_idct_add (uint8_t *dest, int line_size, int16_t *block) -{ - ff_bfin_idct (block); - ff_bfin_add_pixels_clamped (block, dest, line_size); -} - -static void bfin_idct_put (uint8_t *dest, int line_size, int16_t *block) -{ - ff_bfin_idct (block); - ff_bfin_put_pixels_clamped (block, dest, line_size); -} - - -static void bfin_clear_blocks (int16_t *blocks) -{ - // This is just a simple memset. - // - __asm__("P0=192; " - "I0=%0; " - "R0=0; " - "LSETUP(clear_blocks_blkfn_lab,clear_blocks_blkfn_lab)LC0=P0;" - "clear_blocks_blkfn_lab:" - "[I0++]=R0;" - ::"a" (blocks):"P0","I0","R0"); -} - -static int bfin_pix_abs16 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) -{ - return ff_bfin_z_sad16x16 (blk1,blk2,line_size,line_size,h); -} - -static int bfin_vsad_intra16 (void *c, uint8_t *blk1, uint8_t *dummy, int stride, int h) { - return ff_bfin_z_sad16x16 (blk1,blk1+stride,stride<<1,stride<<1,h); -} - -static int bfin_vsad (void *c, uint8_t *blk1, uint8_t *blk2, int stride, int h) { - return ff_bfin_z_sad16x16 (blk1,blk1+stride,stride<<1,stride<<1,h) - + ff_bfin_z_sad16x16 (blk2,blk2+stride,stride<<1,stride<<1,h); -} - -static uint8_t vtmp_blk[256] attribute_l1_data_b; - -static int bfin_pix_abs16_x2 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) -{ - ff_bfin_put_pixels16uc (vtmp_blk, blk2, blk2+1, 16, line_size, h); - return ff_bfin_z_sad16x16 (blk1, vtmp_blk, line_size, 16, h); -} - -static int bfin_pix_abs16_y2 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) -{ - ff_bfin_put_pixels16uc (vtmp_blk, blk2, blk2+line_size, 16, line_size, h); - return ff_bfin_z_sad16x16 (blk1, vtmp_blk, line_size, 16, h); -} - -static int bfin_pix_abs16_xy2 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) -{ - ff_bfin_z_put_pixels16_xy2 (vtmp_blk, blk2, 16, line_size, h); - return ff_bfin_z_sad16x16 (blk1, vtmp_blk, line_size, 16, h); -} - -static int bfin_pix_abs8 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) -{ - return ff_bfin_z_sad8x8 (blk1,blk2,line_size,line_size, h); -} - -static int bfin_pix_abs8_x2 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) -{ - ff_bfin_put_pixels8uc (vtmp_blk, blk2, blk2+1, 8, line_size, h); - return ff_bfin_z_sad8x8 (blk1, vtmp_blk, line_size, 8, h); -} - -static int bfin_pix_abs8_y2 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) -{ - ff_bfin_put_pixels8uc (vtmp_blk, blk2, blk2+line_size, 8, line_size, h); - return ff_bfin_z_sad8x8 (blk1, vtmp_blk, line_size, 8, h); -} - -static int bfin_pix_abs8_xy2 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) -{ - ff_bfin_z_put_pixels8_xy2 (vtmp_blk, blk2, 8, line_size, h); - return ff_bfin_z_sad8x8 (blk1, vtmp_blk, line_size, 8, h); -} - - -/* - decoder optimization - start on 2/11 100 frames of 352x240@25 compiled with no optimization -g debugging - 9.824s ~ 2.44x off - 6.360s ~ 1.58x off with -O2 - 5.740s ~ 1.43x off with idcts - - 2.64s 2/20 same sman.mp4 decode only - -*/ - -av_cold void ff_dsputil_init_bfin(DSPContext *c, AVCodecContext *avctx) -{ - const int high_bit_depth = avctx->bits_per_raw_sample > 8; - - c->diff_pixels = ff_bfin_diff_pixels; - c->put_pixels_clamped = ff_bfin_put_pixels_clamped; - c->add_pixels_clamped = ff_bfin_add_pixels_clamped; - - if (!high_bit_depth) - c->get_pixels = ff_bfin_get_pixels; - c->clear_blocks = bfin_clear_blocks; - c->pix_sum = ff_bfin_pix_sum; - c->pix_norm1 = ff_bfin_pix_norm1; - - c->sad[0] = bfin_pix_abs16; - c->sad[1] = bfin_pix_abs8; - -/* c->vsad[0] = bfin_vsad; */ -/* c->vsad[4] = bfin_vsad_intra16; */ - - /* TODO [0] 16 [1] 8 */ - c->pix_abs[0][0] = bfin_pix_abs16; - c->pix_abs[0][1] = bfin_pix_abs16_x2; - c->pix_abs[0][2] = bfin_pix_abs16_y2; - c->pix_abs[0][3] = bfin_pix_abs16_xy2; - - c->pix_abs[1][0] = bfin_pix_abs8; - c->pix_abs[1][1] = bfin_pix_abs8_x2; - c->pix_abs[1][2] = bfin_pix_abs8_y2; - c->pix_abs[1][3] = bfin_pix_abs8_xy2; - - - c->sse[0] = ff_bfin_sse16; - c->sse[1] = ff_bfin_sse8; - c->sse[2] = ff_bfin_sse4; - - if (avctx->bits_per_raw_sample <= 8) { - if (avctx->dct_algo == FF_DCT_AUTO) - c->fdct = ff_bfin_fdct; - - if (avctx->idct_algo == FF_IDCT_AUTO) { - c->idct_permutation_type = FF_NO_IDCT_PERM; - c->idct = ff_bfin_idct; - c->idct_add = bfin_idct_add; - c->idct_put = bfin_idct_put; - } - } -} diff --git a/libavcodec/bfin/dsputil_bfin.h b/libavcodec/bfin/dsputil_bfin.h deleted file mode 100644 index 079ebdda6..000000000 --- a/libavcodec/bfin/dsputil_bfin.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * BlackFin DSPUTILS COMMON OPTIMIZATIONS HEADER - * - * Copyright (C) 2007 Marc Hoffman - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifndef AVCODEC_BFIN_DSPUTIL_BFIN_H -#define AVCODEC_BFIN_DSPUTIL_BFIN_H - -#include - -#include "config.h" - -#if defined(__FDPIC__) && CONFIG_SRAM -#define attribute_l1_text __attribute__ ((l1_text)) -#define attribute_l1_data_b __attribute__((l1_data_B)) -#else -#define attribute_l1_text -#define attribute_l1_data_b -#endif - -void ff_bfin_idct (int16_t *block) attribute_l1_text; -void ff_bfin_fdct (int16_t *block) attribute_l1_text; -void ff_bfin_add_pixels_clamped (const int16_t *block, uint8_t *dest, int line_size) attribute_l1_text; -void ff_bfin_put_pixels_clamped (const int16_t *block, uint8_t *dest, int line_size) attribute_l1_text; -void ff_bfin_diff_pixels (int16_t *block, const uint8_t *s1, const uint8_t *s2, int stride) attribute_l1_text; -void ff_bfin_get_pixels (int16_t *restrict block, const uint8_t *pixels, int line_size) attribute_l1_text; -int ff_bfin_pix_norm1 (uint8_t * pix, int line_size) attribute_l1_text; -int ff_bfin_z_sad8x8 (uint8_t *blk1, uint8_t *blk2, int dsz, int line_size, int h) attribute_l1_text; -int ff_bfin_z_sad16x16 (uint8_t *blk1, uint8_t *blk2, int dsz, int line_size, int h) attribute_l1_text; - -int ff_bfin_pix_sum (uint8_t *p, int stride) attribute_l1_text; - -int ff_bfin_sse4 (void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) attribute_l1_text; -int ff_bfin_sse8 (void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) attribute_l1_text; -int ff_bfin_sse16 (void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) attribute_l1_text; - - -#ifdef BFIN_PROFILE - -static double Telem[16]; -static char *TelemNames[16]; -static int TelemCnt; - -#define PROF(lab,e) { int xx_e = e; char*xx_lab = lab; uint64_t xx_t0 = read_time(); -#define EPROF() xx_t0 = read_time()-xx_t0; Telem[xx_e] = Telem[xx_e] + xx_t0; TelemNames[xx_e] = xx_lab; } - -static void prof_report (void) -{ - int i; - double s = 0; - for (i=0;i<16;i++) { - double v; - if (TelemNames[i]) { - v = Telem[i]/TelemCnt; - av_log (NULL,AV_LOG_DEBUG,"%-20s: %12.4f\t%12.4f\n", TelemNames[i],v,v/64); - s = s + Telem[i]; - } - } - av_log (NULL,AV_LOG_DEBUG,"%-20s: %12.4f\t%12.4f\n%20.4f\t%d\n", - "total",s/TelemCnt,s/TelemCnt/64,s,TelemCnt); -} - -static void bfprof (void) -{ - static int init; - if (!init) atexit (prof_report); - init=1; - TelemCnt++; -} - -#else -#define PROF(a,b) -#define EPROF() -#define bfprof() -#endif - -#endif /* AVCODEC_BFIN_DSPUTIL_BFIN_H */ diff --git a/libavcodec/bfin/fdct_bfin.S b/libavcodec/bfin/fdct_bfin.S deleted file mode 100644 index 916957467..000000000 --- a/libavcodec/bfin/fdct_bfin.S +++ /dev/null @@ -1,332 +0,0 @@ -/* - * fdct BlackFin - * - * Copyright (C) 2007 Marc Hoffman - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -/* - void ff_bfin_fdct (int16_t *buf); - - This implementation works only for 8x8 input. The range of input - must be -256 to 255 i.e. 8bit input represented in a 16bit data - word. The original data must be sign extended into the 16bit data - words. - - - Chen factorization of - - 8 - X(m) = sum (x(n) * cos ((2n+1)*m*pi/16)) - n=0 - - C4 - 0 --*-------------*0+7---*-----*0+3-------*-*-------------------> 0 - \ / \ / X S4,S4 - 1 --*-\---------/-*1+6---*-\-/-*1+2-------*-*-------------------> 4 - \ / \ -C4 C3 - 2 --*---\-----/---*2+5---*-/-\-*1-2---------------*-*-----------> 2 - \ / / \ X S3,-S3 - 3 --*-----\-/-----*3+4---*-----*0-3---------------*-*-----------> 6 - / C7 C3 - 4 --*-----/-\-----*3-4------------*-*4+5--*-----*---------------> 1 - / \ -C4 X \ /S7 C3 - 5 --*---/-----\---*2-5---*-*------*=*4-5----\-/------*-*--------> 5 - / \ X S4,S4 / X S3,-S3 - 6 --*-/---------\-*1-6---*-*------*=*7-6----/-\------*-*--------> 3 - / \ C4 X / \-S7 C3 - --*-------------*0-7------------*-*7+6--*-----*---------------> 7 - C7 - -Notation - Cn = cos(n*pi/8) used throughout the code. - - - Registers used: - R0, R1, R2, R3, R4, R5, R6,R7, P0, P1, P2, P3, P4, P5, A0, A1. - Other registers used: - I0, I1, I2, I3, B0, B2, B3, M0, M1, L3 registers and LC0. - - Input - r0 - pointer to start of int16_t *block - - Output - The DCT output coefficients in the int16_t *block - - Register constraint: - This code is called from jpeg_encode. - R6, R5, R4 if modified should be stored and restored. - - - Performance: (Timer version 0.6.33) - Code Size : 240 Bytes. - Memory Required : - Input Matrix : 8 * 8 * 2 Bytes. - Coefficients : 16 Bytes - Temporary matrix: 8 * 8 * 2 Bytes. - Cycle Count :26+{18+8*(14+2S)}*2 where S -> Stalls - (7.45 c/pel) - ----------------------------------------- - | Size | Forward DCT | Inverse DCT | - ----------------------------------------- - | 8x8 | 284 Cycles | 311 Cycles | - ----------------------------------------- - -Ck = int16(cos(k/16*pi)*32767+.5)/2 -#define C4 23170 -#define C3 13623 -#define C6 6270 -#define C7 3196 - -Sk = int16(sin(k/16*pi)*32767+.5)/2 -#define S4 11585 -#define S3 9102 -#define S6 15137 -#define S7 16069 - -the coefficients are ordered as follows: -short dct_coef[] - C4,S4, - C6,S6, - C7,S7, - S3,C3, - ------------------------------------------------------------ -FFMPEG conformance testing results ------------------------------------------------------------ -dct-test: modified with the following - dct_error("BFINfdct", 0, ff_bfin_fdct, fdct, test); -produces the following output: - -root:/u/ffmpeg/bhead/libavcodec> ./dct-test -ffmpeg DCT/IDCT test - - 2 -131 -6 -48 -36 33 -83 24 - 34 52 -24 -15 5 92 57 143 - -67 -43 -1 74 -16 5 -71 32 - -78 106 92 -34 -38 81 20 -18 - 7 -62 40 2 -15 90 -62 -83 - -83 1 -104 -13 43 -19 7 11 - -63 31 12 -29 83 72 21 10 - -17 -63 -15 73 50 -91 159 -14 -DCT BFINfdct: err_inf=2 err2=0.16425938 syserr=0.00795000 maxout=2098 blockSumErr=27 -DCT BFINfdct: 92.1 kdct/s -root:/u/ffmpeg/bhead/libavcodec> - -*/ - -#include "config.h" -#include "config_bfin.h" - -#if defined(__FDPIC__) && CONFIG_SRAM -.section .l1.data.B,"aw",@progbits -#else -.data -#endif -.align 4; -dct_coeff: -.short 0x5a82, 0x2d41, 0x187e, 0x3b21, 0x0c7c, 0x3ec5, 0x238e, 0x3537; - -#if defined(__FDPIC__) && CONFIG_SRAM -.section .l1.data.A,"aw",@progbits -#endif -.align 4 -vtmp: .space 128 - -.text -DEFUN(fdct,mL1, - (int16_t *block)): - [--SP] = (R7:4, P5:3); // Push the registers onto the stack. - - b0 = r0; - RELOC(r0, P3, dct_coeff); - b3 = r0; - RELOC(r0, P3, vtmp); - b2 = r0; - - L3 = 16; // L3 is set to 16 to make the coefficient - // array Circular. - - -//---------------------------------------------------------------------------- - -/* - * I0, I1, and I2 registers are used to read the input data. I3 register is used - * to read the coefficients. P0 and P1 registers are used for writing the output - * data. - */ - M0 = 12 (X); // All these initializations are used in the - M1 = 16 (X); // modification of address offsets. - - M2 = 128 (X); - - P2 = 16; - P3 = 32 (X); - P4 = -110 (X); - P5 = -62 (X); - P0 = 2(X); - - - // Prescale the input to get the correct precision. - i0=b0; - i1=b0; - - lsetup (.0, .1) LC0 = P3; - r0=[i0++]; -.0: r1=r0<<3 (v) || r0=[i0++] ; -.1: [i1++]=r1; - - /* - * B0 points to the "in" buffer. - * B2 points to "temp" buffer in the first iteration. - */ - - lsetup (.2, .3) LC0 = P0; -.2: - I0 = B0; // I0 points to Input Element (0, 0). - I1 = B0; // Element 1 and 0 is read in R0. - I1 += M0 || R0 = [I0++]; // I1 points to Input Element (0, 6). - I2 = I1; // Element 6 is read into R3.H. - I2 -= 4 || R3.H = W[I1++]; // I2 points to Input Element (0, 4). - - I3 = B3; // I3 points to Coefficients. - P0 = B2; // P0 points to temporary array Element - // (0, 0). - P1 = B2; // P1 points to temporary array. - R7 = [P1++P2] || R2 = [I2++]; // P1 points to temporary array - // Element (1, 0). - // R7 is a dummy read. X4,X5 - // are read into R2. - R3.L = W[I1--]; // X7 is read into R3.L. - R1.H = W[I0++]; // X2 is read into R1.H. - - - /* - * X0 = (X0 + X7) / 2. - * X1 = (X1 + X6) / 2. - * X6 = (X1 - X6) / 2. - * X7 = (X0 - X7) / 2. - * It reads the data 3 in R1.L. - */ - - R0 = R0 +|+ R3, R3 = R0 -|- R3 || R1.L = W[I0++] || NOP; - - /* - * X2 = (X2 + X5) / 2. - * X3 = (X3 + X4) / 2. - * X4 = (X3 - X4) / 2. - * X5 = (X2 - X5) / 2. - * R7 = C4 = cos(4*pi/16) - */ - - R1 = R1 +|+ R2, R2 = R1 -|- R2 (CO) || NOP || R7 = [I3++]; - - /* - * At the end of stage 1 R0 has (1,0), R1 has (2,3), R2 has (4, 5) and - * R3 has (6,7). - * Where the notation (x, y) represents uper/lower half pairs. - */ - - /* - * X0 = X0 + X3. - * X1 = X1 + X2. - * X2 = X1 - X2. - * X3 = X0 - X3. - */ - R0 = R0 +|+ R1, R1 = R0 -|- R1; - - lsetup (.row0, .row1) LC1 = P2 >> 1; // 1d dct, loops 8x -.row0: - - /* - * This is part 2 computation continued..... - * A1 = X6 * cos(pi/4) - * A0 = X6 * cos(pi/4) - * A1 = A1 - X5 * cos(pi/4) - * A0 = A0 + X5 * cos(pi/4). - * The instruction W[I0] = R3.L is used for packing it to R2.L. - */ - - A1=R3.H*R7.l, A0=R3.H*R7.l || I1+=M1 || W[I0] = R3.L; - R4.H=(A1-=R2.L*R7.l), R4.L=(A0+=R2.L*R7.l) || I2+=M0 || NOP; - - /* R0 = (X1,X0) R1 = (X2,X3) R4 = (X5, X6). */ - - /* - * A1 = X0 * cos(pi/4) - * A0 = X0 * cos(pi/4) - * A1 = A1 - X1 * cos(pi/4) - * A0 = A0 + X1 * cos(pi/4) - * R7 = (C2,C6) - */ - A1=R0.L*R7.h, A0=R0.L*R7.h || NOP || R3.H=W[I1++]; - R5.H=(A1-=R0.H*R7.h),R5.L=(A0+=R0.H*R7.h) || R7=[I3++] || NOP; - - /* - * A1 = X2 * cos(3pi/8) - * A0 = X3 * cos(3pi/8) - * A1 = A1 + X3 * cos(pi/8) - * A0 = A0 - X2 * cos(pi/8) - * R3 = cos(pi/4) - * R7 = (cos(7pi/8),cos(pi/8)) - * X4 = X4 + X5. - * X5 = X4 - X5. - * X6 = X7 - X6. - * X7 = X7 + X6. - */ - A1=R1.H*R7.L, A0=R1.L*R7.L || W[P0++P3]=R5.L || R2.L=W[I0]; - R2=R2+|+R4, R4=R2-|-R4 || I0+=4 || R3.L=W[I1--]; - R6.H=(A1+=R1.L*R7.H),R6.L=(A0 -= R1.H * R7.H) || I0+=4 || R7=[I3++]; - - /* R2 = (X4, X7) R4 = (X5,X6) R5 = (X1, X0) R6 = (X2,X3). */ - - /* - * A1 = X4 * cos(7pi/16) - * A0 = X7 * cos(7pi/16) - * A1 = A1 + X7 * cos(pi/16) - * A0 = A0 - X4 * cos(pi/16) - */ - - A1=R2.H*R7.L, A0=R2.L*R7.L || W[P0++P3]=R6.H || R0=[I0++]; - R2.H=(A1+=R2.L*R7.H),R2.L=(A0-=R2.H*R7.H) || W[P0++P3]=R5.H || R7=[I3++]; - - /* - * A1 = X5 * cos(3pi/16) - * A0 = X6 * cos(3pi/16) - * A1 = A1 + X6 * cos(5pi/16) - * A0 = A0 - X5 * cos(5pi/16) - * The output values are written. - */ - - A1=R4.H*R7.H, A0=R4.L*R7.H || W[P0++P2]=R6.L || R1.H=W[I0++]; - R4.H=(A1+=R4.L*R7.L),R4.L=(A0-=R4.H*R7.L) || W[P0++P4]=R2.L || R1.L=W[I0++]; - - - /* Beginning of next stage, **pipelined** + drain and store the - rest of the column store. */ - - R0=R0+|+R3,R3=R0-|-R3 || W[P1++P3]=R2.H || R2=[I2++]; - R1=R1+|+R2,R2=R1-|-R2 (CO) || W[P1++P3]=R4.L || R7=[I3++]; -.row1: R0=R0+|+R1,R1=R0-|-R1 || W[P1++P5]=R4.H || NOP; - - // Exchange input with output. - B1 = B0; - B0 = B2; -.3: B2 = B1; - - L3=0; - (r7:4,p5:3) = [sp++]; - RTS; -DEFUN_END(fdct) diff --git a/libavcodec/bfin/hpel_pixels_bfin.S b/libavcodec/bfin/hpel_pixels_bfin.S deleted file mode 100644 index c0cbf1f7f..000000000 --- a/libavcodec/bfin/hpel_pixels_bfin.S +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Blackfin Pixel Operations - * Copyright (C) 2007 Marc Hoffman - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include "config_bfin.h" - -/* - motion compensation - primitives - - * Halfpel motion compensation with rounding (a+b+1)>>1. - * This is an array[4][4] of motion compensation funcions for 4 - * horizontal blocksizes (8,16) and the 4 halfpel positions
- * *pixels_tab[ 0->16xH 1->8xH ][ xhalfpel + 2*yhalfpel ] - * @param block destination where the result is stored - * @param pixels source - * @param line_size number of bytes in a horizontal line of block - * @param h height - -*/ - -DEFUN(put_pixels8uc,mL1, - (uint8_t *block, const uint8_t *s0, const uint8_t *s1, - int dest_size, int line_size, int h)): - i3=r0; // dest - i0=r1; // src0 - i1=r2; // src1 - r0=[sp+12]; // dest_size - r2=[sp+16]; // line_size - p0=[sp+20]; // h - [--sp] = (r7:6); - r0+=-4; - m3=r0; - r2+=-8; - m0=r2; - LSETUP(pp8$0,pp8$1) LC0=P0; - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - -pp8$0: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; - R6 = BYTEOP1P(R1:0,R3:2) || R0 = [I0++M0]|| R2 =[I1++M0]; - R7 = BYTEOP1P(R1:0,R3:2)(R) || R0 = [I0++] || [I3++] = R6 ; -pp8$1: DISALGNEXCPT || R2 = [I1++] || [I3++M3] = R7; - - (r7:6) = [sp++]; - RTS; -DEFUN_END(put_pixels8uc) - -DEFUN(put_pixels16uc,mL1, - (uint8_t *block, const uint8_t *s0, const uint8_t *s1, - int dest_size, int line_size, int h)): - link 0; - [--sp] = (r7:6); - i3=r0; // dest - i0=r1; // src0 - i1=r2; // src1 - r0=[fp+20]; // dest_size - r2=[fp+24]; // line_size - p0=[fp+28]; // h - - - r0+=-12; - m3=r0; // line_size - r2+=-16; - m0=r2; - - LSETUP(pp16$0,pp16$1) LC0=P0; - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - -pp16$0: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; - R6 = BYTEOP1P(R1:0,R3:2) || R0 = [I0++] || R2 =[I1++]; - R7 = BYTEOP1P(R1:0,R3:2)(R) || R1 = [I0++] || R3 =[I1++]; - [I3++] = R6; - R6 = BYTEOP1P(R1:0,R3:2) || R0 = [I0++M0] || R2 =[I1++M0]; - R7 = BYTEOP1P(R1:0,R3:2)(R) || R0 = [I0++] || [I3++] = R7 ; - [I3++] = R6; -pp16$1: DISALGNEXCPT || R2 = [I1++] || [I3++M3] = R7; - - (r7:6) = [sp++]; - unlink; - RTS; -DEFUN_END(put_pixels16uc) - - - - - - -DEFUN(put_pixels8uc_nornd,mL1, - (uint8_t *block, const uint8_t *s0, const uint8_t *s1, - int line_size, int h)): - i3=r0; // dest - i0=r1; // src0 - i1=r2; // src1 - r2=[sp+12]; // line_size - p0=[sp+16]; // h - [--sp] = (r7:6); - r2+=-4; - m3=r2; - r2+=-4; - m0=r2; - LSETUP(pp8$2,pp8$3) LC0=P0; - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - -pp8$2: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; - R6 = BYTEOP1P(R1:0,R3:2)(T) || R0 = [I0++M0]|| R2 =[I1++M0]; - R7 = BYTEOP1P(R1:0,R3:2)(T,R) || R0 = [I0++] || [I3++] = R6 ; -pp8$3: DISALGNEXCPT || R2 = [I1++] || [I3++M3] = R7; - - (r7:6) = [sp++]; - RTS; -DEFUN_END(put_pixels8uc_nornd) - -DEFUN(put_pixels16uc_nornd,mL1, - (uint8_t *block, const uint8_t *s0, const uint8_t *s1, - int line_size, int h)): - i3=r0; // dest - i0=r1; // src0 - i1=r2; // src1 - r2=[sp+12]; // line_size - p0=[sp+16]; // h - - [--sp] = (r7:6); - r2+=-12; - m3=r2; // line_size - r2+=-4; - m0=r2; - - LSETUP(pp16$2,pp16$3) LC0=P0; - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - -pp16$2: - DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; - R6 = BYTEOP1P(R1:0,R3:2)(T) || R0 = [I0++] || R2 =[I1++]; - R7 = BYTEOP1P(R1:0,R3:2)(T,R) || R1 = [I0++] || R3 =[I1++]; - [I3++] = R6; - - R6 = BYTEOP1P(R1:0,R3:2)(T) || R0 = [I0++M0] || R2 =[I1++M0]; - R7 = BYTEOP1P(R1:0,R3:2)(T,R) || R0 = [I0++] || [I3++] = R7 ; - [I3++] = R6; -pp16$3: DISALGNEXCPT || R2 = [I1++] || [I3++M3] = R7; - - (r7:6) = [sp++]; - - RTS; -DEFUN_END(put_pixels16uc_nornd) - -DEFUN(z_put_pixels16_xy2,mL1, - (uint8_t *block, const uint8_t *s0, - int dest_size, int line_size, int h)): - link 0; - [--sp] = (r7:4); - i3=r0; // dest - i0=r1; // src0--> pixels - i1=r1; // src1--> pixels + line_size - r2+=-12; - m2=r2; // m2=dest_width-4 - r2=[fp+20]; - m3=r2; // line_size - p0=[fp+24]; // h - r2+=-16; - i1+=m3; /* src1 + line_size */ - m0=r2; /* line-size - 20 */ - - B0 = I0; - B1 = I1; - B3 = I3; - - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - - LSETUP(LS$16E,LE$16E) LC0=P0; -LS$16E: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; - R4 = BYTEOP2P (R3:2,R1:0) (RNDL) || R0 = [I0++] || R2 =[I1++]; - R5 = BYTEOP2P (R3:2,R1:0) (RNDL,R) || R1 = [I0++] || [I3++] = R4 ; - DISALGNEXCPT || R3 = [I1++] || [I3++] = R5; - R4 = BYTEOP2P (R3:2,R1:0) (RNDL) || R0 = [I0++M0]|| R2 = [I1++M0]; - R5 = BYTEOP2P (R3:2,R1:0) (RNDL,R) || R0 = [I0++] || [I3++] = R4 ; -LE$16E: DISALGNEXCPT || R2 = [I1++] || [I3++M2] = R5; - - M1 = 1; - I3 = B3; - I1 = B1; - I0 = B0; - - I0 += M1; - I1 += M1; - - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - LSETUP(LS$16O,LE$16O) LC0=P0; -LS$16O: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; - R4 = BYTEOP2P (R3:2,R1:0) (RNDH) || R0 = [I0++] || R2 =[I1++]; - R5 = BYTEOP2P (R3:2,R1:0) (RNDH,R) || R1 = [I0++] || R6 =[I3++]; - R4 = R4 +|+ R6 || R7 = [I3--]; - R5 = R5 +|+ R7 || [I3++] = R4; - DISALGNEXCPT || R3 =[I1++] || [I3++] = R5; - R4 = BYTEOP2P (R3:2,R1:0) (RNDH) || R0 = [I0++M0]|| R2 = [I1++M0]; - R5 = BYTEOP2P (R3:2,R1:0) (RNDH,R) || R0 = [I0++] || R6 = [I3++]; - R4 = R4 +|+ R6 || R7 = [I3--]; - R5 = R5 +|+ R7 || [I3++] = R4; -LE$16O: DISALGNEXCPT || R2 = [I1++] || [I3++M2] = R5; - - (r7:4) = [sp++]; - unlink; - rts; -DEFUN_END(z_put_pixels16_xy2) - -DEFUN(put_pixels16_xy2_nornd,mL1, - (uint8_t *block, const uint8_t *s0, - int line_size, int h)): - link 0; - [--sp] = (r7:4); - i3=r0; // dest - i0=r1; // src0--> pixels - i1=r1; // src1--> pixels + line_size - m3=r2; - r2+=-12; - m2=r2; - r2+=-4; - i1+=m3; /* src1 + line_size */ - m0=r2; /* line-size - 20 */ - p0=[fp+20]; // h - - B0=I0; - B1=I1; - B3=I3; - - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - - LSETUP(LS$16ET,LE$16ET) LC0=P0; -LS$16ET:DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; - R4 = BYTEOP2P (R3:2,R1:0) (TL) || R0 = [I0++] || R2 =[I1++]; - R5 = BYTEOP2P (R3:2,R1:0) (TL,R) || R1 = [I0++] || [I3++] = R4 ; - DISALGNEXCPT || R3 = [I1++] || [I3++] = R5; - R4 = BYTEOP2P (R3:2,R1:0) (TL) || R0 = [I0++M0]|| R2 = [I1++M0]; - R5 = BYTEOP2P (R3:2,R1:0) (TL,R) || R0 = [I0++] || [I3++] = R4 ; -LE$16ET:DISALGNEXCPT || R2 = [I1++] || [I3++M2] = R5; - - M1 = 1; - I3=B3; - I1=B1; - I0=B0; - - I0 += M1; - I1 += M1; - - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - LSETUP(LS$16OT,LE$16OT) LC0=P0; -LS$16OT:DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; - R4 = BYTEOP2P (R3:2,R1:0) (TH) || R0 = [I0++] || R2 =[I1++]; - R5 = BYTEOP2P (R3:2,R1:0) (TH,R) || R1 = [I0++] || R6 =[I3++]; - R4 = R4 +|+ R6 || R7 = [I3--]; - R5 = R5 +|+ R7 || [I3++] = R4; - DISALGNEXCPT || R3 =[I1++] || [I3++] = R5; - R4 = BYTEOP2P (R3:2,R1:0) (TH) || R0 = [I0++M0]|| R2 = [I1++M0]; - R5 = BYTEOP2P (R3:2,R1:0) (TH,R) || R0 = [I0++] || R6 = [I3++]; - R4 = R4 +|+ R6 || R7 = [I3--]; - R5 = R5 +|+ R7 || [I3++] = R4; -LE$16OT:DISALGNEXCPT || R2 = [I1++] || [I3++M2] = R5; - - (r7:4) = [sp++]; - unlink; - rts; -DEFUN_END(put_pixels16_xy2_nornd) - -DEFUN(z_put_pixels8_xy2,mL1, - (uint8_t *block, const uint8_t *s0, - int dest_size, int line_size, int h)): - link 0; - [--sp] = (r7:4); - i3=r0; // dest - i0=r1; // src0--> pixels - i1=r1; // src1--> pixels + line_size - r2+=-4; - m2=r2; // m2=dest_width-4 - r2=[fp+20]; - m3=r2; // line_size - p0=[fp+24]; // h - r2+=-8; - i1+=m3; /* src1 + line_size */ - m0=r2; /* line-size - 20 */ - - b0 = I0; - b1 = I1; - b3 = I3; - - LSETUP(LS$8E,LE$8E) LC0=P0; - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; -LS$8E: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; - R4 = BYTEOP2P (R3:2,R1:0) (RNDL) || R0 = [I0++M0] || R2 =[I1++M0]; - R5 = BYTEOP2P (R3:2,R1:0) (RNDL,R) || R0 = [I0++] || [I3++] = R4 ; -LE$8E: DISALGNEXCPT || R2 = [I1++] || [I3++M2] = R5; - - M1 = 1; - I3 = b3; - I1 = b1; - I0 = b0; - - I0 += M1; - I1 += M1; - - LSETUP(LS$8O,LE$8O) LC0=P0; - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; -LS$8O: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; - R4 = BYTEOP2P (R3:2,R1:0) (RNDH) || R0 = [I0++M0] || R2 =[I1++M0]; - R5 = BYTEOP2P (R3:2,R1:0) (RNDH,R) || R0 = [I0++] || R6 =[I3++]; - R4 = R4 +|+ R6 || R7 = [I3--]; - R5 = R5 +|+ R7 || [I3++] = R4; -LE$8O: DISALGNEXCPT || R2 =[I1++] || [I3++M2] = R5; - - (r7:4) = [sp++]; - unlink; - rts; -DEFUN_END(z_put_pixels8_xy2) - -DEFUN(put_pixels8_xy2_nornd,mL1, - (uint8_t *block, const uint8_t *s0, int line_size, int h)): - link 0; - [--sp] = (r7:4); - i3=r0; // dest - i0=r1; // src0--> pixels - i1=r1; // src1--> pixels + line_size - m3=r2; - r2+=-4; - m2=r2; - r2+=-4; - i1+=m3; /* src1 + line_size */ - m0=r2; /* line-size - 20 */ - p0=[fp+20]; // h - - - b0 = I0; - b1 = I1; - b3 = I3; - - LSETUP(LS$8ET,LE$8ET) LC0=P0; - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - -LS$8ET: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; - R4 = BYTEOP2P (R3:2,R1:0) (TL) || R0 = [I0++M0] || R2 = [I1++M0]; - R5 = BYTEOP2P (R3:2,R1:0) (TL,R) || R0 = [I0++] || [I3++] = R4 ; -LE$8ET: DISALGNEXCPT || R2 = [I1++] || [I3++M2] = R5; - - M1 = 1; - I3 = b3; - I1 = b1; - I0 = b0; - - I0 += M1; - I1 += M1; - - LSETUP(LS$8OT,LE$8OT) LC0=P0; - DISALGNEXCPT || R0 = [I0++] || R2 = [I1++]; - -LS$8OT: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; - R4 = BYTEOP2P (R3:2,R1:0) (TH) || R0 = [I0++M0] || R2 = [I1++M0]; - R5 = BYTEOP2P (R3:2,R1:0) (TH,R) || R0 = [I0++] || R6 = [I3++]; - R4 = R4 +|+ R6 || R7 = [I3--]; - R5 = R5 +|+ R7 || [I3++] = R4; -LE$8OT: DISALGNEXCPT || R2 =[I1++] || [I3++M2] = R5; - - (r7:4) = [sp++]; - unlink; - rts; -DEFUN_END(put_pixels8_xy2_nornd) diff --git a/libavcodec/bfin/hpeldsp_bfin.c b/libavcodec/bfin/hpeldsp_bfin.c deleted file mode 100644 index 2df551b89..000000000 --- a/libavcodec/bfin/hpeldsp_bfin.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * BlackFin DSPUTILS - * - * Copyright (C) 2007 Marc Hoffman - * Copyright (c) 2006 Michael Benjamin - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include "libavutil/attributes.h" -#include "libavcodec/hpeldsp.h" -#include "hpeldsp_bfin.h" - -static void bfin_put_pixels8 (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -{ - ff_bfin_put_pixels8uc (block, pixels, pixels, line_size, line_size, h); -} - -static void bfin_put_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -{ - ff_bfin_put_pixels8uc (block, pixels, pixels+1, line_size, line_size, h); -} - -static void bfin_put_pixels8_y2 (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -{ - ff_bfin_put_pixels8uc (block, pixels, pixels+line_size, line_size, line_size, h); -} - -static void bfin_put_pixels8_xy2 (uint8_t *block, const uint8_t *s0, ptrdiff_t line_size, int h) -{ - ff_bfin_z_put_pixels8_xy2 (block,s0,line_size, line_size, h); -} - -static void bfin_put_pixels16 (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -{ - ff_bfin_put_pixels16uc (block, pixels, pixels, line_size, line_size, h); -} - -static void bfin_put_pixels16_x2 (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -{ - ff_bfin_put_pixels16uc (block, pixels, pixels+1, line_size, line_size, h); -} - -static void bfin_put_pixels16_y2 (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -{ - ff_bfin_put_pixels16uc (block, pixels, pixels+line_size, line_size, line_size, h); -} - -static void bfin_put_pixels16_xy2 (uint8_t *block, const uint8_t *s0, ptrdiff_t line_size, int h) -{ - ff_bfin_z_put_pixels16_xy2 (block,s0,line_size, line_size, h); -} - -static void bfin_put_pixels8_nornd (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -{ - ff_bfin_put_pixels8uc_nornd (block, pixels, pixels, line_size, h); -} - -static void bfin_put_pixels8_x2_nornd (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -{ - ff_bfin_put_pixels8uc_nornd (block, pixels, pixels+1, line_size, h); -} - -static void bfin_put_pixels8_y2_nornd (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -{ - ff_bfin_put_pixels8uc_nornd (block, pixels, pixels+line_size, line_size, h); -} - - -static void bfin_put_pixels16_nornd (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -{ - ff_bfin_put_pixels16uc_nornd (block, pixels, pixels, line_size, h); -} - -static void bfin_put_pixels16_x2_nornd (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -{ - ff_bfin_put_pixels16uc_nornd (block, pixels, pixels+1, line_size, h); -} - -static void bfin_put_pixels16_y2_nornd (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -{ - ff_bfin_put_pixels16uc_nornd (block, pixels, pixels+line_size, line_size, h); -} - -av_cold void ff_hpeldsp_init_bfin(HpelDSPContext *c, int flags) -{ - c->put_pixels_tab[0][0] = bfin_put_pixels16; - c->put_pixels_tab[0][1] = bfin_put_pixels16_x2; - c->put_pixels_tab[0][2] = bfin_put_pixels16_y2; - c->put_pixels_tab[0][3] = bfin_put_pixels16_xy2; - - c->put_pixels_tab[1][0] = bfin_put_pixels8; - c->put_pixels_tab[1][1] = bfin_put_pixels8_x2; - c->put_pixels_tab[1][2] = bfin_put_pixels8_y2; - c->put_pixels_tab[1][3] = bfin_put_pixels8_xy2; - - c->put_no_rnd_pixels_tab[1][0] = bfin_put_pixels8_nornd; - c->put_no_rnd_pixels_tab[1][1] = bfin_put_pixels8_x2_nornd; - c->put_no_rnd_pixels_tab[1][2] = bfin_put_pixels8_y2_nornd; -/* c->put_no_rnd_pixels_tab[1][3] = ff_bfin_put_pixels8_xy2_nornd; */ - - c->put_no_rnd_pixels_tab[0][0] = bfin_put_pixels16_nornd; - c->put_no_rnd_pixels_tab[0][1] = bfin_put_pixels16_x2_nornd; - c->put_no_rnd_pixels_tab[0][2] = bfin_put_pixels16_y2_nornd; -/* c->put_no_rnd_pixels_tab[0][3] = ff_bfin_put_pixels16_xy2_nornd; */ -} diff --git a/libavcodec/bfin/hpeldsp_bfin.h b/libavcodec/bfin/hpeldsp_bfin.h deleted file mode 100644 index 36f38722d..000000000 --- a/libavcodec/bfin/hpeldsp_bfin.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * BlackFin DSPUTILS COMMON OPTIMIZATIONS HEADER - * - * Copyright (C) 2007 Marc Hoffman - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifndef AVCODEC_BFIN_HPELDSP_BFIN_H -#define AVCODEC_BFIN_HPELDSP_BFIN_H - -#include - -#include "config.h" - -#if defined(__FDPIC__) && CONFIG_SRAM -#define attribute_l1_text __attribute__ ((l1_text)) -#define attribute_l1_data_b __attribute__((l1_data_B)) -#else -#define attribute_l1_text -#define attribute_l1_data_b -#endif - -void ff_bfin_z_put_pixels16_xy2 (uint8_t *block, const uint8_t *s0, int dest_size, int line_size, int h) attribute_l1_text; -void ff_bfin_z_put_pixels8_xy2 (uint8_t *block, const uint8_t *s0, int dest_size, int line_size, int h) attribute_l1_text; -void ff_bfin_put_pixels16_xy2_nornd (uint8_t *block, const uint8_t *s0, int line_size, int h) attribute_l1_text; -void ff_bfin_put_pixels8_xy2_nornd (uint8_t *block, const uint8_t *s0, int line_size, int h) attribute_l1_text; - - -void ff_bfin_put_pixels8uc (uint8_t *block, const uint8_t *s0, const uint8_t *s1, int dest_size, int line_size, int h) attribute_l1_text; -void ff_bfin_put_pixels16uc (uint8_t *block, const uint8_t *s0, const uint8_t *s1, int dest_size, int line_size, int h) attribute_l1_text; -void ff_bfin_put_pixels8uc_nornd (uint8_t *block, const uint8_t *s0, const uint8_t *s1, int line_size, int h) attribute_l1_text; -void ff_bfin_put_pixels16uc_nornd (uint8_t *block, const uint8_t *s0, const uint8_t *s1, int line_size, int h) attribute_l1_text; - -#endif /* AVCODEC_BFIN_HPELDSP_BFIN_H */ diff --git a/libavcodec/bfin/idct_bfin.S b/libavcodec/bfin/idct_bfin.S deleted file mode 100644 index bd80447bd..000000000 --- a/libavcodec/bfin/idct_bfin.S +++ /dev/null @@ -1,304 +0,0 @@ -/* - * idct BlackFin - * - * Copyright (C) 2007 Marc Hoffman - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -/* - This blackfin DSP code implements an 8x8 inverse type II DCT. - -Prototype : void ff_bfin_idct(int16_t *in) - -Registers Used : A0, A1, R0-R7, I0-I3, B0, B2, B3, M0-M2, L0-L3, P0-P5, LC0. - -Performance : - Code Size : 498 Bytes. - Cycle Count : 417 Cycles - - ------------------------------------------------------------ -FFMPEG conformance testing results ------------------------------------------------------------ - -dct-test: modified with the following - dct_error("BFINidct", 1, ff_bfin_idct, idct, test); -produces the following output - -root:/u/ffmpeg/bhead/libavcodec> ./dct-test -i -ffmpeg DCT/IDCT test - - 8 15 -2 21 24 17 0 10 - 2 -10 -5 -5 -3 7 -14 -3 - 2 -13 -10 -19 18 -6 6 -2 - 9 4 16 -3 9 12 10 15 - 15 -9 -2 10 1 16 0 -15 - -15 5 7 3 13 0 13 20 - -6 -15 24 9 -18 1 9 -22 - -8 25 23 2 -7 0 30 13 -IDCT BFINidct: err_inf=1 err2=0.01002344 syserr=0.00150000 maxout=266 blockSumErr=64 -IDCT BFINidct: 88.3 kdct/s - -*/ - -#include "config.h" -#include "config_bfin.h" - -#if defined(__FDPIC__) && CONFIG_SRAM -.section .l1.data.B,"aw",@progbits -#else -.data -#endif - -.align 4; -coefs: -.short 0x5a82; // C4 -.short 0x5a82; // C4 -.short 0x30FC; //cos(3pi/8) C6 -.short 0x7642; //cos(pi/8) C2 -.short 0x18F9; //cos(7pi/16) -.short 0x7D8A; //cos(pi/16) -.short 0x471D; //cos(5pi/16) -.short 0x6A6E; //cos(3pi/16) -.short 0x18F9; //cos(7pi/16) -.short 0x7D8A; //cos(pi/16) - -#if defined(__FDPIC__) && CONFIG_SRAM -.section .l1.data.A,"aw",@progbits -#endif - -vtmp: .space 256 - -#define TMP0 FP-8 -#define TMP1 FP-12 -#define TMP2 FP-16 - - -.text -DEFUN(idct,mL1, - (int16_t *block)): - -/********************** Function Prologue *********************************/ - link 16; - [--SP] = (R7:4, P5:3); // Push the registers onto the stack. - B0 = R0; // Pointer to Input matrix - RELOC(R1, P3, coefs); // Pointer to Coefficients - RELOC(R2, P3, vtmp); // Pointer to Temporary matrix - B3 = R1; - B2 = R2; - L3 = 20; // L3 is used for making the coefficient array - // circular. - // MUST BE RESTORED TO ZERO at function exit. - M1 = 16 (X); // All these registers are initialized for - M3 = 8(X); // modifying address offsets. - - I0 = B0; // I0 points to Input Element (0, 0). - I2 = B0; // I2 points to Input Element (0, 0). - I2 += M3 || R0.H = W[I0]; - // Element 0 is read into R0.H - I1 = I2; // I1 points to input Element (0, 6). - I1 += 4 || R0.L = W[I2++]; - // I2 points to input Element (0, 4). - // Element 4 is read into R0.L. - P2 = 8 (X); - P3 = 32 (X); - P4 = -32 (X); - P5 = 98 (X); - R7 = 0x8000(Z); - I3 = B3; // I3 points to Coefficients - P0 = B2; // P0 points to array Element (0, 0) of temp - P1 = B2; - R7 = [I3++] || [TMP2]=R7; // Coefficient C4 is read into R7.H and R7.L. - MNOP; - NOP; - - /* - * A1 = Y0 * cos(pi/4) - * A0 = Y0 * cos(pi/4) - * A1 = A1 + Y4 * cos(pi/4) - * A0 = A0 - Y4 * cos(pi/4) - * load: - * R1=(Y2,Y6) - * R7=(C2,C6) - * res: - * R3=Y0, R2=Y4 - */ - A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || I0+= 4 || R1.L=W[I1++]; - R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || R1.H=W[I0--] || R7=[I3++]; - - LSETUP (.0, .1) LC0 = P2; // perform 8 1d idcts - - P2 = 112 (X); - P1 = P1 + P2; // P1 points to element (7, 0) of temp buffer. - P2 = -94(X); - -.0: - /* - * A1 = Y2 * cos(3pi/8) - * A0 = Y2 * cos(pi/8) - * A1 = A1 - Y6 * cos(pi/8) - * A0 = A0 + Y6 * cos(3pi/8) - * R5 = (Y1,Y7) - * R7 = (C1,C7) - * res: - * R1=Y2, R0=Y6 - */ - A1=R7.L*R1.H, A0=R7.H*R1.H (IS) || I0+=4 || R5.H=W[I0]; - R1=(A1-=R7.H*R1.L), R0=(A0+=R7.L*R1.L) (IS) || R5.L=W[I1--] || R7=[I3++]; - /* - * Y0 = Y0 + Y6. - * Y4 = Y4 + Y2. - * Y2 = Y4 - Y2. - * Y6 = Y0 - Y6. - * R3 is saved - * R6.l=Y3 - * note: R3: Y0, R2: Y4, R1: Y2, R0: Y6 - */ - R3=R3+R0, R0=R3-R0; - R2=R2+R1, R1=R2-R1 || [TMP0]=R3 || R6.L=W[I0--]; - /* - * Compute the odd portion (1,3,5,7) even is done. - * - * Y1 = C7 * Y1 - C1 * Y7 + C3 * Y5 - C5 * Y3. - * Y7 = C1 * Y1 + C7 * Y7 + C5 * Y5 + C3 * Y3. - * Y5 = C5 * Y1 + C3 * Y7 + C7 * Y5 - C1 * Y3. - * Y3 = C3 * Y1 - C5 * Y7 - C1 * Y5 - C7 * Y3. - */ - // R5=(Y1,Y7) R6=(Y5,Y3) // R7=(C1,C7) - A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || [TMP1]=R2 || R6.H=W[I2--]; - A1-=R7.H*R5.L, A0+=R7.L*R5.L (IS) || I0-=4 || R7=[I3++]; - A1+=R7.H*R6.H, A0+=R7.L*R6.H (IS) || I0+=M1; // R7=(C3,C5) - R3 =(A1-=R7.L*R6.L), R2 =(A0+=R7.H*R6.L) (IS); - A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || R4=[TMP0]; - A1+=R7.H*R5.L, A0-=R7.L*R5.L (IS) || I1+=M1 || R7=[I3++]; // R7=(C1,C7) - A1+=R7.L*R6.H, A0-=R7.H*R6.H (IS); - R7 =(A1-=R7.H*R6.L), R6 =(A0-=R7.L*R6.L) (IS) || I2+=M1; - // R3=Y1, R2=Y7, R7=Y5, R6=Y3 - - /* Transpose write column. */ - R5.H=R4+R2 (RND12); // Y0=Y0+Y7 - R5.L=R4-R2 (RND12) || R4 = [TMP1]; // Y7=Y7-Y0 - R2.H=R1+R7 (RND12) || W[P0++P3]=R5.H; // Y2=Y2+Y5 st Y0 - R2.L=R1-R7 (RND12) || W[P1++P4]=R5.L || R7=[I3++]; // Y5=Y2-Y5 st Y7 - R5.H=R0-R3 (RND12) || W[P0++P3]=R2.H || R1.L=W[I1++]; // Y1=Y6-Y1 st Y2 - R5.L=R0+R3 (RND12) || W[P1++P4]=R2.L || R0.H=W[I0++]; // Y6=Y6+Y1 st Y5 - R3.H=R4-R6 (RND12) || W[P0++P3]=R5.H || R0.L=W[I2++]; // Y3=Y3-Y4 st Y1 - R3.L=R4+R6 (RND12) || W[P1++P4]=R5.L || R1.H=W[I0++]; // Y4=Y3+Y4 st Y6 - - /* pipeline loop start, + drain Y3, Y4 */ - A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || W[P0++P2]= R3.H || R1.H = W[I0--]; -.1: R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || W[P1++P5]= R3.L || R7 = [I3++]; - - - - I0 = B2; // I0 points to Input Element (0, 0) - I2 = B2; // I2 points to Input Element (0, 0) - I2 += M3 || R0.H = W[I0]; - // Y0 is read in R0.H - I1 = I2; // I1 points to input Element (0, 6) - I1 += 4 || R0.L = W[I2++]; - // I2 points to input Element (0, 4) - // Y4 is read in R0.L - P2 = 8 (X); - I3 = B3; // I3 points to Coefficients - P0 = B0; // P0 points to array Element (0, 0) for writing - // output - P1 = B0; - R7 = [I3++]; // R7.H = C4 and R7.L = C4 - NOP; - - /* - * A1 = Y0 * cos(pi/4) - * A0 = Y0 * cos(pi/4) - * A1 = A1 + Y4 * cos(pi/4) - * A0 = A0 - Y4 * cos(pi/4) - * load: - * R1=(Y2,Y6) - * R7=(C2,C6) - * res: - * R3=Y0, R2=Y4 - */ - A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || I0+=4 || R1.L=W[I1++]; - R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || R1.H=W[I0--] || R7=[I3++]; - - LSETUP (.2, .3) LC0 = P2; // peform 8 1d idcts - P2 = 112 (X); - P1 = P1 + P2; - P2 = -94(X); - -.2: - /* - * A1 = Y2 * cos(3pi/8) - * A0 = Y2 * cos(pi/8) - * A1 = A1 - Y6 * cos(pi/8) - * A0 = A0 + Y6 * cos(3pi/8) - * R5 = (Y1,Y7) - * R7 = (C1,C7) - * res: - * R1=Y2, R0=Y6 - */ - A1=R7.L*R1.H, A0=R7.H*R1.H (IS) || I0+=4 || R5.H=W[I0]; - R1=(A1-=R7.H*R1.L), R0=(A0+=R7.L*R1.L) (IS) || R5.L=W[I1--] || R7=[I3++]; - /* - * Y0 = Y0 + Y6. - * Y4 = Y4 + Y2. - * Y2 = Y4 - Y2. - * Y6 = Y0 - Y6. - * R3 is saved - * R6.l=Y3 - * note: R3: Y0, R2: Y4, R1: Y2, R0: Y6 - */ - R3=R3+R0, R0=R3-R0; - R2=R2+R1, R1=R2-R1 || [TMP0]=R3 || R6.L=W[I0--]; - /* - * Compute the odd portion (1,3,5,7) even is done. - * - * Y1 = C7 * Y1 - C1 * Y7 + C3 * Y5 - C5 * Y3. - * Y7 = C1 * Y1 + C7 * Y7 + C5 * Y5 + C3 * Y3. - * Y5 = C5 * Y1 + C3 * Y7 + C7 * Y5 - C1 * Y3. - * Y3 = C3 * Y1 - C5 * Y7 - C1 * Y5 - C7 * Y3. - */ - // R5=(Y1,Y7) R6=(Y5,Y3) // R7=(C1,C7) - A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || [TMP1]=R2 || R6.H=W[I2--]; - A1-=R7.H*R5.L, A0+=R7.L*R5.L (IS) || I0-=4 || R7=[I3++]; - A1+=R7.H*R6.H, A0+=R7.L*R6.H (IS) || I0+=M1; // R7=(C3,C5) - R3 =(A1-=R7.L*R6.L), R2 =(A0+=R7.H*R6.L) (IS); - A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || R4=[TMP0]; - A1+=R7.H*R5.L, A0-=R7.L*R5.L (IS) || I1+=M1 || R7=[I3++]; // R7=(C1,C7) - A1+=R7.L*R6.H, A0-=R7.H*R6.H (IS); - R7 =(A1-=R7.H*R6.L), R6 =(A0-=R7.L*R6.L) (IS) || I2+=M1; - // R3=Y1, R2=Y7, R7=Y5, R6=Y3 - - /* Transpose write column. */ - R5.H=R4+R2 (RND20); // Y0=Y0+Y7 - R5.L=R4-R2 (RND20) || R4 = [TMP1]; // Y7=Y7-Y0 - R2.H=R1+R7 (RND20) || W[P0++P3]=R5.H; // Y2=Y2+Y5 st Y0 - R2.L=R1-R7 (RND20) || W[P1++P4]=R5.L || R7=[I3++]; // Y5=Y2-Y5 st Y7 - R5.H=R0-R3 (RND20) || W[P0++P3]=R2.H || R1.L=W[I1++]; // Y1=Y6-Y1 st Y2 - R5.L=R0+R3 (RND20) || W[P1++P4]=R2.L || R0.H=W[I0++]; // Y6=Y6+Y1 st Y5 - R3.H=R4-R6 (RND20) || W[P0++P3]=R5.H || R0.L=W[I2++]; // Y3=Y3-Y4 st Y1 - R3.L=R4+R6 (RND20) || W[P1++P4]=R5.L || R1.H=W[I0++]; // Y4=Y3+Y4 st Y6 - - /* pipeline loop start, + drain Y3, Y4 */ - A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || W[P0++P2]= R3.H || R1.H = W[I0--]; -.3: R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || W[P1++P5]= R3.L || R7 = [I3++]; - - L3 = 0; - (R7:4,P5:3)=[SP++]; - unlink; - RTS; -DEFUN_END(idct) diff --git a/libavcodec/bfin/mathops.h b/libavcodec/bfin/mathops.h deleted file mode 100644 index 50c03160e..000000000 --- a/libavcodec/bfin/mathops.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * simple math operations - * - * Copyright (C) 2007 Marc Hoffman - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#ifndef AVCODEC_BFIN_MATHOPS_H -#define AVCODEC_BFIN_MATHOPS_H - -#include "config.h" - -#define MULH(X,Y) ({ int xxo; \ - __asm__ ( \ - "a1 = %2.L * %1.L (FU);\n\t" \ - "a1 = a1 >> 16;\n\t" \ - "a1 += %2.H * %1.L (IS,M);\n\t" \ - "a0 = %1.H * %2.H, a1+= %1.H * %2.L (IS,M);\n\t"\ - "a1 = a1 >>> 16;\n\t" \ - "%0 = (a0 += a1);\n\t" \ - : "=d" (xxo) : "d" (X), "d" (Y) : "A0","A1"); xxo; }) - -/* signed 16x16 -> 32 multiply */ -#define MUL16(a, b) ({ int xxo; \ - __asm__ ( \ - "%0 = %1.l*%2.l (is);\n\t" \ - : "=W" (xxo) : "d" (a), "d" (b) : "A1"); \ - xxo; }) - -#endif /* AVCODEC_BFIN_MATHOPS_H */ diff --git a/libavcodec/bfin/pixels_bfin.S b/libavcodec/bfin/pixels_bfin.S deleted file mode 100644 index 2c84deb83..000000000 --- a/libavcodec/bfin/pixels_bfin.S +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Blackfin Pixel Operations - * Copyright (C) 2007 Marc Hoffman - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include "config_bfin.h" - -DEFUN(put_pixels_clamped,mL1, - (int16_t *block, uint8_t *dest, int line_size)): - [--SP] = (R7:4); - R4 = 0; - R5.l = 0x00ff; - R5.h = 0x00ff; - I0 = R0; // block - I1 = R1; // dest - R2 += -4; // line_size - M1 = R2; - P0 = 8; - R0 = [I0++]; - R1 = [I0++]; - R2 = MAX(R0, R4) (V); - LSETUP (ppc$0,ppc$1) LC0=P0; -ppc$0: R2 = MIN(R2, R5) (V); - R3 = MAX(R1, R4) (V); - R3 = MIN(R3, R5) (V) || R0 = [I0++]; - R6 = BYTEPACK (R2,R3) || R1 = [I0++]; - R2 = MAX(R0, R4) (V) || [I1++] = R6; - R2 = MIN(R2, R5) (V); - R3 = MAX(R1, R4) (V); - R3 = MIN(R3, R5) (V) || R0 = [I0++]; - R6 = BYTEPACK (R2,R3) || R1 = [I0++]; -ppc$1: R2 = Max(R0, R4) (V) || [I1++M1] = R6; - - (R7:4) = [SP++]; - RTS; -DEFUN_END(put_pixels_clamped) - -DEFUN(add_pixels_clamped,mL1, - (int16_t *block, uint8_t *dest, int line_size)): - [-- SP] = (R7:4); - R4 = 0; - I0 = 0; - R2 += -4; // line_size - M0 = R2; - I1 = R1; // dest - I3 = R0; // block - I2 = R1; // dest - P0 = 8; - M3 = 2; - R0 = [I3++] || R2 = [I1]; - R2 = R2 << 8 || R0.H = W[I3--] || R3 = [I1++]; - R3 = R3 >> 8 || R1.L = W[I3] || I3 += 4; - R6 = BYTEOP3P(R1:0, R3:2) (LO) || R1.H = W[I3++] || R2 = [I1]; - - LSETUP(apc$2,apc$3) LC1 = P0; -apc$2: R7 = BYTEOP3P(R1:0, R3:2) (HI, R) || R0 = [I3++] || R3 = [I1++M0]; - R2 = R2 << 8 || R0.H = W[I3--]; - R3 = R3 >> 8 || R1.L = W[I3] || I3 += 4; - R6 = R6 + R7 (S) || R1.H = W[I3]; - R6 = BYTEOP3P(R1:0, R3:2) (LO) || I3+=M3 || [I2++]=R6; - R7 = BYTEOP3P(R1:0, R3:2) (HI, R) || R0 = [I3++] || R2 = [I1]; - R2 = R2 << 8 || R0.H = W[I3--] || R3 = [I1++]; - R3 = R3 >> 8 || R1.L = W[I3] || I3 += 4; - R6 = R6 + R7 (S) || R1.H = W[I3++]; -apc$3: R6 = BYTEOP3P(R1:0, R3:2) (LO) || [I2++M0] = R6 || R2 = [I1]; - - (R7:4) = [SP++]; - RTS; -DEFUN_END(add_pixels_clamped) - -DEFUN(diff_pixels,mL1, - (int16_t *block, uint8_t *s1, uint8_t *s2, int stride)): - link 0; - [--sp] = (r7:4); - p0=8; - i3=r0; // block - i0=r1; // s1 - i1=r2; // s2 - r2=[fp+20]; // stride - r2+=-8; - m0=r2; - - - LSETUP(.LS0,.LE0) LC0=P0; - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - -.LS0: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; - (R5,R4) = BYTEOP16M (R1:0,R3:2) || R0 = [I0++M0] || R2 = [I1++M0]; - (R7,R6) = BYTEOP16M (R1:0,R3:2) (R)|| R0 = [I0++] || [I3++] = R4; - DISALGNEXCPT || R2 = [I1++] || [I3++] = R5; - [i3++]=r6; -.LE0: [i3++]=r7; - - (r7:4) = [sp++]; - unlink; - rts; -DEFUN_END(diff_pixels) - -/* - for (i = 0; i < 16; i++) { - for (j = 0; j < 16; j++) { - sum += pix[j]; - } - pix += line_size; - } -*/ -DEFUN(pix_sum,mL1, - (uint8_t *p, int stride)): - link 0; - [--sp] = (r7:4); - p0=8; - i0=r0; // s1 - i1=r0; - m1=r1; - r1=r1+r1; - r1+=-16; // stride - m0=r1; - i1+=m1; - - r6=0; - - LSETUP(LS$PS,LE$PS) LC0=P0; - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - -LS$PS: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; - (R5,R4) = BYTEOP16P (R3:2,R1:0) || R0 = [I0++] || R2 = [I1++]; - r6=r6+|+r5; - r6=r6+|+r4; - (R5,R4) = BYTEOP16P (R3:2,R1:0) (R)|| R1 = [I0++] || R3 = [I1++]; - r6=r6+|+r5; - r6=r6+|+r4; - (R5,R4) = BYTEOP16P (R3:2,R1:0) || R0 = [I0++m0] || R2 = [I1++m0]; - r6=r6+|+r5; - r6=r6+|+r4; - (R5,R4) = BYTEOP16P (R3:2,R1:0) (R)|| R0 = [I0++] || R2 = [I1++]; - r6=r6+|+r5; -LE$PS: r6=r6+|+r4; - r0.l=r6.l+r6.h; - r0.h=0; - - (r7:4) = [sp++]; - unlink; - rts; -DEFUN_END(pix_sum) - - -DEFUN(get_pixels,mL1, - (int16_t *av_restrict block, const uint8_t *pixels, int line_size)): - [--sp] = (r7:4); - i3=r0; // dest - i0=r1; // src0 - p0=8; - r2+=-8; - m0=r2; - LSETUP(gp8$0,gp8$1) LC0=P0; - - DISALGNEXCPT || R0 = [I0++]; - DISALGNEXCPT || R1 = [I0++]; - -gp8$0: (R7,R6) = byteunpack R1:0 || R0 = [I0++M0]; - (R5,R4) = byteunpack R1:0 (R) || R0 = [I0++] || [I3++]=R6; - DISALGNEXCPT || R1 = [I0++] || [I3++]=R7; - [I3++]=R4; -gp8$1: [I3++]=R5 - - - (r7:4) = [sp++]; - RTS; -DEFUN_END(get_pixels) - - -/* sad = sad16x16 (ubyte *mb, ubyte *refwin, srcwidth, refwinwidth, h) */ -/* 91 cycles */ -DEFUN(z_sad16x16,mL1, - (uint8_t *blk1, uint8_t *blk2, int dsz, int line_size, int h)): - link 0; - I0 = R0; - I1 = R1; - - A1 = A0 = 0; - R0 = [sp+20]; // rwidth - P2 = [sp+24]; // height - R3 = 16; - R0 = R0 - R3; - R3 = R2 - R3; - M1 = R0; - M0 = R3; - - DISALGNEXCPT || R0 = [I0++] || R2 = [I1++]; - LSETUP (s$16, e$16) LC0=P2; -s$16: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; - SAA (R1:0,R3:2) || R0 = [I0++] || R2 = [I1++]; - SAA (R1:0,R3:2) (R) || R1 = [I0++] || R3 = [I1++]; - SAA (R1:0,R3:2) || R0 = [I0++M0] || R2 = [I1++M1]; -e$16: SAA (R1:0,R3:2) (R) || R0 = [I0++] || R2 = [I1++]; - - R3=A1.L+A1.H, R2=A0.L+A0.H ; - R0 = R2 + R3 ; - unlink; - RTS; -DEFUN_END(z_sad16x16) - -/* sad = sad8x8 (ubyte *mb, ubyte *refwin, int srcwidth, int refwinwidth, int h) */ -/* 36 cycles */ -DEFUN(z_sad8x8,mL1, - (uint8_t *blk1, uint8_t *blk2, int dsz, int line_size, int h)): - I0 = R0; - I1 = R1; - - A1 = A0 = 0; - r0 = [sp+12]; // rwidth - P2 = [sp+16]; //height - R3 = 8; - R0 = R0 - R3; - R3 = R2 - R3; - M0 = R3; - M1 = R0; - - LSETUP (s$8, e$8) LC0=P2; - DISALGNEXCPT || R0 = [I0++] || R2 = [I1++]; - DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; -s$8: SAA (R1:0,R3:2) || R0 = [I0++M0] || R2 = [I1++M1]; - SAA (R1:0,R3:2) (R) || R0 = [I0++] || R2 = [I1++]; -e$8: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; - - R3=A1.L+A1.H, R2=A0.L+A0.H ; - R0 = R2 + R3 ; - RTS; -DEFUN_END(z_sad8x8) - -DEFUN(pix_norm1,mL1, - (uint8_t * pix, int line_size)): - [--SP]=(R7:4,P5:3); - - // Fetch the input arguments. - P1 = R0; // pix - P0 = R1; // line_size - P5 = 16; // loop ctr. - P0 -= P5; - M0 = P0; // M0 = line_size-16; - // Now for the real work. - A1 = A0 = 0; - lsetup(_pix_norm1_blkfn_loopStart, _pix_norm1_blkfn_loopEnd) LC1 = P5; - I0 = P1; - DISALGNEXCPT || r0 = [i0++]; - -_pix_norm1_blkfn_loopStart: - // following unpacks pix1[0..15] pix1+line_size[0..15] - DISALGNEXCPT || r1 = [i0++]; - - (r5, r4) = byteunpack r1:0 || r0 = [i0++]; - a1 += r5.h * r5.h, a0 += r5.l * r5.l (is); - a1 += r4.h * r4.h, a0 += r4.l * r4.l (is); - (r5, r4) = byteunpack r1:0(r) || r1 = [i0++]; - a1 += r5.h * r5.h, a0 += r5.l * r5.l (is); - a1 += r4.h * r4.h, a0 += r4.l * r4.l (is); - (r5, r4) = byteunpack r1:0 || r0 = [i0++M0]; - a1 += r5.h * r5.h, a0 += r5.l * r5.l (is); - a1 += r4.h * r4.h, a0 += r4.l * r4.l (is); - (r5, r4) = byteunpack r1:0(r) || r0 = [i0++]; - a1 += r5.h * r5.h, a0 += r5.l * r5.l (is); -_pix_norm1_blkfn_loopEnd: - a1 += r4.h * r4.h, a0 += r4.l * r4.l (is); - - -// Clean up at the end: - R2 = A0, R3 = A1; - R0 = R2 + R3 (S); - - (R7:4,P5:3)=[SP++]; - - RTS; -DEFUN_END(pix_norm1) - -DEFUN(sse4,mL1, - (void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)): - link 0; - [--sp] = (r7:6); - p0=[fp+24]; // h - i0=r1; // pix1 - i1=r2; // pix2 - r2=[fp+20]; // line_size - r2+=-4; - m0=r2; - - a0=a1=0; - LSETUP(.S40,.E40) LC0=P0; - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - -.S40: DISALGNEXCPT || R1 = [I0++M0] || R3 = [I1++M0]; - (R7,R6) = BYTEOP16M (R1:0,R3:2); - a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); -.E40: a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); - a0 += a1; - r0 = a0; - - (r7:6) = [sp++]; - unlink; - rts; -DEFUN_END(sse4) - -DEFUN(sse8,mL1, - (void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)): - link 0; - [--sp] = (r7:6); - p0=[fp+24]; // h - i0=r1; // pix1 - i1=r2; // pix2 - r2=[fp+20]; // line_size - r2+=-8; - m0=r2; - - a0=a1=0; - LSETUP(.S80,.E80) LC0=P0; - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - -.S80: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; - (R7,R6) = BYTEOP16M (R1:0,R3:2) || R0 = [I0++M0] || R2 = [I1++M0]; - a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); - a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); - (R7,R6) = BYTEOP16M (R1:0,R3:2) (R)|| R0 = [I0++] || R2 = [I1++]; - a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); -.E80: a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); - a0 += a1; - r0 = a0; - - (r7:6) = [sp++]; - unlink; - rts; -DEFUN_END(sse8) - -DEFUN(sse16,mL1, - (void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)): - link 0; - [--sp] = (r7:6); - p0=[fp+24]; // h - i0=r1; // pix1 - i1=r2; // pix2 - r2=[fp+20]; // line_size - r2+=-16; - m0=r2; - - a0=a1=0; - DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; - LSETUP(.S160,.E160) LC0=P0; - -.S160: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; - (R7,R6) = BYTEOP16M (R1:0,R3:2) || R0 = [I0++] || R2 = [I1++]; - a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); - a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); - (R7,R6) = BYTEOP16M (R1:0,R3:2) (R)|| R1 = [I0++] || R3 = [I1++]; - a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); - a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); - (R7,R6) = BYTEOP16M (R1:0,R3:2) || R0 = [I0++M0] || R2 = [I1++M0]; - a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); - a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); - (R7,R6) = BYTEOP16M (R1:0,R3:2) (R)|| R0 = [I0++] || R2 = [I1++]; - a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); -.E160: a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); - a0 += a1; - r0 = a0; - - (r7:6) = [sp++]; - unlink; - rts; -DEFUN_END(sse16) diff --git a/libavcodec/bfin/vp3_bfin.c b/libavcodec/bfin/vp3_bfin.c deleted file mode 100644 index 868c43149..000000000 --- a/libavcodec/bfin/vp3_bfin.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2007 Marc Hoffman - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "libavutil/attributes.h" -#include "libavcodec/avcodec.h" -#include "libavcodec/vp3dsp.h" -#include "libavcodec/dsputil.h" -#include "dsputil_bfin.h" -#include "vp3_bfin.h" - -/* Intra iDCT offset 128 */ -static void bfin_vp3_idct_put(uint8_t *dest, int line_size, int16_t *block) -{ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP + 128; - int i,j; - - ff_bfin_vp3_idct (block); - - for (i=0;i<8;i++) - for (j=0;j<8;j++) - dest[line_size*i + j] = cm[block[j*8 + i]]; - - memset(block, 0, 128); -} - -/* Inter iDCT */ -static void bfin_vp3_idct_add(uint8_t *dest, int line_size, int16_t *block) -{ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; - int i, j; - - ff_bfin_vp3_idct (block); - for (i = 0; i < 8; i++) - for (j = 0; j < 8; j++) - dest[line_size*i + j] = cm[dest[line_size*i + j] + block[j*8 + i]]; - - memset(block, 0, 128); -} - -av_cold void ff_vp3dsp_init_bfin(VP3DSPContext *c, int flags) -{ - if (!(flags & CODEC_FLAG_BITEXACT)) { - c->idct_add = bfin_vp3_idct_add; - c->idct_put = bfin_vp3_idct_put; - } -} diff --git a/libavcodec/bfin/vp3_idct_bfin.S b/libavcodec/bfin/vp3_idct_bfin.S deleted file mode 100644 index 5d88801f9..000000000 --- a/libavcodec/bfin/vp3_idct_bfin.S +++ /dev/null @@ -1,280 +0,0 @@ -/* - * vp3_idct BlackFin - * - * Copyright (C) 2007 Marc Hoffman - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -/* - This blackfin DSP code implements an 8x8 inverse type II DCT. - -Prototype : void ff_bfin_vp3_idct(int16_t *in) - -Registers Used : A0, A1, R0-R7, I0-I3, B0, B2, B3, M0-M2, L0-L3, P0-P5, LC0. - -*/ - -#include "config.h" -#include "config_bfin.h" - -#if defined(__FDPIC__) && CONFIG_SRAM -.section .l1.data.B,"aw",@progbits -#else -.data -#endif - -.align 4; -coefs: -.short 0x5a82; // C4 -.short 0x5a82; // C4 -.short 0x30FC; //cos(3pi/8) C6 -.short 0x7642; //cos(pi/8) C2 -.short 0x18F9; //cos(7pi/16) -.short 0x7D8A; //cos(pi/16) -.short 0x471D; //cos(5pi/16) -.short 0x6A6E; //cos(3pi/16) -.short 0x18F9; //cos(7pi/16) -.short 0x7D8A; //cos(pi/16) - -#if defined(__FDPIC__) && CONFIG_SRAM -.section .l1.data.A,"aw",@progbits -#endif - -vtmp: .space 256 - -#define TMP0 FP-8 -#define TMP1 FP-12 -#define TMP2 FP-16 - - -.text -DEFUN(vp3_idct,mL1, - (int16_t *block)): - -/********************** Function Prologue *********************************/ - link 16; - [--SP] = (R7:4, P5:3); // Push the registers onto the stack. - B0 = R0; // Pointer to Input matrix - RELOC(R1, P3, coefs); // Pointer to Coefficients - RELOC(R2, P3, vtmp); // Pointer to Temporary matrix - B3 = R1; - B2 = R2; - L3 = 20; // L3 is used for making the coefficient array - // circular. - // MUST BE RESTORED TO ZERO at function exit. - M1 = 16 (X); // All these registers are initialized for - M3 = 8(X); // modifying address offsets. - - I0 = B0; // I0 points to Input Element (0, 0). - I2 = B0; // I2 points to Input Element (0, 0). - I2 += M3 || R0.H = W[I0]; - // Element 0 is read into R0.H - I1 = I2; // I1 points to input Element (0, 6). - I1 += 4 || R0.L = W[I2++]; - // I2 points to input Element (0, 4). - // Element 4 is read into R0.L. - P2 = 8 (X); - P3 = 32 (X); - P4 = -32 (X); - P5 = 98 (X); - R7 = 0x8000(Z); - I3 = B3; // I3 points to Coefficients - P0 = B2; // P0 points to array Element (0, 0) of temp - P1 = B2; - R7 = [I3++] || [TMP2]=R7; // Coefficient C4 is read into R7.H and R7.L. - MNOP; - NOP; - - /* - * A1 = Y0 * cos(pi/4) - * A0 = Y0 * cos(pi/4) - * A1 = A1 + Y4 * cos(pi/4) - * A0 = A0 - Y4 * cos(pi/4) - * load: - * R1=(Y2,Y6) - * R7=(C2,C6) - * res: - * R3=Y0, R2=Y4 - */ - A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || I0+= 4 || R1.L=W[I1++]; - R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || R1.H=W[I0--] || R7=[I3++]; - - LSETUP (.0, .1) LC0 = P2; // perform 8 1d idcts - - P2 = 112 (X); - P1 = P1 + P2; // P1 points to element (7, 0) of temp buffer. - P2 = -94(X); - -.0: - /* - * A1 = Y2 * cos(3pi/8) - * A0 = Y2 * cos(pi/8) - * A1 = A1 - Y6 * cos(pi/8) - * A0 = A0 + Y6 * cos(3pi/8) - * R5 = (Y1,Y7) - * R7 = (C1,C7) - * res: - * R1=Y2, R0=Y6 - */ - A1=R7.L*R1.H, A0=R7.H*R1.H (IS) || I0+=4 || R5.H=W[I0]; - R1=(A1-=R7.H*R1.L), R0=(A0+=R7.L*R1.L) (IS) || R5.L=W[I1--] || R7=[I3++]; - /* - * Y0 = Y0 + Y6. - * Y4 = Y4 + Y2. - * Y2 = Y4 - Y2. - * Y6 = Y0 - Y6. - * R3 is saved - * R6.l=Y3 - * note: R3: Y0, R2: Y4, R1: Y2, R0: Y6 - */ - R3=R3+R0, R0=R3-R0; - R2=R2+R1, R1=R2-R1 || [TMP0]=R3 || R6.L=W[I0--]; - /* - * Compute the odd portion (1,3,5,7) even is done. - * - * Y1 = C7 * Y1 - C1 * Y7 + C3 * Y5 - C5 * Y3. - * Y7 = C1 * Y1 + C7 * Y7 + C5 * Y5 + C3 * Y3. - * Y5 = C5 * Y1 + C3 * Y7 + C7 * Y5 - C1 * Y3. - * Y3 = C3 * Y1 - C5 * Y7 - C1 * Y5 - C7 * Y3. - */ - // R5=(Y1,Y7) R6=(Y5,Y3) // R7=(C1,C7) - A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || [TMP1]=R2 || R6.H=W[I2--]; - A1-=R7.H*R5.L, A0+=R7.L*R5.L (IS) || I0-=4 || R7=[I3++]; - A1+=R7.H*R6.H, A0+=R7.L*R6.H (IS) || I0+=M1; // R7=(C3,C5) - R3 =(A1-=R7.L*R6.L), R2 =(A0+=R7.H*R6.L) (IS); - A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || R4=[TMP0]; - A1+=R7.H*R5.L, A0-=R7.L*R5.L (IS) || I1+=M1 || R7=[I3++]; // R7=(C1,C7) - A1+=R7.L*R6.H, A0-=R7.H*R6.H (IS); - R7 =(A1-=R7.H*R6.L), R6 =(A0-=R7.L*R6.L) (IS) || I2+=M1; - // R3=Y1, R2=Y7, R7=Y5, R6=Y3 - - /* Transpose write column. */ - R5.H=R4+R2 (RND12); // Y0=Y0+Y7 - R5.L=R4-R2 (RND12) || R4 = [TMP1]; // Y7=Y7-Y0 - R2.H=R1+R7 (RND12) || W[P0++P3]=R5.H; // Y2=Y2+Y5 st Y0 - R2.L=R1-R7 (RND12) || W[P1++P4]=R5.L || R7=[I3++]; // Y5=Y2-Y5 st Y7 - R5.H=R0-R3 (RND12) || W[P0++P3]=R2.H || R1.L=W[I1++]; // Y1=Y6-Y1 st Y2 - R5.L=R0+R3 (RND12) || W[P1++P4]=R2.L || R0.H=W[I0++]; // Y6=Y6+Y1 st Y5 - R3.H=R4-R6 (RND12) || W[P0++P3]=R5.H || R0.L=W[I2++]; // Y3=Y3-Y4 st Y1 - R3.L=R4+R6 (RND12) || W[P1++P4]=R5.L || R1.H=W[I0++]; // Y4=Y3+Y4 st Y6 - - /* pipeline loop start, + drain Y3, Y4 */ - A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || W[P0++P2]= R3.H || R1.H = W[I0--]; -.1: R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || W[P1++P5]= R3.L || R7 = [I3++]; - - - - I0 = B2; // I0 points to Input Element (0, 0) - I2 = B2; // I2 points to Input Element (0, 0) - I2 += M3 || R0.H = W[I0]; - // Y0 is read in R0.H - I1 = I2; // I1 points to input Element (0, 6) - I1 += 4 || R0.L = W[I2++]; - // I2 points to input Element (0, 4) - // Y4 is read in R0.L - P2 = 8 (X); - I3 = B3; // I3 points to Coefficients - P0 = B0; // P0 points to array Element (0, 0) for writing - // output - P1 = B0; - R7 = [I3++]; // R7.H = C4 and R7.L = C4 - NOP; - - /* - * A1 = Y0 * cos(pi/4) - * A0 = Y0 * cos(pi/4) - * A1 = A1 + Y4 * cos(pi/4) - * A0 = A0 - Y4 * cos(pi/4) - * load: - * R1=(Y2,Y6) - * R7=(C2,C6) - * res: - * R3=Y0, R2=Y4 - */ - A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || I0+=4 || R1.L=W[I1++]; - R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || R1.H=W[I0--] || R7=[I3++]; - - LSETUP (.2, .3) LC0 = P2; // peform 8 1d idcts - P2 = 112 (X); - P1 = P1 + P2; - P2 = -94(X); - -.2: - /* - * A1 = Y2 * cos(3pi/8) - * A0 = Y2 * cos(pi/8) - * A1 = A1 - Y6 * cos(pi/8) - * A0 = A0 + Y6 * cos(3pi/8) - * R5 = (Y1,Y7) - * R7 = (C1,C7) - * res: - * R1=Y2, R0=Y6 - */ - A1=R7.L*R1.H, A0=R7.H*R1.H (IS) || I0+=4 || R5.H=W[I0]; - R1=(A1-=R7.H*R1.L), R0=(A0+=R7.L*R1.L) (IS) || R5.L=W[I1--] || R7=[I3++]; - /* - * Y0 = Y0 + Y6. - * Y4 = Y4 + Y2. - * Y2 = Y4 - Y2. - * Y6 = Y0 - Y6. - * R3 is saved - * R6.l=Y3 - * note: R3: Y0, R2: Y4, R1: Y2, R0: Y6 - */ - R3=R3+R0, R0=R3-R0; - R2=R2+R1, R1=R2-R1 || [TMP0]=R3 || R6.L=W[I0--]; - /* - * Compute the odd portion (1,3,5,7) even is done. - * - * Y1 = C7 * Y1 - C1 * Y7 + C3 * Y5 - C5 * Y3. - * Y7 = C1 * Y1 + C7 * Y7 + C5 * Y5 + C3 * Y3. - * Y5 = C5 * Y1 + C3 * Y7 + C7 * Y5 - C1 * Y3. - * Y3 = C3 * Y1 - C5 * Y7 - C1 * Y5 - C7 * Y3. - */ - // R5=(Y1,Y7) R6=(Y5,Y3) // R7=(C1,C7) - A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || [TMP1]=R2 || R6.H=W[I2--]; - A1-=R7.H*R5.L, A0+=R7.L*R5.L (IS) || I0-=4 || R7=[I3++]; - A1+=R7.H*R6.H, A0+=R7.L*R6.H (IS) || I0+=M1; // R7=(C3,C5) - R3 =(A1-=R7.L*R6.L), R2 =(A0+=R7.H*R6.L) (IS); - A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || R4=[TMP0]; - A1+=R7.H*R5.L, A0-=R7.L*R5.L (IS) || I1+=M1 || R7=[I3++]; // R7=(C1,C7) - A1+=R7.L*R6.H, A0-=R7.H*R6.H (IS); - R7 =(A1-=R7.H*R6.L), R6 =(A0-=R7.L*R6.L) (IS) || I2+=M1; - // R3=Y1, R2=Y7, R7=Y5, R6=Y3 - - /* Transpose write column. */ - R5.H=R4+R2 (RND20); // Y0=Y0+Y7 - R5.L=R4-R2 (RND20) || R4 = [TMP1]; // Y7=Y7-Y0 - R5=R5>>>2(v); - R2.H=R1+R7 (RND20) || W[P0++P3]=R5.H; // Y2=Y2+Y5 st Y0 - R2.L=R1-R7 (RND20) || W[P1++P4]=R5.L || R7=[I3++]; // Y5=Y2-Y5 st Y7 - R2=R2>>>2(v); - R5.H=R0-R3 (RND20) || W[P0++P3]=R2.H || R1.L=W[I1++]; // Y1=Y6-Y1 st Y2 - R5.L=R0+R3 (RND20) || W[P1++P4]=R2.L || R0.H=W[I0++]; // Y6=Y6+Y1 st Y5 - R5=R5>>>2(v); - R3.H=R4-R6 (RND20) || W[P0++P3]=R5.H || R0.L=W[I2++]; // Y3=Y3-Y4 st Y1 - R3.L=R4+R6 (RND20) || W[P1++P4]=R5.L || R1.H=W[I0++]; // Y4=Y3+Y4 st Y6 - R3=R3>>>2(v); - /* pipeline loop start, + drain Y3, Y4 */ - A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || W[P0++P2]= R3.H || R1.H = W[I0--]; -.3: R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || W[P1++P5]= R3.L || R7 = [I3++]; - - L3 = 0; - (R7:4,P5:3)=[SP++]; - unlink; - RTS; -DEFUN_END(vp3_idct) diff --git a/libavcodec/bink.c b/libavcodec/bink.c index f23542f17..bc3d25c73 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -24,9 +24,9 @@ #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "avcodec.h" -#include "dsputil.h" #include "binkdata.h" #include "binkdsp.h" +#include "blockdsp.h" #include "hpeldsp.h" #include "internal.h" #include "mathops.h" @@ -113,9 +113,9 @@ typedef struct Bundle { */ typedef struct BinkContext { AVCodecContext *avctx; - DSPContext dsp; + BlockDSPContext bdsp; HpelDSPContext hdsp; - BinkDSPContext bdsp; + BinkDSPContext binkdsp; AVFrame *last; int version; ///< internal Bink file version int has_alpha; @@ -873,7 +873,7 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, dctblock[0] = binkb_get_value(c, BINKB_SRC_INTRA_DC); qp = binkb_get_value(c, BINKB_SRC_INTRA_Q); read_dct_coeffs(gb, dctblock, bink_scan, (const int32_t (*)[64])binkb_intra_quant, qp); - c->bdsp.idct_put(dst, stride, dctblock); + c->binkdsp.idct_put(dst, stride, dctblock); break; case 3: xoff = binkb_get_value(c, BINKB_SRC_X_OFF); @@ -886,10 +886,10 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, } else { put_pixels8x8_overlapped(dst, ref, stride); } - c->dsp.clear_block(block); + c->bdsp.clear_block(block); v = binkb_get_value(c, BINKB_SRC_INTER_COEFS); read_residue(gb, block, v); - c->dsp.add_pixels8(dst, block, stride); + c->binkdsp.add_pixels8(dst, block, stride); break; case 4: xoff = binkb_get_value(c, BINKB_SRC_X_OFF); @@ -906,11 +906,11 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, dctblock[0] = binkb_get_value(c, BINKB_SRC_INTER_DC); qp = binkb_get_value(c, BINKB_SRC_INTER_Q); read_dct_coeffs(gb, dctblock, bink_scan, (const int32_t (*)[64])binkb_inter_quant, qp); - c->bdsp.idct_add(dst, stride, dctblock); + c->binkdsp.idct_add(dst, stride, dctblock); break; case 5: v = binkb_get_value(c, BINKB_SRC_COLORS); - c->dsp.fill_block_tab[1](dst, v, stride, 8); + c->bdsp.fill_block_tab[1](dst, v, stride, 8); break; case 6: for (i = 0; i < 2; i++) @@ -1049,11 +1049,11 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = get_value(c, BINK_SRC_INTRA_DC); read_dct_coeffs(gb, dctblock, bink_scan, bink_intra_quant, -1); - c->bdsp.idct_put(ublock, 8, dctblock); + c->binkdsp.idct_put(ublock, 8, dctblock); break; case FILL_BLOCK: v = get_value(c, BINK_SRC_COLORS); - c->dsp.fill_block_tab[0](dst, v, stride, 16); + c->bdsp.fill_block_tab[0](dst, v, stride, 16); break; case PATTERN_BLOCK: for (i = 0; i < 2; i++) @@ -1074,7 +1074,7 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, return AVERROR_INVALIDDATA; } if (blk != FILL_BLOCK) - c->bdsp.scale_block(ublock, dst, stride); + c->binkdsp.scale_block(ublock, dst, stride); bx++; dst += 8; prev += 8; @@ -1123,20 +1123,20 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, return AVERROR_INVALIDDATA; } c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); - c->dsp.clear_block(block); + c->bdsp.clear_block(block); v = get_bits(gb, 7); read_residue(gb, block, v); - c->dsp.add_pixels8(dst, block, stride); + c->binkdsp.add_pixels8(dst, block, stride); break; case INTRA_BLOCK: memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = get_value(c, BINK_SRC_INTRA_DC); read_dct_coeffs(gb, dctblock, bink_scan, bink_intra_quant, -1); - c->bdsp.idct_put(dst, stride, dctblock); + c->binkdsp.idct_put(dst, stride, dctblock); break; case FILL_BLOCK: v = get_value(c, BINK_SRC_COLORS); - c->dsp.fill_block_tab[1](dst, v, stride, 8); + c->bdsp.fill_block_tab[1](dst, v, stride, 8); break; case INTER_BLOCK: xoff = get_value(c, BINK_SRC_X_OFF); @@ -1151,7 +1151,7 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = get_value(c, BINK_SRC_INTER_DC); read_dct_coeffs(gb, dctblock, bink_scan, bink_inter_quant, -1); - c->bdsp.idct_add(dst, stride, dctblock); + c->binkdsp.idct_add(dst, stride, dctblock); break; case PATTERN_BLOCK: for (i = 0; i < 2; i++) @@ -1306,9 +1306,9 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->pix_fmt = c->has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P; - ff_dsputil_init(&c->dsp, avctx); + ff_blockdsp_init(&c->bdsp, avctx); ff_hpeldsp_init(&c->hdsp, avctx->flags); - ff_binkdsp_init(&c->bdsp); + ff_binkdsp_init(&c->binkdsp); if ((ret = init_bundles(c)) < 0) { free_bundles(c); diff --git a/libavcodec/binkdsp.c b/libavcodec/binkdsp.c index a23f9c73b..9d70e2326 100644 --- a/libavcodec/binkdsp.c +++ b/libavcodec/binkdsp.c @@ -24,8 +24,8 @@ * Bink DSP routines */ +#include "config.h" #include "libavutil/attributes.h" -#include "dsputil.h" #include "binkdsp.h" #define A1 2896 /* (1/sqrt(2))<<12 */ @@ -129,9 +129,29 @@ static void scale_block_c(const uint8_t src[64]/*align 8*/, uint8_t *dst/*align } } +static void add_pixels8_c(uint8_t *av_restrict pixels, int16_t *block, + int line_size) +{ + int i; + + for (i = 0; i < 8; i++) { + pixels[0] += block[0]; + pixels[1] += block[1]; + pixels[2] += block[2]; + pixels[3] += block[3]; + pixels[4] += block[4]; + pixels[5] += block[5]; + pixels[6] += block[6]; + pixels[7] += block[7]; + pixels += line_size; + block += 8; + } +} + av_cold void ff_binkdsp_init(BinkDSPContext *c) { c->idct_add = bink_idct_add_c; c->idct_put = bink_idct_put_c; c->scale_block = scale_block_c; + c->add_pixels8 = add_pixels8_c; } diff --git a/libavcodec/binkdsp.h b/libavcodec/binkdsp.h index 6b84e014a..f319d1ffe 100644 --- a/libavcodec/binkdsp.h +++ b/libavcodec/binkdsp.h @@ -33,6 +33,7 @@ typedef struct BinkDSPContext { void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, int32_t *block/*align 16*/); void (*idct_add)(uint8_t *dest/*align 8*/, int line_size, int32_t *block/*align 16*/); void (*scale_block)(const uint8_t src[64]/*align 8*/, uint8_t *dst/*align 8*/, int linesize); + void (*add_pixels8)(uint8_t *pixels, int16_t *block, int line_size); } BinkDSPContext; void ff_binkdsp_init(BinkDSPContext *c); diff --git a/libavcodec/bit_depth_template.c b/libavcodec/bit_depth_template.c index 56c2935a2..80184892f 100644 --- a/libavcodec/bit_depth_template.c +++ b/libavcodec/bit_depth_template.c @@ -16,6 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "mathops.h" #include "rnd_avg.h" #include "libavutil/intreadwrite.h" diff --git a/libavcodec/bitstream.c b/libavcodec/bitstream.c index e90732287..d041643ef 100644 --- a/libavcodec/bitstream.c +++ b/libavcodec/bitstream.c @@ -117,6 +117,7 @@ static int alloc_table(VLC *vlc, int size, int use_static) vlc->table_size = 0; return AVERROR(ENOMEM); } + memset(vlc->table + vlc->table_allocated - (1 << vlc->bits), 0, sizeof(VLC_TYPE) * 2 << vlc->bits); } return index; } @@ -162,7 +163,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, int table_size, table_index, index, code_prefix, symbol, subtable_bits; int i, j, k, n, nb, inc; uint32_t code; - VLC_TYPE (*table)[2]; + volatile VLC_TYPE (* volatile table)[2]; // the double volatile is needed to prevent a internal compiler error in gcc 4.2 table_size = 1 << table_nb_bits; if (table_nb_bits > 30) @@ -171,12 +172,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, av_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]; - - for (i = 0; i < table_size; i++) { - table[i][1] = 0; //bits - table[i][0] = -1; //codes - } + table = (volatile VLC_TYPE (*)[2])&vlc->table[table_index]; /* first pass: map codes and compute auxiliary table sizes */ for (i = 0; i < nb_codes; i++) { @@ -194,8 +190,9 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, inc = 1 << n; } for (k = 0; k < nb; k++) { + int bits = table[j][1]; av_dlog(NULL, "%4x: code=%d n=%d\n", j, i, n); - if (table[j][1] /*bits*/ != 0) { + if (bits != 0 && bits != n) { av_log(NULL, AV_LOG_ERROR, "incorrect codes\n"); return AVERROR_INVALIDDATA; } @@ -230,12 +227,17 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, if (index < 0) return index; /* note: realloc has been done, so reload tables */ - table = &vlc->table[table_index]; + table = (volatile VLC_TYPE (*)[2])&vlc->table[table_index]; table[j][0] = index; //code - av_assert0(table[j][0] == index); i = k-1; } } + + for (i = 0; i < table_size; i++) { + if (table[i][1] == 0) //bits + table[i][0] = -1; //codes + } + return table_index; } @@ -266,7 +268,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, 'use_static' should be set to 1 for tables, which should be freed with av_free_static(), 0 if ff_free_vlc() will be used. */ -int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, +int ff_init_vlc_sparse(VLC *vlc_arg, 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, @@ -275,25 +277,22 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, VLCcode *buf; int i, j, ret; VLCcode localbuf[1500]; // the maximum currently needed is 1296 by rv34 - void *state; + VLC localvlc, *vlc; + vlc = vlc_arg; vlc->bits = nb_bits; if (flags & INIT_VLC_USE_NEW_STATIC) { - while (state = avpriv_atomic_ptr_cas(&vlc->init_state, NULL, vlc)) { - if (state == vlc + 1) { - av_assert0(vlc->table_size && vlc->table_size == vlc->table_allocated); - return 0; - } - } - av_assert0(!vlc->table_size); av_assert0(nb_codes + 1 <= FF_ARRAY_ELEMS(localbuf)); buf = localbuf; + localvlc = *vlc_arg; + vlc = &localvlc; + vlc->table_size = 0; } else { vlc->table = NULL; vlc->table_allocated = 0; vlc->table_size = 0; - buf = av_malloc((nb_codes + 1) * sizeof(VLCcode)); + buf = av_malloc_array((nb_codes + 1), sizeof(VLCcode)); if (!buf) return AVERROR(ENOMEM); } @@ -340,9 +339,9 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, if (flags & INIT_VLC_USE_NEW_STATIC) { if(vlc->table_size != vlc->table_allocated) av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", vlc->table_size, vlc->table_allocated); - state = avpriv_atomic_ptr_cas(&vlc->init_state, vlc, vlc+1); - av_assert0(state == vlc); + av_assert0(ret >= 0); + *vlc_arg = *vlc; } else { av_free(buf); if (ret < 0) { diff --git a/libavcodec/blockdsp.c b/libavcodec/blockdsp.c new file mode 100644 index 000000000..f5259f637 --- /dev/null +++ b/libavcodec/blockdsp.c @@ -0,0 +1,80 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "avcodec.h" +#include "blockdsp.h" +#include "version.h" + +static void clear_block_8_c(int16_t *block) +{ + memset(block, 0, sizeof(int16_t) * 64); +} + +static void clear_blocks_8_c(int16_t *blocks) +{ + memset(blocks, 0, sizeof(int16_t) * 6 * 64); +} + +static void fill_block16_c(uint8_t *block, uint8_t value, int line_size, int h) +{ + int i; + + for (i = 0; i < h; i++) { + memset(block, value, 16); + block += line_size; + } +} + +static void fill_block8_c(uint8_t *block, uint8_t value, int line_size, int h) +{ + int i; + + for (i = 0; i < h; i++) { + memset(block, value, 8); + block += line_size; + } +} + +av_cold void ff_blockdsp_init(BlockDSPContext *c, AVCodecContext *avctx) +{ + const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; + + c->clear_block = clear_block_8_c; + c->clear_blocks = clear_blocks_8_c; + + c->fill_block_tab[0] = fill_block16_c; + c->fill_block_tab[1] = fill_block8_c; + + if (ARCH_ALPHA) + ff_blockdsp_init_alpha(c, high_bit_depth); + if (ARCH_ARM) + ff_blockdsp_init_arm(c, high_bit_depth); + if (ARCH_PPC) + ff_blockdsp_init_ppc(c, high_bit_depth); + if (ARCH_X86) +#if FF_API_XVMC + ff_blockdsp_init_x86(c, high_bit_depth, avctx); +#else + ff_blockdsp_init_x86(c, high_bit_depth); +#endif /* FF_API_XVMC */ +} diff --git a/libavcodec/blockdsp.h b/libavcodec/blockdsp.h new file mode 100644 index 000000000..c7ad265db --- /dev/null +++ b/libavcodec/blockdsp.h @@ -0,0 +1,53 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_BLOCKDSP_H +#define AVCODEC_BLOCKDSP_H + +#include + +#include "avcodec.h" +#include "version.h" + +/* add and put pixel (decoding) + * Block sizes for op_pixels_func are 8x4,8x8 16x8 16x16. + * h for op_pixels_func is limited to { width / 2, width }, + * but never larger than 16 and never smaller than 4. */ +typedef void (*op_fill_func)(uint8_t *block /* align width (8 or 16) */, + uint8_t value, int line_size, int h); + +typedef struct BlockDSPContext { + void (*clear_block)(int16_t *block /* align 16 */); + void (*clear_blocks)(int16_t *blocks /* align 16 */); + + op_fill_func fill_block_tab[2]; +} BlockDSPContext; + +void ff_blockdsp_init(BlockDSPContext *c, AVCodecContext *avctx); + +void ff_blockdsp_init_alpha(BlockDSPContext *c, unsigned high_bit_depth); +void ff_blockdsp_init_arm(BlockDSPContext *c, unsigned high_bit_depth); +void ff_blockdsp_init_ppc(BlockDSPContext *c, unsigned high_bit_depth); +#if FF_API_XVMC +void ff_blockdsp_init_x86(BlockDSPContext *c, unsigned high_bit_depth, + AVCodecContext *avctx); +#else +void ff_blockdsp_init_x86(BlockDSPContext *c, unsigned high_bit_depth); +#endif /* FF_API_XVMC */ + +#endif /* AVCODEC_BLOCKDSP_H */ diff --git a/libavcodec/bmp.c b/libavcodec/bmp.c index 404c47dec..458fd0c76 100644 --- a/libavcodec/bmp.c +++ b/libavcodec/bmp.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "avcodec.h" #include "bytestream.h" #include "bmp.h" @@ -58,7 +60,7 @@ static int bmp_decode_frame(AVCodecContext *avctx, fsize = bytestream_get_le32(&buf); if (buf_size < fsize) { - av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d), trying to decode anyway\n", + av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %u), trying to decode anyway\n", buf_size, fsize); fsize = buf_size; } @@ -68,8 +70,8 @@ static int bmp_decode_frame(AVCodecContext *avctx, hsize = bytestream_get_le32(&buf); /* header size */ ihsize = bytestream_get_le32(&buf); /* more header size */ - if (ihsize + 14 > hsize) { - av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize); + if (ihsize + 14LL > hsize) { + av_log(avctx, AV_LOG_ERROR, "invalid header size %u\n", hsize); return AVERROR_INVALIDDATA; } @@ -78,7 +80,8 @@ static int bmp_decode_frame(AVCodecContext *avctx, fsize = buf_size - 2; if (fsize <= hsize) { - av_log(avctx, AV_LOG_ERROR, "declared file size is less than header size (%d < %d)\n", + av_log(avctx, AV_LOG_ERROR, + "Declared file size is less than header size (%u < %u)\n", fsize, hsize); return AVERROR_INVALIDDATA; } @@ -125,6 +128,7 @@ static int bmp_decode_frame(AVCodecContext *avctx, rgb[0] = bytestream_get_le32(&buf); rgb[1] = bytestream_get_le32(&buf); rgb[2] = bytestream_get_le32(&buf); + if (ihsize > 40) alpha = bytestream_get_le32(&buf); } @@ -166,7 +170,9 @@ static int bmp_decode_frame(AVCodecContext *avctx, else if (rgb[0] == 0x0F00 && rgb[1] == 0x00F0 && rgb[2] == 0x000F) avctx->pix_fmt = AV_PIX_FMT_RGB444; else { - av_log(avctx, AV_LOG_ERROR, "Unknown bitfields %0X %0X %0X\n", rgb[0], rgb[1], rgb[2]); + av_log(avctx, AV_LOG_ERROR, + "Unknown bitfields %0"PRIX32" %0"PRIX32" %0"PRIX32"\n", + rgb[0], rgb[1], rgb[2]); return AVERROR(EINVAL); } } @@ -182,12 +188,13 @@ static int bmp_decode_frame(AVCodecContext *avctx, if (hsize - ihsize - 14 > 0) { avctx->pix_fmt = AV_PIX_FMT_PAL8; } else { - av_log(avctx, AV_LOG_ERROR, "Unknown palette for %d-colour BMP\n", 1< (1 << depth)) { - av_log(avctx, AV_LOG_ERROR, "Incorrect number of colors - %X for bitdepth %d\n", t, depth); + av_log(avctx, AV_LOG_ERROR, + "Incorrect number of colors - %X for bitdepth %u\n", + t, depth); } else if (t) { colors = t; } + } else { + colors = FFMIN(256, (hsize-ihsize-14) / 3); } buf = buf0 + 14 + ihsize; //palette location // OS/2 bitmap, 3 bytes per palette entry diff --git a/libavcodec/bmp_parser.c b/libavcodec/bmp_parser.c index 06ed367b3..eae8ae0a7 100644 --- a/libavcodec/bmp_parser.c +++ b/libavcodec/bmp_parser.c @@ -25,6 +25,8 @@ */ #include "libavutil/bswap.h" +#include "libavutil/common.h" + #include "parser.h" typedef struct BMPParseContext { @@ -42,8 +44,6 @@ static int bmp_parse(AVCodecParserContext *s, AVCodecContext *avctx, int next = END_NOT_FOUND; int i = 0; - s->pict_type = AV_PICTURE_TYPE_NONE; - *poutbuf_size = 0; if (buf_size == 0) return 0; diff --git a/libavcodec/bmvaudio.c b/libavcodec/bmvaudio.c new file mode 100644 index 000000000..0e473df90 --- /dev/null +++ b/libavcodec/bmvaudio.c @@ -0,0 +1,89 @@ +/* + * Discworld II BMV audio decoder + * Copyright (c) 2011 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" + +#include "avcodec.h" +#include "internal.h" + +static const int bmv_aud_mults[16] = { + 16512, 8256, 4128, 2064, 1032, 516, 258, 192, 129, 88, 64, 56, 48, 40, 36, 32 +}; + +static av_cold int bmv_aud_decode_init(AVCodecContext *avctx) +{ + avctx->channels = 2; + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + return 0; +} + +static int bmv_aud_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int blocks = 0, total_blocks, i; + int ret; + int16_t *output_samples; + int scale[2]; + + total_blocks = *buf++; + if (buf_size < total_blocks * 65 + 1) { + av_log(avctx, AV_LOG_ERROR, "expected %d bytes, got %d\n", + total_blocks * 65 + 1, buf_size); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = total_blocks * 32; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + output_samples = (int16_t *)frame->data[0]; + + for (blocks = 0; blocks < total_blocks; blocks++) { + uint8_t code = *buf++; + code = (code >> 1) | (code << 7); + scale[0] = bmv_aud_mults[code & 0xF]; + scale[1] = bmv_aud_mults[code >> 4]; + for (i = 0; i < 32; i++) { + *output_samples++ = av_clip_int16((scale[0] * (int8_t)*buf++) >> 5); + *output_samples++ = av_clip_int16((scale[1] * (int8_t)*buf++) >> 5); + } + } + + *got_frame_ptr = 1; + + return buf_size; +} + +AVCodec ff_bmv_audio_decoder = { + .name = "bmv_audio", + .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV audio"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_BMV_AUDIO, + .init = bmv_aud_decode_init, + .decode = bmv_aud_decode_frame, + .capabilities = CODEC_CAP_DR1, +}; diff --git a/libavcodec/bmv.c b/libavcodec/bmvvideo.c similarity index 82% rename from libavcodec/bmv.c rename to libavcodec/bmvvideo.c index baa1c8b6f..5143b2a76 100644 --- a/libavcodec/bmv.c +++ b/libavcodec/bmvvideo.c @@ -1,5 +1,5 @@ /* - * Discworld II BMV video and audio decoder + * Discworld II BMV video decoder * Copyright (c) 2011 Konstantin Shishkov * * This file is part of FFmpeg. @@ -20,7 +20,8 @@ */ #include "libavutil/avassert.h" -#include "libavutil/channel_layout.h" +#include "libavutil/common.h" + #include "avcodec.h" #include "bytestream.h" #include "internal.h" @@ -285,59 +286,6 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -static const int bmv_aud_mults[16] = { - 16512, 8256, 4128, 2064, 1032, 516, 258, 192, 129, 88, 64, 56, 48, 40, 36, 32 -}; - -static av_cold int bmv_aud_decode_init(AVCodecContext *avctx) -{ - avctx->channels = 2; - avctx->channel_layout = AV_CH_LAYOUT_STEREO; - avctx->sample_fmt = AV_SAMPLE_FMT_S16; - - return 0; -} - -static int bmv_aud_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame_ptr, AVPacket *avpkt) -{ - AVFrame *frame = data; - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; - int blocks = 0, total_blocks, i; - int ret; - int16_t *output_samples; - int scale[2]; - - total_blocks = *buf++; - if (buf_size < total_blocks * 65 + 1) { - av_log(avctx, AV_LOG_ERROR, "expected %d bytes, got %d\n", - total_blocks * 65 + 1, buf_size); - return AVERROR_INVALIDDATA; - } - - /* get output buffer */ - frame->nb_samples = total_blocks * 32; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; - output_samples = (int16_t *)frame->data[0]; - - for (blocks = 0; blocks < total_blocks; blocks++) { - uint8_t code = *buf++; - code = (code >> 1) | (code << 7); - scale[0] = bmv_aud_mults[code & 0xF]; - scale[1] = bmv_aud_mults[code >> 4]; - for (i = 0; i < 32; i++) { - *output_samples++ = av_clip_int16((scale[0] * (int8_t)*buf++) >> 5); - *output_samples++ = av_clip_int16((scale[1] * (int8_t)*buf++) >> 5); - } - } - - *got_frame_ptr = 1; - - return buf_size; -} - AVCodec ff_bmv_video_decoder = { .name = "bmv_video", .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV video"), @@ -348,13 +296,3 @@ AVCodec ff_bmv_video_decoder = { .decode = decode_frame, .capabilities = CODEC_CAP_DR1, }; - -AVCodec ff_bmv_audio_decoder = { - .name = "bmv_audio", - .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_BMV_AUDIO, - .init = bmv_aud_decode_init, - .decode = bmv_aud_decode_frame, - .capabilities = CODEC_CAP_DR1, -}; diff --git a/libavcodec/brender_pix.c b/libavcodec/brender_pix.c deleted file mode 100644 index 23a46cc0e..000000000 --- a/libavcodec/brender_pix.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * BRender PIX (.pix) image decoder - * Copyright (c) 2012 Aleksi Nurmi - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * Tested against samples from I-War / Independence War and Defiance. - * If the PIX file does not contain a palette, the - * palette_has_changed property of the AVFrame is set to 0. - */ - -#include "libavutil/imgutils.h" -#include "avcodec.h" -#include "bytestream.h" -#include "internal.h" - -typedef struct BRPixHeader { - int format; - unsigned int width, height; -} BRPixHeader; - -static int brpix_decode_header(BRPixHeader *out, GetByteContext *pgb) -{ - unsigned int header_len = bytestream2_get_be32(pgb); - - out->format = bytestream2_get_byte(pgb); - bytestream2_skip(pgb, 2); - out->width = bytestream2_get_be16(pgb); - out->height = bytestream2_get_be16(pgb); - - // the header is at least 11 bytes long; we read the first 7 - if (header_len < 11) { - return 0; - } - - // skip the rest of the header - bytestream2_skip(pgb, header_len-7); - - return 1; -} - -static int brpix_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) -{ - AVFrame *frame = data; - - int ret; - GetByteContext gb; - - unsigned int bytes_pp; - - unsigned int magic[4]; - unsigned int chunk_type; - unsigned int data_len; - BRPixHeader hdr; - - bytestream2_init(&gb, avpkt->data, avpkt->size); - - magic[0] = bytestream2_get_be32(&gb); - magic[1] = bytestream2_get_be32(&gb); - magic[2] = bytestream2_get_be32(&gb); - magic[3] = bytestream2_get_be32(&gb); - - if (magic[0] != 0x12 || - magic[1] != 0x8 || - magic[2] != 0x2 || - magic[3] != 0x2) { - av_log(avctx, AV_LOG_ERROR, "Not a BRender PIX file\n"); - return AVERROR_INVALIDDATA; - } - - chunk_type = bytestream2_get_be32(&gb); - if (chunk_type != 0x3 && chunk_type != 0x3d) { - av_log(avctx, AV_LOG_ERROR, "Invalid chunk type %d\n", chunk_type); - return AVERROR_INVALIDDATA; - } - - ret = brpix_decode_header(&hdr, &gb); - if (!ret) { - av_log(avctx, AV_LOG_ERROR, "Invalid header length\n"); - return AVERROR_INVALIDDATA; - } - switch (hdr.format) { - case 3: - avctx->pix_fmt = AV_PIX_FMT_PAL8; - bytes_pp = 1; - break; - case 4: - avctx->pix_fmt = AV_PIX_FMT_RGB555BE; - bytes_pp = 2; - break; - case 5: - avctx->pix_fmt = AV_PIX_FMT_RGB565BE; - bytes_pp = 2; - break; - case 6: - avctx->pix_fmt = AV_PIX_FMT_RGB24; - bytes_pp = 3; - break; - case 7: - avctx->pix_fmt = AV_PIX_FMT_0RGB; - bytes_pp = 4; - break; - case 18: - avctx->pix_fmt = AV_PIX_FMT_GRAY8A; - bytes_pp = 2; - break; - default: - av_log(avctx, AV_LOG_ERROR, "Format %d is not supported\n", - hdr.format); - return AVERROR_PATCHWELCOME; - } - - if ((ret = ff_set_dimensions(avctx, hdr.width, hdr.height)) < 0) - return ret; - - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; - - chunk_type = bytestream2_get_be32(&gb); - - if (avctx->pix_fmt == AV_PIX_FMT_PAL8 && - (chunk_type == 0x3 || chunk_type == 0x3d)) { - BRPixHeader palhdr; - uint32_t *pal_out = (uint32_t *)frame->data[1]; - int i; - - ret = brpix_decode_header(&palhdr, &gb); - if (!ret) { - av_log(avctx, AV_LOG_ERROR, "Invalid palette header length\n"); - return AVERROR_INVALIDDATA; - } - if (palhdr.format != 7) { - av_log(avctx, AV_LOG_ERROR, "Palette is not in 0RGB format\n"); - return AVERROR_INVALIDDATA; - } - - chunk_type = bytestream2_get_be32(&gb); - data_len = bytestream2_get_be32(&gb); - bytestream2_skip(&gb, 8); - if (chunk_type != 0x21 || data_len != 1032 || - bytestream2_get_bytes_left(&gb) < 1032) { - av_log(avctx, AV_LOG_ERROR, "Invalid palette data\n"); - return AVERROR_INVALIDDATA; - } - // convert 0RGB to machine endian format (ARGB32) - for (i = 0; i < 256; ++i) { - bytestream2_skipu(&gb, 1); - *pal_out++ = (0xFFU << 24) | bytestream2_get_be24u(&gb); - } - bytestream2_skip(&gb, 8); - - frame->palette_has_changed = 1; - - chunk_type = bytestream2_get_be32(&gb); - } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { - uint32_t *pal_out = (uint32_t *)frame->data[1]; - int i; - - for (i = 0; i < 256; ++i) { - *pal_out++ = (0xFFU << 24) | (i * 0x010101); - } - frame->palette_has_changed = 1; - } - - data_len = bytestream2_get_be32(&gb); - bytestream2_skip(&gb, 8); - - // read the image data to the buffer - { - unsigned int bytes_per_scanline = bytes_pp * hdr.width; - unsigned int bytes_left = bytestream2_get_bytes_left(&gb); - - if (chunk_type != 0x21 || data_len != bytes_left || - bytes_left / bytes_per_scanline < hdr.height) - { - av_log(avctx, AV_LOG_ERROR, "Invalid image data\n"); - return AVERROR_INVALIDDATA; - } - - av_image_copy_plane(frame->data[0], frame->linesize[0], - avpkt->data + bytestream2_tell(&gb), - bytes_per_scanline, - bytes_per_scanline, hdr.height); - } - - *got_frame = 1; - - return avpkt->size; -} - -AVCodec ff_brender_pix_decoder = { - .name = "brender_pix", - .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_BRENDER_PIX, - .decode = brpix_decode_frame, - .capabilities = CODEC_CAP_DR1, -}; diff --git a/libavcodec/brenderpix.c b/libavcodec/brenderpix.c new file mode 100644 index 000000000..e0d033fcf --- /dev/null +++ b/libavcodec/brenderpix.c @@ -0,0 +1,292 @@ +/* + * BRender PIX (.pix) image decoder + * Copyright (c) 2012 Aleksi Nurmi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Tested against samples from I-War / Independence War and Defiance. */ + +#include "libavutil/imgutils.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#define HEADER1_CHUNK 0x03 +#define HEADER2_CHUNK 0x3D +#define IMAGE_DATA_CHUNK 0x21 + +/* In 8-bit colour mode, 256 colours are available at any time. Which 256 + * colours are available is determined by the contents of the hardware palette + * (or CLUT). In this case, the palette supplied with BRender (std.pal) has + * been loaded into the CLUT. + * + * The 256 colours in std.pal are divided into seven ranges, or `colour ramps'. + * The first 64 colours represent shades of grey ranging from very dark grey + * (black) to very light grey (white). The following colours are 32-element + * ramps for six colours as shown below. + */ +static const uint32_t std_pal_table[256] = { + // gray + 0xFF000000, 0xFF030303, 0xFF060606, 0xFF090909, 0xFF0C0C0C, 0xFF0F0F0F, + 0xFF121212, 0xFF151515, 0xFF181818, 0xFF1B1B1B, 0xFF1E1E1E, 0xFF212121, + 0xFF242424, 0xFF272727, 0xFF2A2A2A, 0xFF2D2D2D, 0xFF313131, 0xFF343434, + 0xFF373737, 0xFF3A3A3A, 0xFF3D3D3D, 0xFF404040, 0xFF434343, 0xFF464646, + 0xFF494949, 0xFF4C4C4C, 0xFF4F4F4F, 0xFF525252, 0xFF555555, 0xFF585858, + 0xFF5B5B5B, 0xFF5E5E5E, 0xFF626262, 0xFF656565, 0xFF686868, 0xFF6B6B6B, + 0xFF6E6E6E, 0xFF717171, 0xFF747474, 0xFF777777, 0xFF7A7A7A, 0xFF7D7D7D, + 0xFF808080, 0xFF838383, 0xFF868686, 0xFF898989, 0xFF8C8C8C, 0xFF8F8F8F, + 0xFF939393, 0xFF999999, 0xFFA0A0A0, 0xFFA7A7A7, 0xFFAEAEAE, 0xFFB4B4B4, + 0xFFBBBBBB, 0xFFC2C2C2, 0xFFC9C9C9, 0xFFCFCFCF, 0xFFD6D6D6, 0xFFDDDDDD, + 0xFFE4E4E4, 0xFFEAEAEA, 0xFFF1F1F1, 0xFFF8F8F8, + + // blue + 0xFF000000, 0xFF020209, 0xFF050513, 0xFF07071D, 0xFF0A0A27, 0xFF0C0C31, + 0xFF0F0F3B, 0xFF111145, 0xFF14144F, 0xFF161659, 0xFF181863, 0xFF1B1B6D, + 0xFF1E1E77, 0xFF202080, 0xFF22228A, 0xFF252594, 0xFF28289E, 0xFF2A2AA8, + 0xFF2D2DB2, 0xFF2F2FBC, 0xFF3131C6, 0xFF3434D0, 0xFF3737DA, 0xFF3939E4, + 0xFF3C3CEE, 0xFF5454F0, 0xFF6C6CF2, 0xFF8585F4, 0xFF9D9DF6, 0xFFB5B5F8, + 0xFFCECEFA, 0xFFE6E6FC, + + // green + 0xFF000000, 0xFF020902, 0xFF051305, 0xFF071D07, 0xFF0A270A, 0xFF0C310C, + 0xFF0F3B0F, 0xFF114511, 0xFF144F14, 0xFF165916, 0xFF186318, 0xFF1B6D1B, + 0xFF1E771E, 0xFF208020, 0xFF228A22, 0xFF259425, 0xFF289E28, 0xFF2AA82A, + 0xFF2DB22D, 0xFF2FBC2F, 0xFF31C631, 0xFF34D034, 0xFF37DA37, 0xFF39E439, + 0xFF3CEE3C, 0xFF54F054, 0xFF6CF26C, 0xFF85F485, 0xFF9DF69D, 0xFFB5F8B5, + 0xFFCEFACE, 0xFFE6FCE6, + + // cyan + 0xFF000000, 0xFF020909, 0xFF051313, 0xFF071D1D, 0xFF0A2727, 0xFF0C3131, + 0xFF0F3B3B, 0xFF114545, 0xFF144F4F, 0xFF165959, 0xFF186363, 0xFF1B6D6D, + 0xFF1E7777, 0xFF208080, 0xFF228A8A, 0xFF259494, 0xFF289E9E, 0xFF2AA8A8, + 0xFF2DB2B2, 0xFF2FBCBC, 0xFF31C6C6, 0xFF34D0D0, 0xFF37DADA, 0xFF39E4E4, + 0xFF3CEEEE, 0xFF54F0F0, 0xFF6CF2F2, 0xFF85F4F4, 0xFF9DF6F6, 0xFFB5F8F8, + 0xFFCEFAFA, 0xFFE6FCFC, + + // red + 0xFF000000, 0xFF090202, 0xFF130505, 0xFF1D0707, 0xFF270A0A, 0xFF310C0C, + 0xFF3B0F0F, 0xFF451111, 0xFF4F1414, 0xFF591616, 0xFF631818, 0xFF6D1B1B, + 0xFF771E1E, 0xFF802020, 0xFF8A2222, 0xFF942525, 0xFF9E2828, 0xFFA82A2A, + 0xFFB22D2D, 0xFFBC2F2F, 0xFFC63131, 0xFFD03434, 0xFFDA3737, 0xFFE43939, + 0xFFEE3C3C, 0xFFF05454, 0xFFF26C6C, 0xFFF48585, 0xFFF69D9D, 0xFFF8B5B5, + 0xFFFACECE, 0xFFFCE6E6, + + // magenta + 0xFF000000, 0xFF090209, 0xFF130513, 0xFF1D071D, 0xFF270A27, 0xFF310C31, + 0xFF3B0F3B, 0xFF451145, 0xFF4F144F, 0xFF591659, 0xFF631863, 0xFF6D1B6D, + 0xFF771E77, 0xFF802080, 0xFF8A228A, 0xFF942594, 0xFF9E289E, 0xFFA82AA8, + 0xFFB22DB2, 0xFFBC2FBC, 0xFFC631C6, 0xFFD034D0, 0xFFDA37DA, 0xFFE439E4, + 0xFFEE3CEE, 0xFFF054F0, 0xFFF26CF2, 0xFFF485F4, 0xFFF69DF6, 0xFFF8B5F8, + 0xFFFACEFA, 0xFFFCE6FC, + + // yellow + 0xFF000000, 0xFF090902, 0xFF131305, 0xFF1D1D07, 0xFF27270A, 0xFF31310C, + 0xFF3B3B0F, 0xFF454511, 0xFF4F4F14, 0xFF595916, 0xFF636318, 0xFF6D6D1B, + 0xFF77771E, 0xFF808020, 0xFF8A8A22, 0xFF949425, 0xFF9E9E28, 0xFFA8A82A, + 0xFFB2B22D, 0xFFBCBC2F, 0xFFC6C631, 0xFFD0D034, 0xFFDADA37, 0xFFE4E439, + 0xFFEEEE3C, 0xFFF0F054, 0xFFF2F26C, 0xFFF4F485, 0xFFF6F69D, 0xFFF8F8B5, + 0xFFFAFACE, 0xFFFCFCE6, +}; + +typedef struct PixHeader { + int width; + int height; + int format; +} PixHeader; + +static int pix_decode_header(PixHeader *out, GetByteContext *pgb) +{ + unsigned int header_len = bytestream2_get_be32(pgb); + + out->format = bytestream2_get_byte(pgb); + bytestream2_skip(pgb, 2); + out->width = bytestream2_get_be16(pgb); + out->height = bytestream2_get_be16(pgb); + + // the header is at least 11 bytes long; we read the first 7 + if (header_len < 11) + return AVERROR_INVALIDDATA; + + // skip the rest of the header + bytestream2_skip(pgb, header_len - 7); + + return 0; +} + +static int pix_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + AVFrame *frame = data; + + int ret, i; + GetByteContext gb; + + unsigned int bytes_pp; + unsigned int magic[4]; + unsigned int chunk_type; + unsigned int data_len; + unsigned int bytes_per_scanline; + unsigned int bytes_left; + PixHeader hdr; + + bytestream2_init(&gb, avpkt->data, avpkt->size); + + magic[0] = bytestream2_get_be32(&gb); + magic[1] = bytestream2_get_be32(&gb); + magic[2] = bytestream2_get_be32(&gb); + magic[3] = bytestream2_get_be32(&gb); + + if (magic[0] != 0x12 || + magic[1] != 0x08 || + magic[2] != 0x02 || + magic[3] != 0x02) { + av_log(avctx, AV_LOG_ERROR, "Not a BRender PIX file.\n"); + return AVERROR_INVALIDDATA; + } + + chunk_type = bytestream2_get_be32(&gb); + if (chunk_type != HEADER1_CHUNK && chunk_type != HEADER2_CHUNK) { + av_log(avctx, AV_LOG_ERROR, "Invalid chunk type %d.\n", chunk_type); + return AVERROR_INVALIDDATA; + } + + ret = pix_decode_header(&hdr, &gb); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid header length.\n"); + return ret; + } + switch (hdr.format) { + case 3: + avctx->pix_fmt = AV_PIX_FMT_PAL8; + bytes_pp = 1; + break; + case 4: + avctx->pix_fmt = AV_PIX_FMT_RGB555BE; + bytes_pp = 2; + break; + case 5: + avctx->pix_fmt = AV_PIX_FMT_RGB565BE; + bytes_pp = 2; + break; + case 6: + avctx->pix_fmt = AV_PIX_FMT_RGB24; + bytes_pp = 3; + break; + case 7: + avctx->pix_fmt = AV_PIX_FMT_0RGB; + bytes_pp = 4; + break; + case 8: // ARGB + avctx->pix_fmt = AV_PIX_FMT_ARGB; + bytes_pp = 4; + break; + case 18: + avctx->pix_fmt = AV_PIX_FMT_Y400A; + bytes_pp = 2; + break; + default: + avpriv_request_sample(avctx, "Format %d", hdr.format); + return AVERROR_PATCHWELCOME; + } + + if ((ret = ff_set_dimensions(avctx, hdr.width, hdr.height)) < 0) + return ret; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + chunk_type = bytestream2_get_be32(&gb); + + if (avctx->pix_fmt == AV_PIX_FMT_PAL8 && + (chunk_type == HEADER1_CHUNK || + chunk_type == HEADER2_CHUNK)) { + /* read palette data from data[1] */ + PixHeader palhdr; + uint32_t *pal_out = (uint32_t *)frame->data[1]; + + ret = pix_decode_header(&palhdr, &gb); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid palette header length.\n"); + return ret; + } + if (palhdr.format != 7) + avpriv_request_sample(avctx, "Palette not in RGB format"); + + chunk_type = bytestream2_get_be32(&gb); + data_len = bytestream2_get_be32(&gb); + bytestream2_skip(&gb, 8); + if (chunk_type != IMAGE_DATA_CHUNK || data_len != 1032 || + bytestream2_get_bytes_left(&gb) < 1032) { + av_log(avctx, AV_LOG_ERROR, "Invalid palette data.\n"); + return AVERROR_INVALIDDATA; + } + // palette data is surrounded by 8 null bytes (both top and bottom) + // convert 0RGB to machine endian format (ARGB32) + for (i = 0; i < 256; ++i) + *pal_out++ = (0xFFU << 24) | bytestream2_get_be32u(&gb); + bytestream2_skip(&gb, 8); + + frame->palette_has_changed = 1; + + chunk_type = bytestream2_get_be32(&gb); + } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + /* no palette supplied, use the default one */ + uint32_t *pal_out = (uint32_t *)frame->data[1]; + + // TODO: add an AVOption to load custom palette files + av_log(avctx, AV_LOG_WARNING, + "Using default palette, colors might be off.\n"); + memcpy(pal_out, std_pal_table, sizeof(uint32_t) * 256); + + frame->palette_has_changed = 1; + } + + data_len = bytestream2_get_be32(&gb); + bytestream2_skip(&gb, 8); + + // read the image data to the buffer + bytes_per_scanline = bytes_pp * hdr.width; + bytes_left = bytestream2_get_bytes_left(&gb); + + if (chunk_type != IMAGE_DATA_CHUNK || data_len != bytes_left || + bytes_left / bytes_per_scanline < hdr.height) { + av_log(avctx, AV_LOG_ERROR, "Invalid image data.\n"); + return AVERROR_INVALIDDATA; + } + + av_image_copy_plane(frame->data[0], frame->linesize[0], + avpkt->data + bytestream2_tell(&gb), + bytes_per_scanline, + bytes_per_scanline, hdr.height); + + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + *got_frame = 1; + + return avpkt->size; +} + +AVCodec ff_brender_pix_decoder = { + .name = "brender_pix", + .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_BRENDER_PIX, + .decode = pix_decode_frame, + .capabilities = CODEC_CAP_DR1, +}; diff --git a/libavcodec/bswapdsp.c b/libavcodec/bswapdsp.c new file mode 100644 index 000000000..a6e1ec069 --- /dev/null +++ b/libavcodec/bswapdsp.c @@ -0,0 +1,56 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/bswap.h" +#include "bswapdsp.h" + +static void bswap_buf(uint32_t *dst, const uint32_t *src, int w) +{ + int i; + + for (i = 0; i + 8 <= w; i += 8) { + dst[i + 0] = av_bswap32(src[i + 0]); + dst[i + 1] = av_bswap32(src[i + 1]); + dst[i + 2] = av_bswap32(src[i + 2]); + dst[i + 3] = av_bswap32(src[i + 3]); + dst[i + 4] = av_bswap32(src[i + 4]); + dst[i + 5] = av_bswap32(src[i + 5]); + dst[i + 6] = av_bswap32(src[i + 6]); + dst[i + 7] = av_bswap32(src[i + 7]); + } + for (; i < w; i++) + dst[i + 0] = av_bswap32(src[i + 0]); +} + +static void bswap16_buf(uint16_t *dst, const uint16_t *src, int len) +{ + while (len--) + *dst++ = av_bswap16(*src++); +} + +av_cold void ff_bswapdsp_init(BswapDSPContext *c) +{ + c->bswap_buf = bswap_buf; + c->bswap16_buf = bswap16_buf; + + if (ARCH_X86) + ff_bswapdsp_init_x86(c); +} diff --git a/libavcodec/bswapdsp.h b/libavcodec/bswapdsp.h new file mode 100644 index 000000000..f167d77fe --- /dev/null +++ b/libavcodec/bswapdsp.h @@ -0,0 +1,32 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_BSWAP_BUF_H +#define AVCODEC_BSWAP_BUF_H + +#include + +typedef struct BswapDSPContext { + void (*bswap_buf)(uint32_t *dst, const uint32_t *src, int w); + void (*bswap16_buf)(uint16_t *dst, const uint16_t *src, int len); +} BswapDSPContext; + +void ff_bswapdsp_init(BswapDSPContext *c); +void ff_bswapdsp_init_x86(BswapDSPContext *c); + +#endif /* AVCODEC_BSWAP_BUF_H */ diff --git a/libavcodec/bytestream.h b/libavcodec/bytestream.h index f2458591c..c2cb60180 100644 --- a/libavcodec/bytestream.h +++ b/libavcodec/bytestream.h @@ -328,6 +328,32 @@ static av_always_inline unsigned int bytestream2_get_eof(PutByteContext *p) return p->eof; } +static av_always_inline unsigned int bytestream2_copy_bufferu(PutByteContext *p, + GetByteContext *g, + unsigned int size) +{ + memcpy(p->buffer, g->buffer, size); + p->buffer += size; + g->buffer += size; + return size; +} + +static av_always_inline unsigned int bytestream2_copy_buffer(PutByteContext *p, + GetByteContext *g, + unsigned int size) +{ + int size2; + + if (p->eof) + return 0; + size = FFMIN(g->buffer_end - g->buffer, size); + size2 = FFMIN(p->buffer_end - p->buffer, size); + if (size2 != size) + p->eof = 1; + + return bytestream2_copy_bufferu(p, g, size2); +} + static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, uint8_t *dst, unsigned int size) diff --git a/libavcodec/cabac.h b/libavcodec/cabac.h index d4bafe08e..eb6b521d3 100644 --- a/libavcodec/cabac.h +++ b/libavcodec/cabac.h @@ -31,6 +31,7 @@ #include "put_bits.h" +extern 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 diff --git a/libavcodec/cabac_functions.h b/libavcodec/cabac_functions.h index 7e22064d0..d7d6d7dfd 100644 --- a/libavcodec/cabac_functions.h +++ b/libavcodec/cabac_functions.h @@ -32,11 +32,16 @@ #include "cabac.h" #include "config.h" +#if ARCH_AARCH64 +# include "aarch64/cabac.h" +#endif +#if ARCH_ARM +# include "arm/cabac.h" +#endif #if ARCH_X86 # include "x86/cabac.h" #endif -extern uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63]; static uint8_t * const ff_h264_norm_shift = ff_h264_cabac_tables + H264_NORM_SHIFT_OFFSET; static uint8_t * const ff_h264_lps_range = ff_h264_cabac_tables + H264_LPS_RANGE_OFFSET; static uint8_t * const ff_h264_mlps_state = ff_h264_cabac_tables + H264_MLPS_STATE_OFFSET; diff --git a/libavcodec/cavs.c b/libavcodec/cavs.c index cc544293d..a41a8aa89 100644 --- a/libavcodec/cavs.c +++ b/libavcodec/cavs.c @@ -29,7 +29,9 @@ #include "get_bits.h" #include "golomb.h" #include "h264chroma.h" +#include "idctdsp.h" #include "mathops.h" +#include "qpeldsp.h" #include "cavs.h" static const uint8_t alpha_tab[64] = { @@ -72,15 +74,16 @@ static inline int get_bs(cavs_vector *mvP, cavs_vector *mvQ, int b) { if ((mvP->ref == REF_INTRA) || (mvQ->ref == REF_INTRA)) return 2; - if ((abs(mvP->x - mvQ->x) >= 4) || (abs(mvP->y - mvQ->y) >= 4)) + if((abs(mvP->x - mvQ->x) >= 4) || + (abs(mvP->y - mvQ->y) >= 4) || + (mvP->ref != mvQ->ref)) return 1; if (b) { mvP += MV_BWD_OFFS; mvQ += MV_BWD_OFFS; - if ((abs(mvP->x - mvQ->x) >= 4) || (abs(mvP->y - mvQ->y) >= 4)) - return 1; - } else { - if (mvP->ref != mvQ->ref) + if((abs(mvP->x - mvQ->x) >= 4) || + (abs(mvP->y - mvQ->y) >= 4) || + (mvP->ref != mvQ->ref)) return 1; } return 0; @@ -146,6 +149,8 @@ void ff_cavs_filter(AVSContext *h, enum cavs_mb mb_type) qp_avg = (h->qp + h->left_qp + 1) >> 1; SET_PARAMS; h->cdsp.cavs_filter_lv(h->cy, h->l_stride, alpha, beta, tc, bs[0], bs[1]); + qp_avg = (ff_cavs_chroma_qp[h->qp] + ff_cavs_chroma_qp[h->left_qp] + 1) >> 1; + SET_PARAMS; h->cdsp.cavs_filter_cv(h->cu, h->c_stride, alpha, beta, tc, bs[0], bs[1]); h->cdsp.cavs_filter_cv(h->cv, h->c_stride, alpha, beta, tc, bs[0], bs[1]); } @@ -158,6 +163,8 @@ void ff_cavs_filter(AVSContext *h, enum cavs_mb mb_type) qp_avg = (h->qp + h->top_qp[h->mbx] + 1) >> 1; SET_PARAMS; h->cdsp.cavs_filter_lh(h->cy, h->l_stride, alpha, beta, tc, bs[4], bs[5]); + qp_avg = (ff_cavs_chroma_qp[h->qp] + ff_cavs_chroma_qp[h->top_qp[h->mbx]] + 1) >> 1; + SET_PARAMS; h->cdsp.cavs_filter_ch(h->cu, h->c_stride, alpha, beta, tc, bs[4], bs[5]); h->cdsp.cavs_filter_ch(h->cv, h->c_stride, alpha, beta, tc, bs[4], bs[5]); } @@ -231,9 +238,14 @@ void ff_cavs_load_intra_pred_chroma(AVSContext *h) /* extend borders by one pixel */ h->left_border_u[9] = h->left_border_u[8]; h->left_border_v[9] = h->left_border_v[8]; - h->top_border_u[h->mbx * 10 + 9] = h->top_border_u[h->mbx * 10 + 8]; - h->top_border_v[h->mbx * 10 + 9] = h->top_border_v[h->mbx * 10 + 8]; - if (h->mbx && h->mby) { + if(h->flags & C_AVAIL) { + h->top_border_u[h->mbx*10 + 9] = h->top_border_u[h->mbx*10 + 11]; + h->top_border_v[h->mbx*10 + 9] = h->top_border_v[h->mbx*10 + 11]; + } else { + h->top_border_u[h->mbx * 10 + 9] = h->top_border_u[h->mbx * 10 + 8]; + h->top_border_v[h->mbx * 10 + 9] = h->top_border_v[h->mbx * 10 + 8]; + } + if((h->flags & A_AVAIL) && (h->flags & B_AVAIL)) { h->top_border_u[h->mbx * 10] = h->left_border_u[0] = h->topleft_border_u; h->top_border_v[h->mbx * 10] = h->left_border_v[0] = h->topleft_border_v; } else { @@ -275,7 +287,7 @@ static void intra_pred_plane(uint8_t *d, uint8_t *top, uint8_t *left, int stride int x, y, ia; int ih = 0; int iv = 0; - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; for (x = 0; x < 4; x++) { ih += (x + 1) * (top[5 + x] - top[3 - x]); @@ -525,7 +537,7 @@ void ff_cavs_inter(AVSContext *h, enum cavs_mb mb_type) static inline void scale_mv(AVSContext *h, int *d_x, int *d_y, cavs_vector *src, int distp) { - int den = h->scale_den[src->ref]; + int den = h->scale_den[FFMAX(src->ref, 0)]; *d_x = (src->x * distp * den + 256 + (src->x >> 31)) >> 9; *d_y = (src->y * distp * den + 256 + (src->y >> 31)) >> 9; @@ -572,7 +584,7 @@ void ff_cavs_mv(AVSContext *h, enum cavs_mv_loc nP, enum cavs_mv_loc nC, mvP->ref = ref; mvP->dist = h->dist[mvP->ref]; - if (mvC->ref == NOT_AVAIL) + if (mvC->ref == NOT_AVAIL || (nP == MV_FWD_X3) || (nP == MV_BWD_X3 )) mvC = &h->mv[nP - 5]; // set to top-left (mvD) if (mode == MV_PRED_PSKIP && (mvA->ref == NOT_AVAIL || @@ -742,16 +754,16 @@ void ff_cavs_init_top_lines(AVSContext *h) { /* alloc top line of predictors */ h->top_qp = av_mallocz(h->mb_width); - h->top_mv[0] = av_mallocz((h->mb_width * 2 + 1) * sizeof(cavs_vector)); - h->top_mv[1] = av_mallocz((h->mb_width * 2 + 1) * sizeof(cavs_vector)); - h->top_pred_Y = av_mallocz(h->mb_width * 2 * sizeof(*h->top_pred_Y)); - h->top_border_y = av_mallocz((h->mb_width + 1) * 16); - h->top_border_u = av_mallocz(h->mb_width * 10); - h->top_border_v = av_mallocz(h->mb_width * 10); + h->top_mv[0] = av_mallocz_array(h->mb_width * 2 + 1, sizeof(cavs_vector)); + h->top_mv[1] = av_mallocz_array(h->mb_width * 2 + 1, sizeof(cavs_vector)); + h->top_pred_Y = av_mallocz_array(h->mb_width * 2, sizeof(*h->top_pred_Y)); + h->top_border_y = av_mallocz_array(h->mb_width + 1, 16); + h->top_border_u = av_mallocz_array(h->mb_width, 10); + h->top_border_v = av_mallocz_array(h->mb_width, 10); /* alloc space for co-located MVs and types */ - h->col_mv = av_mallocz(h->mb_width * h->mb_height * 4 * - sizeof(cavs_vector)); + h->col_mv = av_mallocz_array(h->mb_width * h->mb_height, + 4 * sizeof(cavs_vector)); h->col_type_base = av_mallocz(h->mb_width * h->mb_height); h->block = av_mallocz(64 * sizeof(int16_t)); } @@ -760,13 +772,14 @@ av_cold int ff_cavs_init(AVCodecContext *avctx) { AVSContext *h = avctx->priv_data; - ff_dsputil_init(&h->dsp, avctx); + ff_blockdsp_init(&h->bdsp, avctx); ff_h264chroma_init(&h->h264chroma, 8); + ff_idctdsp_init(&h->idsp, avctx); ff_videodsp_init(&h->vdsp, 8); ff_cavsdsp_init(&h->cdsp, avctx); - ff_init_scantable_permutation(h->dsp.idct_permutation, + ff_init_scantable_permutation(h->idsp.idct_permutation, h->cdsp.idct_perm); - ff_init_scantable(h->dsp.idct_permutation, &h->scantable, ff_zigzag_direct); + ff_init_scantable(h->idsp.idct_permutation, &h->scantable, ff_zigzag_direct); h->avctx = avctx; avctx->pix_fmt = AV_PIX_FMT_YUV420P; diff --git a/libavcodec/cavs.h b/libavcodec/cavs.h index f85140927..12f396228 100644 --- a/libavcodec/cavs.h +++ b/libavcodec/cavs.h @@ -23,8 +23,9 @@ #define AVCODEC_CAVS_H #include "cavsdsp.h" -#include "dsputil.h" +#include "blockdsp.h" #include "h264chroma.h" +#include "idctdsp.h" #include "get_bits.h" #include "videodsp.h" @@ -161,8 +162,9 @@ typedef struct AVSFrame { typedef struct AVSContext { AVCodecContext *avctx; - DSPContext dsp; + BlockDSPContext bdsp; H264ChromaContext h264chroma; + IDCTDSPContext idsp; VideoDSPContext vdsp; CAVSDSPContext cdsp; GetBitContext gb; @@ -240,6 +242,7 @@ typedef struct AVSContext { int16_t *block; } AVSContext; +extern const uint8_t ff_cavs_chroma_qp[64]; extern const uint8_t ff_cavs_partition_flags[30]; extern const cavs_vector ff_cavs_intra_mv; extern const cavs_vector ff_cavs_dir_mv; diff --git a/libavcodec/cavsdata.c b/libavcodec/cavsdata.c index 905a306ef..2835a4be0 100644 --- a/libavcodec/cavsdata.c +++ b/libavcodec/cavsdata.c @@ -54,6 +54,13 @@ const uint8_t ff_cavs_partition_flags[30] = { SPLITH|SPLITV, //B_8X8 = 29 }; +const uint8_t ff_cavs_chroma_qp[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 43, 43, 44, 44, + 45, 45, 46, 46, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 51 +}; + /** mark block as "no prediction from this direction" e.g. forward motion vector in BWD partition */ const cavs_vector ff_cavs_dir_mv = {0,0,1,REF_DIR}; diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c index 399b5b914..34b65e689 100644 --- a/libavcodec/cavsdec.c +++ b/libavcodec/cavsdec.c @@ -52,13 +52,6 @@ static const uint8_t cbp_tab[64][2] = { static const uint8_t scan3x3[4] = { 4, 5, 7, 8 }; -static const uint8_t cavs_chroma_qp[64] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 43, 43, 44, 44, - 45, 45, 46, 46, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 51 -}; - static const uint8_t dequant_shift[64] = { 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, @@ -589,7 +582,7 @@ static int decode_residual_block(AVSContext *h, GetBitContext *gb, dequant_shift[qp], i)) < 0) return ret; h->cdsp.cavs_idct8_add(dst, block, stride); - h->dsp.clear_block(block); + h->bdsp.clear_block(block); return 0; } @@ -598,10 +591,10 @@ static inline void decode_residual_chroma(AVSContext *h) { if (h->cbp & (1 << 4)) decode_residual_block(h, &h->gb, chroma_dec, 0, - cavs_chroma_qp[h->qp], h->cu, h->c_stride); + ff_cavs_chroma_qp[h->qp], h->cu, h->c_stride); if (h->cbp & (1 << 5)) decode_residual_block(h, &h->gb, chroma_dec, 0, - cavs_chroma_qp[h->qp], h->cv, h->c_stride); + ff_cavs_chroma_qp[h->qp], h->cv, h->c_stride); } static inline int decode_residual_inter(AVSContext *h) @@ -805,6 +798,8 @@ static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type) ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_MEDIAN, BLK_16X16, 0); break; case B_8X8: +#define TMP_UNUSED_INX 7 + flags = 0; for (block = 0; block < 4; block++) sub_type[block] = get_bits(&h->gb, 2); for (block = 0; block < 4; block++) { @@ -812,11 +807,30 @@ static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type) case B_SUB_DIRECT: if (!h->col_type_base[h->mbidx]) { /* intra MB at co-location, do in-plane prediction */ - ff_cavs_mv(h, mv_scan[block], mv_scan[block] - 3, - MV_PRED_BSKIP, BLK_8X8, 1); - ff_cavs_mv(h, mv_scan[block] + MV_BWD_OFFS, - mv_scan[block] - 3 + MV_BWD_OFFS, - MV_PRED_BSKIP, BLK_8X8, 0); + if(flags==0) { + // if col-MB is a Intra MB, current Block size is 16x16. + // AVS standard section 9.9.1 + if(block>0){ + h->mv[TMP_UNUSED_INX ] = h->mv[MV_FWD_X0 ]; + h->mv[TMP_UNUSED_INX + MV_BWD_OFFS] = h->mv[MV_FWD_X0 + MV_BWD_OFFS]; + } + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, + MV_PRED_BSKIP, BLK_8X8, 1); + ff_cavs_mv(h, MV_FWD_X0+MV_BWD_OFFS, + MV_FWD_C2+MV_BWD_OFFS, + MV_PRED_BSKIP, BLK_8X8, 0); + if(block>0) { + flags = mv_scan[block]; + h->mv[flags ] = h->mv[MV_FWD_X0 ]; + h->mv[flags + MV_BWD_OFFS] = h->mv[MV_FWD_X0 + MV_BWD_OFFS]; + h->mv[MV_FWD_X0 ] = h->mv[TMP_UNUSED_INX ]; + h->mv[MV_FWD_X0 + MV_BWD_OFFS] = h->mv[TMP_UNUSED_INX + MV_BWD_OFFS]; + } else + flags = MV_FWD_X0; + } else { + h->mv[mv_scan[block] ] = h->mv[flags ]; + h->mv[mv_scan[block] + MV_BWD_OFFS] = h->mv[flags + MV_BWD_OFFS]; + } } else mv_pred_direct(h, &h->mv[mv_scan[block]], &h->col_mv[h->mbidx * 4 + block]); @@ -832,6 +846,7 @@ static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type) break; } } +#undef TMP_UNUSED_INX for (block = 0; block < 4; block++) { if (sub_type[block] == B_SUB_BWD) ff_cavs_mv(h, mv_scan[block] + MV_BWD_OFFS, @@ -1003,11 +1018,11 @@ static int decode_pic(AVSContext *h) /* get temporal distances and MV scaling factors */ if (h->cur.f->pict_type != AV_PICTURE_TYPE_B) { - h->dist[0] = (h->cur.poc - h->DPB[0].poc + 512) % 512; + h->dist[0] = (h->cur.poc - h->DPB[0].poc) & 511; } else { - h->dist[0] = (h->DPB[0].poc - h->cur.poc + 512) % 512; + h->dist[0] = (h->DPB[0].poc - h->cur.poc) & 511; } - h->dist[1] = (h->cur.poc - h->DPB[1].poc + 512) % 512; + h->dist[1] = (h->cur.poc - h->DPB[1].poc) & 511; h->scale_den[0] = h->dist[0] ? 512/h->dist[0] : 0; h->scale_den[1] = h->dist[1] ? 512/h->dist[1] : 0; if (h->cur.f->pict_type == AV_PICTURE_TYPE_B) { @@ -1199,8 +1214,8 @@ static int cavs_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, break; *got_frame = 1; if (h->cur.f->pict_type != AV_PICTURE_TYPE_B) { - if (h->DPB[1].f->data[0]) { - if ((ret = av_frame_ref(data, h->DPB[1].f)) < 0) + if (h->DPB[!h->low_delay].f->data[0]) { + if ((ret = av_frame_ref(data, h->DPB[!h->low_delay].f)) < 0) return ret; } else { *got_frame = 0; diff --git a/libavcodec/cavsdsp.c b/libavcodec/cavsdsp.c index 61283c23c..6ca11b956 100644 --- a/libavcodec/cavsdsp.c +++ b/libavcodec/cavsdsp.c @@ -23,7 +23,9 @@ */ #include -#include "dsputil.h" + +#include "idctdsp.h" +#include "mathops.h" #include "cavsdsp.h" #include "libavutil/common.h" @@ -186,7 +188,7 @@ 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) { int i; int16_t (*src)[8] = (int16_t(*)[8])block; - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; src[0][0] += 8; @@ -261,7 +263,7 @@ 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, uint8_t *src, int dstStride, int srcStride){\ const int h=8;\ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i;\ for(i=0; i -#include "dsputil.h" + +#include "avcodec.h" +#include "qpeldsp.h" typedef struct CAVSDSPContext { qpel_mc_func put_cavs_qpel_pixels_tab[2][16]; diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index 9f990dbe5..727734519 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -236,11 +236,11 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) if (!(s->frame_buf = av_malloc(frame_buf_size))) goto enomem; - if (!(s->mb = av_malloc(mb_count*sizeof(mb_info)))) + if (!(s->mb = av_malloc_array(mb_count, sizeof(mb_info)))) goto enomem; #ifdef CINEPAKENC_DEBUG - if (!(s->best_mb = av_malloc(mb_count*sizeof(mb_info)))) + if (!(s->best_mb = av_malloc_array(mb_count, sizeof(mb_info)))) goto enomem; #endif @@ -623,7 +623,7 @@ static int encode_mode(CinepakEncContext *s, int h, AVPicture *scratch_pict, AVP int needs_extra_bit, should_write_temp; unsigned char temp[64]; //32/2 = 16 V4 blocks at 4 B each -> 64 B mb_info *mb; - AVPicture sub_scratch, sub_last; + AVPicture sub_scratch = {{0}}, sub_last = {{0}}; //encode codebooks ////// MacOS vintage decoder compatibility dictates the presence of @@ -1120,14 +1120,14 @@ static int write_cvid_header(CinepakEncContext *s, unsigned char *buf, int num_s static int rd_frame(CinepakEncContext *s, const AVFrame *frame, int isakeyframe, unsigned char *buf, int buf_size) { - int num_strips, strip, i, y, nexty, size, temp_size, best_size; + int num_strips, strip, i, y, nexty, size, temp_size; AVPicture last_pict, pict, scratch_pict; int64_t best_score = 0, score, score_temp; #ifdef CINEPAK_REPORT_SERR int64_t best_serr = 0, serr, serr_temp; #endif - int best_nstrips; + int best_nstrips = -1, best_size = -1; // mark as uninitialzed if(s->pix_fmt == AV_PIX_FMT_RGB24) { int x; @@ -1239,6 +1239,8 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, int isakeyframe, break; } + av_assert0(best_nstrips >= 0 && best_size >= 0); + // let the number of strips slowly adapt to the changes in the contents, // compared to full bruteforcing every time this will occasionally lead // to some r/d performance loss but makes encoding up to several times faster @@ -1281,8 +1283,6 @@ static int cinepak_encode_frame(AVCodecContext *avctx, AVPacket *pkt, pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; - avctx->coded_frame = frame; - FFSWAP(AVFrame *, s->last_frame, s->best_frame); if (++s->curframe >= s->keyint) diff --git a/libavcodec/cljrdec.c b/libavcodec/cljrdec.c new file mode 100644 index 000000000..68c877175 --- /dev/null +++ b/libavcodec/cljrdec.c @@ -0,0 +1,94 @@ +/* + * Cirrus Logic AccuPak (CLJR) decoder + * Copyright (c) 2003 Alex Beregszaszi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Cirrus Logic AccuPak decoder. + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + GetBitContext gb; + AVFrame * const p = data; + int x, y, ret; + + if (avctx->height <= 0 || avctx->width <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid width or height\n"); + return AVERROR_INVALIDDATA; + } + + if (buf_size / avctx->height < avctx->width) { + av_log(avctx, AV_LOG_ERROR, + "Resolution larger than buffer size. Invalid header?\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + init_get_bits(&gb, buf, buf_size * 8); + + for (y = 0; y < avctx->height; y++) { + uint8_t *luma = &p->data[0][y * p->linesize[0]]; + uint8_t *cb = &p->data[1][y * p->linesize[1]]; + uint8_t *cr = &p->data[2][y * p->linesize[2]]; + for (x = 0; x < avctx->width; x += 4) { + luma[3] = (get_bits(&gb, 5)*33) >> 2; + luma[2] = (get_bits(&gb, 5)*33) >> 2; + luma[1] = (get_bits(&gb, 5)*33) >> 2; + luma[0] = (get_bits(&gb, 5)*33) >> 2; + luma += 4; + *(cb++) = get_bits(&gb, 6) << 2; + *(cr++) = get_bits(&gb, 6) << 2; + } + } + + *got_frame = 1; + + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV411P; + return 0; +} + +AVCodec ff_cljr_decoder = { + .name = "cljr", + .long_name = NULL_IF_CONFIG_SMALL("Cirrus Logic AccuPak"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CLJR, + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, +}; + diff --git a/libavcodec/cljr.c b/libavcodec/cljrenc.c similarity index 59% rename from libavcodec/cljr.c rename to libavcodec/cljrenc.c index 7e0773b6b..c672f800f 100644 --- a/libavcodec/cljr.c +++ b/libavcodec/cljrenc.c @@ -1,5 +1,5 @@ /* - * Cirrus Logic AccuPak (CLJR) codec + * Cirrus Logic AccuPak (CLJR) encoder * Copyright (c) 2003 Alex Beregszaszi * * This file is part of FFmpeg. @@ -21,102 +21,21 @@ /** * @file - * Cirrus Logic AccuPak codec. + * Cirrus Logic AccuPak encoder. */ -#include "avcodec.h" +#include "libavutil/common.h" #include "libavutil/opt.h" -#include "get_bits.h" + +#include "avcodec.h" #include "internal.h" #include "put_bits.h" -#if CONFIG_CLJR_DECODER -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) -{ - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; - GetBitContext gb; - AVFrame * const p = data; - int x, y, ret; - - if (avctx->height <= 0 || avctx->width <= 0) { - av_log(avctx, AV_LOG_ERROR, "Invalid width or height\n"); - return AVERROR_INVALIDDATA; - } - - if (buf_size / avctx->height < avctx->width) { - av_log(avctx, AV_LOG_ERROR, - "Resolution larger than buffer size. Invalid header?\n"); - return AVERROR_INVALIDDATA; - } - - if ((ret = ff_get_buffer(avctx, p, 0)) < 0) - return ret; - p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; - - init_get_bits(&gb, buf, buf_size * 8); - - for (y = 0; y < avctx->height; y++) { - uint8_t *luma = &p->data[0][y * p->linesize[0]]; - uint8_t *cb = &p->data[1][y * p->linesize[1]]; - uint8_t *cr = &p->data[2][y * p->linesize[2]]; - for (x = 0; x < avctx->width; x += 4) { - luma[3] = (get_bits(&gb, 5)*33) >> 2; - luma[2] = (get_bits(&gb, 5)*33) >> 2; - luma[1] = (get_bits(&gb, 5)*33) >> 2; - luma[0] = (get_bits(&gb, 5)*33) >> 2; - luma += 4; - *(cb++) = get_bits(&gb, 6) << 2; - *(cr++) = get_bits(&gb, 6) << 2; - } - } - - *got_frame = 1; - - return buf_size; -} - -static av_cold int decode_init(AVCodecContext *avctx) -{ - avctx->pix_fmt = AV_PIX_FMT_YUV411P; - return 0; -} - -AVCodec ff_cljr_decoder = { - .name = "cljr", - .long_name = NULL_IF_CONFIG_SMALL("Cirrus Logic AccuPak"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CLJR, - .init = decode_init, - .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, -}; -#endif - -#if CONFIG_CLJR_ENCODER typedef struct CLJRContext { AVClass *avclass; int dither_type; } CLJRContext; -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) { @@ -130,24 +49,34 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, { 0xCB2A0000, 0xCB250000 }, }; + if (avctx->width%4 && avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { + av_log(avctx, AV_LOG_ERROR, + "Widths which are not a multiple of 4 might fail with some decoders, " + "use vstrict=-1 / -strict -1 to use %d anyway.\n", avctx->width); + return AVERROR_EXPERIMENTAL; + } + if ((ret = ff_alloc_packet2(avctx, pkt, 32*avctx->height*avctx->width/4)) < 0) return ret; - avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; - avctx->coded_frame->key_frame = 1; - init_put_bits(&pb, pkt->data, pkt->size); for (y = 0; y < avctx->height; y++) { uint8_t *luma = &p->data[0][y * p->linesize[0]]; uint8_t *cb = &p->data[1][y * p->linesize[1]]; uint8_t *cr = &p->data[2][y * p->linesize[2]]; + uint8_t luma_tmp[4]; for (x = 0; x < avctx->width; x += 4) { switch (a->dither_type) { case 0: dither = 0x492A0000; break; case 1: dither = dither * 1664525 + 1013904223; break; case 2: dither = ordered_dither[ y&1 ][ (x>>2)&1 ];break; } + if (x+3 >= avctx->width) { + memset(luma_tmp, 0, sizeof(luma_tmp)); + memcpy(luma_tmp, luma, avctx->width - x); + luma = luma_tmp; + } put_bits(&pb, 5, (249*(luma[3] + (dither>>29) )) >> 11); put_bits(&pb, 5, (249*(luma[2] + ((dither>>26)&7))) >> 11); put_bits(&pb, 5, (249*(luma[1] + ((dither>>23)&7))) >> 11); @@ -186,11 +115,8 @@ AVCodec ff_cljr_encoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_CLJR, .priv_data_size = sizeof(CLJRContext), - .init = encode_init, .encode2 = encode_frame, - .close = encode_close, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, AV_PIX_FMT_NONE }, .priv_class = &cljr_class, }; -#endif diff --git a/libavcodec/cllc.c b/libavcodec/cllc.c index ee77381fd..9c710bbb9 100644 --- a/libavcodec/cllc.c +++ b/libavcodec/cllc.c @@ -20,15 +20,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/intreadwrite.h" -#include "dsputil.h" +#include "bswapdsp.h" #include "get_bits.h" #include "avcodec.h" #include "internal.h" typedef struct CLLCContext { - DSPContext dsp; AVCodecContext *avctx; + BswapDSPContext bdsp; uint8_t *swapped_buf; int swapped_buf_size; @@ -367,7 +369,7 @@ static int cllc_decode_frame(AVCodecContext *avctx, void *data, info_offset = AV_RL32(src + 4); if (info_offset > UINT32_MAX - 8 || info_offset + 8 > avpkt->size) { av_log(avctx, AV_LOG_ERROR, - "Invalid INFO header offset: 0x%08X is too large.\n", + "Invalid INFO header offset: 0x%08"PRIX32" is too large.\n", info_offset); return AVERROR_INVALIDDATA; } @@ -389,8 +391,8 @@ static int cllc_decode_frame(AVCodecContext *avctx, void *data, } /* bswap16 the buffer since CLLC's bitreader works in 16-bit words */ - ctx->dsp.bswap16_buf((uint16_t *) ctx->swapped_buf, (uint16_t *) src, - data_size / 2); + ctx->bdsp.bswap16_buf((uint16_t *) ctx->swapped_buf, (uint16_t *) src, + data_size / 2); init_get_bits(&gb, ctx->swapped_buf, data_size * 8); @@ -474,7 +476,7 @@ static av_cold int cllc_decode_init(AVCodecContext *avctx) ctx->swapped_buf = NULL; ctx->swapped_buf_size = 0; - ff_dsputil_init(&ctx->dsp, avctx); + ff_bswapdsp_init(&ctx->bdsp); return 0; } diff --git a/libavcodec/cngdec.c b/libavcodec/cngdec.c index 12241c3b9..855baaaa8 100644 --- a/libavcodec/cngdec.c +++ b/libavcodec/cngdec.c @@ -59,12 +59,12 @@ static av_cold int cng_decode_init(AVCodecContext *avctx) p->order = 12; avctx->frame_size = 640; - p->refl_coef = av_mallocz(p->order * sizeof(*p->refl_coef)); - p->target_refl_coef = av_mallocz(p->order * sizeof(*p->target_refl_coef)); - p->lpc_coef = av_mallocz(p->order * sizeof(*p->lpc_coef)); - p->filter_out = av_mallocz((avctx->frame_size + p->order) * + p->refl_coef = av_mallocz_array(p->order, sizeof(*p->refl_coef)); + p->target_refl_coef = av_mallocz_array(p->order, sizeof(*p->target_refl_coef)); + p->lpc_coef = av_mallocz_array(p->order, sizeof(*p->lpc_coef)); + p->filter_out = av_mallocz_array(avctx->frame_size + p->order, sizeof(*p->filter_out)); - p->excitation = av_mallocz(avctx->frame_size * sizeof(*p->excitation)); + p->excitation = av_mallocz_array(avctx->frame_size, sizeof(*p->excitation)); if (!p->refl_coef || !p->target_refl_coef || !p->lpc_coef || !p->filter_out || !p->excitation) { cng_decode_close(avctx); diff --git a/libavcodec/cngenc.c b/libavcodec/cngenc.c index 5ab6e365c..bf5f7bf54 100644 --- a/libavcodec/cngenc.c +++ b/libavcodec/cngenc.c @@ -56,8 +56,8 @@ static av_cold int cng_encode_init(AVCodecContext *avctx) p->order = 10; if ((ret = ff_lpc_init(&p->lpc, avctx->frame_size, p->order, FF_LPC_TYPE_LEVINSON)) < 0) return ret; - p->samples32 = av_malloc(avctx->frame_size * sizeof(*p->samples32)); - p->ref_coef = av_malloc(p->order * sizeof(*p->ref_coef)); + p->samples32 = av_malloc_array(avctx->frame_size, sizeof(*p->samples32)); + p->ref_coef = av_malloc_array(p->order, sizeof(*p->ref_coef)); if (!p->samples32 || !p->ref_coef) { cng_encode_close(avctx); return AVERROR(ENOMEM); diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index a217d3567..4906a0a21 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -26,6 +26,8 @@ #include "avcodec.h" #include "version.h" +#define MT(...) (const char *const[]){ __VA_ARGS__, NULL } + static const AVCodecDescriptor codec_descriptors[] = { /* video codecs */ { @@ -85,6 +87,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "mjpeg", .long_name = NULL_IF_CONFIG_SMALL("Motion JPEG"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + .mime_types= MT("image/jpeg"), }, { .id = AV_CODEC_ID_MJPEGB, @@ -93,28 +96,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Apple MJPEG-B"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_LJPEG, - .type = AVMEDIA_TYPE_VIDEO, - .name = "ljpeg", - .long_name = NULL_IF_CONFIG_SMALL("Lossless JPEG"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_SP5X, - .type = AVMEDIA_TYPE_VIDEO, - .name = "sp5x", - .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_JPEGLS, - .type = AVMEDIA_TYPE_VIDEO, - .name = "jpegls", - .long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | - AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_MPEG4, .type = AVMEDIA_TYPE_VIDEO, @@ -465,48 +446,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Q-team QPEG"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_PNG, - .type = AVMEDIA_TYPE_VIDEO, - .name = "png", - .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), - .props = AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_PPM, - .type = AVMEDIA_TYPE_VIDEO, - .name = "ppm", - .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_PBM, - .type = AVMEDIA_TYPE_VIDEO, - .name = "pbm", - .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_PGM, - .type = AVMEDIA_TYPE_VIDEO, - .name = "pgm", - .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_PGMYUV, - .type = AVMEDIA_TYPE_VIDEO, - .name = "pgmyuv", - .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_PAM, - .type = AVMEDIA_TYPE_VIDEO, - .name = "pam", - .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_FFVHUFF, .type = AVMEDIA_TYPE_VIDEO, @@ -590,6 +529,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "bmp", .long_name = NULL_IF_CONFIG_SMALL("BMP (Windows and OS/2 bitmap)"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/x-ms-bmp"), }, { .id = AV_CODEC_ID_CSCD, @@ -661,6 +601,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, + .mime_types= MT("image/jp2"), }, { .id = AV_CODEC_ID_VMNC, @@ -690,13 +631,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("On2 VP6 (Flash version)"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_TARGA, - .type = AVMEDIA_TYPE_VIDEO, - .name = "targa", - .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_DSICINVIDEO, .type = AVMEDIA_TYPE_VIDEO, @@ -711,20 +645,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_TIFF, - .type = AVMEDIA_TYPE_VIDEO, - .name = "tiff", - .long_name = NULL_IF_CONFIG_SMALL("TIFF image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_GIF, - .type = AVMEDIA_TYPE_VIDEO, - .name = "gif", - .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), - .props = AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_DXA, .type = AVMEDIA_TYPE_VIDEO, @@ -746,20 +666,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Nintendo Gamecube THP video"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_SGI, - .type = AVMEDIA_TYPE_VIDEO, - .name = "sgi", - .long_name = NULL_IF_CONFIG_SMALL("SGI image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_SGIRLE, - .type = AVMEDIA_TYPE_VIDEO, - .name = "sgirle", - .long_name = NULL_IF_CONFIG_SMALL("SGI RLE 8-bit"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_C93, .type = AVMEDIA_TYPE_VIDEO, @@ -774,20 +680,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Bethesda VID video"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_PTX, - .type = AVMEDIA_TYPE_VIDEO, - .name = "ptx", - .long_name = NULL_IF_CONFIG_SMALL("V.Flash PTX image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_TXD, - .type = AVMEDIA_TYPE_VIDEO, - .name = "txd", - .long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, - }, { .id = AV_CODEC_ID_VP6A, .type = AVMEDIA_TYPE_VIDEO, @@ -809,20 +701,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Beam Software VB"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_PCX, - .type = AVMEDIA_TYPE_VIDEO, - .name = "pcx", - .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_SUNRAST, - .type = AVMEDIA_TYPE_VIDEO, - .name = "sunrast", - .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_INDEO4, .type = AVMEDIA_TYPE_VIDEO, @@ -925,6 +803,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .id = AV_CODEC_ID_V210X, .type = AVMEDIA_TYPE_VIDEO, .name = "v210x", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { @@ -941,13 +820,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, - { - .id = AV_CODEC_ID_DPX, - .type = AVMEDIA_TYPE_VIDEO, - .name = "dpx", - .long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_MAD, .type = AVMEDIA_TYPE_VIDEO, @@ -1046,13 +918,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Pictor/PC Paint"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_ANSI, - .type = AVMEDIA_TYPE_VIDEO, - .name = "ansi", - .long_name = NULL_IF_CONFIG_SMALL("ASCII/ANSI art"), - .props = AV_CODEC_PROP_LOSSY, - }, { .id = AV_CODEC_ID_A64_MULTI, .type = AVMEDIA_TYPE_VIDEO, @@ -1123,20 +988,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Chronomaster DFA"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_WMV3IMAGE, - .type = AVMEDIA_TYPE_VIDEO, - .name = "wmv3image", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image"), - .props = AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_VC1IMAGE, - .type = AVMEDIA_TYPE_VIDEO, - .name = "vc1image", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image v2"), - .props = AV_CODEC_PROP_LOSSY, - }, { .id = AV_CODEC_ID_UTVIDEO, .type = AVMEDIA_TYPE_VIDEO, @@ -1172,13 +1023,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:4:4 10-bit"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, - { - .id = AV_CODEC_ID_XWD, - .type = AVMEDIA_TYPE_VIDEO, - .name = "xwd", - .long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_CDXL, .type = AVMEDIA_TYPE_VIDEO, @@ -1186,13 +1030,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_XBM, - .type = AVMEDIA_TYPE_VIDEO, - .name = "xbm", - .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_ZEROCODEC, .type = AVMEDIA_TYPE_VIDEO, @@ -1263,14 +1100,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Escape 130"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_EXR, - .type = AVMEDIA_TYPE_VIDEO, - .name = "exr", - .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | - AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_AVRP, .type = AVMEDIA_TYPE_VIDEO, @@ -1327,20 +1156,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"), .props = AV_CODEC_PROP_INTRA_ONLY, }, - { - .id = AV_CODEC_ID_SANM, - .type = AVMEDIA_TYPE_VIDEO, - .name = "sanm", - .long_name = NULL_IF_CONFIG_SMALL("LucasArts SMUSH video"), - .props = AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_PAF_VIDEO, - .type = AVMEDIA_TYPE_VIDEO, - .name = "paf_video", - .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video"), - .props = AV_CODEC_PROP_LOSSY, - }, { .id = AV_CODEC_ID_AVRN, .type = AVMEDIA_TYPE_VIDEO, @@ -1360,13 +1175,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("X-face image"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_BRENDER_PIX, - .type = AVMEDIA_TYPE_VIDEO, - .name = "brender_pix", - .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_SMVJPEG, .type = AVMEDIA_TYPE_VIDEO, @@ -1381,14 +1189,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Go2Meeting"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_WEBP, - .type = AVMEDIA_TYPE_VIDEO, - .name = "webp", - .long_name = NULL_IF_CONFIG_SMALL("WebP"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | - AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_HNM4_VIDEO, .type = AVMEDIA_TYPE_VIDEO, @@ -1410,6 +1210,236 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Mirillis FIC"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_PAF_VIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "paf_video", + .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VP7, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vp7", + .long_name = NULL_IF_CONFIG_SMALL("On2 VP7"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SANM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sanm", + .long_name = NULL_IF_CONFIG_SMALL("LucasArts SANM/SMUSH video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SGIRLE, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sgirle", + .long_name = NULL_IF_CONFIG_SMALL("SGI RLE 8-bit"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + + /* image codecs */ + { + .id = AV_CODEC_ID_ALIAS_PIX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "alias_pix", + .long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_ANSI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ansi", + .long_name = NULL_IF_CONFIG_SMALL("ASCII/ANSI art"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_BRENDER_PIX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "brender_pix", + .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_DPX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dpx", + .long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_EXR, + .type = AVMEDIA_TYPE_VIDEO, + .name = "exr", + .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_GIF, + .type = AVMEDIA_TYPE_VIDEO, + .name = "gif", + .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), + .props = AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/gif"), + }, + { + .id = AV_CODEC_ID_JPEGLS, + .type = AVMEDIA_TYPE_VIDEO, + .name = "jpegls", + .long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_LJPEG, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ljpeg", + .long_name = NULL_IF_CONFIG_SMALL("Lossless JPEG"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PAM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pam", + .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/x-portable-pixmap"), + }, + { + .id = AV_CODEC_ID_PBM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pbm", + .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pcx", + .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/x-pcx"), + }, + { + .id = AV_CODEC_ID_PGM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pgm", + .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PGMYUV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pgmyuv", + .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PNG, + .type = AVMEDIA_TYPE_VIDEO, + .name = "png", + .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), + .props = AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/png"), + }, + { + .id = AV_CODEC_ID_PPM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ppm", + .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PTX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ptx", + .long_name = NULL_IF_CONFIG_SMALL("V.Flash PTX image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SGI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sgi", + .long_name = NULL_IF_CONFIG_SMALL("SGI image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_SP5X, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sp5x", + .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SUNRAST, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sunrast", + .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_TARGA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "targa", + .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/x-targa", "image/x-tga"), + }, + { + .id = AV_CODEC_ID_TIFF, + .type = AVMEDIA_TYPE_VIDEO, + .name = "tiff", + .long_name = NULL_IF_CONFIG_SMALL("TIFF image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/tiff"), + }, + { + .id = AV_CODEC_ID_TXD, + .type = AVMEDIA_TYPE_VIDEO, + .name = "txd", + .long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VC1IMAGE, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vc1image", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image v2"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WEBP, + .type = AVMEDIA_TYPE_VIDEO, + .name = "webp", + .long_name = NULL_IF_CONFIG_SMALL("WebP"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/webp"), + }, + { + .id = AV_CODEC_ID_WMV3IMAGE, + .type = AVMEDIA_TYPE_VIDEO, + .name = "wmv3image", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_XBM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "xbm", + .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_XWD, + .type = AVMEDIA_TYPE_VIDEO, + .name = "xwd", + .long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/x-xwindowdump"), + }, /* various PCM "codecs" */ { @@ -1876,6 +1906,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM little-endian"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_ADPCM_VIMA, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_vima", + .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"), + .props = AV_CODEC_PROP_LOSSY, + }, /* AMR */ { @@ -1972,20 +2009,21 @@ static const AVCodecDescriptor codec_descriptors[] = { .id = AV_CODEC_ID_DTS, .type = AVMEDIA_TYPE_AUDIO, .name = "dts", - .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"), + .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"), .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_VORBIS, .type = AVMEDIA_TYPE_AUDIO, .name = "vorbis", - .long_name = NULL_IF_CONFIG_SMALL("Vorbis"), + .long_name = NULL_IF_CONFIG_SMALL("Vorbis"), .props = AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_DVAUDIO, .type = AVMEDIA_TYPE_AUDIO, .name = "dvaudio", + .long_name = NULL_IF_CONFIG_SMALL("DV audio"), .props = AV_CODEC_PROP_LOSSY, }, { @@ -2368,13 +2406,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_VIMA, - .type = AVMEDIA_TYPE_AUDIO, - .name = "vima", - .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"), - .props = AV_CODEC_PROP_LOSSY, - }, { .id = AV_CODEC_ID_FFWAVESYNTH, .type = AVMEDIA_TYPE_AUDIO, @@ -2393,13 +2424,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "sonicls", .long_name = NULL_IF_CONFIG_SMALL("Sonic lossless"), }, - { - .id = AV_CODEC_ID_PAF_AUDIO, - .type = AVMEDIA_TYPE_AUDIO, - .name = "paf_audio", - .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio"), - .props = AV_CODEC_PROP_LOSSY, - }, { .id = AV_CODEC_ID_OPUS, .type = AVMEDIA_TYPE_AUDIO, @@ -2428,6 +2452,20 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Voxware MetaSound"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_PAF_AUDIO, + .type = AVMEDIA_TYPE_AUDIO, + .name = "paf_audio", + .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ON2AVC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "avc", + .long_name = NULL_IF_CONFIG_SMALL("On2 Audio for Video Codec"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_EVRC, .type = AVMEDIA_TYPE_AUDIO, @@ -2442,6 +2480,34 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("SMV (Selectable Mode Vocoder)"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_DSD_LSBF, + .type = AVMEDIA_TYPE_AUDIO, + .name = "dsd_lsbf", + .long_name = NULL_IF_CONFIG_SMALL("DSD (Direct Stream Digital), least significant bit first"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_DSD_MSBF, + .type = AVMEDIA_TYPE_AUDIO, + .name = "dsd_msbf", + .long_name = NULL_IF_CONFIG_SMALL("DSD (Direct Stream Digital), most significant bit first"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_DSD_LSBF_PLANAR, + .type = AVMEDIA_TYPE_AUDIO, + .name = "dsd_lsbf_planar", + .long_name = NULL_IF_CONFIG_SMALL("DSD (Direct Stream Digital), least significant bit first, planar"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_DSD_MSBF_PLANAR, + .type = AVMEDIA_TYPE_AUDIO, + .name = "dsd_msbf_planar", + .long_name = NULL_IF_CONFIG_SMALL("DSD (Direct Stream Digital), most significant bit first, planar"), + .props = AV_CODEC_PROP_LOSSY, + }, /* subtitle codecs */ { @@ -2596,6 +2662,15 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), .props = AV_CODEC_PROP_TEXT_SUB, }, + + /* other kind of codecs and pseudo-codecs */ + { + .id = AV_CODEC_ID_TTF, + .type = AVMEDIA_TYPE_DATA, + .name = "ttf", + .long_name = NULL_IF_CONFIG_SMALL("TrueType font"), + .mime_types= MT("application/x-truetype-font", "application/x-font"), + }, { .id = AV_CODEC_ID_BINTEXT, .type = AVMEDIA_TYPE_VIDEO, @@ -2617,6 +2692,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("iCEDraw text"), .props = AV_CODEC_PROP_INTRA_ONLY, }, + { + .id = AV_CODEC_ID_OTF, + .type = AVMEDIA_TYPE_DATA, + .name = "otf", + .long_name = NULL_IF_CONFIG_SMALL("OpenType font"), + .mime_types= MT("application/vnd.ms-opentype"), + }, { .id = AV_CODEC_ID_SMPTE_KLV, .type = AVMEDIA_TYPE_DATA, @@ -2635,7 +2717,130 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "timed_id3", .long_name = NULL_IF_CONFIG_SMALL("timed ID3 metadata"), }, + { + .id = AV_CODEC_ID_BIN_DATA, + .type = AVMEDIA_TYPE_DATA, + .name = "bin_data", + .long_name = NULL_IF_CONFIG_SMALL("binary data"), + .mime_types= MT("application/octet-stream"), + }, + /* deprecated codec ids */ + { + .id = AV_CODEC_ID_BRENDER_PIX_DEPRECATED, + .type = AVMEDIA_TYPE_VIDEO, + .name = "brender_pix_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image (deprecated id)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_ESCAPE130_DEPRECATED, + .type = AVMEDIA_TYPE_VIDEO, + .name = "escape130_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("Escape 130 (deprecated id)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_EXR_DEPRECATED, + .type = AVMEDIA_TYPE_VIDEO, + .name = "exr_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image (deprecated id)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_G2M_DEPRECATED, + .type = AVMEDIA_TYPE_VIDEO, + .name = "g2m_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("Go2Meeting (deprecated id)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_HEVC_DEPRECATED, + .type = AVMEDIA_TYPE_VIDEO, + .name = "hevc_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("H.265 / HEVC (High Efficiency Video Coding) (deprecated id)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PAF_VIDEO_DEPRECATED, + .type = AVMEDIA_TYPE_VIDEO, + .name = "paf_video_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video (deprecated id)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SANM_DEPRECATED, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sanm_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("LucasArts SANM/SMUSH video (deprecated id)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VP7_DEPRECATED, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vp7_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("On2 VP7 (deprecated id)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WEBP_DEPRECATED, + .type = AVMEDIA_TYPE_VIDEO, + .name = "webp_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("WebP (deprecated id)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + }, + + { + .id = AV_CODEC_ID_VIMA, + .type = AVMEDIA_TYPE_AUDIO, + .name = "vima", + .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio (deprecated id)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_VIMA_DEPRECATED, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_vima_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio (deprecated id)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_OPUS_DEPRECATED, + .type = AVMEDIA_TYPE_AUDIO, + .name = "opus_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("Opus (Opus Interactive Audio Codec) (deprecated id)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PAF_AUDIO_DEPRECATED, + .type = AVMEDIA_TYPE_AUDIO, + .name = "paf_audio_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio (deprecated id)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PCM_S24LE_PLANAR_DEPRECATED, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s24le_planar_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 24-bit little-endian planar (deprecated id)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_S32LE_PLANAR_DEPRECATED, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s32le_planar_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 32-bit little-endian planar (deprecated id)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_TAK_DEPRECATED, + .type = AVMEDIA_TYPE_AUDIO, + .name = "tak_deprecated", + .long_name = NULL_IF_CONFIG_SMALL("TAK (Tom's lossless Audio Kompressor) (deprecated id)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, }; const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id) @@ -2661,9 +2866,8 @@ const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name) { const AVCodecDescriptor *desc = NULL; - while ((desc = avcodec_descriptor_next(desc))) { + while ((desc = avcodec_descriptor_next(desc))) if (!strcmp(desc->name, name)) return desc; - } return NULL; } diff --git a/libavcodec/cook.c b/libavcodec/cook.c index 402093c42..5860288e0 100644 --- a/libavcodec/cook.c +++ b/libavcodec/cook.c @@ -44,9 +44,10 @@ #include "libavutil/channel_layout.h" #include "libavutil/lfg.h" + +#include "audiodsp.h" #include "avcodec.h" #include "get_bits.h" -#include "dsputil.h" #include "bytestream.h" #include "fft.h" #include "internal.h" @@ -123,7 +124,7 @@ typedef struct cook { void (*saturate_output)(struct cook *q, float *out); AVCodecContext* avctx; - DSPContext dsp; + AudioDSPContext adsp; GetBitContext gb; /* stream data */ int num_vectors; @@ -219,7 +220,7 @@ static av_cold int init_cook_mlt(COOKContext *q) int j, ret; int mlt_size = q->samples_per_channel; - if ((q->mlt_window = av_malloc(mlt_size * sizeof(*q->mlt_window))) == 0) + if ((q->mlt_window = av_malloc_array(mlt_size, sizeof(*q->mlt_window))) == 0) return AVERROR(ENOMEM); /* Initialize the MLT window: simple sine window. */ @@ -873,8 +874,8 @@ static inline void decode_bytes_and_gain(COOKContext *q, COOKSubpacket *p, */ static void saturate_output_float(COOKContext *q, float *out) { - q->dsp.vector_clipf(out, q->mono_mdct_output + q->samples_per_channel, - -1.0f, 1.0f, FFALIGN(q->samples_per_channel, 8)); + q->adsp.vector_clipf(out, q->mono_mdct_output + q->samples_per_channel, + -1.0f, 1.0f, FFALIGN(q->samples_per_channel, 8)); } @@ -1072,7 +1073,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) /* Initialize RNG. */ av_lfg_init(&q->random_state, 0); - ff_dsputil_init(&q->dsp, avctx); + ff_audiodsp_init(&q->adsp); while (edata_ptr < edata_ptr_end) { /* 8 for mono, 16 for stereo, ? for multichannel diff --git a/libavcodec/copy_block.h b/libavcodec/copy_block.h index a73910d80..9ed451f29 100644 --- a/libavcodec/copy_block.h +++ b/libavcodec/copy_block.h @@ -37,57 +37,52 @@ static inline void copy_block2(uint8_t *dst, const uint8_t *src, int dstStride, static inline void copy_block4(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h) { int i; - for(i=0; i #include #include -#include #include #include @@ -90,6 +89,10 @@ #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" +#if HAVE_UNISTD_H +#include +#endif + /** Timeout parameter passed to DtsProcOutput() in us */ #define OUTPUT_PROC_TIMEOUT 50 /** Step between fake timestamps passed to hardware in units of 100ns */ @@ -419,7 +422,7 @@ static av_cold int init(AVCodecContext *avctx) int dummy_int; /* Back up the extradata so it can be restored at close time. */ - priv->orig_extradata = av_malloc(avctx->extradata_size); + priv->orig_extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); if (!priv->orig_extradata) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate copy of extradata\n"); diff --git a/libavcodec/dca.c b/libavcodec/dca.c index 1c1c08035..fcdfef214 100644 --- a/libavcodec/dca.c +++ b/libavcodec/dca.c @@ -25,8 +25,10 @@ #include #include -#include "put_bits.h" +#include "libavutil/error.h" + #include "dca.h" +#include "put_bits.h" const uint32_t avpriv_dca_sample_rates[16] = { diff --git a/libavcodec/dcadata.h b/libavcodec/dcadata.h index 0ae125c2f..72aebde69 100644 --- a/libavcodec/dcadata.h +++ b/libavcodec/dcadata.h @@ -7520,38 +7520,38 @@ DECLARE_ALIGNED(16, static const float, lfe_fir_128)[] = * 2) [-29.750 to -15] with resolution of 0.250 dB * 3) [-14.875 to 0] with resolution of 0.125 dB */ -static const float dca_dmixtable[241] = { - 0.001000, 0.001059, 0.001122, 0.001189, 0.001259, 0.001334, 0.001413, 0.001496, - 0.001585, 0.001679, 0.001778, 0.001884, 0.001995, 0.002113, 0.002239, 0.002371, - 0.002512, 0.002661, 0.002818, 0.002985, 0.003162, 0.003350, 0.003548, 0.003758, - 0.003981, 0.004217, 0.004467, 0.004732, 0.005012, 0.005309, 0.005623, 0.005957, - 0.006310, 0.006683, 0.007079, 0.007499, 0.007943, 0.008414, 0.008913, 0.009441, - 0.010000, 0.010593, 0.011220, 0.011885, 0.012589, 0.013335, 0.014125, 0.014962, - 0.015849, 0.016788, 0.017783, 0.018836, 0.019953, 0.021135, 0.022387, 0.023714, - 0.025119, 0.026607, 0.028184, 0.029854, 0.031623, 0.032546, 0.033497, 0.034475, - 0.035481, 0.036517, 0.037584, 0.038681, 0.039811, 0.040973, 0.042170, 0.043401, - 0.044668, 0.045973, 0.047315, 0.048697, 0.050119, 0.051582, 0.053088, 0.054639, - 0.056234, 0.057876, 0.059566, 0.061306, 0.063096, 0.064938, 0.066834, 0.068786, - 0.070795, 0.072862, 0.074989, 0.077179, 0.079433, 0.081752, 0.084140, 0.086596, - 0.089125, 0.091728, 0.094406, 0.097163, 0.100000, 0.102920, 0.105925, 0.109018, - 0.112202, 0.115478, 0.118850, 0.122321, 0.125893, 0.129569, 0.133352, 0.137246, - 0.141254, 0.145378, 0.149624, 0.153993, 0.158489, 0.163117, 0.167880, 0.172783, - 0.177828, 0.180406, 0.183021, 0.185674, 0.188365, 0.191095, 0.193865, 0.196675, - 0.199526, 0.202418, 0.205353, 0.208329, 0.211349, 0.214412, 0.217520, 0.220673, - 0.223872, 0.227117, 0.230409, 0.233749, 0.237137, 0.240575, 0.244062, 0.247600, - 0.251189, 0.254830, 0.258523, 0.262271, 0.266073, 0.269929, 0.273842, 0.277811, - 0.281838, 0.285924, 0.290068, 0.294273, 0.298538, 0.302866, 0.307256, 0.311709, - 0.316228, 0.320812, 0.325462, 0.330179, 0.334965, 0.339821, 0.344747, 0.349744, - 0.354813, 0.359956, 0.365174, 0.370467, 0.375837, 0.381285, 0.386812, 0.392419, - 0.398107, 0.403878, 0.409732, 0.415671, 0.421697, 0.427809, 0.434010, 0.440301, - 0.446684, 0.453158, 0.459727, 0.466391, 0.473151, 0.480010, 0.486968, 0.494026, - 0.501187, 0.508452, 0.515822, 0.523299, 0.530884, 0.538580, 0.546387, 0.554307, - 0.562341, 0.570493, 0.578762, 0.587151, 0.595662, 0.604296, 0.613056, 0.621942, - 0.630957, 0.640103, 0.649382, 0.658795, 0.668344, 0.678032, 0.687860, 0.697831, - 0.707107, 0.718208, 0.728618, 0.739180, 0.749894, 0.760764, 0.771792, 0.782979, - 0.794328, 0.805842, 0.817523, 0.829373, 0.841395, 0.853591, 0.865964, 0.878517, - 0.891251, 0.904170, 0.917276, 0.930572, 0.944061, 0.957745, 0.971628, 0.985712, - 1.000000, +static const 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] = { diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c index 4392f032f..c671fcd72 100644 --- a/libavcodec/dcadec.c +++ b/libavcodec/dcadec.c @@ -478,6 +478,8 @@ typedef struct { FmtConvertContext fmt_conv; } DCAContext; +static float dca_dmix_code(unsigned code); + 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, @@ -568,7 +570,7 @@ static int dca_parse_audio_coding_header(DCAContext *s, int base_channel, static const int bitlen[11] = { 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3 }; static const int thr[11] = { 0, 1, 3, 3, 3, 3, 7, 7, 7, 7, 7 }; int hdr_pos = 0, hdr_size = 0; - float sign, mag, scale_factor; + float scale_factor; int this_chans, acc_mask; int embedded_downmix; int nchans, mask[8]; @@ -598,8 +600,14 @@ static int dca_parse_audio_coding_header(DCAContext *s, int base_channel, /* check for downmixing information */ if (get_bits1(&s->gb)) { embedded_downmix = get_bits1(&s->gb); - scale_factor = - 1.0f / dca_dmixtable[(get_bits(&s->gb, 6) - 1) << 2]; + coeff = get_bits(&s->gb, 6); + + if (coeff<1 || coeff>61) { + av_log(s->avctx, AV_LOG_ERROR, "6bit coeff %d is out of range\n", coeff); + return AVERROR_INVALIDDATA; + } + + scale_factor = -1.0f / dca_dmix_code((coeff<<2)-3); s->xxch_dmix_sf[s->xxch_chset] = scale_factor; @@ -619,10 +627,12 @@ static int dca_parse_audio_coding_header(DCAContext *s, int base_channel, } coeff = get_bits(&s->gb, 7); - sign = (coeff & 64) ? 1.0 : -1.0; - mag = dca_dmixtable[((coeff & 63) - 1) << 2]; ichan = dca_xxch2index(s, 1 << i); - s->xxch_dmix_coeff[j][ichan] = sign * mag; + if ((coeff&63)<1 || (coeff&63)>61) { + av_log(s->avctx, AV_LOG_ERROR, "7bit coeff %d is out of range\n", coeff); + return AVERROR_INVALIDDATA; + } + s->xxch_dmix_coeff[j][ichan] = dca_dmix_code((coeff<<2)-3); } } } @@ -2064,6 +2074,8 @@ static void dca_exss_parse_header(DCAContext *s) } } + av_assert0(num_assets > 0); // silence a warning + for (i = 0; i < num_assets; i++) asset_size[i] = get_bits_long(&s->gb, 16 + 4 * blownup); @@ -2075,7 +2087,6 @@ static void dca_exss_parse_header(DCAContext *s) /* not parsed further, we were only interested in the extensions mask * from the asset header */ - if (num_assets > 0) { j = get_bits_count(&s->gb); if (start_posn + hdrsize * 8 > j) skip_bits_long(&s->gb, start_posn + hdrsize * 8 - j); @@ -2100,7 +2111,13 @@ static void dca_exss_parse_header(DCAContext *s) if (start_posn + asset_size[i] * 8 > j) skip_bits_long(&s->gb, start_posn + asset_size[i] * 8 - j); } - } +} + +static float dca_dmix_code(unsigned code) +{ + int sign = (code >> 8) - 1; + code &= 0xff; + return ((dca_dmixtable[code] ^ sign) - sign) * (1.0 / (1 << 15)); } /** @@ -2142,7 +2159,6 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } - init_get_bits(&s->gb, s->dca_buffer, s->dca_buffer_size * 8); if ((ret = dca_parse_frame_header(s)) < 0) { //seems like the frame is corrupt, try with the next one return ret; @@ -2172,16 +2188,10 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, */ if (s->core_downmix && (s->core_downmix_amode == DCA_STEREO || s->core_downmix_amode == DCA_STEREO_TOTAL)) { - int sign, code; for (i = 0; i < num_core_channels + !!s->lfe; i++) { - sign = s->core_downmix_codes[i][0] & 0x100 ? 1 : -1; - code = s->core_downmix_codes[i][0] & 0x0FF; - s->downmix_coef[i][0] = (!code ? 0.0f : - sign * dca_dmixtable[code - 1]); - sign = s->core_downmix_codes[i][1] & 0x100 ? 1 : -1; - code = s->core_downmix_codes[i][1] & 0x0FF; - s->downmix_coef[i][1] = (!code ? 0.0f : - sign * dca_dmixtable[code - 1]); + /* Range checked earlier */ + s->downmix_coef[i][0] = dca_dmix_code(s->core_downmix_codes[i][0]); + s->downmix_coef[i][1] = dca_dmix_code(s->core_downmix_codes[i][1]); } s->output = s->core_downmix_amode; } else { @@ -2422,7 +2432,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } } - /* make sure that we have managed to get equivelant dts/avcodec channel + /* make sure that we have managed to get equivalent dts/avcodec channel * masks in some sense -- unfortunately some channels could overlap */ if (av_popcount(channel_mask) != av_popcount(channel_layout)) { av_log(avctx, AV_LOG_DEBUG, diff --git a/libavcodec/dcaenc.c b/libavcodec/dcaenc.c index cb73f42a0..905cdc9ad 100644 --- a/libavcodec/dcaenc.c +++ b/libavcodec/dcaenc.c @@ -29,6 +29,7 @@ #include "dcadata.h" #include "dcaenc.h" #include "internal.h" +#include "mathops.h" #include "put_bits.h" #define MAX_CHANNELS 6 @@ -867,7 +868,7 @@ static void put_subframe(DCAContext *c, int subframe) for (band = 0; band < DCA_SUBBANDS; band++) put_bits(&c->pb, 1, 0); - /* Prediction VQ addres: not transmitted */ + /* Prediction VQ address: not transmitted */ /* Bit allocation index */ for (ch = 0; ch < c->fullband_channels; ch++) for (band = 0; band < DCA_SUBBANDS; band++) diff --git a/libavcodec/dct-test.c b/libavcodec/dct-test.c index 630834836..f7c47fbb5 100644 --- a/libavcodec/dct-test.c +++ b/libavcodec/dct-test.c @@ -47,10 +47,6 @@ #include "x86/idct_xvid.h" #include "dctref.h" -// BFIN -void ff_bfin_idct(int16_t *block); -void ff_bfin_fdct(int16_t *block); - // ALTIVEC void ff_fdct_altivec(int16_t *block); @@ -92,10 +88,6 @@ static const struct algo fdct_tab[] = { { "altivecfdct", ff_fdct_altivec, NO_PERM, AV_CPU_FLAG_ALTIVEC }, #endif -#if ARCH_BFIN - { "BFINfdct", ff_bfin_fdct, NO_PERM }, -#endif - { 0 } }; @@ -153,10 +145,6 @@ static const struct algo idct_tab[] = { #endif #endif -#if ARCH_BFIN - { "BFINidct", ff_bfin_idct, NO_PERM }, -#endif - #if ARCH_ARM { "SIMPLE-ARM", ff_simple_idct_arm, NO_PERM }, { "INT-ARM", ff_j_rev_dct_arm, MMX_PERM }, @@ -348,7 +336,7 @@ static int dct_error(const struct algo *dct, int test, int is_idct, int speed, c init_block(block, test, is_idct, &prng, vals); permute(block1, block, dct->format); - ti = av_gettime(); + ti = av_gettime_relative(); it1 = 0; do { for (it = 0; it < NB_ITS_SPEED; it++) { @@ -357,7 +345,7 @@ static int dct_error(const struct algo *dct, int test, int is_idct, int speed, c } emms_c(); it1 += NB_ITS_SPEED; - ti1 = av_gettime() - ti; + ti1 = av_gettime_relative() - ti; } while (ti1 < 1000000); printf("%s %s: %0.1f kdct/s\n", is_idct ? "IDCT" : "DCT", dct->name, @@ -508,7 +496,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++) { @@ -518,7 +506,7 @@ static void idct248_error(const char *name, } emms_c(); it1 += NB_ITS_SPEED; - ti1 = av_gettime() - ti; + ti1 = av_gettime_relative() - ti; } while (ti1 < 1000000); printf("%s %s: %0.1f kdct/s\n", 1 ? "IDCT248" : "DCT248", name, diff --git a/libavcodec/dct.c b/libavcodec/dct.c index b1ee06a81..26b485106 100644 --- a/libavcodec/dct.c +++ b/libavcodec/dct.c @@ -190,7 +190,7 @@ av_cold int ff_dct_init(DCTContext *s, int nbits, enum DCTTransformType inverse) ff_init_ff_cos_tabs(nbits + 2); s->costab = ff_cos_tabs[nbits + 2]; - s->csc2 = av_malloc(n / 2 * sizeof(FFTSample)); + s->csc2 = av_malloc_array(n / 2, sizeof(FFTSample)); if (ff_rdft_init(&s->rdft, nbits, inverse == DCT_III) < 0) { av_free(s->csc2); diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c index b1be475ef..f13291ef2 100644 --- a/libavcodec/dfa.c +++ b/libavcodec/dfa.c @@ -20,11 +20,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/avassert.h" +#include + #include "avcodec.h" #include "bytestream.h" #include "internal.h" +#include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/mem.h" @@ -369,7 +371,8 @@ static int dfa_decode_frame(AVCodecContext *avctx, return AVERROR_INVALIDDATA; } } else { - av_log(avctx, AV_LOG_WARNING, "Ignoring unknown chunk type %d\n", + av_log(avctx, AV_LOG_WARNING, + "Ignoring unknown chunk type %"PRIu32"\n", chunk_type); } buf += chunk_size; diff --git a/libavcodec/dirac.c b/libavcodec/dirac.c index 3dad75a30..55553d67e 100644 --- a/libavcodec/dirac.c +++ b/libavcodec/dirac.c @@ -322,6 +322,8 @@ int avpriv_dirac_parse_sequence_header(AVCodecContext *avctx, GetBitContext *gb, if (ret < 0) return ret; + ff_set_sar(avctx, avctx->sample_aspect_ratio); + /* [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); diff --git a/libavcodec/dirac_dwt.h b/libavcodec/dirac_dwt.h index 25c13d1a6..e5e447b0a 100644 --- a/libavcodec/dirac_dwt.h +++ b/libavcodec/dirac_dwt.h @@ -82,7 +82,7 @@ int ff_spatial_idwt_init2(DWTContext *d, IDWTELEM *buffer, int width, int height void ff_spatial_idwt_slice2(DWTContext *d, int y); -// shared stuff for simd optimiztions +// shared stuff for simd optimizations #define COMPOSE_53iL0(b0, b1, b2)\ (b1 - ((b0 + b2 + 2) >> 2)) diff --git a/libavcodec/diracdec.c b/libavcodec/diracdec.c index 06d8b79b1..a18c867a3 100644 --- a/libavcodec/diracdec.c +++ b/libavcodec/diracdec.c @@ -27,13 +27,14 @@ */ #include "avcodec.h" -#include "dsputil.h" #include "get_bits.h" #include "bytestream.h" #include "internal.h" #include "golomb.h" #include "dirac_arith.h" #include "mpeg12data.h" +#include "libavcodec/mpegvideo.h" +#include "mpegvideoencdsp.h" #include "dirac_dwt.h" #include "dirac.h" #include "diracdsp.h" @@ -136,7 +137,7 @@ typedef struct Plane { typedef struct DiracContext { AVCodecContext *avctx; - DSPContext dsp; + MpegvideoEncDSPContext mpvencdsp; DiracDSPContext diracdsp; GetBitContext gb; dirac_source_params source; @@ -199,7 +200,7 @@ typedef struct DiracContext { uint8_t *edge_emu_buffer[4]; uint8_t *edge_emu_buffer_base; - uint16_t *mctmp; /* buffer holding the MC data multipled by OBMC weights */ + uint16_t *mctmp; /* buffer holding the MC data multiplied by OBMC weights */ uint8_t *mcscratch; int buffer_stride; @@ -337,8 +338,8 @@ static int alloc_sequence_buffers(DiracContext *s) w = FFALIGN(CALC_PADDING(w, MAX_DWT_LEVELS), 8); /* FIXME: Should this be 16 for SSE??? */ h = top_padding + CALC_PADDING(h, MAX_DWT_LEVELS) + max_yblen/2; - s->plane[i].idwt_buf_base = av_mallocz((w+max_xblen)*h * sizeof(IDWTELEM)); - s->plane[i].idwt_tmp = av_malloc((w+16) * sizeof(IDWTELEM)); + s->plane[i].idwt_buf_base = av_mallocz_array((w+max_xblen), h * sizeof(IDWTELEM)); + s->plane[i].idwt_tmp = av_malloc_array((w+16), sizeof(IDWTELEM)); s->plane[i].idwt_buf = s->plane[i].idwt_buf_base + top_padding*w; if (!s->plane[i].idwt_buf_base || !s->plane[i].idwt_tmp) return AVERROR(ENOMEM); @@ -422,8 +423,8 @@ static av_cold int dirac_decode_init(AVCodecContext *avctx) s->avctx = avctx; s->frame_number = -1; - ff_dsputil_init(&s->dsp, avctx); ff_diracdsp_init(&s->diracdsp); + ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx); for (i = 0; i < MAX_FRAMES; i++) { s->all_frames[i].avframe = av_frame_alloc(); @@ -694,7 +695,7 @@ static void lowdelay_subband(DiracContext *s, GetBitContext *gb, int quant, IDWTELEM *buf1 = b1->ibuf + top * b1->stride; IDWTELEM *buf2 = b2 ? b2->ibuf + top * b2->stride : NULL; int x, y; - /* we have to constantly check for overread since the spec explictly + /* we have to constantly check for overread since the spec explicitly requires this, with the meaning that all remaining coeffs are set to 0 */ if (get_bits_count(gb) >= bits_end) return; @@ -778,7 +779,7 @@ static void decode_lowdelay(DiracContext *s) struct lowdelay_slice *slices; int slice_num = 0; - slices = av_mallocz(s->lowdelay.num_x * s->lowdelay.num_y * sizeof(struct lowdelay_slice)); + slices = av_mallocz_array(s->lowdelay.num_x, s->lowdelay.num_y * sizeof(struct lowdelay_slice)); align_get_bits(&s->gb); /*[DIRAC_STD] 13.5.2 Slices. slice(sx,sy) */ @@ -1556,7 +1557,7 @@ static void interpolate_refplane(DiracContext *s, DiracFrame *ref, int plane, in int i, edge = EDGE_WIDTH/2; ref->hpel[plane][0] = ref->avframe->data[plane]; - s->dsp.draw_edges(ref->hpel[plane][0], ref->avframe->linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); /* EDGE_TOP | EDGE_BOTTOM values just copied to make it build, this needs to be ensured */ + s->mpvencdsp.draw_edges(ref->hpel[plane][0], ref->avframe->linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); /* EDGE_TOP | EDGE_BOTTOM values just copied to make it build, this needs to be ensured */ /* no need for hpel if we only have fpel vectors */ if (!s->mv_precision) @@ -1573,9 +1574,9 @@ static void interpolate_refplane(DiracContext *s, DiracFrame *ref, int plane, in s->diracdsp.dirac_hpel_filter(ref->hpel[plane][1], ref->hpel[plane][2], ref->hpel[plane][3], ref->hpel[plane][0], ref->avframe->linesize[plane], width, height); - s->dsp.draw_edges(ref->hpel[plane][1], ref->avframe->linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); - s->dsp.draw_edges(ref->hpel[plane][2], ref->avframe->linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); - s->dsp.draw_edges(ref->hpel[plane][3], ref->avframe->linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); + s->mpvencdsp.draw_edges(ref->hpel[plane][1], ref->avframe->linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); + s->mpvencdsp.draw_edges(ref->hpel[plane][2], ref->avframe->linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); + s->mpvencdsp.draw_edges(ref->hpel[plane][3], ref->avframe->linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); } ref->interpolated[plane] = 1; } diff --git a/libavcodec/dnxhd_parser.c b/libavcodec/dnxhd_parser.c index 6e030e421..fffb98fa4 100644 --- a/libavcodec/dnxhd_parser.c +++ b/libavcodec/dnxhd_parser.c @@ -46,7 +46,7 @@ static int dnxhd_find_frame_end(DNXHDParserContext *dctx, if (!pic_found) { for (i = 0; i < buf_size; i++) { - state = (state<<8) | buf[i]; + state = (state << 8) | buf[i]; if ((state & 0xffffffffff00LL) == DNXHD_HEADER_PREFIX) { i++; pic_found = 1; @@ -61,14 +61,14 @@ static int dnxhd_find_frame_end(DNXHDParserContext *dctx, if (!buf_size) /* EOF considered as end of frame */ return 0; for (; i < buf_size; i++) { - state = (state<<8) | buf[i]; + state = (state << 8) | buf[i]; if ((state & 0xffffffffff00LL) == DNXHD_HEADER_PREFIX) { if (!interlaced || dctx->cur_field) { pc->frame_start_found = 0; pc->state64 = -1; dctx->interlaced = interlaced; dctx->cur_field = 0; - return i-5; + return i - 5; } else { /* continue, to get the second field */ dctx->interlaced = interlaced = (state&2)>>1; @@ -98,12 +98,12 @@ static int dnxhd_parse(AVCodecParserContext *s, } else { next = dnxhd_find_frame_end(dctx, buf, buf_size); if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { - *poutbuf = NULL; + *poutbuf = NULL; *poutbuf_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 80f533728..7ea91915e 100644 --- a/libavcodec/dnxhddata.c +++ b/libavcodec/dnxhddata.c @@ -1067,7 +1067,7 @@ int avpriv_dnxhd_get_frame_size(int cid) int ff_dnxhd_find_cid(AVCodecContext *avctx, int bit_depth) { int i, j; - int mbs = avctx->bit_rate/1000000; + int mbs = avctx->bit_rate / 1000000; if (!mbs) return 0; for (i = 0; i < FF_ARRAY_ELEMS(ff_dnxhd_cid_table); i++) { diff --git a/libavcodec/dnxhddata.h b/libavcodec/dnxhddata.h index b8bcb21d8..8166ee848 100644 --- a/libavcodec/dnxhddata.h +++ b/libavcodec/dnxhddata.h @@ -42,7 +42,7 @@ typedef struct CIDEntry { const uint8_t *ac_flags; const uint16_t *run_codes; const uint8_t *run_bits, *run; - int bit_rates[5]; ///< Helpher to choose variants, rounded to nearest 5Mb/s + int bit_rates[5]; ///< Helper to choose variants, rounded to nearest 5Mb/s AVRational frame_rates[5]; } CIDEntry; diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c index 0f9fd16b5..787c6c5ec 100644 --- a/libavcodec/dnxhddec.c +++ b/libavcodec/dnxhddec.c @@ -25,15 +25,17 @@ #include "libavutil/imgutils.h" #include "libavutil/timer.h" #include "avcodec.h" +#include "blockdsp.h" #include "get_bits.h" #include "dnxhddata.h" -#include "dsputil.h" +#include "idctdsp.h" #include "internal.h" #include "thread.h" typedef struct DNXHDContext { AVCodecContext *avctx; GetBitContext gb; + BlockDSPContext bdsp; int64_t cid; ///< compression id unsigned int width, height; unsigned int mb_width, mb_height; @@ -41,7 +43,7 @@ typedef struct DNXHDContext { int cur_field; ///< current interlaced field VLC ac_vlc, dc_vlc, run_vlc; int last_dc[3]; - DSPContext dsp; + IDCTDSPContext idsp; DECLARE_ALIGNED(16, int16_t, blocks)[12][64]; ScanTable scantable; const CIDEntry *cid_table; @@ -57,9 +59,12 @@ typedef struct DNXHDContext { #define DNXHD_VLC_BITS 9 #define DNXHD_DC_VLC_BITS 7 -static void dnxhd_decode_dct_block_8(DNXHDContext *ctx, int16_t *block, int n, int qscale); -static void dnxhd_decode_dct_block_10(DNXHDContext *ctx, int16_t *block, int n, int qscale); -static void dnxhd_decode_dct_block_10_444(DNXHDContext *ctx, int16_t *block, int n, int qscale); +static void dnxhd_decode_dct_block_8(DNXHDContext *ctx, int16_t *block, + int n, int qscale); +static void dnxhd_decode_dct_block_10(DNXHDContext *ctx, int16_t *block, + int n, int qscale); +static void dnxhd_decode_dct_block_10_444(DNXHDContext *ctx, int16_t *block, + int n, int qscale); static av_cold int dnxhd_decode_init(AVCodecContext *avctx) { @@ -99,14 +104,16 @@ static int dnxhd_init_vlc(DNXHDContext *ctx, uint32_t cid) ctx->cid_table->run_bits, 1, 1, ctx->cid_table->run_codes, 2, 2, 0); - ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, ff_zigzag_direct); + ff_init_scantable(ctx->idsp.idct_permutation, &ctx->scantable, + ff_zigzag_direct); ctx->cid = cid; } return 0; } static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, - const uint8_t *buf, int buf_size, int first_field) + const uint8_t *buf, int buf_size, + int first_field) { static const uint8_t header_prefix[] = { 0x00, 0x00, 0x02, 0x80, 0x01 }; static const uint8_t header_prefix444[] = { 0x00, 0x00, 0x02, 0x80, 0x02 }; @@ -123,7 +130,8 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, ctx->cur_field = buf[5] & 1; frame->interlaced_frame = 1; frame->top_field_first = first_field ^ ctx->cur_field; - av_log(ctx->avctx, AV_LOG_DEBUG, "interlaced %d, cur field %d\n", buf[5] & 3, ctx->cur_field); + av_log(ctx->avctx, AV_LOG_DEBUG, + "interlaced %d, cur field %d\n", buf[5] & 3, ctx->cur_field); } ctx->height = AV_RB16(buf + 0x18); @@ -136,7 +144,8 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, ctx->avctx->pix_fmt = AV_PIX_FMT_YUV444P10; ctx->avctx->bits_per_raw_sample = 10; if (ctx->bit_depth != 10) { - ff_dsputil_init(&ctx->dsp, ctx->avctx); + ff_blockdsp_init(&ctx->bdsp, ctx->avctx); + ff_idctdsp_init(&ctx->idsp, ctx->avctx); ctx->bit_depth = 10; ctx->decode_dct_block = dnxhd_decode_dct_block_10_444; } @@ -145,7 +154,8 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P10; ctx->avctx->bits_per_raw_sample = 10; if (ctx->bit_depth != 10) { - ff_dsputil_init(&ctx->dsp, ctx->avctx); + ff_blockdsp_init(&ctx->bdsp, ctx->avctx); + ff_idctdsp_init(&ctx->idsp, ctx->avctx); ctx->bit_depth = 10; ctx->decode_dct_block = dnxhd_decode_dct_block_10; } @@ -153,7 +163,8 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P; ctx->avctx->bits_per_raw_sample = 8; if (ctx->bit_depth != 8) { - ff_dsputil_init(&ctx->dsp, ctx->avctx); + 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; } @@ -170,22 +181,24 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, return AVERROR_INVALIDDATA; } - ctx->mb_width = ctx->width>>4; + ctx->mb_width = ctx->width >> 4; ctx->mb_height = buf[0x16d]; - av_dlog(ctx->avctx, "mb width %d, mb height %d\n", ctx->mb_width, ctx->mb_height); + av_dlog(ctx->avctx, + "mb width %d, mb height %d\n", ctx->mb_width, ctx->mb_height); - if ((ctx->height+15)>>4 == ctx->mb_height && frame->interlaced_frame) + if ((ctx->height + 15) >> 4 == ctx->mb_height && frame->interlaced_frame) ctx->height <<= 1; if (ctx->mb_height > 68 || - (ctx->mb_height << frame->interlaced_frame) > (ctx->height+15)>>4) { - av_log(ctx->avctx, AV_LOG_ERROR, "mb height too big: %d\n", ctx->mb_height); + (ctx->mb_height << frame->interlaced_frame) > (ctx->height + 15) >> 4) { + av_log(ctx->avctx, AV_LOG_ERROR, + "mb height too big: %d\n", ctx->mb_height); return AVERROR_INVALIDDATA; } for (i = 0; i < ctx->mb_height; i++) { - ctx->mb_scan_index[i] = AV_RB32(buf + 0x170 + (i<<2)); + ctx->mb_scan_index[i] = AV_RB32(buf + 0x170 + (i << 2)); av_dlog(ctx->avctx, "mb scan index %d\n", ctx->mb_scan_index[i]); if (buf_size < ctx->mb_scan_index[i] + 0x280LL) { av_log(ctx->avctx, AV_LOG_ERROR, "invalid mb scan index\n"); @@ -213,12 +226,12 @@ static av_always_inline void dnxhd_decode_dct_block(DNXHDContext *ctx, OPEN_READER(bs, &ctx->gb); if (!ctx->is_444) { - if (n&2) { - component = 1 + (n&1); + if (n & 2) { + component = 1 + (n & 1); scale = ctx->chroma_scale; weight_matrix = ctx->cid_table->chroma_weight; } else { - component = 0; + component = 0; scale = ctx->luma_scale; weight_matrix = ctx->cid_table->luma_weight; } @@ -274,13 +287,13 @@ static av_always_inline void dnxhd_decode_dct_block(DNXHDContext *ctx, break; } - j = ctx->scantable.permutated[i]; + j = ctx->scantable.permutated[i]; level *= scale[i]; if (level_bias < 32 || weight_matrix[i] != level_bias) level += level_bias; level >>= level_shift; - block[j] = (level^sign) - sign; + block[j] = (level ^ sign) - sign; UPDATE_CACHE(bs, &ctx->gb); GET_VLC(index1, bs, &ctx->gb, ctx->ac_vlc.table, @@ -308,7 +321,8 @@ static void dnxhd_decode_dct_block_10_444(DNXHDContext *ctx, int16_t *block, dnxhd_decode_dct_block(ctx, block, n, qscale, 6, 32, 6); } -static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, int x, int y) +static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, + int x, int y) { int shift1 = ctx->bit_depth == 10; int dct_linesize_luma = frame->linesize[0]; @@ -329,12 +343,12 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, int x, int } for (i = 0; i < 8; i++) { - ctx->dsp.clear_block(ctx->blocks[i]); + ctx->bdsp.clear_block(ctx->blocks[i]); ctx->decode_dct_block(ctx, ctx->blocks[i], i, qscale); } if (ctx->is_444) { for (; i < 12; i++) { - ctx->dsp.clear_block(ctx->blocks[i]); + ctx->bdsp.clear_block(ctx->blocks[i]); ctx->decode_dct_block(ctx, ctx->blocks[i], i, qscale); } } @@ -357,34 +371,34 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, int x, int dct_y_offset = dct_linesize_luma << 3; dct_x_offset = 8 << shift1; if (!ctx->is_444) { - ctx->dsp.idct_put(dest_y, dct_linesize_luma, ctx->blocks[0]); - ctx->dsp.idct_put(dest_y + dct_x_offset, dct_linesize_luma, ctx->blocks[1]); - ctx->dsp.idct_put(dest_y + dct_y_offset, dct_linesize_luma, ctx->blocks[4]); - ctx->dsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, ctx->blocks[5]); + ctx->idsp.idct_put(dest_y, dct_linesize_luma, ctx->blocks[0]); + ctx->idsp.idct_put(dest_y + dct_x_offset, dct_linesize_luma, ctx->blocks[1]); + 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; - ctx->dsp.idct_put(dest_u, dct_linesize_chroma, ctx->blocks[2]); - ctx->dsp.idct_put(dest_v, dct_linesize_chroma, ctx->blocks[3]); - ctx->dsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, ctx->blocks[6]); - ctx->dsp.idct_put(dest_v + dct_y_offset, dct_linesize_chroma, ctx->blocks[7]); + 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]); + ctx->idsp.idct_put(dest_v + dct_y_offset, dct_linesize_chroma, ctx->blocks[7]); } } else { - ctx->dsp.idct_put(dest_y, dct_linesize_luma, ctx->blocks[0]); - ctx->dsp.idct_put(dest_y + dct_x_offset, dct_linesize_luma, ctx->blocks[1]); - ctx->dsp.idct_put(dest_y + dct_y_offset, dct_linesize_luma, ctx->blocks[6]); - ctx->dsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, ctx->blocks[7]); + ctx->idsp.idct_put(dest_y, dct_linesize_luma, ctx->blocks[0]); + ctx->idsp.idct_put(dest_y + dct_x_offset, dct_linesize_luma, ctx->blocks[1]); + 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; - ctx->dsp.idct_put(dest_u, dct_linesize_chroma, ctx->blocks[2]); - ctx->dsp.idct_put(dest_u + dct_x_offset, dct_linesize_chroma, ctx->blocks[3]); - ctx->dsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, ctx->blocks[8]); - ctx->dsp.idct_put(dest_u + dct_y_offset + dct_x_offset, dct_linesize_chroma, ctx->blocks[9]); - ctx->dsp.idct_put(dest_v, dct_linesize_chroma, ctx->blocks[4]); - ctx->dsp.idct_put(dest_v + dct_x_offset, dct_linesize_chroma, ctx->blocks[5]); - ctx->dsp.idct_put(dest_v + dct_y_offset, dct_linesize_chroma, ctx->blocks[10]); - ctx->dsp.idct_put(dest_v + dct_y_offset + dct_x_offset, dct_linesize_chroma, ctx->blocks[11]); + 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]); + ctx->idsp.idct_put(dest_u + dct_y_offset + dct_x_offset, dct_linesize_chroma, ctx->blocks[9]); + ctx->idsp.idct_put(dest_v, dct_linesize_chroma, ctx->blocks[4]); + ctx->idsp.idct_put(dest_v + dct_x_offset, dct_linesize_chroma, ctx->blocks[5]); + ctx->idsp.idct_put(dest_v + dct_y_offset, dct_linesize_chroma, ctx->blocks[10]); + ctx->idsp.idct_put(dest_v + dct_y_offset + dct_x_offset, dct_linesize_chroma, ctx->blocks[11]); } } @@ -409,8 +423,8 @@ static int dnxhd_decode_macroblocks(DNXHDContext *ctx, AVFrame *frame, return 0; } -static int dnxhd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int dnxhd_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -422,7 +436,7 @@ static int dnxhd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, av_dlog(avctx, "frame size %d\n", buf_size); - decode_coding_unit: +decode_coding_unit: if ((ret = dnxhd_decode_header(ctx, picture, buf, buf_size, first_field)) < 0) return ret; diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index fb37a9d3e..3ad625352 100644 --- a/libavcodec/dnxhdenc.c +++ b/libavcodec/dnxhdenc.c @@ -23,24 +23,30 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#define RC_VARIANCE 1 // use variance or ssd for fast rc - #include "libavutil/attributes.h" #include "libavutil/internal.h" #include "libavutil/opt.h" #include "libavutil/timer.h" + #include "avcodec.h" -#include "dsputil.h" +#include "blockdsp.h" +#include "fdctdsp.h" #include "internal.h" #include "mpegvideo.h" +#include "pixblockdsp.h" #include "dnxhdenc.h" -#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM -#define DNX10BIT_QMAT_SHIFT 18 // The largest value that will not lead to overflow for 10bit samples. -static const AVOption options[]={ - {"nitris_compat", "encode with Avid Nitris compatibility", offsetof(DNXHDEncContext, nitris_compat), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, VE}, -{NULL} +// The largest value that will not lead to overflow for 10bit samples. +#define DNX10BIT_QMAT_SHIFT 18 +#define RC_VARIANCE 1 // use variance or ssd for fast rc +#define LAMBDA_FRAC_BITS 10 + +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "nitris_compat", "encode with Avid Nitris compatibility", + offsetof(DNXHDEncContext, nitris_compat), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { NULL } }; static const AVClass dnxhd_class = { @@ -50,18 +56,22 @@ static const AVClass dnxhd_class = { .version = LIBAVUTIL_VERSION_INT, }; -#define LAMBDA_FRAC_BITS 10 - -static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint8_t *pixels, int line_size) +static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *av_restrict block, + const uint8_t *pixels, + ptrdiff_t line_size) { int i; for (i = 0; i < 4; i++) { - block[0] = pixels[0]; block[1] = pixels[1]; - block[2] = pixels[2]; block[3] = pixels[3]; - block[4] = pixels[4]; block[5] = pixels[5]; - block[6] = pixels[6]; block[7] = pixels[7]; - pixels += line_size; - block += 8; + block[0] = pixels[0]; + block[1] = pixels[1]; + block[2] = pixels[2]; + block[3] = pixels[3]; + block[4] = pixels[4]; + block[5] = pixels[5]; + block[6] = pixels[6]; + block[7] = pixels[7]; + pixels += line_size; + block += 8; } memcpy(block, block - 8, sizeof(*block) * 8); memcpy(block + 8, block - 16, sizeof(*block) * 8); @@ -69,7 +79,10 @@ static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint memcpy(block + 24, block - 32, sizeof(*block) * 8); } -static av_always_inline void dnxhd_10bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint8_t *pixels, int line_size) +static av_always_inline +void dnxhd_10bit_get_pixels_8x4_sym(int16_t *av_restrict block, + const uint8_t *pixels, + ptrdiff_t line_size) { int i; const uint16_t* pixels16 = (const uint16_t*)pixels; @@ -97,7 +110,7 @@ static int dnxhd_10bit_dct_quantize(MpegEncContext *ctx, int16_t *block, int last_non_zero = 0; int i; - ctx->dsp.fdct(block); + ctx->fdsp.fdct(block); // Divide by 4 with rounding, to compensate scaling of DCT coefficients block[0] = (block[0] + 2) >> 2; @@ -118,24 +131,28 @@ static int dnxhd_10bit_dct_quantize(MpegEncContext *ctx, int16_t *block, static av_cold int dnxhd_init_vlc(DNXHDEncContext *ctx) { int i, j, level, run; - int max_level = 1<<(ctx->cid_table->bit_depth+2); + int max_level = 1 << (ctx->cid_table->bit_depth + 2); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->vlc_codes, max_level*4*sizeof(*ctx->vlc_codes), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->vlc_bits, max_level*4*sizeof(*ctx->vlc_bits) , fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->run_codes, 63*2, fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->run_bits, 63, fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->vlc_codes, + max_level * 4 * sizeof(*ctx->vlc_codes), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->vlc_bits, + max_level * 4 * sizeof(*ctx->vlc_bits), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->run_codes, + 63 * 2, fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->run_bits, + 63, fail); - ctx->vlc_codes += max_level*2; - ctx->vlc_bits += max_level*2; + ctx->vlc_codes += max_level * 2; + ctx->vlc_bits += max_level * 2; for (level = -max_level; level < max_level; level++) { for (run = 0; run < 2; run++) { - int index = (level<<1)|run; + int index = (level << 1) | run; int sign, offset = 0, alevel = level; MASK_ABS(sign, alevel); if (alevel > 64) { - offset = (alevel-1)>>6; - alevel -= offset<<6; + offset = (alevel - 1) >> 6; + alevel -= offset << 6; } for (j = 0; j < 257; j++) { if (ctx->cid_table->ac_level[j] >> 1 == alevel && @@ -143,19 +160,21 @@ static av_cold int dnxhd_init_vlc(DNXHDEncContext *ctx) (!run || (ctx->cid_table->ac_flags[j] & 2) && run)) { av_assert1(!ctx->vlc_codes[index]); if (alevel) { - ctx->vlc_codes[index] = (ctx->cid_table->ac_codes[j]<<1)|(sign&1); - ctx->vlc_bits [index] = ctx->cid_table->ac_bits[j]+1; + ctx->vlc_codes[index] = + (ctx->cid_table->ac_codes[j] << 1) | (sign & 1); + ctx->vlc_bits[index] = ctx->cid_table->ac_bits[j] + 1; } else { ctx->vlc_codes[index] = ctx->cid_table->ac_codes[j]; - ctx->vlc_bits [index] = ctx->cid_table->ac_bits [j]; + ctx->vlc_bits[index] = ctx->cid_table->ac_bits[j]; } break; } } av_assert0(!alevel || j < 257); if (offset) { - ctx->vlc_codes[index] = (ctx->vlc_codes[index]<cid_table->index_bits)|offset; - ctx->vlc_bits [index]+= ctx->cid_table->index_bits; + ctx->vlc_codes[index] = + (ctx->vlc_codes[index] << ctx->cid_table->index_bits) | offset; + ctx->vlc_bits[index] += ctx->cid_table->index_bits; } } } @@ -163,63 +182,79 @@ static av_cold int dnxhd_init_vlc(DNXHDEncContext *ctx) int run = ctx->cid_table->run[i]; av_assert0(run < 63); ctx->run_codes[run] = ctx->cid_table->run_codes[i]; - ctx->run_bits [run] = ctx->cid_table->run_bits[i]; + ctx->run_bits[run] = ctx->cid_table->run_bits[i]; } return 0; - fail: +fail: return AVERROR(ENOMEM); } static av_cold int dnxhd_init_qmat(DNXHDEncContext *ctx, int lbias, int cbias) { // init first elem to 1 to avoid div by 0 in convert_matrix - uint16_t weight_matrix[64] = {1,}; // convert_matrix needs uint16_t* + uint16_t weight_matrix[64] = { 1, }; // convert_matrix needs uint16_t* int qscale, i; const uint8_t *luma_weight_table = ctx->cid_table->luma_weight; const uint8_t *chroma_weight_table = ctx->cid_table->chroma_weight; - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_l, (ctx->m.avctx->qmax+1) * 64 * sizeof(int), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_c, (ctx->m.avctx->qmax+1) * 64 * sizeof(int), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_l16, (ctx->m.avctx->qmax+1) * 64 * 2 * sizeof(uint16_t), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_c16, (ctx->m.avctx->qmax+1) * 64 * 2 * sizeof(uint16_t), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_l, + (ctx->m.avctx->qmax + 1) * 64 * sizeof(int), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_c, + (ctx->m.avctx->qmax + 1) * 64 * sizeof(int), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_l16, + (ctx->m.avctx->qmax + 1) * 64 * 2 * sizeof(uint16_t), + fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_c16, + (ctx->m.avctx->qmax + 1) * 64 * 2 * sizeof(uint16_t), + fail); if (ctx->cid_table->bit_depth == 8) { for (i = 1; i < 64; i++) { - int j = ctx->m.dsp.idct_permutation[ff_zigzag_direct[i]]; + int j = ctx->m.idsp.idct_permutation[ff_zigzag_direct[i]]; weight_matrix[j] = ctx->cid_table->luma_weight[i]; } - ff_convert_matrix(&ctx->m.dsp, ctx->qmatrix_l, ctx->qmatrix_l16, weight_matrix, - ctx->m.intra_quant_bias, 1, ctx->m.avctx->qmax, 1); + ff_convert_matrix(&ctx->m, ctx->qmatrix_l, ctx->qmatrix_l16, + weight_matrix, ctx->m.intra_quant_bias, 1, + ctx->m.avctx->qmax, 1); for (i = 1; i < 64; i++) { - int j = ctx->m.dsp.idct_permutation[ff_zigzag_direct[i]]; + 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.dsp, ctx->qmatrix_c, ctx->qmatrix_c16, weight_matrix, - ctx->m.intra_quant_bias, 1, ctx->m.avctx->qmax, 1); + ff_convert_matrix(&ctx->m, ctx->qmatrix_c, ctx->qmatrix_c16, + weight_matrix, ctx->m.intra_quant_bias, 1, + ctx->m.avctx->qmax, 1); for (qscale = 1; qscale <= ctx->m.avctx->qmax; qscale++) { for (i = 0; i < 64; i++) { - ctx->qmatrix_l [qscale] [i] <<= 2; ctx->qmatrix_c [qscale] [i] <<= 2; - ctx->qmatrix_l16[qscale][0][i] <<= 2; ctx->qmatrix_l16[qscale][1][i] <<= 2; - ctx->qmatrix_c16[qscale][0][i] <<= 2; ctx->qmatrix_c16[qscale][1][i] <<= 2; + ctx->qmatrix_l[qscale][i] <<= 2; + ctx->qmatrix_c[qscale][i] <<= 2; + ctx->qmatrix_l16[qscale][0][i] <<= 2; + ctx->qmatrix_l16[qscale][1][i] <<= 2; + ctx->qmatrix_c16[qscale][0][i] <<= 2; + ctx->qmatrix_c16[qscale][1][i] <<= 2; } } } else { // 10-bit for (qscale = 1; qscale <= ctx->m.avctx->qmax; qscale++) { for (i = 1; i < 64; i++) { - int j = ctx->m.dsp.idct_permutation[ff_zigzag_direct[i]]; + int j = ctx->m.idsp.idct_permutation[ff_zigzag_direct[i]]; - // The quantization formula from the VC-3 standard is: - // quantized = sign(block[i]) * floor(abs(block[i]/s) * p / (qscale * weight_table[i])) - // Where p is 32 for 8-bit samples and 8 for 10-bit ones. - // The s factor compensates scaling of DCT coefficients done by the DCT routines, - // and therefore is not present in standard. It's 8 for 8-bit samples and 4 for 10-bit ones. - // We want values of ctx->qtmatrix_l and ctx->qtmatrix_r to be: - // ((1 << DNX10BIT_QMAT_SHIFT) * (p / s)) / (qscale * weight_table[i]) - // For 10-bit samples, p / s == 2 - ctx->qmatrix_l[qscale][j] = (1 << (DNX10BIT_QMAT_SHIFT + 1)) / (qscale * luma_weight_table[i]); - ctx->qmatrix_c[qscale][j] = (1 << (DNX10BIT_QMAT_SHIFT + 1)) / (qscale * chroma_weight_table[i]); + /* The quantization formula from the VC-3 standard is: + * quantized = sign(block[i]) * floor(abs(block[i]/s) * p / + * (qscale * weight_table[i])) + * Where p is 32 for 8-bit samples and 8 for 10-bit ones. + * The s factor compensates scaling of DCT coefficients done by + * the DCT routines, and therefore is not present in standard. + * It's 8 for 8-bit samples and 4 for 10-bit ones. + * We want values of ctx->qtmatrix_l and ctx->qtmatrix_r to be: + * ((1 << DNX10BIT_QMAT_SHIFT) * (p / s)) / + * (qscale * weight_table[i]) + * For 10-bit samples, p / s == 2 */ + ctx->qmatrix_l[qscale][j] = (1 << (DNX10BIT_QMAT_SHIFT + 1)) / + (qscale * luma_weight_table[i]); + ctx->qmatrix_c[qscale][j] = (1 << (DNX10BIT_QMAT_SHIFT + 1)) / + (qscale * chroma_weight_table[i]); } } } @@ -230,21 +265,23 @@ static av_cold int dnxhd_init_qmat(DNXHDEncContext *ctx, int lbias, int cbias) ctx->m.q_intra_matrix = ctx->qmatrix_l; return 0; - fail: +fail: return AVERROR(ENOMEM); } static av_cold int dnxhd_init_rc(DNXHDEncContext *ctx) { - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_rc, 8160*(ctx->m.avctx->qmax + 1)*sizeof(RCEntry), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_rc, 8160 * (ctx->m.avctx->qmax + 1) * sizeof(RCEntry), fail); if (ctx->m.avctx->mb_decision != FF_MB_DECISION_RD) - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_cmp, ctx->m.mb_num*sizeof(RCCMPEntry), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_cmp, + ctx->m.mb_num * sizeof(RCCMPEntry), fail); - ctx->frame_bits = (ctx->cid_table->coding_unit_size - 640 - 4 - ctx->min_padding) * 8; + ctx->frame_bits = (ctx->cid_table->coding_unit_size - + 640 - 4 - ctx->min_padding) * 8; ctx->qscale = 1; - ctx->lambda = 2<lambda = 2 << LAMBDA_FRAC_BITS; // qscale 2 return 0; - fail: +fail: return AVERROR(ENOMEM); } @@ -261,13 +298,15 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) bit_depth = 10; break; default: - av_log(avctx, AV_LOG_ERROR, "pixel format is incompatible with DNxHD\n"); + av_log(avctx, AV_LOG_ERROR, + "pixel format is incompatible with DNxHD\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. Valid DNxHD profiles:\n"); + av_log(avctx, AV_LOG_ERROR, + "video parameters incompatible with DNxHD. Valid DNxHD profiles:\n"); ff_dnxhd_print_profiles(avctx, AV_LOG_ERROR); return AVERROR(EINVAL); } @@ -277,12 +316,17 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) av_assert0(index >= 0); ctx->cid_table = &ff_dnxhd_cid_table[index]; - ctx->m.avctx = avctx; + ctx->m.avctx = avctx; ctx->m.mb_intra = 1; ctx->m.h263_aic = 1; avctx->bits_per_raw_sample = ctx->cid_table->bit_depth; + ff_blockdsp_init(&ctx->bdsp, avctx); + ff_fdctdsp_init(&ctx->m.fdsp, avctx); + ff_idctdsp_init(&ctx->m.idsp, avctx); + ff_mpegvideoencdsp_init(&ctx->m.mpvencdsp, avctx); + ff_pixblockdsp_init(&ctx->m.pdsp, avctx); ff_dct_common_init(&ctx->m); ff_dct_encode_init(&ctx->m); @@ -290,12 +334,12 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) ctx->m.dct_quantize = ff_dct_quantize_c; if (ctx->cid_table->bit_depth == 10) { - ctx->m.dct_quantize = dnxhd_10bit_dct_quantize; - ctx->get_pixels_8x4_sym = dnxhd_10bit_get_pixels_8x4_sym; - ctx->block_width_l2 = 4; + ctx->m.dct_quantize = dnxhd_10bit_dct_quantize; + ctx->get_pixels_8x4_sym = dnxhd_10bit_get_pixels_8x4_sym; + ctx->block_width_l2 = 4; } else { - ctx->get_pixels_8x4_sym = dnxhd_8bit_get_pixels_8x4_sym; - ctx->block_width_l2 = 3; + ctx->get_pixels_8x4_sym = dnxhd_8bit_get_pixels_8x4_sym; + ctx->block_width_l2 = 3; } if (ARCH_X86) @@ -305,7 +349,7 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) ctx->m.mb_width = (avctx->width + 15) / 16; if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) { - ctx->interlaced = 1; + ctx->interlaced = 1; ctx->m.mb_height /= 2; } @@ -313,10 +357,12 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) if (avctx->intra_quant_bias != FF_DEFAULT_QUANT_BIAS) ctx->m.intra_quant_bias = avctx->intra_quant_bias; - if ((ret = dnxhd_init_qmat(ctx, ctx->m.intra_quant_bias, 0)) < 0) // XXX tune lbias/cbias + // XXX tune lbias/cbias + if ((ret = dnxhd_init_qmat(ctx, ctx->m.intra_quant_bias, 0)) < 0) return ret; - // Avid Nitris hardware decoder requires a minimum amount of padding in the coding unit payload + /* Avid Nitris hardware decoder requires a minimum amount of padding + * in the coding unit payload */ if (ctx->nitris_compat) ctx->min_padding = 1600; @@ -325,10 +371,14 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) if ((ret = dnxhd_init_rc(ctx)) < 0) return ret; - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->slice_size, ctx->m.mb_height*sizeof(uint32_t), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->slice_offs, ctx->m.mb_height*sizeof(uint32_t), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_bits, ctx->m.mb_num *sizeof(uint16_t), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_qscale, ctx->m.mb_num *sizeof(uint8_t), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->slice_size, + ctx->m.mb_height * sizeof(uint32_t), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->slice_offs, + ctx->m.mb_height * sizeof(uint32_t), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_bits, + ctx->m.mb_num * sizeof(uint16_t), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_qscale, + ctx->m.mb_num * sizeof(uint8_t), fail); avctx->coded_frame = av_frame_alloc(); if (!avctx->coded_frame) @@ -349,32 +399,32 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) ctx->thread[0] = ctx; for (i = 1; i < avctx->thread_count; i++) { - ctx->thread[i] = av_malloc(sizeof(DNXHDEncContext)); + ctx->thread[i] = av_malloc(sizeof(DNXHDEncContext)); memcpy(ctx->thread[i], ctx, sizeof(DNXHDEncContext)); } return 0; - fail: //for FF_ALLOCZ_OR_GOTO +fail: // for FF_ALLOCZ_OR_GOTO return AVERROR(ENOMEM); } static int dnxhd_write_header(AVCodecContext *avctx, uint8_t *buf) { DNXHDEncContext *ctx = avctx->priv_data; - static 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); memcpy(buf, header_prefix, 5); - buf[5] = ctx->interlaced ? ctx->cur_field+2 : 0x01; + buf[5] = ctx->interlaced ? ctx->cur_field + 2 : 0x01; buf[6] = 0x80; // crc flag off buf[7] = 0xa0; // reserved - AV_WB16(buf + 0x18, avctx->height>>ctx->interlaced); // ALPF + AV_WB16(buf + 0x18, avctx->height >> ctx->interlaced); // ALPF AV_WB16(buf + 0x1a, avctx->width); // SPL - AV_WB16(buf + 0x1d, avctx->height>>ctx->interlaced); // NAL + AV_WB16(buf + 0x1d, avctx->height >> ctx->interlaced); // NAL buf[0x21] = ctx->cid_table->bit_depth == 10 ? 0x58 : 0x38; - buf[0x22] = 0x88 + (ctx->interlaced<<2); + buf[0x22] = 0x88 + (ctx->interlaced << 2); AV_WB32(buf + 0x28, ctx->cid); // CID buf[0x2c] = ctx->interlaced ? 0 : 0x80; @@ -393,16 +443,19 @@ static av_always_inline void dnxhd_encode_dc(DNXHDEncContext *ctx, int diff) { int nbits; if (diff < 0) { - nbits = av_log2_16bit(-2*diff); + nbits = av_log2_16bit(-2 * diff); diff--; } else { - nbits = av_log2_16bit(2*diff); + nbits = av_log2_16bit(2 * diff); } put_bits(&ctx->m.pb, ctx->cid_table->dc_bits[nbits] + nbits, - (ctx->cid_table->dc_codes[nbits]<cid_table->dc_codes[nbits] << nbits) + + (diff & ((1 << nbits) - 1))); } -static av_always_inline void dnxhd_encode_block(DNXHDEncContext *ctx, int16_t *block, int last_index, int n) +static av_always_inline +void dnxhd_encode_block(DNXHDEncContext *ctx, int16_t *block, + int last_index, int n) { int last_non_zero = 0; int slevel, i, j; @@ -415,30 +468,34 @@ static av_always_inline void dnxhd_encode_block(DNXHDEncContext *ctx, int16_t *b slevel = block[j]; if (slevel) { int run_level = i - last_non_zero - 1; - int rlevel = (slevel<<1)|!!run_level; + int rlevel = (slevel << 1) | !!run_level; put_bits(&ctx->m.pb, ctx->vlc_bits[rlevel], ctx->vlc_codes[rlevel]); if (run_level) - put_bits(&ctx->m.pb, ctx->run_bits[run_level], ctx->run_codes[run_level]); + put_bits(&ctx->m.pb, ctx->run_bits[run_level], + ctx->run_codes[run_level]); last_non_zero = i; } } put_bits(&ctx->m.pb, ctx->vlc_bits[0], ctx->vlc_codes[0]); // EOB } -static av_always_inline void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *block, int n, int qscale, int last_index) +static av_always_inline +void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *block, int n, + int qscale, int last_index) { const uint8_t *weight_matrix; int level; int i; - weight_matrix = (n&2) ? ctx->cid_table->chroma_weight : ctx->cid_table->luma_weight; + weight_matrix = (n & 2) ? ctx->cid_table->chroma_weight + : ctx->cid_table->luma_weight; for (i = 1; i <= last_index; i++) { int j = ctx->m.intra_scantable.permutated[i]; level = block[j]; if (level) { if (level < 0) { - level = (1-2*level) * qscale * weight_matrix[i]; + level = (1 - 2 * level) * qscale * weight_matrix[i]; if (ctx->cid_table->bit_depth == 10) { if (weight_matrix[i] != 8) level += 8; @@ -450,7 +507,7 @@ static av_always_inline void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *b } level = -level; } else { - level = (2*level+1) * qscale * weight_matrix[i]; + level = (2 * level + 1) * qscale * weight_matrix[i]; if (ctx->cid_table->bit_depth == 10) { if (weight_matrix[i] != 8) level += 8; @@ -475,7 +532,8 @@ static av_always_inline int dnxhd_ssd_block(int16_t *qblock, int16_t *block) return score; } -static av_always_inline int dnxhd_calc_ac_bits(DNXHDEncContext *ctx, int16_t *block, int last_index) +static av_always_inline +int dnxhd_calc_ac_bits(DNXHDEncContext *ctx, int16_t *block, int last_index) { int last_non_zero = 0; int bits = 0; @@ -485,54 +543,73 @@ static av_always_inline int dnxhd_calc_ac_bits(DNXHDEncContext *ctx, int16_t *bl level = block[j]; if (level) { int run_level = i - last_non_zero - 1; - bits += ctx->vlc_bits[(level<<1)|!!run_level]+ctx->run_bits[run_level]; + bits += ctx->vlc_bits[(level << 1) | + !!run_level] + ctx->run_bits[run_level]; last_non_zero = i; } } return bits; } -static av_always_inline void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y) +static av_always_inline +void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y) { const int bs = ctx->block_width_l2; const int bw = 1 << bs; - const uint8_t *ptr_y = ctx->thread[0]->src[0] + ((mb_y << 4) * ctx->m.linesize) + (mb_x << bs+1); - const uint8_t *ptr_u = ctx->thread[0]->src[1] + ((mb_y << 4) * ctx->m.uvlinesize) + (mb_x << bs); - const uint8_t *ptr_v = ctx->thread[0]->src[2] + ((mb_y << 4) * ctx->m.uvlinesize) + (mb_x << bs); - DSPContext *dsp = &ctx->m.dsp; + const uint8_t *ptr_y = ctx->thread[0]->src[0] + + ((mb_y << 4) * ctx->m.linesize) + (mb_x << bs + 1); + const uint8_t *ptr_u = ctx->thread[0]->src[1] + + ((mb_y << 4) * ctx->m.uvlinesize) + (mb_x << bs); + const uint8_t *ptr_v = ctx->thread[0]->src[2] + + ((mb_y << 4) * ctx->m.uvlinesize) + (mb_x << bs); + PixblockDSPContext *pdsp = &ctx->m.pdsp; - dsp->get_pixels(ctx->blocks[0], ptr_y, ctx->m.linesize); - dsp->get_pixels(ctx->blocks[1], ptr_y + bw, ctx->m.linesize); - dsp->get_pixels(ctx->blocks[2], ptr_u, ctx->m.uvlinesize); - dsp->get_pixels(ctx->blocks[3], ptr_v, ctx->m.uvlinesize); + pdsp->get_pixels(ctx->blocks[0], ptr_y, ctx->m.linesize); + pdsp->get_pixels(ctx->blocks[1], ptr_y + bw, ctx->m.linesize); + pdsp->get_pixels(ctx->blocks[2], ptr_u, ctx->m.uvlinesize); + pdsp->get_pixels(ctx->blocks[3], ptr_v, ctx->m.uvlinesize); - if (mb_y+1 == ctx->m.mb_height && ctx->m.avctx->height == 1080) { + if (mb_y + 1 == ctx->m.mb_height && ctx->m.avctx->height == 1080) { if (ctx->interlaced) { - ctx->get_pixels_8x4_sym(ctx->blocks[4], ptr_y + ctx->dct_y_offset, ctx->m.linesize); - ctx->get_pixels_8x4_sym(ctx->blocks[5], ptr_y + ctx->dct_y_offset + bw, ctx->m.linesize); - ctx->get_pixels_8x4_sym(ctx->blocks[6], ptr_u + ctx->dct_uv_offset, ctx->m.uvlinesize); - ctx->get_pixels_8x4_sym(ctx->blocks[7], ptr_v + ctx->dct_uv_offset, ctx->m.uvlinesize); + ctx->get_pixels_8x4_sym(ctx->blocks[4], + ptr_y + ctx->dct_y_offset, + ctx->m.linesize); + ctx->get_pixels_8x4_sym(ctx->blocks[5], + ptr_y + ctx->dct_y_offset + bw, + ctx->m.linesize); + ctx->get_pixels_8x4_sym(ctx->blocks[6], + ptr_u + ctx->dct_uv_offset, + ctx->m.uvlinesize); + ctx->get_pixels_8x4_sym(ctx->blocks[7], + ptr_v + ctx->dct_uv_offset, + ctx->m.uvlinesize); } else { - dsp->clear_block(ctx->blocks[4]); - dsp->clear_block(ctx->blocks[5]); - dsp->clear_block(ctx->blocks[6]); - dsp->clear_block(ctx->blocks[7]); + ctx->bdsp.clear_block(ctx->blocks[4]); + ctx->bdsp.clear_block(ctx->blocks[5]); + ctx->bdsp.clear_block(ctx->blocks[6]); + ctx->bdsp.clear_block(ctx->blocks[7]); } } else { - dsp->get_pixels(ctx->blocks[4], ptr_y + ctx->dct_y_offset, ctx->m.linesize); - dsp->get_pixels(ctx->blocks[5], ptr_y + ctx->dct_y_offset + bw, ctx->m.linesize); - dsp->get_pixels(ctx->blocks[6], ptr_u + ctx->dct_uv_offset, ctx->m.uvlinesize); - dsp->get_pixels(ctx->blocks[7], ptr_v + ctx->dct_uv_offset, ctx->m.uvlinesize); + pdsp->get_pixels(ctx->blocks[4], + ptr_y + ctx->dct_y_offset, ctx->m.linesize); + pdsp->get_pixels(ctx->blocks[5], + ptr_y + ctx->dct_y_offset + bw, ctx->m.linesize); + pdsp->get_pixels(ctx->blocks[6], + ptr_u + ctx->dct_uv_offset, ctx->m.uvlinesize); + pdsp->get_pixels(ctx->blocks[7], + ptr_v + ctx->dct_uv_offset, ctx->m.uvlinesize); } } -static av_always_inline int dnxhd_switch_matrix(DNXHDEncContext *ctx, int i) +static av_always_inline +int dnxhd_switch_matrix(DNXHDEncContext *ctx, int i) { const static uint8_t component[8]={0,0,1,2,0,0,1,2}; return component[i]; } -static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr) +static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, + int jobnr, int threadnr) { DNXHDEncContext *ctx = avctx->priv_data; int mb_y = jobnr, mb_x; @@ -558,13 +635,16 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, int jobnr, i int overflow, nbits, diff, last_index; int n = dnxhd_switch_matrix(ctx, i); - memcpy(block, src_block, 64*sizeof(*block)); - last_index = ctx->m.dct_quantize(&ctx->m, block, 4&(2*i), qscale, &overflow); - ac_bits += dnxhd_calc_ac_bits(ctx, block, last_index); + memcpy(block, src_block, 64 * sizeof(*block)); + last_index = ctx->m.dct_quantize(&ctx->m, block, 4 & (2*i), + qscale, &overflow); + ac_bits += dnxhd_calc_ac_bits(ctx, block, last_index); diff = block[0] - ctx->m.last_dc[n]; - if (diff < 0) nbits = av_log2_16bit(-2*diff); - else nbits = av_log2_16bit( 2*diff); + if (diff < 0) + nbits = av_log2_16bit(-2 * diff); + else + nbits = av_log2_16bit(2 * diff); av_assert1(nbits < ctx->cid_table->bit_depth + 4); dc_bits += ctx->cid_table->dc_bits[nbits] + nbits; @@ -573,22 +653,25 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, int jobnr, i if (avctx->mb_decision == FF_MB_DECISION_RD || !RC_VARIANCE) { dnxhd_unquantize_c(ctx, block, i, qscale, last_index); - ctx->m.dsp.idct(block); + ctx->m.idsp.idct(block); ssd += dnxhd_ssd_block(block, src_block); } } - ctx->mb_rc[qscale][mb].ssd = ssd; - ctx->mb_rc[qscale][mb].bits = ac_bits+dc_bits+12+8*ctx->vlc_bits[0]; + ctx->mb_rc[qscale][mb].ssd = ssd; + ctx->mb_rc[qscale][mb].bits = ac_bits + dc_bits + 12 + + 8 * ctx->vlc_bits[0]; } return 0; } -static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr) +static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg, + int jobnr, int threadnr) { DNXHDEncContext *ctx = avctx->priv_data; int mb_y = jobnr, mb_x; ctx = ctx->thread[threadnr]; - init_put_bits(&ctx->m.pb, (uint8_t *)arg + 640 + ctx->slice_offs[jobnr], ctx->slice_size[jobnr]); + init_put_bits(&ctx->m.pb, (uint8_t *)arg + 640 + ctx->slice_offs[jobnr], + ctx->slice_size[jobnr]); ctx->m.last_dc[0] = ctx->m.last_dc[1] = @@ -598,21 +681,22 @@ static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg, int jobnr, int int qscale = ctx->mb_qscale[mb]; int i; - put_bits(&ctx->m.pb, 12, qscale<<1); + put_bits(&ctx->m.pb, 12, qscale << 1); dnxhd_get_blocks(ctx, mb_x, mb_y); for (i = 0; i < 8; i++) { int16_t *block = ctx->blocks[i]; int overflow, n = dnxhd_switch_matrix(ctx, i); - int last_index = ctx->m.dct_quantize(&ctx->m, block, 4&(2*i), qscale, &overflow); - //START_TIMER; + int last_index = ctx->m.dct_quantize(&ctx->m, block, 4 & (2*i), + qscale, &overflow); + // START_TIMER; dnxhd_encode_block(ctx, block, last_index, n); - //STOP_TIMER("encode_block"); + // STOP_TIMER("encode_block"); } } - if (put_bits_count(&ctx->m.pb)&31) - put_bits(&ctx->m.pb, 32-(put_bits_count(&ctx->m.pb)&31), 0); + if (put_bits_count(&ctx->m.pb) & 31) + put_bits(&ctx->m.pb, 32 - (put_bits_count(&ctx->m.pb) & 31), 0); flush_put_bits(&ctx->m.pb); return 0; } @@ -629,14 +713,15 @@ static void dnxhd_setup_threads_slices(DNXHDEncContext *ctx) unsigned mb = mb_y * ctx->m.mb_width + mb_x; ctx->slice_size[mb_y] += ctx->mb_bits[mb]; } - ctx->slice_size[mb_y] = (ctx->slice_size[mb_y]+31)&~31; + ctx->slice_size[mb_y] = (ctx->slice_size[mb_y] + 31) & ~31; ctx->slice_size[mb_y] >>= 3; thread_size = ctx->slice_size[mb_y]; offset += thread_size; } } -static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr) +static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, + int jobnr, int threadnr) { DNXHDEncContext *ctx = avctx->priv_data; int mb_y = jobnr, mb_x, x, y; @@ -645,15 +730,15 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, int jobnr, int ctx = ctx->thread[threadnr]; if (ctx->cid_table->bit_depth == 8) { - uint8_t *pix = ctx->thread[0]->src[0] + ((mb_y<<4) * ctx->m.linesize); + uint8_t *pix = ctx->thread[0]->src[0] + ((mb_y << 4) * ctx->m.linesize); for (mb_x = 0; mb_x < ctx->m.mb_width; ++mb_x, pix += 16) { - unsigned mb = mb_y * ctx->m.mb_width + mb_x; + unsigned mb = mb_y * ctx->m.mb_width + mb_x; int sum; int varc; if (!partial_last_row && mb_x * 16 <= avctx->width - 16) { - sum = ctx->m.dsp.pix_sum(pix, ctx->m.linesize); - varc = ctx->m.dsp.pix_norm1(pix, ctx->m.linesize); + sum = ctx->m.mpvencdsp.pix_sum(pix, ctx->m.linesize); + varc = ctx->m.mpvencdsp.pix_norm1(pix, ctx->m.linesize); } else { int bw = FFMIN(avctx->width - 16 * mb_x, 16); int bh = FFMIN((avctx->height >> ctx->interlaced) - 16 * mb_y, 16); @@ -666,15 +751,16 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, int jobnr, int } } } - varc = (varc - (((unsigned)sum * sum) >> 8) + 128) >> 8; + varc = (varc - (((unsigned) sum * sum) >> 8) + 128) >> 8; ctx->mb_cmp[mb].value = varc; - ctx->mb_cmp[mb].mb = mb; + ctx->mb_cmp[mb].mb = mb; } } else { // 10-bit int const linesize = ctx->m.linesize >> 1; for (mb_x = 0; mb_x < ctx->m.mb_width; ++mb_x) { - uint16_t *pix = (uint16_t*)ctx->thread[0]->src[0] + ((mb_y << 4) * linesize) + (mb_x << 4); + uint16_t *pix = (uint16_t *)ctx->thread[0]->src[0] + + ((mb_y << 4) * linesize) + (mb_x << 4); unsigned mb = mb_y * ctx->m.mb_width + mb_x; int sum = 0; int sqsum = 0; @@ -684,8 +770,8 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, int jobnr, int for (i = 0; i < 16; ++i) { for (j = 0; j < 16; ++j) { // Turn 16-bit pixels into 10-bit ones. - int const sample = (unsigned)pix[j] >> 6; - sum += sample; + int const sample = (unsigned) pix[j] >> 6; + sum += sample; sqsum += sample * sample; // 2^10 * 2^10 * 16 * 16 = 2^28, which is less than INT_MAX } @@ -694,7 +780,7 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, int jobnr, int mean = sum >> 8; // 16*16 == 2^8 sqmean = sqsum >> 8; ctx->mb_cmp[mb].value = sqmean - mean * mean; - ctx->mb_cmp[mb].mb = mb; + ctx->mb_cmp[mb].mb = mb; } } return 0; @@ -708,14 +794,15 @@ static int dnxhd_encode_rdo(AVCodecContext *avctx, DNXHDEncContext *ctx) for (q = 1; q < avctx->qmax; q++) { ctx->qscale = q; - avctx->execute2(avctx, dnxhd_calc_bits_thread, NULL, NULL, ctx->m.mb_height); + avctx->execute2(avctx, dnxhd_calc_bits_thread, + NULL, NULL, ctx->m.mb_height); } - up_step = down_step = 2<lambda; + up_step = down_step = 2 << LAMBDA_FRAC_BITS; + lambda = ctx->lambda; for (;;) { int bits = 0; - int end = 0; + int end = 0; if (lambda == last_higher) { lambda++; end = 1; // need to set final qscales/bits @@ -724,25 +811,26 @@ static int dnxhd_encode_rdo(AVCodecContext *avctx, DNXHDEncContext *ctx) for (x = 0; x < ctx->m.mb_width; x++) { unsigned min = UINT_MAX; int qscale = 1; - int mb = y*ctx->m.mb_width+x; + int mb = y * ctx->m.mb_width + x; for (q = 1; q < avctx->qmax; q++) { - unsigned score = ctx->mb_rc[q][mb].bits*lambda+ - ((unsigned)ctx->mb_rc[q][mb].ssd<mb_rc[q][mb].bits * lambda + + ((unsigned) ctx->mb_rc[q][mb].ssd << LAMBDA_FRAC_BITS); if (score < min) { - min = score; + min = score; qscale = q; } } bits += ctx->mb_rc[qscale][mb].bits; ctx->mb_qscale[mb] = qscale; - ctx->mb_bits[mb] = ctx->mb_rc[qscale][mb].bits; + ctx->mb_bits[mb] = ctx->mb_rc[qscale][mb].bits; } - bits = (bits+31)&~31; // padding + bits = (bits + 31) & ~31; // padding if (bits > ctx->frame_bits) break; } - //av_dlog(ctx->m.avctx, "lambda %d, up %u, down %u, bits %d, frame %d\n", - // lambda, last_higher, last_lower, bits, ctx->frame_bits); + // av_dlog(ctx->m.avctx, + // "lambda %d, up %u, down %u, bits %d, frame %d\n", + // lambda, last_higher, last_lower, bits, ctx->frame_bits); if (end) { if (bits > ctx->frame_bits) return AVERROR(EINVAL); @@ -791,7 +879,8 @@ static int dnxhd_find_qscale(DNXHDEncContext *ctx) bits = 0; ctx->qscale = qscale; // XXX avoid recalculating bits - ctx->m.avctx->execute2(ctx->m.avctx, dnxhd_calc_bits_thread, NULL, NULL, ctx->m.mb_height); + ctx->m.avctx->execute2(ctx->m.avctx, dnxhd_calc_bits_thread, + NULL, NULL, ctx->m.mb_height); for (y = 0; y < ctx->m.mb_height; y++) { for (x = 0; x < ctx->m.mb_width; x++) bits += ctx->mb_rc[qscale][y*ctx->m.mb_width+x].bits; @@ -799,8 +888,10 @@ static int dnxhd_find_qscale(DNXHDEncContext *ctx) if (bits > ctx->frame_bits) break; } - //av_dlog(ctx->m.avctx, "%d, qscale %d, bits %d, frame %d, higher %d, lower %d\n", - // ctx->m.avctx->frame_number, qscale, bits, ctx->frame_bits, last_higher, last_lower); + // av_dlog(ctx->m.avctx, + // "%d, qscale %d, bits %d, frame %d, higher %d, lower %d\n", + // ctx->m.avctx->frame_number, qscale, bits, ctx->frame_bits, + // last_higher, last_lower); if (bits < ctx->frame_bits) { if (qscale == 1) return 1; @@ -810,7 +901,7 @@ static int dnxhd_find_qscale(DNXHDEncContext *ctx) } last_lower = FFMIN(qscale, last_lower); if (last_higher != 0) - qscale = (qscale+last_higher)>>1; + qscale = (qscale + last_higher) >> 1; else qscale -= down_step++; if (qscale < 1) @@ -821,7 +912,7 @@ static int dnxhd_find_qscale(DNXHDEncContext *ctx) break; last_higher = FFMAX(qscale, last_higher); if (last_lower != INT_MAX) - qscale = (qscale+last_lower)>>1; + qscale = (qscale + last_lower) >> 1; else qscale += up_step++; down_step = 1; @@ -841,11 +932,12 @@ static int dnxhd_find_qscale(DNXHDEncContext *ctx) static inline int get_bucket(int value, int shift) { value >>= shift; - value &= NBUCKETS - 1; + value &= NBUCKETS - 1; return NBUCKETS - 1 - value; } -static void radix_count(const RCCMPEntry *data, int size, int buckets[RADIX_PASSES][NBUCKETS]) +static void radix_count(const RCCMPEntry *data, int size, + int buckets[RADIX_PASSES][NBUCKETS]) { int i, j; memset(buckets, 0, sizeof(buckets[0][0]) * RADIX_PASSES * NBUCKETS); @@ -865,12 +957,13 @@ static void radix_count(const RCCMPEntry *data, int size, int buckets[RADIX_PASS } } -static void radix_sort_pass(RCCMPEntry *dst, const RCCMPEntry *data, int size, int buckets[NBUCKETS], int pass) +static void radix_sort_pass(RCCMPEntry *dst, const RCCMPEntry *data, + int size, int buckets[NBUCKETS], int pass) { int shift = pass * BUCKET_BITS; int i; for (i = 0; i < size; i++) { - int v = get_bucket(data[i].value, shift); + int v = get_bucket(data[i].value, shift); int pos = buckets[v]++; dst[pos] = data[i]; } @@ -879,7 +972,7 @@ static void radix_sort_pass(RCCMPEntry *dst, const RCCMPEntry *data, int size, i static void radix_sort(RCCMPEntry *data, int size) { int buckets[RADIX_PASSES][NBUCKETS]; - RCCMPEntry *tmp = av_malloc(sizeof(*tmp) * size); + RCCMPEntry *tmp = av_malloc_array(size, sizeof(*tmp)); radix_count(data, size, buckets); radix_sort_pass(tmp, data, size, buckets[0], 0); radix_sort_pass(data, tmp, size, buckets[1], 1); @@ -898,30 +991,35 @@ static int dnxhd_encode_fast(AVCodecContext *avctx, DNXHDEncContext *ctx) return ret; for (y = 0; y < ctx->m.mb_height; y++) { for (x = 0; x < ctx->m.mb_width; x++) { - int mb = y*ctx->m.mb_width+x; + int mb = y * ctx->m.mb_width + x; int delta_bits; ctx->mb_qscale[mb] = ctx->qscale; ctx->mb_bits[mb] = ctx->mb_rc[ctx->qscale][mb].bits; max_bits += ctx->mb_rc[ctx->qscale][mb].bits; if (!RC_VARIANCE) { - delta_bits = ctx->mb_rc[ctx->qscale][mb].bits-ctx->mb_rc[ctx->qscale+1][mb].bits; + delta_bits = ctx->mb_rc[ctx->qscale][mb].bits - + ctx->mb_rc[ctx->qscale + 1][mb].bits; ctx->mb_cmp[mb].mb = mb; - ctx->mb_cmp[mb].value = delta_bits ? - ((ctx->mb_rc[ctx->qscale][mb].ssd-ctx->mb_rc[ctx->qscale+1][mb].ssd)*100)/delta_bits - : INT_MIN; //avoid increasing qscale + ctx->mb_cmp[mb].value = + delta_bits ? ((ctx->mb_rc[ctx->qscale][mb].ssd - + ctx->mb_rc[ctx->qscale + 1][mb].ssd) * 100) / + delta_bits + : INT_MIN; // avoid increasing qscale } } - max_bits += 31; //worst padding + max_bits += 31; // worst padding } if (!ret) { if (RC_VARIANCE) - avctx->execute2(avctx, dnxhd_mb_var_thread, NULL, NULL, ctx->m.mb_height); + avctx->execute2(avctx, dnxhd_mb_var_thread, + NULL, NULL, ctx->m.mb_height); radix_sort(ctx->mb_cmp, ctx->m.mb_num); for (x = 0; x < ctx->m.mb_num && max_bits > ctx->frame_bits; x++) { int mb = ctx->mb_cmp[x].mb; - max_bits -= ctx->mb_rc[ctx->qscale][mb].bits - ctx->mb_rc[ctx->qscale+1][mb].bits; - ctx->mb_qscale[mb] = ctx->qscale+1; - ctx->mb_bits[mb] = ctx->mb_rc[ctx->qscale+1][mb].bits; + max_bits -= ctx->mb_rc[ctx->qscale][mb].bits - + ctx->mb_rc[ctx->qscale + 1][mb].bits; + ctx->mb_qscale[mb] = ctx->qscale + 1; + ctx->mb_bits[mb] = ctx->mb_rc[ctx->qscale + 1][mb].bits; } } return 0; @@ -956,7 +1054,7 @@ static int dnxhd_encode_picture(AVCodecContext *avctx, AVPacket *pkt, dnxhd_load_picture(ctx, frame); - encode_coding_unit: +encode_coding_unit: for (i = 0; i < 3; i++) { ctx->src[i] = frame->data[i]; if (ctx->interlaced && ctx->cur_field) @@ -987,14 +1085,15 @@ static int dnxhd_encode_picture(AVCodecContext *avctx, AVPacket *pkt, avctx->execute2(avctx, dnxhd_encode_thread, buf, NULL, ctx->m.mb_height); av_assert1(640 + offset + 4 <= ctx->cid_table->coding_unit_size); - memset(buf + 640 + offset, 0, ctx->cid_table->coding_unit_size - 4 - offset - 640); + memset(buf + 640 + offset, 0, + ctx->cid_table->coding_unit_size - 4 - offset - 640); AV_WB32(buf + ctx->cid_table->coding_unit_size - 4, 0x600DC0DE); // EOF if (ctx->interlaced && first_field) { first_field = 0; ctx->cur_field ^= 1; - buf += ctx->cid_table->coding_unit_size; + buf += ctx->cid_table->coding_unit_size; goto encode_coding_unit; } @@ -1008,11 +1107,11 @@ static int dnxhd_encode_picture(AVCodecContext *avctx, AVPacket *pkt, static av_cold int dnxhd_encode_end(AVCodecContext *avctx) { DNXHDEncContext *ctx = avctx->priv_data; - int max_level = 1<<(ctx->cid_table->bit_depth+2); + int max_level = 1 << (ctx->cid_table->bit_depth + 2); int i; - av_free(ctx->vlc_codes-max_level*2); - av_free(ctx->vlc_bits -max_level*2); + av_free(ctx->vlc_codes - max_level * 2); + av_free(ctx->vlc_bits - max_level * 2); av_freep(&ctx->run_codes); av_freep(&ctx->run_bits); @@ -1051,9 +1150,11 @@ AVCodec ff_dnxhd_encoder = { .encode2 = dnxhd_encode_picture, .close = dnxhd_encode_end, .capabilities = CODEC_CAP_SLICE_THREADS, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P, - AV_PIX_FMT_YUV422P10, - AV_PIX_FMT_NONE }, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_NONE + }, .priv_class = &dnxhd_class, .defaults = dnxhd_defaults, }; diff --git a/libavcodec/dnxhdenc.h b/libavcodec/dnxhdenc.h index 110b0ad9e..7ef0b9645 100644 --- a/libavcodec/dnxhdenc.h +++ b/libavcodec/dnxhdenc.h @@ -41,6 +41,7 @@ typedef struct RCEntry { typedef struct DNXHDEncContext { AVClass *class; + BlockDSPContext bdsp; MpegEncContext m; ///< Used for quantization dsp functions int cid; @@ -89,7 +90,8 @@ typedef struct DNXHDEncContext { RCCMPEntry *mb_cmp; RCEntry (*mb_rc)[8160]; - void (*get_pixels_8x4_sym)(int16_t * /*align 16*/, const uint8_t *, int); + void (*get_pixels_8x4_sym)(int16_t * /* align 16 */, + const uint8_t *, ptrdiff_t); } DNXHDEncContext; void ff_dnxhdenc_init_x86(DNXHDEncContext *ctx); diff --git a/libavcodec/dpx.c b/libavcodec/dpx.c index 5c3c3e81c..5f05cd81b 100644 --- a/libavcodec/dpx.c +++ b/libavcodec/dpx.c @@ -20,6 +20,7 @@ */ #include "libavutil/intreadwrite.h" +#include "libavutil/intfloat.h" #include "libavutil/imgutils.h" #include "bytestream.h" #include "avcodec.h" @@ -146,6 +147,16 @@ static int decode_frame(AVCodecContext *avctx, else avctx->sample_aspect_ratio = (AVRational){ 0, 1 }; + if (offset >= 1724 + 4) { + buf = avpkt->data + 1724; + i = read32(&buf, endian); + if(i) { + AVRational q = av_d2q(av_int2float(i), 4096); + if (q.num > 0 && q.den > 0) + avctx->time_base = av_inv_q(q); + } + } + switch (descriptor) { case 6: // Y elements = 1; @@ -244,6 +255,8 @@ static int decode_frame(AVCodecContext *avctx, return AVERROR_PATCHWELCOME; } + ff_set_sar(avctx, avctx->sample_aspect_ratio); + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; diff --git a/libavcodec/dpx_parser.c b/libavcodec/dpx_parser.c index 70baaf42c..dd2a335c6 100644 --- a/libavcodec/dpx_parser.c +++ b/libavcodec/dpx_parser.c @@ -48,7 +48,7 @@ static int dpx_parse(AVCodecParserContext *s, AVCodecContext *avctx, *poutbuf_size = 0; if (buf_size == 0) - return 0; + next = 0; if (!d->pc.frame_start_found) { for (; i < buf_size; i++) { @@ -57,6 +57,7 @@ static int dpx_parse(AVCodecParserContext *s, AVCodecContext *avctx, 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; } } @@ -67,33 +68,38 @@ static int dpx_parse(AVCodecParserContext *s, AVCodecContext *avctx, d->remaining_size -= i; if (d->remaining_size) goto flush; - next = i; } } for (;d->pc.frame_start_found && i < buf_size; i++) { d->pc.state = (d->pc.state << 8) | buf[i]; - if (d->index == 16) { + d->index++; + if (d->index == 17) { d->fsize = d->is_be ? d->pc.state : av_bswap32(d->pc.state); if (d->fsize <= 1664) { - d->index = d->pc.frame_start_found = 0; + d->pc.frame_start_found = 0; goto flush; } - d->index = 0; if (d->fsize > buf_size - i + 19) d->remaining_size = d->fsize - buf_size + i - 19; else - next = d->fsize + i - 19; + 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; + } } - d->index++; } flush: if (ff_combine_frame(&d->pc, next, &buf, &buf_size) < 0) return buf_size; - d->index = d->pc.frame_start_found = 0; + d->pc.frame_start_found = 0; *poutbuf = buf; *poutbuf_size = buf_size; diff --git a/libavcodec/dsd_tablegen.c b/libavcodec/dsd_tablegen.c new file mode 100644 index 000000000..dbeb9fe20 --- /dev/null +++ b/libavcodec/dsd_tablegen.c @@ -0,0 +1,38 @@ +/* + * Generate a header file for hardcoded DSD tables + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#define CONFIG_HARDCODED_TABLES 0 +#include "dsd_tablegen.h" +#include "tableprint.h" +#include + +int main(void) +{ + dsd_ctables_tableinit(); + + write_fileheader(); + + printf("static const double ctables[CTABLES][256] = {\n"); + write_float_2d_array(ctables, CTABLES, 256); + printf("};\n"); + + return 0; +} diff --git a/libavcodec/dsd_tablegen.h b/libavcodec/dsd_tablegen.h new file mode 100644 index 000000000..6afb4167d --- /dev/null +++ b/libavcodec/dsd_tablegen.h @@ -0,0 +1,95 @@ +/* + * Header file for hardcoded DSD tables + * based on BSD licensed dsd2pcm by Sebastian Gesemann + * Copyright (c) 2009, 2011 Sebastian Gesemann. All rights reserved. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DSD_TABLEGEN_H +#define AVCODEC_DSD_TABLEGEN_H + +#include +#include "libavutil/attributes.h" + +#define HTAPS 48 /** number of FIR constants */ +#define CTABLES ((HTAPS + 7) / 8) /** number of "8 MACs" lookup tables */ + +#if CONFIG_HARDCODED_TABLES +#define dsd_ctables_tableinit() +#include "libavcodec/dsd_tables.h" +#else +#include "libavutil/common.h" + +/* + * Properties of this 96-tap lowpass filter when applied on a signal + * with sampling rate of 44100*64 Hz: + * + * () has a delay of 17 microseconds. + * + * () flat response up to 48 kHz + * + * () if you downsample afterwards by a factor of 8, the + * spectrum below 70 kHz is practically alias-free. + * + * () stopband rejection is about 160 dB + * + * The coefficient tables ("ctables") take only 6 Kibi Bytes and + * should fit into a modern processor's fast cache. + */ + +/** + * The 2nd half (48 coeffs) of a 96-tap symmetric lowpass filter + */ +static const double htaps[HTAPS] = { + 0.09950731974056658, 0.09562845727714668, 0.08819647126516944, + 0.07782552527068175, 0.06534876523171299, 0.05172629311427257, + 0.0379429484910187, 0.02490921351762261, 0.0133774746265897, + 0.003883043418804416, -0.003284703416210726, -0.008080250212687497, + -0.01067241812471033, -0.01139427235000863, -0.0106813877974587, + -0.009007905078766049, -0.006828859761015335, -0.004535184322001496, + -0.002425035959059578, -0.0006922187080790708, 0.0005700762133516592, + 0.001353838005269448, 0.001713709169690937, 0.001742046839472948, + 0.001545601648013235, 0.001226696225277855, 0.0008704322683580222, + 0.0005381636200535649, 0.000266446345425276, 7.002968738383528e-05, + -5.279407053811266e-05, -0.0001140625650874684, -0.0001304796361231895, + -0.0001189970287491285, -9.396247155265073e-05, -6.577634378272832e-05, + -4.07492895872535e-05, -2.17407957554587e-05, -9.163058931391722e-06, + -2.017460145032201e-06, 1.249721855219005e-06, 2.166655190537392e-06, + 1.930520892991082e-06, 1.319400334374195e-06, 7.410039764949091e-07, + 3.423230509967409e-07, 1.244182214744588e-07, 3.130441005359396e-08 +}; + +static float ctables[CTABLES][256]; + +static av_cold void dsd_ctables_tableinit(void) +{ + int t, e, m, k; + double acc; + for (t = 0; t < CTABLES; ++t) { + k = FFMIN(HTAPS - t * 8, 8); + for (e = 0; e < 256; ++e) { + acc = 0.0; + for (m = 0; m < k; ++m) + acc += (((e >> (7 - m)) & 1) * 2 - 1) * htaps[t * 8 + m]; + ctables[CTABLES - 1 - t][e] = (float)acc; + } + } +} +#endif /* CONFIG_HARDCODED_TABLES */ + +#endif /* AVCODEC_DSD_TABLEGEN_H */ diff --git a/libavcodec/dsddec.c b/libavcodec/dsddec.c new file mode 100644 index 000000000..f1dfd4b23 --- /dev/null +++ b/libavcodec/dsddec.c @@ -0,0 +1,167 @@ +/* + * Direct Stream Digital (DSD) decoder + * based on BSD licensed dsd2pcm by Sebastian Gesemann + * Copyright (c) 2009, 2011 Sebastian Gesemann. All rights reserved. + * Copyright (c) 2014 Peter Ross + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Direct Stream Digital (DSD) decoder + */ + +#include "libavcodec/internal.h" +#include "libavcodec/mathops.h" +#include "avcodec.h" +#include "dsd_tablegen.h" + +#define FIFOSIZE 16 /** must be a power of two */ +#define FIFOMASK (FIFOSIZE - 1) /** bit mask for FIFO offsets */ + +#if FIFOSIZE * 8 < HTAPS * 2 +#error "FIFOSIZE too small" +#endif + +/** + * Per-channel buffer + */ +typedef struct { + unsigned char buf[FIFOSIZE]; + unsigned pos; +} DSDContext; + +static void dsd2pcm_translate(DSDContext* s, size_t samples, int lsbf, + const unsigned char *src, ptrdiff_t src_stride, + float *dst, ptrdiff_t dst_stride) +{ + unsigned pos, i; + unsigned char* p; + double sum; + + pos = s->pos; + + while (samples-- > 0) { + s->buf[pos] = lsbf ? ff_reverse[*src] : *src; + src += src_stride; + + p = s->buf + ((pos - CTABLES) & FIFOMASK); + *p = ff_reverse[*p]; + + sum = 0.0; + for (i = 0; i < CTABLES; i++) { + unsigned char a = s->buf[(pos - i) & FIFOMASK]; + unsigned char b = s->buf[(pos - (CTABLES*2 - 1) + i) & FIFOMASK]; + sum += ctables[i][a] + ctables[i][b]; + } + + *dst = (float)sum; + dst += dst_stride; + + pos = (pos + 1) & FIFOMASK; + } + + s->pos = pos; +} + +static av_cold void init_static_data(void) +{ + static int done = 0; + if (done) + return; + dsd_ctables_tableinit(); + done = 1; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + DSDContext * s; + int i; + + init_static_data(); + + s = av_malloc_array(sizeof(DSDContext), avctx->channels); + if (!s) + return AVERROR(ENOMEM); + + for (i = 0; i < avctx->channels; i++) { + s[i].pos = 0; + memset(s[i].buf, 0x69, sizeof(s[i].buf)); + + /* 0x69 = 01101001 + * This pattern "on repeat" makes a low energy 352.8 kHz tone + * and a high energy 1.0584 MHz tone which should be filtered + * out completely by any playback system --> silence + */ + } + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + avctx->priv_data = s; + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + DSDContext * s = avctx->priv_data; + AVFrame *frame = data; + int ret, i; + int lsbf = avctx->codec_id == AV_CODEC_ID_DSD_LSBF || avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR; + int src_next; + int src_stride; + + frame->nb_samples = avpkt->size / avctx->channels; + + if (avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR || avctx->codec_id == AV_CODEC_ID_DSD_MSBF_PLANAR) { + src_next = frame->nb_samples; + src_stride = 1; + } else { + src_next = 1; + src_stride = avctx->channels; + } + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (i = 0; i < avctx->channels; i++) { + float * dst = ((float **)frame->extended_data)[i]; + dsd2pcm_translate(&s[i], frame->nb_samples, lsbf, + avpkt->data + i * src_next, src_stride, + dst, 1); + } + + *got_frame_ptr = 1; + return frame->nb_samples * avctx->channels; +} + +#define DSD_DECODER(id_, name_, long_name_) \ +AVCodec ff_##name_##_decoder = { \ + .name = #name_, \ + .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ + .type = AVMEDIA_TYPE_AUDIO, \ + .id = AV_CODEC_ID_##id_, \ + .init = decode_init, \ + .decode = decode_frame, \ + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, \ + AV_SAMPLE_FMT_NONE }, \ +}; + +DSD_DECODER(DSD_LSBF, dsd_lsbf, "DSD (Direct Stream Digital), least significant bit first") +DSD_DECODER(DSD_MSBF, dsd_msbf, "DSD (Direct Stream Digital), most significant bit first") +DSD_DECODER(DSD_MSBF_PLANAR, dsd_msbf_planar, "DSD (Direct Stream Digital), most significant bit first, planar") +DSD_DECODER(DSD_LSBF_PLANAR, dsd_lsbf_planar, "DSD (Direct Stream Digital), least significant bit first, planar") diff --git a/libavcodec/dsicinaudio.c b/libavcodec/dsicinaudio.c new file mode 100644 index 000000000..b336d2c58 --- /dev/null +++ b/libavcodec/dsicinaudio.c @@ -0,0 +1,133 @@ +/* + * Delphine Software International CIN audio decoder + * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Delphine Software International CIN audio decoder + */ + +#include "libavutil/channel_layout.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "mathops.h" + +typedef struct CinAudioContext { + int initial_decode_frame; + int delta; +} CinAudioContext; + + +/* table defining a geometric sequence with multiplier = 32767 ^ (1 / 128) */ +static const int16_t cinaudio_delta16_table[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -30210, -27853, -25680, -23677, -21829, + -20126, -18556, -17108, -15774, -14543, -13408, -12362, -11398, + -10508, -9689, -8933, -8236, -7593, -7001, -6455, -5951, + -5487, -5059, -4664, -4300, -3964, -3655, -3370, -3107, + -2865, -2641, -2435, -2245, -2070, -1908, -1759, -1622, + -1495, -1379, -1271, -1172, -1080, -996, -918, -847, + -781, -720, -663, -612, -564, -520, -479, -442, + -407, -376, -346, -319, -294, -271, -250, -230, + -212, -196, -181, -166, -153, -141, -130, -120, + -111, -102, -94, -87, -80, -74, -68, -62, + -58, -53, -49, -45, -41, -38, -35, -32, + -30, -27, -25, -23, -21, -20, -18, -17, + -15, -14, -13, -12, -11, -10, -9, -8, + -7, -6, -5, -4, -3, -2, -1, 0, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 17, 18, 20, 21, 23, 25, 27, 30, + 32, 35, 38, 41, 45, 49, 53, 58, + 62, 68, 74, 80, 87, 94, 102, 111, + 120, 130, 141, 153, 166, 181, 196, 212, + 230, 250, 271, 294, 319, 346, 376, 407, + 442, 479, 520, 564, 612, 663, 720, 781, + 847, 918, 996, 1080, 1172, 1271, 1379, 1495, + 1622, 1759, 1908, 2070, 2245, 2435, 2641, 2865, + 3107, 3370, 3655, 3964, 4300, 4664, 5059, 5487, + 5951, 6455, 7001, 7593, 8236, 8933, 9689, 10508, + 11398, 12362, 13408, 14543, 15774, 17108, 18556, 20126, + 21829, 23677, 25680, 27853, 30210, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static av_cold int cinaudio_decode_init(AVCodecContext *avctx) +{ + CinAudioContext *cin = avctx->priv_data; + + cin->initial_decode_frame = 1; + cin->delta = 0; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + + return 0; +} + +static int cinaudio_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + CinAudioContext *cin = avctx->priv_data; + const uint8_t *buf_end = buf + avpkt->size; + int16_t *samples; + int delta, ret; + + /* get output buffer */ + frame->nb_samples = avpkt->size - cin->initial_decode_frame; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (int16_t *)frame->data[0]; + + delta = cin->delta; + if (cin->initial_decode_frame) { + cin->initial_decode_frame = 0; + delta = sign_extend(AV_RL16(buf), 16); + buf += 2; + *samples++ = delta; + } + while (buf < buf_end) { + delta += cinaudio_delta16_table[*buf++]; + delta = av_clip_int16(delta); + *samples++ = delta; + } + cin->delta = delta; + + *got_frame_ptr = 1; + + return avpkt->size; +} + +AVCodec ff_dsicinaudio_decoder = { + .name = "dsicinaudio", + .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_DSICINAUDIO, + .priv_data_size = sizeof(CinAudioContext), + .init = cinaudio_decode_init, + .decode = cinaudio_decode_frame, + .capabilities = CODEC_CAP_DR1, +}; diff --git a/libavcodec/dsicinav.c b/libavcodec/dsicinvideo.c similarity index 69% rename from libavcodec/dsicinav.c rename to libavcodec/dsicinvideo.c index 2d06ad8c1..48fb635c6 100644 --- a/libavcodec/dsicinav.c +++ b/libavcodec/dsicinvideo.c @@ -1,5 +1,5 @@ /* - * Delphine Software International CIN Audio/Video Decoders + * Delphine Software International CIN video decoder * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net) * * This file is part of FFmpeg. @@ -21,15 +21,12 @@ /** * @file - * Delphine Software International CIN audio/video decoders + * Delphine Software International CIN video decoder */ -#include "libavutil/channel_layout.h" #include "avcodec.h" #include "bytestream.h" #include "internal.h" -#include "mathops.h" - typedef enum CinVideoBitmapIndex { CIN_CUR_BMP = 0, /* current */ @@ -45,48 +42,6 @@ typedef struct CinVideoContext { uint8_t *bitmap_table[3]; } CinVideoContext; -typedef struct CinAudioContext { - int initial_decode_frame; - int delta; -} CinAudioContext; - - -/* table defining a geometric sequence with multiplier = 32767 ^ (1 / 128) */ -static const int16_t cinaudio_delta16_table[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -30210, -27853, -25680, -23677, -21829, - -20126, -18556, -17108, -15774, -14543, -13408, -12362, -11398, - -10508, -9689, -8933, -8236, -7593, -7001, -6455, -5951, - -5487, -5059, -4664, -4300, -3964, -3655, -3370, -3107, - -2865, -2641, -2435, -2245, -2070, -1908, -1759, -1622, - -1495, -1379, -1271, -1172, -1080, -996, -918, -847, - -781, -720, -663, -612, -564, -520, -479, -442, - -407, -376, -346, -319, -294, -271, -250, -230, - -212, -196, -181, -166, -153, -141, -130, -120, - -111, -102, -94, -87, -80, -74, -68, -62, - -58, -53, -49, -45, -41, -38, -35, -32, - -30, -27, -25, -23, -21, -20, -18, -17, - -15, -14, -13, -12, -11, -10, -9, -8, - -7, -6, -5, -4, -3, -2, -1, 0, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 17, 18, 20, 21, 23, 25, 27, 30, - 32, 35, 38, 41, 45, 49, 53, 58, - 62, 68, 74, 80, 87, 94, 102, 111, - 120, 130, 141, 153, 166, 181, 196, 212, - 230, 250, 271, 294, 319, 346, 376, 407, - 442, 479, 520, 564, 612, 663, 720, 781, - 847, 918, 996, 1080, 1172, 1271, 1379, 1495, - 1622, 1759, 1908, 2070, 2245, 2435, 2641, 2865, - 3107, 3370, 3655, 3964, 4300, 4664, 5059, 5487, - 5951, 6455, 7001, 7593, 8236, 8933, 9689, 10508, - 11398, 12362, 13408, 14543, 15774, 17108, 18556, 20126, - 21829, 23677, 25680, 27853, 30210, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - static av_cold void destroy_buffers(CinVideoContext *cin) { int i; @@ -349,54 +304,6 @@ static av_cold int cinvideo_decode_end(AVCodecContext *avctx) return 0; } -static av_cold int cinaudio_decode_init(AVCodecContext *avctx) -{ - CinAudioContext *cin = avctx->priv_data; - - cin->initial_decode_frame = 1; - cin->delta = 0; - avctx->sample_fmt = AV_SAMPLE_FMT_S16; - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; - - return 0; -} - -static int cinaudio_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame_ptr, AVPacket *avpkt) -{ - AVFrame *frame = data; - const uint8_t *buf = avpkt->data; - CinAudioContext *cin = avctx->priv_data; - const uint8_t *buf_end = buf + avpkt->size; - int16_t *samples; - int delta, ret; - - /* get output buffer */ - frame->nb_samples = avpkt->size - cin->initial_decode_frame; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; - samples = (int16_t *)frame->data[0]; - - delta = cin->delta; - if (cin->initial_decode_frame) { - cin->initial_decode_frame = 0; - delta = sign_extend(AV_RL16(buf), 16); - buf += 2; - *samples++ = delta; - } - while (buf < buf_end) { - delta += cinaudio_delta16_table[*buf++]; - delta = av_clip_int16(delta); - *samples++ = delta; - } - cin->delta = delta; - - *got_frame_ptr = 1; - - return avpkt->size; -} - AVCodec ff_dsicinvideo_decoder = { .name = "dsicinvideo", .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN video"), @@ -408,14 +315,3 @@ AVCodec ff_dsicinvideo_decoder = { .decode = cinvideo_decode_frame, .capabilities = CODEC_CAP_DR1, }; - -AVCodec ff_dsicinaudio_decoder = { - .name = "dsicinaudio", - .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_DSICINAUDIO, - .priv_data_size = sizeof(CinAudioContext), - .init = cinaudio_decode_init, - .decode = cinaudio_decode_frame, - .capabilities = CODEC_CAP_DR1, -}; diff --git a/libavcodec/dsputil.c b/libavcodec/dsputil.c index 0e9e34798..315e85317 100644 --- a/libavcodec/dsputil.c +++ b/libavcodec/dsputil.c @@ -3,8 +3,6 @@ * Copyright (c) 2000, 2001 Fabrice Bellard * Copyright (c) 2002-2004 Michael Niedermayer * - * gmc & q-pel & 32/64 bit based MC by Michael Niedermayer - * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -28,290 +26,71 @@ */ #include "libavutil/attributes.h" -#include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "avcodec.h" #include "copy_block.h" -#include "dct.h" #include "dsputil.h" #include "simple_idct.h" -#include "faandct.h" -#include "faanidct.h" -#include "imgconvert.h" -#include "mathops.h" #include "mpegvideo.h" #include "config.h" -#include "diracdsp.h" -uint32_t ff_squareTbl[512] = {0, }; +uint32_t ff_square_tab[512] = { 0, }; -#define BIT_DEPTH 16 -#include "dsputil_template.c" -#undef BIT_DEPTH - -#define BIT_DEPTH 8 -#include "dsputil_template.c" - -// 0x7f7f7f7f or 0x7f7f7f7f7f7f7f7f or whatever, depending on the cpu's native arithmetic size -#define pb_7f (~0UL/255 * 0x7f) -#define pb_80 (~0UL/255 * 0x80) - -/* Specific zigzag scan for 248 idct. NOTE that unlike the - specification, we interleave the fields */ -const uint8_t ff_zigzag248_direct[64] = { - 0, 8, 1, 9, 16, 24, 2, 10, - 17, 25, 32, 40, 48, 56, 33, 41, - 18, 26, 3, 11, 4, 12, 19, 27, - 34, 42, 49, 57, 50, 58, 35, 43, - 20, 28, 5, 13, 6, 14, 21, 29, - 36, 44, 51, 59, 52, 60, 37, 45, - 22, 30, 7, 15, 23, 31, 38, 46, - 53, 61, 54, 62, 39, 47, 55, 63, -}; - -const uint8_t ff_alternate_horizontal_scan[64] = { - 0, 1, 2, 3, 8, 9, 16, 17, - 10, 11, 4, 5, 6, 7, 15, 14, - 13, 12, 19, 18, 24, 25, 32, 33, - 26, 27, 20, 21, 22, 23, 28, 29, - 30, 31, 34, 35, 40, 41, 48, 49, - 42, 43, 36, 37, 38, 39, 44, 45, - 46, 47, 50, 51, 56, 57, 58, 59, - 52, 53, 54, 55, 60, 61, 62, 63, -}; - -const uint8_t ff_alternate_vertical_scan[64] = { - 0, 8, 16, 24, 1, 9, 2, 10, - 17, 25, 32, 40, 48, 56, 57, 49, - 41, 33, 26, 18, 3, 11, 4, 12, - 19, 27, 34, 42, 50, 58, 35, 43, - 51, 59, 20, 28, 5, 13, 6, 14, - 21, 29, 36, 44, 52, 60, 37, 45, - 53, 61, 22, 30, 7, 15, 23, 31, - 38, 46, 54, 62, 39, 47, 55, 63, -}; - -/* Input permutation for the simple_idct_mmx */ -static const uint8_t simple_mmx_permutation[64]={ - 0x00, 0x08, 0x04, 0x09, 0x01, 0x0C, 0x05, 0x0D, - 0x10, 0x18, 0x14, 0x19, 0x11, 0x1C, 0x15, 0x1D, - 0x20, 0x28, 0x24, 0x29, 0x21, 0x2C, 0x25, 0x2D, - 0x12, 0x1A, 0x16, 0x1B, 0x13, 0x1E, 0x17, 0x1F, - 0x02, 0x0A, 0x06, 0x0B, 0x03, 0x0E, 0x07, 0x0F, - 0x30, 0x38, 0x34, 0x39, 0x31, 0x3C, 0x35, 0x3D, - 0x22, 0x2A, 0x26, 0x2B, 0x23, 0x2E, 0x27, 0x2F, - 0x32, 0x3A, 0x36, 0x3B, 0x33, 0x3E, 0x37, 0x3F, -}; - -static const uint8_t idct_sse2_row_perm[8] = {0, 4, 1, 5, 2, 6, 3, 7}; - -av_cold void ff_init_scantable(uint8_t *permutation, ScanTable *st, - const uint8_t *src_scantable) +static int sse4_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h) { - int i; - int end; + int s = 0, i; + uint32_t *sq = ff_square_tab + 256; - st->scantable= src_scantable; - - for(i=0; i<64; i++){ - int j; - j = src_scantable[i]; - st->permutated[i] = permutation[j]; - } - - end=-1; - for(i=0; i<64; i++){ - int j; - j = st->permutated[i]; - if(j>end) end=j; - st->raster_end[i]= end; - } -} - -av_cold void ff_init_scantable_permutation(uint8_t *idct_permutation, - int idct_permutation_type) -{ - int i; - - switch(idct_permutation_type){ - case FF_NO_IDCT_PERM: - for(i=0; i<64; i++) - idct_permutation[i]= i; - break; - case FF_LIBMPEG2_IDCT_PERM: - for(i=0; i<64; i++) - idct_permutation[i]= (i & 0x38) | ((i & 6) >> 1) | ((i & 1) << 2); - break; - case FF_SIMPLE_IDCT_PERM: - for(i=0; i<64; i++) - idct_permutation[i]= simple_mmx_permutation[i]; - break; - case FF_TRANSPOSE_IDCT_PERM: - for(i=0; i<64; i++) - idct_permutation[i]= ((i&7)<<3) | (i>>3); - break; - case FF_PARTTRANS_IDCT_PERM: - for(i=0; i<64; i++) - idct_permutation[i]= (i&0x24) | ((i&3)<<3) | ((i>>3)&3); - break; - case FF_SSE2_IDCT_PERM: - for(i=0; i<64; i++) - idct_permutation[i]= (i&0x38) | idct_sse2_row_perm[i&7]; - break; - default: - av_log(NULL, AV_LOG_ERROR, "Internal error, IDCT permutation not set\n"); - } -} - -static int pix_sum_c(uint8_t * pix, int line_size) -{ - int s, i, j; - - s = 0; - for (i = 0; i < 16; i++) { - for (j = 0; j < 16; j += 8) { - s += pix[0]; - s += pix[1]; - s += pix[2]; - s += pix[3]; - s += pix[4]; - s += pix[5]; - s += pix[6]; - s += pix[7]; - pix += 8; - } - pix += line_size - 16; - } - return s; -} - -static int pix_norm1_c(uint8_t * pix, int line_size) -{ - int s, i, j; - uint32_t *sq = ff_squareTbl + 256; - - s = 0; - for (i = 0; i < 16; i++) { - for (j = 0; j < 16; j += 8) { -#if 0 - s += sq[pix[0]]; - s += sq[pix[1]]; - s += sq[pix[2]]; - s += sq[pix[3]]; - s += sq[pix[4]]; - s += sq[pix[5]]; - s += sq[pix[6]]; - s += sq[pix[7]]; -#else -#if HAVE_FAST_64BIT - register uint64_t x=*(uint64_t*)pix; - s += sq[x&0xff]; - s += sq[(x>>8)&0xff]; - s += sq[(x>>16)&0xff]; - s += sq[(x>>24)&0xff]; - s += sq[(x>>32)&0xff]; - s += sq[(x>>40)&0xff]; - s += sq[(x>>48)&0xff]; - s += sq[(x>>56)&0xff]; -#else - register uint32_t x=*(uint32_t*)pix; - s += sq[x&0xff]; - s += sq[(x>>8)&0xff]; - s += sq[(x>>16)&0xff]; - s += sq[(x>>24)&0xff]; - x=*(uint32_t*)(pix+4); - s += sq[x&0xff]; - s += sq[(x>>8)&0xff]; - s += sq[(x>>16)&0xff]; - s += sq[(x>>24)&0xff]; -#endif -#endif - pix += 8; - } - pix += line_size - 16; - } - return s; -} - -static void bswap_buf(uint32_t *dst, const uint32_t *src, int w){ - int i; - - for(i=0; i+8<=w; i+=8){ - dst[i+0]= av_bswap32(src[i+0]); - dst[i+1]= av_bswap32(src[i+1]); - dst[i+2]= av_bswap32(src[i+2]); - dst[i+3]= av_bswap32(src[i+3]); - dst[i+4]= av_bswap32(src[i+4]); - dst[i+5]= av_bswap32(src[i+5]); - dst[i+6]= av_bswap32(src[i+6]); - dst[i+7]= av_bswap32(src[i+7]); - } - for(;i 127) - *pixels = 255; - else - *pixels = (uint8_t)(*block + 128); - block++; - pixels++; - } - pixels += (line_size - 8); - } -} - -static void add_pixels8_c(uint8_t *av_restrict pixels, - int16_t *block, - int line_size) -{ - int i; - - for(i=0;i<8;i++) { - pixels[0] += block[0]; - pixels[1] += block[1]; - pixels[2] += block[2]; - pixels[3] += block[3]; - pixels[4] += block[4]; - pixels[5] += block[5]; - pixels[6] += block[6]; - pixels[7] += block[7]; - pixels += line_size; - block += 8; - } -} - -static void add_pixels_clamped_c(const int16_t *block, uint8_t *av_restrict pixels, - int line_size) -{ - int i; - - /* read the pixels */ - for(i=0;i<8;i++) { - pixels[0] = av_clip_uint8(pixels[0] + block[0]); - pixels[1] = av_clip_uint8(pixels[1] + block[1]); - pixels[2] = av_clip_uint8(pixels[2] + block[2]); - pixels[3] = av_clip_uint8(pixels[3] + block[3]); - pixels[4] = av_clip_uint8(pixels[4] + block[4]); - pixels[5] = av_clip_uint8(pixels[5] + block[5]); - pixels[6] = av_clip_uint8(pixels[6] + block[6]); - pixels[7] = av_clip_uint8(pixels[7] + block[7]); - pixels += line_size; - block += 8; - } -} - -static void add_pixels_clamped4_c(const int16_t *block, uint8_t *av_restrict pixels, - int line_size) -{ - int i; - - /* read the pixels */ - for(i=0;i<4;i++) { - pixels[0] = av_clip_uint8(pixels[0] + block[0]); - pixels[1] = av_clip_uint8(pixels[1] + block[1]); - pixels[2] = av_clip_uint8(pixels[2] + block[2]); - pixels[3] = av_clip_uint8(pixels[3] + block[3]); - pixels += line_size; - block += 8; - } -} - -static void add_pixels_clamped2_c(const int16_t *block, uint8_t *av_restrict pixels, - int line_size) -{ - int i; - - /* read the pixels */ - for(i=0;i<2;i++) { - pixels[0] = av_clip_uint8(pixels[0] + block[0]); - pixels[1] = av_clip_uint8(pixels[1] + block[1]); - pixels += line_size; - block += 8; - } -} - static int sum_abs_dctelem_c(int16_t *block) { - int sum=0, i; - for(i=0; i<64; i++) - sum+= FFABS(block[i]); + int sum = 0, i; + + for (i = 0; i < 64; i++) + sum += FFABS(block[i]); return sum; } -static void fill_block16_c(uint8_t *block, uint8_t value, int line_size, int h) +#define avg2(a, b) ((a + b + 1) >> 1) +#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) { - int i; + int s = 0, i; for (i = 0; i < h; i++) { - memset(block, value, 16); - block += line_size; + s += abs(pix1[0] - pix2[0]); + s += abs(pix1[1] - pix2[1]); + s += abs(pix1[2] - pix2[2]); + s += abs(pix1[3] - pix2[3]); + s += abs(pix1[4] - pix2[4]); + s += abs(pix1[5] - pix2[5]); + s += abs(pix1[6] - pix2[6]); + s += abs(pix1[7] - pix2[7]); + s += abs(pix1[8] - pix2[8]); + s += abs(pix1[9] - pix2[9]); + s += abs(pix1[10] - pix2[10]); + s += abs(pix1[11] - pix2[11]); + s += abs(pix1[12] - pix2[12]); + s += abs(pix1[13] - pix2[13]); + s += abs(pix1[14] - pix2[14]); + s += abs(pix1[15] - pix2[15]); + pix1 += line_size; + pix2 += line_size; } + return s; } -static void fill_block8_c(uint8_t *block, uint8_t value, int line_size, int h) +static int pix_abs16_x2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h) { - int i; + int s = 0, i; for (i = 0; i < h; i++) { - memset(block, value, 8); - block += line_size; - } -} - -#define avg2(a,b) ((a+b+1)>>1) -#define avg4(a,b,c,d) ((a+b+c+d+2)>>2) - -static void gmc1_c(uint8_t *dst, uint8_t *src, int stride, int h, int x16, int y16, int rounder) -{ - const int A=(16-x16)*(16-y16); - const int B=( x16)*(16-y16); - const int C=(16-x16)*( y16); - const int D=( x16)*( y16); - int i; - - for(i=0; i>8; - dst[1]= (A*src[1] + B*src[2] + C*src[stride+1] + D*src[stride+2] + rounder)>>8; - dst[2]= (A*src[2] + B*src[3] + C*src[stride+2] + D*src[stride+3] + rounder)>>8; - dst[3]= (A*src[3] + B*src[4] + C*src[stride+3] + D*src[stride+4] + rounder)>>8; - dst[4]= (A*src[4] + B*src[5] + C*src[stride+4] + D*src[stride+5] + rounder)>>8; - dst[5]= (A*src[5] + B*src[6] + C*src[stride+5] + D*src[stride+6] + rounder)>>8; - dst[6]= (A*src[6] + B*src[7] + C*src[stride+6] + D*src[stride+7] + rounder)>>8; - dst[7]= (A*src[7] + B*src[8] + C*src[stride+7] + D*src[stride+8] + rounder)>>8; - dst+= stride; - src+= stride; - } -} - -void ff_gmc_c(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int oy, - int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height) -{ - int y, vx, vy; - const int s= 1<>16; - src_y= vy>>16; - frac_x= src_x&(s-1); - frac_y= src_y&(s-1); - src_x>>=shift; - src_y>>=shift; - - if((unsigned)src_x < width){ - if((unsigned)src_y < height){ - index= src_x + src_y*stride; - dst[y*stride + x]= ( ( src[index ]*(s-frac_x) - + src[index +1]* frac_x )*(s-frac_y) - + ( src[index+stride ]*(s-frac_x) - + src[index+stride+1]* frac_x )* frac_y - + r)>>(shift*2); - }else{ - index= src_x + av_clip(src_y, 0, height)*stride; - dst[y*stride + x]= ( ( src[index ]*(s-frac_x) - + src[index +1]* frac_x )*s - + r)>>(shift*2); - } - }else{ - if((unsigned)src_y < height){ - index= av_clip(src_x, 0, width) + src_y*stride; - dst[y*stride + x]= ( ( src[index ]*(s-frac_y) - + src[index+stride ]* frac_y )*s - + r)>>(shift*2); - }else{ - index= av_clip(src_x, 0, width) + av_clip(src_y, 0, height)*stride; - dst[y*stride + x]= src[index ]; - } - } - - vx+= dxx; - vy+= dyx; - } - ox += dxy; - oy += dyy; - } -} - -static inline void put_tpel_pixels_mc00_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - switch(width){ - case 2: put_pixels2_8_c (dst, src, stride, height); break; - case 4: put_pixels4_8_c (dst, src, stride, height); break; - case 8: put_pixels8_8_c (dst, src, stride, height); break; - case 16:put_pixels16_8_c(dst, src, stride, height); break; - } -} - -static inline void put_tpel_pixels_mc10_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (683*(2*src[j] + src[j+1] + 1)) >> 11; - } - src += stride; - dst += stride; - } -} - -static inline void put_tpel_pixels_mc20_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (683*(src[j] + 2*src[j+1] + 1)) >> 11; - } - src += stride; - dst += stride; - } -} - -static inline void put_tpel_pixels_mc01_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (683*(2*src[j] + src[j+stride] + 1)) >> 11; - } - src += stride; - dst += stride; - } -} - -static inline void put_tpel_pixels_mc11_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (2731*(4*src[j] + 3*src[j+1] + 3*src[j+stride] + 2*src[j+stride+1] + 6)) >> 15; - } - src += stride; - dst += stride; - } -} - -static inline void put_tpel_pixels_mc12_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (2731*(3*src[j] + 2*src[j+1] + 4*src[j+stride] + 3*src[j+stride+1] + 6)) >> 15; - } - src += stride; - dst += stride; - } -} - -static inline void put_tpel_pixels_mc02_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (683*(src[j] + 2*src[j+stride] + 1)) >> 11; - } - src += stride; - dst += stride; - } -} - -static inline void put_tpel_pixels_mc21_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (2731*(3*src[j] + 4*src[j+1] + 2*src[j+stride] + 3*src[j+stride+1] + 6)) >> 15; - } - src += stride; - dst += stride; - } -} - -static inline void put_tpel_pixels_mc22_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (2731*(2*src[j] + 3*src[j+1] + 3*src[j+stride] + 4*src[j+stride+1] + 6)) >> 15; - } - src += stride; - dst += stride; - } -} - -static inline void avg_tpel_pixels_mc00_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - switch(width){ - case 2: avg_pixels2_8_c (dst, src, stride, height); break; - case 4: avg_pixels4_8_c (dst, src, stride, height); break; - case 8: avg_pixels8_8_c (dst, src, stride, height); break; - case 16:avg_pixels16_8_c(dst, src, stride, height); break; - } -} - -static inline void avg_tpel_pixels_mc10_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (dst[j] + ((683*(2*src[j] + src[j+1] + 1)) >> 11) + 1) >> 1; - } - src += stride; - dst += stride; - } -} - -static inline void avg_tpel_pixels_mc20_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (dst[j] + ((683*(src[j] + 2*src[j+1] + 1)) >> 11) + 1) >> 1; - } - src += stride; - dst += stride; - } -} - -static inline void avg_tpel_pixels_mc01_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (dst[j] + ((683*(2*src[j] + src[j+stride] + 1)) >> 11) + 1) >> 1; - } - src += stride; - dst += stride; - } -} - -static inline void avg_tpel_pixels_mc11_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (dst[j] + ((2731*(4*src[j] + 3*src[j+1] + 3*src[j+stride] + 2*src[j+stride+1] + 6)) >> 15) + 1) >> 1; - } - src += stride; - dst += stride; - } -} - -static inline void avg_tpel_pixels_mc12_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (dst[j] + ((2731*(3*src[j] + 2*src[j+1] + 4*src[j+stride] + 3*src[j+stride+1] + 6)) >> 15) + 1) >> 1; - } - src += stride; - dst += stride; - } -} - -static inline void avg_tpel_pixels_mc02_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (dst[j] + ((683*(src[j] + 2*src[j+stride] + 1)) >> 11) + 1) >> 1; - } - src += stride; - dst += stride; - } -} - -static inline void avg_tpel_pixels_mc21_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (dst[j] + ((2731*(3*src[j] + 4*src[j+1] + 2*src[j+stride] + 3*src[j+stride+1] + 6)) >> 15) + 1) >> 1; - } - src += stride; - dst += stride; - } -} - -static inline void avg_tpel_pixels_mc22_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ - int i,j; - for (i=0; i < height; i++) { - for (j=0; j < width; j++) { - dst[j] = (dst[j] + ((2731*(2*src[j] + 3*src[j+1] + 3*src[j+stride] + 4*src[j+stride+1] + 6)) >> 15) + 1) >> 1; - } - src += stride; - dst += stride; - } -} - -#define QPEL_MC(r, OPNAME, RND, OP) \ -static void OPNAME ## mpeg4_qpel8_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ - int i;\ - for(i=0; i>5]+1)>>1) -#define op_avg_no_rnd(a, b) a = (((a)+cm[((b) + 15)>>5])>>1) -#define op_put(a, b) a = cm[((b) + 16)>>5] -#define op_put_no_rnd(a, b) a = cm[((b) + 15)>>5] - -QPEL_MC(0, put_ , _ , op_put) -QPEL_MC(1, put_no_rnd_, _no_rnd_, op_put_no_rnd) -QPEL_MC(0, avg_ , _ , op_avg) -//QPEL_MC(1, avg_no_rnd , _ , op_avg) -#undef op_avg -#undef op_avg_no_rnd -#undef op_put -#undef op_put_no_rnd - -void ff_put_pixels8x8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - put_pixels8_8_c(dst, src, stride, 8); -} -void ff_avg_pixels8x8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - avg_pixels8_8_c(dst, src, stride, 8); -} -void ff_put_pixels16x16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - put_pixels16_8_c(dst, src, stride, 16); -} -void ff_avg_pixels16x16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - avg_pixels16_8_c(dst, src, stride, 16); -} - -#define put_qpel8_mc00_c ff_put_pixels8x8_c -#define avg_qpel8_mc00_c ff_avg_pixels8x8_c -#define put_qpel16_mc00_c ff_put_pixels16x16_c -#define avg_qpel16_mc00_c ff_avg_pixels16x16_c -#define put_no_rnd_qpel8_mc00_c ff_put_pixels8x8_c -#define put_no_rnd_qpel16_mc00_c ff_put_pixels16x16_c - -static void wmv2_mspel8_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; - int i; - - for(i=0; i>4]; - dst[1]= cm[(9*(src[1] + src[2]) - (src[ 0] + src[3]) + 8)>>4]; - dst[2]= cm[(9*(src[2] + src[3]) - (src[ 1] + src[4]) + 8)>>4]; - dst[3]= cm[(9*(src[3] + src[4]) - (src[ 2] + src[5]) + 8)>>4]; - dst[4]= cm[(9*(src[4] + src[5]) - (src[ 3] + src[6]) + 8)>>4]; - dst[5]= cm[(9*(src[5] + src[6]) - (src[ 4] + src[7]) + 8)>>4]; - dst[6]= cm[(9*(src[6] + src[7]) - (src[ 5] + src[8]) + 8)>>4]; - dst[7]= cm[(9*(src[7] + src[8]) - (src[ 6] + src[9]) + 8)>>4]; - dst+=dstStride; - src+=srcStride; - } -} - -#if CONFIG_RV40_DECODER -void ff_put_rv40_qpel16_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - put_pixels16_xy2_8_c(dst, src, stride, 16); -} -void ff_avg_rv40_qpel16_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - avg_pixels16_xy2_8_c(dst, src, stride, 16); -} -void ff_put_rv40_qpel8_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - put_pixels8_xy2_8_c(dst, src, stride, 8); -} -void ff_avg_rv40_qpel8_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - avg_pixels8_xy2_8_c(dst, src, stride, 8); -} -#endif /* CONFIG_RV40_DECODER */ - -#if CONFIG_DIRAC_DECODER -#define DIRAC_MC(OPNAME)\ -void ff_ ## OPNAME ## _dirac_pixels8_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ -{\ - OPNAME ## _pixels8_8_c(dst, src[0], stride, h);\ -}\ -void ff_ ## OPNAME ## _dirac_pixels16_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ -{\ - OPNAME ## _pixels16_8_c(dst, src[0], stride, h);\ -}\ -void ff_ ## OPNAME ## _dirac_pixels32_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ -{\ - OPNAME ## _pixels16_8_c(dst , src[0] , stride, h);\ - OPNAME ## _pixels16_8_c(dst+16, src[0]+16, stride, h);\ -}\ -void ff_ ## OPNAME ## _dirac_pixels8_l2_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ -{\ - OPNAME ## _pixels8_l2_8(dst, src[0], src[1], stride, stride, stride, h);\ -}\ -void ff_ ## OPNAME ## _dirac_pixels16_l2_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ -{\ - OPNAME ## _pixels16_l2_8(dst, src[0], src[1], stride, stride, stride, h);\ -}\ -void ff_ ## OPNAME ## _dirac_pixels32_l2_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ -{\ - OPNAME ## _pixels16_l2_8(dst , src[0] , src[1] , stride, stride, stride, h);\ - OPNAME ## _pixels16_l2_8(dst+16, src[0]+16, src[1]+16, stride, stride, stride, h);\ -}\ -void ff_ ## OPNAME ## _dirac_pixels8_l4_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ -{\ - OPNAME ## _pixels8_l4_8(dst, src[0], src[1], src[2], src[3], stride, stride, stride, stride, stride, h);\ -}\ -void ff_ ## OPNAME ## _dirac_pixels16_l4_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ -{\ - OPNAME ## _pixels16_l4_8(dst, src[0], src[1], src[2], src[3], stride, stride, stride, stride, stride, h);\ -}\ -void ff_ ## OPNAME ## _dirac_pixels32_l4_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ -{\ - OPNAME ## _pixels16_l4_8(dst , src[0] , src[1] , src[2] , src[3] , stride, stride, stride, stride, stride, h);\ - OPNAME ## _pixels16_l4_8(dst+16, src[0]+16, src[1]+16, src[2]+16, src[3]+16, stride, stride, stride, stride, stride, h);\ -} -DIRAC_MC(put) -DIRAC_MC(avg) -#endif - -static void wmv2_mspel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int w){ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; - int i; - - for(i=0; i>4]; - dst[1*dstStride]= cm[(9*(src1 + src2) - (src0 + src3) + 8)>>4]; - dst[2*dstStride]= cm[(9*(src2 + src3) - (src1 + src4) + 8)>>4]; - dst[3*dstStride]= cm[(9*(src3 + src4) - (src2 + src5) + 8)>>4]; - dst[4*dstStride]= cm[(9*(src4 + src5) - (src3 + src6) + 8)>>4]; - dst[5*dstStride]= cm[(9*(src5 + src6) - (src4 + src7) + 8)>>4]; - dst[6*dstStride]= cm[(9*(src6 + src7) - (src5 + src8) + 8)>>4]; - dst[7*dstStride]= cm[(9*(src7 + src8) - (src6 + src9) + 8)>>4]; - src++; - dst++; - } -} - -static void put_mspel8_mc10_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - uint8_t half[64]; - wmv2_mspel8_h_lowpass(half, src, 8, stride, 8); - put_pixels8_l2_8(dst, src, half, stride, stride, 8, 8); -} - -static void put_mspel8_mc20_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - wmv2_mspel8_h_lowpass(dst, src, stride, stride, 8); -} - -static void put_mspel8_mc30_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - uint8_t half[64]; - wmv2_mspel8_h_lowpass(half, src, 8, stride, 8); - put_pixels8_l2_8(dst, src+1, half, stride, stride, 8, 8); -} - -static void put_mspel8_mc02_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - wmv2_mspel8_v_lowpass(dst, src, stride, stride, 8); -} - -static void put_mspel8_mc12_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - uint8_t halfH[88]; - uint8_t halfV[64]; - uint8_t halfHV[64]; - wmv2_mspel8_h_lowpass(halfH, src-stride, 8, stride, 11); - wmv2_mspel8_v_lowpass(halfV, src, 8, stride, 8); - wmv2_mspel8_v_lowpass(halfHV, halfH+8, 8, 8, 8); - put_pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8); -} -static void put_mspel8_mc32_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - uint8_t halfH[88]; - uint8_t halfV[64]; - uint8_t halfHV[64]; - wmv2_mspel8_h_lowpass(halfH, src-stride, 8, stride, 11); - wmv2_mspel8_v_lowpass(halfV, src+1, 8, stride, 8); - wmv2_mspel8_v_lowpass(halfHV, halfH+8, 8, 8, 8); - put_pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8); -} -static void put_mspel8_mc22_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) -{ - uint8_t halfH[88]; - wmv2_mspel8_h_lowpass(halfH, src-stride, 8, stride, 11); - wmv2_mspel8_v_lowpass(dst, halfH+8, stride, 8, 8); -} - -static inline int pix_abs16_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) -{ - int s, i; - - s = 0; - for(i=0;iavctx->nsse_weight; - else return score1 + FFABS(score2)*8; + if (c) + return score1 + FFABS(score2) * c->avctx->nsse_weight; + else + return score1 + FFABS(score2) * 8; } -static int nsse8_c(void *v, uint8_t *s1, uint8_t *s2, int stride, int h){ - MpegEncContext *c = v; - int score1=0; - int score2=0; - int x,y; +static int nsse8_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, int stride, int h) +{ + int score1 = 0, score2 = 0, x, y; - for(y=0; yavctx->nsse_weight; - else return score1 + FFABS(score2)*8; + if (c) + return score1 + FFABS(score2) * c->avctx->nsse_weight; + else + return score1 + FFABS(score2) * 8; } -static int try_8x8basis_c(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale){ - int i; - unsigned int sum=0; - - for(i=0; i<8*8; i++){ - int b= rem[i] + ((basis[i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT)); - int w= weight[i]; - b>>= RECON_SHIFT; - av_assert2(-512>4; - } - return sum>>2; -} - -static void add_8x8basis_c(int16_t rem[64], int16_t basis[64], int scale){ - int i; - - for(i=0; i<8*8; i++){ - rem[i] += (basis[i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT); - } -} - -static int zero_cmp(void *s, uint8_t *a, uint8_t *b, int stride, int h){ +static int zero_cmp(MpegEncContext *s, uint8_t *a, uint8_t *b, + int stride, int h) +{ return 0; } -void ff_set_cmp(DSPContext* c, me_cmp_func *cmp, int type){ +void ff_set_cmp(DSPContext *c, me_cmp_func *cmp, int type) +{ int i; - memset(cmp, 0, sizeof(void*)*6); + memset(cmp, 0, sizeof(void *) * 6); - for(i=0; i<6; i++){ - switch(type&0xFF){ + for (i = 0; i < 6; i++) { + switch (type & 0xFF) { case FF_CMP_SAD: - cmp[i]= c->sad[i]; + cmp[i] = c->sad[i]; break; case FF_CMP_SATD: - cmp[i]= c->hadamard8_diff[i]; + cmp[i] = c->hadamard8_diff[i]; break; case FF_CMP_SSE: - cmp[i]= c->sse[i]; + cmp[i] = c->sse[i]; break; case FF_CMP_DCT: - cmp[i]= c->dct_sad[i]; + cmp[i] = c->dct_sad[i]; break; case FF_CMP_DCT264: - cmp[i]= c->dct264_sad[i]; + cmp[i] = c->dct264_sad[i]; break; case FF_CMP_DCTMAX: - cmp[i]= c->dct_max[i]; + cmp[i] = c->dct_max[i]; break; case FF_CMP_PSNR: - cmp[i]= c->quant_psnr[i]; + cmp[i] = c->quant_psnr[i]; break; case FF_CMP_BIT: - cmp[i]= c->bit[i]; + cmp[i] = c->bit[i]; break; case FF_CMP_RD: - cmp[i]= c->rd[i]; + cmp[i] = c->rd[i]; break; case FF_CMP_VSAD: - cmp[i]= c->vsad[i]; + cmp[i] = c->vsad[i]; break; case FF_CMP_VSSE: - cmp[i]= c->vsse[i]; + cmp[i] = c->vsse[i]; break; case FF_CMP_ZERO: - cmp[i]= zero_cmp; + cmp[i] = zero_cmp; break; case FF_CMP_NSSE: - cmp[i]= c->nsse[i]; + cmp[i] = c->nsse[i]; break; #if CONFIG_DWT case FF_CMP_W53: @@ -1847,576 +426,474 @@ void ff_set_cmp(DSPContext* c, me_cmp_func *cmp, int type){ break; #endif default: - av_log(NULL, AV_LOG_ERROR,"internal error in cmp function selection\n"); + av_log(NULL, AV_LOG_ERROR, + "internal error in cmp function selection\n"); } } } -static void add_bytes_c(uint8_t *dst, uint8_t *src, int w){ - long i; - for (i = 0; i <= w - (int)sizeof(long); i += sizeof(long)) { - long a = *(long*)(src+i); - long b = *(long*)(dst+i); - *(long*)(dst+i) = ((a&pb_7f) + (b&pb_7f)) ^ ((a^b)&pb_80); - } - for(; idsp.diff_pixels(temp, src1, src2, stride); - s->dsp.fdct(temp); + s->pdsp.diff_pixels(temp, src1, src2, stride); + s->fdsp.fdct(temp); return s->dsp.sum_abs_dctelem(temp); } #if CONFIG_GPL -#define DCT8_1D {\ - const int s07 = SRC(0) + SRC(7);\ - const int s16 = SRC(1) + SRC(6);\ - const int s25 = SRC(2) + SRC(5);\ - const int s34 = SRC(3) + SRC(4);\ - const int a0 = s07 + s34;\ - const int a1 = s16 + s25;\ - const int a2 = s07 - s34;\ - const int a3 = s16 - s25;\ - const int d07 = SRC(0) - SRC(7);\ - const int d16 = SRC(1) - SRC(6);\ - const int d25 = SRC(2) - SRC(5);\ - const int d34 = SRC(3) - SRC(4);\ - const int a4 = d16 + d25 + (d07 + (d07>>1));\ - const int a5 = d07 - d34 - (d25 + (d25>>1));\ - const int a6 = d07 + d34 - (d16 + (d16>>1));\ - const int a7 = d16 - d25 + (d34 + (d34>>1));\ - DST(0, a0 + a1 ) ;\ - DST(1, a4 + (a7>>2)) ;\ - DST(2, a2 + (a3>>1)) ;\ - DST(3, a5 + (a6>>2)) ;\ - DST(4, a0 - a1 ) ;\ - DST(5, a6 - (a5>>2)) ;\ - DST(6, (a2>>1) - a3 ) ;\ - DST(7, (a4>>2) - a7 ) ;\ -} +#define DCT8_1D \ + { \ + const int s07 = SRC(0) + SRC(7); \ + const int s16 = SRC(1) + SRC(6); \ + const int s25 = SRC(2) + SRC(5); \ + const int s34 = SRC(3) + SRC(4); \ + const int a0 = s07 + s34; \ + const int a1 = s16 + s25; \ + const int a2 = s07 - s34; \ + const int a3 = s16 - s25; \ + const int d07 = SRC(0) - SRC(7); \ + const int d16 = SRC(1) - SRC(6); \ + const int d25 = SRC(2) - SRC(5); \ + const int d34 = SRC(3) - SRC(4); \ + const int a4 = d16 + d25 + (d07 + (d07 >> 1)); \ + const int a5 = d07 - d34 - (d25 + (d25 >> 1)); \ + const int a6 = d07 + d34 - (d16 + (d16 >> 1)); \ + const int a7 = d16 - d25 + (d34 + (d34 >> 1)); \ + DST(0, a0 + a1); \ + DST(1, a4 + (a7 >> 2)); \ + DST(2, a2 + (a3 >> 1)); \ + DST(3, a5 + (a6 >> 2)); \ + DST(4, a0 - a1); \ + DST(5, a6 - (a5 >> 2)); \ + DST(6, (a2 >> 1) - a3); \ + DST(7, (a4 >> 2) - a7); \ + } -static int dct264_sad8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){ - MpegEncContext * const s= (MpegEncContext *)c; +static int dct264_sad8x8_c(MpegEncContext *s, uint8_t *src1, + uint8_t *src2, int stride, int h) +{ int16_t dct[8][8]; - int i; - int sum=0; + int i, sum = 0; - s->dsp.diff_pixels(dct[0], src1, src2, stride); + s->pdsp.diff_pixels(dct[0], src1, src2, stride); #define SRC(x) dct[i][x] -#define DST(x,v) dct[i][x]= v - for( i = 0; i < 8; i++ ) +#define DST(x, v) dct[i][x] = v + for (i = 0; i < 8; i++) DCT8_1D #undef SRC #undef DST #define SRC(x) dct[x][i] -#define DST(x,v) sum += FFABS(v) - for( i = 0; i < 8; i++ ) - DCT8_1D +#define DST(x, v) sum += FFABS(v) + for (i = 0; i < 8; i++) + DCT8_1D #undef SRC #undef DST - return sum; + return sum; } #endif -static int dct_max8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){ - MpegEncContext * const s= (MpegEncContext *)c; +static int dct_max8x8_c(MpegEncContext *s, uint8_t *src1, + uint8_t *src2, int stride, int h) +{ LOCAL_ALIGNED_16(int16_t, temp, [64]); - int sum=0, i; + int sum = 0, i; - av_assert2(h==8); + av_assert2(h == 8); - s->dsp.diff_pixels(temp, src1, src2, stride); - s->dsp.fdct(temp); + s->pdsp.diff_pixels(temp, src1, src2, stride); + s->fdsp.fdct(temp); - for(i=0; i<64; i++) - sum= FFMAX(sum, FFABS(temp[i])); + for (i = 0; i < 64; i++) + sum = FFMAX(sum, FFABS(temp[i])); return sum; } -static int quant_psnr8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){ - MpegEncContext * const s= (MpegEncContext *)c; - LOCAL_ALIGNED_16(int16_t, temp, [64*2]); - int16_t * const bak = temp+64; - int sum=0, i; +static int quant_psnr8x8_c(MpegEncContext *s, uint8_t *src1, + uint8_t *src2, int stride, int h) +{ + LOCAL_ALIGNED_16(int16_t, temp, [64 * 2]); + int16_t *const bak = temp + 64; + int sum = 0, i; - av_assert2(h==8); - s->mb_intra=0; + av_assert2(h == 8); + s->mb_intra = 0; - s->dsp.diff_pixels(temp, src1, src2, stride); + s->pdsp.diff_pixels(temp, src1, src2, stride); - memcpy(bak, temp, 64*sizeof(int16_t)); + memcpy(bak, temp, 64 * sizeof(int16_t)); - s->block_last_index[0/*FIXME*/]= s->fast_dct_quantize(s, temp, 0/*FIXME*/, s->qscale, &i); + s->block_last_index[0 /* FIXME */] = + s->fast_dct_quantize(s, temp, 0 /* FIXME */, s->qscale, &i); s->dct_unquantize_inter(s, temp, 0, s->qscale); - ff_simple_idct_8(temp); //FIXME + ff_simple_idct_8(temp); // FIXME - for(i=0; i<64; i++) - sum+= (temp[i]-bak[i])*(temp[i]-bak[i]); + for (i = 0; i < 64; i++) + sum += (temp[i] - bak[i]) * (temp[i] - bak[i]); return sum; } -static int rd8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){ - MpegEncContext * const s= (MpegEncContext *)c; - const uint8_t *scantable= s->intra_scantable.permutated; +static int rd8x8_c(MpegEncContext *s, uint8_t *src1, uint8_t *src2, + int stride, int h) +{ + const uint8_t *scantable = s->intra_scantable.permutated; LOCAL_ALIGNED_16(int16_t, temp, [64]); LOCAL_ALIGNED_16(uint8_t, lsrc1, [64]); LOCAL_ALIGNED_16(uint8_t, lsrc2, [64]); int i, last, run, bits, level, distortion, start_i; - const int esc_length= s->ac_esc_length; - uint8_t * length; - uint8_t * last_length; + const int esc_length = s->ac_esc_length; + uint8_t *length, *last_length; - av_assert2(h==8); + av_assert2(h == 8); copy_block8(lsrc1, src1, 8, stride, 8); copy_block8(lsrc2, src2, 8, stride, 8); - s->dsp.diff_pixels(temp, lsrc1, lsrc2, 8); + s->pdsp.diff_pixels(temp, lsrc1, lsrc2, 8); - s->block_last_index[0/*FIXME*/]= last= s->fast_dct_quantize(s, temp, 0/*FIXME*/, s->qscale, &i); + s->block_last_index[0 /* FIXME */] = + last = + s->fast_dct_quantize(s, temp, 0 /* FIXME */, s->qscale, &i); - bits=0; + bits = 0; if (s->mb_intra) { - start_i = 1; - length = s->intra_ac_vlc_length; - last_length= s->intra_ac_vlc_last_length; - bits+= s->luma_dc_vlc_length[temp[0] + 256]; //FIXME chroma + start_i = 1; + length = s->intra_ac_vlc_length; + last_length = s->intra_ac_vlc_last_length; + bits += s->luma_dc_vlc_length[temp[0] + 256]; // FIXME: chroma } else { - start_i = 0; - length = s->inter_ac_vlc_length; - last_length= s->inter_ac_vlc_last_length; + start_i = 0; + length = s->inter_ac_vlc_length; + last_length = s->inter_ac_vlc_last_length; } - if(last>=start_i){ - run=0; - for(i=start_i; i= start_i) { + run = 0; + for (i = start_i; i < last; i++) { + int j = scantable[i]; + level = temp[j]; - if(level){ - level+=64; - if((level&(~127)) == 0){ - bits+= length[UNI_AC_ENC_INDEX(run, level)]; - }else - bits+= esc_length; - run=0; - }else + if (level) { + level += 64; + if ((level & (~127)) == 0) + bits += length[UNI_AC_ENC_INDEX(run, level)]; + else + bits += esc_length; + run = 0; + } else run++; } - i= scantable[last]; + i = scantable[last]; - level= temp[i] + 64; + level = temp[i] + 64; av_assert2(level - 64); - if((level&(~127)) == 0){ - bits+= last_length[UNI_AC_ENC_INDEX(run, level)]; - }else - bits+= esc_length; - + if ((level & (~127)) == 0) { + bits += last_length[UNI_AC_ENC_INDEX(run, level)]; + } else + bits += esc_length; } - if(last>=0){ - if(s->mb_intra) + if (last >= 0) { + if (s->mb_intra) s->dct_unquantize_intra(s, temp, 0, s->qscale); else s->dct_unquantize_inter(s, temp, 0, s->qscale); } - s->dsp.idct_add(lsrc2, 8, temp); + s->idsp.idct_add(lsrc2, 8, temp); - distortion= s->dsp.sse[1](NULL, lsrc2, lsrc1, 8, 8); + distortion = s->dsp.sse[1](NULL, lsrc2, lsrc1, 8, 8); - return distortion + ((bits*s->qscale*s->qscale*109 + 64)>>7); + return distortion + ((bits * s->qscale * s->qscale * 109 + 64) >> 7); } -static int bit8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){ - MpegEncContext * const s= (MpegEncContext *)c; - const uint8_t *scantable= s->intra_scantable.permutated; +static int bit8x8_c(MpegEncContext *s, uint8_t *src1, uint8_t *src2, + int stride, int h) +{ + const uint8_t *scantable = s->intra_scantable.permutated; LOCAL_ALIGNED_16(int16_t, temp, [64]); int i, last, run, bits, level, start_i; - const int esc_length= s->ac_esc_length; - uint8_t * length; - uint8_t * last_length; + const int esc_length = s->ac_esc_length; + uint8_t *length, *last_length; - av_assert2(h==8); + av_assert2(h == 8); - s->dsp.diff_pixels(temp, src1, src2, stride); + s->pdsp.diff_pixels(temp, src1, src2, stride); - s->block_last_index[0/*FIXME*/]= last= s->fast_dct_quantize(s, temp, 0/*FIXME*/, s->qscale, &i); + s->block_last_index[0 /* FIXME */] = + last = + s->fast_dct_quantize(s, temp, 0 /* FIXME */, s->qscale, &i); - bits=0; + bits = 0; if (s->mb_intra) { - start_i = 1; - length = s->intra_ac_vlc_length; - last_length= s->intra_ac_vlc_last_length; - bits+= s->luma_dc_vlc_length[temp[0] + 256]; //FIXME chroma + start_i = 1; + length = s->intra_ac_vlc_length; + last_length = s->intra_ac_vlc_last_length; + bits += s->luma_dc_vlc_length[temp[0] + 256]; // FIXME: chroma } else { - start_i = 0; - length = s->inter_ac_vlc_length; - last_length= s->inter_ac_vlc_last_length; + start_i = 0; + length = s->inter_ac_vlc_length; + last_length = s->inter_ac_vlc_last_length; } - if(last>=start_i){ - run=0; - for(i=start_i; i= start_i) { + run = 0; + for (i = start_i; i < last; i++) { + int j = scantable[i]; + level = temp[j]; - if(level){ - level+=64; - if((level&(~127)) == 0){ - bits+= length[UNI_AC_ENC_INDEX(run, level)]; - }else - bits+= esc_length; - run=0; - }else + if (level) { + level += 64; + if ((level & (~127)) == 0) + bits += length[UNI_AC_ENC_INDEX(run, level)]; + else + bits += esc_length; + run = 0; + } else run++; } - i= scantable[last]; + i = scantable[last]; - level= temp[i] + 64; + level = temp[i] + 64; av_assert2(level - 64); - if((level&(~127)) == 0){ - bits+= last_length[UNI_AC_ENC_INDEX(run, level)]; - }else - bits+= esc_length; + if ((level & (~127)) == 0) + bits += last_length[UNI_AC_ENC_INDEX(run, level)]; + else + bits += esc_length; } return bits; } -#define VSAD_INTRA(size) \ -static int vsad_intra##size##_c(/*MpegEncContext*/ void *c, uint8_t *s, uint8_t *dummy, int stride, int h){ \ - int score=0; \ - int x,y; \ - \ - for(y=1; y mini) return mini; - else if((a^(1U<<31)) > maxisign) return maxi; - else return a; -} - -static void vector_clipf_c_opposite_sign(float *dst, const float *src, float *min, float *max, int len){ - int i; - uint32_t mini = *(uint32_t*)min; - uint32_t maxi = *(uint32_t*)max; - uint32_t maxisign = maxi ^ (1U<<31); - uint32_t *dsti = (uint32_t*)dst; - const uint32_t *srci = (const uint32_t*)src; - for(i=0; i 0) { - vector_clipf_c_opposite_sign(dst, src, &min, &max, len); - } else { - for(i=0; i < len; i+=8) { - dst[i ] = av_clipf(src[i ], min, max); - dst[i + 1] = av_clipf(src[i + 1], min, max); - dst[i + 2] = av_clipf(src[i + 2], min, max); - dst[i + 3] = av_clipf(src[i + 3], min, max); - dst[i + 4] = av_clipf(src[i + 4], min, max); - dst[i + 5] = av_clipf(src[i + 5], min, max); - dst[i + 6] = av_clipf(src[i + 6], min, max); - dst[i + 7] = av_clipf(src[i + 7], min, max); - } - } -} - -static int32_t scalarproduct_int16_c(const int16_t * v1, const int16_t * v2, int order) -{ - int res = 0; - - while (order--) - res += *v1++ * *v2++; - - return res; -} - -static int32_t scalarproduct_and_madd_int16_c(int16_t *v1, const int16_t *v2, const int16_t *v3, int order, int mul) -{ - int res = 0; - while (order--) { - res += *v1 * *v2++; - *v1++ += mul * *v3++; - } - return res; -} - -static void vector_clip_int32_c(int32_t *dst, const int32_t *src, int32_t min, - int32_t max, unsigned int len) -{ - do { - *dst++ = av_clip(*src++, min, max); - *dst++ = av_clip(*src++, min, max); - *dst++ = av_clip(*src++, min, max); - *dst++ = av_clip(*src++, min, max); - *dst++ = av_clip(*src++, min, max); - *dst++ = av_clip(*src++, min, max); - *dst++ = av_clip(*src++, min, max); - *dst++ = av_clip(*src++, min, max); - len -= 8; - } while (len > 0); -} - -static void 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); -} - -static void ff_jref_idct4_put(uint8_t *dest, int line_size, int16_t *block) -{ - ff_j_rev_dct4 (block); - put_pixels_clamped4_c(block, dest, line_size); -} -static void ff_jref_idct4_add(uint8_t *dest, int line_size, int16_t *block) -{ - ff_j_rev_dct4 (block); - add_pixels_clamped4_c(block, dest, line_size); -} - -static void ff_jref_idct2_put(uint8_t *dest, int line_size, int16_t *block) -{ - ff_j_rev_dct2 (block); - put_pixels_clamped2_c(block, dest, line_size); -} -static void ff_jref_idct2_add(uint8_t *dest, int line_size, int16_t *block) -{ - ff_j_rev_dct2 (block); - add_pixels_clamped2_c(block, dest, line_size); -} - -static void ff_jref_idct1_put(uint8_t *dest, int line_size, int16_t *block) -{ - dest[0] = av_clip_uint8((block[0] + 4)>>3); -} -static void ff_jref_idct1_add(uint8_t *dest, int line_size, int16_t *block) -{ - dest[0] = av_clip_uint8(dest[0] + ((block[0] + 4)>>3)); -} - /* init static data */ av_cold void ff_dsputil_static_init(void) { int i; - for(i=0;i<512;i++) { - ff_squareTbl[i] = (i - 256) * (i - 256); - } + for (i = 0; i < 512; i++) + ff_square_tab[i] = (i - 256) * (i - 256); } -int ff_check_alignment(void){ - static int did_fail=0; +int ff_check_alignment(void) +{ + static int did_fail = 0; LOCAL_ALIGNED_16(int, aligned, [4]); - if((intptr_t)aligned & 15){ - if(!did_fail){ + if ((intptr_t)aligned & 15) { + if (!did_fail) { #if HAVE_MMX || HAVE_ALTIVEC av_log(NULL, AV_LOG_ERROR, "Compiler did not align stack variables. Libavcodec has been miscompiled\n" @@ -2583,88 +937,11 @@ int ff_check_alignment(void){ return 0; } -av_cold void ff_dsputil_init(DSPContext* c, AVCodecContext *avctx) +av_cold void ff_dsputil_init(DSPContext *c, AVCodecContext *avctx) { ff_check_alignment(); -#if CONFIG_ENCODERS - if (avctx->bits_per_raw_sample == 10) { - c->fdct = ff_jpeg_fdct_islow_10; - c->fdct248 = ff_fdct248_islow_10; - } else { - if(avctx->dct_algo==FF_DCT_FASTINT) { - c->fdct = ff_fdct_ifast; - c->fdct248 = ff_fdct_ifast248; - } - else if(avctx->dct_algo==FF_DCT_FAAN) { - c->fdct = ff_faandct; - c->fdct248 = ff_faandct248; - } - else { - c->fdct = ff_jpeg_fdct_islow_8; //slow/accurate/default - c->fdct248 = ff_fdct248_islow_8; - } - } -#endif //CONFIG_ENCODERS - - if(avctx->lowres==1){ - c->idct_put= ff_jref_idct4_put; - c->idct_add= ff_jref_idct4_add; - c->idct = ff_j_rev_dct4; - c->idct_permutation_type= FF_NO_IDCT_PERM; - }else if(avctx->lowres==2){ - c->idct_put= ff_jref_idct2_put; - c->idct_add= ff_jref_idct2_add; - c->idct = ff_j_rev_dct2; - c->idct_permutation_type= FF_NO_IDCT_PERM; - }else if(avctx->lowres==3){ - c->idct_put= ff_jref_idct1_put; - c->idct_add= ff_jref_idct1_add; - c->idct = ff_j_rev_dct1; - c->idct_permutation_type= FF_NO_IDCT_PERM; - }else{ - if (avctx->bits_per_raw_sample == 10) { - c->idct_put = ff_simple_idct_put_10; - c->idct_add = ff_simple_idct_add_10; - c->idct = ff_simple_idct_10; - c->idct_permutation_type = FF_NO_IDCT_PERM; - } else if (avctx->bits_per_raw_sample == 12) { - c->idct_put = ff_simple_idct_put_12; - c->idct_add = ff_simple_idct_add_12; - c->idct = ff_simple_idct_12; - c->idct_permutation_type = FF_NO_IDCT_PERM; - } else { - if(avctx->idct_algo==FF_IDCT_INT){ - c->idct_put= jref_idct_put; - c->idct_add= jref_idct_add; - c->idct = ff_j_rev_dct; - c->idct_permutation_type= FF_LIBMPEG2_IDCT_PERM; - }else if(avctx->idct_algo==FF_IDCT_FAAN){ - c->idct_put= ff_faanidct_put; - c->idct_add= ff_faanidct_add; - c->idct = ff_faanidct; - c->idct_permutation_type= FF_NO_IDCT_PERM; - }else{ //accurate/default - c->idct_put = ff_simple_idct_put_8; - c->idct_add = ff_simple_idct_add_8; - c->idct = ff_simple_idct_8; - c->idct_permutation_type= FF_NO_IDCT_PERM; - } - } - } - - c->diff_pixels = diff_pixels_c; - c->put_pixels_clamped = put_pixels_clamped_c; - c->put_signed_pixels_clamped = put_signed_pixels_clamped_c; - c->add_pixels_clamped = add_pixels_clamped_c; c->sum_abs_dctelem = sum_abs_dctelem_c; - c->gmc1 = gmc1_c; - c->gmc = ff_gmc_c; - c->pix_sum = pix_sum_c; - c->pix_norm1 = pix_norm1_c; - - c->fill_block_tab[0] = fill_block16_c; - c->fill_block_tab[1] = fill_block8_c; /* TODO [0] 16 [1] 8 */ c->pix_abs[0][0] = pix_abs16_c; @@ -2676,169 +953,48 @@ av_cold void ff_dsputil_init(DSPContext* c, AVCodecContext *avctx) c->pix_abs[1][2] = pix_abs8_y2_c; c->pix_abs[1][3] = pix_abs8_xy2_c; - c->put_tpel_pixels_tab[ 0] = put_tpel_pixels_mc00_c; - c->put_tpel_pixels_tab[ 1] = put_tpel_pixels_mc10_c; - c->put_tpel_pixels_tab[ 2] = put_tpel_pixels_mc20_c; - c->put_tpel_pixels_tab[ 4] = put_tpel_pixels_mc01_c; - c->put_tpel_pixels_tab[ 5] = put_tpel_pixels_mc11_c; - c->put_tpel_pixels_tab[ 6] = put_tpel_pixels_mc21_c; - c->put_tpel_pixels_tab[ 8] = put_tpel_pixels_mc02_c; - c->put_tpel_pixels_tab[ 9] = put_tpel_pixels_mc12_c; - c->put_tpel_pixels_tab[10] = put_tpel_pixels_mc22_c; - - c->avg_tpel_pixels_tab[ 0] = avg_tpel_pixels_mc00_c; - c->avg_tpel_pixels_tab[ 1] = avg_tpel_pixels_mc10_c; - c->avg_tpel_pixels_tab[ 2] = avg_tpel_pixels_mc20_c; - c->avg_tpel_pixels_tab[ 4] = avg_tpel_pixels_mc01_c; - c->avg_tpel_pixels_tab[ 5] = avg_tpel_pixels_mc11_c; - c->avg_tpel_pixels_tab[ 6] = avg_tpel_pixels_mc21_c; - c->avg_tpel_pixels_tab[ 8] = avg_tpel_pixels_mc02_c; - c->avg_tpel_pixels_tab[ 9] = avg_tpel_pixels_mc12_c; - c->avg_tpel_pixels_tab[10] = avg_tpel_pixels_mc22_c; - -#define dspfunc(PFX, IDX, NUM) \ - c->PFX ## _pixels_tab[IDX][ 0] = PFX ## NUM ## _mc00_c; \ - c->PFX ## _pixels_tab[IDX][ 1] = PFX ## NUM ## _mc10_c; \ - c->PFX ## _pixels_tab[IDX][ 2] = PFX ## NUM ## _mc20_c; \ - c->PFX ## _pixels_tab[IDX][ 3] = PFX ## NUM ## _mc30_c; \ - c->PFX ## _pixels_tab[IDX][ 4] = PFX ## NUM ## _mc01_c; \ - c->PFX ## _pixels_tab[IDX][ 5] = PFX ## NUM ## _mc11_c; \ - c->PFX ## _pixels_tab[IDX][ 6] = PFX ## NUM ## _mc21_c; \ - c->PFX ## _pixels_tab[IDX][ 7] = PFX ## NUM ## _mc31_c; \ - c->PFX ## _pixels_tab[IDX][ 8] = PFX ## NUM ## _mc02_c; \ - c->PFX ## _pixels_tab[IDX][ 9] = PFX ## NUM ## _mc12_c; \ - c->PFX ## _pixels_tab[IDX][10] = PFX ## NUM ## _mc22_c; \ - c->PFX ## _pixels_tab[IDX][11] = PFX ## NUM ## _mc32_c; \ - c->PFX ## _pixels_tab[IDX][12] = PFX ## NUM ## _mc03_c; \ - c->PFX ## _pixels_tab[IDX][13] = PFX ## NUM ## _mc13_c; \ - c->PFX ## _pixels_tab[IDX][14] = PFX ## NUM ## _mc23_c; \ - c->PFX ## _pixels_tab[IDX][15] = PFX ## NUM ## _mc33_c - - dspfunc(put_qpel, 0, 16); - dspfunc(put_no_rnd_qpel, 0, 16); - - dspfunc(avg_qpel, 0, 16); - /* dspfunc(avg_no_rnd_qpel, 0, 16); */ - - dspfunc(put_qpel, 1, 8); - dspfunc(put_no_rnd_qpel, 1, 8); - - dspfunc(avg_qpel, 1, 8); - /* dspfunc(avg_no_rnd_qpel, 1, 8); */ - -#undef dspfunc - - c->put_mspel_pixels_tab[0]= ff_put_pixels8x8_c; - c->put_mspel_pixels_tab[1]= put_mspel8_mc10_c; - c->put_mspel_pixels_tab[2]= put_mspel8_mc20_c; - c->put_mspel_pixels_tab[3]= put_mspel8_mc30_c; - c->put_mspel_pixels_tab[4]= put_mspel8_mc02_c; - c->put_mspel_pixels_tab[5]= put_mspel8_mc12_c; - c->put_mspel_pixels_tab[6]= put_mspel8_mc22_c; - c->put_mspel_pixels_tab[7]= put_mspel8_mc32_c; - -#define SET_CMP_FUNC(name) \ - c->name[0]= name ## 16_c;\ - c->name[1]= name ## 8x8_c; +#define SET_CMP_FUNC(name) \ + c->name[0] = name ## 16_c; \ + c->name[1] = name ## 8x8_c; SET_CMP_FUNC(hadamard8_diff) - c->hadamard8_diff[4]= hadamard8_intra16_c; - c->hadamard8_diff[5]= hadamard8_intra8x8_c; + c->hadamard8_diff[4] = hadamard8_intra16_c; + c->hadamard8_diff[5] = hadamard8_intra8x8_c; SET_CMP_FUNC(dct_sad) SET_CMP_FUNC(dct_max) #if CONFIG_GPL SET_CMP_FUNC(dct264_sad) #endif - c->sad[0]= pix_abs16_c; - c->sad[1]= pix_abs8_c; - c->sse[0]= sse16_c; - c->sse[1]= sse8_c; - c->sse[2]= sse4_c; + c->sad[0] = pix_abs16_c; + c->sad[1] = pix_abs8_c; + c->sse[0] = sse16_c; + c->sse[1] = sse8_c; + c->sse[2] = sse4_c; SET_CMP_FUNC(quant_psnr) SET_CMP_FUNC(rd) SET_CMP_FUNC(bit) - c->vsad[0]= vsad16_c; - c->vsad[4]= vsad_intra16_c; - c->vsad[5]= vsad_intra8_c; - c->vsse[0]= vsse16_c; - c->vsse[4]= vsse_intra16_c; - c->vsse[5]= vsse_intra8_c; - c->nsse[0]= nsse16_c; - c->nsse[1]= nsse8_c; + c->vsad[0] = vsad16_c; + c->vsad[1] = vsad8_c; + c->vsad[4] = vsad_intra16_c; + c->vsad[5] = vsad_intra8_c; + c->vsse[0] = vsse16_c; + c->vsse[1] = vsse8_c; + c->vsse[4] = vsse_intra16_c; + c->vsse[5] = vsse_intra8_c; + c->nsse[0] = nsse16_c; + c->nsse[1] = nsse8_c; #if CONFIG_SNOW_DECODER || CONFIG_SNOW_ENCODER ff_dsputil_init_dwt(c); #endif - c->ssd_int8_vs_int16 = ssd_int8_vs_int16_c; - - c->add_bytes= add_bytes_c; - c->diff_bytes= diff_bytes_c; - c->add_hfyu_median_prediction= add_hfyu_median_prediction_c; - c->sub_hfyu_median_prediction= sub_hfyu_median_prediction_c; - c->add_hfyu_left_prediction = add_hfyu_left_prediction_c; - c->add_hfyu_left_prediction_bgr32 = add_hfyu_left_prediction_bgr32_c; - c->bswap_buf= bswap_buf; - c->bswap16_buf = bswap16_buf; - - c->try_8x8basis= try_8x8basis_c; - c->add_8x8basis= add_8x8basis_c; - - c->vector_clipf = vector_clipf_c; - c->scalarproduct_int16 = scalarproduct_int16_c; - c->scalarproduct_and_madd_int16 = scalarproduct_and_madd_int16_c; - c->vector_clip_int32 = vector_clip_int32_c; - - c->shrink[0]= av_image_copy_plane; - c->shrink[1]= ff_shrink22; - c->shrink[2]= ff_shrink44; - c->shrink[3]= ff_shrink88; - - c->add_pixels8 = add_pixels8_c; - -#undef FUNC -#undef FUNCC -#define FUNC(f, depth) f ## _ ## depth -#define FUNCC(f, depth) f ## _ ## depth ## _c - - c->draw_edges = FUNCC(draw_edges, 8); - c->clear_block = FUNCC(clear_block, 8); - c->clear_blocks = FUNCC(clear_blocks, 8); - -#define BIT_DEPTH_FUNCS(depth) \ - c->get_pixels = FUNCC(get_pixels, depth); - - switch (avctx->bits_per_raw_sample) { - case 9: - case 10: - case 12: - case 14: - BIT_DEPTH_FUNCS(16); - break; - default: - if(avctx->bits_per_raw_sample<=8 || avctx->codec_type != AVMEDIA_TYPE_VIDEO) { - BIT_DEPTH_FUNCS(8); - } - break; - } - - if (ARCH_ALPHA) ff_dsputil_init_alpha(c, avctx); if (ARCH_ARM) ff_dsputil_init_arm(c, avctx); - if (ARCH_BFIN) - ff_dsputil_init_bfin(c, avctx); if (ARCH_PPC) ff_dsputil_init_ppc(c, avctx); - if (ARCH_SH4) - ff_dsputil_init_sh4(c, avctx); - if (HAVE_VIS) - ff_dsputil_init_vis(c, avctx); if (ARCH_X86) ff_dsputil_init_x86(c, avctx); - - ff_init_scantable_permutation(c->idct_permutation, - c->idct_permutation_type); } av_cold void dsputil_init(DSPContext* c, AVCodecContext *avctx) diff --git a/libavcodec/dsputil.h b/libavcodec/dsputil.h index 0897c560b..9010729b9 100644 --- a/libavcodec/dsputil.h +++ b/libavcodec/dsputil.h @@ -23,127 +23,46 @@ /** * @file * DSP utils. - * note, many functions in here may use MMX which trashes the FPU state, it is - * absolutely necessary to call emms_c() between dsp & float/double code + * Note, many functions in here may use MMX which trashes the FPU state, it is + * absolutely necessary to call emms_c() between DSP & float/double code. */ #ifndef AVCODEC_DSPUTIL_H #define AVCODEC_DSPUTIL_H -#include "libavutil/intreadwrite.h" #include "avcodec.h" -#include "rnd_avg.h" -/* encoding scans */ -extern const uint8_t ff_alternate_horizontal_scan[64]; -extern const uint8_t ff_alternate_vertical_scan[64]; -extern const uint8_t ff_zigzag_direct[64]; -extern const uint8_t ff_zigzag248_direct[64]; +extern uint32_t ff_square_tab[512]; -/* pixel operations */ -#define MAX_NEG_CROP 1024 - -/* temporary */ -extern uint32_t ff_squareTbl[512]; -extern const uint8_t ff_cropTbl[256 + 2 * MAX_NEG_CROP]; - -void ff_put_pixels8x8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_pixels8x8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_pixels16x16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_pixels16x16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); - -/* RV40 functions */ -void ff_put_rv40_qpel16_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_rv40_qpel16_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_rv40_qpel8_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_rv40_qpel8_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); - -void ff_gmc_c(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int oy, - int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height); /* minimum alignment rules ;) -If you notice errors in the align stuff, need more alignment for some ASM code -for some CPU or need to use a function with less aligned data then send a mail -to the ffmpeg-devel mailing list, ... - -!warning These alignments might not match reality, (missing attribute((align)) -stuff somewhere possible). -I (Michael) did not check them, these are just the alignments which I think -could be reached easily ... - -!future video codecs might need functions with less strict alignment -*/ - -/* add and put pixel (decoding) */ -// blocksizes for op_pixels_func are 8x4,8x8 16x8 16x16 -//h for op_pixels_func is limited to {width/2, width} but never larger than 16 and never smaller than 4 -typedef void (*tpel_mc_func)(uint8_t *block/*align width (8 or 16)*/, const uint8_t *pixels/*align 1*/, int line_size, int w, int h); -typedef void (*qpel_mc_func)(uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, ptrdiff_t stride); - -typedef void (*op_fill_func)(uint8_t *block/*align width (8 or 16)*/, uint8_t value, int line_size, int h); - -#define DEF_OLD_QPEL(name)\ -void ff_put_ ## name (uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, ptrdiff_t stride);\ -void ff_put_no_rnd_ ## name (uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, ptrdiff_t stride);\ -void ff_avg_ ## name (uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, ptrdiff_t stride); - -DEF_OLD_QPEL(qpel16_mc11_old_c) -DEF_OLD_QPEL(qpel16_mc31_old_c) -DEF_OLD_QPEL(qpel16_mc12_old_c) -DEF_OLD_QPEL(qpel16_mc32_old_c) -DEF_OLD_QPEL(qpel16_mc13_old_c) -DEF_OLD_QPEL(qpel16_mc33_old_c) -DEF_OLD_QPEL(qpel8_mc11_old_c) -DEF_OLD_QPEL(qpel8_mc31_old_c) -DEF_OLD_QPEL(qpel8_mc12_old_c) -DEF_OLD_QPEL(qpel8_mc32_old_c) -DEF_OLD_QPEL(qpel8_mc13_old_c) -DEF_OLD_QPEL(qpel8_mc33_old_c) - -/* motion estimation */ -// h is limited to {width/2, width, 2*width} but never larger than 16 and never smaller than 2 -// although currently h<4 is not used as functions with width <8 are neither used nor implemented -typedef int (*me_cmp_func)(void /*MpegEncContext*/ *s, uint8_t *blk1/*align width (8 or 16)*/, uint8_t *blk2/*align 1*/, int line_size, int h)/* __attribute__ ((const))*/; - -/** - * Scantable. + * If you notice errors in the align stuff, need more alignment for some ASM code + * for some CPU or need to use a function with less aligned data then send a mail + * to the ffmpeg-devel mailing list, ... + * + * !warning These alignments might not match reality, (missing attribute((align)) + * stuff somewhere possible). + * I (Michael) did not check them, these are just the alignments which I think + * could be reached easily ... + * + * !future video codecs might need functions with less strict alignment */ -typedef struct ScanTable{ - const uint8_t *scantable; - uint8_t permutated[64]; - uint8_t raster_end[64]; -} ScanTable; -void ff_init_scantable(uint8_t *, ScanTable *st, const uint8_t *src_scantable); -void ff_init_scantable_permutation(uint8_t *idct_permutation, - int idct_permutation_type); +struct MpegEncContext; +/* Motion estimation: + * h is limited to { width / 2, width, 2 * width }, + * but never larger than 16 and never smaller than 2. + * Although currently h < 4 is not used as functions with + * width < 8 are neither used nor implemented. */ +typedef int (*me_cmp_func)(struct MpegEncContext *c, + uint8_t *blk1 /* align width (8 or 16) */, + uint8_t *blk2 /* align 1 */, int line_size, int h); /** * DSPContext. */ typedef struct DSPContext { - /* pixel ops : interface with DCT */ - void (*get_pixels)(int16_t *block/*align 16*/, const uint8_t *pixels/*align 8*/, int line_size); - void (*diff_pixels)(int16_t *block/*align 16*/, const uint8_t *s1/*align 8*/, const uint8_t *s2/*align 8*/, int stride); - void (*put_pixels_clamped)(const int16_t *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size); - void (*put_signed_pixels_clamped)(const int16_t *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size); - void (*add_pixels_clamped)(const int16_t *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size); - void (*add_pixels8)(uint8_t *pixels, int16_t *block, int line_size); - int (*sum_abs_dctelem)(int16_t *block/*align 16*/); - /** - * translational global motion compensation. - */ - void (*gmc1)(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int srcStride, int h, int x16, int y16, int rounder); - /** - * global motion compensation. - */ - void (*gmc )(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int ox, int oy, - int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height); - void (*clear_block)(int16_t *block/*align 16*/); - void (*clear_blocks)(int16_t *blocks/*align 16*/); - int (*pix_sum)(uint8_t * pix, int line_size); - int (*pix_norm1)(uint8_t * pix, int line_size); -// 16x16 8x8 4x4 2x2 16x8 8x4 4x2 8x16 4x8 2x4 + int (*sum_abs_dctelem)(int16_t *block /* align 16 */); me_cmp_func sad[6]; /* identical to pix_absAxA except additional void * */ me_cmp_func sse[6]; @@ -164,151 +83,25 @@ typedef struct DSPContext { me_cmp_func me_cmp[6]; me_cmp_func me_sub_cmp[6]; me_cmp_func mb_cmp[6]; - me_cmp_func ildct_cmp[6]; //only width 16 used - me_cmp_func frame_skip_cmp[6]; //only width 8 used - - int (*ssd_int8_vs_int16)(const int8_t *pix1, const int16_t *pix2, - int size); - - /** - * Thirdpel motion compensation with rounding (a+b+1)>>1. - * this is an array[12] of motion compensation functions for the 9 thirdpe - * positions
- * *pixels_tab[ xthirdpel + 4*ythirdpel ] - * @param block destination where the result is stored - * @param pixels source - * @param line_size number of bytes in a horizontal line of block - * @param h height - */ - tpel_mc_func put_tpel_pixels_tab[11]; //FIXME individual func ptr per width? - tpel_mc_func avg_tpel_pixels_tab[11]; //FIXME individual func ptr per width? - - qpel_mc_func put_qpel_pixels_tab[2][16]; - qpel_mc_func avg_qpel_pixels_tab[2][16]; - qpel_mc_func put_no_rnd_qpel_pixels_tab[2][16]; - qpel_mc_func put_mspel_pixels_tab[8]; + me_cmp_func ildct_cmp[6]; // only width 16 used + me_cmp_func frame_skip_cmp[6]; // only width 8 used me_cmp_func pix_abs[2][4]; - - /* huffyuv specific */ - void (*add_bytes)(uint8_t *dst/*align 16*/, uint8_t *src/*align 16*/, int w); - void (*diff_bytes)(uint8_t *dst/*align 16*/, const uint8_t *src1/*align 16*/, const uint8_t *src2/*align 1*/,int w); - /** - * subtract huffyuv's variant of median prediction - * note, this might read from src1[-1], src2[-1] - */ - void (*sub_hfyu_median_prediction)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int w, int *left, int *left_top); - void (*add_hfyu_median_prediction)(uint8_t *dst, const uint8_t *top, const uint8_t *diff, int w, int *left, int *left_top); - int (*add_hfyu_left_prediction)(uint8_t *dst, const uint8_t *src, int w, int left); - void (*add_hfyu_left_prediction_bgr32)(uint8_t *dst, const uint8_t *src, int w, int *red, int *green, int *blue, int *alpha); - /* this might write to dst[w] */ - void (*bswap_buf)(uint32_t *dst, const uint32_t *src, int w); - void (*bswap16_buf)(uint16_t *dst, const uint16_t *src, int len); - - /* assume len is a multiple of 8, and arrays are 16-byte aligned */ - void (*vector_clipf)(float *dst /* align 16 */, const float *src /* align 16 */, float min, float max, int len /* align 16 */); - - /* (I)DCT */ - void (*fdct)(int16_t *block/* align 16*/); - void (*fdct248)(int16_t *block/* align 16*/); - - /* IDCT really*/ - void (*idct)(int16_t *block/* align 16*/); - - /** - * block -> idct -> clip to unsigned 8 bit -> dest. - * (-1392, 0, 0, ...) -> idct -> (-174, -174, ...) -> put -> (0, 0, ...) - * @param line_size size in bytes of a horizontal line of dest - */ - void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, int16_t *block/*align 16*/); - - /** - * block -> idct -> add dest -> clip to unsigned 8 bit -> dest. - * @param line_size size in bytes of a horizontal line of dest - */ - void (*idct_add)(uint8_t *dest/*align 8*/, int line_size, int16_t *block/*align 16*/); - - /** - * idct input permutation. - * several optimized IDCTs need a permutated input (relative to the normal order of the reference - * IDCT) - * this permutation must be performed before the idct_put/add, note, normally this can be merged - * with the zigzag/alternate scan
- * an example to avoid confusion: - * - (->decode coeffs -> zigzag reorder -> dequant -> reference idct ->...) - * - (x -> reference dct -> reference idct -> x) - * - (x -> reference dct -> simple_mmx_perm = idct_permutation -> simple_idct_mmx -> x) - * - (->decode coeffs -> zigzag reorder -> simple_mmx_perm -> dequant -> simple_idct_mmx ->...) - */ - uint8_t idct_permutation[64]; - int idct_permutation_type; -#define FF_NO_IDCT_PERM 1 -#define FF_LIBMPEG2_IDCT_PERM 2 -#define FF_SIMPLE_IDCT_PERM 3 -#define FF_TRANSPOSE_IDCT_PERM 4 -#define FF_PARTTRANS_IDCT_PERM 5 -#define FF_SSE2_IDCT_PERM 6 - - int (*try_8x8basis)(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale); - void (*add_8x8basis)(int16_t rem[64], int16_t basis[64], int scale); -#define BASIS_SHIFT 16 -#define RECON_SHIFT 6 - - void (*draw_edges)(uint8_t *buf, int wrap, int width, int height, int w, int h, int sides); -#define EDGE_WIDTH 16 -#define EDGE_TOP 1 -#define EDGE_BOTTOM 2 - - void (*shrink[4])(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height); - - /** - * Calculate scalar product of two vectors. - * @param len length of vectors, should be multiple of 16 - */ - int32_t (*scalarproduct_int16)(const int16_t *v1, const int16_t *v2/*align 16*/, int len); - /* ape functions */ - /** - * Calculate scalar product of v1 and v2, - * and v1[i] += v3[i] * mul - * @param len length of vectors, should be multiple of 16 - */ - int32_t (*scalarproduct_and_madd_int16)(int16_t *v1/*align 16*/, const int16_t *v2, const int16_t *v3, int len, int mul); - - /** - * Clip each element in an array of int32_t to a given minimum and maximum value. - * @param dst destination array - * constraints: 16-byte aligned - * @param src source array - * constraints: 16-byte aligned - * @param min minimum value - * constraints: must be in the range [-(1 << 24), 1 << 24] - * @param max maximum value - * constraints: must be in the range [-(1 << 24), 1 << 24] - * @param len number of elements in the array - * constraints: multiple of 32 greater than zero - */ - void (*vector_clip_int32)(int32_t *dst, const int32_t *src, int32_t min, - int32_t max, unsigned int len); - - op_fill_func fill_block_tab[2]; } DSPContext; void ff_dsputil_static_init(void); -void ff_dsputil_init(DSPContext* p, AVCodecContext *avctx); +void ff_dsputil_init(DSPContext *p, AVCodecContext *avctx); void avpriv_dsputil_init(DSPContext* p, AVCodecContext *avctx); attribute_deprecated void dsputil_init(DSPContext* c, AVCodecContext *avctx); int ff_check_alignment(void); -void ff_set_cmp(DSPContext* c, me_cmp_func *cmp, int type); +void ff_set_cmp(DSPContext *c, me_cmp_func *cmp, int type); void ff_dsputil_init_alpha(DSPContext* c, AVCodecContext *avctx); -void ff_dsputil_init_arm(DSPContext* c, AVCodecContext *avctx); -void ff_dsputil_init_bfin(DSPContext* c, AVCodecContext *avctx); -void ff_dsputil_init_ppc(DSPContext* c, AVCodecContext *avctx); -void ff_dsputil_init_sh4(DSPContext* c, AVCodecContext *avctx); -void ff_dsputil_init_vis(DSPContext* c, AVCodecContext *avctx); -void ff_dsputil_init_x86(DSPContext* c, AVCodecContext *avctx); +void ff_dsputil_init_arm(DSPContext *c, AVCodecContext *avctx); +void ff_dsputil_init_ppc(DSPContext *c, AVCodecContext *avctx); +void ff_dsputil_init_x86(DSPContext *c, AVCodecContext *avctx); void ff_dsputil_init_dwt(DSPContext *c); diff --git a/libavcodec/dsputil_template.c b/libavcodec/dsputil_template.c deleted file mode 100644 index 96be7a6a6..000000000 --- a/libavcodec/dsputil_template.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * DSP utils - * Copyright (c) 2000, 2001 Fabrice Bellard - * Copyright (c) 2002-2004 Michael Niedermayer - * - * gmc & q-pel & 32/64 bit based MC by Michael Niedermayer - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * DSP utils - */ - -#include "bit_depth_template.c" - -#if BIT_DEPTH == 8 -/* draw the edges of width 'w' of an image of size width, height */ -//FIXME check that this is ok for mpeg4 interlaced -static void FUNCC(draw_edges)(uint8_t *p_buf, int p_wrap, int width, int height, int w, int h, int sides) -{ - pixel *buf = (pixel*)p_buf; - int wrap = p_wrap / sizeof(pixel); - pixel *ptr, *last_line; - int i; - - /* left and right */ - ptr = buf; - for(i=0;i>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - l1= (c&0x03030303UL)\ - + (d&0x03030303UL);\ - h1= ((c&0xFCFCFCFCUL)>>2)\ - + ((d&0xFCFCFCFCUL)>>2);\ - OP(*((uint32_t*)&dst[i*dst_stride]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ - a= AV_RN32(&src1[i*src_stride1+4]);\ - b= AV_RN32(&src2[i*src_stride2+4]);\ - c= AV_RN32(&src3[i*src_stride3+4]);\ - d= AV_RN32(&src4[i*src_stride4+4]);\ - l0= (a&0x03030303UL)\ - + (b&0x03030303UL)\ - + 0x02020202UL;\ - h0= ((a&0xFCFCFCFCUL)>>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - l1= (c&0x03030303UL)\ - + (d&0x03030303UL);\ - h1= ((c&0xFCFCFCFCUL)>>2)\ - + ((d&0xFCFCFCFCUL)>>2);\ - OP(*((uint32_t*)&dst[i*dst_stride+4]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ - }\ -}\ -\ -static inline void FUNC(OPNAME ## _no_rnd_pixels8_l4)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, const uint8_t *src3, const uint8_t *src4,\ - int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ - /* FIXME HIGH BIT DEPTH*/\ - int i;\ - for(i=0; i>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - l1= (c&0x03030303UL)\ - + (d&0x03030303UL);\ - h1= ((c&0xFCFCFCFCUL)>>2)\ - + ((d&0xFCFCFCFCUL)>>2);\ - OP(*((uint32_t*)&dst[i*dst_stride]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ - a= AV_RN32(&src1[i*src_stride1+4]);\ - b= AV_RN32(&src2[i*src_stride2+4]);\ - c= AV_RN32(&src3[i*src_stride3+4]);\ - d= AV_RN32(&src4[i*src_stride4+4]);\ - l0= (a&0x03030303UL)\ - + (b&0x03030303UL)\ - + 0x01010101UL;\ - h0= ((a&0xFCFCFCFCUL)>>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - l1= (c&0x03030303UL)\ - + (d&0x03030303UL);\ - h1= ((c&0xFCFCFCFCUL)>>2)\ - + ((d&0xFCFCFCFCUL)>>2);\ - OP(*((uint32_t*)&dst[i*dst_stride+4]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ - }\ -}\ -static inline void FUNC(OPNAME ## _pixels16_l4)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, const uint8_t *src3, const uint8_t *src4,\ - int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ - FUNC(OPNAME ## _pixels8_l4)(dst , src1 , src2 , src3 , src4 , dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\ - FUNC(OPNAME ## _pixels8_l4)(dst+8*sizeof(pixel), src1+8*sizeof(pixel), src2+8*sizeof(pixel), src3+8*sizeof(pixel), src4+8*sizeof(pixel), dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\ -}\ -static inline void FUNC(OPNAME ## _no_rnd_pixels16_l4)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, const uint8_t *src3, const uint8_t *src4,\ - int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ - FUNC(OPNAME ## _no_rnd_pixels8_l4)(dst , src1 , src2 , src3 , src4 , dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\ - FUNC(OPNAME ## _no_rnd_pixels8_l4)(dst+8*sizeof(pixel), src1+8*sizeof(pixel), src2+8*sizeof(pixel), src3+8*sizeof(pixel), src4+8*sizeof(pixel), dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\ -}\ -\ -static inline void FUNCC(OPNAME ## _pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)\ -{\ - /* FIXME HIGH BIT DEPTH */\ - int j;\ - for(j=0; j<2; j++){\ - int i;\ - const uint32_t a= AV_RN32(pixels );\ - const uint32_t b= AV_RN32(pixels+1);\ - uint32_t l0= (a&0x03030303UL)\ - + (b&0x03030303UL)\ - + 0x02020202UL;\ - uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - uint32_t l1,h1;\ -\ - pixels+=line_size;\ - for(i=0; i>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ - pixels+=line_size;\ - block +=line_size;\ - a= AV_RN32(pixels );\ - b= AV_RN32(pixels+1);\ - l0= (a&0x03030303UL)\ - + (b&0x03030303UL)\ - + 0x02020202UL;\ - h0= ((a&0xFCFCFCFCUL)>>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ - pixels+=line_size;\ - block +=line_size;\ - }\ - pixels+=4-line_size*(h+1);\ - block +=4-line_size*h;\ - }\ -}\ -\ -CALL_2X_PIXELS(FUNCC(OPNAME ## _pixels16_xy2), FUNCC(OPNAME ## _pixels8_xy2), 8*sizeof(pixel))\ - -#define op_avg(a, b) a = rnd_avg_pixel4(a, b) -#define op_put(a, b) a = b -#if BIT_DEPTH == 8 -#define put_no_rnd_pixels8_8_c put_pixels8_8_c -PIXOP2(avg, op_avg) -PIXOP2(put, op_put) -#endif -#undef op_avg -#undef op_put diff --git a/libavcodec/dv.c b/libavcodec/dv.c index ea05e9dd8..25f53a7c6 100644 --- a/libavcodec/dv.c +++ b/libavcodec/dv.c @@ -51,7 +51,7 @@ /* XXX: also include quantization */ RL_VLC_ELEM ff_dv_rl_vlc[1184]; -static inline void dv_calc_mb_coordinates(const DVprofile *d, int chan, int seq, int slot, +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 }; @@ -175,58 +175,54 @@ static const uint8_t dv100_qstep[16] = { static const uint8_t dv_quant_areas[4] = { 6, 21, 43, 64 }; -int ff_dv_init_dynamic_tables(const DVprofile *d) +int ff_dv_init_dynamic_tables(DVVideoContext *ctx, const AVDVProfile *d) { int j,i,c,s,p; uint32_t *factor1, *factor2; const int *iweight1, *iweight2; - if (!d->work_chunks[dv_work_pool_size(d)-1].buf_offset) { - p = i = 0; - for (c=0; cn_difchan; c++) { - for (s=0; sdifseg_size; s++) { - p += 6; - for (j=0; j<27; j++) { - p += !(j%3); - if (!(DV_PROFILE_IS_1080i50(d) && c != 0 && s == 11) && - !(DV_PROFILE_IS_720p50(d) && s > 9)) { - dv_calc_mb_coordinates(d, c, s, j, &d->work_chunks[i].mb_coordinates[0]); - d->work_chunks[i++].buf_offset = p; - } - p += 5; + p = i = 0; + for (c = 0; c < d->n_difchan; c++) { + for (s = 0; s < d->difseg_size; s++) { + p += 6; + for (j = 0; j < 27; j++) { + p += !(j % 3); + if (!(DV_PROFILE_IS_1080i50(d) && c != 0 && s == 11) && + !(DV_PROFILE_IS_720p50(d) && s > 9)) { + dv_calc_mb_coordinates(d, c, s, j, &ctx->work_chunks[i].mb_coordinates[0]); + ctx->work_chunks[i++].buf_offset = p; } + p += 5; } } } - if (!d->idct_factor[DV_PROFILE_IS_HD(d)?8191:5631]) { - factor1 = &d->idct_factor[0]; - factor2 = &d->idct_factor[DV_PROFILE_IS_HD(d)?4096:2816]; - if (d->height == 720) { - iweight1 = &ff_dv_iweight_720_y[0]; - iweight2 = &ff_dv_iweight_720_c[0]; - } else { - iweight1 = &ff_dv_iweight_1080_y[0]; - iweight2 = &ff_dv_iweight_1080_c[0]; - } - if (DV_PROFILE_IS_HD(d)) { - for (c = 0; c < 4; c++) { - for (s = 0; s < 16; s++) { - for (i = 0; i < 64; i++) { - *factor1++ = (dv100_qstep[s] << (c + 9)) * iweight1[i]; - *factor2++ = (dv100_qstep[s] << (c + 9)) * iweight2[i]; - } + factor1 = &ctx->idct_factor[0]; + factor2 = &ctx->idct_factor[DV_PROFILE_IS_HD(d) ? 4096 : 2816]; + if (d->height == 720) { + iweight1 = &ff_dv_iweight_720_y[0]; + iweight2 = &ff_dv_iweight_720_c[0]; + } else { + iweight1 = &ff_dv_iweight_1080_y[0]; + iweight2 = &ff_dv_iweight_1080_c[0]; + } + if (DV_PROFILE_IS_HD(d)) { + for (c = 0; c < 4; c++) { + for (s = 0; s < 16; s++) { + for (i = 0; i < 64; i++) { + *factor1++ = (dv100_qstep[s] << (c + 9)) * iweight1[i]; + *factor2++ = (dv100_qstep[s] << (c + 9)) * iweight2[i]; } } - } else { - iweight1 = &ff_dv_iweight_88[0]; - for (j = 0; j < 2; j++, iweight1 = &ff_dv_iweight_248[0]) { - for (s = 0; s < 22; s++) { - for (i = c = 0; c < 4; c++) { - for (; i < dv_quant_areas[c]; i++) { - *factor1 = iweight1[i] << (ff_dv_quant_shifts[s][c] + 1); - *factor2++ = (*factor1++) << 1; - } + } + } else { + iweight1 = &ff_dv_iweight_88[0]; + for (j = 0; j < 2; j++, iweight1 = &ff_dv_iweight_248[0]) { + for (s = 0; s < 22; s++) { + for (i = c = 0; c < 4; c++) { + for (; i < dv_quant_areas[c]; i++) { + *factor1 = iweight1[i] << (ff_dv_quant_shifts[s][c] + 1); + *factor2++ = (*factor1++) << 1; } } } @@ -239,7 +235,6 @@ int ff_dv_init_dynamic_tables(const DVprofile *d) av_cold int ff_dvvideo_init(AVCodecContext *avctx) { DVVideoContext *s = avctx->priv_data; - DSPContext dsp; static int done = 0; int i, j; @@ -296,30 +291,6 @@ av_cold int ff_dvvideo_init(AVCodecContext *avctx) ff_free_vlc(&dv_vlc); } - /* Generic DSP setup */ - memset(&dsp,0, sizeof(dsp)); - ff_dsputil_init(&dsp, avctx); - ff_set_cmp(&dsp, dsp.ildct_cmp, avctx->ildct_cmp); - s->get_pixels = dsp.get_pixels; - s->ildct_cmp = dsp.ildct_cmp[5]; - - /* 88DCT setup */ - s->fdct[0] = dsp.fdct; - s->idct_put[0] = dsp.idct_put; - for (i = 0; i < 64; i++) - s->dv_zigzag[0][i] = dsp.idct_permutation[ff_zigzag_direct[i]]; - - /* 248DCT setup */ - s->fdct[1] = dsp.fdct248; - s->idct_put[1] = ff_simple_idct248_put; // FIXME: need to add it to DSP - if (avctx->lowres){ - for (i = 0; i < 64; i++){ - int j = ff_zigzag248_direct[i]; - s->dv_zigzag[1][i] = dsp.idct_permutation[(j & 7) + (j & 8) * 4 + (j & 48) / 2]; - } - }else - memcpy(s->dv_zigzag[1], ff_zigzag248_direct, 64); - s->avctx = avctx; avctx->chroma_sample_location = AVCHROMA_LOC_TOPLEFT; diff --git a/libavcodec/dv.h b/libavcodec/dv.h index 73ceb7fe0..54ac06a65 100644 --- a/libavcodec/dv.h +++ b/libavcodec/dv.h @@ -32,8 +32,13 @@ #include "get_bits.h" #include "dv_profile.h" +typedef struct DVwork_chunk { + uint16_t buf_offset; + uint16_t mb_coordinates[5]; +} DVwork_chunk; + typedef struct DVVideoContext { - const DVprofile *sys; + const AVDVProfile *sys; AVFrame *frame; AVCodecContext *avctx; uint8_t *buf; @@ -44,6 +49,8 @@ typedef struct DVVideoContext { void (*fdct[2])(int16_t *block); void (*idct_put[2])(uint8_t *dest, int line_size, int16_t *block); me_cmp_func ildct_cmp; + DVwork_chunk work_chunks[4 * 12 * 27]; + uint32_t idct_factor[2 * 4 * 16 * 64]; } DVVideoContext; enum dv_section_type { @@ -88,10 +95,10 @@ enum dv_pack_type { extern RL_VLC_ELEM ff_dv_rl_vlc[1184]; -int ff_dv_init_dynamic_tables(const DVprofile *d); +int ff_dv_init_dynamic_tables(DVVideoContext *s, const AVDVProfile *d); int ff_dvvideo_init(AVCodecContext *avctx); -static inline int dv_work_pool_size(const DVprofile *d) +static inline int dv_work_pool_size(const AVDVProfile *d) { int size = d->n_difchan*d->difseg_size*27; if (DV_PROFILE_IS_1080i50(d)) diff --git a/libavcodec/dv_profile.c b/libavcodec/dv_profile.c index e73af29c8..58ce79f26 100644 --- a/libavcodec/dv_profile.c +++ b/libavcodec/dv_profile.c @@ -18,26 +18,17 @@ #include +#include "config.h" + #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "libavutil/pixdesc.h" #include "avcodec.h" #include "dv_profile.h" +#include "dv_profile_internal.h" -static DVwork_chunk work_chunks_dv25pal [1*12*27]; -static DVwork_chunk work_chunks_dv25pal411[1*12*27]; -static DVwork_chunk work_chunks_dv25ntsc [1*10*27]; -static DVwork_chunk work_chunks_dv50pal [2*12*27]; -static DVwork_chunk work_chunks_dv50ntsc [2*10*27]; -static DVwork_chunk work_chunks_dv100palp [2*12*27]; -static DVwork_chunk work_chunks_dv100ntscp[2*10*27]; -static DVwork_chunk work_chunks_dv100pali [4*12*27]; -static DVwork_chunk work_chunks_dv100ntsci[4*10*27]; - -static uint32_t dv_idct_factor_sd [2*2*22*64]; -static uint32_t dv_idct_factor_hd1080[2*4*16*64]; -static uint32_t dv_idct_factor_hd720 [2*4*16*64]; +#if CONFIG_DVPROFILE static const uint8_t dv_audio_shuffle525[10][9] = { { 0, 30, 60, 20, 50, 80, 10, 40, 70 }, /* 1st channel */ @@ -78,7 +69,7 @@ static const uint8_t block_sizes_dv100[8] = { 80, 80, 80, 80, 80, 80, 64, 64, }; -static const DVprofile dv_profiles[] = { +static const AVDVProfile dv_profiles[] = { { .dsf = 0, .video_stype = 0x0, .frame_size = 120000, /* IEC 61834, SMPTE-314M - 525/60 (NTSC) */ @@ -89,8 +80,6 @@ static const DVprofile dv_profiles[] = { .height = 480, .width = 720, .sar = {{8, 9}, {32, 27}}, - .work_chunks = &work_chunks_dv25ntsc[0], - .idct_factor = &dv_idct_factor_sd[0], .pix_fmt = AV_PIX_FMT_YUV411P, .bpm = 6, .block_sizes = block_sizes_dv2550, @@ -109,8 +98,6 @@ static const DVprofile dv_profiles[] = { .height = 576, .width = 720, .sar = {{16, 15}, {64, 45}}, - .work_chunks = &work_chunks_dv25pal[0], - .idct_factor = &dv_idct_factor_sd[0], .pix_fmt = AV_PIX_FMT_YUV420P, .bpm = 6, .block_sizes = block_sizes_dv2550, @@ -129,8 +116,6 @@ static const DVprofile dv_profiles[] = { .height = 576, .width = 720, .sar = {{16, 15}, {64, 45}}, - .work_chunks = &work_chunks_dv25pal411[0], - .idct_factor = &dv_idct_factor_sd[0], .pix_fmt = AV_PIX_FMT_YUV411P, .bpm = 6, .block_sizes = block_sizes_dv2550, @@ -149,8 +134,6 @@ static const DVprofile dv_profiles[] = { .height = 480, .width = 720, .sar = {{8, 9}, {32, 27}}, - .work_chunks = &work_chunks_dv50ntsc[0], - .idct_factor = &dv_idct_factor_sd[0], .pix_fmt = AV_PIX_FMT_YUV422P, .bpm = 6, .block_sizes = block_sizes_dv2550, @@ -169,8 +152,6 @@ static const DVprofile dv_profiles[] = { .height = 576, .width = 720, .sar = {{16, 15}, {64, 45}}, - .work_chunks = &work_chunks_dv50pal[0], - .idct_factor = &dv_idct_factor_sd[0], .pix_fmt = AV_PIX_FMT_YUV422P, .bpm = 6, .block_sizes = block_sizes_dv2550, @@ -189,8 +170,6 @@ static const DVprofile dv_profiles[] = { .height = 1080, .width = 1280, .sar = {{1, 1}, {3, 2}}, - .work_chunks = &work_chunks_dv100ntsci[0], - .idct_factor = &dv_idct_factor_hd1080[0], .pix_fmt = AV_PIX_FMT_YUV422P, .bpm = 8, .block_sizes = block_sizes_dv100, @@ -209,8 +188,6 @@ static const DVprofile dv_profiles[] = { .height = 1080, .width = 1440, .sar = {{1, 1}, {4, 3}}, - .work_chunks = &work_chunks_dv100pali[0], - .idct_factor = &dv_idct_factor_hd1080[0], .pix_fmt = AV_PIX_FMT_YUV422P, .bpm = 8, .block_sizes = block_sizes_dv100, @@ -229,8 +206,6 @@ static const DVprofile dv_profiles[] = { .height = 720, .width = 960, .sar = {{1, 1}, {4, 3}}, - .work_chunks = &work_chunks_dv100ntscp[0], - .idct_factor = &dv_idct_factor_hd720[0], .pix_fmt = AV_PIX_FMT_YUV422P, .bpm = 8, .block_sizes = block_sizes_dv100, @@ -249,8 +224,6 @@ static const DVprofile dv_profiles[] = { .height = 720, .width = 960, .sar = {{1, 1}, {4, 3}}, - .work_chunks = &work_chunks_dv100palp[0], - .idct_factor = &dv_idct_factor_hd720[0], .pix_fmt = AV_PIX_FMT_YUV422P, .bpm = 8, .block_sizes = block_sizes_dv100, @@ -269,8 +242,6 @@ static const DVprofile dv_profiles[] = { .height = 576, .width = 720, .sar = {{16, 15}, {64, 45}}, - .work_chunks = &work_chunks_dv25pal[0], - .idct_factor = &dv_idct_factor_sd[0], .pix_fmt = AV_PIX_FMT_YUV420P, .bpm = 6, .block_sizes = block_sizes_dv2550, @@ -281,9 +252,23 @@ static const DVprofile dv_profiles[] = { } }; -const DVprofile* avpriv_dv_frame_profile2(AVCodecContext* codec, const DVprofile *sys, - const uint8_t* frame, unsigned buf_size) +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), + p->time_base.den, p->time_base.num); + } +} + +#endif /* CONFIG_DVPROFILE */ + +const AVDVProfile* avpriv_dv_frame_profile2(AVCodecContext* codec, const AVDVProfile *sys, + const uint8_t* frame, unsigned buf_size) +{ +#if CONFIG_DVPROFILE int i, dsf, stype; if(buf_size < DV_PROFILE_BYTES) @@ -316,45 +301,45 @@ const DVprofile* avpriv_dv_frame_profile2(AVCodecContext* codec, const DVprofile /* hack for trac issue #217, dv files created with QuickTime 3 */ if ((frame[3] & 0x7f) == 0x3f && frame[80 * 5 + 48 + 3] == 0xff) return &dv_profiles[dsf]; +#endif return NULL; } -const DVprofile* avpriv_dv_frame_profile(const DVprofile *sys, - const uint8_t* frame, unsigned buf_size) +const AVDVProfile *av_dv_frame_profile(const AVDVProfile *sys, + const uint8_t* frame, unsigned buf_size) { return avpriv_dv_frame_profile2(NULL, sys, frame, buf_size); } -const DVprofile* avpriv_dv_codec_profile(AVCodecContext* codec) +const AVDVProfile *av_dv_codec_profile(int width, int height, + enum AVPixelFormat pix_fmt) { +#if CONFIG_DVPROFILE int i; - int w, h; - - if (codec->coded_width || codec->coded_height) { - w = codec->coded_width; - h = codec->coded_height; - } else { - w = codec->width; - h = codec->height; - } for (i=0; ipix_fmt == dv_profiles[i].pix_fmt && - w == dv_profiles[i].width) - return &dv_profiles[i]; + if (height == dv_profiles[i].height && + pix_fmt == dv_profiles[i].pix_fmt && + width == dv_profiles[i].width) + return &dv_profiles[i]; +#endif return NULL; } -void ff_dv_print_profiles(void *logctx, int loglevel) +#if LIBAVCODEC_VERSION_MAJOR < 56 +const AVDVProfile *avpriv_dv_frame_profile(const AVDVProfile *sys, + const uint8_t* frame, unsigned buf_size) { - int i; - for (i = 0; i < FF_ARRAY_ELEMS(dv_profiles); i++) { - const DVprofile *p = &dv_profiles[i]; - av_log(logctx, loglevel, "Frame size: %dx%d; pixel format: %s, " - "framerate: %d/%d\n", p->width, p->height, av_get_pix_fmt_name(p->pix_fmt), - p->time_base.den, p->time_base.num); - } + return av_dv_frame_profile(sys, frame, buf_size); } + +const AVDVProfile *avpriv_dv_codec_profile(AVCodecContext *codec) +{ + if (codec->coded_width || codec->coded_height) { + return av_dv_codec_profile(codec->coded_width, codec->coded_height, codec->pix_fmt); + } else + return av_dv_codec_profile(codec->width, codec->height, codec->pix_fmt); +} +#endif diff --git a/libavcodec/dv_profile.h b/libavcodec/dv_profile.h index 8f0faf315..a2ef608b5 100644 --- a/libavcodec/dv_profile.h +++ b/libavcodec/dv_profile.h @@ -29,18 +29,13 @@ determine the profile */ #define DV_PROFILE_BYTES (6*80) /* 6 DIF blocks */ -typedef struct DVwork_chunk { - uint16_t buf_offset; - uint16_t mb_coordinates[5]; -} DVwork_chunk; - /* - * DVprofile is used to express the differences between various + * AVDVProfile is used to express the differences between various * DV flavors. For now it's primarily used for differentiating * 525/60 and 625/50, but the plans are to use it for various * DV specs as well (e.g. SMPTE314M vs. IEC 61834). */ -typedef struct DVprofile { +typedef struct AVDVProfile { int dsf; /* value of the dsf in the DV header */ int video_stype; /* stype for VAUX source pack */ int frame_size; /* total size of one frame in bytes */ @@ -51,8 +46,6 @@ typedef struct DVprofile { int height; /* picture height in pixels */ int width; /* picture width in pixels */ AVRational sar[2]; /* sample aspect ratios for 4:3 and 16:9 */ - DVwork_chunk *work_chunks; /* each thread gets its own chunk of frame to work on */ - uint32_t *idct_factor; /* set of iDCT factor tables */ enum AVPixelFormat pix_fmt; /* picture pixel format */ int bpm; /* blocks per macroblock */ const uint8_t *block_sizes; /* AC block sizes, in bits */ @@ -62,17 +55,30 @@ typedef struct DVprofile { int audio_samples_dist[5]; /* how many samples are supposed to be */ /* in each frame in a 5 frames window */ const uint8_t (*audio_shuffle)[9]; /* PCM shuffling table */ -} DVprofile; +} AVDVProfile; -const DVprofile* avpriv_dv_frame_profile(const DVprofile *sys, - const uint8_t* frame, unsigned buf_size); -const DVprofile* avpriv_dv_frame_profile2(AVCodecContext* codec, const DVprofile *sys, - const uint8_t* frame, unsigned buf_size); -const DVprofile* avpriv_dv_codec_profile(AVCodecContext* codec); +const AVDVProfile* avpriv_dv_frame_profile2(AVCodecContext* codec, const AVDVProfile *sys, + const uint8_t* frame, unsigned buf_size); +#if LIBAVCODEC_VERSION_MAJOR < 56 +const AVDVProfile *avpriv_dv_frame_profile(const AVDVProfile *sys, + const uint8_t* frame, unsigned buf_size); +const AVDVProfile *avpriv_dv_codec_profile(AVCodecContext* codec); +#endif /** - * Print all allowed DV profiles into logctx at specified logging level. + * Get a DV profile for the provided compressed frame. + * + * @param sys the profile used for the previous frame, may be NULL + * @param frame the compressed data buffer + * @param buf_size size of the buffer in bytes + * @return the DV profile for the supplied data or NULL on failure */ -void ff_dv_print_profiles(void *logctx, int loglevel); +const AVDVProfile *av_dv_frame_profile(const AVDVProfile *sys, + const uint8_t *frame, unsigned buf_size); + +/** + * Get a DV profile for the provided stream parameters. + */ +const AVDVProfile *av_dv_codec_profile(int width, int height, enum AVPixelFormat pix_fmt); #endif /* AVCODEC_DV_PROFILE_H */ diff --git a/libavcodec/dv_profile_internal.h b/libavcodec/dv_profile_internal.h new file mode 100644 index 000000000..97720416a --- /dev/null +++ b/libavcodec/dv_profile_internal.h @@ -0,0 +1,27 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DV_PROFILE_INTERNAL_H +#define AVCODEC_DV_PROFILE_INTERNAL_H + +/** + * Print all allowed DV profiles into logctx at specified logging level. + */ +void ff_dv_print_profiles(void *logctx, int loglevel); + +#endif /* AVCODEC_DV_PROFILE_INTERNAL_H */ diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index 551a1a205..a40da768d 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -18,11 +18,12 @@ * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + #include "avcodec.h" -#include "dsputil.h" #include "get_bits.h" #include "bytestream.h" #include "libavutil/colorspace.h" +#include "libavutil/opt.h" #define DVBSUB_PAGE_SEGMENT 0x10 #define DVBSUB_REGION_SEGMENT 0x11 @@ -31,7 +32,7 @@ #define DVBSUB_DISPLAYDEFINITION_SEGMENT 0x14 #define DVBSUB_DISPLAY_SEGMENT 0x80 -#define cm (ff_cropTbl + MAX_NEG_CROP) +#define cm (ff_crop_tab + MAX_NEG_CROP) #ifdef DEBUG #if 0 @@ -227,11 +228,15 @@ typedef struct DVBSubDisplayDefinition { } DVBSubDisplayDefinition; typedef struct DVBSubContext { + AVClass *class; int composition_id; int ancillary_id; int version; int time_out; + int compute_edt; /**< if 1 end display time calculated using pts + if 0 (Default) calculated using time out */ + int64_t prev_start; DVBSubRegion *region_list; DVBSubCLUT *clut_list; DVBSubObject *object_list; @@ -381,6 +386,7 @@ static av_cold int dvbsub_init_decoder(AVCodecContext *avctx) } ctx->version = -1; + ctx->prev_start = AV_NOPTS_VALUE; default_clut.id = -1; default_clut.next = NULL; @@ -757,8 +763,97 @@ static int dvbsub_read_8bit_string(uint8_t *destbuf, int dbuf_len, return pixels_read; } +static void save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub, int *got_output) +{ + DVBSubContext *ctx = avctx->priv_data; + DVBSubRegionDisplay *display; + DVBSubDisplayDefinition *display_def = ctx->display_definition; + DVBSubRegion *region; + AVSubtitleRect *rect; + DVBSubCLUT *clut; + uint32_t *clut_table; + int i; + int offset_x=0, offset_y=0; + if (display_def) { + offset_x = display_def->x; + offset_y = display_def->y; + } + + /* Not touching AVSubtitles again*/ + if(sub->num_rects) { + avpriv_request_sample(ctx, "Different Version of Segment asked Twice\n"); + return; + } + for (display = ctx->display_list; display; display = display->next) { + region = get_region(ctx, display->region_id); + if (region && region->dirty) + sub->num_rects++; + } + + if(ctx->compute_edt == 0) { + sub->end_display_time = ctx->time_out * 1000; + *got_output = 1; + } else if (ctx->prev_start != AV_NOPTS_VALUE) { + sub->end_display_time = av_rescale_q((sub->pts - ctx->prev_start ), AV_TIME_BASE_Q, (AVRational){ 1, 1000 }) - 1; + *got_output = 1; + } + if (sub->num_rects > 0) { + + sub->rects = av_mallocz_array(sizeof(*sub->rects), sub->num_rects); + for(i=0; inum_rects; i++) + sub->rects[i] = av_mallocz(sizeof(*sub->rects[i])); + + i = 0; + + for (display = ctx->display_list; display; display = display->next) { + region = get_region(ctx, display->region_id); + + if (!region) + continue; + + if (!region->dirty) + continue; + + rect = sub->rects[i]; + rect->x = display->x_pos + offset_x; + rect->y = display->y_pos + offset_y; + rect->w = region->width; + rect->h = region->height; + rect->nb_colors = (1 << region->depth); + rect->type = SUBTITLE_BITMAP; + rect->pict.linesize[0] = region->width; + + clut = get_clut(ctx, region->clut); + + if (!clut) + clut = &default_clut; + + switch (region->depth) { + case 2: + clut_table = clut->clut4; + break; + case 8: + clut_table = clut->clut256; + break; + case 4: + default: + clut_table = clut->clut16; + break; + } + + rect->pict.data[1] = av_mallocz(AVPALETTE_SIZE); + memcpy(rect->pict.data[1], clut_table, (1 << region->depth) * sizeof(uint32_t)); + + rect->pict.data[0] = av_malloc(region->buf_size); + memcpy(rect->pict.data[0], region->pbuf, region->buf_size); + + i++; + } + } +} + static void dvbsub_parse_pixel_data_block(AVCodecContext *avctx, DVBSubObjectDisplay *display, const uint8_t *buf, int buf_size, int top_bottom, int non_mod) { @@ -1148,7 +1243,7 @@ static void dvbsub_parse_region_segment(AVCodecContext *avctx, } static void dvbsub_parse_page_segment(AVCodecContext *avctx, - const uint8_t *buf, int buf_size) + const uint8_t *buf, int buf_size, AVSubtitle *sub, int *got_output) { DVBSubContext *ctx = avctx->priv_data; DVBSubRegionDisplay *display; @@ -1167,13 +1262,18 @@ static void dvbsub_parse_page_segment(AVCodecContext *avctx, version = ((*buf)>>4) & 15; page_state = ((*buf++) >> 2) & 3; - if (ctx->version != version) { + if (ctx->version == version) { + return; + } ctx->time_out = timeout; ctx->version = version; av_dlog(avctx, "Page time out %ds, state %d\n", ctx->time_out, page_state); + if(ctx->compute_edt == 1) + save_subtitle_set(avctx, sub, got_output); + if (page_state == 1 || page_state == 2) { delete_regions(ctx); delete_objects(ctx); @@ -1220,7 +1320,6 @@ static void dvbsub_parse_page_segment(AVCodecContext *avctx, av_free(display); } - } } @@ -1364,92 +1463,17 @@ static void dvbsub_parse_display_definition_segment(AVCodecContext *avctx, } } -static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, - int buf_size, AVSubtitle *sub) +static void dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, + int buf_size, AVSubtitle *sub,int *got_output) { DVBSubContext *ctx = avctx->priv_data; - DVBSubDisplayDefinition *display_def = ctx->display_definition; - DVBSubRegion *region; - DVBSubRegionDisplay *display; - AVSubtitleRect *rect; - DVBSubCLUT *clut; - uint32_t *clut_table; - int i; - int offset_x=0, offset_y=0; - - sub->end_display_time = ctx->time_out * 1000; - - if (display_def) { - offset_x = display_def->x; - offset_y = display_def->y; - } - - sub->num_rects = 0; - for (display = ctx->display_list; display; display = display->next) - { - region = get_region(ctx, display->region_id); - if (region && region->dirty) - sub->num_rects++; - } - - if (sub->num_rects > 0){ - sub->rects = av_mallocz(sizeof(*sub->rects) * sub->num_rects); - for(i=0; inum_rects; i++) - sub->rects[i] = av_mallocz(sizeof(*sub->rects[i])); - - i = 0; - - for (display = ctx->display_list; display; display = display->next) { - region = get_region(ctx, display->region_id); - - if (!region) - continue; - - if (!region->dirty) - continue; - - rect = sub->rects[i]; - rect->x = display->x_pos + offset_x; - rect->y = display->y_pos + offset_y; - rect->w = region->width; - rect->h = region->height; - rect->nb_colors = (1 << region->depth); - rect->type = SUBTITLE_BITMAP; - rect->pict.linesize[0] = region->width; - - clut = get_clut(ctx, region->clut); - - if (!clut) - clut = &default_clut; - - switch (region->depth) { - case 2: - clut_table = clut->clut4; - break; - case 8: - clut_table = clut->clut256; - break; - case 4: - default: - clut_table = clut->clut16; - break; - } - - rect->pict.data[1] = av_mallocz(AVPALETTE_SIZE); - memcpy(rect->pict.data[1], clut_table, (1 << region->depth) * sizeof(uint32_t)); - - rect->pict.data[0] = av_malloc(region->buf_size); - memcpy(rect->pict.data[0], region->pbuf, region->buf_size); - - i++; - } - } + if(ctx->compute_edt == 0) + save_subtitle_set(avctx, sub, got_output); #ifdef DEBUG save_display_set(ctx); #endif - return 1; } static int dvbsub_decode(AVCodecContext *avctx, @@ -1465,7 +1489,7 @@ static int dvbsub_decode(AVCodecContext *avctx, int page_id; int segment_length; int i; - int ret; + int ret = 0; int got_segment = 0; av_dlog(avctx, "DVB sub packet:\n"); @@ -1495,16 +1519,21 @@ static int dvbsub_decode(AVCodecContext *avctx, segment_length = AV_RB16(p); p += 2; + if (avctx->debug & FF_DEBUG_STARTCODE) { + av_log(avctx, AV_LOG_DEBUG, "segment_type:%d page_id:%d segment_length:%d\n", segment_type, page_id, segment_length); + } + if (p_end - p < segment_length) { av_dlog(avctx, "incomplete or broken packet"); - return -1; + ret = -1; + goto end; } if (page_id == ctx->composition_id || page_id == ctx->ancillary_id || ctx->composition_id == -1 || ctx->ancillary_id == -1) { switch (segment_type) { case DVBSUB_PAGE_SEGMENT: - dvbsub_parse_page_segment(avctx, p, segment_length); + dvbsub_parse_page_segment(avctx, p, segment_length, sub, data_size); got_segment |= 1; break; case DVBSUB_REGION_SEGMENT: @@ -1513,7 +1542,7 @@ static int dvbsub_decode(AVCodecContext *avctx, break; case DVBSUB_CLUT_SEGMENT: ret = dvbsub_parse_clut_segment(avctx, p, segment_length); - if (ret < 0) return ret; + if (ret < 0) goto end; got_segment |= 4; break; case DVBSUB_OBJECT_SEGMENT: @@ -1524,7 +1553,7 @@ static int dvbsub_decode(AVCodecContext *avctx, 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); + dvbsub_display_end_segment(avctx, p, segment_length, sub, data_size); got_segment |= 16; break; default: @@ -1538,12 +1567,34 @@ static int dvbsub_decode(AVCodecContext *avctx, } // Some streams do not send a display segment but if we have all the other // segments then we need no further data. - if (got_segment == 15 && sub) - *data_size = dvbsub_display_end_segment(avctx, p, 0, sub); + if (got_segment == 15) { + av_log(avctx, AV_LOG_DEBUG, "Missing display_end_segment, emulating\n"); + dvbsub_display_end_segment(avctx, p, 0, sub, data_size); + } + +end: + if(ret < 0) { + *data_size = 0; + avsubtitle_free(sub); + return ret; + } else { + if(ctx->compute_edt == 1 ) + FFSWAP(int64_t, ctx->prev_start, sub->pts); + } return p - buf; } +static const AVOption options[] = { + {"compute_edt", "compute end of time using pts or timeout", offsetof(DVBSubContext, compute_edt), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 1, 0}, + {NULL} +}; +static const AVClass dvbsubdec_class = { + .class_name = "DVB Sub Decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_dvbsub_decoder = { .name = "dvbsub", @@ -1554,4 +1605,5 @@ AVCodec ff_dvbsub_decoder = { .init = dvbsub_init_decoder, .close = dvbsub_close_decoder, .decode = dvbsub_decode, + .priv_class = &dvbsubdec_class, }; diff --git a/libavcodec/dvdata.c b/libavcodec/dvdata.c index a3be7fd7a..ace01ffda 100644 --- a/libavcodec/dvdata.c +++ b/libavcodec/dvdata.c @@ -28,6 +28,19 @@ #include "dvdata.h" +/* Specific zigzag scan for 248 idct. NOTE that unlike the + * specification, we interleave the fields */ +const uint8_t ff_dv_zigzag248_direct[64] = { + 0, 8, 1, 9, 16, 24, 2, 10, + 17, 25, 32, 40, 48, 56, 33, 41, + 18, 26, 3, 11, 4, 12, 19, 27, + 34, 42, 49, 57, 50, 58, 35, 43, + 20, 28, 5, 13, 6, 14, 21, 29, + 36, 44, 51, 59, 52, 60, 37, 45, + 22, 30, 7, 15, 23, 31, 38, 46, + 53, 61, 54, 62, 39, 47, 55, 63, +}; + /* unquant tables (not used directly) */ const uint8_t ff_dv_quant_shifts[22][4] = { { 3,3,4,4 }, diff --git a/libavcodec/dvdata.h b/libavcodec/dvdata.h index 8c120df72..0932d3ad1 100644 --- a/libavcodec/dvdata.h +++ b/libavcodec/dvdata.h @@ -21,6 +21,8 @@ #include +extern const uint8_t ff_dv_zigzag248_direct[64]; + extern const uint8_t ff_dv_quant_shifts[22][4]; extern const uint8_t ff_dv_quant_offset[4]; diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c index 727f91d65..fbd158f7d 100644 --- a/libavcodec/dvdec.c +++ b/libavcodec/dvdec.c @@ -37,8 +37,10 @@ #include "libavutil/avassert.h" #include "libavutil/internal.h" +#include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "idctdsp.h" #include "internal.h" #include "get_bits.h" #include "put_bits.h" @@ -58,6 +60,32 @@ typedef struct BlockInfo { static const int dv_iweight_bits = 14; +static av_cold int dvvideo_decode_init(AVCodecContext *avctx) +{ + DVVideoContext *s = avctx->priv_data; + IDCTDSPContext idsp; + int i; + + memset(&idsp,0, sizeof(idsp)); + ff_idctdsp_init(&idsp, avctx); + + for (i = 0; i < 64; i++) + s->dv_zigzag[0][i] = idsp.idct_permutation[ff_zigzag_direct[i]]; + + if (avctx->lowres){ + for (i = 0; i < 64; i++){ + int j = ff_dv_zigzag248_direct[i]; + s->dv_zigzag[1][i] = idsp.idct_permutation[(j & 7) + (j & 8) * 4 + (j & 48) / 2]; + } + }else + memcpy(s->dv_zigzag[1], ff_dv_zigzag248_direct, sizeof(s->dv_zigzag[1])); + + s->idct_put[0] = idsp.idct_put; + s->idct_put[1] = ff_simple_idct248_put; + + return ff_dvvideo_init(avctx); +} + /* decode AC coefficients */ static void dv_decode_ac(GetBitContext *gb, BlockInfo *mb, int16_t *block) { @@ -179,12 +207,12 @@ 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->sys->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->sys->idct_factor[(class1 == 3)*2*22*64 + dct_mode*22*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; @@ -321,13 +349,23 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, DVVideoContext *s = avctx->priv_data; const uint8_t* vsc_pack; int apt, is16_9, ret; + const AVDVProfile *sys; - s->sys = avpriv_dv_frame_profile2(avctx, s->sys, buf, buf_size); - if (!s->sys || buf_size < s->sys->frame_size || ff_dv_init_dynamic_tables(s->sys)) { + sys = avpriv_dv_frame_profile2(avctx, s->sys, buf, buf_size); + if (!sys || buf_size < sys->frame_size) { av_log(avctx, AV_LOG_ERROR, "could not find dv frame profile\n"); return -1; /* NOTE: we only accept several full frames */ } + if (sys != s->sys) { + ret = ff_dv_init_dynamic_tables(s, sys); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error initializing the work tables.\n"); + return ret; + } + s->sys = sys; + } + s->frame = data; s->frame->key_frame = 1; s->frame->pict_type = AV_PICTURE_TYPE_I; @@ -338,22 +376,26 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, 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[2] & 0x07) == 0x02 || (!apt && (vsc_pack[2] & 0x07) == 0x07); + ff_set_sar(avctx, s->sys->sar[is16_9]); + } + if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0) return ret; s->frame->interlaced_frame = 1; s->frame->top_field_first = 0; - /* Determine the codec's sample_aspect ratio and field order from the packet */ - vsc_pack = buf + 80*5 + 48 + 5; + /* Determine the codec's field order from the packet */ if ( *vsc_pack == dv_video_control ) { - apt = buf[4] & 0x07; - is16_9 = (vsc_pack[2] & 0x07) == 0x02 || (!apt && (vsc_pack[2] & 0x07) == 0x07); - avctx->sample_aspect_ratio = s->sys->sar[is16_9]; s->frame->top_field_first = !(vsc_pack[3] & 0x40); } s->buf = buf; - avctx->execute(avctx, dv_decode_video_segment, s->sys->work_chunks, NULL, + avctx->execute(avctx, dv_decode_video_segment, s->work_chunks, NULL, dv_work_pool_size(s->sys), sizeof(DVwork_chunk)); emms_c(); @@ -370,7 +412,7 @@ AVCodec ff_dvvideo_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_DVVIDEO, .priv_data_size = sizeof(DVVideoContext), - .init = ff_dvvideo_init, + .init = dvvideo_decode_init, .decode = dvvideo_decode_frame, .capabilities = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS, .max_lowres = 3, diff --git a/libavcodec/dvdsubdec.c b/libavcodec/dvdsubdec.c index 637f3e614..39b0e25a1 100644 --- a/libavcodec/dvdsubdec.c +++ b/libavcodec/dvdsubdec.c @@ -18,9 +18,9 @@ * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + #include "avcodec.h" #include "get_bits.h" -#include "dsputil.h" #include "internal.h" #include "libavutil/attributes.h" @@ -46,7 +46,7 @@ typedef struct DVDSubContext static void yuv_a_to_rgba(const uint8_t *ycbcr, const uint8_t *alpha, uint32_t *rgba, int num_values) { - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; uint8_t r, g, b; int i, y, cb, cr; int r_add, g_add, b_add; @@ -345,7 +345,7 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, w = x2 - x1 + 1; if (w < 0) w = 0; - h = y2 - y1; + h = y2 - y1 + 1; if (h < 0) h = 0; if (w > 0 && h > 0) { @@ -462,10 +462,13 @@ static int find_smallest_bounding_rectangle(AVSubtitle *s) } #ifdef DEBUG +#define ALPHA_MIX(A,BACK,FORE) (((255-(A)) * (BACK) + (A) * (FORE)) / 255) static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h, uint32_t *rgba_palette) { - int x, y, v; + int x, y, alpha; + uint32_t v; + int back[3] = {0, 255, 0}; /* green background */ FILE *f; f = fopen(filename, "w"); @@ -480,9 +483,10 @@ static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h, 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); + alpha = v >> 24; + putc(ALPHA_MIX(alpha, back[0], (v >> 16) & 0xff), f); + putc(ALPHA_MIX(alpha, back[1], (v >> 8) & 0xff), f); + putc(ALPHA_MIX(alpha, back[2], (v >> 0) & 0xff), f); } } fclose(f); @@ -552,7 +556,7 @@ static int dvdsub_decode(AVCodecContext *avctx, sub->start_display_time, sub->end_display_time); ppm_save(ppm_name, sub->rects[0]->pict.data[0], - sub->rects[0]->w, sub->rects[0]->h, sub->rects[0]->pict.data[1]); + sub->rects[0]->w, sub->rects[0]->h, (uint32_t*) sub->rects[0]->pict.data[1]); } #endif diff --git a/libavcodec/dvdsubenc.c b/libavcodec/dvdsubenc.c index 8130b74a7..ced09dd5e 100644 --- a/libavcodec/dvdsubenc.c +++ b/libavcodec/dvdsubenc.c @@ -24,9 +24,12 @@ #include "libavutil/avassert.h" #include "libavutil/bprint.h" #include "libavutil/imgutils.h" +#include "libavutil/opt.h" typedef struct { + AVClass *class; uint32_t global_palette[16]; + int even_rows_fix; } DVDSubtitleContext; // ncnt is the nibble counter @@ -259,6 +262,7 @@ static int encode_dvd_subtitles(AVCodecContext *avctx, AVSubtitleRect vrect; uint8_t *vrect_data = NULL; int x2, y2; + int forced = 0; if (rects == 0 || h->rects == NULL) return AVERROR(EINVAL); @@ -267,6 +271,12 @@ static int encode_dvd_subtitles(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "Bitmap subtitle required\n"); return AVERROR(EINVAL); } + /* Mark this subtitle forced if any of the rectangles is forced. */ + for (i = 0; i < rects; i++) + if ((h->rects[i]->flags & AV_SUBTITLE_FLAG_FORCED) != 0) { + forced = 1; + break; + } vrect = *h->rects[0]; if (rects > 1) { @@ -338,6 +348,13 @@ static int encode_dvd_subtitles(AVCodecContext *avctx, dvd_encode_rle(&q, vrect.pict.data[0] + vrect.w, vrect.w * 2, vrect.w, vrect.h >> 1, cmap); + if (dvdc->even_rows_fix && (vrect.h & 1)) { + // Work-around for some players that want the height to be even. + vrect.h++; + *q++ = 0x00; // 0x00 0x00 == empty row, i.e. fully transparent + *q++ = 0x00; + } + // set data packet size qq = outbuf + 2; bytestream_put_be16(&qq, q - outbuf); @@ -371,7 +388,7 @@ static int encode_dvd_subtitles(AVCodecContext *avctx, bytestream_put_be16(&q, offset1); bytestream_put_be16(&q, offset2); - *q++ = 0x01; // start command + *q++ = forced ? 0x00 : 0x01; // start command *q++ = 0xff; // terminating command // send stop display command last @@ -383,7 +400,7 @@ static int encode_dvd_subtitles(AVCodecContext *avctx, qq = outbuf; bytestream_put_be16(&qq, q - outbuf); - av_log(NULL, AV_LOG_DEBUG, "subtitle_packet size=%td\n", q - outbuf); + av_log(NULL, AV_LOG_DEBUG, "subtitle_packet size=%"PTRDIFF_SPECIFIER"\n", q - outbuf); ret = q - outbuf; fail: @@ -432,6 +449,20 @@ static int dvdsub_encode(AVCodecContext *avctx, return ret; } +#define OFFSET(x) offsetof(DVDSubtitleContext, x) +#define SE AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + {"even_rows_fix", "Make number of rows even (workaround for some players)", OFFSET(even_rows_fix), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, SE}, + { NULL }, +}; + +static const AVClass dvdsubenc_class = { + .class_name = "VOBSUB subtitle encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_dvdsub_encoder = { .name = "dvdsub", .long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"), @@ -439,5 +470,6 @@ AVCodec ff_dvdsub_encoder = { .id = AV_CODEC_ID_DVD_SUBTITLE, .init = dvdsub_init, .encode_sub = dvdsub_encode, + .priv_class = &dvdsubenc_class, .priv_data_size = sizeof(DVDSubtitleContext), }; diff --git a/libavcodec/dvenc.c b/libavcodec/dvenc.c index 3efe53a83..aeb4a3325 100644 --- a/libavcodec/dvenc.c +++ b/libavcodec/dvenc.c @@ -28,14 +28,25 @@ #include "libavutil/pixdesc.h" #include "config.h" #include "avcodec.h" +#include "dsputil.h" +#include "fdctdsp.h" #include "internal.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) { - if (!avpriv_dv_codec_profile(avctx)) { + DVVideoContext *s = avctx->priv_data; + DSPContext dsp; + FDCTDSPContext fdsp; + PixblockDSPContext pdsp; + int ret; + + s->sys = avpriv_dv_codec_profile(avctx); + if (!s->sys) { av_log(avctx, AV_LOG_ERROR, "Found no DV profile for %ix%i %s video. " "Valid DV profiles are:\n", avctx->width, avctx->height, av_get_pix_fmt_name(avctx->pix_fmt)); @@ -46,6 +57,11 @@ static av_cold int dvvideo_encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "DVCPRO HD encoding is not supported.\n"); return AVERROR_PATCHWELCOME; } + ret = ff_dv_init_dynamic_tables(s, s->sys); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error initializing work tables.\n"); + return ret; + } avctx->coded_frame = av_frame_alloc(); if (!avctx->coded_frame) @@ -53,6 +69,18 @@ static av_cold int dvvideo_encode_init(AVCodecContext *avctx) dv_vlc_map_tableinit(); + memset(&dsp,0, sizeof(dsp)); + ff_dsputil_init(&dsp, avctx); + ff_fdctdsp_init(&fdsp, avctx); + ff_pixblockdsp_init(&pdsp, avctx); + ff_set_cmp(&dsp, dsp.ildct_cmp, avctx->ildct_cmp); + + s->get_pixels = pdsp.get_pixels; + s->ildct_cmp = dsp.ildct_cmp[5]; + + s->fdct[0] = fdsp.fdct; + s->fdct[1] = fdsp.fdct248; + return ff_dvvideo_init(avctx); } @@ -249,7 +277,7 @@ static av_always_inline int dv_init_enc_block(EncBlockInfo* bi, uint8_t *data, i } bi->mb[0] = blk[0]; - zigzag_scan = bi->dct_mode ? ff_zigzag248_direct : ff_zigzag_direct; + zigzag_scan = bi->dct_mode ? ff_dv_zigzag248_direct : ff_zigzag_direct; weight = bi->dct_mode ? dv_weight_248 : dv_weight_88; for (area = 0; area < 4; area++) { @@ -665,9 +693,6 @@ static int dvvideo_encode_frame(AVCodecContext *c, AVPacket *pkt, DVVideoContext *s = c->priv_data; int ret; - s->sys = avpriv_dv_codec_profile(c); - if (!s->sys || ff_dv_init_dynamic_tables(s->sys)) - return -1; if ((ret = ff_alloc_packet2(c, pkt, s->sys->frame_size)) < 0) return ret; @@ -677,7 +702,7 @@ static int dvvideo_encode_frame(AVCodecContext *c, AVPacket *pkt, c->coded_frame->pict_type = AV_PICTURE_TYPE_I; s->buf = pkt->data; - c->execute(c, dv_encode_video_segment, s->sys->work_chunks, NULL, + c->execute(c, dv_encode_video_segment, s->work_chunks, NULL, dv_work_pool_size(s->sys), sizeof(DVwork_chunk)); emms_c(); diff --git a/libavcodec/dxtory.c b/libavcodec/dxtory.c index afadcbb68..1a59ae7a0 100644 --- a/libavcodec/dxtory.c +++ b/libavcodec/dxtory.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" @@ -269,18 +271,18 @@ static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic, slice_size = bytestream2_get_le32(&gb); if (slice_size > src_size - off) { av_log(avctx, AV_LOG_ERROR, - "invalid slice size %d (only %d bytes left)\n", + "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 %d\n", slice_size); + 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 %d instead of %d\n", + "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); @@ -350,18 +352,19 @@ static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic, slice_size = bytestream2_get_le32(&gb); if (slice_size > src_size - off) { av_log(avctx, AV_LOG_ERROR, - "invalid slice size %d (only %d bytes left)\n", + "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 %d\n", slice_size); + 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 %d instead of %d\n", + "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); @@ -448,18 +451,18 @@ static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic, slice_height = (next_y & ~3) - (cur_y & ~3); if (slice_size > src_size - off) { av_log(avctx, AV_LOG_ERROR, - "invalid slice size %d (only %d bytes left)\n", + "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 %d\n", slice_size); + 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 %d instead of %d\n", + "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); @@ -552,18 +555,18 @@ static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic, slice_height = (next_y & ~1) - (cur_y & ~1); if (slice_size > src_size - off) { av_log(avctx, AV_LOG_ERROR, - "invalid slice size %d (only %d bytes left)\n", + "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 %d\n", slice_size); + 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 %d instead of %d\n", + "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); @@ -645,18 +648,18 @@ static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic, slice_size = bytestream2_get_le32(&gb); if (slice_size > src_size - off) { av_log(avctx, AV_LOG_ERROR, - "invalid slice size %d (only %d bytes left)\n", + "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 %d\n", slice_size); + 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 %d instead of %d\n", + "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); @@ -728,7 +731,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0); break; default: - avpriv_request_sample(avctx, "Frame header %X", AV_RB32(src)); + avpriv_request_sample(avctx, "Frame header %"PRIX32, AV_RB32(src)); return AVERROR_PATCHWELCOME; } diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index 1b29f2081..c1c768140 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -30,15 +30,15 @@ #include "mpegvideo.h" #include "dxva2_internal.h" -void *ff_dxva2_get_surface(const Picture *picture) +void *ff_dxva2_get_surface(const AVFrame *frame) { - return picture->f.data[3]; + return frame->data[3]; } unsigned ff_dxva2_get_surface_index(const struct dxva_context *ctx, - const Picture *picture) + const AVFrame *frame) { - void *surface = ff_dxva2_get_surface(picture); + void *surface = ff_dxva2_get_surface(frame); unsigned i; for (i = 0; i < ctx->surface_count; i++) @@ -91,7 +91,7 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx, return result; } -int ff_dxva2_common_end_frame(AVCodecContext *avctx, Picture *pic, +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 *, @@ -107,7 +107,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, Picture *pic, do { hr = IDirectXVideoDecoder_BeginFrame(ctx->decoder, - ff_dxva2_get_surface(pic), + ff_dxva2_get_surface(frame), NULL); if (hr == E_PENDING) av_usleep(2000); diff --git a/libavcodec/dxva2.h b/libavcodec/dxva2.h index ac39e0691..2639d89d9 100644 --- a/libavcodec/dxva2.h +++ b/libavcodec/dxva2.h @@ -49,6 +49,7 @@ */ #define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for DXVA2 and old UVD/UVD+ ATI video cards +#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for DXVA2 and old Intel GPUs with ClearVideo interface /** * This structure is used to provides the necessary configurations and data diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c index 02d3f5413..117418895 100644 --- a/libavcodec/dxva2_h264.c +++ b/libavcodec/dxva2_h264.c @@ -23,6 +23,7 @@ #include "dxva2_internal.h" #include "h264.h" #include "h264data.h" +#include "mpegutils.h" struct dxva2_picture_context { DXVA_PicParams_H264 pp; @@ -44,19 +45,19 @@ static void fill_picture_entry(DXVA_PicEntry_H264 *pic, static void fill_picture_parameters(struct dxva_context *ctx, const H264Context *h, DXVA_PicParams_H264 *pp) { - const Picture *current_picture = h->cur_pic_ptr; + const H264Picture *current_picture = h->cur_pic_ptr; int i, j; memset(pp, 0, sizeof(*pp)); /* Configure current picture */ fill_picture_entry(&pp->CurrPic, - ff_dxva2_get_surface_index(ctx, current_picture), + ff_dxva2_get_surface_index(ctx, ¤t_picture->f), h->picture_structure == PICT_BOTTOM_FIELD); /* Configure the set of references */ pp->UsedForReferenceFlags = 0; pp->NonExistingFrameFlags = 0; for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) { - const Picture *r; + const H264Picture *r; if (j < h->short_ref_count) { r = h->short_ref[j++]; } else { @@ -66,7 +67,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), + ff_dxva2_get_surface_index(ctx, &r->f), r->long_ref != 0); if ((r->reference & PICT_TOP_FIELD) && r->field_poc[0] != INT_MAX) @@ -115,6 +116,8 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context pp->bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8; if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) pp->Reserved16Bits = 0; + else if (ctx->workaround & 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++; @@ -194,8 +197,18 @@ static void fill_slice_short(DXVA_Slice_H264_Short *slice, slice->wBadSliceChopping = 0; } +static int get_refpic_index(const DXVA_PicParams_H264 *pp, int surface_index) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) { + if ((pp->RefFrameList[i].bPicEntry & 0x7f) == surface_index) + return i; + } + return 0x7f; +} + static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, - unsigned position, unsigned size) + const DXVA_PicParams_H264 *pp, unsigned position, unsigned size) { const H264Context *h = avctx->priv_data; struct dxva_context *ctx = avctx->hwaccel_context; @@ -226,10 +239,14 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, unsigned i; for (i = 0; i < FF_ARRAY_ELEMS(slice->RefPicList[list]); i++) { if (list < h->list_count && i < h->ref_count[list]) { - const Picture *r = &h->ref_list[list][i]; + const H264Picture *r = &h->ref_list[list][i]; unsigned plane; - fill_picture_entry(&slice->RefPicList[list][i], - ff_dxva2_get_surface_index(ctx, r), + unsigned index; + if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) + index = ff_dxva2_get_surface_index(ctx, &r->f); + else + index = get_refpic_index(pp, ff_dxva2_get_surface_index(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; @@ -277,7 +294,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, const H264Context *h = avctx->priv_data; const unsigned mb_count = h->mb_width * h->mb_height; struct dxva_context *ctx = avctx->hwaccel_context; - const Picture *current_picture = h->cur_pic_ptr; + 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; uint8_t *dxva_data, *current, *end; @@ -397,7 +414,7 @@ static int dxva2_h264_decode_slice(AVCodecContext *avctx, { const H264Context *h = avctx->priv_data; struct dxva_context *ctx = avctx->hwaccel_context; - const Picture *current_picture = h->cur_pic_ptr; + const H264Picture *current_picture = h->cur_pic_ptr; struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; unsigned position; @@ -414,7 +431,7 @@ static int dxva2_h264_decode_slice(AVCodecContext *avctx, position, size); else fill_slice_long(avctx, &ctx_pic->slice_long[ctx_pic->slice_count], - position, size); + &ctx_pic->pp, position, size); ctx_pic->slice_count++; if (h->slice_type != AV_PICTURE_TYPE_I && h->slice_type != AV_PICTURE_TYPE_SI) @@ -431,7 +448,7 @@ static int dxva2_h264_end_frame(AVCodecContext *avctx) if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) return -1; - ret = ff_dxva2_common_end_frame(avctx, h->cur_pic_ptr, + 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); @@ -448,5 +465,5 @@ AVHWAccel ff_h264_dxva2_hwaccel = { .start_frame = dxva2_h264_start_frame, .decode_slice = dxva2_h264_decode_slice, .end_frame = dxva2_h264_end_frame, - .priv_data_size = sizeof(struct dxva2_picture_context), + .frame_priv_data_size = sizeof(struct dxva2_picture_context), }; diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h index 8a454c129..427c1ffdf 100644 --- a/libavcodec/dxva2_internal.h +++ b/libavcodec/dxva2_internal.h @@ -35,10 +35,10 @@ #include "avcodec.h" #include "mpegvideo.h" -void *ff_dxva2_get_surface(const Picture *picture); +void *ff_dxva2_get_surface(const AVFrame *frame); unsigned ff_dxva2_get_surface_index(const struct dxva_context *, - const Picture *picture); + const AVFrame *frame); int ff_dxva2_commit_buffer(AVCodecContext *, struct dxva_context *, DXVA2_DecodeBufferDesc *, @@ -46,7 +46,7 @@ int ff_dxva2_commit_buffer(AVCodecContext *, struct dxva_context *, unsigned mb_count); -int ff_dxva2_common_end_frame(AVCodecContext *, Picture *, +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 *, diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c index e2f6b709a..ee832bc21 100644 --- a/libavcodec/dxva2_mpeg2.c +++ b/libavcodec/dxva2_mpeg2.c @@ -20,7 +20,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/log.h" #include "dxva2_internal.h" +#include "mpegutils.h" #define MAX_SLICES 1024 struct dxva2_picture_context { @@ -42,14 +44,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); + pp->wDecodedPictureIndex = ff_dxva2_get_surface_index(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); + pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(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); + pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, s->next_picture.f); else pp->wBackwardRefPictureIndex = 0xffff; pp->wPicWidthInMBminus1 = s->mb_width - 1; @@ -108,7 +110,7 @@ static void fill_quantization_matrices(AVCodecContext *avctx, for (i = 0; i < 4; i++) qm->bNewQmatrix[i] = 1; for (i = 0; i < 64; i++) { - int n = s->dsp.idct_permutation[ff_zigzag_direct[i]]; + int n = s->idsp.idct_permutation[ff_zigzag_direct[i]]; qm->Qmatrix[0][i] = s->intra_matrix[n]; qm->Qmatrix[1][i] = s->inter_matrix[n]; qm->Qmatrix[2][i] = s->chroma_intra_matrix[n]; @@ -232,9 +234,11 @@ static int dxva2_mpeg2_decode_slice(AVCodecContext *avctx, s->current_picture_ptr->hwaccel_picture_private; unsigned position; - if (ctx_pic->slice_count >= MAX_SLICES) + if (ctx_pic->slice_count >= MAX_SLICES) { + avpriv_request_sample(avctx, "%d slices in dxva2", + ctx_pic->slice_count); return -1; - + } if (!ctx_pic->bitstream) ctx_pic->bitstream = buffer; ctx_pic->bitstream_size += size; @@ -254,7 +258,7 @@ static int dxva2_mpeg2_end_frame(AVCodecContext *avctx) if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) return -1; - ret = ff_dxva2_common_end_frame(avctx, s->current_picture_ptr, + ret = ff_dxva2_common_end_frame(avctx, s->current_picture_ptr->f, &ctx_pic->pp, sizeof(ctx_pic->pp), &ctx_pic->qm, sizeof(ctx_pic->qm), commit_bitstream_and_slice_buffer); @@ -271,5 +275,5 @@ AVHWAccel ff_mpeg2_dxva2_hwaccel = { .start_frame = dxva2_mpeg2_start_frame, .decode_slice = dxva2_mpeg2_decode_slice, .end_frame = dxva2_mpeg2_end_frame, - .priv_data_size = sizeof(struct dxva2_picture_context), + .frame_priv_data_size = sizeof(struct dxva2_picture_context), }; diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c index a86d7cdc2..b2b5cedc1 100644 --- a/libavcodec/dxva2_vc1.c +++ b/libavcodec/dxva2_vc1.c @@ -21,6 +21,7 @@ */ #include "dxva2_internal.h" +#include "mpegutils.h" #include "vc1.h" #include "vc1data.h" @@ -43,20 +44,20 @@ static void fill_picture_parameters(AVCodecContext *avctx, // determine if intensity compensation is needed if (s->pict_type == AV_PICTURE_TYPE_P) { if ((v->fcm == ILACE_FRAME && v->intcomp) || (v->fcm != ILACE_FRAME && v->mv_mode == MV_PMODE_INTENSITY_COMP)) { - if (v->lumscale != 32 || v->lumshift != 0 || (s->picture_structure != PICT_FRAME && (v->lumscale2 != 32 && v->lumshift2 != 0))) + if (v->lumscale != 32 || v->lumshift != 0 || (s->picture_structure != PICT_FRAME && (v->lumscale2 != 32 || v->lumshift2 != 0))) intcomp = 1; } } memset(pp, 0, sizeof(*pp)); pp->wDecodedPictureIndex = - pp->wDeblockedPictureIndex = ff_dxva2_get_surface_index(ctx, current_picture); + pp->wDeblockedPictureIndex = ff_dxva2_get_surface_index(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); + pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(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); + pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, s->next_picture.f); else pp->wBackwardRefPictureIndex = 0xffff; if (v->profile == PROFILE_ADVANCED) { @@ -168,7 +169,7 @@ static void fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice, slice->dwSliceDataLocation = position; slice->bStartCodeBitOffset = 0; slice->bReservedBits = (s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type) ? v->bfraction_lut_index + 9 : 0; - slice->wMBbitOffset = v->p_frame_skipped ? 0xffff : get_bits_count(&s->gb); + slice->wMBbitOffset = v->p_frame_skipped ? 0xffff : get_bits_count(&s->gb) + (avctx->codec_id == AV_CODEC_ID_VC1 ? 32 : 0); slice->wNumberMBsInSlice = s->mb_width * s->mb_height; /* XXX We assume 1 slice */ slice->wQuantizerScaleCode = v->pq; slice->wBadSliceChopping = 0; @@ -282,7 +283,7 @@ static int dxva2_vc1_end_frame(AVCodecContext *avctx) if (ctx_pic->bitstream_size <= 0) return -1; - ret = ff_dxva2_common_end_frame(avctx, v->s.current_picture_ptr, + ret = ff_dxva2_common_end_frame(avctx, v->s.current_picture_ptr->f, &ctx_pic->pp, sizeof(ctx_pic->pp), NULL, 0, commit_bitstream_and_slice_buffer); @@ -300,7 +301,7 @@ AVHWAccel ff_wmv3_dxva2_hwaccel = { .start_frame = dxva2_vc1_start_frame, .decode_slice = dxva2_vc1_decode_slice, .end_frame = dxva2_vc1_end_frame, - .priv_data_size = sizeof(struct dxva2_picture_context), + .frame_priv_data_size = sizeof(struct dxva2_picture_context), }; #endif @@ -312,5 +313,5 @@ AVHWAccel ff_vc1_dxva2_hwaccel = { .start_frame = dxva2_vc1_start_frame, .decode_slice = dxva2_vc1_decode_slice, .end_frame = dxva2_vc1_end_frame, - .priv_data_size = sizeof(struct dxva2_picture_context), + .frame_priv_data_size = sizeof(struct dxva2_picture_context), }; diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c index 994461753..e1d61f68b 100644 --- a/libavcodec/eac3enc.c +++ b/libavcodec/eac3enc.c @@ -251,14 +251,13 @@ void ff_eac3_output_frame_header(AC3EncodeContext *s) } -#if CONFIG_EAC3_ENCODER AVCodec ff_eac3_encoder = { .name = "eac3", .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52 E-AC-3"), .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_EAC3, .priv_data_size = sizeof(AC3EncodeContext), - .init = ff_ac3_encode_init, + .init = ff_ac3_float_encode_init, .encode2 = ff_ac3_float_encode_frame, .close = ff_ac3_encode_close, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, @@ -267,4 +266,3 @@ AVCodec ff_eac3_encoder = { .channel_layouts = ff_ac3_channel_layouts, .defaults = ac3_defaults, }; -#endif diff --git a/libavcodec/eamad.c b/libavcodec/eamad.c index 2d34d35a5..f4944ee83 100644 --- a/libavcodec/eamad.c +++ b/libavcodec/eamad.c @@ -29,9 +29,11 @@ */ #include "avcodec.h" +#include "bswapdsp.h" #include "get_bits.h" #include "aandcttab.h" #include "eaidct.h" +#include "idctdsp.h" #include "internal.h" #include "mpeg12.h" #include "mpeg12data.h" @@ -44,7 +46,9 @@ typedef struct MadContext { AVCodecContext *avctx; - DSPContext dsp; + BlockDSPContext bdsp; + BswapDSPContext bbdsp; + IDCTDSPContext idsp; AVFrame *last_frame; GetBitContext gb; void *bitstream_buf; @@ -61,9 +65,11 @@ static av_cold int decode_init(AVCodecContext *avctx) MadContext *s = avctx->priv_data; s->avctx = avctx; avctx->pix_fmt = AV_PIX_FMT_YUV420P; - ff_dsputil_init(&s->dsp, avctx); - ff_init_scantable_permutation(s->dsp.idct_permutation, FF_NO_IDCT_PERM); - ff_init_scantable(s->dsp.idct_permutation, &s->scantable, ff_zigzag_direct); + ff_blockdsp_init(&s->bdsp, avctx); + ff_bswapdsp_init(&s->bbdsp); + ff_idctdsp_init(&s->idsp, avctx); + ff_init_scantable_permutation(s->idsp.idct_permutation, FF_NO_IDCT_PERM); + ff_init_scantable(s->idsp.idct_permutation, &s->scantable, ff_zigzag_direct); ff_mpeg12_init_vlcs(); s->last_frame = av_frame_alloc(); @@ -195,7 +201,7 @@ static int decode_motion(GetBitContext *gb) static int decode_mb(MadContext *s, AVFrame *frame, int inter) { int mv_map = 0; - int mv_x, mv_y; + int av_uninit(mv_x), av_uninit(mv_y); int j; if (inter) { @@ -213,7 +219,7 @@ static int decode_mb(MadContext *s, AVFrame *frame, int inter) if (s->last_frame->data[0]) comp_block(s, frame, s->mb_x, s->mb_y, j, mv_x, mv_y, add); } else { - s->dsp.clear_block(s->block); + s->bdsp.clear_block(s->block); if(decode_block_intra(s, s->block) < 0) return -1; idct_put(s, frame, s->block, s->mb_x, s->mb_y, j); @@ -295,7 +301,8 @@ static int decode_frame(AVCodecContext *avctx, buf_end - buf); if (!s->bitstream_buf) return AVERROR(ENOMEM); - s->dsp.bswap16_buf(s->bitstream_buf, (const uint16_t*)buf, (buf_end-buf)/2); + s->bbdsp.bswap16_buf(s->bitstream_buf, (const uint16_t *) buf, + (buf_end - buf) / 2); memset((uint8_t*)s->bitstream_buf + (buf_end-buf), 0, FF_INPUT_BUFFER_PADDING_SIZE); init_get_bits(&s->gb, s->bitstream_buf, 8*(buf_end-buf)); diff --git a/libavcodec/eatgq.c b/libavcodec/eatgq.c index 2950d055d..100abe92a 100644 --- a/libavcodec/eatgq.c +++ b/libavcodec/eatgq.c @@ -32,7 +32,7 @@ #define BITSTREAM_READER_LE #include "get_bits.h" #include "bytestream.h" -#include "dsputil.h" +#include "idctdsp.h" #include "aandcttab.h" #include "eaidct.h" #include "internal.h" diff --git a/libavcodec/eatqi.c b/libavcodec/eatqi.c index 387456a93..f22a75320 100644 --- a/libavcodec/eatqi.c +++ b/libavcodec/eatqi.c @@ -27,15 +27,19 @@ */ #include "avcodec.h" +#include "blockdsp.h" +#include "bswapdsp.h" #include "get_bits.h" #include "aandcttab.h" #include "eaidct.h" +#include "idctdsp.h" #include "internal.h" #include "mpeg12.h" #include "mpegvideo.h" typedef struct TqiContext { MpegEncContext s; + BswapDSPContext bsdsp; void *bitstream_buf; unsigned int bitstream_buf_size; DECLARE_ALIGNED(16, int16_t, block)[6][64]; @@ -46,9 +50,11 @@ static av_cold int tqi_decode_init(AVCodecContext *avctx) TqiContext *t = avctx->priv_data; MpegEncContext *s = &t->s; s->avctx = avctx; - ff_dsputil_init(&s->dsp, avctx); - ff_init_scantable_permutation(s->dsp.idct_permutation, FF_NO_IDCT_PERM); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); + ff_blockdsp_init(&s->bdsp, avctx); + ff_bswapdsp_init(&t->bsdsp); + ff_idctdsp_init(&s->idsp, avctx); + ff_init_scantable_permutation(s->idsp.idct_permutation, FF_NO_IDCT_PERM); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); s->qscale = 1; avctx->time_base = (AVRational){1, 15}; avctx->pix_fmt = AV_PIX_FMT_YUV420P; @@ -59,7 +65,7 @@ static av_cold int tqi_decode_init(AVCodecContext *avctx) static int tqi_decode_mb(MpegEncContext *s, int16_t (*block)[64]) { int n; - s->dsp.clear_blocks(block[0]); + s->bdsp.clear_blocks(block[0]); for (n=0; n<6; n++) if (ff_mpeg1_decode_block_intra(s, block[n], n) < 0) return -1; @@ -122,7 +128,8 @@ static int tqi_decode_frame(AVCodecContext *avctx, buf_end - buf); if (!t->bitstream_buf) return AVERROR(ENOMEM); - s->dsp.bswap_buf(t->bitstream_buf, (const uint32_t*)buf, (buf_end-buf)/4); + 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; diff --git a/libavcodec/elbg.c b/libavcodec/elbg.c index 5c7018b47..9bbb6d88a 100644 --- a/libavcodec/elbg.c +++ b/libavcodec/elbg.c @@ -51,7 +51,7 @@ typedef struct{ int *codebook; cell **cells; int *utility; - int *utility_inc; + int64_t *utility_inc; int *nearest_cb; int *points; AVLFG *rand_state; @@ -108,9 +108,18 @@ static int get_high_utility_cell(elbg_data *elbg) { int i=0; /* Using linear search, do binary if it ever turns to be speed critical */ - int r = av_lfg_get(elbg->rand_state)%elbg->utility_inc[elbg->numCB-1] + 1; - while (elbg->utility_inc[i] < r) + uint64_t r; + + if (elbg->utility_inc[elbg->numCB-1] < INT_MAX) { + r = av_lfg_get(elbg->rand_state) % (unsigned int)elbg->utility_inc[elbg->numCB-1] + 1; + } else { + r = av_lfg_get(elbg->rand_state); + r = (av_lfg_get(elbg->rand_state) + (r<<32)) % elbg->utility_inc[elbg->numCB-1] + 1; + } + + while (elbg->utility_inc[i] < r) { i++; + } av_assert2(elbg->cells[i]); @@ -227,7 +236,8 @@ static void shift_codebook(elbg_data *elbg, int *indexes, static void evaluate_utility_inc(elbg_data *elbg) { - int i, inc=0; + int i; + int64_t inc=0; for (i=0; i < elbg->numCB; i++) { if (elbg->numCB*elbg->utility[i] > elbg->error) @@ -333,7 +343,7 @@ void avpriv_init_elbg(int *points, int dim, int numpoints, int *codebook, 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)); + int *temp_points = av_malloc_array(dim, (numpoints/8)*sizeof(int)); for (i=0; idim = dim; elbg->numCB = numCB; elbg->codebook = codebook; - elbg->cells = av_malloc(numCB*sizeof(cell *)); - elbg->utility = av_malloc(numCB*sizeof(int)); + elbg->cells = av_malloc_array(numCB, sizeof(cell *)); + elbg->utility = av_malloc_array(numCB, sizeof(int)); elbg->nearest_cb = closest_cb; elbg->points = points; - elbg->utility_inc = av_malloc(numCB*sizeof(int)); - elbg->scratchbuf = av_malloc(5*dim*sizeof(int)); + elbg->utility_inc = av_malloc_array(numCB, sizeof(*elbg->utility_inc)); + elbg->scratchbuf = av_malloc_array(5*dim, sizeof(int)); elbg->rand_state = rand_state; diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index ebd671a74..7bb7860f9 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 "mpegutils.h" #include "mpegvideo.h" #include "rectangle.h" #include "thread.h" @@ -57,7 +58,7 @@ static void set_mv_strides(ERContext *s, int *mv_step, int *stride) static void put_dc(ERContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y) { - int *linesize = s->cur_pic->f.linesize; + int *linesize = s->cur_pic.f->linesize; int dc, dcu, dcv, y, i; for (i = 0; i < 4; i++) { dc = s->dc_val[0][mb_x * 2 + (i & 1) + (mb_y * 2 + (i >> 1)) * s->b8_stride]; @@ -135,8 +136,8 @@ static void guess_dc(ERContext *s, int16_t *dc, int w, int h, int stride, int is_luma) { int b_x, b_y; - int16_t (*col )[4] = av_malloc(stride*h*sizeof( int16_t)*4); - uint32_t (*dist)[4] = av_malloc(stride*h*sizeof(uint32_t)*4); + int16_t (*col )[4] = av_malloc_array(stride, h*sizeof( int16_t)*4); + uint32_t (*dist)[4] = av_malloc_array(stride, h*sizeof(uint32_t)*4); if(!col || !dist) { av_log(s->avctx, AV_LOG_ERROR, "guess_dc() is out of memory\n"); @@ -149,7 +150,7 @@ static void guess_dc(ERContext *s, int16_t *dc, int w, for(b_x=0; b_x>is_luma) + (b_y>>is_luma)*s->mb_stride; int error_j= s->error_status_table[mb_index_j]; - int intra_j = IS_INTRA(s->cur_pic->mb_type[mb_index_j]); + int intra_j = IS_INTRA(s->cur_pic.mb_type[mb_index_j]); if(intra_j==0 || !(error_j&ER_DC_ERROR)){ color= dc[b_x + b_y*stride]; distance= b_x; @@ -162,7 +163,7 @@ static void guess_dc(ERContext *s, int16_t *dc, int w, for(b_x=w-1; b_x>=0; b_x--){ int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride; int error_j= s->error_status_table[mb_index_j]; - int intra_j = IS_INTRA(s->cur_pic->mb_type[mb_index_j]); + int intra_j = IS_INTRA(s->cur_pic.mb_type[mb_index_j]); if(intra_j==0 || !(error_j&ER_DC_ERROR)){ color= dc[b_x + b_y*stride]; distance= b_x; @@ -177,7 +178,7 @@ static void guess_dc(ERContext *s, int16_t *dc, int w, for(b_y=0; b_y>is_luma) + (b_y>>is_luma)*s->mb_stride; int error_j= s->error_status_table[mb_index_j]; - int intra_j = IS_INTRA(s->cur_pic->mb_type[mb_index_j]); + int intra_j = IS_INTRA(s->cur_pic.mb_type[mb_index_j]); if(intra_j==0 || !(error_j&ER_DC_ERROR)){ color= dc[b_x + b_y*stride]; distance= b_y; @@ -190,7 +191,7 @@ static void guess_dc(ERContext *s, int16_t *dc, int w, for(b_y=h-1; b_y>=0; b_y--){ int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride; int error_j= s->error_status_table[mb_index_j]; - int intra_j = IS_INTRA(s->cur_pic->mb_type[mb_index_j]); + int intra_j = IS_INTRA(s->cur_pic.mb_type[mb_index_j]); if(intra_j==0 || !(error_j&ER_DC_ERROR)){ color= dc[b_x + b_y*stride]; distance= b_y; @@ -207,7 +208,7 @@ static void guess_dc(ERContext *s, int16_t *dc, int w, mb_index = (b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride; error = s->error_status_table[mb_index]; - if (IS_INTER(s->cur_pic->mb_type[mb_index])) + if (IS_INTER(s->cur_pic.mb_type[mb_index])) continue; // inter if (!(error & ER_DC_ERROR)) continue; // dc-ok @@ -238,7 +239,7 @@ static void h_block_filter(ERContext *s, uint8_t *dst, int w, int h, int stride, int is_luma) { int b_x, b_y, mvx_stride, mvy_stride; - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; set_mv_strides(s, &mvx_stride, &mvy_stride); mvx_stride >>= is_luma; mvy_stride *= mvx_stride; @@ -248,13 +249,13 @@ static void h_block_filter(ERContext *s, uint8_t *dst, int w, int y; int left_status = s->error_status_table[( b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]; int right_status = s->error_status_table[((b_x + 1) >> is_luma) + (b_y >> is_luma) * s->mb_stride]; - int left_intra = IS_INTRA(s->cur_pic->mb_type[( b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]); - int right_intra = IS_INTRA(s->cur_pic->mb_type[((b_x + 1) >> is_luma) + (b_y >> is_luma) * s->mb_stride]); + int left_intra = IS_INTRA(s->cur_pic.mb_type[( b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]); + int right_intra = IS_INTRA(s->cur_pic.mb_type[((b_x + 1) >> is_luma) + (b_y >> is_luma) * s->mb_stride]); int left_damage = left_status & ER_MB_ERROR; int right_damage = right_status & ER_MB_ERROR; int offset = b_x * 8 + b_y * stride * 8; - int16_t *left_mv = s->cur_pic->motion_val[0][mvy_stride * b_y + mvx_stride * b_x]; - int16_t *right_mv = s->cur_pic->motion_val[0][mvy_stride * b_y + mvx_stride * (b_x + 1)]; + int16_t *left_mv = s->cur_pic.motion_val[0][mvy_stride * b_y + mvx_stride * b_x]; + int16_t *right_mv = s->cur_pic.motion_val[0][mvy_stride * b_y + mvx_stride * (b_x + 1)]; if (!(left_damage || right_damage)) continue; // both undamaged if ((!left_intra) && (!right_intra) && @@ -306,7 +307,7 @@ static void v_block_filter(ERContext *s, uint8_t *dst, int w, int h, int stride, int is_luma) { int b_x, b_y, mvx_stride, mvy_stride; - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; set_mv_strides(s, &mvx_stride, &mvy_stride); mvx_stride >>= is_luma; mvy_stride *= mvx_stride; @@ -316,14 +317,14 @@ static void v_block_filter(ERContext *s, uint8_t *dst, int w, int h, int x; int top_status = s->error_status_table[(b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]; int bottom_status = s->error_status_table[(b_x >> is_luma) + ((b_y + 1) >> is_luma) * s->mb_stride]; - int top_intra = IS_INTRA(s->cur_pic->mb_type[(b_x >> is_luma) + ( b_y >> is_luma) * s->mb_stride]); - int bottom_intra = IS_INTRA(s->cur_pic->mb_type[(b_x >> is_luma) + ((b_y + 1) >> is_luma) * s->mb_stride]); + int top_intra = IS_INTRA(s->cur_pic.mb_type[(b_x >> is_luma) + ( b_y >> is_luma) * s->mb_stride]); + int bottom_intra = IS_INTRA(s->cur_pic.mb_type[(b_x >> is_luma) + ((b_y + 1) >> is_luma) * s->mb_stride]); int top_damage = top_status & ER_MB_ERROR; int bottom_damage = bottom_status & ER_MB_ERROR; int offset = b_x * 8 + b_y * stride * 8; - int16_t *top_mv = s->cur_pic->motion_val[0][mvy_stride * b_y + mvx_stride * b_x]; - int16_t *bottom_mv = s->cur_pic->motion_val[0][mvy_stride * (b_y + 1) + mvx_stride * b_x]; + int16_t *top_mv = s->cur_pic.motion_val[0][mvy_stride * b_y + mvx_stride * b_x]; + int16_t *bottom_mv = s->cur_pic.motion_val[0][mvy_stride * (b_y + 1) + mvx_stride * b_x]; if (!(top_damage || bottom_damage)) continue; // both undamaged @@ -388,7 +389,7 @@ static void guess_mv(ERContext *s) int f = 0; int error = s->error_status_table[mb_xy]; - if (IS_INTRA(s->cur_pic->mb_type[mb_xy])) + if (IS_INTRA(s->cur_pic.mb_type[mb_xy])) f = MV_FROZEN; // intra // FIXME check if (!(error & ER_MV_ERROR)) f = MV_FROZEN; // inter with undamaged MV @@ -396,13 +397,13 @@ static void guess_mv(ERContext *s) fixed[mb_xy] = f; if (f == MV_FROZEN) num_avail++; - else if(s->last_pic->f.data[0] && s->last_pic->motion_val[0]){ + else if(s->last_pic.f->data[0] && s->last_pic.motion_val[0]){ const int mb_y= mb_xy / s->mb_stride; const int mb_x= mb_xy % s->mb_stride; const int mot_index= (mb_x + mb_y*mot_stride) * mot_step; - s->cur_pic->motion_val[0][mot_index][0]= s->last_pic->motion_val[0][mot_index][0]; - s->cur_pic->motion_val[0][mot_index][1]= s->last_pic->motion_val[0][mot_index][1]; - s->cur_pic->ref_index[0][4*mb_xy] = s->last_pic->ref_index[0][4*mb_xy]; + s->cur_pic.motion_val[0][mot_index][0]= s->last_pic.motion_val[0][mot_index][0]; + s->cur_pic.motion_val[0][mot_index][1]= s->last_pic.motion_val[0][mot_index][1]; + s->cur_pic.ref_index[0][4*mb_xy] = s->last_pic.ref_index[0][4*mb_xy]; } } @@ -411,9 +412,9 @@ static void guess_mv(ERContext *s) for (mb_y = 0; mb_y < s->mb_height; mb_y++) { for (mb_x = 0; mb_x < s->mb_width; mb_x++) { const int mb_xy = mb_x + mb_y * s->mb_stride; - int mv_dir = (s->last_pic && s->last_pic->f.data[0]) ? MV_DIR_FORWARD : MV_DIR_BACKWARD; + int mv_dir = (s->last_pic.f && s->last_pic.f->data[0]) ? MV_DIR_FORWARD : MV_DIR_BACKWARD; - if (IS_INTRA(s->cur_pic->mb_type[mb_xy])) + if (IS_INTRA(s->cur_pic.mb_type[mb_xy])) continue; if (!(s->error_status_table[mb_xy] & ER_MV_ERROR)) continue; @@ -454,8 +455,8 @@ static void guess_mv(ERContext *s) if (fixed[mb_xy] == MV_FROZEN) continue; - av_assert1(!IS_INTRA(s->cur_pic->mb_type[mb_xy])); - av_assert1(s->last_pic && s->last_pic->f.data[0]); + av_assert1(!IS_INTRA(s->cur_pic.mb_type[mb_xy])); + av_assert1(s->last_pic.f && s->last_pic.f->data[0]); j = 0; if (mb_x > 0 && fixed[mb_xy - 1] == MV_FROZEN) @@ -485,38 +486,38 @@ static void guess_mv(ERContext *s) if (mb_x > 0 && fixed[mb_xy - 1]) { mv_predictor[pred_count][0] = - s->cur_pic->motion_val[0][mot_index - mot_step][0]; + s->cur_pic.motion_val[0][mot_index - mot_step][0]; mv_predictor[pred_count][1] = - s->cur_pic->motion_val[0][mot_index - mot_step][1]; + s->cur_pic.motion_val[0][mot_index - mot_step][1]; ref[pred_count] = - s->cur_pic->ref_index[0][4 * (mb_xy - 1)]; + s->cur_pic.ref_index[0][4 * (mb_xy - 1)]; pred_count++; } if (mb_x + 1 < mb_width && fixed[mb_xy + 1]) { mv_predictor[pred_count][0] = - s->cur_pic->motion_val[0][mot_index + mot_step][0]; + s->cur_pic.motion_val[0][mot_index + mot_step][0]; mv_predictor[pred_count][1] = - s->cur_pic->motion_val[0][mot_index + mot_step][1]; + s->cur_pic.motion_val[0][mot_index + mot_step][1]; ref[pred_count] = - s->cur_pic->ref_index[0][4 * (mb_xy + 1)]; + s->cur_pic.ref_index[0][4 * (mb_xy + 1)]; pred_count++; } if (mb_y > 0 && fixed[mb_xy - mb_stride]) { mv_predictor[pred_count][0] = - s->cur_pic->motion_val[0][mot_index - mot_stride * mot_step][0]; + s->cur_pic.motion_val[0][mot_index - mot_stride * mot_step][0]; mv_predictor[pred_count][1] = - s->cur_pic->motion_val[0][mot_index - mot_stride * mot_step][1]; + s->cur_pic.motion_val[0][mot_index - mot_stride * mot_step][1]; ref[pred_count] = - s->cur_pic->ref_index[0][4 * (mb_xy - s->mb_stride)]; + s->cur_pic.ref_index[0][4 * (mb_xy - s->mb_stride)]; pred_count++; } if (mb_y + 1cur_pic->motion_val[0][mot_index + mot_stride * mot_step][0]; + s->cur_pic.motion_val[0][mot_index + mot_stride * mot_step][0]; mv_predictor[pred_count][1] = - s->cur_pic->motion_val[0][mot_index + mot_stride * mot_step][1]; + s->cur_pic.motion_val[0][mot_index + mot_stride * mot_step][1]; ref[pred_count] = - s->cur_pic->ref_index[0][4 * (mb_xy + s->mb_stride)]; + s->cur_pic.ref_index[0][4 * (mb_xy + s->mb_stride)]; pred_count++; } if (pred_count == 0) @@ -574,19 +575,19 @@ skip_mean_and_median: if (s->avctx->codec_id == AV_CODEC_ID_H264) { // FIXME } else { - ff_thread_await_progress(&s->last_pic->tf, + ff_thread_await_progress(s->last_pic.tf, mb_y, 0); } - if (!s->last_pic->motion_val[0] || - !s->last_pic->ref_index[0]) + if (!s->last_pic.motion_val[0] || + !s->last_pic.ref_index[0]) goto skip_last_mv; - prev_x = s->last_pic->motion_val[0][mot_index][0]; - prev_y = s->last_pic->motion_val[0][mot_index][1]; - prev_ref = s->last_pic->ref_index[0][4 * mb_xy]; + prev_x = s->last_pic.motion_val[0][mot_index][0]; + prev_y = s->last_pic.motion_val[0][mot_index][1]; + prev_ref = s->last_pic.ref_index[0][4 * mb_xy]; } else { - prev_x = s->cur_pic->motion_val[0][mot_index][0]; - prev_y = s->cur_pic->motion_val[0][mot_index][1]; - prev_ref = s->cur_pic->ref_index[0][4 * mb_xy]; + prev_x = s->cur_pic.motion_val[0][mot_index][0]; + prev_y = s->cur_pic.motion_val[0][mot_index][1]; + prev_ref = s->cur_pic.ref_index[0][4 * mb_xy]; } /* last MV */ @@ -598,14 +599,14 @@ skip_mean_and_median: skip_last_mv: for (j = 0; j < pred_count; j++) { - int *linesize = s->cur_pic->f.linesize; + int *linesize = s->cur_pic.f->linesize; int score = 0; - uint8_t *src = s->cur_pic->f.data[0] + + uint8_t *src = s->cur_pic.f->data[0] + mb_x * 16 + mb_y * 16 * linesize[0]; - s->cur_pic->motion_val[0][mot_index][0] = + s->cur_pic.motion_val[0][mot_index][0] = s->mv[0][0][0] = mv_predictor[j][0]; - s->cur_pic->motion_val[0][mot_index][1] = + s->cur_pic.motion_val[0][mot_index][1] = s->mv[0][0][1] = mv_predictor[j][1]; // predictor intra or otherwise not available @@ -650,8 +651,8 @@ skip_last_mv: for (i = 0; i < mot_step; i++) for (j = 0; j < mot_step; j++) { - s->cur_pic->motion_val[0][mot_index + i + j * mot_stride][0] = s->mv[0][0][0]; - s->cur_pic->motion_val[0][mot_index + i + j * mot_stride][1] = s->mv[0][0][1]; + s->cur_pic.motion_val[0][mot_index + i + j * mot_stride][0] = s->mv[0][0][0]; + s->cur_pic.motion_val[0][mot_index + i + j * mot_stride][1] = s->mv[0][0][1]; } s->decode_mb(s->opaque, ref[best_pred], MV_DIR_FORWARD, @@ -682,9 +683,12 @@ static int is_intra_more_likely(ERContext *s) { int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y; - if (!s->last_pic || !s->last_pic->f.data[0]) + if (!s->last_pic.f || !s->last_pic.f->data[0]) return 1; // no previous frame available -> use spatial prediction + if (s->avctx->error_concealment & FF_EC_FAVOR_INTER) + return 0; + undamaged_count = 0; for (i = 0; i < s->mb_num; i++) { const int mb_xy = s->mb_index2xy[i]; @@ -702,7 +706,7 @@ static int is_intra_more_likely(ERContext *s) // prevent dsp.sad() check, that requires access to the image if (CONFIG_XVMC && s->avctx->hwaccel && s->avctx->hwaccel->decode_mb && - s->cur_pic->f.pict_type == AV_PICTURE_TYPE_I) + s->cur_pic.f->pict_type == AV_PICTURE_TYPE_I) return 1; skip_amount = FFMAX(undamaged_count / 50, 1); // check only up to 50 MBs @@ -723,17 +727,17 @@ static int is_intra_more_likely(ERContext *s) if ((j % skip_amount) != 0) continue; - if (s->cur_pic->f.pict_type == AV_PICTURE_TYPE_I) { - int *linesize = s->cur_pic->f.linesize; - uint8_t *mb_ptr = s->cur_pic->f.data[0] + + if (s->cur_pic.f->pict_type == AV_PICTURE_TYPE_I) { + int *linesize = s->cur_pic.f->linesize; + uint8_t *mb_ptr = s->cur_pic.f->data[0] + mb_x * 16 + mb_y * 16 * linesize[0]; - uint8_t *last_mb_ptr = s->last_pic->f.data[0] + + uint8_t *last_mb_ptr = s->last_pic.f->data[0] + mb_x * 16 + mb_y * 16 * linesize[0]; if (s->avctx->codec_id == AV_CODEC_ID_H264) { // FIXME } else { - ff_thread_await_progress(&s->last_pic->tf, mb_y, 0); + ff_thread_await_progress(s->last_pic.tf, mb_y, 0); } is_intra_likely += s->dsp->sad[0](NULL, last_mb_ptr, mb_ptr, linesize[0], 16); @@ -742,7 +746,7 @@ static int is_intra_more_likely(ERContext *s) last_mb_ptr + linesize[0] * 16, linesize[0], 16); } else { - if (IS_INTRA(s->cur_pic->mb_type[mb_xy])) + if (IS_INTRA(s->cur_pic.mb_type[mb_xy])) is_intra_likely++; else is_intra_likely--; @@ -768,8 +772,8 @@ static int er_supported(ERContext *s) { if(s->avctx->hwaccel && s->avctx->hwaccel->decode_slice || s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU || - !s->cur_pic || - s->cur_pic->field_picture + !s->cur_pic.f || + s->cur_pic.field_picture ) return 0; return 1; @@ -854,7 +858,7 @@ void ff_er_add_slice(ERContext *s, int startx, int starty, void ff_er_frame_end(ERContext *s) { - int *linesize = s->cur_pic->f.linesize; + int *linesize = s->cur_pic.f->linesize; int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error; int distance; int threshold_part[4] = { 100, 100, 100 }; @@ -886,40 +890,40 @@ void ff_er_frame_end(ERContext *s) return; } - if (s->last_pic) { - if (s->last_pic->f.width != s->cur_pic->f.width || - s->last_pic->f.height != s->cur_pic->f.height || - s->last_pic->f.format != s->cur_pic->f.format) { + if (s->last_pic.f) { + if (s->last_pic.f->width != s->cur_pic.f->width || + s->last_pic.f->height != s->cur_pic.f->height || + s->last_pic.f->format != s->cur_pic.f->format) { av_log(s->avctx, AV_LOG_WARNING, "Cannot use previous picture in error concealment\n"); - s->last_pic = NULL; + memset(&s->last_pic, 0, sizeof(s->last_pic)); } } - if (s->next_pic) { - if (s->next_pic->f.width != s->cur_pic->f.width || - s->next_pic->f.height != s->cur_pic->f.height || - s->next_pic->f.format != s->cur_pic->f.format) { + if (s->next_pic.f) { + if (s->next_pic.f->width != s->cur_pic.f->width || + s->next_pic.f->height != s->cur_pic.f->height || + s->next_pic.f->format != s->cur_pic.f->format) { av_log(s->avctx, AV_LOG_WARNING, "Cannot use next picture in error concealment\n"); - s->next_pic = NULL; + memset(&s->next_pic, 0, sizeof(s->next_pic)); } } - if (s->cur_pic->motion_val[0] == NULL) { + if (!s->cur_pic.motion_val[0] || !s->cur_pic.ref_index[0]) { av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n"); for (i = 0; i < 2; i++) { - s->cur_pic->ref_index_buf[i] = av_buffer_allocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t)); - s->cur_pic->motion_val_buf[i] = av_buffer_allocz((size + 4) * 2 * sizeof(uint16_t)); - if (!s->cur_pic->ref_index_buf[i] || !s->cur_pic->motion_val_buf[i]) + s->ref_index_buf[i] = av_buffer_allocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t)); + s->motion_val_buf[i] = av_buffer_allocz((size + 4) * 2 * sizeof(uint16_t)); + if (!s->ref_index_buf[i] || !s->motion_val_buf[i]) break; - s->cur_pic->ref_index[i] = s->cur_pic->ref_index_buf[i]->data; - s->cur_pic->motion_val[i] = (int16_t (*)[2])s->cur_pic->motion_val_buf[i]->data + 4; + s->cur_pic.ref_index[i] = s->ref_index_buf[i]->data; + s->cur_pic.motion_val[i] = (int16_t (*)[2])s->motion_val_buf[i]->data + 4; } if (i < 2) { for (i = 0; i < 2; i++) { - av_buffer_unref(&s->cur_pic->ref_index_buf[i]); - av_buffer_unref(&s->cur_pic->motion_val_buf[i]); - s->cur_pic->ref_index[i] = NULL; - s->cur_pic->motion_val[i] = NULL; + av_buffer_unref(&s->ref_index_buf[i]); + av_buffer_unref(&s->motion_val_buf[i]); + s->cur_pic.ref_index[i] = NULL; + s->cur_pic.motion_val[i] = NULL; } return; } @@ -1073,7 +1077,7 @@ void ff_er_frame_end(ERContext *s) mv_error++; } av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors in %c frame\n", - dc_error, ac_error, mv_error, av_get_picture_type_char(s->cur_pic->f.pict_type)); + dc_error, ac_error, mv_error, av_get_picture_type_char(s->cur_pic.f->pict_type)); is_intra_likely = is_intra_more_likely(s); @@ -1085,26 +1089,26 @@ void ff_er_frame_end(ERContext *s) continue; if (is_intra_likely) - s->cur_pic->mb_type[mb_xy] = MB_TYPE_INTRA4x4; + s->cur_pic.mb_type[mb_xy] = MB_TYPE_INTRA4x4; else - s->cur_pic->mb_type[mb_xy] = MB_TYPE_16x16 | MB_TYPE_L0; + s->cur_pic.mb_type[mb_xy] = MB_TYPE_16x16 | MB_TYPE_L0; } // change inter to intra blocks if no reference frames are available - if (!(s->last_pic && s->last_pic->f.data[0]) && - !(s->next_pic && s->next_pic->f.data[0])) + if (!(s->last_pic.f && s->last_pic.f->data[0]) && + !(s->next_pic.f && s->next_pic.f->data[0])) for (i = 0; i < s->mb_num; i++) { const int mb_xy = s->mb_index2xy[i]; - if (!IS_INTRA(s->cur_pic->mb_type[mb_xy])) - s->cur_pic->mb_type[mb_xy] = MB_TYPE_INTRA4x4; + if (!IS_INTRA(s->cur_pic.mb_type[mb_xy])) + s->cur_pic.mb_type[mb_xy] = MB_TYPE_INTRA4x4; } /* handle inter blocks with damaged AC */ for (mb_y = 0; mb_y < s->mb_height; mb_y++) { for (mb_x = 0; mb_x < s->mb_width; mb_x++) { const int mb_xy = mb_x + mb_y * s->mb_stride; - const int mb_type = s->cur_pic->mb_type[mb_xy]; - const int dir = !(s->last_pic && s->last_pic->f.data[0]); + const int mb_type = s->cur_pic.mb_type[mb_xy]; + const int dir = !(s->last_pic.f && s->last_pic.f->data[0]); const int mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD; int mv_type; @@ -1122,13 +1126,13 @@ void ff_er_frame_end(ERContext *s) int j; mv_type = MV_TYPE_8X8; for (j = 0; j < 4; j++) { - s->mv[0][j][0] = s->cur_pic->motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][0]; - s->mv[0][j][1] = s->cur_pic->motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][1]; + s->mv[0][j][0] = s->cur_pic.motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][0]; + s->mv[0][j][1] = s->cur_pic.motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][1]; } } else { mv_type = MV_TYPE_16X16; - s->mv[0][0][0] = s->cur_pic->motion_val[dir][mb_x * 2 + mb_y * 2 * s->b8_stride][0]; - s->mv[0][0][1] = s->cur_pic->motion_val[dir][mb_x * 2 + mb_y * 2 * s->b8_stride][1]; + s->mv[0][0][0] = s->cur_pic.motion_val[dir][mb_x * 2 + mb_y * 2 * s->b8_stride][0]; + s->mv[0][0][1] = s->cur_pic.motion_val[dir][mb_x * 2 + mb_y * 2 * s->b8_stride][1]; } s->decode_mb(s->opaque, 0 /* FIXME h264 partitioned slices need this set */, @@ -1137,12 +1141,12 @@ void ff_er_frame_end(ERContext *s) } /* guess MVs */ - if (s->cur_pic->f.pict_type == AV_PICTURE_TYPE_B) { + if (s->cur_pic.f->pict_type == AV_PICTURE_TYPE_B) { for (mb_y = 0; mb_y < s->mb_height; mb_y++) { for (mb_x = 0; mb_x < s->mb_width; mb_x++) { int xy = mb_x * 2 + mb_y * 2 * s->b8_stride; const int mb_xy = mb_x + mb_y * s->mb_stride; - const int mb_type = s->cur_pic->mb_type[mb_xy]; + const int mb_type = s->cur_pic.mb_type[mb_xy]; int mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD; error = s->error_status_table[mb_xy]; @@ -1154,9 +1158,9 @@ void ff_er_frame_end(ERContext *s) if (!(error & ER_AC_ERROR)) continue; // undamaged inter - if (!(s->last_pic && s->last_pic->f.data[0])) + if (!(s->last_pic.f && s->last_pic.f->data[0])) mv_dir &= ~MV_DIR_FORWARD; - if (!(s->next_pic && s->next_pic->f.data[0])) + if (!(s->next_pic.f && s->next_pic.f->data[0])) mv_dir &= ~MV_DIR_BACKWARD; if (s->pp_time) { @@ -1164,12 +1168,12 @@ void ff_er_frame_end(ERContext *s) int time_pb = s->pb_time; av_assert0(s->avctx->codec_id != AV_CODEC_ID_H264); - ff_thread_await_progress(&s->next_pic->tf, mb_y, 0); + ff_thread_await_progress(s->next_pic.tf, mb_y, 0); - s->mv[0][0][0] = s->next_pic->motion_val[0][xy][0] * time_pb / time_pp; - s->mv[0][0][1] = s->next_pic->motion_val[0][xy][1] * time_pb / time_pp; - s->mv[1][0][0] = s->next_pic->motion_val[0][xy][0] * (time_pb - time_pp) / time_pp; - s->mv[1][0][1] = s->next_pic->motion_val[0][xy][1] * (time_pb - time_pp) / time_pp; + s->mv[0][0][0] = s->next_pic.motion_val[0][xy][0] * time_pb / time_pp; + s->mv[0][0][1] = s->next_pic.motion_val[0][xy][1] * time_pb / time_pp; + s->mv[1][0][0] = s->next_pic.motion_val[0][xy][0] * (time_pb - time_pp) / time_pp; + s->mv[1][0][1] = s->next_pic.motion_val[0][xy][1] * (time_pb - time_pp) / time_pp; } else { s->mv[0][0][0] = 0; s->mv[0][0][1] = 0; @@ -1194,7 +1198,7 @@ void ff_er_frame_end(ERContext *s) int16_t *dc_ptr; uint8_t *dest_y, *dest_cb, *dest_cr; const int mb_xy = mb_x + mb_y * s->mb_stride; - const int mb_type = s->cur_pic->mb_type[mb_xy]; + const int mb_type = s->cur_pic.mb_type[mb_xy]; error = s->error_status_table[mb_xy]; @@ -1203,9 +1207,9 @@ void ff_er_frame_end(ERContext *s) // if (error & ER_MV_ERROR) // continue; // inter data damaged FIXME is this good? - dest_y = s->cur_pic->f.data[0] + mb_x * 16 + mb_y * 16 * linesize[0]; - dest_cb = s->cur_pic->f.data[1] + mb_x * 8 + mb_y * 8 * linesize[1]; - dest_cr = s->cur_pic->f.data[2] + mb_x * 8 + mb_y * 8 * linesize[2]; + dest_y = s->cur_pic.f->data[0] + mb_x * 16 + mb_y * 16 * linesize[0]; + dest_cb = s->cur_pic.f->data[1] + mb_x * 8 + mb_y * 8 * linesize[1]; + dest_cr = s->cur_pic.f->data[2] + mb_x * 8 + mb_y * 8 * linesize[2]; dc_ptr = &s->dc_val[0][mb_x * 2 + mb_y * 2 * s->b8_stride]; for (n = 0; n < 4; n++) { @@ -1247,7 +1251,7 @@ void ff_er_frame_end(ERContext *s) for (mb_x = 0; mb_x < s->mb_width; mb_x++) { uint8_t *dest_y, *dest_cb, *dest_cr; const int mb_xy = mb_x + mb_y * s->mb_stride; - const int mb_type = s->cur_pic->mb_type[mb_xy]; + const int mb_type = s->cur_pic.mb_type[mb_xy]; error = s->error_status_table[mb_xy]; @@ -1256,9 +1260,9 @@ void ff_er_frame_end(ERContext *s) if (!(error & ER_AC_ERROR)) continue; // undamaged - dest_y = s->cur_pic->f.data[0] + mb_x * 16 + mb_y * 16 * linesize[0]; - dest_cb = s->cur_pic->f.data[1] + mb_x * 8 + mb_y * 8 * linesize[1]; - dest_cr = s->cur_pic->f.data[2] + mb_x * 8 + mb_y * 8 * linesize[2]; + dest_y = s->cur_pic.f->data[0] + mb_x * 16 + mb_y * 16 * linesize[0]; + dest_cb = s->cur_pic.f->data[1] + mb_x * 8 + mb_y * 8 * linesize[1]; + dest_cr = s->cur_pic.f->data[2] + mb_x * 8 + mb_y * 8 * linesize[2]; put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y); } @@ -1267,19 +1271,19 @@ void ff_er_frame_end(ERContext *s) if (s->avctx->error_concealment & FF_EC_DEBLOCK) { /* filter horizontal block boundaries */ - h_block_filter(s, s->cur_pic->f.data[0], s->mb_width * 2, + h_block_filter(s, s->cur_pic.f->data[0], s->mb_width * 2, s->mb_height * 2, linesize[0], 1); - h_block_filter(s, s->cur_pic->f.data[1], s->mb_width, + h_block_filter(s, s->cur_pic.f->data[1], s->mb_width, s->mb_height, linesize[1], 0); - h_block_filter(s, s->cur_pic->f.data[2], s->mb_width, + h_block_filter(s, s->cur_pic.f->data[2], s->mb_width, s->mb_height, linesize[2], 0); /* filter vertical block boundaries */ - v_block_filter(s, s->cur_pic->f.data[0], s->mb_width * 2, + v_block_filter(s, s->cur_pic.f->data[0], s->mb_width * 2, s->mb_height * 2, linesize[0], 1); - v_block_filter(s, s->cur_pic->f.data[1], s->mb_width, + v_block_filter(s, s->cur_pic.f->data[1], s->mb_width, s->mb_height, linesize[1], 0); - v_block_filter(s, s->cur_pic->f.data[2], s->mb_width, + v_block_filter(s, s->cur_pic.f->data[2], s->mb_width, s->mb_height, linesize[2], 0); } @@ -1289,13 +1293,21 @@ ec_clean: 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->cur_pic.f->pict_type != AV_PICTURE_TYPE_B && (error & (ER_DC_ERROR | ER_MV_ERROR | ER_AC_ERROR))) { s->mbskip_table[mb_xy] = 0; } s->mbintra_table[mb_xy] = 1; } - s->cur_pic = NULL; - s->next_pic = NULL; - s->last_pic = NULL; + + for (i = 0; i < 2; i++) { + av_buffer_unref(&s->ref_index_buf[i]); + av_buffer_unref(&s->motion_val_buf[i]); + s->cur_pic.ref_index[i] = NULL; + s->cur_pic.motion_val[i] = NULL; + } + + memset(&s->cur_pic, 0, sizeof(ERPicture)); + memset(&s->last_pic, 0, sizeof(ERPicture)); + memset(&s->next_pic, 0, sizeof(ERPicture)); } diff --git a/libavcodec/error_resilience.h b/libavcodec/error_resilience.h index 970fdc206..9d227e87a 100644 --- a/libavcodec/error_resilience.h +++ b/libavcodec/error_resilience.h @@ -24,6 +24,7 @@ #include "avcodec.h" #include "dsputil.h" +#include "thread.h" ///< current MB is the first after a resync marker #define VP_START 1 @@ -37,6 +38,18 @@ #define ER_MB_ERROR (ER_AC_ERROR|ER_DC_ERROR|ER_MV_ERROR) #define ER_MB_END (ER_AC_END|ER_DC_END|ER_MV_END) +typedef struct ERPicture { + AVFrame *f; + ThreadFrame *tf; + + // it's the caller's responsibility to allocate these buffers + int16_t (*motion_val[2])[2]; + int8_t *ref_index[2]; + + uint32_t *mb_type; + int field_picture; +} ERPicture; + typedef struct ERContext { AVCodecContext *avctx; DSPContext *dsp; @@ -55,9 +68,12 @@ typedef struct ERContext { uint8_t *mbintra_table; int mv[2][4][2]; - struct Picture *cur_pic; - struct Picture *last_pic; - struct Picture *next_pic; + ERPicture cur_pic; + ERPicture last_pic; + ERPicture next_pic; + + AVBufferRef *ref_index_buf[2]; + AVBufferRef *motion_val_buf[2]; uint16_t pp_time; uint16_t pb_time; diff --git a/libavcodec/exif.c b/libavcodec/exif.c index 96464261c..a980da2a7 100644 --- a/libavcodec/exif.c +++ b/libavcodec/exif.c @@ -48,9 +48,11 @@ static int exif_add_metadata(AVCodecContext *avctx, int count, int type, { switch(type) { case TIFF_DOUBLE : return ff_tadd_doubles_metadata(count, name, sep, gb, le, metadata); - case TIFF_SHORT : return ff_tadd_shorts_metadata(count, name, sep, gb, le, metadata); + case TIFF_SSHORT : return ff_tadd_shorts_metadata(count, name, sep, gb, le, 1, metadata); + case TIFF_SHORT : return ff_tadd_shorts_metadata(count, name, sep, gb, le, 0, metadata); + case TIFF_SBYTE : return ff_tadd_bytes_metadata(count, name, sep, gb, le, 1, metadata); case TIFF_BYTE : - case TIFF_UNDEFINED: return ff_tadd_bytes_metadata(count, name, sep, gb, le, metadata); + case TIFF_UNDEFINED: return ff_tadd_bytes_metadata(count, name, sep, gb, le, 0, metadata); case TIFF_STRING : return ff_tadd_string_metadata(count, name, gb, le, metadata); case TIFF_SRATIONAL: case TIFF_RATIONAL : return ff_tadd_rational_metadata(count, name, sep, gb, le, metadata); @@ -76,11 +78,16 @@ static int exif_decode_tag(AVCodecContext *avctx, GetByteContext *gbytes, int le ff_tread_tag(gbytes, le, &id, &type, &count, &cur_pos); + if (!bytestream2_tell(gbytes)) { + bytestream2_seek(gbytes, cur_pos, SEEK_SET); + return 0; + } + // read count values and add it metadata // store metadata or proceed with next IFD ret = ff_tis_ifd(id); if (ret) { - ret = ff_exif_decode_ifd(avctx, gbytes, le, depth + 1, metadata); + ret = avpriv_exif_decode_ifd(avctx, gbytes, le, depth + 1, metadata); } else { const char *name = exif_get_tag_name(id); char *use_name = (char*) name; @@ -107,8 +114,8 @@ static int exif_decode_tag(AVCodecContext *avctx, GetByteContext *gbytes, int le } -int ff_exif_decode_ifd(AVCodecContext *avctx, GetByteContext *gbytes, int le, - int depth, AVDictionary **metadata) +int avpriv_exif_decode_ifd(AVCodecContext *avctx, GetByteContext *gbytes, int le, + int depth, AVDictionary **metadata) { int i, ret; int entries; diff --git a/libavcodec/exif.h b/libavcodec/exif.h index 71fe8292e..2f509ba1e 100644 --- a/libavcodec/exif.h +++ b/libavcodec/exif.h @@ -164,7 +164,7 @@ static const struct exif_tag tag_list[] = { // JEITA CP-3451 EXIF specification: /** Recursively decodes all IFD's and * adds included TAGS into the metadata dictionary. */ -int ff_exif_decode_ifd(AVCodecContext *avctx, GetByteContext *gbytes, int le, - int depth, AVDictionary **metadata); +int avpriv_exif_decode_ifd(AVCodecContext *avctx, GetByteContext *gbytes, int le, + int depth, AVDictionary **metadata); #endif /* AVCODEC_EXIF_H */ diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 77247fcb8..62e8521ad 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -27,40 +27,46 @@ * 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/opt.h" +#include "libavutil/intfloat.h" -#include "get_bits.h" #include "avcodec.h" #include "bytestream.h" +#include "get_bits.h" #include "internal.h" #include "mathops.h" #include "thread.h" -#include "libavutil/imgutils.h" -#include "libavutil/avassert.h" -#include "libavutil/opt.h" enum ExrCompr { - EXR_RAW = 0, - EXR_RLE = 1, - EXR_ZIP1 = 2, - EXR_ZIP16 = 3, - EXR_PIZ = 4, - EXR_PXR24 = 5, - EXR_B44 = 6, - EXR_B44A = 7, + EXR_RAW, + EXR_RLE, + EXR_ZIP1, + EXR_ZIP16, + EXR_PIZ, + EXR_PXR24, + EXR_B44, + EXR_B44A, + EXR_UNKN, }; enum ExrPixelType { EXR_UINT, EXR_HALF, - EXR_FLOAT + EXR_FLOAT, + EXR_UNKNOWN, }; typedef struct EXRChannel { - int xsub, ysub; + int xsub, ysub; enum ExrPixelType pixel_type; } EXRChannel; @@ -76,52 +82,108 @@ typedef struct EXRThreadData { } EXRThreadData; typedef struct EXRContext { - AVClass *class; + AVClass *class; AVFrame *picture; - int compr; + AVCodecContext *avctx; + + enum ExrCompr compression; enum ExrPixelType pixel_type; int channel_offsets[4]; // 0 = red, 1 = green, 2 = blue and 3 = alpha const AVPixFmtDescriptor *desc; + int w, h; uint32_t xmax, xmin; uint32_t ymax, ymin; uint32_t xdelta, ydelta; - int ysize; uint64_t scan_line_size; int scan_lines_per_block; - const uint8_t *buf, *table; + GetByteContext gb; + const uint8_t *buf; int buf_size; EXRChannel *channels; int nb_channels; EXRThreadData *thread_data; - int thread_data_size; - const char* layer; + const char *layer; + + float gamma; + + uint16_t gamma_table[65536]; + } EXRContext; -#define OFFSET(x) offsetof(EXRContext, x) -#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM -static const AVOption options[] = { - { "layer", "Set the decoding layer", OFFSET(layer), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD}, - { NULL }, -}; +/* -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; +} -static const AVClass exr_class = { - .class_name = "EXR", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; /** - * Converts from 32-bit float as uint32_t to uint16_t + * Convert from 32-bit float as uint32_t to uint16_t. * * @param v 32-bit float + * * @return normalized 16-bit unsigned int */ static inline uint16_t exr_flt2uint(uint32_t v) @@ -129,7 +191,7 @@ static inline uint16_t exr_flt2uint(uint32_t v) unsigned int exp = v >> 23; // "HACK": negative values result in exp< 0, so clipping them to 0 // is also handled by this condition, avoids explicit check for sign bit. - if (exp<= 127 + 7 - 24) // we would shift out all bits anyway + if (exp <= 127 + 7 - 24) // we would shift out all bits anyway return 0; if (exp >= 127) return 0xffff; @@ -138,83 +200,32 @@ static inline uint16_t exr_flt2uint(uint32_t v) } /** - * Converts from 16-bit float as uint16_t to uint16_t + * Convert from 16-bit float as uint16_t to uint16_t. * * @param v 16-bit float + * * @return normalized 16-bit unsigned int */ static inline uint16_t exr_halflt2uint(uint16_t v) { unsigned exp = 14 - (v >> 10); if (exp >= 14) { - if (exp == 14) return (v >> 9) & 1; - else return (v & 0x8000) ? 0 : 0xffff; + if (exp == 14) + return (v >> 9) & 1; + else + return (v & 0x8000) ? 0 : 0xffff; } v <<= 6; return (v + (1 << 16)) >> (exp + 1); } -/** - * Gets the size of the header variable - * - * @param **buf the current pointer location in the header where - * the variable data starts - * @param *buf_end pointer location of the end of the buffer - * @return size of variable data - */ -static unsigned int get_header_variable_length(const uint8_t **buf, - const uint8_t *buf_end) -{ - unsigned int variable_buffer_data_size = bytestream_get_le32(buf); - if (variable_buffer_data_size >= buf_end - *buf) - return 0; - return variable_buffer_data_size; -} - -/** - * Checks if the variable name corresponds with it's data type - * - * @param *avctx the AVCodecContext - * @param **buf the current pointer location in the header where - * the variable name starts - * @param *buf_end pointer location of the end of the buffer - * @param *value_name name of the varible to check - * @param *value_type type of the varible to check - * @param minimum_length minimum length of the variable data - * @param variable_buffer_data_size variable length read from the header - * after it's checked - * @return negative if variable is invalid - */ -static int check_header_variable(AVCodecContext *avctx, - const uint8_t **buf, - const uint8_t *buf_end, - const char *value_name, - const char *value_type, - unsigned int minimum_length, - unsigned int *variable_buffer_data_size) -{ - if (buf_end - *buf >= minimum_length && !strcmp(*buf, value_name)) { - *buf += strlen(value_name)+1; - if (!strcmp(*buf, value_type)) { - *buf += strlen(value_type)+1; - *variable_buffer_data_size = get_header_variable_length(buf, buf_end); - if (!*variable_buffer_data_size) - av_log(avctx, AV_LOG_ERROR, "Incomplete header\n"); - return 1; - } - *buf -= strlen(value_name)+1; - av_log(avctx, AV_LOG_WARNING, "Unknown data type for header variable %s\n", value_name); - } - return -1; -} - static void predictor(uint8_t *src, int size) { - uint8_t *t = src + 1; + uint8_t *t = src + 1; uint8_t *stop = src + size; while (t < stop) { - int d = (int)t[-1] + (int)t[0] - 128; + int d = (int) t[-1] + (int) t[0] - 128; t[0] = d; ++t; } @@ -224,8 +235,8 @@ static void reorder_pixels(uint8_t *src, uint8_t *dst, int size) { const int8_t *t1 = src; const int8_t *t2 = src + (size + 1) / 2; - int8_t *s = dst; - int8_t *stop = s + size; + int8_t *s = dst; + int8_t *stop = s + size; while (1) { if (s < stop) @@ -247,7 +258,7 @@ static int zip_uncompress(const uint8_t *src, int compressed_size, if (uncompress(td->tmp, &dest_len, src, compressed_size) != Z_OK || dest_len != uncompressed_size) - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; predictor(td->tmp, uncompressed_size); reorder_pixels(td->tmp, td->uncompressed_data, uncompressed_size); @@ -258,11 +269,11 @@ static int zip_uncompress(const uint8_t *src, int compressed_size, static int rle_uncompress(const uint8_t *src, int compressed_size, int uncompressed_size, EXRThreadData *td) { - int8_t *d = (int8_t *)td->tmp; - const int8_t *s = (const int8_t *)src; - int ssize = compressed_size; - int dsize = uncompressed_size; - int8_t *dend = d + dsize; + uint8_t *d = td->tmp; + const int8_t *s = src; + int ssize = compressed_size; + int dsize = uncompressed_size; + uint8_t *dend = d + dsize; int count; while (ssize > 0) { @@ -271,9 +282,9 @@ static int rle_uncompress(const uint8_t *src, int compressed_size, if (count < 0) { count = -count; - if ((dsize -= count ) < 0 || + if ((dsize -= count) < 0 || (ssize -= count + 1) < 0) - return -1; + return AVERROR_INVALIDDATA; while (count--) *d++ = *s++; @@ -281,8 +292,8 @@ static int rle_uncompress(const uint8_t *src, int compressed_size, count++; if ((dsize -= count) < 0 || - (ssize -= 2 ) < 0) - return -1; + (ssize -= 2) < 0) + return AVERROR_INVALIDDATA; while (count--) *d++ = *s; @@ -301,16 +312,15 @@ static int rle_uncompress(const uint8_t *src, int compressed_size, } #define USHORT_RANGE (1 << 16) -#define BITMAP_SIZE (1 << 13) +#define BITMAP_SIZE (1 << 13) static uint16_t reverse_lut(const uint8_t *bitmap, uint16_t *lut) { int i, k = 0; - for (i = 0; i < USHORT_RANGE; i++) { + for (i = 0; i < USHORT_RANGE; i++) if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7)))) lut[k++] = i; - } i = k - 1; @@ -331,7 +341,7 @@ static void apply_lut(const uint16_t *lut, uint16_t *dst, int dsize) #define HUF_DECBITS 14 // decoding bit size (>= 8) #define HUF_ENCSIZE ((1 << HUF_ENCBITS) + 1) // encoding table size -#define HUF_DECSIZE (1 << HUF_DECBITS) // decoding table size +#define HUF_DECSIZE (1 << HUF_DECBITS) // decoding table size #define HUF_DECMASK (HUF_DECSIZE - 1) typedef struct HufDec { @@ -352,7 +362,7 @@ static void huf_canonical_code_table(uint64_t *hcode) for (i = 58; i > 0; --i) { uint64_t nc = ((c + n[i]) >> 1); n[i] = c; - c = nc; + c = nc; } for (i = 0; i < HUF_ENCSIZE; ++i) { @@ -388,7 +398,7 @@ static int huf_unpack_enc_table(GetByteContext *gb, hcode[im++] = 0; im--; - } else if (l >= (uint64_t) SHORT_ZEROCODE_RUN) { + } else if (l >= SHORT_ZEROCODE_RUN) { int zerun = l - SHORT_ZEROCODE_RUN + 2; if (im + zerun > iM + 1) @@ -424,7 +434,7 @@ static int huf_build_dec_table(const uint64_t *hcode, int im, pl->lit++; - pl->p = av_realloc_f(pl->p, pl->lit, sizeof(int)); + pl->p = av_realloc(pl->p, pl->lit * sizeof(int)); if (!pl->p) return AVERROR(ENOMEM); @@ -444,40 +454,42 @@ static int huf_build_dec_table(const uint64_t *hcode, int im, return 0; } -#define get_char(c, lc, gb) { \ - c = (c << 8) | bytestream2_get_byte(gb); \ - lc += 8; \ +#define get_char(c, lc, gb) \ +{ \ + c = (c << 8) | bytestream2_get_byte(gb); \ + lc += 8; \ } -#define get_code(po, rlc, c, lc, gb, out, oe) { \ - if (po == rlc) { \ - if (lc < 8) \ - get_char(c, lc, gb); \ - lc -= 8; \ - \ - cs = c >> lc; \ - \ - if (out + cs > oe) \ - return AVERROR_INVALIDDATA; \ - \ - s = out[-1]; \ - \ - while (cs-- > 0) \ - *out++ = s; \ - } else if (out < oe) { \ - *out++ = po; \ - } else { \ - return AVERROR_INVALIDDATA; \ - } \ +#define get_code(po, rlc, c, lc, gb, out, oe) \ +{ \ + if (po == rlc) { \ + if (lc < 8) \ + get_char(c, lc, gb); \ + lc -= 8; \ + \ + cs = c >> lc; \ + \ + if (out + cs > oe) \ + return AVERROR_INVALIDDATA; \ + \ + s = out[-1]; \ + \ + while (cs-- > 0) \ + *out++ = s; \ + } else if (out < oe) { \ + *out++ = po; \ + } else { \ + return AVERROR_INVALIDDATA; \ + } \ } static int huf_decode(const uint64_t *hcode, const HufDec *hdecod, GetByteContext *gb, int nbits, int rlc, int no, uint16_t *out) { - uint64_t c = 0; - uint16_t *outb = out; - uint16_t *oe = out + no; + uint64_t c = 0; + uint16_t *outb = out; + uint16_t *oe = out + no; const uint8_t *ie = gb->buffer + (nbits + 7) / 8; // input byte size uint8_t cs, s; int i, lc = 0; @@ -486,7 +498,7 @@ static int huf_decode(const uint64_t *hcode, const HufDec *hdecod, get_char(c, lc, gb); while (lc >= HUF_DECBITS) { - const HufDec pl = hdecod[(c >> (lc-HUF_DECBITS)) & HUF_DECMASK]; + const HufDec pl = hdecod[(c >> (lc - HUF_DECBITS)) & HUF_DECMASK]; if (pl.len) { lc -= pl.len; @@ -519,7 +531,7 @@ static int huf_decode(const uint64_t *hcode, const HufDec *hdecod, } } - i = (8 - nbits) & 7; + i = (8 - nbits) & 7; c >>= i; lc -= i; @@ -549,8 +561,8 @@ static int huf_uncompress(GetByteContext *gb, int ret, i; src_size = bytestream2_get_le32(gb); - im = bytestream2_get_le32(gb); - iM = bytestream2_get_le32(gb); + im = bytestream2_get_le32(gb); + iM = bytestream2_get_le32(gb); bytestream2_skip(gb, 4); nBits = bytestream2_get_le32(gb); if (im < 0 || im >= HUF_ENCSIZE || @@ -560,8 +572,8 @@ static int huf_uncompress(GetByteContext *gb, bytestream2_skip(gb, 4); - freq = av_calloc(HUF_ENCSIZE, sizeof(*freq)); - hdec = av_calloc(HUF_DECSIZE, sizeof(*hdec)); + freq = av_mallocz_array(HUF_ENCSIZE, sizeof(*freq)); + hdec = av_mallocz_array(HUF_DECSIZE, sizeof(*hdec)); if (!freq || !hdec) { ret = AVERROR(ENOMEM); goto fail; @@ -580,10 +592,9 @@ static int huf_uncompress(GetByteContext *gb, ret = huf_decode(freq, hdec, gb, nBits, iM, dst_size, dst); fail: - for (i = 0; i < HUF_DECSIZE; i++) { + for (i = 0; i < HUF_DECSIZE; i++) if (hdec) av_freep(&hdec[i].p); - } av_free(freq); av_free(hdec); @@ -595,8 +606,8 @@ static inline void wdec14(uint16_t l, uint16_t h, uint16_t *a, uint16_t *b) { int16_t ls = l; int16_t hs = h; - int hi = hs; - int ai = ls + (hi & 1) + (hi >> 1); + int hi = hs; + int ai = ls + (hi & 1) + (hi >> 1); int16_t as = ai; int16_t bs = ai - hi; @@ -605,13 +616,13 @@ static inline void wdec14(uint16_t l, uint16_t h, uint16_t *a, uint16_t *b) } #define NBITS 16 -#define A_OFFSET (1 << (NBITS - 1)) +#define A_OFFSET (1 << (NBITS - 1)) #define MOD_MASK ((1 << NBITS) - 1) static inline void wdec16(uint16_t l, uint16_t h, uint16_t *a, uint16_t *b) { - int m = l; - int d = h; + int m = l; + int d = h; int bb = (m - (d >> 1)) & MOD_MASK; int aa = (d + bb - A_OFFSET) & MOD_MASK; *b = bb; @@ -622,8 +633,8 @@ static void wav_decode(uint16_t *in, int nx, int ox, int ny, int oy, uint16_t mx) { int w14 = (mx < (1 << 14)); - int n = (nx > ny) ? ny: nx; - int p = 1; + int n = (nx > ny) ? ny : nx; + int p = 1; int p2; while (p <= n) @@ -647,19 +658,19 @@ static void wav_decode(uint16_t *in, int nx, int ox, uint16_t *ex = py + ox * (nx - p2); for (; px <= ex; px += ox2) { - uint16_t *p01 = px + ox1; - uint16_t *p10 = px + oy1; + uint16_t *p01 = px + ox1; + uint16_t *p10 = px + oy1; uint16_t *p11 = p10 + ox1; if (w14) { - wdec14(*px, *p10, &i00, &i10); + wdec14(*px, *p10, &i00, &i10); wdec14(*p01, *p11, &i01, &i11); - wdec14(i00, i01, px, p01); + wdec14(i00, i01, px, p01); wdec14(i10, i11, p10, p11); } else { - wdec16(*px, *p10, &i00, &i10); + wdec16(*px, *p10, &i00, &i10); wdec16(*p01, *p11, &i01, &i11); - wdec16(i00, i01, px, p01); + wdec16(i00, i01, px, p01); wdec16(i10, i11, p10, p11); } } @@ -692,25 +703,30 @@ static void wav_decode(uint16_t *in, int nx, int ox, } } - p2 = p; + p2 = p; p >>= 1; } } -static int piz_uncompress(EXRContext *s, const uint8_t *src, int ssize, int dsize, EXRThreadData *td) +static int piz_uncompress(EXRContext *s, const uint8_t *src, int ssize, + int dsize, EXRThreadData *td) { GetByteContext gb; uint16_t maxval, min_non_zero, max_non_zero; - uint16_t *ptr, *tmp = (uint16_t *)td->tmp; - int8_t *out; + uint16_t *ptr; + uint16_t *tmp = (uint16_t *)td->tmp; + uint8_t *out; int ret, i, j; if (!td->bitmap) td->bitmap = av_malloc(BITMAP_SIZE); if (!td->lut) td->lut = av_malloc(1 << 17); - if (!td->bitmap || !td->lut) + if (!td->bitmap || !td->lut) { + av_freep(&td->bitmap); + av_freep(&td->lut); return AVERROR(ENOMEM); + } bytestream2_init(&gb, src, ssize); min_non_zero = bytestream2_get_le16(&gb); @@ -727,7 +743,7 @@ static int piz_uncompress(EXRContext *s, const uint8_t *src, int ssize, int dsiz maxval = reverse_lut(td->bitmap, td->lut); - ret = huf_uncompress(&gb, tmp, dsize / sizeof(int16_t)); + ret = huf_uncompress(&gb, tmp, dsize / sizeof(uint16_t)); if (ret) return ret; @@ -737,20 +753,20 @@ static int piz_uncompress(EXRContext *s, const uint8_t *src, int ssize, int dsiz int size = channel->pixel_type; for (j = 0; j < size; j++) - wav_decode(ptr + j, s->xdelta, size, s->ysize, s->xdelta * size, maxval); + wav_decode(ptr + j, s->xdelta, size, s->ysize, + s->xdelta * size, maxval); ptr += s->xdelta * s->ysize * size; } - apply_lut(td->lut, tmp, dsize / sizeof(int16_t)); + apply_lut(td->lut, tmp, dsize / sizeof(uint16_t)); out = td->uncompressed_data; - for (i = 0; i < s->ysize; i++) { + for (i = 0; i < s->ysize; i++) for (j = 0; j < s->nb_channels; j++) { uint16_t *in = tmp + j * s->xdelta * s->ysize + i * s->xdelta; memcpy(out, in, s->xdelta * 2); out += s->xdelta * 2; } - } return 0; } @@ -766,10 +782,10 @@ static int pxr24_uncompress(EXRContext *s, const uint8_t *src, if (uncompress(td->tmp, &dest_len, src, compressed_size) != Z_OK || dest_len != uncompressed_size) - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; out = td->uncompressed_data; - for (i = 0; i < s->ysize; i++) { + for (i = 0; i < s->ysize; i++) for (c = 0; c < s->nb_channels; c++) { EXRChannel *channel = &s->channels[c]; const uint8_t *ptr[4]; @@ -780,12 +796,12 @@ static int pxr24_uncompress(EXRContext *s, const uint8_t *src, ptr[0] = in; ptr[1] = ptr[0] + s->xdelta; ptr[2] = ptr[1] + s->xdelta; - in = ptr[2] + s->xdelta; + in = ptr[2] + s->xdelta; for (j = 0; j < s->xdelta; ++j) { uint32_t diff = (*(ptr[0]++) << 24) | (*(ptr[1]++) << 16) | - (*(ptr[2]++) << 8); + (*(ptr[2]++) << 8); pixel += diff; bytestream_put_le32(&out, pixel); } @@ -793,7 +809,7 @@ static int pxr24_uncompress(EXRContext *s, const uint8_t *src, case EXR_HALF: ptr[0] = in; ptr[1] = ptr[0] + s->xdelta; - in = ptr[1] + s->xdelta; + in = ptr[1] + s->xdelta; for (j = 0; j < s->xdelta; j++) { uint32_t diff = (*(ptr[0]++) << 8) | *(ptr[1]++); @@ -802,10 +818,9 @@ static int pxr24_uncompress(EXRContext *s, const uint8_t *src, } break; default: - av_assert1(0); + return AVERROR_INVALIDDATA; } } - } return 0; } @@ -822,19 +837,20 @@ static int decode_block(AVCodecContext *avctx, void *tdata, uint32_t xdelta = s->xdelta; uint16_t *ptr_x; uint8_t *ptr; - int32_t data_size, line; + uint32_t data_size, line; const uint8_t *src; int axmax = (avctx->width - (s->xmax + 1)) * 2 * s->desc->nb_components; int bxmin = s->xmin * 2 * s->desc->nb_components; int i, x, buf_size = s->buf_size; - int av_unused ret; + int ret; + float one_gamma = 1.0f / s->gamma; - line_offset = AV_RL64(s->table + jobnr * 8); + line_offset = AV_RL64(s->gb.buffer + jobnr * 8); // Check if the buffer has the required bytes needed from the offset if (line_offset > buf_size - 8) return AVERROR_INVALIDDATA; - src = buf + line_offset + 8; + src = buf + line_offset + 8; line = AV_RL32(src - 8); if (line < s->ymin || line > s->ymax) return AVERROR_INVALIDDATA; @@ -843,22 +859,24 @@ static int decode_block(AVCodecContext *avctx, void *tdata, if (data_size <= 0 || data_size > buf_size) return AVERROR_INVALIDDATA; - s->ysize = FFMIN(s->scan_lines_per_block, s->ymax - line + 1); + s->ysize = FFMIN(s->scan_lines_per_block, s->ymax - line + 1); uncompressed_size = s->scan_line_size * s->ysize; - if ((s->compr == EXR_RAW && (data_size != uncompressed_size || + if ((s->compression == EXR_RAW && (data_size != uncompressed_size || line_offset > buf_size - uncompressed_size)) || - (s->compr != EXR_RAW && (data_size > uncompressed_size || + (s->compression != EXR_RAW && (data_size > uncompressed_size || line_offset > buf_size - data_size))) { return AVERROR_INVALIDDATA; } if (data_size < uncompressed_size) { - av_fast_padded_malloc(&td->uncompressed_data, &td->uncompressed_size, uncompressed_size); + av_fast_padded_malloc(&td->uncompressed_data, + &td->uncompressed_size, uncompressed_size); av_fast_padded_malloc(&td->tmp, &td->tmp_size, uncompressed_size); if (!td->uncompressed_data || !td->tmp) return AVERROR(ENOMEM); - switch (s->compr) { + ret = AVERROR_INVALIDDATA; + switch (s->compression) { case EXR_ZIP1: case EXR_ZIP16: ret = zip_uncompress(src, data_size, uncompressed_size, td); @@ -872,7 +890,10 @@ static int decode_block(AVCodecContext *avctx, void *tdata, case EXR_RLE: ret = rle_uncompress(src, data_size, uncompressed_size, td); } - + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "decode_block() failed.\n"); + return ret; + } src = td->uncompressed_data; } @@ -883,7 +904,9 @@ static int decode_block(AVCodecContext *avctx, void *tdata, channel_buffer[3] = src + xdelta * s->channel_offsets[3]; ptr = p->data[0] + line * p->linesize[0]; - for (i = 0; i < s->scan_lines_per_block && line + i <= s->ymax; i++, ptr += p->linesize[0]) { + for (i = 0; + i < s->scan_lines_per_block && line + i <= s->ymax; + i++, ptr += p->linesize[0]) { const uint8_t *r, *g, *b, *a; r = channel_buffer[0]; @@ -892,7 +915,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata, if (channel_buffer[3]) a = channel_buffer[3]; - ptr_x = (uint16_t *)ptr; + ptr_x = (uint16_t *) ptr; // Zero out the start if xmin is not 0 memset(ptr_x, 0, bxmin); @@ -900,18 +923,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)); } @@ -930,256 +965,296 @@ static int decode_block(AVCodecContext *avctx, void *tdata, return 0; } -static int decode_frame(AVCodecContext *avctx, - void *data, - int *got_frame, - AVPacket *avpkt) +/** + * Check if the variable name corresponds to its data type. + * + * @param s the EXRContext + * @param value_name name of the variable to check + * @param value_type type of the variable to check + * @param minimum_length minimum length of the variable data + * + * @return bytes to read containing variable data + * -1 if variable is not found + * 0 if buffer ended prematurely + */ +static int check_header_variable(EXRContext *s, + const char *value_name, + const char *value_type, + unsigned int minimum_length) { - const uint8_t *buf = avpkt->data; - unsigned int buf_size = avpkt->size; - const uint8_t *buf_end = buf + buf_size; + int var_size = -1; - EXRContext *const s = avctx->priv_data; - ThreadFrame frame = { .f = data }; - AVFrame *picture = data; - uint8_t *ptr; + if (bytestream2_get_bytes_left(&s->gb) >= minimum_length && + !strcmp(s->gb.buffer, value_name)) { + // found value_name, jump to value_type (null terminated strings) + s->gb.buffer += strlen(value_name) + 1; + if (!strcmp(s->gb.buffer, value_type)) { + s->gb.buffer += strlen(value_type) + 1; + var_size = bytestream2_get_le32(&s->gb); + // don't go read past boundaries + if (var_size > bytestream2_get_bytes_left(&s->gb)) + var_size = 0; + } else { + // value_type not found, reset the buffer + s->gb.buffer -= strlen(value_name) + 1; + av_log(s->avctx, AV_LOG_WARNING, + "Unknown data type %s for header variable %s.\n", + value_type, value_name); + } + } - int i, y, magic_number, version, flags, ret; - int w = 0; - int h = 0; + return var_size; +} - int out_line_size; - int scan_line_blocks; +static int decode_header(EXRContext *s) +{ + int current_channel_offset = 0; + int magic_number, version, flags, i; - unsigned int current_channel_offset = 0; - - s->xmin = ~0; - s->xmax = ~0; - s->ymin = ~0; - s->ymax = ~0; - s->xdelta = ~0; - s->ydelta = ~0; - s->channel_offsets[0] = -1; - s->channel_offsets[1] = -1; - s->channel_offsets[2] = -1; - s->channel_offsets[3] = -1; - s->pixel_type = -1; - s->nb_channels = 0; - s->compr = -1; - s->buf = buf; - s->buf_size = buf_size; - - if (buf_size < 10) { - av_log(avctx, AV_LOG_ERROR, "Too short header to parse\n"); + if (bytestream2_get_bytes_left(&s->gb) < 10) { + av_log(s->avctx, AV_LOG_ERROR, "Header too short to parse.\n"); return AVERROR_INVALIDDATA; } - magic_number = bytestream_get_le32(&buf); - if (magic_number != 20000630) { // As per documentation of OpenEXR it's supposed to be int 20000630 little-endian - av_log(avctx, AV_LOG_ERROR, "Wrong magic number %d\n", magic_number); + magic_number = bytestream2_get_le32(&s->gb); + if (magic_number != 20000630) { + /* As per documentation of OpenEXR, it is supposed to be + * int 20000630 little-endian */ + av_log(s->avctx, AV_LOG_ERROR, "Wrong magic number %d.\n", magic_number); return AVERROR_INVALIDDATA; } - version = bytestream_get_byte(&buf); + version = bytestream2_get_byte(&s->gb); if (version != 2) { - avpriv_report_missing_feature(avctx, "Version %d", version); + avpriv_report_missing_feature(s->avctx, "Version %d", version); return AVERROR_PATCHWELCOME; } - flags = bytestream_get_le24(&buf); - if (flags & 0x2) { - avpriv_report_missing_feature(avctx, "Tile support"); + flags = bytestream2_get_le24(&s->gb); + if (flags & 0x02) { + avpriv_report_missing_feature(s->avctx, "Tile support"); return AVERROR_PATCHWELCOME; } // Parse the header - while (buf < buf_end && buf[0]) { - unsigned int variable_buffer_data_size; - // Process the channel list - if (check_header_variable(avctx, &buf, buf_end, "channels", "chlist", 38, &variable_buffer_data_size) >= 0) { - const uint8_t *channel_list_end; - if (!variable_buffer_data_size) + while (bytestream2_get_bytes_left(&s->gb) > 0 && *s->gb.buffer) { + int var_size; + if ((var_size = check_header_variable(s, "channels", + "chlist", 38)) >= 0) { + GetByteContext ch_gb; + if (!var_size) return AVERROR_INVALIDDATA; - channel_list_end = buf + variable_buffer_data_size; - while (channel_list_end - buf >= 19) { + bytestream2_init(&ch_gb, s->gb.buffer, var_size); + + while (bytestream2_get_bytes_left(&ch_gb) >= 19) { EXRChannel *channel; enum ExrPixelType current_pixel_type; int channel_index = -1; int xsub, ysub; - const char* b = buf; - - if ( strcmp( s->layer, "" ) != 0 ) { - if ( strncmp( b, s->layer, strlen(s->layer) ) == 0 ) { - b += strlen(s->layer); - if ( *b == '.' ) ++b; /* skip dot if not given */ - av_log( avctx, AV_LOG_INFO, "Layer %s.%s matched\n", - s->layer, b ); + if (strcmp(s->layer, "") != 0) { + if (strncmp(ch_gb.buffer, s->layer, strlen(s->layer)) == 0) { + ch_gb.buffer += strlen(s->layer); + if (*ch_gb.buffer == '.') + ch_gb.buffer++; /* skip dot if not given */ + av_log(s->avctx, AV_LOG_INFO, + "Layer %s.%s matched.\n", s->layer, ch_gb.buffer); } } - - if (!strcmp(b, "R")||!strcmp(b, "X")||!strcmp(b,"U")) + if (!strcmp(ch_gb.buffer, "R") || + !strcmp(ch_gb.buffer, "X") || + !strcmp(ch_gb.buffer, "U")) channel_index = 0; - else if (!strcmp(b, "G")||!strcmp(b, "Y")||!strcmp(b,"V")) + else if (!strcmp(ch_gb.buffer, "G") || + !strcmp(ch_gb.buffer, "Y") || + !strcmp(ch_gb.buffer, "V")) channel_index = 1; - else if (!strcmp(b, "B")||!strcmp(b, "Z")||!strcmp(b,"W")) + else if (!strcmp(ch_gb.buffer, "B") || + !strcmp(ch_gb.buffer, "Z") || + !strcmp(ch_gb.buffer, "W")) channel_index = 2; - else if (!strcmp(b, "A")) + else if (!strcmp(ch_gb.buffer, "A")) channel_index = 3; else - av_log(avctx, AV_LOG_WARNING, "Unsupported channel %.256s\n", buf); + av_log(s->avctx, AV_LOG_WARNING, + "Unsupported channel %.256s.\n", ch_gb.buffer); - while (bytestream_get_byte(&buf) && buf < channel_list_end) - continue; /* skip */ + /* skip until you get a 0 */ + while (bytestream2_get_bytes_left(&ch_gb) > 0 && + bytestream2_get_byte(&ch_gb)) + continue; - if (channel_list_end - * &buf < 4) { - av_log(avctx, AV_LOG_ERROR, "Incomplete header\n"); + if (bytestream2_get_bytes_left(&ch_gb) < 4) { + av_log(s->avctx, AV_LOG_ERROR, "Incomplete header.\n"); return AVERROR_INVALIDDATA; } - current_pixel_type = bytestream_get_le32(&buf); - if (current_pixel_type > 2) { - av_log(avctx, AV_LOG_ERROR, "Unknown pixel type\n"); - return AVERROR_INVALIDDATA; + current_pixel_type = bytestream2_get_le32(&ch_gb); + if (current_pixel_type >= EXR_UNKNOWN) { + avpriv_report_missing_feature(s->avctx, + "Pixel type %d.\n", + current_pixel_type); + return AVERROR_PATCHWELCOME; } - buf += 4; - xsub = bytestream_get_le32(&buf); - ysub = bytestream_get_le32(&buf); + bytestream2_skip(&ch_gb, 4); + xsub = bytestream2_get_le32(&ch_gb); + ysub = bytestream2_get_le32(&ch_gb); if (xsub != 1 || ysub != 1) { - avpriv_report_missing_feature(avctx, "Subsampling %dx%d", xsub, ysub); + avpriv_report_missing_feature(s->avctx, + "Subsampling %dx%d", + xsub, ysub); return AVERROR_PATCHWELCOME; } if (channel_index >= 0) { - if (s->pixel_type != -1 && s->pixel_type != current_pixel_type) { - av_log(avctx, AV_LOG_ERROR, "RGB channels not of the same depth\n"); + if (s->pixel_type != EXR_UNKNOWN && + s->pixel_type != current_pixel_type) { + av_log(s->avctx, AV_LOG_ERROR, + "RGB channels not of the same depth.\n"); return AVERROR_INVALIDDATA; } - s->pixel_type = current_pixel_type; + s->pixel_type = current_pixel_type; s->channel_offsets[channel_index] = current_channel_offset; } - s->channels = av_realloc_f(s->channels, ++s->nb_channels, sizeof(EXRChannel)); + s->channels = av_realloc(s->channels, + ++s->nb_channels * sizeof(EXRChannel)); if (!s->channels) return AVERROR(ENOMEM); - channel = &s->channels[s->nb_channels - 1]; + channel = &s->channels[s->nb_channels - 1]; channel->pixel_type = current_pixel_type; - channel->xsub = xsub; - channel->ysub = ysub; + channel->xsub = xsub; + channel->ysub = ysub; current_channel_offset += 1 << current_pixel_type; } /* Check if all channels are set with an offset or if the channels * are causing an overflow */ - if (FFMIN3(s->channel_offsets[0], s->channel_offsets[1], s->channel_offsets[2]) < 0) { if (s->channel_offsets[0] < 0) - av_log(avctx, AV_LOG_ERROR, "Missing red channel\n"); + av_log(s->avctx, AV_LOG_ERROR, "Missing red channel.\n"); if (s->channel_offsets[1] < 0) - av_log(avctx, AV_LOG_ERROR, "Missing green channel\n"); + av_log(s->avctx, AV_LOG_ERROR, "Missing green channel.\n"); if (s->channel_offsets[2] < 0) - av_log(avctx, AV_LOG_ERROR, "Missing blue channel\n"); + av_log(s->avctx, AV_LOG_ERROR, "Missing blue channel.\n"); return AVERROR_INVALIDDATA; } - buf = channel_list_end; + // skip one last byte and update main gb + s->gb.buffer = ch_gb.buffer + 1; continue; - } else if (check_header_variable(avctx, &buf, buf_end, "dataWindow", "box2i", 31, &variable_buffer_data_size) >= 0) { - if (!variable_buffer_data_size) + } else if ((var_size = check_header_variable(s, "dataWindow", "box2i", + 31)) >= 0) { + if (!var_size) return AVERROR_INVALIDDATA; - s->xmin = AV_RL32(buf); - s->ymin = AV_RL32(buf + 4); - s->xmax = AV_RL32(buf + 8); - s->ymax = AV_RL32(buf + 12); + s->xmin = bytestream2_get_le32(&s->gb); + s->ymin = bytestream2_get_le32(&s->gb); + s->xmax = bytestream2_get_le32(&s->gb); + s->ymax = bytestream2_get_le32(&s->gb); s->xdelta = (s->xmax - s->xmin) + 1; s->ydelta = (s->ymax - s->ymin) + 1; - buf += variable_buffer_data_size; continue; - } else if (check_header_variable(avctx, &buf, buf_end, "displayWindow", "box2i", 34, &variable_buffer_data_size) >= 0) { - if (!variable_buffer_data_size) + } else if ((var_size = check_header_variable(s, "displayWindow", + "box2i", 34)) >= 0) { + if (!var_size) return AVERROR_INVALIDDATA; - w = AV_RL32(buf + 8) + 1; - h = AV_RL32(buf + 12) + 1; + bytestream2_skip(&s->gb, 8); + s->w = bytestream2_get_le32(&s->gb) + 1; + s->h = bytestream2_get_le32(&s->gb) + 1; - buf += variable_buffer_data_size; continue; - } else if (check_header_variable(avctx, &buf, buf_end, "lineOrder", "lineOrder", 25, &variable_buffer_data_size) >= 0) { - if (!variable_buffer_data_size) + } else if ((var_size = check_header_variable(s, "lineOrder", + "lineOrder", 25)) >= 0) { + int line_order; + if (!var_size) return AVERROR_INVALIDDATA; - av_log(avctx, AV_LOG_DEBUG, "line order : %d\n", *buf); - if (*buf > 2) { - av_log(avctx, AV_LOG_ERROR, "Unknown line order\n"); + line_order = bytestream2_get_byte(&s->gb); + av_log(s->avctx, AV_LOG_DEBUG, "line order: %d.\n", line_order); + if (line_order > 2) { + av_log(s->avctx, AV_LOG_ERROR, "Unknown line order.\n"); return AVERROR_INVALIDDATA; } - buf += variable_buffer_data_size; continue; - } else if (check_header_variable(avctx, &buf, buf_end, "pixelAspectRatio", "float", 31, &variable_buffer_data_size) >= 0) { - if (!variable_buffer_data_size) + } else if ((var_size = check_header_variable(s, "pixelAspectRatio", + "float", 31)) >= 0) { + if (!var_size) return AVERROR_INVALIDDATA; - avctx->sample_aspect_ratio = av_d2q(av_int2float(AV_RL32(buf)), 255); + ff_set_sar(s->avctx, + av_d2q(av_int2float(bytestream2_get_le32(&s->gb)), 255)); - buf += variable_buffer_data_size; continue; - } else if (check_header_variable(avctx, &buf, buf_end, "compression", "compression", 29, &variable_buffer_data_size) >= 0) { - if (!variable_buffer_data_size) + } else if ((var_size = check_header_variable(s, "compression", + "compression", 29)) >= 0) { + if (!var_size) return AVERROR_INVALIDDATA; - if (s->compr == -1) - s->compr = *buf; + if (s->compression == EXR_UNKN) + s->compression = bytestream2_get_byte(&s->gb); else - av_log(avctx, AV_LOG_WARNING, "Found more than one compression attribute\n"); + av_log(s->avctx, AV_LOG_WARNING, + "Found more than one compression attribute.\n"); - buf += variable_buffer_data_size; continue; } - // Check if there is enough bytes for a header - if (buf_end - buf <= 9) { - av_log(avctx, AV_LOG_ERROR, "Incomplete header\n"); + // Check if there are enough bytes for a header + if (bytestream2_get_bytes_left(&s->gb) <= 9) { + av_log(s->avctx, AV_LOG_ERROR, "Incomplete header\n"); return AVERROR_INVALIDDATA; } // Process unknown variables - for (i = 0; i < 2; i++) { - // Skip variable name/type - while (++buf < buf_end) - if (buf[0] == 0x0) - break; - } - buf++; + for (i = 0; i < 2; i++) // value_name and value_type + while (bytestream2_get_byte(&s->gb) != 0); + // Skip variable length - if (buf_end - buf >= 5) { - variable_buffer_data_size = get_header_variable_length(&buf, buf_end); - if (!variable_buffer_data_size) { - av_log(avctx, AV_LOG_ERROR, "Incomplete header\n"); - return AVERROR_INVALIDDATA; - } - buf += variable_buffer_data_size; - } + bytestream2_skip(&s->gb, bytestream2_get_le32(&s->gb)); } - if (s->compr == -1) { - av_log(avctx, AV_LOG_ERROR, "Missing compression attribute\n"); + if (s->compression == EXR_UNKN) { + av_log(s->avctx, AV_LOG_ERROR, "Missing compression attribute.\n"); + return AVERROR_INVALIDDATA; + } + s->scan_line_size = s->xdelta * current_channel_offset; + + if (bytestream2_get_bytes_left(&s->gb) <= 0) { + av_log(s->avctx, AV_LOG_ERROR, "Incomplete frame.\n"); return AVERROR_INVALIDDATA; } - if (buf >= buf_end) { - av_log(avctx, AV_LOG_ERROR, "Incomplete frame\n"); - return AVERROR_INVALIDDATA; - } - buf++; + // aaand we are done + bytestream2_skip(&s->gb, 1); + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + EXRContext *s = avctx->priv_data; + ThreadFrame frame = { .f = data }; + AVFrame *picture = data; + uint8_t *ptr; + + int y, ret; + int out_line_size; + int scan_line_blocks; + + bytestream2_init(&s->gb, avpkt->data, avpkt->size); + + if ((ret = decode_header(s)) < 0) + return ret; switch (s->pixel_type) { case EXR_FLOAT: @@ -1193,11 +1268,11 @@ static int decode_frame(AVCodecContext *avctx, avpriv_request_sample(avctx, "32-bit unsigned int"); return AVERROR_PATCHWELCOME; default: - av_log(avctx, AV_LOG_ERROR, "Missing channel list\n"); + av_log(avctx, AV_LOG_ERROR, "Missing channel list.\n"); return AVERROR_INVALIDDATA; } - switch (s->compr) { + switch (s->compression) { case EXR_RAW: case EXR_RLE: case EXR_ZIP1: @@ -1211,49 +1286,41 @@ static int decode_frame(AVCodecContext *avctx, s->scan_lines_per_block = 32; break; default: - avpriv_report_missing_feature(avctx, "Compression %d", s->compr); + avpriv_report_missing_feature(avctx, "Compression %d", s->compression); return AVERROR_PATCHWELCOME; } - // Verify the xmin, xmax, ymin, ymax and xdelta before setting the actual image size - if (s->xmin > s->xmax || - s->ymin > s->ymax || + /* Verify the xmin, xmax, ymin, ymax and xdelta before setting + * the actual image size. */ + if (s->xmin > s->xmax || + s->ymin > s->ymax || s->xdelta != s->xmax - s->xmin + 1 || - s->xmax >= w || s->ymax >= h) { - av_log(avctx, AV_LOG_ERROR, "Wrong sizing or missing size information\n"); + s->xmax >= s->w || + s->ymax >= s->h) { + av_log(avctx, AV_LOG_ERROR, "Wrong or missing size information.\n"); return AVERROR_INVALIDDATA; } - if ((ret = ff_set_dimensions(avctx, w, h)) < 0) + if ((ret = ff_set_dimensions(avctx, s->w, s->h)) < 0) return ret; - s->desc = av_pix_fmt_desc_get(avctx->pix_fmt); - out_line_size = avctx->width * 2 * s->desc->nb_components; - s->scan_line_size = s->xdelta * current_channel_offset; - scan_line_blocks = (s->ydelta + s->scan_lines_per_block - 1) / s->scan_lines_per_block; - - if (s->compr != EXR_RAW) { - size_t thread_data_size, prev_size; - EXRThreadData *m; - - prev_size = s->thread_data_size; - if (av_size_mult(avctx->thread_count, sizeof(EXRThreadData), &thread_data_size)) - return AVERROR(EINVAL); - - m = av_fast_realloc(s->thread_data, &s->thread_data_size, thread_data_size); - if (!m) - return AVERROR(ENOMEM); - s->thread_data = m; - memset(s->thread_data + prev_size, 0, s->thread_data_size - prev_size); - } + s->desc = av_pix_fmt_desc_get(avctx->pix_fmt); + if (!s->desc) + return AVERROR_INVALIDDATA; + out_line_size = avctx->width * 2 * s->desc->nb_components; + scan_line_blocks = (s->ydelta + s->scan_lines_per_block - 1) / + s->scan_lines_per_block; if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; - if (buf_end - buf < scan_line_blocks * 8) + if (bytestream2_get_bytes_left(&s->gb) < scan_line_blocks * 8) return AVERROR_INVALIDDATA; - s->table = buf; - ptr = picture->data[0]; + + // save pointer we are going to use in decode_block + s->buf = avpkt->data; + s->buf_size = avpkt->size; + ptr = picture->data[0]; // Zero out the start if ymin is not 0 for (y = 0; y < s->ymin; y++) { @@ -1273,15 +1340,74 @@ static int decode_frame(AVCodecContext *avctx, picture->pict_type = AV_PICTURE_TYPE_I; *got_frame = 1; - return buf_size; + return avpkt->size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + uint32_t i; + union av_intfloat32 t; + EXRContext *s = avctx->priv_data; + float one_gamma = 1.0f / s->gamma; + + s->avctx = avctx; + s->xmin = ~0; + s->xmax = ~0; + s->ymin = ~0; + s->ymax = ~0; + s->xdelta = ~0; + s->ydelta = ~0; + s->channel_offsets[0] = -1; + s->channel_offsets[1] = -1; + s->channel_offsets[2] = -1; + s->channel_offsets[3] = -1; + s->pixel_type = EXR_UNKNOWN; + s->compression = EXR_UNKN; + s->nb_channels = 0; + s->w = 0; + s->h = 0; + + 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 compreesion types + s->thread_data = av_mallocz_array(avctx->thread_count, sizeof(EXRThreadData)); + if (!s->thread_data) + return AVERROR_INVALIDDATA; + + return 0; +} + +static int decode_init_thread_copy(AVCodecContext *avctx) +{ EXRContext *s = avctx->priv_data; + + // allocate thread data, used for non EXR_RAW compreesion types + s->thread_data = av_mallocz_array(avctx->thread_count, sizeof(EXRThreadData)); + if (!s->thread_data) + return AVERROR_INVALIDDATA; + + return 0; } static av_cold int decode_end(AVCodecContext *avctx) { EXRContext *s = avctx->priv_data; int i; - - for (i = 0; i < s->thread_data_size / sizeof(EXRThreadData); i++) { + for (i = 0; i < avctx->thread_count; i++) { EXRThreadData *td = &s->thread_data[i]; av_freep(&td->uncompressed_data); av_freep(&td->tmp); @@ -1290,20 +1416,39 @@ static av_cold int decode_end(AVCodecContext *avctx) } av_freep(&s->thread_data); - s->thread_data_size = 0; av_freep(&s->channels); return 0; } +#define OFFSET(x) offsetof(EXRContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +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 (experimental/unsupported)", OFFSET(gamma), + AV_OPT_TYPE_FLOAT, { .dbl = 1.0f }, 0.001, FLT_MAX, VD }, + { NULL }, +}; + +static const AVClass exr_class = { + .class_name = "EXR", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_exr_decoder = { - .name = "exr", - .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_EXR, - .priv_data_size = sizeof(EXRContext), - .close = decode_end, - .decode = decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS, - .priv_class = &exr_class, + .name = "exr", + .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_EXR, + .priv_data_size = sizeof(EXRContext), + .init = decode_init, + .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, + .priv_class = &exr_class, }; diff --git a/libavcodec/faxcompr.c b/libavcodec/faxcompr.c index 900851b3f..155f78da6 100644 --- a/libavcodec/faxcompr.c +++ b/libavcodec/faxcompr.c @@ -287,8 +287,8 @@ int ff_ccitt_unpack(AVCodecContext *avctx, const uint8_t *src, int srcsize, int runsize = avctx->width + 2; int has_eol; - runs = av_malloc(runsize * sizeof(runs[0])); - ref = av_malloc(runsize * sizeof(ref[0])); + runs = av_malloc_array(runsize, sizeof(runs[0])); + ref = av_malloc_array(runsize, sizeof(ref[0])); if (!runs || !ref) { ret = AVERROR(ENOMEM); goto fail; diff --git a/libavcodec/fdctdsp.c b/libavcodec/fdctdsp.c new file mode 100644 index 000000000..f75eed508 --- /dev/null +++ b/libavcodec/fdctdsp.c @@ -0,0 +1,50 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "avcodec.h" +#include "dct.h" +#include "faandct.h" +#include "fdctdsp.h" +#include "config.h" + +av_cold void ff_fdctdsp_init(FDCTDSPContext *c, AVCodecContext *avctx) +{ + const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; + + if (avctx->bits_per_raw_sample == 10) { + c->fdct = ff_jpeg_fdct_islow_10; + c->fdct248 = ff_fdct248_islow_10; + } else { + if (avctx->dct_algo == FF_DCT_FASTINT) { + c->fdct = ff_fdct_ifast; + c->fdct248 = ff_fdct_ifast248; + } else if (avctx->dct_algo == FF_DCT_FAAN) { + c->fdct = ff_faandct; + c->fdct248 = ff_faandct248; + } else { + c->fdct = ff_jpeg_fdct_islow_8; // slow/accurate/default + c->fdct248 = ff_fdct248_islow_8; + } + } + + if (ARCH_PPC) + ff_fdctdsp_init_ppc(c, avctx, high_bit_depth); + if (ARCH_X86) + ff_fdctdsp_init_x86(c, avctx, high_bit_depth); +} diff --git a/libavcodec/fdctdsp.h b/libavcodec/fdctdsp.h new file mode 100644 index 000000000..3e1f683b9 --- /dev/null +++ b/libavcodec/fdctdsp.h @@ -0,0 +1,37 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_FDCTDSP_H +#define AVCODEC_FDCTDSP_H + +#include + +#include "avcodec.h" + +typedef struct FDCTDSPContext { + void (*fdct)(int16_t *block /* align 16 */); + void (*fdct248)(int16_t *block /* align 16 */); +} FDCTDSPContext; + +void ff_fdctdsp_init(FDCTDSPContext *c, AVCodecContext *avctx); +void ff_fdctdsp_init_ppc(FDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); +void ff_fdctdsp_init_x86(FDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); + +#endif /* AVCODEC_FDCTDSP_H */ diff --git a/libavcodec/fft-test.c b/libavcodec/fft-test.c index ef1d62240..6af6bcb80 100644 --- a/libavcodec/fft-test.c +++ b/libavcodec/fft-test.c @@ -75,7 +75,7 @@ static void fft_ref_init(int nbits, int inverse) double c1, s1, alpha; n = 1 << nbits; - exptab = av_malloc((n / 2) * sizeof(*exptab)); + exptab = av_malloc_array((n / 2), sizeof(*exptab)); for (i = 0; i < (n/2); i++) { alpha = 2 * M_PI * (float)i / (float)n; @@ -117,6 +117,7 @@ static void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits) } } +#if CONFIG_MDCT static void imdct_ref(FFTSample *out, FFTSample *in, int nbits) { int n = 1<fft_permute(s, tab); @@ -384,6 +394,7 @@ int main(int argc, char **argv) err = check_diff((FFTSample *)tab_ref, (FFTSample *)tab, fft_size * 2, 1.0); break; #if FFT_FLOAT +#if CONFIG_RDFT case TRANSFORM_RDFT: fft_size_2 = fft_size >> 1; if (do_inverse) { @@ -415,6 +426,8 @@ int main(int argc, char **argv) err = check_diff((float *)tab_ref, (float *)tab2, fft_size, 1.0); } break; +#endif /* CONFIG_RDFT */ +#if CONFIG_DCT case TRANSFORM_DCT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); d->dct_calc(d, (FFTSample *)tab); @@ -425,6 +438,7 @@ int main(int argc, char **argv) } err = check_diff((float *)tab_ref, (float *)tab, fft_size, 1.0); break; +#endif /* CONFIG_DCT */ #endif } @@ -438,7 +452,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 +478,7 @@ int main(int argc, char **argv) #endif } } - duration = av_gettime() - time_start; + duration = av_gettime_relative() - time_start; if (duration >= 1000000) break; nb_its *= 2; @@ -476,21 +490,25 @@ int main(int argc, char **argv) } switch (transform) { +#if CONFIG_MDCT case TRANSFORM_MDCT: ff_mdct_end(m); break; +#endif /* CONFIG_MDCT */ case TRANSFORM_FFT: ff_fft_end(s); break; #if FFT_FLOAT +# if CONFIG_RDFT case TRANSFORM_RDFT: ff_rdft_end(r); break; +# endif /* CONFIG_RDFT */ # if CONFIG_DCT case TRANSFORM_DCT: ff_dct_end(d); break; -# endif +# endif /* CONFIG_DCT */ #endif } diff --git a/libavcodec/fft.h b/libavcodec/fft.h index 1c48145b0..2d7e25498 100644 --- a/libavcodec/fft.h +++ b/libavcodec/fft.h @@ -148,6 +148,7 @@ void ff_init_ff_cos_tabs(int index); */ int ff_fft_init(FFTContext *s, int nbits, int inverse); +void ff_fft_init_aarch64(FFTContext *s); void ff_fft_init_x86(FFTContext *s); void ff_fft_init_arm(FFTContext *s); void ff_fft_init_mips(FFTContext *s); diff --git a/libavcodec/fft_table.h b/libavcodec/fft_table.h index 687e5b94f..7f3142d7a 100644 --- a/libavcodec/fft_table.h +++ b/libavcodec/fft_table.h @@ -56,7 +56,7 @@ #include "libavcodec/fft.h" -#define MAX_LOG2_NFFT 16 //!< Specifies maxiumum allowed fft size +#define MAX_LOG2_NFFT 16 //!< Specifies maximum allowed fft size #define MAX_FFT_SIZE (1 << MAX_LOG2_NFFT) extern int32_t w_tab_sr[]; diff --git a/libavcodec/fft_template.c b/libavcodec/fft_template.c index 97224fe5a..b8d6417fd 100644 --- a/libavcodec/fft_template.c +++ b/libavcodec/fft_template.c @@ -170,6 +170,7 @@ av_cold int ff_fft_init(FFTContext *s, int nbits, int inverse) } #else /* FFT_FIXED_32 */ #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); diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c index f8556b01f..ab58a6074 100644 --- a/libavcodec/ffv1.c +++ b/libavcodec/ffv1.c @@ -54,8 +54,6 @@ av_cold int ffv1_common_init(AVCodecContext *avctx) if (!s->picture.f || !s->last_picture.f) return AVERROR(ENOMEM); - ff_dsputil_init(&s->dsp, avctx); - s->width = avctx->width; s->height = avctx->height; @@ -77,13 +75,13 @@ av_cold int ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs) if (fs->ac) { if (!p->state) - p->state = av_malloc(CONTEXT_SIZE * p->context_count * + p->state = av_malloc_array(p->context_count, CONTEXT_SIZE * sizeof(uint8_t)); if (!p->state) return AVERROR(ENOMEM); } else { if (!p->vlc_state) - p->vlc_state = av_malloc(p->context_count * sizeof(VlcState)); + p->vlc_state = av_malloc_array(p->context_count, sizeof(VlcState)); if (!p->vlc_state) return AVERROR(ENOMEM); } @@ -139,7 +137,7 @@ av_cold int ffv1_init_slice_contexts(FFV1Context *f) fs->slice_x = sxs; fs->slice_y = sys; - fs->sample_buffer = av_malloc(3 * MAX_PLANES * (fs->width + 6) * + fs->sample_buffer = av_malloc_array((fs->width + 6), 3 * MAX_PLANES * sizeof(*fs->sample_buffer)); if (!fs->sample_buffer) return AVERROR(ENOMEM); @@ -152,7 +150,7 @@ int ffv1_allocate_initial_states(FFV1Context *f) int i; for (i = 0; i < f->quant_table_count; i++) { - f->initial_states[i] = av_malloc(f->context_count[i] * + f->initial_states[i] = av_malloc_array(f->context_count[i], sizeof(*f->initial_states[i])); if (!f->initial_states[i]) return AVERROR(ENOMEM); diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h index 9d8329f00..5081397f5 100644 --- a/libavcodec/ffv1.h +++ b/libavcodec/ffv1.h @@ -35,7 +35,6 @@ #include "libavutil/pixdesc.h" #include "libavutil/timer.h" #include "avcodec.h" -#include "dsputil.h" #include "get_bits.h" #include "internal.h" #include "mathops.h" @@ -54,8 +53,6 @@ #define MAX_QUANT_TABLES 8 #define MAX_CONTEXT_INPUTS 5 -extern const uint8_t ff_log2_run[41]; - typedef struct VlcState { int16_t drift; uint16_t error_sum; @@ -118,8 +115,6 @@ typedef struct FFV1Context { int gob_count; int quant_table_count; - DSPContext dsp; - struct FFV1Context *slice_context[MAX_SLICES]; int slice_count; int num_v_slices; diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index d7dd11054..b10e212ce 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -330,6 +330,15 @@ static int decode_slice_header(FFV1Context *f, FFV1Context *fs) } f->cur->sample_aspect_ratio.num = get_symbol(c, state, 0); f->cur->sample_aspect_ratio.den = get_symbol(c, state, 0); + + if (av_image_check_sar(f->width, f->height, + f->cur->sample_aspect_ratio) < 0) { + av_log(f->avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\n", + f->cur->sample_aspect_ratio.num, + f->cur->sample_aspect_ratio.den); + f->cur->sample_aspect_ratio = (AVRational){ 0, 1 }; + } + if (fs->version > 3) { fs->slice_reset_contexts = get_rac(c, state); fs->slice_coding_mode = get_symbol(c, state, 0); @@ -342,6 +351,7 @@ static int decode_slice_header(FFV1Context *f, FFV1Context *fs) } } } + return 0; } @@ -380,10 +390,10 @@ static int decode_slice(AVCodecContext *c, void *arg) pdst->vlc_state = NULL; if (fssrc->ac) { - pdst->state = av_malloc(CONTEXT_SIZE * psrc->context_count); + pdst->state = av_malloc_array(CONTEXT_SIZE, psrc->context_count); memcpy(pdst->state, psrc->state, CONTEXT_SIZE * psrc->context_count); } else { - pdst->vlc_state = av_malloc(sizeof(*pdst->vlc_state) * psrc->context_count); + pdst->vlc_state = av_malloc_array(sizeof(*pdst->vlc_state), psrc->context_count); memcpy(pdst->vlc_state, psrc->vlc_state, sizeof(*pdst->vlc_state) * psrc->context_count); } } diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index c7479e649..b63ed429d 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -549,7 +549,7 @@ static int write_extradata(FFV1Context *f) f->avctx->extradata_size = 10000 + 4 + (11 * 11 * 5 * 5 * 5 + 11 * 11 * 11) * 32; - f->avctx->extradata = av_malloc(f->avctx->extradata_size); + f->avctx->extradata = av_malloc(f->avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); if (!f->avctx->extradata) return AVERROR(ENOMEM); ff_init_range_encoder(c, f->avctx->extradata, f->avctx->extradata_size); diff --git a/libavcodec/fic.c b/libavcodec/fic.c index 6b8ac83b5..d08d240ef 100644 --- a/libavcodec/fic.c +++ b/libavcodec/fic.c @@ -24,7 +24,6 @@ #include "libavutil/common.h" #include "avcodec.h" #include "internal.h" -#include "dsputil.h" #include "get_bits.h" #include "golomb.h" @@ -39,9 +38,7 @@ typedef struct FICThreadContext { typedef struct FICContext { AVCodecContext *avctx; AVFrame *frame; - - DSPContext dsp; - ScanTable scantable; + AVFrame *final_frame; FICThreadContext *slice_data; int slice_data_size; @@ -52,6 +49,8 @@ typedef struct FICContext { int aligned_width, aligned_height; int num_slices, slice_h; + + uint8_t cursor_buf[4096]; } FICContext; static const uint8_t fic_qmat_hq[64] = { @@ -80,6 +79,56 @@ static const uint8_t fic_header[7] = { 0, 0, 1, 'F', 'I', 'C', 'V' }; #define FIC_HEADER_SIZE 27 +static av_always_inline void fic_idct(int16_t *blk, int step, int shift, int rnd) +{ + const int t0 = 27246 * blk[3 * step] + 18405 * blk[5 * step]; + const int t1 = 27246 * blk[5 * step] - 18405 * blk[3 * step]; + const int t2 = 6393 * blk[7 * step] + 32139 * blk[1 * step]; + const int t3 = 6393 * blk[1 * step] - 32139 * blk[7 * step]; + const int t4 = 5793 * (t2 + t0 + 0x800 >> 12); + const int t5 = 5793 * (t3 + t1 + 0x800 >> 12); + const int t6 = t2 - t0; + const int t7 = t3 - t1; + const int t8 = 17734 * blk[2 * step] - 42813 * blk[6 * step]; + const int t9 = 17734 * blk[6 * step] + 42814 * blk[2 * step]; + const int tA = (blk[0 * step] - blk[4 * step] << 15) + rnd; + const int tB = (blk[0 * step] + blk[4 * step] << 15) + rnd; + blk[0 * step] = ( t4 + t9 + tB) >> shift; + blk[1 * step] = ( t6 + t7 + t8 + tA) >> shift; + blk[2 * step] = ( t6 - t7 - t8 + tA) >> shift; + blk[3 * step] = ( t5 - t9 + tB) >> shift; + blk[4 * step] = ( -t5 - t9 + tB) >> shift; + blk[5 * step] = (-(t6 - t7) - t8 + tA) >> shift; + blk[6 * step] = (-(t6 + t7) + t8 + tA) >> shift; + blk[7 * step] = ( -t4 + t9 + tB) >> shift; +} + +static void fic_idct_put(uint8_t *dst, int stride, int16_t *block) +{ + int i, j; + int16_t *ptr; + + ptr = block; + fic_idct(ptr++, 8, 13, (1 << 12) + (1 << 17)); + for (i = 1; i < 8; i++) { + fic_idct(ptr, 8, 13, 1 << 12); + ptr++; + } + + ptr = block; + for (i = 0; i < 8; i++) { + fic_idct(ptr, 1, 20, 0); + ptr += 8; + } + + ptr = block; + for (j = 0; j < 8; j++) { + for (i = 0; i < 8; i++) + dst[i] = av_clip_uint8(ptr[i]); + dst += stride; + ptr += 8; + } +} static int fic_decode_block(FICContext *ctx, GetBitContext *gb, uint8_t *dst, int stride, int16_t *block) { @@ -94,16 +143,17 @@ static int fic_decode_block(FICContext *ctx, GetBitContext *gb, return 0; } - ctx->dsp.clear_block(block); + memset(block, 0, sizeof(*block) * 64); num_coeff = get_bits(gb, 7); if (num_coeff > 64) return AVERROR_INVALIDDATA; for (i = 0; i < num_coeff; i++) - block[ctx->scantable.permutated[i]] = get_se_golomb(gb) * ctx->qmat[i]; + block[ff_zigzag_direct[i]] = get_se_golomb(gb) * + ctx->qmat[ff_zigzag_direct[i]]; - ctx->dsp.idct_put(dst, stride, block); + fic_idct_put(dst, stride, block); return 0; } @@ -140,6 +190,69 @@ static int fic_decode_slice(AVCodecContext *avctx, void *tdata) return 0; } +static av_always_inline void fic_alpha_blend(uint8_t *dst, uint8_t *src, + int size, uint8_t *alpha) +{ + int i; + + for (i = 0; i < size; i++) + dst[i] += ((src[i] - dst[i]) * alpha[i]) >> 8; +} + +static void fic_draw_cursor(AVCodecContext *avctx, int cur_x, int cur_y) +{ + FICContext *ctx = avctx->priv_data; + uint8_t *ptr = ctx->cursor_buf; + uint8_t *dstptr[3]; + uint8_t planes[4][1024]; + uint8_t chroma[3][256]; + int i, j, p; + + /* Convert to YUVA444. */ + for (i = 0; i < 1024; i++) { + planes[0][i] = (( 25 * ptr[0] + 129 * ptr[1] + 66 * ptr[2]) / 255) + 16; + planes[1][i] = ((-38 * ptr[0] + 112 * ptr[1] + -74 * ptr[2]) / 255) + 128; + planes[2][i] = ((-18 * ptr[0] + 112 * ptr[1] + -94 * ptr[2]) / 255) + 128; + planes[3][i] = ptr[3]; + + ptr += 4; + } + + /* Subsample chroma. */ + for (i = 0; i < 32; i += 2) + for (j = 0; j < 32; j += 2) + for (p = 0; p < 3; p++) + chroma[p][16 * (i / 2) + j / 2] = (planes[p + 1][32 * i + j ] + + planes[p + 1][32 * i + j + 1] + + planes[p + 1][32 * (i + 1) + j ] + + planes[p + 1][32 * (i + 1) + j + 1]) / 4; + + /* Seek to x/y pos of cursor. */ + for (i = 0; i < 3; i++) + dstptr[i] = ctx->final_frame->data[i] + + (ctx->final_frame->linesize[i] * (cur_y >> !!i)) + + (cur_x >> !!i) + !!i; + + /* Copy. */ + for (i = 0; i < FFMIN(32, avctx->height - cur_y) - 1; i += 2) { + int lsize = FFMIN(32, avctx->width - cur_x); + int csize = lsize / 2; + + fic_alpha_blend(dstptr[0], + planes[0] + i * 32, lsize, planes[3] + i * 32); + fic_alpha_blend(dstptr[0] + ctx->final_frame->linesize[0], + planes[0] + (i + 1) * 32, lsize, planes[3] + (i + 1) * 32); + fic_alpha_blend(dstptr[1], + chroma[0] + (i / 2) * 16, csize, chroma[2] + (i / 2) * 16); + fic_alpha_blend(dstptr[2], + chroma[1] + (i / 2) * 16, csize, chroma[2] + (i / 2) * 16); + + dstptr[0] += ctx->final_frame->linesize[0] * 2; + dstptr[1] += ctx->final_frame->linesize[1]; + dstptr[2] += ctx->final_frame->linesize[2]; + } +} + static int fic_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { @@ -149,6 +262,8 @@ static int fic_decode_frame(AVCodecContext *avctx, void *data, int slice, nslices; int msize; int tsize; + int cur_x, cur_y; + int skip_cursor = 0; uint8_t *sdata; if ((ret = ff_reget_buffer(avctx, ctx->frame)) < 0) { @@ -182,10 +297,34 @@ static int fic_decode_frame(AVCodecContext *avctx, void *data, /* Skip cursor data. */ tsize = AV_RB24(src + 24); if (tsize > avpkt->size - FIC_HEADER_SIZE) { - av_log(avctx, AV_LOG_ERROR, "Invalid cursor data size.\n"); + av_log(avctx, AV_LOG_ERROR, + "Packet is too small to contain cursor (%d vs %d bytes).\n", + tsize, avpkt->size - FIC_HEADER_SIZE); return AVERROR_INVALIDDATA; } + if (tsize < 32) { + av_log(avctx, AV_LOG_WARNING, + "Cursor data too small. Skipping cursor.\n"); + skip_cursor = 1; + } + + /* Cursor position. */ + cur_x = AV_RL16(src + 33); + cur_y = AV_RL16(src + 35); + if (cur_x > avctx->width || cur_y > avctx->height) { + av_log(avctx, AV_LOG_WARNING, + "Invalid cursor position: (%d,%d). Skipping cusor.\n", + cur_x, cur_y); + skip_cursor = 1; + } + + if (AV_RL16(src + 37) != 32 || AV_RL16(src + 39) != 32) { + av_log(avctx, AV_LOG_WARNING, + "Invalid cursor size. Skipping cursor.\n"); + skip_cursor = 1; + } + /* Slice height for all but the last slice. */ ctx->slice_h = 16 * (ctx->aligned_height >> 4) / nslices; if (ctx->slice_h % 16) @@ -250,9 +389,28 @@ static int fic_decode_frame(AVCodecContext *avctx, void *data, NULL, nslices, sizeof(ctx->slice_data[0]))) < 0) return ret; + av_frame_free(&ctx->final_frame); + ctx->final_frame = av_frame_clone(ctx->frame); + if (!ctx->final_frame) { + av_log(avctx, AV_LOG_ERROR, "Could not clone frame buffer.\n"); + return AVERROR(ENOMEM); + } + + /* Make sure we use a user-supplied buffer. */ + if ((ret = ff_reget_buffer(avctx, ctx->final_frame)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not make frame writable.\n"); + return ret; + } + + /* Draw cursor. */ + if (!skip_cursor) { + memcpy(ctx->cursor_buf, src + 59, 32 * 32 * 4); + fic_draw_cursor(avctx, cur_x, cur_y); + } + skip: *got_frame = 1; - if ((ret = av_frame_ref(data, ctx->frame)) < 0) + if ((ret = av_frame_ref(data, ctx->final_frame)) < 0) return ret; return avpkt->size; @@ -263,6 +421,7 @@ static av_cold int fic_decode_close(AVCodecContext *avctx) FICContext *ctx = avctx->priv_data; av_freep(&ctx->slice_data); + av_frame_free(&ctx->final_frame); av_frame_free(&ctx->frame); return 0; @@ -284,10 +443,6 @@ static av_cold int fic_decode_init(AVCodecContext *avctx) if (!ctx->frame) return AVERROR(ENOMEM); - ff_dsputil_init(&ctx->dsp, avctx); - - ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, ff_zigzag_direct); - return 0; } diff --git a/libavcodec/flac.c b/libavcodec/flac.c index 3874b6cce..aeb276bcd 100644 --- a/libavcodec/flac.c +++ b/libavcodec/flac.c @@ -225,7 +225,10 @@ void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo * avctx->channels = s->channels; avctx->sample_rate = s->samplerate; avctx->bits_per_raw_sample = s->bps; - ff_flac_set_channel_layout(avctx); + + if (!avctx->channel_layout || + av_get_channel_layout_nb_channels(avctx->channel_layout) != avctx->channels) + ff_flac_set_channel_layout(avctx); s->samples = get_bits64(&gb, 36); @@ -233,14 +236,10 @@ void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo * skip_bits_long(&gb, 64); /* md5 sum */ } +#if LIBAVCODEC_VERSION_MAJOR < 56 void avpriv_flac_parse_block_header(const uint8_t *block_header, int *last, int *type, int *size) { - int tmp = bytestream_get_byte(&block_header); - if (last) - *last = tmp & 0x80; - if (type) - *type = tmp & 0x7F; - if (size) - *size = bytestream_get_be24(&block_header); + flac_parse_block_header(block_header, last, type, size); } +#endif diff --git a/libavcodec/flac.h b/libavcodec/flac.h index 13e863b87..b4f28cfcb 100644 --- a/libavcodec/flac.h +++ b/libavcodec/flac.h @@ -28,6 +28,7 @@ #define AVCODEC_FLAC_H #include "avcodec.h" +#include "bytestream.h" #include "get_bits.h" #define FLAC_STREAMINFO_SIZE 34 @@ -109,15 +110,10 @@ int avpriv_flac_is_extradata_valid(AVCodecContext *avctx, enum FLACExtradataFormat *format, uint8_t **streaminfo_start); -/** - * Parse the metadata block parameters from the header. - * @param[in] block_header header data, at least 4 bytes - * @param[out] last indicator for last metadata block - * @param[out] type metadata block type - * @param[out] size metadata block size - */ +#if LIBAVCODEC_VERSION_MAJOR < 56 void avpriv_flac_parse_block_header(const uint8_t *block_header, int *last, int *type, int *size); +#endif /** * Calculate an estimate for the maximum frame size based on verbatim mode. @@ -140,4 +136,23 @@ int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, void ff_flac_set_channel_layout(AVCodecContext *avctx); +/** + * Parse the metadata block parameters from the header. + * @param[in] block_header header data, at least 4 bytes + * @param[out] last indicator for last metadata block + * @param[out] type metadata block type + * @param[out] size metadata block size + */ +static av_always_inline void flac_parse_block_header(const uint8_t *block_header, + int *last, int *type, int *size) +{ + int tmp = bytestream_get_byte(&block_header); + if (last) + *last = tmp & 0x80; + if (type) + *type = tmp & 0x7F; + if (size) + *size = bytestream_get_be24(&block_header); +} + #endif /* AVCODEC_FLAC_H */ diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c index ba1f060fd..68c915e9c 100644 --- a/libavcodec/flac_parser.c +++ b/libavcodec/flac_parser.c @@ -489,6 +489,14 @@ static int get_best_header(FLACParseContext* fpc, const uint8_t **poutbuf, &fpc->wrap_buf, &fpc->wrap_buf_allocated_size); + + if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS){ + if (header->fi.is_var_size) + fpc->pc->pts = header->fi.frame_or_sample_num; + else if (header->best_child) + fpc->pc->pts = header->fi.frame_or_sample_num * header->fi.blocksize; + } + fpc->best_header_valid = 0; fpc->last_fi_valid = 1; fpc->last_fi = header->fi; @@ -516,6 +524,11 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, s->duration = fi.blocksize; if (!avctx->sample_rate) avctx->sample_rate = fi.samplerate; + if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS){ + fpc->pc->pts = fi.frame_or_sample_num; + if (!fi.is_var_size) + fpc->pc->pts *= fi.blocksize; + } } *poutbuf = buf; *poutbuf_size = buf_size; @@ -599,7 +612,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, if ( av_fifo_space(fpc->fifo_buf) < read_end - read_start && av_fifo_realloc2(fpc->fifo_buf, (read_end - read_start) + 2*av_fifo_size(fpc->fifo_buf)) < 0) { av_log(avctx, AV_LOG_ERROR, - "couldn't reallocate buffer of size %td\n", + "couldn't reallocate buffer of size %"PTRDIFF_SPECIFIER"\n", (read_end - read_start) + av_fifo_size(fpc->fifo_buf)); goto handle_error; } @@ -694,7 +707,7 @@ static av_cold int flac_parse_init(AVCodecParserContext *c) fpc->pc = c; /* There will generally be FLAC_MIN_HEADERS buffered in the fifo before it drains. This is allocated early to avoid slow reallocation. */ - fpc->fifo_buf = av_fifo_alloc(FLAC_AVG_FRAME_SIZE * (FLAC_MIN_HEADERS + 3)); + fpc->fifo_buf = av_fifo_alloc_array(FLAC_MIN_HEADERS + 3, FLAC_AVG_FRAME_SIZE); if (!fpc->fifo_buf) return AVERROR(ENOMEM); return 0; @@ -711,7 +724,7 @@ static void flac_parse_close(AVCodecParserContext *c) av_free(curr); curr = temp; } - av_fifo_free(fpc->fifo_buf); + av_fifo_freep(&fpc->fifo_buf); av_free(fpc->wrap_buf); } diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c index f63a918b1..b8d45b8e1 100644 --- a/libavcodec/flacdec.c +++ b/libavcodec/flacdec.c @@ -162,7 +162,7 @@ static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size) /* need more data */ return 0; } - avpriv_flac_parse_block_header(&buf[4], NULL, &metadata_type, &metadata_size); + flac_parse_block_header(&buf[4], NULL, &metadata_type, &metadata_size); if (metadata_type != FLAC_METADATA_TYPE_STREAMINFO || metadata_size != FLAC_STREAMINFO_SIZE) { return AVERROR_INVALIDDATA; @@ -193,7 +193,7 @@ static int get_metadata_size(const uint8_t *buf, int buf_size) do { if (buf_end - buf < 4) return 0; - avpriv_flac_parse_block_header(buf, &metadata_last, NULL, &metadata_size); + flac_parse_block_header(buf, &metadata_last, NULL, &metadata_size); buf += 4; if (buf_end - buf < metadata_size) { /* need more data in order to read the complete header */ @@ -512,12 +512,12 @@ static int flac_decode_frame(AVCodecContext *avctx, void *data, } if (buf_size > 5 && !memcmp(buf, "\177FLAC", 5)) { - av_log(s->avctx, AV_LOG_DEBUG, "skiping flac header packet 1\n"); + av_log(s->avctx, AV_LOG_DEBUG, "skipping flac header packet 1\n"); return buf_size; } if (buf_size > 0 && (*buf & 0x7F) == FLAC_METADATA_TYPE_VORBIS_COMMENT) { - av_log(s->avctx, AV_LOG_DEBUG, "skiping vorbis comment\n"); + av_log(s->avctx, AV_LOG_DEBUG, "skipping vorbis comment\n"); return buf_size; } diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c index 1fc8c4ce6..3a3b2ae9f 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -25,7 +25,7 @@ #include "libavutil/md5.h" #include "libavutil/opt.h" #include "avcodec.h" -#include "dsputil.h" +#include "bswapdsp.h" #include "put_bits.h" #include "golomb.h" #include "internal.h" @@ -113,8 +113,11 @@ typedef struct FlacEncodeContext { struct AVMD5 *md5ctx; uint8_t *md5_buffer; unsigned int md5_buffer_size; - DSPContext dsp; + BswapDSPContext bdsp; FLACDSPContext flac_dsp; + + int flushed; + int64_t next_pts; } FlacEncodeContext; @@ -424,7 +427,7 @@ static av_cold int flac_encode_init(AVCodecContext *avctx) ret = ff_lpc_init(&s->lpc_ctx, avctx->frame_size, s->options.max_prediction_order, FF_LPC_TYPE_LEVINSON); - ff_dsputil_init(&s->dsp, avctx); + ff_bswapdsp_init(&s->bdsp); ff_flacdsp_init(&s->flac_dsp, avctx->sample_fmt, avctx->bits_per_raw_sample); @@ -649,7 +652,7 @@ 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)); + udata = av_malloc_array(n, sizeof(uint32_t)); for (i = 0; i < n; i++) udata[i] = (2*data[i]) ^ (data[i]>>31); @@ -1203,8 +1206,8 @@ static int update_md5_sum(FlacEncodeContext *s, const void *samples) if (s->avctx->bits_per_raw_sample <= 16) { buf = (const uint8_t *)samples; #if HAVE_BIGENDIAN - s->dsp.bswap16_buf((uint16_t *)s->md5_buffer, - (const uint16_t *)samples, buf_size / 2); + s->bdsp.bswap16_buf((uint16_t *) s->md5_buffer, + (const uint16_t *) samples, buf_size / 2); buf = s->md5_buffer; #endif } else { @@ -1239,6 +1242,20 @@ static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, s->max_framesize = s->max_encoded_framesize; av_md5_final(s->md5ctx, s->md5sum); write_streaminfo(s, avctx->extradata); + + if (avctx->side_data_only_packets && !s->flushed) { + uint8_t *side_data = av_packet_new_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, + avctx->extradata_size); + if (!side_data) + return AVERROR(ENOMEM); + memcpy(side_data, avctx->extradata, avctx->extradata_size); + + avpkt->pts = s->next_pts; + + *got_packet_ptr = 1; + s->flushed = 1; + } + return 0; } @@ -1289,6 +1306,9 @@ static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, avpkt->pts = frame->pts; avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples); avpkt->size = out_bytes; + + s->next_pts = avpkt->pts + avpkt->duration; + *got_packet_ptr = 1; return 0; } diff --git a/libavcodec/flvdec.c b/libavcodec/flvdec.c index f425f0042..3b048f666 100644 --- a/libavcodec/flvdec.c +++ b/libavcodec/flvdec.c @@ -22,11 +22,12 @@ #include "flv.h" #include "libavutil/imgutils.h" -void ff_flv2_decode_ac_esc(GetBitContext *gb, int *level, int *run, int *last){ +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){ + *run = get_bits(gb, 6); + if (is11) { *level = get_sbits(gb, 11); } else { *level = get_sbits(gb, 7); @@ -47,45 +48,45 @@ int ff_flv_decode_picture_header(MpegEncContext *s) av_log(s->avctx, AV_LOG_ERROR, "Bad picture format\n"); return AVERROR_INVALIDDATA; } - s->h263_flv = format+1; + s->h263_flv = format + 1; s->picture_number = get_bits(&s->gb, 8); /* picture timestamp */ - format = get_bits(&s->gb, 3); + format = get_bits(&s->gb, 3); switch (format) { case 0: - width = get_bits(&s->gb, 8); + width = get_bits(&s->gb, 8); height = get_bits(&s->gb, 8); break; case 1: - width = get_bits(&s->gb, 16); + width = get_bits(&s->gb, 16); height = get_bits(&s->gb, 16); break; case 2: - width = 352; + width = 352; height = 288; break; case 3: - width = 176; + width = 176; height = 144; break; case 4: - width = 128; + width = 128; height = 96; break; case 5: - width = 320; + width = 320; height = 240; break; case 6: - width = 160; + width = 160; height = 120; break; default: width = height = 0; break; } - if(av_image_check_size(width, height, 0, s->avctx)) + if (av_image_check_size(width, height, 0, s->avctx)) return AVERROR(EINVAL); - s->width = width; + s->width = width; s->height = height; s->pict_type = AV_PICTURE_TYPE_I + get_bits(&s->gb, 2); @@ -94,29 +95,29 @@ int ff_flv_decode_picture_header(MpegEncContext *s) s->pict_type = AV_PICTURE_TYPE_P; skip_bits1(&s->gb); /* deblocking flag */ - s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); + s->chroma_qscale = s->qscale = get_bits(&s->gb, 5); s->h263_plus = 0; - s->unrestricted_mv = 1; + s->unrestricted_mv = 1; s->h263_long_vectors = 0; /* PEI */ if (skip_1stop_8data_bits(&s->gb) < 0) return AVERROR_INVALIDDATA; + s->f_code = 1; if (s->ehc_mode) s->avctx->sample_aspect_ratio= (AVRational){1,2}; - if(s->avctx->debug & FF_DEBUG_PICT_INFO){ + if (s->avctx->debug & FF_DEBUG_PICT_INFO) { av_log(s->avctx, AV_LOG_DEBUG, "%c esc_type:%d, qp:%d num:%d\n", s->droppable ? 'D' : av_get_picture_type_char(s->pict_type), s->h263_flv - 1, s->qscale, s->picture_number); } - s->y_dc_scale_table= - s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + s->y_dc_scale_table = s->c_dc_scale_table = ff_mpeg1_dc_scale_table; return 0; } @@ -132,5 +133,8 @@ AVCodec ff_flv_decoder = { .decode = ff_h263_decode_frame, .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, .max_lowres = 3, - .pix_fmts = ff_pixfmt_list_420, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, }; diff --git a/libavcodec/frame_thread_encoder.c b/libavcodec/frame_thread_encoder.c index 3ab5b9103..9e176985e 100644 --- a/libavcodec/frame_thread_encoder.c +++ b/libavcodec/frame_thread_encoder.c @@ -142,7 +142,7 @@ int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options){ if (avctx->codec_id == AV_CODEC_ID_HUFFYUV || avctx->codec_id == AV_CODEC_ID_FFVHUFF) { - // huffyuv doesnt support these with multiple frame threads currently + // huffyuv does not support these with multiple frame threads currently if (avctx->context_model > 0 || (avctx->flags & CODEC_FLAG_PASS1)) { av_log(avctx, AV_LOG_WARNING, "Forcing thread count to 1 for huffyuv encoding with first pass or context 1\n"); @@ -168,7 +168,7 @@ int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options){ c->parent_avctx = avctx; - c->task_fifo = av_fifo_alloc(sizeof(Task) * BUFFER_SIZE); + c->task_fifo = av_fifo_alloc_array(BUFFER_SIZE, sizeof(Task)); if(!c->task_fifo) goto fail; @@ -234,7 +234,7 @@ void ff_frame_thread_encoder_free(AVCodecContext *avctx){ pthread_mutex_destroy(&c->buffer_mutex); pthread_cond_destroy(&c->task_fifo_cond); pthread_cond_destroy(&c->finished_task_cond); - av_fifo_free(c->task_fifo); c->task_fifo = NULL; + av_fifo_freep(&c->task_fifo); av_freep(&avctx->internal->frame_thread_encoder); } diff --git a/libavcodec/fraps.c b/libavcodec/fraps.c index 225da1129..c49866e7e 100644 --- a/libavcodec/fraps.c +++ b/libavcodec/fraps.c @@ -35,7 +35,7 @@ #include "get_bits.h" #include "huffman.h" #include "bytestream.h" -#include "dsputil.h" +#include "bswapdsp.h" #include "internal.h" #include "thread.h" @@ -47,9 +47,9 @@ */ typedef struct FrapsContext { AVCodecContext *avctx; + BswapDSPContext bdsp; uint8_t *tmpbuf; int tmpbuf_size; - DSPContext dsp; } FrapsContext; @@ -65,7 +65,7 @@ static av_cold int decode_init(AVCodecContext *avctx) s->avctx = avctx; s->tmpbuf = NULL; - ff_dsputil_init(&s->dsp, avctx); + ff_bswapdsp_init(&s->bdsp); return 0; } @@ -102,7 +102,8 @@ static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w, /* we have built Huffman table and are ready to decode plane */ /* convert bits so they may be used by standard bitreader */ - s->dsp.bswap_buf((uint32_t *)s->tmpbuf, (const uint32_t *)src, size >> 2); + s->bdsp.bswap_buf((uint32_t *) s->tmpbuf, + (const uint32_t *) src, size >> 2); init_get_bits(&gb, s->tmpbuf, size * 8); for (j = 0; j < h; j++) { @@ -207,7 +208,8 @@ static int decode_frame(AVCodecContext *avctx, f->key_frame = 1; avctx->pix_fmt = version & 1 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_YUVJ420P; - avctx->color_range = version & 1 ? AVCOL_RANGE_UNSPECIFIED : AVCOL_RANGE_JPEG; + avctx->color_range = version & 1 ? AVCOL_RANGE_UNSPECIFIED + : AVCOL_RANGE_JPEG; avctx->colorspace = version & 1 ? AVCOL_SPC_UNSPECIFIED : AVCOL_SPC_BT709; if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index 70b5f2604..60c48c382 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -24,12 +24,14 @@ * Go2Webinar decoder */ +#include #include #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "blockdsp.h" #include "bytestream.h" -#include "dsputil.h" +#include "idctdsp.h" #include "get_bits.h" #include "internal.h" #include "mjpeg.h" @@ -71,7 +73,8 @@ static const uint8_t chroma_quant[64] = { }; typedef struct JPGContext { - DSPContext dsp; + BlockDSPContext bdsp; + IDCTDSPContext idsp; ScanTable scantable; VLC dc_vlc[2], ac_vlc[2]; @@ -149,8 +152,9 @@ static av_cold int jpg_init(AVCodecContext *avctx, JPGContext *c) if (ret) return ret; - ff_dsputil_init(&c->dsp, avctx); - ff_init_scantable(c->dsp.idct_permutation, &c->scantable, + ff_blockdsp_init(&c->bdsp, avctx); + ff_idctdsp_init(&c->idsp, avctx); + ff_init_scantable(c->idsp.idct_permutation, &c->scantable, ff_zigzag_direct); return 0; @@ -192,14 +196,14 @@ static int jpg_decode_block(JPGContext *c, GetBitContext *gb, const int is_chroma = !!plane; const uint8_t *qmat = is_chroma ? chroma_quant : luma_quant; - c->dsp.clear_block(block); + c->bdsp.clear_block(block); dc = get_vlc2(gb, c->dc_vlc[is_chroma].table, 9, 3); if (dc < 0) return AVERROR_INVALIDDATA; if (dc) dc = get_xbits(gb, dc); - dc = dc * qmat[0] + c->prev_dc[plane]; - block[0] = dc; + dc = dc * qmat[0] + c->prev_dc[plane]; + block[0] = dc; c->prev_dc[plane] = dc; pos = 0; @@ -214,8 +218,8 @@ static int jpg_decode_block(JPGContext *c, GetBitContext *gb, if (val) { int nbits = val; - val = get_xbits(gb, nbits); - val *= qmat[ff_zigzag_direct[pos]]; + val = get_xbits(gb, nbits); + val *= qmat[ff_zigzag_direct[pos]]; block[c->scantable.permutated[pos]] = val; } } @@ -258,7 +262,7 @@ 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; - c->dsp.clear_blocks(c->block[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++) { if (mask && !mask[mb_x * 2] && !mask[mb_x * 2 + 1] && @@ -275,13 +279,13 @@ static int jpg_decode_data(JPGContext *c, int width, int height, if ((ret = jpg_decode_block(c, &gb, 0, c->block[i + j * 2])) != 0) return ret; - c->dsp.idct(c->block[i + j * 2]); + c->idsp.idct(c->block[i + j * 2]); } } for (i = 1; i < 3; i++) { if ((ret = jpg_decode_block(c, &gb, i, c->block[i + 3])) != 0) return ret; - c->dsp.idct(c->block[i + 3]); + c->idsp.idct(c->block[i + 3]); } for (j = 0; j < 16; j++) { @@ -359,7 +363,7 @@ static int kempf_decode_tile(G2MContext *c, int tile_x, int tile_y, width = FFMIN(c->width - tile_x * c->tile_width, c->tile_width); height = FFMIN(c->height - tile_y * c->tile_height, c->tile_height); - hdr = *src++; + hdr = *src++; sub_type = hdr >> 5; if (sub_type == 0) { int j; @@ -381,19 +385,21 @@ static int kempf_decode_tile(G2MContext *c, int tile_x, int tile_y, npal = *src++ + 1; if (src_end - src < npal * 3) return AVERROR_INVALIDDATA; - memcpy(pal, src, npal * 3); src += npal * 3; + memcpy(pal, src, npal * 3); + src += npal * 3; if (sub_type != 2) { for (i = 0; i < npal; i++) { if (!memcmp(pal + i * 3, transp, 3)) { - tidx = i; - break; + tidx = i; + break; } } } if (src_end - src < 2) return 0; - zsize = (src[0] << 8) | src[1]; src += 2; + zsize = (src[0] << 8) | src[1]; + src += 2; if (src_end - src < zsize + (sub_type != 2)) return AVERROR_INVALIDDATA; @@ -491,30 +497,30 @@ static int g2m_load_cursor(AVCodecContext *avctx, G2MContext *c, uint32_t cursor_hot_x, cursor_hot_y; int cursor_fmt, err; - cur_size = bytestream2_get_be32(gb); - cursor_w = bytestream2_get_byte(gb); - cursor_h = bytestream2_get_byte(gb); - cursor_hot_x = bytestream2_get_byte(gb); - cursor_hot_y = bytestream2_get_byte(gb); - cursor_fmt = bytestream2_get_byte(gb); + cur_size = bytestream2_get_be32(gb); + cursor_w = bytestream2_get_byte(gb); + cursor_h = bytestream2_get_byte(gb); + cursor_hot_x = bytestream2_get_byte(gb); + cursor_hot_y = bytestream2_get_byte(gb); + cursor_fmt = bytestream2_get_byte(gb); cursor_stride = FFALIGN(cursor_w, cursor_fmt==1 ? 32 : 1) * 4; if (cursor_w < 1 || cursor_w > 256 || cursor_h < 1 || cursor_h > 256) { - av_log(avctx, AV_LOG_ERROR, "Invalid cursor dimensions %dx%d\n", + av_log(avctx, AV_LOG_ERROR, "Invalid cursor dimensions %"PRIu32"x%"PRIu32"\n", cursor_w, cursor_h); return AVERROR_INVALIDDATA; } if (cursor_hot_x > cursor_w || cursor_hot_y > cursor_h) { - av_log(avctx, AV_LOG_WARNING, "Invalid hotspot position %d,%d\n", + av_log(avctx, AV_LOG_WARNING, "Invalid hotspot position %"PRIu32",%"PRIu32"\n", cursor_hot_x, cursor_hot_y); cursor_hot_x = FFMIN(cursor_hot_x, cursor_w - 1); cursor_hot_y = FFMIN(cursor_hot_y, cursor_h - 1); } if (cur_size - 9 > bytestream2_get_bytes_left(gb) || c->cursor_w * c->cursor_h / 4 > cur_size) { - av_log(avctx, AV_LOG_ERROR, "Invalid cursor data size %d/%d\n", + av_log(avctx, AV_LOG_ERROR, "Invalid cursor data size %"PRIu32"/%u\n", cur_size, bytestream2_get_bytes_left(gb)); return AVERROR_INVALIDDATA; } @@ -544,7 +550,7 @@ static int g2m_load_cursor(AVCodecContext *avctx, G2MContext *c, bits = bytestream2_get_be32(gb); for (k = 0; k < 32; k++) { dst[0] = !!(bits & 0x80000000); - dst += 4; + dst += 4; bits <<= 1; } } @@ -558,18 +564,24 @@ static int g2m_load_cursor(AVCodecContext *avctx, G2MContext *c, 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; + 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; + 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[0] = 0x00; + dst[1] = 0x00; + dst[2] = 0x00; + dst[3] = 0x00; } - dst += 4; + dst += 4; bits <<= 1; } } @@ -685,7 +697,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, chunk_type = bytestream2_get_byte(&bc); chunk_start = bytestream2_tell(&bc); if (chunk_size > bytestream2_get_bytes_left(&bc)) { - av_log(avctx, AV_LOG_ERROR, "Invalid chunk size %d type %02X\n", + av_log(avctx, AV_LOG_ERROR, "Invalid chunk size %"PRIu32" type %02X\n", chunk_size, chunk_type); break; } @@ -694,7 +706,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, got_header = c->got_header = 0; if (chunk_size < 21) { - av_log(avctx, AV_LOG_ERROR, "Invalid display info size %d\n", + av_log(avctx, AV_LOG_ERROR, "Invalid display info size %"PRIu32"\n", chunk_size); break; } @@ -733,10 +745,10 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, } c->tiles_x = (c->width + c->tile_width - 1) / c->tile_width; c->tiles_y = (c->height + c->tile_height - 1) / c->tile_height; - c->bpp = bytestream2_get_byte(&bc); + c->bpp = bytestream2_get_byte(&bc); if (c->bpp == 32) { if (bytestream2_get_bytes_left(&bc) < 16 || - (chunk_size - 21) < 16 ) { + (chunk_size - 21) < 16) { av_log(avctx, AV_LOG_ERROR, "Display info: missing bitmasks!\n"); ret = AVERROR_INVALIDDATA; @@ -747,7 +759,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, b_mask = bytestream2_get_be32(&bc); if (r_mask != 0xFF0000 || g_mask != 0xFF00 || b_mask != 0xFF) { av_log(avctx, AV_LOG_ERROR, - "Invalid or unsupported bitmasks: R=%X, G=%X, B=%X\n", + "Invalid or unsupported bitmasks: R=%"PRIX32", G=%"PRIX32", B=%"PRIX32"\n", r_mask, g_mask, b_mask); ret = AVERROR_PATCHWELCOME; goto header_fail; @@ -770,7 +782,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, break; } if (chunk_size < 2) { - av_log(avctx, AV_LOG_ERROR, "Invalid tile data size %d\n", + av_log(avctx, AV_LOG_ERROR, "Invalid tile data size %"PRIu32"\n", chunk_size); break; } @@ -800,7 +812,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, break; case CURSOR_POS: if (chunk_size < 5) { - av_log(avctx, AV_LOG_ERROR, "Invalid cursor pos size %d\n", + av_log(avctx, AV_LOG_ERROR, "Invalid cursor pos size %"PRIu32"\n", chunk_size); break; } @@ -809,7 +821,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, break; case CURSOR_SHAPE: if (chunk_size < 8) { - av_log(avctx, AV_LOG_ERROR, "Invalid cursor data size %d\n", + av_log(avctx, AV_LOG_ERROR, "Invalid cursor data size %"PRIu32"\n", chunk_size); break; } @@ -821,7 +833,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, case CHUNK_CD: break; default: - av_log(avctx, AV_LOG_WARNING, "Skipping chunk type %02X\n", + av_log(avctx, AV_LOG_WARNING, "Skipping chunk type %02d\n", chunk_type); } @@ -840,7 +852,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, for (i = 0; i < avctx->height; i++) memcpy(pic->data[0] + i * pic->linesize[0], - c->framebuf + i * c->framebuf_stride, + c->framebuf + i * c->framebuf_stride, c->width * 3); g2m_paint_cursor(c, pic->data[0], pic->linesize[0]); @@ -848,15 +860,18 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, } return buf_size; + header_fail: - c->width = c->height = 0; - c->tiles_x = c->tiles_y = 0; + c->width = + c->height = 0; + c->tiles_x = + c->tiles_y = 0; return ret; } static av_cold int g2m_decode_init(AVCodecContext *avctx) { - G2MContext * const c = avctx->priv_data; + G2MContext *const c = avctx->priv_data; int ret; if ((ret = jpg_init(avctx, &c->jc)) != 0) { @@ -872,7 +887,7 @@ static av_cold int g2m_decode_init(AVCodecContext *avctx) static av_cold int g2m_decode_end(AVCodecContext *avctx) { - G2MContext * const c = avctx->priv_data; + G2MContext *const c = avctx->priv_data; jpg_free_context(&c->jc); diff --git a/libavcodec/g723_1.c b/libavcodec/g723_1.c index e4bde2afd..66afd6af6 100644 --- a/libavcodec/g723_1.c +++ b/libavcodec/g723_1.c @@ -2346,11 +2346,15 @@ static int g723_1_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, int16_t weighted_lpc[LPC_ORDER * SUBFRAMES << 1]; int16_t vector[FRAME_LEN + PITCH_MAX]; int offset, ret; - int16_t *in = (const int16_t *)frame->data[0]; + int16_t *in_orig = av_memdup(frame->data[0], frame->nb_samples * sizeof(int16_t)); + int16_t *in = in_orig; HFParam hf[4]; int i, j; + if (!in) + return AVERROR(ENOMEM); + highpass_filter(in, &p->hpf_fir_mem, &p->hpf_iir_mem); memcpy(vector, p->prev_data, HALF_FRAME_LEN * sizeof(int16_t)); @@ -2456,6 +2460,8 @@ static int g723_1_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, offset += LPC_ORDER; } + av_freep(&in_orig); in = NULL; + if ((ret = ff_alloc_packet2(avctx, avpkt, 24)) < 0) return ret; diff --git a/libavcodec/g729dec.c b/libavcodec/g729dec.c index d29ad1f50..6eb057f5d 100644 --- a/libavcodec/g729dec.c +++ b/libavcodec/g729dec.c @@ -25,7 +25,7 @@ #include "avcodec.h" #include "libavutil/avutil.h" #include "get_bits.h" -#include "dsputil.h" +#include "audiodsp.h" #include "internal.h" @@ -100,7 +100,7 @@ typedef struct { } G729FormatDescription; typedef struct { - DSPContext dsp; + AudioDSPContext adsp; /// past excitation signal buffer int16_t exc_base[2*SUBFRAME_SIZE+PITCH_DELAY_MAX+INTERPOL_LEN]; @@ -381,8 +381,8 @@ static av_cold int decoder_init(AVCodecContext * avctx) for(i=0; i<4; i++) ctx->quant_energy[i] = -14336; // -14 in (5.10) - ff_dsputil_init(&ctx->dsp, avctx); - ctx->dsp.scalarproduct_int16 = scalarproduct_int16_c; + ff_audiodsp_init(&ctx->adsp); + ctx->adsp.scalarproduct_int16 = scalarproduct_int16_c; return 0; } @@ -578,7 +578,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, } /* Decode the fixed-codebook gain. */ - ctx->past_gain_code[0] = ff_acelp_decode_gain_code(&ctx->dsp, gain_corr_factor, + ctx->past_gain_code[0] = ff_acelp_decode_gain_code(&ctx->adsp, gain_corr_factor, fc, MR_ENERGY, ctx->quant_energy, ma_prediction_coeff, @@ -668,7 +668,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, /* Call postfilter and also update voicing decision for use in next frame. */ ff_g729_postfilter( - &ctx->dsp, + &ctx->adsp, &ctx->ht_prev_data, &is_periodic, &lp[i][0], diff --git a/libavcodec/g729postfilter.c b/libavcodec/g729postfilter.c index fc903740e..9a775c47b 100644 --- a/libavcodec/g729postfilter.c +++ b/libavcodec/g729postfilter.c @@ -107,7 +107,7 @@ static void residual_filter(int16_t* out, const int16_t* filter_coeffs, const in * * \return 0 if long-term prediction gain is less than 3dB, 1 - otherwise */ -static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int, +static int16_t long_term_filter(AudioDSPContext *adsp, int pitch_delay_int, const int16_t* residual, int16_t *residual_filt, int subframe_size) { @@ -161,7 +161,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int, /* Start of best delay searching code */ gain_num = 0; - ener = dsp->scalarproduct_int16(sig_scaled + RES_PREV_DATA_SIZE, + ener = adsp->scalarproduct_int16(sig_scaled + RES_PREV_DATA_SIZE, sig_scaled + RES_PREV_DATA_SIZE, subframe_size); if (ener) { @@ -190,7 +190,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int, corr_int_num = 0; best_delay_int = pitch_delay_int - 1; for (i = pitch_delay_int - 1; i <= pitch_delay_int + 1; i++) { - sum = dsp->scalarproduct_int16(sig_scaled + RES_PREV_DATA_SIZE, + sum = adsp->scalarproduct_int16(sig_scaled + RES_PREV_DATA_SIZE, sig_scaled + RES_PREV_DATA_SIZE - i, subframe_size); if (sum > corr_int_num) { @@ -200,7 +200,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int, } if (corr_int_num) { /* Compute denominator of pseudo-normalized correlation R'(0). */ - corr_int_den = dsp->scalarproduct_int16(sig_scaled - best_delay_int + RES_PREV_DATA_SIZE, + corr_int_den = adsp->scalarproduct_int16(sig_scaled - best_delay_int + RES_PREV_DATA_SIZE, sig_scaled - best_delay_int + RES_PREV_DATA_SIZE, subframe_size); @@ -227,7 +227,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int, Also compute maximum value of above denominators over all k. */ tmp = corr_int_den; for (k = 0; k < ANALYZED_FRAC_DELAYS; k++) { - sum = dsp->scalarproduct_int16(&delayed_signal[k][1], + sum = adsp->scalarproduct_int16(&delayed_signal[k][1], &delayed_signal[k][1], subframe_size - 1); corr_den[k][0] = sum + delayed_signal[k][0 ] * delayed_signal[k][0 ]; @@ -255,7 +255,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int, int gain_num_short_square; /* Compute numerator of pseudo-normalized correlation R'(k). */ - sum = dsp->scalarproduct_int16(&delayed_signal[k][i], + sum = adsp->scalarproduct_int16(&delayed_signal[k][i], sig_scaled + RES_PREV_DATA_SIZE, subframe_size); gain_num_short = FFMAX(sum >> sh_gain_num, 0); @@ -312,7 +312,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int, LONG_INT_FILT_LEN, subframe_size + 1); /* Compute R'(k) correlation's numerator. */ - sum = dsp->scalarproduct_int16(residual_filt, + sum = adsp->scalarproduct_int16(residual_filt, sig_scaled + RES_PREV_DATA_SIZE, subframe_size); @@ -327,7 +327,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int, } /* Compute R'(k) correlation's denominator. */ - sum = dsp->scalarproduct_int16(residual_filt, residual_filt, subframe_size); + sum = adsp->scalarproduct_int16(residual_filt, residual_filt, subframe_size); tmp = FFMAX(av_log2(sum) - 14, 0); sum >>= tmp; @@ -389,7 +389,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int, lt_filt_factor_a = (gain_den << 15) / (gain_den + gain_num); } #else - L64_temp0 = ((int64_t)gain_num) << (sh_gain_num - 1); + L64_temp0 = (((int64_t)gain_num) << sh_gain_num) >> 1; L64_temp1 = ((int64_t)gain_den) << sh_gain_den; lt_filt_factor_a = FFMAX((L64_temp1 << 15) / (L64_temp1 + L64_temp0), MIN_LT_FILT_FACTOR_A); #endif @@ -421,7 +421,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int, * * \note All members of lp_gn, except 10-19 must be equal to zero. */ -static int16_t get_tilt_comp(DSPContext *dsp, int16_t *lp_gn, +static int16_t get_tilt_comp(AudioDSPContext *adsp, int16_t *lp_gn, const int16_t *lp_gd, int16_t* speech, int subframe_size) { @@ -437,8 +437,8 @@ static int16_t get_tilt_comp(DSPContext *dsp, int16_t *lp_gn, /* Now lp_gn (starting with 10) contains impulse response of A(z/FORMANT_PP_FACTOR_NUM)/A(z/FORMANT_PP_FACTOR_DEN) filter. */ - rh0 = dsp->scalarproduct_int16(lp_gn + 10, lp_gn + 10, 20); - rh1 = dsp->scalarproduct_int16(lp_gn + 10, lp_gn + 11, 20); + rh0 = adsp->scalarproduct_int16(lp_gn + 10, lp_gn + 10, 20); + rh1 = adsp->scalarproduct_int16(lp_gn + 10, lp_gn + 11, 20); /* downscale to avoid overflow */ temp = av_log2(rh0) - 14; @@ -511,7 +511,7 @@ static int16_t apply_tilt_comp(int16_t* out, int16_t* res_pst, int refl_coeff, return tmp; } -void ff_g729_postfilter(DSPContext *dsp, int16_t* ht_prev_data, int* voicing, +void ff_g729_postfilter(AudioDSPContext *adsp, int16_t* ht_prev_data, int* voicing, const int16_t *lp_filter_coeffs, int pitch_delay_int, int16_t* residual, int16_t* res_filter_data, int16_t* pos_filter_data, int16_t *speech, int subframe_size) @@ -541,7 +541,7 @@ void ff_g729_postfilter(DSPContext *dsp, int16_t* ht_prev_data, int* voicing, /* long-term filter. If long-term prediction gain is larger than 3dB (returned value is nonzero) then declare current subframe as periodic. */ - *voicing = FFMAX(*voicing, long_term_filter(dsp, pitch_delay_int, + *voicing = FFMAX(*voicing, long_term_filter(adsp, pitch_delay_int, residual, residual_filt_buf + 10, subframe_size)); @@ -549,7 +549,7 @@ void ff_g729_postfilter(DSPContext *dsp, int16_t* ht_prev_data, int* voicing, memmove(residual, residual + subframe_size, RES_PREV_DATA_SIZE * sizeof(int16_t)); /* short-term filter tilt compensation */ - tilt_comp_coeff = get_tilt_comp(dsp, lp_gn, lp_gd, residual_filt_buf + 10, subframe_size); + tilt_comp_coeff = get_tilt_comp(adsp, lp_gn, lp_gd, residual_filt_buf + 10, subframe_size); /* Apply second half of short-term postfilter: 1/A(z/FORMANT_PP_FACTOR_DEN) */ ff_celp_lp_synthesis_filter(pos_filter_data + 10, lp_gd + 1, diff --git a/libavcodec/g729postfilter.h b/libavcodec/g729postfilter.h index 5239fc80d..89e3e40ce 100644 --- a/libavcodec/g729postfilter.h +++ b/libavcodec/g729postfilter.h @@ -22,7 +22,7 @@ #define FFMPEG_G729POSTFILTER_H #include -#include "dsputil.h" +#include "audiodsp.h" /** * tilt compensation factor (G.729, k1>0) @@ -94,7 +94,7 @@ * Short-term postfilter (4.2.2). * Tilt-compensation (4.2.3) */ -void ff_g729_postfilter(DSPContext *dsp, int16_t* ht_prev_data, int* voicing, +void ff_g729_postfilter(AudioDSPContext *adsp, int16_t* ht_prev_data, int* voicing, const int16_t *lp_filter_coeffs, int pitch_delay_int, int16_t* residual, int16_t* res_filter_data, int16_t* pos_filter_data, int16_t *speech, diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 7824e5ab0..d8d7b6ea0 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -64,7 +64,6 @@ typedef struct VLC { int bits; VLC_TYPE (*table)[2]; ///< code, bits int table_size, table_allocated; - void * volatile init_state; } VLC; typedef struct RL_VLC_ELEM { @@ -219,7 +218,7 @@ static inline void skip_bits_long(GetBitContext *s, int n) } /** - * read mpeg1 dc style vlc (sign bit + mantisse with no MSB). + * read mpeg1 dc style vlc (sign bit + mantissa with no MSB). * if MSB not set it is negative * @param n length in bits */ @@ -513,7 +512,7 @@ void ff_free_vlc(VLC *vlc); SKIP_BITS(name, gb, n); \ } while (0) -#define GET_RL_VLC(level, run, name, gb, table, bits, \ +#define GET_RL_VLC_INTERNAL(level, run, name, gb, table, bits, \ max_depth, need_update) \ do { \ int n, nb_bits; \ @@ -642,6 +641,25 @@ static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], return r; } +#define GET_RL_VLC(level, run, name, gb, table, bits, \ + max_depth, need_update) \ + do { \ + int show = SHOW_UBITS(name, gb, 24); \ + int len; \ + int pos = name ## _index; \ + \ + GET_RL_VLC_INTERNAL(level, run, name, gb, table, bits,max_depth, need_update); \ + \ + len = name ## _index - pos + 1; \ + show = show >> (24 - len); \ + \ + print_bin(show, len); \ + \ + av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d/%-3d rlv @%5d in %s %s:%d\n",\ + show, len, run-1, level, pos, __FILE__, __PRETTY_FUNCTION__, __LINE__);\ + } while (0) \ + + static inline int get_xbits_trace(GetBitContext *s, int n, const char *file, const char *func, int line) { @@ -666,6 +684,7 @@ static inline int get_xbits_trace(GetBitContext *s, int n, const char *file, #else //TRACE #define tprintf(p, ...) { } +#define GET_RL_VLC GET_RL_VLC_INTERNAL #endif #endif /* AVCODEC_GET_BITS_H */ diff --git a/libavcodec/h261data.c b/libavcodec/h261data.c index 0d1f30541..a9891edd0 100644 --- a/libavcodec/h261data.c +++ b/libavcodec/h261data.c @@ -26,6 +26,7 @@ #include +#include "mpegutils.h" #include "rl.h" #include "h261.h" diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c index 49f1b4a19..7e63f2949 100644 --- a/libavcodec/h261dec.c +++ b/libavcodec/h261dec.c @@ -27,6 +27,8 @@ #include "libavutil/avassert.h" #include "avcodec.h" +#include "mpeg_er.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "h263.h" #include "h261.h" @@ -431,10 +433,17 @@ static int h261_decode_mb(H261Context *h) s->mv[0][0][0] = h->current_mv_x * 2; // gets divided by 2 in motion compensation s->mv[0][0][1] = h->current_mv_y * 2; + if (s->current_picture.motion_val[0]) { + int b_stride = 2*s->mb_width + 1; + int b_xy = 2 * s->mb_x + (2 * s->mb_y) * b_stride; + s->current_picture.motion_val[0][b_xy][0] = s->mv[0][0][0]; + s->current_picture.motion_val[0][b_xy][1] = s->mv[0][0][1]; + } + intra: /* decode each block */ if (s->mb_intra || HAS_CBP(h->mtype)) { - s->dsp.clear_blocks(s->block[0]); + s->bdsp.clear_blocks(s->block[0]); for (i = 0; i < 6; i++) { if (h261_decode_block(h, s->block[i], i, cbp & 32) < 0) return SLICE_ERROR; @@ -609,8 +618,8 @@ retry: } // for skipping the frame - s->current_picture.f.pict_type = s->pict_type; - s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; + s->current_picture.f->pict_type = s->pict_type; + s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; if ((avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type == AV_PICTURE_TYPE_B) || (avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type != AV_PICTURE_TYPE_I) || @@ -633,10 +642,10 @@ retry: } ff_MPV_frame_end(s); - av_assert0(s->current_picture.f.pict_type == s->current_picture_ptr->f.pict_type); - av_assert0(s->current_picture.f.pict_type == s->pict_type); + av_assert0(s->current_picture.f->pict_type == s->current_picture_ptr->f->pict_type); + av_assert0(s->current_picture.f->pict_type == s->pict_type); - if ((ret = av_frame_ref(pict, &s->current_picture_ptr->f)) < 0) + if ((ret = av_frame_ref(pict, s->current_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->current_picture_ptr, pict); diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index e185f5ec0..47696e583 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -28,6 +28,7 @@ #include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "avcodec.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "h263.h" #include "h261.h" diff --git a/libavcodec/h263.c b/libavcodec/h263.c index dafc4ecbb..b08e32e86 100644 --- a/libavcodec/h263.c +++ b/libavcodec/h263.c @@ -34,6 +34,7 @@ #include "h263.h" #include "h263data.h" #include "mathops.h" +#include "mpegutils.h" #include "unary.h" #include "flv.h" #include "mpeg4video.h" @@ -266,7 +267,7 @@ void ff_h263_pred_acdc(MpegEncContext * s, int16_t *block, int n) if (a != 1024) { ac_val -= 16; for(i=1;i<8;i++) { - block[s->dsp.idct_permutation[i<<3]] += ac_val[i]; + block[s->idsp.idct_permutation[i << 3]] += ac_val[i]; } pred_dc = a; } @@ -275,7 +276,7 @@ void ff_h263_pred_acdc(MpegEncContext * s, int16_t *block, int n) if (c != 1024) { ac_val -= 16 * wrap; for(i=1;i<8;i++) { - block[s->dsp.idct_permutation[i ]] += ac_val[i + 8]; + block[s->idsp.idct_permutation[i]] += ac_val[i + 8]; } pred_dc = c; } @@ -303,10 +304,10 @@ void ff_h263_pred_acdc(MpegEncContext * s, int16_t *block, int n) /* left copy */ for(i=1;i<8;i++) - ac_val1[i ] = block[s->dsp.idct_permutation[i<<3]]; + ac_val1[i] = block[s->idsp.idct_permutation[i << 3]]; /* top copy */ for(i=1;i<8;i++) - ac_val1[8 + i] = block[s->dsp.idct_permutation[i ]]; + ac_val1[8 + i] = block[s->idsp.idct_permutation[i]]; } int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir, diff --git a/libavcodec/h263.h b/libavcodec/h263.h index 962d44cbb..54ce2a5f9 100644 --- a/libavcodec/h263.h +++ b/libavcodec/h263.h @@ -196,7 +196,7 @@ static inline int get_p_cbp(MpegEncContext * s, for (i = 0; i < 6; i++) { if (s->block_last_index[i] >= 0 && ((cbp >> (5 - i))&1)==0 ){ s->block_last_index[i]= -1; - s->dsp.clear_block(s->block[i]); + s->bdsp.clear_block(s->block[i]); } } }else{ diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 6324e9be8..31ec642e9 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -34,10 +34,12 @@ #include "h263.h" #include "h263_parser.h" #include "internal.h" +#include "mpeg_er.h" #include "mpeg4video.h" #include "mpeg4video_parser.h" #include "mpegvideo.h" #include "msmpeg4.h" +#include "qpeldsp.h" #include "vdpau_internal.h" #include "thread.h" @@ -60,7 +62,7 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx) if (avctx->codec->id == AV_CODEC_ID_MSS2) avctx->pix_fmt = AV_PIX_FMT_YUV420P; else - avctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts); + avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts); s->unrestricted_mv = 1; /* select sub codec */ @@ -112,7 +114,6 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx) return AVERROR(ENOSYS); } s->codec_id = avctx->codec->id; - avctx->hwaccel = ff_find_hwaccel(avctx); if (avctx->stream_codec_tag == AV_RL32("l263") && avctx->extradata_size == 56 && avctx->extradata[0] == 1) s->ehc_mode = 1; @@ -125,6 +126,7 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx) return ret; ff_h263dsp_init(&s->h263dsp); + ff_qpeldsp_init(&s->qdsp); ff_h263_decode_init_vlc(); return 0; @@ -235,6 +237,8 @@ static int decode_slice(MpegEncContext *s) s->mv_type = MV_TYPE_16X16; av_dlog(s, "%d %d %06X\n", ret, get_bits_count(&s->gb), show_bits(&s->gb, 24)); + + tprintf(NULL, "Decoding MB at %dx%d\n", s->mb_x, s->mb_y); ret = s->decode_mb(s, s->block); if (s->pict_type != AV_PICTURE_TYPE_B) @@ -271,6 +275,8 @@ static int decode_slice(MpegEncContext *s) ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR & part_mask); + if (s->err_recognition & AV_EF_IGNORE_ERR) + continue; return AVERROR_INVALIDDATA; } @@ -319,6 +325,17 @@ static int decode_slice(MpegEncContext *s) } } + if (s->codec_id == AV_CODEC_ID_H263 && + (s->workaround_bugs & FF_BUG_AUTODETECT) && + get_bits_left(&s->gb) >= 8 && + get_bits_left(&s->gb) < 300 && + s->pict_type == AV_PICTURE_TYPE_I && + show_bits(&s->gb, 8) == 0 && + !s->data_partitioning) { + + s->padding_bug_score += 32; + } + if (s->workaround_bugs & FF_BUG_AUTODETECT) { if (s->padding_bug_score > -2 && !s->data_partitioning) s->workaround_bugs |= FF_BUG_NO_PADDING; @@ -383,7 +400,7 @@ int ff_h263_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (buf_size == 0) { /* special case for last picture */ if (s->low_delay == 0 && s->next_picture_ptr) { - if ((ret = av_frame_ref(pict, &s->next_picture_ptr->f)) < 0) + if ((ret = av_frame_ref(pict, s->next_picture_ptr->f)) < 0) return ret; s->next_picture_ptr = NULL; @@ -444,7 +461,7 @@ retry: /* We need to set current_picture_ptr before reading the header, * otherwise we cannot store anyting in there */ - if (s->current_picture_ptr == NULL || s->current_picture_ptr->f.data[0]) { + if (s->current_picture_ptr == NULL || s->current_picture_ptr->f->data[0]) { int i = ff_find_unused_picture(s, 0); if (i < 0) return i; @@ -510,6 +527,8 @@ retry: if (ret < 0) return ret; + ff_set_sar(avctx, avctx->sample_aspect_ratio); + if ((ret = ff_MPV_common_frame_size_change(s))) return ret; } @@ -520,8 +539,8 @@ retry: s->gob_index = ff_h263_get_gob_height(s); // for skipping the frame - s->current_picture.f.pict_type = s->pict_type; - s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; + s->current_picture.f->pict_type = s->pict_type; + s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; /* skip B-frames if we don't have reference frames */ if (s->last_picture_ptr == NULL && @@ -542,11 +561,11 @@ retry: } if ((!s->no_rounding) || s->pict_type == AV_PICTURE_TYPE_B) { - s->me.qpel_put = s->dsp.put_qpel_pixels_tab; - s->me.qpel_avg = s->dsp.avg_qpel_pixels_tab; + s->me.qpel_put = s->qdsp.put_qpel_pixels_tab; + s->me.qpel_avg = s->qdsp.avg_qpel_pixels_tab; } else { - s->me.qpel_put = s->dsp.put_no_rnd_qpel_pixels_tab; - s->me.qpel_avg = s->dsp.avg_qpel_pixels_tab; + s->me.qpel_put = s->qdsp.put_no_rnd_qpel_pixels_tab; + s->me.qpel_avg = s->qdsp.avg_qpel_pixels_tab; } if ((ret = ff_MPV_frame_start(s, avctx)) < 0) @@ -556,7 +575,7 @@ retry: ff_thread_finish_setup(avctx); if (CONFIG_MPEG4_VDPAU_DECODER && (s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)) { - ff_vdpau_mpeg4_decode_picture(s, s->gb.buffer, s->gb.buffer_end - s->gb.buffer); + ff_vdpau_mpeg4_decode_picture(avctx->priv_data, s->gb.buffer, s->gb.buffer_end - s->gb.buffer); goto frame_end; } @@ -629,15 +648,15 @@ frame_end: if (!s->divx_packed && avctx->hwaccel) ff_thread_finish_setup(avctx); - av_assert1(s->current_picture.f.pict_type == s->current_picture_ptr->f.pict_type); - av_assert1(s->current_picture.f.pict_type == s->pict_type); + av_assert1(s->current_picture.f->pict_type == s->current_picture_ptr->f->pict_type); + av_assert1(s->current_picture.f->pict_type == s->pict_type); if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { - if ((ret = av_frame_ref(pict, &s->current_picture_ptr->f)) < 0) + if ((ret = av_frame_ref(pict, s->current_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->current_picture_ptr, pict); ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_QSCALE_TYPE_MPEG1); } else if (s->last_picture_ptr != NULL) { - if ((ret = av_frame_ref(pict, &s->last_picture_ptr->f)) < 0) + if ((ret = av_frame_ref(pict, s->last_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->last_picture_ptr, pict); ff_mpv_export_qp_table(s, pict, s->last_picture_ptr, FF_QSCALE_TYPE_MPEG1); @@ -669,10 +688,10 @@ frame_end: } const enum AVPixelFormat ff_h263_hwaccel_pixfmt_list_420[] = { -#if CONFIG_VAAPI +#if CONFIG_H263_VAAPI_HWACCEL || CONFIG_MPEG4_VAAPI_HWACCEL AV_PIX_FMT_VAAPI_VLD, #endif -#if CONFIG_VDPAU +#if CONFIG_H263_VDPAU_HWACCEL || CONFIG_MPEG4_VDPAU_HWACCEL AV_PIX_FMT_VDPAU, #endif AV_PIX_FMT_YUV420P, diff --git a/libavcodec/h264.c b/libavcodec/h264.c index d855b7bfb..1d919872f 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -28,6 +28,7 @@ #define UNCHECKED_BITSTREAM_READER 1 #include "libavutil/avassert.h" +#include "libavutil/display.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/stereo3d.h" @@ -38,13 +39,13 @@ #include "dsputil.h" #include "error_resilience.h" #include "avcodec.h" -#include "mpegvideo.h" #include "h264.h" #include "h264data.h" #include "h264chroma.h" #include "h264_mvpred.h" #include "golomb.h" #include "mathops.h" +#include "mpegutils.h" #include "rectangle.h" #include "svq3.h" #include "thread.h" @@ -52,147 +53,8 @@ #include -static void flush_change(H264Context *h); - const uint16_t ff_h264_mb_sizes[4] = { 256, 384, 512, 768 }; -static const uint8_t rem6[QP_MAX_NUM + 1] = { - 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, - 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, - 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, - 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, - 0, 1, 2, 3, -}; - -static const uint8_t div6[QP_MAX_NUM + 1] = { - 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, - 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, - 10,10,10,11,11,11,11,11,11,12,12,12,12,12,12,13,13,13, 13, 13, 13, - 14,14,14,14, -}; - -static const uint8_t field_scan[16+1] = { - 0 + 0 * 4, 0 + 1 * 4, 1 + 0 * 4, 0 + 2 * 4, - 0 + 3 * 4, 1 + 1 * 4, 1 + 2 * 4, 1 + 3 * 4, - 2 + 0 * 4, 2 + 1 * 4, 2 + 2 * 4, 2 + 3 * 4, - 3 + 0 * 4, 3 + 1 * 4, 3 + 2 * 4, 3 + 3 * 4, -}; - -static const uint8_t field_scan8x8[64+1] = { - 0 + 0 * 8, 0 + 1 * 8, 0 + 2 * 8, 1 + 0 * 8, - 1 + 1 * 8, 0 + 3 * 8, 0 + 4 * 8, 1 + 2 * 8, - 2 + 0 * 8, 1 + 3 * 8, 0 + 5 * 8, 0 + 6 * 8, - 0 + 7 * 8, 1 + 4 * 8, 2 + 1 * 8, 3 + 0 * 8, - 2 + 2 * 8, 1 + 5 * 8, 1 + 6 * 8, 1 + 7 * 8, - 2 + 3 * 8, 3 + 1 * 8, 4 + 0 * 8, 3 + 2 * 8, - 2 + 4 * 8, 2 + 5 * 8, 2 + 6 * 8, 2 + 7 * 8, - 3 + 3 * 8, 4 + 1 * 8, 5 + 0 * 8, 4 + 2 * 8, - 3 + 4 * 8, 3 + 5 * 8, 3 + 6 * 8, 3 + 7 * 8, - 4 + 3 * 8, 5 + 1 * 8, 6 + 0 * 8, 5 + 2 * 8, - 4 + 4 * 8, 4 + 5 * 8, 4 + 6 * 8, 4 + 7 * 8, - 5 + 3 * 8, 6 + 1 * 8, 6 + 2 * 8, 5 + 4 * 8, - 5 + 5 * 8, 5 + 6 * 8, 5 + 7 * 8, 6 + 3 * 8, - 7 + 0 * 8, 7 + 1 * 8, 6 + 4 * 8, 6 + 5 * 8, - 6 + 6 * 8, 6 + 7 * 8, 7 + 2 * 8, 7 + 3 * 8, - 7 + 4 * 8, 7 + 5 * 8, 7 + 6 * 8, 7 + 7 * 8, -}; - -static const uint8_t field_scan8x8_cavlc[64+1] = { - 0 + 0 * 8, 1 + 1 * 8, 2 + 0 * 8, 0 + 7 * 8, - 2 + 2 * 8, 2 + 3 * 8, 2 + 4 * 8, 3 + 3 * 8, - 3 + 4 * 8, 4 + 3 * 8, 4 + 4 * 8, 5 + 3 * 8, - 5 + 5 * 8, 7 + 0 * 8, 6 + 6 * 8, 7 + 4 * 8, - 0 + 1 * 8, 0 + 3 * 8, 1 + 3 * 8, 1 + 4 * 8, - 1 + 5 * 8, 3 + 1 * 8, 2 + 5 * 8, 4 + 1 * 8, - 3 + 5 * 8, 5 + 1 * 8, 4 + 5 * 8, 6 + 1 * 8, - 5 + 6 * 8, 7 + 1 * 8, 6 + 7 * 8, 7 + 5 * 8, - 0 + 2 * 8, 0 + 4 * 8, 0 + 5 * 8, 2 + 1 * 8, - 1 + 6 * 8, 4 + 0 * 8, 2 + 6 * 8, 5 + 0 * 8, - 3 + 6 * 8, 6 + 0 * 8, 4 + 6 * 8, 6 + 2 * 8, - 5 + 7 * 8, 6 + 4 * 8, 7 + 2 * 8, 7 + 6 * 8, - 1 + 0 * 8, 1 + 2 * 8, 0 + 6 * 8, 3 + 0 * 8, - 1 + 7 * 8, 3 + 2 * 8, 2 + 7 * 8, 4 + 2 * 8, - 3 + 7 * 8, 5 + 2 * 8, 4 + 7 * 8, 5 + 4 * 8, - 6 + 3 * 8, 6 + 5 * 8, 7 + 3 * 8, 7 + 7 * 8, -}; - -// zigzag_scan8x8_cavlc[i] = zigzag_scan8x8[(i/4) + 16*(i%4)] -static const uint8_t zigzag_scan8x8_cavlc[64+1] = { - 0 + 0 * 8, 1 + 1 * 8, 1 + 2 * 8, 2 + 2 * 8, - 4 + 1 * 8, 0 + 5 * 8, 3 + 3 * 8, 7 + 0 * 8, - 3 + 4 * 8, 1 + 7 * 8, 5 + 3 * 8, 6 + 3 * 8, - 2 + 7 * 8, 6 + 4 * 8, 5 + 6 * 8, 7 + 5 * 8, - 1 + 0 * 8, 2 + 0 * 8, 0 + 3 * 8, 3 + 1 * 8, - 3 + 2 * 8, 0 + 6 * 8, 4 + 2 * 8, 6 + 1 * 8, - 2 + 5 * 8, 2 + 6 * 8, 6 + 2 * 8, 5 + 4 * 8, - 3 + 7 * 8, 7 + 3 * 8, 4 + 7 * 8, 7 + 6 * 8, - 0 + 1 * 8, 3 + 0 * 8, 0 + 4 * 8, 4 + 0 * 8, - 2 + 3 * 8, 1 + 5 * 8, 5 + 1 * 8, 5 + 2 * 8, - 1 + 6 * 8, 3 + 5 * 8, 7 + 1 * 8, 4 + 5 * 8, - 4 + 6 * 8, 7 + 4 * 8, 5 + 7 * 8, 6 + 7 * 8, - 0 + 2 * 8, 2 + 1 * 8, 1 + 3 * 8, 5 + 0 * 8, - 1 + 4 * 8, 2 + 4 * 8, 6 + 0 * 8, 4 + 3 * 8, - 0 + 7 * 8, 4 + 4 * 8, 7 + 2 * 8, 3 + 6 * 8, - 5 + 5 * 8, 6 + 5 * 8, 6 + 6 * 8, 7 + 7 * 8, -}; - -static const uint8_t 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, -#endif -#if CONFIG_H264_VDPAU_HWACCEL - AV_PIX_FMT_VDPAU, -#endif - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_NONE -}; - -static const enum AVPixelFormat h264_hwaccel_pixfmt_list_jpeg_420[] = { -#if CONFIG_H264_DXVA2_HWACCEL - AV_PIX_FMT_DXVA2_VLD, -#endif -#if CONFIG_H264_VAAPI_HWACCEL - AV_PIX_FMT_VAAPI_VLD, -#endif -#if CONFIG_H264_VDA_HWACCEL - AV_PIX_FMT_VDA_VLD, -#endif -#if CONFIG_H264_VDPAU_HWACCEL - AV_PIX_FMT_VDPAU, -#endif - AV_PIX_FMT_YUVJ420P, - AV_PIX_FMT_NONE -}; - int avpriv_h264_has_num_reorder_frames(AVCodecContext *avctx) { H264Context *h = avctx->priv_data; @@ -237,8 +99,8 @@ static void h264_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type, void ff_h264_draw_horiz_band(H264Context *h, int y, int height) { AVCodecContext *avctx = h->avctx; - Picture *cur = &h->cur_pic; - Picture *last = h->ref_list[0][0].f.data[0] ? &h->ref_list[0][0] : NULL; + 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; @@ -257,11 +119,11 @@ void ff_h264_draw_horiz_band(H264Context *h, int y, int height) int offset[AV_NUM_DATA_POINTERS]; int i; - if (cur->f.pict_type == AV_PICTURE_TYPE_B || h->low_delay || + if (cur->pict_type == AV_PICTURE_TYPE_B || h->low_delay || (avctx->slice_flags & SLICE_FLAG_CODED_ORDER)) - src = &cur->f; + src = cur; else if (last) - src = &last->f; + src = last; else return; @@ -278,254 +140,6 @@ void ff_h264_draw_horiz_band(H264Context *h, int y, int height) } } -static void unref_picture(H264Context *h, Picture *pic) -{ - int off = offsetof(Picture, tf) + sizeof(pic->tf); - int i; - - if (!pic->f.buf[0]) - return; - - ff_thread_release_buffer(h->avctx, &pic->tf); - av_buffer_unref(&pic->hwaccel_priv_buf); - - av_buffer_unref(&pic->qscale_table_buf); - av_buffer_unref(&pic->mb_type_buf); - for (i = 0; i < 2; i++) { - av_buffer_unref(&pic->motion_val_buf[i]); - av_buffer_unref(&pic->ref_index_buf[i]); - } - - memset((uint8_t*)pic + off, 0, sizeof(*pic) - off); -} - -static void release_unused_pictures(H264Context *h, int remove_current) -{ - int i; - - /* release non reference frames */ - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - if (h->DPB[i].f.buf[0] && !h->DPB[i].reference && - (remove_current || &h->DPB[i] != h->cur_pic_ptr)) { - unref_picture(h, &h->DPB[i]); - } - } -} - -static int ref_picture(H264Context *h, Picture *dst, Picture *src) -{ - int ret, i; - - av_assert0(!dst->f.buf[0]); - av_assert0(src->f.buf[0]); - - src->tf.f = &src->f; - dst->tf.f = &dst->f; - ret = ff_thread_ref_frame(&dst->tf, &src->tf); - if (ret < 0) - goto fail; - - dst->qscale_table_buf = av_buffer_ref(src->qscale_table_buf); - dst->mb_type_buf = av_buffer_ref(src->mb_type_buf); - if (!dst->qscale_table_buf || !dst->mb_type_buf) - goto fail; - dst->qscale_table = src->qscale_table; - dst->mb_type = src->mb_type; - - for (i = 0; i < 2; i++) { - dst->motion_val_buf[i] = av_buffer_ref(src->motion_val_buf[i]); - dst->ref_index_buf[i] = av_buffer_ref(src->ref_index_buf[i]); - if (!dst->motion_val_buf[i] || !dst->ref_index_buf[i]) - goto fail; - dst->motion_val[i] = src->motion_val[i]; - dst->ref_index[i] = src->ref_index[i]; - } - - if (src->hwaccel_picture_private) { - dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); - if (!dst->hwaccel_priv_buf) - goto fail; - dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; - } - - for (i = 0; i < 2; i++) - dst->field_poc[i] = src->field_poc[i]; - - memcpy(dst->ref_poc, src->ref_poc, sizeof(src->ref_poc)); - memcpy(dst->ref_count, src->ref_count, sizeof(src->ref_count)); - - dst->poc = src->poc; - dst->frame_num = src->frame_num; - dst->mmco_reset = src->mmco_reset; - dst->pic_id = src->pic_id; - dst->long_ref = src->long_ref; - dst->mbaff = src->mbaff; - dst->field_picture = src->field_picture; - dst->needs_realloc = src->needs_realloc; - dst->reference = src->reference; - dst->crop = src->crop; - dst->crop_left = src->crop_left; - dst->crop_top = src->crop_top; - dst->recovered = src->recovered; - dst->invalid_gap = src->invalid_gap; - - return 0; -fail: - unref_picture(h, dst); - return ret; -} - -static int alloc_scratch_buffers(H264Context *h, int linesize) -{ - int alloc_size = FFALIGN(FFABS(linesize) + 32, 32); - - if (h->bipred_scratchpad) - return 0; - - h->bipred_scratchpad = av_malloc(16 * 6 * alloc_size); - // edge emu needs blocksize + filter length - 1 - // (= 21x21 for h264) - h->edge_emu_buffer = av_mallocz(alloc_size * 2 * 21); - h->me.scratchpad = av_mallocz(alloc_size * 2 * 16 * 2); - - if (!h->bipred_scratchpad || !h->edge_emu_buffer || !h->me.scratchpad) { - av_freep(&h->bipred_scratchpad); - av_freep(&h->edge_emu_buffer); - av_freep(&h->me.scratchpad); - return AVERROR(ENOMEM); - } - - h->me.temp = h->me.scratchpad; - - return 0; -} - -static int init_table_pools(H264Context *h) -{ - const int big_mb_num = h->mb_stride * (h->mb_height + 1) + 1; - const int mb_array_size = h->mb_stride * h->mb_height; - const int b4_stride = h->mb_width * 4 + 1; - const int b4_array_size = b4_stride * h->mb_height * 4; - - h->qscale_table_pool = av_buffer_pool_init(big_mb_num + h->mb_stride, - av_buffer_allocz); - h->mb_type_pool = av_buffer_pool_init((big_mb_num + h->mb_stride) * - sizeof(uint32_t), av_buffer_allocz); - h->motion_val_pool = av_buffer_pool_init(2 * (b4_array_size + 4) * - sizeof(int16_t), av_buffer_allocz); - h->ref_index_pool = av_buffer_pool_init(4 * mb_array_size, av_buffer_allocz); - - if (!h->qscale_table_pool || !h->mb_type_pool || !h->motion_val_pool || - !h->ref_index_pool) { - av_buffer_pool_uninit(&h->qscale_table_pool); - av_buffer_pool_uninit(&h->mb_type_pool); - av_buffer_pool_uninit(&h->motion_val_pool); - av_buffer_pool_uninit(&h->ref_index_pool); - return AVERROR(ENOMEM); - } - - return 0; -} - -static int alloc_picture(H264Context *h, Picture *pic) -{ - int i, ret = 0; - - av_assert0(!pic->f.data[0]); - - pic->tf.f = &pic->f; - ret = ff_thread_get_buffer(h->avctx, &pic->tf, pic->reference ? - AV_GET_BUFFER_FLAG_REF : 0); - if (ret < 0) - goto fail; - - h->linesize = pic->f.linesize[0]; - h->uvlinesize = pic->f.linesize[1]; - pic->crop = h->sps.crop; - pic->crop_top = h->sps.crop_top; - pic->crop_left= h->sps.crop_left; - - if (h->avctx->hwaccel) { - const AVHWAccel *hwaccel = h->avctx->hwaccel; - av_assert0(!pic->hwaccel_picture_private); - if (hwaccel->priv_data_size) { - pic->hwaccel_priv_buf = av_buffer_allocz(hwaccel->priv_data_size); - if (!pic->hwaccel_priv_buf) - return AVERROR(ENOMEM); - pic->hwaccel_picture_private = pic->hwaccel_priv_buf->data; - } - } - if (!h->avctx->hwaccel && CONFIG_GRAY && h->flags & CODEC_FLAG_GRAY && pic->f.data[2]) { - int h_chroma_shift, v_chroma_shift; - av_pix_fmt_get_chroma_sub_sample(pic->f.format, - &h_chroma_shift, &v_chroma_shift); - - for(i=0; iavctx->height, v_chroma_shift); i++) { - memset(pic->f.data[1] + pic->f.linesize[1]*i, - 0x80, FF_CEIL_RSHIFT(h->avctx->width, h_chroma_shift)); - memset(pic->f.data[2] + pic->f.linesize[2]*i, - 0x80, FF_CEIL_RSHIFT(h->avctx->width, h_chroma_shift)); - } - } - - if (!h->qscale_table_pool) { - ret = init_table_pools(h); - if (ret < 0) - goto fail; - } - - pic->qscale_table_buf = av_buffer_pool_get(h->qscale_table_pool); - pic->mb_type_buf = av_buffer_pool_get(h->mb_type_pool); - if (!pic->qscale_table_buf || !pic->mb_type_buf) - goto fail; - - pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * h->mb_stride + 1; - pic->qscale_table = pic->qscale_table_buf->data + 2 * h->mb_stride + 1; - - for (i = 0; i < 2; i++) { - pic->motion_val_buf[i] = av_buffer_pool_get(h->motion_val_pool); - pic->ref_index_buf[i] = av_buffer_pool_get(h->ref_index_pool); - if (!pic->motion_val_buf[i] || !pic->ref_index_buf[i]) - goto fail; - - pic->motion_val[i] = (int16_t (*)[2])pic->motion_val_buf[i]->data + 4; - pic->ref_index[i] = pic->ref_index_buf[i]->data; - } - - return 0; -fail: - unref_picture(h, pic); - return (ret < 0) ? ret : AVERROR(ENOMEM); -} - -static inline int pic_is_unused(H264Context *h, Picture *pic) -{ - if (!pic->f.buf[0]) - return 1; - if (pic->needs_realloc && !(pic->reference & DELAYED_PIC_REF)) - return 1; - return 0; -} - -static int find_unused_picture(H264Context *h) -{ - int i; - - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - if (pic_is_unused(h, &h->DPB[i])) - break; - } - if (i == MAX_PICTURE_COUNT) - return AVERROR_INVALIDDATA; - - if (h->DPB[i].needs_realloc) { - h->DPB[i].needs_realloc = 0; - unref_picture(h, &h->DPB[i]); - } - - return i; -} - /** * Check if the top & left blocks are available if needed and * change the dc mode so it only uses the available blocks. @@ -751,464 +365,7 @@ static int decode_rbsp_trailing(H264Context *h, const uint8_t *src) return 0; } -static inline int get_lowest_part_list_y(H264Context *h, Picture *pic, int n, - int height, int y_offset, int list) -{ - int raw_my = h->mv_cache[list][scan8[n]][1]; - int filter_height_down = (raw_my & 3) ? 3 : 0; - int full_my = (raw_my >> 2) + y_offset; - int bottom = full_my + filter_height_down + height; - - av_assert2(height >= 0); - - return FFMAX(0, bottom); -} - -static inline void get_lowest_part_y(H264Context *h, int refs[2][48], int n, - int height, int y_offset, int list0, - int list1, int *nrefs) -{ - int my; - - y_offset += 16 * (h->mb_y >> MB_FIELD(h)); - - if (list0) { - int ref_n = h->ref_cache[0][scan8[n]]; - Picture *ref = &h->ref_list[0][ref_n]; - - // Error resilience puts the current picture in the ref list. - // Don't try to wait on these as it will cause a deadlock. - // Fields can wait on each other, though. - if (ref->tf.progress->data != h->cur_pic.tf.progress->data || - (ref->reference & 3) != h->picture_structure) { - my = get_lowest_part_list_y(h, ref, n, height, y_offset, 0); - if (refs[0][ref_n] < 0) - nrefs[0] += 1; - refs[0][ref_n] = FFMAX(refs[0][ref_n], my); - } - } - - if (list1) { - int ref_n = h->ref_cache[1][scan8[n]]; - Picture *ref = &h->ref_list[1][ref_n]; - - if (ref->tf.progress->data != h->cur_pic.tf.progress->data || - (ref->reference & 3) != h->picture_structure) { - my = get_lowest_part_list_y(h, ref, n, height, y_offset, 1); - if (refs[1][ref_n] < 0) - nrefs[1] += 1; - refs[1][ref_n] = FFMAX(refs[1][ref_n], my); - } - } -} - -/** - * Wait until all reference frames are available for MC operations. - * - * @param h the H264 context - */ -static void await_references(H264Context *h) -{ - const int mb_xy = h->mb_xy; - const int mb_type = h->cur_pic.mb_type[mb_xy]; - int refs[2][48]; - int nrefs[2] = { 0 }; - int ref, list; - - memset(refs, -1, sizeof(refs)); - - if (IS_16X16(mb_type)) { - get_lowest_part_y(h, refs, 0, 16, 0, - IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs); - } else if (IS_16X8(mb_type)) { - get_lowest_part_y(h, refs, 0, 8, 0, - IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs); - get_lowest_part_y(h, refs, 8, 8, 8, - IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1), nrefs); - } else if (IS_8X16(mb_type)) { - get_lowest_part_y(h, refs, 0, 16, 0, - IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs); - get_lowest_part_y(h, refs, 4, 16, 0, - IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1), nrefs); - } else { - int i; - - av_assert2(IS_8X8(mb_type)); - - for (i = 0; i < 4; i++) { - const int sub_mb_type = h->sub_mb_type[i]; - const int n = 4 * i; - int y_offset = (i & 2) << 2; - - if (IS_SUB_8X8(sub_mb_type)) { - get_lowest_part_y(h, refs, n, 8, y_offset, - IS_DIR(sub_mb_type, 0, 0), - IS_DIR(sub_mb_type, 0, 1), - nrefs); - } else if (IS_SUB_8X4(sub_mb_type)) { - get_lowest_part_y(h, refs, n, 4, y_offset, - IS_DIR(sub_mb_type, 0, 0), - IS_DIR(sub_mb_type, 0, 1), - nrefs); - get_lowest_part_y(h, refs, n + 2, 4, y_offset + 4, - IS_DIR(sub_mb_type, 0, 0), - IS_DIR(sub_mb_type, 0, 1), - nrefs); - } else if (IS_SUB_4X8(sub_mb_type)) { - get_lowest_part_y(h, refs, n, 8, y_offset, - IS_DIR(sub_mb_type, 0, 0), - IS_DIR(sub_mb_type, 0, 1), - nrefs); - get_lowest_part_y(h, refs, n + 1, 8, y_offset, - IS_DIR(sub_mb_type, 0, 0), - IS_DIR(sub_mb_type, 0, 1), - nrefs); - } else { - int j; - av_assert2(IS_SUB_4X4(sub_mb_type)); - for (j = 0; j < 4; j++) { - int sub_y_offset = y_offset + 2 * (j & 2); - get_lowest_part_y(h, refs, n + j, 4, sub_y_offset, - IS_DIR(sub_mb_type, 0, 0), - IS_DIR(sub_mb_type, 0, 1), - nrefs); - } - } - } - } - - for (list = h->list_count - 1; list >= 0; list--) - for (ref = 0; ref < 48 && nrefs[list]; ref++) { - int row = refs[list][ref]; - if (row >= 0) { - Picture *ref_pic = &h->ref_list[list][ref]; - int ref_field = ref_pic->reference - 1; - int ref_field_picture = ref_pic->field_picture; - int pic_height = 16 * h->mb_height >> ref_field_picture; - - row <<= MB_MBAFF(h); - nrefs[list]--; - - if (!FIELD_PICTURE(h) && ref_field_picture) { // frame referencing two fields - ff_thread_await_progress(&ref_pic->tf, - FFMIN((row >> 1) - !(row & 1), - pic_height - 1), - 1); - ff_thread_await_progress(&ref_pic->tf, - FFMIN((row >> 1), pic_height - 1), - 0); - } else if (FIELD_PICTURE(h) && !ref_field_picture) { // field referencing one field of a frame - ff_thread_await_progress(&ref_pic->tf, - FFMIN(row * 2 + ref_field, - pic_height - 1), - 0); - } else if (FIELD_PICTURE(h)) { - ff_thread_await_progress(&ref_pic->tf, - FFMIN(row, pic_height - 1), - ref_field); - } else { - ff_thread_await_progress(&ref_pic->tf, - FFMIN(row, pic_height - 1), - 0); - } - } - } -} - -static av_always_inline void mc_dir_part(H264Context *h, Picture *pic, - int n, int square, int height, - int delta, int list, - uint8_t *dest_y, uint8_t *dest_cb, - uint8_t *dest_cr, - int src_x_offset, int src_y_offset, - qpel_mc_func *qpix_op, - h264_chroma_mc_func chroma_op, - int pixel_shift, int chroma_idc) -{ - const int mx = h->mv_cache[list][scan8[n]][0] + src_x_offset * 8; - int my = h->mv_cache[list][scan8[n]][1] + src_y_offset * 8; - const int luma_xy = (mx & 3) + ((my & 3) << 2); - ptrdiff_t offset = ((mx >> 2) << pixel_shift) + (my >> 2) * h->mb_linesize; - uint8_t *src_y = pic->f.data[0] + offset; - uint8_t *src_cb, *src_cr; - int extra_width = 0; - int extra_height = 0; - int emu = 0; - const int full_mx = mx >> 2; - const int full_my = my >> 2; - const int pic_width = 16 * h->mb_width; - const int pic_height = 16 * h->mb_height >> MB_FIELD(h); - int ysh; - - if (mx & 7) - extra_width -= 3; - if (my & 7) - extra_height -= 3; - - if (full_mx < 0 - extra_width || - full_my < 0 - extra_height || - full_mx + 16 /*FIXME*/ > pic_width + extra_width || - full_my + 16 /*FIXME*/ > pic_height + extra_height) { - h->vdsp.emulated_edge_mc(h->edge_emu_buffer, - src_y - (2 << pixel_shift) - 2 * h->mb_linesize, - h->mb_linesize, h->mb_linesize, - 16 + 5, 16 + 5 /*FIXME*/, full_mx - 2, - full_my - 2, pic_width, pic_height); - src_y = h->edge_emu_buffer + (2 << pixel_shift) + 2 * h->mb_linesize; - emu = 1; - } - - qpix_op[luma_xy](dest_y, src_y, h->mb_linesize); // FIXME try variable height perhaps? - if (!square) - qpix_op[luma_xy](dest_y + delta, src_y + delta, h->mb_linesize); - - if (CONFIG_GRAY && h->flags & CODEC_FLAG_GRAY) - return; - - if (chroma_idc == 3 /* yuv444 */) { - src_cb = pic->f.data[1] + offset; - if (emu) { - h->vdsp.emulated_edge_mc(h->edge_emu_buffer, - src_cb - (2 << pixel_shift) - 2 * h->mb_linesize, - h->mb_linesize, h->mb_linesize, - 16 + 5, 16 + 5 /*FIXME*/, - full_mx - 2, full_my - 2, - pic_width, pic_height); - src_cb = h->edge_emu_buffer + (2 << pixel_shift) + 2 * h->mb_linesize; - } - qpix_op[luma_xy](dest_cb, src_cb, h->mb_linesize); // FIXME try variable height perhaps? - if (!square) - qpix_op[luma_xy](dest_cb + delta, src_cb + delta, h->mb_linesize); - - src_cr = pic->f.data[2] + offset; - if (emu) { - h->vdsp.emulated_edge_mc(h->edge_emu_buffer, - src_cr - (2 << pixel_shift) - 2 * h->mb_linesize, - h->mb_linesize, h->mb_linesize, - 16 + 5, 16 + 5 /*FIXME*/, - full_mx - 2, full_my - 2, - pic_width, pic_height); - src_cr = h->edge_emu_buffer + (2 << pixel_shift) + 2 * h->mb_linesize; - } - qpix_op[luma_xy](dest_cr, src_cr, h->mb_linesize); // FIXME try variable height perhaps? - if (!square) - qpix_op[luma_xy](dest_cr + delta, src_cr + delta, h->mb_linesize); - return; - } - - ysh = 3 - (chroma_idc == 2 /* yuv422 */); - if (chroma_idc == 1 /* yuv420 */ && MB_FIELD(h)) { - // chroma offset when predicting from a field of opposite parity - my += 2 * ((h->mb_y & 1) - (pic->reference - 1)); - emu |= (my >> 3) < 0 || (my >> 3) + 8 >= (pic_height >> 1); - } - - src_cb = pic->f.data[1] + ((mx >> 3) << pixel_shift) + - (my >> ysh) * h->mb_uvlinesize; - src_cr = pic->f.data[2] + ((mx >> 3) << pixel_shift) + - (my >> ysh) * h->mb_uvlinesize; - - if (emu) { - h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_cb, - h->mb_uvlinesize, h->mb_uvlinesize, - 9, 8 * chroma_idc + 1, (mx >> 3), (my >> ysh), - pic_width >> 1, pic_height >> (chroma_idc == 1 /* yuv420 */)); - src_cb = h->edge_emu_buffer; - } - chroma_op(dest_cb, src_cb, h->mb_uvlinesize, - height >> (chroma_idc == 1 /* yuv420 */), - mx & 7, (my << (chroma_idc == 2 /* yuv422 */)) & 7); - - if (emu) { - h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_cr, - h->mb_uvlinesize, h->mb_uvlinesize, - 9, 8 * chroma_idc + 1, (mx >> 3), (my >> ysh), - pic_width >> 1, pic_height >> (chroma_idc == 1 /* yuv420 */)); - src_cr = h->edge_emu_buffer; - } - chroma_op(dest_cr, src_cr, h->mb_uvlinesize, height >> (chroma_idc == 1 /* yuv420 */), - mx & 7, (my << (chroma_idc == 2 /* yuv422 */)) & 7); -} - -static av_always_inline void mc_part_std(H264Context *h, int n, int square, - int height, int delta, - uint8_t *dest_y, uint8_t *dest_cb, - uint8_t *dest_cr, - int x_offset, int y_offset, - qpel_mc_func *qpix_put, - h264_chroma_mc_func chroma_put, - qpel_mc_func *qpix_avg, - h264_chroma_mc_func chroma_avg, - int list0, int list1, - int pixel_shift, int chroma_idc) -{ - qpel_mc_func *qpix_op = qpix_put; - h264_chroma_mc_func chroma_op = chroma_put; - - dest_y += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; - if (chroma_idc == 3 /* yuv444 */) { - dest_cb += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; - dest_cr += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; - } else if (chroma_idc == 2 /* yuv422 */) { - dest_cb += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; - dest_cr += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; - } else { /* yuv420 */ - dest_cb += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; - dest_cr += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; - } - x_offset += 8 * h->mb_x; - y_offset += 8 * (h->mb_y >> MB_FIELD(h)); - - if (list0) { - Picture *ref = &h->ref_list[0][h->ref_cache[0][scan8[n]]]; - mc_dir_part(h, ref, n, square, height, delta, 0, - dest_y, dest_cb, dest_cr, x_offset, y_offset, - qpix_op, chroma_op, pixel_shift, chroma_idc); - - qpix_op = qpix_avg; - chroma_op = chroma_avg; - } - - if (list1) { - Picture *ref = &h->ref_list[1][h->ref_cache[1][scan8[n]]]; - mc_dir_part(h, ref, n, square, height, delta, 1, - dest_y, dest_cb, dest_cr, x_offset, y_offset, - qpix_op, chroma_op, pixel_shift, chroma_idc); - } -} - -static av_always_inline void mc_part_weighted(H264Context *h, int n, int square, - int height, int delta, - uint8_t *dest_y, uint8_t *dest_cb, - uint8_t *dest_cr, - int x_offset, int y_offset, - qpel_mc_func *qpix_put, - h264_chroma_mc_func chroma_put, - h264_weight_func luma_weight_op, - h264_weight_func chroma_weight_op, - h264_biweight_func luma_weight_avg, - h264_biweight_func chroma_weight_avg, - int list0, int list1, - int pixel_shift, int chroma_idc) -{ - int chroma_height; - - dest_y += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; - if (chroma_idc == 3 /* yuv444 */) { - chroma_height = height; - chroma_weight_avg = luma_weight_avg; - chroma_weight_op = luma_weight_op; - dest_cb += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; - dest_cr += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; - } else if (chroma_idc == 2 /* yuv422 */) { - chroma_height = height; - dest_cb += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; - dest_cr += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; - } else { /* yuv420 */ - chroma_height = height >> 1; - dest_cb += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; - dest_cr += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; - } - x_offset += 8 * h->mb_x; - y_offset += 8 * (h->mb_y >> MB_FIELD(h)); - - if (list0 && list1) { - /* don't optimize for luma-only case, since B-frames usually - * use implicit weights => chroma too. */ - uint8_t *tmp_cb = h->bipred_scratchpad; - uint8_t *tmp_cr = h->bipred_scratchpad + (16 << pixel_shift); - uint8_t *tmp_y = h->bipred_scratchpad + 16 * h->mb_uvlinesize; - int refn0 = h->ref_cache[0][scan8[n]]; - int refn1 = h->ref_cache[1][scan8[n]]; - - mc_dir_part(h, &h->ref_list[0][refn0], n, square, height, delta, 0, - dest_y, dest_cb, dest_cr, - x_offset, y_offset, qpix_put, chroma_put, - pixel_shift, chroma_idc); - mc_dir_part(h, &h->ref_list[1][refn1], n, square, height, delta, 1, - tmp_y, tmp_cb, tmp_cr, - x_offset, y_offset, qpix_put, chroma_put, - pixel_shift, chroma_idc); - - if (h->use_weight == 2) { - int weight0 = h->implicit_weight[refn0][refn1][h->mb_y & 1]; - int weight1 = 64 - weight0; - luma_weight_avg(dest_y, tmp_y, h->mb_linesize, - height, 5, weight0, weight1, 0); - chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, - chroma_height, 5, weight0, weight1, 0); - chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, - chroma_height, 5, weight0, weight1, 0); - } else { - luma_weight_avg(dest_y, tmp_y, h->mb_linesize, height, - h->luma_log2_weight_denom, - h->luma_weight[refn0][0][0], - h->luma_weight[refn1][1][0], - h->luma_weight[refn0][0][1] + - h->luma_weight[refn1][1][1]); - chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, chroma_height, - h->chroma_log2_weight_denom, - h->chroma_weight[refn0][0][0][0], - h->chroma_weight[refn1][1][0][0], - h->chroma_weight[refn0][0][0][1] + - h->chroma_weight[refn1][1][0][1]); - chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, chroma_height, - h->chroma_log2_weight_denom, - h->chroma_weight[refn0][0][1][0], - h->chroma_weight[refn1][1][1][0], - h->chroma_weight[refn0][0][1][1] + - h->chroma_weight[refn1][1][1][1]); - } - } else { - int list = list1 ? 1 : 0; - int refn = h->ref_cache[list][scan8[n]]; - Picture *ref = &h->ref_list[list][refn]; - mc_dir_part(h, ref, n, square, height, delta, list, - dest_y, dest_cb, dest_cr, x_offset, y_offset, - qpix_put, chroma_put, pixel_shift, chroma_idc); - - luma_weight_op(dest_y, h->mb_linesize, height, - h->luma_log2_weight_denom, - h->luma_weight[refn][list][0], - h->luma_weight[refn][list][1]); - if (h->use_weight_chroma) { - chroma_weight_op(dest_cb, h->mb_uvlinesize, chroma_height, - h->chroma_log2_weight_denom, - h->chroma_weight[refn][list][0][0], - h->chroma_weight[refn][list][0][1]); - chroma_weight_op(dest_cr, h->mb_uvlinesize, chroma_height, - h->chroma_log2_weight_denom, - h->chroma_weight[refn][list][1][0], - h->chroma_weight[refn][list][1][1]); - } - } -} - -static av_always_inline void prefetch_motion(H264Context *h, int list, - int pixel_shift, int chroma_idc) -{ - /* fetch pixels for estimated mv 4 macroblocks ahead - * optimized for 64byte cache lines */ - const int refn = h->ref_cache[list][scan8[0]]; - if (refn >= 0) { - const int mx = (h->mv_cache[list][scan8[0]][0] >> 2) + 16 * h->mb_x + 8; - const int my = (h->mv_cache[list][scan8[0]][1] >> 2) + 16 * h->mb_y; - uint8_t **src = h->ref_list[list][refn].f.data; - int off = (mx << pixel_shift) + - (my + (h->mb_x & 3) * 4) * h->mb_linesize + - (64 << pixel_shift); - h->vdsp.prefetch(src[0] + off, h->linesize, 4); - if (chroma_idc == 3 /* yuv444 */) { - h->vdsp.prefetch(src[1] + off, h->linesize, 4); - h->vdsp.prefetch(src[2] + off, h->linesize, 4); - } else { - off= (((mx>>1)+64)<>1) + (h->mb_x&7))*h->uvlinesize; - h->vdsp.prefetch(src[1] + off, src[2] - src[1], 2); - } - } -} - -static void free_tables(H264Context *h, int free_rbsp) +void ff_h264_free_tables(H264Context *h, int free_rbsp) { int i; H264Context *hx; @@ -1233,17 +390,17 @@ static void free_tables(H264Context *h, int free_rbsp) av_buffer_pool_uninit(&h->ref_index_pool); if (free_rbsp && h->DPB) { - for (i = 0; i < MAX_PICTURE_COUNT; i++) - unref_picture(h, &h->DPB[i]); + 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 < MAX_PICTURE_COUNT; i++) + for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) h->DPB[i].needs_realloc = 1; } h->cur_pic_ptr = NULL; - for (i = 0; i < MAX_THREADS; i++) { + for (i = 0; i < H264_MAX_THREADS; i++) { hx = h->thread_context[i]; if (!hx) continue; @@ -1252,7 +409,6 @@ static void free_tables(H264Context *h, int free_rbsp) av_freep(&hx->bipred_scratchpad); av_freep(&hx->edge_emu_buffer); av_freep(&hx->dc_val_base); - av_freep(&hx->me.scratchpad); av_freep(&hx->er.mb_index2xy); av_freep(&hx->er.error_status_table); av_freep(&hx->er.er_temp_buffer); @@ -1270,78 +426,6 @@ static void free_tables(H264Context *h, int free_rbsp) } } -static void init_dequant8_coeff_table(H264Context *h) -{ - int i, j, q, x; - const int max_qp = 51 + 6 * (h->sps.bit_depth_luma - 8); - - for (i = 0; i < 6; i++) { - h->dequant8_coeff[i] = h->dequant8_buffer[i]; - for (j = 0; j < i; j++) - if (!memcmp(h->pps.scaling_matrix8[j], h->pps.scaling_matrix8[i], - 64 * sizeof(uint8_t))) { - h->dequant8_coeff[i] = h->dequant8_buffer[j]; - break; - } - if (j < i) - continue; - - for (q = 0; q < max_qp + 1; q++) { - int shift = div6[q]; - int idx = rem6[q]; - for (x = 0; x < 64; x++) - h->dequant8_coeff[i][q][(x >> 3) | ((x & 7) << 3)] = - ((uint32_t)dequant8_coeff_init[idx][dequant8_coeff_init_scan[((x >> 1) & 12) | (x & 3)]] * - h->pps.scaling_matrix8[i][x]) << shift; - } - } -} - -static void init_dequant4_coeff_table(H264Context *h) -{ - int i, j, q, x; - const int max_qp = 51 + 6 * (h->sps.bit_depth_luma - 8); - for (i = 0; i < 6; i++) { - h->dequant4_coeff[i] = h->dequant4_buffer[i]; - for (j = 0; j < i; j++) - if (!memcmp(h->pps.scaling_matrix4[j], h->pps.scaling_matrix4[i], - 16 * sizeof(uint8_t))) { - h->dequant4_coeff[i] = h->dequant4_buffer[j]; - break; - } - if (j < i) - continue; - - for (q = 0; q < max_qp + 1; q++) { - int shift = div6[q] + 2; - int idx = rem6[q]; - for (x = 0; x < 16; x++) - h->dequant4_coeff[i][q][(x >> 2) | ((x << 2) & 0xF)] = - ((uint32_t)dequant4_coeff_init[idx][(x & 1) + ((x >> 2) & 1)] * - h->pps.scaling_matrix4[i][x]) << shift; - } - } -} - -static void init_dequant_tables(H264Context *h) -{ - int i, x; - init_dequant4_coeff_table(h); - memset(h->dequant8_coeff, 0, sizeof(h->dequant8_coeff)); - - if (h->pps.transform_8x8_mode) - init_dequant8_coeff_table(h); - if (h->sps.transform_bypass) { - for (i = 0; i < 6; i++) - for (x = 0; x < 16; x++) - h->dequant4_coeff[i][0][x] = 1 << 6; - if (h->pps.transform_8x8_mode) - for (i = 0; i < 6; i++) - for (x = 0; x < 64; x++) - h->dequant8_coeff[i][0][x] = 1 << 6; - } -} - int ff_h264_alloc_tables(H264Context *h) { const int big_mb_num = h->mb_stride * (h->mb_height + 1); @@ -1385,13 +469,13 @@ int ff_h264_alloc_tables(H264Context *h) } if (!h->dequant4_coeff[0]) - init_dequant_tables(h); + h264_init_dequant_tables(h); if (!h->DPB) { - h->DPB = av_mallocz_array(MAX_PICTURE_COUNT, sizeof(*h->DPB)); + h->DPB = av_mallocz_array(H264_MAX_PICTURE_COUNT, sizeof(*h->DPB)); if (!h->DPB) return AVERROR(ENOMEM); - for (i = 0; i < MAX_PICTURE_COUNT; i++) + for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) av_frame_unref(&h->DPB[i].f); av_frame_unref(&h->cur_pic.f); } @@ -1399,41 +483,15 @@ int ff_h264_alloc_tables(H264Context *h) return 0; fail: - free_tables(h, 1); + ff_h264_free_tables(h, 1); return AVERROR(ENOMEM); } -/** - * Mimic alloc_tables(), but for every context thread. - */ -static void clone_tables(H264Context *dst, H264Context *src, int i) -{ - dst->intra4x4_pred_mode = src->intra4x4_pred_mode + i * 8 * 2 * src->mb_stride; - dst->non_zero_count = src->non_zero_count; - dst->slice_table = src->slice_table; - dst->cbp_table = src->cbp_table; - dst->mb2b_xy = src->mb2b_xy; - dst->mb2br_xy = src->mb2br_xy; - dst->chroma_pred_mode_table = src->chroma_pred_mode_table; - dst->mvd_table[0] = src->mvd_table[0] + i * 8 * 2 * src->mb_stride; - dst->mvd_table[1] = src->mvd_table[1] + i * 8 * 2 * src->mb_stride; - dst->direct_table = src->direct_table; - dst->list_counts = src->list_counts; - dst->DPB = src->DPB; - dst->cur_pic_ptr = src->cur_pic_ptr; - dst->cur_pic = src->cur_pic; - dst->bipred_scratchpad = NULL; - dst->edge_emu_buffer = NULL; - dst->me.scratchpad = NULL; - ff_h264_pred_init(&dst->hpc, src->avctx->codec_id, src->sps.bit_depth_luma, - src->sps.chroma_format_idc); -} - /** * Init context * Allocate buffers which are not shared amongst multiple threads. */ -static int context_init(H264Context *h) +int ff_h264_context_init(H264Context *h) { ERContext *er = &h->er; int mb_array_size = h->mb_height * h->mb_stride; @@ -1499,7 +557,7 @@ static int context_init(H264Context *h) return 0; fail: - return AVERROR(ENOMEM); // free_tables will clean up for us + 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, @@ -1652,49 +710,7 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx) avctx->internal->allocate_progress = 1; - flush_change(h); - - return 0; -} - -#define IN_RANGE(a, b, size) (((a) >= (b)) && ((a) < ((b) + (size)))) -#undef REBASE_PICTURE -#define REBASE_PICTURE(pic, new_ctx, old_ctx) \ - ((pic && pic >= old_ctx->DPB && \ - pic < old_ctx->DPB + MAX_PICTURE_COUNT) ? \ - &new_ctx->DPB[pic - old_ctx->DPB] : NULL) - -static void copy_picture_range(Picture **to, Picture **from, int count, - H264Context *new_base, - H264Context *old_base) -{ - int i; - - for (i = 0; i < count; i++) { - assert((IN_RANGE(from[i], old_base, sizeof(*old_base)) || - IN_RANGE(from[i], old_base->DPB, - sizeof(Picture) * MAX_PICTURE_COUNT) || - !from[i])); - to[i] = REBASE_PICTURE(from[i], new_base, old_base); - } -} - -static 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); - } + ff_h264_flush_change(h); return 0; } @@ -1717,323 +733,6 @@ static int decode_init_thread_copy(AVCodecContext *avctx) return 0; } -#define copy_fields(to, from, start_field, end_field) \ - memcpy(&to->start_field, &from->start_field, \ - (char *)&to->end_field - (char *)&to->start_field) - -static int h264_slice_header_init(H264Context *, int); - -static int h264_set_parameter_from_sps(H264Context *h); - -static int decode_update_thread_context(AVCodecContext *dst, - const AVCodecContext *src) -{ - H264Context *h = dst->priv_data, *h1 = src->priv_data; - int inited = h->context_initialized, err = 0; - int context_reinitialized = 0; - int i, ret; - - if (dst == src) - return 0; - - if (inited && - (h->width != h1->width || - h->height != h1->height || - h->mb_width != h1->mb_width || - h->mb_height != h1->mb_height || - h->sps.bit_depth_luma != h1->sps.bit_depth_luma || - h->sps.chroma_format_idc != h1->sps.chroma_format_idc || - h->sps.colorspace != h1->sps.colorspace)) { - - /* set bits_per_raw_sample to the previous value. the check for changed - * bit depth in h264_set_parameter_from_sps() uses it and sets it to - * the current value */ - h->avctx->bits_per_raw_sample = h->sps.bit_depth_luma; - - av_freep(&h->bipred_scratchpad); - - h->width = h1->width; - h->height = h1->height; - h->mb_height = h1->mb_height; - h->mb_width = h1->mb_width; - h->mb_num = h1->mb_num; - h->mb_stride = h1->mb_stride; - h->b_stride = h1->b_stride; - // SPS/PPS - 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; - - if ((err = h264_slice_header_init(h, 1)) < 0) { - av_log(h->avctx, AV_LOG_ERROR, "h264_slice_header_init() failed"); - return err; - } - context_reinitialized = 1; - -#if 0 - h264_set_parameter_from_sps(h); - //Note we set context_reinitialized which will cause h264_set_parameter_from_sps to be reexecuted - h->cur_chroma_format_idc = h1->cur_chroma_format_idc; -#endif - } - /* update linesize on resize for h264. The h264 decoder doesn't - * necessarily call ff_MPV_frame_start in the new thread */ - h->linesize = h1->linesize; - h->uvlinesize = h1->uvlinesize; - - /* copy block_offset since frame_start may not be called */ - memcpy(h->block_offset, h1->block_offset, sizeof(h->block_offset)); - - if (!inited) { - for (i = 0; i < MAX_SPS_COUNT; i++) - av_freep(h->sps_buffers + i); - - for (i = 0; i < MAX_PPS_COUNT; i++) - av_freep(h->pps_buffers + i); - - av_freep(&h->rbsp_buffer[0]); - av_freep(&h->rbsp_buffer[1]); - memcpy(h, h1, offsetof(H264Context, intra_pcm_ptr)); - memcpy(&h->cabac, &h1->cabac, - sizeof(H264Context) - offsetof(H264Context, cabac)); - av_assert0((void*)&h->cabac == &h->mb_padding + 1); - - memset(h->sps_buffers, 0, sizeof(h->sps_buffers)); - memset(h->pps_buffers, 0, sizeof(h->pps_buffers)); - - memset(&h->er, 0, sizeof(h->er)); - memset(&h->me, 0, sizeof(h->me)); - 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)); - memset(&h->cur_pic, 0, sizeof(h->cur_pic)); - - 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; - for (i = 0; i < 2; i++) { - h->rbsp_buffer[i] = NULL; - h->rbsp_buffer_size[i] = 0; - } - - if (h1->context_initialized) { - 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; - - ret = ff_h264_alloc_tables(h); - if (ret < 0) { - av_log(dst, AV_LOG_ERROR, "Could not allocate memory\n"); - return ret; - } - ret = context_init(h); - if (ret < 0) { - av_log(dst, AV_LOG_ERROR, "context_init() failed.\n"); - return ret; - } - } - - h->bipred_scratchpad = NULL; - h->edge_emu_buffer = NULL; - - h->thread_context[0] = h; - h->context_initialized = h1->context_initialized; - } - - h->avctx->coded_height = h1->avctx->coded_height; - h->avctx->coded_width = h1->avctx->coded_width; - h->avctx->width = h1->avctx->width; - h->avctx->height = h1->avctx->height; - h->coded_picture_number = h1->coded_picture_number; - h->first_field = h1->first_field; - h->picture_structure = h1->picture_structure; - h->qscale = h1->qscale; - h->droppable = h1->droppable; - h->low_delay = h1->low_delay; - - for (i = 0; h->DPB && i < MAX_PICTURE_COUNT; i++) { - unref_picture(h, &h->DPB[i]); - if (h1->DPB && h1->DPB[i].f.buf[0] && - (ret = ref_picture(h, &h->DPB[i], &h1->DPB[i])) < 0) - return ret; - } - - h->cur_pic_ptr = REBASE_PICTURE(h1->cur_pic_ptr, h, h1); - unref_picture(h, &h->cur_pic); - if (h1->cur_pic.f.buf[0] && (ret = ref_picture(h, &h->cur_pic, &h1->cur_pic)) < 0) - return ret; - - h->workaround_bugs = h1->workaround_bugs; - h->low_delay = h1->low_delay; - h->droppable = h1->droppable; - - // extradata/NAL handling - h->is_avc = h1->is_avc; - - // SPS/PPS - 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]); - - for (i = 0; i < 6; i++) - h->dequant8_coeff[i] = h->dequant8_buffer[0] + - (h1->dequant8_coeff[i] - h1->dequant8_buffer[0]); - - h->dequant_coeff_pps = h1->dequant_coeff_pps; - - // POC timing - copy_fields(h, h1, poc_lsb, redundant_pic_count); - - // reference lists - copy_fields(h, h1, short_ref, cabac_init_idc); - - copy_picture_range(h->short_ref, h1->short_ref, 32, h, h1); - copy_picture_range(h->long_ref, h1->long_ref, 32, h, h1); - copy_picture_range(h->delayed_pic, h1->delayed_pic, - MAX_DELAYED_PIC_COUNT + 2, h, h1); - - h->frame_recovered = h1->frame_recovered; - - if (context_reinitialized) - h264_set_parameter_from_sps(h); - - if (!h->cur_pic_ptr) - return 0; - - if (!h->droppable) { - err = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index); - h->prev_poc_msb = h->poc_msb; - h->prev_poc_lsb = h->poc_lsb; - } - h->prev_frame_num_offset = h->frame_num_offset; - h->prev_frame_num = h->frame_num; - h->outputed_poc = h->next_outputed_poc; - - h->recovery_frame = h1->recovery_frame; - - return err; -} - -static int h264_frame_start(H264Context *h) -{ - Picture *pic; - int i, ret; - const int pixel_shift = h->pixel_shift; - int c[4] = { - 1<<(h->sps.bit_depth_luma-1), - 1<<(h->sps.bit_depth_chroma-1), - 1<<(h->sps.bit_depth_chroma-1), - -1 - }; - - if (!ff_thread_can_start_frame(h->avctx)) { - av_log(h->avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n"); - return -1; - } - - release_unused_pictures(h, 1); - h->cur_pic_ptr = NULL; - - i = find_unused_picture(h); - if (i < 0) { - av_log(h->avctx, AV_LOG_ERROR, "no frame buffer available\n"); - return i; - } - pic = &h->DPB[i]; - - pic->reference = h->droppable ? 0 : h->picture_structure; - pic->f.coded_picture_number = h->coded_picture_number++; - pic->field_picture = h->picture_structure != PICT_FRAME; - - /* - * Zero key_frame here; IDR markings per slice in frame or fields are ORed - * in later. - * See decode_nal_units(). - */ - pic->f.key_frame = 0; - pic->mmco_reset = 0; - pic->recovered = 0; - pic->invalid_gap = 0; - - if ((ret = alloc_picture(h, pic)) < 0) - return ret; - if(!h->frame_recovered && !h->avctx->hwaccel && - !(h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)) - avpriv_color_frame(&pic->f, c); - - h->cur_pic_ptr = pic; - unref_picture(h, &h->cur_pic); - if (CONFIG_ERROR_RESILIENCE) { - h->er.cur_pic = NULL; - } - - if ((ret = ref_picture(h, &h->cur_pic, h->cur_pic_ptr)) < 0) - return ret; - - if (CONFIG_ERROR_RESILIENCE) { - ff_er_frame_start(&h->er); - h->er.last_pic = - h->er.next_pic = NULL; - } - - assert(h->linesize && h->uvlinesize); - - for (i = 0; i < 16; i++) { - h->block_offset[i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * h->linesize * ((scan8[i] - scan8[0]) >> 3); - h->block_offset[48 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * h->linesize * ((scan8[i] - scan8[0]) >> 3); - } - for (i = 0; i < 16; i++) { - h->block_offset[16 + i] = - h->block_offset[32 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * h->uvlinesize * ((scan8[i] - scan8[0]) >> 3); - h->block_offset[48 + 16 + i] = - h->block_offset[48 + 32 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * h->uvlinesize * ((scan8[i] - scan8[0]) >> 3); - } - - // s->decode = (h->flags & CODEC_FLAG_PSNR) || !s->encoding || - // h->cur_pic.reference /* || h->contains_intra */ || 1; - - /* We mark the current picture as non-reference after allocating it, so - * that if we break out due to an error it can be released automatically - * in the next ff_MPV_frame_start(). - */ - h->cur_pic_ptr->reference = 0; - - h->cur_pic_ptr->field_poc[0] = h->cur_pic_ptr->field_poc[1] = INT_MAX; - - h->next_output_pic = NULL; - - assert(h->cur_pic_ptr->long_ref == 0); - - return 0; -} - /** * Run setup operations that must be run after slice header decoding. * This includes finding the next displayed frame. @@ -2044,8 +743,8 @@ static int h264_frame_start(H264Context *h) */ static void decode_postinit(H264Context *h, int setup_finished) { - Picture *out = h->cur_pic_ptr; - Picture *cur = h->cur_pic_ptr; + H264Picture *out = h->cur_pic_ptr; + H264Picture *cur = h->cur_pic_ptr; int i, pics, out_of_order, out_idx; h->cur_pic_ptr->f.pict_type = h->pict_type; @@ -2168,6 +867,20 @@ static void decode_postinit(H264Context *h, int setup_finished) 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_vflip, h->sei_hflip); + } + cur->mmco_reset = h->mmco_reset; h->mmco_reset = 0; @@ -2267,424 +980,6 @@ static void decode_postinit(H264Context *h, int setup_finished) ff_thread_finish_setup(h->avctx); } -static av_always_inline void backup_mb_border(H264Context *h, uint8_t *src_y, - uint8_t *src_cb, uint8_t *src_cr, - int linesize, int uvlinesize, - int simple) -{ - uint8_t *top_border; - int top_idx = 1; - const int pixel_shift = h->pixel_shift; - int chroma444 = CHROMA444(h); - int chroma422 = CHROMA422(h); - - src_y -= linesize; - src_cb -= uvlinesize; - src_cr -= uvlinesize; - - if (!simple && FRAME_MBAFF(h)) { - if (h->mb_y & 1) { - if (!MB_MBAFF(h)) { - top_border = h->top_borders[0][h->mb_x]; - AV_COPY128(top_border, src_y + 15 * linesize); - if (pixel_shift) - AV_COPY128(top_border + 16, src_y + 15 * linesize + 16); - if (simple || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { - if (chroma444) { - if (pixel_shift) { - AV_COPY128(top_border + 32, src_cb + 15 * uvlinesize); - AV_COPY128(top_border + 48, src_cb + 15 * uvlinesize + 16); - AV_COPY128(top_border + 64, src_cr + 15 * uvlinesize); - AV_COPY128(top_border + 80, src_cr + 15 * uvlinesize + 16); - } else { - AV_COPY128(top_border + 16, src_cb + 15 * uvlinesize); - AV_COPY128(top_border + 32, src_cr + 15 * uvlinesize); - } - } else if (chroma422) { - if (pixel_shift) { - AV_COPY128(top_border + 32, src_cb + 15 * uvlinesize); - AV_COPY128(top_border + 48, src_cr + 15 * uvlinesize); - } else { - AV_COPY64(top_border + 16, src_cb + 15 * uvlinesize); - AV_COPY64(top_border + 24, src_cr + 15 * uvlinesize); - } - } else { - if (pixel_shift) { - AV_COPY128(top_border + 32, src_cb + 7 * uvlinesize); - AV_COPY128(top_border + 48, src_cr + 7 * uvlinesize); - } else { - AV_COPY64(top_border + 16, src_cb + 7 * uvlinesize); - AV_COPY64(top_border + 24, src_cr + 7 * uvlinesize); - } - } - } - } - } else if (MB_MBAFF(h)) { - top_idx = 0; - } else - return; - } - - top_border = h->top_borders[top_idx][h->mb_x]; - /* There are two lines saved, the line above the top macroblock - * of a pair, and the line above the bottom macroblock. */ - AV_COPY128(top_border, src_y + 16 * linesize); - if (pixel_shift) - AV_COPY128(top_border + 16, src_y + 16 * linesize + 16); - - if (simple || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { - if (chroma444) { - if (pixel_shift) { - AV_COPY128(top_border + 32, src_cb + 16 * linesize); - AV_COPY128(top_border + 48, src_cb + 16 * linesize + 16); - AV_COPY128(top_border + 64, src_cr + 16 * linesize); - AV_COPY128(top_border + 80, src_cr + 16 * linesize + 16); - } else { - AV_COPY128(top_border + 16, src_cb + 16 * linesize); - AV_COPY128(top_border + 32, src_cr + 16 * linesize); - } - } else if (chroma422) { - if (pixel_shift) { - AV_COPY128(top_border + 32, src_cb + 16 * uvlinesize); - AV_COPY128(top_border + 48, src_cr + 16 * uvlinesize); - } else { - AV_COPY64(top_border + 16, src_cb + 16 * uvlinesize); - AV_COPY64(top_border + 24, src_cr + 16 * uvlinesize); - } - } else { - if (pixel_shift) { - AV_COPY128(top_border + 32, src_cb + 8 * uvlinesize); - AV_COPY128(top_border + 48, src_cr + 8 * uvlinesize); - } else { - AV_COPY64(top_border + 16, src_cb + 8 * uvlinesize); - AV_COPY64(top_border + 24, src_cr + 8 * uvlinesize); - } - } - } -} - -static av_always_inline void xchg_mb_border(H264Context *h, uint8_t *src_y, - uint8_t *src_cb, uint8_t *src_cr, - int linesize, int uvlinesize, - int xchg, int chroma444, - int simple, int pixel_shift) -{ - int deblock_topleft; - int deblock_top; - int top_idx = 1; - uint8_t *top_border_m1; - uint8_t *top_border; - - if (!simple && FRAME_MBAFF(h)) { - if (h->mb_y & 1) { - if (!MB_MBAFF(h)) - return; - } else { - top_idx = MB_MBAFF(h) ? 0 : 1; - } - } - - if (h->deblocking_filter == 2) { - deblock_topleft = h->slice_table[h->mb_xy - 1 - h->mb_stride] == h->slice_num; - deblock_top = h->top_type; - } else { - deblock_topleft = (h->mb_x > 0); - deblock_top = (h->mb_y > !!MB_FIELD(h)); - } - - src_y -= linesize + 1 + pixel_shift; - src_cb -= uvlinesize + 1 + pixel_shift; - src_cr -= uvlinesize + 1 + pixel_shift; - - top_border_m1 = h->top_borders[top_idx][h->mb_x - 1]; - top_border = h->top_borders[top_idx][h->mb_x]; - -#define XCHG(a, b, xchg) \ - if (pixel_shift) { \ - if (xchg) { \ - AV_SWAP64(b + 0, a + 0); \ - AV_SWAP64(b + 8, a + 8); \ - } else { \ - AV_COPY128(b, a); \ - } \ - } else if (xchg) \ - AV_SWAP64(b, a); \ - else \ - AV_COPY64(b, a); - - if (deblock_top) { - if (deblock_topleft) { - XCHG(top_border_m1 + (8 << pixel_shift), - src_y - (7 << pixel_shift), 1); - } - XCHG(top_border + (0 << pixel_shift), src_y + (1 << pixel_shift), xchg); - XCHG(top_border + (8 << pixel_shift), src_y + (9 << pixel_shift), 1); - if (h->mb_x + 1 < h->mb_width) { - XCHG(h->top_borders[top_idx][h->mb_x + 1], - src_y + (17 << pixel_shift), 1); - } - if (simple || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { - if (chroma444) { - if (deblock_topleft) { - XCHG(top_border_m1 + (24 << pixel_shift), src_cb - (7 << pixel_shift), 1); - XCHG(top_border_m1 + (40 << pixel_shift), src_cr - (7 << pixel_shift), 1); - } - XCHG(top_border + (16 << pixel_shift), src_cb + (1 << pixel_shift), xchg); - XCHG(top_border + (24 << pixel_shift), src_cb + (9 << pixel_shift), 1); - XCHG(top_border + (32 << pixel_shift), src_cr + (1 << pixel_shift), xchg); - XCHG(top_border + (40 << pixel_shift), src_cr + (9 << pixel_shift), 1); - if (h->mb_x + 1 < h->mb_width) { - XCHG(h->top_borders[top_idx][h->mb_x + 1] + (16 << pixel_shift), src_cb + (17 << pixel_shift), 1); - XCHG(h->top_borders[top_idx][h->mb_x + 1] + (32 << pixel_shift), src_cr + (17 << pixel_shift), 1); - } - } else { - if (deblock_topleft) { - XCHG(top_border_m1 + (16 << pixel_shift), src_cb - (7 << pixel_shift), 1); - XCHG(top_border_m1 + (24 << pixel_shift), src_cr - (7 << pixel_shift), 1); - } - XCHG(top_border + (16 << pixel_shift), src_cb + 1 + pixel_shift, 1); - XCHG(top_border + (24 << pixel_shift), src_cr + 1 + pixel_shift, 1); - } - } - } -} - -static av_always_inline int dctcoef_get(int16_t *mb, int high_bit_depth, - int index) -{ - if (high_bit_depth) { - return AV_RN32A(((int32_t *)mb) + index); - } else - return AV_RN16A(mb + index); -} - -static av_always_inline void dctcoef_set(int16_t *mb, int high_bit_depth, - int index, int value) -{ - if (high_bit_depth) { - AV_WN32A(((int32_t *)mb) + index, value); - } else - AV_WN16A(mb + index, value); -} - -static av_always_inline void hl_decode_mb_predict_luma(H264Context *h, - int mb_type, int is_h264, - int simple, - int transform_bypass, - int pixel_shift, - int *block_offset, - int linesize, - uint8_t *dest_y, int p) -{ - void (*idct_add)(uint8_t *dst, int16_t *block, int stride); - void (*idct_dc_add)(uint8_t *dst, int16_t *block, int stride); - int i; - int qscale = p == 0 ? h->qscale : h->chroma_qp[p - 1]; - block_offset += 16 * p; - if (IS_INTRA4x4(mb_type)) { - if (IS_8x8DCT(mb_type)) { - if (transform_bypass) { - idct_dc_add = - idct_add = h->h264dsp.h264_add_pixels8_clear; - } else { - idct_dc_add = h->h264dsp.h264_idct8_dc_add; - idct_add = h->h264dsp.h264_idct8_add; - } - for (i = 0; i < 16; i += 4) { - uint8_t *const ptr = dest_y + block_offset[i]; - const int dir = h->intra4x4_pred_mode_cache[scan8[i]]; - if (transform_bypass && h->sps.profile_idc == 244 && dir <= 1) { - h->hpc.pred8x8l_add[dir](ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); - } else { - const int nnz = h->non_zero_count_cache[scan8[i + p * 16]]; - h->hpc.pred8x8l[dir](ptr, (h->topleft_samples_available << i) & 0x8000, - (h->topright_samples_available << i) & 0x4000, linesize); - if (nnz) { - if (nnz == 1 && dctcoef_get(h->mb, pixel_shift, i * 16 + p * 256)) - idct_dc_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); - else - idct_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); - } - } - } - } else { - if (transform_bypass) { - idct_dc_add = - idct_add = h->h264dsp.h264_add_pixels4_clear; - } else { - idct_dc_add = h->h264dsp.h264_idct_dc_add; - idct_add = h->h264dsp.h264_idct_add; - } - for (i = 0; i < 16; i++) { - uint8_t *const ptr = dest_y + block_offset[i]; - const int dir = h->intra4x4_pred_mode_cache[scan8[i]]; - - if (transform_bypass && h->sps.profile_idc == 244 && dir <= 1) { - h->hpc.pred4x4_add[dir](ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); - } else { - uint8_t *topright; - int nnz, tr; - uint64_t tr_high; - if (dir == DIAG_DOWN_LEFT_PRED || dir == VERT_LEFT_PRED) { - const int topright_avail = (h->topright_samples_available << i) & 0x8000; - av_assert2(h->mb_y || linesize <= block_offset[i]); - if (!topright_avail) { - if (pixel_shift) { - tr_high = ((uint16_t *)ptr)[3 - linesize / 2] * 0x0001000100010001ULL; - topright = (uint8_t *)&tr_high; - } else { - tr = ptr[3 - linesize] * 0x01010101u; - topright = (uint8_t *)&tr; - } - } else - topright = ptr + (4 << pixel_shift) - linesize; - } else - topright = NULL; - - h->hpc.pred4x4[dir](ptr, topright, linesize); - nnz = h->non_zero_count_cache[scan8[i + p * 16]]; - if (nnz) { - if (is_h264) { - if (nnz == 1 && dctcoef_get(h->mb, pixel_shift, i * 16 + p * 256)) - idct_dc_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); - else - idct_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); - } else if (CONFIG_SVQ3_DECODER) - ff_svq3_add_idct_c(ptr, h->mb + i * 16 + p * 256, linesize, qscale, 0); - } - } - } - } - } else { - h->hpc.pred16x16[h->intra16x16_pred_mode](dest_y, linesize); - if (is_h264) { - if (h->non_zero_count_cache[scan8[LUMA_DC_BLOCK_INDEX + p]]) { - if (!transform_bypass) - h->h264dsp.h264_luma_dc_dequant_idct(h->mb + (p * 256 << pixel_shift), - h->mb_luma_dc[p], - h->dequant4_coeff[p][qscale][0]); - else { - static const uint8_t dc_mapping[16] = { - 0 * 16, 1 * 16, 4 * 16, 5 * 16, - 2 * 16, 3 * 16, 6 * 16, 7 * 16, - 8 * 16, 9 * 16, 12 * 16, 13 * 16, - 10 * 16, 11 * 16, 14 * 16, 15 * 16 - }; - for (i = 0; i < 16; i++) - dctcoef_set(h->mb + (p * 256 << pixel_shift), - pixel_shift, dc_mapping[i], - dctcoef_get(h->mb_luma_dc[p], - pixel_shift, i)); - } - } - } else if (CONFIG_SVQ3_DECODER) - ff_svq3_luma_dc_dequant_idct_c(h->mb + p * 256, - h->mb_luma_dc[p], qscale); - } -} - -static av_always_inline void hl_decode_mb_idct_luma(H264Context *h, int mb_type, - int is_h264, int simple, - int transform_bypass, - int pixel_shift, - int *block_offset, - int linesize, - uint8_t *dest_y, int p) -{ - void (*idct_add)(uint8_t *dst, int16_t *block, int stride); - int i; - block_offset += 16 * p; - if (!IS_INTRA4x4(mb_type)) { - if (is_h264) { - if (IS_INTRA16x16(mb_type)) { - if (transform_bypass) { - if (h->sps.profile_idc == 244 && - (h->intra16x16_pred_mode == VERT_PRED8x8 || - h->intra16x16_pred_mode == HOR_PRED8x8)) { - h->hpc.pred16x16_add[h->intra16x16_pred_mode](dest_y, block_offset, - h->mb + (p * 256 << pixel_shift), - linesize); - } else { - for (i = 0; i < 16; i++) - if (h->non_zero_count_cache[scan8[i + p * 16]] || - dctcoef_get(h->mb, pixel_shift, i * 16 + p * 256)) - h->h264dsp.h264_add_pixels4_clear(dest_y + block_offset[i], - h->mb + (i * 16 + p * 256 << pixel_shift), - linesize); - } - } else { - h->h264dsp.h264_idct_add16intra(dest_y, block_offset, - h->mb + (p * 256 << pixel_shift), - linesize, - h->non_zero_count_cache + p * 5 * 8); - } - } else if (h->cbp & 15) { - if (transform_bypass) { - const int di = IS_8x8DCT(mb_type) ? 4 : 1; - idct_add = IS_8x8DCT(mb_type) ? h->h264dsp.h264_add_pixels8_clear - : h->h264dsp.h264_add_pixels4_clear; - for (i = 0; i < 16; i += di) - if (h->non_zero_count_cache[scan8[i + p * 16]]) - idct_add(dest_y + block_offset[i], - h->mb + (i * 16 + p * 256 << pixel_shift), - linesize); - } else { - if (IS_8x8DCT(mb_type)) - h->h264dsp.h264_idct8_add4(dest_y, block_offset, - h->mb + (p * 256 << pixel_shift), - linesize, - h->non_zero_count_cache + p * 5 * 8); - else - h->h264dsp.h264_idct_add16(dest_y, block_offset, - h->mb + (p * 256 << pixel_shift), - linesize, - h->non_zero_count_cache + p * 5 * 8); - } - } - } else if (CONFIG_SVQ3_DECODER) { - for (i = 0; i < 16; i++) - if (h->non_zero_count_cache[scan8[i + p * 16]] || h->mb[i * 16 + p * 256]) { - // FIXME benchmark weird rule, & below - uint8_t *const ptr = dest_y + block_offset[i]; - ff_svq3_add_idct_c(ptr, h->mb + i * 16 + p * 256, linesize, - h->qscale, IS_INTRA(mb_type) ? 1 : 0); - } - } - } -} - -#define BITS 8 -#define SIMPLE 1 -#include "h264_mb_template.c" - -#undef BITS -#define BITS 16 -#include "h264_mb_template.c" - -#undef SIMPLE -#define SIMPLE 0 -#include "h264_mb_template.c" - -void ff_h264_hl_decode_mb(H264Context *h) -{ - const int mb_xy = h->mb_xy; - const int mb_type = h->cur_pic.mb_type[mb_xy]; - int is_complex = CONFIG_SMALL || h->is_complex || - IS_INTRA_PCM(mb_type) || h->qscale == 0; - - if (CHROMA444(h)) { - if (is_complex || h->pixel_shift) - hl_decode_mb_444_complex(h); - else - hl_decode_mb_444_simple_8(h); - } else if (is_complex) { - hl_decode_mb_complex(h); - } else if (h->pixel_shift) { - hl_decode_mb_simple_16(h); - } else - hl_decode_mb_simple_8(h); -} - int ff_pred_weight_table(H264Context *h) { int list, i; @@ -2747,72 +1042,6 @@ int ff_pred_weight_table(H264Context *h) return 0; } -/** - * Initialize implicit_weight table. - * @param field 0/1 initialize the weight for interlaced MBAFF - * -1 initializes the rest - */ -static void implicit_weight_table(H264Context *h, int field) -{ - int ref0, ref1, i, cur_poc, ref_start, ref_count0, ref_count1; - - for (i = 0; i < 2; i++) { - h->luma_weight_flag[i] = 0; - h->chroma_weight_flag[i] = 0; - } - - if (field < 0) { - if (h->picture_structure == PICT_FRAME) { - cur_poc = h->cur_pic_ptr->poc; - } else { - cur_poc = h->cur_pic_ptr->field_poc[h->picture_structure - 1]; - } - if (h->ref_count[0] == 1 && h->ref_count[1] == 1 && !FRAME_MBAFF(h) && - h->ref_list[0][0].poc + h->ref_list[1][0].poc == 2 * cur_poc) { - h->use_weight = 0; - h->use_weight_chroma = 0; - return; - } - ref_start = 0; - ref_count0 = h->ref_count[0]; - ref_count1 = h->ref_count[1]; - } else { - cur_poc = h->cur_pic_ptr->field_poc[field]; - ref_start = 16; - ref_count0 = 16 + 2 * h->ref_count[0]; - ref_count1 = 16 + 2 * h->ref_count[1]; - } - - h->use_weight = 2; - h->use_weight_chroma = 2; - h->luma_log2_weight_denom = 5; - h->chroma_log2_weight_denom = 5; - - for (ref0 = ref_start; ref0 < ref_count0; ref0++) { - int poc0 = h->ref_list[0][ref0].poc; - for (ref1 = ref_start; ref1 < ref_count1; ref1++) { - int w = 32; - if (!h->ref_list[0][ref0].long_ref && !h->ref_list[1][ref1].long_ref) { - int poc1 = h->ref_list[1][ref1].poc; - int td = av_clip(poc1 - poc0, -128, 127); - if (td) { - int tb = av_clip(cur_poc - poc0, -128, 127); - int tx = (16384 + (FFABS(td) >> 1)) / td; - int dist_scale_factor = (tb * tx + 32) >> 8; - if (dist_scale_factor >= -64 && dist_scale_factor <= 128) - w = 64 - dist_scale_factor; - } - } - if (field < 0) { - h->implicit_weight[ref0][ref1][0] = - h->implicit_weight[ref0][ref1][1] = w; - } else { - h->implicit_weight[ref0][ref1][field] = w; - } - } - } -} - /** * instantaneous decoder refresh. */ @@ -2829,7 +1058,7 @@ static void idr(H264Context *h) } /* forget old pics after a seek */ -static void flush_change(H264Context *h) +void ff_h264_flush_change(H264Context *h) { int i, j; @@ -2870,13 +1099,13 @@ static void flush_dpb(AVCodecContext *avctx) h->delayed_pic[i] = NULL; } - flush_change(h); + ff_h264_flush_change(h); if (h->DPB) - for (i = 0; i < MAX_PICTURE_COUNT; i++) - unref_picture(h, &h->DPB[i]); + for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) + ff_h264_unref_picture(h, &h->DPB[i]); h->cur_pic_ptr = NULL; - unref_picture(h, &h->cur_pic); + ff_h264_unref_picture(h, &h->cur_pic); h->mb_x = h->mb_y = 0; @@ -2887,7 +1116,7 @@ static void flush_dpb(AVCodecContext *avctx) h->parse_context.index = 0; h->parse_context.last_index = 0; - free_tables(h, 1); + ff_h264_free_tables(h, 1); h->context_initialized = 0; } @@ -2969,128 +1198,6 @@ int ff_init_poc(H264Context *h, int pic_field_poc[2], int *pic_poc) return 0; } -/** - * initialize scan tables - */ -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->field_scan[i] = TRANSPOSE(field_scan[i]); -#undef TRANSPOSE - } - for (i = 0; i < 64; i++) { -#define TRANSPOSE(x) (x >> 3) | ((x & 7) << 3) - h->zigzag_scan8x8[i] = TRANSPOSE(ff_zigzag_direct[i]); - h->zigzag_scan8x8_cavlc[i] = TRANSPOSE(zigzag_scan8x8_cavlc[i]); - h->field_scan8x8[i] = TRANSPOSE(field_scan8x8[i]); - h->field_scan8x8_cavlc[i] = TRANSPOSE(field_scan8x8_cavlc[i]); -#undef TRANSPOSE - } - if (h->sps.transform_bypass) { // FIXME same ugly - memcpy(h->zigzag_scan_q0 , zigzag_scan , sizeof(h->zigzag_scan_q0 )); - memcpy(h->zigzag_scan8x8_q0 , ff_zigzag_direct , sizeof(h->zigzag_scan8x8_q0 )); - memcpy(h->zigzag_scan8x8_cavlc_q0 , zigzag_scan8x8_cavlc , sizeof(h->zigzag_scan8x8_cavlc_q0)); - memcpy(h->field_scan_q0 , field_scan , sizeof(h->field_scan_q0 )); - memcpy(h->field_scan8x8_q0 , field_scan8x8 , sizeof(h->field_scan8x8_q0 )); - memcpy(h->field_scan8x8_cavlc_q0 , field_scan8x8_cavlc , sizeof(h->field_scan8x8_cavlc_q0 )); - } else { - memcpy(h->zigzag_scan_q0 , h->zigzag_scan , sizeof(h->zigzag_scan_q0 )); - memcpy(h->zigzag_scan8x8_q0 , h->zigzag_scan8x8 , sizeof(h->zigzag_scan8x8_q0 )); - memcpy(h->zigzag_scan8x8_cavlc_q0 , h->zigzag_scan8x8_cavlc , sizeof(h->zigzag_scan8x8_cavlc_q0)); - memcpy(h->field_scan_q0 , h->field_scan , sizeof(h->field_scan_q0 )); - memcpy(h->field_scan8x8_q0 , h->field_scan8x8 , sizeof(h->field_scan8x8_q0 )); - memcpy(h->field_scan8x8_cavlc_q0 , h->field_scan8x8_cavlc , sizeof(h->field_scan8x8_cavlc_q0 )); - } -} - -static int field_end(H264Context *h, int in_setup) -{ - AVCodecContext *const avctx = h->avctx; - int err = 0; - h->mb_y = 0; - - if (CONFIG_H264_VDPAU_DECODER && - h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) - ff_vdpau_h264_set_reference_frames(h); - - if (in_setup || !(avctx->active_thread_type & FF_THREAD_FRAME)) { - if (!h->droppable) { - err = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index); - h->prev_poc_msb = h->poc_msb; - h->prev_poc_lsb = h->poc_lsb; - } - h->prev_frame_num_offset = h->frame_num_offset; - h->prev_frame_num = h->frame_num; - h->outputed_poc = h->next_outputed_poc; - } - - if (avctx->hwaccel) { - if (avctx->hwaccel->end_frame(avctx) < 0) - av_log(avctx, AV_LOG_ERROR, - "hardware accelerator failed to decode picture\n"); - } - - if (CONFIG_H264_VDPAU_DECODER && - h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) - ff_vdpau_h264_picture_complete(h); - - /* - * FIXME: Error handling code does not seem to support interlaced - * when slices span multiple rows - * The ff_er_add_slice calls don't work right for bottom - * fields; they cause massive erroneous error concealing - * Error marking covers both fields (top and bottom). - * This causes a mismatched s->error_count - * and a bad error table. Further, the error count goes to - * INT_MAX when called for bottom field, because mb_y is - * past end by one (callers fault) and resync_mb_y != 0 - * causes problems for the first MB line, too. - */ - if (CONFIG_ERROR_RESILIENCE && !FIELD_PICTURE(h) && h->current_slice && !h->sps.new) { - h->er.cur_pic = h->cur_pic_ptr; - ff_er_frame_end(&h->er); - } - if (!in_setup && !h->droppable) - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, - h->picture_structure == PICT_BOTTOM_FIELD); - emms_c(); - - h->current_slice = 0; - - return err; -} - -/** - * Replicate H264 "master" context to thread contexts. - */ -static int clone_slice(H264Context *dst, H264Context *src) -{ - memcpy(dst->block_offset, src->block_offset, sizeof(dst->block_offset)); - dst->cur_pic_ptr = src->cur_pic_ptr; - dst->cur_pic = src->cur_pic; - dst->linesize = src->linesize; - dst->uvlinesize = src->uvlinesize; - dst->first_field = src->first_field; - - dst->prev_poc_msb = src->prev_poc_msb; - dst->prev_poc_lsb = src->prev_poc_lsb; - dst->prev_frame_num_offset = src->prev_frame_num_offset; - dst->prev_frame_num = src->prev_frame_num; - dst->short_ref_count = src->short_ref_count; - - memcpy(dst->short_ref, src->short_ref, sizeof(dst->short_ref)); - memcpy(dst->long_ref, src->long_ref, sizeof(dst->long_ref)); - memcpy(dst->default_ref_list, src->default_ref_list, sizeof(dst->default_ref_list)); - - memcpy(dst->dequant4_coeff, src->dequant4_coeff, sizeof(src->dequant4_coeff)); - memcpy(dst->dequant8_coeff, src->dequant8_coeff, sizeof(src->dequant8_coeff)); - - return 0; -} - /** * Compute profile from profile_idc and constraint_set?_flags. * @@ -3118,7 +1225,7 @@ int ff_h264_get_profile(SPS *sps) return profile; } -static int h264_set_parameter_from_sps(H264Context *h) +int ff_h264_set_parameter_from_sps(H264Context *h) { if (h->flags & CODEC_FLAG_LOW_DELAY || (h->sps.bitstream_restriction_flag && @@ -3167,230 +1274,6 @@ static int h264_set_parameter_from_sps(H264Context *h) return 0; } -static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) -{ - switch (h->sps.bit_depth_luma) { - case 9: - if (CHROMA444(h)) { - if (h->avctx->colorspace == AVCOL_SPC_RGB) { - return AV_PIX_FMT_GBRP9; - } else - return AV_PIX_FMT_YUV444P9; - } else if (CHROMA422(h)) - return AV_PIX_FMT_YUV422P9; - else - return AV_PIX_FMT_YUV420P9; - break; - case 10: - if (CHROMA444(h)) { - if (h->avctx->colorspace == AVCOL_SPC_RGB) { - return AV_PIX_FMT_GBRP10; - } else - return AV_PIX_FMT_YUV444P10; - } else if (CHROMA422(h)) - return AV_PIX_FMT_YUV422P10; - else - return AV_PIX_FMT_YUV420P10; - break; - case 12: - if (CHROMA444(h)) { - if (h->avctx->colorspace == AVCOL_SPC_RGB) { - return AV_PIX_FMT_GBRP12; - } else - return AV_PIX_FMT_YUV444P12; - } else if (CHROMA422(h)) - return AV_PIX_FMT_YUV422P12; - else - return AV_PIX_FMT_YUV420P12; - break; - case 14: - if (CHROMA444(h)) { - if (h->avctx->colorspace == AVCOL_SPC_RGB) { - return AV_PIX_FMT_GBRP14; - } else - return AV_PIX_FMT_YUV444P14; - } else if (CHROMA422(h)) - return AV_PIX_FMT_YUV422P14; - else - return AV_PIX_FMT_YUV420P14; - break; - case 8: - if (CHROMA444(h)) { - if (h->avctx->colorspace == AVCOL_SPC_RGB) { - av_log(h->avctx, AV_LOG_DEBUG, "Detected GBR colorspace.\n"); - return AV_PIX_FMT_GBR24P; - } else if (h->avctx->colorspace == AVCOL_SPC_YCGCO) { - av_log(h->avctx, AV_LOG_WARNING, "Detected unsupported YCgCo colorspace.\n"); - } - return h->avctx->color_range == AVCOL_RANGE_JPEG ? AV_PIX_FMT_YUVJ444P - : AV_PIX_FMT_YUV444P; - } else if (CHROMA422(h)) { - return h->avctx->color_range == AVCOL_RANGE_JPEG ? AV_PIX_FMT_YUVJ422P - : AV_PIX_FMT_YUV422P; - } else { - int i; - const enum AVPixelFormat * fmt = h->avctx->codec->pix_fmts ? - h->avctx->codec->pix_fmts : - h->avctx->color_range == AVCOL_RANGE_JPEG ? - h264_hwaccel_pixfmt_list_jpeg_420 : - h264_hwaccel_pixfmt_list_420; - - for (i=0; fmt[i] != AV_PIX_FMT_NONE; i++) - if (fmt[i] == h->avctx->pix_fmt && !force_callback) - return fmt[i]; - return ff_thread_get_format(h->avctx, fmt); - } - break; - default: - av_log(h->avctx, AV_LOG_ERROR, - "Unsupported bit depth %d\n", h->sps.bit_depth_luma); - return AVERROR_INVALIDDATA; - } -} - -/* 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); - av_assert0(h->sps.crop_right + h->sps.crop_left < (unsigned)h->width); - av_assert0(h->sps.crop_top + h->sps.crop_bottom < (unsigned)h->height); - - /* handle container cropping */ - if (!h->sps.crop && - FFALIGN(h->avctx->width, 16) == h->width && - FFALIGN(h->avctx->height, 16) == h->height) { - width = h->avctx->width; - height = h->avctx->height; - } - - if (width <= 0 || height <= 0) { - av_log(h->avctx, AV_LOG_ERROR, "Invalid cropped dimensions: %dx%d.\n", - width, height); - if (h->avctx->err_recognition & AV_EF_EXPLODE) - 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 = 0; - h->sps.crop = 0; - - width = h->width; - height = h->height; - } - - h->avctx->coded_width = h->width; - h->avctx->coded_height = h->height; - h->avctx->width = width; - h->avctx->height = height; - - return 0; -} - -static int h264_slice_header_init(H264Context *h, int reinit) -{ - int nb_slices = (HAVE_THREADS && - h->avctx->active_thread_type & FF_THREAD_SLICE) ? - h->avctx->thread_count : 1; - int i, ret; - - h->avctx->sample_aspect_ratio = h->sps.sar; - av_assert0(h->avctx->sample_aspect_ratio.den); - av_pix_fmt_get_chroma_sub_sample(h->avctx->pix_fmt, - &h->chroma_x_shift, &h->chroma_y_shift); - - if (h->sps.timing_info_present_flag) { - int64_t den = h->sps.time_scale; - if (h->x264_build < 44U) - den *= 2; - av_reduce(&h->avctx->time_base.num, &h->avctx->time_base.den, - h->sps.num_units_in_tick, den, 1 << 30); - } - - h->avctx->hwaccel = ff_find_hwaccel(h->avctx); - - if (reinit) - free_tables(h, 0); - h->first_field = 0; - h->prev_interlaced_frame = 1; - - init_scan_tables(h); - ret = ff_h264_alloc_tables(h); - if (ret < 0) { - av_log(h->avctx, AV_LOG_ERROR, "Could not allocate memory\n"); - return ret; - } - - if (nb_slices > MAX_THREADS || (nb_slices > h->mb_height && h->mb_height)) { - int max_slices; - if (h->mb_height) - max_slices = FFMIN(MAX_THREADS, h->mb_height); - else - max_slices = MAX_THREADS; - av_log(h->avctx, AV_LOG_WARNING, "too many threads/slices %d," - " reducing to %d\n", nb_slices, max_slices); - nb_slices = max_slices; - } - h->slice_context_count = nb_slices; - - if (!HAVE_THREADS || !(h->avctx->active_thread_type & FF_THREAD_SLICE)) { - ret = context_init(h); - 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; - if (CONFIG_ERROR_RESILIENCE) { - c->dsp = h->dsp; - } - c->vdsp = h->vdsp; - c->h264dsp = h->h264dsp; - c->h264qpel = h->h264qpel; - c->h264chroma = h->h264chroma; - c->sps = h->sps; - c->pps = h->pps; - c->pixel_shift = h->pixel_shift; - c->cur_chroma_format_idc = h->cur_chroma_format_idc; - c->width = h->width; - c->height = h->height; - c->linesize = h->linesize; - c->uvlinesize = h->uvlinesize; - c->chroma_x_shift = h->chroma_x_shift; - c->chroma_y_shift = h->chroma_y_shift; - c->qscale = h->qscale; - c->droppable = h->droppable; - c->data_partitioning = h->data_partitioning; - c->low_delay = h->low_delay; - c->mb_width = h->mb_width; - c->mb_height = h->mb_height; - c->mb_stride = h->mb_stride; - c->mb_num = h->mb_num; - c->flags = h->flags; - c->workaround_bugs = h->workaround_bugs; - c->pict_type = h->pict_type; - - init_scan_tables(c); - clone_tables(c, h, i); - c->context_initialized = 1; - } - - for (i = 0; i < h->slice_context_count; i++) - if ((ret = context_init(h->thread_context[i])) < 0) { - av_log(h->avctx, AV_LOG_ERROR, "context_init() failed.\n"); - return ret; - } - } - - h->context_initialized = 1; - - return 0; -} - int ff_set_ref_count(H264Context *h) { int ref_count[2], list_count; @@ -3445,1326 +1328,127 @@ int ff_set_ref_count(H264Context *h) return 0; } -static enum AVPixelFormat non_j_pixfmt(enum AVPixelFormat a) -{ - switch (a) { - case AV_PIX_FMT_YUVJ420P: return AV_PIX_FMT_YUV420P; - case AV_PIX_FMT_YUVJ422P: return AV_PIX_FMT_YUV422P; - case AV_PIX_FMT_YUVJ444P: return AV_PIX_FMT_YUV444P; - default: - return a; - } -} - -/** - * 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 - */ -static int decode_slice_header(H264Context *h, H264Context *h0) -{ - unsigned int first_mb_in_slice; - unsigned int pps_id; - int ret; - unsigned int slice_type, tmp, i, j; - int last_pic_structure, last_pic_droppable; - int must_reinit; - int needs_reinit = 0; - int field_pic_flag, bottom_field_flag; - - h->me.qpel_put = h->h264qpel.put_h264_qpel_pixels_tab; - h->me.qpel_avg = h->h264qpel.avg_h264_qpel_pixels_tab; - - first_mb_in_slice = get_ue_golomb_long(&h->gb); - - if (first_mb_in_slice == 0) { // FIXME better field boundary detection - if (h0->current_slice && h->cur_pic_ptr && FIELD_PICTURE(h)) { - field_end(h, 1); - } - - h0->current_slice = 0; - if (!h0->first_field) { - if (h->cur_pic_ptr && !h->droppable) { - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, - h->picture_structure == PICT_BOTTOM_FIELD); - } - h->cur_pic_ptr = NULL; - } - } - - slice_type = get_ue_golomb_31(&h->gb); - if (slice_type > 9) { - av_log(h->avctx, AV_LOG_ERROR, - "slice type %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]; - 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; - } - if (h0->au_pps_id >= 0 && pps_id != h0->au_pps_id) { - av_log(h->avctx, AV_LOG_ERROR, - "PPS change from %d to %d forbidden\n", - h0->au_pps_id, 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 || - h->pps.sps_id != h->current_sps_id || - h0->sps_buffers[h->pps.sps_id]->new) { - - h->sps = *h0->sps_buffers[h->pps.sps_id]; - - if (h->mb_width != h->sps.mb_width || - h->mb_height != h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) || - h->avctx->bits_per_raw_sample != h->sps.bit_depth_luma || - h->cur_chroma_format_idc != h->sps.chroma_format_idc - ) - needs_reinit = 1; - - if (h->bit_depth_luma != h->sps.bit_depth_luma || - h->chroma_format_idc != h->sps.chroma_format_idc) { - h->bit_depth_luma = h->sps.bit_depth_luma; - h->chroma_format_idc = h->sps.chroma_format_idc; - needs_reinit = 1; - } - if ((ret = h264_set_parameter_from_sps(h)) < 0) - return ret; - } - - h->avctx->profile = ff_h264_get_profile(&h->sps); - h->avctx->level = h->sps.level_idc; - h->avctx->refs = h->sps.ref_frame_count; - - must_reinit = (h->context_initialized && - ( 16*h->sps.mb_width != h->avctx->coded_width - || 16*h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) != h->avctx->coded_height - || h->avctx->bits_per_raw_sample != h->sps.bit_depth_luma - || h->cur_chroma_format_idc != h->sps.chroma_format_idc - || av_cmp_q(h->sps.sar, h->avctx->sample_aspect_ratio) - || h->mb_width != h->sps.mb_width - || h->mb_height != h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) - )); - if (non_j_pixfmt(h0->avctx->pix_fmt) != non_j_pixfmt(get_pixel_format(h0, 0))) - must_reinit = 1; - - h->mb_width = h->sps.mb_width; - h->mb_height = h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag); - h->mb_num = h->mb_width * h->mb_height; - h->mb_stride = h->mb_width + 1; - - h->b_stride = h->mb_width * 4; - - h->chroma_y_shift = h->sps.chroma_format_idc <= 1; // 400 uses yuv420p - - h->width = 16 * h->mb_width; - h->height = 16 * h->mb_height; - - ret = init_dimensions(h); - if (ret < 0) - return ret; - - if (h->sps.video_signal_type_present_flag) { - h->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG - : AVCOL_RANGE_MPEG; - if (h->sps.colour_description_present_flag) { - if (h->avctx->colorspace != h->sps.colorspace) - needs_reinit = 1; - h->avctx->color_primaries = h->sps.color_primaries; - h->avctx->color_trc = h->sps.color_trc; - h->avctx->colorspace = h->sps.colorspace; - } - } - - if (h->context_initialized && - (h->width != h->avctx->coded_width || - h->height != h->avctx->coded_height || - must_reinit || - needs_reinit)) { - if (h != h0) { - 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); - return AVERROR_INVALIDDATA; - } - - flush_change(h); - - if ((ret = get_pixel_format(h, 1)) < 0) - return ret; - h->avctx->pix_fmt = ret; - - av_log(h->avctx, AV_LOG_INFO, "Reinit context to %dx%d, " - "pix_fmt: %s\n", h->width, h->height, av_get_pix_fmt_name(h->avctx->pix_fmt)); - - if ((ret = h264_slice_header_init(h, 1)) < 0) { - av_log(h->avctx, AV_LOG_ERROR, - "h264_slice_header_init() failed\n"); - return ret; - } - } - if (!h->context_initialized) { - if (h != h0) { - av_log(h->avctx, AV_LOG_ERROR, - "Cannot (re-)initialize context during parallel decoding.\n"); - return AVERROR_PATCHWELCOME; - } - - if ((ret = get_pixel_format(h, 1)) < 0) - return ret; - h->avctx->pix_fmt = ret; - - if ((ret = h264_slice_header_init(h, 0)) < 0) { - av_log(h->avctx, AV_LOG_ERROR, - "h264_slice_header_init() failed\n"); - return ret; - } - } - - if (h == h0 && h->dequant_coeff_pps != pps_id) { - h->dequant_coeff_pps = pps_id; - init_dequant_tables(h); - } - - h->frame_num = get_bits(&h->gb, h->sps.log2_max_frame_num); - - h->mb_mbaff = 0; - h->mb_aff_frame = 0; - last_pic_structure = h0->picture_structure; - last_pic_droppable = h0->droppable; - h->droppable = h->nal_ref_idc == 0; - if (h->sps.frame_mbs_only_flag) { - h->picture_structure = PICT_FRAME; - } else { - if (!h->sps.direct_8x8_inference_flag && slice_type == AV_PICTURE_TYPE_B) { - av_log(h->avctx, AV_LOG_ERROR, "This stream was generated by a broken encoder, invalid 8x8 inference\n"); - return -1; - } - 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; - } else { - h->picture_structure = PICT_FRAME; - h->mb_aff_frame = h->sps.mb_aff; - } - } - h->mb_field_decoding_flag = h->picture_structure != PICT_FRAME; - - if (h0->current_slice != 0) { - if (last_pic_structure != h->picture_structure || - last_pic_droppable != h->droppable) { - av_log(h->avctx, AV_LOG_ERROR, - "Changing field mode (%d -> %d) between slices is not allowed\n", - last_pic_structure, h->picture_structure); - h->picture_structure = last_pic_structure; - h->droppable = last_pic_droppable; - return AVERROR_INVALIDDATA; - } else if (!h0->cur_pic_ptr) { - av_log(h->avctx, AV_LOG_ERROR, - "unset cur_pic_ptr on slice %d\n", - h0->current_slice + 1); - return AVERROR_INVALIDDATA; - } - } else { - /* Shorten frame num gaps so we don't have to allocate reference - * frames just to throw them away */ - if (h->frame_num != h->prev_frame_num) { - int unwrap_prev_frame_num = h->prev_frame_num; - int max_frame_num = 1 << h->sps.log2_max_frame_num; - - if (unwrap_prev_frame_num > h->frame_num) - unwrap_prev_frame_num -= max_frame_num; - - if ((h->frame_num - unwrap_prev_frame_num) > h->sps.ref_frame_count) { - unwrap_prev_frame_num = (h->frame_num - h->sps.ref_frame_count) - 1; - if (unwrap_prev_frame_num < 0) - unwrap_prev_frame_num += max_frame_num; - - h->prev_frame_num = unwrap_prev_frame_num; - } - } - - /* See if we have a decoded first field looking for a pair... - * Here, we're using that to see if we should mark previously - * decode frames as "finished". - * We have to do that before the "dummy" in-between frame allocation, - * since that can modify h->cur_pic_ptr. */ - if (h0->first_field) { - assert(h0->cur_pic_ptr); - assert(h0->cur_pic_ptr->f.buf[0]); - assert(h0->cur_pic_ptr->reference != DELAYED_PIC_REF); - - /* Mark old field/frame as completed */ - if (h0->cur_pic_ptr->tf.owner == h0->avctx) { - ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, - last_pic_structure == PICT_BOTTOM_FIELD); - } - - /* figure out if we have a complementary field pair */ - if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) { - /* Previous field is unmatched. Don't display it, but let it - * remain for reference if marked as such. */ - if (last_pic_structure != PICT_FRAME) { - ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, - last_pic_structure == PICT_TOP_FIELD); - } - } else { - if (h0->cur_pic_ptr->frame_num != h->frame_num) { - /* This and previous field were reference, but had - * different frame_nums. Consider this field first in - * pair. Throw away previous field except for reference - * purposes. */ - if (last_pic_structure != PICT_FRAME) { - ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, - last_pic_structure == PICT_TOP_FIELD); - } - } else { - /* Second field in complementary pair */ - if (!((last_pic_structure == PICT_TOP_FIELD && - h->picture_structure == PICT_BOTTOM_FIELD) || - (last_pic_structure == PICT_BOTTOM_FIELD && - h->picture_structure == PICT_TOP_FIELD))) { - av_log(h->avctx, AV_LOG_ERROR, - "Invalid field mode combination %d/%d\n", - last_pic_structure, h->picture_structure); - h->picture_structure = last_pic_structure; - h->droppable = last_pic_droppable; - return AVERROR_INVALIDDATA; - } else if (last_pic_droppable != h->droppable) { - avpriv_request_sample(h->avctx, - "Found reference and non-reference fields in the same frame, which"); - h->picture_structure = last_pic_structure; - h->droppable = last_pic_droppable; - return AVERROR_PATCHWELCOME; - } - } - } - } - - while (h->frame_num != h->prev_frame_num && !h0->first_field && - h->frame_num != (h->prev_frame_num + 1) % (1 << h->sps.log2_max_frame_num)) { - Picture *prev = h->short_ref_count ? h->short_ref[0] : NULL; - av_log(h->avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n", - h->frame_num, h->prev_frame_num); - if (!h->sps.gaps_in_frame_num_allowed_flag) - for(i=0; ilast_pocs); i++) - h->last_pocs[i] = INT_MIN; - ret = h264_frame_start(h); - if (ret < 0) { - h0->first_field = 0; - return ret; - } - - 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; - h->cur_pic_ptr->invalid_gap = !h->sps.gaps_in_frame_num_allowed_flag; - 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; - } - } - - /* 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); - } else { - if (h0->cur_pic_ptr->frame_num != h->frame_num) { - ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, - h0->picture_structure==PICT_BOTTOM_FIELD); - /* This and the previous field had different frame_nums. - * Consider this field first in pair. Throw away previous - * one except for reference purposes. */ - h0->first_field = 1; - h0->cur_pic_ptr = NULL; - } else { - /* Second field in complementary pair */ - h0->first_field = 0; - } - } - } else { - /* Frame or first field in a potentially complementary pair */ - h0->first_field = FIELD_PICTURE(h); - } - - if (!FIELD_PICTURE(h) || h0->first_field) { - if (h264_frame_start(h) < 0) { - h0->first_field = 0; - return AVERROR_INVALIDDATA; - } - } else { - release_unused_pictures(h, 0); - } - /* Some macroblocks can be accessed before they're available in case - * of lost slices, MBAFF or threading. */ - if (FIELD_PICTURE(h)) { - for(i = (h->picture_structure == PICT_BOTTOM_FIELD); imb_height; i++) - memset(h->slice_table + i*h->mb_stride, -1, (h->mb_stride - (i+1==h->mb_height)) * sizeof(*h->slice_table)); - } else { - memset(h->slice_table, -1, - (h->mb_height * h->mb_stride - 1) * sizeof(*h->slice_table)); - } - h0->last_slice_type = -1; - } - if (h != h0 && (ret = clone_slice(h, h0)) < 0) - return ret; - - /* can't be in alloc_tables because linesize isn't known there. - * FIXME: redo bipred weight to not require extra buffer? */ - for (i = 0; i < h->slice_context_count; i++) - if (h->thread_context[i]) { - ret = alloc_scratch_buffers(h->thread_context[i], h->linesize); - if (ret < 0) - return ret; - } - - h->cur_pic_ptr->frame_num = h->frame_num; // FIXME frame_num cleanup - - av_assert1(h->mb_num == h->mb_width * h->mb_height); - if (first_mb_in_slice << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num || - first_mb_in_slice >= h->mb_num) { - av_log(h->avctx, AV_LOG_ERROR, "first_mb_in_slice overflow\n"); - return AVERROR_INVALIDDATA; - } - h->resync_mb_x = h->mb_x = first_mb_in_slice % h->mb_width; - h->resync_mb_y = h->mb_y = (first_mb_in_slice / h->mb_width) << - FIELD_OR_MBAFF_PICTURE(h); - if (h->picture_structure == PICT_BOTTOM_FIELD) - h->resync_mb_y = h->mb_y = h->mb_y + 1; - av_assert1(h->mb_y < h->mb_height); - - if (h->picture_structure == PICT_FRAME) { - h->curr_pic_num = h->frame_num; - h->max_pic_num = 1 << h->sps.log2_max_frame_num; - } else { - h->curr_pic_num = 2 * h->frame_num + 1; - h->max_pic_num = 1 << (h->sps.log2_max_frame_num + 1); - } - - if (h->nal_unit_type == NAL_IDR_SLICE) - get_ue_golomb(&h->gb); /* idr_pic_id */ - - if (h->sps.poc_type == 0) { - h->poc_lsb = get_bits(&h->gb, h->sps.log2_max_poc_lsb); - - if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) - h->delta_poc_bottom = get_se_golomb(&h->gb); - } - - if (h->sps.poc_type == 1 && !h->sps.delta_pic_order_always_zero_flag) { - h->delta_poc[0] = get_se_golomb(&h->gb); - - if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) - h->delta_poc[1] = get_se_golomb(&h->gb); - } - - ff_init_poc(h, h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc); - - if (h->pps.redundant_pic_cnt_present) - h->redundant_pic_count = get_ue_golomb(&h->gb); - - ret = ff_set_ref_count(h); - if (ret < 0) - return ret; - - if (slice_type != AV_PICTURE_TYPE_I && - (h0->current_slice == 0 || - slice_type != h0->last_slice_type || - memcmp(h0->last_ref_count, h0->ref_count, sizeof(h0->ref_count)))) { - - ff_h264_fill_default_ref_list(h); - } - - 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; - } - } - - 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); - } else { - h->use_weight = 0; - for (i = 0; i < 2; i++) { - h->luma_weight_flag[i] = 0; - h->chroma_weight_flag[i] = 0; - } - } - - // If frame-mt is enabled, only update mmco tables for the first slice - // in a field. Subsequent slices can temporarily clobber h->mmco_index - // or h->mmco, which will cause ref list mix-ups and decoding errors - // further down the line. This may break decoding if the first slice is - // corrupt, thus we only do this if frame-mt is enabled. - if (h->nal_ref_idc) { - 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 (FRAME_MBAFF(h)) { - ff_h264_fill_mbaff_ref_list(h); - - if (h->pps.weighted_bipred_idc == 2 && h->slice_type_nos == AV_PICTURE_TYPE_B) { - implicit_weight_table(h, 0); - implicit_weight_table(h, 1); - } - } - - if (h->slice_type_nos == AV_PICTURE_TYPE_B && !h->direct_spatial_mv_pred) - ff_h264_direct_dist_scale_factor(h); - ff_h264_direct_ref_list_init(h); - - if (h->slice_type_nos != AV_PICTURE_TYPE_I && h->pps.cabac) { - tmp = get_ue_golomb_31(&h->gb); - if (tmp > 2) { - av_log(h->avctx, AV_LOG_ERROR, "cabac_init_idc %u overflow\n", tmp); - return AVERROR_INVALIDDATA; - } - h->cabac_init_idc = tmp; - } - - h->last_qscale_diff = 0; - tmp = h->pps.init_qp + get_se_golomb(&h->gb); - if (tmp > 51 + 6 * (h->sps.bit_depth_luma - 8)) { - av_log(h->avctx, AV_LOG_ERROR, "QP %u out of range\n", tmp); - return 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); - // 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 (tmp > 2) { - av_log(h->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, - "deblocking filter parameters %d %d out of range\n", - h->slice_alpha_c0_offset, h->slice_beta_offset); - return AVERROR_INVALIDDATA; - } - } - } - - if (h->avctx->skip_loop_filter >= AVDISCARD_ALL || - (h->avctx->skip_loop_filter >= AVDISCARD_NONKEY && - h->slice_type_nos != AV_PICTURE_TYPE_I) || - (h->avctx->skip_loop_filter >= AVDISCARD_BIDIR && - h->slice_type_nos == AV_PICTURE_TYPE_B) || - (h->avctx->skip_loop_filter >= AVDISCARD_NONREF && - h->nal_ref_idc == 0)) - h->deblocking_filter = 0; - - if (h->deblocking_filter == 1 && h0->max_contexts > 1) { - if (h->avctx->flags2 & CODEC_FLAG2_FAST) { - /* Cheat slightly for speed: - * Do not bother to deblock across slices. */ - h->deblocking_filter = 2; - } else { - h0->max_contexts = 1; - if (!h0->single_decode_warning) { - av_log(h->avctx, AV_LOG_INFO, - "Cannot parallelize deblocking type 1, decoding such frames in sequential order\n"); - h0->single_decode_warning = 1; - } - if (h != h0) { - av_log(h->avctx, AV_LOG_ERROR, - "Deblocking switched inside frame.\n"); - return 1; - } - } - } - h->qp_thresh = 15 - - FFMIN(h->slice_alpha_c0_offset, h->slice_beta_offset) - - FFMAX3(0, - h->pps.chroma_qp_index_offset[0], - h->pps.chroma_qp_index_offset[1]) + - 6 * (h->sps.bit_depth_luma - 8); - - h0->last_slice_type = slice_type; - memcpy(h0->last_ref_count, h0->ref_count, sizeof(h0->last_ref_count)); - h->slice_num = ++h0->current_slice; - - if (h->slice_num) - h0->slice_row[(h->slice_num-1)&(MAX_SLICES-1)]= h->resync_mb_y; - if ( h0->slice_row[h->slice_num&(MAX_SLICES-1)] + 3 >= h->resync_mb_y - && h0->slice_row[h->slice_num&(MAX_SLICES-1)] <= h->resync_mb_y - && h->slice_num >= MAX_SLICES) { - //in case of ASO this check needs to be updated depending on how we decide to assign slice numbers in this case - av_log(h->avctx, AV_LOG_WARNING, "Possibly too many slices (%d >= %d), increase MAX_SLICES and recompile if there are artifacts\n", h->slice_num, MAX_SLICES); - } - - for (j = 0; j < 2; j++) { - int id_list[16]; - int *ref2frm = h->ref2frm[h->slice_num & (MAX_SLICES - 1)][j]; - for (i = 0; i < 16; i++) { - id_list[i] = 60; - if (j < h->list_count && i < h->ref_count[j] && - h->ref_list[j][i].f.buf[0]) { - int k; - AVBuffer *buf = h->ref_list[j][i].f.buf[0]->buffer; - for (k = 0; k < h->short_ref_count; k++) - if (h->short_ref[k]->f.buf[0]->buffer == buf) { - id_list[i] = k; - break; - } - for (k = 0; k < h->long_ref_count; k++) - if (h->long_ref[k] && h->long_ref[k]->f.buf[0]->buffer == buf) { - id_list[i] = h->short_ref_count + k; - break; - } - } - } - - ref2frm[0] = - ref2frm[1] = -1; - for (i = 0; i < 16; i++) - ref2frm[i + 2] = 4 * id_list[i] + (h->ref_list[j][i].reference & 3); - ref2frm[18 + 0] = - ref2frm[18 + 1] = -1; - for (i = 16; i < 48; i++) - ref2frm[i + 4] = 4 * id_list[(i - 16) >> 1] + - (h->ref_list[j][i].reference & 3); - } - - if (h->ref_count[0]) h->er.last_pic = &h->ref_list[0][0]; - if (h->ref_count[1]) h->er.next_pic = &h->ref_list[1][0]; - h->er.ref_count = h->ref_count[0]; - h0->au_pps_id = pps_id; - h->sps.new = - h0->sps_buffers[h->pps.sps_id]->new = 0; - h->current_sps_id = h->pps.sps_id; - - if (h->avctx->debug & FF_DEBUG_PICT_INFO) { - av_log(h->avctx, AV_LOG_DEBUG, - "slice:%d %s mb:%d %c%s%s pps:%u frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n", - h->slice_num, - (h->picture_structure == PICT_FRAME ? "F" : h->picture_structure == PICT_TOP_FIELD ? "T" : "B"), - first_mb_in_slice, - av_get_picture_type_char(h->slice_type), - h->slice_type_fixed ? " fix" : "", - h->nal_unit_type == NAL_IDR_SLICE ? " IDR" : "", - pps_id, h->frame_num, - h->cur_pic_ptr->field_poc[0], - h->cur_pic_ptr->field_poc[1], - h->ref_count[0], h->ref_count[1], - h->qscale, - h->deblocking_filter, - h->slice_alpha_c0_offset, 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") : ""); - } - - return 0; -} - -int ff_h264_get_slice_type(const H264Context *h) -{ - switch (h->slice_type) { - case AV_PICTURE_TYPE_P: - return 0; - case AV_PICTURE_TYPE_B: - return 1; - case AV_PICTURE_TYPE_I: - return 2; - case AV_PICTURE_TYPE_SP: - return 3; - case AV_PICTURE_TYPE_SI: - return 4; - default: - return AVERROR_INVALIDDATA; - } -} - -static av_always_inline void fill_filter_caches_inter(H264Context *h, - int mb_type, int top_xy, - int left_xy[LEFT_MBS], - int top_type, - int left_type[LEFT_MBS], - int mb_xy, int list) -{ - int b_stride = h->b_stride; - int16_t(*mv_dst)[2] = &h->mv_cache[list][scan8[0]]; - int8_t *ref_cache = &h->ref_cache[list][scan8[0]]; - if (IS_INTER(mb_type) || IS_DIRECT(mb_type)) { - if (USES_LIST(top_type, list)) { - const int b_xy = h->mb2b_xy[top_xy] + 3 * b_stride; - const int b8_xy = 4 * top_xy + 2; - int (*ref2frm)[64] = (void*)(h->ref2frm[h->slice_table[top_xy] & (MAX_SLICES - 1)][0] + (MB_MBAFF(h) ? 20 : 2)); - AV_COPY128(mv_dst - 1 * 8, h->cur_pic.motion_val[list][b_xy + 0]); - ref_cache[0 - 1 * 8] = - ref_cache[1 - 1 * 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 0]]; - ref_cache[2 - 1 * 8] = - ref_cache[3 - 1 * 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 1]]; - } else { - AV_ZERO128(mv_dst - 1 * 8); - AV_WN32A(&ref_cache[0 - 1 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); - } - - if (!IS_INTERLACED(mb_type ^ left_type[LTOP])) { - if (USES_LIST(left_type[LTOP], list)) { - const int b_xy = h->mb2b_xy[left_xy[LTOP]] + 3; - const int b8_xy = 4 * left_xy[LTOP] + 1; - int (*ref2frm)[64] =(void*)( h->ref2frm[h->slice_table[left_xy[LTOP]] & (MAX_SLICES - 1)][0] + (MB_MBAFF(h) ? 20 : 2)); - AV_COPY32(mv_dst - 1 + 0, h->cur_pic.motion_val[list][b_xy + b_stride * 0]); - AV_COPY32(mv_dst - 1 + 8, h->cur_pic.motion_val[list][b_xy + b_stride * 1]); - AV_COPY32(mv_dst - 1 + 16, h->cur_pic.motion_val[list][b_xy + b_stride * 2]); - AV_COPY32(mv_dst - 1 + 24, h->cur_pic.motion_val[list][b_xy + b_stride * 3]); - ref_cache[-1 + 0] = - ref_cache[-1 + 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 2 * 0]]; - ref_cache[-1 + 16] = - ref_cache[-1 + 24] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 2 * 1]]; - } else { - AV_ZERO32(mv_dst - 1 + 0); - AV_ZERO32(mv_dst - 1 + 8); - AV_ZERO32(mv_dst - 1 + 16); - AV_ZERO32(mv_dst - 1 + 24); - ref_cache[-1 + 0] = - ref_cache[-1 + 8] = - ref_cache[-1 + 16] = - ref_cache[-1 + 24] = LIST_NOT_USED; - } - } - } - - if (!USES_LIST(mb_type, list)) { - fill_rectangle(mv_dst, 4, 4, 8, pack16to32(0, 0), 4); - AV_WN32A(&ref_cache[0 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); - AV_WN32A(&ref_cache[1 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); - AV_WN32A(&ref_cache[2 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); - AV_WN32A(&ref_cache[3 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); - return; - } - - { - int8_t *ref = &h->cur_pic.ref_index[list][4 * mb_xy]; - int (*ref2frm)[64] = (void*)(h->ref2frm[h->slice_num & (MAX_SLICES - 1)][0] + (MB_MBAFF(h) ? 20 : 2)); - uint32_t ref01 = (pack16to32(ref2frm[list][ref[0]], ref2frm[list][ref[1]]) & 0x00FF00FF) * 0x0101; - uint32_t ref23 = (pack16to32(ref2frm[list][ref[2]], ref2frm[list][ref[3]]) & 0x00FF00FF) * 0x0101; - AV_WN32A(&ref_cache[0 * 8], ref01); - AV_WN32A(&ref_cache[1 * 8], ref01); - AV_WN32A(&ref_cache[2 * 8], ref23); - AV_WN32A(&ref_cache[3 * 8], ref23); - } - - { - int16_t(*mv_src)[2] = &h->cur_pic.motion_val[list][4 * h->mb_x + 4 * h->mb_y * b_stride]; - AV_COPY128(mv_dst + 8 * 0, mv_src + 0 * b_stride); - AV_COPY128(mv_dst + 8 * 1, mv_src + 1 * b_stride); - AV_COPY128(mv_dst + 8 * 2, mv_src + 2 * b_stride); - AV_COPY128(mv_dst + 8 * 3, mv_src + 3 * b_stride); - } -} - -/** - * - * @return non zero if the loop filter can be skipped - */ -static int fill_filter_caches(H264Context *h, int mb_type) -{ - const int mb_xy = h->mb_xy; - int top_xy, left_xy[LEFT_MBS]; - int top_type, left_type[LEFT_MBS]; - uint8_t *nnz; - uint8_t *nnz_cache; - - top_xy = mb_xy - (h->mb_stride << MB_FIELD(h)); - - /* Wow, what a mess, why didn't they simplify the interlacing & intra - * stuff, I can't imagine that these complex rules are worth it. */ - - left_xy[LBOT] = left_xy[LTOP] = mb_xy - 1; - if (FRAME_MBAFF(h)) { - const int left_mb_field_flag = IS_INTERLACED(h->cur_pic.mb_type[mb_xy - 1]); - const int curr_mb_field_flag = IS_INTERLACED(mb_type); - if (h->mb_y & 1) { - if (left_mb_field_flag != curr_mb_field_flag) - left_xy[LTOP] -= h->mb_stride; - } else { - if (curr_mb_field_flag) - top_xy += h->mb_stride & - (((h->cur_pic.mb_type[top_xy] >> 7) & 1) - 1); - if (left_mb_field_flag != curr_mb_field_flag) - left_xy[LBOT] += h->mb_stride; - } - } - - h->top_mb_xy = top_xy; - h->left_mb_xy[LTOP] = left_xy[LTOP]; - h->left_mb_xy[LBOT] = left_xy[LBOT]; - { - /* For sufficiently low qp, filtering wouldn't do anything. - * This is a conservative estimate: could also check beta_offset - * and more accurate chroma_qp. */ - int qp_thresh = h->qp_thresh; // FIXME strictly we should store qp_thresh for each mb of a slice - int qp = h->cur_pic.qscale_table[mb_xy]; - if (qp <= qp_thresh && - (left_xy[LTOP] < 0 || - ((qp + h->cur_pic.qscale_table[left_xy[LTOP]] + 1) >> 1) <= qp_thresh) && - (top_xy < 0 || - ((qp + h->cur_pic.qscale_table[top_xy] + 1) >> 1) <= qp_thresh)) { - if (!FRAME_MBAFF(h)) - return 1; - if ((left_xy[LTOP] < 0 || - ((qp + h->cur_pic.qscale_table[left_xy[LBOT]] + 1) >> 1) <= qp_thresh) && - (top_xy < h->mb_stride || - ((qp + h->cur_pic.qscale_table[top_xy - h->mb_stride] + 1) >> 1) <= qp_thresh)) - return 1; - } - } - - top_type = h->cur_pic.mb_type[top_xy]; - left_type[LTOP] = h->cur_pic.mb_type[left_xy[LTOP]]; - left_type[LBOT] = h->cur_pic.mb_type[left_xy[LBOT]]; - if (h->deblocking_filter == 2) { - if (h->slice_table[top_xy] != h->slice_num) - top_type = 0; - if (h->slice_table[left_xy[LBOT]] != h->slice_num) - left_type[LTOP] = left_type[LBOT] = 0; - } else { - if (h->slice_table[top_xy] == 0xFFFF) - top_type = 0; - if (h->slice_table[left_xy[LBOT]] == 0xFFFF) - left_type[LTOP] = left_type[LBOT] = 0; - } - h->top_type = top_type; - h->left_type[LTOP] = left_type[LTOP]; - h->left_type[LBOT] = left_type[LBOT]; - - if (IS_INTRA(mb_type)) - return 0; - - fill_filter_caches_inter(h, mb_type, top_xy, left_xy, - top_type, left_type, mb_xy, 0); - if (h->list_count == 2) - fill_filter_caches_inter(h, mb_type, top_xy, left_xy, - top_type, left_type, mb_xy, 1); - - nnz = h->non_zero_count[mb_xy]; - nnz_cache = h->non_zero_count_cache; - AV_COPY32(&nnz_cache[4 + 8 * 1], &nnz[0]); - AV_COPY32(&nnz_cache[4 + 8 * 2], &nnz[4]); - AV_COPY32(&nnz_cache[4 + 8 * 3], &nnz[8]); - AV_COPY32(&nnz_cache[4 + 8 * 4], &nnz[12]); - h->cbp = h->cbp_table[mb_xy]; - - if (top_type) { - nnz = h->non_zero_count[top_xy]; - AV_COPY32(&nnz_cache[4 + 8 * 0], &nnz[3 * 4]); - } - - if (left_type[LTOP]) { - nnz = h->non_zero_count[left_xy[LTOP]]; - nnz_cache[3 + 8 * 1] = nnz[3 + 0 * 4]; - nnz_cache[3 + 8 * 2] = nnz[3 + 1 * 4]; - nnz_cache[3 + 8 * 3] = nnz[3 + 2 * 4]; - nnz_cache[3 + 8 * 4] = nnz[3 + 3 * 4]; - } - - /* CAVLC 8x8dct requires NNZ values for residual decoding that differ - * from what the loop filter needs */ - if (!CABAC(h) && h->pps.transform_8x8_mode) { - if (IS_8x8DCT(top_type)) { - nnz_cache[4 + 8 * 0] = - nnz_cache[5 + 8 * 0] = (h->cbp_table[top_xy] & 0x4000) >> 12; - nnz_cache[6 + 8 * 0] = - nnz_cache[7 + 8 * 0] = (h->cbp_table[top_xy] & 0x8000) >> 12; - } - if (IS_8x8DCT(left_type[LTOP])) { - nnz_cache[3 + 8 * 1] = - nnz_cache[3 + 8 * 2] = (h->cbp_table[left_xy[LTOP]] & 0x2000) >> 12; // FIXME check MBAFF - } - if (IS_8x8DCT(left_type[LBOT])) { - nnz_cache[3 + 8 * 3] = - nnz_cache[3 + 8 * 4] = (h->cbp_table[left_xy[LBOT]] & 0x8000) >> 12; // FIXME check MBAFF - } - - if (IS_8x8DCT(mb_type)) { - nnz_cache[scan8[0]] = - nnz_cache[scan8[1]] = - nnz_cache[scan8[2]] = - nnz_cache[scan8[3]] = (h->cbp & 0x1000) >> 12; - - nnz_cache[scan8[0 + 4]] = - nnz_cache[scan8[1 + 4]] = - nnz_cache[scan8[2 + 4]] = - nnz_cache[scan8[3 + 4]] = (h->cbp & 0x2000) >> 12; - - nnz_cache[scan8[0 + 8]] = - nnz_cache[scan8[1 + 8]] = - nnz_cache[scan8[2 + 8]] = - nnz_cache[scan8[3 + 8]] = (h->cbp & 0x4000) >> 12; - - nnz_cache[scan8[0 + 12]] = - nnz_cache[scan8[1 + 12]] = - nnz_cache[scan8[2 + 12]] = - nnz_cache[scan8[3 + 12]] = (h->cbp & 0x8000) >> 12; - } - } - - return 0; -} - -static void loop_filter(H264Context *h, int start_x, int end_x) -{ - uint8_t *dest_y, *dest_cb, *dest_cr; - int linesize, uvlinesize, mb_x, mb_y; - const int end_mb_y = h->mb_y + FRAME_MBAFF(h); - const int old_slice_type = h->slice_type; - const int pixel_shift = h->pixel_shift; - const int block_h = 16 >> h->chroma_y_shift; - - if (h->deblocking_filter) { - for (mb_x = start_x; mb_x < end_x; mb_x++) - for (mb_y = end_mb_y - FRAME_MBAFF(h); mb_y <= end_mb_y; mb_y++) { - int mb_xy, mb_type; - mb_xy = h->mb_xy = mb_x + mb_y * h->mb_stride; - h->slice_num = h->slice_table[mb_xy]; - mb_type = h->cur_pic.mb_type[mb_xy]; - h->list_count = h->list_counts[mb_xy]; - - if (FRAME_MBAFF(h)) - h->mb_mbaff = - h->mb_field_decoding_flag = !!IS_INTERLACED(mb_type); - - h->mb_x = mb_x; - h->mb_y = mb_y; - dest_y = h->cur_pic.f.data[0] + - ((mb_x << pixel_shift) + mb_y * h->linesize) * 16; - dest_cb = h->cur_pic.f.data[1] + - (mb_x << pixel_shift) * (8 << CHROMA444(h)) + - mb_y * h->uvlinesize * block_h; - dest_cr = h->cur_pic.f.data[2] + - (mb_x << pixel_shift) * (8 << CHROMA444(h)) + - mb_y * h->uvlinesize * block_h; - // FIXME simplify above - - if (MB_FIELD(h)) { - linesize = h->mb_linesize = h->linesize * 2; - uvlinesize = h->mb_uvlinesize = h->uvlinesize * 2; - if (mb_y & 1) { // FIXME move out of this function? - dest_y -= h->linesize * 15; - dest_cb -= h->uvlinesize * (block_h - 1); - dest_cr -= h->uvlinesize * (block_h - 1); - } - } else { - linesize = h->mb_linesize = h->linesize; - uvlinesize = h->mb_uvlinesize = h->uvlinesize; - } - backup_mb_border(h, dest_y, dest_cb, dest_cr, linesize, - uvlinesize, 0); - if (fill_filter_caches(h, mb_type)) - continue; - h->chroma_qp[0] = get_chroma_qp(h, 0, h->cur_pic.qscale_table[mb_xy]); - h->chroma_qp[1] = get_chroma_qp(h, 1, h->cur_pic.qscale_table[mb_xy]); - - if (FRAME_MBAFF(h)) { - ff_h264_filter_mb(h, mb_x, mb_y, dest_y, dest_cb, dest_cr, - linesize, uvlinesize); - } else { - ff_h264_filter_mb_fast(h, mb_x, mb_y, dest_y, dest_cb, - dest_cr, linesize, uvlinesize); - } - } - } - h->slice_type = old_slice_type; - h->mb_x = end_x; - h->mb_y = end_mb_y - FRAME_MBAFF(h); - h->chroma_qp[0] = get_chroma_qp(h, 0, h->qscale); - h->chroma_qp[1] = get_chroma_qp(h, 1, h->qscale); -} - -static void predict_field_decoding_flag(H264Context *h) -{ - const int mb_xy = h->mb_x + h->mb_y * h->mb_stride; - int mb_type = (h->slice_table[mb_xy - 1] == h->slice_num) ? - h->cur_pic.mb_type[mb_xy - 1] : - (h->slice_table[mb_xy - h->mb_stride] == h->slice_num) ? - h->cur_pic.mb_type[mb_xy - h->mb_stride] : 0; - h->mb_mbaff = h->mb_field_decoding_flag = IS_INTERLACED(mb_type) ? 1 : 0; -} - -/** - * Draw edges and report progress for the last MB row. - */ -static void decode_finish_row(H264Context *h) -{ - int top = 16 * (h->mb_y >> FIELD_PICTURE(h)); - int pic_height = 16 * h->mb_height >> FIELD_PICTURE(h); - int height = 16 << FRAME_MBAFF(h); - int deblock_border = (16 + 4) << FRAME_MBAFF(h); - - if (h->deblocking_filter) { - if ((top + height) >= pic_height) - height += deblock_border; - top -= deblock_border; - } - - if (top >= pic_height || (top + height) < 0) - return; - - height = FFMIN(height, pic_height - top); - if (top < 0) { - height = top + height; - top = 0; - } - - ff_h264_draw_horiz_band(h, top, height); - - if (h->droppable || h->er.error_occurred) - return; - - ff_thread_report_progress(&h->cur_pic_ptr->tf, top + height - 1, - h->picture_structure == PICT_BOTTOM_FIELD); -} - -static void er_add_slice(H264Context *h, int startx, int starty, - int endx, int endy, int status) -{ - if (CONFIG_ERROR_RESILIENCE) { - ERContext *er = &h->er; - - ff_er_add_slice(er, startx, starty, endx, endy, status); - } -} - -static int decode_slice(struct AVCodecContext *avctx, void *arg) -{ - H264Context *h = *(void **)arg; - int lf_x_start = h->mb_x; - - h->mb_skip_run = -1; - - av_assert0(h->block_offset[15] == (4 * ((scan8[15] - scan8[0]) & 7) << h->pixel_shift) + 4 * h->linesize * ((scan8[15] - scan8[0]) >> 3)); - - h->is_complex = FRAME_MBAFF(h) || h->picture_structure != PICT_FRAME || - avctx->codec_id != AV_CODEC_ID_H264 || - (CONFIG_GRAY && (h->flags & CODEC_FLAG_GRAY)); - - if (!(h->avctx->active_thread_type & FF_THREAD_SLICE) && h->picture_structure == PICT_FRAME && h->er.error_status_table) { - const int start_i = av_clip(h->resync_mb_x + h->resync_mb_y * h->mb_width, 0, h->mb_num - 1); - if (start_i) { - int prev_status = h->er.error_status_table[h->er.mb_index2xy[start_i - 1]]; - prev_status &= ~ VP_START; - if (prev_status != (ER_MV_END | ER_DC_END | ER_AC_END)) - h->er.error_occurred = 1; - } - } - - if (h->pps.cabac) { - /* realign */ - align_get_bits(&h->gb); - - /* init cabac */ - ff_init_cabac_decoder(&h->cabac, - h->gb.buffer + get_bits_count(&h->gb) / 8, - (get_bits_left(&h->gb) + 7) / 8); - - ff_h264_init_cabac_states(h); - - for (;;) { - // START_TIMER - int ret = ff_h264_decode_mb_cabac(h); - int eos; - // STOP_TIMER("decode_mb_cabac") - - if (ret >= 0) - ff_h264_hl_decode_mb(h); - - // FIXME optimal? or let mb_decode decode 16x32 ? - if (ret >= 0 && FRAME_MBAFF(h)) { - h->mb_y++; - - ret = ff_h264_decode_mb_cabac(h); - - if (ret >= 0) - ff_h264_hl_decode_mb(h); - h->mb_y--; - } - eos = get_cabac_terminate(&h->cabac); - - if ((h->workaround_bugs & FF_BUG_TRUNCATED) && - h->cabac.bytestream > h->cabac.bytestream_end + 2) { - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x - 1, - h->mb_y, ER_MB_END); - if (h->mb_x >= lf_x_start) - loop_filter(h, lf_x_start, h->mb_x + 1); - return 0; - } - if (h->cabac.bytestream > h->cabac.bytestream_end + 2 ) - av_log(h->avctx, AV_LOG_DEBUG, "bytestream overread %td\n", h->cabac.bytestream_end - h->cabac.bytestream); - if (ret < 0 || h->cabac.bytestream > h->cabac.bytestream_end + 4) { - av_log(h->avctx, AV_LOG_ERROR, - "error while decoding MB %d %d, bytestream %td\n", - h->mb_x, h->mb_y, - h->cabac.bytestream_end - h->cabac.bytestream); - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x, - h->mb_y, ER_MB_ERROR); - return 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 (FIELD_OR_MBAFF_PICTURE(h)) { - ++h->mb_y; - if (FRAME_MBAFF(h) && h->mb_y < h->mb_height) - predict_field_decoding_flag(h); - } - } - - if (eos || h->mb_y >= h->mb_height) { - tprintf(h->avctx, "slice end %d %d\n", - get_bits_count(&h->gb), h->gb.size_in_bits); - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x - 1, - h->mb_y, ER_MB_END); - if (h->mb_x > lf_x_start) - loop_filter(h, lf_x_start, h->mb_x); - return 0; - } - } - } else { - for (;;) { - int ret = ff_h264_decode_mb_cavlc(h); - - if (ret >= 0) - ff_h264_hl_decode_mb(h); - - // FIXME optimal? or let mb_decode decode 16x32 ? - if (ret >= 0 && FRAME_MBAFF(h)) { - h->mb_y++; - ret = ff_h264_decode_mb_cavlc(h); - - if (ret >= 0) - ff_h264_hl_decode_mb(h); - h->mb_y--; - } - - if (ret < 0) { - av_log(h->avctx, AV_LOG_ERROR, - "error while decoding MB %d %d\n", h->mb_x, h->mb_y); - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x, - h->mb_y, ER_MB_ERROR); - return 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 (FIELD_OR_MBAFF_PICTURE(h)) { - ++h->mb_y; - if (FRAME_MBAFF(h) && h->mb_y < h->mb_height) - predict_field_decoding_flag(h); - } - if (h->mb_y >= h->mb_height) { - tprintf(h->avctx, "slice end %d %d\n", - get_bits_count(&h->gb), h->gb.size_in_bits); - - if ( get_bits_left(&h->gb) == 0 - || get_bits_left(&h->gb) > 0 && !(h->avctx->err_recognition & AV_EF_AGGRESSIVE)) { - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, - h->mb_x - 1, h->mb_y, - ER_MB_END); - - return 0; - } else { - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, - h->mb_x, h->mb_y, - ER_MB_END); - - return 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(&h->gb) == 0) { - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, - h->mb_x - 1, h->mb_y, - ER_MB_END); - if (h->mb_x > lf_x_start) - loop_filter(h, lf_x_start, h->mb_x); - - return 0; - } else { - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x, - h->mb_y, ER_MB_ERROR); - - return AVERROR_INVALIDDATA; - } - } - } - } -} - -/** - * Call decode_slice() for each context. - * - * @param h h264 master context - * @param context_count number of contexts to execute - */ -static int execute_decode_slices(H264Context *h, unsigned context_count) -{ - AVCodecContext *const avctx = h->avctx; - H264Context *hx; - int i; - - av_assert0(h->mb_y < h->mb_height); - - if (h->avctx->hwaccel || - h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) - return 0; - if (context_count == 1) { - return decode_slice(avctx, &h); - } else { - av_assert0(context_count > 0); - for (i = 1; i < context_count; i++) { - hx = h->thread_context[i]; - if (CONFIG_ERROR_RESILIENCE) { - hx->er.error_count = 0; - } - hx->x264_build = h->x264_build; - } - - avctx->execute(avctx, decode_slice, h->thread_context, - NULL, context_count, sizeof(void *)); - - /* pull back stuff from slices to master context */ - hx = h->thread_context[context_count - 1]; - h->mb_x = hx->mb_x; - h->mb_y = hx->mb_y; - h->droppable = hx->droppable; - h->picture_structure = hx->picture_structure; - if (CONFIG_ERROR_RESILIENCE) { - for (i = 1; i < context_count; i++) - h->er.error_count += h->thread_context[i]->er.error_count; - } - } - - return 0; -} - static const uint8_t start_code[] = { 0x00, 0x00, 0x01 }; +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; + + buf_index += 3; + + if (buf_index >= buf_size) + return buf_size; + + return buf_index; +} + +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; + int first_slice = 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; + if (buf_index >= next_avc) + continue; + } + + ptr = ff_h264_decode_nal(h, buf + buf_index, &dst_length, &consumed, + next_avc - buf_index); + + if (ptr == NULL || 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) || + !first_slice || + first_slice != h->nal_unit_type) + nals_needed = nal_index; + if (!first_slice) + first_slice = h->nal_unit_type; + } + } + + return nals_needed; +} + static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, int parse_extradata) { @@ -4773,11 +1457,9 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, int buf_index; unsigned context_count; int next_avc; - int pass = !(avctx->active_thread_type & FF_THREAD_FRAME); int nals_needed = 0; ///< number of NALs that need decoding before the next frame thread starts int nal_index; int idr_cleared=0; - int first_slice = 0; int ret = 0; h->nal_unit_type= 0; @@ -4799,7 +1481,10 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, h->is_avc = 1; } - for (; pass <= 1; pass++) { + 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; @@ -4809,36 +1494,18 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, int dst_length; int bit_length; const uint8_t *ptr; - int i, nalsize = 0; + int nalsize = 0; int err; if (buf_index >= next_avc) { - if (buf_index >= buf_size - h->nal_length_size) + nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index); + if (nalsize < 0) break; - nalsize = 0; - for (i = 0; i < h->nal_length_size; i++) - nalsize = (nalsize << 8) | buf[buf_index++]; - if (nalsize <= 0 || nalsize > buf_size - buf_index) { - av_log(h->avctx, AV_LOG_ERROR, - "AVC: nal size %d\n", nalsize); - break; - } next_avc = buf_index + nalsize; } else { - // start code prefix search - for (; buf_index + 3 < next_avc; buf_index++) - // This should always succeed in the first iteration. - if (buf[buf_index] == 0 && - buf[buf_index + 1] == 0 && - buf[buf_index + 2] == 1) - break; - - if (buf_index + 3 >= buf_size) { - buf_index = buf_size; + buf_index = find_start_code(buf, buf_size, buf_index, next_avc); + if (buf_index >= buf_size) break; - } - - buf_index += 3; if (buf_index >= next_avc) continue; } @@ -4851,23 +1518,14 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, ret = -1; goto end; } - i = buf_index + consumed; - if ((h->workaround_bugs & FF_BUG_AUTODETECT) && i + 3 < next_avc && - buf[i] == 0x00 && buf[i + 1] == 0x00 && - buf[i + 2] == 0x01 && buf[i + 3] == 0xE0) - h->workaround_bugs |= FF_BUG_TRUNCATED; - if (!(h->workaround_bugs & FF_BUG_TRUNCATED)) - while (dst_length > 0 && ptr[dst_length - 1] == 0) - dst_length--; - bit_length = !dst_length ? 0 - : (8 * dst_length - - decode_rbsp_trailing(h, ptr + dst_length - 1)); + 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/%d at %d/%d length %d pass %d\n", - hx->nal_unit_type, hx->nal_ref_idc, buf_index, buf_size, dst_length, pass); + "NAL %d/%d at %d/%d length %d\n", + hx->nal_unit_type, hx->nal_ref_idc, buf_index, buf_size, dst_length); if (h->is_avc && (nalsize != consumed) && nalsize) av_log(h->avctx, AV_LOG_DEBUG, @@ -4877,38 +1535,6 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, buf_index += consumed; nal_index++; - if (pass == 0) { - /* packets can sometimes contain multiple PPS/SPS, - * e.g. two PAFF field pictures in one packet, or a demuxer - * which splits NALs strangely if so, when frame threading we - * can't start the next thread until we've read all of them */ - switch (hx->nal_unit_type) { - case NAL_SPS: - case NAL_PPS: - nals_needed = nal_index; - break; - case NAL_DPA: - case NAL_IDR_SLICE: - case NAL_SLICE: - init_get_bits(&hx->gb, ptr, bit_length); - if (!get_ue_golomb(&hx->gb) || - !first_slice || - first_slice != hx->nal_unit_type) - nals_needed = nal_index; - if (!first_slice) - first_slice = hx->nal_unit_type; - } - continue; - } - - if (!first_slice) - switch (hx->nal_unit_type) { - case NAL_DPA: - case NAL_IDR_SLICE: - case NAL_SLICE: - first_slice = hx->nal_unit_type; - } - if (avctx->skip_frame >= AVDISCARD_NONREF && h->nal_ref_idc == 0 && h->nal_unit_type != NAL_SEI) @@ -4957,7 +1583,7 @@ again: hx->inter_gb_ptr = &hx->gb; hx->data_partitioning = 0; - if ((err = decode_slice_header(hx, h))) + if ((err = ff_h264_decode_slice_header(hx, h))) break; if (h->sei_recovery_frame_cnt >= 0) { @@ -5006,14 +1632,7 @@ again: ff_vdpau_h264_picture_start(h); } - if (hx->redundant_pic_count == 0 && - (avctx->skip_frame < AVDISCARD_NONREF || - hx->nal_ref_idc) && - (avctx->skip_frame < AVDISCARD_BIDIR || - hx->slice_type_nos != AV_PICTURE_TYPE_B) && - (avctx->skip_frame < AVDISCARD_NONKEY || - hx->slice_type_nos == AV_PICTURE_TYPE_I) && - avctx->skip_frame < AVDISCARD_ALL) { + if (hx->redundant_pic_count == 0) { if (avctx->hwaccel) { ret = avctx->hwaccel->decode_slice(avctx, &buf[buf_index - consumed], @@ -5044,7 +1663,7 @@ again: hx->intra_gb_ptr = hx->inter_gb_ptr = NULL; - if ((err = decode_slice_header(hx, h)) < 0) { + if ((err = ff_h264_decode_slice_header(hx, h))) { /* 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 */ @@ -5072,14 +1691,16 @@ again: (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 || + (avctx->skip_frame < AVDISCARD_NONINTRA || hx->slice_type_nos == AV_PICTURE_TYPE_I) && avctx->skip_frame < AVDISCARD_ALL) context_count++; break; case NAL_SEI: init_get_bits(&h->gb, ptr, bit_length); - ff_h264_decode_sei(h); + 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); @@ -5098,7 +1719,9 @@ again: break; case NAL_PPS: init_get_bits(&h->gb, ptr, bit_length); - ff_h264_decode_picture_parameter_set(h, 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: @@ -5115,14 +1738,17 @@ again: } if (context_count == h->max_contexts) { - execute_decode_slices(h, context_count); + 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"); + if (err < 0 || err == SLICE_SKIPED) { + 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) { + } else if (err == SLICE_SINGLETHREAD) { /* 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 @@ -5134,9 +1760,13 @@ again: } } } - if (context_count) - execute_decode_slices(h, context_count); + 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) { @@ -5160,7 +1790,7 @@ static int get_consumed_bytes(int pos, int buf_size) return pos; } -static int output_frame(H264Context *h, AVFrame *dst, Picture *srcp) +static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp) { AVFrame *src = &srcp->f; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(src->format); @@ -5171,6 +1801,8 @@ static int output_frame(H264Context *h, AVFrame *dst, Picture *srcp) av_dict_set(&dst->metadata, "stereo_mode", ff_h264_sei_stereo_mode(h), 0); + if (srcp->sei_recovery_frame_cnt == 0) + dst->key_frame = 1; if (!srcp->crop) return 0; @@ -5192,7 +1824,7 @@ static int h264_decode_frame(AVCodecContext *avctx, void *data, H264Context *h = avctx->priv_data; AVFrame *pict = data; int buf_index = 0; - Picture *out; + H264Picture *out; int i, out_idx; int ret; @@ -5279,7 +1911,7 @@ not_extra: if (avctx->flags2 & CODEC_FLAG2_CHUNKS) decode_postinit(h, 1); - field_end(h, 0); + ff_h264_field_end(h, 0); /* Wait for second field. */ *got_frame = 0; @@ -5293,7 +1925,10 @@ not_extra: return ret; *got_frame = 1; if (CONFIG_MPEGVIDEO) { - ff_print_debug_info2(h->avctx, h->next_output_pic, pict, h->er.mbskip_table, + ff_print_debug_info2(h->avctx, pict, h->er.mbskip_table, + h->next_output_pic->mb_type, + h->next_output_pic->qscale_table, + h->next_output_pic->motion_val, &h->low_delay, h->mb_width, h->mb_height, h->mb_stride, 1); } @@ -5309,7 +1944,7 @@ av_cold void ff_h264_free_context(H264Context *h) { int i; - free_tables(h, 1); // FIXME cleanup init stuff perhaps + 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); @@ -5325,7 +1960,7 @@ static av_cold int h264_decode_end(AVCodecContext *avctx) ff_h264_remove_all_refs(h); ff_h264_free_context(h); - unref_picture(h, &h->cur_pic); + ff_h264_unref_picture(h, &h->cur_pic); return 0; } @@ -5381,7 +2016,7 @@ AVCodec ff_h264_decoder = { 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(decode_update_thread_context), + .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_h264_update_thread_context), .profiles = NULL_IF_CONFIG_SMALL(profiles), .priv_class = &h264_class, }; diff --git a/libavcodec/h264.h b/libavcodec/h264.h index 4a41fffe6..228558b6f 100644 --- a/libavcodec/h264.h +++ b/libavcodec/h264.h @@ -30,14 +30,21 @@ #include "libavutil/intreadwrite.h" #include "cabac.h" +#include "dsputil.h" #include "error_resilience.h" #include "get_bits.h" -#include "mpegvideo.h" #include "h264chroma.h" #include "h264dsp.h" #include "h264pred.h" #include "h264qpel.h" +#include "mpegutils.h" +#include "parser.h" +#include "qpeldsp.h" #include "rectangle.h" +#include "videodsp.h" + +#define H264_MAX_PICTURE_COUNT 36 +#define H264_MAX_THREADS 32 #define MAX_SPS_COUNT 32 #define MAX_PPS_COUNT 256 @@ -129,6 +136,7 @@ typedef enum { 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; /** @@ -281,6 +289,50 @@ typedef struct MMCO { int long_arg; ///< index, pic_num, or num long refs depending on opcode } MMCO; +typedef struct H264Picture { + struct AVFrame f; + uint8_t avframe_padding[1024]; // hack to allow linking to a avutil with larger AVFrame + 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/fields used as reference (FIXME need per slice) + int ref_count[2][2]; ///< number of entries in ref_poc (FIXME need per slice) + int mbaff; ///< 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 + int invalid_gap; + int sei_recovery_frame_cnt; + + int crop; + int crop_left; + int crop_top; +} H264Picture; + /** * H264Context */ @@ -290,15 +342,14 @@ typedef struct H264Context { H264DSPContext h264dsp; H264ChromaContext h264chroma; H264QpelContext h264qpel; - MotionEstContext me; ParseContext parse_context; GetBitContext gb; DSPContext dsp; ERContext er; - Picture *DPB; - Picture *cur_pic_ptr; - Picture cur_pic; + 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 @@ -433,7 +484,7 @@ typedef struct H264Context { unsigned int ref_count[2]; ///< counts frames or fields, depending on current mb mode unsigned int list_count; uint8_t *list_counts; ///< Array of list_count per MB specifying the slice type - Picture ref_list[2][48]; /**< 0..15: frame refs, 16..47: mbaff field refs. + 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 @@ -445,7 +496,7 @@ typedef struct H264Context { 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)[16 * 48 * 2]; ///< as a dct coefficient 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 @@ -548,12 +599,12 @@ typedef struct H264Context { int redundant_pic_count; - Picture default_ref_list[2][32]; ///< base reference list for all slices of a coded picture - Picture *short_ref[32]; - Picture *long_ref[32]; - Picture *delayed_pic[MAX_DELAYED_PIC_COUNT + 2]; // FIXME size? + 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]; - Picture *next_output_pic; + H264Picture *next_output_pic; int outputed_poc; int next_outputed_poc; @@ -573,7 +624,7 @@ typedef struct H264Context { * @name Members for slice based multithreading * @{ */ - struct H264Context *thread_context[MAX_THREADS]; + struct H264Context *thread_context[H264_MAX_THREADS]; /** * current slice number, used to initialize slice_num of each thread/context @@ -623,6 +674,13 @@ typedef struct H264Context { 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 @@ -701,6 +759,10 @@ typedef struct H264Context { 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[7][QP_MAX_NUM + 1]; ///< One chroma qp table for each possible bit depth (8-14). @@ -804,6 +866,8 @@ 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); @@ -1028,9 +1092,31 @@ static av_always_inline int get_dct8x8_allowed(H264Context *h) 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); +#define SLICE_SINGLETHREAD 1 +#define SLICE_SKIPED 2 + +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); + +void ff_h264_set_erpic(ERPicture *dst, H264Picture *src); + #endif /* AVCODEC_H264_H */ diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c index 83aac22bb..5b1a82766 100644 --- a/libavcodec/h264_cabac.c +++ b/libavcodec/h264_cabac.c @@ -29,6 +29,7 @@ #define UNCHECKED_BITSTREAM_READER 1 #include "libavutil/attributes.h" +#include "libavutil/avassert.h" #include "libavutil/timer.h" #include "config.h" #include "cabac.h" @@ -39,7 +40,7 @@ #include "h264data.h" #include "h264_mvpred.h" #include "golomb.h" -#include "libavutil/avassert.h" +#include "mpegutils.h" #if ARCH_X86 #include "x86/h264_i386.h" @@ -1620,7 +1621,7 @@ decode_cabac_residual_internal(H264Context *h, int16_t *block, cc.range = h->cabac.range; cc.low = h->cabac.low; cc.bytestream= h->cabac.bytestream; -#if !UNCHECKED_BITSTREAM_READER +#if !UNCHECKED_BITSTREAM_READER || ARCH_AARCH64 cc.bytestream_end = h->cabac.bytestream_end; #endif #else @@ -2193,7 +2194,7 @@ decode_intra_mb: } }else ref=0; - fill_rectangle(&h->ref_cache[list][ scan8[0] ], 4, 4, 8, ref, 1); + fill_rectangle(&h->ref_cache[list][ scan8[0] ], 4, 4, 8, ref, 1); } } for(list=0; listlist_count; list++){ diff --git a/libavcodec/h264_cavlc.c b/libavcodec/h264_cavlc.c index a06203bac..ca587a46f 100644 --- a/libavcodec/h264_cavlc.c +++ b/libavcodec/h264_cavlc.c @@ -30,11 +30,11 @@ #include "internal.h" #include "avcodec.h" -#include "mpegvideo.h" #include "h264.h" #include "h264data.h" // FIXME FIXME FIXME #include "h264_mvpred.h" #include "golomb.h" +#include "mpegutils.h" #include "libavutil/avassert.h" diff --git a/libavcodec/h264_direct.c b/libavcodec/h264_direct.c index 477359c8f..b83a279bc 100644 --- a/libavcodec/h264_direct.c +++ b/libavcodec/h264_direct.c @@ -27,8 +27,8 @@ #include "internal.h" #include "avcodec.h" -#include "mpegvideo.h" #include "h264.h" +#include "mpegutils.h" #include "rectangle.h" #include "thread.h" @@ -48,7 +48,9 @@ static int get_scale_factor(H264Context * const h, int poc, int poc1, int i){ } void ff_h264_direct_dist_scale_factor(H264Context * const h){ - const int poc = h->cur_pic_ptr->field_poc[h->picture_structure == PICT_BOTTOM_FIELD]; + const int poc = h->picture_structure == PICT_FRAME ? + h->cur_pic_ptr->poc : + h->cur_pic_ptr->field_poc[h->picture_structure == PICT_BOTTOM_FIELD]; const int poc1 = h->ref_list[1][0].poc; int i, field; @@ -67,7 +69,7 @@ void ff_h264_direct_dist_scale_factor(H264Context * const h){ } static void fill_colmap(H264Context *h, int map[2][16+32], int list, int field, int colfield, int mbafi){ - Picture * const ref1 = &h->ref_list[1][0]; + H264Picture * const ref1 = &h->ref_list[1][0]; int j, old_ref, rfield; int start= mbafi ? 16 : 0; int end = mbafi ? 16+2*h->ref_count[0] : h->ref_count[0]; @@ -100,8 +102,8 @@ static void fill_colmap(H264Context *h, int map[2][16+32], int list, int field, } void ff_h264_direct_ref_list_init(H264Context * const h){ - Picture * const ref1 = &h->ref_list[1][0]; - Picture * const cur = h->cur_pic_ptr; + H264Picture * const ref1 = &h->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; @@ -140,7 +142,7 @@ void ff_h264_direct_ref_list_init(H264Context * const h){ } } -static void await_reference_mb_row(H264Context * const h, Picture *ref, int mb_y) +static void await_reference_mb_row(H264Context * const h, H264Picture *ref, int mb_y) { int ref_field = ref->reference - 1; int ref_field_picture = ref->field_picture; diff --git a/libavcodec/h264_loopfilter.c b/libavcodec/h264_loopfilter.c index 820887a91..8c052c3e2 100644 --- a/libavcodec/h264_loopfilter.c +++ b/libavcodec/h264_loopfilter.c @@ -29,9 +29,9 @@ #include "libavutil/intreadwrite.h" #include "internal.h" #include "avcodec.h" -#include "mpegvideo.h" #include "h264.h" #include "mathops.h" +#include "mpegutils.h" #include "rectangle.h" /* Deblocking filter (p153) */ diff --git a/libavcodec/h264_mb.c b/libavcodec/h264_mb.c new file mode 100644 index 000000000..191c01aa7 --- /dev/null +++ b/libavcodec/h264_mb.c @@ -0,0 +1,821 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... decoder + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 macroblock decoding + */ + +#include + +#include "config.h" + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "h264.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) +{ + int raw_my = h->mv_cache[list][scan8[n]][1]; + int filter_height_down = (raw_my & 3) ? 3 : 0; + int full_my = (raw_my >> 2) + y_offset; + int bottom = full_my + filter_height_down + height; + + av_assert2(height >= 0); + + return FFMAX(0, bottom); +} + +static inline void get_lowest_part_y(H264Context *h, int refs[2][48], int n, + int height, int y_offset, int list0, + int list1, int *nrefs) +{ + int my; + + y_offset += 16 * (h->mb_y >> MB_FIELD(h)); + + if (list0) { + int ref_n = h->ref_cache[0][scan8[n]]; + H264Picture *ref = &h->ref_list[0][ref_n]; + + // Error resilience puts the current picture in the ref list. + // Don't try to wait on these as it will cause a deadlock. + // Fields can wait on each other, though. + if (ref->tf.progress->data != h->cur_pic.tf.progress->data || + (ref->reference & 3) != h->picture_structure) { + my = get_lowest_part_list_y(h, ref, n, height, y_offset, 0); + if (refs[0][ref_n] < 0) + nrefs[0] += 1; + refs[0][ref_n] = FFMAX(refs[0][ref_n], my); + } + } + + if (list1) { + int ref_n = h->ref_cache[1][scan8[n]]; + H264Picture *ref = &h->ref_list[1][ref_n]; + + if (ref->tf.progress->data != h->cur_pic.tf.progress->data || + (ref->reference & 3) != h->picture_structure) { + my = get_lowest_part_list_y(h, ref, n, height, y_offset, 1); + if (refs[1][ref_n] < 0) + nrefs[1] += 1; + refs[1][ref_n] = FFMAX(refs[1][ref_n], my); + } + } +} + +/** + * Wait until all reference frames are available for MC operations. + * + * @param h the H264 context + */ +static void await_references(H264Context *h) +{ + const int mb_xy = h->mb_xy; + const int mb_type = h->cur_pic.mb_type[mb_xy]; + int refs[2][48]; + int nrefs[2] = { 0 }; + int ref, list; + + memset(refs, -1, sizeof(refs)); + + if (IS_16X16(mb_type)) { + get_lowest_part_y(h, refs, 0, 16, 0, + IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs); + } else if (IS_16X8(mb_type)) { + get_lowest_part_y(h, refs, 0, 8, 0, + IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs); + get_lowest_part_y(h, refs, 8, 8, 8, + IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1), nrefs); + } else if (IS_8X16(mb_type)) { + get_lowest_part_y(h, refs, 0, 16, 0, + IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs); + get_lowest_part_y(h, refs, 4, 16, 0, + IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1), nrefs); + } else { + int i; + + av_assert2(IS_8X8(mb_type)); + + for (i = 0; i < 4; i++) { + const int sub_mb_type = h->sub_mb_type[i]; + const int n = 4 * i; + int y_offset = (i & 2) << 2; + + if (IS_SUB_8X8(sub_mb_type)) { + get_lowest_part_y(h, refs, n, 8, y_offset, + IS_DIR(sub_mb_type, 0, 0), + IS_DIR(sub_mb_type, 0, 1), + nrefs); + } else if (IS_SUB_8X4(sub_mb_type)) { + get_lowest_part_y(h, refs, n, 4, y_offset, + IS_DIR(sub_mb_type, 0, 0), + IS_DIR(sub_mb_type, 0, 1), + nrefs); + get_lowest_part_y(h, refs, n + 2, 4, y_offset + 4, + IS_DIR(sub_mb_type, 0, 0), + IS_DIR(sub_mb_type, 0, 1), + nrefs); + } else if (IS_SUB_4X8(sub_mb_type)) { + get_lowest_part_y(h, refs, n, 8, y_offset, + IS_DIR(sub_mb_type, 0, 0), + IS_DIR(sub_mb_type, 0, 1), + nrefs); + get_lowest_part_y(h, refs, n + 1, 8, y_offset, + IS_DIR(sub_mb_type, 0, 0), + IS_DIR(sub_mb_type, 0, 1), + nrefs); + } else { + int j; + av_assert2(IS_SUB_4X4(sub_mb_type)); + for (j = 0; j < 4; j++) { + int sub_y_offset = y_offset + 2 * (j & 2); + get_lowest_part_y(h, refs, n + j, 4, sub_y_offset, + IS_DIR(sub_mb_type, 0, 0), + IS_DIR(sub_mb_type, 0, 1), + nrefs); + } + } + } + } + + for (list = h->list_count - 1; list >= 0; list--) + for (ref = 0; ref < 48 && nrefs[list]; ref++) { + int row = refs[list][ref]; + if (row >= 0) { + H264Picture *ref_pic = &h->ref_list[list][ref]; + int ref_field = ref_pic->reference - 1; + int ref_field_picture = ref_pic->field_picture; + int pic_height = 16 * h->mb_height >> ref_field_picture; + + row <<= MB_MBAFF(h); + nrefs[list]--; + + if (!FIELD_PICTURE(h) && ref_field_picture) { // frame referencing two fields + ff_thread_await_progress(&ref_pic->tf, + FFMIN((row >> 1) - !(row & 1), + pic_height - 1), + 1); + ff_thread_await_progress(&ref_pic->tf, + FFMIN((row >> 1), pic_height - 1), + 0); + } else if (FIELD_PICTURE(h) && !ref_field_picture) { // field referencing one field of a frame + ff_thread_await_progress(&ref_pic->tf, + FFMIN(row * 2 + ref_field, + pic_height - 1), + 0); + } else if (FIELD_PICTURE(h)) { + ff_thread_await_progress(&ref_pic->tf, + FFMIN(row, pic_height - 1), + ref_field); + } else { + ff_thread_await_progress(&ref_pic->tf, + FFMIN(row, pic_height - 1), + 0); + } + } + } +} + +static av_always_inline void mc_dir_part(H264Context *h, H264Picture *pic, + int n, int square, int height, + int delta, int list, + uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, + int src_x_offset, int src_y_offset, + qpel_mc_func *qpix_op, + h264_chroma_mc_func chroma_op, + int pixel_shift, int chroma_idc) +{ + const int mx = h->mv_cache[list][scan8[n]][0] + src_x_offset * 8; + int my = h->mv_cache[list][scan8[n]][1] + src_y_offset * 8; + const int luma_xy = (mx & 3) + ((my & 3) << 2); + ptrdiff_t offset = ((mx >> 2) << pixel_shift) + (my >> 2) * h->mb_linesize; + uint8_t *src_y = pic->f.data[0] + offset; + uint8_t *src_cb, *src_cr; + int extra_width = 0; + int extra_height = 0; + int emu = 0; + const int full_mx = mx >> 2; + const int full_my = my >> 2; + const int pic_width = 16 * h->mb_width; + const int pic_height = 16 * h->mb_height >> MB_FIELD(h); + int ysh; + + if (mx & 7) + extra_width -= 3; + if (my & 7) + extra_height -= 3; + + if (full_mx < 0 - extra_width || + full_my < 0 - extra_height || + full_mx + 16 /*FIXME*/ > pic_width + extra_width || + full_my + 16 /*FIXME*/ > pic_height + extra_height) { + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, + src_y - (2 << pixel_shift) - 2 * h->mb_linesize, + h->mb_linesize, h->mb_linesize, + 16 + 5, 16 + 5 /*FIXME*/, full_mx - 2, + full_my - 2, pic_width, pic_height); + src_y = h->edge_emu_buffer + (2 << pixel_shift) + 2 * h->mb_linesize; + emu = 1; + } + + qpix_op[luma_xy](dest_y, src_y, h->mb_linesize); // FIXME try variable height perhaps? + if (!square) + qpix_op[luma_xy](dest_y + delta, src_y + delta, h->mb_linesize); + + if (CONFIG_GRAY && h->flags & CODEC_FLAG_GRAY) + return; + + if (chroma_idc == 3 /* yuv444 */) { + src_cb = pic->f.data[1] + offset; + if (emu) { + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, + src_cb - (2 << pixel_shift) - 2 * h->mb_linesize, + h->mb_linesize, h->mb_linesize, + 16 + 5, 16 + 5 /*FIXME*/, + full_mx - 2, full_my - 2, + pic_width, pic_height); + src_cb = h->edge_emu_buffer + (2 << pixel_shift) + 2 * h->mb_linesize; + } + qpix_op[luma_xy](dest_cb, src_cb, h->mb_linesize); // FIXME try variable height perhaps? + if (!square) + qpix_op[luma_xy](dest_cb + delta, src_cb + delta, h->mb_linesize); + + src_cr = pic->f.data[2] + offset; + if (emu) { + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, + src_cr - (2 << pixel_shift) - 2 * h->mb_linesize, + h->mb_linesize, h->mb_linesize, + 16 + 5, 16 + 5 /*FIXME*/, + full_mx - 2, full_my - 2, + pic_width, pic_height); + src_cr = h->edge_emu_buffer + (2 << pixel_shift) + 2 * h->mb_linesize; + } + qpix_op[luma_xy](dest_cr, src_cr, h->mb_linesize); // FIXME try variable height perhaps? + if (!square) + qpix_op[luma_xy](dest_cr + delta, src_cr + delta, h->mb_linesize); + return; + } + + ysh = 3 - (chroma_idc == 2 /* yuv422 */); + if (chroma_idc == 1 /* yuv420 */ && MB_FIELD(h)) { + // chroma offset when predicting from a field of opposite parity + my += 2 * ((h->mb_y & 1) - (pic->reference - 1)); + emu |= (my >> 3) < 0 || (my >> 3) + 8 >= (pic_height >> 1); + } + + src_cb = pic->f.data[1] + ((mx >> 3) << pixel_shift) + + (my >> ysh) * h->mb_uvlinesize; + src_cr = pic->f.data[2] + ((mx >> 3) << pixel_shift) + + (my >> ysh) * h->mb_uvlinesize; + + if (emu) { + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_cb, + h->mb_uvlinesize, h->mb_uvlinesize, + 9, 8 * chroma_idc + 1, (mx >> 3), (my >> ysh), + pic_width >> 1, pic_height >> (chroma_idc == 1 /* yuv420 */)); + src_cb = h->edge_emu_buffer; + } + chroma_op(dest_cb, src_cb, h->mb_uvlinesize, + height >> (chroma_idc == 1 /* yuv420 */), + mx & 7, (my << (chroma_idc == 2 /* yuv422 */)) & 7); + + if (emu) { + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_cr, + h->mb_uvlinesize, h->mb_uvlinesize, + 9, 8 * chroma_idc + 1, (mx >> 3), (my >> ysh), + pic_width >> 1, pic_height >> (chroma_idc == 1 /* yuv420 */)); + src_cr = h->edge_emu_buffer; + } + chroma_op(dest_cr, src_cr, h->mb_uvlinesize, height >> (chroma_idc == 1 /* yuv420 */), + mx & 7, (my << (chroma_idc == 2 /* yuv422 */)) & 7); +} + +static av_always_inline void mc_part_std(H264Context *h, int n, int square, + int height, int delta, + uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, + int x_offset, int y_offset, + qpel_mc_func *qpix_put, + h264_chroma_mc_func chroma_put, + qpel_mc_func *qpix_avg, + h264_chroma_mc_func chroma_avg, + int list0, int list1, + int pixel_shift, int chroma_idc) +{ + qpel_mc_func *qpix_op = qpix_put; + h264_chroma_mc_func chroma_op = chroma_put; + + dest_y += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + if (chroma_idc == 3 /* yuv444 */) { + dest_cb += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + dest_cr += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + } else if (chroma_idc == 2 /* yuv422 */) { + dest_cb += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; + dest_cr += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; + } else { /* yuv420 */ + dest_cb += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; + dest_cr += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; + } + x_offset += 8 * h->mb_x; + y_offset += 8 * (h->mb_y >> MB_FIELD(h)); + + if (list0) { + H264Picture *ref = &h->ref_list[0][h->ref_cache[0][scan8[n]]]; + mc_dir_part(h, ref, n, square, height, delta, 0, + dest_y, dest_cb, dest_cr, x_offset, y_offset, + qpix_op, chroma_op, pixel_shift, chroma_idc); + + qpix_op = qpix_avg; + chroma_op = chroma_avg; + } + + if (list1) { + H264Picture *ref = &h->ref_list[1][h->ref_cache[1][scan8[n]]]; + mc_dir_part(h, ref, n, square, height, delta, 1, + dest_y, dest_cb, dest_cr, x_offset, y_offset, + qpix_op, chroma_op, pixel_shift, chroma_idc); + } +} + +static av_always_inline void mc_part_weighted(H264Context *h, int n, int square, + int height, int delta, + uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, + int x_offset, int y_offset, + qpel_mc_func *qpix_put, + h264_chroma_mc_func chroma_put, + h264_weight_func luma_weight_op, + h264_weight_func chroma_weight_op, + h264_biweight_func luma_weight_avg, + h264_biweight_func chroma_weight_avg, + int list0, int list1, + int pixel_shift, int chroma_idc) +{ + int chroma_height; + + dest_y += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + if (chroma_idc == 3 /* yuv444 */) { + chroma_height = height; + chroma_weight_avg = luma_weight_avg; + chroma_weight_op = luma_weight_op; + dest_cb += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + dest_cr += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + } else if (chroma_idc == 2 /* yuv422 */) { + chroma_height = height; + dest_cb += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; + dest_cr += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; + } else { /* yuv420 */ + chroma_height = height >> 1; + dest_cb += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; + dest_cr += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; + } + x_offset += 8 * h->mb_x; + y_offset += 8 * (h->mb_y >> MB_FIELD(h)); + + if (list0 && list1) { + /* don't optimize for luma-only case, since B-frames usually + * use implicit weights => chroma too. */ + uint8_t *tmp_cb = h->bipred_scratchpad; + uint8_t *tmp_cr = h->bipred_scratchpad + (16 << pixel_shift); + uint8_t *tmp_y = h->bipred_scratchpad + 16 * h->mb_uvlinesize; + int refn0 = h->ref_cache[0][scan8[n]]; + int refn1 = h->ref_cache[1][scan8[n]]; + + mc_dir_part(h, &h->ref_list[0][refn0], n, square, height, delta, 0, + dest_y, dest_cb, dest_cr, + x_offset, y_offset, qpix_put, chroma_put, + pixel_shift, chroma_idc); + mc_dir_part(h, &h->ref_list[1][refn1], n, square, height, delta, 1, + tmp_y, tmp_cb, tmp_cr, + x_offset, y_offset, qpix_put, chroma_put, + pixel_shift, chroma_idc); + + if (h->use_weight == 2) { + int weight0 = h->implicit_weight[refn0][refn1][h->mb_y & 1]; + int weight1 = 64 - weight0; + luma_weight_avg(dest_y, tmp_y, h->mb_linesize, + height, 5, weight0, weight1, 0); + chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, + chroma_height, 5, weight0, weight1, 0); + chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, + chroma_height, 5, weight0, weight1, 0); + } else { + luma_weight_avg(dest_y, tmp_y, h->mb_linesize, height, + h->luma_log2_weight_denom, + h->luma_weight[refn0][0][0], + h->luma_weight[refn1][1][0], + h->luma_weight[refn0][0][1] + + h->luma_weight[refn1][1][1]); + chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, chroma_height, + h->chroma_log2_weight_denom, + h->chroma_weight[refn0][0][0][0], + h->chroma_weight[refn1][1][0][0], + h->chroma_weight[refn0][0][0][1] + + h->chroma_weight[refn1][1][0][1]); + chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, chroma_height, + h->chroma_log2_weight_denom, + h->chroma_weight[refn0][0][1][0], + h->chroma_weight[refn1][1][1][0], + h->chroma_weight[refn0][0][1][1] + + h->chroma_weight[refn1][1][1][1]); + } + } else { + int list = list1 ? 1 : 0; + int refn = h->ref_cache[list][scan8[n]]; + H264Picture *ref = &h->ref_list[list][refn]; + mc_dir_part(h, ref, n, square, height, delta, list, + dest_y, dest_cb, dest_cr, x_offset, y_offset, + qpix_put, chroma_put, pixel_shift, chroma_idc); + + luma_weight_op(dest_y, h->mb_linesize, height, + h->luma_log2_weight_denom, + h->luma_weight[refn][list][0], + h->luma_weight[refn][list][1]); + if (h->use_weight_chroma) { + chroma_weight_op(dest_cb, h->mb_uvlinesize, chroma_height, + h->chroma_log2_weight_denom, + h->chroma_weight[refn][list][0][0], + h->chroma_weight[refn][list][0][1]); + chroma_weight_op(dest_cr, h->mb_uvlinesize, chroma_height, + h->chroma_log2_weight_denom, + h->chroma_weight[refn][list][1][0], + h->chroma_weight[refn][list][1][1]); + } + } +} + +static av_always_inline void prefetch_motion(H264Context *h, int list, + int pixel_shift, int chroma_idc) +{ + /* fetch pixels for estimated mv 4 macroblocks ahead + * optimized for 64byte cache lines */ + const int refn = h->ref_cache[list][scan8[0]]; + if (refn >= 0) { + const int mx = (h->mv_cache[list][scan8[0]][0] >> 2) + 16 * h->mb_x + 8; + const int my = (h->mv_cache[list][scan8[0]][1] >> 2) + 16 * h->mb_y; + uint8_t **src = h->ref_list[list][refn].f.data; + int off = (mx << pixel_shift) + + (my + (h->mb_x & 3) * 4) * h->mb_linesize + + (64 << pixel_shift); + h->vdsp.prefetch(src[0] + off, h->linesize, 4); + if (chroma_idc == 3 /* yuv444 */) { + h->vdsp.prefetch(src[1] + off, h->linesize, 4); + h->vdsp.prefetch(src[2] + off, h->linesize, 4); + } else { + off= (((mx>>1)+64)<>1) + (h->mb_x&7))*h->uvlinesize; + h->vdsp.prefetch(src[1] + off, src[2] - src[1], 2); + } + } +} + +static av_always_inline void xchg_mb_border(H264Context *h, uint8_t *src_y, + uint8_t *src_cb, uint8_t *src_cr, + int linesize, int uvlinesize, + int xchg, int chroma444, + int simple, int pixel_shift) +{ + int deblock_topleft; + int deblock_top; + int top_idx = 1; + uint8_t *top_border_m1; + uint8_t *top_border; + + if (!simple && FRAME_MBAFF(h)) { + if (h->mb_y & 1) { + if (!MB_MBAFF(h)) + return; + } else { + top_idx = MB_MBAFF(h) ? 0 : 1; + } + } + + if (h->deblocking_filter == 2) { + deblock_topleft = h->slice_table[h->mb_xy - 1 - h->mb_stride] == h->slice_num; + deblock_top = h->top_type; + } else { + deblock_topleft = (h->mb_x > 0); + deblock_top = (h->mb_y > !!MB_FIELD(h)); + } + + src_y -= linesize + 1 + pixel_shift; + src_cb -= uvlinesize + 1 + pixel_shift; + src_cr -= uvlinesize + 1 + pixel_shift; + + top_border_m1 = h->top_borders[top_idx][h->mb_x - 1]; + top_border = h->top_borders[top_idx][h->mb_x]; + +#define XCHG(a, b, xchg) \ + if (pixel_shift) { \ + if (xchg) { \ + AV_SWAP64(b + 0, a + 0); \ + AV_SWAP64(b + 8, a + 8); \ + } else { \ + AV_COPY128(b, a); \ + } \ + } else if (xchg) \ + AV_SWAP64(b, a); \ + else \ + AV_COPY64(b, a); + + if (deblock_top) { + if (deblock_topleft) { + XCHG(top_border_m1 + (8 << pixel_shift), + src_y - (7 << pixel_shift), 1); + } + XCHG(top_border + (0 << pixel_shift), src_y + (1 << pixel_shift), xchg); + XCHG(top_border + (8 << pixel_shift), src_y + (9 << pixel_shift), 1); + if (h->mb_x + 1 < h->mb_width) { + XCHG(h->top_borders[top_idx][h->mb_x + 1], + src_y + (17 << pixel_shift), 1); + } + if (simple || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { + if (chroma444) { + if (deblock_topleft) { + XCHG(top_border_m1 + (24 << pixel_shift), src_cb - (7 << pixel_shift), 1); + XCHG(top_border_m1 + (40 << pixel_shift), src_cr - (7 << pixel_shift), 1); + } + XCHG(top_border + (16 << pixel_shift), src_cb + (1 << pixel_shift), xchg); + XCHG(top_border + (24 << pixel_shift), src_cb + (9 << pixel_shift), 1); + XCHG(top_border + (32 << pixel_shift), src_cr + (1 << pixel_shift), xchg); + XCHG(top_border + (40 << pixel_shift), src_cr + (9 << pixel_shift), 1); + if (h->mb_x + 1 < h->mb_width) { + XCHG(h->top_borders[top_idx][h->mb_x + 1] + (16 << pixel_shift), src_cb + (17 << pixel_shift), 1); + XCHG(h->top_borders[top_idx][h->mb_x + 1] + (32 << pixel_shift), src_cr + (17 << pixel_shift), 1); + } + } else { + if (deblock_topleft) { + XCHG(top_border_m1 + (16 << pixel_shift), src_cb - (7 << pixel_shift), 1); + XCHG(top_border_m1 + (24 << pixel_shift), src_cr - (7 << pixel_shift), 1); + } + XCHG(top_border + (16 << pixel_shift), src_cb + 1 + pixel_shift, 1); + XCHG(top_border + (24 << pixel_shift), src_cr + 1 + pixel_shift, 1); + } + } + } +} + +static av_always_inline int dctcoef_get(int16_t *mb, int high_bit_depth, + int index) +{ + if (high_bit_depth) { + return AV_RN32A(((int32_t *)mb) + index); + } else + return AV_RN16A(mb + index); +} + +static av_always_inline void dctcoef_set(int16_t *mb, int high_bit_depth, + int index, int value) +{ + if (high_bit_depth) { + AV_WN32A(((int32_t *)mb) + index, value); + } else + AV_WN16A(mb + index, value); +} + +static av_always_inline void hl_decode_mb_predict_luma(H264Context *h, + int mb_type, int is_h264, + int simple, + int transform_bypass, + int pixel_shift, + int *block_offset, + int linesize, + uint8_t *dest_y, int p) +{ + void (*idct_add)(uint8_t *dst, int16_t *block, int stride); + void (*idct_dc_add)(uint8_t *dst, int16_t *block, int stride); + int i; + int qscale = p == 0 ? h->qscale : h->chroma_qp[p - 1]; + block_offset += 16 * p; + if (IS_INTRA4x4(mb_type)) { + if (IS_8x8DCT(mb_type)) { + if (transform_bypass) { + idct_dc_add = + idct_add = h->h264dsp.h264_add_pixels8_clear; + } else { + idct_dc_add = h->h264dsp.h264_idct8_dc_add; + idct_add = h->h264dsp.h264_idct8_add; + } + for (i = 0; i < 16; i += 4) { + uint8_t *const ptr = dest_y + block_offset[i]; + const int dir = h->intra4x4_pred_mode_cache[scan8[i]]; + if (transform_bypass && h->sps.profile_idc == 244 && dir <= 1) { + if (h->x264_build != -1) { + h->hpc.pred8x8l_add[dir](ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + } else + h->hpc.pred8x8l_filter_add[dir](ptr, h->mb + (i * 16 + p * 256 << pixel_shift), + (h-> topleft_samples_available << i) & 0x8000, + (h->topright_samples_available << i) & 0x4000, linesize); + } else { + const int nnz = h->non_zero_count_cache[scan8[i + p * 16]]; + h->hpc.pred8x8l[dir](ptr, (h->topleft_samples_available << i) & 0x8000, + (h->topright_samples_available << i) & 0x4000, linesize); + if (nnz) { + if (nnz == 1 && dctcoef_get(h->mb, pixel_shift, i * 16 + p * 256)) + idct_dc_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + else + idct_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + } + } + } + } else { + if (transform_bypass) { + idct_dc_add = + idct_add = h->h264dsp.h264_add_pixels4_clear; + } else { + idct_dc_add = h->h264dsp.h264_idct_dc_add; + idct_add = h->h264dsp.h264_idct_add; + } + for (i = 0; i < 16; i++) { + uint8_t *const ptr = dest_y + block_offset[i]; + const int dir = h->intra4x4_pred_mode_cache[scan8[i]]; + + if (transform_bypass && h->sps.profile_idc == 244 && dir <= 1) { + h->hpc.pred4x4_add[dir](ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + } else { + uint8_t *topright; + int nnz, tr; + uint64_t tr_high; + if (dir == DIAG_DOWN_LEFT_PRED || dir == VERT_LEFT_PRED) { + const int topright_avail = (h->topright_samples_available << i) & 0x8000; + av_assert2(h->mb_y || linesize <= block_offset[i]); + if (!topright_avail) { + if (pixel_shift) { + tr_high = ((uint16_t *)ptr)[3 - linesize / 2] * 0x0001000100010001ULL; + topright = (uint8_t *)&tr_high; + } else { + tr = ptr[3 - linesize] * 0x01010101u; + topright = (uint8_t *)&tr; + } + } else + topright = ptr + (4 << pixel_shift) - linesize; + } else + topright = NULL; + + h->hpc.pred4x4[dir](ptr, topright, linesize); + nnz = h->non_zero_count_cache[scan8[i + p * 16]]; + if (nnz) { + if (is_h264) { + if (nnz == 1 && dctcoef_get(h->mb, pixel_shift, i * 16 + p * 256)) + idct_dc_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + else + idct_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + } else if (CONFIG_SVQ3_DECODER) + ff_svq3_add_idct_c(ptr, h->mb + i * 16 + p * 256, linesize, qscale, 0); + } + } + } + } + } else { + h->hpc.pred16x16[h->intra16x16_pred_mode](dest_y, linesize); + if (is_h264) { + if (h->non_zero_count_cache[scan8[LUMA_DC_BLOCK_INDEX + p]]) { + if (!transform_bypass) + h->h264dsp.h264_luma_dc_dequant_idct(h->mb + (p * 256 << pixel_shift), + h->mb_luma_dc[p], + h->dequant4_coeff[p][qscale][0]); + else { + static const uint8_t dc_mapping[16] = { + 0 * 16, 1 * 16, 4 * 16, 5 * 16, + 2 * 16, 3 * 16, 6 * 16, 7 * 16, + 8 * 16, 9 * 16, 12 * 16, 13 * 16, + 10 * 16, 11 * 16, 14 * 16, 15 * 16 + }; + for (i = 0; i < 16; i++) + dctcoef_set(h->mb + (p * 256 << pixel_shift), + pixel_shift, dc_mapping[i], + dctcoef_get(h->mb_luma_dc[p], + pixel_shift, i)); + } + } + } else if (CONFIG_SVQ3_DECODER) + ff_svq3_luma_dc_dequant_idct_c(h->mb + p * 256, + h->mb_luma_dc[p], qscale); + } +} + +static av_always_inline void hl_decode_mb_idct_luma(H264Context *h, int mb_type, + int is_h264, int simple, + int transform_bypass, + int pixel_shift, + int *block_offset, + int linesize, + uint8_t *dest_y, int p) +{ + void (*idct_add)(uint8_t *dst, int16_t *block, int stride); + int i; + block_offset += 16 * p; + if (!IS_INTRA4x4(mb_type)) { + if (is_h264) { + if (IS_INTRA16x16(mb_type)) { + if (transform_bypass) { + if (h->sps.profile_idc == 244 && + (h->intra16x16_pred_mode == VERT_PRED8x8 || + h->intra16x16_pred_mode == HOR_PRED8x8)) { + h->hpc.pred16x16_add[h->intra16x16_pred_mode](dest_y, block_offset, + h->mb + (p * 256 << pixel_shift), + linesize); + } else { + for (i = 0; i < 16; i++) + if (h->non_zero_count_cache[scan8[i + p * 16]] || + dctcoef_get(h->mb, pixel_shift, i * 16 + p * 256)) + h->h264dsp.h264_add_pixels4_clear(dest_y + block_offset[i], + h->mb + (i * 16 + p * 256 << pixel_shift), + linesize); + } + } else { + h->h264dsp.h264_idct_add16intra(dest_y, block_offset, + h->mb + (p * 256 << pixel_shift), + linesize, + h->non_zero_count_cache + p * 5 * 8); + } + } else if (h->cbp & 15) { + if (transform_bypass) { + const int di = IS_8x8DCT(mb_type) ? 4 : 1; + idct_add = IS_8x8DCT(mb_type) ? h->h264dsp.h264_add_pixels8_clear + : h->h264dsp.h264_add_pixels4_clear; + for (i = 0; i < 16; i += di) + if (h->non_zero_count_cache[scan8[i + p * 16]]) + idct_add(dest_y + block_offset[i], + h->mb + (i * 16 + p * 256 << pixel_shift), + linesize); + } else { + if (IS_8x8DCT(mb_type)) + h->h264dsp.h264_idct8_add4(dest_y, block_offset, + h->mb + (p * 256 << pixel_shift), + linesize, + h->non_zero_count_cache + p * 5 * 8); + else + h->h264dsp.h264_idct_add16(dest_y, block_offset, + h->mb + (p * 256 << pixel_shift), + linesize, + h->non_zero_count_cache + p * 5 * 8); + } + } + } else if (CONFIG_SVQ3_DECODER) { + for (i = 0; i < 16; i++) + if (h->non_zero_count_cache[scan8[i + p * 16]] || h->mb[i * 16 + p * 256]) { + // FIXME benchmark weird rule, & below + uint8_t *const ptr = dest_y + block_offset[i]; + ff_svq3_add_idct_c(ptr, h->mb + i * 16 + p * 256, linesize, + h->qscale, IS_INTRA(mb_type) ? 1 : 0); + } + } + } +} + +#define BITS 8 +#define SIMPLE 1 +#include "h264_mb_template.c" + +#undef BITS +#define BITS 16 +#include "h264_mb_template.c" + +#undef SIMPLE +#define SIMPLE 0 +#include "h264_mb_template.c" + +void ff_h264_hl_decode_mb(H264Context *h) +{ + const int mb_xy = h->mb_xy; + const int mb_type = h->cur_pic.mb_type[mb_xy]; + int is_complex = CONFIG_SMALL || h->is_complex || + IS_INTRA_PCM(mb_type) || h->qscale == 0; + + if (CHROMA444(h)) { + if (is_complex || h->pixel_shift) + hl_decode_mb_444_complex(h); + else + hl_decode_mb_444_simple_8(h); + } else if (is_complex) { + hl_decode_mb_complex(h); + } else if (h->pixel_shift) { + hl_decode_mb_simple_16(h); + } else + hl_decode_mb_simple_8(h); +} diff --git a/libavcodec/h264_mb_template.c b/libavcodec/h264_mb_template.c index da3a9263d..7c9d72b35 100644 --- a/libavcodec/h264_mb_template.c +++ b/libavcodec/h264_mb_template.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "svq3.h" + #undef FUNC #undef PIXEL_SHIFT @@ -172,14 +174,14 @@ static av_noinline void FUNC(hl_decode_mb)(H264Context *h) } else if (is_h264) { if (chroma422) { FUNC(hl_motion_422)(h, dest_y, dest_cb, dest_cr, - h->me.qpel_put, h->h264chroma.put_h264_chroma_pixels_tab, - h->me.qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab, + h->qpel_put, h->h264chroma.put_h264_chroma_pixels_tab, + h->qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab, h->h264dsp.weight_h264_pixels_tab, h->h264dsp.biweight_h264_pixels_tab); } else { FUNC(hl_motion_420)(h, dest_y, dest_cb, dest_cr, - h->me.qpel_put, h->h264chroma.put_h264_chroma_pixels_tab, - h->me.qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab, + h->qpel_put, h->h264chroma.put_h264_chroma_pixels_tab, + h->qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab, h->h264dsp.weight_h264_pixels_tab, h->h264dsp.biweight_h264_pixels_tab); } @@ -351,8 +353,8 @@ static av_noinline void FUNC(hl_decode_mb_444)(H264Context *h) linesize, 0, 1, SIMPLE, PIXEL_SHIFT); } else { FUNC(hl_motion_444)(h, dest[0], dest[1], dest[2], - h->me.qpel_put, h->h264chroma.put_h264_chroma_pixels_tab, - h->me.qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab, + h->qpel_put, h->h264chroma.put_h264_chroma_pixels_tab, + h->qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab, h->h264dsp.weight_h264_pixels_tab, h->h264dsp.biweight_h264_pixels_tab); } diff --git a/libavcodec/h264_mc_template.c b/libavcodec/h264_mc_template.c index 7aec43ba9..0e4e47713 100644 --- a/libavcodec/h264_mc_template.c +++ b/libavcodec/h264_mc_template.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "h264.h" + #undef MCFUNC #if CHROMA_IDC == 1 diff --git a/libavcodec/h264_mvpred.h b/libavcodec/h264_mvpred.h index afe327c57..5f1e9a1ee 100644 --- a/libavcodec/h264_mvpred.h +++ b/libavcodec/h264_mvpred.h @@ -31,6 +31,7 @@ #include "internal.h" #include "avcodec.h" #include "h264.h" +#include "mpegutils.h" #include "libavutil/avassert.h" diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index 443287176..ea0ab9803 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -32,6 +32,7 @@ #include "h264data.h" #include "golomb.h" #include "internal.h" +#include "mpegutils.h" static int h264_find_frame_end(H264Context *h, const uint8_t *buf, diff --git a/libavcodec/h264_picture.c b/libavcodec/h264_picture.c new file mode 100644 index 000000000..b6bdae491 --- /dev/null +++ b/libavcodec/h264_picture.c @@ -0,0 +1,213 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... decoder + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 codec. + * @author Michael Niedermayer + */ + +#include "libavutil/avassert.h" +#include "libavutil/imgutils.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 "mpegutils.h" +#include "rectangle.h" +#include "thread.h" +#include "vdpau_internal.h" + +void ff_h264_unref_picture(H264Context *h, H264Picture *pic) +{ + int off = offsetof(H264Picture, tf) + sizeof(pic->tf); + int i; + + if (!pic->f.buf[0]) + return; + + ff_thread_release_buffer(h->avctx, &pic->tf); + av_buffer_unref(&pic->hwaccel_priv_buf); + + av_buffer_unref(&pic->qscale_table_buf); + av_buffer_unref(&pic->mb_type_buf); + for (i = 0; i < 2; i++) { + av_buffer_unref(&pic->motion_val_buf[i]); + av_buffer_unref(&pic->ref_index_buf[i]); + } + + memset((uint8_t*)pic + off, 0, sizeof(*pic) - off); +} + +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]); + + src->tf.f = &src->f; + dst->tf.f = &dst->f; + ret = ff_thread_ref_frame(&dst->tf, &src->tf); + if (ret < 0) + goto fail; + + dst->qscale_table_buf = av_buffer_ref(src->qscale_table_buf); + dst->mb_type_buf = av_buffer_ref(src->mb_type_buf); + if (!dst->qscale_table_buf || !dst->mb_type_buf) + goto fail; + dst->qscale_table = src->qscale_table; + dst->mb_type = src->mb_type; + + for (i = 0; i < 2; i++) { + dst->motion_val_buf[i] = av_buffer_ref(src->motion_val_buf[i]); + dst->ref_index_buf[i] = av_buffer_ref(src->ref_index_buf[i]); + if (!dst->motion_val_buf[i] || !dst->ref_index_buf[i]) + goto fail; + dst->motion_val[i] = src->motion_val[i]; + dst->ref_index[i] = src->ref_index[i]; + } + + if (src->hwaccel_picture_private) { + dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); + if (!dst->hwaccel_priv_buf) + goto fail; + dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; + } + + for (i = 0; i < 2; i++) + dst->field_poc[i] = src->field_poc[i]; + + memcpy(dst->ref_poc, src->ref_poc, sizeof(src->ref_poc)); + memcpy(dst->ref_count, src->ref_count, sizeof(src->ref_count)); + + dst->poc = src->poc; + dst->frame_num = src->frame_num; + dst->mmco_reset = src->mmco_reset; + dst->pic_id = src->pic_id; + dst->long_ref = src->long_ref; + dst->mbaff = src->mbaff; + dst->field_picture = src->field_picture; + dst->needs_realloc = src->needs_realloc; + dst->reference = src->reference; + dst->crop = src->crop; + dst->crop_left = src->crop_left; + dst->crop_top = src->crop_top; + dst->recovered = src->recovered; + dst->invalid_gap = src->invalid_gap; + dst->sei_recovery_frame_cnt = src->sei_recovery_frame_cnt; + + return 0; +fail: + ff_h264_unref_picture(h, dst); + return ret; +} + +void ff_h264_set_erpic(ERPicture *dst, H264Picture *src) +{ +#if CONFIG_ERROR_RESILIENCE + int i; + + memset(dst, 0, sizeof(*dst)); + + if (!src) + return; + + dst->f = &src->f; + dst->tf = &src->tf; + + for (i = 0; i < 2; i++) { + dst->motion_val[i] = src->motion_val[i]; + dst->ref_index[i] = src->ref_index[i]; + } + + dst->mb_type = src->mb_type; + dst->field_picture = src->field_picture; +#endif /* CONFIG_ERROR_RESILIENCE */ +} + +int ff_h264_field_end(H264Context *h, int in_setup) +{ + AVCodecContext *const avctx = h->avctx; + int err = 0; + h->mb_y = 0; + + if (CONFIG_H264_VDPAU_DECODER && + h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) + ff_vdpau_h264_set_reference_frames(h); + + if (in_setup || !(avctx->active_thread_type & FF_THREAD_FRAME)) { + if (!h->droppable) { + err = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index); + h->prev_poc_msb = h->poc_msb; + h->prev_poc_lsb = h->poc_lsb; + } + h->prev_frame_num_offset = h->frame_num_offset; + h->prev_frame_num = h->frame_num; + h->outputed_poc = h->next_outputed_poc; + } + + if (avctx->hwaccel) { + if (avctx->hwaccel->end_frame(avctx) < 0) + av_log(avctx, AV_LOG_ERROR, + "hardware accelerator failed to decode picture\n"); + } + + if (CONFIG_H264_VDPAU_DECODER && + h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) + ff_vdpau_h264_picture_complete(h); + +#if CONFIG_ERROR_RESILIENCE + /* + * FIXME: Error handling code does not seem to support interlaced + * when slices span multiple rows + * The ff_er_add_slice calls don't work right for bottom + * fields; they cause massive erroneous error concealing + * Error marking covers both fields (top and bottom). + * This causes a mismatched s->error_count + * and a bad error table. Further, the error count goes to + * INT_MAX when called for bottom field, because mb_y is + * past end by one (callers fault) and resync_mb_y != 0 + * causes problems for the first MB line, too. + */ + if (!FIELD_PICTURE(h) && h->current_slice && !h->sps.new) { + ff_h264_set_erpic(&h->er.cur_pic, h->cur_pic_ptr); + ff_er_frame_end(&h->er); + } +#endif /* CONFIG_ERROR_RESILIENCE */ + + if (!in_setup && !h->droppable) + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, + h->picture_structure == PICT_BOTTOM_FIELD); + emms_c(); + + h->current_slice = 0; + + return err; +} diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index 603f1681e..970733289 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -25,6 +25,8 @@ * @author Michael Niedermayer */ +#include + #include "libavutil/imgutils.h" #include "internal.h" #include "avcodec.h" @@ -213,7 +215,7 @@ static inline int decode_vui_parameters(H264Context *h, SPS *sps) sps->time_scale = get_bits_long(&h->gb, 32); if (!sps->num_units_in_tick || !sps->time_scale) { av_log(h->avctx, AV_LOG_ERROR, - "time_scale/num_units_in_tick invalid or unsupported (%d/%d)\n", + "time_scale/num_units_in_tick invalid or unsupported (%"PRIu32"/%"PRIu32")\n", sps->time_scale, sps->num_units_in_tick); return AVERROR_INVALIDDATA; } @@ -335,7 +337,7 @@ int ff_h264_decode_seq_parameter_set(H264Context *h) constraint_set_flags |= get_bits1(&h->gb) << 3; // constraint_set3_flag constraint_set_flags |= get_bits1(&h->gb) << 4; // constraint_set4_flag constraint_set_flags |= get_bits1(&h->gb) << 5; // constraint_set5_flag - get_bits(&h->gb, 2); // reserved + skip_bits(&h->gb, 2); // reserved_zero_2bits level_idc = get_bits(&h->gb, 8); sps_id = get_ue_golomb_31(&h->gb); @@ -359,11 +361,17 @@ int ff_h264_decode_seq_parameter_set(H264Context *h) sps->scaling_matrix_present = 0; sps->colorspace = 2; //AVCOL_SPC_UNSPECIFIED - if (sps->profile_idc == 100 || sps->profile_idc == 110 || - sps->profile_idc == 122 || sps->profile_idc == 244 || - sps->profile_idc == 44 || sps->profile_idc == 83 || - sps->profile_idc == 86 || sps->profile_idc == 118 || - sps->profile_idc == 128 || sps->profile_idc == 144) { + if (sps->profile_idc == 100 || // High profile + sps->profile_idc == 110 || // High10 profile + sps->profile_idc == 122 || // High422 profile + sps->profile_idc == 244 || // High444 Predictive profile + sps->profile_idc == 44 || // Cavlc444 profile + sps->profile_idc == 83 || // Scalable Constrained High profile (SVC) + sps->profile_idc == 86 || // Scalable High Intra profile (SVC) + sps->profile_idc == 118 || // Stereo High profile (MVC) + 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); if (sps->chroma_format_idc > 3U) { avpriv_request_sample(h->avctx, "chroma_format_idc %u", @@ -425,7 +433,7 @@ int ff_h264_decode_seq_parameter_set(H264Context *h) if ((unsigned)sps->poc_cycle_length >= FF_ARRAY_ELEMS(sps->offset_for_ref_frame)) { av_log(h->avctx, AV_LOG_ERROR, - "poc_cycle_length overflow %u\n", sps->poc_cycle_length); + "poc_cycle_length overflow %d\n", sps->poc_cycle_length); goto fail; } @@ -439,7 +447,7 @@ int ff_h264_decode_seq_parameter_set(H264Context *h) sps->ref_frame_count = get_ue_golomb_31(&h->gb); if (h->avctx->codec_tag == MKTAG('S', 'M', 'V', '2')) sps->ref_frame_count = FFMAX(2, sps->ref_frame_count); - if (sps->ref_frame_count > MAX_PICTURE_COUNT - 2 || + if (sps->ref_frame_count > H264_MAX_PICTURE_COUNT - 2 || sps->ref_frame_count > 16U) { av_log(h->avctx, AV_LOG_ERROR, "too many reference frames %d\n", sps->ref_frame_count); @@ -480,7 +488,7 @@ int ff_h264_decode_seq_parameter_set(H264Context *h) if (h->avctx->flags2 & CODEC_FLAG2_IGNORE_CROP) { av_log(h->avctx, AV_LOG_DEBUG, "discarding sps cropping, original " - "values are l:%u r:%u t:%u b:%u\n", + "values are l:%d r:%d t:%d b:%d\n", crop_left, crop_right, crop_top, crop_bottom); sps->crop_left = @@ -540,7 +548,7 @@ int ff_h264_decode_seq_parameter_set(H264Context *h) if (h->avctx->debug & FF_DEBUG_PICT_INFO) { static const char csp[4][5] = { "Gray", "420", "422", "444" }; av_log(h->avctx, AV_LOG_DEBUG, - "sps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%d/%d/%d/%d %s %s %d/%d b%d reo:%d\n", + "sps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%u/%u/%u/%u %s %s %"PRId32"/%"PRId32" b%d reo:%d\n", sps_id, sps->profile_idc, sps->level_idc, sps->poc_type, sps->ref_frame_count, @@ -709,7 +717,7 @@ int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length) if (h->avctx->debug & FF_DEBUG_PICT_INFO) { av_log(h->avctx, AV_LOG_DEBUG, - "pps:%u sps:%u %s slice_groups:%d ref:%d/%d %s qp:%d/%d/%d/%d %s %s %s %s\n", + "pps:%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", pps->slice_group_count, diff --git a/libavcodec/h264_refs.c b/libavcodec/h264_refs.c index 1cd8a6dfd..de1f60a41 100644 --- a/libavcodec/h264_refs.c +++ b/libavcodec/h264_refs.c @@ -25,11 +25,14 @@ * @author Michael Niedermayer */ +#include + #include "libavutil/avassert.h" #include "internal.h" #include "avcodec.h" #include "h264.h" #include "golomb.h" +#include "mpegutils.h" #include @@ -41,7 +44,7 @@ do {\ } while (0) -static void pic_as_field(Picture *pic, const int parity){ +static void pic_as_field(H264Picture *pic, const int parity){ int i; for (i = 0; i < 4; ++i) { if (parity == PICT_BOTTOM_FIELD) @@ -52,7 +55,7 @@ static void pic_as_field(Picture *pic, const int parity){ pic->poc= pic->field_poc[parity == PICT_BOTTOM_FIELD]; } -static int split_field_copy(Picture *dest, Picture *src, int parity, int id_add) +static int split_field_copy(H264Picture *dest, H264Picture *src, int parity, int id_add) { int match = !!(src->reference & parity); @@ -68,8 +71,8 @@ static int split_field_copy(Picture *dest, Picture *src, int parity, int id_add) return match; } -static int build_def_list(Picture *def, int def_len, - Picture **in, int len, int is_long, int sel) +static int build_def_list(H264Picture *def, int def_len, + H264Picture **in, int len, int is_long, int sel) { int i[2] = { 0 }; int index = 0; @@ -94,7 +97,7 @@ static int build_def_list(Picture *def, int def_len, return index; } -static int add_sorted(Picture **sorted, Picture **src, int len, int limit, int dir) +static int add_sorted(H264Picture **sorted, H264Picture **src, int len, int limit, int dir) { int i, best_poc; int out_i = 0; @@ -121,7 +124,7 @@ int ff_h264_fill_default_ref_list(H264Context *h) int i, len; if (h->slice_type_nos == AV_PICTURE_TYPE_B) { - Picture *sorted[32]; + H264Picture *sorted[32]; int cur_poc, list; int lens[2]; @@ -143,7 +146,7 @@ int ff_h264_fill_default_ref_list(H264Context *h) av_assert0(len <= 32); if (len < h->ref_count[list]) - memset(&h->default_ref_list[list][len], 0, sizeof(Picture) * (h->ref_count[list] - len)); + memset(&h->default_ref_list[list][len], 0, sizeof(H264Picture) * (h->ref_count[list] - len)); lens[list] = len; } @@ -152,7 +155,7 @@ int ff_h264_fill_default_ref_list(H264Context *h) h->default_ref_list[0][i].f.buf[0]->buffer == h->default_ref_list[1][i].f.buf[0]->buffer; i++); if (i == lens[0]) { - Picture tmp; + 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); @@ -167,7 +170,7 @@ int ff_h264_fill_default_ref_list(H264Context *h) av_assert0(len <= 32); if (len < h->ref_count[0]) - memset(&h->default_ref_list[0][len], 0, sizeof(Picture) * (h->ref_count[0] - len)); + 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++) { @@ -225,16 +228,16 @@ int ff_h264_decode_ref_pic_list_reordering(H264Context *h) for (i = 0; i < h->ref_count[list]; i++) COPY_PICTURE(&h->ref_list[list][i], &h->default_ref_list[list][i]); - if (get_bits1(&h->gb)) { + if (get_bits1(&h->gb)) { // ref_pic_list_modification_flag_l[01] int pred = h->curr_pic_num; for (index = 0; ; index++) { - unsigned int reordering_of_pic_nums_idc = get_ue_golomb_31(&h->gb); + unsigned int modification_of_pic_nums_idc = get_ue_golomb_31(&h->gb); unsigned int pic_id; int i; - Picture *ref = NULL; + H264Picture *ref = NULL; - if (reordering_of_pic_nums_idc == 3) + if (modification_of_pic_nums_idc == 3) break; if (index >= h->ref_count[list]) { @@ -242,7 +245,7 @@ int ff_h264_decode_ref_pic_list_reordering(H264Context *h) return -1; } - switch (reordering_of_pic_nums_idc) { + switch (modification_of_pic_nums_idc) { case 0: case 1: { const unsigned int abs_diff_pic_num = get_ue_golomb(&h->gb) + 1; @@ -254,7 +257,7 @@ int ff_h264_decode_ref_pic_list_reordering(H264Context *h) return AVERROR_INVALIDDATA; } - if (reordering_of_pic_nums_idc == 0) + if (modification_of_pic_nums_idc == 0) pred -= abs_diff_pic_num; else pred += abs_diff_pic_num; @@ -298,14 +301,15 @@ int ff_h264_decode_ref_pic_list_reordering(H264Context *h) } default: av_log(h->avctx, AV_LOG_ERROR, - "illegal reordering_of_pic_nums_idc\n"); + "illegal modification_of_pic_nums_idc %u\n", + modification_of_pic_nums_idc); return AVERROR_INVALIDDATA; } if (i < 0) { av_log(h->avctx, AV_LOG_ERROR, "reference picture missing during reorder\n"); - memset(&h->ref_list[list][index], 0, sizeof(Picture)); // FIXME + memset(&h->ref_list[list][index], 0, sizeof(H264Picture)); // FIXME } else { for (i = index; i + 1 < h->ref_count[list]; i++) { if (ref->long_ref == h->ref_list[list][i].long_ref && @@ -349,8 +353,8 @@ void ff_h264_fill_mbaff_ref_list(H264Context *h) int list, i, j; for (list = 0; list < h->list_count; list++) { for (i = 0; i < h->ref_count[list]; i++) { - Picture *frame = &h->ref_list[list][i]; - Picture *field = &h->ref_list[list][16 + 2 * i]; + 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; @@ -383,7 +387,7 @@ void ff_h264_fill_mbaff_ref_list(H264Context *h) * for display purposes) zero if one of the fields remains in * reference */ -static inline int unreference_pic(H264Context *h, Picture *pic, int refmask) +static inline int unreference_pic(H264Context *h, H264Picture *pic, int refmask) { int i; if (pic->reference &= refmask) { @@ -399,19 +403,19 @@ static inline int unreference_pic(H264Context *h, Picture *pic, int refmask) } /** - * Find a Picture in the short term reference list by frame number. + * Find a H264Picture in the short term reference list by frame number. * @param frame_num frame number to search for * @param idx the index into h->short_ref where returned picture is found * undefined if no picture found. * @return pointer to the found picture, or NULL if no pic with the provided * frame number is found */ -static Picture *find_short(H264Context *h, int frame_num, int *idx) +static H264Picture *find_short(H264Context *h, int frame_num, int *idx) { int i; for (i = 0; i < h->short_ref_count; i++) { - Picture *pic = h->short_ref[i]; + H264Picture *pic = h->short_ref[i]; if (h->avctx->debug & FF_DEBUG_MMCO) av_log(h->avctx, AV_LOG_DEBUG, "%d %d %p\n", i, pic->frame_num, pic); if (pic->frame_num == frame_num) { @@ -434,16 +438,16 @@ static void remove_short_at_index(H264Context *h, int i) h->short_ref[i] = NULL; if (--h->short_ref_count) memmove(&h->short_ref[i], &h->short_ref[i + 1], - (h->short_ref_count - i) * sizeof(Picture*)); + (h->short_ref_count - i) * sizeof(H264Picture*)); } /** * * @return the removed picture or NULL if an error occurs */ -static Picture *remove_short(H264Context *h, int frame_num, int ref_mask) +static H264Picture *remove_short(H264Context *h, int frame_num, int ref_mask) { - Picture *pic; + H264Picture *pic; int i; if (h->avctx->debug & FF_DEBUG_MMCO) @@ -463,9 +467,9 @@ static Picture *remove_short(H264Context *h, int frame_num, int ref_mask) * that list. * @return the removed picture or NULL if an error occurs */ -static Picture *remove_long(H264Context *h, int i, int ref_mask) +static H264Picture *remove_long(H264Context *h, int i, int ref_mask) { - Picture *pic; + H264Picture *pic; pic = h->long_ref[i]; if (pic) { @@ -508,8 +512,8 @@ static void print_short_term(H264Context *h) if (h->avctx->debug & FF_DEBUG_MMCO) { av_log(h->avctx, AV_LOG_DEBUG, "short term list:\n"); for (i = 0; i < h->short_ref_count; i++) { - Picture *pic = h->short_ref[i]; - av_log(h->avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n", + 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]); } } @@ -524,9 +528,9 @@ static void print_long_term(H264Context *h) if (h->avctx->debug & FF_DEBUG_MMCO) { av_log(h->avctx, AV_LOG_DEBUG, "long term list:\n"); for (i = 0; i < 16; i++) { - Picture *pic = h->long_ref[i]; + H264Picture *pic = h->long_ref[i]; if (pic) { - av_log(h->avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n", + av_log(h->avctx, AV_LOG_DEBUG, "%"PRIu32" fn:%d poc:%d %p\n", i, pic->frame_num, pic->poc, pic->f.data[0]); } } @@ -551,7 +555,7 @@ static int check_opcodes(MMCO *mmco1, MMCO *mmco2, int n_mmcos) 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; + int mmco_index = 0, i = 0; if (h->short_ref_count && h->long_ref_count + h->short_ref_count >= h->sps.ref_frame_count && @@ -585,7 +589,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count) int i, av_uninit(j); int pps_count; int current_ref_assigned = 0, err = 0; - Picture *av_uninit(pic); + H264Picture *av_uninit(pic); if ((h->avctx->debug & FF_DEBUG_MMCO) && mmco_count == 0) av_log(h->avctx, AV_LOG_DEBUG, "no mmco here\n"); @@ -719,7 +723,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count) if (h->short_ref_count) memmove(&h->short_ref[1], &h->short_ref[0], - h->short_ref_count * sizeof(Picture*)); + h->short_ref_count * sizeof(H264Picture*)); h->short_ref[0] = h->cur_pic_ptr; h->short_ref_count++; diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c index 88bf0f497..aa889b8bb 100644 --- a/libavcodec/h264_sei.c +++ b/libavcodec/h264_sei.c @@ -41,6 +41,7 @@ void ff_h264_reset_sei(H264Context *h) h->sei_cpb_removal_delay = -1; h->sei_buffering_period_present = 0; h->sei_frame_packing_present = 0; + h->sei_display_orientation_present = 0; } static int decode_picture_timing(H264Context *h) @@ -262,6 +263,22 @@ static int decode_frame_packing_arrangement(H264Context *h) return 0; } +static int decode_display_orientation(H264Context *h) +{ + h->sei_display_orientation_present = !get_bits1(&h->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 + + 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 + } + + return 0; +} + int ff_h264_decode_sei(H264Context *h) { while (get_bits_left(&h->gb) > 16) { @@ -322,6 +339,11 @@ int ff_h264_decode_sei(H264Context *h) if (ret < 0) return ret; break; + case SEI_TYPE_DISPLAY_ORIENTATION: + ret = decode_display_orientation(h); + if (ret < 0) + return ret; + break; default: av_log(h->avctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type); } diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c new file mode 100644 index 000000000..ded26f846 --- /dev/null +++ b/libavcodec/h264_slice.c @@ -0,0 +1,2576 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... decoder + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 codec. + * @author Michael Niedermayer + */ + +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "libavutil/timer.h" +#include "internal.h" +#include "cabac.h" +#include "cabac_functions.h" +#include "dsputil.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 "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, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + 0, 1, 2, 3, +}; + +static const uint8_t div6[QP_MAX_NUM + 1] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, + 10,10,10,11,11,11,11,11,11,12,12,12,12,12,12,13,13,13, 13, 13, 13, + 14,14,14,14, +}; + +static const uint8_t field_scan[16+1] = { + 0 + 0 * 4, 0 + 1 * 4, 1 + 0 * 4, 0 + 2 * 4, + 0 + 3 * 4, 1 + 1 * 4, 1 + 2 * 4, 1 + 3 * 4, + 2 + 0 * 4, 2 + 1 * 4, 2 + 2 * 4, 2 + 3 * 4, + 3 + 0 * 4, 3 + 1 * 4, 3 + 2 * 4, 3 + 3 * 4, +}; + +static const uint8_t field_scan8x8[64+1] = { + 0 + 0 * 8, 0 + 1 * 8, 0 + 2 * 8, 1 + 0 * 8, + 1 + 1 * 8, 0 + 3 * 8, 0 + 4 * 8, 1 + 2 * 8, + 2 + 0 * 8, 1 + 3 * 8, 0 + 5 * 8, 0 + 6 * 8, + 0 + 7 * 8, 1 + 4 * 8, 2 + 1 * 8, 3 + 0 * 8, + 2 + 2 * 8, 1 + 5 * 8, 1 + 6 * 8, 1 + 7 * 8, + 2 + 3 * 8, 3 + 1 * 8, 4 + 0 * 8, 3 + 2 * 8, + 2 + 4 * 8, 2 + 5 * 8, 2 + 6 * 8, 2 + 7 * 8, + 3 + 3 * 8, 4 + 1 * 8, 5 + 0 * 8, 4 + 2 * 8, + 3 + 4 * 8, 3 + 5 * 8, 3 + 6 * 8, 3 + 7 * 8, + 4 + 3 * 8, 5 + 1 * 8, 6 + 0 * 8, 5 + 2 * 8, + 4 + 4 * 8, 4 + 5 * 8, 4 + 6 * 8, 4 + 7 * 8, + 5 + 3 * 8, 6 + 1 * 8, 6 + 2 * 8, 5 + 4 * 8, + 5 + 5 * 8, 5 + 6 * 8, 5 + 7 * 8, 6 + 3 * 8, + 7 + 0 * 8, 7 + 1 * 8, 6 + 4 * 8, 6 + 5 * 8, + 6 + 6 * 8, 6 + 7 * 8, 7 + 2 * 8, 7 + 3 * 8, + 7 + 4 * 8, 7 + 5 * 8, 7 + 6 * 8, 7 + 7 * 8, +}; + +static const uint8_t field_scan8x8_cavlc[64+1] = { + 0 + 0 * 8, 1 + 1 * 8, 2 + 0 * 8, 0 + 7 * 8, + 2 + 2 * 8, 2 + 3 * 8, 2 + 4 * 8, 3 + 3 * 8, + 3 + 4 * 8, 4 + 3 * 8, 4 + 4 * 8, 5 + 3 * 8, + 5 + 5 * 8, 7 + 0 * 8, 6 + 6 * 8, 7 + 4 * 8, + 0 + 1 * 8, 0 + 3 * 8, 1 + 3 * 8, 1 + 4 * 8, + 1 + 5 * 8, 3 + 1 * 8, 2 + 5 * 8, 4 + 1 * 8, + 3 + 5 * 8, 5 + 1 * 8, 4 + 5 * 8, 6 + 1 * 8, + 5 + 6 * 8, 7 + 1 * 8, 6 + 7 * 8, 7 + 5 * 8, + 0 + 2 * 8, 0 + 4 * 8, 0 + 5 * 8, 2 + 1 * 8, + 1 + 6 * 8, 4 + 0 * 8, 2 + 6 * 8, 5 + 0 * 8, + 3 + 6 * 8, 6 + 0 * 8, 4 + 6 * 8, 6 + 2 * 8, + 5 + 7 * 8, 6 + 4 * 8, 7 + 2 * 8, 7 + 6 * 8, + 1 + 0 * 8, 1 + 2 * 8, 0 + 6 * 8, 3 + 0 * 8, + 1 + 7 * 8, 3 + 2 * 8, 2 + 7 * 8, 4 + 2 * 8, + 3 + 7 * 8, 5 + 2 * 8, 4 + 7 * 8, 5 + 4 * 8, + 6 + 3 * 8, 6 + 5 * 8, 7 + 3 * 8, 7 + 7 * 8, +}; + +// zigzag_scan8x8_cavlc[i] = zigzag_scan8x8[(i/4) + 16*(i%4)] +static const uint8_t zigzag_scan8x8_cavlc[64+1] = { + 0 + 0 * 8, 1 + 1 * 8, 1 + 2 * 8, 2 + 2 * 8, + 4 + 1 * 8, 0 + 5 * 8, 3 + 3 * 8, 7 + 0 * 8, + 3 + 4 * 8, 1 + 7 * 8, 5 + 3 * 8, 6 + 3 * 8, + 2 + 7 * 8, 6 + 4 * 8, 5 + 6 * 8, 7 + 5 * 8, + 1 + 0 * 8, 2 + 0 * 8, 0 + 3 * 8, 3 + 1 * 8, + 3 + 2 * 8, 0 + 6 * 8, 4 + 2 * 8, 6 + 1 * 8, + 2 + 5 * 8, 2 + 6 * 8, 6 + 2 * 8, 5 + 4 * 8, + 3 + 7 * 8, 7 + 3 * 8, 4 + 7 * 8, 7 + 6 * 8, + 0 + 1 * 8, 3 + 0 * 8, 0 + 4 * 8, 4 + 0 * 8, + 2 + 3 * 8, 1 + 5 * 8, 5 + 1 * 8, 5 + 2 * 8, + 1 + 6 * 8, 3 + 5 * 8, 7 + 1 * 8, 4 + 5 * 8, + 4 + 6 * 8, 7 + 4 * 8, 5 + 7 * 8, 6 + 7 * 8, + 0 + 2 * 8, 2 + 1 * 8, 1 + 3 * 8, 5 + 0 * 8, + 1 + 4 * 8, 2 + 4 * 8, 6 + 0 * 8, 4 + 3 * 8, + 0 + 7 * 8, 4 + 4 * 8, 7 + 2 * 8, 3 + 6 * 8, + 5 + 5 * 8, 6 + 5 * 8, 6 + 6 * 8, 7 + 7 * 8, +}; + +static const uint8_t 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 && + (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) +{ + int alloc_size = FFALIGN(FFABS(linesize) + 32, 32); + + if (h->bipred_scratchpad) + return 0; + + h->bipred_scratchpad = av_malloc(16 * 6 * alloc_size); + // edge emu needs blocksize + filter length - 1 + // (= 21x21 for h264) + h->edge_emu_buffer = av_mallocz(alloc_size * 2 * 21); + + if (!h->bipred_scratchpad || !h->edge_emu_buffer) { + av_freep(&h->bipred_scratchpad); + av_freep(&h->edge_emu_buffer); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int init_table_pools(H264Context *h) +{ + const int big_mb_num = h->mb_stride * (h->mb_height + 1) + 1; + const int mb_array_size = h->mb_stride * h->mb_height; + const int b4_stride = h->mb_width * 4 + 1; + const int b4_array_size = b4_stride * h->mb_height * 4; + + h->qscale_table_pool = av_buffer_pool_init(big_mb_num + h->mb_stride, + av_buffer_allocz); + h->mb_type_pool = av_buffer_pool_init((big_mb_num + h->mb_stride) * + sizeof(uint32_t), av_buffer_allocz); + h->motion_val_pool = av_buffer_pool_init(2 * (b4_array_size + 4) * + sizeof(int16_t), av_buffer_allocz); + h->ref_index_pool = av_buffer_pool_init(4 * mb_array_size, av_buffer_allocz); + + if (!h->qscale_table_pool || !h->mb_type_pool || !h->motion_val_pool || + !h->ref_index_pool) { + av_buffer_pool_uninit(&h->qscale_table_pool); + av_buffer_pool_uninit(&h->mb_type_pool); + av_buffer_pool_uninit(&h->motion_val_pool); + av_buffer_pool_uninit(&h->ref_index_pool); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int alloc_picture(H264Context *h, H264Picture *pic) +{ + int i, ret = 0; + + av_assert0(!pic->f.data[0]); + + pic->tf.f = &pic->f; + ret = ff_thread_get_buffer(h->avctx, &pic->tf, pic->reference ? + AV_GET_BUFFER_FLAG_REF : 0); + if (ret < 0) + goto fail; + + h->linesize = pic->f.linesize[0]; + h->uvlinesize = pic->f.linesize[1]; + pic->crop = h->sps.crop; + pic->crop_top = h->sps.crop_top; + pic->crop_left= h->sps.crop_left; + + if (h->avctx->hwaccel) { + const AVHWAccel *hwaccel = h->avctx->hwaccel; + av_assert0(!pic->hwaccel_picture_private); + if (hwaccel->frame_priv_data_size) { + pic->hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size); + if (!pic->hwaccel_priv_buf) + return AVERROR(ENOMEM); + pic->hwaccel_picture_private = pic->hwaccel_priv_buf->data; + } + } + if (!h->avctx->hwaccel && CONFIG_GRAY && h->flags & CODEC_FLAG_GRAY && pic->f.data[2]) { + int h_chroma_shift, v_chroma_shift; + av_pix_fmt_get_chroma_sub_sample(pic->f.format, + &h_chroma_shift, &v_chroma_shift); + + for(i=0; iavctx->height, v_chroma_shift); i++) { + memset(pic->f.data[1] + pic->f.linesize[1]*i, + 0x80, FF_CEIL_RSHIFT(h->avctx->width, h_chroma_shift)); + memset(pic->f.data[2] + pic->f.linesize[2]*i, + 0x80, FF_CEIL_RSHIFT(h->avctx->width, h_chroma_shift)); + } + } + + if (!h->qscale_table_pool) { + ret = init_table_pools(h); + if (ret < 0) + goto fail; + } + + pic->qscale_table_buf = av_buffer_pool_get(h->qscale_table_pool); + pic->mb_type_buf = av_buffer_pool_get(h->mb_type_pool); + if (!pic->qscale_table_buf || !pic->mb_type_buf) + goto fail; + + pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * h->mb_stride + 1; + pic->qscale_table = pic->qscale_table_buf->data + 2 * h->mb_stride + 1; + + for (i = 0; i < 2; i++) { + pic->motion_val_buf[i] = av_buffer_pool_get(h->motion_val_pool); + pic->ref_index_buf[i] = av_buffer_pool_get(h->ref_index_pool); + if (!pic->motion_val_buf[i] || !pic->ref_index_buf[i]) + goto fail; + + pic->motion_val[i] = (int16_t (*)[2])pic->motion_val_buf[i]->data + 4; + pic->ref_index[i] = pic->ref_index_buf[i]->data; + } + + return 0; +fail: + ff_h264_unref_picture(h, pic); + return (ret < 0) ? ret : AVERROR(ENOMEM); +} + +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)) + return 1; + return 0; +} + +static int find_unused_picture(H264Context *h) +{ + int i; + + for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) { + if (pic_is_unused(h, &h->DPB[i])) + break; + } + 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) +{ + int i, j, q, x; + const int max_qp = 51 + 6 * (h->sps.bit_depth_luma - 8); + + for (i = 0; i < 6; i++) { + h->dequant8_coeff[i] = h->dequant8_buffer[i]; + for (j = 0; j < i; j++) + if (!memcmp(h->pps.scaling_matrix8[j], h->pps.scaling_matrix8[i], + 64 * sizeof(uint8_t))) { + h->dequant8_coeff[i] = h->dequant8_buffer[j]; + break; + } + if (j < i) + continue; + + for (q = 0; q < max_qp + 1; q++) { + int shift = div6[q]; + int idx = rem6[q]; + for (x = 0; x < 64; x++) + h->dequant8_coeff[i][q][(x >> 3) | ((x & 7) << 3)] = + ((uint32_t)dequant8_coeff_init[idx][dequant8_coeff_init_scan[((x >> 1) & 12) | (x & 3)]] * + h->pps.scaling_matrix8[i][x]) << shift; + } + } +} + +static void init_dequant4_coeff_table(H264Context *h) +{ + int i, j, q, x; + const int max_qp = 51 + 6 * (h->sps.bit_depth_luma - 8); + for (i = 0; i < 6; i++) { + h->dequant4_coeff[i] = h->dequant4_buffer[i]; + for (j = 0; j < i; j++) + if (!memcmp(h->pps.scaling_matrix4[j], h->pps.scaling_matrix4[i], + 16 * sizeof(uint8_t))) { + h->dequant4_coeff[i] = h->dequant4_buffer[j]; + break; + } + if (j < i) + continue; + + for (q = 0; q < max_qp + 1; q++) { + int shift = div6[q] + 2; + int idx = rem6[q]; + for (x = 0; x < 16; x++) + h->dequant4_coeff[i][q][(x >> 2) | ((x << 2) & 0xF)] = + ((uint32_t)dequant4_coeff_init[idx][(x & 1) + ((x >> 2) & 1)] * + h->pps.scaling_matrix4[i][x]) << shift; + } + } +} + +void h264_init_dequant_tables(H264Context *h) +{ + int i, x; + init_dequant4_coeff_table(h); + memset(h->dequant8_coeff, 0, sizeof(h->dequant8_coeff)); + + 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; + } +} + +/** + * 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); +} + +#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) ? \ + &(new_ctx)->DPB[(pic) - (old_ctx)->DPB] : NULL) + +static void copy_picture_range(H264Picture **to, H264Picture **from, int count, + H264Context *new_base, + H264Context *old_base) +{ + int i; + + for (i = 0; i < count; i++) { + assert((IN_RANGE(from[i], old_base, sizeof(*old_base)) || + IN_RANGE(from[i], old_base->DPB, + sizeof(H264Picture) * H264_MAX_PICTURE_COUNT) || + !from[i])); + to[i] = REBASE_PICTURE(from[i], new_base, old_base); + } +} + +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); + +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 i, ret; + + if (dst == src) + return 0; + + if (inited && + (h->width != h1->width || + h->height != h1->height || + h->mb_width != h1->mb_width || + h->mb_height != h1->mb_height || + h->sps.bit_depth_luma != h1->sps.bit_depth_luma || + h->sps.chroma_format_idc != h1->sps.chroma_format_idc || + h->sps.colorspace != h1->sps.colorspace)) { + + /* set bits_per_raw_sample to the previous value. the check for changed + * bit depth in h264_set_parameter_from_sps() uses it and sets it to + * the current value */ + h->avctx->bits_per_raw_sample = h->sps.bit_depth_luma; + + av_freep(&h->bipred_scratchpad); + + h->width = h1->width; + h->height = h1->height; + h->mb_height = h1->mb_height; + h->mb_width = h1->mb_width; + h->mb_num = h1->mb_num; + h->mb_stride = h1->mb_stride; + h->b_stride = h1->b_stride; + // SPS/PPS + 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; + + if ((err = h264_slice_header_init(h, 1)) < 0) { + av_log(h->avctx, AV_LOG_ERROR, "h264_slice_header_init() failed"); + return err; + } + context_reinitialized = 1; + +#if 0 + h264_set_parameter_from_sps(h); + //Note we set context_reinitialized which will cause h264_set_parameter_from_sps to be reexecuted + h->cur_chroma_format_idc = h1->cur_chroma_format_idc; +#endif + } + /* update linesize on resize for h264. The h264 decoder doesn't + * necessarily call ff_MPV_frame_start in the new thread */ + h->linesize = h1->linesize; + h->uvlinesize = h1->uvlinesize; + + /* copy block_offset since frame_start may not be called */ + memcpy(h->block_offset, h1->block_offset, sizeof(h->block_offset)); + + if (!inited) { + for (i = 0; i < MAX_SPS_COUNT; i++) + av_freep(h->sps_buffers + i); + + for (i = 0; i < MAX_PPS_COUNT; i++) + av_freep(h->pps_buffers + i); + + av_freep(&h->rbsp_buffer[0]); + av_freep(&h->rbsp_buffer[1]); + memcpy(h, h1, offsetof(H264Context, intra_pcm_ptr)); + memcpy(&h->cabac, &h1->cabac, + sizeof(H264Context) - offsetof(H264Context, cabac)); + av_assert0((void*)&h->cabac == &h->mb_padding + 1); + + memset(h->sps_buffers, 0, sizeof(h->sps_buffers)); + memset(h->pps_buffers, 0, sizeof(h->pps_buffers)); + + memset(&h->er, 0, sizeof(h->er)); + memset(&h->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)); + memset(&h->cur_pic, 0, sizeof(h->cur_pic)); + + 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; + for (i = 0; i < 2; i++) { + h->rbsp_buffer[i] = NULL; + h->rbsp_buffer_size[i] = 0; + } + + if (h1->context_initialized) { + 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; + + 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; + } + } + + h->bipred_scratchpad = NULL; + h->edge_emu_buffer = NULL; + + h->thread_context[0] = h; + h->context_initialized = h1->context_initialized; + } + + h->avctx->coded_height = h1->avctx->coded_height; + h->avctx->coded_width = h1->avctx->coded_width; + h->avctx->width = h1->avctx->width; + h->avctx->height = h1->avctx->height; + h->coded_picture_number = h1->coded_picture_number; + h->first_field = h1->first_field; + h->picture_structure = h1->picture_structure; + h->qscale = h1->qscale; + h->droppable = h1->droppable; + h->low_delay = h1->low_delay; + + for (i = 0; h->DPB && i < H264_MAX_PICTURE_COUNT; i++) { + ff_h264_unref_picture(h, &h->DPB[i]); + if (h1->DPB && 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] && (ret = ff_h264_ref_picture(h, &h->cur_pic, &h1->cur_pic)) < 0) + return ret; + + h->workaround_bugs = h1->workaround_bugs; + h->low_delay = h1->low_delay; + h->droppable = h1->droppable; + + // extradata/NAL handling + h->is_avc = h1->is_avc; + + // SPS/PPS + 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]); + + for (i = 0; i < 6; i++) + h->dequant8_coeff[i] = h->dequant8_buffer[0] + + (h1->dequant8_coeff[i] - h1->dequant8_buffer[0]); + + h->dequant_coeff_pps = h1->dequant_coeff_pps; + + // POC timing + copy_fields(h, h1, poc_lsb, redundant_pic_count); + + // reference lists + copy_fields(h, h1, short_ref, cabac_init_idc); + + copy_picture_range(h->short_ref, h1->short_ref, 32, h, h1); + copy_picture_range(h->long_ref, h1->long_ref, 32, h, h1); + copy_picture_range(h->delayed_pic, h1->delayed_pic, + MAX_DELAYED_PIC_COUNT + 2, h, h1); + + h->frame_recovered = h1->frame_recovered; + + 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; + } + h->prev_frame_num_offset = h->frame_num_offset; + h->prev_frame_num = h->frame_num; + h->outputed_poc = h->next_outputed_poc; + + h->recovery_frame = h1->recovery_frame; + + return err; +} + +static int h264_frame_start(H264Context *h) +{ + H264Picture *pic; + int i, ret; + const int pixel_shift = h->pixel_shift; + int c[4] = { + 1<<(h->sps.bit_depth_luma-1), + 1<<(h->sps.bit_depth_chroma-1), + 1<<(h->sps.bit_depth_chroma-1), + -1 + }; + + if (!ff_thread_can_start_frame(h->avctx)) { + av_log(h->avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n"); + return -1; + } + + release_unused_pictures(h, 1); + h->cur_pic_ptr = NULL; + + i = find_unused_picture(h); + if (i < 0) { + av_log(h->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return i; + } + pic = &h->DPB[i]; + + pic->reference = h->droppable ? 0 : h->picture_structure; + pic->f.coded_picture_number = h->coded_picture_number++; + pic->field_picture = h->picture_structure != PICT_FRAME; + + /* + * Zero key_frame here; IDR markings per slice in frame or fields are ORed + * in later. + * See decode_nal_units(). + */ + pic->f.key_frame = 0; + pic->mmco_reset = 0; + pic->recovered = 0; + pic->invalid_gap = 0; + pic->sei_recovery_frame_cnt = h->sei_recovery_frame_cnt; + + if ((ret = alloc_picture(h, pic)) < 0) + return ret; + if(!h->frame_recovered && !h->avctx->hwaccel && + !(h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)) + avpriv_color_frame(&pic->f, c); + + h->cur_pic_ptr = pic; + ff_h264_unref_picture(h, &h->cur_pic); + if (CONFIG_ERROR_RESILIENCE) { + ff_h264_set_erpic(&h->er.cur_pic, NULL); + } + + if ((ret = ff_h264_ref_picture(h, &h->cur_pic, h->cur_pic_ptr)) < 0) + return ret; + + if (CONFIG_ERROR_RESILIENCE) { + ff_er_frame_start(&h->er); + ff_h264_set_erpic(&h->er.last_pic, NULL); + ff_h264_set_erpic(&h->er.next_pic, NULL); + } + + assert(h->linesize && h->uvlinesize); + + for (i = 0; i < 16; i++) { + h->block_offset[i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * h->linesize * ((scan8[i] - scan8[0]) >> 3); + h->block_offset[48 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * h->linesize * ((scan8[i] - scan8[0]) >> 3); + } + for (i = 0; i < 16; i++) { + h->block_offset[16 + i] = + h->block_offset[32 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * h->uvlinesize * ((scan8[i] - scan8[0]) >> 3); + h->block_offset[48 + 16 + i] = + h->block_offset[48 + 32 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * h->uvlinesize * ((scan8[i] - scan8[0]) >> 3); + } + + /* We mark the current picture as non-reference after allocating it, so + * that if we break out due to an error it can be released automatically + * in the next ff_MPV_frame_start(). + */ + h->cur_pic_ptr->reference = 0; + + h->cur_pic_ptr->field_poc[0] = h->cur_pic_ptr->field_poc[1] = INT_MAX; + + h->next_output_pic = NULL; + + assert(h->cur_pic_ptr->long_ref == 0); + + return 0; +} + +static av_always_inline void backup_mb_border(H264Context *h, uint8_t *src_y, + uint8_t *src_cb, uint8_t *src_cr, + int linesize, int uvlinesize, + int simple) +{ + uint8_t *top_border; + int top_idx = 1; + const int pixel_shift = h->pixel_shift; + int chroma444 = CHROMA444(h); + int chroma422 = CHROMA422(h); + + src_y -= linesize; + src_cb -= uvlinesize; + src_cr -= uvlinesize; + + if (!simple && FRAME_MBAFF(h)) { + if (h->mb_y & 1) { + if (!MB_MBAFF(h)) { + top_border = h->top_borders[0][h->mb_x]; + AV_COPY128(top_border, src_y + 15 * linesize); + if (pixel_shift) + AV_COPY128(top_border + 16, src_y + 15 * linesize + 16); + if (simple || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { + if (chroma444) { + if (pixel_shift) { + AV_COPY128(top_border + 32, src_cb + 15 * uvlinesize); + AV_COPY128(top_border + 48, src_cb + 15 * uvlinesize + 16); + AV_COPY128(top_border + 64, src_cr + 15 * uvlinesize); + AV_COPY128(top_border + 80, src_cr + 15 * uvlinesize + 16); + } else { + AV_COPY128(top_border + 16, src_cb + 15 * uvlinesize); + AV_COPY128(top_border + 32, src_cr + 15 * uvlinesize); + } + } else if (chroma422) { + if (pixel_shift) { + AV_COPY128(top_border + 32, src_cb + 15 * uvlinesize); + AV_COPY128(top_border + 48, src_cr + 15 * uvlinesize); + } else { + AV_COPY64(top_border + 16, src_cb + 15 * uvlinesize); + AV_COPY64(top_border + 24, src_cr + 15 * uvlinesize); + } + } else { + if (pixel_shift) { + AV_COPY128(top_border + 32, src_cb + 7 * uvlinesize); + AV_COPY128(top_border + 48, src_cr + 7 * uvlinesize); + } else { + AV_COPY64(top_border + 16, src_cb + 7 * uvlinesize); + AV_COPY64(top_border + 24, src_cr + 7 * uvlinesize); + } + } + } + } + } else if (MB_MBAFF(h)) { + top_idx = 0; + } else + return; + } + + top_border = h->top_borders[top_idx][h->mb_x]; + /* There are two lines saved, the line above the top macroblock + * of a pair, and the line above the bottom macroblock. */ + AV_COPY128(top_border, src_y + 16 * linesize); + if (pixel_shift) + AV_COPY128(top_border + 16, src_y + 16 * linesize + 16); + + if (simple || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { + if (chroma444) { + if (pixel_shift) { + AV_COPY128(top_border + 32, src_cb + 16 * linesize); + AV_COPY128(top_border + 48, src_cb + 16 * linesize + 16); + AV_COPY128(top_border + 64, src_cr + 16 * linesize); + AV_COPY128(top_border + 80, src_cr + 16 * linesize + 16); + } else { + AV_COPY128(top_border + 16, src_cb + 16 * linesize); + AV_COPY128(top_border + 32, src_cr + 16 * linesize); + } + } else if (chroma422) { + if (pixel_shift) { + AV_COPY128(top_border + 32, src_cb + 16 * uvlinesize); + AV_COPY128(top_border + 48, src_cr + 16 * uvlinesize); + } else { + AV_COPY64(top_border + 16, src_cb + 16 * uvlinesize); + AV_COPY64(top_border + 24, src_cr + 16 * uvlinesize); + } + } else { + if (pixel_shift) { + AV_COPY128(top_border + 32, src_cb + 8 * uvlinesize); + AV_COPY128(top_border + 48, src_cr + 8 * uvlinesize); + } else { + AV_COPY64(top_border + 16, src_cb + 8 * uvlinesize); + AV_COPY64(top_border + 24, src_cr + 8 * uvlinesize); + } + } + } +} + +/** + * Initialize implicit_weight table. + * @param field 0/1 initialize the weight for interlaced MBAFF + * -1 initializes the rest + */ +static void implicit_weight_table(H264Context *h, int field) +{ + int ref0, ref1, i, cur_poc, ref_start, ref_count0, ref_count1; + + for (i = 0; i < 2; i++) { + h->luma_weight_flag[i] = 0; + h->chroma_weight_flag[i] = 0; + } + + if (field < 0) { + if (h->picture_structure == PICT_FRAME) { + cur_poc = h->cur_pic_ptr->poc; + } else { + cur_poc = h->cur_pic_ptr->field_poc[h->picture_structure - 1]; + } + if (h->ref_count[0] == 1 && h->ref_count[1] == 1 && !FRAME_MBAFF(h) && + h->ref_list[0][0].poc + h->ref_list[1][0].poc == 2 * cur_poc) { + h->use_weight = 0; + h->use_weight_chroma = 0; + return; + } + ref_start = 0; + ref_count0 = h->ref_count[0]; + ref_count1 = h->ref_count[1]; + } else { + cur_poc = h->cur_pic_ptr->field_poc[field]; + ref_start = 16; + ref_count0 = 16 + 2 * h->ref_count[0]; + ref_count1 = 16 + 2 * h->ref_count[1]; + } + + h->use_weight = 2; + h->use_weight_chroma = 2; + h->luma_log2_weight_denom = 5; + h->chroma_log2_weight_denom = 5; + + for (ref0 = ref_start; ref0 < ref_count0; ref0++) { + int poc0 = h->ref_list[0][ref0].poc; + for (ref1 = ref_start; ref1 < ref_count1; ref1++) { + int w = 32; + if (!h->ref_list[0][ref0].long_ref && !h->ref_list[1][ref1].long_ref) { + int poc1 = h->ref_list[1][ref1].poc; + int td = av_clip(poc1 - poc0, -128, 127); + if (td) { + int tb = av_clip(cur_poc - poc0, -128, 127); + int tx = (16384 + (FFABS(td) >> 1)) / td; + int dist_scale_factor = (tb * tx + 32) >> 8; + if (dist_scale_factor >= -64 && dist_scale_factor <= 128) + w = 64 - dist_scale_factor; + } + } + if (field < 0) { + h->implicit_weight[ref0][ref1][0] = + h->implicit_weight[ref0][ref1][1] = w; + } else { + h->implicit_weight[ref0][ref1][field] = w; + } + } + } +} + +/** + * initialize scan tables + */ +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->field_scan[i] = TRANSPOSE(field_scan[i]); +#undef TRANSPOSE + } + for (i = 0; i < 64; i++) { +#define TRANSPOSE(x) ((x) >> 3) | (((x) & 7) << 3) + h->zigzag_scan8x8[i] = TRANSPOSE(ff_zigzag_direct[i]); + h->zigzag_scan8x8_cavlc[i] = TRANSPOSE(zigzag_scan8x8_cavlc[i]); + h->field_scan8x8[i] = TRANSPOSE(field_scan8x8[i]); + h->field_scan8x8_cavlc[i] = TRANSPOSE(field_scan8x8_cavlc[i]); +#undef TRANSPOSE + } + if (h->sps.transform_bypass) { // FIXME same ugly + memcpy(h->zigzag_scan_q0 , zigzag_scan , sizeof(h->zigzag_scan_q0 )); + memcpy(h->zigzag_scan8x8_q0 , ff_zigzag_direct , sizeof(h->zigzag_scan8x8_q0 )); + memcpy(h->zigzag_scan8x8_cavlc_q0 , zigzag_scan8x8_cavlc , sizeof(h->zigzag_scan8x8_cavlc_q0)); + memcpy(h->field_scan_q0 , field_scan , sizeof(h->field_scan_q0 )); + memcpy(h->field_scan8x8_q0 , field_scan8x8 , sizeof(h->field_scan8x8_q0 )); + memcpy(h->field_scan8x8_cavlc_q0 , field_scan8x8_cavlc , sizeof(h->field_scan8x8_cavlc_q0 )); + } else { + memcpy(h->zigzag_scan_q0 , h->zigzag_scan , sizeof(h->zigzag_scan_q0 )); + memcpy(h->zigzag_scan8x8_q0 , h->zigzag_scan8x8 , sizeof(h->zigzag_scan8x8_q0 )); + memcpy(h->zigzag_scan8x8_cavlc_q0 , h->zigzag_scan8x8_cavlc , sizeof(h->zigzag_scan8x8_cavlc_q0)); + memcpy(h->field_scan_q0 , h->field_scan , sizeof(h->field_scan_q0 )); + memcpy(h->field_scan8x8_q0 , h->field_scan8x8 , sizeof(h->field_scan8x8_q0 )); + memcpy(h->field_scan8x8_cavlc_q0 , h->field_scan8x8_cavlc , sizeof(h->field_scan8x8_cavlc_q0 )); + } +} + +/** + * 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, int force_callback) +{ + switch (h->sps.bit_depth_luma) { + case 9: + if (CHROMA444(h)) { + if (h->avctx->colorspace == AVCOL_SPC_RGB) { + return AV_PIX_FMT_GBRP9; + } else + return AV_PIX_FMT_YUV444P9; + } else if (CHROMA422(h)) + return AV_PIX_FMT_YUV422P9; + else + return AV_PIX_FMT_YUV420P9; + break; + case 10: + if (CHROMA444(h)) { + if (h->avctx->colorspace == AVCOL_SPC_RGB) { + return AV_PIX_FMT_GBRP10; + } else + return AV_PIX_FMT_YUV444P10; + } else if (CHROMA422(h)) + return AV_PIX_FMT_YUV422P10; + else + return AV_PIX_FMT_YUV420P10; + break; + case 12: + if (CHROMA444(h)) { + if (h->avctx->colorspace == AVCOL_SPC_RGB) { + return AV_PIX_FMT_GBRP12; + } else + return AV_PIX_FMT_YUV444P12; + } else if (CHROMA422(h)) + return AV_PIX_FMT_YUV422P12; + else + return AV_PIX_FMT_YUV420P12; + break; + case 14: + if (CHROMA444(h)) { + if (h->avctx->colorspace == AVCOL_SPC_RGB) { + return AV_PIX_FMT_GBRP14; + } else + return AV_PIX_FMT_YUV444P14; + } else if (CHROMA422(h)) + return AV_PIX_FMT_YUV422P14; + else + return AV_PIX_FMT_YUV420P14; + break; + case 8: + if (CHROMA444(h)) { + if (h->avctx->colorspace == AVCOL_SPC_RGB) { + av_log(h->avctx, AV_LOG_DEBUG, "Detected GBR colorspace.\n"); + return AV_PIX_FMT_GBR24P; + } else if (h->avctx->colorspace == AVCOL_SPC_YCGCO) { + av_log(h->avctx, AV_LOG_WARNING, "Detected unsupported YCgCo colorspace.\n"); + } + return h->avctx->color_range == AVCOL_RANGE_JPEG ? AV_PIX_FMT_YUVJ444P + : AV_PIX_FMT_YUV444P; + } else if (CHROMA422(h)) { + return h->avctx->color_range == AVCOL_RANGE_JPEG ? AV_PIX_FMT_YUVJ422P + : AV_PIX_FMT_YUV422P; + } else { + int i; + const enum AVPixelFormat * fmt = h->avctx->codec->pix_fmts ? + h->avctx->codec->pix_fmts : + h->avctx->color_range == AVCOL_RANGE_JPEG ? + h264_hwaccel_pixfmt_list_jpeg_420 : + h264_hwaccel_pixfmt_list_420; + + for (i=0; fmt[i] != AV_PIX_FMT_NONE; i++) + if (fmt[i] == h->avctx->pix_fmt && !force_callback) + return fmt[i]; + return ff_thread_get_format(h->avctx, fmt); + } + break; + default: + av_log(h->avctx, AV_LOG_ERROR, + "Unsupported bit depth %d\n", h->sps.bit_depth_luma); + return AVERROR_INVALIDDATA; + } +} + +/* 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); + av_assert0(h->sps.crop_right + h->sps.crop_left < (unsigned)h->width); + av_assert0(h->sps.crop_top + h->sps.crop_bottom < (unsigned)h->height); + + /* handle container cropping */ + if (!h->sps.crop && + FFALIGN(h->avctx->width, 16) == h->width && + FFALIGN(h->avctx->height, 16) == h->height) { + width = h->avctx->width; + height = h->avctx->height; + } + + if (width <= 0 || height <= 0) { + av_log(h->avctx, AV_LOG_ERROR, "Invalid cropped dimensions: %dx%d.\n", + width, height); + if (h->avctx->err_recognition & AV_EF_EXPLODE) + 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 = 0; + h->sps.crop = 0; + + width = h->width; + height = h->height; + } + + h->avctx->coded_width = h->width; + h->avctx->coded_height = h->height; + h->avctx->width = width; + h->avctx->height = height; + + return 0; +} + +static int h264_slice_header_init(H264Context *h, int reinit) +{ + int nb_slices = (HAVE_THREADS && + h->avctx->active_thread_type & FF_THREAD_SLICE) ? + h->avctx->thread_count : 1; + int i, ret; + + ff_set_sar(h->avctx, h->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) + den *= 2; + av_reduce(&h->avctx->time_base.num, &h->avctx->time_base.den, + h->sps.num_units_in_tick, den, 1 << 30); + } + + if (reinit) + ff_h264_free_tables(h, 0); + h->first_field = 0; + h->prev_interlaced_frame = 1; + + init_scan_tables(h); + ret = ff_h264_alloc_tables(h); + if (ret < 0) { + av_log(h->avctx, AV_LOG_ERROR, "Could not allocate memory\n"); + 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; + } + h->slice_context_count = nb_slices; + + if (!HAVE_THREADS || !(h->avctx->active_thread_type & FF_THREAD_SLICE)) { + ret = ff_h264_context_init(h); + 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; + if (CONFIG_ERROR_RESILIENCE) { + c->dsp = h->dsp; + } + c->vdsp = h->vdsp; + c->h264dsp = h->h264dsp; + c->h264qpel = h->h264qpel; + c->h264chroma = h->h264chroma; + c->sps = h->sps; + c->pps = h->pps; + c->pixel_shift = h->pixel_shift; + c->cur_chroma_format_idc = h->cur_chroma_format_idc; + c->width = h->width; + c->height = h->height; + c->linesize = h->linesize; + c->uvlinesize = h->uvlinesize; + c->chroma_x_shift = h->chroma_x_shift; + c->chroma_y_shift = h->chroma_y_shift; + c->qscale = h->qscale; + c->droppable = h->droppable; + c->data_partitioning = h->data_partitioning; + c->low_delay = h->low_delay; + c->mb_width = h->mb_width; + c->mb_height = h->mb_height; + c->mb_stride = h->mb_stride; + c->mb_num = h->mb_num; + c->flags = h->flags; + c->workaround_bugs = h->workaround_bugs; + c->pict_type = h->pict_type; + + init_scan_tables(c); + clone_tables(c, h, i); + c->context_initialized = 1; + } + + for (i = 0; i < h->slice_context_count; i++) + if ((ret = ff_h264_context_init(h->thread_context[i])) < 0) { + av_log(h->avctx, AV_LOG_ERROR, "context_init() failed.\n"); + return ret; + } + } + + h->context_initialized = 1; + + return 0; +} + +static enum AVPixelFormat non_j_pixfmt(enum AVPixelFormat a) +{ + switch (a) { + case AV_PIX_FMT_YUVJ420P: return AV_PIX_FMT_YUV420P; + case AV_PIX_FMT_YUVJ422P: return AV_PIX_FMT_YUV422P; + case AV_PIX_FMT_YUVJ444P: return AV_PIX_FMT_YUV444P; + default: + return a; + } +} + +/** + * 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) +{ + unsigned int first_mb_in_slice; + unsigned int pps_id; + int ret; + unsigned int slice_type, tmp, i, j; + int last_pic_structure, last_pic_droppable; + int must_reinit; + 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_long(&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]; + 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; + } + + if ( + (h->avctx->skip_frame >= AVDISCARD_NONREF && !h->nal_ref_idc) || + (h->avctx->skip_frame >= AVDISCARD_BIDIR && h->slice_type_nos == AV_PICTURE_TYPE_B) || + (h->avctx->skip_frame >= AVDISCARD_NONINTRA && h->slice_type_nos != AV_PICTURE_TYPE_I) || + (h->avctx->skip_frame >= AVDISCARD_NONKEY && h->nal_unit_type != NAL_IDR_SLICE) || + h->avctx->skip_frame >= AVDISCARD_ALL) { + return SLICE_SKIPED; + } + + // 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; + } + if (h0->au_pps_id >= 0 && pps_id != h0->au_pps_id) { + av_log(h->avctx, AV_LOG_ERROR, + "PPS change from %d to %d forbidden\n", + h0->au_pps_id, 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 || + h->pps.sps_id != h->current_sps_id || + h0->sps_buffers[h->pps.sps_id]->new) { + + h->sps = *h0->sps_buffers[h->pps.sps_id]; + + if (h->mb_width != h->sps.mb_width || + h->mb_height != h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) || + h->avctx->bits_per_raw_sample != h->sps.bit_depth_luma || + h->cur_chroma_format_idc != h->sps.chroma_format_idc + ) + needs_reinit = 1; + + if (h->bit_depth_luma != h->sps.bit_depth_luma || + h->chroma_format_idc != h->sps.chroma_format_idc) { + h->bit_depth_luma = h->sps.bit_depth_luma; + h->chroma_format_idc = h->sps.chroma_format_idc; + needs_reinit = 1; + } + if ((ret = ff_h264_set_parameter_from_sps(h)) < 0) + return ret; + } + + h->avctx->profile = ff_h264_get_profile(&h->sps); + h->avctx->level = h->sps.level_idc; + h->avctx->refs = h->sps.ref_frame_count; + + must_reinit = (h->context_initialized && + ( 16*h->sps.mb_width != h->avctx->coded_width + || 16*h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) != h->avctx->coded_height + || h->avctx->bits_per_raw_sample != h->sps.bit_depth_luma + || h->cur_chroma_format_idc != h->sps.chroma_format_idc + || av_cmp_q(h->sps.sar, h->avctx->sample_aspect_ratio) + || h->mb_width != h->sps.mb_width + || h->mb_height != h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) + )); + if (non_j_pixfmt(h0->avctx->pix_fmt) != non_j_pixfmt(get_pixel_format(h0, 0))) + must_reinit = 1; + + h->mb_width = h->sps.mb_width; + h->mb_height = h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag); + h->mb_num = h->mb_width * h->mb_height; + h->mb_stride = h->mb_width + 1; + + h->b_stride = h->mb_width * 4; + + h->chroma_y_shift = h->sps.chroma_format_idc <= 1; // 400 uses yuv420p + + h->width = 16 * h->mb_width; + h->height = 16 * h->mb_height; + + ret = init_dimensions(h); + if (ret < 0) + return ret; + + if (h->sps.video_signal_type_present_flag) { + h->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG + : AVCOL_RANGE_MPEG; + if (h->sps.colour_description_present_flag) { + if (h->avctx->colorspace != h->sps.colorspace) + needs_reinit = 1; + h->avctx->color_primaries = h->sps.color_primaries; + h->avctx->color_trc = h->sps.color_trc; + h->avctx->colorspace = h->sps.colorspace; + } + } + + if (h->context_initialized && + (must_reinit || needs_reinit)) { + if (h != h0) { + 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); + return AVERROR_INVALIDDATA; + } + + ff_h264_flush_change(h); + + if ((ret = get_pixel_format(h, 1)) < 0) + return ret; + h->avctx->pix_fmt = ret; + + av_log(h->avctx, AV_LOG_INFO, "Reinit context to %dx%d, " + "pix_fmt: %s\n", h->width, h->height, av_get_pix_fmt_name(h->avctx->pix_fmt)); + + if ((ret = h264_slice_header_init(h, 1)) < 0) { + av_log(h->avctx, AV_LOG_ERROR, + "h264_slice_header_init() failed\n"); + return ret; + } + } + if (!h->context_initialized) { + if (h != h0) { + av_log(h->avctx, AV_LOG_ERROR, + "Cannot (re-)initialize context during parallel decoding.\n"); + return AVERROR_PATCHWELCOME; + } + + if ((ret = get_pixel_format(h, 1)) < 0) + return ret; + h->avctx->pix_fmt = ret; + + if ((ret = h264_slice_header_init(h, 0)) < 0) { + av_log(h->avctx, AV_LOG_ERROR, + "h264_slice_header_init() failed\n"); + return ret; + } + } + + if (h == h0 && h->dequant_coeff_pps != pps_id) { + h->dequant_coeff_pps = pps_id; + h264_init_dequant_tables(h); + } + + h->frame_num = get_bits(&h->gb, h->sps.log2_max_frame_num); + + h->mb_mbaff = 0; + h->mb_aff_frame = 0; + last_pic_structure = h0->picture_structure; + last_pic_droppable = h0->droppable; + h->droppable = h->nal_ref_idc == 0; + if (h->sps.frame_mbs_only_flag) { + h->picture_structure = PICT_FRAME; + } else { + if (!h->sps.direct_8x8_inference_flag && slice_type == AV_PICTURE_TYPE_B) { + av_log(h->avctx, AV_LOG_ERROR, "This stream was generated by a broken encoder, invalid 8x8 inference\n"); + return -1; + } + 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; + } else { + h->picture_structure = PICT_FRAME; + h->mb_aff_frame = h->sps.mb_aff; + } + } + h->mb_field_decoding_flag = h->picture_structure != PICT_FRAME; + + if (h0->current_slice != 0) { + if (last_pic_structure != h->picture_structure || + last_pic_droppable != h->droppable) { + av_log(h->avctx, AV_LOG_ERROR, + "Changing field mode (%d -> %d) between slices is not allowed\n", + last_pic_structure, h->picture_structure); + h->picture_structure = last_pic_structure; + h->droppable = last_pic_droppable; + return AVERROR_INVALIDDATA; + } else if (!h0->cur_pic_ptr) { + av_log(h->avctx, AV_LOG_ERROR, + "unset cur_pic_ptr on slice %d\n", + h0->current_slice + 1); + return AVERROR_INVALIDDATA; + } + } else { + /* Shorten frame num gaps so we don't have to allocate reference + * frames just to throw them away */ + if (h->frame_num != h->prev_frame_num) { + int unwrap_prev_frame_num = h->prev_frame_num; + int max_frame_num = 1 << h->sps.log2_max_frame_num; + + if (unwrap_prev_frame_num > h->frame_num) + unwrap_prev_frame_num -= max_frame_num; + + if ((h->frame_num - unwrap_prev_frame_num) > h->sps.ref_frame_count) { + unwrap_prev_frame_num = (h->frame_num - h->sps.ref_frame_count) - 1; + if (unwrap_prev_frame_num < 0) + unwrap_prev_frame_num += max_frame_num; + + h->prev_frame_num = unwrap_prev_frame_num; + } + } + + /* See if we have a decoded first field looking for a pair... + * Here, we're using that to see if we should mark previously + * decode frames as "finished". + * We have to do that before the "dummy" in-between frame allocation, + * since that can modify h->cur_pic_ptr. */ + if (h0->first_field) { + assert(h0->cur_pic_ptr); + assert(h0->cur_pic_ptr->f.buf[0]); + assert(h0->cur_pic_ptr->reference != DELAYED_PIC_REF); + + /* Mark old field/frame as completed */ + if (h0->cur_pic_ptr->tf.owner == h0->avctx) { + ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, + last_pic_structure == PICT_BOTTOM_FIELD); + } + + /* figure out if we have a complementary field pair */ + if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) { + /* Previous field is unmatched. Don't display it, but let it + * remain for reference if marked as such. */ + if (last_pic_structure != PICT_FRAME) { + ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, + last_pic_structure == PICT_TOP_FIELD); + } + } else { + if (h0->cur_pic_ptr->frame_num != h->frame_num) { + /* This and previous field were reference, but had + * different frame_nums. Consider this field first in + * pair. Throw away previous field except for reference + * purposes. */ + if (last_pic_structure != PICT_FRAME) { + ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, + last_pic_structure == PICT_TOP_FIELD); + } + } else { + /* Second field in complementary pair */ + if (!((last_pic_structure == PICT_TOP_FIELD && + h->picture_structure == PICT_BOTTOM_FIELD) || + (last_pic_structure == PICT_BOTTOM_FIELD && + h->picture_structure == PICT_TOP_FIELD))) { + av_log(h->avctx, AV_LOG_ERROR, + "Invalid field mode combination %d/%d\n", + last_pic_structure, h->picture_structure); + h->picture_structure = last_pic_structure; + h->droppable = last_pic_droppable; + return AVERROR_INVALIDDATA; + } else if (last_pic_droppable != h->droppable) { + avpriv_request_sample(h->avctx, + "Found reference and non-reference fields in the same frame, which"); + h->picture_structure = last_pic_structure; + h->droppable = last_pic_droppable; + return AVERROR_PATCHWELCOME; + } + } + } + } + + while (h->frame_num != h->prev_frame_num && !h0->first_field && + 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); + if (!h->sps.gaps_in_frame_num_allowed_flag) + for(i=0; ilast_pocs); i++) + h->last_pocs[i] = INT_MIN; + ret = h264_frame_start(h); + if (ret < 0) { + h0->first_field = 0; + return ret; + } + + 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; + h->cur_pic_ptr->invalid_gap = !h->sps.gaps_in_frame_num_allowed_flag; + 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; + } + } + + /* 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); + } else { + if (h0->cur_pic_ptr->frame_num != h->frame_num) { + ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, + h0->picture_structure==PICT_BOTTOM_FIELD); + /* This and the previous field had different frame_nums. + * Consider this field first in pair. Throw away previous + * one except for reference purposes. */ + h0->first_field = 1; + h0->cur_pic_ptr = NULL; + } else { + /* Second field in complementary pair */ + h0->first_field = 0; + } + } + } else { + /* Frame or first field in a potentially complementary pair */ + h0->first_field = FIELD_PICTURE(h); + } + + if (!FIELD_PICTURE(h) || h0->first_field) { + if (h264_frame_start(h) < 0) { + h0->first_field = 0; + return AVERROR_INVALIDDATA; + } + } else { + release_unused_pictures(h, 0); + } + /* Some macroblocks can be accessed before they're available in case + * of lost slices, MBAFF or threading. */ + if (FIELD_PICTURE(h)) { + for(i = (h->picture_structure == PICT_BOTTOM_FIELD); imb_height; i++) + memset(h->slice_table + i*h->mb_stride, -1, (h->mb_stride - (i+1==h->mb_height)) * sizeof(*h->slice_table)); + } else { + memset(h->slice_table, -1, + (h->mb_height * h->mb_stride - 1) * sizeof(*h->slice_table)); + } + h0->last_slice_type = -1; + } + if (h != h0 && (ret = clone_slice(h, h0)) < 0) + return ret; + + /* can't be in alloc_tables because linesize isn't known there. + * FIXME: redo bipred weight to not require extra buffer? */ + for (i = 0; i < h->slice_context_count; i++) + if (h->thread_context[i]) { + ret = alloc_scratch_buffers(h->thread_context[i], h->linesize); + if (ret < 0) + return ret; + } + + h->cur_pic_ptr->frame_num = h->frame_num; // FIXME frame_num cleanup + + av_assert1(h->mb_num == h->mb_width * h->mb_height); + if (first_mb_in_slice << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num || + first_mb_in_slice >= h->mb_num) { + av_log(h->avctx, AV_LOG_ERROR, "first_mb_in_slice overflow\n"); + return AVERROR_INVALIDDATA; + } + h->resync_mb_x = h->mb_x = first_mb_in_slice % h->mb_width; + h->resync_mb_y = h->mb_y = (first_mb_in_slice / h->mb_width) << + FIELD_OR_MBAFF_PICTURE(h); + if (h->picture_structure == PICT_BOTTOM_FIELD) + h->resync_mb_y = h->mb_y = h->mb_y + 1; + av_assert1(h->mb_y < h->mb_height); + + if (h->picture_structure == PICT_FRAME) { + h->curr_pic_num = h->frame_num; + h->max_pic_num = 1 << h->sps.log2_max_frame_num; + } else { + h->curr_pic_num = 2 * h->frame_num + 1; + h->max_pic_num = 1 << (h->sps.log2_max_frame_num + 1); + } + + if (h->nal_unit_type == NAL_IDR_SLICE) + get_ue_golomb(&h->gb); /* idr_pic_id */ + + if (h->sps.poc_type == 0) { + h->poc_lsb = get_bits(&h->gb, h->sps.log2_max_poc_lsb); + + if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) + h->delta_poc_bottom = get_se_golomb(&h->gb); + } + + if (h->sps.poc_type == 1 && !h->sps.delta_pic_order_always_zero_flag) { + h->delta_poc[0] = get_se_golomb(&h->gb); + + if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) + h->delta_poc[1] = get_se_golomb(&h->gb); + } + + ff_init_poc(h, h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc); + + if (h->pps.redundant_pic_cnt_present) + h->redundant_pic_count = get_ue_golomb(&h->gb); + + ret = ff_set_ref_count(h); + if (ret < 0) + return ret; + + if (slice_type != AV_PICTURE_TYPE_I && + (h0->current_slice == 0 || + slice_type != h0->last_slice_type || + memcmp(h0->last_ref_count, h0->ref_count, sizeof(h0->ref_count)))) { + + ff_h264_fill_default_ref_list(h); + } + + 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; + } + } + + 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); + } else { + h->use_weight = 0; + for (i = 0; i < 2; i++) { + h->luma_weight_flag[i] = 0; + h->chroma_weight_flag[i] = 0; + } + } + + // If frame-mt is enabled, only update mmco tables for the first slice + // in a field. Subsequent slices can temporarily clobber h->mmco_index + // or h->mmco, which will cause ref list mix-ups and decoding errors + // further down the line. This may break decoding if the first slice is + // corrupt, thus we only do this if frame-mt is enabled. + if (h->nal_ref_idc) { + 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 (FRAME_MBAFF(h)) { + ff_h264_fill_mbaff_ref_list(h); + + if (h->pps.weighted_bipred_idc == 2 && h->slice_type_nos == AV_PICTURE_TYPE_B) { + implicit_weight_table(h, 0); + implicit_weight_table(h, 1); + } + } + + if (h->slice_type_nos == AV_PICTURE_TYPE_B && !h->direct_spatial_mv_pred) + ff_h264_direct_dist_scale_factor(h); + ff_h264_direct_ref_list_init(h); + + if (h->slice_type_nos != AV_PICTURE_TYPE_I && h->pps.cabac) { + tmp = get_ue_golomb_31(&h->gb); + if (tmp > 2) { + av_log(h->avctx, AV_LOG_ERROR, "cabac_init_idc %u overflow\n", tmp); + return AVERROR_INVALIDDATA; + } + h->cabac_init_idc = tmp; + } + + h->last_qscale_diff = 0; + tmp = h->pps.init_qp + get_se_golomb(&h->gb); + if (tmp > 51 + 6 * (h->sps.bit_depth_luma - 8)) { + av_log(h->avctx, AV_LOG_ERROR, "QP %u out of range\n", tmp); + return 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); + // 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 (tmp > 2) { + av_log(h->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, + "deblocking filter parameters %d %d out of range\n", + h->slice_alpha_c0_offset, h->slice_beta_offset); + return AVERROR_INVALIDDATA; + } + } + } + + if (h->avctx->skip_loop_filter >= AVDISCARD_ALL || + (h->avctx->skip_loop_filter >= AVDISCARD_NONKEY && + h->nal_unit_type != NAL_IDR_SLICE) || + (h->avctx->skip_loop_filter >= AVDISCARD_NONINTRA && + h->slice_type_nos != AV_PICTURE_TYPE_I) || + (h->avctx->skip_loop_filter >= AVDISCARD_BIDIR && + h->slice_type_nos == AV_PICTURE_TYPE_B) || + (h->avctx->skip_loop_filter >= AVDISCARD_NONREF && + h->nal_ref_idc == 0)) + h->deblocking_filter = 0; + + if (h->deblocking_filter == 1 && h0->max_contexts > 1) { + if (h->avctx->flags2 & CODEC_FLAG2_FAST) { + /* Cheat slightly for speed: + * Do not bother to deblock across slices. */ + h->deblocking_filter = 2; + } else { + h0->max_contexts = 1; + if (!h0->single_decode_warning) { + av_log(h->avctx, AV_LOG_INFO, + "Cannot parallelize slice decoding with deblocking filter type 1, decoding such frames in sequential order\n" + "To parallelize slice decoding you need video encoded with disable_deblocking_filter_idc set to 2 (deblock only edges that do not cross slices).\n" + "Setting the flags2 libavcodec option to +fast (-flags2 +fast) will disable deblocking across slices and enable parallel slice decoding " + "but will generate non-standard-compliant output.\n"); + h0->single_decode_warning = 1; + } + if (h != h0) { + av_log(h->avctx, AV_LOG_ERROR, + "Deblocking switched inside frame.\n"); + return SLICE_SINGLETHREAD; + } + } + } + h->qp_thresh = 15 - + FFMIN(h->slice_alpha_c0_offset, h->slice_beta_offset) - + FFMAX3(0, + h->pps.chroma_qp_index_offset[0], + h->pps.chroma_qp_index_offset[1]) + + 6 * (h->sps.bit_depth_luma - 8); + + h0->last_slice_type = slice_type; + memcpy(h0->last_ref_count, h0->ref_count, sizeof(h0->last_ref_count)); + h->slice_num = ++h0->current_slice; + + if (h->slice_num) + h0->slice_row[(h->slice_num-1)&(MAX_SLICES-1)]= h->resync_mb_y; + if ( h0->slice_row[h->slice_num&(MAX_SLICES-1)] + 3 >= h->resync_mb_y + && h0->slice_row[h->slice_num&(MAX_SLICES-1)] <= h->resync_mb_y + && h->slice_num >= MAX_SLICES) { + //in case of ASO this check needs to be updated depending on how we decide to assign slice numbers in this case + av_log(h->avctx, AV_LOG_WARNING, "Possibly too many slices (%d >= %d), increase MAX_SLICES and recompile if there are artifacts\n", h->slice_num, MAX_SLICES); + } + + for (j = 0; j < 2; j++) { + int id_list[16]; + int *ref2frm = h->ref2frm[h->slice_num & (MAX_SLICES - 1)][j]; + for (i = 0; i < 16; i++) { + id_list[i] = 60; + if (j < h->list_count && i < h->ref_count[j] && + h->ref_list[j][i].f.buf[0]) { + int k; + AVBuffer *buf = h->ref_list[j][i].f.buf[0]->buffer; + for (k = 0; k < h->short_ref_count; k++) + if (h->short_ref[k]->f.buf[0]->buffer == buf) { + id_list[i] = k; + break; + } + for (k = 0; k < h->long_ref_count; k++) + if (h->long_ref[k] && h->long_ref[k]->f.buf[0]->buffer == buf) { + id_list[i] = h->short_ref_count + k; + break; + } + } + } + + ref2frm[0] = + ref2frm[1] = -1; + for (i = 0; i < 16; i++) + ref2frm[i + 2] = 4 * id_list[i] + (h->ref_list[j][i].reference & 3); + ref2frm[18 + 0] = + ref2frm[18 + 1] = -1; + for (i = 16; i < 48; i++) + ref2frm[i + 4] = 4 * id_list[(i - 16) >> 1] + + (h->ref_list[j][i].reference & 3); + } + + if (h->ref_count[0]) ff_h264_set_erpic(&h->er.last_pic, &h->ref_list[0][0]); + if (h->ref_count[1]) ff_h264_set_erpic(&h->er.next_pic, &h->ref_list[1][0]); + + h->er.ref_count = h->ref_count[0]; + h0->au_pps_id = pps_id; + h->sps.new = + h0->sps_buffers[h->pps.sps_id]->new = 0; + h->current_sps_id = h->pps.sps_id; + + if (h->avctx->debug & FF_DEBUG_PICT_INFO) { + av_log(h->avctx, AV_LOG_DEBUG, + "slice:%d %s mb:%d %c%s%s pps:%u frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n", + h->slice_num, + (h->picture_structure == PICT_FRAME ? "F" : h->picture_structure == PICT_TOP_FIELD ? "T" : "B"), + first_mb_in_slice, + av_get_picture_type_char(h->slice_type), + h->slice_type_fixed ? " fix" : "", + h->nal_unit_type == NAL_IDR_SLICE ? " IDR" : "", + pps_id, h->frame_num, + h->cur_pic_ptr->field_poc[0], + h->cur_pic_ptr->field_poc[1], + h->ref_count[0], h->ref_count[1], + h->qscale, + h->deblocking_filter, + h->slice_alpha_c0_offset, 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") : ""); + } + + return 0; +} + +int ff_h264_get_slice_type(const H264Context *h) +{ + switch (h->slice_type) { + case AV_PICTURE_TYPE_P: + return 0; + case AV_PICTURE_TYPE_B: + return 1; + case AV_PICTURE_TYPE_I: + return 2; + case AV_PICTURE_TYPE_SP: + return 3; + case AV_PICTURE_TYPE_SI: + return 4; + default: + return AVERROR_INVALIDDATA; + } +} + +static av_always_inline void fill_filter_caches_inter(H264Context *h, + int mb_type, int top_xy, + int left_xy[LEFT_MBS], + int top_type, + int left_type[LEFT_MBS], + int mb_xy, int list) +{ + int b_stride = h->b_stride; + int16_t(*mv_dst)[2] = &h->mv_cache[list][scan8[0]]; + int8_t *ref_cache = &h->ref_cache[list][scan8[0]]; + if (IS_INTER(mb_type) || IS_DIRECT(mb_type)) { + if (USES_LIST(top_type, list)) { + const int b_xy = h->mb2b_xy[top_xy] + 3 * b_stride; + const int b8_xy = 4 * top_xy + 2; + int (*ref2frm)[64] = (void*)(h->ref2frm[h->slice_table[top_xy] & (MAX_SLICES - 1)][0] + (MB_MBAFF(h) ? 20 : 2)); + AV_COPY128(mv_dst - 1 * 8, h->cur_pic.motion_val[list][b_xy + 0]); + ref_cache[0 - 1 * 8] = + ref_cache[1 - 1 * 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 0]]; + ref_cache[2 - 1 * 8] = + ref_cache[3 - 1 * 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 1]]; + } else { + AV_ZERO128(mv_dst - 1 * 8); + AV_WN32A(&ref_cache[0 - 1 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); + } + + if (!IS_INTERLACED(mb_type ^ left_type[LTOP])) { + if (USES_LIST(left_type[LTOP], list)) { + const int b_xy = h->mb2b_xy[left_xy[LTOP]] + 3; + const int b8_xy = 4 * left_xy[LTOP] + 1; + int (*ref2frm)[64] =(void*)( h->ref2frm[h->slice_table[left_xy[LTOP]] & (MAX_SLICES - 1)][0] + (MB_MBAFF(h) ? 20 : 2)); + AV_COPY32(mv_dst - 1 + 0, h->cur_pic.motion_val[list][b_xy + b_stride * 0]); + AV_COPY32(mv_dst - 1 + 8, h->cur_pic.motion_val[list][b_xy + b_stride * 1]); + AV_COPY32(mv_dst - 1 + 16, h->cur_pic.motion_val[list][b_xy + b_stride * 2]); + AV_COPY32(mv_dst - 1 + 24, h->cur_pic.motion_val[list][b_xy + b_stride * 3]); + ref_cache[-1 + 0] = + ref_cache[-1 + 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 2 * 0]]; + ref_cache[-1 + 16] = + ref_cache[-1 + 24] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 2 * 1]]; + } else { + AV_ZERO32(mv_dst - 1 + 0); + AV_ZERO32(mv_dst - 1 + 8); + AV_ZERO32(mv_dst - 1 + 16); + AV_ZERO32(mv_dst - 1 + 24); + ref_cache[-1 + 0] = + ref_cache[-1 + 8] = + ref_cache[-1 + 16] = + ref_cache[-1 + 24] = LIST_NOT_USED; + } + } + } + + if (!USES_LIST(mb_type, list)) { + fill_rectangle(mv_dst, 4, 4, 8, pack16to32(0, 0), 4); + AV_WN32A(&ref_cache[0 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); + AV_WN32A(&ref_cache[1 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); + AV_WN32A(&ref_cache[2 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); + AV_WN32A(&ref_cache[3 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); + return; + } + + { + int8_t *ref = &h->cur_pic.ref_index[list][4 * mb_xy]; + int (*ref2frm)[64] = (void*)(h->ref2frm[h->slice_num & (MAX_SLICES - 1)][0] + (MB_MBAFF(h) ? 20 : 2)); + uint32_t ref01 = (pack16to32(ref2frm[list][ref[0]], ref2frm[list][ref[1]]) & 0x00FF00FF) * 0x0101; + uint32_t ref23 = (pack16to32(ref2frm[list][ref[2]], ref2frm[list][ref[3]]) & 0x00FF00FF) * 0x0101; + AV_WN32A(&ref_cache[0 * 8], ref01); + AV_WN32A(&ref_cache[1 * 8], ref01); + AV_WN32A(&ref_cache[2 * 8], ref23); + AV_WN32A(&ref_cache[3 * 8], ref23); + } + + { + int16_t(*mv_src)[2] = &h->cur_pic.motion_val[list][4 * h->mb_x + 4 * h->mb_y * b_stride]; + AV_COPY128(mv_dst + 8 * 0, mv_src + 0 * b_stride); + AV_COPY128(mv_dst + 8 * 1, mv_src + 1 * b_stride); + AV_COPY128(mv_dst + 8 * 2, mv_src + 2 * b_stride); + AV_COPY128(mv_dst + 8 * 3, mv_src + 3 * b_stride); + } +} + +/** + * + * @return non zero if the loop filter can be skipped + */ +static int fill_filter_caches(H264Context *h, int mb_type) +{ + const int mb_xy = h->mb_xy; + int top_xy, left_xy[LEFT_MBS]; + int top_type, left_type[LEFT_MBS]; + uint8_t *nnz; + uint8_t *nnz_cache; + + top_xy = mb_xy - (h->mb_stride << MB_FIELD(h)); + + /* Wow, what a mess, why didn't they simplify the interlacing & intra + * stuff, I can't imagine that these complex rules are worth it. */ + + left_xy[LBOT] = left_xy[LTOP] = mb_xy - 1; + if (FRAME_MBAFF(h)) { + const int left_mb_field_flag = IS_INTERLACED(h->cur_pic.mb_type[mb_xy - 1]); + const int curr_mb_field_flag = IS_INTERLACED(mb_type); + if (h->mb_y & 1) { + if (left_mb_field_flag != curr_mb_field_flag) + left_xy[LTOP] -= h->mb_stride; + } else { + if (curr_mb_field_flag) + top_xy += h->mb_stride & + (((h->cur_pic.mb_type[top_xy] >> 7) & 1) - 1); + if (left_mb_field_flag != curr_mb_field_flag) + left_xy[LBOT] += h->mb_stride; + } + } + + h->top_mb_xy = top_xy; + h->left_mb_xy[LTOP] = left_xy[LTOP]; + h->left_mb_xy[LBOT] = left_xy[LBOT]; + { + /* For sufficiently low qp, filtering wouldn't do anything. + * This is a conservative estimate: could also check beta_offset + * and more accurate chroma_qp. */ + int qp_thresh = h->qp_thresh; // FIXME strictly we should store qp_thresh for each mb of a slice + int qp = h->cur_pic.qscale_table[mb_xy]; + if (qp <= qp_thresh && + (left_xy[LTOP] < 0 || + ((qp + h->cur_pic.qscale_table[left_xy[LTOP]] + 1) >> 1) <= qp_thresh) && + (top_xy < 0 || + ((qp + h->cur_pic.qscale_table[top_xy] + 1) >> 1) <= qp_thresh)) { + if (!FRAME_MBAFF(h)) + return 1; + if ((left_xy[LTOP] < 0 || + ((qp + h->cur_pic.qscale_table[left_xy[LBOT]] + 1) >> 1) <= qp_thresh) && + (top_xy < h->mb_stride || + ((qp + h->cur_pic.qscale_table[top_xy - h->mb_stride] + 1) >> 1) <= qp_thresh)) + return 1; + } + } + + top_type = h->cur_pic.mb_type[top_xy]; + left_type[LTOP] = h->cur_pic.mb_type[left_xy[LTOP]]; + left_type[LBOT] = h->cur_pic.mb_type[left_xy[LBOT]]; + if (h->deblocking_filter == 2) { + if (h->slice_table[top_xy] != h->slice_num) + top_type = 0; + if (h->slice_table[left_xy[LBOT]] != h->slice_num) + left_type[LTOP] = left_type[LBOT] = 0; + } else { + if (h->slice_table[top_xy] == 0xFFFF) + top_type = 0; + if (h->slice_table[left_xy[LBOT]] == 0xFFFF) + left_type[LTOP] = left_type[LBOT] = 0; + } + h->top_type = top_type; + h->left_type[LTOP] = left_type[LTOP]; + h->left_type[LBOT] = left_type[LBOT]; + + if (IS_INTRA(mb_type)) + return 0; + + fill_filter_caches_inter(h, mb_type, top_xy, left_xy, + top_type, left_type, mb_xy, 0); + if (h->list_count == 2) + fill_filter_caches_inter(h, mb_type, top_xy, left_xy, + top_type, left_type, mb_xy, 1); + + nnz = h->non_zero_count[mb_xy]; + nnz_cache = h->non_zero_count_cache; + AV_COPY32(&nnz_cache[4 + 8 * 1], &nnz[0]); + AV_COPY32(&nnz_cache[4 + 8 * 2], &nnz[4]); + AV_COPY32(&nnz_cache[4 + 8 * 3], &nnz[8]); + AV_COPY32(&nnz_cache[4 + 8 * 4], &nnz[12]); + h->cbp = h->cbp_table[mb_xy]; + + if (top_type) { + nnz = h->non_zero_count[top_xy]; + AV_COPY32(&nnz_cache[4 + 8 * 0], &nnz[3 * 4]); + } + + if (left_type[LTOP]) { + nnz = h->non_zero_count[left_xy[LTOP]]; + nnz_cache[3 + 8 * 1] = nnz[3 + 0 * 4]; + nnz_cache[3 + 8 * 2] = nnz[3 + 1 * 4]; + nnz_cache[3 + 8 * 3] = nnz[3 + 2 * 4]; + nnz_cache[3 + 8 * 4] = nnz[3 + 3 * 4]; + } + + /* CAVLC 8x8dct requires NNZ values for residual decoding that differ + * from what the loop filter needs */ + if (!CABAC(h) && h->pps.transform_8x8_mode) { + if (IS_8x8DCT(top_type)) { + nnz_cache[4 + 8 * 0] = + nnz_cache[5 + 8 * 0] = (h->cbp_table[top_xy] & 0x4000) >> 12; + nnz_cache[6 + 8 * 0] = + nnz_cache[7 + 8 * 0] = (h->cbp_table[top_xy] & 0x8000) >> 12; + } + if (IS_8x8DCT(left_type[LTOP])) { + nnz_cache[3 + 8 * 1] = + nnz_cache[3 + 8 * 2] = (h->cbp_table[left_xy[LTOP]] & 0x2000) >> 12; // FIXME check MBAFF + } + if (IS_8x8DCT(left_type[LBOT])) { + nnz_cache[3 + 8 * 3] = + nnz_cache[3 + 8 * 4] = (h->cbp_table[left_xy[LBOT]] & 0x8000) >> 12; // FIXME check MBAFF + } + + if (IS_8x8DCT(mb_type)) { + nnz_cache[scan8[0]] = + nnz_cache[scan8[1]] = + nnz_cache[scan8[2]] = + nnz_cache[scan8[3]] = (h->cbp & 0x1000) >> 12; + + nnz_cache[scan8[0 + 4]] = + nnz_cache[scan8[1 + 4]] = + nnz_cache[scan8[2 + 4]] = + nnz_cache[scan8[3 + 4]] = (h->cbp & 0x2000) >> 12; + + nnz_cache[scan8[0 + 8]] = + nnz_cache[scan8[1 + 8]] = + nnz_cache[scan8[2 + 8]] = + nnz_cache[scan8[3 + 8]] = (h->cbp & 0x4000) >> 12; + + nnz_cache[scan8[0 + 12]] = + nnz_cache[scan8[1 + 12]] = + nnz_cache[scan8[2 + 12]] = + nnz_cache[scan8[3 + 12]] = (h->cbp & 0x8000) >> 12; + } + } + + return 0; +} + +static void loop_filter(H264Context *h, int start_x, int end_x) +{ + uint8_t *dest_y, *dest_cb, *dest_cr; + int linesize, uvlinesize, mb_x, mb_y; + const int end_mb_y = h->mb_y + FRAME_MBAFF(h); + const int old_slice_type = h->slice_type; + const int pixel_shift = h->pixel_shift; + const int block_h = 16 >> h->chroma_y_shift; + + if (h->deblocking_filter) { + for (mb_x = start_x; mb_x < end_x; mb_x++) + for (mb_y = end_mb_y - FRAME_MBAFF(h); mb_y <= end_mb_y; mb_y++) { + int mb_xy, mb_type; + mb_xy = h->mb_xy = mb_x + mb_y * h->mb_stride; + h->slice_num = h->slice_table[mb_xy]; + mb_type = h->cur_pic.mb_type[mb_xy]; + h->list_count = h->list_counts[mb_xy]; + + if (FRAME_MBAFF(h)) + h->mb_mbaff = + h->mb_field_decoding_flag = !!IS_INTERLACED(mb_type); + + h->mb_x = mb_x; + h->mb_y = mb_y; + dest_y = h->cur_pic.f.data[0] + + ((mb_x << pixel_shift) + mb_y * h->linesize) * 16; + dest_cb = h->cur_pic.f.data[1] + + (mb_x << pixel_shift) * (8 << CHROMA444(h)) + + mb_y * h->uvlinesize * block_h; + dest_cr = h->cur_pic.f.data[2] + + (mb_x << pixel_shift) * (8 << CHROMA444(h)) + + mb_y * h->uvlinesize * block_h; + // FIXME simplify above + + if (MB_FIELD(h)) { + linesize = h->mb_linesize = h->linesize * 2; + uvlinesize = h->mb_uvlinesize = h->uvlinesize * 2; + if (mb_y & 1) { // FIXME move out of this function? + dest_y -= h->linesize * 15; + dest_cb -= h->uvlinesize * (block_h - 1); + dest_cr -= h->uvlinesize * (block_h - 1); + } + } else { + linesize = h->mb_linesize = h->linesize; + uvlinesize = h->mb_uvlinesize = h->uvlinesize; + } + backup_mb_border(h, dest_y, dest_cb, dest_cr, linesize, + uvlinesize, 0); + if (fill_filter_caches(h, mb_type)) + continue; + h->chroma_qp[0] = get_chroma_qp(h, 0, h->cur_pic.qscale_table[mb_xy]); + h->chroma_qp[1] = get_chroma_qp(h, 1, h->cur_pic.qscale_table[mb_xy]); + + if (FRAME_MBAFF(h)) { + ff_h264_filter_mb(h, mb_x, mb_y, dest_y, dest_cb, dest_cr, + linesize, uvlinesize); + } else { + ff_h264_filter_mb_fast(h, mb_x, mb_y, dest_y, dest_cb, + dest_cr, linesize, uvlinesize); + } + } + } + h->slice_type = old_slice_type; + h->mb_x = end_x; + h->mb_y = end_mb_y - FRAME_MBAFF(h); + h->chroma_qp[0] = get_chroma_qp(h, 0, h->qscale); + h->chroma_qp[1] = get_chroma_qp(h, 1, h->qscale); +} + +static void predict_field_decoding_flag(H264Context *h) +{ + const int mb_xy = h->mb_x + h->mb_y * h->mb_stride; + int mb_type = (h->slice_table[mb_xy - 1] == h->slice_num) ? + h->cur_pic.mb_type[mb_xy - 1] : + (h->slice_table[mb_xy - h->mb_stride] == h->slice_num) ? + h->cur_pic.mb_type[mb_xy - h->mb_stride] : 0; + h->mb_mbaff = h->mb_field_decoding_flag = IS_INTERLACED(mb_type) ? 1 : 0; +} + +/** + * Draw edges and report progress for the last MB row. + */ +static void decode_finish_row(H264Context *h) +{ + int top = 16 * (h->mb_y >> FIELD_PICTURE(h)); + int pic_height = 16 * h->mb_height >> FIELD_PICTURE(h); + int height = 16 << FRAME_MBAFF(h); + int deblock_border = (16 + 4) << FRAME_MBAFF(h); + + if (h->deblocking_filter) { + if ((top + height) >= pic_height) + height += deblock_border; + top -= deblock_border; + } + + if (top >= pic_height || (top + height) < 0) + return; + + height = FFMIN(height, pic_height - top); + if (top < 0) { + height = top + height; + top = 0; + } + + ff_h264_draw_horiz_band(h, top, height); + + if (h->droppable || h->er.error_occurred) + return; + + ff_thread_report_progress(&h->cur_pic_ptr->tf, top + height - 1, + h->picture_structure == PICT_BOTTOM_FIELD); +} + +static void er_add_slice(H264Context *h, int startx, int starty, + int endx, int endy, int status) +{ + if (CONFIG_ERROR_RESILIENCE) { + ERContext *er = &h->er; + + ff_er_add_slice(er, startx, starty, endx, endy, status); + } +} + +static int decode_slice(struct AVCodecContext *avctx, void *arg) +{ + H264Context *h = *(void **)arg; + int lf_x_start = h->mb_x; + + h->mb_skip_run = -1; + + av_assert0(h->block_offset[15] == (4 * ((scan8[15] - scan8[0]) & 7) << h->pixel_shift) + 4 * h->linesize * ((scan8[15] - scan8[0]) >> 3)); + + h->is_complex = FRAME_MBAFF(h) || h->picture_structure != PICT_FRAME || + avctx->codec_id != AV_CODEC_ID_H264 || + (CONFIG_GRAY && (h->flags & CODEC_FLAG_GRAY)); + + if (!(h->avctx->active_thread_type & FF_THREAD_SLICE) && h->picture_structure == PICT_FRAME && h->er.error_status_table) { + const int start_i = av_clip(h->resync_mb_x + h->resync_mb_y * h->mb_width, 0, h->mb_num - 1); + if (start_i) { + int prev_status = h->er.error_status_table[h->er.mb_index2xy[start_i - 1]]; + prev_status &= ~ VP_START; + if (prev_status != (ER_MV_END | ER_DC_END | ER_AC_END)) + h->er.error_occurred = 1; + } + } + + if (h->pps.cabac) { + /* realign */ + align_get_bits(&h->gb); + + /* init cabac */ + ff_init_cabac_decoder(&h->cabac, + h->gb.buffer + get_bits_count(&h->gb) / 8, + (get_bits_left(&h->gb) + 7) / 8); + + ff_h264_init_cabac_states(h); + + for (;;) { + // START_TIMER + int ret = ff_h264_decode_mb_cabac(h); + int eos; + // STOP_TIMER("decode_mb_cabac") + + if (ret >= 0) + ff_h264_hl_decode_mb(h); + + // FIXME optimal? or let mb_decode decode 16x32 ? + if (ret >= 0 && FRAME_MBAFF(h)) { + h->mb_y++; + + ret = ff_h264_decode_mb_cabac(h); + + if (ret >= 0) + ff_h264_hl_decode_mb(h); + h->mb_y--; + } + eos = get_cabac_terminate(&h->cabac); + + if ((h->workaround_bugs & FF_BUG_TRUNCATED) && + h->cabac.bytestream > h->cabac.bytestream_end + 2) { + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x - 1, + h->mb_y, ER_MB_END); + if (h->mb_x >= lf_x_start) + loop_filter(h, lf_x_start, h->mb_x + 1); + return 0; + } + if (h->cabac.bytestream > h->cabac.bytestream_end + 2 ) + av_log(h->avctx, AV_LOG_DEBUG, "bytestream overread %"PTRDIFF_SPECIFIER"\n", h->cabac.bytestream_end - h->cabac.bytestream); + if (ret < 0 || h->cabac.bytestream > h->cabac.bytestream_end + 4) { + av_log(h->avctx, AV_LOG_ERROR, + "error while decoding MB %d %d, bytestream %"PTRDIFF_SPECIFIER"\n", + h->mb_x, h->mb_y, + h->cabac.bytestream_end - h->cabac.bytestream); + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x, + h->mb_y, ER_MB_ERROR); + return 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 (FIELD_OR_MBAFF_PICTURE(h)) { + ++h->mb_y; + if (FRAME_MBAFF(h) && h->mb_y < h->mb_height) + predict_field_decoding_flag(h); + } + } + + if (eos || h->mb_y >= h->mb_height) { + tprintf(h->avctx, "slice end %d %d\n", + get_bits_count(&h->gb), h->gb.size_in_bits); + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x - 1, + h->mb_y, ER_MB_END); + if (h->mb_x > lf_x_start) + loop_filter(h, lf_x_start, h->mb_x); + return 0; + } + } + } else { + for (;;) { + int ret = ff_h264_decode_mb_cavlc(h); + + if (ret >= 0) + ff_h264_hl_decode_mb(h); + + // FIXME optimal? or let mb_decode decode 16x32 ? + if (ret >= 0 && FRAME_MBAFF(h)) { + h->mb_y++; + ret = ff_h264_decode_mb_cavlc(h); + + if (ret >= 0) + ff_h264_hl_decode_mb(h); + h->mb_y--; + } + + if (ret < 0) { + av_log(h->avctx, AV_LOG_ERROR, + "error while decoding MB %d %d\n", h->mb_x, h->mb_y); + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x, + h->mb_y, ER_MB_ERROR); + return 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 (FIELD_OR_MBAFF_PICTURE(h)) { + ++h->mb_y; + if (FRAME_MBAFF(h) && h->mb_y < h->mb_height) + predict_field_decoding_flag(h); + } + if (h->mb_y >= h->mb_height) { + tprintf(h->avctx, "slice end %d %d\n", + get_bits_count(&h->gb), h->gb.size_in_bits); + + if ( get_bits_left(&h->gb) == 0 + || get_bits_left(&h->gb) > 0 && !(h->avctx->err_recognition & AV_EF_AGGRESSIVE)) { + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, + h->mb_x - 1, h->mb_y, + ER_MB_END); + + return 0; + } else { + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, + h->mb_x, h->mb_y, + ER_MB_END); + + return 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(&h->gb) == 0) { + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, + h->mb_x - 1, h->mb_y, + ER_MB_END); + if (h->mb_x > lf_x_start) + loop_filter(h, lf_x_start, h->mb_x); + + return 0; + } else { + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x, + h->mb_y, ER_MB_ERROR); + + return AVERROR_INVALIDDATA; + } + } + } + } +} + +/** + * 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) +{ + AVCodecContext *const avctx = h->avctx; + H264Context *hx; + int i; + + av_assert0(h->mb_y < h->mb_height); + + if (h->avctx->hwaccel || + h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) + return 0; + if (context_count == 1) { + return decode_slice(avctx, &h); + } else { + av_assert0(context_count > 0); + for (i = 1; i < context_count; i++) { + hx = h->thread_context[i]; + if (CONFIG_ERROR_RESILIENCE) { + hx->er.error_count = 0; + } + hx->x264_build = h->x264_build; + } + + avctx->execute(avctx, decode_slice, h->thread_context, + NULL, context_count, sizeof(void *)); + + /* pull back stuff from slices to master context */ + hx = h->thread_context[context_count - 1]; + h->mb_x = hx->mb_x; + h->mb_y = hx->mb_y; + h->droppable = hx->droppable; + h->picture_structure = hx->picture_structure; + if (CONFIG_ERROR_RESILIENCE) { + for (i = 1; i < context_count; i++) + h->er.error_count += h->thread_context[i]->er.error_count; + } + } + + return 0; +} diff --git a/libavcodec/h264data.h b/libavcodec/h264data.h index eb229f3f4..38f32583f 100644 --- a/libavcodec/h264data.h +++ b/libavcodec/h264data.h @@ -32,7 +32,6 @@ #include #include "libavutil/rational.h" -#include "mpegvideo.h" #include "h264.h" static const uint8_t golomb_to_pict_type[5] = { diff --git a/libavcodec/h264dsp.c b/libavcodec/h264dsp.c index a2a4abad9..a4da7764e 100644 --- a/libavcodec/h264dsp.c +++ b/libavcodec/h264dsp.c @@ -33,6 +33,7 @@ #include "avcodec.h" #include "h264dsp.h" #include "h264idct.h" +#include "startcode.h" #include "libavutil/common.h" #define BIT_DEPTH 8 @@ -63,34 +64,6 @@ #include "h264addpx_template.c" #undef BIT_DEPTH -static int h264_find_start_code_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 - * bytes at the end. - */ -# if HAVE_FAST_64BIT - while (i < size && - !((~*(const uint64_t *)(buf + i) & - (*(const uint64_t *)(buf + i) - 0x0101010101010101ULL)) & - 0x8080808080808080ULL)) - i += 8; -# else - while (i < size && - !((~*(const uint32_t *)(buf + i) & - (*(const uint32_t *)(buf + i) - 0x01010101U)) & - 0x80808080U)) - i += 4; -# endif -#endif - for (; i < size; i++) - if (!buf[i]) - break; - return i; -} - av_cold void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, const int chroma_format_idc) { @@ -178,7 +151,7 @@ av_cold void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, H264_DSP(8); break; } - c->h264_find_start_code_candidate = h264_find_start_code_candidate_c; + c->h264_find_start_code_candidate = ff_startcode_find_candidate_c; if (ARCH_AARCH64) ff_h264dsp_init_aarch64(c, bit_depth, chroma_format_idc); if (ARCH_ARM) ff_h264dsp_init_arm(c, bit_depth, chroma_format_idc); diff --git a/libavcodec/h264idct_template.c b/libavcodec/h264idct_template.c index 42c32d15e..abf888ed9 100644 --- a/libavcodec/h264idct_template.c +++ b/libavcodec/h264idct_template.c @@ -28,6 +28,7 @@ #include "bit_depth_template.c" #include "libavutil/common.h" #include "h264.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 7045ca768..044fc90c4 100644 --- a/libavcodec/h264pred.c +++ b/libavcodec/h264pred.c @@ -27,9 +27,9 @@ #include "libavutil/attributes.h" #include "libavutil/avassert.h" -#include "dsputil.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" #include "h264pred.h" -#include "avcodec.h" // for AV_CODEC_ID_* #define BIT_DEPTH 8 #include "h264pred_template.c" @@ -279,7 +279,7 @@ static void pred4x4_horizontal_up_rv40_nodown_c(uint8_t *src, static void pred4x4_tm_vp8_c(uint8_t *src, const uint8_t *topright, ptrdiff_t stride) { - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP - src[-1-stride]; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP - src[-1-stride]; uint8_t *top = src-stride; int y; @@ -305,7 +305,7 @@ static void pred16x16_plane_rv40_c(uint8_t *src, ptrdiff_t stride) static void pred16x16_tm_vp8_c(uint8_t *src, ptrdiff_t stride) { - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP - src[-1-stride]; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP - src[-1-stride]; uint8_t *top = src-stride; int y; @@ -387,7 +387,7 @@ static void pred8x8_dc_rv40_c(uint8_t *src, ptrdiff_t stride) static void pred8x8_tm_vp8_c(uint8_t *src, ptrdiff_t stride) { - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP - src[-1-stride]; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP - src[-1-stride]; uint8_t *top = src-stride; int y; @@ -420,7 +420,7 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, #define H264_PRED(depth) \ if(codec_id != AV_CODEC_ID_RV40){\ - if(codec_id == AV_CODEC_ID_VP8) {\ + if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) {\ h->pred4x4[VERT_PRED ]= FUNCD(pred4x4_vertical_vp8);\ h->pred4x4[HOR_PRED ]= FUNCD(pred4x4_horizontal_vp8);\ } else {\ @@ -435,15 +435,14 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred4x4[DIAG_DOWN_RIGHT_PRED]= FUNCC(pred4x4_down_right , depth);\ h->pred4x4[VERT_RIGHT_PRED ]= FUNCC(pred4x4_vertical_right , depth);\ h->pred4x4[HOR_DOWN_PRED ]= FUNCC(pred4x4_horizontal_down , depth);\ - if (codec_id == AV_CODEC_ID_VP8) {\ + if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) {\ h->pred4x4[VERT_LEFT_PRED ]= FUNCD(pred4x4_vertical_left_vp8);\ } else\ h->pred4x4[VERT_LEFT_PRED ]= FUNCC(pred4x4_vertical_left , depth);\ h->pred4x4[HOR_UP_PRED ]= FUNCC(pred4x4_horizontal_up , depth);\ - if(codec_id != AV_CODEC_ID_VP8) {\ + if (codec_id != AV_CODEC_ID_VP7 && codec_id != AV_CODEC_ID_VP8) {\ h->pred4x4[LEFT_DC_PRED ]= FUNCC(pred4x4_left_dc , depth);\ h->pred4x4[TOP_DC_PRED ]= FUNCC(pred4x4_top_dc , depth);\ - h->pred4x4[DC_128_PRED ]= FUNCC(pred4x4_128_dc , depth);\ } else {\ h->pred4x4[TM_VP8_PRED ]= FUNCD(pred4x4_tm_vp8);\ h->pred4x4[DC_127_PRED ]= FUNCC(pred4x4_127_dc , depth);\ @@ -451,6 +450,8 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred4x4[VERT_VP8_PRED ]= FUNCC(pred4x4_vertical , depth);\ h->pred4x4[HOR_VP8_PRED ]= FUNCC(pred4x4_horizontal , depth);\ }\ + if (codec_id != AV_CODEC_ID_VP8)\ + h->pred4x4[DC_128_PRED ]= FUNCC(pred4x4_128_dc , depth);\ }else{\ h->pred4x4[VERT_PRED ]= FUNCC(pred4x4_vertical , depth);\ h->pred4x4[HOR_PRED ]= FUNCC(pred4x4_horizontal , depth);\ @@ -489,7 +490,7 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred8x8[VERT_PRED8x8 ]= FUNCC(pred8x16_vertical , depth);\ h->pred8x8[HOR_PRED8x8 ]= FUNCC(pred8x16_horizontal , depth);\ }\ - if (codec_id != AV_CODEC_ID_VP8) {\ + if (codec_id != AV_CODEC_ID_VP7 && codec_id != AV_CODEC_ID_VP8) {\ if (chroma_format_idc <= 1) {\ h->pred8x8[PLANE_PRED8x8]= FUNCC(pred8x8_plane , depth);\ } else {\ @@ -497,7 +498,8 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, }\ } else\ h->pred8x8[PLANE_PRED8x8]= FUNCD(pred8x8_tm_vp8);\ - if(codec_id != AV_CODEC_ID_RV40 && codec_id != AV_CODEC_ID_VP8){\ + if (codec_id != AV_CODEC_ID_RV40 && codec_id != AV_CODEC_ID_VP7 && \ + codec_id != AV_CODEC_ID_VP8) {\ if (chroma_format_idc <= 1) {\ h->pred8x8[DC_PRED8x8 ]= FUNCC(pred8x8_dc , depth);\ h->pred8x8[LEFT_DC_PRED8x8]= FUNCC(pred8x8_left_dc , depth);\ @@ -519,7 +521,7 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred8x8[DC_PRED8x8 ]= FUNCD(pred8x8_dc_rv40);\ h->pred8x8[LEFT_DC_PRED8x8]= FUNCD(pred8x8_left_dc_rv40);\ h->pred8x8[TOP_DC_PRED8x8 ]= FUNCD(pred8x8_top_dc_rv40);\ - if (codec_id == AV_CODEC_ID_VP8) {\ + if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) {\ h->pred8x8[DC_127_PRED8x8]= FUNCC(pred8x8_127_dc , depth);\ h->pred8x8[DC_129_PRED8x8]= FUNCC(pred8x8_129_dc , depth);\ }\ @@ -540,6 +542,7 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, case AV_CODEC_ID_RV40:\ h->pred16x16[PLANE_PRED8x8 ]= FUNCD(pred16x16_plane_rv40);\ break;\ + case AV_CODEC_ID_VP7:\ case AV_CODEC_ID_VP8:\ h->pred16x16[PLANE_PRED8x8 ]= FUNCD(pred16x16_tm_vp8);\ h->pred16x16[DC_127_PRED8x8]= FUNCC(pred16x16_127_dc , depth);\ @@ -558,6 +561,8 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred4x4_add [ HOR_PRED ]= FUNCC(pred4x4_horizontal_add , depth);\ h->pred8x8l_add [VERT_PRED ]= FUNCC(pred8x8l_vertical_add , depth);\ h->pred8x8l_add [ HOR_PRED ]= FUNCC(pred8x8l_horizontal_add , depth);\ + h->pred8x8l_filter_add [VERT_PRED ]= FUNCC(pred8x8l_vertical_filter_add , depth);\ + h->pred8x8l_filter_add [ HOR_PRED ]= FUNCC(pred8x8l_horizontal_filter_add , depth);\ if (chroma_format_idc <= 1) {\ h->pred8x8_add [VERT_PRED8x8]= FUNCC(pred8x8_vertical_add , depth);\ h->pred8x8_add [ HOR_PRED8x8]= FUNCC(pred8x8_horizontal_add , depth);\ diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h index 00af03a56..670829204 100644 --- a/libavcodec/h264pred.h +++ b/libavcodec/h264pred.h @@ -101,6 +101,8 @@ typedef struct H264PredContext { int16_t *block /*align 16*/, ptrdiff_t stride); void(*pred8x8l_add[2])(uint8_t *pix /*align 8*/, int16_t *block /*align 16*/, ptrdiff_t stride); + void(*pred8x8l_filter_add[2])(uint8_t *pix /*align 8*/, + int16_t *block /*align 16*/, int topleft, int topright, ptrdiff_t stride); void(*pred8x8_add[3])(uint8_t *pix /*align 8*/, const int *block_offset, int16_t *block /*align 16*/, ptrdiff_t stride); diff --git a/libavcodec/h264pred_template.c b/libavcodec/h264pred_template.c index 8d8d62e0b..f684433ab 100644 --- a/libavcodec/h264pred_template.c +++ b/libavcodec/h264pred_template.c @@ -25,6 +25,8 @@ * @author Michael Niedermayer */ +#include "libavutil/intreadwrite.h" + #include "mathops.h" #include "bit_depth_template.c" @@ -1122,6 +1124,79 @@ static void FUNCC(pred8x8l_horizontal_up)(uint8_t *_src, int has_topleft, SRC(5,6)=SRC(5,7)=SRC(6,4)=SRC(6,5)=SRC(6,6)= SRC(6,7)=SRC(7,4)=SRC(7,5)=SRC(7,6)=SRC(7,7)= l7; } + +static void FUNCC(pred8x8l_vertical_filter_add)(uint8_t *_src, int16_t *_block, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + int i; + pixel *src = (pixel*)_src; + const dctcoef *block = (const dctcoef*)_block; + pixel pix[8]; + int stride = _stride>>(sizeof(pixel)-1); + PREDICT_8x8_LOAD_TOP; + + pix[0] = t0; + pix[1] = t1; + pix[2] = t2; + pix[3] = t3; + pix[4] = t4; + pix[5] = t5; + pix[6] = t6; + pix[7] = t7; + + for(i=0; i<8; i++){ + pixel v = pix[i]; + src[0*stride]= v += block[0]; + src[1*stride]= v += block[8]; + src[2*stride]= v += block[16]; + src[3*stride]= v += block[24]; + src[4*stride]= v += block[32]; + src[5*stride]= v += block[40]; + src[6*stride]= v += block[48]; + src[7*stride]= v + block[56]; + src++; + block++; + } + + memset(_block, 0, sizeof(dctcoef) * 64); +} + +static void FUNCC(pred8x8l_horizontal_filter_add)(uint8_t *_src, int16_t *_block, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + int i; + pixel *src = (pixel*)_src; + const dctcoef *block = (const dctcoef*)_block; + pixel pix[8]; + int stride = _stride>>(sizeof(pixel)-1); + PREDICT_8x8_LOAD_LEFT; + + pix[0] = l0; + pix[1] = l1; + pix[2] = l2; + pix[3] = l3; + pix[4] = l4; + pix[5] = l5; + pix[6] = l6; + pix[7] = l7; + + for(i=0; i<8; i++){ + pixel v = pix[i]; + src[0]= v += block[0]; + src[1]= v += block[1]; + src[2]= v += block[2]; + src[3]= v += block[3]; + src[4]= v += block[4]; + src[5]= v += block[5]; + src[6]= v += block[6]; + src[7]= v + block[7]; + src+= stride; + block+= 8; + } + + memset(_block, 0, sizeof(dctcoef) * 64); +} + #undef PREDICT_8x8_LOAD_LEFT #undef PREDICT_8x8_LOAD_TOP #undef PREDICT_8x8_LOAD_TOPLEFT diff --git a/libavcodec/h264qpel.h b/libavcodec/h264qpel.h index 041ee7d14..d71130d1e 100644 --- a/libavcodec/h264qpel.h +++ b/libavcodec/h264qpel.h @@ -22,7 +22,7 @@ #ifndef AVCODEC_H264QPEL_H #define AVCODEC_H264QPEL_H -#include "dsputil.h" +#include "qpeldsp.h" typedef struct H264QpelContext { qpel_mc_func put_h264_qpel_pixels_tab[4][16]; diff --git a/libavcodec/h264qpel_template.c b/libavcodec/h264qpel_template.c index 48eb8c874..4878c365a 100644 --- a/libavcodec/h264qpel_template.c +++ b/libavcodec/h264qpel_template.c @@ -20,8 +20,11 @@ */ #include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + #include "bit_depth_template.c" #include "hpel_template.c" +#include "pel_template.c" static inline void FUNC(copy_block2)(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h) { diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index eae0757c8..afb2baaf6 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -26,21 +26,20 @@ #include "libavutil/atomic.h" #include "libavutil/attributes.h" #include "libavutil/common.h" +#include "libavutil/display.h" #include "libavutil/internal.h" #include "libavutil/md5.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/stereo3d.h" +#include "bswapdsp.h" #include "bytestream.h" #include "cabac_functions.h" -#include "dsputil.h" #include "golomb.h" #include "hevc.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_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 }; /** * NOTE: Each function hls_foo correspond to the function foo in the @@ -56,7 +55,6 @@ static void pic_arrays_free(HEVCContext *s) { av_freep(&s->sao); av_freep(&s->deblock); - av_freep(&s->split_cu_flag); av_freep(&s->skip_flag); av_freep(&s->tab_ct_depth); @@ -86,7 +84,6 @@ static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) int log2_min_cb_size = sps->log2_min_cb_size; int width = sps->width; int height = sps->height; - int pic_size = width * height; int pic_size_in_ctb = ((width >> log2_min_cb_size) + 1) * ((height >> log2_min_cb_size) + 1); int ctb_count = sps->ctb_width * sps->ctb_height; @@ -97,8 +94,7 @@ static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) s->sao = av_mallocz_array(ctb_count, sizeof(*s->sao)); s->deblock = av_mallocz_array(ctb_count, sizeof(*s->deblock)); - s->split_cu_flag = av_malloc(pic_size); - if (!s->sao || !s->deblock || !s->split_cu_flag) + if (!s->sao || !s->deblock) goto fail; s->skip_flag = av_malloc(pic_size_in_ctb); @@ -126,7 +122,7 @@ static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) goto fail; s->tab_mvf_pool = av_buffer_pool_init(min_pu_size * sizeof(MvField), - av_buffer_alloc); + av_buffer_allocz); s->rpl_tab_pool = av_buffer_pool_init(ctb_count * sizeof(RefPicListTab), av_buffer_allocz); if (!s->tab_mvf_pool || !s->rpl_tab_pool) @@ -151,7 +147,7 @@ static void pred_weight_table(HEVCContext *s, GetBitContext *gb) s->sh.luma_log2_weight_denom = get_ue_golomb_long(gb); if (s->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++) { @@ -161,7 +157,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->sps->chroma_format_idc != 0) { for (i = 0; i < s->sh.nb_refs[L0]; i++) chroma_weight_l0_flag[i] = get_bits1(gb); } else { @@ -179,7 +175,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 { @@ -215,7 +211,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 { @@ -244,7 +240,7 @@ static int decode_lt_rps(HEVCContext *s, LongTermRPS *rps, GetBitContext *gb) nb_sps = get_ue_golomb_long(gb); nb_sh = get_ue_golomb_long(gb); - if (nb_sh + nb_sps > FF_ARRAY_ELEMS(rps->poc)) + if (nb_sh + (uint64_t)nb_sps > FF_ARRAY_ELEMS(rps->poc)) return AVERROR_INVALIDDATA; rps->nb_refs = nb_sh + nb_sps; @@ -295,9 +291,10 @@ static int set_sps(HEVCContext *s, const HEVCSPS *sps) s->avctx->width = sps->output_width; s->avctx->height = sps->output_height; s->avctx->pix_fmt = sps->pix_fmt; - s->avctx->sample_aspect_ratio = sps->vui.sar; s->avctx->has_b_frames = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics; + ff_set_sar(s->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; @@ -349,6 +346,17 @@ fail: return ret; } +static int is_sps_exist(HEVCContext *s, const HEVCSPS* last_sps) +{ + int i; + + for( i = 0; i < MAX_SPS_COUNT; i++) + if(s->sps_list[i]) + if (last_sps == (HEVCSPS*)s->sps_list[i]->data) + return 1; + return 0; +} + static int hls_slice_header(HEVCContext *s) { GetBitContext *gb = &s->HEVClc->gb; @@ -363,8 +371,11 @@ static int hls_slice_header(HEVCContext *s) if (IS_IDR(s)) ff_hevc_clear_refs(s); } - if (s->nal_unit_type >= 16 && s->nal_unit_type <= 23) + sh->no_output_of_prior_pics_flag = 0; + if (IS_IRAP(s)) sh->no_output_of_prior_pics_flag = get_bits1(gb); + if (s->nal_unit_type == NAL_CRA_NUT && s->last_eos == 1) + sh->no_output_of_prior_pics_flag = 1; sh->pps_id = get_ue_golomb_long(gb); if (sh->pps_id >= MAX_PPS_COUNT || !s->pps_list[sh->pps_id]) { @@ -379,7 +390,16 @@ static int hls_slice_header(HEVCContext *s) s->pps = (HEVCPPS*)s->pps_list[sh->pps_id]->data; if (s->sps != (HEVCSPS*)s->sps_list[s->pps->sps_id]->data) { + const HEVCSPS* last_sps = s->sps; s->sps = (HEVCSPS*)s->sps_list[s->pps->sps_id]->data; + if (last_sps) { + if (is_sps_exist(s, last_sps)) { + if (s->sps->width != last_sps->width || s->sps->height != last_sps->height || + s->sps->temporal_layer[s->sps->max_sub_layers - 1].max_dec_pic_buffering != last_sps->temporal_layer[last_sps->max_sub_layers - 1].max_dec_pic_buffering) + sh->no_output_of_prior_pics_flag = 0; + } else + sh->no_output_of_prior_pics_flag = 0; + } ff_hevc_clear_refs(s); ret = set_sps(s, s->sps); if (ret < 0) @@ -438,6 +458,8 @@ static int hls_slice_header(HEVCContext *s) return AVERROR_INVALIDDATA; } + // when flag is not present, picture is inferred to be output + sh->pic_output_flag = 1; if (s->pps->output_flag_present_flag) sh->pic_output_flag = get_bits1(gb); @@ -606,6 +628,11 @@ static int hls_slice_header(HEVCContext *s) sh->slice_cr_qp_offset = 0; } + if (s->pps->chroma_qp_offset_list_enabled_flag) + sh->cu_chroma_qp_offset_enabled_flag = get_bits1(gb); + else + sh->cu_chroma_qp_offset_enabled_flag = 0; + if (s->pps->deblocking_filter_control_present_flag) { int deblocking_filter_override_flag = 0; @@ -683,6 +710,10 @@ static int hls_slice_header(HEVCContext *s) if (s->pps->slice_header_extension_present_flag) { unsigned int length = get_ue_golomb_long(gb); + if (length*8LL > get_bits_left(gb)) { + av_log(s->avctx, AV_LOG_ERROR, "too many slice_header_extension_data_bytes\n"); + return AVERROR_INVALIDDATA; + } for (i = 0; i < length; i++) skip_bits(gb, 8); // slice_header_extension_data_byte } @@ -712,6 +743,8 @@ static int hls_slice_header(HEVCContext *s) s->HEVClc->qp_y = s->sh.slice_qp; s->slice_initialized = 1; + s->HEVClc->tu.cu_qp_offset_cb = 0; + s->HEVClc->tu.cu_qp_offset_cr = 0; return 0; } @@ -735,7 +768,6 @@ 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); SAOParams *sao = &CTB(s->sao, rx, ry); int c_idx, i; @@ -752,6 +784,9 @@ static void hls_sao_param(HEVCContext *s, int rx, int ry) } for (c_idx = 0; c_idx < 3; c_idx++) { + int log2_sao_offset_scale = c_idx == 0 ? s->pps->log2_sao_offset_scale_luma : + s->pps->log2_sao_offset_scale_chroma; + if (!s->sh.slice_sample_adaptive_offset_flag[c_idx]) { sao->type_idx[c_idx] = SAO_NOT_APPLIED; continue; @@ -787,13 +822,14 @@ static void hls_sao_param(HEVCContext *s, int rx, int ry) // Inferred parameters sao->offset_val[c_idx][0] = 0; for (i = 0; i < 4; i++) { - sao->offset_val[c_idx][i + 1] = sao->offset_abs[c_idx][i] << shift; + sao->offset_val[c_idx][i + 1] = sao->offset_abs[c_idx][i]; if (sao->type_idx[c_idx] == SAO_EDGE) { if (i > 1) sao->offset_val[c_idx][i + 1] = -sao->offset_val[c_idx][i + 1]; } else if (sao->offset_sign[c_idx][i]) { sao->offset_val[c_idx][i + 1] = -sao->offset_val[c_idx][i + 1]; } + sao->offset_val[c_idx][i + 1] <<= log2_sao_offset_scale; } } } @@ -801,37 +837,52 @@ static void hls_sao_param(HEVCContext *s, int rx, int ry) #undef SET_SAO #undef CTB +static int hls_cross_component_pred(HEVCContext *s, int idx) { + HEVCLocalContext *lc = s->HEVClc; + int log2_res_scale_abs_plus1 = ff_hevc_log2_res_scale_abs(s, idx); + + if (log2_res_scale_abs_plus1 != 0) { + int res_scale_sign_flag = ff_hevc_res_scale_sign_flag(s, idx); + lc->tu.res_scale_val = (1 << (log2_res_scale_abs_plus1 - 1)) * + (1 - 2 * res_scale_sign_flag); + } else { + lc->tu.res_scale_val = 0; + } + + + return 0; +} + 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) { HEVCLocalContext *lc = s->HEVClc; + const int log2_trafo_size_c = log2_trafo_size - s->sps->hshift[1]; + int i; if (lc->cu.pred_mode == MODE_INTRA) { int trafo_size = 1 << log2_trafo_size; ff_hevc_set_neighbour_available(s, x0, y0, trafo_size, trafo_size); - s->hpc.intra_pred(s, x0, y0, log2_trafo_size, 0); - if (log2_trafo_size > 2) { - trafo_size = trafo_size << (s->sps->hshift[1] - 1); - ff_hevc_set_neighbour_available(s, x0, y0, trafo_size, trafo_size); - s->hpc.intra_pred(s, x0, y0, log2_trafo_size - 1, 1); - s->hpc.intra_pred(s, x0, y0, log2_trafo_size - 1, 2); - } else if (blk_idx == 3) { - trafo_size = trafo_size << s->sps->hshift[1]; - ff_hevc_set_neighbour_available(s, xBase, yBase, - trafo_size, trafo_size); - s->hpc.intra_pred(s, xBase, yBase, log2_trafo_size, 1); - s->hpc.intra_pred(s, xBase, yBase, log2_trafo_size, 2); - } + s->hpc.intra_pred[log2_trafo_size - 2](s, x0, y0, 0); } if (lc->tt.cbf_luma || SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0) || - SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0)) { + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0) || + (s->sps->chroma_format_idc == 2 && + (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (1 << log2_trafo_size_c)) || + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (1 << log2_trafo_size_c))))) { int scan_idx = SCAN_DIAG; int scan_idx_c = SCAN_DIAG; + int cbf_luma = lc->tt.cbf_luma; + int cbf_chroma = SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0) || + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0) || + (s->sps->chroma_format_idc == 2 && + (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (1 << log2_trafo_size_c)) || + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (1 << log2_trafo_size_c)))); if (s->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); @@ -854,38 +905,164 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, ff_hevc_set_qPy(s, x0, y0, cb_xBase, cb_yBase, log2_cb_size); } + if (s->sh.cu_chroma_qp_offset_enabled_flag && cbf_chroma && + !lc->cu.cu_transquant_bypass_flag && !lc->tu.is_cu_chroma_qp_offset_coded) { + int cu_chroma_qp_offset_flag = ff_hevc_cu_chroma_qp_offset_flag(s); + if (cu_chroma_qp_offset_flag) { + int cu_chroma_qp_offset_idx = 0; + if (s->pps->chroma_qp_offset_list_len_minus1 > 0) { + cu_chroma_qp_offset_idx = ff_hevc_cu_chroma_qp_offset_idx(s); + av_log(s->avctx, AV_LOG_ERROR, + "cu_chroma_qp_offset_idx not yet tested.\n"); + } + lc->tu.cu_qp_offset_cb = s->pps->cb_qp_offset_list[cu_chroma_qp_offset_idx]; + lc->tu.cu_qp_offset_cr = s->pps->cr_qp_offset_list[cu_chroma_qp_offset_idx]; + } else { + lc->tu.cu_qp_offset_cb = 0; + lc->tu.cu_qp_offset_cr = 0; + } + lc->tu.is_cu_chroma_qp_offset_coded = 1; + } + if (lc->cu.pred_mode == MODE_INTRA && log2_trafo_size < 4) { - if (lc->tu.cur_intra_pred_mode >= 6 && - lc->tu.cur_intra_pred_mode <= 14) { + if (lc->tu.intra_pred_mode >= 6 && + lc->tu.intra_pred_mode <= 14) { scan_idx = SCAN_VERT; - } else if (lc->tu.cur_intra_pred_mode >= 22 && - lc->tu.cur_intra_pred_mode <= 30) { + } else if (lc->tu.intra_pred_mode >= 22 && + lc->tu.intra_pred_mode <= 30) { scan_idx = SCAN_HORIZ; } - if (lc->pu.intra_pred_mode_c >= 6 && - lc->pu.intra_pred_mode_c <= 14) { + if (lc->tu.intra_pred_mode_c >= 6 && + lc->tu.intra_pred_mode_c <= 14) { scan_idx_c = SCAN_VERT; - } else if (lc->pu.intra_pred_mode_c >= 22 && - lc->pu.intra_pred_mode_c <= 30) { + } else if (lc->tu.intra_pred_mode_c >= 22 && + lc->tu.intra_pred_mode_c <= 30) { scan_idx_c = SCAN_HORIZ; } } - if (lc->tt.cbf_luma) + lc->tu.cross_pf = 0; + + if (cbf_luma) ff_hevc_hls_residual_coding(s, x0, y0, log2_trafo_size, scan_idx, 0); - if (log2_trafo_size > 2) { - if (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0)) - ff_hevc_hls_residual_coding(s, x0, y0, log2_trafo_size - 1, scan_idx_c, 1); - if (SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0)) - ff_hevc_hls_residual_coding(s, x0, y0, log2_trafo_size - 1, scan_idx_c, 2); + if (log2_trafo_size > 2 || s->sps->chroma_format_idc == 3) { + int trafo_size_h = 1 << (log2_trafo_size_c + s->sps->hshift[1]); + int trafo_size_v = 1 << (log2_trafo_size_c + s->sps->vshift[1]); + lc->tu.cross_pf = (s->pps->cross_component_prediction_enabled_flag && cbf_luma && + (lc->cu.pred_mode == MODE_INTER || + (lc->tu.chroma_mode_c == 4))); + + if (lc->tu.cross_pf) { + hls_cross_component_pred(s, 0); + } + for (i = 0; i < (s->sps->chroma_format_idc == 2 ? 2 : 1); i++) { + if (lc->cu.pred_mode == MODE_INTRA) { + ff_hevc_set_neighbour_available(s, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 1); + } + if (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (i << log2_trafo_size_c))) + ff_hevc_hls_residual_coding(s, x0, y0 + (i << log2_trafo_size_c), + log2_trafo_size_c, scan_idx_c, 1); + else + if (lc->tu.cross_pf) { + ptrdiff_t stride = s->frame->linesize[1]; + int hshift = s->sps->hshift[1]; + int vshift = s->sps->vshift[1]; + int16_t *coeffs_y = lc->tu.coeffs[0]; + int16_t *coeffs = lc->tu.coeffs[1]; + int size = 1 << log2_trafo_size_c; + + uint8_t *dst = &s->frame->data[1][(y0 >> vshift) * stride + + ((x0 >> hshift) << s->sps->pixel_shift)]; + for (i = 0; i < (size * size); i++) { + coeffs[i] = ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); + } + s->hevcdsp.transform_add[log2_trafo_size-2](dst, coeffs, stride); + } + } + + if (lc->tu.cross_pf) { + hls_cross_component_pred(s, 1); + } + for (i = 0; i < (s->sps->chroma_format_idc == 2 ? 2 : 1); i++) { + if (lc->cu.pred_mode == MODE_INTRA) { + ff_hevc_set_neighbour_available(s, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 2); + } + if (SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (i << log2_trafo_size_c))) + ff_hevc_hls_residual_coding(s, x0, y0 + (i << log2_trafo_size_c), + log2_trafo_size_c, scan_idx_c, 2); + else + if (lc->tu.cross_pf) { + ptrdiff_t stride = s->frame->linesize[2]; + int hshift = s->sps->hshift[2]; + int vshift = s->sps->vshift[2]; + int16_t *coeffs_y = lc->tu.coeffs[0]; + int16_t *coeffs = lc->tu.coeffs[1]; + int size = 1 << log2_trafo_size_c; + + uint8_t *dst = &s->frame->data[2][(y0 >> vshift) * stride + + ((x0 >> hshift) << s->sps->pixel_shift)]; + for (i = 0; i < (size * size); i++) { + coeffs[i] = ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); + } + s->hevcdsp.transform_add[log2_trafo_size-2](dst, coeffs, stride); + } + } } else if (blk_idx == 3) { - if (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], xBase, yBase)) - ff_hevc_hls_residual_coding(s, xBase, yBase, log2_trafo_size, scan_idx_c, 1); - if (SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], xBase, yBase)) - ff_hevc_hls_residual_coding(s, xBase, yBase, log2_trafo_size, scan_idx_c, 2); + int trafo_size_h = 1 << (log2_trafo_size + 1); + int trafo_size_v = 1 << (log2_trafo_size + s->sps->vshift[1]); + for (i = 0; i < (s->sps->chroma_format_idc == 2 ? 2 : 1); i++) { + if (lc->cu.pred_mode == MODE_INTRA) { + ff_hevc_set_neighbour_available(s, xBase, yBase + (i << log2_trafo_size), + trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 1); + } + if (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], xBase, yBase + (i << log2_trafo_size_c))) + ff_hevc_hls_residual_coding(s, xBase, yBase + (i << log2_trafo_size), + log2_trafo_size, scan_idx_c, 1); + } + for (i = 0; i < (s->sps->chroma_format_idc == 2 ? 2 : 1); i++) { + if (lc->cu.pred_mode == MODE_INTRA) { + ff_hevc_set_neighbour_available(s, xBase, yBase + (i << log2_trafo_size), + trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 2); + } + if (SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], xBase, yBase + (i << log2_trafo_size_c))) + ff_hevc_hls_residual_coding(s, xBase, yBase + (i << log2_trafo_size), + log2_trafo_size, scan_idx_c, 2); + } + } + } else if (lc->cu.pred_mode == MODE_INTRA) { + if (log2_trafo_size > 2 || s->sps->chroma_format_idc == 3) { + int trafo_size_h = 1 << (log2_trafo_size_c + s->sps->hshift[1]); + int trafo_size_v = 1 << (log2_trafo_size_c + s->sps->vshift[1]); + ff_hevc_set_neighbour_available(s, x0, y0, trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 1); + s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 2); + if (s->sps->chroma_format_idc == 2) { + ff_hevc_set_neighbour_available(s, x0, y0 + (1 << log2_trafo_size_c), + trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 1); + s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 2); + } + } else if (blk_idx == 3) { + int trafo_size_h = 1 << (log2_trafo_size + 1); + int trafo_size_v = 1 << (log2_trafo_size + s->sps->vshift[1]); + ff_hevc_set_neighbour_available(s, xBase, yBase, + trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 1); + s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 2); + if (s->sps->chroma_format_idc == 2) { + ff_hevc_set_neighbour_available(s, xBase, yBase + (1 << (log2_trafo_size)), + trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 1); + s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 2); + } } } + return 0; } @@ -918,16 +1095,38 @@ static int hls_transform_tree(HEVCContext *s, int x0, int y0, SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth - 1], xBase, yBase); SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0) = SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth - 1], xBase, yBase); + if (s->sps->chroma_format_idc == 2) { + int xBase_cb = xBase & ((1 << log2_trafo_size) - 1); + int yBase_cb = yBase & ((1 << log2_trafo_size) - 1); + SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) = + SAMPLE_CBF2(lc->tt.cbf_cb[trafo_depth - 1], xBase_cb, yBase_cb + (1 << (log2_trafo_size))); + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) = + SAMPLE_CBF2(lc->tt.cbf_cr[trafo_depth - 1], xBase_cb, yBase_cb + (1 << (log2_trafo_size))); + } } else { SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0) = SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0) = 0; + if (s->sps->chroma_format_idc == 2) { + SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) = + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) = 0; + } } if (lc->cu.intra_split_flag) { - if (trafo_depth == 1) - lc->tu.cur_intra_pred_mode = lc->pu.intra_pred_mode[blk_idx]; + if (trafo_depth == 1) { + lc->tu.intra_pred_mode = lc->pu.intra_pred_mode[blk_idx]; + if (s->sps->chroma_format_idc == 3) { + lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[blk_idx]; + lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[blk_idx]; + } else { + lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[0]; + lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[0]; + } + } } else { - lc->tu.cur_intra_pred_mode = lc->pu.intra_pred_mode[0]; + lc->tu.intra_pred_mode = lc->pu.intra_pred_mode[0]; + lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[0]; + lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[0]; } lc->tt.cbf_luma = 1; @@ -948,17 +1147,25 @@ static int hls_transform_tree(HEVCContext *s, int x0, int y0, lc->tt.inter_split_flag; } - if (log2_trafo_size > 2) { + if (log2_trafo_size > 2 || s->sps->chroma_format_idc == 3) { if (trafo_depth == 0 || SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth - 1], xBase, yBase)) { SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0) = ff_hevc_cbf_cb_cr_decode(s, trafo_depth); + if (s->sps->chroma_format_idc == 2 && (!split_transform_flag || log2_trafo_size == 3)) { + SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) = + ff_hevc_cbf_cb_cr_decode(s, trafo_depth); + } } if (trafo_depth == 0 || SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth - 1], xBase, yBase)) { SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0) = ff_hevc_cbf_cb_cr_decode(s, trafo_depth); + if (s->sps->chroma_format_idc == 2 && (!split_transform_flag || log2_trafo_size == 3)) { + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) = + ff_hevc_cbf_cb_cr_decode(s, trafo_depth); + } } } @@ -993,7 +1200,10 @@ static int hls_transform_tree(HEVCContext *s, int x0, int y0, if (lc->cu.pred_mode == MODE_INTRA || trafo_depth != 0 || SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0) || - SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0)) { + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0) || + (s->sps->chroma_format_idc == 2 && + (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) || + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1)))))) { lc->tt.cbf_luma = ff_hevc_cbf_luma_decode(s, trafo_depth); } @@ -1013,9 +1223,7 @@ static int hls_transform_tree(HEVCContext *s, int x0, int y0, } } if (!s->sh.disable_deblocking_filter_flag) { - ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_trafo_size, - lc->slice_or_tiles_up_boundary, - lc->slice_or_tiles_left_boundary); + ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_trafo_size); if (s->pps->transquant_bypass_enable_flag && lc->cu.cu_transquant_bypass_flag) set_deblocking_bypass(s, x0, y0, log2_trafo_size); @@ -1037,26 +1245,34 @@ static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size) 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)]; - int length = cb_size * cb_size * s->sps->pcm.bit_depth + ((cb_size * cb_size) >> 1) * s->sps->pcm.bit_depth_chroma; - const uint8_t *pcm = skip_bytes(&s->HEVClc->cc, (length + 7) >> 3); + int length = cb_size * cb_size * s->sps->pcm.bit_depth + + (((cb_size >> s->sps->hshift[1]) * (cb_size >> s->sps->vshift[1])) + + ((cb_size >> s->sps->hshift[2]) * (cb_size >> s->sps->vshift[2]))) * + s->sps->pcm.bit_depth_chroma; + const uint8_t *pcm = skip_bytes(&lc->cc, (length + 7) >> 3); int ret; - ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size, - lc->slice_or_tiles_up_boundary, - lc->slice_or_tiles_left_boundary); + if (!s->sh.disable_deblocking_filter_flag) + ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size); ret = init_get_bits(&gb, pcm, length); 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, cb_size, &gb, s->sps->pcm.bit_depth); + s->hevcdsp.put_pcm(dst1, stride1, + cb_size >> s->sps->hshift[1], + cb_size >> s->sps->vshift[1], + &gb, s->sps->pcm.bit_depth_chroma); + s->hevcdsp.put_pcm(dst2, stride2, + cb_size >> s->sps->hshift[2], + cb_size >> s->sps->vshift[2], + &gb, s->sps->pcm.bit_depth_chroma); return 0; } /** - * 8.5.3.2.2.1 Luma sample interpolation process + * 8.5.3.2.2.1 Luma sample unidirectional interpolation process * * @param s HEVC decoding context * @param dst target buffer for block data at block position @@ -1067,49 +1283,148 @@ static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size) * @param y_off vertical position of block from origin (0, 0) * @param block_w width of block * @param block_h height of block + * @param luma_weight weighting factor applied to the luma prediction + * @param luma_offset additive offset applied to the luma prediction value */ -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) + +static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, + AVFrame *ref, const Mv *mv, int x_off, int y_off, + int block_w, int block_h, int luma_weight, int luma_offset) { 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 mx = mv->x & 3; - int my = mv->y & 3; - int extra_left = ff_hevc_qpel_extra_before[mx]; - int extra_top = ff_hevc_qpel_extra_before[my]; + int mx = mv->x & 3; + int my = mv->y & 3; + int weight_flag = (s->sh.slice_type == P_SLICE && s->pps->weighted_pred_flag) || + (s->sh.slice_type == B_SLICE && s->pps->weighted_bipred_flag); + int idx = ff_hevc_pel_weight[block_w]; x_off += mv->x >> 2; y_off += mv->y >> 2; src += y_off * srcstride + (x_off << s->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]) { + if (x_off < QPEL_EXTRA_BEFORE || y_off < QPEL_EXTRA_AFTER || + x_off >= pic_width - block_w - QPEL_EXTRA_AFTER || + y_off >= pic_height - block_h - QPEL_EXTRA_AFTER) { const int edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->sps->pixel_shift; - int offset = extra_top * srcstride + (extra_left << s->sps->pixel_shift); - int buf_offset = extra_top * - edge_emu_stride + (extra_left << s->sps->pixel_shift); + int offset = QPEL_EXTRA_BEFORE * srcstride + (QPEL_EXTRA_BEFORE << s->sps->pixel_shift); + int buf_offset = QPEL_EXTRA_BEFORE * edge_emu_stride + (QPEL_EXTRA_BEFORE << s->sps->pixel_shift); s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src - offset, edge_emu_stride, srcstride, - block_w + ff_hevc_qpel_extra[mx], - block_h + ff_hevc_qpel_extra[my], - x_off - extra_left, y_off - extra_top, + block_w + QPEL_EXTRA, + block_h + QPEL_EXTRA, + x_off - QPEL_EXTRA_BEFORE, y_off - QPEL_EXTRA_BEFORE, pic_width, pic_height); 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); + + if (!weight_flag) + s->hevcdsp.put_hevc_qpel_uni[idx][!!my][!!mx](dst, dststride, src, srcstride, + block_h, mx, my, block_w); + else + s->hevcdsp.put_hevc_qpel_uni_w[idx][!!my][!!mx](dst, dststride, src, srcstride, + block_h, s->sh.luma_log2_weight_denom, + luma_weight, luma_offset, mx, my, block_w); } /** - * 8.5.3.2.2.2 Chroma sample interpolation process + * 8.5.3.2.2.1 Luma sample bidirectional interpolation process + * + * @param s HEVC decoding context + * @param dst target buffer for block data at block position + * @param dststride stride of the dst buffer + * @param ref0 reference picture0 buffer at origin (0, 0) + * @param mv0 motion vector0 (relative to block position) to get pixel data from + * @param x_off horizontal position of block from origin (0, 0) + * @param y_off vertical position of block from origin (0, 0) + * @param block_w width of block + * @param block_h height of block + * @param ref1 reference picture1 buffer at origin (0, 0) + * @param mv1 motion vector1 (relative to block position) to get pixel data from + * @param current_mv current motion vector structure + */ + static void luma_mc_bi(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, + AVFrame *ref0, const Mv *mv0, int x_off, int y_off, + int block_w, int block_h, AVFrame *ref1, const Mv *mv1, struct MvField *current_mv) +{ + HEVCLocalContext *lc = s->HEVClc; + DECLARE_ALIGNED(16, int16_t, tmp[MAX_PB_SIZE * MAX_PB_SIZE]); + ptrdiff_t src0stride = ref0->linesize[0]; + ptrdiff_t src1stride = ref1->linesize[0]; + int pic_width = s->sps->width; + int pic_height = s->sps->height; + int mx0 = mv0->x & 3; + int my0 = mv0->y & 3; + int mx1 = mv1->x & 3; + int my1 = mv1->y & 3; + int weight_flag = (s->sh.slice_type == P_SLICE && s->pps->weighted_pred_flag) || + (s->sh.slice_type == B_SLICE && s->pps->weighted_bipred_flag); + int x_off0 = x_off + (mv0->x >> 2); + int y_off0 = y_off + (mv0->y >> 2); + int x_off1 = x_off + (mv1->x >> 2); + int y_off1 = y_off + (mv1->y >> 2); + int idx = ff_hevc_pel_weight[block_w]; + + uint8_t *src0 = ref0->data[0] + y_off0 * src0stride + (int)((unsigned)x_off0 << s->sps->pixel_shift); + uint8_t *src1 = ref1->data[0] + y_off1 * src1stride + (int)((unsigned)x_off1 << s->sps->pixel_shift); + + if (x_off0 < QPEL_EXTRA_BEFORE || y_off0 < QPEL_EXTRA_AFTER || + x_off0 >= pic_width - block_w - QPEL_EXTRA_AFTER || + y_off0 >= pic_height - block_h - QPEL_EXTRA_AFTER) { + const int edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->sps->pixel_shift; + int offset = QPEL_EXTRA_BEFORE * src0stride + (QPEL_EXTRA_BEFORE << s->sps->pixel_shift); + int buf_offset = QPEL_EXTRA_BEFORE * edge_emu_stride + (QPEL_EXTRA_BEFORE << s->sps->pixel_shift); + + s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src0 - offset, + edge_emu_stride, src0stride, + block_w + QPEL_EXTRA, + block_h + QPEL_EXTRA, + x_off0 - QPEL_EXTRA_BEFORE, y_off0 - QPEL_EXTRA_BEFORE, + pic_width, pic_height); + src0 = lc->edge_emu_buffer + buf_offset; + src0stride = edge_emu_stride; + } + + if (x_off1 < QPEL_EXTRA_BEFORE || y_off1 < QPEL_EXTRA_AFTER || + x_off1 >= pic_width - block_w - QPEL_EXTRA_AFTER || + y_off1 >= pic_height - block_h - QPEL_EXTRA_AFTER) { + const int edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->sps->pixel_shift; + int offset = QPEL_EXTRA_BEFORE * src1stride + (QPEL_EXTRA_BEFORE << s->sps->pixel_shift); + int buf_offset = QPEL_EXTRA_BEFORE * edge_emu_stride + (QPEL_EXTRA_BEFORE << s->sps->pixel_shift); + + s->vdsp.emulated_edge_mc(lc->edge_emu_buffer2, src1 - offset, + edge_emu_stride, src1stride, + block_w + QPEL_EXTRA, + block_h + QPEL_EXTRA, + x_off1 - QPEL_EXTRA_BEFORE, y_off1 - QPEL_EXTRA_BEFORE, + pic_width, pic_height); + src1 = lc->edge_emu_buffer2 + buf_offset; + src1stride = edge_emu_stride; + } + + s->hevcdsp.put_hevc_qpel[idx][!!my0][!!mx0](tmp, MAX_PB_SIZE, src0, src0stride, + block_h, mx0, my0, block_w); + if (!weight_flag) + s->hevcdsp.put_hevc_qpel_bi[idx][!!my1][!!mx1](dst, dststride, src1, src1stride, tmp, MAX_PB_SIZE, + block_h, mx1, my1, block_w); + else + s->hevcdsp.put_hevc_qpel_bi_w[idx][!!my1][!!mx1](dst, dststride, src1, src1stride, tmp, MAX_PB_SIZE, + block_h, 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]], + mx1, my1, block_w); + +} + +/** + * 8.5.3.2.2.2 Chroma sample uniprediction interpolation process * * @param s HEVC decoding context * @param dst1 target buffer for block data at block position (U plane) @@ -1121,70 +1436,165 @@ static void luma_mc(HEVCContext *s, int16_t *dst, ptrdiff_t dststride, * @param y_off vertical position of block from origin (0, 0) * @param block_w width of block * @param block_h height of block + * @param chroma_weight weighting factor applied to the chroma prediction + * @param chroma_offset additive offset applied to the chroma prediction value */ -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) + +static void chroma_mc_uni(HEVCContext *s, uint8_t *dst0, + ptrdiff_t dststride, uint8_t *src0, ptrdiff_t srcstride, int reflist, + int x_off, int y_off, int block_w, int block_h, struct MvField *current_mv, int chroma_weight, int chroma_offset) { 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->sps->width >> s->sps->hshift[1]; + int pic_height = s->sps->height >> s->sps->vshift[1]; + const Mv *mv = ¤t_mv->mv[reflist]; + int weight_flag = (s->sh.slice_type == P_SLICE && s->pps->weighted_pred_flag) || + (s->sh.slice_type == B_SLICE && s->pps->weighted_bipred_flag); + int idx = ff_hevc_pel_weight[block_w]; + int hshift = s->sps->hshift[1]; + int vshift = s->sps->vshift[1]; + intptr_t mx = mv->x & ((1 << (2 + hshift)) - 1); + intptr_t my = mv->y & ((1 << (2 + vshift)) - 1); + intptr_t _mx = mx << (1 - hshift); + intptr_t _my = my << (1 - vshift); - 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); + x_off += mv->x >> (2 + hshift); + y_off += mv->y >> (2 + vshift); + src0 += y_off * srcstride + (x_off << s->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 offset0 = EPEL_EXTRA_BEFORE * (srcstride + (1 << s->sps->pixel_shift)); + int buf_offset0 = EPEL_EXTRA_BEFORE * + (edge_emu_stride + (1 << s->sps->pixel_shift)); + s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src0 - offset0, + edge_emu_stride, srcstride, + block_w + EPEL_EXTRA, block_h + EPEL_EXTRA, + x_off - EPEL_EXTRA_BEFORE, + y_off - EPEL_EXTRA_BEFORE, + pic_width, pic_height); + + src0 = lc->edge_emu_buffer + buf_offset0; + srcstride = edge_emu_stride; + } + if (!weight_flag) + s->hevcdsp.put_hevc_epel_uni[idx][!!my][!!mx](dst0, dststride, src0, srcstride, + block_h, _mx, _my, block_w); + else + s->hevcdsp.put_hevc_epel_uni_w[idx][!!my][!!mx](dst0, dststride, src0, srcstride, + block_h, s->sh.chroma_log2_weight_denom, + chroma_weight, chroma_offset, _mx, _my, block_w); +} + +/** + * 8.5.3.2.2.2 Chroma sample bidirectional interpolation process + * + * @param s HEVC decoding context + * @param dst target buffer for block data at block position + * @param dststride stride of the dst buffer + * @param ref0 reference picture0 buffer at origin (0, 0) + * @param mv0 motion vector0 (relative to block position) to get pixel data from + * @param x_off horizontal position of block from origin (0, 0) + * @param y_off vertical position of block from origin (0, 0) + * @param block_w width of block + * @param block_h height of block + * @param ref1 reference picture1 buffer at origin (0, 0) + * @param mv1 motion vector1 (relative to block position) to get pixel data from + * @param current_mv current motion vector structure + * @param cidx chroma component(cb, cr) + */ +static void chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVFrame *ref0, AVFrame *ref1, + int x_off, int y_off, int block_w, int block_h, struct MvField *current_mv, int cidx) +{ + DECLARE_ALIGNED(16, int16_t, tmp [MAX_PB_SIZE * MAX_PB_SIZE]); + int tmpstride = MAX_PB_SIZE; + HEVCLocalContext *lc = s->HEVClc; + uint8_t *src1 = ref0->data[cidx+1]; + uint8_t *src2 = ref1->data[cidx+1]; + ptrdiff_t src1stride = ref0->linesize[cidx+1]; + ptrdiff_t src2stride = ref1->linesize[cidx+1]; + int weight_flag = (s->sh.slice_type == P_SLICE && s->pps->weighted_pred_flag) || + (s->sh.slice_type == B_SLICE && s->pps->weighted_bipred_flag); + int pic_width = s->sps->width >> s->sps->hshift[1]; + int pic_height = s->sps->height >> s->sps->vshift[1]; + Mv *mv0 = ¤t_mv->mv[0]; + Mv *mv1 = ¤t_mv->mv[1]; + int hshift = s->sps->hshift[1]; + int vshift = s->sps->vshift[1]; + + intptr_t mx0 = mv0->x & ((1 << (2 + hshift)) - 1); + intptr_t my0 = mv0->y & ((1 << (2 + vshift)) - 1); + intptr_t mx1 = mv1->x & ((1 << (2 + hshift)) - 1); + intptr_t my1 = mv1->y & ((1 << (2 + vshift)) - 1); + intptr_t _mx0 = mx0 << (1 - hshift); + intptr_t _my0 = my0 << (1 - vshift); + intptr_t _mx1 = mx1 << (1 - hshift); + intptr_t _my1 = my1 << (1 - vshift); + + int x_off0 = x_off + (mv0->x >> (2 + hshift)); + int y_off0 = y_off + (mv0->y >> (2 + vshift)); + int x_off1 = x_off + (mv1->x >> (2 + hshift)); + int y_off1 = y_off + (mv1->y >> (2 + vshift)); + int idx = ff_hevc_pel_weight[block_w]; + src1 += y_off0 * src1stride + (int)((unsigned)x_off0 << s->sps->pixel_shift); + src2 += y_off1 * src2stride + (int)((unsigned)x_off1 << s->sps->pixel_shift); + + if (x_off0 < EPEL_EXTRA_BEFORE || y_off0 < EPEL_EXTRA_AFTER || + x_off0 >= pic_width - block_w - EPEL_EXTRA_AFTER || + y_off0 >= 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)); 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)); - int buf_offset2 = EPEL_EXTRA_BEFORE * - (edge_emu_stride + (1 << s->sps->pixel_shift)); s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src1 - offset1, edge_emu_stride, src1stride, block_w + EPEL_EXTRA, block_h + EPEL_EXTRA, - x_off - EPEL_EXTRA_BEFORE, - y_off - EPEL_EXTRA_BEFORE, + x_off0 - EPEL_EXTRA_BEFORE, + y_off0 - EPEL_EXTRA_BEFORE, pic_width, pic_height); 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->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src2 - offset2, + if (x_off1 < EPEL_EXTRA_BEFORE || y_off1 < EPEL_EXTRA_AFTER || + x_off1 >= pic_width - block_w - EPEL_EXTRA_AFTER || + y_off1 >= 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 * (src2stride + (1 << s->sps->pixel_shift)); + int buf_offset1 = EPEL_EXTRA_BEFORE * + (edge_emu_stride + (1 << s->sps->pixel_shift)); + + s->vdsp.emulated_edge_mc(lc->edge_emu_buffer2, src2 - offset1, edge_emu_stride, src2stride, block_w + EPEL_EXTRA, block_h + EPEL_EXTRA, - x_off - EPEL_EXTRA_BEFORE, - y_off - EPEL_EXTRA_BEFORE, + x_off1 - EPEL_EXTRA_BEFORE, + y_off1 - EPEL_EXTRA_BEFORE, pic_width, pic_height); - 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); - } 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); + src2 = lc->edge_emu_buffer2 + buf_offset1; + src2stride = edge_emu_stride; } + + s->hevcdsp.put_hevc_epel[idx][!!my0][!!mx0](tmp, tmpstride, src1, src1stride, + block_h, _mx0, _my0, block_w); + if (!weight_flag) + s->hevcdsp.put_hevc_epel_bi[idx][!!my1][!!mx1](dst0, s->frame->linesize[cidx+1], + src2, src2stride, tmp, tmpstride, + block_h, _mx1, _my1, block_w); + else + s->hevcdsp.put_hevc_epel_bi_w[idx][!!my1][!!mx1](dst0, s->frame->linesize[cidx+1], + src2, src2stride, tmp, tmpstride, + block_h, + s->sh.chroma_log2_weight_denom, + s->sh.chroma_weight_l0[current_mv->ref_idx[0]][cidx], + s->sh.chroma_weight_l1[current_mv->ref_idx[1]][cidx], + s->sh.chroma_offset_l0[current_mv->ref_idx[0]][cidx], + s->sh.chroma_offset_l1[current_mv->ref_idx[1]][cidx], + _mx1, _my1, block_w); } static void hevc_await_progress(HEVCContext *s, HEVCFrame *ref, @@ -1198,7 +1608,7 @@ static void hevc_await_progress(HEVCContext *s, HEVCFrame *ref, static void hls_prediction_unit(HEVCContext *s, int x0, int y0, int nPbW, int nPbH, - int log2_cb_size, int partIdx) + int log2_cb_size, int partIdx, int idx) { #define POS(c_idx, x, y) \ &s->frame->data[c_idx][((y) >> s->sps->vshift[c_idx]) * s->frame->linesize[c_idx] + \ @@ -1212,9 +1622,6 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, MvField *tab_mvf = s->ref->tab_mvf; RefPicList *refPicList = s->ref->refPicList; HEVCFrame *ref0, *ref1; - - int tmpstride = MAX_PB_SIZE; - uint8_t *dst0 = POS(0, x0, y0); uint8_t *dst1 = POS(1, x0, y0); uint8_t *dst2 = POS(2, x0, y0); @@ -1241,8 +1648,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, x_pu = x0 >> s->sps->log2_min_pu_size; y_pu = y0 >> s->sps->log2_min_pu_size; - for (i = 0; i < nPbW >> s->sps->log2_min_pu_size; i++) - for (j = 0; j < nPbH >> s->sps->log2_min_pu_size; j++) + 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); @@ -1257,12 +1664,13 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, x_pu = x0 >> s->sps->log2_min_pu_size; y_pu = y0 >> s->sps->log2_min_pu_size; - for (i = 0; i < nPbW >> s->sps->log2_min_pu_size; i++) - for (j = 0; j < nPbH >> s->sps->log2_min_pu_size; j++) + 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); + current_mv.pred_flag = 0; if (s->sh.slice_type == B_SLICE) inter_pred_idc = ff_hevc_inter_pred_idc_decode(s, nPbW, nPbH); @@ -1271,7 +1679,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, 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; + current_mv.pred_flag = PF_L0; ff_hevc_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, @@ -1294,7 +1702,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ff_hevc_hls_mvd_coding(s, x0, y0, 1); } - current_mv.pred_flag[1] = 1; + current_mv.pred_flag += PF_L1; 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, @@ -1306,154 +1714,75 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, x_pu = x0 >> s->sps->log2_min_pu_size; y_pu = y0 >> s->sps->log2_min_pu_size; - for (i = 0; i < nPbW >> s->sps->log2_min_pu_size; i++) - for(j = 0; j < nPbH >> s->sps->log2_min_pu_size; j++) + 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; } } - if (current_mv.pred_flag[0]) { + if (current_mv.pred_flag & PF_L0) { ref0 = refPicList[0].ref[current_mv.ref_idx[0]]; if (!ref0) return; hevc_await_progress(s, ref0, ¤t_mv.mv[0], y0, nPbH); } - if (current_mv.pred_flag[1]) { + if (current_mv.pred_flag & PF_L1) { ref1 = refPicList[1].ref[current_mv.ref_idx[1]]; if (!ref1) return; hevc_await_progress(s, ref1, ¤t_mv.mv[1], y0, nPbH); } - 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 (current_mv.pred_flag == PF_L0) { + int x0_c = x0 >> s->sps->hshift[1]; + int y0_c = y0 >> s->sps->vshift[1]; + int nPbW_c = nPbW >> s->sps->hshift[1]; + int nPbH_c = nPbH >> s->sps->vshift[1]; - luma_mc(s, tmp, tmpstride, ref0->frame, - ¤t_mv.mv[0], x0, y0, nPbW, nPbH); + luma_mc_uni(s, dst0, s->frame->linesize[0], ref0->frame, + ¤t_mv.mv[0], x0, y0, nPbW, nPbH, + s->sh.luma_weight_l0[current_mv.ref_idx[0]], + s->sh.luma_offset_l0[current_mv.ref_idx[0]]); - 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); - } else { - s->hevcdsp.put_unweighted_pred(dst0, s->frame->linesize[0], tmp, tmpstride, nPbW, nPbH); - } - chroma_mc(s, tmp, tmp2, tmpstride, ref0->frame, - ¤t_mv.mv[0], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2); + chroma_mc_uni(s, dst1, s->frame->linesize[1], ref0->frame->data[1], ref0->frame->linesize[1], + 0, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, + s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0]); + chroma_mc_uni(s, dst2, s->frame->linesize[2], ref0->frame->data[2], ref0->frame->linesize[2], + 0, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, + s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1]); + } else if (current_mv.pred_flag == PF_L1) { + int x0_c = x0 >> s->sps->hshift[1]; + int y0_c = y0 >> s->sps->vshift[1]; + int nPbW_c = nPbW >> s->sps->hshift[1]; + int nPbH_c = nPbH >> s->sps->vshift[1]; - 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); - } 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); - } - } 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]); + luma_mc_uni(s, dst0, s->frame->linesize[0], ref1->frame, + ¤t_mv.mv[1], x0, y0, nPbW, nPbH, + s->sh.luma_weight_l1[current_mv.ref_idx[1]], + s->sh.luma_offset_l1[current_mv.ref_idx[1]]); - if (!ref1) - return; + chroma_mc_uni(s, dst1, s->frame->linesize[1], ref1->frame->data[1], ref1->frame->linesize[1], + 1, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, + s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0]); - luma_mc(s, tmp, tmpstride, ref1->frame, - ¤t_mv.mv[1], x0, y0, nPbW, nPbH); + chroma_mc_uni(s, dst2, s->frame->linesize[2], ref1->frame->data[2], ref1->frame->linesize[2], + 1, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, + s->sh.chroma_weight_l1[current_mv.ref_idx[1]][1], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1]); + } else if (current_mv.pred_flag == PF_BI) { + int x0_c = x0 >> s->sps->hshift[1]; + int y0_c = y0 >> s->sps->vshift[1]; + int nPbW_c = nPbW >> s->sps->hshift[1]; + int nPbH_c = nPbH >> s->sps->vshift[1]; - 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); - } else { - s->hevcdsp.put_unweighted_pred(dst0, s->frame->linesize[0], tmp, tmpstride, nPbW, nPbH); - } + luma_mc_bi(s, dst0, s->frame->linesize[0], ref0->frame, + ¤t_mv.mv[0], x0, y0, nPbW, nPbH, + ref1->frame, ¤t_mv.mv[1], ¤t_mv); - chroma_mc(s, tmp, tmp2, tmpstride, ref1->frame, - ¤t_mv.mv[1], x0/2, y0/2, nPbW/2, nPbH/2); + chroma_mc_bi(s, dst1, s->frame->linesize[1], ref0->frame, ref1->frame, + x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, 0); - 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); - } 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); - } - } 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); - 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); - } else { - s->hevcdsp.put_weighted_pred_avg(dst0, s->frame->linesize[0], - tmp, tmp2, tmpstride, nPbW, nPbH); - } - - chroma_mc(s, tmp, tmp2, tmpstride, ref0->frame, - ¤t_mv.mv[0], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2); - 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); - } 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); - } + chroma_mc_bi(s, dst2, s->frame->linesize[2], ref0->frame, ref1->frame, + x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, 1); } } @@ -1533,15 +1862,7 @@ static int luma_intra_pred_mode(HEVCContext *s, int x0, int y0, int pu_size, intra_pred_mode, size_in_pus); for (j = 0; j < size_in_pus; j++) { - tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].is_intra = 1; - tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].pred_flag[0] = 0; - tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].pred_flag[1] = 0; - tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].ref_idx[0] = 0; - tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].ref_idx[1] = 0; - tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].mv[0].x = 0; - tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].mv[0].y = 0; - tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].mv[1].x = 0; - tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].mv[1].y = 0; + tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].pred_flag = PF_INTRA; } } @@ -1561,6 +1882,10 @@ static av_always_inline void set_ct_depth(HEVCContext *s, int x0, int y0, ct_depth, length); } +static const uint8_t tab_mode_idx[] = { + 0, 1, 2, 2, 2, 2, 3, 5, 7, 8, 10, 12, 13, 15, 17, 18, 19, 20, + 21, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, 29, 29, 30, 31}; + static void intra_prediction_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) { @@ -1590,14 +1915,42 @@ static void intra_prediction_unit(HEVCContext *s, int x0, int y0, } } - chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s); - if (chroma_mode != 4) { - if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode]) - lc->pu.intra_pred_mode_c = 34; - else - lc->pu.intra_pred_mode_c = intra_chroma_table[chroma_mode]; - } else { - lc->pu.intra_pred_mode_c = lc->pu.intra_pred_mode[0]; + if (s->sps->chroma_format_idc == 3) { + for (i = 0; i < side; i++) { + for (j = 0; j < side; j++) { + lc->pu.chroma_mode_c[2 * i + j] = chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s); + if (chroma_mode != 4) { + if (lc->pu.intra_pred_mode[2 * i + j] == intra_chroma_table[chroma_mode]) + lc->pu.intra_pred_mode_c[2 * i + j] = 34; + else + lc->pu.intra_pred_mode_c[2 * i + j] = intra_chroma_table[chroma_mode]; + } else { + lc->pu.intra_pred_mode_c[2 * i + j] = lc->pu.intra_pred_mode[2 * i + j]; + } + } + } + } else if (s->sps->chroma_format_idc == 2) { + int mode_idx; + lc->pu.chroma_mode_c[0] = chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s); + if (chroma_mode != 4) { + if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode]) + mode_idx = 34; + else + mode_idx = intra_chroma_table[chroma_mode]; + } else { + mode_idx = lc->pu.intra_pred_mode[0]; + } + lc->pu.intra_pred_mode_c[0] = tab_mode_idx[mode_idx]; + } else if (s->sps->chroma_format_idc != 0) { + chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s); + if (chroma_mode != 4) { + if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode]) + lc->pu.intra_pred_mode_c[0] = 34; + else + lc->pu.intra_pred_mode_c[0] = intra_chroma_table[chroma_mode]; + } else { + lc->pu.intra_pred_mode_c[0] = lc->pu.intra_pred_mode[0]; + } } } @@ -1616,11 +1969,12 @@ static void intra_prediction_unit_default_value(HEVCContext *s, if (size_in_pus == 0) size_in_pus = 1; - for (j = 0; j < size_in_pus; j++) { + for (j = 0; j < size_in_pus; j++) memset(&s->tab_ipm[(y_pu + j) * min_pu_width + x_pu], INTRA_DC, size_in_pus); - for (k = 0; k < size_in_pus; k++) - tab_mvf[(y_pu + j) * min_pu_width + x_pu + k].is_intra = lc->cu.pred_mode == MODE_INTRA; - } + if (lc->cu.pred_mode == MODE_INTRA) + for (j = 0; j < size_in_pus; j++) + for (k = 0; k < size_in_pus; k++) + tab_mvf[(y_pu + j) * min_pu_width + x_pu + k].pred_flag = PF_INTRA; } static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) @@ -1632,8 +1986,9 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) int min_cb_width = s->sps->min_cb_width; int x_cb = x0 >> log2_min_cb_size; int y_cb = y0 >> log2_min_cb_size; + int idx = log2_cb_size - 2; + int qp_block_mask = (1<<(s->sps->log2_ctb_size - s->pps->diff_cu_qp_delta_depth)) - 1; int x, y, ret; - int qp_block_mask = (1<<(s->sps->log2_ctb_size - s->pps->diff_cu_qp_delta_depth)) - 1; lc->cu.x = x0; lc->cu.y = y0; @@ -1656,7 +2011,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); @@ -1666,13 +2020,11 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) } if (SAMPLE_CTB(s->skip_flag, x_cb, y_cb)) { - hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0); + hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx); intra_prediction_unit_default_value(s, x0, y0, log2_cb_size); if (!s->sh.disable_deblocking_filter_flag) - ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size, - lc->slice_or_tiles_up_boundary, - lc->slice_or_tiles_left_boundary); + ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size); } else { if (s->sh.slice_type != I_SLICE) lc->cu.pred_mode = ff_hevc_pred_mode_decode(s); @@ -1704,37 +2056,37 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) intra_prediction_unit_default_value(s, x0, y0, log2_cb_size); switch (lc->cu.part_mode) { case PART_2Nx2N: - hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0); + hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx); break; case PART_2NxN: - hls_prediction_unit(s, x0, y0, cb_size, cb_size / 2, log2_cb_size, 0); - hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size, cb_size / 2, log2_cb_size, 1); + hls_prediction_unit(s, x0, y0, cb_size, cb_size / 2, log2_cb_size, 0, idx); + hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size, cb_size / 2, log2_cb_size, 1, idx); break; case PART_Nx2N: - hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size, log2_cb_size, 0); - hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size, log2_cb_size, 1); + hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size, log2_cb_size, 0, idx - 1); + hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size, log2_cb_size, 1, idx - 1); break; case PART_2NxnU: - hls_prediction_unit(s, x0, y0, cb_size, cb_size / 4, log2_cb_size, 0); - hls_prediction_unit(s, x0, y0 + cb_size / 4, cb_size, cb_size * 3 / 4, log2_cb_size, 1); + hls_prediction_unit(s, x0, y0, cb_size, cb_size / 4, log2_cb_size, 0, idx); + hls_prediction_unit(s, x0, y0 + cb_size / 4, cb_size, cb_size * 3 / 4, log2_cb_size, 1, idx); break; case PART_2NxnD: - hls_prediction_unit(s, x0, y0, cb_size, cb_size * 3 / 4, log2_cb_size, 0); - hls_prediction_unit(s, x0, y0 + cb_size * 3 / 4, cb_size, cb_size / 4, log2_cb_size, 1); + hls_prediction_unit(s, x0, y0, cb_size, cb_size * 3 / 4, log2_cb_size, 0, idx); + hls_prediction_unit(s, x0, y0 + cb_size * 3 / 4, cb_size, cb_size / 4, log2_cb_size, 1, idx); break; case PART_nLx2N: - hls_prediction_unit(s, x0, y0, cb_size / 4, cb_size, log2_cb_size, 0); - hls_prediction_unit(s, x0 + cb_size / 4, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 1); + hls_prediction_unit(s, x0, y0, cb_size / 4, cb_size, log2_cb_size, 0, idx - 2); + hls_prediction_unit(s, x0 + cb_size / 4, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 1, idx - 2); break; case PART_nRx2N: - hls_prediction_unit(s, x0, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 0); - hls_prediction_unit(s, x0 + cb_size * 3 / 4, y0, cb_size / 4, cb_size, log2_cb_size, 1); + hls_prediction_unit(s, x0, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 0, idx - 2); + hls_prediction_unit(s, x0 + cb_size * 3 / 4, y0, cb_size / 4, cb_size, log2_cb_size, 1, idx - 2); break; case PART_NxN: - hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size / 2, log2_cb_size, 0); - hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size / 2, log2_cb_size, 1); - hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 2); - hls_prediction_unit(s, x0 + cb_size / 2, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 3); + hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size / 2, log2_cb_size, 0, idx - 1); + hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size / 2, log2_cb_size, 1, idx - 1); + hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 2, idx - 1); + hls_prediction_unit(s, x0 + cb_size / 2, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 3, idx - 1); break; } } @@ -1755,9 +2107,7 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) return ret; } else { if (!s->sh.disable_deblocking_filter_flag) - ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size, - lc->slice_or_tiles_up_boundary, - lc->slice_or_tiles_left_boundary); + ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size); } } } @@ -1788,16 +2138,15 @@ static int hls_coding_quadtree(HEVCContext *s, int x0, int y0, const int cb_size = 1 << log2_cb_size; int ret; int qp_block_mask = (1<<(s->sps->log2_ctb_size - s->pps->diff_cu_qp_delta_depth)) - 1; + int split_cu_flag; 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) { - SAMPLE(s->split_cu_flag, x0, y0) = - ff_hevc_split_coding_unit_flag_decode(s, cb_depth, x0, y0); + split_cu_flag = ff_hevc_split_coding_unit_flag_decode(s, cb_depth, x0, y0); } else { - SAMPLE(s->split_cu_flag, x0, y0) = - (log2_cb_size > s->sps->log2_min_cb_size); + split_cu_flag = (log2_cb_size > s->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) { @@ -1805,7 +2154,12 @@ static int hls_coding_quadtree(HEVCContext *s, int x0, int y0, lc->tu.cu_qp_delta = 0; } - if (SAMPLE(s->split_cu_flag, x0, y0)) { + if (s->sh.cu_chroma_qp_offset_enabled_flag && + log2_cb_size >= s->sps->log2_ctb_size - s->pps->diff_cu_chroma_qp_offset_depth) { + lc->tu.is_cu_chroma_qp_offset_coded = 0; + } + + if (split_cu_flag) { const int cb_size_split = cb_size >> 1; const int x1 = x0 + cb_size_split; const int y1 = y0 + cb_size_split; @@ -1965,7 +2319,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) if (x_ctb + ctb_size >= s->sps->width && y_ctb + ctb_size >= s->sps->height) - ff_hevc_hls_filter(s, x_ctb, y_ctb); + ff_hevc_hls_filter(s, x_ctb, y_ctb, ctb_size); return ctb_addr_ts; } @@ -2040,7 +2394,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int } if ((x_ctb+ctb_size) >= s->sps->width && (y_ctb+ctb_size) >= s->sps->height ) { - ff_hevc_hls_filter(s, x_ctb, y_ctb); + ff_hevc_hls_filter(s, x_ctb, y_ctb, ctb_size); ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP); return ctb_addr_ts; } @@ -2073,7 +2427,7 @@ static int hls_slice_data_wpp(HEVCContext *s, const uint8_t *nal, int length) for (i = 1; i < s->threads_number; i++) { s->sList[i] = av_malloc(sizeof(HEVCContext)); memcpy(s->sList[i], s, sizeof(HEVCContext)); - s->HEVClcList[i] = av_malloc(sizeof(HEVCLocalContext)); + s->HEVClcList[i] = av_mallocz(sizeof(HEVCLocalContext)); s->sList[i]->HEVClc = s->HEVClcList[i]; } } @@ -2159,33 +2513,6 @@ static int hls_nal_unit(HEVCContext *s) return nuh_layer_id == 0; } -static void restore_tqb_pixels(HEVCContext *s) -{ - int min_pu_size = 1 << s->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 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)]; - for (n = 0; n < (min_pu_size >> vshift); n++) { - memcpy(dst, src, len); - src += stride; - dst += stride; - } - } - } - } - } -} - static int set_side_data(HEVCContext *s) { AVFrame *out = s->ref->frame; @@ -2218,6 +2545,20 @@ static int set_side_data(HEVCContext *s) stereo->flags = AV_STEREO3D_FLAG_INVERT; } + if (s->sei_display_orientation_present && + (s->sei_anticlockwise_rotation || s->sei_hflip || s->sei_vflip)) { + double angle = s->sei_anticlockwise_rotation * 360 / (double) (1 << 16); + AVFrameSideData *rotation = av_frame_new_side_data(out, + AV_FRAME_DATA_DISPLAYMATRIX, + sizeof(int32_t) * 9); + if (!rotation) + return AVERROR(ENOMEM); + + av_display_rotation_set((int32_t *)rotation->data, angle); + av_display_matrix_flip((int32_t *)rotation->data, + s->sei_vflip, s->sei_hflip); + } + return 0; } @@ -2227,6 +2568,7 @@ static int hevc_frame_start(HEVCContext *s) int pic_size_in_ctb = ((s->sps->width >> s->sps->log2_min_cb_size) + 1) * ((s->sps->height >> s->sps->log2_min_cb_size) + 1); int ret; + AVFrame *cur_frame; 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)); @@ -2251,10 +2593,15 @@ static int hevc_frame_start(HEVCContext *s) goto fail; } + s->ref->frame->key_frame = IS_IRAP(s); + ret = set_side_data(s); if (ret < 0) goto fail; + cur_frame = s->sps->sao_enabled ? s->sao_frame : s->frame; + cur_frame->pict_type = 3 - s->sh.slice_type; + av_frame_unref(s->output_frame); ret = ff_hevc_output_frame(s, s->output_frame, 0); if (ret < 0) @@ -2381,10 +2728,6 @@ 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 (ctb_addr_ts < 0) { @@ -2526,6 +2869,7 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) int i, consumed, ret = 0; s->ref = NULL; + s->last_eos = s->eos; s->eos = 0; /* split the input packet into NAL units, so we know the upper bound on the @@ -2678,8 +3022,8 @@ static int verify_md5(HEVCContext *s, AVFrame *frame) const uint8_t *src = frame->data[i] + j * frame->linesize[i]; #if HAVE_BIGENDIAN if (pixel_shift) { - s->dsp.bswap16_buf((uint16_t*)s->checksum_buf, - (const uint16_t*)src, w); + s->bdsp.bswap16_buf((uint16_t *) s->checksum_buf, + (const uint16_t *) src, w); src = s->checksum_buf; } #endif @@ -2817,6 +3161,11 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) 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]); + s->sps = NULL; + s->pps = NULL; + s->vps = NULL; + + av_buffer_unref(&s->current_sps); av_freep(&s->sh.entry_point_offset); av_freep(&s->sh.offset); @@ -2879,9 +3228,10 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) if (!s->md5_ctx) goto fail; - ff_dsputil_init(&s->dsp, avctx); + ff_bswapdsp_init(&s->bdsp); s->context_initialized = 1; + s->eos = 0; return 0; @@ -2912,6 +3262,8 @@ static int hevc_update_thread_context(AVCodecContext *dst, } } + if (s->sps != s0->sps) + s->sps = NULL; for (i = 0; i < FF_ARRAY_ELEMS(s->vps_list); i++) { av_buffer_unref(&s->vps_list[i]); if (s0->vps_list[i]) { @@ -2939,6 +3291,13 @@ static int hevc_update_thread_context(AVCodecContext *dst, } } + av_buffer_unref(&s->current_sps); + if (s0->current_sps) { + s->current_sps = av_buffer_ref(s0->current_sps); + if (!s->current_sps) + return AVERROR(ENOMEM); + } + if (s->sps != s0->sps) ret = set_sps(s, s0->sps); @@ -2946,6 +3305,7 @@ static int hevc_update_thread_context(AVCodecContext *dst, s->seq_output = s0->seq_output; s->pocTid0 = s0->pocTid0; s->max_ra = s0->max_ra; + s->eos = s0->eos; s->is_nalff = s0->is_nalff; s->nal_length_size = s0->nal_length_size; @@ -3090,6 +3450,7 @@ 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_HEVC_REXT, "Rext" }, { FF_PROFILE_UNKNOWN }, }; diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index a1c76fe49..2a5ce2523 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -27,8 +27,8 @@ #include "libavutil/md5.h" #include "avcodec.h" +#include "bswapdsp.h" #include "cabac.h" -#include "dsputil.h" #include "get_bits.h" #include "hevcpred.h" #include "hevcdsp.h" @@ -61,7 +61,7 @@ #define MAX_QP 51 #define DEFAULT_INTRA_TC_OFFSET 2 -#define HEVC_CONTEXTS 183 +#define HEVC_CONTEXTS 199 #define MRG_MAX_NUM_CANDS 5 @@ -71,6 +71,9 @@ #define EPEL_EXTRA_BEFORE 1 #define EPEL_EXTRA_AFTER 2 #define EPEL_EXTRA 3 +#define QPEL_EXTRA_BEFORE 3 +#define QPEL_EXTRA_AFTER 4 +#define QPEL_EXTRA 7 #define EDGE_EMU_BUFFER_STRIDE 80 @@ -80,6 +83,7 @@ #define SAMPLE(tab, x, y) ((tab)[(y) * s->sps->width + (x)]) #define SAMPLE_CTB(tab, x, y) ((tab)[(y) * min_cb_width + (x)]) #define SAMPLE_CBF(tab, x, y) ((tab)[((y) & ((1<nal_unit_type == NAL_IDR_W_RADL || (s)->nal_unit_type == NAL_IDR_N_LP) #define IS_BLA(s) ((s)->nal_unit_type == NAL_BLA_W_RADL || (s)->nal_unit_type == NAL_BLA_W_LP || \ @@ -166,6 +170,8 @@ enum SyntaxElement { CBF_LUMA, CBF_CB_CR, TRANSFORM_SKIP_FLAG, + EXPLICIT_RDPCM_FLAG, + EXPLICIT_RDPCM_DIR_FLAG, LAST_SIGNIFICANT_COEFF_X_PREFIX, LAST_SIGNIFICANT_COEFF_Y_PREFIX, LAST_SIGNIFICANT_COEFF_X_SUFFIX, @@ -176,6 +182,10 @@ enum SyntaxElement { COEFF_ABS_LEVEL_GREATER2_FLAG, COEFF_ABS_LEVEL_REMAINING, COEFF_SIGN_FLAG, + LOG2_RES_SCALE_ABS, + RES_SCALE_SIGN_FLAG, + CU_CHROMA_QP_OFFSET_FLAG, + CU_CHROMA_QP_OFFSET_IDX, }; enum PartMode { @@ -201,6 +211,13 @@ enum InterPredIdc { PRED_BI, }; +enum PredFlag { + PF_INTRA = 0, + PF_L0, + PF_L1, + PF_BI, +}; + enum IntraPredMode { INTRA_PLANAR = 0, INTRA_DC, @@ -441,6 +458,13 @@ typedef struct HEVCSPS { int max_transform_hierarchy_depth_inter; int max_transform_hierarchy_depth_intra; + int transform_skip_rotation_enabled_flag; + int transform_skip_context_enabled_flag; + int implicit_rdpcm_enabled_flag; + int explicit_rdpcm_enabled_flag; + int intra_smoothing_disabled_flag; + int persistent_rice_adaptation_enabled_flag; + ///< coded frame dimension in various units int width; int height; @@ -453,6 +477,7 @@ typedef struct HEVCSPS { int min_tb_height; int min_pu_width; int min_pu_height; + int tb_mask; int hshift[3]; int vshift[3]; @@ -509,6 +534,15 @@ typedef struct HEVCPPS { int log2_parallel_merge_level; ///< log2_parallel_merge_level_minus2 + 2 int num_extra_slice_header_bits; uint8_t slice_header_extension_present_flag; + uint8_t log2_max_transform_skip_block_size; + uint8_t cross_component_prediction_enabled_flag; + uint8_t chroma_qp_offset_list_enabled_flag; + uint8_t diff_cu_chroma_qp_offset_depth; + uint8_t chroma_qp_offset_list_len_minus1; + int8_t cb_qp_offset_list[5]; + int8_t cr_qp_offset_list[5]; + uint8_t log2_sao_offset_scale_luma; + uint8_t log2_sao_offset_scale_chroma; // Inferred parameters unsigned int *column_width; ///< ColumnWidth @@ -521,8 +555,8 @@ typedef struct HEVCPPS { int *ctb_addr_ts_to_rs; ///< CtbAddrTSToRS int *tile_id; ///< TileId int *tile_pos_rs; ///< TilePosRS - int *min_cb_addr_zs; ///< MinCbAddrZS int *min_tb_addr_zs; ///< MinTbAddrZS + int *min_tb_addr_zs_tab;///< MinTbAddrZS } HEVCPPS; typedef struct SliceHeader { @@ -568,6 +602,8 @@ typedef struct SliceHeader { int slice_cb_qp_offset; int slice_cr_qp_offset; + uint8_t cu_chroma_qp_offset_enabled_flag; + int beta_offset; ///< beta_offset_div2 * 2 int tc_offset; ///< tc_offset_div2 * 2 @@ -626,8 +662,7 @@ typedef struct Mv { typedef struct MvField { Mv mv[2]; int8_t ref_idx[2]; - int8_t pred_flag[2]; - uint8_t is_intra; + int8_t pred_flag; } MvField; typedef struct NeighbourAvailable { @@ -645,7 +680,8 @@ typedef struct PredictionUnit { uint8_t intra_pred_mode[4]; Mv mvd; uint8_t merge_flag; - uint8_t intra_pred_mode_c; + uint8_t intra_pred_mode_c[4]; + uint8_t chroma_mode_c[4]; } PredictionUnit; typedef struct TransformTree { @@ -658,11 +694,20 @@ typedef struct TransformTree { } TransformTree; typedef struct TransformUnit { + DECLARE_ALIGNED(32, int16_t, coeffs[2][MAX_TB_SIZE * MAX_TB_SIZE]); int cu_qp_delta; + int res_scale_val; + // Inferred parameters; - int cur_intra_pred_mode; + int intra_pred_mode; + int intra_pred_mode_c; + int chroma_mode_c; uint8_t is_cu_qp_delta_coded; + uint8_t is_cu_chroma_qp_offset_coded; + int8_t cu_qp_offset_cb; + int8_t cu_qp_offset_cr; + uint8_t cross_pf; } TransformUnit; typedef struct DBParams { @@ -714,6 +759,8 @@ typedef struct HEVCLocalContext { DECLARE_ALIGNED(16, int16_t, mc_buffer[(MAX_PB_SIZE + 7) * MAX_PB_SIZE]); uint8_t cabac_state[HEVC_CONTEXTS]; + uint8_t stat_coeff[4]; + uint8_t first_qp_group; GetBitContext gb; @@ -735,6 +782,8 @@ typedef struct HEVCLocalContext { int end_of_tiles_y; /* +7 is for subpixel interpolation, *2 for high bit depths */ DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[(MAX_PB_SIZE + 7) * EDGE_EMU_BUFFER_STRIDE * 2]; + DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer2)[(MAX_PB_SIZE + 7) * EDGE_EMU_BUFFER_STRIDE * 2]; + CodingTree ct; CodingUnit cu; PredictionUnit pu; @@ -776,6 +825,8 @@ typedef struct HEVCContext { AVBufferRef *sps_list[MAX_SPS_COUNT]; AVBufferRef *pps_list[MAX_PPS_COUNT]; + AVBufferRef *current_sps; + AVBufferPool *tab_mvf_pool; AVBufferPool *rpl_tab_pool; @@ -793,6 +844,7 @@ typedef struct HEVCContext { int pocTid0; int slice_idx; ///< number of the slice being currently decoded int eos; ///< current packet contains an EOS/EOB NAL + int last_eos; ///< last packet contains an EOS/EOB NAL int max_ra; int bs_width; int bs_height; @@ -802,9 +854,8 @@ typedef struct HEVCContext { HEVCPredContext hpc; HEVCDSPContext hevcdsp; VideoDSPContext vdsp; - DSPContext dsp; + BswapDSPContext bdsp; int8_t *qp_y_tab; - uint8_t *split_cu_flag; uint8_t *horizontal_bs; uint8_t *vertical_bs; @@ -843,7 +894,7 @@ typedef struct HEVCContext { int **skipped_bytes_pos_nal; int *skipped_bytes_pos_size_nal; - uint8_t *data; + const uint8_t *data; HEVCNAL *nals; int nb_nals; @@ -872,6 +923,11 @@ typedef struct HEVCContext { int content_interpretation_type; int quincunx_subsampling; + /** display orientation */ + int sei_display_orientation_present; + int sei_anticlockwise_rotation; + int sei_hflip, sei_vflip; + int picture_struct; } HEVCContext; @@ -943,7 +999,8 @@ int ff_hevc_no_residual_syntax_flag_decode(HEVCContext *s); int ff_hevc_split_transform_flag_decode(HEVCContext *s, int log2_trafo_size); int ff_hevc_cbf_cb_cr_decode(HEVCContext *s, int trafo_depth); int ff_hevc_cbf_luma_decode(HEVCContext *s, int trafo_depth); -int ff_hevc_transform_skip_flag_decode(HEVCContext *s, int c_idx); +int ff_hevc_log2_res_scale_abs(HEVCContext *s, int idx); +int ff_hevc_res_scale_sign_flag(HEVCContext *s, int idx); /** * Get the number of candidate references for the current frame. @@ -972,12 +1029,12 @@ void ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, void ff_hevc_set_qPy(HEVCContext *s, int xC, int yC, int xBase, int yBase, int log2_cb_size); void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, - int log2_trafo_size, - int slice_or_tiles_up_boundary, - int slice_or_tiles_left_boundary); + int log2_trafo_size); int ff_hevc_cu_qp_delta_sign_flag(HEVCContext *s); int ff_hevc_cu_qp_delta_abs(HEVCContext *s); -void ff_hevc_hls_filter(HEVCContext *s, int x, int y); +int ff_hevc_cu_chroma_qp_offset_flag(HEVCContext *s); +int ff_hevc_cu_chroma_qp_offset_idx(HEVCContext *s); +void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size); void ff_hevc_hls_filters(HEVCContext *s, int x_ctb, int y_ctb, int ctb_size); void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, int log2_trafo_size, enum ScanType scan_idx, diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c index da7a21373..92b2d7af8 100644 --- a/libavcodec/hevc_cabac.c +++ b/libavcodec/hevc_cabac.c @@ -27,12 +27,12 @@ #include "cabac_functions.h" #include "hevc.h" -#define CABAC_MAX_BIN 100 +#define CABAC_MAX_BIN 31 /** * number of bin by SyntaxElement. */ -static const int8_t num_bins_in_se[] = { +av_unused static const int8_t num_bins_in_se[] = { 1, // sao_merge_flag 1, // sao_type_idx 0, // sao_eo_class @@ -66,65 +66,77 @@ static const int8_t num_bins_in_se[] = { 2, // cbf_luma 4, // cbf_cb, cbf_cr 2, // transform_skip_flag[][] + 2, // explicit_rdpcm_flag[][] + 2, // explicit_rdpcm_dir_flag[][] 18, // last_significant_coeff_x_prefix 18, // last_significant_coeff_y_prefix 0, // last_significant_coeff_x_suffix 0, // last_significant_coeff_y_suffix 4, // significant_coeff_group_flag - 42, // significant_coeff_flag + 44, // significant_coeff_flag 24, // coeff_abs_level_greater1_flag 6, // coeff_abs_level_greater2_flag 0, // coeff_abs_level_remaining 0, // coeff_sign_flag + 8, // log2_res_scale_abs + 2, // res_scale_sign_flag + 1, // cu_chroma_qp_offset_flag + 1, // cu_chroma_qp_offset_idx }; /** * Offset to ctxIdx 0 in init_values and states, indexed by SyntaxElement. */ static const int elem_offset[sizeof(num_bins_in_se)] = { - 0, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 5, - 6, - 9, - 12, - 13, - 17, - 17, - 18, - 18, - 18, - 20, - 21, - 22, - 27, - 29, - 31, - 33, - 35, - 35, - 35, - 36, - 37, - 40, - 42, - 46, - 48, - 66, - 84, - 84, - 84, - 88, - 130, - 154, - 160, - 160, + 0, // sao_merge_flag + 1, // sao_type_idx + 2, // sao_eo_class + 2, // sao_band_position + 2, // sao_offset_abs + 2, // sao_offset_sign + 2, // end_of_slice_flag + 2, // split_coding_unit_flag + 5, // cu_transquant_bypass_flag + 6, // skip_flag + 9, // cu_qp_delta + 12, // pred_mode + 13, // part_mode + 17, // pcm_flag + 17, // prev_intra_luma_pred_mode + 18, // mpm_idx + 18, // rem_intra_luma_pred_mode + 18, // intra_chroma_pred_mode + 20, // merge_flag + 21, // merge_idx + 22, // inter_pred_idc + 27, // ref_idx_l0 + 29, // ref_idx_l1 + 31, // abs_mvd_greater0_flag + 33, // abs_mvd_greater1_flag + 35, // abs_mvd_minus2 + 35, // mvd_sign_flag + 35, // mvp_lx_flag + 36, // no_residual_data_flag + 37, // split_transform_flag + 40, // cbf_luma + 42, // cbf_cb, cbf_cr + 46, // transform_skip_flag[][] + 48, // explicit_rdpcm_flag[][] + 50, // explicit_rdpcm_dir_flag[][] + 52, // last_significant_coeff_x_prefix + 70, // last_significant_coeff_y_prefix + 88, // last_significant_coeff_x_suffix + 88, // last_significant_coeff_y_suffix + 88, // significant_coeff_group_flag + 92, // significant_coeff_flag + 136, // coeff_abs_level_greater1_flag + 160, // coeff_abs_level_greater2_flag + 166, // coeff_abs_level_remaining + 166, // coeff_sign_flag + 166, // log2_res_scale_abs + 174, // res_scale_sign_flag + 176, // cu_chroma_qp_offset_flag + 177, // cu_chroma_qp_offset_idx }; #define CNU 154 @@ -178,6 +190,10 @@ static const uint8_t init_values[3][HEVC_CONTEXTS] = { 94, 138, 182, 154, // transform_skip_flag 139, 139, + // explicit_rdpcm_flag + 139, 139, + // explicit_rdpcm_dir_flag + 139, 139, // last_significant_coeff_x_prefix 110, 110, 124, 125, 140, 153, 125, 127, 140, 109, 111, 143, 127, 111, 79, 108, 123, 63, @@ -190,11 +206,21 @@ static const uint8_t init_values[3][HEVC_CONTEXTS] = { 111, 111, 125, 110, 110, 94, 124, 108, 124, 107, 125, 141, 179, 153, 125, 107, 125, 141, 179, 153, 125, 107, 125, 141, 179, 153, 125, 140, 139, 182, 182, 152, 136, 152, 136, 153, 136, 139, 111, 136, 139, 111, + 141, 111, // coeff_abs_level_greater1_flag 140, 92, 137, 138, 140, 152, 138, 139, 153, 74, 149, 92, 139, 107, 122, 152, 140, 179, 166, 182, 140, 227, 122, 197, // coeff_abs_level_greater2_flag - 138, 153, 136, 167, 152, 152, }, + 138, 153, 136, 167, 152, 152, + // log2_res_scale_abs + 154, 154, 154, 154, 154, 154, 154, 154, + // res_scale_sign_flag + 154, 154, + // cu_chroma_qp_offset_flag + 154, + // cu_chroma_qp_offset_idx + 154, + }, { // sao_merge_flag 153, // sao_type_idx @@ -241,6 +267,10 @@ static const uint8_t init_values[3][HEVC_CONTEXTS] = { 149, 107, 167, 154, // transform_skip_flag 139, 139, + // explicit_rdpcm_flag + 139, 139, + // explicit_rdpcm_dir_flag + 139, 139, // last_significant_coeff_x_prefix 125, 110, 94, 110, 95, 79, 125, 111, 110, 78, 110, 111, 111, 95, 94, 108, 123, 108, @@ -253,11 +283,21 @@ static const uint8_t init_values[3][HEVC_CONTEXTS] = { 155, 154, 139, 153, 139, 123, 123, 63, 153, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 170, 153, 123, 123, 107, 121, 107, 121, 167, 151, 183, 140, 151, 183, 140, + 140, 140, // coeff_abs_level_greater1_flag 154, 196, 196, 167, 154, 152, 167, 182, 182, 134, 149, 136, 153, 121, 136, 137, 169, 194, 166, 167, 154, 167, 137, 182, // coeff_abs_level_greater2_flag - 107, 167, 91, 122, 107, 167, }, + 107, 167, 91, 122, 107, 167, + // log2_res_scale_abs + 154, 154, 154, 154, 154, 154, 154, 154, + // res_scale_sign_flag + 154, 154, + // cu_chroma_qp_offset_flag + 154, + // cu_chroma_qp_offset_idx + 154, + }, { // sao_merge_flag 153, // sao_type_idx @@ -304,6 +344,10 @@ static const uint8_t init_values[3][HEVC_CONTEXTS] = { 149, 92, 167, 154, // transform_skip_flag 139, 139, + // explicit_rdpcm_flag + 139, 139, + // explicit_rdpcm_dir_flag + 139, 139, // last_significant_coeff_x_prefix 125, 110, 124, 110, 95, 94, 125, 111, 111, 79, 125, 126, 111, 111, 79, 108, 123, 93, @@ -316,11 +360,21 @@ static const uint8_t init_values[3][HEVC_CONTEXTS] = { 170, 154, 139, 153, 139, 123, 123, 63, 124, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 170, 153, 138, 138, 122, 121, 122, 121, 167, 151, 183, 140, 151, 183, 140, + 140, 140, // coeff_abs_level_greater1_flag 154, 196, 167, 167, 154, 152, 167, 182, 182, 134, 149, 136, 153, 121, 136, 122, 169, 208, 166, 167, 154, 152, 167, 182, // coeff_abs_level_greater2_flag - 107, 167, 91, 107, 107, 167, }, + 107, 167, 91, 107, 107, 167, + // log2_res_scale_abs + 154, 154, 154, 154, 154, 154, 154, 154, + // res_scale_sign_flag + 154, 154, + // cu_chroma_qp_offset_flag + 154, + // cu_chroma_qp_offset_idx + 154, + }, }; static const uint8_t scan_1x1[1] = { @@ -360,14 +414,6 @@ static const uint8_t horiz_scan8x8_inv[8][8] = { { 44, 45, 46, 47, 60, 61, 62, 63, }, }; -static const uint8_t diag_scan4x1_x[4] = { - 0, 1, 2, 3, -}; - -static const uint8_t diag_scan1x4_y[4] = { - 0, 1, 2, 3, -}; - static const uint8_t diag_scan2x2_x[4] = { 0, 0, 1, 1, }; @@ -381,50 +427,6 @@ static const uint8_t diag_scan2x2_inv[2][2] = { { 1, 3, }, }; -static const uint8_t diag_scan8x2_x[16] = { - 0, 0, 1, 1, - 2, 2, 3, 3, - 4, 4, 5, 5, - 6, 6, 7, 7, -}; - -static const uint8_t diag_scan8x2_y[16] = { - 0, 1, 0, 1, - 0, 1, 0, 1, - 0, 1, 0, 1, - 0, 1, 0, 1, -}; - -static const uint8_t diag_scan8x2_inv[2][8] = { - { 0, 2, 4, 6, 8, 10, 12, 14, }, - { 1, 3, 5, 7, 9, 11, 13, 15, }, -}; - -static const uint8_t diag_scan2x8_x[16] = { - 0, 0, 1, 0, - 1, 0, 1, 0, - 1, 0, 1, 0, - 1, 0, 1, 1, -}; - -static const uint8_t diag_scan2x8_y[16] = { - 0, 1, 0, 2, - 1, 3, 2, 4, - 3, 5, 4, 6, - 5, 7, 6, 7, -}; - -static const uint8_t diag_scan2x8_inv[8][2] = { - { 0, 2, }, - { 1, 4, }, - { 3, 6, }, - { 5, 8, }, - { 7, 10, }, - { 9, 12, }, - { 11, 14, }, - { 13, 15, }, -}; - const uint8_t ff_hevc_diag_scan4x4_x[16] = { 0, 0, 1, 0, 1, 2, 0, 1, @@ -537,13 +539,16 @@ 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) pre = 124 + (pre & 1); s->HEVClc->cabac_state[i] = pre; } + + for (i = 0; i < 4; i++) + s->HEVClc->stat_coeff[i] = 0; } void ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts) @@ -694,6 +699,22 @@ int ff_hevc_cu_qp_delta_sign_flag(HEVCContext *s) return get_cabac_bypass(&s->HEVClc->cc); } +int ff_hevc_cu_chroma_qp_offset_flag(HEVCContext *s) +{ + return GET_CABAC(elem_offset[CU_CHROMA_QP_OFFSET_FLAG]); +} + +int ff_hevc_cu_chroma_qp_offset_idx(HEVCContext *s) +{ + int c_max= FFMAX(5, s->pps->chroma_qp_offset_list_len_minus1); + int i = 0; + + while (i < c_max && GET_CABAC(elem_offset[CU_CHROMA_QP_OFFSET_IDX])) + i++; + + return i; +} + int ff_hevc_pred_mode_decode(HEVCContext *s) { return GET_CABAC(elem_offset[PRED_MODE_FLAG]); @@ -892,38 +913,58 @@ int ff_hevc_cbf_luma_decode(HEVCContext *s, int trafo_depth) return GET_CABAC(elem_offset[CBF_LUMA] + !trafo_depth); } -int ff_hevc_transform_skip_flag_decode(HEVCContext *s, int c_idx) +static int ff_hevc_transform_skip_flag_decode(HEVCContext *s, int c_idx) { return GET_CABAC(elem_offset[TRANSFORM_SKIP_FLAG] + !!c_idx); } -#define LAST_SIG_COEFF(elem) \ - int i = 0; \ - int max = (log2_size << 1) - 1; \ - int ctx_offset, ctx_shift; \ - \ - if (c_idx == 0) { \ - ctx_offset = 3 * (log2_size - 2) + ((log2_size - 1) >> 2); \ - ctx_shift = (log2_size + 1) >> 2; \ - } else { \ - ctx_offset = 15; \ - ctx_shift = log2_size - 2; \ - } \ - while (i < max && \ - GET_CABAC(elem_offset[elem] + (i >> ctx_shift) + ctx_offset)) \ - i++; \ - return i; - -static av_always_inline int last_significant_coeff_x_prefix_decode(HEVCContext *s, int c_idx, - int log2_size) +static int explicit_rdpcm_flag_decode(HEVCContext *s, int c_idx) { - LAST_SIG_COEFF(LAST_SIGNIFICANT_COEFF_X_PREFIX) + return GET_CABAC(elem_offset[EXPLICIT_RDPCM_FLAG] + !!c_idx); } -static av_always_inline int last_significant_coeff_y_prefix_decode(HEVCContext *s, int c_idx, - int log2_size) +static int explicit_rdpcm_dir_flag_decode(HEVCContext *s, int c_idx) { - LAST_SIG_COEFF(LAST_SIGNIFICANT_COEFF_Y_PREFIX) + return GET_CABAC(elem_offset[EXPLICIT_RDPCM_DIR_FLAG] + !!c_idx); +} + +int ff_hevc_log2_res_scale_abs(HEVCContext *s, int idx) { + int i =0; + + while (i < 4 && GET_CABAC(elem_offset[LOG2_RES_SCALE_ABS] + 4 * idx + i)) + i++; + + return i; +} + +int ff_hevc_res_scale_sign_flag(HEVCContext *s, int idx) { + return GET_CABAC(elem_offset[RES_SCALE_SIGN_FLAG] + idx); +} + +static av_always_inline void last_significant_coeff_xy_prefix_decode(HEVCContext *s, int c_idx, + int log2_size, int *last_scx_prefix, int *last_scy_prefix) +{ + int i = 0; + int max = (log2_size << 1) - 1; + int ctx_offset, ctx_shift; + + if (!c_idx) { + ctx_offset = 3 * (log2_size - 2) + ((log2_size - 1) >> 2); + ctx_shift = (log2_size + 1) >> 2; + } else { + ctx_offset = 15; + ctx_shift = log2_size - 2; + } + while (i < max && + GET_CABAC(elem_offset[LAST_SIGNIFICANT_COEFF_X_PREFIX] + (i >> ctx_shift) + ctx_offset)) + i++; + *last_scx_prefix = i; + + i = 0; + while (i < max && + GET_CABAC(elem_offset[LAST_SIGNIFICANT_COEFF_Y_PREFIX] + (i >> ctx_shift) + ctx_offset)) + i++; + *last_scy_prefix = i; } static av_always_inline int last_significant_coeff_suffix_decode(HEVCContext *s, @@ -946,58 +987,18 @@ static av_always_inline int significant_coeff_group_flag_decode(HEVCContext *s, return GET_CABAC(elem_offset[SIGNIFICANT_COEFF_GROUP_FLAG] + inc); } - -static av_always_inline int significant_coeff_flag_decode(HEVCContext *s, int c_idx, int x_c, int y_c, - int log2_trafo_size, int scan_idx, int prev_sig) +static av_always_inline int significant_coeff_flag_decode(HEVCContext *s, int x_c, int y_c, + int offset, const uint8_t *ctx_idx_map) { - static const uint8_t ctx_idx_map[] = { - 0, 1, 4, 5, 2, 3, 4, 5, 6, 6, 8, 8, 7, 7, 8, 8 - }; - int x_cg = x_c >> 2; - int y_cg = y_c >> 2; - int sig_ctx; - int inc; - - if (x_c + y_c == 0) { - sig_ctx = 0; - } else if (log2_trafo_size == 2) { - sig_ctx = ctx_idx_map[(y_c << 2) + x_c]; - } else { - switch (prev_sig) { - case 0: { - int x_off = x_c & 3; - int y_off = y_c & 3; - sig_ctx = ((x_off + y_off) == 0) ? 2 : ((x_off + y_off) <= 2) ? 1 : 0; - } - break; - case 1: - sig_ctx = 2 - FFMIN(y_c & 3, 2); - break; - case 2: - sig_ctx = 2 - FFMIN(x_c & 3, 2); - break; - default: - sig_ctx = 2; - } - - if (c_idx == 0 && (x_cg > 0 || y_cg > 0)) - sig_ctx += 3; - - if (log2_trafo_size == 3) { - sig_ctx += (scan_idx == SCAN_DIAG) ? 9 : 15; - } else { - sig_ctx += c_idx ? 12 : 21; - } - } - - if (c_idx == 0) - inc = sig_ctx; - else - inc = sig_ctx + 27; - + int inc = ctx_idx_map[(y_c << 2) + x_c] + offset; return GET_CABAC(elem_offset[SIGNIFICANT_COEFF_FLAG] + inc); } +static av_always_inline int significant_coeff_flag_decode_0(HEVCContext *s, int c_idx, int offset) +{ + return GET_CABAC(elem_offset[SIGNIFICANT_COEFF_FLAG] + offset); +} + static av_always_inline int coeff_abs_level_greater1_flag_decode(HEVCContext *s, int c_idx, int inc) { @@ -1015,7 +1016,7 @@ static av_always_inline int coeff_abs_level_greater2_flag_decode(HEVCContext *s, return GET_CABAC(elem_offset[COEFF_ABS_LEVEL_GREATER2_FLAG] + inc); } -static av_always_inline int coeff_abs_level_remaining_decode(HEVCContext *s, int base_level, int rc_rice_param) +static av_always_inline int coeff_abs_level_remaining_decode(HEVCContext *s, int rc_rice_param) { int prefix = 0; int suffix = 0; @@ -1056,8 +1057,8 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, { #define GET_COORD(offset, n) \ do { \ - x_c = (scan_x_cg[offset >> 4] << 2) + scan_x_off[n]; \ - y_c = (scan_y_cg[offset >> 4] << 2) + scan_y_off[n]; \ + x_c = (x_cg << 2) + scan_x_off[n]; \ + y_c = (y_cg << 2) + scan_y_off[n]; \ } while (0) HEVCLocalContext *lc = s->HEVClc; int transform_skip_flag = 0; @@ -1078,29 +1079,37 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, int vshift = s->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}; - DECLARE_ALIGNED(8, uint8_t, significant_coeff_group_flag[8][8]) = {{0}}; + int16_t *coeffs = lc->tu.coeffs[c_idx > 0]; + uint8_t significant_coeff_group_flag[8][8] = {{0}}; + int explicit_rdpcm_flag = 0; + int explicit_rdpcm_dir_flag; int trafo_size = 1 << log2_trafo_size; int i; int qp,shift,add,scale,scale_m; const uint8_t level_scale[] = { 40, 45, 51, 57, 64, 72 }; - const uint8_t *scale_matrix; + const uint8_t *scale_matrix = NULL; uint8_t dc_scale; + int pred_mode_intra = (c_idx == 0) ? lc->tu.intra_pred_mode : + lc->tu.intra_pred_mode_c; + + memset(coeffs, 0, trafo_size * trafo_size * sizeof(int16_t)); // Derive QP for dequant if (!lc->cu.cu_transquant_bypass_flag) { static const int qp_c[] = { 29, 30, 31, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37 }; - static const uint8_t rem6[51 + 2 * 6 + 1] = { + static const uint8_t rem6[51 + 4 * 6 + 1] = { 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + 4, 5, 0, 1, 2, 3, 4, 5, 0, 1 }; - static const uint8_t div6[51 + 2 * 6 + 1] = { + static const uint8_t div6[51 + 4 * 6 + 1] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 11, 12, 12 }; int qp_y = lc->qp_y; @@ -1110,17 +1119,26 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, int qp_i, offset; if (c_idx == 1) - offset = s->pps->cb_qp_offset + s->sh.slice_cb_qp_offset; + offset = s->pps->cb_qp_offset + s->sh.slice_cb_qp_offset + + lc->tu.cu_qp_offset_cb; else - offset = s->pps->cr_qp_offset + s->sh.slice_cr_qp_offset; + offset = s->pps->cr_qp_offset + s->sh.slice_cr_qp_offset + + lc->tu.cu_qp_offset_cr; - qp_i = av_clip_c(qp_y + offset, - s->sps->qp_bd_offset, 57); - if (qp_i < 30) - qp = qp_i; - else if (qp_i > 43) - qp = qp_i - 6; - else - qp = qp_c[qp_i - 30]; + qp_i = av_clip(qp_y + offset, - s->sps->qp_bd_offset, 57); + if (s->sps->chroma_format_idc == 1) { + if (qp_i < 30) + qp = qp_i; + else if (qp_i > 43) + qp = qp_i - 6; + else + qp = qp_c[qp_i - 30]; + } else { + if (qp_i > 51) + qp = 51; + else + qp = qp_i; + } qp += s->sps->qp_bd_offset; } @@ -1143,17 +1161,28 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, if (log2_trafo_size >= 4) dc_scale = sl->sl_dc[log2_trafo_size - 4][matrix_id]; } + } else { + shift = 0; + add = 0; + scale = 0; + dc_scale = 0; } if (s->pps->transform_skip_enabled_flag && !lc->cu.cu_transquant_bypass_flag && - log2_trafo_size == 2) { + log2_trafo_size <= s->pps->log2_max_transform_skip_block_size) { transform_skip_flag = ff_hevc_transform_skip_flag_decode(s, c_idx); } - last_significant_coeff_x = - last_significant_coeff_x_prefix_decode(s, c_idx, log2_trafo_size); - last_significant_coeff_y = - last_significant_coeff_y_prefix_decode(s, c_idx, log2_trafo_size); + if (lc->cu.pred_mode == MODE_INTER && s->sps->explicit_rdpcm_enabled_flag && + (transform_skip_flag || lc->cu.cu_transquant_bypass_flag)) { + explicit_rdpcm_flag = explicit_rdpcm_flag_decode(s, c_idx); + if (explicit_rdpcm_flag) { + explicit_rdpcm_dir_flag = explicit_rdpcm_dir_flag_decode(s, c_idx); + } + } + + last_significant_coeff_xy_prefix_decode(s, c_idx, log2_trafo_size, + &last_significant_coeff_x, &last_significant_coeff_y); if (last_significant_coeff_x > 3) { int suffix = last_significant_coeff_suffix_decode(s, last_significant_coeff_x); @@ -1226,6 +1255,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, int64_t trans_coeff_level; int prev_sig = 0; int offset = i << 4; + int rice_init = 0; uint8_t significant_coeff_flag_idx[16]; uint8_t nb_significant_coeff_flag = 0; @@ -1260,26 +1290,85 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, } if (x_cg < ((1 << log2_trafo_size) - 1) >> 2) - prev_sig = significant_coeff_group_flag[x_cg + 1][y_cg]; + prev_sig = !!significant_coeff_group_flag[x_cg + 1][y_cg]; if (y_cg < ((1 << log2_trafo_size) - 1) >> 2) - prev_sig += (significant_coeff_group_flag[x_cg][y_cg + 1] << 1); + prev_sig += (!!significant_coeff_group_flag[x_cg][y_cg + 1] << 1); - for (n = n_end; n >= 0; n--) { - GET_COORD(offset, n); - - if (significant_coeff_group_flag[x_cg][y_cg] && - (n > 0 || implicit_non_zero_coeff == 0)) { - if (significant_coeff_flag_decode(s, c_idx, x_c, y_c, log2_trafo_size, scan_idx, prev_sig) == 1) { + if (significant_coeff_group_flag[x_cg][y_cg] && n_end >= 0) { + static const uint8_t ctx_idx_map[] = { + 0, 1, 4, 5, 2, 3, 4, 5, 6, 6, 8, 8, 7, 7, 8, 8, // log2_trafo_size == 2 + 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // prev_sig == 0 + 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, // prev_sig == 1 + 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, // prev_sig == 2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // default + }; + const uint8_t *ctx_idx_map_p; + int scf_offset = 0; + if (s->sps->transform_skip_context_enabled_flag && + (transform_skip_flag || lc->cu.cu_transquant_bypass_flag)) { + ctx_idx_map_p = (uint8_t*) &ctx_idx_map[4 * 16]; + if (c_idx == 0) { + scf_offset = 40; + } else { + scf_offset = 14 + 27; + } + } else { + if (c_idx != 0) + scf_offset = 27; + if (log2_trafo_size == 2) { + ctx_idx_map_p = (uint8_t*) &ctx_idx_map[0]; + } else { + ctx_idx_map_p = (uint8_t*) &ctx_idx_map[(prev_sig + 1) << 4]; + if (c_idx == 0) { + if ((x_cg > 0 || y_cg > 0)) + scf_offset += 3; + if (log2_trafo_size == 3) { + scf_offset += (scan_idx == SCAN_DIAG) ? 9 : 15; + } else { + scf_offset += 21; + } + } else { + if (log2_trafo_size == 3) + scf_offset += 9; + else + scf_offset += 12; + } + } + } + for (n = n_end; n > 0; n--) { + x_c = scan_x_off[n]; + y_c = scan_y_off[n]; + if (significant_coeff_flag_decode(s, x_c, y_c, scf_offset, ctx_idx_map_p)) { significant_coeff_flag_idx[nb_significant_coeff_flag] = n; nb_significant_coeff_flag++; implicit_non_zero_coeff = 0; } - } else { - int last_cg = (x_c == (x_cg << 2) && y_c == (y_cg << 2)); - if (last_cg && implicit_non_zero_coeff && significant_coeff_group_flag[x_cg][y_cg]) { - significant_coeff_flag_idx[nb_significant_coeff_flag] = n; + } + if (implicit_non_zero_coeff == 0) { + if (s->sps->transform_skip_context_enabled_flag && + (transform_skip_flag || lc->cu.cu_transquant_bypass_flag)) { + if (c_idx == 0) { + scf_offset = 42; + } else { + scf_offset = 16 + 27; + } + } else { + if (i == 0) { + if (c_idx == 0) + scf_offset = 0; + else + scf_offset = 27; + } else { + scf_offset = 2 + scf_offset; + } + } + if (significant_coeff_flag_decode_0(s, c_idx, scf_offset) == 1) { + significant_coeff_flag_idx[nb_significant_coeff_flag] = 0; nb_significant_coeff_flag++; } + } else { + significant_coeff_flag_idx[nb_significant_coeff_flag] = 0; + nb_significant_coeff_flag++; } } @@ -1287,41 +1376,55 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, if (n_end) { - int first_nz_pos_in_cg = 16; - int last_nz_pos_in_cg = -1; + int first_nz_pos_in_cg; + int last_nz_pos_in_cg; int c_rice_param = 0; int first_greater1_coeff_idx = -1; - uint8_t coeff_abs_level_greater1_flag[16] = {0}; + uint8_t coeff_abs_level_greater1_flag[8]; uint16_t coeff_sign_flag; int sum_abs = 0; - int sign_hidden = 0; + int sign_hidden; + int sb_type; + // initialize first elem of coeff_bas_level_greater1_flag int ctx_set = (i > 0 && c_idx == 0) ? 2 : 0; + if (s->sps->persistent_rice_adaptation_enabled_flag) { + if (!transform_skip_flag && !lc->cu.cu_transquant_bypass_flag) + sb_type = 2 * (c_idx == 0 ? 1 : 0); + else + sb_type = 2 * (c_idx == 0 ? 1 : 0) + 1; + c_rice_param = lc->stat_coeff[sb_type] / 4; + } + if (!(i == num_last_subset) && greater1_ctx == 0) ctx_set++; greater1_ctx = 1; last_nz_pos_in_cg = significant_coeff_flag_idx[0]; for (m = 0; m < (n_end > 8 ? 8 : n_end); m++) { - int n_idx = significant_coeff_flag_idx[m]; int inc = (ctx_set << 2) + greater1_ctx; - coeff_abs_level_greater1_flag[n_idx] = + coeff_abs_level_greater1_flag[m] = coeff_abs_level_greater1_flag_decode(s, c_idx, inc); - if (coeff_abs_level_greater1_flag[n_idx]) { + if (coeff_abs_level_greater1_flag[m]) { greater1_ctx = 0; + if (first_greater1_coeff_idx == -1) + first_greater1_coeff_idx = m; } else if (greater1_ctx > 0 && greater1_ctx < 3) { greater1_ctx++; } - - if (coeff_abs_level_greater1_flag[n_idx] && - first_greater1_coeff_idx == -1) - first_greater1_coeff_idx = n_idx; } first_nz_pos_in_cg = significant_coeff_flag_idx[n_end - 1]; - sign_hidden = (last_nz_pos_in_cg - first_nz_pos_in_cg >= 4 && - !lc->cu.cu_transquant_bypass_flag); + + if (lc->cu.cu_transquant_bypass_flag || + (lc->cu.pred_mode == MODE_INTRA && + s->sps->implicit_rdpcm_enabled_flag && transform_skip_flag && + (pred_mode_intra == 10 || pred_mode_intra == 26 )) || + explicit_rdpcm_flag) + sign_hidden = 0; + else + sign_hidden = (last_nz_pos_in_cg - first_nz_pos_in_cg >= 4); if (first_greater1_coeff_idx != -1) { coeff_abs_level_greater1_flag[first_greater1_coeff_idx] += coeff_abs_level_greater2_flag_decode(s, c_idx, ctx_set); @@ -1335,15 +1438,39 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, for (m = 0; m < n_end; m++) { n = significant_coeff_flag_idx[m]; GET_COORD(offset, n); - trans_coeff_level = 1 + coeff_abs_level_greater1_flag[n]; - if (trans_coeff_level == ((m < 8) ? - ((n == first_greater1_coeff_idx) ? 3 : 2) : 1)) { - int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(s, trans_coeff_level, c_rice_param); + if (m < 8) { + trans_coeff_level = 1 + coeff_abs_level_greater1_flag[m]; + if (trans_coeff_level == ((m == first_greater1_coeff_idx) ? 3 : 2)) { + int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(s, c_rice_param); - trans_coeff_level += last_coeff_abs_level_remaining; + trans_coeff_level += last_coeff_abs_level_remaining; + if (trans_coeff_level > (3 << c_rice_param)) + c_rice_param = s->sps->persistent_rice_adaptation_enabled_flag ? c_rice_param + 1 : FFMIN(c_rice_param + 1, 4); + if (s->sps->persistent_rice_adaptation_enabled_flag && !rice_init) { + int c_rice_p_init = lc->stat_coeff[sb_type] / 4; + if (last_coeff_abs_level_remaining >= (3 << c_rice_p_init)) + lc->stat_coeff[sb_type]++; + else if (2 * last_coeff_abs_level_remaining < (1 << c_rice_p_init)) + if (lc->stat_coeff[sb_type] > 0) + lc->stat_coeff[sb_type]--; + rice_init = 1; + } + } + } else { + int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(s, c_rice_param); + + trans_coeff_level = 1 + last_coeff_abs_level_remaining; if (trans_coeff_level > (3 << c_rice_param)) - c_rice_param = FFMIN(c_rice_param + 1, 4); - + c_rice_param = s->sps->persistent_rice_adaptation_enabled_flag ? c_rice_param + 1 : FFMIN(c_rice_param + 1, 4); + if (s->sps->persistent_rice_adaptation_enabled_flag && !rice_init) { + int c_rice_p_init = lc->stat_coeff[sb_type] / 4; + if (last_coeff_abs_level_remaining >= (3 << c_rice_p_init)) + lc->stat_coeff[sb_type]++; + else if (2 * last_coeff_abs_level_remaining < (1 << c_rice_p_init)) + if (lc->stat_coeff[sb_type] > 0) + lc->stat_coeff[sb_type]--; + rice_init = 1; + } } if (s->pps->sign_data_hiding_flag && sign_hidden) { sum_abs += trans_coeff_level; @@ -1360,7 +1487,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, case 3: pos = (y_c << 3) + x_c; break; case 4: pos = ((y_c >> 1) << 3) + (x_c >> 1); break; case 5: pos = ((y_c >> 2) << 3) + (x_c >> 2); break; - default: pos = (y_c << 2) + x_c; + default: pos = (y_c << 2) + x_c; break; } scale_m = scale_matrix[pos]; } else { @@ -1382,15 +1509,56 @@ void ff_hevc_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); + if (explicit_rdpcm_flag || (s->sps->implicit_rdpcm_enabled_flag && + (pred_mode_intra == 10 || pred_mode_intra == 26))) { + int mode = s->sps->implicit_rdpcm_enabled_flag ? (pred_mode_intra == 26) : explicit_rdpcm_dir_flag; + + s->hevcdsp.transform_rdpcm(coeffs, log2_trafo_size, mode); + } } else { - if (transform_skip_flag) - s->hevcdsp.transform_skip(dst, coeffs, stride); - 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); + if (transform_skip_flag) { + int rot = s->sps->transform_skip_rotation_enabled_flag && + lc->cu.pred_mode == MODE_INTRA; + if (rot) { + for (i = 0; i < (trafo_size * trafo_size >> 1); i++) + FFSWAP(int16_t, coeffs[i], coeffs[trafo_size * trafo_size - i - 1]); + } + + s->hevcdsp.transform_skip(coeffs, log2_trafo_size); + + if (explicit_rdpcm_flag || (s->sps->implicit_rdpcm_enabled_flag && + lc->cu.pred_mode == MODE_INTRA && + (pred_mode_intra == 10 || pred_mode_intra == 26))) { + int mode = s->sps->implicit_rdpcm_enabled_flag ? (pred_mode_intra == 26) : explicit_rdpcm_dir_flag; + + s->hevcdsp.transform_rdpcm(coeffs, log2_trafo_size, mode); + } + } else if (lc->cu.pred_mode == MODE_INTRA && c_idx == 0 && log2_trafo_size == 2) { + s->hevcdsp.idct_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); + } + } } + if (lc->tu.cross_pf) { + int16_t *coeffs_y = lc->tu.coeffs[0]; + + for (i = 0; i < (trafo_size * trafo_size); i++) { + coeffs[i] = coeffs[i] + ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); + } + } + s->hevcdsp.transform_add[log2_trafo_size-2](dst, coeffs, stride); } void ff_hevc_hls_mvd_coding(HEVCContext *s, int x0, int y0, int log2_cb_size) diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c index 443f2223c..0d3e238d6 100644 --- a/libavcodec/hevc_filter.c +++ b/libavcodec/hevc_filter.c @@ -60,15 +60,19 @@ static int chroma_tc(HEVCContext *s, int qp_y, int c_idx, int tc_offset) else offset = s->pps->cr_qp_offset; - qp_i = av_clip_c(qp_y + offset, 0, 57); - if (qp_i < 30) - qp = qp_i; - else if (qp_i > 43) - qp = qp_i - 6; - else - qp = qp_c[qp_i - 30]; + qp_i = av_clip(qp_y + offset, 0, 57); + if (s->sps->chroma_format_idc == 1) { + if (qp_i < 30) + qp = qp_i; + else if (qp_i > 43) + qp = qp_i - 6; + else + qp = qp_c[qp_i - 30]; + } else { + qp = av_clip(qp_i, 0, 51); + } - 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]; } @@ -149,133 +153,134 @@ static void copy_CTB(uint8_t *dst, uint8_t *src, } } +static void restore_tqb_pixels(HEVCContext *s, int x0, int y0, int width, int height, int c_idx) +{ + if ( s->pps->transquant_bypass_enable_flag || + (s->sps->pcm.loop_filter_disable_flag && s->sps->pcm_enabled_flag)) { + int x, y; + ptrdiff_t stride = s->frame->linesize[c_idx]; + int min_pu_size = 1 << s->sps->log2_min_pu_size; + int hshift = s->sps->hshift[c_idx]; + int vshift = s->sps->vshift[c_idx]; + int x_min = ((x0 ) >> s->sps->log2_min_pu_size); + int y_min = ((y0 ) >> s->sps->log2_min_pu_size); + int x_max = ((x0 + width ) >> s->sps->log2_min_pu_size); + int y_max = ((y0 + height) >> s->sps->log2_min_pu_size); + int len = min_pu_size >> hshift; + for (y = y_min; y < y_max; y++) { + for (x = x_min; x < x_max; x++) { + if (s->is_pcm[y * s->sps->min_pu_width + x]) { + int n; + 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)]; + for (n = 0; n < (min_pu_size >> vshift); n++) { + memcpy(dst, src, len); + src += stride; + dst += stride; + } + } + } + } + } +} + #define CTB(tab, x, y) ((tab)[(y) * s->sps->ctb_width + (x)]) static void sao_filter_CTB(HEVCContext *s, int x, int y) { - // TODO: This should be easily parallelizable - // TODO: skip CBs when (cu_transquant_bypass_flag || (pcm_loop_filter_disable_flag && pcm_flag)) - int c_idx = 0; - int class = 1, class_index; + int c_idx; int edges[4]; // 0 left 1 top 2 right 3 bottom - 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->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]; + SAOParams *sao = &CTB(s->sao, x_ctb, y_ctb); // 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 left_tile_edge = 0; - uint8_t up_tile_edge = 0; + uint8_t vert_edge[] = { 0, 0 }; + uint8_t horiz_edge[] = { 0, 0 }; + uint8_t diag_edge[] = { 0, 0, 0, 0 }; + uint8_t lfase = CTB(s->filter_slice_edges, x_ctb, y_ctb); + uint8_t no_tile_filter = s->pps->tiles_enabled_flag && + !s->pps->loop_filter_across_tiles_enabled_flag; + uint8_t restore = no_tile_filter || !lfase; + uint8_t left_tile_edge = 0; + uint8_t right_tile_edge = 0; + uint8_t up_tile_edge = 0; + uint8_t bottom_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; - 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]]; - 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]; - lfase[2] = CTB(s->filter_slice_edges, x_ctb - 1, y_ctb); - classes[class] = 2; - class++; - x_shift = 8; - } - - 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]]; - 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]; - lfase[1] = CTB(s->filter_slice_edges, x_ctb, y_ctb - 1); - classes[class] = 1; - class++; - y_shift = 4; + if (restore) { if (!edges[0]) { - classes[class] = 3; - sao[class] = &CTB(s->sao, x_ctb - 1, y_ctb - 1); - class++; - - // Tile check here is done current CTB row/col, not above/left like you'd expect, - //but that is because the tile boundary always extends through the whole pic - vert_edge[1] = (!lfase[1] && CTB(s->tab_slice_address, x_ctb, y_ctb - 1) != CTB(s->tab_slice_address, x_ctb - 1, y_ctb - 1)) || left_tile_edge; - vert_edge[3] = vert_edge[1]; - horiz_edge[2] = (!lfase[2] && CTB(s->tab_slice_address, x_ctb - 1, y_ctb) != CTB(s->tab_slice_address, x_ctb - 1, y_ctb - 1)) || up_tile_edge; - horiz_edge[3] = horiz_edge[2]; - diag_edge[0] = (!lfase[0] && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb - 1, y_ctb - 1)) || left_tile_edge || up_tile_edge; - diag_edge[3] = diag_edge[0]; - - // Does left CTB comes after above CTB? - if (CTB(s->tab_slice_address, x_ctb - 1, y_ctb) > - CTB(s->tab_slice_address, x_ctb, y_ctb - 1)) { - diag_edge[2] = !lfase[2] || left_tile_edge || up_tile_edge; - diag_edge[1] = diag_edge[2]; - } else if (CTB(s->tab_slice_address, x_ctb - 1, y_ctb) < - CTB(s->tab_slice_address, x_ctb, y_ctb - 1)) { - diag_edge[1] = !lfase[1] || left_tile_edge || up_tile_edge; - diag_edge[2] = diag_edge[1]; - } else { - // Same slice, only consider tiles - diag_edge[2] = left_tile_edge || up_tile_edge; - diag_edge[1] = diag_edge[2]; - } + 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]]; + vert_edge[0] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb - 1, y_ctb)) || left_tile_edge; + } + if (!edges[2]) { + right_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]]; + vert_edge[1] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb + 1, y_ctb)) || right_tile_edge; + } + 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]]; + horiz_edge[0] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb, y_ctb - 1)) || up_tile_edge; + } + if (!edges[3]) { + bottom_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]]; + horiz_edge[1] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb, y_ctb + 1)) || bottom_tile_edge; + } + if (!edges[0] && !edges[1]) { + diag_edge[0] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb - 1, y_ctb - 1)) || left_tile_edge || up_tile_edge; + } + if (!edges[1] && !edges[2]) { + diag_edge[1] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb + 1, y_ctb - 1)) || right_tile_edge || up_tile_edge; + } + if (!edges[2] && !edges[3]) { + diag_edge[2] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb + 1, y_ctb + 1)) || right_tile_edge || bottom_tile_edge; + } + if (!edges[0] && !edges[3]) { + diag_edge[3] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb - 1, y_ctb + 1)) || left_tile_edge || bottom_tile_edge; } } for (c_idx = 0; c_idx < 3; c_idx++) { - int chroma = c_idx ? 1 : 0; - 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 width = FFMIN(ctb_size, - (s->sps->width >> s->sps->hshift[c_idx]) - x0); - int height = FFMIN(ctb_size, - (s->sps->height >> s->sps->vshift[c_idx]) - y0); + int x0 = x >> s->sps->hshift[c_idx]; + int y0 = y >> s->sps->vshift[c_idx]; + int stride = s->frame->linesize[c_idx]; + int ctb_size_h = (1 << (s->sps->log2_ctb_size)) >> s->sps->hshift[c_idx]; + int ctb_size_v = (1 << (s->sps->log2_ctb_size)) >> s->sps->vshift[c_idx]; + int width = FFMIN(ctb_size_h, + (s->sps->width >> s->sps->hshift[c_idx]) - x0); + int height = FFMIN(ctb_size_v, + (s->sps->height >> s->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); - copy_CTB(dst - offset, src - offset, - (edges[2] ? width + (x_shift >> chroma) : width) << s->sps->pixel_shift, - (edges[3] ? height + (y_shift >> chroma) : height), stride); - - for (class_index = 0; class_index < class; class_index++) { - - switch (sao[class_index]->type_idx[c_idx]) { - case SAO_BAND: - s->hevcdsp.sao_band_filter[classes[class_index]](dst, src, - stride, - sao[class_index], - edges, width, - height, c_idx); - break; - case SAO_EDGE: - s->hevcdsp.sao_edge_filter[classes[class_index]](dst, src, - stride, - sao[class_index], - edges, width, - height, c_idx, - vert_edge[classes[class_index]], - horiz_edge[classes[class_index]], - diag_edge[classes[class_index]]); - break; - } + switch (sao->type_idx[c_idx]) { + case SAO_BAND: + s->hevcdsp.sao_band_filter(dst, src, + stride, + sao, + edges, width, + height, c_idx); + restore_tqb_pixels(s, x, y, width, height, c_idx); + break; + case SAO_EDGE: + s->hevcdsp.sao_edge_filter[restore](dst, src, + stride, + sao, + edges, width, + height, c_idx, + vert_edge, + horiz_edge, + diag_edge); + restore_tqb_pixels(s, x, y, width, height, c_idx); + break; + default : + copy_CTB(dst, src, width << s->sps->pixel_shift, height, stride); + break; } } } @@ -326,6 +331,9 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) if (x0) { left_tc_offset = s->deblock[ctb - 1].tc_offset; left_beta_offset = s->deblock[ctb - 1].beta_offset; + } else { + left_tc_offset = 0; + left_beta_offset = 0; } x_end = x0 + ctb_size; @@ -370,22 +378,25 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) // vertical filtering chroma for (chroma = 1; chroma <= 2; chroma++) { - for (y = y0; y < y_end; y += 16) { - for (x = x0 ? x0 : 16; x < x_end; x += 16) { - const int bs0 = s->vertical_bs[(x >> 3) + (y >> 2) * s->bs_width]; - const int bs1 = s->vertical_bs[(x >> 3) + ((y + 8) >> 2) * s->bs_width]; + int h = 1 << s->sps->hshift[chroma]; + int v = 1 << s->sps->vshift[chroma]; + for (y = y0; y < y_end; y += (8 * v)) { + for (x = x0 ? x0 : 8 * h; x < x_end; x += (8 * h)) { + const int bs0 = s->vertical_bs[(x >> 3) + (y >> 2) * s->bs_width]; + const int bs1 = s->vertical_bs[(x >> 3) + ((y + (4 * v)) >> 2) * s->bs_width]; + if ((bs0 == 2) || (bs1 == 2)) { - const int qp0 = (get_qPy(s, x - 1, y) + get_qPy(s, x, y) + 1) >> 1; - const int qp1 = (get_qPy(s, x - 1, y + 8) + get_qPy(s, x, y + 8) + 1) >> 1; + const int qp0 = (get_qPy(s, x - 1, y) + get_qPy(s, x, y) + 1) >> 1; + const int qp1 = (get_qPy(s, x - 1, y + (4 * v)) + get_qPy(s, x, y + (4 * v)) + 1) >> 1; 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 >> s->sps->vshift[chroma]) * s->frame->linesize[chroma] + ((x >> s->sps->hshift[chroma]) << s->sps->pixel_shift)]; if (pcmf) { no_p[0] = get_pcm(s, x - 1, y); - no_p[1] = get_pcm(s, x - 1, y + 8); + no_p[1] = get_pcm(s, x - 1, y + (4 * v)); no_q[0] = get_pcm(s, x, y); - no_q[1] = get_pcm(s, x, y + 8); + no_q[1] = get_pcm(s, x, y + (4 * v)); s->hevcdsp.hevc_v_loop_filter_chroma_c(src, s->frame->linesize[chroma], c_tc, no_p, no_q); @@ -435,35 +446,37 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) // horizontal filtering chroma for (chroma = 1; chroma <= 2; chroma++) { - for (y = y0 ? y0 : 16; y < y_end; y += 16) { - for (x = x0 - 8; x < x_end; x += 16) { + int h = 1 << s->sps->hshift[chroma]; + int v = 1 << s->sps->vshift[chroma]; + for (y = y0 ? y0 : 8 * v; y < y_end; y += (8 * v)) { + for (x = x0 - 8; x < x_end; x += (8 * h)) { int bs0, bs1; // to make sure no memory access over boundary when x = -8 // TODO: simplify with row based deblocking if (x < 0) { bs0 = 0; - bs1 = s->horizontal_bs[(x + 8 + y * s->bs_width) >> 2]; - } else if (x >= x_end - 8) { - bs0 = s->horizontal_bs[(x + y * s->bs_width) >> 2]; + bs1 = s->horizontal_bs[(x + (4 * h) + y * s->bs_width) >> 2]; + } else if (x >= x_end - 4 * h) { + bs0 = s->horizontal_bs[(x + y * s->bs_width) >> 2]; bs1 = 0; } else { - bs0 = s->horizontal_bs[(x + y * s->bs_width) >> 2]; - bs1 = s->horizontal_bs[(x + 8 + y * s->bs_width) >> 2]; + bs0 = s->horizontal_bs[(x + y * s->bs_width) >> 2]; + bs1 = s->horizontal_bs[(x + (4 * h) + y * s->bs_width) >> 2]; } if ((bs0 == 2) || (bs1 == 2)) { - const int qp0 = bs0 == 2 ? (get_qPy(s, x, y - 1) + get_qPy(s, x, y) + 1) >> 1 : 0; - const int qp1 = bs1 == 2 ? (get_qPy(s, x + 8, y - 1) + get_qPy(s, x + 8, y) + 1) >> 1 : 0; + const int qp0 = bs0 == 2 ? (get_qPy(s, x, y - 1) + get_qPy(s, x, y) + 1) >> 1 : 0; + const int qp1 = bs1 == 2 ? (get_qPy(s, x + (4 * h), y - 1) + get_qPy(s, x + (4 * h), y) + 1) >> 1 : 0; 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 >> s->sps->vshift[1]) * s->frame->linesize[chroma] + ((x >> s->sps->hshift[1]) << s->sps->pixel_shift)]; if (pcmf) { - no_p[0] = get_pcm(s, x, y - 1); - no_p[1] = get_pcm(s, x + 8, y - 1); - no_q[0] = get_pcm(s, x, y); - no_q[1] = get_pcm(s, x + 8, y); + no_p[0] = get_pcm(s, x, y - 1); + no_p[1] = get_pcm(s, x + (4 * h), y - 1); + no_q[0] = get_pcm(s, x, y); + no_q[1] = get_pcm(s, x + (4 * h), y); s->hevcdsp.hevc_h_loop_filter_chroma_c(src, s->frame->linesize[chroma], c_tc, no_p, no_q); @@ -477,138 +490,96 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) } } -static int boundary_strength(HEVCContext *s, MvField *curr, - uint8_t curr_cbf_luma, MvField *neigh, - uint8_t neigh_cbf_luma, - RefPicList *neigh_refPicList, - int tu_border) +static int boundary_strength(HEVCContext *s, MvField *curr, MvField *neigh, + RefPicList *neigh_refPicList) { - int mvs = curr->pred_flag[0] + curr->pred_flag[1]; - - if (tu_border) { - if (curr->is_intra || neigh->is_intra) - return 2; - if (curr_cbf_luma || neigh_cbf_luma) + if (curr->pred_flag == PF_BI && neigh->pred_flag == PF_BI) { + // same L0 and L1 + if (s->ref->refPicList[0].list[curr->ref_idx[0]] == neigh_refPicList[0].list[neigh->ref_idx[0]] && + s->ref->refPicList[0].list[curr->ref_idx[0]] == s->ref->refPicList[1].list[curr->ref_idx[1]] && + neigh_refPicList[0].list[neigh->ref_idx[0]] == neigh_refPicList[1].list[neigh->ref_idx[1]]) { + if ((FFABS(neigh->mv[0].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 4 || + FFABS(neigh->mv[1].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 4) && + (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 4 || + FFABS(neigh->mv[0].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 4)) + return 1; + else + return 0; + } else if (neigh_refPicList[0].list[neigh->ref_idx[0]] == s->ref->refPicList[0].list[curr->ref_idx[0]] && + neigh_refPicList[1].list[neigh->ref_idx[1]] == s->ref->refPicList[1].list[curr->ref_idx[1]]) { + if (FFABS(neigh->mv[0].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 4 || + FFABS(neigh->mv[1].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 4) + return 1; + else + return 0; + } else if (neigh_refPicList[1].list[neigh->ref_idx[1]] == s->ref->refPicList[0].list[curr->ref_idx[0]] && + neigh_refPicList[0].list[neigh->ref_idx[0]] == s->ref->refPicList[1].list[curr->ref_idx[1]]) { + if (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 4 || + FFABS(neigh->mv[0].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 4) + return 1; + else + return 0; + } else { return 1; - } - - if (mvs == neigh->pred_flag[0] + neigh->pred_flag[1]) { - if (mvs == 2) { - // same L0 and L1 - if (s->ref->refPicList[0].list[curr->ref_idx[0]] == neigh_refPicList[0].list[neigh->ref_idx[0]] && - s->ref->refPicList[0].list[curr->ref_idx[0]] == s->ref->refPicList[1].list[curr->ref_idx[1]] && - neigh_refPicList[0].list[neigh->ref_idx[0]] == neigh_refPicList[1].list[neigh->ref_idx[1]]) { - if ((abs(neigh->mv[0].x - curr->mv[0].x) >= 4 || abs(neigh->mv[0].y - curr->mv[0].y) >= 4 || - abs(neigh->mv[1].x - curr->mv[1].x) >= 4 || abs(neigh->mv[1].y - curr->mv[1].y) >= 4) && - (abs(neigh->mv[1].x - curr->mv[0].x) >= 4 || abs(neigh->mv[1].y - curr->mv[0].y) >= 4 || - abs(neigh->mv[0].x - curr->mv[1].x) >= 4 || abs(neigh->mv[0].y - curr->mv[1].y) >= 4)) - return 1; - else - return 0; - } else if (neigh_refPicList[0].list[neigh->ref_idx[0]] == s->ref->refPicList[0].list[curr->ref_idx[0]] && - neigh_refPicList[1].list[neigh->ref_idx[1]] == s->ref->refPicList[1].list[curr->ref_idx[1]]) { - if (abs(neigh->mv[0].x - curr->mv[0].x) >= 4 || abs(neigh->mv[0].y - curr->mv[0].y) >= 4 || - abs(neigh->mv[1].x - curr->mv[1].x) >= 4 || abs(neigh->mv[1].y - curr->mv[1].y) >= 4) - return 1; - else - return 0; - } else if (neigh_refPicList[1].list[neigh->ref_idx[1]] == s->ref->refPicList[0].list[curr->ref_idx[0]] && - neigh_refPicList[0].list[neigh->ref_idx[0]] == s->ref->refPicList[1].list[curr->ref_idx[1]]) { - if (abs(neigh->mv[1].x - curr->mv[0].x) >= 4 || abs(neigh->mv[1].y - curr->mv[0].y) >= 4 || - abs(neigh->mv[0].x - curr->mv[1].x) >= 4 || abs(neigh->mv[0].y - curr->mv[1].y) >= 4) - return 1; - else - return 0; - } else { - return 1; - } - } else { // 1 MV - Mv A, B; - int ref_A, ref_B; - - if (curr->pred_flag[0]) { - A = curr->mv[0]; - ref_A = s->ref->refPicList[0].list[curr->ref_idx[0]]; - } else { - A = curr->mv[1]; - ref_A = s->ref->refPicList[1].list[curr->ref_idx[1]]; - } - - if (neigh->pred_flag[0]) { - B = neigh->mv[0]; - ref_B = neigh_refPicList[0].list[neigh->ref_idx[0]]; - } else { - B = neigh->mv[1]; - ref_B = neigh_refPicList[1].list[neigh->ref_idx[1]]; - } - - if (ref_A == ref_B) { - if (abs(A.x - B.x) >= 4 || abs(A.y - B.y) >= 4) - return 1; - else - return 0; - } else - return 1; } + } else if ((curr->pred_flag != PF_BI) && (neigh->pred_flag != PF_BI)){ // 1 MV + Mv A, B; + int ref_A, ref_B; + + if (curr->pred_flag & 1) { + A = curr->mv[0]; + ref_A = s->ref->refPicList[0].list[curr->ref_idx[0]]; + } else { + A = curr->mv[1]; + ref_A = s->ref->refPicList[1].list[curr->ref_idx[1]]; + } + + if (neigh->pred_flag & 1) { + B = neigh->mv[0]; + ref_B = neigh_refPicList[0].list[neigh->ref_idx[0]]; + } else { + B = neigh->mv[1]; + ref_B = neigh_refPicList[1].list[neigh->ref_idx[1]]; + } + + if (ref_A == ref_B) { + if (FFABS(A.x - B.x) >= 4 || FFABS(A.y - B.y) >= 4) + return 1; + else + return 0; + } else + return 1; } return 1; } void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, - int log2_trafo_size, - int slice_or_tiles_up_boundary, - int slice_or_tiles_left_boundary) + int log2_trafo_size) { + 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 is_intra = tab_mvf[(y0 >> log2_min_pu_size) * min_pu_width + - (x0 >> log2_min_pu_size)].is_intra; + (x0 >> log2_min_pu_size)].pred_flag == PF_INTRA; int i, j, bs; if (y0 > 0 && (y0 & 7) == 0) { - int yp_pu = (y0 - 1) >> log2_min_pu_size; - int yq_pu = y0 >> log2_min_pu_size; - int yp_tu = (y0 - 1) >> log2_min_tu_size; - int yq_tu = y0 >> log2_min_tu_size; - - for (i = 0; i < (1 << log2_trafo_size); i += 4) { - int x_pu = (x0 + i) >> log2_min_pu_size; - int x_tu = (x0 + i) >> log2_min_tu_size; - MvField *top = &tab_mvf[yp_pu * min_pu_width + x_pu]; - MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu]; - uint8_t top_cbf_luma = s->cbf_luma[yp_tu * min_tu_width + x_tu]; - uint8_t curr_cbf_luma = s->cbf_luma[yq_tu * min_tu_width + x_tu]; + int bd_ctby = y0 & ((1 << s->sps->log2_ctb_size) - 1); + int bd_slice = s->sh.slice_loop_filter_across_slices_enabled_flag || + !(lc->slice_or_tiles_up_boundary & 1); + int bd_tiles = s->pps->loop_filter_across_tiles_enabled_flag || + !(lc->slice_or_tiles_up_boundary & 2); + if (((bd_slice && bd_tiles) || bd_ctby)) { + int yp_pu = (y0 - 1) >> log2_min_pu_size; + int yq_pu = y0 >> log2_min_pu_size; + int yp_tu = (y0 - 1) >> log2_min_tu_size; + int yq_tu = y0 >> log2_min_tu_size; RefPicList *top_refPicList = ff_hevc_get_ref_list(s, s->ref, - x0 + i, y0 - 1); - - bs = boundary_strength(s, curr, curr_cbf_luma, - top, top_cbf_luma, top_refPicList, 1); - if (!s->sh.slice_loop_filter_across_slices_enabled_flag && - (slice_or_tiles_up_boundary & 1) && - (y0 % (1 << s->sps->log2_ctb_size)) == 0) - bs = 0; - else if (!s->pps->loop_filter_across_tiles_enabled_flag && - (slice_or_tiles_up_boundary & 2) && - (y0 % (1 << s->sps->log2_ctb_size)) == 0) - bs = 0; - if (y0 == 0 || s->sh.disable_deblocking_filter_flag == 1) - bs = 0; - if (bs) - s->horizontal_bs[((x0 + i) + y0 * s->bs_width) >> 2] = bs; - } - } - - // bs for TU internal horizontal PU boundaries - if (log2_trafo_size > s->sps->log2_min_pu_size && !is_intra) - for (j = 8; j < (1 << log2_trafo_size); j += 8) { - int yp_pu = (y0 + j - 1) >> log2_min_pu_size; - int yq_pu = (y0 + j) >> log2_min_pu_size; - int yp_tu = (y0 + j - 1) >> log2_min_tu_size; - int yq_tu = (y0 + j) >> log2_min_tu_size; + x0, y0 - 1); for (i = 0; i < (1 << log2_trafo_size); i += 4) { int x_pu = (x0 + i) >> log2_min_pu_size; @@ -617,103 +588,127 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu]; uint8_t top_cbf_luma = s->cbf_luma[yp_tu * min_tu_width + x_tu]; uint8_t curr_cbf_luma = s->cbf_luma[yq_tu * min_tu_width + x_tu]; - RefPicList *top_refPicList = ff_hevc_get_ref_list(s, s->ref, - x0 + i, - y0 + j - 1); - bs = boundary_strength(s, curr, curr_cbf_luma, - top, top_cbf_luma, top_refPicList, 0); - if (s->sh.disable_deblocking_filter_flag == 1) - bs = 0; - if (bs) - s->horizontal_bs[((x0 + i) + (y0 + j) * s->bs_width) >> 2] = bs; + if (curr->pred_flag == PF_INTRA || top->pred_flag == PF_INTRA) + bs = 2; + else if (curr_cbf_luma || top_cbf_luma) + bs = 1; + else + bs = boundary_strength(s, curr, top, top_refPicList); + s->horizontal_bs[((x0 + i) + y0 * s->bs_width) >> 2] = bs; } } - - // bs for vertical TU boundaries - if (x0 > 0 && (x0 & 7) == 0) { - int xp_pu = (x0 - 1) >> log2_min_pu_size; - int xq_pu = x0 >> log2_min_pu_size; - int xp_tu = (x0 - 1) >> log2_min_tu_size; - int xq_tu = x0 >> log2_min_tu_size; - - for (i = 0; i < (1 << log2_trafo_size); i += 4) { - int y_pu = (y0 + i) >> log2_min_pu_size; - int y_tu = (y0 + i) >> log2_min_tu_size; - MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu]; - MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu]; - - uint8_t left_cbf_luma = s->cbf_luma[y_tu * min_tu_width + xp_tu]; - uint8_t curr_cbf_luma = s->cbf_luma[y_tu * min_tu_width + xq_tu]; - RefPicList *left_refPicList = ff_hevc_get_ref_list(s, s->ref, - x0 - 1, y0 + i); - - bs = boundary_strength(s, curr, curr_cbf_luma, - left, left_cbf_luma, left_refPicList, 1); - if (!s->sh.slice_loop_filter_across_slices_enabled_flag && - (slice_or_tiles_left_boundary & 1) && - (x0 % (1 << s->sps->log2_ctb_size)) == 0) - bs = 0; - else if (!s->pps->loop_filter_across_tiles_enabled_flag && - (slice_or_tiles_left_boundary & 2) && - (x0 % (1 << s->sps->log2_ctb_size)) == 0) - bs = 0; - if (x0 == 0 || s->sh.disable_deblocking_filter_flag == 1) - bs = 0; - if (bs) - s->vertical_bs[(x0 >> 3) + ((y0 + i) >> 2) * s->bs_width] = bs; - } } - // bs for TU internal vertical PU boundaries - if (log2_trafo_size > log2_min_pu_size && !is_intra) - for (j = 0; j < (1 << log2_trafo_size); j += 4) { - int y_pu = (y0 + j) >> log2_min_pu_size; - int y_tu = (y0 + j) >> log2_min_tu_size; + // bs for vertical TU boundaries + if (x0 > 0 && (x0 & 7) == 0) { + int bd_ctbx = x0 & ((1 << s->sps->log2_ctb_size) - 1); + int bd_slice = s->sh.slice_loop_filter_across_slices_enabled_flag || + !(lc->slice_or_tiles_left_boundary & 1); + int bd_tiles = s->pps->loop_filter_across_tiles_enabled_flag || + !(lc->slice_or_tiles_left_boundary & 2); + if (((bd_slice && bd_tiles) || bd_ctbx)) { + int xp_pu = (x0 - 1) >> log2_min_pu_size; + int xq_pu = x0 >> log2_min_pu_size; + int xp_tu = (x0 - 1) >> log2_min_tu_size; + int xq_tu = x0 >> log2_min_tu_size; + RefPicList *left_refPicList = ff_hevc_get_ref_list(s, s->ref, + x0 - 1, y0); - for (i = 8; i < (1 << log2_trafo_size); i += 8) { - int xp_pu = (x0 + i - 1) >> log2_min_pu_size; - int xq_pu = (x0 + i) >> log2_min_pu_size; - int xp_tu = (x0 + i - 1) >> log2_min_tu_size; - int xq_tu = (x0 + i) >> log2_min_tu_size; + for (i = 0; i < (1 << log2_trafo_size); i += 4) { + int y_pu = (y0 + i) >> log2_min_pu_size; + int y_tu = (y0 + i) >> log2_min_tu_size; MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu]; MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu]; uint8_t left_cbf_luma = s->cbf_luma[y_tu * min_tu_width + xp_tu]; uint8_t curr_cbf_luma = s->cbf_luma[y_tu * min_tu_width + xq_tu]; - RefPicList *left_refPicList = ff_hevc_get_ref_list(s, s->ref, - x0 + i - 1, - y0 + j); - bs = boundary_strength(s, curr, curr_cbf_luma, - left, left_cbf_luma, left_refPicList, 0); - if (s->sh.disable_deblocking_filter_flag == 1) - bs = 0; - if (bs) - s->vertical_bs[((x0 + i) >> 3) + ((y0 + j) >> 2) * s->bs_width] = bs; + if (curr->pred_flag == PF_INTRA || left->pred_flag == PF_INTRA) + bs = 2; + else if (curr_cbf_luma || left_cbf_luma) + bs = 1; + else + bs = boundary_strength(s, curr, left, left_refPicList); + s->vertical_bs[(x0 >> 3) + ((y0 + i) >> 2) * s->bs_width] = bs; } } + } + + if (log2_trafo_size > log2_min_pu_size && !is_intra) { + RefPicList *refPicList = ff_hevc_get_ref_list(s, s->ref, + x0, + y0); + // bs for TU internal horizontal PU boundaries + for (j = 8; j < (1 << log2_trafo_size); j += 8) { + int yp_pu = (y0 + j - 1) >> log2_min_pu_size; + int yq_pu = (y0 + j) >> log2_min_pu_size; + + for (i = 0; i < (1 << log2_trafo_size); i += 4) { + int x_pu = (x0 + i) >> log2_min_pu_size; + MvField *top = &tab_mvf[yp_pu * min_pu_width + x_pu]; + MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu]; + + bs = boundary_strength(s, curr, top, refPicList); + s->horizontal_bs[((x0 + i) + (y0 + j) * s->bs_width) >> 2] = bs; + } + } + + // bs for TU internal vertical PU boundaries + for (j = 0; j < (1 << log2_trafo_size); j += 4) { + int y_pu = (y0 + j) >> log2_min_pu_size; + + for (i = 8; i < (1 << log2_trafo_size); i += 8) { + int xp_pu = (x0 + i - 1) >> log2_min_pu_size; + int xq_pu = (x0 + i) >> log2_min_pu_size; + MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu]; + MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu]; + + bs = boundary_strength(s, curr, left, refPicList); + s->vertical_bs[((x0 + i) >> 3) + ((y0 + j) >> 2) * s->bs_width] = bs; + } + } + } } #undef LUMA #undef CB #undef CR -void ff_hevc_hls_filter(HEVCContext *s, int x, int y) +void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) { deblocking_filter_CTB(s, x, y); - if (s->sps->sao_enabled) - sao_filter_CTB(s, x, y); + if (s->sps->sao_enabled) { + int x_end = x >= s->sps->width - ctb_size; + int y_end = y >= s->sps->height - ctb_size; + if (y && x) + sao_filter_CTB(s, x - ctb_size, y - ctb_size); + if (x && y_end) + sao_filter_CTB(s, x - ctb_size, y); + if (y && x_end) { + sao_filter_CTB(s, x, y - ctb_size); + if (s->threads_type & FF_THREAD_FRAME ) + ff_thread_report_progress(&s->ref->tf, y - ctb_size, 0); + } + if (x_end && y_end) { + sao_filter_CTB(s, x , y); + if (s->threads_type & FF_THREAD_FRAME ) + ff_thread_report_progress(&s->ref->tf, y, 0); + } + } else { + if (y && x >= s->sps->width - ctb_size) + if (s->threads_type & FF_THREAD_FRAME ) + ff_thread_report_progress(&s->ref->tf, y, 0); + } } void ff_hevc_hls_filters(HEVCContext *s, int x_ctb, int y_ctb, int ctb_size) { + int x_end = x_ctb >= s->sps->width - ctb_size; + int y_end = y_ctb >= s->sps->height - 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) { - ff_hevc_hls_filter(s, x_ctb, y_ctb - ctb_size); - if (s->threads_type == FF_THREAD_FRAME ) - ff_thread_report_progress(&s->ref->tf, y_ctb - ctb_size, 0); - } - if (x_ctb && y_ctb >= s->sps->height - ctb_size) - ff_hevc_hls_filter(s, x_ctb - ctb_size, y_ctb); + ff_hevc_hls_filter(s, x_ctb - ctb_size, y_ctb - ctb_size, ctb_size); + if (y_ctb && x_end) + ff_hevc_hls_filter(s, x_ctb, y_ctb - ctb_size, ctb_size); + if (x_ctb && y_end) + ff_hevc_hls_filter(s, x_ctb - ctb_size, y_ctb, ctb_size); } diff --git a/libavcodec/hevc_mvs.c b/libavcodec/hevc_mvs.c index 2b5c07c65..023fb55fb 100644 --- a/libavcodec/hevc_mvs.c +++ b/libavcodec/hevc_mvs.c @@ -65,20 +65,27 @@ 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); - int N; + s->pps->min_tb_addr_zs[(y) * (s->sps->tb_mask+2) + (x)] + + int xCurr_ctb = xCurr >> s->sps->log2_ctb_size; + int yCurr_ctb = yCurr >> s->sps->log2_ctb_size; + int xN_ctb = xN >> s->sps->log2_ctb_size; + int yN_ctb = yN >> s->sps->log2_ctb_size; if (xN < 0 || yN < 0 || xN >= s->sps->width || yN >= s->sps->height) return 0; - N = MIN_TB_ADDR_ZS(xN >> s->sps->log2_min_tb_size, - yN >> s->sps->log2_min_tb_size); - - return N <= Curr; + if( yN_ctb < yCurr_ctb || xN_ctb < xCurr_ctb ) + return 1; + else { + int Curr = MIN_TB_ADDR_ZS((xCurr >> s->sps->log2_min_tb_size) & s->sps->tb_mask, + (yCurr >> s->sps->log2_min_tb_size) & s->sps->tb_mask); + int N = MIN_TB_ADDR_ZS((xN >> s->sps->log2_min_tb_size) & s->sps->tb_mask, + (yN >> s->sps->log2_min_tb_size) & s->sps->tb_mask); + return N <= Curr; + } } static int same_prediction_block(HEVCLocalContext *lc, int log2_cb_size, @@ -123,16 +130,18 @@ static int isDiffMER(HEVCContext *s, int xN, int yN, int xP, int yP) // check if the mv's and refidx are the same between A and B static int compareMVrefidx(struct MvField A, struct MvField B) { - if (A.pred_flag[0] && A.pred_flag[1] && B.pred_flag[0] && B.pred_flag[1]) - return MATCH(ref_idx[0]) && MATCH(mv[0].x) && MATCH(mv[0].y) && - MATCH(ref_idx[1]) && MATCH(mv[1].x) && MATCH(mv[1].y); - - if (A.pred_flag[0] && !A.pred_flag[1] && B.pred_flag[0] && !B.pred_flag[1]) - return MATCH(ref_idx[0]) && MATCH(mv[0].x) && MATCH(mv[0].y); - - if (!A.pred_flag[0] && A.pred_flag[1] && !B.pred_flag[0] && B.pred_flag[1]) - return MATCH(ref_idx[1]) && MATCH(mv[1].x) && MATCH(mv[1].y); - + int a_pf = A.pred_flag; + int b_pf = B.pred_flag; + if (a_pf == b_pf) { + if (a_pf == PF_BI) { + return MATCH(ref_idx[0]) && MATCH(mv[0].x) && MATCH(mv[0].y) && + MATCH(ref_idx[1]) && MATCH(mv[1].x) && MATCH(mv[1].y); + } else if (a_pf == PF_L0) { + return MATCH(ref_idx[0]) && MATCH(mv[0].x) && MATCH(mv[0].y); + } else if (a_pf == PF_L1) { + return MATCH(ref_idx[1]) && MATCH(mv[1].x) && MATCH(mv[1].y); + } + } return 0; } @@ -140,14 +149,14 @@ 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 * src->x < 0)) >> 8); - dst->y = av_clip_int16_c((scale_factor * src->y + 127 + - (scale_factor * src->y < 0)) >> 8); + 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((scale_factor * src->y + 127 + + (scale_factor * src->y < 0)) >> 8); } static int check_mvset(Mv *mvLXCol, Mv *mvCol, @@ -168,10 +177,7 @@ static int check_mvset(Mv *mvLXCol, Mv *mvCol, col_poc_diff = colPic - refPicList_col[listCol].list[refidxCol]; cur_poc_diff = poc - refPicList[X].list[refIdxLx]; - if (!col_poc_diff) - col_poc_diff = 1; // error resilience - - if (cur_lt || col_poc_diff == cur_poc_diff) { + if (cur_lt || col_poc_diff == cur_poc_diff || !col_poc_diff) { mvLXCol->x = mvCol->x; mvLXCol->y = mvCol->y; } else { @@ -193,17 +199,14 @@ static int derive_temporal_colocated_mvs(HEVCContext *s, MvField temp_col, { RefPicList *refPicList = s->ref->refPicList; - if (temp_col.is_intra) { - mvLXCol->x = 0; - mvLXCol->y = 0; + if (temp_col.pred_flag == PF_INTRA) return 0; - } - if (temp_col.pred_flag[0] == 0) + if (!(temp_col.pred_flag & PF_L0)) return CHECK_MVSET(1); - else if (temp_col.pred_flag[0] == 1 && temp_col.pred_flag[1] == 0) + else if (temp_col.pred_flag == PF_L0) return CHECK_MVSET(0); - else if (temp_col.pred_flag[0] == 1 && temp_col.pred_flag[1] == 1) { + else if (temp_col.pred_flag == PF_BI) { int check_diffpicount = 0; int i = 0; for (i = 0; i < refPicList[0].nb_refs; i++) { @@ -272,8 +275,8 @@ static int temporal_luma_motion_vector(HEVCContext *s, int x0, int y0, (y0 >> s->sps->log2_ctb_size) == (y >> s->sps->log2_ctb_size) && y < s->sps->height && x < s->sps->width) { - x = ((x >> 4) << 4); - y = ((y >> 4) << 4); + x &= -16; + y &= -16; x_pu = x >> s->sps->log2_min_pu_size; y_pu = y >> s->sps->log2_min_pu_size; temp_col = TAB_MVF(x_pu, y_pu); @@ -284,8 +287,8 @@ static int temporal_luma_motion_vector(HEVCContext *s, int x0, int y0, if (tab_mvf && !availableFlagLXCol) { x = x0 + (nPbW >> 1); y = y0 + (nPbH >> 1); - x = ((x >> 4) << 4); - y = ((y >> 4) << 4); + x &= -16; + y &= -16; x_pu = x >> s->sps->log2_min_pu_size; y_pu = y >> s->sps->log2_min_pu_size; temp_col = TAB_MVF(x_pu, y_pu); @@ -295,7 +298,7 @@ static int temporal_luma_motion_vector(HEVCContext *s, int x0, int y0, } #define AVAILABLE(cand, v) \ - (cand && !TAB_MVF_PU(v).is_intra) + (cand && !(TAB_MVF_PU(v).pred_flag == PF_INTRA)) #define PRED_BLOCK_AVAILABLE(v) \ check_prediction_block_available(s, log2_cb_size, \ @@ -312,6 +315,7 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, int nPbW, int nPbH, int log2_cb_size, int singleMCLFlag, int part_idx, + int merge_idx, struct MvField mergecandlist[]) { HEVCLocalContext *lc = s->HEVClc; @@ -380,8 +384,11 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, is_available_a1 = 0; } - if (is_available_a1) - mergecandlist[nb_merge_cand++] = TAB_MVF_PU(A1); + if (is_available_a1) { + mergecandlist[0] = TAB_MVF_PU(A1); + if (merge_idx == 0) return; + nb_merge_cand++; + } // above spatial merge candidate is_available_b1 = AVAILABLE(cand_up, B1); @@ -412,8 +419,11 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, if (is_available_b1 && is_available_b0) check_MER = !COMPARE_MV_REFIDX(B0, B1); - if (is_available_b0 && check_MER) - mergecandlist[nb_merge_cand++] = TAB_MVF_PU(B0); + if (is_available_b0 && check_MER) { + mergecandlist[nb_merge_cand] = TAB_MVF_PU(B0); + if (merge_idx == nb_merge_cand) return; + nb_merge_cand++; + } // left bottom spatial merge candidate check_MER = 1; @@ -427,8 +437,11 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, if (is_available_a1 && is_available_a0) check_MER = !COMPARE_MV_REFIDX(A0, A1); - if (is_available_a0 && check_MER) - mergecandlist[nb_merge_cand++] = TAB_MVF_PU(A0); + if (is_available_a0 && check_MER) { + mergecandlist[nb_merge_cand] = TAB_MVF_PU(A0); + if (merge_idx == nb_merge_cand) return; + nb_merge_cand++; + } // above left spatial merge candidate check_MER = 1; @@ -444,8 +457,11 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, if (is_available_b1 && is_available_b2) check_MER_1 = !COMPARE_MV_REFIDX(B2, B1); - if (is_available_b2 && check_MER && check_MER_1 && nb_merge_cand != 4) - mergecandlist[nb_merge_cand++] = TAB_MVF_PU(B2); + if (is_available_b2 && check_MER && check_MER_1 && nb_merge_cand != 4) { + mergecandlist[nb_merge_cand] = TAB_MVF_PU(B2); + if (merge_idx == nb_merge_cand) return; + nb_merge_cand++; + } // temporal motion vector candidate if (s->sh.slice_temporal_mvp_enabled_flag && @@ -458,9 +474,7 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, 0, &mv_l1_col, 1) : 0; if (available_l0 || available_l1) { - mergecandlist[nb_merge_cand].is_intra = 0; - mergecandlist[nb_merge_cand].pred_flag[0] = available_l0; - mergecandlist[nb_merge_cand].pred_flag[1] = available_l1; + mergecandlist[nb_merge_cand].pred_flag = available_l0 + (available_l1 << 1); if (available_l0) { mergecandlist[nb_merge_cand].mv[0] = mv_l0_col; mergecandlist[nb_merge_cand].ref_idx[0] = 0; @@ -469,6 +483,7 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, mergecandlist[nb_merge_cand].mv[1] = mv_l1_col; mergecandlist[nb_merge_cand].ref_idx[1] = 0; } + if (merge_idx == nb_merge_cand) return; nb_merge_cand++; } } @@ -487,20 +502,19 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, MvField l0_cand = mergecandlist[l0_cand_idx]; MvField l1_cand = mergecandlist[l1_cand_idx]; - if (l0_cand.pred_flag[0] && l1_cand.pred_flag[1] && + if ((l0_cand.pred_flag & PF_L0) && (l1_cand.pred_flag & PF_L1) && (refPicList[0].list[l0_cand.ref_idx[0]] != refPicList[1].list[l1_cand.ref_idx[1]] || l0_cand.mv[0].x != l1_cand.mv[1].x || l0_cand.mv[0].y != l1_cand.mv[1].y)) { mergecandlist[nb_merge_cand].ref_idx[0] = l0_cand.ref_idx[0]; mergecandlist[nb_merge_cand].ref_idx[1] = l1_cand.ref_idx[1]; - mergecandlist[nb_merge_cand].pred_flag[0] = 1; - mergecandlist[nb_merge_cand].pred_flag[1] = 1; + mergecandlist[nb_merge_cand].pred_flag = PF_BI; mergecandlist[nb_merge_cand].mv[0].x = l0_cand.mv[0].x; mergecandlist[nb_merge_cand].mv[0].y = l0_cand.mv[0].y; mergecandlist[nb_merge_cand].mv[1].x = l1_cand.mv[1].x; mergecandlist[nb_merge_cand].mv[1].y = l1_cand.mv[1].y; - mergecandlist[nb_merge_cand].is_intra = 0; + if (merge_idx == nb_merge_cand) return; nb_merge_cand++; } } @@ -508,16 +522,15 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, // append Zero motion vector candidates while (nb_merge_cand < s->sh.max_num_merge_cand) { - mergecandlist[nb_merge_cand].pred_flag[0] = 1; - mergecandlist[nb_merge_cand].pred_flag[1] = s->sh.slice_type == B_SLICE; + mergecandlist[nb_merge_cand].pred_flag = PF_L0 + ((s->sh.slice_type == B_SLICE) << 1); mergecandlist[nb_merge_cand].mv[0].x = 0; mergecandlist[nb_merge_cand].mv[0].y = 0; mergecandlist[nb_merge_cand].mv[1].x = 0; mergecandlist[nb_merge_cand].mv[1].y = 0; - mergecandlist[nb_merge_cand].is_intra = 0; mergecandlist[nb_merge_cand].ref_idx[0] = zero_idx < nb_refs ? zero_idx : 0; mergecandlist[nb_merge_cand].ref_idx[1] = zero_idx < nb_refs ? zero_idx : 0; + if (merge_idx == nb_merge_cand) return; nb_merge_cand++; zero_idx++; } @@ -548,13 +561,12 @@ void ff_hevc_luma_mv_merge_mode(HEVCContext *s, int x0, int y0, int nPbW, ff_hevc_set_neighbour_available(s, x0, y0, nPbW, nPbH); derive_spatial_merge_candidates(s, x0, y0, nPbW, nPbH, log2_cb_size, - singleMCLFlag, part_idx, mergecand_list); + singleMCLFlag, part_idx, + merge_idx, mergecand_list); - if (mergecand_list[merge_idx].pred_flag[0] == 1 && - mergecand_list[merge_idx].pred_flag[1] == 1 && + if (mergecand_list[merge_idx].pred_flag == PF_BI && (nPbW2 + nPbH2) == 12) { - mergecand_list[merge_idx].ref_idx[1] = -1; - mergecand_list[merge_idx].pred_flag[1] = 0; + mergecand_list[merge_idx].pred_flag = PF_L0; } *mv = mergecand_list[merge_idx]; @@ -585,7 +597,7 @@ static int mv_mp_mode_mx(HEVCContext *s, int x, int y, int pred_flag_index, RefPicList *refPicList = s->ref->refPicList; - if (TAB_MVF(x, y).pred_flag[pred_flag_index] == 1 && + if (((TAB_MVF(x, y).pred_flag) & (1 << pred_flag_index)) && refPicList[pred_flag_index].list[TAB_MVF(x, y).ref_idx[pred_flag_index]] == refPicList[ref_idx_curr].list[ref_idx]) { *mv = TAB_MVF(x, y).mv[pred_flag_index]; return 1; @@ -600,18 +612,20 @@ static int mv_mp_mode_mx_lt(HEVCContext *s, int x, int y, int pred_flag_index, int min_pu_width = s->sps->min_pu_width; RefPicList *refPicList = s->ref->refPicList; - int currIsLongTerm = refPicList[ref_idx_curr].isLongTerm[ref_idx]; - int colIsLongTerm = - refPicList[pred_flag_index].isLongTerm[(TAB_MVF(x, y).ref_idx[pred_flag_index])]; + if ((TAB_MVF(x, y).pred_flag) & (1 << pred_flag_index)) { + int currIsLongTerm = refPicList[ref_idx_curr].isLongTerm[ref_idx]; - if (TAB_MVF(x, y).pred_flag[pred_flag_index] && - colIsLongTerm == currIsLongTerm) { - *mv = TAB_MVF(x, y).mv[pred_flag_index]; - if (!currIsLongTerm) - dist_scale(s, mv, min_pu_width, x, y, - pred_flag_index, ref_idx_curr, ref_idx); - return 1; + int colIsLongTerm = + refPicList[pred_flag_index].isLongTerm[(TAB_MVF(x, y).ref_idx[pred_flag_index])]; + + if (colIsLongTerm == currIsLongTerm) { + *mv = TAB_MVF(x, y).mv[pred_flag_index]; + if (!currIsLongTerm) + dist_scale(s, mv, min_pu_width, x, y, + pred_flag_index, ref_idx_curr, ref_idx); + return 1; + } } return 0; } @@ -657,8 +671,8 @@ void ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW, int xB2_pu = 0, yB2_pu = 0; int is_available_b2 = 0; Mv mvpcand_list[2] = { { 0 } }; - Mv mxA = { 0 }; - Mv mxB = { 0 }; + Mv mxA; + Mv mxB; int ref_idx_curr = 0; int ref_idx = 0; int pred_flag_index_l0; @@ -723,6 +737,11 @@ void ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW, availableFlagLXA0 = MP_MX_LT(A1, pred_flag_index_l1, mxA); } + if(availableFlagLXA0 && !mvp_lx_flag) { + mv->mv[LX] = mxA; + return; + } + // B candidates // above right spatial merge candidate xB0 = x0 + nPbW; @@ -812,10 +831,5 @@ void ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW, mvpcand_list[numMVPCandLX++] = mv_col; } - // insert zero motion vectors when the number of available candidates are less than 2 - while (numMVPCandLX < 2) - mvpcand_list[numMVPCandLX++] = (Mv){ 0, 0 }; - - mv->mv[LX].x = mvpcand_list[mvp_lx_flag].x; - mv->mv[LX].y = mvpcand_list[mvp_lx_flag].y; + mv->mv[LX] = mvpcand_list[mvp_lx_flag]; } diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c index dc1f6d5a3..834b93b9e 100644 --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@ -169,7 +169,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx s->picture_structure = h->picture_struct; s->field_order = h->picture_struct; - if (h->nal_unit_type >= 16 && h->nal_unit_type <= 23) { + if (IS_IRAP(h)) { s->key_frame = 1; sh->no_output_of_prior_pics_flag = get_bits1(gb); } @@ -331,6 +331,9 @@ static void hevc_close(AVCodecParserContext *s) for (i = 0; i < FF_ARRAY_ELEMS(h->pps_list); i++) av_buffer_unref(&h->pps_list[i]); + av_buffer_unref(&h->current_sps); + h->sps = NULL; + for (i = 0; i < h->nals_allocated; i++) av_freep(&h->nals[i].rbsp_buffer); av_freep(&h->nals); diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 647f83eec..98d987dcf 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -207,6 +207,8 @@ static void decode_profile_tier_level(HEVCContext *s, PTLCommon *ptl) av_log(s->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"); + else if (ptl->profile_idc == FF_PROFILE_HEVC_REXT) + av_log(s->avctx, AV_LOG_DEBUG, "Range Extension profile bitstream\n"); else av_log(s->avctx, AV_LOG_WARNING, "Unknown HEVC profile: %d\n", ptl->profile_idc); @@ -370,20 +372,26 @@ int ff_hevc_decode_nal_vps(HEVCContext *s) vps->vps_num_reorder_pics[i] = get_ue_golomb_long(gb); vps->vps_max_latency_increase[i] = get_ue_golomb_long(gb) - 1; - if (vps->vps_max_dec_pic_buffering[i] > MAX_DPB_SIZE) { + if (vps->vps_max_dec_pic_buffering[i] > MAX_DPB_SIZE || !vps->vps_max_dec_pic_buffering[i]) { av_log(s->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_ERROR, "vps_max_num_reorder_pics out of range: %d\n", + av_log(s->avctx, AV_LOG_WARNING, "vps_max_num_reorder_pics out of range: %d\n", vps->vps_num_reorder_pics[i]); - goto err; + if (s->avctx->err_recognition & AV_EF_EXPLODE) + goto err; } } vps->vps_max_layer_id = get_bits(gb, 6); vps->vps_num_layer_sets = get_ue_golomb_long(gb) + 1; + if ((vps->vps_num_layer_sets - 1LL) * (vps->vps_max_layer_id + 1LL) > get_bits_left(gb)) { + av_log(s->avctx, AV_LOG_ERROR, "too many layer_id_included_flags\n"); + goto err; + } + for (i = 1; i < vps->vps_num_layer_sets; i++) for (j = 0; j <= vps->vps_max_layer_id; j++) skip_bits(gb, 1); // layer_id_included_flag[i][j] @@ -662,8 +670,8 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) } 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"); + if (!(sps->chroma_format_idc == 1 || sps->chroma_format_idc == 2 || sps->chroma_format_idc == 3)) { + avpriv_report_missing_feature(s->avctx, "chroma_format_idc != {1, 2, 3}\n"); ret = AVERROR_PATCHWELCOME; goto err; } @@ -671,6 +679,9 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) if (sps->chroma_format_idc == 3) sps->separate_colour_plane_flag = get_bits1(gb); + if (sps->separate_colour_plane_flag) + sps->chroma_format_idc = 0; + sps->width = get_ue_golomb_long(gb); sps->height = get_ue_golomb_long(gb); if ((ret = av_image_check_size(sps->width, @@ -712,20 +723,30 @@ 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 { + switch (sps->bit_depth) { + case 8: + if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P; + if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P; + if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P; + break; + case 9: + if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P9; + if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P9; + if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P9; + break; + case 10: + if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P10; + if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P10; + if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P10; + break; + case 12: + if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P12; + if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P12; + if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P12; + break; + default: av_log(s->avctx, AV_LOG_ERROR, - "non-4:2:0 support is currently unspecified.\n"); + "4:2:0, 4:2:2, 4:4:4 supports are currently specified for 8, 10 and 12 bits.\n"); return AVERROR_PATCHWELCOME; } @@ -762,9 +783,10 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) 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_ERROR, "sps_max_num_reorder_pics out of range: %d\n", + av_log(s->avctx, AV_LOG_WARNING, "sps_max_num_reorder_pics out of range: %d\n", sps->temporal_layer[i].num_reorder_pics); - if (sps->temporal_layer[i].num_reorder_pics > MAX_DPB_SIZE - 1) { + if (s->avctx->err_recognition & AV_EF_EXPLODE || + sps->temporal_layer[i].num_reorder_pics > MAX_DPB_SIZE - 1) { ret = AVERROR_INVALIDDATA; goto err; } @@ -855,8 +877,42 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) vui_present = get_bits1(gb); if (vui_present) decode_vui(s, sps); - skip_bits1(gb); // sps_extension_flag + if (get_bits1(gb)) { // sps_extension_flag + int sps_extension_flag[1]; + for (i = 0; i < 1; i++) + sps_extension_flag[i] = get_bits1(gb); + skip_bits(gb, 7); //sps_extension_7bits = get_bits(gb, 7); + if (sps_extension_flag[0]) { + int extended_precision_processing_flag; + int high_precision_offsets_enabled_flag; + int cabac_bypass_alignment_enabled_flag; + + sps->transform_skip_rotation_enabled_flag = get_bits1(gb); + sps->transform_skip_context_enabled_flag = get_bits1(gb); + sps->implicit_rdpcm_enabled_flag = get_bits1(gb); + + sps->explicit_rdpcm_enabled_flag = get_bits1(gb); + + extended_precision_processing_flag = get_bits1(gb); + if (extended_precision_processing_flag) + av_log(s->avctx, AV_LOG_WARNING, + "extended_precision_processing_flag not yet implemented\n"); + + sps->intra_smoothing_disabled_flag = get_bits1(gb); + high_precision_offsets_enabled_flag = get_bits1(gb); + if (high_precision_offsets_enabled_flag) + av_log(s->avctx, AV_LOG_WARNING, + "high_precision_offsets_enabled_flag not yet implemented\n"); + + sps->persistent_rice_adaptation_enabled_flag = get_bits1(gb); + + cabac_bypass_alignment_enabled_flag = get_bits1(gb); + if (cabac_bypass_alignment_enabled_flag) + av_log(s->avctx, AV_LOG_WARNING, + "cabac_bypass_alignment_enabled_flag not yet implemented\n"); + } + } if (s->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; @@ -906,6 +962,7 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) sps->min_tb_height = sps->height >> sps->log2_min_tb_size; sps->min_pu_width = sps->width >> sps->log2_min_pu_size; sps->min_pu_height = sps->height >> sps->log2_min_pu_size; + sps->tb_mask = (1 << (sps->log2_ctb_size - sps->log2_min_tb_size)) - 1; sps->qp_bd_offset = 6 * (sps->bit_depth - 8); @@ -956,6 +1013,12 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) if (s->pps_list[i] && ((HEVCPPS*)s->pps_list[i]->data)->sps_id == sps_id) av_buffer_unref(&s->pps_list[i]); } + if (s->sps_list[sps_id] && s->sps == (HEVCSPS*)s->sps_list[sps_id]->data) { + av_buffer_unref(&s->current_sps); + s->current_sps = av_buffer_ref(s->sps_list[sps_id]); + if (!s->current_sps) + s->sps = NULL; + } av_buffer_unref(&s->sps_list[sps_id]); s->sps_list[sps_id] = sps_buf; } @@ -980,17 +1043,56 @@ static void hevc_pps_free(void *opaque, uint8_t *data) av_freep(&pps->ctb_addr_ts_to_rs); av_freep(&pps->tile_pos_rs); av_freep(&pps->tile_id); - av_freep(&pps->min_cb_addr_zs); - av_freep(&pps->min_tb_addr_zs); + av_freep(&pps->min_tb_addr_zs_tab); av_freep(&pps); } +static int pps_range_extensions(HEVCContext *s, HEVCPPS *pps, HEVCSPS *sps) { + GetBitContext *gb = &s->HEVClc->gb; + int i; + + if (pps->transform_skip_enabled_flag) { + pps->log2_max_transform_skip_block_size = get_ue_golomb_long(gb) + 2; + } + pps->cross_component_prediction_enabled_flag = get_bits1(gb); + if (pps->cross_component_prediction_enabled_flag) { + av_log(s->avctx, AV_LOG_WARNING, + "cross_component_prediction_enabled_flag is not yet implemented.\n"); + } + pps->chroma_qp_offset_list_enabled_flag = get_bits1(gb); + if (pps->chroma_qp_offset_list_enabled_flag) { + pps->diff_cu_chroma_qp_offset_depth = get_ue_golomb_long(gb); + pps->chroma_qp_offset_list_len_minus1 = get_ue_golomb_long(gb); + if (pps->chroma_qp_offset_list_len_minus1 && pps->chroma_qp_offset_list_len_minus1 >= 5) { + av_log(s->avctx, AV_LOG_ERROR, + "chroma_qp_offset_list_len_minus1 shall be in the range [0, 5].\n"); + return AVERROR_INVALIDDATA; + } + for (i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) { + pps->cb_qp_offset_list[i] = get_se_golomb_long(gb); + if (pps->cb_qp_offset_list[i]) { + av_log(s->avctx, AV_LOG_WARNING, + "cb_qp_offset_list not tested yet.\n"); + } + pps->cr_qp_offset_list[i] = get_se_golomb_long(gb); + if (pps->cr_qp_offset_list[i]) { + av_log(s->avctx, AV_LOG_WARNING, + "cb_qp_offset_list not tested yet.\n"); + } + } + } + pps->log2_sao_offset_scale_luma = get_ue_golomb_long(gb); + pps->log2_sao_offset_scale_chroma = get_ue_golomb_long(gb); + + return(0); +} + int ff_hevc_decode_nal_pps(HEVCContext *s) { GetBitContext *gb = &s->HEVClc->gb; HEVCSPS *sps = NULL; - int pic_area_in_ctbs, pic_area_in_min_cbs, pic_area_in_min_tbs; + int pic_area_in_ctbs; int log2_diff_ctb_min_tb_size; int i, j, x, y, ctb_addr_rs, tile_id; int ret = 0; @@ -1019,6 +1121,7 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) pps->disable_dbf = 0; pps->beta_offset = 0; pps->tc_offset = 0; + pps->log2_max_transform_skip_block_size = 2; // Coded parameters pps_id = get_ue_golomb_long(gb); @@ -1179,7 +1282,16 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) } pps->slice_header_extension_present_flag = get_bits1(gb); - skip_bits1(gb); // pps_extension_flag + + if (get_bits1(gb)) { // pps_extension_present_flag + int pps_range_extensions_flag = get_bits1(gb); + /* int pps_extension_7bits = */ get_bits(gb, 7); + if (sps->ptl.general_ptl.profile_idc == FF_PROFILE_HEVC_REXT && pps_range_extensions_flag) { + av_log(s->avctx, AV_LOG_ERROR, + "PPS extension flag is partially implemented.\n"); + pps_range_extensions(s, pps, sps); + } + } // Inferred parameters pps->col_bd = av_malloc_array(pps->num_tile_columns + 1, sizeof(*pps->col_bd)); @@ -1229,16 +1341,13 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) * 6.5 */ pic_area_in_ctbs = sps->ctb_width * sps->ctb_height; - pic_area_in_min_cbs = sps->min_cb_width * sps->min_cb_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_cb_addr_zs = av_malloc_array(pic_area_in_min_cbs, sizeof(*pps->min_cb_addr_zs)); - pps->min_tb_addr_zs = av_malloc_array(pic_area_in_min_tbs, sizeof(*pps->min_tb_addr_zs)); + pps->min_tb_addr_zs_tab = av_malloc_array((sps->tb_mask+2) * (sps->tb_mask+2), sizeof(*pps->min_tb_addr_zs_tab)); if (!pps->ctb_addr_rs_to_ts || !pps->ctb_addr_ts_to_rs || - !pps->tile_id || !pps->min_cb_addr_zs || !pps->min_tb_addr_zs) { + !pps->tile_id || !pps->min_tb_addr_zs_tab) { ret = AVERROR(ENOMEM); goto err; } @@ -1292,24 +1401,14 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) 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]; - for (y = 0; y < sps->min_cb_height; y++) { - for (x = 0; x < sps->min_cb_width; x++) { - int tb_x = x >> sps->log2_diff_max_min_coding_block_size; - int tb_y = y >> sps->log2_diff_max_min_coding_block_size; - int ctb_addr_rs = sps->ctb_width * tb_y + tb_x; - int val = pps->ctb_addr_rs_to_ts[ctb_addr_rs] << - (sps->log2_diff_max_min_coding_block_size * 2); - for (i = 0; i < sps->log2_diff_max_min_coding_block_size; i++) { - int m = 1 << i; - val += (m & x ? m * m : 0) + (m & y ? 2 * m * m : 0); - } - pps->min_cb_addr_zs[y * sps->min_cb_width + x] = val; - } - } - 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++) { + pps->min_tb_addr_zs = &pps->min_tb_addr_zs_tab[1*(sps->tb_mask+2)+1]; + for (y = 0; y < sps->tb_mask+2; y++) { + pps->min_tb_addr_zs_tab[y*(sps->tb_mask+2)] = -1; + pps->min_tb_addr_zs_tab[y] = -1; + } + for (y = 0; y < sps->tb_mask+1; y++) { + for (x = 0; x < sps->tb_mask+1; 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; @@ -1319,7 +1418,7 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) 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; + pps->min_tb_addr_zs[y * (sps->tb_mask+2) + x] = val; } } diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c index 3a8e4a3f2..136cc6ff0 100644 --- a/libavcodec/hevc_refs.c +++ b/libavcodec/hevc_refs.c @@ -144,8 +144,12 @@ int ff_hevc_set_new_ref(HEVCContext *s, AVFrame **frame, int poc) *frame = ref->frame; s->ref = ref; + if (s->sh.pic_output_flag) + ref->flags = HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_SHORT_REF; + else + ref->flags = HEVC_FRAME_FLAG_SHORT_REF; + ref->poc = poc; - ref->flags = HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_SHORT_REF; ref->sequence = s->seq_decode; ref->window = s->sps->output_window; @@ -159,6 +163,16 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush) int min_poc = INT_MAX; int i, min_idx, ret; + if (s->sh.no_output_of_prior_pics_flag == 1) { + for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { + HEVCFrame *frame = &s->DPB[i]; + if ((frame->flags & HEVC_FRAME_FLAG_OUTPUT) && frame->poc != s->poc && + frame->sequence == s->seq_output) { + frame->flags &= ~(HEVC_FRAME_FLAG_OUTPUT); + } + } + } + for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { HEVCFrame *frame = &s->DPB[i]; if ((frame->flags & HEVC_FRAME_FLAG_OUTPUT) && diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 216db37e5..5bb5c9010 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -43,7 +43,7 @@ static void decode_nal_sei_decoded_picture_hash(HEVCContext *s) // picture_crc = get_bits(gb, 16); skip_bits(gb, 16); } else if (hash_type == 2) { - // picture_checksum = get_bits(gb, 32); + // picture_checksum = get_bits_long(gb, 32); skip_bits(gb, 32); } } @@ -74,6 +74,21 @@ static void decode_nal_sei_frame_packing_arrangement(HEVCContext *s) skip_bits1(gb); // upsampled_aspect_ratio_flag } +static void decode_nal_sei_display_orientation(HEVCContext *s) +{ + GetBitContext *gb = &s->HEVClc->gb; + + s->sei_display_orientation_present = !get_bits1(gb); + + if (s->sei_display_orientation_present) { + s->sei_hflip = get_bits1(gb); // hor_flip + s->sei_vflip = get_bits1(gb); // ver_flip + + s->sei_anticlockwise_rotation = get_bits(gb, 16); + skip_bits1(gb); // display_orientation_persistence_flag + } +} + static int decode_pic_timing(HEVCContext *s) { GetBitContext *gb = &s->HEVClc->gb; @@ -145,10 +160,10 @@ static int decode_nal_sei_message(HEVCContext *s) if (s->nal_unit_type == NAL_SEI_PREFIX) { if (payload_type == 256 /*&& s->decode_checksum_sei*/) { decode_nal_sei_decoded_picture_hash(s); - return 1; } else if (payload_type == 45) { decode_nal_sei_frame_packing_arrangement(s); - return 1; + } else if (payload_type == 47) { + decode_nal_sei_display_orientation(s); } else if (payload_type == 1){ int ret = decode_pic_timing(s); av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type); @@ -157,11 +172,9 @@ static int decode_nal_sei_message(HEVCContext *s) } else if (payload_type == 129){ active_parameter_sets(s); av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type); - return 1; } else { av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type); skip_bits(gb, 8*payload_size); - return 1; } } else { /* nal_unit_type == NAL_SEI_SUFFIX */ if (payload_type == 132 /* && s->decode_checksum_sei */) @@ -170,8 +183,8 @@ static int decode_nal_sei_message(HEVCContext *s) av_log(s->avctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", payload_type); skip_bits(gb, 8 * payload_size); } - return 1; } + return 1; } static int more_rbsp_data(GetBitContext *gb) diff --git a/libavcodec/hevcdsp.c b/libavcodec/hevcdsp.c index be44bc995..218c48f84 100644 --- a/libavcodec/hevcdsp.c +++ b/libavcodec/hevcdsp.c @@ -2,6 +2,8 @@ * HEVC video decoder * * Copyright (C) 2012 - 2013 Guillaume Martres + * Copyright (C) 2013 - 2014 Pierre-Edouard Lepere + * * * This file is part of FFmpeg. * @@ -89,14 +91,20 @@ 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]) = { - { -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 int8_t, ff_hevc_epel_filters[7][4]) = { + { -2, 58, 10, -2}, + { -4, 54, 16, -2}, + { -6, 46, 28, -4}, + { -4, 36, 36, -4}, + { -4, 28, 46, -6}, + { -2, 16, 54, -4}, + { -2, 10, 58, -2}, +}; + +DECLARE_ALIGNED(16, const int8_t, ff_hevc_qpel_filters[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 @@ -111,62 +119,110 @@ DECLARE_ALIGNED(16, const int8_t, ff_hevc_epel_filters[7][16]) = { #include "hevcdsp_template.c" #undef BIT_DEPTH +#define BIT_DEPTH 12 +#include "hevcdsp_template.c" +#undef BIT_DEPTH + void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth) { #undef FUNC #define FUNC(a, depth) a ## _ ## depth +#undef PEL_FUNC +#define PEL_FUNC(dst1, idx1, idx2, a, depth) \ + for(i = 0 ; i < 10 ; i++) \ +{ \ + hevcdsp->dst1[i][idx1][idx2] = a ## _ ## depth; \ +} + +#undef EPEL_FUNCS +#define EPEL_FUNCS(depth) \ + PEL_FUNC(put_hevc_epel, 0, 0, put_hevc_pel_pixels, depth); \ + PEL_FUNC(put_hevc_epel, 0, 1, put_hevc_epel_h, depth); \ + PEL_FUNC(put_hevc_epel, 1, 0, put_hevc_epel_v, depth); \ + PEL_FUNC(put_hevc_epel, 1, 1, put_hevc_epel_hv, depth) + +#undef EPEL_UNI_FUNCS +#define EPEL_UNI_FUNCS(depth) \ + PEL_FUNC(put_hevc_epel_uni, 0, 0, put_hevc_pel_uni_pixels, depth); \ + PEL_FUNC(put_hevc_epel_uni, 0, 1, put_hevc_epel_uni_h, depth); \ + PEL_FUNC(put_hevc_epel_uni, 1, 0, put_hevc_epel_uni_v, depth); \ + PEL_FUNC(put_hevc_epel_uni, 1, 1, put_hevc_epel_uni_hv, depth); \ + PEL_FUNC(put_hevc_epel_uni_w, 0, 0, put_hevc_pel_uni_w_pixels, depth); \ + PEL_FUNC(put_hevc_epel_uni_w, 0, 1, put_hevc_epel_uni_w_h, depth); \ + PEL_FUNC(put_hevc_epel_uni_w, 1, 0, put_hevc_epel_uni_w_v, depth); \ + PEL_FUNC(put_hevc_epel_uni_w, 1, 1, put_hevc_epel_uni_w_hv, depth) + +#undef EPEL_BI_FUNCS +#define EPEL_BI_FUNCS(depth) \ + PEL_FUNC(put_hevc_epel_bi, 0, 0, put_hevc_pel_bi_pixels, depth); \ + PEL_FUNC(put_hevc_epel_bi, 0, 1, put_hevc_epel_bi_h, depth); \ + PEL_FUNC(put_hevc_epel_bi, 1, 0, put_hevc_epel_bi_v, depth); \ + PEL_FUNC(put_hevc_epel_bi, 1, 1, put_hevc_epel_bi_hv, depth); \ + PEL_FUNC(put_hevc_epel_bi_w, 0, 0, put_hevc_pel_bi_w_pixels, depth); \ + PEL_FUNC(put_hevc_epel_bi_w, 0, 1, put_hevc_epel_bi_w_h, depth); \ + PEL_FUNC(put_hevc_epel_bi_w, 1, 0, put_hevc_epel_bi_w_v, depth); \ + PEL_FUNC(put_hevc_epel_bi_w, 1, 1, put_hevc_epel_bi_w_hv, depth) + +#undef QPEL_FUNCS +#define QPEL_FUNCS(depth) \ + PEL_FUNC(put_hevc_qpel, 0, 0, put_hevc_pel_pixels, depth); \ + PEL_FUNC(put_hevc_qpel, 0, 1, put_hevc_qpel_h, depth); \ + PEL_FUNC(put_hevc_qpel, 1, 0, put_hevc_qpel_v, depth); \ + PEL_FUNC(put_hevc_qpel, 1, 1, put_hevc_qpel_hv, depth) + +#undef QPEL_UNI_FUNCS +#define QPEL_UNI_FUNCS(depth) \ + PEL_FUNC(put_hevc_qpel_uni, 0, 0, put_hevc_pel_uni_pixels, depth); \ + PEL_FUNC(put_hevc_qpel_uni, 0, 1, put_hevc_qpel_uni_h, depth); \ + PEL_FUNC(put_hevc_qpel_uni, 1, 0, put_hevc_qpel_uni_v, depth); \ + PEL_FUNC(put_hevc_qpel_uni, 1, 1, put_hevc_qpel_uni_hv, depth); \ + PEL_FUNC(put_hevc_qpel_uni_w, 0, 0, put_hevc_pel_uni_w_pixels, depth); \ + PEL_FUNC(put_hevc_qpel_uni_w, 0, 1, put_hevc_qpel_uni_w_h, depth); \ + PEL_FUNC(put_hevc_qpel_uni_w, 1, 0, put_hevc_qpel_uni_w_v, depth); \ + PEL_FUNC(put_hevc_qpel_uni_w, 1, 1, put_hevc_qpel_uni_w_hv, depth) + +#undef QPEL_BI_FUNCS +#define QPEL_BI_FUNCS(depth) \ + PEL_FUNC(put_hevc_qpel_bi, 0, 0, put_hevc_pel_bi_pixels, depth); \ + PEL_FUNC(put_hevc_qpel_bi, 0, 1, put_hevc_qpel_bi_h, depth); \ + PEL_FUNC(put_hevc_qpel_bi, 1, 0, put_hevc_qpel_bi_v, depth); \ + PEL_FUNC(put_hevc_qpel_bi, 1, 1, put_hevc_qpel_bi_hv, depth); \ + PEL_FUNC(put_hevc_qpel_bi_w, 0, 0, put_hevc_pel_bi_w_pixels, depth); \ + PEL_FUNC(put_hevc_qpel_bi_w, 0, 1, put_hevc_qpel_bi_w_h, depth); \ + PEL_FUNC(put_hevc_qpel_bi_w, 1, 0, put_hevc_qpel_bi_w_v, depth); \ + PEL_FUNC(put_hevc_qpel_bi_w, 1, 1, put_hevc_qpel_bi_w_hv, 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_add[0] = FUNC(transform_add4x4, depth); \ + hevcdsp->transform_add[1] = FUNC(transform_add8x8, depth); \ + hevcdsp->transform_add[2] = FUNC(transform_add16x16, depth); \ + hevcdsp->transform_add[3] = FUNC(transform_add32x32, 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->transform_rdpcm = FUNC(transform_rdpcm, depth); \ + hevcdsp->idct_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->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); \ - hevcdsp->sao_band_filter[3] = FUNC(sao_band_filter_3, depth); \ - \ - hevcdsp->sao_edge_filter[0] = FUNC(sao_edge_filter_0, depth); \ - hevcdsp->sao_edge_filter[1] = FUNC(sao_edge_filter_1, 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); \ - \ - hevcdsp->put_unweighted_pred = FUNC(put_unweighted_pred, depth); \ - hevcdsp->put_weighted_pred_avg = FUNC(put_weighted_pred_avg, depth); \ - \ - hevcdsp->weighted_pred = FUNC(weighted_pred, depth); \ - hevcdsp->weighted_pred_avg = FUNC(weighted_pred_avg, 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 = FUNC(sao_band_filter_0, depth); \ + hevcdsp->sao_edge_filter[0] = FUNC(sao_edge_filter_0, depth); \ + hevcdsp->sao_edge_filter[1] = FUNC(sao_edge_filter_1, depth); \ + \ + QPEL_FUNCS(depth); \ + QPEL_UNI_FUNCS(depth); \ + QPEL_BI_FUNCS(depth); \ + EPEL_FUNCS(depth); \ + EPEL_UNI_FUNCS(depth); \ + EPEL_BI_FUNCS(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); \ hevcdsp->hevc_h_loop_filter_chroma = FUNC(hevc_h_loop_filter_chroma, depth); \ @@ -174,7 +230,8 @@ void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth) hevcdsp->hevc_h_loop_filter_luma_c = FUNC(hevc_h_loop_filter_luma, depth); \ hevcdsp->hevc_v_loop_filter_luma_c = FUNC(hevc_v_loop_filter_luma, depth); \ hevcdsp->hevc_h_loop_filter_chroma_c = FUNC(hevc_h_loop_filter_chroma, depth); \ - hevcdsp->hevc_v_loop_filter_chroma_c = FUNC(hevc_v_loop_filter_chroma, depth); + hevcdsp->hevc_v_loop_filter_chroma_c = FUNC(hevc_v_loop_filter_chroma, depth) +int i = 0; switch (bit_depth) { case 9: @@ -183,8 +240,12 @@ void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth) case 10: HEVC_DSP(10); break; + case 12: + HEVC_DSP(12); + break; default: HEVC_DSP(8); break; } + if (ARCH_X86) ff_hevcdsp_init_x86(hevcdsp, bit_depth); } diff --git a/libavcodec/hevcdsp.h b/libavcodec/hevcdsp.h index 4dd3ebd1e..3b82fabff 100644 --- a/libavcodec/hevcdsp.h +++ b/libavcodec/hevcdsp.h @@ -2,6 +2,8 @@ * HEVC video decoder * * Copyright (C) 2012 - 2013 Guillaume Martres + * Copyright (C) 2013 - 2014 Pierre-Edouard Lepere + * * * This file is part of FFmpeg. * @@ -39,44 +41,60 @@ typedef struct SAOParams { } SAOParams; typedef struct HEVCDSPContext { - void (*put_pcm)(uint8_t *dst, ptrdiff_t stride, int size, - GetBitContext *gb, int pcm_bit_depth); + void (*put_pcm)(uint8_t *_dst, ptrdiff_t _stride, int width, int height, + struct GetBitContext *gb, int pcm_bit_depth); - void (*transquant_bypass[4])(uint8_t *dst, int16_t *coeffs, - ptrdiff_t stride); + void (*transform_add[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 (*transform_skip)(int16_t *coeffs, int16_t log2_size); - void (*sao_band_filter[4])(uint8_t *dst, uint8_t *src, ptrdiff_t stride, - struct SAOParams *sao, int *borders, - int width, int height, int c_idx); - void (*sao_edge_filter[4])(uint8_t *dst, uint8_t *src, ptrdiff_t stride, - struct SAOParams *sao, int *borders, int width, - int height, int c_idx, uint8_t vert_edge, - uint8_t horiz_edge, uint8_t diag_edge); + void (*transform_rdpcm)(int16_t *coeffs, int16_t log2_size, int mode); - 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 (*idct_4x4_luma)(int16_t *coeffs); - 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 (*idct[4])(int16_t *coeffs, int col_limit); + + void (*idct_dc[4])(int16_t *coeffs); + + void (*transform_dc_add[4])(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride); + + void (*sao_band_filter)(uint8_t *_dst, uint8_t *_src, ptrdiff_t _stride, + struct SAOParams *sao, int *borders, + int width, int height, int c_idx); + + void (*sao_edge_filter[2])(uint8_t *_dst, uint8_t *_src, ptrdiff_t _stride, + struct SAOParams *sao, int *borders, int _width, + int _height, int c_idx, uint8_t *vert_edge, + uint8_t *horiz_edge, uint8_t *diag_edge); + + void (*put_hevc_qpel[10][2][2])(int16_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int height, intptr_t mx, intptr_t my, int width); + void (*put_hevc_qpel_uni[10][2][2])(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int height, intptr_t mx, intptr_t my, int width); + void (*put_hevc_qpel_uni_w[10][2][2])(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width); + + void (*put_hevc_qpel_bi[10][2][2])(uint8_t *dst, ptrdiff_t dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, intptr_t mx, intptr_t my, int width); + void (*put_hevc_qpel_bi_w[10][2][2])(uint8_t *dst, ptrdiff_t dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, int denom, int wx0, int wx1, + int ox0, int ox1, intptr_t mx, intptr_t my, int width); + void (*put_hevc_epel[10][2][2])(int16_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int height, intptr_t mx, intptr_t my, int width); + + void (*put_hevc_epel_uni[10][2][2])(uint8_t *dst, ptrdiff_t dststride, uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width); + void (*put_hevc_epel_uni_w[10][2][2])(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width); + void (*put_hevc_epel_bi[10][2][2])(uint8_t *dst, ptrdiff_t dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, intptr_t mx, intptr_t my, int width); + void (*put_hevc_epel_bi_w[10][2][2])(uint8_t *dst, ptrdiff_t dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, int denom, int wx0, int ox0, int wx1, + int ox1, intptr_t mx, intptr_t my, int width); void (*hevc_h_loop_filter_luma)(uint8_t *pix, ptrdiff_t stride, int *beta, int *tc, @@ -104,6 +122,9 @@ typedef struct HEVCDSPContext { void ff_hevc_dsp_init(HEVCDSPContext *hpc, int bit_depth); -extern const int8_t ff_hevc_epel_filters[7][16]; +extern const int8_t ff_hevc_epel_filters[7][4]; +extern const int8_t ff_hevc_qpel_filters[3][16]; + +void ff_hevcdsp_init_x86(HEVCDSPContext *c, const int bit_depth); #endif /* AVCODEC_HEVCDSP_H */ diff --git a/libavcodec/hevcdsp_template.c b/libavcodec/hevcdsp_template.c index 8ceb093df..f0bb256b4 100644 --- a/libavcodec/hevcdsp_template.c +++ b/libavcodec/hevcdsp_template.c @@ -27,7 +27,7 @@ #include "hevcdsp.h" -static void FUNC(put_pcm)(uint8_t *_dst, ptrdiff_t stride, int size, +static void FUNC(put_pcm)(uint8_t *_dst, ptrdiff_t stride, int width, int height, GetBitContext *gb, int pcm_bit_depth) { int x, y; @@ -35,14 +35,14 @@ static void FUNC(put_pcm)(uint8_t *_dst, ptrdiff_t stride, int size, stride /= sizeof(pixel); - for (y = 0; y < size; y++) { - for (x = 0; x < size; x++) + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) dst[x] = get_bits(gb, pcm_bit_depth) << (BIT_DEPTH - pcm_bit_depth); dst += stride; } } -static void FUNC(transquant_bypass4x4)(uint8_t *_dst, int16_t *coeffs, +static void FUNC(transform_add4x4)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t stride) { int x, y; @@ -59,7 +59,7 @@ static void FUNC(transquant_bypass4x4)(uint8_t *_dst, int16_t *coeffs, } } -static void FUNC(transquant_bypass8x8)(uint8_t *_dst, int16_t *coeffs, +static void FUNC(transform_add8x8)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t stride) { int x, y; @@ -76,7 +76,7 @@ static void FUNC(transquant_bypass8x8)(uint8_t *_dst, int16_t *coeffs, } } -static void FUNC(transquant_bypass16x16)(uint8_t *_dst, int16_t *coeffs, +static void FUNC(transform_add16x16)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t stride) { int x, y; @@ -93,7 +93,7 @@ static void FUNC(transquant_bypass16x16)(uint8_t *_dst, int16_t *coeffs, } } -static void FUNC(transquant_bypass32x32)(uint8_t *_dst, int16_t *coeffs, +static void FUNC(transform_add32x32)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t stride) { int x, y; @@ -110,24 +110,52 @@ static void FUNC(transquant_bypass32x32)(uint8_t *_dst, int16_t *coeffs, } } -static void FUNC(transform_skip)(uint8_t *_dst, int16_t *coeffs, - ptrdiff_t stride) + +static void FUNC(transform_rdpcm)(int16_t *_coeffs, int16_t log2_size, int mode) { - pixel *dst = (pixel *)_dst; - int shift = 13 - BIT_DEPTH; -#if BIT_DEPTH <= 13 - int offset = 1 << (shift - 1); -#else - int offset = 0; -#endif + int16_t *coeffs = (int16_t *) _coeffs; int x, y; + int size = 1 << log2_size; - stride /= sizeof(pixel); + if (mode) { + coeffs += size; + for (y = 0; y < size - 1; y++) { + for (x = 0; x < size; x++) + coeffs[x] += coeffs[x - size]; + coeffs += size; + } + } else { + for (y = 0; y < size; y++) { + for (x = 1; x < size; x++) + coeffs[x] += coeffs[x - 1]; + coeffs += size; + } + } +} - 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; +static void FUNC(transform_skip)(int16_t *_coeffs, int16_t log2_size) +{ + int shift = 15 - BIT_DEPTH - log2_size; + int x, y; + int size = 1 << log2_size; + int16_t *coeffs = _coeffs; + + + if (shift > 0) { + int offset = 1 << (shift - 1); + for (y = 0; y < size; y++) { + for (x = 0; x < size; x++) { + *coeffs = (*coeffs + offset) >> shift; + coeffs++; + } + } + } else { + for (y = 0; y < size; y++) { + for (x = 0; x < size; x++) { + *coeffs = *coeffs << -shift; + coeffs++; + } + } } } @@ -151,17 +179,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++; @@ -170,643 +194,357 @@ 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) \ - do { \ - const int e0 = transform[8 * 0][0] * src[0 * sstep] + \ - transform[8 * 2][0] * src[2 * sstep]; \ - const int e1 = transform[8 * 0][1] * src[0 * sstep] + \ - transform[8 * 2][1] * src[2 * sstep]; \ - const int o0 = transform[8 * 1][0] * src[1 * sstep] + \ - transform[8 * 3][0] * src[3 * sstep]; \ - const int o1 = transform[8 * 1][1] * src[1 * sstep] + \ - transform[8 * 3][1] * src[3 * sstep]; \ - \ - assign(dst[0 * dstep], e0 + o0); \ - assign(dst[1 * dstep], e1 + o1); \ - assign(dst[2 * dstep], e1 - o1); \ - assign(dst[3 * dstep], e0 - o0); \ +#define TR_4(dst, src, dstep, sstep, assign, end) \ + do { \ + const int e0 = 64 * src[0 * sstep] + 64 * src[2 * sstep]; \ + const int e1 = 64 * src[0 * sstep] - 64 * src[2 * sstep]; \ + const int o0 = 83 * src[1 * sstep] + 36 * src[3 * sstep]; \ + const int o1 = 36 * src[1 * sstep] - 83 * src[3 * sstep]; \ + \ + assign(dst[0 * dstep], e0 + o0); \ + assign(dst[1 * dstep], e1 + o1); \ + assign(dst[2 * dstep], e1 - o1); \ + 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) \ - 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) \ - o_8[i] += transform[4 * j][i] * src[j * sstep]; \ - TR_4(e_8, src, 1, 2 * sstep, SET); \ - \ - for (i = 0; i < 4; i++) { \ - assign(dst[i * dstep], e_8[i] + o_8[i]); \ - assign(dst[(7 - i) * dstep], e_8[i] - o_8[i]); \ - } \ +#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 < end; j += 2) \ + o_8[i] += transform[4 * j][i] * src[j * sstep]; \ + 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]); \ + assign(dst[(7 - i) * dstep], e_8[i] - o_8[i]); \ + } \ } while (0) -#define TR_16(dst, src, dstep, sstep, assign) \ - 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) \ - o_16[i] += transform[2 * j][i] * src[j * sstep]; \ - TR_8(e_16, src, 1, 2 * sstep, SET); \ - \ - for (i = 0; i < 8; i++) { \ - assign(dst[i * dstep], e_16[i] + o_16[i]); \ - assign(dst[(15 - i) * dstep], e_16[i] - o_16[i]); \ - } \ +#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 < end; j += 2) \ + o_16[i] += transform[2 * j][i] * src[j * sstep]; \ + 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]); \ + assign(dst[(15 - i) * dstep], e_16[i] - o_16[i]); \ + } \ } while (0) -#define TR_32(dst, src, dstep, sstep, assign) \ - 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) \ - o_32[i] += transform[j][i] * src[j * sstep]; \ - TR_16(e_32, src, 1, 2 * sstep, SET); \ - \ - for (i = 0; i < 16; i++) { \ - assign(dst[i * dstep], e_32[i] + o_32[i]); \ - assign(dst[(31 - i) * dstep], e_32[i] - o_32[i]); \ - } \ +#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 < end; j += 2) \ + o_32[i] += transform[j][i] * src[j * sstep]; \ + 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]); \ + assign(dst[(31 - i) * dstep], e_32[i] - o_32[i]); \ + } \ } while (0) +#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) - -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(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; +IDCT( 4) +IDCT( 8) +IDCT(16) +IDCT(32) - stride /= sizeof(pixel); +IDCT_DC( 4) +IDCT_DC( 8) +IDCT_DC(16) +IDCT_DC(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; - } -} - -static void FUNC(sao_band_filter)(uint8_t *_dst, uint8_t *_src, - ptrdiff_t stride, SAOParams *sao, - int *borders, int width, int height, - int c_idx, int class) -{ - pixel *dst = (pixel *)_dst; - pixel *src = (pixel *)_src; - int offset_table[32] = { 0 }; - int k, y, x; - int chroma = !!c_idx; - int shift = BIT_DEPTH - 5; - int *sao_offset_val = sao->offset_val[c_idx]; - int sao_left_class = sao->band_position[c_idx]; - int init_y = 0, init_x = 0; - - stride /= sizeof(pixel); - - switch (class) { - case 0: - if (!borders[2]) - width -= (8 >> chroma) + 2; - if (!borders[3]) - height -= (4 >> chroma) + 2; - break; - case 1: - init_y = -(4 >> chroma) - 2; - if (!borders[2]) - width -= (8 >> chroma) + 2; - height = (4 >> chroma) + 2; - break; - case 2: - init_x = -(8 >> chroma) - 2; - width = (8 >> chroma) + 2; - if (!borders[3]) - height -= (4 >> chroma) + 2; - break; - case 3: - init_y = -(4 >> chroma) - 2; - init_x = -(8 >> chroma) - 2; - width = (8 >> chroma) + 2; - height = (4 >> chroma) + 2; - break; - } - - dst = dst + (init_y * stride + init_x); - src = src + (init_y * stride + init_x); - for (k = 0; k < 4; k++) - offset_table[(k + sao_left_class) & 31] = sao_offset_val[k + 1]; - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) - dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); - dst += stride; - src += stride; - } -} - -static void FUNC(sao_band_filter_0)(uint8_t *dst, uint8_t *src, - ptrdiff_t stride, SAOParams *sao, - int *borders, int width, int height, - int c_idx) -{ - FUNC(sao_band_filter)(dst, src, stride, sao, borders, - width, height, c_idx, 0); -} - -static void FUNC(sao_band_filter_1)(uint8_t *dst, uint8_t *src, - ptrdiff_t stride, SAOParams *sao, - int *borders, int width, int height, - int c_idx) -{ - FUNC(sao_band_filter)(dst, src, stride, sao, borders, - width, height, c_idx, 1); -} - -static void FUNC(sao_band_filter_2)(uint8_t *dst, uint8_t *src, - ptrdiff_t stride, SAOParams *sao, - int *borders, int width, int height, - int c_idx) -{ - FUNC(sao_band_filter)(dst, src, stride, sao, borders, - width, height, c_idx, 2); -} - -static void FUNC(sao_band_filter_3)(uint8_t *_dst, uint8_t *_src, - ptrdiff_t stride, SAOParams *sao, - int *borders, int width, int height, - int c_idx) -{ - FUNC(sao_band_filter)(_dst, _src, stride, sao, borders, - width, height, c_idx, 3); -} - -static void FUNC(sao_edge_filter_0)(uint8_t *_dst, uint8_t *_src, - ptrdiff_t stride, SAOParams *sao, - int *borders, int _width, int _height, - int c_idx, uint8_t vert_edge, - uint8_t horiz_edge, uint8_t diag_edge) -{ - int x, y; - pixel *dst = (pixel *)_dst; - pixel *src = (pixel *)_src; - int chroma = !!c_idx; - int *sao_offset_val = sao->offset_val[c_idx]; - int sao_eo_class = sao->eo_class[c_idx]; - int init_x = 0, init_y = 0, width = _width, height = _height; - - static const int8_t pos[4][2][2] = { - { { -1, 0 }, { 1, 0 } }, // horizontal - { { 0, -1 }, { 0, 1 } }, // vertical - { { -1, -1 }, { 1, 1 } }, // 45 degree - { { 1, -1 }, { -1, 1 } }, // 135 degree - }; - static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 }; - -#define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1)) - - stride /= sizeof(pixel); - - if (!borders[2]) - width -= (8 >> chroma) + 2; - if (!borders[3]) - height -= (4 >> chroma) + 2; - - dst = dst + (init_y * stride + init_x); - src = src + (init_y * stride + init_x); - init_y = init_x = 0; - if (sao_eo_class != SAO_EO_VERT) { - if (borders[0]) { - int offset_val = sao_offset_val[0]; - int y_stride = 0; - for (y = 0; y < height; y++) { - dst[y_stride] = av_clip_pixel(src[y_stride] + offset_val); - y_stride += stride; - } - init_x = 1; - } - if (borders[2]) { - int offset_val = sao_offset_val[0]; - int x_stride = width - 1; - for (x = 0; x < height; x++) { - dst[x_stride] = av_clip_pixel(src[x_stride] + offset_val); - x_stride += stride; - } - width--; - } - } - if (sao_eo_class != SAO_EO_HORIZ) { - if (borders[1]) { - int offset_val = sao_offset_val[0]; - for (x = init_x; x < width; x++) - dst[x] = av_clip_pixel(src[x] + offset_val); - init_y = 1; - } - if (borders[3]) { - int offset_val = sao_offset_val[0]; - int y_stride = stride * (height - 1); - for (x = init_x; x < width; x++) - dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + offset_val); - height--; - } - } - { - int y_stride = init_y * stride; - int pos_0_0 = pos[sao_eo_class][0][0]; - int pos_0_1 = pos[sao_eo_class][0][1]; - int pos_1_0 = pos[sao_eo_class][1][0]; - int pos_1_1 = pos[sao_eo_class][1][1]; - - int y_stride_0_1 = (init_y + pos_0_1) * stride; - int y_stride_1_1 = (init_y + pos_1_1) * stride; - for (y = init_y; y < height; y++) { - for (x = init_x; x < width; x++) { - int diff0 = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]); - int diff1 = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]); - int offset_val = edge_idx[2 + diff0 + diff1]; - dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]); - } - y_stride += stride; - y_stride_0_1 += stride; - y_stride_1_1 += stride; - } - } - - { - // Restore pixels that can't be modified - int save_upper_left = !diag_edge && sao_eo_class == SAO_EO_135D && !borders[0] && !borders[1]; - if (vert_edge && sao_eo_class != SAO_EO_VERT) - for (y = init_y+save_upper_left; y< height; y++) - dst[y*stride] = src[y*stride]; - if(horiz_edge && sao_eo_class != SAO_EO_HORIZ) - for(x = init_x+save_upper_left; xoffset_val[c_idx]; - int sao_eo_class = sao->eo_class[c_idx]; - int init_x = 0, init_y = 0, width = _width, height = _height; - - static const int8_t pos[4][2][2] = { - { { -1, 0 }, { 1, 0 } }, // horizontal - { { 0, -1 }, { 0, 1 } }, // vertical - { { -1, -1 }, { 1, 1 } }, // 45 degree - { { 1, -1 }, { -1, 1 } }, // 135 degree - }; - static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 }; - -#define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1)) - - stride /= sizeof(pixel); - - init_y = -(4 >> chroma) - 2; - if (!borders[2]) - width -= (8 >> chroma) + 2; - height = (4 >> chroma) + 2; - - dst = dst + (init_y * stride + init_x); - src = src + (init_y * stride + init_x); - init_y = init_x = 0; - if (sao_eo_class != SAO_EO_VERT) { - if (borders[0]) { - int offset_val = sao_offset_val[0]; - int y_stride = 0; - for (y = 0; y < height; y++) { - dst[y_stride] = av_clip_pixel(src[y_stride] + offset_val); - y_stride += stride; - } - init_x = 1; - } - if (borders[2]) { - int offset_val = sao_offset_val[0]; - int x_stride = width - 1; - for (x = 0; x < height; x++) { - dst[x_stride] = av_clip_pixel(src[x_stride] + offset_val); - x_stride += stride; - } - width--; - } - } - { - int y_stride = init_y * stride; - int pos_0_0 = pos[sao_eo_class][0][0]; - int pos_0_1 = pos[sao_eo_class][0][1]; - int pos_1_0 = pos[sao_eo_class][1][0]; - int pos_1_1 = pos[sao_eo_class][1][1]; - - int y_stride_0_1 = (init_y + pos_0_1) * stride; - int y_stride_1_1 = (init_y + pos_1_1) * stride; - for (y = init_y; y < height; y++) { - for (x = init_x; x < width; x++) { - int diff0 = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]); - int diff1 = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]); - int offset_val = edge_idx[2 + diff0 + diff1]; - dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]); - } - y_stride += stride; - y_stride_0_1 += stride; - y_stride_1_1 += stride; - } - } - - { - // Restore pixels that can't be modified - int save_lower_left = !diag_edge && sao_eo_class == SAO_EO_45D && !borders[0]; - if(vert_edge && sao_eo_class != SAO_EO_VERT) - for(y = init_y; y< height-save_lower_left; y++) - dst[y*stride] = src[y*stride]; - if(horiz_edge && sao_eo_class != SAO_EO_HORIZ) - for(x = init_x+save_lower_left; xoffset_val[c_idx]; - int sao_eo_class = sao->eo_class[c_idx]; - int init_x = 0, init_y = 0, width = _width, height = _height; - - static const int8_t pos[4][2][2] = { - { { -1, 0 }, { 1, 0 } }, // horizontal - { { 0, -1 }, { 0, 1 } }, // vertical - { { -1, -1 }, { 1, 1 } }, // 45 degree - { { 1, -1 }, { -1, 1 } }, // 135 degree - }; - static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 }; - -#define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1)) - - stride /= sizeof(pixel); - - init_x = -(8 >> chroma) - 2; - width = (8 >> chroma) + 2; - if (!borders[3]) - height -= (4 >> chroma) + 2; - - dst = dst + (init_y * stride + init_x); - src = src + (init_y * stride + init_x); - init_y = init_x = 0; - if (sao_eo_class != SAO_EO_HORIZ) { - if (borders[1]) { - int offset_val = sao_offset_val[0]; - for (x = init_x; x < width; x++) - dst[x] = av_clip_pixel(src[x] + offset_val); - init_y = 1; - } - if (borders[3]) { - int offset_val = sao_offset_val[0]; - int y_stride = stride * (height - 1); - for (x = init_x; x < width; x++) - dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + offset_val); - height--; - } - } - { - int y_stride = init_y * stride; - int pos_0_0 = pos[sao_eo_class][0][0]; - int pos_0_1 = pos[sao_eo_class][0][1]; - int pos_1_0 = pos[sao_eo_class][1][0]; - int pos_1_1 = pos[sao_eo_class][1][1]; - - int y_stride_0_1 = (init_y + pos_0_1) * stride; - int y_stride_1_1 = (init_y + pos_1_1) * stride; - for (y = init_y; y < height; y++) { - for (x = init_x; x < width; x++) { - int diff0 = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]); - int diff1 = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]); - int offset_val = edge_idx[2 + diff0 + diff1]; - dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]); - } - y_stride += stride; - y_stride_0_1 += stride; - y_stride_1_1 += stride; - } - } - - { - // Restore pixels that can't be modified - int save_upper_right = !diag_edge && sao_eo_class == SAO_EO_45D && !borders[1]; - if(vert_edge && sao_eo_class != SAO_EO_VERT) - for(y = init_y+save_upper_right; y< height; y++) - dst[y*stride+width-1] = src[y*stride+width-1]; - if(horiz_edge && sao_eo_class != SAO_EO_HORIZ) - for(x = init_x; xoffset_val[c_idx]; - int sao_eo_class = sao->eo_class[c_idx]; - int init_x = 0, init_y = 0, width = _width, height = _height; - - static const int8_t pos[4][2][2] = { - { { -1, 0 }, { 1, 0 } }, // horizontal - { { 0, -1 }, { 0, 1 } }, // vertical - { { -1, -1 }, { 1, 1 } }, // 45 degree - { { 1, -1 }, { -1, 1 } }, // 135 degree - }; - static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 }; - -#define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1)) - - stride /= sizeof(pixel); - - init_y = -(4 >> chroma) - 2; - init_x = -(8 >> chroma) - 2; - width = (8 >> chroma) + 2; - height = (4 >> chroma) + 2; - - - dst = dst + (init_y * stride + init_x); - src = src + (init_y * stride + init_x); - init_y = init_x = 0; - - { - int y_stride = init_y * stride; - int pos_0_0 = pos[sao_eo_class][0][0]; - int pos_0_1 = pos[sao_eo_class][0][1]; - int pos_1_0 = pos[sao_eo_class][1][0]; - int pos_1_1 = pos[sao_eo_class][1][1]; - - int y_stride_0_1 = (init_y + pos_0_1) * stride; - int y_stride_1_1 = (init_y + pos_1_1) * stride; - - for (y = init_y; y < height; y++) { - for (x = init_x; x < width; x++) { - int diff0 = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]); - int diff1 = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]); - int offset_val = edge_idx[2 + diff0 + diff1]; - dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]); - } - y_stride += stride; - y_stride_0_1 += stride; - y_stride_1_1 += stride; - } - } - - { - // Restore pixels that can't be modified - int save_lower_right = !diag_edge && sao_eo_class == SAO_EO_135D; - if(vert_edge && sao_eo_class != SAO_EO_VERT) - for(y = init_y; y< height-save_lower_right; y++) - dst[y*stride+width-1] = src[y*stride+width-1]; - if(horiz_edge && sao_eo_class != SAO_EO_HORIZ) - for(x = init_x; xoffset_val[c_idx]; + int sao_left_class = sao->band_position[c_idx]; + + stride /= sizeof(pixel); + + for (k = 0; k < 4; k++) + offset_table[(k + sao_left_class) & 31] = sao_offset_val[k + 1]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(src[x] + offset_table[av_clip_pixel(src[x] >> shift)]); + dst += stride; + src += stride; + } +} + +#define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1)) + +static void FUNC(sao_edge_filter)(uint8_t *_dst, uint8_t *_src, + ptrdiff_t stride, SAOParams *sao, + int width, int height, + int c_idx, int init_x, int init_y) { + + static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 }; + static const int8_t pos[4][2][2] = { + { { -1, 0 }, { 1, 0 } }, // horizontal + { { 0, -1 }, { 0, 1 } }, // vertical + { { -1, -1 }, { 1, 1 } }, // 45 degree + { { 1, -1 }, { -1, 1 } }, // 135 degree + }; + int *sao_offset_val = sao->offset_val[c_idx]; + int sao_eo_class = sao->eo_class[c_idx]; + pixel *dst = (pixel *)_dst; + pixel *src = (pixel *)_src; + + int y_stride = init_y * stride; + int pos_0_0 = pos[sao_eo_class][0][0]; + int pos_0_1 = pos[sao_eo_class][0][1]; + int pos_1_0 = pos[sao_eo_class][1][0]; + int pos_1_1 = pos[sao_eo_class][1][1]; + int x, y; + + int y_stride_0_1 = (init_y + pos_0_1) * stride; + int y_stride_1_1 = (init_y + pos_1_1) * stride; + for (y = init_y; y < height; y++) { + for (x = init_x; x < width; x++) { + int diff0 = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]); + int diff1 = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]); + int offset_val = edge_idx[2 + diff0 + diff1]; + dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]); + } + y_stride += stride; + y_stride_0_1 += stride; + y_stride_1_1 += stride; + } +} + +static void FUNC(sao_edge_filter_0)(uint8_t *_dst, uint8_t *_src, + ptrdiff_t stride, SAOParams *sao, + int *borders, int _width, int _height, + int c_idx, uint8_t *vert_edge, + uint8_t *horiz_edge, uint8_t *diag_edge) +{ + int x, y; + pixel *dst = (pixel *)_dst; + pixel *src = (pixel *)_src; + int *sao_offset_val = sao->offset_val[c_idx]; + int sao_eo_class = sao->eo_class[c_idx]; + int init_x = 0, init_y = 0, width = _width, height = _height; + + stride /= sizeof(pixel); + + if (sao_eo_class != SAO_EO_VERT) { + if (borders[0]) { + int offset_val = sao_offset_val[0]; + int y_stride = 0; + for (y = 0; y < height; y++) { + dst[y_stride] = av_clip_pixel(src[y_stride] + offset_val); + y_stride += stride; + } + init_x = 1; + } + if (borders[2]) { + int offset_val = sao_offset_val[0]; + int x_stride = width - 1; + for (x = 0; x < height; x++) { + dst[x_stride] = av_clip_pixel(src[x_stride] + offset_val); + x_stride += stride; + } + width--; + } + } + if (sao_eo_class != SAO_EO_HORIZ) { + if (borders[1]) { + int offset_val = sao_offset_val[0]; + for (x = init_x; x < width; x++) + dst[x] = av_clip_pixel(src[x] + offset_val); + init_y = 1; + } + if (borders[3]) { + int offset_val = sao_offset_val[0]; + int y_stride = stride * (height - 1); + for (x = init_x; x < width; x++) + dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + offset_val); + height--; + } + } + + FUNC(sao_edge_filter)((uint8_t *)dst, (uint8_t *)src, stride, sao, width, height, c_idx, init_x, init_y); +} + +static void FUNC(sao_edge_filter_1)(uint8_t *_dst, uint8_t *_src, + ptrdiff_t stride, SAOParams *sao, + int *borders, int _width, int _height, + int c_idx, uint8_t *vert_edge, + uint8_t *horiz_edge, uint8_t *diag_edge) +{ + int x, y; + pixel *dst = (pixel *)_dst; + pixel *src = (pixel *)_src; + int *sao_offset_val = sao->offset_val[c_idx]; + int sao_eo_class = sao->eo_class[c_idx]; + int init_x = 0, init_y = 0, width = _width, height = _height; + + stride /= sizeof(pixel); + + if (sao_eo_class != SAO_EO_VERT) { + if (borders[0]) { + int offset_val = sao_offset_val[0]; + int y_stride = 0; + for (y = 0; y < height; y++) { + dst[y_stride] = av_clip_pixel(src[y_stride] + offset_val); + y_stride += stride; + } + init_x = 1; + } + if (borders[2]) { + int offset_val = sao_offset_val[0]; + int x_stride = width - 1; + for (x = 0; x < height; x++) { + dst[x_stride] = av_clip_pixel(src[x_stride] + offset_val); + x_stride += stride; + } + width--; + } + } + if (sao_eo_class != SAO_EO_HORIZ) { + if (borders[1]) { + int offset_val = sao_offset_val[0]; + for (x = init_x; x < width; x++) + dst[x] = av_clip_pixel(src[x] + offset_val); + init_y = 1; + } + if (borders[3]) { + int offset_val = sao_offset_val[0]; + int y_stride = stride * (height - 1); + for (x = init_x; x < width; x++) + dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + offset_val); + height--; + } + } + + FUNC(sao_edge_filter)((uint8_t *)dst, (uint8_t *)src, stride, sao, width, height, c_idx, init_x, init_y); + + { + int save_upper_left = !diag_edge[0] && sao_eo_class == SAO_EO_135D && !borders[0] && !borders[1]; + int save_upper_right = !diag_edge[1] && sao_eo_class == SAO_EO_45D && !borders[1] && !borders[2]; + int save_lower_right = !diag_edge[2] && sao_eo_class == SAO_EO_135D && !borders[2] && !borders[3]; + int save_lower_left = !diag_edge[3] && sao_eo_class == SAO_EO_45D && !borders[0] && !borders[3]; + + // Restore pixels that can't be modified + if(vert_edge[0] && sao_eo_class != SAO_EO_VERT) { + for(y = init_y+save_upper_left; y< height-save_lower_left; y++) + dst[y*stride] = src[y*stride]; + } + if(vert_edge[1] && sao_eo_class != SAO_EO_VERT) { + for(y = init_y+save_upper_right; y< height-save_lower_right; y++) + dst[y*stride+width-1] = src[y*stride+width-1]; + } + + if(horiz_edge[0] && sao_eo_class != SAO_EO_HORIZ) { + for(x = init_x+save_upper_left; x < width-save_upper_right; x++) + dst[x] = src[x]; + } + if(horiz_edge[1] && sao_eo_class != SAO_EO_HORIZ) { + for(x = init_x+save_lower_left; x < width-save_lower_right; x++) + dst[(height-1)*stride+x] = src[(height-1)*stride+x]; + } + if(diag_edge[0] && sao_eo_class == SAO_EO_135D) + dst[0] = src[0]; + if(diag_edge[1] && sao_eo_class == SAO_EO_45D) + dst[width-1] = src[width-1]; + if(diag_edge[2] && sao_eo_class == SAO_EO_135D) + dst[stride*(height-1)+width-1] = src[stride*(height-1)+width-1]; + if(diag_edge[3] && sao_eo_class == SAO_EO_45D) + dst[stride*(height-1)] = src[stride*(height-1)]; + + } +} + +#undef CMP + +//////////////////////////////////////////////////////////////////////////////// +// +//////////////////////////////////////////////////////////////////////////////// +static void FUNC(put_hevc_pel_pixels)(int16_t *dst, ptrdiff_t dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width) { int x, y; pixel *src = (pixel *)_src; @@ -820,157 +558,573 @@ static void FUNC(put_hevc_qpel_pixels)(int16_t *dst, ptrdiff_t dststride, } } -#define QPEL_FILTER_1(src, stride) \ - (1 * -src[x - 3 * stride] + \ - 4 * src[x - 2 * stride] - \ - 10 * src[x - stride] + \ - 58 * src[x] + \ - 17 * src[x + stride] - \ - 5 * src[x + 2 * stride] + \ - 1 * src[x + 3 * stride]) - -#define QPEL_FILTER_2(src, stride) \ - (1 * -src[x - 3 * stride] + \ - 4 * src[x - 2 * stride] - \ - 11 * src[x - stride] + \ - 40 * src[x] + \ - 40 * src[x + stride] - \ - 11 * src[x + 2 * stride] + \ - 4 * src[x + 3 * stride] - \ - 1 * src[x + 4 * stride]) - -#define QPEL_FILTER_3(src, stride) \ - (1 * src[x - 2 * stride] - \ - 5 * src[x - stride] + \ - 17 * src[x] + \ - 58 * src[x + stride] - \ - 10 * src[x + 2 * stride] + \ - 4 * src[x + 3 * stride] - \ - 1 * src[x + 4 * stride]) - - -#define PUT_HEVC_QPEL_H(H) \ -static void FUNC(put_hevc_qpel_h ## H)(int16_t *dst, ptrdiff_t dststride, \ - uint8_t *_src, ptrdiff_t _srcstride, \ - int width, int height, \ - int16_t* mcbuffer) \ -{ \ - int x, y; \ - pixel *src = (pixel*)_src; \ - ptrdiff_t srcstride = _srcstride / sizeof(pixel); \ - \ - for (y = 0; y < height; y++) { \ - for (x = 0; x < width; x++) \ - dst[x] = QPEL_FILTER_ ## H(src, 1) >> (BIT_DEPTH - 8); \ - src += srcstride; \ - dst += dststride; \ - } \ -} - -#define PUT_HEVC_QPEL_V(V) \ -static void FUNC(put_hevc_qpel_v ## V)(int16_t *dst, ptrdiff_t dststride, \ - uint8_t *_src, ptrdiff_t _srcstride, \ - int width, int height, \ - int16_t* mcbuffer) \ -{ \ - int x, y; \ - pixel *src = (pixel*)_src; \ - ptrdiff_t srcstride = _srcstride / sizeof(pixel); \ - \ - for (y = 0; y < height; y++) { \ - for (x = 0; x < width; x++) \ - dst[x] = QPEL_FILTER_ ## V(src, srcstride) >> (BIT_DEPTH - 8); \ - src += srcstride; \ - dst += dststride; \ - } \ -} - -#define PUT_HEVC_QPEL_HV(H, V) \ -static void FUNC(put_hevc_qpel_h ## H ## v ## V)(int16_t *dst, \ - ptrdiff_t dststride, \ - uint8_t *_src, \ - ptrdiff_t _srcstride, \ - int width, int height, \ - int16_t* mcbuffer) \ -{ \ - int x, y; \ - pixel *src = (pixel*)_src; \ - ptrdiff_t srcstride = _srcstride / sizeof(pixel); \ - \ - int16_t tmp_array[(MAX_PB_SIZE + 7) * MAX_PB_SIZE]; \ - int16_t *tmp = tmp_array; \ - \ - src -= ff_hevc_qpel_extra_before[V] * srcstride; \ - \ - for (y = 0; y < height + ff_hevc_qpel_extra[V]; y++) { \ - for (x = 0; x < width; x++) \ - tmp[x] = QPEL_FILTER_ ## H(src, 1) >> (BIT_DEPTH - 8); \ - src += srcstride; \ - tmp += MAX_PB_SIZE; \ - } \ - \ - tmp = tmp_array + ff_hevc_qpel_extra_before[V] * MAX_PB_SIZE; \ - \ - for (y = 0; y < height; y++) { \ - for (x = 0; x < width; x++) \ - dst[x] = QPEL_FILTER_ ## V(tmp, MAX_PB_SIZE) >> 6; \ - tmp += MAX_PB_SIZE; \ - dst += dststride; \ - } \ -} - -PUT_HEVC_QPEL_H(1) -PUT_HEVC_QPEL_H(2) -PUT_HEVC_QPEL_H(3) -PUT_HEVC_QPEL_V(1) -PUT_HEVC_QPEL_V(2) -PUT_HEVC_QPEL_V(3) -PUT_HEVC_QPEL_HV(1, 1) -PUT_HEVC_QPEL_HV(1, 2) -PUT_HEVC_QPEL_HV(1, 3) -PUT_HEVC_QPEL_HV(2, 1) -PUT_HEVC_QPEL_HV(2, 2) -PUT_HEVC_QPEL_HV(2, 3) -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) +static void FUNC(put_hevc_pel_uni_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width) { - int x, y; + int y; pixel *src = (pixel *)_src; ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) - dst[x] = src[x] << (14 - BIT_DEPTH); + memcpy(dst, src, width * sizeof(pixel)); src += srcstride; dst += dststride; } } -#define EPEL_FILTER(src, stride) \ - (filter_0 * src[x - stride] + \ - filter_1 * src[x] + \ - filter_2 * src[x + stride] + \ - filter_3 * src[x + 2 * stride]) +static void FUNC(put_hevc_pel_bi_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + + int shift = 14 + 1 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((src[x] << (14 - BIT_DEPTH)) + src2[x] + offset) >> shift); + src += srcstride; + dst += dststride; + src2 += src2stride; + } +} + +static void FUNC(put_hevc_pel_uni_w_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + int shift = denom + 14 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + ox = ox * (1 << (BIT_DEPTH - 8)); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel((((src[x] << (14 - BIT_DEPTH)) * wx + offset) >> shift) + ox); + src += srcstride; + dst += dststride; + } +} + +static void FUNC(put_hevc_pel_bi_w_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, int denom, int wx0, int wx1, + int ox0, int ox1, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + + int shift = 14 + 1 - BIT_DEPTH; + int log2Wd = denom + shift - 1; + + ox0 = ox0 * (1 << (BIT_DEPTH - 8)); + ox1 = ox1 * (1 << (BIT_DEPTH - 8)); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + dst[x] = av_clip_pixel(( (src[x] << (14 - BIT_DEPTH)) * wx1 + src2[x] * wx0 + ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); + } + src += srcstride; + dst += dststride; + src2 += src2stride; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +//////////////////////////////////////////////////////////////////////////////// +#define QPEL_FILTER(src, stride) \ + (filter[0] * src[x - 3 * stride] + \ + filter[1] * src[x - 2 * stride] + \ + filter[2] * src[x - stride] + \ + filter[3] * src[x ] + \ + filter[4] * src[x + stride] + \ + filter[5] * src[x + 2 * stride] + \ + filter[6] * src[x + 3 * stride] + \ + filter[7] * src[x + 4 * stride]) + +static void FUNC(put_hevc_qpel_h)(int16_t *dst, ptrdiff_t dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + const int8_t *filter = ff_hevc_qpel_filters[mx - 1]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); + src += srcstride; + dst += dststride; + } +} + +static void FUNC(put_hevc_qpel_v)(int16_t *dst, ptrdiff_t dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + const int8_t *filter = ff_hevc_qpel_filters[my - 1]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8); + src += srcstride; + dst += dststride; + } +} + +static void FUNC(put_hevc_qpel_hv)(int16_t *dst, + ptrdiff_t dststride, + uint8_t *_src, + ptrdiff_t _srcstride, + int height, intptr_t mx, + intptr_t my, int width) +{ + int x, y; + const int8_t *filter; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE]; + int16_t *tmp = tmp_array; + + src -= QPEL_EXTRA_BEFORE * srcstride; + filter = ff_hevc_qpel_filters[mx - 1]; + for (y = 0; y < height + QPEL_EXTRA; y++) { + for (x = 0; x < width; x++) + tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); + src += srcstride; + tmp += MAX_PB_SIZE; + } + + tmp = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE; + filter = ff_hevc_qpel_filters[my - 1]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6; + tmp += MAX_PB_SIZE; + dst += dststride; + } +} + +static void FUNC(put_hevc_qpel_uni_h)(uint8_t *_dst, ptrdiff_t _dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_qpel_filters[mx - 1]; + int shift = 14 - BIT_DEPTH; + +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) + offset) >> shift); + src += srcstride; + dst += dststride; + } +} + +static void FUNC(put_hevc_qpel_bi_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + + const int8_t *filter = ff_hevc_qpel_filters[mx - 1]; + + int shift = 14 + 1 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) + src2[x] + offset) >> shift); + src += srcstride; + dst += dststride; + src2 += src2stride; + } +} + +static void FUNC(put_hevc_qpel_uni_v)(uint8_t *_dst, ptrdiff_t _dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_qpel_filters[my - 1]; + int shift = 14 - BIT_DEPTH; + +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) + offset) >> shift); + src += srcstride; + dst += dststride; + } +} + + +static void FUNC(put_hevc_qpel_bi_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + + const int8_t *filter = ff_hevc_qpel_filters[my - 1]; + + int shift = 14 + 1 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) + src2[x] + offset) >> shift); + src += srcstride; + dst += dststride; + src2 += src2stride; + } +} + +static void FUNC(put_hevc_qpel_uni_hv)(uint8_t *_dst, ptrdiff_t _dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width) +{ + int x, y; + const int8_t *filter; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE]; + int16_t *tmp = tmp_array; + int shift = 14 - BIT_DEPTH; + +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + src -= QPEL_EXTRA_BEFORE * srcstride; + filter = ff_hevc_qpel_filters[mx - 1]; + for (y = 0; y < height + QPEL_EXTRA; y++) { + for (x = 0; x < width; x++) + tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); + src += srcstride; + tmp += MAX_PB_SIZE; + } + + tmp = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE; + filter = ff_hevc_qpel_filters[my - 1]; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) + offset) >> shift); + tmp += MAX_PB_SIZE; + dst += dststride; + } +} + +static void FUNC(put_hevc_qpel_bi_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, intptr_t mx, intptr_t my, int width) +{ + int x, y; + const int8_t *filter; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE]; + int16_t *tmp = tmp_array; + int shift = 14 + 1 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + src -= QPEL_EXTRA_BEFORE * srcstride; + filter = ff_hevc_qpel_filters[mx - 1]; + for (y = 0; y < height + QPEL_EXTRA; y++) { + for (x = 0; x < width; x++) + tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); + src += srcstride; + tmp += MAX_PB_SIZE; + } + + tmp = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE; + filter = ff_hevc_qpel_filters[my - 1]; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) + src2[x] + offset) >> shift); + tmp += MAX_PB_SIZE; + dst += dststride; + src2 += src2stride; + } +} + +static void FUNC(put_hevc_qpel_uni_w_h)(uint8_t *_dst, ptrdiff_t _dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, + intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_qpel_filters[mx - 1]; + int shift = denom + 14 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + ox = ox * (1 << (BIT_DEPTH - 8)); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel((((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx + offset) >> shift) + ox); + src += srcstride; + dst += dststride; + } +} + +static void FUNC(put_hevc_qpel_bi_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, int denom, int wx0, int wx1, + int ox0, int ox1, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + + const int8_t *filter = ff_hevc_qpel_filters[mx - 1]; + + int shift = 14 + 1 - BIT_DEPTH; + int log2Wd = denom + shift - 1; + + ox0 = ox0 * (1 << (BIT_DEPTH - 8)); + ox1 = ox1 * (1 << (BIT_DEPTH - 8)); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 + + ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); + src += srcstride; + dst += dststride; + src2 += src2stride; + } +} + +static void FUNC(put_hevc_qpel_uni_w_v)(uint8_t *_dst, ptrdiff_t _dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, + intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_qpel_filters[my - 1]; + int shift = denom + 14 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + ox = ox * (1 << (BIT_DEPTH - 8)); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel((((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx + offset) >> shift) + ox); + src += srcstride; + dst += dststride; + } +} + +static void FUNC(put_hevc_qpel_bi_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, int denom, int wx0, int wx1, + int ox0, int ox1, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + + const int8_t *filter = ff_hevc_qpel_filters[my - 1]; + + int shift = 14 + 1 - BIT_DEPTH; + int log2Wd = denom + shift - 1; + + ox0 = ox0 * (1 << (BIT_DEPTH - 8)); + ox1 = ox1 * (1 << (BIT_DEPTH - 8)); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 + + ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); + src += srcstride; + dst += dststride; + src2 += src2stride; + } +} + +static void FUNC(put_hevc_qpel_uni_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, + intptr_t mx, intptr_t my, int width) +{ + int x, y; + const int8_t *filter; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE]; + int16_t *tmp = tmp_array; + int shift = denom + 14 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + src -= QPEL_EXTRA_BEFORE * srcstride; + filter = ff_hevc_qpel_filters[mx - 1]; + for (y = 0; y < height + QPEL_EXTRA; y++) { + for (x = 0; x < width; x++) + tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); + src += srcstride; + tmp += MAX_PB_SIZE; + } + + tmp = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE; + filter = ff_hevc_qpel_filters[my - 1]; + + ox = ox * (1 << (BIT_DEPTH - 8)); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel((((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx + offset) >> shift) + ox); + tmp += MAX_PB_SIZE; + dst += dststride; + } +} + +static void FUNC(put_hevc_qpel_bi_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, int denom, int wx0, int wx1, + int ox0, int ox1, intptr_t mx, intptr_t my, int width) +{ + int x, y; + const int8_t *filter; + pixel *src = (pixel*)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE]; + int16_t *tmp = tmp_array; + int shift = 14 + 1 - BIT_DEPTH; + int log2Wd = denom + shift - 1; + + src -= QPEL_EXTRA_BEFORE * srcstride; + filter = ff_hevc_qpel_filters[mx - 1]; + for (y = 0; y < height + QPEL_EXTRA; y++) { + for (x = 0; x < width; x++) + tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); + src += srcstride; + tmp += MAX_PB_SIZE; + } + + tmp = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE; + filter = ff_hevc_qpel_filters[my - 1]; + + ox0 = ox0 * (1 << (BIT_DEPTH - 8)); + ox1 = ox1 * (1 << (BIT_DEPTH - 8)); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx1 + src2[x] * wx0 + + ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); + tmp += MAX_PB_SIZE; + dst += dststride; + src2 += src2stride; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +//////////////////////////////////////////////////////////////////////////////// +#define EPEL_FILTER(src, stride) \ + (filter[0] * src[x - stride] + \ + filter[1] * src[x] + \ + 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) + int height, intptr_t mx, intptr_t my, int width) { int x, y; pixel *src = (pixel *)_src; ptrdiff_t srcstride = _srcstride / sizeof(pixel); const int8_t *filter = ff_hevc_epel_filters[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]; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); @@ -981,17 +1135,12 @@ 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) + int height, intptr_t mx, intptr_t my, int width) { int x, y; pixel *src = (pixel *)_src; ptrdiff_t srcstride = _srcstride / sizeof(pixel); const int8_t *filter = ff_hevc_epel_filters[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]; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) @@ -1003,19 +1152,13 @@ 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) + int height, intptr_t mx, intptr_t my, int width) { 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]; - int8_t filter_0 = filter_h[0]; - int8_t filter_1 = filter_h[1]; - int8_t filter_2 = filter_h[2]; - int8_t filter_3 = filter_h[3]; - int16_t tmp_array[(MAX_PB_SIZE + 3) * MAX_PB_SIZE]; + const int8_t *filter = ff_hevc_epel_filters[mx - 1]; + int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE]; int16_t *tmp = tmp_array; src -= EPEL_EXTRA_BEFORE * srcstride; @@ -1028,10 +1171,8 @@ static void FUNC(put_hevc_epel_hv)(int16_t *dst, ptrdiff_t dststride, } tmp = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE; - filter_0 = filter_v[0]; - filter_1 = filter_v[1]; - filter_2 = filter_v[2]; - filter_3 = filter_v[3]; + filter = ff_hevc_epel_filters[my - 1]; + for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6; @@ -1040,37 +1181,91 @@ 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) +static void FUNC(put_hevc_epel_uni_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width) { int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); pixel *dst = (pixel *)_dst; ptrdiff_t dststride = _dststride / sizeof(pixel); - + const int8_t *filter = ff_hevc_epel_filters[mx - 1]; int shift = 14 - BIT_DEPTH; #if BIT_DEPTH < 14 int offset = 1 << (shift - 1); #else int offset = 0; #endif + for (y = 0; y < height; y++) { for (x = 0; x < width; x++) - dst[x] = av_clip_pixel((src[x] + offset) >> shift); - dst += dststride; + dst[x] = av_clip_pixel(((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) + offset) >> shift); src += srcstride; + dst += 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 void FUNC(put_hevc_epel_bi_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, intptr_t mx, intptr_t my, int width) { int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); pixel *dst = (pixel *)_dst; ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_epel_filters[mx - 1]; + int shift = 14 + 1 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + dst[x] = av_clip_pixel(((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) + src2[x] + offset) >> shift); + } + dst += dststride; + src += srcstride; + src2 += src2stride; + } +} + +static void FUNC(put_hevc_epel_uni_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_epel_filters[my - 1]; + int shift = 14 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) + offset) >> shift); + src += srcstride; + dst += dststride; + } +} + +static void FUNC(put_hevc_epel_bi_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + const int8_t *filter = ff_hevc_epel_filters[my - 1]; + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); int shift = 14 + 1 - BIT_DEPTH; #if BIT_DEPTH < 14 int offset = 1 << (shift - 1); @@ -1080,71 +1275,273 @@ static void FUNC(put_weighted_pred_avg)(uint8_t *_dst, ptrdiff_t _dststride, for (y = 0; y < height; y++) { for (x = 0; x < width; x++) - dst[x] = av_clip_pixel((src1[x] + src2[x] + offset) >> shift); + dst[x] = av_clip_pixel(((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) + src2[x] + offset) >> shift); dst += dststride; - src1 += srcstride; - src2 += srcstride; + src += srcstride; + src2 += src2stride; } } -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 void FUNC(put_hevc_epel_uni_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width) { - int shift, log2Wd, wx, ox, x, y, offset; + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); pixel *dst = (pixel *)_dst; ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_epel_filters[mx - 1]; + int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE]; + int16_t *tmp = tmp_array; + int shift = 14 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif - shift = 14 - BIT_DEPTH; - log2Wd = denom + shift; - offset = 1 << (log2Wd - 1); - wx = wlxFlag; - ox = olxFlag * (1 << (BIT_DEPTH - 8)); + src -= EPEL_EXTRA_BEFORE * srcstride; + + for (y = 0; y < height + EPEL_EXTRA; y++) { + for (x = 0; x < width; x++) + tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); + src += srcstride; + tmp += MAX_PB_SIZE; + } + + tmp = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE; + filter = ff_hevc_epel_filters[my - 1]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) + offset) >> shift); + tmp += MAX_PB_SIZE; + dst += dststride; + } +} + +static void FUNC(put_hevc_epel_bi_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_epel_filters[mx - 1]; + int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE]; + int16_t *tmp = tmp_array; + int shift = 14 + 1 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + src -= EPEL_EXTRA_BEFORE * srcstride; + + for (y = 0; y < height + EPEL_EXTRA; y++) { + for (x = 0; x < width; x++) + tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); + src += srcstride; + tmp += MAX_PB_SIZE; + } + + tmp = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE; + filter = ff_hevc_epel_filters[my - 1]; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) + src2[x] + offset) >> shift); + tmp += MAX_PB_SIZE; + dst += dststride; + src2 += src2stride; + } +} + +static void FUNC(put_hevc_epel_uni_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_epel_filters[mx - 1]; + int shift = denom + 14 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + ox = ox * (1 << (BIT_DEPTH - 8)); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { - if (log2Wd >= 1) { - dst[x] = av_clip_pixel(((src[x] * wx + offset) >> log2Wd) + ox); - } else { - dst[x] = av_clip_pixel(src[x] * wx + ox); - } + dst[x] = av_clip_pixel((((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx + offset) >> shift) + ox); } dst += dststride; src += srcstride; } } -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 void FUNC(put_hevc_epel_bi_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, int denom, int wx0, int wx1, + int ox0, int ox1, intptr_t mx, intptr_t my, int width) { - int shift, log2Wd, w0, w1, o0, o1, x, y; - pixel *dst = (pixel *)_dst; + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_epel_filters[mx - 1]; + int shift = 14 + 1 - BIT_DEPTH; + int log2Wd = denom + shift - 1; - shift = 14 - BIT_DEPTH; - log2Wd = denom + shift; - w0 = wl0Flag; - w1 = wl1Flag; - o0 = ol0Flag * (1 << (BIT_DEPTH - 8)); - o1 = ol1Flag * (1 << (BIT_DEPTH - 8)); - + ox0 = ox0 * (1 << (BIT_DEPTH - 8)); + ox1 = ox1 * (1 << (BIT_DEPTH - 8)); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) - dst[x] = av_clip_pixel((src1[x] * w0 + src2[x] * w1 + - ((o0 + o1 + 1) << log2Wd)) >> (log2Wd + 1)); + dst[x] = av_clip_pixel(((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 + + ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); + src += srcstride; dst += dststride; - src1 += srcstride; - src2 += srcstride; + src2 += src2stride; } } -// line zero +static void FUNC(put_hevc_epel_uni_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_epel_filters[my - 1]; + int shift = denom + 14 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + ox = ox * (1 << (BIT_DEPTH - 8)); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + dst[x] = av_clip_pixel((((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx + offset) >> shift) + ox); + } + dst += dststride; + src += srcstride; + } +} + +static void FUNC(put_hevc_epel_bi_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, int denom, int wx0, int wx1, + int ox0, int ox1, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + const int8_t *filter = ff_hevc_epel_filters[my - 1]; + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + int shift = 14 + 1 - BIT_DEPTH; + int log2Wd = denom + shift - 1; + + ox0 = ox0 * (1 << (BIT_DEPTH - 8)); + ox1 = ox1 * (1 << (BIT_DEPTH - 8)); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 + + ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); + src += srcstride; + dst += dststride; + src2 += src2stride; + } +} + +static void FUNC(put_hevc_epel_uni_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_epel_filters[mx - 1]; + int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE]; + int16_t *tmp = tmp_array; + int shift = denom + 14 - BIT_DEPTH; +#if BIT_DEPTH < 14 + int offset = 1 << (shift - 1); +#else + int offset = 0; +#endif + + src -= EPEL_EXTRA_BEFORE * srcstride; + + for (y = 0; y < height + EPEL_EXTRA; y++) { + for (x = 0; x < width; x++) + tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); + src += srcstride; + tmp += MAX_PB_SIZE; + } + + tmp = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE; + filter = ff_hevc_epel_filters[my - 1]; + + ox = ox * (1 << (BIT_DEPTH - 8)); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel((((EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx + offset) >> shift) + ox); + tmp += MAX_PB_SIZE; + dst += dststride; + } +} + +static void FUNC(put_hevc_epel_bi_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, + int16_t *src2, ptrdiff_t src2stride, + int height, int denom, int wx0, int wx1, + int ox0, int ox1, intptr_t mx, intptr_t my, int width) +{ + int x, y; + pixel *src = (pixel *)_src; + ptrdiff_t srcstride = _srcstride / sizeof(pixel); + pixel *dst = (pixel *)_dst; + ptrdiff_t dststride = _dststride / sizeof(pixel); + const int8_t *filter = ff_hevc_epel_filters[mx - 1]; + int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE]; + int16_t *tmp = tmp_array; + int shift = 14 + 1 - BIT_DEPTH; + int log2Wd = denom + shift - 1; + + src -= EPEL_EXTRA_BEFORE * srcstride; + + for (y = 0; y < height + EPEL_EXTRA; y++) { + for (x = 0; x < width; x++) + tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); + src += srcstride; + tmp += MAX_PB_SIZE; + } + + tmp = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE; + filter = ff_hevc_epel_filters[my - 1]; + + ox0 = ox0 * (1 << (BIT_DEPTH - 8)); + ox1 = ox1 * (1 << (BIT_DEPTH - 8)); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = av_clip_pixel(((EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx1 + src2[x] * wx0 + + ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); + tmp += MAX_PB_SIZE; + dst += dststride; + src2 += src2stride; + } +}// line zero #define P3 pix[-4 * xstride] #define P2 pix[-3 * xstride] #define P1 pix[-2 * xstride] diff --git a/libavcodec/hevcpred.c b/libavcodec/hevcpred.c index e4987f8ec..4598229b3 100644 --- a/libavcodec/hevcpred.c +++ b/libavcodec/hevcpred.c @@ -36,13 +36,20 @@ #include "hevcpred_template.c" #undef BIT_DEPTH +#define BIT_DEPTH 12 +#include "hevcpred_template.c" +#undef BIT_DEPTH + void ff_hevc_pred_init(HEVCPredContext *hpc, int bit_depth) { #undef FUNC #define FUNC(a, depth) a ## _ ## depth #define HEVC_PRED(depth) \ - hpc->intra_pred = FUNC(intra_pred, depth); \ + hpc->intra_pred[0] = FUNC(intra_pred_2, depth); \ + hpc->intra_pred[1] = FUNC(intra_pred_3, depth); \ + hpc->intra_pred[2] = FUNC(intra_pred_4, depth); \ + hpc->intra_pred[3] = FUNC(intra_pred_5, depth); \ hpc->pred_planar[0] = FUNC(pred_planar_0, depth); \ hpc->pred_planar[1] = FUNC(pred_planar_1, depth); \ hpc->pred_planar[2] = FUNC(pred_planar_2, depth); \ @@ -60,6 +67,9 @@ void ff_hevc_pred_init(HEVCPredContext *hpc, int bit_depth) case 10: HEVC_PRED(10); break; + case 12: + HEVC_PRED(12); + break; default: HEVC_PRED(8); break; diff --git a/libavcodec/hevcpred.h b/libavcodec/hevcpred.h index 4dead2ecd..7f14a76da 100644 --- a/libavcodec/hevcpred.h +++ b/libavcodec/hevcpred.h @@ -29,13 +29,15 @@ struct HEVCContext; typedef struct HEVCPredContext { - void (*intra_pred)(struct HEVCContext *s, int x0, int y0, int log2_size, int c_idx); + void (*intra_pred[4])(struct HEVCContext *s, int x0, int y0, int c_idx); - void(*pred_planar[4])(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); - void(*pred_dc)(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, - int log2_size, int c_idx); - void(*pred_angular[4])(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, - int c_idx, int mode); + void (*pred_planar[4])(uint8_t *src, const uint8_t *top, + const uint8_t *left, ptrdiff_t stride); + void (*pred_dc)(uint8_t *src, const uint8_t *top, const uint8_t *left, + ptrdiff_t stride, int log2_size, int c_idx); + void (*pred_angular[4])(uint8_t *src, const uint8_t *top, + const uint8_t *left, ptrdiff_t stride, + int c_idx, int mode); } HEVCPredContext; void ff_hevc_pred_init(HEVCPredContext *hpc, int bit_depth); diff --git a/libavcodec/hevcpred_template.c b/libavcodec/hevcpred_template.c index 5ba95919b..81242304d 100644 --- a/libavcodec/hevcpred_template.c +++ b/libavcodec/hevcpred_template.c @@ -27,7 +27,8 @@ #define POS(x, y) src[(x) + stride * (y)] -static void FUNC(intra_pred)(HEVCContext *s, int x0, int y0, int log2_size, int c_idx) +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) @@ -36,47 +37,53 @@ static void FUNC(intra_pred)(HEVCContext *s, int x0, int y0, int log2_size, int #define MVF_PU(x, y) \ MVF(PU(x0 + ((x) << hshift)), PU(y0 + ((y) << vshift))) #define IS_INTRA(x, y) \ - MVF_PU(x, y).is_intra + (MVF_PU(x, y).pred_flag == PF_INTRA) #define MIN_TB_ADDR_ZS(x, y) \ - s->pps->min_tb_addr_zs[(y) * s->sps->min_tb_width + (x)] -#define EXTEND_LEFT(ptr, start, length) \ - for (i = (start); i > (start) - (length); i--) \ - ptr[i - 1] = ptr[i] -#define EXTEND_RIGHT(ptr, start, length) \ - for (i = (start); i < (start) + (length); i++) \ - ptr[i] = ptr[i - 1] -#define EXTEND_UP(ptr, start, length) EXTEND_LEFT(ptr, start, length) -#define EXTEND_DOWN(ptr, start, length) EXTEND_RIGHT(ptr, start, length) + s->pps->min_tb_addr_zs[(y) * (s->sps->tb_mask+2) + (x)] +#define EXTEND(ptr, val, len) \ +do { \ + pixel4 pix = PIXEL_SPLAT_X4(val); \ + for (i = 0; i < (len); i += 4) \ + AV_WN4P(ptr + i, pix); \ +} while (0) + +#define EXTEND_RIGHT_CIP(ptr, start, length) \ + for (i = start; i < (start) + (length); i += 4) \ + if (!IS_INTRA(i, -1)) \ + AV_WN4P(&ptr[i], a); \ + else \ + a = PIXEL_SPLAT_X4(ptr[i+3]) #define EXTEND_LEFT_CIP(ptr, start, length) \ - for (i = (start); i > (start) - (length); i--) \ + for (i = start; i > (start) - (length); i--) \ if (!IS_INTRA(i - 1, -1)) \ ptr[i - 1] = ptr[i] -#define EXTEND_RIGHT_CIP(ptr, start, length) \ - for (i = (start); i < (start) + (length); i++) \ - if (!IS_INTRA(i, -1)) \ - ptr[i] = ptr[i - 1] -#define EXTEND_UP_CIP(ptr, start, length) \ - for (i = (start); i > (start) - (length); i--) \ - if (!IS_INTRA(-1, i - 1)) \ - ptr[i - 1] = ptr[i] -#define EXTEND_UP_CIP_0(ptr, start, length) \ - for (i = (start); i > (start) - (length); i--) \ - ptr[i - 1] = ptr[i] -#define EXTEND_DOWN_CIP(ptr, start, length) \ - for (i = (start); i < (start) + (length); i++) \ - if (!IS_INTRA(-1, i)) \ - ptr[i] = ptr[i - 1] +#define EXTEND_UP_CIP(ptr, start, length) \ + for (i = (start); i > (start) - (length); i -= 4) \ + if (!IS_INTRA(-1, i - 3)) \ + AV_WN4P(&ptr[i - 3], a); \ + else \ + a = PIXEL_SPLAT_X4(ptr[i - 3]) +#define EXTEND_DOWN_CIP(ptr, start, length) \ + for (i = start; i < (start) + (length); i += 4) \ + if (!IS_INTRA(-1, i)) \ + AV_WN4P(&ptr[i], a); \ + else \ + a = PIXEL_SPLAT_X4(ptr[i + 3]) + HEVCLocalContext *lc = s->HEVClc; int i; int hshift = s->sps->hshift[c_idx]; int vshift = s->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_luma_h = size << hshift; + int size_in_tbs_h = size_in_luma_h >> s->sps->log2_min_tb_size; + int size_in_luma_v = size << vshift; + int size_in_tbs_v = size_in_luma_v >> s->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->sps->log2_min_tb_size) & s->sps->tb_mask; + int y_tb = (y0 >> s->sps->log2_min_tb_size) & s->sps->tb_mask; + int cur_tb_addr = MIN_TB_ADDR_ZS(x_tb, y_tb); ptrdiff_t stride = s->frame->linesize[c_idx] / sizeof(pixel); @@ -84,108 +91,96 @@ static void FUNC(intra_pred)(HEVCContext *s, int x0, int y0, int log2_size, int int min_pu_width = s->sps->min_pu_width; - enum IntraPredMode mode = c_idx ? lc->pu.intra_pred_mode_c : - lc->tu.cur_intra_pred_mode; + enum IntraPredMode mode = c_idx ? lc->tu.intra_pred_mode_c : + lc->tu.intra_pred_mode; + pixel4 a; + pixel left_array[2 * MAX_TB_SIZE + 1]; + pixel filtered_left_array[2 * MAX_TB_SIZE + 1]; + pixel top_array[2 * MAX_TB_SIZE + 1]; + pixel filtered_top_array[2 * MAX_TB_SIZE + 1]; - pixel left_array[2 * MAX_TB_SIZE + 1]; - pixel filtered_left_array[2 * MAX_TB_SIZE + 1]; - pixel top_array[2 * MAX_TB_SIZE + 1]; - pixel filtered_top_array[2 * MAX_TB_SIZE + 1]; - - pixel *left = left_array + 1; - pixel *top = top_array + 1; - pixel *filtered_left = filtered_left_array + 1; - pixel *filtered_top = filtered_top_array + 1; - - int cand_bottom_left = lc->na.cand_bottom_left && cur_tb_addr > MIN_TB_ADDR_ZS(x_tb - 1, y_tb + size_in_tbs); + pixel *left = left_array + 1; + pixel *top = top_array + 1; + pixel *filtered_left = filtered_left_array + 1; + pixel *filtered_top = filtered_top_array + 1; + int cand_bottom_left = lc->na.cand_bottom_left && cur_tb_addr > MIN_TB_ADDR_ZS( x_tb - 1, (y_tb + size_in_tbs_v) & s->sps->tb_mask); int cand_left = lc->na.cand_left; int cand_up_left = lc->na.cand_up_left; 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 cand_up_right = lc->na.cand_up_right && cur_tb_addr > MIN_TB_ADDR_ZS((x_tb + size_in_tbs_h) & s->sps->tb_mask, y_tb - 1); - int bottom_left_size = (FFMIN(y0 + 2 * size_in_luma, s->sps->height) - - (y0 + size_in_luma)) >> vshift; - int top_right_size = (FFMIN(x0 + 2 * size_in_luma, s->sps->width) - - (x0 + size_in_luma)) >> hshift; + int bottom_left_size = (FFMIN(y0 + 2 * size_in_luma_v, s->sps->height) - + (y0 + size_in_luma_v)) >> vshift; + int top_right_size = (FFMIN(x0 + 2 * size_in_luma_h, s->sps->width) - + (x0 + size_in_luma_h)) >> hshift; if (s->pps->constrained_intra_pred_flag == 1) { - int size_in_luma_pu = PU(size_in_luma); + int size_in_luma_pu_v = PU(size_in_luma_v); + int size_in_luma_pu_h = PU(size_in_luma_h); 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)); - if (!size_in_luma_pu) - size_in_luma_pu++; + if (!size_in_luma_pu_h) + size_in_luma_pu_h++; 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 y_bottom_pu = PU(y0 + size_in_luma_v); + int max = FFMIN(size_in_luma_pu_v, s->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; + for (i = 0; i < max; i += 2) + cand_bottom_left |= (MVF(x_left_pu, y_bottom_pu + i).pred_flag == PF_INTRA); } 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_v, s->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; + for (i = 0; i < max; i += 2) + cand_left |= (MVF(x_left_pu, y_left_pu + i).pred_flag == PF_INTRA); } if (cand_up_left == 1) { int x_left_pu = PU(x0 - 1); int y_top_pu = PU(y0 - 1); - cand_up_left = MVF(x_left_pu, y_top_pu).is_intra; + cand_up_left = MVF(x_left_pu, y_top_pu).pred_flag == PF_INTRA; } 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_h, s->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; + for (i = 0; i < max; i += 2) + cand_up |= (MVF(x_top_pu + i, y_top_pu).pred_flag == PF_INTRA); } 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 x_right_pu = PU(x0 + size_in_luma_h); + int max = FFMIN(size_in_luma_pu_h, s->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; - } - for (i = 0; i < 2 * MAX_TB_SIZE; i++) { - left[i] = 128; - top[i] = 128; + for (i = 0; i < max; i += 2) + cand_up_right |= (MVF(x_right_pu + i, y_top_pu).pred_flag == PF_INTRA); } + memset(left, 128, 2 * MAX_TB_SIZE*sizeof(pixel)); + memset(top , 128, 2 * MAX_TB_SIZE*sizeof(pixel)); + top[-1] = 128; } - if (cand_bottom_left) { - for (i = size + bottom_left_size; i < (size << 1); i++) - if (IS_INTRA(-1, size + bottom_left_size - 1) || - !s->pps->constrained_intra_pred_flag) - left[i] = POS(-1, size + bottom_left_size - 1); - for (i = size + bottom_left_size - 1; i >= size; i--) - if (IS_INTRA(-1, i) || !s->pps->constrained_intra_pred_flag) - left[i] = POS(-1, i); + if (cand_up_left) { + left[-1] = POS(-1, -1); + top[-1] = left[-1]; + } + if (cand_up) + memcpy(top, src - stride, size * sizeof(pixel)); + if (cand_up_right) { + memcpy(top + size, src - stride + size, size * sizeof(pixel)); + EXTEND(top + size + top_right_size, POS(size + top_right_size - 1, -1), + size - top_right_size); } if (cand_left) - for (i = size - 1; i >= 0; i--) - if (IS_INTRA(-1, i) || !s->pps->constrained_intra_pred_flag) - left[i] = POS(-1, i); - if (cand_up_left) - if (IS_INTRA(-1, -1) || !s->pps->constrained_intra_pred_flag) { - left[-1] = POS(-1, -1); - top[-1] = left[-1]; - } - if (cand_up) - for (i = size - 1; i >= 0; i--) - if (IS_INTRA(i, -1) || !s->pps->constrained_intra_pred_flag) - top[i] = POS(i, -1); - if (cand_up_right) { - for (i = size + top_right_size; i < (size << 1); i++) - if (IS_INTRA(size + top_right_size - 1, -1) || - !s->pps->constrained_intra_pred_flag) - top[i] = POS(size + top_right_size - 1, -1); - for (i = size + top_right_size - 1; i >= size; i--) - if (IS_INTRA(i, -1) || !s->pps->constrained_intra_pred_flag) - top[i] = POS(i, -1); + for (i = 0; i < size; i++) + left[i] = POS(-1, i); + if (cand_bottom_left) { + for (i = size; i < size + bottom_left_size; i++) + left[i] = POS(-1, i); + EXTEND(left + size + bottom_left_size, POS(-1, size + bottom_left_size - 1), + size - bottom_left_size); } if (s->pps->constrained_intra_pred_flag == 1) { @@ -212,7 +207,6 @@ static void FUNC(intra_pred)(HEVCContext *s, int x0, int y0, int log2_size, int j++; EXTEND_LEFT_CIP(top, j, j + 1); left[-1] = top[-1]; - j = 0; } } else { j = 0; @@ -226,26 +220,30 @@ static void FUNC(intra_pred)(HEVCContext *s, int x0, int y0, int log2_size, int top[-1] = top[0]; } left[-1] = top[-1]; - j = 0; } + left[-1] = top[-1]; if (cand_bottom_left || cand_left) { - EXTEND_DOWN_CIP(left, j, size_max_y - j); - } - if (!cand_left) { - EXTEND_DOWN(left, 0, size); - } - if (!cand_bottom_left) { - EXTEND_DOWN(left, size, size); + a = PIXEL_SPLAT_X4(left[-1]); + EXTEND_DOWN_CIP(left, 0, size_max_y); } + if (!cand_left) + EXTEND(left, left[-1], size); + if (!cand_bottom_left) + EXTEND(left + size, left[size - 1], size); if (x0 != 0 && y0 != 0) { + a = PIXEL_SPLAT_X4(left[size_max_y - 1]); EXTEND_UP_CIP(left, size_max_y - 1, size_max_y); + if (!IS_INTRA(-1, - 1)) + left[-1] = left[0]; } else if (x0 == 0) { - EXTEND_UP_CIP_0(left, size_max_y - 1, size_max_y); + EXTEND(left, 0, size_max_y); } else { - EXTEND_UP_CIP(left, size_max_y - 1, size_max_y - 1); + a = PIXEL_SPLAT_X4(left[size_max_y - 1]); + EXTEND_UP_CIP(left, size_max_y - 1, size_max_y); } top[-1] = left[-1]; if (y0 != 0) { + a = PIXEL_SPLAT_X4(left[-1]); EXTEND_RIGHT_CIP(top, 0, size_max_x); } } @@ -253,80 +251,78 @@ static void FUNC(intra_pred)(HEVCContext *s, int x0, int y0, int log2_size, int // Infer the unavailable samples if (!cand_bottom_left) { if (cand_left) { - EXTEND_DOWN(left, size, size); + EXTEND(left + size, left[size - 1], size); } else if (cand_up_left) { - EXTEND_DOWN(left, 0, 2 * size); + EXTEND(left, left[-1], 2 * size); cand_left = 1; } else if (cand_up) { left[-1] = top[0]; - EXTEND_DOWN(left, 0, 2 * size); + EXTEND(left, left[-1], 2 * size); cand_up_left = 1; cand_left = 1; } else if (cand_up_right) { - EXTEND_LEFT(top, size, size); - left[-1] = top[0]; - EXTEND_DOWN(left, 0, 2 * size); + EXTEND(top, top[size], size); + left[-1] = top[size]; + EXTEND(left, left[-1], 2 * size); cand_up = 1; cand_up_left = 1; cand_left = 1; } else { // No samples available - top[0] = left[-1] = (1 << (BIT_DEPTH - 1)); - EXTEND_RIGHT(top, 1, 2 * size - 1); - EXTEND_DOWN(left, 0, 2 * size); + left[-1] = (1 << (BIT_DEPTH - 1)); + EXTEND(top, left[-1], 2 * size); + EXTEND(left, left[-1], 2 * size); } } - if (!cand_left) { - EXTEND_UP(left, size, size); - } + if (!cand_left) + EXTEND(left, left[size], size); if (!cand_up_left) { left[-1] = left[0]; } - if (!cand_up) { - top[0] = left[-1]; - EXTEND_RIGHT(top, 1, size - 1); - } - if (!cand_up_right) { - EXTEND_RIGHT(top, size, size); - } + if (!cand_up) + EXTEND(top, left[-1], size); + if (!cand_up_right) + EXTEND(top + size, top[size - 1], size); top[-1] = left[-1]; // Filtering process - if (c_idx == 0 && mode != INTRA_DC && size != 4) { - int intra_hor_ver_dist_thresh[] = { 7, 1, 0 }; - int min_dist_vert_hor = FFMIN(FFABS((int)(mode - 26U)), - FFABS((int)(mode - 10U))); - 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 && - log2_size == 5 && - FFABS(top[-1] + top[63] - 2 * top[31]) < threshold && - FFABS(left[-1] + left[63] - 2 * left[31]) < threshold) { - // We can't just overwrite values in top because it could be - // a pointer into src - filtered_top[-1] = top[-1]; - filtered_top[63] = top[63]; - for (i = 0; i < 63; i++) - filtered_top[i] = ((64 - (i + 1)) * top[-1] + - (i + 1) * top[63] + 32) >> 6; - for (i = 0; i < 63; i++) - left[i] = ((64 - (i + 1)) * left[-1] + - (i + 1) * left[63] + 32) >> 6; - top = filtered_top; - } else { - filtered_left[2 * size - 1] = left[2 * size - 1]; - filtered_top[2 * size - 1] = top[2 * size - 1]; - for (i = 2 * size - 2; i >= 0; i--) - filtered_left[i] = (left[i + 1] + 2 * left[i] + - left[i - 1] + 2) >> 2; - filtered_top[-1] = - filtered_left[-1] = (left[0] + 2 * left[-1] + top[0] + 2) >> 2; - for (i = 2 * size - 2; i >= 0; i--) - filtered_top[i] = (top[i + 1] + 2 * top[i] + - top[i - 1] + 2) >> 2; - left = filtered_left; - top = filtered_top; + if (!s->sps->intra_smoothing_disabled_flag && (c_idx == 0 || s->sps->chroma_format_idc == 3)) { + if (mode != INTRA_DC && size != 4){ + int intra_hor_ver_dist_thresh[] = { 7, 1, 0 }; + int min_dist_vert_hor = FFMIN(FFABS((int)(mode - 26U)), + FFABS((int)(mode - 10U))); + 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 && c_idx == 0 && + log2_size == 5 && + FFABS(top[-1] + top[63] - 2 * top[31]) < threshold && + FFABS(left[-1] + left[63] - 2 * left[31]) < threshold) { + // We can't just overwrite values in top because it could be + // a pointer into src + filtered_top[-1] = top[-1]; + filtered_top[63] = top[63]; + for (i = 0; i < 63; i++) + filtered_top[i] = ((64 - (i + 1)) * top[-1] + + (i + 1) * top[63] + 32) >> 6; + for (i = 0; i < 63; i++) + left[i] = ((64 - (i + 1)) * left[-1] + + (i + 1) * left[63] + 32) >> 6; + top = filtered_top; + } else { + filtered_left[2 * size - 1] = left[2 * size - 1]; + filtered_top[2 * size - 1] = top[2 * size - 1]; + for (i = 2 * size - 2; i >= 0; i--) + filtered_left[i] = (left[i + 1] + 2 * left[i] + + left[i - 1] + 2) >> 2; + filtered_top[-1] = + filtered_left[-1] = (left[0] + 2 * left[-1] + top[0] + 2) >> 2; + for (i = 2 * size - 2; i >= 0; i--) + filtered_top[i] = (top[i + 1] + 2 * top[i] + + top[i - 1] + 2) >> 2; + left = filtered_left; + top = filtered_top; + } } } } @@ -348,58 +344,47 @@ static void FUNC(intra_pred)(HEVCContext *s, int x0, int y0, int log2_size, int } } -static void FUNC(pred_planar_0)(uint8_t *_src, const uint8_t *_top, - const uint8_t *_left, - ptrdiff_t stride) -{ - int x, y; - pixel *src = (pixel *)_src; - const pixel *top = (const pixel *)_top; - const pixel *left = (const pixel *)_left; - for (y = 0; y < 4; y++) - for (x = 0; x < 4; x++) - POS(x, y) = ((3 - x) * left[y] + (x + 1) * top[4] + - (3 - y) * top[x] + (y + 1) * left[4] + 4) >> 3; +#define INTRA_PRED(size) \ +static void FUNC(intra_pred_ ## size)(HEVCContext *s, int x0, int y0, int c_idx) \ +{ \ + FUNC(intra_pred)(s, x0, y0, size, c_idx); \ } -static void FUNC(pred_planar_1)(uint8_t *_src, const uint8_t *_top, - const uint8_t *_left, ptrdiff_t stride) +INTRA_PRED(2) +INTRA_PRED(3) +INTRA_PRED(4) +INTRA_PRED(5) + +#undef INTRA_PRED + +static av_always_inline void FUNC(pred_planar)(uint8_t *_src, const uint8_t *_top, + const uint8_t *_left, ptrdiff_t stride, + int trafo_size) { int x, y; pixel *src = (pixel *)_src; const pixel *top = (const pixel *)_top; const pixel *left = (const pixel *)_left; - for (y = 0; y < 8; y++) - for (x = 0; x < 8; x++) - POS(x, y) = ((7 - x) * left[y] + (x + 1) * top[8] + - (7 - y) * top[x] + (y + 1) * left[8] + 8) >> 4; + int size = 1 << trafo_size; + for (y = 0; y < size; y++) + for (x = 0; x < size; x++) + POS(x, y) = ((size - 1 - x) * left[y] + (x + 1) * top[size] + + (size - 1 - y) * top[x] + (y + 1) * left[size] + size) >> (trafo_size + 1); } -static void FUNC(pred_planar_2)(uint8_t *_src, const uint8_t *_top, - const uint8_t *_left, ptrdiff_t stride) -{ - int x, y; - pixel *src = (pixel *)_src; - const pixel *top = (const pixel *)_top; - const pixel *left = (const pixel *)_left; - for (y = 0; y < 16; y++) - for (x = 0; x < 16; x++) - POS(x, y) = ((15 - x) * left[y] + (x + 1) * top[16] + - (15 - y) * top[x] + (y + 1) * left[16] + 16) >> 5; +#define PRED_PLANAR(size)\ +static void FUNC(pred_planar_ ## size)(uint8_t *src, const uint8_t *top, \ + const uint8_t *left, ptrdiff_t stride) \ +{ \ + FUNC(pred_planar)(src, top, left, stride, size + 2); \ } -static void FUNC(pred_planar_3)(uint8_t *_src, const uint8_t *_top, - const uint8_t *_left, ptrdiff_t stride) -{ - int x, y; - pixel *src = (pixel *)_src; - const pixel *top = (const pixel *)_top; - const pixel *left = (const pixel *)_left; - for (y = 0; y < 32; y++) - for (x = 0; x < 32; x++) - POS(x, y) = ((31 - x) * left[y] + (x + 1) * top[32] + - (31 - y) * top[x] + (y + 1) * left[32] + 32) >> 6; -} +PRED_PLANAR(0) +PRED_PLANAR(1) +PRED_PLANAR(2) +PRED_PLANAR(3) + +#undef PRED_PLANAR static void FUNC(pred_dc)(uint8_t *_src, const uint8_t *_top, const uint8_t *_left, @@ -420,8 +405,8 @@ static void FUNC(pred_dc)(uint8_t *_src, const uint8_t *_top, a = PIXEL_SPLAT_X4(dc); for (i = 0; i < size; i++) - for (j = 0; j < size / 4; j++) - AV_WN4PA(&POS(j * 4, i), a); + for (j = 0; j < size; j+=4) + AV_WN4P(&POS(j, i), a); if (c_idx == 0 && size < 32) { POS(0, 0) = (left[0] + 2 * dc + top[0] + 2) >> 2; @@ -453,7 +438,7 @@ static av_always_inline void FUNC(pred_angular)(uint8_t *_src, }; int angle = intra_pred_angle[mode - 2]; - pixel ref_array[3 * MAX_TB_SIZE + 1]; + pixel ref_array[3 * MAX_TB_SIZE + 4]; pixel *ref_tmp = ref_array + size; const pixel *ref; int last = (size * angle) >> 5; @@ -461,8 +446,8 @@ static av_always_inline void FUNC(pred_angular)(uint8_t *_src, if (mode >= 18) { ref = top - 1; if (angle < 0 && last < -1) { - for (x = 0; x <= size; x++) - ref_tmp[x] = top[x - 1]; + for (x = 0; x <= size; x += 4) + AV_WN4P(&ref_tmp[x], AV_RN4P(&top[x - 1])); for (x = last; x <= -1; x++) ref_tmp[x] = left[-1 + ((x * inv_angle[mode - 11] + 128) >> 8)]; ref = ref_tmp; @@ -472,13 +457,19 @@ static av_always_inline void FUNC(pred_angular)(uint8_t *_src, int idx = ((y + 1) * angle) >> 5; int fact = ((y + 1) * angle) & 31; if (fact) { - for (x = 0; x < size; x++) { - POS(x, y) = ((32 - fact) * ref[x + idx + 1] + - fact * ref[x + idx + 2] + 16) >> 5; + for (x = 0; x < size; x += 4) { + POS(x , y) = ((32 - fact) * ref[x + idx + 1] + + fact * ref[x + idx + 2] + 16) >> 5; + POS(x + 1, y) = ((32 - fact) * ref[x + 1 + idx + 1] + + fact * ref[x + 1 + idx + 2] + 16) >> 5; + POS(x + 2, y) = ((32 - fact) * ref[x + 2 + idx + 1] + + fact * ref[x + 2 + idx + 2] + 16) >> 5; + POS(x + 3, y) = ((32 - fact) * ref[x + 3 + idx + 1] + + fact * ref[x + 3 + idx + 2] + 16) >> 5; } } else { - for (x = 0; x < size; x++) - POS(x, y) = ref[x + idx + 1]; + for (x = 0; x < size; x += 4) + AV_WN4P(&POS(x, y), AV_RN4P(&ref[x + idx + 1])); } } if (mode == 26 && c_idx == 0 && size < 32) { @@ -488,8 +479,8 @@ static av_always_inline void FUNC(pred_angular)(uint8_t *_src, } else { ref = left - 1; if (angle < 0 && last < -1) { - for (x = 0; x <= size; x++) - ref_tmp[x] = left[x - 1]; + for (x = 0; x <= size; x += 4) + AV_WN4P(&ref_tmp[x], AV_RN4P(&left[x - 1])); for (x = last; x <= -1; x++) ref_tmp[x] = top[-1 + ((x * inv_angle[mode - 11] + 128) >> 8)]; ref = ref_tmp; @@ -509,8 +500,12 @@ static av_always_inline void FUNC(pred_angular)(uint8_t *_src, } } if (mode == 10 && c_idx == 0 && size < 32) { - for (x = 0; x < size; x++) - POS(x, 0) = av_clip_pixel(left[0] + ((top[x] - top[-1]) >> 1)); + for (x = 0; x < size; x += 4) { + POS(x, 0) = av_clip_pixel(left[0] + ((top[x ] - top[-1]) >> 1)); + POS(x + 1, 0) = av_clip_pixel(left[0] + ((top[x + 1] - top[-1]) >> 1)); + POS(x + 2, 0) = av_clip_pixel(left[0] + ((top[x + 2] - top[-1]) >> 1)); + POS(x + 3, 0) = av_clip_pixel(left[0] + ((top[x + 3] - top[-1]) >> 1)); + } } } } @@ -551,9 +546,6 @@ static void FUNC(pred_angular_3)(uint8_t *src, const uint8_t *top, #undef MVF_PU #undef MVF #undef PU -#undef EXTEND_LEFT -#undef EXTEND_RIGHT -#undef EXTEND_UP -#undef EXTEND_DOWN +#undef EXTEND #undef MIN_TB_ADDR_ZS #undef POS diff --git a/libavcodec/hpel_template.c b/libavcodec/hpel_template.c index 3b4699927..fccfe7610 100644 --- a/libavcodec/hpel_template.c +++ b/libavcodec/hpel_template.c @@ -19,81 +19,87 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#define DEF_HPEL(OPNAME, OP) \ -static inline void FUNCC(OPNAME ## _pixels2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){\ - int i;\ - for(i=0; i> 2; /* FIXME non put */ \ + block[1] = (b1 + b0) >> 2; \ + \ + pixels += line_size; \ + block += line_size; \ + \ + a0 = pixels[0]; \ + b0 = pixels[1] + 2; \ + a0 += b0; \ + b0 += pixels[2]; \ + \ + block[0] = (a1 + a0) >> 2; \ + block[1] = (b1 + b0) >> 2; \ + pixels += line_size; \ + block += line_size; \ + } \ +} \ + \ +static inline void OPNAME ## _pixels4_xy2_8_c(uint8_t *block, \ + const uint8_t *pixels, \ + ptrdiff_t line_size, \ + int h) \ +{ \ + /* FIXME HIGH BIT DEPTH */ \ + int i; \ + const uint32_t a = AV_RN32(pixels); \ + const uint32_t b = AV_RN32(pixels + 1); \ + uint32_t l0 = (a & 0x03030303UL) + \ + (b & 0x03030303UL) + \ + 0x02020202UL; \ + uint32_t h0 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + uint32_t l1, h1; \ + \ + pixels += line_size; \ + for (i = 0; i < h; i += 2) { \ + uint32_t a = AV_RN32(pixels); \ + uint32_t b = AV_RN32(pixels + 1); \ + l1 = (a & 0x03030303UL) + \ + (b & 0x03030303UL); \ + h1 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + OP(*((uint32_t *) block), h0 + h1 + \ + (((l0 + l1) >> 2) & 0x0F0F0F0FUL)); \ + pixels += line_size; \ + block += line_size; \ + a = AV_RN32(pixels); \ + b = AV_RN32(pixels + 1); \ + l0 = (a & 0x03030303UL) + \ + (b & 0x03030303UL) + \ + 0x02020202UL; \ + h0 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + OP(*((uint32_t *) block), h0 + h1 + \ + (((l0 + l1) >> 2) & 0x0F0F0F0FUL)); \ + pixels += line_size; \ + block += line_size; \ + } \ +} \ + \ +static inline void OPNAME ## _pixels8_xy2_8_c(uint8_t *block, \ + const uint8_t *pixels, \ + ptrdiff_t line_size, \ + int h) \ +{ \ + /* FIXME HIGH BIT DEPTH */ \ + int j; \ + \ + for (j = 0; j < 2; j++) { \ + int i; \ + const uint32_t a = AV_RN32(pixels); \ + const uint32_t b = AV_RN32(pixels + 1); \ + uint32_t l0 = (a & 0x03030303UL) + \ + (b & 0x03030303UL) + \ + 0x02020202UL; \ + uint32_t h0 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + uint32_t l1, h1; \ + \ + pixels += line_size; \ + for (i = 0; i < h; i += 2) { \ + uint32_t a = AV_RN32(pixels); \ + uint32_t b = AV_RN32(pixels + 1); \ + l1 = (a & 0x03030303UL) + \ + (b & 0x03030303UL); \ + h1 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + OP(*((uint32_t *) block), h0 + h1 + \ + (((l0 + l1) >> 2) & 0x0F0F0F0FUL)); \ + pixels += line_size; \ + block += line_size; \ + a = AV_RN32(pixels); \ + b = AV_RN32(pixels + 1); \ + l0 = (a & 0x03030303UL) + \ + (b & 0x03030303UL) + \ + 0x02020202UL; \ + h0 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + OP(*((uint32_t *) block), h0 + h1 + \ + (((l0 + l1) >> 2) & 0x0F0F0F0FUL)); \ + pixels += line_size; \ + block += line_size; \ + } \ + pixels += 4 - line_size * (h + 1); \ + block += 4 - line_size * h; \ + } \ +} \ + \ +static inline void OPNAME ## _no_rnd_pixels8_xy2_8_c(uint8_t *block, \ + const uint8_t *pixels, \ + ptrdiff_t line_size, \ + int h) \ +{ \ + /* FIXME HIGH BIT DEPTH */ \ + int j; \ + \ + for (j = 0; j < 2; j++) { \ + int i; \ + const uint32_t a = AV_RN32(pixels); \ + const uint32_t b = AV_RN32(pixels + 1); \ + uint32_t l0 = (a & 0x03030303UL) + \ + (b & 0x03030303UL) + \ + 0x01010101UL; \ + uint32_t h0 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + uint32_t l1, h1; \ + \ + pixels += line_size; \ + for (i = 0; i < h; i += 2) { \ + uint32_t a = AV_RN32(pixels); \ + uint32_t b = AV_RN32(pixels + 1); \ + l1 = (a & 0x03030303UL) + \ + (b & 0x03030303UL); \ + h1 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + OP(*((uint32_t *) block), h0 + h1 + \ + (((l0 + l1) >> 2) & 0x0F0F0F0FUL)); \ + pixels += line_size; \ + block += line_size; \ + a = AV_RN32(pixels); \ + b = AV_RN32(pixels + 1); \ + l0 = (a & 0x03030303UL) + \ + (b & 0x03030303UL) + \ + 0x01010101UL; \ + h0 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + OP(*((uint32_t *) block), h0 + h1 + \ + (((l0 + l1) >> 2) & 0x0F0F0F0FUL)); \ + pixels += line_size; \ + block += line_size; \ + } \ + pixels += 4 - line_size * (h + 1); \ + block += 4 - line_size * h; \ + } \ +} \ + \ +CALL_2X_PIXELS(OPNAME ## _pixels16_x2_8_c, \ + OPNAME ## _pixels8_x2_8_c, \ + 8) \ +CALL_2X_PIXELS(OPNAME ## _pixels16_y2_8_c, \ + OPNAME ## _pixels8_y2_8_c, \ + 8) \ +CALL_2X_PIXELS(OPNAME ## _pixels16_xy2_8_c, \ + OPNAME ## _pixels8_xy2_8_c, \ + 8) \ +CALL_2X_PIXELS(OPNAME ## _no_rnd_pixels16_8_c, \ + OPNAME ## _pixels8_8_c, \ + 8) \ +CALL_2X_PIXELS(OPNAME ## _no_rnd_pixels16_x2_8_c, \ + OPNAME ## _no_rnd_pixels8_x2_8_c, \ + 8) \ +CALL_2X_PIXELS(OPNAME ## _no_rnd_pixels16_y2_8_c, \ + OPNAME ## _no_rnd_pixels8_y2_8_c, \ + 8) \ +CALL_2X_PIXELS(OPNAME ## _no_rnd_pixels16_xy2_8_c, \ + OPNAME ## _no_rnd_pixels8_xy2_8_c, \ + 8) \ + +#define op_avg(a, b) a = rnd_avg32(a, b) +#define op_put(a, b) a = b +#define put_no_rnd_pixels8_8_c put_pixels8_8_c +PIXOP2(avg, op_avg) +PIXOP2(put, op_put) +#undef op_avg +#undef op_put av_cold void ff_hpeldsp_init(HpelDSPContext *c, int flags) { @@ -60,12 +361,8 @@ av_cold void ff_hpeldsp_init(HpelDSPContext *c, int flags) ff_hpeldsp_init_alpha(c, flags); if (ARCH_ARM) ff_hpeldsp_init_arm(c, flags); - if (ARCH_BFIN) - ff_hpeldsp_init_bfin(c, flags); if (ARCH_PPC) ff_hpeldsp_init_ppc(c, flags); - if (HAVE_VIS) - ff_hpeldsp_init_vis(c, flags); if (ARCH_X86) ff_hpeldsp_init_x86(c, flags); } diff --git a/libavcodec/hpeldsp.h b/libavcodec/hpeldsp.h index ac94f6a8d..07c293ae7 100644 --- a/libavcodec/hpeldsp.h +++ b/libavcodec/hpeldsp.h @@ -97,9 +97,7 @@ void ff_hpeldsp_init(HpelDSPContext *c, int flags); void ff_hpeldsp_init_aarch64(HpelDSPContext *c, int flags); void ff_hpeldsp_init_alpha(HpelDSPContext *c, int flags); void ff_hpeldsp_init_arm(HpelDSPContext *c, int flags); -void ff_hpeldsp_init_bfin(HpelDSPContext *c, int flags); void ff_hpeldsp_init_ppc(HpelDSPContext *c, int flags); -void ff_hpeldsp_init_vis(HpelDSPContext *c, int flags); void ff_hpeldsp_init_x86(HpelDSPContext *c, int flags); #endif /* AVCODEC_HPELDSP_H */ diff --git a/libavcodec/hpeldsp_template.c b/libavcodec/hpeldsp_template.c deleted file mode 100644 index 9c9fd2b9e..000000000 --- a/libavcodec/hpeldsp_template.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Half-pel DSP functions. - * Copyright (c) 2000, 2001 Fabrice Bellard - * Copyright (c) 2002-2004 Michael Niedermayer - * - * gmc & q-pel & 32/64 bit based MC by Michael Niedermayer - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * Half-pel DSP functions. - */ - -#include "bit_depth_template.c" - -#include "hpel_template.c" - -#define PIXOP2(OPNAME, OP) \ -static inline void FUNC(OPNAME ## _no_rnd_pixels8_l2)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, \ - int src_stride1, int src_stride2, int h){\ - int i;\ - for(i=0; i>= sizeof(pixel)-1;\ - a0= pixels[0];\ - b0= pixels[1] + 2;\ - a0 += b0;\ - b0 += pixels[2];\ -\ - pixels+=line_size;\ - for(i=0; i>2; /* FIXME non put */\ - block[1]= (b1+b0)>>2;\ -\ - pixels+=line_size;\ - block +=line_size;\ -\ - a0= pixels[0];\ - b0= pixels[1] + 2;\ - a0 += b0;\ - b0 += pixels[2];\ -\ - block[0]= (a1+a0)>>2;\ - block[1]= (b1+b0)>>2;\ - pixels+=line_size;\ - block +=line_size;\ - }\ -}\ -\ -static inline void FUNCC(OPNAME ## _pixels4_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)\ -{\ - /* FIXME HIGH BIT DEPTH */\ - int i;\ - const uint32_t a= AV_RN32(pixels );\ - const uint32_t b= AV_RN32(pixels+1);\ - uint32_t l0= (a&0x03030303UL)\ - + (b&0x03030303UL)\ - + 0x02020202UL;\ - uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - uint32_t l1,h1;\ -\ - pixels+=line_size;\ - for(i=0; i>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ - pixels+=line_size;\ - block +=line_size;\ - a= AV_RN32(pixels );\ - b= AV_RN32(pixels+1);\ - l0= (a&0x03030303UL)\ - + (b&0x03030303UL)\ - + 0x02020202UL;\ - h0= ((a&0xFCFCFCFCUL)>>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ - pixels+=line_size;\ - block +=line_size;\ - }\ -}\ -\ -static inline void FUNCC(OPNAME ## _pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)\ -{\ - /* FIXME HIGH BIT DEPTH */\ - int j;\ - for(j=0; j<2; j++){\ - int i;\ - const uint32_t a= AV_RN32(pixels );\ - const uint32_t b= AV_RN32(pixels+1);\ - uint32_t l0= (a&0x03030303UL)\ - + (b&0x03030303UL)\ - + 0x02020202UL;\ - uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - uint32_t l1,h1;\ -\ - pixels+=line_size;\ - for(i=0; i>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ - pixels+=line_size;\ - block +=line_size;\ - a= AV_RN32(pixels );\ - b= AV_RN32(pixels+1);\ - l0= (a&0x03030303UL)\ - + (b&0x03030303UL)\ - + 0x02020202UL;\ - h0= ((a&0xFCFCFCFCUL)>>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ - pixels+=line_size;\ - block +=line_size;\ - }\ - pixels+=4-line_size*(h+1);\ - block +=4-line_size*h;\ - }\ -}\ -\ -static inline void FUNCC(OPNAME ## _no_rnd_pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)\ -{\ - /* FIXME HIGH BIT DEPTH */\ - int j;\ - for(j=0; j<2; j++){\ - int i;\ - const uint32_t a= AV_RN32(pixels );\ - const uint32_t b= AV_RN32(pixels+1);\ - uint32_t l0= (a&0x03030303UL)\ - + (b&0x03030303UL)\ - + 0x01010101UL;\ - uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - uint32_t l1,h1;\ -\ - pixels+=line_size;\ - for(i=0; i>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ - pixels+=line_size;\ - block +=line_size;\ - a= AV_RN32(pixels );\ - b= AV_RN32(pixels+1);\ - l0= (a&0x03030303UL)\ - + (b&0x03030303UL)\ - + 0x01010101UL;\ - h0= ((a&0xFCFCFCFCUL)>>2)\ - + ((b&0xFCFCFCFCUL)>>2);\ - OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ - pixels+=line_size;\ - block +=line_size;\ - }\ - pixels+=4-line_size*(h+1);\ - block +=4-line_size*h;\ - }\ -}\ -\ -CALL_2X_PIXELS(FUNCC(OPNAME ## _pixels16_x2) , FUNCC(OPNAME ## _pixels8_x2) , 8*sizeof(pixel))\ -CALL_2X_PIXELS(FUNCC(OPNAME ## _pixels16_y2) , FUNCC(OPNAME ## _pixels8_y2) , 8*sizeof(pixel))\ -CALL_2X_PIXELS(FUNCC(OPNAME ## _pixels16_xy2), FUNCC(OPNAME ## _pixels8_xy2), 8*sizeof(pixel))\ -av_unused CALL_2X_PIXELS(FUNCC(OPNAME ## _no_rnd_pixels16) , FUNCC(OPNAME ## _pixels8) , 8*sizeof(pixel))\ -CALL_2X_PIXELS(FUNCC(OPNAME ## _no_rnd_pixels16_x2) , FUNCC(OPNAME ## _no_rnd_pixels8_x2) , 8*sizeof(pixel))\ -CALL_2X_PIXELS(FUNCC(OPNAME ## _no_rnd_pixels16_y2) , FUNCC(OPNAME ## _no_rnd_pixels8_y2) , 8*sizeof(pixel))\ -CALL_2X_PIXELS(FUNCC(OPNAME ## _no_rnd_pixels16_xy2), FUNCC(OPNAME ## _no_rnd_pixels8_xy2), 8*sizeof(pixel))\ - -#define op_avg(a, b) a = rnd_avg_pixel4(a, b) -#define op_put(a, b) a = b -#if BIT_DEPTH == 8 -#define put_no_rnd_pixels8_8_c put_pixels8_8_c -PIXOP2(avg, op_avg) -PIXOP2(put, op_put) -#endif -#undef op_avg -#undef op_put diff --git a/libavcodec/huffman.c b/libavcodec/huffman.c index d126e8ba3..2866eef31 100644 --- a/libavcodec/huffman.c +++ b/libavcodec/huffman.c @@ -52,12 +52,14 @@ static void heap_sift(HeapElem *h, int root, int size) } } -int ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats, int size) +int ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats, int stats_size, int skip0) { - HeapElem *h = av_malloc(sizeof(*h) * size); - int *up = av_malloc(sizeof(*up) * 2 * size); - uint8_t *len = av_malloc(sizeof(*len) * 2 * size); + HeapElem *h = av_malloc_array(sizeof(*h), stats_size); + int *up = av_malloc_array(sizeof(*up) * 2, stats_size); + uint8_t *len = av_malloc_array(sizeof(*len) * 2, stats_size); + uint16_t *map= av_malloc_array(sizeof(*map), stats_size); int offset, i, next; + int size = 0; int ret = 0; if (!h || !up || !len) { @@ -65,10 +67,16 @@ int ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats, int size) goto end; } + for (i = 0; i= 0; i--) heap_sift(h, i, size); @@ -89,8 +97,8 @@ int ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats, int size) for (i = 2 * size - 3; i >= size; i--) len[i] = len[up[i]] + 1; for (i = 0; i < size; i++) { - dst[i] = len[up[i]] + 1; - if (dst[i] >= 32) break; + dst[map[i]] = len[up[i]] + 1; + if (dst[map[i]] >= 32) break; } if (i==size) break; } @@ -98,6 +106,7 @@ end: av_free(h); av_free(up); av_free(len); + av_free(map); return ret; } diff --git a/libavcodec/huffman.h b/libavcodec/huffman.h index b1ace6220..6ab23ae21 100644 --- a/libavcodec/huffman.h +++ b/libavcodec/huffman.h @@ -43,6 +43,6 @@ typedef int (*HuffCmp)(const void *va, const void *vb); int ff_huff_build_tree(AVCodecContext *avctx, VLC *vlc, int nb_codes, int nb_bits, Node *nodes, HuffCmp cmp, int flags); -int ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats, int n); +int ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats, int n, int skip0); #endif /* AVCODEC_HUFFMAN_H */ diff --git a/libavcodec/huffyuv.c b/libavcodec/huffyuv.c index 386653518..492155550 100644 --- a/libavcodec/huffyuv.c +++ b/libavcodec/huffyuv.c @@ -33,6 +33,7 @@ #include "libavutil/mem.h" #include "avcodec.h" +#include "bswapdsp.h" #include "huffyuv.h" int ff_huffyuv_generate_bits_table(uint32_t *dst, const uint8_t *len_table, int n) @@ -74,7 +75,7 @@ av_cold void ff_huffyuv_common_init(AVCodecContext *avctx) s->avctx = avctx; s->flags = avctx->flags; - ff_dsputil_init(&s->dsp, avctx); + ff_bswapdsp_init(&s->bdsp); ff_llviddsp_init(&s->llviddsp, avctx); s->width = avctx->width; diff --git a/libavcodec/huffyuv.h b/libavcodec/huffyuv.h index da4e3b5a1..2b3a1b33e 100644 --- a/libavcodec/huffyuv.h +++ b/libavcodec/huffyuv.h @@ -32,29 +32,19 @@ #include #include "avcodec.h" -#include "dsputil.h" +#include "bswapdsp.h" #include "get_bits.h" +#include "huffyuvdsp.h" +#include "huffyuvencdsp.h" #include "put_bits.h" #include "lossless_videodsp.h" -#define VLC_BITS 11 +#define VLC_BITS 12 #define MAX_BITS 16 #define MAX_N (1<bits[p0][y] << len1) + s->bits[p][u]; symbols[i] = (y << 8) + (u & 0xFF); - if(symbols[i] != 0xffff) // reserved to mean "invalid" i++; } } @@ -265,6 +267,7 @@ static av_cold int decode_init(AVCodecContext *avctx) { HYuvContext *s = avctx->priv_data; + ff_huffyuvdsp_init(&s->hdsp); memset(s->vlc, 0, 4 * sizeof(VLC)); s->interlaced = avctx->height > 288; @@ -557,62 +560,97 @@ static av_cold int decode_init_thread_copy(AVCodecContext *avctx) return 0; } -/* TODO instead of restarting the read when the code isn't in the first level - * of the joint table, jump into the 2nd level of the individual table. */ -#define READ_2PIX(dst0, dst1, plane1){\ - uint16_t code = get_vlc2(&s->gb, s->vlc[4+plane1].table, VLC_BITS, 1);\ - if(code != 0xffff){\ - dst0 = code>>8;\ - dst1 = code;\ - }else{\ - dst0 = get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3);\ - dst1 = get_vlc2(&s->gb, s->vlc[plane1].table, VLC_BITS, 3);\ - }\ -} +/** Subset of GET_VLC for use in hand-roller VLC code */ +#define VLC_INTERN(dst, table, gb, name, bits, max_depth) \ + code = table[index][0]; \ + n = table[index][1]; \ + if (max_depth > 1 && n < 0) { \ + LAST_SKIP_BITS(name, gb, bits); \ + UPDATE_CACHE(name, gb); \ + \ + nb_bits = -n; \ + index = SHOW_UBITS(name, gb, nb_bits) + code; \ + code = table[index][0]; \ + n = table[index][1]; \ + if (max_depth > 2 && n < 0) { \ + LAST_SKIP_BITS(name, gb, nb_bits); \ + UPDATE_CACHE(name, gb); \ + \ + nb_bits = -n; \ + index = SHOW_UBITS(name, gb, nb_bits) + code; \ + code = table[index][0]; \ + n = table[index][1]; \ + } \ + } \ + dst = code; \ + LAST_SKIP_BITS(name, gb, n) + + +#define GET_VLC_DUAL(dst0, dst1, name, gb, dtable, table1, table2, \ + bits, max_depth, OP) \ + do { \ + unsigned int index = SHOW_UBITS(name, gb, bits); \ + int code, n = dtable[index][1]; \ + \ + if (n<=0) { \ + int nb_bits; \ + VLC_INTERN(dst0, table1, gb, name, bits, max_depth); \ + \ + UPDATE_CACHE(re, gb); \ + index = SHOW_UBITS(name, gb, bits); \ + VLC_INTERN(dst1, table2, gb, name, bits, max_depth); \ + } else { \ + code = dtable[index][0]; \ + OP(dst0, dst1, code); \ + LAST_SKIP_BITS(name, gb, n); \ + } \ + } while (0) + +#define OP8bits(dst0, dst1, code) dst0 = code>>8; dst1 = code + +#define READ_2PIX(dst0, dst1, plane1)\ + UPDATE_CACHE(re, &s->gb); \ + GET_VLC_DUAL(dst0, dst1, re, &s->gb, s->vlc[4+plane1].table, \ + s->vlc[0].table, s->vlc[plane1].table, VLC_BITS, 3, OP8bits) static void decode_422_bitstream(HYuvContext *s, int count) { - int i; - + int i, icount; + OPEN_READER(re, &s->gb); count /= 2; - if (count >= (get_bits_left(&s->gb)) / (31 * 4)) { - for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) { + icount = get_bits_left(&s->gb) / (32 * 4); + if (count >= icount) { + for (i = 0; i < icount; i++) { READ_2PIX(s->temp[0][2 * i ], s->temp[1][i], 1); READ_2PIX(s->temp[0][2 * i + 1], s->temp[2][i], 2); } + for (; i < count && get_bits_left(&s->gb) > 0; i++) { + READ_2PIX(s->temp[0][2 * i ], s->temp[1][i], 1); + if (get_bits_left(&s->gb) <= 0) break; + READ_2PIX(s->temp[0][2 * i + 1], s->temp[2][i], 2); + } for (; i < count; i++) s->temp[0][2 * i ] = s->temp[1][i] = - s->temp[0][2 * i + 1] = s->temp[2][i] = 128; + s->temp[0][2 * i + 1] = s->temp[2][i] = 0; } else { for (i = 0; i < count; i++) { READ_2PIX(s->temp[0][2 * i ], s->temp[1][i], 1); READ_2PIX(s->temp[0][2 * i + 1], s->temp[2][i], 2); } } + CLOSE_READER(re, &s->gb); } -#define READ_2PIX_PLANE(dst0, dst1, plane){\ - uint16_t code = get_vlc2(&s->gb, s->vlc[4+plane].table, VLC_BITS, 1);\ - if(code != 0xffff){\ - dst0 = code>>8;\ - dst1 = code;\ - }else{\ - dst0 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\ - dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\ - }\ -} -#define READ_2PIX_PLANE14(dst0, dst1, plane){\ - int16_t code = get_vlc2(&s->gb, s->vlc[4+plane].table, VLC_BITS, 1);\ - if(code != (int16_t)0xffff){\ - dst0 = code>>8;\ - dst1 = sign_extend(code, 8);\ - }else{\ - dst0 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\ - dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\ - }\ -} +#define READ_2PIX_PLANE(dst0, dst1, plane, OP) \ + UPDATE_CACHE(re, &s->gb); \ + GET_VLC_DUAL(dst0, dst1, re, &s->gb, s->vlc[4+plane].table, \ + s->vlc[plane].table, s->vlc[plane].table, VLC_BITS, 3, OP) +#define OP14bits(dst0, dst1, code) dst0 = code>>8; dst1 = sign_extend(code, 8) + +/* TODO instead of restarting the read when the code isn't in the first level + * of the joint table, jump into the 2nd level of the individual table. */ #define READ_2PIX_PLANE16(dst0, dst1, plane){\ dst0 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3)<<2;\ dst0 += get_bits(&s->gb, 2);\ @@ -626,27 +664,31 @@ static void decode_plane_bitstream(HYuvContext *s, int count, int plane) count/=2; if (s->bps <= 8) { - if (count >= (get_bits_left(&s->gb)) / (31 * 2)) { + OPEN_READER(re, &s->gb); + if (count >= (get_bits_left(&s->gb)) / (32 * 2)) { for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) { - READ_2PIX_PLANE(s->temp[0][2 * i], s->temp[0][2 * i + 1], plane); + READ_2PIX_PLANE(s->temp[0][2 * i], s->temp[0][2 * i + 1], plane, OP8bits); } } else { for(i=0; itemp[0][2 * i], s->temp[0][2 * i + 1], plane); + READ_2PIX_PLANE(s->temp[0][2 * i], s->temp[0][2 * i + 1], plane, OP8bits); } } + CLOSE_READER(re, &s->gb); } else if (s->bps <= 14) { - if (count >= (get_bits_left(&s->gb)) / (31 * 2)) { + OPEN_READER(re, &s->gb); + if (count >= (get_bits_left(&s->gb)) / (32 * 2)) { for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) { - READ_2PIX_PLANE14(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane); + READ_2PIX_PLANE(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane, OP14bits); } } else { for(i=0; itemp16[0][2 * i], s->temp16[0][2 * i + 1], plane); + READ_2PIX_PLANE(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane, OP14bits); } } + CLOSE_READER(re, &s->gb); } else { - if (count >= (get_bits_left(&s->gb)) / (31 * 2)) { + if (count >= (get_bits_left(&s->gb)) / (32 * 2)) { for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) { READ_2PIX_PLANE16(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane); } @@ -661,10 +703,10 @@ static void decode_plane_bitstream(HYuvContext *s, int count, int plane) static void decode_gray_bitstream(HYuvContext *s, int count) { int i; - + OPEN_READER(re, &s->gb); count/=2; - if (count >= (get_bits_left(&s->gb)) / (31 * 2)) { + if (count >= (get_bits_left(&s->gb)) / (32 * 2)) { for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) { READ_2PIX(s->temp[0][2 * i], s->temp[0][2 * i + 1], 0); } @@ -673,30 +715,66 @@ static void decode_gray_bitstream(HYuvContext *s, int count) READ_2PIX(s->temp[0][2 * i], s->temp[0][2 * i + 1], 0); } } + CLOSE_READER(re, &s->gb); } static av_always_inline void decode_bgr_1(HYuvContext *s, int count, int decorrelate, int alpha) { int i; - for (i = 0; i < count; i++) { - int code = get_vlc2(&s->gb, s->vlc[4].table, VLC_BITS, 1); - if (code != -1) { + OPEN_READER(re, &s->gb); + + for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) { + unsigned int index; + int code, n; + + UPDATE_CACHE(re, &s->gb); + index = SHOW_UBITS(re, &s->gb, VLC_BITS); + n = s->vlc[4].table[index][1]; + + if (n>0) { + code = s->vlc[4].table[index][0]; *(uint32_t*)&s->temp[0][4 * i] = s->pix_bgr_map[code]; - } else if(decorrelate) { - s->temp[0][4 * i + G] = get_vlc2(&s->gb, s->vlc[1].table, VLC_BITS, 3); - s->temp[0][4 * i + B] = get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3) + - s->temp[0][4 * i + G]; - s->temp[0][4 * i + R] = get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3) + - s->temp[0][4 * i + G]; + LAST_SKIP_BITS(re, &s->gb, n); } else { - s->temp[0][4 * i + B] = get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3); - s->temp[0][4 * i + G] = get_vlc2(&s->gb, s->vlc[1].table, VLC_BITS, 3); - s->temp[0][4 * i + R] = get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3); + int nb_bits; + if(decorrelate) { + VLC_INTERN(s->temp[0][4 * i + G], s->vlc[1].table, + &s->gb, re, VLC_BITS, 3); + + UPDATE_CACHE(re, &s->gb); + index = SHOW_UBITS(re, &s->gb, VLC_BITS); + VLC_INTERN(code, s->vlc[0].table, &s->gb, re, VLC_BITS, 3); + s->temp[0][4 * i + B] = code + s->temp[0][4 * i + G]; + + UPDATE_CACHE(re, &s->gb); + index = SHOW_UBITS(re, &s->gb, VLC_BITS); + VLC_INTERN(code, s->vlc[2].table, &s->gb, re, VLC_BITS, 3); + s->temp[0][4 * i + R] = code + s->temp[0][4 * i + G]; + } else { + VLC_INTERN(s->temp[0][4 * i + B], s->vlc[0].table, + &s->gb, re, VLC_BITS, 3); + + UPDATE_CACHE(re, &s->gb); + index = SHOW_UBITS(re, &s->gb, VLC_BITS); + VLC_INTERN(s->temp[0][4 * i + G], s->vlc[1].table, + &s->gb, re, VLC_BITS, 3); + + UPDATE_CACHE(re, &s->gb); + index = SHOW_UBITS(re, &s->gb, VLC_BITS); + VLC_INTERN(s->temp[0][4 * i + R], s->vlc[2].table, + &s->gb, re, VLC_BITS, 3); + } + if (alpha) { + UPDATE_CACHE(re, &s->gb); + index = SHOW_UBITS(re, &s->gb, VLC_BITS); + VLC_INTERN(s->temp[0][4 * i + A], s->vlc[2].table, + &s->gb, re, VLC_BITS, 3); + } else + s->temp[0][4 * i + A] = 0; } - if (alpha) - s->temp[0][4 * i + A] = get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3); } + CLOSE_READER(re, &s->gb); } static void decode_bgr_bitstream(HYuvContext *s, int count) @@ -746,16 +824,16 @@ static void draw_slice(HYuvContext *s, AVFrame *frame, int y) static int left_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *src, int w, int acc) { if (s->bps <= 8) { - return s->dsp.add_hfyu_left_prediction(dst, src, w, acc); + return s->hdsp.add_hfyu_left_pred(dst, src, w, acc); } else { - return s->llviddsp.add_hfyu_left_prediction_int16(( uint16_t *)dst, (const uint16_t *)src, s->n-1, w, acc); + return s->llviddsp.add_hfyu_left_pred_int16(( uint16_t *)dst, (const uint16_t *)src, s->n-1, w, acc); } } static void add_bytes(HYuvContext *s, uint8_t *dst, uint8_t *src, int w) { if (s->bps <= 8) { - s->dsp.add_bytes(dst, src, w); + s->hdsp.add_bytes(dst, src, w); } else { s->llviddsp.add_int16((uint16_t*)dst, (const uint16_t*)src, s->n - 1, w); } @@ -764,9 +842,9 @@ static void add_bytes(HYuvContext *s, uint8_t *dst, uint8_t *src, int w) static void add_median_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *src, const uint8_t *diff, int w, int *left, int *left_top) { if (s->bps <= 8) { - s->dsp.add_hfyu_median_prediction(dst, src, diff, w, left, left_top); + s->hdsp.add_hfyu_median_pred(dst, src, diff, w, left, left_top); } else { - s->llviddsp.add_hfyu_median_prediction_int16((uint16_t *)dst, (const uint16_t *)src, (const uint16_t *)diff, s->n-1, w, left, left_top); + s->llviddsp.add_hfyu_median_pred_int16((uint16_t *)dst, (const uint16_t *)src, (const uint16_t *)diff, s->n-1, w, left, left_top); } } static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, @@ -789,8 +867,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (!s->bitstream_buffer) return AVERROR(ENOMEM); - s->dsp.bswap_buf((uint32_t*)s->bitstream_buffer, - (const uint32_t*)buf, buf_size / 4); + s->bdsp.bswap_buf((uint32_t *) s->bitstream_buffer, + (const uint32_t *) buf, buf_size / 4); if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; @@ -903,10 +981,10 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, case LEFT: case PLANE: decode_422_bitstream(s, width-2); - lefty = s->dsp.add_hfyu_left_prediction(p->data[0] + 2, s->temp[0], width-2, lefty); + lefty = s->hdsp.add_hfyu_left_pred(p->data[0] + 2, s->temp[0], width - 2, lefty); if (!(s->flags&CODEC_FLAG_GRAY)) { - leftu = s->dsp.add_hfyu_left_prediction(p->data[1] + 1, s->temp[1], width2 - 1, leftu); - leftv = s->dsp.add_hfyu_left_prediction(p->data[2] + 1, s->temp[2], width2 - 1, leftv); + 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); } for (cy = y = 1; y < s->height; y++, cy++) { @@ -917,10 +995,10 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, ydst = p->data[0] + p->linesize[0] * y; - lefty = s->dsp.add_hfyu_left_prediction(ydst, s->temp[0], width, lefty); + lefty = s->hdsp.add_hfyu_left_pred(ydst, s->temp[0], width, lefty); if (s->predictor == PLANE) { if (y > s->interlaced) - s->dsp.add_bytes(ydst, ydst - fake_ystride, width); + s->hdsp.add_bytes(ydst, ydst - fake_ystride, width); } y++; if (y >= s->height) break; @@ -933,17 +1011,17 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, vdst = p->data[2] + p->linesize[2]*cy; decode_422_bitstream(s, width); - lefty = s->dsp.add_hfyu_left_prediction(ydst, s->temp[0], width, lefty); + lefty = s->hdsp.add_hfyu_left_pred(ydst, s->temp[0], width, lefty); if (!(s->flags & CODEC_FLAG_GRAY)) { - leftu= s->dsp.add_hfyu_left_prediction(udst, s->temp[1], width2, leftu); - leftv= s->dsp.add_hfyu_left_prediction(vdst, s->temp[2], width2, leftv); + 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->dsp.add_bytes(ydst, ydst - fake_ystride, width); + s->hdsp.add_bytes(ydst, ydst - fake_ystride, width); if (!(s->flags & CODEC_FLAG_GRAY)) { - s->dsp.add_bytes(udst, udst - fake_ustride, width2); - s->dsp.add_bytes(vdst, vdst - fake_vstride, width2); + s->hdsp.add_bytes(udst, udst - fake_ustride, width2); + s->hdsp.add_bytes(vdst, vdst - fake_vstride, width2); } } } @@ -954,10 +1032,10 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, case MEDIAN: /* first line except first 2 pixels is left predicted */ decode_422_bitstream(s, width - 2); - lefty= s->dsp.add_hfyu_left_prediction(p->data[0] + 2, s->temp[0], width - 2, lefty); + lefty = s->hdsp.add_hfyu_left_pred(p->data[0] + 2, s->temp[0], width - 2, lefty); if (!(s->flags & CODEC_FLAG_GRAY)) { - leftu = s->dsp.add_hfyu_left_prediction(p->data[1] + 1, s->temp[1], width2 - 1, leftu); - leftv = s->dsp.add_hfyu_left_prediction(p->data[2] + 1, s->temp[2], width2 - 1, leftv); + 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); } cy = y = 1; @@ -965,31 +1043,31 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, /* second line is left predicted for interlaced case */ if (s->interlaced) { decode_422_bitstream(s, width); - lefty = s->dsp.add_hfyu_left_prediction(p->data[0] + p->linesize[0], s->temp[0], width, lefty); + lefty = s->hdsp.add_hfyu_left_pred(p->data[0] + p->linesize[0], s->temp[0], width, lefty); if (!(s->flags & CODEC_FLAG_GRAY)) { - leftu = s->dsp.add_hfyu_left_prediction(p->data[1] + p->linesize[2], s->temp[1], width2, leftu); - leftv = s->dsp.add_hfyu_left_prediction(p->data[2] + p->linesize[1], s->temp[2], width2, leftv); + 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); } y++; cy++; } /* next 4 pixels are left predicted too */ decode_422_bitstream(s, 4); - lefty = s->dsp.add_hfyu_left_prediction(p->data[0] + fake_ystride, s->temp[0], 4, lefty); + lefty = s->hdsp.add_hfyu_left_pred(p->data[0] + fake_ystride, s->temp[0], 4, lefty); if (!(s->flags&CODEC_FLAG_GRAY)) { - leftu = s->dsp.add_hfyu_left_prediction(p->data[1] + fake_ustride, s->temp[1], 2, leftu); - leftv = s->dsp.add_hfyu_left_prediction(p->data[2] + fake_vstride, s->temp[2], 2, leftv); + 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); } /* next line except the first 4 pixels is median predicted */ lefttopy = p->data[0][3]; decode_422_bitstream(s, width - 4); - s->dsp.add_hfyu_median_prediction(p->data[0] + fake_ystride+4, p->data[0]+4, s->temp[0], width-4, &lefty, &lefttopy); + 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)) { lefttopu = p->data[1][1]; lefttopv = p->data[2][1]; - s->dsp.add_hfyu_median_prediction(p->data[1] + fake_ustride+2, p->data[1] + 2, s->temp[1], width2 - 2, &leftu, &lefttopu); - s->dsp.add_hfyu_median_prediction(p->data[2] + fake_vstride+2, p->data[2] + 2, s->temp[2], width2 - 2, &leftv, &lefttopv); + s->hdsp.add_hfyu_median_pred(p->data[1] + fake_ustride + 2, p->data[1] + 2, s->temp[1], width2 - 2, &leftu, &lefttopu); + s->hdsp.add_hfyu_median_pred(p->data[2] + fake_vstride + 2, p->data[2] + 2, s->temp[2], width2 - 2, &leftv, &lefttopv); } y++; cy++; @@ -1000,7 +1078,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, while (2 * cy > y) { decode_gray_bitstream(s, width); ydst = p->data[0] + p->linesize[0] * y; - s->dsp.add_hfyu_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); + s->hdsp.add_hfyu_median_pred(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); y++; } if (y >= height) break; @@ -1013,10 +1091,10 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, udst = p->data[1] + p->linesize[1] * cy; vdst = p->data[2] + p->linesize[2] * cy; - s->dsp.add_hfyu_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); + s->hdsp.add_hfyu_median_pred(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); if (!(s->flags & CODEC_FLAG_GRAY)) { - s->dsp.add_hfyu_median_prediction(udst, udst - fake_ustride, s->temp[1], width2, &leftu, &lefttopu); - s->dsp.add_hfyu_median_prediction(vdst, vdst - fake_vstride, s->temp[2], width2, &leftv, &lefttopv); + 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); } } @@ -1026,19 +1104,19 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } } else { int y; - int leftr, leftg, leftb, lefta; + uint8_t left[4]; const int last_line = (height - 1) * p->linesize[0]; if (s->bitstream_bpp == 32) { - lefta = p->data[0][last_line+A] = get_bits(&s->gb, 8); - leftr = p->data[0][last_line+R] = get_bits(&s->gb, 8); - leftg = p->data[0][last_line+G] = get_bits(&s->gb, 8); - leftb = p->data[0][last_line+B] = get_bits(&s->gb, 8); + left[A] = p->data[0][last_line+A] = get_bits(&s->gb, 8); + left[R] = p->data[0][last_line+R] = get_bits(&s->gb, 8); + left[G] = p->data[0][last_line+G] = get_bits(&s->gb, 8); + left[B] = p->data[0][last_line+B] = get_bits(&s->gb, 8); } else { - leftr = p->data[0][last_line+R] = get_bits(&s->gb, 8); - leftg = p->data[0][last_line+G] = get_bits(&s->gb, 8); - leftb = p->data[0][last_line+B] = get_bits(&s->gb, 8); - lefta = p->data[0][last_line+A] = 255; + left[R] = p->data[0][last_line+R] = get_bits(&s->gb, 8); + left[G] = p->data[0][last_line+G] = get_bits(&s->gb, 8); + left[B] = p->data[0][last_line+B] = get_bits(&s->gb, 8); + left[A] = p->data[0][last_line+A] = 255; skip_bits(&s->gb, 8); } @@ -1047,19 +1125,19 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, case LEFT: case PLANE: decode_bgr_bitstream(s, width - 1); - s->dsp.add_hfyu_left_prediction_bgr32(p->data[0] + last_line+4, s->temp[0], width - 1, &leftr, &leftg, &leftb, &lefta); + s->hdsp.add_hfyu_left_pred_bgr32(p->data[0] + last_line + 4, s->temp[0], width - 1, left); for (y = s->height - 2; y >= 0; y--) { //Yes it is stored upside down. decode_bgr_bitstream(s, width); - s->dsp.add_hfyu_left_prediction_bgr32(p->data[0] + p->linesize[0]*y, s->temp[0], width, &leftr, &leftg, &leftb, &lefta); + s->hdsp.add_hfyu_left_pred_bgr32(p->data[0] + p->linesize[0] * y, s->temp[0], width, left); if (s->predictor == PLANE) { - if (s->bitstream_bpp != 32) lefta = 0; + if (s->bitstream_bpp != 32) left[A] = 0; if ((y & s->interlaced) == 0 && y < s->height - 1 - s->interlaced) { - s->dsp.add_bytes(p->data[0] + p->linesize[0] * y, - p->data[0] + p->linesize[0] * y + - fake_ystride, fake_ystride); + s->hdsp.add_bytes(p->data[0] + p->linesize[0] * y, + p->data[0] + p->linesize[0] * y + + fake_ystride, fake_ystride); } } } @@ -1098,7 +1176,6 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -#if CONFIG_HUFFYUV_DECODER AVCodec ff_huffyuv_decoder = { .name = "huffyuv", .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), @@ -1112,7 +1189,6 @@ AVCodec ff_huffyuv_decoder = { CODEC_CAP_FRAME_THREADS, .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), }; -#endif #if CONFIG_FFVHUFF_DECODER AVCodec ff_ffvhuff_decoder = { diff --git a/libavcodec/huffyuvdsp.c b/libavcodec/huffyuvdsp.c new file mode 100644 index 000000000..e8a05f659 --- /dev/null +++ b/libavcodec/huffyuvdsp.c @@ -0,0 +1,117 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "mathops.h" +#include "huffyuvdsp.h" + +// 0x7f7f7f7f or 0x7f7f7f7f7f7f7f7f or whatever, depending on the cpu's native arithmetic size +#define pb_7f (~0UL / 255 * 0x7f) +#define pb_80 (~0UL / 255 * 0x80) + +static void add_bytes_c(uint8_t *dst, uint8_t *src, intptr_t w) +{ + long i; + + for (i = 0; i <= w - (int) sizeof(long); i += sizeof(long)) { + long a = *(long *) (src + i); + long b = *(long *) (dst + i); + *(long *) (dst + i) = ((a & pb_7f) + (b & pb_7f)) ^ ((a ^ b) & pb_80); + } + for (; i < w; i++) + dst[i + 0] += src[i + 0]; +} + +static void add_hfyu_median_pred_c(uint8_t *dst, const uint8_t *src1, + const uint8_t *diff, intptr_t w, + int *left, int *left_top) +{ + int i; + uint8_t l, lt; + + l = *left; + lt = *left_top; + + for (i = 0; i < w; i++) { + l = mid_pred(l, src1[i], (l + src1[i] - lt) & 0xFF) + diff[i]; + lt = src1[i]; + dst[i] = l; + } + + *left = l; + *left_top = lt; +} + +static int add_hfyu_left_pred_c(uint8_t *dst, const uint8_t *src, intptr_t w, + int acc) +{ + int i; + + for (i = 0; i < w - 1; i++) { + acc += src[i]; + dst[i] = acc; + i++; + acc += src[i]; + dst[i] = acc; + } + + for (; i < w; i++) { + acc += src[i]; + dst[i] = acc; + } + + return acc; +} + +static void add_hfyu_left_pred_bgr32_c(uint8_t *dst, const uint8_t *src, + intptr_t w, uint8_t *left) +{ + int i; + uint8_t r = left[R], g = left[G], b = left[B], a = left[A]; + + for (i = 0; i < w; i++) { + b += src[4 * i + B]; + g += src[4 * i + G]; + r += src[4 * i + R]; + a += src[4 * i + A]; + + dst[4 * i + B] = b; + dst[4 * i + G] = g; + dst[4 * i + R] = r; + dst[4 * i + A] = a; + } + + left[B] = b; + left[G] = g; + left[R] = r; + left[A] = a; +} + +av_cold void ff_huffyuvdsp_init(HuffYUVDSPContext *c) +{ + c->add_bytes = add_bytes_c; + c->add_hfyu_median_pred = add_hfyu_median_pred_c; + c->add_hfyu_left_pred = add_hfyu_left_pred_c; + c->add_hfyu_left_pred_bgr32 = add_hfyu_left_pred_bgr32_c; + + if (ARCH_X86) + ff_huffyuvdsp_init_x86(c); +} diff --git a/libavcodec/huffyuvdsp.h b/libavcodec/huffyuvdsp.h new file mode 100644 index 000000000..78b2bca13 --- /dev/null +++ b/libavcodec/huffyuvdsp.h @@ -0,0 +1,52 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HUFFYUVDSP_H +#define AVCODEC_HUFFYUVDSP_H + +#include + +#if HAVE_BIGENDIAN +#define B 3 +#define G 2 +#define R 1 +#define A 0 +#else +#define B 0 +#define G 1 +#define R 2 +#define A 3 +#endif + +typedef struct HuffYUVDSPContext { + void (*add_bytes)(uint8_t *dst /* align 16 */, uint8_t *src /* align 16 */, + intptr_t w); + void (*add_hfyu_median_pred)(uint8_t *dst, const uint8_t *top, + const uint8_t *diff, intptr_t w, + int *left, int *left_top); + int (*add_hfyu_left_pred)(uint8_t *dst, const uint8_t *src, + intptr_t w, int left); + void (*add_hfyu_left_pred_bgr32)(uint8_t *dst, const uint8_t *src, + intptr_t w, uint8_t *left); +} HuffYUVDSPContext; + +void ff_huffyuvdsp_init(HuffYUVDSPContext *c); +void ff_huffyuvdsp_init_ppc(HuffYUVDSPContext *c); +void ff_huffyuvdsp_init_x86(HuffYUVDSPContext *c); + +#endif /* AVCODEC_HUFFYUVDSP_H */ diff --git a/libavcodec/huffyuvenc.c b/libavcodec/huffyuvenc.c index aa5e2cbb2..8d72b6328 100644 --- a/libavcodec/huffyuvenc.c +++ b/libavcodec/huffyuvenc.c @@ -31,6 +31,7 @@ #include "avcodec.h" #include "huffyuv.h" #include "huffman.h" +#include "huffyuvencdsp.h" #include "internal.h" #include "put_bits.h" #include "libavutil/pixdesc.h" @@ -39,7 +40,7 @@ static inline void diff_bytes(HYuvContext *s, uint8_t *dst, const uint8_t *src0, const uint8_t *src1, int w) { if (s->bps <= 8) { - s->dsp.diff_bytes(dst, src0, src1, w); + s->hencdsp.diff_bytes(dst, src0, src1, w); } else { s->llviddsp.diff_int16((uint16_t *)dst, (const uint16_t *)src0, (const uint16_t *)src1, s->n - 1, w); } @@ -63,7 +64,7 @@ static inline int sub_left_prediction(HYuvContext *s, uint8_t *dst, dst[i] = temp - left; left = temp; } - s->dsp.diff_bytes(dst + 16, src + 16, src + 15, w - 16); + s->hencdsp.diff_bytes(dst + 16, src + 16, src + 15, w - 16); return src[w-1]; } } else { @@ -115,7 +116,7 @@ static inline void sub_left_prediction_bgr32(HYuvContext *s, uint8_t *dst, a = at; } - s->dsp.diff_bytes(dst + 16, src + 16, src + 12, w * 4 - 16); + s->hencdsp.diff_bytes(dst + 16, src + 16, src + 12, w * 4 - 16); *red = src[(w - 1) * 4 + R]; *green = src[(w - 1) * 4 + G]; @@ -144,7 +145,7 @@ static inline void sub_left_prediction_rgb24(HYuvContext *s, uint8_t *dst, b = bt; } - s->dsp.diff_bytes(dst + 48, src + 48, src + 48 - 3, w * 3 - 48); + s->hencdsp.diff_bytes(dst + 48, src + 48, src + 48 - 3, w * 3 - 48); *red = src[(w - 1) * 3 + 0]; *green = src[(w - 1) * 3 + 1]; @@ -154,9 +155,9 @@ static inline void sub_left_prediction_rgb24(HYuvContext *s, uint8_t *dst, static void sub_median_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int w, int *left, int *left_top) { if (s->bps <= 8) { - s->dsp.sub_hfyu_median_prediction(dst, src1, src2, w , left, left_top); + s->hencdsp.sub_hfyu_median_pred(dst, src1, src2, w , left, left_top); } else { - s->llviddsp.sub_hfyu_median_prediction_int16((uint16_t *)dst, (const uint16_t *)src1, (const uint16_t *)src2, s->n - 1, w , left, left_top); + s->llviddsp.sub_hfyu_median_pred_int16((uint16_t *)dst, (const uint16_t *)src1, (const uint16_t *)src2, s->n - 1, w , left, left_top); } } @@ -195,7 +196,7 @@ static int store_huffman_tables(HYuvContext *s, uint8_t *buf) count = 1 + s->alpha + 2*s->chroma; for (i = 0; i < count; i++) { - if ((ret = ff_huff_gen_len_table(s->len[i], s->stats[i], s->vlc_n)) < 0) + if ((ret = ff_huff_gen_len_table(s->len[i], s->stats[i], s->vlc_n, 0)) < 0) return ret; if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i], s->vlc_n) < 0) { @@ -215,6 +216,7 @@ static av_cold int encode_init(AVCodecContext *avctx) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); ff_huffyuv_common_init(avctx); + ff_huffyuvencdsp_init(&s->hencdsp); avctx->extradata = av_mallocz(3*MAX_N + 4); if (!avctx->extradata) @@ -345,8 +347,8 @@ static av_cold int encode_init(AVCodecContext *avctx) "using huffyuv 2.2.0 or newer interlacing flag\n"); } - if (s->version > 2 && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { - av_log(avctx, AV_LOG_ERROR, "Ver > 2 is under development, files encoded with it may not be decodable with future versions!!!\n" + if (s->version > 3 && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + av_log(avctx, AV_LOG_ERROR, "Ver > 3 is under development, files encoded with it may not be decodable with future versions!!!\n" "Use vstrict=-2 / -strict -2 to use it anyway.\n"); return AVERROR(EINVAL); } @@ -398,7 +400,7 @@ static av_cold int encode_init(AVCodecContext *avctx) for (j = 0; j < s->vlc_n; j++) { int d = FFMIN(j, s->vlc_n - j); - s->stats[i][j] = 100000000 / (d + 1); + s->stats[i][j] = 100000000 / (d*d + 1); } } @@ -412,7 +414,7 @@ static av_cold int encode_init(AVCodecContext *avctx) int pels = s->width * s->height / (i ? 40 : 10); for (j = 0; j < s->vlc_n; j++) { int d = FFMIN(j, s->vlc_n - j); - s->stats[i][j] = pels/(d + 1); + s->stats[i][j] = pels/(d*d + 1); } } } else { @@ -754,9 +756,9 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, lefttopy = p->data[0][3]; lefttopu = p->data[1][1]; lefttopv = p->data[2][1]; - s->dsp.sub_hfyu_median_prediction(s->temp[0], p->data[0]+4, p->data[0] + fake_ystride + 4, width - 4 , &lefty, &lefttopy); - s->dsp.sub_hfyu_median_prediction(s->temp[1], p->data[1]+2, p->data[1] + fake_ustride + 2, width2 - 2, &leftu, &lefttopu); - s->dsp.sub_hfyu_median_prediction(s->temp[2], p->data[2]+2, p->data[2] + fake_vstride + 2, width2 - 2, &leftv, &lefttopv); + s->hencdsp.sub_hfyu_median_pred(s->temp[0], p->data[0] + 4, p->data[0] + fake_ystride + 4, width - 4, &lefty, &lefttopy); + s->hencdsp.sub_hfyu_median_pred(s->temp[1], p->data[1] + 2, p->data[1] + fake_ustride + 2, width2 - 2, &leftu, &lefttopu); + s->hencdsp.sub_hfyu_median_pred(s->temp[2], p->data[2] + 2, p->data[2] + fake_vstride + 2, width2 - 2, &leftv, &lefttopv); encode_422_bitstream(s, 0, width - 4); y++; cy++; @@ -766,7 +768,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (s->bitstream_bpp == 12) { while (2 * cy > y) { ydst = p->data[0] + p->linesize[0] * y; - s->dsp.sub_hfyu_median_prediction(s->temp[0], ydst - fake_ystride, ydst, width , &lefty, &lefttopy); + s->hencdsp.sub_hfyu_median_pred(s->temp[0], ydst - fake_ystride, ydst, width, &lefty, &lefttopy); encode_gray_bitstream(s, width); y++; } @@ -776,9 +778,9 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, udst = p->data[1] + p->linesize[1] * cy; vdst = p->data[2] + p->linesize[2] * cy; - s->dsp.sub_hfyu_median_prediction(s->temp[0], ydst - fake_ystride, ydst, width , &lefty, &lefttopy); - s->dsp.sub_hfyu_median_prediction(s->temp[1], udst - fake_ustride, udst, width2, &leftu, &lefttopu); - s->dsp.sub_hfyu_median_prediction(s->temp[2], vdst - fake_vstride, vdst, width2, &leftv, &lefttopv); + s->hencdsp.sub_hfyu_median_pred(s->temp[0], ydst - fake_ystride, ydst, width, &lefty, &lefttopy); + s->hencdsp.sub_hfyu_median_pred(s->temp[1], udst - fake_ustride, udst, width2, &leftu, &lefttopu); + s->hencdsp.sub_hfyu_median_pred(s->temp[2], vdst - fake_vstride, vdst, width2, &leftv, &lefttopv); encode_422_bitstream(s, 0, width); } @@ -791,7 +793,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, ydst = p->data[0] + p->linesize[0] * y; if (s->predictor == PLANE && s->interlaced < y) { - s->dsp.diff_bytes(s->temp[1], ydst, ydst - fake_ystride, width); + s->hencdsp.diff_bytes(s->temp[1], ydst, ydst - fake_ystride, width); lefty = sub_left_prediction(s, s->temp[0], s->temp[1], width , lefty); } else { @@ -807,9 +809,9 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, vdst = p->data[2] + p->linesize[2] * cy; if (s->predictor == PLANE && s->interlaced < cy) { - s->dsp.diff_bytes(s->temp[1], ydst, ydst - fake_ystride, width); - s->dsp.diff_bytes(s->temp[2], udst, udst - fake_ustride, width2); - s->dsp.diff_bytes(s->temp[2] + width2, vdst, vdst - fake_vstride, width2); + s->hencdsp.diff_bytes(s->temp[1], ydst, ydst - fake_ystride, width); + s->hencdsp.diff_bytes(s->temp[2], udst, udst - fake_ustride, width2); + s->hencdsp.diff_bytes(s->temp[2] + width2, vdst, vdst - fake_vstride, width2); lefty = sub_left_prediction(s, s->temp[0], s->temp[1], width , lefty); leftu = sub_left_prediction(s, s->temp[1], s->temp[2], width2, leftu); @@ -842,7 +844,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, for (y = 1; y < s->height; y++) { uint8_t *dst = data + y*stride; if (s->predictor == PLANE && s->interlaced < y) { - s->dsp.diff_bytes(s->temp[1], dst, dst - fake_stride, width * 4); + s->hencdsp.diff_bytes(s->temp[1], dst, dst - fake_stride, width * 4); sub_left_prediction_bgr32(s, s->temp[0], s->temp[1], width, &leftr, &leftg, &leftb, &lefta); } else { @@ -870,8 +872,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, for (y = 1; y < s->height; y++) { uint8_t *dst = data + y * stride; if (s->predictor == PLANE && s->interlaced < y) { - s->dsp.diff_bytes(s->temp[1], dst, dst - fake_stride, - width * 3); + s->hencdsp.diff_bytes(s->temp[1], dst, dst - fake_stride, + width * 3); sub_left_prediction_rgb24(s, s->temp[0], s->temp[1], width, &leftr, &leftg, &leftb); } else { @@ -962,7 +964,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, avctx->stats_out[0] = '\0'; if (!(s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)) { flush_put_bits(&s->pb); - s->dsp.bswap_buf((uint32_t*)pkt->data, (uint32_t*)pkt->data, size); + s->bdsp.bswap_buf((uint32_t *) pkt->data, (uint32_t *) pkt->data, size); } s->picture_number++; @@ -988,7 +990,6 @@ static av_cold int encode_end(AVCodecContext *avctx) return 0; } -#if CONFIG_HUFFYUV_ENCODER AVCodec ff_huffyuv_encoder = { .name = "huffyuv", .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), @@ -1004,7 +1005,6 @@ AVCodec ff_huffyuv_encoder = { AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE }, }; -#endif #if CONFIG_FFVHUFF_ENCODER AVCodec ff_ffvhuff_encoder = { diff --git a/libavcodec/huffyuvencdsp.c b/libavcodec/huffyuvencdsp.c new file mode 100644 index 000000000..95fcc1958 --- /dev/null +++ b/libavcodec/huffyuvencdsp.c @@ -0,0 +1,84 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/attributes.h" +#include "huffyuvencdsp.h" +#include "mathops.h" + +// 0x7f7f7f7f or 0x7f7f7f7f7f7f7f7f or whatever, depending on the cpu's native arithmetic size +#define pb_7f (~0UL / 255 * 0x7f) +#define pb_80 (~0UL / 255 * 0x80) + +static void diff_bytes_c(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int w) +{ + long i; + +#if !HAVE_FAST_UNALIGNED + if (((long)src1 | (long)src2) & (sizeof(long) - 1)) { + for (i = 0; i + 7 < w; i += 8) { + dst[i + 0] = src1[i + 0] - src2[i + 0]; + dst[i + 1] = src1[i + 1] - src2[i + 1]; + dst[i + 2] = src1[i + 2] - src2[i + 2]; + dst[i + 3] = src1[i + 3] - src2[i + 3]; + dst[i + 4] = src1[i + 4] - src2[i + 4]; + dst[i + 5] = src1[i + 5] - src2[i + 5]; + dst[i + 6] = src1[i + 6] - src2[i + 6]; + dst[i + 7] = src1[i + 7] - src2[i + 7]; + } + } else +#endif + for (i = 0; i <= w - (int) sizeof(long); i += sizeof(long)) { + long a = *(long *) (src1 + i); + long b = *(long *) (src2 + i); + *(long *) (dst + i) = ((a | pb_80) - (b & pb_7f)) ^ + ((a ^ b ^ pb_80) & pb_80); + } + for (; i < w; i++) + dst[i + 0] = src1[i + 0] - src2[i + 0]; +} + +static void sub_hfyu_median_pred_c(uint8_t *dst, const uint8_t *src1, + const uint8_t *src2, int w, + int *left, int *left_top) +{ + int i; + uint8_t l, lt; + + l = *left; + lt = *left_top; + + for (i = 0; i < w; i++) { + const int pred = mid_pred(l, src1[i], (l + src1[i] - lt) & 0xFF); + lt = src1[i]; + l = src2[i]; + dst[i] = l - pred; + } + + *left = l; + *left_top = lt; +} + +av_cold void ff_huffyuvencdsp_init(HuffYUVEncDSPContext *c) +{ + c->diff_bytes = diff_bytes_c; + c->sub_hfyu_median_pred = sub_hfyu_median_pred_c; + + if (ARCH_X86) + ff_huffyuvencdsp_init_x86(c); +} diff --git a/libavcodec/huffyuvencdsp.h b/libavcodec/huffyuvencdsp.h new file mode 100644 index 000000000..3a49b4a7e --- /dev/null +++ b/libavcodec/huffyuvencdsp.h @@ -0,0 +1,41 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HUFFYUVENCDSP_H +#define AVCODEC_HUFFYUVENCDSP_H + +#include + +typedef struct HuffYUVEncDSPContext { + void (*diff_bytes)(uint8_t *dst /* align 16 */, + const uint8_t *src1 /* align 16 */, + const uint8_t *src2 /* align 1 */, + int w); + /** + * Subtract HuffYUV's variant of median prediction. + * Note, this might read from src1[-1], src2[-1]. + */ + void (*sub_hfyu_median_pred)(uint8_t *dst, const uint8_t *src1, + const uint8_t *src2, int w, + int *left, int *left_top); +} HuffYUVEncDSPContext; + +void ff_huffyuvencdsp_init(HuffYUVEncDSPContext *c); +void ff_huffyuvencdsp_init_x86(HuffYUVEncDSPContext *c); + +#endif /* AVCODEC_HUFFYUVENCDSP_H */ diff --git a/libavcodec/idctdsp.c b/libavcodec/idctdsp.c new file mode 100644 index 000000000..31a4854cc --- /dev/null +++ b/libavcodec/idctdsp.c @@ -0,0 +1,313 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "avcodec.h" +#include "dct.h" +#include "faanidct.h" +#include "idctdsp.h" +#include "simple_idct.h" + +av_cold void ff_init_scantable(uint8_t *permutation, ScanTable *st, + const uint8_t *src_scantable) +{ + int i, end; + + st->scantable = src_scantable; + + for (i = 0; i < 64; i++) { + int j = src_scantable[i]; + st->permutated[i] = permutation[j]; + } + + end = -1; + for (i = 0; i < 64; i++) { + int j = st->permutated[i]; + if (j > end) + end = j; + st->raster_end[i] = end; + } +} + +av_cold void ff_init_scantable_permutation(uint8_t *idct_permutation, + int idct_permutation_type) +{ + int i; + + if (ARCH_X86) + if (ff_init_scantable_permutation_x86(idct_permutation, + idct_permutation_type)) + return; + + switch (idct_permutation_type) { + case FF_NO_IDCT_PERM: + for (i = 0; i < 64; i++) + idct_permutation[i] = i; + break; + case FF_LIBMPEG2_IDCT_PERM: + for (i = 0; i < 64; i++) + idct_permutation[i] = (i & 0x38) | ((i & 6) >> 1) | ((i & 1) << 2); + break; + case FF_TRANSPOSE_IDCT_PERM: + for (i = 0; i < 64; i++) + idct_permutation[i] = ((i & 7) << 3) | (i >> 3); + break; + case FF_PARTTRANS_IDCT_PERM: + for (i = 0; i < 64; i++) + idct_permutation[i] = (i & 0x24) | ((i & 3) << 3) | ((i >> 3) & 3); + break; + default: + av_log(NULL, AV_LOG_ERROR, + "Internal error, IDCT permutation not set\n"); + } +} + +static void put_pixels_clamped_c(const int16_t *block, uint8_t *av_restrict pixels, + int line_size) +{ + int i; + + /* read the pixels */ + for (i = 0; i < 8; i++) { + pixels[0] = av_clip_uint8(block[0]); + pixels[1] = av_clip_uint8(block[1]); + pixels[2] = av_clip_uint8(block[2]); + pixels[3] = av_clip_uint8(block[3]); + pixels[4] = av_clip_uint8(block[4]); + pixels[5] = av_clip_uint8(block[5]); + pixels[6] = av_clip_uint8(block[6]); + pixels[7] = av_clip_uint8(block[7]); + + pixels += line_size; + block += 8; + } +} + +static void put_pixels_clamped4_c(const int16_t *block, uint8_t *av_restrict pixels, + int line_size) +{ + int i; + + /* read the pixels */ + for(i=0;i<4;i++) { + pixels[0] = av_clip_uint8(block[0]); + pixels[1] = av_clip_uint8(block[1]); + pixels[2] = av_clip_uint8(block[2]); + pixels[3] = av_clip_uint8(block[3]); + + pixels += line_size; + block += 8; + } +} + +static void put_pixels_clamped2_c(const int16_t *block, uint8_t *av_restrict pixels, + int line_size) +{ + int i; + + /* read the pixels */ + for(i=0;i<2;i++) { + pixels[0] = av_clip_uint8(block[0]); + pixels[1] = av_clip_uint8(block[1]); + + pixels += line_size; + block += 8; + } +} + +static void put_signed_pixels_clamped_c(const int16_t *block, + uint8_t *av_restrict pixels, + int line_size) +{ + int i, j; + + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + if (*block < -128) + *pixels = 0; + else if (*block > 127) + *pixels = 255; + else + *pixels = (uint8_t) (*block + 128); + block++; + pixels++; + } + pixels += (line_size - 8); + } +} + +static void add_pixels_clamped_c(const int16_t *block, uint8_t *av_restrict pixels, + int line_size) +{ + int i; + + /* read the pixels */ + for (i = 0; i < 8; i++) { + pixels[0] = av_clip_uint8(pixels[0] + block[0]); + pixels[1] = av_clip_uint8(pixels[1] + block[1]); + pixels[2] = av_clip_uint8(pixels[2] + block[2]); + pixels[3] = av_clip_uint8(pixels[3] + block[3]); + pixels[4] = av_clip_uint8(pixels[4] + block[4]); + pixels[5] = av_clip_uint8(pixels[5] + block[5]); + pixels[6] = av_clip_uint8(pixels[6] + block[6]); + pixels[7] = av_clip_uint8(pixels[7] + block[7]); + pixels += line_size; + block += 8; + } +} + +static void add_pixels_clamped4_c(const int16_t *block, uint8_t *av_restrict pixels, + int line_size) +{ + int i; + + /* read the pixels */ + for(i=0;i<4;i++) { + pixels[0] = av_clip_uint8(pixels[0] + block[0]); + pixels[1] = av_clip_uint8(pixels[1] + block[1]); + pixels[2] = av_clip_uint8(pixels[2] + block[2]); + pixels[3] = av_clip_uint8(pixels[3] + block[3]); + pixels += line_size; + block += 8; + } +} + +static void add_pixels_clamped2_c(const int16_t *block, uint8_t *av_restrict pixels, + int line_size) +{ + int i; + + /* read the pixels */ + for(i=0;i<2;i++) { + pixels[0] = av_clip_uint8(pixels[0] + block[0]); + pixels[1] = av_clip_uint8(pixels[1] + block[1]); + pixels += line_size; + block += 8; + } +} + +static 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); +} +static void ff_jref_idct4_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct4 (block); + put_pixels_clamped4_c(block, dest, line_size); +} +static void ff_jref_idct4_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct4 (block); + add_pixels_clamped4_c(block, dest, line_size); +} + +static void ff_jref_idct2_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct2 (block); + put_pixels_clamped2_c(block, dest, line_size); +} +static void ff_jref_idct2_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct2 (block); + add_pixels_clamped2_c(block, dest, line_size); +} + +static void ff_jref_idct1_put(uint8_t *dest, int line_size, int16_t *block) +{ + dest[0] = av_clip_uint8((block[0] + 4)>>3); +} +static void ff_jref_idct1_add(uint8_t *dest, int line_size, int16_t *block) +{ + dest[0] = av_clip_uint8(dest[0] + ((block[0] + 4)>>3)); +} + +av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) +{ + const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; + + if (avctx->lowres==1) { + c->idct_put = ff_jref_idct4_put; + c->idct_add = ff_jref_idct4_add; + c->idct = ff_j_rev_dct4; + c->idct_permutation_type = FF_NO_IDCT_PERM; + } else if (avctx->lowres==2) { + c->idct_put = ff_jref_idct2_put; + c->idct_add = ff_jref_idct2_add; + c->idct = ff_j_rev_dct2; + c->idct_permutation_type = FF_NO_IDCT_PERM; + } else if (avctx->lowres==3) { + c->idct_put = ff_jref_idct1_put; + c->idct_add = ff_jref_idct1_add; + c->idct = ff_j_rev_dct1; + c->idct_permutation_type = FF_NO_IDCT_PERM; + } else { + if (avctx->bits_per_raw_sample == 10) { + c->idct_put = ff_simple_idct_put_10; + c->idct_add = ff_simple_idct_add_10; + c->idct = ff_simple_idct_10; + c->idct_permutation_type = FF_NO_IDCT_PERM; + } else if (avctx->bits_per_raw_sample == 12) { + c->idct_put = ff_simple_idct_put_12; + c->idct_add = ff_simple_idct_add_12; + c->idct = ff_simple_idct_12; + c->idct_permutation_type = FF_NO_IDCT_PERM; + } else { + if (avctx->idct_algo == FF_IDCT_INT) { + c->idct_put = jref_idct_put; + c->idct_add = jref_idct_add; + c->idct = ff_j_rev_dct; + c->idct_permutation_type = FF_LIBMPEG2_IDCT_PERM; + } else if (avctx->idct_algo == FF_IDCT_FAAN) { + c->idct_put = ff_faanidct_put; + c->idct_add = ff_faanidct_add; + c->idct = ff_faanidct; + c->idct_permutation_type = FF_NO_IDCT_PERM; + } else { // accurate/default + c->idct_put = ff_simple_idct_put_8; + c->idct_add = ff_simple_idct_add_8; + c->idct = ff_simple_idct_8; + c->idct_permutation_type = FF_NO_IDCT_PERM; + } + } + } + + c->put_pixels_clamped = put_pixels_clamped_c; + c->put_signed_pixels_clamped = put_signed_pixels_clamped_c; + c->add_pixels_clamped = add_pixels_clamped_c; + + if (ARCH_ALPHA) + ff_idctdsp_init_alpha(c, avctx, high_bit_depth); + if (ARCH_ARM) + ff_idctdsp_init_arm(c, avctx, high_bit_depth); + if (ARCH_PPC) + ff_idctdsp_init_ppc(c, avctx, high_bit_depth); + if (ARCH_X86) + ff_idctdsp_init_x86(c, avctx, high_bit_depth); + + ff_init_scantable_permutation(c->idct_permutation, + c->idct_permutation_type); +} diff --git a/libavcodec/idctdsp.h b/libavcodec/idctdsp.h new file mode 100644 index 000000000..b1fa6e29c --- /dev/null +++ b/libavcodec/idctdsp.h @@ -0,0 +1,106 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_IDCTDSP_H +#define AVCODEC_IDCTDSP_H + +#include + +#include "avcodec.h" + +/** + * Scantable. + */ +typedef struct ScanTable { + const uint8_t *scantable; + uint8_t permutated[64]; + uint8_t raster_end[64]; +} ScanTable; + +void ff_init_scantable(uint8_t *permutation, ScanTable *st, + const uint8_t *src_scantable); +void ff_init_scantable_permutation(uint8_t *idct_permutation, + int idct_permutation_type); +int ff_init_scantable_permutation_x86(uint8_t *idct_permutation, + int idct_permutation_type); + +typedef struct IDCTDSPContext { + /* pixel ops : interface with DCT */ + void (*put_pixels_clamped)(const int16_t *block /* align 16 */, + uint8_t *pixels /* align 8 */, + int line_size); + void (*put_signed_pixels_clamped)(const int16_t *block /* align 16 */, + uint8_t *pixels /* align 8 */, + int line_size); + void (*add_pixels_clamped)(const int16_t *block /* align 16 */, + uint8_t *pixels /* align 8 */, + int line_size); + + void (*idct)(int16_t *block /* align 16 */); + + /** + * block -> idct -> clip to unsigned 8 bit -> dest. + * (-1392, 0, 0, ...) -> idct -> (-174, -174, ...) -> put -> (0, 0, ...) + * @param line_size size in bytes of a horizontal line of dest + */ + void (*idct_put)(uint8_t *dest /* align 8 */, + int line_size, int16_t *block /* align 16 */); + + /** + * block -> idct -> add dest -> clip to unsigned 8 bit -> dest. + * @param line_size size in bytes of a horizontal line of dest + */ + void (*idct_add)(uint8_t *dest /* align 8 */, + int line_size, int16_t *block /* align 16 */); + + /** + * IDCT input permutation. + * Several optimized IDCTs need a permutated input (relative to the + * normal order of the reference IDCT). + * This permutation must be performed before the idct_put/add. + * Note, normally this can be merged with the zigzag/alternate scan
+ * An example to avoid confusion: + * - (->decode coeffs -> zigzag reorder -> dequant -> reference IDCT -> ...) + * - (x -> reference DCT -> reference IDCT -> x) + * - (x -> reference DCT -> simple_mmx_perm = idct_permutation + * -> simple_idct_mmx -> x) + * - (-> decode coeffs -> zigzag reorder -> simple_mmx_perm -> dequant + * -> simple_idct_mmx -> ...) + */ + uint8_t idct_permutation[64]; + int idct_permutation_type; +#define FF_NO_IDCT_PERM 1 +#define FF_LIBMPEG2_IDCT_PERM 2 +#define FF_SIMPLE_IDCT_PERM 3 +#define FF_TRANSPOSE_IDCT_PERM 4 +#define FF_PARTTRANS_IDCT_PERM 5 +#define FF_SSE2_IDCT_PERM 6 +} IDCTDSPContext; + +void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx); + +void ff_idctdsp_init_alpha(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); +void ff_idctdsp_init_arm(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); +void ff_idctdsp_init_ppc(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); +void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); + +#endif /* AVCODEC_IDCTDSP_H */ diff --git a/libavcodec/imc.c b/libavcodec/imc.c index cbd7041de..e6a087ada 100644 --- a/libavcodec/imc.c +++ b/libavcodec/imc.c @@ -40,8 +40,8 @@ #include "libavutil/internal.h" #include "libavutil/libm.h" #include "avcodec.h" +#include "bswapdsp.h" #include "get_bits.h" -#include "dsputil.h" #include "fft.h" #include "internal.h" #include "sinewin.h" @@ -95,7 +95,7 @@ typedef struct { float sqrt_tab[30]; GetBitContext gb; - DSPContext dsp; + BswapDSPContext bdsp; AVFloatDSPContext fdsp; FFTContext fft; DECLARE_ALIGNED(32, FFTComplex, samples)[COEFFS / 2]; @@ -247,7 +247,7 @@ static av_cold int imc_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_INFO, "FFT init failed\n"); return ret; } - ff_dsputil_init(&q->dsp, avctx); + ff_bswapdsp_init(&q->bdsp); avpriv_float_dsp_init(&q->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO @@ -1025,7 +1025,7 @@ static int imc_decode_frame(AVCodecContext *avctx, void *data, for (i = 0; i < avctx->channels; i++) { q->out_samples = (float *)frame->extended_data[i]; - q->dsp.bswap16_buf(buf16, (const uint16_t*)buf, IMC_BLOCK_SIZE / 2); + q->bdsp.bswap16_buf(buf16, (const uint16_t *) buf, IMC_BLOCK_SIZE / 2); init_get_bits(&q->gb, (const uint8_t*)buf16, IMC_BLOCK_SIZE * 8); diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c index ee58cfb49..27c984a67 100644 --- a/libavcodec/imgconvert.c +++ b/libavcodec/imgconvert.c @@ -31,25 +31,15 @@ */ #include "avcodec.h" -#include "dsputil.h" #include "imgconvert.h" #include "internal.h" +#include "mathops.h" #include "libavutil/avassert.h" #include "libavutil/colorspace.h" #include "libavutil/common.h" #include "libavutil/pixdesc.h" #include "libavutil/imgutils.h" -#if HAVE_MMX_EXTERNAL -#include "x86/dsputil_x86.h" -#endif - -#define FF_COLOR_NA -1 -#define FF_COLOR_RGB 0 /**< RGB color space */ -#define FF_COLOR_GRAY 1 /**< gray color space */ -#define FF_COLOR_YUV 2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */ -#define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */ - #if HAVE_MMX_EXTERNAL #define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx #define deinterlace_line ff_deinterlace_line_mmx @@ -58,10 +48,6 @@ #define deinterlace_line deinterlace_line_c #endif -#define pixdesc_has_alpha(pixdesc) \ - ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & AV_PIX_FMT_FLAG_PAL) - - void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); @@ -70,184 +56,17 @@ void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift = desc->log2_chroma_h; } -static int get_color_type(const AVPixFmtDescriptor *desc) { - if (desc->flags & AV_PIX_FMT_FLAG_PAL) - return FF_COLOR_RGB; - - if(desc->nb_components == 1 || desc->nb_components == 2) - return FF_COLOR_GRAY; - - if(desc->name && !strncmp(desc->name, "yuvj", 4)) - return FF_COLOR_YUV_JPEG; - - if(desc->flags & AV_PIX_FMT_FLAG_RGB) - return FF_COLOR_RGB; - - if(desc->nb_components == 0) - return FF_COLOR_NA; - - return FF_COLOR_YUV; -} - -static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - int i; - - if (!desc || !desc->nb_components) { - *min = *max = 0; - return AVERROR(EINVAL); - } - - *min = INT_MAX, *max = -INT_MAX; - for (i = 0; i < desc->nb_components; i++) { - *min = FFMIN(desc->comp[i].depth_minus1+1, *min); - *max = FFMAX(desc->comp[i].depth_minus1+1, *max); - } - return 0; -} - -static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt, - enum AVPixelFormat src_pix_fmt, - unsigned *lossp, unsigned consider) -{ - const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt); - const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt); - int src_color, dst_color; - int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth; - int ret, loss, i, nb_components; - int score = INT_MAX - 1; - - if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE) - return ~0; - - /* compute loss */ - *lossp = loss = 0; - - if (dst_pix_fmt == src_pix_fmt) - return INT_MAX; - - if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0) - return ret; - if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0) - return ret; - - src_color = get_color_type(src_desc); - dst_color = get_color_type(dst_desc); - nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components); - - for (i = 0; i < nb_components; i++) - if (src_desc->comp[i].depth_minus1 > dst_desc->comp[i].depth_minus1 && (consider & FF_LOSS_DEPTH)) { - loss |= FF_LOSS_DEPTH; - score -= 65536 >> dst_desc->comp[i].depth_minus1; - } - - if (consider & FF_LOSS_RESOLUTION) { - if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w) { - loss |= FF_LOSS_RESOLUTION; - score -= 256 << dst_desc->log2_chroma_w; - } - if (dst_desc->log2_chroma_h > src_desc->log2_chroma_h) { - loss |= FF_LOSS_RESOLUTION; - score -= 256 << dst_desc->log2_chroma_h; - } - // don't favor 422 over 420 if downsampling is needed, because 420 has much better support on the decoder side - if (dst_desc->log2_chroma_w == 1 && src_desc->log2_chroma_w == 0 && - dst_desc->log2_chroma_h == 1 && src_desc->log2_chroma_h == 0 ) { - score += 512; - } - } - - if(consider & FF_LOSS_COLORSPACE) - switch(dst_color) { - case FF_COLOR_RGB: - if (src_color != FF_COLOR_RGB && - src_color != FF_COLOR_GRAY) - loss |= FF_LOSS_COLORSPACE; - break; - case FF_COLOR_GRAY: - if (src_color != FF_COLOR_GRAY) - loss |= FF_LOSS_COLORSPACE; - break; - case FF_COLOR_YUV: - if (src_color != FF_COLOR_YUV) - loss |= FF_LOSS_COLORSPACE; - break; - case FF_COLOR_YUV_JPEG: - if (src_color != FF_COLOR_YUV_JPEG && - src_color != FF_COLOR_YUV && - src_color != FF_COLOR_GRAY) - loss |= FF_LOSS_COLORSPACE; - break; - default: - /* fail safe test */ - if (src_color != dst_color) - loss |= FF_LOSS_COLORSPACE; - break; - } - if(loss & FF_LOSS_COLORSPACE) - score -= (nb_components * 65536) >> FFMIN(dst_desc->comp[0].depth_minus1, src_desc->comp[0].depth_minus1); - - if (dst_color == FF_COLOR_GRAY && - src_color != FF_COLOR_GRAY && (consider & FF_LOSS_CHROMA)) { - loss |= FF_LOSS_CHROMA; - score -= 2 * 65536; - } - if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))) { - loss |= FF_LOSS_ALPHA; - score -= 65536; - } - if (dst_pix_fmt == AV_PIX_FMT_PAL8 && (consider & FF_LOSS_COLORQUANT) && - (src_pix_fmt != AV_PIX_FMT_PAL8 && (src_color != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))))) { - loss |= FF_LOSS_COLORQUANT; - score -= 65536; - } - - *lossp = loss; - return score; -} - int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt, int has_alpha) { - int loss; - int ret = get_pix_fmt_score(dst_pix_fmt, src_pix_fmt, &loss, has_alpha ? ~0 : ~FF_LOSS_ALPHA); - if (ret < 0) - return ret; - return loss; + return av_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); } enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr) { - enum AVPixelFormat dst_pix_fmt; - int loss1, loss2, loss_mask; - const AVPixFmtDescriptor *desc1 = av_pix_fmt_desc_get(dst_pix_fmt1); - const AVPixFmtDescriptor *desc2 = av_pix_fmt_desc_get(dst_pix_fmt2); - int score1, score2; - - loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */ - if(!has_alpha) - loss_mask &= ~FF_LOSS_ALPHA; - - dst_pix_fmt = AV_PIX_FMT_NONE; - score1 = get_pix_fmt_score(dst_pix_fmt1, src_pix_fmt, &loss1, loss_mask); - score2 = get_pix_fmt_score(dst_pix_fmt2, src_pix_fmt, &loss2, loss_mask); - - if (score1 == score2) { - if(av_get_padded_bits_per_pixel(desc2) != av_get_padded_bits_per_pixel(desc1)) { - dst_pix_fmt = av_get_padded_bits_per_pixel(desc2) < av_get_padded_bits_per_pixel(desc1) ? dst_pix_fmt2 : dst_pix_fmt1; - } else { - dst_pix_fmt = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1; - } - } else { - dst_pix_fmt = score1 < score2 ? dst_pix_fmt2 : dst_pix_fmt1; - } - - if (loss_ptr) - *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); - return dst_pix_fmt; + return av_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr); } #if AV_HAVE_INCOMPATIBLE_LIBAV_ABI @@ -486,7 +305,7 @@ static void deinterlace_line_c(uint8_t *dst, const uint8_t *lum, int size) { - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; int sum; for(;size > 0;size--) { @@ -509,7 +328,7 @@ 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_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; int sum; for(;size > 0;size--) { @@ -656,7 +475,7 @@ int main(void){ av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip); skip = 0; } - av_log(NULL, AV_LOG_INFO, "pix fmt %s yuv_plan:%d avg_bpp:%d colortype:%d\n", desc->name, is_yuv_planar(desc), av_get_padded_bits_per_pixel(desc), get_color_type(desc)); + av_log(NULL, AV_LOG_INFO, "pix fmt %s yuv_plan:%d avg_bpp:%d\n", desc->name, is_yuv_planar(desc), av_get_padded_bits_per_pixel(desc)); if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) { av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n"); err = 1; diff --git a/libavcodec/imgconvert.h b/libavcodec/imgconvert.h index df8cee794..0ce626d7a 100644 --- a/libavcodec/imgconvert.h +++ b/libavcodec/imgconvert.h @@ -21,6 +21,24 @@ #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); diff --git a/libavcodec/indeo2.c b/libavcodec/indeo2.c index aabe348b4..cccac44bf 100644 --- a/libavcodec/indeo2.c +++ b/libavcodec/indeo2.c @@ -49,7 +49,7 @@ static inline int ir2_get_code(GetBitContext *gb) } static int ir2_decode_plane(Ir2Context *ctx, int width, int height, uint8_t *dst, - int stride, const uint8_t *table) + int pitch, const uint8_t *table) { int i; int j; @@ -74,7 +74,7 @@ static int ir2_decode_plane(Ir2Context *ctx, int width, int height, uint8_t *dst dst[out++] = table[(c * 2) + 1]; } } - dst += stride; + dst += pitch; for (j = 1; j < height; j++) { out = 0; @@ -85,27 +85,27 @@ static int ir2_decode_plane(Ir2Context *ctx, int width, int height, uint8_t *dst if (out + c*2 > width) return AVERROR_INVALIDDATA; for (i = 0; i < c * 2; i++) { - dst[out] = dst[out - stride]; + dst[out] = dst[out - pitch]; out++; } } else { /* add two deltas from table */ - t = dst[out - stride] + (table[c * 2] - 128); + t = dst[out - pitch] + (table[c * 2] - 128); t = av_clip_uint8(t); dst[out] = t; out++; - t = dst[out - stride] + (table[(c * 2) + 1] - 128); + t = dst[out - pitch] + (table[(c * 2) + 1] - 128); t = av_clip_uint8(t); dst[out] = t; out++; } } - dst += stride; + dst += pitch; } return 0; } static int ir2_decode_plane_inter(Ir2Context *ctx, int width, int height, uint8_t *dst, - int stride, const uint8_t *table) + int pitch, const uint8_t *table) { int j; int out = 0; @@ -133,7 +133,7 @@ static int ir2_decode_plane_inter(Ir2Context *ctx, int width, int height, uint8_ out++; } } - dst += stride; + dst += pitch; } return 0; } diff --git a/libavcodec/indeo4.c b/libavcodec/indeo4.c index 0774f82ce..ed4272bbe 100644 --- a/libavcodec/indeo4.c +++ b/libavcodec/indeo4.c @@ -34,19 +34,6 @@ #include "ivi_common.h" #include "indeo4data.h" -/** - * Indeo 4 frame types. - */ -enum { - FRAMETYPE_INTRA = 0, - FRAMETYPE_INTRA1 = 1, ///< intra frame with slightly different bitstream coding - FRAMETYPE_INTER = 2, ///< non-droppable P-frame - FRAMETYPE_BIDIR = 3, ///< bidirectional frame - FRAMETYPE_INTER_NOREF = 4, ///< droppable P-frame - FRAMETYPE_NULL_FIRST = 5, ///< empty frame with no data - FRAMETYPE_NULL_LAST = 6 ///< empty frame with no data -}; - #define IVI4_PIC_SIZE_ESC 7 @@ -132,7 +119,7 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx) } #if IVI4_STREAM_ANALYSER - if (ctx->frame_type == FRAMETYPE_BIDIR) + if (ctx->frame_type == IVI4_FRAMETYPE_BIDIR) ctx->has_b_frames = 1; #endif @@ -152,7 +139,7 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx) ctx->data_size = get_bits1(&ctx->gb) ? get_bits(&ctx->gb, 24) : 0; /* null frames don't contain anything else so we just return */ - if (ctx->frame_type >= FRAMETYPE_NULL_FIRST) { + if (ctx->frame_type >= IVI4_FRAMETYPE_NULL_FIRST) { av_dlog(avctx, "Null frame encountered!\n"); return 0; } @@ -208,7 +195,7 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx) /* check if picture layout was changed and reallocate buffers */ if (ivi_pic_config_cmp(&pic_conf, &ctx->pic_conf)) { - if (ff_ivi_init_planes(ctx->planes, &pic_conf)) { + if (ff_ivi_init_planes(ctx->planes, &pic_conf, 1)) { av_log(avctx, AV_LOG_ERROR, "Couldn't reallocate color planes!\n"); ctx->pic_conf.luma_bands = 0; return AVERROR(ENOMEM); @@ -329,7 +316,7 @@ static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *band, band->glob_quant = get_bits(&ctx->gb, 5); - if (!get_bits1(&ctx->gb) || ctx->frame_type == FRAMETYPE_INTRA) { + if (!get_bits1(&ctx->gb) || ctx->frame_type == IVI4_FRAMETYPE_INTRA) { transform_id = get_bits(&ctx->gb, 5); if (transform_id >= FF_ARRAY_ELEMS(transforms) || !transforms[transform_id].inv_trans) { @@ -489,7 +476,7 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band, offs = tile->ypos * band->pitch + tile->xpos; blks_per_mb = band->mb_size != band->blk_size ? 4 : 1; - mb_type_bits = ctx->frame_type == FRAMETYPE_BIDIR ? 2 : 1; + mb_type_bits = ctx->frame_type == IVI4_FRAMETYPE_BIDIR ? 2 : 1; /* scale factor for motion vectors */ mv_scale = (ctx->planes[0].bands[0].mb_size >> 3) - (band->mb_size >> 3); @@ -507,9 +494,11 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band, mb->xpos = x; mb->ypos = y; mb->buf_offs = mb_offset; + mb->b_mv_x = + mb->b_mv_y = 0; if (get_bits1(&ctx->gb)) { - if (ctx->frame_type == FRAMETYPE_INTRA) { + if (ctx->frame_type == IVI4_FRAMETYPE_INTRA) { av_log(avctx, AV_LOG_ERROR, "Empty macroblock in an INTRA picture!\n"); return AVERROR_INVALIDDATA; } @@ -542,8 +531,8 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band, return AVERROR_INVALIDDATA; } mb->type = ref_mb->type; - } else if (ctx->frame_type == FRAMETYPE_INTRA || - ctx->frame_type == FRAMETYPE_INTRA1) { + } else if (ctx->frame_type == IVI4_FRAMETYPE_INTRA || + ctx->frame_type == IVI4_FRAMETYPE_INTRA1) { mb->type = 0; /* mb_type is always INTRA for intra-frames */ } else { mb->type = get_bits(&ctx->gb, mb_type_bits); @@ -584,6 +573,24 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band, mv_x += IVI_TOSIGNED(mv_delta); mb->mv_x = mv_x; mb->mv_y = mv_y; + if (mb->type == 3) { + mv_delta = get_vlc2(&ctx->gb, + ctx->mb_vlc.tab->table, + IVI_VLC_BITS, 1); + mv_y += IVI_TOSIGNED(mv_delta); + mv_delta = get_vlc2(&ctx->gb, + ctx->mb_vlc.tab->table, + IVI_VLC_BITS, 1); + mv_x += IVI_TOSIGNED(mv_delta); + mb->b_mv_x = -mv_x; + mb->b_mv_y = -mv_y; + } + } + if (mb->type == 2) { + mb->b_mv_x = -mb->mv_x; + mb->b_mv_y = -mb->mv_y; + mb->mv_x = 0; + mb->mv_y = 0; } } } @@ -619,38 +626,36 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band, */ static void switch_buffers(IVI45DecContext *ctx) { + int is_prev_ref = 0, is_ref = 0; + switch (ctx->prev_frame_type) { - case FRAMETYPE_INTRA: - case FRAMETYPE_INTRA1: - case FRAMETYPE_INTER: - ctx->buf_switch ^= 1; - ctx->dst_buf = ctx->buf_switch; - ctx->ref_buf = ctx->buf_switch ^ 1; - break; - case FRAMETYPE_INTER_NOREF: + case IVI4_FRAMETYPE_INTRA: + case IVI4_FRAMETYPE_INTRA1: + case IVI4_FRAMETYPE_INTER: + is_prev_ref = 1; break; } switch (ctx->frame_type) { - case FRAMETYPE_INTRA: - case FRAMETYPE_INTRA1: - ctx->buf_switch = 0; - /* FALLTHROUGH */ - case FRAMETYPE_INTER: - ctx->dst_buf = ctx->buf_switch; - ctx->ref_buf = ctx->buf_switch ^ 1; - break; - case FRAMETYPE_INTER_NOREF: - case FRAMETYPE_NULL_FIRST: - case FRAMETYPE_NULL_LAST: + case IVI4_FRAMETYPE_INTRA: + case IVI4_FRAMETYPE_INTRA1: + case IVI4_FRAMETYPE_INTER: + is_ref = 1; break; } + + if (is_prev_ref && is_ref) { + FFSWAP(int, ctx->dst_buf, ctx->ref_buf); + } else if (is_prev_ref) { + FFSWAP(int, ctx->ref_buf, ctx->b_ref_buf); + FFSWAP(int, ctx->dst_buf, ctx->ref_buf); + } } static int is_nonnull_frame(IVI45DecContext *ctx) { - return ctx->frame_type < FRAMETYPE_NULL_FIRST; + return ctx->frame_type < IVI4_FRAMETYPE_NULL_FIRST; } @@ -676,6 +681,15 @@ static av_cold int decode_init(AVCodecContext *avctx) ctx->switch_buffers = switch_buffers; ctx->is_nonnull_frame = is_nonnull_frame; + ctx->is_indeo4 = 1; + + ctx->dst_buf = 0; + ctx->ref_buf = 1; + ctx->b_ref_buf = 3; /* buffer 2 is used for scalability mode */ + ctx->p_frame = av_frame_alloc(); + if (!ctx->p_frame) + return AVERROR(ENOMEM); + return 0; } diff --git a/libavcodec/indeo4data.h b/libavcodec/indeo4data.h index 0ea4f405a..d96ee9850 100644 --- a/libavcodec/indeo4data.h +++ b/libavcodec/indeo4data.h @@ -28,8 +28,9 @@ #define AVCODEC_INDEO4DATA_H #include -#include "dsputil.h" + #include "ivi_common.h" +#include "mathops.h" /** * standard picture dimensions diff --git a/libavcodec/indeo5.c b/libavcodec/indeo5.c index e48cb4340..71a54d59e 100644 --- a/libavcodec/indeo5.c +++ b/libavcodec/indeo5.c @@ -30,7 +30,6 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" -#include "dsputil.h" #include "ivi_dsp.h" #include "ivi_common.h" #include "indeo5data.h" @@ -114,7 +113,7 @@ static int decode_gop_header(IVI45DecContext *ctx, AVCodecContext *avctx) /* check if picture layout was changed and reallocate buffers */ if (ivi_pic_config_cmp(&pic_conf, &ctx->pic_conf) || ctx->gop_invalid) { - result = ff_ivi_init_planes(ctx->planes, &pic_conf); + result = ff_ivi_init_planes(ctx->planes, &pic_conf, 0); if (result < 0) { av_log(avctx, AV_LOG_ERROR, "Couldn't reallocate color planes!\n"); return result; @@ -290,14 +289,18 @@ static int decode_gop_header(IVI45DecContext *ctx, AVCodecContext *avctx) * * @param[in,out] gb the GetBit context */ -static inline void skip_hdr_extension(GetBitContext *gb) +static inline int skip_hdr_extension(GetBitContext *gb) { int i, len; do { len = get_bits(gb, 8); + if (8*len > get_bits_left(gb)) + return AVERROR_INVALIDDATA; for (i = 0; i < len; i++) skip_bits(gb, 8); } while(len); + + return 0; } @@ -336,7 +339,7 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx) } if (ctx->frame_type == FRAMETYPE_INTER_SCAL && !ctx->is_scalable) { - av_log(avctx, AV_LOG_ERROR, "Scalable inter frame in non scaleable stream\n"); + av_log(avctx, AV_LOG_ERROR, "Scalable inter frame in non scalable stream\n"); ctx->frame_type = FRAMETYPE_INTER; return AVERROR_INVALIDDATA; } @@ -654,7 +657,7 @@ static av_cold int decode_init(AVCodecContext *avctx) ctx->pic_conf.tile_height = avctx->height; ctx->pic_conf.luma_bands = ctx->pic_conf.chroma_bands = 1; - result = ff_ivi_init_planes(ctx->planes, &ctx->pic_conf); + result = ff_ivi_init_planes(ctx->planes, &ctx->pic_conf, 0); if (result) { av_log(avctx, AV_LOG_ERROR, "Couldn't allocate color planes!\n"); return AVERROR_INVALIDDATA; @@ -669,6 +672,8 @@ static av_cold int decode_init(AVCodecContext *avctx) ctx->switch_buffers = switch_buffers; ctx->is_nonnull_frame = is_nonnull_frame; + ctx->is_indeo4 = 0; + avctx->pix_fmt = AV_PIX_FMT_YUV410P; return 0; diff --git a/libavcodec/intelh263dec.c b/libavcodec/intelh263dec.c index 5da420243..5ed1cdba7 100644 --- a/libavcodec/intelh263dec.c +++ b/libavcodec/intelh263dec.c @@ -26,6 +26,10 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s) { int format; + if (get_bits_left(&s->gb) == 64) { /* special dummy frames */ + return FRAME_SKIPPED; + } + /* picture header */ if (get_bits_long(&s->gb, 22) != 0x20) { av_log(s->avctx, AV_LOG_ERROR, "Bad picture start code\n"); @@ -133,5 +137,8 @@ AVCodec ff_h263i_decoder = { .close = ff_h263_decode_end, .decode = ff_h263_decode_frame, .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, - .pix_fmts = ff_pixfmt_list_420, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, }; diff --git a/libavcodec/internal.h b/libavcodec/internal.h index d300dcdd6..e00aad943 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -35,7 +35,9 @@ #define FF_SANE_NB_CHANNELS 63U -#if HAVE_NEON || ARCH_PPC || HAVE_MMX +#if HAVE_AVX +# define STRIDE_ALIGN 32 +#elif HAVE_NEON || ARCH_PPC || HAVE_MMX # define STRIDE_ALIGN 16 #else # define STRIDE_ALIGN 8 @@ -122,6 +124,11 @@ typedef struct AVCodecInternal { * Number of audio samples to skip at the start of the next decoded frame */ int skip_samples; + + /** + * hwaccel-specific private data + */ + void *hwaccel_priv_data; } AVCodecInternal; struct AVCodecDefault { @@ -129,14 +136,7 @@ struct AVCodecDefault { const uint8_t *value; }; -/** - * Return the hardware accelerated codec for codec codec_id and - * pixel format pix_fmt. - * - * @param avctx The codec context containing the codec_id and pixel format. - * @return the hardware accelerated codec, or NULL if none was found. - */ -AVHWAccel *ff_find_hwaccel(AVCodecContext *avctx); +extern const uint8_t ff_log2_run[41]; /** * Return the index into tab at which {a,b} match elements {[0],[1]} of tab. @@ -225,11 +225,6 @@ int avpriv_h264_has_num_reorder_frames(AVCodecContext *avctx); */ int ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); -/** - * Call avcodec_close recursively, counterpart to avcodec_open2_recursive. - */ -int ff_codec_close_recursive(AVCodecContext *avctx); - /** * Finalize buf into extradata and set its size appropriately. */ @@ -245,10 +240,28 @@ const uint8_t *avpriv_find_start_code(const uint8_t *p, */ int ff_set_dimensions(AVCodecContext *s, int width, int height); +/** + * Check that the provided sample aspect ratio is valid and set it on the codec + * context. + */ +int ff_set_sar(AVCodecContext *avctx, AVRational sar); + /** * Add or update AV_FRAME_DATA_MATRIXENCODING side data. */ int ff_side_data_update_matrix_encoding(AVFrame *frame, enum AVMatrixEncoding matrix_encoding); +/** + * Select the (possibly hardware accelerated) pixel format. + * This is a wrapper around AVCodecContext.get_format() and should be used + * instead of calling get_format() directly. + */ +int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt); + +/** + * Set various frame properties from the codec context / packet data. + */ +int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame); + #endif /* AVCODEC_INTERNAL_H */ diff --git a/libavcodec/intrax8.c b/libavcodec/intrax8.c index ffdfb079b..c6df8cf2e 100644 --- a/libavcodec/intrax8.c +++ b/libavcodec/intrax8.c @@ -25,6 +25,7 @@ #include "avcodec.h" #include "error_resilience.h" #include "get_bits.h" +#include "idctdsp.h" #include "mpegvideo.h" #include "msmpeg4data.h" #include "intrax8huf.h" @@ -303,7 +304,7 @@ static int x8_setup_spatial_predictor(IntraX8Context * const w, const int chroma int quant; w->dsp.setup_spatial_compensation(s->dest[chroma], s->edge_emu_buffer, - s->current_picture.f.linesize[chroma>0], + s->current_picture.f->linesize[chroma>0], &range, &sum, w->edges); if(chroma){ w->orient=w->chroma_orient; @@ -535,7 +536,7 @@ static int x8_decode_intra_mb(IntraX8Context* const w, const int chroma){ int sign; av_assert2(w->orient<12); - s->dsp.clear_block(s->block[0]); + s->bdsp.clear_block(s->block[0]); if(chroma){ dc_mode=2; @@ -612,7 +613,7 @@ static int x8_decode_intra_mb(IntraX8Context* const w, const int chroma){ 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]); + s->dest[chroma], s->current_picture.f->linesize[!!chroma]); goto block_placed; } @@ -636,16 +637,16 @@ static int x8_decode_intra_mb(IntraX8Context* const w, const int chroma){ } if(w->flat_dc){ - dsp_x8_put_solidcolor(w->predicted_dc, s->dest[chroma], s->current_picture.f.linesize[!!chroma]); + 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] ); + s->current_picture.f->linesize[!!chroma] ); } if(!zeros_only) - w->wdsp.idct_add (s->dest[chroma], - s->current_picture.f.linesize[!!chroma], - s->block[0] ); + w->wdsp.idct_add(s->dest[chroma], + s->current_picture.f->linesize[!!chroma], + s->block[0]); block_placed: @@ -655,7 +656,7 @@ block_placed: if(s->loop_filter){ uint8_t* ptr = s->dest[chroma]; - int linesize = s->current_picture.f.linesize[!!chroma]; + int linesize = s->current_picture.f->linesize[!!chroma]; if(!( (w->edges&2) || ( zeros_only && (w->orient|4)==4 ) )){ w->dsp.h_loop_filter(ptr, linesize, w->quant); @@ -670,12 +671,12 @@ block_placed: 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]; + 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->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 diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c index 71e36c190..e64c2bb76 100644 --- a/libavcodec/ituh263dec.c +++ b/libavcodec/ituh263dec.c @@ -37,6 +37,7 @@ #include "mpegvideo.h" #include "h263.h" #include "mathops.h" +#include "mpegutils.h" #include "unary.h" #include "flv.h" #include "mpeg4video.h" @@ -516,7 +517,7 @@ retry: rl = &ff_rl_intra_aic; i = 0; s->gb= gb; - s->dsp.clear_block(block); + s->bdsp.clear_block(block); goto retry; } av_log(s->avctx, AV_LOG_ERROR, "run overflow at %dx%d i:%d\n", s->mb_x, s->mb_y, s->mb_intra); @@ -609,7 +610,7 @@ int ff_h263_decode_mb(MpegEncContext *s, } }while(cbpc == 20); - s->dsp.clear_blocks(s->block[0]); + s->bdsp.clear_blocks(s->block[0]); dquant = cbpc & 8; s->mb_intra = ((cbpc & 4) != 0); @@ -704,7 +705,7 @@ int ff_h263_decode_mb(MpegEncContext *s, s->mb_intra = IS_INTRA(mb_type); if(HAS_CBP(mb_type)){ - s->dsp.clear_blocks(s->block[0]); + s->bdsp.clear_blocks(s->block[0]); cbpc = get_vlc2(&s->gb, cbpc_b_vlc.table, CBPC_B_VLC_BITS, 1); if(s->mb_intra){ dquant = IS_QUANT(mb_type); @@ -776,7 +777,7 @@ int ff_h263_decode_mb(MpegEncContext *s, } }while(cbpc == 8); - s->dsp.clear_blocks(s->block[0]); + s->bdsp.clear_blocks(s->block[0]); dquant = cbpc & 4; s->mb_intra = 1; diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index 2db958111..43ad08026 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -34,6 +34,7 @@ #include "mpegvideo.h" #include "h263.h" #include "mathops.h" +#include "mpegutils.h" #include "unary.h" #include "flv.h" #include "mpeg4video.h" @@ -230,14 +231,6 @@ void ff_h263_encode_picture_header(MpegEncContext * s, int picture_number) put_bits(&s->pb, 1, 1); } - - if(s->h263_aic){ - s->y_dc_scale_table= - s->c_dc_scale_table= ff_aic_dc_scale_table; - }else{ - s->y_dc_scale_table= - s->c_dc_scale_table= ff_mpeg1_dc_scale_table; - } } /** @@ -565,10 +558,6 @@ void ff_h263_encode_mb(MpegEncContext * s, else level = (level - (scale>>1))/scale; - /* AIC can change CBP */ - if (level == 0 && s->block_last_index[i] == 0) - s->block_last_index[i] = -1; - if(!s->modified_quant){ if (level < -127) level = -127; @@ -591,7 +580,9 @@ void ff_h263_encode_mb(MpegEncContext * s, /* Update AC/DC tables */ *dc_ptr[i] = rec_intradc[i]; - if (s->block_last_index[i] >= 0) + /* AIC can change CBP */ + if (s->block_last_index[i] > 0 || + (s->block_last_index[i] == 0 && level !=0)) cbp |= 1 << (5 - i); } }else{ @@ -816,12 +807,15 @@ av_cold void ff_h263_encode_init(MpegEncContext *s) s->min_qcoeff= -127; s->max_qcoeff= 127; } - s->y_dc_scale_table= - s->c_dc_scale_table= ff_mpeg1_dc_scale_table; break; default: //nothing needed - default table already set in mpegvideo.c s->min_qcoeff= -127; s->max_qcoeff= 127; + } + 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; } diff --git a/libavcodec/ivi_common.c b/libavcodec/ivi_common.c index b24d44fc4..379508123 100644 --- a/libavcodec/ivi_common.c +++ b/libavcodec/ivi_common.c @@ -26,6 +26,8 @@ * Indeo5 decoders. */ +#include + #define BITSTREAM_READER_LE #include "libavutil/attributes.h" #include "libavutil/timer.h" @@ -71,20 +73,43 @@ static VLC ivi_blk_vlc_tabs[8]; ///< static block Huffman tables typedef void (*ivi_mc_func) (int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type); +typedef void (*ivi_mc_avg_func) (int16_t *buf, const int16_t *ref_buf1, + const int16_t *ref_buf2, + uint32_t pitch, int mc_type, int mc_type2); -static int ivi_mc(IVIBandDesc *band, ivi_mc_func mc, - int offs, int mv_x, int mv_y, int mc_type) +static int ivi_mc(IVIBandDesc *band, ivi_mc_func mc, ivi_mc_avg_func mc_avg, + int offs, int mv_x, int mv_y, int mv_x2, int mv_y2, + int mc_type, int mc_type2) { int ref_offs = offs + mv_y * band->pitch + mv_x; int buf_size = band->pitch * band->aheight; int min_size = band->pitch * (band->blk_size - 1) + band->blk_size; int ref_size = (mc_type > 1) * band->pitch + (mc_type & 1); - av_assert0(offs >= 0 && ref_offs >= 0 && band->ref_buf); - av_assert0(buf_size - min_size >= offs); - av_assert0(buf_size - min_size - ref_size >= ref_offs); + if (mc_type != -1) { + av_assert0(offs >= 0 && ref_offs >= 0 && band->ref_buf); + av_assert0(buf_size - min_size >= offs); + av_assert0(buf_size - min_size - ref_size >= ref_offs); + } - mc(band->buf + offs, band->ref_buf + ref_offs, band->pitch, mc_type); + if (mc_type2 == -1) { + mc(band->buf + offs, band->ref_buf + ref_offs, band->pitch, mc_type); + } else { + int ref_offs2 = offs + mv_y2 * band->pitch + mv_x2; + int ref_size2 = (mc_type2 > 1) * band->pitch + (mc_type2 & 1); + if (offs < 0 || ref_offs2 < 0 || !band->b_ref_buf) + return AVERROR_INVALIDDATA; + if (buf_size - min_size - ref_size2 < ref_offs2) + return AVERROR_INVALIDDATA; + + if (mc_type == -1) + mc(band->buf + offs, band->b_ref_buf + ref_offs2, + band->pitch, mc_type2); + else + mc_avg(band->buf + offs, band->ref_buf + ref_offs, + band->b_ref_buf + ref_offs2, band->pitch, + mc_type, mc_type2); + } return 0; } @@ -262,6 +287,7 @@ static av_cold void ivi_free_buffers(IVIPlaneDesc *planes) av_freep(&planes[p].bands[b].bufs[0]); av_freep(&planes[p].bands[b].bufs[1]); av_freep(&planes[p].bands[b].bufs[2]); + av_freep(&planes[p].bands[b].bufs[3]); if (planes[p].bands[b].blk_vlc.cust_tab.table) ff_free_vlc(&planes[p].bands[b].blk_vlc.cust_tab); @@ -274,7 +300,8 @@ static av_cold void ivi_free_buffers(IVIPlaneDesc *planes) } } -av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg) +av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg, + int is_indeo4) { int p, b; uint32_t b_width, b_height, align_fac, width_aligned, @@ -298,7 +325,7 @@ av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg) planes[1].num_bands = planes[2].num_bands = cfg->chroma_bands; for (p = 0; p < 3; p++) { - planes[p].bands = av_mallocz(planes[p].num_bands * sizeof(IVIBandDesc)); + planes[p].bands = av_mallocz_array(planes[p].num_bands, sizeof(IVIBandDesc)); if (!planes[p].bands) return AVERROR(ENOMEM); @@ -337,6 +364,11 @@ av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg) if (!band->bufs[2]) return AVERROR(ENOMEM); } + if (is_indeo4) { + band->bufs[3] = av_mallocz(buf_size); + if (!band->bufs[3]) + return AVERROR(ENOMEM); + } /* reset custom vlc */ planes[p].bands[0].blk_vlc.cust_desc.num_rows = 0; } @@ -364,7 +396,7 @@ static int ivi_init_tiles(IVIBandDesc *band, IVITile *ref_tile, band->mb_size); av_freep(&tile->mbs); - tile->mbs = av_mallocz(tile->num_MBs * sizeof(IVIMbInfo)); + tile->mbs = av_mallocz_array(tile->num_MBs, sizeof(IVIMbInfo)); if (!tile->mbs) return AVERROR(ENOMEM); @@ -408,7 +440,7 @@ av_cold int ff_ivi_init_tiles(IVIPlaneDesc *planes, band->num_tiles = x_tiles * y_tiles; av_freep(&band->tiles); - band->tiles = av_mallocz(band->num_tiles * sizeof(IVITile)); + band->tiles = av_mallocz_array(band->num_tiles, sizeof(IVITile)); if (!band->tiles) return AVERROR(ENOMEM); @@ -467,8 +499,11 @@ static int ivi_dc_transform(IVIBandDesc *band, int *prev_dc, int buf_offs, } static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band, - ivi_mc_func mc, int mv_x, int mv_y, - int *prev_dc, int is_intra, int mc_type, + ivi_mc_func mc, ivi_mc_avg_func mc_avg, + int mv_x, int mv_y, + int mv_x2, int mv_y2, + int *prev_dc, int is_intra, + int mc_type, int mc_type2, uint32_t quant, int offs, AVCodecContext *avctx) { @@ -513,7 +548,7 @@ static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band, val = IVI_TOSIGNED((hi << 6) | lo); } else { if (sym >= 256U) { - av_log(avctx, AV_LOG_ERROR, "Invalid sym encountered: %d.\n", sym); + av_log(avctx, AV_LOG_ERROR, "Invalid sym encountered: %"PRIu32".\n", sym); return AVERROR_INVALIDDATA; } run = rvmap->runtab[sym]; @@ -558,7 +593,8 @@ static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band, /* apply motion compensation */ if (!is_intra) - return ivi_mc(band, mc, offs, mv_x, mv_y, mc_type); + return ivi_mc(band, mc, mc_avg, offs, mv_x, mv_y, mv_x2, mv_y2, + mc_type, mc_type2); return 0; } @@ -576,12 +612,14 @@ static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band, static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, IVITile *tile, AVCodecContext *avctx) { - int mbn, blk, num_blocks, blk_size, ret, is_intra, mc_type = 0; - int mv_x = 0, mv_y = 0; + int mbn, blk, num_blocks, blk_size, ret, is_intra; + int mc_type = 0, mc_type2 = -1; + int mv_x = 0, mv_y = 0, mv_x2 = 0, mv_y2 = 0; int32_t prev_dc; uint32_t cbp, quant, buf_offs; IVIMbInfo *mb; ivi_mc_func mc_with_delta_func, mc_no_delta_func; + ivi_mc_avg_func mc_avg_with_delta_func, mc_avg_no_delta_func; const uint8_t *scale_tab; /* init intra prediction for the DC coefficient */ @@ -590,11 +628,15 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, /* number of blocks per mb */ num_blocks = (band->mb_size != blk_size) ? 4 : 1; if (blk_size == 8) { - mc_with_delta_func = ff_ivi_mc_8x8_delta; - mc_no_delta_func = ff_ivi_mc_8x8_no_delta; + mc_with_delta_func = ff_ivi_mc_8x8_delta; + mc_no_delta_func = ff_ivi_mc_8x8_no_delta; + mc_avg_with_delta_func = ff_ivi_mc_avg_8x8_delta; + mc_avg_no_delta_func = ff_ivi_mc_avg_8x8_no_delta; } else { - mc_with_delta_func = ff_ivi_mc_4x4_delta; - mc_no_delta_func = ff_ivi_mc_4x4_no_delta; + mc_with_delta_func = ff_ivi_mc_4x4_delta; + mc_no_delta_func = ff_ivi_mc_4x4_no_delta; + mc_avg_with_delta_func = ff_ivi_mc_avg_4x4_delta; + mc_avg_no_delta_func = ff_ivi_mc_avg_4x4_no_delta; } for (mbn = 0, mb = tile->mbs; mbn < tile->num_MBs; mb++, mbn++) { @@ -613,13 +655,22 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, quant = scale_tab[quant]; if (!is_intra) { - mv_x = mb->mv_x; - mv_y = mb->mv_y; + mv_x = mb->mv_x; + mv_y = mb->mv_y; + mv_x2 = mb->b_mv_x; + mv_y2 = mb->b_mv_y; if (band->is_halfpel) { - mc_type = ((mv_y & 1) << 1) | (mv_x & 1); - mv_x >>= 1; - mv_y >>= 1; /* convert halfpel vectors into fullpel ones */ + mc_type = ((mv_y & 1) << 1) | (mv_x & 1); + mc_type2 = ((mv_y2 & 1) << 1) | (mv_x2 & 1); + mv_x >>= 1; + mv_y >>= 1; + mv_x2 >>= 1; + mv_y2 >>= 1; /* convert halfpel vectors into fullpel ones */ } + if (mb->type == 2) + mc_type = -1; + if (mb->type != 2 && mb->type != 3) + mc_type2 = -1; if (mb->type) { int dmv_x, dmv_y, cx, cy; @@ -628,6 +679,21 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, cx = mb->mv_x & band->is_halfpel; cy = mb->mv_y & band->is_halfpel; + if (mb->xpos + dmv_x < 0 || + mb->xpos + dmv_x + band->mb_size + cx > band->pitch || + mb->ypos + dmv_y < 0 || + mb->ypos + dmv_y + band->mb_size + cy > band->aheight) { + return AVERROR_INVALIDDATA; + } + } + if (mb->type == 2 || mb->type == 3) { + int dmv_x, dmv_y, cx, cy; + + dmv_x = mb->b_mv_x >> band->is_halfpel; + dmv_y = mb->b_mv_y >> band->is_halfpel; + cx = mb->b_mv_x & band->is_halfpel; + cy = mb->b_mv_y & band->is_halfpel; + if (mb->xpos + dmv_x < 0 || mb->xpos + dmv_x + band->mb_size + cx > band->pitch || mb->ypos + dmv_y < 0 || @@ -648,8 +714,11 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, if (cbp & 1) { /* block coded ? */ ret = ivi_decode_coded_blocks(gb, band, mc_with_delta_func, - mv_x, mv_y, &prev_dc, is_intra, - mc_type, quant, buf_offs, avctx); + mc_avg_with_delta_func, + mv_x, mv_y, mv_x2, mv_y2, + &prev_dc, is_intra, + mc_type, mc_type2, quant, + buf_offs, avctx); if (ret < 0) return ret; } else { @@ -661,8 +730,9 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, if (ret < 0) return ret; } else { - ret = ivi_mc(band, mc_no_delta_func, buf_offs, - mv_x, mv_y, mc_type); + ret = ivi_mc(band, mc_no_delta_func, mc_avg_no_delta_func, + buf_offs, mv_x, mv_y, mv_x2, mv_y2, + mc_type, mc_type2); if (ret < 0) return ret; } @@ -784,8 +854,8 @@ static int ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band, for (blk = 0; blk < num_blocks; blk++) { /* adjust block position in the buffer according with its number */ offs = mb->buf_offs + band->blk_size * ((blk & 1) + !!(blk & 2) * band->pitch); - ret = ivi_mc(band, mc_no_delta_func, offs, - mv_x, mv_y, mc_type); + ret = ivi_mc(band, mc_no_delta_func, 0, offs, + mv_x, mv_y, 0, 0, mc_type, -1); if (ret < 0) return ret; } @@ -867,8 +937,14 @@ static int decode_band(IVI45DecContext *ctx, av_log(avctx, AV_LOG_ERROR, "Band buffer points to no data!\n"); return AVERROR_INVALIDDATA; } - band->ref_buf = band->bufs[ctx->ref_buf]; - band->data_ptr = ctx->frame_data + (get_bits_count(&ctx->gb) >> 3); + if (ctx->is_indeo4 && ctx->frame_type == IVI4_FRAMETYPE_BIDIR) { + band->ref_buf = band->bufs[ctx->b_ref_buf]; + band->b_ref_buf = band->bufs[ctx->ref_buf]; + } else { + band->ref_buf = band->bufs[ctx->ref_buf]; + band->b_ref_buf = 0; + } + band->data_ptr = ctx->frame_data + (get_bits_count(&ctx->gb) >> 3); result = ctx->decode_band_hdr(ctx, band, avctx); if (result) { @@ -962,7 +1038,7 @@ static int decode_band(IVI45DecContext *ctx, if (chksum != band->checksum) { av_log(avctx, AV_LOG_ERROR, "Band checksum mismatch! Plane %d, band %d, " - "received: %x, calculated: %x\n", + "received: %"PRIx32", calculated: %"PRIx16"\n", band->plane, band->band_num, band->checksum, chksum); } } @@ -995,6 +1071,17 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (ctx->gop_invalid) return AVERROR_INVALIDDATA; + if (ctx->is_indeo4 && ctx->frame_type == IVI4_FRAMETYPE_NULL_LAST) { + if (ctx->got_p_frame) { + av_frame_move_ref(data, ctx->p_frame); + *got_frame = 1; + ctx->got_p_frame = 0; + } else { + *got_frame = 0; + } + return buf_size; + } + if (ctx->gop_flags & IVI5_IS_PROTECTED) { avpriv_report_missing_feature(avctx, "Password-protected clip!\n"); return AVERROR_PATCHWELCOME; @@ -1036,24 +1123,6 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, //STOP_TIMER("decode_planes"); } - /* If the bidirectional mode is enabled, next I and the following P - * frame will be sent together. Unfortunately the approach below seems - * to be the only way to handle the B-frames mode. - * That's exactly the same Intel decoders do. - */ - if (avctx->codec_id == AV_CODEC_ID_INDEO4 && - ctx->frame_type == 0/*FRAMETYPE_INTRA*/) { - // skip version string - while (get_bits(&ctx->gb, 8)) { - if (get_bits_left(&ctx->gb) < 8) - return AVERROR_INVALIDDATA; - } - - skip_bits_long(&ctx->gb, 64); // skip padding, TODO: implement correct 8-bytes alignment - if (get_bits_left(&ctx->gb) > 18 && show_bits(&ctx->gb, 18) == 0x3FFF8) - av_log(avctx, AV_LOG_ERROR, "Buffer contains IP frames!\n"); - } - if (!ctx->is_nonnull_frame(ctx)) return buf_size; @@ -1065,7 +1134,7 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return result; if (ctx->is_scalable) { - if (avctx->codec_id == AV_CODEC_ID_INDEO4) + if (ctx->is_indeo4) ff_ivi_recompose_haar(&ctx->planes[0], frame->data[0], frame->linesize[0]); else ff_ivi_recompose53 (&ctx->planes[0], frame->data[0], frame->linesize[0]); @@ -1078,6 +1147,30 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, *got_frame = 1; + /* If the bidirectional mode is enabled, next I and the following P + * frame will be sent together. Unfortunately the approach below seems + * to be the only way to handle the B-frames mode. + * That's exactly the same Intel decoders do. + */ + if (ctx->is_indeo4 && ctx->frame_type == IVI4_FRAMETYPE_INTRA) { + int left; + + // skip version string + while (get_bits(&ctx->gb, 8)) { + if (get_bits_left(&ctx->gb) < 8) + return AVERROR_INVALIDDATA; + } + left = get_bits_count(&ctx->gb) & 0x18; + skip_bits_long(&ctx->gb, 64 - left); + if (get_bits_left(&ctx->gb) > 18 && + show_bits_long(&ctx->gb, 21) == 0xBFFF8) { // syncheader + inter type + AVPacket pkt; + pkt.data = avpkt->data + (get_bits_count(&ctx->gb) >> 3); + pkt.size = get_bits_left(&ctx->gb) >> 3; + ff_ivi_decode_frame(avctx, ctx->p_frame, &ctx->got_p_frame, &pkt); + } + } + return buf_size; } @@ -1094,7 +1187,7 @@ av_cold int ff_ivi_decode_close(AVCodecContext *avctx) ff_free_vlc(&ctx->mb_vlc.cust_tab); #if IVI4_STREAM_ANALYSER - if (avctx->codec_id == AV_CODEC_ID_INDEO4) { + if (ctx->is_indeo4) { if (ctx->is_scalable) av_log(avctx, AV_LOG_ERROR, "This video uses scalability mode!\n"); if (ctx->uses_tiling) @@ -1110,6 +1203,8 @@ av_cold int ff_ivi_decode_close(AVCodecContext *avctx) } #endif + av_frame_free(&ctx->p_frame); + return 0; } diff --git a/libavcodec/ivi_common.h b/libavcodec/ivi_common.h index 72ab54f0a..9fec960e0 100644 --- a/libavcodec/ivi_common.h +++ b/libavcodec/ivi_common.h @@ -33,6 +33,19 @@ #include "get_bits.h" #include +/** + * Indeo 4 frame types. + */ +enum { + IVI4_FRAMETYPE_INTRA = 0, + IVI4_FRAMETYPE_INTRA1 = 1, ///< intra frame with slightly different bitstream coding + IVI4_FRAMETYPE_INTER = 2, ///< non-droppable P-frame + IVI4_FRAMETYPE_BIDIR = 3, ///< bidirectional frame + IVI4_FRAMETYPE_INTER_NOREF = 4, ///< droppable P-frame + IVI4_FRAMETYPE_NULL_FIRST = 5, ///< empty frame with no data + IVI4_FRAMETYPE_NULL_LAST = 6 ///< empty frame with no data +}; + #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 @@ -104,6 +117,8 @@ typedef struct IVIMbInfo { int8_t q_delta; ///< quant delta int8_t mv_x; ///< motion vector (x component) int8_t mv_y; ///< motion vector (y component) + int8_t b_mv_x; ///< second motion vector (x component) + int8_t b_mv_y; ///< second motion vector (y component) } IVIMbInfo; @@ -137,7 +152,8 @@ typedef struct IVIBandDesc { int data_size; ///< size of the band data int16_t *buf; ///< pointer to the output buffer for this band int16_t *ref_buf; ///< pointer to the reference frame buffer (for motion compensation) - int16_t *bufs[3]; ///< array of pointers to the band buffers + int16_t *b_ref_buf; ///< pointer to the second reference frame buffer (for motion compensation) + int16_t *bufs[4]; ///< array of pointers to the band buffers int pitch; ///< pitch associated with the buffers above int is_empty; ///< = 1 if this band doesn't contain any data int mb_size; ///< macroblock size @@ -219,6 +235,7 @@ typedef struct IVI45DecContext { int dst_buf; ///< buffer index for the currently decoded frame int ref_buf; ///< inter frame reference buffer index int ref2_buf; ///< temporal storage for switching buffers + int b_ref_buf; ///< second reference frame buffer index IVIHuffTab mb_vlc; ///< current macroblock table descriptor IVIHuffTab blk_vlc; ///< current block table descriptor @@ -248,7 +265,12 @@ typedef struct IVI45DecContext { int (*is_nonnull_frame)(struct IVI45DecContext *ctx); int gop_invalid; - int buf_invalid[3]; + int buf_invalid[4]; + + int is_indeo4; + + AVFrame *p_frame; + int got_p_frame; } IVI45DecContext; /** compare some properties of two pictures */ @@ -298,11 +320,13 @@ int ff_ivi_dec_huff_desc(GetBitContext *gb, int desc_coded, int which_tab, /** * Initialize planes (prepares descriptors, allocates buffers etc). * - * @param[in,out] planes pointer to the array of the plane descriptors - * @param[in] cfg pointer to the ivi_pic_config structure describing picture layout + * @param[in,out] planes pointer to the array of the plane descriptors + * @param[in] cfg pointer to the ivi_pic_config structure describing picture layout + * @param[in] is_indeo4 flag signalling if it is Indeo 4 or not * @return result code: 0 - OK */ -int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg); +int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg, + int is_indeo4); /** * Initialize tile and macroblock descriptors. diff --git a/libavcodec/ivi_dsp.c b/libavcodec/ivi_dsp.c index 9537cb037..89121ac08 100644 --- a/libavcodec/ivi_dsp.c +++ b/libavcodec/ivi_dsp.c @@ -772,39 +772,66 @@ void ff_ivi_put_dc_pixel_8x8(const int32_t *in, int16_t *out, uint32_t pitch, } #define IVI_MC_TEMPLATE(size, suffix, OP) \ -void ff_ivi_mc_ ## size ##x## size ## suffix (int16_t *buf, const int16_t *ref_buf, \ - uint32_t pitch, int mc_type) \ +static void ivi_mc_ ## size ##x## size ## suffix(int16_t *buf, \ + uint32_t dpitch, \ + const int16_t *ref_buf, \ + uint32_t pitch, int mc_type) \ { \ int i, j; \ const int16_t *wptr; \ \ switch (mc_type) { \ case 0: /* fullpel (no interpolation) */ \ - for (i = 0; i < size; i++, buf += pitch, ref_buf += pitch) { \ + for (i = 0; i < size; i++, buf += dpitch, ref_buf += pitch) { \ for (j = 0; j < size; j++) {\ OP(buf[j], ref_buf[j]); \ } \ } \ break; \ case 1: /* horizontal halfpel interpolation */ \ - for (i = 0; i < size; i++, buf += pitch, ref_buf += pitch) \ + for (i = 0; i < size; i++, buf += dpitch, ref_buf += pitch) \ for (j = 0; j < size; j++) \ OP(buf[j], (ref_buf[j] + ref_buf[j+1]) >> 1); \ break; \ case 2: /* vertical halfpel interpolation */ \ wptr = ref_buf + pitch; \ - for (i = 0; i < size; i++, buf += pitch, wptr += pitch, ref_buf += pitch) \ + for (i = 0; i < size; i++, buf += dpitch, wptr += pitch, ref_buf += pitch) \ for (j = 0; j < size; j++) \ OP(buf[j], (ref_buf[j] + wptr[j]) >> 1); \ break; \ case 3: /* vertical and horizontal halfpel interpolation */ \ wptr = ref_buf + pitch; \ - for (i = 0; i < size; i++, buf += pitch, wptr += pitch, ref_buf += pitch) \ + for (i = 0; i < size; i++, buf += dpitch, wptr += pitch, ref_buf += pitch) \ for (j = 0; j < size; j++) \ OP(buf[j], (ref_buf[j] + ref_buf[j+1] + wptr[j] + wptr[j+1]) >> 2); \ break; \ } \ } \ +\ +void ff_ivi_mc_ ## size ##x## size ## suffix(int16_t *buf, const int16_t *ref_buf, \ + uint32_t pitch, int mc_type) \ +{ \ + ivi_mc_ ## size ##x## size ## suffix(buf, pitch, ref_buf, pitch, mc_type); \ +} \ + +#define IVI_MC_AVG_TEMPLATE(size, suffix, OP) \ +void ff_ivi_mc_avg_ ## size ##x## size ## suffix(int16_t *buf, \ + const int16_t *ref_buf, \ + const int16_t *ref_buf2, \ + uint32_t pitch, \ + int mc_type, int mc_type2) \ +{ \ + int16_t tmp[size * size]; \ + int i, j; \ +\ + ivi_mc_ ## size ##x## size ## _no_delta(tmp, size, ref_buf, pitch, mc_type); \ + ivi_mc_ ## size ##x## size ## _delta(tmp, size, ref_buf2, pitch, mc_type2); \ + for (i = 0; i < size; i++, buf += pitch) { \ + for (j = 0; j < size; j++) {\ + OP(buf[j], tmp[i * size + j] >> 1); \ + } \ + } \ +} \ #define OP_PUT(a, b) (a) = (b) #define OP_ADD(a, b) (a) += (b) @@ -813,3 +840,7 @@ IVI_MC_TEMPLATE(8, _no_delta, OP_PUT) IVI_MC_TEMPLATE(8, _delta, OP_ADD) IVI_MC_TEMPLATE(4, _no_delta, OP_PUT) IVI_MC_TEMPLATE(4, _delta, OP_ADD) +IVI_MC_AVG_TEMPLATE(8, _no_delta, OP_PUT) +IVI_MC_AVG_TEMPLATE(8, _delta, OP_ADD) +IVI_MC_AVG_TEMPLATE(4, _no_delta, OP_PUT) +IVI_MC_AVG_TEMPLATE(4, _delta, OP_ADD) diff --git a/libavcodec/ivi_dsp.h b/libavcodec/ivi_dsp.h index 245f01d63..15562b6e3 100644 --- a/libavcodec/ivi_dsp.h +++ b/libavcodec/ivi_dsp.h @@ -295,4 +295,52 @@ void ff_ivi_mc_8x8_no_delta(int16_t *buf, const int16_t *ref_buf, uint32_t pitch */ void ff_ivi_mc_4x4_no_delta(int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type); +/** + * 8x8 block motion compensation with adding delta + * + * @param[in,out] buf pointer to the block in the current frame buffer containing delta + * @param[in] ref_buf pointer to the corresponding block in the backward reference frame + * @param[in] ref_buf2 pointer to the corresponding block in the forward reference frame + * @param[in] pitch pitch for moving to the next y line + * @param[in] mc_type interpolation type for backward reference + * @param[in] mc_type2 interpolation type for forward reference + */ +void ff_ivi_mc_avg_8x8_delta(int16_t *buf, const int16_t *ref_buf, const int16_t *ref_buf2, uint32_t pitch, int mc_type, int mc_type2); + +/** + * 4x4 block motion compensation with adding delta + * + * @param[in,out] buf pointer to the block in the current frame buffer containing delta + * @param[in] ref_buf pointer to the corresponding block in the backward reference frame + * @param[in] ref_buf2 pointer to the corresponding block in the forward reference frame + * @param[in] pitch pitch for moving to the next y line + * @param[in] mc_type interpolation type for backward reference + * @param[in] mc_type2 interpolation type for forward reference + */ +void ff_ivi_mc_avg_4x4_delta(int16_t *buf, const int16_t *ref_buf, const int16_t *ref_buf2, uint32_t pitch, int mc_type, int mc_type2); + +/** + * motion compensation without adding delta for B-frames + * + * @param[in,out] buf pointer to the block in the current frame receiving the result + * @param[in] ref_buf pointer to the corresponding block in the backward reference frame + * @param[in] ref_buf2 pointer to the corresponding block in the forward reference frame + * @param[in] pitch pitch for moving to the next y line + * @param[in] mc_type interpolation type for backward reference + * @param[in] mc_type2 interpolation type for forward reference + */ +void ff_ivi_mc_avg_8x8_no_delta(int16_t *buf, const int16_t *ref_buf, const int16_t *ref_buf2, uint32_t pitch, int mc_type, int mc_type2); + +/** + * 4x4 block motion compensation without adding delta for B-frames + * + * @param[in,out] buf pointer to the block in the current frame receiving the result + * @param[in] ref_buf pointer to the corresponding block in the backward reference frame + * @param[in] ref_buf2 pointer to the corresponding block in the forward reference frame + * @param[in] pitch pitch for moving to the next y line + * @param[in] mc_type interpolation type for backward reference + * @param[in] mc_type2 interpolation type for forward reference + */ +void ff_ivi_mc_avg_4x4_no_delta(int16_t *buf, const int16_t *ref_buf, const int16_t *ref_buf2, uint32_t pitch, int mc_type, int mc_type2); + #endif /* AVCODEC_IVI_DSP_H */ diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 498c7c022..ddb0b686c 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -343,14 +343,14 @@ static int init_tiles(Jpeg2000EncoderContext *s) s->numXtiles = ff_jpeg2000_ceildiv(s->width, s->tile_width); s->numYtiles = ff_jpeg2000_ceildiv(s->height, s->tile_height); - s->tile = av_malloc(s->numXtiles * s->numYtiles * sizeof(Jpeg2000Tile)); + s->tile = av_malloc_array(s->numXtiles, s->numYtiles * sizeof(Jpeg2000Tile)); if (!s->tile) return AVERROR(ENOMEM); for (tileno = 0, tiley = 0; tiley < s->numYtiles; tiley++) for (tilex = 0; tilex < s->numXtiles; tilex++, tileno++){ Jpeg2000Tile *tile = s->tile + tileno; - tile->comp = av_mallocz(s->ncomponents * sizeof(Jpeg2000Component)); + tile->comp = av_mallocz_array(s->ncomponents, sizeof(Jpeg2000Component)); if (!tile->comp) return AVERROR(ENOMEM); for (compno = 0; compno < s->ncomponents; compno++){ diff --git a/libavcodec/jfdctint_template.c b/libavcodec/jfdctint_template.c index c6a163810..3ea2f5dad 100644 --- a/libavcodec/jfdctint_template.c +++ b/libavcodec/jfdctint_template.c @@ -216,8 +216,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 cbcf946ff..ede1a791c 100644 --- a/libavcodec/jpeg2000.c +++ b/libavcodec/jpeg2000.c @@ -25,6 +25,7 @@ * JPEG 2000 image encoder and decoder common functions */ +#include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/mem.h" @@ -153,7 +154,7 @@ static int getsgnctxno(int flag, uint8_t *xorbit) return ctxlbltab[hcontrib][vcontrib]; } -void ff_jpeg2000_init_tier1_luts(void) +void av_cold ff_jpeg2000_init_tier1_luts(void) { int i, j; for (i = 0; i < 256; i++) @@ -249,7 +250,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) diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 845feb6e7..d6204bbfc 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -25,6 +25,9 @@ * JPEG 2000 image decoder */ +#include + +#include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/opt.h" @@ -446,7 +449,7 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c, if (tmp.mct && s->ncomponents < 3) { av_log(s->avctx, AV_LOG_ERROR, - "MCT %d with too few components (%d)\n", + "MCT %"PRIu8" with too few components (%d)\n", tmp.mct, s->ncomponents); return AVERROR_INVALIDDATA; } @@ -598,12 +601,12 @@ static int get_sot(Jpeg2000DecoderContext *s, int n) bytestream2_get_byteu(&s->g); // TNsot if (Psot > bytestream2_get_bytes_left(&s->g) + n + 2) { - av_log(s->avctx, AV_LOG_ERROR, "Psot %d too big\n", Psot); + av_log(s->avctx, AV_LOG_ERROR, "Psot %"PRIu32" too big\n", Psot); return AVERROR_INVALIDDATA; } if (TPsot >= FF_ARRAY_ELEMS(s->tile[Isot].tile_part)) { - avpriv_request_sample(s->avctx, "Support for %d components", TPsot); + avpriv_request_sample(s->avctx, "Support for %"PRIu8" components", TPsot); return AVERROR_PATCHWELCOME; } @@ -780,7 +783,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, return ret; if (ret > sizeof(cblk->data)) { avpriv_request_sample(s->avctx, - "Block with lengthinc greater than %zu", + "Block with lengthinc greater than %"SIZE_SPECIFIER"", sizeof(cblk->data)); return AVERROR_PATCHWELCOME; } @@ -808,7 +811,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, || sizeof(cblk->data) < cblk->length + cblk->lengthinc + 2 ) { av_log(s->avctx, AV_LOG_ERROR, - "Block length %d or lengthinc %d is too large\n", + "Block length %"PRIu16" or lengthinc %d is too large\n", cblk->length, cblk->lengthinc); return AVERROR_INVALIDDATA; } @@ -1483,14 +1486,15 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) break; default: av_log(s->avctx, AV_LOG_ERROR, - "unsupported marker 0x%.4X at pos 0x%X\n", + "unsupported marker 0x%.4"PRIX16" at pos 0x%X\n", marker, bytestream2_tell(&s->g) - 4); bytestream2_skip(&s->g, len - 2); break; } if (bytestream2_tell(&s->g) - oldpos != len || ret) { av_log(s->avctx, AV_LOG_ERROR, - "error during processing marker segment %.4x\n", marker); + "error during processing marker segment %.4"PRIx16"\n", + marker); return ret ? ret : -1; } } @@ -1688,7 +1692,7 @@ end: return ret; } -static void jpeg2000_init_static_data(AVCodec *codec) +static av_cold void jpeg2000_init_static_data(AVCodec *codec) { ff_jpeg2000_init_tier1_luts(); ff_mqc_init_context_tables(); diff --git a/libavcodec/jpeg2000dwt.c b/libavcodec/jpeg2000dwt.c index 266edece0..ceceda36d 100644 --- a/libavcodec/jpeg2000dwt.c +++ b/libavcodec/jpeg2000dwt.c @@ -518,17 +518,17 @@ int ff_jpeg2000_dwt_init(DWTContext *s, uint16_t border[2][2], } switch (type) { case FF_DWT97: - s->f_linebuf = av_malloc((maxlen + 12) * sizeof(*s->f_linebuf)); + s->f_linebuf = av_malloc_array((maxlen + 12), sizeof(*s->f_linebuf)); if (!s->f_linebuf) return AVERROR(ENOMEM); break; case FF_DWT97_INT: - s->i_linebuf = av_malloc((maxlen + 12) * sizeof(*s->i_linebuf)); + s->i_linebuf = av_malloc_array((maxlen + 12), sizeof(*s->i_linebuf)); if (!s->i_linebuf) return AVERROR(ENOMEM); break; case FF_DWT53: - s->i_linebuf = av_malloc((maxlen + 6) * sizeof(*s->i_linebuf)); + s->i_linebuf = av_malloc_array((maxlen + 6), sizeof(*s->i_linebuf)); if (!s->i_linebuf) return AVERROR(ENOMEM); break; diff --git a/libavcodec/jpegls.h b/libavcodec/jpegls.h index 10ae054a7..c8997c786 100644 --- a/libavcodec/jpegls.h +++ b/libavcodec/jpegls.h @@ -30,6 +30,7 @@ #include "libavutil/common.h" #include "avcodec.h" +#include "internal.h" typedef struct JpeglsContext { AVCodecContext *avctx; @@ -43,8 +44,6 @@ typedef struct JLSState { int run_index[4]; } JLSState; -extern const uint8_t ff_log2_run[32]; - /** * Calculate initial JPEG-LS parameters */ diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c index 190b9b6d2..fb3762dad 100644 --- a/libavcodec/jpeglsdec.c +++ b/libavcodec/jpeglsdec.c @@ -50,27 +50,79 @@ int ff_jpegls_decode_lse(MJpegDecodeContext *s) { int id; + int tid, wt, maxtab, i, j; - skip_bits(&s->gb, 16); /* length: FIXME: verify field validity */ + int len = get_bits(&s->gb, 16); id = get_bits(&s->gb, 8); switch (id) { case 1: + if (len < 13) + return AVERROR_INVALIDDATA; + s->maxval = get_bits(&s->gb, 16); s->t1 = get_bits(&s->gb, 16); s->t2 = get_bits(&s->gb, 16); s->t3 = get_bits(&s->gb, 16); s->reset = get_bits(&s->gb, 16); + if(s->avctx->debug & FF_DEBUG_PICT_INFO) { + av_log(s->avctx, AV_LOG_DEBUG, "Coding parameters maxval:%d T1:%d T2:%d T3:%d reset:%d\n", + s->maxval, s->t1, s->t2, s->t3, s->reset); + } + // ff_jpegls_reset_coding_parameters(s, 0); //FIXME quant table? break; case 2: + s->palette_index = 0; case 3: - av_log(s->avctx, AV_LOG_ERROR, "palette not supported\n"); - return AVERROR(ENOSYS); + tid= get_bits(&s->gb, 8); + wt = get_bits(&s->gb, 8); + + if (len < 5) + return AVERROR_INVALIDDATA; + + if (wt < 1 || wt > MAX_COMPONENTS) { + avpriv_request_sample(s->avctx, "wt %d", wt); + return AVERROR_PATCHWELCOME; + } + + if (!s->maxval) + maxtab = 255; + else if ((5 + wt*(s->maxval+1)) < 65535) + maxtab = s->maxval; + else + maxtab = 65530/wt - 1; + + if(s->avctx->debug & FF_DEBUG_PICT_INFO) { + av_log(s->avctx, AV_LOG_DEBUG, "LSE palette %d tid:%d wt:%d maxtab:%d\n", id, tid, wt, maxtab); + } + if (maxtab >= 256) { + avpriv_request_sample(s->avctx, ">8bit palette"); + return AVERROR_PATCHWELCOME; + } + maxtab = FFMIN(maxtab, (len - 5) / wt + s->palette_index); + + if (s->palette_index > maxtab) + return AVERROR_INVALIDDATA; + + if ((s->avctx->pix_fmt == AV_PIX_FMT_GRAY8 || s->avctx->pix_fmt == AV_PIX_FMT_PAL8) && + (s->picture_ptr->format == AV_PIX_FMT_GRAY8 || s->picture_ptr->format == AV_PIX_FMT_PAL8)) { + uint32_t *pal = (uint32_t *)s->picture_ptr->data[1]; + s->picture_ptr->format = + s->avctx->pix_fmt = AV_PIX_FMT_PAL8; + for (i=s->palette_index; i<=maxtab; i++) { + pal[i] = 0; + for (j=0; jgb, 8) << (8*(wt-j-1)); + } + } + s->palette_index = i; + } + break; case 4: - av_log(s->avctx, AV_LOG_ERROR, "oversize image not supported\n"); + avpriv_request_sample(s->avctx, "oversize image"); return AVERROR(ENOSYS); default: av_log(s->avctx, AV_LOG_ERROR, "invalid id %d\n", id); diff --git a/libavcodec/jpeglsenc.c b/libavcodec/jpeglsenc.c index 030178f9a..2f02332a3 100644 --- a/libavcodec/jpeglsenc.c +++ b/libavcodec/jpeglsenc.c @@ -431,6 +431,7 @@ AVCodec ff_jpegls_encoder = { .id = AV_CODEC_ID_JPEGLS, .init = encode_init_ls, .close = encode_close, + .capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, .encode2 = encode_picture_ls, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB24, diff --git a/libavcodec/jrevdct.c b/libavcodec/jrevdct.c index 91780b2e4..d4e6571ac 100644 --- a/libavcodec/jrevdct.c +++ b/libavcodec/jrevdct.c @@ -249,8 +249,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 +272,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 +284,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 +298,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 +307,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 +618,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 +630,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 +644,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 +653,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; } } diff --git a/libavcodec/jvdec.c b/libavcodec/jvdec.c index 03da880b7..47e8edcae 100644 --- a/libavcodec/jvdec.c +++ b/libavcodec/jvdec.c @@ -28,12 +28,12 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" -#include "dsputil.h" +#include "blockdsp.h" #include "get_bits.h" #include "internal.h" typedef struct JvContext { - DSPContext dsp; + BlockDSPContext bdsp; AVFrame *frame; uint32_t palette[AVPALETTE_COUNT]; int palette_has_changed; @@ -48,7 +48,7 @@ static av_cold int decode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); avctx->pix_fmt = AV_PIX_FMT_PAL8; - ff_dsputil_init(&s->dsp, avctx); + ff_blockdsp_init(&s->bdsp, avctx); return 0; } @@ -113,14 +113,14 @@ static inline void decode4x4(GetBitContext *gb, uint8_t *dst, int linesize) * Decode 8x8 block */ static inline void decode8x8(GetBitContext *gb, uint8_t *dst, int linesize, - DSPContext *dsp) + BlockDSPContext *bdsp) { int i, j, v[2]; switch (get_bits(gb, 2)) { case 1: v[0] = get_bits(gb, 8); - dsp->fill_block_tab[1](dst, v[0], linesize, 8); + bdsp->fill_block_tab[1](dst, v[0], linesize, 8); break; case 2: v[0] = get_bits(gb, 8); @@ -167,7 +167,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, for (i = 0; i < avctx->width; i += 8) decode8x8(&gb, s->frame->data[0] + j * s->frame->linesize[0] + i, - s->frame->linesize[0], &s->dsp); + s->frame->linesize[0], &s->bdsp); buf += video_size; } else if (video_type == 2) { diff --git a/libavcodec/kbdwin.c b/libavcodec/kbdwin.c index 5a62e9da2..bf32aeb31 100644 --- a/libavcodec/kbdwin.c +++ b/libavcodec/kbdwin.c @@ -45,3 +45,13 @@ av_cold void ff_kbd_window_init(float *window, float alpha, int n) for (i = 0; i < n; i++) window[i] = sqrt(local_window[i] / sum); } + +av_cold void ff_kbd_window_init_fixed(int32_t *window, float alpha, int n) +{ + int i; + float local_window[FF_KBD_WINDOW_MAX]; + + ff_kbd_window_init(local_window, alpha, n); + for (i = 0; i < n; i++) + window[i] = (int)floor(2147483647.0 * local_window[i] + 0.5); +} diff --git a/libavcodec/kbdwin.h b/libavcodec/kbdwin.h index 4b939756c..4185c4206 100644 --- a/libavcodec/kbdwin.h +++ b/libavcodec/kbdwin.h @@ -19,6 +19,8 @@ #ifndef AVCODEC_KBDWIN_H #define AVCODEC_KBDWIN_H +#include + /** * Maximum window size for ff_kbd_window_init. */ @@ -31,5 +33,6 @@ * @param n size of half window, max FF_KBD_WINDOW_MAX */ void ff_kbd_window_init(float *window, float alpha, int n); +void ff_kbd_window_init_fixed(int32_t *window, float alpha, int n); #endif /* AVCODEC_KBDWIN_H */ diff --git a/libavcodec/kgv1dec.c b/libavcodec/kgv1dec.c index edbc2b266..b81ba7532 100644 --- a/libavcodec/kgv1dec.c +++ b/libavcodec/kgv1dec.c @@ -82,8 +82,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if ((res = ff_get_buffer(avctx, frame, 0)) < 0) return res; - out = c->frame_buffer; - prev = c->last_frame_buffer; + out = (uint8_t*)c->frame_buffer; + prev = (uint8_t*)c->last_frame_buffer; for (i = 0; i < 8; i++) offsets[i] = -1; diff --git a/libavcodec/lagarith.c b/libavcodec/lagarith.c index 69fa33704..a08d7fde1 100644 --- a/libavcodec/lagarith.c +++ b/libavcodec/lagarith.c @@ -25,10 +25,12 @@ * @author Nathan Caldwell */ +#include + #include "avcodec.h" #include "get_bits.h" #include "mathops.h" -#include "dsputil.h" +#include "huffyuvdsp.h" #include "lagarithrac.h" #include "thread.h" @@ -48,7 +50,7 @@ enum LagarithFrameType { typedef struct LagarithContext { AVCodecContext *avctx; - DSPContext dsp; + HuffYUVDSPContext hdsp; int zeros; /**< number of consecutive zero bytes encountered */ int zeros_rem; /**< number of zero bytes remaining to output */ uint8_t *rgb_planes; @@ -231,7 +233,7 @@ static void add_lag_median_prediction(uint8_t *dst, uint8_t *src1, uint8_t *diff, int w, int *left, int *left_top) { - /* This is almost identical to add_hfyu_median_prediction in dsputil.h. + /* This is almost identical to add_hfyu_median_pred in huffyuvdsp.h. * However the &0xFF on the gradient predictor yealds incorrect output * for lagarith. */ @@ -258,8 +260,7 @@ static void lag_pred_line(LagarithContext *l, uint8_t *buf, if (!line) { /* Left prediction only for first line */ - L = l->dsp.add_hfyu_left_prediction(buf, buf, - width, 0); + L = l->hdsp.add_hfyu_left_pred(buf, buf, width, 0); } else { /* Left pixel is actually prev_row[width] */ L = buf[width - stride - 1]; @@ -288,7 +289,7 @@ static void lag_pred_line_yuy2(LagarithContext *l, uint8_t *buf, L= buf[0]; if (is_luma) buf[0] = 0; - l->dsp.add_hfyu_left_prediction(buf, buf, width, 0); + l->hdsp.add_hfyu_left_pred(buf, buf, width, 0); if (is_luma) buf[0] = L; return; @@ -311,8 +312,7 @@ static void lag_pred_line_yuy2(LagarithContext *l, uint8_t *buf, } else { TL = buf[width - (2 * stride) - 1]; L = buf[width - stride - 1]; - l->dsp.add_hfyu_median_prediction(buf, buf - stride, buf, width, - &L, &TL); + l->hdsp.add_hfyu_median_pred(buf, buf - stride, buf, width, &L, &TL); } } @@ -460,7 +460,7 @@ static int lag_decode_arith_plane(LagarithContext *l, uint8_t *dst, if (read > length) av_log(l->avctx, AV_LOG_WARNING, - "Output more bytes than length (%d of %d)\n", read, + "Output more bytes than length (%d of %"PRIu32")\n", read, length); } else if (esc_count < 8) { esc_count -= 4; @@ -711,7 +711,7 @@ static int lag_decode_frame(AVCodecContext *avctx, break; default: av_log(avctx, AV_LOG_ERROR, - "Unsupported Lagarith frame type: %#x\n", frametype); + "Unsupported Lagarith frame type: %#"PRIx8"\n", frametype); return AVERROR_PATCHWELCOME; } @@ -725,7 +725,7 @@ static av_cold int lag_decode_init(AVCodecContext *avctx) LagarithContext *l = avctx->priv_data; l->avctx = avctx; - ff_dsputil_init(&l->dsp, avctx); + ff_huffyuvdsp_init(&l->hdsp); return 0; } diff --git a/libavcodec/lagarithrac.c b/libavcodec/lagarithrac.c index 895acb0d3..37ac2cf57 100644 --- a/libavcodec/lagarithrac.c +++ b/libavcodec/lagarithrac.c @@ -45,15 +45,12 @@ void ff_lag_rac_init(lag_rac *l, GetBitContext *gb, int length) l->range = 0x80; l->low = *l->bytestream >> 1; - l->hash_shift = FFMAX((int)l->scale - 8, 0); + l->hash_shift = FFMAX((int)l->scale - 10, 0); - for (i = j = 0; i < 256; i++) { + for (i = j = 0; i < 1024; i++) { unsigned r = i << l->hash_shift; while (l->prob[j + 1] <= r) j++; l->range_hash[i] = j; } - - /* Add conversion factor to hash_shift so we don't have to in lag_get_rac. */ - l->hash_shift += 23; } diff --git a/libavcodec/lagarithrac.h b/libavcodec/lagarithrac.h index 9892d11fb..dfdfea0db 100644 --- a/libavcodec/lagarithrac.h +++ b/libavcodec/lagarithrac.h @@ -48,7 +48,7 @@ typedef struct lag_rac { const uint8_t *bytestream_end; /**< End position of input bytestream. */ uint32_t prob[258]; /**< Table of cumulative probability for each symbol. */ - uint8_t range_hash[256]; /**< Hash table mapping upper byte to approximate symbol. */ + uint8_t range_hash[1024]; /**< Hash table mapping upper byte to approximate symbol. */ } lag_rac; void ff_lag_rac_init(lag_rac *l, GetBitContext *gb, int length); @@ -72,9 +72,8 @@ static inline void lag_rac_refill(lag_rac *l) */ static inline uint8_t lag_get_rac(lag_rac *l) { - unsigned range_scaled, low_scaled, div; + unsigned range_scaled, low_scaled; int val; - uint8_t shift; lag_rac_refill(l); @@ -85,18 +84,9 @@ static inline uint8_t lag_get_rac(lag_rac *l) if (l->low < range_scaled * l->prob[1]) { val = 0; } else { - /* FIXME __builtin_clz is ~20% faster here, but not allowed in generic code. */ - shift = 30 - av_log2(range_scaled); - div = ((range_scaled << shift) + (1 << 23) - 1) >> 23; - /* low>>24 ensures that any cases too big for exact FASTDIV are - * under- rather than over-estimated - */ - low_scaled = FASTDIV(l->low - (l->low >> 24), div); - shift -= l->hash_shift; - shift &= 31; - low_scaled = (low_scaled << shift) | (low_scaled >> (32 - shift)); - /* low_scaled is now a lower bound of low/range_scaled */ - val = l->range_hash[(uint8_t) low_scaled]; + low_scaled = l->low / (range_scaled<<(l->hash_shift)); + + val = l->range_hash[low_scaled]; while (l->low >= range_scaled * l->prob[val + 1]) val++; } diff --git a/libavcodec/lclenc.c b/libavcodec/lclenc.c index 0afe5530b..201d35789 100644 --- a/libavcodec/lclenc.c +++ b/libavcodec/lclenc.c @@ -197,5 +197,6 @@ AVCodec ff_zlib_encoder = { .init = encode_init, .encode2 = encode_frame, .close = encode_end, + .capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/libavcodec.v b/libavcodec/libavcodec.v index 69e653c78..5a8c005b9 100644 --- a/libavcodec/libavcodec.v +++ b/libavcodec/libavcodec.v @@ -27,5 +27,8 @@ LIBAVCODEC_$MAJOR { ff_jpeg_fdct*; ff_dnxhd_get_cid_table; ff_dnxhd_cid_table; + ff_idctdsp_init; + ff_fdctdsp_init; + ff_pixblockdsp_init; local: *; }; diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c index c833a98a8..624d57959 100644 --- a/libavcodec/libfdk-aacdec.c +++ b/libavcodec/libfdk-aacdec.c @@ -4,19 +4,17 @@ * * This file is part of FFmpeg. * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include @@ -28,7 +26,6 @@ #include "internal.h" enum ConcealMethod { - CONCEAL_METHOD_DEFAULT = -1, CONCEAL_METHOD_SPECTRAL_MUTING = 0, CONCEAL_METHOD_NOISE_SUBSTITUTION = 1, CONCEAL_METHOD_ENERGY_INTERPOLATION = 2, @@ -45,8 +42,7 @@ typedef struct FDKAACDecContext { #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[] = { - { "conceal", "Error concealment method", OFFSET(conceal_method), AV_OPT_TYPE_INT, { .i64 = CONCEAL_METHOD_DEFAULT }, CONCEAL_METHOD_DEFAULT, CONCEAL_METHOD_NB - 1, AD, "conceal" }, - { "default", "Default", 0, AV_OPT_TYPE_CONST, { .i64 = CONCEAL_METHOD_DEFAULT }, INT_MIN, INT_MAX, AD, "conceal" }, + { "conceal", "Error concealment method", OFFSET(conceal_method), AV_OPT_TYPE_INT, { .i64 = CONCEAL_METHOD_NOISE_SUBSTITUTION }, CONCEAL_METHOD_SPECTRAL_MUTING, CONCEAL_METHOD_NB - 1, AD, "conceal" }, { "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" }, @@ -197,12 +193,10 @@ static av_cold int fdk_aac_decode_init(AVCodecContext *avctx) } } - if (s->conceal_method != CONCEAL_METHOD_DEFAULT) { - if ((err = aacDecoder_SetParam(s->handle, AAC_CONCEAL_METHOD, - s->conceal_method)) != AAC_DEC_OK) { - av_log(avctx, AV_LOG_ERROR, "Unable to set error concealment method\n"); - return AVERROR_UNKNOWN; - } + if ((err = aacDecoder_SetParam(s->handle, AAC_CONCEAL_METHOD, + s->conceal_method)) != AAC_DEC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set error concealment method\n"); + return AVERROR_UNKNOWN; } avctx->sample_fmt = AV_SAMPLE_FMT_S16; @@ -300,6 +294,6 @@ AVCodec ff_libfdk_aac_decoder = { .decode = fdk_aac_decode_frame, .close = fdk_aac_decode_close, .flush = fdk_aac_decode_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_CHANNEL_CONF, .priv_class = &fdk_aac_dec_class, }; diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c index bc7040089..b9c9a132b 100644 --- a/libavcodec/libfdk-aacenc.c +++ b/libavcodec/libfdk-aacenc.c @@ -4,19 +4,17 @@ * * This file is part of FFmpeg. * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index f2d455c52..fed82e271 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -209,6 +209,8 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, default: return AVERROR_BUG; } + } else if (!s->afq.frame_alloc) { + lame_result = 0; } else { lame_result = lame_encode_flush(s->gfp, s->buffer + s->buffer_index, s->buffer_size - s->buffer_index); diff --git a/libavcodec/libopencore-amr.c b/libavcodec/libopencore-amr.c index 3a8787b9d..4c7b6afc7 100644 --- a/libavcodec/libopencore-amr.c +++ b/libavcodec/libopencore-amr.c @@ -241,7 +241,7 @@ static int amr_nb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (frame) { if (frame->nb_samples < avctx->frame_size) { - flush_buf = av_mallocz(avctx->frame_size * sizeof(*flush_buf)); + flush_buf = av_mallocz_array(avctx->frame_size, sizeof(*flush_buf)); if (!flush_buf) return AVERROR(ENOMEM); memcpy(flush_buf, samples, frame->nb_samples * sizeof(*flush_buf)); @@ -256,7 +256,7 @@ static int amr_nb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } else { if (s->enc_last_frame < 0) return 0; - flush_buf = av_mallocz(avctx->frame_size * sizeof(*flush_buf)); + flush_buf = av_mallocz_array(avctx->frame_size, sizeof(*flush_buf)); if (!flush_buf) return AVERROR(ENOMEM); samples = flush_buf; diff --git a/libavcodec/libopenjpegdec.c b/libavcodec/libopenjpegdec.c index 0389dbd2c..178e4488c 100644 --- a/libavcodec/libopenjpegdec.c +++ b/libavcodec/libopenjpegdec.c @@ -27,10 +27,11 @@ #define OPJ_STATIC #include "libavutil/common.h" -#include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" -#include "libavutil/pixfmt.h" +#include "libavutil/intreadwrite.h" #include "libavutil/opt.h" +#include "libavutil/pixfmt.h" + #include "avcodec.h" #include "internal.h" #include "thread.h" @@ -46,29 +47,38 @@ // pix_fmts with lower bpp have to be listed before // similar pix_fmts with higher bpp. -#define RGB_PIXEL_FORMATS AV_PIX_FMT_RGB24,AV_PIX_FMT_RGBA,AV_PIX_FMT_RGB48,AV_PIX_FMT_RGBA64 -#define GRAY_PIXEL_FORMATS AV_PIX_FMT_GRAY8,AV_PIX_FMT_GRAY8A,AV_PIX_FMT_GRAY16 -#define YUV_PIXEL_FORMATS AV_PIX_FMT_YUV410P,AV_PIX_FMT_YUV411P,AV_PIX_FMT_YUVA420P, \ - AV_PIX_FMT_YUV420P,AV_PIX_FMT_YUV422P,AV_PIX_FMT_YUVA422P, \ - AV_PIX_FMT_YUV440P,AV_PIX_FMT_YUV444P,AV_PIX_FMT_YUVA444P, \ - AV_PIX_FMT_YUV420P9,AV_PIX_FMT_YUV422P9,AV_PIX_FMT_YUV444P9, \ - AV_PIX_FMT_YUVA420P9,AV_PIX_FMT_YUVA422P9,AV_PIX_FMT_YUVA444P9, \ - AV_PIX_FMT_YUV420P10,AV_PIX_FMT_YUV422P10,AV_PIX_FMT_YUV444P10, \ - AV_PIX_FMT_YUVA420P10,AV_PIX_FMT_YUVA422P10,AV_PIX_FMT_YUVA444P10, \ - AV_PIX_FMT_YUV420P12,AV_PIX_FMT_YUV422P12,AV_PIX_FMT_YUV444P12, \ - AV_PIX_FMT_YUV420P14,AV_PIX_FMT_YUV422P14,AV_PIX_FMT_YUV444P14, \ - AV_PIX_FMT_YUV420P16,AV_PIX_FMT_YUV422P16,AV_PIX_FMT_YUV444P16, \ - AV_PIX_FMT_YUVA420P16,AV_PIX_FMT_YUVA422P16,AV_PIX_FMT_YUVA444P16 +#define RGB_PIXEL_FORMATS AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, \ + AV_PIX_FMT_RGB48, AV_PIX_FMT_RGBA64 + +#define GRAY_PIXEL_FORMATS AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, \ + AV_PIX_FMT_GRAY16 + +#define YUV_PIXEL_FORMATS AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUVA420P, \ + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA422P, \ + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, \ + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, \ + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, \ + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, \ + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, \ + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, \ + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, \ + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, \ + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16 #define XYZ_PIXEL_FORMATS AV_PIX_FMT_XYZ12 -static const enum AVPixelFormat libopenjpeg_rgb_pix_fmts[] = {RGB_PIXEL_FORMATS}; -static const enum AVPixelFormat libopenjpeg_gray_pix_fmts[] = {GRAY_PIXEL_FORMATS}; -static const enum AVPixelFormat libopenjpeg_yuv_pix_fmts[] = {YUV_PIXEL_FORMATS}; -static const enum AVPixelFormat libopenjpeg_all_pix_fmts[] = {RGB_PIXEL_FORMATS, - GRAY_PIXEL_FORMATS, - YUV_PIXEL_FORMATS, - XYZ_PIXEL_FORMATS}; +static const enum AVPixelFormat libopenjpeg_rgb_pix_fmts[] = { + RGB_PIXEL_FORMATS +}; +static const enum AVPixelFormat libopenjpeg_gray_pix_fmts[] = { + GRAY_PIXEL_FORMATS +}; +static const enum AVPixelFormat libopenjpeg_yuv_pix_fmts[] = { + YUV_PIXEL_FORMATS +}; +static const enum AVPixelFormat libopenjpeg_all_pix_fmts[] = { + RGB_PIXEL_FORMATS, GRAY_PIXEL_FORMATS, YUV_PIXEL_FORMATS, XYZ_PIXEL_FORMATS +}; typedef struct { AVClass *class; @@ -86,18 +96,26 @@ static inline int libopenjpeg_matches_pix_fmt(const opj_image_t *image, enum AVP } switch (desc->nb_components) { - case 4: match = match && desc->comp[3].depth_minus1 + 1 >= image->comps[3].prec && - 1 == image->comps[3].dx && - 1 == image->comps[3].dy; - case 3: match = match && desc->comp[2].depth_minus1 + 1 >= image->comps[2].prec && - 1 << desc->log2_chroma_w == image->comps[2].dx && - 1 << desc->log2_chroma_h == image->comps[2].dy; - case 2: match = match && desc->comp[1].depth_minus1 + 1 >= image->comps[1].prec && - 1 << desc->log2_chroma_w == image->comps[1].dx && - 1 << desc->log2_chroma_h == image->comps[1].dy; - case 1: match = match && desc->comp[0].depth_minus1 + 1 >= image->comps[0].prec && - 1 == image->comps[0].dx && - 1 == image->comps[0].dy; + case 4: + match = match && + desc->comp[3].depth_minus1 + 1 >= image->comps[3].prec && + 1 == image->comps[3].dx && + 1 == image->comps[3].dy; + case 3: + match = match && + desc->comp[2].depth_minus1 + 1 >= image->comps[2].prec && + 1 << desc->log2_chroma_w == image->comps[2].dx && + 1 << desc->log2_chroma_h == image->comps[2].dy; + case 2: + match = match && + desc->comp[1].depth_minus1 + 1 >= image->comps[1].prec && + 1 << desc->log2_chroma_w == image->comps[1].dx && + 1 << desc->log2_chroma_h == image->comps[1].dy; + case 1: + match = match && + desc->comp[0].depth_minus1 + 1 >= image->comps[0].prec && + 1 == image->comps[0].dx && + 1 == image->comps[0].dy; default: break; } @@ -112,28 +130,27 @@ static inline enum AVPixelFormat libopenjpeg_guess_pix_fmt(const opj_image_t *im switch (image->color_space) { case CLRSPC_SRGB: - possible_fmts = libopenjpeg_rgb_pix_fmts; + possible_fmts = libopenjpeg_rgb_pix_fmts; possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_rgb_pix_fmts); break; case CLRSPC_GRAY: - possible_fmts = libopenjpeg_gray_pix_fmts; + possible_fmts = libopenjpeg_gray_pix_fmts; possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_gray_pix_fmts); break; case CLRSPC_SYCC: - possible_fmts = libopenjpeg_yuv_pix_fmts; + possible_fmts = libopenjpeg_yuv_pix_fmts; possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_yuv_pix_fmts); break; default: - possible_fmts = libopenjpeg_all_pix_fmts; + possible_fmts = libopenjpeg_all_pix_fmts; possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_all_pix_fmts); break; } - for (index = 0; index < possible_fmts_nb; ++index) { + for (index = 0; index < possible_fmts_nb; ++index) if (libopenjpeg_matches_pix_fmt(image, possible_fmts[index])) { return possible_fmts[index]; } - } return AV_PIX_FMT_NONE; } @@ -147,10 +164,9 @@ static inline int libopenjpeg_ispacked(enum AVPixelFormat pix_fmt) return 0; component_plane = desc->comp[0].plane; - for (i = 1; i < desc->nb_components; i++) { + for (i = 1; i < desc->nb_components; i++) if (component_plane != desc->comp[i].plane) return 0; - } return 1; } @@ -158,13 +174,11 @@ static inline void libopenjpeg_copy_to_packed8(AVFrame *picture, opj_image_t *im uint8_t *img_ptr; int index, x, y, c; for (y = 0; y < picture->height; y++) { - index = y*picture->width; - img_ptr = picture->data[0] + y*picture->linesize[0]; - for (x = 0; x < picture->width; x++, index++) { - for (c = 0; c < image->numcomps; c++) { + index = y * picture->width; + img_ptr = picture->data[0] + y * picture->linesize[0]; + for (x = 0; x < picture->width; x++, index++) + for (c = 0; c < image->numcomps; c++) *img_ptr++ = 0x80 * image->comps[c].sgnd + image->comps[c].data[index]; - } - } } } @@ -176,14 +190,12 @@ static inline void libopenjpeg_copy_to_packed16(AVFrame *picture, opj_image_t *i adjust[x] = FFMAX(FFMIN(av_pix_fmt_desc_get(picture->format)->comp[x].depth_minus1 + 1 - image->comps[x].prec, 8), 0); for (y = 0; y < picture->height; y++) { - index = y*picture->width; - img_ptr = (uint16_t*) (picture->data[0] + y*picture->linesize[0]); - for (x = 0; x < picture->width; x++, index++) { - for (c = 0; c < image->numcomps; c++) { + index = y * picture->width; + img_ptr = (uint16_t *) (picture->data[0] + y * picture->linesize[0]); + for (x = 0; x < picture->width; x++, index++) + for (c = 0; c < image->numcomps; c++) *img_ptr++ = (1 << image->comps[c].prec - 1) * image->comps[c].sgnd + (unsigned)image->comps[c].data[index] << adjust[c]; - } - } } } @@ -216,7 +228,7 @@ static inline void libopenjpeg_copyto16(AVFrame *picture, opj_image_t *image) { for (index = 0; index < image->numcomps; index++) { comp_data = image->comps[index].data; for (y = 0; y < image->comps[index].h; y++) { - img_ptr = (uint16_t*) (picture->data[index] + y * picture->linesize[index]); + img_ptr = (uint16_t *)(picture->data[index] + y * picture->linesize[index]); for (x = 0; x < image->comps[index].w; x++) { *img_ptr = (1 << image->comps[index].prec - 1) * image->comps[index].sgnd + (unsigned)*comp_data << adjust[index]; @@ -239,24 +251,24 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { - uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; + uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; LibOpenJPEGContext *ctx = avctx->priv_data; - ThreadFrame frame = { .f = data }; - AVFrame *picture = data; + ThreadFrame frame = { .f = data }; + AVFrame *picture = data; const AVPixFmtDescriptor *desc; opj_dinfo_t *dec; opj_cio_t *stream; opj_image_t *image; int width, height, ret; int pixel_size = 0; - int ispacked = 0; + int ispacked = 0; int i; *got_frame = 0; // Check if input is a raw jpeg2k codestream or in jp2 wrapping - if ((AV_RB32(buf) == 12) && + if ((AV_RB32(buf) == 12) && (AV_RB32(buf + 4) == JP2_SIG_TYPE) && (AV_RB32(buf + 8) == JP2_SIG_VALUE)) { dec = opj_create_decompress(CODEC_JP2); @@ -272,12 +284,12 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "Error initializing decoder.\n"); return AVERROR_UNKNOWN; } - opj_set_event_mgr((opj_common_ptr)dec, NULL, NULL); + opj_set_event_mgr((opj_common_ptr) dec, NULL, NULL); ctx->dec_params.cp_limit_decoding = LIMIT_TO_MAIN_HEADER; ctx->dec_params.cp_layer = ctx->lowqual; // Tie decoder with decoding parameters opj_setup_decoder(dec, &ctx->dec_params); - stream = opj_cio_open((opj_common_ptr)dec, buf, buf_size); + stream = opj_cio_open((opj_common_ptr) dec, buf, buf_size); if (!stream) { av_log(avctx, AV_LOG_ERROR, @@ -325,7 +337,7 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, ctx->dec_params.cp_reduce = avctx->lowres; // Tie decoder with decoding parameters. opj_setup_decoder(dec, &ctx->dec_params); - stream = opj_cio_open((opj_common_ptr)dec, buf, buf_size); + stream = opj_cio_open((opj_common_ptr) dec, buf, buf_size); if (!stream) { av_log(avctx, AV_LOG_ERROR, "Codestream could not be opened for reading.\n"); @@ -344,9 +356,9 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, goto done; } - desc = av_pix_fmt_desc_get(avctx->pix_fmt); + desc = av_pix_fmt_desc_get(avctx->pix_fmt); pixel_size = desc->comp[0].step_minus1 + 1; - ispacked = libopenjpeg_ispacked(avctx->pix_fmt); + ispacked = libopenjpeg_ispacked(avctx->pix_fmt); switch (pixel_size) { case 1: @@ -394,7 +406,8 @@ done: #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { - { "lowqual", "Limit the number of layers used for decoding", OFFSET(lowqual), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VD }, + { "lowqual", "Limit the number of layers used for decoding", + OFFSET(lowqual), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VD }, { NULL }, }; @@ -406,14 +419,14 @@ static const AVClass openjpeg_class = { }; AVCodec ff_libopenjpeg_decoder = { - .name = "libopenjpeg", - .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_JPEG2000, - .priv_data_size = sizeof(LibOpenJPEGContext), - .init = libopenjpeg_decode_init, - .decode = libopenjpeg_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, - .max_lowres = 31, - .priv_class = &openjpeg_class, + .name = "libopenjpeg", + .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_JPEG2000, + .priv_data_size = sizeof(LibOpenJPEGContext), + .init = libopenjpeg_decode_init, + .decode = libopenjpeg_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .max_lowres = 31, + .priv_class = &openjpeg_class, }; diff --git a/libavcodec/libopenjpegenc.c b/libavcodec/libopenjpegenc.c index 083da6425..0fcc48ffd 100644 --- a/libavcodec/libopenjpegenc.c +++ b/libavcodec/libopenjpegenc.c @@ -235,7 +235,7 @@ static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx) } opj_setup_encoder(ctx->compress, &ctx->enc_params, ctx->image); - ctx->stream = opj_cio_open((opj_common_ptr)ctx->compress, NULL, 0); + ctx->stream = opj_cio_open((opj_common_ptr) ctx->compress, NULL, 0); if (!ctx->stream) { av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n"); err = AVERROR(ENOMEM); @@ -252,7 +252,7 @@ static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx) ctx->event_mgr.info_handler = info_callback; ctx->event_mgr.error_handler = error_callback; ctx->event_mgr.warning_handler = warning_callback; - opj_set_event_mgr((opj_common_ptr)ctx->compress, &ctx->event_mgr, avctx); + opj_set_event_mgr((opj_common_ptr) ctx->compress, &ctx->event_mgr, avctx); return 0; @@ -310,12 +310,11 @@ static int libopenjpeg_copy_packed8(AVCodecContext *avctx, const AVFrame *frame, static int libopenjpeg_copy_packed12(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) { int compno; - int x; - int y; + int x, y; int *image_line; int frame_index; - const int numcomps = image->numcomps; - uint16_t *frame_ptr = (uint16_t*)frame->data[0]; + const int numcomps = image->numcomps; + uint16_t *frame_ptr = (uint16_t *)frame->data[0]; for (compno = 0; compno < numcomps; ++compno) { if (image->comps[compno].w > frame->linesize[0] / numcomps) { @@ -406,7 +405,7 @@ static int libopenjpeg_copy_unpacked8(AVCodecContext *avctx, const AVFrame *fram } for (compno = 0; compno < numcomps; ++compno) { - width = avctx->width / image->comps[compno].dx; + width = avctx->width / image->comps[compno].dx; height = avctx->height / image->comps[compno].dy; for (y = 0; y < height; ++y) { image_line = image->comps[compno].data + y * image->comps[compno].w; @@ -448,9 +447,9 @@ static int libopenjpeg_copy_unpacked16(AVCodecContext *avctx, const AVFrame *fra } for (compno = 0; compno < numcomps; ++compno) { - width = avctx->width / image->comps[compno].dx; - height = avctx->height / image->comps[compno].dy; - frame_ptr = (uint16_t*)frame->data[compno]; + width = avctx->width / image->comps[compno].dx; + height = avctx->height / image->comps[compno].dy; + frame_ptr = (uint16_t *)frame->data[compno]; for (y = 0; y < height; ++y) { image_line = image->comps[compno].data + y * image->comps[compno].w; frame_index = y * (frame->linesize[compno] / 2); @@ -475,9 +474,9 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { LibOpenJPEGContext *ctx = avctx->priv_data; - opj_cinfo_t *compress = ctx->compress; - opj_image_t *image = ctx->image; - opj_cio_t *stream = ctx->stream; + opj_cinfo_t *compress = ctx->compress; + opj_image_t *image = ctx->image; + opj_cio_t *stream = ctx->stream; int cpyresult = 0; int ret, len; AVFrame *gbrframe; @@ -646,10 +645,10 @@ AVCodec ff_libopenjpeg_encoder = { .init = libopenjpeg_encode_init, .encode2 = libopenjpeg_encode_frame, .close = libopenjpeg_encode_close, - .capabilities = 0, + .capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, .pix_fmts = (const enum AVPixelFormat[]) { - AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48, AV_PIX_FMT_RGBA64, - AV_PIX_FMT_GBR24P, + AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48, + AV_PIX_FMT_RGBA64, AV_PIX_FMT_GBR24P, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, AV_PIX_FMT_GRAY16, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, diff --git a/libavcodec/libspeexdec.c b/libavcodec/libspeexdec.c index afe117619..5e149a5d5 100644 --- a/libavcodec/libspeexdec.c +++ b/libavcodec/libspeexdec.c @@ -43,7 +43,6 @@ static av_cold int libspeex_decode_init(AVCodecContext *avctx) SpeexHeader *header = NULL; int spx_mode; - avctx->sample_fmt = AV_SAMPLE_FMT_S16; if (avctx->extradata && avctx->extradata_size >= 80) { header = speex_packet_to_header(avctx->extradata, avctx->extradata_size); @@ -125,6 +124,7 @@ static int libspeex_decode_frame(AVCodecContext *avctx, void *data, AVFrame *frame = data; int16_t *output; int ret, consumed = 0; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; /* get output buffer */ frame->nb_samples = s->frame_size; @@ -159,6 +159,8 @@ static int libspeex_decode_frame(AVCodecContext *avctx, void *data, *got_frame_ptr = 1; + if (!avctx->bit_rate) + speex_decoder_ctl(s->dec_state, SPEEX_GET_BITRATE, &avctx->bit_rate); return consumed; } diff --git a/libavcodec/libtwolame.c b/libavcodec/libtwolame.c index dc4efe58b..e26454bb8 100644 --- a/libavcodec/libtwolame.c +++ b/libavcodec/libtwolame.c @@ -26,22 +26,25 @@ #include +#include "libavutil/common.h" #include "libavutil/opt.h" + #include "avcodec.h" #include "internal.h" #include "mpegaudio.h" typedef struct TWOLAMEContext { - AVClass *class; - int mode; - int psymodel; - int energy; - int error_protection; - int copyright; - int original; + AVClass *class; + int mode; + int psymodel; + int energy; + int error_protection; + int copyright; + int original; + int verbosity; twolame_options *glopts; - int64_t next_pts; + int64_t next_pts; } TWOLAMEContext; static av_cold int twolame_encode_close(AVCodecContext *avctx) @@ -57,12 +60,13 @@ static av_cold int twolame_encode_init(AVCodecContext *avctx) int ret; avctx->frame_size = TWOLAME_SAMPLES_PER_FRAME; + avctx->delay = 512 - 32 + 1; s->glopts = twolame_init(); if (!s->glopts) return AVERROR(ENOMEM); - twolame_set_verbosity(s->glopts, 0); + twolame_set_verbosity(s->glopts, s->verbosity); twolame_set_mode(s->glopts, s->mode); twolame_set_psymodel(s->glopts, s->psymodel); twolame_set_energy_levels(s->glopts, s->energy); @@ -73,21 +77,27 @@ 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->bit_rate) + avctx->bit_rate = avctx->sample_rate < 28000 ? 160000 : 384000; + if (avctx->flags & CODEC_FLAG_QSCALE || !avctx->bit_rate) { twolame_set_VBR(s->glopts, TRUE); - twolame_set_VBR_level(s->glopts, avctx->global_quality); - av_log(avctx, AV_LOG_WARNING, "VBR mode is experimental!\n"); + twolame_set_VBR_level(s->glopts, + avctx->global_quality / (float) FF_QP2LAMBDA); + av_log(avctx, AV_LOG_WARNING, + "VBR in MP2 is a hack, use another codec that supports it.\n"); } else { twolame_set_bitrate(s->glopts, avctx->bit_rate / 1000); } - if ((ret = twolame_init_params(s->glopts))) - goto error; + ret = twolame_init_params(s->glopts); + if (ret) { + twolame_encode_close(avctx); + return AVERROR_UNKNOWN; + } return 0; -error: - twolame_encode_close(avctx); - return ret; } static int twolame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, @@ -103,96 +113,117 @@ static int twolame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, switch (avctx->sample_fmt) { case AV_SAMPLE_FMT_FLT: ret = twolame_encode_buffer_float32_interleaved(s->glopts, - frame->data[0], - frame->nb_samples, - avpkt->data, avpkt->size); + (const float *)frame->data[0], + frame->nb_samples, + avpkt->data, + avpkt->size); break; case AV_SAMPLE_FMT_FLTP: ret = twolame_encode_buffer_float32(s->glopts, - frame->data[0], frame->data[1], - frame->nb_samples, - avpkt->data, avpkt->size); + (const float *)frame->data[0], + (const float *)frame->data[1], + frame->nb_samples, + avpkt->data, avpkt->size); break; case AV_SAMPLE_FMT_S16: ret = twolame_encode_buffer_interleaved(s->glopts, - frame->data[0], - frame->nb_samples, - avpkt->data, avpkt->size); + (const short int *)frame->data[0], + frame->nb_samples, + avpkt->data, avpkt->size); break; case AV_SAMPLE_FMT_S16P: ret = twolame_encode_buffer(s->glopts, - frame->data[0], frame->data[1], + (const short int *)frame->data[0], + (const short int *)frame->data[1], frame->nb_samples, avpkt->data, avpkt->size); break; default: + av_log(avctx, AV_LOG_ERROR, + "Unsupported sample format %d.\n", avctx->sample_fmt); return AVERROR_BUG; } } else { ret = twolame_encode_flush(s->glopts, avpkt->data, avpkt->size); } - if (ret > 0) { - avpkt->duration = ff_samples_to_time_base(avctx, avctx->frame_size); - if (frame) { - if (frame->pts != AV_NOPTS_VALUE) - avpkt->pts = frame->pts; - } else { - avpkt->pts = s->next_pts; - } - if (avpkt->pts != AV_NOPTS_VALUE) - s->next_pts = avpkt->pts + avpkt->duration; - - avpkt->size = ret; - *got_packet_ptr = 1; + if (!ret) // no bytes written return 0; - } + if (ret < 0) // twolame error + return AVERROR_UNKNOWN; - return ret; + avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples); + if (frame) { + if (frame->pts != AV_NOPTS_VALUE) + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); + } else { + avpkt->pts = s->next_pts; + } + // this is for setting pts for flushed packet(s). + if (avpkt->pts != AV_NOPTS_VALUE) + s->next_pts = avpkt->pts + avpkt->duration; + + av_shrink_packet(avpkt, ret); + *got_packet_ptr = 1; + return 0; } #define OFFSET(x) offsetof(TWOLAMEContext, x) #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "mode", "Mpeg Mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = TWOLAME_AUTO_MODE }, TWOLAME_AUTO_MODE, TWOLAME_MONO, AE, "mode"}, - { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_AUTO_MODE }, 0, 0, AE, "mode" }, - { "stereo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_STEREO }, 0, 0, AE, "mode" }, - { "joint_stereo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_JOINT_STEREO }, 0, 0, AE, "mode" }, - { "dual_channel", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_DUAL_CHANNEL }, 0, 0, AE, "mode" }, - { "mono", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_MONO }, 0, 0, AE, "mode" }, - { "psymodel", "Psychoacoustic Model", OFFSET(psymodel), AV_OPT_TYPE_INT, { .i64 = 3 }, -1, 4, AE}, - { "energy_levels","enable energy levels", OFFSET(energy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE}, + { "mode", "Mpeg Mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = TWOLAME_AUTO_MODE }, TWOLAME_AUTO_MODE, TWOLAME_MONO, AE, "mode"}, + { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_AUTO_MODE }, 0, 0, AE, "mode" }, + { "stereo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_STEREO }, 0, 0, AE, "mode" }, + { "joint_stereo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_JOINT_STEREO }, 0, 0, AE, "mode" }, + { "dual_channel", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_DUAL_CHANNEL }, 0, 0, AE, "mode" }, + { "mono", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_MONO }, 0, 0, AE, "mode" }, + { "psymodel", "Psychoacoustic Model", OFFSET(psymodel), AV_OPT_TYPE_INT, { .i64 = 3 }, -1, 4, AE}, + { "energy_levels","enable energy levels", OFFSET(energy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE}, { "error_protection","enable CRC error protection", OFFSET(error_protection), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE}, - { "copyright", "set MPEG Audio Copyright flag", OFFSET(copyright), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE}, - { "original", "set MPEG Audio Original flag", OFFSET(original), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE}, + { "copyright", "set MPEG Audio Copyright flag", OFFSET(copyright), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE}, + { "original", "set MPEG Audio Original flag", OFFSET(original), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE}, + { "verbosity", "set library optput level (0-10)", OFFSET(verbosity), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 10, AE}, { NULL }, }; -static const AVClass libtwolame_class = { +static const AVClass twolame_class = { .class_name = "libtwolame encoder", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, }; +static const AVCodecDefault twolame_defaults[] = { + { "b", "0" }, + { NULL }, +}; + +static const int twolame_samplerates[] = { + 16000, 22050, 24000, 32000, 44100, 48000, 0 +}; + AVCodec ff_libtwolame_encoder = { - .name = "libtwolame", - .long_name = NULL_IF_CONFIG_SMALL("libtwolame MP2 (MPEG audio layer 2)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP2, - .priv_data_size = sizeof(TWOLAMEContext), - .init = twolame_encode_init, - .encode2 = twolame_encode_frame, - .close = twolame_encode_close, - .capabilities = CODEC_CAP_DELAY, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, - AV_SAMPLE_FMT_FLTP, - AV_SAMPLE_FMT_S16, - AV_SAMPLE_FMT_S16P, - AV_SAMPLE_FMT_NONE }, - .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, - AV_CH_LAYOUT_STEREO, - 0 }, - .supported_samplerates = (const int[]){ 16000, 22050, 24000, 32000, 44100, 48000, 0 }, - .priv_class = &libtwolame_class, + .name = "libtwolame", + .long_name = NULL_IF_CONFIG_SMALL("libtwolame MP2 (MPEG audio layer 2)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP2, + .priv_data_size = sizeof(TWOLAMEContext), + .init = twolame_encode_init, + .encode2 = twolame_encode_frame, + .close = twolame_encode_close, + .capabilities = CODEC_CAP_DELAY, + .defaults = twolame_defaults, + .priv_class = &twolame_class, + .sample_fmts = (const enum AVSampleFormat[]) { + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE + }, + .channel_layouts = (const uint64_t[]) { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + 0 }, + .supported_samplerates = twolame_samplerates, }; diff --git a/libavcodec/libutvideoenc.cpp b/libavcodec/libutvideoenc.cpp index ad70669a6..f0d56194b 100644 --- a/libavcodec/libutvideoenc.cpp +++ b/libavcodec/libutvideoenc.cpp @@ -44,12 +44,18 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) case AV_PIX_FMT_YUV420P: in_format = UTVF_YV12; avctx->bits_per_coded_sample = 12; - avctx->codec_tag = MKTAG('U', 'L', 'Y', '0'); + if (avctx->colorspace == AVCOL_SPC_BT709) + avctx->codec_tag = MKTAG('U', 'L', 'H', '0'); + else + avctx->codec_tag = MKTAG('U', 'L', 'Y', '0'); break; case AV_PIX_FMT_YUYV422: in_format = UTVF_YUYV; avctx->bits_per_coded_sample = 16; - avctx->codec_tag = MKTAG('U', 'L', 'Y', '2'); + if (avctx->colorspace == AVCOL_SPC_BT709) + avctx->codec_tag = MKTAG('U', 'L', 'H', '2'); + else + avctx->codec_tag = MKTAG('U', 'L', 'Y', '2'); break; case AV_PIX_FMT_BGR24: in_format = UTVF_NFCC_BGR_BU; diff --git a/libavcodec/libvorbisenc.c b/libavcodec/libvorbisenc.c index 6a7767028..ed6baa90d 100644 --- a/libavcodec/libvorbisenc.c +++ b/libavcodec/libvorbisenc.c @@ -183,7 +183,7 @@ static av_cold int libvorbis_encode_close(AVCodecContext *avctx) vorbis_dsp_clear(&s->vd); vorbis_info_clear(&s->vi); - av_fifo_free(s->pkt_fifo); + av_fifo_freep(&s->pkt_fifo); ff_af_queue_close(&s->afq); av_freep(&avctx->extradata); @@ -295,7 +295,7 @@ static int libvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) return ret; } else { - if (!s->eof) + if (!s->eof && s->afq.frame_alloc) if ((ret = vorbis_analysis_wrote(&s->vd, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "error in vorbis_analysis_wrote()\n"); return vorbis_error_to_averror(ret); diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 869c8fe11..3dddffd88 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -158,7 +158,7 @@ static av_cold void dump_enc_cfg(AVCodecContext *avctx, width, "g_lag_in_frames:", cfg->g_lag_in_frames); av_log(avctx, level, "rate control settings\n" " %*s%u\n %*s%u\n %*s%u\n %*s%u\n" - " %*s%d\n %*s%p(%zu)\n %*s%u\n", + " %*s%d\n %*s%p(%"SIZE_SPECIFIER")\n %*s%u\n", width, "rc_dropframe_thresh:", cfg->rc_dropframe_thresh, width, "rc_resize_allowed:", cfg->rc_resize_allowed, width, "rc_resize_up_thresh:", cfg->rc_resize_up_thresh, @@ -373,7 +373,7 @@ static av_cold int vpx_init(AVCodecContext *avctx, ctx->twopass_stats.buf = av_malloc(ctx->twopass_stats.sz); if (!ctx->twopass_stats.buf) { av_log(avctx, AV_LOG_ERROR, - "Stat buffer alloc (%zu bytes) failed\n", + "Stat buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n", ctx->twopass_stats.sz); return AVERROR(ENOMEM); } @@ -415,8 +415,7 @@ static av_cold int vpx_init(AVCodecContext *avctx, //codec control failures are currently treated only as warnings av_log(avctx, AV_LOG_DEBUG, "vpx_codec_control\n"); - if (ctx->cpu_used != INT_MIN) - codecctl_int(avctx, VP8E_SET_CPUUSED, ctx->cpu_used); + codecctl_int(avctx, VP8E_SET_CPUUSED, ctx->cpu_used); if (ctx->flags & VP8F_AUTO_ALT_REF) ctx->auto_alt_ref = 1; if (ctx->auto_alt_ref >= 0) @@ -616,7 +615,7 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out, if (!cx_frame->buf) { av_log(avctx, AV_LOG_ERROR, - "Data buffer alloc (%zu bytes) failed\n", + "Data buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n", cx_frame->sz); av_free(cx_frame); return AVERROR(ENOMEM); @@ -626,7 +625,7 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out, cx_frame->buf_alpha = av_malloc(cx_frame->sz_alpha); if (!cx_frame->buf_alpha) { av_log(avctx, AV_LOG_ERROR, - "Data buffer alloc (%zu bytes) failed\n", + "Data buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n", cx_frame->sz_alpha); av_free(cx_frame); return AVERROR(ENOMEM); @@ -754,7 +753,7 @@ static int vp8_encode(AVCodecContext *avctx, AVPacket *pkt, #endif #define COMMON_OPTIONS \ - { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used), AV_OPT_TYPE_INT, {.i64 = INT_MIN}, INT_MIN, INT_MAX, VE}, \ + { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, -16, 16, VE}, \ { "auto-alt-ref", "Enable use of alternate reference " \ "frames (2-pass only)", OFFSET(auto_alt_ref), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE}, \ { "lag-in-frames", "Number of frames to look ahead for " \ diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 685a066ce..edf6fc613 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/eval.h" #include "libavutil/internal.h" #include "libavutil/opt.h" #include "libavutil/mem.h" @@ -193,6 +194,39 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, 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->cqp >= 0 && + 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; @@ -330,6 +364,9 @@ static av_cold int X264_init(AVCodecContext *avctx) X264Context *x4 = avctx->priv_data; int sw,sh; + if (avctx->global_quality > 0) + av_log(avctx, AV_LOG_WARNING, "-qscale is ignored, -crf is recommended.\n"); + x264_param_default(&x4->params); x4->params.b_deblocking_filter = avctx->flags & CODEC_FLAG_LOOP_FILTER; @@ -423,6 +460,28 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.rc.f_qcompress = avctx->qcompress; /* 0.0 => cbr, 1.0 => constant qp */ if (avctx->refs >= 0) x4->params.i_frame_reference = avctx->refs; + else if (x4->level) { + int i; + int mbn = FF_CEIL_RSHIFT(avctx->width, 4) * FF_CEIL_RSHIFT(avctx->height, 4); + int level_id = -1; + char *tail; + int scale = X264_BUILD < 129 ? 384 : 1; + + if (!strcmp(x4->level, "1b")) { + level_id = 9; + } else if (strlen(x4->level) <= 3){ + level_id = av_strtod(x4->level, &tail) * 10 + 0.5; + if (*tail) + level_id = -1; + } + if (level_id <= 0) + av_log(avctx, AV_LOG_WARNING, "Failed to parse level\n"); + + for (i = 0; iparams.i_frame_reference = av_clip(x264_levels[i].dpb / mbn / scale, 1, x4->params.i_frame_reference); + } + if (avctx->trellis >= 0) x4->params.analyse.i_trellis = avctx->trellis; if (avctx->me_range >= 0) diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 31b85de99..4cf8c8572 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -20,6 +20,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#if defined(_MSC_VER) +#define X265_API_IMPORTS 1 +#endif + #include #include "libavutil/internal.h" @@ -29,17 +33,11 @@ #include "avcodec.h" #include "internal.h" -#if defined(_MSC_VER) -#define X265_API_IMPORTS 1 -#endif - typedef struct libx265Context { const AVClass *class; x265_encoder *encoder; x265_param *params; - uint8_t *header; - int header_size; char *preset; char *tune; @@ -66,7 +64,6 @@ static av_cold int libx265_encode_close(AVCodecContext *avctx) libx265Context *ctx = avctx->priv_data; av_frame_free(&avctx->coded_frame); - av_freep(&ctx->header); x265_param_free(ctx->params); @@ -80,18 +77,14 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) { libx265Context *ctx = avctx->priv_data; x265_nal *nal; - uint8_t *buf; - char sar[10]; + char sar[12]; int sar_num, sar_den; int nnal; - int ret; - int i; if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL && - !av_pix_fmt_desc_get(avctx->pix_fmt)->log2_chroma_w && - !av_pix_fmt_desc_get(avctx->pix_fmt)->log2_chroma_h) { + !av_pix_fmt_desc_get(avctx->pix_fmt)->log2_chroma_w) { av_log(avctx, AV_LOG_ERROR, - "4:4:4 support is not fully defined for HEVC yet. " + "4:2:2 and 4:4:4 support is not fully defined for HEVC yet. " "Set -strict experimental to encode anyway.\n"); return AVERROR(ENOSYS); } @@ -119,25 +112,26 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) ctx->params->sourceWidth = avctx->width; ctx->params->sourceHeight = avctx->height; - av_reduce(&sar_num, &sar_den, - avctx->sample_aspect_ratio.num, - avctx->sample_aspect_ratio.den, 4096); - snprintf(sar, sizeof(sar), "%d:%d", sar_num, sar_den); - if (x265_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; + if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) { + 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) { + av_log(avctx, AV_LOG_ERROR, "Invalid SAR: %d:%d.\n", sar_num, sar_den); + return AVERROR_INVALIDDATA; + } } - if (x265_max_bit_depth == 8) - ctx->params->internalBitDepth = 8; - else if (x265_max_bit_depth == 12) - ctx->params->internalBitDepth = 10; - switch (avctx->pix_fmt) { case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUV420P10: ctx->params->internalCsp = X265_CSP_I420; break; + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV422P10: + ctx->params->internalCsp = X265_CSP_I422; + break; case AV_PIX_FMT_YUV444P: case AV_PIX_FMT_YUV444P10: ctx->params->internalCsp = X265_CSP_I444; @@ -149,6 +143,9 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) ctx->params->rc.rateControlMode = X265_RC_ABR; } + if (!(avctx->flags & CODEC_FLAG_GLOBAL_HEADER)) + ctx->params->bRepeatHeaders = 1; + if (ctx->x265_opts) { AVDictionary *dict = NULL; AVDictionaryEntry *en = NULL; @@ -181,35 +178,23 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } - ret = x265_encoder_headers(ctx->encoder, &nal, &nnal); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n"); - libx265_encode_close(avctx); - return AVERROR_INVALIDDATA; - } - - for (i = 0; i < nnal; i++) - ctx->header_size += nal[i].sizeBytes; - - ctx->header = av_malloc(ctx->header_size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!ctx->header) { - av_log(avctx, AV_LOG_ERROR, - "Cannot allocate HEVC header of size %d.\n", ctx->header_size); - libx265_encode_close(avctx); - return AVERROR(ENOMEM); - } - - buf = ctx->header; - for (i = 0; i < nnal; i++) { - memcpy(buf, nal[i].payload, nal[i].sizeBytes); - buf += nal[i].sizeBytes; - } - if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { - avctx->extradata_size = ctx->header_size; - avctx->extradata = ctx->header; - ctx->header_size = 0; - ctx->header = NULL; + avctx->extradata_size = x265_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); + if (!avctx->extradata) { + av_log(avctx, AV_LOG_ERROR, + "Cannot allocate HEVC header of size %d.\n", avctx->extradata_size); + libx265_encode_close(avctx); + return AVERROR(ENOMEM); + } + + memcpy(avctx->extradata, nal[0].payload, avctx->extradata_size); } return 0; @@ -251,8 +236,6 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, for (i = 0; i < nnal; i++) payload += nal[i].sizeBytes; - payload += ctx->header_size; - ret = ff_alloc_packet(pkt, payload); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); @@ -260,14 +243,6 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } dst = pkt->data; - if (ctx->header) { - memcpy(dst, ctx->header, ctx->header_size); - dst += ctx->header_size; - - av_freep(&ctx->header); - ctx->header_size = 0; - } - for (i = 0; i < nnal; i++) { memcpy(dst, nal[i].payload, nal[i].sizeBytes); dst += nal[i].sizeBytes; @@ -285,14 +260,17 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, static const enum AVPixelFormat x265_csp_eight[] = { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }; static const enum AVPixelFormat x265_csp_twelve[] = { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV420P10, + AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_NONE }; diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c index ffe3411c9..92dceceac 100644 --- a/libavcodec/libxavs.c +++ b/libavcodec/libxavs.c @@ -353,7 +353,7 @@ static av_cold int XAVS_init(AVCodecContext *avctx) if (!x4->enc) return -1; - if (!(x4->pts_buffer = av_mallocz((avctx->max_b_frames+1) * sizeof(*x4->pts_buffer)))) + if (!(x4->pts_buffer = av_mallocz_array((avctx->max_b_frames+1), sizeof(*x4->pts_buffer)))) return AVERROR(ENOMEM); avctx->coded_frame = av_frame_alloc(); diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c index 97ab2d4a0..e60b2d8f9 100644 --- a/libavcodec/libxvid.c +++ b/libavcodec/libxvid.c @@ -26,7 +26,6 @@ */ #include -#include #include "avcodec.h" #include "internal.h" #include "libavutil/file.h" @@ -36,6 +35,10 @@ #include "libxvid.h" #include "mpegvideo.h" +#if HAVE_UNISTD_H +#include +#endif + /** * Buffer management macros. */ @@ -67,6 +70,7 @@ struct xvid_context { int variance_aq; /**< Variance adaptive quantization */ int ssim; /**< SSIM information display mode */ int ssim_acc; /**< SSIM accuracy. 0: accurate. 4: fast. */ + int gmc; }; /** @@ -422,8 +426,13 @@ static av_cold int xvid_encode_init(AVCodecContext *avctx) { } /* Bring in VOL flags from ffmpeg command-line */ +#if FF_API_GMC + if (avctx->flags & CODEC_FLAG_GMC) + x->gmc = 1; +#endif + x->vol_flags = 0; - if( xvid_flags & CODEC_FLAG_GMC ) { + if (x->gmc) { x->vol_flags |= XVID_VOL_GMC; x->me_flags |= XVID_ME_GME_REFINE; } @@ -531,25 +540,26 @@ static av_cold int xvid_encode_init(AVCodecContext *avctx) { xvid_enc_create.num_plugins++; } - if ( avctx->lumi_masking != 0.0) + if (avctx->lumi_masking != 0.0) x->lumi_aq = 1; /* Luminance Masking */ - if( x->lumi_aq ) { + if (x->lumi_aq) { 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 ) { + if (x->variance_aq) { masking_v.method = 1; plugins[xvid_enc_create.num_plugins].func = xvid_plugin_lumimasking; - plugins[xvid_enc_create.num_plugins].param = &masking_v ; + plugins[xvid_enc_create.num_plugins].param = &masking_v; xvid_enc_create.num_plugins++; } @@ -559,9 +569,9 @@ static av_cold int xvid_encode_init(AVCodecContext *avctx) { "will be the worse one of the two effects made by the AQ.\n"); /* SSIM */ - if( x->ssim ) { + if (x->ssim) { plugins[xvid_enc_create.num_plugins].func = xvid_plugin_ssim; - ssim.b_printstat = ( x->ssim == 2 ); + ssim.b_printstat = x->ssim == 2; ssim.acc = x->ssim_acc; ssim.cpu_flags = xvid_gbl_init.cpu_flags; ssim.b_visualize = 0; @@ -688,7 +698,7 @@ static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt, /* Initialize input image fields */ if( avctx->pix_fmt != AV_PIX_FMT_YUV420P ) { av_log(avctx, AV_LOG_ERROR, "Xvid: Color spaces other than 420p not supported\n"); - return -1; + return AVERROR(EINVAL); } xvid_enc_frame.input.csp = XVID_CSP_PLANAR; /* YUV420P */ @@ -775,7 +785,7 @@ static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (!xerr) return 0; av_log(avctx, AV_LOG_ERROR, "Xvid: Encoding Error Occurred: %i\n", xerr); - return -1; + return AVERROR_EXTERNAL; } } @@ -814,6 +824,7 @@ static const AVOption options[] = { { "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 }, { NULL }, }; diff --git a/libavcodec/libxvid_rc.c b/libavcodec/libxvid_rc.c index 5da435b00..1351dcde6 100644 --- a/libavcodec/libxvid_rc.c +++ b/libavcodec/libxvid_rc.c @@ -22,13 +22,16 @@ #include "config.h" #include -#include #include "libavutil/attributes.h" #include "libavutil/file.h" #include "avcodec.h" #include "libxvid.h" #include "mpegvideo.h" +#if HAVE_UNISTD_H +#include +#endif + #undef NDEBUG #include diff --git a/libavcodec/libzvbi-teletextdec.c b/libavcodec/libzvbi-teletextdec.c index 4129bacb7..e65e3fb55 100644 --- a/libavcodec/libzvbi-teletextdec.c +++ b/libavcodec/libzvbi-teletextdec.c @@ -23,6 +23,7 @@ #include "libavutil/opt.h" #include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" +#include "libavutil/log.h" #include @@ -36,6 +37,7 @@ #define MAX_BUFFERED_PAGES 25 #define BITMAP_CHAR_WIDTH 12 #define BITMAP_CHAR_HEIGHT 10 +#define MAX_SLICES 64 typedef struct TeletextPage { @@ -64,11 +66,10 @@ typedef struct TeletextContext int handler_ret; vbi_decoder * vbi; - vbi_dvb_demux * dx; #ifdef DEBUG vbi_export * ex; #endif - vbi_sliced sliced[64]; + vbi_sliced sliced[MAX_SLICES]; } TeletextContext; static int chop_spaces_utf8(const unsigned char* t, int len) @@ -272,10 +273,7 @@ static int gen_sub_bitmap(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_pa b = VBI_B(page->color_map[ci]); a = VBI_A(page->color_map[ci]); ((uint32_t *)sub_rect->pict.data[1])[ci] = RGBA(r, g, b, a); -#ifdef DEBUG - av_log(ctx, AV_LOG_DEBUG, "palette %0x\n", - ((uint32_t *)sub_rect->pict.data[1])[ci]); -#endif + av_dlog(ctx, "palette %0x\n", ((uint32_t *)sub_rect->pict.data[1])[ci]); } ((uint32_t *)sub_rect->pict.data[1])[cmax] = RGBA(0, 0, 0, 0); sub_rect->type = SUBTITLE_BITMAP; @@ -360,15 +358,46 @@ static void handler(vbi_event *ev, void *user_data) vbi_unref_page(&page); } +static inline int data_identifier_is_teletext(int data_identifier) { + /* See EN 301 775 section 4.4.2. */ + return (data_identifier >= 0x10 && data_identifier <= 0x1F || + data_identifier >= 0x99 && data_identifier <= 0x9B); +} + +static int slice_to_vbi_lines(TeletextContext *ctx, uint8_t* buf, int size) +{ + int lines = 0; + while (size >= 2 && lines < MAX_SLICES) { + int data_unit_id = buf[0]; + int data_unit_length = buf[1]; + if (data_unit_length + 2 > size) + return AVERROR_INVALIDDATA; + if (data_unit_id == 0x02 || data_unit_id == 0x03) { + if (data_unit_length != 0x2c) + return AVERROR_INVALIDDATA; + else { + int line_offset = buf[2] & 0x1f; + int field_parity = buf[2] & 0x20; + int i; + ctx->sliced[lines].id = VBI_SLICED_TELETEXT_B; + ctx->sliced[lines].line = (line_offset > 0 ? (line_offset + (field_parity ? 0 : 313)) : 0); + for (i = 0; i < 42; i++) + ctx->sliced[lines].data[i] = vbi_rev8(buf[4 + i]); + lines++; + } + } + size -= data_unit_length + 2; + buf += data_unit_length + 2; + } + if (size) + av_log(ctx, AV_LOG_WARNING, "%d bytes remained after slicing data\n", size); + return lines; +} + static int teletext_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *pkt) { TeletextContext *ctx = avctx->priv_data; AVSubtitle *sub = data; - const uint8_t *buf = pkt->data; - int left = pkt->size; - uint8_t pesheader[45] = {0x00, 0x00, 0x01, 0xbd, 0x00, 0x00, 0x85, 0x80, 0x24, 0x21, 0x00, 0x01, 0x00, 0x01}; - int pesheader_size = sizeof(pesheader); - const uint8_t *pesheader_buf = pesheader; int ret = 0; if (!ctx->vbi) { @@ -380,43 +409,34 @@ static int teletext_decode_frame(AVCodecContext *avctx, void *data, int *data_si return AVERROR(ENOMEM); } } - if (!ctx->dx && (!(ctx->dx = vbi_dvb_pes_demux_new (/* callback */ NULL, NULL)))) - return AVERROR(ENOMEM); if (avctx->pkt_timebase.den && pkt->pts != AV_NOPTS_VALUE) ctx->pts = av_rescale_q(pkt->pts, avctx->pkt_timebase, AV_TIME_BASE_Q); - if (left) { + if (pkt->size) { + int lines; + const int full_pes_size = pkt->size + 45; /* PES header is 45 bytes */ + // We allow unreasonably big packets, even if the standard only allows a max size of 1472 - if ((pesheader_size + left) < 184 || (pesheader_size + left) > 65504 || (pesheader_size + left) % 184 != 0) + if (full_pes_size < 184 || full_pes_size > 65504 || full_pes_size % 184 != 0) return AVERROR_INVALIDDATA; - memset(pesheader + 14, 0xff, pesheader_size - 14); - AV_WB16(pesheader + 4, left + pesheader_size - 6); - - /* PTS is deliberately left as 0 in the PES header, otherwise libzvbi uses - * it to detect dropped frames. Unforunatey the guessed packet PTS values - * (see mpegts demuxer) are not accurate enough to pass that test. */ - vbi_dvb_demux_cor(ctx->dx, ctx->sliced, 64, NULL, &pesheader_buf, &pesheader_size); - ctx->handler_ret = pkt->size; - while (left > 0) { - int64_t pts = 0; - unsigned int lines = vbi_dvb_demux_cor(ctx->dx, ctx->sliced, 64, &pts, &buf, &left); -#ifdef DEBUG - av_log(avctx, AV_LOG_DEBUG, - "ctx=%p buf_size=%d left=%u lines=%u pts=%f pkt_pts=%f\n", - ctx, pkt->size, left, lines, (double)pts/90000.0, (double)pkt->pts/90000.0); -#endif + if (data_identifier_is_teletext(*pkt->data)) { + if ((lines = slice_to_vbi_lines(ctx, pkt->data + 1, pkt->size - 1)) < 0) + return lines; + av_dlog(avctx, "ctx=%p buf_size=%d lines=%u pkt_pts=%7.3f\n", + ctx, pkt->size, lines, (double)pkt->pts/90000.0); if (lines > 0) { -#ifdef DEBUGx +#ifdef DEBUG int i; - for(i=0; isliced[i].id); + av_log(avctx, AV_LOG_DEBUG, "line numbers:"); + for(i = 0; i < lines; i++) + av_log(avctx, AV_LOG_DEBUG, " %d", ctx->sliced[i].line); + av_log(avctx, AV_LOG_DEBUG, "\n"); #endif - vbi_decode(ctx->vbi, ctx->sliced, lines, (double)pts/90000.0); + vbi_decode(ctx->vbi, ctx->sliced, lines, 0.0); ctx->lines_processed += lines; } } @@ -437,7 +457,7 @@ static int teletext_decode_frame(AVCodecContext *avctx, void *data, int *data_si sub->pts = ctx->pages->pts; if (ctx->pages->sub_rect->type != SUBTITLE_NONE) { - sub->rects = av_malloc(sizeof(*sub->rects) * 1); + sub->rects = av_malloc(sizeof(*sub->rects)); if (sub->rects) { sub->num_rects = 1; sub->rects[0] = ctx->pages->sub_rect; @@ -479,7 +499,6 @@ static int teletext_init_decoder(AVCodecContext *avctx) avctx->height = 25 * BITMAP_CHAR_HEIGHT; } - ctx->dx = NULL; ctx->vbi = NULL; ctx->pts = AV_NOPTS_VALUE; @@ -497,16 +516,12 @@ static int teletext_close_decoder(AVCodecContext *avctx) { TeletextContext *ctx = avctx->priv_data; -#ifdef DEBUG - av_log(avctx, AV_LOG_DEBUG, "lines_total=%u\n", ctx->lines_processed); -#endif + av_dlog(avctx, "lines_total=%u\n", ctx->lines_processed); while (ctx->nb_pages) subtitle_rect_free(&ctx->pages[--ctx->nb_pages].sub_rect); av_freep(&ctx->pages); - vbi_dvb_demux_delete(ctx->dx); vbi_decoder_delete(ctx->vbi); - ctx->dx = NULL; ctx->vbi = NULL; ctx->pts = AV_NOPTS_VALUE; return 0; diff --git a/libavcodec/ljpegenc.c b/libavcodec/ljpegenc.c index b7e3d358c..19ae1517b 100644 --- a/libavcodec/ljpegenc.c +++ b/libavcodec/ljpegenc.c @@ -35,14 +35,15 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" -#include "dsputil.h" +#include "idctdsp.h" #include "internal.h" +#include "mjpegenc_common.h" #include "mpegvideo.h" #include "mjpeg.h" #include "mjpegenc.h" typedef struct LJpegEncContext { - DSPContext dsp; + IDCTDSPContext idsp; ScanTable scantable; uint16_t matrix[64]; @@ -275,7 +276,8 @@ static av_cold int ljpeg_encode_init(AVCodecContext *avctx) if ((avctx->pix_fmt == AV_PIX_FMT_YUV420P || avctx->pix_fmt == AV_PIX_FMT_YUV422P || - avctx->pix_fmt == AV_PIX_FMT_YUV444P) && + avctx->pix_fmt == AV_PIX_FMT_YUV444P || + avctx->color_range == AVCOL_RANGE_MPEG) && avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { av_log(avctx, AV_LOG_ERROR, "Limited range YUV is non-standard, set strict_std_compliance to " @@ -292,8 +294,9 @@ static av_cold int ljpeg_encode_init(AVCodecContext *avctx) s->scratch = av_malloc_array(avctx->width + 1, sizeof(*s->scratch)); - ff_dsputil_init(&s->dsp, avctx); - ff_init_scantable(s->dsp.idct_permutation, &s->scantable, ff_zigzag_direct); + ff_idctdsp_init(&s->idsp, avctx); + ff_init_scantable(s->idsp.idct_permutation, &s->scantable, + ff_zigzag_direct); ff_mjpeg_init_hvsample(avctx, s->hsample, s->vsample); @@ -318,6 +321,7 @@ AVCodec ff_ljpeg_encoder = { .init = ljpeg_encode_init, .encode2 = ljpeg_encode_frame, .close = ljpeg_encode_close, + .capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24 , AV_PIX_FMT_BGRA , AV_PIX_FMT_BGR0, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, diff --git a/libavcodec/lossless_audiodsp.c b/libavcodec/lossless_audiodsp.c new file mode 100644 index 000000000..32f4c9e85 --- /dev/null +++ b/libavcodec/lossless_audiodsp.c @@ -0,0 +1,49 @@ +/* + * Monkey's Audio lossless audio decoder + * Copyright (c) 2007 Benjamin Zores + * based upon libdemac from Dave Chapman. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "lossless_audiodsp.h" + +static int32_t scalarproduct_and_madd_int16_c(int16_t *v1, const int16_t *v2, + const int16_t *v3, + int order, int mul) +{ + int res = 0; + + while (order--) { + res += *v1 * *v2++; + *v1++ += mul * *v3++; + } + return res; +} + +av_cold void ff_llauddsp_init(LLAudDSPContext *c) +{ + c->scalarproduct_and_madd_int16 = scalarproduct_and_madd_int16_c; + + if (ARCH_ARM) + ff_llauddsp_init_arm(c); + if (ARCH_PPC) + ff_llauddsp_init_ppc(c); + if (ARCH_X86) + ff_llauddsp_init_x86(c); +} diff --git a/libavcodec/lossless_audiodsp.h b/libavcodec/lossless_audiodsp.h new file mode 100644 index 000000000..4c2750284 --- /dev/null +++ b/libavcodec/lossless_audiodsp.h @@ -0,0 +1,45 @@ +/* + * Monkey's Audio lossless audio decoder + * Copyright (c) 2007 Benjamin Zores + * based upon libdemac from Dave Chapman. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LLAUDDSP_H +#define AVCODEC_LLAUDDSP_H + +#include + +typedef struct LLAudDSPContext { + /** + * Calculate scalar product of v1 and v2, + * and v1[i] += v3[i] * mul + * @param len length of vectors, should be multiple of 16 + */ + int32_t (*scalarproduct_and_madd_int16)(int16_t *v1 /* align 16 */, + const int16_t *v2, + const int16_t *v3, + int len, int mul); +} LLAudDSPContext; + +void ff_llauddsp_init(LLAudDSPContext *c); +void ff_llauddsp_init_arm(LLAudDSPContext *c); +void ff_llauddsp_init_ppc(LLAudDSPContext *c); +void ff_llauddsp_init_x86(LLAudDSPContext *c); + +#endif /* AVCODEC_LLAUDDSP_H */ diff --git a/libavcodec/lossless_videodsp.c b/libavcodec/lossless_videodsp.c index ca55e6e7c..3491621dc 100644 --- a/libavcodec/lossless_videodsp.c +++ b/libavcodec/lossless_videodsp.c @@ -60,7 +60,7 @@ static void diff_int16_c(uint16_t *dst, const uint16_t *src1, const uint16_t *sr dst[i] = (src1[i] - src2[i]) & mask; } -static void add_hfyu_median_prediction_int16_c(uint16_t *dst, const uint16_t *src, const uint16_t *diff, unsigned mask, int w, int *left, int *left_top){ +static void add_hfyu_median_pred_int16_c(uint16_t *dst, const uint16_t *src, const uint16_t *diff, unsigned mask, int w, int *left, int *left_top){ int i; uint16_t l, lt; @@ -77,7 +77,7 @@ static void add_hfyu_median_prediction_int16_c(uint16_t *dst, const uint16_t *sr *left_top = lt; } -static void sub_hfyu_median_prediction_int16_c(uint16_t *dst, const uint16_t *src1, const uint16_t *src2, unsigned mask, int w, int *left, int *left_top){ +static void sub_hfyu_median_pred_int16_c(uint16_t *dst, const uint16_t *src1, const uint16_t *src2, unsigned mask, int w, int *left, int *left_top){ int i; uint16_t l, lt; @@ -95,7 +95,7 @@ static void sub_hfyu_median_prediction_int16_c(uint16_t *dst, const uint16_t *sr *left_top = lt; } -static int add_hfyu_left_prediction_int16_c(uint16_t *dst, const uint16_t *src, unsigned mask, int w, unsigned acc){ +static int add_hfyu_left_pred_int16_c(uint16_t *dst, const uint16_t *src, unsigned mask, int w, unsigned acc){ int i; for(i=0; iadd_int16 = add_int16_c; c->diff_int16= diff_int16_c; - c->add_hfyu_left_prediction_int16 = add_hfyu_left_prediction_int16_c; - c->add_hfyu_median_prediction_int16 = add_hfyu_median_prediction_int16_c; - c->sub_hfyu_median_prediction_int16 = sub_hfyu_median_prediction_int16_c; + c->add_hfyu_left_pred_int16 = add_hfyu_left_pred_int16_c; + c->add_hfyu_median_pred_int16 = add_hfyu_median_pred_int16_c; + c->sub_hfyu_median_pred_int16 = sub_hfyu_median_pred_int16_c; if (ARCH_X86) ff_llviddsp_init_x86(c, avctx); diff --git a/libavcodec/lossless_videodsp.h b/libavcodec/lossless_videodsp.h index c656fa14c..040902e7b 100644 --- a/libavcodec/lossless_videodsp.h +++ b/libavcodec/lossless_videodsp.h @@ -29,9 +29,9 @@ typedef struct LLVidDSPContext { void (*add_int16)(uint16_t *dst/*align 16*/, const uint16_t *src/*align 16*/, unsigned mask, int w); void (*diff_int16)(uint16_t *dst/*align 16*/, const uint16_t *src1/*align 16*/, const uint16_t *src2/*align 1*/, unsigned mask, int w); - void (*sub_hfyu_median_prediction_int16)(uint16_t *dst, const uint16_t *src1, const uint16_t *src2, unsigned mask, int w, int *left, int *left_top); - void (*add_hfyu_median_prediction_int16)(uint16_t *dst, const uint16_t *top, const uint16_t *diff, unsigned mask, int w, int *left, int *left_top); - int (*add_hfyu_left_prediction_int16)(uint16_t *dst, const uint16_t *src, unsigned mask, int w, int left); + void (*sub_hfyu_median_pred_int16)(uint16_t *dst, const uint16_t *src1, const uint16_t *src2, unsigned mask, int w, int *left, int *left_top); + void (*add_hfyu_median_pred_int16)(uint16_t *dst, const uint16_t *top, const uint16_t *diff, unsigned mask, int w, int *left, int *left_top); + int (*add_hfyu_left_pred_int16)(uint16_t *dst, const uint16_t *src, unsigned mask, int w, unsigned left); } LLVidDSPContext; void ff_llviddsp_init(LLVidDSPContext *llviddsp, AVCodecContext *avctx); diff --git a/libavcodec/lzwenc.c b/libavcodec/lzwenc.c index d5a07bc7b..03080ee58 100644 --- a/libavcodec/lzwenc.c +++ b/libavcodec/lzwenc.c @@ -26,8 +26,9 @@ */ #include "avcodec.h" -#include "put_bits.h" #include "lzw.h" +#include "mathops.h" +#include "put_bits.h" #define LZW_MAXBITS 12 #define LZW_SIZTABLE (1<> 32)) #endif /* FASTDIV */ -#ifndef MOD_UNLIKELY -# define MOD_UNLIKELY(modulus, dividend, divisor, prev_dividend) \ - do { \ - if ((prev_dividend) == 0 || (dividend) - (prev_dividend) != (divisor)) \ - (modulus) = (dividend) % (divisor); \ - (prev_dividend) = (dividend); \ - } while (0) -#endif - static inline av_const unsigned int ff_sqrt(unsigned int a) { unsigned int b; diff --git a/libavcodec/mathtables.c b/libavcodec/mathtables.c index ec5ba7942..a07ac50c0 100644 --- a/libavcodec/mathtables.c +++ b/libavcodec/mathtables.c @@ -20,6 +20,8 @@ #include +#include "mathops.h" + /* a*inverse[b]>>32 == a/b for all 0<=a<=16909558 && 2<=b<=256 * for a>16909558, is an overestimate by less than 1 part in 1<<24 */ const uint32_t ff_inverse[257]={ @@ -91,7 +93,7 @@ const uint8_t ff_reverse[256] = { #define times4(x) x, x, x, x #define times256(x) times4(times4(times4(times4(times4(x))))) -const uint8_t ff_cropTbl[256 + 2 * 1024] = { +const uint8_t ff_crop_tab[256 + 2 * MAX_NEG_CROP] = { times256(0x00), 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, diff --git a/libavcodec/mdct_template.c b/libavcodec/mdct_template.c index a66ac4c47..7fa8bcce5 100644 --- a/libavcodec/mdct_template.c +++ b/libavcodec/mdct_template.c @@ -60,7 +60,7 @@ 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->tcos = av_malloc(n/2 * sizeof(FFTSample)); + s->tcos = av_malloc_array(n/2, sizeof(FFTSample)); if (!s->tcos) goto fail; diff --git a/libavcodec/mdec.c b/libavcodec/mdec.c index 1567e14a1..051adaefe 100644 --- a/libavcodec/mdec.c +++ b/libavcodec/mdec.c @@ -28,13 +28,18 @@ */ #include "avcodec.h" +#include "blockdsp.h" +#include "bswapdsp.h" +#include "idctdsp.h" #include "mpegvideo.h" #include "mpeg12.h" #include "thread.h" typedef struct MDECContext { AVCodecContext *avctx; - DSPContext dsp; + BlockDSPContext bdsp; + BswapDSPContext bbdsp; + IDCTDSPContext idsp; ThreadFrame frame; GetBitContext gb; ScanTable scantable; @@ -123,7 +128,7 @@ static inline int decode_mb(MDECContext *a, int16_t block[6][64]) int i, ret; static const int block_index[6] = { 5, 4, 0, 1, 2, 3 }; - a->dsp.clear_blocks(block[0]); + a->bdsp.clear_blocks(block[0]); for (i = 0; i < 6; i++) { if ((ret = mdec_decode_block_intra(a, block[block_index[i]], @@ -144,14 +149,14 @@ static inline void idct_put(MDECContext *a, AVFrame *frame, int mb_x, int mb_y) uint8_t *dest_cb = frame->data[1] + (mb_y * 8 * frame->linesize[1]) + mb_x * 8; uint8_t *dest_cr = frame->data[2] + (mb_y * 8 * frame->linesize[2]) + mb_x * 8; - a->dsp.idct_put(dest_y, linesize, block[0]); - a->dsp.idct_put(dest_y + 8, linesize, block[1]); - a->dsp.idct_put(dest_y + 8 * linesize, linesize, block[2]); - a->dsp.idct_put(dest_y + 8 * linesize + 8, linesize, block[3]); + 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)) { - a->dsp.idct_put(dest_cb, frame->linesize[1], block[4]); - a->dsp.idct_put(dest_cr, frame->linesize[2], block[5]); + a->idsp.idct_put(dest_cb, frame->linesize[1], block[4]); + a->idsp.idct_put(dest_cr, frame->linesize[2], block[5]); } } @@ -173,7 +178,7 @@ static int decode_frame(AVCodecContext *avctx, av_fast_padded_malloc(&a->bitstream_buffer, &a->bitstream_buffer_size, buf_size); if (!a->bitstream_buffer) return AVERROR(ENOMEM); - a->dsp.bswap16_buf((uint16_t *)a->bitstream_buffer, (uint16_t *)buf, (buf_size + 1) / 2); + a->bbdsp.bswap16_buf((uint16_t *)a->bitstream_buffer, (uint16_t *)buf, (buf_size + 1) / 2); if ((ret = init_get_bits8(&a->gb, a->bitstream_buffer, buf_size)) < 0) return ret; @@ -208,13 +213,17 @@ static av_cold int decode_init(AVCodecContext *avctx) a->avctx = avctx; - ff_dsputil_init(&a->dsp, avctx); + ff_blockdsp_init(&a->bdsp, avctx); + ff_bswapdsp_init(&a->bbdsp); + ff_idctdsp_init(&a->idsp, avctx); ff_mpeg12_init_vlcs(); - ff_init_scantable(a->dsp.idct_permutation, &a->scantable, ff_zigzag_direct); + ff_init_scantable(a->idsp.idct_permutation, &a->scantable, + ff_zigzag_direct); if (avctx->idct_algo == FF_IDCT_AUTO) avctx->idct_algo = FF_IDCT_SIMPLE; avctx->pix_fmt = AV_PIX_FMT_YUVJ420P; + avctx->color_range = AVCOL_RANGE_JPEG; return 0; } diff --git a/libavcodec/metasound.c b/libavcodec/metasound.c index 677e959d4..2dab135bd 100644 --- a/libavcodec/metasound.c +++ b/libavcodec/metasound.c @@ -21,6 +21,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include @@ -283,7 +284,7 @@ static av_cold int metasound_decode_init(AVCodecContext *avctx) for (;;) { if (!props->tag) { - av_log(avctx, AV_LOG_ERROR, "Could not find tag %08X\n", tag); + av_log(avctx, AV_LOG_ERROR, "Could not find tag %08"PRIX32"\n", tag); return AVERROR_INVALIDDATA; } if (props->tag == tag) { diff --git a/libavcodec/mimic.c b/libavcodec/mimic.c index 31d63931a..24724fa75 100644 --- a/libavcodec/mimic.c +++ b/libavcodec/mimic.c @@ -24,11 +24,13 @@ #include #include "avcodec.h" +#include "blockdsp.h" #include "internal.h" #include "get_bits.h" #include "bytestream.h" -#include "dsputil.h" +#include "bswapdsp.h" #include "hpeldsp.h" +#include "idctdsp.h" #include "thread.h" #define MIMIC_HEADER_SIZE 20 @@ -52,8 +54,10 @@ typedef struct { GetBitContext gb; ScanTable scantable; - DSPContext dsp; + BlockDSPContext bdsp; + BswapDSPContext bbdsp; HpelDSPContext hdsp; + IDCTDSPContext idsp; VLC vlc; /* Kept in the context so multithreading can have a constant to read from */ @@ -146,9 +150,11 @@ static av_cold int mimic_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "error initializing vlc table\n"); return ret; } - ff_dsputil_init(&ctx->dsp, avctx); + ff_blockdsp_init(&ctx->bdsp, avctx); + ff_bswapdsp_init(&ctx->bbdsp); ff_hpeldsp_init(&ctx->hdsp, avctx->flags); - ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, col_zag); + ff_idctdsp_init(&ctx->idsp, avctx); + ff_init_scantable(ctx->idsp.idct_permutation, &ctx->scantable, col_zag); for (i = 0; i < FF_ARRAY_ELEMS(ctx->frames); i++) { ctx->frames[i].f = av_frame_alloc(); @@ -228,7 +234,7 @@ static int vlc_decode_block(MimicContext *ctx, int num_coeffs, int qscale) int16_t *block = ctx->dct_block; unsigned int pos; - ctx->dsp.clear_block(block); + ctx->bdsp.clear_block(block); block[0] = get_bits(&ctx->gb, 8) << 3; @@ -297,7 +303,7 @@ static int decode(MimicContext *ctx, int quality, int num_coeffs, "block.\n"); return ret; } - ctx->dsp.idct_put(dst, stride, ctx->dct_block); + ctx->idsp.idct_put(dst, stride, ctx->dct_block); } else { unsigned int backref = get_bits(&ctx->gb, 4); int index = (ctx->cur_index + backref) & 15; @@ -421,9 +427,9 @@ static int mimic_decode_frame(AVCodecContext *avctx, void *data, if (!ctx->swap_buf) return AVERROR(ENOMEM); - ctx->dsp.bswap_buf(ctx->swap_buf, - (const uint32_t*) (buf + MIMIC_HEADER_SIZE), - swap_buf_size >> 2); + ctx->bbdsp.bswap_buf(ctx->swap_buf, + (const uint32_t *) (buf + MIMIC_HEADER_SIZE), + swap_buf_size >> 2); init_get_bits(&ctx->gb, ctx->swap_buf, swap_buf_size << 3); res = decode(ctx, quality, num_coeffs, !is_pframe); diff --git a/libavcodec/mjpeg.h b/libavcodec/mjpeg.h index 96e18545a..73db1dd1e 100644 --- a/libavcodec/mjpeg.h +++ b/libavcodec/mjpeg.h @@ -33,10 +33,11 @@ #ifndef AVCODEC_MJPEG_H #define AVCODEC_MJPEG_H +#include "libavutil/internal.h" + #include "avcodec.h" #include "put_bits.h" - /* JPEG marker codes */ typedef enum { /* start of frame */ diff --git a/libavcodec/mjpeg2jpeg_bsf.c b/libavcodec/mjpeg2jpeg_bsf.c index f3672881b..6adeaf0ac 100644 --- a/libavcodec/mjpeg2jpeg_bsf.c +++ b/libavcodec/mjpeg2jpeg_bsf.c @@ -25,6 +25,10 @@ */ #include + +#include "libavutil/error.h" +#include "libavutil/mem.h" + #include "avcodec.h" #include "mjpeg.h" diff --git a/libavcodec/mjpegbdec.c b/libavcodec/mjpegbdec.c index 61640952f..f6ee7057f 100644 --- a/libavcodec/mjpegbdec.c +++ b/libavcodec/mjpegbdec.c @@ -24,6 +24,8 @@ * Apple MJPEG-B decoder. */ +#include + #include "avcodec.h" #include "mjpeg.h" #include "mjpegdec.h" @@ -74,13 +76,14 @@ read_header: } field_size = get_bits_long(&hgb, 32); /* field size */ - av_log(avctx, AV_LOG_DEBUG, "field size: 0x%x\n", field_size); + av_log(avctx, AV_LOG_DEBUG, "field size: 0x%"PRIx32"\n", field_size); skip_bits(&hgb, 32); /* padded field size */ second_field_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "second_field_offs is %d and size is %d\n"); - av_log(avctx, AV_LOG_DEBUG, "second field offs: 0x%x\n", second_field_offs); + av_log(avctx, AV_LOG_DEBUG, "second field offs: 0x%"PRIx32"\n", + second_field_offs); dqt_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "dqt is %d and size is %d\n"); - av_log(avctx, AV_LOG_DEBUG, "dqt offs: 0x%x\n", dqt_offs); + av_log(avctx, AV_LOG_DEBUG, "dqt offs: 0x%"PRIx32"\n", dqt_offs); if (dqt_offs) { init_get_bits(&s->gb, buf_ptr+dqt_offs, (buf_end - (buf_ptr+dqt_offs))*8); @@ -91,7 +94,7 @@ read_header: } dht_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "dht is %d and size is %d\n"); - av_log(avctx, AV_LOG_DEBUG, "dht offs: 0x%x\n", dht_offs); + av_log(avctx, AV_LOG_DEBUG, "dht offs: 0x%"PRIx32"\n", dht_offs); if (dht_offs) { init_get_bits(&s->gb, buf_ptr+dht_offs, (buf_end - (buf_ptr+dht_offs))*8); @@ -100,7 +103,7 @@ read_header: } sof_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "sof is %d and size is %d\n"); - av_log(avctx, AV_LOG_DEBUG, "sof offs: 0x%x\n", sof_offs); + av_log(avctx, AV_LOG_DEBUG, "sof offs: 0x%"PRIx32"\n", sof_offs); if (sof_offs) { init_get_bits(&s->gb, buf_ptr+sof_offs, (buf_end - (buf_ptr+sof_offs))*8); @@ -110,9 +113,9 @@ read_header: } sos_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "sos is %d and size is %d\n"); - av_log(avctx, AV_LOG_DEBUG, "sos offs: 0x%x\n", sos_offs); + av_log(avctx, AV_LOG_DEBUG, "sos offs: 0x%"PRIx32"\n", sos_offs); sod_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "sof is %d and size is %d\n"); - av_log(avctx, AV_LOG_DEBUG, "sod offs: 0x%x\n", sod_offs); + av_log(avctx, AV_LOG_DEBUG, "sod offs: 0x%"PRIx32"\n", sod_offs); if (sos_offs) { init_get_bits(&s->gb, buf_ptr + sos_offs, diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index b498d0fad..1a774ddc6 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -34,7 +34,9 @@ #include "libavutil/avassert.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "blockdsp.h" #include "copy_block.h" +#include "idctdsp.h" #include "internal.h" #include "mjpeg.h" #include "mjpegdec.h" @@ -106,9 +108,11 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) } s->avctx = avctx; + ff_blockdsp_init(&s->bdsp, avctx); ff_hpeldsp_init(&s->hdsp, avctx->flags); - ff_dsputil_init(&s->dsp, avctx); - ff_init_scantable(s->dsp.idct_permutation, &s->scantable, ff_zigzag_direct); + ff_idctdsp_init(&s->idsp, avctx); + ff_init_scantable(s->idsp.idct_permutation, &s->scantable, + ff_zigzag_direct); s->buffer_size = 0; s->buffer = NULL; s->start_code = -1; @@ -116,6 +120,7 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) s->got_picture = 0; s->org_height = avctx->coded_height; avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; + avctx->colorspace = AVCOL_SPC_BT470BG; build_basic_mjpeg_vlc(s); @@ -264,6 +269,9 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) height = get_bits(&s->gb, 16); width = get_bits(&s->gb, 16); + if (s->avctx->codec_id == AV_CODEC_ID_AMV && (height&15)) + avpriv_request_sample(s->avctx, "non mod 16 height AMV\n"); + // HACK for odd_height.mov if (s->interlaced && s->width == width && s->height == height + 1) height= s->height; @@ -380,6 +388,22 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) if (!(pix_fmt_id & 0x0D0D0D0D)) pix_fmt_id -= (pix_fmt_id & 0x0F0F0F0F) >> 1; + for (i = 0; i < 8; i++) { + int j = 6 + (i&1) - (i&6); + int is = (pix_fmt_id >> (4*i)) & 0xF; + int js = (pix_fmt_id >> (4*j)) & 0xF; + + if (is == 1 && js != 2 && (i < 2 || i > 5)) + js = (pix_fmt_id >> ( 8 + 4*(i&1))) & 0xF; + if (is == 1 && js != 2 && (i < 2 || i > 5)) + js = (pix_fmt_id >> (16 + 4*(i&1))) & 0xF; + + if (is == 1 && js == 2) { + if (i & 1) s->upscale_h |= 1 << (j/2); + else s->upscale_v |= 1 << (j/2); + } + } + switch (pix_fmt_id) { case 0x11111100: if (s->rgb) @@ -408,33 +432,42 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) } av_assert0(s->nb_components == 4); break; + case 0x22111122: + if (s->adobe_transform == 0 && s->bits <= 8) { + s->avctx->pix_fmt = AV_PIX_FMT_GBRAP; + s->upscale_v = 6; + s->upscale_h = 6; + s->chroma_height = s->height; + } else if (s->adobe_transform == 2 && s->bits <= 8) { + s->avctx->pix_fmt = AV_PIX_FMT_YUVA444P; + s->upscale_v = 6; + s->upscale_h = 6; + s->chroma_height = s->height; + s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + } else { + if (s->bits <= 8) s->avctx->pix_fmt = AV_PIX_FMT_YUVA420P; + else s->avctx->pix_fmt = AV_PIX_FMT_YUVA420P16; + s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + } + av_assert0(s->nb_components == 4); + break; case 0x12121100: case 0x22122100: - if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P; - else - goto unk_pixfmt; - s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; - s->upscale_v = 2; - s->upscale_h = (pix_fmt_id == 0x22122100); - s->chroma_height = s->height; - break; case 0x21211100: case 0x22211200: if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P; else goto unk_pixfmt; s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; - s->upscale_v = (pix_fmt_id == 0x22211200); - s->upscale_h = 2; s->chroma_height = s->height; break; case 0x22221100: + case 0x22112200: + case 0x11222200: if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P; else goto unk_pixfmt; s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; - s->upscale_v = 2; - s->upscale_h = 2; s->chroma_height = s->height / 2; break; case 0x11000000: @@ -458,7 +491,6 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) else goto unk_pixfmt; s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; - s->upscale_h = (pix_fmt_id == 0x22211100) * 2 + (pix_fmt_id == 0x22112100); s->chroma_height = s->height / 2; break; case 0x21111100: @@ -472,12 +504,16 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) else goto unk_pixfmt; s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; - s->upscale_v = (pix_fmt_id == 0x22121100) + 1; break; case 0x22111100: + case 0x42111100: if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUVJ420P; else s->avctx->pix_fmt = AV_PIX_FMT_YUV420P16; s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + if (pix_fmt_id == 0x42111100) { + s->upscale_h = 6; + s->chroma_height = s->height / 2; + } break; case 0x41111100: if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV411P : AV_PIX_FMT_YUVJ411P; @@ -488,6 +524,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) default: unk_pixfmt: av_log(s->avctx, AV_LOG_ERROR, "Unhandled pixel format 0x%x\n", pix_fmt_id); + s->upscale_h = s->upscale_v = 0; return AVERROR_PATCHWELCOME; } if ((s->upscale_h || s->upscale_v) && s->avctx->lowres) { @@ -498,6 +535,8 @@ unk_pixfmt: s->upscale_h = s->upscale_v = 0; if (s->nb_components > 1) s->avctx->pix_fmt = AV_PIX_FMT_RGB24; + else if (s->palette_index && s->bits <= 8) + s->avctx->pix_fmt = AV_PIX_FMT_PAL8; else if (s->bits <= 8) s->avctx->pix_fmt = AV_PIX_FMT_GRAY8; else @@ -541,8 +580,8 @@ unk_pixfmt: int size = bw * bh * s->h_count[i] * s->v_count[i]; av_freep(&s->blocks[i]); av_freep(&s->last_nnz[i]); - s->blocks[i] = av_mallocz(size * sizeof(**s->blocks)); - s->last_nnz[i] = av_mallocz(size * sizeof(**s->last_nnz)); + s->blocks[i] = av_mallocz_array(size, sizeof(**s->blocks)); + s->last_nnz[i] = av_mallocz_array(size, sizeof(**s->last_nnz)); if (!s->blocks[i] || !s->last_nnz[i]) return AVERROR(ENOMEM); s->block_stride[i] = bw * s->h_count[i]; @@ -623,7 +662,7 @@ static int decode_dc_progressive(MJpegDecodeContext *s, int16_t *block, int16_t *quant_matrix, int Al) { int val; - s->dsp.clear_block(block); + s->bdsp.clear_block(block); val = mjpeg_decode_dc(s, dc_index); if (val == 0xfffff) { av_log(s->avctx, AV_LOG_ERROR, "error dc\n"); @@ -1132,7 +1171,7 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, uint8_t *data[MAX_COMPONENTS]; const uint8_t *reference_data[MAX_COMPONENTS]; int linesize[MAX_COMPONENTS]; - GetBitContext mb_bitmask_gb; + GetBitContext mb_bitmask_gb = {0}; // initialize to silence gcc warning int bytes_per_pixel = 1 + (s->bits > 8); if (mb_bitmask) { @@ -1188,7 +1227,7 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, linesize[c], s->avctx->lowres); else { - s->dsp.clear_block(s->block); + s->bdsp.clear_block(s->block); if (decode_block(s, s->block, i, s->dc_index[i], s->ac_index[i], s->quant_matrixes[s->quant_sindex[i]]) < 0) { @@ -1196,7 +1235,7 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, "error y=%d x=%d\n", mb_y, mb_x); return AVERROR_INVALIDDATA; } - s->dsp.idct_put(ptr, linesize[c], s->block); + s->idsp.idct_put(ptr, linesize[c], s->block); if (s->bits & 7) shift_output(s, ptr, linesize[c]); } @@ -1251,7 +1290,7 @@ static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss, } if (!Al) { - s->coefs_finished[c] |= (2LL << se) - (1LL << ss); + s->coefs_finished[c] |= (2ULL << se) - (1ULL << ss); last_scan = !~s->coefs_finished[c]; } @@ -1283,7 +1322,7 @@ static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss, } if (last_scan) { - s->dsp.idct_put(ptr, linesize, *block); + s->idsp.idct_put(ptr, linesize, *block); if (s->bits & 7) shift_output(s, ptr, linesize); ptr += bytes_per_pixel*8 >> s->avctx->lowres; @@ -1520,6 +1559,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) s->avctx->sample_aspect_ratio.num = get_bits(&s->gb, 16); s->avctx->sample_aspect_ratio.den = get_bits(&s->gb, 16); + ff_set_sar(s->avctx, s->avctx->sample_aspect_ratio); if (s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_INFO, @@ -1644,17 +1684,15 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) ret = ff_tdecode_header(&gbytes, &le, &ifd_offset); if (ret) { av_log(s->avctx, AV_LOG_ERROR, "mjpeg: invalid TIFF header in EXIF data\n"); - return ret; - } + } else { + bytestream2_seek(&gbytes, ifd_offset, SEEK_SET); - bytestream2_seek(&gbytes, ifd_offset, SEEK_SET); - - // read 0th IFD and store the metadata - // (return values > 0 indicate the presence of subimage metadata) - ret = ff_exif_decode_ifd(s->avctx, &gbytes, le, 0, &s->exif_metadata); - if (ret < 0) { - av_log(s->avctx, AV_LOG_ERROR, "mjpeg: error decoding EXIF data\n"); - return ret; + // read 0th IFD and store the metadata + // (return values > 0 indicate the presence of subimage metadata) + ret = avpriv_exif_decode_ifd(s->avctx, &gbytes, le, 0, &s->exif_metadata); + if (ret < 0) { + av_log(s->avctx, AV_LOG_ERROR, "mjpeg: error decoding EXIF data\n"); + } } bytes_read = bytestream2_tell(&gbytes); @@ -1794,7 +1832,7 @@ int ff_mjpeg_find_marker(MJpegDecodeContext *s, memset(s->buffer + *unescaped_buf_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); - av_log(s->avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n", + av_log(s->avctx, AV_LOG_DEBUG, "escaping removed %"PTRDIFF_SPECIFIER" bytes\n", (buf_end - *buf_ptr) - (dst - s->buffer)); } else if (start_code == SOS && s->ls) { const uint8_t *src = *buf_ptr; @@ -1877,7 +1915,7 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, start_code, unescaped_buf_size, buf_size); return AVERROR_INVALIDDATA; } - av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%td\n", + av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%"PTRDIFF_SPECIFIER"\n", start_code, buf_end - buf_ptr); ret = init_get_bits8(&s->gb, unescaped_buf_ptr, unescaped_buf_size); @@ -2035,36 +2073,59 @@ fail: return ret; the_end: if (s->upscale_h) { - uint8_t *line = s->picture_ptr->data[s->upscale_h]; + int p; av_assert0(avctx->pix_fmt == AV_PIX_FMT_YUVJ444P || avctx->pix_fmt == AV_PIX_FMT_YUV444P || avctx->pix_fmt == AV_PIX_FMT_YUVJ440P || - avctx->pix_fmt == AV_PIX_FMT_YUV440P); - for (i = 0; i < s->chroma_height; i++) { - for (index = s->width - 1; index; index--) - line[index] = (line[index / 2] + line[(index + 1) / 2]) >> 1; - line += s->linesize[s->upscale_h]; + avctx->pix_fmt == AV_PIX_FMT_YUV440P || + avctx->pix_fmt == AV_PIX_FMT_YUVA444P || + avctx->pix_fmt == AV_PIX_FMT_YUVJ420P || + avctx->pix_fmt == AV_PIX_FMT_YUV420P || + avctx->pix_fmt == AV_PIX_FMT_GBRAP + ); + avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift); + for (p = 0; p<4; p++) { + uint8_t *line = s->picture_ptr->data[p]; + int w = s->width; + if (!(s->upscale_h & (1<>= hshift; + for (i = 0; i < s->chroma_height; i++) { + for (index = w - 1; index; index--) + line[index] = (line[index / 2] + line[(index + 1) / 2]) >> 1; + line += s->linesize[p]; + } } } if (s->upscale_v) { - uint8_t *dst = &((uint8_t *)s->picture_ptr->data[s->upscale_v])[(s->height - 1) * s->linesize[s->upscale_v]]; - int w; - avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift); - w = s->width >> hshift; + int p; av_assert0(avctx->pix_fmt == AV_PIX_FMT_YUVJ444P || avctx->pix_fmt == AV_PIX_FMT_YUV444P || avctx->pix_fmt == AV_PIX_FMT_YUVJ422P || - avctx->pix_fmt == AV_PIX_FMT_YUV422P); - for (i = s->height - 1; i; i--) { - uint8_t *src1 = &((uint8_t *)s->picture_ptr->data[s->upscale_v])[i / 2 * s->linesize[s->upscale_v]]; - uint8_t *src2 = &((uint8_t *)s->picture_ptr->data[s->upscale_v])[(i + 1) / 2 * s->linesize[s->upscale_v]]; - if (src1 == src2) { - memcpy(dst, src1, w); - } else { - for (index = 0; index < w; index++) - dst[index] = (src1[index] + src2[index]) >> 1; + avctx->pix_fmt == AV_PIX_FMT_YUV422P || + avctx->pix_fmt == AV_PIX_FMT_YUVA444P || + avctx->pix_fmt == AV_PIX_FMT_GBRAP + ); + avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift); + for (p = 0; p < 4; p++) { + uint8_t *dst = &((uint8_t *)s->picture_ptr->data[p])[(s->height - 1) * s->linesize[p]]; + int w = s->width; + if (!(s->upscale_v & (1<>= hshift; + for (i = s->height - 1; i; i--) { + uint8_t *src1 = &((uint8_t *)s->picture_ptr->data[p])[i / 2 * s->linesize[p]]; + uint8_t *src2 = &((uint8_t *)s->picture_ptr->data[p])[(i + 1) / 2 * s->linesize[p]]; + if (src1 == src2) { + memcpy(dst, src1, w); + } else { + for (index = 0; index < w; index++) + dst[index] = (src1[index] + src2[index]) >> 1; + } + dst -= s->linesize[p]; } - dst -= s->linesize[s->upscale_v]; } } if (s->flipped) { @@ -2111,6 +2172,28 @@ the_end: } } } + if (s->adobe_transform == 2 && s->avctx->pix_fmt == AV_PIX_FMT_YUVA444P) { + int w = s->picture_ptr->width; + int h = s->picture_ptr->height; + for (i=0; ipicture_ptr->data[index] + + s->picture_ptr->linesize[index]*i; + } + for (j=0; j> 16; + dst[1][j] = (g*257 >> 16) + 128; + dst[2][j] = (b*257 >> 16) + 128; + dst[3][j] = 255; + } + } + } if (s->stereo3d) { AVStereo3D *stereo = av_stereo3d_create_side_data(data); @@ -2124,7 +2207,7 @@ the_end: av_dict_copy(avpriv_frame_get_metadatap(data), s->exif_metadata, 0); av_dict_free(&s->exif_metadata); - av_log(avctx, AV_LOG_DEBUG, "decode frame unused %td bytes\n", + av_log(avctx, AV_LOG_DEBUG, "decode frame unused %"PTRDIFF_SPECIFIER" bytes\n", buf_end - buf_ptr); // return buf_end - buf_ptr; return buf_ptr - buf; diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h index 77bbfed1d..53a412c7b 100644 --- a/libavcodec/mjpegdec.h +++ b/libavcodec/mjpegdec.h @@ -34,9 +34,10 @@ #include "libavutil/stereo3d.h" #include "avcodec.h" +#include "blockdsp.h" #include "get_bits.h" -#include "dsputil.h" #include "hpeldsp.h" +#include "idctdsp.h" #define MAX_COMPONENTS 4 @@ -102,9 +103,11 @@ typedef struct MJpegDecodeContext { int16_t (*blocks[MAX_COMPONENTS])[64]; ///< intermediate sums (progressive mode) uint8_t *last_nnz[MAX_COMPONENTS]; uint64_t coefs_finished[MAX_COMPONENTS]; ///< bitmask of which coefs have been completely decoded (progressive mode) + int palette_index; ScanTable scantable; - DSPContext dsp; + BlockDSPContext bdsp; HpelDSPContext hdsp; + IDCTDSPContext idsp; int restart_interval; int restart_count; diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 842528e5f..ce230ade2 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -33,6 +33,7 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "mjpegenc_common.h" #include "mpegvideo.h" #include "mjpeg.h" #include "mjpegenc.h" @@ -80,355 +81,6 @@ void ff_mjpeg_encode_close(MpegEncContext *s) av_free(s->mjpeg_ctx); } -/* table_class: 0 = DC coef, 1 = AC coefs */ -static int put_huffman_table(PutBitContext *p, int table_class, int table_id, - const uint8_t *bits_table, const uint8_t *value_table) -{ - int n, i; - - put_bits(p, 4, table_class); - put_bits(p, 4, table_id); - - n = 0; - for(i=1;i<=16;i++) { - n += bits_table[i]; - put_bits(p, 8, bits_table[i]); - } - - for(i=0;icodec_id != AV_CODEC_ID_LJPEG) { - int matrix_count = 1 + !!memcmp(luma_intra_matrix, - chroma_intra_matrix, - sizeof(luma_intra_matrix[0]) * 64); - /* quant matrixes */ - put_marker(p, DQT); - put_bits(p, 16, 2 + matrix_count * (1 + 64)); - put_bits(p, 4, 0); /* 8 bit precision */ - put_bits(p, 4, 0); /* table 0 */ - for(i=0;i<64;i++) { - j = intra_scantable->permutated[i]; - put_bits(p, 8, luma_intra_matrix[j]); - } - - if (matrix_count > 1) { - put_bits(p, 4, 0); /* 8 bit precision */ - put_bits(p, 4, 1); /* table 1 */ - for(i=0;i<64;i++) { - j = intra_scantable->permutated[i]; - put_bits(p, 8, chroma_intra_matrix[j]); - } - } - } - - if(avctx->active_thread_type & FF_THREAD_SLICE){ - put_marker(p, DRI); - put_bits(p, 16, 4); - put_bits(p, 16, (avctx->width-1)/(8*hsample[0]) + 1); - } - - /* huffman table */ - put_marker(p, DHT); - flush_put_bits(p); - ptr = put_bits_ptr(p); - put_bits(p, 16, 0); /* patched later */ - size = 2; - size += put_huffman_table(p, 0, 0, avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); - size += put_huffman_table(p, 0, 1, avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); - - size += put_huffman_table(p, 1, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance); - size += put_huffman_table(p, 1, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance); - AV_WB16(ptr, size); -} - -static void jpeg_put_comments(AVCodecContext *avctx, PutBitContext *p) -{ - int size; - uint8_t *ptr; - - if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) { - /* JFIF header */ - put_marker(p, APP0); - put_bits(p, 16, 16); - avpriv_put_string(p, "JFIF", 1); /* this puts the trailing zero-byte too */ - put_bits(p, 16, 0x0102); /* v 1.02 */ - put_bits(p, 8, 0); /* units type: 0 - aspect ratio */ - put_bits(p, 16, avctx->sample_aspect_ratio.num); - put_bits(p, 16, avctx->sample_aspect_ratio.den); - put_bits(p, 8, 0); /* thumbnail width */ - put_bits(p, 8, 0); /* thumbnail height */ - } - - /* comment */ - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { - put_marker(p, COM); - flush_put_bits(p); - ptr = put_bits_ptr(p); - put_bits(p, 16, 0); /* patched later */ - avpriv_put_string(p, LIBAVCODEC_IDENT, 1); - size = strlen(LIBAVCODEC_IDENT)+3; - AV_WB16(ptr, size); - } - - if (avctx->pix_fmt == AV_PIX_FMT_YUV420P || - avctx->pix_fmt == AV_PIX_FMT_YUV422P || - avctx->pix_fmt == AV_PIX_FMT_YUV444P) { - put_marker(p, COM); - flush_put_bits(p); - ptr = put_bits_ptr(p); - put_bits(p, 16, 0); /* patched later */ - avpriv_put_string(p, "CS=ITU601", 1); - size = strlen("CS=ITU601")+3; - AV_WB16(ptr, size); - } -} - -void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[3], int vsample[3]) -{ - int chroma_h_shift, chroma_v_shift; - - av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &chroma_h_shift, - &chroma_v_shift); - if (avctx->codec->id == AV_CODEC_ID_LJPEG && - ( avctx->pix_fmt == AV_PIX_FMT_BGR0 - || avctx->pix_fmt == AV_PIX_FMT_BGRA - || avctx->pix_fmt == AV_PIX_FMT_BGR24)) { - vsample[0] = hsample[0] = - vsample[1] = hsample[1] = - vsample[2] = hsample[2] = 1; - } else if (avctx->pix_fmt == AV_PIX_FMT_YUV444P || avctx->pix_fmt == AV_PIX_FMT_YUVJ444P) { - vsample[0] = vsample[1] = vsample[2] = 2; - hsample[0] = hsample[1] = hsample[2] = 1; - } else { - vsample[0] = 2; - vsample[1] = 2 >> chroma_v_shift; - vsample[2] = 2 >> chroma_v_shift; - hsample[0] = 2; - hsample[1] = 2 >> chroma_h_shift; - hsample[2] = 2 >> chroma_h_shift; - } -} - -void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, - ScanTable *intra_scantable, - uint16_t luma_intra_matrix[64], - uint16_t chroma_intra_matrix[64]) -{ - const int lossless = avctx->codec_id != AV_CODEC_ID_MJPEG && avctx->codec_id != AV_CODEC_ID_AMV; - int hsample[3], vsample[3]; - int i; - int chroma_matrix = !!memcmp(luma_intra_matrix, - chroma_intra_matrix, - sizeof(luma_intra_matrix[0])*64); - - ff_mjpeg_init_hvsample(avctx, hsample, vsample); - - put_marker(pb, SOI); - - // hack for AMV mjpeg format - if(avctx->codec_id == AV_CODEC_ID_AMV) goto end; - - jpeg_put_comments(avctx, pb); - - jpeg_table_header(avctx, pb, intra_scantable, luma_intra_matrix, chroma_intra_matrix, hsample); - - switch (avctx->codec_id) { - case AV_CODEC_ID_MJPEG: put_marker(pb, SOF0 ); break; - case AV_CODEC_ID_LJPEG: put_marker(pb, SOF3 ); break; - default: av_assert0(0); - } - - put_bits(pb, 16, 17); - if (lossless && ( avctx->pix_fmt == AV_PIX_FMT_BGR0 - || avctx->pix_fmt == AV_PIX_FMT_BGRA - || avctx->pix_fmt == AV_PIX_FMT_BGR24)) - put_bits(pb, 8, 9); /* 9 bits/component RCT */ - else - put_bits(pb, 8, 8); /* 8 bits/component */ - put_bits(pb, 16, avctx->height); - put_bits(pb, 16, avctx->width); - put_bits(pb, 8, 3); /* 3 components */ - - /* Y component */ - put_bits(pb, 8, 1); /* component number */ - put_bits(pb, 4, hsample[0]); /* H factor */ - put_bits(pb, 4, vsample[0]); /* V factor */ - put_bits(pb, 8, 0); /* select matrix */ - - /* Cb component */ - put_bits(pb, 8, 2); /* component number */ - put_bits(pb, 4, hsample[1]); /* H factor */ - put_bits(pb, 4, vsample[1]); /* V factor */ - put_bits(pb, 8, lossless ? 0 : chroma_matrix); /* select matrix */ - - /* Cr component */ - put_bits(pb, 8, 3); /* component number */ - put_bits(pb, 4, hsample[2]); /* H factor */ - put_bits(pb, 4, vsample[2]); /* V factor */ - put_bits(pb, 8, lossless ? 0 : chroma_matrix); /* select matrix */ - - /* scan header */ - put_marker(pb, SOS); - put_bits(pb, 16, 12); /* length */ - put_bits(pb, 8, 3); /* 3 components */ - - /* Y component */ - put_bits(pb, 8, 1); /* index */ - put_bits(pb, 4, 0); /* DC huffman table index */ - put_bits(pb, 4, 0); /* AC huffman table index */ - - /* Cb component */ - put_bits(pb, 8, 2); /* index */ - put_bits(pb, 4, 1); /* DC huffman table index */ - put_bits(pb, 4, lossless ? 0 : 1); /* AC huffman table index */ - - /* Cr component */ - put_bits(pb, 8, 3); /* index */ - 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) */ - - switch (avctx->codec_id) { - case AV_CODEC_ID_MJPEG: put_bits(pb, 8, 63); break; /* Se (not used) */ - case AV_CODEC_ID_LJPEG: put_bits(pb, 8, 0); break; /* not used */ - default: av_assert0(0); - } - - put_bits(pb, 8, 0); /* Ah/Al (not used) */ - -end: - if (!lossless) { - MpegEncContext *s = avctx->priv_data; - av_assert0(avctx->codec->priv_data_size == sizeof(MpegEncContext)); - - s->esc_pos = put_bits_count(pb) >> 3; - for(i=1; islice_context_count; i++) - s->thread_context[i]->esc_pos = 0; - } -} - -void ff_mjpeg_escape_FF(PutBitContext *pb, int start) -{ - int size; - int i, ff_count; - uint8_t *buf = pb->buf + start; - int align= (-(size_t)(buf))&3; - int pad = (-put_bits_count(pb))&7; - - if (pad) - put_bits(pb, pad, (1<>= 3; - - ff_count=0; - for(i=0; i>4))&0x0F0F0F0F)+0x01010101)&0x10101010; - v= *(uint32_t*)(&buf[i+4]); - acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; - v= *(uint32_t*)(&buf[i+8]); - acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; - v= *(uint32_t*)(&buf[i+12]); - acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; - - acc>>=4; - acc+= (acc>>16); - acc+= (acc>>8); - ff_count+= acc&0xFF; - } - for(; ipb; - int mb_y = s->mb_y - !s->mb_x; - - ff_mjpeg_escape_FF(pbc, s->esc_pos); - - if((s->avctx->active_thread_type & FF_THREAD_SLICE) && mb_y < s->mb_height) - put_marker(pbc, RST0 + (mb_y&7)); - s->esc_pos = put_bits_count(pbc) >> 3; - - for(i=0; i<3; i++) - s->last_dc[i] = 128 << s->intra_dc_precision; -} - -void ff_mjpeg_encode_picture_trailer(PutBitContext *pb, int header_bits) -{ - av_assert1((header_bits & 7) == 0); - - put_marker(pb, EOI); -} - -void ff_mjpeg_encode_dc(PutBitContext *pb, int val, - uint8_t *huff_size, uint16_t *huff_code) -{ - int mant, nbits; - - if (val == 0) { - put_bits(pb, huff_size[0], huff_code[0]); - } else { - mant = val; - if (val < 0) { - val = -val; - mant--; - } - - nbits= av_log2_16bit(val) + 1; - - put_bits(pb, huff_size[nbits], huff_code[nbits]); - - put_sbits(pb, nbits, mant); - } -} - static void encode_block(MpegEncContext *s, int16_t *block, int n) { int mant, nbits, code, i, j; @@ -539,13 +191,22 @@ static int amv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, if(s->avctx->flags & CODEC_FLAG_EMU_EDGE) return AVERROR(EINVAL); + if ((avctx->height & 15) && avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { + av_log(avctx, AV_LOG_ERROR, + "Heights which are not a multiple of 16 might fail with some decoders, " + "use vstrict=-1 / -strict -1 to use %d anyway.\n", avctx->height); + av_log(avctx, AV_LOG_WARNING, "If you have a device that plays AMV videos, please test if videos " + "with such heights work with it and report your findings to ffmpeg-devel@ffmpeg.org\n"); + return AVERROR_EXPERIMENTAL; + } + pic = av_frame_clone(pic_arg); if (!pic) return AVERROR(ENOMEM); //picture should be flipped upside-down for(i=0; i < 3; i++) { int vsample = i ? 2 >> chroma_v_shift : 2; - pic->data[i] += (pic->linesize[i] * (vsample * (8 * s->mb_height -((s->height/V_MAX)&7)) - 1 )); + pic->data[i] += pic->linesize[i] * (vsample * s->height / V_MAX - 1); pic->linesize[i] *= -1; } ret = ff_MPV_encode_picture(avctx, pkt, pic, got_packet); diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h index 94bb652fb..069d43c81 100644 --- a/libavcodec/mjpegenc.h +++ b/libavcodec/mjpegenc.h @@ -51,16 +51,6 @@ typedef struct MJpegContext { int ff_mjpeg_encode_init(MpegEncContext *s); void ff_mjpeg_encode_close(MpegEncContext *s); -void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, - ScanTable *intra_scantable, - uint16_t luma_intra_matrix[64], - uint16_t chroma_intra_matrix[64]); -void ff_mjpeg_encode_picture_trailer(PutBitContext *pb, int header_bits); -void ff_mjpeg_escape_FF(PutBitContext *pb, int start); -void ff_mjpeg_encode_stuffing(MpegEncContext *s); -void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[3], int vsample[3]); -void ff_mjpeg_encode_dc(PutBitContext *pb, int val, - uint8_t *huff_size, uint16_t *huff_code); void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]); #endif /* AVCODEC_MJPEGENC_H */ diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c new file mode 100644 index 000000000..8a5b99f22 --- /dev/null +++ b/libavcodec/mjpegenc_common.c @@ -0,0 +1,383 @@ +/* + * lossless JPEG shared bits + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/pixdesc.h" +#include "libavutil/pixfmt.h" + +#include "avcodec.h" +#include "idctdsp.h" +#include "put_bits.h" +#include "mjpegenc_common.h" +#include "mjpeg.h" + +/* table_class: 0 = DC coef, 1 = AC coefs */ +static int put_huffman_table(PutBitContext *p, int table_class, int table_id, + const uint8_t *bits_table, const uint8_t *value_table) +{ + int n, i; + + put_bits(p, 4, table_class); + put_bits(p, 4, table_id); + + n = 0; + for(i=1;i<=16;i++) { + n += bits_table[i]; + put_bits(p, 8, bits_table[i]); + } + + for(i=0;icodec_id != AV_CODEC_ID_LJPEG) { + int matrix_count = 1 + !!memcmp(luma_intra_matrix, + chroma_intra_matrix, + sizeof(luma_intra_matrix[0]) * 64); + /* quant matrixes */ + put_marker(p, DQT); + put_bits(p, 16, 2 + matrix_count * (1 + 64)); + put_bits(p, 4, 0); /* 8 bit precision */ + put_bits(p, 4, 0); /* table 0 */ + for(i=0;i<64;i++) { + j = intra_scantable->permutated[i]; + put_bits(p, 8, luma_intra_matrix[j]); + } + + if (matrix_count > 1) { + put_bits(p, 4, 0); /* 8 bit precision */ + put_bits(p, 4, 1); /* table 1 */ + for(i=0;i<64;i++) { + j = intra_scantable->permutated[i]; + put_bits(p, 8, chroma_intra_matrix[j]); + } + } + } + + if(avctx->active_thread_type & FF_THREAD_SLICE){ + put_marker(p, DRI); + put_bits(p, 16, 4); + put_bits(p, 16, (avctx->width-1)/(8*hsample[0]) + 1); + } + + /* huffman table */ + put_marker(p, DHT); + flush_put_bits(p); + ptr = put_bits_ptr(p); + put_bits(p, 16, 0); /* patched later */ + size = 2; + size += put_huffman_table(p, 0, 0, avpriv_mjpeg_bits_dc_luminance, + avpriv_mjpeg_val_dc); + size += put_huffman_table(p, 0, 1, avpriv_mjpeg_bits_dc_chrominance, + avpriv_mjpeg_val_dc); + + size += put_huffman_table(p, 1, 0, avpriv_mjpeg_bits_ac_luminance, + avpriv_mjpeg_val_ac_luminance); + size += put_huffman_table(p, 1, 1, avpriv_mjpeg_bits_ac_chrominance, + avpriv_mjpeg_val_ac_chrominance); + AV_WB16(ptr, size); +} + +static void jpeg_put_comments(AVCodecContext *avctx, PutBitContext *p) +{ + int size; + uint8_t *ptr; + + if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) { + /* JFIF header */ + put_marker(p, APP0); + put_bits(p, 16, 16); + avpriv_put_string(p, "JFIF", 1); /* this puts the trailing zero-byte too */ + put_bits(p, 16, 0x0102); /* v 1.02 */ + put_bits(p, 8, 0); /* units type: 0 - aspect ratio */ + put_bits(p, 16, avctx->sample_aspect_ratio.num); + put_bits(p, 16, avctx->sample_aspect_ratio.den); + put_bits(p, 8, 0); /* thumbnail width */ + put_bits(p, 8, 0); /* thumbnail height */ + } + + /* comment */ + if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + put_marker(p, COM); + flush_put_bits(p); + ptr = put_bits_ptr(p); + put_bits(p, 16, 0); /* patched later */ + avpriv_put_string(p, LIBAVCODEC_IDENT, 1); + size = strlen(LIBAVCODEC_IDENT)+3; + AV_WB16(ptr, size); + } + + if (avctx->pix_fmt == AV_PIX_FMT_YUV420P || + avctx->pix_fmt == AV_PIX_FMT_YUV422P || + avctx->pix_fmt == AV_PIX_FMT_YUV444P) { + put_marker(p, COM); + flush_put_bits(p); + ptr = put_bits_ptr(p); + put_bits(p, 16, 0); /* patched later */ + avpriv_put_string(p, "CS=ITU601", 1); + size = strlen("CS=ITU601")+3; + AV_WB16(ptr, size); + } +} + +void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[3], int vsample[3]) +{ + int chroma_h_shift, chroma_v_shift; + + av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &chroma_h_shift, + &chroma_v_shift); + if (avctx->codec->id == AV_CODEC_ID_LJPEG && + ( avctx->pix_fmt == AV_PIX_FMT_BGR0 + || avctx->pix_fmt == AV_PIX_FMT_BGRA + || avctx->pix_fmt == AV_PIX_FMT_BGR24)) { + vsample[0] = hsample[0] = + vsample[1] = hsample[1] = + vsample[2] = hsample[2] = 1; + } else if (avctx->pix_fmt == AV_PIX_FMT_YUV444P || avctx->pix_fmt == AV_PIX_FMT_YUVJ444P) { + vsample[0] = vsample[1] = vsample[2] = 2; + hsample[0] = hsample[1] = hsample[2] = 1; + } else { + vsample[0] = 2; + vsample[1] = 2 >> chroma_v_shift; + vsample[2] = 2 >> chroma_v_shift; + hsample[0] = 2; + hsample[1] = 2 >> chroma_h_shift; + hsample[2] = 2 >> chroma_h_shift; + } +} + +void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, + ScanTable *intra_scantable, + uint16_t luma_intra_matrix[64], + uint16_t chroma_intra_matrix[64]) +{ + const int lossless = avctx->codec_id != AV_CODEC_ID_MJPEG && avctx->codec_id != AV_CODEC_ID_AMV; + int hsample[3], vsample[3]; + int i; + int chroma_matrix = !!memcmp(luma_intra_matrix, + chroma_intra_matrix, + sizeof(luma_intra_matrix[0])*64); + + ff_mjpeg_init_hvsample(avctx, hsample, vsample); + + put_marker(pb, SOI); + + // hack for AMV mjpeg format + if(avctx->codec_id == AV_CODEC_ID_AMV) goto end; + + jpeg_put_comments(avctx, pb); + + jpeg_table_header(avctx, pb, intra_scantable, luma_intra_matrix, chroma_intra_matrix, hsample); + + switch (avctx->codec_id) { + case AV_CODEC_ID_MJPEG: put_marker(pb, SOF0 ); break; + case AV_CODEC_ID_LJPEG: put_marker(pb, SOF3 ); break; + default: av_assert0(0); + } + + put_bits(pb, 16, 17); + if (lossless && ( avctx->pix_fmt == AV_PIX_FMT_BGR0 + || avctx->pix_fmt == AV_PIX_FMT_BGRA + || avctx->pix_fmt == AV_PIX_FMT_BGR24)) + put_bits(pb, 8, 9); /* 9 bits/component RCT */ + else + put_bits(pb, 8, 8); /* 8 bits/component */ + put_bits(pb, 16, avctx->height); + put_bits(pb, 16, avctx->width); + put_bits(pb, 8, 3); /* 3 components */ + + /* Y component */ + put_bits(pb, 8, 1); /* component number */ + put_bits(pb, 4, hsample[0]); /* H factor */ + put_bits(pb, 4, vsample[0]); /* V factor */ + put_bits(pb, 8, 0); /* select matrix */ + + /* Cb component */ + put_bits(pb, 8, 2); /* component number */ + put_bits(pb, 4, hsample[1]); /* H factor */ + put_bits(pb, 4, vsample[1]); /* V factor */ + put_bits(pb, 8, lossless ? 0 : chroma_matrix); /* select matrix */ + + /* Cr component */ + put_bits(pb, 8, 3); /* component number */ + put_bits(pb, 4, hsample[2]); /* H factor */ + put_bits(pb, 4, vsample[2]); /* V factor */ + put_bits(pb, 8, lossless ? 0 : chroma_matrix); /* select matrix */ + + /* scan header */ + put_marker(pb, SOS); + put_bits(pb, 16, 12); /* length */ + put_bits(pb, 8, 3); /* 3 components */ + + /* Y component */ + put_bits(pb, 8, 1); /* index */ + put_bits(pb, 4, 0); /* DC huffman table index */ + put_bits(pb, 4, 0); /* AC huffman table index */ + + /* Cb component */ + put_bits(pb, 8, 2); /* index */ + put_bits(pb, 4, 1); /* DC huffman table index */ + put_bits(pb, 4, lossless ? 0 : 1); /* AC huffman table index */ + + /* Cr component */ + put_bits(pb, 8, 3); /* index */ + 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) */ + + switch (avctx->codec_id) { + case AV_CODEC_ID_MJPEG: put_bits(pb, 8, 63); break; /* Se (not used) */ + case AV_CODEC_ID_LJPEG: put_bits(pb, 8, 0); break; /* not used */ + default: av_assert0(0); + } + + put_bits(pb, 8, 0); /* Ah/Al (not used) */ + +end: + if (!lossless) { + MpegEncContext *s = avctx->priv_data; + av_assert0(avctx->codec->priv_data_size == sizeof(MpegEncContext)); + + s->esc_pos = put_bits_count(pb) >> 3; + for(i=1; islice_context_count; i++) + s->thread_context[i]->esc_pos = 0; + } +} + +void ff_mjpeg_escape_FF(PutBitContext *pb, int start) +{ + int size; + int i, ff_count; + uint8_t *buf = pb->buf + start; + int align= (-(size_t)(buf))&3; + int pad = (-put_bits_count(pb))&7; + + if (pad) + put_bits(pb, pad, (1<>= 3; + + ff_count=0; + for(i=0; i>4))&0x0F0F0F0F)+0x01010101)&0x10101010; + v= *(uint32_t*)(&buf[i+4]); + acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; + v= *(uint32_t*)(&buf[i+8]); + acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; + v= *(uint32_t*)(&buf[i+12]); + acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; + + acc>>=4; + acc+= (acc>>16); + acc+= (acc>>8); + ff_count+= acc&0xFF; + } + for(; ipb; + int mb_y = s->mb_y - !s->mb_x; + + ff_mjpeg_escape_FF(pbc, s->esc_pos); + + if((s->avctx->active_thread_type & FF_THREAD_SLICE) && mb_y < s->mb_height) + put_marker(pbc, RST0 + (mb_y&7)); + s->esc_pos = put_bits_count(pbc) >> 3; + + for(i=0; i<3; i++) + s->last_dc[i] = 128 << s->intra_dc_precision; +} + +void ff_mjpeg_encode_picture_trailer(PutBitContext *pb, int header_bits) +{ + av_assert1((header_bits & 7) == 0); + + put_marker(pb, EOI); +} + +void ff_mjpeg_encode_dc(PutBitContext *pb, int val, + uint8_t *huff_size, uint16_t *huff_code) +{ + int mant, nbits; + + if (val == 0) { + put_bits(pb, huff_size[0], huff_code[0]); + } else { + mant = val; + if (val < 0) { + val = -val; + mant--; + } + + nbits= av_log2_16bit(val) + 1; + + put_bits(pb, huff_size[nbits], huff_code[nbits]); + + put_sbits(pb, nbits, mant); + } +} diff --git a/libavcodec/mjpegenc_common.h b/libavcodec/mjpegenc_common.h new file mode 100644 index 000000000..38b9b3f9f --- /dev/null +++ b/libavcodec/mjpegenc_common.h @@ -0,0 +1,43 @@ +/* + * lossless JPEG shared bits + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MJPEGENC_COMMON_H +#define AVCODEC_MJPEGENC_COMMON_H + +#include + +#include "avcodec.h" +#include "idctdsp.h" +#include "mpegvideo.h" +#include "put_bits.h" + +void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, + ScanTable *intra_scantable, + uint16_t luma_intra_matrix[64], + uint16_t chroma_intra_matrix[64]); +void ff_mjpeg_encode_picture_trailer(PutBitContext *pb, int header_bits); +void ff_mjpeg_escape_FF(PutBitContext *pb, int start); +void ff_mjpeg_encode_stuffing(MpegEncContext *s); +void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[3], int vsample[3]); + +void ff_mjpeg_encode_dc(PutBitContext *pb, int val, + uint8_t *huff_size, uint16_t *huff_code); + +#endif /* AVCODEC_MJPEGENC_COMMON_H */ diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index dae19e756..4bb82eebb 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -230,6 +230,7 @@ static int mlp_parse(AVCodecParserContext *s, int sync_present; uint8_t parity_bits; int next; + int ret; int i, p = 0; *poutbuf_size = 0; @@ -256,7 +257,10 @@ static int mlp_parse(AVCodecParserContext *s, return buf_size; } - ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size); + if ((ret = ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size)) < 0) { + av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n"); + return ret; + } return i - 7; } diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 292f3ab94..ed6a7fb58 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -37,9 +37,16 @@ #include "mlp_parser.h" #include "mlpdsp.h" #include "mlp.h" +#include "config.h" /** number of bits used for VLC lookup - longest Huffman code is 9 */ +#if ARCH_ARM +#define VLC_BITS 5 +#define VLC_STATIC_SIZE 64 +#else #define VLC_BITS 9 +#define VLC_STATIC_SIZE 512 +#endif typedef struct SubStream { /// Set if a valid restart header has been read. Otherwise the substream cannot be decoded. @@ -193,13 +200,13 @@ static av_cold void init_static(void) if (!huff_vlc[0].bits) { INIT_VLC_STATIC(&huff_vlc[0], VLC_BITS, 18, &ff_mlp_huffman_tables[0][0][1], 2, 1, - &ff_mlp_huffman_tables[0][0][0], 2, 1, 512); + &ff_mlp_huffman_tables[0][0][0], 2, 1, VLC_STATIC_SIZE); INIT_VLC_STATIC(&huff_vlc[1], VLC_BITS, 16, &ff_mlp_huffman_tables[1][0][1], 2, 1, - &ff_mlp_huffman_tables[1][0][0], 2, 1, 512); + &ff_mlp_huffman_tables[1][0][0], 2, 1, VLC_STATIC_SIZE); INIT_VLC_STATIC(&huff_vlc[2], VLC_BITS, 15, &ff_mlp_huffman_tables[2][0][1], 2, 1, - &ff_mlp_huffman_tables[2][0][0], 2, 1, 512); + &ff_mlp_huffman_tables[2][0][0], 2, 1, VLC_STATIC_SIZE); } ff_mlp_init_crc(); @@ -356,6 +363,10 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) m->avctx->sample_fmt = AV_SAMPLE_FMT_S32; else m->avctx->sample_fmt = AV_SAMPLE_FMT_S16; + m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(m->substream[m->max_decoded_substream].ch_assign, + m->substream[m->max_decoded_substream].output_shift, + m->substream[m->max_decoded_substream].max_matrix_channel, + m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); m->params_valid = 1; for (substr = 0; substr < MAX_SUBSTREAMS; substr++) @@ -605,6 +616,10 @@ FF_ENABLE_DEPRECATION_WARNINGS if (substr == m->max_decoded_substream) { m->avctx->channels = s->max_matrix_channel + 1; m->avctx->channel_layout = s->ch_layout; + m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(s->ch_assign, + s->output_shift, + s->max_matrix_channel, + m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); if (m->avctx->codec_id == AV_CODEC_ID_MLP && m->needs_reordering) { if (m->avctx->channel_layout == (AV_CH_LAYOUT_QUAD|AV_CH_LOW_FREQUENCY) || @@ -850,9 +865,15 @@ static int read_decoding_params(MLPDecodeContext *m, GetBitContext *gbp, return ret; if (s->param_presence_flags & PARAM_OUTSHIFT) - if (get_bits1(gbp)) + if (get_bits1(gbp)) { for (ch = 0; ch <= s->max_matrix_channel; ch++) s->output_shift[ch] = get_sbits(gbp, 4); + if (substr == m->max_decoded_substream) + m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(s->ch_assign, + s->output_shift, + s->max_matrix_channel, + m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); + } if (s->param_presence_flags & PARAM_QUANTSTEP) if (get_bits1(gbp)) @@ -1017,7 +1038,7 @@ static void fill_noise_buffer(MLPDecodeContext *m, unsigned int substr) static void rematrix_channels(MLPDecodeContext *m, unsigned int substr) { SubStream *s = &m->substream[substr]; - unsigned int mat, src_ch, i; + unsigned int mat; unsigned int maxchan; maxchan = s->max_matrix_channel; @@ -1029,31 +1050,18 @@ static void rematrix_channels(MLPDecodeContext *m, unsigned int substr) } for (mat = 0; mat < s->num_primitive_matrices; mat++) { - int matrix_noise_shift = s->matrix_noise_shift[mat]; unsigned int dest_ch = s->matrix_out_ch[mat]; - int32_t mask = MSB_MASK(s->quant_step_size[dest_ch]); - int32_t *coeffs = s->matrix_coeff[mat]; - int index = s->num_primitive_matrices - mat; - int index2 = 2 * index + 1; - - /* TODO: DSPContext? */ - - for (i = 0; i < s->blockpos; i++) { - int32_t bypassed_lsb = m->bypassed_lsbs[i][mat]; - int32_t *samples = m->sample_buffer[i]; - int64_t accum = 0; - - for (src_ch = 0; src_ch <= maxchan; src_ch++) - accum += (int64_t) samples[src_ch] * coeffs[src_ch]; - - if (matrix_noise_shift) { - index &= m->access_unit_size_pow2 - 1; - accum += m->noise_buffer[index] << (matrix_noise_shift + 7); - index += index2; - } - - samples[dest_ch] = ((accum >> 14) & mask) + bypassed_lsb; - } + m->dsp.mlp_rematrix_channel(&m->sample_buffer[0][0], + s->matrix_coeff[mat], + &m->bypassed_lsbs[0][mat], + m->noise_buffer, + s->num_primitive_matrices - mat, + dest_ch, + s->blockpos, + maxchan, + s->matrix_noise_shift[mat], + m->access_unit_size_pow2, + MSB_MASK(s->quant_step_size[dest_ch])); } } @@ -1064,9 +1072,6 @@ static int output_data(MLPDecodeContext *m, unsigned int substr, { AVCodecContext *avctx = m->avctx; SubStream *s = &m->substream[substr]; - unsigned int i, out_ch = 0; - int32_t *data_32; - int16_t *data_16; int ret; int is32 = (m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); @@ -1084,19 +1089,14 @@ static int output_data(MLPDecodeContext *m, unsigned int substr, frame->nb_samples = s->blockpos; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - data_32 = (int32_t *)frame->data[0]; - data_16 = (int16_t *)frame->data[0]; - - for (i = 0; i < s->blockpos; i++) { - for (out_ch = 0; out_ch <= s->max_matrix_channel; out_ch++) { - int mat_ch = s->ch_assign[out_ch]; - int32_t sample = m->sample_buffer[i][mat_ch] - << s->output_shift[mat_ch]; - s->lossless_check_data ^= (sample & 0xffffff) << mat_ch; - if (is32) *data_32++ = sample << 8; - else *data_16++ = sample >> 8; - } - } + s->lossless_check_data = m->dsp.mlp_pack_output(s->lossless_check_data, + s->blockpos, + m->sample_buffer, + frame->data[0], + s->ch_assign, + s->output_shift, + s->max_matrix_channel, + is32); /* Update matrix encoding side data */ if ((ret = ff_side_data_update_matrix_encoding(frame, s->matrix_encoding)) < 0) diff --git a/libavcodec/mlpdsp.c b/libavcodec/mlpdsp.c index b413e86db..3ae8c3770 100644 --- a/libavcodec/mlpdsp.c +++ b/libavcodec/mlpdsp.c @@ -57,9 +57,82 @@ static void mlp_filter_channel(int32_t *state, const int32_t *coeff, } } +void ff_mlp_rematrix_channel(int32_t *samples, + const int32_t *coeffs, + const uint8_t *bypassed_lsbs, + const int8_t *noise_buffer, + int index, + unsigned int dest_ch, + uint16_t blockpos, + unsigned int maxchan, + int matrix_noise_shift, + int access_unit_size_pow2, + int32_t mask) +{ + unsigned int src_ch, i; + int index2 = 2 * index + 1; + for (i = 0; i < blockpos; i++) { + int64_t accum = 0; + + for (src_ch = 0; src_ch <= maxchan; src_ch++) + accum += (int64_t) samples[src_ch] * coeffs[src_ch]; + + if (matrix_noise_shift) { + index &= access_unit_size_pow2 - 1; + accum += noise_buffer[index] << (matrix_noise_shift + 7); + index += index2; + } + + samples[dest_ch] = ((accum >> 14) & mask) + *bypassed_lsbs; + bypassed_lsbs += MAX_CHANNELS; + samples += MAX_CHANNELS; + } +} + +static int32_t (*mlp_select_pack_output(uint8_t *ch_assign, + int8_t *output_shift, + uint8_t max_matrix_channel, + int is32))(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int) +{ + return ff_mlp_pack_output; +} + +int32_t ff_mlp_pack_output(int32_t lossless_check_data, + uint16_t blockpos, + int32_t (*sample_buffer)[MAX_CHANNELS], + void *data, + uint8_t *ch_assign, + int8_t *output_shift, + uint8_t max_matrix_channel, + int is32) +{ + unsigned int i, out_ch = 0; + int32_t *data_32 = data; + int16_t *data_16 = data; + + for (i = 0; i < blockpos; i++) { + for (out_ch = 0; out_ch <= max_matrix_channel; out_ch++) { + int mat_ch = ch_assign[out_ch]; + int32_t sample = sample_buffer[i][mat_ch] + << output_shift[mat_ch]; + lossless_check_data ^= (sample & 0xffffff) << mat_ch; + if (is32) + *data_32++ = sample << 8; + else + *data_16++ = sample >> 8; + } + } + return lossless_check_data; +} + av_cold void ff_mlpdsp_init(MLPDSPContext *c) { c->mlp_filter_channel = mlp_filter_channel; + c->mlp_rematrix_channel = ff_mlp_rematrix_channel; + c->mlp_select_pack_output = mlp_select_pack_output; + c->mlp_pack_output = ff_mlp_pack_output; + if (ARCH_ARM) + ff_mlpdsp_init_arm(c); if (ARCH_X86) ff_mlpdsp_init_x86(c); } diff --git a/libavcodec/mlpdsp.h b/libavcodec/mlpdsp.h index 84a8aa3a3..a0edeb776 100644 --- a/libavcodec/mlpdsp.h +++ b/libavcodec/mlpdsp.h @@ -23,15 +23,61 @@ #define AVCODEC_MLPDSP_H #include +#include "mlp.h" + +void ff_mlp_rematrix_channel(int32_t *samples, + const int32_t *coeffs, + const uint8_t *bypassed_lsbs, + const int8_t *noise_buffer, + int index, + unsigned int dest_ch, + uint16_t blockpos, + unsigned int maxchan, + int matrix_noise_shift, + int access_unit_size_pow2, + int32_t mask); + +int32_t ff_mlp_pack_output(int32_t lossless_check_data, + uint16_t blockpos, + int32_t (*sample_buffer)[MAX_CHANNELS], + void *data, + uint8_t *ch_assign, + int8_t *output_shift, + uint8_t max_matrix_channel, + int is32); typedef struct MLPDSPContext { void (*mlp_filter_channel)(int32_t *state, const int32_t *coeff, int firorder, int iirorder, unsigned int filter_shift, int32_t mask, int blocksize, int32_t *sample_buffer); + void (*mlp_rematrix_channel)(int32_t *samples, + const int32_t *coeffs, + const uint8_t *bypassed_lsbs, + const int8_t *noise_buffer, + int index, + unsigned int dest_ch, + uint16_t blockpos, + unsigned int maxchan, + int matrix_noise_shift, + int access_unit_size_pow2, + int32_t mask); + int32_t (*(*mlp_select_pack_output)(uint8_t *ch_assign, + int8_t *output_shift, + uint8_t max_matrix_channel, + int is32))(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int); + int32_t (*mlp_pack_output)(int32_t lossless_check_data, + uint16_t blockpos, + int32_t (*sample_buffer)[MAX_CHANNELS], + void *data, + uint8_t *ch_assign, + int8_t *output_shift, + uint8_t max_matrix_channel, + int is32); } MLPDSPContext; void ff_mlpdsp_init(MLPDSPContext *c); +void ff_mlpdsp_init_arm(MLPDSPContext *c); void ff_mlpdsp_init_x86(MLPDSPContext *c); #endif /* AVCODEC_MLPDSP_H */ diff --git a/libavcodec/motion-test.c b/libavcodec/motion-test.c index 53cfedbe7..73087177a 100644 --- a/libavcodec/motion-test.c +++ b/libavcodec/motion-test.c @@ -91,7 +91,7 @@ static void test_motion(const char *name, emms_c(); /* speed test */ - ti = av_gettime(); + ti = av_gettime_relative(); d1 = 0; for(it=0;itflags |= CODEC_FLAG_BITEXACT; + av_force_cpu_flags(0); memset(&cctx, 0, sizeof(cctx)); ff_dsputil_init(&cctx, ctx); for (c = 0; c < flags_size; c++) { diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c index 5ca59aa2e..6b3cd61e8 100644 --- a/libavcodec/motion_est.c +++ b/libavcodec/motion_est.c @@ -33,6 +33,7 @@ #include "avcodec.h" #include "mathops.h" +#include "mpegutils.h" #include "mpegvideo.h" #undef NDEBUG @@ -285,7 +286,9 @@ static int cmp_qpel(MpegEncContext *s, const int x, const int y, const int subx, #include "motion_est_template.c" -static int zero_cmp(void *s, uint8_t *a, uint8_t *b, int stride, int h){ +static int zero_cmp(MpegEncContext *s, uint8_t *a, uint8_t *b, + int stride, int h) +{ return 0; } @@ -325,9 +328,11 @@ int ff_init_me(MpegEncContext *s){ /*FIXME s->no_rounding b_type*/ if(s->flags&CODEC_FLAG_QPEL){ c->sub_motion_search= qpel_motion_search; - c->qpel_avg= s->dsp.avg_qpel_pixels_tab; - if(s->no_rounding) c->qpel_put= s->dsp.put_no_rnd_qpel_pixels_tab; - else c->qpel_put= s->dsp.put_qpel_pixels_tab; + c->qpel_avg = s->qdsp.avg_qpel_pixels_tab; + if (s->no_rounding) + c->qpel_put = s->qdsp.put_no_rnd_qpel_pixels_tab; + else + c->qpel_put = s->qdsp.put_qpel_pixels_tab; }else{ if(c->avctx->me_sub_cmp&FF_CMP_CHROMA) c->sub_motion_search= hpel_motion_search; @@ -615,7 +620,11 @@ static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift) P_MV1[0]= mx; P_MV1[1]= my; if(saftey_cliping) - for(i=0; i<10; i++){ + for(i=1; i<10; i++){ + if (s->first_slice_line && block<2 && i>1 && i<9) + continue; + if (i>4 && i<9) + continue; if(P[i][0] > (c->xmax<xmax< (c->ymax<ymax<no_rounding) - s->dsp.put_no_rnd_qpel_pixels_tab[1][dxy](dest_y , ref , stride); + s->qdsp.put_no_rnd_qpel_pixels_tab[1][dxy](dest_y, ref, stride); else - s->dsp.put_qpel_pixels_tab [1][dxy](dest_y , ref , stride); + s->qdsp.put_qpel_pixels_tab[1][dxy](dest_y, ref, stride); }else{ uint8_t *ref= c->ref[block][0] + (mx4>>1) + (my4>>1)*stride; dxy = ((my4 & 1) << 1) | (mx4 & 1); @@ -667,7 +676,7 @@ static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift) return INT_MAX; if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){ - dmin_sum += s->dsp.mb_cmp[0](s, s->new_picture.f.data[0] + s->mb_x*16 + s->mb_y*16*stride, c->scratchpad, stride, 16); + dmin_sum += s->dsp.mb_cmp[0](s, s->new_picture.f->data[0] + s->mb_x*16 + s->mb_y*16*stride, c->scratchpad, stride, 16); } if(c->avctx->mb_cmp&FF_CMP_CHROMA){ @@ -682,15 +691,15 @@ static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift) offset= (s->mb_x*8 + (mx>>1)) + (s->mb_y*8 + (my>>1))*s->uvlinesize; if(s->no_rounding){ - s->hdsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad , s->last_picture.f.data[1] + offset, s->uvlinesize, 8); - s->hdsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad + 8, s->last_picture.f.data[2] + offset, s->uvlinesize, 8); + s->hdsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad , s->last_picture.f->data[1] + offset, s->uvlinesize, 8); + s->hdsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad + 8, s->last_picture.f->data[2] + offset, s->uvlinesize, 8); }else{ - s->hdsp.put_pixels_tab [1][dxy](c->scratchpad , s->last_picture.f.data[1] + offset, s->uvlinesize, 8); - s->hdsp.put_pixels_tab [1][dxy](c->scratchpad + 8, s->last_picture.f.data[2] + offset, s->uvlinesize, 8); + s->hdsp.put_pixels_tab [1][dxy](c->scratchpad , s->last_picture.f->data[1] + offset, s->uvlinesize, 8); + s->hdsp.put_pixels_tab [1][dxy](c->scratchpad + 8, s->last_picture.f->data[2] + offset, s->uvlinesize, 8); } - dmin_sum += s->dsp.mb_cmp[1](s, s->new_picture.f.data[1] + s->mb_x*8 + s->mb_y*8*s->uvlinesize, c->scratchpad , s->uvlinesize, 8); - dmin_sum += s->dsp.mb_cmp[1](s, s->new_picture.f.data[2] + s->mb_x*8 + s->mb_y*8*s->uvlinesize, c->scratchpad+8, s->uvlinesize, 8); + dmin_sum += s->dsp.mb_cmp[1](s, s->new_picture.f->data[1] + s->mb_x*8 + s->mb_y*8*s->uvlinesize, c->scratchpad , s->uvlinesize, 8); + dmin_sum += s->dsp.mb_cmp[1](s, s->new_picture.f->data[2] + s->mb_x*8 + s->mb_y*8*s->uvlinesize, c->scratchpad+8, s->uvlinesize, 8); } c->pred_x= mx; @@ -878,7 +887,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, int mb_type=0; Picture * const pic= &s->current_picture; - init_ref(c, s->new_picture.f.data, s->last_picture.f.data, NULL, 16*mb_x, 16*mb_y, 0); + init_ref(c, s->new_picture.f->data, s->last_picture.f->data, NULL, 16*mb_x, 16*mb_y, 0); av_assert0(s->quarter_sample==0 || s->quarter_sample==1); av_assert0(s->linesize == c->stride); @@ -894,8 +903,9 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, /* intra / predictive decision */ pix = c->src[0][0]; - sum = s->dsp.pix_sum(pix, s->linesize); - varc = s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)sum*sum)>>8) + 500; + sum = s->mpvencdsp.pix_sum(pix, s->linesize); + varc = s->mpvencdsp.pix_norm1(pix, s->linesize) - + (((unsigned) sum * sum) >> 8) + 500; pic->mb_mean[s->mb_stride * mb_y + mb_x] = (sum+128)>>8; pic->mb_var [s->mb_stride * mb_y + mb_x] = (varc+128)>>8; @@ -988,7 +998,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, // if (varc*2 + 200*256 + 50*(s->lambda2>>FF_LAMBDA_SHIFT) > vard){ mb_type|= CANDIDATE_MB_TYPE_INTER; c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16); - if(s->flags&CODEC_FLAG_MV0) + if (s->mpv_flags & FF_MPV_FLAG_MV0) if(mx || my) mb_type |= CANDIDATE_MB_TYPE_SKIPPED; //FIXME check difference }else{ @@ -1077,7 +1087,7 @@ int ff_pre_estimate_p_frame_motion(MpegEncContext * s, int P[10][2]; const int shift= 1+s->quarter_sample; const int xy= mb_x + mb_y*s->mb_stride; - init_ref(c, s->new_picture.f.data, s->last_picture.f.data, NULL, 16*mb_x, 16*mb_y, 0); + init_ref(c, s->new_picture.f->data, s->last_picture.f->data, NULL, 16*mb_x, 16*mb_y, 0); av_assert0(s->quarter_sample==0 || s->quarter_sample==1); @@ -1223,14 +1233,14 @@ static inline int check_bidir_mv(MpegEncContext * s, src_y = motion_fy >> 2; ptr = ref_data[0] + (src_y * stride) + src_x; - s->dsp.put_qpel_pixels_tab[0][dxy](dest_y , ptr , stride); + s->qdsp.put_qpel_pixels_tab[0][dxy](dest_y, ptr, stride); dxy = ((motion_by & 3) << 2) | (motion_bx & 3); src_x = motion_bx >> 2; src_y = motion_by >> 2; ptr = ref2_data[0] + (src_y * stride) + src_x; - s->dsp.avg_qpel_pixels_tab[size][dxy](dest_y , ptr , stride); + s->qdsp.avg_qpel_pixels_tab[size][dxy](dest_y, ptr, stride); }else{ dxy = ((motion_fy & 1) << 1) | (motion_fx & 1); src_x = motion_fx >> 1; @@ -1516,8 +1526,8 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, int fmin, bmin, dmin, fbmin, bimin, fimin; int type=0; const int xy = mb_y*s->mb_stride + mb_x; - init_ref(c, s->new_picture.f.data, s->last_picture.f.data, - s->next_picture.f.data, 16 * mb_x, 16 * mb_y, 2); + init_ref(c, s->new_picture.f->data, s->last_picture.f->data, + s->next_picture.f->data, 16 * mb_x, 16 * mb_y, 2); get_limits(s, 16*mb_x, 16*mb_y); @@ -1607,7 +1617,8 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, } //FIXME something smarter if(dmin>256*256*16) type&= ~CANDIDATE_MB_TYPE_DIRECT; //do not try direct mode if it is invalid for this MB - if(s->codec_id == AV_CODEC_ID_MPEG4 && type&CANDIDATE_MB_TYPE_DIRECT && s->flags&CODEC_FLAG_MV0 && *(uint32_t*)s->b_direct_mv_table[xy]) + if (s->codec_id == AV_CODEC_ID_MPEG4 && type&CANDIDATE_MB_TYPE_DIRECT && + s->mpv_flags & FF_MPV_FLAG_MV0 && *(uint32_t*)s->b_direct_mv_table[xy]) type |= CANDIDATE_MB_TYPE_DIRECT0; } diff --git a/libavcodec/motion_est_template.c b/libavcodec/motion_est_template.c index 3123edcf9..53a39c0cb 100644 --- a/libavcodec/motion_est_template.c +++ b/libavcodec/motion_est_template.c @@ -24,6 +24,8 @@ * Motion estimation template. */ +#include "mpegvideo.h" + //Let us hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...) #define LOAD_COMMON\ uint32_t av_unused * const score_map= c->score_map;\ @@ -892,7 +894,8 @@ static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int score_map[0]= dmin; //FIXME precalc first term below? - if((s->pict_type == AV_PICTURE_TYPE_B && !(c->flags & FLAG_DIRECT)) || s->flags&CODEC_FLAG_MV0) + if ((s->pict_type == AV_PICTURE_TYPE_B && !(c->flags & FLAG_DIRECT)) || + s->mpv_flags & FF_MPV_FLAG_MV0) dmin += (mv_penalty[pred_x] + mv_penalty[pred_y])*penalty_factor; /* first line */ diff --git a/libavcodec/motionpixels.c b/libavcodec/motionpixels.c index 089909a4d..19da10a8f 100644 --- a/libavcodec/motionpixels.c +++ b/libavcodec/motionpixels.c @@ -21,7 +21,7 @@ #include "avcodec.h" #include "get_bits.h" -#include "dsputil.h" +#include "bswapdsp.h" #include "internal.h" #define MAX_HUFF_CODES 16 @@ -37,7 +37,7 @@ typedef struct HuffCode { typedef struct MotionPixelsContext { AVCodecContext *avctx; AVFrame *frame; - DSPContext dsp; + BswapDSPContext bdsp; uint8_t *changes_map; int offset_bits_len; int codes_count, current_codes_count; @@ -76,11 +76,11 @@ static av_cold int mp_decode_init(AVCodecContext *avctx) motionpixels_tableinit(); mp->avctx = avctx; - ff_dsputil_init(&mp->dsp, avctx); - mp->changes_map = av_mallocz(avctx->width * h4); + ff_bswapdsp_init(&mp->bdsp); + mp->changes_map = av_mallocz_array(avctx->width, h4); mp->offset_bits_len = av_log2(avctx->width * avctx->height) + 1; - mp->vpt = av_mallocz(avctx->height * sizeof(YuvPixel)); - mp->hpt = av_mallocz(h4 * w4 / 16 * sizeof(YuvPixel)); + mp->vpt = av_mallocz_array(avctx->height, sizeof(YuvPixel)); + mp->hpt = av_mallocz_array(h4 / 4, w4 / 4 * sizeof(YuvPixel)); if (!mp->changes_map || !mp->vpt || !mp->hpt) { av_freep(&mp->changes_map); av_freep(&mp->vpt); @@ -297,7 +297,8 @@ static int mp_decode_frame(AVCodecContext *avctx, av_fast_padded_malloc(&mp->bswapbuf, &mp->bswapbuf_size, buf_size); if (!mp->bswapbuf) return AVERROR(ENOMEM); - mp->dsp.bswap_buf((uint32_t *)mp->bswapbuf, (const uint32_t *)buf, buf_size / 4); + 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); init_get_bits(&gb, mp->bswapbuf, buf_size * 8); diff --git a/libavcodec/motionpixels_tablegen.c b/libavcodec/motionpixels_tablegen.c index 31e5cdf71..14b7b9bb8 100644 --- a/libavcodec/motionpixels_tablegen.c +++ b/libavcodec/motionpixels_tablegen.c @@ -23,7 +23,7 @@ #include #define CONFIG_HARDCODED_TABLES 0 #define MAX_NEG_CROP 0 -#define ff_cropTbl ((uint8_t *)NULL) +#define ff_crop_tab ((uint8_t *)NULL) #include "motionpixels_tablegen.h" #include "tableprint.h" diff --git a/libavcodec/motionpixels_tablegen.h b/libavcodec/motionpixels_tablegen.h index b9802e589..8fb840f0f 100644 --- a/libavcodec/motionpixels_tablegen.h +++ b/libavcodec/motionpixels_tablegen.h @@ -30,7 +30,7 @@ typedef struct YuvPixel { } YuvPixel; static int mp_yuv_to_rgb(int y, int v, int u, int clip_rgb) { - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; int r, g, b; r = (1000 * y + 701 * v) / 1000; diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c index 9b0a6c5bc..5d91e94f7 100644 --- a/libavcodec/movtextenc.c +++ b/libavcodec/movtextenc.c @@ -75,7 +75,7 @@ static av_cold int mov_text_encode_init(AVCodecContext *avctx) MovTextContext *s = avctx->priv_data; avctx->extradata_size = sizeof text_sample_entry; - avctx->extradata = av_mallocz(avctx->extradata_size); + avctx->extradata = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) return AVERROR(ENOMEM); diff --git a/libavcodec/mpc.h b/libavcodec/mpc.h index 295b4c7ae..4cb857489 100644 --- a/libavcodec/mpc.h +++ b/libavcodec/mpc.h @@ -31,8 +31,8 @@ #include "libavutil/lfg.h" #include "avcodec.h" +#include "bswapdsp.h" #include "get_bits.h" -#include "dsputil.h" #include "mpegaudio.h" #include "mpegaudiodsp.h" @@ -50,7 +50,7 @@ typedef struct Band { }Band; typedef struct MPCContext { - DSPContext dsp; + BswapDSPContext bdsp; MPADSPContext mpadsp; GetBitContext gb; int IS, MSS, gapless; diff --git a/libavcodec/mpc7.c b/libavcodec/mpc7.c index 86aca63fb..0f1e34a8f 100644 --- a/libavcodec/mpc7.c +++ b/libavcodec/mpc7.c @@ -30,7 +30,6 @@ #include "libavutil/lfg.h" #include "avcodec.h" #include "get_bits.h" -#include "dsputil.h" #include "internal.h" #include "mpegaudiodsp.h" @@ -71,9 +70,9 @@ static av_cold int mpc7_decode_init(AVCodecContext * avctx) } memset(c->oldDSCF, 0, sizeof(c->oldDSCF)); av_lfg_init(&c->rnd, 0xDEADBEEF); - ff_dsputil_init(&c->dsp, avctx); + ff_bswapdsp_init(&c->bdsp); ff_mpadsp_init(&c->mpadsp); - c->dsp.bswap_buf((uint32_t*)buf, (const uint32_t*)avctx->extradata, 4); + c->bdsp.bswap_buf((uint32_t *) buf, (const uint32_t *) avctx->extradata, 4); ff_mpc_init(); init_get_bits(&gb, buf, 128); @@ -230,7 +229,8 @@ static int mpc7_decode_frame(AVCodecContext * avctx, void *data, av_fast_padded_malloc(&c->bits, &c->buf_size, buf_size); if (!c->bits) return AVERROR(ENOMEM); - c->dsp.bswap_buf((uint32_t *)c->bits, (const uint32_t *)buf, buf_size >> 2); + c->bdsp.bswap_buf((uint32_t *) c->bits, (const uint32_t *) buf, + buf_size >> 2); init_get_bits(&gb, c->bits, buf_size * 8); skip_bits_long(&gb, skip); diff --git a/libavcodec/mpc8.c b/libavcodec/mpc8.c index 2f58805e1..29c65f9ef 100644 --- a/libavcodec/mpc8.c +++ b/libavcodec/mpc8.c @@ -29,7 +29,6 @@ #include "libavutil/lfg.h" #include "avcodec.h" #include "get_bits.h" -#include "dsputil.h" #include "internal.h" #include "mpegaudiodsp.h" @@ -119,7 +118,6 @@ static av_cold int mpc8_decode_init(AVCodecContext * avctx) } memset(c->oldDSCF, 0, sizeof(c->oldDSCF)); av_lfg_init(&c->rnd, 0xDEADBEEF); - ff_dsputil_init(&c->dsp, avctx); ff_mpadsp_init(&c->mpadsp); ff_mpc_init(); diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 09b1f19e4..27d680fd8 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -33,7 +33,6 @@ #include "internal.h" #include "avcodec.h" -#include "dsputil.h" #include "mpegvideo.h" #include "error_resilience.h" #include "mpeg12.h" diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 1f8983051..fcc1d4c48 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -26,17 +26,21 @@ */ #define UNCHECKED_BITSTREAM_READER 1 +#include + #include "libavutil/attributes.h" #include "libavutil/internal.h" #include "libavutil/stereo3d.h" #include "avcodec.h" #include "bytestream.h" -#include "dsputil.h" #include "error_resilience.h" +#include "idctdsp.h" #include "internal.h" +#include "mpeg_er.h" #include "mpeg12.h" #include "mpeg12data.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "thread.h" #include "version.h" @@ -796,10 +800,10 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) av_dlog(s->avctx, "mb_type=%x\n", mb_type); // motion_type = 0; /* avoid warning */ if (IS_INTRA(mb_type)) { - s->dsp.clear_blocks(s->block[0]); + s->bdsp.clear_blocks(s->block[0]); if (!s->chroma_y_shift) - s->dsp.clear_blocks(s->block[6]); + s->bdsp.clear_blocks(s->block[6]); /* compute DCT type */ // FIXME: add an interlaced_dct coded var? @@ -1036,13 +1040,13 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) s->mb_intra = 0; if (HAS_CBP(mb_type)) { - s->dsp.clear_blocks(s->block[0]); + s->bdsp.clear_blocks(s->block[0]); cbp = get_vlc2(&s->gb, ff_mb_pat_vlc.table, MB_PAT_VLC_BITS, 1); if (mb_block_count > 6) { cbp <<= mb_block_count - 6; cbp |= get_bits(&s->gb, mb_block_count - 6); - s->dsp.clear_blocks(s->block[6]); + s->bdsp.clear_blocks(s->block[6]); } if (cbp <= 0) { av_log(s->avctx, AV_LOG_ERROR, @@ -1117,7 +1121,7 @@ static av_cold int mpeg_decode_init(AVCodecContext *avctx) /* we need some permutation to store matrices, * until MPV_common_init() sets the real permutation. */ for (i = 0; i < 64; i++) - s2->dsp.idct_permutation[i] = i; + s2->idsp.idct_permutation[i] = i; ff_MPV_decode_defaults(s2); @@ -1228,7 +1232,6 @@ static enum AVPixelFormat mpeg_get_pixelformat(AVCodecContext *avctx) static void setup_hwaccel_for_pixfmt(AVCodecContext *avctx) { - avctx->hwaccel = ff_find_hwaccel(avctx); // until then pix_fmt may be changed right after codec init if (avctx->hwaccel || uses_vdpau(avctx)) if (avctx->idct_algo == FF_IDCT_AUTO) @@ -1260,7 +1263,7 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) s1->save_width != s->width || s1->save_height != s->height || s1->save_aspect_info != s->aspect_ratio_info || - (s1->save_progressive_seq != s->progressive_sequence && (s->height&31)) || + (s1->save_progressive_seq != s->progressive_sequence && FFALIGN(s->height, 16) != FFALIGN(s->height, 32)) || 0) { if (s1->mpeg_enc_ctx_allocated) { ParseContext pc = s->parse_context; @@ -1345,20 +1348,22 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) } } // MPEG-2 + ff_set_sar(s->avctx, s->avctx->sample_aspect_ratio); + avctx->pix_fmt = mpeg_get_pixelformat(avctx); setup_hwaccel_for_pixfmt(avctx); /* Quantization matrices may need reordering * if DCT permutation is changed. */ - memcpy(old_permutation, s->dsp.idct_permutation, 64 * sizeof(uint8_t)); + memcpy(old_permutation, s->idsp.idct_permutation, 64 * sizeof(uint8_t)); if (ff_MPV_common_init(s) < 0) return -2; - quant_matrix_rebuild(s->intra_matrix, old_permutation, s->dsp.idct_permutation); - quant_matrix_rebuild(s->inter_matrix, old_permutation, s->dsp.idct_permutation); - quant_matrix_rebuild(s->chroma_intra_matrix, old_permutation, s->dsp.idct_permutation); - quant_matrix_rebuild(s->chroma_inter_matrix, old_permutation, s->dsp.idct_permutation); + quant_matrix_rebuild(s->intra_matrix, old_permutation, s->idsp.idct_permutation); + quant_matrix_rebuild(s->inter_matrix, old_permutation, s->idsp.idct_permutation); + quant_matrix_rebuild(s->chroma_intra_matrix, old_permutation, s->idsp.idct_permutation); + quant_matrix_rebuild(s->chroma_inter_matrix, old_permutation, s->idsp.idct_permutation); s1->mpeg_enc_ctx_allocated = 1; } @@ -1400,8 +1405,8 @@ static int mpeg1_decode_picture(AVCodecContext *avctx, const uint8_t *buf, s->mpeg_f_code[1][0] = f_code; s->mpeg_f_code[1][1] = f_code; } - s->current_picture.f.pict_type = s->pict_type; - s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; + s->current_picture.f->pict_type = s->pict_type; + s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; if (avctx->debug & FF_DEBUG_PICT_INFO) av_log(avctx, AV_LOG_DEBUG, @@ -1500,7 +1505,8 @@ static void mpeg_decode_picture_display_extension(Mpeg1Context *s1) } if (s->avctx->debug & FF_DEBUG_PICT_INFO) - av_log(s->avctx, AV_LOG_DEBUG, "pde (%d,%d) (%d,%d) (%d,%d)\n", + av_log(s->avctx, AV_LOG_DEBUG, + "pde (%"PRId16",%"PRId16") (%"PRId16",%"PRId16") (%"PRId16",%"PRId16")\n", s1->pan_scan.position[0][0], s1->pan_scan.position[0][1], s1->pan_scan.position[1][0], s1->pan_scan.position[1][1], s1->pan_scan.position[2][0], s1->pan_scan.position[2][1]); @@ -1512,7 +1518,7 @@ static int load_matrix(MpegEncContext *s, uint16_t matrix0[64], int i; for (i = 0; i < 64; i++) { - int j = s->dsp.idct_permutation[ff_zigzag_direct[i]]; + int j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; int v = get_bits(&s->gb, 8); if (v == 0) { av_log(s->avctx, AV_LOG_ERROR, "matrix damaged\n"); @@ -1562,8 +1568,8 @@ static void mpeg_decode_picture_coding_extension(Mpeg1Context *s1) s->pict_type = AV_PICTURE_TYPE_P; } else s->pict_type = AV_PICTURE_TYPE_B; - s->current_picture.f.pict_type = s->pict_type; - s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; + s->current_picture.f->pict_type = s->pict_type; + s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; } s->mpeg_f_code[0][0] += !s->mpeg_f_code[0][0]; s->mpeg_f_code[0][1] += !s->mpeg_f_code[0][1]; @@ -1583,11 +1589,11 @@ static void mpeg_decode_picture_coding_extension(Mpeg1Context *s1) s->progressive_frame = get_bits1(&s->gb); if (s->alternate_scan) { - ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable, ff_alternate_vertical_scan); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_alternate_vertical_scan); } else { - ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable, ff_zigzag_direct); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); + ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_zigzag_direct); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); } /* composite display not parsed */ @@ -1617,19 +1623,19 @@ static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size) ff_mpeg_er_frame_start(s); /* first check if we must repeat the frame */ - s->current_picture_ptr->f.repeat_pict = 0; + s->current_picture_ptr->f->repeat_pict = 0; if (s->repeat_first_field) { if (s->progressive_sequence) { if (s->top_field_first) - s->current_picture_ptr->f.repeat_pict = 4; + s->current_picture_ptr->f->repeat_pict = 4; else - s->current_picture_ptr->f.repeat_pict = 2; + s->current_picture_ptr->f->repeat_pict = 2; } else if (s->progressive_frame) { - s->current_picture_ptr->f.repeat_pict = 1; + s->current_picture_ptr->f->repeat_pict = 1; } } - pan_scan = av_frame_new_side_data(&s->current_picture_ptr->f, + pan_scan = av_frame_new_side_data(s->current_picture_ptr->f, AV_FRAME_DATA_PANSCAN, sizeof(s1->pan_scan)); if (!pan_scan) @@ -1638,7 +1644,7 @@ static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size) if (s1->a53_caption) { AVFrameSideData *sd = av_frame_new_side_data( - &s->current_picture_ptr->f, AV_FRAME_DATA_A53_CC, + s->current_picture_ptr->f, AV_FRAME_DATA_A53_CC, s1->a53_caption_size); if (sd) memcpy(sd->data, s1->a53_caption, s1->a53_caption_size); @@ -1646,7 +1652,7 @@ static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size) } if (s1->has_stereo3d) { - AVStereo3D *stereo = av_stereo3d_create_side_data(&s->current_picture_ptr->f); + AVStereo3D *stereo = av_stereo3d_create_side_data(s->current_picture_ptr->f); if (!stereo) return AVERROR(ENOMEM); @@ -1671,10 +1677,10 @@ static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size) } for (i = 0; i < 4; i++) { - s->current_picture.f.data[i] = s->current_picture_ptr->f.data[i]; + s->current_picture.f->data[i] = s->current_picture_ptr->f->data[i]; if (s->picture_structure == PICT_BOTTOM_FIELD) - s->current_picture.f.data[i] += - s->current_picture_ptr->f.linesize[i]; + s->current_picture.f->data[i] += + s->current_picture_ptr->f->linesize[i]; } } @@ -2024,7 +2030,7 @@ static int slice_end(AVCodecContext *avctx, AVFrame *pict) ff_MPV_frame_end(s); if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { - int ret = av_frame_ref(pict, &s->current_picture_ptr->f); + int ret = av_frame_ref(pict, s->current_picture_ptr->f); if (ret < 0) return ret; ff_print_debug_info(s, s->current_picture_ptr, pict); @@ -2035,7 +2041,7 @@ static int slice_end(AVCodecContext *avctx, AVFrame *pict) /* latency of 1 frame for I- and P-frames */ /* XXX: use another variable than picture_number */ if (s->last_picture_ptr != NULL) { - int ret = av_frame_ref(pict, &s->last_picture_ptr->f); + int ret = av_frame_ref(pict, s->last_picture_ptr->f); if (ret < 0) return ret; ff_print_debug_info(s, s->last_picture_ptr, pict); @@ -2090,7 +2096,7 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, load_matrix(s, s->chroma_intra_matrix, s->intra_matrix, 1); } else { for (i = 0; i < 64; i++) { - j = s->dsp.idct_permutation[i]; + j = s->idsp.idct_permutation[i]; v = ff_mpeg1_default_intra_matrix[i]; s->intra_matrix[j] = v; s->chroma_intra_matrix[j] = v; @@ -2100,7 +2106,7 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, load_matrix(s, s->chroma_inter_matrix, s->inter_matrix, 0); } else { for (i = 0; i < 64; i++) { - int j = s->dsp.idct_permutation[i]; + int j = s->idsp.idct_permutation[i]; v = ff_mpeg1_default_non_intra_matrix[i]; s->inter_matrix[j] = v; s->chroma_inter_matrix[j] = v; @@ -2158,7 +2164,7 @@ static int vcr2_init_sequence(AVCodecContext *avctx) s1->mpeg_enc_ctx_allocated = 1; for (i = 0; i < 64; i++) { - int j = s->dsp.idct_permutation[i]; + int j = s->idsp.idct_permutation[i]; v = ff_mpeg1_default_intra_matrix[i]; s->intra_matrix[j] = v; s->chroma_intra_matrix[j] = v; @@ -2387,7 +2393,7 @@ static int decode_chunks(AVCodecContext *avctx, AVFrame *picture, input_size = buf_end - buf_ptr; if (avctx->debug & FF_DEBUG_STARTCODE) - av_log(avctx, AV_LOG_DEBUG, "%3X at %td left %d\n", + av_log(avctx, AV_LOG_DEBUG, "%3"PRIX32" at %"PTRDIFF_SPECIFIER" left %d\n", start_code, buf_ptr - buf, input_size); /* prepare data for next start code */ @@ -2673,12 +2679,11 @@ 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"); if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == SEQ_END_CODE)) { /* special case for last picture */ if (s2->low_delay == 0 && s2->next_picture_ptr) { - int ret = av_frame_ref(picture, &s2->next_picture_ptr->f); + int ret = av_frame_ref(picture, s2->next_picture_ptr->f); if (ret < 0) return ret; diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 22f9fcba0..0dbcda86b 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -39,6 +39,7 @@ #include "mathops.h" #include "mpeg12.h" #include "mpeg12data.h" +#include "mpegutils.h" #include "mpegvideo.h" @@ -239,13 +240,13 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) unsigned int vbv_buffer_size, fps, v; int i, constraint_parameter_flag; uint64_t time_code; - float best_aspect_error = 1E10; - float aspect_ratio = av_q2d(s->avctx->sample_aspect_ratio); + int64_t best_aspect_error = INT64_MAX; + AVRational aspect_ratio = s->avctx->sample_aspect_ratio; - if (aspect_ratio == 0.0) - aspect_ratio = 1.0; // pixel aspect 1.1 (VGA) + if (aspect_ratio.num == 0 || aspect_ratio.den == 0) + aspect_ratio = (AVRational){1,1}; // pixel aspect 1.1 (VGA) - if (s->current_picture.f.key_frame) { + if (s->current_picture.f->key_frame) { AVRational framerate = ff_mpeg12_frame_rate_tab[s->frame_rate_index]; /* mpeg1 header repeated every gop */ @@ -255,15 +256,15 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) put_sbits(&s->pb, 12, s->height & 0xFFF); for (i = 1; i < 15; i++) { - float error = aspect_ratio; + int64_t error = aspect_ratio.num * (1LL<<32) / aspect_ratio.den; if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || i <= 1) - error -= 1.0 / ff_mpeg1_aspect[i]; + error -= (1LL<<32) / ff_mpeg1_aspect[i]; else - error -= av_q2d(ff_mpeg2_aspect[i]) * s->height / s->width; + error -= (1LL<<32)*ff_mpeg2_aspect[i].num * s->height / s->width / ff_mpeg2_aspect[i].den; error = FFABS(error); - if (error < best_aspect_error) { + if (error - 2 <= best_aspect_error) { best_aspect_error = error; s->aspect_ratio_info = i; } @@ -310,6 +311,11 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) ff_write_quant_matrix(&s->pb, s->avctx->inter_matrix); if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + AVFrameSideData *side_data; + int width = s->width; + int height = s->height; + int use_seq_disp_ext; + put_header(s, EXT_START_CODE); put_bits(&s->pb, 4, 1); // seq ext @@ -328,6 +334,35 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) put_bits(&s->pb, 1, s->low_delay); put_bits(&s->pb, 2, s->mpeg2_frame_rate_ext.num-1); // frame_rate_ext_n put_bits(&s->pb, 5, s->mpeg2_frame_rate_ext.den-1); // frame_rate_ext_d + + side_data = av_frame_get_side_data(s->current_picture_ptr->f, AV_FRAME_DATA_PANSCAN); + if (side_data) { + AVPanScan *pan_scan = (AVPanScan *)side_data->data; + if (pan_scan->width && pan_scan->height) { + width = pan_scan->width >> 4; + height = pan_scan->height >> 4; + } + } + + use_seq_disp_ext = (width != s->width || + height != s->height || + s->avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + s->avctx->color_trc != AVCOL_TRC_UNSPECIFIED || + s->avctx->colorspace != AVCOL_SPC_UNSPECIFIED); + + if (s->seq_disp_ext == 1 || (s->seq_disp_ext == -1 && use_seq_disp_ext)) { + put_header(s, EXT_START_CODE); + put_bits(&s->pb, 4, 2); // sequence display extension + put_bits(&s->pb, 3, 0); // video_format: 0 is components + put_bits(&s->pb, 1, 1); // colour_description + put_bits(&s->pb, 8, s->avctx->color_primaries); // colour_primaries + put_bits(&s->pb, 8, s->avctx->color_trc); // transfer_characteristics + put_bits(&s->pb, 8, s->avctx->colorspace); // matrix_coefficients + put_bits(&s->pb, 14, width); // display_horizontal_size + put_bits(&s->pb, 1, 1); // marker_bit + put_bits(&s->pb, 14, height); // display_vertical_size + put_bits(&s->pb, 3, 0); // remaining 3 bits are zero padding + } } put_header(s, GOP_START_CODE); @@ -335,10 +370,10 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) /* time code: we must convert from the real frame rate to a * fake MPEG frame rate in case of low frame rate */ fps = (framerate.num + framerate.den / 2) / framerate.den; - time_code = s->current_picture_ptr->f.coded_picture_number + + time_code = s->current_picture_ptr->f->coded_picture_number + s->avctx->timecode_frame_start; - s->gop_picture_number = s->current_picture_ptr->f.coded_picture_number; + s->gop_picture_number = s->current_picture_ptr->f->coded_picture_number; av_assert0(s->drop_frame_timecode == !!(s->tc.flags & AV_TIMECODE_FLAG_DROPFRAME)); if (s->drop_frame_timecode) @@ -349,7 +384,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->flags & CODEC_FLAG_CLOSED_GOP) || s->intra_only || !s->gop_picture_number); put_bits(&s->pb, 1, 0); // broken link } } @@ -450,7 +485,7 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) if (s->progressive_sequence) put_bits(&s->pb, 1, 0); /* no repeat */ else - put_bits(&s->pb, 1, s->current_picture_ptr->f.top_field_first); + put_bits(&s->pb, 1, s->current_picture_ptr->f->top_field_first); /* XXX: optimize the generation of this flag with entropy measures */ s->frame_pred_frame_dct = s->progressive_sequence; @@ -474,7 +509,7 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) for (i = 0; i < sizeof(svcd_scan_offset_placeholder); i++) put_bits(&s->pb, 8, svcd_scan_offset_placeholder[i]); } - side_data = av_frame_get_side_data(&s->current_picture_ptr->f, + side_data = av_frame_get_side_data(s->current_picture_ptr->f, AV_FRAME_DATA_STEREO3D); if (side_data) { AVStereo3D *stereo = (AVStereo3D *)side_data->data; @@ -682,7 +717,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) { @@ -959,7 +994,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) @@ -1088,6 +1123,10 @@ static const AVOption mpeg2_options[] = { COMMON_OPTS { "non_linear_quant", "Use nonlinear quantizer.", OFFSET(q_scale_type), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, { "alternate_scan", "Enable alternate scantable.", OFFSET(alternate_scan), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "seq_disp_ext", "Write sequence_display_extension blocks.", OFFSET(seq_disp_ext), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE, "seq_disp_ext" }, + { "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, VE, "seq_disp_ext" }, + { "never", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, VE, "seq_disp_ext" }, + { "always", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, VE, "seq_disp_ext" }, FF_MPV_COMMON_OPTS { NULL }, }; diff --git a/libavcodec/mpeg4video.c b/libavcodec/mpeg4video.c index 3f92ba5a9..38ed5af66 100644 --- a/libavcodec/mpeg4video.c +++ b/libavcodec/mpeg4video.c @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "mpegutils.h" #include "mpegvideo.h" #include "mpeg4video.h" #include "mpeg4data.h" diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index a1f530c3b..0b25e2982 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -24,7 +24,9 @@ #include "libavutil/opt.h" #include "error_resilience.h" +#include "idctdsp.h" #include "internal.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "mpeg4video.h" #include "h263.h" @@ -73,11 +75,11 @@ void ff_mpeg4_pred_ac(MpegEncContext *s, int16_t *block, int n, int dir) n == 1 || n == 3) { /* same qscale */ for (i = 1; i < 8; i++) - block[s->dsp.idct_permutation[i << 3]] += ac_val[i]; + block[s->idsp.idct_permutation[i << 3]] += ac_val[i]; } else { /* different qscale, we must rescale */ for (i = 1; i < 8; i++) - block[s->dsp.idct_permutation[i << 3]] += ROUNDED_DIV(ac_val[i] * qscale_table[xy], s->qscale); + block[s->idsp.idct_permutation[i << 3]] += ROUNDED_DIV(ac_val[i] * qscale_table[xy], s->qscale); } } else { const int xy = s->mb_x + s->mb_y * s->mb_stride - s->mb_stride; @@ -88,21 +90,21 @@ void ff_mpeg4_pred_ac(MpegEncContext *s, int16_t *block, int n, int dir) n == 2 || n == 3) { /* same qscale */ for (i = 1; i < 8; i++) - block[s->dsp.idct_permutation[i]] += ac_val[i + 8]; + block[s->idsp.idct_permutation[i]] += ac_val[i + 8]; } else { /* different qscale, we must rescale */ for (i = 1; i < 8; i++) - block[s->dsp.idct_permutation[i]] += ROUNDED_DIV(ac_val[i + 8] * qscale_table[xy], s->qscale); + block[s->idsp.idct_permutation[i]] += ROUNDED_DIV(ac_val[i + 8] * qscale_table[xy], s->qscale); } } } /* left copy */ for (i = 1; i < 8; i++) - ac_val1[i] = block[s->dsp.idct_permutation[i << 3]]; + ac_val1[i] = block[s->idsp.idct_permutation[i << 3]]; /* top copy */ for (i = 1; i < 8; i++) - ac_val1[8 + i] = block[s->dsp.idct_permutation[i]]; + ac_val1[8 + i] = block[s->idsp.idct_permutation[i]]; } /** @@ -613,7 +615,7 @@ static int mpeg4_decode_partition_a(Mpeg4DecContext *ctx) cbpc = get_vlc2(&s->gb, ff_h263_intra_MCBPC_vlc.table, INTRA_MCBPC_VLC_BITS, 2); if (cbpc < 0) { av_log(s->avctx, AV_LOG_ERROR, - "cbpc corrupted at %d %d\n", s->mb_x, s->mb_y); + "mcbpc corrupted at %d %d\n", s->mb_x, s->mb_y); return -1; } } while (cbpc == 8); @@ -685,7 +687,7 @@ try_again: cbpc = get_vlc2(&s->gb, ff_h263_inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2); if (cbpc < 0) { av_log(s->avctx, AV_LOG_ERROR, - "cbpc corrupted at %d %d\n", s->mb_x, s->mb_y); + "mcbpc corrupted at %d %d\n", s->mb_x, s->mb_y); return -1; } if (cbpc == 20) @@ -1083,7 +1085,8 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, if (SHOW_UBITS(re, &s->gb, 1) == 0) { av_log(s->avctx, AV_LOG_ERROR, "1. marker bit missing in 3. esc\n"); - return -1; + if (!(s->err_recognition & AV_EF_IGNORE_ERR)) + return -1; } SKIP_CACHE(re, &s->gb, 1); @@ -1093,7 +1096,8 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, if (SHOW_UBITS(re, &s->gb, 1) == 0) { av_log(s->avctx, AV_LOG_ERROR, "2. marker bit missing in 3. esc\n"); - return -1; + if (!(s->err_recognition & AV_EF_IGNORE_ERR)) + return -1; } SKIP_COUNTER(re, &s->gb, 1 + 12 + 1); @@ -1164,6 +1168,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); LAST_SKIP_BITS(re, &s->gb, 1); } + tprintf(s->avctx, "dct[%d][%d] = %- 4d end?:%d\n", scan_table[i&63]&7, scan_table[i&63] >> 3, level, i>62); if (i > 62) { i -= 192; if (i & (~63)) { @@ -1257,7 +1262,7 @@ static int mpeg4_decode_partitioned_mb(MpegEncContext *s, int16_t block[6][64]) if (!IS_SKIP(mb_type)) { int i; - s->dsp.clear_blocks(s->block[0]); + s->bdsp.clear_blocks(s->block[0]); /* decode each block */ for (i = 0; i < 6; i++) { if (mpeg4_decode_block(ctx, block[i], i, cbp & 32, s->mb_intra, ctx->rvlc) < 0) { @@ -1330,12 +1335,12 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) cbpc = get_vlc2(&s->gb, ff_h263_inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2); if (cbpc < 0) { av_log(s->avctx, AV_LOG_ERROR, - "cbpc damaged at %d %d\n", s->mb_x, s->mb_y); + "mcbpc damaged at %d %d\n", s->mb_x, s->mb_y); return -1; } } while (cbpc == 20); - s->dsp.clear_blocks(s->block[0]); + s->bdsp.clear_blocks(s->block[0]); dquant = cbpc & 8; s->mb_intra = ((cbpc & 4) != 0); if (s->mb_intra) @@ -1481,7 +1486,7 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) if (modb2) { cbp = 0; } else { - s->dsp.clear_blocks(s->block[0]); + s->bdsp.clear_blocks(s->block[0]); cbp = get_bits(&s->gb, 6); } @@ -1616,7 +1621,7 @@ intra: if (!s->progressive_sequence) s->interlaced_dct = get_bits1(&s->gb); - s->dsp.clear_blocks(s->block[0]); + s->bdsp.clear_blocks(s->block[0]); /* decode each block */ for (i = 0; i < 6; i++) { if (mpeg4_decode_block(ctx, block[i], i, cbp & 32, 1, 0) < 0) @@ -1739,7 +1744,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 won't be overridden. */ if (s->picture_number == 0) s->low_delay = 0; } @@ -1852,7 +1857,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) /* load default matrixes */ for (i = 0; i < 64; i++) { - int j = s->dsp.idct_permutation[i]; + int j = s->idsp.idct_permutation[i]; v = ff_mpeg4_default_intra_matrix[i]; s->intra_matrix[j] = v; s->chroma_intra_matrix[j] = v; @@ -1872,14 +1877,14 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) break; last = v; - j = s->dsp.idct_permutation[ff_zigzag_direct[i]]; + j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; s->intra_matrix[j] = last; s->chroma_intra_matrix[j] = last; } /* replicate last value */ for (; i < 64; i++) { - int j = s->dsp.idct_permutation[ff_zigzag_direct[i]]; + int j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; s->intra_matrix[j] = last; s->chroma_intra_matrix[j] = last; } @@ -1895,14 +1900,14 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) break; last = v; - j = s->dsp.idct_permutation[ff_zigzag_direct[i]]; + j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; s->inter_matrix[j] = v; s->chroma_inter_matrix[j] = v; } /* replicate last value */ for (; i < 64; i++) { - int j = s->dsp.idct_permutation[ff_zigzag_direct[i]]; + int j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; s->inter_matrix[j] = last; s->chroma_inter_matrix[j] = last; } @@ -2153,9 +2158,9 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx) s->workaround_bugs |= FF_BUG_DC_CLIP; #define SET_QPEL_FUNC(postfix1, postfix2) \ - s->dsp.put_ ## postfix1 = ff_put_ ## postfix2; \ - s->dsp.put_no_rnd_ ## postfix1 = ff_put_no_rnd_ ## postfix2; \ - s->dsp.avg_ ## postfix1 = ff_avg_ ## postfix2; + s->qdsp.put_ ## postfix1 = ff_put_ ## postfix2; \ + s->qdsp.put_no_rnd_ ## postfix1 = ff_put_no_rnd_ ## postfix2; \ + s->qdsp.avg_ ## postfix1 = ff_avg_ ## postfix2; if (ctx->lavc_build < 4653U) s->workaround_bugs |= FF_BUG_STD_QPEL; @@ -2378,15 +2383,15 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) } if (s->alternate_scan) { - ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable, ff_alternate_vertical_scan); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable, ff_alternate_vertical_scan); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, ff_alternate_vertical_scan); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); } else { - ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable, ff_zigzag_direct); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_zigzag_direct); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); } if (s->pict_type == AV_PICTURE_TYPE_S && diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index 14c6e8fae..f93811947 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -23,6 +23,7 @@ #include "libavutil/attributes.h" #include "libavutil/log.h" #include "libavutil/opt.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "h263.h" #include "mpeg4video.h" @@ -109,11 +110,11 @@ static inline void restore_ac_coeffs(MpegEncContext *s, int16_t block[6][64], if (dir[n]) { /* top prediction */ for (i = 1; i < 8; i++) - block[n][s->dsp.idct_permutation[i]] = ac_val[i + 8]; + block[n][s->idsp.idct_permutation[i]] = ac_val[i + 8]; } else { /* left prediction */ for (i = 1; i < 8; i++) - block[n][s->dsp.idct_permutation[i << 3]] = ac_val[i]; + block[n][s->idsp.idct_permutation[i << 3]] = ac_val[i]; } } } @@ -151,17 +152,17 @@ static inline int decide_ac_pred(MpegEncContext *s, int16_t block[6][64], if (s->mb_y == 0 || s->qscale == qscale_table[xy] || n == 2 || n == 3) { /* same qscale */ for (i = 1; i < 8; i++) { - const int level = block[n][s->dsp.idct_permutation[i]]; - block[n][s->dsp.idct_permutation[i]] = level - ac_val[i + 8]; - ac_val1[i] = block[n][s->dsp.idct_permutation[i << 3]]; + const int level = block[n][s->idsp.idct_permutation[i]]; + block[n][s->idsp.idct_permutation[i]] = level - ac_val[i + 8]; + ac_val1[i] = block[n][s->idsp.idct_permutation[i << 3]]; ac_val1[i + 8] = level; } } else { /* different qscale, we must rescale */ for (i = 1; i < 8; i++) { - const int level = block[n][s->dsp.idct_permutation[i]]; - block[n][s->dsp.idct_permutation[i]] = level - ROUNDED_DIV(ac_val[i + 8] * qscale_table[xy], s->qscale); - ac_val1[i] = block[n][s->dsp.idct_permutation[i << 3]]; + const int level = block[n][s->idsp.idct_permutation[i]]; + block[n][s->idsp.idct_permutation[i]] = level - ROUNDED_DIV(ac_val[i + 8] * qscale_table[xy], s->qscale); + ac_val1[i] = block[n][s->idsp.idct_permutation[i << 3]]; ac_val1[i + 8] = level; } } @@ -173,18 +174,18 @@ static inline int decide_ac_pred(MpegEncContext *s, int16_t block[6][64], if (s->mb_x == 0 || s->qscale == qscale_table[xy] || n == 1 || n == 3) { /* same qscale */ for (i = 1; i < 8; i++) { - const int level = block[n][s->dsp.idct_permutation[i << 3]]; - block[n][s->dsp.idct_permutation[i << 3]] = level - ac_val[i]; + const int level = block[n][s->idsp.idct_permutation[i << 3]]; + block[n][s->idsp.idct_permutation[i << 3]] = level - ac_val[i]; ac_val1[i] = level; - ac_val1[i + 8] = block[n][s->dsp.idct_permutation[i]]; + ac_val1[i + 8] = block[n][s->idsp.idct_permutation[i]]; } } else { /* different qscale, we must rescale */ for (i = 1; i < 8; i++) { - const int level = block[n][s->dsp.idct_permutation[i << 3]]; - block[n][s->dsp.idct_permutation[i << 3]] = level - ROUNDED_DIV(ac_val[i] * qscale_table[xy], s->qscale); + const int level = block[n][s->idsp.idct_permutation[i << 3]]; + block[n][s->idsp.idct_permutation[i << 3]] = level - ROUNDED_DIV(ac_val[i] * qscale_table[xy], s->qscale); ac_val1[i] = level; - ac_val1[i + 8] = block[n][s->dsp.idct_permutation[i]]; + ac_val1[i + 8] = block[n][s->idsp.idct_permutation[i]]; } } st[n] = s->intra_v_scantable.permutated; @@ -277,19 +278,19 @@ static inline void mpeg4_encode_dc(PutBitContext *s, int level, int n) if (n < 4) { /* luminance */ - put_bits(&s->pb, ff_mpeg4_DCtab_lum[size][1], ff_mpeg4_DCtab_lum[size][0]); + put_bits(s, 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]); + put_bits(s, 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); + put_bits(s, size, level); if (size > 8) - put_bits(&s->pb, 1, 1); + put_bits(s, 1, 1); } #endif } @@ -484,7 +485,7 @@ static inline int get_b_cbp(MpegEncContext *s, int16_t block[6][64], for (i = 0; i < 6; i++) { if (s->block_last_index[i] >= 0 && ((cbp >> (5 - i)) & 1) == 0) { s->block_last_index[i] = -1; - s->dsp.clear_block(s->block[i]); + s->bdsp.clear_block(s->block[i]); } } } else { @@ -670,7 +671,7 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], y = s->mb_y * 16; offset = x + y * s->linesize; - p_pic = s->new_picture.f.data[0] + offset; + p_pic = s->new_picture.f->data[0] + offset; s->mb_skipped = 1; for (i = 0; i < s->max_b_frames; i++) { @@ -678,10 +679,10 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], int diff; Picture *pic = s->reordered_input_picture[i + 1]; - if (!pic || pic->f.pict_type != AV_PICTURE_TYPE_B) + if (!pic || pic->f->pict_type != AV_PICTURE_TYPE_B) break; - b_pic = pic->f.data[0] + offset; + b_pic = pic->f->data[0] + offset; if (!pic->shared) b_pic += INPLACE_OFFSET; @@ -915,9 +916,9 @@ static void mpeg4_encode_gop_header(MpegEncContext *s) put_bits(&s->pb, 16, 0); put_bits(&s->pb, 16, GOP_STARTCODE); - time = s->current_picture_ptr->f.pts; + time = s->current_picture_ptr->f->pts; if (s->reordered_input_picture[1]) - time = FFMIN(time, s->reordered_input_picture[1]->f.pts); + time = FFMIN(time, s->reordered_input_picture[1]->f->pts); time = time * s->avctx->time_base.num; s->last_time_base = FFUDIV(time, s->avctx->time_base.den); @@ -1125,7 +1126,7 @@ void ff_mpeg4_encode_picture_header(MpegEncContext *s, int picture_number) } put_bits(&s->pb, 3, 0); /* intra dc VLC threshold */ if (!s->progressive_sequence) { - put_bits(&s->pb, 1, s->current_picture_ptr->f.top_field_first); + put_bits(&s->pb, 1, s->current_picture_ptr->f->top_field_first); put_bits(&s->pb, 1, s->alternate_scan); } // FIXME sprite stuff diff --git a/libavcodec/mpeg_er.c b/libavcodec/mpeg_er.c new file mode 100644 index 000000000..3d90582db --- /dev/null +++ b/libavcodec/mpeg_er.c @@ -0,0 +1,60 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "error_resilience.h" +#include "mpegvideo.h" +#include "mpeg_er.h" + +static void set_erpic(ERPicture *dst, Picture *src) +{ + int i; + + memset(dst, 0, sizeof(*dst)); + if (!src) { + dst->f = NULL; + dst->tf = NULL; + return; + } + + dst->f = src->f; + dst->tf = &src->tf; + + for (i = 0; i < 2; i++) { + dst->motion_val[i] = src->motion_val[i]; + dst->ref_index[i] = src->ref_index[i]; + } + + dst->mb_type = src->mb_type; + dst->field_picture = src->field_picture; +} + +void ff_mpeg_er_frame_start(MpegEncContext *s) +{ + ERContext *er = &s->er; + + set_erpic(&er->cur_pic, s->current_picture_ptr); + set_erpic(&er->next_pic, s->next_picture_ptr); + set_erpic(&er->last_pic, s->last_picture_ptr); + + er->pp_time = s->pp_time; + er->pb_time = s->pb_time; + er->quarter_sample = s->quarter_sample; + er->partitioned_frame = s->partitioned_frame; + + ff_er_frame_start(er); +} diff --git a/libavcodec/mpeg_er.h b/libavcodec/mpeg_er.h new file mode 100644 index 000000000..bd74fbb0c --- /dev/null +++ b/libavcodec/mpeg_er.h @@ -0,0 +1,26 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MPEG_ER_H +#define AVCODEC_MPEG_ER_H + +#include "mpegvideo.h" + +void ff_mpeg_er_frame_start(MpegEncContext *s); + +#endif /* AVCODEC_MPEG_ER_H */ diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c index 1c1ab6e59..05237070e 100644 --- a/libavcodec/mpegaudiodec_template.c +++ b/libavcodec/mpegaudiodec_template.c @@ -216,7 +216,7 @@ static inline int l1_unscale(int n, int mant, int scale_factor) shift = scale_factor_modshift[scale_factor]; mod = shift & 3; shift >>= 2; - val = MUL64(mant + (-1 << n) + 1, scale_factor_mult[n-1][mod]); + val = MUL64((int)(mant + (-1U << n) + 1), scale_factor_mult[n-1][mod]); shift += n; /* NOTE: at this point, 1 <= shift >= 21 + 15 */ return (int)((val + (1LL << (shift - 1))) >> shift); @@ -1705,7 +1705,9 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame_ptr, static void mp_flush(MPADecodeContext *ctx) { memset(ctx->synth_buf, 0, sizeof(ctx->synth_buf)); + memset(ctx->mdct_buf, 0, sizeof(ctx->mdct_buf)); ctx->last_buf_size = 0; + ctx->dither_state = 0; } static void flush(AVCodecContext *avctx) diff --git a/libavcodec/mpegaudiodsp.c b/libavcodec/mpegaudiodsp.c index ddb742845..5fe344489 100644 --- a/libavcodec/mpegaudiodsp.c +++ b/libavcodec/mpegaudiodsp.c @@ -41,6 +41,7 @@ av_cold void ff_mpadsp_init(MPADSPContext *s) s->imdct36_blocks_float = ff_imdct36_blocks_float; s->imdct36_blocks_fixed = ff_imdct36_blocks_fixed; + if (ARCH_AARCH64) ff_mpadsp_init_aarch64(s); if (ARCH_ARM) ff_mpadsp_init_arm(s); if (ARCH_PPC) ff_mpadsp_init_ppc(s); if (ARCH_X86) ff_mpadsp_init_x86(s); diff --git a/libavcodec/mpegaudiodsp.h b/libavcodec/mpegaudiodsp.h index 38c75c7fe..a722a2f36 100644 --- a/libavcodec/mpegaudiodsp.h +++ b/libavcodec/mpegaudiodsp.h @@ -55,6 +55,7 @@ void ff_mpa_synth_filter_float(MPADSPContext *s, float *samples, int incr, float *sb_samples); +void ff_mpadsp_init_aarch64(MPADSPContext *s); void ff_mpadsp_init_arm(MPADSPContext *s); void ff_mpadsp_init_ppc(MPADSPContext *s); void ff_mpadsp_init_x86(MPADSPContext *s); diff --git a/libavcodec/mpegaudioenc_template.c b/libavcodec/mpegaudioenc_template.c index b2dfe7825..e9571d83c 100644 --- a/libavcodec/mpegaudioenc_template.c +++ b/libavcodec/mpegaudioenc_template.c @@ -108,10 +108,15 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx) s->freq_index = i; /* encoding bitrate & frequency */ - for(i=0;i<15;i++) { + for(i=1;i<15;i++) { if (avpriv_mpa_bitrate_tab[s->lsf][1][i] == bitrate) break; } + if (i == 15 && !avctx->bit_rate) { + i = 14; + bitrate = avpriv_mpa_bitrate_tab[s->lsf][1][i]; + avctx->bit_rate = bitrate * 1000; + } if (i == 15){ av_log(avctx, AV_LOG_ERROR, "bitrate %d is not allowed in mp2\n", bitrate); return AVERROR(EINVAL); @@ -700,9 +705,10 @@ static void encode_frame(MpegAudioContext *s, else q1 = sample >> shift; q1 = (q1 * mult) >> P; - q[m] = ((q1 + (1 << P)) * steps) >> (P + 1); - if (q[m] < 0) - q[m] = 0; + q1 += 1 << P; + if (q1 < 0) + q1 = 0; + q[m] = (q1 * (unsigned)steps) >> (P + 1); } #endif if (q[m] >= steps) @@ -773,7 +779,7 @@ static int MPA_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } static const AVCodecDefault mp2_defaults[] = { - { "b", "128k" }, + { "b", "0" }, { NULL }, }; diff --git a/libavcodec/mpegutils.c b/libavcodec/mpegutils.c new file mode 100644 index 000000000..62cc36aa6 --- /dev/null +++ b/libavcodec/mpegutils.c @@ -0,0 +1,80 @@ +/* + * Mpeg video formats-related defines and utility functions + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/frame.h" +#include "libavutil/pixdesc.h" + +#include "avcodec.h" +#include "mpegutils.h" + +void ff_draw_horiz_band(AVCodecContext *avctx, + AVFrame *cur, AVFrame *last, + int y, int h, int picture_structure, + int first_field, int low_delay) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + int vshift = desc->log2_chroma_h; + const int field_pic = picture_structure != PICT_FRAME; + if (field_pic) { + h <<= 1; + y <<= 1; + } + + h = FFMIN(h, avctx->height - y); + + if (field_pic && first_field && + !(avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD)) + return; + + if (avctx->draw_horiz_band) { + AVFrame *src; + int offset[AV_NUM_DATA_POINTERS]; + int i; + + if (cur->pict_type == AV_PICTURE_TYPE_B || low_delay || + (avctx->slice_flags & SLICE_FLAG_CODED_ORDER)) + src = cur; + else if (last) + src = last; + else + return; + + if (cur->pict_type == AV_PICTURE_TYPE_B && + picture_structure == PICT_FRAME && + avctx->codec_id != AV_CODEC_ID_SVQ3) { + for (i = 0; i < AV_NUM_DATA_POINTERS; i++) + offset[i] = 0; + } else { + offset[0]= y * src->linesize[0]; + offset[1]= + offset[2]= (y >> vshift) * src->linesize[1]; + for (i = 3; i < AV_NUM_DATA_POINTERS; i++) + offset[i] = 0; + } + + emms_c(); + + avctx->draw_horiz_band(avctx, src, offset, + y, picture_structure, h); + } +} diff --git a/libavcodec/mpegutils.h b/libavcodec/mpegutils.h new file mode 100644 index 000000000..6d59c2242 --- /dev/null +++ b/libavcodec/mpegutils.h @@ -0,0 +1,127 @@ +/* + * Mpeg video formats-related defines and utility functions + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MPEGUTILS_H +#define AVCODEC_MPEGUTILS_H + +#include + +#include "libavutil/frame.h" + +#include "avcodec.h" +#include "version.h" + + +/* picture type */ +#define PICT_TOP_FIELD 1 +#define PICT_BOTTOM_FIELD 2 +#define PICT_FRAME 3 + +/** + * Value of Picture.reference when Picture is not a reference picture, but + * is held for delayed output. + */ +#define DELAYED_PIC_REF 4 + + +/* MB types */ +#if !FF_API_MB_TYPE +#define MB_TYPE_INTRA4x4 (1 << 0) +#define MB_TYPE_INTRA16x16 (1 << 1) // FIXME H.264-specific +#define MB_TYPE_INTRA_PCM (1 << 2) // FIXME H.264-specific +#define MB_TYPE_16x16 (1 << 3) +#define MB_TYPE_16x8 (1 << 4) +#define MB_TYPE_8x16 (1 << 5) +#define MB_TYPE_8x8 (1 << 6) +#define MB_TYPE_INTERLACED (1 << 7) +#define MB_TYPE_DIRECT2 (1 << 8) // FIXME +#define MB_TYPE_ACPRED (1 << 9) +#define MB_TYPE_GMC (1 << 10) +#define MB_TYPE_SKIP (1 << 11) +#define MB_TYPE_P0L0 (1 << 12) +#define MB_TYPE_P1L0 (1 << 13) +#define MB_TYPE_P0L1 (1 << 14) +#define MB_TYPE_P1L1 (1 << 15) +#define MB_TYPE_L0 (MB_TYPE_P0L0 | MB_TYPE_P1L0) +#define MB_TYPE_L1 (MB_TYPE_P0L1 | MB_TYPE_P1L1) +#define MB_TYPE_L0L1 (MB_TYPE_L0 | MB_TYPE_L1) +#define MB_TYPE_QUANT (1 << 16) +#define MB_TYPE_CBP (1 << 17) +#endif + +#define MB_TYPE_INTRA MB_TYPE_INTRA4x4 // default mb_type if there is just one type + +#define IS_INTRA4x4(a) ((a) & MB_TYPE_INTRA4x4) +#define IS_INTRA16x16(a) ((a) & MB_TYPE_INTRA16x16) +#define IS_PCM(a) ((a) & MB_TYPE_INTRA_PCM) +#define IS_INTRA(a) ((a) & 7) +#define IS_INTER(a) ((a) & (MB_TYPE_16x16 | MB_TYPE_16x8 | \ + MB_TYPE_8x16 | MB_TYPE_8x8)) +#define IS_SKIP(a) ((a) & MB_TYPE_SKIP) +#define IS_INTRA_PCM(a) ((a) & MB_TYPE_INTRA_PCM) +#define IS_INTERLACED(a) ((a) & MB_TYPE_INTERLACED) +#define IS_DIRECT(a) ((a) & MB_TYPE_DIRECT2) +#define IS_GMC(a) ((a) & MB_TYPE_GMC) +#define IS_16X16(a) ((a) & MB_TYPE_16x16) +#define IS_16X8(a) ((a) & MB_TYPE_16x8) +#define IS_8X16(a) ((a) & MB_TYPE_8x16) +#define IS_8X8(a) ((a) & MB_TYPE_8x8) +#define IS_SUB_8X8(a) ((a) & MB_TYPE_16x16) // note reused +#define IS_SUB_8X4(a) ((a) & MB_TYPE_16x8) // note reused +#define IS_SUB_4X8(a) ((a) & MB_TYPE_8x16) // note reused +#define IS_SUB_4X4(a) ((a) & MB_TYPE_8x8) // note reused +#define IS_ACPRED(a) ((a) & MB_TYPE_ACPRED) +#define IS_QUANT(a) ((a) & MB_TYPE_QUANT) +#define IS_DIR(a, part, list) ((a) & (MB_TYPE_P0L0 << ((part) + 2 * (list)))) + +// does this mb use listX, note does not work if subMBs +#define USES_LIST(a, list) ((a) & ((MB_TYPE_P0L0 | MB_TYPE_P1L0) << (2 * (list)))) + +#define HAS_CBP(a) ((a) & MB_TYPE_CBP) + +/* MB types for encoding */ +#define CANDIDATE_MB_TYPE_INTRA (1 << 0) +#define CANDIDATE_MB_TYPE_INTER (1 << 1) +#define CANDIDATE_MB_TYPE_INTER4V (1 << 2) +#define CANDIDATE_MB_TYPE_SKIPPED (1 << 3) + +#define CANDIDATE_MB_TYPE_DIRECT (1 << 4) +#define CANDIDATE_MB_TYPE_FORWARD (1 << 5) +#define CANDIDATE_MB_TYPE_BACKWARD (1 << 6) +#define CANDIDATE_MB_TYPE_BIDIR (1 << 7) + +#define CANDIDATE_MB_TYPE_INTER_I (1 << 8) +#define CANDIDATE_MB_TYPE_FORWARD_I (1 << 9) +#define CANDIDATE_MB_TYPE_BACKWARD_I (1 << 10) +#define CANDIDATE_MB_TYPE_BIDIR_I (1 << 11) + +#define CANDIDATE_MB_TYPE_DIRECT0 (1 << 12) + + +/** + * Draw a horizontal band if supported. + * + * @param h is the normal height, this will be reduced automatically if needed + */ +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 */ diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 4dc41e83d..a9024a978 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -33,13 +33,16 @@ #include "libavutil/internal.h" #include "libavutil/timer.h" #include "avcodec.h" -#include "dsputil.h" +#include "blockdsp.h" #include "h264chroma.h" +#include "idctdsp.h" #include "internal.h" #include "mathops.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "mjpegenc.h" #include "msmpeg4.h" +#include "qpeldsp.h" #include "thread.h" #include @@ -104,9 +107,26 @@ const uint8_t *const ff_mpeg2_dc_scale_table[4] = { mpeg2_dc_scale_table3, }; -const enum AVPixelFormat ff_pixfmt_list_420[] = { - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_NONE +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, @@ -333,25 +353,53 @@ static void mpeg_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type, ff_init_block_index(s); ff_update_block_index(s); - s->dsp.clear_blocks(s->block[0]); + 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); + 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); } +static void gray16(uint8_t *dst, const uint8_t *src, ptrdiff_t linesize, int h) +{ + while(h--) + memset(dst + h*linesize, 128, 16); +} + +static void gray8(uint8_t *dst, const uint8_t *src, ptrdiff_t linesize, int h) +{ + while(h--) + memset(dst + h*linesize, 128, 8); +} + /* init common dct for both encoder and decoder */ av_cold int ff_dct_common_init(MpegEncContext *s) { + ff_blockdsp_init(&s->bdsp, s->avctx); ff_dsputil_init(&s->dsp, s->avctx); ff_h264chroma_init(&s->h264chroma, 8); //for lowres ff_hpeldsp_init(&s->hdsp, s->avctx->flags); + ff_idctdsp_init(&s->idsp, s->avctx); + ff_mpegvideodsp_init(&s->mdsp); ff_videodsp_init(&s->vdsp, s->avctx->bits_per_raw_sample); + if (s->avctx->debug & FF_DEBUG_NOMC) { + int i; + for (i=0; i<4; i++) { + s->hdsp.avg_pixels_tab[0][i] = gray16; + s->hdsp.put_pixels_tab[0][i] = gray16; + s->hdsp.put_no_rnd_pixels_tab[0][i] = gray16; + + s->hdsp.avg_pixels_tab[1][i] = gray8; + s->hdsp.put_pixels_tab[1][i] = gray8; + s->hdsp.put_no_rnd_pixels_tab[1][i] = gray8; + } + } + s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_c; s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_c; s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_c; @@ -374,14 +422,14 @@ av_cold int ff_dct_common_init(MpegEncContext *s) * note: only wmv uses different ones */ if (s->alternate_scan) { - ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , ff_alternate_vertical_scan); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_alternate_vertical_scan); } else { - ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , ff_zigzag_direct); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , ff_zigzag_direct); + ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_zigzag_direct); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); } - ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); return 0; } @@ -390,12 +438,21 @@ static int frame_size_alloc(MpegEncContext *s, int linesize) { int alloc_size = FFALIGN(FFABS(linesize) + 64, 32); + if (s->avctx->hwaccel || s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) + return 0; + + if (linesize < 24) { + av_log(s->avctx, AV_LOG_ERROR, "Image too small, temporary buffers cannot function\n"); + return AVERROR_PATCHWELCOME; + } + // edge emu needs blocksize + filter length - 1 // (= 17x17 for halfpel / 21x21 for h264) // VC1 computes luma and chroma simultaneously and needs 19X19 + 9x9 // at uvlinesize. It supports only YUV420 so 24x24 is enough // linesize * interlaced * MBsize - FF_ALLOCZ_OR_GOTO(s->avctx, s->edge_emu_buffer, alloc_size * 4 * 24, + // we also use this buffer for encoding in encode_mb_internal() needig an additional 32 lines + FF_ALLOCZ_OR_GOTO(s->avctx, s->edge_emu_buffer, alloc_size * 4 * 68, fail); FF_ALLOCZ_OR_GOTO(s->avctx, s->me.scratchpad, alloc_size * 4 * 16 * 2, @@ -419,46 +476,46 @@ 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; + 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; + 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); + 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]) { + 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]); + r, pic->f->data[0]); return -1; } if (edges_needed) { int i; - for (i = 0; pic->f.data[i]; i++) { + for (i = 0; pic->f->data[i]; i++) { int offset = (EDGE_WIDTH >> (i ? s->chroma_y_shift : 0)) * - pic->f.linesize[i] + + pic->f->linesize[i] + (EDGE_WIDTH >> (i ? s->chroma_x_shift : 0)); - pic->f.data[i] += offset; + pic->f->data[i] += offset; } - pic->f.width = s->avctx->width; - pic->f.height = s->avctx->height; + 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->priv_data_size) { - pic->hwaccel_priv_buf = av_buffer_allocz(s->avctx->hwaccel->priv_data_size); + 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; @@ -467,15 +524,15 @@ static int alloc_frame_buffer(MpegEncContext *s, Picture *pic) } } - if (s->linesize && (s->linesize != pic->f.linesize[0] || - s->uvlinesize != pic->f.linesize[1])) { + 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]) { + 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); @@ -483,7 +540,7 @@ static int alloc_frame_buffer(MpegEncContext *s, Picture *pic) } if (!s->edge_emu_buffer && - (ret = frame_size_alloc(s, pic->f.linesize[0])) < 0) { + (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); @@ -593,16 +650,16 @@ int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared) ff_free_picture_tables(pic); if (shared) { - av_assert0(pic->f.data[0]); + av_assert0(pic->f->data[0]); pic->shared = 1; } else { - av_assert0(!pic->f.buf[0]); + av_assert0(!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]; + s->linesize = pic->f->linesize[0]; + s->uvlinesize = pic->f->linesize[1]; } if (!pic->qscale_table_buf) @@ -644,15 +701,15 @@ void ff_mpeg_unref_picture(MpegEncContext *s, Picture *pic) { int off = offsetof(Picture, mb_mean) + sizeof(pic->mb_mean); - pic->tf.f = &pic->f; + pic->tf.f = pic->f; /* WM Image / Screen codecs allocate internal buffers with different * dimensions / colorspaces; ignore user-defined callbacks for these. */ if (s->codec_id != AV_CODEC_ID_WMV3IMAGE && s->codec_id != AV_CODEC_ID_VC1IMAGE && s->codec_id != AV_CODEC_ID_MSS2) ff_thread_release_buffer(s->avctx, &pic->tf); - else - av_frame_unref(&pic->f); + else if (pic->f) + av_frame_unref(pic->f); av_buffer_unref(&pic->hwaccel_priv_buf); @@ -711,11 +768,11 @@ 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]); + 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; @@ -927,7 +984,7 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, if(s->picture) for (i = 0; i < MAX_PICTURE_COUNT; i++) { ff_mpeg_unref_picture(s, &s->picture[i]); - if (s1->picture[i].f.buf[0] && + if (s1->picture[i].f->buf[0] && (ret = ff_mpeg_ref_picture(s, &s->picture[i], &s1->picture[i])) < 0) return ret; } @@ -935,7 +992,7 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, #define UPDATE_PICTURE(pic)\ do {\ ff_mpeg_unref_picture(s, &s->pic);\ - if (s1->pic.f.buf[0])\ + if (s1->pic.f && s1->pic.f->buf[0])\ ret = ff_mpeg_ref_picture(s, &s->pic, &s1->pic);\ else\ ret = update_picture_tables(&s->pic, &s1->pic);\ @@ -1002,7 +1059,7 @@ do {\ if (!s1->first_field) { s->last_pict_type = s1->pict_type; if (s1->current_picture_ptr) - s->last_lambda_for[s1->pict_type] = s1->current_picture_ptr->f.quality; + s->last_lambda_for[s1->pict_type] = s1->current_picture_ptr->f->quality; } return 0; @@ -1089,11 +1146,10 @@ static int init_context_frame(MpegEncContext *s) s->mb_width = (s->width + 15) / 16; s->mb_stride = s->mb_width + 1; s->b8_stride = s->mb_width * 2 + 1; - s->b4_stride = s->mb_width * 4 + 1; mb_array_size = s->mb_height * s->mb_stride; mv_table_size = (s->mb_height + 2) * s->mb_stride + 1; - /* set default edge pos, will be overriden + /* 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; @@ -1261,14 +1317,26 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) FF_ALLOCZ_OR_GOTO(s->avctx, s->picture, MAX_PICTURE_COUNT * sizeof(Picture), fail); for (i = 0; i < MAX_PICTURE_COUNT; i++) { - av_frame_unref(&s->picture[i].f); + s->picture[i].f = av_frame_alloc(); + if (!s->picture[i].f) + goto fail; } memset(&s->next_picture, 0, sizeof(s->next_picture)); memset(&s->last_picture, 0, sizeof(s->last_picture)); memset(&s->current_picture, 0, sizeof(s->current_picture)); - av_frame_unref(&s->next_picture.f); - av_frame_unref(&s->last_picture.f); - av_frame_unref(&s->current_picture.f); + memset(&s->new_picture, 0, sizeof(s->new_picture)); + s->next_picture.f = av_frame_alloc(); + if (!s->next_picture.f) + goto fail; + s->last_picture.f = av_frame_alloc(); + if (!s->last_picture.f) + goto fail; + s->current_picture.f = av_frame_alloc(); + if (!s->current_picture.f) + goto fail; + s->new_picture.f = av_frame_alloc(); + if (!s->new_picture.f) + goto fail; if (init_context_frame(s)) goto fail; @@ -1462,15 +1530,22 @@ void ff_MPV_common_end(MpegEncContext *s) for (i = 0; i < MAX_PICTURE_COUNT; i++) { ff_free_picture_tables(&s->picture[i]); ff_mpeg_unref_picture(s, &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); + av_frame_free(&s->last_picture.f); ff_free_picture_tables(&s->current_picture); ff_mpeg_unref_picture(s, &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); + av_frame_free(&s->next_picture.f); + ff_free_picture_tables(&s->new_picture); + ff_mpeg_unref_picture(s, &s->new_picture); + av_frame_free(&s->new_picture.f); free_context_frame(s); @@ -1588,7 +1663,7 @@ static inline int pic_is_unused(MpegEncContext *s, Picture *pic) { if (pic == s->last_picture_ptr) return 0; - if (pic->f.buf[0] == NULL) + if (pic->f->buf[0] == NULL) return 1; if (pic->needs_realloc && !(pic->reference & DELAYED_PIC_REF)) return 1; @@ -1601,7 +1676,7 @@ static int find_unused_picture(MpegEncContext *s, int shared) if (shared) { for (i = 0; i < MAX_PICTURE_COUNT; i++) { - if (s->picture[i].f.buf[0] == NULL && &s->picture[i] != s->last_picture_ptr) + if (s->picture[i].f->buf[0] == NULL && &s->picture[i] != s->last_picture_ptr) return i; } } else { @@ -1642,6 +1717,22 @@ int ff_find_unused_picture(MpegEncContext *s, int shared) return ret; } +static void gray_frame(AVFrame *frame) +{ + int i, h_chroma_shift, v_chroma_shift; + + av_pix_fmt_get_chroma_sub_sample(frame->format, &h_chroma_shift, &v_chroma_shift); + + for(i=0; iheight; i++) + memset(frame->data[0] + frame->linesize[0]*i, 0x80, frame->width); + for(i=0; iheight, v_chroma_shift); i++) { + memset(frame->data[1] + frame->linesize[1]*i, + 0x80, FF_CEIL_RSHIFT(frame->width, h_chroma_shift)); + memset(frame->data[2] + frame->linesize[2]*i, + 0x80, FF_CEIL_RSHIFT(frame->width, h_chroma_shift)); + } +} + /** * generic function called after decoding * the header and before a frame is decoded. @@ -1660,7 +1751,7 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) /* mark & release old frames */ if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && s->last_picture_ptr != s->next_picture_ptr && - s->last_picture_ptr->f.buf[0]) { + s->last_picture_ptr->f->buf[0]) { ff_mpeg_unref_picture(s, s->last_picture_ptr); } @@ -1682,7 +1773,7 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) release_unused_pictures(s); if (s->current_picture_ptr && - s->current_picture_ptr->f.buf[0] == NULL) { + s->current_picture_ptr->f->buf[0] == NULL) { // we already have a unused image // (maybe it was set before reading the header) pic = s->current_picture_ptr; @@ -1701,28 +1792,28 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) pic->reference = 3; } - pic->f.coded_picture_number = s->coded_picture_number++; + pic->f->coded_picture_number = s->coded_picture_number++; if (ff_alloc_picture(s, pic, 0) < 0) return -1; s->current_picture_ptr = pic; // FIXME use only the vars from current_pic - s->current_picture_ptr->f.top_field_first = s->top_field_first; + s->current_picture_ptr->f->top_field_first = s->top_field_first; if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { if (s->picture_structure != PICT_FRAME) - s->current_picture_ptr->f.top_field_first = + s->current_picture_ptr->f->top_field_first = (s->picture_structure == PICT_TOP_FIELD) == s->first_field; } - s->current_picture_ptr->f.interlaced_frame = !s->progressive_frame && + s->current_picture_ptr->f->interlaced_frame = !s->progressive_frame && !s->progressive_sequence; s->current_picture_ptr->field_picture = s->picture_structure != PICT_FRAME; - s->current_picture_ptr->f.pict_type = s->pict_type; + s->current_picture_ptr->f->pict_type = s->pict_type; // if (s->flags && CODEC_FLAG_QSCALE) // s->current_picture_ptr->quality = s->new_picture_ptr->quality; - s->current_picture_ptr->f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; + s->current_picture_ptr->f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; if ((ret = ff_mpeg_ref_picture(s, &s->current_picture, s->current_picture_ptr)) < 0) @@ -1735,19 +1826,19 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) } av_dlog(s->avctx, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr, - s->last_picture_ptr ? s->last_picture_ptr->f.data[0] : NULL, - s->next_picture_ptr ? s->next_picture_ptr->f.data[0] : NULL, - s->current_picture_ptr ? s->current_picture_ptr->f.data[0] : NULL, + s->last_picture_ptr ? s->last_picture_ptr->f->data[0] : NULL, + s->next_picture_ptr ? s->next_picture_ptr->f->data[0] : NULL, + s->current_picture_ptr ? s->current_picture_ptr->f->data[0] : NULL, s->pict_type, s->droppable); if ((s->last_picture_ptr == NULL || - s->last_picture_ptr->f.buf[0] == NULL) && + s->last_picture_ptr->f->buf[0] == NULL) && (s->pict_type != AV_PICTURE_TYPE_I || s->picture_structure != PICT_FRAME)) { int h_chroma_shift, v_chroma_shift; av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift); - if (s->pict_type == AV_PICTURE_TYPE_B && s->next_picture_ptr && s->next_picture_ptr->f.buf[0]) + if (s->pict_type == AV_PICTURE_TYPE_B && s->next_picture_ptr && s->next_picture_ptr->f->buf[0]) av_log(avctx, AV_LOG_DEBUG, "allocating dummy last picture for B frame\n"); else if (s->pict_type != AV_PICTURE_TYPE_I) @@ -1766,8 +1857,8 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) s->last_picture_ptr = &s->picture[i]; s->last_picture_ptr->reference = 3; - s->last_picture_ptr->f.key_frame = 0; - s->last_picture_ptr->f.pict_type = AV_PICTURE_TYPE_P; + s->last_picture_ptr->f->key_frame = 0; + s->last_picture_ptr->f->pict_type = AV_PICTURE_TYPE_P; if (ff_alloc_picture(s, s->last_picture_ptr, 0) < 0) { s->last_picture_ptr = NULL; @@ -1776,18 +1867,18 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) if (!avctx->hwaccel && !(avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)) { for(i=0; iheight; i++) - memset(s->last_picture_ptr->f.data[0] + s->last_picture_ptr->f.linesize[0]*i, + memset(s->last_picture_ptr->f->data[0] + s->last_picture_ptr->f->linesize[0]*i, 0x80, avctx->width); for(i=0; iheight, v_chroma_shift); i++) { - memset(s->last_picture_ptr->f.data[1] + s->last_picture_ptr->f.linesize[1]*i, + memset(s->last_picture_ptr->f->data[1] + s->last_picture_ptr->f->linesize[1]*i, 0x80, FF_CEIL_RSHIFT(avctx->width, h_chroma_shift)); - memset(s->last_picture_ptr->f.data[2] + s->last_picture_ptr->f.linesize[2]*i, + memset(s->last_picture_ptr->f->data[2] + s->last_picture_ptr->f->linesize[2]*i, 0x80, FF_CEIL_RSHIFT(avctx->width, h_chroma_shift)); } if(s->codec_id == AV_CODEC_ID_FLV1 || s->codec_id == AV_CODEC_ID_H263){ for(i=0; iheight; i++) - memset(s->last_picture_ptr->f.data[0] + s->last_picture_ptr->f.linesize[0]*i, 16, avctx->width); + memset(s->last_picture_ptr->f->data[0] + s->last_picture_ptr->f->linesize[0]*i, 16, avctx->width); } } @@ -1795,7 +1886,7 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 1); } if ((s->next_picture_ptr == NULL || - s->next_picture_ptr->f.buf[0] == NULL) && + s->next_picture_ptr->f->buf[0] == NULL) && s->pict_type == AV_PICTURE_TYPE_B) { /* Allocate a dummy frame */ i = ff_find_unused_picture(s, 0); @@ -1806,8 +1897,8 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) s->next_picture_ptr = &s->picture[i]; s->next_picture_ptr->reference = 3; - s->next_picture_ptr->f.key_frame = 0; - s->next_picture_ptr->f.pict_type = AV_PICTURE_TYPE_P; + s->next_picture_ptr->f->key_frame = 0; + s->next_picture_ptr->f->pict_type = AV_PICTURE_TYPE_P; if (ff_alloc_picture(s, s->next_picture_ptr, 0) < 0) { s->next_picture_ptr = NULL; @@ -1818,37 +1909,37 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) } #if 0 // BUFREF-FIXME - memset(s->last_picture.f.data, 0, sizeof(s->last_picture.f.data)); - memset(s->next_picture.f.data, 0, sizeof(s->next_picture.f.data)); + memset(s->last_picture.f->data, 0, sizeof(s->last_picture.f->data)); + memset(s->next_picture.f->data, 0, sizeof(s->next_picture.f->data)); #endif if (s->last_picture_ptr) { ff_mpeg_unref_picture(s, &s->last_picture); - if (s->last_picture_ptr->f.buf[0] && + if (s->last_picture_ptr->f->buf[0] && (ret = ff_mpeg_ref_picture(s, &s->last_picture, s->last_picture_ptr)) < 0) return ret; } if (s->next_picture_ptr) { ff_mpeg_unref_picture(s, &s->next_picture); - if (s->next_picture_ptr->f.buf[0] && + if (s->next_picture_ptr->f->buf[0] && (ret = ff_mpeg_ref_picture(s, &s->next_picture, s->next_picture_ptr)) < 0) return ret; } av_assert0(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr && - s->last_picture_ptr->f.buf[0])); + s->last_picture_ptr->f->buf[0])); if (s->picture_structure!= PICT_FRAME) { int i; for (i = 0; i < 4; i++) { if (s->picture_structure == PICT_BOTTOM_FIELD) { - s->current_picture.f.data[i] += - s->current_picture.f.linesize[i]; + s->current_picture.f->data[i] += + s->current_picture.f->linesize[i]; } - s->current_picture.f.linesize[i] *= 2; - s->last_picture.f.linesize[i] *= 2; - s->next_picture.f.linesize[i] *= 2; + s->current_picture.f->linesize[i] *= 2; + s->last_picture.f->linesize[i] *= 2; + s->next_picture.f->linesize[i] *= 2; } } @@ -1868,6 +1959,10 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) s->dct_unquantize_inter = s->dct_unquantize_mpeg1_inter; } + if (s->avctx->debug & FF_DEBUG_NOMC) { + gray_frame(s->current_picture_ptr->f); + } + return 0; } @@ -1880,6 +1975,29 @@ void ff_MPV_frame_end(MpegEncContext *s) ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); } + +static int clip_line(int *sx, int *sy, int *ex, int *ey, int maxx) +{ + if(*sx > *ex) + return clip_line(ex, ey, sx, sy, maxx); + + if (*sx < 0) { + if (*ex < 0) + return 1; + *sy = *ey + (*sy - *ey) * (int64_t)*ex / (*ex - *sx); + *sx = 0; + } + + if (*ex > maxx) { + if (*sx > maxx) + return 1; + *ey = *sy + (*ey - *sy) * (int64_t)(maxx - *sx) / (*ex - *sx); + *ex = maxx; + } + return 0; +} + + /** * Draw a line from (ex, ey) -> (sx, sy). * @param w width of the image @@ -1892,6 +2010,11 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, { int x, y, fr, f; + if (clip_line(&sx, &sy, &ex, &ey, w - 1)) + return; + if (clip_line(&sy, &sx, &ey, &ex, h - 1)) + return; + sx = av_clip(sx, 0, w - 1); sy = av_clip(sy, 0, h - 1); ex = av_clip(ex, 0, w - 1); @@ -1941,10 +2064,15 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, * @param color color of the arrow */ static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, - int ey, int w, int h, int stride, int color) + int ey, int w, int h, int stride, int color, int tail, int direction) { int dx,dy; + if (direction) { + FFSWAP(int, sx, ex); + FFSWAP(int, sy, ey); + } + sx = av_clip(sx, -100, w + 100); sy = av_clip(sy, -100, h + 100); ex = av_clip(ex, -100, w + 100); @@ -1962,6 +2090,11 @@ static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, rx = ROUNDED_DIV(rx * 3 << 4, length); ry = ROUNDED_DIV(ry * 3 << 4, length); + if (tail) { + rx = -rx; + ry = -ry; + } + draw_line(buf, sx, sy, sx + rx, sy + ry, w, h, stride, color); draw_line(buf, sx, sy, sx - ry, sy + rx, w, h, stride, color); } @@ -1971,11 +2104,12 @@ static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, /** * Print debugging info for the given picture. */ -void ff_print_debug_info2(AVCodecContext *avctx, Picture *p, AVFrame *pict, uint8_t *mbskip_table, +void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_table, + uint32_t *mbtype_table, int8_t *qscale_table, int16_t (*motion_val[2])[2], int *low_delay, int mb_width, int mb_height, int mb_stride, int quarter_sample) { - if (avctx->hwaccel || !p || !p->mb_type + if (avctx->hwaccel || !mbtype_table || (avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)) return; @@ -1995,10 +2129,10 @@ void ff_print_debug_info2(AVCodecContext *avctx, Picture *p, AVFrame *pict, uint } if (avctx->debug & FF_DEBUG_QP) { av_log(avctx, AV_LOG_DEBUG, "%2d", - p->qscale_table[x + y * mb_stride]); + qscale_table[x + y * mb_stride]); } if (avctx->debug & FF_DEBUG_MB_TYPE) { - int mb_type = p->mb_type[x + y * mb_stride]; + int mb_type = mbtype_table[x + y * mb_stride]; // Type & MV direction if (IS_PCM(mb_type)) av_log(avctx, AV_LOG_DEBUG, "P"); @@ -2077,7 +2211,7 @@ void ff_print_debug_info2(AVCodecContext *avctx, Picture *p, AVFrame *pict, uint int mb_x; for (mb_x = 0; mb_x < mb_width; mb_x++) { const int mb_index = mb_x + mb_y * mb_stride; - if ((avctx->debug_mv) && p->motion_val[0]) { + if ((avctx->debug_mv) && motion_val[0]) { int type; for (type = 0; type < 3; type++) { int direction = 0; @@ -2101,63 +2235,63 @@ void ff_print_debug_info2(AVCodecContext *avctx, Picture *p, AVFrame *pict, uint direction = 1; break; } - if (!USES_LIST(p->mb_type[mb_index], direction)) + if (!USES_LIST(mbtype_table[mb_index], direction)) continue; - if (IS_8X8(p->mb_type[mb_index])) { + if (IS_8X8(mbtype_table[mb_index])) { int i; for (i = 0; i < 4; i++) { int sx = mb_x * 16 + 4 + 8 * (i & 1); int sy = mb_y * 16 + 4 + 8 * (i >> 1); int xy = (mb_x * 2 + (i & 1) + (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); - int mx = (p->motion_val[direction][xy][0] >> shift) + sx; - int my = (p->motion_val[direction][xy][1] >> shift) + sy; + int mx = (motion_val[direction][xy][0] >> shift) + sx; + int my = (motion_val[direction][xy][1] >> shift) + sy; draw_arrow(ptr, sx, sy, mx, my, width, - height, pict->linesize[0], 100); + height, pict->linesize[0], 100, 0, direction); } - } else if (IS_16X8(p->mb_type[mb_index])) { + } else if (IS_16X8(mbtype_table[mb_index])) { int i; for (i = 0; i < 2; i++) { int sx = mb_x * 16 + 8; int sy = mb_y * 16 + 4 + 8 * i; int xy = (mb_x * 2 + (mb_y * 2 + i) * mv_stride) << (mv_sample_log2 - 1); - int mx = (p->motion_val[direction][xy][0] >> shift); - int my = (p->motion_val[direction][xy][1] >> shift); + int mx = (motion_val[direction][xy][0] >> shift); + int my = (motion_val[direction][xy][1] >> shift); - if (IS_INTERLACED(p->mb_type[mb_index])) + if (IS_INTERLACED(mbtype_table[mb_index])) my *= 2; - draw_arrow(ptr, sx, sy, mx + sx, my + sy, width, - height, pict->linesize[0], 100); + draw_arrow(ptr, sx, sy, mx + sx, my + sy, width, + height, pict->linesize[0], 100, 0, direction); } - } else if (IS_8X16(p->mb_type[mb_index])) { + } else if (IS_8X16(mbtype_table[mb_index])) { int i; for (i = 0; i < 2; i++) { int sx = mb_x * 16 + 4 + 8 * i; int sy = mb_y * 16 + 8; int xy = (mb_x * 2 + i + mb_y * 2 * mv_stride) << (mv_sample_log2 - 1); - int mx = p->motion_val[direction][xy][0] >> shift; - int my = p->motion_val[direction][xy][1] >> shift; + int mx = motion_val[direction][xy][0] >> shift; + int my = motion_val[direction][xy][1] >> shift; - if (IS_INTERLACED(p->mb_type[mb_index])) + if (IS_INTERLACED(mbtype_table[mb_index])) my *= 2; draw_arrow(ptr, sx, sy, mx + sx, my + sy, width, - height, pict->linesize[0], 100); + height, pict->linesize[0], 100, 0, direction); } } else { int sx= mb_x * 16 + 8; int sy= mb_y * 16 + 8; int xy= (mb_x + mb_y * mv_stride) << mv_sample_log2; - int mx= (p->motion_val[direction][xy][0]>>shift) + sx; - int my= (p->motion_val[direction][xy][1]>>shift) + sy; - draw_arrow(ptr, sx, sy, mx, my, width, height, pict->linesize[0], 100); + int mx= (motion_val[direction][xy][0]>>shift) + sx; + int my= (motion_val[direction][xy][1]>>shift) + sy; + draw_arrow(ptr, sx, sy, mx, my, width, height, pict->linesize[0], 100, 0, direction); } } } if ((avctx->debug & FF_DEBUG_VIS_QP)) { - uint64_t c = (p->qscale_table[mb_index] * 128 / 31) * + uint64_t c = (qscale_table[mb_index] * 128 / 31) * 0x0101010101010101ULL; int y; for (y = 0; y < block_height; y++) { @@ -2170,8 +2304,8 @@ void ff_print_debug_info2(AVCodecContext *avctx, Picture *p, AVFrame *pict, uint } } if ((avctx->debug & FF_DEBUG_VIS_MB_TYPE) && - p->motion_val[0]) { - int mb_type = p->mb_type[mb_index]; + motion_val[0]) { + int mb_type = mbtype_table[mb_index]; uint64_t u,v; int y; #define COLOR(theta, r) \ @@ -2235,7 +2369,7 @@ void ff_print_debug_info2(AVCodecContext *avctx, Picture *p, AVFrame *pict, uint int xy = (mb_x * 2 + (i & 1) + (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); // FIXME bidir - int32_t *mv = (int32_t *) &p->motion_val[0][xy]; + int32_t *mv = (int32_t *) &motion_val[0][xy]; if (mv[0] != mv[dm] || mv[dm * mv_stride] != mv[dm * (mv_stride + 1)]) for (y = 0; y < 8; y++) @@ -2259,7 +2393,8 @@ void ff_print_debug_info2(AVCodecContext *avctx, Picture *p, AVFrame *pict, uint void ff_print_debug_info(MpegEncContext *s, Picture *p, AVFrame *pict) { - ff_print_debug_info2(s->avctx, p, pict, s->mbskip_table, &s->low_delay, + ff_print_debug_info2(s->avctx, pict, s->mbskip_table, p->mb_type, + p->qscale_table, p->motion_val, &s->low_delay, s->mb_width, s->mb_height, s->mb_stride, s->quarter_sample); } @@ -2343,8 +2478,8 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s, const int s_mask = (2 << lowres) - 1; const int h_edge_pos = s->h_edge_pos >> lowres; const int v_edge_pos = s->v_edge_pos >> lowres; - linesize = s->current_picture.f.linesize[0] << field_based; - uvlinesize = s->current_picture.f.linesize[1] << field_based; + linesize = s->current_picture.f->linesize[0] << field_based; + uvlinesize = s->current_picture.f->linesize[1] << field_based; // FIXME obviously not perfect but qpel will not work in lowres anyway if (s->quarter_sample) { @@ -2413,23 +2548,24 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *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, + uint8_t *ubuf = s->edge_emu_buffer + 18 * s->linesize; + uint8_t *vbuf =ubuf + 9 * s->uvlinesize; + s->vdsp.emulated_edge_mc(ubuf, ptr_cb, uvlinesize >> field_based, uvlinesize >> field_based, 9, 9 + field_based, uvsrc_x, uvsrc_y << field_based, h_edge_pos >> 1, v_edge_pos >> 1); - s->vdsp.emulated_edge_mc(uvbuf + 16, ptr_cr, + s->vdsp.emulated_edge_mc(vbuf, ptr_cr, uvlinesize >> field_based,uvlinesize >> field_based, 9, 9 + field_based, uvsrc_x, uvsrc_y << field_based, h_edge_pos >> 1, v_edge_pos >> 1); - ptr_cb = uvbuf; - ptr_cr = uvbuf + 16; + ptr_cb = ubuf; + ptr_cr = vbuf; } } - // FIXME use this for field pix too instead of the obnoxious hack which changes picture.f.data + // FIXME use this for field pix too instead of the obnoxious hack which changes picture.f->data if (bottom_field) { dest_y += s->linesize; dest_cb += s->uvlinesize; @@ -2587,7 +2723,7 @@ static inline void MPV_motion_lowres(MpegEncContext *s, } else { if (s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != AV_PICTURE_TYPE_B && !s->first_field) { - ref_picture = s->current_picture_ptr->f.data; + ref_picture = s->current_picture_ptr->f->data; } mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, @@ -2605,7 +2741,7 @@ static inline void MPV_motion_lowres(MpegEncContext *s, s->pict_type == AV_PICTURE_TYPE_B || s->first_field) { ref2picture = ref_picture; } else { - ref2picture = s->current_picture_ptr->f.data; + ref2picture = s->current_picture_ptr->f->data; } mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, @@ -2647,7 +2783,7 @@ static inline void MPV_motion_lowres(MpegEncContext *s, // opposite parity is always in the same // frame if this is second field if (!s->first_field) { - ref_picture = s->current_picture_ptr->f.data; + ref_picture = s->current_picture_ptr->f->data; } } } @@ -2700,7 +2836,7 @@ static inline void put_dct(MpegEncContext *s, int16_t *block, int i, uint8_t *dest, int line_size, int qscale) { s->dct_unquantize_intra(s, block, i, qscale); - s->dsp.idct_put (dest, line_size, block); + s->idsp.idct_put(dest, line_size, block); } /* add block[] to dest[] */ @@ -2708,7 +2844,7 @@ static inline void add_dct(MpegEncContext *s, int16_t *block, int i, uint8_t *dest, int line_size) { if (s->block_last_index[i] >= 0) { - s->dsp.idct_add (dest, line_size, block); + s->idsp.idct_add(dest, line_size, block); } } @@ -2718,7 +2854,7 @@ static inline void add_dequant_dct(MpegEncContext *s, if (s->block_last_index[i] >= 0) { s->dct_unquantize_inter(s, block, i, qscale); - s->dsp.idct_add (dest, line_size, block); + s->idsp.idct_add(dest, line_size, block); } } @@ -2783,7 +2919,8 @@ void MPV_decode_mb_internal(MpegEncContext *s, int16_t block[12][64], av_log(s->avctx, AV_LOG_DEBUG, "DCT coeffs of MB at %dx%d:\n", s->mb_x, s->mb_y); for(i=0; i<6; i++){ for(j=0; j<64; j++){ - av_log(s->avctx, AV_LOG_DEBUG, "%5d", block[i][s->dsp.idct_permutation[j]]); + av_log(s->avctx, AV_LOG_DEBUG, "%5d", + block[i][s->idsp.idct_permutation[j]]); } av_log(s->avctx, AV_LOG_DEBUG, "\n"); } @@ -2812,8 +2949,8 @@ void MPV_decode_mb_internal(MpegEncContext *s, int16_t block[12][64], int dct_linesize, dct_offset; op_pixels_func (*op_pix)[4]; qpel_mc_func (*op_qpix)[16]; - const int linesize = s->current_picture.f.linesize[0]; //not s->linesize as this would be wrong for field pics - const int uvlinesize = s->current_picture.f.linesize[1]; + const int linesize = s->current_picture.f->linesize[0]; //not s->linesize as this would be wrong for field pics + const int uvlinesize = s->current_picture.f->linesize[1]; const int readable= s->pict_type != AV_PICTURE_TYPE_B || s->encoding || s->avctx->draw_horiz_band || lowres_flag; const int block_size= lowres_flag ? 8>>s->avctx->lowres : 8; @@ -2868,11 +3005,11 @@ void MPV_decode_mb_internal(MpegEncContext *s, int16_t block[12][64], h264_chroma_mc_func *op_pix = s->h264chroma.put_h264_chroma_pixels_tab; if (s->mv_dir & MV_DIR_FORWARD) { - MPV_motion_lowres(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f.data, op_pix); + MPV_motion_lowres(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f->data, op_pix); op_pix = s->h264chroma.avg_h264_chroma_pixels_tab; } if (s->mv_dir & MV_DIR_BACKWARD) { - MPV_motion_lowres(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f.data, op_pix); + MPV_motion_lowres(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f->data, op_pix); } }else{ op_qpix = s->me.qpel_put; @@ -2882,12 +3019,12 @@ void MPV_decode_mb_internal(MpegEncContext *s, int16_t block[12][64], op_pix = s->hdsp.put_no_rnd_pixels_tab; } if (s->mv_dir & MV_DIR_FORWARD) { - ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f.data, op_pix, op_qpix); + ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f->data, op_pix, op_qpix); op_pix = s->hdsp.avg_pixels_tab; op_qpix= s->me.qpel_avg; } if (s->mv_dir & MV_DIR_BACKWARD) { - ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f.data, op_pix, op_qpix); + ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f->data, op_pix, op_qpix); } } } @@ -2974,29 +3111,29 @@ void MPV_decode_mb_internal(MpegEncContext *s, int16_t block[12][64], } } }else{ - s->dsp.idct_put(dest_y , dct_linesize, block[0]); - s->dsp.idct_put(dest_y + block_size, dct_linesize, block[1]); - s->dsp.idct_put(dest_y + dct_offset , dct_linesize, block[2]); - s->dsp.idct_put(dest_y + dct_offset + block_size, dct_linesize, block[3]); + s->idsp.idct_put(dest_y, dct_linesize, block[0]); + s->idsp.idct_put(dest_y + block_size, dct_linesize, block[1]); + 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(s->chroma_y_shift){ - s->dsp.idct_put(dest_cb, uvlinesize, block[4]); - s->dsp.idct_put(dest_cr, uvlinesize, block[5]); + s->idsp.idct_put(dest_cb, uvlinesize, block[4]); + s->idsp.idct_put(dest_cr, uvlinesize, block[5]); }else{ dct_linesize = uvlinesize << s->interlaced_dct; dct_offset = s->interlaced_dct ? uvlinesize : uvlinesize*block_size; - s->dsp.idct_put(dest_cb, dct_linesize, block[4]); - s->dsp.idct_put(dest_cr, dct_linesize, block[5]); - s->dsp.idct_put(dest_cb + dct_offset, dct_linesize, block[6]); - s->dsp.idct_put(dest_cr + dct_offset, dct_linesize, block[7]); + s->idsp.idct_put(dest_cb, dct_linesize, block[4]); + s->idsp.idct_put(dest_cr, dct_linesize, block[5]); + s->idsp.idct_put(dest_cb + dct_offset, dct_linesize, block[6]); + s->idsp.idct_put(dest_cr + dct_offset, dct_linesize, block[7]); if(!s->chroma_x_shift){//Chroma444 - s->dsp.idct_put(dest_cb + block_size, dct_linesize, block[8]); - s->dsp.idct_put(dest_cr + block_size, dct_linesize, block[9]); - s->dsp.idct_put(dest_cb + block_size + dct_offset, dct_linesize, block[10]); - s->dsp.idct_put(dest_cr + block_size + dct_offset, dct_linesize, block[11]); + s->idsp.idct_put(dest_cb + block_size, dct_linesize, block[8]); + s->idsp.idct_put(dest_cr + block_size, dct_linesize, block[9]); + s->idsp.idct_put(dest_cb + block_size + dct_offset, dct_linesize, block[10]); + s->idsp.idct_put(dest_cr + block_size + dct_offset, dct_linesize, block[11]); } } }//gray @@ -3022,68 +3159,16 @@ void ff_MPV_decode_mb(MpegEncContext *s, int16_t block[12][64]){ else MPV_decode_mb_internal(s, block, 0, 0); } -/** - * @param h is the normal height, this will be reduced automatically if needed for the last row - */ -void ff_draw_horiz_band(AVCodecContext *avctx, Picture *cur, - Picture *last, int y, int h, int picture_structure, - int first_field, int low_delay) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); - int vshift = desc->log2_chroma_h; - const int field_pic = picture_structure != PICT_FRAME; - if(field_pic){ - h <<= 1; - y <<= 1; - } - - h = FFMIN(h, avctx->height - y); - - if(field_pic && first_field && !(avctx->slice_flags&SLICE_FLAG_ALLOW_FIELD)) return; - - if (avctx->draw_horiz_band) { - AVFrame *src; - int offset[AV_NUM_DATA_POINTERS]; - int i; - - if(cur->f.pict_type == AV_PICTURE_TYPE_B || low_delay || - (avctx->slice_flags & SLICE_FLAG_CODED_ORDER)) - src = &cur->f; - else if (last) - src = &last->f; - else - return; - - if (cur->f.pict_type == AV_PICTURE_TYPE_B && - picture_structure == PICT_FRAME && - avctx->codec_id != AV_CODEC_ID_SVQ3) { - for (i = 0; i < AV_NUM_DATA_POINTERS; i++) - offset[i] = 0; - }else{ - offset[0]= y * src->linesize[0]; - offset[1]= - offset[2]= (y >> vshift) * src->linesize[1]; - for (i = 3; i < AV_NUM_DATA_POINTERS; i++) - offset[i] = 0; - } - - emms_c(); - - avctx->draw_horiz_band(avctx, src, offset, - y, picture_structure, h); - } -} - void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h) { - ff_draw_horiz_band(s->avctx, s->current_picture_ptr, - s->last_picture_ptr, y, h, s->picture_structure, + ff_draw_horiz_band(s->avctx, s->current_picture_ptr->f, + s->last_picture_ptr ? s->last_picture_ptr->f : NULL, y, h, s->picture_structure, s->first_field, s->low_delay); } void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename - const int linesize = s->current_picture.f.linesize[0]; //not s->linesize as this would be wrong for field pics - const int uvlinesize = s->current_picture.f.linesize[1]; + const int linesize = s->current_picture.f->linesize[0]; //not s->linesize as this would be wrong for field pics + const int uvlinesize = s->current_picture.f->linesize[1]; const int mb_size= 4 - s->avctx->lowres; s->block_index[0]= s->b8_stride*(s->mb_y*2 ) - 2 + s->mb_x*2; @@ -3094,9 +3179,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) << mb_size); + s->dest[1] = s->current_picture.f->data[1] + ((s->mb_x - 1) << (mb_size - s->chroma_x_shift)); + s->dest[2] = s->current_picture.f->data[2] + ((s->mb_x - 1) << (mb_size - s->chroma_x_shift)); if(!(s->pict_type==AV_PICTURE_TYPE_B && s->avctx->draw_horiz_band && s->picture_structure==PICT_FRAME)) { @@ -3192,21 +3277,3 @@ void ff_MPV_report_decode_progress(MpegEncContext *s) if (s->pict_type != AV_PICTURE_TYPE_B && !s->partitioned_frame && !s->er.error_occurred) ff_thread_report_progress(&s->current_picture_ptr->tf, s->mb_y, 0); } - -#if CONFIG_ERROR_RESILIENCE -void ff_mpeg_er_frame_start(MpegEncContext *s) -{ - ERContext *er = &s->er; - - er->cur_pic = s->current_picture_ptr; - er->last_pic = s->last_picture_ptr; - er->next_pic = s->next_picture_ptr; - - er->pp_time = s->pp_time; - er->pb_time = s->pb_time; - er->quarter_sample = s->quarter_sample; - er->partitioned_frame = s->partitioned_frame; - - ff_er_frame_start(er); -} -#endif /* CONFIG_ERROR_RESILIENCE */ diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 0811e62af..94937e5cd 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -29,16 +29,23 @@ #define AVCODEC_MPEGVIDEO_H #include "avcodec.h" +#include "blockdsp.h" #include "dsputil.h" #include "error_resilience.h" +#include "fdctdsp.h" #include "get_bits.h" #include "h264chroma.h" #include "h263dsp.h" #include "hpeldsp.h" +#include "idctdsp.h" +#include "mpegvideodsp.h" +#include "mpegvideoencdsp.h" +#include "pixblockdsp.h" #include "put_bits.h" #include "ratecontrol.h" #include "parser.h" #include "mpeg12data.h" +#include "qpeldsp.h" #include "rl.h" #include "thread.h" #include "videodsp.h" @@ -76,6 +83,8 @@ enum OutputFormat { #define INPLACE_OFFSET 16 +#define EDGE_WIDTH 16 + /* Start codes. */ #define SEQ_END_CODE 0x000001b7 #define SEQ_START_CODE 0x000001b3 @@ -86,11 +95,9 @@ enum OutputFormat { #define EXT_START_CODE 0x000001b5 #define USER_START_CODE 0x000001b2 -/** - * Value of Picture.reference when Picture is not a reference picture, but - * is held for delayed output. - */ -#define DELAYED_PIC_REF 4 +/* encoding scans */ +extern const uint8_t ff_alternate_horizontal_scan[64]; +extern const uint8_t ff_alternate_vertical_scan[64]; struct MpegEncContext; @@ -98,8 +105,7 @@ struct MpegEncContext; * Picture. */ typedef struct Picture{ - struct AVFrame f; - uint8_t avframe_padding[1024]; // hack to allow linking to a avutil with larger AVFrame + struct AVFrame *f; ThreadFrame tf; AVBufferRef *qscale_table_buf; @@ -109,31 +115,7 @@ typedef struct Picture{ int16_t (*motion_val[2])[2]; AVBufferRef *mb_type_buf; - uint32_t *mb_type; - -#if !FF_API_MB_TYPE -#define MB_TYPE_INTRA4x4 0x0001 -#define MB_TYPE_INTRA16x16 0x0002 //FIXME H.264-specific -#define MB_TYPE_INTRA_PCM 0x0004 //FIXME H.264-specific -#define MB_TYPE_16x16 0x0008 -#define MB_TYPE_16x8 0x0010 -#define MB_TYPE_8x16 0x0020 -#define MB_TYPE_8x8 0x0040 -#define MB_TYPE_INTERLACED 0x0080 -#define MB_TYPE_DIRECT2 0x0100 //FIXME -#define MB_TYPE_ACPRED 0x0200 -#define MB_TYPE_GMC 0x0400 -#define MB_TYPE_SKIP 0x0800 -#define MB_TYPE_P0L0 0x1000 -#define MB_TYPE_P1L0 0x2000 -#define MB_TYPE_P0L1 0x4000 -#define MB_TYPE_P1L1 0x8000 -#define MB_TYPE_L0 (MB_TYPE_P0L0 | MB_TYPE_P1L0) -#define MB_TYPE_L1 (MB_TYPE_P0L1 | MB_TYPE_P1L1) -#define MB_TYPE_L0L1 (MB_TYPE_L0 | MB_TYPE_L1) -#define MB_TYPE_QUANT 0x00010000 -#define MB_TYPE_CBP 0x00020000 -#endif + uint32_t *mb_type; ///< types and macros are defined in mpegutils.h AVBufferRef *mbskip_table_buf; uint8_t *mbskip_table; @@ -159,41 +141,6 @@ typedef struct Picture{ */ void *hwaccel_picture_private; -#define MB_TYPE_INTRA MB_TYPE_INTRA4x4 //default mb_type if there is just one type -#define IS_INTRA4x4(a) ((a)&MB_TYPE_INTRA4x4) -#define IS_INTRA16x16(a) ((a)&MB_TYPE_INTRA16x16) -#define IS_PCM(a) ((a)&MB_TYPE_INTRA_PCM) -#define IS_INTRA(a) ((a)&7) -#define IS_INTER(a) ((a)&(MB_TYPE_16x16|MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_8x8)) -#define IS_SKIP(a) ((a)&MB_TYPE_SKIP) -#define IS_INTRA_PCM(a) ((a)&MB_TYPE_INTRA_PCM) -#define IS_INTERLACED(a) ((a)&MB_TYPE_INTERLACED) -#define IS_DIRECT(a) ((a)&MB_TYPE_DIRECT2) -#define IS_GMC(a) ((a)&MB_TYPE_GMC) -#define IS_16X16(a) ((a)&MB_TYPE_16x16) -#define IS_16X8(a) ((a)&MB_TYPE_16x8) -#define IS_8X16(a) ((a)&MB_TYPE_8x16) -#define IS_8X8(a) ((a)&MB_TYPE_8x8) -#define IS_SUB_8X8(a) ((a)&MB_TYPE_16x16) //note reused -#define IS_SUB_8X4(a) ((a)&MB_TYPE_16x8) //note reused -#define IS_SUB_4X8(a) ((a)&MB_TYPE_8x16) //note reused -#define IS_SUB_4X4(a) ((a)&MB_TYPE_8x8) //note reused -#define IS_ACPRED(a) ((a)&MB_TYPE_ACPRED) -#define IS_QUANT(a) ((a)&MB_TYPE_QUANT) -#define IS_DIR(a, part, list) ((a) & (MB_TYPE_P0L0<<((part)+2*(list)))) -#define USES_LIST(a, list) ((a) & ((MB_TYPE_P0L0|MB_TYPE_P1L0)<<(2*(list)))) ///< does this mb use listX, note does not work if subMBs -#define HAS_CBP(a) ((a)&MB_TYPE_CBP) - - int field_poc[2]; ///< h264 top/bottom POC - int poc; ///< h264 frame POC - int frame_num; ///< h264 frame_num (raw frame_num from slice header) - int mmco_reset; ///< h264 MMCO_RESET set this 1. Reordering code must not mix pictures before and after MMCO_RESET. - int pic_id; /**< h264 pic_num (short -> no wrap version of pic_num, - pic_num & max_pic_num; long -> long_pic_num) */ - int long_ref; ///< 1->long term reference 0->short term reference - int ref_poc[2][2][32]; ///< h264 POCs of the frames/fields used as reference (FIXME need per slice) - int ref_count[2][2]; ///< number of entries in ref_poc (FIXME need per slice) - int mbaff; ///< h264 1 -> MBAFF frame 0-> not MBAFF int field_picture; ///< whether or not the picture was encoded in separate fields int64_t mb_var_sum; ///< sum of MB variance for current frame @@ -204,12 +151,8 @@ typedef struct Picture{ int reference; int shared; - int recovered; ///< Picture at IDR or recovery point + recovery count - int invalid_gap; - int crop; - int crop_left; - int crop_top; + uint64_t error[AV_NUM_DATA_POINTERS]; } Picture; /** @@ -273,6 +216,21 @@ typedef struct MotionEstContext{ */ typedef struct MpegEncContext { AVClass *class; + + int y_dc_scale, c_dc_scale; + int ac_pred; + int block_last_index[12]; ///< last non zero coefficient in block + int h263_aic; ///< Advanded INTRA Coding (AIC) + + /* scantables */ + ScanTable inter_scantable; ///< if inter == intra then intra should be used to reduce tha cache usage + ScanTable intra_scantable; + ScanTable intra_h_scantable; + ScanTable intra_v_scantable; + + /* WARNING: changes above this line require updates to hardcoded + * offsets used in asm. */ + struct AVCodecContext *avctx; /* the following parameters must be initialized before encoding */ int width, height;///< picture size. must be a multiple of 16 @@ -310,7 +268,6 @@ typedef struct MpegEncContext { int mb_width, mb_height; ///< number of MBs horizontally & vertically int mb_stride; ///< mb_width+1 used for some arrays to allow simple addressing of left & top MBs without sig11 int b8_stride; ///< 2*mb_width+1 used for some 8x8 block arrays to allow simple addressing - int b4_stride; ///< 4*mb_width+1 used for some 4x4 block arrays to allow simple addressing int h_edge_pos, v_edge_pos;///< horizontal / vertical position of the right/bottom edge (pixel replication) int mb_num; ///< number of MBs of a picture ptrdiff_t linesize; ///< line size, in bytes, may be different from width @@ -319,20 +276,6 @@ typedef struct MpegEncContext { Picture **input_picture; ///< next pictures on display order for encoding Picture **reordered_input_picture; ///< pointer to the next pictures in codedorder for encoding - int y_dc_scale, c_dc_scale; - int ac_pred; - int block_last_index[12]; ///< last non zero coefficient in block - int h263_aic; ///< Advanded INTRA Coding (AIC) - - /* scantables */ - ScanTable inter_scantable; ///< if inter == intra then intra should be used to reduce tha cache usage - ScanTable intra_scantable; - ScanTable intra_h_scantable; - ScanTable intra_v_scantable; - - /* WARNING: changes above this line require updates to hardcoded - * offsets used in asm. */ - int64_t user_specified_pts; ///< last non-zero pts from AVFrame which was passed into avcodec_encode_video2() /** * pts difference between the first and second input frame, used for @@ -421,9 +364,16 @@ typedef struct MpegEncContext { int unrestricted_mv; ///< mv can point outside of the coded picture int h263_long_vectors; ///< use horrible h263v1 long vector mode + BlockDSPContext bdsp; DSPContext dsp; ///< pointers for accelerated dsp functions + FDCTDSPContext fdsp; H264ChromaContext h264chroma; HpelDSPContext hdsp; + IDCTDSPContext idsp; + MpegVideoDSPContext mdsp; + MpegvideoEncDSPContext mpvencdsp; + PixblockDSPContext pdsp; + QpelDSPContext qdsp; VideoDSPContext vdsp; H263DSPContext h263dsp; int f_code; ///< forward MV resolution @@ -477,24 +427,7 @@ typedef struct MpegEncContext { int mb_x, mb_y; int mb_skip_run; int mb_intra; - uint16_t *mb_type; ///< Table for candidate MB types for encoding -#define CANDIDATE_MB_TYPE_INTRA 0x01 -#define CANDIDATE_MB_TYPE_INTER 0x02 -#define CANDIDATE_MB_TYPE_INTER4V 0x04 -#define CANDIDATE_MB_TYPE_SKIPPED 0x08 -//#define MB_TYPE_GMC 0x10 - -#define CANDIDATE_MB_TYPE_DIRECT 0x10 -#define CANDIDATE_MB_TYPE_FORWARD 0x20 -#define CANDIDATE_MB_TYPE_BACKWARD 0x40 -#define CANDIDATE_MB_TYPE_BIDIR 0x80 - -#define CANDIDATE_MB_TYPE_INTER_I 0x100 -#define CANDIDATE_MB_TYPE_FORWARD_I 0x200 -#define CANDIDATE_MB_TYPE_BACKWARD_I 0x400 -#define CANDIDATE_MB_TYPE_BIDIR_I 0x800 - -#define CANDIDATE_MB_TYPE_DIRECT0 0x1000 + uint16_t *mb_type; ///< Table for candidate MB types for encoding (defines in mpegutils.h) int block_index[6]; ///< index to current MB in block based arrays with edges int block_wrap[6]; @@ -658,11 +591,9 @@ typedef struct MpegEncContext { /* MPEG-2-specific - I wished not to have to support this mess. */ int progressive_sequence; int mpeg_f_code[2][2]; + + // picture structure defines are loaded from mpegutils.h int picture_structure; -/* picture type */ -#define PICT_TOP_FIELD 1 -#define PICT_BOTTOM_FIELD 2 -#define PICT_FRAME 3 int intra_dc_precision; int frame_pred_frame_dct; @@ -671,6 +602,7 @@ typedef struct MpegEncContext { int q_scale_type; int intra_vlc_format; int alternate_scan; + int seq_disp_ext; int repeat_first_field; int chroma_420_type; int chroma_format; @@ -758,6 +690,8 @@ typedef struct MpegEncContext { #define FF_MPV_FLAG_STRICT_GOP 0x0002 #define FF_MPV_FLAG_QP_RD 0x0004 #define FF_MPV_FLAG_CBP_RD 0x0008 +#define FF_MPV_FLAG_NAQ 0x0010 +#define FF_MPV_FLAG_MV0 0x0020 #define FF_MPV_OFFSET(x) offsetof(MpegEncContext, x) #define FF_MPV_OPT_FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) @@ -767,6 +701,8 @@ typedef struct MpegEncContext { { "strict_gop", "Strictly enforce gop size", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_STRICT_GOP }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ { "qp_rd", "Use rate distortion optimization for qp selection", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_QP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ { "cbp_rd", "use rate distortion optimization for CBP", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_CBP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "naq", "normalize adaptive quantization", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_NAQ }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "mv0", "always try a mb with mv=<0,0>", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_MV0 }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ { "luma_elim_threshold", "single coefficient elimination threshold for luminance (negative values also consider dc coefficient)",\ FF_MPV_OFFSET(luma_elim_threshold), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS },\ { "chroma_elim_threshold", "single coefficient elimination threshold for chrominance (negative values also consider dc coefficient)",\ @@ -809,14 +745,12 @@ void ff_MPV_common_init_axp(MpegEncContext *s); void ff_MPV_common_init_arm(MpegEncContext *s); void ff_MPV_common_init_ppc(MpegEncContext *s); void ff_clean_intra_table_entries(MpegEncContext *s); -void ff_draw_horiz_band(AVCodecContext *avctx, Picture *cur, Picture *last, - int y, int h, int picture_structure, int first_field, - int low_delay); void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h); void ff_mpeg_flush(AVCodecContext *avctx); void ff_print_debug_info(MpegEncContext *s, Picture *p, AVFrame *pict); -void ff_print_debug_info2(AVCodecContext *avctx, Picture *p, AVFrame *pict, uint8_t *mbskip_table, +void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_table, + uint32_t *mbtype_table, int8_t *qscale_table, int16_t (*motion_val[2])[2], int *low_delay, int mb_width, int mb_height, int mb_stride, int quarter_sample); @@ -831,11 +765,9 @@ void ff_MPV_report_decode_progress(MpegEncContext *s); int ff_mpeg_update_thread_context(AVCodecContext *dst, const AVCodecContext *src); void ff_set_qscale(MpegEncContext * s, int qscale); -void ff_mpeg_er_frame_start(MpegEncContext *s); - int ff_dct_common_init(MpegEncContext *s); int ff_dct_encode_init(MpegEncContext *s); -void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64], uint16_t (*qmat16)[2][64], +void ff_convert_matrix(MpegEncContext *s, int (*qmat)[64], uint16_t (*qmat16)[2][64], const uint16_t *quant_matrix, int bias, int qmin, int qmax, int intra); int ff_dct_quantize_c(MpegEncContext *s, int16_t *block, int n, int qscale, int *overflow); @@ -854,8 +786,6 @@ void ff_MPV_motion(MpegEncContext *s, */ int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared); -extern const enum AVPixelFormat ff_pixfmt_list_420[]; - /** * permute block according to permuatation. * @param last last non zero element in scantable order diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index eaa80e2a1..a4786b4a3 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -37,14 +37,18 @@ #include "libavutil/timer.h" #include "avcodec.h" #include "dct.h" -#include "dsputil.h" +#include "idctdsp.h" #include "mpeg12.h" #include "mpegvideo.h" #include "h261.h" #include "h263.h" +#include "mjpegenc_common.h" #include "mathops.h" +#include "mpegutils.h" #include "mjpegenc.h" #include "msmpeg4.h" +#include "pixblockdsp.h" +#include "qpeldsp.h" #include "faandct.h" #include "thread.h" #include "aandcttab.h" @@ -69,21 +73,22 @@ const AVOption ff_mpv_generic_options[] = { { NULL }, }; -void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64], +void ff_convert_matrix(MpegEncContext *s, int (*qmat)[64], uint16_t (*qmat16)[2][64], const uint16_t *quant_matrix, int bias, int qmin, int qmax, int intra) { + FDCTDSPContext *fdsp = &s->fdsp; int qscale; int shift = 0; for (qscale = qmin; qscale <= qmax; qscale++) { int i; - if (dsp->fdct == ff_jpeg_fdct_islow_8 || - dsp->fdct == ff_jpeg_fdct_islow_10 || - dsp->fdct == ff_faandct) { + if (fdsp->fdct == ff_jpeg_fdct_islow_8 || + fdsp->fdct == ff_jpeg_fdct_islow_10 || + fdsp->fdct == ff_faandct) { for (i = 0; i < 64; i++) { - const int j = dsp->idct_permutation[i]; + const int j = s->idsp.idct_permutation[i]; /* 16 <= qscale * quant_matrix[i] <= 7905 * Assume x = ff_aanscales[i] * qscale * quant_matrix[i] * 19952 <= x <= 249205026 @@ -93,9 +98,9 @@ void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64], qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) / (qscale * quant_matrix[j])); } - } else if (dsp->fdct == ff_fdct_ifast) { + } else if (fdsp->fdct == ff_fdct_ifast) { for (i = 0; i < 64; i++) { - const int j = dsp->idct_permutation[i]; + const int j = s->idsp.idct_permutation[i]; /* 16 <= qscale * quant_matrix[i] <= 7905 * Assume x = ff_aanscales[i] * qscale * quant_matrix[i] * 19952 <= x <= 249205026 @@ -107,7 +112,7 @@ void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64], } } else { for (i = 0; i < 64; i++) { - const int j = dsp->idct_permutation[i]; + const int j = s->idsp.idct_permutation[i]; /* We can safely suppose that 16 <= quant_matrix[i] <= 255 * Assume x = qscale * quant_matrix[i] * So 16 <= x <= 7905 @@ -131,7 +136,7 @@ void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64], for (i = intra; i < 64; i++) { int64_t max = 8191; - if (dsp->fdct == ff_fdct_ifast) { + if (fdsp->fdct == ff_fdct_ifast) { max = (8191LL * ff_aanscales[i]) >> 14; } while (((max * qmat[qscale][i]) >> shift) > INT_MAX) { @@ -244,7 +249,7 @@ av_cold int ff_dct_encode_init(MpegEncContext *s) { av_cold int ff_MPV_encode_init(AVCodecContext *avctx) { MpegEncContext *s = avctx->priv_data; - int i, ret; + int i, ret, format_supported; MPV_encode_defaults(s); @@ -259,13 +264,24 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx) break; case AV_CODEC_ID_MJPEG: case AV_CODEC_ID_AMV: - if (avctx->pix_fmt != AV_PIX_FMT_YUVJ420P && - avctx->pix_fmt != AV_PIX_FMT_YUVJ422P && - avctx->pix_fmt != AV_PIX_FMT_YUVJ444P && - ((avctx->pix_fmt != AV_PIX_FMT_YUV420P && - avctx->pix_fmt != AV_PIX_FMT_YUV422P && - avctx->pix_fmt != AV_PIX_FMT_YUV444P) || - avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL)) { + format_supported = 0; + /* JPEG color space */ + if (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 && + (avctx->pix_fmt == AV_PIX_FMT_YUV420P || + avctx->pix_fmt == AV_PIX_FMT_YUV422P || + avctx->pix_fmt == AV_PIX_FMT_YUV444P))) + format_supported = 1; + /* MPEG color space */ + else if (avctx->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL && + (avctx->pix_fmt == AV_PIX_FMT_YUV420P || + avctx->pix_fmt == AV_PIX_FMT_YUV422P || + avctx->pix_fmt == AV_PIX_FMT_YUV444P)) + format_supported = 1; + + if (!format_supported) { av_log(avctx, AV_LOG_ERROR, "colorspace not supported in jpeg\n"); return -1; } @@ -319,6 +335,24 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx) s->mpeg_quant = avctx->mpeg_quant; s->rtp_mode = !!avctx->rtp_payload_size; s->intra_dc_precision = avctx->intra_dc_precision; + + // workaround some differences between how applications specify dc precission + if (s->intra_dc_precision < 0) { + s->intra_dc_precision += 8; + } else if (s->intra_dc_precision >= 8) + s->intra_dc_precision -= 8; + + if (s->intra_dc_precision < 0) { + av_log(avctx, AV_LOG_ERROR, + "intra dc precision must be positive, note some applications use" + " 0 and some 8 as base meaning 8bit, the value must not be smaller than that\n"); + return AVERROR(EINVAL); + } + + if (s->intra_dc_precision > (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 3 : 0)) { + av_log(avctx, AV_LOG_ERROR, "intra dc precision too large\n"); + return AVERROR(EINVAL); + } s->user_specified_pts = AV_NOPTS_VALUE; if (s->gop_size <= 1) { @@ -372,8 +406,7 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx) if ((!avctx->rc_max_rate) != (!avctx->rc_buffer_size)) { av_log(avctx, AV_LOG_ERROR, "Either both buffer size and max rate or neither must be specified\n"); - if (avctx->rc_max_rate && !avctx->rc_buffer_size) - return -1; + return -1; } if (avctx->rc_min_rate && avctx->rc_max_rate != avctx->rc_min_rate) { @@ -408,9 +441,9 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx) if (!s->fixed_qscale && avctx->bit_rate * av_q2d(avctx->time_base) > avctx->bit_rate_tolerance) { - av_log(avctx, AV_LOG_ERROR, - "bitrate tolerance %d too small for bitrate %d\n", avctx->bit_rate_tolerance, avctx->bit_rate); - return -1; + av_log(avctx, AV_LOG_WARNING, + "bitrate tolerance %d too small for bitrate %d, overriding\n", avctx->bit_rate_tolerance, avctx->bit_rate); + avctx->bit_rate_tolerance = 5 * avctx->bit_rate * av_q2d(avctx->time_base); } if (s->avctx->rc_max_rate && @@ -802,7 +835,12 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx) if (ff_MPV_common_init(s) < 0) return -1; - s->avctx->coded_frame = &s->current_picture.f; + ff_fdctdsp_init(&s->fdsp, avctx); + ff_mpegvideoencdsp_init(&s->mpvencdsp, 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, @@ -849,7 +887,7 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx) /* init q matrix */ for (i = 0; i < 64; i++) { - int j = s->dsp.idct_permutation[i]; + int j = s->idsp.idct_permutation[i]; if (CONFIG_MPEG4_ENCODER && s->codec_id == AV_CODEC_ID_MPEG4 && s->mpeg_quant) { s->intra_matrix[j] = ff_mpeg4_default_intra_matrix[i]; @@ -871,10 +909,10 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx) /* precompute matrix */ /* for mjpeg, we do include qscale in the matrix */ if (s->out_format != FMT_MJPEG) { - ff_convert_matrix(&s->dsp, s->q_intra_matrix, s->q_intra_matrix16, + ff_convert_matrix(s, s->q_intra_matrix, s->q_intra_matrix16, s->intra_matrix, s->intra_quant_bias, avctx->qmin, 31, 1); - ff_convert_matrix(&s->dsp, s->q_inter_matrix, s->q_inter_matrix16, + ff_convert_matrix(s, s->q_inter_matrix, s->q_inter_matrix16, s->inter_matrix, s->inter_quant_bias, avctx->qmin, 31, 0); } @@ -889,6 +927,20 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx) FF_ENABLE_DEPRECATION_WARNINGS; #endif +#if FF_API_NORMALIZE_AQP + FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->flags & CODEC_FLAG_NORMALIZE_AQP) + s->mpv_flags |= FF_MPV_FLAG_NAQ; + FF_ENABLE_DEPRECATION_WARNINGS; +#endif + +#if FF_API_MV0 + FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->flags & CODEC_FLAG_MV0) + s->mpv_flags |= FF_MPV_FLAG_MV0; + FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (avctx->b_frame_strategy == 2) { for (i = 0; i < s->max_b_frames + 2; i++) { s->tmp_frames[i] = av_frame_alloc(); @@ -977,7 +1029,7 @@ static int get_intra_count(MpegEncContext *s, uint8_t *src, int offset = x + y * stride; int sad = s->dsp.sad[0](NULL, src + offset, ref + offset, stride, 16); - int mean = (s->dsp.pix_sum(src + offset, stride) + 128) >> 8; + int mean = (s->mpvencdsp.pix_sum(src + offset, stride) + 128) >> 8; int sae = get_sae(src + offset, mean, stride); acc += sae + 500 < sad; @@ -1044,7 +1096,7 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) if (s->linesize & (STRIDE_ALIGN-1)) direct = 0; - av_dlog(s->avctx, "%d %d %td %td\n", pic_arg->linesize[0], + av_dlog(s->avctx, "%d %d %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"\n", pic_arg->linesize[0], pic_arg->linesize[1], s->linesize, s->uvlinesize); if (direct) { @@ -1055,7 +1107,7 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) pic = &s->picture[i]; pic->reference = 3; - if ((ret = av_frame_ref(&pic->f, pic_arg)) < 0) + if ((ret = av_frame_ref(pic->f, pic_arg)) < 0) return ret; if (ff_alloc_picture(s, pic, 1) < 0) { return -1; @@ -1072,9 +1124,9 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) return -1; } - if (pic->f.data[0] + INPLACE_OFFSET == pic_arg->data[0] && - pic->f.data[1] + INPLACE_OFFSET == pic_arg->data[1] && - pic->f.data[2] + INPLACE_OFFSET == pic_arg->data[2]) { + if (pic->f->data[0] + INPLACE_OFFSET == pic_arg->data[0] && + pic->f->data[1] + INPLACE_OFFSET == pic_arg->data[1] && + pic->f->data[2] + INPLACE_OFFSET == pic_arg->data[2]) { // empty } else { int h_chroma_shift, v_chroma_shift; @@ -1090,11 +1142,13 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) int w = s->width >> h_shift; int h = s->height >> v_shift; uint8_t *src = pic_arg->data[i]; - uint8_t *dst = pic->f.data[i]; + uint8_t *dst = pic->f->data[i]; + int vpad = 16; - if (s->codec_id == AV_CODEC_ID_AMV && !(s->avctx->flags & CODEC_FLAG_EMU_EDGE)) { - h = ((s->height + 15)/16*16) >> v_shift; - } + if ( s->codec_id == AV_CODEC_ID_MPEG2VIDEO + && !s->progressive_sequence + && FFALIGN(s->height, 32) - s->height > 16) + vpad = 32; if (!s->avctx->rc_buffer_size) dst += INPLACE_OFFSET; @@ -1110,22 +1164,22 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) src += src_stride; } } - if ((s->width & 15) || (s->height & 15)) { - s->dsp.draw_edges(dst, dst_stride, - w, h, - 16>>h_shift, - 16>>v_shift, - EDGE_BOTTOM); + if ((s->width & 15) || (s->height & (vpad-1))) { + s->mpvencdsp.draw_edges(dst, dst_stride, + w, h, + 16>>h_shift, + vpad>>v_shift, + EDGE_BOTTOM); } } } } - ret = av_frame_copy_props(&pic->f, pic_arg); + ret = av_frame_copy_props(pic->f, pic_arg); if (ret < 0) 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->display_picture_number = display_picture_number; + pic->f->pts = pts; // we set this here to avoid modifiying pic_arg } /* shift buffer entries */ @@ -1144,13 +1198,13 @@ static int skip_check(MpegEncContext *s, Picture *p, Picture *ref) int64_t score64 = 0; for (plane = 0; plane < 3; plane++) { - const int stride = p->f.linesize[plane]; + const int stride = p->f->linesize[plane]; const int bw = plane ? 1 : 2; for (y = 0; y < s->mb_height * bw; y++) { for (x = 0; x < s->mb_width * bw; x++) { int off = p->shared ? 0 : 16; - uint8_t *dptr = p->f.data[plane] + 8 * (x + y * stride) + off; - uint8_t *rptr = ref->f.data[plane] + 8 * (x + y * stride); + uint8_t *dptr = p->f->data[plane] + 8 * (x + y * stride) + off; + uint8_t *rptr = ref->f->data[plane] + 8 * (x + y * stride); int v = s->dsp.frame_skip_cmp[1](s, dptr, rptr, stride, 8); switch (FFABS(s->avctx->frame_skip_exp)) { @@ -1216,8 +1270,7 @@ 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 | - CODEC_FLAG_INPUT_PRESERVED; + c->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_PSNR; c->flags |= s->avctx->flags & CODEC_FLAG_QPEL; c->mb_decision = s->avctx->mb_decision; c->me_cmp = s->avctx->me_cmp; @@ -1233,25 +1286,33 @@ static int estimate_best_b_count(MpegEncContext *s) for (i = 0; i < s->max_b_frames + 2; i++) { Picture pre_input, *pre_input_ptr = i ? s->input_picture[i - 1] : s->next_picture_ptr; + uint8_t *data[4]; if (pre_input_ptr && (!i || s->input_picture[i - 1])) { pre_input = *pre_input_ptr; + memcpy(data, pre_input_ptr->f->data, sizeof(data)); if (!pre_input.shared && i) { - pre_input.f.data[0] += INPLACE_OFFSET; - pre_input.f.data[1] += INPLACE_OFFSET; - pre_input.f.data[2] += INPLACE_OFFSET; + data[0] += INPLACE_OFFSET; + data[1] += INPLACE_OFFSET; + data[2] += INPLACE_OFFSET; } - s->dsp.shrink[scale](s->tmp_frames[i]->data[0], s->tmp_frames[i]->linesize[0], - pre_input.f.data[0], pre_input.f.linesize[0], - c->width, c->height); - s->dsp.shrink[scale](s->tmp_frames[i]->data[1], s->tmp_frames[i]->linesize[1], - pre_input.f.data[1], pre_input.f.linesize[1], - c->width >> 1, c->height >> 1); - s->dsp.shrink[scale](s->tmp_frames[i]->data[2], s->tmp_frames[i]->linesize[2], - pre_input.f.data[2], pre_input.f.linesize[2], - c->width >> 1, c->height >> 1); + s->mpvencdsp.shrink[scale](s->tmp_frames[i]->data[0], + s->tmp_frames[i]->linesize[0], + data[0], + pre_input.f->linesize[0], + c->width, c->height); + s->mpvencdsp.shrink[scale](s->tmp_frames[i]->data[1], + s->tmp_frames[i]->linesize[1], + data[1], + pre_input.f->linesize[1], + c->width >> 1, c->height >> 1); + s->mpvencdsp.shrink[scale](s->tmp_frames[i]->data[2], + s->tmp_frames[i]->linesize[2], + data[2], + pre_input.f->linesize[2], + c->width >> 1, c->height >> 1); } } @@ -1317,7 +1378,7 @@ static int select_input_picture(MpegEncContext *s) s->next_picture_ptr && skip_check(s, s->input_picture[0], s->next_picture_ptr)) { // FIXME check that te gop check above is +-1 correct - av_frame_unref(&s->input_picture[0]->f); + av_frame_unref(s->input_picture[0]->f); ff_vbv_update(s, 0); @@ -1328,15 +1389,15 @@ static int select_input_picture(MpegEncContext *s) if (/*s->picture_in_gop_number >= s->gop_size ||*/ s->next_picture_ptr == NULL || s->intra_only) { s->reordered_input_picture[0] = s->input_picture[0]; - s->reordered_input_picture[0]->f.pict_type = AV_PICTURE_TYPE_I; - s->reordered_input_picture[0]->f.coded_picture_number = + s->reordered_input_picture[0]->f->pict_type = AV_PICTURE_TYPE_I; + s->reordered_input_picture[0]->f->coded_picture_number = s->coded_picture_number++; } else { int b_frames; if (s->flags & CODEC_FLAG_PASS2) { for (i = 0; i < s->max_b_frames + 1; i++) { - int pict_num = s->input_picture[0]->f.display_picture_number + i; + int pict_num = s->input_picture[0]->f->display_picture_number + i; if (pict_num >= s->rc_context.num_entries) break; @@ -1345,7 +1406,7 @@ static int select_input_picture(MpegEncContext *s) break; } - s->input_picture[i]->f.pict_type = + s->input_picture[i]->f->pict_type = s->rc_context.entry[pict_num].new_pict_type; } } @@ -1360,8 +1421,8 @@ static int select_input_picture(MpegEncContext *s) s->input_picture[i]->b_frame_score == 0) { s->input_picture[i]->b_frame_score = get_intra_count(s, - s->input_picture[i ]->f.data[0], - s->input_picture[i - 1]->f.data[0], + s->input_picture[i ]->f->data[0], + s->input_picture[i - 1]->f->data[0], s->linesize) + 1; } } @@ -1388,11 +1449,11 @@ static int select_input_picture(MpegEncContext *s) emms_c(); for (i = b_frames - 1; i >= 0; i--) { - int type = s->input_picture[i]->f.pict_type; + int type = s->input_picture[i]->f->pict_type; if (type && type != AV_PICTURE_TYPE_B) b_frames = i; } - if (s->input_picture[b_frames]->f.pict_type == AV_PICTURE_TYPE_B && + 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"); @@ -1405,24 +1466,24 @@ static int select_input_picture(MpegEncContext *s) } else { if (s->flags & CODEC_FLAG_CLOSED_GOP) b_frames = 0; - s->input_picture[b_frames]->f.pict_type = AV_PICTURE_TYPE_I; + s->input_picture[b_frames]->f->pict_type = AV_PICTURE_TYPE_I; } } if ((s->flags & CODEC_FLAG_CLOSED_GOP) && b_frames && - s->input_picture[b_frames]->f.pict_type == AV_PICTURE_TYPE_I) + s->input_picture[b_frames]->f->pict_type == AV_PICTURE_TYPE_I) b_frames--; s->reordered_input_picture[0] = s->input_picture[b_frames]; - if (s->reordered_input_picture[0]->f.pict_type != AV_PICTURE_TYPE_I) - s->reordered_input_picture[0]->f.pict_type = AV_PICTURE_TYPE_P; - s->reordered_input_picture[0]->f.coded_picture_number = + if (s->reordered_input_picture[0]->f->pict_type != AV_PICTURE_TYPE_I) + s->reordered_input_picture[0]->f->pict_type = AV_PICTURE_TYPE_P; + s->reordered_input_picture[0]->f->coded_picture_number = s->coded_picture_number++; for (i = 0; i < b_frames; i++) { s->reordered_input_picture[i + 1] = s->input_picture[i]; - s->reordered_input_picture[i + 1]->f.pict_type = + s->reordered_input_picture[i + 1]->f->pict_type = AV_PICTURE_TYPE_B; - s->reordered_input_picture[i + 1]->f.coded_picture_number = + s->reordered_input_picture[i + 1]->f->coded_picture_number = s->coded_picture_number++; } } @@ -1430,7 +1491,7 @@ static int select_input_picture(MpegEncContext *s) no_output_pic: if (s->reordered_input_picture[0]) { s->reordered_input_picture[0]->reference = - s->reordered_input_picture[0]->f.pict_type != + s->reordered_input_picture[0]->f->pict_type != AV_PICTURE_TYPE_B ? 3 : 0; ff_mpeg_unref_picture(s, &s->new_picture); @@ -1452,12 +1513,12 @@ no_output_pic: return -1; } - ret = av_frame_copy_props(&pic->f, &s->reordered_input_picture[0]->f); + ret = av_frame_copy_props(pic->f, s->reordered_input_picture[0]->f); if (ret < 0) return ret; /* mark us unused / free shared pic */ - av_frame_unref(&s->reordered_input_picture[0]->f); + av_frame_unref(s->reordered_input_picture[0]->f); s->reordered_input_picture[0]->shared = 0; s->current_picture_ptr = pic; @@ -1465,7 +1526,7 @@ no_output_pic: // input is not a shared pix -> reuse buffer for current_pix s->current_picture_ptr = s->reordered_input_picture[0]; for (i = 0; i < 4; i++) { - s->new_picture.f.data[i] += INPLACE_OFFSET; + s->new_picture.f->data[i] += INPLACE_OFFSET; } } ff_mpeg_unref_picture(s, &s->current_picture); @@ -1473,7 +1534,7 @@ no_output_pic: s->current_picture_ptr)) < 0) return ret; - s->picture_number = s->new_picture.f.display_picture_number; + s->picture_number = s->new_picture.f->display_picture_number; } else { ff_mpeg_unref_picture(s, &s->new_picture); } @@ -1488,28 +1549,35 @@ static void frame_end(MpegEncContext *s) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->avctx->pix_fmt); int hshift = desc->log2_chroma_w; int vshift = desc->log2_chroma_h; - s->dsp.draw_edges(s->current_picture.f.data[0], s->current_picture.f.linesize[0], - s->h_edge_pos, s->v_edge_pos, - EDGE_WIDTH, EDGE_WIDTH, - EDGE_TOP | EDGE_BOTTOM); - s->dsp.draw_edges(s->current_picture.f.data[1], s->current_picture.f.linesize[1], - s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, - EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, - EDGE_TOP | EDGE_BOTTOM); - s->dsp.draw_edges(s->current_picture.f.data[2], s->current_picture.f.linesize[2], - s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, - EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, - EDGE_TOP | EDGE_BOTTOM); + s->mpvencdsp.draw_edges(s->current_picture.f->data[0], + s->current_picture.f->linesize[0], + s->h_edge_pos, s->v_edge_pos, + EDGE_WIDTH, EDGE_WIDTH, + EDGE_TOP | EDGE_BOTTOM); + s->mpvencdsp.draw_edges(s->current_picture.f->data[1], + s->current_picture.f->linesize[1], + s->h_edge_pos >> hshift, + s->v_edge_pos >> vshift, + EDGE_WIDTH >> hshift, + EDGE_WIDTH >> vshift, + EDGE_TOP | EDGE_BOTTOM); + s->mpvencdsp.draw_edges(s->current_picture.f->data[2], + s->current_picture.f->linesize[2], + s->h_edge_pos >> hshift, + s->v_edge_pos >> vshift, + EDGE_WIDTH >> hshift, + EDGE_WIDTH >> vshift, + EDGE_TOP | EDGE_BOTTOM); } emms_c(); s->last_pict_type = s->pict_type; - s->last_lambda_for [s->pict_type] = s->current_picture_ptr->f.quality; + s->last_lambda_for [s->pict_type] = s->current_picture_ptr->f->quality; if (s->pict_type!= AV_PICTURE_TYPE_B) s->last_non_b_pict_type = s->pict_type; - s->avctx->coded_frame = &s->current_picture_ptr->f; + s->avctx->coded_frame = s->current_picture_ptr->f; } @@ -1541,12 +1609,12 @@ static int frame_start(MpegEncContext *s) /* mark & release old frames */ if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && s->last_picture_ptr != s->next_picture_ptr && - s->last_picture_ptr->f.buf[0]) { + s->last_picture_ptr->f->buf[0]) { ff_mpeg_unref_picture(s, 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; + 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, @@ -1561,14 +1629,14 @@ static int frame_start(MpegEncContext *s) if (s->last_picture_ptr) { ff_mpeg_unref_picture(s, &s->last_picture); - if (s->last_picture_ptr->f.buf[0] && + if (s->last_picture_ptr->f->buf[0] && (ret = ff_mpeg_ref_picture(s, &s->last_picture, s->last_picture_ptr)) < 0) return ret; } if (s->next_picture_ptr) { ff_mpeg_unref_picture(s, &s->next_picture); - if (s->next_picture_ptr->f.buf[0] && + if (s->next_picture_ptr->f->buf[0] && (ret = ff_mpeg_ref_picture(s, &s->next_picture, s->next_picture_ptr)) < 0) return ret; @@ -1578,12 +1646,12 @@ static int frame_start(MpegEncContext *s) int i; for (i = 0; i < 4; i++) { if (s->picture_structure == PICT_BOTTOM_FIELD) { - s->current_picture.f.data[i] += - s->current_picture.f.linesize[i]; + s->current_picture.f->data[i] += + s->current_picture.f->linesize[i]; } - s->current_picture.f.linesize[i] *= 2; - s->last_picture.f.linesize[i] *= 2; - s->next_picture.f.linesize[i] *= 2; + s->current_picture.f->linesize[i] *= 2; + s->last_picture.f->linesize[i] *= 2; + s->next_picture.f->linesize[i] *= 2; } } @@ -1623,7 +1691,7 @@ int ff_MPV_encode_picture(AVCodecContext *avctx, AVPacket *pkt, } /* output? */ - if (s->new_picture.f.data[0]) { + if (s->new_picture.f->data[0]) { if ((ret = ff_alloc_packet2(avctx, pkt, s->mb_width*s->mb_height*(MAX_MB_BYTES+100)+10000)) < 0) return ret; if (s->mb_info) { @@ -1643,7 +1711,7 @@ int ff_MPV_encode_picture(AVCodecContext *avctx, AVPacket *pkt, init_put_bits(&s->thread_context[i]->pb, start, end - start); } - s->pict_type = s->new_picture.f.pict_type; + s->pict_type = s->new_picture.f->pict_type; //emms_c(); ret = frame_start(s); if (ret < 0) @@ -1702,15 +1770,17 @@ vbv_retry: goto vbv_retry; } - assert(s->avctx->rc_max_rate); + av_assert0(s->avctx->rc_max_rate); } if (s->flags & CODEC_FLAG_PASS1) ff_write_pass1_stats(s); for (i = 0; i < 4; i++) { - s->current_picture_ptr->f.error[i] = s->current_picture.f.error[i]; - avctx->error[i] += s->current_picture_ptr->f.error[i]; + s->current_picture_ptr->f->error[i] = + s->current_picture.f->error[i] = + s->current_picture.error[i]; + avctx->error[i] += s->current_picture_ptr->f->error[i]; } if (s->flags & CODEC_FLAG_PASS1) @@ -1788,16 +1858,16 @@ vbv_retry: s->total_bits += s->frame_bits; avctx->frame_bits = s->frame_bits; - pkt->pts = s->current_picture.f.pts; + pkt->pts = s->current_picture.f->pts; if (!s->low_delay && s->pict_type != AV_PICTURE_TYPE_B) { - if (!s->current_picture.f.coded_picture_number) + if (!s->current_picture.f->coded_picture_number) pkt->dts = pkt->pts - s->dts_delta; else pkt->dts = s->reordered_pts; s->reordered_pts = pkt->pts; } else pkt->dts = pkt->pts; - if (s->current_picture.f.key_frame) + if (s->current_picture.f->key_frame) pkt->flags |= AV_PKT_FLAG_KEY; if (s->mb_info) av_packet_shrink_side_data(pkt, AV_PKT_DATA_H263_MB_INFO, s->mb_info_size); @@ -1811,7 +1881,7 @@ vbv_retry: ff_mpeg_unref_picture(s, &s->picture[i]); } - assert((s->frame_bits & 7) == 0); + av_assert1((s->frame_bits & 7) == 0); pkt->size = s->frame_bits / 8; *got_packet = !!pkt->size; @@ -1984,15 +2054,15 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, wrap_y = s->linesize; wrap_c = s->uvlinesize; - ptr_y = s->new_picture.f.data[0] + + ptr_y = s->new_picture.f->data[0] + (mb_y * 16 * wrap_y) + mb_x * 16; - ptr_cb = s->new_picture.f.data[1] + + ptr_cb = s->new_picture.f->data[1] + (mb_y * mb_block_height * wrap_c) + mb_x * mb_block_width; - ptr_cr = s->new_picture.f.data[2] + + ptr_cr = s->new_picture.f->data[2] + (mb_y * mb_block_height * wrap_c) + mb_x * mb_block_width; if((mb_x * 16 + 16 > s->width || mb_y * 16 + 16 > s->height) && s->codec_id != AV_CODEC_ID_AMV){ - uint8_t *ebuf = s->edge_emu_buffer + 32; + uint8_t *ebuf = s->edge_emu_buffer + 36 * wrap_y; int cw = (s->width + s->chroma_x_shift) >> s->chroma_x_shift; int ch = (s->height + s->chroma_y_shift) >> s->chroma_y_shift; s->vdsp.emulated_edge_mc(ebuf, ptr_y, @@ -2000,18 +2070,18 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, 16, 16, mb_x * 16, mb_y * 16, s->width, s->height); ptr_y = ebuf; - s->vdsp.emulated_edge_mc(ebuf + 18 * wrap_y, ptr_cb, + s->vdsp.emulated_edge_mc(ebuf + 16 * wrap_y, ptr_cb, wrap_c, wrap_c, mb_block_width, mb_block_height, mb_x * mb_block_width, mb_y * mb_block_height, cw, ch); - ptr_cb = ebuf + 18 * wrap_y; - s->vdsp.emulated_edge_mc(ebuf + 18 * wrap_y + 16, ptr_cr, + ptr_cb = ebuf + 16 * wrap_y; + s->vdsp.emulated_edge_mc(ebuf + 16 * wrap_y + 16, ptr_cr, wrap_c, wrap_c, mb_block_width, mb_block_height, mb_x * mb_block_width, mb_y * mb_block_height, cw, ch); - ptr_cr = ebuf + 18 * wrap_y + 16; + ptr_cr = ebuf + 16 * wrap_y + 16; } if (s->mb_intra) { @@ -2042,27 +2112,27 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, } } - s->dsp.get_pixels(s->block[0], ptr_y , wrap_y); - s->dsp.get_pixels(s->block[1], ptr_y + 8 , wrap_y); - s->dsp.get_pixels(s->block[2], ptr_y + dct_offset , wrap_y); - s->dsp.get_pixels(s->block[3], ptr_y + dct_offset + 8 , wrap_y); + s->pdsp.get_pixels(s->block[0], ptr_y, wrap_y); + s->pdsp.get_pixels(s->block[1], ptr_y + 8, wrap_y); + 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) { skip_dct[4] = 1; skip_dct[5] = 1; } else { - s->dsp.get_pixels(s->block[4], ptr_cb, wrap_c); - s->dsp.get_pixels(s->block[5], ptr_cr, wrap_c); + s->pdsp.get_pixels(s->block[4], ptr_cb, wrap_c); + s->pdsp.get_pixels(s->block[5], ptr_cr, wrap_c); if (!s->chroma_y_shift && s->chroma_x_shift) { /* 422 */ - s->dsp.get_pixels(s->block[6], ptr_cb + uv_dct_offset, wrap_c); - s->dsp.get_pixels(s->block[7], ptr_cr + uv_dct_offset, wrap_c); + s->pdsp.get_pixels(s->block[6], ptr_cb + uv_dct_offset, wrap_c); + s->pdsp.get_pixels(s->block[7], ptr_cr + uv_dct_offset, wrap_c); } else if (!s->chroma_y_shift && !s->chroma_x_shift) { /* 444 */ - s->dsp.get_pixels(s->block[6], ptr_cb + 8, wrap_c); - s->dsp.get_pixels(s->block[7], ptr_cr + 8, wrap_c); - s->dsp.get_pixels(s->block[8], ptr_cb + uv_dct_offset, wrap_c); - s->dsp.get_pixels(s->block[9], ptr_cr + uv_dct_offset, wrap_c); - s->dsp.get_pixels(s->block[10], ptr_cb + uv_dct_offset + 8, wrap_c); - s->dsp.get_pixels(s->block[11], ptr_cr + uv_dct_offset + 8, wrap_c); + s->pdsp.get_pixels(s->block[ 6], ptr_cb + 8, wrap_c); + s->pdsp.get_pixels(s->block[ 7], ptr_cr + 8, wrap_c); + s->pdsp.get_pixels(s->block[ 8], ptr_cb + uv_dct_offset, wrap_c); + s->pdsp.get_pixels(s->block[ 9], ptr_cr + uv_dct_offset, wrap_c); + s->pdsp.get_pixels(s->block[10], ptr_cb + uv_dct_offset + 8, wrap_c); + s->pdsp.get_pixels(s->block[11], ptr_cr + uv_dct_offset + 8, wrap_c); } } } else { @@ -2076,22 +2146,22 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, if ((!s->no_rounding) || s->pict_type == AV_PICTURE_TYPE_B) { op_pix = s->hdsp.put_pixels_tab; - op_qpix = s->dsp.put_qpel_pixels_tab; + op_qpix = s->qdsp.put_qpel_pixels_tab; } else { op_pix = s->hdsp.put_no_rnd_pixels_tab; - op_qpix = s->dsp.put_no_rnd_qpel_pixels_tab; + op_qpix = s->qdsp.put_no_rnd_qpel_pixels_tab; } if (s->mv_dir & MV_DIR_FORWARD) { ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 0, - s->last_picture.f.data, + s->last_picture.f->data, op_pix, op_qpix); op_pix = s->hdsp.avg_pixels_tab; - op_qpix = s->dsp.avg_qpel_pixels_tab; + op_qpix = s->qdsp.avg_qpel_pixels_tab; } if (s->mv_dir & MV_DIR_BACKWARD) { ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 1, - s->next_picture.f.data, + s->next_picture.f->data, op_pix, op_qpix); } @@ -2129,24 +2199,24 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, } } - s->dsp.diff_pixels(s->block[0], ptr_y, dest_y, wrap_y); - s->dsp.diff_pixels(s->block[1], ptr_y + 8, dest_y + 8, wrap_y); - s->dsp.diff_pixels(s->block[2], ptr_y + dct_offset, - dest_y + dct_offset, wrap_y); - s->dsp.diff_pixels(s->block[3], ptr_y + dct_offset + 8, - dest_y + dct_offset + 8, wrap_y); + s->pdsp.diff_pixels(s->block[0], ptr_y, dest_y, wrap_y); + s->pdsp.diff_pixels(s->block[1], ptr_y + 8, dest_y + 8, wrap_y); + s->pdsp.diff_pixels(s->block[2], ptr_y + dct_offset, + dest_y + dct_offset, wrap_y); + 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) { skip_dct[4] = 1; skip_dct[5] = 1; } else { - s->dsp.diff_pixels(s->block[4], ptr_cb, dest_cb, wrap_c); - s->dsp.diff_pixels(s->block[5], ptr_cr, dest_cr, wrap_c); + s->pdsp.diff_pixels(s->block[4], ptr_cb, dest_cb, wrap_c); + s->pdsp.diff_pixels(s->block[5], ptr_cr, dest_cr, wrap_c); if (!s->chroma_y_shift) { /* 422 */ - s->dsp.diff_pixels(s->block[6], ptr_cb + uv_dct_offset, - dest_cb + uv_dct_offset, wrap_c); - s->dsp.diff_pixels(s->block[7], ptr_cr + uv_dct_offset, - dest_cr + uv_dct_offset, wrap_c); + s->pdsp.diff_pixels(s->block[6], ptr_cb + uv_dct_offset, + dest_cb + uv_dct_offset, wrap_c); + s->pdsp.diff_pixels(s->block[7], ptr_cr + uv_dct_offset, + dest_cr + uv_dct_offset, wrap_c); } } /* pre quantization */ @@ -2416,7 +2486,7 @@ static inline void encode_mb_hq(MpegEncContext *s, MpegEncContext *backup, MpegE s->dest[0] = s->rd_scratchpad; s->dest[1] = s->rd_scratchpad + 16*s->linesize; s->dest[2] = s->rd_scratchpad + 16*s->linesize + 8; - assert(s->linesize >= 32); //FIXME + av_assert0(s->linesize >= 32); //FIXME } encode_mb(s, motion_x, motion_y); @@ -2447,7 +2517,7 @@ static inline void encode_mb_hq(MpegEncContext *s, MpegEncContext *backup, MpegE } static int sse(MpegEncContext *s, uint8_t *src1, uint8_t *src2, int w, int h, int stride){ - uint32_t *sq = ff_squareTbl + 256; + uint32_t *sq = ff_square_tab + 256; int acc=0; int x,y; @@ -2476,18 +2546,18 @@ static int sse_mb(MpegEncContext *s){ if(w==16 && h==16) if(s->avctx->mb_cmp == FF_CMP_NSSE){ - return s->dsp.nsse[0](s, s->new_picture.f.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], s->linesize, 16) - +s->dsp.nsse[1](s, s->new_picture.f.data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[1], s->uvlinesize, 8) - +s->dsp.nsse[1](s, s->new_picture.f.data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[2], s->uvlinesize, 8); + return s->dsp.nsse[0](s, s->new_picture.f->data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], s->linesize, 16) + +s->dsp.nsse[1](s, s->new_picture.f->data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[1], s->uvlinesize, 8) + +s->dsp.nsse[1](s, s->new_picture.f->data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[2], s->uvlinesize, 8); }else{ - return s->dsp.sse[0](NULL, s->new_picture.f.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], s->linesize, 16) - +s->dsp.sse[1](NULL, s->new_picture.f.data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[1], s->uvlinesize, 8) - +s->dsp.sse[1](NULL, s->new_picture.f.data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[2], s->uvlinesize, 8); + return s->dsp.sse[0](NULL, s->new_picture.f->data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], s->linesize, 16) + +s->dsp.sse[1](NULL, s->new_picture.f->data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[1], s->uvlinesize, 8) + +s->dsp.sse[1](NULL, s->new_picture.f->data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[2], s->uvlinesize, 8); } else - return sse(s, s->new_picture.f.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], w, h, s->linesize) - +sse(s, s->new_picture.f.data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[1], w>>1, h>>1, s->uvlinesize) - +sse(s, s->new_picture.f.data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[2], w>>1, h>>1, s->uvlinesize); + return sse(s, s->new_picture.f->data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], w, h, s->linesize) + +sse(s, s->new_picture.f->data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[1], w>>1, h>>1, s->uvlinesize) + +sse(s, s->new_picture.f->data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[2], w>>1, h>>1, s->uvlinesize); } static int pre_estimate_motion_thread(AVCodecContext *c, void *arg){ @@ -2546,11 +2616,12 @@ static int mb_var_thread(AVCodecContext *c, void *arg){ for(mb_x=0; mb_x < s->mb_width; mb_x++) { int xx = mb_x * 16; int yy = mb_y * 16; - uint8_t *pix = s->new_picture.f.data[0] + (yy * s->linesize) + xx; + uint8_t *pix = s->new_picture.f->data[0] + (yy * s->linesize) + xx; int varc; - int sum = s->dsp.pix_sum(pix, s->linesize); + int sum = s->mpvencdsp.pix_sum(pix, s->linesize); - varc = (s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)sum*sum)>>8) + 500 + 128)>>8; + varc = (s->mpvencdsp.pix_norm1(pix, s->linesize) - + (((unsigned) sum * sum) >> 8) + 500 + 128) >> 8; s->current_picture.mb_var [s->mb_stride * mb_y + mb_x] = varc; s->current_picture.mb_mean[s->mb_stride * mb_y + mb_x] = (sum+128)>>8; @@ -2655,7 +2726,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.error[i] = 0; } if(s->codec_id==AV_CODEC_ID_AMV){ s->last_dc[0] = 128*8/13; @@ -3222,14 +3293,14 @@ static int encode_thread(AVCodecContext *c, void *arg){ if(s->mb_x*16 + 16 > s->width ) w= s->width - s->mb_x*16; if(s->mb_y*16 + 16 > s->height) h= s->height- s->mb_y*16; - s->current_picture.f.error[0] += sse( - s, s->new_picture.f.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, + s->current_picture.error[0] += sse( + s, s->new_picture.f->data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], w, h, s->linesize); - s->current_picture.f.error[1] += sse( - s, s->new_picture.f.data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*chr_h, + s->current_picture.error[1] += sse( + s, s->new_picture.f->data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*chr_h, s->dest[1], w>>1, h>>s->chroma_y_shift, s->uvlinesize); - s->current_picture.f.error[2] += sse( - s, s->new_picture.f.data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*chr_h, + s->current_picture.error[2] += sse( + s, s->new_picture.f->data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*chr_h, s->dest[2], w>>1, h>>s->chroma_y_shift, s->uvlinesize); } if(s->loop_filter){ @@ -3281,9 +3352,9 @@ 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.error[0]); + MERGE(current_picture.error[1]); + MERGE(current_picture.error[2]); if(dst->avctx->noise_reduction){ for(i=0; i<64; i++){ @@ -3300,13 +3371,13 @@ static void merge_context_after_encode(MpegEncContext *dst, MpegEncContext *src) static int estimate_qp(MpegEncContext *s, int dry_run){ if (s->next_lambda){ - s->current_picture_ptr->f.quality = - s->current_picture.f.quality = s->next_lambda; + s->current_picture_ptr->f->quality = + s->current_picture.f->quality = s->next_lambda; if(!dry_run) s->next_lambda= 0; } else if (!s->fixed_qscale) { - s->current_picture_ptr->f.quality = - s->current_picture.f.quality = ff_rate_estimate_qscale(s, dry_run); - if (s->current_picture.f.quality < 0) + s->current_picture_ptr->f->quality = + s->current_picture.f->quality = ff_rate_estimate_qscale(s, dry_run); + if (s->current_picture.f->quality < 0) return -1; } @@ -3329,15 +3400,15 @@ static int estimate_qp(MpegEncContext *s, int dry_run){ s->lambda= s->lambda_table[0]; //FIXME broken }else - s->lambda = s->current_picture.f.quality; + s->lambda = s->current_picture.f->quality; update_qscale(s); return 0; } /* must be called before writing the header */ static void set_frame_distances(MpegEncContext * s){ - assert(s->current_picture_ptr->f.pts != AV_NOPTS_VALUE); - s->time = s->current_picture_ptr->f.pts * s->avctx->time_base.num; + av_assert1(s->current_picture_ptr->f->pts != AV_NOPTS_VALUE); + s->time = s->current_picture_ptr->f->pts * s->avctx->time_base.num; if(s->pict_type==AV_PICTURE_TYPE_B){ s->pb_time= s->pp_time - (s->last_non_b_time - s->time); @@ -3520,7 +3591,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) /* for mjpeg, we do include qscale in the matrix */ for(i=1;i<64;i++){ - int j= s->dsp.idct_permutation[i]; + int j = s->idsp.idct_permutation[i]; s->chroma_intra_matrix[j] = av_clip_uint8((chroma_matrix[i] * s->qscale) >> 3); s-> intra_matrix[j] = av_clip_uint8(( luma_matrix[i] * s->qscale) >> 3); @@ -3529,9 +3600,9 @@ static int encode_picture(MpegEncContext *s, int picture_number) s->c_dc_scale_table= ff_mpeg2_dc_scale_table[s->intra_dc_precision]; s->chroma_intra_matrix[0] = s->intra_matrix[0] = ff_mpeg2_dc_scale_table[s->intra_dc_precision][8]; - ff_convert_matrix(&s->dsp, s->q_intra_matrix, s->q_intra_matrix16, + ff_convert_matrix(s, s->q_intra_matrix, s->q_intra_matrix16, s->intra_matrix, s->intra_quant_bias, 8, 8, 1); - ff_convert_matrix(&s->dsp, s->q_chroma_intra_matrix, s->q_chroma_intra_matrix16, + ff_convert_matrix(s, s->q_chroma_intra_matrix, s->q_chroma_intra_matrix16, s->chroma_intra_matrix, s->intra_quant_bias, 8, 8, 1); s->qscale= 8; } @@ -3539,7 +3610,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) static const uint8_t y[32]={13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13}; static const uint8_t c[32]={14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; for(i=1;i<64;i++){ - int j= s->dsp.idct_permutation[ff_zigzag_direct[i]]; + int j= s->idsp.idct_permutation[ff_zigzag_direct[i]]; s->intra_matrix[j] = sp5x_quant_table[5*2+0][i]; s->chroma_intra_matrix[j] = sp5x_quant_table[5*2+1][i]; @@ -3548,20 +3619,20 @@ static int encode_picture(MpegEncContext *s, int picture_number) s->c_dc_scale_table= c; s->intra_matrix[0] = 13; s->chroma_intra_matrix[0] = 14; - ff_convert_matrix(&s->dsp, s->q_intra_matrix, s->q_intra_matrix16, + ff_convert_matrix(s, s->q_intra_matrix, s->q_intra_matrix16, s->intra_matrix, s->intra_quant_bias, 8, 8, 1); - ff_convert_matrix(&s->dsp, s->q_chroma_intra_matrix, s->q_chroma_intra_matrix16, + ff_convert_matrix(s, s->q_chroma_intra_matrix, s->q_chroma_intra_matrix16, s->chroma_intra_matrix, s->intra_quant_bias, 8, 8, 1); s->qscale= 8; } //FIXME var duplication - s->current_picture_ptr->f.key_frame = - s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; //FIXME pic_ptr - s->current_picture_ptr->f.pict_type = - s->current_picture.f.pict_type = s->pict_type; + s->current_picture_ptr->f->key_frame = + s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; //FIXME pic_ptr + s->current_picture_ptr->f->pict_type = + s->current_picture.f->pict_type = s->pict_type; - if (s->current_picture.f.key_frame) + if (s->current_picture.f->key_frame) s->picture_in_gop_number=0; s->mb_x = s->mb_y = 0; @@ -3663,7 +3734,7 @@ static int dct_quantize_trellis_c(MpegEncContext *s, uint8_t * last_length; const int lambda= s->lambda2 >> (FF_LAMBDA_SHIFT - 6); - s->dsp.fdct (block); + s->fdsp.fdct(block); if(s->dct_error_sum) s->denoise_dct(s, block); @@ -3758,7 +3829,7 @@ static int dct_quantize_trellis_c(MpegEncContext *s, int dct_coeff= FFABS(block[ scantable[i] ]); int best_score=256*256*256*120; - if (s->dsp.fdct == ff_fdct_ifast) + if (s->fdsp.fdct == ff_fdct_ifast) dct_coeff= (dct_coeff*ff_inv_aanscales[ scantable[i] ]) >> 12; zero_distortion= dct_coeff*dct_coeff; @@ -3773,7 +3844,7 @@ static int dct_quantize_trellis_c(MpegEncContext *s, if(s->out_format == FMT_H263 || s->out_format == FMT_H261){ unquant_coeff= alevel*qmul + qadd; }else{ //MPEG1 - j= s->dsp.idct_permutation[ scantable[i] ]; //FIXME optimize + j = s->idsp.idct_permutation[scantable[i]]; // FIXME: optimize if(s->mb_intra){ unquant_coeff = (int)( alevel * qscale * s->intra_matrix[j]) >> 3; unquant_coeff = (unquant_coeff - 1) | 1; @@ -3979,7 +4050,7 @@ static int messed_sign=0; #endif if(basis[0][0] == 0) - build_basis(s->dsp.idct_permutation); + build_basis(s->idsp.idct_permutation); qmul= qscale*2; qadd= (qscale-1)|1; @@ -4054,7 +4125,7 @@ STOP_TIMER("memset rem[]")} run_tab[rle_index++]=run; run=0; - s->dsp.add_8x8basis(rem, basis[j], coeff); + s->mpvencdsp.add_8x8basis(rem, basis[j], coeff); }else{ run++; } @@ -4068,7 +4139,7 @@ STOP_TIMER("init rem[]") {START_TIMER #endif for(;;){ - int best_score=s->dsp.try_8x8basis(rem, weight, basis[0], 0); + int best_score = s->mpvencdsp.try_8x8basis(rem, weight, basis[0], 0); int best_coeff=0; int best_change=0; int run2, best_unquant_change=0, analyze_gradient; @@ -4090,7 +4161,7 @@ STOP_TIMER("init rem[]") STOP_TIMER("rem*w*w")} {START_TIMER #endif - s->dsp.fdct(d1); + s->fdsp.fdct(d1); #ifdef REFINE_STATS STOP_TIMER("dct")} #endif @@ -4112,7 +4183,8 @@ STOP_TIMER("dct")} if(new_coeff >= 2048 || new_coeff < 0) continue; - score= s->dsp.try_8x8basis(rem, weight, basis[0], new_coeff - old_coeff); + score = s->mpvencdsp.try_8x8basis(rem, weight, basis[0], + new_coeff - old_coeff); if(score -100*lambda) || lambda==0); - score+= s->dsp.try_8x8basis(rem, weight, basis[j], unquant_change); + score += s->mpvencdsp.try_8x8basis(rem, weight, basis[j], + unquant_change); if(scoredsp.add_8x8basis(rem, basis[j], best_unquant_change); + s->mpvencdsp.add_8x8basis(rem, basis[j], best_unquant_change); }else{ break; } @@ -4335,7 +4408,7 @@ int ff_dct_quantize_c(MpegEncContext *s, int max=0; unsigned int threshold1, threshold2; - s->dsp.fdct (block); + s->fdsp.fdct(block); if(s->dct_error_sum) s->denoise_dct(s, block); @@ -4398,8 +4471,9 @@ int ff_dct_quantize_c(MpegEncContext *s, *overflow= s->max_qcoeff < max; //overflow might have happened /* we need this permutation so that we correct the IDCT, we only permute the !=0 elements */ - if (s->dsp.idct_permutation_type != FF_NO_IDCT_PERM) - ff_block_permute(block, s->dsp.idct_permutation, scantable, last_non_zero); + if (s->idsp.idct_permutation_type != FF_NO_IDCT_PERM) + ff_block_permute(block, s->idsp.idct_permutation, + scantable, last_non_zero); return last_non_zero; } diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c index 8398fdff9..0d3ba08de 100644 --- a/libavcodec/mpegvideo_motion.c +++ b/libavcodec/mpegvideo_motion.c @@ -26,11 +26,12 @@ #include "libavutil/avassert.h" #include "libavutil/internal.h" #include "avcodec.h" -#include "dsputil.h" #include "h261.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "mjpegenc.h" #include "msmpeg4.h" +#include "qpeldsp.h" #include static void gmc1_motion(MpegEncContext *s, @@ -71,10 +72,10 @@ static void gmc1_motion(MpegEncContext *s, } if ((motion_x | motion_y) & 7) { - s->dsp.gmc1(dest_y, ptr, linesize, 16, - motion_x & 15, motion_y & 15, 128 - s->no_rounding); - s->dsp.gmc1(dest_y + 8, ptr + 8, linesize, 16, - motion_x & 15, motion_y & 15, 128 - s->no_rounding); + s->mdsp.gmc1(dest_y, ptr, linesize, 16, + motion_x & 15, motion_y & 15, 128 - s->no_rounding); + s->mdsp.gmc1(dest_y + 8, ptr + 8, linesize, 16, + motion_x & 15, motion_y & 15, 128 - s->no_rounding); } else { int dxy; @@ -114,8 +115,8 @@ static void gmc1_motion(MpegEncContext *s, ptr = s->edge_emu_buffer; emu = 1; } - s->dsp.gmc1(dest_cb, ptr, uvlinesize, 8, - motion_x & 15, motion_y & 15, 128 - s->no_rounding); + s->mdsp.gmc1(dest_cb, ptr, uvlinesize, 8, + motion_x & 15, motion_y & 15, 128 - s->no_rounding); ptr = ref_picture[2] + offset; if (emu) { @@ -126,8 +127,8 @@ static void gmc1_motion(MpegEncContext *s, s->h_edge_pos >> 1, s->v_edge_pos >> 1); ptr = s->edge_emu_buffer; } - s->dsp.gmc1(dest_cr, ptr, uvlinesize, 8, - motion_x & 15, motion_y & 15, 128 - s->no_rounding); + s->mdsp.gmc1(dest_cr, ptr, uvlinesize, 8, + motion_x & 15, motion_y & 15, 128 - s->no_rounding); } static void gmc_motion(MpegEncContext *s, @@ -149,19 +150,19 @@ static void gmc_motion(MpegEncContext *s, oy = s->sprite_offset[0][1] + s->sprite_delta[1][0] * s->mb_x * 16 + s->sprite_delta[1][1] * s->mb_y * 16; - s->dsp.gmc(dest_y, ptr, linesize, 16, - ox, oy, - s->sprite_delta[0][0], s->sprite_delta[0][1], - s->sprite_delta[1][0], s->sprite_delta[1][1], - a + 1, (1 << (2 * a + 1)) - s->no_rounding, - s->h_edge_pos, s->v_edge_pos); - s->dsp.gmc(dest_y + 8, ptr, linesize, 16, - ox + s->sprite_delta[0][0] * 8, - oy + s->sprite_delta[1][0] * 8, - s->sprite_delta[0][0], s->sprite_delta[0][1], - s->sprite_delta[1][0], s->sprite_delta[1][1], - a + 1, (1 << (2 * a + 1)) - s->no_rounding, - s->h_edge_pos, s->v_edge_pos); + s->mdsp.gmc(dest_y, ptr, linesize, 16, + ox, oy, + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + a + 1, (1 << (2 * a + 1)) - s->no_rounding, + s->h_edge_pos, s->v_edge_pos); + s->mdsp.gmc(dest_y + 8, ptr, linesize, 16, + ox + s->sprite_delta[0][0] * 8, + oy + s->sprite_delta[1][0] * 8, + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + a + 1, (1 << (2 * a + 1)) - s->no_rounding, + s->h_edge_pos, s->v_edge_pos); if (CONFIG_GRAY && s->flags & CODEC_FLAG_GRAY) return; @@ -172,20 +173,20 @@ static void gmc_motion(MpegEncContext *s, s->sprite_delta[1][1] * s->mb_y * 8; ptr = ref_picture[1]; - s->dsp.gmc(dest_cb, ptr, uvlinesize, 8, - ox, oy, - s->sprite_delta[0][0], s->sprite_delta[0][1], - s->sprite_delta[1][0], s->sprite_delta[1][1], - a + 1, (1 << (2 * a + 1)) - s->no_rounding, - s->h_edge_pos >> 1, s->v_edge_pos >> 1); + s->mdsp.gmc(dest_cb, ptr, uvlinesize, 8, + ox, oy, + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + a + 1, (1 << (2 * a + 1)) - s->no_rounding, + s->h_edge_pos >> 1, s->v_edge_pos >> 1); ptr = ref_picture[2]; - s->dsp.gmc(dest_cr, ptr, uvlinesize, 8, - ox, oy, - s->sprite_delta[0][0], s->sprite_delta[0][1], - s->sprite_delta[1][0], s->sprite_delta[1][1], - a + 1, (1 << (2 * a + 1)) - s->no_rounding, - s->h_edge_pos >> 1, s->v_edge_pos >> 1); + s->mdsp.gmc(dest_cr, ptr, uvlinesize, 8, + ox, oy, + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + a + 1, (1 << (2 * a + 1)) - s->no_rounding, + s->h_edge_pos >> 1, s->v_edge_pos >> 1); } static inline int hpel_motion(MpegEncContext *s, @@ -252,8 +253,8 @@ void mpeg_motion_internal(MpegEncContext *s, #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; + linesize = s->current_picture.f->linesize[0] << field_based; + uvlinesize = s->current_picture.f->linesize[1] << field_based; dxy = ((motion_y & 1) << 1) | (motion_x & 1); src_x = s->mb_x * 16 + (motion_x >> 1); @@ -322,19 +323,20 @@ void mpeg_motion_internal(MpegEncContext *s, 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, + uint8_t *ubuf = s->edge_emu_buffer + 18 * s->linesize; + uint8_t *vbuf = ubuf + 9 * s->uvlinesize; + s->vdsp.emulated_edge_mc(ubuf, 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->vdsp.emulated_edge_mc(vbuf, 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; + ptr_cb = ubuf; + ptr_cr = vbuf; } } @@ -403,7 +405,7 @@ static void mpeg_motion_field(MpegEncContext *s, uint8_t *dest_y, motion_x, motion_y, h, 0, mb_y); } -// FIXME move to dsputil, avg variant, 16x16 version +// FIXME: SIMDify, avg variant, 16x16 version static inline void put_obmc(uint8_t *dst, uint8_t *src[5], int stride) { int x; @@ -543,19 +545,20 @@ static inline void qpel_motion(MpegEncContext *s, 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, + uint8_t *ubuf = s->edge_emu_buffer + 18 * s->linesize; + uint8_t *vbuf = ubuf + 9 * s->uvlinesize; + s->vdsp.emulated_edge_mc(ubuf, 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->vdsp.emulated_edge_mc(vbuf, 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; + ptr_cb = ubuf; + ptr_cr = vbuf; } } @@ -898,7 +901,7 @@ static av_always_inline void MPV_motion_internal(MpegEncContext *s, } else { if ( s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != AV_PICTURE_TYPE_B && !s->first_field || !ref_picture[0]) { - ref_picture = s->current_picture_ptr->f.data; + ref_picture = s->current_picture_ptr->f->data; } mpeg_motion(s, dest_y, dest_cb, dest_cr, @@ -915,7 +918,7 @@ static av_always_inline void MPV_motion_internal(MpegEncContext *s, || s->pict_type == AV_PICTURE_TYPE_B || s->first_field) && ref_picture[0]) { ref2picture = ref_picture; } else { - ref2picture = s->current_picture_ptr->f.data; + ref2picture = s->current_picture_ptr->f->data; } mpeg_motion(s, dest_y, dest_cb, dest_cr, @@ -942,7 +945,7 @@ static av_always_inline void MPV_motion_internal(MpegEncContext *s, } } else { if (!ref_picture[0]) { - ref_picture = s->current_picture_ptr->f.data; + ref_picture = s->current_picture_ptr->f->data; } for (i = 0; i < 2; i++) { mpeg_motion(s, dest_y, dest_cb, dest_cr, @@ -957,7 +960,7 @@ static av_always_inline void MPV_motion_internal(MpegEncContext *s, /* opposite parity is always in the same frame if this is * second field */ if (!s->first_field) { - ref_picture = s->current_picture_ptr->f.data; + ref_picture = s->current_picture_ptr->f->data; } } } diff --git a/libavcodec/mpegvideo_xvmc.c b/libavcodec/mpegvideo_xvmc.c index 9fc97cb0f..7d7f7ecb9 100644 --- a/libavcodec/mpegvideo_xvmc.c +++ b/libavcodec/mpegvideo_xvmc.c @@ -23,6 +23,7 @@ #include #include "avcodec.h" +#include "mpegutils.h" #include "mpegvideo.h" #undef NDEBUG @@ -41,7 +42,7 @@ */ void ff_xvmc_init_block(MpegEncContext *s) { - struct xvmc_pix_fmt *render = (struct xvmc_pix_fmt*)s->current_picture.f.data[2]; + struct xvmc_pix_fmt *render = (struct xvmc_pix_fmt*)s->current_picture.f->data[2]; assert(render && render->xvmc_id == AV_XVMC_ID); s->block = (int16_t (*)[64])(render->data_blocks + render->next_free_data_block_num * 64); @@ -86,7 +87,7 @@ void ff_xvmc_pack_pblocks(MpegEncContext *s, int cbp) static int ff_xvmc_field_start(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size) { struct MpegEncContext *s = avctx->priv_data; - struct xvmc_pix_fmt *last, *next, *render = (struct xvmc_pix_fmt*)s->current_picture.f.data[2]; + struct xvmc_pix_fmt *last, *next, *render = (struct xvmc_pix_fmt*)s->current_picture.f->data[2]; const int mb_block_count = 4 + (1 << s->chroma_format); assert(avctx); @@ -126,7 +127,7 @@ static int ff_xvmc_field_start(AVCodecContext *avctx, const uint8_t *buf, uint32 case AV_PICTURE_TYPE_I: return 0; // no prediction from other frames case AV_PICTURE_TYPE_B: - next = (struct xvmc_pix_fmt*)s->next_picture.f.data[2]; + next = (struct xvmc_pix_fmt*)s->next_picture.f->data[2]; if (!next) return -1; if (next->xvmc_id != AV_XVMC_ID) @@ -134,7 +135,7 @@ static int ff_xvmc_field_start(AVCodecContext *avctx, const uint8_t *buf, uint32 render->p_future_surface = next->p_surface; // no return here, going to set forward prediction case AV_PICTURE_TYPE_P: - last = (struct xvmc_pix_fmt*)s->last_picture.f.data[2]; + last = (struct xvmc_pix_fmt*)s->last_picture.f->data[2]; if (!last) last = render; // predict second field from the first if (last->xvmc_id != AV_XVMC_ID) @@ -155,7 +156,7 @@ return -1; static int ff_xvmc_field_end(AVCodecContext *avctx) { struct MpegEncContext *s = avctx->priv_data; - struct xvmc_pix_fmt *render = (struct xvmc_pix_fmt*)s->current_picture.f.data[2]; + struct xvmc_pix_fmt *render = (struct xvmc_pix_fmt*)s->current_picture.f->data[2]; assert(render); if (render->filled_mv_blocks_num > 0) @@ -197,7 +198,7 @@ static void ff_xvmc_decode_mb(struct MpegEncContext *s) s->current_picture.qscale_table[mb_xy] = s->qscale; // start of XVMC-specific code - render = (struct xvmc_pix_fmt*)s->current_picture.f.data[2]; + render = (struct xvmc_pix_fmt*)s->current_picture.f->data[2]; assert(render); assert(render->xvmc_id == AV_XVMC_ID); assert(render->mv_blocks); @@ -319,7 +320,7 @@ static void ff_xvmc_decode_mb(struct MpegEncContext *s) if (s->mb_intra && (render->idct || !render->unsigned_intra)) *s->pblocks[i][0] -= 1 << 10; if (!render->idct) { - s->dsp.idct(*s->pblocks[i]); + s->idsp.idct(*s->pblocks[i]); /* It is unclear if MC hardware requires pixel diff values to be * in the range [-255;255]. TODO: Clipping if such hardware is * ever found. As of now it would only be an unnecessary diff --git a/libavcodec/mpegvideodsp.c b/libavcodec/mpegvideodsp.c new file mode 100644 index 000000000..a58e45ad4 --- /dev/null +++ b/libavcodec/mpegvideodsp.c @@ -0,0 +1,119 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "mpegvideodsp.h" + +static void gmc1_c(uint8_t *dst, uint8_t *src, int stride, int h, + int x16, int y16, int rounder) +{ + const int A = (16 - x16) * (16 - y16); + const int B = (x16) * (16 - y16); + const int C = (16 - x16) * (y16); + const int D = (x16) * (y16); + int i; + + for (i = 0; i < h; i++) { + dst[0] = (A * src[0] + B * src[1] + C * src[stride + 0] + D * src[stride + 1] + rounder) >> 8; + dst[1] = (A * src[1] + B * src[2] + C * src[stride + 1] + D * src[stride + 2] + rounder) >> 8; + dst[2] = (A * src[2] + B * src[3] + C * src[stride + 2] + D * src[stride + 3] + rounder) >> 8; + dst[3] = (A * src[3] + B * src[4] + C * src[stride + 3] + D * src[stride + 4] + rounder) >> 8; + dst[4] = (A * src[4] + B * src[5] + C * src[stride + 4] + D * src[stride + 5] + rounder) >> 8; + dst[5] = (A * src[5] + B * src[6] + C * src[stride + 5] + D * src[stride + 6] + rounder) >> 8; + dst[6] = (A * src[6] + B * src[7] + C * src[stride + 6] + D * src[stride + 7] + rounder) >> 8; + dst[7] = (A * src[7] + B * src[8] + C * src[stride + 7] + D * src[stride + 8] + rounder) >> 8; + dst += stride; + src += stride; + } +} + +void ff_gmc_c(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, int shift, int r, + int width, int height) +{ + int y, vx, vy; + const int s = 1 << shift; + + width--; + height--; + + for (y = 0; y < h; y++) { + int x; + + vx = ox; + vy = oy; + for (x = 0; x < 8; x++) { // FIXME: optimize + int index; + int src_x = vx >> 16; + int src_y = vy >> 16; + int frac_x = src_x & (s - 1); + int frac_y = src_y & (s - 1); + + src_x >>= shift; + src_y >>= shift; + + if ((unsigned) src_x < width) { + if ((unsigned) src_y < height) { + index = src_x + src_y * stride; + dst[y * stride + x] = + ((src[index] * (s - frac_x) + + src[index + 1] * frac_x) * (s - frac_y) + + (src[index + stride] * (s - frac_x) + + src[index + stride + 1] * frac_x) * frac_y + + r) >> (shift * 2); + } else { + index = src_x + av_clip(src_y, 0, height) * stride; + dst[y * stride + x] = + ((src[index] * (s - frac_x) + + src[index + 1] * frac_x) * s + + r) >> (shift * 2); + } + } else { + if ((unsigned) src_y < height) { + index = av_clip(src_x, 0, width) + src_y * stride; + dst[y * stride + x] = + ((src[index] * (s - frac_y) + + src[index + stride] * frac_y) * s + + r) >> (shift * 2); + } else { + index = av_clip(src_x, 0, width) + + av_clip(src_y, 0, height) * stride; + dst[y * stride + x] = src[index]; + } + } + + vx += dxx; + vy += dyx; + } + ox += dxy; + oy += dyy; + } +} + +av_cold void ff_mpegvideodsp_init(MpegVideoDSPContext *c) +{ + c->gmc1 = gmc1_c; + c->gmc = ff_gmc_c; + + if (ARCH_PPC) + ff_mpegvideodsp_init_ppc(c); + if (ARCH_X86) + ff_mpegvideodsp_init_x86(c); +} diff --git a/libavcodec/mpegvideodsp.h b/libavcodec/mpegvideodsp.h new file mode 100644 index 000000000..293e2548d --- /dev/null +++ b/libavcodec/mpegvideodsp.h @@ -0,0 +1,47 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MPEGVIDEODSP_H +#define AVCODEC_MPEGVIDEODSP_H + +#include + +void ff_gmc_c(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, int shift, int r, + int width, int height); + +typedef struct MpegVideoDSPContext { + /** + * translational global motion compensation. + */ + void (*gmc1)(uint8_t *dst /* align 8 */, uint8_t *src /* align 1 */, + int srcStride, int h, int x16, int y16, int rounder); + /** + * global motion compensation. + */ + void (*gmc)(uint8_t *dst /* align 8 */, uint8_t *src /* align 1 */, + int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, + int shift, int r, int width, int height); +} MpegVideoDSPContext; + +void ff_mpegvideodsp_init(MpegVideoDSPContext *c); +void ff_mpegvideodsp_init_ppc(MpegVideoDSPContext *c); +void ff_mpegvideodsp_init_x86(MpegVideoDSPContext *c); + +#endif /* AVCODEC_MPEGVIDEODSP_H */ diff --git a/libavcodec/mpegvideoencdsp.c b/libavcodec/mpegvideoencdsp.c new file mode 100644 index 000000000..10ad369a6 --- /dev/null +++ b/libavcodec/mpegvideoencdsp.c @@ -0,0 +1,179 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "config.h" +#include "libavutil/avassert.h" +#include "libavutil/attributes.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "dsputil.h" +#include "imgconvert.h" +#include "mpegvideoencdsp.h" + +static int try_8x8basis_c(int16_t rem[64], int16_t weight[64], + int16_t basis[64], int scale) +{ + int i; + unsigned int sum = 0; + + for (i = 0; i < 8 * 8; i++) { + int b = rem[i] + ((basis[i] * scale + + (1 << (BASIS_SHIFT - RECON_SHIFT - 1))) >> + (BASIS_SHIFT - RECON_SHIFT)); + int w = weight[i]; + b >>= RECON_SHIFT; + av_assert2(-512 < b && b < 512); + + sum += (w * b) * (w * b) >> 4; + } + return sum >> 2; +} + +static void add_8x8basis_c(int16_t rem[64], int16_t basis[64], int scale) +{ + int i; + + for (i = 0; i < 8 * 8; i++) + rem[i] += (basis[i] * scale + + (1 << (BASIS_SHIFT - RECON_SHIFT - 1))) >> + (BASIS_SHIFT - RECON_SHIFT); +} + +static int pix_sum_c(uint8_t *pix, int line_size) +{ + int s = 0, i, j; + + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j += 8) { + s += pix[0]; + s += pix[1]; + s += pix[2]; + s += pix[3]; + s += pix[4]; + s += pix[5]; + s += pix[6]; + s += pix[7]; + pix += 8; + } + pix += line_size - 16; + } + return s; +} + +static int pix_norm1_c(uint8_t *pix, int line_size) +{ + int s = 0, i, j; + uint32_t *sq = ff_square_tab + 256; + + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j += 8) { +#if 0 + s += sq[pix[0]]; + s += sq[pix[1]]; + s += sq[pix[2]]; + s += sq[pix[3]]; + s += sq[pix[4]]; + s += sq[pix[5]]; + s += sq[pix[6]]; + s += sq[pix[7]]; +#else +#if HAVE_FAST_64BIT + register uint64_t x = *(uint64_t *) pix; + s += sq[x & 0xff]; + s += sq[(x >> 8) & 0xff]; + s += sq[(x >> 16) & 0xff]; + s += sq[(x >> 24) & 0xff]; + s += sq[(x >> 32) & 0xff]; + s += sq[(x >> 40) & 0xff]; + s += sq[(x >> 48) & 0xff]; + s += sq[(x >> 56) & 0xff]; +#else + register uint32_t x = *(uint32_t *) pix; + s += sq[x & 0xff]; + s += sq[(x >> 8) & 0xff]; + s += sq[(x >> 16) & 0xff]; + s += sq[(x >> 24) & 0xff]; + x = *(uint32_t *) (pix + 4); + s += sq[x & 0xff]; + s += sq[(x >> 8) & 0xff]; + s += sq[(x >> 16) & 0xff]; + s += sq[(x >> 24) & 0xff]; +#endif +#endif + pix += 8; + } + pix += line_size - 16; + } + return s; +} + +/* draw the edges of width 'w' of an image of size width, height */ +// FIXME: Check that this is OK for MPEG-4 interlaced. +static void draw_edges_8_c(uint8_t *buf, int wrap, int width, int height, + int w, int h, int sides) +{ + uint8_t *ptr = buf, *last_line; + int i; + + /* left and right */ + for (i = 0; i < height; i++) { + memset(ptr - w, ptr[0], w); + memset(ptr + width, ptr[width - 1], w); + ptr += wrap; + } + + /* top and bottom + corners */ + buf -= w; + last_line = buf + (height - 1) * wrap; + if (sides & EDGE_TOP) + for (i = 0; i < h; i++) + // top + memcpy(buf - (i + 1) * wrap, buf, width + w + w); + if (sides & EDGE_BOTTOM) + for (i = 0; i < h; i++) + // bottom + memcpy(last_line + (i + 1) * wrap, last_line, width + w + w); +} + +av_cold void ff_mpegvideoencdsp_init(MpegvideoEncDSPContext *c, + AVCodecContext *avctx) +{ + c->try_8x8basis = try_8x8basis_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->pix_sum = pix_sum_c; + c->pix_norm1 = pix_norm1_c; + + c->draw_edges = draw_edges_8_c; + + if (ARCH_ARM) + ff_mpegvideoencdsp_init_arm(c, avctx); + if (ARCH_PPC) + ff_mpegvideoencdsp_init_ppc(c, avctx); + if (ARCH_X86) + ff_mpegvideoencdsp_init_x86(c, avctx); +} diff --git a/libavcodec/mpegvideoencdsp.h b/libavcodec/mpegvideoencdsp.h new file mode 100644 index 000000000..e12f4c6a3 --- /dev/null +++ b/libavcodec/mpegvideoencdsp.h @@ -0,0 +1,56 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MPEGVIDEOENCDSP_H +#define AVCODEC_MPEGVIDEOENCDSP_H + +#include + +#include "avcodec.h" + +#define BASIS_SHIFT 16 +#define RECON_SHIFT 6 + +#define EDGE_TOP 1 +#define EDGE_BOTTOM 2 + +typedef struct MpegvideoEncDSPContext { + int (*try_8x8basis)(int16_t rem[64], int16_t weight[64], + int16_t basis[64], int scale); + void (*add_8x8basis)(int16_t rem[64], int16_t basis[64], int scale); + + int (*pix_sum)(uint8_t *pix, int line_size); + int (*pix_norm1)(uint8_t *pix, int line_size); + + void (*shrink[4])(uint8_t *dst, int dst_wrap, const uint8_t *src, + int src_wrap, int width, int height); + + void (*draw_edges)(uint8_t *buf, int wrap, int width, int height, + int w, int h, int sides); +} MpegvideoEncDSPContext; + +void ff_mpegvideoencdsp_init(MpegvideoEncDSPContext *c, + AVCodecContext *avctx); +void ff_mpegvideoencdsp_init_arm(MpegvideoEncDSPContext *c, + AVCodecContext *avctx); +void ff_mpegvideoencdsp_init_ppc(MpegvideoEncDSPContext *c, + AVCodecContext *avctx); +void ff_mpegvideoencdsp_init_x86(MpegvideoEncDSPContext *c, + AVCodecContext *avctx); + +#endif /* AVCODEC_MPEGVIDEOENCDSP_H */ diff --git a/libavcodec/mqc.c b/libavcodec/mqc.c index f8294cd54..f2d1e3b83 100644 --- a/libavcodec/mqc.c +++ b/libavcodec/mqc.c @@ -28,6 +28,8 @@ #include #include +#include "libavutil/attributes.h" + #include "mqc.h" /* MQ coder context state structure */ @@ -92,7 +94,7 @@ uint16_t ff_mqc_qe [2 * 47]; uint8_t ff_mqc_nlps[2 * 47]; uint8_t ff_mqc_nmps[2 * 47]; -void ff_mqc_init_context_tables(void) +void av_cold ff_mqc_init_context_tables(void) { int i; for (i = 0; i < 47; i++) { diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index b071d74c9..7300af316 100644 --- a/libavcodec/msmpeg4.c +++ b/libavcodec/msmpeg4.c @@ -28,7 +28,7 @@ */ #include "avcodec.h" -#include "dsputil.h" +#include "idctdsp.h" #include "mpegvideo.h" #include "msmpeg4.h" #include "libavutil/x86/asm.h" @@ -138,10 +138,10 @@ av_cold void ff_msmpeg4_common_init(MpegEncContext *s) if(s->msmpeg4_version>=4){ - ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , ff_wmv1_scantable[1]); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, ff_wmv1_scantable[2]); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, ff_wmv1_scantable[3]); - ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , ff_wmv1_scantable[0]); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_wmv1_scantable[1]); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_wmv1_scantable[2]); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_wmv1_scantable[3]); + ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_wmv1_scantable[0]); } //Note the default tables are set in common_init in mpegvideo.c @@ -276,10 +276,10 @@ int ff_msmpeg4_pred_dc(MpegEncContext *s, int n, int bs = 8 >> s->avctx->lowres; if(n<4){ wrap= s->linesize; - dest= s->current_picture.f.data[0] + (((n >> 1) + 2*s->mb_y) * bs* wrap ) + ((n & 1) + 2*s->mb_x) * bs; + dest= s->current_picture.f->data[0] + (((n >> 1) + 2*s->mb_y) * bs* wrap ) + ((n & 1) + 2*s->mb_x) * bs; }else{ wrap= s->uvlinesize; - dest= s->current_picture.f.data[n - 3] + (s->mb_y * bs * wrap) + s->mb_x * bs; + dest= s->current_picture.f->data[n - 3] + (s->mb_y * bs * wrap) + s->mb_x * bs; } if(s->mb_x==0) a= (1024 + (scale>>1))/scale; else a= get_dc(dest-bs, wrap, scale*8>>(2*s->avctx->lowres), bs); diff --git a/libavcodec/msmpeg4.h b/libavcodec/msmpeg4.h index a72388819..db77ce1d7 100644 --- a/libavcodec/msmpeg4.h +++ b/libavcodec/msmpeg4.h @@ -59,10 +59,12 @@ int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]); #define CONFIG_MSMPEG4_DECODER (CONFIG_MSMPEG4V1_DECODER || \ CONFIG_MSMPEG4V2_DECODER || \ CONFIG_MSMPEG4V3_DECODER || \ + CONFIG_WMV1_DECODER || \ CONFIG_WMV2_DECODER || \ CONFIG_VC1_DECODER) #define CONFIG_MSMPEG4_ENCODER (CONFIG_MSMPEG4V2_ENCODER || \ CONFIG_MSMPEG4V3_ENCODER || \ + CONFIG_WMV1_ENCODER || \ CONFIG_WMV2_ENCODER) #endif /* AVCODEC_MSMPEG4_H */ diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c index a5845d8a0..94ea3c27b 100644 --- a/libavcodec/msmpeg4dec.c +++ b/libavcodec/msmpeg4dec.c @@ -23,7 +23,7 @@ */ #include "avcodec.h" -#include "dsputil.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "msmpeg4.h" #include "libavutil/imgutils.h" @@ -179,7 +179,7 @@ static int msmpeg4v12_decode_mb(MpegEncContext *s, int16_t block[6][64]) *mb_type_ptr = MB_TYPE_INTRA; } - s->dsp.clear_blocks(s->block[0]); + 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) { @@ -270,7 +270,7 @@ static int msmpeg4v34_decode_mb(MpegEncContext *s, int16_t block[6][64]) } } - s->dsp.clear_blocks(s->block[0]); + 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) { @@ -922,7 +922,10 @@ AVCodec ff_msmpeg4v1_decoder = { .decode = ff_h263_decode_frame, .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, .max_lowres = 3, - .pix_fmts = ff_pixfmt_list_420, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, }; AVCodec ff_msmpeg4v2_decoder = { @@ -936,7 +939,10 @@ AVCodec ff_msmpeg4v2_decoder = { .decode = ff_h263_decode_frame, .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, .max_lowres = 3, - .pix_fmts = ff_pixfmt_list_420, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, }; AVCodec ff_msmpeg4v3_decoder = { @@ -950,7 +956,10 @@ AVCodec ff_msmpeg4v3_decoder = { .decode = ff_h263_decode_frame, .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, .max_lowres = 3, - .pix_fmts = ff_pixfmt_list_420, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, }; AVCodec ff_wmv1_decoder = { @@ -964,5 +973,8 @@ AVCodec ff_wmv1_decoder = { .decode = ff_h263_decode_frame, .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, .max_lowres = 3, - .pix_fmts = ff_pixfmt_list_420, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, }; diff --git a/libavcodec/mss12.c b/libavcodec/mss12.c index b522e4a40..7d54d2917 100644 --- a/libavcodec/mss12.c +++ b/libavcodec/mss12.c @@ -23,6 +23,8 @@ * Common functions for Microsoft Screen 1 and 2 */ +#include + #include "libavutil/intfloat.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" @@ -573,7 +575,7 @@ av_cold int ff_mss12_decode_init(MSS12Context *c, int version, if (AV_RB32(avctx->extradata) < avctx->extradata_size) { av_log(avctx, AV_LOG_ERROR, - "Insufficient extradata size: expected %d got %d\n", + "Insufficient extradata size: expected %"PRIu32" got %d\n", AV_RB32(avctx->extradata), avctx->extradata_size); return AVERROR_INVALIDDATA; @@ -592,7 +594,7 @@ av_cold int ff_mss12_decode_init(MSS12Context *c, int version, return AVERROR_INVALIDDATA; } - av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d\n", + av_log(avctx, AV_LOG_DEBUG, "Encoder version %"PRIu32".%"PRIu32"\n", AV_RB32(avctx->extradata + 4), AV_RB32(avctx->extradata + 8)); if (version != AV_RB32(avctx->extradata + 4) > 1) { av_log(avctx, AV_LOG_ERROR, @@ -609,13 +611,13 @@ av_cold int ff_mss12_decode_init(MSS12Context *c, int version, } av_log(avctx, AV_LOG_DEBUG, "%d free colour(s)\n", c->free_colours); - av_log(avctx, AV_LOG_DEBUG, "Display dimensions %dx%d\n", + av_log(avctx, AV_LOG_DEBUG, "Display dimensions %"PRIu32"x%"PRIu32"\n", AV_RB32(avctx->extradata + 12), AV_RB32(avctx->extradata + 16)); av_log(avctx, AV_LOG_DEBUG, "Coded dimensions %dx%d\n", avctx->coded_width, avctx->coded_height); av_log(avctx, AV_LOG_DEBUG, "%g frames per second\n", av_int2float(AV_RB32(avctx->extradata + 28))); - av_log(avctx, AV_LOG_DEBUG, "Bitrate %d bps\n", + av_log(avctx, AV_LOG_DEBUG, "Bitrate %"PRIu32" bps\n", AV_RB32(avctx->extradata + 32)); av_log(avctx, AV_LOG_DEBUG, "Max. lead time %g ms\n", av_int2float(AV_RB32(avctx->extradata + 36))); diff --git a/libavcodec/mss2.c b/libavcodec/mss2.c index 505c981a4..35c5d2722 100644 --- a/libavcodec/mss2.c +++ b/libavcodec/mss2.c @@ -26,7 +26,9 @@ #include "libavutil/avassert.h" #include "error_resilience.h" #include "internal.h" +#include "mpeg_er.h" #include "msmpeg4data.h" +#include "qpeldsp.h" #include "vc1.h" #include "mss12.h" #include "mss2dsp.h" @@ -37,6 +39,7 @@ typedef struct MSS2Context { AVFrame *last_pic; MSS12Context c; MSS2DSPContext dsp; + QpelDSPContext qdsp; SliceContext sc[2]; } MSS2Context; @@ -417,7 +420,7 @@ static int decode_wmv9(AVCodecContext *avctx, const uint8_t *buf, int buf_size, ff_MPV_frame_end(s); - f = &s->current_picture.f; + f = s->current_picture.f; if (v->respic == 3) { ctx->dsp.upsample_plane(f->data[0], f->linesize[0], w, h); @@ -786,8 +789,8 @@ static av_cold int wmv9_init(AVCodecContext *avctx) return ret; /* error concealment */ - v->s.me.qpel_put = v->s.dsp.put_qpel_pixels_tab; - v->s.me.qpel_avg = v->s.dsp.avg_qpel_pixels_tab; + v->s.me.qpel_put = v->s.qdsp.put_qpel_pixels_tab; + v->s.me.qpel_avg = v->s.qdsp.avg_qpel_pixels_tab; return 0; } @@ -827,6 +830,7 @@ static av_cold int mss2_decode_init(AVCodecContext *avctx) return ret; } ff_mss2dsp_init(&ctx->dsp); + ff_qpeldsp_init(&ctx->qdsp); avctx->pix_fmt = c->free_colours == 127 ? AV_PIX_FMT_RGB555 : AV_PIX_FMT_RGB24; diff --git a/libavcodec/mss3.c b/libavcodec/mss3.c index c6bb83804..075685b90 100644 --- a/libavcodec/mss3.c +++ b/libavcodec/mss3.c @@ -26,8 +26,8 @@ #include "avcodec.h" #include "bytestream.h" -#include "dsputil.h" #include "internal.h" +#include "mathops.h" #include "mss34dsp.h" #define HEADER_SIZE 27 diff --git a/libavcodec/mss4.c b/libavcodec/mss4.c index 6dadf0731..c5b8e07aa 100644 --- a/libavcodec/mss4.c +++ b/libavcodec/mss4.c @@ -27,7 +27,6 @@ #include "avcodec.h" #include "bytestream.h" -#include "dsputil.h" #include "get_bits.h" #include "internal.h" #include "mss34dsp.h" diff --git a/libavcodec/msvideo1enc.c b/libavcodec/msvideo1enc.c index b27eadf06..6852c9868 100644 --- a/libavcodec/msvideo1enc.c +++ b/libavcodec/msvideo1enc.c @@ -58,7 +58,7 @@ enum MSV1Mode{ #define SKIP_PREFIX 0x8400 #define SKIPS_MAX 0x03FF -#define MKRGB555(in, off) ((in[off] << 10) | (in[off + 1] << 5) | (in[off + 2])) +#define MKRGB555(in, off) (((in)[off] << 10) | ((in)[(off) + 1] << 5) | ((in)[(off) + 2])) static const int remap[16] = { 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15 }; diff --git a/libavcodec/mvcdec.c b/libavcodec/mvcdec.c index 2cc7735cf..69f0ee259 100644 --- a/libavcodec/mvcdec.c +++ b/libavcodec/mvcdec.c @@ -25,6 +25,7 @@ */ #include "libavutil/intreadwrite.h" + #include "avcodec.h" #include "bytestream.h" #include "internal.h" @@ -37,8 +38,8 @@ typedef struct MvcContext { static av_cold int mvc_decode_init(AVCodecContext *avctx) { MvcContext *s = avctx->priv_data; - int width = avctx->width; - int height = avctx->height; + int width = avctx->width; + int height = avctx->height; int ret; if (avctx->codec_id == AV_CODEC_ID_MVC1) { @@ -50,62 +51,60 @@ static av_cold int mvc_decode_init(AVCodecContext *avctx) if ((ret = ff_set_dimensions(avctx, width, height)) < 0) return ret; - avctx->pix_fmt = (avctx->codec_id == AV_CODEC_ID_MVC1) ? AV_PIX_FMT_RGB555 : AV_PIX_FMT_BGRA; - s->frame = av_frame_alloc(); + avctx->pix_fmt = (avctx->codec_id == AV_CODEC_ID_MVC1) ? AV_PIX_FMT_RGB555 + : AV_PIX_FMT_RGB32; + s->frame = av_frame_alloc(); if (!s->frame) return AVERROR(ENOMEM); - s->vflip = avctx->extradata_size >= 9 && !memcmp(avctx->extradata + avctx->extradata_size - 9, "BottomUp", 9); + s->vflip = avctx->extradata_size >= 9 && + !memcmp(avctx->extradata + avctx->extradata_size - 9, "BottomUp", 9); return 0; } -static int decode_mvc1(AVCodecContext *avctx, GetByteContext *gb, uint8_t *dst_start, int width, int height, int linesize) +static int decode_mvc1(AVCodecContext *avctx, GetByteContext *gb, + uint8_t *dst_start, int width, int height, int linesize) { uint8_t *dst; uint16_t v[8]; int mask, x, y, i; - x = y= 0; - while (bytestream2_get_bytes_left(gb) >= 6) { - mask = bytestream2_get_be16u(gb); - v[0] = bytestream2_get_be16u(gb); - v[1] = bytestream2_get_be16u(gb); - if ((v[0] & 0x8000)) { - if (bytestream2_get_bytes_left(gb) < 12) { - av_log(avctx, AV_LOG_WARNING, "buffer overflow\n"); - return AVERROR_INVALIDDATA; + for (y = 0; y < height; y += 4) { + for (x = 0; x < width; x += 4) { + if (bytestream2_get_bytes_left(gb) < 6) + return 0; + + mask = bytestream2_get_be16u(gb); + v[0] = bytestream2_get_be16u(gb); + v[1] = bytestream2_get_be16u(gb); + if ((v[0] & 0x8000)) { + if (bytestream2_get_bytes_left(gb) < 12) { + av_log(avctx, AV_LOG_WARNING, "buffer overflow\n"); + return AVERROR_INVALIDDATA; + } + for (i = 2; i < 8; i++) + v[i] = bytestream2_get_be16u(gb); + } else { + v[2] = v[4] = v[6] = v[0]; + v[3] = v[5] = v[7] = v[1]; } - for (i = 2; i < 8; i++) - v[i] = bytestream2_get_be16u(gb); - } else { - v[2] = v[4] = v[6] = v[0]; - v[3] = v[5] = v[7] = v[1]; - } -#define PIX16(target, true, false) \ - i = (mask & target) ? true : false; \ - AV_WN16A(dst, (v[i] & 0x7C00) | (v[i] & 0x3E0) | (v[i] & 0x1F)); \ - dst += 2; +#define PIX16(target, true, false) \ + i = (mask & target) ? true : false; \ + AV_WN16A(dst, v[i] & 0x7FFF); \ + dst += 2; -#define ROW16(row, a1, a0, b1, b0) \ - dst = dst_start + (y + row) * linesize + x * 2; \ - PIX16(1 << (row * 4), a1, a0) \ - PIX16(1 << (row * 4 + 1), a1, a0) \ - PIX16(1 << (row * 4 + 2), b1, b0) \ - PIX16(1 << (row * 4 + 3), b1, b0) +#define ROW16(row, a1, a0, b1, b0) \ + dst = dst_start + (y + row) * linesize + x * 2; \ + PIX16(1 << (row * 4), a1, a0) \ + PIX16(1 << (row * 4 + 1), a1, a0) \ + PIX16(1 << (row * 4 + 2), b1, b0) \ + PIX16(1 << (row * 4 + 3), b1, b0) - ROW16(0, 0, 1, 2, 3); - ROW16(1, 0, 1, 2, 3); - ROW16(2, 4, 5, 6, 7); - ROW16(3, 4, 5, 6, 7); - - x += 4; - if (x >= width) { - y += 4; - if (y >= height) { - break; - } - x = 0; + ROW16(0, 0, 1, 2, 3); + ROW16(1, 0, 1, 2, 3); + ROW16(2, 4, 5, 6, 7); + ROW16(3, 4, 5, 6, 7); } } return 0; @@ -119,24 +118,26 @@ static void set_4x4_block(uint8_t *dst, int linesize, uint32_t pixel) AV_WN32A(dst + j * linesize + i * 4, pixel); } -#define PIX32(target, true, false) \ - AV_WN32A(dst, (mask & target) ? v[true] : v[false]); \ +#define PIX32(target, true, false) \ + AV_WN32A(dst, (mask & target) ? v[true] : v[false]); \ dst += 4; -#define ROW32(row, a1, a0, b1, b0) \ - dst = dst_start + (y + row) * linesize + x * 4; \ - PIX32(1 << (row * 4), a1, a0) \ - PIX32(1 << (row * 4 + 1), a1, a0) \ - PIX32(1 << (row * 4 + 2), b1, b0) \ +#define ROW32(row, a1, a0, b1, b0) \ + dst = dst_start + (y + row) * linesize + x * 4; \ + PIX32(1 << (row * 4), a1, a0) \ + PIX32(1 << (row * 4 + 1), a1, a0) \ + PIX32(1 << (row * 4 + 2), b1, b0) \ PIX32(1 << (row * 4 + 3), b1, b0) -#define MVC2_BLOCK \ - ROW32(0, 1, 0, 3, 2); \ - ROW32(1, 1, 0, 3, 2); \ - ROW32(2, 5, 4, 7, 6); \ +#define MVC2_BLOCK \ + ROW32(0, 1, 0, 3, 2); \ + ROW32(1, 1, 0, 3, 2); \ + ROW32(2, 5, 4, 7, 6); \ ROW32(3, 5, 4, 7, 6); -static int decode_mvc2(AVCodecContext *avctx, GetByteContext *gb, uint8_t *dst_start, int width, int height, int linesize, int vflip) +static int decode_mvc2(AVCodecContext *avctx, GetByteContext *gb, + uint8_t *dst_start, int width, int height, + int linesize, int vflip) { uint8_t *dst; uint32_t color[128], v[8]; @@ -165,7 +166,7 @@ static int decode_mvc2(AVCodecContext *avctx, GetByteContext *gb, uint8_t *dst_s if (vflip) { dst_start += (height - 1) * linesize; - linesize = -linesize; + linesize = -linesize; } x = y = 0; while (bytestream2_get_bytes_left(gb) >= 1) { @@ -173,17 +174,19 @@ static int decode_mvc2(AVCodecContext *avctx, GetByteContext *gb, uint8_t *dst_s if ((p0 & 0x80)) { if ((p0 & 0x40)) { p0 &= 0x3F; - p0 = (p0 << 2) | (p0 >> 4); - set_4x4_block(dst_start + y * linesize + x * 4, linesize, 0xFF000000 | (p0 << 16) | (p0 << 8) | p0); + p0 = (p0 << 2) | (p0 >> 4); + set_4x4_block(dst_start + y * linesize + x * 4, linesize, + 0xFF000000 | (p0 << 16) | (p0 << 8) | p0); } else { int g, r; p0 &= 0x3F; - p0 = (p0 << 2) | (p0 >> 4); + p0 = (p0 << 2) | (p0 >> 4); if (bytestream2_get_bytes_left(gb) < 2) return AVERROR_INVALIDDATA; g = bytestream2_get_byteu(gb); r = bytestream2_get_byteu(gb); - set_4x4_block(dst_start + y * linesize + x * 4, linesize, 0xFF000000 | (r << 16) | (g << 8) | p0); + set_4x4_block(dst_start + y * linesize + x * 4, linesize, + 0xFF000000 | (r << 16) | (g << 8) | p0); } } else { if (bytestream2_get_bytes_left(gb) < 1) @@ -191,7 +194,8 @@ static int decode_mvc2(AVCodecContext *avctx, GetByteContext *gb, uint8_t *dst_s p1 = bytestream2_get_byteu(gb); if ((p1 & 0x80)) { if ((p0 & 0x7F) == (p1 & 0x7F)) { - set_4x4_block(dst_start + y * linesize + x * 4, linesize, color[p0 & 0x7F]); + set_4x4_block(dst_start + y * linesize + x * 4, linesize, + color[p0 & 0x7F]); } else { if (bytestream2_get_bytes_left(gb) < 2) return AVERROR_INVALIDDATA; @@ -223,8 +227,7 @@ static int decode_mvc2(AVCodecContext *avctx, GetByteContext *gb, uint8_t *dst_s return 0; } -static int mvc_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, +static int mvc_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { MvcContext *s = avctx->priv_data; @@ -236,9 +239,12 @@ static int mvc_decode_frame(AVCodecContext *avctx, bytestream2_init(&gb, avpkt->data, avpkt->size); if (avctx->codec_id == AV_CODEC_ID_MVC1) - ret = decode_mvc1(avctx, &gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]); + ret = decode_mvc1(avctx, &gb, s->frame->data[0], + avctx->width, avctx->height, s->frame->linesize[0]); else - ret = decode_mvc2(avctx, &gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0], s->vflip); + ret = decode_mvc2(avctx, &gb, s->frame->data[0], + avctx->width, avctx->height, s->frame->linesize[0], + s->vflip); if (ret < 0) return ret; diff --git a/libavcodec/nellymoserenc.c b/libavcodec/nellymoserenc.c index f9d1389a7..98e33f0e2 100644 --- a/libavcodec/nellymoserenc.c +++ b/libavcodec/nellymoserenc.c @@ -35,13 +35,15 @@ * http://wiki.multimedia.cx/index.php?title=Nellymoser */ +#include "libavutil/common.h" #include "libavutil/float_dsp.h" #include "libavutil/mathematics.h" -#include "nellymoser.h" -#include "avcodec.h" + #include "audio_frame_queue.h" +#include "avcodec.h" #include "fft.h" #include "internal.h" +#include "nellymoser.h" #include "sinewin.h" #define BITSTREAM_WRITER_LE diff --git a/libavcodec/nuv.c b/libavcodec/nuv.c index 358bf0567..048ad6f69 100644 --- a/libavcodec/nuv.c +++ b/libavcodec/nuv.c @@ -25,9 +25,11 @@ #include "libavutil/bswap.h" #include "libavutil/common.h" +#include "libavutil/intreadwrite.h" #include "libavutil/lzo.h" #include "libavutil/imgutils.h" #include "avcodec.h" +#include "idctdsp.h" #include "internal.h" #include "rtjpeg.h" @@ -40,7 +42,6 @@ typedef struct { unsigned char *decomp_buf; uint32_t lq[64], cq[64]; RTJpegContext rtj; - DSPContext dsp; } NuvContext; static const uint8_t fallback_lquant[] = { @@ -138,13 +139,11 @@ static int codec_reinit(AVCodecContext *avctx, int width, int height, "Can't allocate decompression buffer.\n"); return AVERROR(ENOMEM); } - ff_rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, - c->lq, c->cq); + ff_rtjpeg_decode_init(&c->rtj, c->width, c->height, c->lq, c->cq); av_frame_unref(c->pic); return 1; } else if (quality != c->quality) - ff_rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, - c->lq, c->cq); + ff_rtjpeg_decode_init(&c->rtj, c->width, c->height, c->lq, c->cq); return 0; } @@ -183,8 +182,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, ret = get_quant(avctx, c, buf, buf_size); if (ret < 0) return ret; - ff_rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, - c->cq); + ff_rtjpeg_decode_init(&c->rtj, c->width, c->height, c->lq, c->cq); return orig_size; } @@ -322,7 +320,7 @@ static av_cold int decode_init(AVCodecContext *avctx) if (avctx->extradata_size) get_quant(avctx, c, avctx->extradata, avctx->extradata_size); - ff_dsputil_init(&c->dsp, avctx); + ff_rtjpeg_init(&c->rtj, avctx); if ((ret = codec_reinit(avctx, avctx->width, avctx->height, -1)) < 0) return ret; diff --git a/libavcodec/old_codec_ids.h b/libavcodec/old_codec_ids.h index b956264f3..c7aa0e0a1 100644 --- a/libavcodec/old_codec_ids.h +++ b/libavcodec/old_codec_ids.h @@ -19,8 +19,6 @@ #ifndef AVCODEC_OLD_CODEC_IDS_H #define AVCODEC_OLD_CODEC_IDS_H -#include "libavutil/common.h" - /* * This header exists to prevent new codec IDs from being accidentally added to * the deprecated list. diff --git a/libavcodec/on2avc.c b/libavcodec/on2avc.c new file mode 100644 index 000000000..ab6048b63 --- /dev/null +++ b/libavcodec/on2avc.c @@ -0,0 +1,1014 @@ +/* + * On2 Audio for Video Codec decoder + * + * Copyright (c) 2013 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/float_dsp.h" +#include "avcodec.h" +#include "bytestream.h" +#include "fft.h" +#include "get_bits.h" +#include "golomb.h" +#include "internal.h" +#include "unary.h" + +#include "on2avcdata.h" + +#define ON2AVC_SUBFRAME_SIZE 1024 + +enum WindowTypes { + WINDOW_TYPE_LONG = 0, + WINDOW_TYPE_LONG_STOP, + WINDOW_TYPE_LONG_START, + WINDOW_TYPE_8SHORT = 3, + WINDOW_TYPE_EXT4, + WINDOW_TYPE_EXT5, + WINDOW_TYPE_EXT6, + WINDOW_TYPE_EXT7, +}; + +typedef struct On2AVCContext { + AVCodecContext *avctx; + AVFloatDSPContext fdsp; + FFTContext mdct, mdct_half, mdct_small; + FFTContext fft128, fft256, fft512, fft1024; + void (*wtf)(struct On2AVCContext *ctx, float *out, float *in, int size); + + int is_av500; + + const On2AVCMode *modes; + int window_type, prev_window_type; + int num_windows, num_bands; + int bits_per_section; + const int *band_start; + + int grouping[8]; + int ms_present; + int ms_info[ON2AVC_MAX_BANDS]; + + int is_long; + + uint8_t band_type[ON2AVC_MAX_BANDS]; + uint8_t band_run_end[ON2AVC_MAX_BANDS]; + int num_sections; + + float band_scales[ON2AVC_MAX_BANDS]; + + VLC scale_diff; + VLC cb_vlc[16]; + + float scale_tab[128]; + + DECLARE_ALIGNED(32, float, coeffs)[2][ON2AVC_SUBFRAME_SIZE]; + DECLARE_ALIGNED(32, float, delay) [2][ON2AVC_SUBFRAME_SIZE]; + + DECLARE_ALIGNED(32, float, temp) [ON2AVC_SUBFRAME_SIZE * 2]; + DECLARE_ALIGNED(32, float, mdct_buf) [ON2AVC_SUBFRAME_SIZE]; + DECLARE_ALIGNED(32, float, long_win) [ON2AVC_SUBFRAME_SIZE]; + DECLARE_ALIGNED(32, float, short_win)[ON2AVC_SUBFRAME_SIZE / 8]; +} On2AVCContext; + +static void on2avc_read_ms_info(On2AVCContext *c, GetBitContext *gb) +{ + int w, b, band_off = 0; + + c->ms_present = get_bits1(gb); + if (!c->ms_present) + return; + for (w = 0; w < c->num_windows; w++) { + if (!c->grouping[w]) { + memcpy(c->ms_info + band_off, + c->ms_info + band_off - c->num_bands, + c->num_bands * sizeof(*c->ms_info)); + band_off += c->num_bands; + continue; + } + for (b = 0; b < c->num_bands; b++) + c->ms_info[band_off++] = get_bits1(gb); + } +} + +// do not see Table 17 in ISO/IEC 13818-7 +static int on2avc_decode_band_types(On2AVCContext *c, GetBitContext *gb) +{ + int bits_per_sect = c->is_long ? 5 : 3; + int esc_val = (1 << bits_per_sect) - 1; + int num_bands = c->num_bands * c->num_windows; + int band = 0, i, band_type, run_len, run; + + while (band < num_bands) { + band_type = get_bits(gb, 4); + run_len = 1; + do { + run = get_bits(gb, bits_per_sect); + run_len += run; + } while (run == esc_val); + if (band + run_len > num_bands) { + av_log(c->avctx, AV_LOG_ERROR, "Invalid band type run\n"); + return AVERROR_INVALIDDATA; + } + for (i = band; i < band + run_len; i++) { + c->band_type[i] = band_type; + c->band_run_end[i] = band + run_len; + } + band += run_len; + } + + return 0; +} + +// completely not like Table 18 in ISO/IEC 13818-7 +// (no intensity stereo, different coding for the first coefficient) +static int on2avc_decode_band_scales(On2AVCContext *c, GetBitContext *gb) +{ + int w, w2, b, scale, first = 1; + int band_off = 0; + + for (w = 0; w < c->num_windows; w++) { + if (!c->grouping[w]) { + memcpy(c->band_scales + band_off, + c->band_scales + band_off - c->num_bands, + c->num_bands * sizeof(*c->band_scales)); + band_off += c->num_bands; + continue; + } + for (b = 0; b < c->num_bands; b++) { + if (!c->band_type[band_off]) { + int all_zero = 1; + for (w2 = w + 1; w2 < c->num_windows; w2++) { + if (c->grouping[w2]) + break; + if (c->band_type[w2 * c->num_bands + b]) { + all_zero = 0; + break; + } + } + if (all_zero) { + c->band_scales[band_off++] = 0; + continue; + } + } + if (first) { + scale = get_bits(gb, 7); + first = 0; + } else { + scale += get_vlc2(gb, c->scale_diff.table, 9, 3) - 60; + } + if (scale < 0 || scale > 127) { + av_log(c->avctx, AV_LOG_ERROR, "Invalid scale value %d\n", + scale); + return AVERROR_INVALIDDATA; + } + c->band_scales[band_off++] = c->scale_tab[scale]; + } + } + + return 0; +} + +static inline float on2avc_scale(int v, float scale) +{ + return v * sqrtf(fabsf(v)) * scale; +} + +// spectral data is coded completely differently - there are no unsigned codebooks +static int on2avc_decode_quads(On2AVCContext *c, GetBitContext *gb, float *dst, + int dst_size, int type, float band_scale) +{ + int i, j, val, val1; + + for (i = 0; i < dst_size; i += 4) { + val = get_vlc2(gb, c->cb_vlc[type].table, 9, 3); + + for (j = 0; j < 4; j++) { + val1 = sign_extend((val >> (12 - j * 4)) & 0xF, 4); + *dst++ = on2avc_scale(val1, band_scale); + } + } + + return 0; +} + +static inline int get_egolomb(GetBitContext *gb) +{ + int v = 4; + + while (get_bits1(gb)) v++; + + return (1 << v) + get_bits(gb, v); +} + +static int on2avc_decode_pairs(On2AVCContext *c, GetBitContext *gb, float *dst, + int dst_size, int type, float band_scale) +{ + int i, val, val1, val2, sign; + + for (i = 0; i < dst_size; i += 2) { + val = get_vlc2(gb, c->cb_vlc[type].table, 9, 3); + + val1 = sign_extend(val >> 8, 8); + val2 = sign_extend(val & 0xFF, 8); + if (type == ON2AVC_ESC_CB) { + if (val1 <= -16 || val1 >= 16) { + sign = 1 - (val1 < 0) * 2; + val1 = sign * get_egolomb(gb); + } + if (val2 <= -16 || val2 >= 16) { + sign = 1 - (val2 < 0) * 2; + val2 = sign * get_egolomb(gb); + } + } + + *dst++ = on2avc_scale(val1, band_scale); + *dst++ = on2avc_scale(val2, band_scale); + } + + return 0; +} + +static int on2avc_read_channel_data(On2AVCContext *c, GetBitContext *gb, int ch) +{ + int ret; + int w, b, band_idx; + float *coeff_ptr; + + if ((ret = on2avc_decode_band_types(c, gb)) < 0) + return ret; + if ((ret = on2avc_decode_band_scales(c, gb)) < 0) + return ret; + + coeff_ptr = c->coeffs[ch]; + band_idx = 0; + memset(coeff_ptr, 0, ON2AVC_SUBFRAME_SIZE * sizeof(*coeff_ptr)); + for (w = 0; w < c->num_windows; w++) { + for (b = 0; b < c->num_bands; b++) { + int band_size = c->band_start[b + 1] - c->band_start[b]; + int band_type = c->band_type[band_idx + b]; + + if (!band_type) { + coeff_ptr += band_size; + continue; + } + if (band_type < 9) + on2avc_decode_quads(c, gb, coeff_ptr, band_size, band_type, + c->band_scales[band_idx + b]); + else + on2avc_decode_pairs(c, gb, coeff_ptr, band_size, band_type, + c->band_scales[band_idx + b]); + coeff_ptr += band_size; + } + band_idx += c->num_bands; + } + + return 0; +} + +static int on2avc_apply_ms(On2AVCContext *c) +{ + int w, b, i; + int band_off = 0; + float *ch0 = c->coeffs[0]; + float *ch1 = c->coeffs[1]; + + for (w = 0; w < c->num_windows; w++) { + for (b = 0; b < c->num_bands; b++) { + if (c->ms_info[band_off + b]) { + for (i = c->band_start[b]; i < c->band_start[b + 1]; i++) { + float l = *ch0, r = *ch1; + *ch0++ = l + r; + *ch1++ = l - r; + } + } else { + ch0 += c->band_start[b + 1] - c->band_start[b]; + ch1 += c->band_start[b + 1] - c->band_start[b]; + } + } + band_off += c->num_bands; + } + return 0; +} + +static void zero_head_and_tail(float *src, int len, int order0, int order1) +{ + memset(src, 0, sizeof(*src) * order0); + memset(src + len - order1, 0, sizeof(*src) * order1); +} + +static void pretwiddle(float *src, float *dst, int dst_len, int tab_step, + int step, int order0, int order1, const double * const *tabs) +{ + float *src2, *out; + const double *tab; + int i, j; + + out = dst; + tab = tabs[0]; + for (i = 0; i < tab_step; i++) { + double sum = 0; + for (j = 0; j < order0; j++) + sum += src[j] * tab[j * tab_step + i]; + out[i] += sum; + } + + out = dst + dst_len - tab_step; + tab = tabs[order0]; + src2 = src + (dst_len - tab_step) / step + 1 + order0; + for (i = 0; i < tab_step; i++) { + double sum = 0; + for (j = 0; j < order1; j++) + sum += src2[j] * tab[j * tab_step + i]; + out[i] += sum; + } +} + +static void twiddle(float *src1, float *src2, int src2_len, + const double *tab, int tab_len, int step, + int order0, int order1, const double * const *tabs) +{ + int steps; + int mask; + int i, j; + + steps = (src2_len - tab_len) / step + 1; + pretwiddle(src1, src2, src2_len, tab_len, step, order0, order1, tabs); + mask = tab_len - 1; + + for (i = 0; i < steps; i++) { + float in0 = src1[order0 + i]; + int pos = (src2_len - 1) & mask; + + if (pos < tab_len) { + const double *t = tab; + for (j = pos; j >= 0; j--) + src2[j] += in0 * *t++; + for (j = 0; j < tab_len - pos - 1; j++) + src2[src2_len - j - 1] += in0 * tab[pos + 1 + j]; + } else { + for (j = 0; j < tab_len; j++) + src2[pos - j] += in0 * tab[j]; + } + mask = pos + step; + } +} + +#define CMUL1_R(s, t, is, it) \ + s[is + 0] * t[it + 0] - s[is + 1] * t[it + 1] +#define CMUL1_I(s, t, is, it) \ + s[is + 0] * t[it + 1] + s[is + 1] * t[it + 0] +#define CMUL2_R(s, t, is, it) \ + s[is + 0] * t[it + 0] + s[is + 1] * t[it + 1] +#define CMUL2_I(s, t, is, it) \ + s[is + 0] * t[it + 1] - s[is + 1] * t[it + 0] + +#define CMUL0(dst, id, s0, s1, s2, s3, t0, t1, t2, t3, is, it) \ + dst[id] = s0[is] * t0[it] + s1[is] * t1[it] \ + + s2[is] * t2[it] + s3[is] * t3[it]; \ + dst[id + 1] = s0[is] * t0[it + 1] + s1[is] * t1[it + 1] \ + + s2[is] * t2[it + 1] + s3[is] * t3[it + 1]; + +#define CMUL1(dst, s0, s1, s2, s3, t0, t1, t2, t3, is, it) \ + *dst++ = CMUL1_R(s0, t0, is, it) \ + + CMUL1_R(s1, t1, is, it) \ + + CMUL1_R(s2, t2, is, it) \ + + CMUL1_R(s3, t3, is, it); \ + *dst++ = CMUL1_I(s0, t0, is, it) \ + + CMUL1_I(s1, t1, is, it) \ + + CMUL1_I(s2, t2, is, it) \ + + CMUL1_I(s3, t3, is, it); + +#define CMUL2(dst, s0, s1, s2, s3, t0, t1, t2, t3, is, it) \ + *dst++ = CMUL2_R(s0, t0, is, it) \ + + CMUL2_R(s1, t1, is, it) \ + + CMUL2_R(s2, t2, is, it) \ + + CMUL2_R(s3, t3, is, it); \ + *dst++ = CMUL2_I(s0, t0, is, it) \ + + CMUL2_I(s1, t1, is, it) \ + + CMUL2_I(s2, t2, is, it) \ + + CMUL2_I(s3, t3, is, it); + +static void combine_fft(float *s0, float *s1, float *s2, float *s3, float *dst, + const float *t0, const float *t1, + const float *t2, const float *t3, int len, int step) +{ + const float *h0, *h1, *h2, *h3; + float *d1, *d2; + int tmp, half; + int len2 = len >> 1, len4 = len >> 2; + int hoff; + int i, j, k; + + tmp = step; + for (half = len2; tmp > 1; half <<= 1, tmp >>= 1); + + h0 = t0 + half; + h1 = t1 + half; + h2 = t2 + half; + h3 = t3 + half; + + CMUL0(dst, 0, s0, s1, s2, s3, t0, t1, t2, t3, 0, 0); + + hoff = 2 * step * (len4 >> 1); + + j = 2; + k = 2 * step; + d1 = dst + 2; + d2 = dst + 2 + (len >> 1); + for (i = 0; i < (len4 - 1) >> 1; i++) { + CMUL1(d1, s0, s1, s2, s3, t0, t1, t2, t3, j, k); + CMUL1(d2, s0, s1, s2, s3, h0, h1, h2, h3, j, k); + j += 2; + k += 2 * step; + } + CMUL0(dst, len4, s0, s1, s2, s3, t0, t1, t2, t3, 1, hoff); + CMUL0(dst, len4 + len2, s0, s1, s2, s3, h0, h1, h2, h3, 1, hoff); + + j = len4; + k = hoff + 2 * step * len4; + d1 = dst + len4 + 2; + d2 = dst + len4 + 2 + len2; + for (i = 0; i < (len4 - 2) >> 1; i++) { + CMUL2(d1, s0, s1, s2, s3, t0, t1, t2, t3, j, k); + CMUL2(d2, s0, s1, s2, s3, h0, h1, h2, h3, j, k); + j -= 2; + k += 2 * step; + } + CMUL0(dst, len2 + 4, s0, s1, s2, s3, t0, t1, t2, t3, 0, k); +} + +static void wtf_end_512(On2AVCContext *c, float *out, float *src, + float *tmp0, float *tmp1) +{ + memcpy(src, tmp0, 384 * sizeof(*tmp0)); + memcpy(tmp0 + 384, src + 384, 128 * sizeof(*tmp0)); + + zero_head_and_tail(src, 128, 16, 4); + zero_head_and_tail(src + 128, 128, 16, 4); + zero_head_and_tail(src + 256, 128, 13, 7); + zero_head_and_tail(src + 384, 128, 15, 5); + + c->fft128.fft_permute(&c->fft128, (FFTComplex*)src); + c->fft128.fft_permute(&c->fft128, (FFTComplex*)(src + 128)); + c->fft128.fft_permute(&c->fft128, (FFTComplex*)(src + 256)); + c->fft128.fft_permute(&c->fft128, (FFTComplex*)(src + 384)); + c->fft128.fft_calc(&c->fft128, (FFTComplex*)src); + c->fft128.fft_calc(&c->fft128, (FFTComplex*)(src + 128)); + c->fft128.fft_calc(&c->fft128, (FFTComplex*)(src + 256)); + c->fft128.fft_calc(&c->fft128, (FFTComplex*)(src + 384)); + combine_fft(src, src + 128, src + 256, src + 384, tmp1, + ff_on2avc_ctab_1, ff_on2avc_ctab_2, + ff_on2avc_ctab_3, ff_on2avc_ctab_4, 512, 2); + c->fft512.fft_permute(&c->fft512, (FFTComplex*)tmp1); + c->fft512.fft_calc(&c->fft512, (FFTComplex*)tmp1); + + pretwiddle(&tmp0[ 0], tmp1, 512, 84, 4, 16, 4, ff_on2avc_tabs_20_84_1); + pretwiddle(&tmp0[128], tmp1, 512, 84, 4, 16, 4, ff_on2avc_tabs_20_84_2); + pretwiddle(&tmp0[256], tmp1, 512, 84, 4, 13, 7, ff_on2avc_tabs_20_84_3); + pretwiddle(&tmp0[384], tmp1, 512, 84, 4, 15, 5, ff_on2avc_tabs_20_84_4); + + memcpy(src, tmp1, 512 * sizeof(float)); +} + +static void wtf_end_1024(On2AVCContext *c, float *out, float *src, + float *tmp0, float *tmp1) +{ + memcpy(src, tmp0, 768 * sizeof(*tmp0)); + memcpy(tmp0 + 768, src + 768, 256 * sizeof(*tmp0)); + + zero_head_and_tail(src, 256, 16, 4); + zero_head_and_tail(src + 256, 256, 16, 4); + zero_head_and_tail(src + 512, 256, 13, 7); + zero_head_and_tail(src + 768, 256, 15, 5); + + c->fft256.fft_permute(&c->fft256, (FFTComplex*)src); + c->fft256.fft_permute(&c->fft256, (FFTComplex*)(src + 256)); + c->fft256.fft_permute(&c->fft256, (FFTComplex*)(src + 512)); + c->fft256.fft_permute(&c->fft256, (FFTComplex*)(src + 768)); + c->fft256.fft_calc(&c->fft256, (FFTComplex*)src); + c->fft256.fft_calc(&c->fft256, (FFTComplex*)(src + 256)); + c->fft256.fft_calc(&c->fft256, (FFTComplex*)(src + 512)); + c->fft256.fft_calc(&c->fft256, (FFTComplex*)(src + 768)); + combine_fft(src, src + 256, src + 512, src + 768, tmp1, + ff_on2avc_ctab_1, ff_on2avc_ctab_2, + ff_on2avc_ctab_3, ff_on2avc_ctab_4, 1024, 1); + c->fft1024.fft_permute(&c->fft1024, (FFTComplex*)tmp1); + c->fft1024.fft_calc(&c->fft1024, (FFTComplex*)tmp1); + + pretwiddle(&tmp0[ 0], tmp1, 1024, 84, 4, 16, 4, ff_on2avc_tabs_20_84_1); + pretwiddle(&tmp0[256], tmp1, 1024, 84, 4, 16, 4, ff_on2avc_tabs_20_84_2); + pretwiddle(&tmp0[512], tmp1, 1024, 84, 4, 13, 7, ff_on2avc_tabs_20_84_3); + pretwiddle(&tmp0[768], tmp1, 1024, 84, 4, 15, 5, ff_on2avc_tabs_20_84_4); + + memcpy(src, tmp1, 1024 * sizeof(float)); +} + +static void wtf_40(On2AVCContext *c, float *out, float *src, int size) +{ + float *tmp0 = c->temp, *tmp1 = c->temp + 1024; + + memset(tmp0, 0, sizeof(*tmp0) * 1024); + memset(tmp1, 0, sizeof(*tmp1) * 1024); + + if (size == 512) { + twiddle(src, &tmp0[ 0], 16, ff_on2avc_tab_10_1, 10, 2, 1, 3, ff_on2avc_tabs_4_10_1); + twiddle(src + 8, &tmp0[ 0], 16, ff_on2avc_tab_10_2, 10, 2, 3, 1, ff_on2avc_tabs_4_10_2); + twiddle(src + 16, &tmp0[ 16], 16, ff_on2avc_tab_10_2, 10, 2, 3, 1, ff_on2avc_tabs_4_10_2); + twiddle(src + 24, &tmp0[ 16], 16, ff_on2avc_tab_10_1, 10, 2, 1, 3, ff_on2avc_tabs_4_10_1); + twiddle(src + 32, &tmp0[ 32], 16, ff_on2avc_tab_10_1, 10, 2, 1, 3, ff_on2avc_tabs_4_10_1); + twiddle(src + 40, &tmp0[ 32], 16, ff_on2avc_tab_10_2, 10, 2, 3, 1, ff_on2avc_tabs_4_10_2); + twiddle(src + 48, &tmp0[ 48], 16, ff_on2avc_tab_10_2, 10, 2, 3, 1, ff_on2avc_tabs_4_10_2); + twiddle(src + 56, &tmp0[ 48], 16, ff_on2avc_tab_10_1, 10, 2, 1, 3, ff_on2avc_tabs_4_10_1); + twiddle(&tmp0[ 0], &tmp1[ 0], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(&tmp0[16], &tmp1[ 0], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(&tmp0[32], &tmp1[ 32], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(&tmp0[48], &tmp1[ 32], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(src + 64, &tmp1[ 64], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(src + 80, &tmp1[ 64], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 96, &tmp1[ 96], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 112, &tmp1[ 96], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(src + 128, &tmp1[128], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(src + 144, &tmp1[128], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 160, &tmp1[160], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 176, &tmp1[160], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + + memset(tmp0, 0, 64 * sizeof(*tmp0)); + + twiddle(&tmp1[ 0], &tmp0[ 0], 128, ff_on2avc_tab_84_1, 84, 4, 16, 4, ff_on2avc_tabs_20_84_1); + twiddle(&tmp1[ 32], &tmp0[ 0], 128, ff_on2avc_tab_84_2, 84, 4, 16, 4, ff_on2avc_tabs_20_84_2); + twiddle(&tmp1[ 64], &tmp0[ 0], 128, ff_on2avc_tab_84_3, 84, 4, 13, 7, ff_on2avc_tabs_20_84_3); + twiddle(&tmp1[ 96], &tmp0[ 0], 128, ff_on2avc_tab_84_4, 84, 4, 15, 5, ff_on2avc_tabs_20_84_4); + twiddle(&tmp1[128], &tmp0[128], 128, ff_on2avc_tab_84_4, 84, 4, 15, 5, ff_on2avc_tabs_20_84_4); + twiddle(&tmp1[160], &tmp0[128], 128, ff_on2avc_tab_84_3, 84, 4, 13, 7, ff_on2avc_tabs_20_84_3); + twiddle(src + 192, &tmp0[128], 128, ff_on2avc_tab_84_2, 84, 4, 16, 4, ff_on2avc_tabs_20_84_2); + twiddle(src + 224, &tmp0[128], 128, ff_on2avc_tab_84_1, 84, 4, 16, 4, ff_on2avc_tabs_20_84_1); + twiddle(src + 256, &tmp0[256], 128, ff_on2avc_tab_84_1, 84, 4, 16, 4, ff_on2avc_tabs_20_84_1); + twiddle(src + 288, &tmp0[256], 128, ff_on2avc_tab_84_2, 84, 4, 16, 4, ff_on2avc_tabs_20_84_2); + twiddle(src + 320, &tmp0[256], 128, ff_on2avc_tab_84_3, 84, 4, 13, 7, ff_on2avc_tabs_20_84_3); + twiddle(src + 352, &tmp0[256], 128, ff_on2avc_tab_84_4, 84, 4, 15, 5, ff_on2avc_tabs_20_84_4); + + wtf_end_512(c, out, src, tmp0, tmp1); + } else { + twiddle(src, &tmp0[ 0], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(src + 16, &tmp0[ 0], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 32, &tmp0[ 32], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 48, &tmp0[ 32], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(src + 64, &tmp0[ 64], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(src + 80, &tmp0[ 64], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 96, &tmp0[ 96], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 112, &tmp0[ 96], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(&tmp0[ 0], &tmp1[ 0], 64, ff_on2avc_tab_40_1, 40, 2, 11, 8, ff_on2avc_tabs_19_40_1); + twiddle(&tmp0[32], &tmp1[ 0], 64, ff_on2avc_tab_40_2, 40, 2, 8, 11, ff_on2avc_tabs_19_40_2); + twiddle(&tmp0[64], &tmp1[ 64], 64, ff_on2avc_tab_40_2, 40, 2, 8, 11, ff_on2avc_tabs_19_40_2); + twiddle(&tmp0[96], &tmp1[ 64], 64, ff_on2avc_tab_40_1, 40, 2, 11, 8, ff_on2avc_tabs_19_40_1); + twiddle(src + 128, &tmp1[128], 64, ff_on2avc_tab_40_1, 40, 2, 11, 8, ff_on2avc_tabs_19_40_1); + twiddle(src + 160, &tmp1[128], 64, ff_on2avc_tab_40_2, 40, 2, 8, 11, ff_on2avc_tabs_19_40_2); + twiddle(src + 192, &tmp1[192], 64, ff_on2avc_tab_40_2, 40, 2, 8, 11, ff_on2avc_tabs_19_40_2); + twiddle(src + 224, &tmp1[192], 64, ff_on2avc_tab_40_1, 40, 2, 11, 8, ff_on2avc_tabs_19_40_1); + twiddle(src + 256, &tmp1[256], 64, ff_on2avc_tab_40_1, 40, 2, 11, 8, ff_on2avc_tabs_19_40_1); + twiddle(src + 288, &tmp1[256], 64, ff_on2avc_tab_40_2, 40, 2, 8, 11, ff_on2avc_tabs_19_40_2); + twiddle(src + 320, &tmp1[320], 64, ff_on2avc_tab_40_2, 40, 2, 8, 11, ff_on2avc_tabs_19_40_2); + twiddle(src + 352, &tmp1[320], 64, ff_on2avc_tab_40_1, 40, 2, 11, 8, ff_on2avc_tabs_19_40_1); + + memset(tmp0, 0, 128 * sizeof(*tmp0)); + + twiddle(&tmp1[ 0], &tmp0[ 0], 256, ff_on2avc_tab_84_1, 84, 4, 16, 4, ff_on2avc_tabs_20_84_1); + twiddle(&tmp1[ 64], &tmp0[ 0], 256, ff_on2avc_tab_84_2, 84, 4, 16, 4, ff_on2avc_tabs_20_84_2); + twiddle(&tmp1[128], &tmp0[ 0], 256, ff_on2avc_tab_84_3, 84, 4, 13, 7, ff_on2avc_tabs_20_84_3); + twiddle(&tmp1[192], &tmp0[ 0], 256, ff_on2avc_tab_84_4, 84, 4, 15, 5, ff_on2avc_tabs_20_84_4); + twiddle(&tmp1[256], &tmp0[256], 256, ff_on2avc_tab_84_4, 84, 4, 15, 5, ff_on2avc_tabs_20_84_4); + twiddle(&tmp1[320], &tmp0[256], 256, ff_on2avc_tab_84_3, 84, 4, 13, 7, ff_on2avc_tabs_20_84_3); + twiddle(src + 384, &tmp0[256], 256, ff_on2avc_tab_84_2, 84, 4, 16, 4, ff_on2avc_tabs_20_84_2); + twiddle(src + 448, &tmp0[256], 256, ff_on2avc_tab_84_1, 84, 4, 16, 4, ff_on2avc_tabs_20_84_1); + twiddle(src + 512, &tmp0[512], 256, ff_on2avc_tab_84_1, 84, 4, 16, 4, ff_on2avc_tabs_20_84_1); + twiddle(src + 576, &tmp0[512], 256, ff_on2avc_tab_84_2, 84, 4, 16, 4, ff_on2avc_tabs_20_84_2); + twiddle(src + 640, &tmp0[512], 256, ff_on2avc_tab_84_3, 84, 4, 13, 7, ff_on2avc_tabs_20_84_3); + twiddle(src + 704, &tmp0[512], 256, ff_on2avc_tab_84_4, 84, 4, 15, 5, ff_on2avc_tabs_20_84_4); + + wtf_end_1024(c, out, src, tmp0, tmp1); + } +} + +static void wtf_44(On2AVCContext *c, float *out, float *src, int size) +{ + float *tmp0 = c->temp, *tmp1 = c->temp + 1024; + + memset(tmp0, 0, sizeof(*tmp0) * 1024); + memset(tmp1, 0, sizeof(*tmp1) * 1024); + + if (size == 512) { + twiddle(src, &tmp0[ 0], 16, ff_on2avc_tab_10_1, 10, 2, 1, 3, ff_on2avc_tabs_4_10_1); + twiddle(src + 8, &tmp0[ 0], 16, ff_on2avc_tab_10_2, 10, 2, 3, 1, ff_on2avc_tabs_4_10_2); + twiddle(src + 16, &tmp0[16], 16, ff_on2avc_tab_10_2, 10, 2, 3, 1, ff_on2avc_tabs_4_10_2); + twiddle(src + 24, &tmp0[16], 16, ff_on2avc_tab_10_1, 10, 2, 1, 3, ff_on2avc_tabs_4_10_1); + twiddle(src + 32, &tmp0[32], 16, ff_on2avc_tab_10_1, 10, 2, 1, 3, ff_on2avc_tabs_4_10_1); + twiddle(src + 40, &tmp0[32], 16, ff_on2avc_tab_10_2, 10, 2, 3, 1, ff_on2avc_tabs_4_10_2); + twiddle(src + 48, &tmp0[48], 16, ff_on2avc_tab_10_2, 10, 2, 3, 1, ff_on2avc_tabs_4_10_2); + twiddle(src + 56, &tmp0[48], 16, ff_on2avc_tab_10_1, 10, 2, 1, 3, ff_on2avc_tabs_4_10_1); + twiddle(&tmp0[ 0], &tmp1[ 0], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(&tmp0[16], &tmp1[ 0], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(&tmp0[32], &tmp1[32], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(&tmp0[48], &tmp1[32], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(src + 64, &tmp1[64], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(src + 80, &tmp1[64], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 96, &tmp1[96], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 112, &tmp1[96], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + + memset(tmp0, 0, 64 * sizeof(*tmp0)); + + twiddle(&tmp1[ 0], &tmp0[ 0], 128, ff_on2avc_tab_84_1, 84, 4, 16, 4, ff_on2avc_tabs_20_84_1); + twiddle(&tmp1[32], &tmp0[ 0], 128, ff_on2avc_tab_84_2, 84, 4, 16, 4, ff_on2avc_tabs_20_84_2); + twiddle(&tmp1[64], &tmp0[ 0], 128, ff_on2avc_tab_84_3, 84, 4, 13, 7, ff_on2avc_tabs_20_84_3); + twiddle(&tmp1[96], &tmp0[ 0], 128, ff_on2avc_tab_84_4, 84, 4, 15, 5, ff_on2avc_tabs_20_84_4); + twiddle(src + 128, &tmp0[128], 128, ff_on2avc_tab_84_4, 84, 4, 15, 5, ff_on2avc_tabs_20_84_4); + twiddle(src + 160, &tmp0[128], 128, ff_on2avc_tab_84_3, 84, 4, 13, 7, ff_on2avc_tabs_20_84_3); + twiddle(src + 192, &tmp0[128], 128, ff_on2avc_tab_84_2, 84, 4, 16, 4, ff_on2avc_tabs_20_84_2); + twiddle(src + 224, &tmp0[128], 128, ff_on2avc_tab_84_1, 84, 4, 16, 4, ff_on2avc_tabs_20_84_1); + twiddle(src + 256, &tmp0[256], 128, ff_on2avc_tab_40_1, 40, 2, 11, 8, ff_on2avc_tabs_19_40_1); + twiddle(src + 320, &tmp0[256], 128, ff_on2avc_tab_40_2, 40, 2, 8, 11, ff_on2avc_tabs_19_40_2); + + wtf_end_512(c, out, src, tmp0, tmp1); + } else { + twiddle(src, &tmp0[ 0], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(src + 16, &tmp0[ 0], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 32, &tmp0[ 32], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 48, &tmp0[ 32], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(src + 64, &tmp0[ 64], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(src + 80, &tmp0[ 64], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 96, &tmp0[ 96], 32, ff_on2avc_tab_20_2, 20, 2, 4, 5, ff_on2avc_tabs_9_20_2); + twiddle(src + 112, &tmp0[ 96], 32, ff_on2avc_tab_20_1, 20, 2, 5, 4, ff_on2avc_tabs_9_20_1); + twiddle(&tmp0[ 0], &tmp1[ 0], 64, ff_on2avc_tab_40_1, 40, 2, 11, 8, ff_on2avc_tabs_19_40_1); + twiddle(&tmp0[32], &tmp1[ 0], 64, ff_on2avc_tab_40_2, 40, 2, 8, 11, ff_on2avc_tabs_19_40_2); + twiddle(&tmp0[64], &tmp1[ 64], 64, ff_on2avc_tab_40_2, 40, 2, 8, 11, ff_on2avc_tabs_19_40_2); + twiddle(&tmp0[96], &tmp1[ 64], 64, ff_on2avc_tab_40_1, 40, 2, 11, 8, ff_on2avc_tabs_19_40_1); + twiddle(src + 128, &tmp1[128], 64, ff_on2avc_tab_40_1, 40, 2, 11, 8, ff_on2avc_tabs_19_40_1); + twiddle(src + 160, &tmp1[128], 64, ff_on2avc_tab_40_2, 40, 2, 8, 11, ff_on2avc_tabs_19_40_2); + twiddle(src + 192, &tmp1[192], 64, ff_on2avc_tab_40_2, 40, 2, 8, 11, ff_on2avc_tabs_19_40_2); + twiddle(src + 224, &tmp1[192], 64, ff_on2avc_tab_40_1, 40, 2, 11, 8, ff_on2avc_tabs_19_40_1); + + memset(tmp0, 0, 128 * sizeof(*tmp0)); + + twiddle(&tmp1[ 0], &tmp0[ 0], 256, ff_on2avc_tab_84_1, 84, 4, 16, 4, ff_on2avc_tabs_20_84_1); + twiddle(&tmp1[ 64], &tmp0[ 0], 256, ff_on2avc_tab_84_2, 84, 4, 16, 4, ff_on2avc_tabs_20_84_2); + twiddle(&tmp1[128], &tmp0[ 0], 256, ff_on2avc_tab_84_3, 84, 4, 13, 7, ff_on2avc_tabs_20_84_3); + twiddle(&tmp1[192], &tmp0[ 0], 256, ff_on2avc_tab_84_4, 84, 4, 15, 5, ff_on2avc_tabs_20_84_4); + twiddle(src + 256, &tmp0[256], 256, ff_on2avc_tab_84_4, 84, 4, 15, 5, ff_on2avc_tabs_20_84_4); + twiddle(src + 320, &tmp0[256], 256, ff_on2avc_tab_84_3, 84, 4, 13, 7, ff_on2avc_tabs_20_84_3); + twiddle(src + 384, &tmp0[256], 256, ff_on2avc_tab_84_2, 84, 4, 16, 4, ff_on2avc_tabs_20_84_2); + twiddle(src + 448, &tmp0[256], 256, ff_on2avc_tab_84_1, 84, 4, 16, 4, ff_on2avc_tabs_20_84_1); + twiddle(src + 512, &tmp0[512], 256, ff_on2avc_tab_40_1, 40, 2, 11, 8, ff_on2avc_tabs_19_40_1); + twiddle(src + 640, &tmp0[512], 256, ff_on2avc_tab_40_2, 40, 2, 8, 11, ff_on2avc_tabs_19_40_2); + + wtf_end_1024(c, out, src, tmp0, tmp1); + } +} + +static int on2avc_reconstruct_stereo(On2AVCContext *c, AVFrame *dst, int offset) +{ + int ch, i; + + for (ch = 0; ch < 2; ch++) { + float *out = (float*)dst->extended_data[ch] + offset; + float *in = c->coeffs[ch]; + float *saved = c->delay[ch]; + float *buf = c->mdct_buf; + float *wout = out + 448; + + switch (c->window_type) { + case WINDOW_TYPE_EXT7: + c->mdct.imdct_half(&c->mdct, buf, in); + break; + case WINDOW_TYPE_EXT4: + c->wtf(c, buf, in, 1024); + break; + case WINDOW_TYPE_EXT5: + c->wtf(c, buf, in, 512); + c->mdct.imdct_half(&c->mdct_half, buf + 512, in + 512); + for (i = 0; i < 256; i++) { + FFSWAP(float, buf[i + 512], buf[1023 - i]); + } + break; + case WINDOW_TYPE_EXT6: + c->mdct.imdct_half(&c->mdct_half, buf, in); + for (i = 0; i < 256; i++) { + FFSWAP(float, buf[i], buf[511 - i]); + } + c->wtf(c, buf + 512, in + 512, 512); + break; + } + + memcpy(out, saved, 448 * sizeof(float)); + c->fdsp.vector_fmul_window(wout, saved + 448, buf, c->short_win, 64); + memcpy(wout + 128, buf + 64, 448 * sizeof(float)); + memcpy(saved, buf + 512, 448 * sizeof(float)); + memcpy(saved + 448, buf + 7*128 + 64, 64 * sizeof(float)); + } + + return 0; +} + +// not borrowed from aacdec.c - the codec has original design after all +static int on2avc_reconstruct_channel(On2AVCContext *c, int channel, + AVFrame *dst, int offset) +{ + int i; + float *out = (float*)dst->extended_data[channel] + offset; + float *in = c->coeffs[channel]; + float *saved = c->delay[channel]; + float *buf = c->mdct_buf; + float *temp = c->temp; + + switch (c->window_type) { + case WINDOW_TYPE_LONG_START: + case WINDOW_TYPE_LONG_STOP: + case WINDOW_TYPE_LONG: + c->mdct.imdct_half(&c->mdct, buf, in); + break; + case WINDOW_TYPE_8SHORT: + for (i = 0; i < ON2AVC_SUBFRAME_SIZE; i += ON2AVC_SUBFRAME_SIZE / 8) + c->mdct_small.imdct_half(&c->mdct_small, buf + i, in + i); + break; + } + + if ((c->prev_window_type == WINDOW_TYPE_LONG || + c->prev_window_type == WINDOW_TYPE_LONG_STOP) && + (c->window_type == WINDOW_TYPE_LONG || + c->window_type == WINDOW_TYPE_LONG_START)) { + c->fdsp.vector_fmul_window(out, saved, buf, c->long_win, 512); + } else { + float *wout = out + 448; + memcpy(out, saved, 448 * sizeof(float)); + + if (c->window_type == WINDOW_TYPE_8SHORT) { + c->fdsp.vector_fmul_window(wout + 0*128, saved + 448, buf + 0*128, c->short_win, 64); + c->fdsp.vector_fmul_window(wout + 1*128, buf + 0*128 + 64, buf + 1*128, c->short_win, 64); + c->fdsp.vector_fmul_window(wout + 2*128, buf + 1*128 + 64, buf + 2*128, c->short_win, 64); + c->fdsp.vector_fmul_window(wout + 3*128, buf + 2*128 + 64, buf + 3*128, c->short_win, 64); + c->fdsp.vector_fmul_window(temp, buf + 3*128 + 64, buf + 4*128, c->short_win, 64); + memcpy(wout + 4*128, temp, 64 * sizeof(float)); + } else { + c->fdsp.vector_fmul_window(wout, saved + 448, buf, c->short_win, 64); + memcpy(wout + 128, buf + 64, 448 * sizeof(float)); + } + } + + // buffer update + switch (c->window_type) { + case WINDOW_TYPE_8SHORT: + memcpy(saved, temp + 64, 64 * sizeof(float)); + c->fdsp.vector_fmul_window(saved + 64, buf + 4*128 + 64, buf + 5*128, c->short_win, 64); + c->fdsp.vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, c->short_win, 64); + c->fdsp.vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, c->short_win, 64); + memcpy(saved + 448, buf + 7*128 + 64, 64 * sizeof(float)); + break; + case WINDOW_TYPE_LONG_START: + memcpy(saved, buf + 512, 448 * sizeof(float)); + memcpy(saved + 448, buf + 7*128 + 64, 64 * sizeof(float)); + break; + case WINDOW_TYPE_LONG_STOP: + case WINDOW_TYPE_LONG: + memcpy(saved, buf + 512, 512 * sizeof(float)); + break; + } + return 0; +} + +static int on2avc_decode_subframe(On2AVCContext *c, const uint8_t *buf, + int buf_size, AVFrame *dst, int offset) +{ + GetBitContext gb; + int i, ret; + + init_get_bits(&gb, buf, buf_size * 8); + if (get_bits1(&gb)) { + av_log(c->avctx, AV_LOG_ERROR, "enh bit set\n"); + return AVERROR_INVALIDDATA; + } + c->prev_window_type = c->window_type; + c->window_type = get_bits(&gb, 3); + if (c->window_type >= WINDOW_TYPE_EXT4 && c->avctx->channels == 1) { + av_log(c->avctx, AV_LOG_ERROR, "stereo mode window for mono audio\n"); + return AVERROR_INVALIDDATA; + } + + c->band_start = c->modes[c->window_type].band_start; + c->num_windows = c->modes[c->window_type].num_windows; + c->num_bands = c->modes[c->window_type].num_bands; + c->is_long = (c->window_type != WINDOW_TYPE_8SHORT); + + c->grouping[0] = 1; + for (i = 1; i < c->num_windows; i++) + c->grouping[i] = !get_bits1(&gb); + + on2avc_read_ms_info(c, &gb); + for (i = 0; i < c->avctx->channels; i++) + if ((ret = on2avc_read_channel_data(c, &gb, i)) < 0) + return AVERROR_INVALIDDATA; + if (c->avctx->channels == 2 && c->ms_present) + on2avc_apply_ms(c); + if (c->window_type < WINDOW_TYPE_EXT4) { + for (i = 0; i < c->avctx->channels; i++) + on2avc_reconstruct_channel(c, i, dst, offset); + } else { + on2avc_reconstruct_stereo(c, dst, offset); + } + + return 0; +} + +static int on2avc_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; + On2AVCContext *c = avctx->priv_data; + GetByteContext gb; + int num_frames = 0, frame_size, audio_off; + int ret; + + if (c->is_av500) { + /* get output buffer */ + frame->nb_samples = ON2AVC_SUBFRAME_SIZE; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + + if ((ret = on2avc_decode_subframe(c, buf, buf_size, frame, 0)) < 0) + return ret; + } else { + bytestream2_init(&gb, buf, buf_size); + while (bytestream2_get_bytes_left(&gb) > 2) { + frame_size = bytestream2_get_le16(&gb); + if (!frame_size || frame_size > bytestream2_get_bytes_left(&gb)) { + av_log(avctx, AV_LOG_ERROR, "Invalid subframe size %d\n", + frame_size); + return AVERROR_INVALIDDATA; + } + num_frames++; + bytestream2_skip(&gb, frame_size); + } + if (!num_frames) { + av_log(avctx, AV_LOG_ERROR, "No subframes present\n"); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = ON2AVC_SUBFRAME_SIZE * num_frames; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + + audio_off = 0; + bytestream2_init(&gb, buf, buf_size); + while (bytestream2_get_bytes_left(&gb) > 2) { + frame_size = bytestream2_get_le16(&gb); + if ((ret = on2avc_decode_subframe(c, gb.buffer, frame_size, + frame, audio_off)) < 0) + return ret; + audio_off += ON2AVC_SUBFRAME_SIZE; + bytestream2_skip(&gb, frame_size); + } + } + + *got_frame_ptr = 1; + + return buf_size; +} + +static av_cold void on2avc_free_vlcs(On2AVCContext *c) +{ + int i; + + ff_free_vlc(&c->scale_diff); + for (i = 1; i < 16; i++) + ff_free_vlc(&c->cb_vlc[i]); +} + +static av_cold int on2avc_decode_init(AVCodecContext *avctx) +{ + On2AVCContext *c = avctx->priv_data; + int i; + + c->avctx = avctx; + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + avctx->channel_layout = (avctx->channels == 2) ? AV_CH_LAYOUT_STEREO + : AV_CH_LAYOUT_MONO; + + c->is_av500 = (avctx->codec_tag == 0x500); + if (c->is_av500 && avctx->channels == 2) { + av_log(avctx, AV_LOG_ERROR, "0x500 version should be mono\n"); + return AVERROR_INVALIDDATA; + } + if (avctx->channels == 2) + av_log(avctx, AV_LOG_WARNING, + "Stereo mode support is not good, patch is welcome\n"); + + for (i = 0; i < 20; i++) + c->scale_tab[i] = ceil(pow(10.0, i * 0.1) * 16) / 32; + for (; i < 128; i++) + c->scale_tab[i] = ceil(pow(10.0, i * 0.1) * 0.5); + + if (avctx->sample_rate < 32000 || avctx->channels == 1) + memcpy(c->long_win, ff_on2avc_window_long_24000, + 1024 * sizeof(*c->long_win)); + else + memcpy(c->long_win, ff_on2avc_window_long_32000, + 1024 * sizeof(*c->long_win)); + memcpy(c->short_win, ff_on2avc_window_short, 128 * sizeof(*c->short_win)); + + c->modes = (avctx->sample_rate <= 40000) ? ff_on2avc_modes_40 + : ff_on2avc_modes_44; + c->wtf = (avctx->sample_rate <= 40000) ? wtf_40 + : wtf_44; + + ff_mdct_init(&c->mdct, 11, 1, 1.0 / (32768.0 * 1024.0)); + ff_mdct_init(&c->mdct_half, 10, 1, 1.0 / (32768.0 * 512.0)); + ff_mdct_init(&c->mdct_small, 8, 1, 1.0 / (32768.0 * 128.0)); + ff_fft_init(&c->fft128, 6, 0); + 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); + + if (init_vlc(&c->scale_diff, 9, ON2AVC_SCALE_DIFFS, + ff_on2avc_scale_diff_bits, 1, 1, + ff_on2avc_scale_diff_codes, 4, 4, 0)) { + av_log(avctx, AV_LOG_ERROR, "Cannot init VLC\n"); + return AVERROR(ENOMEM); + } + for (i = 1; i < 9; i++) { + int idx = i - 1; + if (ff_init_vlc_sparse(&c->cb_vlc[i], 9, ff_on2avc_quad_cb_elems[idx], + ff_on2avc_quad_cb_bits[idx], 1, 1, + ff_on2avc_quad_cb_codes[idx], 4, 4, + ff_on2avc_quad_cb_syms[idx], 2, 2, 0)) { + av_log(avctx, AV_LOG_ERROR, "Cannot init VLC\n"); + on2avc_free_vlcs(c); + return AVERROR(ENOMEM); + } + } + for (i = 9; i < 16; i++) { + int idx = i - 9; + if (ff_init_vlc_sparse(&c->cb_vlc[i], 9, ff_on2avc_pair_cb_elems[idx], + ff_on2avc_pair_cb_bits[idx], 1, 1, + ff_on2avc_pair_cb_codes[idx], 2, 2, + ff_on2avc_pair_cb_syms[idx], 2, 2, 0)) { + av_log(avctx, AV_LOG_ERROR, "Cannot init VLC\n"); + on2avc_free_vlcs(c); + return AVERROR(ENOMEM); + } + } + + return 0; +} + +static av_cold int on2avc_decode_close(AVCodecContext *avctx) +{ + On2AVCContext *c = avctx->priv_data; + + ff_mdct_end(&c->mdct); + ff_mdct_end(&c->mdct_half); + ff_mdct_end(&c->mdct_small); + ff_fft_end(&c->fft128); + ff_fft_end(&c->fft256); + ff_fft_end(&c->fft512); + ff_fft_end(&c->fft1024); + + on2avc_free_vlcs(c); + + return 0; +} + + +AVCodec ff_on2avc_decoder = { + .name = "on2avc", + .long_name = NULL_IF_CONFIG_SMALL("On2 Audio for Video Codec"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ON2AVC, + .priv_data_size = sizeof(On2AVCContext), + .init = on2avc_decode_init, + .decode = on2avc_decode_frame, + .close = on2avc_decode_close, + .capabilities = CODEC_CAP_DR1, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/libavcodec/on2avcdata.c b/libavcodec/on2avcdata.c new file mode 100644 index 000000000..abe598350 --- /dev/null +++ b/libavcodec/on2avcdata.c @@ -0,0 +1,9383 @@ +/* + * On2 Audio for Video Codec decoder + * + * Copyright (c) 2013 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "on2avcdata.h" + +static const int on2avc_swb_start_long[] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, + 72, 80, 88, 96, 108, 120, 132, 144, 156, 172, 188, 204, 224, 244, + 264, 288, 312, 340, 368, 400, 432, 464, 496, 528, 560, 592, 624, 656, + 688, 720, 752, 784, 816, 848, 880, 1024 +}; + +static const int on2avc_swb_start_short[] = { + 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 56, 68, 80, 108, 128 +}; + +static const int on2avc_swb_start_mode_4_40[] = { + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, + 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, 256, 264, 272, 280, + 288, 296, 304, 312, 320, 328, 336, 344, 352, 360, 368, 376, 384, 400, + 416, 432, 448, 464, 480, 496, 512, 520, 528, 536, 544, 552, 560, 568, + 576, 584, 592, 600, 608, 616, 624, 632, 640, 648, 656, 664, 672, 680, + 688, 696, 704, 712, 720, 728, 736, 744, 752, 760, 768, 800, 832, 864, + 896, 928, 960, 992, 1024 +}; + +static const int on2avc_swb_start_mode_5_40[] = { + 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 136, + 144, 152, 160, 168, 176, 184, 192, 208, 224, 240, 256, 264, 272, 280, + 288, 296, 304, 312, 320, 328, 336, 344, 352, 360, 368, 376, 384, 416, + 448, 480, 512, 516, 520, 524, 528, 532, 536, 540, 548, 556, 568, 580, + 592, 608, 624, 640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, + 816, 832, 848, 864, 880, 896, 912, 928, 944, 1024 +}; + +static const int on2avc_swb_start_mode_6_40[] = { + 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 56, 68, 80, 96, + 112, 128, 144, 160, 176, 192, 208, 224, 240, 256, 272, 288, 304, 320, + 336, 352, 368, 384, 400, 416, 432, 512, 520, 528, 536, 544, 552, 560, + 568, 576, 592, 608, 624, 640, 648, 656, 664, 672, 680, 688, 696, 704, + 720, 736, 752, 768, 776, 784, 792, 800, 808, 816, 824, 832, 840, 848, + 856, 864, 872, 880, 888, 896, 928, 960, 992, 1024 +}; + +static const int on2avc_swb_start_mode_4_44[] = { + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, + 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, + 224, 232, 240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, + 336, 344, 352, 360, 368, 376, 384, 392, 400, 408, 416, 424, 432, 440, + 448, 456, 464, 472, 480, 488, 496, 504, 512, 528, 544, 560, 576, 592, + 608, 624, 640, 672, 704, 736, 768, 832, 896, 960, 1024 +}; + +static const int on2avc_swb_start_mode_5_44[] = { + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, + 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, + 224, 232, 240, 248, 256, 272, 288, 304, 320, 352, 384, 448, 512, 516, + 520, 524, 528, 532, 536, 540, 548, 556, 568, 580, 592, 608, 624, 640, + 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816, 832, 848, 864, + 880, 896, 912, 928, 944, 1024 +}; + +static const int on2avc_swb_start_mode_6_44[] = { + 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 56, 68, 80, 96, + 112, 128, 144, 160, 176, 192, 208, 224, 240, 256, 272, 288, 304, 320, + 336, 352, 368, 384, 400, 416, 432, 512, 520, 528, 536, 544, 552, 560, + 568, 576, 584, 592, 600, 608, 616, 624, 632, 640, 648, 656, 664, 672, + 680, 688, 696, 704, 712, 720, 728, 736, 744, 752, 760, 768, 784, 800, + 816, 832, 864, 896, 960, 1024 +}; + +const On2AVCMode ff_on2avc_modes_40[8] = { + { 1, 49, on2avc_swb_start_long }, + { 1, 49, on2avc_swb_start_long }, + { 1, 49, on2avc_swb_start_long }, + { 8, 14, on2avc_swb_start_short }, + { 1, 88, on2avc_swb_start_mode_4_40 }, + { 1, 79, on2avc_swb_start_mode_5_40 }, + { 1, 79, on2avc_swb_start_mode_6_40 }, + { 1, 49, on2avc_swb_start_long }, +}; + +const On2AVCMode ff_on2avc_modes_44[8] = { + { 1, 49, on2avc_swb_start_long }, + { 1, 49, on2avc_swb_start_long }, + { 1, 49, on2avc_swb_start_long }, + { 8, 14, on2avc_swb_start_short }, + { 1, 80, on2avc_swb_start_mode_4_44 }, + { 1, 75, on2avc_swb_start_mode_5_44 }, + { 1, 75, on2avc_swb_start_mode_6_44 }, + { 1, 49, on2avc_swb_start_long }, +}; + +const uint32_t ff_on2avc_scale_diff_codes[ON2AVC_SCALE_DIFFS] = { + 0x6FFFF, 0xBFFF2, 0xBFFF3, 0xBFFF4, 0xBFFF5, 0xBFFF6, + 0xBFFF7, 0xBFFF8, 0xBFFF9, 0xBFFFA, 0xBFFFB, 0xBFFFC, + 0xBFFFD, 0xBFFFE, 0xBFFFF, 0xDF9A0, 0xDF9A1, 0xDF9A2, + 0xDF9A3, 0xDF9A4, 0xDF9A5, 0xDF9A6, 0xDF9A7, 0xDF9A8, + 0xDF9A9, 0x37FFE, 0x6FCDE, 0x6FFFA, 0x0BFF7, 0x0B7FF, + 0x0DF9F, 0x05FF8, 0x0B7FE, 0x05FF9, 0x06FCE, 0x05BFE, + 0x037FE, 0x02DFE, 0x00DFA, 0x00DFE, 0x017FC, 0x00DBE, + 0x00B7E, 0x005FE, 0x0037D, 0x002DE, 0x0017E, 0x0016C, + 0x000DE, 0x000BE, 0x0006C, 0x0005A, 0x0003E, 0x00034, + 0x0002C, 0x0001F, 0x0000E, 0x0000E, 0x00006, 0x00002, + 0x00000, 0x00004, 0x0000A, 0x0000C, 0x0001E, 0x0001E, + 0x0002E, 0x00035, 0x0003F, 0x0005E, 0x0006E, 0x000DA, + 0x0016D, 0x0016E, 0x001B6, 0x002FE, 0x0036E, 0x0037C, + 0x005BE, 0x006DE, 0x006FE, 0x00DBF, 0x00DFB, 0x016FE, + 0x017FD, 0x01BFE, 0x01BF2, 0x02FFE, 0x06FCC, 0x05FFE, + 0x05FFA, 0x06FFE, 0x0BFF6, 0x0BFFE, 0x0DF9E, 0x00DF8, + 0x0DFFE, 0x37FFC, 0x6FFFB, 0x5FFF8, 0xDF9AA, 0xDF9AB, + 0xDF9AC, 0xDF9AD, 0xDF9AE, 0xDF9AF, 0xDF9B0, 0xDF9B1, + 0xDF9B2, 0xDF9B3, 0x6FFFE, 0xDF9B4, 0xDF9B5, 0xDF9B6, + 0xDF9B7, 0xDF9B8, 0xDF9B9, 0xDF9BA, 0xDF9BB, 0xDF9BE, + 0xDF9BF, +}; + +const uint8_t ff_on2avc_scale_diff_bits[ON2AVC_SCALE_DIFFS] = { + 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, + 20, 20, 20, 21, 21, 21, + 21, 21, 21, 21, 21, 21, + 21, 19, 20, 20, 16, 16, + 17, 15, 16, 15, 16, 15, + 15, 14, 13, 13, 13, 13, + 12, 11, 11, 10, 9, 9, + 9, 8, 8, 7, 7, 7, + 6, 5, 5, 4, 3, 3, + 2, 3, 4, 5, 5, 6, + 6, 7, 7, 7, 8, 9, + 9, 9, 10, 10, 11, 11, + 11, 12, 12, 13, 13, 13, + 13, 14, 14, 14, 16, 15, + 15, 16, 16, 16, 17, 13, + 17, 19, 20, 19, 21, 21, + 21, 21, 21, 21, 21, 21, + 21, 21, 20, 21, 21, 21, + 21, 21, 21, 21, 21, 21, + 21, +}; + +#define ON2AVC_CB1_CODES 41 +static const uint32_t on2avc_cb1_codes[ON2AVC_CB1_CODES] = { + 0x0000, 0x0022, 0x001C, 0x001B, 0x0024, 0x0030, + 0x0029, 0x0027, 0x0021, 0x002B, 0x002E, 0x0020, + 0x0026, 0x0033, 0x0031, 0x002C, 0x002A, 0x001E, + 0x0094, 0x01FF, 0x01F7, 0x012E, 0x001A, 0x01F5, + 0x007E, 0x012C, 0x01FC, 0x002D, 0x0032, 0x0028, + 0x002F, 0x001D, 0x01FD, 0x012D, 0x007C, 0x01F4, + 0x0023, 0x012F, 0x01F6, 0x01FE, 0x0095, +}; + +static const uint8_t on2avc_cb1_bits[ON2AVC_CB1_CODES] = { + 1, 6, 5, 5, 6, 6, + 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 5, + 8, 9, 9, 9, 5, 9, + 7, 9, 9, 6, 6, 6, + 6, 5, 9, 9, 7, 9, + 6, 9, 9, 9, 8, +}; + +static const uint16_t on2avc_cb1_syms[ON2AVC_CB1_CODES] = { + 0x0000, 0x0011, 0x001F, 0x00F1, 0x00FF, 0x0101, + 0x010F, 0x0110, 0x01F0, 0x0F01, 0x0F0F, 0x0F10, + 0x0FF0, 0x1001, 0x100F, 0x1010, 0x10F0, 0x1100, + 0x1111, 0x111F, 0x11F1, 0x11FF, 0x1F00, 0x1F11, + 0x1F1F, 0x1FF1, 0x1FFF, 0xF001, 0xF00F, 0xF010, + 0xF0F0, 0xF100, 0xF111, 0xF11F, 0xF1F1, 0xF1FF, + 0xFF00, 0xFF11, 0xFF1F, 0xFFF1, 0xFFFF, +}; + +#define ON2AVC_CB2_CODES 41 +static const uint32_t on2avc_cb2_codes[ON2AVC_CB2_CODES] = { + 0x0006, 0x0003, 0x001F, 0x001E, 0x0000, 0x0014, + 0x0009, 0x000E, 0x000D, 0x000C, 0x0015, 0x0008, + 0x0010, 0x000F, 0x0004, 0x0012, 0x0007, 0x0016, + 0x0005, 0x002F, 0x0017, 0x0006, 0x001D, 0x002C, + 0x005E, 0x0014, 0x0016, 0x0006, 0x0011, 0x000A, + 0x0013, 0x001C, 0x002D, 0x0015, 0x005F, 0x002E, + 0x0002, 0x0007, 0x005D, 0x005C, 0x0004, +}; + +static const uint8_t on2avc_cb2_bits[ON2AVC_CB2_CODES] = { + 3, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, + 7, 7, 7, 7, 5, 7, + 7, 7, 7, 5, 5, 5, + 5, 5, 7, 7, 7, 7, + 5, 7, 7, 7, 7, +}; + +static const uint16_t on2avc_cb2_syms[ON2AVC_CB2_CODES] = { + 0x0000, 0x0011, 0x001F, 0x00F1, 0x00FF, 0x0101, + 0x010F, 0x0110, 0x01F0, 0x0F01, 0x0F0F, 0x0F10, + 0x0FF0, 0x1001, 0x100F, 0x1010, 0x10F0, 0x1100, + 0x1111, 0x111F, 0x11F1, 0x11FF, 0x1F00, 0x1F11, + 0x1F1F, 0x1FF1, 0x1FFF, 0xF001, 0xF00F, 0xF010, + 0xF0F0, 0xF100, 0xF111, 0xF11F, 0xF1F1, 0xF1FF, + 0xFF00, 0xFF11, 0xFF1F, 0xFFF1, 0xFFFF, +}; + +#define ON2AVC_CB3_CODES 313 +static const uint32_t on2avc_cb3_codes[ON2AVC_CB3_CODES] = { + 0x00000, 0x00044, 0x00042, 0x00034, 0x0002E, 0x000CD, + 0x002DF, 0x0024A, 0x000CC, 0x0022E, 0x002D6, 0x00031, + 0x0003B, 0x00048, 0x00052, 0x00056, 0x001B8, 0x00160, + 0x001FA, 0x0015E, 0x0015C, 0x0014E, 0x0003C, 0x0010C, + 0x00166, 0x000CA, 0x0324C, 0x00FDA, 0x003DE, 0x002DB, + 0x0057F, 0x02C9E, 0x008BF, 0x0037F, 0x021DC, 0x00B1E, + 0x002DE, 0x002D2, 0x000C8, 0x014D6, 0x03576, 0x002CA, + 0x002CF, 0x003DB, 0x007FE, 0x01F7E, 0x005A3, 0x008BE, + 0x02D7E, 0x002D3, 0x0037E, 0x0004D, 0x0004C, 0x00041, + 0x0016A, 0x0010D, 0x0015D, 0x0011F, 0x00162, 0x0021E, + 0x00055, 0x00161, 0x001BE, 0x0004E, 0x0004A, 0x0004B, + 0x003EE, 0x00352, 0x0043A, 0x0033E, 0x0035C, 0x0036C, + 0x00050, 0x0032F, 0x003D6, 0x00039, 0x0067E, 0x00536, + 0x000FE, 0x001F4, 0x0036D, 0x007EF, 0x00CFE, 0x002D0, + 0x00F8C, 0x00D96, 0x001E9, 0x001F6, 0x00476, 0x00367, + 0x001F2, 0x01FF6, 0x016BB, 0x007FC, 0x00D5C, 0x00B24, + 0x00C92, 0x0014F, 0x01EA6, 0x01936, 0x00366, 0x0035E, + 0x00116, 0x00FBE, 0x01B5E, 0x0092F, 0x007EE, 0x00CEE, + 0x00B26, 0x0011E, 0x014DF, 0x035DE, 0x00030, 0x00473, + 0x005A2, 0x001BC, 0x000D6, 0x002DA, 0x00B5E, 0x007AA, + 0x002C8, 0x00D94, 0x00D97, 0x001AA, 0x001EE, 0x0003A, + 0x035DF, 0x03D4F, 0x0064F, 0x0064A, 0x02D73, 0x1ABBE, + 0x0B1CF, 0x00F8E, 0x06AFF, 0x0475E, 0x00472, 0x00596, + 0x003E7, 0x0036E, 0x00196, 0x0357E, 0x03F6E, 0x0324E, + 0x0324F, 0x0163B, 0x0192F, 0x001B4, 0x0326A, 0x02C9F, + 0x0021F, 0x0F8FF, 0x064D6, 0x007BE, 0x00DDF, 0x033BC, + 0x033BD, 0x06AEE, 0x00876, 0x07C7E, 0x0B1CE, 0x00D76, + 0x00DDC, 0x001EC, 0x0649B, 0x0B1CD, 0x00F8D, 0x007D6, + 0x01AEE, 0x0163F, 0x03E3E, 0x00A6A, 0x06D7E, 0x0DDDF, + 0x00F7E, 0x00DAE, 0x0036F, 0x00338, 0x0016C, 0x033BF, + 0x036BE, 0x01FF7, 0x01937, 0x01ABA, 0x014D7, 0x0014C, + 0x01F7F, 0x0475F, 0x00040, 0x07FFC, 0x03F6F, 0x00477, + 0x00496, 0x014DE, 0x0649A, 0x064D7, 0x02C9C, 0x0B1CC, + 0x1ABBF, 0x00648, 0x006BA, 0x00364, 0x0032E, 0x00126, + 0x03D4E, 0x02C72, 0x011D6, 0x01638, 0x01934, 0x02C9D, + 0x0016E, 0x021DD, 0x03DFF, 0x001F0, 0x07FFE, 0x043BF, + 0x00D5E, 0x00FAE, 0x0092E, 0x07FFF, 0x0F8FE, 0x02D7F, + 0x043BE, 0x06D7F, 0x008E9, 0x00FFA, 0x0021C, 0x06EEE, + 0x0D5DE, 0x00F57, 0x00CFF, 0x016BA, 0x07FFD, 0x06AFE, + 0x021DE, 0x0DDDE, 0x023AE, 0x00FAF, 0x006D6, 0x0037B, + 0x003E6, 0x001B9, 0x01F1E, 0x033BE, 0x0192E, 0x016BE, + 0x01FB6, 0x01BBA, 0x0019E, 0x03776, 0x03DFE, 0x00046, + 0x00051, 0x0004F, 0x003D7, 0x0033A, 0x00376, 0x00353, + 0x00356, 0x003EA, 0x00054, 0x00339, 0x003E2, 0x0002F, + 0x0064C, 0x00534, 0x00238, 0x001A8, 0x002C6, 0x00D95, + 0x00F52, 0x002CE, 0x007DE, 0x00B2F, 0x000D8, 0x001BA, + 0x0036A, 0x0035F, 0x00127, 0x01EFE, 0x016B8, 0x008EA, + 0x00CEC, 0x007EC, 0x00A6E, 0x00114, 0x01ABE, 0x00FFE, + 0x0037A, 0x0045E, 0x00124, 0x0163E, 0x02D72, 0x00CED, + 0x00B2E, 0x00C96, 0x007A8, 0x001FE, 0x0163A, 0x01FFE, + 0x00038, 0x0057E, 0x0064E, 0x001F8, 0x001E8, 0x002BE, + 0x00DDE, 0x00F56, 0x003DA, 0x00B25, 0x008E8, 0x001F9, + 0x00115, +}; + +static const uint8_t on2avc_cb3_bits[ON2AVC_CB3_CODES] = { + 1, 7, 7, 6, 6, 8, + 10, 10, 8, 10, 10, 6, + 6, 7, 7, 7, 9, 9, + 9, 9, 9, 9, 6, 9, + 9, 8, 14, 12, 10, 10, + 11, 14, 12, 10, 14, 12, + 10, 10, 8, 13, 14, 10, + 10, 10, 11, 13, 11, 12, + 14, 10, 10, 7, 7, 7, + 9, 9, 9, 9, 9, 10, + 7, 9, 9, 7, 7, 7, + 10, 10, 11, 10, 10, 10, + 7, 10, 10, 6, 11, 11, + 8, 9, 10, 11, 12, 10, + 12, 12, 9, 9, 11, 10, + 9, 13, 13, 11, 12, 12, + 12, 9, 13, 13, 10, 10, + 9, 12, 13, 12, 11, 12, + 12, 9, 13, 14, 6, 11, + 11, 9, 8, 10, 12, 11, + 10, 12, 12, 9, 9, 6, + 14, 14, 11, 11, 14, 17, + 16, 12, 15, 15, 11, 11, + 10, 10, 9, 14, 14, 14, + 14, 13, 13, 9, 14, 14, + 10, 16, 15, 11, 12, 14, + 14, 15, 12, 15, 16, 12, + 12, 9, 15, 16, 12, 11, + 13, 13, 14, 12, 15, 16, + 12, 12, 10, 10, 9, 14, + 14, 13, 13, 13, 13, 9, + 13, 15, 7, 15, 14, 11, + 11, 13, 15, 15, 14, 16, + 17, 11, 11, 10, 10, 9, + 14, 14, 13, 13, 13, 14, + 9, 14, 14, 9, 15, 15, + 12, 12, 12, 15, 16, 14, + 15, 15, 12, 12, 10, 15, + 16, 12, 12, 13, 15, 15, + 14, 16, 14, 12, 11, 10, + 10, 9, 13, 14, 13, 13, + 13, 13, 9, 14, 14, 7, + 7, 7, 10, 10, 10, 10, + 10, 10, 7, 10, 10, 6, + 11, 11, 10, 9, 10, 12, + 12, 10, 11, 12, 8, 9, + 10, 10, 9, 13, 13, 12, + 12, 11, 12, 9, 13, 12, + 10, 11, 9, 13, 14, 12, + 12, 12, 11, 9, 13, 13, + 6, 11, 11, 9, 9, 10, + 12, 12, 10, 12, 12, 9, + 9, +}; + +static const uint16_t on2avc_cb3_syms[ON2AVC_CB3_CODES] = { + 0x0000, 0x0002, 0x000E, 0x0011, 0x001F, 0x0020, + 0x0022, 0x002E, 0x00E0, 0x00E2, 0x00EE, 0x00F1, + 0x00FF, 0x0101, 0x010F, 0x0110, 0x0112, 0x011E, + 0x0121, 0x012F, 0x01E1, 0x01EF, 0x01F0, 0x01F2, + 0x01FE, 0x0200, 0x0202, 0x020E, 0x0211, 0x021F, + 0x0220, 0x0222, 0x022E, 0x02E0, 0x02E2, 0x02EE, + 0x02F1, 0x02FF, 0x0E00, 0x0E02, 0x0E0E, 0x0E11, + 0x0E1F, 0x0E20, 0x0E22, 0x0E2E, 0x0EE0, 0x0EE2, + 0x0EEE, 0x0EF1, 0x0EFF, 0x0F01, 0x0F0F, 0x0F10, + 0x0F12, 0x0F1E, 0x0F21, 0x0F2F, 0x0FE1, 0x0FEF, + 0x0FF0, 0x0FF2, 0x0FFE, 0x1001, 0x100F, 0x1010, + 0x1012, 0x101E, 0x1021, 0x102F, 0x10E1, 0x10EF, + 0x10F0, 0x10F2, 0x10FE, 0x1100, 0x1102, 0x110E, + 0x1111, 0x111F, 0x1120, 0x1122, 0x112E, 0x11E0, + 0x11E2, 0x11EE, 0x11F1, 0x11FF, 0x1201, 0x120F, + 0x1210, 0x1212, 0x121E, 0x1221, 0x122F, 0x12E1, + 0x12EF, 0x12F0, 0x12F2, 0x12FE, 0x1E01, 0x1E0F, + 0x1E10, 0x1E12, 0x1E1E, 0x1E21, 0x1E2F, 0x1EE1, + 0x1EEF, 0x1EF0, 0x1EF2, 0x1EFE, 0x1F00, 0x1F02, + 0x1F0E, 0x1F11, 0x1F1F, 0x1F20, 0x1F22, 0x1F2E, + 0x1FE0, 0x1FE2, 0x1FEE, 0x1FF1, 0x1FFF, 0x2000, + 0x2002, 0x200E, 0x2011, 0x201F, 0x2020, 0x2022, + 0x202E, 0x20E0, 0x20E2, 0x20EE, 0x20F1, 0x20FF, + 0x2101, 0x210F, 0x2110, 0x2112, 0x211E, 0x2121, + 0x212F, 0x21E1, 0x21EF, 0x21F0, 0x21F2, 0x21FE, + 0x2200, 0x2202, 0x220E, 0x2211, 0x221F, 0x2220, + 0x2222, 0x222E, 0x22E0, 0x22E2, 0x22EE, 0x22F1, + 0x22FF, 0x2E00, 0x2E02, 0x2E0E, 0x2E11, 0x2E1F, + 0x2E20, 0x2E22, 0x2E2E, 0x2EE0, 0x2EE2, 0x2EEE, + 0x2EF1, 0x2EFF, 0x2F01, 0x2F0F, 0x2F10, 0x2F12, + 0x2F1E, 0x2F21, 0x2F2F, 0x2FE1, 0x2FEF, 0x2FF0, + 0x2FF2, 0x2FFE, 0xE000, 0xE002, 0xE00E, 0xE011, + 0xE01F, 0xE020, 0xE022, 0xE02E, 0xE0E0, 0xE0E2, + 0xE0EE, 0xE0F1, 0xE0FF, 0xE101, 0xE10F, 0xE110, + 0xE112, 0xE11E, 0xE121, 0xE12F, 0xE1E1, 0xE1EF, + 0xE1F0, 0xE1F2, 0xE1FE, 0xE200, 0xE202, 0xE20E, + 0xE211, 0xE21F, 0xE220, 0xE222, 0xE22E, 0xE2E0, + 0xE2E2, 0xE2EE, 0xE2F1, 0xE2FF, 0xEE00, 0xEE02, + 0xEE0E, 0xEE11, 0xEE1F, 0xEE20, 0xEE22, 0xEE2E, + 0xEEE0, 0xEEE2, 0xEEEE, 0xEEF1, 0xEEFF, 0xEF01, + 0xEF0F, 0xEF10, 0xEF12, 0xEF1E, 0xEF21, 0xEF2F, + 0xEFE1, 0xEFEF, 0xEFF0, 0xEFF2, 0xEFFE, 0xF001, + 0xF00F, 0xF010, 0xF012, 0xF01E, 0xF021, 0xF02F, + 0xF0E1, 0xF0EF, 0xF0F0, 0xF0F2, 0xF0FE, 0xF100, + 0xF102, 0xF10E, 0xF111, 0xF11F, 0xF120, 0xF122, + 0xF12E, 0xF1E0, 0xF1E2, 0xF1EE, 0xF1F1, 0xF1FF, + 0xF201, 0xF20F, 0xF210, 0xF212, 0xF21E, 0xF221, + 0xF22F, 0xF2E1, 0xF2EF, 0xF2F0, 0xF2F2, 0xF2FE, + 0xFE01, 0xFE0F, 0xFE10, 0xFE12, 0xFE1E, 0xFE21, + 0xFE2F, 0xFEE1, 0xFEEF, 0xFEF0, 0xFEF2, 0xFEFE, + 0xFF00, 0xFF02, 0xFF0E, 0xFF11, 0xFF1F, 0xFF20, + 0xFF22, 0xFF2E, 0xFFE0, 0xFFE2, 0xFFEE, 0xFFF1, + 0xFFFF, +}; + +#define ON2AVC_CB4_CODES 313 +static const uint32_t on2avc_cb4_codes[ON2AVC_CB4_CODES] = { + 0x000A, 0x013B, 0x0127, 0x0004, 0x0015, 0x012C, + 0x065F, 0x08CD, 0x016A, 0x08E7, 0x06BA, 0x001B, + 0x001D, 0x0018, 0x000A, 0x0002, 0x00C0, 0x012B, + 0x00CE, 0x013C, 0x012A, 0x012D, 0x0020, 0x0128, + 0x0121, 0x00FC, 0x066B, 0x0472, 0x010A, 0x004E, + 0x06AE, 0x063F, 0x1ABF, 0x0B4E, 0x084E, 0x1ABE, + 0x010E, 0x0094, 0x00C8, 0x0464, 0x069A, 0x00C9, + 0x00FA, 0x041B, 0x2FDE, 0x08CB, 0x05B7, 0x1ABD, + 0x066A, 0x008D, 0x00F8, 0x0003, 0x001A, 0x001E, + 0x0120, 0x011E, 0x0138, 0x0125, 0x0170, 0x00C4, + 0x000B, 0x013E, 0x00C5, 0x000C, 0x000E, 0x001C, + 0x00FE, 0x009C, 0x010F, 0x0115, 0x009F, 0x008C, + 0x0008, 0x002E, 0x00CF, 0x001C, 0x0110, 0x002F, + 0x002C, 0x0002, 0x0116, 0x01FE, 0x032D, 0x00CB, + 0x030D, 0x02EC, 0x002E, 0x0037, 0x00CF, 0x0086, + 0x00C8, 0x032C, 0x031E, 0x01AC, 0x030C, 0x02ED, + 0x035C, 0x013A, 0x02FF, 0x02E2, 0x00BE, 0x00CE, + 0x0126, 0x0356, 0x034E, 0x0347, 0x025F, 0x0306, + 0x02DA, 0x0168, 0x02E7, 0x020F, 0x0016, 0x0081, + 0x0114, 0x0024, 0x001B, 0x010C, 0x03FE, 0x027F, + 0x0084, 0x02F9, 0x0237, 0x0000, 0x001A, 0x011A, + 0x05A6, 0x04A6, 0x00F9, 0x00CC, 0x05B6, 0x0BF6, + 0x0B96, 0x0446, 0x08CE, 0x007F, 0x002C, 0x000E, + 0x0080, 0x00C9, 0x00BA, 0x035E, 0x03EF, 0x0345, + 0x02FE, 0x02FB, 0x02E6, 0x00D2, 0x021C, 0x0238, + 0x06BB, 0x0B97, 0x007E, 0x01AA, 0x023A, 0x05BE, + 0x031D, 0x094E, 0x1ABC, 0x0948, 0x088E, 0x02E4, + 0x0273, 0x084C, 0x08CC, 0x094B, 0x02D2, 0x023B, + 0x043E, 0x2FDF, 0x063E, 0x109B, 0x08CA, 0x08E6, + 0x02DE, 0x02F4, 0x00D4, 0x002D, 0x00CA, 0x020E, + 0x0344, 0x02FD, 0x030F, 0x02EE, 0x02D6, 0x0123, + 0x02F7, 0x03ED, 0x009E, 0x05CA, 0x060E, 0x000D, + 0x004D, 0x0444, 0x043F, 0x094A, 0x05FA, 0x109A, + 0x0B4F, 0x00FD, 0x0117, 0x0096, 0x0082, 0x0122, + 0x025D, 0x0304, 0x034C, 0x027B, 0x035B, 0x02FC, + 0x00FC, 0x035F, 0x03EE, 0x088B, 0x0C1E, 0x088A, + 0x02F5, 0x0272, 0x17EE, 0x0C1F, 0x084F, 0x088F, + 0x069B, 0x0949, 0x023F, 0x02E3, 0x07FE, 0x041A, + 0x0B7E, 0x027A, 0x0336, 0x07FF, 0x08CF, 0x094F, + 0x065E, 0x0B7F, 0x02DD, 0x0212, 0x01FB, 0x00C6, + 0x0095, 0x00D0, 0x023E, 0x025C, 0x02FC, 0x032E, + 0x025E, 0x021E, 0x00BC, 0x021D, 0x035A, 0x0007, + 0x000F, 0x0006, 0x00C2, 0x000C, 0x00BD, 0x00CD, + 0x0113, 0x0118, 0x001D, 0x00CA, 0x008E, 0x0014, + 0x010D, 0x0085, 0x0001, 0x003E, 0x008F, 0x0236, + 0x030E, 0x00FF, 0x025E, 0x0337, 0x000A, 0x0026, + 0x010B, 0x009D, 0x012E, 0x025F, 0x02EF, 0x0305, + 0x02DC, 0x027E, 0x02FE, 0x0124, 0x034F, 0x003E, + 0x004F, 0x00BC, 0x016C, 0x02D7, 0x03EC, 0x02FA, + 0x02F8, 0x02F6, 0x01FA, 0x00CC, 0x02FF, 0x0334, + 0x001E, 0x004C, 0x0112, 0x0036, 0x0022, 0x00FE, + 0x031C, 0x0346, 0x0108, 0x020C, 0x001E, 0x0012, + 0x0026, +}; + +static const uint8_t on2avc_cb4_bits[ON2AVC_CB4_CODES] = { + 4, 9, 9, 6, 6, 9, + 11, 12, 9, 12, 11, 6, + 5, 6, 6, 6, 8, 9, + 8, 9, 9, 9, 6, 9, + 9, 9, 11, 11, 9, 9, + 11, 11, 13, 12, 12, 13, + 9, 9, 9, 11, 11, 9, + 9, 12, 14, 12, 11, 13, + 11, 9, 9, 6, 6, 6, + 9, 9, 9, 9, 9, 8, + 6, 9, 8, 6, 6, 6, + 8, 9, 9, 9, 9, 9, + 6, 9, 8, 5, 9, 9, + 6, 7, 9, 9, 10, 9, + 10, 10, 7, 6, 9, 9, + 8, 10, 10, 9, 10, 10, + 10, 9, 11, 10, 9, 9, + 9, 10, 10, 10, 10, 10, + 10, 9, 10, 11, 6, 9, + 9, 7, 7, 9, 10, 10, + 9, 10, 10, 7, 7, 9, + 11, 11, 9, 9, 11, 12, + 12, 11, 12, 12, 9, 9, + 9, 8, 8, 10, 11, 10, + 11, 10, 10, 8, 11, 10, + 11, 12, 12, 9, 10, 11, + 10, 12, 13, 12, 12, 10, + 10, 12, 12, 12, 10, 10, + 12, 14, 11, 13, 12, 12, + 10, 10, 8, 9, 8, 11, + 10, 11, 10, 10, 10, 9, + 10, 11, 9, 11, 11, 9, + 9, 11, 12, 12, 11, 13, + 12, 9, 9, 9, 9, 9, + 11, 10, 10, 10, 10, 11, + 8, 10, 11, 12, 12, 12, + 10, 10, 13, 12, 12, 12, + 11, 12, 10, 10, 11, 12, + 12, 10, 10, 11, 12, 12, + 11, 12, 10, 10, 9, 8, + 9, 8, 10, 11, 10, 10, + 11, 11, 8, 11, 10, 6, + 6, 6, 8, 9, 9, 9, + 9, 9, 6, 9, 9, 6, + 9, 9, 7, 6, 9, 10, + 10, 9, 10, 10, 7, 7, + 9, 9, 9, 11, 10, 10, + 10, 10, 10, 9, 10, 11, + 9, 9, 9, 10, 11, 10, + 10, 10, 9, 8, 10, 10, + 5, 9, 9, 6, 7, 9, + 10, 10, 9, 11, 10, 7, + 6, +}; + +static const uint16_t on2avc_cb4_syms[ON2AVC_CB4_CODES] = { + 0x0000, 0x0002, 0x000E, 0x0011, 0x001F, 0x0020, + 0x0022, 0x002E, 0x00E0, 0x00E2, 0x00EE, 0x00F1, + 0x00FF, 0x0101, 0x010F, 0x0110, 0x0112, 0x011E, + 0x0121, 0x012F, 0x01E1, 0x01EF, 0x01F0, 0x01F2, + 0x01FE, 0x0200, 0x0202, 0x020E, 0x0211, 0x021F, + 0x0220, 0x0222, 0x022E, 0x02E0, 0x02E2, 0x02EE, + 0x02F1, 0x02FF, 0x0E00, 0x0E02, 0x0E0E, 0x0E11, + 0x0E1F, 0x0E20, 0x0E22, 0x0E2E, 0x0EE0, 0x0EE2, + 0x0EEE, 0x0EF1, 0x0EFF, 0x0F01, 0x0F0F, 0x0F10, + 0x0F12, 0x0F1E, 0x0F21, 0x0F2F, 0x0FE1, 0x0FEF, + 0x0FF0, 0x0FF2, 0x0FFE, 0x1001, 0x100F, 0x1010, + 0x1012, 0x101E, 0x1021, 0x102F, 0x10E1, 0x10EF, + 0x10F0, 0x10F2, 0x10FE, 0x1100, 0x1102, 0x110E, + 0x1111, 0x111F, 0x1120, 0x1122, 0x112E, 0x11E0, + 0x11E2, 0x11EE, 0x11F1, 0x11FF, 0x1201, 0x120F, + 0x1210, 0x1212, 0x121E, 0x1221, 0x122F, 0x12E1, + 0x12EF, 0x12F0, 0x12F2, 0x12FE, 0x1E01, 0x1E0F, + 0x1E10, 0x1E12, 0x1E1E, 0x1E21, 0x1E2F, 0x1EE1, + 0x1EEF, 0x1EF0, 0x1EF2, 0x1EFE, 0x1F00, 0x1F02, + 0x1F0E, 0x1F11, 0x1F1F, 0x1F20, 0x1F22, 0x1F2E, + 0x1FE0, 0x1FE2, 0x1FEE, 0x1FF1, 0x1FFF, 0x2000, + 0x2002, 0x200E, 0x2011, 0x201F, 0x2020, 0x2022, + 0x202E, 0x20E0, 0x20E2, 0x20EE, 0x20F1, 0x20FF, + 0x2101, 0x210F, 0x2110, 0x2112, 0x211E, 0x2121, + 0x212F, 0x21E1, 0x21EF, 0x21F0, 0x21F2, 0x21FE, + 0x2200, 0x2202, 0x220E, 0x2211, 0x221F, 0x2220, + 0x2222, 0x222E, 0x22E0, 0x22E2, 0x22EE, 0x22F1, + 0x22FF, 0x2E00, 0x2E02, 0x2E0E, 0x2E11, 0x2E1F, + 0x2E20, 0x2E22, 0x2E2E, 0x2EE0, 0x2EE2, 0x2EEE, + 0x2EF1, 0x2EFF, 0x2F01, 0x2F0F, 0x2F10, 0x2F12, + 0x2F1E, 0x2F21, 0x2F2F, 0x2FE1, 0x2FEF, 0x2FF0, + 0x2FF2, 0x2FFE, 0xE000, 0xE002, 0xE00E, 0xE011, + 0xE01F, 0xE020, 0xE022, 0xE02E, 0xE0E0, 0xE0E2, + 0xE0EE, 0xE0F1, 0xE0FF, 0xE101, 0xE10F, 0xE110, + 0xE112, 0xE11E, 0xE121, 0xE12F, 0xE1E1, 0xE1EF, + 0xE1F0, 0xE1F2, 0xE1FE, 0xE200, 0xE202, 0xE20E, + 0xE211, 0xE21F, 0xE220, 0xE222, 0xE22E, 0xE2E0, + 0xE2E2, 0xE2EE, 0xE2F1, 0xE2FF, 0xEE00, 0xEE02, + 0xEE0E, 0xEE11, 0xEE1F, 0xEE20, 0xEE22, 0xEE2E, + 0xEEE0, 0xEEE2, 0xEEEE, 0xEEF1, 0xEEFF, 0xEF01, + 0xEF0F, 0xEF10, 0xEF12, 0xEF1E, 0xEF21, 0xEF2F, + 0xEFE1, 0xEFEF, 0xEFF0, 0xEFF2, 0xEFFE, 0xF001, + 0xF00F, 0xF010, 0xF012, 0xF01E, 0xF021, 0xF02F, + 0xF0E1, 0xF0EF, 0xF0F0, 0xF0F2, 0xF0FE, 0xF100, + 0xF102, 0xF10E, 0xF111, 0xF11F, 0xF120, 0xF122, + 0xF12E, 0xF1E0, 0xF1E2, 0xF1EE, 0xF1F1, 0xF1FF, + 0xF201, 0xF20F, 0xF210, 0xF212, 0xF21E, 0xF221, + 0xF22F, 0xF2E1, 0xF2EF, 0xF2F0, 0xF2F2, 0xF2FE, + 0xFE01, 0xFE0F, 0xFE10, 0xFE12, 0xFE1E, 0xFE21, + 0xFE2F, 0xFEE1, 0xFEEF, 0xFEF0, 0xFEF2, 0xFEFE, + 0xFF00, 0xFF02, 0xFF0E, 0xFF11, 0xFF1F, 0xFF20, + 0xFF22, 0xFF2E, 0xFFE0, 0xFFE2, 0xFFEE, 0xFFF1, + 0xFFFF, +}; + +#define ON2AVC_CB5_CODES 1201 +static const uint32_t on2avc_cb5_codes[ON2AVC_CB5_CODES] = { + 0x00000, 0x000D6, 0x000E2, 0x00044, 0x0009E, 0x0009A, + 0x0003A, 0x004E6, 0x00A29, 0x007FE, 0x0024A, 0x004EE, + 0x00496, 0x001EE, 0x001C8, 0x008FA, 0x0050F, 0x001EF, + 0x00486, 0x00906, 0x00904, 0x0003E, 0x00094, 0x000A6, + 0x00046, 0x00061, 0x0012A, 0x0020D, 0x00060, 0x00066, + 0x00452, 0x00692, 0x0087E, 0x00242, 0x0050C, 0x008BE, + 0x0024C, 0x0045A, 0x0025A, 0x001C6, 0x002EE, 0x00294, + 0x006CE, 0x001EC, 0x00492, 0x00690, 0x00055, 0x00474, + 0x0063E, 0x00524, 0x04802, 0x04DC5, 0x00DEF, 0x01A62, + 0x00E6A, 0x00A7F, 0x027FB, 0x034B5, 0x036C5, 0x00A3A, + 0x036C6, 0x0219B, 0x00296, 0x0090F, 0x027FA, 0x028C8, + 0x0052A, 0x0127E, 0x0598E, 0x034B4, 0x00C78, 0x0146E, + 0x00F5F, 0x00BAA, 0x00432, 0x0FF63, 0x0598F, 0x0091C, + 0x00257, 0x0240B, 0x014E6, 0x00E6B, 0x05173, 0x01647, + 0x007F9, 0x022F3, 0x04DC6, 0x022F2, 0x0087F, 0x036C7, + 0x01AB9, 0x00C79, 0x06944, 0x043C6, 0x0043E, 0x00218, + 0x031C4, 0x014E5, 0x0093E, 0x0FF62, 0x3FAE0, 0x00328, + 0x00228, 0x01428, 0x03FEA, 0x007A3, 0x034B3, 0x0D23B, + 0x00B29, 0x01AB8, 0x028C7, 0x0598D, 0x00B28, 0x0149B, + 0x0149A, 0x008EE, 0x027F9, 0x07FC0, 0x00CFE, 0x0025E, + 0x01CBB, 0x026EF, 0x00512, 0x0297B, 0x05172, 0x00D36, + 0x00FCA, 0x01EA5, 0x00D86, 0x01FC5, 0x031C3, 0x02CD6, + 0x00276, 0x01F8A, 0x04801, 0x00B2A, 0x00329, 0x00FC9, + 0x03F0C, 0x00D35, 0x01971, 0x04DC4, 0x036C4, 0x00A4F, + 0x00FEA, 0x01FC4, 0x0122A, 0x00058, 0x001CA, 0x0013A, + 0x0005E, 0x00054, 0x0053E, 0x0039E, 0x006C6, 0x00284, + 0x001C2, 0x0087A, 0x0020E, 0x0050E, 0x006F2, 0x00288, + 0x0029E, 0x00457, 0x006F9, 0x005D3, 0x00248, 0x008F7, + 0x00068, 0x0069D, 0x00497, 0x0005F, 0x0091D, 0x00738, + 0x00057, 0x0005A, 0x00A3E, 0x009CF, 0x00D3E, 0x00D87, + 0x00C6B, 0x00CBD, 0x003F6, 0x00A74, 0x00C6E, 0x0049C, + 0x012FE, 0x0137F, 0x00DBB, 0x010DA, 0x00CAB, 0x0127F, + 0x00056, 0x00A2A, 0x0083E, 0x00040, 0x00BAE, 0x00BA2, + 0x0012E, 0x006F0, 0x0096E, 0x0022C, 0x00FDE, 0x011EB, + 0x01ABE, 0x007EA, 0x014E7, 0x011F2, 0x00256, 0x009FC, + 0x0297C, 0x01C13, 0x006F4, 0x00B26, 0x0144E, 0x021EE, + 0x001C0, 0x00707, 0x00B3F, 0x00244, 0x00E0B, 0x02CD8, + 0x034B6, 0x00B2B, 0x00914, 0x027FD, 0x028CA, 0x01396, + 0x014EB, 0x01972, 0x01B71, 0x013BE, 0x00D9A, 0x00D3F, + 0x009C9, 0x014EA, 0x031C6, 0x022F5, 0x027FC, 0x0240D, + 0x0297D, 0x006F5, 0x02CD7, 0x0396A, 0x0018C, 0x04DC7, + 0x028CB, 0x007E7, 0x0D23C, 0x043C8, 0x008FC, 0x00C7A, + 0x031C7, 0x018EB, 0x0396B, 0x0D23D, 0x036C9, 0x01973, + 0x018EA, 0x07FC1, 0x08FD8, 0x01673, 0x0067C, 0x027FE, + 0x036C8, 0x004BE, 0x08FD9, 0x07FC2, 0x009B6, 0x00148, + 0x026F0, 0x05174, 0x0071C, 0x07279, 0x08FD7, 0x005D4, + 0x00E0A, 0x01A63, 0x01F8B, 0x0114E, 0x01ABA, 0x05990, + 0x043C7, 0x01BEE, 0x3FAE1, 0x1FE94, 0x01CBE, 0x006F3, + 0x018E7, 0x0240C, 0x006FA, 0x03967, 0x08FD6, 0x0045B, + 0x00DBA, 0x01A65, 0x03969, 0x00CFF, 0x0067E, 0x026F1, + 0x028C9, 0x022F4, 0x018D2, 0x01B70, 0x011EA, 0x00BBF, + 0x00B3E, 0x0144D, 0x00D3D, 0x0146F, 0x01A64, 0x01FFF, + 0x01B6F, 0x03968, 0x024EB, 0x00656, 0x031C5, 0x0727A, + 0x0003C, 0x00D22, 0x00D99, 0x0021A, 0x00706, 0x007EE, + 0x0013E, 0x00CBC, 0x01C12, 0x01A66, 0x0022E, 0x00E77, + 0x01672, 0x004D8, 0x006D3, 0x01CBF, 0x01ABB, 0x008BF, + 0x00E76, 0x01BEF, 0x01FC6, 0x001B2, 0x00736, 0x008FB, + 0x0021D, 0x000D7, 0x04804, 0x06948, 0x00D37, 0x0396E, + 0x06949, 0x0120A, 0x03F0F, 0x1437E, 0x043CB, 0x028D0, + 0x0A2BE, 0x08FDD, 0x05996, 0x022F6, 0x1FE96, 0x0FF64, + 0x026F2, 0x028CF, 0x04DCB, 0x03F0E, 0x00A3F, 0x05178, + 0x05995, 0x00BA3, 0x00A4A, 0x07FC8, 0x0727E, 0x007AA, + 0x003D0, 0x0599A, 0x02CDB, 0x034BB, 0x07FC9, 0x0D261, + 0x04805, 0x04806, 0x0727F, 0x022F7, 0x018FE, 0x0240F, + 0x02CDA, 0x031CB, 0x04DCC, 0x034BA, 0x036CB, 0x0052B, + 0x05997, 0x036CE, 0x00907, 0x08FDF, 0x043CD, 0x00E7E, + 0x0517A, 0x04DCD, 0x0197E, 0x0A2BF, 0x028D1, 0x04807, + 0x028D2, 0x04808, 0x0D262, 0x024ED, 0x01ABF, 0x072C0, + 0x1437F, 0x034BE, 0x05179, 0x144F0, 0x072C1, 0x029C1, + 0x08FDE, 0x043CC, 0x023AE, 0x00A3B, 0x1FE97, 0x08FE1, + 0x0142A, 0x006AC, 0x04809, 0x024EE, 0x00C7B, 0x3FAE3, + 0x08FE2, 0x01F8F, 0x0A2C0, 0x023AF, 0x08FE3, 0x02416, + 0x072C2, 0x0FF65, 0x00FCB, 0x08FE0, 0x144F1, 0x01EA6, + 0x00590, 0x04DCE, 0x0396F, 0x01FC7, 0x05991, 0x3FAE2, + 0x0096C, 0x00657, 0x034B8, 0x05992, 0x0240E, 0x0A2BC, + 0x08FDA, 0x0114F, 0x0727C, 0x06945, 0x05175, 0x01B72, + 0x0727B, 0x07FC3, 0x01472, 0x0A2BB, 0x0D23E, 0x00CBE, + 0x00636, 0x034B7, 0x043C9, 0x008AA, 0x08FDB, 0x0D23F, + 0x02852, 0x0727D, 0x05994, 0x00E3E, 0x031CA, 0x06947, + 0x04DC8, 0x02CD9, 0x1FE95, 0x0D260, 0x028CD, 0x024EC, + 0x04803, 0x07FC4, 0x01976, 0x028CC, 0x05993, 0x07FC5, + 0x027FF, 0x06946, 0x03FEB, 0x03F0D, 0x0096D, 0x08FDC, + 0x04DC9, 0x0097E, 0x003D3, 0x0A2BD, 0x0286E, 0x07FC6, + 0x07FC7, 0x034B9, 0x029C0, 0x01F8E, 0x04DCA, 0x05177, + 0x01977, 0x03FEE, 0x0297E, 0x028CE, 0x036CA, 0x05176, + 0x0297F, 0x00596, 0x02853, 0x043CA, 0x0090E, 0x144FA, + 0x0D26A, 0x008AB, 0x000CE, 0x072C3, 0x034BF, 0x02417, + 0x3FAF0, 0x3FAEF, 0x026F3, 0x1FEA0, 0x3FAF1, 0x1FE9F, + 0x0D269, 0x0FF6A, 0x1FE9D, 0x029C6, 0x3FAEE, 0x1FE9E, + 0x036CF, 0x001AA, 0x0480E, 0x0A2C7, 0x000A0, 0x07FCE, + 0x3FAF4, 0x008F8, 0x3FAF5, 0x144FB, 0x00A16, 0x024EF, + 0x04DD3, 0x0694E, 0x1FEA2, 0x3FAF7, 0x3FAF6, 0x0D26B, + 0x04DD2, 0x3FAF2, 0x1FEA1, 0x08FE6, 0x0122B, 0x08FE7, + 0x0480F, 0x00C6F, 0x0FF6B, 0x3FAF3, 0x008EF, 0x00C7E, + 0x3FAF8, 0x1FEA4, 0x00DF6, 0x00362, 0x0694F, 0x0599B, + 0x0142B, 0x1FEA6, 0x1FEA5, 0x03FEF, 0x07FCF, 0x1FEA7, + 0x3FAF9, 0x029C7, 0x0D26E, 0x144FE, 0x01C3E, 0x1FEA3, + 0x0A2CA, 0x01CE6, 0x0049E, 0x043CF, 0x04EFE, 0x0036B, + 0x3FAFE, 0x11F32, 0x01EAE, 0x1FEAA, 0x0D26F, 0x049D2, + 0x02EAE, 0x0356A, 0x08FEA, 0x07ABE, 0x08FEB, 0x3FAFF, + 0x1FEAB, 0x0292E, 0x144FF, 0x3FAFA, 0x08FE8, 0x01EA7, + 0x0B27A, 0x0A2CB, 0x0164E, 0x3FAFB, 0x08FE9, 0x021EF, + 0x00A76, 0x1FE9A, 0x144F2, 0x029C3, 0x3FAE8, 0x3FAE7, + 0x014EE, 0x03F12, 0x0D264, 0x08FE4, 0x0FF67, 0x1FE9B, + 0x144F3, 0x0FF66, 0x0D263, 0x3FAE5, 0x3FAE4, 0x029C2, + 0x031FE, 0x0A2C1, 0x1FE98, 0x01FD6, 0x3FAE6, 0x1FE99, + 0x01473, 0x00D9B, 0x144F5, 0x144F4, 0x00FD2, 0x0036A, + 0x043CE, 0x03F13, 0x0517B, 0x0D267, 0x144F6, 0x01756, + 0x0A2C2, 0x144F8, 0x144F7, 0x0480A, 0x0FF68, 0x0D265, + 0x01B73, 0x0D266, 0x3FAE9, 0x01A67, 0x00493, 0x0694B, + 0x0694A, 0x00082, 0x03F7E, 0x04DCF, 0x009B7, 0x3FAEB, + 0x1FE9C, 0x0071D, 0x028D3, 0x0D268, 0x0A2C5, 0x0A2C6, + 0x3FAED, 0x3FAEC, 0x08FE5, 0x07FCA, 0x3FAEA, 0x144F9, + 0x0A2C3, 0x00D3C, 0x07FCB, 0x0480B, 0x009CA, 0x0FF69, + 0x0A2C4, 0x0091E, 0x007EB, 0x1FE85, 0x0FF56, 0x0091F, + 0x0019E, 0x0693A, 0x0593E, 0x020FC, 0x1FE86, 0x0FF57, + 0x027F4, 0x0146A, 0x04BFC, 0x0CBF9, 0x0CBF8, 0x1FE83, + 0x3F7F5, 0x08F9E, 0x3F7F6, 0x1FE84, 0x036C0, 0x00098, + 0x0593C, 0x071F9, 0x0006E, 0x0593F, 0x03963, 0x00A3C, + 0x13BFD, 0x1FE89, 0x007F2, 0x00FD3, 0x03F08, 0x03D5E, + 0x034A9, 0x13BFF, 0x13BFE, 0x071FA, 0x011E8, 0x1FE87, + 0x3F7F7, 0x0FF58, 0x01B66, 0x07FB8, 0x05168, 0x0070E, + 0x0FF59, 0x1FE88, 0x009B3, 0x00BBC, 0x1FE8B, 0x3F7F8, + 0x00FE6, 0x004FC, 0x0CBFC, 0x03FE6, 0x022F0, 0x1FE8C, + 0x0CBFD, 0x01CE7, 0x08F9F, 0x0FF5A, 0x071FD, 0x1FE8A, + 0x071FB, 0x14378, 0x01AB4, 0x0CBFB, 0x0CBFA, 0x036C1, + 0x0037E, 0x05980, 0x071FC, 0x00D5E, 0x3F7FC, 0x08FD0, + 0x014EF, 0x3F7FE, 0x3F7FD, 0x01CFE, 0x01FBE, 0x05982, + 0x1437A, 0x04BFD, 0x1FE8E, 0x3F7FF, 0x071FF, 0x0FF5B, + 0x1FE8D, 0x3F7F9, 0x14379, 0x047F7, 0x05981, 0x071FE, + 0x014E2, 0x3F7FB, 0x3F7FA, 0x02CCE, 0x0037F, 0x0A27E, + 0x3D5FA, 0x02CCC, 0x1FE80, 0x1FD7E, 0x01496, 0x018E4, + 0x3D5FB, 0x05164, 0x070FD, 0x3D5FC, 0x11F33, 0x0277E, + 0x0FF54, 0x08F98, 0x07FB6, 0x070FC, 0x026E8, 0x07FB7, + 0x034A6, 0x0356B, 0x3D5F9, 0x3D5F8, 0x034A8, 0x0114C, + 0x3F7F0, 0x3D5FF, 0x00C74, 0x0024D, 0x05167, 0x049D3, + 0x0292F, 0x08F9C, 0x3F7F1, 0x01CB6, 0x03962, 0x070FF, + 0x08F9D, 0x08F9A, 0x3D5FD, 0x0A2B0, 0x024E8, 0x070FE, + 0x3D5FE, 0x01A5E, 0x00392, 0x08F9B, 0x05166, 0x00099, + 0x06939, 0x06938, 0x009B2, 0x0C7FE, 0x3F7F4, 0x007F7, + 0x011D6, 0x02EAF, 0x028BE, 0x071F8, 0x0C7FF, 0x1FE82, + 0x047F6, 0x06936, 0x3F7F3, 0x3F7F2, 0x1FE81, 0x026EA, + 0x0C7FC, 0x0B27B, 0x009FA, 0x0C7FD, 0x13BFC, 0x007A8, + 0x000D4, 0x08FD1, 0x0D234, 0x00D34, 0x07274, 0x05988, + 0x00F5C, 0x0516D, 0x0516E, 0x0516C, 0x036C3, 0x0A2B4, + 0x0D235, 0x036C2, 0x034AC, 0x0D233, 0x07FBA, 0x034AB, + 0x0A2B3, 0x1437D, 0x1437C, 0x00B3B, 0x07273, 0x0516B, + 0x00D84, 0x009FB, 0x0693F, 0x0598A, 0x007F8, 0x005D6, + 0x047FB, 0x024EA, 0x026EC, 0x0516F, 0x047FC, 0x031A7, + 0x01397, 0x026ED, 0x02975, 0x02CD1, 0x034AD, 0x07275, + 0x027F6, 0x05989, 0x043C1, 0x0693E, 0x00454, 0x034AE, + 0x043C2, 0x007F6, 0x0A2B7, 0x07FBB, 0x02408, 0x0598B, + 0x047FD, 0x01B6A, 0x04DC1, 0x0FF5F, 0x07FBC, 0x01B6B, + 0x07277, 0x0D236, 0x020FD, 0x01B68, 0x0A2B5, 0x0FF5E, + 0x02976, 0x043C3, 0x02977, 0x0A2B6, 0x012DE, 0x07276, + 0x03FE9, 0x01B69, 0x00A4C, 0x0FF60, 0x1FE93, 0x013BC, + 0x00592, 0x02978, 0x02CD3, 0x00D8E, 0x0D237, 0x05170, + 0x01FC1, 0x028C2, 0x06941, 0x0D238, 0x07278, 0x034AF, + 0x06940, 0x00E5E, 0x08FD2, 0x07FBD, 0x020FE, 0x007E6, + 0x043C4, 0x02CD2, 0x0166E, 0x0CBFF, 0x0CBFE, 0x00A5C, + 0x005D0, 0x026EB, 0x047F8, 0x01F88, 0x1FE90, 0x1FE8F, + 0x00C68, 0x021EC, 0x0A2B1, 0x0D230, 0x04BFE, 0x0693B, + 0x028BF, 0x028C0, 0x07270, 0x0FF5C, 0x00E08, 0x00360, + 0x0436C, 0x05983, 0x009BE, 0x0FF5D, 0x1FE91, 0x01A60, + 0x04BFF, 0x0A2B2, 0x0436E, 0x03F0A, 0x07FB9, 0x05984, + 0x01FC0, 0x1FE92, 0x1437B, 0x01646, 0x03F09, 0x0693C, + 0x027F5, 0x047F9, 0x034AA, 0x0D231, 0x0436D, 0x01AB6, + 0x047FA, 0x07271, 0x00CFA, 0x006CF, 0x07272, 0x05986, + 0x00B3A, 0x00654, 0x028C1, 0x0436F, 0x02CD0, 0x03FE8, + 0x05987, 0x043C0, 0x0146B, 0x02974, 0x031A6, 0x02CCF, + 0x03964, 0x04DC0, 0x0516A, 0x05985, 0x05169, 0x02406, + 0x003D6, 0x0D232, 0x0693D, 0x0005C, 0x006F6, 0x0086E, + 0x00062, 0x0005B, 0x006F1, 0x007E0, 0x00D98, 0x00BBE, + 0x00E72, 0x00D8F, 0x004DA, 0x0137B, 0x0137A, 0x00386, + 0x00A7E, 0x00C6A, 0x00CBA, 0x00F5E, 0x00F5D, 0x013BD, + 0x00064, 0x009CE, 0x008EC, 0x0003B, 0x00F56, 0x00CAA, + 0x00246, 0x008ED, 0x0086C, 0x001ED, 0x00C77, 0x0240A, + 0x01B6D, 0x0086F, 0x02CD5, 0x01FC3, 0x0073E, 0x005D2, + 0x01970, 0x014E4, 0x00456, 0x00B22, 0x0114D, 0x02198, + 0x00138, 0x0069C, 0x00737, 0x0020C, 0x00A4E, 0x04DC2, + 0x018E6, 0x00E1E, 0x006D2, 0x047FF, 0x02979, 0x01FFE, + 0x04800, 0x021ED, 0x028C6, 0x00917, 0x01671, 0x01CFF, + 0x00CFB, 0x00FE7, 0x00A1A, 0x0146D, 0x01670, 0x01B6E, + 0x0137E, 0x006D1, 0x01FFD, 0x028C5, 0x00176, 0x05171, + 0x0219A, 0x0023C, 0x0A2BA, 0x043C5, 0x006F8, 0x006DF, + 0x01EA4, 0x01CBA, 0x027F8, 0x0FF61, 0x08FD5, 0x0177B, + 0x02199, 0x0D23A, 0x03966, 0x0297A, 0x00A38, 0x0177A, + 0x01A61, 0x00597, 0x07FBF, 0x04DC3, 0x007F4, 0x00196, + 0x034B0, 0x03F0B, 0x008F6, 0x0598C, 0x08FD3, 0x003D2, + 0x006D0, 0x01FC2, 0x031C1, 0x026EE, 0x0A2B9, 0x0D239, + 0x0175F, 0x0175E, 0x031C0, 0x06942, 0x01FF6, 0x00A3D, + 0x0166F, 0x027F7, 0x009C8, 0x0A2B8, 0x07FBE, 0x00734, + 0x00FC6, 0x03965, 0x06943, 0x010CF, 0x006DE, 0x02CD4, + 0x08FD4, 0x034B2, 0x01CB8, 0x028C3, 0x01FFC, 0x0041E, + 0x0146C, 0x01B6C, 0x00C76, 0x00B3C, 0x010CE, 0x022F1, + 0x0144C, 0x012DF, 0x01436, 0x0073A, 0x034B1, 0x031C2, + 0x00042, 0x00DEE, 0x00B3D, 0x001CC, 0x00A17, 0x007E8, + 0x0021C, 0x00A28, 0x01CB9, 0x02409, 0x00916, 0x020FF, + 0x047FE, 0x00726, 0x00238, 0x011E9, 0x01AB7, 0x0071E, + 0x00FC8, 0x028C4, 0x00D85, 0x00239, 0x008EA, 0x007A2, + 0x0012C, +}; + +static const uint8_t on2avc_cb5_bits[ON2AVC_CB5_CODES] = { + 1, 8, 8, 7, 8, 8, + 6, 11, 12, 11, 10, 11, + 11, 9, 9, 12, 11, 9, + 11, 12, 12, 6, 8, 8, + 7, 7, 9, 10, 7, 7, + 11, 11, 12, 10, 11, 12, + 10, 11, 10, 9, 10, 10, + 11, 9, 11, 11, 7, 11, + 11, 11, 15, 15, 12, 13, + 12, 12, 14, 14, 14, 12, + 14, 14, 10, 12, 14, 14, + 11, 13, 15, 14, 12, 13, + 12, 12, 11, 16, 15, 12, + 10, 14, 13, 12, 15, 13, + 11, 14, 15, 14, 12, 14, + 13, 12, 15, 15, 11, 10, + 14, 13, 12, 16, 18, 10, + 10, 13, 14, 11, 14, 16, + 12, 13, 14, 15, 12, 13, + 13, 12, 14, 15, 12, 10, + 13, 14, 11, 14, 15, 12, + 12, 13, 12, 13, 14, 14, + 10, 13, 15, 12, 10, 12, + 14, 12, 13, 15, 14, 12, + 12, 13, 13, 7, 9, 9, + 7, 7, 11, 10, 11, 10, + 9, 12, 10, 11, 11, 10, + 10, 11, 11, 11, 10, 12, + 7, 11, 11, 7, 12, 11, + 7, 7, 12, 12, 12, 12, + 12, 12, 10, 12, 12, 11, + 13, 13, 12, 13, 12, 13, + 7, 12, 12, 7, 12, 12, + 9, 11, 12, 10, 12, 13, + 13, 11, 13, 13, 10, 12, + 14, 13, 11, 12, 13, 14, + 9, 11, 12, 10, 12, 14, + 14, 12, 12, 14, 14, 13, + 13, 13, 13, 13, 12, 12, + 12, 13, 14, 14, 14, 14, + 14, 11, 14, 14, 9, 15, + 14, 11, 16, 15, 12, 12, + 14, 13, 14, 16, 14, 13, + 13, 15, 16, 13, 11, 14, + 14, 11, 16, 15, 12, 9, + 14, 15, 11, 15, 16, 11, + 12, 13, 13, 13, 13, 15, + 15, 13, 18, 17, 13, 11, + 13, 14, 11, 14, 16, 11, + 12, 13, 14, 12, 11, 14, + 14, 14, 13, 13, 13, 12, + 12, 13, 12, 13, 13, 13, + 13, 14, 14, 11, 14, 15, + 6, 12, 12, 10, 11, 11, + 9, 12, 13, 13, 10, 12, + 13, 11, 11, 13, 13, 12, + 12, 13, 13, 9, 11, 12, + 10, 8, 15, 15, 12, 14, + 15, 13, 14, 17, 15, 14, + 16, 16, 15, 14, 17, 16, + 14, 14, 15, 14, 12, 15, + 15, 12, 12, 15, 15, 11, + 10, 15, 14, 14, 15, 16, + 15, 15, 15, 14, 13, 14, + 14, 14, 15, 14, 14, 11, + 15, 14, 12, 16, 15, 12, + 15, 15, 13, 16, 14, 15, + 14, 15, 16, 14, 13, 15, + 17, 14, 15, 17, 15, 14, + 16, 15, 14, 12, 17, 16, + 13, 11, 15, 14, 12, 18, + 16, 13, 16, 14, 16, 14, + 15, 16, 12, 16, 17, 13, + 11, 15, 14, 13, 15, 18, + 12, 11, 14, 15, 14, 16, + 16, 13, 15, 15, 15, 13, + 15, 15, 13, 16, 16, 12, + 11, 14, 15, 12, 16, 16, + 14, 15, 15, 12, 14, 15, + 15, 14, 17, 16, 14, 14, + 15, 15, 13, 14, 15, 15, + 14, 15, 14, 14, 12, 16, + 15, 12, 10, 16, 14, 15, + 15, 14, 14, 13, 15, 15, + 13, 14, 14, 14, 14, 15, + 14, 11, 14, 15, 12, 17, + 16, 12, 8, 15, 14, 14, + 18, 18, 14, 17, 18, 17, + 16, 16, 17, 14, 18, 17, + 14, 9, 15, 16, 8, 15, + 18, 12, 18, 17, 12, 14, + 15, 15, 17, 18, 18, 16, + 15, 18, 17, 16, 13, 16, + 15, 12, 16, 18, 12, 12, + 18, 17, 12, 10, 15, 15, + 13, 17, 17, 14, 15, 17, + 18, 14, 16, 17, 13, 17, + 16, 13, 11, 15, 15, 10, + 18, 17, 13, 17, 16, 15, + 14, 14, 16, 15, 16, 18, + 17, 14, 17, 18, 16, 13, + 16, 16, 13, 18, 16, 14, + 12, 17, 17, 14, 18, 18, + 13, 14, 16, 16, 16, 17, + 17, 16, 16, 18, 18, 14, + 14, 16, 17, 13, 18, 17, + 13, 12, 17, 17, 12, 10, + 15, 14, 15, 16, 17, 13, + 16, 17, 17, 15, 16, 16, + 13, 16, 18, 13, 11, 15, + 15, 8, 14, 15, 12, 18, + 17, 11, 14, 16, 16, 16, + 18, 18, 16, 15, 18, 17, + 16, 12, 15, 15, 12, 16, + 16, 12, 11, 17, 16, 12, + 9, 15, 15, 14, 17, 16, + 14, 13, 15, 16, 16, 17, + 18, 16, 18, 17, 14, 8, + 15, 15, 7, 15, 14, 12, + 17, 17, 11, 12, 14, 14, + 14, 17, 17, 15, 13, 17, + 18, 16, 13, 15, 15, 11, + 16, 17, 12, 12, 17, 18, + 12, 11, 16, 14, 14, 17, + 16, 13, 16, 16, 15, 17, + 15, 17, 13, 16, 16, 14, + 10, 15, 15, 12, 18, 16, + 13, 18, 18, 13, 13, 15, + 17, 15, 17, 18, 15, 16, + 17, 18, 17, 15, 15, 15, + 13, 18, 18, 14, 10, 16, + 18, 14, 17, 17, 13, 13, + 18, 15, 15, 18, 17, 14, + 16, 16, 15, 15, 14, 15, + 14, 14, 18, 18, 14, 13, + 18, 18, 12, 10, 15, 15, + 14, 16, 18, 13, 14, 15, + 16, 16, 18, 16, 14, 15, + 18, 13, 10, 16, 15, 8, + 15, 15, 12, 16, 18, 11, + 13, 14, 14, 15, 16, 17, + 15, 15, 18, 18, 17, 14, + 16, 16, 12, 16, 17, 11, + 8, 16, 16, 12, 15, 15, + 12, 15, 15, 15, 14, 16, + 16, 14, 14, 16, 15, 14, + 16, 17, 17, 12, 15, 15, + 12, 12, 15, 15, 11, 11, + 15, 14, 14, 15, 15, 14, + 13, 14, 14, 14, 14, 15, + 14, 15, 15, 15, 11, 14, + 15, 11, 16, 15, 14, 15, + 15, 13, 15, 16, 15, 13, + 15, 16, 14, 13, 16, 16, + 14, 15, 14, 16, 13, 15, + 14, 13, 12, 16, 17, 13, + 11, 14, 14, 12, 16, 15, + 13, 14, 15, 16, 15, 14, + 15, 12, 16, 15, 14, 11, + 15, 14, 13, 16, 16, 12, + 11, 14, 15, 13, 17, 17, + 12, 14, 16, 16, 15, 15, + 14, 14, 15, 16, 12, 10, + 15, 15, 12, 16, 17, 13, + 15, 16, 15, 14, 15, 15, + 13, 17, 17, 13, 14, 15, + 14, 15, 14, 16, 15, 13, + 15, 15, 12, 11, 15, 15, + 12, 11, 14, 15, 14, 14, + 15, 15, 13, 14, 14, 14, + 14, 15, 15, 15, 15, 14, + 10, 16, 15, 7, 11, 12, + 7, 7, 11, 11, 12, 12, + 12, 12, 11, 13, 13, 10, + 12, 12, 12, 12, 12, 13, + 7, 12, 12, 6, 12, 12, + 10, 12, 12, 9, 12, 14, + 13, 12, 14, 13, 11, 11, + 13, 13, 11, 12, 13, 14, + 9, 11, 11, 10, 12, 15, + 13, 12, 11, 15, 14, 13, + 15, 14, 14, 12, 13, 13, + 12, 12, 12, 13, 13, 13, + 13, 11, 13, 14, 9, 15, + 14, 10, 16, 15, 11, 11, + 13, 13, 14, 16, 16, 13, + 14, 16, 14, 14, 12, 13, + 13, 11, 15, 15, 11, 9, + 14, 14, 12, 15, 16, 10, + 11, 13, 14, 14, 16, 16, + 13, 13, 14, 15, 13, 12, + 13, 14, 12, 16, 15, 11, + 12, 14, 15, 13, 11, 14, + 16, 14, 13, 14, 13, 11, + 13, 13, 12, 12, 13, 14, + 13, 13, 13, 11, 14, 14, + 7, 12, 12, 9, 12, 11, + 10, 12, 13, 14, 12, 14, + 15, 11, 10, 13, 13, 11, + 12, 14, 12, 10, 12, 11, + 9, +}; + +static const uint16_t on2avc_cb5_syms[ON2AVC_CB5_CODES] = { + 0x0000, 0x0002, 0x000E, 0x0011, 0x0013, 0x001D, + 0x001F, 0x0020, 0x0022, 0x002E, 0x0031, 0x0033, + 0x003D, 0x003F, 0x00D1, 0x00D3, 0x00DD, 0x00DF, + 0x00E0, 0x00E2, 0x00EE, 0x00F1, 0x00F3, 0x00FD, + 0x00FF, 0x0101, 0x0103, 0x010D, 0x010F, 0x0110, + 0x0112, 0x011E, 0x0121, 0x0123, 0x012D, 0x012F, + 0x0130, 0x0132, 0x013E, 0x01D0, 0x01D2, 0x01DE, + 0x01E1, 0x01E3, 0x01ED, 0x01EF, 0x01F0, 0x01F2, + 0x01FE, 0x0200, 0x0202, 0x020E, 0x0211, 0x0213, + 0x021D, 0x021F, 0x0220, 0x0222, 0x022E, 0x0231, + 0x0233, 0x023D, 0x023F, 0x02D1, 0x02D3, 0x02DD, + 0x02DF, 0x02E0, 0x02E2, 0x02EE, 0x02F1, 0x02F3, + 0x02FD, 0x02FF, 0x0301, 0x0303, 0x030D, 0x030F, + 0x0310, 0x0312, 0x031E, 0x0321, 0x0323, 0x032D, + 0x032F, 0x0330, 0x0332, 0x033E, 0x03D0, 0x03D2, + 0x03DE, 0x03E1, 0x03E3, 0x03ED, 0x03EF, 0x03F0, + 0x03F2, 0x03FE, 0x0D01, 0x0D03, 0x0D0D, 0x0D0F, + 0x0D10, 0x0D12, 0x0D1E, 0x0D21, 0x0D23, 0x0D2D, + 0x0D2F, 0x0D30, 0x0D32, 0x0D3E, 0x0DD0, 0x0DD2, + 0x0DDE, 0x0DE1, 0x0DE3, 0x0DED, 0x0DEF, 0x0DF0, + 0x0DF2, 0x0DFE, 0x0E00, 0x0E02, 0x0E0E, 0x0E11, + 0x0E13, 0x0E1D, 0x0E1F, 0x0E20, 0x0E22, 0x0E2E, + 0x0E31, 0x0E33, 0x0E3D, 0x0E3F, 0x0ED1, 0x0ED3, + 0x0EDD, 0x0EDF, 0x0EE0, 0x0EE2, 0x0EEE, 0x0EF1, + 0x0EF3, 0x0EFD, 0x0EFF, 0x0F01, 0x0F03, 0x0F0D, + 0x0F0F, 0x0F10, 0x0F12, 0x0F1E, 0x0F21, 0x0F23, + 0x0F2D, 0x0F2F, 0x0F30, 0x0F32, 0x0F3E, 0x0FD0, + 0x0FD2, 0x0FDE, 0x0FE1, 0x0FE3, 0x0FED, 0x0FEF, + 0x0FF0, 0x0FF2, 0x0FFE, 0x1001, 0x1003, 0x100D, + 0x100F, 0x1010, 0x1012, 0x101E, 0x1021, 0x1023, + 0x102D, 0x102F, 0x1030, 0x1032, 0x103E, 0x10D0, + 0x10D2, 0x10DE, 0x10E1, 0x10E3, 0x10ED, 0x10EF, + 0x10F0, 0x10F2, 0x10FE, 0x1100, 0x1102, 0x110E, + 0x1111, 0x1113, 0x111D, 0x111F, 0x1120, 0x1122, + 0x112E, 0x1131, 0x1133, 0x113D, 0x113F, 0x11D1, + 0x11D3, 0x11DD, 0x11DF, 0x11E0, 0x11E2, 0x11EE, + 0x11F1, 0x11F3, 0x11FD, 0x11FF, 0x1201, 0x1203, + 0x120D, 0x120F, 0x1210, 0x1212, 0x121E, 0x1221, + 0x1223, 0x122D, 0x122F, 0x1230, 0x1232, 0x123E, + 0x12D0, 0x12D2, 0x12DE, 0x12E1, 0x12E3, 0x12ED, + 0x12EF, 0x12F0, 0x12F2, 0x12FE, 0x1300, 0x1302, + 0x130E, 0x1311, 0x1313, 0x131D, 0x131F, 0x1320, + 0x1322, 0x132E, 0x1331, 0x1333, 0x133D, 0x133F, + 0x13D1, 0x13D3, 0x13DD, 0x13DF, 0x13E0, 0x13E2, + 0x13EE, 0x13F1, 0x13F3, 0x13FD, 0x13FF, 0x1D00, + 0x1D02, 0x1D0E, 0x1D11, 0x1D13, 0x1D1D, 0x1D1F, + 0x1D20, 0x1D22, 0x1D2E, 0x1D31, 0x1D33, 0x1D3D, + 0x1D3F, 0x1DD1, 0x1DD3, 0x1DDD, 0x1DDF, 0x1DE0, + 0x1DE2, 0x1DEE, 0x1DF1, 0x1DF3, 0x1DFD, 0x1DFF, + 0x1E01, 0x1E03, 0x1E0D, 0x1E0F, 0x1E10, 0x1E12, + 0x1E1E, 0x1E21, 0x1E23, 0x1E2D, 0x1E2F, 0x1E30, + 0x1E32, 0x1E3E, 0x1ED0, 0x1ED2, 0x1EDE, 0x1EE1, + 0x1EE3, 0x1EED, 0x1EEF, 0x1EF0, 0x1EF2, 0x1EFE, + 0x1F00, 0x1F02, 0x1F0E, 0x1F11, 0x1F13, 0x1F1D, + 0x1F1F, 0x1F20, 0x1F22, 0x1F2E, 0x1F31, 0x1F33, + 0x1F3D, 0x1F3F, 0x1FD1, 0x1FD3, 0x1FDD, 0x1FDF, + 0x1FE0, 0x1FE2, 0x1FEE, 0x1FF1, 0x1FF3, 0x1FFD, + 0x1FFF, 0x2000, 0x2002, 0x200E, 0x2011, 0x2013, + 0x201D, 0x201F, 0x2020, 0x2022, 0x202E, 0x2031, + 0x2033, 0x203D, 0x203F, 0x20D1, 0x20D3, 0x20DD, + 0x20DF, 0x20E0, 0x20E2, 0x20EE, 0x20F1, 0x20F3, + 0x20FD, 0x20FF, 0x2101, 0x2103, 0x210D, 0x210F, + 0x2110, 0x2112, 0x211E, 0x2121, 0x2123, 0x212D, + 0x212F, 0x2130, 0x2132, 0x213E, 0x21D0, 0x21D2, + 0x21DE, 0x21E1, 0x21E3, 0x21ED, 0x21EF, 0x21F0, + 0x21F2, 0x21FE, 0x2200, 0x2202, 0x220E, 0x2211, + 0x2213, 0x221D, 0x221F, 0x2220, 0x2222, 0x222E, + 0x2231, 0x2233, 0x223D, 0x223F, 0x22D1, 0x22D3, + 0x22DD, 0x22DF, 0x22E0, 0x22E2, 0x22EE, 0x22F1, + 0x22F3, 0x22FD, 0x22FF, 0x2301, 0x2303, 0x230D, + 0x230F, 0x2310, 0x2312, 0x231E, 0x2321, 0x2323, + 0x232D, 0x232F, 0x2330, 0x2332, 0x233E, 0x23D0, + 0x23D2, 0x23DE, 0x23E1, 0x23E3, 0x23ED, 0x23EF, + 0x23F0, 0x23F2, 0x23FE, 0x2D01, 0x2D03, 0x2D0D, + 0x2D0F, 0x2D10, 0x2D12, 0x2D1E, 0x2D21, 0x2D23, + 0x2D2D, 0x2D2F, 0x2D30, 0x2D32, 0x2D3E, 0x2DD0, + 0x2DD2, 0x2DDE, 0x2DE1, 0x2DE3, 0x2DED, 0x2DEF, + 0x2DF0, 0x2DF2, 0x2DFE, 0x2E00, 0x2E02, 0x2E0E, + 0x2E11, 0x2E13, 0x2E1D, 0x2E1F, 0x2E20, 0x2E22, + 0x2E2E, 0x2E31, 0x2E33, 0x2E3D, 0x2E3F, 0x2ED1, + 0x2ED3, 0x2EDD, 0x2EDF, 0x2EE0, 0x2EE2, 0x2EEE, + 0x2EF1, 0x2EF3, 0x2EFD, 0x2EFF, 0x2F01, 0x2F03, + 0x2F0D, 0x2F0F, 0x2F10, 0x2F12, 0x2F1E, 0x2F21, + 0x2F23, 0x2F2D, 0x2F2F, 0x2F30, 0x2F32, 0x2F3E, + 0x2FD0, 0x2FD2, 0x2FDE, 0x2FE1, 0x2FE3, 0x2FED, + 0x2FEF, 0x2FF0, 0x2FF2, 0x2FFE, 0x3001, 0x3003, + 0x300D, 0x300F, 0x3010, 0x3012, 0x301E, 0x3021, + 0x3023, 0x302D, 0x302F, 0x3030, 0x3032, 0x303E, + 0x30D0, 0x30D2, 0x30DE, 0x30E1, 0x30E3, 0x30ED, + 0x30EF, 0x30F0, 0x30F2, 0x30FE, 0x3100, 0x3102, + 0x310E, 0x3111, 0x3113, 0x311D, 0x311F, 0x3120, + 0x3122, 0x312E, 0x3131, 0x3133, 0x313D, 0x313F, + 0x31D1, 0x31D3, 0x31DD, 0x31DF, 0x31E0, 0x31E2, + 0x31EE, 0x31F1, 0x31F3, 0x31FD, 0x31FF, 0x3201, + 0x3203, 0x320D, 0x320F, 0x3210, 0x3212, 0x321E, + 0x3221, 0x3223, 0x322D, 0x322F, 0x3230, 0x3232, + 0x323E, 0x32D0, 0x32D2, 0x32DE, 0x32E1, 0x32E3, + 0x32ED, 0x32EF, 0x32F0, 0x32F2, 0x32FE, 0x3300, + 0x3302, 0x330E, 0x3311, 0x3313, 0x331D, 0x331F, + 0x3320, 0x3322, 0x332E, 0x3331, 0x3333, 0x333D, + 0x333F, 0x33D1, 0x33D3, 0x33DD, 0x33DF, 0x33E0, + 0x33E2, 0x33EE, 0x33F1, 0x33F3, 0x33FD, 0x33FF, + 0x3D00, 0x3D02, 0x3D0E, 0x3D11, 0x3D13, 0x3D1D, + 0x3D1F, 0x3D20, 0x3D22, 0x3D2E, 0x3D31, 0x3D33, + 0x3D3D, 0x3D3F, 0x3DD1, 0x3DD3, 0x3DDD, 0x3DDF, + 0x3DE0, 0x3DE2, 0x3DEE, 0x3DF1, 0x3DF3, 0x3DFD, + 0x3DFF, 0x3E01, 0x3E03, 0x3E0D, 0x3E0F, 0x3E10, + 0x3E12, 0x3E1E, 0x3E21, 0x3E23, 0x3E2D, 0x3E2F, + 0x3E30, 0x3E32, 0x3E3E, 0x3ED0, 0x3ED2, 0x3EDE, + 0x3EE1, 0x3EE3, 0x3EED, 0x3EEF, 0x3EF0, 0x3EF2, + 0x3EFE, 0x3F00, 0x3F02, 0x3F0E, 0x3F11, 0x3F13, + 0x3F1D, 0x3F1F, 0x3F20, 0x3F22, 0x3F2E, 0x3F31, + 0x3F33, 0x3F3D, 0x3F3F, 0x3FD1, 0x3FD3, 0x3FDD, + 0x3FDF, 0x3FE0, 0x3FE2, 0x3FEE, 0x3FF1, 0x3FF3, + 0x3FFD, 0x3FFF, 0xD001, 0xD003, 0xD00D, 0xD00F, + 0xD010, 0xD012, 0xD01E, 0xD021, 0xD023, 0xD02D, + 0xD02F, 0xD030, 0xD032, 0xD03E, 0xD0D0, 0xD0D2, + 0xD0DE, 0xD0E1, 0xD0E3, 0xD0ED, 0xD0EF, 0xD0F0, + 0xD0F2, 0xD0FE, 0xD100, 0xD102, 0xD10E, 0xD111, + 0xD113, 0xD11D, 0xD11F, 0xD120, 0xD122, 0xD12E, + 0xD131, 0xD133, 0xD13D, 0xD13F, 0xD1D1, 0xD1D3, + 0xD1DD, 0xD1DF, 0xD1E0, 0xD1E2, 0xD1EE, 0xD1F1, + 0xD1F3, 0xD1FD, 0xD1FF, 0xD201, 0xD203, 0xD20D, + 0xD20F, 0xD210, 0xD212, 0xD21E, 0xD221, 0xD223, + 0xD22D, 0xD22F, 0xD230, 0xD232, 0xD23E, 0xD2D0, + 0xD2D2, 0xD2DE, 0xD2E1, 0xD2E3, 0xD2ED, 0xD2EF, + 0xD2F0, 0xD2F2, 0xD2FE, 0xD300, 0xD302, 0xD30E, + 0xD311, 0xD313, 0xD31D, 0xD31F, 0xD320, 0xD322, + 0xD32E, 0xD331, 0xD333, 0xD33D, 0xD33F, 0xD3D1, + 0xD3D3, 0xD3DD, 0xD3DF, 0xD3E0, 0xD3E2, 0xD3EE, + 0xD3F1, 0xD3F3, 0xD3FD, 0xD3FF, 0xDD00, 0xDD02, + 0xDD0E, 0xDD11, 0xDD13, 0xDD1D, 0xDD1F, 0xDD20, + 0xDD22, 0xDD2E, 0xDD31, 0xDD33, 0xDD3D, 0xDD3F, + 0xDDD1, 0xDDD3, 0xDDDD, 0xDDDF, 0xDDE0, 0xDDE2, + 0xDDEE, 0xDDF1, 0xDDF3, 0xDDFD, 0xDDFF, 0xDE01, + 0xDE03, 0xDE0D, 0xDE0F, 0xDE10, 0xDE12, 0xDE1E, + 0xDE21, 0xDE23, 0xDE2D, 0xDE2F, 0xDE30, 0xDE32, + 0xDE3E, 0xDED0, 0xDED2, 0xDEDE, 0xDEE1, 0xDEE3, + 0xDEED, 0xDEEF, 0xDEF0, 0xDEF2, 0xDEFE, 0xDF00, + 0xDF02, 0xDF0E, 0xDF11, 0xDF13, 0xDF1D, 0xDF1F, + 0xDF20, 0xDF22, 0xDF2E, 0xDF31, 0xDF33, 0xDF3D, + 0xDF3F, 0xDFD1, 0xDFD3, 0xDFDD, 0xDFDF, 0xDFE0, + 0xDFE2, 0xDFEE, 0xDFF1, 0xDFF3, 0xDFFD, 0xDFFF, + 0xE000, 0xE002, 0xE00E, 0xE011, 0xE013, 0xE01D, + 0xE01F, 0xE020, 0xE022, 0xE02E, 0xE031, 0xE033, + 0xE03D, 0xE03F, 0xE0D1, 0xE0D3, 0xE0DD, 0xE0DF, + 0xE0E0, 0xE0E2, 0xE0EE, 0xE0F1, 0xE0F3, 0xE0FD, + 0xE0FF, 0xE101, 0xE103, 0xE10D, 0xE10F, 0xE110, + 0xE112, 0xE11E, 0xE121, 0xE123, 0xE12D, 0xE12F, + 0xE130, 0xE132, 0xE13E, 0xE1D0, 0xE1D2, 0xE1DE, + 0xE1E1, 0xE1E3, 0xE1ED, 0xE1EF, 0xE1F0, 0xE1F2, + 0xE1FE, 0xE200, 0xE202, 0xE20E, 0xE211, 0xE213, + 0xE21D, 0xE21F, 0xE220, 0xE222, 0xE22E, 0xE231, + 0xE233, 0xE23D, 0xE23F, 0xE2D1, 0xE2D3, 0xE2DD, + 0xE2DF, 0xE2E0, 0xE2E2, 0xE2EE, 0xE2F1, 0xE2F3, + 0xE2FD, 0xE2FF, 0xE301, 0xE303, 0xE30D, 0xE30F, + 0xE310, 0xE312, 0xE31E, 0xE321, 0xE323, 0xE32D, + 0xE32F, 0xE330, 0xE332, 0xE33E, 0xE3D0, 0xE3D2, + 0xE3DE, 0xE3E1, 0xE3E3, 0xE3ED, 0xE3EF, 0xE3F0, + 0xE3F2, 0xE3FE, 0xED01, 0xED03, 0xED0D, 0xED0F, + 0xED10, 0xED12, 0xED1E, 0xED21, 0xED23, 0xED2D, + 0xED2F, 0xED30, 0xED32, 0xED3E, 0xEDD0, 0xEDD2, + 0xEDDE, 0xEDE1, 0xEDE3, 0xEDED, 0xEDEF, 0xEDF0, + 0xEDF2, 0xEDFE, 0xEE00, 0xEE02, 0xEE0E, 0xEE11, + 0xEE13, 0xEE1D, 0xEE1F, 0xEE20, 0xEE22, 0xEE2E, + 0xEE31, 0xEE33, 0xEE3D, 0xEE3F, 0xEED1, 0xEED3, + 0xEEDD, 0xEEDF, 0xEEE0, 0xEEE2, 0xEEEE, 0xEEF1, + 0xEEF3, 0xEEFD, 0xEEFF, 0xEF01, 0xEF03, 0xEF0D, + 0xEF0F, 0xEF10, 0xEF12, 0xEF1E, 0xEF21, 0xEF23, + 0xEF2D, 0xEF2F, 0xEF30, 0xEF32, 0xEF3E, 0xEFD0, + 0xEFD2, 0xEFDE, 0xEFE1, 0xEFE3, 0xEFED, 0xEFEF, + 0xEFF0, 0xEFF2, 0xEFFE, 0xF001, 0xF003, 0xF00D, + 0xF00F, 0xF010, 0xF012, 0xF01E, 0xF021, 0xF023, + 0xF02D, 0xF02F, 0xF030, 0xF032, 0xF03E, 0xF0D0, + 0xF0D2, 0xF0DE, 0xF0E1, 0xF0E3, 0xF0ED, 0xF0EF, + 0xF0F0, 0xF0F2, 0xF0FE, 0xF100, 0xF102, 0xF10E, + 0xF111, 0xF113, 0xF11D, 0xF11F, 0xF120, 0xF122, + 0xF12E, 0xF131, 0xF133, 0xF13D, 0xF13F, 0xF1D1, + 0xF1D3, 0xF1DD, 0xF1DF, 0xF1E0, 0xF1E2, 0xF1EE, + 0xF1F1, 0xF1F3, 0xF1FD, 0xF1FF, 0xF201, 0xF203, + 0xF20D, 0xF20F, 0xF210, 0xF212, 0xF21E, 0xF221, + 0xF223, 0xF22D, 0xF22F, 0xF230, 0xF232, 0xF23E, + 0xF2D0, 0xF2D2, 0xF2DE, 0xF2E1, 0xF2E3, 0xF2ED, + 0xF2EF, 0xF2F0, 0xF2F2, 0xF2FE, 0xF300, 0xF302, + 0xF30E, 0xF311, 0xF313, 0xF31D, 0xF31F, 0xF320, + 0xF322, 0xF32E, 0xF331, 0xF333, 0xF33D, 0xF33F, + 0xF3D1, 0xF3D3, 0xF3DD, 0xF3DF, 0xF3E0, 0xF3E2, + 0xF3EE, 0xF3F1, 0xF3F3, 0xF3FD, 0xF3FF, 0xFD00, + 0xFD02, 0xFD0E, 0xFD11, 0xFD13, 0xFD1D, 0xFD1F, + 0xFD20, 0xFD22, 0xFD2E, 0xFD31, 0xFD33, 0xFD3D, + 0xFD3F, 0xFDD1, 0xFDD3, 0xFDDD, 0xFDDF, 0xFDE0, + 0xFDE2, 0xFDEE, 0xFDF1, 0xFDF3, 0xFDFD, 0xFDFF, + 0xFE01, 0xFE03, 0xFE0D, 0xFE0F, 0xFE10, 0xFE12, + 0xFE1E, 0xFE21, 0xFE23, 0xFE2D, 0xFE2F, 0xFE30, + 0xFE32, 0xFE3E, 0xFED0, 0xFED2, 0xFEDE, 0xFEE1, + 0xFEE3, 0xFEED, 0xFEEF, 0xFEF0, 0xFEF2, 0xFEFE, + 0xFF00, 0xFF02, 0xFF0E, 0xFF11, 0xFF13, 0xFF1D, + 0xFF1F, 0xFF20, 0xFF22, 0xFF2E, 0xFF31, 0xFF33, + 0xFF3D, 0xFF3F, 0xFFD1, 0xFFD3, 0xFFDD, 0xFFDF, + 0xFFE0, 0xFFE2, 0xFFEE, 0xFFF1, 0xFFF3, 0xFFFD, + 0xFFFF, +}; + +#define ON2AVC_CB6_CODES 1201 +static const uint32_t on2avc_cb6_codes[ON2AVC_CB6_CODES] = { + 0x0018, 0x0088, 0x0082, 0x0024, 0x05B4, 0x08DF, + 0x0044, 0x0197, 0x01DE, 0x021F, 0x0D77, 0x0A72, + 0x7E77, 0x0B8B, 0x03F1, 0x0433, 0x073F, 0x1E5C, + 0x016A, 0x01C5, 0x00D2, 0x0062, 0x0CE4, 0x0096, + 0x0020, 0x0052, 0x00B7, 0x0127, 0x003A, 0x0041, + 0x00CC, 0x01B6, 0x0124, 0x07D3, 0x01AE, 0x01C4, + 0x00DA, 0x03D8, 0x03F3, 0x1638, 0x03F2, 0x12FC, + 0x01E2, 0x0DBC, 0x026C, 0x008A, 0x0054, 0x01A6, + 0x0195, 0x0164, 0x01E2, 0x026D, 0x0051, 0x049F, + 0x01B3, 0x01E0, 0x01B4, 0x026E, 0x07DE, 0x0129, + 0x0292, 0x0DBD, 0x013E, 0x00F3, 0x05B5, 0x09A6, + 0x01FB, 0x02CF, 0x01FF, 0x037C, 0x004A, 0x067E, + 0x016B, 0x002A, 0x09A7, 0x10EE, 0x1639, 0x0135, + 0x0CCA, 0x016A, 0x011B, 0x03EE, 0x07A2, 0x0D7E, + 0x028F, 0x0FE2, 0x07DA, 0x0357, 0x92F6, 0x0F31, + 0x0217, 0x036A, 0x0CE5, 0x07A1, 0x0229, 0x03D9, + 0x0377, 0x00B7, 0x01A6, 0x0655, 0x012E, 0x002B, + 0x002E, 0x00F2, 0x06F2, 0x02D0, 0x0F98, 0x07A0, + 0x009C, 0x0332, 0x0014, 0x01BD, 0x017E, 0x0331, + 0x0371, 0x025B, 0x0498, 0x161F, 0x039E, 0x0654, + 0x00C2, 0x06BA, 0x0140, 0x021E, 0x02F8, 0x01B4, + 0x0134, 0x03FF, 0x0066, 0x0477, 0x01DF, 0x01FE, + 0x0A14, 0x029E, 0x0356, 0x038F, 0x035A, 0x3CB3, + 0x01B2, 0x016A, 0x011A, 0x00B6, 0x02DE, 0x01DD, + 0x017C, 0x0376, 0x002F, 0x0039, 0x03D7, 0x01BE, + 0x0056, 0x0050, 0x017C, 0x01CC, 0x0034, 0x0B3E, + 0x0499, 0x0014, 0x08DE, 0x037B, 0x03EB, 0x08BF, + 0x186E, 0x050F, 0x0030, 0x0169, 0x07F2, 0x00F6, + 0x0042, 0x0198, 0x00BC, 0x002E, 0x023A, 0x01E3, + 0x0036, 0x004C, 0x012E, 0x01A1, 0x007D, 0x00C3, + 0x0392, 0x0063, 0x0F33, 0x016C, 0x01A7, 0x0E77, + 0x01DF, 0x0177, 0x0032, 0x03FE, 0x0322, 0x01AC, + 0x0030, 0x017E, 0x011E, 0x0022, 0x01FB, 0x012A, + 0x002B, 0x0068, 0x00D4, 0x006E, 0x0015, 0x001C, + 0x00E5, 0x01A9, 0x0436, 0x053F, 0x05AE, 0x00B2, + 0x072A, 0x02EA, 0x008E, 0x0175, 0x02BE, 0x018E, + 0x0002, 0x005E, 0x01D6, 0x0055, 0x006A, 0x07F3, + 0x02F9, 0x01D4, 0x016E, 0x03AB, 0x00FF, 0x003C, + 0x0192, 0x01D6, 0x0256, 0x0137, 0x0148, 0x022A, + 0x039C, 0x016D, 0x0116, 0x038A, 0x033E, 0x0156, + 0x03CF, 0x004B, 0x00E6, 0x018F, 0x1E5D, 0x03DA, + 0x0292, 0x0108, 0x06F5, 0x03DB, 0x0092, 0x0178, + 0x014A, 0x03FF, 0x03EE, 0x0A79, 0x0A16, 0x00F7, + 0x01B5, 0x0A15, 0x0D7F, 0x02FA, 0x01E4, 0x0157, + 0x01E2, 0x0185, 0x057E, 0x07DB, 0x0098, 0x0DBE, + 0x019A, 0x05FE, 0x003B, 0x03F5, 0x01BF, 0x01E4, + 0x011E, 0x001B, 0x03AA, 0x0337, 0x1F9C, 0x0942, + 0x05AB, 0x0430, 0x24BF, 0x163A, 0x037E, 0x014E, + 0x00F4, 0x0217, 0x0059, 0x0F32, 0x03F4, 0x01F2, + 0x0031, 0x0136, 0x05C6, 0x0076, 0x0006, 0x02FE, + 0x03FB, 0x009D, 0x013F, 0x002E, 0x02E6, 0x00AD, + 0x0234, 0x021E, 0x0253, 0x012A, 0x0346, 0x029A, + 0x012B, 0x021C, 0x02DA, 0x0004, 0x013C, 0x00F5, + 0x004E, 0x017D, 0x01F8, 0x0006, 0x01FA, 0x01F9, + 0x007A, 0x0067, 0x033B, 0x033A, 0x0586, 0x05C7, + 0x05FF, 0x00C8, 0x014B, 0x024F, 0x02C5, 0x00E7, + 0x014C, 0x035C, 0x00A2, 0x006A, 0x01F3, 0x0071, + 0x005E, 0x0084, 0x063A, 0x03EF, 0x0064, 0x02FE, + 0x0255, 0x003A, 0x061A, 0x0333, 0x037F, 0x00FE, + 0x115B, 0x0F9A, 0x00A6, 0x027D, 0x0B5F, 0x013F, + 0x029E, 0x0293, 0x07B6, 0x000F, 0x0196, 0x02FB, + 0x033F, 0x01FE, 0x019E, 0x01B3, 0x037F, 0x00C4, + 0x00DE, 0x02D2, 0x007A, 0x03CA, 0x01E3, 0x02F7, + 0x00AE, 0x05AF, 0x02FF, 0x026F, 0x00CA, 0x0356, + 0x02C7, 0x02D1, 0x0256, 0x006B, 0x0141, 0x012C, + 0x03BE, 0x0026, 0x00F0, 0x03A3, 0x02D6, 0x005F, + 0x00FF, 0x03F2, 0x00AE, 0x0257, 0x01FE, 0x035E, + 0x01B6, 0x00EE, 0x0658, 0x008F, 0x0232, 0x0657, + 0x12FD, 0x00AF, 0x00E6, 0x0426, 0x0666, 0x009E, + 0x0467, 0x003F, 0x014A, 0x02D3, 0x12FE, 0x099A, + 0x03BF, 0x00DD, 0x04DF, 0x009F, 0x00B8, 0x0863, + 0x06F7, 0x01B8, 0x0346, 0x0179, 0x0FE3, 0x0667, + 0x0659, 0x01CE, 0x00B3, 0x0372, 0x065A, 0x025E, + 0x01AA, 0x0276, 0x027E, 0x02DB, 0x0CE6, 0x115A, + 0x02E7, 0x0139, 0x03DA, 0x01FA, 0x021C, 0x0943, + 0x0862, 0x011F, 0x08B6, 0x07E6, 0x029F, 0x00E5, + 0x0656, 0x049A, 0x000E, 0x0F99, 0x06F6, 0x00DC, + 0x00EC, 0x014B, 0x0230, 0x04A2, 0x0016, 0x02EB, + 0x03AE, 0x02DF, 0x01AA, 0x033E, 0x0196, 0x092E, + 0x06F3, 0x00E7, 0x0B5E, 0x03F2, 0x0086, 0x0347, + 0x022A, 0x0A17, 0x01EF, 0x067F, 0x004A, 0x037E, + 0x02EE, 0x015E, 0x0696, 0x006A, 0x01CD, 0x0077, + 0x073F, 0x0016, 0x01E3, 0x012E, 0x00DB, 0x03BD, + 0x0496, 0x01C6, 0x0323, 0x005E, 0x02F6, 0x027C, + 0x0235, 0x0231, 0x00DA, 0x01EB, 0x0232, 0x02C6, + 0x01F2, 0x016F, 0x02C6, 0x036B, 0x0050, 0x0AFE, + 0x0F9B, 0x00C6, 0x014E, 0x02BC, 0x01CA, 0x027F, + 0x07A5, 0x0DE1, 0x01F1, 0x039E, 0x0DE2, 0x1E5E, + 0x065E, 0x0DE0, 0x115F, 0x00F7, 0x02AB, 0x116E, + 0x019B, 0x04CE, 0x00D3, 0x01C7, 0x02D6, 0x01F3, + 0x016F, 0x014E, 0x05B7, 0x0FA3, 0x0118, 0x025F, + 0x017E, 0x0437, 0x049B, 0x05AE, 0x497A, 0x0D2E, + 0x05B6, 0x1E5F, 0x0DE3, 0x0512, 0x031A, 0x01F2, + 0x007E, 0x015C, 0x035E, 0x04CF, 0x01C8, 0x0194, + 0x12FF, 0x1F7F, 0x00E0, 0x01A2, 0x012F, 0x0087, + 0x014C, 0x0643, 0x0D5E, 0x017F, 0x07A6, 0x0513, + 0x0D5F, 0x022B, 0x065F, 0x03F6, 0x022E, 0x03F7, + 0x0642, 0x036E, 0x00D0, 0x01CB, 0x0378, 0x125EE, + 0x035F, 0x014F, 0x035F, 0x116F, 0x0A4F, 0x0102, + 0x032A, 0x0173, 0x0536, 0x03A7, 0x075E, 0x1F9F, + 0x163B, 0x14DA, 0x526E, 0x165F, 0x0A6E, 0x0596, + 0x07A7, 0x042A, 0x0172, 0x19C2, 0x07E6, 0x04A3, + 0x0327, 0x02A8, 0x07A3, 0x046E, 0x012F, 0x2EFF, + 0x01D7, 0x0266, 0x0BBE, 0x066E, 0x186F, 0x0A73, + 0x1336, 0x02A9, 0x0373, 0x017F, 0x1F9E, 0x0B62, + 0x03A6, 0x0DBF, 0x035B, 0x063B, 0x053B, 0x10EF, + 0x016E, 0x011B, 0x115D, 0x115C, 0x00F2, 0x0176, + 0x0393, 0x034A, 0x0107, 0x115E, 0x0B63, 0x023F, + 0x002A, 0x0CE7, 0x0A7A, 0x06FA, 0x06FB, 0x02AA, + 0x02C2, 0x065B, 0x07A4, 0x02D4, 0x0130, 0x0106, + 0x01FB, 0x0B3F, 0x01B7, 0x00F6, 0x0056, 0x053F, + 0x0126, 0x0048, 0x0233, 0x017D, 0x00A4, 0x08BE, + 0x165E, 0x165D, 0x0A7B, 0x0427, 0x078F, 0x1F7E, + 0x0641, 0x02E4, 0x01E6, 0x01DA, 0x00F8, 0x043A, + 0x02BE, 0x011C, 0x006F, 0x036D, 0x19C3, 0x0020, + 0x06AE, 0x0372, 0x0288, 0x00C0, 0x079D, 0x036E, + 0x0117, 0x02FB, 0x0538, 0x06F2, 0x12F9, 0x1337, + 0x1E58, 0x0214, 0x005E, 0x0CE0, 0x01EE, 0x0A6E, + 0x0215, 0x01C2, 0x12FA, 0x033A, 0x009A, 0x0174, + 0x0CE2, 0x09A1, 0x00FE, 0x0250, 0x02CA, 0x035E, + 0x03A2, 0x0D7D, 0x2EFE, 0x02E8, 0x24BE, 0x1F7C, + 0x10EC, 0x04A2, 0x0052, 0x010D, 0x0277, 0x003A, + 0x0CDE, 0x0A6F, 0x0086, 0x00E4, 0x12FB, 0x14DE, + 0x009E, 0x0062, 0x03CA, 0x03BC, 0x02CA, 0x14DF, + 0x0FE0, 0x030C, 0x03F0, 0x06F3, 0x0796, 0x0B1E, + 0x05B0, 0x15FE, 0x013A, 0x0CDF, 0x079E, 0x01E2, + 0x0166, 0x02BD, 0x0151, 0x0153, 0x0650, 0x0940, + 0x010F, 0x3CB2, 0x10ED, 0x057E, 0x03D4, 0x029E, + 0x0358, 0x06F4, 0x7E76, 0x017C, 0x15FF, 0x047D, + 0x1158, 0x3F3A, 0x0CE3, 0x005F, 0x043A, 0x032F, + 0x010E, 0x1E5A, 0x0A4C, 0x0152, 0x125EF, 0x0B88, + 0x057F, 0x059E, 0x042B, 0x2936, 0x0138, 0x03A1, + 0x03C6, 0x0E56, 0x12F8, 0x149A, 0x526F, 0x0F2E, + 0x079C, 0x02FA, 0x0476, 0x0267, 0x0636, 0x03A0, + 0x014E, 0x0092, 0x0D7C, 0x05AF, 0x010C, 0x011C, + 0x0A10, 0x177E, 0x0131, 0x09A0, 0x03EA, 0x02C2, + 0x02D6, 0x0B89, 0x032E, 0x01E8, 0x0F30, 0x01BA, + 0x0532, 0x0A6C, 0x0F6E, 0x04CC, 0x008E, 0x036C, + 0x0E57, 0x00D6, 0x0162, 0x0024, 0x0252, 0x0F6F, + 0x01AE, 0x0150, 0x0038, 0x07CE, 0x01BB, 0x01F6, + 0x026A, 0x038B, 0x01DB, 0x07CF, 0x14DB, 0x24BC, + 0x0272, 0x053E, 0x073E, 0x078E, 0x0C36, 0x0176, + 0x032B, 0x017A, 0x0190, 0x0CCB, 0x047C, 0x0170, + 0x0054, 0x03EC, 0x049D, 0x0197, 0x043B, 0x0432, + 0x0192, 0x026A, 0x01F0, 0x0076, 0x0216, 0x0A11, + 0x1F7D, 0x02C4, 0x0298, 0x1159, 0x0A4E, 0x0116, + 0x00E4, 0x0216, 0x029A, 0x000F, 0x04DA, 0x04D2, + 0x002B, 0x0011, 0x049E, 0x045A, 0x01BF, 0x01EF, + 0x03CE, 0x01F8, 0x026E, 0x0466, 0x02DC, 0x0168, + 0x030E, 0x00B4, 0x01C3, 0x03CC, 0x028D, 0x01AE, + 0x038E, 0x01B0, 0x0664, 0x0119, 0x01BE, 0x035B, + 0x035F, 0x028E, 0x0A78, 0x01DE, 0x0397, 0x03FE, + 0x01B1, 0x028E, 0x07D2, 0x09A2, 0x033C, 0x02C1, + 0x0FA0, 0x0359, 0x031E, 0x00C1, 0x03D6, 0x0A12, + 0x01C4, 0x0330, 0x075F, 0x0B1F, 0x025A, 0x027B, + 0x04DB, 0x02E5, 0x01FA, 0x036F, 0x0A13, 0x02BB, + 0x00FA, 0x01D4, 0x01F8, 0x018A, 0x161E, 0x0E75, + 0x026B, 0x05B3, 0x01BC, 0x05B2, 0x09A3, 0x0424, + 0x047E, 0x01EE, 0x0FE1, 0x161D, 0x024C, 0x017E, + 0x026B, 0x01DC, 0x00A5, 0x0F2F, 0x161C, 0x028B, + 0x0196, 0x0168, 0x01EF, 0x0394, 0x0E74, 0x013C, + 0x00C9, 0x032E, 0x0941, 0x0D76, 0x050C, 0x0228, + 0x006C, 0x0236, 0x0D2F, 0x0156, 0x00D2, 0x0B8A, + 0x0148, 0x028A, 0x028B, 0x033B, 0x0214, 0x01E9, + 0x03C2, 0x049C, 0x02BA, 0x02E9, 0x028C, 0x01FC, + 0x0103, 0x0B5C, 0x050D, 0x031C, 0x0268, 0x0651, + 0x013A, 0x013B, 0x0118, 0x03D5, 0x0252, 0x0044, + 0x0637, 0x01D2, 0x000E, 0x00F0, 0x0323, 0x02C3, + 0x019A, 0x016C, 0x0046, 0x03E3, 0x024A, 0x00AC, + 0x0269, 0x02C0, 0x0396, 0x027A, 0x0253, 0x0273, + 0x073E, 0x0322, 0x003A, 0x025E, 0x0336, 0x0257, + 0x00D6, 0x0026, 0x03C3, 0x0034, 0x019A, 0x00FB, + 0x0038, 0x0040, 0x0096, 0x01F0, 0x0184, 0x021A, + 0x003E, 0x0042, 0x050E, 0x03CE, 0x035E, 0x0FA1, + 0x017B, 0x02CD, 0x0058, 0x0326, 0x00E4, 0x002E, + 0x004F, 0x000C, 0x0164, 0x0048, 0x0048, 0x0194, + 0x0074, 0x006E, 0x0070, 0x006C, 0x01A4, 0x00A3, + 0x034F, 0x011E, 0x0374, 0x0157, 0x0138, 0x011D, + 0x03CF, 0x033D, 0x0132, 0x0050, 0x023E, 0x005A, + 0x0076, 0x01EC, 0x005D, 0x0008, 0x004C, 0x024E, + 0x0154, 0x001E, 0x01C6, 0x0027, 0x00FE, 0x01EA, + 0x02CE, 0x01DD, 0x02CB, 0x035A, 0x0318, 0x013E, + 0x009B, 0x0288, 0x0339, 0x024D, 0x031F, 0x0128, + 0x00B6, 0x0028, 0x028A, 0x0289, 0x029F, 0x01FD, + 0x029A, 0x00F6, 0x0FA2, 0x0347, 0x0080, 0x01A8, + 0x028F, 0x0326, 0x0327, 0x0370, 0x165C, 0x043F, + 0x0375, 0x013D, 0x1E5B, 0x04DE, 0x0155, 0x00D8, + 0x0319, 0x0096, 0x0640, 0x07E7, 0x007C, 0x0652, + 0x0373, 0x05DE, 0x00CF, 0x0E76, 0x0653, 0x01A0, + 0x0160, 0x0169, 0x01D5, 0x05AA, 0x053A, 0x0B5D, + 0x0254, 0x079A, 0x0533, 0x0425, 0x053E, 0x00A6, + 0x030F, 0x01A2, 0x00B0, 0x04A3, 0x079F, 0x011A, + 0x01EE, 0x02CC, 0x045E, 0x005C, 0x0024, 0x022C, + 0x001A, 0x0338, 0x0132, 0x026C, 0x004E, 0x047F, + 0x01B2, 0x0113, 0x043E, 0x0336, 0x00F0, 0x02CE, + 0x0112, 0x018B, 0x0010, 0x0114, 0x01BE, 0x03FA, + 0x002A, 0x00FA, 0x0033, 0x0060, 0x0146, 0x01DC, + 0x0000, 0x0025, 0x037A, 0x034E, 0x012E, 0x029B, + 0x079B, 0x00E6, 0x03CD, 0x02DD, 0x0117, 0x017A, + 0x002C, 0x03E2, 0x003E, 0x0070, 0x00CE, 0x00B1, + 0x003B, +}; + +static const uint8_t on2avc_cb6_bits[ON2AVC_CB6_CODES] = { + 7, 10, 10, 7, 12, 12, + 7, 10, 11, 11, 12, 15, + 17, 12, 13, 11, 15, 13, + 10, 11, 11, 7, 13, 13, + 7, 7, 12, 12, 7, 7, + 9, 9, 9, 11, 10, 9, + 12, 12, 13, 13, 13, 13, + 9, 12, 10, 10, 7, 9, + 9, 10, 12, 11, 10, 11, + 11, 9, 11, 11, 11, 11, + 12, 12, 13, 11, 12, 12, + 10, 11, 12, 12, 10, 11, + 11, 10, 12, 14, 13, 11, + 12, 12, 11, 10, 13, 14, + 10, 12, 12, 12, 16, 12, + 12, 10, 13, 13, 13, 12, + 11, 11, 11, 13, 14, 13, + 13, 11, 11, 10, 13, 13, + 11, 12, 12, 13, 16, 12, + 14, 10, 13, 13, 10, 13, + 11, 11, 10, 11, 11, 9, + 11, 11, 10, 11, 12, 12, + 13, 12, 12, 10, 13, 14, + 12, 11, 11, 12, 11, 9, + 11, 11, 10, 7, 12, 13, + 7, 7, 9, 9, 10, 12, + 13, 10, 12, 10, 10, 12, + 13, 12, 10, 10, 11, 9, + 7, 9, 9, 7, 10, 10, + 7, 7, 9, 9, 10, 11, + 10, 10, 12, 11, 11, 12, + 11, 11, 10, 10, 10, 9, + 7, 9, 9, 7, 9, 9, + 7, 10, 10, 7, 10, 10, + 11, 10, 11, 11, 11, 10, + 11, 12, 10, 9, 10, 10, + 8, 10, 9, 7, 10, 11, + 11, 9, 9, 10, 10, 10, + 10, 11, 10, 11, 10, 10, + 10, 11, 11, 10, 11, 11, + 10, 10, 11, 10, 13, 12, + 11, 10, 13, 12, 10, 11, + 11, 10, 11, 12, 13, 12, + 11, 13, 14, 11, 10, 11, + 11, 9, 13, 12, 10, 12, + 11, 11, 10, 13, 13, 9, + 11, 11, 10, 11, 15, 13, + 11, 11, 14, 13, 11, 10, + 11, 11, 10, 12, 13, 9, + 10, 11, 11, 10, 10, 10, + 10, 11, 11, 11, 10, 11, + 10, 10, 10, 11, 10, 10, + 11, 11, 10, 10, 10, 11, + 7, 9, 9, 8, 9, 9, + 7, 10, 10, 10, 11, 11, + 11, 10, 10, 12, 11, 10, + 9, 10, 10, 7, 9, 10, + 7, 10, 11, 11, 10, 11, + 11, 10, 11, 12, 12, 12, + 13, 13, 12, 11, 13, 13, + 11, 11, 11, 11, 9, 11, + 11, 9, 9, 12, 11, 9, + 9, 10, 11, 10, 11, 11, + 11, 11, 11, 11, 11, 11, + 11, 10, 11, 11, 10, 9, + 10, 10, 11, 12, 11, 10, + 12, 11, 10, 11, 10, 12, + 11, 11, 13, 11, 10, 13, + 13, 11, 12, 12, 11, 11, + 11, 11, 10, 10, 13, 13, + 10, 10, 11, 11, 10, 12, + 13, 10, 12, 11, 12, 11, + 13, 13, 10, 14, 13, 10, + 10, 11, 11, 10, 13, 13, + 10, 10, 10, 11, 10, 13, + 12, 10, 12, 12, 12, 12, + 13, 13, 11, 13, 13, 10, + 10, 11, 11, 11, 12, 12, + 10, 11, 11, 10, 12, 12, + 11, 11, 13, 12, 11, 10, + 13, 13, 10, 11, 12, 12, + 10, 11, 11, 11, 9, 12, + 11, 10, 9, 11, 11, 10, + 11, 11, 10, 12, 11, 11, + 10, 11, 11, 10, 11, 11, + 10, 9, 10, 10, 9, 12, + 13, 9, 13, 10, 11, 11, + 13, 14, 11, 14, 14, 13, + 13, 14, 13, 11, 13, 13, + 11, 12, 11, 11, 13, 11, + 11, 9, 12, 12, 9, 11, + 11, 11, 13, 14, 15, 12, + 12, 13, 14, 12, 10, 11, + 11, 9, 13, 12, 9, 10, + 13, 13, 10, 9, 11, 11, + 10, 12, 13, 11, 13, 12, + 13, 13, 13, 13, 10, 13, + 12, 10, 10, 11, 10, 17, + 13, 13, 11, 13, 14, 11, + 11, 11, 12, 12, 11, 15, + 13, 13, 17, 14, 13, 12, + 13, 13, 11, 14, 13, 11, + 10, 13, 13, 11, 14, 14, + 11, 12, 12, 11, 13, 15, + 14, 13, 14, 16, 15, 13, + 12, 12, 13, 11, 14, 14, + 11, 10, 13, 13, 10, 9, + 10, 10, 11, 13, 13, 10, + 13, 13, 12, 13, 13, 13, + 10, 13, 13, 10, 10, 11, + 11, 12, 11, 11, 9, 12, + 12, 9, 11, 11, 11, 12, + 14, 14, 12, 12, 14, 13, + 12, 10, 11, 11, 9, 12, + 12, 9, 10, 14, 14, 9, + 12, 11, 11, 11, 13, 14, + 11, 17, 14, 13, 13, 14, + 13, 11, 14, 13, 11, 12, + 11, 11, 13, 11, 11, 9, + 13, 12, 9, 10, 11, 10, + 12, 14, 14, 12, 14, 13, + 14, 12, 11, 11, 11, 9, + 12, 12, 9, 10, 13, 14, + 10, 10, 11, 10, 10, 14, + 12, 10, 13, 13, 12, 12, + 12, 13, 10, 12, 13, 10, + 9, 10, 11, 11, 13, 13, + 11, 14, 14, 11, 12, 13, + 13, 13, 17, 16, 13, 13, + 13, 16, 13, 12, 11, 13, + 11, 13, 14, 11, 17, 12, + 13, 11, 13, 16, 11, 12, + 13, 12, 13, 15, 17, 13, + 13, 17, 11, 12, 11, 12, + 11, 11, 14, 14, 11, 10, + 13, 13, 10, 12, 10, 11, + 10, 12, 13, 10, 12, 13, + 13, 12, 12, 12, 11, 14, + 12, 10, 9, 11, 11, 12, + 11, 11, 10, 12, 13, 9, + 10, 10, 11, 12, 13, 14, + 12, 12, 15, 14, 12, 11, + 11, 11, 9, 12, 13, 9, + 10, 11, 11, 9, 11, 11, + 9, 11, 11, 12, 11, 13, + 13, 11, 12, 13, 14, 12, + 12, 12, 12, 10, 11, 11, + 10, 10, 11, 11, 9, 9, + 10, 10, 10, 11, 11, 10, + 10, 11, 11, 11, 11, 12, + 10, 11, 11, 11, 9, 10, + 10, 11, 12, 12, 10, 11, + 11, 10, 11, 12, 11, 10, + 12, 13, 10, 11, 12, 13, + 11, 12, 11, 12, 10, 11, + 11, 10, 10, 14, 13, 10, + 10, 11, 11, 10, 13, 12, + 10, 12, 13, 12, 12, 12, + 13, 10, 12, 13, 10, 10, + 11, 11, 11, 13, 13, 10, + 10, 11, 11, 10, 12, 13, + 10, 12, 13, 12, 12, 13, + 11, 10, 12, 12, 10, 12, + 11, 11, 11, 11, 12, 10, + 10, 11, 10, 12, 11, 12, + 11, 13, 12, 10, 11, 13, + 11, 11, 11, 12, 10, 10, + 11, 11, 10, 9, 11, 11, + 9, 9, 10, 10, 10, 11, + 11, 10, 10, 11, 11, 12, + 11, 11, 11, 11, 11, 10, + 9, 11, 10, 7, 10, 10, + 7, 7, 9, 9, 9, 10, + 11, 10, 12, 11, 11, 12, + 11, 11, 10, 10, 11, 10, + 7, 10, 9, 7, 10, 9, + 7, 10, 10, 7, 9, 10, + 10, 10, 11, 12, 10, 10, + 11, 11, 10, 10, 10, 11, + 7, 9, 10, 8, 10, 12, + 11, 10, 9, 11, 10, 10, + 11, 11, 10, 10, 10, 11, + 11, 10, 10, 10, 10, 11, + 11, 10, 10, 10, 13, 12, + 11, 12, 12, 12, 10, 10, + 11, 11, 11, 14, 14, 11, + 11, 13, 13, 11, 11, 11, + 10, 10, 12, 12, 10, 13, + 11, 11, 10, 12, 13, 9, + 10, 11, 11, 11, 14, 13, + 11, 11, 13, 12, 11, 11, + 10, 11, 10, 12, 13, 10, + 9, 11, 11, 10, 10, 10, + 11, 10, 11, 11, 11, 13, + 11, 11, 11, 10, 10, 10, + 11, 10, 10, 9, 10, 10, + 7, 9, 10, 7, 9, 9, + 8, 10, 10, 10, 10, 12, + 11, 10, 11, 11, 12, 10, + 10, 10, 10, 7, 10, 10, + 7, +}; + +static const uint16_t on2avc_cb6_syms[ON2AVC_CB6_CODES] = { + 0x0000, 0x0002, 0x000E, 0x0011, 0x0013, 0x001D, + 0x001F, 0x0020, 0x0022, 0x002E, 0x0031, 0x0033, + 0x003D, 0x003F, 0x00D1, 0x00D3, 0x00DD, 0x00DF, + 0x00E0, 0x00E2, 0x00EE, 0x00F1, 0x00F3, 0x00FD, + 0x00FF, 0x0101, 0x0103, 0x010D, 0x010F, 0x0110, + 0x0112, 0x011E, 0x0121, 0x0123, 0x012D, 0x012F, + 0x0130, 0x0132, 0x013E, 0x01D0, 0x01D2, 0x01DE, + 0x01E1, 0x01E3, 0x01ED, 0x01EF, 0x01F0, 0x01F2, + 0x01FE, 0x0200, 0x0202, 0x020E, 0x0211, 0x0213, + 0x021D, 0x021F, 0x0220, 0x0222, 0x022E, 0x0231, + 0x0233, 0x023D, 0x023F, 0x02D1, 0x02D3, 0x02DD, + 0x02DF, 0x02E0, 0x02E2, 0x02EE, 0x02F1, 0x02F3, + 0x02FD, 0x02FF, 0x0301, 0x0303, 0x030D, 0x030F, + 0x0310, 0x0312, 0x031E, 0x0321, 0x0323, 0x032D, + 0x032F, 0x0330, 0x0332, 0x033E, 0x03D0, 0x03D2, + 0x03DE, 0x03E1, 0x03E3, 0x03ED, 0x03EF, 0x03F0, + 0x03F2, 0x03FE, 0x0D01, 0x0D03, 0x0D0D, 0x0D0F, + 0x0D10, 0x0D12, 0x0D1E, 0x0D21, 0x0D23, 0x0D2D, + 0x0D2F, 0x0D30, 0x0D32, 0x0D3E, 0x0DD0, 0x0DD2, + 0x0DDE, 0x0DE1, 0x0DE3, 0x0DED, 0x0DEF, 0x0DF0, + 0x0DF2, 0x0DFE, 0x0E00, 0x0E02, 0x0E0E, 0x0E11, + 0x0E13, 0x0E1D, 0x0E1F, 0x0E20, 0x0E22, 0x0E2E, + 0x0E31, 0x0E33, 0x0E3D, 0x0E3F, 0x0ED1, 0x0ED3, + 0x0EDD, 0x0EDF, 0x0EE0, 0x0EE2, 0x0EEE, 0x0EF1, + 0x0EF3, 0x0EFD, 0x0EFF, 0x0F01, 0x0F03, 0x0F0D, + 0x0F0F, 0x0F10, 0x0F12, 0x0F1E, 0x0F21, 0x0F23, + 0x0F2D, 0x0F2F, 0x0F30, 0x0F32, 0x0F3E, 0x0FD0, + 0x0FD2, 0x0FDE, 0x0FE1, 0x0FE3, 0x0FED, 0x0FEF, + 0x0FF0, 0x0FF2, 0x0FFE, 0x1001, 0x1003, 0x100D, + 0x100F, 0x1010, 0x1012, 0x101E, 0x1021, 0x1023, + 0x102D, 0x102F, 0x1030, 0x1032, 0x103E, 0x10D0, + 0x10D2, 0x10DE, 0x10E1, 0x10E3, 0x10ED, 0x10EF, + 0x10F0, 0x10F2, 0x10FE, 0x1100, 0x1102, 0x110E, + 0x1111, 0x1113, 0x111D, 0x111F, 0x1120, 0x1122, + 0x112E, 0x1131, 0x1133, 0x113D, 0x113F, 0x11D1, + 0x11D3, 0x11DD, 0x11DF, 0x11E0, 0x11E2, 0x11EE, + 0x11F1, 0x11F3, 0x11FD, 0x11FF, 0x1201, 0x1203, + 0x120D, 0x120F, 0x1210, 0x1212, 0x121E, 0x1221, + 0x1223, 0x122D, 0x122F, 0x1230, 0x1232, 0x123E, + 0x12D0, 0x12D2, 0x12DE, 0x12E1, 0x12E3, 0x12ED, + 0x12EF, 0x12F0, 0x12F2, 0x12FE, 0x1300, 0x1302, + 0x130E, 0x1311, 0x1313, 0x131D, 0x131F, 0x1320, + 0x1322, 0x132E, 0x1331, 0x1333, 0x133D, 0x133F, + 0x13D1, 0x13D3, 0x13DD, 0x13DF, 0x13E0, 0x13E2, + 0x13EE, 0x13F1, 0x13F3, 0x13FD, 0x13FF, 0x1D00, + 0x1D02, 0x1D0E, 0x1D11, 0x1D13, 0x1D1D, 0x1D1F, + 0x1D20, 0x1D22, 0x1D2E, 0x1D31, 0x1D33, 0x1D3D, + 0x1D3F, 0x1DD1, 0x1DD3, 0x1DDD, 0x1DDF, 0x1DE0, + 0x1DE2, 0x1DEE, 0x1DF1, 0x1DF3, 0x1DFD, 0x1DFF, + 0x1E01, 0x1E03, 0x1E0D, 0x1E0F, 0x1E10, 0x1E12, + 0x1E1E, 0x1E21, 0x1E23, 0x1E2D, 0x1E2F, 0x1E30, + 0x1E32, 0x1E3E, 0x1ED0, 0x1ED2, 0x1EDE, 0x1EE1, + 0x1EE3, 0x1EED, 0x1EEF, 0x1EF0, 0x1EF2, 0x1EFE, + 0x1F00, 0x1F02, 0x1F0E, 0x1F11, 0x1F13, 0x1F1D, + 0x1F1F, 0x1F20, 0x1F22, 0x1F2E, 0x1F31, 0x1F33, + 0x1F3D, 0x1F3F, 0x1FD1, 0x1FD3, 0x1FDD, 0x1FDF, + 0x1FE0, 0x1FE2, 0x1FEE, 0x1FF1, 0x1FF3, 0x1FFD, + 0x1FFF, 0x2000, 0x2002, 0x200E, 0x2011, 0x2013, + 0x201D, 0x201F, 0x2020, 0x2022, 0x202E, 0x2031, + 0x2033, 0x203D, 0x203F, 0x20D1, 0x20D3, 0x20DD, + 0x20DF, 0x20E0, 0x20E2, 0x20EE, 0x20F1, 0x20F3, + 0x20FD, 0x20FF, 0x2101, 0x2103, 0x210D, 0x210F, + 0x2110, 0x2112, 0x211E, 0x2121, 0x2123, 0x212D, + 0x212F, 0x2130, 0x2132, 0x213E, 0x21D0, 0x21D2, + 0x21DE, 0x21E1, 0x21E3, 0x21ED, 0x21EF, 0x21F0, + 0x21F2, 0x21FE, 0x2200, 0x2202, 0x220E, 0x2211, + 0x2213, 0x221D, 0x221F, 0x2220, 0x2222, 0x222E, + 0x2231, 0x2233, 0x223D, 0x223F, 0x22D1, 0x22D3, + 0x22DD, 0x22DF, 0x22E0, 0x22E2, 0x22EE, 0x22F1, + 0x22F3, 0x22FD, 0x22FF, 0x2301, 0x2303, 0x230D, + 0x230F, 0x2310, 0x2312, 0x231E, 0x2321, 0x2323, + 0x232D, 0x232F, 0x2330, 0x2332, 0x233E, 0x23D0, + 0x23D2, 0x23DE, 0x23E1, 0x23E3, 0x23ED, 0x23EF, + 0x23F0, 0x23F2, 0x23FE, 0x2D01, 0x2D03, 0x2D0D, + 0x2D0F, 0x2D10, 0x2D12, 0x2D1E, 0x2D21, 0x2D23, + 0x2D2D, 0x2D2F, 0x2D30, 0x2D32, 0x2D3E, 0x2DD0, + 0x2DD2, 0x2DDE, 0x2DE1, 0x2DE3, 0x2DED, 0x2DEF, + 0x2DF0, 0x2DF2, 0x2DFE, 0x2E00, 0x2E02, 0x2E0E, + 0x2E11, 0x2E13, 0x2E1D, 0x2E1F, 0x2E20, 0x2E22, + 0x2E2E, 0x2E31, 0x2E33, 0x2E3D, 0x2E3F, 0x2ED1, + 0x2ED3, 0x2EDD, 0x2EDF, 0x2EE0, 0x2EE2, 0x2EEE, + 0x2EF1, 0x2EF3, 0x2EFD, 0x2EFF, 0x2F01, 0x2F03, + 0x2F0D, 0x2F0F, 0x2F10, 0x2F12, 0x2F1E, 0x2F21, + 0x2F23, 0x2F2D, 0x2F2F, 0x2F30, 0x2F32, 0x2F3E, + 0x2FD0, 0x2FD2, 0x2FDE, 0x2FE1, 0x2FE3, 0x2FED, + 0x2FEF, 0x2FF0, 0x2FF2, 0x2FFE, 0x3001, 0x3003, + 0x300D, 0x300F, 0x3010, 0x3012, 0x301E, 0x3021, + 0x3023, 0x302D, 0x302F, 0x3030, 0x3032, 0x303E, + 0x30D0, 0x30D2, 0x30DE, 0x30E1, 0x30E3, 0x30ED, + 0x30EF, 0x30F0, 0x30F2, 0x30FE, 0x3100, 0x3102, + 0x310E, 0x3111, 0x3113, 0x311D, 0x311F, 0x3120, + 0x3122, 0x312E, 0x3131, 0x3133, 0x313D, 0x313F, + 0x31D1, 0x31D3, 0x31DD, 0x31DF, 0x31E0, 0x31E2, + 0x31EE, 0x31F1, 0x31F3, 0x31FD, 0x31FF, 0x3201, + 0x3203, 0x320D, 0x320F, 0x3210, 0x3212, 0x321E, + 0x3221, 0x3223, 0x322D, 0x322F, 0x3230, 0x3232, + 0x323E, 0x32D0, 0x32D2, 0x32DE, 0x32E1, 0x32E3, + 0x32ED, 0x32EF, 0x32F0, 0x32F2, 0x32FE, 0x3300, + 0x3302, 0x330E, 0x3311, 0x3313, 0x331D, 0x331F, + 0x3320, 0x3322, 0x332E, 0x3331, 0x3333, 0x333D, + 0x333F, 0x33D1, 0x33D3, 0x33DD, 0x33DF, 0x33E0, + 0x33E2, 0x33EE, 0x33F1, 0x33F3, 0x33FD, 0x33FF, + 0x3D00, 0x3D02, 0x3D0E, 0x3D11, 0x3D13, 0x3D1D, + 0x3D1F, 0x3D20, 0x3D22, 0x3D2E, 0x3D31, 0x3D33, + 0x3D3D, 0x3D3F, 0x3DD1, 0x3DD3, 0x3DDD, 0x3DDF, + 0x3DE0, 0x3DE2, 0x3DEE, 0x3DF1, 0x3DF3, 0x3DFD, + 0x3DFF, 0x3E01, 0x3E03, 0x3E0D, 0x3E0F, 0x3E10, + 0x3E12, 0x3E1E, 0x3E21, 0x3E23, 0x3E2D, 0x3E2F, + 0x3E30, 0x3E32, 0x3E3E, 0x3ED0, 0x3ED2, 0x3EDE, + 0x3EE1, 0x3EE3, 0x3EED, 0x3EEF, 0x3EF0, 0x3EF2, + 0x3EFE, 0x3F00, 0x3F02, 0x3F0E, 0x3F11, 0x3F13, + 0x3F1D, 0x3F1F, 0x3F20, 0x3F22, 0x3F2E, 0x3F31, + 0x3F33, 0x3F3D, 0x3F3F, 0x3FD1, 0x3FD3, 0x3FDD, + 0x3FDF, 0x3FE0, 0x3FE2, 0x3FEE, 0x3FF1, 0x3FF3, + 0x3FFD, 0x3FFF, 0xD001, 0xD003, 0xD00D, 0xD00F, + 0xD010, 0xD012, 0xD01E, 0xD021, 0xD023, 0xD02D, + 0xD02F, 0xD030, 0xD032, 0xD03E, 0xD0D0, 0xD0D2, + 0xD0DE, 0xD0E1, 0xD0E3, 0xD0ED, 0xD0EF, 0xD0F0, + 0xD0F2, 0xD0FE, 0xD100, 0xD102, 0xD10E, 0xD111, + 0xD113, 0xD11D, 0xD11F, 0xD120, 0xD122, 0xD12E, + 0xD131, 0xD133, 0xD13D, 0xD13F, 0xD1D1, 0xD1D3, + 0xD1DD, 0xD1DF, 0xD1E0, 0xD1E2, 0xD1EE, 0xD1F1, + 0xD1F3, 0xD1FD, 0xD1FF, 0xD201, 0xD203, 0xD20D, + 0xD20F, 0xD210, 0xD212, 0xD21E, 0xD221, 0xD223, + 0xD22D, 0xD22F, 0xD230, 0xD232, 0xD23E, 0xD2D0, + 0xD2D2, 0xD2DE, 0xD2E1, 0xD2E3, 0xD2ED, 0xD2EF, + 0xD2F0, 0xD2F2, 0xD2FE, 0xD300, 0xD302, 0xD30E, + 0xD311, 0xD313, 0xD31D, 0xD31F, 0xD320, 0xD322, + 0xD32E, 0xD331, 0xD333, 0xD33D, 0xD33F, 0xD3D1, + 0xD3D3, 0xD3DD, 0xD3DF, 0xD3E0, 0xD3E2, 0xD3EE, + 0xD3F1, 0xD3F3, 0xD3FD, 0xD3FF, 0xDD00, 0xDD02, + 0xDD0E, 0xDD11, 0xDD13, 0xDD1D, 0xDD1F, 0xDD20, + 0xDD22, 0xDD2E, 0xDD31, 0xDD33, 0xDD3D, 0xDD3F, + 0xDDD1, 0xDDD3, 0xDDDD, 0xDDDF, 0xDDE0, 0xDDE2, + 0xDDEE, 0xDDF1, 0xDDF3, 0xDDFD, 0xDDFF, 0xDE01, + 0xDE03, 0xDE0D, 0xDE0F, 0xDE10, 0xDE12, 0xDE1E, + 0xDE21, 0xDE23, 0xDE2D, 0xDE2F, 0xDE30, 0xDE32, + 0xDE3E, 0xDED0, 0xDED2, 0xDEDE, 0xDEE1, 0xDEE3, + 0xDEED, 0xDEEF, 0xDEF0, 0xDEF2, 0xDEFE, 0xDF00, + 0xDF02, 0xDF0E, 0xDF11, 0xDF13, 0xDF1D, 0xDF1F, + 0xDF20, 0xDF22, 0xDF2E, 0xDF31, 0xDF33, 0xDF3D, + 0xDF3F, 0xDFD1, 0xDFD3, 0xDFDD, 0xDFDF, 0xDFE0, + 0xDFE2, 0xDFEE, 0xDFF1, 0xDFF3, 0xDFFD, 0xDFFF, + 0xE000, 0xE002, 0xE00E, 0xE011, 0xE013, 0xE01D, + 0xE01F, 0xE020, 0xE022, 0xE02E, 0xE031, 0xE033, + 0xE03D, 0xE03F, 0xE0D1, 0xE0D3, 0xE0DD, 0xE0DF, + 0xE0E0, 0xE0E2, 0xE0EE, 0xE0F1, 0xE0F3, 0xE0FD, + 0xE0FF, 0xE101, 0xE103, 0xE10D, 0xE10F, 0xE110, + 0xE112, 0xE11E, 0xE121, 0xE123, 0xE12D, 0xE12F, + 0xE130, 0xE132, 0xE13E, 0xE1D0, 0xE1D2, 0xE1DE, + 0xE1E1, 0xE1E3, 0xE1ED, 0xE1EF, 0xE1F0, 0xE1F2, + 0xE1FE, 0xE200, 0xE202, 0xE20E, 0xE211, 0xE213, + 0xE21D, 0xE21F, 0xE220, 0xE222, 0xE22E, 0xE231, + 0xE233, 0xE23D, 0xE23F, 0xE2D1, 0xE2D3, 0xE2DD, + 0xE2DF, 0xE2E0, 0xE2E2, 0xE2EE, 0xE2F1, 0xE2F3, + 0xE2FD, 0xE2FF, 0xE301, 0xE303, 0xE30D, 0xE30F, + 0xE310, 0xE312, 0xE31E, 0xE321, 0xE323, 0xE32D, + 0xE32F, 0xE330, 0xE332, 0xE33E, 0xE3D0, 0xE3D2, + 0xE3DE, 0xE3E1, 0xE3E3, 0xE3ED, 0xE3EF, 0xE3F0, + 0xE3F2, 0xE3FE, 0xED01, 0xED03, 0xED0D, 0xED0F, + 0xED10, 0xED12, 0xED1E, 0xED21, 0xED23, 0xED2D, + 0xED2F, 0xED30, 0xED32, 0xED3E, 0xEDD0, 0xEDD2, + 0xEDDE, 0xEDE1, 0xEDE3, 0xEDED, 0xEDEF, 0xEDF0, + 0xEDF2, 0xEDFE, 0xEE00, 0xEE02, 0xEE0E, 0xEE11, + 0xEE13, 0xEE1D, 0xEE1F, 0xEE20, 0xEE22, 0xEE2E, + 0xEE31, 0xEE33, 0xEE3D, 0xEE3F, 0xEED1, 0xEED3, + 0xEEDD, 0xEEDF, 0xEEE0, 0xEEE2, 0xEEEE, 0xEEF1, + 0xEEF3, 0xEEFD, 0xEEFF, 0xEF01, 0xEF03, 0xEF0D, + 0xEF0F, 0xEF10, 0xEF12, 0xEF1E, 0xEF21, 0xEF23, + 0xEF2D, 0xEF2F, 0xEF30, 0xEF32, 0xEF3E, 0xEFD0, + 0xEFD2, 0xEFDE, 0xEFE1, 0xEFE3, 0xEFED, 0xEFEF, + 0xEFF0, 0xEFF2, 0xEFFE, 0xF001, 0xF003, 0xF00D, + 0xF00F, 0xF010, 0xF012, 0xF01E, 0xF021, 0xF023, + 0xF02D, 0xF02F, 0xF030, 0xF032, 0xF03E, 0xF0D0, + 0xF0D2, 0xF0DE, 0xF0E1, 0xF0E3, 0xF0ED, 0xF0EF, + 0xF0F0, 0xF0F2, 0xF0FE, 0xF100, 0xF102, 0xF10E, + 0xF111, 0xF113, 0xF11D, 0xF11F, 0xF120, 0xF122, + 0xF12E, 0xF131, 0xF133, 0xF13D, 0xF13F, 0xF1D1, + 0xF1D3, 0xF1DD, 0xF1DF, 0xF1E0, 0xF1E2, 0xF1EE, + 0xF1F1, 0xF1F3, 0xF1FD, 0xF1FF, 0xF201, 0xF203, + 0xF20D, 0xF20F, 0xF210, 0xF212, 0xF21E, 0xF221, + 0xF223, 0xF22D, 0xF22F, 0xF230, 0xF232, 0xF23E, + 0xF2D0, 0xF2D2, 0xF2DE, 0xF2E1, 0xF2E3, 0xF2ED, + 0xF2EF, 0xF2F0, 0xF2F2, 0xF2FE, 0xF300, 0xF302, + 0xF30E, 0xF311, 0xF313, 0xF31D, 0xF31F, 0xF320, + 0xF322, 0xF32E, 0xF331, 0xF333, 0xF33D, 0xF33F, + 0xF3D1, 0xF3D3, 0xF3DD, 0xF3DF, 0xF3E0, 0xF3E2, + 0xF3EE, 0xF3F1, 0xF3F3, 0xF3FD, 0xF3FF, 0xFD00, + 0xFD02, 0xFD0E, 0xFD11, 0xFD13, 0xFD1D, 0xFD1F, + 0xFD20, 0xFD22, 0xFD2E, 0xFD31, 0xFD33, 0xFD3D, + 0xFD3F, 0xFDD1, 0xFDD3, 0xFDDD, 0xFDDF, 0xFDE0, + 0xFDE2, 0xFDEE, 0xFDF1, 0xFDF3, 0xFDFD, 0xFDFF, + 0xFE01, 0xFE03, 0xFE0D, 0xFE0F, 0xFE10, 0xFE12, + 0xFE1E, 0xFE21, 0xFE23, 0xFE2D, 0xFE2F, 0xFE30, + 0xFE32, 0xFE3E, 0xFED0, 0xFED2, 0xFEDE, 0xFEE1, + 0xFEE3, 0xFEED, 0xFEEF, 0xFEF0, 0xFEF2, 0xFEFE, + 0xFF00, 0xFF02, 0xFF0E, 0xFF11, 0xFF13, 0xFF1D, + 0xFF1F, 0xFF20, 0xFF22, 0xFF2E, 0xFF31, 0xFF33, + 0xFF3D, 0xFF3F, 0xFFD1, 0xFFD3, 0xFFDD, 0xFFDF, + 0xFFE0, 0xFFE2, 0xFFEE, 0xFFF1, 0xFFF3, 0xFFFD, + 0xFFFF, +}; + +#define ON2AVC_CB7_CODES 3281 +static const uint32_t on2avc_cb7_codes[ON2AVC_CB7_CODES] = { + 0x00000, 0x000EA, 0x000E6, 0x000F4, 0x000F6, 0x00047, + 0x003E2, 0x004A7, 0x00044, 0x004D3, 0x0082A, 0x0026E, + 0x0020E, 0x008A5, 0x02603, 0x02895, 0x049B0, 0x02894, + 0x007BE, 0x0069E, 0x01154, 0x01153, 0x0095F, 0x0038E, + 0x004AC, 0x0128E, 0x00E5E, 0x00992, 0x02A84, 0x0386A, + 0x03F6F, 0x01C54, 0x005D4, 0x00AFB, 0x001BE, 0x00258, + 0x00A59, 0x00043, 0x004A6, 0x004D7, 0x00040, 0x0006C, + 0x007FF, 0x00D39, 0x0005B, 0x00066, 0x0034A, 0x00124, + 0x004B6, 0x00626, 0x0071F, 0x014A3, 0x014A2, 0x0083E, + 0x032D4, 0x049B3, 0x0045E, 0x00ED5, 0x02896, 0x00ABA, + 0x0107B, 0x009EC, 0x0082C, 0x0082B, 0x00D38, 0x0072B, + 0x004FC, 0x049B2, 0x050B1, 0x003FE, 0x009EB, 0x049B1, + 0x00966, 0x00F75, 0x03F70, 0x007BC, 0x00054, 0x00394, + 0x000E8, 0x0052F, 0x0057A, 0x00458, 0x0FB4B, 0x01C55, + 0x00948, 0x032D6, 0x00ED6, 0x0A05F, 0x050B3, 0x00BBD, + 0x0197E, 0x024FC, 0x020C6, 0x0094A, 0x0386B, 0x1F2FF, + 0x050B4, 0x0A060, 0x0FB4C, 0x009ED, 0x02A85, 0x0FB4D, + 0x02605, 0x00ABB, 0x009A2, 0x0145B, 0x0A05D, 0x03F71, + 0x00BFF, 0x1F2FE, 0x0FB49, 0x0FB48, 0x050B2, 0x01155, + 0x01FD6, 0x032D5, 0x00976, 0x02604, 0x00A5A, 0x0A05E, + 0x0FB4A, 0x00DB9, 0x0A063, 0x1F307, 0x0FB4F, 0x1F306, + 0x049B4, 0x0FB50, 0x0FB51, 0x050B6, 0x1F308, 0x050B7, + 0x1F30A, 0x1F309, 0x0A064, 0x1F30B, 0x0A066, 0x06535, + 0x020C7, 0x0A065, 0x032D7, 0x0FB52, 0x02897, 0x0077A, + 0x03F72, 0x0FB4E, 0x050B5, 0x0076E, 0x1F301, 0x1F302, + 0x06533, 0x01FD7, 0x1F300, 0x0A061, 0x1F304, 0x1F303, + 0x07E54, 0x024FD, 0x1F305, 0x06534, 0x02606, 0x0A062, + 0x007C0, 0x0A06A, 0x1F30F, 0x0FB54, 0x0386D, 0x009E6, + 0x1F310, 0x06538, 0x00DBA, 0x014A4, 0x050B9, 0x1F311, + 0x0A06B, 0x0128F, 0x07E55, 0x1F312, 0x0FB55, 0x01C56, + 0x07E56, 0x0FB56, 0x1F313, 0x050BA, 0x01C57, 0x02608, + 0x0A067, 0x1F30D, 0x1F30C, 0x02607, 0x0386C, 0x0A069, + 0x0A068, 0x01557, 0x00ED7, 0x06536, 0x1F30E, 0x0FB53, + 0x02609, 0x007BF, 0x050B8, 0x06537, 0x00DE5, 0x00392, + 0x03F69, 0x0A055, 0x0FB3C, 0x0A054, 0x00AB7, 0x050AB, + 0x0FB3D, 0x00CE6, 0x009E8, 0x014A1, 0x049A8, 0x1F2ED, + 0x02890, 0x009E9, 0x049A9, 0x1F2EE, 0x032D1, 0x020C4, + 0x049AA, 0x0A056, 0x0FB3E, 0x0FB3F, 0x0A051, 0x0A052, + 0x0A053, 0x0FB39, 0x0A050, 0x0096E, 0x0FB3A, 0x1F2EB, + 0x029FE, 0x007FE, 0x0128D, 0x049A7, 0x1F2EC, 0x07E50, + 0x00E36, 0x03867, 0x0FB3B, 0x006EA, 0x03F6B, 0x1F2F4, + 0x1F2F3, 0x03868, 0x049AB, 0x1F2F6, 0x029FF, 0x1F2F5, + 0x0A05A, 0x07E52, 0x1F2F7, 0x07E51, 0x03F6C, 0x1F2FA, + 0x07E53, 0x025FF, 0x1F2F8, 0x1F2F9, 0x009A0, 0x06532, + 0x0FB45, 0x024FB, 0x008B9, 0x01D7D, 0x0FB40, 0x01FD3, + 0x0FB42, 0x0A058, 0x050AC, 0x0A057, 0x0FB41, 0x0A059, + 0x1F2F0, 0x1F2EF, 0x0FB43, 0x03F6A, 0x0FB44, 0x020C5, + 0x1F2F1, 0x1F2F2, 0x004FE, 0x02601, 0x00A58, 0x01FD5, + 0x049AD, 0x00A46, 0x02A80, 0x050AD, 0x009E5, 0x01B56, + 0x02A81, 0x00A36, 0x01556, 0x032D3, 0x02A82, 0x0FB47, + 0x1F2FD, 0x050AE, 0x004BA, 0x00A6B, 0x03F6D, 0x049AE, + 0x01317, 0x009A1, 0x00AB8, 0x02891, 0x03869, 0x01FD4, + 0x049AC, 0x1F2FB, 0x0FB46, 0x0A05B, 0x02600, 0x032D2, + 0x0137E, 0x01C53, 0x02892, 0x00BFE, 0x0A05C, 0x1F2FC, + 0x00CE7, 0x00058, 0x00FF7, 0x009EA, 0x00068, 0x00060, + 0x004D2, 0x004BD, 0x000EE, 0x003A4, 0x006E2, 0x0137F, + 0x0197D, 0x006EB, 0x050B0, 0x03F6E, 0x00E37, 0x00316, + 0x02893, 0x004CB, 0x006EE, 0x01152, 0x008AE, 0x0067E, + 0x00991, 0x0145A, 0x00AB9, 0x049AF, 0x02A83, 0x00A6C, + 0x0045F, 0x02602, 0x006E1, 0x050AF, 0x012D2, 0x0073F, + 0x00061, 0x00526, 0x004D6, 0x0013E, 0x003AE, 0x0005E, + 0x01D7E, 0x0289F, 0x00059, 0x0006A, 0x0082D, 0x00F77, + 0x009EE, 0x006E3, 0x00D3F, 0x1F32B, 0x02A8B, 0x00D3E, + 0x032DE, 0x0FB60, 0x02A8C, 0x020CC, 0x03874, 0x0045B, + 0x00DE8, 0x0082E, 0x00636, 0x012D6, 0x049B9, 0x0260C, + 0x01157, 0x06540, 0x0A073, 0x02504, 0x0289D, 0x050C2, + 0x00AFE, 0x0260D, 0x0289E, 0x00A6F, 0x0004E, 0x006EF, + 0x0099C, 0x00EDA, 0x0062E, 0x00048, 0x00A3A, 0x01292, + 0x013C2, 0x00A72, 0x0012A, 0x028A0, 0x02507, 0x00174, + 0x00DE9, 0x00ABF, 0x00EDE, 0x01146, 0x013C3, 0x032E1, + 0x049BA, 0x03875, 0x03876, 0x00824, 0x0077B, 0x032E2, + 0x01050, 0x00677, 0x00EDB, 0x0145C, 0x02505, 0x032DF, + 0x019C0, 0x050C3, 0x06541, 0x0A074, 0x032E0, 0x00A37, + 0x02506, 0x00ABE, 0x00E78, 0x02A8D, 0x001B4, 0x02A8E, + 0x01D7F, 0x001A4, 0x00DEA, 0x1F32F, 0x050C5, 0x009EF, + 0x00977, 0x020CD, 0x01B60, 0x019C3, 0x017DE, 0x0131A, + 0x0260F, 0x0A075, 0x01C5C, 0x0FB61, 0x07E62, 0x00E79, + 0x02610, 0x0A076, 0x014A7, 0x02611, 0x009FA, 0x007C1, + 0x0145D, 0x1F32C, 0x049BB, 0x019C1, 0x06543, 0x1F32D, + 0x06544, 0x01FD8, 0x06542, 0x01B5E, 0x06545, 0x1F32E, + 0x019C2, 0x005F4, 0x0260E, 0x050C4, 0x01B5F, 0x01C5B, + 0x032E3, 0x1F339, 0x1F33A, 0x1F338, 0x0FB63, 0x028A1, + 0x1F33B, 0x0FB64, 0x049BC, 0x0A07A, 0x1F33C, 0x0A07B, + 0x032E4, 0x07E63, 0x1F33E, 0x07E64, 0x1F33D, 0x0FB65, + 0x028A2, 0x02612, 0x02613, 0x050C6, 0x00967, 0x0155A, + 0x03F78, 0x1F330, 0x0A077, 0x03877, 0x0A078, 0x1F333, + 0x1F331, 0x1F332, 0x03878, 0x1F335, 0x1F336, 0x06546, + 0x1F334, 0x06547, 0x1F337, 0x0A079, 0x0FB62, 0x006FE, + 0x1F342, 0x0FB69, 0x008A7, 0x009FB, 0x1F343, 0x1F344, + 0x050C7, 0x0654A, 0x020CF, 0x1F345, 0x020CE, 0x01FD9, + 0x028A5, 0x0A07C, 0x0A07D, 0x050C8, 0x013C6, 0x03F7A, + 0x0A07E, 0x0387B, 0x01C5D, 0x03879, 0x06548, 0x1F33F, + 0x028A3, 0x00DBE, 0x03F79, 0x1F340, 0x0FB66, 0x028A4, + 0x008B2, 0x0FB67, 0x0387A, 0x0131B, 0x005D5, 0x06549, + 0x1F341, 0x0FB68, 0x0155B, 0x00DE6, 0x07E59, 0x1F318, + 0x00266, 0x00823, 0x01B57, 0x0FB58, 0x1F319, 0x0386F, + 0x01B58, 0x02899, 0x050BB, 0x00DBB, 0x01B59, 0x032D9, + 0x050BC, 0x1F31A, 0x03F74, 0x032DA, 0x0A06D, 0x06539, + 0x03870, 0x0386E, 0x1F315, 0x1F314, 0x024FE, 0x0176A, + 0x032D8, 0x0A06C, 0x1F316, 0x07E57, 0x014A5, 0x049B5, + 0x07E58, 0x00D3A, 0x0075B, 0x02898, 0x1F317, 0x0FB57, + 0x03F73, 0x01B5A, 0x0FB5B, 0x050BE, 0x1F31F, 0x0FB5A, + 0x0653B, 0x1F320, 0x0FB5C, 0x07E5C, 0x07E5D, 0x1F322, + 0x050BF, 0x0A06F, 0x1F321, 0x0FB5D, 0x1F325, 0x1F323, + 0x1F324, 0x01C58, 0x00ED8, 0x0289A, 0x1F326, 0x03F77, + 0x013C0, 0x0653A, 0x03F75, 0x1F31B, 0x024FF, 0x03F76, + 0x0FB59, 0x07E5A, 0x0A06E, 0x02500, 0x07E5B, 0x02A86, + 0x050BD, 0x1F31C, 0x032DB, 0x1F31E, 0x1F31D, 0x049B6, + 0x00C49, 0x1F329, 0x1F328, 0x00BBE, 0x008A6, 0x03871, + 0x01B5B, 0x02A88, 0x01558, 0x020C9, 0x0FB5F, 0x049B7, + 0x014A6, 0x07E5F, 0x1F32A, 0x0197F, 0x01B5C, 0x03872, + 0x00726, 0x01156, 0x02501, 0x0104F, 0x00C48, 0x032DC, + 0x0653C, 0x0176B, 0x1F327, 0x0653D, 0x0289B, 0x07E5E, + 0x0FB5E, 0x0176E, 0x0A071, 0x0A070, 0x0260A, 0x00993, + 0x020C8, 0x0176F, 0x02A87, 0x0289C, 0x00042, 0x00CE8, + 0x01C5A, 0x00F76, 0x008BA, 0x001C8, 0x02A8A, 0x02503, + 0x00136, 0x00A6E, 0x020CB, 0x00A5B, 0x008AF, 0x00ED9, + 0x03873, 0x0653F, 0x07E61, 0x050C1, 0x007A9, 0x0067F, + 0x013C1, 0x01559, 0x00D3B, 0x00DE7, 0x01B5D, 0x050C0, + 0x0260B, 0x02A89, 0x0653E, 0x0A072, 0x07E60, 0x049B8, + 0x00A6D, 0x02502, 0x00E5F, 0x012D3, 0x020CA, 0x0015D, + 0x032DD, 0x01C59, 0x0018E, 0x000E0, 0x07E77, 0x07E78, + 0x07E76, 0x049C5, 0x00BEA, 0x0A090, 0x0A08F, 0x00A3B, + 0x03F80, 0x0655A, 0x0655B, 0x050D1, 0x0A091, 0x1F37E, + 0x1F37F, 0x1F37C, 0x1F37D, 0x0FB77, 0x0655D, 0x050D2, + 0x1F380, 0x0655C, 0x02618, 0x049C3, 0x1F379, 0x0A08D, + 0x07E72, 0x07E73, 0x1F37B, 0x1F37A, 0x0A08E, 0x0145E, + 0x06558, 0x06559, 0x07E74, 0x049C4, 0x0083F, 0x07E75, + 0x0FB76, 0x007AA, 0x008A8, 0x1F382, 0x0FB7B, 0x007AB, + 0x004B2, 0x050D5, 0x07E7C, 0x07E7B, 0x032E8, 0x0261A, + 0x07E7D, 0x1F383, 0x03F81, 0x1F384, 0x0655F, 0x0FB7C, + 0x0A094, 0x0A095, 0x020D3, 0x1F385, 0x050D6, 0x050D7, + 0x01B61, 0x0FB78, 0x07E79, 0x028A7, 0x07E7A, 0x0A092, + 0x1F381, 0x050D3, 0x0FB79, 0x032E7, 0x0655E, 0x0A093, + 0x01DA2, 0x0053B, 0x02619, 0x050D4, 0x0FB7A, 0x020D2, + 0x0094B, 0x0A09A, 0x0FB7F, 0x0FB7E, 0x03884, 0x00C4A, + 0x0FB80, 0x1F38B, 0x019C6, 0x032E9, 0x01C5F, 0x0FB82, + 0x1F38C, 0x0FB81, 0x050D9, 0x07E7E, 0x1F38D, 0x1F38E, + 0x03885, 0x050DB, 0x07E7F, 0x06562, 0x050DA, 0x00E7A, + 0x02A92, 0x1F386, 0x0A096, 0x06560, 0x06561, 0x1F389, + 0x1F387, 0x1F388, 0x050D8, 0x0A098, 0x0FB7D, 0x02A93, + 0x0A097, 0x01FDC, 0x1F38A, 0x0A099, 0x020D4, 0x07E82, + 0x0FB89, 0x1F394, 0x07E81, 0x0A09E, 0x0FB8B, 0x1F395, + 0x07E83, 0x0FB8A, 0x028A8, 0x1F397, 0x1F396, 0x0A09F, + 0x0FB8C, 0x03F82, 0x049C6, 0x1F398, 0x1F399, 0x06563, + 0x02508, 0x03886, 0x07E84, 0x012E6, 0x0A09B, 0x1F38F, + 0x032EA, 0x0FB85, 0x1F390, 0x0FB86, 0x0FB83, 0x0FB84, + 0x0A09C, 0x1F392, 0x1F391, 0x0FB87, 0x02A94, 0x1F393, + 0x0A09D, 0x07E80, 0x0FB88, 0x006B6, 0x1F39D, 0x1F39E, + 0x0A0A1, 0x0A0A2, 0x0155E, 0x1F39F, 0x0A0A3, 0x02509, + 0x020D5, 0x0A0A4, 0x1F3A0, 0x07E86, 0x06564, 0x01FDE, + 0x0FB90, 0x049C8, 0x06565, 0x050DE, 0x0A0A6, 0x07E87, + 0x0A0A5, 0x06566, 0x00E7B, 0x049C7, 0x1F39A, 0x0A0A0, + 0x050DC, 0x00DEC, 0x07E85, 0x0FB8D, 0x01FDD, 0x00CE9, + 0x050DD, 0x0FB8E, 0x1F39B, 0x03F83, 0x0051F, 0x1F39C, + 0x0FB8F, 0x01293, 0x009A3, 0x049BE, 0x1F34E, 0x1F34D, + 0x0654B, 0x0115A, 0x0A07F, 0x0654C, 0x00A47, 0x01C5E, + 0x049BF, 0x1F350, 0x1F34F, 0x0387C, 0x07E67, 0x1F351, + 0x07E66, 0x02A8F, 0x1F353, 0x07E68, 0x1F354, 0x1F352, + 0x0A080, 0x00BBF, 0x1F347, 0x1F348, 0x1F346, 0x0FB6A, + 0x032E5, 0x07E65, 0x1F349, 0x006E4, 0x012D7, 0x049BD, + 0x1F34A, 0x0FB6B, 0x050C9, 0x00DEB, 0x1F34C, 0x1F34B, + 0x0052E, 0x07E6A, 0x1F35F, 0x1F35E, 0x0A081, 0x0387D, + 0x1F361, 0x0654F, 0x1F360, 0x0A082, 0x0387E, 0x1F363, + 0x1F362, 0x050CA, 0x0A084, 0x1F365, 0x03F7D, 0x0A083, + 0x1F364, 0x032E6, 0x1F366, 0x0A085, 0x06550, 0x020D0, + 0x1F356, 0x1F355, 0x00A73, 0x1F357, 0x1F358, 0x1F359, + 0x07E69, 0x0654D, 0x1F35B, 0x0FB6C, 0x1F35A, 0x0654E, + 0x03F7B, 0x1F35D, 0x03F7C, 0x0FB6D, 0x1F35C, 0x009AA, + 0x03880, 0x1F36B, 0x0A086, 0x1F36A, 0x01FDA, 0x1F36C, + 0x0A087, 0x01051, 0x049C2, 0x0FB71, 0x07E6E, 0x0A088, + 0x03F7E, 0x06553, 0x1F36E, 0x1F36D, 0x06552, 0x028A6, + 0x02A90, 0x0A089, 0x1F36F, 0x03881, 0x0074A, 0x049C0, + 0x0FB6F, 0x0FB6E, 0x02614, 0x0FB70, 0x1F368, 0x1F367, + 0x07E6B, 0x0387F, 0x049C1, 0x07E6C, 0x06551, 0x050CB, + 0x014AA, 0x07E6D, 0x1F369, 0x02615, 0x0072C, 0x1F373, + 0x1F372, 0x008BB, 0x00450, 0x07E70, 0x1F375, 0x1F374, + 0x050CE, 0x03882, 0x1F376, 0x0FB74, 0x02617, 0x1F377, + 0x1F378, 0x07E71, 0x06557, 0x0FB75, 0x050CF, 0x050D0, + 0x0A08C, 0x03883, 0x02A91, 0x06555, 0x050CC, 0x06554, + 0x0A08A, 0x1F370, 0x050CD, 0x06556, 0x0FB72, 0x02616, + 0x07E6F, 0x0A08B, 0x01FDB, 0x0053A, 0x03F7F, 0x0FB73, + 0x1F371, 0x020D1, 0x01FE0, 0x1F3F9, 0x1F3F8, 0x02A98, + 0x00C4E, 0x0A0B6, 0x0FBB1, 0x1F3FA, 0x0FBB0, 0x1F3FC, + 0x1F3FD, 0x1F3FB, 0x0A0B7, 0x1F400, 0x1F401, 0x1F402, + 0x1F3FE, 0x1F3FF, 0x1F404, 0x1F405, 0x0FBB2, 0x1F403, + 0x1F3EF, 0x1F3F0, 0x1F3ED, 0x1F3EE, 0x1F3F3, 0x1F3F4, + 0x0FBAB, 0x1F3F1, 0x1F3F2, 0x0A0B5, 0x1F3F6, 0x1F3F5, + 0x0FBAC, 0x01052, 0x0FBAF, 0x1F3F7, 0x0FBAD, 0x0FBAE, + 0x004BC, 0x1F40D, 0x1F40E, 0x1F40C, 0x0FBB8, 0x049CC, + 0x1F410, 0x1F40F, 0x03F87, 0x0A0B9, 0x0A0BA, 0x1F412, + 0x0FBB9, 0x1F411, 0x1F415, 0x1F416, 0x1F413, 0x1F414, + 0x1F418, 0x0A0BB, 0x0FBBA, 0x1F417, 0x07E95, 0x07E93, + 0x1F406, 0x1F407, 0x0A0B8, 0x07E92, 0x0FBB5, 0x1F408, + 0x0FBB3, 0x0FBB4, 0x07E94, 0x0FBB7, 0x1F409, 0x0FBB6, + 0x03F86, 0x01DA3, 0x1F40B, 0x1F40A, 0x019C7, 0x06572, + 0x1F421, 0x1F420, 0x0250F, 0x00DBF, 0x1F422, 0x1F423, + 0x0FBBE, 0x050E2, 0x049CD, 0x1F425, 0x1F424, 0x07E97, + 0x1F427, 0x0FBC0, 0x1F428, 0x0FBBF, 0x1F426, 0x1F42A, + 0x1F42B, 0x1F429, 0x0A0C0, 0x013C7, 0x0A0BD, 0x1F419, + 0x0A0BC, 0x1F41C, 0x1F41D, 0x1F41E, 0x1F41A, 0x1F41B, + 0x0FBBC, 0x1F41F, 0x06571, 0x0FBBB, 0x01FE1, 0x0FBBD, + 0x0A0BF, 0x0A0BE, 0x07E96, 0x0FBC6, 0x1F437, 0x1F438, + 0x1F435, 0x1F436, 0x0A0C3, 0x1F43A, 0x1F439, 0x0FBC7, + 0x1F43B, 0x0FBC9, 0x0FBCA, 0x0FBC8, 0x07E99, 0x0A0C4, + 0x07E9A, 0x1F43C, 0x1F43D, 0x1F43E, 0x0A0C5, 0x050E4, + 0x0FBCB, 0x0FBCC, 0x050E3, 0x07E98, 0x0FBC2, 0x1F42C, + 0x0FBC1, 0x1F42F, 0x1F430, 0x1F42D, 0x1F42E, 0x0A0C1, + 0x1F432, 0x1F433, 0x0FBC3, 0x1F431, 0x0FBC5, 0x1F434, + 0x0FBC4, 0x0A0C2, 0x00AF6, 0x1F444, 0x0FBCF, 0x0261C, + 0x014AB, 0x0A0C8, 0x1F446, 0x1F445, 0x06573, 0x0261D, + 0x1F448, 0x1F447, 0x02A99, 0x0FBD1, 0x0A0C9, 0x1F449, + 0x0FBD0, 0x06574, 0x1F44C, 0x049CF, 0x1F44A, 0x1F44B, + 0x032EC, 0x1F440, 0x1F43F, 0x07E9B, 0x01B62, 0x0388A, + 0x1F441, 0x07E9C, 0x0A0C6, 0x00D6A, 0x0A0C7, 0x0FBCD, + 0x049CE, 0x00EDF, 0x0FBCE, 0x1F443, 0x1F442, 0x07E9D, + 0x03888, 0x0FB91, 0x1F3A8, 0x00E96, 0x00CEA, 0x0FB93, + 0x0FB94, 0x0FB92, 0x1F3A9, 0x03889, 0x0FB95, 0x0A0A7, + 0x0155F, 0x050E0, 0x0A0A8, 0x1F3AB, 0x1F3AA, 0x07E89, + 0x07E8A, 0x0A0AA, 0x0FB96, 0x0A0A9, 0x06567, 0x1F3A2, + 0x1F3A1, 0x02A95, 0x0250A, 0x06568, 0x1F3A4, 0x1F3A3, + 0x050DF, 0x02A96, 0x1F3A5, 0x06569, 0x00C4B, 0x00AFF, + 0x03887, 0x1F3A7, 0x1F3A6, 0x07E88, 0x0261B, 0x1F3BC, + 0x1F3BD, 0x1F3BA, 0x1F3BB, 0x0656C, 0x0FB97, 0x1F3BE, + 0x0656B, 0x1F3C0, 0x0FB98, 0x1F3C1, 0x07E8C, 0x1F3BF, + 0x1F3C2, 0x0FB9A, 0x0FB99, 0x0A0AC, 0x0656D, 0x0FB9B, + 0x1F3C4, 0x1F3C3, 0x07E8D, 0x049C9, 0x0A0AB, 0x1F3AE, + 0x1F3AC, 0x1F3AD, 0x1F3B1, 0x1F3B2, 0x1F3AF, 0x1F3B0, + 0x1F3B5, 0x1F3B6, 0x1F3B7, 0x1F3B3, 0x1F3B4, 0x0656A, + 0x1F3B9, 0x1F3B8, 0x07E8B, 0x03F84, 0x1F3CF, 0x1F3CE, + 0x032EB, 0x0250B, 0x0FB9E, 0x0A0AF, 0x1F3D0, 0x0A0AE, + 0x0A0B1, 0x1F3D1, 0x0A0B0, 0x049CA, 0x1F3D3, 0x1F3D4, + 0x0FBA0, 0x0FB9F, 0x1F3D2, 0x0FBA1, 0x0A0B2, 0x1F3D5, + 0x07E90, 0x07E8E, 0x1F3C6, 0x1F3C5, 0x0656E, 0x1F3C7, + 0x1F3C8, 0x0656F, 0x07E8F, 0x0FB9C, 0x0A0AD, 0x0FB9D, + 0x1F3C9, 0x050E1, 0x01FDF, 0x1F3CC, 0x1F3CD, 0x1F3CA, + 0x1F3CB, 0x00410, 0x0FBA9, 0x1F3DF, 0x1F3DE, 0x0FBA8, + 0x02A97, 0x1F3E1, 0x1F3E0, 0x0250E, 0x0FBAA, 0x1F3E3, + 0x1F3E4, 0x07E91, 0x1F3E2, 0x1F3E7, 0x1F3E8, 0x1F3E5, + 0x1F3E6, 0x1F3EA, 0x1F3EB, 0x1F3EC, 0x1F3E9, 0x0A0B4, + 0x03F85, 0x0FBA4, 0x1F3D6, 0x0FBA2, 0x0FBA3, 0x1F3D8, + 0x0FBA6, 0x1F3D7, 0x0FBA5, 0x1F3DB, 0x0A0B3, 0x1F3DC, + 0x1F3D9, 0x1F3DA, 0x049CB, 0x0FBA7, 0x1F3DD, 0x06570, + 0x0014C, 0x1F4A6, 0x1F4A7, 0x1F4A5, 0x0FBE7, 0x00DEF, + 0x1F4A9, 0x1F4A8, 0x01166, 0x050EB, 0x050EC, 0x1F4AB, + 0x1F4AA, 0x0A0D7, 0x0FBE8, 0x1F4AD, 0x1F4AC, 0x0A0D8, + 0x0A0D9, 0x1F4B0, 0x1F4B1, 0x1F4AE, 0x1F4AF, 0x0FBE6, + 0x1F49C, 0x1F49D, 0x1F49B, 0x0FBE5, 0x07EA2, 0x1F49F, + 0x1F49E, 0x0A0D6, 0x019F6, 0x1F4A1, 0x1F4A2, 0x1F4A0, + 0x050EA, 0x01C9E, 0x1F4A4, 0x1F4A3, 0x0133A, 0x00E4E, + 0x1F4BE, 0x1F4BD, 0x00BEE, 0x001AE, 0x050EE, 0x1F4C0, + 0x1F4BF, 0x050ED, 0x020DA, 0x1F4C2, 0x1F4C1, 0x050EF, + 0x0FBEB, 0x1F4C3, 0x1F4C4, 0x0FBE9, 0x0FBEA, 0x1F4C6, + 0x1F4C7, 0x1F4C5, 0x0A0DC, 0x1F4B4, 0x1F4B5, 0x1F4B2, + 0x1F4B3, 0x03F8A, 0x1F4B7, 0x1F4B8, 0x1F4B6, 0x0A0DA, + 0x02A9B, 0x1F4BA, 0x1F4B9, 0x0145F, 0x004AD, 0x0A0DB, + 0x1F4BC, 0x1F4BB, 0x03F8B, 0x003A6, 0x0A0DE, 0x1F4D1, + 0x1F4D0, 0x0FBED, 0x00DCA, 0x0FBEE, 0x1F4D2, 0x00EFE, + 0x02096, 0x0A0DF, 0x1F4D4, 0x1F4D3, 0x07EA6, 0x0FBEF, + 0x1F4D6, 0x1F4D5, 0x0A0E0, 0x1F4D9, 0x1F4DA, 0x1F4DB, + 0x1F4D7, 0x1F4D8, 0x07EA3, 0x1F4CA, 0x1F4CB, 0x1F4C8, + 0x1F4C9, 0x0388E, 0x0FBEC, 0x1F4CC, 0x049D8, 0x00CEB, + 0x0657A, 0x0A0DD, 0x1F4CD, 0x049D9, 0x00521, 0x1F4CF, + 0x1F4CE, 0x00CFA, 0x01B67, 0x1F4E4, 0x1F4E3, 0x032EF, + 0x00292, 0x0FBF2, 0x1F4E6, 0x1F4E5, 0x0FBF1, 0x014D2, + 0x0A0E5, 0x0A0E4, 0x028AA, 0x1F4E9, 0x0657F, 0x1F4EA, + 0x1F4E7, 0x1F4E8, 0x1F4ED, 0x1F4EE, 0x1F4EB, 0x1F4EC, + 0x0412E, 0x1F4DC, 0x0A0E1, 0x0A0E2, 0x049DA, 0x1F4DE, + 0x1F4DF, 0x1F4DD, 0x0657B, 0x01B66, 0x1F4E0, 0x0FBF0, + 0x0388F, 0x00522, 0x0A0E3, 0x1F4E2, 0x1F4E1, 0x0657E, + 0x007C2, 0x0A0EB, 0x1F4F8, 0x1F4F7, 0x0FBF5, 0x00F7A, + 0x1F4F9, 0x0FBF6, 0x020DB, 0x028AB, 0x1F4FB, 0x1F4FC, + 0x1F4FA, 0x0FBF7, 0x01DFE, 0x0BEFA, 0x1F4FD, 0x07EA7, + 0x1F502, 0x13FC2, 0x1F503, 0x1F4FE, 0x1F4FF, 0x1F4F1, + 0x0FBF3, 0x1F4F2, 0x1F4EF, 0x1F4F0, 0x02576, 0x0A0E7, + 0x1F4F3, 0x0A0E6, 0x07092, 0x0FBF4, 0x1F4F5, 0x1F4F4, + 0x049DB, 0x0096F, 0x1F4F6, 0x0A0EA, 0x02623, 0x006FF, + 0x1F45C, 0x1F45D, 0x1F45B, 0x07E9E, 0x03F88, 0x1F45F, + 0x1F45E, 0x020D7, 0x06575, 0x1F462, 0x0FBD2, 0x1F460, + 0x1F461, 0x1F464, 0x0FBD4, 0x0FBD3, 0x1F463, 0x1F467, + 0x1F468, 0x1F469, 0x1F465, 0x1F466, 0x1F44F, 0x1F450, + 0x1F451, 0x1F44D, 0x1F44E, 0x1F453, 0x1F454, 0x1F452, + 0x020D6, 0x0388B, 0x1F457, 0x1F458, 0x1F455, 0x1F456, + 0x028A9, 0x1F45A, 0x1F459, 0x00DED, 0x020D8, 0x1F472, + 0x1F471, 0x0261F, 0x006F0, 0x0FBD6, 0x1F474, 0x1F473, + 0x050E5, 0x049D3, 0x0FBD7, 0x1F475, 0x015EE, 0x1F477, + 0x0A0CD, 0x1F478, 0x1F476, 0x050E6, 0x1F47A, 0x1F47B, + 0x1F479, 0x0A0CE, 0x0A0CB, 0x1F46A, 0x0A0CA, 0x0261E, + 0x049D0, 0x0A0CC, 0x1F46C, 0x1F46B, 0x06576, 0x049D1, + 0x1F46E, 0x1F46D, 0x01FE2, 0x004DE, 0x049D2, 0x1F470, + 0x1F46F, 0x0FBD5, 0x00376, 0x0FBDB, 0x0FBDC, 0x1F482, + 0x0A0D0, 0x00C5E, 0x1F484, 0x1F483, 0x00BEB, 0x020D9, + 0x06578, 0x1F486, 0x1F485, 0x07E9F, 0x0A0D1, 0x1F487, + 0x07EA0, 0x050E8, 0x1F488, 0x0FBDF, 0x1F489, 0x0FBDD, + 0x0FBDE, 0x050E7, 0x0A0CF, 0x1F47D, 0x1F47C, 0x0FBD8, + 0x06577, 0x1F47F, 0x1F47E, 0x032ED, 0x012BA, 0x03F89, + 0x0FBD9, 0x1F480, 0x032EE, 0x00C4F, 0x1F481, 0x0FBDA, + 0x01B63, 0x00DEE, 0x0FBE1, 0x1F491, 0x0115B, 0x001CE, + 0x049D6, 0x1F493, 0x1F492, 0x0A0D4, 0x049D7, 0x1F495, + 0x1F494, 0x02A9A, 0x0A0D5, 0x0FBE3, 0x1F497, 0x1F496, + 0x0FBE2, 0x0FBE4, 0x1F49A, 0x1F498, 0x1F499, 0x049D4, + 0x1F48A, 0x0A0D2, 0x0FBE0, 0x049D5, 0x0A0D3, 0x1F48C, + 0x1F48B, 0x07EA1, 0x01FE3, 0x1F48E, 0x1F48D, 0x02622, + 0x00520, 0x050E9, 0x1F490, 0x1F48F, 0x06579, 0x0018A, + 0x09FE6, 0x1F0E6, 0x1F0E5, 0x0459C, 0x00DCB, 0x1F0E7, + 0x0FA96, 0x012D0, 0x020A6, 0x1F0E9, 0x1F0EA, 0x1F0E8, + 0x0FA97, 0x09FE7, 0x1F0EC, 0x1F0EB, 0x06370, 0x09FE8, + 0x1F0EE, 0x1F0EF, 0x0FA98, 0x1F0ED, 0x1F0DC, 0x1F0DD, + 0x1F0DE, 0x1F0DA, 0x1F0DB, 0x1F0DF, 0x1F0E0, 0x0FA93, + 0x0FA94, 0x0507C, 0x1F0E2, 0x1F0E3, 0x1F0E1, 0x0507B, + 0x00AAE, 0x1F0E4, 0x0FA95, 0x00F5D, 0x00DB4, 0x0FA9C, + 0x1F0F9, 0x00FF2, 0x003AC, 0x1F0FB, 0x1F0FC, 0x1F0FA, + 0x029E0, 0x025CF, 0x1F0FE, 0x1F0FD, 0x029E1, 0x029E2, + 0x09FE9, 0x1F180, 0x1F0FF, 0x07E04, 0x0FA9D, 0x1F183, + 0x1F181, 0x1F182, 0x0FA9A, 0x1F0F1, 0x0FA99, 0x1F0F0, + 0x0384C, 0x1F0F3, 0x1F0F4, 0x1F0F2, 0x0FA9B, 0x019F7, + 0x1F0F6, 0x1F0F5, 0x02878, 0x0018C, 0x06371, 0x1F0F8, + 0x1F0F7, 0x07E03, 0x002FC, 0x0507E, 0x1F18E, 0x1F18D, + 0x06373, 0x00D2C, 0x1F190, 0x1F18F, 0x01356, 0x01357, + 0x0FAA0, 0x1F192, 0x1F191, 0x0507F, 0x02879, 0x1F194, + 0x1F193, 0x0384D, 0x1F197, 0x0FAA1, 0x0FAA2, 0x1F195, + 0x1F196, 0x1F186, 0x1F187, 0x1F188, 0x1F184, 0x1F185, + 0x0507D, 0x1F189, 0x0FA9E, 0x06372, 0x020A7, 0x07E05, + 0x1F18B, 0x1F18A, 0x09FEA, 0x00AF8, 0x0FA9F, 0x1F18C, + 0x00A30, 0x0106F, 0x1F19F, 0x1F19E, 0x01AD6, 0x005F6, + 0x1F1A1, 0x1F1A2, 0x1F1A0, 0x0FAA8, 0x0099E, 0x0FAA9, + 0x1F1A3, 0x06375, 0x0459E, 0x07E07, 0x1F1A6, 0x1F1A4, + 0x1F1A5, 0x09FEC, 0x0FAAA, 0x1F1A7, 0x09FEB, 0x0FAA4, + 0x1F199, 0x1F198, 0x0FAA3, 0x0FAA6, 0x0459D, 0x1F19B, + 0x1F19A, 0x0FAA5, 0x01C49, 0x07E06, 0x1F19C, 0x03F56, + 0x0077E, 0x05080, 0x1F19D, 0x0FAA7, 0x06374, 0x008A2, + 0x1F1B3, 0x1F1B4, 0x0FAAE, 0x1F1B2, 0x00AB0, 0x1F1B6, + 0x1F1B5, 0x04980, 0x0384E, 0x0FAAF, 0x1F1B8, 0x1F1B7, + 0x06377, 0x04981, 0x1F1BA, 0x1F1B9, 0x07E09, 0x07E0A, + 0x1F1BC, 0x1F1BD, 0x1F1BB, 0x0FAB0, 0x1F1AA, 0x1F1AB, + 0x1F1AC, 0x1F1A8, 0x1F1A9, 0x0FAAC, 0x07E08, 0x0FAAB, + 0x1F1AD, 0x029E3, 0x06376, 0x0FAAD, 0x1F1AE, 0x1F1AF, + 0x0459F, 0x1F1B1, 0x1F1B0, 0x01AD7, 0x00822, 0x1DFF2, + 0x1DFF3, 0x1DFF1, 0x0FA82, 0x03F52, 0x1DFF5, 0x1DFF4, + 0x00BF6, 0x062F8, 0x07DFD, 0x1DFF7, 0x1DFF6, 0x09FE0, + 0x062F9, 0x1DFF9, 0x1DFF8, 0x029A6, 0x0FA83, 0x1DFFC, + 0x1DFFD, 0x1DFFA, 0x1DFFB, 0x13FC3, 0x17DF6, 0x17DF7, + 0x0FA80, 0x0412F, 0x05074, 0x1C24C, 0x05F7C, 0x05F7E, + 0x03848, 0x05F7F, 0x1C24E, 0x1C24D, 0x07DFC, 0x01FC6, + 0x1DFF0, 0x1C24F, 0x02577, 0x029A7, 0x1EF67, 0x1EF66, + 0x024EE, 0x003BE, 0x0FA88, 0x1EF69, 0x1EF68, 0x062FA, + 0x0384B, 0x1EF6B, 0x1EF6A, 0x015EF, 0x05076, 0x0FA89, + 0x1EF6D, 0x1EF6C, 0x07E00, 0x1EF6F, 0x0FA8A, 0x1EF6E, + 0x062FB, 0x1EF60, 0x0FA84, 0x1DFFE, 0x1DFFF, 0x07DFE, + 0x0FA85, 0x1EF62, 0x1EF61, 0x03F54, 0x0384A, 0x1EF63, + 0x0FA86, 0x00E30, 0x002EC, 0x0FA87, 0x1EF65, 0x1EF64, + 0x07DFF, 0x002FE, 0x09FE3, 0x1EF7C, 0x1EF7B, 0x07E01, + 0x0095C, 0x1EF7E, 0x1EF7D, 0x01456, 0x0133B, 0x05077, + 0x1F0C0, 0x1EF7F, 0x062FD, 0x05078, 0x1F0C2, 0x1F0C1, + 0x01C46, 0x03F55, 0x1F0C4, 0x1F0C5, 0x1F0C3, 0x0FA8D, + 0x1EF72, 0x1EF73, 0x1EF74, 0x1EF70, 0x1EF71, 0x062FC, + 0x1EF75, 0x0FA8B, 0x09FE2, 0x0154E, 0x1EF78, 0x0FA8C, + 0x1EF76, 0x1EF77, 0x00F5C, 0x1EF7A, 0x1EF79, 0x00DB2, + 0x0106E, 0x1F0D3, 0x1F0D2, 0x00ED0, 0x0045A, 0x07E02, + 0x0FA8F, 0x1F0D4, 0x1F0D5, 0x01C48, 0x0FA91, 0x0FA90, + 0x025CE, 0x032BE, 0x062FF, 0x1F0D7, 0x1F0D6, 0x0FA92, + 0x09FE5, 0x1F0D9, 0x1F0D8, 0x09FE4, 0x1F0C8, 0x1F0C9, + 0x1F0C6, 0x1F0C7, 0x05079, 0x1F0CB, 0x1F0CC, 0x1F0CA, + 0x0FA8E, 0x0507A, 0x1F0CE, 0x1F0CD, 0x024EF, 0x0018F, + 0x1F0D0, 0x1F0D1, 0x1F0CF, 0x062FE, 0x04986, 0x1F211, + 0x1F210, 0x029E5, 0x0149C, 0x09FFF, 0x1F212, 0x0FAD5, + 0x0FAD6, 0x0FAD8, 0x1F214, 0x1F213, 0x0FAD7, 0x0A000, + 0x0A001, 0x1F216, 0x1F215, 0x0FAD9, 0x0A003, 0x0FADA, + 0x1F217, 0x0A002, 0x0FAD1, 0x1F205, 0x1F203, 0x1F204, + 0x1F207, 0x1F208, 0x1F209, 0x1F206, 0x0FAD2, 0x1F20C, + 0x0FAD3, 0x1F20A, 0x1F20B, 0x00E31, 0x0FAD4, 0x1F20F, + 0x1F20D, 0x1F20E, 0x003BC, 0x1F221, 0x0FADD, 0x1F21F, + 0x1F220, 0x01D2E, 0x1F223, 0x1F222, 0x0384F, 0x0A007, + 0x1F225, 0x1F226, 0x07E18, 0x1F224, 0x1F229, 0x1F22A, + 0x1F227, 0x1F228, 0x01ADD, 0x0A009, 0x1F22B, 0x0A008, + 0x04987, 0x0FADC, 0x07E16, 0x1F218, 0x0FADB, 0x07E15, + 0x1F21B, 0x1F21C, 0x1F219, 0x1F21A, 0x0637A, 0x0A005, + 0x0A006, 0x07E17, 0x0A004, 0x025F0, 0x1F21E, 0x1F21D, + 0x01ADC, 0x05088, 0x1F235, 0x1F234, 0x05087, 0x01978, + 0x1F238, 0x07E1A, 0x1F236, 0x1F237, 0x07E1C, 0x1F239, + 0x0FAE2, 0x07E1B, 0x1F23B, 0x0A00D, 0x1F23C, 0x1F23A, + 0x0FAE3, 0x01979, 0x0A00E, 0x1F23D, 0x04989, 0x1F22E, + 0x1F22F, 0x1F22C, 0x1F22D, 0x1F231, 0x0A00A, 0x1F232, + 0x0FADE, 0x1F230, 0x04988, 0x0FADF, 0x1F233, 0x07E19, + 0x01ADE, 0x0A00C, 0x0FAE1, 0x0FAE0, 0x0A00B, 0x032C2, + 0x1F249, 0x1F24A, 0x1F248, 0x0A010, 0x05089, 0x1F24C, + 0x0A011, 0x1F24B, 0x0A012, 0x0FAEA, 0x1F24E, 0x0508A, + 0x1F24D, 0x0A014, 0x1F250, 0x0A013, 0x1F24F, 0x029E6, + 0x07E1D, 0x1F253, 0x1F251, 0x1F252, 0x0FAE4, 0x0FAE5, + 0x0FAE6, 0x1F23E, 0x1F23F, 0x1F242, 0x0A00F, 0x1F240, + 0x1F241, 0x0FAE8, 0x1F244, 0x1F245, 0x0FAE7, 0x1F243, + 0x0FAE9, 0x1F247, 0x1F246, 0x03850, 0x01286, 0x1F25E, + 0x1F25D, 0x03851, 0x00D2D, 0x1F260, 0x1F261, 0x1F25F, + 0x07E1E, 0x00A68, 0x1F262, 0x0A015, 0x0637C, 0x0508C, + 0x0498A, 0x1F265, 0x1F263, 0x1F264, 0x03852, 0x0FAEE, + 0x1F266, 0x0A016, 0x0FAEB, 0x0FAEC, 0x1F254, 0x1F255, + 0x1F258, 0x0637B, 0x1F259, 0x1F256, 0x1F257, 0x032C3, + 0x0FAED, 0x0508B, 0x03F59, 0x01310, 0x032C4, 0x1F25C, + 0x1F25A, 0x1F25B, 0x04982, 0x09FEE, 0x1F1C4, 0x00FF3, + 0x01457, 0x06378, 0x1F1C6, 0x1F1C5, 0x0FAB4, 0x0287B, + 0x0FAB6, 0x0FAB5, 0x00FF6, 0x03F57, 0x0FAB7, 0x09FEF, + 0x1F1C7, 0x05083, 0x09FF0, 0x1F1C8, 0x0FAB8, 0x01FC8, + 0x09FED, 0x0FAB2, 0x0FAB1, 0x1F1BE, 0x07E0B, 0x05081, + 0x0FAB3, 0x1F1BF, 0x024F0, 0x0287A, 0x1F1C1, 0x1F1C0, + 0x01FC7, 0x00E5A, 0x05082, 0x1F1C3, 0x1F1C2, 0x07E0C, + 0x032C0, 0x0FABE, 0x0FABF, 0x1F1D1, 0x1F1D2, 0x07E10, + 0x1F1D5, 0x1F1D3, 0x1F1D4, 0x0FAC2, 0x0FAC3, 0x1F1D6, + 0x0FAC0, 0x0FAC1, 0x1F1D9, 0x1F1DA, 0x1F1D7, 0x1F1D8, + 0x05085, 0x09FF2, 0x1F1DC, 0x1F1DB, 0x0FAC4, 0x0FAB9, + 0x0FABA, 0x1F1CA, 0x07E0D, 0x1F1C9, 0x1F1CB, 0x1F1CC, + 0x07E0E, 0x0FABB, 0x0FABD, 0x1F1CD, 0x1F1CE, 0x0FABC, + 0x09FF1, 0x07E0F, 0x1F1D0, 0x1F1CF, 0x05084, 0x0287C, + 0x1F1E6, 0x1F1E5, 0x03F58, 0x0287D, 0x09FF6, 0x1F1E9, + 0x1F1E7, 0x1F1E8, 0x07E13, 0x09FF8, 0x1F1EA, 0x09FF7, + 0x1F1ED, 0x09FF9, 0x0FAC8, 0x1F1EB, 0x1F1EC, 0x09FFB, + 0x04984, 0x09FFA, 0x04983, 0x09FF3, 0x1F1DE, 0x1F1DD, + 0x07E11, 0x1F1DF, 0x1F1E0, 0x0FAC6, 0x09FF4, 0x0FAC5, + 0x07E12, 0x1F1E2, 0x1F1E1, 0x05086, 0x00ED2, 0x09FF5, + 0x1F1E4, 0x1F1E3, 0x0FAC7, 0x004D4, 0x1F1F9, 0x1F1FA, + 0x09FFC, 0x0FACD, 0x029E4, 0x0FACE, 0x1F1FB, 0x0287E, + 0x09FFD, 0x0FAD0, 0x1F1FC, 0x0FACF, 0x06379, 0x1F1FE, + 0x1F1FF, 0x1F1FD, 0x09FFE, 0x04985, 0x07E14, 0x1F202, + 0x1F200, 0x1F201, 0x1F1EF, 0x1F1F0, 0x1F1F1, 0x1F1EE, + 0x0FAC9, 0x1F1F3, 0x1F1F4, 0x1F1F2, 0x0FACA, 0x032C1, + 0x1F1F6, 0x0FACC, 0x1F1F5, 0x0FACB, 0x01C9F, 0x1F1F8, + 0x1F1F7, 0x01FC9, 0x000EC, 0x0650B, 0x0650C, 0x07E2B, + 0x029EC, 0x00DB6, 0x0FB04, 0x1F298, 0x0098C, 0x01FCC, + 0x0650D, 0x07E2C, 0x0FB05, 0x0FB06, 0x0FB08, 0x1F29A, + 0x1F299, 0x0FB07, 0x00ED3, 0x05094, 0x1F29B, 0x07E2D, + 0x0FB09, 0x03855, 0x06508, 0x0FB02, 0x1F292, 0x0FB01, + 0x1F295, 0x1F296, 0x1F293, 0x1F294, 0x05093, 0x0FB03, + 0x0650A, 0x07E2A, 0x06509, 0x00BB6, 0x0A02B, 0x1F297, + 0x00A54, 0x00708, 0x1F2A2, 0x1F2A1, 0x007A8, 0x004CA, + 0x029EE, 0x07E2F, 0x05095, 0x0197B, 0x01C4A, 0x0A02D, + 0x07E30, 0x01FCD, 0x0FB0C, 0x0650F, 0x0FB0D, 0x1F2A3, + 0x0650E, 0x01D78, 0x06510, 0x07E31, 0x07E32, 0x04993, + 0x07E2E, 0x0A02C, 0x03F5D, 0x1F29E, 0x1F29F, 0x03856, + 0x1F29C, 0x1F29D, 0x03857, 0x0FB0A, 0x1F2A0, 0x029ED, + 0x004B8, 0x024F5, 0x03F5E, 0x0FB0B, 0x03858, 0x008AC, + 0x0FB13, 0x07E35, 0x0FB12, 0x06512, 0x01C4C, 0x07E36, + 0x0FB14, 0x01550, 0x02882, 0x07E37, 0x07E38, 0x06513, + 0x05096, 0x06514, 0x0A032, 0x1F2A7, 0x1F2A8, 0x006E7, + 0x032CA, 0x1F2A9, 0x0FB15, 0x029EF, 0x07E34, 0x0A02E, + 0x0A02F, 0x0FB0E, 0x07E33, 0x0FB10, 0x06511, 0x1F2A4, + 0x0FB0F, 0x04994, 0x02881, 0x0A031, 0x0A030, 0x0FB11, + 0x01289, 0x1F2A6, 0x1F2A5, 0x01C4B, 0x05098, 0x1F2AE, + 0x1F2AD, 0x07E3A, 0x06519, 0x1F2AF, 0x1F2B0, 0x0FB19, + 0x0A038, 0x05099, 0x1F2B2, 0x1F2B1, 0x07E3B, 0x0FB1A, + 0x1F2B4, 0x1F2B5, 0x04995, 0x1F2B3, 0x0149D, 0x03F60, + 0x0FB1B, 0x025F2, 0x0A033, 0x06516, 0x06515, 0x03F5F, + 0x0A035, 0x1F2AA, 0x07E39, 0x0A034, 0x0FB16, 0x06517, + 0x1F2AC, 0x1F2AB, 0x0FB17, 0x05097, 0x0A036, 0x0A037, + 0x0FB18, 0x06518, 0x0031A, 0x0A03C, 0x1F2BA, 0x1F2B9, + 0x07E3F, 0x0057E, 0x0FB1C, 0x1F2BB, 0x00F5E, 0x01551, + 0x025F3, 0x1F2BC, 0x07E40, 0x04996, 0x00BB8, 0x1F2BD, + 0x04997, 0x0385A, 0x00E32, 0x0651D, 0x1F2BF, 0x1F2BE, + 0x07E41, 0x0651A, 0x0A03A, 0x1F2B7, 0x1F2B6, 0x0A039, + 0x03859, 0x07E3D, 0x07E3C, 0x0509A, 0x029F0, 0x0651C, + 0x0A03B, 0x0651B, 0x07E3E, 0x0096A, 0x1F2B8, 0x0509B, + 0x01D79, 0x0073E, 0x0A01C, 0x1F26B, 0x1F26A, 0x0FAF0, + 0x01312, 0x0FAF1, 0x1F26C, 0x0074E, 0x00DE2, 0x0637D, + 0x0FAF2, 0x1F26D, 0x029E9, 0x025F1, 0x0508D, 0x1F26E, + 0x0072A, 0x01288, 0x1F270, 0x1F271, 0x1F26F, 0x0637E, + 0x1F267, 0x0A018, 0x0498B, 0x0A017, 0x029E7, 0x0A019, + 0x0A01A, 0x1F268, 0x029E8, 0x0175C, 0x0287F, 0x0A01B, + 0x1F269, 0x03F5A, 0x02880, 0x0498C, 0x0FAEF, 0x00DB5, + 0x07E1F, 0x1F27B, 0x1F27A, 0x0FAF4, 0x024F1, 0x1F27E, + 0x0A01F, 0x1F27C, 0x1F27D, 0x0FAF5, 0x1F280, 0x1F27F, + 0x06502, 0x0FAF6, 0x1F282, 0x07E21, 0x07E20, 0x1F281, + 0x029EA, 0x07E23, 0x07E22, 0x0154F, 0x0637F, 0x06500, + 0x0498D, 0x0FAF3, 0x1F272, 0x1F273, 0x0A01D, 0x0508E, + 0x032C5, 0x1F275, 0x1F276, 0x1F274, 0x06501, 0x03853, + 0x0A01E, 0x1F279, 0x1F277, 0x1F278, 0x0074F, 0x03854, + 0x032C7, 0x0FAFA, 0x1F286, 0x029EB, 0x07E25, 0x0A024, + 0x024F3, 0x01FCA, 0x0508F, 0x032C8, 0x1F287, 0x0A025, + 0x07E26, 0x0A026, 0x1F288, 0x1F289, 0x006E6, 0x0498E, + 0x1F28B, 0x1F28A, 0x032C9, 0x032C6, 0x0A021, 0x0A022, + 0x0A020, 0x03F5B, 0x1F283, 0x1F284, 0x06503, 0x0FAF7, + 0x024F2, 0x07E24, 0x1F285, 0x0FAF8, 0x01313, 0x01ADF, + 0x0FAF9, 0x0A023, 0x00AB1, 0x0055E, 0x1F28F, 0x1F28E, + 0x00972, 0x005FA, 0x024F4, 0x0FAFE, 0x1F290, 0x04990, + 0x020BC, 0x0FAFF, 0x1F291, 0x01D2F, 0x04991, 0x0A02A, + 0x05092, 0x0A029, 0x0FB00, 0x04992, 0x06507, 0x06506, + 0x01FCB, 0x03F5C, 0x05090, 0x06504, 0x0A027, 0x1F28C, + 0x1F28D, 0x07E28, 0x07E27, 0x0A028, 0x05091, 0x0FAFC, + 0x0FAFB, 0x0197A, 0x003D6, 0x0FAFD, 0x07E29, 0x0498F, + 0x06505, 0x00056, 0x020C0, 0x02888, 0x0005C, 0x0005A, + 0x0071E, 0x00CE4, 0x00A32, 0x005D6, 0x00A34, 0x0288A, + 0x02889, 0x00A33, 0x049A2, 0x0A046, 0x01D7A, 0x025F9, + 0x0A045, 0x01315, 0x01316, 0x07E4B, 0x01458, 0x00676, + 0x00F71, 0x01B51, 0x006FD, 0x07E4A, 0x06529, 0x01768, + 0x00AB3, 0x07E49, 0x009E4, 0x03F64, 0x050A1, 0x00DE3, + 0x00064, 0x008B8, 0x00AB4, 0x00BBB, 0x007FA, 0x0003C, + 0x009E7, 0x00AFA, 0x01459, 0x00AB5, 0x001AF, 0x03862, + 0x0288C, 0x0019E, 0x00BFD, 0x01C51, 0x0149F, 0x00F73, + 0x029FA, 0x07E4C, 0x0A047, 0x1F2D4, 0x03863, 0x00F74, + 0x01B52, 0x01B53, 0x050A2, 0x0137D, 0x006E8, 0x008A4, + 0x029F9, 0x00E33, 0x006E0, 0x03F65, 0x049A3, 0x1F2D3, + 0x03861, 0x00A35, 0x0197C, 0x00F72, 0x012D1, 0x0288B, + 0x0015C, 0x01FCF, 0x049A4, 0x001A6, 0x00BBC, 0x1F2D5, + 0x0A048, 0x00AB6, 0x0075A, 0x020C2, 0x03864, 0x0104E, + 0x050A5, 0x01D7B, 0x0A049, 0x1F2D6, 0x024F8, 0x0652B, + 0x1F2D7, 0x03865, 0x025FA, 0x07E4E, 0x014A0, 0x0652C, + 0x029FC, 0x00E5D, 0x00CE5, 0x0288D, 0x0098F, 0x006E9, + 0x0FB2C, 0x0652A, 0x01C52, 0x0104D, 0x0FB2B, 0x0128B, + 0x050A3, 0x07E4D, 0x029FB, 0x00990, 0x01FD0, 0x024F7, + 0x050A4, 0x020C1, 0x01B54, 0x1F2DD, 0x0FB30, 0x0FB2E, + 0x0FB2F, 0x049A6, 0x1F2DF, 0x1F2DE, 0x0288E, 0x029FD, + 0x0FB31, 0x025FD, 0x07E4F, 0x1F2E0, 0x0652E, 0x1F2E2, + 0x1F2E1, 0x0A04D, 0x0128C, 0x03F67, 0x0FB33, 0x0FB32, + 0x01B55, 0x025FC, 0x03F66, 0x0652D, 0x025FB, 0x0083C, + 0x1F2DA, 0x0FB2D, 0x1F2D8, 0x1F2D9, 0x0A04B, 0x050A6, + 0x050A7, 0x024F9, 0x0A04A, 0x0A04C, 0x1F2DC, 0x1F2DB, + 0x049A5, 0x00538, 0x0FB35, 0x0FB34, 0x01147, 0x0051E, + 0x03866, 0x0A04F, 0x1F2E7, 0x024FA, 0x002BC, 0x1F2E8, + 0x0FB36, 0x00DE4, 0x01555, 0x050AA, 0x1F2E9, 0x0FB37, + 0x0288F, 0x01FD2, 0x1F2EA, 0x0FB38, 0x032D0, 0x0652F, + 0x1F2E3, 0x020C3, 0x01FD1, 0x025FE, 0x03F68, 0x0A04E, + 0x06530, 0x01769, 0x01D7C, 0x1F2E4, 0x050A8, 0x00ED4, + 0x0099F, 0x050A9, 0x1F2E6, 0x1F2E5, 0x06531, 0x00F5F, + 0x0FB20, 0x0FB1F, 0x006B4, 0x0067C, 0x029F1, 0x1F2C2, + 0x1F2C1, 0x032CB, 0x0149E, 0x0509E, 0x1F2C3, 0x00A6A, + 0x00E5B, 0x025F4, 0x0FB21, 0x1F2C4, 0x1F2C5, 0x02883, + 0x0651F, 0x0FB22, 0x03F61, 0x0509C, 0x04998, 0x0FB1D, + 0x07E42, 0x0175D, 0x0107A, 0x0A03D, 0x07E43, 0x04999, + 0x01B50, 0x0509D, 0x0651E, 0x0104A, 0x0137C, 0x0499A, + 0x0FB1E, 0x1F2C0, 0x07E44, 0x0385C, 0x07E45, 0x0A040, + 0x1F2CA, 0x1F2CB, 0x032CC, 0x1F2CD, 0x1F2CC, 0x0385D, + 0x02884, 0x06523, 0x03F63, 0x1F2CE, 0x0FB24, 0x0FB25, + 0x1F2D1, 0x1F2CF, 0x1F2D0, 0x00F70, 0x07E46, 0x0FB26, + 0x1F2D2, 0x0499C, 0x03F62, 0x0095E, 0x01C4D, 0x0499B, + 0x00BF7, 0x06520, 0x1F2C6, 0x0FB23, 0x0A03E, 0x0A03F, + 0x1F2C7, 0x025F5, 0x0385B, 0x06521, 0x0509F, 0x1F2C9, + 0x1F2C8, 0x06522, 0x00AF9, 0x0A042, 0x0FB27, 0x00A56, + 0x006DE, 0x029F2, 0x029F3, 0x032CD, 0x032CE, 0x02886, + 0x0385E, 0x07E48, 0x0175F, 0x050A0, 0x0FB29, 0x01C4F, + 0x029F4, 0x0FB28, 0x01553, 0x0A043, 0x025F6, 0x01314, + 0x006FC, 0x0098E, 0x02885, 0x01552, 0x0A041, 0x06525, + 0x0128A, 0x020BD, 0x06524, 0x01C4E, 0x07E47, 0x0499D, + 0x00CE2, 0x0071A, 0x06526, 0x01FCE, 0x0175E, 0x024F6, + 0x00046, 0x009E2, 0x01C50, 0x00DB7, 0x00BB9, 0x00188, + 0x06527, 0x0499E, 0x0017C, 0x00D2F, 0x025F7, 0x00BBA, + 0x00DB8, 0x02887, 0x049A1, 0x06528, 0x0499F, 0x049A0, + 0x0104C, 0x020BF, 0x0FB2A, 0x029F8, 0x025F8, 0x00A31, + 0x0051C, 0x01554, 0x029F5, 0x00BFC, 0x032CF, 0x0A044, + 0x0385F, 0x029F6, 0x00AB2, 0x020BE, 0x00E5C, 0x00A57, + 0x00D2E, 0x001AC, 0x029F7, 0x03860, 0x00125, +}; + +static const uint8_t on2avc_cb7_bits[ON2AVC_CB7_CODES] = { + 1, 8, 8, 8, 8, 7, + 10, 11, 7, 11, 12, 10, + 10, 12, 14, 14, 15, 14, + 11, 11, 13, 13, 12, 10, + 11, 13, 12, 12, 14, 14, + 14, 13, 11, 12, 9, 10, + 12, 7, 11, 11, 7, 7, + 11, 12, 7, 7, 10, 9, + 11, 11, 11, 13, 13, 12, + 14, 15, 11, 12, 14, 12, + 13, 12, 12, 12, 12, 11, + 11, 15, 15, 10, 12, 15, + 12, 12, 14, 11, 7, 10, + 8, 11, 11, 11, 16, 13, + 12, 14, 12, 16, 15, 12, + 13, 14, 14, 12, 14, 17, + 15, 16, 16, 12, 14, 16, + 14, 12, 12, 13, 16, 14, + 12, 17, 16, 16, 15, 13, + 13, 14, 12, 14, 12, 16, + 16, 12, 16, 17, 16, 17, + 15, 16, 16, 15, 17, 15, + 17, 17, 16, 17, 16, 15, + 14, 16, 14, 16, 14, 11, + 14, 16, 15, 11, 17, 17, + 15, 13, 17, 16, 17, 17, + 15, 14, 17, 15, 14, 16, + 11, 16, 17, 16, 14, 12, + 17, 15, 12, 13, 15, 17, + 16, 13, 15, 17, 16, 13, + 15, 16, 17, 15, 13, 14, + 16, 17, 17, 14, 14, 16, + 16, 13, 12, 15, 17, 16, + 14, 11, 15, 15, 12, 10, + 14, 16, 16, 16, 12, 15, + 16, 12, 12, 13, 15, 17, + 14, 12, 15, 17, 14, 14, + 15, 16, 16, 16, 16, 16, + 16, 16, 16, 12, 16, 17, + 14, 11, 13, 15, 17, 15, + 12, 14, 16, 11, 14, 17, + 17, 14, 15, 17, 14, 17, + 16, 15, 17, 15, 14, 17, + 15, 14, 17, 17, 12, 15, + 16, 14, 12, 13, 16, 13, + 16, 16, 15, 16, 16, 16, + 17, 17, 16, 14, 16, 14, + 17, 17, 11, 14, 12, 13, + 15, 12, 14, 15, 12, 13, + 14, 12, 13, 14, 14, 16, + 17, 15, 11, 12, 14, 15, + 13, 12, 12, 14, 14, 13, + 15, 17, 16, 16, 14, 14, + 13, 13, 14, 12, 16, 17, + 12, 7, 12, 12, 7, 7, + 11, 11, 8, 10, 11, 13, + 13, 11, 15, 14, 12, 10, + 14, 11, 11, 13, 12, 11, + 12, 13, 12, 15, 14, 12, + 11, 14, 11, 15, 13, 11, + 7, 11, 11, 9, 10, 7, + 13, 14, 7, 7, 12, 12, + 12, 11, 12, 17, 14, 12, + 14, 16, 14, 14, 14, 11, + 12, 12, 11, 13, 15, 14, + 13, 15, 16, 14, 14, 15, + 12, 14, 14, 12, 7, 11, + 12, 12, 11, 7, 12, 13, + 13, 12, 9, 14, 14, 9, + 12, 12, 12, 13, 13, 14, + 15, 14, 14, 12, 11, 14, + 13, 11, 12, 13, 14, 14, + 13, 15, 15, 16, 14, 12, + 14, 12, 12, 14, 9, 14, + 13, 9, 12, 17, 15, 12, + 12, 14, 13, 13, 13, 13, + 14, 16, 13, 16, 15, 12, + 14, 16, 13, 14, 12, 11, + 13, 17, 15, 13, 15, 17, + 15, 13, 15, 13, 15, 17, + 13, 11, 14, 15, 13, 13, + 14, 17, 17, 17, 16, 14, + 17, 16, 15, 16, 17, 16, + 14, 15, 17, 15, 17, 16, + 14, 14, 14, 15, 12, 13, + 14, 17, 16, 14, 16, 17, + 17, 17, 14, 17, 17, 15, + 17, 15, 17, 16, 16, 11, + 17, 16, 12, 12, 17, 17, + 15, 15, 14, 17, 14, 13, + 14, 16, 16, 15, 13, 14, + 16, 14, 13, 14, 15, 17, + 14, 12, 14, 17, 16, 14, + 12, 16, 14, 13, 11, 15, + 17, 16, 13, 12, 15, 17, + 10, 12, 13, 16, 17, 14, + 13, 14, 15, 12, 13, 14, + 15, 17, 14, 14, 16, 15, + 14, 14, 17, 17, 14, 13, + 14, 16, 17, 15, 13, 15, + 15, 12, 11, 14, 17, 16, + 14, 13, 16, 15, 17, 16, + 15, 17, 16, 15, 15, 17, + 15, 16, 17, 16, 17, 17, + 17, 13, 12, 14, 17, 14, + 13, 15, 14, 17, 14, 14, + 16, 15, 16, 14, 15, 14, + 15, 17, 14, 17, 17, 15, + 12, 17, 17, 12, 12, 14, + 13, 14, 13, 14, 16, 15, + 13, 15, 17, 13, 13, 14, + 11, 13, 14, 13, 12, 14, + 15, 13, 17, 15, 14, 15, + 16, 13, 16, 16, 14, 12, + 14, 13, 14, 14, 7, 12, + 13, 12, 12, 9, 14, 14, + 9, 12, 14, 12, 12, 12, + 14, 15, 15, 15, 11, 11, + 13, 13, 12, 12, 13, 15, + 14, 14, 15, 16, 15, 15, + 12, 14, 12, 13, 14, 9, + 14, 13, 9, 8, 15, 15, + 15, 15, 12, 16, 16, 12, + 14, 15, 15, 15, 16, 17, + 17, 17, 17, 16, 15, 15, + 17, 15, 14, 15, 17, 16, + 15, 15, 17, 17, 16, 13, + 15, 15, 15, 15, 12, 15, + 16, 11, 12, 17, 16, 11, + 11, 15, 15, 15, 14, 14, + 15, 17, 14, 17, 15, 16, + 16, 16, 14, 17, 15, 15, + 13, 16, 15, 14, 15, 16, + 17, 15, 16, 14, 15, 16, + 13, 11, 14, 15, 16, 14, + 12, 16, 16, 16, 14, 12, + 16, 17, 13, 14, 13, 16, + 17, 16, 15, 15, 17, 17, + 14, 15, 15, 15, 15, 12, + 14, 17, 16, 15, 15, 17, + 17, 17, 15, 16, 16, 14, + 16, 13, 17, 16, 14, 15, + 16, 17, 15, 16, 16, 17, + 15, 16, 14, 17, 17, 16, + 16, 14, 15, 17, 17, 15, + 14, 14, 15, 13, 16, 17, + 14, 16, 17, 16, 16, 16, + 16, 17, 17, 16, 14, 17, + 16, 15, 16, 11, 17, 17, + 16, 16, 13, 17, 16, 14, + 14, 16, 17, 15, 15, 13, + 16, 15, 15, 15, 16, 15, + 16, 15, 12, 15, 17, 16, + 15, 12, 15, 16, 13, 12, + 15, 16, 17, 14, 11, 17, + 16, 13, 12, 15, 17, 17, + 15, 13, 16, 15, 12, 13, + 15, 17, 17, 14, 15, 17, + 15, 14, 17, 15, 17, 17, + 16, 12, 17, 17, 17, 16, + 14, 15, 17, 11, 13, 15, + 17, 16, 15, 12, 17, 17, + 11, 15, 17, 17, 16, 14, + 17, 15, 17, 16, 14, 17, + 17, 15, 16, 17, 14, 16, + 17, 14, 17, 16, 15, 14, + 17, 17, 12, 17, 17, 17, + 15, 15, 17, 16, 17, 15, + 14, 17, 14, 16, 17, 12, + 14, 17, 16, 17, 13, 17, + 16, 13, 15, 16, 15, 16, + 14, 15, 17, 17, 15, 14, + 14, 16, 17, 14, 11, 15, + 16, 16, 14, 16, 17, 17, + 15, 14, 15, 15, 15, 15, + 13, 15, 17, 14, 11, 17, + 17, 12, 11, 15, 17, 17, + 15, 14, 17, 16, 14, 17, + 17, 15, 15, 16, 15, 15, + 16, 14, 14, 15, 15, 15, + 16, 17, 15, 15, 16, 14, + 15, 16, 13, 11, 14, 16, + 17, 14, 13, 17, 17, 14, + 12, 16, 16, 17, 16, 17, + 17, 17, 16, 17, 17, 17, + 17, 17, 17, 17, 16, 17, + 17, 17, 17, 17, 17, 17, + 16, 17, 17, 16, 17, 17, + 16, 13, 16, 17, 16, 16, + 11, 17, 17, 17, 16, 15, + 17, 17, 14, 16, 16, 17, + 16, 17, 17, 17, 17, 17, + 17, 16, 16, 17, 15, 15, + 17, 17, 16, 15, 16, 17, + 16, 16, 15, 16, 17, 16, + 14, 13, 17, 17, 13, 15, + 17, 17, 14, 12, 17, 17, + 16, 15, 15, 17, 17, 15, + 17, 16, 17, 16, 17, 17, + 17, 17, 16, 13, 16, 17, + 16, 17, 17, 17, 17, 17, + 16, 17, 15, 16, 13, 16, + 16, 16, 15, 16, 17, 17, + 17, 17, 16, 17, 17, 16, + 17, 16, 16, 16, 15, 16, + 15, 17, 17, 17, 16, 15, + 16, 16, 15, 15, 16, 17, + 16, 17, 17, 17, 17, 16, + 17, 17, 16, 17, 16, 17, + 16, 16, 12, 17, 16, 14, + 13, 16, 17, 17, 15, 14, + 17, 17, 14, 16, 16, 17, + 16, 15, 17, 15, 17, 17, + 14, 17, 17, 15, 13, 14, + 17, 15, 16, 12, 16, 16, + 15, 12, 16, 17, 17, 15, + 14, 16, 17, 12, 12, 16, + 16, 16, 17, 14, 16, 16, + 13, 15, 16, 17, 17, 15, + 15, 16, 16, 16, 15, 17, + 17, 14, 14, 15, 17, 17, + 15, 14, 17, 15, 12, 12, + 14, 17, 17, 15, 14, 17, + 17, 17, 17, 15, 16, 17, + 15, 17, 16, 17, 15, 17, + 17, 16, 16, 16, 15, 16, + 17, 17, 15, 15, 16, 17, + 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 15, + 17, 17, 15, 14, 17, 17, + 14, 14, 16, 16, 17, 16, + 16, 17, 16, 15, 17, 17, + 16, 16, 17, 16, 16, 17, + 15, 15, 17, 17, 15, 17, + 17, 15, 15, 16, 16, 16, + 17, 15, 13, 17, 17, 17, + 17, 11, 16, 17, 17, 16, + 14, 17, 17, 14, 16, 17, + 17, 15, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 16, + 14, 16, 17, 16, 16, 17, + 16, 17, 16, 17, 16, 17, + 17, 17, 15, 16, 17, 15, + 9, 17, 17, 17, 16, 12, + 17, 17, 13, 15, 15, 17, + 17, 16, 16, 17, 17, 16, + 16, 17, 17, 17, 17, 16, + 17, 17, 17, 16, 15, 17, + 17, 16, 13, 17, 17, 17, + 15, 13, 17, 17, 13, 12, + 17, 17, 12, 9, 15, 17, + 17, 15, 14, 17, 17, 15, + 16, 17, 17, 16, 16, 17, + 17, 17, 16, 17, 17, 17, + 17, 14, 17, 17, 17, 16, + 14, 17, 17, 13, 11, 16, + 17, 17, 14, 10, 16, 17, + 17, 16, 12, 16, 17, 12, + 14, 16, 17, 17, 15, 16, + 17, 17, 16, 17, 17, 17, + 17, 17, 15, 17, 17, 17, + 17, 14, 16, 17, 15, 12, + 15, 16, 17, 15, 11, 17, + 17, 12, 13, 17, 17, 14, + 10, 16, 17, 17, 16, 13, + 16, 16, 14, 17, 15, 17, + 17, 17, 17, 17, 17, 17, + 15, 17, 16, 16, 15, 17, + 17, 17, 15, 13, 17, 16, + 14, 11, 16, 17, 17, 15, + 11, 16, 17, 17, 16, 12, + 17, 16, 14, 14, 17, 17, + 17, 16, 13, 16, 17, 15, + 17, 17, 17, 17, 17, 17, + 16, 17, 17, 17, 14, 16, + 17, 16, 15, 16, 17, 17, + 15, 12, 17, 16, 14, 11, + 17, 17, 17, 15, 14, 17, + 17, 14, 15, 17, 16, 17, + 17, 17, 16, 16, 17, 17, + 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, + 14, 14, 17, 17, 17, 17, + 14, 17, 17, 12, 14, 17, + 17, 14, 11, 16, 17, 17, + 15, 15, 16, 17, 13, 17, + 16, 17, 17, 15, 17, 17, + 17, 16, 16, 17, 16, 14, + 15, 16, 17, 17, 15, 15, + 17, 17, 13, 11, 15, 17, + 17, 16, 10, 16, 16, 17, + 16, 12, 17, 17, 12, 14, + 15, 17, 17, 15, 16, 17, + 15, 15, 17, 16, 17, 16, + 16, 15, 16, 17, 17, 16, + 15, 17, 17, 14, 13, 14, + 16, 17, 14, 12, 17, 16, + 13, 12, 16, 17, 13, 9, + 15, 17, 17, 16, 15, 17, + 17, 14, 16, 16, 17, 17, + 16, 16, 17, 17, 17, 15, + 17, 16, 16, 15, 16, 17, + 17, 15, 13, 17, 17, 14, + 11, 15, 17, 17, 15, 9, + 16, 17, 17, 15, 12, 17, + 16, 13, 14, 17, 17, 17, + 16, 16, 17, 17, 15, 16, + 17, 17, 16, 17, 17, 17, + 17, 17, 17, 17, 17, 16, + 16, 15, 17, 17, 17, 15, + 12, 17, 16, 12, 12, 16, + 17, 12, 10, 17, 17, 17, + 14, 14, 17, 17, 14, 14, + 16, 17, 17, 15, 16, 17, + 17, 17, 16, 17, 16, 17, + 14, 17, 17, 17, 16, 13, + 17, 17, 14, 9, 15, 17, + 17, 15, 10, 15, 17, 17, + 15, 12, 17, 17, 13, 13, + 16, 17, 17, 15, 14, 17, + 17, 14, 17, 16, 16, 17, + 17, 17, 17, 17, 17, 17, + 15, 17, 16, 15, 14, 15, + 17, 17, 16, 12, 16, 17, + 12, 13, 17, 17, 13, 11, + 17, 17, 17, 16, 12, 16, + 17, 15, 15, 15, 17, 17, + 17, 16, 16, 17, 16, 16, + 17, 17, 16, 16, 15, 17, + 17, 16, 13, 15, 17, 14, + 11, 15, 17, 16, 15, 12, + 17, 17, 16, 17, 12, 17, + 17, 15, 14, 16, 17, 17, + 15, 15, 17, 17, 15, 15, + 17, 17, 17, 16, 17, 17, + 17, 17, 17, 16, 15, 16, + 17, 14, 15, 16, 17, 17, + 15, 17, 17, 13, 12, 17, + 17, 17, 16, 14, 17, 17, + 12, 15, 15, 17, 17, 16, + 15, 17, 17, 14, 16, 17, + 17, 17, 17, 17, 17, 17, + 16, 15, 15, 17, 15, 15, + 14, 15, 17, 17, 15, 13, + 17, 17, 14, 14, 17, 17, + 14, 10, 16, 17, 17, 15, + 14, 17, 17, 13, 15, 16, + 17, 17, 15, 17, 16, 17, + 15, 17, 16, 17, 17, 15, + 16, 17, 17, 14, 14, 17, + 16, 12, 10, 16, 17, 17, + 15, 10, 16, 17, 17, 15, + 12, 17, 17, 13, 13, 15, + 17, 17, 15, 15, 17, 17, + 13, 14, 17, 17, 17, 16, + 17, 17, 17, 17, 17, 15, + 17, 16, 16, 13, 17, 16, + 17, 17, 12, 17, 17, 12, + 13, 17, 17, 12, 11, 15, + 16, 17, 17, 13, 16, 16, + 14, 14, 15, 17, 17, 16, + 16, 17, 17, 16, 17, 17, + 17, 17, 15, 17, 17, 17, + 16, 15, 17, 17, 14, 9, + 17, 17, 17, 15, 15, 17, + 17, 14, 13, 16, 17, 16, + 16, 16, 17, 17, 16, 16, + 16, 17, 17, 16, 16, 16, + 17, 16, 16, 17, 17, 17, + 17, 17, 17, 17, 16, 17, + 16, 17, 17, 12, 16, 17, + 17, 17, 10, 17, 16, 17, + 17, 13, 17, 17, 14, 16, + 17, 17, 15, 17, 17, 17, + 17, 17, 13, 16, 17, 16, + 15, 16, 15, 17, 16, 15, + 17, 17, 17, 17, 15, 16, + 16, 15, 16, 14, 17, 17, + 13, 15, 17, 17, 15, 13, + 17, 15, 17, 17, 15, 17, + 16, 15, 17, 16, 17, 17, + 16, 13, 16, 17, 15, 17, + 17, 17, 17, 17, 16, 17, + 16, 17, 15, 16, 17, 15, + 13, 16, 16, 16, 16, 14, + 17, 17, 17, 16, 15, 17, + 16, 17, 16, 16, 17, 15, + 17, 16, 17, 16, 17, 14, + 15, 17, 17, 17, 16, 16, + 16, 17, 17, 17, 16, 17, + 17, 16, 17, 17, 16, 17, + 16, 17, 17, 14, 13, 17, + 17, 14, 12, 17, 17, 17, + 15, 12, 17, 16, 15, 15, + 15, 17, 17, 17, 14, 16, + 17, 16, 16, 16, 17, 17, + 17, 15, 17, 17, 17, 14, + 16, 15, 14, 13, 14, 17, + 17, 17, 15, 16, 17, 12, + 13, 15, 17, 17, 16, 14, + 16, 16, 12, 14, 16, 16, + 17, 15, 16, 17, 16, 13, + 16, 16, 16, 17, 15, 15, + 16, 17, 14, 14, 17, 17, + 13, 12, 15, 17, 17, 15, + 14, 16, 16, 17, 17, 15, + 17, 17, 17, 16, 16, 17, + 16, 16, 17, 17, 17, 17, + 15, 16, 17, 17, 16, 16, + 16, 17, 15, 17, 17, 17, + 15, 16, 16, 17, 17, 16, + 16, 15, 17, 17, 15, 14, + 17, 17, 14, 14, 16, 17, + 17, 17, 15, 16, 17, 16, + 17, 16, 16, 17, 17, 16, + 15, 16, 15, 16, 17, 17, + 15, 17, 17, 16, 16, 16, + 15, 17, 17, 15, 12, 16, + 17, 17, 16, 11, 17, 17, + 16, 16, 14, 16, 17, 14, + 16, 16, 17, 16, 15, 17, + 17, 17, 16, 15, 15, 17, + 17, 17, 17, 17, 17, 17, + 16, 17, 17, 17, 16, 14, + 17, 16, 17, 16, 13, 17, + 17, 13, 8, 15, 15, 15, + 14, 12, 16, 17, 12, 13, + 15, 15, 16, 16, 16, 17, + 17, 16, 12, 15, 17, 15, + 16, 14, 15, 16, 17, 16, + 17, 17, 17, 17, 15, 16, + 15, 15, 15, 12, 16, 17, + 12, 11, 17, 17, 11, 11, + 14, 15, 15, 13, 13, 16, + 15, 13, 16, 15, 16, 17, + 15, 13, 15, 15, 15, 15, + 15, 16, 14, 17, 17, 14, + 17, 17, 14, 16, 17, 14, + 11, 14, 14, 16, 14, 12, + 16, 15, 16, 15, 13, 15, + 16, 13, 14, 15, 15, 15, + 15, 15, 16, 17, 17, 11, + 14, 17, 16, 14, 15, 16, + 16, 16, 15, 16, 15, 17, + 16, 15, 14, 16, 16, 16, + 13, 17, 17, 13, 15, 17, + 17, 15, 15, 17, 17, 16, + 16, 15, 17, 17, 15, 16, + 17, 17, 15, 17, 13, 14, + 16, 14, 16, 15, 15, 14, + 16, 17, 15, 16, 16, 15, + 17, 17, 16, 15, 16, 16, + 16, 15, 10, 16, 17, 17, + 15, 11, 16, 17, 12, 13, + 14, 17, 15, 15, 12, 17, + 15, 14, 12, 15, 17, 17, + 15, 15, 16, 17, 17, 16, + 14, 15, 15, 15, 14, 15, + 16, 15, 15, 12, 17, 15, + 13, 11, 16, 17, 17, 16, + 13, 16, 17, 11, 12, 15, + 16, 17, 14, 14, 15, 17, + 11, 13, 17, 17, 17, 15, + 17, 16, 15, 16, 14, 16, + 16, 17, 14, 13, 14, 16, + 17, 14, 14, 15, 16, 12, + 15, 17, 17, 16, 14, 17, + 16, 17, 17, 16, 17, 17, + 15, 16, 17, 15, 15, 17, + 14, 15, 15, 13, 15, 15, + 15, 16, 17, 17, 16, 15, + 14, 17, 17, 17, 15, 14, + 16, 17, 17, 17, 11, 14, + 14, 16, 17, 14, 15, 16, + 14, 13, 15, 14, 17, 16, + 15, 16, 17, 17, 11, 15, + 17, 17, 14, 14, 16, 16, + 16, 14, 17, 17, 15, 16, + 14, 15, 17, 16, 13, 13, + 16, 16, 12, 11, 17, 17, + 12, 11, 14, 16, 17, 15, + 14, 16, 17, 13, 15, 16, + 15, 16, 16, 15, 15, 15, + 13, 14, 15, 15, 16, 17, + 17, 15, 15, 16, 15, 16, + 16, 13, 10, 16, 15, 15, + 15, 7, 14, 14, 7, 7, + 11, 12, 12, 11, 12, 14, + 14, 12, 15, 16, 13, 14, + 16, 13, 13, 15, 13, 11, + 12, 13, 11, 15, 15, 13, + 12, 15, 12, 14, 15, 12, + 7, 12, 12, 12, 11, 6, + 12, 12, 13, 12, 9, 14, + 14, 9, 12, 13, 13, 12, + 14, 15, 16, 17, 14, 12, + 13, 13, 15, 13, 11, 12, + 14, 12, 11, 14, 15, 17, + 14, 12, 13, 12, 13, 14, + 9, 13, 15, 9, 12, 17, + 16, 12, 11, 14, 14, 13, + 15, 13, 16, 17, 14, 15, + 17, 14, 14, 15, 13, 15, + 14, 12, 12, 14, 12, 11, + 16, 15, 13, 13, 16, 13, + 15, 15, 14, 12, 13, 14, + 15, 14, 13, 17, 16, 16, + 16, 15, 17, 17, 14, 14, + 16, 14, 15, 17, 15, 17, + 17, 16, 13, 14, 16, 16, + 13, 14, 14, 15, 14, 12, + 17, 16, 17, 17, 16, 15, + 15, 14, 16, 16, 17, 17, + 15, 11, 16, 16, 13, 11, + 14, 16, 17, 14, 10, 17, + 16, 12, 13, 15, 17, 16, + 14, 13, 17, 16, 14, 15, + 17, 14, 13, 14, 14, 16, + 15, 13, 13, 17, 15, 12, + 12, 15, 17, 17, 15, 12, + 16, 16, 11, 11, 14, 17, + 17, 14, 13, 15, 17, 12, + 12, 14, 16, 17, 17, 14, + 15, 16, 14, 15, 15, 16, + 15, 13, 13, 16, 15, 15, + 13, 15, 15, 13, 13, 15, + 16, 17, 15, 14, 15, 16, + 17, 17, 14, 17, 17, 14, + 14, 15, 14, 17, 16, 16, + 17, 17, 17, 12, 15, 16, + 17, 15, 14, 12, 13, 15, + 12, 15, 17, 16, 16, 16, + 17, 14, 14, 15, 15, 17, + 17, 15, 12, 16, 16, 12, + 11, 14, 14, 14, 14, 14, + 14, 15, 13, 15, 16, 13, + 14, 16, 13, 16, 14, 13, + 11, 12, 14, 13, 16, 15, + 13, 14, 15, 13, 15, 15, + 12, 11, 15, 13, 13, 14, + 7, 12, 13, 12, 12, 9, + 15, 15, 9, 12, 14, 12, + 12, 14, 15, 15, 15, 15, + 13, 14, 16, 14, 14, 12, + 11, 13, 14, 12, 14, 16, + 14, 14, 12, 14, 12, 12, + 12, 9, 14, 14, 9, +}; + +static const uint16_t on2avc_cb7_syms[ON2AVC_CB7_CODES] = { + 0x0000, 0x0002, 0x0004, 0x000C, 0x000E, 0x0011, + 0x0013, 0x001D, 0x001F, 0x0020, 0x0022, 0x0024, + 0x002C, 0x002E, 0x0031, 0x0033, 0x003D, 0x003F, + 0x0040, 0x0042, 0x0044, 0x004C, 0x004E, 0x00C0, + 0x00C2, 0x00C4, 0x00CC, 0x00CE, 0x00D1, 0x00D3, + 0x00DD, 0x00DF, 0x00E0, 0x00E2, 0x00E4, 0x00EC, + 0x00EE, 0x00F1, 0x00F3, 0x00FD, 0x00FF, 0x0101, + 0x0103, 0x010D, 0x010F, 0x0110, 0x0112, 0x0114, + 0x011C, 0x011E, 0x0121, 0x0123, 0x012D, 0x012F, + 0x0130, 0x0132, 0x0134, 0x013C, 0x013E, 0x0141, + 0x0143, 0x014D, 0x014F, 0x01C1, 0x01C3, 0x01CD, + 0x01CF, 0x01D0, 0x01D2, 0x01D4, 0x01DC, 0x01DE, + 0x01E1, 0x01E3, 0x01ED, 0x01EF, 0x01F0, 0x01F2, + 0x01F4, 0x01FC, 0x01FE, 0x0200, 0x0202, 0x0204, + 0x020C, 0x020E, 0x0211, 0x0213, 0x021D, 0x021F, + 0x0220, 0x0222, 0x0224, 0x022C, 0x022E, 0x0231, + 0x0233, 0x023D, 0x023F, 0x0240, 0x0242, 0x0244, + 0x024C, 0x024E, 0x02C0, 0x02C2, 0x02C4, 0x02CC, + 0x02CE, 0x02D1, 0x02D3, 0x02DD, 0x02DF, 0x02E0, + 0x02E2, 0x02E4, 0x02EC, 0x02EE, 0x02F1, 0x02F3, + 0x02FD, 0x02FF, 0x0301, 0x0303, 0x030D, 0x030F, + 0x0310, 0x0312, 0x0314, 0x031C, 0x031E, 0x0321, + 0x0323, 0x032D, 0x032F, 0x0330, 0x0332, 0x0334, + 0x033C, 0x033E, 0x0341, 0x0343, 0x034D, 0x034F, + 0x03C1, 0x03C3, 0x03CD, 0x03CF, 0x03D0, 0x03D2, + 0x03D4, 0x03DC, 0x03DE, 0x03E1, 0x03E3, 0x03ED, + 0x03EF, 0x03F0, 0x03F2, 0x03F4, 0x03FC, 0x03FE, + 0x0400, 0x0402, 0x0404, 0x040C, 0x040E, 0x0411, + 0x0413, 0x041D, 0x041F, 0x0420, 0x0422, 0x0424, + 0x042C, 0x042E, 0x0431, 0x0433, 0x043D, 0x043F, + 0x0440, 0x0442, 0x0444, 0x044C, 0x044E, 0x04C0, + 0x04C2, 0x04C4, 0x04CC, 0x04CE, 0x04D1, 0x04D3, + 0x04DD, 0x04DF, 0x04E0, 0x04E2, 0x04E4, 0x04EC, + 0x04EE, 0x04F1, 0x04F3, 0x04FD, 0x04FF, 0x0C00, + 0x0C02, 0x0C04, 0x0C0C, 0x0C0E, 0x0C11, 0x0C13, + 0x0C1D, 0x0C1F, 0x0C20, 0x0C22, 0x0C24, 0x0C2C, + 0x0C2E, 0x0C31, 0x0C33, 0x0C3D, 0x0C3F, 0x0C40, + 0x0C42, 0x0C44, 0x0C4C, 0x0C4E, 0x0CC0, 0x0CC2, + 0x0CC4, 0x0CCC, 0x0CCE, 0x0CD1, 0x0CD3, 0x0CDD, + 0x0CDF, 0x0CE0, 0x0CE2, 0x0CE4, 0x0CEC, 0x0CEE, + 0x0CF1, 0x0CF3, 0x0CFD, 0x0CFF, 0x0D01, 0x0D03, + 0x0D0D, 0x0D0F, 0x0D10, 0x0D12, 0x0D14, 0x0D1C, + 0x0D1E, 0x0D21, 0x0D23, 0x0D2D, 0x0D2F, 0x0D30, + 0x0D32, 0x0D34, 0x0D3C, 0x0D3E, 0x0D41, 0x0D43, + 0x0D4D, 0x0D4F, 0x0DC1, 0x0DC3, 0x0DCD, 0x0DCF, + 0x0DD0, 0x0DD2, 0x0DD4, 0x0DDC, 0x0DDE, 0x0DE1, + 0x0DE3, 0x0DED, 0x0DEF, 0x0DF0, 0x0DF2, 0x0DF4, + 0x0DFC, 0x0DFE, 0x0E00, 0x0E02, 0x0E04, 0x0E0C, + 0x0E0E, 0x0E11, 0x0E13, 0x0E1D, 0x0E1F, 0x0E20, + 0x0E22, 0x0E24, 0x0E2C, 0x0E2E, 0x0E31, 0x0E33, + 0x0E3D, 0x0E3F, 0x0E40, 0x0E42, 0x0E44, 0x0E4C, + 0x0E4E, 0x0EC0, 0x0EC2, 0x0EC4, 0x0ECC, 0x0ECE, + 0x0ED1, 0x0ED3, 0x0EDD, 0x0EDF, 0x0EE0, 0x0EE2, + 0x0EE4, 0x0EEC, 0x0EEE, 0x0EF1, 0x0EF3, 0x0EFD, + 0x0EFF, 0x0F01, 0x0F03, 0x0F0D, 0x0F0F, 0x0F10, + 0x0F12, 0x0F14, 0x0F1C, 0x0F1E, 0x0F21, 0x0F23, + 0x0F2D, 0x0F2F, 0x0F30, 0x0F32, 0x0F34, 0x0F3C, + 0x0F3E, 0x0F41, 0x0F43, 0x0F4D, 0x0F4F, 0x0FC1, + 0x0FC3, 0x0FCD, 0x0FCF, 0x0FD0, 0x0FD2, 0x0FD4, + 0x0FDC, 0x0FDE, 0x0FE1, 0x0FE3, 0x0FED, 0x0FEF, + 0x0FF0, 0x0FF2, 0x0FF4, 0x0FFC, 0x0FFE, 0x1001, + 0x1003, 0x100D, 0x100F, 0x1010, 0x1012, 0x1014, + 0x101C, 0x101E, 0x1021, 0x1023, 0x102D, 0x102F, + 0x1030, 0x1032, 0x1034, 0x103C, 0x103E, 0x1041, + 0x1043, 0x104D, 0x104F, 0x10C1, 0x10C3, 0x10CD, + 0x10CF, 0x10D0, 0x10D2, 0x10D4, 0x10DC, 0x10DE, + 0x10E1, 0x10E3, 0x10ED, 0x10EF, 0x10F0, 0x10F2, + 0x10F4, 0x10FC, 0x10FE, 0x1100, 0x1102, 0x1104, + 0x110C, 0x110E, 0x1111, 0x1113, 0x111D, 0x111F, + 0x1120, 0x1122, 0x1124, 0x112C, 0x112E, 0x1131, + 0x1133, 0x113D, 0x113F, 0x1140, 0x1142, 0x1144, + 0x114C, 0x114E, 0x11C0, 0x11C2, 0x11C4, 0x11CC, + 0x11CE, 0x11D1, 0x11D3, 0x11DD, 0x11DF, 0x11E0, + 0x11E2, 0x11E4, 0x11EC, 0x11EE, 0x11F1, 0x11F3, + 0x11FD, 0x11FF, 0x1201, 0x1203, 0x120D, 0x120F, + 0x1210, 0x1212, 0x1214, 0x121C, 0x121E, 0x1221, + 0x1223, 0x122D, 0x122F, 0x1230, 0x1232, 0x1234, + 0x123C, 0x123E, 0x1241, 0x1243, 0x124D, 0x124F, + 0x12C1, 0x12C3, 0x12CD, 0x12CF, 0x12D0, 0x12D2, + 0x12D4, 0x12DC, 0x12DE, 0x12E1, 0x12E3, 0x12ED, + 0x12EF, 0x12F0, 0x12F2, 0x12F4, 0x12FC, 0x12FE, + 0x1300, 0x1302, 0x1304, 0x130C, 0x130E, 0x1311, + 0x1313, 0x131D, 0x131F, 0x1320, 0x1322, 0x1324, + 0x132C, 0x132E, 0x1331, 0x1333, 0x133D, 0x133F, + 0x1340, 0x1342, 0x1344, 0x134C, 0x134E, 0x13C0, + 0x13C2, 0x13C4, 0x13CC, 0x13CE, 0x13D1, 0x13D3, + 0x13DD, 0x13DF, 0x13E0, 0x13E2, 0x13E4, 0x13EC, + 0x13EE, 0x13F1, 0x13F3, 0x13FD, 0x13FF, 0x1401, + 0x1403, 0x140D, 0x140F, 0x1410, 0x1412, 0x1414, + 0x141C, 0x141E, 0x1421, 0x1423, 0x142D, 0x142F, + 0x1430, 0x1432, 0x1434, 0x143C, 0x143E, 0x1441, + 0x1443, 0x144D, 0x144F, 0x14C1, 0x14C3, 0x14CD, + 0x14CF, 0x14D0, 0x14D2, 0x14D4, 0x14DC, 0x14DE, + 0x14E1, 0x14E3, 0x14ED, 0x14EF, 0x14F0, 0x14F2, + 0x14F4, 0x14FC, 0x14FE, 0x1C01, 0x1C03, 0x1C0D, + 0x1C0F, 0x1C10, 0x1C12, 0x1C14, 0x1C1C, 0x1C1E, + 0x1C21, 0x1C23, 0x1C2D, 0x1C2F, 0x1C30, 0x1C32, + 0x1C34, 0x1C3C, 0x1C3E, 0x1C41, 0x1C43, 0x1C4D, + 0x1C4F, 0x1CC1, 0x1CC3, 0x1CCD, 0x1CCF, 0x1CD0, + 0x1CD2, 0x1CD4, 0x1CDC, 0x1CDE, 0x1CE1, 0x1CE3, + 0x1CED, 0x1CEF, 0x1CF0, 0x1CF2, 0x1CF4, 0x1CFC, + 0x1CFE, 0x1D00, 0x1D02, 0x1D04, 0x1D0C, 0x1D0E, + 0x1D11, 0x1D13, 0x1D1D, 0x1D1F, 0x1D20, 0x1D22, + 0x1D24, 0x1D2C, 0x1D2E, 0x1D31, 0x1D33, 0x1D3D, + 0x1D3F, 0x1D40, 0x1D42, 0x1D44, 0x1D4C, 0x1D4E, + 0x1DC0, 0x1DC2, 0x1DC4, 0x1DCC, 0x1DCE, 0x1DD1, + 0x1DD3, 0x1DDD, 0x1DDF, 0x1DE0, 0x1DE2, 0x1DE4, + 0x1DEC, 0x1DEE, 0x1DF1, 0x1DF3, 0x1DFD, 0x1DFF, + 0x1E01, 0x1E03, 0x1E0D, 0x1E0F, 0x1E10, 0x1E12, + 0x1E14, 0x1E1C, 0x1E1E, 0x1E21, 0x1E23, 0x1E2D, + 0x1E2F, 0x1E30, 0x1E32, 0x1E34, 0x1E3C, 0x1E3E, + 0x1E41, 0x1E43, 0x1E4D, 0x1E4F, 0x1EC1, 0x1EC3, + 0x1ECD, 0x1ECF, 0x1ED0, 0x1ED2, 0x1ED4, 0x1EDC, + 0x1EDE, 0x1EE1, 0x1EE3, 0x1EED, 0x1EEF, 0x1EF0, + 0x1EF2, 0x1EF4, 0x1EFC, 0x1EFE, 0x1F00, 0x1F02, + 0x1F04, 0x1F0C, 0x1F0E, 0x1F11, 0x1F13, 0x1F1D, + 0x1F1F, 0x1F20, 0x1F22, 0x1F24, 0x1F2C, 0x1F2E, + 0x1F31, 0x1F33, 0x1F3D, 0x1F3F, 0x1F40, 0x1F42, + 0x1F44, 0x1F4C, 0x1F4E, 0x1FC0, 0x1FC2, 0x1FC4, + 0x1FCC, 0x1FCE, 0x1FD1, 0x1FD3, 0x1FDD, 0x1FDF, + 0x1FE0, 0x1FE2, 0x1FE4, 0x1FEC, 0x1FEE, 0x1FF1, + 0x1FF3, 0x1FFD, 0x1FFF, 0x2000, 0x2002, 0x2004, + 0x200C, 0x200E, 0x2011, 0x2013, 0x201D, 0x201F, + 0x2020, 0x2022, 0x2024, 0x202C, 0x202E, 0x2031, + 0x2033, 0x203D, 0x203F, 0x2040, 0x2042, 0x2044, + 0x204C, 0x204E, 0x20C0, 0x20C2, 0x20C4, 0x20CC, + 0x20CE, 0x20D1, 0x20D3, 0x20DD, 0x20DF, 0x20E0, + 0x20E2, 0x20E4, 0x20EC, 0x20EE, 0x20F1, 0x20F3, + 0x20FD, 0x20FF, 0x2101, 0x2103, 0x210D, 0x210F, + 0x2110, 0x2112, 0x2114, 0x211C, 0x211E, 0x2121, + 0x2123, 0x212D, 0x212F, 0x2130, 0x2132, 0x2134, + 0x213C, 0x213E, 0x2141, 0x2143, 0x214D, 0x214F, + 0x21C1, 0x21C3, 0x21CD, 0x21CF, 0x21D0, 0x21D2, + 0x21D4, 0x21DC, 0x21DE, 0x21E1, 0x21E3, 0x21ED, + 0x21EF, 0x21F0, 0x21F2, 0x21F4, 0x21FC, 0x21FE, + 0x2200, 0x2202, 0x2204, 0x220C, 0x220E, 0x2211, + 0x2213, 0x221D, 0x221F, 0x2220, 0x2222, 0x2224, + 0x222C, 0x222E, 0x2231, 0x2233, 0x223D, 0x223F, + 0x2240, 0x2242, 0x2244, 0x224C, 0x224E, 0x22C0, + 0x22C2, 0x22C4, 0x22CC, 0x22CE, 0x22D1, 0x22D3, + 0x22DD, 0x22DF, 0x22E0, 0x22E2, 0x22E4, 0x22EC, + 0x22EE, 0x22F1, 0x22F3, 0x22FD, 0x22FF, 0x2301, + 0x2303, 0x230D, 0x230F, 0x2310, 0x2312, 0x2314, + 0x231C, 0x231E, 0x2321, 0x2323, 0x232D, 0x232F, + 0x2330, 0x2332, 0x2334, 0x233C, 0x233E, 0x2341, + 0x2343, 0x234D, 0x234F, 0x23C1, 0x23C3, 0x23CD, + 0x23CF, 0x23D0, 0x23D2, 0x23D4, 0x23DC, 0x23DE, + 0x23E1, 0x23E3, 0x23ED, 0x23EF, 0x23F0, 0x23F2, + 0x23F4, 0x23FC, 0x23FE, 0x2400, 0x2402, 0x2404, + 0x240C, 0x240E, 0x2411, 0x2413, 0x241D, 0x241F, + 0x2420, 0x2422, 0x2424, 0x242C, 0x242E, 0x2431, + 0x2433, 0x243D, 0x243F, 0x2440, 0x2442, 0x2444, + 0x244C, 0x244E, 0x24C0, 0x24C2, 0x24C4, 0x24CC, + 0x24CE, 0x24D1, 0x24D3, 0x24DD, 0x24DF, 0x24E0, + 0x24E2, 0x24E4, 0x24EC, 0x24EE, 0x24F1, 0x24F3, + 0x24FD, 0x24FF, 0x2C00, 0x2C02, 0x2C04, 0x2C0C, + 0x2C0E, 0x2C11, 0x2C13, 0x2C1D, 0x2C1F, 0x2C20, + 0x2C22, 0x2C24, 0x2C2C, 0x2C2E, 0x2C31, 0x2C33, + 0x2C3D, 0x2C3F, 0x2C40, 0x2C42, 0x2C44, 0x2C4C, + 0x2C4E, 0x2CC0, 0x2CC2, 0x2CC4, 0x2CCC, 0x2CCE, + 0x2CD1, 0x2CD3, 0x2CDD, 0x2CDF, 0x2CE0, 0x2CE2, + 0x2CE4, 0x2CEC, 0x2CEE, 0x2CF1, 0x2CF3, 0x2CFD, + 0x2CFF, 0x2D01, 0x2D03, 0x2D0D, 0x2D0F, 0x2D10, + 0x2D12, 0x2D14, 0x2D1C, 0x2D1E, 0x2D21, 0x2D23, + 0x2D2D, 0x2D2F, 0x2D30, 0x2D32, 0x2D34, 0x2D3C, + 0x2D3E, 0x2D41, 0x2D43, 0x2D4D, 0x2D4F, 0x2DC1, + 0x2DC3, 0x2DCD, 0x2DCF, 0x2DD0, 0x2DD2, 0x2DD4, + 0x2DDC, 0x2DDE, 0x2DE1, 0x2DE3, 0x2DED, 0x2DEF, + 0x2DF0, 0x2DF2, 0x2DF4, 0x2DFC, 0x2DFE, 0x2E00, + 0x2E02, 0x2E04, 0x2E0C, 0x2E0E, 0x2E11, 0x2E13, + 0x2E1D, 0x2E1F, 0x2E20, 0x2E22, 0x2E24, 0x2E2C, + 0x2E2E, 0x2E31, 0x2E33, 0x2E3D, 0x2E3F, 0x2E40, + 0x2E42, 0x2E44, 0x2E4C, 0x2E4E, 0x2EC0, 0x2EC2, + 0x2EC4, 0x2ECC, 0x2ECE, 0x2ED1, 0x2ED3, 0x2EDD, + 0x2EDF, 0x2EE0, 0x2EE2, 0x2EE4, 0x2EEC, 0x2EEE, + 0x2EF1, 0x2EF3, 0x2EFD, 0x2EFF, 0x2F01, 0x2F03, + 0x2F0D, 0x2F0F, 0x2F10, 0x2F12, 0x2F14, 0x2F1C, + 0x2F1E, 0x2F21, 0x2F23, 0x2F2D, 0x2F2F, 0x2F30, + 0x2F32, 0x2F34, 0x2F3C, 0x2F3E, 0x2F41, 0x2F43, + 0x2F4D, 0x2F4F, 0x2FC1, 0x2FC3, 0x2FCD, 0x2FCF, + 0x2FD0, 0x2FD2, 0x2FD4, 0x2FDC, 0x2FDE, 0x2FE1, + 0x2FE3, 0x2FED, 0x2FEF, 0x2FF0, 0x2FF2, 0x2FF4, + 0x2FFC, 0x2FFE, 0x3001, 0x3003, 0x300D, 0x300F, + 0x3010, 0x3012, 0x3014, 0x301C, 0x301E, 0x3021, + 0x3023, 0x302D, 0x302F, 0x3030, 0x3032, 0x3034, + 0x303C, 0x303E, 0x3041, 0x3043, 0x304D, 0x304F, + 0x30C1, 0x30C3, 0x30CD, 0x30CF, 0x30D0, 0x30D2, + 0x30D4, 0x30DC, 0x30DE, 0x30E1, 0x30E3, 0x30ED, + 0x30EF, 0x30F0, 0x30F2, 0x30F4, 0x30FC, 0x30FE, + 0x3100, 0x3102, 0x3104, 0x310C, 0x310E, 0x3111, + 0x3113, 0x311D, 0x311F, 0x3120, 0x3122, 0x3124, + 0x312C, 0x312E, 0x3131, 0x3133, 0x313D, 0x313F, + 0x3140, 0x3142, 0x3144, 0x314C, 0x314E, 0x31C0, + 0x31C2, 0x31C4, 0x31CC, 0x31CE, 0x31D1, 0x31D3, + 0x31DD, 0x31DF, 0x31E0, 0x31E2, 0x31E4, 0x31EC, + 0x31EE, 0x31F1, 0x31F3, 0x31FD, 0x31FF, 0x3201, + 0x3203, 0x320D, 0x320F, 0x3210, 0x3212, 0x3214, + 0x321C, 0x321E, 0x3221, 0x3223, 0x322D, 0x322F, + 0x3230, 0x3232, 0x3234, 0x323C, 0x323E, 0x3241, + 0x3243, 0x324D, 0x324F, 0x32C1, 0x32C3, 0x32CD, + 0x32CF, 0x32D0, 0x32D2, 0x32D4, 0x32DC, 0x32DE, + 0x32E1, 0x32E3, 0x32ED, 0x32EF, 0x32F0, 0x32F2, + 0x32F4, 0x32FC, 0x32FE, 0x3300, 0x3302, 0x3304, + 0x330C, 0x330E, 0x3311, 0x3313, 0x331D, 0x331F, + 0x3320, 0x3322, 0x3324, 0x332C, 0x332E, 0x3331, + 0x3333, 0x333D, 0x333F, 0x3340, 0x3342, 0x3344, + 0x334C, 0x334E, 0x33C0, 0x33C2, 0x33C4, 0x33CC, + 0x33CE, 0x33D1, 0x33D3, 0x33DD, 0x33DF, 0x33E0, + 0x33E2, 0x33E4, 0x33EC, 0x33EE, 0x33F1, 0x33F3, + 0x33FD, 0x33FF, 0x3401, 0x3403, 0x340D, 0x340F, + 0x3410, 0x3412, 0x3414, 0x341C, 0x341E, 0x3421, + 0x3423, 0x342D, 0x342F, 0x3430, 0x3432, 0x3434, + 0x343C, 0x343E, 0x3441, 0x3443, 0x344D, 0x344F, + 0x34C1, 0x34C3, 0x34CD, 0x34CF, 0x34D0, 0x34D2, + 0x34D4, 0x34DC, 0x34DE, 0x34E1, 0x34E3, 0x34ED, + 0x34EF, 0x34F0, 0x34F2, 0x34F4, 0x34FC, 0x34FE, + 0x3C01, 0x3C03, 0x3C0D, 0x3C0F, 0x3C10, 0x3C12, + 0x3C14, 0x3C1C, 0x3C1E, 0x3C21, 0x3C23, 0x3C2D, + 0x3C2F, 0x3C30, 0x3C32, 0x3C34, 0x3C3C, 0x3C3E, + 0x3C41, 0x3C43, 0x3C4D, 0x3C4F, 0x3CC1, 0x3CC3, + 0x3CCD, 0x3CCF, 0x3CD0, 0x3CD2, 0x3CD4, 0x3CDC, + 0x3CDE, 0x3CE1, 0x3CE3, 0x3CED, 0x3CEF, 0x3CF0, + 0x3CF2, 0x3CF4, 0x3CFC, 0x3CFE, 0x3D00, 0x3D02, + 0x3D04, 0x3D0C, 0x3D0E, 0x3D11, 0x3D13, 0x3D1D, + 0x3D1F, 0x3D20, 0x3D22, 0x3D24, 0x3D2C, 0x3D2E, + 0x3D31, 0x3D33, 0x3D3D, 0x3D3F, 0x3D40, 0x3D42, + 0x3D44, 0x3D4C, 0x3D4E, 0x3DC0, 0x3DC2, 0x3DC4, + 0x3DCC, 0x3DCE, 0x3DD1, 0x3DD3, 0x3DDD, 0x3DDF, + 0x3DE0, 0x3DE2, 0x3DE4, 0x3DEC, 0x3DEE, 0x3DF1, + 0x3DF3, 0x3DFD, 0x3DFF, 0x3E01, 0x3E03, 0x3E0D, + 0x3E0F, 0x3E10, 0x3E12, 0x3E14, 0x3E1C, 0x3E1E, + 0x3E21, 0x3E23, 0x3E2D, 0x3E2F, 0x3E30, 0x3E32, + 0x3E34, 0x3E3C, 0x3E3E, 0x3E41, 0x3E43, 0x3E4D, + 0x3E4F, 0x3EC1, 0x3EC3, 0x3ECD, 0x3ECF, 0x3ED0, + 0x3ED2, 0x3ED4, 0x3EDC, 0x3EDE, 0x3EE1, 0x3EE3, + 0x3EED, 0x3EEF, 0x3EF0, 0x3EF2, 0x3EF4, 0x3EFC, + 0x3EFE, 0x3F00, 0x3F02, 0x3F04, 0x3F0C, 0x3F0E, + 0x3F11, 0x3F13, 0x3F1D, 0x3F1F, 0x3F20, 0x3F22, + 0x3F24, 0x3F2C, 0x3F2E, 0x3F31, 0x3F33, 0x3F3D, + 0x3F3F, 0x3F40, 0x3F42, 0x3F44, 0x3F4C, 0x3F4E, + 0x3FC0, 0x3FC2, 0x3FC4, 0x3FCC, 0x3FCE, 0x3FD1, + 0x3FD3, 0x3FDD, 0x3FDF, 0x3FE0, 0x3FE2, 0x3FE4, + 0x3FEC, 0x3FEE, 0x3FF1, 0x3FF3, 0x3FFD, 0x3FFF, + 0x4000, 0x4002, 0x4004, 0x400C, 0x400E, 0x4011, + 0x4013, 0x401D, 0x401F, 0x4020, 0x4022, 0x4024, + 0x402C, 0x402E, 0x4031, 0x4033, 0x403D, 0x403F, + 0x4040, 0x4042, 0x4044, 0x404C, 0x404E, 0x40C0, + 0x40C2, 0x40C4, 0x40CC, 0x40CE, 0x40D1, 0x40D3, + 0x40DD, 0x40DF, 0x40E0, 0x40E2, 0x40E4, 0x40EC, + 0x40EE, 0x40F1, 0x40F3, 0x40FD, 0x40FF, 0x4101, + 0x4103, 0x410D, 0x410F, 0x4110, 0x4112, 0x4114, + 0x411C, 0x411E, 0x4121, 0x4123, 0x412D, 0x412F, + 0x4130, 0x4132, 0x4134, 0x413C, 0x413E, 0x4141, + 0x4143, 0x414D, 0x414F, 0x41C1, 0x41C3, 0x41CD, + 0x41CF, 0x41D0, 0x41D2, 0x41D4, 0x41DC, 0x41DE, + 0x41E1, 0x41E3, 0x41ED, 0x41EF, 0x41F0, 0x41F2, + 0x41F4, 0x41FC, 0x41FE, 0x4200, 0x4202, 0x4204, + 0x420C, 0x420E, 0x4211, 0x4213, 0x421D, 0x421F, + 0x4220, 0x4222, 0x4224, 0x422C, 0x422E, 0x4231, + 0x4233, 0x423D, 0x423F, 0x4240, 0x4242, 0x4244, + 0x424C, 0x424E, 0x42C0, 0x42C2, 0x42C4, 0x42CC, + 0x42CE, 0x42D1, 0x42D3, 0x42DD, 0x42DF, 0x42E0, + 0x42E2, 0x42E4, 0x42EC, 0x42EE, 0x42F1, 0x42F3, + 0x42FD, 0x42FF, 0x4301, 0x4303, 0x430D, 0x430F, + 0x4310, 0x4312, 0x4314, 0x431C, 0x431E, 0x4321, + 0x4323, 0x432D, 0x432F, 0x4330, 0x4332, 0x4334, + 0x433C, 0x433E, 0x4341, 0x4343, 0x434D, 0x434F, + 0x43C1, 0x43C3, 0x43CD, 0x43CF, 0x43D0, 0x43D2, + 0x43D4, 0x43DC, 0x43DE, 0x43E1, 0x43E3, 0x43ED, + 0x43EF, 0x43F0, 0x43F2, 0x43F4, 0x43FC, 0x43FE, + 0x4400, 0x4402, 0x4404, 0x440C, 0x440E, 0x4411, + 0x4413, 0x441D, 0x441F, 0x4420, 0x4422, 0x4424, + 0x442C, 0x442E, 0x4431, 0x4433, 0x443D, 0x443F, + 0x4440, 0x4442, 0x4444, 0x444C, 0x444E, 0x44C0, + 0x44C2, 0x44C4, 0x44CC, 0x44CE, 0x44D1, 0x44D3, + 0x44DD, 0x44DF, 0x44E0, 0x44E2, 0x44E4, 0x44EC, + 0x44EE, 0x44F1, 0x44F3, 0x44FD, 0x44FF, 0x4C00, + 0x4C02, 0x4C04, 0x4C0C, 0x4C0E, 0x4C11, 0x4C13, + 0x4C1D, 0x4C1F, 0x4C20, 0x4C22, 0x4C24, 0x4C2C, + 0x4C2E, 0x4C31, 0x4C33, 0x4C3D, 0x4C3F, 0x4C40, + 0x4C42, 0x4C44, 0x4C4C, 0x4C4E, 0x4CC0, 0x4CC2, + 0x4CC4, 0x4CCC, 0x4CCE, 0x4CD1, 0x4CD3, 0x4CDD, + 0x4CDF, 0x4CE0, 0x4CE2, 0x4CE4, 0x4CEC, 0x4CEE, + 0x4CF1, 0x4CF3, 0x4CFD, 0x4CFF, 0x4D01, 0x4D03, + 0x4D0D, 0x4D0F, 0x4D10, 0x4D12, 0x4D14, 0x4D1C, + 0x4D1E, 0x4D21, 0x4D23, 0x4D2D, 0x4D2F, 0x4D30, + 0x4D32, 0x4D34, 0x4D3C, 0x4D3E, 0x4D41, 0x4D43, + 0x4D4D, 0x4D4F, 0x4DC1, 0x4DC3, 0x4DCD, 0x4DCF, + 0x4DD0, 0x4DD2, 0x4DD4, 0x4DDC, 0x4DDE, 0x4DE1, + 0x4DE3, 0x4DED, 0x4DEF, 0x4DF0, 0x4DF2, 0x4DF4, + 0x4DFC, 0x4DFE, 0x4E00, 0x4E02, 0x4E04, 0x4E0C, + 0x4E0E, 0x4E11, 0x4E13, 0x4E1D, 0x4E1F, 0x4E20, + 0x4E22, 0x4E24, 0x4E2C, 0x4E2E, 0x4E31, 0x4E33, + 0x4E3D, 0x4E3F, 0x4E40, 0x4E42, 0x4E44, 0x4E4C, + 0x4E4E, 0x4EC0, 0x4EC2, 0x4EC4, 0x4ECC, 0x4ECE, + 0x4ED1, 0x4ED3, 0x4EDD, 0x4EDF, 0x4EE0, 0x4EE2, + 0x4EE4, 0x4EEC, 0x4EEE, 0x4EF1, 0x4EF3, 0x4EFD, + 0x4EFF, 0x4F01, 0x4F03, 0x4F0D, 0x4F0F, 0x4F10, + 0x4F12, 0x4F14, 0x4F1C, 0x4F1E, 0x4F21, 0x4F23, + 0x4F2D, 0x4F2F, 0x4F30, 0x4F32, 0x4F34, 0x4F3C, + 0x4F3E, 0x4F41, 0x4F43, 0x4F4D, 0x4F4F, 0x4FC1, + 0x4FC3, 0x4FCD, 0x4FCF, 0x4FD0, 0x4FD2, 0x4FD4, + 0x4FDC, 0x4FDE, 0x4FE1, 0x4FE3, 0x4FED, 0x4FEF, + 0x4FF0, 0x4FF2, 0x4FF4, 0x4FFC, 0x4FFE, 0xC000, + 0xC002, 0xC004, 0xC00C, 0xC00E, 0xC011, 0xC013, + 0xC01D, 0xC01F, 0xC020, 0xC022, 0xC024, 0xC02C, + 0xC02E, 0xC031, 0xC033, 0xC03D, 0xC03F, 0xC040, + 0xC042, 0xC044, 0xC04C, 0xC04E, 0xC0C0, 0xC0C2, + 0xC0C4, 0xC0CC, 0xC0CE, 0xC0D1, 0xC0D3, 0xC0DD, + 0xC0DF, 0xC0E0, 0xC0E2, 0xC0E4, 0xC0EC, 0xC0EE, + 0xC0F1, 0xC0F3, 0xC0FD, 0xC0FF, 0xC101, 0xC103, + 0xC10D, 0xC10F, 0xC110, 0xC112, 0xC114, 0xC11C, + 0xC11E, 0xC121, 0xC123, 0xC12D, 0xC12F, 0xC130, + 0xC132, 0xC134, 0xC13C, 0xC13E, 0xC141, 0xC143, + 0xC14D, 0xC14F, 0xC1C1, 0xC1C3, 0xC1CD, 0xC1CF, + 0xC1D0, 0xC1D2, 0xC1D4, 0xC1DC, 0xC1DE, 0xC1E1, + 0xC1E3, 0xC1ED, 0xC1EF, 0xC1F0, 0xC1F2, 0xC1F4, + 0xC1FC, 0xC1FE, 0xC200, 0xC202, 0xC204, 0xC20C, + 0xC20E, 0xC211, 0xC213, 0xC21D, 0xC21F, 0xC220, + 0xC222, 0xC224, 0xC22C, 0xC22E, 0xC231, 0xC233, + 0xC23D, 0xC23F, 0xC240, 0xC242, 0xC244, 0xC24C, + 0xC24E, 0xC2C0, 0xC2C2, 0xC2C4, 0xC2CC, 0xC2CE, + 0xC2D1, 0xC2D3, 0xC2DD, 0xC2DF, 0xC2E0, 0xC2E2, + 0xC2E4, 0xC2EC, 0xC2EE, 0xC2F1, 0xC2F3, 0xC2FD, + 0xC2FF, 0xC301, 0xC303, 0xC30D, 0xC30F, 0xC310, + 0xC312, 0xC314, 0xC31C, 0xC31E, 0xC321, 0xC323, + 0xC32D, 0xC32F, 0xC330, 0xC332, 0xC334, 0xC33C, + 0xC33E, 0xC341, 0xC343, 0xC34D, 0xC34F, 0xC3C1, + 0xC3C3, 0xC3CD, 0xC3CF, 0xC3D0, 0xC3D2, 0xC3D4, + 0xC3DC, 0xC3DE, 0xC3E1, 0xC3E3, 0xC3ED, 0xC3EF, + 0xC3F0, 0xC3F2, 0xC3F4, 0xC3FC, 0xC3FE, 0xC400, + 0xC402, 0xC404, 0xC40C, 0xC40E, 0xC411, 0xC413, + 0xC41D, 0xC41F, 0xC420, 0xC422, 0xC424, 0xC42C, + 0xC42E, 0xC431, 0xC433, 0xC43D, 0xC43F, 0xC440, + 0xC442, 0xC444, 0xC44C, 0xC44E, 0xC4C0, 0xC4C2, + 0xC4C4, 0xC4CC, 0xC4CE, 0xC4D1, 0xC4D3, 0xC4DD, + 0xC4DF, 0xC4E0, 0xC4E2, 0xC4E4, 0xC4EC, 0xC4EE, + 0xC4F1, 0xC4F3, 0xC4FD, 0xC4FF, 0xCC00, 0xCC02, + 0xCC04, 0xCC0C, 0xCC0E, 0xCC11, 0xCC13, 0xCC1D, + 0xCC1F, 0xCC20, 0xCC22, 0xCC24, 0xCC2C, 0xCC2E, + 0xCC31, 0xCC33, 0xCC3D, 0xCC3F, 0xCC40, 0xCC42, + 0xCC44, 0xCC4C, 0xCC4E, 0xCCC0, 0xCCC2, 0xCCC4, + 0xCCCC, 0xCCCE, 0xCCD1, 0xCCD3, 0xCCDD, 0xCCDF, + 0xCCE0, 0xCCE2, 0xCCE4, 0xCCEC, 0xCCEE, 0xCCF1, + 0xCCF3, 0xCCFD, 0xCCFF, 0xCD01, 0xCD03, 0xCD0D, + 0xCD0F, 0xCD10, 0xCD12, 0xCD14, 0xCD1C, 0xCD1E, + 0xCD21, 0xCD23, 0xCD2D, 0xCD2F, 0xCD30, 0xCD32, + 0xCD34, 0xCD3C, 0xCD3E, 0xCD41, 0xCD43, 0xCD4D, + 0xCD4F, 0xCDC1, 0xCDC3, 0xCDCD, 0xCDCF, 0xCDD0, + 0xCDD2, 0xCDD4, 0xCDDC, 0xCDDE, 0xCDE1, 0xCDE3, + 0xCDED, 0xCDEF, 0xCDF0, 0xCDF2, 0xCDF4, 0xCDFC, + 0xCDFE, 0xCE00, 0xCE02, 0xCE04, 0xCE0C, 0xCE0E, + 0xCE11, 0xCE13, 0xCE1D, 0xCE1F, 0xCE20, 0xCE22, + 0xCE24, 0xCE2C, 0xCE2E, 0xCE31, 0xCE33, 0xCE3D, + 0xCE3F, 0xCE40, 0xCE42, 0xCE44, 0xCE4C, 0xCE4E, + 0xCEC0, 0xCEC2, 0xCEC4, 0xCECC, 0xCECE, 0xCED1, + 0xCED3, 0xCEDD, 0xCEDF, 0xCEE0, 0xCEE2, 0xCEE4, + 0xCEEC, 0xCEEE, 0xCEF1, 0xCEF3, 0xCEFD, 0xCEFF, + 0xCF01, 0xCF03, 0xCF0D, 0xCF0F, 0xCF10, 0xCF12, + 0xCF14, 0xCF1C, 0xCF1E, 0xCF21, 0xCF23, 0xCF2D, + 0xCF2F, 0xCF30, 0xCF32, 0xCF34, 0xCF3C, 0xCF3E, + 0xCF41, 0xCF43, 0xCF4D, 0xCF4F, 0xCFC1, 0xCFC3, + 0xCFCD, 0xCFCF, 0xCFD0, 0xCFD2, 0xCFD4, 0xCFDC, + 0xCFDE, 0xCFE1, 0xCFE3, 0xCFED, 0xCFEF, 0xCFF0, + 0xCFF2, 0xCFF4, 0xCFFC, 0xCFFE, 0xD001, 0xD003, + 0xD00D, 0xD00F, 0xD010, 0xD012, 0xD014, 0xD01C, + 0xD01E, 0xD021, 0xD023, 0xD02D, 0xD02F, 0xD030, + 0xD032, 0xD034, 0xD03C, 0xD03E, 0xD041, 0xD043, + 0xD04D, 0xD04F, 0xD0C1, 0xD0C3, 0xD0CD, 0xD0CF, + 0xD0D0, 0xD0D2, 0xD0D4, 0xD0DC, 0xD0DE, 0xD0E1, + 0xD0E3, 0xD0ED, 0xD0EF, 0xD0F0, 0xD0F2, 0xD0F4, + 0xD0FC, 0xD0FE, 0xD100, 0xD102, 0xD104, 0xD10C, + 0xD10E, 0xD111, 0xD113, 0xD11D, 0xD11F, 0xD120, + 0xD122, 0xD124, 0xD12C, 0xD12E, 0xD131, 0xD133, + 0xD13D, 0xD13F, 0xD140, 0xD142, 0xD144, 0xD14C, + 0xD14E, 0xD1C0, 0xD1C2, 0xD1C4, 0xD1CC, 0xD1CE, + 0xD1D1, 0xD1D3, 0xD1DD, 0xD1DF, 0xD1E0, 0xD1E2, + 0xD1E4, 0xD1EC, 0xD1EE, 0xD1F1, 0xD1F3, 0xD1FD, + 0xD1FF, 0xD201, 0xD203, 0xD20D, 0xD20F, 0xD210, + 0xD212, 0xD214, 0xD21C, 0xD21E, 0xD221, 0xD223, + 0xD22D, 0xD22F, 0xD230, 0xD232, 0xD234, 0xD23C, + 0xD23E, 0xD241, 0xD243, 0xD24D, 0xD24F, 0xD2C1, + 0xD2C3, 0xD2CD, 0xD2CF, 0xD2D0, 0xD2D2, 0xD2D4, + 0xD2DC, 0xD2DE, 0xD2E1, 0xD2E3, 0xD2ED, 0xD2EF, + 0xD2F0, 0xD2F2, 0xD2F4, 0xD2FC, 0xD2FE, 0xD300, + 0xD302, 0xD304, 0xD30C, 0xD30E, 0xD311, 0xD313, + 0xD31D, 0xD31F, 0xD320, 0xD322, 0xD324, 0xD32C, + 0xD32E, 0xD331, 0xD333, 0xD33D, 0xD33F, 0xD340, + 0xD342, 0xD344, 0xD34C, 0xD34E, 0xD3C0, 0xD3C2, + 0xD3C4, 0xD3CC, 0xD3CE, 0xD3D1, 0xD3D3, 0xD3DD, + 0xD3DF, 0xD3E0, 0xD3E2, 0xD3E4, 0xD3EC, 0xD3EE, + 0xD3F1, 0xD3F3, 0xD3FD, 0xD3FF, 0xD401, 0xD403, + 0xD40D, 0xD40F, 0xD410, 0xD412, 0xD414, 0xD41C, + 0xD41E, 0xD421, 0xD423, 0xD42D, 0xD42F, 0xD430, + 0xD432, 0xD434, 0xD43C, 0xD43E, 0xD441, 0xD443, + 0xD44D, 0xD44F, 0xD4C1, 0xD4C3, 0xD4CD, 0xD4CF, + 0xD4D0, 0xD4D2, 0xD4D4, 0xD4DC, 0xD4DE, 0xD4E1, + 0xD4E3, 0xD4ED, 0xD4EF, 0xD4F0, 0xD4F2, 0xD4F4, + 0xD4FC, 0xD4FE, 0xDC01, 0xDC03, 0xDC0D, 0xDC0F, + 0xDC10, 0xDC12, 0xDC14, 0xDC1C, 0xDC1E, 0xDC21, + 0xDC23, 0xDC2D, 0xDC2F, 0xDC30, 0xDC32, 0xDC34, + 0xDC3C, 0xDC3E, 0xDC41, 0xDC43, 0xDC4D, 0xDC4F, + 0xDCC1, 0xDCC3, 0xDCCD, 0xDCCF, 0xDCD0, 0xDCD2, + 0xDCD4, 0xDCDC, 0xDCDE, 0xDCE1, 0xDCE3, 0xDCED, + 0xDCEF, 0xDCF0, 0xDCF2, 0xDCF4, 0xDCFC, 0xDCFE, + 0xDD00, 0xDD02, 0xDD04, 0xDD0C, 0xDD0E, 0xDD11, + 0xDD13, 0xDD1D, 0xDD1F, 0xDD20, 0xDD22, 0xDD24, + 0xDD2C, 0xDD2E, 0xDD31, 0xDD33, 0xDD3D, 0xDD3F, + 0xDD40, 0xDD42, 0xDD44, 0xDD4C, 0xDD4E, 0xDDC0, + 0xDDC2, 0xDDC4, 0xDDCC, 0xDDCE, 0xDDD1, 0xDDD3, + 0xDDDD, 0xDDDF, 0xDDE0, 0xDDE2, 0xDDE4, 0xDDEC, + 0xDDEE, 0xDDF1, 0xDDF3, 0xDDFD, 0xDDFF, 0xDE01, + 0xDE03, 0xDE0D, 0xDE0F, 0xDE10, 0xDE12, 0xDE14, + 0xDE1C, 0xDE1E, 0xDE21, 0xDE23, 0xDE2D, 0xDE2F, + 0xDE30, 0xDE32, 0xDE34, 0xDE3C, 0xDE3E, 0xDE41, + 0xDE43, 0xDE4D, 0xDE4F, 0xDEC1, 0xDEC3, 0xDECD, + 0xDECF, 0xDED0, 0xDED2, 0xDED4, 0xDEDC, 0xDEDE, + 0xDEE1, 0xDEE3, 0xDEED, 0xDEEF, 0xDEF0, 0xDEF2, + 0xDEF4, 0xDEFC, 0xDEFE, 0xDF00, 0xDF02, 0xDF04, + 0xDF0C, 0xDF0E, 0xDF11, 0xDF13, 0xDF1D, 0xDF1F, + 0xDF20, 0xDF22, 0xDF24, 0xDF2C, 0xDF2E, 0xDF31, + 0xDF33, 0xDF3D, 0xDF3F, 0xDF40, 0xDF42, 0xDF44, + 0xDF4C, 0xDF4E, 0xDFC0, 0xDFC2, 0xDFC4, 0xDFCC, + 0xDFCE, 0xDFD1, 0xDFD3, 0xDFDD, 0xDFDF, 0xDFE0, + 0xDFE2, 0xDFE4, 0xDFEC, 0xDFEE, 0xDFF1, 0xDFF3, + 0xDFFD, 0xDFFF, 0xE000, 0xE002, 0xE004, 0xE00C, + 0xE00E, 0xE011, 0xE013, 0xE01D, 0xE01F, 0xE020, + 0xE022, 0xE024, 0xE02C, 0xE02E, 0xE031, 0xE033, + 0xE03D, 0xE03F, 0xE040, 0xE042, 0xE044, 0xE04C, + 0xE04E, 0xE0C0, 0xE0C2, 0xE0C4, 0xE0CC, 0xE0CE, + 0xE0D1, 0xE0D3, 0xE0DD, 0xE0DF, 0xE0E0, 0xE0E2, + 0xE0E4, 0xE0EC, 0xE0EE, 0xE0F1, 0xE0F3, 0xE0FD, + 0xE0FF, 0xE101, 0xE103, 0xE10D, 0xE10F, 0xE110, + 0xE112, 0xE114, 0xE11C, 0xE11E, 0xE121, 0xE123, + 0xE12D, 0xE12F, 0xE130, 0xE132, 0xE134, 0xE13C, + 0xE13E, 0xE141, 0xE143, 0xE14D, 0xE14F, 0xE1C1, + 0xE1C3, 0xE1CD, 0xE1CF, 0xE1D0, 0xE1D2, 0xE1D4, + 0xE1DC, 0xE1DE, 0xE1E1, 0xE1E3, 0xE1ED, 0xE1EF, + 0xE1F0, 0xE1F2, 0xE1F4, 0xE1FC, 0xE1FE, 0xE200, + 0xE202, 0xE204, 0xE20C, 0xE20E, 0xE211, 0xE213, + 0xE21D, 0xE21F, 0xE220, 0xE222, 0xE224, 0xE22C, + 0xE22E, 0xE231, 0xE233, 0xE23D, 0xE23F, 0xE240, + 0xE242, 0xE244, 0xE24C, 0xE24E, 0xE2C0, 0xE2C2, + 0xE2C4, 0xE2CC, 0xE2CE, 0xE2D1, 0xE2D3, 0xE2DD, + 0xE2DF, 0xE2E0, 0xE2E2, 0xE2E4, 0xE2EC, 0xE2EE, + 0xE2F1, 0xE2F3, 0xE2FD, 0xE2FF, 0xE301, 0xE303, + 0xE30D, 0xE30F, 0xE310, 0xE312, 0xE314, 0xE31C, + 0xE31E, 0xE321, 0xE323, 0xE32D, 0xE32F, 0xE330, + 0xE332, 0xE334, 0xE33C, 0xE33E, 0xE341, 0xE343, + 0xE34D, 0xE34F, 0xE3C1, 0xE3C3, 0xE3CD, 0xE3CF, + 0xE3D0, 0xE3D2, 0xE3D4, 0xE3DC, 0xE3DE, 0xE3E1, + 0xE3E3, 0xE3ED, 0xE3EF, 0xE3F0, 0xE3F2, 0xE3F4, + 0xE3FC, 0xE3FE, 0xE400, 0xE402, 0xE404, 0xE40C, + 0xE40E, 0xE411, 0xE413, 0xE41D, 0xE41F, 0xE420, + 0xE422, 0xE424, 0xE42C, 0xE42E, 0xE431, 0xE433, + 0xE43D, 0xE43F, 0xE440, 0xE442, 0xE444, 0xE44C, + 0xE44E, 0xE4C0, 0xE4C2, 0xE4C4, 0xE4CC, 0xE4CE, + 0xE4D1, 0xE4D3, 0xE4DD, 0xE4DF, 0xE4E0, 0xE4E2, + 0xE4E4, 0xE4EC, 0xE4EE, 0xE4F1, 0xE4F3, 0xE4FD, + 0xE4FF, 0xEC00, 0xEC02, 0xEC04, 0xEC0C, 0xEC0E, + 0xEC11, 0xEC13, 0xEC1D, 0xEC1F, 0xEC20, 0xEC22, + 0xEC24, 0xEC2C, 0xEC2E, 0xEC31, 0xEC33, 0xEC3D, + 0xEC3F, 0xEC40, 0xEC42, 0xEC44, 0xEC4C, 0xEC4E, + 0xECC0, 0xECC2, 0xECC4, 0xECCC, 0xECCE, 0xECD1, + 0xECD3, 0xECDD, 0xECDF, 0xECE0, 0xECE2, 0xECE4, + 0xECEC, 0xECEE, 0xECF1, 0xECF3, 0xECFD, 0xECFF, + 0xED01, 0xED03, 0xED0D, 0xED0F, 0xED10, 0xED12, + 0xED14, 0xED1C, 0xED1E, 0xED21, 0xED23, 0xED2D, + 0xED2F, 0xED30, 0xED32, 0xED34, 0xED3C, 0xED3E, + 0xED41, 0xED43, 0xED4D, 0xED4F, 0xEDC1, 0xEDC3, + 0xEDCD, 0xEDCF, 0xEDD0, 0xEDD2, 0xEDD4, 0xEDDC, + 0xEDDE, 0xEDE1, 0xEDE3, 0xEDED, 0xEDEF, 0xEDF0, + 0xEDF2, 0xEDF4, 0xEDFC, 0xEDFE, 0xEE00, 0xEE02, + 0xEE04, 0xEE0C, 0xEE0E, 0xEE11, 0xEE13, 0xEE1D, + 0xEE1F, 0xEE20, 0xEE22, 0xEE24, 0xEE2C, 0xEE2E, + 0xEE31, 0xEE33, 0xEE3D, 0xEE3F, 0xEE40, 0xEE42, + 0xEE44, 0xEE4C, 0xEE4E, 0xEEC0, 0xEEC2, 0xEEC4, + 0xEECC, 0xEECE, 0xEED1, 0xEED3, 0xEEDD, 0xEEDF, + 0xEEE0, 0xEEE2, 0xEEE4, 0xEEEC, 0xEEEE, 0xEEF1, + 0xEEF3, 0xEEFD, 0xEEFF, 0xEF01, 0xEF03, 0xEF0D, + 0xEF0F, 0xEF10, 0xEF12, 0xEF14, 0xEF1C, 0xEF1E, + 0xEF21, 0xEF23, 0xEF2D, 0xEF2F, 0xEF30, 0xEF32, + 0xEF34, 0xEF3C, 0xEF3E, 0xEF41, 0xEF43, 0xEF4D, + 0xEF4F, 0xEFC1, 0xEFC3, 0xEFCD, 0xEFCF, 0xEFD0, + 0xEFD2, 0xEFD4, 0xEFDC, 0xEFDE, 0xEFE1, 0xEFE3, + 0xEFED, 0xEFEF, 0xEFF0, 0xEFF2, 0xEFF4, 0xEFFC, + 0xEFFE, 0xF001, 0xF003, 0xF00D, 0xF00F, 0xF010, + 0xF012, 0xF014, 0xF01C, 0xF01E, 0xF021, 0xF023, + 0xF02D, 0xF02F, 0xF030, 0xF032, 0xF034, 0xF03C, + 0xF03E, 0xF041, 0xF043, 0xF04D, 0xF04F, 0xF0C1, + 0xF0C3, 0xF0CD, 0xF0CF, 0xF0D0, 0xF0D2, 0xF0D4, + 0xF0DC, 0xF0DE, 0xF0E1, 0xF0E3, 0xF0ED, 0xF0EF, + 0xF0F0, 0xF0F2, 0xF0F4, 0xF0FC, 0xF0FE, 0xF100, + 0xF102, 0xF104, 0xF10C, 0xF10E, 0xF111, 0xF113, + 0xF11D, 0xF11F, 0xF120, 0xF122, 0xF124, 0xF12C, + 0xF12E, 0xF131, 0xF133, 0xF13D, 0xF13F, 0xF140, + 0xF142, 0xF144, 0xF14C, 0xF14E, 0xF1C0, 0xF1C2, + 0xF1C4, 0xF1CC, 0xF1CE, 0xF1D1, 0xF1D3, 0xF1DD, + 0xF1DF, 0xF1E0, 0xF1E2, 0xF1E4, 0xF1EC, 0xF1EE, + 0xF1F1, 0xF1F3, 0xF1FD, 0xF1FF, 0xF201, 0xF203, + 0xF20D, 0xF20F, 0xF210, 0xF212, 0xF214, 0xF21C, + 0xF21E, 0xF221, 0xF223, 0xF22D, 0xF22F, 0xF230, + 0xF232, 0xF234, 0xF23C, 0xF23E, 0xF241, 0xF243, + 0xF24D, 0xF24F, 0xF2C1, 0xF2C3, 0xF2CD, 0xF2CF, + 0xF2D0, 0xF2D2, 0xF2D4, 0xF2DC, 0xF2DE, 0xF2E1, + 0xF2E3, 0xF2ED, 0xF2EF, 0xF2F0, 0xF2F2, 0xF2F4, + 0xF2FC, 0xF2FE, 0xF300, 0xF302, 0xF304, 0xF30C, + 0xF30E, 0xF311, 0xF313, 0xF31D, 0xF31F, 0xF320, + 0xF322, 0xF324, 0xF32C, 0xF32E, 0xF331, 0xF333, + 0xF33D, 0xF33F, 0xF340, 0xF342, 0xF344, 0xF34C, + 0xF34E, 0xF3C0, 0xF3C2, 0xF3C4, 0xF3CC, 0xF3CE, + 0xF3D1, 0xF3D3, 0xF3DD, 0xF3DF, 0xF3E0, 0xF3E2, + 0xF3E4, 0xF3EC, 0xF3EE, 0xF3F1, 0xF3F3, 0xF3FD, + 0xF3FF, 0xF401, 0xF403, 0xF40D, 0xF40F, 0xF410, + 0xF412, 0xF414, 0xF41C, 0xF41E, 0xF421, 0xF423, + 0xF42D, 0xF42F, 0xF430, 0xF432, 0xF434, 0xF43C, + 0xF43E, 0xF441, 0xF443, 0xF44D, 0xF44F, 0xF4C1, + 0xF4C3, 0xF4CD, 0xF4CF, 0xF4D0, 0xF4D2, 0xF4D4, + 0xF4DC, 0xF4DE, 0xF4E1, 0xF4E3, 0xF4ED, 0xF4EF, + 0xF4F0, 0xF4F2, 0xF4F4, 0xF4FC, 0xF4FE, 0xFC01, + 0xFC03, 0xFC0D, 0xFC0F, 0xFC10, 0xFC12, 0xFC14, + 0xFC1C, 0xFC1E, 0xFC21, 0xFC23, 0xFC2D, 0xFC2F, + 0xFC30, 0xFC32, 0xFC34, 0xFC3C, 0xFC3E, 0xFC41, + 0xFC43, 0xFC4D, 0xFC4F, 0xFCC1, 0xFCC3, 0xFCCD, + 0xFCCF, 0xFCD0, 0xFCD2, 0xFCD4, 0xFCDC, 0xFCDE, + 0xFCE1, 0xFCE3, 0xFCED, 0xFCEF, 0xFCF0, 0xFCF2, + 0xFCF4, 0xFCFC, 0xFCFE, 0xFD00, 0xFD02, 0xFD04, + 0xFD0C, 0xFD0E, 0xFD11, 0xFD13, 0xFD1D, 0xFD1F, + 0xFD20, 0xFD22, 0xFD24, 0xFD2C, 0xFD2E, 0xFD31, + 0xFD33, 0xFD3D, 0xFD3F, 0xFD40, 0xFD42, 0xFD44, + 0xFD4C, 0xFD4E, 0xFDC0, 0xFDC2, 0xFDC4, 0xFDCC, + 0xFDCE, 0xFDD1, 0xFDD3, 0xFDDD, 0xFDDF, 0xFDE0, + 0xFDE2, 0xFDE4, 0xFDEC, 0xFDEE, 0xFDF1, 0xFDF3, + 0xFDFD, 0xFDFF, 0xFE01, 0xFE03, 0xFE0D, 0xFE0F, + 0xFE10, 0xFE12, 0xFE14, 0xFE1C, 0xFE1E, 0xFE21, + 0xFE23, 0xFE2D, 0xFE2F, 0xFE30, 0xFE32, 0xFE34, + 0xFE3C, 0xFE3E, 0xFE41, 0xFE43, 0xFE4D, 0xFE4F, + 0xFEC1, 0xFEC3, 0xFECD, 0xFECF, 0xFED0, 0xFED2, + 0xFED4, 0xFEDC, 0xFEDE, 0xFEE1, 0xFEE3, 0xFEED, + 0xFEEF, 0xFEF0, 0xFEF2, 0xFEF4, 0xFEFC, 0xFEFE, + 0xFF00, 0xFF02, 0xFF04, 0xFF0C, 0xFF0E, 0xFF11, + 0xFF13, 0xFF1D, 0xFF1F, 0xFF20, 0xFF22, 0xFF24, + 0xFF2C, 0xFF2E, 0xFF31, 0xFF33, 0xFF3D, 0xFF3F, + 0xFF40, 0xFF42, 0xFF44, 0xFF4C, 0xFF4E, 0xFFC0, + 0xFFC2, 0xFFC4, 0xFFCC, 0xFFCE, 0xFFD1, 0xFFD3, + 0xFFDD, 0xFFDF, 0xFFE0, 0xFFE2, 0xFFE4, 0xFFEC, + 0xFFEE, 0xFFF1, 0xFFF3, 0xFFFD, 0xFFFF, +}; + +#define ON2AVC_CB8_CODES 3281 +static const uint32_t on2avc_cb8_codes[ON2AVC_CB8_CODES] = { + 0x028C, 0x05E6, 0xFAD9, 0x7DEF, 0x06CE, 0x004C, + 0x0178, 0x0A1D, 0x00AE, 0x046E, 0x03D5, 0x3F58, + 0x0EAA, 0x0233, 0x1A6A, 0x271F, 0x05CE, 0x0179, + 0x02FB, 0x0029, 0x237D, 0x7DF0, 0x03BA, 0xFAD6, + 0xFAD7, 0x7DEE, 0xFAD5, 0x0081, 0x033C, 0x1A69, + 0xFAD8, 0x05A1, 0x01F1, 0x063D, 0x237C, 0x003E, + 0x0323, 0x010C, 0x05A3, 0x05A2, 0x0051, 0x019D, + 0xFADB, 0x0EAB, 0x00AA, 0x003E, 0x01A6, 0x7DF2, + 0x0058, 0x01F1, 0x029B, 0x03C0, 0x122D, 0x0075, + 0x3F5A, 0x0B98, 0x0005, 0x058B, 0x0D68, 0x013F, + 0x00D0, 0x05CF, 0x01C0, 0x03BB, 0x046F, 0xFADA, + 0x01A0, 0x0972, 0x122C, 0x3F59, 0x0766, 0x05A4, + 0x00ED, 0x05A5, 0x0D67, 0x03D0, 0x0046, 0x01FF, + 0x7DF1, 0x00D6, 0x017C, 0x0034, 0x08B5, 0x0234, + 0x237E, 0x0033, 0x0083, 0x0B99, 0x0EAC, 0x0202, + 0x0714, 0x0715, 0x01C3, 0x05A6, 0x0324, 0x13EC, + 0x02F8, 0x7DF3, 0x13EB, 0x0140, 0x0470, 0x04F8, + 0x0007, 0x0377, 0x0208, 0x04A3, 0x13EA, 0x0006, + 0x0188, 0x033D, 0x122E, 0x1A6B, 0x0A1E, 0x0126, + 0x03C1, 0x05E7, 0x05D0, 0x04F7, 0x03DB, 0x033E, + 0x122F, 0x0082, 0x1A6F, 0x2380, 0x05D2, 0x0009, + 0x05A9, 0x1A70, 0x1233, 0x05A7, 0x05A8, 0x0975, + 0x2381, 0x1234, 0x0788, 0x2720, 0x1235, 0x05D3, + 0xFADD, 0x3F5B, 0x0789, 0x0D69, 0xFADE, 0xFADF, + 0x01C4, 0x0EAD, 0x0EA1, 0x1230, 0x0008, 0x13ED, + 0x1A6C, 0xFADC, 0x1231, 0x0973, 0x1232, 0x1A6D, + 0x13EE, 0x1A6E, 0x0974, 0x237F, 0x05D1, 0x033F, + 0x0267, 0x078A, 0xFAE3, 0xFAE2, 0x0B9A, 0x00FC, + 0x0EAE, 0x05D6, 0x0325, 0x0326, 0x0B9B, 0x3F5F, + 0x3F5E, 0x0471, 0x02F9, 0xFAE4, 0x1A72, 0x03C2, + 0x05D7, 0x2721, 0x3F60, 0xFAE5, 0x2382, 0xFAE0, + 0x7DF5, 0xFAE1, 0x7DF4, 0x000A, 0x0235, 0x3F5C, + 0x1A71, 0x0716, 0x036C, 0x0767, 0x05D4, 0x3F5D, + 0x0717, 0x01BF, 0x000B, 0x05D5, 0x0243, 0xFAD0, + 0x04F6, 0x7DE5, 0xFACF, 0x0E9E, 0x0074, 0x271A, + 0x1A61, 0x015B, 0x0046, 0x06CA, 0x237A, 0x7DE6, + 0x0070, 0x1A62, 0x1227, 0x7DE7, 0x0032, 0xFAD1, + 0x05CA, 0x7DE8, 0x237B, 0x13E6, 0x05C8, 0x1226, + 0x2377, 0x2719, 0x3F54, 0x3F55, 0x13E5, 0x2378, + 0x03BF, 0x05C9, 0x01C0, 0x7DE4, 0x7DE3, 0x0A19, + 0x0045, 0x1A60, 0x2379, 0x021B, 0x271C, 0x13E7, + 0x271B, 0x1A67, 0x059D, 0x0EA6, 0x0EA7, 0x0174, + 0x0EA5, 0x0A1A, 0x1FFD, 0x033A, 0x0E9F, 0x3F57, + 0x122B, 0xFAD2, 0x0D64, 0x05CC, 0x06CB, 0x1FFE, + 0x059E, 0x02F7, 0x1228, 0x7DE9, 0x059B, 0x096C, + 0x1A63, 0x1A64, 0x1A65, 0x1229, 0x0EA3, 0x059C, + 0x096D, 0x05CB, 0x003C, 0x1A66, 0x0D63, 0x3F56, + 0x122A, 0x0EA4, 0x0712, 0x0232, 0x13E8, 0x061E, + 0x08B4, 0x016E, 0x0176, 0x033B, 0x0028, 0x05E5, + 0x061F, 0x0000, 0x0376, 0x0071, 0x096F, 0x7DEB, + 0x0001, 0x05CD, 0xFAD3, 0x0186, 0x0EA9, 0x13E9, + 0x06CD, 0x7DEA, 0x0340, 0x271D, 0x0175, 0x01C1, + 0x0D65, 0x1FFF, 0x0B97, 0x0EA8, 0x06CC, 0x0375, + 0x05E4, 0x08B3, 0x05E3, 0x0341, 0x0EA0, 0x096E, + 0x03CF, 0x0056, 0x0970, 0x1A68, 0x029A, 0x010A, + 0x00A8, 0x01CA, 0x7DED, 0x00A5, 0x001E, 0x05A0, + 0x0D66, 0x0047, 0x0971, 0x0A1C, 0x02CE, 0xFAD4, + 0x0004, 0x010F, 0x271E, 0x0415, 0x0212, 0x019F, + 0x7DEC, 0x01C2, 0x0187, 0x059F, 0x0A1B, 0x0527, + 0x0002, 0x003D, 0x0041, 0x0177, 0x0713, 0x010E, + 0x0102, 0x02CF, 0x00CA, 0x0003, 0x01BF, 0x0120, + 0x05DE, 0x0043, 0x01D0, 0x018C, 0x00AB, 0x029F, + 0x03DF, 0x03C5, 0x0247, 0x08BB, 0x0013, 0x03D2, + 0x0015, 0x0EB0, 0x02FA, 0x05E8, 0x0014, 0x0EB1, + 0x0476, 0x1A78, 0x01F4, 0x06D1, 0x017C, 0x0042, + 0x063F, 0x0011, 0x0012, 0x01C7, 0x04FB, 0x1A77, + 0x01AA, 0x04FC, 0x0A21, 0x021D, 0x01EE, 0x02BC, + 0x01C2, 0x021E, 0x00AA, 0x00D6, 0x021F, 0x016F, + 0x0077, 0x01AB, 0x00AC, 0x0073, 0x078D, 0x00AF, + 0x002E, 0x0220, 0x0086, 0x0103, 0x0086, 0x0127, + 0x0BA0, 0x05DF, 0x0EA5, 0x03D3, 0x05E0, 0x017D, + 0xFAE7, 0x015A, 0x03C6, 0x0768, 0xFAE6, 0x3F65, + 0x01F3, 0x0B9F, 0x0016, 0x0EA4, 0x078C, 0x02BD, + 0x004D, 0x0116, 0x037A, 0x0076, 0x0056, 0x058E, + 0x06D2, 0x0014, 0x009F, 0x0A23, 0x0346, 0x014E, + 0x02BF, 0x00A7, 0x0528, 0x0378, 0x0106, 0x01C3, + 0x017E, 0x0044, 0x03C7, 0x097F, 0x04A5, 0x020B, + 0x05E9, 0x0A24, 0x03D9, 0x0661, 0x0660, 0x014F, + 0x02BE, 0x023B, 0x04FD, 0x0313, 0x0017, 0x08BC, + 0x0769, 0x0622, 0x0D6C, 0x03D7, 0x01C8, 0x0A22, + 0x01AB, 0x0203, 0x076A, 0x03D8, 0x02D1, 0x00A6, + 0x05E3, 0x1A79, 0x1A7A, 0x0981, 0x05B1, 0x04FF, + 0x0982, 0x0348, 0x0128, 0x08BD, 0x0D6D, 0x13F4, + 0x05B2, 0x0624, 0x05B3, 0x0EB2, 0x2729, 0x1237, + 0x05B4, 0x0129, 0x0349, 0x2386, 0x0019, 0x04FE, + 0x05B0, 0xFAE8, 0x3F66, 0x0623, 0x05E1, 0x05E2, + 0x3F67, 0x0980, 0x0347, 0x0BA1, 0x0046, 0x0045, + 0x0EA6, 0x01C9, 0x0018, 0x13F3, 0x078E, 0x0152, + 0x0983, 0x1238, 0x272B, 0x01F2, 0x028F, 0x05E5, + 0x3F69, 0x0418, 0x02FC, 0x017F, 0x0EB3, 0x00EF, + 0x0790, 0x0791, 0x1239, 0x05E6, 0x05E7, 0x1A7C, + 0x034A, 0x001A, 0x0984, 0x05B5, 0x272A, 0x1A7B, + 0x0EA7, 0x0529, 0x02FB, 0x2387, 0x3F68, 0x078F, + 0x006D, 0x0D6E, 0x05B6, 0x039F, 0x014E, 0x058F, + 0x13F5, 0x05E4, 0x020C, 0x0342, 0x1A73, 0x7DF7, + 0x2724, 0x0082, 0x0209, 0x1A74, 0x05DB, 0x03D6, + 0x001F, 0x0B9C, 0x04F9, 0x0096, 0x03C3, 0x0620, + 0x7DF9, 0x7DF8, 0x0EA2, 0x000C, 0x2725, 0x3F61, + 0x0977, 0x0976, 0x2723, 0x05D8, 0x2722, 0x058C, + 0x08B6, 0x05D9, 0x2383, 0x0236, 0x036D, 0x0A1F, + 0x05AA, 0x019C, 0x01C0, 0x0327, 0x05DA, 0x7DF6, + 0x02CF, 0x05DD, 0x0341, 0x05AE, 0x0EAF, 0x2384, + 0x0342, 0x13F0, 0x000D, 0x08B7, 0x000E, 0x003F, + 0x097B, 0x0343, 0x0D6A, 0x1A75, 0x000F, 0x3F63, + 0x05AF, 0x06CF, 0x06D0, 0x2385, 0x13F1, 0x058D, + 0x0237, 0x05AB, 0x7DFA, 0x0EA3, 0x03C4, 0x13EF, + 0x05DC, 0x2726, 0x1236, 0x017A, 0x0978, 0x05AD, + 0x05AC, 0x0340, 0x0238, 0x097A, 0x3F62, 0x0979, + 0x03DE, 0x0010, 0x0345, 0x002A, 0x03D1, 0x01A7, + 0x01F2, 0x009E, 0x020A, 0x0189, 0x0D6B, 0x03C6, + 0x00EE, 0x0A20, 0x017B, 0x04FA, 0x0472, 0x0040, + 0x00CB, 0x08B9, 0x02D0, 0x029E, 0x0020, 0x0344, + 0x0239, 0x02D0, 0x0B9D, 0x023A, 0x0B9E, 0x028D, + 0x03C5, 0x03BE, 0x08B8, 0x078B, 0x0337, 0x0246, + 0x004C, 0x0416, 0x0141, 0x04A4, 0x00E2, 0x0213, + 0x028E, 0x01A7, 0x021C, 0x00D4, 0x01C6, 0x0072, + 0x0067, 0x002B, 0x0473, 0x036F, 0x01E0, 0x036E, + 0x0041, 0x3F64, 0x097E, 0x0621, 0x02BB, 0x00D7, + 0x2728, 0x2727, 0x01C1, 0x0129, 0x0417, 0x13F2, + 0x097C, 0x0142, 0x097D, 0x1A76, 0x08BA, 0x063E, + 0x0100, 0x01AA, 0x018A, 0x00EA, 0x014D, 0x001E, + 0x01C5, 0x03C7, 0x0053, 0x05EC, 0x012D, 0x004C, + 0x0D71, 0x01D0, 0x0023, 0x0D72, 0x0185, 0x02D2, + 0x0719, 0x012F, 0x0502, 0x012E, 0x0A28, 0x098E, + 0x238B, 0x272D, 0x05EE, 0x05BE, 0x0130, 0xFAEE, + 0x272E, 0x0BA2, 0x05EB, 0x01CF, 0xFAED, 0x238A, + 0x01CE, 0x098C, 0x7DFD, 0x05BD, 0x004A, 0x0036, + 0x0037, 0x0628, 0x02FD, 0x048A, 0x017E, 0x004B, + 0x098D, 0x0153, 0x0216, 0x0D73, 0x1A82, 0x0042, + 0x017F, 0x026C, 0x020D, 0x0794, 0x0143, 0x007E, + 0x062A, 0x0798, 0x004F, 0x0EBA, 0x0BA4, 0x023E, + 0x05BF, 0x0EB9, 0x0592, 0x03CC, 0x004E, 0x018E, + 0x032C, 0x0629, 0x0BA3, 0x01F7, 0x0EB8, 0x004D, + 0x0990, 0x0350, 0x098F, 0x0343, 0x0023, 0x052B, + 0x004E, 0x0178, 0x04A6, 0x0291, 0x05ED, 0x00DC, + 0x032D, 0x0504, 0x0991, 0x0A29, 0x0593, 0x01F3, + 0x0A2A, 0x0505, 0x015B, 0x0666, 0x0087, 0x03DA, + 0x0BA5, 0x076D, 0x05C1, 0x03CD, 0x0024, 0x0992, + 0x04A7, 0x0131, 0x05C2, 0x272F, 0x01D1, 0x076B, + 0x076C, 0x1242, 0x05EF, 0x062B, 0x0EAE, 0x13FD, + 0x05C0, 0x0EBB, 0x023F, 0x0D74, 0x0503, 0x02FE, + 0x041A, 0x037B, 0x08BE, 0x0240, 0x0316, 0x0EBD, + 0x3F70, 0x0EBC, 0x0A2B, 0x0BA7, 0x0053, 0x05C5, + 0x13FE, 0x0506, 0x03CE, 0x0026, 0x0994, 0x0038, + 0x0027, 0x0132, 0x020E, 0x2731, 0x0EBE, 0x0796, + 0x018F, 0x05C6, 0x02FF, 0x0795, 0x1A83, 0x3F6E, + 0x0BA6, 0x0025, 0x1243, 0x3F6F, 0x004F, 0x2730, + 0x062C, 0x0993, 0x05C3, 0x05C4, 0x0051, 0x0052, + 0x0351, 0x062D, 0x0050, 0x01F6, 0x08BF, 0x3F71, + 0x238E, 0x05C7, 0x01F7, 0x05C8, 0x062E, 0x012A, + 0x032F, 0x0077, 0x1A86, 0x0EBF, 0x03DB, 0x04AA, + 0x0BA8, 0x13FF, 0x062F, 0xFAF2, 0x071A, 0x0054, + 0xFAF1, 0x2732, 0xFAF0, 0x238C, 0x238D, 0xFAEF, + 0x1A84, 0x0392, 0x1244, 0x0995, 0x0799, 0x007F, + 0x032E, 0x7DFE, 0x1A85, 0x05EE, 0x018A, 0x0996, + 0x0028, 0x0152, 0x025A, 0x0A25, 0x7DFC, 0x3F6B, + 0x023C, 0x018B, 0x05B7, 0x0180, 0x00FD, 0x01BA, + 0x05EA, 0x123D, 0x05E8, 0x002F, 0x0625, 0x05B9, + 0x05B8, 0x0477, 0x13F7, 0x0D6F, 0x3F6C, 0xFAEA, + 0x01CB, 0xFAE9, 0x0985, 0x2388, 0x7DFB, 0x034B, + 0x01CA, 0x0047, 0x123A, 0x3F6A, 0x017D, 0x0662, + 0x123C, 0x123B, 0x0379, 0x024A, 0x13F6, 0x1A7D, + 0x016A, 0x0EAA, 0x123F, 0xFAEC, 0x0EA9, 0x13FB, + 0x0182, 0x0792, 0x05BA, 0x0181, 0x0D70, 0x001F, + 0x001E, 0x05BB, 0x3F6D, 0x0020, 0x2389, 0x1240, + 0x0183, 0x0501, 0x1A7F, 0x06D6, 0x0663, 0x06D3, + 0x13F8, 0x034C, 0x0EB4, 0x123E, 0x1A7E, 0x13F9, + 0x001B, 0x05E9, 0x0EA8, 0x001C, 0xFAEB, 0x05EA, + 0x034D, 0x0500, 0x13FA, 0x001D, 0x0048, 0x0794, + 0x0075, 0x0795, 0x0793, 0x0074, 0x008A, 0x03C9, + 0x05EB, 0x0087, 0x0076, 0x012B, 0x012C, 0x037A, + 0x0718, 0x0022, 0x272C, 0x0988, 0x0EB5, 0x0328, + 0x03CA, 0x05EC, 0x0EAB, 0x06D7, 0x0021, 0x0664, + 0x1A80, 0x0986, 0x0419, 0x03C8, 0x034E, 0x0987, + 0x0626, 0x02FC, 0x00AE, 0x01CC, 0x023D, 0x012A, + 0x0021, 0x0A26, 0x05BC, 0x01F6, 0x0221, 0x0049, + 0x0EB6, 0x0042, 0x02D2, 0x00F2, 0x00AF, 0x0290, + 0x0043, 0x052A, 0x13FC, 0x0A27, 0x032A, 0x1241, + 0x0EB7, 0x0EAD, 0x034F, 0x0EAC, 0x0022, 0x05ED, + 0x0797, 0x032B, 0x0035, 0x0989, 0x0184, 0x037B, + 0x098A, 0x1A81, 0x098B, 0x0796, 0x01CD, 0x025B, + 0x03CB, 0x0627, 0x02DA, 0x010C, 0x02D1, 0x06EA, + 0x0665, 0x0329, 0x0D78, 0x7E05, 0x7E04, 0x140A, + 0x0EB3, 0x0ECF, 0x3F7C, 0x1256, 0x05FB, 0x05CF, + 0xFAFF, 0x3F7D, 0x0ED0, 0x7E06, 0x3F7E, 0x3F7F, + 0xFB00, 0x239B, 0x0ED2, 0x1257, 0x7E07, 0x0ED1, + 0x002D, 0x1255, 0x273A, 0x09A4, 0x239A, 0x0ECD, + 0x273B, 0x1A8C, 0x002E, 0x09A5, 0xFAFE, 0x273C, + 0x0BAF, 0x0BB0, 0x05CE, 0x09A6, 0x00D1, 0x0ECE, + 0x09A8, 0x0030, 0x1A8E, 0x0ED3, 0x09A7, 0x0667, + 0x1258, 0x2740, 0x0D79, 0x3F80, 0x0189, 0x09A9, + 0x0EB5, 0x0359, 0x0ED4, 0x125A, 0x239D, 0x1259, + 0x05D1, 0x0D7A, 0x7E0A, 0x7E09, 0x09AA, 0x273D, + 0x0EB4, 0x273E, 0x002F, 0x0354, 0x05FC, 0x239C, + 0x1A8D, 0x0355, 0x0357, 0x05D0, 0x0358, 0x0356, + 0x01D2, 0x0508, 0x7E08, 0x273F, 0x0302, 0x0ED7, + 0x239E, 0x3F84, 0x08C4, 0x01D3, 0x0BB1, 0x0509, + 0x239F, 0x0303, 0x0133, 0x035C, 0x125B, 0x03D1, + 0x0ED8, 0x035D, 0x035E, 0x2743, 0x2744, 0x09AD, + 0x018A, 0x0031, 0x09AC, 0x3F82, 0x2741, 0x3F81, + 0x035A, 0x3F83, 0x05FD, 0x09AB, 0x0ED5, 0x0ED6, + 0x0633, 0x2742, 0x0055, 0x08C3, 0x0636, 0x035B, + 0x05FE, 0x0D7B, 0x0039, 0xFB05, 0x7E0B, 0x7E0C, + 0x140D, 0x018B, 0x09AF, 0x2746, 0x0032, 0x0056, + 0x09B0, 0x03D2, 0x0A30, 0x2747, 0x0057, 0x0EDA, + 0x050A, 0x125E, 0x0033, 0x2748, 0x0D7C, 0x03D3, + 0x3F85, 0x0034, 0xFB01, 0x140B, 0xFB02, 0x05FF, + 0x125C, 0xFB03, 0x125D, 0x1A8F, 0x0600, 0x05D2, + 0x0602, 0x2745, 0x0601, 0x0ED9, 0x1A90, 0xFB04, + 0x140C, 0x09AE, 0x033A, 0x7E0F, 0x23A2, 0x0A31, + 0x0EB6, 0x0058, 0x3F8A, 0x23A3, 0x01D6, 0x04AB, + 0x0059, 0x0EDB, 0x02D3, 0x018C, 0x04C6, 0x1260, + 0x3F8B, 0x125F, 0x1261, 0x071E, 0x7E10, 0x2749, + 0x140E, 0x3F87, 0x3F86, 0x0035, 0x3F88, 0x3F89, + 0x7E0D, 0x23A0, 0x1A91, 0x0797, 0x0603, 0x1A92, + 0x050B, 0x066A, 0x0306, 0x7E0E, 0x23A1, 0x079B, + 0x0BAA, 0x3F73, 0x7E01, 0x0292, 0x0216, 0x0998, + 0x1247, 0x2390, 0x0301, 0x0999, 0x1400, 0x1A87, + 0x041E, 0x1401, 0x0EC1, 0x2391, 0x3F74, 0x0A2C, + 0x1248, 0x3F75, 0x05C9, 0x0EC2, 0x2733, 0x238F, + 0xFAF3, 0xFAF4, 0x0EC0, 0x0997, 0x3F72, 0xFAF5, + 0x1245, 0x08C0, 0x0BA9, 0x1246, 0x020F, 0x041B, + 0x0186, 0x7E00, 0x7DFF, 0x0300, 0xFAFA, 0x2734, + 0x05F2, 0x124D, 0x2395, 0x099A, 0x2735, 0x3F77, + 0x0EC4, 0x0EC5, 0x1403, 0x0EC6, 0x1402, 0x1A89, + 0x3F78, 0x05F5, 0x05F3, 0x05F4, 0x2736, 0x1404, + 0x7E02, 0x124E, 0x0D75, 0x0029, 0x2392, 0xFAF7, + 0xFAF6, 0x0EC3, 0x1249, 0x2394, 0x2393, 0x05F0, + 0xFAF8, 0x124B, 0x124C, 0x124A, 0x3F76, 0x05CA, + 0x05F1, 0xFAF9, 0x1A88, 0x0187, 0x05F7, 0x124F, + 0x0631, 0x0D76, 0x0EAF, 0x2737, 0x0BAC, 0x099D, + 0x0A2D, 0x1250, 0x1407, 0x0BAD, 0x3F7A, 0x2396, + 0x2397, 0x0353, 0x1A8B, 0x08C2, 0x05CD, 0x099E, + 0x05CC, 0x0352, 0x002A, 0x05CB, 0x03CF, 0x1A8A, + 0x1405, 0x1406, 0x099B, 0x0EC7, 0x0630, 0x002B, + 0x3F79, 0x08C1, 0x0BAB, 0x0507, 0x05F6, 0x0EC8, + 0x099C, 0x0EB0, 0x0A2F, 0x0EB1, 0x2739, 0x09A1, + 0x03D0, 0x1252, 0x7E03, 0x0241, 0x0188, 0x0EB2, + 0x0BAE, 0x05FA, 0x09A2, 0x1254, 0x2398, 0xFAFB, + 0x1253, 0x2399, 0x0ECC, 0xFAFD, 0xFAFC, 0x09A3, + 0x1408, 0x09A0, 0x05F8, 0x3F7B, 0x099F, 0x0D77, + 0x1409, 0x002C, 0x0EC9, 0x0ECB, 0x0A2E, 0x1251, + 0x0ECA, 0x079A, 0x071B, 0x05F9, 0x2738, 0x0632, + 0x002E, 0x0012, 0x7E25, 0xFB1C, 0x0262, 0x001C, + 0x03D6, 0x018E, 0x007C, 0x0342, 0x052E, 0x7E26, + 0xFB1D, 0x01D7, 0x0D7F, 0x126A, 0x2756, 0x09B6, + 0xFB20, 0x3F97, 0xFB21, 0xFB1E, 0xFB1F, 0x23AF, + 0xFB19, 0xFB1A, 0x23AE, 0x7E24, 0x1A95, 0x2755, + 0x2754, 0x05D7, 0x050D, 0x0EE3, 0xFB1B, 0x0EE2, + 0x0BB5, 0x00E3, 0x08CB, 0x05D8, 0x01B9, 0x00E7, + 0x1412, 0x1A96, 0x015A, 0x009A, 0x007B, 0xFB24, + 0x3F99, 0x026D, 0x0026, 0x0EE5, 0x0EE4, 0x0222, + 0x05D9, 0x0D82, 0x7E28, 0x3F9A, 0x0A36, 0xFB25, + 0xFB26, 0x23B1, 0x7E29, 0x126B, 0x7E27, 0x23B0, + 0xFB22, 0x1411, 0x0BB6, 0x3F98, 0x126C, 0x09B7, + 0x02C2, 0x0442, 0x0A33, 0x012B, 0x01C1, 0x0034, + 0xFB23, 0x126D, 0x03DF, 0x0084, 0x0EB7, 0x23B2, + 0x7E2A, 0x052F, 0x018D, 0x0B16, 0x7E2B, 0x01A2, + 0x0736, 0x00F3, 0x060F, 0x003B, 0x003B, 0x081A, + 0x003F, 0x1416, 0x003E, 0x3F9D, 0x126E, 0x7E2E, + 0x7E2C, 0x7E2D, 0x2757, 0x060E, 0xFB28, 0xFB27, + 0x3F9B, 0x050E, 0x0EE6, 0x018F, 0x05DA, 0x0136, + 0x071F, 0xFB29, 0x1413, 0x0137, 0x3F9C, 0x0EE7, + 0x05DB, 0x02DB, 0x05EF, 0x23B5, 0x0EBB, 0x0243, + 0xFB2D, 0x0307, 0xFB2E, 0x275A, 0x0293, 0x041F, + 0x0686, 0x3F9E, 0x0217, 0x0612, 0x05FA, 0x23B6, + 0x7E2F, 0x1A97, 0x275B, 0x0613, 0xFB2F, 0x7E30, + 0xFB2A, 0x23B4, 0x126F, 0x23B3, 0x1270, 0x2758, + 0xFB2B, 0x0610, 0x0BB7, 0x03D7, 0x2759, 0x0916, + 0x050F, 0x0EBA, 0x0BF6, 0xFB2C, 0x0611, 0x00D3, + 0x2C5E, 0x7E36, 0xFB34, 0xFB33, 0x3FA2, 0xFB35, + 0x2FDE, 0x1417, 0x0A37, 0x3FA3, 0x02A2, 0x7E37, + 0xFB36, 0x005E, 0x058A, 0x076F, 0x0886, 0x005F, + 0xFB3B, 0x0686, 0x0342, 0xFB37, 0xFB3A, 0x3F9F, + 0x3FA0, 0xFB31, 0xFB30, 0x23B7, 0x3FA1, 0x23BB, + 0x23BA, 0x1271, 0x0D83, 0x1036, 0x7E32, 0x1272, + 0x7E31, 0x7E33, 0x162E, 0x1273, 0xFB32, 0xFB0C, + 0x1262, 0xFB0D, 0xFB0B, 0x3F8F, 0x0037, 0x1263, + 0x3F90, 0x0EDD, 0x0038, 0x05D3, 0xFB0E, 0x23A7, + 0x0606, 0x1265, 0x3F91, 0x1264, 0x0039, 0xFB0F, + 0x7E14, 0xFB10, 0x274A, 0x274B, 0xFB07, 0xFB08, + 0x23A5, 0xFB06, 0x23A4, 0x0EDC, 0xFB0A, 0xFB09, + 0x7E11, 0x0036, 0x0605, 0x3F8C, 0x7E12, 0x0604, + 0x3F8E, 0x23A6, 0x7E13, 0x3F8D, 0x03DE, 0x7E19, + 0x7E18, 0x0242, 0x0097, 0x08C5, 0xFB13, 0x7E1A, + 0x005A, 0x079B, 0x0607, 0x09B2, 0x033B, 0x05D4, + 0x09B3, 0xFB14, 0x23A8, 0x0637, 0x7E1B, 0x23AA, + 0x23A9, 0x0608, 0x274C, 0xFB12, 0xFB11, 0x7E15, + 0x1266, 0x140F, 0x1267, 0x7E16, 0x274D, 0x079E, + 0x274E, 0x0EDE, 0x066B, 0x09B1, 0x0D7D, 0x3F92, + 0x7E17, 0x079A, 0x002A, 0x00D2, 0x23AC, 0x23AB, + 0x02F2, 0x00B6, 0x0BB2, 0x05D5, 0x0066, 0x03A2, + 0x003A, 0x060B, 0x060A, 0x0317, 0x079F, 0x0362, + 0x2750, 0x050C, 0x3F95, 0x7E1D, 0x7E1E, 0xFB15, + 0x23AD, 0x274F, 0x3F93, 0x3F94, 0x7E1C, 0x0609, + 0x08C6, 0x0EE0, 0x0EDF, 0x035F, 0x0136, 0x076E, + 0x1A93, 0x1268, 0x0A32, 0x024B, 0x08C7, 0x1410, + 0x01EC, 0x0036, 0x0EE1, 0x0363, 0x0072, 0x0030, + 0x003E, 0x2753, 0x7E21, 0x00D7, 0x0117, 0x003A, + 0x0BB4, 0x0126, 0x018D, 0x05D6, 0x7E22, 0xFB16, + 0x0D7E, 0x060D, 0xFB18, 0xFB17, 0x7E23, 0x7E1F, + 0x2752, 0x1269, 0x2751, 0x09B4, 0x08CA, 0x1A94, + 0x3F96, 0x0BB3, 0x0107, 0x09B5, 0x005B, 0x03D6, + 0x00B0, 0x0101, 0x7E20, 0x060C, 0x03D7, 0x0032, + 0x04DE, 0xFA91, 0x7DA8, 0x088E, 0x0374, 0x7DA9, + 0x054E, 0x007A, 0x0223, 0x0152, 0x3F26, 0x7DAA, + 0x0610, 0x1A36, 0x13B3, 0x0E58, 0x1A35, 0x7DAD, + 0x3F27, 0x7DAE, 0x7DAB, 0x7DAC, 0xFA8D, 0x2347, + 0xFA8E, 0xFA8C, 0x7DA6, 0x3F24, 0x2348, 0x7DA7, + 0x0E4F, 0x02C8, 0x0376, 0xFA90, 0xFA8F, 0x0116, + 0x008A, 0x059A, 0x3F25, 0x0044, 0x00AC, 0x1A37, + 0x0153, 0x0066, 0x01DE, 0x049C, 0xFA96, 0x3F28, + 0x0370, 0x00EA, 0x054F, 0x3F29, 0x006B, 0x093C, + 0x0570, 0x11E2, 0x26E0, 0x1A38, 0x26E1, 0x234A, + 0x7DB1, 0x093D, 0x1FD7, 0x2349, 0x7DAF, 0x7DB0, + 0x0310, 0x0775, 0xFA93, 0xFA92, 0x13B4, 0x009A, + 0x0022, 0x093B, 0x020E, 0x002A, 0x003C, 0xFA95, + 0xFA94, 0x033C, 0x00A8, 0x00C9, 0x26E3, 0xFA99, + 0x051D, 0x00FA, 0x0154, 0x093E, 0x00DE, 0x0371, + 0x002E, 0xFA9A, 0x11E3, 0x0377, 0x0776, 0x7DB2, + 0x11E4, 0x11E5, 0x7DB3, 0x3F2B, 0xFA9B, 0x234E, + 0x11E6, 0x26E2, 0x059B, 0xFA98, 0xFA97, 0x234B, + 0x0A0D, 0x059C, 0x234C, 0x0571, 0x006C, 0x075C, + 0x234D, 0x3F2A, 0x06C2, 0x00FE, 0x0311, 0x059D, + 0x010A, 0x031C, 0x059E, 0x11E8, 0x0587, 0x2352, + 0x0312, 0x7DB6, 0xFA9E, 0x04DF, 0x1FD8, 0x11E9, + 0x093F, 0x0A0E, 0x0E5A, 0x11EA, 0x2353, 0x1FD9, + 0x0573, 0x11EB, 0x7DB7, 0xFA9F, 0x0E5B, 0xFA9C, + 0xFA9D, 0x7DB4, 0x234F, 0x0E59, 0x0572, 0x2351, + 0x2350, 0x11E7, 0x049D, 0x3F2D, 0x3F2C, 0x0023, + 0x010D, 0x088F, 0x7DB5, 0x26E4, 0x0611, 0xFAA4, + 0x1A39, 0xFAA5, 0xFAA3, 0x26E7, 0xFAA6, 0x3F2F, + 0x2356, 0x2357, 0x0940, 0x13B8, 0xFAA7, 0x7DBC, + 0x1FDA, 0x2358, 0xFAA8, 0x3F30, 0x26E8, 0xFAA9, + 0xFAAA, 0xFAAB, 0x2359, 0x7DBD, 0x7DB9, 0x2354, + 0x11EC, 0xFAA0, 0x7DB8, 0x13B5, 0x11ED, 0x2355, + 0x7DBA, 0x13B6, 0x13B7, 0x7DBB, 0xFAA1, 0x26E5, + 0x0612, 0x3F2E, 0x26E6, 0xFAA2, 0x7D9E, 0x0590, + 0x7D9F, 0xBF7D, 0x0D0F, 0x13AF, 0x0591, 0x1A1C, + 0x1FD3, 0x17EE, 0x0592, 0x3F1A, 0xBF7E, 0x11DC, + 0x0593, 0x206F, 0x7DA0, 0x3F1C, 0xBF7F, 0x1A1E, + 0x3F1D, 0x1A1D, 0x245C, 0x110E, 0x110F, 0x58BE, + 0x0220, 0x0150, 0x1FD2, 0x7D9C, 0x04DC, 0x05E6, + 0x0D0E, 0x001E, 0xBF7C, 0x58BF, 0x0B80, 0x054C, + 0x13AE, 0x206E, 0x02A3, 0x051C, 0x1A30, 0x245F, + 0x0466, 0x7DA1, 0x030A, 0x3F1F, 0xFA82, 0x088C, + 0x05E7, 0x04DD, 0x13B0, 0x0790, 0x1A31, 0x1FD4, + 0x13B1, 0x7DA2, 0x2638, 0x1A32, 0x2341, 0x2340, + 0x2639, 0x3F1E, 0xFA80, 0x0594, 0x11DE, 0x11DF, + 0x0596, 0x1A1F, 0x0595, 0x02C4, 0x051A, 0x0E4D, + 0x0E4C, 0x040C, 0x245E, 0x0464, 0xFA81, 0x245D, + 0x0222, 0x0074, 0x031A, 0x3F21, 0x263B, 0x06EB, + 0x0254, 0x0774, 0x0020, 0x0078, 0x0410, 0x02EE, + 0x13B2, 0xFA84, 0x06C0, 0x0A0A, 0x0E4E, 0x0597, + 0xFA85, 0xFA87, 0x0598, 0x11E0, 0xFA86, 0x263C, + 0x1FD5, 0x2343, 0xFA83, 0x3F20, 0x2342, 0x030B, + 0x263A, 0x0B81, 0x0586, 0x040E, 0x040F, 0x2345, + 0x2344, 0x02C6, 0x0130, 0x030C, 0x054D, 0x01BE, + 0x0132, 0x0599, 0x3F23, 0x00FA, 0x012E, 0x03CE, + 0xFA8B, 0x263E, 0x02C7, 0x006A, 0x093A, 0x0E6E, + 0x0182, 0x0021, 0x00C8, 0x1A33, 0x7DA5, 0x0E6F, + 0x1FD6, 0x1A34, 0x2346, 0x263F, 0x3F22, 0x7DA4, + 0xFA88, 0x7DA3, 0x030D, 0x0A0C, 0xFA89, 0x11E1, + 0x088D, 0x0256, 0x030F, 0x030E, 0x02F8, 0x0060, + 0x02B8, 0xFA8A, 0x263D, 0x0257, 0x13BE, 0x7DCD, + 0xFAB4, 0x0E83, 0x13BF, 0x015B, 0x26F8, 0x26F7, + 0x0B89, 0x0947, 0x3F39, 0x11F9, 0x13C0, 0x26F9, + 0x05AF, 0x11FC, 0x11FA, 0x11FB, 0x0E84, 0x11FE, + 0xFAB5, 0x11FD, 0x26F5, 0xFAB2, 0x235F, 0x05AC, + 0x26F6, 0x05AD, 0x7DCB, 0x7DCA, 0x2360, 0x0946, + 0x7DCC, 0xFAB3, 0x057A, 0x0318, 0x11F8, 0x05AE, + 0x2361, 0x0B88, 0x26FB, 0x1203, 0x1204, 0x0E85, + 0x0E86, 0x0D4F, 0x0E87, 0x0948, 0x0A10, 0x1FE2, + 0x057C, 0x1A3F, 0x0D50, 0x015D, 0x057D, 0x1205, + 0x1A40, 0x13C2, 0x26FC, 0x26FD, 0x1206, 0x3F3A, + 0x1A41, 0x1FE1, 0x0E8E, 0x26FA, 0xFAB6, 0x11FF, + 0x1201, 0x7DCE, 0x1200, 0x05B0, 0x13C1, 0x089E, + 0x0319, 0x015C, 0x057B, 0x070A, 0x1A3E, 0x1202, + 0x011D, 0x031A, 0x7DCF, 0x1209, 0x0E90, 0x015F, + 0x002B, 0x05B1, 0x0D54, 0x04E5, 0x0160, 0x05B2, + 0x13C4, 0x0E88, 0x1FE5, 0x1FE6, 0x2362, 0x3F3B, + 0x13C5, 0x26FF, 0x0161, 0x057E, 0x0779, 0x0D51, + 0x13C3, 0x1A42, 0x04E4, 0x1208, 0x1A44, 0x1FE3, + 0x1207, 0x1A43, 0x0225, 0x26FE, 0x1FE4, 0x015E, + 0x0D53, 0x002A, 0x0E8F, 0x0D52, 0x0778, 0x2701, + 0x2363, 0x3F3E, 0x1FE8, 0xFAB8, 0x13C9, 0x2365, + 0x2364, 0x031B, 0x120A, 0x0E8B, 0x05B8, 0x0E8A, + 0x13CA, 0x3F3F, 0x2702, 0x1FE9, 0x120B, 0x7DD0, + 0x094A, 0x2366, 0xFAB9, 0x13CB, 0x1A45, 0x13C7, + 0x05B3, 0xFAB7, 0x13C6, 0x3F3D, 0x05B4, 0x3F3C, + 0x1FE7, 0x05B5, 0x13C8, 0x0E89, 0x1A46, 0x1A47, + 0x05B6, 0x05B7, 0x2700, 0x0949, 0x0122, 0x05B9, + 0x2704, 0x031D, 0x0469, 0x094C, 0xFABA, 0x120F, + 0x1A48, 0x0638, 0x1210, 0x13CC, 0x01B3, 0x3F42, + 0x1A49, 0xFABB, 0x3F41, 0x0E8C, 0x1A4A, 0x2367, + 0x3F43, 0x094D, 0x2703, 0x094B, 0x7DD1, 0x3F40, + 0x031C, 0x0226, 0x1FEA, 0x7DD2, 0x120C, 0x03DA, + 0x0B8A, 0x120D, 0x002C, 0x03CC, 0x04E6, 0x7DD3, + 0x120E, 0x089F, 0x04E2, 0x059F, 0xFAAD, 0x0117, + 0x0137, 0x0613, 0x235C, 0x3F31, 0x0899, 0x02EF, + 0x0025, 0x0942, 0x0468, 0x0E8C, 0x0A0F, 0x13BA, + 0x7DBE, 0x13B9, 0x05A0, 0x7DC0, 0x26EB, 0x7DBF, + 0x235A, 0x235B, 0x0372, 0x0313, 0x0941, 0x0898, + 0x26E9, 0x0574, 0x02C9, 0x051E, 0x0024, 0x1FDB, + 0x0467, 0x0791, 0x04E1, 0x26EA, 0xFAAC, 0x04E0, + 0x3F34, 0x0E5D, 0x26ED, 0xFAAE, 0x1FDC, 0x0575, + 0x0314, 0x7DC4, 0x1FDD, 0x1FDE, 0x05A1, 0x0E5E, + 0x26EE, 0x26EF, 0x7DC5, 0x11EE, 0xFAAF, 0x3F35, + 0x11EF, 0x26F0, 0x7DC6, 0xFAB0, 0x05A2, 0x7DC1, + 0x0E5C, 0x7DC2, 0x00CA, 0x01B0, 0x235D, 0x3F32, + 0x075E, 0x0B82, 0x0155, 0x0156, 0x3F33, 0x26EC, + 0x0708, 0x0B83, 0x1A3B, 0x7DC3, 0x1A3A, 0x089B, + 0x11F2, 0x05A5, 0x0E5F, 0x0027, 0x01B2, 0x089C, + 0x26F3, 0x0B85, 0x0157, 0x011C, 0x0944, 0x0577, + 0x7DC8, 0x13BB, 0x089D, 0x05A6, 0x0315, 0x0E8D, + 0xFAB1, 0x1A3C, 0x03AC, 0x0576, 0x7DC7, 0x0B84, + 0x05A3, 0x26F1, 0x26F2, 0x05A4, 0x0224, 0x0943, + 0x0D4C, 0x11F0, 0x1FDF, 0x089A, 0x02F0, 0x0D4D, + 0x0026, 0x11F1, 0x0777, 0x0E82, 0x0029, 0x05A8, + 0x1A3D, 0x0028, 0x00CB, 0x0159, 0x11F6, 0x0709, + 0x0614, 0x04E3, 0x015A, 0x0578, 0x0B87, 0x1FE0, + 0x05AA, 0x7DC9, 0x05A9, 0x05AB, 0x0579, 0x11F7, + 0x3F38, 0x0945, 0x13BC, 0x26F4, 0x235E, 0x3F36, + 0x0158, 0x05A7, 0x3F37, 0x0E80, 0x11F3, 0x13BD, + 0x0B86, 0x0E81, 0x0316, 0x0317, 0x0D4E, 0x11F5, + 0x11F4, 0x075F, 0x06C3, 0x08A6, 0x0B8D, 0x0584, + 0x022A, 0x02CA, 0x13D5, 0x0E93, 0x0217, 0x011F, + 0x0124, 0x0120, 0x0B8E, 0x06C4, 0x0326, 0x0327, + 0x05BC, 0x0B8F, 0xFAC1, 0x0955, 0x1217, 0x7DD9, + 0x0328, 0x0323, 0x0324, 0x2369, 0x7DD8, 0x0031, + 0x1FF3, 0x1216, 0xFAC0, 0x1215, 0x0032, 0x00CD, + 0x03AF, 0x0A12, 0x01BC, 0x0070, 0x0325, 0x0E92, + 0x038E, 0x02D7, 0x2708, 0x13D7, 0x0296, 0x039A, + 0x00FE, 0x070D, 0x01ED, 0x02D8, 0x0398, 0x077E, + 0x0167, 0x0244, 0x0329, 0x01BD, 0x0521, 0x022B, + 0x1A50, 0x0122, 0x08A9, 0x0A13, 0x05DD, 0x070C, + 0x04E9, 0x0033, 0x0121, 0x13D6, 0x0956, 0x08A7, + 0x0585, 0x0166, 0x0204, 0x08A8, 0x0586, 0x04A0, + 0x02CB, 0x003D, 0x0588, 0x0289, 0x03C2, 0x03B8, + 0x077F, 0x0587, 0x04EB, 0x00CF, 0x01A3, 0x13D9, + 0x0617, 0x01A2, 0x06C5, 0x0522, 0x03B9, 0x070E, + 0x0762, 0x08AA, 0x1A51, 0x0169, 0x03BA, 0x1218, + 0x0523, 0x04EC, 0x3F49, 0x0E96, 0x04EA, 0x02CA, + 0x0D59, 0x13D8, 0x03D2, 0x0E95, 0x0957, 0x0E94, + 0x0168, 0x0123, 0x031E, 0x0412, 0x032A, 0x00CE, + 0x039C, 0x0E95, 0x0D5A, 0x0071, 0x13DC, 0x7DDA, + 0x236C, 0x0E96, 0x13DD, 0x032C, 0x1A52, 0x0B90, + 0x0589, 0x032D, 0x2709, 0x1FF6, 0x058A, 0x1219, + 0x05BD, 0x058B, 0x0035, 0x270A, 0x05DE, 0x095A, + 0x1A53, 0x016B, 0x022C, 0x070F, 0x13DA, 0x0958, + 0x3F4A, 0x0588, 0x0D5B, 0x13DB, 0x236A, 0x0780, + 0x3F4B, 0x1FF4, 0x0959, 0x0034, 0x016A, 0x236B, + 0x1FF5, 0x032B, 0x270B, 0x02F3, 0xFAC4, 0x7DDC, + 0x1FF7, 0x0124, 0x095C, 0x016C, 0x0072, 0x016A, + 0x04EE, 0x270D, 0x270C, 0x022D, 0x04A1, 0x270E, + 0x0E97, 0x0618, 0xFAC5, 0x0E98, 0x3F4C, 0x236E, + 0x1A54, 0x05BF, 0x032E, 0x121A, 0xFAC2, 0x05BE, + 0x01EE, 0x04ED, 0x236D, 0x03BB, 0x0125, 0x00EC, + 0x7DDB, 0xFAC3, 0x05DF, 0x00C9, 0x08AB, 0x095B, + 0x013C, 0x01FE, 0x0B8B, 0xFABD, 0x7DD4, 0x0615, + 0x01EA, 0x0E91, 0x057F, 0x016E, 0x0156, 0x08A1, + 0x094E, 0x7DD5, 0x03D1, 0x01B6, 0x1FEC, 0x1FEB, + 0xFABE, 0x7DD6, 0x1212, 0x7DD7, 0xFABF, 0x1A4C, + 0x0E8D, 0x3F44, 0xFABC, 0x002D, 0x006A, 0x01B5, + 0x13CD, 0x08A0, 0x01B4, 0x03D0, 0x006B, 0x1211, + 0x3F45, 0x0227, 0x02FE, 0x077A, 0x1A4B, 0x014A, + 0x0E91, 0x1FED, 0x2705, 0x0162, 0x094F, 0x002E, + 0x04E8, 0x1FEE, 0x0A11, 0x0950, 0x0581, 0x1FEF, + 0x1FF0, 0x2706, 0x3F47, 0x1A4F, 0x0582, 0x05BA, + 0x002F, 0x031E, 0x13CF, 0x0760, 0x0580, 0x0E92, + 0x031D, 0x04E7, 0x1A4D, 0x1A4E, 0x0E8E, 0x01B7, + 0x02F1, 0x02F2, 0x3F46, 0x0E8F, 0x0616, 0x0D55, + 0x006C, 0x0E93, 0x0E90, 0x13CE, 0x049E, 0x0411, + 0x13D0, 0x08A2, 0x03AD, 0x02D3, 0x0228, 0x13D1, + 0x006D, 0x006D, 0x0792, 0x01B8, 0x077C, 0x0229, + 0x0320, 0x1FF1, 0x3F48, 0x0D56, 0x13D2, 0x01B9, + 0x2707, 0x2368, 0x0D57, 0x00CC, 0x0520, 0x1213, + 0x0163, 0x051F, 0x0951, 0x1214, 0x0E94, 0x0164, + 0x00FC, 0x070B, 0x077B, 0x0761, 0x00C6, 0x017A, + 0x031F, 0x0583, 0x01EE, 0x00D4, 0x0165, 0x0952, + 0x02C8, 0x00C8, 0x023A, 0x0030, 0x01EC, 0x00FD, + 0x02F9, 0x01BB, 0x0953, 0x01A0, 0x13D4, 0x08A5, + 0x0030, 0x08A4, 0x077D, 0x006E, 0x0D58, 0x0954, + 0x05DC, 0x0123, 0x0321, 0x01BA, 0x0288, 0x05BB, + 0x13D3, 0x0322, 0x03AE, 0x0B8C, 0x049F, 0x1FF2, + 0x08A3, 0x006E, 0x02D6, 0x006F, 0x011E, 0x0373, + 0x03BF, 0x01EA, 0x08AF, 0x0595, 0x0100, 0x0112, + 0x0050, 0x02B9, 0x014C, 0x01A4, 0x0258, 0x04F2, + 0x0596, 0x00A4, 0x13E1, 0x0124, 0x08B0, 0x04F3, + 0x0171, 0x0413, 0x2713, 0x0E9B, 0x046C, 0x00A2, + 0x0765, 0x05E0, 0x019C, 0x0964, 0x0335, 0x061C, + 0x3F4F, 0x0E9A, 0x009A, 0x0170, 0x0784, 0x003E, + 0x012F, 0x01A3, 0x023D, 0x01F0, 0x016B, 0x00A3, + 0x023F, 0x03C4, 0x03D4, 0x0377, 0x0052, 0x01BE, + 0x0031, 0x0012, 0x0157, 0x021A, 0x0242, 0x039E, + 0x04A2, 0x05E1, 0x02F6, 0x1A5D, 0x0336, 0x0126, + 0x05E2, 0x2374, 0x05C4, 0x046D, 0x0311, 0x01A5, + 0x04F4, 0xFAC8, 0x023E, 0x0A17, 0x0D5F, 0x05C3, + 0x08B1, 0x009C, 0x02CD, 0x0299, 0x036A, 0x0376, + 0x006C, 0x0037, 0x0785, 0x0076, 0x0040, 0x0965, + 0x13E2, 0x02CC, 0x0259, 0x0414, 0x06C6, 0x01A6, + 0x033F, 0x0334, 0x0E9C, 0x0786, 0x0127, 0x0966, + 0x06C7, 0x063B, 0x0039, 0x0172, 0x0374, 0x003A, + 0x0597, 0x0128, 0x00FF, 0x0526, 0x2375, 0x0044, + 0x0337, 0x0B95, 0x0230, 0x7DDE, 0x0D60, 0x0185, + 0x0D61, 0x0038, 0x0321, 0x003F, 0x009D, 0x0101, + 0x03B9, 0x0312, 0x0969, 0x1A5E, 0x1220, 0x2714, + 0x003B, 0x0598, 0x2715, 0x1FFB, 0x08B2, 0x096A, + 0x0EA1, 0x7DDF, 0x1FFC, 0x0A18, 0x1A5F, 0x1222, + 0x1221, 0x0173, 0x0793, 0x061D, 0x096B, 0x7DE0, + 0x0787, 0x0231, 0x0711, 0x0EA0, 0xFAC9, 0x121D, + 0x05C5, 0x121F, 0x121E, 0x3F50, 0x0E9D, 0x0338, + 0x0968, 0x0967, 0x04F5, 0x0B96, 0x05C7, 0x05C6, + 0x03BE, 0x01B8, 0x1225, 0x1224, 0x02CE, 0x0160, + 0x0102, 0xFACD, 0x3F51, 0x0322, 0xFACE, 0x0339, + 0x059A, 0x019E, 0x063C, 0x01BF, 0x7DE2, 0x3F52, + 0x0D62, 0x2718, 0x3F53, 0x2717, 0x0EA2, 0x0599, + 0x13E3, 0xFACA, 0xFACB, 0x06C8, 0x06C9, 0xFACC, + 0x7DE1, 0x0125, 0x01BC, 0x13E4, 0x1223, 0x0336, + 0x02BA, 0x028B, 0x2716, 0x2376, 0x02CD, 0x013D, + 0x095E, 0x05C0, 0x0016, 0x016F, 0x0525, 0x2371, + 0x2370, 0x0205, 0x01C8, 0x058C, 0x0B91, 0x00E6, + 0x0639, 0x0330, 0x2372, 0x3F4D, 0x0763, 0x016E, + 0x121B, 0x1FF9, 0x058D, 0x016D, 0x1A55, 0x270F, + 0x13DE, 0xFAC6, 0x1FF8, 0x236F, 0x1A56, 0x04EF, + 0x0298, 0x0E99, 0x095D, 0x01BE, 0x02CC, 0x0524, + 0x032F, 0x7DDD, 0x0589, 0x095F, 0x03BC, 0x1A59, + 0x0E9A, 0x0E9B, 0x061A, 0x13E0, 0x0E9C, 0x08AD, + 0x0332, 0x0A15, 0x0591, 0x0D5D, 0x0590, 0x0960, + 0x2373, 0x2711, 0x1A5A, 0x058A, 0x006F, 0x3F4E, + 0x2712, 0x0764, 0x08AC, 0x05C1, 0xFAC7, 0x0331, + 0x1FFA, 0x13DF, 0x2710, 0x1A57, 0x0E97, 0x058E, + 0x0619, 0x0A14, 0x1A58, 0x0D5C, 0x0782, 0x058F, + 0x121C, 0x0781, 0x0210, 0x0594, 0x0962, 0x0080, + 0x0399, 0x03C3, 0x02F5, 0x0184, 0x028A, 0x046B, + 0x0963, 0x0B92, 0x0100, 0x1A5B, 0x0A16, 0x0E9D, + 0x03BD, 0x0B93, 0x01A4, 0x0333, 0x0783, 0x033E, + 0x00FE, 0x0592, 0x031F, 0x046A, 0x0593, 0x0961, + 0x04F0, 0x00FF, 0x02F4, 0x0073, 0x0E98, 0x04F1, + 0x033D, 0x0266, 0x02FF, 0x03D3, 0x0320, 0x0206, + 0x004E, 0x023C, 0x01EF, 0x0211, 0x0027, 0x000C, + 0x063A, 0x08AE, 0x008C, 0x03CE, 0x02D9, 0x02FA, + 0x01A2, 0x01A5, 0x061B, 0x0E9E, 0x05C2, 0x022F, + 0x039D, 0x01F0, 0x1A5C, 0x0E9F, 0x02CB, 0x03B8, + 0x014B, 0x0B94, 0x0E99, 0x013E, 0x016F, 0x0036, + 0x0334, 0x0D5E, 0x0310, 0x0207, 0x0044, 0x017B, + 0x00DF, 0x0042, 0x022E, 0x0710, 0x007E, +}; + +static const uint8_t on2avc_cb8_bits[ON2AVC_CB8_CODES] = { + 11, 11, 16, 15, 11, 9, + 13, 12, 9, 11, 11, 14, + 13, 12, 13, 14, 14, 13, + 10, 11, 15, 15, 10, 16, + 16, 15, 16, 11, 13, 13, + 16, 13, 11, 11, 15, 13, + 11, 9, 13, 13, 10, 9, + 16, 13, 9, 10, 10, 15, + 10, 10, 10, 12, 14, 11, + 14, 12, 14, 11, 12, 11, + 12, 14, 10, 10, 11, 16, + 10, 13, 14, 14, 11, 13, + 11, 13, 12, 10, 10, 10, + 15, 10, 10, 12, 12, 12, + 15, 12, 11, 12, 13, 10, + 11, 11, 12, 13, 11, 13, + 12, 15, 13, 11, 11, 12, + 14, 11, 11, 11, 13, 14, + 11, 13, 14, 13, 12, 12, + 12, 11, 14, 12, 10, 13, + 14, 11, 13, 15, 14, 14, + 13, 13, 14, 13, 13, 13, + 15, 14, 12, 14, 14, 14, + 16, 14, 12, 12, 16, 16, + 12, 13, 12, 14, 14, 13, + 13, 16, 14, 13, 14, 13, + 13, 13, 13, 15, 14, 13, + 10, 12, 16, 16, 12, 10, + 13, 14, 11, 11, 12, 14, + 14, 11, 12, 16, 13, 12, + 14, 14, 14, 16, 15, 16, + 15, 16, 15, 14, 12, 14, + 13, 11, 10, 11, 14, 14, + 11, 9, 14, 14, 10, 16, + 12, 15, 16, 12, 11, 14, + 13, 9, 11, 11, 15, 15, + 12, 13, 14, 15, 12, 16, + 14, 15, 15, 13, 14, 14, + 15, 14, 14, 14, 13, 15, + 12, 14, 12, 15, 15, 12, + 11, 13, 15, 10, 14, 13, + 14, 13, 13, 13, 13, 13, + 13, 12, 13, 13, 12, 14, + 14, 16, 12, 14, 11, 13, + 13, 12, 14, 15, 13, 13, + 13, 13, 13, 14, 13, 13, + 13, 14, 13, 13, 12, 14, + 14, 13, 11, 12, 13, 12, + 12, 10, 13, 13, 11, 11, + 12, 14, 11, 12, 13, 15, + 14, 14, 16, 11, 13, 13, + 11, 15, 10, 14, 13, 12, + 12, 13, 12, 13, 11, 11, + 11, 12, 11, 10, 12, 13, + 10, 10, 13, 13, 10, 10, + 10, 10, 15, 11, 11, 13, + 12, 11, 13, 12, 11, 16, + 14, 10, 14, 11, 10, 10, + 15, 12, 11, 13, 12, 11, + 14, 13, 11, 13, 11, 10, + 9, 10, 10, 14, 10, 9, + 14, 13, 9, 9, 10, 10, + 10, 10, 10, 12, 14, 10, + 14, 13, 12, 11, 14, 13, + 11, 13, 9, 11, 13, 13, + 11, 14, 14, 12, 12, 13, + 10, 12, 12, 10, 9, 10, + 10, 10, 10, 9, 10, 10, + 11, 10, 8, 12, 12, 9, + 11, 10, 10, 11, 11, 12, + 12, 14, 12, 10, 14, 13, + 16, 10, 10, 11, 16, 14, + 11, 12, 14, 12, 12, 10, + 11, 10, 10, 11, 9, 11, + 11, 9, 11, 12, 13, 10, + 10, 11, 11, 11, 11, 10, + 13, 13, 10, 13, 11, 11, + 11, 12, 11, 11, 11, 10, + 10, 12, 12, 10, 14, 12, + 11, 12, 12, 11, 12, 12, + 11, 10, 11, 11, 11, 11, + 14, 13, 13, 13, 13, 12, + 13, 13, 12, 12, 12, 13, + 13, 12, 13, 13, 14, 14, + 13, 12, 13, 15, 14, 12, + 13, 16, 14, 12, 14, 14, + 14, 13, 13, 12, 13, 13, + 12, 12, 14, 13, 12, 10, + 13, 14, 14, 10, 11, 14, + 14, 11, 10, 13, 13, 11, + 12, 12, 14, 14, 14, 13, + 13, 14, 13, 13, 14, 13, + 12, 11, 12, 15, 14, 12, + 9, 12, 13, 10, 9, 11, + 13, 14, 11, 10, 13, 15, + 14, 10, 11, 13, 14, 11, + 11, 12, 12, 10, 12, 12, + 15, 15, 12, 14, 14, 14, + 13, 13, 14, 14, 14, 11, + 12, 14, 15, 12, 10, 12, + 13, 9, 9, 11, 14, 15, + 11, 14, 13, 13, 13, 15, + 13, 13, 14, 12, 14, 13, + 13, 13, 12, 13, 14, 14, + 13, 11, 11, 15, 13, 11, + 12, 13, 15, 12, 12, 13, + 14, 14, 14, 13, 13, 13, + 13, 13, 12, 13, 14, 13, + 10, 14, 13, 11, 10, 11, + 11, 11, 11, 11, 12, 12, + 11, 12, 13, 12, 11, 13, + 10, 12, 11, 10, 11, 13, + 12, 10, 12, 12, 12, 11, + 12, 10, 12, 12, 10, 10, + 11, 11, 11, 11, 9, 10, + 11, 10, 10, 9, 12, 12, + 9, 11, 11, 10, 9, 10, + 13, 14, 13, 12, 10, 10, + 14, 14, 10, 11, 11, 13, + 13, 11, 13, 13, 12, 11, + 10, 11, 11, 10, 10, 9, + 12, 12, 9, 11, 12, 13, + 12, 12, 11, 12, 13, 11, + 11, 12, 12, 12, 12, 13, + 15, 14, 14, 13, 12, 16, + 14, 12, 11, 12, 16, 15, + 12, 13, 15, 13, 13, 12, + 12, 12, 12, 11, 10, 13, + 13, 10, 10, 12, 13, 10, + 10, 10, 11, 11, 11, 11, + 12, 12, 11, 13, 12, 12, + 13, 13, 11, 12, 13, 11, + 11, 12, 12, 11, 13, 13, + 13, 13, 13, 10, 14, 11, + 11, 10, 11, 11, 11, 10, + 11, 12, 13, 12, 11, 10, + 12, 12, 10, 11, 10, 11, + 12, 11, 13, 12, 14, 13, + 11, 12, 13, 14, 12, 11, + 11, 14, 14, 12, 12, 13, + 13, 13, 12, 12, 12, 12, + 11, 10, 12, 12, 10, 13, + 14, 13, 12, 12, 13, 13, + 13, 12, 12, 14, 13, 12, + 14, 12, 11, 14, 13, 11, + 11, 13, 12, 11, 13, 14, + 12, 14, 14, 14, 13, 14, + 12, 13, 13, 13, 13, 13, + 13, 12, 13, 10, 12, 14, + 15, 13, 10, 13, 12, 11, + 11, 12, 13, 13, 11, 11, + 12, 13, 12, 16, 11, 13, + 16, 14, 16, 15, 15, 16, + 13, 11, 14, 13, 12, 11, + 11, 15, 13, 11, 9, 13, + 14, 11, 10, 12, 15, 14, + 12, 11, 13, 13, 10, 11, + 11, 14, 14, 11, 12, 13, + 13, 11, 13, 12, 14, 16, + 12, 16, 13, 15, 15, 13, + 12, 13, 14, 14, 10, 11, + 14, 14, 11, 10, 13, 13, + 9, 12, 14, 16, 12, 13, + 13, 12, 13, 13, 12, 14, + 14, 13, 14, 14, 15, 14, + 13, 12, 13, 11, 11, 11, + 13, 13, 13, 14, 13, 13, + 14, 14, 12, 14, 16, 14, + 13, 12, 13, 14, 13, 12, + 12, 12, 12, 12, 11, 12, + 14, 11, 12, 12, 12, 11, + 11, 14, 14, 13, 13, 11, + 12, 14, 12, 11, 14, 11, + 13, 13, 11, 12, 13, 13, + 12, 12, 11, 12, 12, 12, + 11, 12, 13, 11, 10, 13, + 13, 11, 10, 11, 11, 11, + 11, 11, 13, 12, 11, 14, + 13, 12, 13, 12, 11, 14, + 12, 11, 12, 13, 13, 11, + 13, 13, 13, 12, 12, 10, + 12, 12, 10, 10, 10, 11, + 11, 11, 12, 15, 15, 13, + 12, 13, 14, 14, 14, 13, + 16, 14, 13, 15, 14, 14, + 16, 15, 13, 14, 15, 13, + 14, 14, 14, 13, 15, 13, + 14, 13, 14, 13, 16, 14, + 12, 12, 13, 13, 12, 13, + 13, 14, 13, 13, 13, 11, + 14, 14, 12, 14, 13, 13, + 12, 13, 13, 14, 15, 14, + 13, 12, 15, 15, 13, 14, + 12, 14, 14, 13, 14, 15, + 13, 13, 13, 13, 13, 13, + 12, 12, 15, 14, 12, 13, + 15, 14, 12, 12, 12, 12, + 15, 12, 12, 13, 14, 12, + 13, 13, 13, 14, 14, 13, + 13, 14, 13, 14, 14, 14, + 13, 14, 14, 13, 13, 13, + 12, 14, 13, 12, 12, 13, + 14, 12, 12, 16, 15, 15, + 13, 13, 13, 14, 14, 13, + 13, 12, 12, 14, 13, 13, + 12, 14, 14, 14, 12, 12, + 14, 14, 16, 13, 16, 14, + 14, 16, 14, 13, 14, 13, + 14, 14, 14, 13, 13, 16, + 13, 13, 11, 15, 15, 12, + 12, 13, 14, 15, 12, 11, + 13, 13, 11, 13, 11, 14, + 14, 14, 14, 11, 15, 14, + 13, 14, 14, 14, 14, 14, + 15, 15, 13, 11, 14, 13, + 12, 11, 12, 15, 15, 12, + 12, 14, 15, 11, 11, 13, + 14, 15, 12, 13, 13, 13, + 11, 13, 13, 15, 14, 12, + 14, 14, 13, 13, 14, 15, + 16, 16, 13, 13, 14, 16, + 14, 12, 12, 14, 11, 11, + 13, 15, 15, 12, 16, 14, + 14, 14, 15, 13, 14, 14, + 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 13, + 15, 14, 12, 14, 15, 16, + 16, 13, 14, 15, 15, 14, + 16, 14, 14, 14, 14, 13, + 14, 16, 13, 13, 14, 14, + 12, 12, 12, 14, 12, 13, + 12, 14, 13, 12, 14, 15, + 15, 13, 13, 12, 13, 13, + 13, 13, 14, 13, 12, 13, + 13, 13, 13, 13, 12, 14, + 14, 12, 12, 12, 14, 13, + 13, 12, 12, 12, 14, 13, + 12, 14, 15, 12, 13, 12, + 12, 14, 13, 14, 15, 16, + 14, 15, 13, 16, 16, 13, + 13, 13, 14, 14, 13, 12, + 13, 14, 13, 13, 12, 14, + 13, 12, 11, 14, 14, 12, + 7, 10, 15, 16, 10, 7, + 12, 13, 7, 11, 11, 15, + 16, 12, 12, 14, 14, 13, + 16, 14, 16, 16, 16, 15, + 16, 16, 15, 15, 13, 14, + 14, 13, 12, 13, 16, 13, + 12, 9, 12, 13, 9, 9, + 13, 13, 9, 8, 10, 16, + 14, 10, 11, 13, 13, 10, + 13, 12, 15, 14, 12, 16, + 16, 15, 15, 14, 15, 15, + 16, 13, 12, 14, 14, 13, + 10, 13, 12, 11, 9, 11, + 16, 14, 11, 9, 12, 15, + 15, 11, 9, 13, 15, 9, + 11, 11, 14, 14, 12, 12, + 14, 13, 14, 14, 14, 15, + 15, 15, 14, 14, 16, 16, + 14, 12, 13, 13, 13, 11, + 11, 16, 13, 12, 14, 13, + 13, 10, 11, 15, 12, 12, + 16, 12, 16, 14, 11, 11, + 13, 14, 11, 14, 11, 15, + 15, 13, 14, 14, 16, 15, + 16, 15, 14, 15, 14, 14, + 16, 14, 12, 12, 14, 12, + 12, 12, 12, 16, 14, 12, + 15, 15, 16, 16, 14, 16, + 14, 13, 12, 14, 14, 15, + 16, 13, 12, 11, 14, 13, + 16, 12, 12, 16, 16, 14, + 14, 16, 16, 15, 14, 15, + 15, 14, 12, 13, 15, 14, + 15, 15, 14, 14, 16, 16, + 14, 16, 16, 14, 14, 14, + 14, 13, 14, 13, 16, 15, + 14, 14, 14, 14, 14, 16, + 15, 16, 14, 14, 16, 16, + 15, 16, 15, 13, 16, 16, + 15, 14, 14, 14, 15, 14, + 14, 15, 15, 14, 11, 15, + 15, 12, 10, 12, 16, 15, + 13, 11, 14, 13, 11, 13, + 13, 16, 15, 12, 15, 15, + 15, 14, 14, 16, 16, 15, + 14, 13, 14, 15, 14, 12, + 14, 13, 11, 13, 12, 14, + 15, 11, 9, 12, 15, 15, + 11, 9, 12, 13, 9, 10, + 12, 14, 14, 10, 12, 13, + 14, 12, 14, 15, 15, 16, + 15, 14, 14, 14, 15, 14, + 12, 13, 13, 13, 12, 11, + 13, 14, 12, 10, 12, 13, + 9, 7, 13, 13, 7, 6, + 9, 14, 15, 9, 10, 14, + 12, 9, 13, 13, 15, 16, + 12, 14, 16, 16, 15, 15, + 14, 14, 14, 13, 12, 13, + 14, 12, 11, 13, 13, 10, + 9, 10, 15, 14, 10, 6, + 12, 16, 15, 12, 10, 15, + 13, 10, 12, 13, 14, 15, + 12, 13, 13, 13, 13, 15, + 14, 15, 15, 15, 16, 15, + 16, 16, 15, 14, 15, 15, + 13, 11, 12, 16, 16, 12, + 9, 14, 14, 8, 9, 13, + 13, 8, 9, 11, 16, 14, + 11, 11, 13, 14, 11, 13, + 13, 14, 14, 13, 14, 15, + 15, 13, 13, 15, 15, 15, + 13, 12, 16, 16, 13, 10, + 13, 13, 10, 6, 11, 16, + 16, 10, 9, 12, 14, 16, + 11, 10, 13, 13, 10, 11, + 12, 16, 14, 12, 12, 15, + 14, 14, 15, 14, 16, 15, + 14, 14, 14, 16, 16, 15, + 12, 14, 15, 13, 11, 11, + 15, 14, 11, 9, 13, 14, + 9, 11, 14, 14, 11, 15, + 13, 15, 16, 12, 13, 14, + 13, 12, 13, 14, 15, 13, + 13, 14, 15, 16, 13, 16, + 16, 15, 15, 13, 13, 15, + 15, 14, 11, 14, 14, 13, + 10, 12, 15, 14, 12, 16, + 13, 16, 16, 14, 16, 14, + 15, 15, 13, 13, 16, 15, + 13, 15, 16, 14, 14, 16, + 16, 16, 15, 15, 15, 15, + 14, 16, 15, 13, 14, 15, + 15, 13, 13, 15, 16, 14, + 12, 14, 14, 16, 15, 14, + 15, 16, 13, 13, 14, 15, + 13, 13, 14, 14, 16, 14, + 14, 14, 15, 14, 16, 15, + 14, 15, 14, 15, 15, 16, + 12, 13, 13, 15, 12, 12, + 13, 13, 16, 16, 12, 13, + 13, 14, 14, 11, 13, 14, + 11, 15, 13, 14, 16, 12, + 12, 12, 13, 11, 13, 13, + 13, 15, 14, 13, 15, 15, + 14, 14, 16, 14, 14, 14, + 14, 15, 14, 11, 11, 13, + 13, 11, 14, 11, 16, 14, + 12, 9, 11, 14, 14, 11, + 10, 12, 13, 10, 11, 12, + 13, 16, 11, 12, 13, 14, + 16, 16, 14, 14, 16, 14, + 13, 15, 16, 14, 15, 13, + 14, 12, 11, 11, 11, 15, + 15, 11, 9, 13, 13, 9, + 9, 14, 14, 9, 9, 11, + 16, 14, 11, 11, 13, 12, + 11, 13, 12, 13, 15, 12, + 13, 13, 15, 14, 14, 15, + 16, 15, 13, 12, 16, 14, + 12, 10, 13, 13, 10, 8, + 10, 16, 14, 10, 13, 15, + 16, 13, 13, 13, 14, 14, + 12, 13, 14, 14, 13, 14, + 14, 14, 14, 14, 13, 14, + 16, 14, 14, 16, 15, 14, + 14, 14, 15, 15, 15, 13, + 15, 16, 13, 13, 14, 14, + 15, 12, 14, 14, 14, 13, + 13, 12, 13, 13, 12, 13, + 13, 13, 12, 13, 13, 14, + 13, 13, 14, 14, 14, 14, + 13, 13, 12, 14, 16, 14, + 14, 15, 14, 14, 13, 12, + 13, 13, 13, 11, 13, 14, + 12, 13, 15, 14, 12, 13, + 13, 14, 12, 12, 13, 14, + 13, 13, 13, 13, 15, 14, + 13, 14, 13, 13, 12, 12, + 13, 13, 12, 14, 13, 13, + 14, 13, 12, 14, 13, 13, + 12, 13, 12, 12, 12, 14, + 15, 14, 13, 16, 13, 15, + 15, 13, 14, 13, 14, 13, + 13, 14, 14, 13, 14, 15, + 13, 15, 16, 13, 13, 13, + 14, 16, 13, 14, 14, 14, + 13, 14, 13, 13, 13, 13, + 14, 14, 14, 13, 11, 14, + 14, 13, 11, 13, 16, 14, + 13, 11, 14, 13, 12, 14, + 13, 16, 14, 13, 13, 15, + 14, 13, 14, 13, 15, 14, + 13, 12, 13, 15, 14, 10, + 12, 14, 13, 10, 12, 15, + 14, 12, 12, 14, 16, 12, + 11, 12, 15, 14, 12, 12, + 13, 13, 11, 12, 12, 13, + 15, 13, 14, 15, 14, 15, + 15, 15, 11, 13, 13, 12, + 14, 13, 11, 11, 13, 13, + 11, 11, 12, 14, 16, 12, + 14, 13, 14, 16, 13, 13, + 13, 15, 13, 13, 14, 13, + 14, 14, 15, 14, 16, 14, + 14, 14, 15, 16, 14, 15, + 13, 15, 12, 12, 15, 14, + 11, 12, 13, 13, 14, 14, + 11, 12, 13, 15, 13, 12, + 14, 14, 13, 13, 12, 12, + 14, 12, 13, 12, 13, 13, + 15, 13, 12, 14, 13, 12, + 16, 13, 12, 13, 15, 12, + 14, 14, 14, 14, 12, 13, + 12, 14, 13, 12, 12, 12, + 13, 14, 12, 13, 13, 14, + 13, 13, 12, 13, 14, 11, + 12, 12, 13, 13, 12, 13, + 14, 15, 14, 14, 13, 14, + 14, 13, 13, 14, 15, 14, + 13, 14, 14, 13, 14, 13, + 12, 13, 13, 13, 12, 14, + 14, 11, 11, 12, 12, 13, + 12, 10, 13, 13, 10, 12, + 11, 12, 12, 11, 13, 13, + 14, 12, 16, 13, 14, 15, + 13, 13, 13, 15, 15, 13, + 13, 14, 16, 14, 13, 12, + 12, 12, 12, 11, 13, 13, + 10, 10, 14, 13, 10, 10, + 11, 11, 11, 10, 10, 12, + 13, 10, 13, 12, 11, 12, + 13, 12, 12, 12, 11, 11, + 12, 13, 12, 13, 13, 12, + 13, 13, 11, 12, 13, 11, + 10, 11, 11, 11, 10, 12, + 12, 13, 12, 12, 11, 13, + 12, 11, 11, 11, 12, 11, + 11, 12, 13, 13, 12, 14, + 11, 12, 14, 12, 12, 11, + 12, 13, 11, 12, 13, 13, + 13, 12, 11, 11, 13, 12, + 10, 13, 12, 11, 13, 15, + 15, 13, 13, 13, 13, 12, + 13, 13, 14, 13, 13, 14, + 14, 13, 13, 14, 11, 13, + 13, 13, 12, 11, 13, 13, + 14, 13, 12, 13, 15, 12, + 14, 13, 13, 13, 13, 15, + 13, 13, 14, 12, 16, 15, + 13, 9, 13, 13, 11, 10, + 12, 14, 14, 12, 11, 14, + 13, 12, 16, 13, 14, 15, + 13, 14, 13, 14, 16, 14, + 11, 12, 15, 12, 11, 11, + 15, 16, 11, 10, 12, 13, + 11, 10, 12, 16, 15, 12, + 11, 12, 13, 9, 10, 12, + 13, 15, 11, 12, 13, 13, + 16, 15, 14, 15, 16, 13, + 13, 14, 16, 13, 12, 12, + 13, 12, 12, 11, 12, 14, + 14, 12, 10, 12, 13, 10, + 13, 13, 14, 13, 13, 13, + 12, 13, 12, 13, 13, 13, + 13, 14, 14, 13, 13, 14, + 13, 13, 13, 11, 13, 12, + 11, 12, 13, 13, 13, 12, + 12, 12, 14, 13, 12, 12, + 12, 12, 13, 13, 11, 11, + 13, 12, 12, 10, 12, 13, + 11, 12, 11, 12, 12, 12, + 13, 13, 14, 12, 13, 12, + 14, 15, 12, 12, 11, 14, + 13, 11, 13, 14, 12, 13, + 11, 11, 12, 11, 10, 10, + 13, 13, 10, 10, 13, 13, + 10, 10, 10, 12, 11, 11, + 10, 12, 13, 11, 13, 12, + 13, 12, 12, 12, 12, 13, + 11, 11, 13, 12, 11, 14, + 13, 13, 12, 12, 11, 13, + 12, 11, 10, 11, 12, 11, + 10, 9, 12, 13, 9, 9, + 10, 10, 10, 10, 10, 12, + 13, 11, 13, 12, 12, 12, + 13, 11, 14, 12, 11, 10, + 11, 11, 10, 13, 13, 12, + 14, 12, 11, 13, 12, 11, + 9, 10, 10, 10, 10, 10, + 10, 10, 11, 10, 9, 12, + 12, 9, 10, 10, 10, 10, + 11, 11, 12, 13, 13, 11, + 11, 15, 14, 11, 10, 10, + 12, 16, 10, 12, 12, 14, + 12, 11, 10, 10, 10, 10, + 9, 13, 12, 9, 11, 13, + 13, 11, 10, 11, 11, 11, + 10, 10, 12, 12, 11, 13, + 11, 11, 13, 13, 11, 13, + 13, 11, 10, 11, 15, 10, + 13, 12, 12, 15, 12, 11, + 12, 13, 11, 11, 11, 11, + 10, 10, 13, 13, 14, 14, + 13, 13, 14, 13, 12, 13, + 13, 15, 13, 12, 13, 14, + 14, 13, 11, 12, 13, 15, + 12, 12, 11, 13, 16, 14, + 14, 14, 14, 14, 12, 13, + 13, 13, 12, 12, 14, 14, + 12, 9, 14, 14, 10, 9, + 11, 16, 14, 11, 16, 13, + 13, 10, 11, 12, 15, 14, + 12, 14, 14, 14, 13, 13, + 13, 16, 16, 11, 11, 16, + 15, 12, 9, 13, 14, 10, + 10, 11, 14, 15, 11, 11, + 13, 14, 10, 9, 11, 15, + 15, 11, 10, 13, 12, 9, + 11, 13, 15, 14, 11, 13, + 14, 13, 13, 13, 13, 14, + 13, 16, 13, 15, 13, 12, + 10, 13, 13, 10, 10, 11, + 13, 15, 11, 13, 12, 13, + 13, 13, 12, 13, 13, 12, + 13, 12, 13, 12, 13, 13, + 15, 14, 13, 11, 12, 14, + 14, 11, 12, 14, 16, 13, + 13, 13, 14, 13, 12, 13, + 12, 12, 13, 12, 12, 13, + 14, 12, 10, 13, 13, 11, + 10, 10, 12, 11, 11, 11, + 13, 12, 11, 13, 12, 13, + 12, 12, 11, 13, 12, 10, + 10, 13, 11, 11, 13, 13, + 12, 11, 12, 11, 12, 12, + 10, 10, 10, 11, 11, 11, + 9, 10, 11, 10, 11, 9, + 11, 12, 9, 10, 10, 10, + 10, 11, 12, 13, 14, 12, + 10, 11, 13, 13, 11, 10, + 10, 12, 12, 11, 13, 13, + 13, 12, 10, 11, 11, 10, + 10, 9, 12, 11, 8, +}; + +static const uint16_t on2avc_cb8_syms[ON2AVC_CB8_CODES] = { + 0x0000, 0x0002, 0x0004, 0x000C, 0x000E, 0x0011, + 0x0013, 0x001D, 0x001F, 0x0020, 0x0022, 0x0024, + 0x002C, 0x002E, 0x0031, 0x0033, 0x003D, 0x003F, + 0x0040, 0x0042, 0x0044, 0x004C, 0x004E, 0x00C0, + 0x00C2, 0x00C4, 0x00CC, 0x00CE, 0x00D1, 0x00D3, + 0x00DD, 0x00DF, 0x00E0, 0x00E2, 0x00E4, 0x00EC, + 0x00EE, 0x00F1, 0x00F3, 0x00FD, 0x00FF, 0x0101, + 0x0103, 0x010D, 0x010F, 0x0110, 0x0112, 0x0114, + 0x011C, 0x011E, 0x0121, 0x0123, 0x012D, 0x012F, + 0x0130, 0x0132, 0x0134, 0x013C, 0x013E, 0x0141, + 0x0143, 0x014D, 0x014F, 0x01C1, 0x01C3, 0x01CD, + 0x01CF, 0x01D0, 0x01D2, 0x01D4, 0x01DC, 0x01DE, + 0x01E1, 0x01E3, 0x01ED, 0x01EF, 0x01F0, 0x01F2, + 0x01F4, 0x01FC, 0x01FE, 0x0200, 0x0202, 0x0204, + 0x020C, 0x020E, 0x0211, 0x0213, 0x021D, 0x021F, + 0x0220, 0x0222, 0x0224, 0x022C, 0x022E, 0x0231, + 0x0233, 0x023D, 0x023F, 0x0240, 0x0242, 0x0244, + 0x024C, 0x024E, 0x02C0, 0x02C2, 0x02C4, 0x02CC, + 0x02CE, 0x02D1, 0x02D3, 0x02DD, 0x02DF, 0x02E0, + 0x02E2, 0x02E4, 0x02EC, 0x02EE, 0x02F1, 0x02F3, + 0x02FD, 0x02FF, 0x0301, 0x0303, 0x030D, 0x030F, + 0x0310, 0x0312, 0x0314, 0x031C, 0x031E, 0x0321, + 0x0323, 0x032D, 0x032F, 0x0330, 0x0332, 0x0334, + 0x033C, 0x033E, 0x0341, 0x0343, 0x034D, 0x034F, + 0x03C1, 0x03C3, 0x03CD, 0x03CF, 0x03D0, 0x03D2, + 0x03D4, 0x03DC, 0x03DE, 0x03E1, 0x03E3, 0x03ED, + 0x03EF, 0x03F0, 0x03F2, 0x03F4, 0x03FC, 0x03FE, + 0x0400, 0x0402, 0x0404, 0x040C, 0x040E, 0x0411, + 0x0413, 0x041D, 0x041F, 0x0420, 0x0422, 0x0424, + 0x042C, 0x042E, 0x0431, 0x0433, 0x043D, 0x043F, + 0x0440, 0x0442, 0x0444, 0x044C, 0x044E, 0x04C0, + 0x04C2, 0x04C4, 0x04CC, 0x04CE, 0x04D1, 0x04D3, + 0x04DD, 0x04DF, 0x04E0, 0x04E2, 0x04E4, 0x04EC, + 0x04EE, 0x04F1, 0x04F3, 0x04FD, 0x04FF, 0x0C00, + 0x0C02, 0x0C04, 0x0C0C, 0x0C0E, 0x0C11, 0x0C13, + 0x0C1D, 0x0C1F, 0x0C20, 0x0C22, 0x0C24, 0x0C2C, + 0x0C2E, 0x0C31, 0x0C33, 0x0C3D, 0x0C3F, 0x0C40, + 0x0C42, 0x0C44, 0x0C4C, 0x0C4E, 0x0CC0, 0x0CC2, + 0x0CC4, 0x0CCC, 0x0CCE, 0x0CD1, 0x0CD3, 0x0CDD, + 0x0CDF, 0x0CE0, 0x0CE2, 0x0CE4, 0x0CEC, 0x0CEE, + 0x0CF1, 0x0CF3, 0x0CFD, 0x0CFF, 0x0D01, 0x0D03, + 0x0D0D, 0x0D0F, 0x0D10, 0x0D12, 0x0D14, 0x0D1C, + 0x0D1E, 0x0D21, 0x0D23, 0x0D2D, 0x0D2F, 0x0D30, + 0x0D32, 0x0D34, 0x0D3C, 0x0D3E, 0x0D41, 0x0D43, + 0x0D4D, 0x0D4F, 0x0DC1, 0x0DC3, 0x0DCD, 0x0DCF, + 0x0DD0, 0x0DD2, 0x0DD4, 0x0DDC, 0x0DDE, 0x0DE1, + 0x0DE3, 0x0DED, 0x0DEF, 0x0DF0, 0x0DF2, 0x0DF4, + 0x0DFC, 0x0DFE, 0x0E00, 0x0E02, 0x0E04, 0x0E0C, + 0x0E0E, 0x0E11, 0x0E13, 0x0E1D, 0x0E1F, 0x0E20, + 0x0E22, 0x0E24, 0x0E2C, 0x0E2E, 0x0E31, 0x0E33, + 0x0E3D, 0x0E3F, 0x0E40, 0x0E42, 0x0E44, 0x0E4C, + 0x0E4E, 0x0EC0, 0x0EC2, 0x0EC4, 0x0ECC, 0x0ECE, + 0x0ED1, 0x0ED3, 0x0EDD, 0x0EDF, 0x0EE0, 0x0EE2, + 0x0EE4, 0x0EEC, 0x0EEE, 0x0EF1, 0x0EF3, 0x0EFD, + 0x0EFF, 0x0F01, 0x0F03, 0x0F0D, 0x0F0F, 0x0F10, + 0x0F12, 0x0F14, 0x0F1C, 0x0F1E, 0x0F21, 0x0F23, + 0x0F2D, 0x0F2F, 0x0F30, 0x0F32, 0x0F34, 0x0F3C, + 0x0F3E, 0x0F41, 0x0F43, 0x0F4D, 0x0F4F, 0x0FC1, + 0x0FC3, 0x0FCD, 0x0FCF, 0x0FD0, 0x0FD2, 0x0FD4, + 0x0FDC, 0x0FDE, 0x0FE1, 0x0FE3, 0x0FED, 0x0FEF, + 0x0FF0, 0x0FF2, 0x0FF4, 0x0FFC, 0x0FFE, 0x1001, + 0x1003, 0x100D, 0x100F, 0x1010, 0x1012, 0x1014, + 0x101C, 0x101E, 0x1021, 0x1023, 0x102D, 0x102F, + 0x1030, 0x1032, 0x1034, 0x103C, 0x103E, 0x1041, + 0x1043, 0x104D, 0x104F, 0x10C1, 0x10C3, 0x10CD, + 0x10CF, 0x10D0, 0x10D2, 0x10D4, 0x10DC, 0x10DE, + 0x10E1, 0x10E3, 0x10ED, 0x10EF, 0x10F0, 0x10F2, + 0x10F4, 0x10FC, 0x10FE, 0x1100, 0x1102, 0x1104, + 0x110C, 0x110E, 0x1111, 0x1113, 0x111D, 0x111F, + 0x1120, 0x1122, 0x1124, 0x112C, 0x112E, 0x1131, + 0x1133, 0x113D, 0x113F, 0x1140, 0x1142, 0x1144, + 0x114C, 0x114E, 0x11C0, 0x11C2, 0x11C4, 0x11CC, + 0x11CE, 0x11D1, 0x11D3, 0x11DD, 0x11DF, 0x11E0, + 0x11E2, 0x11E4, 0x11EC, 0x11EE, 0x11F1, 0x11F3, + 0x11FD, 0x11FF, 0x1201, 0x1203, 0x120D, 0x120F, + 0x1210, 0x1212, 0x1214, 0x121C, 0x121E, 0x1221, + 0x1223, 0x122D, 0x122F, 0x1230, 0x1232, 0x1234, + 0x123C, 0x123E, 0x1241, 0x1243, 0x124D, 0x124F, + 0x12C1, 0x12C3, 0x12CD, 0x12CF, 0x12D0, 0x12D2, + 0x12D4, 0x12DC, 0x12DE, 0x12E1, 0x12E3, 0x12ED, + 0x12EF, 0x12F0, 0x12F2, 0x12F4, 0x12FC, 0x12FE, + 0x1300, 0x1302, 0x1304, 0x130C, 0x130E, 0x1311, + 0x1313, 0x131D, 0x131F, 0x1320, 0x1322, 0x1324, + 0x132C, 0x132E, 0x1331, 0x1333, 0x133D, 0x133F, + 0x1340, 0x1342, 0x1344, 0x134C, 0x134E, 0x13C0, + 0x13C2, 0x13C4, 0x13CC, 0x13CE, 0x13D1, 0x13D3, + 0x13DD, 0x13DF, 0x13E0, 0x13E2, 0x13E4, 0x13EC, + 0x13EE, 0x13F1, 0x13F3, 0x13FD, 0x13FF, 0x1401, + 0x1403, 0x140D, 0x140F, 0x1410, 0x1412, 0x1414, + 0x141C, 0x141E, 0x1421, 0x1423, 0x142D, 0x142F, + 0x1430, 0x1432, 0x1434, 0x143C, 0x143E, 0x1441, + 0x1443, 0x144D, 0x144F, 0x14C1, 0x14C3, 0x14CD, + 0x14CF, 0x14D0, 0x14D2, 0x14D4, 0x14DC, 0x14DE, + 0x14E1, 0x14E3, 0x14ED, 0x14EF, 0x14F0, 0x14F2, + 0x14F4, 0x14FC, 0x14FE, 0x1C01, 0x1C03, 0x1C0D, + 0x1C0F, 0x1C10, 0x1C12, 0x1C14, 0x1C1C, 0x1C1E, + 0x1C21, 0x1C23, 0x1C2D, 0x1C2F, 0x1C30, 0x1C32, + 0x1C34, 0x1C3C, 0x1C3E, 0x1C41, 0x1C43, 0x1C4D, + 0x1C4F, 0x1CC1, 0x1CC3, 0x1CCD, 0x1CCF, 0x1CD0, + 0x1CD2, 0x1CD4, 0x1CDC, 0x1CDE, 0x1CE1, 0x1CE3, + 0x1CED, 0x1CEF, 0x1CF0, 0x1CF2, 0x1CF4, 0x1CFC, + 0x1CFE, 0x1D00, 0x1D02, 0x1D04, 0x1D0C, 0x1D0E, + 0x1D11, 0x1D13, 0x1D1D, 0x1D1F, 0x1D20, 0x1D22, + 0x1D24, 0x1D2C, 0x1D2E, 0x1D31, 0x1D33, 0x1D3D, + 0x1D3F, 0x1D40, 0x1D42, 0x1D44, 0x1D4C, 0x1D4E, + 0x1DC0, 0x1DC2, 0x1DC4, 0x1DCC, 0x1DCE, 0x1DD1, + 0x1DD3, 0x1DDD, 0x1DDF, 0x1DE0, 0x1DE2, 0x1DE4, + 0x1DEC, 0x1DEE, 0x1DF1, 0x1DF3, 0x1DFD, 0x1DFF, + 0x1E01, 0x1E03, 0x1E0D, 0x1E0F, 0x1E10, 0x1E12, + 0x1E14, 0x1E1C, 0x1E1E, 0x1E21, 0x1E23, 0x1E2D, + 0x1E2F, 0x1E30, 0x1E32, 0x1E34, 0x1E3C, 0x1E3E, + 0x1E41, 0x1E43, 0x1E4D, 0x1E4F, 0x1EC1, 0x1EC3, + 0x1ECD, 0x1ECF, 0x1ED0, 0x1ED2, 0x1ED4, 0x1EDC, + 0x1EDE, 0x1EE1, 0x1EE3, 0x1EED, 0x1EEF, 0x1EF0, + 0x1EF2, 0x1EF4, 0x1EFC, 0x1EFE, 0x1F00, 0x1F02, + 0x1F04, 0x1F0C, 0x1F0E, 0x1F11, 0x1F13, 0x1F1D, + 0x1F1F, 0x1F20, 0x1F22, 0x1F24, 0x1F2C, 0x1F2E, + 0x1F31, 0x1F33, 0x1F3D, 0x1F3F, 0x1F40, 0x1F42, + 0x1F44, 0x1F4C, 0x1F4E, 0x1FC0, 0x1FC2, 0x1FC4, + 0x1FCC, 0x1FCE, 0x1FD1, 0x1FD3, 0x1FDD, 0x1FDF, + 0x1FE0, 0x1FE2, 0x1FE4, 0x1FEC, 0x1FEE, 0x1FF1, + 0x1FF3, 0x1FFD, 0x1FFF, 0x2000, 0x2002, 0x2004, + 0x200C, 0x200E, 0x2011, 0x2013, 0x201D, 0x201F, + 0x2020, 0x2022, 0x2024, 0x202C, 0x202E, 0x2031, + 0x2033, 0x203D, 0x203F, 0x2040, 0x2042, 0x2044, + 0x204C, 0x204E, 0x20C0, 0x20C2, 0x20C4, 0x20CC, + 0x20CE, 0x20D1, 0x20D3, 0x20DD, 0x20DF, 0x20E0, + 0x20E2, 0x20E4, 0x20EC, 0x20EE, 0x20F1, 0x20F3, + 0x20FD, 0x20FF, 0x2101, 0x2103, 0x210D, 0x210F, + 0x2110, 0x2112, 0x2114, 0x211C, 0x211E, 0x2121, + 0x2123, 0x212D, 0x212F, 0x2130, 0x2132, 0x2134, + 0x213C, 0x213E, 0x2141, 0x2143, 0x214D, 0x214F, + 0x21C1, 0x21C3, 0x21CD, 0x21CF, 0x21D0, 0x21D2, + 0x21D4, 0x21DC, 0x21DE, 0x21E1, 0x21E3, 0x21ED, + 0x21EF, 0x21F0, 0x21F2, 0x21F4, 0x21FC, 0x21FE, + 0x2200, 0x2202, 0x2204, 0x220C, 0x220E, 0x2211, + 0x2213, 0x221D, 0x221F, 0x2220, 0x2222, 0x2224, + 0x222C, 0x222E, 0x2231, 0x2233, 0x223D, 0x223F, + 0x2240, 0x2242, 0x2244, 0x224C, 0x224E, 0x22C0, + 0x22C2, 0x22C4, 0x22CC, 0x22CE, 0x22D1, 0x22D3, + 0x22DD, 0x22DF, 0x22E0, 0x22E2, 0x22E4, 0x22EC, + 0x22EE, 0x22F1, 0x22F3, 0x22FD, 0x22FF, 0x2301, + 0x2303, 0x230D, 0x230F, 0x2310, 0x2312, 0x2314, + 0x231C, 0x231E, 0x2321, 0x2323, 0x232D, 0x232F, + 0x2330, 0x2332, 0x2334, 0x233C, 0x233E, 0x2341, + 0x2343, 0x234D, 0x234F, 0x23C1, 0x23C3, 0x23CD, + 0x23CF, 0x23D0, 0x23D2, 0x23D4, 0x23DC, 0x23DE, + 0x23E1, 0x23E3, 0x23ED, 0x23EF, 0x23F0, 0x23F2, + 0x23F4, 0x23FC, 0x23FE, 0x2400, 0x2402, 0x2404, + 0x240C, 0x240E, 0x2411, 0x2413, 0x241D, 0x241F, + 0x2420, 0x2422, 0x2424, 0x242C, 0x242E, 0x2431, + 0x2433, 0x243D, 0x243F, 0x2440, 0x2442, 0x2444, + 0x244C, 0x244E, 0x24C0, 0x24C2, 0x24C4, 0x24CC, + 0x24CE, 0x24D1, 0x24D3, 0x24DD, 0x24DF, 0x24E0, + 0x24E2, 0x24E4, 0x24EC, 0x24EE, 0x24F1, 0x24F3, + 0x24FD, 0x24FF, 0x2C00, 0x2C02, 0x2C04, 0x2C0C, + 0x2C0E, 0x2C11, 0x2C13, 0x2C1D, 0x2C1F, 0x2C20, + 0x2C22, 0x2C24, 0x2C2C, 0x2C2E, 0x2C31, 0x2C33, + 0x2C3D, 0x2C3F, 0x2C40, 0x2C42, 0x2C44, 0x2C4C, + 0x2C4E, 0x2CC0, 0x2CC2, 0x2CC4, 0x2CCC, 0x2CCE, + 0x2CD1, 0x2CD3, 0x2CDD, 0x2CDF, 0x2CE0, 0x2CE2, + 0x2CE4, 0x2CEC, 0x2CEE, 0x2CF1, 0x2CF3, 0x2CFD, + 0x2CFF, 0x2D01, 0x2D03, 0x2D0D, 0x2D0F, 0x2D10, + 0x2D12, 0x2D14, 0x2D1C, 0x2D1E, 0x2D21, 0x2D23, + 0x2D2D, 0x2D2F, 0x2D30, 0x2D32, 0x2D34, 0x2D3C, + 0x2D3E, 0x2D41, 0x2D43, 0x2D4D, 0x2D4F, 0x2DC1, + 0x2DC3, 0x2DCD, 0x2DCF, 0x2DD0, 0x2DD2, 0x2DD4, + 0x2DDC, 0x2DDE, 0x2DE1, 0x2DE3, 0x2DED, 0x2DEF, + 0x2DF0, 0x2DF2, 0x2DF4, 0x2DFC, 0x2DFE, 0x2E00, + 0x2E02, 0x2E04, 0x2E0C, 0x2E0E, 0x2E11, 0x2E13, + 0x2E1D, 0x2E1F, 0x2E20, 0x2E22, 0x2E24, 0x2E2C, + 0x2E2E, 0x2E31, 0x2E33, 0x2E3D, 0x2E3F, 0x2E40, + 0x2E42, 0x2E44, 0x2E4C, 0x2E4E, 0x2EC0, 0x2EC2, + 0x2EC4, 0x2ECC, 0x2ECE, 0x2ED1, 0x2ED3, 0x2EDD, + 0x2EDF, 0x2EE0, 0x2EE2, 0x2EE4, 0x2EEC, 0x2EEE, + 0x2EF1, 0x2EF3, 0x2EFD, 0x2EFF, 0x2F01, 0x2F03, + 0x2F0D, 0x2F0F, 0x2F10, 0x2F12, 0x2F14, 0x2F1C, + 0x2F1E, 0x2F21, 0x2F23, 0x2F2D, 0x2F2F, 0x2F30, + 0x2F32, 0x2F34, 0x2F3C, 0x2F3E, 0x2F41, 0x2F43, + 0x2F4D, 0x2F4F, 0x2FC1, 0x2FC3, 0x2FCD, 0x2FCF, + 0x2FD0, 0x2FD2, 0x2FD4, 0x2FDC, 0x2FDE, 0x2FE1, + 0x2FE3, 0x2FED, 0x2FEF, 0x2FF0, 0x2FF2, 0x2FF4, + 0x2FFC, 0x2FFE, 0x3001, 0x3003, 0x300D, 0x300F, + 0x3010, 0x3012, 0x3014, 0x301C, 0x301E, 0x3021, + 0x3023, 0x302D, 0x302F, 0x3030, 0x3032, 0x3034, + 0x303C, 0x303E, 0x3041, 0x3043, 0x304D, 0x304F, + 0x30C1, 0x30C3, 0x30CD, 0x30CF, 0x30D0, 0x30D2, + 0x30D4, 0x30DC, 0x30DE, 0x30E1, 0x30E3, 0x30ED, + 0x30EF, 0x30F0, 0x30F2, 0x30F4, 0x30FC, 0x30FE, + 0x3100, 0x3102, 0x3104, 0x310C, 0x310E, 0x3111, + 0x3113, 0x311D, 0x311F, 0x3120, 0x3122, 0x3124, + 0x312C, 0x312E, 0x3131, 0x3133, 0x313D, 0x313F, + 0x3140, 0x3142, 0x3144, 0x314C, 0x314E, 0x31C0, + 0x31C2, 0x31C4, 0x31CC, 0x31CE, 0x31D1, 0x31D3, + 0x31DD, 0x31DF, 0x31E0, 0x31E2, 0x31E4, 0x31EC, + 0x31EE, 0x31F1, 0x31F3, 0x31FD, 0x31FF, 0x3201, + 0x3203, 0x320D, 0x320F, 0x3210, 0x3212, 0x3214, + 0x321C, 0x321E, 0x3221, 0x3223, 0x322D, 0x322F, + 0x3230, 0x3232, 0x3234, 0x323C, 0x323E, 0x3241, + 0x3243, 0x324D, 0x324F, 0x32C1, 0x32C3, 0x32CD, + 0x32CF, 0x32D0, 0x32D2, 0x32D4, 0x32DC, 0x32DE, + 0x32E1, 0x32E3, 0x32ED, 0x32EF, 0x32F0, 0x32F2, + 0x32F4, 0x32FC, 0x32FE, 0x3300, 0x3302, 0x3304, + 0x330C, 0x330E, 0x3311, 0x3313, 0x331D, 0x331F, + 0x3320, 0x3322, 0x3324, 0x332C, 0x332E, 0x3331, + 0x3333, 0x333D, 0x333F, 0x3340, 0x3342, 0x3344, + 0x334C, 0x334E, 0x33C0, 0x33C2, 0x33C4, 0x33CC, + 0x33CE, 0x33D1, 0x33D3, 0x33DD, 0x33DF, 0x33E0, + 0x33E2, 0x33E4, 0x33EC, 0x33EE, 0x33F1, 0x33F3, + 0x33FD, 0x33FF, 0x3401, 0x3403, 0x340D, 0x340F, + 0x3410, 0x3412, 0x3414, 0x341C, 0x341E, 0x3421, + 0x3423, 0x342D, 0x342F, 0x3430, 0x3432, 0x3434, + 0x343C, 0x343E, 0x3441, 0x3443, 0x344D, 0x344F, + 0x34C1, 0x34C3, 0x34CD, 0x34CF, 0x34D0, 0x34D2, + 0x34D4, 0x34DC, 0x34DE, 0x34E1, 0x34E3, 0x34ED, + 0x34EF, 0x34F0, 0x34F2, 0x34F4, 0x34FC, 0x34FE, + 0x3C01, 0x3C03, 0x3C0D, 0x3C0F, 0x3C10, 0x3C12, + 0x3C14, 0x3C1C, 0x3C1E, 0x3C21, 0x3C23, 0x3C2D, + 0x3C2F, 0x3C30, 0x3C32, 0x3C34, 0x3C3C, 0x3C3E, + 0x3C41, 0x3C43, 0x3C4D, 0x3C4F, 0x3CC1, 0x3CC3, + 0x3CCD, 0x3CCF, 0x3CD0, 0x3CD2, 0x3CD4, 0x3CDC, + 0x3CDE, 0x3CE1, 0x3CE3, 0x3CED, 0x3CEF, 0x3CF0, + 0x3CF2, 0x3CF4, 0x3CFC, 0x3CFE, 0x3D00, 0x3D02, + 0x3D04, 0x3D0C, 0x3D0E, 0x3D11, 0x3D13, 0x3D1D, + 0x3D1F, 0x3D20, 0x3D22, 0x3D24, 0x3D2C, 0x3D2E, + 0x3D31, 0x3D33, 0x3D3D, 0x3D3F, 0x3D40, 0x3D42, + 0x3D44, 0x3D4C, 0x3D4E, 0x3DC0, 0x3DC2, 0x3DC4, + 0x3DCC, 0x3DCE, 0x3DD1, 0x3DD3, 0x3DDD, 0x3DDF, + 0x3DE0, 0x3DE2, 0x3DE4, 0x3DEC, 0x3DEE, 0x3DF1, + 0x3DF3, 0x3DFD, 0x3DFF, 0x3E01, 0x3E03, 0x3E0D, + 0x3E0F, 0x3E10, 0x3E12, 0x3E14, 0x3E1C, 0x3E1E, + 0x3E21, 0x3E23, 0x3E2D, 0x3E2F, 0x3E30, 0x3E32, + 0x3E34, 0x3E3C, 0x3E3E, 0x3E41, 0x3E43, 0x3E4D, + 0x3E4F, 0x3EC1, 0x3EC3, 0x3ECD, 0x3ECF, 0x3ED0, + 0x3ED2, 0x3ED4, 0x3EDC, 0x3EDE, 0x3EE1, 0x3EE3, + 0x3EED, 0x3EEF, 0x3EF0, 0x3EF2, 0x3EF4, 0x3EFC, + 0x3EFE, 0x3F00, 0x3F02, 0x3F04, 0x3F0C, 0x3F0E, + 0x3F11, 0x3F13, 0x3F1D, 0x3F1F, 0x3F20, 0x3F22, + 0x3F24, 0x3F2C, 0x3F2E, 0x3F31, 0x3F33, 0x3F3D, + 0x3F3F, 0x3F40, 0x3F42, 0x3F44, 0x3F4C, 0x3F4E, + 0x3FC0, 0x3FC2, 0x3FC4, 0x3FCC, 0x3FCE, 0x3FD1, + 0x3FD3, 0x3FDD, 0x3FDF, 0x3FE0, 0x3FE2, 0x3FE4, + 0x3FEC, 0x3FEE, 0x3FF1, 0x3FF3, 0x3FFD, 0x3FFF, + 0x4000, 0x4002, 0x4004, 0x400C, 0x400E, 0x4011, + 0x4013, 0x401D, 0x401F, 0x4020, 0x4022, 0x4024, + 0x402C, 0x402E, 0x4031, 0x4033, 0x403D, 0x403F, + 0x4040, 0x4042, 0x4044, 0x404C, 0x404E, 0x40C0, + 0x40C2, 0x40C4, 0x40CC, 0x40CE, 0x40D1, 0x40D3, + 0x40DD, 0x40DF, 0x40E0, 0x40E2, 0x40E4, 0x40EC, + 0x40EE, 0x40F1, 0x40F3, 0x40FD, 0x40FF, 0x4101, + 0x4103, 0x410D, 0x410F, 0x4110, 0x4112, 0x4114, + 0x411C, 0x411E, 0x4121, 0x4123, 0x412D, 0x412F, + 0x4130, 0x4132, 0x4134, 0x413C, 0x413E, 0x4141, + 0x4143, 0x414D, 0x414F, 0x41C1, 0x41C3, 0x41CD, + 0x41CF, 0x41D0, 0x41D2, 0x41D4, 0x41DC, 0x41DE, + 0x41E1, 0x41E3, 0x41ED, 0x41EF, 0x41F0, 0x41F2, + 0x41F4, 0x41FC, 0x41FE, 0x4200, 0x4202, 0x4204, + 0x420C, 0x420E, 0x4211, 0x4213, 0x421D, 0x421F, + 0x4220, 0x4222, 0x4224, 0x422C, 0x422E, 0x4231, + 0x4233, 0x423D, 0x423F, 0x4240, 0x4242, 0x4244, + 0x424C, 0x424E, 0x42C0, 0x42C2, 0x42C4, 0x42CC, + 0x42CE, 0x42D1, 0x42D3, 0x42DD, 0x42DF, 0x42E0, + 0x42E2, 0x42E4, 0x42EC, 0x42EE, 0x42F1, 0x42F3, + 0x42FD, 0x42FF, 0x4301, 0x4303, 0x430D, 0x430F, + 0x4310, 0x4312, 0x4314, 0x431C, 0x431E, 0x4321, + 0x4323, 0x432D, 0x432F, 0x4330, 0x4332, 0x4334, + 0x433C, 0x433E, 0x4341, 0x4343, 0x434D, 0x434F, + 0x43C1, 0x43C3, 0x43CD, 0x43CF, 0x43D0, 0x43D2, + 0x43D4, 0x43DC, 0x43DE, 0x43E1, 0x43E3, 0x43ED, + 0x43EF, 0x43F0, 0x43F2, 0x43F4, 0x43FC, 0x43FE, + 0x4400, 0x4402, 0x4404, 0x440C, 0x440E, 0x4411, + 0x4413, 0x441D, 0x441F, 0x4420, 0x4422, 0x4424, + 0x442C, 0x442E, 0x4431, 0x4433, 0x443D, 0x443F, + 0x4440, 0x4442, 0x4444, 0x444C, 0x444E, 0x44C0, + 0x44C2, 0x44C4, 0x44CC, 0x44CE, 0x44D1, 0x44D3, + 0x44DD, 0x44DF, 0x44E0, 0x44E2, 0x44E4, 0x44EC, + 0x44EE, 0x44F1, 0x44F3, 0x44FD, 0x44FF, 0x4C00, + 0x4C02, 0x4C04, 0x4C0C, 0x4C0E, 0x4C11, 0x4C13, + 0x4C1D, 0x4C1F, 0x4C20, 0x4C22, 0x4C24, 0x4C2C, + 0x4C2E, 0x4C31, 0x4C33, 0x4C3D, 0x4C3F, 0x4C40, + 0x4C42, 0x4C44, 0x4C4C, 0x4C4E, 0x4CC0, 0x4CC2, + 0x4CC4, 0x4CCC, 0x4CCE, 0x4CD1, 0x4CD3, 0x4CDD, + 0x4CDF, 0x4CE0, 0x4CE2, 0x4CE4, 0x4CEC, 0x4CEE, + 0x4CF1, 0x4CF3, 0x4CFD, 0x4CFF, 0x4D01, 0x4D03, + 0x4D0D, 0x4D0F, 0x4D10, 0x4D12, 0x4D14, 0x4D1C, + 0x4D1E, 0x4D21, 0x4D23, 0x4D2D, 0x4D2F, 0x4D30, + 0x4D32, 0x4D34, 0x4D3C, 0x4D3E, 0x4D41, 0x4D43, + 0x4D4D, 0x4D4F, 0x4DC1, 0x4DC3, 0x4DCD, 0x4DCF, + 0x4DD0, 0x4DD2, 0x4DD4, 0x4DDC, 0x4DDE, 0x4DE1, + 0x4DE3, 0x4DED, 0x4DEF, 0x4DF0, 0x4DF2, 0x4DF4, + 0x4DFC, 0x4DFE, 0x4E00, 0x4E02, 0x4E04, 0x4E0C, + 0x4E0E, 0x4E11, 0x4E13, 0x4E1D, 0x4E1F, 0x4E20, + 0x4E22, 0x4E24, 0x4E2C, 0x4E2E, 0x4E31, 0x4E33, + 0x4E3D, 0x4E3F, 0x4E40, 0x4E42, 0x4E44, 0x4E4C, + 0x4E4E, 0x4EC0, 0x4EC2, 0x4EC4, 0x4ECC, 0x4ECE, + 0x4ED1, 0x4ED3, 0x4EDD, 0x4EDF, 0x4EE0, 0x4EE2, + 0x4EE4, 0x4EEC, 0x4EEE, 0x4EF1, 0x4EF3, 0x4EFD, + 0x4EFF, 0x4F01, 0x4F03, 0x4F0D, 0x4F0F, 0x4F10, + 0x4F12, 0x4F14, 0x4F1C, 0x4F1E, 0x4F21, 0x4F23, + 0x4F2D, 0x4F2F, 0x4F30, 0x4F32, 0x4F34, 0x4F3C, + 0x4F3E, 0x4F41, 0x4F43, 0x4F4D, 0x4F4F, 0x4FC1, + 0x4FC3, 0x4FCD, 0x4FCF, 0x4FD0, 0x4FD2, 0x4FD4, + 0x4FDC, 0x4FDE, 0x4FE1, 0x4FE3, 0x4FED, 0x4FEF, + 0x4FF0, 0x4FF2, 0x4FF4, 0x4FFC, 0x4FFE, 0xC000, + 0xC002, 0xC004, 0xC00C, 0xC00E, 0xC011, 0xC013, + 0xC01D, 0xC01F, 0xC020, 0xC022, 0xC024, 0xC02C, + 0xC02E, 0xC031, 0xC033, 0xC03D, 0xC03F, 0xC040, + 0xC042, 0xC044, 0xC04C, 0xC04E, 0xC0C0, 0xC0C2, + 0xC0C4, 0xC0CC, 0xC0CE, 0xC0D1, 0xC0D3, 0xC0DD, + 0xC0DF, 0xC0E0, 0xC0E2, 0xC0E4, 0xC0EC, 0xC0EE, + 0xC0F1, 0xC0F3, 0xC0FD, 0xC0FF, 0xC101, 0xC103, + 0xC10D, 0xC10F, 0xC110, 0xC112, 0xC114, 0xC11C, + 0xC11E, 0xC121, 0xC123, 0xC12D, 0xC12F, 0xC130, + 0xC132, 0xC134, 0xC13C, 0xC13E, 0xC141, 0xC143, + 0xC14D, 0xC14F, 0xC1C1, 0xC1C3, 0xC1CD, 0xC1CF, + 0xC1D0, 0xC1D2, 0xC1D4, 0xC1DC, 0xC1DE, 0xC1E1, + 0xC1E3, 0xC1ED, 0xC1EF, 0xC1F0, 0xC1F2, 0xC1F4, + 0xC1FC, 0xC1FE, 0xC200, 0xC202, 0xC204, 0xC20C, + 0xC20E, 0xC211, 0xC213, 0xC21D, 0xC21F, 0xC220, + 0xC222, 0xC224, 0xC22C, 0xC22E, 0xC231, 0xC233, + 0xC23D, 0xC23F, 0xC240, 0xC242, 0xC244, 0xC24C, + 0xC24E, 0xC2C0, 0xC2C2, 0xC2C4, 0xC2CC, 0xC2CE, + 0xC2D1, 0xC2D3, 0xC2DD, 0xC2DF, 0xC2E0, 0xC2E2, + 0xC2E4, 0xC2EC, 0xC2EE, 0xC2F1, 0xC2F3, 0xC2FD, + 0xC2FF, 0xC301, 0xC303, 0xC30D, 0xC30F, 0xC310, + 0xC312, 0xC314, 0xC31C, 0xC31E, 0xC321, 0xC323, + 0xC32D, 0xC32F, 0xC330, 0xC332, 0xC334, 0xC33C, + 0xC33E, 0xC341, 0xC343, 0xC34D, 0xC34F, 0xC3C1, + 0xC3C3, 0xC3CD, 0xC3CF, 0xC3D0, 0xC3D2, 0xC3D4, + 0xC3DC, 0xC3DE, 0xC3E1, 0xC3E3, 0xC3ED, 0xC3EF, + 0xC3F0, 0xC3F2, 0xC3F4, 0xC3FC, 0xC3FE, 0xC400, + 0xC402, 0xC404, 0xC40C, 0xC40E, 0xC411, 0xC413, + 0xC41D, 0xC41F, 0xC420, 0xC422, 0xC424, 0xC42C, + 0xC42E, 0xC431, 0xC433, 0xC43D, 0xC43F, 0xC440, + 0xC442, 0xC444, 0xC44C, 0xC44E, 0xC4C0, 0xC4C2, + 0xC4C4, 0xC4CC, 0xC4CE, 0xC4D1, 0xC4D3, 0xC4DD, + 0xC4DF, 0xC4E0, 0xC4E2, 0xC4E4, 0xC4EC, 0xC4EE, + 0xC4F1, 0xC4F3, 0xC4FD, 0xC4FF, 0xCC00, 0xCC02, + 0xCC04, 0xCC0C, 0xCC0E, 0xCC11, 0xCC13, 0xCC1D, + 0xCC1F, 0xCC20, 0xCC22, 0xCC24, 0xCC2C, 0xCC2E, + 0xCC31, 0xCC33, 0xCC3D, 0xCC3F, 0xCC40, 0xCC42, + 0xCC44, 0xCC4C, 0xCC4E, 0xCCC0, 0xCCC2, 0xCCC4, + 0xCCCC, 0xCCCE, 0xCCD1, 0xCCD3, 0xCCDD, 0xCCDF, + 0xCCE0, 0xCCE2, 0xCCE4, 0xCCEC, 0xCCEE, 0xCCF1, + 0xCCF3, 0xCCFD, 0xCCFF, 0xCD01, 0xCD03, 0xCD0D, + 0xCD0F, 0xCD10, 0xCD12, 0xCD14, 0xCD1C, 0xCD1E, + 0xCD21, 0xCD23, 0xCD2D, 0xCD2F, 0xCD30, 0xCD32, + 0xCD34, 0xCD3C, 0xCD3E, 0xCD41, 0xCD43, 0xCD4D, + 0xCD4F, 0xCDC1, 0xCDC3, 0xCDCD, 0xCDCF, 0xCDD0, + 0xCDD2, 0xCDD4, 0xCDDC, 0xCDDE, 0xCDE1, 0xCDE3, + 0xCDED, 0xCDEF, 0xCDF0, 0xCDF2, 0xCDF4, 0xCDFC, + 0xCDFE, 0xCE00, 0xCE02, 0xCE04, 0xCE0C, 0xCE0E, + 0xCE11, 0xCE13, 0xCE1D, 0xCE1F, 0xCE20, 0xCE22, + 0xCE24, 0xCE2C, 0xCE2E, 0xCE31, 0xCE33, 0xCE3D, + 0xCE3F, 0xCE40, 0xCE42, 0xCE44, 0xCE4C, 0xCE4E, + 0xCEC0, 0xCEC2, 0xCEC4, 0xCECC, 0xCECE, 0xCED1, + 0xCED3, 0xCEDD, 0xCEDF, 0xCEE0, 0xCEE2, 0xCEE4, + 0xCEEC, 0xCEEE, 0xCEF1, 0xCEF3, 0xCEFD, 0xCEFF, + 0xCF01, 0xCF03, 0xCF0D, 0xCF0F, 0xCF10, 0xCF12, + 0xCF14, 0xCF1C, 0xCF1E, 0xCF21, 0xCF23, 0xCF2D, + 0xCF2F, 0xCF30, 0xCF32, 0xCF34, 0xCF3C, 0xCF3E, + 0xCF41, 0xCF43, 0xCF4D, 0xCF4F, 0xCFC1, 0xCFC3, + 0xCFCD, 0xCFCF, 0xCFD0, 0xCFD2, 0xCFD4, 0xCFDC, + 0xCFDE, 0xCFE1, 0xCFE3, 0xCFED, 0xCFEF, 0xCFF0, + 0xCFF2, 0xCFF4, 0xCFFC, 0xCFFE, 0xD001, 0xD003, + 0xD00D, 0xD00F, 0xD010, 0xD012, 0xD014, 0xD01C, + 0xD01E, 0xD021, 0xD023, 0xD02D, 0xD02F, 0xD030, + 0xD032, 0xD034, 0xD03C, 0xD03E, 0xD041, 0xD043, + 0xD04D, 0xD04F, 0xD0C1, 0xD0C3, 0xD0CD, 0xD0CF, + 0xD0D0, 0xD0D2, 0xD0D4, 0xD0DC, 0xD0DE, 0xD0E1, + 0xD0E3, 0xD0ED, 0xD0EF, 0xD0F0, 0xD0F2, 0xD0F4, + 0xD0FC, 0xD0FE, 0xD100, 0xD102, 0xD104, 0xD10C, + 0xD10E, 0xD111, 0xD113, 0xD11D, 0xD11F, 0xD120, + 0xD122, 0xD124, 0xD12C, 0xD12E, 0xD131, 0xD133, + 0xD13D, 0xD13F, 0xD140, 0xD142, 0xD144, 0xD14C, + 0xD14E, 0xD1C0, 0xD1C2, 0xD1C4, 0xD1CC, 0xD1CE, + 0xD1D1, 0xD1D3, 0xD1DD, 0xD1DF, 0xD1E0, 0xD1E2, + 0xD1E4, 0xD1EC, 0xD1EE, 0xD1F1, 0xD1F3, 0xD1FD, + 0xD1FF, 0xD201, 0xD203, 0xD20D, 0xD20F, 0xD210, + 0xD212, 0xD214, 0xD21C, 0xD21E, 0xD221, 0xD223, + 0xD22D, 0xD22F, 0xD230, 0xD232, 0xD234, 0xD23C, + 0xD23E, 0xD241, 0xD243, 0xD24D, 0xD24F, 0xD2C1, + 0xD2C3, 0xD2CD, 0xD2CF, 0xD2D0, 0xD2D2, 0xD2D4, + 0xD2DC, 0xD2DE, 0xD2E1, 0xD2E3, 0xD2ED, 0xD2EF, + 0xD2F0, 0xD2F2, 0xD2F4, 0xD2FC, 0xD2FE, 0xD300, + 0xD302, 0xD304, 0xD30C, 0xD30E, 0xD311, 0xD313, + 0xD31D, 0xD31F, 0xD320, 0xD322, 0xD324, 0xD32C, + 0xD32E, 0xD331, 0xD333, 0xD33D, 0xD33F, 0xD340, + 0xD342, 0xD344, 0xD34C, 0xD34E, 0xD3C0, 0xD3C2, + 0xD3C4, 0xD3CC, 0xD3CE, 0xD3D1, 0xD3D3, 0xD3DD, + 0xD3DF, 0xD3E0, 0xD3E2, 0xD3E4, 0xD3EC, 0xD3EE, + 0xD3F1, 0xD3F3, 0xD3FD, 0xD3FF, 0xD401, 0xD403, + 0xD40D, 0xD40F, 0xD410, 0xD412, 0xD414, 0xD41C, + 0xD41E, 0xD421, 0xD423, 0xD42D, 0xD42F, 0xD430, + 0xD432, 0xD434, 0xD43C, 0xD43E, 0xD441, 0xD443, + 0xD44D, 0xD44F, 0xD4C1, 0xD4C3, 0xD4CD, 0xD4CF, + 0xD4D0, 0xD4D2, 0xD4D4, 0xD4DC, 0xD4DE, 0xD4E1, + 0xD4E3, 0xD4ED, 0xD4EF, 0xD4F0, 0xD4F2, 0xD4F4, + 0xD4FC, 0xD4FE, 0xDC01, 0xDC03, 0xDC0D, 0xDC0F, + 0xDC10, 0xDC12, 0xDC14, 0xDC1C, 0xDC1E, 0xDC21, + 0xDC23, 0xDC2D, 0xDC2F, 0xDC30, 0xDC32, 0xDC34, + 0xDC3C, 0xDC3E, 0xDC41, 0xDC43, 0xDC4D, 0xDC4F, + 0xDCC1, 0xDCC3, 0xDCCD, 0xDCCF, 0xDCD0, 0xDCD2, + 0xDCD4, 0xDCDC, 0xDCDE, 0xDCE1, 0xDCE3, 0xDCED, + 0xDCEF, 0xDCF0, 0xDCF2, 0xDCF4, 0xDCFC, 0xDCFE, + 0xDD00, 0xDD02, 0xDD04, 0xDD0C, 0xDD0E, 0xDD11, + 0xDD13, 0xDD1D, 0xDD1F, 0xDD20, 0xDD22, 0xDD24, + 0xDD2C, 0xDD2E, 0xDD31, 0xDD33, 0xDD3D, 0xDD3F, + 0xDD40, 0xDD42, 0xDD44, 0xDD4C, 0xDD4E, 0xDDC0, + 0xDDC2, 0xDDC4, 0xDDCC, 0xDDCE, 0xDDD1, 0xDDD3, + 0xDDDD, 0xDDDF, 0xDDE0, 0xDDE2, 0xDDE4, 0xDDEC, + 0xDDEE, 0xDDF1, 0xDDF3, 0xDDFD, 0xDDFF, 0xDE01, + 0xDE03, 0xDE0D, 0xDE0F, 0xDE10, 0xDE12, 0xDE14, + 0xDE1C, 0xDE1E, 0xDE21, 0xDE23, 0xDE2D, 0xDE2F, + 0xDE30, 0xDE32, 0xDE34, 0xDE3C, 0xDE3E, 0xDE41, + 0xDE43, 0xDE4D, 0xDE4F, 0xDEC1, 0xDEC3, 0xDECD, + 0xDECF, 0xDED0, 0xDED2, 0xDED4, 0xDEDC, 0xDEDE, + 0xDEE1, 0xDEE3, 0xDEED, 0xDEEF, 0xDEF0, 0xDEF2, + 0xDEF4, 0xDEFC, 0xDEFE, 0xDF00, 0xDF02, 0xDF04, + 0xDF0C, 0xDF0E, 0xDF11, 0xDF13, 0xDF1D, 0xDF1F, + 0xDF20, 0xDF22, 0xDF24, 0xDF2C, 0xDF2E, 0xDF31, + 0xDF33, 0xDF3D, 0xDF3F, 0xDF40, 0xDF42, 0xDF44, + 0xDF4C, 0xDF4E, 0xDFC0, 0xDFC2, 0xDFC4, 0xDFCC, + 0xDFCE, 0xDFD1, 0xDFD3, 0xDFDD, 0xDFDF, 0xDFE0, + 0xDFE2, 0xDFE4, 0xDFEC, 0xDFEE, 0xDFF1, 0xDFF3, + 0xDFFD, 0xDFFF, 0xE000, 0xE002, 0xE004, 0xE00C, + 0xE00E, 0xE011, 0xE013, 0xE01D, 0xE01F, 0xE020, + 0xE022, 0xE024, 0xE02C, 0xE02E, 0xE031, 0xE033, + 0xE03D, 0xE03F, 0xE040, 0xE042, 0xE044, 0xE04C, + 0xE04E, 0xE0C0, 0xE0C2, 0xE0C4, 0xE0CC, 0xE0CE, + 0xE0D1, 0xE0D3, 0xE0DD, 0xE0DF, 0xE0E0, 0xE0E2, + 0xE0E4, 0xE0EC, 0xE0EE, 0xE0F1, 0xE0F3, 0xE0FD, + 0xE0FF, 0xE101, 0xE103, 0xE10D, 0xE10F, 0xE110, + 0xE112, 0xE114, 0xE11C, 0xE11E, 0xE121, 0xE123, + 0xE12D, 0xE12F, 0xE130, 0xE132, 0xE134, 0xE13C, + 0xE13E, 0xE141, 0xE143, 0xE14D, 0xE14F, 0xE1C1, + 0xE1C3, 0xE1CD, 0xE1CF, 0xE1D0, 0xE1D2, 0xE1D4, + 0xE1DC, 0xE1DE, 0xE1E1, 0xE1E3, 0xE1ED, 0xE1EF, + 0xE1F0, 0xE1F2, 0xE1F4, 0xE1FC, 0xE1FE, 0xE200, + 0xE202, 0xE204, 0xE20C, 0xE20E, 0xE211, 0xE213, + 0xE21D, 0xE21F, 0xE220, 0xE222, 0xE224, 0xE22C, + 0xE22E, 0xE231, 0xE233, 0xE23D, 0xE23F, 0xE240, + 0xE242, 0xE244, 0xE24C, 0xE24E, 0xE2C0, 0xE2C2, + 0xE2C4, 0xE2CC, 0xE2CE, 0xE2D1, 0xE2D3, 0xE2DD, + 0xE2DF, 0xE2E0, 0xE2E2, 0xE2E4, 0xE2EC, 0xE2EE, + 0xE2F1, 0xE2F3, 0xE2FD, 0xE2FF, 0xE301, 0xE303, + 0xE30D, 0xE30F, 0xE310, 0xE312, 0xE314, 0xE31C, + 0xE31E, 0xE321, 0xE323, 0xE32D, 0xE32F, 0xE330, + 0xE332, 0xE334, 0xE33C, 0xE33E, 0xE341, 0xE343, + 0xE34D, 0xE34F, 0xE3C1, 0xE3C3, 0xE3CD, 0xE3CF, + 0xE3D0, 0xE3D2, 0xE3D4, 0xE3DC, 0xE3DE, 0xE3E1, + 0xE3E3, 0xE3ED, 0xE3EF, 0xE3F0, 0xE3F2, 0xE3F4, + 0xE3FC, 0xE3FE, 0xE400, 0xE402, 0xE404, 0xE40C, + 0xE40E, 0xE411, 0xE413, 0xE41D, 0xE41F, 0xE420, + 0xE422, 0xE424, 0xE42C, 0xE42E, 0xE431, 0xE433, + 0xE43D, 0xE43F, 0xE440, 0xE442, 0xE444, 0xE44C, + 0xE44E, 0xE4C0, 0xE4C2, 0xE4C4, 0xE4CC, 0xE4CE, + 0xE4D1, 0xE4D3, 0xE4DD, 0xE4DF, 0xE4E0, 0xE4E2, + 0xE4E4, 0xE4EC, 0xE4EE, 0xE4F1, 0xE4F3, 0xE4FD, + 0xE4FF, 0xEC00, 0xEC02, 0xEC04, 0xEC0C, 0xEC0E, + 0xEC11, 0xEC13, 0xEC1D, 0xEC1F, 0xEC20, 0xEC22, + 0xEC24, 0xEC2C, 0xEC2E, 0xEC31, 0xEC33, 0xEC3D, + 0xEC3F, 0xEC40, 0xEC42, 0xEC44, 0xEC4C, 0xEC4E, + 0xECC0, 0xECC2, 0xECC4, 0xECCC, 0xECCE, 0xECD1, + 0xECD3, 0xECDD, 0xECDF, 0xECE0, 0xECE2, 0xECE4, + 0xECEC, 0xECEE, 0xECF1, 0xECF3, 0xECFD, 0xECFF, + 0xED01, 0xED03, 0xED0D, 0xED0F, 0xED10, 0xED12, + 0xED14, 0xED1C, 0xED1E, 0xED21, 0xED23, 0xED2D, + 0xED2F, 0xED30, 0xED32, 0xED34, 0xED3C, 0xED3E, + 0xED41, 0xED43, 0xED4D, 0xED4F, 0xEDC1, 0xEDC3, + 0xEDCD, 0xEDCF, 0xEDD0, 0xEDD2, 0xEDD4, 0xEDDC, + 0xEDDE, 0xEDE1, 0xEDE3, 0xEDED, 0xEDEF, 0xEDF0, + 0xEDF2, 0xEDF4, 0xEDFC, 0xEDFE, 0xEE00, 0xEE02, + 0xEE04, 0xEE0C, 0xEE0E, 0xEE11, 0xEE13, 0xEE1D, + 0xEE1F, 0xEE20, 0xEE22, 0xEE24, 0xEE2C, 0xEE2E, + 0xEE31, 0xEE33, 0xEE3D, 0xEE3F, 0xEE40, 0xEE42, + 0xEE44, 0xEE4C, 0xEE4E, 0xEEC0, 0xEEC2, 0xEEC4, + 0xEECC, 0xEECE, 0xEED1, 0xEED3, 0xEEDD, 0xEEDF, + 0xEEE0, 0xEEE2, 0xEEE4, 0xEEEC, 0xEEEE, 0xEEF1, + 0xEEF3, 0xEEFD, 0xEEFF, 0xEF01, 0xEF03, 0xEF0D, + 0xEF0F, 0xEF10, 0xEF12, 0xEF14, 0xEF1C, 0xEF1E, + 0xEF21, 0xEF23, 0xEF2D, 0xEF2F, 0xEF30, 0xEF32, + 0xEF34, 0xEF3C, 0xEF3E, 0xEF41, 0xEF43, 0xEF4D, + 0xEF4F, 0xEFC1, 0xEFC3, 0xEFCD, 0xEFCF, 0xEFD0, + 0xEFD2, 0xEFD4, 0xEFDC, 0xEFDE, 0xEFE1, 0xEFE3, + 0xEFED, 0xEFEF, 0xEFF0, 0xEFF2, 0xEFF4, 0xEFFC, + 0xEFFE, 0xF001, 0xF003, 0xF00D, 0xF00F, 0xF010, + 0xF012, 0xF014, 0xF01C, 0xF01E, 0xF021, 0xF023, + 0xF02D, 0xF02F, 0xF030, 0xF032, 0xF034, 0xF03C, + 0xF03E, 0xF041, 0xF043, 0xF04D, 0xF04F, 0xF0C1, + 0xF0C3, 0xF0CD, 0xF0CF, 0xF0D0, 0xF0D2, 0xF0D4, + 0xF0DC, 0xF0DE, 0xF0E1, 0xF0E3, 0xF0ED, 0xF0EF, + 0xF0F0, 0xF0F2, 0xF0F4, 0xF0FC, 0xF0FE, 0xF100, + 0xF102, 0xF104, 0xF10C, 0xF10E, 0xF111, 0xF113, + 0xF11D, 0xF11F, 0xF120, 0xF122, 0xF124, 0xF12C, + 0xF12E, 0xF131, 0xF133, 0xF13D, 0xF13F, 0xF140, + 0xF142, 0xF144, 0xF14C, 0xF14E, 0xF1C0, 0xF1C2, + 0xF1C4, 0xF1CC, 0xF1CE, 0xF1D1, 0xF1D3, 0xF1DD, + 0xF1DF, 0xF1E0, 0xF1E2, 0xF1E4, 0xF1EC, 0xF1EE, + 0xF1F1, 0xF1F3, 0xF1FD, 0xF1FF, 0xF201, 0xF203, + 0xF20D, 0xF20F, 0xF210, 0xF212, 0xF214, 0xF21C, + 0xF21E, 0xF221, 0xF223, 0xF22D, 0xF22F, 0xF230, + 0xF232, 0xF234, 0xF23C, 0xF23E, 0xF241, 0xF243, + 0xF24D, 0xF24F, 0xF2C1, 0xF2C3, 0xF2CD, 0xF2CF, + 0xF2D0, 0xF2D2, 0xF2D4, 0xF2DC, 0xF2DE, 0xF2E1, + 0xF2E3, 0xF2ED, 0xF2EF, 0xF2F0, 0xF2F2, 0xF2F4, + 0xF2FC, 0xF2FE, 0xF300, 0xF302, 0xF304, 0xF30C, + 0xF30E, 0xF311, 0xF313, 0xF31D, 0xF31F, 0xF320, + 0xF322, 0xF324, 0xF32C, 0xF32E, 0xF331, 0xF333, + 0xF33D, 0xF33F, 0xF340, 0xF342, 0xF344, 0xF34C, + 0xF34E, 0xF3C0, 0xF3C2, 0xF3C4, 0xF3CC, 0xF3CE, + 0xF3D1, 0xF3D3, 0xF3DD, 0xF3DF, 0xF3E0, 0xF3E2, + 0xF3E4, 0xF3EC, 0xF3EE, 0xF3F1, 0xF3F3, 0xF3FD, + 0xF3FF, 0xF401, 0xF403, 0xF40D, 0xF40F, 0xF410, + 0xF412, 0xF414, 0xF41C, 0xF41E, 0xF421, 0xF423, + 0xF42D, 0xF42F, 0xF430, 0xF432, 0xF434, 0xF43C, + 0xF43E, 0xF441, 0xF443, 0xF44D, 0xF44F, 0xF4C1, + 0xF4C3, 0xF4CD, 0xF4CF, 0xF4D0, 0xF4D2, 0xF4D4, + 0xF4DC, 0xF4DE, 0xF4E1, 0xF4E3, 0xF4ED, 0xF4EF, + 0xF4F0, 0xF4F2, 0xF4F4, 0xF4FC, 0xF4FE, 0xFC01, + 0xFC03, 0xFC0D, 0xFC0F, 0xFC10, 0xFC12, 0xFC14, + 0xFC1C, 0xFC1E, 0xFC21, 0xFC23, 0xFC2D, 0xFC2F, + 0xFC30, 0xFC32, 0xFC34, 0xFC3C, 0xFC3E, 0xFC41, + 0xFC43, 0xFC4D, 0xFC4F, 0xFCC1, 0xFCC3, 0xFCCD, + 0xFCCF, 0xFCD0, 0xFCD2, 0xFCD4, 0xFCDC, 0xFCDE, + 0xFCE1, 0xFCE3, 0xFCED, 0xFCEF, 0xFCF0, 0xFCF2, + 0xFCF4, 0xFCFC, 0xFCFE, 0xFD00, 0xFD02, 0xFD04, + 0xFD0C, 0xFD0E, 0xFD11, 0xFD13, 0xFD1D, 0xFD1F, + 0xFD20, 0xFD22, 0xFD24, 0xFD2C, 0xFD2E, 0xFD31, + 0xFD33, 0xFD3D, 0xFD3F, 0xFD40, 0xFD42, 0xFD44, + 0xFD4C, 0xFD4E, 0xFDC0, 0xFDC2, 0xFDC4, 0xFDCC, + 0xFDCE, 0xFDD1, 0xFDD3, 0xFDDD, 0xFDDF, 0xFDE0, + 0xFDE2, 0xFDE4, 0xFDEC, 0xFDEE, 0xFDF1, 0xFDF3, + 0xFDFD, 0xFDFF, 0xFE01, 0xFE03, 0xFE0D, 0xFE0F, + 0xFE10, 0xFE12, 0xFE14, 0xFE1C, 0xFE1E, 0xFE21, + 0xFE23, 0xFE2D, 0xFE2F, 0xFE30, 0xFE32, 0xFE34, + 0xFE3C, 0xFE3E, 0xFE41, 0xFE43, 0xFE4D, 0xFE4F, + 0xFEC1, 0xFEC3, 0xFECD, 0xFECF, 0xFED0, 0xFED2, + 0xFED4, 0xFEDC, 0xFEDE, 0xFEE1, 0xFEE3, 0xFEED, + 0xFEEF, 0xFEF0, 0xFEF2, 0xFEF4, 0xFEFC, 0xFEFE, + 0xFF00, 0xFF02, 0xFF04, 0xFF0C, 0xFF0E, 0xFF11, + 0xFF13, 0xFF1D, 0xFF1F, 0xFF20, 0xFF22, 0xFF24, + 0xFF2C, 0xFF2E, 0xFF31, 0xFF33, 0xFF3D, 0xFF3F, + 0xFF40, 0xFF42, 0xFF44, 0xFF4C, 0xFF4E, 0xFFC0, + 0xFFC2, 0xFFC4, 0xFFCC, 0xFFCE, 0xFFD1, 0xFFD3, + 0xFFDD, 0xFFDF, 0xFFE0, 0xFFE2, 0xFFE4, 0xFFEC, + 0xFFEE, 0xFFF1, 0xFFF3, 0xFFFD, 0xFFFF, +}; + +#define ON2AVC_CB9_CODES 121 +static const uint16_t on2avc_cb9_codes[ON2AVC_CB9_CODES] = { + 0x0000, 0x000F, 0x0098, 0x026E, 0x045C, 0x00A6, + 0x00AC, 0x045D, 0x027E, 0x009A, 0x0012, 0x000E, + 0x001A, 0x00DE, 0x022C, 0x053E, 0x00A2, 0x009E, + 0x0538, 0x01B2, 0x00BA, 0x0018, 0x00AD, 0x00BF, + 0x01BE, 0x037E, 0x05C6, 0x0132, 0x0112, 0x08B5, + 0x0457, 0x01B6, 0x00BC, 0x02AE, 0x022A, 0x045E, + 0x08B6, 0x08FA, 0x0147, 0x013E, 0x119F, 0x05C7, + 0x044F, 0x0170, 0x0456, 0x047F, 0x06C7, 0x0A72, + 0x0D8B, 0x0267, 0x0266, 0x0D8A, 0x08B7, 0x05CF, + 0x045F, 0x0054, 0x00A4, 0x0118, 0x0142, 0x0234, + 0x036F, 0x036E, 0x029E, 0x0156, 0x0114, 0x0088, + 0x00A0, 0x00A5, 0x00DA, 0x015F, 0x026F, 0x02E2, + 0x02E6, 0x0236, 0x015E, 0x0143, 0x00AA, 0x053A, + 0x0466, 0x04FE, 0x09FE, 0x119E, 0x0232, 0x0237, + 0x0A73, 0x09FF, 0x08B4, 0x046B, 0x02AF, 0x01B0, + 0x037F, 0x053F, 0x08FB, 0x0136, 0x0146, 0x08CE, + 0x05CE, 0x044E, 0x01B3, 0x008E, 0x00DD, 0x0226, + 0x047E, 0x06C6, 0x00AE, 0x011E, 0x06C4, 0x047C, + 0x0172, 0x00BE, 0x0010, 0x0016, 0x00BD, 0x0176, + 0x053B, 0x009D, 0x009C, 0x046A, 0x0177, 0x00DC, + 0x0019, +}; + +static const uint8_t on2avc_cb9_bits[ON2AVC_CB9_CODES] = { + 1, 4, 8, 10, 11, 8, + 8, 11, 10, 8, 5, 4, + 5, 8, 10, 11, 8, 8, + 11, 9, 8, 5, 8, 8, + 9, 10, 11, 9, 9, 12, + 11, 9, 8, 10, 10, 11, + 12, 12, 9, 9, 13, 11, + 11, 9, 11, 11, 11, 12, + 12, 10, 10, 12, 12, 11, + 11, 7, 8, 9, 9, 10, + 10, 10, 10, 9, 9, 8, + 8, 8, 8, 9, 10, 10, + 10, 10, 9, 9, 8, 11, + 11, 11, 12, 13, 10, 10, + 12, 12, 12, 11, 10, 9, + 10, 11, 12, 9, 9, 12, + 11, 11, 9, 8, 8, 10, + 11, 11, 8, 9, 11, 11, + 9, 8, 5, 5, 8, 9, + 11, 8, 8, 11, 9, 8, + 5, +}; + +static const uint16_t on2avc_cb9_syms[ON2AVC_CB9_CODES] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x0100, + 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x01FB, + 0x01FC, 0x01FD, 0x01FE, 0x01FF, 0x0200, 0x0201, + 0x0202, 0x0203, 0x0204, 0x0205, 0x02FB, 0x02FC, + 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, + 0x0303, 0x0304, 0x0305, 0x03FB, 0x03FC, 0x03FD, + 0x03FE, 0x03FF, 0x0400, 0x0401, 0x0402, 0x0403, + 0x0404, 0x0405, 0x04FB, 0x04FC, 0x04FD, 0x04FE, + 0x04FF, 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, + 0x0505, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, + 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0xFB05, + 0xFBFB, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, + 0xFC01, 0xFC02, 0xFC03, 0xFC04, 0xFC05, 0xFCFB, + 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, 0xFD00, 0xFD01, + 0xFD02, 0xFD03, 0xFD04, 0xFD05, 0xFDFB, 0xFDFC, + 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, 0xFE01, 0xFE02, + 0xFE03, 0xFE04, 0xFE05, 0xFEFB, 0xFEFC, 0xFEFD, + 0xFEFE, 0xFEFF, 0xFF00, 0xFF01, 0xFF02, 0xFF03, + 0xFF04, 0xFF05, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, + 0xFFFF, +}; + +#define ON2AVC_CB10_CODES 121 +static const uint16_t on2avc_cb10_codes[ON2AVC_CB10_CODES] = { + 0x002E, 0x001A, 0x003C, 0x001F, 0x006E, 0x002E, + 0x00AE, 0x006F, 0x002A, 0x003E, 0x0014, 0x0016, + 0x0002, 0x000E, 0x004E, 0x00F7, 0x0042, 0x0027, + 0x00F6, 0x0046, 0x0014, 0x0008, 0x0032, 0x0016, + 0x0030, 0x0012, 0x0056, 0x0018, 0x005F, 0x00DE, + 0x006E, 0x0036, 0x001A, 0x0023, 0x003D, 0x003F, + 0x007A, 0x008E, 0x0071, 0x0006, 0x0012, 0x000F, + 0x0043, 0x003E, 0x00AE, 0x0001, 0x00AB, 0x00C7, + 0x0013, 0x000A, 0x0002, 0x01CA, 0x0003, 0x0000, + 0x000F, 0x0022, 0x0016, 0x002A, 0x007F, 0x001C, + 0x0036, 0x00AF, 0x00C6, 0x000E, 0x0010, 0x0006, + 0x008F, 0x001E, 0x0054, 0x000D, 0x00AA, 0x0056, + 0x00AC, 0x001D, 0x0076, 0x0013, 0x004F, 0x0057, + 0x00E6, 0x00EE, 0x000E, 0x01CB, 0x00AF, 0x000B, + 0x0007, 0x00EF, 0x00AD, 0x00E4, 0x0008, 0x005E, + 0x0070, 0x001E, 0x00DF, 0x000C, 0x007E, 0x00CE, + 0x0002, 0x001A, 0x003C, 0x0002, 0x0020, 0x003A, + 0x004D, 0x00CF, 0x0066, 0x0026, 0x002F, 0x001F, + 0x0022, 0x001B, 0x0012, 0x000E, 0x0017, 0x0062, + 0x00E7, 0x0019, 0x0014, 0x0006, 0x004C, 0x0012, + 0x000C, +}; + +static const uint8_t on2avc_cb10_bits[ON2AVC_CB10_CODES] = { + 6, 5, 6, 8, 9, 8, + 8, 9, 8, 6, 5, 5, + 5, 6, 7, 8, 7, 7, + 8, 7, 6, 5, 6, 6, + 6, 7, 8, 7, 7, 8, + 7, 6, 6, 8, 7, 7, + 7, 8, 7, 8, 9, 8, + 7, 7, 9, 9, 8, 8, + 9, 8, 9, 9, 9, 9, + 9, 8, 7, 7, 7, 8, + 8, 9, 8, 8, 7, 6, + 8, 7, 7, 8, 8, 9, + 8, 8, 7, 7, 7, 9, + 8, 8, 9, 9, 8, 8, + 9, 8, 8, 8, 8, 7, + 7, 8, 8, 8, 7, 8, + 8, 7, 7, 7, 6, 6, + 7, 8, 7, 7, 8, 7, + 6, 6, 5, 5, 6, 7, + 8, 7, 7, 9, 7, 6, + 5, +}; + +static const uint16_t on2avc_cb10_syms[ON2AVC_CB10_CODES] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x0100, + 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x01FB, + 0x01FC, 0x01FD, 0x01FE, 0x01FF, 0x0200, 0x0201, + 0x0202, 0x0203, 0x0204, 0x0205, 0x02FB, 0x02FC, + 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, + 0x0303, 0x0304, 0x0305, 0x03FB, 0x03FC, 0x03FD, + 0x03FE, 0x03FF, 0x0400, 0x0401, 0x0402, 0x0403, + 0x0404, 0x0405, 0x04FB, 0x04FC, 0x04FD, 0x04FE, + 0x04FF, 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, + 0x0505, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, + 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0xFB05, + 0xFBFB, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, + 0xFC01, 0xFC02, 0xFC03, 0xFC04, 0xFC05, 0xFCFB, + 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, 0xFD00, 0xFD01, + 0xFD02, 0xFD03, 0xFD04, 0xFD05, 0xFDFB, 0xFDFC, + 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, 0xFE01, 0xFE02, + 0xFE03, 0xFE04, 0xFE05, 0xFEFB, 0xFEFC, 0xFEFD, + 0xFEFE, 0xFEFF, 0xFF00, 0xFF01, 0xFF02, 0xFF03, + 0xFF04, 0xFF05, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, + 0xFFFF, +}; + +#define ON2AVC_CB11_CODES 225 +static const uint16_t on2avc_cb11_codes[ON2AVC_CB11_CODES] = { + 0x0000, 0x000E, 0x0056, 0x00CD, 0x0173, 0x0232, + 0x00C7, 0x014F, 0x01AA, 0x00BE, 0x026F, 0x0192, + 0x00BC, 0x0058, 0x000F, 0x000C, 0x0010, 0x004E, + 0x0082, 0x0142, 0x01BF, 0x0098, 0x015E, 0x0136, + 0x0086, 0x01BB, 0x014E, 0x00BA, 0x003E, 0x0012, + 0x0054, 0x0036, 0x0050, 0x008F, 0x014B, 0x0262, + 0x00AA, 0x015C, 0x013E, 0x00B7, 0x02BE, 0x0176, + 0x00A2, 0x0058, 0x003C, 0x00C2, 0x00A6, 0x008A, + 0x00B2, 0x0122, 0x02AC, 0x00CA, 0x012F, 0x014A, + 0x00DC, 0x02DE, 0x017A, 0x0134, 0x0092, 0x00B4, + 0x0166, 0x0148, 0x016E, 0x013F, 0x0134, 0x02FF, + 0x014F, 0x019E, 0x0267, 0x016C, 0x02A6, 0x02CE, + 0x013A, 0x010A, 0x0108, 0x026E, 0x02CB, 0x028E, + 0x02CF, 0x020F, 0x02DF, 0x010B, 0x02AD, 0x0227, + 0x018A, 0x04DB, 0x02A7, 0x02FE, 0x0236, 0x026C, + 0x00C6, 0x009C, 0x00C4, 0x00CE, 0x00D6, 0x0135, + 0x0156, 0x025A, 0x02FF, 0x0286, 0x015F, 0x0132, + 0x00D7, 0x00AC, 0x00A2, 0x0176, 0x0118, 0x0123, + 0x0157, 0x01BC, 0x02AE, 0x02EE, 0x04DA, 0x0467, + 0x033F, 0x0287, 0x0193, 0x0182, 0x013B, 0x0112, + 0x0133, 0x017D, 0x0117, 0x0186, 0x026E, 0x025B, + 0x02EF, 0x0466, 0x0316, 0x0237, 0x02F6, 0x01BA, + 0x015D, 0x012E, 0x015A, 0x014A, 0x008E, 0x00B6, + 0x0135, 0x0100, 0x017B, 0x028C, 0x033E, 0x0297, + 0x015B, 0x0102, 0x0140, 0x00D4, 0x00BA, 0x0088, + 0x02EE, 0x0283, 0x02BF, 0x020E, 0x02CE, 0x0317, + 0x0172, 0x0296, 0x026F, 0x0101, 0x02CF, 0x02F7, + 0x01BD, 0x02EF, 0x028F, 0x0263, 0x0164, 0x011A, + 0x0147, 0x0292, 0x02FE, 0x015E, 0x02AF, 0x01AB, + 0x0130, 0x02CA, 0x0183, 0x014E, 0x017C, 0x017E, + 0x00C8, 0x00AA, 0x009E, 0x0132, 0x0152, 0x0226, + 0x00CC, 0x017E, 0x0187, 0x00CB, 0x0293, 0x0106, + 0x00C0, 0x0087, 0x00BC, 0x005C, 0x003D, 0x005A, + 0x00A8, 0x0103, 0x028D, 0x00A4, 0x0116, 0x0146, + 0x00B8, 0x01BE, 0x016D, 0x0093, 0x004A, 0x003F, + 0x000D, 0x0011, 0x004F, 0x00AE, 0x0166, 0x0266, + 0x0090, 0x0109, 0x012C, 0x00A6, 0x0282, 0x017A, + 0x00B5, 0x0034, 0x000E, +}; + +static const uint8_t on2avc_cb11_bits[ON2AVC_CB11_CODES] = { + 2, 4, 7, 9, 10, 11, + 9, 10, 10, 9, 11, 10, + 9, 7, 4, 4, 5, 7, + 9, 9, 10, 9, 10, 10, + 9, 10, 9, 8, 7, 5, + 7, 7, 8, 9, 9, 10, + 9, 10, 10, 9, 10, 9, + 9, 8, 7, 9, 8, 9, + 9, 10, 10, 9, 10, 10, + 9, 10, 10, 9, 9, 8, + 10, 9, 9, 10, 10, 10, + 9, 10, 10, 9, 11, 10, + 10, 10, 10, 11, 10, 10, + 10, 11, 10, 10, 10, 11, + 10, 11, 11, 10, 11, 10, + 9, 9, 9, 9, 9, 10, + 10, 11, 11, 10, 10, 10, + 9, 9, 8, 10, 10, 10, + 10, 10, 10, 10, 11, 12, + 11, 10, 10, 10, 10, 10, + 10, 9, 10, 10, 10, 11, + 11, 12, 11, 11, 10, 10, + 10, 10, 10, 9, 9, 9, + 9, 10, 10, 10, 11, 11, + 10, 10, 9, 9, 9, 9, + 11, 10, 10, 11, 11, 11, + 10, 11, 10, 10, 11, 10, + 10, 10, 10, 10, 9, 10, + 10, 10, 11, 9, 10, 10, + 9, 10, 10, 10, 9, 9, + 9, 8, 9, 9, 10, 11, + 9, 10, 10, 9, 10, 10, + 9, 9, 8, 7, 7, 8, + 9, 10, 10, 9, 10, 10, + 9, 10, 9, 9, 8, 7, + 4, 5, 7, 8, 9, 10, + 9, 10, 10, 9, 10, 9, + 8, 7, 5, +}; + +static const uint16_t on2avc_cb11_syms[ON2AVC_CB11_CODES] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x00F9, 0x00FA, 0x00FB, 0x00FC, + 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x0101, 0x0102, + 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x01F9, + 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, + 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, + 0x0206, 0x0207, 0x02F9, 0x02FA, 0x02FB, 0x02FC, + 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, + 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x03F9, + 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, + 0x0406, 0x0407, 0x04F9, 0x04FA, 0x04FB, 0x04FC, + 0x04FD, 0x04FE, 0x04FF, 0x0500, 0x0501, 0x0502, + 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x05F9, + 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, + 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, + 0x0606, 0x0607, 0x06F9, 0x06FA, 0x06FB, 0x06FC, + 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, + 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x07F9, + 0x07FA, 0x07FB, 0x07FC, 0x07FD, 0x07FE, 0x07FF, + 0xF900, 0xF901, 0xF902, 0xF903, 0xF904, 0xF905, + 0xF906, 0xF907, 0xF9F9, 0xF9FA, 0xF9FB, 0xF9FC, + 0xF9FD, 0xF9FE, 0xF9FF, 0xFA00, 0xFA01, 0xFA02, + 0xFA03, 0xFA04, 0xFA05, 0xFA06, 0xFA07, 0xFAF9, + 0xFAFA, 0xFAFB, 0xFAFC, 0xFAFD, 0xFAFE, 0xFAFF, + 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0xFB05, + 0xFB06, 0xFB07, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, + 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, 0xFC01, 0xFC02, + 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFCF9, + 0xFCFA, 0xFCFB, 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, + 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04, 0xFD05, + 0xFD06, 0xFD07, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, + 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, 0xFE01, 0xFE02, + 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFEF9, + 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0xFEFF, + 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, + 0xFF06, 0xFF07, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, + 0xFFFD, 0xFFFE, 0xFFFF, +}; + +#define ON2AVC_CB12_CODES 441 +static const uint16_t on2avc_cb12_codes[ON2AVC_CB12_CODES] = { + 0x0000, 0x000C, 0x004F, 0x0156, 0x02E6, 0x0462, + 0x044C, 0x086A, 0x0222, 0x0228, 0x047F, 0x037A, + 0x028F, 0x02B8, 0x0BB7, 0x04B7, 0x02DA, 0x0262, + 0x0124, 0x0052, 0x000F, 0x000D, 0x000E, 0x0058, + 0x00A2, 0x0129, 0x02C8, 0x0256, 0x044D, 0x016E, + 0x02AA, 0x02BE, 0x027F, 0x02A9, 0x016E, 0x0597, + 0x02EE, 0x02EE, 0x013A, 0x00A4, 0x004E, 0x000C, + 0x0056, 0x004B, 0x0058, 0x0125, 0x010E, 0x01A7, + 0x026A, 0x0415, 0x010C, 0x0228, 0x0446, 0x0232, + 0x017E, 0x0128, 0x0473, 0x035E, 0x026A, 0x015E, + 0x00DB, 0x005E, 0x0048, 0x017A, 0x00AE, 0x00BA, + 0x0172, 0x0229, 0x02FB, 0x0458, 0x05A4, 0x015A, + 0x0296, 0x05BE, 0x044E, 0x0216, 0x012A, 0x0423, + 0x053E, 0x02F0, 0x02F1, 0x011E, 0x0110, 0x009C, + 0x026B, 0x0112, 0x011B, 0x01B3, 0x01BF, 0x0263, + 0x057E, 0x04B8, 0x016B, 0x02DE, 0x04DE, 0x0416, + 0x02DB, 0x02AB, 0x06EE, 0x04CF, 0x025F, 0x02EB, + 0x022A, 0x011A, 0x010A, 0x05A5, 0x0238, 0x0217, + 0x02D6, 0x025A, 0x0282, 0x044F, 0x043D, 0x01AE, + 0x026B, 0x05C2, 0x043C, 0x044F, 0x02DB, 0x05A7, + 0x044E, 0x05BF, 0x0297, 0x022A, 0x026C, 0x02BD, + 0x0897, 0x0283, 0x02B6, 0x02B7, 0x0264, 0x0459, + 0x040B, 0x04DF, 0x0298, 0x0456, 0x0AFF, 0x06B7, + 0x0448, 0x0449, 0x08BE, 0x06EF, 0x04B9, 0x0597, + 0x049A, 0x02D2, 0x02F8, 0x08F7, 0x0476, 0x0452, + 0x0453, 0x045A, 0x05BE, 0x043E, 0x04D2, 0x02F2, + 0x02E4, 0x0477, 0x0AFE, 0x05A6, 0x02E3, 0x0BB6, + 0x0A7E, 0x05A6, 0x0A66, 0x08BF, 0x05FF, 0x0492, + 0x0170, 0x0106, 0x0140, 0x0142, 0x022E, 0x02CF, + 0x02B9, 0x02E2, 0x02F3, 0x05A0, 0x088E, 0x0DD7, + 0x04F6, 0x047E, 0x045B, 0x0347, 0x029E, 0x026D, + 0x01AC, 0x013B, 0x0104, 0x035F, 0x02EC, 0x026E, + 0x0233, 0x0207, 0x023E, 0x026E, 0x053F, 0x05A7, + 0x0456, 0x04AE, 0x0DD6, 0x0A67, 0x0493, 0x04BA, + 0x05D3, 0x05C3, 0x0246, 0x0247, 0x0202, 0x02E8, + 0x05AE, 0x0374, 0x0537, 0x05C6, 0x04BB, 0x0686, + 0x04D3, 0x04DE, 0x08C3, 0x05BF, 0x04F7, 0x14FB, + 0x0997, 0x0A7F, 0x08C2, 0x0417, 0x0434, 0x0477, + 0x037B, 0x0463, 0x02EF, 0x0592, 0x02E5, 0x049B, + 0x035A, 0x0436, 0x05AF, 0x0687, 0x0896, 0x095F, + 0x09BE, 0x0996, 0x0558, 0x088F, 0x0B8E, 0x057E, + 0x04CA, 0x05CE, 0x05F3, 0x047A, 0x05A1, 0x02E2, + 0x02FA, 0x0204, 0x022C, 0x020E, 0x0360, 0x02AE, + 0x05FC, 0x0457, 0x05DA, 0x086B, 0x14FA, 0x04B6, + 0x02FE, 0x040A, 0x02E6, 0x0576, 0x044A, 0x028C, + 0x0212, 0x0248, 0x02E0, 0x029A, 0x0126, 0x017E, + 0x0130, 0x024C, 0x0232, 0x0596, 0x0378, 0x053A, + 0x04CC, 0x0A7C, 0x0470, 0x0593, 0x02D8, 0x029C, + 0x02D9, 0x02BE, 0x01A0, 0x014E, 0x0120, 0x013C, + 0x06EC, 0x04CD, 0x0559, 0x06B6, 0x0420, 0x057F, + 0x0596, 0x09BF, 0x0532, 0x055A, 0x095E, 0x08BC, + 0x0472, 0x02CA, 0x05F2, 0x05FD, 0x047E, 0x05A2, + 0x06EA, 0x05CF, 0x04D2, 0x043F, 0x028E, 0x0422, + 0x0460, 0x05DE, 0x053B, 0x08F6, 0x0B8F, 0x02CE, + 0x0473, 0x06ED, 0x0421, 0x028D, 0x023C, 0x047F, + 0x05A3, 0x044C, 0x044D, 0x0457, 0x02CA, 0x02D8, + 0x027C, 0x029E, 0x023E, 0x027D, 0x0361, 0x0414, + 0x05BC, 0x08BD, 0x02DA, 0x024A, 0x0437, 0x055B, + 0x0379, 0x01BE, 0x05DF, 0x04D3, 0x0268, 0x0206, + 0x0213, 0x02BA, 0x0203, 0x0236, 0x0127, 0x0136, + 0x0268, 0x0242, 0x02CF, 0x05FE, 0x05D2, 0x0237, + 0x0243, 0x0472, 0x0362, 0x027A, 0x02AE, 0x0471, + 0x0474, 0x024B, 0x02AF, 0x01A6, 0x012C, 0x0166, + 0x0166, 0x00A6, 0x00AC, 0x0100, 0x01B2, 0x020F, + 0x0363, 0x0446, 0x016A, 0x022E, 0x0577, 0x02FF, + 0x022D, 0x0168, 0x0475, 0x027E, 0x0222, 0x01A2, + 0x017B, 0x00D2, 0x00BE, 0x0050, 0x0054, 0x006A, + 0x011A, 0x0143, 0x024F, 0x02E7, 0x0447, 0x0110, + 0x0233, 0x02D9, 0x02AF, 0x024E, 0x016A, 0x0536, + 0x0342, 0x02BC, 0x0176, 0x00DA, 0x0054, 0x004A, + 0x000E, 0x0010, 0x004C, 0x00DC, 0x0164, 0x023A, + 0x0476, 0x04CE, 0x0118, 0x02CE, 0x025E, 0x0346, + 0x02A8, 0x0122, 0x05BD, 0x022F, 0x02EA, 0x014A, + 0x00AA, 0x0051, 0x000F, +}; + +static const uint8_t on2avc_cb12_bits[ON2AVC_CB12_CODES] = { + 2, 4, 7, 9, 10, 11, + 12, 13, 10, 11, 11, 11, + 11, 10, 12, 12, 11, 11, + 9, 7, 4, 4, 5, 7, + 9, 10, 10, 11, 12, 10, + 10, 11, 11, 10, 9, 12, + 11, 10, 10, 9, 7, 5, + 7, 7, 8, 9, 10, 10, + 11, 12, 10, 10, 11, 11, + 10, 10, 12, 11, 10, 10, + 9, 8, 7, 9, 9, 9, + 9, 10, 10, 11, 11, 10, + 11, 11, 11, 11, 10, 12, + 11, 10, 10, 10, 9, 9, + 10, 10, 10, 10, 10, 11, + 11, 12, 10, 11, 11, 12, + 11, 10, 12, 12, 11, 10, + 10, 10, 10, 11, 10, 11, + 10, 11, 11, 12, 12, 10, + 11, 11, 12, 11, 10, 12, + 12, 11, 11, 11, 10, 10, + 12, 11, 11, 11, 11, 11, + 12, 12, 10, 11, 12, 12, + 11, 11, 12, 12, 12, 11, + 11, 11, 10, 12, 12, 12, + 12, 11, 12, 12, 12, 10, + 11, 12, 12, 11, 11, 12, + 13, 12, 12, 12, 11, 12, + 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 12, 13, + 12, 12, 11, 11, 11, 10, + 10, 10, 10, 11, 10, 10, + 11, 11, 11, 11, 11, 11, + 12, 12, 13, 12, 12, 12, + 11, 11, 11, 11, 11, 10, + 11, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 12, 14, + 13, 13, 12, 12, 12, 11, + 11, 11, 11, 11, 11, 11, + 11, 12, 11, 12, 12, 13, + 12, 13, 12, 12, 12, 12, + 12, 11, 11, 11, 11, 11, + 10, 11, 11, 11, 11, 11, + 11, 12, 11, 13, 14, 12, + 11, 12, 11, 11, 11, 11, + 11, 11, 10, 10, 10, 9, + 10, 10, 10, 11, 11, 11, + 12, 13, 12, 11, 10, 10, + 10, 10, 10, 10, 10, 10, + 12, 12, 12, 12, 12, 12, + 12, 12, 11, 12, 13, 12, + 11, 10, 11, 11, 11, 11, + 12, 11, 11, 12, 11, 12, + 11, 11, 11, 12, 12, 11, + 11, 12, 12, 11, 10, 12, + 11, 11, 11, 11, 11, 11, + 11, 10, 10, 11, 11, 12, + 11, 12, 10, 11, 12, 12, + 11, 10, 11, 11, 11, 11, + 11, 10, 11, 10, 10, 10, + 10, 11, 11, 11, 11, 10, + 11, 12, 11, 11, 10, 12, + 11, 11, 10, 10, 10, 10, + 9, 9, 9, 10, 10, 11, + 11, 12, 10, 11, 11, 11, + 11, 10, 11, 11, 11, 10, + 9, 9, 9, 7, 7, 8, + 9, 10, 10, 11, 12, 10, + 10, 11, 11, 10, 9, 11, + 11, 10, 10, 9, 8, 7, + 4, 5, 7, 9, 10, 11, + 11, 12, 10, 10, 11, 11, + 10, 10, 11, 11, 10, 10, + 9, 7, 5, +}; + +static const uint16_t on2avc_cb12_syms[ON2AVC_CB12_CODES] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x00F6, + 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, + 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x0101, 0x0102, + 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, + 0x0109, 0x010A, 0x01F6, 0x01F7, 0x01F8, 0x01F9, + 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, + 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, + 0x0206, 0x0207, 0x0208, 0x0209, 0x020A, 0x02F6, + 0x02F7, 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, + 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, + 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, + 0x0309, 0x030A, 0x03F6, 0x03F7, 0x03F8, 0x03F9, + 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, + 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x04F6, + 0x04F7, 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, + 0x04FD, 0x04FE, 0x04FF, 0x0500, 0x0501, 0x0502, + 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, + 0x0509, 0x050A, 0x05F6, 0x05F7, 0x05F8, 0x05F9, + 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, + 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, + 0x0606, 0x0607, 0x0608, 0x0609, 0x060A, 0x06F6, + 0x06F7, 0x06F8, 0x06F9, 0x06FA, 0x06FB, 0x06FC, + 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, + 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, + 0x0709, 0x070A, 0x07F6, 0x07F7, 0x07F8, 0x07F9, + 0x07FA, 0x07FB, 0x07FC, 0x07FD, 0x07FE, 0x07FF, + 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, + 0x0806, 0x0807, 0x0808, 0x0809, 0x080A, 0x08F6, + 0x08F7, 0x08F8, 0x08F9, 0x08FA, 0x08FB, 0x08FC, + 0x08FD, 0x08FE, 0x08FF, 0x0900, 0x0901, 0x0902, + 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, + 0x0909, 0x090A, 0x09F6, 0x09F7, 0x09F8, 0x09F9, + 0x09FA, 0x09FB, 0x09FC, 0x09FD, 0x09FE, 0x09FF, + 0x0A00, 0x0A01, 0x0A02, 0x0A03, 0x0A04, 0x0A05, + 0x0A06, 0x0A07, 0x0A08, 0x0A09, 0x0A0A, 0x0AF6, + 0x0AF7, 0x0AF8, 0x0AF9, 0x0AFA, 0x0AFB, 0x0AFC, + 0x0AFD, 0x0AFE, 0x0AFF, 0xF600, 0xF601, 0xF602, + 0xF603, 0xF604, 0xF605, 0xF606, 0xF607, 0xF608, + 0xF609, 0xF60A, 0xF6F6, 0xF6F7, 0xF6F8, 0xF6F9, + 0xF6FA, 0xF6FB, 0xF6FC, 0xF6FD, 0xF6FE, 0xF6FF, + 0xF700, 0xF701, 0xF702, 0xF703, 0xF704, 0xF705, + 0xF706, 0xF707, 0xF708, 0xF709, 0xF70A, 0xF7F6, + 0xF7F7, 0xF7F8, 0xF7F9, 0xF7FA, 0xF7FB, 0xF7FC, + 0xF7FD, 0xF7FE, 0xF7FF, 0xF800, 0xF801, 0xF802, + 0xF803, 0xF804, 0xF805, 0xF806, 0xF807, 0xF808, + 0xF809, 0xF80A, 0xF8F6, 0xF8F7, 0xF8F8, 0xF8F9, + 0xF8FA, 0xF8FB, 0xF8FC, 0xF8FD, 0xF8FE, 0xF8FF, + 0xF900, 0xF901, 0xF902, 0xF903, 0xF904, 0xF905, + 0xF906, 0xF907, 0xF908, 0xF909, 0xF90A, 0xF9F6, + 0xF9F7, 0xF9F8, 0xF9F9, 0xF9FA, 0xF9FB, 0xF9FC, + 0xF9FD, 0xF9FE, 0xF9FF, 0xFA00, 0xFA01, 0xFA02, + 0xFA03, 0xFA04, 0xFA05, 0xFA06, 0xFA07, 0xFA08, + 0xFA09, 0xFA0A, 0xFAF6, 0xFAF7, 0xFAF8, 0xFAF9, + 0xFAFA, 0xFAFB, 0xFAFC, 0xFAFD, 0xFAFE, 0xFAFF, + 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0xFB05, + 0xFB06, 0xFB07, 0xFB08, 0xFB09, 0xFB0A, 0xFBF6, + 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, + 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, 0xFC01, 0xFC02, + 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08, + 0xFC09, 0xFC0A, 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, + 0xFCFA, 0xFCFB, 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, + 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04, 0xFD05, + 0xFD06, 0xFD07, 0xFD08, 0xFD09, 0xFD0A, 0xFDF6, + 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, + 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, 0xFE01, 0xFE02, + 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, + 0xFE09, 0xFE0A, 0xFEF6, 0xFEF7, 0xFEF8, 0xFEF9, + 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0xFEFF, + 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, + 0xFF06, 0xFF07, 0xFF08, 0xFF09, 0xFF0A, 0xFFF6, + 0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, + 0xFFFD, 0xFFFE, 0xFFFF, +}; + +#define ON2AVC_CB13_CODES 625 +static const uint16_t on2avc_cb13_codes[ON2AVC_CB13_CODES] = { + 0x0000, 0x0015, 0x008E, 0x0338, 0x09FB, 0x0BEC, + 0x0C61, 0x13E1, 0x18A7, 0x313B, 0x61BB, 0x05D9, + 0x0896, 0x066B, 0x05C6, 0x18A6, 0x40E4, 0x2081, + 0x104F, 0x13E0, 0x0C22, 0x07E4, 0x03F7, 0x0087, + 0x0014, 0x0016, 0x001D, 0x009C, 0x02E2, 0x037E, + 0x0897, 0x0898, 0x0C63, 0x117D, 0x2082, 0x27AA, + 0x033B, 0x06C5, 0x04F2, 0x0331, 0x19EB, 0x18A8, + 0x13E2, 0x0DE7, 0x0C62, 0x06DF, 0x05C7, 0x02F4, + 0x0098, 0x001A, 0x007C, 0x0080, 0x0106, 0x02F5, + 0x03EC, 0x0617, 0x0621, 0x08F9, 0x1050, 0x117F, + 0x11E0, 0x036A, 0x045A, 0x06C6, 0x037F, 0x117E, + 0x2083, 0x0BED, 0x0C9E, 0x0658, 0x04F3, 0x0368, + 0x02EE, 0x00FA, 0x008D, 0x031C, 0x01FF, 0x0206, + 0x031E, 0x06C8, 0x0659, 0x09B5, 0x0C23, 0x0BEF, + 0x0C9F, 0x19EC, 0x04CC, 0x0623, 0x06C7, 0x0622, + 0x313C, 0x17BB, 0x11E1, 0x0C64, 0x0BEE, 0x07DC, + 0x04CB, 0x0375, 0x0205, 0x026E, 0x0C24, 0x06C9, + 0x0324, 0x04DF, 0x0642, 0x09B6, 0x0643, 0x0BF2, + 0x083B, 0x1051, 0x27AB, 0x036C, 0x0607, 0x06E2, + 0x045B, 0x313D, 0x2084, 0x18A9, 0x13E3, 0x0CA0, + 0x0899, 0x066E, 0x06E3, 0x0369, 0x0606, 0x0DE8, + 0x061A, 0x0453, 0x065A, 0x065B, 0x089B, 0x089C, + 0x09FD, 0x0BA5, 0x18AA, 0x11E2, 0x05C8, 0x09B7, + 0x066F, 0x06CA, 0x19ED, 0x2085, 0x2086, 0x0D83, + 0x1052, 0x1053, 0x09FC, 0x089A, 0x0644, 0x083E, + 0x13E4, 0x08FC, 0x0624, 0x1055, 0x0C65, 0x089D, + 0x0645, 0x08FD, 0x0C66, 0x0CA1, 0x1056, 0x05E1, + 0x089E, 0x08FA, 0x07E5, 0x313E, 0x2087, 0x11E3, + 0x19EE, 0x18AB, 0x1054, 0x19EF, 0x17BC, 0x08FB, + 0x07E6, 0x18AD, 0x0BF3, 0x07E7, 0x0C67, 0x1057, + 0x07EA, 0x08FF, 0x1058, 0x0DE9, 0x18AE, 0x19F0, + 0x0608, 0x089F, 0x08FE, 0x06CB, 0x313F, 0x2088, + 0x13E5, 0x3142, 0x11E4, 0x18AC, 0x11E5, 0x0CA2, + 0x065E, 0x13E6, 0x27AD, 0x19F1, 0x0D86, 0x0DEA, + 0x0CA3, 0x0DEB, 0x17BE, 0x0C2A, 0x13E8, 0x0CA6, + 0x0DEE, 0x05FD, 0x0992, 0x0C25, 0x063E, 0x40E5, + 0x11E6, 0x3143, 0x18AF, 0x27AC, 0x0C26, 0x17BD, + 0x13E7, 0x0C27, 0x11E7, 0x27B2, 0x40E8, 0x18B3, + 0x17C0, 0x18FE, 0x19F2, 0x19F3, 0x31FE, 0x17C1, + 0x19F6, 0x0BA6, 0x09FE, 0x0DEF, 0x17BF, 0x0C2B, + 0x40E6, 0x18B0, 0x40E7, 0x13E9, 0x2089, 0x27AE, + 0x27AF, 0x208A, 0x18B1, 0x18B2, 0x27B3, 0xBCEF, + 0x2F3A, 0x40EA, 0x17C5, 0x17C6, 0x17C7, 0x19F7, + 0x133E, 0x105A, 0x17CA, 0x065F, 0x0CA7, 0x0C7E, + 0x1059, 0xBCED, 0x40E9, 0xBCEE, 0x17C2, 0x63FE, + 0x208B, 0x208E, 0x208F, 0x17C3, 0x17C4, 0x0625, + 0x03ED, 0x045C, 0x04CD, 0x05DA, 0x05CE, 0x05FF, + 0x0626, 0x060A, 0x05E3, 0x083F, 0x0BA8, 0x0BA9, + 0x40EB, 0x13EA, 0x0CCA, 0x0BA7, 0x08A2, 0x0646, + 0x0609, 0x05E2, 0x041E, 0x05FE, 0x0373, 0x0376, + 0x099E, 0x05DE, 0x0647, 0x05E6, 0x06D6, 0x07EB, + 0x09FF, 0x1B5E, 0x0BAB, 0x08AE, 0x0C36, 0x0FBA, + 0x17CB, 0x4CFE, 0x105B, 0x0D87, 0x0DAE, 0x13EB, + 0x0BAA, 0x0993, 0x08A3, 0x085E, 0x0600, 0x0601, + 0x05DB, 0x0664, 0x04F0, 0x05F8, 0x0634, 0x085F, + 0x06F6, 0x08F4, 0x0C5A, 0x0CFC, 0x0DDC, 0x09F6, + 0x0C16, 0x115E, 0x13D8, 0x13DA, 0x0C94, 0x0CFA, + 0x082E, 0x0B9E, 0x06C2, 0x0BE4, 0x06DA, 0x05C0, + 0x0614, 0x05C9, 0x05DF, 0x033A, 0x0336, 0x05FA, + 0x04CE, 0x05C1, 0x0890, 0x0891, 0x0838, 0x0839, + 0x0CFD, 0x0BA0, 0x61B8, 0x07DE, 0x0635, 0x0B9F, + 0x0640, 0x06DB, 0x082F, 0x09AC, 0x04C8, 0x0666, + 0x04DE, 0x03F4, 0x0339, 0x2079, 0x267E, 0x179E, + 0x30DE, 0x63FF, 0x27A0, 0x1997, 0x36BF, 0x3EEC, + 0x99FE, 0x99FF, 0x0C95, 0x1048, 0x0C5B, 0x0636, + 0x0C5C, 0x2076, 0x13DB, 0x115F, 0x179C, 0x2077, + 0x1046, 0x36BE, 0x1996, 0x2078, 0x61B9, 0x1175, + 0x17B0, 0x3EED, 0x19E1, 0x19E2, 0x207A, 0x3EEE, + 0xBCEC, 0x3138, 0x3139, 0x07DF, 0x1176, 0x0892, + 0x0667, 0x18A0, 0x18A2, 0x13DC, 0x1174, 0x13DD, + 0x179F, 0x30DF, 0x19E0, 0x18A3, 0x1049, 0x17B2, + 0x207B, 0x17B3, 0x0C17, 0x19E3, 0x17B4, 0x207C, + 0x3EEF, 0x207D, 0x19E4, 0x27A1, 0x0C5F, 0x08F5, + 0x0DDD, 0x0652, 0x18A4, 0x0C96, 0x0C5D, 0x104A, + 0x1177, 0x0CFE, 0x0C5E, 0x0DDE, 0x09F7, 0x17B1, + 0x19E6, 0x0C1E, 0x09AE, 0x1179, 0x0DE0, 0x17B5, + 0x0BA2, 0x17B6, 0x27A3, 0x40E0, 0x40E1, 0x06DC, + 0x09AF, 0x09AD, 0x05C2, 0x19E5, 0x27A2, 0x0DDF, + 0x0C1C, 0x0C1D, 0x0BE6, 0x0BA1, 0x1178, 0x0654, + 0x13DE, 0x40E2, 0x0893, 0x0668, 0x07E1, 0x0BE7, + 0x08F6, 0x0DE1, 0x27A4, 0x104B, 0x19E7, 0x40E3, + 0x05D6, 0x09F9, 0x06DD, 0x04CA, 0x17B7, 0x17B8, + 0x0C97, 0x0C98, 0x07E0, 0x0C99, 0x0655, 0x09F8, + 0x0656, 0x0C9A, 0x0DE2, 0x0669, 0x04D3, 0x061C, + 0x0894, 0x13DF, 0x0C1F, 0x104C, 0x27A6, 0x61BA, + 0x27A7, 0x066A, 0x061D, 0x0637, 0x04D2, 0x27A5, + 0x117A, 0x0C9B, 0x09B0, 0x09B1, 0x05E0, 0x0602, + 0x05FB, 0x04F1, 0x08F7, 0x06FA, 0x0603, 0x037C, + 0x05C3, 0x0BE8, 0x0895, 0x0C60, 0x117B, 0x19E8, + 0x27A8, 0x19E9, 0x0657, 0x083A, 0x06C4, 0x05D7, + 0x17B9, 0x0CFF, 0x0DE3, 0x104D, 0x07E2, 0x0641, + 0x061E, 0x05D8, 0x0366, 0x0616, 0x032E, 0x0268, + 0x02E6, 0x0456, 0x0BA3, 0x06FB, 0x0D80, 0x0DE5, + 0x104E, 0x17BA, 0x27A9, 0x0330, 0x07E3, 0x061F, + 0x0367, 0x207E, 0x0C9C, 0x117C, 0x0DE4, 0x06DE, + 0x0620, 0x0450, 0x042E, 0x02F2, 0x0204, 0x0086, + 0x008C, 0x00FE, 0x022A, 0x0372, 0x05CA, 0x0452, + 0x08F8, 0x0BA4, 0x19EA, 0x18A5, 0x0306, 0x05FC, + 0x03F6, 0x0458, 0x0D81, 0x0BE9, 0x09B2, 0x0C20, + 0x09FA, 0x0604, 0x0370, 0x01FE, 0x010A, 0x0084, + 0x0012, 0x001C, 0x0088, 0x026A, 0x05CB, 0x063B, + 0x09B4, 0x0D82, 0x0DE6, 0x207F, 0x2080, 0x030C, + 0x0605, 0x0459, 0x0374, 0x313A, 0x0C9D, 0x0BEA, + 0x0BEB, 0x0C21, 0x09B3, 0x063A, 0x0216, 0x009D, + 0x001E, +}; + +static const uint8_t on2avc_cb13_bits[ON2AVC_CB13_CODES] = { + 1, 5, 8, 10, 12, 12, + 12, 13, 13, 14, 15, 11, + 12, 11, 11, 13, 15, 14, + 13, 13, 12, 11, 10, 8, + 5, 5, 5, 8, 10, 10, + 12, 12, 12, 13, 14, 14, + 10, 11, 11, 10, 13, 13, + 13, 12, 12, 11, 11, 10, + 8, 5, 7, 8, 9, 10, + 10, 11, 11, 12, 13, 13, + 13, 10, 11, 11, 10, 13, + 14, 12, 12, 11, 11, 10, + 10, 8, 8, 10, 9, 10, + 10, 11, 11, 12, 12, 12, + 12, 13, 11, 11, 11, 11, + 14, 13, 13, 12, 12, 11, + 11, 10, 10, 10, 12, 11, + 10, 11, 11, 12, 11, 12, + 12, 13, 14, 10, 11, 11, + 11, 14, 14, 13, 13, 12, + 12, 11, 11, 10, 11, 12, + 11, 11, 11, 11, 12, 12, + 12, 12, 13, 13, 11, 12, + 11, 11, 13, 14, 14, 12, + 13, 13, 12, 12, 11, 12, + 13, 12, 11, 13, 12, 12, + 11, 12, 12, 12, 13, 11, + 12, 12, 11, 14, 14, 13, + 13, 13, 13, 13, 13, 12, + 11, 13, 12, 11, 12, 13, + 11, 12, 13, 12, 13, 13, + 11, 12, 12, 11, 14, 14, + 13, 14, 13, 13, 13, 12, + 11, 13, 14, 13, 12, 12, + 12, 12, 13, 12, 13, 12, + 12, 11, 12, 12, 11, 15, + 13, 14, 13, 14, 12, 13, + 13, 12, 13, 14, 15, 13, + 13, 13, 13, 13, 14, 13, + 13, 12, 12, 12, 13, 12, + 15, 13, 15, 13, 14, 14, + 14, 14, 13, 13, 14, 16, + 14, 15, 13, 13, 13, 13, + 13, 13, 13, 11, 12, 12, + 13, 16, 15, 16, 13, 15, + 14, 14, 14, 13, 13, 11, + 10, 11, 11, 11, 11, 11, + 11, 11, 11, 12, 12, 12, + 15, 13, 12, 12, 12, 11, + 11, 11, 11, 11, 10, 10, + 12, 11, 11, 11, 11, 11, + 12, 13, 12, 12, 12, 12, + 13, 15, 13, 12, 12, 13, + 12, 12, 12, 12, 11, 11, + 11, 11, 11, 11, 11, 12, + 11, 12, 12, 12, 12, 12, + 12, 13, 13, 13, 12, 12, + 12, 12, 11, 12, 11, 11, + 11, 11, 11, 10, 10, 11, + 11, 11, 12, 12, 12, 12, + 12, 12, 15, 11, 11, 12, + 11, 11, 12, 12, 11, 11, + 11, 10, 10, 14, 14, 13, + 14, 15, 14, 13, 14, 14, + 16, 16, 12, 13, 12, 11, + 12, 14, 13, 13, 13, 14, + 13, 14, 13, 14, 15, 13, + 13, 14, 13, 13, 14, 14, + 16, 14, 14, 11, 13, 12, + 11, 13, 13, 13, 13, 13, + 13, 14, 13, 13, 13, 13, + 14, 13, 12, 13, 13, 14, + 14, 14, 13, 14, 12, 12, + 12, 11, 13, 12, 12, 13, + 13, 12, 12, 12, 12, 13, + 13, 12, 12, 13, 12, 13, + 12, 13, 14, 15, 15, 11, + 12, 12, 11, 13, 14, 12, + 12, 12, 12, 12, 13, 11, + 13, 15, 12, 11, 11, 12, + 12, 12, 14, 13, 13, 15, + 11, 12, 11, 11, 13, 13, + 12, 12, 11, 12, 11, 12, + 11, 12, 12, 11, 11, 11, + 12, 13, 12, 13, 14, 15, + 14, 11, 11, 11, 11, 14, + 13, 12, 12, 12, 11, 11, + 11, 11, 12, 11, 11, 10, + 11, 12, 12, 12, 13, 13, + 14, 13, 11, 12, 11, 11, + 13, 12, 12, 13, 11, 11, + 11, 11, 10, 11, 10, 10, + 10, 11, 12, 11, 12, 12, + 13, 13, 14, 10, 11, 11, + 10, 14, 12, 13, 12, 11, + 11, 11, 11, 10, 10, 8, + 8, 8, 10, 10, 11, 11, + 12, 12, 13, 13, 10, 11, + 10, 11, 12, 12, 12, 12, + 12, 11, 10, 9, 9, 8, + 5, 5, 8, 10, 11, 11, + 12, 12, 12, 14, 14, 10, + 11, 11, 10, 14, 12, 12, + 12, 12, 12, 11, 10, 8, + 5, +}; + +static const uint16_t on2avc_cb13_syms[ON2AVC_CB13_CODES] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, + 0x000C, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, + 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, + 0x00FF, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, + 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, + 0x010B, 0x010C, 0x01F4, 0x01F5, 0x01F6, 0x01F7, + 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, + 0x01FE, 0x01FF, 0x0200, 0x0201, 0x0202, 0x0203, + 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, + 0x020A, 0x020B, 0x020C, 0x02F4, 0x02F5, 0x02F6, + 0x02F7, 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, + 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, + 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, + 0x0309, 0x030A, 0x030B, 0x030C, 0x03F4, 0x03F5, + 0x03F6, 0x03F7, 0x03F8, 0x03F9, 0x03FA, 0x03FB, + 0x03FC, 0x03FD, 0x03FE, 0x03FF, 0x0400, 0x0401, + 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x04F4, + 0x04F5, 0x04F6, 0x04F7, 0x04F8, 0x04F9, 0x04FA, + 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, 0x0500, + 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, + 0x0507, 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, + 0x05F4, 0x05F5, 0x05F6, 0x05F7, 0x05F8, 0x05F9, + 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, + 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, + 0x0606, 0x0607, 0x0608, 0x0609, 0x060A, 0x060B, + 0x060C, 0x06F4, 0x06F5, 0x06F6, 0x06F7, 0x06F8, + 0x06F9, 0x06FA, 0x06FB, 0x06FC, 0x06FD, 0x06FE, + 0x06FF, 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, + 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, 0x070A, + 0x070B, 0x070C, 0x07F4, 0x07F5, 0x07F6, 0x07F7, + 0x07F8, 0x07F9, 0x07FA, 0x07FB, 0x07FC, 0x07FD, + 0x07FE, 0x07FF, 0x0800, 0x0801, 0x0802, 0x0803, + 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809, + 0x080A, 0x080B, 0x080C, 0x08F4, 0x08F5, 0x08F6, + 0x08F7, 0x08F8, 0x08F9, 0x08FA, 0x08FB, 0x08FC, + 0x08FD, 0x08FE, 0x08FF, 0x0900, 0x0901, 0x0902, + 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, + 0x0909, 0x090A, 0x090B, 0x090C, 0x09F4, 0x09F5, + 0x09F6, 0x09F7, 0x09F8, 0x09F9, 0x09FA, 0x09FB, + 0x09FC, 0x09FD, 0x09FE, 0x09FF, 0x0A00, 0x0A01, + 0x0A02, 0x0A03, 0x0A04, 0x0A05, 0x0A06, 0x0A07, + 0x0A08, 0x0A09, 0x0A0A, 0x0A0B, 0x0A0C, 0x0AF4, + 0x0AF5, 0x0AF6, 0x0AF7, 0x0AF8, 0x0AF9, 0x0AFA, + 0x0AFB, 0x0AFC, 0x0AFD, 0x0AFE, 0x0AFF, 0x0B00, + 0x0B01, 0x0B02, 0x0B03, 0x0B04, 0x0B05, 0x0B06, + 0x0B07, 0x0B08, 0x0B09, 0x0B0A, 0x0B0B, 0x0B0C, + 0x0BF4, 0x0BF5, 0x0BF6, 0x0BF7, 0x0BF8, 0x0BF9, + 0x0BFA, 0x0BFB, 0x0BFC, 0x0BFD, 0x0BFE, 0x0BFF, + 0x0C00, 0x0C01, 0x0C02, 0x0C03, 0x0C04, 0x0C05, + 0x0C06, 0x0C07, 0x0C08, 0x0C09, 0x0C0A, 0x0C0B, + 0x0C0C, 0x0CF4, 0x0CF5, 0x0CF6, 0x0CF7, 0x0CF8, + 0x0CF9, 0x0CFA, 0x0CFB, 0x0CFC, 0x0CFD, 0x0CFE, + 0x0CFF, 0xF400, 0xF401, 0xF402, 0xF403, 0xF404, + 0xF405, 0xF406, 0xF407, 0xF408, 0xF409, 0xF40A, + 0xF40B, 0xF40C, 0xF4F4, 0xF4F5, 0xF4F6, 0xF4F7, + 0xF4F8, 0xF4F9, 0xF4FA, 0xF4FB, 0xF4FC, 0xF4FD, + 0xF4FE, 0xF4FF, 0xF500, 0xF501, 0xF502, 0xF503, + 0xF504, 0xF505, 0xF506, 0xF507, 0xF508, 0xF509, + 0xF50A, 0xF50B, 0xF50C, 0xF5F4, 0xF5F5, 0xF5F6, + 0xF5F7, 0xF5F8, 0xF5F9, 0xF5FA, 0xF5FB, 0xF5FC, + 0xF5FD, 0xF5FE, 0xF5FF, 0xF600, 0xF601, 0xF602, + 0xF603, 0xF604, 0xF605, 0xF606, 0xF607, 0xF608, + 0xF609, 0xF60A, 0xF60B, 0xF60C, 0xF6F4, 0xF6F5, + 0xF6F6, 0xF6F7, 0xF6F8, 0xF6F9, 0xF6FA, 0xF6FB, + 0xF6FC, 0xF6FD, 0xF6FE, 0xF6FF, 0xF700, 0xF701, + 0xF702, 0xF703, 0xF704, 0xF705, 0xF706, 0xF707, + 0xF708, 0xF709, 0xF70A, 0xF70B, 0xF70C, 0xF7F4, + 0xF7F5, 0xF7F6, 0xF7F7, 0xF7F8, 0xF7F9, 0xF7FA, + 0xF7FB, 0xF7FC, 0xF7FD, 0xF7FE, 0xF7FF, 0xF800, + 0xF801, 0xF802, 0xF803, 0xF804, 0xF805, 0xF806, + 0xF807, 0xF808, 0xF809, 0xF80A, 0xF80B, 0xF80C, + 0xF8F4, 0xF8F5, 0xF8F6, 0xF8F7, 0xF8F8, 0xF8F9, + 0xF8FA, 0xF8FB, 0xF8FC, 0xF8FD, 0xF8FE, 0xF8FF, + 0xF900, 0xF901, 0xF902, 0xF903, 0xF904, 0xF905, + 0xF906, 0xF907, 0xF908, 0xF909, 0xF90A, 0xF90B, + 0xF90C, 0xF9F4, 0xF9F5, 0xF9F6, 0xF9F7, 0xF9F8, + 0xF9F9, 0xF9FA, 0xF9FB, 0xF9FC, 0xF9FD, 0xF9FE, + 0xF9FF, 0xFA00, 0xFA01, 0xFA02, 0xFA03, 0xFA04, + 0xFA05, 0xFA06, 0xFA07, 0xFA08, 0xFA09, 0xFA0A, + 0xFA0B, 0xFA0C, 0xFAF4, 0xFAF5, 0xFAF6, 0xFAF7, + 0xFAF8, 0xFAF9, 0xFAFA, 0xFAFB, 0xFAFC, 0xFAFD, + 0xFAFE, 0xFAFF, 0xFB00, 0xFB01, 0xFB02, 0xFB03, + 0xFB04, 0xFB05, 0xFB06, 0xFB07, 0xFB08, 0xFB09, + 0xFB0A, 0xFB0B, 0xFB0C, 0xFBF4, 0xFBF5, 0xFBF6, + 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, + 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, 0xFC01, 0xFC02, + 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08, + 0xFC09, 0xFC0A, 0xFC0B, 0xFC0C, 0xFCF4, 0xFCF5, + 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, 0xFCFA, 0xFCFB, + 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, 0xFD00, 0xFD01, + 0xFD02, 0xFD03, 0xFD04, 0xFD05, 0xFD06, 0xFD07, + 0xFD08, 0xFD09, 0xFD0A, 0xFD0B, 0xFD0C, 0xFDF4, + 0xFDF5, 0xFDF6, 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, + 0xFDFB, 0xFDFC, 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, + 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, + 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, + 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, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, 0xFFF8, + 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, + 0xFFFF, +}; + +#define ON2AVC_CB14_CODES 729 +static const uint16_t on2avc_cb14_codes[ON2AVC_CB14_CODES] = { + 0x0000, 0x0018, 0x009C, 0x033F, 0x06CF, 0x0860, + 0x3ED2, 0x15F8, 0x0CA3, 0x15F9, 0x3ED3, 0x3ED4, + 0x3ED5, 0x03B3, 0x0336, 0x3ECF, 0x3ED0, 0x15F5, + 0x15F6, 0x3ED1, 0x1FB6, 0x15F7, 0x0D6D, 0x074E, + 0x02A4, 0x008C, 0x0017, 0x0016, 0x0024, 0x00A8, + 0x02AB, 0x043C, 0x038D, 0x15FA, 0x0CA4, 0x1FB8, + 0x15FB, 0x3ED9, 0x1FB9, 0x15FC, 0x01D8, 0x01F1, + 0x3ED6, 0x1090, 0x1FB7, 0x0D6E, 0x3ED7, 0x3ED8, + 0x074F, 0x0D6F, 0x0750, 0x01F2, 0x0098, 0x0020, + 0x0070, 0x009D, 0x00E4, 0x026F, 0x03AE, 0x055D, + 0x06D0, 0x0862, 0x0667, 0x09ED, 0x1900, 0x3EDA, + 0x1901, 0x01DE, 0x026B, 0x15FD, 0x15FE, 0x1091, + 0x15FF, 0x0D70, 0x0666, 0x0689, 0x0861, 0x034E, + 0x026E, 0x00E8, 0x008E, 0x019E, 0x01BF, 0x01F3, + 0x02B5, 0x054E, 0x0669, 0x09EE, 0x09EF, 0x0D71, + 0x0CA5, 0x1FBB, 0x1FBC, 0x3EDF, 0x02A6, 0x01CA, + 0x3EDB, 0x3EDC, 0x3EDD, 0x3EDE, 0x1FBA, 0x1092, + 0x0863, 0x0751, 0x0668, 0x038E, 0x02B4, 0x01C4, + 0x068A, 0x0CA7, 0x06D1, 0x055F, 0x043E, 0x09F0, + 0x0865, 0x0866, 0x0867, 0x0752, 0x1902, 0x3EE2, + 0x1096, 0x0278, 0x02B6, 0x3EE0, 0x1FBD, 0x3EE1, + 0x0864, 0x1FBE, 0x0CA6, 0x1093, 0x1094, 0x1095, + 0x0478, 0x043D, 0x055E, 0x3EE5, 0x0CA9, 0x066A, + 0x0D75, 0x0560, 0x0561, 0x0868, 0x0D76, 0x0CAA, + 0x0CAB, 0x3EE6, 0x3EE7, 0x3EE8, 0x02AC, 0x038F, + 0x3EE3, 0x1FBF, 0x3EE4, 0x0D72, 0x0D73, 0x0D74, + 0x09F1, 0x068B, 0x0CA8, 0x0479, 0x06D2, 0x1097, + 0x1099, 0x09F3, 0x066B, 0x06D3, 0x0CAD, 0x109A, + 0x06D4, 0x068C, 0x06D5, 0x0D79, 0x0D7A, 0x109B, + 0x1FC1, 0x02B2, 0x0396, 0x3EE9, 0x1903, 0x3EEA, + 0x1904, 0x1905, 0x1FC0, 0x09F2, 0x0D77, 0x0D78, + 0x1098, 0x0562, 0x0CAC, 0x190C, 0x109C, 0x06D6, + 0x0D7C, 0x1FC4, 0x0D7D, 0x09F4, 0x06D7, 0x09F5, + 0x3EEE, 0x0CAE, 0x0D7E, 0x3EEF, 0x03AF, 0x043F, + 0x3EEB, 0x1906, 0x1FC2, 0x1907, 0x3EEC, 0x1908, + 0x1909, 0x190A, 0x1FC3, 0x3EED, 0x0D7B, 0x190B, + 0x1FC6, 0x10A1, 0x10A2, 0x0D7F, 0x0CB0, 0x190E, + 0x0D80, 0x10A3, 0x0869, 0x190F, 0x1910, 0x10A4, + 0x10A5, 0x0753, 0x068D, 0x3EF0, 0x3EF1, 0x190D, + 0x1FC5, 0x3EF2, 0x3EF3, 0x109D, 0x109E, 0x0CAF, + 0x109F, 0x3EF4, 0x10A0, 0x10A7, 0x3EFC, 0x0CB1, + 0x09F7, 0x1911, 0x10A8, 0x09F8, 0x10A9, 0x1912, + 0x06D9, 0x09F9, 0x3EFD, 0x1913, 0x068E, 0x06D8, + 0x3EF5, 0x3EF6, 0x3EF7, 0x3EF8, 0x3EF9, 0x0D81, + 0x3EFA, 0x1FC7, 0x1FC8, 0x10A6, 0x09F6, 0x3EFB, + 0x1FCE, 0x0CB2, 0x3F02, 0x10AA, 0x3F03, 0x1FCF, + 0x10AB, 0x10AC, 0x1916, 0x3F04, 0x09FA, 0x0D83, + 0x3F05, 0x068F, 0x086A, 0x1914, 0x3EFE, 0x1FC9, + 0x1FCA, 0x3EFF, 0x0D82, 0x1FCB, 0x1FCC, 0x3F00, + 0x1FCD, 0x3F01, 0x1915, 0x3F0F, 0x1918, 0x10AD, + 0x0CB3, 0x3F10, 0x1919, 0x3F11, 0x191A, 0x1FD2, + 0x0CB4, 0x0CB5, 0x10AE, 0x191B, 0x047A, 0x06DA, + 0x3F06, 0x3F07, 0x1917, 0x3F08, 0x3F09, 0x3F0A, + 0x3F0B, 0x3F0C, 0x3F0D, 0x3F0E, 0x1FD0, 0x1FD1, + 0x3F18, 0x191F, 0x1FDA, 0x3F19, 0x3F1A, 0x10AF, + 0x3F1B, 0x10B2, 0x1FDB, 0x0D86, 0x0D87, 0x10B3, + 0x0CB6, 0x086B, 0x09FB, 0x3F12, 0x1FD3, 0x1FD4, + 0x3F13, 0x1FD5, 0x191E, 0x1FD6, 0x3F14, 0x3F15, + 0x3F16, 0x1FD7, 0x3F17, 0x033A, 0x01AA, 0x02B8, + 0x01DF, 0x02B9, 0x02BA, 0x086F, 0x03BB, 0x03B2, + 0x046A, 0x066F, 0x08DE, 0x0563, 0x046B, 0x0CB7, + 0x11BE, 0x086E, 0x066E, 0x06DB, 0x047B, 0x03BA, + 0x0A9E, 0x02B7, 0x0340, 0x0264, 0x01CE, 0x01A9, + 0x0265, 0x01A8, 0x0266, 0x02A8, 0x036F, 0x03AB, + 0x037A, 0x04FE, 0x0683, 0x06C4, 0x0C90, 0x065D, + 0x0D3C, 0x0FEC, 0x0436, 0x06C2, 0x0682, 0x0C8E, + 0x055A, 0x033B, 0x065C, 0x0348, 0x03AA, 0x0234, + 0x036E, 0x01F0, 0x01A6, 0x3E86, 0x3E87, 0x153E, + 0x3E88, 0x3E89, 0x0FEF, 0x3E8A, 0x3E8B, 0x3E8C, + 0x3E8D, 0x3E8E, 0x3E8F, 0x3E90, 0x09E4, 0x03AC, + 0x11BF, 0x1F8E, 0x1F8F, 0x0FEE, 0x3E80, 0x3E81, + 0x3E82, 0x3E83, 0x3E84, 0x3E85, 0x1F90, 0x1F91, + 0x3E95, 0x3E96, 0x0C91, 0x3E97, 0x3E98, 0x3E99, + 0x3E9A, 0x3E9B, 0x3E9C, 0x3E9D, 0x3E9E, 0x3E9F, + 0x3EA0, 0x0858, 0x04FF, 0x0FF0, 0x0FF1, 0x153F, + 0x0FF2, 0x3E91, 0x1F92, 0x3E92, 0x1F93, 0x3E93, + 0x1F94, 0x3E94, 0x0D3D, 0x3EA3, 0x1F99, 0x0FF7, + 0x0D3E, 0x3EA4, 0x1F9A, 0x15D9, 0x0D3F, 0x3EA5, + 0x3EA6, 0x3EA7, 0x0D58, 0x3EA8, 0x06C5, 0x072E, + 0x3EA1, 0x1F95, 0x1F96, 0x0C92, 0x0FF3, 0x0FF4, + 0x0FF5, 0x15D8, 0x1F97, 0x0FF6, 0x1F98, 0x3EA2, + 0x3EAC, 0x0FF9, 0x1F9C, 0x15DB, 0x1F9D, 0x15DC, + 0x0FFA, 0x1F9E, 0x3EAD, 0x3EAE, 0x3EAF, 0x3EB0, + 0x3EB1, 0x065E, 0x055B, 0x3EA9, 0x0D59, 0x15DA, + 0x0FF8, 0x3EAA, 0x0D5A, 0x3EAB, 0x0D5B, 0x0D5C, + 0x0D5D, 0x072F, 0x1F9B, 0x3EB4, 0x1FA0, 0x073C, + 0x0D5F, 0x1FA1, 0x1FA2, 0x0FFE, 0x1FA3, 0x1FA4, + 0x3EB5, 0x3EB6, 0x3EB7, 0x3EB8, 0x065F, 0x06C6, + 0x3EB2, 0x15DD, 0x0FFB, 0x3EB3, 0x1F9F, 0x0D5E, + 0x0C93, 0x0C94, 0x0FFC, 0x0FFD, 0x15DE, 0x15DF, + 0x1FA7, 0x15E1, 0x06C7, 0x0D62, 0x15E2, 0x0C96, + 0x15E3, 0x1082, 0x15E4, 0x1FA8, 0x3EBA, 0x3EBB, + 0x3EBC, 0x0660, 0x046E, 0x3EB9, 0x1FA5, 0x0FFF, + 0x1FA6, 0x1080, 0x1081, 0x0D60, 0x0C95, 0x15E0, + 0x0D61, 0x073D, 0x085A, 0x15E6, 0x09E9, 0x085B, + 0x0C97, 0x1083, 0x0C98, 0x0D63, 0x0D64, 0x0C99, + 0x15E7, 0x15E8, 0x1FAC, 0x3EBE, 0x0684, 0x037B, + 0x1FA9, 0x1FAA, 0x3EBD, 0x073E, 0x1FAB, 0x15E5, + 0x06C8, 0x09E5, 0x09E6, 0x09E7, 0x0661, 0x09E8, + 0x1FAE, 0x0C9A, 0x06CA, 0x055C, 0x0C9B, 0x3EC0, + 0x15EB, 0x1085, 0x1086, 0x15EC, 0x1087, 0x3EC1, + 0x3EC2, 0x02A9, 0x02B3, 0x1FAD, 0x15E9, 0x3EBF, + 0x15EA, 0x1084, 0x0D65, 0x0662, 0x0D66, 0x06C9, + 0x0438, 0x054A, 0x073F, 0x085D, 0x0663, 0x0439, + 0x0686, 0x06CB, 0x0C9E, 0x0C9F, 0x1088, 0x15EF, + 0x3EC6, 0x1089, 0x1FAF, 0x3EC7, 0x0349, 0x0267, + 0x3EC3, 0x3EC4, 0x15ED, 0x15EE, 0x3EC5, 0x09EA, + 0x0C9C, 0x0C9D, 0x054B, 0x0685, 0x085C, 0x09EB, + 0x01BC, 0x01DC, 0x01BE, 0x03AD, 0x038A, 0x0749, + 0x0688, 0x0665, 0x074A, 0x0CA1, 0x0D68, 0x3EC8, + 0x1FB1, 0x0236, 0x034A, 0x1FB0, 0x108A, 0x108B, + 0x0CA0, 0x0D67, 0x0687, 0x0748, 0x0664, 0x038B, + 0x023E, 0x01DA, 0x01DB, 0x006E, 0x0094, 0x00E6, + 0x033E, 0x043A, 0x06CD, 0x085E, 0x085F, 0x0D69, + 0x0D6A, 0x1FB3, 0x1FB4, 0x3ECA, 0x034B, 0x023F, + 0x3EC9, 0x108C, 0x1FB2, 0x15F0, 0x15F1, 0x074B, + 0x06CC, 0x074C, 0x038C, 0x0268, 0x0136, 0x0095, + 0x0014, 0x001E, 0x0097, 0x019C, 0x074D, 0x0D6C, + 0x06CE, 0x0CA2, 0x108E, 0x09EC, 0x3ECD, 0x108F, + 0x3ECE, 0x026A, 0x02AA, 0x3ECB, 0x1FB5, 0x15F2, + 0x3ECC, 0x15F3, 0x15F4, 0x0D6B, 0x108D, 0x043B, + 0x0269, 0x0096, 0x0022, +}; + +static const uint8_t on2avc_cb14_bits[ON2AVC_CB14_CODES] = { + 1, 5, 8, 10, 11, 12, + 14, 13, 12, 13, 14, 14, + 14, 10, 10, 14, 14, 13, + 13, 14, 13, 13, 12, 11, + 10, 8, 5, 5, 6, 8, + 10, 11, 10, 13, 12, 13, + 13, 14, 13, 13, 9, 9, + 14, 13, 13, 12, 14, 14, + 11, 12, 11, 9, 8, 6, + 7, 8, 8, 10, 10, 11, + 11, 12, 11, 12, 13, 14, + 13, 9, 10, 13, 13, 13, + 13, 12, 11, 11, 12, 10, + 10, 8, 8, 9, 9, 9, + 10, 11, 11, 12, 12, 12, + 12, 13, 13, 14, 10, 9, + 14, 14, 14, 14, 13, 13, + 12, 11, 11, 10, 10, 9, + 11, 12, 11, 11, 11, 12, + 12, 12, 12, 11, 13, 14, + 13, 10, 10, 14, 13, 14, + 12, 13, 12, 13, 13, 13, + 11, 11, 11, 14, 12, 11, + 12, 11, 11, 12, 12, 12, + 12, 14, 14, 14, 10, 10, + 14, 13, 14, 12, 12, 12, + 12, 11, 12, 11, 11, 13, + 13, 12, 11, 11, 12, 13, + 11, 11, 11, 12, 12, 13, + 13, 10, 10, 14, 13, 14, + 13, 13, 13, 12, 12, 12, + 13, 11, 12, 13, 13, 11, + 12, 13, 12, 12, 11, 12, + 14, 12, 12, 14, 10, 11, + 14, 13, 13, 13, 14, 13, + 13, 13, 13, 14, 12, 13, + 13, 13, 13, 12, 12, 13, + 12, 13, 12, 13, 13, 13, + 13, 11, 11, 14, 14, 13, + 13, 14, 14, 13, 13, 12, + 13, 14, 13, 13, 14, 12, + 12, 13, 13, 12, 13, 13, + 11, 12, 14, 13, 11, 11, + 14, 14, 14, 14, 14, 12, + 14, 13, 13, 13, 12, 14, + 13, 12, 14, 13, 14, 13, + 13, 13, 13, 14, 12, 12, + 14, 11, 12, 13, 14, 13, + 13, 14, 12, 13, 13, 14, + 13, 14, 13, 14, 13, 13, + 12, 14, 13, 14, 13, 13, + 12, 12, 13, 13, 11, 11, + 14, 14, 13, 14, 14, 14, + 14, 14, 14, 14, 13, 13, + 14, 13, 13, 14, 14, 13, + 14, 13, 13, 12, 12, 13, + 12, 12, 12, 14, 13, 13, + 14, 13, 13, 13, 14, 14, + 14, 13, 14, 10, 9, 10, + 9, 10, 10, 12, 10, 10, + 11, 11, 12, 11, 11, 12, + 13, 12, 11, 11, 11, 10, + 12, 10, 10, 10, 9, 9, + 10, 9, 10, 10, 10, 10, + 10, 11, 11, 11, 12, 11, + 12, 12, 11, 11, 11, 12, + 11, 10, 11, 10, 10, 10, + 10, 9, 9, 14, 14, 13, + 14, 14, 12, 14, 14, 14, + 14, 14, 14, 14, 12, 10, + 13, 13, 13, 12, 14, 14, + 14, 14, 14, 14, 13, 13, + 14, 14, 12, 14, 14, 14, + 14, 14, 14, 14, 14, 14, + 14, 12, 11, 12, 12, 13, + 12, 14, 13, 14, 13, 14, + 13, 14, 12, 14, 13, 12, + 12, 14, 13, 13, 12, 14, + 14, 14, 12, 14, 11, 11, + 14, 13, 13, 12, 12, 12, + 12, 13, 13, 12, 13, 14, + 14, 12, 13, 13, 13, 13, + 12, 13, 14, 14, 14, 14, + 14, 11, 11, 14, 12, 13, + 12, 14, 12, 14, 12, 12, + 12, 11, 13, 14, 13, 11, + 12, 13, 13, 12, 13, 13, + 14, 14, 14, 14, 11, 11, + 14, 13, 12, 14, 13, 12, + 12, 12, 12, 12, 13, 13, + 13, 13, 11, 12, 13, 12, + 13, 13, 13, 13, 14, 14, + 14, 11, 11, 14, 13, 12, + 13, 13, 13, 12, 12, 13, + 12, 11, 12, 13, 12, 12, + 12, 13, 12, 12, 12, 12, + 13, 13, 13, 14, 11, 10, + 13, 13, 14, 11, 13, 13, + 11, 12, 12, 12, 11, 12, + 13, 12, 11, 11, 12, 14, + 13, 13, 13, 13, 13, 14, + 14, 10, 10, 13, 13, 14, + 13, 13, 12, 11, 12, 11, + 11, 11, 11, 12, 11, 11, + 11, 11, 12, 12, 13, 13, + 14, 13, 13, 14, 10, 10, + 14, 14, 13, 13, 14, 12, + 12, 12, 11, 11, 12, 12, + 9, 9, 9, 10, 10, 11, + 11, 11, 11, 12, 12, 14, + 13, 10, 10, 13, 13, 13, + 12, 12, 11, 11, 11, 10, + 10, 9, 9, 7, 8, 8, + 10, 11, 11, 12, 12, 12, + 12, 13, 13, 14, 10, 10, + 14, 13, 13, 13, 13, 11, + 11, 11, 10, 10, 9, 8, + 5, 5, 8, 9, 11, 12, + 11, 12, 13, 12, 14, 13, + 14, 10, 10, 14, 13, 13, + 14, 13, 13, 12, 13, 11, + 10, 8, 6, +}; + +static const uint16_t on2avc_cb14_syms[ON2AVC_CB14_CODES] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, + 0x000C, 0x000D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, + 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, + 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x0101, 0x0102, + 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, + 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x01F3, + 0x01F4, 0x01F5, 0x01F6, 0x01F7, 0x01F8, 0x01F9, + 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, + 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, + 0x0206, 0x0207, 0x0208, 0x0209, 0x020A, 0x020B, + 0x020C, 0x020D, 0x02F3, 0x02F4, 0x02F5, 0x02F6, + 0x02F7, 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, + 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, + 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, + 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x03F3, + 0x03F4, 0x03F5, 0x03F6, 0x03F7, 0x03F8, 0x03F9, + 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, + 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, + 0x040C, 0x040D, 0x04F3, 0x04F4, 0x04F5, 0x04F6, + 0x04F7, 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, + 0x04FD, 0x04FE, 0x04FF, 0x0500, 0x0501, 0x0502, + 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, + 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x05F3, + 0x05F4, 0x05F5, 0x05F6, 0x05F7, 0x05F8, 0x05F9, + 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, + 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, + 0x0606, 0x0607, 0x0608, 0x0609, 0x060A, 0x060B, + 0x060C, 0x060D, 0x06F3, 0x06F4, 0x06F5, 0x06F6, + 0x06F7, 0x06F8, 0x06F9, 0x06FA, 0x06FB, 0x06FC, + 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, + 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, + 0x0709, 0x070A, 0x070B, 0x070C, 0x070D, 0x07F3, + 0x07F4, 0x07F5, 0x07F6, 0x07F7, 0x07F8, 0x07F9, + 0x07FA, 0x07FB, 0x07FC, 0x07FD, 0x07FE, 0x07FF, + 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, + 0x0806, 0x0807, 0x0808, 0x0809, 0x080A, 0x080B, + 0x080C, 0x080D, 0x08F3, 0x08F4, 0x08F5, 0x08F6, + 0x08F7, 0x08F8, 0x08F9, 0x08FA, 0x08FB, 0x08FC, + 0x08FD, 0x08FE, 0x08FF, 0x0900, 0x0901, 0x0902, + 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, + 0x0909, 0x090A, 0x090B, 0x090C, 0x090D, 0x09F3, + 0x09F4, 0x09F5, 0x09F6, 0x09F7, 0x09F8, 0x09F9, + 0x09FA, 0x09FB, 0x09FC, 0x09FD, 0x09FE, 0x09FF, + 0x0A00, 0x0A01, 0x0A02, 0x0A03, 0x0A04, 0x0A05, + 0x0A06, 0x0A07, 0x0A08, 0x0A09, 0x0A0A, 0x0A0B, + 0x0A0C, 0x0A0D, 0x0AF3, 0x0AF4, 0x0AF5, 0x0AF6, + 0x0AF7, 0x0AF8, 0x0AF9, 0x0AFA, 0x0AFB, 0x0AFC, + 0x0AFD, 0x0AFE, 0x0AFF, 0x0B00, 0x0B01, 0x0B02, + 0x0B03, 0x0B04, 0x0B05, 0x0B06, 0x0B07, 0x0B08, + 0x0B09, 0x0B0A, 0x0B0B, 0x0B0C, 0x0B0D, 0x0BF3, + 0x0BF4, 0x0BF5, 0x0BF6, 0x0BF7, 0x0BF8, 0x0BF9, + 0x0BFA, 0x0BFB, 0x0BFC, 0x0BFD, 0x0BFE, 0x0BFF, + 0x0C00, 0x0C01, 0x0C02, 0x0C03, 0x0C04, 0x0C05, + 0x0C06, 0x0C07, 0x0C08, 0x0C09, 0x0C0A, 0x0C0B, + 0x0C0C, 0x0C0D, 0x0CF3, 0x0CF4, 0x0CF5, 0x0CF6, + 0x0CF7, 0x0CF8, 0x0CF9, 0x0CFA, 0x0CFB, 0x0CFC, + 0x0CFD, 0x0CFE, 0x0CFF, 0x0D00, 0x0D01, 0x0D02, + 0x0D03, 0x0D04, 0x0D05, 0x0D06, 0x0D07, 0x0D08, + 0x0D09, 0x0D0A, 0x0D0B, 0x0D0C, 0x0D0D, 0x0DF3, + 0x0DF4, 0x0DF5, 0x0DF6, 0x0DF7, 0x0DF8, 0x0DF9, + 0x0DFA, 0x0DFB, 0x0DFC, 0x0DFD, 0x0DFE, 0x0DFF, + 0xF300, 0xF301, 0xF302, 0xF303, 0xF304, 0xF305, + 0xF306, 0xF307, 0xF308, 0xF309, 0xF30A, 0xF30B, + 0xF30C, 0xF30D, 0xF3F3, 0xF3F4, 0xF3F5, 0xF3F6, + 0xF3F7, 0xF3F8, 0xF3F9, 0xF3FA, 0xF3FB, 0xF3FC, + 0xF3FD, 0xF3FE, 0xF3FF, 0xF400, 0xF401, 0xF402, + 0xF403, 0xF404, 0xF405, 0xF406, 0xF407, 0xF408, + 0xF409, 0xF40A, 0xF40B, 0xF40C, 0xF40D, 0xF4F3, + 0xF4F4, 0xF4F5, 0xF4F6, 0xF4F7, 0xF4F8, 0xF4F9, + 0xF4FA, 0xF4FB, 0xF4FC, 0xF4FD, 0xF4FE, 0xF4FF, + 0xF500, 0xF501, 0xF502, 0xF503, 0xF504, 0xF505, + 0xF506, 0xF507, 0xF508, 0xF509, 0xF50A, 0xF50B, + 0xF50C, 0xF50D, 0xF5F3, 0xF5F4, 0xF5F5, 0xF5F6, + 0xF5F7, 0xF5F8, 0xF5F9, 0xF5FA, 0xF5FB, 0xF5FC, + 0xF5FD, 0xF5FE, 0xF5FF, 0xF600, 0xF601, 0xF602, + 0xF603, 0xF604, 0xF605, 0xF606, 0xF607, 0xF608, + 0xF609, 0xF60A, 0xF60B, 0xF60C, 0xF60D, 0xF6F3, + 0xF6F4, 0xF6F5, 0xF6F6, 0xF6F7, 0xF6F8, 0xF6F9, + 0xF6FA, 0xF6FB, 0xF6FC, 0xF6FD, 0xF6FE, 0xF6FF, + 0xF700, 0xF701, 0xF702, 0xF703, 0xF704, 0xF705, + 0xF706, 0xF707, 0xF708, 0xF709, 0xF70A, 0xF70B, + 0xF70C, 0xF70D, 0xF7F3, 0xF7F4, 0xF7F5, 0xF7F6, + 0xF7F7, 0xF7F8, 0xF7F9, 0xF7FA, 0xF7FB, 0xF7FC, + 0xF7FD, 0xF7FE, 0xF7FF, 0xF800, 0xF801, 0xF802, + 0xF803, 0xF804, 0xF805, 0xF806, 0xF807, 0xF808, + 0xF809, 0xF80A, 0xF80B, 0xF80C, 0xF80D, 0xF8F3, + 0xF8F4, 0xF8F5, 0xF8F6, 0xF8F7, 0xF8F8, 0xF8F9, + 0xF8FA, 0xF8FB, 0xF8FC, 0xF8FD, 0xF8FE, 0xF8FF, + 0xF900, 0xF901, 0xF902, 0xF903, 0xF904, 0xF905, + 0xF906, 0xF907, 0xF908, 0xF909, 0xF90A, 0xF90B, + 0xF90C, 0xF90D, 0xF9F3, 0xF9F4, 0xF9F5, 0xF9F6, + 0xF9F7, 0xF9F8, 0xF9F9, 0xF9FA, 0xF9FB, 0xF9FC, + 0xF9FD, 0xF9FE, 0xF9FF, 0xFA00, 0xFA01, 0xFA02, + 0xFA03, 0xFA04, 0xFA05, 0xFA06, 0xFA07, 0xFA08, + 0xFA09, 0xFA0A, 0xFA0B, 0xFA0C, 0xFA0D, 0xFAF3, + 0xFAF4, 0xFAF5, 0xFAF6, 0xFAF7, 0xFAF8, 0xFAF9, + 0xFAFA, 0xFAFB, 0xFAFC, 0xFAFD, 0xFAFE, 0xFAFF, + 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0xFB05, + 0xFB06, 0xFB07, 0xFB08, 0xFB09, 0xFB0A, 0xFB0B, + 0xFB0C, 0xFB0D, 0xFBF3, 0xFBF4, 0xFBF5, 0xFBF6, + 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, + 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, 0xFC01, 0xFC02, + 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08, + 0xFC09, 0xFC0A, 0xFC0B, 0xFC0C, 0xFC0D, 0xFCF3, + 0xFCF4, 0xFCF5, 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, + 0xFCFA, 0xFCFB, 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, + 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04, 0xFD05, + 0xFD06, 0xFD07, 0xFD08, 0xFD09, 0xFD0A, 0xFD0B, + 0xFD0C, 0xFD0D, 0xFDF3, 0xFDF4, 0xFDF5, 0xFDF6, + 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, + 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, 0xFE01, 0xFE02, + 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, + 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 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, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, + 0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, + 0xFFFD, 0xFFFE, 0xFFFF, +}; + +#define ON2AVC_CB15_CODES 1089 +static const uint16_t on2avc_cb15_codes[ON2AVC_CB15_CODES] = { + 0x00000, 0x0000A, 0x00064, 0x00104, 0x0034B, 0x0047B, + 0x007D7, 0x00E14, 0x00957, 0x021FD, 0x013B0, 0x03F08, + 0x07A01, 0x0E579, 0x00E15, 0x013A1, 0x003A2, 0x00397, + 0x0137F, 0x01F96, 0x021FC, 0x034CD, 0x01E97, 0x01A82, + 0x013A0, 0x01A83, 0x0089D, 0x00F6B, 0x0076C, 0x0026A, + 0x00118, 0x0006E, 0x00008, 0x0000B, 0x00015, 0x00076, + 0x000EC, 0x001D2, 0x003A6, 0x00716, 0x00726, 0x01F98, + 0x00E77, 0x01BF0, 0x01A84, 0x021FE, 0x021FF, 0x00D93, + 0x01A85, 0x0036E, 0x003B4, 0x00FFE, 0x00FDF, 0x07A02, + 0x065AF, 0x01E98, 0x01F97, 0x00E16, 0x00F30, 0x00CF0, + 0x00846, 0x00398, 0x0020F, 0x000EB, 0x00074, 0x00012, + 0x0007C, 0x00049, 0x0009C, 0x00136, 0x00344, 0x0026D, + 0x0076E, 0x00847, 0x00F6C, 0x00958, 0x01A86, 0x00F6D, + 0x013A3, 0x013B1, 0x009F8, 0x00F31, 0x0032F, 0x00268, + 0x00FE0, 0x0076D, 0x01F99, 0x013A2, 0x03D05, 0x0111A, + 0x00FFF, 0x00CF1, 0x0080D, 0x004FA, 0x0040B, 0x0023E, + 0x0011B, 0x0008E, 0x00077, 0x0010A, 0x000F8, 0x001B0, + 0x001D4, 0x003D9, 0x004C6, 0x006AE, 0x007DE, 0x0080E, + 0x00F33, 0x00E78, 0x01BF1, 0x0111B, 0x034CE, 0x00959, + 0x0111C, 0x00262, 0x001FA, 0x00F32, 0x00FE1, 0x02200, + 0x01F9A, 0x013A4, 0x00E17, 0x00FE2, 0x004B7, 0x00FE3, + 0x00717, 0x00453, 0x00366, 0x001C6, 0x0011A, 0x0010E, + 0x0032B, 0x0023F, 0x00345, 0x0035A, 0x0036F, 0x007B6, + 0x00E19, 0x00705, 0x0076F, 0x0111D, 0x00E79, 0x00D57, + 0x01BF4, 0x01A87, 0x0095B, 0x0095C, 0x00216, 0x0039A, + 0x00F34, 0x0095A, 0x01BF2, 0x01BF3, 0x01000, 0x00F6E, + 0x00F6F, 0x00E18, 0x007DF, 0x008F1, 0x007BE, 0x003BD, + 0x003EB, 0x00342, 0x0022D, 0x00772, 0x007BF, 0x00454, + 0x00455, 0x0071E, 0x004FB, 0x00727, 0x0080F, 0x009E7, + 0x00E7C, 0x01BF6, 0x01A89, 0x01001, 0x01BF7, 0x0089E, + 0x00E1A, 0x0027F, 0x00334, 0x00F35, 0x00F36, 0x01BF5, + 0x01F9B, 0x013A5, 0x00E7A, 0x0095D, 0x00D58, 0x00E7B, + 0x01A88, 0x00FE4, 0x006CE, 0x0040E, 0x00687, 0x006D2, + 0x00E1C, 0x00706, 0x00747, 0x006B6, 0x0084E, 0x00CF2, + 0x006F2, 0x00D59, 0x00CF3, 0x01004, 0x013A6, 0x00F71, + 0x01A8B, 0x01E99, 0x00D5A, 0x00D94, 0x00335, 0x0022E, + 0x0095E, 0x00E1B, 0x01A8A, 0x01BF8, 0x01BF9, 0x01002, + 0x009F9, 0x00F70, 0x01003, 0x00773, 0x00F37, 0x00812, + 0x004D2, 0x004A3, 0x0089F, 0x013A9, 0x013AA, 0x00813, + 0x0081E, 0x00707, 0x008A0, 0x00E1E, 0x00D95, 0x008F2, + 0x009FB, 0x00E7D, 0x00E7E, 0x00F39, 0x01F9C, 0x00CF4, + 0x00F75, 0x00346, 0x0026E, 0x01005, 0x00F72, 0x013A7, + 0x0111E, 0x01BFA, 0x00F73, 0x013A8, 0x00F38, 0x00F74, + 0x009FA, 0x00FE5, 0x0084F, 0x0095F, 0x00E1D, 0x009EA, + 0x01A8D, 0x00E20, 0x00E21, 0x007CE, 0x00D96, 0x01008, + 0x00E22, 0x00960, 0x01121, 0x00E7F, 0x01122, 0x01A8E, + 0x01BFB, 0x01A8F, 0x008A1, 0x01009, 0x0035F, 0x00368, + 0x013B2, 0x01A8C, 0x01F9D, 0x02201, 0x01006, 0x0111F, + 0x013AB, 0x013AC, 0x01120, 0x00F76, 0x01007, 0x009FC, + 0x008F3, 0x00E1F, 0x01E9A, 0x01F9F, 0x013B3, 0x00F3B, + 0x00F77, 0x00F78, 0x00FE7, 0x009FD, 0x00FE8, 0x01123, + 0x00D97, 0x01BFF, 0x00E80, 0x01A93, 0x01124, 0x00D9E, + 0x00D5B, 0x003DA, 0x003A7, 0x00961, 0x01BFC, 0x01F9E, + 0x01BFD, 0x01BFE, 0x01A90, 0x01A91, 0x013AD, 0x00F3A, + 0x01A92, 0x00FE6, 0x00962, 0x0085E, 0x00963, 0x013AE, + 0x03D06, 0x01C01, 0x013B5, 0x00965, 0x01FA2, 0x02202, + 0x009FE, 0x00F79, 0x00F7A, 0x00E23, 0x00E26, 0x00966, + 0x013B1, 0x01E9C, 0x00F7B, 0x008A2, 0x003FE, 0x003AB, + 0x00964, 0x013B4, 0x01C00, 0x01E9B, 0x01FA0, 0x01FA1, + 0x0100A, 0x013AF, 0x03F09, 0x00E81, 0x01A94, 0x01125, + 0x01126, 0x01A95, 0x013B0, 0x03D08, 0x01E9E, 0x01FA3, + 0x013B4, 0x01A99, 0x0100B, 0x013B9, 0x00F3E, 0x00967, + 0x00E27, 0x0100C, 0x01E9F, 0x00968, 0x01C05, 0x00F3F, + 0x00E82, 0x0039B, 0x00386, 0x01A96, 0x01C02, 0x03D07, + 0x013B6, 0x01C03, 0x01E9D, 0x01127, 0x01A97, 0x01C04, + 0x013B2, 0x013B3, 0x013B7, 0x01A98, 0x013B8, 0x03F0A, + 0x0E57A, 0x07A03, 0x013BB, 0x01FA4, 0x01A9C, 0x01FA5, + 0x01FA6, 0x013BC, 0x0100D, 0x01FA7, 0x013B5, 0x0100E, + 0x01A9D, 0x0100F, 0x0096A, 0x01128, 0x00328, 0x003FF, + 0x00969, 0x01EA0, 0x01C06, 0x013BA, 0x01A9A, 0x034CF, + 0x00F7C, 0x02203, 0x034D2, 0x01EA1, 0x01C07, 0x02204, + 0x01A9B, 0x01EA2, 0x06982, 0x03D09, 0x0E57B, 0x01FA8, + 0x013C2, 0x013C3, 0x01129, 0x01FA9, 0x0112A, 0x01010, + 0x01FAA, 0x01EA6, 0x03F0F, 0x013B6, 0x00CF5, 0x0072A, + 0x00F7D, 0x00340, 0x0025F, 0x02205, 0x02206, 0x06983, + 0x01C08, 0x013BD, 0x013BE, 0x01EA3, 0x013BF, 0x034D3, + 0x01EA4, 0x02207, 0x01A9E, 0x01EA5, 0x03F0B, 0x03F0E, + 0x01AA2, 0x00E00, 0x00E3E, 0x00D9F, 0x00D5F, 0x00CF7, + 0x00CFE, 0x01011, 0x00E85, 0x00E01, 0x00E02, 0x0096B, + 0x00CFF, 0x00F92, 0x00D6E, 0x008CA, 0x00359, 0x00456, + 0x01CAE, 0x03D0A, 0x01A9F, 0x0112B, 0x00E83, 0x013B7, + 0x00F7E, 0x009FF, 0x00E84, 0x00FE9, 0x009EB, 0x00F7F, + 0x008A3, 0x00D5E, 0x00CF6, 0x0112E, 0x0112F, 0x01016, + 0x00F93, 0x01FAE, 0x00FEA, 0x00FEB, 0x009A6, 0x00E03, + 0x01C0A, 0x01017, 0x01C0B, 0x01FAF, 0x00F9E, 0x013BB, + 0x0196A, 0x0039C, 0x003F6, 0x0379A, 0x03D0B, 0x01FAB, + 0x01EA7, 0x013B8, 0x01012, 0x01AA3, 0x01C09, 0x013B9, + 0x01013, 0x00CB4, 0x00E86, 0x01F3E, 0x013BA, 0x00E87, + 0x007FB, 0x003CF, 0x0037A, 0x003AD, 0x00387, 0x0038A, + 0x003B5, 0x0039E, 0x0026F, 0x0038B, 0x00272, 0x0039F, + 0x00399, 0x0038E, 0x00252, 0x0039A, 0x00018, 0x0001B, + 0x003CE, 0x00457, 0x003E8, 0x0067E, 0x0041A, 0x003BE, + 0x003BF, 0x003EE, 0x00437, 0x0039D, 0x003AC, 0x00464, + 0x003C6, 0x003C7, 0x0041B, 0x007F6, 0x0042E, 0x0025C, + 0x0038C, 0x003BA, 0x003E9, 0x003EA, 0x00271, 0x003BB, + 0x0026A, 0x0025D, 0x0025E, 0x00389, 0x003EE, 0x004F4, + 0x00415, 0x0001A, 0x00017, 0x00388, 0x0038E, 0x003FC, + 0x00270, 0x00378, 0x0038A, 0x003AE, 0x003AA, 0x00398, + 0x003E8, 0x00358, 0x00414, 0x00384, 0x003B8, 0x006D3, + 0x01A6B, 0x00FEA, 0x01BCE, 0x009E4, 0x00E56, 0x01BCF, + 0x0131D, 0x009E5, 0x01BD8, 0x01BD9, 0x034C0, 0x01F86, + 0x01A6C, 0x01F3F, 0x065AC, 0x072BE, 0x00436, 0x0022C, + 0x009E0, 0x00F54, 0x009E2, 0x01104, 0x01105, 0x00FE8, + 0x009E3, 0x00FE9, 0x00F55, 0x0131C, 0x01A68, 0x01A6A, + 0x00E06, 0x01106, 0x01BCC, 0x00E6E, 0x00E3F, 0x00CB7, + 0x00F28, 0x00702, 0x0094E, 0x00F29, 0x00FEC, 0x00F2A, + 0x0131E, 0x00F56, 0x0131F, 0x00F57, 0x0110A, 0x0134E, + 0x01E86, 0x00712, 0x001F6, 0x0081F, 0x00D6F, 0x00FEB, + 0x01107, 0x00CB6, 0x0094C, 0x01BDA, 0x01108, 0x01109, + 0x009E6, 0x00E6C, 0x01F88, 0x00E6D, 0x00896, 0x0094D, + 0x03F00, 0x01E88, 0x0217C, 0x03F01, 0x03F02, 0x01399, + 0x01E89, 0x0E578, 0x0139A, 0x01E8A, 0x01F8A, 0x01F8B, + 0x01E8B, 0x03D02, 0x01F8C, 0x0139B, 0x00392, 0x0035E, + 0x00F58, 0x009DE, 0x0094F, 0x01358, 0x01359, 0x0135A, + 0x0134F, 0x01BDB, 0x0135B, 0x0379B, 0x01F89, 0x01398, + 0x034C2, 0x065AD, 0x01E87, 0x03F04, 0x07A00, 0x0217D, + 0x01A6D, 0x065AE, 0x01E8C, 0x0217E, 0x01BDD, 0x0135C, + 0x01A6E, 0x034C4, 0x01E8D, 0x03F05, 0x01E8E, 0x0217F, + 0x0139D, 0x003F7, 0x0032C, 0x034C3, 0x00E07, 0x0110B, + 0x009E7, 0x00F59, 0x03D03, 0x00D8A, 0x01F8D, 0x00E6F, + 0x00FED, 0x03F03, 0x00FEE, 0x01BDC, 0x0139C, 0x072BF, + 0x03F06, 0x021F2, 0x01A70, 0x021F3, 0x0135E, 0x0139E, + 0x01F8E, 0x01F8F, 0x0139F, 0x01E91, 0x013A0, 0x0135F, + 0x034C6, 0x0110E, 0x01A71, 0x021F4, 0x0026C, 0x00206, + 0x0110C, 0x009E8, 0x01BDE, 0x00F5A, 0x00FEF, 0x0135D, + 0x00FF0, 0x01E8F, 0x021F0, 0x009E9, 0x01E90, 0x021F1, + 0x01A6F, 0x0110D, 0x034C5, 0x021F5, 0x01A73, 0x01BE2, + 0x01BE3, 0x01F91, 0x01A74, 0x00E70, 0x021F6, 0x034C8, + 0x00FF3, 0x01F92, 0x013A1, 0x013A2, 0x013A3, 0x01A75, + 0x01372, 0x003BC, 0x00341, 0x034C7, 0x00950, 0x00FF1, + 0x00FF2, 0x009EA, 0x00F5B, 0x01370, 0x01BDF, 0x01371, + 0x01A72, 0x01BE0, 0x009EB, 0x01F90, 0x0110F, 0x01BE1, + 0x01E92, 0x013A6, 0x00D8B, 0x00FD8, 0x01BE5, 0x00FF4, + 0x00FF5, 0x01BE6, 0x013A7, 0x00F5F, 0x01BE7, 0x021F7, + 0x021F8, 0x034C9, 0x009EC, 0x013A8, 0x003EF, 0x00269, + 0x00CD8, 0x00FD6, 0x00F5C, 0x013A4, 0x00F5D, 0x00F2B, + 0x00E08, 0x01110, 0x01BE4, 0x00E09, 0x013A5, 0x00F2C, + 0x00898, 0x00F5E, 0x01A76, 0x013A9, 0x00D8C, 0x009DF, + 0x009E0, 0x00FF8, 0x00D8D, 0x01374, 0x01A78, 0x01112, + 0x01BE8, 0x01A79, 0x01F93, 0x01113, 0x01375, 0x00F61, + 0x01376, 0x00399, 0x0027C, 0x009ED, 0x00F60, 0x01373, + 0x01A77, 0x00951, 0x009EE, 0x00D50, 0x00CD9, 0x00FF6, + 0x00FD9, 0x00FF7, 0x00899, 0x007C8, 0x00D52, 0x01111, + 0x009EF, 0x007D3, 0x007D4, 0x0071E, 0x00CDB, 0x00746, + 0x00E0A, 0x00E0B, 0x021F9, 0x00FF9, 0x01A7A, 0x00952, + 0x013AB, 0x01377, 0x009F0, 0x01E93, 0x003AF, 0x0032E, + 0x009E1, 0x007CA, 0x013AA, 0x01114, 0x00F62, 0x00E71, + 0x008CB, 0x008CC, 0x0089A, 0x008CD, 0x00840, 0x00CDA, + 0x007D2, 0x009E2, 0x00E72, 0x00F63, 0x006D6, 0x00841, + 0x0079E, 0x00D53, 0x008CE, 0x00955, 0x00E0C, 0x0137A, + 0x00E74, 0x01115, 0x01F94, 0x01116, 0x01BEA, 0x00E0D, + 0x01A7B, 0x0038D, 0x0033E, 0x00CDC, 0x00D8E, 0x01BE9, + 0x01378, 0x01379, 0x00FDA, 0x00E73, 0x00953, 0x00954, + 0x009E3, 0x004D6, 0x007B7, 0x007BA, 0x007BB, 0x004A0, + 0x0089B, 0x006D7, 0x0047A, 0x00408, 0x007F7, 0x00E0E, + 0x009E4, 0x007D5, 0x00842, 0x00D90, 0x009F1, 0x034CA, + 0x01A7C, 0x01A7D, 0x00E0F, 0x01A7E, 0x00329, 0x0021E, + 0x00F64, 0x01117, 0x021FA, 0x01118, 0x013AC, 0x013AD, + 0x00D8F, 0x008CF, 0x008F0, 0x0071F, 0x004A1, 0x00686, + 0x00426, 0x00416, 0x007CB, 0x003D8, 0x00264, 0x00347, + 0x003DC, 0x004F6, 0x004D7, 0x00F2D, 0x00F65, 0x009F3, + 0x00FDB, 0x00E75, 0x009F4, 0x0137B, 0x013AE, 0x009E5, + 0x00E10, 0x0027E, 0x0020C, 0x00FFA, 0x00956, 0x01BEB, + 0x01E94, 0x01E95, 0x00D91, 0x009F2, 0x00D54, 0x007BC, + 0x007BD, 0x0040A, 0x00385, 0x0036A, 0x0022F, 0x0020E, + 0x000FC, 0x000F2, 0x001AE, 0x001C8, 0x0034A, 0x004F7, + 0x00452, 0x00CDE, 0x00843, 0x00E76, 0x00F2E, 0x00F67, + 0x0137C, 0x01A7F, 0x0080C, 0x00FDC, 0x0021A, 0x001FC, + 0x00E11, 0x009F5, 0x01BEC, 0x00F66, 0x013AF, 0x00CDD, + 0x00E12, 0x00D55, 0x00703, 0x0080A, 0x00394, 0x00265, + 0x001F6, 0x001B6, 0x0010C, 0x00078, 0x0004C, 0x000CC, + 0x001A4, 0x00212, 0x00396, 0x006C4, 0x0089C, 0x00CDF, + 0x01A80, 0x00F68, 0x00FFD, 0x0137D, 0x01F95, 0x00845, + 0x00E13, 0x00267, 0x00266, 0x00FFB, 0x009F6, 0x03D04, + 0x01BED, 0x01BEE, 0x034CB, 0x00FFC, 0x00844, 0x007D6, + 0x00704, 0x003C8, 0x0032A, 0x00130, 0x000CE, 0x00048, + 0x0000C, 0x00014, 0x0007A, 0x000F0, 0x001E6, 0x00417, + 0x004A2, 0x004B6, 0x00D92, 0x01A81, 0x009F7, 0x0137E, + 0x01E96, 0x03F07, 0x009E6, 0x00FDE, 0x003C9, 0x00268, + 0x00F2F, 0x00D56, 0x021FB, 0x034CC, 0x01BEF, 0x00F69, + 0x01119, 0x00F6A, 0x00FDD, 0x007FA, 0x003E6, 0x001E2, + 0x000EA, 0x00072, 0x00016, +}; + +static const uint8_t on2avc_cb15_bits[ON2AVC_CB15_CODES] = { + 2, 5, 7, 9, 10, 11, + 12, 12, 13, 14, 14, 14, + 16, 17, 12, 13, 11, 11, + 13, 13, 14, 14, 14, 13, + 13, 13, 12, 13, 12, 10, + 9, 7, 5, 5, 5, 7, + 9, 10, 11, 11, 12, 13, + 13, 13, 13, 14, 14, 12, + 13, 10, 11, 13, 12, 16, + 15, 14, 13, 12, 12, 12, + 12, 11, 10, 9, 7, 5, + 7, 8, 8, 9, 10, 11, + 12, 12, 13, 13, 13, 13, + 13, 14, 13, 12, 10, 10, + 12, 12, 13, 13, 15, 13, + 13, 12, 12, 11, 11, 10, + 9, 8, 7, 9, 9, 9, + 9, 10, 11, 11, 12, 12, + 12, 13, 13, 13, 14, 13, + 13, 10, 10, 12, 12, 14, + 13, 13, 12, 12, 12, 12, + 11, 11, 10, 10, 9, 9, + 10, 10, 10, 10, 10, 11, + 12, 12, 12, 13, 13, 12, + 13, 13, 13, 13, 10, 10, + 12, 13, 13, 13, 13, 13, + 13, 12, 12, 12, 11, 11, + 10, 10, 10, 12, 11, 11, + 11, 11, 11, 12, 12, 12, + 13, 13, 13, 13, 13, 12, + 12, 10, 10, 12, 12, 13, + 13, 13, 13, 13, 12, 13, + 13, 12, 11, 11, 11, 11, + 12, 12, 12, 11, 12, 12, + 11, 12, 12, 13, 13, 13, + 13, 14, 12, 12, 10, 10, + 13, 12, 13, 13, 13, 13, + 13, 13, 13, 12, 12, 12, + 12, 12, 12, 13, 13, 12, + 12, 12, 12, 12, 12, 12, + 13, 13, 13, 12, 13, 12, + 13, 10, 11, 13, 13, 13, + 13, 13, 13, 13, 12, 13, + 13, 12, 12, 13, 12, 12, + 13, 12, 12, 12, 12, 13, + 12, 13, 13, 13, 13, 13, + 13, 13, 12, 13, 10, 10, + 14, 13, 13, 14, 13, 13, + 13, 13, 13, 13, 13, 13, + 12, 12, 14, 13, 14, 12, + 13, 13, 12, 13, 12, 13, + 12, 13, 13, 13, 13, 12, + 12, 10, 11, 13, 13, 13, + 13, 13, 13, 13, 13, 12, + 13, 12, 13, 12, 13, 13, + 15, 13, 14, 13, 13, 14, + 13, 13, 13, 12, 12, 13, + 13, 14, 13, 12, 10, 10, + 13, 14, 13, 14, 13, 13, + 13, 13, 14, 13, 13, 13, + 13, 13, 13, 15, 14, 13, + 13, 13, 13, 14, 12, 13, + 12, 13, 14, 13, 13, 12, + 13, 10, 11, 13, 13, 15, + 14, 13, 14, 13, 13, 13, + 13, 13, 14, 13, 14, 14, + 17, 16, 14, 13, 13, 13, + 13, 14, 13, 13, 13, 13, + 13, 13, 13, 13, 10, 10, + 13, 14, 13, 14, 13, 14, + 13, 14, 14, 14, 13, 14, + 13, 14, 15, 15, 17, 13, + 14, 14, 13, 13, 13, 13, + 13, 14, 14, 13, 12, 12, + 13, 10, 11, 14, 14, 15, + 13, 14, 14, 14, 14, 14, + 14, 14, 13, 14, 14, 14, + 13, 13, 12, 12, 12, 12, + 12, 13, 13, 13, 13, 13, + 12, 13, 12, 12, 10, 11, + 14, 15, 13, 13, 13, 13, + 13, 13, 13, 12, 12, 13, + 12, 12, 12, 13, 13, 13, + 13, 13, 12, 12, 13, 13, + 13, 13, 13, 13, 13, 13, + 13, 10, 11, 14, 15, 13, + 14, 13, 13, 13, 13, 13, + 13, 12, 13, 14, 13, 13, + 11, 11, 10, 10, 11, 11, + 11, 10, 11, 11, 11, 10, + 11, 11, 11, 11, 5, 6, + 11, 11, 11, 11, 11, 11, + 11, 10, 11, 10, 10, 11, + 11, 11, 11, 11, 11, 11, + 10, 11, 10, 10, 11, 11, + 11, 11, 11, 11, 11, 11, + 11, 6, 5, 11, 10, 10, + 11, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, + 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 14, 13, + 13, 14, 15, 16, 11, 10, + 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, + 12, 13, 13, 13, 12, 12, + 12, 12, 13, 12, 13, 12, + 13, 13, 13, 13, 13, 14, + 14, 11, 10, 12, 12, 13, + 13, 12, 13, 13, 13, 13, + 13, 13, 13, 13, 12, 13, + 14, 14, 14, 14, 14, 14, + 14, 17, 14, 14, 13, 13, + 14, 15, 13, 14, 11, 10, + 13, 12, 13, 13, 13, 13, + 14, 13, 13, 14, 13, 14, + 14, 15, 14, 14, 16, 14, + 13, 15, 14, 14, 13, 13, + 13, 14, 14, 14, 14, 14, + 14, 11, 10, 14, 12, 13, + 13, 13, 15, 12, 13, 13, + 13, 14, 13, 13, 14, 16, + 14, 14, 13, 14, 13, 14, + 13, 13, 14, 14, 14, 13, + 14, 13, 13, 14, 11, 10, + 13, 13, 13, 13, 13, 13, + 13, 14, 14, 13, 14, 14, + 13, 13, 14, 14, 13, 13, + 13, 13, 13, 13, 14, 14, + 13, 13, 14, 14, 14, 13, + 13, 11, 10, 14, 13, 13, + 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, + 14, 14, 12, 12, 13, 13, + 13, 13, 14, 13, 13, 14, + 14, 14, 13, 14, 10, 10, + 12, 12, 13, 14, 13, 12, + 12, 13, 13, 12, 14, 12, + 12, 13, 13, 14, 12, 12, + 12, 13, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, + 13, 10, 10, 13, 13, 13, + 13, 13, 13, 12, 12, 13, + 12, 13, 12, 12, 12, 13, + 13, 12, 12, 12, 12, 12, + 12, 12, 14, 13, 13, 13, + 14, 13, 13, 14, 10, 10, + 12, 12, 14, 13, 13, 13, + 12, 12, 12, 12, 12, 12, + 12, 12, 13, 13, 11, 12, + 11, 12, 12, 13, 12, 13, + 13, 13, 13, 13, 13, 12, + 13, 10, 10, 12, 12, 13, + 13, 13, 12, 13, 13, 13, + 12, 12, 11, 11, 11, 12, + 12, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 13, 14, + 13, 13, 12, 13, 10, 10, + 13, 13, 14, 13, 14, 14, + 12, 12, 12, 12, 12, 11, + 11, 11, 12, 10, 10, 10, + 10, 11, 12, 12, 13, 13, + 12, 13, 13, 13, 14, 12, + 12, 10, 10, 13, 13, 13, + 14, 14, 12, 13, 12, 11, + 11, 11, 11, 10, 10, 10, + 9, 9, 9, 10, 10, 11, + 11, 12, 12, 13, 12, 13, + 13, 13, 12, 12, 10, 10, + 12, 13, 13, 13, 14, 12, + 12, 12, 12, 12, 11, 10, + 9, 9, 9, 7, 8, 8, + 9, 10, 11, 11, 12, 12, + 13, 13, 13, 13, 13, 12, + 12, 10, 10, 13, 13, 15, + 13, 13, 14, 13, 12, 12, + 12, 10, 10, 9, 8, 8, + 5, 5, 7, 9, 10, 11, + 12, 12, 12, 13, 13, 13, + 14, 14, 12, 12, 10, 11, + 12, 12, 14, 14, 13, 13, + 13, 13, 12, 11, 11, 10, + 9, 7, 5, +}; + +static const uint16_t on2avc_cb15_syms[ON2AVC_CB15_CODES] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, + 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x00F0, + 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, + 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, + 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x0101, 0x0102, + 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, + 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, + 0x010F, 0x0110, 0x01F0, 0x01F1, 0x01F2, 0x01F3, + 0x01F4, 0x01F5, 0x01F6, 0x01F7, 0x01F8, 0x01F9, + 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, + 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, + 0x0206, 0x0207, 0x0208, 0x0209, 0x020A, 0x020B, + 0x020C, 0x020D, 0x020E, 0x020F, 0x0210, 0x02F0, + 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, + 0x02F7, 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, + 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, + 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, + 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, + 0x030F, 0x0310, 0x03F0, 0x03F1, 0x03F2, 0x03F3, + 0x03F4, 0x03F5, 0x03F6, 0x03F7, 0x03F8, 0x03F9, + 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, + 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, + 0x040C, 0x040D, 0x040E, 0x040F, 0x0410, 0x04F0, + 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, + 0x04F7, 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, + 0x04FD, 0x04FE, 0x04FF, 0x0500, 0x0501, 0x0502, + 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, + 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, + 0x050F, 0x0510, 0x05F0, 0x05F1, 0x05F2, 0x05F3, + 0x05F4, 0x05F5, 0x05F6, 0x05F7, 0x05F8, 0x05F9, + 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, + 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, + 0x0606, 0x0607, 0x0608, 0x0609, 0x060A, 0x060B, + 0x060C, 0x060D, 0x060E, 0x060F, 0x0610, 0x06F0, + 0x06F1, 0x06F2, 0x06F3, 0x06F4, 0x06F5, 0x06F6, + 0x06F7, 0x06F8, 0x06F9, 0x06FA, 0x06FB, 0x06FC, + 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, + 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, + 0x0709, 0x070A, 0x070B, 0x070C, 0x070D, 0x070E, + 0x070F, 0x0710, 0x07F0, 0x07F1, 0x07F2, 0x07F3, + 0x07F4, 0x07F5, 0x07F6, 0x07F7, 0x07F8, 0x07F9, + 0x07FA, 0x07FB, 0x07FC, 0x07FD, 0x07FE, 0x07FF, + 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, + 0x0806, 0x0807, 0x0808, 0x0809, 0x080A, 0x080B, + 0x080C, 0x080D, 0x080E, 0x080F, 0x0810, 0x08F0, + 0x08F1, 0x08F2, 0x08F3, 0x08F4, 0x08F5, 0x08F6, + 0x08F7, 0x08F8, 0x08F9, 0x08FA, 0x08FB, 0x08FC, + 0x08FD, 0x08FE, 0x08FF, 0x0900, 0x0901, 0x0902, + 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, + 0x0909, 0x090A, 0x090B, 0x090C, 0x090D, 0x090E, + 0x090F, 0x0910, 0x09F0, 0x09F1, 0x09F2, 0x09F3, + 0x09F4, 0x09F5, 0x09F6, 0x09F7, 0x09F8, 0x09F9, + 0x09FA, 0x09FB, 0x09FC, 0x09FD, 0x09FE, 0x09FF, + 0x0A00, 0x0A01, 0x0A02, 0x0A03, 0x0A04, 0x0A05, + 0x0A06, 0x0A07, 0x0A08, 0x0A09, 0x0A0A, 0x0A0B, + 0x0A0C, 0x0A0D, 0x0A0E, 0x0A0F, 0x0A10, 0x0AF0, + 0x0AF1, 0x0AF2, 0x0AF3, 0x0AF4, 0x0AF5, 0x0AF6, + 0x0AF7, 0x0AF8, 0x0AF9, 0x0AFA, 0x0AFB, 0x0AFC, + 0x0AFD, 0x0AFE, 0x0AFF, 0x0B00, 0x0B01, 0x0B02, + 0x0B03, 0x0B04, 0x0B05, 0x0B06, 0x0B07, 0x0B08, + 0x0B09, 0x0B0A, 0x0B0B, 0x0B0C, 0x0B0D, 0x0B0E, + 0x0B0F, 0x0B10, 0x0BF0, 0x0BF1, 0x0BF2, 0x0BF3, + 0x0BF4, 0x0BF5, 0x0BF6, 0x0BF7, 0x0BF8, 0x0BF9, + 0x0BFA, 0x0BFB, 0x0BFC, 0x0BFD, 0x0BFE, 0x0BFF, + 0x0C00, 0x0C01, 0x0C02, 0x0C03, 0x0C04, 0x0C05, + 0x0C06, 0x0C07, 0x0C08, 0x0C09, 0x0C0A, 0x0C0B, + 0x0C0C, 0x0C0D, 0x0C0E, 0x0C0F, 0x0C10, 0x0CF0, + 0x0CF1, 0x0CF2, 0x0CF3, 0x0CF4, 0x0CF5, 0x0CF6, + 0x0CF7, 0x0CF8, 0x0CF9, 0x0CFA, 0x0CFB, 0x0CFC, + 0x0CFD, 0x0CFE, 0x0CFF, 0x0D00, 0x0D01, 0x0D02, + 0x0D03, 0x0D04, 0x0D05, 0x0D06, 0x0D07, 0x0D08, + 0x0D09, 0x0D0A, 0x0D0B, 0x0D0C, 0x0D0D, 0x0D0E, + 0x0D0F, 0x0D10, 0x0DF0, 0x0DF1, 0x0DF2, 0x0DF3, + 0x0DF4, 0x0DF5, 0x0DF6, 0x0DF7, 0x0DF8, 0x0DF9, + 0x0DFA, 0x0DFB, 0x0DFC, 0x0DFD, 0x0DFE, 0x0DFF, + 0x0E00, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, + 0x0E06, 0x0E07, 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, + 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0EF0, + 0x0EF1, 0x0EF2, 0x0EF3, 0x0EF4, 0x0EF5, 0x0EF6, + 0x0EF7, 0x0EF8, 0x0EF9, 0x0EFA, 0x0EFB, 0x0EFC, + 0x0EFD, 0x0EFE, 0x0EFF, 0x0F00, 0x0F01, 0x0F02, + 0x0F03, 0x0F04, 0x0F05, 0x0F06, 0x0F07, 0x0F08, + 0x0F09, 0x0F0A, 0x0F0B, 0x0F0C, 0x0F0D, 0x0F0E, + 0x0F0F, 0x0F10, 0x0FF0, 0x0FF1, 0x0FF2, 0x0FF3, + 0x0FF4, 0x0FF5, 0x0FF6, 0x0FF7, 0x0FF8, 0x0FF9, + 0x0FFA, 0x0FFB, 0x0FFC, 0x0FFD, 0x0FFE, 0x0FFF, + 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, + 0x1006, 0x1007, 0x1008, 0x1009, 0x100A, 0x100B, + 0x100C, 0x100D, 0x100E, 0x100F, 0x1010, 0x10F0, + 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, + 0x10F7, 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, + 0x10FD, 0x10FE, 0x10FF, 0xF000, 0xF001, 0xF002, + 0xF003, 0xF004, 0xF005, 0xF006, 0xF007, 0xF008, + 0xF009, 0xF00A, 0xF00B, 0xF00C, 0xF00D, 0xF00E, + 0xF00F, 0xF010, 0xF0F0, 0xF0F1, 0xF0F2, 0xF0F3, + 0xF0F4, 0xF0F5, 0xF0F6, 0xF0F7, 0xF0F8, 0xF0F9, + 0xF0FA, 0xF0FB, 0xF0FC, 0xF0FD, 0xF0FE, 0xF0FF, + 0xF100, 0xF101, 0xF102, 0xF103, 0xF104, 0xF105, + 0xF106, 0xF107, 0xF108, 0xF109, 0xF10A, 0xF10B, + 0xF10C, 0xF10D, 0xF10E, 0xF10F, 0xF110, 0xF1F0, + 0xF1F1, 0xF1F2, 0xF1F3, 0xF1F4, 0xF1F5, 0xF1F6, + 0xF1F7, 0xF1F8, 0xF1F9, 0xF1FA, 0xF1FB, 0xF1FC, + 0xF1FD, 0xF1FE, 0xF1FF, 0xF200, 0xF201, 0xF202, + 0xF203, 0xF204, 0xF205, 0xF206, 0xF207, 0xF208, + 0xF209, 0xF20A, 0xF20B, 0xF20C, 0xF20D, 0xF20E, + 0xF20F, 0xF210, 0xF2F0, 0xF2F1, 0xF2F2, 0xF2F3, + 0xF2F4, 0xF2F5, 0xF2F6, 0xF2F7, 0xF2F8, 0xF2F9, + 0xF2FA, 0xF2FB, 0xF2FC, 0xF2FD, 0xF2FE, 0xF2FF, + 0xF300, 0xF301, 0xF302, 0xF303, 0xF304, 0xF305, + 0xF306, 0xF307, 0xF308, 0xF309, 0xF30A, 0xF30B, + 0xF30C, 0xF30D, 0xF30E, 0xF30F, 0xF310, 0xF3F0, + 0xF3F1, 0xF3F2, 0xF3F3, 0xF3F4, 0xF3F5, 0xF3F6, + 0xF3F7, 0xF3F8, 0xF3F9, 0xF3FA, 0xF3FB, 0xF3FC, + 0xF3FD, 0xF3FE, 0xF3FF, 0xF400, 0xF401, 0xF402, + 0xF403, 0xF404, 0xF405, 0xF406, 0xF407, 0xF408, + 0xF409, 0xF40A, 0xF40B, 0xF40C, 0xF40D, 0xF40E, + 0xF40F, 0xF410, 0xF4F0, 0xF4F1, 0xF4F2, 0xF4F3, + 0xF4F4, 0xF4F5, 0xF4F6, 0xF4F7, 0xF4F8, 0xF4F9, + 0xF4FA, 0xF4FB, 0xF4FC, 0xF4FD, 0xF4FE, 0xF4FF, + 0xF500, 0xF501, 0xF502, 0xF503, 0xF504, 0xF505, + 0xF506, 0xF507, 0xF508, 0xF509, 0xF50A, 0xF50B, + 0xF50C, 0xF50D, 0xF50E, 0xF50F, 0xF510, 0xF5F0, + 0xF5F1, 0xF5F2, 0xF5F3, 0xF5F4, 0xF5F5, 0xF5F6, + 0xF5F7, 0xF5F8, 0xF5F9, 0xF5FA, 0xF5FB, 0xF5FC, + 0xF5FD, 0xF5FE, 0xF5FF, 0xF600, 0xF601, 0xF602, + 0xF603, 0xF604, 0xF605, 0xF606, 0xF607, 0xF608, + 0xF609, 0xF60A, 0xF60B, 0xF60C, 0xF60D, 0xF60E, + 0xF60F, 0xF610, 0xF6F0, 0xF6F1, 0xF6F2, 0xF6F3, + 0xF6F4, 0xF6F5, 0xF6F6, 0xF6F7, 0xF6F8, 0xF6F9, + 0xF6FA, 0xF6FB, 0xF6FC, 0xF6FD, 0xF6FE, 0xF6FF, + 0xF700, 0xF701, 0xF702, 0xF703, 0xF704, 0xF705, + 0xF706, 0xF707, 0xF708, 0xF709, 0xF70A, 0xF70B, + 0xF70C, 0xF70D, 0xF70E, 0xF70F, 0xF710, 0xF7F0, + 0xF7F1, 0xF7F2, 0xF7F3, 0xF7F4, 0xF7F5, 0xF7F6, + 0xF7F7, 0xF7F8, 0xF7F9, 0xF7FA, 0xF7FB, 0xF7FC, + 0xF7FD, 0xF7FE, 0xF7FF, 0xF800, 0xF801, 0xF802, + 0xF803, 0xF804, 0xF805, 0xF806, 0xF807, 0xF808, + 0xF809, 0xF80A, 0xF80B, 0xF80C, 0xF80D, 0xF80E, + 0xF80F, 0xF810, 0xF8F0, 0xF8F1, 0xF8F2, 0xF8F3, + 0xF8F4, 0xF8F5, 0xF8F6, 0xF8F7, 0xF8F8, 0xF8F9, + 0xF8FA, 0xF8FB, 0xF8FC, 0xF8FD, 0xF8FE, 0xF8FF, + 0xF900, 0xF901, 0xF902, 0xF903, 0xF904, 0xF905, + 0xF906, 0xF907, 0xF908, 0xF909, 0xF90A, 0xF90B, + 0xF90C, 0xF90D, 0xF90E, 0xF90F, 0xF910, 0xF9F0, + 0xF9F1, 0xF9F2, 0xF9F3, 0xF9F4, 0xF9F5, 0xF9F6, + 0xF9F7, 0xF9F8, 0xF9F9, 0xF9FA, 0xF9FB, 0xF9FC, + 0xF9FD, 0xF9FE, 0xF9FF, 0xFA00, 0xFA01, 0xFA02, + 0xFA03, 0xFA04, 0xFA05, 0xFA06, 0xFA07, 0xFA08, + 0xFA09, 0xFA0A, 0xFA0B, 0xFA0C, 0xFA0D, 0xFA0E, + 0xFA0F, 0xFA10, 0xFAF0, 0xFAF1, 0xFAF2, 0xFAF3, + 0xFAF4, 0xFAF5, 0xFAF6, 0xFAF7, 0xFAF8, 0xFAF9, + 0xFAFA, 0xFAFB, 0xFAFC, 0xFAFD, 0xFAFE, 0xFAFF, + 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0xFB05, + 0xFB06, 0xFB07, 0xFB08, 0xFB09, 0xFB0A, 0xFB0B, + 0xFB0C, 0xFB0D, 0xFB0E, 0xFB0F, 0xFB10, 0xFBF0, + 0xFBF1, 0xFBF2, 0xFBF3, 0xFBF4, 0xFBF5, 0xFBF6, + 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, + 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, 0xFC01, 0xFC02, + 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08, + 0xFC09, 0xFC0A, 0xFC0B, 0xFC0C, 0xFC0D, 0xFC0E, + 0xFC0F, 0xFC10, 0xFCF0, 0xFCF1, 0xFCF2, 0xFCF3, + 0xFCF4, 0xFCF5, 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, + 0xFCFA, 0xFCFB, 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, + 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04, 0xFD05, + 0xFD06, 0xFD07, 0xFD08, 0xFD09, 0xFD0A, 0xFD0B, + 0xFD0C, 0xFD0D, 0xFD0E, 0xFD0F, 0xFD10, 0xFDF0, + 0xFDF1, 0xFDF2, 0xFDF3, 0xFDF4, 0xFDF5, 0xFDF6, + 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, + 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, 0xFE01, 0xFE02, + 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, + 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, + 0xFE0F, 0xFE10, 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, 0xFFF0, + 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, + 0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, + 0xFFFD, 0xFFFE, 0xFFFF, +}; + +const uint32_t * const ff_on2avc_quad_cb_codes[] = { + on2avc_cb1_codes, on2avc_cb2_codes, on2avc_cb3_codes, on2avc_cb4_codes, + on2avc_cb5_codes, on2avc_cb6_codes, on2avc_cb7_codes, on2avc_cb8_codes +}; + +const uint8_t * const ff_on2avc_quad_cb_bits[] = { + on2avc_cb1_bits, on2avc_cb2_bits, on2avc_cb3_bits, on2avc_cb4_bits, + on2avc_cb5_bits, on2avc_cb6_bits, on2avc_cb7_bits, on2avc_cb8_bits +}; + +const uint16_t * const ff_on2avc_quad_cb_syms[] = { + on2avc_cb1_syms, on2avc_cb2_syms, on2avc_cb3_syms, on2avc_cb4_syms, + on2avc_cb5_syms, on2avc_cb6_syms, on2avc_cb7_syms, on2avc_cb8_syms +}; + +const int ff_on2avc_quad_cb_elems[] = { + ON2AVC_CB1_CODES, ON2AVC_CB2_CODES, ON2AVC_CB3_CODES, ON2AVC_CB4_CODES, + ON2AVC_CB5_CODES, ON2AVC_CB6_CODES, ON2AVC_CB7_CODES, ON2AVC_CB8_CODES, +}; + +const uint16_t * const ff_on2avc_pair_cb_codes[] = { + on2avc_cb9_codes, on2avc_cb10_codes, on2avc_cb11_codes, on2avc_cb12_codes, + on2avc_cb13_codes, on2avc_cb14_codes, on2avc_cb15_codes +}; + +const uint8_t * const ff_on2avc_pair_cb_bits[] = { + on2avc_cb9_bits, on2avc_cb10_bits, on2avc_cb11_bits, on2avc_cb12_bits, + on2avc_cb13_bits, on2avc_cb14_bits, on2avc_cb15_bits +}; + +const uint16_t * const ff_on2avc_pair_cb_syms[] = { + on2avc_cb9_syms, on2avc_cb10_syms, on2avc_cb11_syms, on2avc_cb12_syms, + on2avc_cb13_syms, on2avc_cb14_syms, on2avc_cb15_syms +}; + +const int ff_on2avc_pair_cb_elems[] = { + ON2AVC_CB9_CODES, ON2AVC_CB10_CODES, ON2AVC_CB11_CODES, ON2AVC_CB12_CODES, + ON2AVC_CB13_CODES, ON2AVC_CB14_CODES, ON2AVC_CB15_CODES, +}; + +const float ff_on2avc_window_long_32000[1024] = { + 0.0007669903, 0.0023009691, 0.0038349426, 0.005368907, + 0.0069028586, 0.0084367944, 0.0099707097, 0.011504602, + 0.013038467, 0.014572302, 0.016106103, 0.017639864, + 0.019173585, 0.020707261, 0.022240886, 0.023774462, + 0.025307981, 0.026841439, 0.028374836, 0.029908165, + 0.031441424, 0.032974608, 0.034507714, 0.036040742, + 0.037573684, 0.039106537, 0.040639296, 0.042171963, + 0.043704528, 0.04523699, 0.046769347, 0.048301592, + 0.049833726, 0.051365741, 0.052897636, 0.054429408, + 0.05596105, 0.057492562, 0.059023935, 0.060555171, + 0.062086266, 0.063617215, 0.065148011, 0.066678658, + 0.068209141, 0.069739468, 0.071269631, 0.07279963, + 0.074329451, 0.0758591, 0.077388577, 0.078917861, + 0.080446966, 0.081975877, 0.083504602, 0.085033126, + 0.086561449, 0.08808957, 0.089617483, 0.091145188, + 0.092672676, 0.094199941, 0.095726989, 0.097253814, + 0.098780409, 0.10030677, 0.1018329, 0.10335878, + 0.10488442, 0.10640982, 0.10793497, 0.10945986, + 0.11098449, 0.11250886, 0.11403297, 0.11555681, + 0.11708038, 0.11860367, 0.12012669, 0.12164942, + 0.12317186, 0.12469402, 0.12621588, 0.12773743, + 0.12925871, 0.13077965, 0.13230032, 0.13382065, + 0.13534068, 0.13686039, 0.13837977, 0.13989884, + 0.14141756, 0.14293596, 0.14445402, 0.14597175, + 0.14748912, 0.14900614, 0.15052283, 0.15203916, + 0.15355512, 0.15507074, 0.15658598, 0.15810084, + 0.15961535, 0.16112947, 0.16264322, 0.16415659, + 0.16566956, 0.16718215, 0.16869435, 0.17020614, + 0.17171754, 0.17322853, 0.17473911, 0.1762493, + 0.17775905, 0.17926839, 0.18077731, 0.1822858, + 0.18379387, 0.1853015, 0.18680871, 0.18831545, + 0.18982176, 0.19132763, 0.19283305, 0.19433801, + 0.19584252, 0.19734655, 0.19885014, 0.20035326, + 0.2018559, 0.20335805, 0.20485975, 0.20636097, + 0.20786168, 0.20936191, 0.21086164, 0.21236089, + 0.21385963, 0.21535787, 0.2168556, 0.21835282, + 0.21984953, 0.22134572, 0.2228414, 0.22433653, + 0.22583115, 0.22732525, 0.22881879, 0.2303118, + 0.23180428, 0.2332962, 0.23478758, 0.2362784, + 0.23776866, 0.23925838, 0.24074753, 0.24223609, + 0.24372411, 0.24521156, 0.24669841, 0.2481847, + 0.24967039, 0.2511555, 0.25264001, 0.25412393, + 0.25560725, 0.25708997, 0.25857207, 0.2600536, + 0.26153448, 0.26301476, 0.26449442, 0.26597348, + 0.26745188, 0.26892966, 0.27040681, 0.27188334, + 0.27335921, 0.27483445, 0.27630904, 0.27778298, + 0.27925625, 0.28072888, 0.28220084, 0.28367215, + 0.28514278, 0.28661272, 0.28808203, 0.28955063, + 0.29101855, 0.2924858, 0.29395235, 0.29541823, + 0.2968834, 0.29834786, 0.29981163, 0.30127469, + 0.30273703, 0.30419868, 0.30565959, 0.30711982, + 0.3085793, 0.31003806, 0.31149608, 0.31295338, + 0.31440994, 0.31586576, 0.31732082, 0.31877515, + 0.32022873, 0.32168156, 0.32313362, 0.32458493, + 0.32603547, 0.32748523, 0.32893425, 0.33038247, + 0.33182994, 0.3332766, 0.33472249, 0.3361676, + 0.33761191, 0.33905542, 0.34049815, 0.34194005, + 0.34338117, 0.34482148, 0.34626096, 0.34769964, + 0.34913751, 0.35057455, 0.35201076, 0.35344613, + 0.35488069, 0.35631442, 0.35774729, 0.35917932, + 0.36061054, 0.36204088, 0.36347035, 0.36489901, + 0.36632678, 0.36775371, 0.36917976, 0.37060493, + 0.37202924, 0.37345266, 0.37487522, 0.37629691, + 0.3777177, 0.37913758, 0.38055661, 0.3819747, + 0.38339192, 0.38480824, 0.38622364, 0.38763815, + 0.38905171, 0.3904644, 0.39187613, 0.39328697, + 0.39469689, 0.39610586, 0.3975139, 0.39892101, + 0.40032718, 0.40173239, 0.40313667, 0.40454, + 0.40594238, 0.4073438, 0.40874428, 0.41014379, + 0.41154233, 0.41293988, 0.4143365, 0.41573212, + 0.41712677, 0.41852042, 0.41991311, 0.42130479, + 0.42269549, 0.4240852, 0.4254739, 0.42686161, + 0.42824832, 0.429634, 0.43101871, 0.43240237, + 0.43378502, 0.43516666, 0.43654725, 0.43792683, + 0.43930539, 0.44068289, 0.44205937, 0.44343483, + 0.4448092, 0.44618255, 0.44755486, 0.44892609, + 0.45029628, 0.45166543, 0.45303348, 0.45440048, + 0.45576641, 0.45713127, 0.45849505, 0.45985776, + 0.4612194, 0.46257991, 0.46393937, 0.46529773, + 0.46665499, 0.46801114, 0.46936622, 0.47072017, + 0.47207302, 0.47342476, 0.4747754, 0.47612491, + 0.47747329, 0.47882056, 0.4801667, 0.48151168, + 0.48285556, 0.4841983, 0.48553991, 0.48688036, + 0.48821968, 0.48955783, 0.49089485, 0.49223071, + 0.49356541, 0.49489892, 0.49623129, 0.4975625, + 0.49889255, 0.50022137, 0.50154907, 0.50287557, + 0.50420088, 0.50552505, 0.50684798, 0.50816971, + 0.50949025, 0.5108096, 0.51212776, 0.51344472, + 0.51476043, 0.51607502, 0.51738828, 0.51870042, + 0.52001131, 0.52132094, 0.52262932, 0.52393657, + 0.52524251, 0.52654725, 0.52785075, 0.52915299, + 0.53045398, 0.53175372, 0.53305221, 0.53434944, + 0.53564548, 0.53694022, 0.53823364, 0.53952587, + 0.54081678, 0.54210645, 0.5433948, 0.54468191, + 0.54596776, 0.5472523, 0.54853553, 0.5498175, + 0.55109817, 0.55237752, 0.55365556, 0.55493236, + 0.55620778, 0.55748194, 0.5587548, 0.56002629, + 0.56129652, 0.56256539, 0.56383294, 0.56509918, + 0.56636411, 0.56762767, 0.56888992, 0.57015079, + 0.57141036, 0.57266855, 0.57392544, 0.57518095, + 0.57643509, 0.57768792, 0.57893938, 0.58018941, + 0.58143812, 0.58268547, 0.58393145, 0.58517605, + 0.58641928, 0.58766115, 0.58890164, 0.5901407, + 0.59137839, 0.59261465, 0.5938496, 0.59508306, + 0.59631521, 0.59754586, 0.59877521, 0.60000306, + 0.60122955, 0.6024546, 0.60367823, 0.60490048, + 0.60612124, 0.60734063, 0.6085586, 0.60977507, + 0.61099017, 0.61220378, 0.61341602, 0.61462677, + 0.61583608, 0.61704391, 0.61825031, 0.61945528, + 0.62065876, 0.6218608, 0.62306136, 0.62426049, + 0.62545812, 0.62665427, 0.62784898, 0.62904221, + 0.63023394, 0.63142419, 0.63261294, 0.63380021, + 0.63498598, 0.63617027, 0.63735306, 0.63853437, + 0.63971412, 0.64089245, 0.64206922, 0.6432445, + 0.64441824, 0.64559048, 0.64676118, 0.64793038, + 0.64909804, 0.6502642, 0.65142882, 0.65259188, + 0.6537534, 0.65491343, 0.6560719, 0.65722883, + 0.6583842, 0.65953803, 0.66069031, 0.66184098, + 0.66299015, 0.66413778, 0.6652838, 0.66642827, + 0.66757119, 0.6687125, 0.66985226, 0.67099047, + 0.67212707, 0.67326206, 0.6743955, 0.67552739, + 0.67665762, 0.67778629, 0.67891335, 0.68003887, + 0.68116271, 0.68228501, 0.6834057, 0.68452471, + 0.68564218, 0.68675804, 0.68787223, 0.68898487, + 0.69009584, 0.6912052, 0.6923129, 0.69341904, + 0.69452351, 0.69562632, 0.69672751, 0.6978271, + 0.69892502, 0.70002127, 0.70111591, 0.70220888, + 0.70330018, 0.70438987, 0.70547789, 0.70656425, + 0.70764893, 0.70873195, 0.7098133, 0.71089298, + 0.71197098, 0.71304733, 0.714122, 0.71519494, + 0.71626627, 0.71733588, 0.71840382, 0.71947002, + 0.72053456, 0.72159743, 0.72265857, 0.72371799, + 0.72477573, 0.72583181, 0.72688609, 0.72793871, + 0.7289896, 0.73003882, 0.73108631, 0.73213202, + 0.73317605, 0.73421836, 0.73525894, 0.73629779, + 0.73733491, 0.7383703, 0.7394039, 0.74043584, + 0.74146599, 0.7424944, 0.74352109, 0.744546, + 0.74556917, 0.74659055, 0.74761021, 0.74862814, + 0.74964422, 0.75065863, 0.7516712, 0.75268203, + 0.75369114, 0.7546984, 0.75570393, 0.75670767, + 0.75770962, 0.75870979, 0.75970817, 0.76070476, + 0.76169956, 0.76269257, 0.7636838, 0.76467323, + 0.76566082, 0.76664668, 0.7676307, 0.76861292, + 0.7695933, 0.77057189, 0.77154869, 0.77252364, + 0.77349681, 0.77446812, 0.77543765, 0.77640533, + 0.77737117, 0.77833521, 0.77929735, 0.78025776, + 0.78121626, 0.78217292, 0.78312778, 0.7840808, + 0.78503191, 0.78598124, 0.78692871, 0.78787434, + 0.78881806, 0.78975999, 0.79070002, 0.7916382, + 0.79257452, 0.79350895, 0.79444152, 0.79537225, + 0.79630107, 0.79722804, 0.79815316, 0.79907638, + 0.79999769, 0.80091715, 0.8018347, 0.80275041, + 0.80366421, 0.8045761, 0.80548608, 0.80639422, + 0.80730045, 0.80820471, 0.80910712, 0.81000763, + 0.81090623, 0.81180298, 0.81269777, 0.81359059, + 0.81448156, 0.81537062, 0.81625772, 0.8171429, + 0.81802619, 0.81890756, 0.81978697, 0.82066447, + 0.82154006, 0.82241368, 0.8232854, 0.82415515, + 0.825023, 0.82588887, 0.82675278, 0.82761478, + 0.82847482, 0.82933295, 0.83018905, 0.83104324, + 0.83189547, 0.83274573, 0.83359408, 0.83444041, + 0.83528483, 0.83612722, 0.83696771, 0.83780622, + 0.83864272, 0.83947724, 0.84030986, 0.84114045, + 0.84196901, 0.84279567, 0.8436203, 0.84444296, + 0.84526366, 0.84608233, 0.84689903, 0.84771377, + 0.84852648, 0.84933716, 0.85014588, 0.85095257, + 0.85175729, 0.85255998, 0.85336071, 0.85415941, + 0.85495609, 0.85575074, 0.85654342, 0.85733408, + 0.85812265, 0.85890925, 0.85969388, 0.86047643, + 0.86125696, 0.86203545, 0.86281192, 0.86358637, + 0.86435878, 0.86512917, 0.86589754, 0.86666387, + 0.86742812, 0.86819035, 0.86895055, 0.86970872, + 0.8704648, 0.8712188, 0.87197083, 0.87272078, + 0.8734687, 0.87421453, 0.87495828, 0.8757, + 0.87643969, 0.8771773, 0.87791282, 0.87864625, + 0.87937766, 0.88010699, 0.88083428, 0.88155943, + 0.88228256, 0.88300359, 0.88372254, 0.88443947, + 0.88515425, 0.88586694, 0.88657761, 0.88728613, + 0.88799256, 0.88869697, 0.88939923, 0.89009941, + 0.8907975, 0.8914935, 0.89218742, 0.89287919, + 0.89356887, 0.89425647, 0.89494199, 0.89562535, + 0.89630663, 0.89698577, 0.89766282, 0.89833778, + 0.8990106, 0.89968133, 0.90034992, 0.90101641, + 0.90168077, 0.90234298, 0.9030031, 0.90366107, + 0.90431696, 0.90497071, 0.9056223, 0.90627176, + 0.90691912, 0.90756428, 0.90820736, 0.90884835, + 0.90948713, 0.91012377, 0.91075826, 0.91139066, + 0.91202086, 0.91264898, 0.91327488, 0.91389865, + 0.91452032, 0.91513979, 0.91575712, 0.9163723, + 0.91698527, 0.91759616, 0.91820484, 0.91881138, + 0.91941577, 0.92001796, 0.92061806, 0.92121589, + 0.92181164, 0.92240518, 0.92299652, 0.92358577, + 0.92417276, 0.92475766, 0.92534029, 0.92592078, + 0.92649913, 0.92707527, 0.92764926, 0.92822099, + 0.92879063, 0.92935801, 0.92992324, 0.93048626, + 0.93104708, 0.93160576, 0.93216223, 0.93271649, + 0.93326855, 0.93381846, 0.93436611, 0.93491161, + 0.93545485, 0.93599594, 0.93653482, 0.9370715, + 0.93760598, 0.93813825, 0.93866825, 0.93919611, + 0.93972176, 0.94024521, 0.94076639, 0.94128537, + 0.9418022, 0.94231677, 0.94282907, 0.94333923, + 0.94384712, 0.94435281, 0.94485629, 0.94535756, + 0.94585657, 0.94635338, 0.94684792, 0.94734025, + 0.94783038, 0.94831824, 0.9488039, 0.9492873, + 0.94976848, 0.95024747, 0.95072412, 0.95119864, + 0.95167089, 0.95214087, 0.95260859, 0.9530741, + 0.9535374, 0.95399845, 0.95445722, 0.95491374, + 0.95536804, 0.95582008, 0.95626986, 0.95671743, + 0.95716268, 0.95760572, 0.9580465, 0.95848507, + 0.95892131, 0.95935535, 0.95978713, 0.96021664, + 0.96064389, 0.96106887, 0.96149158, 0.96191204, + 0.96233022, 0.96274614, 0.9631598, 0.96357119, + 0.96398038, 0.96438724, 0.96479183, 0.96519411, + 0.96559417, 0.96599197, 0.96638745, 0.96678072, + 0.96717167, 0.96756035, 0.96794677, 0.96833086, + 0.96871275, 0.96909231, 0.96946961, 0.96984458, + 0.97021735, 0.97058779, 0.97095597, 0.97132182, + 0.97168541, 0.97204667, 0.97240573, 0.97276247, + 0.97311687, 0.97346902, 0.9738189, 0.97416645, + 0.97451174, 0.97485471, 0.97519541, 0.97553378, + 0.97586989, 0.97620368, 0.9765352, 0.9768644, + 0.97719133, 0.97751594, 0.97783822, 0.97815824, + 0.97847593, 0.97879136, 0.97910446, 0.97941524, + 0.97972369, 0.98002988, 0.98033381, 0.98063534, + 0.98093462, 0.98123157, 0.98152626, 0.98181856, + 0.98210859, 0.9823963, 0.98268169, 0.98296481, + 0.98324561, 0.98352402, 0.98380023, 0.98407406, + 0.98434556, 0.98461479, 0.98488164, 0.98514622, + 0.98540848, 0.98566842, 0.98592603, 0.98618132, + 0.98643428, 0.98668498, 0.98693329, 0.98717928, + 0.98742294, 0.98766434, 0.98790336, 0.98814011, + 0.98837447, 0.98860651, 0.98883629, 0.98906368, + 0.98928875, 0.98951149, 0.98973197, 0.98995006, + 0.99016583, 0.99037921, 0.99059033, 0.99079913, + 0.9910056, 0.99120969, 0.99141145, 0.99161088, + 0.991808, 0.99200279, 0.99219525, 0.99238533, + 0.99257314, 0.99275857, 0.99294168, 0.99312246, + 0.99330086, 0.99347699, 0.99365073, 0.99382216, + 0.9939912, 0.99415797, 0.99432236, 0.99448442, + 0.99464417, 0.99480152, 0.99495655, 0.99510926, + 0.99525958, 0.99540764, 0.99555331, 0.9956966, + 0.99583763, 0.99597627, 0.99611259, 0.99624652, + 0.99637812, 0.99650741, 0.9966343, 0.99675888, + 0.99688113, 0.99700099, 0.99711853, 0.99723375, + 0.99734658, 0.99745709, 0.99756527, 0.99767107, + 0.99777448, 0.99787563, 0.9979744, 0.99807078, + 0.99816483, 0.99825656, 0.99834591, 0.99843293, + 0.99851763, 0.99859995, 0.99867994, 0.99875754, + 0.99883282, 0.99890572, 0.99897629, 0.99904448, + 0.99911034, 0.99917388, 0.99923503, 0.99929386, + 0.99935031, 0.99940443, 0.99945617, 0.99950558, + 0.99955267, 0.99959737, 0.99963969, 0.99967968, + 0.99971735, 0.99975264, 0.9997856, 0.99981618, + 0.99984443, 0.9998703, 0.99989384, 0.999915, + 0.99993384, 0.99995029, 0.99996442, 0.99997616, + 0.99998558, 0.99999267, 0.99999738, 0.9999997, +}; + +const float ff_on2avc_window_long_24000[1024] = { + 0.00000102, 0.0000091700003, 0.000025470001, 0.00004993, + 0.000082530001, 0.00012328, 0.00017219, 0.00022924, + 0.00029443001, 0.00036778001, 0.00044927001, 0.00053890003, + 0.00063666998, 0.00074257998, 0.00085662998, 0.00097881001, + 0.00110913, 0.00124758, 0.00139415, 0.00154885, + 0.00171168, 0.00188262, 0.00206168, 0.00224885, + 0.0024441299, 0.00264751, 0.0028589999, 0.0030785799, + 0.0033062601, 0.00354202, 0.00378588, 0.00403781, + 0.0042978101, 0.0045658899, 0.0048420299, 0.0051262402, + 0.0054184902, 0.0057187998, 0.00602715, 0.0063435398, + 0.00666796, 0.00700041, 0.0073408699, 0.0076893498, + 0.0080458401, 0.0084103197, 0.0087828003, 0.0091632698, + 0.0095517104, 0.0099481298, 0.01035251, 0.01076485, + 0.01118513, 0.01161336, 0.01204952, 0.0124936, + 0.0129456, 0.01340551, 0.01387332, 0.01434902, + 0.0148326, 0.01532405, 0.015823361, 0.016330531, + 0.01684555, 0.017368389, 0.01789907, 0.018437561, + 0.01898385, 0.019537929, 0.020099809, 0.020669449, + 0.02124686, 0.021832019, 0.02242492, 0.02302555, + 0.023633899, 0.02424995, 0.024873709, 0.02550514, + 0.026144249, 0.026791019, 0.02744543, 0.02810749, + 0.02877716, 0.029454449, 0.030139331, 0.030831801, + 0.031531841, 0.032239441, 0.032954589, 0.033677269, + 0.03440747, 0.035145171, 0.035890371, 0.036643039, + 0.03740317, 0.038170759, 0.038945779, 0.039728221, + 0.040518072, 0.041315299, 0.04211992, 0.042931888, + 0.04375121, 0.044577859, 0.045411821, 0.046253089, + 0.047101639, 0.04795745, 0.048820522, 0.04969082, + 0.05056835, 0.051453069, 0.052344982, 0.053244069, + 0.054150298, 0.055063669, 0.055984162, 0.056911752, + 0.057846431, 0.058788169, 0.059736971, 0.060692791, + 0.061655629, 0.062625468, 0.063602284, 0.064586058, + 0.065576769, 0.06657441, 0.067578949, 0.06859038, + 0.069608673, 0.070633821, 0.071665794, 0.072704569, + 0.073750138, 0.074802481, 0.075861573, 0.076927401, + 0.077999942, 0.079079159, 0.080165058, 0.081257619, + 0.082356803, 0.083462588, 0.084574983, 0.085693933, + 0.086819433, 0.087951459, 0.089089997, 0.090235017, + 0.091386512, 0.092544436, 0.093708791, 0.094879538, + 0.09605667, 0.097240157, 0.098429978, 0.099626116, + 0.10082854, 0.10203723, 0.10325217, 0.10447333, + 0.1057007, 0.10693424, 0.10817393, 0.10941976, + 0.1106717, 0.11192972, 0.1131938, 0.11446393, + 0.11574007, 0.1170222, 0.1183103, 0.11960435, + 0.12090432, 0.12221018, 0.12352192, 0.12483951, + 0.12616292, 0.12749213, 0.12882711, 0.13016786, + 0.13151433, 0.13286649, 0.13422433, 0.13558783, + 0.13695695, 0.13833167, 0.13971195, 0.1410978, + 0.14248917, 0.14388604, 0.14528839, 0.1466962, + 0.14810941, 0.14952803, 0.150952, 0.15238133, + 0.15381598, 0.15525591, 0.15670112, 0.15815157, + 0.15960722, 0.16106807, 0.16253406, 0.16400519, + 0.16548143, 0.16696274, 0.1684491, 0.1699405, + 0.17143688, 0.17293824, 0.17444454, 0.17595574, + 0.17747185, 0.17899281, 0.1805186, 0.1820492, + 0.18358457, 0.18512468, 0.18666951, 0.18821906, + 0.18977325, 0.19133207, 0.19289552, 0.19446352, + 0.19603609, 0.19761316, 0.19919474, 0.20078079, + 0.20237127, 0.20396616, 0.20556541, 0.20716903, + 0.20877695, 0.21038917, 0.21200565, 0.21362637, + 0.21525128, 0.21688037, 0.21851361, 0.22015095, + 0.22179238, 0.22343788, 0.22508739, 0.2267409, + 0.22839837, 0.23005977, 0.2317251, 0.23339429, + 0.23506732, 0.2367442, 0.23842482, 0.24010922, + 0.24179734, 0.24348916, 0.24518465, 0.24688376, + 0.24858648, 0.25029278, 0.2520026, 0.25371596, + 0.25543278, 0.25715306, 0.25887677, 0.26060385, + 0.26233432, 0.26406807, 0.26580516, 0.26754549, + 0.26928905, 0.27103582, 0.27278578, 0.27453887, + 0.27629507, 0.27805433, 0.27981666, 0.281582, + 0.28335032, 0.28512162, 0.28689581, 0.28867289, + 0.29045284, 0.29223564, 0.29402119, 0.29580954, + 0.2976006, 0.29939437, 0.30119082, 0.3029899, + 0.30479157, 0.30659583, 0.30840263, 0.31021196, + 0.31202373, 0.31383798, 0.31565461, 0.31747365, + 0.31929505, 0.32111874, 0.32294473, 0.32477298, + 0.32660347, 0.32843611, 0.33027095, 0.33210787, + 0.33394691, 0.33578804, 0.33763117, 0.33947629, + 0.34132338, 0.34317243, 0.34502336, 0.34687617, + 0.3487308, 0.35058725, 0.35244548, 0.35430545, + 0.35616711, 0.35803047, 0.35989544, 0.36176205, + 0.36363024, 0.36549997, 0.36737123, 0.36924395, + 0.37111813, 0.37299374, 0.37487072, 0.37674904, + 0.3786287, 0.38050967, 0.38239187, 0.38427529, + 0.38615993, 0.3880457, 0.3899326, 0.39182061, + 0.39370969, 0.39559978, 0.39749089, 0.39938298, + 0.40127596, 0.40316987, 0.40506464, 0.40696028, + 0.40885669, 0.41075388, 0.41265181, 0.41455048, + 0.41644979, 0.41834977, 0.42025036, 0.42215151, + 0.42405322, 0.42595547, 0.42785817, 0.42976135, + 0.43166494, 0.43356892, 0.43547326, 0.43737793, + 0.43928292, 0.44118813, 0.4430936, 0.44499925, + 0.44690508, 0.44881102, 0.45071709, 0.45262322, + 0.4545294, 0.45643559, 0.45834175, 0.46024784, + 0.46215388, 0.46405977, 0.46596554, 0.46787113, + 0.46977648, 0.47168162, 0.47358647, 0.47549102, + 0.47739524, 0.4792991, 0.48120254, 0.48310557, + 0.48500812, 0.48691019, 0.48881173, 0.49071273, + 0.49261314, 0.49451295, 0.4964121, 0.4983106, + 0.50020838, 0.50210541, 0.50400168, 0.50589716, + 0.50779182, 0.50968558, 0.5115785, 0.51347047, + 0.51536149, 0.51725155, 0.5191406, 0.52102858, + 0.52291554, 0.52480137, 0.52668607, 0.52856964, + 0.53045195, 0.53233314, 0.53421301, 0.53609163, + 0.53796893, 0.53984493, 0.54171956, 0.54359275, + 0.54546458, 0.54733491, 0.54920375, 0.55107111, + 0.55293691, 0.55480117, 0.55666381, 0.55852479, + 0.56038415, 0.56224185, 0.56409782, 0.565952, + 0.56780452, 0.56965512, 0.571504, 0.57335097, + 0.57519609, 0.57703924, 0.57888049, 0.58071983, + 0.58255708, 0.58439237, 0.58622563, 0.58805674, + 0.58988583, 0.59171271, 0.59353751, 0.5953601, + 0.59718043, 0.59899855, 0.60081446, 0.60262799, + 0.60443926, 0.6062482, 0.6080547, 0.60985887, + 0.6116606, 0.61345983, 0.61525661, 0.61705089, + 0.61884266, 0.62063187, 0.62241846, 0.62420249, + 0.62598389, 0.62776262, 0.62953866, 0.63131201, + 0.63308257, 0.63485044, 0.63661551, 0.63837773, + 0.6401372, 0.64189374, 0.64364743, 0.6453982, + 0.64714605, 0.64889091, 0.65063286, 0.6523717, + 0.65410763, 0.65584046, 0.65757018, 0.65929681, + 0.6610204, 0.66274077, 0.66445798, 0.66617203, + 0.6678828, 0.66959041, 0.67129469, 0.67299575, + 0.67469347, 0.67638785, 0.67807889, 0.67976654, + 0.68145084, 0.68313169, 0.68480909, 0.68648309, + 0.68815356, 0.68982053, 0.69148397, 0.69314384, + 0.6948002, 0.69645292, 0.69810206, 0.69974756, + 0.70138937, 0.70302755, 0.70466202, 0.70629281, + 0.70791984, 0.70954311, 0.71116263, 0.71277833, + 0.71439022, 0.71599829, 0.71760249, 0.71920282, + 0.72079927, 0.72239184, 0.72398043, 0.72556508, + 0.72714579, 0.72872251, 0.73029518, 0.73186392, + 0.73342854, 0.73498911, 0.73654562, 0.73809808, + 0.73964638, 0.74119055, 0.74273056, 0.74426645, + 0.74579811, 0.74732566, 0.74884892, 0.75036794, + 0.75188273, 0.75339329, 0.75489956, 0.75640148, + 0.75789917, 0.75939244, 0.76088142, 0.76236606, + 0.76384634, 0.76532215, 0.76679361, 0.76826066, + 0.76972324, 0.77118134, 0.77263504, 0.77408427, + 0.77552897, 0.77696913, 0.77840483, 0.779836, + 0.78126258, 0.78268462, 0.78410208, 0.78551495, + 0.78692323, 0.78832692, 0.7897259, 0.79112029, + 0.79251003, 0.79389513, 0.79527551, 0.79665124, + 0.79802221, 0.79938853, 0.80075008, 0.80210692, + 0.80345899, 0.80480635, 0.80614889, 0.80748665, + 0.80881965, 0.81014782, 0.81147122, 0.8127898, + 0.81410348, 0.8154124, 0.81671643, 0.81801558, + 0.81930989, 0.82059932, 0.8218838, 0.82316345, + 0.82443815, 0.82570797, 0.82697284, 0.82823282, + 0.8294878, 0.83073789, 0.83198297, 0.8332231, + 0.83445829, 0.83568847, 0.8369137, 0.83813387, + 0.83934909, 0.8405593, 0.84176451, 0.84296465, + 0.84415978, 0.84534991, 0.84653497, 0.84771496, + 0.84888995, 0.85005987, 0.85122472, 0.85238451, + 0.85353923, 0.85468888, 0.85583341, 0.85697287, + 0.85810727, 0.85923654, 0.86036074, 0.86147982, + 0.86259383, 0.86370265, 0.86480641, 0.86590505, + 0.86699861, 0.86808699, 0.86917025, 0.87024838, + 0.87132144, 0.87238932, 0.87345207, 0.87450963, + 0.87556213, 0.87660944, 0.87765163, 0.87868869, + 0.87972057, 0.88074732, 0.88176894, 0.88278538, + 0.88379669, 0.88480288, 0.88580388, 0.88679975, + 0.88779044, 0.88877606, 0.88975644, 0.89073175, + 0.89170188, 0.89266688, 0.89362669, 0.89458138, + 0.89553094, 0.89647537, 0.89741462, 0.89834881, + 0.89927781, 0.90020168, 0.90112042, 0.90203404, + 0.90294254, 0.90384591, 0.90474415, 0.90563726, + 0.90652531, 0.90740818, 0.90828604, 0.90915871, + 0.91002631, 0.91088885, 0.91174626, 0.91259861, + 0.91344583, 0.91428804, 0.91512513, 0.91595721, + 0.91678417, 0.91760612, 0.918423, 0.91923481, + 0.92004162, 0.92084336, 0.92164016, 0.92243183, + 0.92321855, 0.92400026, 0.92477697, 0.92554867, + 0.92631537, 0.92707711, 0.92783386, 0.92858565, + 0.92933249, 0.93007439, 0.93081135, 0.93154335, + 0.93227047, 0.93299264, 0.93370992, 0.93442225, + 0.93512976, 0.93583232, 0.93653005, 0.93722296, + 0.93791091, 0.9385941, 0.9392724, 0.93994594, + 0.94061458, 0.94127852, 0.94193757, 0.94259191, + 0.94324142, 0.94388616, 0.9445262, 0.94516146, + 0.94579202, 0.94641781, 0.94703895, 0.94765538, + 0.9482671, 0.94887418, 0.94947654, 0.95007432, + 0.95066744, 0.95125592, 0.9518398, 0.95241904, + 0.95299375, 0.95356387, 0.95412946, 0.95469046, + 0.95524693, 0.95579892, 0.95634633, 0.95688927, + 0.9574278, 0.9579618, 0.95849133, 0.95901644, + 0.95953715, 0.96005344, 0.96056533, 0.96107286, + 0.96157598, 0.96207482, 0.96256924, 0.96305943, + 0.9635452, 0.96402675, 0.96450406, 0.96497703, + 0.96544582, 0.96591038, 0.9663707, 0.9668268, + 0.96727878, 0.96772653, 0.96817023, 0.96860969, + 0.9690451, 0.9694764, 0.96990365, 0.97032678, + 0.97074586, 0.97116095, 0.97157204, 0.97197908, + 0.97238219, 0.9727813, 0.97317648, 0.97356778, + 0.97395509, 0.97433859, 0.97471815, 0.9750939, + 0.97546583, 0.97583389, 0.9761982, 0.97655869, + 0.97691542, 0.97726846, 0.97761768, 0.97796327, + 0.97830516, 0.97864336, 0.97897792, 0.97930884, + 0.97963619, 0.97995991, 0.9802801, 0.98059666, + 0.98090976, 0.98121929, 0.98152536, 0.98182797, + 0.98212707, 0.98242277, 0.98271501, 0.98300391, + 0.98328942, 0.98357159, 0.98385036, 0.98412585, + 0.98439807, 0.984667, 0.98493266, 0.9851951, + 0.98545432, 0.98571032, 0.98596323, 0.98621291, + 0.98645949, 0.98670292, 0.9869433, 0.98718059, + 0.98741484, 0.98764604, 0.98787427, 0.98809952, + 0.98832178, 0.98854107, 0.98875749, 0.98897099, + 0.98918158, 0.98938936, 0.98959428, 0.98979634, + 0.98999566, 0.99019217, 0.99038595, 0.99057698, + 0.99076533, 0.99095094, 0.99113393, 0.99131429, + 0.99149197, 0.99166709, 0.99183959, 0.99200952, + 0.99217695, 0.99234182, 0.99250424, 0.99266416, + 0.99282163, 0.99297667, 0.99312931, 0.99327952, + 0.9934274, 0.99357295, 0.99371612, 0.99385703, + 0.99399561, 0.99413198, 0.99426609, 0.994398, + 0.9945277, 0.99465519, 0.9947806, 0.9949038, + 0.99502492, 0.99514401, 0.99526095, 0.99537587, + 0.99548876, 0.99559963, 0.99570858, 0.99581552, + 0.99592048, 0.9960236, 0.99612474, 0.99622405, + 0.9963215, 0.99641711, 0.99651092, 0.99660289, + 0.99669313, 0.99678159, 0.99686831, 0.99695337, + 0.9970367, 0.99711835, 0.99719834, 0.99727672, + 0.99735349, 0.99742872, 0.99750233, 0.99757439, + 0.9976449, 0.99771392, 0.99778146, 0.99784756, + 0.99791217, 0.99797535, 0.9980371, 0.99809748, + 0.99815649, 0.99821413, 0.99827045, 0.99832547, + 0.99837923, 0.99843168, 0.99848282, 0.99853277, + 0.99858153, 0.99862903, 0.99867541, 0.99872059, + 0.99876463, 0.99880755, 0.99884939, 0.9988901, + 0.99892974, 0.99896836, 0.99900591, 0.99904245, + 0.99907798, 0.99911255, 0.99914616, 0.99917883, + 0.99921054, 0.99924135, 0.99927121, 0.99930024, + 0.99932843, 0.99935573, 0.9993822, 0.99940789, + 0.99943274, 0.99945682, 0.99948019, 0.99950278, + 0.99952459, 0.99954569, 0.99956614, 0.99958587, + 0.99960488, 0.9996233, 0.99964106, 0.99965817, + 0.99967468, 0.99969059, 0.99970591, 0.99972069, + 0.99973488, 0.99974853, 0.99976164, 0.99977428, + 0.99978638, 0.999798, 0.99980915, 0.99981982, + 0.99983001, 0.99983978, 0.99984914, 0.99985808, + 0.99986666, 0.99987477, 0.99988258, 0.99988997, + 0.99989706, 0.99990374, 0.99991012, 0.9999162, + 0.99992198, 0.9999274, 0.99993259, 0.99993742, + 0.99994206, 0.99994642, 0.99995053, 0.9999544, + 0.99995804, 0.99996144, 0.99996465, 0.99996763, + 0.99997044, 0.99997306, 0.9999755, 0.99997777, + 0.99997985, 0.99998182, 0.99998367, 0.99998534, + 0.99998689, 0.99998826, 0.99998957, 0.99999076, + 0.99999183, 0.99999285, 0.99999374, 0.99999452, + 0.99999523, 0.99999589, 0.99999648, 0.99999702, + 0.9999975, 0.99999785, 0.99999821, 0.99999857, + 0.99999881, 0.99999905, 0.99999923, 0.9999994, + 0.99999952, 0.99999964, 0.9999997, 0.99999982, + 0.99999982, 0.99999988, 0.99999994, 0.99999994, + 0.99999994, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, +}; + +const float ff_on2avc_window_short[128] = { + 1.320684e-12, 1.3218859e-12, 1.324119e-12, 1.3269172e-12, + 1.3297907e-12, 1.3316993e-12, 1.3321618e-12, 1.3303409e-12, + 1.3297163e-12, 1.3598052e-12, 1.6224489e-12, 3.238457e-12, + 1.1376874e-11, 4.6434454e-11, 1.80557e-10, 6.4489758e-10, + 2.1179569e-9, 6.4429635e-9, 1.8292885e-8, 4.880043e-8, + 1.2303467e-7, 2.946195e-7, 6.729764e-7, 0.0000014718792, + 0.0000030924566, 0.0000062596109, 0.000012238012, 0.000023162085, + 0.000042523086, 0.000075864329, 0.00013174133, 0.00022300506, + 0.00036846122, 0.00059494411, 0.00093981833, 0.001453883, + 0.0022046037, 0.0032795328, 0.004789711, 0.0068727732, + 0.0096954042, 0.01345476, 0.018378416, 0.02472244, + 0.032767218, 0.042810757, 0.055159383, 0.070115872, + 0.087965287, 0.10895917, 0.1332987, 0.16111787, + 0.19246797, 0.22730421, 0.26547599, 0.30672187, + 0.35066974, 0.39684334, 0.44467437, 0.49352086, + 0.54269004, 0.59146535, 0.6391356, 0.68502444, + 0.72851861, 0.76909274, 0.80632913, 0.83993185, + 0.8697328, 0.89569116, 0.91788524, 0.93649811, + 0.95179814, 0.96411639, 0.97382277, 0.9813022, + 0.98693413, 0.99107492, 0.9940452, 0.99612254, + 0.99753785, 0.99847656, 0.99908221, 0.99946207, + 0.99969339, 0.99983019, 0.99990857, 0.99995208, + 0.9999755, 0.99998766, 0.9999938, 0.99999678, + 0.99999821, 0.99999893, 0.99999923, 0.99999946, + 0.99999958, 0.9999997, 0.99999982, 0.99999994, + 1.0000001, 1.0000002, 1.0000004, 1.0000005, + 1.0000006, 1.0000008, 1.000001, 1.000001, + 1.0000011, 1.0000012, 1.0000013, 1.0000014, + 1.0000014, 1.0000015, 1.0000015, 1.0000015, + 1.0000015, 1.0000014, 1.0000014, 1.0000014, + 1.0000013, 1.0000013, 1.0000012, 1.0000012, + 1.0000011, 1.0000011, 1.0000011, 1.0000011, +}; + +const double ff_on2avc_tab_10_1[] = { + 0.0033357253, -0.012580752, -0.0062414902, 0.077571494, -0.03224487, + -0.24229489, 0.13842815, 0.72430853, 0.60382927, 0.1601024 +}; + +const double ff_on2avc_tab_10_2[] = { + -0.1601024, 0.60382927, -0.72430853, 0.13842815, 0.24229489, + -0.03224487, -0.077571494, -0.0062414902, 0.012580752, 0.0033357253, + 0.33266699, 0.80689015, 0.45988244, -0.13500994, -0.085442654, + 0.035226542, -0.035226543, -0.085442656, 0.13500994, 0.45988246, + -0.80689017, 0.332667 +}; + +const double ff_on2avc_tab_20_1[] = { + -0.0014416961, -0.00056214974, 0.020948911, 0.025363335, -0.10427845, + -0.2318503, 0.06892613, 0.63810513, 0.6843251, 0.20162185, + -0.033582, 0.07313663, 0.08143964, -0.0063137698, -0.012688661, + 0.0089685127, 0.0035534843, -0.0016078273, -0.000095677464, 0.0002453756 +}; + +const double ff_on2avc_tab_20_2[] = { + -0.0002453755997325089, -0.00009567746389569924, 0.001607827298247261, + 0.003553484296126244, -0.008968512690223166, -0.01268866098616772, + 0.006313769793117177, 0.08143963991122029, -0.07313662992027165, + -0.03358199996339129, -0.2016218497802062, 0.6843250992539974, + -0.6381051293043832, 0.06892612992486163, 0.2318502997472533, + -0.1042784498863231, -0.0253633349723507, 0.02094891097716299, + 0.0005621497393871844, -0.001441696098428365 +}; + +const double ff_on2avc_tab_40_1[] = { + -0.0000017445457, -0.000001814441, 0.000038676008, 0.000045716169, + -0.00041789492, -0.00062315149, 0.0027052457, 0.0053753308, + -0.010572396, -0.030726394, 0.01871785, 0.11585315, + 0.03958068, -0.25000242, -0.29886274, 0.18287176, + 0.65781885, 0.548686, 0.17696839, 0.08330372, + 0.14234582, 0.064187778, -0.03396015, -0.013302871, + 0.020618859, 0.0018984093, -0.010561246, -0.00010918036, + 0.0035190253, -0.00057674024, -0.0010263441, 0.00030131618, + 0.00022613687, -0.000089637969, -0.000032248444, 0.00001882641, + 0.0000029119687, -0.0000023940844, -1.3944369e-7, 1.3407205e-7, +}; + +const double ff_on2avc_tab_40_2[] = { + -1.340720502155867e-7, -1.394436902242243e-7, 0.000002394084403849667, + 0.000002911968704682421, -0.00001882641003027271, -0.00003224844405185522, + 0.00008963796914413709, 0.0002261368703636262, -0.0003013161804845139, + -0.001026344101650353, 0.0005767402409273933, 0.003519025305658563, + 0.0001091803601755611, -0.01056124601698239, -0.001898409303052626, + 0.02061885903315495, 0.0133028710213909, -0.03396015005460763, + -0.0641877781032134, 0.1423458202288909, -0.08330372013395167, + 0.1769683902845637, -0.5486860008822824, 0.6578188510577671, + -0.1828717602940562, -0.2988627404805687, 0.2500024204020018, + 0.03958068006364539, -0.1158531501862909, 0.01871785003009814, + 0.03072639404940778, -0.01057239601700032, -0.005375330808643486, + 0.002705245704350012, 0.0006231514910020222, -0.0004178949206719714, + -0.00004571616907351121, 0.00003867600806219069, 0.000001814441002917606, + -0.000001744545702805214 +}; + +const double ff_on2avc_tab_84_1[] = { + -0.003834605569340214, -0.01399666493880675, -0.02423522354202532, + -0.02098660725909453, -0.003033811991149968, 0.02580968794845409, + 0.05022200106698627, 0.05480106279059652, 0.0370527194554745, + 0.01293943431893363, 0.012874098608023, 0.06242007669752228, + 0.1711674720067008, 0.3168985339332503, 0.4463224645440312, + 0.4997307843290636, 0.442680199327905, 0.2862974432523162, + 0.08192922995482327, -0.100687848630388, -0.2010749890073668, + -0.1970564705797125, -0.1136363541357198, -0.006482554176098804, + 0.06983853153253429, 0.08958734697447382, 0.0598384364842016, + 0.009627953684538691, -0.02776530291935209, -0.03485384358824609, + -0.01638430987962629, 0.01132787970877885, 0.02744697607433038, + 0.02280082564277705, 0.003817601656862559, -0.01536124106173835, + -0.02070943469222549, -0.01286651718416282, 0.0005632574484435138, + 0.007577496599690143, 0.01014022979594007, 0.006400316454349855, + -0.001317309067039239, -0.00317940336781777, -0.002405842901164466, + -0.001661745856529503, -0.00005380161101133026, 0.0009898316472595594, + 0.0007039765787268925, -0.000189661703240109, -0.0001182674960570266, + 0.0002115051270037225, -0.00008565649434604059, -0.0001252806220197323, + 0.0001500012974557671, 0.00002957208561445737, -0.000118882457357092, + -0.000007421996284144832, 0.00004351015061547388, -0.000005737099377545248, + -0.0000164747057254053, 0.00001923482660002518, -0.00001093031593938137, + -0.00001002792095051621, 0.00001250573423880376, 0.000004127061570609871, + -0.000003458244341720683, -0.000003058993334597815, 0.000002160520943418329, + 8.907414904197164e-7, -0.000001316252923085336, 3.681255415998394e-7, + 6.245867533258108e-7, -1.129925213069921e-7, 3.315839446922364e-7, + -1.356572071896963e-7, -4.318309977365961e-7, -1.367503553365523e-7, + 4.470828965968303e-8, 9.212902857354196e-8, 3.695547755036224e-8, + 1.505766197979149e-8, -6.958994047152974e-9, -8.758631202056997e-9 +}; + +const double ff_on2avc_tab_84_2[] = { + 0.002715349650922232, -0.01033050750152524, -0.01528172942791371, + 0.005838722508994047, 0.01599086024371182, -0.01737535183522147, + -0.01418596452135431, 0.05969677252151454, 0.07139735966046348, + -0.06379927990205171, -0.1516174471801191, 0.008365792873769096, + 0.1866714915958021, 0.04432405351099893, -0.2179875184285703, + -0.1089585577690529, 0.2761321070772847, 0.294949416655377, + -0.1811068533291373, -0.4710662031299601, -0.1397679263799359, + 0.3386633432956985, 0.3588950861292916, 0.03198338392910033, + -0.1801130026394404, -0.178622266226761, -0.1270863570294224, + -0.0332786110926095, 0.1326619748641741, 0.2077421015185226, + 0.07027624884033033, -0.1065486044522993, -0.125884731750194, + -0.0399897264540468, 0.003687144241560403, 0.01609004681595481, + 0.04950212493135606, 0.05748681524682781, 0.004041844771574074, + -0.04142122345639772, -0.02559310071302269, 0.002755316641486144, + 0.003184997421951853, -0.005531116810971506, 0.008338191103621911, + 0.01252616152446114, -0.003312308536298372, -0.007161498814519848, + 0.001337745209122465, 0.002343332617933073, -0.001621098790238126, + -0.00129682569402033, 0.001491028268251773, 0.0003044153446278188, + -0.0007048834926788463, 0.00004445131250124058, 0.0003635790848622476, + -0.000143533732887211, -0.00002972390773997905, 0.0001176094971737509, + -0.00006171908908217019, -0.0001084231902960109, 0.00007896973444840752, + 0.0000499995995843891, -0.00006444906759864038, -0.000018321011061942, + 0.00001482481130354497, 0.00001058934262851235, -0.000004798424433342611, + -4.761276869473942e-7, 0.00000188617755070578, -0.000001674634418015107, + -1.53944330645465e-7, 9.240123633592371e-7, -0.000001235630235014779, + 4.925891606823236e-8, 0.000001206615355189743, 3.647623817617871e-7, + -1.087267533862797e-7, -2.529052443169693e-7, -1.1961026302477e-7, + -4.873569574324943e-8, 2.252351108799612e-8, 2.834822470870021e-8 +}; + +const double ff_on2avc_tab_84_3[] = { + -0.00434676231664159, 0.006714123005267953, 0.008698054407437532, + -0.01370846523601941, 0.01012828941725749, -0.007068078935658625, + -0.008138346009558437, 0.0467353028783406, -0.0658381497176358, + 0.01310067828595943, 0.07269279617480232, -0.1069564909021104, + 0.06762691282426264, 0.01034035065310993, -0.1175699606097785, + 0.192812157569135, -0.1084409432849384, -0.1353394082449725, + 0.290587999391769, -0.1665935202779336, -0.09927986222827791, + 0.2394316349364771, -0.196937680294991, 0.04675035632757467, + 0.160737603124711, -0.2866953475517299, 0.11533530450257, + 0.2313808347485174, -0.285955205900817, -0.07033046899644142, + 0.3010809341153604, -0.03711556319204814, -0.2854261021892172, + 0.1326266190726841, 0.2334442000696142, -0.2160410554670428, + -0.122575309612308, 0.2186808995859664, 0.02544075501374961, + -0.1660358993667236, 0.02009196196614523, 0.1162583994153812, + -0.03991958608138682, -0.07115975637749203, 0.04270444046513863, + 0.03536651879157764, -0.02655940136961219, -0.0166541988800009, + 0.01811758653663791, 0.003161066879299114, -0.006590249135122636, + 0.0000224660373347443, 0.002764837297017082, -0.001816050098089884, + 0.000221385824782758, 0.001325129169916481, -0.0009313048485056467, + -0.001002997644614651, 0.0006461390960813223, 0.0005091843808757102, + -0.0004981831027749185, -0.0002132118318370338, 0.0001692041329121999, + 0.00009203280989519006, -0.0000726634301061485, -0.000003776173954180476, + 0.000005650286559057409, 1.015871235188678e-8, 0.000009297695668468626, + 0.000008217172691037263, -0.000005352793597674221, -0.000004293043830914206, + 0.00000406840557498943, 0.000001957539844881767, -0.000001357985014138161, + -7.970430363552399e-7, 5.338776009119553e-7, 1.022190984936616e-7, + 7.153181993493103e-9, -9.647767193713991e-8, -1.087063157245304e-7, + -4.429283737485961e-8, 2.047021589652069e-8, 2.576393519656189e-8 +}; + +const double ff_on2avc_tab_84_4[] = { + -0.0008804814258974317, 0.001677984795861344, 0.0019438229200474, + -0.002374701634816941, 0.002842769830143803, -0.00313020546738317, + -0.002246992394582708, 0.01055408593972395, -0.01218520382203817, + -0.0006735617784857061, 0.02057268271156303, -0.03472338199007904, + 0.02960799007316684, -0.003269335988224603, -0.02972969305167542, + 0.05008512160999294, -0.04400487480883553, 0.01713790123047206, + 0.001794796985095048, 0.02465108569696885, -0.1185046238791295, + 0.2661533909042693, -0.4170434096290337, 0.5056971209966197, + -0.4839205146480338, 0.348475120088803, -0.1457287020663733, + -0.04963861239550338, 0.1710032440522816, -0.1892135762829684, + 0.1231345995813251, -0.02389080306388811, -0.054785057318703, + 0.08416222204781872, -0.0666027804409105, 0.02377207113744183, + 0.01203829040820619, -0.02516530033022068, 0.01840432198285431, + -0.006286010406016099, -0.004035603243854861, 0.006949156667744018, + -0.00161215048516293, -0.001828701991824727, 0.0009090589499595256, + 0.0009761363135882747, -0.002142429121283414, 0.0004188485015062717, + 0.001809279129203381, -0.000932687525032396, -0.0009486028487922317, + 0.0009397940062201393, 0.000281183371137153, -0.0009248586848561844, + 0.0002152615409451283, 0.0005477801444594987, -0.0002659748756010768, + -0.0002773742035095173, 0.0002260622852620992, 0.0001512792970069076, + -0.0001768728566277711, -0.00002986876958461399, 0.00005130565743733275, + 0.000004374757277468806, -0.00002195539036180244, 0.000002913282980087422, + 3.818084416943484e-7, -0.000006288075796943977, 0.000006984829418122699, + 0.00000614694006919441, -0.000005946919055089292, -0.000001264733599421358, + 0.000004339214975250828, 0.000001188830031229202, -2.565690994853701e-7, + -8.929058735983076e-7, -5.618418560386023e-7, -2.216635610199557e-7, + 9.901798023372271e-8, 1.312667895662033e-7, 6.845290101279972e-9, + 2.7891417275888e-9, -1.289019550645086e-9, -1.62236765541716e-9 +}; + +static const double tabs_4_10[4 * 2][10] = { + { 0.92756648, 0.17727433, -0.31028851, -0.041293536, 0.099339873, + -0.0079929986, -0.016111206, 0.004271808, 0.0, 0.0 }, + { 0.0, 0.0, 0.16008016, 0.60374538, 0.7244924, + 0.13948189, -0.24189853, -0.03548063, 0.075736174, 0.0034171261 }, + { 0.0, 0.0, -2.0495447e-10, -7.6501622e-10, 0.15922493, + 0.60051988, 0.72580564, 0.15828764, -0.23272256, -0.089524832 }, + { 0.0, 0.0, 1.7673448e-10, 6.4163071e-10, 0.000032608112, + 0.00012297965, 0.15178394, 0.57192786, 0.73750254, 0.32549984 }, + { 0.32549984, -0.73750254, 0.57192786, -0.15178394, 0.00012297965, + -0.000032608112, 6.4163071e-10, -1.7673448e-10, 0.0, 0.0 }, + { -0.089524832, 0.23272256, 0.15828764, -0.72580564, 0.60051988, + -0.15922493, -7.6501621e-10, 2.0495446e-10, 0.0, 0.0 }, + { 0.0034171261, -0.075736174, -0.03548063, 0.24189853, 0.13948189, + -0.7244924, 0.60374538, -0.16008016, 0.0, 0.0 }, + { 0.0, 0.0, 0.004271808, 0.016111206, -0.0079929986, + -0.099339873, -0.041293536, 0.31028851, 0.17727433, -0.92756648 } +}; + +const double * const ff_on2avc_tabs_4_10_1[4] = { + tabs_4_10[0], tabs_4_10[1], tabs_4_10[2], tabs_4_10[3] +}; + +const double * const ff_on2avc_tabs_4_10_2[4] = { + tabs_4_10[4], tabs_4_10[5], tabs_4_10[6], tabs_4_10[7] +}; + +static const double tabs_9_20[9 * 2][20] = { + { 0.20265566, 0.6892313, 0.64164786, 0.066309055, -0.23597194, + -0.10432145, 0.027402007, 0.02147583, -0.0011571443, -0.0016923795, + 0.00010941944, 0.000063155164, -0.000012061176, -0.0000094681391, 6.8164837e-7, + 8.0672986e-7, -1.2001096e-8, -3.0778157e-8, 0.0, 0.0, }, + { 0.07340142, -0.033796895, 0.20223772, 0.68677248, 0.64011737, + 0.068365159, -0.23333401, -0.10451285, 0.025911516, 0.021156819, + -0.00066987817, -0.0015032608, 0.000010536012, 0.000009012748, -4.0880101e-7, + -6.3486186e-7, 5.2718557e-9, 1.3520266e-8, 0.0, 0.0, }, + { -0.0063151262, 0.081450872, 0.073146431, -0.033591262, 0.20164331, + 0.68441526, 0.63817515, 0.068893633, -0.23191782, -0.10429366, + 0.025382739, 0.020958119, -0.0005645414, -0.0014434993, 1.2043506e-7, + 1.5836305e-7, -1.9186041e-9, -4.9204755e-9, 0.0, 0.0, }, + { 0.0089685824, -0.012688761, -0.0063138246, 0.081440272, 0.073137193, + -0.033582316, 0.20162334, 0.68433035, 0.63810986, 0.068926154, + -0.23185254, -0.1042793, 0.025363699, 0.020949148, -0.00056217266, + -0.0014417225, 4.1287276e-10, 1.0588585e-9, 0.0, 0.0, }, + { -0.0016078274, 0.0035534844, 0.008968513, -0.012688661, -0.00631377, + 0.081439643, 0.073136632, -0.033582001, 0.20162186, 0.68432512, + 0.63810515, 0.068926132, -0.23185031, -0.10427845, 0.025363336, + 0.020948912, -0.00056214976, -0.0014416961, 0.0, 0.0, }, + { 0.0, 0.0, 0.00024537589, -0.000095677578, -0.0016078292, + 0.0035534886, 0.0089685234, -0.012688676, -0.0063137774, 0.081439737, + 0.073136717, -0.03358204, 0.20162209, 0.68432592, 0.63810589, + 0.068926212, -0.23185058, -0.10427857, 0.025363365, 0.020948936, }, + { 0.0, 0.0, -1.091532e-8, 4.2561286e-9, 0.00024558029, + -0.000095887463, -0.0016090989, 0.0035559773, 0.0089736609, -0.01269917, + -0.0063204498, 0.081485332, 0.073167353, -0.033630667, 0.20170289, + 0.68469343, 0.63846175, 0.068968176, -0.23197726, -0.10433598, }, + { 0.0, 0.0, 7.1344765e-8, -2.7818928e-8, -0.000002528456, + 0.0000018368197, 0.00026997937, -0.00013252441, -0.001740633, 0.0038067121, + 0.0093531772, -0.013821566, -0.0070879361, 0.084739015, 0.074159694, + -0.040471924, 0.20317226, 0.70739793, 0.66214244, 0.072193371, }, + { 0.0, 0.0, -1.7745724e-7, 6.919457e-8, 0.0000079212679, + -0.0000052051852, -0.00011186159, 0.00013087209, 0.0010011907, -0.0014292895, + -0.0047484872, 0.010485041, 0.016207683, -0.039758642, -0.022104737, + 0.14309317, 0.071659816, -0.21620638, 0.12174763, 0.95412469, }, + { 0.96811974, -0.066460839, -0.18990589, -0.12699724, 0.074900229, + 0.019365102, -0.0094028752, -0.0073225687, 0.0024846173, 0.001133314, + -0.000066782094, -0.00017127018, -5.1701849e-12, -2.6883967e-12, 8.4434004e-13, + 4.5714433e-13, -2.0336233e-14, -4.8142821e-14, 0.0, 0.0, }, + { 0.070051015, -0.67622735, 0.69971496, -0.18987268, -0.023601022, + -0.073694534, 0.076964926, 0.0049448517, -0.011660957, -0.0084153664, + 0.003416879, 0.0015114204, -0.000092440393, -0.00023707381, -7.8278594e-12, + -3.4041849e-12, 2.1213123e-13, 5.424444e-13, 0.0, 0.0, }, + { -0.10400446, 0.23379783, 0.070139677, -0.63985915, 0.68278382, + -0.20175657, -0.032740047, -0.072931763, 0.08122816, 0.006212184, + -0.012650812, -0.0089459474, 0.0035507517, 0.0016049328, -0.000095625024, + -0.00024524111, -5.4947649e-15, -1.3849329e-14, 0.0, 0.0, }, + { 0.020927727, -0.025453371, -0.10434942, 0.23188113, 0.068987354, + -0.63810296, 0.68429767, -0.20162896, -0.033573142, -0.073133229, + 0.081437918, 0.006312788, -0.012688459, -0.00896836, 0.0035534757, + 0.0016078143, -0.000095677348, -0.0002453753, 0.0, 0.0, }, + { 0.0, 0.0, -0.001441696, 0.00056214971, 0.020948908, + -0.025363333, -0.10427841, 0.23185026, 0.068925853, -0.63810466, + 0.68432625, -0.20162446, -0.033584819, -0.073127012, 0.081444767, + 0.0062889982, -0.012692356, -0.008907458, 0.0035730328, 0.001494756, }, + { 0.0, 0.0, -8.891553e-14, 3.465479e-14, -0.0014416744, + 0.00056214128, 0.020948423, -0.025362886, -0.10427345, 0.23184342, + 0.06889794, -0.63805105, 0.68441106, -0.20186695, -0.033718945, + -0.072480772, 0.081576567, 0.0047896878, -0.012951761, -0.0055205304, }, + { 0.0, 0.0, 3.1384661e-12, -1.2236911e-12, -4.5712737e-11, + 5.5252991e-11, -0.0014413395, 0.00056201026, 0.020940121, -0.025355656, + -0.10419478, 0.23172734, 0.068557589, -0.63726677, 0.68504332, + -0.20430545, -0.034154654, -0.067051635, 0.082518833, -0.0074921348, }, + { 0.0, 0.0, 2.1591083e-13, -8.4449036e-14, 1.2247511e-13, + 2.5428931e-12, -3.0481069e-11, 2.2021003e-11, -0.0014310921, 0.00055801468, + 0.020774997, -0.025169051, -0.10308717, 0.22974304, 0.064648504, + -0.62768798, 0.69288569, -0.23617203, -0.037952156, 0.0066274123, }, + { 0.0, 0.0, 6.0226175e-14, -2.3096046e-14, -7.8692048e-13, + 1.0072813e-12, 5.1344469e-12, -8.9372637e-12, -3.4167908e-11, 5.4327109e-11, + -0.0014266369, 0.00055627748, 0.020644778, -0.025065139, -0.10169917, + 0.22783, 0.058894795, -0.61350902, 0.69559873, -0.27013783, } +}; + +const double* const ff_on2avc_tabs_9_20_1[9] = { + tabs_9_20[0], tabs_9_20[1], tabs_9_20[2], tabs_9_20[3], tabs_9_20[4], + tabs_9_20[5], tabs_9_20[6], tabs_9_20[7], tabs_9_20[8] +}; + +const double* const ff_on2avc_tabs_9_20_2[9] = { + tabs_9_20[ 9], tabs_9_20[10], tabs_9_20[11], tabs_9_20[12], tabs_9_20[13], + tabs_9_20[14], tabs_9_20[15], tabs_9_20[16], tabs_9_20[17] +}; + +static const double tabs_19_40[19 * 2][40] = { + { 0.56930638, 0.68416675, 0.20290636, -0.29270057, -0.25598083, 0.030953821, 0.11394564, 0.022880839, + -0.028207704, -0.012215512, 0.003721839, 0.003276676, 0.00026276625, -0.00056233677, -0.00035737156, 0.000045825146, + 0.00015152336, 0.000014158357, -0.000048183036, -0.000010022261, 0.000012417808, 0.0000037410435, -0.0000026072561, -0.000001014039, + 4.4228357e-7, 2.1030097e-7, -5.993645000000001e-8, -3.3779106e-8, 6.3845155e-9, 4.1681669e-9, -5.2093484e-10, -3.8565026e-10, + 3.1069535e-11, 2.5581578e-11, -1.2377426e-12, -1.114565e-12, 2.5948758e-14, 2.4949169e-14, 0.0, 0.0, }, + { 0.083936735, 0.17821863, 0.5557409800000001, 0.66602779, 0.18178906, -0.30696561, -0.25275335, 0.044259687, + 0.11887063, 0.016608155, -0.032850108, -0.009887007200000001, 0.0065059949, 0.0025768587, -0.001107713, -0.00043230142, + 0.00021702341, 0.00006287448900000001, -0.000052147048, -0.000013629236, 0.000012262655, 0.0000039527411, -0.0000024594151, -9.9628076e-7, + 4.0201906e-7, 1.9618194e-7, -5.2873852e-8, -3.0291222e-8, 5.4982857e-9, 3.6241851e-9, -4.4014692e-10, -3.274108e-10, + 2.5877833e-11, 2.1342274e-11, -1.021061e-12, -9.1957797e-13, 2.1361163e-14, 2.0538295e-14, 0.0, 0.0, }, + { 0.06426235399999999, 0.14252447, 0.08331282299999999, 0.17697664, 0.54915213, 0.65833374, 0.18253037, -0.29973661, + -0.2501844, 0.040186639, 0.1162191, 0.01848039, -0.030986232, -0.010520451, 0.0054986371, 0.0027059342, + -0.00066811525, -0.00042405191, 0.000058970897, 0.000041824657, -0.0000050297476, -0.0000027888321, 6.4141372e-7, 2.6119558e-7, + -1.0436111e-7, -5.1153743e-8, 1.3625299e-8, 7.8592626e-9, -1.3937291e-9, -9.315507e-10, 1.0721353e-10, 8.1948407e-11, + -5.7676714e-12, -4.9562407e-12, 1.8554768e-13, 1.7299401e-13, -1.8580814e-15, -1.786505e-15, 0.0, 0.0, }, + { -0.013307048, -0.033975901, 0.06420919899999999, 0.14239611, 0.083308942, 0.17697702, 0.54882206, 0.65796781, + 0.18278485, -0.29910579, -0.25007544, 0.039720818, 0.11595345, 0.018673713, -0.030787294, -0.010566866, + 0.0054007477, 0.002707498, -0.0006312670199999999, -0.00041960532, 0.000047781271, 0.000039310002, -0.0000022421464, -0.0000019114661, + 7.288871400000001e-8, 3.3940173e-8, -1.0341206e-8, -5.5262517e-9, 1.2264303e-9, 7.3318115e-10, -1.205231e-10, -7.999549799999999e-11, + 9.360987e-12, 7.031617e-12, -5.2275601e-13, -4.536133e-13, 1.6843252e-14, 1.6194422e-14, 0.0, 0.0, }, + { 0.0018985257, 0.020620645, -0.013303786, -0.033963287, 0.064192393, 0.14235646, 0.08330606, 0.176973, + 0.5487176499999999, 0.65785432, 0.1828607, -0.29890778, -0.25001974, 0.039603104, 0.11587197, 0.018712544, + -0.030736214, -0.010572356, 0.0053789802, 0.002705838, -0.00062416865, -0.00041818516, 0.000045935153, 0.000038762853, + -0.0000018498967, -0.0000017627229, 4.1333815e-9, 2.700156e-9, -3.0391538e-10, -2.6291895e-10, 7.6542367e-12, 1.2019785e-11, + 9.0469833e-13, 5.0485213e-13, -1.0391267e-13, -9.305248e-14, 2.356875e-15, 2.2660843e-15, 0.0, 0.0, }, + { -0.0001091778, -0.010561339, 0.0018984228, 0.020619062, -0.013302974, -0.033960505, 0.064188298, 0.14234701, + 0.08330394300000001, 0.17696883, 0.54868941, 0.6578225599999999, 0.18287011, -0.29886826, -0.25000476, 0.039583069, + 0.11585553, 0.018717708, -0.030727247, -0.010572428, 0.0053756484, 0.0027053082, -0.0006232358500000001, -0.00041792434, + 0.000045731688, 0.000038685285, -0.0000018149671, -0.0000017460375, -5.167502e-10, 9.390694299999999e-12, 1.594319e-10, 5.8184529e-11, + -2.4161347e-11, -1.4454629e-11, 2.1037566e-12, 1.7321615e-12, -9.986456699999999e-14, -9.6017617e-14, 0.0, 0.0, }, + { -0.0005767410599999999, 0.0035190291, -0.00010917955, -0.010561258, 0.0018984108, 0.020618888, -0.013302882, -0.033960202, + 0.064187838, 0.14234596, 0.083303668, 0.17696827, 0.54868618, 0.65781893, 0.18287097, -0.298864, + -0.25000294, 0.039581151, 0.11585376, 0.018718064, -0.03072639, -0.010572378, 0.0053753363, 0.0027052073, + -0.00062317825, -0.00041788417, 0.000045733074, 0.000038677454, -0.0000018196051, -0.0000017460967, 9.887897300000001e-10, 4.6848142e-10, + -1.2195123e-10, -7.9561868e-11, 9.378916700000001e-12, 7.8791268e-12, -3.9130514e-13, -3.7623141e-13, 0.0, 0.0, }, + { 0.00030131631, -0.0010263444, -0.00057674065, 0.0035190268, -0.00010917966, -0.010561251, 0.0018984097, 0.020618873, + -0.013302874, -0.033960176, 0.064187798, 0.14234586, 0.083303637, 0.17696821, 0.54868588, 0.65781858, + 0.182871, -0.29886366, -0.25000278, 0.039580995, 0.11585361, 0.018718039, -0.03072645, -0.010572511, + 0.0053752804, 0.0027052669, -0.00062312096, -0.00041789128, 0.000045707579, 0.000038673143, -0.0000018129216, -0.0000017437794, + -1.7501699e-10, -1.1843802e-10, 1.2678547e-11, 1.0773126e-11, -4.8703456e-13, -4.6827318e-13, 0.0, 0.0, }, + { -0.000089637995, 0.00022613691, 0.0003013163, -0.0010263444, -0.00057674064, 0.0035190267, -0.00010917963, -0.010561251, + 0.0018984096, 0.020618873, -0.013302874, -0.033960176, 0.06418779600000001, 0.14234586, 0.083303635, 0.1769682, + 0.54868587, 0.65781858, 0.18287099, -0.29886369, -0.2500028, 0.039580943, 0.11585345, 0.018717863, + -0.030726497, -0.010572431, 0.005375347, 0.002705256, -0.00062315197, -0.00041789626, 0.000045715815, 0.000038675974, + -0.0000018143635, -0.0000017445048, -7.806062e-12, -6.3155567e-12, 4.0893858e-13, 3.9318559e-13, 0.0, 0.0, }, + { 0.000018826413, -0.000032248448, -0.000089637995, 0.00022613691, 0.0003013163, -0.0010263444, -0.00057674066, 0.0035190267, + -0.00010917957, -0.010561251, 0.0018984095, 0.020618874, -0.013302874, -0.033960178, 0.06418779600000001, 0.14234587, + 0.083303632, 0.17696819, 0.54868589, 0.65781861, 0.18287101, -0.29886365, -0.25000267, 0.039581091, + 0.11585349, 0.018717796, -0.030726553, -0.010572422, 0.0053753731, 0.0027052603, -0.00062315889, -0.00041789864, + 0.000045717027, 0.000038676583, -0.0000018145039, -0.0000017445989, 2.4971934e-12, 2.4009973e-12, 0.0, 0.0, }, + { -0.0000023940844, 0.0000029119687, 0.00001882641, -0.000032248444, -0.000089637969, 0.00022613687, 0.00030131618, -0.0010263441, + -0.00057674024, 0.0035190253, -0.00010918036, -0.010561246, 0.0018984093, 0.020618859, -0.013302871, -0.03396015, + 0.064187778, 0.14234582, 0.08330372, 0.17696839, 0.548686, 0.65781885, 0.18287176, -0.29886274, + -0.25000242, 0.03958068, 0.11585315, 0.01871785, -0.030726394, -0.010572396, 0.0053753308, 0.0027052457, + -0.00062315149, -0.00041789492, 0.000045716169, 0.000038676008, -0.000001814441, -0.0000017445457, 0.0, 0.0, }, + { 0.0, 0.0, 1.3407205e-7, -1.3944369e-7, -0.0000023940844, 0.0000029119687, 0.00001882641, -0.000032248444, + -0.000089637969, 0.00022613687, 0.00030131618, -0.0010263441, -0.00057674024, 0.0035190253, -0.00010918036, -0.010561246, + 0.0018984093, 0.020618859, -0.013302871, -0.03396015, 0.064187778, 0.14234582, 0.08330372, 0.17696839, + 0.548686, 0.65781885, 0.18287176, -0.29886274, -0.25000242, 0.03958068, 0.11585315, 0.01871785, + -0.030726394, -0.010572396, 0.0053753308, 0.0027052457, -0.00062315149, -0.00041789492, 0.000045716169, 0.000038676008, }, + { 0.0, 0.0, -1.8454182e-13, 1.9193555e-13, 1.3407535e-7, -1.394477e-7, -0.0000023941103, 0.0000029120131, + 0.000018826533, -0.000032248755, -0.000089638384, 0.00022613828, 0.00030131697, -0.0010263489, -0.00057674009, 0.0035190398, + -0.00010918297, -0.010561274, 0.0018984276, 0.020618906, -0.013302959, -0.033960346, 0.06418766400000001, 0.14234558, + 0.08330296500000001, 0.17696749, 0.54868575, 0.65781926, 0.1828721, -0.2988628, -0.25000258, 0.039580654, + 0.11585319, 0.018717865, -0.030726402, -0.0105724, 0.0053753317, 0.0027052463, -0.00062315156, -0.00041789497, }, + { 0.0, 0.0, -2.9968756e-14, 3.1169464e-14, 3.4461485e-13, -4.5274253e-13, 1.3407128e-7, -1.3944066e-7, + -0.0000023940918, 0.0000029119648, 0.000018826475, -0.000032248545, -0.000089638294, 0.00022613761, 0.00030131711, -0.001026347, + -0.00057674067, 0.0035190367, -0.00010918012, -0.010561271, 0.0018984144, 0.020618881, -0.013302985, -0.033960402, + 0.06418755499999999, 0.14234546, 0.083302923, 0.17696757, 0.54868595, 0.65781945, 0.18287214, -0.29886289, + -0.25000265, 0.039580667, 0.11585323, 0.01871787, -0.03072641, -0.010572403, 0.0053753332, 0.0027052471, }, + { 0.0, 0.0, 3.4053947e-14, -3.541833e-14, -5.9108424e-13, 7.219441e-13, 3.686965e-12, -6.9987332e-12, + 1.3406826e-7, -1.3941009e-7, -0.0000023941744, 0.0000029119806, 0.000018827177, -0.000032249608, -0.000089641497, 0.00022614485, + 0.00030132559, -0.0010263798, -0.00057675334, 0.0035191463, -0.00010917896, -0.01056153, 0.001898552, 0.020619502, + -0.013303345, -0.033961425, 0.06418858299999999, 0.1423474, 0.083301974, 0.17696773, 0.54869501, 0.65783272, + 0.18287661, -0.29886847, -0.2500077, 0.039581297, 0.11585546, 0.018718257, -0.030726991, -0.010572606, }, + { 0.0, 0.0, 3.8851186e-14, -4.0407771e-14, -9.0297499e-13, 1.0614292e-12, 1.2369841e-11, -1.7194763e-11, + -1.3889432e-10, 2.127443e-10, 1.3529716e-7, -1.415165e-7, -0.000002401917, 0.0000029279859, 0.000018862624, -0.000032344139, + -0.00008976013300000001, 0.00022657145, 0.00030158676, -0.0010279007, -0.00057694943, 0.0035236425, -0.00011001072, -0.010572116, + 0.0019036557, 0.020640207, -0.013321797, -0.034004076, 0.064218883, 0.14240437, 0.083244411, 0.17692659, + 0.54894337, 0.65823916, 0.1830245, -0.29903361, -0.250163, 0.039598328, 0.11592277, 0.018730262, }, + { 0.0, 0.0, -2.5424375e-14, 2.6443011e-14, 1.3072139e-12, -1.4396059e-12, -2.9838328e-11, 3.6121355e-11, + 4.2808479e-10, -5.8577848e-10, -4.3953309e-9, 6.8915491e-9, 1.6727789e-7, -2.00599e-7, -0.0000025787194, 0.0000033304637, + 0.000019584144, -0.000034476114, -0.00009189714, 0.00023541633, 0.00030555578, -0.0010574794, -0.000577822, 0.0036058258, + -0.00013178926, -0.010757609, 0.0020075294, 0.020999334, -0.013644546, -0.03471548, 0.0647074, 0.14319792, + 0.081890324, 0.17546099, 0.55189921, 0.66398787, 0.18532974, -0.30125552, -0.25236809, 0.039796138, }, + { 0.0, 0.0, 5.450404e-14, -5.6687762e-14, -2.413723e-12, 2.68197e-12, 5.4122889e-11, -6.597469100000001e-11, + -7.9689529e-10, 1.0842539e-9, 8.4827594e-9, -1.309149e-8, -6.848642999999999e-8, 1.2194237e-7, 5.5864479e-7, -0.0000010344816, + -0.0000044039463, 0.0000081482122, 0.000025993389, -0.000056794375, -0.0001079834, 0.00031887419, 0.00032752081, -0.0013147952, + -0.00055367277, 0.0042710356, -0.00037367267, -0.01217995, 0.0029410132, 0.023714229, -0.016091617, -0.03973309, + 0.068419296, 0.14835553, 0.070059102, 0.15950508, 0.56354819, 0.6963379, 0.20020752, -0.31277075, }, + { 0.0, 0.0, 2.0986643e-14, -2.1827479e-14, -6.2317928e-13, 7.1419835e-13, 4.9978335e-12, -7.9628623e-12, + 6.4574499e-11, -3.0391734e-11, -2.093182e-9, 2.2676782e-9, 2.7596774e-8, -3.8208137e-8, -2.3879395e-7, 4.0380176e-7, + 0.0000016333254, -0.0000032376466, -0.0000094150001, 0.000021168371, 0.000043315086, -0.00011711363, -0.0001502271, 0.0005427171400000001, + 0.00038159158, -0.0019974544, -0.0004777833, 0.0060120078, -0.0010436508, -0.015880165, 0.0054219755, 0.030749996, + -0.022330626, -0.052220715, 0.07871199800000001, 0.16235935, 0.039966293, 0.11703729, 0.58925396, 0.77487668, }, + { 0.76082901, -0.61501045, 0.070732318, -0.076233884, 0.16721565, -0.04604786, -0.038872216, 0.0073908504, + 0.018642214, -0.00059960166, -0.009041801, 0.000017181816, 0.0029672586, 0.0004791856, -0.00087051626, -0.0002528999, + 0.00019443347, 0.00007609031299999999, -0.000028013417, -0.000016226544, 0.0000025515355, 0.0000020939308, -1.2352758e-7, -1.1871399e-7, + 3.7653573e-11, -5.1553467e-12, -1.2189794e-11, -1.0694795e-12, 4.391544e-12, 1.0258575e-12, -1.1546382e-12, -3.8647265e-13, + 1.8127896e-13, 1.0023162e-13, -1.7537934e-14, -1.43414e-14, 8.6649097e-16, 8.3311729e-16, 0.0, 0.0, }, + { -0.29020148, -0.17058579, 0.73009051, -0.54522599, 0.15148724, -0.089863731, 0.14246903, -0.057880136, + -0.032908729, 0.011933145, 0.019248716, -0.001642844, -0.009891541, 0.00011758938, 0.0032933357, 0.00053302425, + -0.00096384007, -0.00028170914, 0.00021364396, 0.000084221396, -0.000030604054, -0.000017803479, 0.0000027741657, 0.0000022790848, + -1.3343692e-7, -1.2837358e-7, -2.8291166e-11, -4.5113932e-12, 9.653859800000001e-12, 2.5188373e-12, -1.9411097e-12, -8.4860379e-13, + 2.4055653e-13, 1.6608885e-13, -1.7834093e-14, -1.5689603e-14, 5.0113872e-16, 4.818492e-16, 0.0, 0.0, }, + { 0.029507585, 0.23915664, -0.31374537, -0.19147782, 0.66761054, -0.54476742, 0.17718214, -0.085893937, + 0.14081423, -0.0629847, -0.033056336, 0.013055001, 0.020096625, -0.0018682292, -0.010351996, 0.00012827752, + 0.0034538681, 0.00056125575, -0.0010101514, -0.00029566086, 0.00022323168, 0.00008825740999999999, -0.000031896814, -0.000018596176, + 0.0000028845736, 0.0000023710501, -1.3832474e-7, -1.3304067e-7, -1.7294869e-11, -2.81197e-12, 6.3974866e-12, 1.5855057e-12, + -1.1972211e-12, -5.6338465e-13, 1.3134602e-13, 1.0379039e-13, -7.732033400000001e-15, -7.434189599999999e-15, 0.0, 0.0, }, + { 0.02137026, -0.11253601, 0.042589994, 0.25148145, -0.29992597, -0.18470705, 0.65790258, -0.54797686, + 0.17746938, -0.083682167, 0.14200727, -0.064059583, -0.033780176, 0.013281042, 0.020536256, -0.0019008618, + -0.010532156, 0.00011385908, 0.0035109303, 0.00057440761, -0.0010245672, -0.0003006148, 0.00022585476, 0.00008948980099999999, + -0.000032218587, -0.000018804752, 0.0000029102318, 0.0000023922344, -1.3952226e-7, -1.3403637e-7, 3.9608302e-11, 1.3905461e-11, + -6.1363765e-12, -3.3840174e-12, 5.9012281e-13, 4.7995226e-13, -3.0052643e-14, -2.8894955e-14, 0.0, 0.0, }, + { -0.01101232, 0.030164564, 0.018237721, -0.11605179, 0.039730974, 0.25027003, -0.29882164, -0.18303474, + 0.65775001, -0.54862086, 0.17703165, -0.083330352, 0.1423101, -0.064180839, -0.033943639, 0.013302586, + 0.020612508, -0.0018991492, -0.010559265, 0.00010961366, 0.003518543, 0.00057658118, -0.0010262483, -0.00030127666, + 0.00022612153, 0.000089630847, -0.000032246277, -0.000018825371, 0.0000029116033, 0.0000023939368, -1.3937709e-7, -1.3404451e-7, + -9.1223008e-12, -5.4094957e-12, 8.1321806e-13, 6.7296866e-13, -3.7437071e-14, -3.5994924e-14, 0.0, 0.0, }, + { 0.0027523866, -0.0053151929, -0.010522001, 0.030746051, 0.018701664, -0.11588024, 0.039576589, 0.25001961, + -0.29885452, -0.18288052, 0.65781266, -0.54868261, 0.1769717, -0.08330388900000001, 0.14234344, -0.064187437, + -0.03395959, 0.013303046, 0.020618614, -0.0018984637, -0.010561198, 0.00010920031, 0.0035190207, 0.00057673481, + -0.0010263442, -0.00030131581, 0.00022613719, 0.000089638071, -0.000032248498, -0.000018826446, 0.0000029119606, 0.0000023940888, + -1.3944039e-7, -1.3407106e-7, -4.6440655e-13, -3.5507487e-13, 3.1428853e-14, 3.0218153e-14, 0.0, 0.0, }, + { -0.000421003, 0.00061919433, 0.0027019638, -0.0053765775, -0.010571322, 0.030728141, 0.018718075, -0.11585434, + 0.039580128, 0.25000318, -0.29886234, -0.18287235, 0.6578189800000001, -0.54868567, 0.17696763, -0.083302976, + 0.14234552, -0.064187667, -0.033960326, 0.013302963, 0.0206189, -0.0018984291, -0.010561273, 0.00010918342, + 0.0035190396, 0.00057673999, -0.0010263489, -0.00030131696, 0.00022613828, 0.000089638382, -0.000032248755, -0.000018826533, + 0.0000029120131, 0.0000023941103, -1.394477e-7, -1.3407534e-7, 1.9191457e-13, 1.8452165e-13, 0.0, 0.0, }, + { 0.000038791283, -0.000045569699, -0.00041777535, 0.00062319501, 0.0027052056, -0.005375393, -0.010572402, 0.030726437, + 0.018717868, -0.11585317, 0.039580663, 0.25000243, -0.29886273, -0.18287176, 0.65781885, -0.548686, + 0.17696839, -0.08330372, 0.14234582, -0.064187778, -0.03396015, 0.013302871, 0.020618859, -0.0018984093, + -0.010561246, 0.00010918036, 0.0035190253, 0.00057674024, -0.0010263441, -0.00030131618, 0.00022613687, 0.000089637969, + -0.000032248444, -0.00001882641, 0.0000029119687, 0.0000023940844, -1.3944369e-7, -1.3407205e-7, 0.0, 0.0, }, + { 0.0, 0.0, -0.0000017445457, 0.000001814441, 0.000038676008, -0.000045716169, -0.00041789492, 0.00062315149, + 0.0027052457, -0.0053753308, -0.010572396, 0.030726394, 0.01871785, -0.11585315, 0.03958068, 0.25000242, + -0.29886274, -0.18287176, 0.65781885, -0.548686, 0.17696839, -0.08330372, 0.14234582, -0.064187778, + -0.03396015, 0.013302872, 0.020618859, -0.0018984103, -0.010561245, 0.00010918227, 0.0035190235, 0.0005767369100000001, + -0.0010263409, -0.00030131137, 0.00022613101, 0.000089630778, -0.000032235242, -0.000018797134, 0.0000029311054, 0.0000023933095, }, + { 0.0, 0.0, 2.400996e-12, -2.497192e-12, -0.0000017445989, 0.0000018145039, 0.000038676583, -0.000045717027, + -0.00041789864, 0.00062315889, 0.0027052603, -0.0053753731, -0.010572422, 0.030726553, 0.018717796, -0.11585349, + 0.039581091, 0.25000267, -0.29886365, -0.182871, 0.65781861, -0.54868589, 0.17696819, -0.083303628, + 0.14234587, -0.064187807, -0.033960174, 0.013302897, 0.020618859, -0.0018984526, -0.010561213, 0.00010925545, + 0.0035189544, 0.0005766278600000001, -0.0010262111, -0.00030114598, 0.00022584654, 0.00008902247699999999, -0.000032552144, -0.000018664449, }, + { 0.0, 0.0, 3.9319783e-13, -4.0895132e-13, -6.3160719e-12, 7.8066363e-12, -0.0000017445047, 0.0000018143635, + 0.000038675973, -0.000045715815, -0.00041789626, 0.00062315196, 0.002705256, -0.005375347, -0.010572431, 0.030726497, + 0.018717863, -0.11585345, 0.039580944, 0.25000279, -0.29886369, -0.18287097, 0.65781858, -0.54868592, + 0.1769682, -0.083303514, 0.14234582, -0.064188067, -0.033960018, 0.013303399, 0.020618438, -0.0018993478, + -0.010560376, 0.0001106233, 0.0035173821, 0.0005745302, -0.0010229283, -0.00029453156, 0.00022779928, 0.000085362615, }, + { 0.0, 0.0, -4.6834912e-13, 4.8711355e-13, 1.0776346e-11, -1.2682135e-11, -1.1850617e-10, 1.751009e-10, + -0.0000017437784, 0.0000018129203, 0.000038673133, -0.000045707564, -0.00041789121, 0.0006231208299999999, 0.0027052664, -0.0053752795, + -0.010572509, 0.030726445, 0.018718032, -0.11585358, 0.039581016, 0.25000268, -0.2988637, -0.18287068, + 0.65781858, -0.54868677, 0.17696847, -0.08330162200000001, 0.14234476, -0.064191787, -0.033957024, 0.013310076, + 0.020612258, -0.0019097554, -0.010548644, 0.00012671842, 0.0034937666, 0.00052913399, -0.0010278304, -0.00025627314, }, + { 0.0, 0.0, -3.7591141e-13, 3.9097232e-13, 7.8654833e-12, -9.3637194e-12, -7.9270845e-11, 1.2159335e-10, + 4.6441491e-10, -9.8316498e-10, -0.0000017460554, 0.00000181954, 0.000038677134, -0.000045732491, -0.00041788222, 0.00062317407, + 0.0027051979, -0.0053753121, -0.010572343, 0.030726274, 0.018717964, -0.1158533, 0.039581338, 0.25000143, + -0.29886407, -0.1828668, 0.65781782, -0.54869588, 0.17697338, -0.083284289, 0.14233111, -0.06422307200000001, + -0.033928145, 0.013359197, 0.020557279, -0.0019859605, -0.010440679, 0.00032845982, 0.0034922164, 0.00031950723, }, + { 0.0, 0.0, -9.7008176e-14, 1.0089481e-13, 1.77473e-12, -2.1511483e-12, -1.5372262e-11, 2.5287645e-11, + 7.115903100000001e-11, -1.77311e-10, -1.2348213e-10, 7.2542972e-10, -0.0000017450016, 0.0000018130844, 0.000038678971, -0.00004571817, + -0.00041789388, 0.00062315711, 0.0027051921, -0.0053752707, -0.010572087, 0.030725736, 0.018717011, -0.11585044, + 0.03958358, 0.24999022, -0.29886524, -0.18283501, 0.65780555, -0.5487611999999999, 0.17702181, -0.083173702, + 0.14222973, -0.064399687, -0.033732817, 0.01363355, 0.020184552, -0.0026582356, -0.010334243, 0.0011989638, }, + { 0.0, 0.0, 4.8096417e-15, -5.0023409e-15, -2.0363605e-13, 2.2693214e-13, 2.9268545e-12, -3.8691566e-12, + -2.2830499e-11, 4.010721e-11, 1.0030539e-10, -2.6202135e-10, -1.750769e-10, 1.0448174e-9, -0.0000017449923, 0.000001812272, + 0.000038676696, -0.00004571407, -0.0004178554, 0.00062310242, 0.0027048621, -0.0053746982, -0.010570284, 0.03072167, + 0.018710471, -0.11582959, 0.039596876, 0.24991347, -0.29886368, -0.18263206, 0.65769914, -0.54914259, + 0.17734742, -0.082618805, 0.14162772, -0.06527709199999999, -0.032607813, 0.015574165, 0.01947389, -0.0058478027, }, + { 0.0, 0.0, 1.1620773e-14, -1.2086359e-14, -2.5281225e-13, 2.9951516e-13, 2.5798868e-12, -3.9238172e-12, + -1.5091708e-11, 3.1934537e-11, 4.7586293e-11, -1.6454863e-10, -2.4363315e-11, 5.0961544e-10, -4.3869198e-10, -6.2033089e-10, + -0.0000017425281, 0.0000018129976, 0.000038659328, -0.000045695417, -0.00041768461, 0.00062286511, 0.0027034675, -0.0053722734, + -0.010562778, 0.030704525, 0.018683973, -0.1157433, 0.039644886, 0.24960502, -0.29882338, -0.18185802, + 0.65720216, -0.55036798, 0.17856616, -0.080914163, 0.13954371, -0.06882522000000001, -0.030723701, 0.022700612, }, + { 0.0, 0.0, 3.3760298e-15, -3.5112922e-15, -6.3206989e-14, 7.636481800000001e-14, 5.5558903e-13, -9.0603035e-13, + -2.6533985e-12, 6.4749011e-12, 5.3634022e-12, -2.7507239e-11, 1.1363474e-11, 5.960222e-11, -1.0091373e-10, 2.5808497e-11, + 1.3953072e-10, -2.6651685e-10, -0.000001742256, 0.0000018124516, 0.000038611107, -0.000045640594, -0.00041703113, 0.00062197544, + 0.0026981501, -0.0053630599, -0.010535085, 0.030640024, 0.018595029, -0.11543077, 0.039765416, 0.24856666, + -0.29852909, -0.17958773, 0.6555599600000001, -0.5538587699999999, 0.18206628, -0.07570165600000001, 0.13430764, -0.08408151899999999, }, + { 0.0, 0.0, 5.9918017e-16, -6.2318032e-16, -9.9379759e-15, 1.2221683e-14, 8.0845727e-14, -1.3829585e-13, + -3.7650038e-13, 9.459626799999999e-13, 9.869205499999999e-13, -4.1121055e-12, -1.1120552e-12, 1.2402418e-11, -2.0576524e-12, -2.6724353e-11, + 1.4957979e-12, 9.137734800000001e-11, -1.5845915e-9, 1.4784326e-9, -0.0000016861848, 0.0000017493852, 0.000037821856, -0.000044585784, + -0.00041031894, 0.00061056275, 0.0026598482, -0.0052790669, -0.010386803, 0.030195423, 0.018217984, -0.11365566, + 0.040288546, 0.24321245, -0.29862004, -0.16484799, 0.64946229, -0.58650413, 0.20634045, -0.014365476, }, + { 0.0, 0.0, 6.6467568e-17, -6.912305e-17, -6.2475603e-16, 8.5867071e-16, 8.7357039e-16, -5.4126396e-15, + 2.2202664e-14, -5.4492598e-15, -1.70592e-13, 2.8319481e-13, 6.331548e-13, -1.7748409e-12, -1.7196603e-12, 6.8530479e-12, + 2.0919589e-12, -1.9194583e-11, -1.3868107e-8, 1.4507548e-8, 2.4548427e-7, -2.9905628e-7, -0.0000035971494, 0.0000050451109, + 0.00004672424, -0.000067456818, -0.00044153822, 0.00071430062, 0.0027532286, -0.0056688462, -0.010727074, 0.031800916, + 0.019871848, -0.11989559, 0.036659135, 0.26632201, -0.3057397, -0.23220335, 0.68741352, -0.54024027, } +}; + +const double* const ff_on2avc_tabs_19_40_1[19] = { + tabs_19_40[ 0], tabs_19_40[ 1], tabs_19_40[ 2], tabs_19_40[ 3], + tabs_19_40[ 4], tabs_19_40[ 5], tabs_19_40[ 6], tabs_19_40[ 7], + tabs_19_40[ 8], tabs_19_40[ 9], tabs_19_40[10], tabs_19_40[11], + tabs_19_40[12], tabs_19_40[13], tabs_19_40[14], tabs_19_40[15], + tabs_19_40[16], tabs_19_40[17], tabs_19_40[18], +}; + +const double* const ff_on2avc_tabs_19_40_2[19] = { + tabs_19_40[19], tabs_19_40[20], tabs_19_40[21], tabs_19_40[22], + tabs_19_40[23], tabs_19_40[24], tabs_19_40[25], tabs_19_40[26], + tabs_19_40[27], tabs_19_40[28], tabs_19_40[29], tabs_19_40[30], + tabs_19_40[31], tabs_19_40[32], tabs_19_40[33], tabs_19_40[34], + tabs_19_40[35], tabs_19_40[36], tabs_19_40[37], +}; + +static const double tabs_20_84[20 * 4][84] = { + { -0.10690582, 0.094662183, 0.31757963, 0.48370235, 0.53678916, 0.46705598, 0.31621123, 0.15326227, + 0.038302765, -0.0054998811, 0.0073520352, 0.043879657, 0.067374408, 0.060077687, 0.027405389, -0.009983873000000001, + -0.032034985, -0.033515334, -0.017328881, -0.0009890252300000001, 0.0060597434, 0.0056072468, 0.002571725, -0.0007936099700000001, + -0.0027018322, -0.0027530703, -0.0014845177, 0.000064203217, 0.0010169666, 0.0011425746, 0.0006388587, -0.0000018624399, + -0.0003856745, -0.00043471053, -0.00023808948, -0.0000010996843, 0.00013049299, 0.00014628934, 0.00008690307399999999, 0.000020136779, + -0.00001317216, -0.000017142035, -0.0000073231078, 0.0000027043389, 0.0000059557329, 0.0000045096238, 0.0000020887956, 1.9940697e-7, + -5.9358256e-7, -7.422066799999999e-7, -7.3570645e-7, -7.3115553e-7, -7.2933999e-7, -6.8435909e-7, -5.0707974e-7, -3.8679328e-7, + -3.4522208e-7, -2.8271694e-7, -1.3713424e-7, 8.1184249e-9, 9.007577e-8, 1.0329366e-7, 6.463027099999999e-8, 2.1860912e-8, + 5.1066896e-10, -2.670761e-9, -8.5876196e-10, 4.9520519e-9, 1.0149098e-8, 1.0748594e-8, 5.7620398e-9, 1.747266e-12, + -3.1210565e-9, -3.4682633e-9, -1.969792e-9, -4.3451013e-10, 2.1837603e-10, 2.5217949e-10, 1.4564222e-10, 3.9900967e-11, + 0.0, 0.0, 0.0, 0.0, }, + { -0.0065157518, -0.11553191, -0.2003235, -0.20418917, -0.10172818, 0.084274311, 0.29189952, 0.4498939, + 0.5060534800000001, 0.44955248, 0.316223, 0.16751007, 0.057934971, 0.009822325, 0.01258206, 0.039193775, + 0.05803246, 0.052804012, 0.026596935, -0.0041283092, -0.023092596, -0.026167999, -0.014874145, -0.0035171769, + 0.0010177737, 0.0010448012, 0.00056458234, -0.00002147272, -0.00037997699, -0.00042776572, -0.00024136656, -0.0000050238535, + 0.0001358557, 0.00015438052, 0.000084239467, -1.6787043e-7, -0.000046506822, -0.000051573195, -0.00003026341, -0.0000066056329, + 0.0000050707828, 0.0000063933192, 0.0000029272058, -5.6899116e-7, -0.0000017091248, -0.000001263969, -5.570908e-7, -1.1465662e-8, + 2.1544169e-7, 2.5116122e-7, 2.3708156e-7, 2.2251093e-7, 2.1287918e-7, 1.9828806e-7, 1.5178343e-7, 1.2339394e-7, + 1.1450823e-7, 9.427839099999999e-8, 4.5909852e-8, -2.8333617e-9, -3.0612544e-8, -3.510426e-8, -2.1859204e-8, -6.9884918e-9, + 6.0182974e-10, 1.7346196e-9, 7.5210778e-10, -1.6045901e-9, -3.5459042e-9, -3.7642404e-9, -2.0232963e-9, -2.1548766e-11, + 1.0548306e-9, 1.1724849e-9, 6.6598834e-10, 1.4716004e-10, -7.3310163e-11, -8.4658191e-11, -4.8892981e-11, -1.3394998e-11, + 0.0, 0.0, 0.0, 0.0, }, + { 0.009584246100000001, 0.060037953, 0.08995716600000001, 0.07015256, -0.0064981541, -0.11412419, -0.19788136, -0.20183985, + -0.10090064, 0.082591928, 0.28777272, 0.44450316, 0.50121997, 0.44689528, 0.31636017, 0.16979842, + 0.060835882, 0.011721646, 0.012592987, 0.037481155, 0.055630623, 0.050971284, 0.026138847, -0.0031939983, + -0.021447285, -0.024707738, -0.014251364, -0.0038152781, 0.00019304198, 0.00021786771, 0.00012308297, 0.0000035156435, + -0.000067129672, -0.000076387194, -0.000041781791, -4.7347618e-7, 0.000021885498, 0.000024212644, 0.000014093384, 0.0000029734778, + -0.0000024267734, -0.0000029909187, -0.0000014079434, 1.6425532e-7, 6.695171e-7, 4.7998271e-7, 2.0415765e-7, -5.5631332e-10, + -8.1446112e-8, -9.140500800000001e-8, -8.6951648e-8, -8.2795203e-8, -7.961575299999999e-8, -7.5512625e-8, -6.0512776e-8, -5.3113926e-8, + -5.1924925e-8, -4.3533669e-8, -2.1569411e-8, 9.781164100000001e-10, 1.3993484e-8, 1.6121335e-8, 9.9502597e-9, 2.8301122e-9, + -9.3071063e-10, -1.4828863e-9, -7.242862e-10, 6.7853969e-10, 1.7198254e-9, 1.833935e-9, 9.910411099999999e-10, 3.1189792e-11, + -4.7625005e-10, -5.2977179e-10, -3.0102006e-10, -6.6842961e-11, 3.2454035e-11, 3.7477749e-11, 2.1644673e-11, 5.9298973e-12, + 0.0, 0.0, 0.0, 0.0, }, + { 0.01136632, -0.016408158, -0.0349332, -0.02784739, 0.0096145776, 0.059932587, 0.089753479, 0.069975671, + -0.0064946134, -0.11385923, -0.19742994, -0.20142361, -0.10079378, 0.08221251, 0.28695123, 0.44351114, + 0.50044723, 0.44666598, 0.31676682, 0.17065633, 0.061771278, 0.012354413, 0.012717225, 0.037140244, + 0.05507189, 0.050498426, 0.025957566, -0.0030533473, -0.02111719, -0.024381244, -0.01407801, -0.0038307086, + 0.000057284264, 0.000064716373, 0.000035447225, 3.3642675e-7, -0.000018979267, -0.000021222982, -0.000012582227, -0.0000029191463, + 0.0000018740006, 0.0000024460463, 0.0000010713877, -3.2487878e-7, -7.6781933e-7, -5.6583195e-7, -2.5068165e-7, -1.2347619e-8, + 8.297339600000001e-8, 9.823114000000001e-8, 9.7588203e-8, 9.926988499999999e-8, 1.0070428e-7, 9.5071923e-8, 7.044354799999999e-8, 5.3494703e-8, + 4.7613879e-8, 3.8919429e-8, 1.8845507e-8, -1.4101785e-9, -1.3040795e-8, -1.4945684e-8, -9.300971000000001e-9, -2.9841161e-9, + 2.2386009e-10, 6.990386e-10, 2.9986977e-10, -6.7535232e-10, -1.4832646e-9, -1.5740818e-9, -8.4577404e-10, -7.8396292e-12, + 4.4323404e-10, 4.9265612e-10, 2.7983182e-10, 6.1820257e-11, -3.0829599e-11, -3.5601859e-11, -2.0561283e-11, -5.6330855e-12, + 0.0, 0.0, 0.0, 0.0, }, + { -0.015370512, 0.0038188528, 0.022815308, 0.027466485, 0.011338678, -0.016392314, -0.034877413, -0.027788336, + 0.009626457999999999, 0.059869085, 0.089638544, 0.06987961299999999, -0.0064874855, -0.11370564, -0.19717232, -0.20118491, + -0.10072609, 0.08200856400000001, 0.28649294, 0.44293937, 0.49997057, 0.44646556, 0.31690834, 0.17106178, + 0.062258998, 0.012728592, 0.012858441, 0.03704681, 0.054844697, 0.050274532, 0.025838622, -0.0030395781, + -0.021015878, -0.024267531, -0.014014183, -0.0038334853, 0.000012294908, 0.000013971577, 0.0000084331492, 0.0000021207154, + -0.0000010613403, -0.0000014692243, -5.674645600000001e-7, 3.6813259e-7, 6.6471952e-7, 5.0732461e-7, 2.3990309e-7, 3.2527713e-8, + -5.2940032e-8, -7.0272097e-8, -7.4243847e-8, -8.004311e-8, -8.432345e-8, -7.9953609e-8, -5.7174812e-8, -4.0198391e-8, + -3.3846855e-8, -2.7391787e-8, -1.3164822e-8, 9.3143613e-10, 8.8830013e-9, 1.0178346e-8, 6.3897086e-9, 2.2544123e-9, + 2.3155551e-10, -6.9016433e-11, 2.2668746e-11, 5.0194474e-10, 9.691114e-10, 1.0241351e-9, 5.4764968e-10, -5.1352834e-12, + -3.0704315e-10, -3.4111839e-10, -1.9371648e-10, -4.2664063e-11, 2.1615536e-11, 2.4961507e-11, 1.4416119e-11, 3.9495215e-12, + 0.0, 0.0, 0.0, 0.0, }, + { 0.0075782552, 0.00056335562, -0.012867845, -0.020711565, -0.015362833, 0.0038178887, 0.022803262, 0.027450127, + 0.01132947, -0.016385813, -0.034857713, -0.027768817, 0.009628209800000001, 0.059844065, 0.08959629, 0.069845594, + -0.0064833885, -0.11364823, -0.19707655, -0.20109459, -0.10069589, 0.08194085600000001, 0.28632947, 0.44272522, + 0.49977611, 0.44635552, 0.31691232, 0.17116302, 0.062405028, 0.012858212, 0.012929921, 0.037051865, + 0.054806207, 0.050228229, 0.025812903, -0.0030350316, -0.020990856, -0.02423998, -0.013999649, -0.0038354321, + 3.9449016e-7, 6.2546153e-7, 2.2880436e-7, -1.9648504e-7, -3.2799492e-7, -2.4605577e-7, -1.1018746e-7, -3.7855249e-9, + 4.0799542e-8, 4.9097347e-8, 4.6905093e-8, 4.6627152e-8, 4.7685199e-8, 4.451826e-8, 3.0728316e-8, 1.9838579e-8, + 1.5327733e-8, 1.1920072e-8, 5.4900593e-9, -8.1671795e-10, -4.4234746e-9, -5.0171323e-9, -3.160912e-9, -1.1972669e-9, + -2.7582833e-10, -1.3699591e-10, -1.0291296e-10, -2.4784306e-10, -4.2875658e-10, -4.5038598e-10, -2.3901171e-10, 9.433746099999999e-12, + 1.480739e-10, 1.6435722e-10, 9.329815700000001e-11, 2.0425522e-11, -1.0664812e-11, -1.2315669e-11, -7.1127172e-12, -1.9486403e-12, + 0.0, 0.0, 0.0, 0.0, }, + { -0.0031794207, -0.0013173157, 0.0064003509, 0.010140285, 0.0075775394, 0.00056326184, -0.012866591, -0.020709553, + -0.015361329, 0.00381762, 0.022800959, 0.027447143, 0.011327957, -0.016384398, -0.034854051, -0.027765481, + 0.009627986, 0.059838762, 0.089587849, 0.069838924, -0.0064825988, -0.11363701, -0.19705759, -0.2010761, + -0.10068835, 0.081929799, 0.28629916, 0.44268271, 0.49973345, 0.44632462, 0.31689976, 0.17116777, + 0.062419762, 0.01287363, 0.012939169, 0.037052802, 0.054801411, 0.050222414, 0.025809986, -0.0030336964, + -0.020986623, -0.024235277, -0.013996668, -0.0038345525, 6.739720499999999e-8, 4.946956e-8, 2.0815264e-8, -1.3278463e-9, + -1.0398185e-8, -1.1792365e-8, -1.0980052e-8, -1.0573121e-8, -1.0506413e-8, -9.6865614e-9, -6.7673913e-9, -4.517767e-9, + -3.5747705e-9, -2.7739698e-9, -1.2696313e-9, 2.1657762e-10, 1.0751539e-9, 1.2157822e-9, 7.633168300000001e-10, 2.8106144e-10, + 5.1205725e-11, 1.6271833e-11, 1.5300631e-11, 5.7579735e-11, 1.0429514e-10, 1.0968885e-10, 5.8276177e-11, -2.045035e-12, + -3.5598539e-11, -3.951248e-11, -2.2429257e-11, -4.9097703e-12, 2.5651279e-12, 2.9621962e-12, 1.7107689e-12, 4.6869195e-13, + 0.0, 0.0, 0.0, 0.0, }, + { 0.0009898319599999999, -0.00005380164, -0.0016617464, -0.0024058437, -0.0031794045, -0.0013173095, 0.0064003186, 0.010140233, + 0.0075774991, 0.0005632576800000001, -0.012866521, -0.020709442, -0.015361246, 0.003817603, 0.022800833, 0.027446985, + 0.011327883, -0.016384315, -0.034853855, -0.027765311, 0.0096279578, 0.059838456, 0.089587375, 0.069838553, + -0.0064825573, -0.11363639, -0.19705653, -0.20107505, -0.10068788, 0.08192925500000001, 0.28629754, 0.44268034, + 0.49973095, 0.44632262, 0.31689865, 0.17116753, 0.062420092, 0.012874085, 0.012939407, 0.03705269, + 0.054801034, 0.050221973, 0.02580966, -0.0030338396, -0.020986632, -0.024235242, -0.013996676, -0.0038346105, + -2.2089352e-9, -9.1397999e-10, 4.1441104e-10, 1.5632064e-9, 2.1674468e-9, 2.2213076e-9, 1.6242991e-9, 1.220069e-9, + 1.1433859e-9, 1.0132949e-9, 5.303622e-10, 6.3673309e-11, -1.7092595e-10, -2.0591998e-10, -1.3238559e-10, -5.2482661e-11, + -1.557149e-11, -1.0780691e-11, -7.849213899999999e-12, -1.390567e-11, -2.2913106e-11, -2.4240643e-11, -1.3014573e-11, -9.3497669e-14, + 6.8837583e-12, 7.660260199999999e-12, 4.3533487e-12, 9.690445799999999e-13, -4.6444337e-13, -5.3633676e-13, -3.097527e-13, -8.486160400000001e-14, + 0.0, 0.0, 0.0, 0.0, }, + { 0.00021150513, -0.0001182675, -0.00018966171, 0.0007039766, 0.0009898316799999999, -0.000053801616, -0.0016617459, -0.002405843, + -0.0031794035, -0.0013173091, 0.0064003166, 0.01014023, 0.0075774968, 0.00056325744, -0.012866517, -0.020709435, + -0.015361241, 0.0038176018, 0.022800826, 0.027446977, 0.01132788, -0.01638431, -0.034853844, -0.027765303, + 0.0096279543, 0.059838438, 0.089587349, 0.06983853299999999, -0.0064825542, -0.11363636, -0.19705648, -0.20107499, + -0.10068785, 0.08192923000000001, 0.28629745, 0.44268021, 0.4997308, 0.44632248, 0.31689855, 0.17116749, + 0.062420089, 0.012874107, 0.01293944, 0.037052722, 0.054801064, 0.050222001, 0.025809687, -0.0030338132, + -0.020986608, -0.024235225, -0.013996666, -0.0038346066, -1.0807056e-9, -9.6194735e-10, -5.8042675e-10, -2.3026093e-10, + -5.2462083e-11, 8.934574699999999e-12, 2.8753664e-11, 4.2948201e-11, 5.7629255e-11, 6.1074334e-11, 3.9278999e-11, 2.0849977e-11, + 1.506808e-11, 1.3966739e-11, 7.822410799999999e-12, 2.9708823e-12, 1.5662219e-12, 1.4169493e-12, 5.9549711e-13, -6.4389303e-13, + -1.5821434e-12, -1.7440449e-12, -9.8694023e-13, -2.0617409e-13, 1.3336526e-13, 1.540095e-13, 8.8945717e-14, 2.4368072e-14, + 0.0, 0.0, 0.0, 0.0, }, + { 0.000029572086, 0.0001500013, -0.00012528062, -0.000085656495, 0.00021150513, -0.0001182675, -0.00018966171, 0.00070397658, + 0.00098983166, -0.000053801612, -0.0016617459, -0.0024058429, -0.0031794034, -0.0013173091, 0.0064003165, 0.01014023, + 0.0075774967, 0.00056325745, -0.012866517, -0.020709435, -0.015361241, 0.0038176017, 0.022800826, 0.027446976, + 0.01132788, -0.01638431, -0.034853844, -0.027765303, 0.0096279538, 0.059838437, 0.089587348, 0.06983853199999999, + -0.0064825542, -0.11363636, -0.19705647, -0.20107499, -0.10068785, 0.08192923000000001, 0.28629745, 0.4426802, + 0.49973079, 0.44632247, 0.31689854, 0.17116747, 0.062420078, 0.012874099, 0.012939434, 0.037052719, + 0.054801063, 0.050222001, 0.025809688, -0.0030338124, -0.020986608, -0.024235224, -0.013996665, -0.0038346058, + -1.7349485e-10, -1.4014027e-10, -6.733694999999999e-11, 2.3535906e-12, 3.9700971e-11, 4.5614905e-11, 2.9175877e-11, 1.2428934e-11, + 5.1956468e-12, 4.160356e-12, 2.590853e-12, 2.6563084e-12, 3.7861708e-12, 3.9536444e-12, 2.0858696e-12, -1.2971498e-13, + -1.3858912e-12, -1.5382753e-12, -8.7320447e-13, -1.911529e-13, 9.9847212e-14, 1.1530303e-13, 6.6591419e-14, 1.8243762e-14, + 0.0, 0.0, 0.0, 0.0, }, + { -0.0000057370994, 0.000043510151, -0.0000074219963, -0.00011888246, 0.000029572086, 0.0001500013, -0.00012528062, -0.000085656494, + 0.00021150513, -0.0001182675, -0.0001896617, 0.00070397658, 0.00098983165, -0.000053801611, -0.0016617459, -0.0024058429, + -0.0031794034, -0.0013173091, 0.0064003165, 0.01014023, 0.0075774966, 0.00056325745, -0.012866517, -0.020709435, + -0.015361241, 0.0038176017, 0.022800826, 0.027446976, 0.01132788, -0.01638431, -0.034853844, -0.027765303, + 0.009627953700000001, 0.059838437, 0.089587347, 0.06983853199999999, -0.0064825542, -0.11363635, -0.19705647, -0.20107499, + -0.10068785, 0.08192923000000001, 0.28629744, 0.4426802, 0.49973078, 0.44632246, 0.31689853, 0.17116747, + 0.062420077, 0.012874099, 0.012939434, 0.037052719, 0.054801063, 0.050222001, 0.025809688, -0.003033812, + -0.020986607, -0.024235224, -0.013996665, -0.0038346056, 8.9844115e-13, 1.8039035e-12, 1.1116515e-12, -1.2672024e-13, + -9.559857e-13, -1.0248827e-12, -5.1382188e-13, 1.808146e-13, 6.3147038e-13, 6.9078155e-13, 3.8644389e-13, 6.3822893e-14, + -8.5035914e-14, -9.6170938e-14, -5.5045873e-14, -1.3511746e-14, 3.2585157e-15, 3.7629168e-15, 2.1732123e-15, 5.9538554e-16, + 0.0, 0.0, 0.0, 0.0, }, + { -0.000010027921, -0.000010930316, 0.000019234827, -0.000016474706, -0.0000057370994, 0.000043510151, -0.0000074219963, -0.00011888246, + 0.000029572086, 0.0001500013, -0.00012528062, -0.000085656494, 0.00021150513, -0.0001182675, -0.0001896617, 0.00070397658, + 0.00098983165, -0.000053801611, -0.0016617459, -0.0024058429, -0.0031794034, -0.0013173091, 0.0064003165, 0.01014023, + 0.0075774966, 0.00056325745, -0.012866517, -0.020709435, -0.015361241, 0.0038176017, 0.022800826, 0.027446976, + 0.01132788, -0.01638431, -0.034853844, -0.027765303, 0.009627953700000001, 0.059838436, 0.089587347, 0.06983853199999999, + -0.0064825542, -0.11363635, -0.19705647, -0.20107499, -0.10068785, 0.08192923000000001, 0.28629744, 0.4426802, + 0.49973078, 0.44632246, 0.31689853, 0.17116747, 0.062420077, 0.012874099, 0.012939434, 0.037052719, + 0.054801063, 0.050222001, 0.025809688, -0.003033812, -0.020986607, -0.024235224, -0.013996665, -0.0038346056, + -5.2802279e-13, -3.8437399e-13, -2.4041388e-13, -2.8463768e-13, -4.2600563e-13, -4.4368416e-13, -2.3294104e-13, 1.9132449e-14, + 1.637729e-13, 1.8161207e-13, 1.0304955e-13, 2.2420723e-14, -1.2069513e-14, -1.393781e-14, -8.0495588e-15, -2.2053027e-15, + 0.0, 0.0, 0.0, 0.0, }, + { -0.0000030589933, -0.0000034582443, 0.0000041270616, 0.000012505734, -0.000010027921, -0.000010930316, 0.000019234827, -0.000016474706, + -0.0000057370994, 0.000043510151, -0.0000074219963, -0.00011888246, 0.000029572086, 0.0001500013, -0.00012528062, -0.000085656494, + 0.00021150513, -0.0001182675, -0.0001896617, 0.00070397658, 0.00098983165, -0.000053801611, -0.0016617459, -0.0024058429, + -0.0031794034, -0.0013173091, 0.0064003165, 0.01014023, 0.0075774966, 0.00056325745, -0.012866517, -0.020709435, + -0.015361241, 0.0038176017, 0.022800826, 0.027446976, 0.01132788, -0.01638431, -0.034853844, -0.027765303, + 0.009627953700000001, 0.059838436, 0.089587347, 0.06983853199999999, -0.0064825542, -0.11363635, -0.19705647, -0.20107499, + -0.10068785, 0.08192923000000001, 0.28629744, 0.4426802, 0.49973078, 0.44632246, 0.31689853, 0.17116747, + 0.062420077, 0.012874099, 0.012939434, 0.037052719, 0.054801063, 0.050222001, 0.025809688, -0.003033812, + -0.020986607, -0.024235224, -0.013996665, -0.0038346056, -6.2170478e-14, -6.383222999999999e-14, -3.2934372e-14, 5.0060707e-15, + 2.7669088e-14, 3.0656054e-14, 1.738787e-14, 3.7610419e-15, -2.0823764e-15, -2.4047173e-15, -1.388806e-15, -3.8048514e-16, + 0.0, 0.0, 0.0, 0.0, }, + { 3.6812554e-7, -0.0000013162529, 8.907414900000001e-7, 0.0000021605209, -0.0000030589933, -0.0000034582443, 0.0000041270616, 0.000012505734, + -0.000010027921, -0.000010930316, 0.000019234827, -0.000016474706, -0.0000057370994, 0.000043510151, -0.0000074219963, -0.00011888246, + 0.000029572086, 0.0001500013, -0.00012528062, -0.000085656494, 0.00021150513, -0.0001182675, -0.0001896617, 0.00070397658, + 0.00098983165, -0.000053801611, -0.0016617459, -0.0024058429, -0.0031794034, -0.0013173091, 0.0064003165, 0.01014023, + 0.0075774966, 0.00056325745, -0.012866517, -0.020709435, -0.015361241, 0.0038176017, 0.022800826, 0.027446976, + 0.01132788, -0.01638431, -0.034853844, -0.027765303, 0.009627953700000001, 0.059838436, 0.089587347, 0.06983853199999999, + -0.0064825542, -0.11363635, -0.19705647, -0.20107499, -0.10068785, 0.08192923000000001, 0.28629744, 0.4426802, + 0.49973078, 0.44632246, 0.31689853, 0.17116747, 0.062420077, 0.012874099, 0.012939434, 0.037052719, + 0.054801063, 0.050222001, 0.025809688, -0.003033812, -0.020986607, -0.024235224, -0.013996665, -0.0038346056, + 6.8070256e-15, 7.5939277e-15, 4.3204891e-15, 9.7727649e-16, -4.2864944e-16, -4.9500211e-16, -2.8588054e-16, -7.832144999999999e-17, + 0.0, 0.0, 0.0, 0.0, }, + { -1.3565721e-7, 3.3158394e-7, -1.1299252e-7, 6.2458675e-7, 3.6812554e-7, -0.0000013162529, 8.907414900000001e-7, 0.0000021605209, + -0.0000030589933, -0.0000034582443, 0.0000041270616, 0.000012505734, -0.000010027921, -0.000010930316, 0.000019234827, -0.000016474706, + -0.0000057370994, 0.000043510151, -0.0000074219963, -0.00011888246, 0.000029572086, 0.0001500013, -0.00012528062, -0.000085656494, + 0.00021150513, -0.0001182675, -0.0001896617, 0.00070397658, 0.00098983165, -0.000053801611, -0.0016617459, -0.0024058429, + -0.0031794034, -0.0013173091, 0.0064003165, 0.01014023, 0.0075774966, 0.00056325745, -0.012866517, -0.020709435, + -0.015361241, 0.0038176017, 0.022800826, 0.027446976, 0.01132788, -0.01638431, -0.034853844, -0.027765303, + 0.009627953700000001, 0.059838436, 0.089587347, 0.06983853199999999, -0.0064825542, -0.11363635, -0.19705647, -0.20107499, + -0.10068785, 0.08192923000000001, 0.28629744, 0.4426802, 0.49973078, 0.44632246, 0.31689853, 0.17116747, + 0.062420077, 0.012874099, 0.012939434, 0.037052719, 0.054801063, 0.050222001, 0.025809688, -0.003033812, + -0.020986607, -0.024235224, -0.013996665, -0.0038346056, 4.0075758e-16, 4.6279274e-16, 2.6727853e-16, 7.3225139e-17, + 0.0, 0.0, 0.0, 0.0, }, + { 9.2129029e-8, 4.470829e-8, -1.3675036e-7, -4.31831e-7, -1.3565721e-7, 3.3158394e-7, -1.1299252e-7, 6.2458675e-7, + 3.6812554e-7, -0.0000013162529, 8.907414900000001e-7, 0.0000021605209, -0.0000030589933, -0.0000034582443, 0.0000041270616, 0.000012505734, + -0.000010027921, -0.000010930316, 0.000019234827, -0.000016474706, -0.0000057370994, 0.000043510151, -0.0000074219963, -0.00011888246, + 0.000029572086, 0.0001500013, -0.00012528062, -0.000085656494, 0.00021150513, -0.0001182675, -0.0001896617, 0.00070397658, + 0.00098983165, -0.000053801611, -0.0016617459, -0.0024058429, -0.0031794034, -0.0013173091, 0.0064003165, 0.01014023, + 0.0075774966, 0.00056325745, -0.012866517, -0.020709435, -0.015361241, 0.0038176017, 0.022800826, 0.027446976, + 0.01132788, -0.01638431, -0.034853844, -0.027765303, 0.009627953700000001, 0.059838436, 0.089587347, 0.06983853199999999, + -0.0064825542, -0.11363635, -0.19705647, -0.20107499, -0.10068785, 0.08192923000000001, 0.28629744, 0.4426802, + 0.49973078, 0.44632246, 0.31689853, 0.17116747, 0.062420077, 0.012874099, 0.012939434, 0.037052719, + 0.054801063, 0.050222001, 0.025809688, -0.003033812, -0.020986607, -0.024235224, -0.013996665, -0.0038346056, + 0.0, 0.0, 0.0, 0.0, }, + { 0.0, 0.0, 0.0, 0.0, -8.764059600000001e-9, -6.963307e-9, 1.5066994e-8, 3.6978382e-8, + 9.2186128e-8, 4.4735999e-8, -1.3683511e-7, -4.3209863e-7, -1.3574128e-7, 3.3178945e-7, -1.1306255e-7, 6.2497386e-7, + 3.683537e-7, -0.0000013170687, 8.9129355e-7, 0.00000216186, -0.0000030608892, -0.0000034603877, 0.0000041296194, 0.000012513485, + -0.000010034136, -0.00001093709, 0.000019246748, -0.000016484916, -0.0000057406551, 0.000043537117, -0.0000074265962, -0.00011895614, + 0.000029590414, 0.00015009426, -0.00012535827, -0.00008570958199999999, 0.00021163621, -0.0001183408, -0.00018977925, 0.00070441288, + 0.0009904451199999999, -0.000053834956, -0.0016627758, -0.002407334, -0.0031813739, -0.0013181255, 0.0064042832, 0.010146514, + 0.0075821929, 0.00056360654, -0.012874492, -0.02072227, -0.015370762, 0.0038199677, 0.022814957, 0.027463987, + 0.0113349, -0.016394464, -0.034875445, -0.027782511, 0.009633920799999999, 0.059875523, 0.089642871, 0.069881816, + -0.0064865719, -0.11370678, -0.1971786, -0.20119961, -0.10075025, 0.08198000699999999, 0.28647488, 0.44295456, + 0.5000405, 0.44659908, 0.31709494, 0.17127356, 0.062458763, 0.012882078, 0.012947454, 0.037075684, + 0.054835027, 0.050253127, 0.025825684, -0.0030356923, }, + { 0.0, 0.0, 0.0, 0.0, 2.3914563e-11, 1.9000834e-11, -4.1113434e-11, -1.0090322e-10, + -9.0429743e-9, -7.1071213e-9, 1.5487424e-8, 3.8272917e-8, 9.284437599999999e-8, 4.3970329e-8, -1.3695386e-7, -4.3515323e-7, + -1.3717026e-7, 3.3641935e-7, -1.1584767e-7, 6.2102624e-7, 3.7785615e-7, -0.0000013117388, 8.8280807e-7, 0.0000021344647, + -0.0000030430666, -0.0000034413485, 0.0000040899953, 0.000012597541, -0.000010049803, -0.000011090041, 0.00001932711, -0.000016211794, + -0.0000058393238, 0.000043263497, -0.0000071077195, -0.0001190937, 0.000029105316, 0.00015088585, -0.00012523184, -0.00008789934600000001, + 0.00020959441, -0.00011856341, -0.0001858346, 0.00071318131, 0.0010022188, -0.000050406274, -0.0016854432, -0.0024425377, + -0.0032119973, -0.0013237792, 0.0064594112, 0.010234742, 0.0076478105, 0.00055494281, -0.012976947, -0.020861916, + -0.015449686, 0.0038766312, 0.022981361, 0.027625553, 0.011344005, -0.016609039, -0.035228952, -0.028059949, + 0.0096817025, 0.060372756, 0.090460822, 0.070649035, -0.006231908, -0.11428553, -0.19857599, -0.20303655, + -0.10242931, 0.08101735, 0.28650414, 0.44387032, 0.50143144, 0.44795843, 0.31804973, 0.17170719, + 0.062504161, 0.012785176, 0.012917411, 0.037199735, }, + { 0.0, 0.0, 0.0, 0.0, 1.7208769e-11, 1.3672881e-11, -2.9584969e-11, -7.260932400000001e-11, + -1.9502299e-10, -9.8973137e-11, 2.9276962e-10, 9.0756433e-10, -8.4024356e-9, -7.5848188e-9, 1.5160135e-8, 3.5281047e-8, + 9.1795739e-8, 4.8119378e-8, -1.3958217e-7, -4.3792198e-7, -1.299519e-7, 3.3845784e-7, -1.2042094e-7, 6.0758667e-7, + 3.8536054e-7, -0.000001308981, 8.6541935e-7, 0.0000022271281, -0.0000030839153, -0.0000035840001, 0.0000041996021, 0.000012795353, + -0.000010161269, -0.000011227452, 0.000019595831, -0.000016605111, -0.0000061431566, 0.000044269118, -0.0000072986449, -0.00012118588, + 0.000028160432, 0.0001509061, -0.00012314444, -0.000080367843, 0.00022072872, -0.00011654453, -0.00020614453, 0.00068484311, + 0.00097637937, -0.000057369856, -0.0016371767, -0.0023647844, -0.0031580486, -0.0013325879, 0.0063771053, 0.010119985, + 0.0075805926, 0.00060526641, -0.012846336, -0.020747422, -0.015463245, 0.0036989769, 0.022719278, 0.027446179, + 0.01143065, -0.016173272, -0.034553004, -0.027441455, 0.009878847, 0.059889938, 0.089299875, 0.06910726, + -0.0076681795, -0.11513091, -0.19851945, -0.20202798, -0.10067452, 0.08315763499999999, 0.28866517, 0.44579776, + 0.5030154, 0.44918495, 0.31895639, 0.17236043, }, + { 0.0, 0.0, 0.0, 0.0, 3.6851694e-10, 2.9279771e-10, -6.335468899999999e-10, -1.5548913e-9, + -4.6510001e-9, -2.4966087e-9, 7.0855764e-9, 2.1437864e-8, 1.3169401e-8, -1.0542802e-8, -6.1601155e-9, -6.1575439e-8, + -3.4073418e-8, 7.724169599999999e-8, -3.4452297e-8, -1.1253081e-8, 2.9592187e-7, 1.2560497e-7, -3.1939331e-7, -9.671230100000001e-7, + -3.3711275e-8, 5.7369354e-7, -5.5258612e-7, 0.0000029538269, -3.0498174e-7, -0.0000051446274, 0.0000037421504, 0.000007933204999999999, + -0.0000073627242, -0.0000087743051, 0.000012632452, 0.000011519312, -0.000022548551, 0.0000044186995, 0.000026652061, -0.00007250452599999999, + -0.000029667452, 0.000072190638, 0.000031608516, -0.000030718401, 0.00028455347, 0.00027795666, -0.00062873194, -0.00071930588, + -0.00018882003, -0.00033095544, 0.00067798053, 0.0026897514, 0.0026281934, -0.00029899771, -0.0042160247, -0.0059853387, + -0.0062551191, -0.0010063188, 0.012567797, 0.017963467, 0.011342289, -0.0027790647, -0.025355323, -0.035902046, + -0.022213305, 0.014809325, 0.049440119, 0.055745988, 0.022283613, -0.034643741, -0.077415581, -0.07472068, + -0.015256075, 0.073924579, 0.13781927, 0.12632161, 0.023452078, -0.13385396, -0.26083401, -0.26880791, + -0.11637654, 0.16325051, 0.4764406, 0.7149867, }, + { -0.8535439, -0.35968119, 0.065351407, 0.059333029, -0.1269521, -0.076877898, -0.10933188, 0.15495355, + 0.054522357, -0.23877106, -0.00046647111, 0.089122653, -0.026462813, 0.048335133, -0.0079782051, -0.016659518, + 0.047159549, -0.037963054, -0.011292312, 0.027672996, -0.018929343, 0.0034709715, 0.0029394227, -0.0041317473, + 0.0053664905, -0.0034050512, -0.0026283962, 0.001701639, -1.4621633e-18, -7.386584000000001e-18, -8.5187602e-19, 8.977116299999999e-18, + 1.7897277e-18, -9.0759985e-18, 1.7650852e-18, 1.3050953e-18, -1.1888393e-18, 3.6267152e-18, -1.5965868e-18, -2.9834012e-19, + 2.6322817e-18, -2.3718141e-18, 6.9968316e-19, 2.1831511e-18, -1.8853562e-18, 1.9795454e-19, 2.0018813e-19, -4.9845616e-19, + 7.4533925e-19, -3.7752172e-19, -3.6230857e-19, 3.6040853e-19, -6.196548599999999e-20, -1.1505867e-19, 9.5248123e-20, 3.1535333e-20, + -7.2976602e-20, 3.3552326e-20, -3.6298577e-20, -2.6232003e-20, 3.7424549e-20, -4.9240473e-20, -5.6073546e-21, 3.8346556e-20, + -2.6796095e-20, 2.3158911e-21, 4.7582374e-21, -2.8967253e-21, 6.5855823e-21, -9.9663562e-21, -5.6020698e-21, 4.1833883e-21, + 1.0439859e-21, 1.7132787e-22, -5.812353400000001e-23, 3.0334018e-22, 2.9773051e-22, -3.5694498e-22, -2.5609715e-22, 1.0779825e-22, + 0.0, 0.0, 0.0, 0.0, }, + { 0.0097491326, 0.49799784, 0.49667555, -0.028559998, -0.42222797, -0.18514687, 0.2500187, 0.31609299, + -0.068894788, -0.23630869, 0.051357429, 0.18649924, -0.0027572124, -0.13295343, -0.066275158, 0.0590209, + 0.064667315, -0.024369346, -0.018853311, 0.022018745, -0.00008582693, -0.012650973, -0.008405076799999999, 0.0012936423, + 0.0016217257, -0.0010289889, -0.00079428773, 0.0005142265, 3.837204e-18, -5.1417775e-18, 1.6180876e-18, 1.3329307e-18, + -3.4207218e-18, 4.2353711e-18, 1.1016565e-18, -6.9071994e-18, 4.800252e-18, 4.6916197e-18, -3.6758436e-18, -2.1583284e-18, + 7.2104057e-19, 2.2650924e-19, 1.4887113e-18, -9.0359689e-19, -1.9341924e-18, 2.0497686e-18, 3.4265221e-19, -1.0853157e-18, + 6.8534707e-19, -3.3981292e-19, -5.8153225e-21, 3.4694372e-19, -3.6884567e-19, 2.325747e-19, 1.1847485e-19, -1.9271002e-19, + 1.0387854e-19, -4.2515241e-21, -4.4545004e-20, 4.429267e-21, -4.2326837e-21, 4.0949538e-21, 1.7076984e-20, -3.7107451e-21, + -1.6750204e-20, 9.3038469e-21, 3.4943875e-21, -4.5159418e-21, 4.0634963e-21, -2.835022e-21, 1.4147726e-22, 2.8528805e-21, + -2.5032938e-21, -4.1947499e-22, -1.4819835e-22, -4.270146e-22, 8.2949421e-22, -3.9522162e-22, -3.2534223e-22, 2.5448899e-22, + 0.0, 0.0, 0.0, 0.0, }, + { -0.043868099, -0.11359779, -0.23884371, -0.31126971, -0.03080143, 0.38884179, 0.3428215, -0.14827109, + -0.46703243, -0.19177262, 0.29481908, 0.27261094, -0.11727332, -0.20703374, 0.041159567, 0.17723309, + 0.019225426, -0.14351258, -0.060622382, 0.07083052099999999, 0.054619012, -0.014728714, -0.017162395, 0.0148445, + 0.0059330378, -0.014589274, -0.009891233100000001, 0.0026891131, -1.4871029e-17, 4.5609802e-18, -6.5993686e-18, -2.0104526e-17, + 8.4690133e-18, -4.8460668e-18, -3.5542414e-18, -2.7023903e-18, 1.2011757e-18, 2.8554601e-18, -1.4641397e-19, -5.2258014e-18, + 2.1733685e-18, 3.3779312e-18, -1.3649109e-19, -2.1880083e-18, -1.5772341e-19, 1.5069148e-18, 1.3492288e-18, -8.802379500000001e-19, + -1.0697808e-18, 6.9070831e-19, 2.3374065e-19, -1.1077769e-19, 1.3077631e-19, -2.8574171e-19, 1.415901e-19, 1.7828577e-19, + -1.5396053e-19, 7.5893357e-20, -4.3050603e-20, -8.3679005e-20, 1.3347946e-19, -5.4974401e-20, -1.7493216e-21, 3.3365805e-20, + -5.8985959e-20, 1.9211594e-20, 8.331346600000001e-21, -1.0148857e-20, 6.4122352e-21, -1.8011728e-20, -2.2948955e-21, 1.1046082e-20, + -6.5384535e-21, -1.9688739e-21, -1.1027418e-21, -7.3109031e-22, 3.475493e-21, -1.7477936e-21, -1.424523e-21, 1.075262e-21, + 0.0, 0.0, 0.0, 0.0, }, + { -0.11350485, 0.078457191, 0.23123985, 0.16377816, -0.0053257425, -0.11081688, -0.17690723, -0.1882482, + 0.024386161, 0.35978077, 0.34619534, -0.13380312, -0.47092927, -0.18321328, 0.29495422, 0.27700897, + -0.1107013, -0.2220893, 0.041645458, 0.187296, 0.010609985, -0.14990385, -0.063127034, 0.071396236, + 0.059312169, -0.014899249, -0.018035052, 0.015904326, 0.0060997472, -0.01511777, -0.01047208, 0.0025348521, + 0.000094772741, 0.00018699728, -0.00009023797399999999, -0.00018613552, 0.000039646997, 0.00012704541, 0.000021476997, -0.00007741941, + -0.000031298152, 0.000067956454, 0.000037690455, -0.000029151857, -0.000015545855, 0.000014856125, 0.000015237388, -0.0000027604675, + -0.0000057556044, -1.3476965e-8, 0.0000028285011, 9.4403854e-7, -2.2498423e-7, -0.0000015897131, -6.5328073e-7, 6.4520141e-7, + 5.13012e-7, -5.7050618e-7, -4.7024882e-7, 1.9002285e-7, 1.6475241e-7, -7.181441e-8, -8.440031899999999e-8, 2.4316993e-8, + 5.7585708e-9, 1.4360563e-8, 5.5108486e-9, -4.6057052e-9, -5.3604255e-9, 5.1973797e-9, 4.9569464e-9, -1.6041796e-9, + -1.868336e-9, 7.621408200000001e-10, 5.8431354e-10, -4.9659479e-10, 2.442538e-10, -1.5448383e-10, -1.1904637e-10, 7.7304831e-11, + 0.0, 0.0, 0.0, 0.0, }, + { 0.018943425, -0.00023134148, -0.051032993, -0.14158766, -0.1219561, 0.060207541, 0.20496175, 0.1352868, + -0.028897426, -0.12425083, -0.17929974, -0.18396477, 0.0280128, 0.35786456, 0.34036011, -0.13789513, + -0.4700605, -0.17977395, 0.29670633, 0.27653234, -0.1105855, -0.21980639, 0.044009223, 0.18725153, + 0.008622334299999999, -0.15146531, -0.063196745, 0.07186579, 0.059376049, -0.014785703, -0.017430318, 0.016309961, + 0.0058585315, -0.015503177, -0.010351797, 0.0028796789, 0.000030161127, -0.00010871535, -0.000054762367, 0.000049991893, + 0.000030931583, -0.000034949267, -0.000026658113, 0.000012548204, 0.0000085226258, -0.0000033484801, -0.000006354489, -6.016628e-7, + 0.0000018156312, 0.0000016799919, -2.9269113e-7, -0.0000011148862, -3.2141225e-7, 0.0000011159281, 6.2161289e-7, -4.3728317e-7, + -3.2357674e-7, 2.9479843e-7, 2.5855335e-7, -9.861939099999999e-8, -7.7174471e-8, 2.357143e-8, 3.4866513e-8, -7.2848793e-9, + 4.1725233e-10, -1.0232913e-8, -5.1858942e-9, 3.493822e-9, 3.2966092e-9, -2.9205056e-9, -2.772405e-9, 9.5707304e-10, + 9.349160000000001e-10, -3.607995e-10, -2.7638764e-10, 2.4385053e-10, -1.3420421e-10, 8.4880481e-11, 6.5409521e-11, -4.2474809e-11, + 0.0, 0.0, 0.0, 0.0, }, + { -0.042099341, 0.0049466918, 0.060032676, 0.053056167, 0.019616496, 0.0062036013, -0.038995874, -0.12624839, + -0.10751575, 0.069583591, 0.20780096, 0.13338201, -0.032366324, -0.12649959, -0.17867505, -0.18073608, + 0.031238128, 0.35847857, 0.33866999, -0.13958546, -0.47087746, -0.18085881, 0.29523238, 0.27623237, + -0.10915239, -0.21827969, 0.044204705, 0.18674789, 0.008460475699999999, -0.15160207, -0.063812811, 0.071407823, + 0.059707723, -0.014212698, -0.017418974, 0.015975258, 0.0058538568, -0.015264018, -0.01033238, 0.0027038771, + -0.0000012051987, 0.000010834885, 0.0000041549531, -0.0000052634061, -0.0000023429131, 0.0000034400397, 0.0000028289785, -9.1863911e-7, + -0.0000012270482, 4.0351997e-7, 7.5101858e-7, 4.7474055e-9, -1.4510685e-7, -1.8989353e-7, -3.8281943e-8, 8.072763899999999e-8, + 7.066967400000001e-8, -9.4210763e-8, -7.3956251e-8, 3.115984e-8, 2.9133811e-8, -1.5014384e-8, -1.606001e-8, 5.2321014e-9, + 1.7924899e-9, 1.7024681e-9, 3.7814988e-10, -4.778233e-10, -7.9390088e-10, 8.1430637e-10, 7.7594964e-10, -2.4383214e-10, + -3.0886716e-10, 1.3001907e-10, 9.9726822e-11, -8.3004062e-11, 3.8036166e-11, -2.4056832e-11, -1.8538371e-11, 1.2038213e-11, + 0.0, 0.0, 0.0, 0.0, }, + { -0.0051186317, 0.0026082139, 0.0011561029, -0.027835056, -0.043654175, 0.0024567809, 0.056866436, 0.049722261, + 0.016705706, 0.0041957359, -0.039911418, -0.12626296, -0.10711407, 0.069886621, 0.207737, 0.13299916, + -0.032807178, -0.12670819, -0.17850805, -0.18026528, 0.03173076, 0.3587233, 0.33861929, -0.13974791, + -0.47100956, -0.18098662, 0.29508412, 0.27616175, -0.10905287, -0.21808239, 0.04432355, 0.18671439, + 0.008368981899999999, -0.15163858, -0.063790702, 0.071424185, 0.059696165, -0.014211805, -0.017387543, 0.016000355, + 0.0058451304, -0.015287092, -0.010335228, 0.0027174845, 0.0000020768948, -5.7483511e-7, -0.0000013986923, -2.0846925e-7, + 3.3989431e-7, 4.6234671e-7, 1.5124727e-8, -2.6644477e-7, -1.0785895e-7, 2.5703709e-7, 1.5722009e-7, -9.7984161e-8, + -7.3898702e-8, 6.035174000000001e-8, 5.4781732e-8, -2.0282833e-8, -1.4592424e-8, 3.0544033e-9, 5.8925631e-9, -9.0937458e-10, + 5.4095235e-10, -2.3396208e-9, -1.3722115e-9, 7.9084999e-10, 7.5764257e-10, -6.0261359e-10, -5.6187916e-10, 2.161657e-10, + 1.5585732e-10, -5.5402911e-11, -4.2385399e-11, 3.9580331e-11, -2.5135395e-11, 1.5897448e-11, 1.225069e-11, -7.9551986e-12, + 0.0, 0.0, 0.0, 0.0, }, + { -0.0071084674, -0.0033836798, 0.012325746, 0.008056183999999999, -0.0058137499, 0.0029806292, 0.0026693637, -0.025573967, + -0.041351054, 0.0041008264, 0.057495506, 0.049458219, 0.016024743, 0.0036418724, -0.039989343, -0.12584118, + -0.10648721, 0.07032519399999999, 0.20775682, 0.13264239, -0.033314247, -0.12711621, -0.17863318, -0.18010455, + 0.032003531, 0.35891666, 0.33867579, -0.13976955, -0.47107608, -0.18111434, 0.29494862, 0.2761335, + -0.10895874, -0.21798696, 0.044327136, 0.18667373, 0.0083638593, -0.15162138, -0.063800826, 0.071398434, + 0.059697546, -0.0141866, -0.017375994, 0.015991099, 0.005839154, -0.015281732, -0.010330736, 0.0027152827, + 6.7571268e-8, 1.0574211e-7, 1.1225055e-8, -5.6939946e-8, -2.7184582e-8, 5.4989418e-8, 3.5491693e-8, -2.0532338e-8, + -1.5851011e-8, 1.199146e-8, 1.1153341e-8, -4.0527661e-9, -2.70396e-9, 3.3976271e-10, 9.757715999999999e-10, -9.7092189e-11, + 1.7708423e-10, -4.9642505e-10, -3.1843656e-10, 1.6615e-10, 1.6237103e-10, -1.1900391e-10, -1.092032e-10, 4.5808636e-11, + 2.4606003e-11, -7.796026e-12, -5.9521785e-12, 6.0340975e-12, -4.5217706e-12, 2.8598959e-12, 2.2038568e-12, -1.4311127e-12, + 0.0, 0.0, 0.0, 0.0, }, + { -0.001265786, -0.0016609477, 0.00222941, 0.0011762007, -0.0073250731, -0.0034332159, 0.012471328, 0.0083430294, + -0.0054961577, 0.003215434, 0.0027593588, -0.025616888, -0.041455975, 0.0040184504, 0.057488632, 0.049527597, + 0.016124517, 0.0037132221, -0.039983743, -0.12589765, -0.1065697, 0.070258873, 0.20773562, 0.13266656, + -0.033268011, -0.12707599, -0.17861669, -0.18011328, 0.031979675, 0.35889134, 0.33866157, -0.13976776, + -0.4710648, -0.18110469, 0.29495129, 0.27613251, -0.10895966, -0.21798881, 0.044323721, 0.18667181, + 0.0083658499, -0.15161776, -0.06379945300000001, 0.071397486, 0.059696885, -0.014186055, -0.017375485, 0.015990851, + 0.005838785, -0.015281695, -0.010330521, 0.0027153303, -1.3725082e-9, 2.288355e-8, 1.1355676e-8, -8.889336600000001e-9, + -7.3277766e-9, 7.1743165e-9, 6.1308246e-9, -2.3901982e-9, -1.9373079e-9, 6.9554647e-10, 9.1814463e-10, -2.40284e-10, + -1.9481616e-11, -2.0716003e-10, -1.0771373e-10, 6.454408900000001e-11, 7.9297993e-11, -6.596152699999999e-11, -6.131494e-11, 2.3139144e-11, + 1.8220157e-11, -6.889387e-12, -5.2758971e-12, 4.7202158e-12, -2.698161e-12, 1.706513e-12, 1.3150514e-12, -8.5395143e-13, + 0.0, 0.0, 0.0, 0.0, }, + { 0.000050159503, -0.00071212184, 0.00028363207, 0.0014615066, -0.0013267837, -0.0016433511, 0.0023330548, 0.0013382911, + -0.0071554962, -0.0033071427, 0.012526538, 0.0083335545, -0.0055376737, 0.0031805864, 0.0027555735, -0.025588465, + -0.041414908, 0.0040466304, 0.057487914, 0.049499743, 0.016086099, 0.0036837639, -0.0399912, -0.12588418, + -0.10654688, 0.070278005, 0.20774306, 0.13266193, -0.033279293, -0.1270871, -0.17862262, -0.18011286, + 0.031983838, 0.35889559, 0.33866366, -0.13976788, -0.47106632, -0.18110697, 0.29494939, 0.27613212, + -0.10895856, -0.21798754, 0.04432405, 0.1866715, 0.008365786, -0.15161747, -0.063799301, 0.07139735799999999, + 0.05969678, -0.014185963, -0.017375356, 0.015990858, 0.0058387245, -0.015281726, -0.010330507, 0.0027153486, + -7.4751925e-10, 1.1363937e-9, 8.6711229e-10, -3.7268833e-10, -3.6811377e-10, 2.0482729e-10, 2.0980924e-10, -7.258209800000001e-11, + -2.7266282e-11, -1.5979419e-11, -9.5719216e-13, 3.8460406e-12, 8.9396574e-12, -9.508538499999999e-12, -9.0540185e-12, 2.7940998e-12, + 3.7212707e-12, -1.5943743e-12, -1.2232114e-12, 1.0063401e-12, -4.4202812e-13, 2.7957097e-13, 2.154394e-13, -1.3989921e-13, + 0.0, 0.0, 0.0, 0.0, }, + { 0.00011533996, -0.000026734332, -0.00013506823, 0.00037552805, 0.000056473736, -0.00069611, 0.00030822484, 0.0014903898, + -0.001299667, -0.001623524, 0.0023429619, 0.0013395122, -0.0071588879, -0.0033105472, 0.012526018, 0.008336244899999999, + -0.0055337618, 0.0031829767, 0.0027548042, -0.025592198, -0.041419704, 0.0040431007, 0.057487257, 0.049501718, + 0.016089174, 0.0036863006, -0.039990188, -0.12588473, -0.10654831, 0.070276592, 0.2077423, 0.13266197, + -0.033278735, -0.12708649, -0.17862233, -0.18011298, 0.031983453, 0.35889516, 0.33866339, -0.13976791, + -0.47106621, -0.18110686, 0.29494942, 0.27613211, -0.10895856, -0.21798752, 0.044324057, 0.1866715, + 0.008365790600000001, -0.15161745, -0.063799281, 0.07139736200000001, 0.059696773, -0.014185967, -0.017375353, 0.015990861, + 0.0058387231, -0.01528173, -0.010330508, 0.0027153498, 1.2421473e-10, -1.6472405e-11, -4.5499511e-11, 4.6952921e-12, + -7.622754700000001e-12, 2.2440782e-11, 1.4394938e-11, -7.4419077e-12, -7.478396099999999e-12, 5.4641676e-12, 5.0064067e-12, -2.1114128e-12, + -1.1146915e-12, 3.5181885e-13, 2.6859057e-13, -2.7304861e-13, 2.0563143e-13, -1.3005576e-13, -1.0022199e-13, 6.5081053e-14, + 0.0, 0.0, 0.0, 0.0, }, + { 0.000048301379, 0.000081244009, -0.00010202271, -0.0000527072, 0.00012665087, -0.000023161991, -0.00014073862, 0.00036301218, + 0.000042236451, -0.00070675058, 0.00030414781, 0.0014924293, -0.0012947379, -0.0016196213, 0.002343374, 0.0013363966, + -0.0071634301, -0.0033138343, 0.01252572, 0.0083387958, -0.0055300282, 0.0031859358, 0.0027557003, -0.02559331, + -0.041421766, 0.0040413078, 0.057486526, 0.049502138, 0.016090249, 0.0036873704, -0.039989605, -0.12588475, + -0.1065487, 0.070276145, 0.20774205, 0.13266197, -0.033278579, -0.12708632, -0.17862224, -0.180113, + 0.031983382, 0.35889508, 0.33866334, -0.13976793, -0.4710662, -0.18110685, 0.29494942, 0.27613211, + -0.10895856, -0.21798752, 0.044324053, 0.18667149, 0.0083657926, -0.15161745, -0.06379928, 0.07139736000000001, + 0.059696773, -0.014185965, -0.017375352, 0.01599086, 0.0058387226, -0.015281729, -0.010330508, 0.0027153497, + 8.4895945e-13, 8.9873902e-12, 4.4939672e-12, -2.8829398e-12, -3.2827318e-12, 2.8288238e-12, 2.6521985e-12, -9.600575e-13, + -8.4408406e-13, 3.2522644e-13, 2.4913156e-13, -2.2004175e-13, 1.2146722e-13, -7.6823174e-14, -5.920069e-14, 3.8443518e-14, + 0.0, 0.0, 0.0, 0.0, }, + { 0.00001049566, 0.000014942095, -0.00001798232, -0.000063966374, 0.000050491712, 0.000079338435, -0.00010824893, -0.000061723045, + 0.00011751212, -0.000029813667, -0.00014355097, 0.00036364052, 0.000044544686, -0.00070482097, 0.00030440767, 0.0014909545, + -0.0012969238, -0.0016211718, 0.0023433177, 0.0013377839, -0.0071614371, -0.0033122572, 0.012526182, 0.008338179500000001, + -0.0055311464, 0.0031849683, 0.0027553009, -0.0255931, -0.041421213, 0.0040418568, 0.057486821, 0.049502123, + 0.01609004, 0.0036871372, -0.03998973, -0.12588473, -0.1065486, 0.070276251, 0.2077421, 0.13266198, + -0.033278611, -0.12708636, -0.17862227, -0.180113, 0.031983384, 0.35889509, 0.33866334, -0.13976793, + -0.4710662, -0.18110685, 0.29494942, 0.27613211, -0.10895856, -0.21798752, 0.044324053, 0.18667149, + 0.0083657929, -0.15161745, -0.06379928, 0.07139736000000001, 0.059696773, -0.014185965, -0.017375352, 0.01599086, + 0.0058387225, -0.015281729, -0.010330508, 0.0027153497, -2.141137e-13, 1.8621291e-13, 1.7348502e-13, -6.3446602e-14, + -5.5329986e-14, 2.1752068e-14, 1.6668418e-14, -1.452183e-14, 7.7079643e-15, -4.8735409e-15, -3.7557779e-15, 2.4394086e-15, + 0.0, 0.0, 0.0, 0.0, }, + { -0.0000016862516, 0.0000019060019, -4.248487e-7, -0.0000047292013, 0.000010654859, 0.000014866629, -0.000018311699, -0.000064466384, + 0.000049972355, 0.000078950867, -0.00010842286, -0.0000617001, 0.0001176368, -0.000029701701, -0.00014352575, 0.00036357185, + 0.000044435351, -0.00070489915, 0.00030440706, 0.0014910288, -0.0012968196, -0.0016210916, 0.0023433373, 0.0013377465, + -0.0071614998, -0.0033123101, 0.012526161, 0.0083381915, -0.0055311158, 0.0031849984, 0.0027553172, -0.025593101, + -0.041421224, 0.0040418445, 0.057486815, 0.049502125, 0.016090047, 0.003687144, -0.039989727, -0.12588473, + -0.1065486, 0.070276249, 0.2077421, 0.13266197, -0.033278611, -0.12708636, -0.17862227, -0.180113, + 0.031983384, 0.35889509, 0.33866334, -0.13976793, -0.4710662, -0.18110685, 0.29494942, 0.27613211, + -0.10895856, -0.21798752, 0.044324054, 0.18667149, 0.0083657929, -0.15161745, -0.06379928, 0.07139736000000001, + 0.059696773, -0.014185965, -0.017375352, 0.01599086, 0.0058387225, -0.015281729, -0.010330508, 0.0027153497, + -9.093892299999999e-16, 1.5923447e-15, 1.2350047e-15, -5.1775324e-16, -5.9423787e-16, 3.7692653e-16, 2.903267e-16, -1.8815403e-16, + 0.0, 0.0, 0.0, 0.0, }, + { 8.5507366e-8, -0.0000012851265, 7.857136300000001e-7, -3.4801813e-7, -0.0000018684855, 0.0000017467446, -5.336318e-7, -0.0000047832847, + 0.000010639476, 0.00001486632, -0.000018315371, -0.000064480605, 0.000049952572, 0.000078935834, -0.0001084256, -0.000061690695, + 0.00011765129, -0.000029690251, -0.00014352319, 0.00036356698, 0.000044428438, -0.00070490357, 0.00030440683, 0.0014910323, + -0.0012968146, -0.0016210877, 0.0023433385, 0.0013377449, -0.0071615031, -0.0033123133, 0.012526159, 0.008338191300000001, + -0.0055311149, 0.0031849995, 0.0027553178, -0.025593101, -0.041421224, 0.0040418441, 0.057486815, 0.049502125, + 0.016090047, 0.0036871443, -0.039989726, -0.12588473, -0.1065486, 0.070276249, 0.2077421, 0.13266197, + -0.033278611, -0.12708636, -0.17862227, -0.180113, 0.031983384, 0.35889509, 0.33866334, -0.13976793, + -0.4710662, -0.18110685, 0.29494942, 0.27613211, -0.10895856, -0.21798752, 0.044324054, 0.18667149, + 0.0083657929, -0.15161745, -0.06379928, 0.07139736000000001, 0.059696773, -0.014185965, -0.017375352, 0.01599086, + 0.0058387225, -0.015281729, -0.010330508, 0.0027153497, -2.284982e-15, 1.4420459e-15, 1.1116432e-15, -7.2294759e-16, + 0.0, 0.0, 0.0, 0.0, }, + { -2.565031e-7, -1.0384266e-7, 3.7843906e-7, 0.0000012258276, 6.8475377e-8, -0.0000012217701, 9.2978511e-7, -1.5535891e-7, + -0.0000016795333, 0.0000018820924, -4.7671008e-7, -0.0000047953669, 0.000010593913, 0.000014828085, -0.000018320832, -0.000064451905, + 0.000049995467, 0.000078966429, -0.0001084242, -0.000061717862, 0.00011761178, -0.000029721923, -0.00014353291, 0.00036357866, + 0.000044450187, -0.00070488461, 0.00030441474, 0.0014910283, -0.0012968253, -0.0016210983, 0.0023433329, 0.0013377452, + -0.007161499, -0.0033123087, 0.012526161, 0.0083381911, -0.0055311167, 0.0031849975, 0.0027553167, -0.025593101, + -0.041421223, 0.0040418448, 0.057486815, 0.049502125, 0.016090047, 0.0036871442, -0.039989726, -0.12588473, + -0.1065486, 0.070276249, 0.2077421, 0.13266197, -0.033278611, -0.12708636, -0.17862227, -0.180113, + 0.031983384, 0.35889509, 0.33866334, -0.13976793, -0.4710662, -0.18110685, 0.29494942, 0.27613211, + -0.10895856, -0.21798752, 0.044324054, 0.18667149, 0.0083657929, -0.15161745, -0.06379928, 0.07139736000000001, + 0.059696773, -0.014185965, -0.017375352, 0.01599086, 0.0058387225, -0.015281729, -0.010330508, 0.0027153497, + 0.0, 0.0, 0.0, 0.0, }, + { 0.0, 0.0, 0.0, 0.0, 2.8347963e-8, 2.2523303e-8, -4.8735247e-8, -1.1960916e-7, + -2.5287662e-7, -1.0870486e-7, 3.6471382e-7, 0.0000012064933, 4.9010332e-8, -0.0000012357305, 9.2436549e-7, -1.5276658e-7, + -0.000001674434, 0.0000018850808, -4.7547238e-7, -0.0000047991778, 0.000010587354, 0.000014826825, -0.00001832123, -0.00006445143200000001, + 0.000050010787, 0.000078981352, -0.00010843969, -0.000061781033, 0.00011764661, -0.000029652232, -0.00014362553, 0.00036355273, + 0.000044555001, -0.00070494037, 0.00030431608, 0.0014913269, -0.0012968481, -0.0016216969, 0.0023436473, 0.0013391667, + -0.0071627289, -0.0033138138, 0.012528415, 0.008339137700000001, -0.0055374361, 0.0031823423, 0.0027663458, -0.025586039, + -0.041424124, 0.0040475437, 0.057484017, 0.049470067, 0.016054175, 0.0036921246, -0.039935715, -0.12582517, + -0.1064918, 0.07029540300000001, 0.20762795, 0.13246998, -0.033414365, -0.12705281, -0.17833346, -0.1797243, + 0.032220064, 0.3587368, 0.33807475, -0.1405286, -0.47145321, -0.18066022, 0.2961133, 0.27732297, + -0.10855845, -0.2187329, 0.042752897, 0.18508766, 0.0077641669, -0.15053787, -0.06122282, 0.074228853, + 0.06099463, -0.015859301, -0.02241404, 0.008369957900000001, }, + { 0.0, 0.0, 0.0, 0.0, 3.1104865e-11, 2.4713744e-11, -5.3474856e-11, -1.3124141e-10, + 2.8076073e-8, 2.240846e-8, -4.8344655e-8, -1.1830887e-7, -2.5288366e-7, -1.1009094e-7, 3.6581885e-7, 0.0000012066097, + 4.7227712e-8, -0.0000012339054, 9.2397559e-7, -1.5830681e-7, -0.0000016623097, 0.000001902708, -4.9736841e-7, -0.0000048746571, + 0.000010641936, 0.000014916903, -0.00001844127, -0.000064515498, 0.000050156285, 0.00007894542200000001, -0.00010861116, -0.000061388997, + 0.0001176581, -0.000030448803, -0.00014326261, 0.00036539096, 0.000043163251, -0.00070690185, 0.00030701988, 0.0014924274, + -0.001304832, -0.0016246302, 0.002357033, 0.0013474944, -0.0071698505, -0.0033108691, 0.012533524, 0.0083162698, + -0.0055818492, 0.003181139, 0.0028309669, -0.025523938, -0.041427794, 0.0040395529, 0.057468792, 0.049353567, + 0.015859766, 0.0037180721, -0.039555569, -0.12557329, -0.10652434, 0.070261595, 0.20734565, 0.1317388, + -0.03404103, -0.12662826, -0.1770882, -0.17860175, 0.032710046, 0.35856033, 0.33678034, -0.14316156, + -0.473647, -0.17975323, 0.30028384, 0.28157025, -0.10762441, -0.22181434, 0.037393303, 0.18007816, + 0.006253649, -0.14515602, -0.046992144, 0.09621433, }, + { 0.0, 0.0, 0.0, 0.0, 4.9302209e-11, 3.9172078e-11, -8.4759363e-11, -2.0802185e-10, + -8.0623665e-11, 9.6317379e-11, 1.6817782e-11, 5.8283731e-10, 2.5759293e-8, 1.9418005e-8, -4.3417929e-8, -1.0682495e-7, + -2.5975641e-7, -1.2300478e-7, 3.8217799e-7, 0.000001218181, 4.4579459e-8, -0.0000012107338, 9.0779212e-7, -3.1709409e-7, + -0.0000014767929, 0.0000022412612, -9.1037095e-7, -0.0000058521315, 0.000011594129, 0.00001609105, -0.000020289796, -0.000065763475, + 0.000052689099, 0.00007888203399999999, -0.00011191315, -0.000056305446, 0.00011794491, -0.000041636402, -0.00013852035, 0.00039353835, + 0.000016087667, -0.00074771176, 0.00036439677, 0.0015550243, -0.001424237, -0.0016912016, 0.0025549356, 0.0014235625, + -0.0074529838, -0.0033190717, 0.012908787, 0.0082218319, -0.0061297864, 0.0033308454, 0.003480986, -0.025683031, + -0.041995976, 0.0044737841, 0.057981001, 0.048634771, 0.014743331, 0.0040970547, -0.037749205, -0.12495603, + -0.10679701, 0.070623223, 0.20681414, 0.12717576, -0.038987624, -0.12484364, -0.16903315, -0.17130917, + 0.036125929, 0.35914755, 0.33062642, -0.16026408, -0.49087723, -0.17615148, 0.32895563, 0.31348535, + -0.097420887, -0.24067157, -0.0068642378, 0.11219697, }, + { 0.0, 0.0, 0.0, 0.0, 1.6669958e-11, 1.3244779e-11, -2.8658655e-11, -7.0335904e-11, + 2.2814041e-10, 2.3549011e-10, -4.3339335e-10, -8.805498899999999e-10, -1.2935862e-9, -5.515234299999999e-10, 1.8861269e-9, 7.3446094e-9, + 1.2543352e-8, 1.545426e-9, -1.5165886e-8, -4.9146175e-8, -2.9234586e-7, -1.7639541e-7, 4.5374829e-7, 0.0000012209487, + 1.2278171e-7, -9.685260999999999e-7, 6.4489216e-7, -0.0000015008025, -3.9354283e-7, 0.0000042281365, -0.0000033565057, -0.000010303686, + 0.000017012562, 0.000020906574, -0.00002961357, -0.000069633977, 0.000062129587, 0.000073870575, -0.00012292418, -0.00001682869, + 0.00010857498, -0.00011195588, -0.00009026875400000001, 0.00053011919, -0.00014608608, -0.00092560829, 0.00067049494, 0.0018019183, + -0.0020404998, -0.0019316755, 0.0035226148, 0.0016869094, -0.008693585, -0.0032849721, 0.014554009, 0.0078151739, + -0.0084537802, 0.0041605347, 0.0058665682, -0.026774198, -0.045914986, 0.0049123195, 0.063776951, 0.050441966, + 0.013630997, 0.0075108398, -0.037034514, -0.1403178, -0.12671833, 0.072889677, 0.2323412, 0.15268124, + -0.024786402, -0.12259352, -0.19576372, -0.23414639, -0.010289108, 0.39690249, 0.43370648, -0.089458844, + -0.50864478, -0.25076346, 0.23238368, 0.17867278, }, + { -0.10336098, 0.43698355, -0.05205054, -0.38094273, 0.25644551, 0.2346896, -0.37978468, 0.12285758, + 0.11406574, -0.19346287, 0.25076721, -0.1000306, -0.21361052, 0.30863792, -0.1077896, -0.13642263, + 0.19131498, -0.10816236, 0.011856046, 0.073645325, -0.10939103, 0.064372891, 0.015456895, -0.058566397, + 0.042702958, -0.009002869700000001, -0.0076727162, 0.0096952662, -0.01108636, 0.0070343222, 0.0054298699, -0.0035153294, + -2.8212126e-17, 2.9364612e-17, -2.8497598e-18, -6.5598367e-18, 2.2196917e-17, -1.5966312e-17, -6.8415466e-19, 1.0256422e-17, + -1.0903092e-17, 6.136113e-18, 1.5503946e-18, -3.4403994e-18, 4.7292107e-18, -3.142732e-18, -1.0747554e-18, 2.4408853e-18, + -1.2884504e-18, 7.997105e-20, 4.4808753e-19, -5.2762049e-19, 1.8594686e-19, 1.0847923e-19, -3.3301754e-19, 1.4273141e-19, + 2.0535414e-19, -1.8929296e-19, 1.2177378e-20, 7.566992799999999e-20, -1.7612349e-19, 5.9536839e-20, -1.1724752e-20, -8.3718063e-20, + 8.1945198e-20, 1.3593323e-21, -1.0939206e-21, 2.7296664e-20, -2.9975079e-20, -5.1646176e-22, 7.0238119e-21, -1.9083712e-21, + 1.5417738e-21, -4.847092e-22, -6.900116e-22, 7.7780343e-22, 1.6035611e-21, -1.1671024e-21, -8.809386700000001e-22, 5.1907549e-22, + 0.0, 0.0, 0.0, 0.0, }, + { -0.2381574, 0.24787821, 0.14738553, -0.31977596, -0.062372762, 0.32513857, -0.068171486, -0.31736026, + 0.24711974, 0.14518414, -0.30433735, 0.15030169, 0.051580316, -0.2025471, 0.24903716, -0.097704256, + -0.18039066, 0.29862922, -0.1263385, -0.11264106, 0.19168629, -0.12019892, 0.009955064200000001, 0.07220718399999999, + -0.10756871, 0.069730504, 0.014077653, -0.063847716, 0.046485607, -0.009319401499999999, -0.0075936564, 0.01014513, + -0.012827683, 0.008134040299999999, 0.0063368034, -0.0040889465, -0.0000063505191, 0.000006950383, -0.00001241348, 0.000007111846, + -0.0000064631173, 0.0000079486222, -0.0000051804315, 9.788376799999999e-7, -0.0000012868637, 0.0000029161477, -2.1119116e-7, -5.2479358e-7, + 1.2924158e-8, 4.5152466e-7, 5.6881144e-7, -1.4409161e-7, -1.6287584e-7, 6.6652555e-8, 1.7433987e-7, -6.663249100000001e-8, + 1.629114e-8, -4.3365806e-8, -8.7838571e-9, 1.3558251e-8, -8.1414893e-10, -6.6948214e-9, -7.456150700000001e-9, 8.8064106e-10, + 3.8271749e-9, -2.1546977e-9, -2.1125387e-9, 1.2521301e-9, -3.3478394e-10, 2.9664332e-10, 2.5333064e-10, -1.2786898e-10, + -8.9606122e-12, 6.8636006e-12, 6.0126818e-12, -3.2434772e-12, 1.7503469e-13, -1.4327545e-13, -1.2368103e-13, 6.4898593e-14, + 0.0, 0.0, 0.0, 0.0, }, + { -0.16594546, 0.021972375, 0.21257073, -0.13795719, -0.23325892, 0.22979788, 0.13646732, -0.28662031, + -0.036960515, 0.3065747, -0.073102404, -0.295528, 0.23381221, 0.12263712, -0.28890599, 0.15882495, + 0.047578576, -0.19677918, 0.24338164, -0.098716897, -0.17095421, 0.29074244, -0.13382557, -0.10865891, + 0.19302541, -0.11817653, 0.01048866, 0.06894270199999999, -0.10712826, 0.071793709, 0.01314768, -0.065370729, + 0.046759544, -0.0084408238, -0.0072321374, 0.010164083, -0.013519027, 0.008576618899999999, 0.0066295855, -0.0042906449, + -9.998778500000001e-7, 0.0000015478204, -0.0000017517036, 7.332273e-7, -0.0000010317518, 0.0000016602753, -9.682844000000001e-7, 2.5190377e-7, + -3.2823674e-7, 5.8315547e-7, 5.514423999999999e-10, -5.4213323e-8, -7.0818943e-8, 1.1415268e-7, 9.940506e-8, -5.6015297e-8, + 5.7225635e-10, 2.8129944e-9, 2.4769282e-8, -5.8898787e-9, -9.4554702e-11, -6.4790772e-9, 3.0551283e-9, 2.0083669e-9, + -1.638693e-9, -1.0561361e-9, -1.5904414e-9, -2.499696e-10, 1.3374645e-9, -7.3325746e-10, -6.863901e-10, 4.357945e-10, + -1.3965471e-10, 1.0984232e-10, 9.5653262e-11, -5.1031561e-11, 1.6616273e-12, -1.3601326e-12, -1.1741202e-12, 6.1609085e-13, + 0.0, 0.0, 0.0, 0.0, }, + { -0.069104323, -0.04237214, 0.10967353, 0.011282401, -0.17415051, 0.021403053, 0.21945724, -0.12028611, + -0.21523085, 0.23230499, 0.12991487, -0.28748783, -0.035689801, 0.30409908, -0.070474384, -0.28821646, + 0.23193231, 0.1174521, -0.28651538, 0.16020319, 0.046143787, -0.19745216, 0.24009639, -0.099156989, + -0.16726204, 0.29091257, -0.13494079, -0.10845704, 0.19287637, -0.11779632, 0.01034376, 0.06791125000000001, + -0.10701528, 0.07252636899999999, 0.013108627, -0.065758523, 0.046754171, -0.0082023024, -0.0071059064, 0.010140732, + -0.013675539, 0.008677084200000001, 0.0066982, -0.0043362722, -4.2928634e-7, 5.5762325e-7, -6.0251197e-7, 2.8545178e-7, + -2.4847952e-7, 3.2216043e-7, -1.1454465e-7, -9.7613984e-9, -1.4180537e-8, 6.336785500000001e-8, 3.1840419e-8, -2.378838e-8, + -4.0718732e-9, 1.1746141e-8, 1.8788076e-8, -7.626240800000001e-9, 9.9899638e-10, -3.5145479e-9, 3.664563e-9, 1.5251639e-9, + -2.2503938e-9, -1.5662936e-10, -5.6682878e-10, -5.3093496e-10, 1.0615418e-9, -6.1065908e-10, -5.6545207e-10, 3.5065135e-10, + -9.9709455e-11, 7.8470462e-11, 6.8324958e-11, -3.6442805e-11, 1.1691909e-12, -9.570465999999999e-13, -8.2616046e-13, 4.3350747e-13, + 0.0, 0.0, 0.0, 0.0, }, + { -0.015911608, -0.027299969, 0.033186044, 0.039995417, -0.07342411, -0.041121331, 0.1163226, 0.020910495, + -0.16563933, 0.024714618, 0.21754715, -0.12284876, -0.2152654, 0.23413165, 0.13237649, -0.28594259, + -0.036907369, 0.30169717, -0.07026452499999999, -0.2863606, 0.23127057, 0.11548435, -0.28671725, 0.1606467, + 0.04670782, -0.19688757, 0.23957645, -0.099297892, -0.16668393, 0.29063735, -0.13529883, -0.10844124, + 0.19282211, -0.11760804, 0.01034761, 0.06766707499999999, -0.10697097, 0.072675087, 0.013100453, -0.065832161, + 0.046742062, -0.0081473039, -0.0070743643, 0.010131315, -0.013705653, 0.0086962898, 0.0067125396, -0.0043457398, + -8.1627608e-8, 8.543780100000001e-8, -5.3712589e-8, 1.327336e-9, 1.9107335e-9, 1.6196752e-8, 3.2215588e-9, -4.4466373e-9, + -2.1746539e-9, 5.3420267e-9, 5.952181e-9, -3.0205576e-9, 6.0999665e-10, -9.590371300000001e-10, 1.368256e-9, 5.2928793e-10, + -9.1403627e-10, 6.763270499999999e-11, -6.7608191e-11, -2.3474385e-10, 3.5310168e-10, -2.0783083e-10, -1.9147887e-10, 1.1741923e-10, + -3.1338961e-11, 2.4671859e-11, 2.1480394e-11, -1.1455478e-11, 3.6436943e-13, -2.9825622e-13, -2.5746655e-13, 1.3509928e-13, + 0.0, 0.0, 0.0, 0.0, }, + { 0.00010953376, -0.0066695294, 0.002925938, 0.017851646, -0.016853728, -0.026665938, 0.035370231, 0.042794613, + -0.07111854500000001, -0.040033922, 0.11610379, 0.020099525, -0.16589307, 0.025495639, 0.21858618, -0.12263584, + -0.21596224, 0.23352451, 0.13258257, -0.28549906, -0.037093532, 0.30113508, -0.070353631, -0.28601051, + 0.23138871, 0.11537757, -0.28669649, 0.16070747, 0.046747369, -0.1969158, 0.2394417, -0.099292696, + -0.1665998, 0.29059798, -0.1353337, -0.10844426, 0.19281049, -0.1175694, 0.010342358, 0.067627653, + -0.1069576, 0.07269242200000001, 0.013100911, -0.065838073, 0.046735578, -0.008138709100000001, -0.0070683408, 0.010128424, + -0.013708364, 0.008697987799999999, 0.0067140604, -0.0043467264, 1.9622188e-9, 1.7406201e-10, -1.672447e-9, 5.4651109e-10, + -4.7595869e-10, 9.2437526e-10, 4.7383151e-10, -4.4720428e-10, 1.7140273e-10, -5.2404856e-11, 1.685328e-10, 6.967566999999999e-11, + -1.444021e-10, 4.4055443e-11, 3.0290447e-11, -4.1955458e-11, 3.608598e-11, -2.2614881e-11, -2.0559587e-11, 1.2228308e-11, + -2.6688281e-12, 2.1036316e-12, 1.8310149e-12, -9.7598049e-13, 3.0073196e-14, -2.4616691e-14, -2.1250116e-14, 1.1150436e-14, + 0.0, 0.0, 0.0, 0.0, }, + { 0.0012742472, 0.00027493115, -0.0016569906, 0.0029734957, 0.00020414488, -0.0064933966, 0.0031591306, 0.018059611, + -0.016689805, -0.026524664, 0.035438013, 0.042736753, -0.071193733, -0.039967886, 0.11625315, 0.02011879, + -0.16603009, 0.025409457, 0.21865285, -0.12256659, -0.21601375, 0.23345319, 0.13261377, -0.28543431, + -0.037106847, 0.30108709, -0.07034105, -0.28596614, 0.23138499, 0.11534424, -0.28669767, 0.16073009, + 0.046750734, -0.19693178, 0.23943261, -0.099283807, -0.16659433, 0.29059092, -0.13533815, -0.10844243, + 0.19281158, -0.11756903, 0.010340932, 0.067626614, -0.10695672, 0.07269291, 0.013100859, -0.065838181, + 0.046735249, -0.008138348300000001, -0.007068071, 0.010128278, -0.013708444, 0.0086980397, 0.006714112, -0.0043467551, + 7.6250582e-11, -2.4269293e-10, -4.4500305e-10, 1.6738798e-10, -1.7254536e-11, 8.666511200000001e-11, -8.2471298e-11, -3.5152726e-11, + 4.9015492e-11, 6.2600825e-12, 1.5877804e-11, 1.1149878e-11, -2.4816445e-11, 1.4173131e-11, 1.3144982e-11, -8.180377100000001e-12, + 2.3708542e-12, -1.8656596e-12, -1.6244826e-12, 8.664931e-13, -2.7867857e-14, 2.2811437e-14, 1.9691784e-14, -1.0332754e-14, + 0.0, 0.0, 0.0, 0.0, }, + { 0.00048543251, 0.00067050041, -0.0009308460499999999, -0.00083948251, 0.001402981, 0.00026296786, -0.0018168877, 0.0027381465, + 0.0000065882746, -0.0065710155, 0.0031962766, 0.018128669, -0.016675065, -0.026579325, 0.035371358, 0.0427177, + -0.071163305, -0.039936092, 0.11625122, 0.020099619, -0.16602767, 0.025440594, 0.21867805, -0.12257452, + -0.21603854, 0.2334434, 0.13262307, -0.28542753, -0.037114116, 0.30108227, -0.070331567, -0.28595691, + 0.23138119, 0.11533681, -0.28669552, 0.16073649, 0.046750369, -0.19693692, 0.23943193, -0.09928029300000001, + -0.16659375, 0.29058837, -0.13533921, -0.10844109, 0.1928121, -0.11756991, 0.010340415, 0.067626916, + -0.10695652, 0.072692795, 0.01310069, -0.065838151, 0.046735307, -0.0081383532, -0.0070680841, 0.010128292, + -0.013708463, 0.0086980527, 0.0067141216, -0.0043467614, -2.102711e-11, 3.3417224e-11, -3.8409085e-11, -1.7490935e-11, + 2.7166852e-11, -1.5216838e-12, 2.6753955e-12, 6.9083671e-12, -1.0809558e-11, 6.3270183e-12, 5.836294e-12, -3.5887054e-12, + 9.731098600000001e-13, -7.6601753e-13, -6.6694169e-13, 3.5569341e-13, -1.1340318e-14, 9.282481500000001e-15, 8.012984599999999e-15, -4.2046742e-15, + 0.0, 0.0, 0.0, 0.0, }, + { 0.00008874163200000001, 0.00017255261, -0.00020334688, -0.00048589084, 0.0005194140799999999, 0.00065162184, -0.0010030955, -0.00093500466, + 0.0013229135, 0.00022422489, -0.0018110625, 0.002766036, 0.000019216306, -0.0065926605, 0.0031624642, 0.018119477, + -0.016655318, -0.026561899, 0.035366048, 0.042705799, -0.07115904100000001, -0.039919962, 0.11625833, 0.020092471, + -0.16603572, 0.025440328, 0.21868056, -0.12257518, -0.2160409, 0.23344412, 0.13262646, -0.28542614, + -0.0371155, 0.301081, -0.070330532, -0.28595529, 0.23138086, 0.11533536, -0.28669534, 0.16073756, + 0.046750343, -0.19693765, 0.23943165, -0.099279878, -0.16659353, 0.29058801, -0.1353394, -0.10844095, + 0.19281216, -0.11756996, 0.010340352, 0.067626914, -0.10695649, 0.072692796, 0.013100678, -0.06583815, + 0.046735303, -0.0081383464, -0.0070680792, 0.01012829, -0.013708465, 0.0086980544, 0.006714123, -0.0043467623, + 4.1692516e-12, -7.121456e-13, -1.7304044e-13, 1.1302171e-12, -1.37798e-12, 8.2446267e-13, 7.569006e-13, -4.6045708e-13, + 1.1710488e-13, -9.2217873e-14, -8.028399700000001e-14, 4.2809906e-14, -1.3535472e-15, 1.1074076e-15, 9.559748499999999e-16, -5.0178012e-16, + 0.0, 0.0, 0.0, 0.0, }, + { 4.9186471e-7, 0.0000051461586, -0.0000052735889, -0.000074617715, 0.000090338235, 0.00016829914, -0.00021319587, -0.00049763725, + 0.00050951791, 0.00064579957, -0.0010036791, -0.0009315934, 0.0013254699, 0.00022183375, -0.0018160248, 0.0027645817, + 0.000022431098, -0.0065899474, 0.0031613131, 0.01811749, -0.016654443, -0.026559467, 0.035366631, 0.042704497, + -0.07115983400000001, -0.039919625, 0.11625849, 0.020092045, -0.16603593, 0.025440686, 0.21868092, -0.12257525, + -0.21604106, 0.23344415, 0.13262661, -0.28542607, -0.037115559, 0.30108091, -0.07033048, -0.28595519, + 0.23138084, 0.1153353, -0.28669535, 0.16073761, 0.046750358, -0.19693768, 0.23943163, -0.099279862, + -0.16659352, 0.290588, -0.13533941, -0.10844094, 0.19281216, -0.11756996, 0.010340351, 0.067626913, + -0.10695649, 0.072692796, 0.013100678, -0.06583815, 0.046735303, -0.008138345999999999, -0.0070680789, 0.010128289, + -0.013708465, 0.0086980544, 0.006714123, -0.0043467623, 2.3376946e-13, -1.3432021e-13, -1.2440416e-13, 7.7199335e-14, + -2.2028344e-14, 1.7343448e-14, 1.5100496e-14, -8.051784e-15, 2.6023509e-16, -2.1274301e-16, -1.8354782e-16, 9.640321599999999e-17, + 0.0, 0.0, 0.0, 0.0, }, + { -0.0000040937358, -0.0000055585317, 0.0000076082811, 0.0000085197263, -6.5244263e-7, 0.0000052950016, -0.0000037713108, -0.00007243937499999999, + 0.000092169031, 0.00016904946, -0.00021350235, -0.00049827953, 0.00050935188, 0.00064630511, -0.0010030326, -0.00093141393, + 0.0013251546, 0.00022152265, -0.0018159844, 0.0027647772, 0.000022393482, -0.0065902524, 0.0031610922, 0.018117583, + -0.016654221, -0.026559397, 0.035366549, 0.042704454, -0.071159768, -0.039919598, 0.11625841, 0.020091976, + -0.1660359, 0.025440742, 0.2186809, -0.1225753, -0.21604106, 0.23344419, 0.13262662, -0.2854261, + -0.037115562, 0.30108093, -0.07033047100000001, -0.2859552, 0.23138084, 0.1153353, -0.28669535, 0.1607376, + 0.046750357, -0.19693768, 0.23943163, -0.099279862, -0.16659352, 0.290588, -0.13533941, -0.10844094, + 0.19281216, -0.11756996, 0.010340351, 0.067626913, -0.10695649, 0.072692796, 0.013100678, -0.06583815, + 0.046735303, -0.008138345999999999, -0.0070680789, 0.010128289, -0.013708465, 0.0086980544, 0.006714123, -0.0043467623, + -8.131355e-15, 6.378939e-15, 5.55643e-15, -2.9687905e-15, 9.4777622e-17, -7.491754e-17, -6.5217812e-17, 3.4928497e-17, + 0.0, 0.0, 0.0, 0.0, }, + { -7.6914904e-7, -0.0000013872766, 0.0000018717906, 0.0000039601571, -0.0000043842735, -0.0000054015677, 0.000008218305099999999, 0.000009330314099999999, + 3.0916655e-8, 0.0000056292333, -0.0000038169114, -0.000072676369, 0.000092055843, 0.00016922368, -0.00021322119, -0.0004981985, + 0.00050919173, 0.00064616029, -0.00100299, -0.0009313142, 0.0013251208, 0.00022138627, -0.0018160486, 0.0027648352, + 0.000022464236, -0.0065902472, 0.0031610699, 0.018117587, -0.0166542, -0.026559402, 0.03536652, 0.042704441, + -0.071159757, -0.039919587, 0.1162584, 0.020091963, -0.1660359, 0.025440754, 0.2186809, -0.12257531, + -0.21604106, 0.2334442, 0.13262662, -0.2854261, -0.037115563, 0.30108093, -0.07033046900000001, -0.28595521, + 0.23138083, 0.1153353, -0.28669535, 0.1607376, 0.046750356, -0.19693768, 0.23943163, -0.099279862, + -0.16659352, 0.290588, -0.13533941, -0.10844094, 0.19281216, -0.11756996, 0.010340351, 0.067626913, + -0.10695649, 0.072692796, 0.013100678, -0.06583815, 0.046735303, -0.008138345999999999, -0.0070680789, 0.010128289, + -0.013708465, 0.0086980544, 0.006714123, -0.0043467623, 9.764870899999999e-18, -1.4718019e-17, -1.1346244e-17, 4.1658833e-18, + 0.0, 0.0, 0.0, 0.0, }, + { -1.0208573e-7, 1.3018186e-8, 1.194814e-7, 5.5588767e-7, -7.7832783e-7, -0.000001347968, 0.0000019573526, 0.0000040619503, + -0.0000042970883, -0.0000053486099, 0.000008225291299999999, 0.000009300481599999999, 5.6623086e-9, 0.0000056459329, -0.0000037749505, -0.000072660374, + 0.000092031895, 0.00016920012, -0.00021321372, -0.00049818143, 0.00050918639, 0.0006461392299999999, -0.0010029982, -0.00093130473, + 0.0013251297, 0.00022138567, -0.0018160509, 0.002764837, 0.000022466322, -0.0065902489, 0.0031610667, 0.018117586, + -0.016654199, -0.026559401, 0.035366519, 0.04270444, -0.071159756, -0.039919586, 0.1162584, 0.020091962, + -0.1660359, 0.025440755, 0.2186809, -0.12257531, -0.21604106, 0.2334442, 0.13262662, -0.2854261, + -0.037115563, 0.30108093, -0.07033046900000001, -0.28595521, 0.23138083, 0.1153353, -0.28669535, 0.1607376, + 0.046750356, -0.19693768, 0.23943163, -0.099279862, -0.16659352, 0.290588, -0.13533941, -0.10844094, + 0.19281216, -0.11756996, 0.010340351, 0.067626913, -0.10695649, 0.072692796, 0.013100678, -0.06583815, + 0.046735303, -0.008138345999999999, -0.0070680789, 0.010128289, -0.013708465, 0.0086980544, 0.006714123, -0.0043467623, + 0.0, 0.0, 0.0, 0.0, }, + { 0.0, 0.0, 0.0, 0.0, 2.5759653e-8, 2.0466814e-8, -4.4285476e-8, -1.0868825e-7, + -9.6447646e-8, 7.1631101e-9, 1.0217806e-7, 5.3372984e-7, -7.9697132e-7, -0.0000013577621, 0.0000019572844, 0.0000040680546, + -0.0000042928595, -0.0000053527451, 0.000008217056199999999, 0.0000092987249, 8.7710696e-9, 0.0000056470119, -0.0000037725847, -0.00007265115, + 0.000092025111, 0.00016919001, -0.00021319519, -0.0004981714, 0.00050916083, 0.00064614419, -0.0010029715, -0.00093137957, + 0.0013251136, 0.00022150757, -0.001816076, 0.0027646198, 0.000022551485, -0.0065901118, 0.0031609105, 0.018118037, + -0.01665361, -0.026559824, 0.03536572, 0.042704521, -0.071159823, -0.039919898, 0.11625875, 0.020089684, + -0.16603036, 0.025448944, 0.21867067, -0.12260165, -0.21601898, 0.23347556, 0.13258048, -0.28544691, + -0.037013621, 0.30109905, -0.07049103, -0.28599544, 0.23154326, 0.11529805, -0.28686781, 0.16093501, + 0.047036544, -0.19708734, 0.2391103, -0.099324941, -0.16644021, 0.29049677, -0.13552768, -0.10796588, + 0.193457, -0.11803531, 0.0092231821, 0.0674976, -0.10592521, 0.07331246399999999, 0.012536859, -0.066336276, + 0.047126045, -0.0081144835, -0.0086391006, 0.0076846839, }, + { 0.0, 0.0, 0.0, 0.0, -2.310967e-13, -1.8361323e-13, 3.9729678e-13, 9.750711799999999e-13, + 2.5735935e-8, 2.0447217e-8, -4.424413e-8, -1.0858931e-7, -9.6323217e-8, 7.1885059e-9, 1.020196e-7, 5.3307751e-7, + -7.9586216e-7, -0.0000013560898, 0.0000019547474, 0.0000040629048, -0.0000042915417, -0.0000053492893, 0.000008213601799999999, 0.0000093049104, + -1.7246536e-8, 0.0000056052413, -0.000003712541, -0.00007247102700000001, 0.0000919272, 0.00016897358, -0.00021294943, -0.0004979377, + 0.00050890982, 0.00064625727, -0.0010028059, -0.00093287896, 0.0013259411, 0.00022450974, -0.0018185077, 0.0027565327, + 0.000028529945, -0.0065815284, 0.0031491404, 0.018115062, -0.016634876, -0.026565874, 0.035342312, 0.042743219, + -0.07115894, -0.03999209, 0.11628727, 0.020224178, -0.16612642, 0.025312132, 0.21889516, -0.12262658, + -0.21642083, 0.23358692, 0.1330733, -0.28544717, -0.037080723, 0.30159241, -0.070810965, -0.28752889, + 0.23108101, 0.11569811, -0.28635917, 0.16342308, 0.049077681, -0.19783438, 0.23674534, -0.10382321, + -0.16979763, 0.29279912, -0.12921646, -0.10115504, 0.19504154, -0.1252006, -0.00050619406, 0.062627694, + -0.1038641, 0.081254391, 0.025697232, -0.045830207, }, + { 0.0, 0.0, 0.0, 0.0, 7.9593377e-13, 6.3239315e-13, -1.3683533e-12, -3.3583002e-12, + -6.753506499999999e-11, -5.1069531e-11, 1.1413876e-10, 2.8886963e-10, 2.6130704e-8, 2.0529246e-8, -4.474577e-8, -1.1054977e-7, + -9.6160198e-8, 9.648097099999999e-9, 9.9857966e-8, 5.312347799999999e-7, -7.8437136e-7, -0.000001350296, 0.0000019393909, 0.0000040340277, + -0.0000042756633, -0.0000053244108, 0.0000081703425, 0.0000093387318, -1.5955554e-7, 0.0000053730519, -0.0000033880106, -0.000071543951, + 0.00009094828600000001, 0.00016742405, -0.00021075319, -0.0004944841499999999, 0.00050572369, 0.00064373234, -0.00099767183, -0.00093517257, + 0.0013226017, 0.00023579616, -0.0018202749, 0.0027128501, 0.00005199085, -0.0065177271, 0.0030889539, 0.018017381, + -0.016482816, -0.026474392, 0.035105113, 0.042707457, -0.070871596, -0.040071693, 0.11582208, 0.020809495, + -0.16571684, 0.024391395, 0.21913828, -0.1225116, -0.2170174, 0.23390508, 0.13334994, -0.28507333, + -0.037333319, 0.30268512, -0.071040561, -0.29189115, 0.23459309, 0.11814362, -0.29366771, 0.168199, + 0.055144579, -0.20517408, 0.23406798, -0.10369417, -0.16592475, 0.30024422, -0.13665322, -0.10712787, + 0.20336628, -0.12304478, -0.012787691, 0.034758271, }, + { 0.0, 0.0, 0.0, 0.0, -1.2748221e-12, -1.0128842e-12, 2.1916484e-12, 5.3788837e-12, + 1.0921985e-10, 8.2631556e-11, -1.8461942e-10, -4.6710814e-10, -1.2157947e-9, -5.9037309e-10, 1.8031028e-9, 5.6089956e-9, + 2.8816076e-8, 1.7242481e-8, -4.5066022e-8, -1.2254137e-7, -1.0212736e-7, 2.8041794e-8, 8.8809173e-8, 5.15863e-7, + -7.6703574e-7, -0.0000013448302, 0.0000019407723, 0.0000040046758, -0.0000041631243, -0.0000052761599, 0.000007990014, 0.0000094025477, + -3.7236461e-7, 0.0000050912212, -0.0000031816081, -0.000070497896, 0.00009005617, 0.00016543404, -0.00020781314, -0.00049140692, + 0.00050388753, 0.00064366586, -0.0009956896499999999, -0.00094188997, 0.0013264845, 0.00025337108, -0.0018357686, 0.0026434454, + 0.00010431219, -0.0064094357, 0.0029459426, 0.017888665, -0.016208348, -0.026453452, 0.034900135, 0.042639749, + -0.070925263, -0.04027267, 0.11533201, 0.023882331, -0.16561734, 0.020518705, 0.22247747, -0.12340487, + -0.2241639, 0.23400827, 0.14119997, -0.2774529, -0.045453944, 0.30578931, -0.060811587, -0.32120566, + 0.22629458, 0.14143909, -0.2932926, 0.18901876, 0.059268121, -0.24117229, 0.23667102, -0.10932962, + -0.18469158, 0.33038169, -0.098611492, -0.050527617, }, + { 0.0, 0.0, 0.0, 0.0, -1.1957895e-23, -9.4222313e-24, 2.0608172e-23, 5.0220109e-23, + 1.0491953e-22, 4.314021e-23, -1.5016783e-22, -4.9824641e-22, 1.442234e-22, 6.4439341e-22, -6.6049116e-22, -6.2852714e-22, + 7.7306433e-22, -1.7153432e-22, -3.6703031e-22, 2.3998726e-21, 2.3787518e-8, 1.8899893e-8, -4.089502e-8, -1.0036718e-7, + -9.1381028e-8, 4.773524e-9, 9.8339297e-8, 5.0264551e-7, -6.6787209e-7, -0.0000012072564, 0.0000016961125, 0.0000034579349, + -0.0000043011076, -0.0000049521991, 0.0000079675964, 0.000010237278, -6.1866699e-7, 0.0000026148365, -6.6753709e-7, -0.000062941151, + 0.00008091389800000001, 0.00015367342, -0.00019217485, -0.00046113989, 0.00047238288, 0.00061502943, -0.00093819179, -0.00095701101, + 0.0013112531, 0.00036070637, -0.0018631093, 0.0022451801, 0.00035463833, -0.0057958687, 0.0023086156, 0.016757115, + -0.014807134, -0.025281505, 0.032288107, 0.042350832, -0.06623280400000001, -0.040838204, 0.10990365, 0.024012049, + -0.16246351, 0.01632983, 0.21889693, -0.10804326, -0.21710906, 0.22495868, 0.13671564, -0.29314566, + -0.049448497, 0.30568883, -0.036034483, -0.32110046, 0.24258397, 0.18749043, -0.41990029, 0.17429974, + 0.14715901, -0.27307926, 0.27262049, -0.13077844, }, + { 0.0, 0.0, 0.0, 0.0, -1.1573241e-23, -9.2381678e-24, 1.9865137e-23, 4.8930224e-23, + 1.1706339e-22, 5.6286956e-23, -1.7324546e-22, -5.5311775e-22, -1.6848279e-22, 4.316996e-22, -1.5922221e-22, 7.5685334e-22, + 3.4316913e-22, -1.7509105e-21, 1.3472139e-21, 3.3351924e-21, -4.5929126e-10, -3.6492062e-10, 7.8960427e-10, 1.9378973e-9, + 2.5820175e-8, 1.902087e-8, -4.3254959e-8, -1.1120419e-7, -1.2565313e-7, -8.519962999999999e-9, 1.4601723e-7, 6.3621432e-7, + -2.6331083e-7, -0.0000010138949, 0.00000110968, 0.0000016838337, -0.0000035744646, -0.0000026460073, 0.0000053205335, 0.000007853747200000001, + 8.9215155e-8, 3.1123563e-7, 0.0000013795845, -0.000044677231, 0.00006865306099999999, 0.00011781359, -0.00015710027, -0.00036064286, + 0.00038031484, 0.00050338751, -0.00077590559, -0.0008674142, 0.0010777226, 0.00039442868, -0.0015444235, 0.0016459382, + 0.00035101212, -0.0046446429, 0.0018138366, 0.01452449, -0.013180724, -0.022957383, 0.028828912, 0.041597157, + -0.061093708, -0.041857191, 0.10188836, 0.033085447, -0.15855498, -0.0034829442, 0.23182062, -0.090326764, + -0.24246823, 0.22358741, 0.14781968, -0.26594426, -0.097818221, 0.28723329, 0.07952021200000001, -0.41757914, + 0.21073239, 0.2897774, -0.48889789, 0.22573225, }, + { 0.0, 0.0, 0.0, 0.0, -1.0733383e-23, -8.6079257e-24, 1.872705e-23, 4.5550867e-23, + 4.5417363e-23, -1.2189591e-25, -4.7937773e-23, -2.4038838e-22, 2.7755606e-22, 5.4224665e-22, -7.515297e-22, -1.4797002e-21, + 1.0502481e-21, 1.4065423e-21, -1.940141e-21, -6.9675157e-22, 1.4806259e-8, 1.1764015e-8, -2.5454621e-8, -6.247236e-8, + -1.3486342e-7, -5.8989698e-8, 1.9527931e-7, 6.419069e-7, 1.1234638e-7, -5.855622599999999e-7, 3.4054381e-7, -4.5951567e-7, + -0.0000013005443, 9.7272754e-7, 2.3198668e-7, -4.0989736e-7, 0.00000479093, 0.0000044838884, -0.000006090609, -0.000028617073, + 0.000020212565, 0.000037572762, -0.000049522919, -0.000030274147, 0.000059032777, 4.0388774e-7, -0.000078724649, 0.00008755813499999999, + 0.00012618231, -0.00018340068, -0.000059928571, 0.00036247195, -0.00015621759, -0.00031281978, 0.00022071986, 0.000021631567, + -0.0023678938, -0.0016216755, 0.0046514578, 0.0060223091, -0.0016579749, -0.0022419727, 0.00179991, -0.003098703, + -0.031223321, -0.015841757, 0.053425774, 0.058517397, -0.03700466, -0.026055767, 0.044009586, -0.030427122, + -0.17559441, -0.0033383422, 0.33021097, 0.014343156, -0.23379297, 0.10912792, 0.010642794, -0.24289997, + -0.17351534, 0.4024428, 0.46042496, -0.56361982, }, + { 0.37382874, -0.51867853, 0.47943749, -0.09378391899999999, -0.18905132, 0.29135353, -0.16447188, -0.07414341200000001, + 0.26094242, -0.23048843, 0.053840185, 0.12786236, -0.1799737, 0.10120967, 0.0045846861, -0.07467683, + 0.08096257900000001, -0.039817601, -0.013746566, 0.036482493, -0.028176001, 0.009026072, 0.0074018258, -0.0070228506, + 0.0057997749, -0.0036799712, -0.0028406099, 0.0018390274, 1.0642048e-17, -2.3879718e-17, 1.2954511e-17, 1.4028154e-17, + -1.4083962e-17, 7.6461113e-18, 2.0534728e-18, -6.184756e-18, 8.647686299999999e-18, -2.4031171e-18, -3.2001736e-18, 4.6656292e-18, + -2.3971523e-19, 3.7425143e-20, 1.7166598e-18, -2.1279204e-19, -6.6740118e-19, 1.5729731e-19, -4.4520642e-19, -4.4010561e-19, + 8.861819300000001e-19, -1.5574435e-20, -1.5525456e-19, 3.1233122e-19, -3.2127869e-19, -9.465079100000001e-20, 8.2112468e-20, -6.74227e-20, + -2.618406e-20, 9.9322619e-20, -1.5963306e-20, -4.8528886e-20, 1.2366602e-20, -5.19528e-20, -1.0067795e-20, 3.7232067e-20, + -2.9793349e-20, 2.8624007e-21, 9.8584485e-21, -1.3461486e-21, 4.4190518e-21, -9.6223827e-21, -6.3801957e-21, 2.9912514e-21, + 3.1636145e-21, -2.3855177e-22, -4.4689007e-22, 8.2869664e-22, -7.0758818e-23, -1.2663701e-22, -7.723131e-23, -9.1997408e-24, + 0.0, 0.0, 0.0, 0.0, }, + { -0.03134196, -0.17628012, 0.35590505, -0.50759131, 0.53725117, -0.45869154, 0.26412691, -0.076134326, + -0.007651761, -0.0021413273, 0.022998087, -0.047846877, 0.055539014, -0.025170751, -0.012140822, 0.032370535, + -0.029020686, 0.015322765, -0.00035189435, -0.0094576725, 0.0073349447, -0.00025913263, -0.0029728115, 0.00072206717, + -0.00059596822, 0.0014931631, 0.00129906, -0.00046872852, -0.00047383082, 0.00030064681, 0.00023207255, -0.00015024512, + 8.7917553e-18, 3.9419635e-18, 5.4735481e-19, 2.4625179e-18, -3.8542589e-18, 2.3167755e-19, 1.966174e-18, -1.1347933e-18, + -6.7944871e-19, 4.0203463e-19, -1.9518285e-19, -2.2669119e-19, 5.6957285e-19, -3.1249475e-19, 7.4451522e-20, 2.8108751e-19, + -4.0423298e-19, -9.275415100000001e-21, 5.3010949e-20, -2.2545586e-20, 1.1869787e-19, -5.9328308e-20, -3.3977341e-20, 5.9668567e-20, + -4.12458e-21, -3.107239e-20, -1.4927732e-20, 3.7425643e-21, 1.7937482e-20, 1.4043326e-20, -7.4193836e-22, -3.6709159e-21, + 2.4343311e-21, -2.8813358e-22, -7.7778006e-22, -4.9534229e-22, -1.8648303e-21, 2.2475477e-21, 1.3430748e-21, -9.8408921e-22, + -2.0997709e-22, 5.6528297e-23, 6.807894400000001e-23, -7.0085213e-23, -6.2883165e-23, 6.8688301e-23, 5.0209405e-23, -2.238441e-23, + 0.0, 0.0, 0.0, 0.0, }, + { -0.030822248, 0.12957914, -0.18512573, 0.16675695, -0.052857771, -0.13908969, 0.35276876, -0.49791235, + 0.51417242, -0.41258809, 0.26195585, -0.11804311, 0.023964219, 0.0010232861, 0.019152748, -0.044474532, + 0.047642352, -0.027203395, -0.0031796077, 0.027978106, -0.033547664, 0.020082559, -0.0007510504099999999, -0.011684609, + 0.009989718599999999, -0.0019747698, -0.0029026379, 0.0026834211, -0.002285624, 0.0018836202, 0.0016300179, -0.00085116188, + -2.7174786e-17, 2.4608677e-17, -5.4277816e-18, -1.5178824e-17, 1.5015794e-17, -4.5329942e-18, 5.0668817e-18, 6.2404078e-18, + -9.9984244e-18, 4.9554126e-18, 1.637905e-18, -2.8010555e-18, 3.3434367e-18, -2.1472836e-18, -6.7005628e-19, 1.7342157e-18, + -7.3535143e-19, 3.8043225e-19, 2.1005548e-19, -4.6648549e-19, 2.3804352e-19, -6.6845216e-20, -1.9323802e-19, 6.5692847e-20, + 2.8876787e-20, -8.108969599999999e-21, 4.8925104e-20, 1.6282379e-20, -7.870229800000001e-20, 1.2005518e-20, -3.4489745e-21, -2.1516959e-20, + 2.5544882e-20, -2.6720197e-21, -6.2833653e-22, 1.1517223e-20, -9.406839299999999e-21, -2.564765e-21, 4.7206229e-22, -2.3146181e-22, + 1.3258513e-21, -8.4052303e-22, -7.1310092e-22, 5.6324852e-22, 5.6863617e-22, -2.894814e-22, -2.3203236e-22, 1.7479559e-22, + 0.0, 0.0, 0.0, 0.0, }, + { 0.025421777, -0.067751664, 0.083134478, -0.052379526, -0.022274344, 0.12127978, -0.18958, 0.17343447, + -0.05080082, -0.14787227, 0.35019791, -0.48373671, 0.50542054, -0.41685964, 0.26577468, -0.11826206, + 0.02521028, 0.00094495453, 0.017027144, -0.043362773, 0.049765927, -0.029643921, -0.0032568805, 0.029534942, + -0.034563771, 0.020453298, -0.00076002331, -0.012130441, 0.010544552, -0.0022418113, -0.0031245172, 0.0028394937, + -0.0023731879, 0.0019425839, 0.0016769152, -0.00087992019, -5.2958493e-18, -4.0877396e-18, 2.772253e-18, -2.0311297e-18, + -2.288765e-18, 7.9289036e-18, 2.5284364e-18, -2.5402696e-18, 9.968205199999999e-19, -5.0944616e-19, 3.9140977e-19, 1.4230412e-18, + -1.2705171e-18, -6.1873396e-20, 3.8139103e-19, 1.7084439e-19, 2.5432643e-19, -3.3303833e-19, -1.4171105e-19, 4.2784771e-20, + 5.5757122e-20, -2.5390025e-20, -1.0232878e-19, 3.4361784e-20, 7.5020104e-20, -1.3646375e-20, 2.4618801e-20, 1.8847275e-20, + -5.9354063e-20, 1.3866702e-20, -4.6895811e-21, -1.278071e-20, 1.7077252e-20, -8.771959499999999e-21, 4.4899158e-22, 1.03643e-20, + -1.0025575e-20, -2.4458956e-21, -9.209271300000001e-22, -1.5410242e-21, 3.3222615e-21, -9.566303300000001e-22, -8.9521542e-22, 9.720106e-22, + 0.0, 0.0, 0.0, 0.0, }, + { -0.0071228475, 0.019049761, -0.024644883, 0.010765621, 0.023054686, -0.065592104, 0.084161342, -0.055948254, + -0.023192439, 0.12405666, -0.19005779, 0.17094339, -0.04939618, -0.14612657, 0.34892501, -0.48406091, + 0.5052392999999999, -0.41645337, 0.26618139, -0.11881742, 0.024890949, 0.0016351911, 0.017138476, -0.043848154, + 0.049926304, -0.02967179, -0.0032277214, 0.029567187, -0.034684308, 0.020548686, -0.00069180842, -0.012172774, + 0.010553003, -0.0022464053, -0.0031296428, 0.0028424184, -0.0023745904, 0.0019437318, 0.0016779062, -0.00088044017, + -1.8475243e-17, 1.4568058e-17, -2.0010569e-18, -1.4842759e-17, 9.308017300000001e-18, 2.7885175e-18, 1.4098213e-18, 7.8711632e-19, + -4.1060061e-18, 3.3844641e-18, 1.6399896e-18, -2.4498493e-18, 4.7428963e-19, 8.4630943e-19, -4.6354074e-19, -1.2947061e-19, + 2.8272731e-19, 1.5542018e-19, 2.3918721e-19, -2.0130475e-19, -2.9555998e-19, 2.7180211e-19, 9.5026985e-20, -2.3738958e-19, + 5.1395559e-20, 1.2154465e-20, 2.7573762e-20, 5.0529356e-20, -7.842936e-20, -2.2160648e-20, 1.9633519e-20, 8.7787609e-21, + -2.3803114e-21, -1.0067923e-20, -7.660827199999999e-21, 2.4925729e-21, 9.6896307e-21, -5.5581321e-21, -4.3914061e-21, 3.0391488e-21, + 0.0, 0.0, 0.0, 0.0, }, + { -0.0018057424, -0.0016866646, 0.0069035273, -0.0041188241, -0.0064422689, 0.018372935, -0.025072938, 0.012034045, + 0.023684689, -0.066573572, 0.084151978, -0.054928148, -0.023777293, 0.12329836, -0.18937441, 0.17096458, + -0.049532242, -0.14576154, 0.3484839, -0.48395708, 0.50564701, -0.41694937, 0.26615718, -0.11857785, + 0.024683551, 0.0018054855, 0.017143896, -0.044001563, 0.050065196, -0.029716819, -0.0032594908, 0.029601577, + -0.034723419, 0.020572699, -0.00067340378, -0.012185211, 0.010554037, -0.0022469977, -0.0031302016, 0.0028427593, + -0.0023746848, 0.0019438091, 0.0016779729, -0.00088047518, -2.0693739e-17, 8.560389100000001e-18, -4.7354788e-18, -1.0263813e-17, + 1.0286909e-17, 2.8410305e-18, 2.8973959e-18, 3.0084238e-18, -5.0483408e-18, 6.748686e-19, 1.0579793e-18, -1.0668294e-18, + 7.5172508e-19, -8.7941528e-20, -3.5368006e-19, 3.726905e-19, 3.9127407e-19, -2.2086158e-19, -2.5947048e-20, -8.9091678e-20, + -2.4548966e-20, 1.9645497e-19, -4.8562499e-20, -1.6401124e-19, 1.1905575e-19, 6.000222099999999e-20, 3.6002571e-20, 1.1443347e-20, + -7.0656252e-20, 2.7338021e-20, 2.4165017e-20, -2.1090532e-20, 1.1579904e-21, -4.3668812e-22, -4.3928957e-22, 3.7120868e-22, + 0.0, 0.0, 0.0, 0.0, }, + { 0.00068393172, -0.0023926981, 0.00072610966, 0.0010990308, -0.0018198967, -0.0019500797, 0.0070152584, -0.0036896504, + -0.0065067349, 0.018163296, -0.02497928, 0.011948147, 0.023789348, -0.066379495, 0.083933271, -0.054793027, + -0.023683757, 0.12297215, -0.18920335, 0.17105637, -0.049743734, -0.14562801, 0.34847623, -0.48400863, + 0.50575808, -0.41704877, 0.26614614, -0.118491, 0.024627691, 0.0018094971, 0.017148822, -0.044012176, + 0.050085326, -0.029729752, -0.0032694011, 0.029607998, -0.034723337, 0.020572644, -0.00067351244, -0.012185184, + 0.010554055, -0.0022469936, -0.0031302016, 0.0028427628, -0.0023746918, 0.0019438149, 0.0016779778, -0.00088047778, + -2.3067914e-17, 5.4003058e-18, -1.251809e-18, -5.2066413e-18, 7.792644200000001e-18, -3.7935423e-19, 3.7777487e-19, 3.4931246e-18, + -2.7529126e-18, 5.0329172e-19, 1.6457288e-19, -6.692252e-19, 9.4932395e-19, -6.4945309e-19, 1.0398817e-19, 1.9002636e-19, + -1.7541128e-19, -3.5753619e-20, -1.0769248e-20, -1.2646435e-19, 9.2812895e-20, -1.1354876e-19, -3.8668441e-20, 5.710273e-20, + -3.4373439e-20, 1.9479008e-20, 9.9343437e-21, -9.122147999999999e-21, 6.8532923e-21, -9.546463e-21, -6.5673988e-21, 2.5025079e-21, + 0.0, 0.0, 0.0, 0.0, }, + { 0.0010687183, -0.0010450744, -0.0010070066, 0.0020253044, 0.0005517824499999999, -0.0022959155, 0.00097057671, 0.0010924508, + -0.0019312501, -0.0017546407, 0.0070874093, -0.0040113854, -0.006331699, 0.018446531, -0.025235592, 0.012062147, + 0.02384824, -0.066697913, 0.084157576, -0.054739183, -0.023923087, 0.12315927, -0.18921469, 0.17097969, + -0.049615501, -0.14573626, 0.34846795, -0.48391368, 0.5056902599999999, -0.41703911, 0.26615604, -0.11850642, + 0.02465109, 0.0017948116, 0.01713781, -0.044004865, 0.050085147, -0.029729697, -0.0032693156, 0.029607987, + -0.03472338, 0.020572672, -0.00067355155, -0.012185201, 0.010554082, -0.0022469952, -0.0031302068, 0.0028427695, + -0.0023746995, 0.0019438212, 0.0016779833, -0.00088048065, -2.1000047e-17, 7.565723700000001e-18, 2.5190234e-18, -7.738874199999999e-18, + 5.1613258e-18, 1.8630382e-18, 4.7500716e-18, 1.5683656e-18, -3.5332673e-18, 2.0768143e-18, -1.4987312e-18, -3.5413893e-21, + 2.4420979e-18, -1.345524e-18, 4.3500825e-20, 6.943662e-19, -6.1374977e-19, 1.0242197e-18, 2.718543e-20, -8.3072249e-19, + 5.9251615e-19, -4.9885031e-20, -4.0607809e-20, 1.0117644e-19, -2.4097676e-19, 1.301706e-19, 1.0250316e-19, -7.4365919e-20, + 0.0, 0.0, 0.0, 0.0, }, + { 0.00056402136, 0.00021333467, -0.00091125097, 0.00036685809, 0.0010149448, -0.00096200703, -0.00094793227, 0.0018387994, + 0.00040516071, -0.0021710487, 0.0010161009, 0.0009399139400000001, -0.0018566059, -0.0016341052, 0.0069538839, -0.0040202907, + -0.0062841631, 0.018383441, -0.02517064, 0.012052401, 0.02377528, -0.066607666, 0.084161445, -0.054781921, + -0.02388942, 0.12313141, -0.18921571, 0.17100415, -0.049638042, -0.14572902, 0.34847456, -0.48392014, + 0.50569705, -0.41704335, 0.26615332, -0.11850458, 0.02465106, 0.0017948162, 0.0171379, -0.044004883, + 0.050085129, -0.029729696, -0.0032693338, 0.029607991, -0.034723382, 0.020572681, -0.00067355989, -0.012185204, + 0.010554086, -0.0022469929, -0.0031302058, 0.0028427698, -0.0023747013, 0.0019438227, 0.0016779846, -0.0008804813, + -9.379688700000001e-18, 2.6146403e-18, 1.5746634e-18, -1.0728369e-17, 4.5804656e-18, 7.107964500000001e-18, 2.3260764e-18, -1.9169252e-19, + -7.0226566e-19, -1.873713e-18, 9.4236304e-19, 4.1572967e-19, -1.2076212e-18, 7.4089255e-19, -2.6527306e-20, -6.578718e-19, + 8.7291408e-19, -4.7704746e-21, -8.057007799999999e-20, 1.7753254e-19, -2.2058122e-19, 7.1324509e-20, 6.6889699e-20, -6.6102385e-20, + 0.0, 0.0, 0.0, 0.0, }, + { 0.00014271253, 0.00023780917, -0.00025714186, -0.00024317058, 0.00057409128, 0.00023010554, -0.00093069112, 0.00027243145, + 0.00094306671, -0.00094563757, -0.00092816994, 0.001821437, 0.00041076611, -0.0021577244, 0.00098623583, 0.00091431244, + -0.0018365761, -0.0016126829, 0.0069466743, -0.0040339626, -0.0062805659, 0.018399842, -0.025165617, 0.012042197, + 0.023770284, -0.066603485, 0.08416202, -0.054785429, -0.023889813, 0.12313399, -0.18921405, 0.17100357, + -0.049638649, -0.14572867, 0.34847509, -0.48392049, 0.5056971, -0.4170434, 0.26615338, -0.11850462, + 0.024651084, 0.0017947992, 0.017137901, -0.044004876, 0.050085122, -0.029729693, -0.0032693353, 0.02960799, + -0.034723382, 0.020572683, -0.00067356152, -0.012185204, 0.010554086, -0.0022469925, -0.0031302055, 0.0028427698, + -0.0023747016, 0.0019438229, 0.0016779848, -0.00088048141, -2.8978181e-17, 8.47362e-18, -4.2763004e-18, -6.8278819e-18, + 1.0819706e-17, 1.2087701e-18, 1.1162283e-18, 2.1511478e-18, -3.1994618e-18, 5.9178468e-19, 2.1698119e-19, -1.3697938e-18, + 9.570426299999999e-19, 1.7932389e-19, 9.624209700000001e-20, 1.6376431e-19, -2.5332735e-19, 9.4050075e-20, 7.611858e-20, -7.3344331e-20, + 0.0, 0.0, 0.0, 0.0, }, + { 0.0000018447549, 0.000053840851, -0.000026051496, -0.00017560402, 0.00015359699, 0.0002298131, -0.00027785099, -0.00026917927, + 0.0005488749299999999, 0.00021718602, -0.00092552858, 0.0002822896, 0.00093939925, -0.00095067092, -0.00093089337, 0.0018096997, + 0.00041718788, -0.0021417498, 0.00097583578, 0.00090879181, -0.0018277373, -0.0016127741, 0.006949134, -0.0040349802, + -0.0062864137, 0.018404312, -0.025165254, 0.012038182, 0.023772235, -0.066602884, 0.084162157, -0.054785014, + -0.023890803, 0.1231346, -0.18921358, 0.17100325, -0.049638615, -0.1457287, 0.34847512, -0.48392051, + 0.50569712, -0.41704341, 0.26615339, -0.11850462, 0.024651086, 0.0017947971, 0.017137901, -0.044004875, + 0.050085122, -0.029729693, -0.0032693359, 0.02960799, -0.034723382, 0.020572683, -0.00067356177, -0.012185204, + 0.010554086, -0.0022469924, -0.0031302055, 0.0028427698, -0.0023747016, 0.0019438229, 0.0016779848, -0.00088048143, + -3.6791394e-17, 4.052262e-18, -1.969778e-18, -7.0296556e-18, 9.7759458e-18, -3.3222873e-18, 4.6273224e-19, 5.2111855e-18, + -4.4401574e-18, -1.2256545e-18, -5.4477758e-19, -6.7353127e-19, 1.469541e-18, -4.7402283e-19, -4.2509837e-19, 4.3223452e-19, + 0.0, 0.0, 0.0, 0.0, }, + { -0.0000065232055, 3.1277378e-7, 0.0000025601527, -0.000023637333, 0.0000027834083, 0.000051419076, -0.000029530267, -0.00017738859, + 0.00015142412, 0.00022660426, -0.00027806924, -0.00026668364, 0.00054837847, 0.0002158698, -0.00092505622, 0.00028086916, + 0.00093984668, -0.00094828387, -0.00093257586, 0.0018090192, 0.00041872951, -0.0021422683, 0.00097615257, 0.00090894629, + -0.0018286964, -0.0016120872, 0.0069491938, -0.0040356127, -0.0062860363, 0.018404337, -0.025165282, 0.012038277, + 0.023772074, -0.066602783, 0.08416222499999999, -0.05478506, -0.023890801, 0.1231346, -0.18921358, 0.17100324, + -0.049638612, -0.1457287, 0.34847512, -0.48392051, 0.50569712, -0.41704341, 0.26615339, -0.11850462, + 0.024651086, 0.001794797, 0.017137901, -0.044004875, 0.050085122, -0.029729693, -0.003269336, 0.02960799, + -0.034723382, 0.020572683, -0.00067356178, -0.012185204, 0.010554086, -0.0022469924, -0.0031302055, 0.0028427698, + -0.0023747016, 0.0019438229, 0.0016779848, -0.00088048143, -1.6713031e-17, 5.5425368e-19, 1.4245021e-18, -1.0072591e-18, + 5.3286569e-18, 1.4946097e-18, 2.8736484e-19, 9.387527700000001e-19, -4.2179426e-19, -9.975578300000001e-19, -5.809857e-19, -5.1089939e-20, + 0.0, 0.0, 0.0, 0.0, }, + { -0.0000010713313, -0.0000062302572, 0.0000055244516, 0.0000061175856, -0.0000071482518, 3.4513491e-9, 0.0000030429546, -0.000021759169, + 0.0000044190563, 0.000051269961, -0.000030117431, -0.00017718171, 0.00015149658, 0.0002263981, -0.00027757249, -0.00026613844, + 0.00054793064, 0.00021538327, -0.00092477868, 0.00028111234, 0.00093967287, -0.00094853506, -0.0009326781, 0.0018092101, + 0.00041887081, -0.0021424066, 0.00097614709, 0.00090906261, -0.0018287172, -0.0016121413, 0.0069491642, -0.0040356085, + -0.0062860096, 0.018404321, -0.0251653, 0.01203829, 0.023772072, -0.066602781, 0.08416222199999999, -0.054785057, + -0.023890803, 0.1231346, -0.18921358, 0.17100324, -0.049638612, -0.1457287, 0.34847512, -0.48392051, + 0.50569712, -0.41704341, 0.26615339, -0.11850462, 0.024651086, 0.001794797, 0.017137901, -0.044004875, + 0.050085122, -0.029729693, -0.003269336, 0.02960799, -0.034723382, 0.020572683, -0.00067356178, -0.012185204, + 0.010554086, -0.0022469924, -0.0031302055, 0.0028427698, -0.0023747016, 0.0019438229, 0.0016779848, -0.00088048143, + -1.8941367e-17, 1.5711291e-18, 2.3452836e-18, -3.899545e-18, 3.6296061e-18, -1.9151907e-19, -4.1068595e-19, 9.915058199999999e-19, + 0.0, 0.0, 0.0, 0.0, }, + { -9.0889843e-7, -2.2626776e-7, 0.000001260977, 0.0000044608021, -0.0000011469721, -0.0000059094081, 0.0000061283667, 0.0000069729643, + -0.000006297129, 3.7634729e-7, 0.0000029524362, -0.00002191209, 0.0000043424749, 0.000051262029, -0.000029845963, -0.00017685033, + 0.00015126363, 0.00022604271, -0.00027738458, -0.00026596286, 0.00054779433, 0.00021525271, -0.0009248599599999999, 0.00028119182, + 0.0009397919999999999, -0.00094860626, -0.00093268933, 0.001809279, 0.00041885032, -0.0021424302, 0.00097613531, 0.00090905965, + -0.0018287021, -0.0016121504, 0.0069491565, -0.0040356031, -0.0062860105, 0.018404322, -0.0251653, 0.01203829, + 0.023772071, -0.06660278, 0.08416222199999999, -0.054785057, -0.023890803, 0.1231346, -0.18921358, 0.17100324, + -0.049638612, -0.1457287, 0.34847512, -0.48392051, 0.50569712, -0.41704341, 0.26615339, -0.11850462, + 0.024651086, 0.001794797, 0.017137901, -0.044004875, 0.050085122, -0.029729693, -0.003269336, 0.02960799, + -0.034723382, 0.020572683, -0.00067356178, -0.012185204, 0.010554086, -0.0022469924, -0.0031302055, 0.0028427698, + -0.0023747016, 0.0019438229, 0.0016779848, -0.00088048143, 6.1878754e-18, -3.6655866e-18, -2.9841768e-18, 1.9922148e-18, + 0.0, 0.0, 0.0, 0.0, }, + { 1.3144978e-7, 9.8657161e-8, -2.2253182e-7, -5.6333606e-7, -8.9434942e-7, -2.5701115e-7, 0.0000011890586, 0.0000043393418, + -0.0000012646187, -0.0000059468393, 0.0000061464536, 0.0000069842975, -0.000006287677, 3.8234005e-7, 0.000002913009, -0.000021955667, + 0.000004374943, 0.000051305901, -0.000029868643, -0.00017687301, 0.00015127913, 0.00022606239, -0.00027737419, -0.00026597498, + 0.00054778017, 0.00021526158, -0.00092485866, 0.00028118337, 0.00093979398, -0.00094860284, -0.00093268751, 0.0018092791, + 0.0004188485, -0.0021424291, 0.00097613632, 0.00090905895, -0.001828702, -0.0016121505, 0.0069491567, -0.0040356032, + -0.0062860104, 0.018404322, -0.0251653, 0.01203829, 0.023772071, -0.06660278, 0.08416222199999999, -0.054785057, + -0.023890803, 0.1231346, -0.18921358, 0.17100324, -0.049638612, -0.1457287, 0.34847512, -0.48392051, + 0.50569712, -0.41704341, 0.26615339, -0.11850462, 0.024651086, 0.001794797, 0.017137901, -0.044004875, + 0.050085122, -0.029729693, -0.003269336, 0.02960799, -0.034723382, 0.020572683, -0.00067356178, -0.012185204, + 0.010554086, -0.0022469924, -0.0031302055, 0.0028427698, -0.0023747016, 0.0019438229, 0.0016779848, -0.00088048143, + 0.0, 0.0, 0.0, 0.0, }, + { 0.0, 0.0, 0.0, 0.0, -1.622356e-9, -1.2890103e-9, 2.7891217e-9, 6.845241e-9, + 1.3126578e-7, 9.901721900000001e-8, -2.2166186e-7, -5.6183755e-7, -8.9289394e-7, -2.5656308e-7, 0.0000011888122, 0.0000043391602, + -0.0000012647803, -0.0000059469017, 0.0000061469773, 0.0000069850389, -0.0000062879678, 3.8158828e-7, 0.0000029133662, -0.000021955518, + 0.0000043746943, 0.000051306159, -0.000029869367, -0.00017687376, 0.00015128051, 0.00022606404, -0.00027737624, -0.00026598254, + 0.00054778393, 0.00021526722, -0.00092486527, 0.00028119529, 0.00093978004, -0.0009486419, -0.00093265228, 0.0018094229, + 0.00041867283, -0.0021426906, 0.00097650436, 0.00090964586, -0.0018293513, -0.0016126855, 0.0069502949, -0.0040354262, + -0.0062870574, 0.018405222, -0.025164144, 0.012032827, 0.023774346, -0.066591942, 0.084151854, -0.054804601, + -0.023862503, 0.12315689, -0.1892543, 0.17095475, -0.049559377, -0.14567882, 0.3483179, -0.4838932, + 0.50588033, -0.41713971, 0.26600252, -0.11841888, 0.024871591, 0.0016210723, 0.016891466, -0.043640211, + 0.050057842, -0.03006571, -0.0030367974, 0.029556911, -0.034590027, 0.020929563, -0.0012983588, -0.012419997, + 0.010951201, -0.002389025, -0.0031262218, 0.0028105997, }, + { 0.0, 0.0, 0.0, 0.0, -3.6439133e-24, -2.8986979e-24, 6.2660146e-24, 1.5379692e-23, + -1.6222016e-9, -1.2888876e-9, 2.7888562e-9, 6.8445893e-9, 1.312523e-7, 9.9007009e-8, -2.2163906e-7, -5.6177991e-7, + -8.9272771e-7, -2.5647732e-7, 0.0000011885618, 0.0000043383995, -0.0000012650025, -0.0000059463278, 0.0000061467672, 0.0000069861743, + -0.0000062897555, 3.7727988e-7, 0.0000029191314, -0.000021941306, 0.0000043687192, 0.000051291624, -0.000029855051, -0.00017686176, + 0.00015125309, 0.0002260747, -0.00027735745, -0.00026608583, 0.00054791784, 0.00021551982, -0.00092512611, 0.00028035321, + 0.00094065862, -0.00094742205, -0.00093450757, 0.0018076545, 0.00042131052, -0.0021417278, 0.00097239854, 0.00091159722, + -0.0018264239, -0.0016199728, 0.0069502154, -0.0040114121, -0.0063040316, 0.018365516, -0.025118693, 0.012102578, + 0.023644377, -0.066685113, 0.084356401, -0.054595596, -0.024125527, 0.12301898, -0.1887722, 0.17066016, + -0.050419921, -0.14528907, 0.34913412, -0.4838335, 0.50558311, -0.41643331, 0.26613447, -0.12101845, + 0.024625157, 0.0033560726, 0.016841212, -0.041760408, 0.050984407, -0.03285494, -0.004117546, 0.028617951, + -0.035237369, 0.023732977, 0.0015240184, -0.008435701800000001, }, + { 0.0, 0.0, 0.0, 0.0, -1.0431812e-23, -8.2803737e-24, 1.7939522e-23, 4.4007904e-23, + 6.4884103e-23, 1.7524634e-23, -8.5803103e-23, -3.2496948e-22, -1.6203806e-9, -1.2874408e-9, 2.7857256e-9, 6.836906e-9, + 1.3109947e-7, 9.889150299999999e-8, -2.2138082e-7, -5.611261e-7, -8.9219889e-7, -2.5658335e-7, 0.0000011880548, 0.0000043354995, + -0.0000012608301, -0.000005938918, 0.0000061362301, 0.0000069641375, -0.0000062687907, 4.0459468e-7, 0.0000028787034, -0.000021983378, + 0.0000044129115, 0.000051289938, -0.000029905595, -0.00017666359, 0.00015087211, 0.00022542775, -0.0002765433, -0.00026376228, + 0.00054507147, 0.00021169912, -0.00091924555, 0.00028840249, 0.00093079662, -0.00095471267, -0.00091771013, 0.0018095019, + 0.00040700431, -0.0021236987, 0.0009811498199999999, 0.0008245475, -0.0017754444, -0.0014644008, 0.0068040412, -0.0043451443, + -0.0058442993, 0.018818003, -0.025939109, 0.011340895, 0.024930389, -0.0661234, 0.082217785, -0.054081764, + -0.020897545, 0.12165048, -0.1920747, 0.17211359, -0.048140833, -0.14851256, 0.3472333, -0.47646397, + 0.50599354, -0.42288577, 0.26917601, -0.12432367, 0.022587169, 0.010412511, 0.015359906, -0.041565257, + 0.055431988, -0.038165138, -0.009985203099999999, 0.018675575, }, + { 0.0, 0.0, 0.0, 0.0, 3.2812725e-24, 2.5848368e-24, -5.6275193e-24, -1.3782151e-23, + -2.3902558e-23, -8.1365251e-24, 3.3008241e-23, 1.1640815e-22, -7.3250277e-23, -1.8762401e-22, 2.2730087e-22, 3.3780674e-22, + -1.616205e-9, -1.2841231e-9, 2.778547e-9, 6.8192879e-9, 1.3237482e-7, 9.9918388e-8, -2.2358368e-7, -5.6648665e-7, + -8.9932696e-7, -2.5816482e-7, 0.0000011972154, 0.0000043720435, -0.000001292952, -0.0000060081096, 0.0000062263636, 0.000007122935, + -0.0000063986485, 2.6724076e-7, 0.0000030929214, -0.000021946257, 0.0000047207535, 0.000052048986, -0.000030742059, -0.00018076981, + 0.00015544318, 0.00023291138, -0.00028644303, -0.00028176127, 0.00056447015, 0.0002311271, -0.00095483998, 0.00027379593, + 0.00096725386, -0.0009771671, -0.00095367853, 0.0019658873, 0.00033910824, -0.0024180526, 0.0012134667, 0.0015009697, + -0.0026057442, -0.0024276335, 0.0084128255, -0.0028188375, -0.008494489799999999, 0.017721873, -0.021825093, 0.010970745, + 0.018597655, -0.064282876, 0.08981873999999999, -0.057812995, -0.02662704, 0.12911772, -0.1885168, 0.15985436, + -0.050361919, -0.13554452, 0.34264685, -0.47581746, 0.51144248, -0.43326474, 0.2710083, -0.12265704, + 0.015729342, 0.016261307, 0.026089652, -0.029242654, }, + { 0.0, 0.0, 0.0, 0.0, -2.2778956e-24, -1.8076424e-24, 3.9250879e-24, 9.6136326e-24, + 2.5282692e-23, 1.2550767e-23, -3.7660392e-23, -1.1740747e-22, -2.9437921e-23, 9.5145047e-23, -4.2770808e-23, 1.4239399e-22, + 1.9286708e-23, -4.034217e-22, 3.6553584e-22, 9.7305538e-22, -1.4431934e-9, -1.1466603e-9, 2.481109e-9, 6.0892965e-9, + 1.2633458e-7, 9.568202499999999e-8, -2.136268e-7, -5.4014939e-7, -8.7095084e-7, -2.5802661e-7, 0.000001165696, 0.000004230512, + -0.0000012146636, -0.0000057632352, 0.0000059410362, 0.000006652386, -0.0000059549064, 6.5404746e-7, 0.0000024605114, -0.000022134786, + 0.0000037026798, 0.000049710525, -0.000028167748, -0.00016723509, 0.00014401584, 0.00021121699, -0.00026020494, -0.00023896016, + 0.00052168195, 0.0001958936, -0.00088205854, 0.0002546882, 0.0009008995099999999, -0.00085354557, -0.00092916911, 0.0015016721, + 0.00054407697, -0.0017561327, 0.0006602936, 0.00048076711, -0.00071974471, -0.0009798873499999999, 0.0049969489, -0.004765169, + -0.0048724692, 0.017594955, -0.026661957, 0.015885895, 0.027476655, -0.070054739, 0.081437923, -0.056044498, + -0.027087963, 0.12330761, -0.18331454, 0.17796109, -0.049807749, -0.14814388, 0.33642099, -0.49016986, + 0.51434408, -0.41486443, 0.27672635, -0.10432054, }, +}; + +const double* const ff_on2avc_tabs_20_84_1[20] = { + tabs_20_84[ 0], tabs_20_84[ 1], tabs_20_84[ 2], tabs_20_84[ 3], + tabs_20_84[ 4], tabs_20_84[ 5], tabs_20_84[ 6], tabs_20_84[ 7], + tabs_20_84[ 8], tabs_20_84[ 9], tabs_20_84[10], tabs_20_84[11], + tabs_20_84[12], tabs_20_84[13], tabs_20_84[14], tabs_20_84[15], + tabs_20_84[16], tabs_20_84[17], tabs_20_84[18], tabs_20_84[19] +}; + +const double* const ff_on2avc_tabs_20_84_2[20] = { + tabs_20_84[20], tabs_20_84[21], tabs_20_84[22], tabs_20_84[23], + tabs_20_84[24], tabs_20_84[25], tabs_20_84[26], tabs_20_84[27], + tabs_20_84[28], tabs_20_84[29], tabs_20_84[30], tabs_20_84[31], + tabs_20_84[32], tabs_20_84[33], tabs_20_84[34], tabs_20_84[35], + tabs_20_84[36], tabs_20_84[37], tabs_20_84[38], tabs_20_84[39] +}; + +const double* const ff_on2avc_tabs_20_84_3[20] = { + tabs_20_84[40], tabs_20_84[41], tabs_20_84[42], tabs_20_84[43], + tabs_20_84[44], tabs_20_84[45], tabs_20_84[46], tabs_20_84[47], + tabs_20_84[48], tabs_20_84[49], tabs_20_84[50], tabs_20_84[51], + tabs_20_84[52], tabs_20_84[53], tabs_20_84[54], tabs_20_84[55], + tabs_20_84[56], tabs_20_84[57], tabs_20_84[58], tabs_20_84[59] +}; + +const double* const ff_on2avc_tabs_20_84_4[20] = { + tabs_20_84[60], tabs_20_84[61], tabs_20_84[62], tabs_20_84[63], + tabs_20_84[64], tabs_20_84[65], tabs_20_84[66], tabs_20_84[67], + tabs_20_84[68], tabs_20_84[69], tabs_20_84[70], tabs_20_84[71], + tabs_20_84[72], tabs_20_84[73], tabs_20_84[74], tabs_20_84[75], + tabs_20_84[76], tabs_20_84[77], tabs_20_84[78], tabs_20_84[79] +}; + +const float ff_on2avc_ctab_1[2048] = { + 2.0, -4.4408921e-16, 1.998863, -0.067429408, 1.9954522, -0.13479699, 1.9897684, -0.20204064, + 1.9818133, -0.26909772, 1.9715892, -0.33590481, 1.9590992, -0.40239748, 1.9443476, -0.46851003, + 1.9273404, -0.5341754, 1.9080848, -0.59932488, 1.8865899, -0.66388828, 1.8628675, -0.72779351, + 1.8369317, -0.79096675, 1.8087995, -0.85333258, 1.7784914, -0.91481382, 1.7460314, -0.9753319, + 1.7114476, -1.0348068, 1.6747727, -1.0931578, 1.6360439, -1.1503029, 1.5953034, -1.2061599, + 1.5525988, -1.2606467, 1.5079833, -1.3136812, 1.4615158, -1.3651828, 1.4132608, -1.4150716, + 1.3632895, -1.4632699, 1.3116785, -1.5097026, 1.2585107, -1.5542974, 1.2038751, -1.5969861, + 1.1478662, -1.637704, 1.0905846, -1.6763921, 1.0321362, -1.7129962, 0.97263169, -1.7474687, + 0.9121868, -1.7797679, 0.85092157, -1.8098596, 0.78895974, -1.8377171, 0.72642845, -1.8633214, + 0.66345739, -1.8866621, 0.60017854, -1.9077374, 0.5367251, -1.9265541, 0.47323114, -1.9431282, + 0.4098306, -1.9574846, 0.34665683, -1.9696577, 0.28384155, -1.9796903, 0.22151428, -1.9876345, + 0.15980156, -1.993551, 0.09882611, -1.9975084, 0.038706206, -1.9995835, -0.02044509, -1.99986, + -0.078520596, -1.9984288, -0.13541964, -1.9953866, -0.19104865, -1.9908354, -0.24532171, -1.984882, + -0.29816103, -1.9776367, -0.34949744, -1.9692125, -0.39927062, -1.9597243, -0.44742957, -1.949288, + -0.49393275, -1.938019, -0.5387482, -1.9260317, -0.58185375, -1.9134382, -0.62323707, -1.900347, + -0.66289538, -1.8868629, -0.70083576, -1.8730848, -0.73707455, -1.8591057, -0.77163762, -1.8450115, + -0.80455959, -1.83088, -0.83588386, -1.8167808, -0.8656621, -1.8027737, -0.89395374, -1.7889093, + -0.9208256, -1.7752278, -0.94635135, -1.761759, -0.97061092, -1.7485228, -0.99368966, -1.7355278, + -1.0156779, -1.7227728, -1.0366703, -1.710247, -1.0567647, -1.6979295, -1.0760615, -1.6857911, + -1.0946627, -1.673794, -1.112671, -1.6618937, -1.1301892, -1.650039, -1.1473182, -1.6381736, + -1.164157, -1.6262373, -1.1808009, -1.6141669, -1.1973405, -1.6018976, -1.2138611, -1.5893645, + -1.2304406, -1.5765032, -1.2471493, -1.5632517, -1.2640481, -1.5495512, -1.2811878, -1.5353475, + -1.2986077, -1.5205914, -1.3163352, -1.5052403, -1.3343842, -1.4892588, -1.3527551, -1.4726188, + -1.3714331, -1.4553007, -1.390389, -1.4372933, -1.4095774, -1.4185938, -1.4289376, -1.3992081, + -1.4483931, -1.3791504, -1.4678518, -1.3584429, -1.4872066, -1.3371153, -1.5063359, -1.3152039, + -1.525104, -1.2927508, -1.5433633, -1.2698036, -1.5609542, -1.2464136, -1.5777074, -1.222635, + -1.5934458, -1.198524, -1.6079853, -1.1741376, -1.6211381, -1.1495321, -1.6327139, -1.1247627, + -1.6425229, -1.0998815, -1.6503778, -1.0749379, -1.656096, -1.0499765, -1.6595027, -1.0250366, + -1.6604328, -1.0001521, -1.6587337, -0.97535098, -1.6542674, -0.95065427, -1.6469128, -0.92607677, + -1.6365674, -0.90162659, -1.6231499, -0.87730545, -1.6066011, -0.85310918, -1.5868859, -0.82902807, + -1.5639942, -0.80504757, -1.5379412, -0.78114909, -1.5087692, -0.75731099, -1.4765463, -0.73350942, + -1.4413673, -0.70971948, -1.4033529, -0.68591642, -1.3626487, -0.66207647, -1.3194243, -0.63817829, + -1.2738714, -0.61420387, -1.2262026, -0.59013963, -1.1766489, -0.56597722, -1.1254574, -0.54171461, + -1.0728892, -0.51735634, -1.0192158, -0.49291453, -0.96471739, -0.468409, -0.90967888, -0.44386747, + -0.85438752, -0.41932571, -0.79912966, -0.39482722, -0.74418765, -0.37042305, -0.68983728, -0.34617117, + -0.63634455, -0.32213587, -0.58396345, -0.29838684, -0.53293306, -0.27499828, -0.48347571, -0.25204778, + -0.43579489, -0.22961509, -0.39007342, -0.20778094, -0.34647217, -0.18662569, -0.30512896, -0.16622795, + -0.26615775, -0.14666332, -0.22964823, -0.12800303, -0.19566566, -0.11031273, -0.1642511, -0.093651295, + -0.13542198, -0.078069784, -0.10917274, -0.063610479, -0.085476093, -0.050306138, -0.064284235, -0.038179338, + -0.04553042, -0.02724205, -0.029130703, -0.017495384, -0.014985808, -0.0089295385, -0.0029831429, -0.0015239252, + 0.0070011336, 0.0047524893, 0.015099987, 0.0099406661, 0.021453392, 0.014090803, 0.026206236, 0.017261485, + 0.029506302, 0.019518688, 0.03150234, 0.020934677, 0.032342274, 0.021586809, 0.032171525, 0.021556264, + 0.031131554, 0.020926755, 0.029358514, 0.019783208, 0.026982145, 0.018210486, 0.024124846, 0.016292138, + 0.020900913, 0.014109233, 0.017415999, 0.011739281, 0.013766737, 0.0092552658, 0.010040524, 0.0067248093, + 0.006315473, 0.0042094728, 0.0026604859, 0.0017642101, -0.00086453988, -0.00056303042, -0.004208413, -0.0027315477, + -0.0073282644, -0.0047079842, -0.010189103, -0.0064662765, -0.01276332, -0.0079874769, -0.015030168, -0.009259454, + -0.016975222, -0.01027649, -0.018589836, -0.01103879, -0.019870605, -0.011551925, -0.020818852, -0.011826212, + -0.021440107, -0.011876071, -0.02174365, -0.011719362, -0.021742038, -0.011376713, -0.021450687, -0.010870866, + -0.020887457, -0.010226041, -0.020072276, -0.0094673438, -0.019026764, -0.0086202007, -0.017773898, -0.0077098534, + -0.016337669, -0.0067608948, -0.014742769, -0.0057968628, -0.013014285, -0.0048398855, -0.011177403, -0.0039103772, + -0.0092571331, -0.0030267884, -0.0072780494, -0.002205404, -0.0052640433, -0.0014601871, -0.0032381038, -0.00080267049, + -0.0012221149, -0.00024189093, 0.00076331489, 0.00021563418, 0.0026989998, 0.00056588947, 0.0045672944, 0.00080730428, + 0.0063521829, 0.00094065693, 0.0080393394, 0.00096894189, 0.0096161636, 0.00089720206, 0.011071794, 0.00073232828, + 0.012397096, 0.00048283004, 0.013584645, 0.00015858111, 0.014628679, -0.00022945412, 0.015525063, -0.00066950807, + 0.016271239, -0.0011493041, 0.016866164, -0.0016563499, 0.017310271, -0.0021782229, 0.017605407, -0.0027028411, + 0.017754791, -0.0032187088, 0.017762953, -0.0037151384, 0.017635692, -0.0041824332, 0.017380001, -0.0046120379, + 0.017004017, -0.0049966443, 0.016516931, -0.0053302632, 0.015928905, -0.0056082504, 0.015250954, -0.0058273012, + 0.014494829, -0.0059854095, 0.013672867, -0.0060818009, 0.012797831, -0.0061168405, 0.011882732, -0.0060919276, + 0.010940637, -0.0060093803, 0.0099844718, -0.0058723139, 0.0090268105, -0.0056845243, 0.0080796788, -0.0054503735, + 0.0071543544, -0.005174689, 0.006261189, -0.0048626713, 0.0054094414, -0.0045198193, 0.0046071433, -0.0041518649, + 0.0038609891, -0.0037647239, 0.0031762596, -0.0033644575, 0.0025567838, -0.0029572411, 0.0020049347, -0.00254934, + 0.0015216633, -0.0021470881, 0.0011065686, -0.0017568644, 0.00075800065, -0.0013850661, 0.0004731935, -0.0010380755, + 0.00024842433, -0.00072221586, 0.00007919284, -0.00044369671, -0.000039584535, -0.00020854612, -0.0001133715, -0.000022529672, + -0.0001478067, 0.000108944, -0.00014850247, 0.00018093004, -0.0001208542, 0.00018906515, -0.000069866226, 0.00012969374, + -2.220446e-16, -5.5511151e-17, 0.000084950341, -0.00020185817, 0.00018195057, -0.00047661722, 0.00028878354, -0.0008237827, + 0.00040406833, -0.0012415157, 0.00052723964, -0.0017265369, 0.00065848755, -0.0022740522, 0.00079865806, -0.0028777081, + 0.00094911765, -0.0035295789, 0.0011115847, -0.0042201951, 0.0012879343, -0.0049386127, 0.0014799823, -0.0056725289, + 0.0016892579, -0.0064084502, 0.0019167721, -0.0071319067, 0.002162795, -0.0078277159, 0.0024266504, -0.0084802955, + 0.0027065387, -0.0090740146, 0.0029994014, -0.0095935827, 0.0033008344, -0.010024459, 0.0036050577, -0.01035328, + 0.003904952, -0.010568285, 0.0041921646, -0.010659733, 0.0044572824, -0.010620279, 0.0046900786, -0.01044532, + 0.0048798202, -0.010133266, 0.0050156307, -0.0096857436, 0.0050868993, -0.0091077117, 0.0050837183, -0.0084074708, + 0.0049973316, -0.0075965733, 0.0048205811, -0.0066896221, 0.0045483187, -0.0057039633, 0.0041777813, -0.0046592737, + 0.0037088934, -0.0035770566, 0.0031444894, -0.002480061, 0.0024904367, -0.0013916414, 0.0017556528, -0.0003350777, + 0.0009520037, 0.00066711544, 0.000094088718, 0.0015938688, -0.00080108939, 0.0024262008, -0.0017145583, 0.0031477951, + -0.0026259006, 0.0037454946, -0.00351385, 0.0042096875, -0.0043569384, 0.0045345738, -0.0051341685, 0.0047182986, + -0.0058256849, 0.0047629494, -0.0064134183, 0.0046744202, -0.0068816775, 0.0044621397, -0.0072176624, 0.0041386886, + -0.0074118823, 0.0037193133, -0.0074584596, 0.0032213603, -0.00735531, 0.0026636559, -0.0071041943, 0.0020658553, + -0.006710636, 0.0014477872, -0.0061837193, 0.00082882162, -0.0055357711, 0.00022728172, -0.0047819447, -0.00034007721, + -0.0039397213, -0.00085850636, -0.0030283579, -0.0013156059, -0.0020682951, -0.0017015649, -0.0010805541, -0.0020092935, + -0.000086142623, -0.0022344531, 0.00089450512, -0.0023753855, 0.0018420418, -0.0024329573, 0.0027386551, -0.0024103273, + 0.0035684374, -0.0023126558, 0.0043176766, -0.0021467698, 0.0049750544, -0.0019208054, 0.0055317623, -0.0016438378, + 0.0059815329, -0.0013255208, 0.0063205939, -0.00097574567, 0.0065475609, -0.00060433155, 0.0066632666, -0.00022075657, + 0.0066705542, 0.00016606481, 0.0065740347, 0.0005479547, 0.0063798288, 0.000917595, 0.0060953014, 0.0012686022, + 0.0057287971, 0.0015955586, 0.0052893902, 0.0018940041, 0.0047866534, 0.0021603971, 0.0042304504, 0.0023920508, + 0.0036307548, 0.0025870528, 0.0029974992, 0.0027441746, 0.0023404511, 0.0028627797, 0.0016691157, 0.0029427363, + 0.00099266251, 0.0029843359, 0.00031987071, 0.0029882274, -0.0003409097, 0.0029553634, -0.00098178594, 0.0028869633, + -0.0015953446, 0.0027844929, -0.0021746708, 0.0026496551, -0.0027133694, 0.0024843954, -0.0032055897, 0.0022909143, + -0.0036460557, 0.0020716845, -0.0040301029, 0.001829469, -0.0043537221, 0.0015673359, -0.0046136077, 0.0012886674, + -0.0048072096, 0.00099715649, -0.0049327859, 0.00069679262, -0.0049894531, 0.000391832, -0.0049772309, 0.000086752072, + -0.0048970757, -0.00021380912, -0.0047509046, -0.00050512824, -0.0045416015, -0.00078248454, -0.0042730039, -0.0010412579, + -0.0039498731, -0.0012770331, -0.0035778389, -0.0014857076, -0.0031633279, -0.0016635971, -0.0027134682, -0.001807537, + -0.0022359758, -0.0019149748, -0.0017390279, -0.0019840484, -0.0012311181, -0.0020136512, -0.00072090683, -0.0020034772, + -0.0002170627, -0.0019540484, 0.00027189584, -0.0018667208, 0.00073775765, -0.00174367, 0.0011727696, -0.0015878571, + 0.0015697783, -0.0014029766, 0.001922359, -0.0011933852, 0.0022249303, -0.00096401788, 0.0024728517, -0.00072028884, + 0.0026625025, -0.00046798357, 0.0027913428, -0.00021314165, 0.0028579531, 0.000038065922, 0.0028620549, 0.00027946298, + 0.0028045103, 0.00050499593, 0.0026873015, 0.00070886087, 0.0025134915, 0.00088562793, 0.0022871648, 0.0010303608, + 0.0020133494, 0.0011387296, 0.0016979213, 0.0012071145, 0.0013474913, 0.0012326987, 0.00096927787, 0.0012135465, + 0.00057096494, 0.001148668, 0.00016054846, 0.0010380625, -0.00025382591, 0.00088274491, -0.00066403102, 0.00068474718, + -0.0010621285, 0.0004470984, -0.001440537, 0.00017377918, -0.0017921957, -0.00013034795, -0.0021107141, -0.00045963225, + -0.0023905102, -0.00080775097, -0.0026269264, -0.0011678453, -0.0028163234, -0.0015326737, -0.002956148, -0.0018947766, + -0.003044971, -0.0022466506, -0.0030824956, -0.0025809242, -0.0030695351, -0.0028905307, -0.003007961, -0.0031688737, + -0.0029006239, -0.0034099782, -0.0027512501, -0.0036086228, -0.0025643157, -0.0037604517, -0.0023449084, -0.0038620592, + -0.0020985759, -0.0039110477, -0.0018311698, -0.003906057, -0.0015486911, -0.0038467669, -0.0012571397, -0.0037338703, + -0.00096237543, -0.0035690248, -0.00066999131, -0.003354782, -0.00038520579, -0.003094499, -0.00011277314, -0.0027922371, + 0.00014308578, -0.0024526515, 0.00037873242, -0.0020808775, 0.00059113972, -0.0016824141, 0.0007779033, -0.0012630108, + 0.00093723694, -0.00082856242, 0.0010679543, -0.00038500843, 0.0011694405, 0.000061755964, 0.0012416149, 0.00050595973, + 0.0012848899, 0.00094202528, 0.0013001257, 0.0013646283, 0.0012885842, 0.0017687485, 0.0012518835, 0.0021497128, + 0.0011919539, 0.0025032314, 0.0011109948, 0.0028254308, 0.0010114345, 0.0031128798, 0.00089589041, 0.0033626144, + 0.00076713093, 0.0035721601, 0.00062803685, 0.0037395512, 0.00048156266, 0.0038633479, 0.00033069632, 0.0039426503, + 0.00017841732, 0.0039771087, 0.000027653001, 0.0039669303, -0.00011876698, 0.0039128768, -0.00025815735, 0.0038162593, + -0.00038802426, 0.0036789209, -0.00050611183, 0.0035032146, -0.00061044592, 0.003291968, -0.00069937482, 0.0030484418, + -0.00077160395, 0.0027762763, -0.00082622346, 0.0024794317, -0.00086272735, 0.0021621194, -0.0008810226, 0.0018287286, + -0.00088142743, 0.0014837491, -0.00086465816, 0.0011316916, -0.00083180465, 0.00077700929, -0.00078429491, 0.0004240229, + -0.00072384975, 0.000076850592, -0.00065242866, -0.00026065443, -0.00057216937, -0.00058495684, -0.00048532296, -0.0008928816, + -0.00039418644, -0.0011816447, -0.00030103643, -0.0014488718, -0.00020806548, -0.0016926047, -0.0001173238, -0.0019112971, + -0.000030668409, -0.0021038, 0.000050278504, -0.0022693386, 0.00012416096, -0.0024074819, 0.00018990933, -0.0025181088, + 0.00024674923, -0.0026013714, 0.00029419933, -0.0026576561, 0.00033205902, -0.0026875495, 0.0003603872, -0.0026918037, + 0.00037947373, -0.0026713097, 0.00038980544, -0.0026270729, 0.00039202863, -0.0025601962, 0.00038691019, -0.0024718693, + 0.00037529902, -0.0023633612, 0.00035808972, -0.0022360198, 0.00033618973, -0.0020912744, 0.00031049116, -0.001930638, + 0.00028184787, -0.0017557153, 0.0002510584, -0.0015682059, 0.0002188544, -0.001369908, 0.00018589437, -0.0011627187, + 0.00015276202, -0.00094863074, 0.00011996848, -0.00072972412, 0.000087957334, -0.00050815433, 0.000057111374, -0.00028613486, + 0.000027760274, -0.00006591557, 1.8815049e-7, 0.00015024227, -0.000025359737, 0.00036009445, -0.000048671653, 0.00056144409, + -0.000069565853, 0.0007521729, -0.000087888977, 0.00093027257, -0.00010351629, 0.0010938746, -0.00011635367, 0.0012412785, + -0.0001263407, 0.0013709769, -0.0001334548, 0.0014816767, -0.0001377154, 0.001572317, -0.00013918804, 0.0016420815, + -0.00013798742, 0.0016904076, -0.00013427943, 0.0017169899, -0.0001282813, 0.0017217799, -0.00012026003, 0.0017049827, + -0.00011052855, 0.0016670482, -0.000099440098, 0.0016086611, -0.000087380431, 0.0015307277, -0.000074758427, 0.0014343602, + -0.000061995306, 0.0013208598, -0.000049512866, 0.0011916994, -0.000037721158, 0.0010485043, -0.000027006179, 0.00089303311, + -0.000017717955, 0.00072715874, -0.000010159566, 0.0005528488, -0.0000045775087, 0.00037214643, -0.0000011537802, 0.00018715112, +}; + +const float ff_on2avc_ctab_2[2048] = { + 6.1062266e-16, -0.0047176247, 0.000025801086, 0.00017171795, 0.00010278686, 0.00033237049, 0.00022971108, 0.00047108173, + 0.00040451737, 0.00057735282, 0.00062436966, 0.00064124417, 0.00088569394, 0.00065355049, 0.0011842304, 0.0006059666, + 0.0015150951, 0.00049124041, 0.0018728492, 0.00030331188, 0.0022515757, 0.000037434522, 0.0026449619, -0.00030972183, + 0.0030463862, -0.00073999004, 0.003449009, -0.0012536477, 0.0038458654, -0.0018493842, 0.0042299605, -0.0025242937, + 0.0045943661, -0.0032738955, 0.0049323193, -0.0040921802, 0.0052373176, -0.0049716844, 0.0055032219, -0.0059035895, + 0.0057243509, -0.0068778461, 0.005895582, -0.0078833178, 0.006012449, -0.0089079468, 0.0060712346, -0.0099389348, + 0.0060690674, -0.010962932, 0.0060040066, -0.01196624, 0.0058751269, -0.01293501, 0.0056825895, -0.013855449, + 0.0054277065, -0.014714016, 0.005112987, -0.015497606, 0.0047421698, -0.016193733, 0.0043202331, -0.016790686, + 0.0038533837, -0.017277677, 0.0033490176, -0.017644968, 0.0028156566, -0.017883981, 0.0022628529, -0.017987385, + 0.0017010663, -0.017949177, 0.0011415118, -0.017764734, 0.00059597875, -0.017430862, 0.000076625569, -0.016945831, + -0.00040424766, -0.016309388, -0.00083444483, -0.015522776, -0.0012021317, -0.014588747, -0.0014961021, -0.013511552, + -0.0017060443, -0.012296947, -0.0018228046, -0.010952174, -0.001838639, -0.0094859507, -0.0017474507, -0.0079084486, + -0.0015450044, -0.0062312619, -0.0012291165, -0.0044673691, -0.0007998143, -0.0026310843, -0.00025946245, -0.00073799869, + 0.00038714762, 0.0011950907, 0.0011327467, 0.003150264, 0.0019675777, 0.0051085735, 0.002879428, 0.007050151, + 0.0038537064, 0.0089543248, 0.0048735668, 0.010799746, 0.0059200767, 0.012564532, 0.0069724373, 0.014226408, + 0.0080082528, 0.015762862, 0.0090038506, 0.017151318, 0.0099346545, 0.018369311, 0.010775609, 0.019394677, + 0.011501653, 0.020205766, 0.012088243, 0.020781681, 0.012511919, 0.021102531, 0.012750908, 0.021149736, + 0.012785755, 0.020906361, 0.012599968, 0.020357504, 0.012180677, 0.019490732, 0.011519265, 0.018296573, + 0.010611986, 0.016769076, 0.0094605172, 0.014906418, 0.0080724526, 0.012711582, 0.006461692, 0.010193078, + 0.0046487241, 0.0073657078, 0.0026607637, 0.0042513679, 0.0005317349, 0.00087985705, -0.0016979208, -0.0027103117, + -0.0039816312, -0.0064711315, -0.0062672808, -0.010344372, -0.0084980074, -0.014260936, -0.010613214, -0.018140316, + -0.012549785, -0.02189021, -0.0142435, -0.02540629, -0.015630638, -0.028572179, -0.016649729, -0.031259675, + -0.017243449, -0.033329193, -0.017360613, -0.034630522, -0.016958216, -0.035003848, -0.016003506, -0.03428109, + -0.014476006, -0.032287523, -0.012369478, -0.028843746, -0.0096937334, -0.023767876, -0.0064762742, -0.016878078, + -0.0027636932, -0.0079952935, 0.0013771985, 0.0030537986, 0.0058585741, 0.016433664, 0.010571149, 0.032296669, + 0.015384134, 0.050779779, 0.020145604, 0.072001241, 0.024683299, 0.096057333, 0.028805861, 0.12301921, + 0.032304518, 0.15292998, 0.034955185, 0.18580194, 0.036520973, 0.22161427, 0.036755085, 0.26031092, + 0.035404034, 0.30179903, 0.032211188, 0.34594777, 0.026920509, 0.39258778, 0.019280523, 0.44151106, + 0.0090483893, 0.49247134, -0.004005983, 0.54518533, -0.020095825, 0.59933424, -0.039413493, 0.65456611, + -0.062126629, 0.71049863, -0.088374533, 0.76672238, -0.11826489, 0.82280493, -0.1518708, 0.87829489, + -0.18922837, 0.93272704, -0.23033462, 0.98562711, -0.27514613, 1.0365173, -0.32357812, 1.084922, + -0.37550423, 1.1303729, -0.43075687, 1.1724157, -0.48912829, 1.210615, -0.55037224, 1.2445599, + -0.61420608, 1.2738692, -0.68031394, 1.2981967, -0.74834985, 1.3172354, -0.81794167, 1.330721, + -0.8886956, 1.3384365, -0.96020055, 1.3402138, -1.0320334, 1.3359363, -1.1037641, 1.3255405, + -1.1749605, 1.3090167, -1.2451944, 1.2864087, -1.3140464, 1.257813, -1.3811105, 1.2233779, + -1.4460001, 1.1833013, -1.5083516, 1.1378273, -1.5678285, 1.0872437, -1.6241266, 1.0318775, + -1.6769751, 0.97209138, -1.7261413, 0.90827817, -1.7714316, 0.84085637, -1.8126934, 0.77026486, + -1.8498163, 0.69695753, -1.882732, 0.62139785, -1.9114146, 0.54405344, -1.9358792, 0.46539098, + -1.9561808, 0.38587096, -1.9724123, 0.3059431, -1.9847021, 0.22604167, -1.9932109, 0.14658169, + -1.9981292, 0.067955181, -1.9996731, -0.00947183, -1.9980807, -0.085361861, -1.9936082, -0.15940794, + -1.9865264, -0.23133504, -1.9771156, -0.30090088, -1.9656627, -0.36789626, -1.952457, -0.43214479, + -1.9377865, -0.49350214, -1.9219347, -0.55185497, -1.905178, -0.60711914, -1.8877819, -0.65923816, + -1.8699998, -0.70818067, -1.8520706, -0.75393814, -1.8342167, -0.79652262, -1.8166438, -0.83596373, + -1.7995393, -0.87230623, -1.7830721, -0.9056074, -1.7673923, -0.93593466, -1.7526317, -0.96336293, + -1.7389038, -0.98797268, -1.7263044, -1.0098475, -1.7149128, -1.0290729, -1.7047921, -1.0457342, + -1.6959906, -1.0599151, -1.6885422, -1.0716969, -1.6824687, -1.0811574, -1.677779, -1.0883702, + -1.6744717, -1.0934039, -1.6725357, -1.0963222, -1.67195, -1.0971831, -1.6726862, -1.0960395, + -1.6747082, -1.0929389, -1.6779734, -1.0879233, -1.6824325, -1.08103, -1.6880317, -1.0722916, + -1.6947116, -1.0617367, -1.7024086, -1.04939, -1.7110549, -1.0352732, -1.7205796, -1.0194054, + -1.730908, -1.0018036, -1.7419629, -0.9824838, -1.7536641, -0.96146131, -1.7659295, -0.93875134, + -1.7786744, -0.91437006, -1.7918122, -0.88833487, -1.8052548, -0.86066544, -1.8189124, -0.83138382, + -1.8326937, -0.80051541, -1.8465064, -0.76808912, -1.860257, -0.73413789, -1.8738515, -0.69869894, + -1.8871957, -0.66181415, -1.9001952, -0.62353003, -1.9127564, -0.58389789, -1.924787, -0.54297411, + -1.9361968, -0.50081998, -1.946898, -0.45750189, -1.9568071, -0.41309139, -1.9658449, -0.36766547, + -1.9739379, -0.32130671, -1.9810196, -0.27410358, -1.9870309, -0.22615109, -1.9919212, -0.17755121, + -1.9956495, -0.12841354, -1.9981841, -0.078856133, -1.9995037, -0.029006185, -1.9995972, 0.020999053, + -1.9984629, 0.071011581, -1.9961088, 0.12087195, -1.9925506, 0.17040877, -1.9878117, 0.21943836, + -1.9819202, 0.26776481, -1.9749084, 0.31518021, -1.9668094, 0.36146545, -1.9576563, 0.40639135, + -1.9474785, 0.44972011, -1.9363006, 0.49120751, -1.9241393, 0.53060538, -1.9110016, 0.5676645, + -1.8968834, 0.60213798, -1.8817675, 0.63378489, -1.8656229, 0.6623742, -1.8484042, 0.68768901, + -1.8300512, 0.70953059, -1.8104898, 0.7277227, -1.7896332, 0.74211556, -1.7673825, 0.75258982, + -1.7436302, 0.75905991, -1.718262, 0.76147729, -1.6911598, 0.75983286, -1.6622057, 0.75415885, + -1.6312853, 0.7445302, -1.598292, 0.73106503, -1.5631305, 0.71392417, -1.5257218, 0.69331038, + -1.4860063, 0.66946632, -1.4439477, 0.64267194, -1.3995371, 0.6132409, -1.3527952, 0.58151656, + -1.3037754, 0.54786724, -1.2525655, 0.51268071, -1.199289, 0.47635838, -1.1441054, 0.43930924, + -1.0872105, 0.40194324, -1.0288347, 0.36466473, -0.96924144, 0.32786602, -0.90872473, 0.2919209, + -0.84760505, 0.25717854, -0.7862255, 0.22395785, -0.7249468, 0.19254236, -0.66414177, 0.16317582, + -0.60418916, 0.13605864, -0.54546744, 0.11134519, -0.4883481, 0.089142092, -0.43318909, 0.069507554, + -0.38032803, 0.052451812, -0.33007616, 0.037938587, -0.28271216, 0.025887616, -0.23847705, 0.016178153, + -0.19756962, 0.0086534023, -0.16014262, 0.0031256941, -0.12630016, -0.00061766239, -0.096096113, -0.0028080596, + -0.069533631, -0.003688961, -0.046565846, -0.0035091597, -0.027097713, -0.0025161188, -0.010989046, -0.00094958977, + 0.0019415142, 0.00096430612, 0.011911541, 0.0030183611, 0.019169118, 0.0050287801, 0.023986517, 0.006838772, + 0.026653459, 0.0083211483, 0.027470166, 0.0093798656, 0.026740402, 0.0099505046, 0.0247647, 0.0099997027, + 0.021834008, 0.0095235975, 0.018223884, 0.0085453819, 0.014189421, 0.0071120788, 0.0099610332, 0.0052907071, + 0.0057411729, 0.0031639794, 0.0017020478, 0.00082572823, -0.0020156475, -0.0016237673, -0.0053030066, -0.0040823757, + -0.0080822473, -0.0064504636, -0.01030519, -0.0086348522, -0.011950996, -0.010552257, -0.013023298, -0.012132118, + -0.013546856, -0.013318742, -0.013563911, -0.014072724, -0.013130371, -0.014371663, -0.012311992, -0.014210164, + -0.011180677, -0.013599193, -0.0098110167, -0.012564868, -0.0082771704, -0.011146758, -0.0066501619, -0.0093958043, + -0.0049956408, -0.0073719709, -0.0033721365, -0.0051417369, -0.0018298116, -0.0027755348, -0.00040969814, -0.00034523915, + 0.00085661822, 0.0020782049, 0.0019469126, 0.004426945, 0.002847892, 0.0066381125, 0.0035544888, 0.0086554019, + 0.0040689427, 0.010430313, 0.0043997411, 0.011923047, 0.0045604752, 0.013103063, 0.0045686788, 0.013949312, + 0.0044446858, 0.014450175, 0.0042105624, 0.014603134, 0.0038891311, 0.014414242, 0.0035031161, 0.01389739, + 0.0030744188, 0.01307346, 0.0026235317, 0.011969374, 0.0021690836, 0.010617082, 0.0017275107, 0.009052542, + 0.0013128433, 0.0073146918, 0.00093659078, 0.0054444592, 0.0006077115, 0.0034838144, 0.00033265035, 0.0014748911, + 0.00011543075, -0.00054083008, -0.000042213407, -0.0025232558, -0.00014067636, -0.0044343388, -0.00018229883, -0.0062386589, + -0.00017117237, -0.0079039233, -0.00011293451, -0.0094013978, -0.000014556788, -0.010706257, 0.00011587302, -0.011797872, + 0.00026937437, -0.012660023, 0.00043630364, -0.013281046, 0.0006065903, -0.013653914, 0.00076997973, -0.013776246, + 0.00091628113, -0.013650244, 0.0010356199, -0.013282579, 0.0011186899, -0.012684184, 0.0011570023, -0.011869996, + 0.0011431255, -0.010858623, 0.0010709089, -0.0096719572, 0.00093568477, -0.0083347168, 0.00073444104, -0.0068739466, + 0.00046595652, -0.0053184745, 0.00013089461, -0.0036983292, -0.00026815146, -0.002044142, -0.00072666444, -0.00038653665, + -0.001238263, 0.0012444736, -0.0017948141, 0.0028200729, -0.0023865986, 0.0043131965, -0.0030025232, 0.0056990399, + -0.0036303743, 0.0069555123, -0.0042571067, 0.0080636218, -0.0048691588, 0.0090077901, -0.0054527833, 0.0097760875, + -0.0059943851, 0.010360379, -0.0064808549, 0.010756395, -0.0068998942, 0.010963713, -0.0072403145, 0.010985666, + -0.0074923136, 0.010829174, -0.0076477141, 0.010504506, -0.0077001643, 0.010024985, -0.0076453011, 0.0094066458, + -0.0074808616, 0.0086678378, -0.0072067594, 0.0078288056, -0.0068251076, 0.0069112377, -0.0063402043, 0.0059377975, + -0.0057584713, 0.0049316445, -0.0050883559, 0.0039159562, -0.004340189, 0.0029134497, -0.0035260066, 0.0019459217, + -0.002659336, 0.001033804, -0.0017549467, 0.00019574871, -0.00082857109, -0.00055175176, 0.00010340517, -0.0011947021, + 0.0010242764, -0.0017218908, 0.0019173701, -0.0021251177, 0.0027664138, -0.0023993575, 0.0035559093, -0.0025428517, + 0.0042715017, -0.0025571233, 0.0049003414, -0.0024469129, 0.0054314188, -0.0022200351, 0.0058558695, -0.0018871534, + 0.0061672316, -0.0014614828, 0.0063616517, -0.00095842173, 0.0064380248, -0.00039512504, 0.0063980608, 0.00020997033, + 0.0062462785, 0.00083765347, 0.0059899129, 0.0014684666, 0.005638747, 0.0020832333, 0.0052048638, 0.0026635726, + 0.0047023292, 0.0031923822, 0.0041468102, 0.0036542746, 0.0035551451, 0.0040359539, 0.0029448776, 0.0043265228, + 0.0023337679, 0.0045177112, 0.0017393016, 0.0046040174, 0.001178207, 0.0045827716, 0.00066600286, 0.0044541075, + 0.00021658542, 0.004220861, -0.0001581293, 0.0038883933, -0.0004484996, 0.0034643558, -0.00064738019, 0.0029584002, + -0.00075026811, 0.0023818521, -0.000755371, 0.0017473593, -0.00066359824, 0.0010685247, -0.00047847957, 0.00035953996, + -0.00020601597, -0.00036517272, 0.00014552828, -0.0010913002, 0.00056588452, -0.0018049506, 0.001043079, -0.0024929349, + 0.0015637625, -0.0031430104, 0.0021135611, -0.003744086, 0.0026774362, -0.0042863889, 0.0032400466, -0.0047615874, + 0.0037861052, -0.0051628826, 0.0043007191, -0.005485056, 0.0047697132, -0.0057244869, 0.0051799244, -0.00587914, + 0.0055194702, -0.0059485212, 0.0057779811, -0.0059336093, 0.005946802, -0.0058367676, 0.006019149, -0.0056616301, + 0.0059902342, -0.0054129749, 0.0058573456, -0.0050965813, 0.0056198868, -0.0047190739, 0.0052793743, -0.0042877593, + 0.0048393975, -0.0038104532, 0.0043055299, -0.0032953112, 0.0036852097, -0.0027506526, 0.0029875766, -0.002184795, + 0.0022232747, -0.0016058958, 0.0014042265, -0.0010218052, 0.00054337748, -0.00043993912, -0.00034557868, 0.00013282956, + -0.0012484904, 0.00069025467, -0.0021510462, 0.0012267748, -0.0030390718, 0.0017375433, -0.0038988206, 0.0022184309, + -0.0047172462, 0.0026660003, -0.0054822522, 0.0030774584, -0.0061829095, 0.0034505837, -0.0068096397, 0.0037836414, + -0.0073543512, 0.004075285, -0.0078105354, 0.0043244553, -0.008173313, 0.0045302799, -0.0084394356, 0.0046919878, + -0.0086072432, 0.004808831, -0.0086765829, 0.00488004, -0.0086486926, 0.0049047922, -0.0085260663, 0.004882222, + -0.0083122877, 0.0048114532, -0.0080118719, 0.0046916641, -0.0076300949, 0.0045221797, -0.0071728369, 0.0043025846, + -0.0066464432, 0.0040328531, -0.0060576024, 0.0037134863, -0.0054132543, 0.0033456483, -0.0047205254, 0.0029312912, + -0.0039866935, 0.0024732621, -0.0032191742, 0.0019753794, -0.0024255351, 0.0014424763, -0.001613521, 0.0008803992, + -0.00079109054, 0.00029596357, 0.00003354808, -0.00030313883, 0.00085190887, -0.00090847781, 0.001655216, -0.0015110652, + 0.0024344153, -0.0021015715, 0.0031802151, -0.002670571, 0.0038831618, -0.0032088049, 0.00453375, -0.0037074534, + 0.0051225699, -0.0041584023, 0.0056404881, -0.0045544938, 0.0060788556, -0.0048897523, 0.0064297421, -0.0051595722, + 0.0066861785, -0.005360858, 0.006842406, -0.0054921173, 0.0068941191, -0.0055534914, 0.0068386863, -0.0055467347, + 0.0066753477, -0.0054751309, 0.0064053647, -0.005343359, 0.0060321307, -0.0051573105, 0.0055612195, -0.0049238643, + 0.0050003757, -0.0046506319, 0.0043594413, -0.0043456783, 0.0036502162, -0.0040172371, 0.002886259, -0.0036734226, + 0.0020826256, -0.0033219547, 0.0012555593, -0.002969909, 0.00042213459, -0.0026234936, -0.0004001323, -0.0022878707, + -0.0011936954, -0.0019670199, -0.0019414022, -0.0016636539, -0.0026269152, -0.0013791855, -0.0032351194, -0.0011137482, + -0.0037525038, -0.00086626812, -0.0041675051, -0.00063458277, -0.0044708052, -0.00041560392, -0.0046555689, -0.00020551546, +}; + +const float ff_on2avc_ctab_3[2048] = { + -1.6653345e-16, -0.0028429052, -0.000042537456, 0.00019487554, -0.00016862253, 0.00040306276, -0.00037372447, 0.00063729816, + -0.0006504606, 0.00090918731, -0.00098884385, 0.0012286865, -0.0013766177, 0.0016036412, -0.0017996682, 0.0020393939, + -0.0022425, 0.0025384782, -0.0026887599, 0.0031004087, -0.0031217942, 0.0037215743, -0.0035252157, 0.0043952391, + -0.0038834687, 0.0051116538, -0.0041823699, 0.005858277, -0.0044096061, 0.0066200914, -0.0045551774, 0.0073800222, + -0.0046117627, 0.0081194276, -0.0045750043, 0.0088186627, -0.0044436962, 0.0094576869, -0.0042198659, 0.010016704, + -0.0039087553, 0.010476815, -0.0035186927, 0.010820654, -0.0030608606, 0.011033002, -0.002548967, 0.011101345, + -0.001998829, 0.011016356, -0.0014278793, 0.010772308, -0.00085461611, 0.01036737, -0.00029800553, 0.0098037962, + 0.00022313831, 0.0090879966, 0.00069077854, 0.0082304832, 0.001088266, 0.0072456878, 0.0014009145, 0.0061516552, + 0.0016165223, 0.0049696299, 0.0017258222, 0.0037235275, 0.0017228439, 0.002439322, 0.0016051769, 0.0011443575, + 0.0013741244, -0.0001333931, 0.0010347385, -0.001366102, 0.00059573731, -0.0025268681, 0.00006930346, -0.0035904851, + -0.00052923308, -0.0045341686, -0.001181817, -0.0053382241, -0.0018681852, -0.0059866291, -0.0025664624, -0.0064675175, + -0.0032538211, -0.0067735398, -0.0039071804, -0.0069020987, -0.0045039295, -0.0068554399, -0.0050226445, -0.0066406005, + -0.0054437858, -0.0062692142, -0.0057503423, -0.0057571726, -0.0059284149, -0.0051241596, -0.0059677036, -0.0043930644, + -0.0058618966, -0.003589293, -0.0056089377, -0.0027400018, -0.0052111652, -0.0018732708, -0.0046753148, -0.0010172459, + -0.0040123845, -0.00019927412, -0.0032373657, 0.00055493839, -0.0023688413, 0.0012221204, -0.0014284686, 0.0017821564, + -0.00044035583, 0.00221871, 0.00056964607, 0.0025197288, 0.0015747172, 0.002677816, 0.0025478832, 0.0026904519, + 0.003462845, 0.0025600623, 0.0042947996, 0.0022939243, 0.0050212229, 0.0019039178, 0.0056225881, 0.0014061241, + 0.0060830046, 0.00082028762, 0.0063907388, 0.00016915375, 0.0065386193, -0.00052229298, 0.0065242914, -0.0012276688, + 0.0063503282, -0.001920081, 0.00602418, -0.0025730385, 0.0055579683, -0.0031613547, 0.0049681277, -0.0036620118, + 0.0042749047, -0.0040549575, 0.0035017261, -0.0043238075, 0.0026744606, -0.0044564288, 0.0018205947, -0.0044453838, + 0.00096834335, -0.0042882231, 0.00014573456, -0.0039876048, -0.0006203127, -0.003551251, -0.0013048799, -0.0029917257, + -0.0018858829, -0.0023260501, -0.0023448193, -0.0015751625, -0.0026674026, -0.00076324248, -0.0028440619, 0.000083084451, + -0.0028702877, 0.00093562948, -0.00274681, 0.0017655863, -0.0024796019, 0.002544506, -0.0020797059, 0.0032452703, + -0.001562885, 0.0038430272, -0.00094911043, 0.0043160599, -0.00026189955, 0.0046465569, 0.00047247464, 0.0048212567, + 0.001225878, 0.0048319423, 0.0019692846, 0.0046757692, 0.0026737878, 0.0043554134, 0.0033116213, 0.0038790288, + 0.0038571535, 0.0032600202, 0.0042878226, 0.0025166313, 0.0045849765, 0.0016713619, 0.004734592, 0.00075023499, + 0.0047278423, -0.00021806663, 0.0045614946, -0.0012031641, 0.0042381193, -0.0021740133, 0.003766102, -0.0030999696, + 0.0031594534, -0.0039518503, 0.0024374237, -0.0047029546, 0.0016239271, -0.0053300103, 0.00074679783, -0.0058140075, + -0.00016310361, -0.0061408947, -0.0010729014, -0.0063021071, -0.0019488039, -0.0062949071, -0.0027572513, -0.0061225249, + -0.0034660769, -0.0057940902, -0.0040456373, -0.0053243539, -0.0044698785, -0.0047332067, -0.0047172923, -0.0040450124, + -0.0047717378, -0.0032877706, -0.0046230876, -0.0024921419, -0.0042676828, -0.0016903625, -0.0037085724, -0.00091508962, + -0.0029555273, -0.0001982145, -0.0020248254, 0.00043031544, -0.00093881134, 0.00094362238, 0.00027475748, 0.0013189322, + 0.0015835584, 0.0015384787, 0.0029517193, 0.001590244, 0.0043409695, 0.0014685061, 0.005711888, 0.001174171, + 0.0070252069, 0.0007148743, 0.0082431259, 0.00010484495, 0.0093305949, -0.00063546957, 0.010256512, -0.0014800054, + 0.010994808, -0.0023978967, 0.011525363, -0.0033544756, 0.01183473, -0.0043124277, 0.011916637, -0.0052330629, + 0.011772243, -0.0060776612, 0.011410139, -0.0068088472, 0.010846091, -0.0073919417, 0.010102529, -0.0077962507, + 0.0092077944, -0.0079962341, 0.0081951711, -0.0079725226, 0.0071017356, -0.0077127367, 0.0059670559, -0.0072120731, + 0.0048317886, -0.0064736474, 0.0037362196, -0.0055085579, 0.0027188035, -0.0043356786, 0.0018147465, -0.0029811764, + 0.001054692, -0.0014777631, 0.00046354943, 0.00013628764, 0.000059517231, 0.0018183383, -0.00014666733, 0.0035227551, + -0.00015221786, 0.0052024024, 0.000037492653, 0.0068102139, 0.00040901723, 0.008300784, 0.00094121607, 0.0096319281, + 0.0016059257, 0.010766147, 0.002368897, 0.011671957, 0.0031909735, 0.012325018, 0.0040294742, 0.012709031, + 0.0048397309, 0.012816358, 0.0055767358, 0.012648351, 0.0061968337, 0.01221535, 0.0066594072, 0.011536373, + 0.0069284872, 0.010638482, 0.0069742394, 0.0095558539, 0.0067742579, 0.0083285747, 0.0063146283, 0.0070012063, + 0.0055907099, 0.0056211669, 0.0046076039, 0.0042369836, 0.0033802853, 0.0028964775, 0.0019333874, 0.0016449478, + 0.00030063081, 0.00052342116, -0.0014760793, -0.0004329654, -0.0033478751, -0.0011963865, -0.0052604238, -0.0017474962, + -0.0071556596, -0.0020762917, -0.0089736925, -0.0021826318, -0.010654833, -0.0020763816, -0.012141662, -0.0017771672, + -0.013381075, -0.0013137354, -0.014326238, -0.00072293397, -0.014938361, -0.000048335231, -0.015188256, 0.00066145579, + -0.015057592, 0.0013547561, -0.014539802, 0.0019789573, -0.013640625, 0.0024828047, -0.012378214, 0.002818716, + -0.01078283, 0.0029450601, -0.0088961152, 0.0028283037, -0.0067699435, 0.0024449378, -0.0044648955, 0.0017831039, + -0.002048397, 0.00084384187, 0.00040742956, -0.00035810683, 0.0028281235, -0.0017939941, 0.0051393877, -0.0034212973, + 0.0072696419, -0.0051845112, 0.0091525484, -0.0070165028, 0.010729411, -0.0088404194, 0.011951371, -0.010572106, + 0.01278131, -0.012122994, 0.013195385, -0.013403381, 0.013184131, -0.01432602, 0.01275308, -0.014809915, + 0.011922853, -0.01478422, 0.010728708, -0.01419212, 0.0092195272, -0.012994564, 0.0074562789, -0.011173738, + 0.0055099544, -0.0087361531, 0.0034590533, -0.0057152319, 0.0013866695, -0.0021732997, -0.00062274013, 0.0017971178, + -0.0024868115, 0.0060727512, -0.0041288515, 0.010499856, -0.0054814275, 0.014895321, -0.0064898543, 0.019048614, + -0.0071154684, 0.022724561, -0.0073385658, 0.025666898, -0.0071609118, 0.027602537, -0.0066077164, 0.028246468, + -0.0057289964, 0.027307168, -0.004600253, 0.0244924, -0.0033224206, 0.019515269, -0.0020210496, 0.012100382, + -0.00084472145, 0.0019899437, 0.000037296293, -0.01105034, 0.00043811565, -0.027225735, 0.00015696014, -0.046707455, + -0.0010165154, -0.069628276, -0.0032974123, -0.096078917, -0.0069003948, -0.12610528, -0.01203424, -0.15970659, + -0.018896269, -0.19683464, -0.027666792, -0.23739384, -0.038503725, -0.28124255, -0.051537503, -0.32819515, + -0.06686642, -0.3780252, -0.084552586, -0.43046936, -0.10461849, -0.48523226, -0.12704438, -0.54199159, + -0.15176651, -0.60040426, -0.17867628, -0.66011244, -0.20762028, -0.72074997, -0.23840135, -0.7819488, + -0.27078056, -0.8433454, -0.30448011, -0.90458667, -0.33918688, -0.96533567, -0.37455717, -1.0252765, + -0.41022155, -1.0841192, -0.44579068, -1.1416026, -0.48086143, -1.1974978, -0.51502305, -1.2516102, + -0.54786384, -1.3037796, -0.57897753, -1.3538816, -0.60796958, -1.4018263, -0.63446349, -1.4475567, + -0.65810603, -1.4910469, -0.67857265, -1.5322988, -0.6955719, -1.571339, -0.70884931, -1.6082149, + -0.71819037, -1.6429906, -0.72342294, -1.6757429, -0.72441858, -1.7065566, -0.72109336, -1.7355207, + -0.71340775, -1.7627244, -0.70136583, -1.7882535, -0.68501353, -1.8121873, -0.664437, -1.8345959, + -0.63975936, -1.8555384, -0.61113822, -1.8750609, -0.5787617, -1.8931965, -0.54284513, -1.9099646, + -0.50362706, -1.9253712, -0.46136531, -1.9394104, -0.41633323, -1.9520659, -0.36881575, -1.9633123, + -0.31910598, -1.9731183, -0.26750168, -1.9814487, -0.21430217, -1.9882675, -0.15980564, -1.9935409, + -0.1043066, -1.9972394, -0.048093725, -1.9993412, 0.0085518388, -1.9998351, 0.06535802, -1.9987217, + 0.12206294, -1.9960158, 0.17841578, -1.9917485, 0.23417741, -1.9859674, 0.28912079, -1.978738, + 0.34303114, -1.9701437, 0.39570591, -1.9602853, 0.44695485, -1.9492812, 0.49659961, -1.9372654, + 0.54447347, -1.924387, 0.59042108, -1.9108082, 0.63429779, -1.8967023, 0.6759693, -1.8822519, + 0.71531093, -1.8676466, 0.7522071, -1.8530809, 0.78655046, -1.8387512, 0.81824118, -1.8248546, + 0.84718591, -1.8115855, 0.87329692, -1.799134, 0.89649087, -1.7876834, 0.91668761, -1.7774082, + 0.93380904, -1.7684723, 0.94777751, -1.7610264, 0.95851475, -1.7552065, 0.96594018, -1.7511318, + 0.96996975, -1.7489027, 0.9705146, -1.7485988, 0.96748, -1.7502769, 0.96076453, -1.7539688, + 0.95025921, -1.7596794, 0.93584764, -1.7673841, 0.91740602, -1.7770265, 0.8948037, -1.788517, + 0.86790472, -1.8017294, 0.83656931, -1.8164997, 0.80065662, -1.8326236, 0.76002777, -1.8498554, + 0.71454966, -1.8679065, 0.66409934, -1.8864441, 0.60856909, -1.9050918, 0.54787195, -1.9234295, + 0.48194784, -1.9409947, 0.41076976, -1.9572846, 0.33435044, -1.9717588, 0.25274888, -1.9838443, + 0.16607688, -1.9929391, 0.07450521, -1.9984198, -0.021730689, -1.999648, -0.12232572, -1.9959785, + -0.22690098, -1.9867691, -0.33500072, -1.9713904, -0.44609061, -1.9492363, -0.55955714, -1.9197356, + -0.67470908, -1.8823639, -0.79077995, -1.8366553, -0.90693277, -1.7822139, -1.0222664, -1.718726, + -1.1358232, -1.64597, -1.2465994, -1.5638269, -1.3535558, -1.4722892, -1.4556309, -1.3714676, + -1.5517555, -1.2615976, -1.6408671, -1.1430426, -1.7219268, -1.016296, -1.7939352, -0.88198137, + -1.8559498, -0.7408486, -1.9071014, -0.59376967, -1.9466108, -0.44173092, -1.9738038, -0.28582337, + -1.9881259, -0.12723051, -1.9891552, 0.032785702, -1.976613, 0.19290088, -1.9503736, 0.35174593, + -1.9104701, 0.50792599, -1.8570991, 0.6600405, -1.7906219, 0.80670393, -1.7115632, 0.94656676, + -1.6206069, 1.0783361, -1.518589, 1.2007964, -1.4064881, 1.3128283, -1.2854123, 1.4134272, + -1.1565856, 1.5017194, -1.0213295, 1.5769756, -0.8810457, 1.6386244, -0.73719448, 1.6862605, + -0.5912739, 1.7196511, -0.44479746, 1.7387406, -0.2992714, 1.74365, -0.15617253, 1.734675, + -0.016926099, 1.7122809, 0.11711492, 1.677093, 0.24468948, 1.629887, 0.36464623, 1.5715742, + 0.47595924, 1.5031863, 0.57774144, 1.4258577, 0.66925532, 1.3408059, 0.74992096, 1.2493112, + 0.81932145, 1.1526958, 0.87720448, 1.0523019, 0.92348218, 0.94947082, 0.95822722, 0.84552169, + 0.98166639, 0.74173182, 0.99417198, 0.63931787, 0.99625009, 0.53941888, 0.98852777, 0.44308114, + 0.97173774, 0.35124525, 0.94670212, 0.2647354, 0.91431493, 0.18425134, 0.87552404, 0.11036279, + 0.83131295, 0.04350647, 0.78268248, -0.016014282, 0.7306332, -0.068027422, 0.67614836, -0.11248776, + 0.62017834, -0.1494704, 0.56362599, -0.17916223, 0.50733423, -0.20185167, 0.45207494, -0.21791716, + 0.39854008, -0.22781442, 0.34733471, -0.2320631, 0.29897237, -0.23123281, 0.25387216, -0.22592908, + 0.21235825, -0.21677956, 0.17466106, -0.20442055, 0.14092025, -0.1894843, 0.11118954, -0.17258726, + 0.085442781, -0.15431944, 0.06358128, -0.13523506, 0.04544213, -0.11584474, 0.030807279, -0.096609004, + 0.01941302, -0.077933475, 0.010959785, -0.060165603, 0.005121904, -0.043592878, 0.0015571543, -0.028442509, + -0.000084115498, -0.014882491, -0.00015046289, -0.003023857, 0.0010184186, 0.0070759403, 0.0030985889, 0.01540874, + 0.0057877772, 0.022010626, 0.0088102622, 0.026956297, 0.011920679, 0.030353062, 0.014906751, 0.032334596, + 0.017590966, 0.033054668, 0.019831251, 0.032680977, 0.021520695, 0.031389244, 0.022586443, 0.029357675, + 0.022987815, 0.026761938, 0.02271381, 0.023770688, 0.021780089, 0.020541752, 0.020225555, 0.017218968, + 0.018108679, 0.013929741, 0.015503671, 0.010783297, 0.012496619, 0.0078696031, 0.0091816904, 0.0052589499, + 0.0056575048, 0.0030021123, 0.0020237456, 0.0011310551, -0.0016219205, -0.00033990419, -0.0051865601, -0.0014125451, + -0.0085842935, -0.0021028898, -0.011738192, -0.0024391229, -0.01458175, -0.0024593701, -0.017059926, -0.002209408, + -0.019129775, -0.001740378, -0.020760702, -0.0011065705, -0.021934342, -0.00036333143, -0.022644157, 0.00043485823, + -0.022894738, 0.0012360946, -0.022700895, 0.0019925251, -0.022086568, 0.0026615674, -0.021083612, 0.0032068638, + -0.019730492, 0.0035989694, -0.018070942, 0.0038157802, -0.01615262, 0.0038427161, -0.014025783, 0.0036726766, + -0.011742038, 0.0033057902, -0.0093531534, 0.0027489865, -0.0069099898, 0.0020154165, -0.0044615306, 0.0011237526, + -0.0020540373, 0.000097393946, 0.00026966495, -0.0010363915, 0.0024707811, -0.002247364, 0.0045150127, -0.0035032234, + 0.0063729058, -0.0047705099, 0.0080200844, -0.0060154819, 0.0094373813, -0.0072049443, 0.010610872, -0.0083070258, + 0.011531814, -0.0092918845, 0.012196518, -0.010132339, 0.01260614, -0.010804415, 0.012766409, -0.011287811, + 0.012687304, -0.011566276, 0.01238268, -0.011627889, 0.011869849, -0.011465268, 0.011169123, -0.011075674, + 0.010303336, -0.010461045, 0.0092973243, -0.009627942, 0.0081774024, -0.0085874097, 0.00697082, -0.0073547787, + 0.0057052155, -0.0059493748, 0.0044080694, -0.0043941792, 0.0031061731, -0.0027154128, 0.0018251112, -0.00094207097, + 0.00058877678, 0.00089459657, -0.00058107794, 0.0027616499, -0.0016652432, 0.0046250583, -0.0026473978, 0.0064503294, + -0.0035143902, 0.0082031535, -0.0042564487, 0.0098500587, -0.004867312, 0.011359059, -0.0053442805, 0.012700289, + -0.0056881784, 0.013846606, -0.005903231, 0.014774157, -0.005996861, 0.015462888, -0.0059794001, 0.015896989, + -0.0058637299, 0.01606526, -0.0056648538, 0.015961399, -0.0053994185, 0.01558418, -0.0050851903, 0.014937551, + -0.0047405036, 0.014030606, -0.0043836995, 0.012877463, -0.0040325602, 0.011497032, -0.0037037728, 0.0099126762, + -0.0034124162, 0.0081517817, -0.0031715068, 0.0062452359, -0.0029916021, 0.0042268233, -0.0028804804, 0.002132565, +}; + +const float ff_on2avc_ctab_4[2048] = { + 0.0, 1.9999924, -0.0000058932724, -0.00018632905, -0.000023430526, -0.00036967263, -0.000052186413, -0.00054710143, + -0.000091459828, -0.00071579742, -0.00014028551, -0.00087310647, -0.00019745006, -0.0010165883, -0.00026151221, -0.0011440613, + -0.00033082708, -0.0012536434, -0.00040357397, -0.0013437853, -0.00047778775, -0.0014132988, -0.00055139291, -0.0014613763, + -0.0006222403, -0.0014876042, -0.00068814593, -0.0014919674, -0.00074693147, -0.0014748453, -0.00079646555, -0.0014370022, + -0.00083470601, -0.0013795681, -0.00085974159, -0.001304013, -0.00086983346, -0.0012121156, -0.00086345506, -0.0011059257, + -0.00083932967, -0.00098772196, -0.00079646567, -0.00085996656, -0.00073418743, -0.0007252564, -0.00065216236, -0.00058627356, + -0.00055042218, -0.00044573518, -0.0004293785, -0.00030634343, -0.00028983151, -0.00017073752, -0.00013297109, -0.000041447816, + 0.000039629722, 0.000079147045, 0.00022602957, 0.00018885947, 0.00042394208, 0.00028572831, 0.00063076714, 0.0003680501, + 0.00084363052, 0.00043440601, 0.0010594303, 0.00048368447, 0.0012748899, 0.0005150995, 0.0014866164, 0.0005282049, + 0.0016911632, 0.00052290427, 0.0018850935, 0.00049945683, 0.0020650467, 0.00045847919, 0.0022278025, 0.00040094266, + 0.0023703419, 0.00032816609, 0.0024899046, 0.00024180381, 0.0025840413, 0.0001438281, 0.0026506572, 0.00003650627, + 0.0026880486, -0.000077628843, 0.002694932, -0.00019581451, 0.0026704618, -0.00031510059, 0.002614242, -0.00043239864, + 0.0025263282, -0.0005445375, 0.0024072223, -0.00064832467, 0.0022578605, -0.00074061239, 0.0020795963, -0.00081836781, + 0.0018741783, -0.00087874458, 0.0016437257, -0.0009191549, 0.0013906998, -0.00093733944, 0.0011178757, -0.0009314327, + 0.0008283116, -0.00090002158, 0.0005253178, -0.00084219524, 0.0002124242, -0.00075758353, -0.00010665277, -0.00064638274, + -0.0004280459, -0.00050936721, -0.00074777508, -0.00034788603, -0.0010617886, -0.00016384445, -0.0013660089, 0.000040329032, + -0.0016563823, 0.00026172952, -0.001928934, 0.0004970344, -0.0021798278, 0.00074257207, -0.0024054295, 0.00099439803, + -0.0026023739, 0.0012483762, -0.0027676339, 0.0015002612, -0.0028985876, 0.0017457816, -0.0029930845, 0.0019807185, + -0.0030495061, 0.0022009795, -0.0030668175, 0.0024026663, -0.0030446108, 0.002582133, -0.0029831338, 0.0027360369, + -0.0028833048, 0.0028613801, -0.0027467103, 0.0029555426, -0.002575587, 0.0030163093, -0.0023727834, 0.0030418884, + -0.0021417083, 0.0030309267, -0.00188626, 0.0029825219, -0.001610745, 0.0028962295, -0.0013197823, 0.0027720702, + -0.0010182032, 0.002610537, -0.00071094313, 0.0024125993, -0.00040293398, 0.0021797076, -0.000098998527, 0.0019137961, + 0.00019625042, 0.0016172826, 0.0004785021, 0.0012930647, 0.00074382918, 0.00094451016, 0.00098875654, 0.00057544146, + 0.0012103159, 0.00019011059, 0.0014060856, -0.00020683407, 0.0015742163, -0.00061039196, 0.0017134408, -0.001015265, + 0.0018230709, -0.0014159229, 0.0019029821, -0.0018066789, 0.0019535855, -0.0021817745, 0.0019757913, -0.0025354712, + 0.0019709636, -0.002862151, 0.0019408683, -0.0031564159, 0.0018876162, -0.0034131943, 0.0018136023, -0.003627843, + 0.0017214427, -0.0037962461, 0.0016139107, -0.0039149108, 0.0014938725, -0.0039810524, 0.0013642251, -0.0039926702, + 0.0012278357, -0.0039486135, 0.001087485, -0.0038486305, 0.0009458157, -0.0036934058, 0.00080528553, -0.0034845807, + 0.00066812726, -0.0032247561, 0.0005363166, -0.0029174781, 0.00041154691, -0.0025672072, 0.00029521331, -0.0021792662, + 0.00018840475, -0.0017597722, 0.000091904491, -0.0013155513, 0.0000061986657, -0.00085403392, -0.000068508154, -0.00038313636, + -0.00013227122, 0.000088872715, -0.00018537903, 0.00055351778, -0.00022832313, 0.0010022718, -0.00026176605, 0.0014267182, + -0.0002865085, 0.0018187162, -0.00030345729, 0.002170566, -0.00031359497, 0.0024751695, -0.00031795207, 0.0027261837, + -0.0003175826, 0.0029181617, -0.00031354246, 0.0030466772, -0.00030687143, 0.0031084325, -0.00029857742, 0.0031013431, + -0.00028962348, 0.0030245974, -0.00028091561, 0.0028786955, -0.00027329178, 0.0026654552, -0.00026751086, 0.0023879989, + -0.00026424107, 0.0020507087, -0.0002640482, 0.0016591615, -0.0002673828, 0.0012200392, -0.00027456757, 0.00074101909, + -0.00028578506, 0.00023064682, -0.00030106661, -0.00030180693, -0.00032028355, -0.00084650156, -0.00034314199, -0.0013931919, + -0.00036918154, -0.0019314003, -0.00039777948, -0.002450594, -0.00042816071, -0.0029403649, -0.00045941351, -0.0033906079, + -0.00049051136, -0.0037916978, -0.00052034017, -0.0041346624, -0.00054773013, -0.0044113463, -0.00057149079, -0.0046145683, + -0.00059044833, -0.0047382633, -0.00060348323, -0.0047776136, -0.00060956669, -0.0047291601, -0.00060779473, -0.0045908964, + -0.00059741817, -0.0043623378, -0.00057786785, -0.0040445696, -0.00054877391, -0.0036402657, -0.00050997949, -0.0031536825, + -0.00046154787, -0.0025906207, -0.0004037637, -0.0019583604, -0.00033712928, -0.0012655669, -0.00026235546, -0.0005221676, + -0.0001803489, 0.00026079561, -0.000092195645, 0.0010713381, 8.5773814e-7, 0.001896725, 0.000097425305, 0.0027236806, + 0.00019600448, 0.0035386102, 0.00029500009, 0.0043278327, 0.00039274961, 0.0050778165, 0.00048754914, 0.0057754163, + 0.00057768018, 0.0064081079, 0.00066143664, 0.0069642127, 0.00073715224, 0.0074331141, 0.00080322672, 0.0078054559, + 0.00085815141, 0.0080733243, 0.00090053247, 0.0082304087, 0.00092911115, 0.0082721328, 0.00094278029, 0.0081957681, + 0.0009405961, 0.0080005014, 0.00092178461, 0.0076874876, 0.00088574266, 0.0072598509, 0.00083203381, 0.0067226603, + 0.00076037919, 0.0060828608, 0.00067064527, 0.0053491686, 0.0005628299, 0.0045319302, 0.00043704818, 0.0036429393, + 0.00029352194, 0.0026952275, 0.00013257378, 0.0017028196, -0.000045370962, 0.00068046764, -0.00023977279, -0.00035663525, + -0.00044995558, -0.0013931503, -0.00067507266, -0.0024138922, -0.00091406191, -0.0034041218, -0.0011655915, -0.0043498254, + -0.0014279993, -0.0052379691, -0.0016992289, -0.0060567264, -0.0019767685, -0.0067956652, -0.0022575972, -0.0074458965, + -0.0025381455, -0.0080001755, -0.0028142736, -0.0084529584, -0.0030812761, -0.0088004144, -0.0033339155, -0.0090403967, + -0.0035664875, -0.0091723735, -0.0037729202, -0.0091973282, -0.0039469078, -0.0091176452, -0.0040820716, -0.0089369677, + -0.004172151, -0.0086600557, -0.0042112102, -0.0082926471, -0.0041938564, -0.0078413244, -0.0041154595, -0.0073133917, + -0.0039723613, -0.0067167743, -0.0037620636, -0.0060599349, -0.0034833867, -0.0053518065, -0.0031365866, -0.0046017431, + -0.0027234256, -0.0038194789, -0.002247188, -0.0030150977, -0.001712642, -0.0021989932, -0.0011259451, -0.0013818274, + -0.00049449678, -0.00057446648, 0.00017325579, 0.00021210148, 0.0008680491, 0.00096687989, 0.0015800633, 0.0016790066, + 0.0022991966, 0.0023379293, 0.0030153422, 0.0029336107, 0.0037186535, 0.0034567595, 0.0043997848, 0.0038990804, + 0.0050500971, 0.0042535327, 0.0056618182, 0.0045145866, 0.0062281508, 0.0046784664, 0.006743324, 0.0047433623, + 0.0072025894, 0.0047096047, 0.0076021603, 0.0045797802, 0.0079391068, 0.0043587871, 0.0082112048, 0.004053812, + 0.0084167644, 0.0036742303, 0.0085544325, 0.0032314239, 0.0086230049, 0.0027385168, 0.008621241, 0.0022100355, + 0.0085477121, 0.0016615022, 0.008400687, 0.0011089721, 0.0081780711, 0.00056853076, 0.0078773974, 0.000055770324, + 0.0074958913, -0.00041473741, 0.007030596, -0.00082994968, 0.006478562, -0.0011788219, 0.0058371006, -0.0014527178, + 0.0051040803, -0.0016457422, 0.0042782673, -0.001754979, 0.0033596819, -0.0017806236, 0.0023499657, -0.0017259984, + 0.0012527303, -0.001597449, 0.000073873452, -0.0014041185, -0.0011781569, -0.001157607, -0.0024921719, -0.00087152363, + -0.0038541388, -0.00056094711, -0.005247179, -0.00024181118, -0.0066516823, 0.000069761314, -0.0080455355, 0.00035815299, + -0.0094044767, 0.00060894678, -0.010702565, 0.00080959394, -0.011912759, 0.00095002784, -0.013007595, 0.0010231955, + -0.013959945, 0.0010254832, -0.014743825, 0.00095701526, -0.015335241, 0.0008218062, -0.015713034, 0.00062775693, + -0.015859697, 0.0003864867, -0.015762128, 0.00011300056, -0.015412294, -0.00017480124, -0.014807777, -0.00045675918, + -0.01395216, -0.00071121694, -0.012855255, -0.00091588532, -0.01153313, -0.0010487777, -0.010007947, -0.0010891829, + -0.0083075836, -0.0010186376, -0.0064650625, -0.00082186121, -0.0045177857, -0.00048761227, -0.0025065942, -0.0000094309362, + -0.00047468659, 0.00061376783, 0.0015335816, 0.0013772795, 0.0034739727, 0.0022703977, 0.0053036748, 0.0032764203, + 0.0069826017, 0.0043728831, 0.0084746322, 0.0055320212, 0.0097487466, 0.0067214468, 0.010780025, 0.0079050288, + 0.011550448, 0.009043945, 0.012049492, 0.010097877, 0.012274483, 0.011026301, 0.012230681, 0.011789839, + 0.011931112, 0.012351614, 0.01139613, 0.012678572, 0.010652733, 0.012742704, 0.0097336508, 0.012522144, + 0.0086762328, 0.012002093, 0.0075211856, 0.011175527, 0.0063111861, 0.010043681, 0.0050894427, 0.0086162686, + 0.0038982306, 0.006911451, 0.0027774705, 0.0049555404, 0.0017633948, 0.0027824503, 0.00088734273, 0.00043292236, + 0.00017473225, -0.0020464575, -0.00035576228, -0.0046044104, -0.00069279957, -0.0071862484, -0.00083271071, -0.009735249, + -0.00077958073, -0.012194071, -0.00054507388, -0.01450618, -0.00014801256, -0.016617225, 0.00038627203, -0.018476345, + 0.0010267919, -0.020037353, 0.0017379262, -0.021259794, 0.0024805821, -0.022109814, 0.003213454, -0.022560883, + 0.0038943416, -0.022594307, 0.004481487, -0.022199562, 0.0049348958, -0.021374447, 0.0052176043, -0.020125058, + 0.0052968613, -0.018465608, 0.0051452029, -0.016418114, 0.0047413921, -0.014011954, 0.0040712133, -0.011283341, + 0.0031281023, -0.0082747173, 0.0019136185, -0.0050341059, 0.00043774495, -0.001614425, -0.0012809716, 0.0019271988, + -0.0032154371, 0.0055301157, -0.0053301733, 0.009130815, -0.0075816144, 0.012663559, -0.0099185258, 0.016060976, + -0.012282523, 0.019254617, -0.014608691, 0.022175461, -0.016826265, 0.024754377, -0.018859385, 0.026922559, + -0.02062788, 0.028611908, -0.022048112, 0.029755389, -0.023033798, 0.03028737, -0.023496887, 0.030143932, + -0.023348402, 0.029263169, -0.022499284, 0.027585492, -0.020861225, 0.025053922, -0.018347459, 0.021614388, + -0.014873539, 0.017216032, -0.010358062, 0.011811542, -0.0047233663, 0.0053574666, 0.0021038246, -0.0021854306, + 0.010191803, -0.010851817, 0.019603329, -0.020671425, 0.030395132, -0.031668674, 0.04261747, -0.043862291, + 0.056313749, -0.057264935, 0.07152018, -0.071882829, 0.088265501, -0.087715395, 0.10657079, -0.10475491, + 0.12644924, -0.1229862, 0.14790612, -0.14238638, 0.17093869, -0.16292457, 0.19553615, -0.18456177, + 0.22167984, -0.20725067, 0.24934319, -0.23093559, 0.27849197, -0.25555256, 0.3090845, -0.28102925, + 0.34107187, -0.30728522, 0.37439832, -0.33423212, 0.40900153, -0.361774, 0.44481304, -0.38980758, + 0.48175868, -0.41822296, 0.51975912, -0.44690385, 0.55873019, -0.47572839, 0.59858364, -0.50456971, + 0.63922757, -0.53329676, 0.68056691, -0.56177497, 0.72250432, -0.58986712, 0.76494032, -0.61743438, + 0.80777425, -0.64433688, 0.8509047, -0.67043501, 0.89423001, -0.69559014, 0.93764895, -0.71966553, + 0.98106116, -0.74252748, 1.0243676, -0.76404625, 1.0674711, -0.78409678, 1.1102771, -0.80255991, + 1.152693, -0.81932294, 1.1946301, -0.83428079, 1.2360026, -0.84733653, 1.2767284, -0.85840225, + 1.3167298, -0.86739963, 1.3559328, -0.87426066, 1.3942684, -0.87892807, 1.4316717, -0.88135582, + 1.468083, -0.88150936, 1.5034472, -0.87936598, 1.5377145, -0.87491488, 1.5708399, -0.86815733, + 1.6027837, -0.85910636, 1.6335113, -0.84778708, 1.6629931, -0.83423591, 1.6912047, -0.81850064, + 1.7181267, -0.80063975, 1.7437447, -0.78072208, 1.7680489, -0.75882602, 1.7910345, -0.73503911, + 1.8127009, -0.70945716, 1.833052, -0.68218356, 1.8520958, -0.65332848, 1.8698444, -0.62300795, + 1.8863133, -0.59134328, 1.9015219, -0.55845982, 1.9154925, -0.52448642, 1.9282508, -0.48955446, + 1.9398252, -0.45379704, 1.9502468, -0.41734815, 1.9595492, -0.38034189, 1.9677683, -0.34291169, + 1.9749422, -0.30518964, 1.9811107, -0.26730573, 1.9863157, -0.22938718, 1.9906008, -0.1915579, + 1.994011, -0.15393782, 1.9965928, -0.11664244, 1.998394, -0.079782248, 1.9994637, -0.043462355, + 1.9998517, -0.0077820257, 1.9996089, 0.027165633, 1.9987869, 0.061293982, 1.997438, 0.094523117, + 1.9956142, 0.12678003, 1.9933683, 0.15799879, 1.9907526, 0.18812059, 1.9878191, 0.21709381, + 1.9846191, 0.24487394, 1.981203, 0.27142358, 1.97762, 0.29671216, 1.9739178, 0.3207159, + 1.9701425, 0.3434175, 1.9663377, 0.36480582, 1.9625452, 0.38487554, 1.9588039, 0.40362692, + 1.95515, 0.42106527, 1.9516169, 0.43720058, 1.9482347, 0.45204708, 1.9450303, 0.46562275, + 1.9420276, 0.47794896, 1.9392464, 0.48904994, 1.9367039, 0.49895242, 1.9344136, 0.50768507, + 1.9323857, 0.51527834, 1.9306273, 0.52176386, 1.929143, 0.52717417, 1.9279337, 0.53154266, + 1.9269985, 0.53490293, 1.9263337, 0.5372889, 1.9259334, 0.5387345, 1.9257902, 0.53927344, + 1.9258945, 0.53893936, 1.9262359, 0.53776574, 1.9268025, 0.53578556, 1.9275814, 0.53303164, + 1.9285592, 0.5295366, 1.9297218, 0.52533281, 1.9310548, 0.52045238, 1.9325439, 0.51492745, + 1.9341741, 0.50879002, 1.9359311, 0.50207198, 1.9378004, 0.4948054, 1.9397678, 0.48702216, + 1.9418195, 0.47875434, 1.943942, 0.47003385, 1.9461217, 0.46089265, 1.9483463, 0.45136252, + 1.9506031, 0.44147509, 1.9528806, 0.43126175, 1.9551672, 0.42075339, 1.9574521, 0.40998054, + 1.9597249, 0.39897302, 1.9619763, 0.38775995, 1.964197, 0.37636963, 1.9663788, 0.3648293, + 1.968514, 0.35316524, 1.9705957, 0.3414025, 1.9726177, 0.32956493, 1.9745748, 0.31767496, + 1.9764622, 0.30575377, 1.9782765, 0.29382104, 1.9800144, 0.28189498, 1.981674, 0.26999241, + 1.9832535, 0.25812861, 1.9847524, 0.24631737, 1.9861704, 0.23457102, 1.9875079, 0.22290041, + 1.988766, 0.21131492, 1.9899458, 0.1998225, 1.9910489, 0.18842971, 1.9920776, 0.17714165, + 1.9930336, 0.16596206, 1.9939193, 0.15489329, 1.9947368, 0.14393641, 1.9954883, 0.13309111, + 1.996176, 0.1223558, 1.9968017, 0.11172768, 1.9973674, 0.1012027, 1.9978747, 0.090775654, + 1.998325, 0.080440246, 1.9987197, 0.070189148, 1.9990598, 0.060014058, 1.9993461, 0.049905833, + 1.9995795, 0.039854541, 1.9997605, 0.029849617, 1.9998894, 0.019879945, 1.9999666, 0.0099340044, +}; diff --git a/libavcodec/on2avcdata.h b/libavcodec/on2avcdata.h new file mode 100644 index 000000000..7f498e58e --- /dev/null +++ b/libavcodec/on2avcdata.h @@ -0,0 +1,82 @@ +/* + * On2 Audio for Video Codec decoder + * + * Copyright (c) 2013 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_ON2AVC_DATA_H +#define AVCODEC_ON2AVC_DATA_H + +#include + +#define ON2AVC_MAX_BANDS 112 +#define ON2AVC_ESC_CB 15 + +typedef struct On2AVCMode { + int num_windows; + int num_bands; + const int *band_start; +} On2AVCMode; + +extern const On2AVCMode ff_on2avc_modes_40[8]; +extern const On2AVCMode ff_on2avc_modes_44[8]; + +#define ON2AVC_SCALE_DIFFS 121 +extern const uint32_t ff_on2avc_scale_diff_codes[]; +extern const uint8_t ff_on2avc_scale_diff_bits[]; + +extern const uint32_t * const ff_on2avc_quad_cb_codes[]; +extern const uint8_t * const ff_on2avc_quad_cb_bits[]; +extern const uint16_t * const ff_on2avc_quad_cb_syms[]; +extern const int ff_on2avc_quad_cb_elems[]; +extern const uint16_t * const ff_on2avc_pair_cb_codes[]; +extern const uint8_t * const ff_on2avc_pair_cb_bits[]; +extern const uint16_t * const ff_on2avc_pair_cb_syms[]; +extern const int ff_on2avc_pair_cb_elems[]; + +extern const float ff_on2avc_window_long_32000[1024]; +extern const float ff_on2avc_window_long_24000[1024]; +extern const float ff_on2avc_window_short[128]; + +extern const double ff_on2avc_tab_10_1[]; +extern const double ff_on2avc_tab_10_2[]; +extern const double ff_on2avc_tab_20_1[]; +extern const double ff_on2avc_tab_20_2[]; +extern const double ff_on2avc_tab_40_1[]; +extern const double ff_on2avc_tab_40_2[]; +extern const double ff_on2avc_tab_84_1[]; +extern const double ff_on2avc_tab_84_2[]; +extern const double ff_on2avc_tab_84_3[]; +extern const double ff_on2avc_tab_84_4[]; +extern const double* const ff_on2avc_tabs_4_10_1[4]; +extern const double* const ff_on2avc_tabs_4_10_2[4]; +extern const double* const ff_on2avc_tabs_9_20_1[9]; +extern const double* const ff_on2avc_tabs_9_20_2[9]; +extern const double* const ff_on2avc_tabs_19_40_1[19]; +extern const double* const ff_on2avc_tabs_19_40_2[19]; +extern const double* const ff_on2avc_tabs_20_84_1[20]; +extern const double* const ff_on2avc_tabs_20_84_2[20]; +extern const double* const ff_on2avc_tabs_20_84_3[20]; +extern const double* const ff_on2avc_tabs_20_84_4[20]; +extern const float ff_on2avc_ctab_1[2048]; +extern const float ff_on2avc_ctab_2[2048]; +extern const float ff_on2avc_ctab_3[2048]; +extern const float ff_on2avc_ctab_4[2048]; + +#endif /* AVCODEC_ON2AVC_DATA_H */ diff --git a/libavcodec/options.c b/libavcodec/options.c index 5ee9d6bd7..64b27e576 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -154,8 +154,26 @@ AVCodecContext *avcodec_alloc_context3(const AVCodec *codec) return avctx; } +void avcodec_free_context(AVCodecContext **pavctx) +{ + AVCodecContext *avctx = *pavctx; + + if (!avctx) + return; + + avcodec_close(avctx); + + av_freep(&avctx->extradata); + av_freep(&avctx->subtitle_header); + + av_freep(pavctx); +} + int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) { + const AVCodec *orig_codec = dest->codec; + uint8_t *orig_priv_data = dest->priv_data; + if (avcodec_is_open(dest)) { // check that the dest context is uninitialized av_log(dest, AV_LOG_ERROR, "Tried to copy AVCodecContext %p into already-initialized %p\n", @@ -164,13 +182,17 @@ int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) } av_opt_free(dest); - av_free(dest->priv_data); memcpy(dest, src, sizeof(*dest)); + dest->priv_data = orig_priv_data; + + if (orig_priv_data) + av_opt_copy(orig_priv_data, src->priv_data); + + dest->codec = orig_codec; + /* set values specific to opened codecs back to their default state */ - dest->priv_data = NULL; - dest->codec = NULL; dest->slice_offset = NULL; dest->hwaccel = NULL; dest->internal = NULL; @@ -181,6 +203,7 @@ int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) dest->intra_matrix = NULL; dest->inter_matrix = NULL; dest->rc_override = NULL; + dest->subtitle_header = NULL; if (src->rc_eq) { dest->rc_eq = av_strdup(src->rc_eq); if (!dest->rc_eq) @@ -202,6 +225,7 @@ int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) 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); alloc_and_copy_or_fail(subtitle_header, src->subtitle_header_size, 1); + av_assert0(dest->subtitle_header_size == src->subtitle_header_size); #undef alloc_and_copy_or_fail return 0; diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index c82c104cb..cbefa5227 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -54,16 +54,24 @@ static const AVOption avcodec_options[] = { {"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"}, +#if FF_API_GMC {"gmc", "use gmc", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_GMC }, INT_MIN, INT_MAX, V|E, "flags"}, +#endif +#if FF_API_MV0 {"mv0", "always try a mb with mv=<0,0>", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_MV0 }, INT_MIN, INT_MAX, V|E, "flags"}, +#endif +#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"}, {"emu_edge", "do not draw edges", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_EMU_EDGE }, INT_MIN, INT_MAX, 0, "flags"}, {"psnr", "error[?] variables will be set during encoding", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_PSNR }, INT_MIN, INT_MAX, V|E, "flags"}, {"truncated", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_TRUNCATED }, INT_MIN, INT_MAX, 0, "flags"}, +#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"}, @@ -155,6 +163,7 @@ static const AVOption avcodec_options[] = { {"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, {"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, {"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, +{"ignore_err", "ignore errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_IGNORE_ERR }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, {"careful", "consider things that violate the spec, are fast to check and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, {"compliant", "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, {"aggressive", "consider things that a sane encoder should not do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, @@ -170,8 +179,8 @@ static const AVOption avcodec_options[] = { "bits2qp(bits), qp2bits(qp). Also the following constants are available: iTex pTex tex mv " "fCode iCount mcVar var isI isP isB avgQP qComp avgIITex avgPITex avgPPTex avgBPTex avgTex.", OFFSET(rc_eq), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, V|E}, -{"maxrate", "Set maximum bitrate tolerance (in bits/s). Requires bufsize to be set.", OFFSET(rc_max_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, -{"minrate", "Set minimum bitrate tolerance (in bits/s). Most useful in setting up a CBR encode. It is of little use otherwise.", +{"maxrate", "maximum bitrate (in bits/s). Used for VBV together with bufsize.", OFFSET(rc_max_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, V|A|E}, +{"minrate", "minimum bitrate (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}, @@ -197,7 +206,9 @@ static const AVOption avcodec_options[] = { {"simplemmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEMMX }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"arm", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ARM }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"altivec", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ALTIVEC }, INT_MIN, INT_MAX, V|E|D, "idct"}, +#if FF_API_ARCH_SH4 {"sh4", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SH4 }, INT_MIN, INT_MAX, V|E|D, "idct"}, +#endif {"simplearm", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARM }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"simplearmv5te", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV5TE }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"simplearmv6", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV6 }, INT_MIN, INT_MAX, V|E|D, "idct"}, @@ -208,10 +219,12 @@ static const AVOption avcodec_options[] = { {"ipp", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_IPP }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"xvidmmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVIDMMX }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"faani", "floating point AAN IDCT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_FAAN }, INT_MIN, INT_MAX, V|D|E, "idct"}, +{"simpleauto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEAUTO }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"slice_count", NULL, OFFSET(slice_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"ec", "set error concealment strategy", OFFSET(error_concealment), AV_OPT_TYPE_FLAGS, {.i64 = 3 }, INT_MIN, INT_MAX, V|D, "ec"}, {"guess_mvs", "iterative motion vector (MV) search (slow)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_GUESS_MVS }, INT_MIN, INT_MAX, V|D, "ec"}, {"deblock", "use strong deblock filter for damaged MBs", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_DEBLOCK }, INT_MIN, INT_MAX, V|D, "ec"}, +{"favor_inter", "favor predicting from the previous frame", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_FAVOR_INTER }, INT_MIN, INT_MAX, V|D, "ec"}, {"bits_per_coded_sample", NULL, OFFSET(bits_per_coded_sample), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"pred", "prediction method", OFFSET(prediction_method), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "pred"}, {"left", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_LEFT }, INT_MIN, INT_MAX, V|E, "pred"}, @@ -238,7 +251,8 @@ static const AVOption avcodec_options[] = { {"vis_mb_type", "visualize block types", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MB_TYPE }, INT_MIN, INT_MAX, V|D, "debug"}, {"buffers", "picture buffer allocations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BUFFERS }, INT_MIN, INT_MAX, V|D, "debug"}, {"thread_ops", "threading operations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_THREADS }, INT_MIN, INT_MAX, V|A|D, "debug"}, -{"vismv", "visualize motion vectors (MVs)", OFFSET(debug_mv), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, V|D, "debug_mv"}, +{"nomc", "skip motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_NOMC }, INT_MIN, INT_MAX, V|A|D, "debug"}, +{"vismv", "visualize motion vectors (MVs)", OFFSET(debug_mv), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, V|D, "debug_mv"}, {"pf", "forward predicted MVs of P-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_P_FOR }, INT_MIN, INT_MAX, V|D, "debug_mv"}, {"bf", "forward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_B_FOR }, INT_MIN, INT_MAX, V|D, "debug_mv"}, {"bb", "backward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_B_BACK }, INT_MIN, INT_MAX, V|D, "debug_mv"}, @@ -303,7 +317,7 @@ static const AVOption avcodec_options[] = { {"auto", "autodetect a suitable number of threads to use", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, INT_MIN, INT_MAX, V|E|D, "threads"}, {"me_threshold", "motion estimation threshold", OFFSET(me_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"mb_threshold", "macroblock threshold", OFFSET(mb_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, -{"dc", "intra_dc_precision", OFFSET(intra_dc_precision), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, V|E}, +{"dc", "intra_dc_precision", OFFSET(intra_dc_precision), AV_OPT_TYPE_INT, {.i64 = 0 }, -8, 16, V|E}, {"nssew", "nsse weight", OFFSET(nsse_weight), AV_OPT_TYPE_INT, {.i64 = 8 }, INT_MIN, INT_MAX, V|E}, {"skip_top", "number of macroblock rows at the top which are skipped", OFFSET(skip_top), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|D}, {"skip_bottom", "number of macroblock rows at the bottom which are skipped", OFFSET(skip_bottom), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|D}, @@ -343,6 +357,7 @@ static const AVOption avcodec_options[] = { {"noref" , "discard all non-reference frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONREF }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"bidir" , "discard all bidirectional frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_BIDIR }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"nokey" , "discard all frames except keyframes", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONKEY }, INT_MIN, INT_MAX, V|D, "avdiscard"}, +{"nointra" , "discard all frames except I frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONINTRA}, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"all" , "discard all frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_ALL }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"bidir_refine", "refine the two motion vectors used in bidirectional macroblocks", OFFSET(bidir_refine), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 4, V|E}, {"brd_scale", "downscale frames for dynamic B-frame decision", OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, 10, V|E}, @@ -366,10 +381,45 @@ static const AVOption avcodec_options[] = { {"rc_max_vbv_use", NULL, OFFSET(rc_max_available_vbv_use), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, 0.0, FLT_MAX, V|E}, {"rc_min_vbv_use", NULL, OFFSET(rc_min_vbv_overflow_use), AV_OPT_TYPE_FLOAT, {.dbl = 3 }, 0.0, FLT_MAX, V|E}, {"ticks_per_frame", NULL, OFFSET(ticks_per_frame), AV_OPT_TYPE_INT, {.i64 = 1 }, 1, INT_MAX, A|V|E|D}, -{"color_primaries", NULL, OFFSET(color_primaries), AV_OPT_TYPE_INT, {.i64 = AVCOL_PRI_UNSPECIFIED }, 1, AVCOL_PRI_NB-1, V|E|D}, -{"color_trc", NULL, OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64 = AVCOL_TRC_UNSPECIFIED }, 1, AVCOL_TRC_NB-1, V|E|D}, -{"colorspace", NULL, OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = AVCOL_SPC_UNSPECIFIED }, 1, AVCOL_SPC_NB-1, V|E|D}, -{"color_range", NULL, OFFSET(color_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, AVCOL_RANGE_NB-1, V|E|D}, +{"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"}, +{"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"}, +{"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"}, +{"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"}, +{"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"}, +{"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"}, +{"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"}, +{"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"}, +{"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"}, +{"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}, {"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}, @@ -394,6 +444,7 @@ static const AVOption avcodec_options[] = { {"auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_AUTOMATIC}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, {"pre_decoder", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_PRE_DECODER}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, {"refcounted_frames", NULL, OFFSET(refcounted_frames), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, A|V|D }, +{"side_data_only_packets", NULL, OFFSET(side_data_only_packets), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, A|V|E }, {"skip_alpha", "Skip processing alpha", OFFSET(skip_alpha), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, V|D }, {"field_order", "Field order", OFFSET(field_order), AV_OPT_TYPE_INT, {.i64 = AV_FIELD_UNKNOWN }, 0, 5, V|D|E, "field_order" }, {"progressive", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_PROGRESSIVE }, 0, 0, V|D|E, "field_order" }, diff --git a/libavcodec/opus.c b/libavcodec/opus.c new file mode 100644 index 000000000..e76c510a7 --- /dev/null +++ b/libavcodec/opus.c @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2012 Andrew D'Addesio + * Copyright (c) 2013-2014 Mozilla Corporation + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Opus decoder/parser shared code + */ + +#include + +#include "libavutil/error.h" + +#include "opus.h" +#include "vorbis.h" + +static const uint16_t opus_frame_duration[32] = { + 480, 960, 1920, 2880, + 480, 960, 1920, 2880, + 480, 960, 1920, 2880, + 480, 960, + 480, 960, + 120, 240, 480, 960, + 120, 240, 480, 960, + 120, 240, 480, 960, + 120, 240, 480, 960, +}; + +/** + * Read a 1- or 2-byte frame length + */ +static inline int xiph_lacing_16bit(const uint8_t **ptr, const uint8_t *end) +{ + int val; + + if (*ptr >= end) + return AVERROR_INVALIDDATA; + val = *(*ptr)++; + if (val >= 252) { + if (*ptr >= end) + return AVERROR_INVALIDDATA; + val += 4 * *(*ptr)++; + } + return val; +} + +/** + * Read a multi-byte length (used for code 3 packet padding size) + */ +static inline int xiph_lacing_full(const uint8_t **ptr, const uint8_t *end) +{ + int val = 0; + int next; + + while (1) { + if (*ptr >= end || val > INT_MAX - 254) + return AVERROR_INVALIDDATA; + next = *(*ptr)++; + val += next; + if (next < 255) + break; + else + val--; + } + return val; +} + +/** + * Parse Opus packet info from raw packet data + */ +int ff_opus_parse_packet(OpusPacket *pkt, const uint8_t *buf, int buf_size, + int self_delimiting) +{ + const uint8_t *ptr = buf; + const uint8_t *end = buf + buf_size; + int padding = 0; + int frame_bytes, i; + + if (buf_size < 1) + goto fail; + + /* TOC byte */ + i = *ptr++; + pkt->code = (i ) & 0x3; + pkt->stereo = (i >> 2) & 0x1; + pkt->config = (i >> 3) & 0x1F; + + /* code 2 and code 3 packets have at least 1 byte after the TOC */ + if (pkt->code >= 2 && buf_size < 2) + goto fail; + + switch (pkt->code) { + case 0: + /* 1 frame */ + pkt->frame_count = 1; + pkt->vbr = 0; + + if (self_delimiting) { + int len = xiph_lacing_16bit(&ptr, end); + if (len < 0 || len > end - ptr) + goto fail; + end = ptr + len; + buf_size = end - buf; + } + + frame_bytes = end - ptr; + if (frame_bytes > MAX_FRAME_SIZE) + goto fail; + pkt->frame_offset[0] = ptr - buf; + pkt->frame_size[0] = frame_bytes; + break; + case 1: + /* 2 frames, equal size */ + pkt->frame_count = 2; + pkt->vbr = 0; + + if (self_delimiting) { + int len = xiph_lacing_16bit(&ptr, end); + if (len < 0 || 2 * len > end - ptr) + goto fail; + end = ptr + 2 * len; + buf_size = end - buf; + } + + frame_bytes = end - ptr; + if (frame_bytes & 1 || frame_bytes >> 1 > MAX_FRAME_SIZE) + goto fail; + pkt->frame_offset[0] = ptr - buf; + pkt->frame_size[0] = frame_bytes >> 1; + pkt->frame_offset[1] = pkt->frame_offset[0] + pkt->frame_size[0]; + pkt->frame_size[1] = frame_bytes >> 1; + break; + case 2: + /* 2 frames, different sizes */ + pkt->frame_count = 2; + pkt->vbr = 1; + + /* read 1st frame size */ + frame_bytes = xiph_lacing_16bit(&ptr, end); + if (frame_bytes < 0) + goto fail; + + if (self_delimiting) { + int len = xiph_lacing_16bit(&ptr, end); + if (len < 0 || len + frame_bytes > end - ptr) + goto fail; + end = ptr + frame_bytes + len; + buf_size = end - buf; + } + + pkt->frame_offset[0] = ptr - buf; + pkt->frame_size[0] = frame_bytes; + + /* calculate 2nd frame size */ + frame_bytes = end - ptr - pkt->frame_size[0]; + if (frame_bytes < 0 || frame_bytes > MAX_FRAME_SIZE) + goto fail; + pkt->frame_offset[1] = pkt->frame_offset[0] + pkt->frame_size[0]; + pkt->frame_size[1] = frame_bytes; + break; + case 3: + /* 1 to 48 frames, can be different sizes */ + i = *ptr++; + pkt->frame_count = (i ) & 0x3F; + padding = (i >> 6) & 0x01; + pkt->vbr = (i >> 7) & 0x01; + + if (pkt->frame_count == 0 || pkt->frame_count > MAX_FRAMES) + goto fail; + + /* read padding size */ + if (padding) { + padding = xiph_lacing_full(&ptr, end); + if (padding < 0) + goto fail; + } + + /* read frame sizes */ + if (pkt->vbr) { + /* for VBR, all frames except the final one have their size coded + in the bitstream. the last frame size is implicit. */ + int total_bytes = 0; + for (i = 0; i < pkt->frame_count - 1; i++) { + frame_bytes = xiph_lacing_16bit(&ptr, end); + if (frame_bytes < 0) + goto fail; + pkt->frame_size[i] = frame_bytes; + total_bytes += frame_bytes; + } + + if (self_delimiting) { + int len = xiph_lacing_16bit(&ptr, end); + if (len < 0 || len + total_bytes + padding > end - ptr) + goto fail; + end = ptr + total_bytes + len + padding; + buf_size = end - buf; + } + + frame_bytes = end - ptr - padding; + if (total_bytes > frame_bytes) + goto fail; + pkt->frame_offset[0] = ptr - buf; + for (i = 1; i < pkt->frame_count; i++) + pkt->frame_offset[i] = pkt->frame_offset[i-1] + pkt->frame_size[i-1]; + pkt->frame_size[pkt->frame_count-1] = frame_bytes - total_bytes; + } else { + /* for CBR, the remaining packet bytes are divided evenly between + the frames */ + if (self_delimiting) { + frame_bytes = xiph_lacing_16bit(&ptr, end); + if (frame_bytes < 0 || pkt->frame_count * frame_bytes + padding > end - ptr) + goto fail; + end = ptr + pkt->frame_count * frame_bytes + padding; + buf_size = end - buf; + } else { + frame_bytes = end - ptr - padding; + if (frame_bytes % pkt->frame_count || + frame_bytes / pkt->frame_count > MAX_FRAME_SIZE) + goto fail; + frame_bytes /= pkt->frame_count; + } + + pkt->frame_offset[0] = ptr - buf; + pkt->frame_size[0] = frame_bytes; + for (i = 1; i < pkt->frame_count; i++) { + pkt->frame_offset[i] = pkt->frame_offset[i-1] + pkt->frame_size[i-1]; + pkt->frame_size[i] = frame_bytes; + } + } + } + + pkt->packet_size = buf_size; + pkt->data_size = pkt->packet_size - padding; + + /* total packet duration cannot be larger than 120ms */ + pkt->frame_duration = opus_frame_duration[pkt->config]; + if (pkt->frame_duration * pkt->frame_count > MAX_PACKET_DUR) + goto fail; + + /* set mode and bandwidth */ + if (pkt->config < 12) { + pkt->mode = OPUS_MODE_SILK; + pkt->bandwidth = pkt->config >> 2; + } else if (pkt->config < 16) { + pkt->mode = OPUS_MODE_HYBRID; + pkt->bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND + (pkt->config >= 14); + } else { + pkt->mode = OPUS_MODE_CELT; + pkt->bandwidth = (pkt->config - 16) >> 2; + /* skip mediumband */ + if (pkt->bandwidth) + pkt->bandwidth++; + } + + return 0; + +fail: + memset(pkt, 0, sizeof(*pkt)); + return AVERROR_INVALIDDATA; +} + +static int channel_reorder_vorbis(int nb_channels, int channel_idx) +{ + return ff_vorbis_channel_layout_offsets[nb_channels - 1][channel_idx]; +} + +static int channel_reorder_unknown(int nb_channels, int channel_idx) +{ + return channel_idx; +} + +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; + + const uint8_t *extradata, *channel_map; + int extradata_size; + int version, channels, map_type, streams, stereo_streams, i, j; + uint64_t layout; + + if (!avctx->extradata) { + if (avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, + "Multichannel configuration without extradata.\n"); + return AVERROR(EINVAL); + } + default_extradata[9] = (avctx->channels == 1) ? 1 : 2; + extradata = default_extradata; + extradata_size = sizeof(default_extradata); + } else { + extradata = avctx->extradata; + extradata_size = avctx->extradata_size; + } + + if (extradata_size < 19) { + av_log(avctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", + extradata_size); + return AVERROR_INVALIDDATA; + } + + version = extradata[8]; + if (version > 15) { + avpriv_request_sample(avctx, "Extradata version %d", version); + return AVERROR_PATCHWELCOME; + } + + avctx->delay = AV_RL16(extradata + 10); + + channels = extradata[9]; + if (!channels) { + av_log(avctx, AV_LOG_ERROR, "Zero channel count specified in the extadata\n"); + return AVERROR_INVALIDDATA; + } + + s->gain_i = AV_RL16(extradata + 16); + if (s->gain_i) + s->gain = pow(10, s->gain_i / (20.0 * 256)); + + map_type = extradata[18]; + if (!map_type) { + if (channels > 2) { + av_log(avctx, AV_LOG_ERROR, + "Channel mapping 0 is only specified for up to 2 channels\n"); + return AVERROR_INVALIDDATA; + } + layout = (channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; + streams = 1; + stereo_streams = channels - 1; + channel_map = default_channel_map; + } else if (map_type == 1 || map_type == 255) { + if (extradata_size < 21 + channels) { + av_log(avctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", + extradata_size); + return AVERROR_INVALIDDATA; + } + + streams = extradata[19]; + stereo_streams = extradata[20]; + if (!streams || stereo_streams > streams || + streams + stereo_streams > 255) { + av_log(avctx, AV_LOG_ERROR, + "Invalid stream/stereo stream count: %d/%d\n", streams, stereo_streams); + return AVERROR_INVALIDDATA; + } + + if (map_type == 1) { + if (channels > 8) { + av_log(avctx, AV_LOG_ERROR, + "Channel mapping 1 is only specified for up to 8 channels\n"); + return AVERROR_INVALIDDATA; + } + layout = ff_vorbis_channel_layouts[channels - 1]; + channel_reorder = channel_reorder_vorbis; + } else + layout = 0; + + channel_map = extradata + 21; + } else { + avpriv_request_sample(avctx, "Mapping type %d", map_type); + return AVERROR_PATCHWELCOME; + } + + s->channel_maps = av_mallocz_array(channels, sizeof(*s->channel_maps)); + if (!s->channel_maps) + return AVERROR(ENOMEM); + + for (i = 0; i < channels; i++) { + ChannelMap *map = &s->channel_maps[i]; + uint8_t idx = channel_map[channel_reorder(channels, i)]; + + if (idx == 255) { + map->silence = 1; + continue; + } else if (idx >= streams + stereo_streams) { + av_log(avctx, AV_LOG_ERROR, + "Invalid channel map for output channel %d: %d\n", i, idx); + return AVERROR_INVALIDDATA; + } + + /* check that we din't see this index yet */ + map->copy = 0; + for (j = 0; j < i; j++) + if (channel_map[channel_reorder(channels, j)] == idx) { + map->copy = 1; + map->copy_idx = j; + break; + } + + if (idx < 2 * stereo_streams) { + map->stream_idx = idx / 2; + map->channel_idx = idx & 1; + } else { + map->stream_idx = idx - stereo_streams; + map->channel_idx = 0; + } + } + + avctx->channels = channels; + avctx->channel_layout = layout; + s->nb_streams = streams; + s->nb_stereo_streams = stereo_streams; + + return 0; +} diff --git a/libavcodec/opus.h b/libavcodec/opus.h new file mode 100644 index 000000000..543d90c60 --- /dev/null +++ b/libavcodec/opus.h @@ -0,0 +1,411 @@ +/* + * Opus decoder/demuxer common functions + * Copyright (c) 2012 Andrew D'Addesio + * Copyright (c) 2013-2014 Mozilla Corporation + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_OPUS_H +#define AVCODEC_OPUS_H + +#include + +#include "libavutil/audio_fifo.h" +#include "libavutil/float_dsp.h" +#include "libavutil/frame.h" + +#include "libswresample/swresample.h" + +#include "avcodec.h" +#include "get_bits.h" + +#define MAX_FRAME_SIZE 1275 +#define MAX_FRAMES 48 +#define MAX_PACKET_DUR 5760 + +#define CELT_SHORT_BLOCKSIZE 120 +#define CELT_OVERLAP CELT_SHORT_BLOCKSIZE +#define CELT_MAX_LOG_BLOCKS 3 +#define CELT_MAX_FRAME_SIZE (CELT_SHORT_BLOCKSIZE * (1 << CELT_MAX_LOG_BLOCKS)) +#define CELT_MAX_BANDS 21 +#define CELT_VECTORS 11 +#define CELT_ALLOC_STEPS 6 +#define CELT_FINE_OFFSET 21 +#define CELT_MAX_FINE_BITS 8 +#define CELT_NORM_SCALE 16384 +#define CELT_QTHETA_OFFSET 4 +#define CELT_QTHETA_OFFSET_TWOPHASE 16 +#define CELT_DEEMPH_COEFF 0.85000610f +#define CELT_POSTFILTER_MINPERIOD 15 +#define CELT_ENERGY_SILENCE (-28.0f) + +#define SILK_HISTORY 322 +#define SILK_MAX_LPC 16 + +#define ROUND_MULL(a,b,s) (((MUL64(a, b) >> ((s) - 1)) + 1) >> 1) +#define ROUND_MUL16(a,b) ((MUL16(a, b) + 16384) >> 15) +#define opus_ilog(i) (av_log2(i) + !!(i)) + +enum OpusMode { + OPUS_MODE_SILK, + OPUS_MODE_HYBRID, + OPUS_MODE_CELT +}; + +enum OpusBandwidth { + OPUS_BANDWIDTH_NARROWBAND, + OPUS_BANDWIDTH_MEDIUMBAND, + OPUS_BANDWIDTH_WIDEBAND, + OPUS_BANDWIDTH_SUPERWIDEBAND, + OPUS_BANDWIDTH_FULLBAND +}; + +typedef struct RawBitsContext { + const uint8_t *position; + unsigned int bytes; + unsigned int cachelen; + unsigned int cacheval; +} RawBitsContext; + +typedef struct OpusRangeCoder { + GetBitContext gb; + RawBitsContext rb; + unsigned int range; + unsigned int value; + unsigned int total_read_bits; +} OpusRangeCoder; + +typedef struct SilkContext SilkContext; + +typedef struct CeltContext CeltContext; + +typedef struct OpusPacket { + int packet_size; /**< packet size */ + int data_size; /**< size of the useful data -- packet size - padding */ + int code; /**< packet code: specifies the frame layout */ + int stereo; /**< whether this packet is mono or stereo */ + int vbr; /**< vbr flag */ + int config; /**< configuration: tells the audio mode, + ** bandwidth, and frame duration */ + int frame_count; /**< frame count */ + int frame_offset[MAX_FRAMES]; /**< frame offsets */ + int frame_size[MAX_FRAMES]; /**< frame sizes */ + int frame_duration; /**< frame duration, in samples @ 48kHz */ + enum OpusMode mode; /**< mode */ + enum OpusBandwidth bandwidth; /**< bandwidth */ +} OpusPacket; + +typedef struct OpusStreamContext { + AVCodecContext *avctx; + int output_channels; + + OpusRangeCoder rc; + OpusRangeCoder redundancy_rc; + SilkContext *silk; + CeltContext *celt; + AVFloatDSPContext *fdsp; + + float silk_buf[2][960]; + float *silk_output[2]; + DECLARE_ALIGNED(32, float, celt_buf)[2][960]; + float *celt_output[2]; + + float redundancy_buf[2][960]; + float *redundancy_output[2]; + + /* data buffers for the final output data */ + float *out[2]; + int out_size; + + float *out_dummy; + int out_dummy_allocated_size; + + SwrContext *swr; + AVAudioFifo *celt_delay; + int silk_samplerate; + /* number of samples we still want to get from the resampler */ + int delayed_samples; + + OpusPacket packet; + + int redundancy_idx; +} OpusStreamContext; + +// a mapping between an opus stream and an output channel +typedef struct ChannelMap { + int stream_idx; + int channel_idx; + + // when a single decoded channel is mapped to multiple output channels, we + // write to the first output directly and copy from it to the others + // this field is set to 1 for those copied output channels + int copy; + // this is the index of the output channel to copy from + int copy_idx; + + // this channel is silent + int silence; +} ChannelMap; + +typedef struct OpusContext { + OpusStreamContext *streams; + int nb_streams; + int nb_stereo_streams; + + AVFloatDSPContext fdsp; + int16_t gain_i; + float gain; + + ChannelMap *channel_maps; +} OpusContext; + +static av_always_inline void opus_rc_normalize(OpusRangeCoder *rc) +{ + while (rc->range <= 1<<23) { + rc->value = ((rc->value << 8) | (get_bits(&rc->gb, 8) ^ 0xFF)) & ((1u << 31) - 1); + rc->range <<= 8; + rc->total_read_bits += 8; + } +} + +static av_always_inline void opus_rc_update(OpusRangeCoder *rc, unsigned int scale, + unsigned int low, unsigned int high, + unsigned int total) +{ + rc->value -= scale * (total - high); + rc->range = low ? scale * (high - low) + : rc->range - scale * (total - high); + opus_rc_normalize(rc); +} + +static av_always_inline unsigned int opus_rc_getsymbol(OpusRangeCoder *rc, const uint16_t *cdf) +{ + unsigned int k, scale, total, symbol, low, high; + + total = *cdf++; + + scale = rc->range / total; + symbol = rc->value / scale + 1; + symbol = total - FFMIN(symbol, total); + + for (k = 0; cdf[k] <= symbol; k++); + high = cdf[k]; + low = k ? cdf[k-1] : 0; + + opus_rc_update(rc, scale, low, high, total); + + return k; +} + +static av_always_inline unsigned int opus_rc_p2model(OpusRangeCoder *rc, unsigned int bits) +{ + unsigned int k, scale; + scale = rc->range >> bits; // in this case, scale = symbol + + if (rc->value >= scale) { + rc->value -= scale; + rc->range -= scale; + k = 0; + } else { + rc->range = scale; + k = 1; + } + opus_rc_normalize(rc); + return k; +} + +/** + * CELT: estimate bits of entropy that have thus far been consumed for the + * current CELT frame, to integer and fractional (1/8th bit) precision + */ +static av_always_inline unsigned int opus_rc_tell(const OpusRangeCoder *rc) +{ + return rc->total_read_bits - av_log2(rc->range) - 1; +} + +static av_always_inline unsigned int opus_rc_tell_frac(const OpusRangeCoder *rc) +{ + unsigned int i, total_bits, rcbuffer, range; + + total_bits = rc->total_read_bits << 3; + rcbuffer = av_log2(rc->range) + 1; + range = rc->range >> (rcbuffer-16); + + for (i = 0; i < 3; i++) { + int bit; + range = range * range >> 15; + bit = range >> 16; + rcbuffer = rcbuffer << 1 | bit; + range >>= bit; + } + + return total_bits - rcbuffer; +} + +/** + * CELT: read 1-25 raw bits at the end of the frame, backwards byte-wise + */ +static av_always_inline unsigned int opus_getrawbits(OpusRangeCoder *rc, unsigned int count) +{ + unsigned int value = 0; + + while (rc->rb.bytes && rc->rb.cachelen < count) { + rc->rb.cacheval |= *--rc->rb.position << rc->rb.cachelen; + rc->rb.cachelen += 8; + rc->rb.bytes--; + } + + value = rc->rb.cacheval & ((1<rb.cacheval >>= count; + rc->rb.cachelen -= count; + rc->total_read_bits += count; + + return value; +} + +/** + * CELT: read a uniform distribution + */ +static av_always_inline unsigned int opus_rc_unimodel(OpusRangeCoder *rc, unsigned int size) +{ + unsigned int bits, k, scale, total; + + bits = opus_ilog(size - 1); + total = (bits > 8) ? ((size - 1) >> (bits - 8)) + 1 : size; + + scale = rc->range / total; + k = rc->value / scale + 1; + k = total - FFMIN(k, total); + opus_rc_update(rc, scale, k, k + 1, total); + + if (bits > 8) { + k = k << (bits - 8) | opus_getrawbits(rc, bits - 8); + return FFMIN(k, size - 1); + } else + return k; +} + +static av_always_inline int opus_rc_laplace(OpusRangeCoder *rc, unsigned int symbol, int decay) +{ + /* extends the range coder to model a Laplace distribution */ + int value = 0; + unsigned int scale, low = 0, center; + + scale = rc->range >> 15; + center = rc->value / scale + 1; + center = (1 << 15) - FFMIN(center, 1 << 15); + + if (center >= symbol) { + value++; + low = symbol; + symbol = 1 + ((32768 - 32 - symbol) * (16384-decay) >> 15); + + while (symbol > 1 && center >= low + 2 * symbol) { + value++; + symbol *= 2; + low += symbol; + symbol = (((symbol - 2) * decay) >> 15) + 1; + } + + if (symbol <= 1) { + int distance = (center - low) >> 1; + value += distance; + low += 2 * distance; + } + + if (center < low + symbol) + value *= -1; + else + low += symbol; + } + + opus_rc_update(rc, scale, low, FFMIN(low + symbol, 32768), 32768); + + return value; +} + +static av_always_inline unsigned int opus_rc_stepmodel(OpusRangeCoder *rc, int k0) +{ + /* Use a probability of 3 up to itheta=8192 and then use 1 after */ + unsigned int k, scale, symbol, total = (k0+1)*3 + k0; + scale = rc->range / total; + symbol = rc->value / scale + 1; + symbol = total - FFMIN(symbol, total); + + k = (symbol < (k0+1)*3) ? symbol/3 : symbol - (k0+1)*2; + + opus_rc_update(rc, scale, (k <= k0) ? 3*(k+0) : (k-1-k0) + 3*(k0+1), + (k <= k0) ? 3*(k+1) : (k-0-k0) + 3*(k0+1), total); + return k; +} + +static av_always_inline unsigned int opus_rc_trimodel(OpusRangeCoder *rc, int qn) +{ + unsigned int k, scale, symbol, total, low, center; + + total = ((qn>>1) + 1) * ((qn>>1) + 1); + scale = rc->range / total; + center = rc->value / scale + 1; + center = total - FFMIN(center, total); + + if (center < total >> 1) { + k = (ff_sqrt(8 * center + 1) - 1) >> 1; + low = k * (k + 1) >> 1; + symbol = k + 1; + } else { + k = (2*(qn + 1) - ff_sqrt(8*(total - center - 1) + 1)) >> 1; + low = total - ((qn + 1 - k) * (qn + 2 - k) >> 1); + symbol = qn + 1 - k; + } + + opus_rc_update(rc, scale, low, low + symbol, total); + + return k; +} + +int ff_opus_parse_packet(OpusPacket *pkt, const uint8_t *buf, int buf_size, + int self_delimited); + +int ff_opus_parse_extradata(AVCodecContext *avctx, OpusContext *s); + +int ff_silk_init(AVCodecContext *avctx, SilkContext **ps, int output_channels); +void ff_silk_free(SilkContext **ps); +void ff_silk_flush(SilkContext *s); + +/** + * Decode the LP layer of one Opus frame (which may correspond to several SILK + * frames). + */ +int ff_silk_decode_superframe(SilkContext *s, OpusRangeCoder *rc, + float *output[2], + enum OpusBandwidth bandwidth, int coded_channels, + int duration_ms); + +int ff_celt_init(AVCodecContext *avctx, CeltContext **s, int output_channels); + +void ff_celt_free(CeltContext **s); + +void ff_celt_flush(CeltContext *s); + +int ff_celt_decode_frame(CeltContext *s, OpusRangeCoder *rc, + float **output, int coded_channels, int frame_size, + int startband, int endband); + +extern const float ff_celt_window2[120]; + +#endif /* AVCODEC_OPUS_H */ diff --git a/libavcodec/opus_celt.c b/libavcodec/opus_celt.c new file mode 100644 index 000000000..fad471beb --- /dev/null +++ b/libavcodec/opus_celt.c @@ -0,0 +1,2221 @@ +/* + * Copyright (c) 2012 Andrew D'Addesio + * Copyright (c) 2013-2014 Mozilla Corporation + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Opus CELT decoder + */ + +#include + +#include "libavutil/float_dsp.h" + +#include "opus.h" +#include "opus_imdct.h" + +enum CeltSpread { + CELT_SPREAD_NONE, + CELT_SPREAD_LIGHT, + CELT_SPREAD_NORMAL, + CELT_SPREAD_AGGRESSIVE +}; + +typedef struct CeltFrame { + float energy[CELT_MAX_BANDS]; + float prev_energy[2][CELT_MAX_BANDS]; + + uint8_t collapse_masks[CELT_MAX_BANDS]; + + /* buffer for mdct output + postfilter */ + DECLARE_ALIGNED(32, float, buf)[2048]; + + /* postfilter parameters */ + int pf_period_new; + float pf_gains_new[3]; + int pf_period; + float pf_gains[3]; + int pf_period_old; + float pf_gains_old[3]; + + float deemph_coeff; +} CeltFrame; + +struct CeltContext { + // constant values that do not change during context lifetime + AVCodecContext *avctx; + CeltIMDCTContext *imdct[4]; + AVFloatDSPContext dsp; + int output_channels; + + // values that have inter-frame effect and must be reset on flush + CeltFrame frame[2]; + uint32_t seed; + int flushed; + + // values that only affect a single frame + int coded_channels; + int framebits; + int duration; + + /* number of iMDCT blocks in the frame */ + int blocks; + /* size of each block */ + int blocksize; + + int startband; + int endband; + int codedbands; + + int anticollapse_bit; + + int intensitystereo; + int dualstereo; + enum CeltSpread spread; + + int remaining; + int remaining2; + int fine_bits [CELT_MAX_BANDS]; + int fine_priority[CELT_MAX_BANDS]; + int pulses [CELT_MAX_BANDS]; + int tf_change [CELT_MAX_BANDS]; + + DECLARE_ALIGNED(32, float, coeffs)[2][CELT_MAX_FRAME_SIZE]; + DECLARE_ALIGNED(32, float, scratch)[22 * 8]; // MAX(celt_freq_range) * 1<> 13; + x = (32767-x) + ROUND_MUL16(x, (-7651 + ROUND_MUL16(x, (8277 + ROUND_MUL16(-626, x))))); + return 1+x; +} + +static inline int celt_log2tan(int isin, int icos) +{ + int lc, ls; + lc = opus_ilog(icos); + ls = opus_ilog(isin); + icos <<= 15 - lc; + isin <<= 15 - ls; + return (ls << 11) - (lc << 11) + + ROUND_MUL16(isin, ROUND_MUL16(isin, -2597) + 7932) - + ROUND_MUL16(icos, ROUND_MUL16(icos, -2597) + 7932); +} + +static inline uint32_t celt_rng(CeltContext *s) +{ + s->seed = 1664525 * s->seed + 1013904223; + return s->seed; +} + +static void celt_decode_coarse_energy(CeltContext *s, OpusRangeCoder *rc) +{ + int i, j; + float prev[2] = {0}; + float alpha, beta; + const uint8_t *model; + + /* use the 2D z-transform to apply prediction in both */ + /* the time domain (alpha) and the frequency domain (beta) */ + + if (opus_rc_tell(rc)+3 <= s->framebits && opus_rc_p2model(rc, 3)) { + /* intra frame */ + alpha = 0; + beta = 1.0f - 4915.0f/32768.0f; + model = celt_coarse_energy_dist[s->duration][1]; + } else { + alpha = celt_alpha_coef[s->duration]; + beta = 1.0f - celt_beta_coef[s->duration]; + model = celt_coarse_energy_dist[s->duration][0]; + } + + for (i = 0; i < CELT_MAX_BANDS; i++) { + for (j = 0; j < s->coded_channels; j++) { + CeltFrame *frame = &s->frame[j]; + float value; + int available; + + if (i < s->startband || i >= s->endband) { + frame->energy[i] = 0.0; + continue; + } + + available = s->framebits - opus_rc_tell(rc); + if (available >= 15) { + /* decode using a Laplace distribution */ + int k = FFMIN(i, 20) << 1; + value = opus_rc_laplace(rc, model[k] << 7, model[k+1] << 6); + } else if (available >= 2) { + int x = opus_rc_getsymbol(rc, celt_model_energy_small); + value = (x>>1) ^ -(x&1); + } else if (available >= 1) { + value = -(float)opus_rc_p2model(rc, 1); + } else value = -1; + + frame->energy[i] = FFMAX(-9.0f, frame->energy[i]) * alpha + prev[j] + value; + prev[j] += beta * value; + } + } +} + +static void celt_decode_fine_energy(CeltContext *s, OpusRangeCoder *rc) +{ + int i; + for (i = s->startband; i < s->endband; i++) { + int j; + if (!s->fine_bits[i]) + continue; + + for (j = 0; j < s->coded_channels; j++) { + CeltFrame *frame = &s->frame[j]; + int q2; + float offset; + q2 = opus_getrawbits(rc, s->fine_bits[i]); + offset = (q2 + 0.5f) * (1 << (14 - s->fine_bits[i])) / 16384.0f - 0.5f; + frame->energy[i] += offset; + } + } +} + +static void celt_decode_final_energy(CeltContext *s, OpusRangeCoder *rc, + int bits_left) +{ + int priority, i, j; + + for (priority = 0; priority < 2; priority++) { + for (i = s->startband; i < s->endband && bits_left >= s->coded_channels; i++) { + if (s->fine_priority[i] != priority || s->fine_bits[i] >= CELT_MAX_FINE_BITS) + continue; + + for (j = 0; j < s->coded_channels; j++) { + int q2; + float offset; + q2 = opus_getrawbits(rc, 1); + offset = (q2 - 0.5f) * (1 << (14 - s->fine_bits[i] - 1)) / 16384.0f; + s->frame[j].energy[i] += offset; + bits_left--; + } + } + } +} + +static void celt_decode_tf_changes(CeltContext *s, OpusRangeCoder *rc, + int transient) +{ + int i, diff = 0, tf_select = 0, tf_changed = 0, tf_select_bit; + int consumed, bits = transient ? 2 : 4; + + consumed = opus_rc_tell(rc); + tf_select_bit = (s->duration != 0 && consumed+bits+1 <= s->framebits); + + for (i = s->startband; i < s->endband; i++) { + if (consumed+bits+tf_select_bit <= s->framebits) { + diff ^= opus_rc_p2model(rc, bits); + consumed = opus_rc_tell(rc); + tf_changed |= diff; + } + s->tf_change[i] = diff; + bits = transient ? 4 : 5; + } + + if (tf_select_bit && celt_tf_select[s->duration][transient][0][tf_changed] != + celt_tf_select[s->duration][transient][1][tf_changed]) + tf_select = opus_rc_p2model(rc, 1); + + for (i = s->startband; i < s->endband; i++) { + s->tf_change[i] = celt_tf_select[s->duration][transient][tf_select][s->tf_change[i]]; + } +} + +static void celt_decode_allocation(CeltContext *s, OpusRangeCoder *rc) +{ + // approx. maximum bit allocation for each band before boost/trim + int cap[CELT_MAX_BANDS]; + int boost[CELT_MAX_BANDS]; + int threshold[CELT_MAX_BANDS]; + int bits1[CELT_MAX_BANDS]; + int bits2[CELT_MAX_BANDS]; + int trim_offset[CELT_MAX_BANDS]; + + int skip_startband = s->startband; + int dynalloc = 6; + int alloctrim = 5; + int extrabits = 0; + + int skip_bit = 0; + int intensitystereo_bit = 0; + int dualstereo_bit = 0; + + int remaining, bandbits; + int low, high, total, done; + int totalbits; + int consumed; + int i, j; + + consumed = opus_rc_tell(rc); + + /* obtain spread flag */ + s->spread = CELT_SPREAD_NORMAL; + if (consumed + 4 <= s->framebits) + s->spread = opus_rc_getsymbol(rc, celt_model_spread); + + /* generate static allocation caps */ + for (i = 0; i < CELT_MAX_BANDS; i++) { + cap[i] = (celt_static_caps[s->duration][s->coded_channels - 1][i] + 64) + * celt_freq_range[i] << (s->coded_channels - 1) << s->duration >> 2; + } + + /* obtain band boost */ + totalbits = s->framebits << 3; // convert to 1/8 bits + consumed = opus_rc_tell_frac(rc); + for (i = s->startband; i < s->endband; i++) { + int quanta, band_dynalloc; + + boost[i] = 0; + + quanta = celt_freq_range[i] << (s->coded_channels - 1) << s->duration; + quanta = FFMIN(quanta << 3, FFMAX(6 << 3, quanta)); + band_dynalloc = dynalloc; + while (consumed + (band_dynalloc<<3) < totalbits && boost[i] < cap[i]) { + int add = opus_rc_p2model(rc, band_dynalloc); + consumed = opus_rc_tell_frac(rc); + if (!add) + break; + + boost[i] += quanta; + totalbits -= quanta; + band_dynalloc = 1; + } + /* dynalloc is more likely to occur if it's already been used for earlier bands */ + if (boost[i]) + dynalloc = FFMAX(2, dynalloc - 1); + } + + /* obtain allocation trim */ + if (consumed + (6 << 3) <= totalbits) + alloctrim = opus_rc_getsymbol(rc, celt_model_alloc_trim); + + /* anti-collapse bit reservation */ + totalbits = (s->framebits << 3) - opus_rc_tell_frac(rc) - 1; + s->anticollapse_bit = 0; + if (s->blocks > 1 && s->duration >= 2 && + totalbits >= ((s->duration + 2) << 3)) + s->anticollapse_bit = 1 << 3; + totalbits -= s->anticollapse_bit; + + /* band skip bit reservation */ + if (totalbits >= 1 << 3) + skip_bit = 1 << 3; + totalbits -= skip_bit; + + /* intensity/dual stereo bit reservation */ + if (s->coded_channels == 2) { + intensitystereo_bit = celt_log2_frac[s->endband - s->startband]; + if (intensitystereo_bit <= totalbits) { + totalbits -= intensitystereo_bit; + if (totalbits >= 1 << 3) { + dualstereo_bit = 1 << 3; + totalbits -= 1 << 3; + } + } else + intensitystereo_bit = 0; + } + + for (i = s->startband; i < s->endband; i++) { + int trim = alloctrim - 5 - s->duration; + int band = celt_freq_range[i] * (s->endband - i - 1); + int duration = s->duration + 3; + int scale = duration + s->coded_channels - 1; + + /* PVQ minimum allocation threshold, below this value the band is + * skipped */ + threshold[i] = FFMAX(3 * celt_freq_range[i] << duration >> 4, + s->coded_channels << 3); + + trim_offset[i] = trim * (band << scale) >> 6; + + if (celt_freq_range[i] << s->duration == 1) + trim_offset[i] -= s->coded_channels << 3; + } + + /* bisection */ + low = 1; + high = CELT_VECTORS - 1; + while (low <= high) { + int center = (low + high) >> 1; + done = total = 0; + + for (i = s->endband - 1; i >= s->startband; i--) { + bandbits = celt_freq_range[i] * celt_static_alloc[center][i] + << (s->coded_channels - 1) << s->duration >> 2; + + if (bandbits) + bandbits = FFMAX(0, bandbits + trim_offset[i]); + bandbits += boost[i]; + + if (bandbits >= threshold[i] || done) { + done = 1; + total += FFMIN(bandbits, cap[i]); + } else if (bandbits >= s->coded_channels << 3) + total += s->coded_channels << 3; + } + + if (total > totalbits) + high = center - 1; + else + low = center + 1; + } + high = low--; + + for (i = s->startband; i < s->endband; i++) { + bits1[i] = celt_freq_range[i] * celt_static_alloc[low][i] + << (s->coded_channels - 1) << s->duration >> 2; + bits2[i] = high >= CELT_VECTORS ? cap[i] : + celt_freq_range[i] * celt_static_alloc[high][i] + << (s->coded_channels - 1) << s->duration >> 2; + + if (bits1[i]) + bits1[i] = FFMAX(0, bits1[i] + trim_offset[i]); + if (bits2[i]) + bits2[i] = FFMAX(0, bits2[i] + trim_offset[i]); + if (low) + bits1[i] += boost[i]; + bits2[i] += boost[i]; + + if (boost[i]) + skip_startband = i; + bits2[i] = FFMAX(0, bits2[i] - bits1[i]); + } + + /* bisection */ + low = 0; + high = 1 << CELT_ALLOC_STEPS; + for (i = 0; i < CELT_ALLOC_STEPS; i++) { + int center = (low + high) >> 1; + done = total = 0; + + for (j = s->endband - 1; j >= s->startband; j--) { + bandbits = bits1[j] + (center * bits2[j] >> CELT_ALLOC_STEPS); + + if (bandbits >= threshold[j] || done) { + done = 1; + total += FFMIN(bandbits, cap[j]); + } else if (bandbits >= s->coded_channels << 3) + total += s->coded_channels << 3; + } + if (total > totalbits) + high = center; + else + low = center; + } + + done = total = 0; + for (i = s->endband - 1; i >= s->startband; i--) { + bandbits = bits1[i] + (low * bits2[i] >> CELT_ALLOC_STEPS); + + if (bandbits >= threshold[i] || done) + done = 1; + else + bandbits = (bandbits >= s->coded_channels << 3) ? + s->coded_channels << 3 : 0; + + bandbits = FFMIN(bandbits, cap[i]); + s->pulses[i] = bandbits; + total += bandbits; + } + + /* band skipping */ + for (s->codedbands = s->endband; ; s->codedbands--) { + int allocation; + j = s->codedbands - 1; + + if (j == skip_startband) { + /* all remaining bands are not skipped */ + totalbits += skip_bit; + break; + } + + /* determine the number of bits available for coding "do not skip" markers */ + remaining = totalbits - total; + bandbits = remaining / (celt_freq_bands[j+1] - celt_freq_bands[s->startband]); + remaining -= bandbits * (celt_freq_bands[j+1] - celt_freq_bands[s->startband]); + allocation = s->pulses[j] + bandbits * celt_freq_range[j] + + FFMAX(0, remaining - (celt_freq_bands[j] - celt_freq_bands[s->startband])); + + /* a "do not skip" marker is only coded if the allocation is + above the chosen threshold */ + if (allocation >= FFMAX(threshold[j], (s->coded_channels + 1) <<3 )) { + if (opus_rc_p2model(rc, 1)) + break; + + total += 1 << 3; + allocation -= 1 << 3; + } + + /* the band is skipped, so reclaim its bits */ + total -= s->pulses[j]; + if (intensitystereo_bit) { + total -= intensitystereo_bit; + intensitystereo_bit = celt_log2_frac[j - s->startband]; + total += intensitystereo_bit; + } + + total += s->pulses[j] = (allocation >= s->coded_channels << 3) ? + s->coded_channels << 3 : 0; + } + + /* obtain stereo flags */ + s->intensitystereo = 0; + s->dualstereo = 0; + if (intensitystereo_bit) + s->intensitystereo = s->startband + + opus_rc_unimodel(rc, s->codedbands + 1 - s->startband); + if (s->intensitystereo <= s->startband) + totalbits += dualstereo_bit; /* no intensity stereo means no dual stereo */ + else if (dualstereo_bit) + s->dualstereo = opus_rc_p2model(rc, 1); + + /* supply the remaining bits in this frame to lower bands */ + remaining = totalbits - total; + bandbits = remaining / (celt_freq_bands[s->codedbands] - celt_freq_bands[s->startband]); + remaining -= bandbits * (celt_freq_bands[s->codedbands] - celt_freq_bands[s->startband]); + for (i = s->startband; i < s->codedbands; i++) { + int bits = FFMIN(remaining, celt_freq_range[i]); + + s->pulses[i] += bits + bandbits * celt_freq_range[i]; + remaining -= bits; + } + + for (i = s->startband; i < s->codedbands; i++) { + int N = celt_freq_range[i] << s->duration; + int prev_extra = extrabits; + s->pulses[i] += extrabits; + + if (N > 1) { + int dof; // degrees of freedom + int temp; // dof * channels * log(dof) + int offset; // fine energy quantization offset, i.e. + // extra bits assigned over the standard + // totalbits/dof + int fine_bits, max_bits; + + extrabits = FFMAX(0, s->pulses[i] - cap[i]); + s->pulses[i] -= extrabits; + + /* intensity stereo makes use of an extra degree of freedom */ + dof = N * s->coded_channels + + (s->coded_channels == 2 && N > 2 && !s->dualstereo && i < s->intensitystereo); + temp = dof * (celt_log_freq_range[i] + (s->duration<<3)); + offset = (temp >> 1) - dof * CELT_FINE_OFFSET; + if (N == 2) /* dof=2 is the only case that doesn't fit the model */ + offset += dof<<1; + + /* grant an additional bias for the first and second pulses */ + if (s->pulses[i] + offset < 2 * (dof << 3)) + offset += temp >> 2; + else if (s->pulses[i] + offset < 3 * (dof << 3)) + offset += temp >> 3; + + fine_bits = (s->pulses[i] + offset + (dof << 2)) / (dof << 3); + max_bits = FFMIN((s->pulses[i]>>3) >> (s->coded_channels - 1), + CELT_MAX_FINE_BITS); + + max_bits = FFMAX(max_bits, 0); + + s->fine_bits[i] = av_clip(fine_bits, 0, max_bits); + + /* if fine_bits was rounded down or capped, + give priority for the final fine energy pass */ + s->fine_priority[i] = (s->fine_bits[i] * (dof<<3) >= s->pulses[i] + offset); + + /* the remaining bits are assigned to PVQ */ + s->pulses[i] -= s->fine_bits[i] << (s->coded_channels - 1) << 3; + } else { + /* all bits go to fine energy except for the sign bit */ + extrabits = FFMAX(0, s->pulses[i] - (s->coded_channels << 3)); + s->pulses[i] -= extrabits; + s->fine_bits[i] = 0; + s->fine_priority[i] = 1; + } + + /* hand back a limited number of extra fine energy bits to this band */ + if (extrabits > 0) { + int fineextra = FFMIN(extrabits >> (s->coded_channels + 2), + CELT_MAX_FINE_BITS - s->fine_bits[i]); + s->fine_bits[i] += fineextra; + + fineextra <<= s->coded_channels + 2; + s->fine_priority[i] = (fineextra >= extrabits - prev_extra); + extrabits -= fineextra; + } + } + s->remaining = extrabits; + + /* skipped bands dedicate all of their bits for fine energy */ + for (; i < s->endband; i++) { + s->fine_bits[i] = s->pulses[i] >> (s->coded_channels - 1) >> 3; + s->pulses[i] = 0; + s->fine_priority[i] = s->fine_bits[i] < 1; + } +} + +static inline int celt_bits2pulses(const uint8_t *cache, int bits) +{ + // TODO: Find the size of cache and make it into an array in the parameters list + int i, low = 0, high; + + high = cache[0]; + bits--; + + for (i = 0; i < 6; i++) { + int center = (low + high + 1) >> 1; + if (cache[center] >= bits) + high = center; + else + low = center; + } + + return (bits - (low == 0 ? -1 : cache[low]) <= cache[high] - bits) ? low : high; +} + +static inline int celt_pulses2bits(const uint8_t *cache, int pulses) +{ + // TODO: Find the size of cache and make it into an array in the parameters list + return (pulses == 0) ? 0 : cache[pulses] + 1; +} + +static inline void celt_normalize_residual(const int * av_restrict iy, float * av_restrict X, + int N, float g) +{ + int i; + for (i = 0; i < N; i++) + X[i] = g * iy[i]; +} + +static void celt_exp_rotation1(float *X, unsigned int len, unsigned int stride, + float c, float s) +{ + float *Xptr; + int i; + + Xptr = X; + for (i = 0; i < len - stride; i++) { + float x1, x2; + x1 = Xptr[0]; + x2 = Xptr[stride]; + Xptr[stride] = c * x2 + s * x1; + *Xptr++ = c * x1 - s * x2; + } + + Xptr = &X[len - 2 * stride - 1]; + for (i = len - 2 * stride - 1; i >= 0; i--) { + float x1, x2; + x1 = Xptr[0]; + x2 = Xptr[stride]; + Xptr[stride] = c * x2 + s * x1; + *Xptr-- = c * x1 - s * x2; + } +} + +static inline void celt_exp_rotation(float *X, unsigned int len, + unsigned int stride, unsigned int K, + enum CeltSpread spread) +{ + unsigned int stride2 = 0; + float c, s; + float gain, theta; + int i; + + if (2*K >= len || spread == CELT_SPREAD_NONE) + return; + + gain = (float)len / (len + (20 - 5*spread) * K); + theta = M_PI * gain * gain / 4; + + c = cos(theta); + s = sin(theta); + + if (len >= stride << 3) { + stride2 = 1; + /* This is just a simple (equivalent) way of computing sqrt(len/stride) with rounding. + It's basically incrementing long as (stride2+0.5)^2 < len/stride. */ + while ((stride2 * stride2 + stride2) * stride + (stride >> 2) < len) + stride2++; + } + + /*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for + extract_collapse_mask().*/ + len /= stride; + for (i = 0; i < stride; i++) { + if (stride2) + celt_exp_rotation1(X + i * len, len, stride2, s, c); + celt_exp_rotation1(X + i * len, len, 1, c, s); + } +} + +static inline unsigned int celt_extract_collapse_mask(const int *iy, + unsigned int N, + unsigned int B) +{ + unsigned int collapse_mask; + int N0; + int i, j; + + if (B <= 1) + return 1; + + /*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for + exp_rotation().*/ + N0 = N/B; + collapse_mask = 0; + for (i = 0; i < B; i++) + for (j = 0; j < N0; j++) + collapse_mask |= (iy[i*N0+j]!=0)<>= 1; + for (i = 0; i < stride; i++) { + for (j = 0; j < N0; j++) { + float x0 = X[stride * (2 * j + 0) + i]; + float x1 = X[stride * (2 * j + 1) + i]; + X[stride * (2 * j + 0) + i] = (x0 + x1) * M_SQRT1_2; + X[stride * (2 * j + 1) + i] = (x0 - x1) * M_SQRT1_2; + } + } +} + +static inline int celt_compute_qn(int N, int b, int offset, int pulse_cap, + int dualstereo) +{ + int qn, qb; + int N2 = 2 * N - 1; + if (dualstereo && N == 2) + N2--; + + /* The upper limit ensures that in a stereo split with itheta==16384, we'll + * always have enough bits left over to code at least one pulse in the + * side; otherwise it would collapse, since it doesn't get folded. */ + qb = FFMIN3(b - pulse_cap - (4 << 3), (b + N2 * offset) / N2, 8 << 3); + qn = (qb < (1 << 3 >> 1)) ? 1 : ((celt_qn_exp2[qb & 0x7] >> (14 - (qb >> 3))) + 1) >> 1 << 1; + return qn; +} + +// this code was adapted from libopus +static inline uint64_t celt_cwrsi(unsigned int N, unsigned int K, unsigned int i, int *y) +{ + uint64_t norm = 0; + uint32_t p; + int s, val; + int k0; + + while (N > 2) { + uint32_t q; + + /*Lots of pulses case:*/ + if (K >= N) { + const uint32_t *row = celt_pvq_u_row[N]; + + /* Are the pulses in this dimension negative? */ + p = row[K + 1]; + s = -(i >= p); + i -= p & s; + + /*Count how many pulses were placed in this dimension.*/ + k0 = K; + q = row[N]; + if (q > i) { + K = N; + do { + p = celt_pvq_u_row[--K][N]; + } while (p > i); + } else + for (p = row[K]; p > i; p = row[K]) + K--; + + i -= p; + val = (k0 - K + s) ^ s; + norm += val * val; + *y++ = val; + } else { /*Lots of dimensions case:*/ + /*Are there any pulses in this dimension at all?*/ + p = celt_pvq_u_row[K ][N]; + q = celt_pvq_u_row[K + 1][N]; + + if (p <= i && i < q) { + i -= p; + *y++ = 0; + } else { + /*Are the pulses in this dimension negative?*/ + s = -(i >= q); + i -= q & s; + + /*Count how many pulses were placed in this dimension.*/ + k0 = K; + do p = celt_pvq_u_row[--K][N]; + while (p > i); + + i -= p; + val = (k0 - K + s) ^ s; + norm += val * val; + *y++ = val; + } + } + N--; + } + + /* N == 2 */ + p = 2 * K + 1; + s = -(i >= p); + i -= p & s; + k0 = K; + K = (i + 1) / 2; + + if (K) + i -= 2 * K - 1; + + val = (k0 - K + s) ^ s; + norm += val * val; + *y++ = val; + + /* N==1 */ + s = -i; + val = (K + s) ^ s; + norm += val * val; + *y = val; + + return norm; +} + +static inline float celt_decode_pulses(OpusRangeCoder *rc, int *y, unsigned int N, unsigned int K) +{ + unsigned int idx; +#define CELT_PVQ_U(n, k) (celt_pvq_u_row[FFMIN(n, k)][FFMAX(n, k)]) +#define CELT_PVQ_V(n, k) (CELT_PVQ_U(n, k) + CELT_PVQ_U(n, (k) + 1)) + idx = opus_rc_unimodel(rc, CELT_PVQ_V(N, K)); + return celt_cwrsi(N, K, idx, y); +} + +/** Decode pulse vector and combine the result with the pitch vector to produce + the final normalised signal in the current band. */ +static inline unsigned int celt_alg_unquant(OpusRangeCoder *rc, float *X, + unsigned int N, unsigned int K, + enum CeltSpread spread, + unsigned int blocks, float gain) +{ + int y[176]; + + gain /= sqrtf(celt_decode_pulses(rc, y, N, K)); + celt_normalize_residual(y, X, N, gain); + celt_exp_rotation(X, N, blocks, K, spread); + return celt_extract_collapse_mask(y, N, blocks); +} + +static unsigned int celt_decode_band(CeltContext *s, OpusRangeCoder *rc, + const int band, float *X, float *Y, + int N, int b, unsigned int blocks, + float *lowband, int duration, + float *lowband_out, int level, + float gain, float *lowband_scratch, + int fill) +{ + const uint8_t *cache; + int dualstereo, split; + int imid = 0, iside = 0; + unsigned int N0 = N; + int N_B; + int N_B0; + int B0 = blocks; + int time_divide = 0; + int recombine = 0; + int inv = 0; + float mid = 0, side = 0; + int longblocks = (B0 == 1); + unsigned int cm = 0; + + N_B0 = N_B = N / blocks; + split = dualstereo = (Y != NULL); + + if (N == 1) { + /* special case for one sample */ + int i; + float *x = X; + for (i = 0; i <= dualstereo; i++) { + int sign = 0; + if (s->remaining2 >= 1<<3) { + sign = opus_getrawbits(rc, 1); + s->remaining2 -= 1 << 3; + b -= 1 << 3; + } + x[0] = sign ? -1.0f : 1.0f; + x = Y; + } + if (lowband_out) + lowband_out[0] = X[0]; + return 1; + } + + if (!dualstereo && level == 0) { + int tf_change = s->tf_change[band]; + int k; + if (tf_change > 0) + recombine = tf_change; + /* Band recombining to increase frequency resolution */ + + if (lowband && + (recombine || ((N_B & 1) == 0 && tf_change < 0) || B0 > 1)) { + int j; + for (j = 0; j < N; j++) + lowband_scratch[j] = lowband[j]; + lowband = lowband_scratch; + } + + for (k = 0; k < recombine; k++) { + if (lowband) + celt_haar1(lowband, N >> k, 1 << k); + fill = celt_bit_interleave[fill & 0xF] | celt_bit_interleave[fill >> 4] << 2; + } + blocks >>= recombine; + N_B <<= recombine; + + /* Increasing the time resolution */ + while ((N_B & 1) == 0 && tf_change < 0) { + if (lowband) + celt_haar1(lowband, N_B, blocks); + fill |= fill << blocks; + blocks <<= 1; + N_B >>= 1; + time_divide++; + tf_change++; + } + B0 = blocks; + N_B0 = N_B; + + /* Reorganize the samples in time order instead of frequency order */ + if (B0 > 1 && lowband) + celt_deinterleave_hadamard(s->scratch, lowband, N_B >> recombine, + B0 << recombine, longblocks); + } + + /* If we need 1.5 more bit than we can produce, split the band in two. */ + cache = celt_cache_bits + + celt_cache_index[(duration + 1) * CELT_MAX_BANDS + band]; + if (!dualstereo && duration >= 0 && b > cache[cache[0]] + 12 && N > 2) { + N >>= 1; + Y = X + N; + split = 1; + duration -= 1; + if (blocks == 1) + fill = (fill & 1) | (fill << 1); + blocks = (blocks + 1) >> 1; + } + + if (split) { + int qn; + int itheta = 0; + int mbits, sbits, delta; + int qalloc; + int pulse_cap; + int offset; + int orig_fill; + int tell; + + /* Decide on the resolution to give to the split parameter theta */ + pulse_cap = celt_log_freq_range[band] + duration * 8; + offset = (pulse_cap >> 1) - (dualstereo && N == 2 ? CELT_QTHETA_OFFSET_TWOPHASE : + CELT_QTHETA_OFFSET); + qn = (dualstereo && band >= s->intensitystereo) ? 1 : + celt_compute_qn(N, b, offset, pulse_cap, dualstereo); + tell = opus_rc_tell_frac(rc); + if (qn != 1) { + /* Entropy coding of the angle. We use a uniform pdf for the + time split, a step for stereo, and a triangular one for the rest. */ + if (dualstereo && N > 2) + itheta = opus_rc_stepmodel(rc, qn/2); + else if (dualstereo || B0 > 1) + itheta = opus_rc_unimodel(rc, qn+1); + else + itheta = opus_rc_trimodel(rc, qn); + itheta = itheta * 16384 / qn; + /* NOTE: Renormalising X and Y *may* help fixed-point a bit at very high rate. + Let's do that at higher complexity */ + } else if (dualstereo) { + inv = (b > 2 << 3 && s->remaining2 > 2 << 3) ? opus_rc_p2model(rc, 2) : 0; + itheta = 0; + } + qalloc = opus_rc_tell_frac(rc) - tell; + b -= qalloc; + + orig_fill = fill; + if (itheta == 0) { + imid = 32767; + iside = 0; + fill &= (1 << blocks) - 1; + delta = -16384; + } else if (itheta == 16384) { + imid = 0; + iside = 32767; + fill &= ((1 << blocks) - 1) << blocks; + delta = 16384; + } else { + imid = celt_cos(itheta); + iside = celt_cos(16384-itheta); + /* This is the mid vs side allocation that minimizes squared error + in that band. */ + delta = ROUND_MUL16((N - 1) << 7, celt_log2tan(iside, imid)); + } + + mid = imid / 32768.0f; + side = iside / 32768.0f; + + /* This is a special case for N=2 that only works for stereo and takes + advantage of the fact that mid and side are orthogonal to encode + the side with just one bit. */ + if (N == 2 && dualstereo) { + int c; + int sign = 0; + float tmp; + float *x2, *y2; + mbits = b; + /* Only need one bit for the side */ + sbits = (itheta != 0 && itheta != 16384) ? 1 << 3 : 0; + mbits -= sbits; + c = (itheta > 8192); + s->remaining2 -= qalloc+sbits; + + x2 = c ? Y : X; + y2 = c ? X : Y; + if (sbits) + sign = opus_getrawbits(rc, 1); + sign = 1 - 2 * sign; + /* We use orig_fill here because we want to fold the side, but if + itheta==16384, we'll have cleared the low bits of fill. */ + cm = celt_decode_band(s, rc, band, x2, NULL, N, mbits, blocks, + lowband, duration, lowband_out, level, gain, + lowband_scratch, orig_fill); + /* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse), + and there's no need to worry about mixing with the other channel. */ + y2[0] = -sign * x2[1]; + y2[1] = sign * x2[0]; + X[0] *= mid; + X[1] *= mid; + Y[0] *= side; + Y[1] *= side; + tmp = X[0]; + X[0] = tmp - Y[0]; + Y[0] = tmp + Y[0]; + tmp = X[1]; + X[1] = tmp - Y[1]; + Y[1] = tmp + Y[1]; + } else { + /* "Normal" split code */ + float *next_lowband2 = NULL; + float *next_lowband_out1 = NULL; + int next_level = 0; + int rebalance; + + /* Give more bits to low-energy MDCTs than they would + * otherwise deserve */ + if (B0 > 1 && !dualstereo && (itheta & 0x3fff)) { + if (itheta > 8192) + /* Rough approximation for pre-echo masking */ + delta -= delta >> (4 - duration); + else + /* Corresponds to a forward-masking slope of + * 1.5 dB per 10 ms */ + delta = FFMIN(0, delta + (N << 3 >> (5 - duration))); + } + mbits = av_clip((b - delta) / 2, 0, b); + sbits = b - mbits; + s->remaining2 -= qalloc; + + if (lowband && !dualstereo) + next_lowband2 = lowband + N; /* >32-bit split case */ + + /* Only stereo needs to pass on lowband_out. + * Otherwise, it's handled at the end */ + if (dualstereo) + next_lowband_out1 = lowband_out; + else + next_level = level + 1; + + rebalance = s->remaining2; + if (mbits >= sbits) { + /* In stereo mode, we do not apply a scaling to the mid + * because we need the normalized mid for folding later */ + cm = celt_decode_band(s, rc, band, X, NULL, N, mbits, blocks, + lowband, duration, next_lowband_out1, + next_level, dualstereo ? 1.0f : (gain * mid), + lowband_scratch, fill); + + rebalance = mbits - (rebalance - s->remaining2); + if (rebalance > 3 << 3 && itheta != 0) + sbits += rebalance - (3 << 3); + + /* For a stereo split, the high bits of fill are always zero, + * so no folding will be done to the side. */ + cm |= celt_decode_band(s, rc, band, Y, NULL, N, sbits, blocks, + next_lowband2, duration, NULL, + next_level, gain * side, NULL, + fill >> blocks) << ((B0 >> 1) & (dualstereo - 1)); + } else { + /* For a stereo split, the high bits of fill are always zero, + * so no folding will be done to the side. */ + cm = celt_decode_band(s, rc, band, Y, NULL, N, sbits, blocks, + next_lowband2, duration, NULL, + next_level, gain * side, NULL, + fill >> blocks) << ((B0 >> 1) & (dualstereo - 1)); + + rebalance = sbits - (rebalance - s->remaining2); + if (rebalance > 3 << 3 && itheta != 16384) + mbits += rebalance - (3 << 3); + + /* In stereo mode, we do not apply a scaling to the mid because + * we need the normalized mid for folding later */ + cm |= celt_decode_band(s, rc, band, X, NULL, N, mbits, blocks, + lowband, duration, next_lowband_out1, + next_level, dualstereo ? 1.0f : (gain * mid), + lowband_scratch, fill); + } + } + } else { + /* This is the basic no-split case */ + unsigned int q = celt_bits2pulses(cache, b); + unsigned int curr_bits = celt_pulses2bits(cache, q); + s->remaining2 -= curr_bits; + + /* Ensures we can never bust the budget */ + while (s->remaining2 < 0 && q > 0) { + s->remaining2 += curr_bits; + curr_bits = celt_pulses2bits(cache, --q); + s->remaining2 -= curr_bits; + } + + if (q != 0) { + /* Finally do the actual quantization */ + cm = celt_alg_unquant(rc, X, N, (q < 8) ? q : (8 + (q & 7)) << ((q >> 3) - 1), + s->spread, blocks, gain); + } else { + /* If there's no pulse, fill the band anyway */ + int j; + unsigned int cm_mask = (1 << blocks) - 1; + fill &= cm_mask; + if (!fill) { + for (j = 0; j < N; j++) + X[j] = 0.0f; + } else { + if (lowband == NULL) { + /* Noise */ + for (j = 0; j < N; j++) + X[j] = (((int32_t)celt_rng(s)) >> 20); + cm = cm_mask; + } else { + /* Folded spectrum */ + for (j = 0; j < N; j++) { + /* About 48 dB below the "normal" folding level */ + X[j] = lowband[j] + (((celt_rng(s)) & 0x8000) ? 1.0f / 256 : -1.0f / 256); + } + cm = fill; + } + celt_renormalize_vector(X, N, gain); + } + } + } + + /* This code is used by the decoder and by the resynthesis-enabled encoder */ + if (dualstereo) { + int j; + if (N != 2) + celt_stereo_merge(X, Y, mid, N); + if (inv) { + for (j = 0; j < N; j++) + Y[j] *= -1; + } + } else if (level == 0) { + int k; + + /* Undo the sample reorganization going from time order to frequency order */ + if (B0 > 1) + celt_interleave_hadamard(s->scratch, X, N_B>>recombine, + B0<>= 1; + N_B <<= 1; + cm |= cm >> blocks; + celt_haar1(X, N_B, blocks); + } + + for (k = 0; k < recombine; k++) { + cm = celt_bit_deinterleave[cm]; + celt_haar1(X, N0>>k, 1<startband; i < s->endband; i++) { + float *dst = data + (celt_freq_bands[i] << s->duration); + float norm = pow(2, frame->energy[i] + celt_mean_energy[i]); + + for (j = 0; j < celt_freq_range[i] << s->duration; j++) + dst[j] *= norm; + } +} + +static void celt_postfilter_apply_transition(CeltFrame *frame, float *data) +{ + const int T0 = frame->pf_period_old; + const int T1 = frame->pf_period; + + float g00, g01, g02; + float g10, g11, g12; + + float x0, x1, x2, x3, x4; + + int i; + + if (frame->pf_gains[0] == 0.0 && + frame->pf_gains_old[0] == 0.0) + return; + + g00 = frame->pf_gains_old[0]; + g01 = frame->pf_gains_old[1]; + g02 = frame->pf_gains_old[2]; + g10 = frame->pf_gains[0]; + g11 = frame->pf_gains[1]; + g12 = frame->pf_gains[2]; + + x1 = data[-T1 + 1]; + x2 = data[-T1]; + x3 = data[-T1 - 1]; + x4 = data[-T1 - 2]; + + for (i = 0; i < CELT_OVERLAP; i++) { + float w = ff_celt_window2[i]; + x0 = data[i - T1 + 2]; + + data[i] += (1.0 - w) * g00 * data[i - T0] + + (1.0 - w) * g01 * (data[i - T0 - 1] + data[i - T0 + 1]) + + (1.0 - w) * g02 * (data[i - T0 - 2] + data[i - T0 + 2]) + + w * g10 * x2 + + w * g11 * (x1 + x3) + + w * g12 * (x0 + x4); + x4 = x3; + x3 = x2; + x2 = x1; + x1 = x0; + } +} + +static void celt_postfilter_apply(CeltFrame *frame, + float *data, int len) +{ + const int T = frame->pf_period; + float g0, g1, g2; + float x0, x1, x2, x3, x4; + int i; + + if (frame->pf_gains[0] == 0.0 || len <= 0) + return; + + g0 = frame->pf_gains[0]; + g1 = frame->pf_gains[1]; + g2 = frame->pf_gains[2]; + + x4 = data[-T - 2]; + x3 = data[-T - 1]; + x2 = data[-T]; + x1 = data[-T + 1]; + + for (i = 0; i < len; i++) { + x0 = data[i - T + 2]; + data[i] += g0 * x2 + + g1 * (x1 + x3) + + g2 * (x0 + x4); + x4 = x3; + x3 = x2; + x2 = x1; + x1 = x0; + } +} + +static void celt_postfilter(CeltContext *s, CeltFrame *frame) +{ + int len = s->blocksize * s->blocks; + + celt_postfilter_apply_transition(frame, frame->buf + 1024); + + frame->pf_period_old = frame->pf_period; + memcpy(frame->pf_gains_old, frame->pf_gains, sizeof(frame->pf_gains)); + + frame->pf_period = frame->pf_period_new; + memcpy(frame->pf_gains, frame->pf_gains_new, sizeof(frame->pf_gains)); + + if (len > CELT_OVERLAP) { + celt_postfilter_apply_transition(frame, frame->buf + 1024 + CELT_OVERLAP); + celt_postfilter_apply(frame, frame->buf + 1024 + 2 * CELT_OVERLAP, + len - 2 * CELT_OVERLAP); + + frame->pf_period_old = frame->pf_period; + memcpy(frame->pf_gains_old, frame->pf_gains, sizeof(frame->pf_gains)); + } + + memmove(frame->buf, frame->buf + len, (1024 + CELT_OVERLAP / 2) * sizeof(float)); +} + +static int parse_postfilter(CeltContext *s, OpusRangeCoder *rc, int consumed) +{ + static const float postfilter_taps[3][3] = { + { 0.3066406250f, 0.2170410156f, 0.1296386719f }, + { 0.4638671875f, 0.2680664062f, 0.0 }, + { 0.7998046875f, 0.1000976562f, 0.0 } + }; + int i; + + memset(s->frame[0].pf_gains_new, 0, sizeof(s->frame[0].pf_gains_new)); + memset(s->frame[1].pf_gains_new, 0, sizeof(s->frame[1].pf_gains_new)); + + if (s->startband == 0 && consumed + 16 <= s->framebits) { + int has_postfilter = opus_rc_p2model(rc, 1); + if (has_postfilter) { + float gain; + int tapset, octave, period; + + octave = opus_rc_unimodel(rc, 6); + period = (16 << octave) + opus_getrawbits(rc, 4 + octave) - 1; + gain = 0.09375f * (opus_getrawbits(rc, 3) + 1); + tapset = (opus_rc_tell(rc) + 2 <= s->framebits) ? + opus_rc_getsymbol(rc, celt_model_tapset) : 0; + + for (i = 0; i < 2; i++) { + CeltFrame *frame = &s->frame[i]; + + frame->pf_period_new = FFMAX(period, CELT_POSTFILTER_MINPERIOD); + frame->pf_gains_new[0] = gain * postfilter_taps[tapset][0]; + frame->pf_gains_new[1] = gain * postfilter_taps[tapset][1]; + frame->pf_gains_new[2] = gain * postfilter_taps[tapset][2]; + } + } + + consumed = opus_rc_tell(rc); + } + + return consumed; +} + +static void process_anticollapse(CeltContext *s, CeltFrame *frame, float *X) +{ + int i, j, k; + + for (i = s->startband; i < s->endband; i++) { + int renormalize = 0; + float *xptr; + float prev[2]; + float Ediff, r; + float thresh, sqrt_1; + int depth; + + /* depth in 1/8 bits */ + depth = (1 + s->pulses[i]) / (celt_freq_range[i] << s->duration); + thresh = pow(2, -1.0 - 0.125f * depth); + sqrt_1 = 1.0f / sqrtf(celt_freq_range[i] << s->duration); + + xptr = X + (celt_freq_bands[i] << s->duration); + + prev[0] = frame->prev_energy[0][i]; + prev[1] = frame->prev_energy[1][i]; + if (s->coded_channels == 1) { + CeltFrame *frame1 = &s->frame[1]; + + prev[0] = FFMAX(prev[0], frame1->prev_energy[0][i]); + prev[1] = FFMAX(prev[1], frame1->prev_energy[1][i]); + } + Ediff = frame->energy[i] - FFMIN(prev[0], prev[1]); + Ediff = FFMAX(0, Ediff); + + /* r needs to be multiplied by 2 or 2*sqrt(2) depending on LM because + short blocks don't have the same energy as long */ + r = pow(2, 1 - Ediff); + if (s->duration == 3) + r *= M_SQRT2; + r = FFMIN(thresh, r) * sqrt_1; + for (k = 0; k < 1 << s->duration; k++) { + /* Detect collapse */ + if (!(frame->collapse_masks[i] & 1 << k)) { + /* Fill with noise */ + for (j = 0; j < celt_freq_range[i]; j++) + xptr[(j << s->duration) + k] = (celt_rng(s) & 0x8000) ? r : -r; + renormalize = 1; + } + } + + /* We just added some energy, so we need to renormalize */ + if (renormalize) + celt_renormalize_vector(xptr, celt_freq_range[i] << s->duration, 1.0f); + } +} + +static void celt_decode_bands(CeltContext *s, OpusRangeCoder *rc) +{ + float lowband_scratch[8 * 22]; + float norm[2 * 8 * 100]; + + int totalbits = (s->framebits << 3) - s->anticollapse_bit; + + int update_lowband = 1; + int lowband_offset = 0; + + int i, j; + + memset(s->coeffs, 0, sizeof(s->coeffs)); + + for (i = s->startband; i < s->endband; i++) { + int band_offset = celt_freq_bands[i] << s->duration; + int band_size = celt_freq_range[i] << s->duration; + float *X = s->coeffs[0] + band_offset; + float *Y = (s->coded_channels == 2) ? s->coeffs[1] + band_offset : NULL; + + int consumed = opus_rc_tell_frac(rc); + float *norm2 = norm + 8 * 100; + int effective_lowband = -1; + unsigned int cm[2]; + int b; + + /* Compute how many bits we want to allocate to this band */ + if (i != s->startband) + s->remaining -= consumed; + 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); + } else + b = 0; + + if (celt_freq_bands[i] - celt_freq_range[i] >= celt_freq_bands[s->startband] && + (update_lowband || lowband_offset == 0)) + lowband_offset = i; + + /* Get a conservative estimate of the collapse_mask's for the bands we're + going to be folding from. */ + if (lowband_offset != 0 && (s->spread != CELT_SPREAD_AGGRESSIVE || + s->blocks > 1 || s->tf_change[i] < 0)) { + int foldstart, foldend; + + /* This ensures we never repeat spectral content within one band */ + effective_lowband = FFMAX(celt_freq_bands[s->startband], + celt_freq_bands[lowband_offset] - celt_freq_range[i]); + foldstart = lowband_offset; + while (celt_freq_bands[--foldstart] > effective_lowband); + foldend = lowband_offset - 1; + while (celt_freq_bands[++foldend] < effective_lowband + celt_freq_range[i]); + + cm[0] = cm[1] = 0; + for (j = foldstart; j < foldend; j++) { + cm[0] |= s->frame[0].collapse_masks[j]; + cm[1] |= s->frame[s->coded_channels - 1].collapse_masks[j]; + } + } else + /* Otherwise, we'll be using the LCG to fold, so all blocks will (almost + always) be non-zero.*/ + cm[0] = cm[1] = (1 << s->blocks) - 1; + + if (s->dualstereo && i == s->intensitystereo) { + /* Switch off dual stereo to do intensity */ + s->dualstereo = 0; + for (j = celt_freq_bands[s->startband] << s->duration; j < band_offset; j++) + norm[j] = (norm[j] + norm2[j]) / 2; + } + + if (s->dualstereo) { + cm[0] = celt_decode_band(s, rc, i, X, NULL, band_size, b / 2, s->blocks, + effective_lowband != -1 ? norm + (effective_lowband << s->duration) : NULL, s->duration, + norm + band_offset, 0, 1.0f, lowband_scratch, cm[0]); + + cm[1] = celt_decode_band(s, rc, i, Y, NULL, band_size, b/2, s->blocks, + effective_lowband != -1 ? norm2 + (effective_lowband << s->duration) : NULL, s->duration, + norm2 + band_offset, 0, 1.0f, lowband_scratch, cm[1]); + } else { + cm[0] = celt_decode_band(s, rc, i, X, Y, band_size, b, s->blocks, + effective_lowband != -1 ? norm + (effective_lowband << s->duration) : NULL, s->duration, + norm + band_offset, 0, 1.0f, lowband_scratch, cm[0]|cm[1]); + + cm[1] = cm[0]; + } + + s->frame[0].collapse_masks[i] = (uint8_t)cm[0]; + s->frame[s->coded_channels - 1].collapse_masks[i] = (uint8_t)cm[1]; + s->remaining += s->pulses[i] + consumed; + + /* Update the folding position only as long as we have 1 bit/sample depth */ + update_lowband = (b > band_size << 3); + } +} + +int ff_celt_decode_frame(CeltContext *s, OpusRangeCoder *rc, + float **output, int coded_channels, int frame_size, + int startband, int endband) +{ + int i, j; + + int consumed; // bits of entropy consumed thus far for this frame + int silence = 0; + int transient = 0; + int anticollapse = 0; + CeltIMDCTContext *imdct; + float imdct_scale = 1.0; + + if (coded_channels != 1 && coded_channels != 2) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid number of coded channels: %d\n", + coded_channels); + return AVERROR_INVALIDDATA; + } + if (startband < 0 || startband > endband || endband > CELT_MAX_BANDS) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid start/end band: %d %d\n", + startband, endband); + return AVERROR_INVALIDDATA; + } + + s->flushed = 0; + s->coded_channels = coded_channels; + s->startband = startband; + s->endband = endband; + s->framebits = rc->rb.bytes * 8; + + s->duration = av_log2(frame_size / CELT_SHORT_BLOCKSIZE); + if (s->duration > CELT_MAX_LOG_BLOCKS || + frame_size != CELT_SHORT_BLOCKSIZE * (1 << s->duration)) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid CELT frame size: %d\n", + frame_size); + return AVERROR_INVALIDDATA; + } + + if (!s->output_channels) + s->output_channels = coded_channels; + + memset(s->frame[0].collapse_masks, 0, sizeof(s->frame[0].collapse_masks)); + memset(s->frame[1].collapse_masks, 0, sizeof(s->frame[1].collapse_masks)); + + consumed = opus_rc_tell(rc); + + /* obtain silence flag */ + if (consumed >= s->framebits) + silence = 1; + else if (consumed == 1) + silence = opus_rc_p2model(rc, 15); + + + if (silence) { + consumed = s->framebits; + rc->total_read_bits += s->framebits - opus_rc_tell(rc); + } + + /* obtain post-filter options */ + consumed = parse_postfilter(s, rc, consumed); + + /* obtain transient flag */ + if (s->duration != 0 && consumed+3 <= s->framebits) + transient = opus_rc_p2model(rc, 3); + + s->blocks = transient ? 1 << s->duration : 1; + s->blocksize = frame_size / s->blocks; + + imdct = s->imdct[transient ? 0 : s->duration]; + + if (coded_channels == 1) { + for (i = 0; i < CELT_MAX_BANDS; i++) + s->frame[0].energy[i] = FFMAX(s->frame[0].energy[i], s->frame[1].energy[i]); + } + + celt_decode_coarse_energy(s, rc); + celt_decode_tf_changes (s, rc, transient); + celt_decode_allocation (s, rc); + celt_decode_fine_energy (s, rc); + celt_decode_bands (s, rc); + + if (s->anticollapse_bit) + anticollapse = opus_getrawbits(rc, 1); + + celt_decode_final_energy(s, rc, s->framebits - opus_rc_tell(rc)); + + /* apply anti-collapse processing and denormalization to + * each coded channel */ + for (i = 0; i < s->coded_channels; i++) { + CeltFrame *frame = &s->frame[i]; + + if (anticollapse) + process_anticollapse(s, frame, s->coeffs[i]); + + celt_denormalize(s, frame, s->coeffs[i]); + } + + /* stereo -> mono downmix */ + if (s->output_channels < s->coded_channels) { + s->dsp.vector_fmac_scalar(s->coeffs[0], s->coeffs[1], 1.0, FFALIGN(frame_size, 16)); + imdct_scale = 0.5; + } else if (s->output_channels > s->coded_channels) + memcpy(s->coeffs[1], s->coeffs[0], frame_size * sizeof(float)); + + if (silence) { + for (i = 0; i < 2; i++) { + CeltFrame *frame = &s->frame[i]; + + for (j = 0; j < FF_ARRAY_ELEMS(frame->energy); j++) + frame->energy[j] = CELT_ENERGY_SILENCE; + } + memset(s->coeffs, 0, sizeof(s->coeffs)); + } + + /* transform and output for each output channel */ + for (i = 0; i < s->output_channels; i++) { + CeltFrame *frame = &s->frame[i]; + float m = frame->deemph_coeff; + + /* iMDCT and overlap-add */ + for (j = 0; j < s->blocks; j++) { + float *dst = frame->buf + 1024 + j * s->blocksize; + + imdct->imdct_half(imdct, dst + CELT_OVERLAP / 2, s->coeffs[i] + j, + s->blocks, imdct_scale); + s->dsp.vector_fmul_window(dst, dst, dst + CELT_OVERLAP / 2, + celt_window, CELT_OVERLAP / 2); + } + + /* postfilter */ + celt_postfilter(s, frame); + + /* deemphasis and output scaling */ + for (j = 0; j < frame_size; j++) { + float tmp = frame->buf[1024 - frame_size + j] + m; + m = tmp * CELT_DEEMPH_COEFF; + output[i][j] = tmp / 32768.; + } + frame->deemph_coeff = m; + } + + if (coded_channels == 1) + memcpy(s->frame[1].energy, s->frame[0].energy, sizeof(s->frame[0].energy)); + + for (i = 0; i < 2; i++ ) { + CeltFrame *frame = &s->frame[i]; + + if (!transient) { + memcpy(frame->prev_energy[1], frame->prev_energy[0], sizeof(frame->prev_energy[0])); + memcpy(frame->prev_energy[0], frame->energy, sizeof(frame->prev_energy[0])); + } else { + for (j = 0; j < CELT_MAX_BANDS; j++) + frame->prev_energy[0][j] = FFMIN(frame->prev_energy[0][j], frame->energy[j]); + } + + for (j = 0; j < s->startband; j++) { + frame->prev_energy[0][j] = CELT_ENERGY_SILENCE; + frame->energy[j] = 0.0; + } + for (j = s->endband; j < CELT_MAX_BANDS; j++) { + frame->prev_energy[0][j] = CELT_ENERGY_SILENCE; + frame->energy[j] = 0.0; + } + } + + s->seed = rc->range; + + return 0; +} + +void ff_celt_flush(CeltContext *s) +{ + int i, j; + + if (s->flushed) + return; + + for (i = 0; i < 2; i++) { + CeltFrame *frame = &s->frame[i]; + + for (j = 0; j < CELT_MAX_BANDS; j++) + frame->prev_energy[0][j] = frame->prev_energy[1][j] = CELT_ENERGY_SILENCE; + + memset(frame->energy, 0, sizeof(frame->energy)); + memset(frame->buf, 0, sizeof(frame->buf)); + + memset(frame->pf_gains, 0, sizeof(frame->pf_gains)); + memset(frame->pf_gains_old, 0, sizeof(frame->pf_gains_old)); + memset(frame->pf_gains_new, 0, sizeof(frame->pf_gains_new)); + + frame->deemph_coeff = 0.0; + } + s->seed = 0; + + s->flushed = 1; +} + +void ff_celt_free(CeltContext **ps) +{ + CeltContext *s = *ps; + int i; + + if (!s) + return; + + for (i = 0; i < FF_ARRAY_ELEMS(s->imdct); i++) + ff_celt_imdct_uninit(&s->imdct[i]); + + av_freep(ps); +} + +int ff_celt_init(AVCodecContext *avctx, CeltContext **ps, int output_channels) +{ + CeltContext *s; + int i, ret; + + if (output_channels != 1 && output_channels != 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of output channels: %d\n", + output_channels); + return AVERROR(EINVAL); + } + + s = av_mallocz(sizeof(*s)); + if (!s) + return AVERROR(ENOMEM); + + s->avctx = avctx; + 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); + if (ret < 0) + goto fail; + } + + avpriv_float_dsp_init(&s->dsp, avctx->flags & CODEC_FLAG_BITEXACT); + + ff_celt_flush(s); + + *ps = s; + + return 0; +fail: + ff_celt_free(&s); + return ret; +} diff --git a/libavcodec/opus_imdct.c b/libavcodec/opus_imdct.c new file mode 100644 index 000000000..0a6fca994 --- /dev/null +++ b/libavcodec/opus_imdct.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2013-2014 Mozilla Corporation + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Celt non-power of 2 iMDCT + */ + +#include +#include +#include + +#include "config.h" + +#include "libavutil/attributes.h" +#include "libavutil/common.h" + +#include "avfft.h" +#include "opus.h" +#include "opus_imdct.h" + +// minimal iMDCT size to make SIMD opts easier +#define CELT_MIN_IMDCT_SIZE 120 + +// complex c = a * b +#define CMUL3(cre, cim, are, aim, bre, bim) \ +do { \ + cre = are * bre - aim * bim; \ + cim = are * bim + aim * bre; \ +} while (0) + +#define CMUL(c, a, b) CMUL3((c).re, (c).im, (a).re, (a).im, (b).re, (b).im) + +// complex c = a * b +// d = a * conjugate(b) +#define CMUL2(c, d, a, b) \ +do { \ + float are = (a).re; \ + float aim = (a).im; \ + float bre = (b).re; \ + float bim = (b).im; \ + float rr = are * bre; \ + float ri = are * bim; \ + float ir = aim * bre; \ + float ii = aim * bim; \ + (c).re = rr - ii; \ + (c).im = ri + ir; \ + (d).re = rr + ii; \ + (d).im = -ri + ir; \ +} while (0) + +av_cold void ff_celt_imdct_uninit(CeltIMDCTContext **ps) +{ + CeltIMDCTContext *s = *ps; + int i; + + if (!s) + return; + + for (i = 0; i < FF_ARRAY_ELEMS(s->exptab); i++) + av_freep(&s->exptab[i]); + + av_freep(&s->twiddle_exptab); + + av_freep(&s->tmp); + + av_freep(ps); +} + +static void celt_imdct_half(CeltIMDCTContext *s, float *dst, const float *src, + ptrdiff_t stride, float scale); + +av_cold int ff_celt_imdct_init(CeltIMDCTContext **ps, int N) +{ + CeltIMDCTContext *s; + int len2 = 15 * (1 << N); + int len = 2 * len2; + int i, j; + + if (len2 > CELT_MAX_FRAME_SIZE || len2 < CELT_MIN_IMDCT_SIZE) + return AVERROR(EINVAL); + + s = av_mallocz(sizeof(*s)); + if (!s) + return AVERROR(ENOMEM); + + s->fft_n = N - 1; + s->len4 = len2 / 2; + s->len2 = len2; + + s->tmp = av_malloc(len * 2 * sizeof(*s->tmp)); + if (!s->tmp) + goto fail; + + s->twiddle_exptab = av_malloc(s->len4 * sizeof(*s->twiddle_exptab)); + if (!s->twiddle_exptab) + goto fail; + + for (i = 0; i < s->len4; i++) { + s->twiddle_exptab[i].re = cos(2 * M_PI * (i + 0.125 + s->len4) / len); + s->twiddle_exptab[i].im = sin(2 * M_PI * (i + 0.125 + s->len4) / len); + } + + for (i = 0; i < FF_ARRAY_ELEMS(s->exptab); i++) { + int N = 15 * (1 << i); + s->exptab[i] = av_malloc(sizeof(*s->exptab[i]) * FFMAX(N, 19)); + if (!s->exptab[i]) + goto fail; + + for (j = 0; j < N; j++) { + s->exptab[i][j].re = cos(2 * M_PI * j / N); + s->exptab[i][j].im = sin(2 * M_PI * j / N); + } + } + + // wrap around to simplify fft15 + for (j = 15; j < 19; j++) + s->exptab[0][j] = s->exptab[0][j - 15]; + + s->imdct_half = celt_imdct_half; + + if (ARCH_AARCH64) + ff_celt_imdct_init_aarch64(s); + + *ps = s; + + return 0; +fail: + ff_celt_imdct_uninit(&s); + return AVERROR(ENOMEM); +} + +static void fft5(FFTComplex *out, const FFTComplex *in, ptrdiff_t stride) +{ + // [0] = exp(2 * i * pi / 5), [1] = exp(2 * i * pi * 2 / 5) + static const FFTComplex fact[] = { { 0.30901699437494745, 0.95105651629515353 }, + { -0.80901699437494734, 0.58778525229247325 } }; + + FFTComplex z[4][4]; + + CMUL2(z[0][0], z[0][3], in[1 * stride], fact[0]); + CMUL2(z[0][1], z[0][2], in[1 * stride], fact[1]); + CMUL2(z[1][0], z[1][3], in[2 * stride], fact[0]); + CMUL2(z[1][1], z[1][2], in[2 * stride], fact[1]); + CMUL2(z[2][0], z[2][3], in[3 * stride], fact[0]); + CMUL2(z[2][1], z[2][2], in[3 * stride], fact[1]); + CMUL2(z[3][0], z[3][3], in[4 * stride], fact[0]); + CMUL2(z[3][1], z[3][2], in[4 * stride], fact[1]); + + out[0].re = in[0].re + in[stride].re + in[2 * stride].re + in[3 * stride].re + in[4 * stride].re; + out[0].im = in[0].im + in[stride].im + in[2 * stride].im + in[3 * stride].im + in[4 * stride].im; + + out[1].re = in[0].re + z[0][0].re + z[1][1].re + z[2][2].re + z[3][3].re; + out[1].im = in[0].im + z[0][0].im + z[1][1].im + z[2][2].im + z[3][3].im; + + out[2].re = in[0].re + z[0][1].re + z[1][3].re + z[2][0].re + z[3][2].re; + out[2].im = in[0].im + z[0][1].im + z[1][3].im + z[2][0].im + z[3][2].im; + + out[3].re = in[0].re + z[0][2].re + z[1][0].re + z[2][3].re + z[3][1].re; + out[3].im = in[0].im + z[0][2].im + z[1][0].im + z[2][3].im + z[3][1].im; + + out[4].re = in[0].re + z[0][3].re + z[1][2].re + z[2][1].re + z[3][0].re; + 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) +{ + const FFTComplex *exptab = s->exptab[0]; + FFTComplex tmp[5]; + FFTComplex tmp1[5]; + FFTComplex tmp2[5]; + int k; + + fft5(tmp, in, stride * 3); + fft5(tmp1, in + stride, stride * 3); + fft5(tmp2, in + 2 * stride, stride * 3); + + for (k = 0; k < 5; k++) { + FFTComplex t1, t2; + + CMUL(t1, tmp1[k], exptab[k]); + CMUL(t2, tmp2[k], exptab[2 * k]); + out[k].re = tmp[k].re + t1.re + t2.re; + out[k].im = tmp[k].im + t1.im + t2.im; + + CMUL(t1, tmp1[k], exptab[k + 5]); + CMUL(t2, tmp2[k], exptab[2 * (k + 5)]); + out[k + 5].re = tmp[k].re + t1.re + t2.re; + out[k + 5].im = tmp[k].im + t1.im + t2.im; + + CMUL(t1, tmp1[k], exptab[k + 10]); + CMUL(t2, tmp2[k], exptab[2 * k + 5]); + out[k + 10].re = tmp[k].re + t1.re + t2.re; + out[k + 10].im = tmp[k].im + t1.im + t2.im; + } +} + +/* + * FFT of the length 15 * (2^N) + */ +static void fft_calc(CeltIMDCTContext *s, FFTComplex *out, const FFTComplex *in, + int N, ptrdiff_t stride) +{ + if (N) { + const FFTComplex *exptab = s->exptab[N]; + const int len2 = 15 * (1 << (N - 1)); + int k; + + fft_calc(s, out, in, N - 1, stride * 2); + fft_calc(s, out + len2, in + stride, N - 1, stride * 2); + + for (k = 0; k < len2; k++) { + FFTComplex t; + + CMUL(t, out[len2 + k], exptab[k]); + + out[len2 + k].re = out[k].re - t.re; + out[len2 + k].im = out[k].im - t.im; + + out[k].re += t.re; + out[k].im += t.im; + } + } else + fft15(s, out, in, stride); +} + +static void celt_imdct_half(CeltIMDCTContext *s, float *dst, const float *src, + ptrdiff_t stride, float scale) +{ + FFTComplex *z = (FFTComplex *)dst; + const int len8 = s->len4 / 2; + const float *in1 = src; + const float *in2 = src + (s->len2 - 1) * stride; + int i; + + for (i = 0; i < s->len4; i++) { + FFTComplex tmp = { *in2, *in1 }; + CMUL(s->tmp[i], tmp, s->twiddle_exptab[i]); + in1 += 2 * stride; + in2 -= 2 * stride; + } + + fft_calc(s, z, s->tmp, s->fft_n, 1); + + for (i = 0; i < len8; i++) { + float r0, i0, r1, i1; + + CMUL3(r0, i1, z[len8 - i - 1].im, z[len8 - i - 1].re, s->twiddle_exptab[len8 - i - 1].im, s->twiddle_exptab[len8 - i - 1].re); + CMUL3(r1, i0, z[len8 + i].im, z[len8 + i].re, s->twiddle_exptab[len8 + i].im, s->twiddle_exptab[len8 + i].re); + z[len8 - i - 1].re = scale * r0; + z[len8 - i - 1].im = scale * i0; + z[len8 + i].re = scale * r1; + z[len8 + i].im = scale * i1; + } +} diff --git a/libavcodec/opus_imdct.h b/libavcodec/opus_imdct.h new file mode 100644 index 000000000..0ca4d973d --- /dev/null +++ b/libavcodec/opus_imdct.h @@ -0,0 +1,57 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_OPUS_IMDCT_H +#define AVCODEC_OPUS_IMDCT_H + +#include + +#include "avfft.h" + +typedef struct CeltIMDCTContext { + int fft_n; + int len2; + int len4; + + FFTComplex *tmp; + + FFTComplex *twiddle_exptab; + + FFTComplex *exptab[6]; + + /** + * Calculate the middle half of the iMDCT + */ + void (*imdct_half)(struct CeltIMDCTContext *s, float *dst, const float *src, + ptrdiff_t src_stride, float scale); +} CeltIMDCTContext; + +/** + * Init an iMDCT of the length 2 * 15 * (2^N) + */ +int ff_celt_imdct_init(CeltIMDCTContext **s, int N); + +/** + * Free an iMDCT. + */ +void ff_celt_imdct_uninit(CeltIMDCTContext **s); + + +void ff_celt_imdct_init_aarch64(CeltIMDCTContext *s); + +#endif /* AVCODEC_OPUS_IMDCT_H */ diff --git a/libavcodec/opus_parser.c b/libavcodec/opus_parser.c new file mode 100644 index 000000000..7eb72f9c3 --- /dev/null +++ b/libavcodec/opus_parser.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013-2014 Mozilla Corporation + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Opus parser + * + * Determines the duration for each packet. + */ + +#include "avcodec.h" +#include "opus.h" + +typedef struct OpusParseContext { + OpusContext ctx; + OpusPacket pkt; + int extradata_parsed; +} OpusParseContext; + +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; + int ret; + + if (!buf_size) + return 0; + + 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; + } + 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; + } + + ctx->duration = s->pkt.frame_count * s->pkt.frame_duration; + +fail: + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; +} + +AVCodecParser ff_opus_parser = { + .codec_ids = { AV_CODEC_ID_OPUS }, + .priv_data_size = sizeof(OpusParseContext), + .parser_parse = opus_parse, +}; diff --git a/libavcodec/opus_silk.c b/libavcodec/opus_silk.c new file mode 100644 index 000000000..7a89479fb --- /dev/null +++ b/libavcodec/opus_silk.c @@ -0,0 +1,1597 @@ +/* + * Copyright (c) 2012 Andrew D'Addesio + * Copyright (c) 2013-2014 Mozilla Corporation + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Opus SILK decoder + */ + +#include + +#include "opus.h" + +typedef struct SilkFrame { + int coded; + int log_gain; + int16_t nlsf[16]; + float lpc[16]; + + float output [2 * SILK_HISTORY]; + float lpc_history[2 * SILK_HISTORY]; + int primarylag; + + int prev_voiced; +} SilkFrame; + +struct SilkContext { + AVCodecContext *avctx; + int output_channels; + + int midonly; + int subframes; + int sflength; + int flength; + int nlsf_interp_factor; + + enum OpusBandwidth bandwidth; + int wb; + + SilkFrame frame[2]; + float prev_stereo_weights[2]; + float stereo_weights[2]; + + int prev_coded_channels; +}; + +static const uint16_t silk_model_stereo_s1[] = { + 256, 7, 9, 10, 11, 12, 22, 46, 54, 55, 56, 59, 82, 174, 197, 200, + 201, 202, 210, 234, 244, 245, 246, 247, 249, 256 +}; + +static const uint16_t silk_model_stereo_s2[] = {256, 85, 171, 256}; + +static const uint16_t silk_model_stereo_s3[] = {256, 51, 102, 154, 205, 256}; + +static const uint16_t silk_model_mid_only[] = {256, 192, 256}; + +static const uint16_t silk_model_frame_type_inactive[] = {256, 26, 256}; + +static const uint16_t silk_model_frame_type_active[] = {256, 24, 98, 246, 256}; + +static const uint16_t silk_model_gain_highbits[3][9] = { + {256, 32, 144, 212, 241, 253, 254, 255, 256}, + {256, 2, 19, 64, 124, 186, 233, 252, 256}, + {256, 1, 4, 30, 101, 195, 245, 254, 256} +}; + +static const uint16_t silk_model_gain_lowbits[] = {256, 32, 64, 96, 128, 160, 192, 224, 256}; + +static const uint16_t silk_model_gain_delta[] = { + 256, 6, 11, 22, 53, 185, 206, 214, 218, 221, 223, 225, 227, 228, 229, 230, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256 +}; +static const uint16_t silk_model_lsf_s1[2][2][33] = { + { + { // NB or MB, unvoiced + 256, 44, 78, 108, 127, 148, 160, 171, 174, 177, 179, 195, 197, 199, 200, 205, + 207, 208, 211, 214, 215, 216, 218, 220, 222, 225, 226, 235, 244, 246, 253, 255, 256 + }, { // NB or MB, voiced + 256, 1, 11, 12, 20, 23, 31, 39, 53, 66, 80, 81, 95, 107, 120, 131, + 142, 154, 165, 175, 185, 196, 204, 213, 221, 228, 236, 237, 238, 244, 245, 251, 256 + } + }, { + { // WB, unvoiced + 256, 31, 52, 55, 72, 73, 81, 98, 102, 103, 121, 137, 141, 143, 146, 147, + 157, 158, 161, 177, 188, 204, 206, 208, 211, 213, 224, 225, 229, 238, 246, 253, 256 + }, { // WB, voiced + 256, 1, 5, 21, 26, 44, 55, 60, 74, 89, 90, 93, 105, 118, 132, 146, + 152, 166, 178, 180, 186, 187, 199, 211, 222, 232, 235, 245, 250, 251, 252, 253, 256 + } + } +}; + +static const uint16_t silk_model_lsf_s2[32][10] = { + // NB, MB + { 256, 1, 2, 3, 18, 242, 253, 254, 255, 256 }, + { 256, 1, 2, 4, 38, 221, 253, 254, 255, 256 }, + { 256, 1, 2, 6, 48, 197, 252, 254, 255, 256 }, + { 256, 1, 2, 10, 62, 185, 246, 254, 255, 256 }, + { 256, 1, 4, 20, 73, 174, 248, 254, 255, 256 }, + { 256, 1, 4, 21, 76, 166, 239, 254, 255, 256 }, + { 256, 1, 8, 32, 85, 159, 226, 252, 255, 256 }, + { 256, 1, 2, 20, 83, 161, 219, 249, 255, 256 }, + + // WB + { 256, 1, 2, 3, 12, 244, 253, 254, 255, 256 }, + { 256, 1, 2, 4, 32, 218, 253, 254, 255, 256 }, + { 256, 1, 2, 5, 47, 199, 252, 254, 255, 256 }, + { 256, 1, 2, 12, 61, 187, 252, 254, 255, 256 }, + { 256, 1, 5, 24, 72, 172, 249, 254, 255, 256 }, + { 256, 1, 2, 16, 70, 170, 242, 254, 255, 256 }, + { 256, 1, 2, 17, 78, 165, 226, 251, 255, 256 }, + { 256, 1, 8, 29, 79, 156, 237, 254, 255, 256 } +}; + +static const uint16_t silk_model_lsf_s2_ext[] = { 256, 156, 216, 240, 249, 253, 255, 256 }; + +static const uint16_t silk_model_lsf_interpolation_offset[] = { 256, 13, 35, 64, 75, 256 }; + +static const uint16_t silk_model_pitch_highbits[] = { + 256, 3, 6, 12, 23, 44, 74, 106, 125, 136, 146, 158, 171, 184, 196, 207, + 216, 224, 231, 237, 241, 243, 245, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256 +}; + +static const uint16_t silk_model_pitch_lowbits_nb[]= { 256, 64, 128, 192, 256 }; + +static const uint16_t silk_model_pitch_lowbits_mb[]= { 256, 43, 85, 128, 171, 213, 256 }; + +static const uint16_t silk_model_pitch_lowbits_wb[]= { 256, 32, 64, 96, 128, 160, 192, 224, 256 }; + +static const uint16_t silk_model_pitch_delta[] = { + 256, 46, 48, 50, 53, 57, 63, 73, 88, 114, 152, 182, 204, 219, 229, 236, + 242, 246, 250, 252, 254, 256 +}; + +static const uint16_t silk_model_pitch_contour_nb10ms[] = { 256, 143, 193, 256 }; + +static const uint16_t silk_model_pitch_contour_nb20ms[] = { + 256, 68, 80, 101, 118, 137, 159, 189, 213, 230, 246, 256 +}; + +static const uint16_t silk_model_pitch_contour_mbwb10ms[] = { + 256, 91, 137, 176, 195, 209, 221, 229, 236, 242, 247, 252, 256 +}; + +static const uint16_t silk_model_pitch_contour_mbwb20ms[] = { + 256, 33, 55, 73, 89, 104, 118, 132, 145, 158, 168, 177, 186, 194, 200, 206, + 212, 217, 221, 225, 229, 232, 235, 238, 240, 242, 244, 246, 248, 250, 252, 253, + 254, 255, 256 +}; + +static const uint16_t silk_model_ltp_filter[] = { 256, 77, 157, 256 }; + +static const uint16_t silk_model_ltp_filter0_sel[] = { + 256, 185, 200, 213, 226, 235, 244, 250, 256 +}; + +static const uint16_t silk_model_ltp_filter1_sel[] = { + 256, 57, 91, 112, 132, 147, 160, 172, 185, 195, 205, 214, 224, 233, 241, 248, 256 +}; + +static const uint16_t silk_model_ltp_filter2_sel[] = { + 256, 15, 31, 45, 57, 69, 81, 92, 103, 114, 124, 133, 142, 151, 160, 168, + 176, 184, 192, 199, 206, 212, 218, 223, 227, 232, 236, 240, 244, 247, 251, 254, 256 +}; + +static const uint16_t silk_model_ltp_scale_index[] = { 256, 128, 192, 256 }; + +static const uint16_t silk_model_lcg_seed[] = { 256, 64, 128, 192, 256 }; + +static const uint16_t silk_model_exc_rate[2][10] = { + { 256, 15, 66, 78, 124, 169, 182, 215, 242, 256 }, // unvoiced + { 256, 33, 63, 99, 116, 150, 199, 217, 238, 256 } // voiced +}; + +static const uint16_t silk_model_pulse_count[11][19] = { + { 256, 131, 205, 230, 238, 241, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256 }, + { 256, 58, 151, 211, 234, 241, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256 }, + { 256, 43, 94, 140, 173, 197, 213, 224, 232, + 238, 241, 244, 247, 249, 250, 251, 253, 254, 256 }, + { 256, 17, 69, 140, 197, 228, 240, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256 }, + { 256, 6, 27, 68, 121, 170, 205, 226, 237, + 243, 246, 248, 250, 251, 252, 253, 254, 255, 256 }, + { 256, 7, 21, 43, 71, 100, 128, 153, 173, + 190, 203, 214, 223, 230, 235, 239, 243, 246, 256 }, + { 256, 2, 7, 21, 50, 92, 138, 179, 210, + 229, 240, 246, 249, 251, 252, 253, 254, 255, 256 }, + { 256, 1, 3, 7, 17, 36, 65, 100, 137, + 171, 199, 219, 233, 241, 246, 250, 252, 254, 256 }, + { 256, 1, 3, 5, 10, 19, 33, 53, 77, + 104, 132, 158, 181, 201, 216, 227, 235, 241, 256 }, + { 256, 1, 2, 3, 9, 36, 94, 150, 189, + 214, 228, 238, 244, 247, 250, 252, 253, 254, 256 }, + { 256, 2, 3, 9, 36, 94, 150, 189, 214, + 228, 238, 244, 247, 250, 252, 253, 254, 256, 256 } +}; + +static const uint16_t silk_model_pulse_location[4][168] = { + { + 256, 126, 256, + 256, 56, 198, 256, + 256, 25, 126, 230, 256, + 256, 12, 72, 180, 244, 256, + 256, 7, 42, 126, 213, 250, 256, + 256, 4, 24, 83, 169, 232, 253, 256, + 256, 3, 15, 53, 125, 200, 242, 254, 256, + 256, 2, 10, 35, 89, 162, 221, 248, 255, 256, + 256, 2, 7, 24, 63, 126, 191, 233, 251, 255, 256, + 256, 1, 5, 17, 45, 94, 157, 211, 241, 252, 255, 256, + 256, 1, 5, 13, 33, 70, 125, 182, 223, 245, 253, 255, 256, + 256, 1, 4, 11, 26, 54, 98, 151, 199, 232, 248, 254, 255, 256, + 256, 1, 3, 9, 21, 42, 77, 124, 172, 212, 237, 249, 254, 255, 256, + 256, 1, 2, 6, 16, 33, 60, 97, 144, 187, 220, 241, 250, 254, 255, 256, + 256, 1, 2, 3, 11, 25, 47, 80, 120, 163, 201, 229, 245, 253, 254, 255, 256, + 256, 1, 2, 3, 4, 17, 35, 62, 98, 139, 180, 214, 238, 252, 253, 254, 255, 256 + },{ + 256, 127, 256, + 256, 53, 202, 256, + 256, 22, 127, 233, 256, + 256, 11, 72, 183, 246, 256, + 256, 6, 41, 127, 215, 251, 256, + 256, 4, 24, 83, 170, 232, 253, 256, + 256, 3, 16, 56, 127, 200, 241, 254, 256, + 256, 3, 12, 39, 92, 162, 218, 246, 255, 256, + 256, 3, 11, 30, 67, 124, 185, 229, 249, 255, 256, + 256, 3, 10, 25, 53, 97, 151, 200, 233, 250, 255, 256, + 256, 1, 8, 21, 43, 77, 123, 171, 209, 237, 251, 255, 256, + 256, 1, 2, 13, 35, 62, 97, 139, 186, 219, 244, 254, 255, 256, + 256, 1, 2, 8, 22, 48, 85, 128, 171, 208, 234, 248, 254, 255, 256, + 256, 1, 2, 6, 16, 36, 67, 107, 149, 189, 220, 240, 250, 254, 255, 256, + 256, 1, 2, 5, 13, 29, 55, 90, 128, 166, 201, 227, 243, 251, 254, 255, 256, + 256, 1, 2, 4, 10, 22, 43, 73, 109, 147, 183, 213, 234, 246, 252, 254, 255, 256 + },{ + 256, 127, 256, + 256, 49, 206, 256, + 256, 20, 127, 236, 256, + 256, 11, 71, 184, 246, 256, + 256, 7, 43, 127, 214, 250, 256, + 256, 6, 30, 87, 169, 229, 252, 256, + 256, 5, 23, 62, 126, 194, 236, 252, 256, + 256, 6, 20, 49, 96, 157, 209, 239, 253, 256, + 256, 1, 16, 39, 74, 125, 175, 215, 245, 255, 256, + 256, 1, 2, 23, 55, 97, 149, 195, 236, 254, 255, 256, + 256, 1, 7, 23, 50, 86, 128, 170, 206, 233, 249, 255, 256, + 256, 1, 6, 18, 39, 70, 108, 148, 186, 217, 238, 250, 255, 256, + 256, 1, 4, 13, 30, 56, 90, 128, 166, 200, 226, 243, 252, 255, 256, + 256, 1, 4, 11, 25, 47, 76, 110, 146, 180, 209, 231, 245, 252, 255, 256, + 256, 1, 3, 8, 19, 37, 62, 93, 128, 163, 194, 219, 237, 248, 253, 255, 256, + 256, 1, 2, 6, 15, 30, 51, 79, 111, 145, 177, 205, 226, 241, 250, 254, 255, 256 + },{ + 256, 128, 256, + 256, 42, 214, 256, + 256, 21, 128, 235, 256, + 256, 12, 72, 184, 245, 256, + 256, 8, 42, 128, 214, 249, 256, + 256, 8, 31, 86, 176, 231, 251, 256, + 256, 5, 20, 58, 130, 202, 238, 253, 256, + 256, 6, 18, 45, 97, 174, 221, 241, 251, 256, + 256, 6, 25, 53, 88, 128, 168, 203, 231, 250, 256, + 256, 4, 18, 40, 71, 108, 148, 185, 216, 238, 252, 256, + 256, 3, 13, 31, 57, 90, 128, 166, 199, 225, 243, 253, 256, + 256, 2, 10, 23, 44, 73, 109, 147, 183, 212, 233, 246, 254, 256, + 256, 1, 6, 16, 33, 58, 90, 128, 166, 198, 223, 240, 250, 255, 256, + 256, 1, 5, 12, 25, 46, 75, 110, 146, 181, 210, 231, 244, 251, 255, 256, + 256, 1, 3, 8, 18, 35, 60, 92, 128, 164, 196, 221, 238, 248, 253, 255, 256, + 256, 1, 3, 7, 14, 27, 48, 76, 110, 146, 180, 208, 229, 242, 249, 253, 255, 256 + } +}; + +static const uint16_t silk_model_excitation_lsb[] = {256, 136, 256}; + +static const uint16_t silk_model_excitation_sign[3][2][7][3] = { + { // Inactive + { // Low offset + {256, 2, 256}, + {256, 207, 256}, + {256, 189, 256}, + {256, 179, 256}, + {256, 174, 256}, + {256, 163, 256}, + {256, 157, 256} + }, { // High offset + {256, 58, 256}, + {256, 245, 256}, + {256, 238, 256}, + {256, 232, 256}, + {256, 225, 256}, + {256, 220, 256}, + {256, 211, 256} + } + }, { // Unvoiced + { // Low offset + {256, 1, 256}, + {256, 210, 256}, + {256, 190, 256}, + {256, 178, 256}, + {256, 169, 256}, + {256, 162, 256}, + {256, 152, 256} + }, { // High offset + {256, 48, 256}, + {256, 242, 256}, + {256, 235, 256}, + {256, 224, 256}, + {256, 214, 256}, + {256, 205, 256}, + {256, 190, 256} + } + }, { // Voiced + { // Low offset + {256, 1, 256}, + {256, 162, 256}, + {256, 152, 256}, + {256, 147, 256}, + {256, 144, 256}, + {256, 141, 256}, + {256, 138, 256} + }, { // High offset + {256, 8, 256}, + {256, 203, 256}, + {256, 187, 256}, + {256, 176, 256}, + {256, 168, 256}, + {256, 161, 256}, + {256, 154, 256} + } + } +}; + +static const int16_t silk_stereo_weights[] = { + -13732, -10050, -8266, -7526, -6500, -5000, -2950, -820, + 820, 2950, 5000, 6500, 7526, 8266, 10050, 13732 +}; + +static const uint8_t silk_lsf_s2_model_sel_nbmb[32][10] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 3, 1, 2, 2, 1, 2, 1, 1, 1 }, + { 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 2, 2, 2, 2, 1, 2, 1, 1, 1 }, + { 2, 3, 3, 3, 3, 2, 2, 2, 2, 2 }, + { 0, 5, 3, 3, 2, 2, 2, 2, 1, 1 }, + { 0, 2, 2, 2, 2, 2, 2, 2, 2, 1 }, + { 2, 3, 6, 4, 4, 4, 5, 4, 5, 5 }, + { 2, 4, 5, 5, 4, 5, 4, 6, 4, 4 }, + { 2, 4, 4, 7, 4, 5, 4, 5, 5, 4 }, + { 4, 3, 3, 3, 2, 3, 2, 2, 2, 2 }, + { 1, 5, 5, 6, 4, 5, 4, 5, 5, 5 }, + { 2, 7, 4, 6, 5, 5, 5, 5, 5, 5 }, + { 2, 7, 5, 5, 5, 5, 5, 6, 5, 4 }, + { 3, 3, 5, 4, 4, 5, 4, 5, 4, 4 }, + { 2, 3, 3, 5, 5, 4, 4, 4, 4, 4 }, + { 2, 4, 4, 6, 4, 5, 4, 5, 5, 5 }, + { 2, 5, 4, 6, 5, 5, 5, 4, 5, 4 }, + { 2, 7, 4, 5, 4, 5, 4, 5, 5, 5 }, + { 2, 5, 4, 6, 7, 6, 5, 6, 5, 4 }, + { 3, 6, 7, 4, 6, 5, 5, 6, 4, 5 }, + { 2, 7, 6, 4, 4, 4, 5, 4, 5, 5 }, + { 4, 5, 5, 4, 6, 6, 5, 6, 5, 4 }, + { 2, 5, 5, 6, 5, 6, 4, 6, 4, 4 }, + { 4, 5, 5, 5, 3, 7, 4, 5, 5, 4 }, + { 2, 3, 4, 5, 5, 6, 4, 5, 5, 4 }, + { 2, 3, 2, 3, 3, 4, 2, 3, 3, 3 }, + { 1, 1, 2, 2, 2, 2, 2, 3, 2, 2 }, + { 4, 5, 5, 6, 6, 6, 5, 6, 4, 5 }, + { 3, 5, 5, 4, 4, 4, 4, 3, 3, 2 }, + { 2, 5, 3, 7, 5, 5, 4, 4, 5, 4 }, + { 4, 4, 5, 4, 5, 6, 5, 6, 5, 4 } +}; + +static const uint8_t silk_lsf_s2_model_sel_wb[32][16] = { + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }, + { 10, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 9, 9, 9, 8, 11 }, + { 10, 13, 13, 11, 15, 12, 12, 13, 10, 13, 12, 13, 13, 12, 11, 11 }, + { 8, 10, 9, 10, 10, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 9 }, + { 8, 14, 13, 12, 14, 12, 15, 13, 12, 12, 12, 13, 13, 12, 12, 11 }, + { 8, 11, 13, 13, 12, 11, 11, 13, 11, 11, 11, 11, 11, 11, 10, 12 }, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }, + { 8, 10, 14, 11, 15, 10, 13, 11, 12, 13, 13, 12, 11, 11, 10, 11 }, + { 8, 14, 10, 14, 14, 12, 13, 12, 14, 13, 12, 12, 13, 11, 11, 11 }, + { 10, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }, + { 8, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9 }, + { 10, 10, 11, 12, 13, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 11 }, + { 10, 10, 11, 11, 12, 11, 11, 11, 11, 11, 11, 11, 11, 10, 9, 11 }, + { 11, 12, 12, 12, 14, 12, 12, 13, 11, 13, 12, 12, 13, 12, 11, 12 }, + { 8, 14, 12, 13, 12, 15, 13, 10, 14, 13, 15, 12, 12, 11, 13, 11 }, + { 8, 9, 8, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 9, 8 }, + { 9, 14, 13, 15, 13, 12, 13, 11, 12, 13, 12, 12, 12, 11, 11, 12 }, + { 9, 11, 11, 12, 12, 11, 11, 13, 10, 11, 11, 13, 13, 13, 11, 12 }, + { 10, 11, 11, 10, 10, 10, 11, 10, 9, 10, 9, 10, 9, 9, 9, 12 }, + { 8, 10, 11, 13, 11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 8 }, + { 11, 12, 11, 13, 11, 11, 10, 10, 9, 9, 9, 9, 9, 10, 10, 12 }, + { 10, 14, 11, 15, 15, 12, 13, 12, 13, 11, 13, 11, 11, 10, 11, 11 }, + { 10, 11, 13, 14, 14, 11, 13, 11, 12, 12, 11, 11, 11, 11, 10, 12 }, + { 9, 11, 11, 12, 12, 12, 12, 11, 13, 13, 13, 11, 9, 9, 9, 9 }, + { 10, 13, 11, 14, 14, 12, 15, 12, 12, 13, 11, 12, 12, 11, 11, 11 }, + { 8, 14, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }, + { 8, 14, 14, 11, 13, 10, 13, 13, 11, 12, 12, 15, 15, 12, 12, 12 }, + { 11, 11, 15, 11, 13, 12, 11, 11, 11, 10, 10, 11, 11, 11, 10, 11 }, + { 8, 8, 9, 8, 8, 8, 10, 9, 10, 9, 9, 10, 10, 10, 9, 9 }, + { 8, 11, 10, 13, 11, 11, 10, 11, 10, 9, 8, 8, 9, 8, 8, 9 }, + { 11, 13, 13, 12, 15, 13, 11, 11, 10, 11, 10, 10, 9, 8, 9, 8 }, + { 10, 11, 13, 11, 12, 11, 11, 11, 10, 9, 10, 14, 12, 8, 8, 8 } +}; + +static const uint8_t silk_lsf_pred_weights_nbmb[2][9] = { + {179, 138, 140, 148, 151, 149, 153, 151, 163}, + {116, 67, 82, 59, 92, 72, 100, 89, 92} +}; + +static const uint8_t silk_lsf_pred_weights_wb[2][15] = { + {175, 148, 160, 176, 178, 173, 174, 164, 177, 174, 196, 182, 198, 192, 182}, + { 68, 62, 66, 60, 72, 117, 85, 90, 118, 136, 151, 142, 160, 142, 155} +}; + +static const uint8_t silk_lsf_weight_sel_nbmb[32][9] = { + { 0, 1, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 0, 0, 0, 0, 1, 0 }, + { 0, 1, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 1, 1, 0, 0, 0, 1, 0 }, + { 0, 1, 1, 0, 0, 1, 1, 0, 0 }, + { 0, 0, 1, 1, 0, 1, 0, 1, 1 }, + { 0, 0, 1, 1, 0, 0, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 1, 1, 1, 1, 1, 0 }, + { 0, 1, 0, 1, 1, 1, 1, 1, 0 }, + { 0, 1, 1, 1, 1, 1, 1, 1, 0 }, + { 1, 0, 1, 1, 0, 1, 1, 1, 1 }, + { 0, 1, 1, 1, 1, 1, 0, 1, 0 }, + { 0, 0, 1, 1, 0, 1, 0, 1, 0 }, + { 0, 0, 1, 1, 1, 0, 1, 1, 1 }, + { 0, 1, 1, 0, 0, 1, 1, 1, 0 }, + { 0, 0, 0, 1, 1, 1, 0, 1, 0 }, + { 0, 1, 1, 0, 0, 1, 0, 1, 0 }, + { 0, 1, 1, 0, 0, 0, 1, 1, 0 }, + { 0, 0, 0, 0, 0, 1, 1, 1, 1 }, + { 0, 0, 1, 1, 0, 0, 0, 1, 1 }, + { 0, 0, 0, 1, 0, 1, 1, 1, 1 }, + { 0, 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, 1, 0, 1, 1, 0, 1, 0 }, + { 1, 0, 0, 1, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 1, 1, 0, 1, 0, 1 }, + { 1, 0, 1, 1, 0, 1, 1, 1, 1 } +}; + +static const uint8_t silk_lsf_weight_sel_wb[32][15] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, + { 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0 }, + { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, + { 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1 }, + { 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0 }, + { 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0 }, + { 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 }, + { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, + { 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0 }, + { 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0 }, + { 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0 }, + { 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, + { 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0 } +}; + +static const uint8_t silk_lsf_codebook_nbmb[32][10] = { + { 12, 35, 60, 83, 108, 132, 157, 180, 206, 228 }, + { 15, 32, 55, 77, 101, 125, 151, 175, 201, 225 }, + { 19, 42, 66, 89, 114, 137, 162, 184, 209, 230 }, + { 12, 25, 50, 72, 97, 120, 147, 172, 200, 223 }, + { 26, 44, 69, 90, 114, 135, 159, 180, 205, 225 }, + { 13, 22, 53, 80, 106, 130, 156, 180, 205, 228 }, + { 15, 25, 44, 64, 90, 115, 142, 168, 196, 222 }, + { 19, 24, 62, 82, 100, 120, 145, 168, 190, 214 }, + { 22, 31, 50, 79, 103, 120, 151, 170, 203, 227 }, + { 21, 29, 45, 65, 106, 124, 150, 171, 196, 224 }, + { 30, 49, 75, 97, 121, 142, 165, 186, 209, 229 }, + { 19, 25, 52, 70, 93, 116, 143, 166, 192, 219 }, + { 26, 34, 62, 75, 97, 118, 145, 167, 194, 217 }, + { 25, 33, 56, 70, 91, 113, 143, 165, 196, 223 }, + { 21, 34, 51, 72, 97, 117, 145, 171, 196, 222 }, + { 20, 29, 50, 67, 90, 117, 144, 168, 197, 221 }, + { 22, 31, 48, 66, 95, 117, 146, 168, 196, 222 }, + { 24, 33, 51, 77, 116, 134, 158, 180, 200, 224 }, + { 21, 28, 70, 87, 106, 124, 149, 170, 194, 217 }, + { 26, 33, 53, 64, 83, 117, 152, 173, 204, 225 }, + { 27, 34, 65, 95, 108, 129, 155, 174, 210, 225 }, + { 20, 26, 72, 99, 113, 131, 154, 176, 200, 219 }, + { 34, 43, 61, 78, 93, 114, 155, 177, 205, 229 }, + { 23, 29, 54, 97, 124, 138, 163, 179, 209, 229 }, + { 30, 38, 56, 89, 118, 129, 158, 178, 200, 231 }, + { 21, 29, 49, 63, 85, 111, 142, 163, 193, 222 }, + { 27, 48, 77, 103, 133, 158, 179, 196, 215, 232 }, + { 29, 47, 74, 99, 124, 151, 176, 198, 220, 237 }, + { 33, 42, 61, 76, 93, 121, 155, 174, 207, 225 }, + { 29, 53, 87, 112, 136, 154, 170, 188, 208, 227 }, + { 24, 30, 52, 84, 131, 150, 166, 186, 203, 229 }, + { 37, 48, 64, 84, 104, 118, 156, 177, 201, 230 } +}; + +static const uint8_t silk_lsf_codebook_wb[32][16] = { + { 7, 23, 38, 54, 69, 85, 100, 116, 131, 147, 162, 178, 193, 208, 223, 239 }, + { 13, 25, 41, 55, 69, 83, 98, 112, 127, 142, 157, 171, 187, 203, 220, 236 }, + { 15, 21, 34, 51, 61, 78, 92, 106, 126, 136, 152, 167, 185, 205, 225, 240 }, + { 10, 21, 36, 50, 63, 79, 95, 110, 126, 141, 157, 173, 189, 205, 221, 237 }, + { 17, 20, 37, 51, 59, 78, 89, 107, 123, 134, 150, 164, 184, 205, 224, 240 }, + { 10, 15, 32, 51, 67, 81, 96, 112, 129, 142, 158, 173, 189, 204, 220, 236 }, + { 8, 21, 37, 51, 65, 79, 98, 113, 126, 138, 155, 168, 179, 192, 209, 218 }, + { 12, 15, 34, 55, 63, 78, 87, 108, 118, 131, 148, 167, 185, 203, 219, 236 }, + { 16, 19, 32, 36, 56, 79, 91, 108, 118, 136, 154, 171, 186, 204, 220, 237 }, + { 11, 28, 43, 58, 74, 89, 105, 120, 135, 150, 165, 180, 196, 211, 226, 241 }, + { 6, 16, 33, 46, 60, 75, 92, 107, 123, 137, 156, 169, 185, 199, 214, 225 }, + { 11, 19, 30, 44, 57, 74, 89, 105, 121, 135, 152, 169, 186, 202, 218, 234 }, + { 12, 19, 29, 46, 57, 71, 88, 100, 120, 132, 148, 165, 182, 199, 216, 233 }, + { 17, 23, 35, 46, 56, 77, 92, 106, 123, 134, 152, 167, 185, 204, 222, 237 }, + { 14, 17, 45, 53, 63, 75, 89, 107, 115, 132, 151, 171, 188, 206, 221, 240 }, + { 9, 16, 29, 40, 56, 71, 88, 103, 119, 137, 154, 171, 189, 205, 222, 237 }, + { 16, 19, 36, 48, 57, 76, 87, 105, 118, 132, 150, 167, 185, 202, 218, 236 }, + { 12, 17, 29, 54, 71, 81, 94, 104, 126, 136, 149, 164, 182, 201, 221, 237 }, + { 15, 28, 47, 62, 79, 97, 115, 129, 142, 155, 168, 180, 194, 208, 223, 238 }, + { 8, 14, 30, 45, 62, 78, 94, 111, 127, 143, 159, 175, 192, 207, 223, 239 }, + { 17, 30, 49, 62, 79, 92, 107, 119, 132, 145, 160, 174, 190, 204, 220, 235 }, + { 14, 19, 36, 45, 61, 76, 91, 108, 121, 138, 154, 172, 189, 205, 222, 238 }, + { 12, 18, 31, 45, 60, 76, 91, 107, 123, 138, 154, 171, 187, 204, 221, 236 }, + { 13, 17, 31, 43, 53, 70, 83, 103, 114, 131, 149, 167, 185, 203, 220, 237 }, + { 17, 22, 35, 42, 58, 78, 93, 110, 125, 139, 155, 170, 188, 206, 224, 240 }, + { 8, 15, 34, 50, 67, 83, 99, 115, 131, 146, 162, 178, 193, 209, 224, 239 }, + { 13, 16, 41, 66, 73, 86, 95, 111, 128, 137, 150, 163, 183, 206, 225, 241 }, + { 17, 25, 37, 52, 63, 75, 92, 102, 119, 132, 144, 160, 175, 191, 212, 231 }, + { 19, 31, 49, 65, 83, 100, 117, 133, 147, 161, 174, 187, 200, 213, 227, 242 }, + { 18, 31, 52, 68, 88, 103, 117, 126, 138, 149, 163, 177, 192, 207, 223, 239 }, + { 16, 29, 47, 61, 76, 90, 106, 119, 133, 147, 161, 176, 193, 209, 224, 240 }, + { 15, 21, 35, 50, 61, 73, 86, 97, 110, 119, 129, 141, 175, 198, 218, 237 } +}; + +static const uint16_t silk_lsf_min_spacing_nbmb[] = { + 250, 3, 6, 3, 3, 3, 4, 3, 3, 3, 461 +}; + +static const uint16_t silk_lsf_min_spacing_wb[] = { + 100, 3, 40, 3, 3, 3, 5, 14, 14, 10, 11, 3, 8, 9, 7, 3, 347 +}; + +static const uint8_t silk_lsf_ordering_nbmb[] = { + 0, 9, 6, 3, 4, 5, 8, 1, 2, 7 +}; + +static const uint8_t silk_lsf_ordering_wb[] = { + 0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1 +}; + +static const int16_t silk_cosine[] = { /* (0.12) */ + 4096, 4095, 4091, 4085, + 4076, 4065, 4052, 4036, + 4017, 3997, 3973, 3948, + 3920, 3889, 3857, 3822, + 3784, 3745, 3703, 3659, + 3613, 3564, 3513, 3461, + 3406, 3349, 3290, 3229, + 3166, 3102, 3035, 2967, + 2896, 2824, 2751, 2676, + 2599, 2520, 2440, 2359, + 2276, 2191, 2106, 2019, + 1931, 1842, 1751, 1660, + 1568, 1474, 1380, 1285, + 1189, 1093, 995, 897, + 799, 700, 601, 501, + 401, 301, 201, 101, + 0, -101, -201, -301, + -401, -501, -601, -700, + -799, -897, -995, -1093, + -1189, -1285, -1380, -1474, + -1568, -1660, -1751, -1842, + -1931, -2019, -2106, -2191, + -2276, -2359, -2440, -2520, + -2599, -2676, -2751, -2824, + -2896, -2967, -3035, -3102, + -3166, -3229, -3290, -3349, + -3406, -3461, -3513, -3564, + -3613, -3659, -3703, -3745, + -3784, -3822, -3857, -3889, + -3920, -3948, -3973, -3997, + -4017, -4036, -4052, -4065, + -4076, -4085, -4091, -4095, + -4096 +}; + +static const uint16_t silk_pitch_scale[] = { 4, 6, 8}; + +static const uint16_t silk_pitch_min_lag[] = { 16, 24, 32}; + +static const uint16_t silk_pitch_max_lag[] = {144, 216, 288}; + +static const int8_t silk_pitch_offset_nb10ms[3][2] = { + { 0, 0}, + { 1, 0}, + { 0, 1} +}; + +static const int8_t silk_pitch_offset_nb20ms[11][4] = { + { 0, 0, 0, 0}, + { 2, 1, 0, -1}, + {-1, 0, 1, 2}, + {-1, 0, 0, 1}, + {-1, 0, 0, 0}, + { 0, 0, 0, 1}, + { 0, 0, 1, 1}, + { 1, 1, 0, 0}, + { 1, 0, 0, 0}, + { 0, 0, 0, -1}, + { 1, 0, 0, -1} +}; + +static const int8_t silk_pitch_offset_mbwb10ms[12][2] = { + { 0, 0}, + { 0, 1}, + { 1, 0}, + {-1, 1}, + { 1, -1}, + {-1, 2}, + { 2, -1}, + {-2, 2}, + { 2, -2}, + {-2, 3}, + { 3, -2}, + {-3, 3} +}; + +static const int8_t silk_pitch_offset_mbwb20ms[34][4] = { + { 0, 0, 0, 0}, + { 0, 0, 1, 1}, + { 1, 1, 0, 0}, + {-1, 0, 0, 0}, + { 0, 0, 0, 1}, + { 1, 0, 0, 0}, + {-1, 0, 0, 1}, + { 0, 0, 0, -1}, + {-1, 0, 1, 2}, + { 1, 0, 0, -1}, + {-2, -1, 1, 2}, + { 2, 1, 0, -1}, + {-2, 0, 0, 2}, + {-2, 0, 1, 3}, + { 2, 1, -1, -2}, + {-3, -1, 1, 3}, + { 2, 0, 0, -2}, + { 3, 1, 0, -2}, + {-3, -1, 2, 4}, + {-4, -1, 1, 4}, + { 3, 1, -1, -3}, + {-4, -1, 2, 5}, + { 4, 2, -1, -3}, + { 4, 1, -1, -4}, + {-5, -1, 2, 6}, + { 5, 2, -1, -4}, + {-6, -2, 2, 6}, + {-5, -2, 2, 5}, + { 6, 2, -1, -5}, + {-7, -2, 3, 8}, + { 6, 2, -2, -6}, + { 5, 2, -2, -5}, + { 8, 3, -2, -7}, + {-9, -3, 3, 9} +}; + +static const int8_t silk_ltp_filter0_taps[8][5] = { + { 4, 6, 24, 7, 5}, + { 0, 0, 2, 0, 0}, + { 12, 28, 41, 13, -4}, + { -9, 15, 42, 25, 14}, + { 1, -2, 62, 41, -9}, + {-10, 37, 65, -4, 3}, + { -6, 4, 66, 7, -8}, + { 16, 14, 38, -3, 33} +}; + +static const int8_t silk_ltp_filter1_taps[16][5] = { + { 13, 22, 39, 23, 12}, + { -1, 36, 64, 27, -6}, + { -7, 10, 55, 43, 17}, + { 1, 1, 8, 1, 1}, + { 6, -11, 74, 53, -9}, + {-12, 55, 76, -12, 8}, + { -3, 3, 93, 27, -4}, + { 26, 39, 59, 3, -8}, + { 2, 0, 77, 11, 9}, + { -8, 22, 44, -6, 7}, + { 40, 9, 26, 3, 9}, + { -7, 20, 101, -7, 4}, + { 3, -8, 42, 26, 0}, + {-15, 33, 68, 2, 23}, + { -2, 55, 46, -2, 15}, + { 3, -1, 21, 16, 41} +}; + +static const int8_t silk_ltp_filter2_taps[32][5] = { + { -6, 27, 61, 39, 5}, + {-11, 42, 88, 4, 1}, + { -2, 60, 65, 6, -4}, + { -1, -5, 73, 56, 1}, + { -9, 19, 94, 29, -9}, + { 0, 12, 99, 6, 4}, + { 8, -19, 102, 46, -13}, + { 3, 2, 13, 3, 2}, + { 9, -21, 84, 72, -18}, + {-11, 46, 104, -22, 8}, + { 18, 38, 48, 23, 0}, + {-16, 70, 83, -21, 11}, + { 5, -11, 117, 22, -8}, + { -6, 23, 117, -12, 3}, + { 3, -8, 95, 28, 4}, + {-10, 15, 77, 60, -15}, + { -1, 4, 124, 2, -4}, + { 3, 38, 84, 24, -25}, + { 2, 13, 42, 13, 31}, + { 21, -4, 56, 46, -1}, + { -1, 35, 79, -13, 19}, + { -7, 65, 88, -9, -14}, + { 20, 4, 81, 49, -29}, + { 20, 0, 75, 3, -17}, + { 5, -9, 44, 92, -8}, + { 1, -3, 22, 69, 31}, + { -6, 95, 41, -12, 5}, + { 39, 67, 16, -4, 1}, + { 0, -6, 120, 55, -36}, + {-13, 44, 122, 4, -24}, + { 81, 5, 11, 3, 7}, + { 2, 0, 9, 10, 88} +}; + +static const uint16_t silk_ltp_scale_factor[] = {15565, 12288, 8192}; + +static const uint8_t silk_shell_blocks[3][2] = { + { 5, 10}, // NB + { 8, 15}, // MB + {10, 20} // WB +}; + +static const uint8_t silk_quant_offset[2][2] = { /* (0.23) */ + {25, 60}, // Inactive or Unvoiced + { 8, 25} // Voiced +}; + +static const int silk_stereo_interp_len[3] = { + 64, 96, 128 +}; + +static inline void silk_stabilize_lsf(int16_t nlsf[16], int order, const uint16_t min_delta[17]) +{ + int pass, i; + for (pass = 0; pass < 20; pass++) { + int k, min_diff = 0; + for (i = 0; i < order+1; i++) { + int low = i != 0 ? nlsf[i-1] : 0; + int high = i != order ? nlsf[i] : 32768; + int diff = (high - low) - (min_delta[i]); + + if (diff < min_diff) { + min_diff = diff; + k = i; + + if (pass == 20) + break; + } + } + if (min_diff == 0) /* no issues; stabilized */ + return; + + /* wiggle one or two LSFs */ + if (k == 0) { + /* repel away from lower bound */ + nlsf[0] = min_delta[0]; + } else if (k == order) { + /* repel away from higher bound */ + nlsf[order-1] = 32768 - min_delta[order]; + } else { + /* repel away from current position */ + int min_center = 0, max_center = 32768, center_val; + + /* lower extent */ + for (i = 0; i < k; i++) + min_center += min_delta[i]; + min_center += min_delta[k] >> 1; + + /* upper extent */ + for (i = order; i > k; i--) + max_center -= min_delta[k]; + max_center -= min_delta[k] >> 1; + + /* move apart */ + center_val = nlsf[k - 1] + nlsf[k]; + center_val = (center_val >> 1) + (center_val & 1); // rounded divide by 2 + center_val = FFMIN(max_center, FFMAX(min_center, center_val)); + + nlsf[k - 1] = center_val - (min_delta[k] >> 1); + nlsf[k] = nlsf[k - 1] + min_delta[k]; + } + } + + /* resort to the fall-back method, the standard method for LSF stabilization */ + + /* sort; as the LSFs should be nearly sorted, use insertion sort */ + for (i = 1; i < order; i++) { + int j, value = nlsf[i]; + for (j = i - 1; j >= 0 && nlsf[j] > value; j--) + nlsf[j + 1] = nlsf[j]; + nlsf[j + 1] = value; + } + + /* push forwards to increase distance */ + if (nlsf[0] < min_delta[0]) + nlsf[0] = min_delta[0]; + for (i = 1; i < order; i++) + if (nlsf[i] < nlsf[i - 1] + min_delta[i]) + nlsf[i] = nlsf[i - 1] + min_delta[i]; + + /* push backwards to increase distance */ + if (nlsf[order-1] > 32768 - min_delta[order]) + nlsf[order-1] = 32768 - min_delta[order]; + for (i = order-2; i >= 0; i--) + if (nlsf[i] > nlsf[i + 1] - min_delta[i+1]) + nlsf[i] = nlsf[i + 1] - min_delta[i+1]; + + return; +} + +static inline int silk_is_lpc_stable(const int16_t lpc[16], int order) +{ + int k, j, DC_resp = 0; + int32_t lpc32[2][16]; // Q24 + int totalinvgain = 1 << 30; // 1.0 in Q30 + int32_t *row = lpc32[0], *prevrow; + + /* initialize the first row for the Levinson recursion */ + for (k = 0; k < order; k++) { + DC_resp += lpc[k]; + row[k] = lpc[k] * 4096; + } + + if (DC_resp >= 4096) + return 0; + + /* check if prediction gain pushes any coefficients too far */ + for (k = order - 1; 1; k--) { + int rc; // Q31; reflection coefficient + int gaindiv; // Q30; inverse of the gain (the divisor) + int gain; // gain for this reflection coefficient + int fbits; // fractional bits used for the gain + int error; // Q29; estimate of the error of our partial estimate of 1/gaindiv + + if (FFABS(row[k]) > 16773022) + return 0; + + rc = -(row[k] * 128); + gaindiv = (1 << 30) - MULH(rc, rc); + + totalinvgain = MULH(totalinvgain, gaindiv) << 2; + if (k == 0) + return (totalinvgain >= 107374); + + /* approximate 1.0/gaindiv */ + fbits = opus_ilog(gaindiv); + gain = ((1 << 29) - 1) / (gaindiv >> (fbits + 1 - 16)); // Q + error = (1 << 29) - MULL(gaindiv << (15 + 16 - fbits), gain, 16); + gain = ((gain << 16) + (error * gain >> 13)); + + /* switch to the next row of the LPC coefficients */ + prevrow = row; + row = lpc32[k & 1]; + + for (j = 0; j < k; j++) { + int x = prevrow[j] - ROUND_MULL(prevrow[k - j - 1], rc, 31); + row[j] = ROUND_MULL(x, gain, fbits); + } + } +} + +static void silk_lsp2poly(const int32_t lsp[16], int32_t pol[16], int half_order) +{ + int i, j; + + pol[0] = 65536; // 1.0 in Q16 + pol[1] = -lsp[0]; + + for (i = 1; i < half_order; i++) { + pol[i + 1] = pol[i - 1] * 2 - ROUND_MULL(lsp[2 * i], pol[i], 16); + for (j = i; j > 1; j--) + pol[j] += pol[j - 2] - ROUND_MULL(lsp[2 * i], pol[j - 1], 16); + + pol[1] -= lsp[2 * i]; + } +} + +static void silk_lsf2lpc(const int16_t nlsf[16], float lpcf[16], int order) +{ + int i, k; + int32_t lsp[16]; // Q17; 2*cos(LSF) + int32_t p[9], q[9]; // Q16 + int32_t lpc32[16]; // Q17 + int16_t lpc[16]; // Q12 + + /* convert the LSFs to LSPs, i.e. 2*cos(LSF) */ + for (k = 0; k < order; k++) { + int index = nlsf[k] >> 8; + int offset = nlsf[k] & 255; + int k2 = (order == 10) ? silk_lsf_ordering_nbmb[k] : silk_lsf_ordering_wb[k]; + + /* interpolate and round */ + lsp[k2] = silk_cosine[index] * 256; + lsp[k2] += (silk_cosine[index + 1] - silk_cosine[index]) * offset; + lsp[k2] = (lsp[k2] + 4) >> 3; + } + + silk_lsp2poly(lsp , p, order >> 1); + silk_lsp2poly(lsp + 1, q, order >> 1); + + /* reconstruct A(z) */ + for (k = 0; k < order>>1; k++) { + lpc32[k] = -p[k + 1] - p[k] - q[k + 1] + q[k]; + lpc32[order-k-1] = -p[k + 1] - p[k] + q[k + 1] - q[k]; + } + + /* limit the range of the LPC coefficients to each fit within an int16_t */ + for (i = 0; i < 10; i++) { + int j; + unsigned int maxabs = 0; + for (j = 0, k = 0; j < order; j++) { + unsigned int x = FFABS(lpc32[k]); + if (x > maxabs) { + maxabs = x; // Q17 + k = j; + } + } + + maxabs = (maxabs + 16) >> 5; // convert to Q12 + + if (maxabs > 32767) { + /* perform bandwidth expansion */ + unsigned int chirp, chirp_base; // Q16 + maxabs = FFMIN(maxabs, 163838); // anything above this overflows chirp's numerator + chirp_base = chirp = 65470 - ((maxabs - 32767) << 14) / ((maxabs * (k+1)) >> 2); + + for (k = 0; k < order; k++) { + lpc32[k] = ROUND_MULL(lpc32[k], chirp, 16); + chirp = (chirp_base * chirp + 32768) >> 16; + } + } else break; + } + + if (i == 10) { + /* time's up: just clamp */ + for (k = 0; k < order; k++) { + int x = (lpc32[k] + 16) >> 5; + lpc[k] = av_clip_int16(x); + lpc32[k] = lpc[k] << 5; // shortcut mandated by the spec; drops lower 5 bits + } + } else { + for (k = 0; k < order; k++) + lpc[k] = (lpc32[k] + 16) >> 5; + } + + /* if the prediction gain causes the LPC filter to become unstable, + apply further bandwidth expansion on the Q17 coefficients */ + for (i = 1; i <= 16 && !silk_is_lpc_stable(lpc, order); i++) { + unsigned int chirp, chirp_base; + chirp_base = chirp = 65536 - (1 << i); + + for (k = 0; k < order; k++) { + lpc32[k] = ROUND_MULL(lpc32[k], chirp, 16); + lpc[k] = (lpc32[k] + 16) >> 5; + chirp = (chirp_base * chirp + 32768) >> 16; + } + } + + for (i = 0; i < order; i++) + lpcf[i] = lpc[i] / 4096.0f; +} + +static inline void silk_decode_lpc(SilkContext *s, SilkFrame *frame, + OpusRangeCoder *rc, + float lpc_leadin[16], float lpc[16], + int *lpc_order, int *has_lpc_leadin, int voiced) +{ + int i; + int order; // order of the LP polynomial; 10 for NB/MB and 16 for WB + int8_t lsf_i1, lsf_i2[16]; // stage-1 and stage-2 codebook indices + int16_t lsf_res[16]; // residual as a Q10 value + int16_t nlsf[16]; // Q15 + + *lpc_order = order = s->wb ? 16 : 10; + + /* obtain LSF stage-1 and stage-2 indices */ + lsf_i1 = opus_rc_getsymbol(rc, silk_model_lsf_s1[s->wb][voiced]); + for (i = 0; i < order; i++) { + int index = s->wb ? silk_lsf_s2_model_sel_wb [lsf_i1][i] : + silk_lsf_s2_model_sel_nbmb[lsf_i1][i]; + lsf_i2[i] = opus_rc_getsymbol(rc, silk_model_lsf_s2[index]) - 4; + if (lsf_i2[i] == -4) + lsf_i2[i] -= opus_rc_getsymbol(rc, silk_model_lsf_s2_ext); + else if (lsf_i2[i] == 4) + lsf_i2[i] += opus_rc_getsymbol(rc, silk_model_lsf_s2_ext); + } + + /* reverse the backwards-prediction step */ + for (i = order - 1; i >= 0; i--) { + int qstep = s->wb ? 9830 : 11796; + + lsf_res[i] = lsf_i2[i] * 1024; + if (lsf_i2[i] < 0) lsf_res[i] += 102; + else if (lsf_i2[i] > 0) lsf_res[i] -= 102; + lsf_res[i] = (lsf_res[i] * qstep) >> 16; + + if (i + 1 < order) { + int weight = s->wb ? silk_lsf_pred_weights_wb [silk_lsf_weight_sel_wb [lsf_i1][i]][i] : + silk_lsf_pred_weights_nbmb[silk_lsf_weight_sel_nbmb[lsf_i1][i]][i]; + lsf_res[i] += (lsf_res[i+1] * weight) >> 8; + } + } + + /* reconstruct the NLSF coefficients from the supplied indices */ + for (i = 0; i < order; i++) { + const uint8_t * codebook = s->wb ? silk_lsf_codebook_wb [lsf_i1] : + silk_lsf_codebook_nbmb[lsf_i1]; + int cur, prev, next, weight_sq, weight, ipart, fpart, y, value; + + /* find the weight of the residual */ + /* TODO: precompute */ + cur = codebook[i]; + prev = i ? codebook[i - 1] : 0; + next = i + 1 < order ? codebook[i + 1] : 256; + weight_sq = (1024 / (cur - prev) + 1024 / (next - cur)) << 16; + + /* approximate square-root with mandated fixed-point arithmetic */ + ipart = opus_ilog(weight_sq); + fpart = (weight_sq >> (ipart-8)) & 127; + y = ((ipart & 1) ? 32768 : 46214) >> ((32 - ipart)>>1); + weight = y + ((213 * fpart * y) >> 16); + + value = cur * 128 + (lsf_res[i] * 16384) / weight; + nlsf[i] = av_clip(value, 0, 32767); + } + + /* stabilize the NLSF coefficients */ + silk_stabilize_lsf(nlsf, order, s->wb ? silk_lsf_min_spacing_wb : + silk_lsf_min_spacing_nbmb); + + /* produce an interpolation for the first 2 subframes, */ + /* and then convert both sets of NLSFs to LPC coefficients */ + *has_lpc_leadin = 0; + if (s->subframes == 4) { + int offset = opus_rc_getsymbol(rc, silk_model_lsf_interpolation_offset); + if (offset != 4 && frame->coded) { + *has_lpc_leadin = 1; + if (offset != 0) { + int16_t nlsf_leadin[16]; + for (i = 0; i < order; i++) + nlsf_leadin[i] = frame->nlsf[i] + + ((nlsf[i] - frame->nlsf[i]) * offset >> 2); + silk_lsf2lpc(nlsf_leadin, lpc_leadin, order); + } else /* avoid re-computation for a (roughly) 1-in-4 occurrence */ + memcpy(lpc_leadin, frame->lpc, 16 * sizeof(float)); + } else + offset = 4; + s->nlsf_interp_factor = offset; + + silk_lsf2lpc(nlsf, lpc, order); + } else { + s->nlsf_interp_factor = 4; + silk_lsf2lpc(nlsf, lpc, order); + } + + memcpy(frame->nlsf, nlsf, order * sizeof(nlsf[0])); + memcpy(frame->lpc, lpc, order * sizeof(lpc[0])); +} + +static inline void silk_count_children(OpusRangeCoder *rc, int model, int32_t total, + int32_t child[2]) +{ + if (total != 0) { + child[0] = opus_rc_getsymbol(rc, + silk_model_pulse_location[model] + (((total - 1 + 5) * (total - 1)) >> 1)); + child[1] = total - child[0]; + } else { + child[0] = 0; + child[1] = 0; + } +} + +static inline void silk_decode_excitation(SilkContext *s, OpusRangeCoder *rc, + float* excitationf, + int qoffset_high, int active, int voiced) +{ + int i; + uint32_t seed; + int shellblocks; + int ratelevel; + uint8_t pulsecount[20]; // total pulses in each shell block + uint8_t lsbcount[20] = {0}; // raw lsbits defined for each pulse in each shell block + int32_t excitation[320]; // Q23 + + /* excitation parameters */ + seed = opus_rc_getsymbol(rc, silk_model_lcg_seed); + shellblocks = silk_shell_blocks[s->bandwidth][s->subframes >> 2]; + ratelevel = opus_rc_getsymbol(rc, silk_model_exc_rate[voiced]); + + for (i = 0; i < shellblocks; i++) { + pulsecount[i] = opus_rc_getsymbol(rc, silk_model_pulse_count[ratelevel]); + if (pulsecount[i] == 17) { + while (pulsecount[i] == 17 && ++lsbcount[i] != 10) + pulsecount[i] = opus_rc_getsymbol(rc, silk_model_pulse_count[9]); + if (lsbcount[i] == 10) + pulsecount[i] = opus_rc_getsymbol(rc, silk_model_pulse_count[10]); + } + } + + /* decode pulse locations using PVQ */ + for (i = 0; i < shellblocks; i++) { + if (pulsecount[i] != 0) { + int a, b, c, d; + int32_t * location = excitation + 16*i; + int32_t branch[4][2]; + branch[0][0] = pulsecount[i]; + + /* unrolled tail recursion */ + for (a = 0; a < 1; a++) { + silk_count_children(rc, 0, branch[0][a], branch[1]); + for (b = 0; b < 2; b++) { + silk_count_children(rc, 1, branch[1][b], branch[2]); + for (c = 0; c < 2; c++) { + silk_count_children(rc, 2, branch[2][c], branch[3]); + for (d = 0; d < 2; d++) { + silk_count_children(rc, 3, branch[3][d], location); + location += 2; + } + } + } + } + } else + memset(excitation + 16*i, 0, 16*sizeof(int32_t)); + } + + /* decode least significant bits */ + for (i = 0; i < shellblocks << 4; i++) { + int bit; + for (bit = 0; bit < lsbcount[i >> 4]; bit++) + excitation[i] = (excitation[i] << 1) | + opus_rc_getsymbol(rc, silk_model_excitation_lsb); + } + + /* decode signs */ + for (i = 0; i < shellblocks << 4; i++) { + if (excitation[i] != 0) { + int sign = opus_rc_getsymbol(rc, silk_model_excitation_sign[active + + voiced][qoffset_high][FFMIN(pulsecount[i >> 4], 6)]); + if (sign == 0) + excitation[i] *= -1; + } + } + + /* assemble the excitation */ + for (i = 0; i < shellblocks << 4; i++) { + int value = excitation[i]; + excitation[i] = value * 256 | silk_quant_offset[voiced][qoffset_high]; + if (value < 0) excitation[i] += 20; + else if (value > 0) excitation[i] -= 20; + + /* invert samples pseudorandomly */ + seed = 196314165 * seed + 907633515; + if (seed & 0x80000000) + excitation[i] *= -1; + seed += value; + + excitationf[i] = excitation[i] / 8388608.0f; + } +} + +/** Maximum residual history according to 4.2.7.6.1 */ +#define SILK_MAX_LAG (288 + LTP_ORDER / 2) + +/** Order of the LTP filter */ +#define LTP_ORDER 5 + +static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc, + int frame_num, int channel, int coded_channels, int active, int active1) +{ + /* per frame */ + int voiced; // combines with active to indicate inactive, active, or active+voiced + int qoffset_high; + int order; // order of the LPC coefficients + float lpc_leadin[16], lpc_body[16], residual[SILK_MAX_LAG + SILK_HISTORY]; + int has_lpc_leadin; + float ltpscale; + + /* per subframe */ + struct { + float gain; + int pitchlag; + float ltptaps[5]; + } sf[4]; + + SilkFrame * const frame = s->frame + channel; + + int i; + + /* obtain stereo weights */ + if (coded_channels == 2 && channel == 0) { + int n, wi[2], ws[2], w[2]; + n = opus_rc_getsymbol(rc, silk_model_stereo_s1); + wi[0] = opus_rc_getsymbol(rc, silk_model_stereo_s2) + 3 * (n / 5); + ws[0] = opus_rc_getsymbol(rc, silk_model_stereo_s3); + wi[1] = opus_rc_getsymbol(rc, silk_model_stereo_s2) + 3 * (n % 5); + ws[1] = opus_rc_getsymbol(rc, silk_model_stereo_s3); + + for (i = 0; i < 2; i++) + w[i] = silk_stereo_weights[wi[i]] + + (((silk_stereo_weights[wi[i] + 1] - silk_stereo_weights[wi[i]]) * 6554) >> 16) + * (ws[i]*2 + 1); + + s->stereo_weights[0] = (w[0] - w[1]) / 8192.0; + s->stereo_weights[1] = w[1] / 8192.0; + + /* and read the mid-only flag */ + s->midonly = active1 ? 0 : opus_rc_getsymbol(rc, silk_model_mid_only); + } + + /* obtain frame type */ + if (!active) { + qoffset_high = opus_rc_getsymbol(rc, silk_model_frame_type_inactive); + voiced = 0; + } else { + int type = opus_rc_getsymbol(rc, silk_model_frame_type_active); + qoffset_high = type & 1; + voiced = type >> 1; + } + + /* obtain subframe quantization gains */ + for (i = 0; i < s->subframes; i++) { + int log_gain; //Q7 + int ipart, fpart, lingain; + + if (i == 0 && (frame_num == 0 || !frame->coded)) { + /* gain is coded absolute */ + int x = opus_rc_getsymbol(rc, silk_model_gain_highbits[active + voiced]); + log_gain = (x<<3) | opus_rc_getsymbol(rc, silk_model_gain_lowbits); + + if (frame->coded) + log_gain = FFMAX(log_gain, frame->log_gain - 16); + } 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); + } + + frame->log_gain = log_gain; + + /* approximate 2**(x/128) with a Q7 (i.e. non-integer) input */ + log_gain = (log_gain * 0x1D1C71 >> 16) + 2090; + ipart = log_gain >> 7; + fpart = log_gain & 127; + lingain = (1 << ipart) + ((-174 * fpart * (128-fpart) >>16) + fpart) * ((1<> 7); + sf[i].gain = lingain / 65536.0f; + } + + /* obtain LPC filter coefficients */ + silk_decode_lpc(s, frame, rc, lpc_leadin, lpc_body, &order, &has_lpc_leadin, voiced); + + /* obtain pitch lags, if this is a voiced frame */ + if (voiced) { + int lag_absolute = (!frame_num || !frame->prev_voiced); + int primarylag; // primary pitch lag for the entire SILK frame + int ltpfilter; + const int8_t * offsets; + + if (!lag_absolute) { + int delta = opus_rc_getsymbol(rc, silk_model_pitch_delta); + if (delta) + primarylag = frame->primarylag + delta - 9; + else + lag_absolute = 1; + } + + if (lag_absolute) { + /* primary lag is coded absolute */ + int highbits, lowbits; + const uint16_t *model[] = { + silk_model_pitch_lowbits_nb, silk_model_pitch_lowbits_mb, + silk_model_pitch_lowbits_wb + }; + highbits = opus_rc_getsymbol(rc, silk_model_pitch_highbits); + lowbits = opus_rc_getsymbol(rc, model[s->bandwidth]); + + primarylag = silk_pitch_min_lag[s->bandwidth] + + highbits*silk_pitch_scale[s->bandwidth] + lowbits; + } + frame->primarylag = primarylag; + + if (s->subframes == 2) + offsets = (s->bandwidth == OPUS_BANDWIDTH_NARROWBAND) + ? silk_pitch_offset_nb10ms[opus_rc_getsymbol(rc, + silk_model_pitch_contour_nb10ms)] + : silk_pitch_offset_mbwb10ms[opus_rc_getsymbol(rc, + silk_model_pitch_contour_mbwb10ms)]; + else + offsets = (s->bandwidth == OPUS_BANDWIDTH_NARROWBAND) + ? silk_pitch_offset_nb20ms[opus_rc_getsymbol(rc, + silk_model_pitch_contour_nb20ms)] + : silk_pitch_offset_mbwb20ms[opus_rc_getsymbol(rc, + silk_model_pitch_contour_mbwb20ms)]; + + for (i = 0; i < s->subframes; i++) + sf[i].pitchlag = av_clip(primarylag + offsets[i], + silk_pitch_min_lag[s->bandwidth], + silk_pitch_max_lag[s->bandwidth]); + + /* obtain LTP filter coefficients */ + ltpfilter = opus_rc_getsymbol(rc, silk_model_ltp_filter); + for (i = 0; i < s->subframes; i++) { + int index, j; + 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] = { + silk_ltp_filter0_taps, silk_ltp_filter1_taps, silk_ltp_filter2_taps + }; + index = opus_rc_getsymbol(rc, filter_sel[ltpfilter]); + for (j = 0; j < 5; j++) + sf[i].ltptaps[j] = filter_taps[ltpfilter][index][j] / 128.0f; + } + } + + /* obtain LTP scale factor */ + if (voiced && frame_num == 0) + ltpscale = silk_ltp_scale_factor[opus_rc_getsymbol(rc, + silk_model_ltp_scale_index)] / 16384.0f; + else ltpscale = 15565.0f/16384.0f; + + /* generate the excitation signal for the entire frame */ + silk_decode_excitation(s, rc, residual + SILK_MAX_LAG, qoffset_high, + active, voiced); + + /* skip synthesising the side channel if we want mono-only */ + if (s->output_channels == channel) + return; + + /* generate the output signal */ + for (i = 0; i < s->subframes; i++) { + const float * lpc_coeff = (i < 2 && has_lpc_leadin) ? lpc_leadin : lpc_body; + float *dst = frame->output + SILK_HISTORY + i * s->sflength; + float *resptr = residual + SILK_MAX_LAG + i * s->sflength; + float *lpc = frame->lpc_history + SILK_HISTORY + i * s->sflength; + float sum; + int j, k; + + if (voiced) { + int out_end; + float scale; + + if (i < 2 || s->nlsf_interp_factor == 4) { + out_end = -i * s->sflength; + scale = ltpscale; + } else { + out_end = -(i - 2) * s->sflength; + scale = 1.0f; + } + + /* when the LPC coefficients change, a re-whitening filter is used */ + /* to produce a residual that accounts for the change */ + for (j = - sf[i].pitchlag - LTP_ORDER/2; j < out_end; j++) { + sum = dst[j]; + for (k = 0; k < order; k++) + sum -= lpc_coeff[k] * dst[j - k - 1]; + resptr[j] = av_clipf(sum, -1.0f, 1.0f) * scale / sf[i].gain; + } + + if (out_end) { + float rescale = sf[i-1].gain / sf[i].gain; + for (j = out_end; j < 0; j++) + resptr[j] *= rescale; + } + + /* LTP synthesis */ + for (j = 0; j < s->sflength; j++) { + sum = resptr[j]; + for (k = 0; k < LTP_ORDER; k++) + sum += sf[i].ltptaps[k] * resptr[j - sf[i].pitchlag + LTP_ORDER/2 - k]; + resptr[j] = sum; + } + } + + /* LPC synthesis */ + for (j = 0; j < s->sflength; j++) { + sum = resptr[j] * sf[i].gain; + for (k = 1; k <= order; k++) + sum += lpc_coeff[k - 1] * lpc[j - k]; + + lpc[j] = sum; + dst[j] = av_clipf(sum, -1.0f, 1.0f); + } + } + + frame->prev_voiced = voiced; + memmove(frame->lpc_history, frame->lpc_history + s->flength, SILK_HISTORY * sizeof(float)); + memmove(frame->output, frame->output + s->flength, SILK_HISTORY * sizeof(float)); + + frame->coded = 1; +} + +static void silk_unmix_ms(SilkContext *s, float *l, float *r) +{ + float *mid = s->frame[0].output + SILK_HISTORY - s->flength; + float *side = s->frame[1].output + SILK_HISTORY - s->flength; + float w0_prev = s->prev_stereo_weights[0]; + float w1_prev = s->prev_stereo_weights[1]; + float w0 = s->stereo_weights[0]; + float w1 = s->stereo_weights[1]; + int n1 = silk_stereo_interp_len[s->bandwidth]; + int i; + + for (i = 0; i < n1; i++) { + float interp0 = w0_prev + i * (w0 - w0_prev) / n1; + float interp1 = w1_prev + i * (w1 - w1_prev) / n1; + float p0 = 0.25 * (mid[i - 2] + 2 * mid[i - 1] + mid[i]); + + l[i] = av_clipf((1 + interp1) * mid[i - 1] + side[i - 1] + interp0 * p0, -1.0, 1.0); + r[i] = av_clipf((1 - interp1) * mid[i - 1] - side[i - 1] - interp0 * p0, -1.0, 1.0); + } + + for (; i < s->flength; i++) { + float p0 = 0.25 * (mid[i - 2] + 2 * mid[i - 1] + mid[i]); + + l[i] = av_clipf((1 + w1) * mid[i - 1] + side[i - 1] + w0 * p0, -1.0, 1.0); + r[i] = av_clipf((1 - w1) * mid[i - 1] - side[i - 1] - w0 * p0, -1.0, 1.0); + } + + memcpy(s->prev_stereo_weights, s->stereo_weights, sizeof(s->stereo_weights)); +} + +static void silk_flush_frame(SilkFrame *frame) +{ + if (!frame->coded) + return; + + memset(frame->output, 0, sizeof(frame->output)); + memset(frame->lpc_history, 0, sizeof(frame->lpc_history)); + + memset(frame->lpc, 0, sizeof(frame->lpc)); + memset(frame->nlsf, 0, sizeof(frame->nlsf)); + + frame->log_gain = 0; + + frame->primarylag = 0; + frame->prev_voiced = 0; + frame->coded = 0; +} + +int ff_silk_decode_superframe(SilkContext *s, OpusRangeCoder *rc, + float *output[2], + enum OpusBandwidth bandwidth, + int coded_channels, + int duration_ms) +{ + int active[2][6], redundancy[2]; + int nb_frames, i, j; + + if (bandwidth > OPUS_BANDWIDTH_WIDEBAND || + coded_channels > 2 || duration_ms > 60) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid parameters passed " + "to the SILK decoder.\n"); + return AVERROR(EINVAL); + } + + nb_frames = 1 + (duration_ms > 20) + (duration_ms > 40); + s->subframes = duration_ms / nb_frames / 5; // 5ms subframes + s->sflength = 20 * (bandwidth + 2); + s->flength = s->sflength * s->subframes; + s->bandwidth = bandwidth; + s->wb = bandwidth == OPUS_BANDWIDTH_WIDEBAND; + + /* make sure to flush the side channel when switching from mono to stereo */ + if (coded_channels > s->prev_coded_channels) + silk_flush_frame(&s->frame[1]); + s->prev_coded_channels = coded_channels; + + /* read the LP-layer header bits */ + for (i = 0; i < coded_channels; i++) { + for (j = 0; j < nb_frames; j++) + active[i][j] = opus_rc_p2model(rc, 1); + + redundancy[i] = opus_rc_p2model(rc, 1); + if (redundancy[i]) { + av_log(s->avctx, AV_LOG_ERROR, "LBRR frames present; this is unsupported\n"); + return AVERROR_PATCHWELCOME; + } + } + + for (i = 0; i < nb_frames; i++) { + for (j = 0; j < coded_channels && !s->midonly; j++) + silk_decode_frame(s, rc, i, j, coded_channels, active[j][i], active[1][i]); + + /* reset the side channel if it is not coded */ + if (s->midonly && s->frame[1].coded) + silk_flush_frame(&s->frame[1]); + + if (coded_channels == 1 || s->output_channels == 1) { + for (j = 0; j < s->output_channels; j++) { + memcpy(output[j] + i * s->flength, + s->frame[0].output + SILK_HISTORY - s->flength - 2, + s->flength * sizeof(float)); + } + } else { + silk_unmix_ms(s, output[0] + i * s->flength, output[1] + i * s->flength); + } + + s->midonly = 0; + } + + return nb_frames * s->flength; +} + +void ff_silk_free(SilkContext **ps) +{ + av_freep(ps); +} + +void ff_silk_flush(SilkContext *s) +{ + silk_flush_frame(&s->frame[0]); + silk_flush_frame(&s->frame[1]); + + memset(s->prev_stereo_weights, 0, sizeof(s->prev_stereo_weights)); +} + +int ff_silk_init(AVCodecContext *avctx, SilkContext **ps, int output_channels) +{ + SilkContext *s; + + if (output_channels != 1 && output_channels != 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of output channels: %d\n", + output_channels); + return AVERROR(EINVAL); + } + + s = av_mallocz(sizeof(*s)); + if (!s) + return AVERROR(ENOMEM); + + s->avctx = avctx; + s->output_channels = output_channels; + + ff_silk_flush(s); + + *ps = s; + + return 0; +} diff --git a/libavcodec/opusdec.c b/libavcodec/opusdec.c new file mode 100644 index 000000000..b28edfbcd --- /dev/null +++ b/libavcodec/opusdec.c @@ -0,0 +1,674 @@ +/* + * Opus decoder + * Copyright (c) 2012 Andrew D'Addesio + * Copyright (c) 2013-2014 Mozilla Corporation + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Opus decoder + * @author Andrew D'Addesio, Anton Khirnov + * + * Codec homepage: http://opus-codec.org/ + * Specification: http://tools.ietf.org/html/rfc6716 + * Ogg Opus specification: https://tools.ietf.org/html/draft-ietf-codec-oggopus-03 + * + * Ogg-contained .opus files can be produced with opus-tools: + * http://git.xiph.org/?p=opus-tools.git + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/audio_fifo.h" +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" + +#include "libswresample/swresample.h" + +#include "avcodec.h" +#include "celp_filters.h" +#include "fft.h" +#include "get_bits.h" +#include "internal.h" +#include "mathops.h" +#include "opus.h" + +static const uint16_t silk_frame_duration_ms[16] = { + 10, 20, 40, 60, + 10, 20, 40, 60, + 10, 20, 40, 60, + 10, 20, + 10, 20, +}; + +/* number of samples of silence to feed to the resampler + * at the beginning */ +static const int silk_resample_delay[] = { + 4, 8, 11, 11, 11 +}; + +static const uint8_t celt_band_end[] = { 13, 17, 17, 19, 21 }; + +static int get_silk_samplerate(int config) +{ + if (config < 4) + return 8000; + else if (config < 8) + return 12000; + return 16000; +} + +/** + * Range decoder + */ +static int opus_rc_init(OpusRangeCoder *rc, const uint8_t *data, int size) +{ + int ret = init_get_bits8(&rc->gb, data, size); + if (ret < 0) + return ret; + + rc->range = 128; + rc->value = 127 - get_bits(&rc->gb, 7); + rc->total_read_bits = 9; + opus_rc_normalize(rc); + + return 0; +} + +static void opus_raw_init(OpusRangeCoder *rc, const uint8_t *rightend, + unsigned int bytes) +{ + rc->rb.position = rightend; + rc->rb.bytes = bytes; + rc->rb.cachelen = 0; + rc->rb.cacheval = 0; +} + +static void opus_fade(float *out, + const float *in1, const float *in2, + const float *window, int len) +{ + int i; + for (i = 0; i < len; i++) + out[i] = in2[i] * window[i] + in1[i] * (1.0 - window[i]); +} + +static int opus_flush_resample(OpusStreamContext *s, int nb_samples) +{ + int celt_size = av_audio_fifo_size(s->celt_delay); + int ret, i; + ret = swr_convert(s->swr, + (uint8_t**)s->out, nb_samples, + NULL, 0); + if (ret < 0) + return ret; + else if (ret != nb_samples) { + av_log(s->avctx, AV_LOG_ERROR, "Wrong number of flushed samples: %d\n", + ret); + return AVERROR_BUG; + } + + if (celt_size) { + if (celt_size != nb_samples) { + av_log(s->avctx, AV_LOG_ERROR, "Wrong number of CELT delay samples.\n"); + return AVERROR_BUG; + } + av_audio_fifo_read(s->celt_delay, (void**)s->celt_output, nb_samples); + for (i = 0; i < s->output_channels; i++) { + s->fdsp->vector_fmac_scalar(s->out[i], + s->celt_output[i], 1.0, + nb_samples); + } + } + + if (s->redundancy_idx) { + for (i = 0; i < s->output_channels; i++) + opus_fade(s->out[i], s->out[i], + s->redundancy_output[i] + 120 + s->redundancy_idx, + ff_celt_window2 + s->redundancy_idx, 120 - s->redundancy_idx); + s->redundancy_idx = 0; + } + + s->out[0] += nb_samples; + s->out[1] += nb_samples; + s->out_size -= nb_samples * sizeof(float); + + return 0; +} + +static int opus_init_resample(OpusStreamContext *s) +{ + static const float delay[16] = { 0.0 }; + const uint8_t *delayptr[2] = { (uint8_t*)delay, (uint8_t*)delay }; + int ret; + + av_opt_set_int(s->swr, "in_sample_rate", s->silk_samplerate, 0); + ret = swr_init(s->swr); + if (ret < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Error opening the resampler.\n"); + return ret; + } + + ret = swr_convert(s->swr, + NULL, 0, + delayptr, silk_resample_delay[s->packet.bandwidth]); + if (ret < 0) { + av_log(s->avctx, AV_LOG_ERROR, + "Error feeding initial silence to the resampler.\n"); + return ret; + } + + return 0; +} + +static int opus_decode_redundancy(OpusStreamContext *s, const uint8_t *data, int size) +{ + int ret; + enum OpusBandwidth bw = s->packet.bandwidth; + + if (s->packet.mode == OPUS_MODE_SILK && + bw == OPUS_BANDWIDTH_MEDIUMBAND) + bw = OPUS_BANDWIDTH_WIDEBAND; + + ret = opus_rc_init(&s->redundancy_rc, data, size); + if (ret < 0) + goto fail; + opus_raw_init(&s->redundancy_rc, data + size, size); + + ret = ff_celt_decode_frame(s->celt, &s->redundancy_rc, + s->redundancy_output, + s->packet.stereo + 1, 240, + 0, celt_band_end[s->packet.bandwidth]); + if (ret < 0) + goto fail; + + return 0; +fail: + av_log(s->avctx, AV_LOG_ERROR, "Error decoding the redundancy frame.\n"); + return ret; +} + +static int opus_decode_frame(OpusStreamContext *s, const uint8_t *data, int size) +{ + int samples = s->packet.frame_duration; + int redundancy = 0; + int redundancy_size, redundancy_pos; + int ret, i, consumed; + int delayed_samples = s->delayed_samples; + + ret = opus_rc_init(&s->rc, data, size); + if (ret < 0) + return ret; + + /* decode the silk frame */ + if (s->packet.mode == OPUS_MODE_SILK || s->packet.mode == OPUS_MODE_HYBRID) { + if (!swr_is_initialized(s->swr)) { + ret = opus_init_resample(s); + if (ret < 0) + return ret; + } + + samples = ff_silk_decode_superframe(s->silk, &s->rc, s->silk_output, + FFMIN(s->packet.bandwidth, OPUS_BANDWIDTH_WIDEBAND), + s->packet.stereo + 1, + silk_frame_duration_ms[s->packet.config]); + if (samples < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Error decoding a SILK frame.\n"); + return samples; + } + samples = swr_convert(s->swr, + (uint8_t**)s->out, s->packet.frame_duration, + (const uint8_t**)s->silk_output, samples); + if (samples < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Error resampling SILK data.\n"); + return samples; + } + av_assert2((samples & 7) == 0); + s->delayed_samples += s->packet.frame_duration - samples; + } else + ff_silk_flush(s->silk); + + // decode redundancy information + consumed = opus_rc_tell(&s->rc); + if (s->packet.mode == OPUS_MODE_HYBRID && consumed + 37 <= size * 8) + redundancy = opus_rc_p2model(&s->rc, 12); + else if (s->packet.mode == OPUS_MODE_SILK && consumed + 17 <= size * 8) + redundancy = 1; + + if (redundancy) { + redundancy_pos = opus_rc_p2model(&s->rc, 1); + + if (s->packet.mode == OPUS_MODE_HYBRID) + redundancy_size = opus_rc_unimodel(&s->rc, 256) + 2; + else + redundancy_size = size - (consumed + 7) / 8; + size -= redundancy_size; + if (size < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid redundancy frame size.\n"); + return AVERROR_INVALIDDATA; + } + + if (redundancy_pos) { + ret = opus_decode_redundancy(s, data + size, redundancy_size); + if (ret < 0) + return ret; + ff_celt_flush(s->celt); + } + } + + /* decode the CELT frame */ + if (s->packet.mode == OPUS_MODE_CELT || s->packet.mode == OPUS_MODE_HYBRID) { + float *out_tmp[2] = { s->out[0], s->out[1] }; + float **dst = (s->packet.mode == OPUS_MODE_CELT) ? + out_tmp : s->celt_output; + int celt_output_samples = samples; + int delay_samples = av_audio_fifo_size(s->celt_delay); + + if (delay_samples) { + if (s->packet.mode == OPUS_MODE_HYBRID) { + av_audio_fifo_read(s->celt_delay, (void**)s->celt_output, delay_samples); + + for (i = 0; i < s->output_channels; i++) { + s->fdsp->vector_fmac_scalar(out_tmp[i], s->celt_output[i], 1.0, + delay_samples); + out_tmp[i] += delay_samples; + } + celt_output_samples -= delay_samples; + } else { + av_log(s->avctx, AV_LOG_WARNING, + "Spurious CELT delay samples present.\n"); + av_audio_fifo_drain(s->celt_delay, delay_samples); + if (s->avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_BUG; + } + } + + opus_raw_init(&s->rc, data + size, size); + + ret = ff_celt_decode_frame(s->celt, &s->rc, dst, + s->packet.stereo + 1, + s->packet.frame_duration, + (s->packet.mode == OPUS_MODE_HYBRID) ? 17 : 0, + celt_band_end[s->packet.bandwidth]); + if (ret < 0) + return ret; + + if (s->packet.mode == OPUS_MODE_HYBRID) { + int celt_delay = s->packet.frame_duration - celt_output_samples; + void *delaybuf[2] = { s->celt_output[0] + celt_output_samples, + s->celt_output[1] + celt_output_samples }; + + for (i = 0; i < s->output_channels; i++) { + s->fdsp->vector_fmac_scalar(out_tmp[i], + s->celt_output[i], 1.0, + celt_output_samples); + } + + ret = av_audio_fifo_write(s->celt_delay, delaybuf, celt_delay); + if (ret < 0) + return ret; + } + } else + ff_celt_flush(s->celt); + + if (s->redundancy_idx) { + for (i = 0; i < s->output_channels; i++) + opus_fade(s->out[i], s->out[i], + s->redundancy_output[i] + 120 + s->redundancy_idx, + ff_celt_window2 + s->redundancy_idx, 120 - s->redundancy_idx); + s->redundancy_idx = 0; + } + if (redundancy) { + if (!redundancy_pos) { + ff_celt_flush(s->celt); + ret = opus_decode_redundancy(s, data + size, redundancy_size); + if (ret < 0) + return ret; + + for (i = 0; i < s->output_channels; i++) { + opus_fade(s->out[i] + samples - 120 + delayed_samples, + s->out[i] + samples - 120 + delayed_samples, + s->redundancy_output[i] + 120, + ff_celt_window2, 120 - delayed_samples); + if (delayed_samples) + s->redundancy_idx = 120 - delayed_samples; + } + } else { + for (i = 0; i < s->output_channels; i++) { + memcpy(s->out[i] + delayed_samples, s->redundancy_output[i], 120 * sizeof(float)); + opus_fade(s->out[i] + 120 + delayed_samples, + s->redundancy_output[i] + 120, + s->out[i] + 120 + delayed_samples, + ff_celt_window2, 120); + } + } + } + + return samples; +} + +static int opus_decode_subpacket(OpusStreamContext *s, + const uint8_t *buf, int buf_size, + int nb_samples) +{ + int output_samples = 0; + int flush_needed = 0; + int i, j, ret; + + /* check if we need to flush the resampler */ + if (swr_is_initialized(s->swr)) { + if (buf) { + int64_t cur_samplerate; + av_opt_get_int(s->swr, "in_sample_rate", 0, &cur_samplerate); + flush_needed = (s->packet.mode == OPUS_MODE_CELT) || (cur_samplerate != s->silk_samplerate); + } else { + flush_needed = !!s->delayed_samples; + } + } + + if (!buf && !flush_needed) + return 0; + + /* use dummy output buffers if the channel is not mapped to anything */ + if (!s->out[0] || + (s->output_channels == 2 && !s->out[1])) { + av_fast_malloc(&s->out_dummy, &s->out_dummy_allocated_size, s->out_size); + if (!s->out_dummy) + return AVERROR(ENOMEM); + if (!s->out[0]) + s->out[0] = s->out_dummy; + if (!s->out[1]) + s->out[1] = s->out_dummy; + } + + /* flush the resampler if necessary */ + if (flush_needed) { + ret = opus_flush_resample(s, s->delayed_samples); + if (ret < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Error flushing the resampler.\n"); + return ret; + } + swr_close(s->swr); + output_samples += s->delayed_samples; + s->delayed_samples = 0; + + if (!buf) + goto finish; + } + + /* decode all the frames in the packet */ + for (i = 0; i < s->packet.frame_count; i++) { + int size = s->packet.frame_size[i]; + int samples = opus_decode_frame(s, buf + s->packet.frame_offset[i], size); + + if (samples < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Error decoding an Opus frame.\n"); + if (s->avctx->err_recognition & AV_EF_EXPLODE) + return samples; + + for (j = 0; j < s->output_channels; j++) + memset(s->out[j], 0, s->packet.frame_duration * sizeof(float)); + samples = s->packet.frame_duration; + } + output_samples += samples; + + for (j = 0; j < s->output_channels; j++) + s->out[j] += samples; + s->out_size -= samples * sizeof(float); + } + +finish: + s->out[0] = s->out[1] = NULL; + s->out_size = 0; + + return output_samples; +} + +static int opus_decode_packet(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + OpusContext *c = avctx->priv_data; + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int coded_samples = 0; + int decoded_samples = 0; + int i, ret; + + /* decode the header of the first sub-packet to find out the sample count */ + if (buf) { + OpusPacket *pkt = &c->streams[0].packet; + ret = ff_opus_parse_packet(pkt, buf, buf_size, c->nb_streams > 1); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error parsing the packet header.\n"); + return ret; + } + coded_samples += pkt->frame_count * pkt->frame_duration; + c->streams[0].silk_samplerate = get_silk_samplerate(pkt->config); + } + + frame->nb_samples = coded_samples + c->streams[0].delayed_samples; + + /* no input or buffered data => nothing to do */ + if (!frame->nb_samples) { + *got_frame_ptr = 0; + return 0; + } + + /* setup the data buffers */ + ret = ff_get_buffer(avctx, frame, 0); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + frame->nb_samples = 0; + + for (i = 0; i < avctx->channels; i++) { + ChannelMap *map = &c->channel_maps[i]; + if (!map->copy) + c->streams[map->stream_idx].out[map->channel_idx] = (float*)frame->extended_data[i]; + } + + for (i = 0; i < c->nb_streams; i++) + c->streams[i].out_size = frame->linesize[0]; + + /* decode each sub-packet */ + for (i = 0; i < c->nb_streams; i++) { + OpusStreamContext *s = &c->streams[i]; + + if (i && buf) { + ret = ff_opus_parse_packet(&s->packet, buf, buf_size, i != c->nb_streams - 1); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error parsing the packet header.\n"); + return ret; + } + s->silk_samplerate = get_silk_samplerate(s->packet.config); + } + + ret = opus_decode_subpacket(&c->streams[i], buf, + s->packet.data_size, coded_samples); + if (ret < 0) + return ret; + if (decoded_samples && ret != decoded_samples) { + av_log(avctx, AV_LOG_ERROR, "Different numbers of decoded samples " + "in a multi-channel stream\n"); + return AVERROR_INVALIDDATA; + } + decoded_samples = ret; + buf += s->packet.packet_size; + buf_size -= s->packet.packet_size; + } + + for (i = 0; i < avctx->channels; i++) { + ChannelMap *map = &c->channel_maps[i]; + + /* handle copied channels */ + if (map->copy) { + memcpy(frame->extended_data[i], + frame->extended_data[map->copy_idx], + frame->linesize[0]); + } else if (map->silence) { + memset(frame->extended_data[i], 0, frame->linesize[0]); + } + + if (c->gain_i) { + c->fdsp.vector_fmul_scalar((float*)frame->extended_data[i], + (float*)frame->extended_data[i], + c->gain, FFALIGN(decoded_samples, 8)); + } + } + + frame->nb_samples = decoded_samples; + *got_frame_ptr = !!decoded_samples; + + return avpkt->size; +} + +static av_cold void opus_decode_flush(AVCodecContext *ctx) +{ + OpusContext *c = ctx->priv_data; + int i; + + for (i = 0; i < c->nb_streams; i++) { + OpusStreamContext *s = &c->streams[i]; + + memset(&s->packet, 0, sizeof(s->packet)); + s->delayed_samples = 0; + + if (s->celt_delay) + av_audio_fifo_drain(s->celt_delay, av_audio_fifo_size(s->celt_delay)); + swr_close(s->swr); + + ff_silk_flush(s->silk); + ff_celt_flush(s->celt); + } +} + +static av_cold int opus_decode_close(AVCodecContext *avctx) +{ + OpusContext *c = avctx->priv_data; + int i; + + for (i = 0; i < c->nb_streams; i++) { + OpusStreamContext *s = &c->streams[i]; + + ff_silk_free(&s->silk); + ff_celt_free(&s->celt); + + av_freep(&s->out_dummy); + s->out_dummy_allocated_size = 0; + + av_audio_fifo_free(s->celt_delay); + swr_free(&s->swr); + } + + av_freep(&c->streams); + c->nb_streams = 0; + + av_freep(&c->channel_maps); + + return 0; +} + +static av_cold int opus_decode_init(AVCodecContext *avctx) +{ + OpusContext *c = avctx->priv_data; + int ret, i, j; + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + avctx->sample_rate = 48000; + + avpriv_float_dsp_init(&c->fdsp, 0); + + /* find out the channel configuration */ + ret = ff_opus_parse_extradata(avctx, c); + if (ret < 0) + return ret; + + /* allocate and init each independent decoder */ + c->streams = av_mallocz_array(c->nb_streams, sizeof(*c->streams)); + if (!c->streams) { + c->nb_streams = 0; + ret = AVERROR(ENOMEM); + goto fail; + } + + for (i = 0; i < c->nb_streams; i++) { + OpusStreamContext *s = &c->streams[i]; + uint64_t layout; + + s->output_channels = (i < c->nb_stereo_streams) ? 2 : 1; + + s->avctx = avctx; + + for (j = 0; j < s->output_channels; j++) { + s->silk_output[j] = s->silk_buf[j]; + s->celt_output[j] = s->celt_buf[j]; + s->redundancy_output[j] = s->redundancy_buf[j]; + } + + s->fdsp = &c->fdsp; + + s->swr =swr_alloc(); + if (!s->swr) + goto fail; + + layout = (s->output_channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; + av_opt_set_int(s->swr, "in_sample_fmt", avctx->sample_fmt, 0); + av_opt_set_int(s->swr, "out_sample_fmt", avctx->sample_fmt, 0); + av_opt_set_int(s->swr, "in_channel_layout", layout, 0); + av_opt_set_int(s->swr, "out_channel_layout", layout, 0); + av_opt_set_int(s->swr, "out_sample_rate", avctx->sample_rate, 0); + av_opt_set_int(s->swr, "filter_size", 16, 0); + + ret = ff_silk_init(avctx, &s->silk, s->output_channels); + if (ret < 0) + goto fail; + + ret = ff_celt_init(avctx, &s->celt, s->output_channels); + if (ret < 0) + goto fail; + + s->celt_delay = av_audio_fifo_alloc(avctx->sample_fmt, + s->output_channels, 1024); + if (!s->celt_delay) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + + return 0; +fail: + opus_decode_close(avctx); + return ret; +} + +AVCodec ff_opus_decoder = { + .name = "opus", + .long_name = NULL_IF_CONFIG_SMALL("Opus"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_OPUS, + .priv_data_size = sizeof(OpusContext), + .init = opus_decode_init, + .close = opus_decode_close, + .decode = opus_decode_packet, + .flush = opus_decode_flush, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, +}; diff --git a/libavcodec/pafaudio.c b/libavcodec/pafaudio.c new file mode 100644 index 000000000..9b485335e --- /dev/null +++ b/libavcodec/pafaudio.c @@ -0,0 +1,84 @@ +/* + * Packed Animation File audio decoder + * Copyright (c) 2012 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" + +#include "avcodec.h" +#include "internal.h" +#include "mathops.h" + +#define PAF_SOUND_SAMPLES 2205 +#define PAF_SOUND_FRAME_SIZE ((256 + PAF_SOUND_SAMPLES) * 2) + +static av_cold int paf_audio_init(AVCodecContext *avctx) +{ + if (avctx->channels != 2) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); + return AVERROR_INVALIDDATA; + } + + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + return 0; +} + +static int paf_audio_decode(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *pkt) +{ + AVFrame *frame = data; + int16_t *output_samples; + const uint8_t *src = pkt->data; + int frames, ret, i, j; + int16_t cb[256]; + + frames = pkt->size / PAF_SOUND_FRAME_SIZE; + if (frames < 1) + return AVERROR_INVALIDDATA; + + frame->nb_samples = PAF_SOUND_SAMPLES * frames; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + output_samples = (int16_t *)frame->data[0]; + // codebook of 256 16-bit samples and 8-bit indices to it + for (j = 0; j < frames; j++) { + for (i = 0; i < 256; i++) + cb[i] = sign_extend(AV_RL16(src + i * 2), 16); + src += 256 * 2; + // always 2 channels + for (i = 0; i < PAF_SOUND_SAMPLES * 2; i++) + *output_samples++ = cb[*src++]; + } + *got_frame = 1; + + return pkt->size; +} + +AVCodec ff_paf_audio_decoder = { + .name = "paf_audio", + .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_PAF_AUDIO, + .init = paf_audio_init, + .decode = paf_audio_decode, + .capabilities = CODEC_CAP_DR1, +}; diff --git a/libavcodec/paf.c b/libavcodec/pafvideo.c similarity index 56% rename from libavcodec/paf.c rename to libavcodec/pafvideo.c index 76c90c9f4..0e92989eb 100644 --- a/libavcodec/paf.c +++ b/libavcodec/pafvideo.c @@ -1,5 +1,5 @@ /* - * Packed Animation File video and audio decoder + * Packed Animation File video decoder * Copyright (c) 2012 Paul B Mahol * * This file is part of FFmpeg. @@ -19,16 +19,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" + #include "libavcodec/paf.h" -#include "bytestream.h" #include "avcodec.h" +#include "bytestream.h" #include "copy_block.h" #include "internal.h" -static const uint8_t block_sequences[16][8] = -{ +static const uint8_t block_sequences[16][8] = { { 0, 0, 0, 0, 0, 0, 0, 0 }, { 2, 0, 0, 0, 0, 0, 0, 0 }, { 5, 7, 0, 0, 0, 0, 0, 0 }, @@ -44,22 +44,25 @@ static const uint8_t block_sequences[16][8] = { 2, 4, 5, 7, 0, 0, 0, 0 }, { 2, 4, 5, 0, 0, 0, 0, 0 }, { 2, 4, 6, 0, 0, 0, 0, 0 }, - { 2, 4, 5, 7, 5, 7, 0, 0 } + { 2, 4, 5, 7, 5, 7, 0, 0 }, }; typedef struct PAFVideoDecContext { AVFrame *pic; GetByteContext gb; - int current_frame; + int width; + int height; + + int current_frame; uint8_t *frame[4]; - int frame_size; - int video_size; + int frame_size; + int video_size; uint8_t *opcodes; } PAFVideoDecContext; -static av_cold int paf_vid_close(AVCodecContext *avctx) +static av_cold int paf_video_close(AVCodecContext *avctx) { PAFVideoDecContext *c = avctx->priv_data; int i; @@ -72,13 +75,18 @@ static av_cold int paf_vid_close(AVCodecContext *avctx) return 0; } -static av_cold int paf_vid_init(AVCodecContext *avctx) +static av_cold int paf_video_init(AVCodecContext *avctx) { PAFVideoDecContext *c = avctx->priv_data; int i; + c->width = avctx->width; + c->height = avctx->height; + if (avctx->height & 3 || avctx->width & 3) { - av_log(avctx, AV_LOG_ERROR, "width and height must be multiplies of 4\n"); + av_log(avctx, AV_LOG_ERROR, + "width %d and height %d must be multiplie of 4.\n", + avctx->width, avctx->height); return AVERROR_INVALIDDATA; } @@ -88,12 +96,12 @@ static av_cold int paf_vid_init(AVCodecContext *avctx) if (!c->pic) return AVERROR(ENOMEM); - c->frame_size = FFALIGN(avctx->height, 256) * avctx->width; - c->video_size = avctx->height * avctx->width; + c->frame_size = avctx->width * FFALIGN(avctx->height, 256); + c->video_size = avctx->width * avctx->height; for (i = 0; i < 4; i++) { c->frame[i] = av_mallocz(c->frame_size); if (!c->frame[i]) { - paf_vid_close(avctx); + paf_video_close(avctx); return AVERROR(ENOMEM); } } @@ -101,58 +109,59 @@ static av_cold int paf_vid_init(AVCodecContext *avctx) return 0; } -static int get_video_page_offset(AVCodecContext *avctx, uint8_t a, uint8_t b) +static void read4x4block(PAFVideoDecContext *c, uint8_t *dst, int width) { - int x, y; - - x = b & 0x7F; - y = ((a & 0x3F) << 1) | (b >> 7 & 1); - - return y * 2 * avctx->width + x * 2; -} - -static void copy4h(AVCodecContext *avctx, uint8_t *dst) -{ - PAFVideoDecContext *c = avctx->priv_data; int i; for (i = 0; i < 4; i++) { bytestream2_get_buffer(&c->gb, dst, 4); - dst += avctx->width; + dst += width; } } -static void copy_color_mask(AVCodecContext *avctx, uint8_t mask, uint8_t *dst, uint8_t color) +static void copy_color_mask(uint8_t *dst, int width, uint8_t mask, uint8_t color) { int i; for (i = 0; i < 4; i++) { - if ((mask >> 4) & (1 << (3 - i))) + if (mask & (1 << 7 - i)) dst[i] = color; - if ((mask & 15) & (1 << (3 - i))) - dst[avctx->width + i] = color; + if (mask & (1 << 3 - i)) + dst[width + i] = color; } } -static void copy_src_mask(AVCodecContext *avctx, uint8_t mask, uint8_t *dst, const uint8_t *src) +static void copy_src_mask(uint8_t *dst, int width, uint8_t mask, const uint8_t *src) { int i; for (i = 0; i < 4; i++) { - if ((mask >> 4) & (1 << (3 - i))) + if (mask & (1 << 7 - i)) dst[i] = src[i]; - if ((mask & 15) & (1 << (3 - i))) - dst[avctx->width + i] = src[avctx->width + i]; + if (mask & (1 << 3 - i)) + dst[width + i] = src[width + i]; } } -static int decode_0(AVCodecContext *avctx, uint8_t code, uint8_t *pkt) +static void set_src_position(PAFVideoDecContext *c, + const uint8_t **p, + const uint8_t **pend) +{ + int val = bytestream2_get_be16(&c->gb); + int page = val >> 14; + int x = (val & 0x7F); + int y = ((val >> 7) & 0x7F); + + *p = c->frame[page] + x * 2 + y * 2 * c->width; + *pend = c->frame[page] + c->frame_size; +} + +static int decode_0(PAFVideoDecContext *c, uint8_t *pkt, uint8_t code) { - PAFVideoDecContext *c = avctx->priv_data; uint32_t opcode_size, offset; - uint8_t *dst, *dend, mask = 0, color = 0, a, b, p; + uint8_t *dst, *dend, mask = 0, color = 0; const uint8_t *src, *send, *opcodes; - int i, j, x = 0; + int i, j, op = 0; i = bytestream2_get_byte(&c->gb); if (i) { @@ -164,21 +173,22 @@ static int decode_0(AVCodecContext *avctx, uint8_t code, uint8_t *pkt) bytestream2_skip(&c->gb, 4 - align); } do { - a = bytestream2_get_byte(&c->gb); - b = bytestream2_get_byte(&c->gb); - p = (a & 0xC0) >> 6; - dst = c->frame[p] + get_video_page_offset(avctx, a, b); - dend = c->frame[p] + c->frame_size; - offset = (b & 0x7F) * 2; + int page, val, x, y; + val = bytestream2_get_be16(&c->gb); + page = val >> 14; + x = (val & 0x7F) * 2; + y = ((val >> 7) & 0x7F) * 2; + dst = c->frame[page] + x + y * c->width; + dend = c->frame[page] + c->frame_size; + offset = (x & 0x7F) * 2; j = bytestream2_get_le16(&c->gb) + offset; - do { offset++; - if (dst + 3 * avctx->width + 4 > dend) + if (dst + 3 * c->width + 4 > dend) return AVERROR_INVALIDDATA; - copy4h(avctx, dst); + read4x4block(c, dst, c->width); if ((offset & 0x3F) == 0) - dst += avctx->width * 3; + dst += c->width * 3; dst += 4; } while (offset < j); } while (--i); @@ -187,18 +197,14 @@ static int decode_0(AVCodecContext *avctx, uint8_t code, uint8_t *pkt) dst = c->frame[c->current_frame]; dend = c->frame[c->current_frame] + c->frame_size; do { - a = bytestream2_get_byte(&c->gb); - b = bytestream2_get_byte(&c->gb); - p = (a & 0xC0) >> 6; - src = c->frame[p] + get_video_page_offset(avctx, a, b); - send = c->frame[p] + c->frame_size; - if ((src + 3 * avctx->width + 4 > send) || - (dst + 3 * avctx->width + 4 > dend)) + set_src_position(c, &src, &send); + if ((src + 3 * c->width + 4 > send) || + (dst + 3 * c->width + 4 > dend)) return AVERROR_INVALIDDATA; - copy_block4(dst, src, avctx->width, avctx->width, 4); + copy_block4(dst, src, c->width, c->width, 4); i++; if ((i & 0x3F) == 0) - dst += avctx->width * 3; + dst += c->width * 3; dst += 4; } while (i < c->video_size / 16); @@ -213,60 +219,53 @@ static int decode_0(AVCodecContext *avctx, uint8_t code, uint8_t *pkt) dst = c->frame[c->current_frame]; - for (i = 0; i < avctx->height; i += 4, dst += avctx->width * 3) { - for (j = 0; j < avctx->width; j += 4, dst += 4) { + for (i = 0; i < c->height; i += 4, dst += c->width * 3) + for (j = 0; j < c->width; j += 4, dst += 4) { int opcode, k = 0; - - if (x > opcode_size) + if (op > opcode_size) return AVERROR_INVALIDDATA; if (j & 4) { - opcode = opcodes[x] & 15; - x++; + opcode = opcodes[op] & 15; + op++; } else { - opcode = opcodes[x] >> 4; + opcode = opcodes[op] >> 4; } while (block_sequences[opcode][k]) { - - offset = avctx->width * 2; + offset = c->width * 2; code = block_sequences[opcode][k++]; switch (code) { case 2: offset = 0; case 3: - color = bytestream2_get_byte(&c->gb); + color = bytestream2_get_byte(&c->gb); case 4: - mask = bytestream2_get_byte(&c->gb); - copy_color_mask(avctx, mask, dst + offset, color); + mask = bytestream2_get_byte(&c->gb); + copy_color_mask(dst + offset, c->width, mask, color); break; case 5: offset = 0; case 6: - a = bytestream2_get_byte(&c->gb); - b = bytestream2_get_byte(&c->gb); - p = (a & 0xC0) >> 6; - src = c->frame[p] + get_video_page_offset(avctx, a, b); - send = c->frame[p] + c->frame_size; + set_src_position(c, &src, &send); case 7: - if (src + offset + avctx->width + 4 > send) + if (src + offset + c->width + 4 > send) return AVERROR_INVALIDDATA; mask = bytestream2_get_byte(&c->gb); - copy_src_mask(avctx, mask, dst + offset, src + offset); + copy_src_mask(dst + offset, c->width, mask, src + offset); break; } } } - } return 0; } -static int paf_vid_decode(AVCodecContext *avctx, void *data, - int *got_frame, AVPacket *pkt) +static int paf_video_decode(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *pkt) { PAFVideoDecContext *c = avctx->priv_data; - uint8_t code, *dst, *src, *end; + uint8_t code, *dst, *end; int i, frame, ret; if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) @@ -275,12 +274,12 @@ static int paf_vid_decode(AVCodecContext *avctx, void *data, bytestream2_init(&c->gb, pkt->data, pkt->size); code = bytestream2_get_byte(&c->gb); - if (code & 0x20) { + if (code & 0x20) { // frame is keyframe for (i = 0; i < 4; i++) memset(c->frame[i], 0, c->frame_size); memset(c->pic->data[1], 0, AVPALETTE_SIZE); - c->current_frame = 0; + c->current_frame = 0; c->pic->key_frame = 1; c->pic->pict_type = AV_PICTURE_TYPE_I; } else { @@ -288,7 +287,7 @@ static int paf_vid_decode(AVCodecContext *avctx, void *data, c->pic->pict_type = AV_PICTURE_TYPE_P; } - if (code & 0x40) { + if (code & 0x40) { // palette update uint32_t *out = (uint32_t *)c->pic->data[1]; int index, count; @@ -297,7 +296,7 @@ static int paf_vid_decode(AVCodecContext *avctx, void *data, if (index + count > 256) return AVERROR_INVALIDDATA; - if (bytestream2_get_bytes_left(&c->gb) < 3*count) + if (bytestream2_get_bytes_left(&c->gb) < 3 * count) return AVERROR_INVALIDDATA; out += index; @@ -310,24 +309,32 @@ static int paf_vid_decode(AVCodecContext *avctx, void *data, g = g << 2 | g >> 4; b = bytestream2_get_byteu(&c->gb); b = b << 2 | b >> 4; - *out++ = 0xFFU << 24 | r << 16 | g << 8 | b; + *out++ = (0xFFU << 24) | (r << 16) | (g << 8) | b; } c->pic->palette_has_changed = 1; } switch (code & 0x0F) { case 0: - if ((ret = decode_0(avctx, code, pkt->data)) < 0) + /* Block-based motion compensation using 4x4 blocks with either + * horizontal or vertical vectors; might incorporate VQ as well. */ + if ((ret = decode_0(c, pkt->data, code)) < 0) return ret; break; case 1: + /* Uncompressed data. This mode specifies that (width * height) bytes + * should be copied directly from the encoded buffer into the output. */ dst = c->frame[c->current_frame]; + // possibly chunk length data bytestream2_skip(&c->gb, 2); if (bytestream2_get_bytes_left(&c->gb) < c->video_size) return AVERROR_INVALIDDATA; bytestream2_get_bufferu(&c->gb, dst, c->video_size); break; case 2: + /* Copy reference frame: Consume the next byte in the stream as the + * reference frame (which should be 0, 1, 2, or 3, and should not be + * the same as the current frame number). */ frame = bytestream2_get_byte(&c->gb); if (frame > 3) return AVERROR_INVALIDDATA; @@ -335,6 +342,7 @@ static int paf_vid_decode(AVCodecContext *avctx, void *data, memcpy(c->frame[c->current_frame], c->frame[frame], c->frame_size); break; case 4: + /* Run length encoding.*/ dst = c->frame[c->current_frame]; end = dst + c->video_size; @@ -364,66 +372,15 @@ static int paf_vid_decode(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } - dst = c->pic->data[0]; - src = c->frame[c->current_frame]; - for (i = 0; i < avctx->height; i++) { - memcpy(dst, src, avctx->width); - dst += c->pic->linesize[0]; - src += avctx->width; - } + av_image_copy_plane(c->pic->data[0], c->pic->linesize[0], + c->frame[c->current_frame], c->width, + c->width, c->height); c->current_frame = (c->current_frame + 1) & 3; if ((ret = av_frame_ref(data, c->pic)) < 0) return ret; - *got_frame = 1; - - return pkt->size; -} - -static av_cold int paf_aud_init(AVCodecContext *avctx) -{ - if (avctx->channels != 2) { - av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); - return AVERROR_INVALIDDATA; - } - - avctx->channel_layout = AV_CH_LAYOUT_STEREO; - avctx->sample_fmt = AV_SAMPLE_FMT_S16; - - return 0; -} - -static int paf_aud_decode(AVCodecContext *avctx, void *data, - int *got_frame_ptr, AVPacket *pkt) -{ - AVFrame *frame = data; - uint8_t *buf = pkt->data; - int16_t *output_samples; - const uint8_t *t; - int frames, ret, i, j, k; - - frames = pkt->size / PAF_SOUND_FRAME_SIZE; - if (frames < 1) - return AVERROR_INVALIDDATA; - - frame->nb_samples = PAF_SOUND_SAMPLES * frames; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; - - output_samples = (int16_t *)frame->data[0]; - for (i = 0; i < frames; i++) { - t = buf + 256 * sizeof(uint16_t); - for (j = 0; j < PAF_SOUND_SAMPLES; j++) { - for (k = 0; k < 2; k++) { - *output_samples++ = AV_RL16(buf + *t * 2); - t++; - } - } - buf += PAF_SOUND_FRAME_SIZE; - } - - *got_frame_ptr = 1; + *got_frame = 1; return pkt->size; } @@ -434,18 +391,8 @@ AVCodec ff_paf_video_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PAF_VIDEO, .priv_data_size = sizeof(PAFVideoDecContext), - .init = paf_vid_init, - .close = paf_vid_close, - .decode = paf_vid_decode, - .capabilities = CODEC_CAP_DR1, -}; - -AVCodec ff_paf_audio_decoder = { - .name = "paf_audio", - .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_PAF_AUDIO, - .init = paf_aud_init, - .decode = paf_aud_decode, + .init = paf_video_init, + .close = paf_video_close, + .decode = paf_video_decode, .capabilities = CODEC_CAP_DR1, }; diff --git a/libavcodec/pel_template.c b/libavcodec/pel_template.c new file mode 100644 index 000000000..6da7a56b2 --- /dev/null +++ b/libavcodec/pel_template.c @@ -0,0 +1,80 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/intreadwrite.h" +#include "pixels.h" +#include "rnd_avg.h" + +#include "bit_depth_template.c" + +#define DEF_PEL(OPNAME, OP) \ +static inline void FUNCC(OPNAME ## _pixels2)(uint8_t *block, \ + const uint8_t *pixels, \ + ptrdiff_t line_size, \ + int h) \ +{ \ + int i; \ + for (i = 0; i < h; i++) { \ + OP(*((pixel2 *) block), AV_RN2P(pixels)); \ + pixels += line_size; \ + block += line_size; \ + } \ +} \ + \ +static inline void FUNCC(OPNAME ## _pixels4)(uint8_t *block, \ + const uint8_t *pixels, \ + ptrdiff_t line_size, \ + int h) \ +{ \ + int i; \ + for (i = 0; i < h; i++) { \ + OP(*((pixel4 *) block), AV_RN4P(pixels)); \ + pixels += line_size; \ + block += line_size; \ + } \ +} \ + \ +static inline void FUNCC(OPNAME ## _pixels8)(uint8_t *block, \ + const uint8_t *pixels, \ + ptrdiff_t line_size, \ + int h) \ +{ \ + int i; \ + for (i = 0; i < h; i++) { \ + OP(*((pixel4 *) block), AV_RN4P(pixels)); \ + OP(*((pixel4 *) (block + 4 * sizeof(pixel))), \ + AV_RN4P(pixels + 4 * sizeof(pixel))); \ + pixels += line_size; \ + block += line_size; \ + } \ +} \ + \ +CALL_2X_PIXELS(FUNCC(OPNAME ## _pixels16), \ + FUNCC(OPNAME ## _pixels8), \ + 8 * sizeof(pixel)) + +#define op_avg(a, b) a = rnd_avg_pixel4(a, b) +#define op_put(a, b) a = b + +DEF_PEL(avg, op_avg) +DEF_PEL(put, op_put) +#undef op_avg +#undef op_put diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c index 71c367ce6..c6331692a 100644 --- a/libavcodec/pgssubdec.c +++ b/libavcodec/pgssubdec.c @@ -25,54 +25,115 @@ */ #include "avcodec.h" -#include "dsputil.h" #include "bytestream.h" #include "internal.h" +#include "mathops.h" #include "libavutil/colorspace.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" #define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) +#define MAX_EPOCH_PALETTES 8 // Max 8 allowed per PGS epoch +#define MAX_EPOCH_OBJECTS 64 // Max 64 allowed per PGS epoch +#define MAX_OBJECT_REFS 2 // Max objects per display set enum SegmentType { PALETTE_SEGMENT = 0x14, - PICTURE_SEGMENT = 0x15, + OBJECT_SEGMENT = 0x15, PRESENTATION_SEGMENT = 0x16, WINDOW_SEGMENT = 0x17, DISPLAY_SEGMENT = 0x80, }; -typedef struct PGSSubPictureReference { - int x; - int y; - int picture_id; - int composition; -} PGSSubPictureReference; +typedef struct PGSSubObjectRef { + int id; + int window_id; + uint8_t composition_flag; + int x; + int y; + int crop_x; + int crop_y; + int crop_w; + int crop_h; +} PGSSubObjectRef; typedef struct PGSSubPresentation { - int id_number; - int object_count; - PGSSubPictureReference *objects; + int id_number; + int palette_id; + int object_count; + PGSSubObjectRef objects[MAX_OBJECT_REFS]; int64_t pts; } PGSSubPresentation; -typedef struct PGSSubPicture { +typedef struct PGSSubObject { + int id; int w; int h; uint8_t *rle; unsigned int rle_buffer_size, rle_data_len; unsigned int rle_remaining_len; -} PGSSubPicture; +} PGSSubObject; + +typedef struct PGSSubObjects { + int count; + PGSSubObject object[MAX_EPOCH_OBJECTS]; +} PGSSubObjects; + +typedef struct PGSSubPalette { + int id; + uint32_t clut[256]; +} PGSSubPalette; + +typedef struct PGSSubPalettes { + int count; + PGSSubPalette palette[MAX_EPOCH_PALETTES]; +} PGSSubPalettes; typedef struct PGSSubContext { AVClass *class; PGSSubPresentation presentation; - uint32_t clut[256]; - PGSSubPicture pictures[UINT16_MAX]; + PGSSubPalettes palettes; + PGSSubObjects objects; int forced_subs_only; } PGSSubContext; +static void flush_cache(AVCodecContext *avctx) +{ + PGSSubContext *ctx = avctx->priv_data; + int i; + + for (i = 0; i < ctx->objects.count; i++) { + av_freep(&ctx->objects.object[i].rle); + ctx->objects.object[i].rle_buffer_size = 0; + ctx->objects.object[i].rle_remaining_len = 0; + } + ctx->objects.count = 0; + ctx->palettes.count = 0; +} + +static PGSSubObject * find_object(int id, PGSSubObjects *objects) +{ + int i; + + for (i = 0; i < objects->count; i++) { + if (objects->object[i].id == id) + return &objects->object[i]; + } + return NULL; +} + +static PGSSubPalette * find_palette(int id, PGSSubPalettes *palettes) +{ + int i; + + for (i = 0; i < palettes->count; i++) { + if (palettes->palette[i].id == id) + return &palettes->palette[i]; + } + return NULL; +} + static av_cold int init_decoder(AVCodecContext *avctx) { avctx->pix_fmt = AV_PIX_FMT_PAL8; @@ -82,17 +143,7 @@ static av_cold int init_decoder(AVCodecContext *avctx) static av_cold int close_decoder(AVCodecContext *avctx) { - uint16_t picture; - - PGSSubContext *ctx = avctx->priv_data; - - av_freep(&ctx->presentation.objects); - ctx->presentation.object_count = 0; - - for (picture = 0; picture < UINT16_MAX; ++picture) { - av_freep(&ctx->pictures[picture].rle); - ctx->pictures[picture].rle_buffer_size = 0; - } + flush_cache(avctx); return 0; } @@ -107,7 +158,7 @@ static av_cold int close_decoder(AVCodecContext *avctx) * @param buf pointer to the RLE data to process * @param buf_size size of the RLE data to process */ -static int decode_rle(AVCodecContext *avctx, AVSubtitle *sub, int rect, +static int decode_rle(AVCodecContext *avctx, AVSubtitleRect *rect, const uint8_t *buf, unsigned int buf_size) { const uint8_t *rle_bitmap_end; @@ -115,15 +166,15 @@ static int decode_rle(AVCodecContext *avctx, AVSubtitle *sub, int rect, rle_bitmap_end = buf + buf_size; - sub->rects[rect]->pict.data[0] = av_malloc(sub->rects[rect]->w * sub->rects[rect]->h); + rect->pict.data[0] = av_malloc(rect->w * rect->h); - if (!sub->rects[rect]->pict.data[0]) - return -1; + if (!rect->pict.data[0]) + return AVERROR(ENOMEM); pixel_count = 0; line_count = 0; - while (buf < rle_bitmap_end && line_count < sub->rects[rect]->h) { + while (buf < rle_bitmap_end && line_count < rect->h) { uint8_t flags, color; int run; @@ -138,27 +189,31 @@ static int decode_rle(AVCodecContext *avctx, AVSubtitle *sub, int rect, color = flags & 0x80 ? bytestream_get_byte(&buf) : 0; } - if (run > 0 && pixel_count + run <= sub->rects[rect]->w * sub->rects[rect]->h) { - memset(sub->rects[rect]->pict.data[0] + pixel_count, color, run); + if (run > 0 && pixel_count + run <= rect->w * rect->h) { + memset(rect->pict.data[0] + pixel_count, color, run); pixel_count += run; } else if (!run) { /* * New Line. Check if correct pixels decoded, if not display warning * and adjust bitmap pointer to correct new line position. */ - if (pixel_count % sub->rects[rect]->w > 0) + if (pixel_count % rect->w > 0) { av_log(avctx, AV_LOG_ERROR, "Decoded %d pixels, when line should be %d pixels\n", - pixel_count % sub->rects[rect]->w, sub->rects[rect]->w); + pixel_count % rect->w, rect->w); + if (avctx->err_recognition & AV_EF_EXPLODE) { + return AVERROR_INVALIDDATA; + } + } line_count++; } } - if (pixel_count < sub->rects[rect]->w * sub->rects[rect]->h) { + if (pixel_count < rect->w * rect->h) { av_log(avctx, AV_LOG_ERROR, "Insufficient RLE data for subtitle\n"); - return -1; + return AVERROR_INVALIDDATA; } - av_dlog(avctx, "Pixel Count = %d, Area = %d\n", pixel_count, sub->rects[rect]->w * sub->rects[rect]->h); + av_dlog(avctx, "Pixel Count = %d, Area = %d\n", pixel_count, rect->w * rect->h); return 0; } @@ -172,43 +227,52 @@ static int decode_rle(AVCodecContext *avctx, AVSubtitle *sub, int rect, * @param avctx contains the current codec context * @param buf pointer to the packet to process * @param buf_size size of packet to process - * @todo TODO: Enable support for RLE data over multiple packets */ -static int parse_picture_segment(AVCodecContext *avctx, +static int parse_object_segment(AVCodecContext *avctx, const uint8_t *buf, int buf_size) { PGSSubContext *ctx = avctx->priv_data; + PGSSubObject *object; uint8_t sequence_desc; unsigned int rle_bitmap_len, width, height; - uint16_t picture_id; + int id; if (buf_size <= 4) - return -1; + return AVERROR_INVALIDDATA; buf_size -= 4; - picture_id = bytestream_get_be16(&buf); + id = bytestream_get_be16(&buf); + object = find_object(id, &ctx->objects); + if (!object) { + if (ctx->objects.count >= MAX_EPOCH_OBJECTS) { + av_log(avctx, AV_LOG_ERROR, "Too many objects in epoch\n"); + return AVERROR_INVALIDDATA; + } + object = &ctx->objects.object[ctx->objects.count++]; + object->id = id; + } - /* skip 1 unknown byte: Version Number */ - buf++; + /* skip object version number */ + buf += 1; /* Read the Sequence Description to determine if start of RLE data or appended to previous RLE */ sequence_desc = bytestream_get_byte(&buf); if (!(sequence_desc & 0x80)) { /* Additional RLE data */ - if (buf_size > ctx->pictures[picture_id].rle_remaining_len) - return -1; + if (buf_size > object->rle_remaining_len) + return AVERROR_INVALIDDATA; - memcpy(ctx->pictures[picture_id].rle + ctx->pictures[picture_id].rle_data_len, buf, buf_size); - ctx->pictures[picture_id].rle_data_len += buf_size; - ctx->pictures[picture_id].rle_remaining_len -= buf_size; + memcpy(object->rle + object->rle_data_len, buf, buf_size); + object->rle_data_len += buf_size; + object->rle_remaining_len -= buf_size; return 0; } if (buf_size <= 7) - return -1; + return AVERROR_INVALIDDATA; buf_size -= 7; /* Decode rle bitmap length, stored size includes width/height data */ @@ -221,7 +285,7 @@ static int parse_picture_segment(AVCodecContext *avctx, /* Make sure the bitmap is not too large */ if (avctx->width < width || avctx->height < height) { av_log(avctx, AV_LOG_ERROR, "Bitmap dimensions larger than video.\n"); - return -1; + return AVERROR_INVALIDDATA; } if (buf_size > rle_bitmap_len) { @@ -229,17 +293,17 @@ static int parse_picture_segment(AVCodecContext *avctx, return AVERROR_INVALIDDATA; } - ctx->pictures[picture_id].w = width; - ctx->pictures[picture_id].h = height; + object->w = width; + object->h = height; - av_fast_padded_malloc(&ctx->pictures[picture_id].rle, &ctx->pictures[picture_id].rle_buffer_size, rle_bitmap_len); + av_fast_padded_malloc(&object->rle, &object->rle_buffer_size, rle_bitmap_len); - if (!ctx->pictures[picture_id].rle) - return -1; + if (!object->rle) + return AVERROR(ENOMEM); - memcpy(ctx->pictures[picture_id].rle, buf, buf_size); - ctx->pictures[picture_id].rle_data_len = buf_size; - ctx->pictures[picture_id].rle_remaining_len = rle_bitmap_len - buf_size; + memcpy(object->rle, buf, buf_size); + object->rle_data_len = buf_size; + object->rle_remaining_len = rle_bitmap_len - buf_size; return 0; } @@ -254,19 +318,32 @@ static int parse_picture_segment(AVCodecContext *avctx, * @param buf pointer to the packet to process * @param buf_size size of packet to process */ -static void parse_palette_segment(AVCodecContext *avctx, +static int parse_palette_segment(AVCodecContext *avctx, const uint8_t *buf, int buf_size) { PGSSubContext *ctx = avctx->priv_data; + PGSSubPalette *palette; const uint8_t *buf_end = buf + buf_size; - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; int color_id; int y, cb, cr, alpha; int r, g, b, r_add, g_add, b_add; + int id; - /* Skip two null bytes */ - buf += 2; + id = bytestream_get_byte(&buf); + palette = find_palette(id, &ctx->palettes); + if (!palette) { + if (ctx->palettes.count >= MAX_EPOCH_PALETTES) { + av_log(avctx, AV_LOG_ERROR, "Too many palettes in epoch\n"); + return AVERROR_INVALIDDATA; + } + palette = &ctx->palettes.palette[ctx->palettes.count++]; + palette->id = id; + } + + /* Skip palette version */ + buf += 1; while (buf < buf_end) { color_id = bytestream_get_byte(&buf); @@ -281,8 +358,9 @@ static void parse_palette_segment(AVCodecContext *avctx, av_dlog(avctx, "Color %d := (%d,%d,%d,%d)\n", color_id, r, g, b, alpha); /* Store color in palette */ - ctx->clut[color_id] = RGBA(r,g,b,alpha); + palette->clut[color_id] = RGBA(r,g,b,alpha); } + return 0; } /** @@ -301,13 +379,13 @@ static int parse_presentation_segment(AVCodecContext *avctx, int64_t pts) { PGSSubContext *ctx = avctx->priv_data; - int ret; + int i, state, ret; + const uint8_t *buf_end = buf + buf_size; + // Video descriptor int w = bytestream_get_be16(&buf); int h = bytestream_get_be16(&buf); - uint16_t object_index; - ctx->presentation.pts = pts; av_dlog(avctx, "Video Dimensions %dx%d\n", @@ -316,57 +394,80 @@ static int parse_presentation_segment(AVCodecContext *avctx, if (ret < 0) return ret; - /* Skip 1 bytes of unknown, frame rate? */ + /* Skip 1 bytes of unknown, frame rate */ buf++; + // Composition descriptor ctx->presentation.id_number = bytestream_get_be16(&buf); + /* + * state is a 2 bit field that defines pgs epoch boundaries + * 00 - Normal, previously defined objects and palettes are still valid + * 01 - Acquisition point, previous objects and palettes can be released + * 10 - Epoch start, previous objects and palettes can be released + * 11 - Epoch continue, previous objects and palettes can be released + * + * reserved 6 bits discarded + */ + state = bytestream_get_byte(&buf) >> 6; + if (state != 0) { + flush_cache(avctx); + } /* - * Skip 3 bytes of unknown: - * state - * palette_update_flag (0x80), - * palette_id_to_use, + * skip palette_update_flag (0x80), */ - buf += 3; - + buf += 1; + ctx->presentation.palette_id = bytestream_get_byte(&buf); ctx->presentation.object_count = bytestream_get_byte(&buf); - if (!ctx->presentation.object_count) - return 0; - - /* Verify that enough bytes are remaining for all of the objects. */ - buf_size -= 11; - if (buf_size < ctx->presentation.object_count * 8) { - ctx->presentation.object_count = 0; - return AVERROR_INVALIDDATA; + if (ctx->presentation.object_count > MAX_OBJECT_REFS) { + av_log(avctx, AV_LOG_ERROR, + "Invalid number of presentation objects %d\n", + ctx->presentation.object_count); + ctx->presentation.object_count = 2; + if (avctx->err_recognition & AV_EF_EXPLODE) { + return AVERROR_INVALIDDATA; + } } - av_freep(&ctx->presentation.objects); - ctx->presentation.objects = av_malloc(sizeof(PGSSubPictureReference) * ctx->presentation.object_count); - if (!ctx->presentation.objects) { - ctx->presentation.object_count = 0; - return AVERROR(ENOMEM); - } - for (object_index = 0; object_index < ctx->presentation.object_count; ++object_index) { - PGSSubPictureReference *reference = &ctx->presentation.objects[object_index]; - reference->picture_id = bytestream_get_be16(&buf); + for (i = 0; i < ctx->presentation.object_count; i++) + { - /* Skip window_id_ref */ - buf++; - /* composition_flag (0x80 - object cropped, 0x40 - object forced) */ - reference->composition = bytestream_get_byte(&buf); + if (buf_end - buf < 8) { + av_log(avctx, AV_LOG_ERROR, "Insufficent space for object\n"); + ctx->presentation.object_count = i; + return AVERROR_INVALIDDATA; + } - reference->x = bytestream_get_be16(&buf); - reference->y = bytestream_get_be16(&buf); + ctx->presentation.objects[i].id = bytestream_get_be16(&buf); + ctx->presentation.objects[i].window_id = bytestream_get_byte(&buf); + ctx->presentation.objects[i].composition_flag = bytestream_get_byte(&buf); - /* TODO If cropping, cropping_x, cropping_y, cropping_width, cropping_height (all 2 bytes).*/ - av_dlog(avctx, "Subtitle Placement ID=%d, x=%d, y=%d\n", reference->picture_id, reference->x, reference->y); + ctx->presentation.objects[i].x = bytestream_get_be16(&buf); + ctx->presentation.objects[i].y = bytestream_get_be16(&buf); - if (reference->x > avctx->width || reference->y > avctx->height) { + // If cropping + if (ctx->presentation.objects[i].composition_flag & 0x80) { + ctx->presentation.objects[i].crop_x = bytestream_get_be16(&buf); + ctx->presentation.objects[i].crop_y = bytestream_get_be16(&buf); + ctx->presentation.objects[i].crop_w = bytestream_get_be16(&buf); + ctx->presentation.objects[i].crop_h = bytestream_get_be16(&buf); + } + + av_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 || + ctx->presentation.objects[i].y > avctx->height) { av_log(avctx, AV_LOG_ERROR, "Subtitle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n", - reference->x, reference->y, avctx->width, avctx->height); - reference->x = 0; - reference->y = 0; + ctx->presentation.objects[i].x, + ctx->presentation.objects[i].y, + avctx->width, avctx->height); + ctx->presentation.objects[i].x = 0; + ctx->presentation.objects[i].y = 0; + if (avctx->err_recognition & AV_EF_EXPLODE) { + return AVERROR_INVALIDDATA; + } } } @@ -382,11 +483,6 @@ static int parse_presentation_segment(AVCodecContext *avctx, * @param data pointer to the data pertaining the subtitle to display * @param buf pointer to the packet to process * @param buf_size size of packet to process - * @todo TODO: Fix start time, relies on correct PTS, currently too late - * - * @todo TODO: Fix end time, normally cleared by a second display - * @todo segment, which is currently ignored as it clears - * @todo the subtitle too early. */ static int display_end_segment(AVCodecContext *avctx, void *data, const uint8_t *buf, int buf_size) @@ -394,61 +490,102 @@ static int display_end_segment(AVCodecContext *avctx, void *data, AVSubtitle *sub = data; PGSSubContext *ctx = avctx->priv_data; int64_t pts; - - uint16_t rect; - - /* - * The end display time is a timeout value and is only reached - * if the next subtitle is later than timeout or subtitle has - * not been cleared by a subsequent empty display command. - */ + PGSSubPalette *palette; + int i, ret; pts = ctx->presentation.pts != AV_NOPTS_VALUE ? ctx->presentation.pts : sub->pts; memset(sub, 0, sizeof(*sub)); sub->pts = pts; ctx->presentation.pts = AV_NOPTS_VALUE; + sub->start_display_time = 0; + // There is no explicit end time for PGS subtitles. The end time + // is defined by the start of the next sub which may contain no + // objects (i.e. clears the previous sub) + sub->end_display_time = UINT32_MAX; + sub->format = 0; // Blank if last object_count was 0. if (!ctx->presentation.object_count) return 1; + sub->rects = av_mallocz(sizeof(*sub->rects) * ctx->presentation.object_count); + if (!sub->rects) { + return AVERROR(ENOMEM); + } + palette = find_palette(ctx->presentation.palette_id, &ctx->palettes); + if (!palette) { + // Missing palette. Should only happen with damaged streams. + av_log(avctx, AV_LOG_ERROR, "Invalid palette id %d\n", + ctx->presentation.palette_id); + avsubtitle_free(sub); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < ctx->presentation.object_count; i++) { + PGSSubObject *object; - sub->start_display_time = 0; - sub->end_display_time = 20000; - sub->format = 0; - - sub->num_rects = ctx->presentation.object_count; - sub->rects = av_mallocz(sizeof(*sub->rects) * sub->num_rects); - - for (rect = 0; rect < sub->num_rects; ++rect) { - uint16_t picture_id = ctx->presentation.objects[rect].picture_id; - sub->rects[rect] = av_mallocz(sizeof(*sub->rects[rect])); - sub->rects[rect]->x = ctx->presentation.objects[rect].x; - sub->rects[rect]->y = ctx->presentation.objects[rect].y; - sub->rects[rect]->w = ctx->pictures[picture_id].w; - sub->rects[rect]->h = ctx->pictures[picture_id].h; - sub->rects[rect]->type = SUBTITLE_BITMAP; + sub->rects[i] = av_mallocz(sizeof(*sub->rects[0])); + if (!sub->rects[i]) { + avsubtitle_free(sub); + return AVERROR(ENOMEM); + } + sub->num_rects++; + sub->rects[i]->type = SUBTITLE_BITMAP; /* Process bitmap */ - sub->rects[rect]->pict.linesize[0] = ctx->pictures[picture_id].w; - if (ctx->pictures[picture_id].rle) { - if (ctx->pictures[picture_id].rle_remaining_len) + object = find_object(ctx->presentation.objects[i].id, &ctx->objects); + if (!object) { + // Missing object. Should only happen with damaged streams. + av_log(avctx, AV_LOG_ERROR, "Invalid object id %d\n", + ctx->presentation.objects[i].id); + if (avctx->err_recognition & AV_EF_EXPLODE) { + avsubtitle_free(sub); + return AVERROR_INVALIDDATA; + } + // Leaves rect empty with 0 width and height. + continue; + } + if (ctx->presentation.objects[i].composition_flag & 0x40) + sub->rects[i]->flags |= AV_SUBTITLE_FLAG_FORCED; + + sub->rects[i]->x = ctx->presentation.objects[i].x; + sub->rects[i]->y = ctx->presentation.objects[i].y; + sub->rects[i]->w = object->w; + sub->rects[i]->h = object->h; + + sub->rects[i]->pict.linesize[0] = object->w; + + if (object->rle) { + if (object->rle_remaining_len) { av_log(avctx, AV_LOG_ERROR, "RLE data length %u is %u bytes shorter than expected\n", - ctx->pictures[picture_id].rle_data_len, ctx->pictures[picture_id].rle_remaining_len); - if (decode_rle(avctx, sub, rect, ctx->pictures[picture_id].rle, ctx->pictures[picture_id].rle_data_len) < 0) - return 0; + object->rle_data_len, object->rle_remaining_len); + if (avctx->err_recognition & AV_EF_EXPLODE) { + avsubtitle_free(sub); + return AVERROR_INVALIDDATA; + } + } + ret = decode_rle(avctx, sub->rects[i], object->rle, object->rle_data_len); + if (ret < 0) { + if ((avctx->err_recognition & AV_EF_EXPLODE) || + ret == AVERROR(ENOMEM)) { + avsubtitle_free(sub); + return ret; + } + sub->rects[i]->w = 0; + sub->rects[i]->h = 0; + continue; + } + } + /* 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]) { + avsubtitle_free(sub); + return AVERROR(ENOMEM); } - /* Allocate memory for colors */ - sub->rects[rect]->nb_colors = 256; - sub->rects[rect]->pict.data[1] = av_mallocz(AVPALETTE_SIZE); + if (!ctx->forced_subs_only || ctx->presentation.objects[i].composition_flag & 0x40) + memcpy(sub->rects[i]->pict.data[1], palette->clut, sub->rects[i]->nb_colors * sizeof(uint32_t)); - /* Copy the forced flag */ - sub->rects[rect]->flags = (ctx->presentation.objects[rect].composition & 0x40) != 0 ? AV_SUBTITLE_FLAG_FORCED : 0; - - if (!ctx->forced_subs_only || ctx->presentation.objects[rect].composition & 0x40) - memcpy(sub->rects[rect]->pict.data[1], ctx->clut, sub->rects[rect]->nb_colors * sizeof(uint32_t)); } - return 1; } @@ -457,7 +594,6 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size, { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVSubtitle *sub = data; const uint8_t *buf_end; uint8_t segment_type; @@ -493,17 +629,16 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size, if (segment_type != DISPLAY_SEGMENT && segment_length > buf_end - buf) break; + ret = 0; switch (segment_type) { case PALETTE_SEGMENT: - parse_palette_segment(avctx, buf, segment_length); + ret = parse_palette_segment(avctx, buf, segment_length); break; - case PICTURE_SEGMENT: - parse_picture_segment(avctx, buf, segment_length); + case OBJECT_SEGMENT: + ret = parse_object_segment(avctx, buf, segment_length); break; case PRESENTATION_SEGMENT: - ret = parse_presentation_segment(avctx, buf, segment_length, sub->pts); - if (ret < 0) - return ret; + ret = parse_presentation_segment(avctx, buf, segment_length, ((AVSubtitle*)(data))->pts); break; case WINDOW_SEGMENT: /* @@ -516,13 +651,18 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size, */ break; case DISPLAY_SEGMENT: - *data_size = display_end_segment(avctx, data, buf, segment_length); + ret = display_end_segment(avctx, data, buf, segment_length); + if (ret >= 0) + *data_size = ret; break; default: av_log(avctx, AV_LOG_ERROR, "Unknown subtitle segment type 0x%x, length %d\n", segment_type, segment_length); + ret = AVERROR_INVALIDDATA; break; } + if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) + return ret; buf += segment_length; } diff --git a/libavcodec/pixblockdsp.c b/libavcodec/pixblockdsp.c new file mode 100644 index 000000000..ebde68b6a --- /dev/null +++ b/libavcodec/pixblockdsp.c @@ -0,0 +1,82 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "avcodec.h" +#include "pixblockdsp.h" + +#define BIT_DEPTH 16 +#include "pixblockdsp_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 8 +#include "pixblockdsp_template.c" + +static void diff_pixels_c(int16_t *av_restrict block, const uint8_t *s1, + const uint8_t *s2, int stride) +{ + int i; + + /* read the pixels */ + for (i = 0; i < 8; i++) { + block[0] = s1[0] - s2[0]; + block[1] = s1[1] - s2[1]; + block[2] = s1[2] - s2[2]; + block[3] = s1[3] - s2[3]; + block[4] = s1[4] - s2[4]; + block[5] = s1[5] - s2[5]; + block[6] = s1[6] - s2[6]; + block[7] = s1[7] - s2[7]; + s1 += stride; + s2 += stride; + block += 8; + } +} + +av_cold void ff_pixblockdsp_init(PixblockDSPContext *c, AVCodecContext *avctx) +{ + const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; + + c->diff_pixels = diff_pixels_c; + + switch (avctx->bits_per_raw_sample) { + case 9: + case 10: + case 12: + case 14: + c->get_pixels = get_pixels_16_c; + break; + default: + if (avctx->bits_per_raw_sample<=8 || avctx->codec_type != AVMEDIA_TYPE_VIDEO) { + c->get_pixels = get_pixels_8_c; + } + break; + } + + if (ARCH_ALPHA) + ff_pixblockdsp_init_alpha(c, avctx, high_bit_depth); + if (ARCH_ARM) + ff_pixblockdsp_init_arm(c, avctx, high_bit_depth); + if (ARCH_PPC) + ff_pixblockdsp_init_ppc(c, avctx, high_bit_depth); + if (ARCH_X86) + ff_pixblockdsp_init_x86(c, avctx, high_bit_depth); +} diff --git a/libavcodec/pixblockdsp.h b/libavcodec/pixblockdsp.h new file mode 100644 index 000000000..2f94f8bc6 --- /dev/null +++ b/libavcodec/pixblockdsp.h @@ -0,0 +1,46 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_PIXBLOCKDSP_H +#define AVCODEC_PIXBLOCKDSP_H + +#include + +#include "avcodec.h" + +typedef struct PixblockDSPContext { + void (*get_pixels)(int16_t *block /* align 16 */, + const uint8_t *pixels /* align 8 */, + int line_size); + void (*diff_pixels)(int16_t *block /* align 16 */, + const uint8_t *s1 /* align 8 */, + const uint8_t *s2 /* align 8 */, + int stride); +} PixblockDSPContext; + +void ff_pixblockdsp_init(PixblockDSPContext *c, AVCodecContext *avctx); +void ff_pixblockdsp_init_alpha(PixblockDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); +void ff_pixblockdsp_init_arm(PixblockDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); +void ff_pixblockdsp_init_ppc(PixblockDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); +void ff_pixblockdsp_init_x86(PixblockDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); + +#endif /* AVCODEC_PIXBLOCKDSP_H */ diff --git a/libavcodec/pixblockdsp_template.c b/libavcodec/pixblockdsp_template.c new file mode 100644 index 000000000..3aeddf526 --- /dev/null +++ b/libavcodec/pixblockdsp_template.c @@ -0,0 +1,40 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "bit_depth_template.c" + +static void FUNCC(get_pixels)(int16_t *av_restrict block, const uint8_t *_pixels, + int line_size) +{ + const pixel *pixels = (const pixel *) _pixels; + int i; + + /* read the pixels */ + for (i = 0; i < 8; i++) { + block[0] = pixels[0]; + block[1] = pixels[1]; + block[2] = pixels[2]; + block[3] = pixels[3]; + block[4] = pixels[4]; + block[5] = pixels[5]; + block[6] = pixels[6]; + block[7] = pixels[7]; + pixels += line_size / sizeof(pixel); + block += 8; + } +} diff --git a/libavcodec/pixels.h b/libavcodec/pixels.h new file mode 100644 index 000000000..98eacd4df --- /dev/null +++ b/libavcodec/pixels.h @@ -0,0 +1,37 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_PIXELS_H +#define AVCODEC_PIXELS_H + +#include +#include + +/* pixel operations */ +#define CALL_2X_PIXELS_MACRO(STATIC, a, b, n) \ +STATIC void a(uint8_t *block, const uint8_t *pixels, \ + ptrdiff_t line_size, int h) \ +{ \ + b(block, pixels, line_size, h); \ + b(block + n, pixels + n, line_size, h); \ +} + +#define CALL_2X_PIXELS(a, b, n) CALL_2X_PIXELS_MACRO(static, a, b, n) +#define CALL_2X_PIXELS_EXPORT(a, b, n) CALL_2X_PIXELS_MACRO(, a, b, n) + +#endif /* AVCODEC_PIXELS_H */ diff --git a/libavcodec/png.c b/libavcodec/png.c index b398d9100..ef52b51bd 100644 --- a/libavcodec/png.c +++ b/libavcodec/png.c @@ -66,7 +66,7 @@ int ff_png_pass_row_size(int pass, int bits_per_pixel, int width) xmin = ff_png_pass_xmin[pass]; if (width <= xmin) return 0; - shift = ff_png_pass_xshift[pass]; + shift = ff_png_pass_xshift[pass]; pass_width = (width - xmin + (1 << shift) - 1) >> shift; return (pass_width * bits_per_pixel + 7) >> 3; } diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 516dd41f0..c92087f5e 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -85,8 +85,8 @@ static const uint8_t png_pass_dsp_mask[NB_PASSES] = { }; /* NOTE: we try to construct a good looking image at each pass. width - is the original image width. We also do pixel format conversion at - this stage */ + * is the original image width. We also do pixel format conversion at + * this stage */ static void png_put_interlaced_row(uint8_t *dst, int width, int bits_per_pixel, int pass, int color_type, const uint8_t *src) @@ -157,7 +157,8 @@ static void png_put_interlaced_row(uint8_t *dst, int width, } } -void ff_add_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, int w, int bpp) +void ff_add_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, + int w, int bpp) { int i; for (i = 0; i < w; i++) { @@ -184,29 +185,35 @@ void ff_add_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, int w } } -#define UNROLL1(bpp, op) {\ - r = dst[0];\ - if(bpp >= 2) g = dst[1];\ - if(bpp >= 3) b = dst[2];\ - if(bpp >= 4) a = dst[3];\ - for(; i <= size - bpp; i+=bpp) {\ - dst[i+0] = r = op(r, src[i+0], last[i+0]);\ - if(bpp == 1) continue;\ - dst[i+1] = g = op(g, src[i+1], last[i+1]);\ - if(bpp == 2) continue;\ - dst[i+2] = b = op(b, src[i+2], last[i+2]);\ - if(bpp == 3) continue;\ - dst[i+3] = a = op(a, src[i+3], last[i+3]);\ - }\ +#define UNROLL1(bpp, op) { \ + r = dst[0]; \ + if (bpp >= 2) \ + g = dst[1]; \ + if (bpp >= 3) \ + b = dst[2]; \ + if (bpp >= 4) \ + a = dst[3]; \ + for (; i <= size - bpp; i += bpp) { \ + dst[i + 0] = r = op(r, src[i + 0], last[i + 0]); \ + if (bpp == 1) \ + continue; \ + dst[i + 1] = g = op(g, src[i + 1], last[i + 1]); \ + if (bpp == 2) \ + continue; \ + dst[i + 2] = b = op(b, src[i + 2], last[i + 2]); \ + if (bpp == 3) \ + continue; \ + dst[i + 3] = a = op(a, src[i + 3], last[i + 3]); \ + } \ } #define UNROLL_FILTER(op)\ - if(bpp == 1) UNROLL1(1, op)\ - else if(bpp == 2) UNROLL1(2, op)\ - else if(bpp == 3) UNROLL1(3, op)\ - else if(bpp == 4) UNROLL1(4, op)\ + if (bpp == 1) UNROLL1(1, op)\ + else if (bpp == 2) UNROLL1(2, op)\ + else if (bpp == 3) UNROLL1(3, op)\ + else if (bpp == 4) UNROLL1(4, op)\ for (; i < size; i++) {\ - dst[i] = op(dst[i-bpp], src[i], last[i]);\ + dst[i] = op(dst[i - bpp], src[i], last[i]);\ }\ /* NOTE: 'dst' can be equal to 'last' */ @@ -220,18 +227,17 @@ static void png_filter_row(PNGDSPContext *dsp, uint8_t *dst, int filter_type, memcpy(dst, src, size); break; case PNG_FILTER_VALUE_SUB: - for (i = 0; i < bpp; i++) { + for (i = 0; i < bpp; i++) dst[i] = src[i]; - } if (bpp == 4) { - p = *(int*)dst; + p = *(int *)dst; for (; i < size; i += bpp) { - unsigned s = *(int*)(src + i); + unsigned s = *(int *)(src + i); p = ((s & 0x7f7f7f7f) + (p & 0x7f7f7f7f)) ^ ((s ^ p) & 0x80808080); - *(int*)(dst + i) = p; + *(int *)(dst + i) = p; } } else { -#define OP_SUB(x,s,l) x+s +#define OP_SUB(x, s, l) ((x) + (s)) UNROLL_FILTER(OP_SUB); } break; @@ -240,19 +246,20 @@ static void png_filter_row(PNGDSPContext *dsp, uint8_t *dst, int filter_type, break; case PNG_FILTER_VALUE_AVG: for (i = 0; i < bpp; i++) { - p = (last[i] >> 1); + p = (last[i] >> 1); dst[i] = p + src[i]; } -#define OP_AVG(x,s,l) (((x + l) >> 1) + s) & 0xff +#define OP_AVG(x, s, l) (((((x) + (l)) >> 1) + (s)) & 0xff) UNROLL_FILTER(OP_AVG); break; case PNG_FILTER_VALUE_PAETH: for (i = 0; i < bpp; i++) { - p = last[i]; + p = last[i]; dst[i] = p + src[i]; } if (bpp > 2 && size > 4) { - // would write off the end of the array if we let it process the last pixel with bpp=3 + /* would write off the end of the array if we let it process + * the last pixel with bpp=3 */ int w = bpp == 4 ? size : size - 3; dsp->add_paeth_prediction(dst + i, src + i, last + i, w - i, bpp); i = w; @@ -269,9 +276,9 @@ static void deloco_ ## NAME(TYPE *dst, int size, int alpha) \ { \ int i; \ for (i = 0; i < size; i += 3 + alpha) { \ - int g = dst [i+1]; \ - dst[i+0] += g; \ - dst[i+2] += g; \ + int g = dst [i + 1]; \ + dst[i + 0] += g; \ + dst[i + 2] += g; \ } \ } @@ -322,12 +329,12 @@ static void png_handle_row(PNGDecContext *s) ptr = s->image_buf + s->image_linesize * s->y; if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) { /* if we already read one row, it is time to stop to - wait for the next one */ + * wait for the next one */ if (got_line) break; png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1, s->last_row, s->pass_row_size, s->bpp); - FFSWAP(uint8_t*, s->last_row, s->tmp_row); + FFSWAP(uint8_t *, s->last_row, s->tmp_row); FFSWAP(unsigned int, s->last_row_size, s->tmp_row_size); got_line = 1; } @@ -346,8 +353,8 @@ static void png_handle_row(PNGDecContext *s) s->pass++; s->y = 0; s->pass_row_size = ff_png_pass_row_size(s->pass, - s->bits_per_pixel, - s->width); + s->bits_per_pixel, + s->width); s->crow_size = s->pass_row_size + 1; if (s->pass_row_size != 0) break; @@ -356,7 +363,7 @@ static void png_handle_row(PNGDecContext *s) } } } - the_end: ; +the_end:; } } @@ -382,7 +389,8 @@ static int png_decode_idat(PNGDecContext *s, int length) s->zstream.next_out = s->crow_buf; } if (ret == Z_STREAM_END && s->zstream.avail_in > 0) { - av_log(NULL, AV_LOG_WARNING, "%d undecompressed bytes left in buffer\n", s->zstream.avail_in); + av_log(NULL, AV_LOG_WARNING, + "%d undecompressed bytes left in buffer\n", s->zstream.avail_in); return 0; } } @@ -509,9 +517,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { - PNGDecContext * const s = avctx->priv_data; - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; + PNGDecContext *const s = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; AVFrame *p; AVDictionary *metadata = NULL; uint32_t tag, length; @@ -546,6 +554,9 @@ static int decode_frame(AVCodecContext *avctx, for (;;) { if (bytestream2_get_bytes_left(&s->gb) <= 0) { av_log(avctx, AV_LOG_ERROR, "No bytes left\n"); + if ( s->state & PNG_ALLIMAGE + && avctx->strict_std_compliance <= FF_COMPLIANCE_NORMAL) + goto exit_loop; goto fail; } @@ -581,7 +592,7 @@ static int decode_frame(AVCodecContext *avctx, s->state |= PNG_IHDR; if (avctx->debug & FF_DEBUG_PICT_INFO) av_log(avctx, AV_LOG_DEBUG, "width=%d height=%d depth=%d color_type=%d " - "compression_type=%d filter_type=%d interlace_type=%d\n", + "compression_type=%d filter_type=%d interlace_type=%d\n", s->width, s->height, s->bit_depth, s->color_type, s->compression_type, s->filter_type, s->interlace_type); break; @@ -657,10 +668,10 @@ static int decode_frame(AVCodecContext *avctx, if (!s->interlace_type) { s->crow_size = s->row_size + 1; } else { - s->pass = 0; + s->pass = 0; s->pass_row_size = ff_png_pass_row_size(s->pass, - s->bits_per_pixel, - s->width); + s->bits_per_pixel, + s->width); s->crow_size = s->pass_row_size + 1; } av_dlog(avctx, "row_size=%d crow_size =%d\n", @@ -696,42 +707,41 @@ static int decode_frame(AVCodecContext *avctx, bytestream2_skip(&s->gb, 4); /* crc */ break; case MKTAG('P', 'L', 'T', 'E'): - { - int n, i, r, g, b; + { + int n, i, r, g, b; - if ((length % 3) != 0 || length > 256 * 3) - goto skip_tag; - /* read the palette */ - n = length / 3; - for (i = 0; i < n; i++) { - r = bytestream2_get_byte(&s->gb); - g = bytestream2_get_byte(&s->gb); - b = bytestream2_get_byte(&s->gb); - s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | b; - } - for (; i < 256; i++) { - s->palette[i] = (0xFFU << 24); - } - s->state |= PNG_PLTE; - bytestream2_skip(&s->gb, 4); /* crc */ + if ((length % 3) != 0 || length > 256 * 3) + goto skip_tag; + /* read the palette */ + n = length / 3; + for (i = 0; i < n; i++) { + r = bytestream2_get_byte(&s->gb); + g = bytestream2_get_byte(&s->gb); + b = bytestream2_get_byte(&s->gb); + s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | b; } - break; + for (; i < 256; i++) + s->palette[i] = (0xFFU << 24); + s->state |= PNG_PLTE; + bytestream2_skip(&s->gb, 4); /* crc */ + } + break; case MKTAG('t', 'R', 'N', 'S'): - { - int v, i; + { + int v, i; - /* read the transparency. XXX: Only palette mode supported */ - if (s->color_type != PNG_COLOR_TYPE_PALETTE || - length > 256 || - !(s->state & PNG_PLTE)) - goto skip_tag; - for (i = 0; i < length; i++) { - v = bytestream2_get_byte(&s->gb); - s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24); - } - bytestream2_skip(&s->gb, 4); /* crc */ + /* read the transparency. XXX: Only palette mode supported */ + if (s->color_type != PNG_COLOR_TYPE_PALETTE || + length > 256 || + !(s->state & PNG_PLTE)) + goto skip_tag; + for (i = 0; i < length; i++) { + v = bytestream2_get_byte(&s->gb); + s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24); } - break; + bytestream2_skip(&s->gb, 4); /* crc */ + } + break; case MKTAG('t', 'E', 'X', 't'): if (decode_text_chunk(s, length, 0, &metadata) < 0) av_log(avctx, AV_LOG_WARNING, "Broken tEXt chunk\n"); @@ -752,12 +762,12 @@ static int decode_frame(AVCodecContext *avctx, goto exit_loop; default: /* skip tag */ - skip_tag: +skip_tag: bytestream2_skip(&s->gb, length + 4); break; } } - exit_loop: +exit_loop: if (s->bits_per_pixel == 1 && s->color_type == PNG_COLOR_TYPE_PALETTE){ int i, j, k; @@ -831,9 +841,9 @@ static int decode_frame(AVCodecContext *avctx, } } - /* handle p-frames only if a predecessor frame is available */ - if (s->last_picture.f->data[0]) { - if ( !(avpkt->flags & AV_PKT_FLAG_KEY) && avctx->codec_tag != AV_RL32("MPNG") + /* handle p-frames only if a predecessor frame is available */ + if (s->last_picture.f->data[0]) { + if ( !(avpkt->flags & AV_PKT_FLAG_KEY) && avctx->codec_tag != AV_RL32("MPNG") && s->last_picture.f->width == p->width && s->last_picture.f->height== p->height && s->last_picture.f->format== p->format @@ -844,9 +854,8 @@ static int decode_frame(AVCodecContext *avctx, ff_thread_await_progress(&s->last_picture, INT_MAX, 0); for (j = 0; j < s->height; j++) { - for (i = 0; i < s->width * s->bpp; i++) { + for (i = 0; i < s->width * s->bpp; i++) pd[i] += pd_last[i]; - } pd += s->image_linesize; pd_last += s->image_linesize; } @@ -863,11 +872,11 @@ static int decode_frame(AVCodecContext *avctx, *got_frame = 1; ret = bytestream2_tell(&s->gb); - the_end: +the_end: inflateEnd(&s->zstream); s->crow_buf = NULL; return ret; - fail: +fail: av_dict_free(&metadata); ff_thread_report_progress(&s->picture, INT_MAX, 0); ret = AVERROR_INVALIDDATA; diff --git a/libavcodec/pngdsp.c b/libavcodec/pngdsp.c index 5ab1c351b..d2753163d 100644 --- a/libavcodec/pngdsp.c +++ b/libavcodec/pngdsp.c @@ -25,13 +25,13 @@ #include "pngdsp.h" // 0x7f7f7f7f or 0x7f7f7f7f7f7f7f7f or whatever, depending on the cpu's native arithmetic size -#define pb_7f (~0UL/255 * 0x7f) -#define pb_80 (~0UL/255 * 0x80) +#define pb_7f (~0UL / 255 * 0x7f) +#define pb_80 (~0UL / 255 * 0x80) static void add_bytes_l2_c(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w) { long i; - for (i = 0; i <= w - (int)sizeof(long); i += sizeof(long)) { + for (i = 0; i <= w - (int) sizeof(long); i += sizeof(long)) { long a = *(long *)(src1 + i); long b = *(long *)(src2 + i); *(long *)(dst + i) = ((a & pb_7f) + (b & pb_7f)) ^ ((a ^ b) & pb_80); @@ -45,5 +45,6 @@ av_cold void ff_pngdsp_init(PNGDSPContext *dsp) dsp->add_bytes_l2 = add_bytes_l2_c; dsp->add_paeth_prediction = ff_add_png_paeth_prediction; - if (ARCH_X86) ff_pngdsp_init_x86(dsp); + if (ARCH_X86) + ff_pngdsp_init_x86(dsp); } diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 35a95921a..0d2c291a8 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -18,10 +18,11 @@ * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + #include "avcodec.h" #include "internal.h" #include "bytestream.h" -#include "dsputil.h" +#include "huffyuvencdsp.h" #include "png.h" #include "libavutil/avassert.h" @@ -33,7 +34,7 @@ typedef struct PNGEncContext { AVClass *class; - DSPContext dsp; + HuffYUVEncDSPContext hdsp; uint8_t *bytestream; uint8_t *bytestream_start; @@ -57,11 +58,11 @@ static void png_get_interlaced_row(uint8_t *dst, int row_size, static const int masks[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; mask = masks[pass]; - switch(bits_per_pixel) { + switch (bits_per_pixel) { case 1: memset(dst, 0, row_size); dst_x = 0; - for(x = 0; x < width; x++) { + for (x = 0; x < width; x++) { j = (x & 7); if ((mask << j) & 0x80) { b = (src[x >> 3] >> (7 - j)) & 1; @@ -74,7 +75,7 @@ static void png_get_interlaced_row(uint8_t *dst, int row_size, bpp = bits_per_pixel >> 3; d = dst; s = src; - for(x = 0; x < width; x++) { + for (x = 0; x < width; x++) { j = x & 7; if ((mask << j) & 0x80) { memcpy(d, s, bpp); @@ -86,17 +87,18 @@ static void png_get_interlaced_row(uint8_t *dst, int row_size, } } -static void sub_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, int w, int bpp) +static void sub_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, + int w, int bpp) { int i; - for(i = 0; i < w; i++) { + for (i = 0; i < w; i++) { int a, b, c, p, pa, pb, pc; a = src[i - bpp]; b = top[i]; c = top[i - bpp]; - p = b - c; + p = b - c; pc = a - c; pa = abs(p); @@ -113,7 +115,7 @@ static void sub_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, i } } -static void sub_left_prediction(DSPContext *dsp, uint8_t *dst, const uint8_t *src, int bpp, int size) +static void sub_left_prediction(PNGEncContext *c, uint8_t *dst, const uint8_t *src, int bpp, int size) { const uint8_t *src1 = src + bpp; const uint8_t *src2 = src; @@ -126,34 +128,34 @@ static void sub_left_prediction(DSPContext *dsp, uint8_t *dst, const uint8_t *sr for (x = 0; x < unaligned_w; x++) *dst++ = *src1++ - *src2++; size -= unaligned_w; - dsp->diff_bytes(dst, src1, src2, size); + c->hdsp.diff_bytes(dst, src1, src2, size); } -static void png_filter_row(DSPContext *dsp, uint8_t *dst, int filter_type, +static void png_filter_row(PNGEncContext *c, uint8_t *dst, int filter_type, uint8_t *src, uint8_t *top, int size, int bpp) { int i; - switch(filter_type) { + switch (filter_type) { case PNG_FILTER_VALUE_NONE: memcpy(dst, src, size); break; case PNG_FILTER_VALUE_SUB: - sub_left_prediction(dsp, dst, src, bpp, size); + sub_left_prediction(c, dst, src, bpp, size); break; case PNG_FILTER_VALUE_UP: - dsp->diff_bytes(dst, src, top, size); + c->hdsp.diff_bytes(dst, src, top, size); break; case PNG_FILTER_VALUE_AVG: - for(i = 0; i < bpp; i++) + for (i = 0; i < bpp; i++) dst[i] = src[i] - (top[i] >> 1); - for(; i < size; i++) - dst[i] = src[i] - ((src[i-bpp] + top[i]) >> 1); + for (; i < size; i++) + dst[i] = src[i] - ((src[i - bpp] + top[i]) >> 1); break; case PNG_FILTER_VALUE_PAETH: - for(i = 0; i < bpp; i++) + for (i = 0; i < bpp; i++) dst[i] = src[i] - top[i]; - sub_png_paeth_prediction(dst+i, src+i, top+i, size-i, bpp); + sub_png_paeth_prediction(dst + i, src + i, top + i, size - i, bpp); break; } } @@ -163,26 +165,26 @@ static uint8_t *png_choose_filter(PNGEncContext *s, uint8_t *dst, { int pred = s->filter_type; av_assert0(bpp || !pred); - if(!top && pred) + if (!top && pred) pred = PNG_FILTER_VALUE_SUB; - if(pred == PNG_FILTER_VALUE_MIXED) { + if (pred == PNG_FILTER_VALUE_MIXED) { int i; int cost, bcost = INT_MAX; uint8_t *buf1 = dst, *buf2 = dst + size + 16; - for(pred=0; pred<5; pred++) { - png_filter_row(&s->dsp, buf1+1, pred, src, top, size, bpp); + for (pred = 0; pred < 5; pred++) { + png_filter_row(s, buf1 + 1, pred, src, top, size, bpp); buf1[0] = pred; cost = 0; - for(i=0; i<=size; i++) - cost += abs((int8_t)buf1[i]); - if(cost < bcost) { + for (i = 0; i <= size; i++) + cost += abs((int8_t) buf1[i]); + if (cost < bcost) { bcost = cost; - FFSWAP(uint8_t*, buf1, buf2); + FFSWAP(uint8_t *, buf1, buf2); } } return buf2; } else { - png_filter_row(&s->dsp, dst+1, pred, src, top, size, bpp); + png_filter_row(s, dst + 1, pred, src, top, size, bpp); dst[0] = pred; return dst; } @@ -213,16 +215,17 @@ static int png_write_row(PNGEncContext *s, const uint8_t *data, int size) int ret; s->zstream.avail_in = size; - s->zstream.next_in = (uint8_t *)data; + s->zstream.next_in = (uint8_t *)data; while (s->zstream.avail_in > 0) { ret = deflate(&s->zstream, Z_NO_FLUSH); if (ret != Z_OK) return -1; if (s->zstream.avail_out == 0) { - if(s->bytestream_end - s->bytestream > IOBUF_SIZE + 100) - png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, IOBUF_SIZE); + if (s->bytestream_end - s->bytestream > IOBUF_SIZE + 100) + png_write_chunk(&s->bytestream, + MKTAG('I', 'D', 'A', 'T'), s->buf, IOBUF_SIZE); s->zstream.avail_out = IOBUF_SIZE; - s->zstream.next_out = s->buf; + s->zstream.next_out = s->buf; } } return 0; @@ -231,19 +234,19 @@ static int png_write_row(PNGEncContext *s, const uint8_t *data, int size) static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { - PNGEncContext *s = avctx->priv_data; - const AVFrame * const p = pict; + PNGEncContext *s = avctx->priv_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; int64_t max_packet_size; int compression_level; - uint8_t *ptr, *top; - uint8_t *crow_base = NULL, *crow_buf, *crow; + uint8_t *ptr, *top, *crow_buf, *crow; + uint8_t *crow_base = NULL; uint8_t *progressive_buf = NULL; - uint8_t *top_buf = NULL; + uint8_t *top_buf = NULL; is_progressive = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT); - switch(avctx->pix_fmt) { + switch (avctx->pix_fmt) { case AV_PIX_FMT_RGBA64BE: bit_depth = 16; color_type = PNG_COLOR_TYPE_RGB_ALPHA; @@ -253,19 +256,19 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, color_type = PNG_COLOR_TYPE_RGB; break; case AV_PIX_FMT_RGBA: - bit_depth = 8; + bit_depth = 8; color_type = PNG_COLOR_TYPE_RGB_ALPHA; break; case AV_PIX_FMT_RGB24: - bit_depth = 8; + bit_depth = 8; color_type = PNG_COLOR_TYPE_RGB; break; case AV_PIX_FMT_GRAY16BE: - bit_depth = 16; + bit_depth = 16; color_type = PNG_COLOR_TYPE_GRAY; break; case AV_PIX_FMT_GRAY8: - bit_depth = 8; + bit_depth = 8; color_type = PNG_COLOR_TYPE_GRAY; break; case AV_PIX_FMT_GRAY8A: @@ -273,25 +276,25 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; case AV_PIX_FMT_MONOBLACK: - bit_depth = 1; + bit_depth = 1; color_type = PNG_COLOR_TYPE_GRAY; break; case AV_PIX_FMT_PAL8: - bit_depth = 8; + bit_depth = 8; color_type = PNG_COLOR_TYPE_PALETTE; break; default: return -1; } bits_per_pixel = ff_png_get_nb_channels(color_type) * bit_depth; - row_size = (avctx->width * bits_per_pixel + 7) >> 3; + row_size = (avctx->width * bits_per_pixel + 7) >> 3; s->zstream.zalloc = ff_png_zalloc; - s->zstream.zfree = ff_png_zfree; + s->zstream.zfree = ff_png_zfree; s->zstream.opaque = NULL; - compression_level = avctx->compression_level == FF_COMPRESSION_DEFAULT ? - Z_DEFAULT_COMPRESSION : - av_clip(avctx->compression_level, 0, 9); + compression_level = avctx->compression_level == FF_COMPRESSION_DEFAULT + ? Z_DEFAULT_COMPRESSION + : av_clip(avctx->compression_level, 0, 9); ret = deflateInit2(&s->zstream, compression_level, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY); if (ret != Z_OK) @@ -313,7 +316,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, crow_base = av_malloc((row_size + 32) << (s->filter_type == PNG_FILTER_VALUE_MIXED)); if (!crow_base) goto fail; - crow_buf = crow_base + 15; // pixel data should be aligned, but there's a control byte before it + // pixel data should be aligned, but there's a control byte before it + crow_buf = crow_base + 15; if (is_progressive) { progressive_buf = av_malloc(row_size + 1); if (!progressive_buf) @@ -331,8 +335,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, AV_WB32(s->buf, avctx->width); AV_WB32(s->buf + 4, avctx->height); - s->buf[8] = bit_depth; - s->buf[9] = color_type; + s->buf[8] = bit_depth; + s->buf[9] = color_type; s->buf[10] = 0; /* compression type */ s->buf[11] = 0; /* filter type */ s->buf[12] = is_progressive; /* interlace type */ @@ -357,61 +361,64 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, uint32_t *palette; uint8_t *alpha_ptr; - palette = (uint32_t *)p->data[1]; - ptr = s->buf; + palette = (uint32_t *)p->data[1]; + ptr = s->buf; alpha_ptr = s->buf + 256 * 3; has_alpha = 0; - for(i = 0; i < 256; i++) { - v = palette[i]; + for (i = 0; i < 256; i++) { + v = palette[i]; alpha = v >> 24; if (alpha != 0xff) has_alpha = 1; *alpha_ptr++ = alpha; bytestream_put_be24(&ptr, v); } - png_write_chunk(&s->bytestream, MKTAG('P', 'L', 'T', 'E'), s->buf, 256 * 3); + png_write_chunk(&s->bytestream, + MKTAG('P', 'L', 'T', 'E'), s->buf, 256 * 3); if (has_alpha) { - png_write_chunk(&s->bytestream, MKTAG('t', 'R', 'N', 'S'), s->buf + 256 * 3, 256); + png_write_chunk(&s->bytestream, + MKTAG('t', 'R', 'N', 'S'), s->buf + 256 * 3, 256); } } /* now put each row */ s->zstream.avail_out = IOBUF_SIZE; - s->zstream.next_out = s->buf; + s->zstream.next_out = s->buf; if (is_progressive) { int pass; - for(pass = 0; pass < NB_PASSES; pass++) { + for (pass = 0; pass < NB_PASSES; pass++) { /* NOTE: a pass is completely omitted if no pixels would be - output */ + * output */ pass_row_size = ff_png_pass_row_size(pass, bits_per_pixel, avctx->width); if (pass_row_size > 0) { top = NULL; - for(y = 0; y < avctx->height; y++) { + for (y = 0; y < avctx->height; y++) if ((ff_png_pass_ymask[pass] << (y & 7)) & 0x80) { ptr = p->data[0] + y * p->linesize[0]; - FFSWAP(uint8_t*, progressive_buf, top_buf); + FFSWAP(uint8_t *, progressive_buf, top_buf); png_get_interlaced_row(progressive_buf, pass_row_size, bits_per_pixel, pass, ptr, avctx->width); - crow = png_choose_filter(s, crow_buf, progressive_buf, top, pass_row_size, bits_per_pixel>>3); + crow = png_choose_filter(s, crow_buf, progressive_buf, + top, pass_row_size, bits_per_pixel >> 3); png_write_row(s, crow, pass_row_size + 1); top = progressive_buf; } - } } } } else { top = NULL; - for(y = 0; y < avctx->height; y++) { + for (y = 0; y < avctx->height; y++) { ptr = p->data[0] + y * p->linesize[0]; - crow = png_choose_filter(s, crow_buf, ptr, top, row_size, bits_per_pixel>>3); + crow = png_choose_filter(s, crow_buf, ptr, top, + row_size, bits_per_pixel >> 3); png_write_row(s, crow, row_size + 1); top = ptr; } } /* compress last bytes */ - for(;;) { + for (;;) { ret = deflate(&s->zstream, Z_FINISH); if (ret == Z_OK || ret == Z_STREAM_END) { len = IOBUF_SIZE - s->zstream.avail_out; @@ -419,7 +426,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, len); } s->zstream.avail_out = IOBUF_SIZE; - s->zstream.next_out = s->buf; + s->zstream.next_out = s->buf; if (ret == Z_STREAM_END) break; } else { @@ -433,21 +440,22 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, *got_packet = 1; ret = 0; - the_end: +the_end: av_free(crow_base); av_free(progressive_buf); av_free(top_buf); deflateEnd(&s->zstream); return ret; - fail: +fail: ret = -1; goto the_end; } -static av_cold int png_enc_init(AVCodecContext *avctx){ +static av_cold int png_enc_init(AVCodecContext *avctx) +{ PNGEncContext *s = avctx->priv_data; - switch(avctx->pix_fmt) { + switch (avctx->pix_fmt) { case AV_PIX_FMT_RGBA: avctx->bits_per_coded_sample = 32; break; @@ -471,10 +479,12 @@ static av_cold int png_enc_init(AVCodecContext *avctx){ avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; - ff_dsputil_init(&s->dsp, avctx); + ff_huffyuvencdsp_init(&s->hdsp); - s->filter_type = av_clip(avctx->prediction_method, PNG_FILTER_VALUE_NONE, PNG_FILTER_VALUE_MIXED); - if(avctx->pix_fmt == AV_PIX_FMT_MONOBLACK) + s->filter_type = av_clip(avctx->prediction_method, + PNG_FILTER_VALUE_NONE, + PNG_FILTER_VALUE_MIXED); + if (avctx->pix_fmt == AV_PIX_FMT_MONOBLACK) s->filter_type = PNG_FILTER_VALUE_NONE; if (s->dpi && s->dpm) { @@ -518,7 +528,7 @@ AVCodec ff_png_encoder = { .close = png_enc_close, .encode2 = encode_frame, .capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, - .pix_fmts = (const enum AVPixelFormat[]){ + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_RGBA64BE, AV_PIX_FMT_PAL8, diff --git a/libavcodec/ppc/Makefile b/libavcodec/ppc/Makefile index 71b23da10..6305904fa 100644 --- a/libavcodec/ppc/Makefile +++ b/libavcodec/ppc/Makefile @@ -1,24 +1,31 @@ -OBJS += ppc/dsputil_ppc.o \ - ppc/fmtconvert_altivec.o \ - ppc/videodsp_ppc.o \ +OBJS += ppc/fmtconvert_altivec.o \ +OBJS-$(CONFIG_AUDIODSP) += ppc/audiodsp.o +OBJS-$(CONFIG_BLOCKDSP) += ppc/blockdsp.o +OBJS-$(CONFIG_DSPUTIL) += ppc/dsputil_altivec.o OBJS-$(CONFIG_FFT) += ppc/fft_altivec.o OBJS-$(CONFIG_H264CHROMA) += ppc/h264chroma_init.o -OBJS-$(CONFIG_H264DSP) += ppc/h264dsp.o +OBJS-$(CONFIG_H264DSP) += ppc/h264dsp.o ppc/hpeldsp_altivec.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_MPEGAUDIODSP) += ppc/mpegaudiodsp_altivec.o -OBJS-$(CONFIG_MPEGVIDEO) += ppc/mpegvideo_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_VIDEODSP) += ppc/videodsp_ppc.o +OBJS-$(CONFIG_VP3DSP) += ppc/vp3dsp_altivec.o + +OBJS-$(CONFIG_LLAUDDSP) += ppc/lossless_audiodsp_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_VP3DSP) += ppc/vp3dsp_altivec.o +OBJS-$(CONFIG_VP7_DECODER) += ppc/vp8dsp_altivec.o OBJS-$(CONFIG_VP8_DECODER) += ppc/vp8dsp_altivec.o -ALTIVEC-OBJS += ppc/dsputil_altivec.o \ - ppc/fdct_altivec.o \ - ppc/gmc_altivec.o \ - ppc/idct_altivec.o \ - ppc/int_altivec.o \ - FFT-OBJS-$(HAVE_GNU_AS) += ppc/fft_altivec_s.o +FFT-OBJS-$(HAVE_VSX) += ppc/fft_vsx.o ALTIVEC-OBJS-$(CONFIG_FFT) += $(FFT-OBJS-yes) diff --git a/libavcodec/ppc/audiodsp.c b/libavcodec/ppc/audiodsp.c new file mode 100644 index 000000000..c88c3d916 --- /dev/null +++ b/libavcodec/ppc/audiodsp.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2007 Luca Barbato + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * miscellaneous audio operations + */ + +#include "config.h" +#if HAVE_ALTIVEC_H +#include +#endif + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/audiodsp.h" + +#if HAVE_ALTIVEC + +static int32_t scalarproduct_int16_altivec(const int16_t *v1, const int16_t *v2, + int order) +{ + int i; + LOAD_ZERO; + register vec_s16 vec1; + register vec_s32 res = vec_splat_s32(0), t; + int32_t ires; + + for (i = 0; i < order; i += 8) { + vec1 = vec_unaligned_load(v1); + t = vec_msum(vec1, vec_ld(0, v2), zero_s32v); + res = vec_sums(t, res); + v1 += 8; + v2 += 8; + } + res = vec_splat(res, 3); + vec_ste(res, 0, &ires); + + return ires; +} + +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_audiodsp_init_ppc(AudioDSPContext *c) +{ +#if HAVE_ALTIVEC + if (!PPC_ALTIVEC(av_get_cpu_flags())) + return; + + c->scalarproduct_int16 = scalarproduct_int16_altivec; +#endif /* HAVE_ALTIVEC */ +} diff --git a/libavcodec/ppc/blockdsp.c b/libavcodec/ppc/blockdsp.c new file mode 100644 index 000000000..0059b3b44 --- /dev/null +++ b/libavcodec/ppc/blockdsp.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2002 Brian Foley + * Copyright (c) 2002 Dieter Shirley + * Copyright (c) 2003-2004 Romain Dolbeau + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#if HAVE_ALTIVEC_H +#include +#endif +#include + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/mem.h" +#include "libavutil/ppc/cpu.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavcodec/blockdsp.h" + +/* ***** WARNING ***** WARNING ***** WARNING ***** */ +/* + * clear_blocks_dcbz32_ppc will not work properly on PowerPC processors with + * a cache line size not equal to 32 bytes. Fortunately all processors used + * by Apple up to at least the 7450 (AKA second generation G4) use 32-byte + * cache lines. This is due to the use of the 'dcbz' instruction. It simply + * clears a single cache line to zero, so you need to know the cache line + * size to use it! It's absurd, but it's fast... + * + * update 24/06/2003: Apple released the G5 yesterday, with a PPC970. + * cache line size: 128 bytes. Oups. + * The semantics of dcbz was changed, it always clears 32 bytes. So the function + * below will work, but will be slow. So I fixed check_dcbz_effect to use dcbzl, + * which is defined to clear a cache line (as dcbz before). So we can still + * distinguish, and use dcbz (32 bytes) or dcbzl (one cache line) as required. + * + * see + * and + */ +static void clear_blocks_dcbz32_ppc(int16_t *blocks) +{ + register int misal = (unsigned long) blocks & 0x00000010, i = 0; + + if (misal) { + ((unsigned long *) blocks)[0] = 0L; + ((unsigned long *) blocks)[1] = 0L; + ((unsigned long *) blocks)[2] = 0L; + ((unsigned long *) blocks)[3] = 0L; + i += 16; + } + for (; i < sizeof(int16_t) * 6 * 64 - 31; i += 32) + __asm__ volatile ("dcbz %0,%1" :: "b" (blocks), "r" (i) : "memory"); + if (misal) { + ((unsigned long *) blocks)[188] = 0L; + ((unsigned long *) blocks)[189] = 0L; + ((unsigned long *) blocks)[190] = 0L; + ((unsigned long *) blocks)[191] = 0L; + i += 16; + } +} + +/* Same as above, when dcbzl clears a whole 128 bytes cache line + * i.e. the PPC970 AKA G5. */ +static void clear_blocks_dcbz128_ppc(int16_t *blocks) +{ +#if HAVE_DCBZL + register int misal = (unsigned long) blocks & 0x0000007f, i = 0; + + if (misal) { + /* We could probably also optimize this case, + * but there's not much point as the machines + * aren't available yet (2003-06-26). */ + memset(blocks, 0, sizeof(int16_t) * 6 * 64); + } else { + for (; i < sizeof(int16_t) * 6 * 64; i += 128) + __asm__ volatile ("dcbzl %0,%1" :: "b" (blocks), "r" (i) : "memory"); + } +#else + memset(blocks, 0, sizeof(int16_t) * 6 * 64); +#endif +} + +/* Check dcbz report how many bytes are set to 0 by dcbz. */ +/* update 24/06/2003: Replace dcbz by dcbzl to get the intended effect + * (Apple "fixed" dcbz). Unfortunately this cannot be used unless the + * assembler knows about dcbzl ... */ +static long check_dcbzl_effect(void) +{ + long count = 0; +#if HAVE_DCBZL + register char *fakedata = av_malloc(1024); + register char *fakedata_middle; + register long zero = 0, i = 0; + + if (!fakedata) + return 0L; + + fakedata_middle = fakedata + 512; + + memset(fakedata, 0xFF, 1024); + + /* Below the constraint "b" seems to mean "address base register" + * in gcc-3.3 / RS/6000 speaks. Seems to avoid using r0, so.... */ + __asm__ volatile ("dcbzl %0, %1" :: "b" (fakedata_middle), "r" (zero)); + + for (i = 0; i < 1024; i++) + if (fakedata[i] == (char) 0) + count++; + + av_free(fakedata); +#endif + + return count; +} + +#if HAVE_ALTIVEC +static void clear_block_altivec(int16_t *block) +{ + LOAD_ZERO; + vec_st(zero_s16v, 0, block); + vec_st(zero_s16v, 16, block); + vec_st(zero_s16v, 32, block); + vec_st(zero_s16v, 48, block); + vec_st(zero_s16v, 64, block); + vec_st(zero_s16v, 80, block); + vec_st(zero_s16v, 96, block); + vec_st(zero_s16v, 112, block); +} +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_blockdsp_init_ppc(BlockDSPContext *c, unsigned high_bit_depth) +{ + // common optimizations whether AltiVec is available or not + if (!high_bit_depth) { + switch (check_dcbzl_effect()) { + case 32: + c->clear_blocks = clear_blocks_dcbz32_ppc; + break; + case 128: + c->clear_blocks = clear_blocks_dcbz128_ppc; + break; + default: + break; + } + } + +#if HAVE_ALTIVEC + if (!PPC_ALTIVEC(av_get_cpu_flags())) + return; + + if (!high_bit_depth) + c->clear_block = clear_block_altivec; +#endif /* HAVE_ALTIVEC */ +} diff --git a/libavcodec/ppc/dsputil_altivec.c b/libavcodec/ppc/dsputil_altivec.c index 8b676bc59..26d088ed7 100644 --- a/libavcodec/ppc/dsputil_altivec.c +++ b/libavcodec/ppc/dsputil_altivec.c @@ -24,49 +24,52 @@ #if HAVE_ALTIVEC_H #include #endif + #include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" #include "libavutil/ppc/types_altivec.h" #include "libavutil/ppc/util_altivec.h" +#include "libavcodec/avcodec.h" #include "libavcodec/dsputil.h" -#include "dsputil_altivec.h" +#include "libavcodec/mpegvideo.h" -static int sad16_x2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +#if HAVE_ALTIVEC +static int sad16_x2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h) { - int i; - int s; - const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); + int i, s = 0; + const vector unsigned char zero = + (const vector unsigned char) vec_splat_u8(0); vector unsigned char perm1 = vec_lvsl(0, pix2); vector unsigned char perm2 = vec_add(perm1, vec_splat_u8(1)); - vector unsigned char pix2l, pix2r; - vector unsigned char pix1v, pix2v, pix2iv, avgv, t5; - vector unsigned int sad; + vector unsigned int sad = (vector unsigned int) vec_splat_u32(0); vector signed int sumdiffs; - s = 0; - sad = (vector unsigned int)vec_splat_u32(0); for (i = 0; i < h; i++) { /* Read unaligned pixels into our vectors. The vectors are as follows: - pix1v: pix1[0]-pix1[15] - pix2v: pix2[0]-pix2[15] pix2iv: pix2[1]-pix2[16] */ - pix1v = vec_ld( 0, pix1); - pix2l = vec_ld( 0, pix2); - pix2r = vec_ld(16, pix2); - pix2v = vec_perm(pix2l, pix2r, perm1); - pix2iv = vec_perm(pix2l, pix2r, perm2); + * pix1v: pix1[0] - pix1[15] + * pix2v: pix2[0] - pix2[15] pix2iv: pix2[1] - pix2[16] */ + vector unsigned char pix1v = vec_ld(0, pix1); + vector unsigned char pix2l = vec_ld(0, pix2); + vector unsigned char pix2r = vec_ld(16, pix2); + vector unsigned char pix2v = vec_perm(pix2l, pix2r, perm1); + vector unsigned char pix2iv = vec_perm(pix2l, pix2r, perm2); - /* Calculate the average vector */ - avgv = vec_avg(pix2v, pix2iv); + /* Calculate the average vector. */ + vector unsigned char avgv = vec_avg(pix2v, pix2iv); - /* Calculate a sum of abs differences vector */ - t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv)); + /* Calculate a sum of abs differences vector. */ + vector unsigned char t5 = vec_sub(vec_max(pix1v, avgv), + vec_min(pix1v, avgv)); - /* Add each 4 pixel group together and put 4 results into sad */ + /* Add each 4 pixel group together and put 4 results into sad. */ sad = vec_sum4s(t5, sad); pix1 += line_size; pix2 += line_size; } - /* Sum up the four partial sums, and put the result into s */ + /* Sum up the four partial sums, and put the result into s. */ sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); sumdiffs = vec_splat(sumdiffs, 3); vec_ste(sumdiffs, 0, &s); @@ -74,152 +77,148 @@ static int sad16_x2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size return s; } -static int sad16_y2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +static int sad16_y2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h) { - int i; - int s; - const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); + int i, s = 0; + const vector unsigned char zero = + (const vector unsigned char) vec_splat_u8(0); vector unsigned char perm = vec_lvsl(0, pix2); - vector unsigned char pix2l, pix2r; - vector unsigned char pix1v, pix2v, pix3v, avgv, t5; - vector unsigned int sad; + vector 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; - s = 0; - sad = (vector unsigned int)vec_splat_u32(0); - /* Due to the fact that pix3 = pix2 + line_size, the pix3 of one - iteration becomes pix2 in the next iteration. We can use this - fact to avoid a potentially expensive unaligned read, each - time around the loop. - Read unaligned pixels into our vectors. The vectors are as follows: - pix2v: pix2[0]-pix2[15] - Split the pixel vectors into shorts */ - pix2l = vec_ld( 0, pix2); - pix2r = vec_ld(15, pix2); - pix2v = vec_perm(pix2l, pix2r, perm); + * iteration becomes pix2 in the next iteration. We can use this + * fact to avoid a potentially expensive unaligned read, each + * time around the loop. + * Read unaligned pixels into our vectors. The vectors are as follows: + * pix2v: pix2[0] - pix2[15] + * Split the pixel vectors into shorts. */ + vector unsigned char pix2l = vec_ld(0, pix2); + vector unsigned char pix2r = vec_ld(15, pix2); + vector unsigned char pix2v = vec_perm(pix2l, pix2r, perm); for (i = 0; i < h; i++) { /* Read unaligned pixels into our vectors. The vectors are as follows: - pix1v: pix1[0]-pix1[15] - pix3v: pix3[0]-pix3[15] */ - pix1v = vec_ld(0, pix1); + * pix1v: pix1[0] - pix1[15] + * pix3v: pix3[0] - pix3[15] */ + pix1v = vec_ld(0, pix1); - pix2l = vec_ld( 0, pix3); + pix2l = vec_ld(0, pix3); pix2r = vec_ld(15, pix3); pix3v = vec_perm(pix2l, pix2r, perm); - /* Calculate the average vector */ + /* Calculate the average vector. */ avgv = vec_avg(pix2v, pix3v); - /* Calculate a sum of abs differences vector */ + /* Calculate a sum of abs differences vector. */ t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv)); - /* Add each 4 pixel group together and put 4 results into sad */ + /* Add each 4 pixel group together and put 4 results into sad. */ sad = vec_sum4s(t5, sad); pix1 += line_size; pix2v = pix3v; pix3 += line_size; - } - /* Sum up the four partial sums, and put the result into s */ + /* Sum up the four partial sums, and put the result into s. */ sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); sumdiffs = vec_splat(sumdiffs, 3); vec_ste(sumdiffs, 0, &s); return s; } -static int sad16_xy2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +static int sad16_xy2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h) { - int i; - int s; + int i, s = 0; uint8_t *pix3 = pix2 + line_size; - const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); - const vector unsigned short two = (const vector unsigned short)vec_splat_u16(2); + const vector unsigned char zero = + (const vector unsigned char) vec_splat_u8(0); + const vector unsigned short two = + (const vector unsigned short) vec_splat_u16(2); vector unsigned char avgv, t5; vector unsigned char perm1 = vec_lvsl(0, pix2); vector unsigned char perm2 = vec_add(perm1, vec_splat_u8(1)); - vector unsigned char pix2l, pix2r; - vector unsigned char pix1v, pix2v, pix3v, pix2iv, pix3iv; - vector unsigned short pix2lv, pix2hv, pix2ilv, pix2ihv; + vector unsigned char pix1v, pix3v, pix3iv; vector unsigned short pix3lv, pix3hv, pix3ilv, pix3ihv; vector unsigned short avghv, avglv; - vector unsigned short t1, t2, t3, t4; - vector unsigned int sad; + vector unsigned int sad = (vector unsigned int) vec_splat_u32(0); vector signed int sumdiffs; - sad = (vector unsigned int)vec_splat_u32(0); - - s = 0; - /* Due to the fact that pix3 = pix2 + line_size, the pix3 of one - iteration becomes pix2 in the next iteration. We can use this - fact to avoid a potentially expensive unaligned read, as well - as some splitting, and vector addition each time around the loop. - Read unaligned pixels into our vectors. The vectors are as follows: - pix2v: pix2[0]-pix2[15] pix2iv: pix2[1]-pix2[16] - Split the pixel vectors into shorts */ - pix2l = vec_ld( 0, pix2); - pix2r = vec_ld(16, pix2); - pix2v = vec_perm(pix2l, pix2r, perm1); - pix2iv = vec_perm(pix2l, pix2r, perm2); + * iteration becomes pix2 in the next iteration. We can use this + * fact to avoid a potentially expensive unaligned read, as well + * as some splitting, and vector addition each time around the loop. + * Read unaligned pixels into our vectors. The vectors are as follows: + * pix2v: pix2[0] - pix2[15] pix2iv: pix2[1] - pix2[16] + * Split the pixel vectors into shorts. */ + vector unsigned char pix2l = vec_ld(0, pix2); + vector unsigned char pix2r = vec_ld(16, pix2); + vector unsigned char pix2v = vec_perm(pix2l, pix2r, perm1); + vector unsigned char pix2iv = vec_perm(pix2l, pix2r, perm2); - pix2hv = (vector unsigned short) vec_mergeh(zero, pix2v); - pix2lv = (vector unsigned short) vec_mergel(zero, pix2v); - pix2ihv = (vector unsigned short) vec_mergeh(zero, pix2iv); - pix2ilv = (vector unsigned short) vec_mergel(zero, pix2iv); - t1 = vec_add(pix2hv, pix2ihv); - t2 = vec_add(pix2lv, pix2ilv); + vector unsigned short pix2hv = + (vector unsigned short) vec_mergeh(zero, pix2v); + vector unsigned short pix2lv = + (vector unsigned short) vec_mergel(zero, pix2v); + vector unsigned short pix2ihv = + (vector unsigned short) vec_mergeh(zero, pix2iv); + vector unsigned short pix2ilv = + (vector unsigned short) vec_mergel(zero, pix2iv); + vector unsigned short t1 = vec_add(pix2hv, pix2ihv); + vector unsigned short t2 = vec_add(pix2lv, pix2ilv); + vector unsigned short t3, t4; for (i = 0; i < h; i++) { /* Read unaligned pixels into our vectors. The vectors are as follows: - pix1v: pix1[0]-pix1[15] - pix3v: pix3[0]-pix3[15] pix3iv: pix3[1]-pix3[16] */ - pix1v = vec_ld(0, pix1); + * pix1v: pix1[0] - pix1[15] + * pix3v: pix3[0] - pix3[15] pix3iv: pix3[1] - pix3[16] */ + pix1v = vec_ld(0, pix1); - pix2l = vec_ld( 0, pix3); + pix2l = vec_ld(0, pix3); pix2r = vec_ld(16, pix3); pix3v = vec_perm(pix2l, pix2r, perm1); pix3iv = vec_perm(pix2l, pix2r, perm2); /* Note that AltiVec does have vec_avg, but this works on vector pairs - and rounds up. We could do avg(avg(a,b),avg(c,d)), but the rounding - would mean that, for example, avg(3,0,0,1) = 2, when it should be 1. - Instead, we have to split the pixel vectors into vectors of shorts, - and do the averaging by hand. */ + * and rounds up. We could do avg(avg(a, b), avg(c, d)), but the + * rounding would mean that, for example, avg(3, 0, 0, 1) = 2, when + * it should be 1. Instead, we have to split the pixel vectors into + * vectors of shorts and do the averaging by hand. */ - /* Split the pixel vectors into shorts */ + /* Split the pixel vectors into shorts. */ pix3hv = (vector unsigned short) vec_mergeh(zero, pix3v); pix3lv = (vector unsigned short) vec_mergel(zero, pix3v); pix3ihv = (vector unsigned short) vec_mergeh(zero, pix3iv); pix3ilv = (vector unsigned short) vec_mergel(zero, pix3iv); - /* Do the averaging on them */ + /* Do the averaging on them. */ t3 = vec_add(pix3hv, pix3ihv); t4 = vec_add(pix3lv, pix3ilv); avghv = vec_sr(vec_add(vec_add(t1, t3), two), two); avglv = vec_sr(vec_add(vec_add(t2, t4), two), two); - /* Pack the shorts back into a result */ + /* Pack the shorts back into a result. */ avgv = vec_pack(avghv, avglv); - /* Calculate a sum of abs differences vector */ + /* Calculate a sum of abs differences vector. */ t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv)); - /* Add each 4 pixel group together and put 4 results into sad */ + /* Add each 4 pixel group together and put 4 results into sad. */ sad = vec_sum4s(t5, sad); pix1 += line_size; pix3 += line_size; - /* Transfer the calculated values for pix3 into pix2 */ + /* Transfer the calculated values for pix3 into pix2. */ t1 = t3; t2 = t4; } - /* Sum up the four partial sums, and put the result into s */ + /* Sum up the four partial sums, and put the result into s. */ sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); sumdiffs = vec_splat(sumdiffs, 3); vec_ste(sumdiffs, 0, &s); @@ -227,39 +226,36 @@ static int sad16_xy2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_siz return s; } -static int sad16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +static int sad16_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h) { - int i; - int s; - const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); + int i, s; + const vector unsigned int zero = + (const vector unsigned int) vec_splat_u32(0); vector unsigned char perm = vec_lvsl(0, pix2); - vector unsigned char t1, t2, t3,t4, t5; - vector unsigned int sad; + vector unsigned int sad = (vector unsigned int) vec_splat_u32(0); vector signed int sumdiffs; - sad = (vector unsigned int)vec_splat_u32(0); - - for (i = 0; i < h; i++) { - /* Read potentially unaligned pixels into t1 and t2 */ - vector unsigned char pix2l = vec_ld( 0, pix2); + /* Read potentially unaligned pixels into t1 and t2. */ + vector unsigned char pix2l = vec_ld(0, pix2); vector unsigned char pix2r = vec_ld(15, pix2); - t1 = vec_ld(0, pix1); - t2 = vec_perm(pix2l, pix2r, perm); + vector unsigned char t1 = vec_ld(0, pix1); + vector unsigned char t2 = vec_perm(pix2l, pix2r, perm); - /* Calculate a sum of abs differences vector */ - t3 = vec_max(t1, t2); - t4 = vec_min(t1, t2); - t5 = vec_sub(t3, t4); + /* Calculate a sum of abs differences vector. */ + vector unsigned char t3 = vec_max(t1, t2); + vector unsigned char t4 = vec_min(t1, t2); + vector unsigned char t5 = vec_sub(t3, t4); - /* Add each 4 pixel group together and put 4 results into sad */ + /* Add each 4 pixel group together and put 4 results into sad. */ sad = vec_sum4s(t5, sad); pix1 += line_size; pix2 += line_size; } - /* Sum up the four partial sums, and put the result into s */ + /* Sum up the four partial sums, and put the result into s. */ sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); sumdiffs = vec_splat(sumdiffs, 3); vec_ste(sumdiffs, 0, &s); @@ -267,44 +263,46 @@ static int sad16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, i return s; } -static int sad8_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +static int sad8_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h) { - int i; - int s; - const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); - const vector unsigned char permclear = (vector unsigned char){255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0}; + int i, s; + const vector unsigned int zero = + (const vector unsigned int) vec_splat_u32(0); + const vector unsigned char permclear = + (vector unsigned char) + { 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0 }; vector unsigned char perm1 = vec_lvsl(0, pix1); vector unsigned char perm2 = vec_lvsl(0, pix2); - vector unsigned char t1, t2, t3,t4, t5; - vector unsigned int sad; + vector unsigned int sad = (vector unsigned int) vec_splat_u32(0); vector signed int sumdiffs; - sad = (vector unsigned int)vec_splat_u32(0); - for (i = 0; i < h; i++) { - /* Read potentially unaligned pixels into t1 and t2 - Since we're reading 16 pixels, and actually only want 8, - mask out the last 8 pixels. The 0s don't change the sum. */ + /* Read potentially unaligned pixels into t1 and t2. + * Since we're reading 16 pixels, and actually only want 8, + * mask out the last 8 pixels. The 0s don't change the sum. */ vector unsigned char pix1l = vec_ld(0, pix1); vector unsigned char pix1r = vec_ld(7, pix1); vector unsigned char pix2l = vec_ld(0, pix2); vector unsigned char pix2r = vec_ld(7, pix2); - t1 = vec_and(vec_perm(pix1l, pix1r, perm1), permclear); - t2 = vec_and(vec_perm(pix2l, pix2r, perm2), permclear); + vector unsigned char t1 = vec_and(vec_perm(pix1l, pix1r, perm1), + permclear); + vector unsigned char t2 = vec_and(vec_perm(pix2l, pix2r, perm2), + permclear); - /* Calculate a sum of abs differences vector */ - t3 = vec_max(t1, t2); - t4 = vec_min(t1, t2); - t5 = vec_sub(t3, t4); + /* Calculate a sum of abs differences vector. */ + vector unsigned char t3 = vec_max(t1, t2); + vector unsigned char t4 = vec_min(t1, t2); + vector unsigned char t5 = vec_sub(t3, t4); - /* Add each 4 pixel group together and put 4 results into sad */ + /* Add each 4 pixel group together and put 4 results into sad. */ sad = vec_sum4s(t5, sad); pix1 += line_size; pix2 += line_size; } - /* Sum up the four partial sums, and put the result into s */ + /* Sum up the four partial sums, and put the result into s. */ sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); sumdiffs = vec_splat(sumdiffs, 3); vec_ste(sumdiffs, 0, &s); @@ -312,84 +310,51 @@ static int sad8_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, in return s; } -static int pix_norm1_altivec(uint8_t *pix, int line_size) +/* 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) { - int i; - int s; - const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); - vector unsigned char perm = vec_lvsl(0, pix); - vector unsigned char pixv; - vector unsigned int sv; - vector signed int sum; - - sv = (vector unsigned int)vec_splat_u32(0); - - s = 0; - for (i = 0; i < 16; i++) { - /* Read in the potentially unaligned pixels */ - vector unsigned char pixl = vec_ld( 0, pix); - vector unsigned char pixr = vec_ld(15, pix); - pixv = vec_perm(pixl, pixr, perm); - - /* Square the values, and add them to our sum */ - sv = vec_msum(pixv, pixv, sv); - - pix += line_size; - } - /* Sum up the four partial sums, and put the result into s */ - sum = vec_sums((vector signed int) sv, (vector signed int) zero); - sum = vec_splat(sum, 3); - vec_ste(sum, 0, &s); - - return s; -} - -/** - * Sum of Squared Errors for a 8x8 block. - * AltiVec-enhanced. - * It's the sad8_altivec code above w/ squaring added. - */ -static int sse8_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) -{ - int i; - int s; - const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); - const vector unsigned char permclear = (vector unsigned char){255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0}; + int i, s; + const vector unsigned int zero = + (const vector unsigned int) vec_splat_u32(0); + const vector unsigned char permclear = + (vector unsigned char) + { 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0 }; vector unsigned char perm1 = vec_lvsl(0, pix1); vector unsigned char perm2 = vec_lvsl(0, pix2); - vector unsigned char t1, t2, t3,t4, t5; - vector unsigned int sum; + vector unsigned int sum = (vector unsigned int) vec_splat_u32(0); vector signed int sumsqr; - sum = (vector unsigned int)vec_splat_u32(0); - for (i = 0; i < h; i++) { - /* Read potentially unaligned pixels into t1 and t2 - Since we're reading 16 pixels, and actually only want 8, - mask out the last 8 pixels. The 0s don't change the sum. */ + /* Read potentially unaligned pixels into t1 and t2. + * Since we're reading 16 pixels, and actually only want 8, + * mask out the last 8 pixels. The 0s don't change the sum. */ vector unsigned char pix1l = vec_ld(0, pix1); vector unsigned char pix1r = vec_ld(7, pix1); vector unsigned char pix2l = vec_ld(0, pix2); vector unsigned char pix2r = vec_ld(7, pix2); - t1 = vec_and(vec_perm(pix1l, pix1r, perm1), permclear); - t2 = vec_and(vec_perm(pix2l, pix2r, perm2), permclear); + vector unsigned char t1 = vec_and(vec_perm(pix1l, pix1r, perm1), + permclear); + vector unsigned char t2 = vec_and(vec_perm(pix2l, pix2r, perm2), + permclear); /* Since we want to use unsigned chars, we can take advantage - of the fact that abs(a-b)^2 = (a-b)^2. */ + * of the fact that abs(a - b) ^ 2 = (a - b) ^ 2. */ - /* Calculate abs differences vector */ - t3 = vec_max(t1, t2); - t4 = vec_min(t1, t2); - t5 = vec_sub(t3, t4); + /* Calculate abs differences vector. */ + vector unsigned char t3 = vec_max(t1, t2); + vector unsigned char t4 = vec_min(t1, t2); + vector unsigned char t5 = vec_sub(t3, t4); - /* Square the values and add them to our sum */ + /* Square the values and add them to our sum. */ sum = vec_msum(t5, t5, sum); pix1 += line_size; pix2 += line_size; } - /* Sum up the four partial sums, and put the result into s */ + /* Sum up the four partial sums, and put the result into s. */ sumsqr = vec_sums((vector signed int) sum, (vector signed int) zero); sumsqr = vec_splat(sumsqr, 3); vec_ste(sumsqr, 0, &s); @@ -397,46 +362,41 @@ static int sse8_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, in return s; } -/** - * Sum of Squared Errors for a 16x16 block. - * AltiVec-enhanced. - * It's the sad16_altivec code above w/ squaring added. - */ -static int sse16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +/* 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) { - int i; - int s; - const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); + int i, s; + const vector unsigned int zero = + (const vector unsigned int) vec_splat_u32(0); vector unsigned char perm = vec_lvsl(0, pix2); - vector unsigned char t1, t2, t3,t4, t5; - vector unsigned int sum; + vector unsigned int sum = (vector unsigned int) vec_splat_u32(0); vector signed int sumsqr; - sum = (vector unsigned int)vec_splat_u32(0); - for (i = 0; i < h; i++) { - /* Read potentially unaligned pixels into t1 and t2 */ - vector unsigned char pix2l = vec_ld( 0, pix2); + /* Read potentially unaligned pixels into t1 and t2. */ + vector unsigned char pix2l = vec_ld(0, pix2); vector unsigned char pix2r = vec_ld(15, pix2); - t1 = vec_ld(0, pix1); - t2 = vec_perm(pix2l, pix2r, perm); + vector unsigned char t1 = vec_ld(0, pix1); + vector unsigned char t2 = vec_perm(pix2l, pix2r, perm); /* Since we want to use unsigned chars, we can take advantage - of the fact that abs(a-b)^2 = (a-b)^2. */ + * of the fact that abs(a - b) ^ 2 = (a - b) ^ 2. */ - /* Calculate abs differences vector */ - t3 = vec_max(t1, t2); - t4 = vec_min(t1, t2); - t5 = vec_sub(t3, t4); + /* Calculate abs differences vector. */ + vector unsigned char t3 = vec_max(t1, t2); + vector unsigned char t4 = vec_min(t1, t2); + vector unsigned char t5 = vec_sub(t3, t4); - /* Square the values and add them to our sum */ + /* Square the values and add them to our sum. */ sum = vec_msum(t5, t5, sum); pix1 += line_size; pix2 += line_size; } - /* Sum up the four partial sums, and put the result into s */ + /* Sum up the four partial sums, and put the result into s. */ sumsqr = vec_sums((vector signed int) sum, (vector signed int) zero); sumsqr = vec_splat(sumsqr, 3); vec_ste(sumsqr, 0, &s); @@ -444,293 +404,138 @@ static int sse16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, i return s; } -static int pix_sum_altivec(uint8_t * pix, int line_size) +static int hadamard8_diff8x8_altivec(MpegEncContext *s, uint8_t *dst, + uint8_t *src, int stride, int h) { - const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); - vector unsigned char perm = vec_lvsl(0, pix); - vector unsigned char t1; - vector unsigned int sad; - vector signed int sumdiffs; - - int i; - int s; - - sad = (vector unsigned int)vec_splat_u32(0); - - for (i = 0; i < 16; i++) { - /* Read the potentially unaligned 16 pixels into t1 */ - vector unsigned char pixl = vec_ld( 0, pix); - vector unsigned char pixr = vec_ld(15, pix); - t1 = vec_perm(pixl, pixr, perm); - - /* Add each 4 pixel group together and put 4 results into sad */ - sad = vec_sum4s(t1, sad); - - pix += line_size; - } - - /* Sum up the four partial sums, and put the result into s */ - sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); - sumdiffs = vec_splat(sumdiffs, 3); - vec_ste(sumdiffs, 0, &s); - - return s; -} - -static void get_pixels_altivec(int16_t *restrict block, const uint8_t *pixels, int line_size) -{ - int i; - vector unsigned char perm = vec_lvsl(0, pixels); - vector unsigned char bytes; - const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); - vector signed short shorts; - - for (i = 0; i < 8; i++) { - // Read potentially unaligned pixels. - // We're reading 16 pixels, and actually only want 8, - // but we simply ignore the extras. - vector unsigned char pixl = vec_ld(0, pixels); - vector unsigned char pixr = vec_ld(7, pixels); - bytes = vec_perm(pixl, pixr, perm); - - // convert the bytes into shorts - shorts = (vector signed short)vec_mergeh(zero, bytes); - - // save the data to the block, we assume the block is 16-byte aligned - vec_st(shorts, i*16, (vector signed short*)block); - - pixels += line_size; - } -} - -static void diff_pixels_altivec(int16_t *restrict block, const uint8_t *s1, - const uint8_t *s2, int stride) -{ - int i; - vector unsigned char perm1 = vec_lvsl(0, s1); - vector unsigned char perm2 = vec_lvsl(0, s2); - vector unsigned char bytes, pixl, pixr; - const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); - vector signed short shorts1, shorts2; - - for (i = 0; i < 4; i++) { - // Read potentially unaligned pixels - // We're reading 16 pixels, and actually only want 8, - // but we simply ignore the extras. - pixl = vec_ld( 0, s1); - pixr = vec_ld(15, s1); - bytes = vec_perm(pixl, pixr, perm1); - - // convert the bytes into shorts - shorts1 = (vector signed short)vec_mergeh(zero, bytes); - - // Do the same for the second block of pixels - pixl = vec_ld( 0, s2); - pixr = vec_ld(15, s2); - bytes = vec_perm(pixl, pixr, perm2); - - // convert the bytes into shorts - shorts2 = (vector signed short)vec_mergeh(zero, bytes); - - // Do the subtraction - shorts1 = vec_sub(shorts1, shorts2); - - // save the data to the block, we assume the block is 16-byte aligned - vec_st(shorts1, 0, (vector signed short*)block); - - s1 += stride; - s2 += stride; - block += 8; - - - // The code below is a copy of the code above... This is a manual - // unroll. - - // Read potentially unaligned pixels - // We're reading 16 pixels, and actually only want 8, - // but we simply ignore the extras. - pixl = vec_ld( 0, s1); - pixr = vec_ld(15, s1); - bytes = vec_perm(pixl, pixr, perm1); - - // convert the bytes into shorts - shorts1 = (vector signed short)vec_mergeh(zero, bytes); - - // Do the same for the second block of pixels - pixl = vec_ld( 0, s2); - pixr = vec_ld(15, s2); - bytes = vec_perm(pixl, pixr, perm2); - - // convert the bytes into shorts - shorts2 = (vector signed short)vec_mergeh(zero, bytes); - - // Do the subtraction - shorts1 = vec_sub(shorts1, shorts2); - - // save the data to the block, we assume the block is 16-byte aligned - vec_st(shorts1, 0, (vector signed short*)block); - - s1 += stride; - s2 += stride; - block += 8; - } -} - - -static void clear_block_altivec(int16_t *block) { - LOAD_ZERO; - vec_st(zero_s16v, 0, block); - vec_st(zero_s16v, 16, block); - vec_st(zero_s16v, 32, block); - vec_st(zero_s16v, 48, block); - vec_st(zero_s16v, 64, block); - vec_st(zero_s16v, 80, block); - vec_st(zero_s16v, 96, block); - vec_st(zero_s16v, 112, block); -} - - -static void add_bytes_altivec(uint8_t *dst, uint8_t *src, int w) { - register int i; - register vector unsigned char vdst, vsrc; - - /* dst and src are 16 bytes-aligned (guaranteed) */ - for (i = 0 ; (i + 15) < w ; i+=16) { - vdst = vec_ld(i, (unsigned char*)dst); - vsrc = vec_ld(i, (unsigned char*)src); - vdst = vec_add(vsrc, vdst); - vec_st(vdst, i, (unsigned char*)dst); - } - /* if w is not a multiple of 16 */ - for (; (i < w) ; i++) { - dst[i] = src[i]; - } -} - -static int hadamard8_diff8x8_altivec(/*MpegEncContext*/ void *s, uint8_t *dst, uint8_t *src, int stride, int h){ int sum; register const vector unsigned char vzero = - (const vector unsigned char)vec_splat_u8(0); + (const vector unsigned char) vec_splat_u8(0); register vector signed short temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; { - register const vector signed short vprod1 =(const vector signed short) - { 1,-1, 1,-1, 1,-1, 1,-1 }; - register const vector signed short vprod2 =(const vector signed short) - { 1, 1,-1,-1, 1, 1,-1,-1 }; - register const vector signed short vprod3 =(const vector signed short) - { 1, 1, 1, 1,-1,-1,-1,-1 }; - register const vector unsigned char perm1 = (const vector unsigned char) - {0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, - 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D}; - register const vector unsigned char perm2 = (const vector unsigned char) - {0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, - 0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B}; - register const vector unsigned char perm3 = (const vector unsigned char) - {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + register const vector signed short vprod1 = + (const vector signed short) { 1, -1, 1, -1, 1, -1, 1, -1 }; + register const vector signed short vprod2 = + (const vector signed short) { 1, 1, -1, -1, 1, 1, -1, -1 }; + register const vector signed short vprod3 = + (const vector signed short) { 1, 1, 1, 1, -1, -1, -1, -1 }; + register const vector unsigned char perm1 = + (const vector unsigned char) + { 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, + 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D }; + register const vector unsigned char perm2 = + (const vector unsigned char) + { 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, + 0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B }; + register const vector unsigned char perm3 = + (const vector unsigned char) + { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; -#define ONEITERBUTTERFLY(i, res) \ - { \ - register vector unsigned char src1, src2, srcO; \ - register vector unsigned char dst1, dst2, dstO; \ - register vector signed short srcV, dstV; \ - register vector signed short but0, but1, but2, op1, op2, op3; \ - src1 = vec_ld(stride * i, src); \ - src2 = vec_ld((stride * i) + 15, src); \ - srcO = vec_perm(src1, src2, vec_lvsl(stride * i, src)); \ - dst1 = vec_ld(stride * i, dst); \ - dst2 = vec_ld((stride * i) + 15, dst); \ - dstO = vec_perm(dst1, dst2, vec_lvsl(stride * i, dst)); \ - /* promote the unsigned chars to signed shorts */ \ - /* we're in the 8x8 function, we only care for the first 8 */ \ - srcV = (vector signed short)vec_mergeh((vector signed char)vzero, \ - (vector signed char)srcO); \ - dstV = (vector signed short)vec_mergeh((vector signed char)vzero, \ - (vector signed char)dstO); \ - /* subtractions inside the first butterfly */ \ - but0 = vec_sub(srcV, dstV); \ - op1 = vec_perm(but0, but0, perm1); \ - but1 = vec_mladd(but0, vprod1, op1); \ - op2 = vec_perm(but1, but1, perm2); \ - but2 = vec_mladd(but1, vprod2, op2); \ - op3 = vec_perm(but2, but2, perm3); \ - res = vec_mladd(but2, vprod3, op3); \ +#define ONEITERBUTTERFLY(i, res) \ + { \ + register vector unsigned char src1 = vec_ld(stride * i, src); \ + register vector unsigned char src2 = vec_ld(stride * i + 15, src); \ + register vector unsigned char srcO = \ + vec_perm(src1, src2, vec_lvsl(stride * i, src)); \ + register vector unsigned char dst1 = vec_ld(stride * i, dst); \ + register vector unsigned char dst2 = vec_ld(stride * i + 15, dst); \ + register vector unsigned char dstO = \ + vec_perm(dst1, dst2, vec_lvsl(stride * i, dst)); \ + \ + /* Promote the unsigned chars to signed shorts. */ \ + /* We're in the 8x8 function, we only care for the first 8. */ \ + register vector signed short srcV = \ + (vector signed short) vec_mergeh((vector signed char) vzero, \ + (vector signed char) srcO); \ + register vector signed short dstV = \ + (vector signed short) vec_mergeh((vector signed char) vzero, \ + (vector signed char) dstO); \ + \ + /* subtractions inside the first butterfly */ \ + register vector signed short but0 = vec_sub(srcV, dstV); \ + register vector signed short op1 = vec_perm(but0, but0, perm1); \ + register vector signed short but1 = vec_mladd(but0, vprod1, op1); \ + register vector signed short op2 = vec_perm(but1, but1, perm2); \ + register vector signed short but2 = vec_mladd(but1, vprod2, op2); \ + register vector signed short op3 = vec_perm(but2, but2, perm3); \ + res = vec_mladd(but2, vprod3, op3); \ } - ONEITERBUTTERFLY(0, temp0); - ONEITERBUTTERFLY(1, temp1); - ONEITERBUTTERFLY(2, temp2); - ONEITERBUTTERFLY(3, temp3); - ONEITERBUTTERFLY(4, temp4); - ONEITERBUTTERFLY(5, temp5); - ONEITERBUTTERFLY(6, temp6); - ONEITERBUTTERFLY(7, temp7); + ONEITERBUTTERFLY(0, temp0); + ONEITERBUTTERFLY(1, temp1); + ONEITERBUTTERFLY(2, temp2); + ONEITERBUTTERFLY(3, temp3); + ONEITERBUTTERFLY(4, temp4); + ONEITERBUTTERFLY(5, temp5); + ONEITERBUTTERFLY(6, temp6); + ONEITERBUTTERFLY(7, temp7); } #undef ONEITERBUTTERFLY { - register vector signed int vsum; - register vector signed short line0 = vec_add(temp0, temp1); - register vector signed short line1 = vec_sub(temp0, temp1); - register vector signed short line2 = vec_add(temp2, temp3); - register vector signed short line3 = vec_sub(temp2, temp3); - register vector signed short line4 = vec_add(temp4, temp5); - register vector signed short line5 = vec_sub(temp4, temp5); - register vector signed short line6 = vec_add(temp6, temp7); - register vector signed short line7 = vec_sub(temp6, temp7); + register vector signed int vsum; + register vector signed short line0 = vec_add(temp0, temp1); + register vector signed short line1 = vec_sub(temp0, temp1); + register vector signed short line2 = vec_add(temp2, temp3); + register vector signed short line3 = vec_sub(temp2, temp3); + register vector signed short line4 = vec_add(temp4, temp5); + register vector signed short line5 = vec_sub(temp4, temp5); + register vector signed short line6 = vec_add(temp6, temp7); + register vector signed short line7 = vec_sub(temp6, temp7); - register vector signed short line0B = vec_add(line0, line2); - register vector signed short line2B = vec_sub(line0, line2); - register vector signed short line1B = vec_add(line1, line3); - register vector signed short line3B = vec_sub(line1, line3); - register vector signed short line4B = vec_add(line4, line6); - register vector signed short line6B = vec_sub(line4, line6); - register vector signed short line5B = vec_add(line5, line7); - register vector signed short line7B = vec_sub(line5, line7); + register vector signed short line0B = vec_add(line0, line2); + register vector signed short line2B = vec_sub(line0, line2); + register vector signed short line1B = vec_add(line1, line3); + register vector signed short line3B = vec_sub(line1, line3); + register vector signed short line4B = vec_add(line4, line6); + register vector signed short line6B = vec_sub(line4, line6); + register vector signed short line5B = vec_add(line5, line7); + register vector signed short line7B = vec_sub(line5, line7); - register vector signed short line0C = vec_add(line0B, line4B); - register vector signed short line4C = vec_sub(line0B, line4B); - register vector signed short line1C = vec_add(line1B, line5B); - register vector signed short line5C = vec_sub(line1B, line5B); - register vector signed short line2C = vec_add(line2B, line6B); - register vector signed short line6C = vec_sub(line2B, line6B); - register vector signed short line3C = vec_add(line3B, line7B); - register vector signed short line7C = vec_sub(line3B, line7B); + register vector signed short line0C = vec_add(line0B, line4B); + register vector signed short line4C = vec_sub(line0B, line4B); + register vector signed short line1C = vec_add(line1B, line5B); + register vector signed short line5C = vec_sub(line1B, line5B); + register vector signed short line2C = vec_add(line2B, line6B); + register vector signed short line6C = vec_sub(line2B, line6B); + register vector signed short line3C = vec_add(line3B, line7B); + register vector signed short line7C = vec_sub(line3B, line7B); - vsum = vec_sum4s(vec_abs(line0C), vec_splat_s32(0)); - vsum = vec_sum4s(vec_abs(line1C), vsum); - vsum = vec_sum4s(vec_abs(line2C), vsum); - vsum = vec_sum4s(vec_abs(line3C), vsum); - vsum = vec_sum4s(vec_abs(line4C), vsum); - vsum = vec_sum4s(vec_abs(line5C), vsum); - vsum = vec_sum4s(vec_abs(line6C), vsum); - vsum = vec_sum4s(vec_abs(line7C), vsum); - vsum = vec_sums(vsum, (vector signed int)vzero); - vsum = vec_splat(vsum, 3); - vec_ste(vsum, 0, &sum); + vsum = vec_sum4s(vec_abs(line0C), vec_splat_s32(0)); + vsum = vec_sum4s(vec_abs(line1C), vsum); + vsum = vec_sum4s(vec_abs(line2C), vsum); + vsum = vec_sum4s(vec_abs(line3C), vsum); + vsum = vec_sum4s(vec_abs(line4C), vsum); + vsum = vec_sum4s(vec_abs(line5C), vsum); + vsum = vec_sum4s(vec_abs(line6C), vsum); + vsum = vec_sum4s(vec_abs(line7C), vsum); + vsum = vec_sums(vsum, (vector signed int) vzero); + vsum = vec_splat(vsum, 3); + vec_ste(vsum, 0, &sum); } return sum; } /* -16x8 works with 16 elements; it allows to avoid replicating loads, and -give the compiler more rooms for scheduling. It's only used from -inside hadamard8_diff16_altivec. - -Unfortunately, it seems gcc-3.3 is a bit dumb, and the compiled code has a LOT -of spill code, it seems gcc (unlike xlc) cannot keep everything in registers -by itself. The following code include hand-made registers allocation. It's not -clean, but on a 7450 the resulting code is much faster (best case fall from -700+ cycles to 550). - -xlc doesn't add spill code, but it doesn't know how to schedule for the 7450, -and its code isn't much faster than gcc-3.3 on the 7450 (but uses 25% less -instructions...) - -On the 970, the hand-made RA is still a win (around 690 vs. around 780), but -xlc goes to around 660 on the regular C code... -*/ - -static int hadamard8_diff16x8_altivec(/*MpegEncContext*/ void *s, uint8_t *dst, uint8_t *src, int stride, int h) { + * 16x8 works with 16 elements; it allows to avoid replicating loads, and + * gives the compiler more room for scheduling. It's only used from + * inside hadamard8_diff16_altivec. + * + * Unfortunately, it seems gcc-3.3 is a bit dumb, and the compiled code has + * a LOT of spill code, it seems gcc (unlike xlc) cannot keep everything in + * registers by itself. The following code includes hand-made register + * allocation. It's not clean, but on a 7450 the resulting code is much faster + * (best case falls from 700+ cycles to 550). + * + * xlc doesn't add spill code, but it doesn't know how to schedule for the + * 7450, and its code isn't much faster than gcc-3.3 on the 7450 (but uses + * 25% fewer instructions...) + * + * On the 970, the hand-made RA is still a win (around 690 vs. around 780), + * but xlc goes to around 660 on the regular C code... + */ +static int hadamard8_diff16x8_altivec(MpegEncContext *s, uint8_t *dst, + uint8_t *src, int stride, int h) +{ int sum; register vector signed short temp0 __asm__ ("v0"), @@ -751,213 +556,212 @@ static int hadamard8_diff16x8_altivec(/*MpegEncContext*/ void *s, uint8_t *dst, temp6S __asm__ ("v14"), temp7S __asm__ ("v15"); register const vector unsigned char vzero __asm__ ("v31") = - (const vector unsigned char)vec_splat_u8(0); + (const vector unsigned char) vec_splat_u8(0); { - register const vector signed short vprod1 __asm__ ("v16") = - (const vector signed short){ 1,-1, 1,-1, 1,-1, 1,-1 }; - register const vector signed short vprod2 __asm__ ("v17") = - (const vector signed short){ 1, 1,-1,-1, 1, 1,-1,-1 }; - register const vector signed short vprod3 __asm__ ("v18") = - (const vector signed short){ 1, 1, 1, 1,-1,-1,-1,-1 }; - register const vector unsigned char perm1 __asm__ ("v19") = - (const vector unsigned char) - {0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, - 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D}; - register const vector unsigned char perm2 __asm__ ("v20") = - (const vector unsigned char) - {0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, - 0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B}; - register const vector unsigned char perm3 __asm__ ("v21") = - (const vector unsigned char) - {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + register const vector signed short vprod1 __asm__ ("v16") = + (const vector signed short) { 1, -1, 1, -1, 1, -1, 1, -1 }; -#define ONEITERBUTTERFLY(i, res1, res2) \ - { \ - register vector unsigned char src1 __asm__ ("v22"), \ - src2 __asm__ ("v23"), \ - dst1 __asm__ ("v24"), \ - dst2 __asm__ ("v25"), \ - srcO __asm__ ("v22"), \ - dstO __asm__ ("v23"); \ - \ - register vector signed short srcV __asm__ ("v24"), \ - dstV __asm__ ("v25"), \ - srcW __asm__ ("v26"), \ - dstW __asm__ ("v27"), \ - but0 __asm__ ("v28"), \ - but0S __asm__ ("v29"), \ - op1 __asm__ ("v30"), \ - but1 __asm__ ("v22"), \ - op1S __asm__ ("v23"), \ - but1S __asm__ ("v24"), \ - op2 __asm__ ("v25"), \ - but2 __asm__ ("v26"), \ - op2S __asm__ ("v27"), \ - but2S __asm__ ("v28"), \ - op3 __asm__ ("v29"), \ - op3S __asm__ ("v30"); \ - \ - src1 = vec_ld(stride * i, src); \ - src2 = vec_ld((stride * i) + 16, src); \ - srcO = vec_perm(src1, src2, vec_lvsl(stride * i, src)); \ - dst1 = vec_ld(stride * i, dst); \ - dst2 = vec_ld((stride * i) + 16, dst); \ - dstO = vec_perm(dst1, dst2, vec_lvsl(stride * i, dst)); \ - /* promote the unsigned chars to signed shorts */ \ - srcV = (vector signed short)vec_mergeh((vector signed char)vzero, \ - (vector signed char)srcO); \ - dstV = (vector signed short)vec_mergeh((vector signed char)vzero, \ - (vector signed char)dstO); \ - srcW = (vector signed short)vec_mergel((vector signed char)vzero, \ - (vector signed char)srcO); \ - dstW = (vector signed short)vec_mergel((vector signed char)vzero, \ - (vector signed char)dstO); \ - /* subtractions inside the first butterfly */ \ - but0 = vec_sub(srcV, dstV); \ - but0S = vec_sub(srcW, dstW); \ - op1 = vec_perm(but0, but0, perm1); \ - but1 = vec_mladd(but0, vprod1, op1); \ - op1S = vec_perm(but0S, but0S, perm1); \ - but1S = vec_mladd(but0S, vprod1, op1S); \ - op2 = vec_perm(but1, but1, perm2); \ - but2 = vec_mladd(but1, vprod2, op2); \ - op2S = vec_perm(but1S, but1S, perm2); \ - but2S = vec_mladd(but1S, vprod2, op2S); \ - op3 = vec_perm(but2, but2, perm3); \ - res1 = vec_mladd(but2, vprod3, op3); \ - op3S = vec_perm(but2S, but2S, perm3); \ - res2 = vec_mladd(but2S, vprod3, op3S); \ + register const vector signed short vprod2 __asm__ ("v17") = + (const vector signed short) { 1, 1, -1, -1, 1, 1, -1, -1 }; + + register const vector signed short vprod3 __asm__ ("v18") = + (const vector signed short) { 1, 1, 1, 1, -1, -1, -1, -1 }; + + register const vector unsigned char perm1 __asm__ ("v19") = + (const vector unsigned char) + { 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, + 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D }; + + register const vector unsigned char perm2 __asm__ ("v20") = + (const vector unsigned char) + { 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, + 0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B }; + + register const vector unsigned char perm3 __asm__ ("v21") = + (const vector unsigned char) + { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; + +#define ONEITERBUTTERFLY(i, res1, res2) \ + { \ + register vector unsigned char src1 __asm__ ("v22") = \ + vec_ld(stride * i, src); \ + register vector unsigned char src2 __asm__ ("v23") = \ + vec_ld(stride * i + 16, src); \ + register vector unsigned char srcO __asm__ ("v22") = \ + vec_perm(src1, src2, vec_lvsl(stride * i, src)); \ + register vector unsigned char dst1 __asm__ ("v24") = \ + vec_ld(stride * i, dst); \ + register vector unsigned char dst2 __asm__ ("v25") = \ + vec_ld(stride * i + 16, dst); \ + register vector unsigned char dstO __asm__ ("v23") = \ + vec_perm(dst1, dst2, vec_lvsl(stride * i, dst)); \ + \ + /* Promote the unsigned chars to signed shorts. */ \ + register vector signed short srcV __asm__ ("v24") = \ + (vector signed short) vec_mergeh((vector signed char) vzero, \ + (vector signed char) srcO); \ + register vector signed short dstV __asm__ ("v25") = \ + (vector signed short) vec_mergeh((vector signed char) vzero, \ + (vector signed char) dstO); \ + register vector signed short srcW __asm__ ("v26") = \ + (vector signed short) vec_mergel((vector signed char) vzero, \ + (vector signed char) srcO); \ + register vector signed short dstW __asm__ ("v27") = \ + (vector signed short) vec_mergel((vector signed char) vzero, \ + (vector signed char) dstO); \ + \ + /* subtractions inside the first butterfly */ \ + register vector signed short but0 __asm__ ("v28") = \ + vec_sub(srcV, dstV); \ + register vector signed short but0S __asm__ ("v29") = \ + vec_sub(srcW, dstW); \ + register vector signed short op1 __asm__ ("v30") = \ + vec_perm(but0, but0, perm1); \ + register vector signed short but1 __asm__ ("v22") = \ + vec_mladd(but0, vprod1, op1); \ + register vector signed short op1S __asm__ ("v23") = \ + vec_perm(but0S, but0S, perm1); \ + register vector signed short but1S __asm__ ("v24") = \ + vec_mladd(but0S, vprod1, op1S); \ + register vector signed short op2 __asm__ ("v25") = \ + vec_perm(but1, but1, perm2); \ + register vector signed short but2 __asm__ ("v26") = \ + vec_mladd(but1, vprod2, op2); \ + register vector signed short op2S __asm__ ("v27") = \ + vec_perm(but1S, but1S, perm2); \ + register vector signed short but2S __asm__ ("v28") = \ + vec_mladd(but1S, vprod2, op2S); \ + register vector signed short op3 __asm__ ("v29") = \ + vec_perm(but2, but2, perm3); \ + register vector signed short op3S __asm__ ("v30") = \ + vec_perm(but2S, but2S, perm3); \ + res1 = vec_mladd(but2, vprod3, op3); \ + res2 = vec_mladd(but2S, vprod3, op3S); \ } - ONEITERBUTTERFLY(0, temp0, temp0S); - ONEITERBUTTERFLY(1, temp1, temp1S); - ONEITERBUTTERFLY(2, temp2, temp2S); - ONEITERBUTTERFLY(3, temp3, temp3S); - ONEITERBUTTERFLY(4, temp4, temp4S); - ONEITERBUTTERFLY(5, temp5, temp5S); - ONEITERBUTTERFLY(6, temp6, temp6S); - ONEITERBUTTERFLY(7, temp7, temp7S); + ONEITERBUTTERFLY(0, temp0, temp0S); + ONEITERBUTTERFLY(1, temp1, temp1S); + ONEITERBUTTERFLY(2, temp2, temp2S); + ONEITERBUTTERFLY(3, temp3, temp3S); + ONEITERBUTTERFLY(4, temp4, temp4S); + ONEITERBUTTERFLY(5, temp5, temp5S); + ONEITERBUTTERFLY(6, temp6, temp6S); + ONEITERBUTTERFLY(7, temp7, temp7S); } #undef ONEITERBUTTERFLY { - register vector signed int vsum; - register vector signed short line0S, line1S, line2S, line3S, line4S, - line5S, line6S, line7S, line0BS,line2BS, - line1BS,line3BS,line4BS,line6BS,line5BS, - line7BS,line0CS,line4CS,line1CS,line5CS, - line2CS,line6CS,line3CS,line7CS; + register vector signed int vsum; - register vector signed short line0 = vec_add(temp0, temp1); - register vector signed short line1 = vec_sub(temp0, temp1); - register vector signed short line2 = vec_add(temp2, temp3); - register vector signed short line3 = vec_sub(temp2, temp3); - register vector signed short line4 = vec_add(temp4, temp5); - register vector signed short line5 = vec_sub(temp4, temp5); - register vector signed short line6 = vec_add(temp6, temp7); - register vector signed short line7 = vec_sub(temp6, temp7); + register vector signed short line0 = vec_add(temp0, temp1); + register vector signed short line1 = vec_sub(temp0, temp1); + register vector signed short line2 = vec_add(temp2, temp3); + register vector signed short line3 = vec_sub(temp2, temp3); + register vector signed short line4 = vec_add(temp4, temp5); + register vector signed short line5 = vec_sub(temp4, temp5); + register vector signed short line6 = vec_add(temp6, temp7); + register vector signed short line7 = vec_sub(temp6, temp7); - register vector signed short line0B = vec_add(line0, line2); - register vector signed short line2B = vec_sub(line0, line2); - register vector signed short line1B = vec_add(line1, line3); - register vector signed short line3B = vec_sub(line1, line3); - register vector signed short line4B = vec_add(line4, line6); - register vector signed short line6B = vec_sub(line4, line6); - register vector signed short line5B = vec_add(line5, line7); - register vector signed short line7B = vec_sub(line5, line7); + register vector signed short line0B = vec_add(line0, line2); + register vector signed short line2B = vec_sub(line0, line2); + register vector signed short line1B = vec_add(line1, line3); + register vector signed short line3B = vec_sub(line1, line3); + register vector signed short line4B = vec_add(line4, line6); + register vector signed short line6B = vec_sub(line4, line6); + register vector signed short line5B = vec_add(line5, line7); + register vector signed short line7B = vec_sub(line5, line7); - register vector signed short line0C = vec_add(line0B, line4B); - register vector signed short line4C = vec_sub(line0B, line4B); - register vector signed short line1C = vec_add(line1B, line5B); - register vector signed short line5C = vec_sub(line1B, line5B); - register vector signed short line2C = vec_add(line2B, line6B); - register vector signed short line6C = vec_sub(line2B, line6B); - register vector signed short line3C = vec_add(line3B, line7B); - register vector signed short line7C = vec_sub(line3B, line7B); + register vector signed short line0C = vec_add(line0B, line4B); + register vector signed short line4C = vec_sub(line0B, line4B); + register vector signed short line1C = vec_add(line1B, line5B); + register vector signed short line5C = vec_sub(line1B, line5B); + register vector signed short line2C = vec_add(line2B, line6B); + register vector signed short line6C = vec_sub(line2B, line6B); + register vector signed short line3C = vec_add(line3B, line7B); + register vector signed short line7C = vec_sub(line3B, line7B); - vsum = vec_sum4s(vec_abs(line0C), vec_splat_s32(0)); - vsum = vec_sum4s(vec_abs(line1C), vsum); - vsum = vec_sum4s(vec_abs(line2C), vsum); - vsum = vec_sum4s(vec_abs(line3C), vsum); - vsum = vec_sum4s(vec_abs(line4C), vsum); - vsum = vec_sum4s(vec_abs(line5C), vsum); - vsum = vec_sum4s(vec_abs(line6C), vsum); - vsum = vec_sum4s(vec_abs(line7C), vsum); + register vector signed short line0S = vec_add(temp0S, temp1S); + register vector signed short line1S = vec_sub(temp0S, temp1S); + register vector signed short line2S = vec_add(temp2S, temp3S); + register vector signed short line3S = vec_sub(temp2S, temp3S); + register vector signed short line4S = vec_add(temp4S, temp5S); + register vector signed short line5S = vec_sub(temp4S, temp5S); + register vector signed short line6S = vec_add(temp6S, temp7S); + register vector signed short line7S = vec_sub(temp6S, temp7S); - line0S = vec_add(temp0S, temp1S); - line1S = vec_sub(temp0S, temp1S); - line2S = vec_add(temp2S, temp3S); - line3S = vec_sub(temp2S, temp3S); - line4S = vec_add(temp4S, temp5S); - line5S = vec_sub(temp4S, temp5S); - line6S = vec_add(temp6S, temp7S); - line7S = vec_sub(temp6S, temp7S); + register vector signed short line0BS = vec_add(line0S, line2S); + register vector signed short line2BS = vec_sub(line0S, line2S); + register vector signed short line1BS = vec_add(line1S, line3S); + register vector signed short line3BS = vec_sub(line1S, line3S); + register vector signed short line4BS = vec_add(line4S, line6S); + register vector signed short line6BS = vec_sub(line4S, line6S); + register vector signed short line5BS = vec_add(line5S, line7S); + register vector signed short line7BS = vec_sub(line5S, line7S); - line0BS = vec_add(line0S, line2S); - line2BS = vec_sub(line0S, line2S); - line1BS = vec_add(line1S, line3S); - line3BS = vec_sub(line1S, line3S); - line4BS = vec_add(line4S, line6S); - line6BS = vec_sub(line4S, line6S); - line5BS = vec_add(line5S, line7S); - line7BS = vec_sub(line5S, line7S); + register vector signed short line0CS = vec_add(line0BS, line4BS); + register vector signed short line4CS = vec_sub(line0BS, line4BS); + register vector signed short line1CS = vec_add(line1BS, line5BS); + register vector signed short line5CS = vec_sub(line1BS, line5BS); + register vector signed short line2CS = vec_add(line2BS, line6BS); + register vector signed short line6CS = vec_sub(line2BS, line6BS); + register vector signed short line3CS = vec_add(line3BS, line7BS); + register vector signed short line7CS = vec_sub(line3BS, line7BS); - line0CS = vec_add(line0BS, line4BS); - line4CS = vec_sub(line0BS, line4BS); - line1CS = vec_add(line1BS, line5BS); - line5CS = vec_sub(line1BS, line5BS); - line2CS = vec_add(line2BS, line6BS); - line6CS = vec_sub(line2BS, line6BS); - line3CS = vec_add(line3BS, line7BS); - line7CS = vec_sub(line3BS, line7BS); + vsum = vec_sum4s(vec_abs(line0C), vec_splat_s32(0)); + vsum = vec_sum4s(vec_abs(line1C), vsum); + vsum = vec_sum4s(vec_abs(line2C), vsum); + vsum = vec_sum4s(vec_abs(line3C), vsum); + vsum = vec_sum4s(vec_abs(line4C), vsum); + vsum = vec_sum4s(vec_abs(line5C), vsum); + vsum = vec_sum4s(vec_abs(line6C), vsum); + vsum = vec_sum4s(vec_abs(line7C), vsum); - vsum = vec_sum4s(vec_abs(line0CS), vsum); - vsum = vec_sum4s(vec_abs(line1CS), vsum); - vsum = vec_sum4s(vec_abs(line2CS), vsum); - vsum = vec_sum4s(vec_abs(line3CS), vsum); - vsum = vec_sum4s(vec_abs(line4CS), vsum); - vsum = vec_sum4s(vec_abs(line5CS), vsum); - vsum = vec_sum4s(vec_abs(line6CS), vsum); - vsum = vec_sum4s(vec_abs(line7CS), vsum); - vsum = vec_sums(vsum, (vector signed int)vzero); - vsum = vec_splat(vsum, 3); - vec_ste(vsum, 0, &sum); + vsum = vec_sum4s(vec_abs(line0CS), vsum); + vsum = vec_sum4s(vec_abs(line1CS), vsum); + vsum = vec_sum4s(vec_abs(line2CS), vsum); + vsum = vec_sum4s(vec_abs(line3CS), vsum); + vsum = vec_sum4s(vec_abs(line4CS), vsum); + vsum = vec_sum4s(vec_abs(line5CS), vsum); + vsum = vec_sum4s(vec_abs(line6CS), vsum); + vsum = vec_sum4s(vec_abs(line7CS), vsum); + vsum = vec_sums(vsum, (vector signed int) vzero); + vsum = vec_splat(vsum, 3); + vec_ste(vsum, 0, &sum); } return sum; } -static int hadamard8_diff16_altivec(/*MpegEncContext*/ void *s, uint8_t *dst, uint8_t *src, int stride, int h){ - int score; - score = hadamard8_diff16x8_altivec(s, dst, src, stride, 8); - if (h==16) { - dst += 8*stride; - src += 8*stride; +static int hadamard8_diff16_altivec(MpegEncContext *s, uint8_t *dst, + uint8_t *src, int stride, int h) +{ + int score = hadamard8_diff16x8_altivec(s, dst, src, stride, 8); + + if (h == 16) { + dst += 8 * stride; + src += 8 * stride; score += hadamard8_diff16x8_altivec(s, dst, src, stride, 8); } return score; } +#endif /* HAVE_ALTIVEC */ -av_cold void ff_dsputil_init_altivec(DSPContext *c, AVCodecContext *avctx) +av_cold void ff_dsputil_init_ppc(DSPContext *c, AVCodecContext *avctx) { - const int high_bit_depth = avctx->bits_per_raw_sample > 8; +#if HAVE_ALTIVEC + if (!PPC_ALTIVEC(av_get_cpu_flags())) + return; c->pix_abs[0][1] = sad16_x2_altivec; c->pix_abs[0][2] = sad16_y2_altivec; c->pix_abs[0][3] = sad16_xy2_altivec; c->pix_abs[0][0] = sad16_altivec; c->pix_abs[1][0] = sad8_altivec; - c->sad[0]= sad16_altivec; - c->sad[1]= sad8_altivec; - c->pix_norm1 = pix_norm1_altivec; - c->sse[1]= sse8_altivec; - c->sse[0]= sse16_altivec; - c->pix_sum = pix_sum_altivec; - c->diff_pixels = diff_pixels_altivec; - c->add_bytes= add_bytes_altivec; - if (!high_bit_depth) { - c->get_pixels = get_pixels_altivec; - c->clear_block = clear_block_altivec; - } + + c->sad[0] = sad16_altivec; + c->sad[1] = sad8_altivec; + c->sse[0] = sse16_altivec; + c->sse[1] = sse8_altivec; c->hadamard8_diff[0] = hadamard8_diff16_altivec; c->hadamard8_diff[1] = hadamard8_diff8x8_altivec; +#endif /* HAVE_ALTIVEC */ } diff --git a/libavcodec/ppc/dsputil_ppc.c b/libavcodec/ppc/dsputil_ppc.c deleted file mode 100644 index 7454ea0f1..000000000 --- a/libavcodec/ppc/dsputil_ppc.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2002 Brian Foley - * Copyright (c) 2002 Dieter Shirley - * Copyright (c) 2003-2004 Romain Dolbeau - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "libavutil/attributes.h" -#include "libavutil/cpu.h" -#include "libavutil/mem.h" -#include "libavutil/ppc/cpu.h" -#include "dsputil_altivec.h" - -/* ***** WARNING ***** WARNING ***** WARNING ***** */ -/* -clear_blocks_dcbz32_ppc will not work properly on PowerPC processors with a -cache line size not equal to 32 bytes. -Fortunately all processor used by Apple up to at least the 7450 (aka second -generation G4) use 32 bytes cache line. -This is due to the use of the 'dcbz' instruction. It simply clear to zero a -single cache line, so you need to know the cache line size to use it ! -It's absurd, but it's fast... - -update 24/06/2003 : Apple released yesterday the G5, with a PPC970. cache line -size: 128 bytes. Oups. -The semantic of dcbz was changed, it always clear 32 bytes. so the function -below will work, but will be slow. So I fixed check_dcbz_effect to use dcbzl, -which is defined to clear a cache line (as dcbz before). So we still can -distinguish, and use dcbz (32 bytes) or dcbzl (one cache line) as required. - -see -and -*/ -static void clear_blocks_dcbz32_ppc(int16_t *blocks) -{ - register int misal = ((unsigned long)blocks & 0x00000010); - register int i = 0; - if (misal) { - ((unsigned long*)blocks)[0] = 0L; - ((unsigned long*)blocks)[1] = 0L; - ((unsigned long*)blocks)[2] = 0L; - ((unsigned long*)blocks)[3] = 0L; - i += 16; - } - for ( ; i < sizeof(int16_t)*6*64-31 ; i += 32) { - __asm__ volatile("dcbz %0,%1" : : "b" (blocks), "r" (i) : "memory"); - } - if (misal) { - ((unsigned long*)blocks)[188] = 0L; - ((unsigned long*)blocks)[189] = 0L; - ((unsigned long*)blocks)[190] = 0L; - ((unsigned long*)blocks)[191] = 0L; - i += 16; - } -} - -/* same as above, when dcbzl clear a whole 128B cache line - i.e. the PPC970 aka G5 */ -#if HAVE_DCBZL -static void clear_blocks_dcbz128_ppc(int16_t *blocks) -{ - register int misal = ((unsigned long)blocks & 0x0000007f); - register int i = 0; - if (misal) { - // we could probably also optimize this case, - // but there's not much point as the machines - // aren't available yet (2003-06-26) - memset(blocks, 0, sizeof(int16_t)*6*64); - } - else - for ( ; i < sizeof(int16_t)*6*64 ; i += 128) { - __asm__ volatile("dcbzl %0,%1" : : "b" (blocks), "r" (i) : "memory"); - } -} -#else -static void clear_blocks_dcbz128_ppc(int16_t *blocks) -{ - memset(blocks, 0, sizeof(int16_t)*6*64); -} -#endif - -#if HAVE_DCBZL -/* check dcbz report how many bytes are set to 0 by dcbz */ -/* update 24/06/2003 : replace dcbz by dcbzl to get - the intended effect (Apple "fixed" dcbz) - unfortunately this cannot be used unless the assembler - knows about dcbzl ... */ -static long check_dcbzl_effect(void) -{ - register char *fakedata = av_malloc(1024); - register char *fakedata_middle; - register long zero = 0; - register long i = 0; - long count = 0; - - if (!fakedata) { - return 0L; - } - - fakedata_middle = (fakedata + 512); - - memset(fakedata, 0xFF, 1024); - - /* below the constraint "b" seems to mean "Address base register" - in gcc-3.3 / RS/6000 speaks. seems to avoid using r0, so.... */ - __asm__ volatile("dcbzl %0, %1" : : "b" (fakedata_middle), "r" (zero)); - - for (i = 0; i < 1024 ; i ++) { - if (fakedata[i] == (char)0) - count++; - } - - av_free(fakedata); - - return count; -} -#else -static long check_dcbzl_effect(void) -{ - return 0; -} -#endif - -av_cold void ff_dsputil_init_ppc(DSPContext *c, AVCodecContext *avctx) -{ - const int high_bit_depth = avctx->bits_per_raw_sample > 8; - int mm_flags = av_get_cpu_flags(); - - // Common optimizations whether AltiVec is available or not - if (!high_bit_depth) { - switch (check_dcbzl_effect()) { - case 32: - c->clear_blocks = clear_blocks_dcbz32_ppc; - break; - case 128: - c->clear_blocks = clear_blocks_dcbz128_ppc; - break; - default: - break; - } - } - - if (PPC_ALTIVEC(mm_flags)) { - ff_dsputil_init_altivec(c, avctx); - ff_int_init_altivec(c, avctx); - c->gmc1 = ff_gmc1_altivec; - -#if CONFIG_ENCODERS - if (avctx->bits_per_raw_sample <= 8 && - (avctx->dct_algo == FF_DCT_AUTO || - avctx->dct_algo == FF_DCT_ALTIVEC)) { - c->fdct = ff_fdct_altivec; - } -#endif //CONFIG_ENCODERS - - if (avctx->lowres == 0 && avctx->bits_per_raw_sample <= 8) { - if ((avctx->idct_algo == FF_IDCT_AUTO) || - (avctx->idct_algo == FF_IDCT_ALTIVEC)) { - c->idct_put = ff_idct_put_altivec; - c->idct_add = ff_idct_add_altivec; - c->idct_permutation_type = FF_TRANSPOSE_IDCT_PERM; - } - } - - } -} diff --git a/libavcodec/ppc/fdct_altivec.c b/libavcodec/ppc/fdct_altivec.c deleted file mode 100644 index ff816e2a5..000000000 --- a/libavcodec/ppc/fdct_altivec.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (C) 2003 James Klicman - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" -#if HAVE_ALTIVEC_H -#include -#endif -#include "libavutil/common.h" -#include "dsputil_altivec.h" - -#define vs16(v) ((vector signed short)(v)) -#define vs32(v) ((vector signed int)(v)) -#define vu8(v) ((vector unsigned char)(v)) -#define vu16(v) ((vector unsigned short)(v)) -#define vu32(v) ((vector unsigned int)(v)) - - -#define C1 0.98078525066375732421875000 /* cos(1*PI/16) */ -#define C2 0.92387950420379638671875000 /* cos(2*PI/16) */ -#define C3 0.83146959543228149414062500 /* cos(3*PI/16) */ -#define C4 0.70710676908493041992187500 /* cos(4*PI/16) */ -#define C5 0.55557024478912353515625000 /* cos(5*PI/16) */ -#define C6 0.38268342614173889160156250 /* cos(6*PI/16) */ -#define C7 0.19509032368659973144531250 /* cos(7*PI/16) */ -#define SQRT_2 1.41421353816986083984375000 /* sqrt(2) */ - - -#define W0 -(2 * C2) -#define W1 (2 * C6) -#define W2 (SQRT_2 * C6) -#define W3 (SQRT_2 * C3) -#define W4 (SQRT_2 * (-C1 + C3 + C5 - C7)) -#define W5 (SQRT_2 * ( C1 + C3 - C5 + C7)) -#define W6 (SQRT_2 * ( C1 + C3 + C5 - C7)) -#define W7 (SQRT_2 * ( C1 + C3 - C5 - C7)) -#define W8 (SQRT_2 * ( C7 - C3)) -#define W9 (SQRT_2 * (-C1 - C3)) -#define WA (SQRT_2 * (-C3 - C5)) -#define WB (SQRT_2 * ( C5 - C3)) - - -static vector float fdctconsts[3] = { - { W0, W1, W2, W3 }, - { W4, W5, W6, W7 }, - { W8, W9, WA, WB } -}; - -#define LD_W0 vec_splat(cnsts0, 0) -#define LD_W1 vec_splat(cnsts0, 1) -#define LD_W2 vec_splat(cnsts0, 2) -#define LD_W3 vec_splat(cnsts0, 3) -#define LD_W4 vec_splat(cnsts1, 0) -#define LD_W5 vec_splat(cnsts1, 1) -#define LD_W6 vec_splat(cnsts1, 2) -#define LD_W7 vec_splat(cnsts1, 3) -#define LD_W8 vec_splat(cnsts2, 0) -#define LD_W9 vec_splat(cnsts2, 1) -#define LD_WA vec_splat(cnsts2, 2) -#define LD_WB vec_splat(cnsts2, 3) - - -#define FDCTROW(b0,b1,b2,b3,b4,b5,b6,b7) /* {{{ */ \ - x0 = vec_add(b0, b7); /* x0 = b0 + b7; */ \ - x7 = vec_sub(b0, b7); /* x7 = b0 - b7; */ \ - x1 = vec_add(b1, b6); /* x1 = b1 + b6; */ \ - x6 = vec_sub(b1, b6); /* x6 = b1 - b6; */ \ - x2 = vec_add(b2, b5); /* x2 = b2 + b5; */ \ - x5 = vec_sub(b2, b5); /* x5 = b2 - b5; */ \ - x3 = vec_add(b3, b4); /* x3 = b3 + b4; */ \ - x4 = vec_sub(b3, b4); /* x4 = b3 - b4; */ \ - \ - b7 = vec_add(x0, x3); /* b7 = x0 + x3; */ \ - b1 = vec_add(x1, x2); /* b1 = x1 + x2; */ \ - b0 = vec_add(b7, b1); /* b0 = b7 + b1; */ \ - b4 = vec_sub(b7, b1); /* b4 = b7 - b1; */ \ - \ - b2 = vec_sub(x0, x3); /* b2 = x0 - x3; */ \ - b6 = vec_sub(x1, x2); /* b6 = x1 - x2; */ \ - b5 = vec_add(b6, b2); /* b5 = b6 + b2; */ \ - cnst = LD_W2; \ - b5 = vec_madd(cnst, b5, mzero); /* b5 = b5 * W2; */ \ - cnst = LD_W1; \ - b2 = vec_madd(cnst, b2, b5); /* b2 = b5 + b2 * W1; */ \ - cnst = LD_W0; \ - b6 = vec_madd(cnst, b6, b5); /* b6 = b5 + b6 * W0; */ \ - \ - x0 = vec_add(x4, x7); /* x0 = x4 + x7; */ \ - x1 = vec_add(x5, x6); /* x1 = x5 + x6; */ \ - x2 = vec_add(x4, x6); /* x2 = x4 + x6; */ \ - x3 = vec_add(x5, x7); /* x3 = x5 + x7; */ \ - x8 = vec_add(x2, x3); /* x8 = x2 + x3; */ \ - cnst = LD_W3; \ - x8 = vec_madd(cnst, x8, mzero); /* x8 = x8 * W3; */ \ - \ - cnst = LD_W8; \ - x0 = vec_madd(cnst, x0, mzero); /* x0 *= W8; */ \ - cnst = LD_W9; \ - x1 = vec_madd(cnst, x1, mzero); /* x1 *= W9; */ \ - cnst = LD_WA; \ - x2 = vec_madd(cnst, x2, x8); /* x2 = x2 * WA + x8; */ \ - cnst = LD_WB; \ - x3 = vec_madd(cnst, x3, x8); /* x3 = x3 * WB + x8; */ \ - \ - cnst = LD_W4; \ - b7 = vec_madd(cnst, x4, x0); /* b7 = x4 * W4 + x0; */ \ - cnst = LD_W5; \ - b5 = vec_madd(cnst, x5, x1); /* b5 = x5 * W5 + x1; */ \ - cnst = LD_W6; \ - b3 = vec_madd(cnst, x6, x1); /* b3 = x6 * W6 + x1; */ \ - cnst = LD_W7; \ - b1 = vec_madd(cnst, x7, x0); /* b1 = x7 * W7 + x0; */ \ - \ - b7 = vec_add(b7, x2); /* b7 = b7 + x2; */ \ - b5 = vec_add(b5, x3); /* b5 = b5 + x3; */ \ - b3 = vec_add(b3, x2); /* b3 = b3 + x2; */ \ - b1 = vec_add(b1, x3); /* b1 = b1 + x3; */ \ - /* }}} */ - -#define FDCTCOL(b0,b1,b2,b3,b4,b5,b6,b7) /* {{{ */ \ - x0 = vec_add(b0, b7); /* x0 = b0 + b7; */ \ - x7 = vec_sub(b0, b7); /* x7 = b0 - b7; */ \ - x1 = vec_add(b1, b6); /* x1 = b1 + b6; */ \ - x6 = vec_sub(b1, b6); /* x6 = b1 - b6; */ \ - x2 = vec_add(b2, b5); /* x2 = b2 + b5; */ \ - x5 = vec_sub(b2, b5); /* x5 = b2 - b5; */ \ - x3 = vec_add(b3, b4); /* x3 = b3 + b4; */ \ - x4 = vec_sub(b3, b4); /* x4 = b3 - b4; */ \ - \ - b7 = vec_add(x0, x3); /* b7 = x0 + x3; */ \ - b1 = vec_add(x1, x2); /* b1 = x1 + x2; */ \ - b0 = vec_add(b7, b1); /* b0 = b7 + b1; */ \ - b4 = vec_sub(b7, b1); /* b4 = b7 - b1; */ \ - \ - b2 = vec_sub(x0, x3); /* b2 = x0 - x3; */ \ - b6 = vec_sub(x1, x2); /* b6 = x1 - x2; */ \ - b5 = vec_add(b6, b2); /* b5 = b6 + b2; */ \ - cnst = LD_W2; \ - b5 = vec_madd(cnst, b5, mzero); /* b5 = b5 * W2; */ \ - cnst = LD_W1; \ - b2 = vec_madd(cnst, b2, b5); /* b2 = b5 + b2 * W1; */ \ - cnst = LD_W0; \ - b6 = vec_madd(cnst, b6, b5); /* b6 = b5 + b6 * W0; */ \ - \ - x0 = vec_add(x4, x7); /* x0 = x4 + x7; */ \ - x1 = vec_add(x5, x6); /* x1 = x5 + x6; */ \ - x2 = vec_add(x4, x6); /* x2 = x4 + x6; */ \ - x3 = vec_add(x5, x7); /* x3 = x5 + x7; */ \ - x8 = vec_add(x2, x3); /* x8 = x2 + x3; */ \ - cnst = LD_W3; \ - x8 = vec_madd(cnst, x8, mzero); /* x8 = x8 * W3; */ \ - \ - cnst = LD_W8; \ - x0 = vec_madd(cnst, x0, mzero); /* x0 *= W8; */ \ - cnst = LD_W9; \ - x1 = vec_madd(cnst, x1, mzero); /* x1 *= W9; */ \ - cnst = LD_WA; \ - x2 = vec_madd(cnst, x2, x8); /* x2 = x2 * WA + x8; */ \ - cnst = LD_WB; \ - x3 = vec_madd(cnst, x3, x8); /* x3 = x3 * WB + x8; */ \ - \ - cnst = LD_W4; \ - b7 = vec_madd(cnst, x4, x0); /* b7 = x4 * W4 + x0; */ \ - cnst = LD_W5; \ - b5 = vec_madd(cnst, x5, x1); /* b5 = x5 * W5 + x1; */ \ - cnst = LD_W6; \ - b3 = vec_madd(cnst, x6, x1); /* b3 = x6 * W6 + x1; */ \ - cnst = LD_W7; \ - b1 = vec_madd(cnst, x7, x0); /* b1 = x7 * W7 + x0; */ \ - \ - b7 = vec_add(b7, x2); /* b7 += x2; */ \ - b5 = vec_add(b5, x3); /* b5 += x3; */ \ - b3 = vec_add(b3, x2); /* b3 += x2; */ \ - b1 = vec_add(b1, x3); /* b1 += x3; */ \ - /* }}} */ - - - -/* two dimensional discrete cosine transform */ - -void ff_fdct_altivec(int16_t *block) -{ - vector signed short *bp; - vector float *cp; - vector float b00, b10, b20, b30, b40, b50, b60, b70; - vector float b01, b11, b21, b31, b41, b51, b61, b71; - vector float mzero, cnst, cnsts0, cnsts1, cnsts2; - vector float x0, x1, x2, x3, x4, x5, x6, x7, x8; - - /* setup constants {{{ */ - /* mzero = -0.0 */ - mzero = ((vector float)vec_splat_u32(-1)); - mzero = ((vector float)vec_sl(vu32(mzero), vu32(mzero))); - cp = fdctconsts; - cnsts0 = vec_ld(0, cp); cp++; - cnsts1 = vec_ld(0, cp); cp++; - cnsts2 = vec_ld(0, cp); - /* }}} */ - - - /* 8x8 matrix transpose (vector short[8]) {{{ */ -#define MERGE_S16(hl,a,b) vec_merge##hl(vs16(a), vs16(b)) - - bp = (vector signed short*)block; - b00 = ((vector float)vec_ld(0, bp)); - b40 = ((vector float)vec_ld(16*4, bp)); - b01 = ((vector float)MERGE_S16(h, b00, b40)); - b11 = ((vector float)MERGE_S16(l, b00, b40)); - bp++; - b10 = ((vector float)vec_ld(0, bp)); - b50 = ((vector float)vec_ld(16*4, bp)); - b21 = ((vector float)MERGE_S16(h, b10, b50)); - b31 = ((vector float)MERGE_S16(l, b10, b50)); - bp++; - b20 = ((vector float)vec_ld(0, bp)); - b60 = ((vector float)vec_ld(16*4, bp)); - b41 = ((vector float)MERGE_S16(h, b20, b60)); - b51 = ((vector float)MERGE_S16(l, b20, b60)); - bp++; - b30 = ((vector float)vec_ld(0, bp)); - b70 = ((vector float)vec_ld(16*4, bp)); - b61 = ((vector float)MERGE_S16(h, b30, b70)); - b71 = ((vector float)MERGE_S16(l, b30, b70)); - - x0 = ((vector float)MERGE_S16(h, b01, b41)); - x1 = ((vector float)MERGE_S16(l, b01, b41)); - x2 = ((vector float)MERGE_S16(h, b11, b51)); - x3 = ((vector float)MERGE_S16(l, b11, b51)); - x4 = ((vector float)MERGE_S16(h, b21, b61)); - x5 = ((vector float)MERGE_S16(l, b21, b61)); - x6 = ((vector float)MERGE_S16(h, b31, b71)); - x7 = ((vector float)MERGE_S16(l, b31, b71)); - - b00 = ((vector float)MERGE_S16(h, x0, x4)); - b10 = ((vector float)MERGE_S16(l, x0, x4)); - b20 = ((vector float)MERGE_S16(h, x1, x5)); - b30 = ((vector float)MERGE_S16(l, x1, x5)); - b40 = ((vector float)MERGE_S16(h, x2, x6)); - b50 = ((vector float)MERGE_S16(l, x2, x6)); - b60 = ((vector float)MERGE_S16(h, x3, x7)); - b70 = ((vector float)MERGE_S16(l, x3, x7)); - -#undef MERGE_S16 - /* }}} */ - - -/* Some of the initial calculations can be done as vector short before - * conversion to vector float. The following code section takes advantage - * of this. - */ - /* fdct rows {{{ */ - x0 = ((vector float)vec_add(vs16(b00), vs16(b70))); - x7 = ((vector float)vec_sub(vs16(b00), vs16(b70))); - x1 = ((vector float)vec_add(vs16(b10), vs16(b60))); - x6 = ((vector float)vec_sub(vs16(b10), vs16(b60))); - x2 = ((vector float)vec_add(vs16(b20), vs16(b50))); - x5 = ((vector float)vec_sub(vs16(b20), vs16(b50))); - x3 = ((vector float)vec_add(vs16(b30), vs16(b40))); - x4 = ((vector float)vec_sub(vs16(b30), vs16(b40))); - - b70 = ((vector float)vec_add(vs16(x0), vs16(x3))); - b10 = ((vector float)vec_add(vs16(x1), vs16(x2))); - - b00 = ((vector float)vec_add(vs16(b70), vs16(b10))); - b40 = ((vector float)vec_sub(vs16(b70), vs16(b10))); - -#define CTF0(n) \ - b##n##1 = ((vector float)vec_unpackl(vs16(b##n##0))); \ - b##n##0 = ((vector float)vec_unpackh(vs16(b##n##0))); \ - b##n##1 = vec_ctf(vs32(b##n##1), 0); \ - b##n##0 = vec_ctf(vs32(b##n##0), 0); - - CTF0(0); - CTF0(4); - - b20 = ((vector float)vec_sub(vs16(x0), vs16(x3))); - b60 = ((vector float)vec_sub(vs16(x1), vs16(x2))); - - CTF0(2); - CTF0(6); - -#undef CTF0 - - x0 = vec_add(b60, b20); - x1 = vec_add(b61, b21); - - cnst = LD_W2; - x0 = vec_madd(cnst, x0, mzero); - x1 = vec_madd(cnst, x1, mzero); - cnst = LD_W1; - b20 = vec_madd(cnst, b20, x0); - b21 = vec_madd(cnst, b21, x1); - cnst = LD_W0; - b60 = vec_madd(cnst, b60, x0); - b61 = vec_madd(cnst, b61, x1); - -#define CTFX(x,b) \ - b##0 = ((vector float)vec_unpackh(vs16(x))); \ - b##1 = ((vector float)vec_unpackl(vs16(x))); \ - b##0 = vec_ctf(vs32(b##0), 0); \ - b##1 = vec_ctf(vs32(b##1), 0); \ - - CTFX(x4, b7); - CTFX(x5, b5); - CTFX(x6, b3); - CTFX(x7, b1); - -#undef CTFX - - - x0 = vec_add(b70, b10); - x1 = vec_add(b50, b30); - x2 = vec_add(b70, b30); - x3 = vec_add(b50, b10); - x8 = vec_add(x2, x3); - cnst = LD_W3; - x8 = vec_madd(cnst, x8, mzero); - - cnst = LD_W8; - x0 = vec_madd(cnst, x0, mzero); - cnst = LD_W9; - x1 = vec_madd(cnst, x1, mzero); - cnst = LD_WA; - x2 = vec_madd(cnst, x2, x8); - cnst = LD_WB; - x3 = vec_madd(cnst, x3, x8); - - cnst = LD_W4; - b70 = vec_madd(cnst, b70, x0); - cnst = LD_W5; - b50 = vec_madd(cnst, b50, x1); - cnst = LD_W6; - b30 = vec_madd(cnst, b30, x1); - cnst = LD_W7; - b10 = vec_madd(cnst, b10, x0); - - b70 = vec_add(b70, x2); - b50 = vec_add(b50, x3); - b30 = vec_add(b30, x2); - b10 = vec_add(b10, x3); - - - x0 = vec_add(b71, b11); - x1 = vec_add(b51, b31); - x2 = vec_add(b71, b31); - x3 = vec_add(b51, b11); - x8 = vec_add(x2, x3); - cnst = LD_W3; - x8 = vec_madd(cnst, x8, mzero); - - cnst = LD_W8; - x0 = vec_madd(cnst, x0, mzero); - cnst = LD_W9; - x1 = vec_madd(cnst, x1, mzero); - cnst = LD_WA; - x2 = vec_madd(cnst, x2, x8); - cnst = LD_WB; - x3 = vec_madd(cnst, x3, x8); - - cnst = LD_W4; - b71 = vec_madd(cnst, b71, x0); - cnst = LD_W5; - b51 = vec_madd(cnst, b51, x1); - cnst = LD_W6; - b31 = vec_madd(cnst, b31, x1); - cnst = LD_W7; - b11 = vec_madd(cnst, b11, x0); - - b71 = vec_add(b71, x2); - b51 = vec_add(b51, x3); - b31 = vec_add(b31, x2); - b11 = vec_add(b11, x3); - /* }}} */ - - - /* 8x8 matrix transpose (vector float[8][2]) {{{ */ - x0 = vec_mergel(b00, b20); - x1 = vec_mergeh(b00, b20); - x2 = vec_mergel(b10, b30); - x3 = vec_mergeh(b10, b30); - - b00 = vec_mergeh(x1, x3); - b10 = vec_mergel(x1, x3); - b20 = vec_mergeh(x0, x2); - b30 = vec_mergel(x0, x2); - - x4 = vec_mergel(b41, b61); - x5 = vec_mergeh(b41, b61); - x6 = vec_mergel(b51, b71); - x7 = vec_mergeh(b51, b71); - - b41 = vec_mergeh(x5, x7); - b51 = vec_mergel(x5, x7); - b61 = vec_mergeh(x4, x6); - b71 = vec_mergel(x4, x6); - - x0 = vec_mergel(b01, b21); - x1 = vec_mergeh(b01, b21); - x2 = vec_mergel(b11, b31); - x3 = vec_mergeh(b11, b31); - - x4 = vec_mergel(b40, b60); - x5 = vec_mergeh(b40, b60); - x6 = vec_mergel(b50, b70); - x7 = vec_mergeh(b50, b70); - - b40 = vec_mergeh(x1, x3); - b50 = vec_mergel(x1, x3); - b60 = vec_mergeh(x0, x2); - b70 = vec_mergel(x0, x2); - - b01 = vec_mergeh(x5, x7); - b11 = vec_mergel(x5, x7); - b21 = vec_mergeh(x4, x6); - b31 = vec_mergel(x4, x6); - /* }}} */ - - - FDCTCOL(b00, b10, b20, b30, b40, b50, b60, b70); - FDCTCOL(b01, b11, b21, b31, b41, b51, b61, b71); - - - /* round, convert back to short {{{ */ -#define CTS(n) \ - b##n##0 = vec_round(b##n##0); \ - b##n##1 = vec_round(b##n##1); \ - b##n##0 = ((vector float)vec_cts(b##n##0, 0)); \ - b##n##1 = ((vector float)vec_cts(b##n##1, 0)); \ - b##n##0 = ((vector float)vec_pack(vs32(b##n##0), vs32(b##n##1))); \ - vec_st(vs16(b##n##0), 0, bp); - - bp = (vector signed short*)block; - CTS(0); bp++; - CTS(1); bp++; - CTS(2); bp++; - CTS(3); bp++; - CTS(4); bp++; - CTS(5); bp++; - CTS(6); bp++; - CTS(7); - -#undef CTS - /* }}} */ -} diff --git a/libavcodec/ppc/fdctdsp.c b/libavcodec/ppc/fdctdsp.c new file mode 100644 index 000000000..561e469ab --- /dev/null +++ b/libavcodec/ppc/fdctdsp.c @@ -0,0 +1,479 @@ +/* + * Copyright (C) 2003 James Klicman + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#if HAVE_ALTIVEC_H +#include +#endif + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" +#include "libavcodec/fdctdsp.h" +#include "fdctdsp.h" + +#if HAVE_ALTIVEC + +#define vs16(v) ((vector signed short) (v)) +#define vs32(v) ((vector signed int) (v)) +#define vu8(v) ((vector unsigned char) (v)) +#define vu16(v) ((vector unsigned short) (v)) +#define vu32(v) ((vector unsigned int) (v)) + +#define C1 0.98078525066375732421875000 /* cos(1 * PI / 16) */ +#define C2 0.92387950420379638671875000 /* cos(2 * PI / 16) */ +#define C3 0.83146959543228149414062500 /* cos(3 * PI / 16) */ +#define C4 0.70710676908493041992187500 /* cos(4 * PI / 16) */ +#define C5 0.55557024478912353515625000 /* cos(5 * PI / 16) */ +#define C6 0.38268342614173889160156250 /* cos(6 * PI / 16) */ +#define C7 0.19509032368659973144531250 /* cos(7 * PI / 16) */ +#define SQRT_2 1.41421353816986083984375000 /* sqrt(2) */ + +#define W0 -(2 * C2) +#define W1 (2 * C6) +#define W2 (SQRT_2 * C6) +#define W3 (SQRT_2 * C3) +#define W4 (SQRT_2 * (-C1 + C3 + C5 - C7)) +#define W5 (SQRT_2 * (C1 + C3 - C5 + C7)) +#define W6 (SQRT_2 * (C1 + C3 + C5 - C7)) +#define W7 (SQRT_2 * (C1 + C3 - C5 - C7)) +#define W8 (SQRT_2 * (C7 - C3)) +#define W9 (SQRT_2 * (-C1 - C3)) +#define WA (SQRT_2 * (-C3 - C5)) +#define WB (SQRT_2 * (C5 - C3)) + +static vector float fdctconsts[3] = { + { W0, W1, W2, W3 }, + { W4, W5, W6, W7 }, + { W8, W9, WA, WB } +}; + +#define LD_W0 vec_splat(cnsts0, 0) +#define LD_W1 vec_splat(cnsts0, 1) +#define LD_W2 vec_splat(cnsts0, 2) +#define LD_W3 vec_splat(cnsts0, 3) +#define LD_W4 vec_splat(cnsts1, 0) +#define LD_W5 vec_splat(cnsts1, 1) +#define LD_W6 vec_splat(cnsts1, 2) +#define LD_W7 vec_splat(cnsts1, 3) +#define LD_W8 vec_splat(cnsts2, 0) +#define LD_W9 vec_splat(cnsts2, 1) +#define LD_WA vec_splat(cnsts2, 2) +#define LD_WB vec_splat(cnsts2, 3) + +#define FDCTROW(b0, b1, b2, b3, b4, b5, b6, b7) /* {{{ */ \ + x0 = vec_add(b0, b7); /* x0 = b0 + b7; */ \ + x7 = vec_sub(b0, b7); /* x7 = b0 - b7; */ \ + x1 = vec_add(b1, b6); /* x1 = b1 + b6; */ \ + x6 = vec_sub(b1, b6); /* x6 = b1 - b6; */ \ + x2 = vec_add(b2, b5); /* x2 = b2 + b5; */ \ + x5 = vec_sub(b2, b5); /* x5 = b2 - b5; */ \ + x3 = vec_add(b3, b4); /* x3 = b3 + b4; */ \ + x4 = vec_sub(b3, b4); /* x4 = b3 - b4; */ \ + \ + b7 = vec_add(x0, x3); /* b7 = x0 + x3; */ \ + b1 = vec_add(x1, x2); /* b1 = x1 + x2; */ \ + b0 = vec_add(b7, b1); /* b0 = b7 + b1; */ \ + b4 = vec_sub(b7, b1); /* b4 = b7 - b1; */ \ + \ + b2 = vec_sub(x0, x3); /* b2 = x0 - x3; */ \ + b6 = vec_sub(x1, x2); /* b6 = x1 - x2; */ \ + b5 = vec_add(b6, b2); /* b5 = b6 + b2; */ \ + cnst = LD_W2; \ + b5 = vec_madd(cnst, b5, mzero); /* b5 = b5 * W2; */ \ + cnst = LD_W1; \ + b2 = vec_madd(cnst, b2, b5); /* b2 = b5 + b2 * W1; */ \ + cnst = LD_W0; \ + b6 = vec_madd(cnst, b6, b5); /* b6 = b5 + b6 * W0; */ \ + \ + x0 = vec_add(x4, x7); /* x0 = x4 + x7; */ \ + x1 = vec_add(x5, x6); /* x1 = x5 + x6; */ \ + x2 = vec_add(x4, x6); /* x2 = x4 + x6; */ \ + x3 = vec_add(x5, x7); /* x3 = x5 + x7; */ \ + x8 = vec_add(x2, x3); /* x8 = x2 + x3; */ \ + cnst = LD_W3; \ + x8 = vec_madd(cnst, x8, mzero); /* x8 = x8 * W3; */ \ + \ + cnst = LD_W8; \ + x0 = vec_madd(cnst, x0, mzero); /* x0 *= W8; */ \ + cnst = LD_W9; \ + x1 = vec_madd(cnst, x1, mzero); /* x1 *= W9; */ \ + cnst = LD_WA; \ + x2 = vec_madd(cnst, x2, x8); /* x2 = x2 * WA + x8; */ \ + cnst = LD_WB; \ + x3 = vec_madd(cnst, x3, x8); /* x3 = x3 * WB + x8; */ \ + \ + cnst = LD_W4; \ + b7 = vec_madd(cnst, x4, x0); /* b7 = x4 * W4 + x0; */ \ + cnst = LD_W5; \ + b5 = vec_madd(cnst, x5, x1); /* b5 = x5 * W5 + x1; */ \ + cnst = LD_W6; \ + b3 = vec_madd(cnst, x6, x1); /* b3 = x6 * W6 + x1; */ \ + cnst = LD_W7; \ + b1 = vec_madd(cnst, x7, x0); /* b1 = x7 * W7 + x0; */ \ + \ + b7 = vec_add(b7, x2); /* b7 = b7 + x2; */ \ + b5 = vec_add(b5, x3); /* b5 = b5 + x3; */ \ + b3 = vec_add(b3, x2); /* b3 = b3 + x2; */ \ + b1 = vec_add(b1, x3) /* b1 = b1 + x3; */ \ + /* }}} */ + +#define FDCTCOL(b0, b1, b2, b3, b4, b5, b6, b7) /* {{{ */ \ + x0 = vec_add(b0, b7); /* x0 = b0 + b7; */ \ + x7 = vec_sub(b0, b7); /* x7 = b0 - b7; */ \ + x1 = vec_add(b1, b6); /* x1 = b1 + b6; */ \ + x6 = vec_sub(b1, b6); /* x6 = b1 - b6; */ \ + x2 = vec_add(b2, b5); /* x2 = b2 + b5; */ \ + x5 = vec_sub(b2, b5); /* x5 = b2 - b5; */ \ + x3 = vec_add(b3, b4); /* x3 = b3 + b4; */ \ + x4 = vec_sub(b3, b4); /* x4 = b3 - b4; */ \ + \ + b7 = vec_add(x0, x3); /* b7 = x0 + x3; */ \ + b1 = vec_add(x1, x2); /* b1 = x1 + x2; */ \ + b0 = vec_add(b7, b1); /* b0 = b7 + b1; */ \ + b4 = vec_sub(b7, b1); /* b4 = b7 - b1; */ \ + \ + b2 = vec_sub(x0, x3); /* b2 = x0 - x3; */ \ + b6 = vec_sub(x1, x2); /* b6 = x1 - x2; */ \ + b5 = vec_add(b6, b2); /* b5 = b6 + b2; */ \ + cnst = LD_W2; \ + b5 = vec_madd(cnst, b5, mzero); /* b5 = b5 * W2; */ \ + cnst = LD_W1; \ + b2 = vec_madd(cnst, b2, b5); /* b2 = b5 + b2 * W1; */ \ + cnst = LD_W0; \ + b6 = vec_madd(cnst, b6, b5); /* b6 = b5 + b6 * W0; */ \ + \ + x0 = vec_add(x4, x7); /* x0 = x4 + x7; */ \ + x1 = vec_add(x5, x6); /* x1 = x5 + x6; */ \ + x2 = vec_add(x4, x6); /* x2 = x4 + x6; */ \ + x3 = vec_add(x5, x7); /* x3 = x5 + x7; */ \ + x8 = vec_add(x2, x3); /* x8 = x2 + x3; */ \ + cnst = LD_W3; \ + x8 = vec_madd(cnst, x8, mzero); /* x8 = x8 * W3; */ \ + \ + cnst = LD_W8; \ + x0 = vec_madd(cnst, x0, mzero); /* x0 *= W8; */ \ + cnst = LD_W9; \ + x1 = vec_madd(cnst, x1, mzero); /* x1 *= W9; */ \ + cnst = LD_WA; \ + x2 = vec_madd(cnst, x2, x8); /* x2 = x2 * WA + x8; */ \ + cnst = LD_WB; \ + x3 = vec_madd(cnst, x3, x8); /* x3 = x3 * WB + x8; */ \ + \ + cnst = LD_W4; \ + b7 = vec_madd(cnst, x4, x0); /* b7 = x4 * W4 + x0; */ \ + cnst = LD_W5; \ + b5 = vec_madd(cnst, x5, x1); /* b5 = x5 * W5 + x1; */ \ + cnst = LD_W6; \ + b3 = vec_madd(cnst, x6, x1); /* b3 = x6 * W6 + x1; */ \ + cnst = LD_W7; \ + b1 = vec_madd(cnst, x7, x0); /* b1 = x7 * W7 + x0; */ \ + \ + b7 = vec_add(b7, x2); /* b7 += x2; */ \ + b5 = vec_add(b5, x3); /* b5 += x3; */ \ + b3 = vec_add(b3, x2); /* b3 += x2; */ \ + b1 = vec_add(b1, x3) /* b1 += x3; */ \ + /* }}} */ + +/* two dimensional discrete cosine transform */ +void ff_fdct_altivec(int16_t *block) +{ + vector signed short *bp; + vector float *cp = fdctconsts; + vector float b00, b10, b20, b30, b40, b50, b60, b70; + vector float b01, b11, b21, b31, b41, b51, b61, b71; + vector float mzero, cnst, cnsts0, cnsts1, cnsts2; + vector float x0, x1, x2, x3, x4, x5, x6, x7, x8; + + /* setup constants {{{ */ + /* mzero = -0.0 */ + mzero = ((vector float) vec_splat_u32(-1)); + mzero = ((vector float) vec_sl(vu32(mzero), vu32(mzero))); + cnsts0 = vec_ld(0, cp); + cp++; + cnsts1 = vec_ld(0, cp); + cp++; + cnsts2 = vec_ld(0, cp); + /* }}} */ + + /* 8x8 matrix transpose (vector short[8]) {{{ */ +#define MERGE_S16(hl, a, b) vec_merge ## hl(vs16(a), vs16(b)) + + bp = (vector signed short *) block; + b00 = ((vector float) vec_ld(0, bp)); + b40 = ((vector float) vec_ld(16 * 4, bp)); + b01 = ((vector float) MERGE_S16(h, b00, b40)); + b11 = ((vector float) MERGE_S16(l, b00, b40)); + bp++; + b10 = ((vector float) vec_ld(0, bp)); + b50 = ((vector float) vec_ld(16 * 4, bp)); + b21 = ((vector float) MERGE_S16(h, b10, b50)); + b31 = ((vector float) MERGE_S16(l, b10, b50)); + bp++; + b20 = ((vector float) vec_ld(0, bp)); + b60 = ((vector float) vec_ld(16 * 4, bp)); + b41 = ((vector float) MERGE_S16(h, b20, b60)); + b51 = ((vector float) MERGE_S16(l, b20, b60)); + bp++; + b30 = ((vector float) vec_ld(0, bp)); + b70 = ((vector float) vec_ld(16 * 4, bp)); + b61 = ((vector float) MERGE_S16(h, b30, b70)); + b71 = ((vector float) MERGE_S16(l, b30, b70)); + + x0 = ((vector float) MERGE_S16(h, b01, b41)); + x1 = ((vector float) MERGE_S16(l, b01, b41)); + x2 = ((vector float) MERGE_S16(h, b11, b51)); + x3 = ((vector float) MERGE_S16(l, b11, b51)); + x4 = ((vector float) MERGE_S16(h, b21, b61)); + x5 = ((vector float) MERGE_S16(l, b21, b61)); + x6 = ((vector float) MERGE_S16(h, b31, b71)); + x7 = ((vector float) MERGE_S16(l, b31, b71)); + + b00 = ((vector float) MERGE_S16(h, x0, x4)); + b10 = ((vector float) MERGE_S16(l, x0, x4)); + b20 = ((vector float) MERGE_S16(h, x1, x5)); + b30 = ((vector float) MERGE_S16(l, x1, x5)); + b40 = ((vector float) MERGE_S16(h, x2, x6)); + b50 = ((vector float) MERGE_S16(l, x2, x6)); + b60 = ((vector float) MERGE_S16(h, x3, x7)); + b70 = ((vector float) MERGE_S16(l, x3, x7)); + +#undef MERGE_S16 + /* }}} */ + + /* Some of the initial calculations can be done as vector short + * before conversion to vector float. The following code section + * takes advantage of this. */ + + /* fdct rows {{{ */ + x0 = ((vector float) vec_add(vs16(b00), vs16(b70))); + x7 = ((vector float) vec_sub(vs16(b00), vs16(b70))); + x1 = ((vector float) vec_add(vs16(b10), vs16(b60))); + x6 = ((vector float) vec_sub(vs16(b10), vs16(b60))); + x2 = ((vector float) vec_add(vs16(b20), vs16(b50))); + x5 = ((vector float) vec_sub(vs16(b20), vs16(b50))); + x3 = ((vector float) vec_add(vs16(b30), vs16(b40))); + x4 = ((vector float) vec_sub(vs16(b30), vs16(b40))); + + b70 = ((vector float) vec_add(vs16(x0), vs16(x3))); + b10 = ((vector float) vec_add(vs16(x1), vs16(x2))); + + b00 = ((vector float) vec_add(vs16(b70), vs16(b10))); + b40 = ((vector float) vec_sub(vs16(b70), vs16(b10))); + +#define CTF0(n) \ + b ## n ## 1 = ((vector float) vec_unpackl(vs16(b ## n ## 0))); \ + b ## n ## 0 = ((vector float) vec_unpackh(vs16(b ## n ## 0))); \ + b ## n ## 1 = vec_ctf(vs32(b ## n ## 1), 0); \ + b ## n ## 0 = vec_ctf(vs32(b ## n ## 0), 0) + + CTF0(0); + CTF0(4); + + b20 = ((vector float) vec_sub(vs16(x0), vs16(x3))); + b60 = ((vector float) vec_sub(vs16(x1), vs16(x2))); + + CTF0(2); + CTF0(6); + +#undef CTF0 + + x0 = vec_add(b60, b20); + x1 = vec_add(b61, b21); + + cnst = LD_W2; + x0 = vec_madd(cnst, x0, mzero); + x1 = vec_madd(cnst, x1, mzero); + cnst = LD_W1; + b20 = vec_madd(cnst, b20, x0); + b21 = vec_madd(cnst, b21, x1); + cnst = LD_W0; + b60 = vec_madd(cnst, b60, x0); + b61 = vec_madd(cnst, b61, x1); + +#define CTFX(x, b) \ + b ## 0 = ((vector float) vec_unpackh(vs16(x))); \ + b ## 1 = ((vector float) vec_unpackl(vs16(x))); \ + b ## 0 = vec_ctf(vs32(b ## 0), 0); \ + b ## 1 = vec_ctf(vs32(b ## 1), 0) + + CTFX(x4, b7); + CTFX(x5, b5); + CTFX(x6, b3); + CTFX(x7, b1); + +#undef CTFX + + x0 = vec_add(b70, b10); + x1 = vec_add(b50, b30); + x2 = vec_add(b70, b30); + x3 = vec_add(b50, b10); + x8 = vec_add(x2, x3); + cnst = LD_W3; + x8 = vec_madd(cnst, x8, mzero); + + cnst = LD_W8; + x0 = vec_madd(cnst, x0, mzero); + cnst = LD_W9; + x1 = vec_madd(cnst, x1, mzero); + cnst = LD_WA; + x2 = vec_madd(cnst, x2, x8); + cnst = LD_WB; + x3 = vec_madd(cnst, x3, x8); + + cnst = LD_W4; + b70 = vec_madd(cnst, b70, x0); + cnst = LD_W5; + b50 = vec_madd(cnst, b50, x1); + cnst = LD_W6; + b30 = vec_madd(cnst, b30, x1); + cnst = LD_W7; + b10 = vec_madd(cnst, b10, x0); + + b70 = vec_add(b70, x2); + b50 = vec_add(b50, x3); + b30 = vec_add(b30, x2); + b10 = vec_add(b10, x3); + + x0 = vec_add(b71, b11); + x1 = vec_add(b51, b31); + x2 = vec_add(b71, b31); + x3 = vec_add(b51, b11); + x8 = vec_add(x2, x3); + cnst = LD_W3; + x8 = vec_madd(cnst, x8, mzero); + + cnst = LD_W8; + x0 = vec_madd(cnst, x0, mzero); + cnst = LD_W9; + x1 = vec_madd(cnst, x1, mzero); + cnst = LD_WA; + x2 = vec_madd(cnst, x2, x8); + cnst = LD_WB; + x3 = vec_madd(cnst, x3, x8); + + cnst = LD_W4; + b71 = vec_madd(cnst, b71, x0); + cnst = LD_W5; + b51 = vec_madd(cnst, b51, x1); + cnst = LD_W6; + b31 = vec_madd(cnst, b31, x1); + cnst = LD_W7; + b11 = vec_madd(cnst, b11, x0); + + b71 = vec_add(b71, x2); + b51 = vec_add(b51, x3); + b31 = vec_add(b31, x2); + b11 = vec_add(b11, x3); + /* }}} */ + + /* 8x8 matrix transpose (vector float[8][2]) {{{ */ + x0 = vec_mergel(b00, b20); + x1 = vec_mergeh(b00, b20); + x2 = vec_mergel(b10, b30); + x3 = vec_mergeh(b10, b30); + + b00 = vec_mergeh(x1, x3); + b10 = vec_mergel(x1, x3); + b20 = vec_mergeh(x0, x2); + b30 = vec_mergel(x0, x2); + + x4 = vec_mergel(b41, b61); + x5 = vec_mergeh(b41, b61); + x6 = vec_mergel(b51, b71); + x7 = vec_mergeh(b51, b71); + + b41 = vec_mergeh(x5, x7); + b51 = vec_mergel(x5, x7); + b61 = vec_mergeh(x4, x6); + b71 = vec_mergel(x4, x6); + + x0 = vec_mergel(b01, b21); + x1 = vec_mergeh(b01, b21); + x2 = vec_mergel(b11, b31); + x3 = vec_mergeh(b11, b31); + + x4 = vec_mergel(b40, b60); + x5 = vec_mergeh(b40, b60); + x6 = vec_mergel(b50, b70); + x7 = vec_mergeh(b50, b70); + + b40 = vec_mergeh(x1, x3); + b50 = vec_mergel(x1, x3); + b60 = vec_mergeh(x0, x2); + b70 = vec_mergel(x0, x2); + + b01 = vec_mergeh(x5, x7); + b11 = vec_mergel(x5, x7); + b21 = vec_mergeh(x4, x6); + b31 = vec_mergel(x4, x6); + /* }}} */ + + FDCTCOL(b00, b10, b20, b30, b40, b50, b60, b70); + FDCTCOL(b01, b11, b21, b31, b41, b51, b61, b71); + + /* round, convert back to short {{{ */ +#define CTS(n) \ + b ## n ## 0 = vec_round(b ## n ## 0); \ + b ## n ## 1 = vec_round(b ## n ## 1); \ + b ## n ## 0 = ((vector float) vec_cts(b ## n ## 0, 0)); \ + b ## n ## 1 = ((vector float) vec_cts(b ## n ## 1, 0)); \ + b ## n ## 0 = ((vector float) vec_pack(vs32(b ## n ## 0), \ + vs32(b ## n ## 1))); \ + vec_st(vs16(b ## n ## 0), 0, bp) + + bp = (vector signed short *) block; + CTS(0); + bp++; + CTS(1); + bp++; + CTS(2); + bp++; + CTS(3); + bp++; + CTS(4); + bp++; + CTS(5); + bp++; + CTS(6); + bp++; + CTS(7); + +#undef CTS + /* }}} */ +} + +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_fdctdsp_init_ppc(FDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) +{ +#if HAVE_ALTIVEC + if (!PPC_ALTIVEC(av_get_cpu_flags())) + return; + + if (!high_bit_depth) { + if (avctx->dct_algo == FF_DCT_AUTO || + avctx->dct_algo == FF_DCT_ALTIVEC) { + c->fdct = ff_fdct_altivec; + } + } +#endif /* HAVE_ALTIVEC */ +} diff --git a/libavcodec/bfin/vp3_bfin.h b/libavcodec/ppc/fdctdsp.h similarity index 84% rename from libavcodec/bfin/vp3_bfin.h rename to libavcodec/ppc/fdctdsp.h index e832de749..89be76846 100644 --- a/libavcodec/bfin/vp3_bfin.h +++ b/libavcodec/ppc/fdctdsp.h @@ -16,12 +16,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef AVCODEC_BFIN_VP3_BFIN_H -#define AVCODEC_BFIN_VP3_BFIN_H +#ifndef AVCODEC_PPC_FDCTDSP_H +#define AVCODEC_PPC_FDCTDSP_H #include -void ff_bfin_vp3_idct(int16_t *block); +void ff_fdct_altivec(int16_t *block); -#endif /* AVCODEC_BFIN_VP3_BFIN_H */ +#endif /* AVCODEC_PPC_FDCTDSP_H */ diff --git a/libavcodec/ppc/fft_altivec.c b/libavcodec/ppc/fft_altivec.c index 2357198f1..675fa33a9 100644 --- a/libavcodec/ppc/fft_altivec.c +++ b/libavcodec/ppc/fft_altivec.c @@ -22,21 +22,26 @@ #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 pair of float + * 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. */ +#if HAVE_VSX +#include "fft_vsx.h" +#else void ff_fft_calc_altivec(FFTContext *s, FFTComplex *z); void ff_fft_calc_interleave_altivec(FFTContext *s, FFTComplex *z); +#endif #if HAVE_GNU_AS && HAVE_ALTIVEC static void imdct_half_altivec(FFTContext *s, FFTSample *output, const FFTSample *input) @@ -93,7 +98,11 @@ static void imdct_half_altivec(FFTContext *s, FFTSample *output, const FFTSample k--; } while(k >= 0); +#if HAVE_VSX + ff_fft_calc_vsx(s, (FFTComplex*)output); +#else ff_fft_calc_altivec(s, (FFTComplex*)output); +#endif /* post rotation + reordering */ j = -n32; @@ -143,10 +152,14 @@ static void imdct_calc_altivec(FFTContext *s, FFTSample *output, const FFTSample av_cold void ff_fft_init_ppc(FFTContext *s) { #if HAVE_GNU_AS && HAVE_ALTIVEC - if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + if (!PPC_ALTIVEC(av_get_cpu_flags())) return; +#if HAVE_VSX + s->fft_calc = ff_fft_calc_interleave_vsx; +#else s->fft_calc = ff_fft_calc_interleave_altivec; +#endif if (s->mdct_bits >= 5) { s->imdct_calc = imdct_calc_altivec; s->imdct_half = imdct_half_altivec; diff --git a/libavcodec/ppc/fft_vsx.c b/libavcodec/ppc/fft_vsx.c new file mode 100644 index 000000000..e92975f74 --- /dev/null +++ b/libavcodec/ppc/fft_vsx.c @@ -0,0 +1,227 @@ +/* + * FFT transform, optimized with VSX built-in functions + * Copyright (c) 2014 Rong Yan + * + * This algorithm (though not any of the implementation details) is + * based on libdjbfft by D. J. Bernstein. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "config.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/fft.h" +#include "libavcodec/fft-internal.h" +#include "fft_vsx.h" + +#if HAVE_VSX + +static void fft32_vsx_interleave(FFTComplex *z) +{ + fft16_vsx_interleave(z); + fft8_vsx_interleave(z+16); + fft8_vsx_interleave(z+24); + pass_vsx_interleave(z,ff_cos_32,4); +} + +static void fft64_vsx_interleave(FFTComplex *z) +{ + fft32_vsx_interleave(z); + fft16_vsx_interleave(z+32); + fft16_vsx_interleave(z+48); + pass_vsx_interleave(z,ff_cos_64, 8); +} +static void fft128_vsx_interleave(FFTComplex *z) +{ + fft64_vsx_interleave(z); + fft32_vsx_interleave(z+64); + fft32_vsx_interleave(z+96); + pass_vsx_interleave(z,ff_cos_128,16); +} +static void fft256_vsx_interleave(FFTComplex *z) +{ + fft128_vsx_interleave(z); + fft64_vsx_interleave(z+128); + fft64_vsx_interleave(z+192); + pass_vsx_interleave(z,ff_cos_256,32); +} +static void fft512_vsx_interleave(FFTComplex *z) +{ + fft256_vsx_interleave(z); + fft128_vsx_interleave(z+256); + fft128_vsx_interleave(z+384); + pass_vsx_interleave(z,ff_cos_512,64); +} +static void fft1024_vsx_interleave(FFTComplex *z) +{ + fft512_vsx_interleave(z); + fft256_vsx_interleave(z+512); + fft256_vsx_interleave(z+768); + pass_vsx_interleave(z,ff_cos_1024,128); + +} +static void fft2048_vsx_interleave(FFTComplex *z) +{ + fft1024_vsx_interleave(z); + fft512_vsx_interleave(z+1024); + fft512_vsx_interleave(z+1536); + pass_vsx_interleave(z,ff_cos_2048,256); +} +static void fft4096_vsx_interleave(FFTComplex *z) +{ + fft2048_vsx_interleave(z); + fft1024_vsx_interleave(z+2048); + fft1024_vsx_interleave(z+3072); + pass_vsx_interleave(z,ff_cos_4096, 512); +} +static void fft8192_vsx_interleave(FFTComplex *z) +{ + fft4096_vsx_interleave(z); + fft2048_vsx_interleave(z+4096); + fft2048_vsx_interleave(z+6144); + pass_vsx_interleave(z,ff_cos_8192,1024); +} +static void fft16384_vsx_interleave(FFTComplex *z) +{ + fft8192_vsx_interleave(z); + fft4096_vsx_interleave(z+8192); + fft4096_vsx_interleave(z+12288); + pass_vsx_interleave(z,ff_cos_16384,2048); +} +static void fft32768_vsx_interleave(FFTComplex *z) +{ + fft16384_vsx_interleave(z); + fft8192_vsx_interleave(z+16384); + fft8192_vsx_interleave(z+24576); + pass_vsx_interleave(z,ff_cos_32768,4096); +} +static void fft65536_vsx_interleave(FFTComplex *z) +{ + fft32768_vsx_interleave(z); + fft16384_vsx_interleave(z+32768); + fft16384_vsx_interleave(z+49152); + pass_vsx_interleave(z,ff_cos_65536,8192); +} + +static void fft32_vsx(FFTComplex *z) +{ + fft16_vsx(z); + fft8_vsx(z+16); + fft8_vsx(z+24); + pass_vsx(z,ff_cos_32,4); +} + +static void fft64_vsx(FFTComplex *z) +{ + fft32_vsx(z); + fft16_vsx(z+32); + fft16_vsx(z+48); + pass_vsx(z,ff_cos_64, 8); +} +static void fft128_vsx(FFTComplex *z) +{ + fft64_vsx(z); + fft32_vsx(z+64); + fft32_vsx(z+96); + pass_vsx(z,ff_cos_128,16); +} +static void fft256_vsx(FFTComplex *z) +{ + fft128_vsx(z); + fft64_vsx(z+128); + fft64_vsx(z+192); + pass_vsx(z,ff_cos_256,32); +} +static void fft512_vsx(FFTComplex *z) +{ + fft256_vsx(z); + fft128_vsx(z+256); + fft128_vsx(z+384); + pass_vsx(z,ff_cos_512,64); +} +static void fft1024_vsx(FFTComplex *z) +{ + fft512_vsx(z); + fft256_vsx(z+512); + fft256_vsx(z+768); + pass_vsx(z,ff_cos_1024,128); + +} +static void fft2048_vsx(FFTComplex *z) +{ + fft1024_vsx(z); + fft512_vsx(z+1024); + fft512_vsx(z+1536); + pass_vsx(z,ff_cos_2048,256); +} +static void fft4096_vsx(FFTComplex *z) +{ + fft2048_vsx(z); + fft1024_vsx(z+2048); + fft1024_vsx(z+3072); + pass_vsx(z,ff_cos_4096, 512); +} +static void fft8192_vsx(FFTComplex *z) +{ + fft4096_vsx(z); + fft2048_vsx(z+4096); + fft2048_vsx(z+6144); + pass_vsx(z,ff_cos_8192,1024); +} +static void fft16384_vsx(FFTComplex *z) +{ + fft8192_vsx(z); + fft4096_vsx(z+8192); + fft4096_vsx(z+12288); + pass_vsx(z,ff_cos_16384,2048); +} +static void fft32768_vsx(FFTComplex *z) +{ + fft16384_vsx(z); + fft8192_vsx(z+16384); + fft8192_vsx(z+24576); + pass_vsx(z,ff_cos_32768,4096); +} +static void fft65536_vsx(FFTComplex *z) +{ + fft32768_vsx(z); + fft16384_vsx(z+32768); + fft16384_vsx(z+49152); + pass_vsx(z,ff_cos_65536,8192); +} + +static void (* const fft_dispatch_vsx[])(FFTComplex*) = { + fft4_vsx, fft8_vsx, fft16_vsx, fft32_vsx, fft64_vsx, fft128_vsx, fft256_vsx, fft512_vsx, fft1024_vsx, + fft2048_vsx, fft4096_vsx, fft8192_vsx, fft16384_vsx, fft32768_vsx, fft65536_vsx, +}; +static void (* const fft_dispatch_vsx_interleave[])(FFTComplex*) = { + fft4_vsx_interleave, fft8_vsx_interleave, fft16_vsx_interleave, fft32_vsx_interleave, fft64_vsx_interleave, + fft128_vsx_interleave, fft256_vsx_interleave, fft512_vsx_interleave, fft1024_vsx_interleave, + fft2048_vsx_interleave, fft4096_vsx_interleave, fft8192_vsx_interleave, fft16384_vsx_interleave, fft32768_vsx_interleave, fft65536_vsx_interleave, +}; +void ff_fft_calc_interleave_vsx(FFTContext *s, FFTComplex *z) +{ + fft_dispatch_vsx_interleave[s->nbits-2](z); +} +void ff_fft_calc_vsx(FFTContext *s, FFTComplex *z) +{ + fft_dispatch_vsx[s->nbits-2](z); +} +#endif /* HAVE_VSX */ diff --git a/libavcodec/ppc/fft_vsx.h b/libavcodec/ppc/fft_vsx.h new file mode 100644 index 000000000..a85475d16 --- /dev/null +++ b/libavcodec/ppc/fft_vsx.h @@ -0,0 +1,830 @@ +#ifndef AVCODEC_PPC_FFT_VSX_H +#define AVCODEC_PPC_FFT_VSX_H +/* + * FFT transform, optimized with VSX built-in functions + * Copyright (c) 2014 Rong Yan Copyright (c) 2009 Loren Merritt + * + * This algorithm (though not any of the implementation details) is + * based on libdjbfft by D. J. Bernstein, and fft_altivec_s.S. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "config.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/fft.h" +#include "libavcodec/fft-internal.h" + +#if HAVE_VSX + +void ff_fft_calc_interleave_vsx(FFTContext *s, FFTComplex *z); +void ff_fft_calc_vsx(FFTContext *s, FFTComplex *z); + + +#define byte_2complex (2*sizeof(FFTComplex)) +#define byte_4complex (4*sizeof(FFTComplex)) +#define byte_6complex (6*sizeof(FFTComplex)) +#define byte_8complex (8*sizeof(FFTComplex)) +#define byte_10complex (10*sizeof(FFTComplex)) +#define byte_12complex (12*sizeof(FFTComplex)) +#define byte_14complex (14*sizeof(FFTComplex)) + +inline static void pass_vsx_interleave(FFTComplex *z, const FFTSample *wre, unsigned int n) +{ + int o1 = n<<1; + int o2 = n<<2; + int o3 = o1+o2; + int i1, i2, i3; + FFTSample* out = (FFTSample*)z; + const FFTSample *wim = wre+o1; + vec_f vz0, vzo1, vzo2, vzo3; + vec_f x0, x1, x2, x3; + vec_f x4, x5, x6, x7; + vec_f x8, x9, x10, x11; + vec_f x12, x13, x14, x15; + vec_f x16, x17, x18, x19; + vec_f x20, x21, x22, x23; + vec_f vz0plus1, vzo1plus1, vzo2plus1, vzo3plus1; + vec_f y0, y1, y2, y3; + vec_f y4, y5, y8, y9; + vec_f y10, y13, y14, y15; + vec_f y16, y17, y18, y19; + vec_f y20, y21, y22, y23; + vec_f wr1, wi1, wr0, wi0; + vec_f wr2, wi2, wr3, wi3; + vec_f xmulwi0, xmulwi1, ymulwi2, ymulwi3; + + n = n-2; + i1 = o1*sizeof(FFTComplex); + i2 = o2*sizeof(FFTComplex); + i3 = o3*sizeof(FFTComplex); + vzo2 = vec_ld(i2, &(out[0])); // zo2.r zo2.i z(o2+1).r z(o2+1).i + vzo2plus1 = vec_ld(i2+16, &(out[0])); + vzo3 = vec_ld(i3, &(out[0])); // zo3.r zo3.i z(o3+1).r z(o3+1).i + vzo3plus1 = vec_ld(i3+16, &(out[0])); + vz0 = vec_ld(0, &(out[0])); // z0.r z0.i z1.r z1.i + vz0plus1 = vec_ld(16, &(out[0])); + vzo1 = vec_ld(i1, &(out[0])); // zo1.r zo1.i z(o1+1).r z(o1+1).i + vzo1plus1 = vec_ld(i1+16, &(out[0])); + + x0 = vec_add(vzo2, vzo3); + x1 = vec_sub(vzo2, vzo3); + y0 = vec_add(vzo2plus1, vzo3plus1); + y1 = vec_sub(vzo2plus1, vzo3plus1); + + wr1 = vec_splats(wre[1]); + wi1 = vec_splats(wim[-1]); + wi2 = vec_splats(wim[-2]); + wi3 = vec_splats(wim[-3]); + wr2 = vec_splats(wre[2]); + wr3 = vec_splats(wre[3]); + + x2 = vec_perm(x0, x1, vcprm(2,s2,3,s3)); + x3 = vec_perm(x0, x1, vcprm(s3,3,s2,2)); + + y4 = vec_perm(y0, y1, vcprm(s1,1,s0,0)); + y5 = vec_perm(y0, y1, vcprm(s3,3,s2,2)); + y2 = vec_perm(y0, y1, vcprm(0,s0,1,s1)); + y3 = vec_perm(y0, y1, vcprm(2,s2,3,s3)); + + ymulwi2 = vec_mul(y4, wi2); + ymulwi3 = vec_mul(y5, wi3); + x4 = vec_mul(x2, wr1); + x5 = vec_mul(x3, wi1); + y8 = vec_madd(y2, wr2, ymulwi2); + y9 = vec_msub(y2, wr2, ymulwi2); + x6 = vec_add(x4, x5); + x7 = vec_sub(x4, x5); + y13 = vec_madd(y3, wr3, ymulwi3); + y14 = vec_msub(y3, wr3, ymulwi3); + + x8 = vec_perm(x6, x7, vcprm(0,1,s2,s3)); + y10 = vec_perm(y8, y9, vcprm(0,1,s2,s3)); + y15 = vec_perm(y13, y14, vcprm(0,1,s2,s3)); + + x9 = vec_perm(x0, x8, vcprm(0,1,s0,s2)); + x10 = vec_perm(x1, x8, vcprm(1,0,s3,s1)); + + y16 = vec_perm(y10, y15, vcprm(0,2,s0,s2)); + y17 = vec_perm(y10, y15, vcprm(3,1,s3,s1)); + + x11 = vec_add(vz0, x9); + x12 = vec_sub(vz0, x9); + x13 = vec_add(vzo1, x10); + x14 = vec_sub(vzo1, x10); + + y18 = vec_add(vz0plus1, y16); + y19 = vec_sub(vz0plus1, y16); + y20 = vec_add(vzo1plus1, y17); + y21 = vec_sub(vzo1plus1, y17); + + x15 = vec_perm(x13, x14, vcprm(0,s1,2,s3)); + x16 = vec_perm(x13, x14, vcprm(s0,1,s2,3)); + y22 = vec_perm(y20, y21, vcprm(0,s1,2,s3)); + y23 = vec_perm(y20, y21, vcprm(s0,1,s2,3)); + + + vec_st(x11, 0, &(out[0])); + vec_st(y18, 16, &(out[0])); + vec_st(x15, i1, &(out[0])); + vec_st(y22, i1+16, &(out[0])); + vec_st(x12, i2, &(out[0])); + vec_st(y19, i2+16, &(out[0])); + vec_st(x16, i3, &(out[0])); + vec_st(y23, i3+16, &(out[0])); + + do { + out += 8; + wre += 4; + wim -= 4; + wr0 = vec_splats(wre[0]); + wr1 = vec_splats(wre[1]); + wi0 = vec_splats(wim[0]); + wi1 = vec_splats(wim[-1]); + + wr2 = vec_splats(wre[2]); + wr3 = vec_splats(wre[3]); + wi2 = vec_splats(wim[-2]); + wi3 = vec_splats(wim[-3]); + + vzo2 = vec_ld(i2, &(out[0])); // zo2.r zo2.i z(o2+1).r z(o2+1).i + vzo2plus1 = vec_ld(i2+16, &(out[0])); + vzo3 = vec_ld(i3, &(out[0])); // zo3.r zo3.i z(o3+1).r z(o3+1).i + vzo3plus1 = vec_ld(i3+16, &(out[0])); + vz0 = vec_ld(0, &(out[0])); // z0.r z0.i z1.r z1.i + vz0plus1 = vec_ld(16, &(out[0])); + vzo1 = vec_ld(i1, &(out[0])); // zo1.r zo1.i z(o1+1).r z(o1+1).i + vzo1plus1 = vec_ld(i1+16, &(out[0])); + + x0 = vec_add(vzo2, vzo3); + x1 = vec_sub(vzo2, vzo3); + + y0 = vec_add(vzo2plus1, vzo3plus1); + y1 = vec_sub(vzo2plus1, vzo3plus1); + + x4 = vec_perm(x0, x1, vcprm(s1,1,s0,0)); + x5 = vec_perm(x0, x1, vcprm(s3,3,s2,2)); + x2 = vec_perm(x0, x1, vcprm(0,s0,1,s1)); + x3 = vec_perm(x0, x1, vcprm(2,s2,3,s3)); + + y2 = vec_perm(y0, y1, vcprm(0,s0,1,s1)); + y3 = vec_perm(y0, y1, vcprm(2,s2,3,s3)); + xmulwi0 = vec_mul(x4, wi0); + xmulwi1 = vec_mul(x5, wi1); + + y4 = vec_perm(y0, y1, vcprm(s1,1,s0,0)); + y5 = vec_perm(y0, y1, vcprm(s3,3,s2,2)); + + x8 = vec_madd(x2, wr0, xmulwi0); + x9 = vec_msub(x2, wr0, xmulwi0); + ymulwi2 = vec_mul(y4, wi2); + ymulwi3 = vec_mul(y5, wi3); + + x13 = vec_madd(x3, wr1, xmulwi1); + x14 = vec_msub(x3, wr1, xmulwi1); + + y8 = vec_madd(y2, wr2, ymulwi2); + y9 = vec_msub(y2, wr2, ymulwi2); + y13 = vec_madd(y3, wr3, ymulwi3); + y14 = vec_msub(y3, wr3, ymulwi3); + + x10 = vec_perm(x8, x9, vcprm(0,1,s2,s3)); + x15 = vec_perm(x13, x14, vcprm(0,1,s2,s3)); + + y10 = vec_perm(y8, y9, vcprm(0,1,s2,s3)); + y15 = vec_perm(y13, y14, vcprm(0,1,s2,s3)); + + x16 = vec_perm(x10, x15, vcprm(0,2,s0,s2)); + x17 = vec_perm(x10, x15, vcprm(3,1,s3,s1)); + + y16 = vec_perm(y10, y15, vcprm(0,2,s0,s2)); + y17 = vec_perm(y10, y15, vcprm(3,1,s3,s1)); + + x18 = vec_add(vz0, x16); + x19 = vec_sub(vz0, x16); + x20 = vec_add(vzo1, x17); + x21 = vec_sub(vzo1, x17); + + y18 = vec_add(vz0plus1, y16); + y19 = vec_sub(vz0plus1, y16); + y20 = vec_add(vzo1plus1, y17); + y21 = vec_sub(vzo1plus1, y17); + + x22 = vec_perm(x20, x21, vcprm(0,s1,2,s3)); + x23 = vec_perm(x20, x21, vcprm(s0,1,s2,3)); + + y22 = vec_perm(y20, y21, vcprm(0,s1,2,s3)); + y23 = vec_perm(y20, y21, vcprm(s0,1,s2,3)); + + vec_st(x18, 0, &(out[0])); + vec_st(y18, 16, &(out[0])); + vec_st(x22, i1, &(out[0])); + vec_st(y22, i1+16, &(out[0])); + vec_st(x19, i2, &(out[0])); + vec_st(y19, i2+16, &(out[0])); + vec_st(x23, i3, &(out[0])); + vec_st(y23, i3+16, &(out[0])); + } while (n-=2); +} + +inline static void fft2_vsx_interleave(FFTComplex *z) +{ + FFTSample r1, i1; + + r1 = z[0].re - z[1].re; + z[0].re += z[1].re; + z[1].re = r1; + + i1 = z[0].im - z[1].im; + z[0].im += z[1].im; + z[1].im = i1; + } + +inline static void fft4_vsx_interleave(FFTComplex *z) +{ + vec_f a, b, c, d; + float* out= (float*)z; + a = vec_ld(0, &(out[0])); + b = vec_ld(byte_2complex, &(out[0])); + + c = vec_perm(a, b, vcprm(0,1,s2,s1)); + d = vec_perm(a, b, vcprm(2,3,s0,s3)); + a = vec_add(c, d); + b = vec_sub(c, d); + + c = vec_perm(a, b, vcprm(0,1,s0,s1)); + d = vec_perm(a, b, vcprm(2,3,s3,s2)); + + a = vec_add(c, d); + b = vec_sub(c, d); + vec_st(a, 0, &(out[0])); + vec_st(b, byte_2complex, &(out[0])); +} + +inline static void fft8_vsx_interleave(FFTComplex *z) +{ + vec_f vz0, vz1, vz2, vz3; + vec_f x0, x1, x2, x3; + vec_f x4, x5, x6, x7; + vec_f x8, x9, x10, x11; + vec_f x12, x13, x14, x15; + vec_f x16, x17, x18, x19; + vec_f x20, x21, x22, x23; + vec_f x24, x25, x26, x27; + vec_f x28, x29, x30, x31; + vec_f x32, x33, x34; + + float* out= (float*)z; + vec_f vc1 = {sqrthalf, sqrthalf, sqrthalf, sqrthalf}; + + vz0 = vec_ld(0, &(out[0])); + vz1 = vec_ld(byte_2complex, &(out[0])); + vz2 = vec_ld(byte_4complex, &(out[0])); + vz3 = vec_ld(byte_6complex, &(out[0])); + + x0 = vec_perm(vz0, vz1, vcprm(0,1,s2,s1)); + x1 = vec_perm(vz0, vz1, vcprm(2,3,s0,s3)); + x2 = vec_perm(vz2, vz3, vcprm(2,1,s0,s1)); + x3 = vec_perm(vz2, vz3, vcprm(0,3,s2,s3)); + + x4 = vec_add(x0, x1); + x5 = vec_sub(x0, x1); + x6 = vec_add(x2, x3); + x7 = vec_sub(x2, x3); + + x8 = vec_perm(x4, x5, vcprm(0,1,s0,s1)); + x9 = vec_perm(x4, x5, vcprm(2,3,s3,s2)); + x10 = vec_perm(x6, x7, vcprm(2,1,s2,s1)); + x11 = vec_perm(x6, x7, vcprm(0,3,s0,s3)); + + x12 = vec_add(x8, x9); + x13 = vec_sub(x8, x9); + x14 = vec_add(x10, x11); + x15 = vec_sub(x10, x11); + x16 = vec_perm(x12, x13, vcprm(0,s0,1,s1)); + x17 = vec_perm(x14, x15, vcprm(0,s0,1,s1)); + x18 = vec_perm(x16, x17, vcprm(s0,s3,s2,s1)); + x19 = vec_add(x16, x18); // z0.r z2.r z0.i z2.i + x20 = vec_sub(x16, x18); // z4.r z6.r z4.i z6.i + + x21 = vec_perm(x12, x13, vcprm(2,s2,3,s3)); + x22 = vec_perm(x14, x15, vcprm(2,3,s2,s3)); + x23 = vec_perm(x14, x15, vcprm(3,2,s3,s2)); + x24 = vec_add(x22, x23); + x25 = vec_sub(x22, x23); + x26 = vec_mul( vec_perm(x24, x25, vcprm(2,s2,0,s0)), vc1); + + x27 = vec_add(x21, x26); // z1.r z7.r z1.i z3.i + x28 = vec_sub(x21, x26); //z5.r z3.r z5.i z7.i + + x29 = vec_perm(x19, x27, vcprm(0,2,s0,s2)); // z0.r z0.i z1.r z1.i + x30 = vec_perm(x19, x27, vcprm(1,3,s1,s3)); // z2.r z2.i z7.r z3.i + x31 = vec_perm(x20, x28, vcprm(0,2,s0,s2)); // z4.r z4.i z5.r z5.i + x32 = vec_perm(x20, x28, vcprm(1,3,s1,s3)); // z6.r z6.i z3.r z7.i + x33 = vec_perm(x30, x32, vcprm(0,1,s2,3)); // z2.r z2.i z3.r z3.i + x34 = vec_perm(x30, x32, vcprm(s0,s1,2,s3)); // z6.r z6.i z7.r z7.i + + vec_st(x29, 0, &(out[0])); + vec_st(x33, byte_2complex, &(out[0])); + vec_st(x31, byte_4complex, &(out[0])); + vec_st(x34, byte_6complex, &(out[0])); +} + +inline static void fft16_vsx_interleave(FFTComplex *z) +{ + float* out= (float*)z; + vec_f vc0 = {sqrthalf, sqrthalf, sqrthalf, sqrthalf}; + vec_f vc1 = {ff_cos_16[1], ff_cos_16[1], ff_cos_16[1], ff_cos_16[1]}; + vec_f vc2 = {ff_cos_16[3], ff_cos_16[3], ff_cos_16[3], ff_cos_16[3]}; + vec_f vz0, vz1, vz2, vz3; + vec_f vz4, vz5, vz6, vz7; + vec_f x0, x1, x2, x3; + vec_f x4, x5, x6, x7; + vec_f x8, x9, x10, x11; + vec_f x12, x13, x14, x15; + vec_f x16, x17, x18, x19; + vec_f x20, x21, x22, x23; + vec_f x24, x25, x26, x27; + vec_f x28, x29, x30, x31; + vec_f x32, x33, x34, x35; + vec_f x36, x37, x38, x39; + vec_f x40, x41, x42, x43; + vec_f x44, x45, x46, x47; + vec_f x48, x49, x50, x51; + vec_f x52, x53, x54, x55; + vec_f x56, x57, x58, x59; + vec_f x60, x61, x62, x63; + vec_f x64, x65, x66, x67; + vec_f x68, x69, x70, x71; + vec_f x72, x73, x74, x75; + vec_f x76, x77, x78, x79; + vec_f x80, x81, x82, x83; + vec_f x84, x85, x86; + + vz0 = vec_ld(0, &(out[0])); + vz1 = vec_ld(byte_2complex, &(out[0])); + vz2 = vec_ld(byte_4complex, &(out[0])); + vz3 = vec_ld(byte_6complex, &(out[0])); + vz4 = vec_ld(byte_8complex, &(out[0])); + vz5 = vec_ld(byte_10complex, &(out[0])); + vz6 = vec_ld(byte_12complex, &(out[0])); + vz7 = vec_ld(byte_14complex, &(out[0])); + + x0 = vec_perm(vz0, vz1, vcprm(0,1,s2,s1)); + x1 = vec_perm(vz0, vz1, vcprm(2,3,s0,s3)); + x2 = vec_perm(vz2, vz3, vcprm(0,1,s0,s1)); + x3 = vec_perm(vz2, vz3, vcprm(2,3,s2,s3)); + + x4 = vec_perm(vz4, vz5, vcprm(0,1,s2,s1)); + x5 = vec_perm(vz4, vz5, vcprm(2,3,s0,s3)); + x6 = vec_perm(vz6, vz7, vcprm(0,1,s2,s1)); + x7 = vec_perm(vz6, vz7, vcprm(2,3,s0,s3)); + + x8 = vec_add(x0, x1); + x9 = vec_sub(x0, x1); + x10 = vec_add(x2, x3); + x11 = vec_sub(x2, x3); + + x12 = vec_add(x4, x5); + x13 = vec_sub(x4, x5); + x14 = vec_add(x6, x7); + x15 = vec_sub(x6, x7); + + x16 = vec_perm(x8, x9, vcprm(0,1,s0,s1)); + x17 = vec_perm(x8, x9, vcprm(2,3,s3,s2)); + x18 = vec_perm(x10, x11, vcprm(2,1,s1,s2)); + x19 = vec_perm(x10, x11, vcprm(0,3,s0,s3)); + x20 = vec_perm(x12, x14, vcprm(0,1,s0, s1)); + x21 = vec_perm(x12, x14, vcprm(2,3,s2,s3)); + x22 = vec_perm(x13, x15, vcprm(0,1,s0,s1)); + x23 = vec_perm(x13, x15, vcprm(3,2,s3,s2)); + + x24 = vec_add(x16, x17); + x25 = vec_sub(x16, x17); + x26 = vec_add(x18, x19); + x27 = vec_sub(x18, x19); + x28 = vec_add(x20, x21); + x29 = vec_sub(x20, x21); + x30 = vec_add(x22, x23); + x31 = vec_sub(x22, x23); + + x32 = vec_add(x24, x26); + x33 = vec_sub(x24, x26); + x34 = vec_perm(x32, x33, vcprm(0,1,s0,s1)); + + x35 = vec_perm(x28, x29, vcprm(2,1,s1,s2)); + x36 = vec_perm(x28, x29, vcprm(0,3,s0,s3)); + x37 = vec_add(x35, x36); + x38 = vec_sub(x35, x36); + x39 = vec_perm(x37, x38, vcprm(0,1,s1,s0)); + + x40 = vec_perm(x27, x38, vcprm(3,2,s2,s3)); + x41 = vec_perm(x26, x37, vcprm(2,3,s3,s2)); + x42 = vec_add(x40, x41); + x43 = vec_sub(x40, x41); + x44 = vec_mul(x42, vc0); + x45 = vec_mul(x43, vc0); + + x46 = vec_add(x34, x39); // z0.r z0.i z4.r z4.i + x47 = vec_sub(x34, x39); // z8.r z8.i z12.r z12.i + + x48 = vec_perm(x30, x31, vcprm(2,1,s1,s2)); + x49 = vec_perm(x30, x31, vcprm(0,3,s3,s0)); + x50 = vec_add(x48, x49); + x51 = vec_sub(x48, x49); + x52 = vec_mul(x50, vc1); + x53 = vec_mul(x50, vc2); + x54 = vec_mul(x51, vc1); + x55 = vec_mul(x51, vc2); + + x56 = vec_perm(x24, x25, vcprm(2,3,s2,s3)); + x57 = vec_perm(x44, x45, vcprm(0,1,s1,s0)); + x58 = vec_add(x56, x57); + x59 = vec_sub(x56, x57); + + x60 = vec_perm(x54, x55, vcprm(1,0,3,2)); + x61 = vec_perm(x54, x55, vcprm(s1,s0,s3,s2)); + x62 = vec_add(x52, x61); + x63 = vec_sub(x52, x61); + x64 = vec_add(x60, x53); + x65 = vec_sub(x60, x53); + x66 = vec_perm(x62, x64, vcprm(0,1,s3,s2)); + x67 = vec_perm(x63, x65, vcprm(s0,s1,3,2)); + + x68 = vec_add(x58, x66); // z1.r z1.i z3.r z3.i + x69 = vec_sub(x58, x66); // z9.r z9.i z11.r z11.i + x70 = vec_add(x59, x67); // z5.r z5.i z15.r z15.i + x71 = vec_sub(x59, x67); // z13.r z13.i z7.r z7.i + + x72 = vec_perm(x25, x27, vcprm(s1,s0,s2,s3)); + x73 = vec_add(x25, x72); + x74 = vec_sub(x25, x72); + x75 = vec_perm(x73, x74, vcprm(0,1,s0,s1)); + x76 = vec_perm(x44, x45, vcprm(3,2,s2,s3)); + x77 = vec_add(x75, x76); // z2.r z2.i z6.r z6.i + x78 = vec_sub(x75, x76); // z10.r z10.i z14.r z14.i + + x79 = vec_perm(x46, x68, vcprm(0,1,s0,s1)); // z0.r z0.i z1.r z1.i + x80 = vec_perm(x77, x68, vcprm(0,1,s2,s3)); // z2.r z2.i z3.r z3.i + x81 = vec_perm(x46, x70, vcprm(2,3,s0,s1)); // z4.r z4.i z5.r z5.i + x82 = vec_perm(x71, x77, vcprm(s2,s3,2,3)); // z6.r z6.i z7.r z7.i + vec_st(x79, 0, &(out[0])); + vec_st(x80, byte_2complex, &(out[0])); + vec_st(x81, byte_4complex, &(out[0])); + vec_st(x82, byte_6complex, &(out[0])); + x83 = vec_perm(x47, x69, vcprm(0,1,s0,s1)); // z8.r z8.i z9.r z9.i + x84 = vec_perm(x78, x69, vcprm(0,1,s2,s3)); // z10.r z10.i z11.r z11.i + x85 = vec_perm(x47, x71, vcprm(2,3,s0,s1)); // z12.r z12.i z13.r z13.i + x86 = vec_perm(x70, x78, vcprm(s2,s3,2,3)); // z14.r z14.i z15.r z15.i + vec_st(x83, byte_8complex, &(out[0])); + vec_st(x84, byte_10complex, &(out[0])); + vec_st(x85, byte_12complex, &(out[0])); + vec_st(x86, byte_14complex, &(out[0])); +} + +inline static void fft4_vsx(FFTComplex *z) +{ + vec_f a, b, c, d; + float* out= (float*)z; + a = vec_ld(0, &(out[0])); + b = vec_ld(byte_2complex, &(out[0])); + + c = vec_perm(a, b, vcprm(0,1,s2,s1)); + d = vec_perm(a, b, vcprm(2,3,s0,s3)); + a = vec_add(c, d); + b = vec_sub(c, d); + + c = vec_perm(a,b, vcprm(0,s0,1,s1)); + d = vec_perm(a, b, vcprm(2,s3,3,s2)); + + a = vec_add(c, d); + b = vec_sub(c, d); + + c = vec_perm(a, b, vcprm(0,1,s0,s1)); + d = vec_perm(a, b, vcprm(2,3,s2,s3)); + + vec_st(c, 0, &(out[0])); + vec_st(d, byte_2complex, &(out[0])); + return; +} + +inline static void fft8_vsx(FFTComplex *z) +{ + vec_f vz0, vz1, vz2, vz3; + vec_f vz4, vz5, vz6, vz7, vz8; + + float* out= (float*)z; + vec_f vc0 = {0.0, 0.0, 0.0, 0.0}; + vec_f vc1 = {-sqrthalf, sqrthalf, sqrthalf, -sqrthalf}; + vec_f vc2 = {sqrthalf, sqrthalf, sqrthalf, sqrthalf}; + + vz0 = vec_ld(0, &(out[0])); + vz1 = vec_ld(byte_2complex, &(out[0])); + vz2 = vec_ld(byte_4complex, &(out[0])); + vz3 = vec_ld(byte_6complex, &(out[0])); + + vz6 = vec_perm(vz2, vz3, vcprm(0,s0,1,s1)); + vz7 = vec_perm(vz2, vz3, vcprm(2,s2,3,s3)); + vz4 = vec_perm(vz0, vz1, vcprm(0,1,s2,s1)); + vz5 = vec_perm(vz0, vz1, vcprm(2,3,s0,s3)); + + vz2 = vec_add(vz6, vz7); + vz3 = vec_sub(vz6, vz7); + vz8 = vec_perm(vz3, vz3, vcprm(2,3,0,1)); + + vz0 = vec_add(vz4, vz5); + vz1 = vec_sub(vz4, vz5); + + vz3 = vec_madd(vz3, vc1, vc0); + vz3 = vec_madd(vz8, vc2, vz3); + + vz4 = vec_perm(vz0, vz1, vcprm(0,s0,1,s1)); + vz5 = vec_perm(vz0, vz1, vcprm(2,s3,3,s2)); + vz6 = vec_perm(vz2, vz3, vcprm(1,2,s3,s0)); + vz7 = vec_perm(vz2, vz3, vcprm(0,3,s2,s1)); + + vz0 = vec_add(vz4, vz5); + vz1 = vec_sub(vz4, vz5); + vz2 = vec_add(vz6, vz7); + vz3 = vec_sub(vz6, vz7); + + vz4 = vec_perm(vz0, vz1, vcprm(0,1,s0,s1)); + vz5 = vec_perm(vz0, vz1, vcprm(2,3,s2,s3)); + vz6 = vec_perm(vz2, vz3, vcprm(0,2,s1,s3)); + vz7 = vec_perm(vz2, vz3, vcprm(1,3,s0,s2)); + + + vz2 = vec_sub(vz4, vz6); + vz3 = vec_sub(vz5, vz7); + + vz0 = vec_add(vz4, vz6); + vz1 = vec_add(vz5, vz7); + + vec_st(vz0, 0, &(out[0])); + vec_st(vz1, byte_2complex, &(out[0])); + vec_st(vz2, byte_4complex, &(out[0])); + vec_st(vz3, byte_6complex, &(out[0])); + return; +} + +inline static void fft16_vsx(FFTComplex *z) +{ + float* out= (float*)z; + vec_f vc0 = {0.0, 0.0, 0.0, 0.0}; + vec_f vc1 = {-sqrthalf, sqrthalf, sqrthalf, -sqrthalf}; + vec_f vc2 = {sqrthalf, sqrthalf, sqrthalf, sqrthalf}; + vec_f vc3 = {1.0, 0.92387953, sqrthalf, 0.38268343}; + vec_f vc4 = {0.0, 0.38268343, sqrthalf, 0.92387953}; + vec_f vc5 = {-0.0, -0.38268343, -sqrthalf, -0.92387953}; + + vec_f vz0, vz1, vz2, vz3; + vec_f vz4, vz5, vz6, vz7; + vec_f vz8, vz9, vz10, vz11; + vec_f vz12, vz13; + + vz0 = vec_ld(byte_8complex, &(out[0])); + vz1 = vec_ld(byte_10complex, &(out[0])); + vz2 = vec_ld(byte_12complex, &(out[0])); + vz3 = vec_ld(byte_14complex, &(out[0])); + + vz4 = vec_perm(vz0, vz1, vcprm(0,1,s2,s1)); + vz5 = vec_perm(vz0, vz1, vcprm(2,3,s0,s3)); + vz6 = vec_perm(vz2, vz3, vcprm(0,1,s2,s1)); + vz7 = vec_perm(vz2, vz3, vcprm(2,3,s0,s3)); + + vz0 = vec_add(vz4, vz5); + vz1= vec_sub(vz4, vz5); + vz2 = vec_add(vz6, vz7); + vz3 = vec_sub(vz6, vz7); + + vz4 = vec_perm(vz0, vz1, vcprm(0,s0,1,s1)); + vz5 = vec_perm(vz0, vz1, vcprm(2,s3,3,s2)); + vz6 = vec_perm(vz2, vz3, vcprm(0,s0,1,s1)); + vz7 = vec_perm(vz2, vz3, vcprm(2,s3,3,s2)); + + vz0 = vec_add(vz4, vz5); + vz1 = vec_sub(vz4, vz5); + vz2 = vec_add(vz6, vz7); + vz3 = vec_sub(vz6, vz7); + + vz4 = vec_perm(vz0, vz1, vcprm(0,1,s0,s1)); + vz5 = vec_perm(vz0, vz1, vcprm(2,3,s2,s3)); + + vz6 = vec_perm(vz2, vz3, vcprm(0,1,s0,s1)); + vz7 = vec_perm(vz2, vz3, vcprm(2,3,s2,s3)); + + vz0 = vec_ld(0, &(out[0])); + vz1 = vec_ld(byte_2complex, &(out[0])); + vz2 = vec_ld(byte_4complex, &(out[0])); + vz3 = vec_ld(byte_6complex, &(out[0])); + vz10 = vec_perm(vz2, vz3, vcprm(0,s0,1,s1)); + vz11 = vec_perm(vz2, vz3, vcprm(2,s2,3,s3)); + vz8 = vec_perm(vz0, vz1, vcprm(0,1,s2,s1)); + vz9 = vec_perm(vz0, vz1, vcprm(2,3,s0,s3)); + + vz2 = vec_add(vz10, vz11); + vz3 = vec_sub(vz10, vz11); + vz12 = vec_perm(vz3, vz3, vcprm(2,3,0,1)); + vz0 = vec_add(vz8, vz9); + vz1 = vec_sub(vz8, vz9); + + vz3 = vec_madd(vz3, vc1, vc0); + vz3 = vec_madd(vz12, vc2, vz3); + vz8 = vec_perm(vz0, vz1, vcprm(0,s0,1,s1)); + vz9 = vec_perm(vz0, vz1, vcprm(2,s3,3,s2)); + vz10 = vec_perm(vz2, vz3, vcprm(1,2,s3,s0)); + vz11 = vec_perm(vz2, vz3, vcprm(0,3,s2,s1)); + + vz0 = vec_add(vz8, vz9); + vz1 = vec_sub(vz8, vz9); + vz2 = vec_add(vz10, vz11); + vz3 = vec_sub(vz10, vz11); + + vz8 = vec_perm(vz0, vz1, vcprm(0,1,s0,s1)); + vz9 = vec_perm(vz0, vz1, vcprm(2,3,s2,s3)); + vz10 = vec_perm(vz2, vz3, vcprm(0,2,s1,s3)); + vz11 = vec_perm(vz2, vz3, vcprm(1,3,s0,s2)); + + vz2 = vec_sub(vz8, vz10); + vz3 = vec_sub(vz9, vz11); + vz0 = vec_add(vz8, vz10); + vz1 = vec_add(vz9, vz11); + + vz8 = vec_madd(vz4, vc3, vc0); + vz9 = vec_madd(vz5, vc3, vc0); + vz10 = vec_madd(vz6, vc3, vc0); + vz11 = vec_madd(vz7, vc3, vc0); + + vz8 = vec_madd(vz5, vc4, vz8); + vz9 = vec_madd(vz4, vc5, vz9); + vz10 = vec_madd(vz7, vc5, vz10); + vz11 = vec_madd(vz6, vc4, vz11); + + vz12 = vec_sub(vz10, vz8); + vz10 = vec_add(vz10, vz8); + + vz13 = vec_sub(vz9, vz11); + vz11 = vec_add(vz9, vz11); + + vz4 = vec_sub(vz0, vz10); + vz0 = vec_add(vz0, vz10); + + vz7= vec_sub(vz3, vz12); + vz3= vec_add(vz3, vz12); + + vz5 = vec_sub(vz1, vz11); + vz1 = vec_add(vz1, vz11); + + vz6 = vec_sub(vz2, vz13); + vz2 = vec_add(vz2, vz13); + + vec_st(vz0, 0, &(out[0])); + vec_st(vz1, byte_2complex, &(out[0])); + vec_st(vz2, byte_4complex, &(out[0])); + vec_st(vz3, byte_6complex, &(out[0])); + vec_st(vz4, byte_8complex, &(out[0])); + vec_st(vz5, byte_10complex, &(out[0])); + vec_st(vz6, byte_12complex, &(out[0])); + vec_st(vz7, byte_14complex, &(out[0])); + return; + +} +inline static void pass_vsx(FFTComplex * z, const FFTSample * wre, unsigned int n) +{ + int o1 = n<<1; + int o2 = n<<2; + int o3 = o1+o2; + int i1, i2, i3; + FFTSample* out = (FFTSample*)z; + const FFTSample *wim = wre+o1; + vec_f v0, v1, v2, v3; + vec_f v4, v5, v6, v7; + vec_f v8, v9, v10, v11; + vec_f v12, v13; + + n = n-2; + i1 = o1*sizeof(FFTComplex); + i2 = o2*sizeof(FFTComplex); + i3 = o3*sizeof(FFTComplex); + + v8 = vec_ld(0, &(wre[0])); + v10 = vec_ld(0, &(wim[0])); + v9 = vec_ld(0, &(wim[-4])); + v9 = vec_perm(v9, v10, vcprm(s0,3,2,1)); + + v4 = vec_ld(i2, &(out[0])); + v5 = vec_ld(i2+16, &(out[0])); + v6 = vec_ld(i3, &(out[0])); + v7 = vec_ld(i3+16, &(out[0])); + v10 = vec_mul(v4, v8); // r2*wre + v11 = vec_mul(v5, v8); // i2*wre + v12 = vec_mul(v6, v8); // r3*wre + v13 = vec_mul(v7, v8); // i3*wre + + v0 = vec_ld(0, &(out[0])); // r0 + v3 = vec_ld(i1+16, &(out[0])); // i1 + v10 = vec_madd(v5, v9, v10); // r2*wim + v11 = vec_nmsub(v4, v9, v11); // i2*wim + v12 = vec_nmsub(v7, v9, v12); // r3*wim + v13 = vec_madd(v6, v9, v13); // i3*wim + + v1 = vec_ld(16, &(out[0])); // i0 + v2 = vec_ld(i1, &(out[0])); // r1 + v8 = vec_sub(v12, v10); + v12 = vec_add(v12, v10); + v9 = vec_sub(v11, v13); + v13 = vec_add(v11, v13); + v4 = vec_sub(v0, v12); + v0 = vec_add(v0, v12); + v7 = vec_sub(v3, v8); + v3 = vec_add(v3, v8); + + vec_st(v0, 0, &(out[0])); // r0 + vec_st(v3, i1+16, &(out[0])); // i1 + vec_st(v4, i2, &(out[0])); // r2 + vec_st(v7, i3+16, &(out[0]));// i3 + + v5 = vec_sub(v1, v13); + v1 = vec_add(v1, v13); + v6 = vec_sub(v2, v9); + v2 = vec_add(v2, v9); + + vec_st(v1, 16, &(out[0])); // i0 + vec_st(v2, i1, &(out[0])); // r1 + vec_st(v5, i2+16, &(out[0])); // i2 + vec_st(v6, i3, &(out[0])); // r3 + + do { + out += 8; + wre += 4; + wim -= 4; + + v8 = vec_ld(0, &(wre[0])); + v10 = vec_ld(0, &(wim[0])); + v9 = vec_ld(0, &(wim[-4])); + v9 = vec_perm(v9, v10, vcprm(s0,3,2,1)); + + v4 = vec_ld(i2, &(out[0])); // r2 + v5 = vec_ld(i2+16, &(out[0])); // i2 + v6 = vec_ld(i3, &(out[0])); // r3 + v7 = vec_ld(i3+16, &(out[0]));// i3 + v10 = vec_mul(v4, v8); // r2*wre + v11 = vec_mul(v5, v8); // i2*wre + v12 = vec_mul(v6, v8); // r3*wre + v13 = vec_mul(v7, v8); // i3*wre + + v0 = vec_ld(0, &(out[0])); // r0 + v3 = vec_ld(i1+16, &(out[0])); // i1 + v10 = vec_madd(v5, v9, v10); // r2*wim + v11 = vec_nmsub(v4, v9, v11); // i2*wim + v12 = vec_nmsub(v7, v9, v12); // r3*wim + v13 = vec_madd(v6, v9, v13); // i3*wim + + v1 = vec_ld(16, &(out[0])); // i0 + v2 = vec_ld(i1, &(out[0])); // r1 + v8 = vec_sub(v12, v10); + v12 = vec_add(v12, v10); + v9 = vec_sub(v11, v13); + v13 = vec_add(v11, v13); + v4 = vec_sub(v0, v12); + v0 = vec_add(v0, v12); + v7 = vec_sub(v3, v8); + v3 = vec_add(v3, v8); + + vec_st(v0, 0, &(out[0])); // r0 + vec_st(v3, i1+16, &(out[0])); // i1 + vec_st(v4, i2, &(out[0])); // r2 + vec_st(v7, i3+16, &(out[0])); // i3 + + v5 = vec_sub(v1, v13); + v1 = vec_add(v1, v13); + v6 = vec_sub(v2, v9); + v2 = vec_add(v2, v9); + + vec_st(v1, 16, &(out[0])); // i0 + vec_st(v2, i1, &(out[0])); // r1 + vec_st(v5, i2+16, &(out[0])); // i2 + vec_st(v6, i3, &(out[0])); // r3 + } while (n-=2); +} + +#endif + +#endif /* AVCODEC_PPC_FFT_VSX_H */ diff --git a/libavcodec/ppc/fmtconvert_altivec.c b/libavcodec/ppc/fmtconvert_altivec.c index cd32e3938..10a7169d1 100644 --- a/libavcodec/ppc/fmtconvert_altivec.c +++ b/libavcodec/ppc/fmtconvert_altivec.c @@ -22,9 +22,9 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/mem.h" +#include "libavutil/ppc/cpu.h" #include "libavutil/ppc/util_altivec.h" #include "libavcodec/fmtconvert.h" -#include "dsputil_altivec.h" #if HAVE_ALTIVEC @@ -165,7 +165,7 @@ av_cold void ff_fmt_convert_init_ppc(FmtConvertContext *c, AVCodecContext *avctx) { #if HAVE_ALTIVEC - if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + if (!PPC_ALTIVEC(av_get_cpu_flags())) return; c->int32_to_float_fmul_scalar = int32_to_float_fmul_scalar_altivec; diff --git a/libavcodec/ppc/gmc_altivec.c b/libavcodec/ppc/gmc_altivec.c deleted file mode 100644 index 45d850a29..000000000 --- a/libavcodec/ppc/gmc_altivec.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * GMC (Global Motion Compensation) - * AltiVec-enabled - * Copyright (c) 2003 Romain Dolbeau - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/mem.h" -#include "libavutil/ppc/types_altivec.h" -#include "libavutil/ppc/util_altivec.h" -#include "dsputil_altivec.h" - -/* - altivec-enhanced gmc1. ATM this code assume stride is a multiple of 8, - to preserve proper dst alignment. -*/ -void ff_gmc1_altivec(uint8_t *dst /* align 8 */, uint8_t *src /* align1 */, int stride, int h, int x16, int y16, int rounder) -{ - const DECLARE_ALIGNED(16, unsigned short, rounder_a) = rounder; - const DECLARE_ALIGNED(16, unsigned short, ABCD)[8] = - { - (16-x16)*(16-y16), /* A */ - ( x16)*(16-y16), /* B */ - (16-x16)*( y16), /* C */ - ( x16)*( y16), /* D */ - 0, 0, 0, 0 /* padding */ - }; - register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0); - register const vector unsigned short vcsr8 = (const vector unsigned short)vec_splat_u16(8); - register vector unsigned char dstv, dstv2, src_0, src_1, srcvA, srcvB, srcvC, srcvD; - register vector unsigned short Av, Bv, Cv, Dv, rounderV, tempA, tempB, tempC, tempD; - int i; - unsigned long dst_odd = (unsigned long)dst & 0x0000000F; - unsigned long src_really_odd = (unsigned long)src & 0x0000000F; - - tempA = vec_ld(0, (const unsigned short*)ABCD); - Av = vec_splat(tempA, 0); - Bv = vec_splat(tempA, 1); - Cv = vec_splat(tempA, 2); - Dv = vec_splat(tempA, 3); - - rounderV = vec_splat((vec_u16)vec_lde(0, &rounder_a), 0); - - // we'll be able to pick-up our 9 char elements - // at src from those 32 bytes - // we load the first batch here, as inside the loop - // we can re-use 'src+stride' from one iteration - // as the 'src' of the next. - src_0 = vec_ld(0, src); - src_1 = vec_ld(16, src); - srcvA = vec_perm(src_0, src_1, vec_lvsl(0, src)); - - if (src_really_odd != 0x0000000F) { - // if (src & 0xF) == 0xF, then (src+1) is properly aligned - // on the second vector. - srcvB = vec_perm(src_0, src_1, vec_lvsl(1, src)); - } else { - srcvB = src_1; - } - srcvA = vec_mergeh(vczero, srcvA); - srcvB = vec_mergeh(vczero, srcvB); - - for(i=0; i 8; - if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + if (!PPC_ALTIVEC(av_get_cpu_flags())) return; if (!high_bit_depth) { diff --git a/libavcodec/ppc/h264dsp.c b/libavcodec/ppc/h264dsp.c index f532197a5..7fc7e0bc7 100644 --- a/libavcodec/ppc/h264dsp.c +++ b/libavcodec/ppc/h264dsp.c @@ -22,6 +22,7 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/intreadwrite.h" +#include "libavutil/ppc/cpu.h" #include "libavutil/ppc/types_altivec.h" #include "libavutil/ppc/util_altivec.h" #include "libavcodec/h264data.h" @@ -745,7 +746,7 @@ av_cold void ff_h264dsp_init_ppc(H264DSPContext *c, const int bit_depth, const int chroma_format_idc) { #if HAVE_ALTIVEC - if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + if (!PPC_ALTIVEC(av_get_cpu_flags())) return; if (bit_depth == 8) { diff --git a/libavcodec/ppc/h264qpel.c b/libavcodec/ppc/h264qpel.c index 1f50ec992..d4e5008c6 100644 --- a/libavcodec/ppc/h264qpel.c +++ b/libavcodec/ppc/h264qpel.c @@ -22,10 +22,11 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/intreadwrite.h" +#include "libavutil/ppc/cpu.h" #include "libavutil/ppc/types_altivec.h" #include "libavutil/ppc/util_altivec.h" #include "libavcodec/h264qpel.h" -#include "dsputil_altivec.h" +#include "hpeldsp_altivec.h" #if HAVE_ALTIVEC @@ -288,7 +289,7 @@ av_cold void ff_h264qpel_init_ppc(H264QpelContext *c, int bit_depth) #if HAVE_ALTIVEC const int high_bit_depth = bit_depth > 8; - if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + if (!PPC_ALTIVEC(av_get_cpu_flags())) return; if (!high_bit_depth) { diff --git a/libavcodec/ppc/hpeldsp_altivec.c b/libavcodec/ppc/hpeldsp_altivec.c index 345ec39b9..7c3b5a1d0 100644 --- a/libavcodec/ppc/hpeldsp_altivec.c +++ b/libavcodec/ppc/hpeldsp_altivec.c @@ -28,10 +28,11 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" #include "libavutil/ppc/types_altivec.h" #include "libavutil/ppc/util_altivec.h" #include "libavcodec/hpeldsp.h" -#include "dsputil_altivec.h" +#include "hpeldsp_altivec.h" #if HAVE_ALTIVEC /* next one assumes that ((line_size % 16) == 0) */ @@ -449,7 +450,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 (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + if (!PPC_ALTIVEC(av_get_cpu_flags())) return; c->avg_pixels_tab[0][0] = ff_avg_pixels16_altivec; diff --git a/libavcodec/ppc/dsputil_altivec.h b/libavcodec/ppc/hpeldsp_altivec.h similarity index 59% rename from libavcodec/ppc/dsputil_altivec.h rename to libavcodec/ppc/hpeldsp_altivec.h index 0e769ab06..590809f53 100644 --- a/libavcodec/ppc/dsputil_altivec.h +++ b/libavcodec/ppc/hpeldsp_altivec.h @@ -20,24 +20,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVCODEC_PPC_DSPUTIL_ALTIVEC_H -#define AVCODEC_PPC_DSPUTIL_ALTIVEC_H +#ifndef AVCODEC_PPC_HPELDSP_ALTIVEC_H +#define AVCODEC_PPC_HPELDSP_ALTIVEC_H +#include #include -#include "libavcodec/dsputil.h" -void ff_put_pixels16_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); +void ff_avg_pixels16_altivec(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_altivec(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); -void ff_avg_pixels16_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); - -void ff_fdct_altivec(int16_t *block); -void ff_gmc1_altivec(uint8_t *dst, uint8_t *src, int stride, int h, - int x16, int y16, int rounder); -void ff_idct_put_altivec(uint8_t *dest, int line_size, int16_t *block); -void ff_idct_add_altivec(uint8_t *dest, int line_size, int16_t *block); - -void ff_dsputil_init_altivec(DSPContext* c, AVCodecContext *avctx); -void ff_float_init_altivec(DSPContext* c, AVCodecContext *avctx); -void ff_int_init_altivec(DSPContext* c, AVCodecContext *avctx); - -#endif /* AVCODEC_PPC_DSPUTIL_ALTIVEC_H */ +#endif /* AVCODEC_PPC_HPELDSP_ALTIVEC_H */ diff --git a/libavcodec/ppc/huffyuvdsp_altivec.c b/libavcodec/ppc/huffyuvdsp_altivec.c new file mode 100644 index 000000000..6701524e4 --- /dev/null +++ b/libavcodec/ppc/huffyuvdsp_altivec.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2002 Brian Foley + * Copyright (c) 2002 Dieter Shirley + * Copyright (c) 2003-2004 Romain Dolbeau + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#if HAVE_ALTIVEC_H +#include +#endif + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/huffyuvdsp.h" + +#if HAVE_ALTIVEC +static void add_bytes_altivec(uint8_t *dst, uint8_t *src, intptr_t w) +{ + register int i; + register vector unsigned char vdst, vsrc; + + /* dst and src are 16 bytes-aligned (guaranteed). */ + for (i = 0; i + 15 < w; i += 16) { + vdst = vec_ld(i, (unsigned char *) dst); + vsrc = vec_ld(i, (unsigned char *) src); + vdst = vec_add(vsrc, vdst); + vec_st(vdst, i, (unsigned char *) dst); + } + /* If w is not a multiple of 16. */ + for (; i < w; i++) + dst[i] = src[i]; +} +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_huffyuvdsp_init_ppc(HuffYUVDSPContext *c) +{ +#if HAVE_ALTIVEC + if (!PPC_ALTIVEC(av_get_cpu_flags())) + return; + + c->add_bytes = add_bytes_altivec; +#endif /* HAVE_ALTIVEC */ +} diff --git a/libavcodec/ppc/idct_altivec.c b/libavcodec/ppc/idct_altivec.c deleted file mode 100644 index c6f2cd8b8..000000000 --- a/libavcodec/ppc/idct_altivec.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2001 Michel Lespinasse - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * NOTE: This code is based on GPL code from the libmpeg2 project. The - * author, Michel Lespinasses, has given explicit permission to release - * under LGPL as part of FFmpeg. - */ - -/* - * FFmpeg integration by Dieter Shirley - * - * This file is a direct copy of the AltiVec IDCT module from the libmpeg2 - * project. I've deleted all of the libmpeg2-specific code, renamed the - * functions and reordered the function parameters. The only change to the - * IDCT function itself was to factor out the partial transposition, and to - * perform a full transpose at the end of the function. - */ - - -#include /* malloc(), free() */ -#include -#include "config.h" -#if HAVE_ALTIVEC_H -#include -#endif -#include "libavutil/ppc/types_altivec.h" -#include "dsputil_altivec.h" - -#define IDCT_HALF \ - /* 1st stage */ \ - t1 = vec_mradds (a1, vx7, vx1 ); \ - t8 = vec_mradds (a1, vx1, vec_subs (zero, vx7)); \ - t7 = vec_mradds (a2, vx5, vx3); \ - t3 = vec_mradds (ma2, vx3, vx5); \ - \ - /* 2nd stage */ \ - t5 = vec_adds (vx0, vx4); \ - t0 = vec_subs (vx0, vx4); \ - t2 = vec_mradds (a0, vx6, vx2); \ - t4 = vec_mradds (a0, vx2, vec_subs (zero, vx6)); \ - t6 = vec_adds (t8, t3); \ - t3 = vec_subs (t8, t3); \ - t8 = vec_subs (t1, t7); \ - t1 = vec_adds (t1, t7); \ - \ - /* 3rd stage */ \ - t7 = vec_adds (t5, t2); \ - t2 = vec_subs (t5, t2); \ - t5 = vec_adds (t0, t4); \ - t0 = vec_subs (t0, t4); \ - t4 = vec_subs (t8, t3); \ - t3 = vec_adds (t8, t3); \ - \ - /* 4th stage */ \ - vy0 = vec_adds (t7, t1); \ - vy7 = vec_subs (t7, t1); \ - vy1 = vec_mradds (c4, t3, t5); \ - vy6 = vec_mradds (mc4, t3, t5); \ - vy2 = vec_mradds (c4, t4, t0); \ - vy5 = vec_mradds (mc4, t4, t0); \ - vy3 = vec_adds (t2, t6); \ - vy4 = vec_subs (t2, t6); - - -#define IDCT \ - vec_s16 vx0, vx1, vx2, vx3, vx4, vx5, vx6, vx7; \ - vec_s16 vy0, vy1, vy2, vy3, vy4, vy5, vy6, vy7; \ - vec_s16 a0, a1, a2, ma2, c4, mc4, zero, bias; \ - vec_s16 t0, t1, t2, t3, t4, t5, t6, t7, t8; \ - vec_u16 shift; \ - \ - c4 = vec_splat (constants[0], 0); \ - a0 = vec_splat (constants[0], 1); \ - a1 = vec_splat (constants[0], 2); \ - a2 = vec_splat (constants[0], 3); \ - mc4 = vec_splat (constants[0], 4); \ - ma2 = vec_splat (constants[0], 5); \ - bias = (vec_s16)vec_splat ((vec_s32)constants[0], 3); \ - \ - zero = vec_splat_s16 (0); \ - shift = vec_splat_u16 (4); \ - \ - vx0 = vec_mradds (vec_sl (block[0], shift), constants[1], zero); \ - vx1 = vec_mradds (vec_sl (block[1], shift), constants[2], zero); \ - vx2 = vec_mradds (vec_sl (block[2], shift), constants[3], zero); \ - vx3 = vec_mradds (vec_sl (block[3], shift), constants[4], zero); \ - vx4 = vec_mradds (vec_sl (block[4], shift), constants[1], zero); \ - vx5 = vec_mradds (vec_sl (block[5], shift), constants[4], zero); \ - vx6 = vec_mradds (vec_sl (block[6], shift), constants[3], zero); \ - vx7 = vec_mradds (vec_sl (block[7], shift), constants[2], zero); \ - \ - IDCT_HALF \ - \ - vx0 = vec_mergeh (vy0, vy4); \ - vx1 = vec_mergel (vy0, vy4); \ - vx2 = vec_mergeh (vy1, vy5); \ - vx3 = vec_mergel (vy1, vy5); \ - vx4 = vec_mergeh (vy2, vy6); \ - vx5 = vec_mergel (vy2, vy6); \ - vx6 = vec_mergeh (vy3, vy7); \ - vx7 = vec_mergel (vy3, vy7); \ - \ - vy0 = vec_mergeh (vx0, vx4); \ - vy1 = vec_mergel (vx0, vx4); \ - vy2 = vec_mergeh (vx1, vx5); \ - vy3 = vec_mergel (vx1, vx5); \ - vy4 = vec_mergeh (vx2, vx6); \ - vy5 = vec_mergel (vx2, vx6); \ - vy6 = vec_mergeh (vx3, vx7); \ - vy7 = vec_mergel (vx3, vx7); \ - \ - vx0 = vec_adds (vec_mergeh (vy0, vy4), bias); \ - vx1 = vec_mergel (vy0, vy4); \ - vx2 = vec_mergeh (vy1, vy5); \ - vx3 = vec_mergel (vy1, vy5); \ - vx4 = vec_mergeh (vy2, vy6); \ - vx5 = vec_mergel (vy2, vy6); \ - vx6 = vec_mergeh (vy3, vy7); \ - vx7 = vec_mergel (vy3, vy7); \ - \ - IDCT_HALF \ - \ - shift = vec_splat_u16 (6); \ - vx0 = vec_sra (vy0, shift); \ - vx1 = vec_sra (vy1, shift); \ - vx2 = vec_sra (vy2, shift); \ - vx3 = vec_sra (vy3, shift); \ - vx4 = vec_sra (vy4, shift); \ - vx5 = vec_sra (vy5, shift); \ - vx6 = vec_sra (vy6, shift); \ - vx7 = vec_sra (vy7, shift); - - -static const vec_s16 constants[5] = { - {23170, 13573, 6518, 21895, -23170, -21895, 32, 31}, - {16384, 22725, 21407, 19266, 16384, 19266, 21407, 22725}, - {22725, 31521, 29692, 26722, 22725, 26722, 29692, 31521}, - {21407, 29692, 27969, 25172, 21407, 25172, 27969, 29692}, - {19266, 26722, 25172, 22654, 19266, 22654, 25172, 26722} -}; - -void ff_idct_put_altivec(uint8_t* dest, int stride, int16_t *blk) -{ - vec_s16 *block = (vec_s16*)blk; - vec_u8 tmp; - - IDCT - -#define COPY(dest,src) \ - tmp = vec_packsu (src, src); \ - vec_ste ((vec_u32)tmp, 0, (unsigned int *)dest); \ - vec_ste ((vec_u32)tmp, 4, (unsigned int *)dest); - - COPY (dest, vx0) dest += stride; - COPY (dest, vx1) dest += stride; - COPY (dest, vx2) dest += stride; - COPY (dest, vx3) dest += stride; - COPY (dest, vx4) dest += stride; - COPY (dest, vx5) dest += stride; - COPY (dest, vx6) dest += stride; - COPY (dest, vx7) -} - -void ff_idct_add_altivec(uint8_t* dest, int stride, int16_t *blk) -{ - vec_s16 *block = (vec_s16*)blk; - vec_u8 tmp; - vec_s16 tmp2, tmp3; - vec_u8 perm0; - vec_u8 perm1; - vec_u8 p0, p1, p; - - IDCT - - p0 = vec_lvsl (0, dest); - p1 = vec_lvsl (stride, dest); - p = vec_splat_u8 (-1); - perm0 = vec_mergeh (p, p0); - perm1 = vec_mergeh (p, p1); - -#define ADD(dest,src,perm) \ - /* *(uint64_t *)&tmp = *(uint64_t *)dest; */ \ - tmp = vec_ld (0, dest); \ - tmp2 = (vec_s16)vec_perm (tmp, (vec_u8)zero, perm); \ - tmp3 = vec_adds (tmp2, src); \ - tmp = vec_packsu (tmp3, tmp3); \ - vec_ste ((vec_u32)tmp, 0, (unsigned int *)dest); \ - vec_ste ((vec_u32)tmp, 4, (unsigned int *)dest); - - ADD (dest, vx0, perm0) dest += stride; - ADD (dest, vx1, perm1) dest += stride; - ADD (dest, vx2, perm0) dest += stride; - ADD (dest, vx3, perm1) dest += stride; - ADD (dest, vx4, perm0) dest += stride; - ADD (dest, vx5, perm1) dest += stride; - ADD (dest, vx6, perm0) dest += stride; - ADD (dest, vx7, perm1) -} diff --git a/libavcodec/ppc/idctdsp.c b/libavcodec/ppc/idctdsp.c new file mode 100644 index 000000000..a09c2b7b9 --- /dev/null +++ b/libavcodec/ppc/idctdsp.c @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2001 Michel Lespinasse + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NOTE: This code is based on GPL code from the libmpeg2 project. The + * author, Michel Lespinasses, has given explicit permission to release + * under LGPL as part of FFmpeg. + * + * FFmpeg integration by Dieter Shirley + * + * This file is a direct copy of the AltiVec IDCT module from the libmpeg2 + * project. I've deleted all of the libmpeg2-specific code, renamed the + * functions and reordered the function parameters. The only change to the + * IDCT function itself was to factor out the partial transposition, and to + * perform a full transpose at the end of the function. */ + +#include +#include +#include "config.h" +#if HAVE_ALTIVEC_H +#include +#endif + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavcodec/idctdsp.h" + +#if HAVE_ALTIVEC + +#define IDCT_HALF \ + /* 1st stage */ \ + t1 = vec_mradds(a1, vx7, vx1); \ + t8 = vec_mradds(a1, vx1, vec_subs(zero, vx7)); \ + t7 = vec_mradds(a2, vx5, vx3); \ + t3 = vec_mradds(ma2, vx3, vx5); \ + \ + /* 2nd stage */ \ + t5 = vec_adds(vx0, vx4); \ + t0 = vec_subs(vx0, vx4); \ + t2 = vec_mradds(a0, vx6, vx2); \ + t4 = vec_mradds(a0, vx2, vec_subs(zero, vx6)); \ + t6 = vec_adds(t8, t3); \ + t3 = vec_subs(t8, t3); \ + t8 = vec_subs(t1, t7); \ + t1 = vec_adds(t1, t7); \ + \ + /* 3rd stage */ \ + t7 = vec_adds(t5, t2); \ + t2 = vec_subs(t5, t2); \ + t5 = vec_adds(t0, t4); \ + t0 = vec_subs(t0, t4); \ + t4 = vec_subs(t8, t3); \ + t3 = vec_adds(t8, t3); \ + \ + /* 4th stage */ \ + vy0 = vec_adds(t7, t1); \ + vy7 = vec_subs(t7, t1); \ + vy1 = vec_mradds(c4, t3, t5); \ + vy6 = vec_mradds(mc4, t3, t5); \ + vy2 = vec_mradds(c4, t4, t0); \ + vy5 = vec_mradds(mc4, t4, t0); \ + vy3 = vec_adds(t2, t6); \ + vy4 = vec_subs(t2, t6) + +#define IDCT \ + vec_s16 vy0, vy1, vy2, vy3, vy4, vy5, vy6, vy7; \ + vec_s16 t0, t1, t2, t3, t4, t5, t6, t7, t8; \ + \ + vec_s16 c4 = vec_splat(constants[0], 0); \ + vec_s16 a0 = vec_splat(constants[0], 1); \ + vec_s16 a1 = vec_splat(constants[0], 2); \ + vec_s16 a2 = vec_splat(constants[0], 3); \ + vec_s16 mc4 = vec_splat(constants[0], 4); \ + vec_s16 ma2 = vec_splat(constants[0], 5); \ + vec_s16 bias = (vec_s16) vec_splat((vec_s32) constants[0], 3); \ + \ + vec_s16 zero = vec_splat_s16(0); \ + vec_u16 shift = vec_splat_u16(4); \ + \ + vec_s16 vx0 = vec_mradds(vec_sl(block[0], shift), constants[1], zero); \ + vec_s16 vx1 = vec_mradds(vec_sl(block[1], shift), constants[2], zero); \ + vec_s16 vx2 = vec_mradds(vec_sl(block[2], shift), constants[3], zero); \ + vec_s16 vx3 = vec_mradds(vec_sl(block[3], shift), constants[4], zero); \ + vec_s16 vx4 = vec_mradds(vec_sl(block[4], shift), constants[1], zero); \ + vec_s16 vx5 = vec_mradds(vec_sl(block[5], shift), constants[4], zero); \ + vec_s16 vx6 = vec_mradds(vec_sl(block[6], shift), constants[3], zero); \ + vec_s16 vx7 = vec_mradds(vec_sl(block[7], shift), constants[2], zero); \ + \ + IDCT_HALF; \ + \ + vx0 = vec_mergeh(vy0, vy4); \ + vx1 = vec_mergel(vy0, vy4); \ + vx2 = vec_mergeh(vy1, vy5); \ + vx3 = vec_mergel(vy1, vy5); \ + vx4 = vec_mergeh(vy2, vy6); \ + vx5 = vec_mergel(vy2, vy6); \ + vx6 = vec_mergeh(vy3, vy7); \ + vx7 = vec_mergel(vy3, vy7); \ + \ + vy0 = vec_mergeh(vx0, vx4); \ + vy1 = vec_mergel(vx0, vx4); \ + vy2 = vec_mergeh(vx1, vx5); \ + vy3 = vec_mergel(vx1, vx5); \ + vy4 = vec_mergeh(vx2, vx6); \ + vy5 = vec_mergel(vx2, vx6); \ + vy6 = vec_mergeh(vx3, vx7); \ + vy7 = vec_mergel(vx3, vx7); \ + \ + vx0 = vec_adds(vec_mergeh(vy0, vy4), bias); \ + vx1 = vec_mergel(vy0, vy4); \ + vx2 = vec_mergeh(vy1, vy5); \ + vx3 = vec_mergel(vy1, vy5); \ + vx4 = vec_mergeh(vy2, vy6); \ + vx5 = vec_mergel(vy2, vy6); \ + vx6 = vec_mergeh(vy3, vy7); \ + vx7 = vec_mergel(vy3, vy7); \ + \ + IDCT_HALF; \ + \ + shift = vec_splat_u16(6); \ + vx0 = vec_sra(vy0, shift); \ + vx1 = vec_sra(vy1, shift); \ + vx2 = vec_sra(vy2, shift); \ + vx3 = vec_sra(vy3, shift); \ + vx4 = vec_sra(vy4, shift); \ + vx5 = vec_sra(vy5, shift); \ + vx6 = vec_sra(vy6, shift); \ + vx7 = vec_sra(vy7, shift) + +static const vec_s16 constants[5] = { + { 23170, 13573, 6518, 21895, -23170, -21895, 32, 31 }, + { 16384, 22725, 21407, 19266, 16384, 19266, 21407, 22725 }, + { 22725, 31521, 29692, 26722, 22725, 26722, 29692, 31521 }, + { 21407, 29692, 27969, 25172, 21407, 25172, 27969, 29692 }, + { 19266, 26722, 25172, 22654, 19266, 22654, 25172, 26722 } +}; + +static void idct_altivec(int16_t *blk) +{ + vec_s16 *block = (vec_s16 *) blk; + + IDCT; + + block[0] = vx0; + block[1] = vx1; + block[2] = vx2; + block[3] = vx3; + block[4] = vx4; + block[5] = vx5; + block[6] = vx6; + block[7] = vx7; +} + +static void idct_put_altivec(uint8_t *dest, int stride, int16_t *blk) +{ + vec_s16 *block = (vec_s16 *) blk; + vec_u8 tmp; + + IDCT; + +#define COPY(dest, src) \ + tmp = vec_packsu(src, src); \ + vec_ste((vec_u32) tmp, 0, (unsigned int *) dest); \ + vec_ste((vec_u32) tmp, 4, (unsigned int *) dest) + + COPY(dest, vx0); + dest += stride; + COPY(dest, vx1); + dest += stride; + COPY(dest, vx2); + dest += stride; + COPY(dest, vx3); + dest += stride; + COPY(dest, vx4); + dest += stride; + COPY(dest, vx5); + dest += stride; + COPY(dest, vx6); + dest += stride; + COPY(dest, vx7); +} + +static void idct_add_altivec(uint8_t *dest, int stride, int16_t *blk) +{ + vec_s16 *block = (vec_s16 *) blk; + vec_u8 tmp; + vec_s16 tmp2, tmp3; + vec_u8 perm0; + vec_u8 perm1; + vec_u8 p0, p1, p; + + IDCT; + + p0 = vec_lvsl(0, dest); + p1 = vec_lvsl(stride, dest); + p = vec_splat_u8(-1); + perm0 = vec_mergeh(p, p0); + perm1 = vec_mergeh(p, p1); + +#define ADD(dest, src, perm) \ + /* *(uint64_t *) &tmp = *(uint64_t *) dest; */ \ + tmp = vec_ld(0, dest); \ + tmp2 = (vec_s16) vec_perm(tmp, (vec_u8) zero, perm); \ + tmp3 = vec_adds(tmp2, src); \ + tmp = vec_packsu(tmp3, tmp3); \ + vec_ste((vec_u32) tmp, 0, (unsigned int *) dest); \ + vec_ste((vec_u32) tmp, 4, (unsigned int *) dest) + + ADD(dest, vx0, perm0); + dest += stride; + ADD(dest, vx1, perm1); + dest += stride; + ADD(dest, vx2, perm0); + dest += stride; + ADD(dest, vx3, perm1); + dest += stride; + ADD(dest, vx4, perm0); + dest += stride; + ADD(dest, vx5, perm1); + dest += stride; + ADD(dest, vx6, perm0); + dest += stride; + ADD(dest, vx7, perm1); +} + +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_idctdsp_init_ppc(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) +{ +#if HAVE_ALTIVEC + if (PPC_ALTIVEC(av_get_cpu_flags())) { + if (!high_bit_depth && avctx->lowres == 0) { + if ((avctx->idct_algo == FF_IDCT_AUTO) || + (avctx->idct_algo == FF_IDCT_ALTIVEC)) { + c->idct = idct_altivec; + c->idct_add = idct_add_altivec; + c->idct_put = idct_put_altivec; + c->idct_permutation_type = FF_TRANSPOSE_IDCT_PERM; + } + } + } +#endif /* HAVE_ALTIVEC */ +} diff --git a/libavcodec/ppc/int_altivec.c b/libavcodec/ppc/int_altivec.c deleted file mode 100644 index d4e0c852e..000000000 --- a/libavcodec/ppc/int_altivec.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2007 Luca Barbato - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - ** @file - ** integer misc ops. - **/ - -#include "config.h" -#if HAVE_ALTIVEC_H -#include -#endif - -#include "libavutil/attributes.h" -#include "libavutil/ppc/types_altivec.h" -#include "libavcodec/dsputil.h" - -#include "dsputil_altivec.h" - -static int ssd_int8_vs_int16_altivec(const int8_t *pix1, const int16_t *pix2, - int size) { - int i, size16; - vector signed char vpix1; - vector signed short vpix2, vdiff, vpix1l,vpix1h; - union { vector signed int vscore; - int32_t score[4]; - } u; - u.vscore = vec_splat_s32(0); -// -//XXX lazy way, fix it later - -#define vec_unaligned_load(b) \ - vec_perm(vec_ld(0,b),vec_ld(15,b),vec_lvsl(0, b)); - - size16 = size >> 4; - while(size16) { -// score += (pix1[i]-pix2[i])*(pix1[i]-pix2[i]); - //load pix1 and the first batch of pix2 - - vpix1 = vec_unaligned_load(pix1); - vpix2 = vec_unaligned_load(pix2); - pix2 += 8; - //unpack - vpix1h = vec_unpackh(vpix1); - vdiff = vec_sub(vpix1h, vpix2); - vpix1l = vec_unpackl(vpix1); - // load another batch from pix2 - vpix2 = vec_unaligned_load(pix2); - u.vscore = vec_msum(vdiff, vdiff, u.vscore); - vdiff = vec_sub(vpix1l, vpix2); - u.vscore = vec_msum(vdiff, vdiff, u.vscore); - pix1 += 16; - pix2 += 8; - size16--; - } - u.vscore = vec_sums(u.vscore, vec_splat_s32(0)); - - size %= 16; - for (i = 0; i < size; i++) { - u.score[3] += (pix1[i]-pix2[i])*(pix1[i]-pix2[i]); - } - return u.score[3]; -} - -static int32_t scalarproduct_int16_altivec(const int16_t *v1, const int16_t *v2, - int order) -{ - int i; - LOAD_ZERO; - register vec_s16 vec1; - register vec_s32 res = vec_splat_s32(0), t; - int32_t ires; - - for(i = 0; i < order; i += 8){ - vec1 = vec_unaligned_load(v1); - t = vec_msum(vec1, vec_ld(0, v2), zero_s32v); - res = vec_sums(t, res); - v1 += 8; - v2 += 8; - } - res = vec_splat(res, 3); - vec_ste(res, 0, &ires); - return ires; -} - -static int32_t scalarproduct_and_madd_int16_altivec(int16_t *v1, const int16_t *v2, const int16_t *v3, int order, int mul) -{ - LOAD_ZERO; - vec_s16 *pv1 = (vec_s16*)v1; - register vec_s16 muls = {mul,mul,mul,mul,mul,mul,mul,mul}; - register vec_s16 t0, t1, i0, i1, i4; - register vec_s16 i2 = vec_ld(0, v2), i3 = vec_ld(0, v3); - register vec_s32 res = zero_s32v; - register vec_u8 align = vec_lvsl(0, v2); - int32_t ires; - order >>= 4; - do { - i1 = vec_ld(16, v2); - t0 = vec_perm(i2, i1, align); - i2 = vec_ld(32, v2); - t1 = vec_perm(i1, i2, align); - i0 = pv1[0]; - i1 = pv1[1]; - res = vec_msum(t0, i0, res); - res = vec_msum(t1, i1, res); - i4 = vec_ld(16, v3); - t0 = vec_perm(i3, i4, align); - i3 = vec_ld(32, v3); - t1 = vec_perm(i4, i3, align); - pv1[0] = vec_mladd(t0, muls, i0); - pv1[1] = vec_mladd(t1, muls, i1); - pv1 += 2; - v2 += 16; - v3 += 16; - } while(--order); - res = vec_splat(vec_sums(res, zero_s32v), 3); - vec_ste(res, 0, &ires); - return ires; -} - -av_cold void ff_int_init_altivec(DSPContext *c, AVCodecContext *avctx) -{ - c->ssd_int8_vs_int16 = ssd_int8_vs_int16_altivec; - c->scalarproduct_int16 = scalarproduct_int16_altivec; - c->scalarproduct_and_madd_int16 = scalarproduct_and_madd_int16_altivec; -} diff --git a/libavcodec/ppc/lossless_audiodsp_altivec.c b/libavcodec/ppc/lossless_audiodsp_altivec.c new file mode 100644 index 000000000..1ebb0f4aa --- /dev/null +++ b/libavcodec/ppc/lossless_audiodsp_altivec.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2007 Luca Barbato + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#if HAVE_ALTIVEC_H +#include +#endif + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavcodec/lossless_audiodsp.h" + +#if HAVE_ALTIVEC +static int32_t scalarproduct_and_madd_int16_altivec(int16_t *v1, + const int16_t *v2, + const int16_t *v3, + int order, int mul) +{ + LOAD_ZERO; + vec_s16 *pv1 = (vec_s16 *) v1; + register vec_s16 muls = { mul, mul, mul, mul, mul, mul, mul, mul }; + register vec_s16 t0, t1, i0, i1, i4; + register vec_s16 i2 = vec_ld(0, v2), i3 = vec_ld(0, v3); + register vec_s32 res = zero_s32v; + register vec_u8 align = vec_lvsl(0, v2); + int32_t ires; + + order >>= 4; + do { + i1 = vec_ld(16, v2); + t0 = vec_perm(i2, i1, align); + i2 = vec_ld(32, v2); + t1 = vec_perm(i1, i2, align); + i0 = pv1[0]; + i1 = pv1[1]; + res = vec_msum(t0, i0, res); + res = vec_msum(t1, i1, res); + i4 = vec_ld(16, v3); + t0 = vec_perm(i3, i4, align); + i3 = vec_ld(32, v3); + t1 = vec_perm(i4, i3, align); + pv1[0] = vec_mladd(t0, muls, i0); + pv1[1] = vec_mladd(t1, muls, i1); + pv1 += 2; + v2 += 16; + v3 += 16; + } while (--order); + res = vec_splat(vec_sums(res, zero_s32v), 3); + vec_ste(res, 0, &ires); + + return ires; +} +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_llauddsp_init_ppc(LLAudDSPContext *c) +{ +#if HAVE_ALTIVEC + if (!PPC_ALTIVEC(av_get_cpu_flags())) + return; + + c->scalarproduct_and_madd_int16 = scalarproduct_and_madd_int16_altivec; +#endif /* HAVE_ALTIVEC */ +} diff --git a/libavcodec/ppc/mpegaudiodsp_altivec.c b/libavcodec/ppc/mpegaudiodsp_altivec.c index 091f9a391..ddfe5dcbb 100644 --- a/libavcodec/ppc/mpegaudiodsp_altivec.c +++ b/libavcodec/ppc/mpegaudiodsp_altivec.c @@ -23,9 +23,9 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/internal.h" +#include "libavutil/ppc/cpu.h" #include "libavutil/ppc/util_altivec.h" #include "libavcodec/mpegaudiodsp.h" -#include "dsputil_altivec.h" #if HAVE_ALTIVEC @@ -133,7 +133,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 (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + if (!PPC_ALTIVEC(av_get_cpu_flags())) return; s->apply_window_float = apply_window_mp3; diff --git a/libavcodec/ppc/mpegvideo_altivec.c b/libavcodec/ppc/mpegvideo_altivec.c index cedc1c8bf..06eed2f20 100644 --- a/libavcodec/ppc/mpegvideo_altivec.c +++ b/libavcodec/ppc/mpegvideo_altivec.c @@ -27,10 +27,10 @@ #include "config.h" #include "libavutil/attributes.h" #include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" #include "libavutil/ppc/types_altivec.h" #include "libavutil/ppc/util_altivec.h" #include "libavcodec/mpegvideo.h" -#include "dsputil_altivec.h" #if HAVE_ALTIVEC @@ -118,7 +118,7 @@ static void dct_unquantize_h263_altivec(MpegEncContext *s, av_cold void ff_MPV_common_init_ppc(MpegEncContext *s) { #if HAVE_ALTIVEC - if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + if (!PPC_ALTIVEC(av_get_cpu_flags())) return; if ((s->avctx->dct_algo == FF_DCT_AUTO) || diff --git a/libavcodec/ppc/mpegvideodsp.c b/libavcodec/ppc/mpegvideodsp.c new file mode 100644 index 000000000..769695433 --- /dev/null +++ b/libavcodec/ppc/mpegvideodsp.c @@ -0,0 +1,133 @@ +/* + * GMC (Global Motion Compensation), AltiVec-enabled + * + * Copyright (c) 2003 Romain Dolbeau + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/mem.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/mpegvideodsp.h" + +#if HAVE_ALTIVEC +/* 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 */, + int stride, int h, int x16, int y16, int rounder) +{ + int i; + const DECLARE_ALIGNED(16, unsigned short, rounder_a) = rounder; + const DECLARE_ALIGNED(16, unsigned short, ABCD)[8] = { + (16 - x16) * (16 - y16), /* A */ + (x16) * (16 - y16), /* B */ + (16 - x16) * (y16), /* C */ + (x16) * (y16), /* D */ + 0, 0, 0, 0 /* padding */ + }; + register const vector unsigned char vczero = + (const vector unsigned char) vec_splat_u8(0); + register const vector unsigned short vcsr8 = + (const vector unsigned short) vec_splat_u16(8); + register vector unsigned char dstv, dstv2, srcvB, srcvC, srcvD; + register vector unsigned short tempB, tempC, tempD; + unsigned long dst_odd = (unsigned long) dst & 0x0000000F; + unsigned long src_really_odd = (unsigned long) src & 0x0000000F; + register vector unsigned short tempA = + vec_ld(0, (const unsigned short *) ABCD); + register vector unsigned short Av = vec_splat(tempA, 0); + register vector unsigned short Bv = vec_splat(tempA, 1); + register vector unsigned short Cv = vec_splat(tempA, 2); + register vector unsigned short Dv = vec_splat(tempA, 3); + register vector unsigned short rounderV = + vec_splat((vec_u16) vec_lde(0, &rounder_a), 0); + + /* we'll be able to pick-up our 9 char elements at src from those + * 32 bytes we load the first batch here, as inside the loop we can + * reuse 'src + stride' from one iteration as the 'src' of the next. */ + register vector unsigned char src_0 = vec_ld(0, src); + register vector unsigned char src_1 = vec_ld(16, src); + register vector unsigned char srcvA = vec_perm(src_0, src_1, + vec_lvsl(0, src)); + + if (src_really_odd != 0x0000000F) + /* If (src & 0xF) == 0xF, then (src + 1) is properly aligned + * on the second vector. */ + srcvB = vec_perm(src_0, src_1, vec_lvsl(1, src)); + else + srcvB = src_1; + srcvA = vec_mergeh(vczero, srcvA); + srcvB = vec_mergeh(vczero, srcvB); + + for (i = 0; i < h; i++) { + dst_odd = (unsigned long) dst & 0x0000000F; + src_really_odd = (((unsigned long) src) + stride) & 0x0000000F; + + dstv = vec_ld(0, dst); + + /* We'll be able to pick-up our 9 char elements at src + stride from + * those 32 bytes then reuse the resulting 2 vectors srvcC and srcvD + * as the next srcvA and srcvB. */ + src_0 = vec_ld(stride + 0, src); + src_1 = vec_ld(stride + 16, src); + srcvC = vec_perm(src_0, src_1, vec_lvsl(stride + 0, src)); + + if (src_really_odd != 0x0000000F) + /* If (src & 0xF) == 0xF, then (src + 1) is properly aligned + * on the second vector. */ + srcvD = vec_perm(src_0, src_1, vec_lvsl(stride + 1, src)); + else + srcvD = src_1; + + srcvC = vec_mergeh(vczero, srcvC); + srcvD = vec_mergeh(vczero, srcvD); + + /* OK, now we (finally) do the math :-) + * Those four instructions replace 32 int muls & 32 int adds. + * Isn't AltiVec nice? */ + tempA = vec_mladd((vector unsigned short) srcvA, Av, rounderV); + tempB = vec_mladd((vector unsigned short) srcvB, Bv, tempA); + tempC = vec_mladd((vector unsigned short) srcvC, Cv, tempB); + tempD = vec_mladd((vector unsigned short) srcvD, Dv, tempC); + + srcvA = srcvC; + srcvB = srcvD; + + tempD = vec_sr(tempD, vcsr8); + + dstv2 = vec_pack(tempD, (vector unsigned short) vczero); + + if (dst_odd) + dstv2 = vec_perm(dstv, dstv2, vcprm(0, 1, s0, s1)); + else + dstv2 = vec_perm(dstv, dstv2, vcprm(s0, s1, 2, 3)); + + vec_st(dstv2, 0, dst); + + dst += stride; + src += stride; + } +} +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_mpegvideodsp_init_ppc(MpegVideoDSPContext *c) +{ +#if HAVE_ALTIVEC + c->gmc1 = gmc1_altivec; +#endif /* HAVE_ALTIVEC */ +} diff --git a/libavcodec/ppc/mpegvideoencdsp.c b/libavcodec/ppc/mpegvideoencdsp.c new file mode 100644 index 000000000..00ae2a6f3 --- /dev/null +++ b/libavcodec/ppc/mpegvideoencdsp.c @@ -0,0 +1,103 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include +#if HAVE_ALTIVEC_H +#include +#endif + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/mpegvideoencdsp.h" + +#if HAVE_ALTIVEC + +static int pix_norm1_altivec(uint8_t *pix, int line_size) +{ + int i, s = 0; + const vector unsigned int zero = + (const vector unsigned int) vec_splat_u32(0); + vector unsigned char perm = vec_lvsl(0, pix); + vector unsigned int sv = (vector unsigned int) vec_splat_u32(0); + vector signed int sum; + + for (i = 0; i < 16; i++) { + /* Read the potentially unaligned pixels. */ + vector unsigned char pixl = vec_ld(0, pix); + vector unsigned char pixr = vec_ld(15, pix); + vector unsigned char pixv = vec_perm(pixl, pixr, perm); + + /* Square the values, and add them to our sum. */ + sv = vec_msum(pixv, pixv, sv); + + pix += line_size; + } + /* Sum up the four partial sums, and put the result into s. */ + sum = vec_sums((vector signed int) sv, (vector signed int) zero); + sum = vec_splat(sum, 3); + vec_ste(sum, 0, &s); + + return s; +} + +static int pix_sum_altivec(uint8_t *pix, int line_size) +{ + int i, s; + const vector unsigned int zero = + (const vector unsigned int) vec_splat_u32(0); + vector unsigned char perm = vec_lvsl(0, pix); + vector unsigned int sad = (vector unsigned int) vec_splat_u32(0); + vector signed int sumdiffs; + + for (i = 0; i < 16; i++) { + /* Read the potentially unaligned 16 pixels into t1. */ + vector unsigned char pixl = vec_ld(0, pix); + vector unsigned char pixr = vec_ld(15, pix); + vector unsigned char t1 = vec_perm(pixl, pixr, perm); + + /* Add each 4 pixel group together and put 4 results into sad. */ + sad = vec_sum4s(t1, sad); + + pix += line_size; + } + + /* Sum up the four partial sums, and put the result into s. */ + sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); + sumdiffs = vec_splat(sumdiffs, 3); + vec_ste(sumdiffs, 0, &s); + + return s; +} + +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_mpegvideoencdsp_init_ppc(MpegvideoEncDSPContext *c, + AVCodecContext *avctx) +{ +#if HAVE_ALTIVEC + if (!PPC_ALTIVEC(av_get_cpu_flags())) + return; + + c->pix_norm1 = pix_norm1_altivec; + c->pix_sum = pix_sum_altivec; +#endif /* HAVE_ALTIVEC */ +} diff --git a/libavcodec/ppc/pixblockdsp.c b/libavcodec/ppc/pixblockdsp.c new file mode 100644 index 000000000..42c5be842 --- /dev/null +++ b/libavcodec/ppc/pixblockdsp.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2002 Brian Foley + * Copyright (c) 2002 Dieter Shirley + * Copyright (c) 2003-2004 Romain Dolbeau + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#if HAVE_ALTIVEC_H +#include +#endif + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/pixblockdsp.h" + +#if HAVE_ALTIVEC + +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); + + 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); + + // Convert the bytes into shorts. + vector signed short shorts = (vector signed short) vec_mergeh(zero, + bytes); + + // Save the data to the block, we assume the block is 16-byte aligned. + vec_st(shorts, i * 16, (vector signed short *) block); + + pixels += line_size; + } +} + +static void diff_pixels_altivec(int16_t *restrict block, const uint8_t *s1, + const uint8_t *s2, int stride) +{ + int i; + vector unsigned char perm1 = vec_lvsl(0, s1); + vector unsigned char perm2 = vec_lvsl(0, s2); + const vector unsigned char zero = + (const vector unsigned char) vec_splat_u8(0); + vector signed short shorts1, shorts2; + + for (i = 0; i < 4; i++) { + /* Read potentially unaligned pixels. + * We're reading 16 pixels, and actually only want 8, + * but we simply ignore the extras. */ + 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); + + // Convert the bytes into shorts. + shorts1 = (vector signed short) vec_mergeh(zero, bytes); + + // Do the same for the second block of pixels. + pixl = vec_ld(0, s2); + pixr = vec_ld(15, s2); + bytes = vec_perm(pixl, pixr, perm2); + + // Convert the bytes into shorts. + shorts2 = (vector signed short) vec_mergeh(zero, bytes); + + // Do the subtraction. + shorts1 = vec_sub(shorts1, shorts2); + + // Save the data to the block, we assume the block is 16-byte aligned. + vec_st(shorts1, 0, (vector signed short *) block); + + s1 += stride; + s2 += stride; + block += 8; + + /* The code below is a copy of the code above... + * This is a manual unroll. */ + + /* Read potentially unaligned pixels. + * We're reading 16 pixels, and actually only want 8, + * but we simply ignore the extras. */ + pixl = vec_ld(0, s1); + pixr = vec_ld(15, s1); + bytes = vec_perm(pixl, pixr, perm1); + + // Convert the bytes into shorts. + shorts1 = (vector signed short) vec_mergeh(zero, bytes); + + // Do the same for the second block of pixels. + pixl = vec_ld(0, s2); + pixr = vec_ld(15, s2); + bytes = vec_perm(pixl, pixr, perm2); + + // Convert the bytes into shorts. + shorts2 = (vector signed short) vec_mergeh(zero, bytes); + + // Do the subtraction. + shorts1 = vec_sub(shorts1, shorts2); + + // Save the data to the block, we assume the block is 16-byte aligned. + vec_st(shorts1, 0, (vector signed short *) block); + + s1 += stride; + s2 += stride; + block += 8; + } +} + +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_pixblockdsp_init_ppc(PixblockDSPContext *c, + AVCodecContext *avctx, + unsigned high_bit_depth) +{ +#if HAVE_ALTIVEC + if (!PPC_ALTIVEC(av_get_cpu_flags())) + return; + + c->diff_pixels = diff_pixels_altivec; + + if (!high_bit_depth) { + c->get_pixels = get_pixels_altivec; + } +#endif /* HAVE_ALTIVEC */ +} diff --git a/libavcodec/ppc/svq1enc_altivec.c b/libavcodec/ppc/svq1enc_altivec.c new file mode 100644 index 000000000..4e25e253f --- /dev/null +++ b/libavcodec/ppc/svq1enc_altivec.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2007 Luca Barbato + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" +#if HAVE_ALTIVEC_H +#include +#endif + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/svq1enc.h" + +#if HAVE_ALTIVEC +static int ssd_int8_vs_int16_altivec(const int8_t *pix1, const int16_t *pix2, + int size) +{ + int i, size16 = size >> 4; + vector signed char vpix1; + vector signed short vpix2, vdiff, vpix1l, vpix1h; + union { + vector signed int vscore; + int32_t score[4]; + } u = { .vscore = vec_splat_s32(0) }; + + while (size16) { + // score += (pix1[i] - pix2[i]) * (pix1[i] - pix2[i]); + // load pix1 and the first batch of pix2 + + vpix1 = vec_unaligned_load(pix1); + vpix2 = vec_unaligned_load(pix2); + pix2 += 8; + // unpack + vpix1h = vec_unpackh(vpix1); + vdiff = vec_sub(vpix1h, vpix2); + vpix1l = vec_unpackl(vpix1); + // load another batch from pix2 + vpix2 = vec_unaligned_load(pix2); + u.vscore = vec_msum(vdiff, vdiff, u.vscore); + vdiff = vec_sub(vpix1l, vpix2); + u.vscore = vec_msum(vdiff, vdiff, u.vscore); + pix1 += 16; + pix2 += 8; + size16--; + } + u.vscore = vec_sums(u.vscore, vec_splat_s32(0)); + + size %= 16; + for (i = 0; i < size; i++) + u.score[3] += (pix1[i] - pix2[i]) * (pix1[i] - pix2[i]); + + return u.score[3]; +} +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_svq1enc_init_ppc(SVQ1EncContext *c) +{ +#if HAVE_ALTIVEC + if (!PPC_ALTIVEC(av_get_cpu_flags())) + return; + + c->ssd_int8_vs_int16 = ssd_int8_vs_int16_altivec; +#endif /* HAVE_ALTIVEC */ +} diff --git a/libavcodec/ppc/vc1dsp_altivec.c b/libavcodec/ppc/vc1dsp_altivec.c index 1b73dd03f..2128b56d0 100644 --- a/libavcodec/ppc/vc1dsp_altivec.c +++ b/libavcodec/ppc/vc1dsp_altivec.c @@ -21,6 +21,8 @@ #include "config.h" #include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" #include "libavutil/ppc/types_altivec.h" #include "libavutil/ppc/util_altivec.h" #include "libavcodec/vc1dsp.h" @@ -343,7 +345,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 (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + if (!PPC_ALTIVEC(av_get_cpu_flags())) return; dsp->vc1_inv_trans_8x8 = vc1_inv_trans_8x8_altivec; diff --git a/libavcodec/ppc/vorbisdsp_altivec.c b/libavcodec/ppc/vorbisdsp_altivec.c index d243bf63c..d7557c815 100644 --- a/libavcodec/ppc/vorbisdsp_altivec.c +++ b/libavcodec/ppc/vorbisdsp_altivec.c @@ -24,6 +24,7 @@ #endif #include "libavutil/attributes.h" #include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" #include "libavcodec/vorbisdsp.h" #if HAVE_ALTIVEC @@ -54,7 +55,7 @@ static void vorbis_inverse_coupling_altivec(float *mag, float *ang, av_cold void ff_vorbisdsp_init_ppc(VorbisDSPContext *c) { #if HAVE_ALTIVEC - if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + if (!PPC_ALTIVEC(av_get_cpu_flags())) return; c->vorbis_inverse_coupling = vorbis_inverse_coupling_altivec; diff --git a/libavcodec/ppc/vp3dsp_altivec.c b/libavcodec/ppc/vp3dsp_altivec.c index 56c2d0b82..9d81b3f26 100644 --- a/libavcodec/ppc/vp3dsp_altivec.c +++ b/libavcodec/ppc/vp3dsp_altivec.c @@ -23,10 +23,10 @@ #include "config.h" #include "libavutil/attributes.h" #include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" #include "libavutil/ppc/types_altivec.h" #include "libavutil/ppc/util_altivec.h" #include "libavcodec/vp3dsp.h" -#include "dsputil_altivec.h" #if HAVE_ALTIVEC @@ -180,7 +180,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 (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + if (!PPC_ALTIVEC(av_get_cpu_flags())) return; c->idct_put = vp3_idct_put_altivec; diff --git a/libavcodec/ppc/vp8dsp_altivec.c b/libavcodec/ppc/vp8dsp_altivec.c index c858d8a45..91ff8cc8f 100644 --- a/libavcodec/ppc/vp8dsp_altivec.c +++ b/libavcodec/ppc/vp8dsp_altivec.c @@ -23,10 +23,11 @@ #include "config.h" #include "libavutil/cpu.h" #include "libavutil/mem.h" +#include "libavutil/ppc/cpu.h" #include "libavutil/ppc/types_altivec.h" #include "libavutil/ppc/util_altivec.h" #include "libavcodec/vp8dsp.h" -#include "dsputil_altivec.h" +#include "hpeldsp_altivec.h" #if HAVE_ALTIVEC #define REPT4(...) { __VA_ARGS__, __VA_ARGS__, __VA_ARGS__, __VA_ARGS__ } @@ -311,10 +312,11 @@ static void put_vp8_pixels16_altivec(uint8_t *dst, ptrdiff_t dstride, uint8_t *s #endif /* HAVE_ALTIVEC */ -av_cold void ff_vp8dsp_init_ppc(VP8DSPContext *c) + +av_cold void ff_vp78dsp_init_ppc(VP8DSPContext *c) { #if HAVE_ALTIVEC - if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + if (!PPC_ALTIVEC(av_get_cpu_flags())) return; c->put_vp8_epel_pixels_tab[0][0][0] = put_vp8_pixels16_altivec; diff --git a/libavcodec/proresdec.h b/libavcodec/proresdec.h index de50daef0..cb7297937 100644 --- a/libavcodec/proresdec.h +++ b/libavcodec/proresdec.h @@ -23,6 +23,7 @@ #define AVCODEC_PRORESDEC_H #include "dsputil.h" +#include "blockdsp.h" #include "proresdsp.h" typedef struct { @@ -36,6 +37,7 @@ typedef struct { typedef struct { DSPContext dsp; + BlockDSPContext bdsp; ProresDSPContext prodsp; AVFrame *frame; int frame_type; ///< 0 = progressive, 1 = tff, 2 = bff diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index b1affadaa..d59711448 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -30,6 +30,7 @@ #include "avcodec.h" #include "get_bits.h" +#include "idctdsp.h" #include "internal.h" #include "simple_idct.h" #include "proresdec.h" @@ -50,6 +51,7 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->bits_per_raw_sample = 10; ff_dsputil_init(&ctx->dsp, avctx); + ff_blockdsp_init(&ctx->bdsp, avctx); ff_proresdsp_init(&ctx->prodsp, avctx); ff_init_scantable_permutation(idct_permutation, @@ -182,7 +184,7 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons if (ctx->slice_count != slice_count || !ctx->slices) { av_freep(&ctx->slices); - ctx->slices = av_mallocz(slice_count * sizeof(*ctx->slices)); + ctx->slices = av_mallocz_array(slice_count, sizeof(*ctx->slices)); if (!ctx->slices) return AVERROR(ENOMEM); ctx->slice_count = slice_count; @@ -366,7 +368,7 @@ static int decode_slice_luma(AVCodecContext *avctx, SliceContext *slice, int ret; for (i = 0; i < blocks_per_slice; i++) - ctx->dsp.clear_block(blocks+(i<<6)); + ctx->bdsp.clear_block(blocks+(i<<6)); init_get_bits(&gb, buf, buf_size << 3); @@ -399,7 +401,7 @@ static int decode_slice_chroma(AVCodecContext *avctx, SliceContext *slice, int ret; for (i = 0; i < blocks_per_slice; i++) - ctx->dsp.clear_block(blocks+(i<<6)); + ctx->bdsp.clear_block(blocks+(i<<6)); init_get_bits(&gb, buf, buf_size << 3); @@ -478,7 +480,7 @@ static void decode_slice_alpha(ProresContext *ctx, int16_t *block; for (i = 0; i < blocks_per_slice<<2; i++) - ctx->dsp.clear_block(blocks+(i<<6)); + ctx->bdsp.clear_block(blocks+(i<<6)); init_get_bits(&gb, buf, buf_size << 3); diff --git a/libavcodec/proresdec_lgpl.c b/libavcodec/proresdec_lgpl.c index a57429d70..f2e24ec78 100644 --- a/libavcodec/proresdec_lgpl.c +++ b/libavcodec/proresdec_lgpl.c @@ -34,7 +34,7 @@ #include "libavutil/intmath.h" #include "avcodec.h" -#include "dsputil.h" +#include "idctdsp.h" #include "internal.h" #include "proresdata.h" #include "proresdsp.h" diff --git a/libavcodec/proresdsp.c b/libavcodec/proresdsp.c index b52306495..e62855493 100644 --- a/libavcodec/proresdsp.c +++ b/libavcodec/proresdsp.c @@ -23,7 +23,7 @@ #include "config.h" #include "libavutil/attributes.h" #include "libavutil/common.h" -#include "dsputil.h" +#include "idctdsp.h" #include "proresdsp.h" #include "simple_idct.h" diff --git a/libavcodec/proresenc_anatoliy.c b/libavcodec/proresenc_anatoliy.c index 80ce1359c..b2445caba 100644 --- a/libavcodec/proresenc_anatoliy.c +++ b/libavcodec/proresenc_anatoliy.c @@ -32,6 +32,7 @@ #include "put_bits.h" #include "bytestream.h" #include "dsputil.h" +#include "fdctdsp.h" #define DEFAULT_SLICE_MB_WIDTH 8 @@ -145,6 +146,7 @@ static const uint8_t QMAT_CHROMA[4][64] = { typedef struct { + FDCTDSPContext fdsp; uint8_t* fill_y; uint8_t* fill_u; uint8_t* fill_v; @@ -183,11 +185,11 @@ static void encode_codeword(PutBitContext *pb, int val, int codebook) } } -#define QSCALE(qmat,ind,val) ((val) / (qmat[ind])) -#define TO_GOLOMB(val) ((val << 1) ^ (val >> 31)) -#define DIFF_SIGN(val, sign) ((val >> 31) ^ sign) -#define IS_NEGATIVE(val) (((val >> 31) ^ -1) + 1) -#define TO_GOLOMB2(val,sign) (val==0 ? 0 : (val << 1) + sign) +#define QSCALE(qmat,ind,val) ((val) / ((qmat)[ind])) +#define TO_GOLOMB(val) (((val) << 1) ^ ((val) >> 31)) +#define DIFF_SIGN(val, sign) (((val) >> 31) ^ (sign)) +#define IS_NEGATIVE(val) ((((val) >> 31) ^ -1) + 1) +#define TO_GOLOMB2(val,sign) ((val)==0 ? 0 : ((val) << 1) + (sign)) static av_always_inline int get_level(int val) { @@ -263,40 +265,39 @@ static void encode_ac_coeffs(AVCodecContext *avctx, PutBitContext *pb, static void get(uint8_t *pixels, int stride, int16_t* block) { - int16_t *p = (int16_t*)pixels; - int i, j; + int i; - stride >>= 1; for (i = 0; i < 8; i++) { - for (j = 0; j < 8; j++) { - block[j] = p[j]; - } - p += stride; + AV_WN64(block, AV_RN64(pixels)); + AV_WN64(block+4, AV_RN64(pixels+8)); + pixels += stride; block += 8; } } -static void fdct_get(uint8_t *pixels, int stride, int16_t* block) +static void fdct_get(FDCTDSPContext *fdsp, uint8_t *pixels, int stride, int16_t* block) { get(pixels, stride, block); - ff_jpeg_fdct_islow_10(block); + fdsp->fdct(block); } static int encode_slice_plane(AVCodecContext *avctx, int mb_count, uint8_t *src, int src_stride, uint8_t *buf, unsigned buf_size, int *qmat, int chroma) { + ProresContext* ctx = avctx->priv_data; + FDCTDSPContext *fdsp = &ctx->fdsp; DECLARE_ALIGNED(16, int16_t, blocks)[DEFAULT_SLICE_MB_WIDTH << 8], *block; int i, blocks_per_slice; PutBitContext pb; block = blocks; for (i = 0; i < mb_count; i++) { - fdct_get(src, src_stride, block + (0 << 6)); - fdct_get(src + 8 * src_stride, src_stride, block + ((2 - chroma) << 6)); + fdct_get(fdsp, src, src_stride, block + (0 << 6)); + fdct_get(fdsp, src + 8 * src_stride, src_stride, block + ((2 - chroma) << 6)); if (!chroma) { - fdct_get(src + 16, src_stride, block + (1 << 6)); - fdct_get(src + 16 + 8 * src_stride, src_stride, block + (3 << 6)); + fdct_get(fdsp, src + 16, src_stride, block + (1 << 6)); + fdct_get(fdsp, src + 16 + 8 * src_stride, src_stride, block + (3 << 6)); } block += (256 >> chroma); @@ -545,12 +546,20 @@ static av_cold int prores_encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "need YUV422P10\n"); return -1; } + avctx->bits_per_raw_sample = 10; + if (avctx->width & 0x1) { av_log(avctx, AV_LOG_ERROR, "frame width needs to be multiple of 2\n"); return -1; } + if (avctx->width > 65534 || avctx->height > 65535) { + av_log(avctx, AV_LOG_ERROR, + "The maximum dimensions are 65534x65535\n"); + return AVERROR(EINVAL); + } + if ((avctx->height & 0xf) || (avctx->width & 0xf)) { ctx->fill_y = av_malloc(4 * (DEFAULT_SLICE_MB_WIDTH << 8)); if (!ctx->fill_y) @@ -574,6 +583,8 @@ static av_cold int prores_encode_init(AVCodecContext *avctx) return -1; } + ff_fdctdsp_init(&ctx->fdsp, avctx); + avctx->codec_tag = AV_RL32((const uint8_t*)profiles[avctx->profile].name); for (i = 1; i <= 16; i++) { diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c index ea1fd8ae7..93bcde727 100644 --- a/libavcodec/proresenc_kostya.c +++ b/libavcodec/proresenc_kostya.c @@ -26,8 +26,7 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avcodec.h" -#include "dct.h" -#include "dsputil.h" +#include "fdctdsp.h" #include "put_bits.h" #include "bytestream.h" #include "internal.h" @@ -195,9 +194,9 @@ typedef struct ProresContext { const uint8_t *quant_mat; const uint8_t *scantable; - void (* fdct)(DSPContext *dsp, const uint16_t *src, - int linesize, int16_t *block); - DSPContext dsp; + void (*fdct)(FDCTDSPContext *fdsp, const uint16_t *src, + int linesize, int16_t *block); + FDCTDSPContext fdsp; int mb_width, mb_height; int mbs_per_slice; @@ -266,27 +265,27 @@ static void get_slice_data(ProresContext *ctx, const uint16_t *src, mb_width * sizeof(*emu_buf)); } if (!is_chroma) { - ctx->fdct(&ctx->dsp, esrc, elinesize, blocks); + ctx->fdct(&ctx->fdsp, esrc, elinesize, blocks); blocks += 64; if (blocks_per_mb > 2) { - ctx->fdct(&ctx->dsp, esrc + 8, elinesize, blocks); + ctx->fdct(&ctx->fdsp, esrc + 8, elinesize, blocks); blocks += 64; } - ctx->fdct(&ctx->dsp, esrc + elinesize * 4, elinesize, blocks); + ctx->fdct(&ctx->fdsp, esrc + elinesize * 4, elinesize, blocks); blocks += 64; if (blocks_per_mb > 2) { - ctx->fdct(&ctx->dsp, esrc + elinesize * 4 + 8, elinesize, blocks); + ctx->fdct(&ctx->fdsp, esrc + elinesize * 4 + 8, elinesize, blocks); blocks += 64; } } else { - ctx->fdct(&ctx->dsp, esrc, elinesize, blocks); + ctx->fdct(&ctx->fdsp, esrc, elinesize, blocks); blocks += 64; - ctx->fdct(&ctx->dsp, esrc + elinesize * 4, elinesize, blocks); + ctx->fdct(&ctx->fdsp, esrc + elinesize * 4, elinesize, blocks); blocks += 64; if (blocks_per_mb > 2) { - ctx->fdct(&ctx->dsp, esrc + 8, elinesize, blocks); + ctx->fdct(&ctx->fdsp, esrc + 8, elinesize, blocks); blocks += 64; - ctx->fdct(&ctx->dsp, esrc + elinesize * 4 + 8, elinesize, blocks); + ctx->fdct(&ctx->fdsp, esrc + elinesize * 4 + 8, elinesize, blocks); blocks += 64; } } @@ -1066,7 +1065,7 @@ static av_cold int encode_close(AVCodecContext *avctx) return 0; } -static void prores_fdct(DSPContext *dsp, const uint16_t *src, +static void prores_fdct(FDCTDSPContext *fdsp, const uint16_t *src, int linesize, int16_t *block) { int x, y; @@ -1077,7 +1076,7 @@ static void prores_fdct(DSPContext *dsp, const uint16_t *src, block[y * 8 + x] = tsrc[x]; tsrc += linesize >> 1; } - dsp->fdct(block); + fdsp->fdct(block); } static av_cold int encode_init(AVCodecContext *avctx) @@ -1096,7 +1095,7 @@ static av_cold int encode_init(AVCodecContext *avctx) ctx->fdct = prores_fdct; ctx->scantable = interlaced ? ff_prores_interlaced_scan : ff_prores_progressive_scan; - ff_dsputil_init(&ctx->dsp, avctx); + ff_fdctdsp_init(&ctx->fdsp, avctx); mps = ctx->mbs_per_slice; if (mps & (mps - 1)) { diff --git a/libavcodec/psymodel.c b/libavcodec/psymodel.c index bfc85b3bc..22d2497f7 100644 --- a/libavcodec/psymodel.c +++ b/libavcodec/psymodel.c @@ -35,10 +35,10 @@ av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, int num_lens, int i, j, k = 0; ctx->avctx = avctx; - ctx->ch = av_mallocz(sizeof(ctx->ch[0]) * avctx->channels * 2); - ctx->group = av_mallocz(sizeof(ctx->group[0]) * num_groups); - ctx->bands = av_malloc (sizeof(ctx->bands[0]) * num_lens); - ctx->num_bands = av_malloc (sizeof(ctx->num_bands[0]) * num_lens); + ctx->ch = av_mallocz_array(sizeof(ctx->ch[0]), avctx->channels * 2); + ctx->group = av_mallocz_array(sizeof(ctx->group[0]), num_groups); + ctx->bands = av_malloc_array (sizeof(ctx->bands[0]), num_lens); + ctx->num_bands = av_malloc_array (sizeof(ctx->num_bands[0]), num_lens); memcpy(ctx->bands, bands, sizeof(ctx->bands[0]) * num_lens); memcpy(ctx->num_bands, num_bands, sizeof(ctx->num_bands[0]) * num_lens); @@ -112,7 +112,7 @@ av_cold struct FFPsyPreprocessContext* ff_psy_preprocess_init(AVCodecContext *av FF_FILTER_MODE_LOWPASS, FILT_ORDER, cutoff_coeff, 0.0, 0.0); if (ctx->fcoeffs) { - ctx->fstate = av_mallocz(sizeof(ctx->fstate[0]) * avctx->channels); + ctx->fstate = av_mallocz_array(sizeof(ctx->fstate[0]), avctx->channels); for (i = 0; i < avctx->channels; i++) ctx->fstate[i] = ff_iir_filter_init_state(FILT_ORDER); } diff --git a/libavcodec/psymodel.h b/libavcodec/psymodel.h index d1a126a88..75261ba4b 100644 --- a/libavcodec/psymodel.h +++ b/libavcodec/psymodel.h @@ -29,7 +29,7 @@ /** maximum number of channels */ #define PSY_MAX_CHANS 20 -#define AAC_CUTOFF(s) (s->bit_rate ? FFMIN3(4000 + s->bit_rate/8, 12000 + s->bit_rate/32, s->sample_rate / 2) : (s->sample_rate / 2)) +#define AAC_CUTOFF(s) ((s)->bit_rate ? FFMIN3(4000 + (s)->bit_rate/8, 12000 + (s)->bit_rate/32, (s)->sample_rate / 2) : ((s)->sample_rate / 2)) /** * single band psychoacoustic information diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index addcecc70..2a67f4d26 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -65,8 +65,6 @@ typedef struct PerThreadContext { AVCodecContext *avctx; ///< Context used to decode packets passed to this thread. AVPacket avpkt; ///< Input packet (for decoding) or output (for encoding). - uint8_t *buf; ///< backup storage for packet data when the input packet is not refcounted - int allocated_buf_size; ///< Size allocated for buf AVFrame *frame; ///< Output frame (for decoding) or input (for encoding). int got_frame; ///< The output of got_picture_ptr from the last avcodec_decode_video() call. @@ -121,8 +119,13 @@ typedef struct FrameThreadContext { int die; ///< Set when threads should exit. } FrameThreadContext; +#if FF_API_GET_BUFFER #define THREAD_SAFE_CALLBACKS(avctx) \ ((avctx)->thread_safe_callbacks || (!(avctx)->get_buffer && (avctx)->get_buffer2 == avcodec_default_get_buffer2)) +#else +#define THREAD_SAFE_CALLBACKS(avctx) \ +((avctx)->thread_safe_callbacks || (avctx)->get_buffer2 == avcodec_default_get_buffer2) +#endif /** * Codec worker thread. @@ -226,6 +229,7 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, dst->sample_rate = src->sample_rate; dst->sample_fmt = src->sample_fmt; dst->channel_layout = src->channel_layout; + dst->internal->hwaccel_priv_data = src->internal->hwaccel_priv_data; } if (for_user) { @@ -317,7 +321,6 @@ static int submit_packet(PerThreadContext *p, AVPacket *avpkt) FrameThreadContext *fctx = p->parent; PerThreadContext *prev_thread = fctx->prev_thread; const AVCodec *codec = p->avctx->codec; - int ret; if (!avpkt->size && !(codec->capabilities & CODEC_CAP_DELAY)) return 0; @@ -341,25 +344,8 @@ static int submit_packet(PerThreadContext *p, AVPacket *avpkt) } } - av_packet_free_side_data(&p->avpkt); - av_buffer_unref(&p->avpkt.buf); - p->avpkt = *avpkt; - if (avpkt->buf) - p->avpkt.buf = av_buffer_ref(avpkt->buf); - else { - av_fast_malloc(&p->buf, &p->allocated_buf_size, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!p->buf) { - pthread_mutex_unlock(&p->mutex); - return AVERROR(ENOMEM); - } - p->avpkt.data = p->buf; - memcpy(p->buf, avpkt->data, avpkt->size); - memset(p->buf + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); - } - if ((ret = av_copy_packet_side_data(&p->avpkt, avpkt)) < 0) { - pthread_mutex_unlock(&p->mutex); - return ret; - } + av_packet_unref(&p->avpkt); + av_packet_ref(&p->avpkt, avpkt); p->state = STATE_SETTING_UP; pthread_cond_signal(&p->input_cond); @@ -390,7 +376,7 @@ FF_ENABLE_DEPRECATION_WARNINGS p->result = ff_get_buffer(p->avctx, p->requested_frame, p->requested_flags); break; case STATE_GET_FORMAT: - p->result_format = p->avctx->get_format(p->avctx, p->available_formats); + p->result_format = ff_get_format(p->avctx, p->available_formats); break; default: call_done = 0; @@ -598,9 +584,7 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) pthread_cond_destroy(&p->input_cond); pthread_cond_destroy(&p->progress_cond); pthread_cond_destroy(&p->output_cond); - av_packet_free_side_data(&p->avpkt); - av_buffer_unref(&p->avpkt.buf); - av_freep(&p->buf); + av_packet_unref(&p->avpkt); av_freep(&p->released_buffers); if (i) { @@ -647,7 +631,7 @@ int ff_frame_thread_init(AVCodecContext *avctx) avctx->internal->thread_ctx = fctx = av_mallocz(sizeof(FrameThreadContext)); - fctx->threads = av_mallocz(sizeof(PerThreadContext) * thread_count); + fctx->threads = av_mallocz_array(thread_count, sizeof(PerThreadContext)); pthread_mutex_init(&fctx->buffer_mutex, NULL); fctx->delaying = 1; @@ -832,7 +816,7 @@ enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixe PerThreadContext *p = avctx->internal->thread_ctx; if (!(avctx->active_thread_type & FF_THREAD_FRAME) || avctx->thread_safe_callbacks || avctx->get_format == avcodec_default_get_format) - return avctx->get_format(avctx, fmt); + return ff_get_format(avctx, fmt); if (p->state != STATE_SETTING_UP) { av_log(avctx, AV_LOG_ERROR, "get_format() cannot be called after ff_thread_finish_setup()\n"); return -1; @@ -875,7 +859,7 @@ FF_DISABLE_DEPRECATION_WARNINGS avctx->get_buffer2 == avcodec_default_get_buffer2); FF_ENABLE_DEPRECATION_WARNINGS - if (!f->f->buf[0]) + if (!f->f || !f->f->buf[0]) return; if (avctx->debug & FF_DEBUG_BUFFERS) diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c index edfe9c662..334aaac0f 100644 --- a/libavcodec/pthread_slice.c +++ b/libavcodec/pthread_slice.c @@ -201,7 +201,7 @@ int ff_slice_thread_init(AVCodecContext *avctx) if (!c) return -1; - c->workers = av_mallocz(sizeof(pthread_t)*thread_count); + c->workers = av_mallocz_array(thread_count, sizeof(pthread_t)); if (!c->workers) { av_free(c); return -1; @@ -266,15 +266,15 @@ int ff_alloc_entries(AVCodecContext *avctx, int count) if (avctx->active_thread_type & FF_THREAD_SLICE) { SliceThreadContext *p = avctx->internal->thread_ctx; p->thread_count = avctx->thread_count; - p->entries = av_mallocz(count * sizeof(int)); + p->entries = av_mallocz_array(count, sizeof(int)); if (!p->entries) { return AVERROR(ENOMEM); } p->entries_count = count; - p->progress_mutex = av_malloc(p->thread_count * sizeof(pthread_mutex_t)); - p->progress_cond = av_malloc(p->thread_count * sizeof(pthread_cond_t)); + p->progress_mutex = av_malloc_array(p->thread_count, sizeof(pthread_mutex_t)); + p->progress_cond = av_malloc_array(p->thread_count, sizeof(pthread_cond_t)); for (i = 0; i < p->thread_count; i++) { pthread_mutex_init(&p->progress_mutex[i], NULL); diff --git a/libavcodec/put_bits.h b/libavcodec/put_bits.h index e2c4a6179..8081fb9ea 100644 --- a/libavcodec/put_bits.h +++ b/libavcodec/put_bits.h @@ -27,16 +27,11 @@ #define AVCODEC_PUT_BITS_H #include -#include +#include #include -#include "libavutil/bswap.h" -#include "libavutil/common.h" #include "libavutil/intreadwrite.h" -#include "libavutil/log.h" #include "libavutil/avassert.h" -#include "mathops.h" -#include "config.h" typedef struct PutBitContext { uint32_t bit_buf; diff --git a/libavcodec/qpel_template.c b/libavcodec/qpel_template.c new file mode 100644 index 000000000..e52a78cf2 --- /dev/null +++ b/libavcodec/qpel_template.c @@ -0,0 +1,221 @@ +/* + * quarterpel DSP function templates + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * quarterpel DSP function templates + */ + +#define PIXOP2(OPNAME, OP) \ +static inline void OPNAME ## _no_rnd_pixels8_l2_8(uint8_t *dst, \ + const uint8_t *src1, \ + const uint8_t *src2, \ + int dst_stride, \ + int src_stride1, \ + int src_stride2, \ + int h) \ +{ \ + int i; \ + \ + for (i = 0; i < h; i++) { \ + uint32_t a, b; \ + a = AV_RN32(&src1[i * src_stride1]); \ + b = AV_RN32(&src2[i * src_stride2]); \ + OP(*((uint32_t *) &dst[i * dst_stride]), \ + no_rnd_avg32(a, b)); \ + a = AV_RN32(&src1[i * src_stride1 + 4]); \ + b = AV_RN32(&src2[i * src_stride2 + 4]); \ + OP(*((uint32_t *) &dst[i * dst_stride + 4]), \ + no_rnd_avg32(a, b)); \ + } \ +} \ + \ +static inline void OPNAME ## _no_rnd_pixels16_l2_8(uint8_t *dst, \ + const uint8_t *src1, \ + const uint8_t *src2, \ + int dst_stride, \ + int src_stride1, \ + int src_stride2, \ + int h) \ +{ \ + OPNAME ## _no_rnd_pixels8_l2_8(dst, src1, src2, dst_stride, \ + src_stride1, src_stride2, h); \ + OPNAME ## _no_rnd_pixels8_l2_8(dst + 8, \ + src1 + 8, \ + src2 + 8, \ + dst_stride, src_stride1, \ + src_stride2, h); \ +} \ + \ +static inline void OPNAME ## _pixels8_l4_8(uint8_t *dst, \ + const uint8_t *src1, \ + const uint8_t *src2, \ + const uint8_t *src3, \ + const uint8_t *src4, \ + int dst_stride, \ + int src_stride1, \ + int src_stride2, \ + int src_stride3, \ + int src_stride4, \ + int h) \ +{ \ + /* FIXME HIGH BIT DEPTH */ \ + int i; \ + \ + for (i = 0; i < h; i++) { \ + uint32_t a, b, c, d, l0, l1, h0, h1; \ + a = AV_RN32(&src1[i * src_stride1]); \ + b = AV_RN32(&src2[i * src_stride2]); \ + c = AV_RN32(&src3[i * src_stride3]); \ + d = AV_RN32(&src4[i * src_stride4]); \ + l0 = (a & 0x03030303UL) + \ + (b & 0x03030303UL) + \ + 0x02020202UL; \ + h0 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + l1 = (c & 0x03030303UL) + \ + (d & 0x03030303UL); \ + h1 = ((c & 0xFCFCFCFCUL) >> 2) + \ + ((d & 0xFCFCFCFCUL) >> 2); \ + OP(*((uint32_t *) &dst[i * dst_stride]), \ + h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL)); \ + a = AV_RN32(&src1[i * src_stride1 + 4]); \ + b = AV_RN32(&src2[i * src_stride2 + 4]); \ + c = AV_RN32(&src3[i * src_stride3 + 4]); \ + d = AV_RN32(&src4[i * src_stride4 + 4]); \ + l0 = (a & 0x03030303UL) + \ + (b & 0x03030303UL) + \ + 0x02020202UL; \ + h0 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + l1 = (c & 0x03030303UL) + \ + (d & 0x03030303UL); \ + h1 = ((c & 0xFCFCFCFCUL) >> 2) + \ + ((d & 0xFCFCFCFCUL) >> 2); \ + OP(*((uint32_t *) &dst[i * dst_stride + 4]), \ + h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL)); \ + } \ +} \ + \ +static inline void OPNAME ## _no_rnd_pixels8_l4_8(uint8_t *dst, \ + const uint8_t *src1, \ + const uint8_t *src2, \ + const uint8_t *src3, \ + const uint8_t *src4, \ + int dst_stride, \ + int src_stride1, \ + int src_stride2, \ + int src_stride3, \ + int src_stride4, \ + int h) \ +{ \ + /* FIXME HIGH BIT DEPTH */ \ + int i; \ + \ + for (i = 0; i < h; i++) { \ + uint32_t a, b, c, d, l0, l1, h0, h1; \ + a = AV_RN32(&src1[i * src_stride1]); \ + b = AV_RN32(&src2[i * src_stride2]); \ + c = AV_RN32(&src3[i * src_stride3]); \ + d = AV_RN32(&src4[i * src_stride4]); \ + l0 = (a & 0x03030303UL) + \ + (b & 0x03030303UL) + \ + 0x01010101UL; \ + h0 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + l1 = (c & 0x03030303UL) + \ + (d & 0x03030303UL); \ + h1 = ((c & 0xFCFCFCFCUL) >> 2) + \ + ((d & 0xFCFCFCFCUL) >> 2); \ + OP(*((uint32_t *) &dst[i * dst_stride]), \ + h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL)); \ + a = AV_RN32(&src1[i * src_stride1 + 4]); \ + b = AV_RN32(&src2[i * src_stride2 + 4]); \ + c = AV_RN32(&src3[i * src_stride3 + 4]); \ + d = AV_RN32(&src4[i * src_stride4 + 4]); \ + l0 = (a & 0x03030303UL) + \ + (b & 0x03030303UL) + \ + 0x01010101UL; \ + h0 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + l1 = (c & 0x03030303UL) + \ + (d & 0x03030303UL); \ + h1 = ((c & 0xFCFCFCFCUL) >> 2) + \ + ((d & 0xFCFCFCFCUL) >> 2); \ + OP(*((uint32_t *) &dst[i * dst_stride + 4]), \ + h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL)); \ + } \ +} \ + \ +static inline void OPNAME ## _pixels16_l4_8(uint8_t *dst, \ + const uint8_t *src1, \ + const uint8_t *src2, \ + const uint8_t *src3, \ + const uint8_t *src4, \ + int dst_stride, \ + int src_stride1, \ + int src_stride2, \ + int src_stride3, \ + int src_stride4, \ + int h) \ +{ \ + OPNAME ## _pixels8_l4_8(dst, src1, src2, src3, src4, dst_stride, \ + src_stride1, src_stride2, src_stride3, \ + src_stride4, h); \ + OPNAME ## _pixels8_l4_8(dst + 8, \ + src1 + 8, src2 + 8, \ + src3 + 8, src4 + 8, \ + dst_stride, src_stride1, src_stride2, \ + src_stride3, src_stride4, h); \ +} \ + \ +static inline void OPNAME ## _no_rnd_pixels16_l4_8(uint8_t *dst, \ + const uint8_t *src1, \ + const uint8_t *src2, \ + const uint8_t *src3, \ + const uint8_t *src4, \ + int dst_stride, \ + int src_stride1, \ + int src_stride2, \ + int src_stride3, \ + int src_stride4, \ + int h) \ +{ \ + OPNAME ## _no_rnd_pixels8_l4_8(dst, src1, src2, src3, src4, \ + dst_stride, src_stride1, \ + src_stride2, src_stride3, \ + src_stride4, h); \ + OPNAME ## _no_rnd_pixels8_l4_8(dst + 8, \ + src1 + 8, src2 + 8, \ + src3 + 8, src4 + 8, \ + dst_stride, src_stride1, \ + src_stride2, src_stride3, \ + src_stride4, h); \ +} \ + +#define op_avg(a, b) a = rnd_avg32(a, b) +#define op_put(a, b) a = b +#define put_no_rnd_pixels8_8_c put_pixels8_8_c +PIXOP2(avg, op_avg) +PIXOP2(put, op_put) +#undef op_avg +#undef op_put diff --git a/libavcodec/qpeldsp.c b/libavcodec/qpeldsp.c new file mode 100644 index 000000000..d9115d0e1 --- /dev/null +++ b/libavcodec/qpeldsp.c @@ -0,0 +1,812 @@ +/* + * quarterpel DSP functions + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * quarterpel DSP functions + */ + +#include +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "copy_block.h" +#include "qpeldsp.h" +#include "diracdsp.h" + +#define BIT_DEPTH 8 +#include "hpel_template.c" +#include "pel_template.c" +#include "qpel_template.c" + +#define QPEL_MC(r, OPNAME, RND, OP) \ +static void OPNAME ## mpeg4_qpel8_h_lowpass(uint8_t *dst, uint8_t *src, \ + int dstStride, int srcStride, \ + int h) \ +{ \ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; \ + int i; \ + \ + for (i = 0; i < h; i++) { \ + OP(dst[0], (src[0] + src[1]) * 20 - (src[0] + src[2]) * 6 + (src[1] + src[3]) * 3 - (src[2] + src[4])); \ + OP(dst[1], (src[1] + src[2]) * 20 - (src[0] + src[3]) * 6 + (src[0] + src[4]) * 3 - (src[1] + src[5])); \ + OP(dst[2], (src[2] + src[3]) * 20 - (src[1] + src[4]) * 6 + (src[0] + src[5]) * 3 - (src[0] + src[6])); \ + OP(dst[3], (src[3] + src[4]) * 20 - (src[2] + src[5]) * 6 + (src[1] + src[6]) * 3 - (src[0] + src[7])); \ + OP(dst[4], (src[4] + src[5]) * 20 - (src[3] + src[6]) * 6 + (src[2] + src[7]) * 3 - (src[1] + src[8])); \ + OP(dst[5], (src[5] + src[6]) * 20 - (src[4] + src[7]) * 6 + (src[3] + src[8]) * 3 - (src[2] + src[8])); \ + OP(dst[6], (src[6] + src[7]) * 20 - (src[5] + src[8]) * 6 + (src[4] + src[8]) * 3 - (src[3] + src[7])); \ + OP(dst[7], (src[7] + src[8]) * 20 - (src[6] + src[8]) * 6 + (src[5] + src[7]) * 3 - (src[4] + src[6])); \ + dst += dstStride; \ + src += srcStride; \ + } \ +} \ + \ +static void OPNAME ## mpeg4_qpel8_v_lowpass(uint8_t *dst, uint8_t *src, \ + int dstStride, int srcStride) \ +{ \ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; \ + const int w = 8; \ + int i; \ + \ + for (i = 0; i < w; i++) { \ + const int src0 = src[0 * srcStride]; \ + const int src1 = src[1 * srcStride]; \ + const int src2 = src[2 * srcStride]; \ + const int src3 = src[3 * srcStride]; \ + const int src4 = src[4 * srcStride]; \ + const int src5 = src[5 * srcStride]; \ + const int src6 = src[6 * srcStride]; \ + const int src7 = src[7 * srcStride]; \ + const int src8 = src[8 * srcStride]; \ + OP(dst[0 * dstStride], (src0 + src1) * 20 - (src0 + src2) * 6 + (src1 + src3) * 3 - (src2 + src4)); \ + OP(dst[1 * dstStride], (src1 + src2) * 20 - (src0 + src3) * 6 + (src0 + src4) * 3 - (src1 + src5)); \ + OP(dst[2 * dstStride], (src2 + src3) * 20 - (src1 + src4) * 6 + (src0 + src5) * 3 - (src0 + src6)); \ + OP(dst[3 * dstStride], (src3 + src4) * 20 - (src2 + src5) * 6 + (src1 + src6) * 3 - (src0 + src7)); \ + OP(dst[4 * dstStride], (src4 + src5) * 20 - (src3 + src6) * 6 + (src2 + src7) * 3 - (src1 + src8)); \ + OP(dst[5 * dstStride], (src5 + src6) * 20 - (src4 + src7) * 6 + (src3 + src8) * 3 - (src2 + src8)); \ + OP(dst[6 * dstStride], (src6 + src7) * 20 - (src5 + src8) * 6 + (src4 + src8) * 3 - (src3 + src7)); \ + OP(dst[7 * dstStride], (src7 + src8) * 20 - (src6 + src8) * 6 + (src5 + src7) * 3 - (src4 + src6)); \ + dst++; \ + src++; \ + } \ +} \ + \ +static void OPNAME ## mpeg4_qpel16_h_lowpass(uint8_t *dst, uint8_t *src, \ + int dstStride, int srcStride, \ + int h) \ +{ \ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; \ + int i; \ + \ + for (i = 0; i < h; i++) { \ + OP(dst[0], (src[0] + src[1]) * 20 - (src[0] + src[2]) * 6 + (src[1] + src[3]) * 3 - (src[2] + src[4])); \ + OP(dst[1], (src[1] + src[2]) * 20 - (src[0] + src[3]) * 6 + (src[0] + src[4]) * 3 - (src[1] + src[5])); \ + OP(dst[2], (src[2] + src[3]) * 20 - (src[1] + src[4]) * 6 + (src[0] + src[5]) * 3 - (src[0] + src[6])); \ + OP(dst[3], (src[3] + src[4]) * 20 - (src[2] + src[5]) * 6 + (src[1] + src[6]) * 3 - (src[0] + src[7])); \ + OP(dst[4], (src[4] + src[5]) * 20 - (src[3] + src[6]) * 6 + (src[2] + src[7]) * 3 - (src[1] + src[8])); \ + OP(dst[5], (src[5] + src[6]) * 20 - (src[4] + src[7]) * 6 + (src[3] + src[8]) * 3 - (src[2] + src[9])); \ + OP(dst[6], (src[6] + src[7]) * 20 - (src[5] + src[8]) * 6 + (src[4] + src[9]) * 3 - (src[3] + src[10])); \ + OP(dst[7], (src[7] + src[8]) * 20 - (src[6] + src[9]) * 6 + (src[5] + src[10]) * 3 - (src[4] + src[11])); \ + OP(dst[8], (src[8] + src[9]) * 20 - (src[7] + src[10]) * 6 + (src[6] + src[11]) * 3 - (src[5] + src[12])); \ + OP(dst[9], (src[9] + src[10]) * 20 - (src[8] + src[11]) * 6 + (src[7] + src[12]) * 3 - (src[6] + src[13])); \ + OP(dst[10], (src[10] + src[11]) * 20 - (src[9] + src[12]) * 6 + (src[8] + src[13]) * 3 - (src[7] + src[14])); \ + OP(dst[11], (src[11] + src[12]) * 20 - (src[10] + src[13]) * 6 + (src[9] + src[14]) * 3 - (src[8] + src[15])); \ + OP(dst[12], (src[12] + src[13]) * 20 - (src[11] + src[14]) * 6 + (src[10] + src[15]) * 3 - (src[9] + src[16])); \ + OP(dst[13], (src[13] + src[14]) * 20 - (src[12] + src[15]) * 6 + (src[11] + src[16]) * 3 - (src[10] + src[16])); \ + OP(dst[14], (src[14] + src[15]) * 20 - (src[13] + src[16]) * 6 + (src[12] + src[16]) * 3 - (src[11] + src[15])); \ + OP(dst[15], (src[15] + src[16]) * 20 - (src[14] + src[16]) * 6 + (src[13] + src[15]) * 3 - (src[12] + src[14])); \ + dst += dstStride; \ + src += srcStride; \ + } \ +} \ + \ +static void OPNAME ## mpeg4_qpel16_v_lowpass(uint8_t *dst, uint8_t *src, \ + int dstStride, int srcStride) \ +{ \ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; \ + const int w = 16; \ + int i; \ + \ + for (i = 0; i < w; i++) { \ + const int src0 = src[0 * srcStride]; \ + const int src1 = src[1 * srcStride]; \ + const int src2 = src[2 * srcStride]; \ + const int src3 = src[3 * srcStride]; \ + const int src4 = src[4 * srcStride]; \ + const int src5 = src[5 * srcStride]; \ + const int src6 = src[6 * srcStride]; \ + const int src7 = src[7 * srcStride]; \ + const int src8 = src[8 * srcStride]; \ + const int src9 = src[9 * srcStride]; \ + const int src10 = src[10 * srcStride]; \ + const int src11 = src[11 * srcStride]; \ + const int src12 = src[12 * srcStride]; \ + const int src13 = src[13 * srcStride]; \ + const int src14 = src[14 * srcStride]; \ + const int src15 = src[15 * srcStride]; \ + const int src16 = src[16 * srcStride]; \ + OP(dst[0 * dstStride], (src0 + src1) * 20 - (src0 + src2) * 6 + (src1 + src3) * 3 - (src2 + src4)); \ + OP(dst[1 * dstStride], (src1 + src2) * 20 - (src0 + src3) * 6 + (src0 + src4) * 3 - (src1 + src5)); \ + OP(dst[2 * dstStride], (src2 + src3) * 20 - (src1 + src4) * 6 + (src0 + src5) * 3 - (src0 + src6)); \ + OP(dst[3 * dstStride], (src3 + src4) * 20 - (src2 + src5) * 6 + (src1 + src6) * 3 - (src0 + src7)); \ + OP(dst[4 * dstStride], (src4 + src5) * 20 - (src3 + src6) * 6 + (src2 + src7) * 3 - (src1 + src8)); \ + OP(dst[5 * dstStride], (src5 + src6) * 20 - (src4 + src7) * 6 + (src3 + src8) * 3 - (src2 + src9)); \ + OP(dst[6 * dstStride], (src6 + src7) * 20 - (src5 + src8) * 6 + (src4 + src9) * 3 - (src3 + src10)); \ + OP(dst[7 * dstStride], (src7 + src8) * 20 - (src6 + src9) * 6 + (src5 + src10) * 3 - (src4 + src11)); \ + OP(dst[8 * dstStride], (src8 + src9) * 20 - (src7 + src10) * 6 + (src6 + src11) * 3 - (src5 + src12)); \ + OP(dst[9 * dstStride], (src9 + src10) * 20 - (src8 + src11) * 6 + (src7 + src12) * 3 - (src6 + src13)); \ + OP(dst[10 * dstStride], (src10 + src11) * 20 - (src9 + src12) * 6 + (src8 + src13) * 3 - (src7 + src14)); \ + OP(dst[11 * dstStride], (src11 + src12) * 20 - (src10 + src13) * 6 + (src9 + src14) * 3 - (src8 + src15)); \ + OP(dst[12 * dstStride], (src12 + src13) * 20 - (src11 + src14) * 6 + (src10 + src15) * 3 - (src9 + src16)); \ + OP(dst[13 * dstStride], (src13 + src14) * 20 - (src12 + src15) * 6 + (src11 + src16) * 3 - (src10 + src16)); \ + OP(dst[14 * dstStride], (src14 + src15) * 20 - (src13 + src16) * 6 + (src12 + src16) * 3 - (src11 + src15)); \ + OP(dst[15 * dstStride], (src15 + src16) * 20 - (src14 + src16) * 6 + (src13 + src15) * 3 - (src12 + src14)); \ + dst++; \ + src++; \ + } \ +} \ + \ +static void OPNAME ## qpel8_mc10_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t half[64]; \ + \ + put ## RND ## mpeg4_qpel8_h_lowpass(half, src, 8, stride, 8); \ + OPNAME ## pixels8_l2_8(dst, src, half, stride, stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc20_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + OPNAME ## mpeg4_qpel8_h_lowpass(dst, src, stride, stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc30_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t half[64]; \ + \ + put ## RND ## mpeg4_qpel8_h_lowpass(half, src, 8, stride, 8); \ + OPNAME ## pixels8_l2_8(dst, src + 1, half, stride, stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc01_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t half[64]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(half, full, 8, 16); \ + OPNAME ## pixels8_l2_8(dst, full, half, stride, 16, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc02_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + OPNAME ## mpeg4_qpel8_v_lowpass(dst, full, stride, 16); \ +} \ + \ +static void OPNAME ## qpel8_mc03_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t half[64]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(half, full, 8, 16); \ + OPNAME ## pixels8_l2_8(dst, full + 16, half, stride, 16, 8, 8); \ +} \ + \ +void ff_ ## OPNAME ## qpel8_mc11_old_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t halfH[72]; \ + uint8_t halfV[64]; \ + uint8_t halfHV[64]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full, 8, 16); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8); \ + OPNAME ## pixels8_l4_8(dst, full, halfH, halfV, halfHV, \ + stride, 16, 8, 8, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc11_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t halfH[72]; \ + uint8_t halfHV[64]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9); \ + put ## RND ## pixels8_l2_8(halfH, halfH, full, 8, 8, 16, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8); \ + OPNAME ## pixels8_l2_8(dst, halfH, halfHV, stride, 8, 8, 8); \ +} \ + \ +void ff_ ## OPNAME ## qpel8_mc31_old_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t halfH[72]; \ + uint8_t halfV[64]; \ + uint8_t halfHV[64]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full + 1, 8, 16); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8); \ + OPNAME ## pixels8_l4_8(dst, full + 1, halfH, halfV, halfHV, \ + stride, 16, 8, 8, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc31_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t halfH[72]; \ + uint8_t halfHV[64]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9); \ + put ## RND ## pixels8_l2_8(halfH, halfH, full + 1, 8, 8, 16, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8); \ + OPNAME ## pixels8_l2_8(dst, halfH, halfHV, stride, 8, 8, 8); \ +} \ + \ +void ff_ ## OPNAME ## qpel8_mc13_old_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t halfH[72]; \ + uint8_t halfV[64]; \ + uint8_t halfHV[64]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full, 8, 16); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8); \ + OPNAME ## pixels8_l4_8(dst, full + 16, halfH + 8, halfV, halfHV, \ + stride, 16, 8, 8, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc13_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t halfH[72]; \ + uint8_t halfHV[64]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9); \ + put ## RND ## pixels8_l2_8(halfH, halfH, full, 8, 8, 16, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8); \ + OPNAME ## pixels8_l2_8(dst, halfH + 8, halfHV, stride, 8, 8, 8); \ +} \ + \ +void ff_ ## OPNAME ## qpel8_mc33_old_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t halfH[72]; \ + uint8_t halfV[64]; \ + uint8_t halfHV[64]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full + 1, 8, 16); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8); \ + OPNAME ## pixels8_l4_8(dst, full + 17, halfH + 8, halfV, halfHV, \ + stride, 16, 8, 8, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc33_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t halfH[72]; \ + uint8_t halfHV[64]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9); \ + put ## RND ## pixels8_l2_8(halfH, halfH, full + 1, 8, 8, 16, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8); \ + OPNAME ## pixels8_l2_8(dst, halfH + 8, halfHV, stride, 8, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc21_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t halfH[72]; \ + uint8_t halfHV[64]; \ + \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, src, 8, stride, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8); \ + OPNAME ## pixels8_l2_8(dst, halfH, halfHV, stride, 8, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc23_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t halfH[72]; \ + uint8_t halfHV[64]; \ + \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, src, 8, stride, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8); \ + OPNAME ## pixels8_l2_8(dst, halfH + 8, halfHV, stride, 8, 8, 8); \ +} \ + \ +void ff_ ## OPNAME ## qpel8_mc12_old_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t halfH[72]; \ + uint8_t halfV[64]; \ + uint8_t halfHV[64]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full, 8, 16); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8); \ + OPNAME ## pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc12_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t halfH[72]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9); \ + put ## RND ## pixels8_l2_8(halfH, halfH, full, 8, 8, 16, 9); \ + OPNAME ## mpeg4_qpel8_v_lowpass(dst, halfH, stride, 8); \ +} \ + \ +void ff_ ## OPNAME ## qpel8_mc32_old_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t halfH[72]; \ + uint8_t halfV[64]; \ + uint8_t halfHV[64]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full + 1, 8, 16); \ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8); \ + OPNAME ## pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc32_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[16 * 9]; \ + uint8_t halfH[72]; \ + \ + copy_block9(full, src, 16, stride, 9); \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9); \ + put ## RND ## pixels8_l2_8(halfH, halfH, full + 1, 8, 8, 16, 9); \ + OPNAME ## mpeg4_qpel8_v_lowpass(dst, halfH, stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc22_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t halfH[72]; \ + \ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, src, 8, stride, 9); \ + OPNAME ## mpeg4_qpel8_v_lowpass(dst, halfH, stride, 8); \ +} \ + \ +static void OPNAME ## qpel16_mc10_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t half[256]; \ + \ + put ## RND ## mpeg4_qpel16_h_lowpass(half, src, 16, stride, 16); \ + OPNAME ## pixels16_l2_8(dst, src, half, stride, stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc20_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + OPNAME ## mpeg4_qpel16_h_lowpass(dst, src, stride, stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc30_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t half[256]; \ + \ + put ## RND ## mpeg4_qpel16_h_lowpass(half, src, 16, stride, 16); \ + OPNAME ## pixels16_l2_8(dst, src + 1, half, stride, stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc01_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t half[256]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(half, full, 16, 24); \ + OPNAME ## pixels16_l2_8(dst, full, half, stride, 24, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc02_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + OPNAME ## mpeg4_qpel16_v_lowpass(dst, full, stride, 24); \ +} \ + \ +static void OPNAME ## qpel16_mc03_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t half[256]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(half, full, 16, 24); \ + OPNAME ## pixels16_l2_8(dst, full + 24, half, stride, 24, 16, 16); \ +} \ + \ +void ff_ ## OPNAME ## qpel16_mc11_old_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t halfH[272]; \ + uint8_t halfV[256]; \ + uint8_t halfHV[256]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full, 16, 24); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16); \ + OPNAME ## pixels16_l4_8(dst, full, halfH, halfV, halfHV, \ + stride, 24, 16, 16, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc11_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t halfH[272]; \ + uint8_t halfHV[256]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17); \ + put ## RND ## pixels16_l2_8(halfH, halfH, full, 16, 16, 24, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16); \ + OPNAME ## pixels16_l2_8(dst, halfH, halfHV, stride, 16, 16, 16); \ +} \ + \ +void ff_ ## OPNAME ## qpel16_mc31_old_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t halfH[272]; \ + uint8_t halfV[256]; \ + uint8_t halfHV[256]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full + 1, 16, 24); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16); \ + OPNAME ## pixels16_l4_8(dst, full + 1, halfH, halfV, halfHV, \ + stride, 24, 16, 16, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc31_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t halfH[272]; \ + uint8_t halfHV[256]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17); \ + put ## RND ## pixels16_l2_8(halfH, halfH, full + 1, 16, 16, 24, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16); \ + OPNAME ## pixels16_l2_8(dst, halfH, halfHV, stride, 16, 16, 16); \ +} \ + \ +void ff_ ## OPNAME ## qpel16_mc13_old_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t halfH[272]; \ + uint8_t halfV[256]; \ + uint8_t halfHV[256]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full, 16, 24); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16); \ + OPNAME ## pixels16_l4_8(dst, full + 24, halfH + 16, halfV, halfHV, \ + stride, 24, 16, 16, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc13_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t halfH[272]; \ + uint8_t halfHV[256]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17); \ + put ## RND ## pixels16_l2_8(halfH, halfH, full, 16, 16, 24, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16); \ + OPNAME ## pixels16_l2_8(dst, halfH + 16, halfHV, stride, 16, 16, 16); \ +} \ + \ +void ff_ ## OPNAME ## qpel16_mc33_old_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t halfH[272]; \ + uint8_t halfV[256]; \ + uint8_t halfHV[256]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full + 1, 16, 24); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16); \ + OPNAME ## pixels16_l4_8(dst, full + 25, halfH + 16, halfV, halfHV, \ + stride, 24, 16, 16, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc33_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t halfH[272]; \ + uint8_t halfHV[256]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17); \ + put ## RND ## pixels16_l2_8(halfH, halfH, full + 1, 16, 16, 24, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16); \ + OPNAME ## pixels16_l2_8(dst, halfH + 16, halfHV, stride, 16, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc21_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t halfH[272]; \ + uint8_t halfHV[256]; \ + \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, src, 16, stride, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16); \ + OPNAME ## pixels16_l2_8(dst, halfH, halfHV, stride, 16, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc23_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t halfH[272]; \ + uint8_t halfHV[256]; \ + \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, src, 16, stride, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16); \ + OPNAME ## pixels16_l2_8(dst, halfH + 16, halfHV, stride, 16, 16, 16); \ +} \ + \ +void ff_ ## OPNAME ## qpel16_mc12_old_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t halfH[272]; \ + uint8_t halfV[256]; \ + uint8_t halfHV[256]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full, 16, 24); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16); \ + OPNAME ## pixels16_l2_8(dst, halfV, halfHV, stride, 16, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc12_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t halfH[272]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17); \ + put ## RND ## pixels16_l2_8(halfH, halfH, full, 16, 16, 24, 17); \ + OPNAME ## mpeg4_qpel16_v_lowpass(dst, halfH, stride, 16); \ +} \ + \ +void ff_ ## OPNAME ## qpel16_mc32_old_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t halfH[272]; \ + uint8_t halfV[256]; \ + uint8_t halfHV[256]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full + 1, 16, 24); \ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16); \ + OPNAME ## pixels16_l2_8(dst, halfV, halfHV, stride, 16, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc32_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t full[24 * 17]; \ + uint8_t halfH[272]; \ + \ + copy_block17(full, src, 24, stride, 17); \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17); \ + put ## RND ## pixels16_l2_8(halfH, halfH, full + 1, 16, 16, 24, 17); \ + OPNAME ## mpeg4_qpel16_v_lowpass(dst, halfH, stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc22_c(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint8_t halfH[272]; \ + \ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, src, 16, stride, 17); \ + OPNAME ## mpeg4_qpel16_v_lowpass(dst, halfH, stride, 16); \ +} + +#define op_avg(a, b) a = (((a) + cm[((b) + 16) >> 5] + 1) >> 1) +#define op_put(a, b) a = cm[((b) + 16) >> 5] +#define op_put_no_rnd(a, b) a = cm[((b) + 15) >> 5] + +QPEL_MC(0, put_, _, op_put) +QPEL_MC(1, put_no_rnd_, _no_rnd_, op_put_no_rnd) +QPEL_MC(0, avg_, _, op_avg) + +#undef op_avg +#undef op_put +#undef op_put_no_rnd + +void ff_put_pixels8x8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + put_pixels8_8_c(dst, src, stride, 8); +} + +void ff_avg_pixels8x8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + avg_pixels8_8_c(dst, src, stride, 8); +} + +void ff_put_pixels16x16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + put_pixels16_8_c(dst, src, stride, 16); +} + +void ff_avg_pixels16x16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + avg_pixels16_8_c(dst, src, stride, 16); +} + +#define put_qpel8_mc00_c ff_put_pixels8x8_c +#define avg_qpel8_mc00_c ff_avg_pixels8x8_c +#define put_qpel16_mc00_c ff_put_pixels16x16_c +#define avg_qpel16_mc00_c ff_avg_pixels16x16_c +#define put_no_rnd_qpel8_mc00_c ff_put_pixels8x8_c +#define put_no_rnd_qpel16_mc00_c ff_put_pixels16x16_c + +void ff_put_pixels8_l2_8(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, + int dst_stride, int src_stride1, int src_stride2, + int h) +{ + put_pixels8_l2_8(dst, src1, src2, dst_stride, src_stride1, src_stride2, h); + +} + +#if CONFIG_DIRAC_DECODER +#define DIRAC_MC(OPNAME)\ +void ff_ ## OPNAME ## _dirac_pixels8_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels8_8_c(dst, src[0], stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels16_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels16_8_c(dst, src[0], stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels32_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels16_8_c(dst , src[0] , stride, h);\ + OPNAME ## _pixels16_8_c(dst+16, src[0]+16, stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels8_l2_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels8_l2_8(dst, src[0], src[1], stride, stride, stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels16_l2_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels16_l2_8(dst, src[0], src[1], stride, stride, stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels32_l2_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels16_l2_8(dst , src[0] , src[1] , stride, stride, stride, h);\ + OPNAME ## _pixels16_l2_8(dst+16, src[0]+16, src[1]+16, stride, stride, stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels8_l4_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels8_l4_8(dst, src[0], src[1], src[2], src[3], stride, stride, stride, stride, stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels16_l4_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels16_l4_8(dst, src[0], src[1], src[2], src[3], stride, stride, stride, stride, stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels32_l4_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels16_l4_8(dst , src[0] , src[1] , src[2] , src[3] , stride, stride, stride, stride, stride, h);\ + OPNAME ## _pixels16_l4_8(dst+16, src[0]+16, src[1]+16, src[2]+16, src[3]+16, stride, stride, stride, stride, stride, h);\ +} +DIRAC_MC(put) +DIRAC_MC(avg) +#endif + +av_cold void ff_qpeldsp_init(QpelDSPContext *c) +{ +#define dspfunc(PFX, IDX, NUM) \ + c->PFX ## _pixels_tab[IDX][0] = PFX ## NUM ## _mc00_c; \ + c->PFX ## _pixels_tab[IDX][1] = PFX ## NUM ## _mc10_c; \ + c->PFX ## _pixels_tab[IDX][2] = PFX ## NUM ## _mc20_c; \ + c->PFX ## _pixels_tab[IDX][3] = PFX ## NUM ## _mc30_c; \ + c->PFX ## _pixels_tab[IDX][4] = PFX ## NUM ## _mc01_c; \ + c->PFX ## _pixels_tab[IDX][5] = PFX ## NUM ## _mc11_c; \ + c->PFX ## _pixels_tab[IDX][6] = PFX ## NUM ## _mc21_c; \ + c->PFX ## _pixels_tab[IDX][7] = PFX ## NUM ## _mc31_c; \ + c->PFX ## _pixels_tab[IDX][8] = PFX ## NUM ## _mc02_c; \ + c->PFX ## _pixels_tab[IDX][9] = PFX ## NUM ## _mc12_c; \ + c->PFX ## _pixels_tab[IDX][10] = PFX ## NUM ## _mc22_c; \ + c->PFX ## _pixels_tab[IDX][11] = PFX ## NUM ## _mc32_c; \ + c->PFX ## _pixels_tab[IDX][12] = PFX ## NUM ## _mc03_c; \ + c->PFX ## _pixels_tab[IDX][13] = PFX ## NUM ## _mc13_c; \ + c->PFX ## _pixels_tab[IDX][14] = PFX ## NUM ## _mc23_c; \ + c->PFX ## _pixels_tab[IDX][15] = PFX ## NUM ## _mc33_c + + dspfunc(put_qpel, 0, 16); + dspfunc(put_qpel, 1, 8); + + dspfunc(put_no_rnd_qpel, 0, 16); + dspfunc(put_no_rnd_qpel, 1, 8); + + dspfunc(avg_qpel, 0, 16); + dspfunc(avg_qpel, 1, 8); + + if (ARCH_X86) + ff_qpeldsp_init_x86(c); +} diff --git a/libavcodec/qpeldsp.h b/libavcodec/qpeldsp.h new file mode 100644 index 000000000..94caf6ffc --- /dev/null +++ b/libavcodec/qpeldsp.h @@ -0,0 +1,78 @@ +/* + * quarterpel DSP functions + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * quarterpel DSP functions + */ + +#ifndef AVCODEC_QPELDSP_H +#define AVCODEC_QPELDSP_H + +#include +#include + +void ff_put_pixels8x8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_avg_pixels8x8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_put_pixels16x16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_avg_pixels16x16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); + +void ff_put_pixels8_l2_8(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, + int dst_stride, int src_stride1, int src_stride2, + int h); + +#define DEF_OLD_QPEL(name) \ + void ff_put_ ## name(uint8_t *dst /* align width (8 or 16) */, \ + uint8_t *src /* align 1 */, ptrdiff_t stride); \ + void ff_put_no_rnd_ ## name(uint8_t *dst /* align width (8 or 16) */, \ + uint8_t *src /* align 1 */, ptrdiff_t stride); \ + void ff_avg_ ## name(uint8_t *dst /* align width (8 or 16) */, \ + uint8_t *src /* align 1 */, ptrdiff_t stride); + +DEF_OLD_QPEL(qpel16_mc11_old_c) +DEF_OLD_QPEL(qpel16_mc31_old_c) +DEF_OLD_QPEL(qpel16_mc12_old_c) +DEF_OLD_QPEL(qpel16_mc32_old_c) +DEF_OLD_QPEL(qpel16_mc13_old_c) +DEF_OLD_QPEL(qpel16_mc33_old_c) +DEF_OLD_QPEL(qpel8_mc11_old_c) +DEF_OLD_QPEL(qpel8_mc31_old_c) +DEF_OLD_QPEL(qpel8_mc12_old_c) +DEF_OLD_QPEL(qpel8_mc32_old_c) +DEF_OLD_QPEL(qpel8_mc13_old_c) +DEF_OLD_QPEL(qpel8_mc33_old_c) + +typedef void (*qpel_mc_func)(uint8_t *dst /* align width (8 or 16) */, + uint8_t *src /* align 1 */, ptrdiff_t stride); + +/** + * quarterpel DSP context + */ +typedef struct QpelDSPContext { + qpel_mc_func put_qpel_pixels_tab[2][16]; + qpel_mc_func avg_qpel_pixels_tab[2][16]; + qpel_mc_func put_no_rnd_qpel_pixels_tab[2][16]; +} QpelDSPContext; + +void ff_qpeldsp_init(QpelDSPContext *c); + +void ff_qpeldsp_init_x86(QpelDSPContext *c); + +#endif /* AVCODEC_QPELDSP_H */ diff --git a/libavcodec/qtrleenc.c b/libavcodec/qtrleenc.c index 7f9525abe..d72318841 100644 --- a/libavcodec/qtrleenc.c +++ b/libavcodec/qtrleenc.c @@ -86,6 +86,10 @@ static av_cold int qtrle_encode_init(AVCodecContext *avctx) switch (avctx->pix_fmt) { case AV_PIX_FMT_GRAY8: + if (avctx->width % 4) { + av_log(avctx, AV_LOG_ERROR, "Width not being a multiple of 4 is not supported\n"); + return AVERROR(EINVAL); + } s->logical_width = avctx->width / 4; s->pixel_size = 4; break; @@ -106,7 +110,7 @@ static av_cold int qtrle_encode_init(AVCodecContext *avctx) s->rlecode_table = av_mallocz(s->logical_width); s->skip_table = av_mallocz(s->logical_width); - s->length_table = av_mallocz((s->logical_width + 1)*sizeof(int)); + s->length_table = av_mallocz_array(s->logical_width + 1, sizeof(int)); if (!s->skip_table || !s->length_table || !s->rlecode_table) { av_log(avctx, AV_LOG_ERROR, "Error allocating memory.\n"); return AVERROR(ENOMEM); diff --git a/libavcodec/ra144.c b/libavcodec/ra144.c index 992972182..d5ad02f2d 100644 --- a/libavcodec/ra144.c +++ b/libavcodec/ra144.c @@ -1681,9 +1681,9 @@ unsigned int ff_rescale_rms(unsigned int rms, unsigned int energy) } /** inverse root mean square */ -int ff_irms(DSPContext *dsp, const int16_t *data) +int ff_irms(AudioDSPContext *adsp, const int16_t *data) { - unsigned int sum = dsp->scalarproduct_int16(data, data, BLOCKSIZE); + unsigned int sum = adsp->scalarproduct_int16(data, data, BLOCKSIZE); if (sum == 0) return 0; /* OOPS - division by zero */ @@ -1701,7 +1701,7 @@ void ff_subblock_synthesis(RA144Context *ractx, const int16_t *lpc_coefs, if (cba_idx) { cba_idx += BLOCKSIZE/2 - 1; ff_copy_and_dup(ractx->buffer_a, ractx->adapt_cb, cba_idx); - m[0] = (ff_irms(&ractx->dsp, ractx->buffer_a) * gval) >> 12; + m[0] = (ff_irms(&ractx->adsp, ractx->buffer_a) * gval) >> 12; } else { m[0] = 0; } diff --git a/libavcodec/ra144.h b/libavcodec/ra144.h index c2ee59b2d..c1ceb8734 100644 --- a/libavcodec/ra144.h +++ b/libavcodec/ra144.h @@ -25,7 +25,7 @@ #include #include "lpc.h" #include "audio_frame_queue.h" -#include "dsputil.h" +#include "audiodsp.h" #define NBLOCKS 4 ///< number of subblocks within a block #define BLOCKSIZE 40 ///< subblock size in 16-bit words @@ -36,7 +36,7 @@ typedef struct RA144Context { AVCodecContext *avctx; - DSPContext dsp; + AudioDSPContext adsp; LPCContext lpc_ctx; AudioFrameQueue afq; int last_frame; @@ -72,7 +72,7 @@ unsigned int ff_rms(const int *data); int ff_interp(RA144Context *ractx, int16_t *out, int a, int copyold, int energy); unsigned int ff_rescale_rms(unsigned int rms, unsigned int energy); -int ff_irms(DSPContext *dsp, const int16_t *data/*align 16*/); +int ff_irms(AudioDSPContext *adsp, const int16_t *data/*align 16*/); void ff_subblock_synthesis(RA144Context *ractx, const int16_t *lpc_coefs, int cba_idx, int cb1_idx, int cb2_idx, int gval, int gain); diff --git a/libavcodec/ra144dec.c b/libavcodec/ra144dec.c index ab7cc6830..29c78229b 100644 --- a/libavcodec/ra144dec.c +++ b/libavcodec/ra144dec.c @@ -34,7 +34,7 @@ static av_cold int ra144_decode_init(AVCodecContext * avctx) RA144Context *ractx = avctx->priv_data; ractx->avctx = avctx; - ff_dsputil_init(&ractx->dsp, avctx); + ff_audiodsp_init(&ractx->adsp); ractx->lpc_coef[0] = ractx->lpc_tables[0]; ractx->lpc_coef[1] = ractx->lpc_tables[1]; diff --git a/libavcodec/ra144enc.c b/libavcodec/ra144enc.c index 0db603261..499c41a03 100644 --- a/libavcodec/ra144enc.c +++ b/libavcodec/ra144enc.c @@ -29,12 +29,12 @@ #include "avcodec.h" #include "audio_frame_queue.h" -#include "internal.h" -#include "put_bits.h" #include "celp_filters.h" +#include "internal.h" +#include "mathops.h" +#include "put_bits.h" #include "ra144.h" - static av_cold int ra144_encode_close(AVCodecContext *avctx) { RA144Context *ractx = avctx->priv_data; @@ -61,7 +61,7 @@ static av_cold int ra144_encode_init(AVCodecContext * avctx) ractx->lpc_coef[0] = ractx->lpc_tables[0]; ractx->lpc_coef[1] = ractx->lpc_tables[1]; ractx->avctx = avctx; - ff_dsputil_init(&ractx->dsp, avctx); + ff_audiodsp_init(&ractx->adsp); ret = ff_lpc_init(&ractx->lpc_ctx, avctx->frame_size, LPC_ORDER, FF_LPC_TYPE_LEVINSON); if (ret < 0) @@ -374,7 +374,7 @@ static void ra144_encode_subblock(RA144Context *ractx, memcpy(cba, work + LPC_ORDER, sizeof(cba)); ff_copy_and_dup(ractx->buffer_a, ractx->adapt_cb, cba_idx + BLOCKSIZE / 2 - 1); - m[0] = (ff_irms(&ractx->dsp, ractx->buffer_a) * rms) >> 12; + m[0] = (ff_irms(&ractx->adsp, ractx->buffer_a) * rms) >> 12; } fixed_cb_search(work + LPC_ORDER, coefs, data, cba_idx, &cb1_idx, &cb2_idx); for (i = 0; i < BLOCKSIZE; i++) { diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 3e8ceb598..a621f8f79 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -28,6 +28,7 @@ #include "libavutil/attributes.h" #include "avcodec.h" #include "ratecontrol.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "libavutil/eval.h" @@ -47,10 +48,10 @@ 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:%"PRId64" var:%"PRId64" icount:%d skipcount:%d hbits:%d;\n", - s->current_picture_ptr->f.display_picture_number, - s->current_picture_ptr->f.coded_picture_number, + 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->current_picture.f->quality, s->i_tex_bits, s->p_tex_bits, s->mv_bits, @@ -688,7 +689,7 @@ static void adaptive_quantization(MpegEncContext *s, double q) } /* handle qmin/qmax clipping */ - if (s->flags & CODEC_FLAG_NORMALIZE_AQP) { + if (s->mpv_flags & FF_MPV_FLAG_NAQ) { float factor = bits_sum / cplx_sum; for (i = 0; i < s->mb_num; i++) { float newq = q * cplx_tab[i] / bits_tab[i]; @@ -713,7 +714,7 @@ static void adaptive_quantization(MpegEncContext *s, double q) float newq = q * cplx_tab[i] / bits_tab[i]; int intq; - if (s->flags & CODEC_FLAG_NORMALIZE_AQP) { + if (s->mpv_flags & FF_MPV_FLAG_NAQ) { newq *= bits_sum / cplx_sum; } @@ -799,10 +800,10 @@ float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) else dts_pic = s->last_picture_ptr; - if (!dts_pic || dts_pic->f.pts == AV_NOPTS_VALUE) + if (!dts_pic || dts_pic->f->pts == AV_NOPTS_VALUE) wanted_bits = (uint64_t)(s->bit_rate * (double)picture_number / fps); else - wanted_bits = (uint64_t)(s->bit_rate * (double)dts_pic->f.pts / fps); + wanted_bits = (uint64_t)(s->bit_rate * (double)dts_pic->f->pts / fps); } diff = s->total_bits - wanted_bits; @@ -951,8 +952,8 @@ static int init_pass2(MpegEncContext *s) return -1; } - qscale = av_malloc(sizeof(double) * rcc->num_entries); - blurred_qscale = av_malloc(sizeof(double) * rcc->num_entries); + qscale = av_malloc_array(rcc->num_entries, sizeof(double)); + blurred_qscale = av_malloc_array(rcc->num_entries, sizeof(double)); toobig = 0; for (step = 256 * 256; step > 0.0000001; step *= 0.5) { diff --git a/libavcodec/raw.c b/libavcodec/raw.c index 83b453c86..551a1722f 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_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') }, { AV_PIX_FMT_UYVY422, MKTAG('U', 'Y', 'N', 'V') }, @@ -219,7 +220,6 @@ const PixelFormatTag ff_raw_pix_fmt_tags[] = { /* special */ { AV_PIX_FMT_RGB565LE,MKTAG( 3 , 0 , 0 , 0 ) }, /* flipped RGB565LE */ { AV_PIX_FMT_YUV444P, MKTAG('Y', 'V', '2', '4') }, /* YUV444P, swapped UV */ - { AV_PIX_FMT_YUYV422, MKTAG('Y', 'V', 'Y', 'U') }, /* YUYV, swapped UV */ { AV_PIX_FMT_NONE, 0 }, }; @@ -234,3 +234,28 @@ unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat fmt) } return 0; } + +const PixelFormatTag avpriv_pix_fmt_bps_avi[] = { + { AV_PIX_FMT_MONOWHITE, 1 }, + { AV_PIX_FMT_PAL8, 2 }, + { AV_PIX_FMT_PAL8, 4 }, + { AV_PIX_FMT_PAL8, 8 }, + { AV_PIX_FMT_RGB444LE, 12 }, + { AV_PIX_FMT_RGB555LE, 15 }, + { AV_PIX_FMT_RGB555LE, 16 }, + { AV_PIX_FMT_BGR24, 24 }, + { AV_PIX_FMT_BGRA, 32 }, + { AV_PIX_FMT_NONE, 0 }, +}; + +const PixelFormatTag avpriv_pix_fmt_bps_mov[] = { + { AV_PIX_FMT_MONOWHITE, 1 }, + { AV_PIX_FMT_PAL8, 2 }, + { AV_PIX_FMT_PAL8, 4 }, + { AV_PIX_FMT_PAL8, 8 }, + { AV_PIX_FMT_RGB555BE, 16 }, + { AV_PIX_FMT_RGB24, 24 }, + { AV_PIX_FMT_ARGB, 32 }, + { AV_PIX_FMT_MONOWHITE,33 }, + { AV_PIX_FMT_NONE, 0 }, +}; diff --git a/libavcodec/raw.h b/libavcodec/raw.h index 3e59f28e3..a4179930a 100644 --- a/libavcodec/raw.h +++ b/libavcodec/raw.h @@ -41,4 +41,7 @@ enum AVPixelFormat ff_find_pix_fmt(const PixelFormatTag *tags, unsigned int four #endif enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc); +extern av_export const PixelFormatTag avpriv_pix_fmt_bps_avi[]; +extern av_export const PixelFormatTag avpriv_pix_fmt_bps_mov[]; + #endif /* AVCODEC_RAW_H */ diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index d187d23cb..ee1f3970a 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -25,6 +25,8 @@ */ #include "avcodec.h" +#include "bswapdsp.h" +#include "get_bits.h" #include "internal.h" #include "raw.h" #include "libavutil/avassert.h" @@ -43,6 +45,10 @@ typedef struct RawVideoContext { int is_yuv2; int is_lt_16bpp; // 16bpp pixfmt and bits_per_coded_sample < 16 int tff; + + BswapDSPContext bbdsp; + void *bitstream_buf; + unsigned int bitstream_buf_size; } RawVideoContext; static const AVOption options[]={ @@ -56,33 +62,6 @@ static const AVClass rawdec_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const PixelFormatTag pix_fmt_bps_avi[] = { - { AV_PIX_FMT_MONOWHITE, 1 }, - { AV_PIX_FMT_PAL8, 2 }, - { AV_PIX_FMT_PAL8, 4 }, - { AV_PIX_FMT_PAL8, 8 }, - { AV_PIX_FMT_RGB444LE, 12 }, - { AV_PIX_FMT_RGB555LE, 15 }, - { AV_PIX_FMT_RGB555LE, 16 }, - { AV_PIX_FMT_BGR24, 24 }, - { AV_PIX_FMT_BGRA, 32 }, - { AV_PIX_FMT_NONE, 0 }, -}; - -static const PixelFormatTag pix_fmt_bps_mov[] = { - { AV_PIX_FMT_MONOWHITE, 1 }, - { AV_PIX_FMT_PAL8, 2 }, - { AV_PIX_FMT_PAL8, 4 }, - { AV_PIX_FMT_PAL8, 8 }, - // FIXME swscale does not support 16 bit in .mov, sample 16bit.mov - // http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html - { AV_PIX_FMT_RGB555BE, 16 }, - { AV_PIX_FMT_RGB24, 24 }, - { AV_PIX_FMT_ARGB, 32 }, - { AV_PIX_FMT_MONOWHITE,33 }, - { AV_PIX_FMT_NONE, 0 }, -}; - #if LIBAVCODEC_VERSION_MAJOR < 55 enum AVPixelFormat ff_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc) { @@ -95,17 +74,19 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx) RawVideoContext *context = avctx->priv_data; const AVPixFmtDescriptor *desc; + ff_bswapdsp_init(&context->bbdsp); + if ( avctx->codec_tag == MKTAG('r','a','w',' ') || avctx->codec_tag == MKTAG('N','O','1','6')) - avctx->pix_fmt = avpriv_find_pix_fmt(pix_fmt_bps_mov, + avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov, avctx->bits_per_coded_sample); else if (avctx->codec_tag == MKTAG('W', 'R', 'A', 'W')) - avctx->pix_fmt = avpriv_find_pix_fmt(pix_fmt_bps_avi, + avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, avctx->bits_per_coded_sample); - else if (avctx->codec_tag) + else if (avctx->codec_tag && (avctx->codec_tag & 0xFFFFFF) != MKTAG('B','I','T', 0)) avctx->pix_fmt = avpriv_find_pix_fmt(ff_raw_pix_fmt_tags, avctx->codec_tag); else if (avctx->pix_fmt == AV_PIX_FMT_NONE && avctx->bits_per_coded_sample) - avctx->pix_fmt = avpriv_find_pix_fmt(pix_fmt_bps_avi, + avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, avctx->bits_per_coded_sample); desc = av_pix_fmt_desc_get(avctx->pix_fmt); @@ -157,6 +138,34 @@ static void flip(AVCodecContext *avctx, AVPicture *picture) picture->linesize[0] *= -1; } +/* + * Scale sample to 16-bit resolution + */ +#define SCALE16(x, bits) (((x) << (16 - (bits))) | ((x) >> (2 * (bits) - 16))) + +/** + * Scale buffer to 16 bits per coded sample resolution + */ +#define MKSCALE16(name, r16, w16) \ +static void name(AVCodecContext *avctx, uint8_t * dst, const uint8_t *buf, int buf_size, int packed) \ +{ \ + int i; \ + if (!packed) { \ + for (i = 0; i + 1 < buf_size; i += 2) \ + w16(dst + i, SCALE16(r16(buf + i), avctx->bits_per_coded_sample)); \ + } else { \ + GetBitContext gb; \ + init_get_bits(&gb, buf, buf_size * 8); \ + for (i = 0; i < avctx->width * avctx->height; i++) { \ + int sample = get_bits(&gb, avctx->bits_per_coded_sample); \ + w16(dst + i*2, SCALE16(sample, avctx->bits_per_coded_sample)); \ + } \ + } \ +} + +MKSCALE16(scale16be, AV_RB16, AV_WB16) +MKSCALE16(scale16le, AV_RL16, AV_WL16) + static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { @@ -173,8 +182,11 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, frame->pict_type = AV_PICTURE_TYPE_I; frame->key_frame = 1; - frame->reordered_opaque = avctx->reordered_opaque; - frame->pkt_pts = avctx->internal->pkt->pts; + + res = ff_decode_frame_props(avctx, frame); + if (res < 0) + return res; + av_frame_set_pkt_pos (frame, avctx->internal->pkt->pos); av_frame_set_pkt_duration(frame, avctx->internal->pkt->duration); @@ -216,15 +228,28 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, } buf = dst; } else if (context->is_lt_16bpp) { - int i; uint8_t *dst = frame->buf[0]->data; - if (desc->flags & AV_PIX_FMT_FLAG_BE) { - for (i = 0; i + 1 < buf_size; i += 2) - AV_WB16(dst + i, AV_RB16(buf + i) << (16 - avctx->bits_per_coded_sample)); - } else { - for (i = 0; i + 1 < buf_size; i += 2) - AV_WL16(dst + i, AV_RL16(buf + i) << (16 - avctx->bits_per_coded_sample)); + int packed = (avctx->codec_tag & 0xFFFFFF) == MKTAG('B','I','T', 0); + int swap = avctx->codec_tag >> 24; + + if (packed && swap) { + av_fast_padded_malloc(&context->bitstream_buf, &context->bitstream_buf_size, buf_size); + if (!context->bitstream_buf) + return AVERROR(ENOMEM); + if (swap == 16) + context->bbdsp.bswap16_buf(context->bitstream_buf, (const uint16_t*)buf, buf_size / 2); + else if (swap == 32) + context->bbdsp.bswap_buf(context->bitstream_buf, (const uint32_t*)buf, buf_size / 4); + else + return AVERROR_INVALIDDATA; + buf = context->bitstream_buf; } + + if (desc->flags & AV_PIX_FMT_FLAG_BE) + scale16be(avctx, dst, buf, buf_size, packed); + else + scale16le(avctx, dst, buf, buf_size, packed); + buf = dst; } else if (need_copy) { memcpy(frame->buf[0]->data, buf, buf_size); @@ -236,7 +261,7 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, buf += buf_size - context->frame_size; len = context->frame_size - (avctx->pix_fmt==AV_PIX_FMT_PAL8 ? AVPALETTE_SIZE : 0); - if (buf_size < len) { + if (buf_size < len && (avctx->codec_tag & 0xFFFFFF) != MKTAG('B','I','T', 0)) { av_log(avctx, AV_LOG_ERROR, "Invalid buffer size, packet size %d < expected frame_size %d\n", buf_size, len); av_buffer_unref(&frame->buf[0]); return AVERROR(EINVAL); @@ -321,16 +346,6 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, line += picture->linesize[0]; } } - if (avctx->codec_tag == AV_RL32("YVYU") && - avctx->pix_fmt == AV_PIX_FMT_YUYV422) { - int x, y; - uint8_t *line = picture->data[0]; - for(y = 0; y < avctx->height; y++) { - for(x = 0; x < avctx->width - 1; x += 2) - FFSWAP(uint8_t, line[2*x + 1], line[2*x + 3]); - line += picture->linesize[0]; - } - } if (avctx->field_order > AV_FIELD_PROGRESSIVE) { /* we have interlaced material flagged in container */ frame->interlaced_frame = 1; diff --git a/libavcodec/rnd_avg.h b/libavcodec/rnd_avg.h index 50ab59a0f..344775e31 100644 --- a/libavcodec/rnd_avg.h +++ b/libavcodec/rnd_avg.h @@ -25,14 +25,8 @@ #include #include -#define CALL_2X_PIXELS(a, b, n)\ -static void a(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){\ - b(block , pixels , line_size, h);\ - b(block+n, pixels+n, line_size, h);\ -} - -#define BYTE_VEC32(c) ((c)*0x01010101UL) -#define BYTE_VEC64(c) ((c)*0x0001000100010001UL) +#define BYTE_VEC32(c) ((c) * 0x01010101UL) +#define BYTE_VEC64(c) ((c) * 0x0001000100010001UL) static inline uint32_t rnd_avg32(uint32_t a, uint32_t b) { diff --git a/libavcodec/roqvideodec.c b/libavcodec/roqvideodec.c index 322345ef1..8efa3001d 100644 --- a/libavcodec/roqvideodec.c +++ b/libavcodec/roqvideodec.c @@ -189,7 +189,8 @@ static av_cold int roq_decode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } - avctx->pix_fmt = AV_PIX_FMT_YUV444P; + avctx->pix_fmt = AV_PIX_FMT_YUVJ444P; + avctx->color_range = AVCOL_RANGE_JPEG; return 0; } diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c index 4b96934a6..1c5970f68 100644 --- a/libavcodec/roqvideoenc.c +++ b/libavcodec/roqvideoenc.c @@ -249,7 +249,7 @@ static void create_cel_evals(RoqContext *enc, RoqTempdata *tempData) { int n=0, x, y, i; - tempData->cel_evals = av_malloc(enc->width*enc->height/64 * sizeof(CelEvaluation)); + tempData->cel_evals = av_malloc_array(enc->width*enc->height/64, sizeof(CelEvaluation)); /* Map to the ROQ quadtree order */ for (y=0; yheight; y+=16) @@ -799,11 +799,11 @@ static void generate_codebook(RoqContext *enc, RoqTempdata *tempdata, int i, j, k; int c_size = size*size/4; int *buf; - int *codebook = av_malloc(6*c_size*cbsize*sizeof(int)); + int *codebook = av_malloc_array(6*c_size, cbsize*sizeof(int)); int *closest_cb; if (size == 4) - closest_cb = av_malloc(6*c_size*inputCount*sizeof(int)); + closest_cb = av_malloc_array(6*c_size, inputCount*sizeof(int)); else closest_cb = tempdata->closest_cb2; @@ -834,8 +834,8 @@ static void generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData) int max = enc->width*enc->height/16; uint8_t mb2[3*4]; roq_cell *results4 = av_malloc(sizeof(roq_cell)*MAX_CBS_4x4*4); - uint8_t *yuvClusters=av_malloc(sizeof(int)*max*6*4); - int *points = av_malloc(max*6*4*sizeof(int)); + uint8_t *yuvClusters=av_malloc_array(max, sizeof(int)*6*4); + int *points = av_malloc_array(max, 6*4*sizeof(int)); int bias; /* Subsample YUV data */ @@ -852,7 +852,7 @@ static void generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData) codebooks->numCB4 = (enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4); - tempData->closest_cb2 = av_malloc(max*4*sizeof(int)); + tempData->closest_cb2 = av_malloc_array(max, 4*sizeof(int)); /* Create 2x2 codebooks */ generate_codebook(enc, tempData, points, max*4, enc->cb2x2, 2, MAX_CBS_2x2); @@ -881,7 +881,7 @@ static void generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData) av_free(results4); } -static void roq_encode_video(RoqContext *enc) +static int roq_encode_video(RoqContext *enc) { RoqTempdata *tempData = enc->tmpData; int i; @@ -903,6 +903,10 @@ static void roq_encode_video(RoqContext *enc) /* Quake 3 can't handle chunks bigger than 65535 bytes */ if (tempData->mainChunkSize/8 > 65535 && enc->quake3_compat) { + if (enc->lambda > 100000) { + av_log(enc->avctx, AV_LOG_ERROR, "Cannot encode video in Quake compatible form\n"); + return AVERROR(EINVAL); + } av_log(enc->avctx, AV_LOG_ERROR, "Warning, generated a frame too big for Quake (%d > 65535), " "now switching to a bigger qscale value.\n", @@ -936,6 +940,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) @@ -966,8 +972,13 @@ static av_cold int roq_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } + if (avctx->width > 65535 || avctx->height > 65535) { + av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n", enc->quake3_compat ? 32768 : 65535); + return AVERROR(EINVAL); + } + if (((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx->height-1))) - av_log(avctx, AV_LOG_ERROR, "Warning: dimensions not power of two\n"); + av_log(avctx, AV_LOG_ERROR, "Warning: dimensions not power of two, this is not supported by quake\n"); enc->width = avctx->width; enc->height = avctx->height; @@ -985,16 +996,16 @@ static av_cold int roq_encode_init(AVCodecContext *avctx) enc->tmpData = av_malloc(sizeof(RoqTempdata)); enc->this_motion4 = - av_mallocz((enc->width*enc->height/16)*sizeof(motion_vect)); + av_mallocz_array((enc->width*enc->height/16), sizeof(motion_vect)); enc->last_motion4 = - av_malloc ((enc->width*enc->height/16)*sizeof(motion_vect)); + av_malloc_array ((enc->width*enc->height/16), sizeof(motion_vect)); enc->this_motion8 = - av_mallocz((enc->width*enc->height/64)*sizeof(motion_vect)); + av_mallocz_array((enc->width*enc->height/64), sizeof(motion_vect)); enc->last_motion8 = - av_malloc ((enc->width*enc->height/64)*sizeof(motion_vect)); + av_malloc_array ((enc->width*enc->height/64), sizeof(motion_vect)); return 0; } @@ -1064,7 +1075,8 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } /* Encode the actual frame */ - roq_encode_video(enc); + if ((ret = roq_encode_video(enc)) < 0) + return ret; pkt->size = enc->out_buf - pkt->data; if (enc->framesSinceKeyframe == 1) @@ -1097,7 +1109,7 @@ AVCodec ff_roq_encoder = { .init = roq_encode_init, .encode2 = roq_encode_frame, .close = roq_encode_end, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_NONE }, .priv_class = &roq_class, }; diff --git a/libavcodec/rtjpeg.c b/libavcodec/rtjpeg.c index 860d95821..8e02bce2e 100644 --- a/libavcodec/rtjpeg.c +++ b/libavcodec/rtjpeg.c @@ -121,7 +121,7 @@ int ff_rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f, if (res < 0) \ return res; \ if (res > 0) \ - c->dsp->idct_put(dst, stride, block); \ + c->idsp.idct_put(dst, stride, block); \ } while (0) int16_t *block = c->block; BLOCK(c->lquant, y1, f->linesize[0]); @@ -148,7 +148,6 @@ int ff_rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f, /** * @brief initialize an RTJpegContext, may be called multiple times * @param c context to initialize - * @param dsp specifies the idct to use for decoding * @param width width of image, will be rounded down to the nearest multiple * of 16 for decoding * @param height height of image, will be rounded down to the nearest multiple @@ -156,21 +155,29 @@ int ff_rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f, * @param lquant luma quantization table to use * @param cquant chroma quantization table to use */ -void ff_rtjpeg_decode_init(RTJpegContext *c, DSPContext *dsp, - int width, int height, +void ff_rtjpeg_decode_init(RTJpegContext *c, int width, int height, const uint32_t *lquant, const uint32_t *cquant) { int i; - c->dsp = dsp; for (i = 0; i < 64; i++) { - int z = ff_zigzag_direct[i]; - int p = c->dsp->idct_permutation[i]; - z = ((z << 3) | (z >> 3)) & 63; // rtjpeg uses a transposed variant - - // permute the scan and quantization tables for the chosen idct - c->scan[i] = c->dsp->idct_permutation[z]; + int p = c->idsp.idct_permutation[i]; c->lquant[p] = lquant[i]; c->cquant[p] = cquant[i]; } c->w = width; c->h = height; } + +void ff_rtjpeg_init(RTJpegContext *c, AVCodecContext *avctx) +{ + int i; + + ff_idctdsp_init(&c->idsp, avctx); + + for (i = 0; i < 64; i++) { + int z = ff_zigzag_direct[i]; + z = ((z << 3) | (z >> 3)) & 63; // rtjpeg uses a transposed variant + + // permute the scan and quantization tables for the chosen idct + c->scan[i] = c->idsp.idct_permutation[z]; + } +} diff --git a/libavcodec/rtjpeg.h b/libavcodec/rtjpeg.h index 294b06c69..d22ff4070 100644 --- a/libavcodec/rtjpeg.h +++ b/libavcodec/rtjpeg.h @@ -23,24 +23,26 @@ #define AVCODEC_RTJPEG_H #include -#include "dsputil.h" + #include "libavutil/mem.h" +#include "idctdsp.h" #define RTJPEG_FILE_VERSION 0 #define RTJPEG_HEADER_SIZE 12 typedef struct RTJpegContext { int w, h; - DSPContext *dsp; + IDCTDSPContext idsp; uint8_t scan[64]; uint32_t lquant[64]; uint32_t cquant[64]; DECLARE_ALIGNED(16, int16_t, block)[64]; } RTJpegContext; -void ff_rtjpeg_decode_init(RTJpegContext *c, DSPContext *dsp, - int width, int height, - const uint32_t *lquant, const uint32_t *cquant); +void ff_rtjpeg_init(RTJpegContext *c, AVCodecContext *avctx); + +void ff_rtjpeg_decode_init(RTJpegContext *c, int width, int height, + const uint32_t *lquant, const uint32_t *cquant); int ff_rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f, const uint8_t *buf, int buf_size); diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c index cf13b9b0c..f908a9a13 100644 --- a/libavcodec/rv10.c +++ b/libavcodec/rv10.c @@ -25,19 +25,23 @@ * RV10/RV20 decoder */ +#include + #include "libavutil/imgutils.h" + #include "avcodec.h" #include "error_resilience.h" +#include "h263.h" #include "internal.h" +#include "mpeg_er.h" #include "mpegvideo.h" #include "mpeg4video.h" -#include "h263.h" #define RV_GET_MAJOR_VER(x) ((x) >> 28) #define RV_GET_MINOR_VER(x) (((x) >> 20) & 0xFF) #define RV_GET_MICRO_VER(x) (((x) >> 12) & 0xFF) -#define DC_VLC_BITS 14 //FIXME find a better solution +#define DC_VLC_BITS 14 // FIXME find a better solution typedef struct RVDecContext { MpegEncContext m; @@ -194,18 +198,18 @@ int ff_rv_decode_dc(MpegEncContext *s, int n) code = get_vlc2(&s->gb, rv_dc_lum.table, DC_VLC_BITS, 2); if (code < 0) { /* XXX: I don't understand why they use LONGER codes than - necessary. The following code would be completely useless - if they had thought about it !!! */ + * necessary. The following code would be completely useless + * if they had thought about it !!! */ code = get_bits(&s->gb, 7); if (code == 0x7c) { - code = (int8_t)(get_bits(&s->gb, 7) + 1); + code = (int8_t) (get_bits(&s->gb, 7) + 1); } else if (code == 0x7d) { code = -128 + get_bits(&s->gb, 7); } else if (code == 0x7e) { if (get_bits1(&s->gb) == 0) - code = (int8_t)(get_bits(&s->gb, 8) + 1); + code = (int8_t) (get_bits(&s->gb, 8) + 1); else - code = (int8_t)(get_bits(&s->gb, 8)); + code = (int8_t) (get_bits(&s->gb, 8)); } else if (code == 0x7f) { skip_bits(&s->gb, 11); code = 1; @@ -219,7 +223,7 @@ int ff_rv_decode_dc(MpegEncContext *s, int n) if (code < 0) { code = get_bits(&s->gb, 9); if (code == 0x1fc) { - code = (int8_t)(get_bits(&s->gb, 7) + 1); + code = (int8_t) (get_bits(&s->gb, 7) + 1); } else if (code == 0x1fd) { code = -128 + get_bits(&s->gb, 7); } else if (code == 0x1fe) { @@ -277,7 +281,7 @@ static int rv10_decode_picture_header(MpegEncContext *s) } } /* if multiple packets per frame are sent, the position at which - to display the macroblocks is coded here */ + * to display the macroblocks is coded here */ mb_xy = s->mb_x + s->mb_y * s->mb_width; if (show_bits(&s->gb, 12) == 0 || (mb_xy && mb_xy < s->mb_num)) { @@ -290,7 +294,7 @@ static int rv10_decode_picture_header(MpegEncContext *s) mb_count = s->mb_width * s->mb_height; } skip_bits(&s->gb, 3); /* ignored */ - s->f_code = 1; + s->f_code = 1; s->unrestricted_mv = 1; return mb_count; @@ -303,11 +307,19 @@ static int rv20_decode_picture_header(RVDecContext *rv) int rpr_max; i = get_bits(&s->gb, 2); - switch(i) { - case 0: s->pict_type = AV_PICTURE_TYPE_I; break; - case 1: s->pict_type = AV_PICTURE_TYPE_I; break; //hmm ... - case 2: s->pict_type = AV_PICTURE_TYPE_P; break; - case 3: s->pict_type = AV_PICTURE_TYPE_B; break; + switch (i) { + case 0: + s->pict_type = AV_PICTURE_TYPE_I; + break; + case 1: + s->pict_type = AV_PICTURE_TYPE_I; + break; // hmm ... + case 2: + s->pict_type = AV_PICTURE_TYPE_P; + break; + case 3: + s->pict_type = AV_PICTURE_TYPE_B; + break; default: av_log(s->avctx, AV_LOG_ERROR, "unknown frame type\n"); return AVERROR_INVALIDDATA; @@ -354,10 +366,10 @@ static int rv20_decode_picture_header(RVDecContext *rv) return AVERROR_INVALIDDATA; } - new_w = 4 * ((uint8_t*)s->avctx->extradata)[6 + 2 * f]; - new_h = 4 * ((uint8_t*)s->avctx->extradata)[7 + 2 * f]; + new_w = 4 * ((uint8_t *) s->avctx->extradata)[6 + 2 * f]; + new_h = 4 * ((uint8_t *) s->avctx->extradata)[7 + 2 * f]; } else { - new_w = s->orig_width ; + new_w = s->orig_width; new_h = s->orig_height; } if (new_w != s->width || new_h != s->height) { @@ -424,7 +436,8 @@ static int rv20_decode_picture_header(RVDecContext *rv) s->no_rounding = get_bits1(&s->gb); if (RV_GET_MINOR_VER(rv->sub_id) <= 1 && s->pict_type == AV_PICTURE_TYPE_B) - skip_bits(&s->gb, 5); // binary decoder reads 3+2 bits here but they don't seem to be used + // binary decoder reads 3+2 bits here but they don't seem to be used + skip_bits(&s->gb, 5); s->f_code = 1; s->unrestricted_mv = 1; @@ -434,18 +447,20 @@ static int rv20_decode_picture_header(RVDecContext *rv) s->loop_filter = 1; if (s->avctx->debug & FF_DEBUG_PICT_INFO) { - av_log(s->avctx, AV_LOG_INFO, "num:%5d x:%2d y:%2d type:%d qscale:%2d rnd:%d\n", - seq, s->mb_x, s->mb_y, s->pict_type, s->qscale, s->no_rounding); + av_log(s->avctx, AV_LOG_INFO, + "num:%5d x:%2d y:%2d type:%d qscale:%2d rnd:%d\n", + seq, s->mb_x, s->mb_y, s->pict_type, s->qscale, + s->no_rounding); } av_assert0(s->pict_type != AV_PICTURE_TYPE_B || !s->low_delay); - return s->mb_width*s->mb_height - mb_pos; + return s->mb_width * s->mb_height - mb_pos; } static av_cold int rv10_decode_init(AVCodecContext *avctx) { - RVDecContext *rv = avctx->priv_data; + RVDecContext *rv = avctx->priv_data; MpegEncContext *s = &rv->m; static int done = 0; int major_ver, minor_ver, micro_ver, ret; @@ -460,15 +475,17 @@ static av_cold int rv10_decode_init(AVCodecContext *avctx) ff_MPV_decode_defaults(s); - s->avctx = avctx; - s->out_format = FMT_H263; - s->codec_id = avctx->codec_id; + s->avctx = avctx; + s->out_format = FMT_H263; + s->codec_id = avctx->codec_id; - s->orig_width = s->width = avctx->coded_width; - s->orig_height = s->height = avctx->coded_height; + s->orig_width = + s->width = avctx->coded_width; + s->orig_height = + s->height = avctx->coded_height; - s->h263_long_vectors = ((uint8_t*)avctx->extradata)[3] & 1; - rv->sub_id = AV_RB32((uint8_t*)avctx->extradata + 4); + s->h263_long_vectors = ((uint8_t *) avctx->extradata)[3] & 1; + rv->sub_id = AV_RB32((uint8_t *) avctx->extradata + 4); major_ver = RV_GET_MAJOR_VER(rv->sub_id); minor_ver = RV_GET_MINOR_VER(rv->sub_id); @@ -493,8 +510,8 @@ static av_cold int rv10_decode_init(AVCodecContext *avctx) } if (avctx->debug & FF_DEBUG_PICT_INFO) { - av_log(avctx, AV_LOG_DEBUG, "ver:%X ver0:%X\n", rv->sub_id, - ((uint32_t*)avctx->extradata)[0]); + av_log(avctx, AV_LOG_DEBUG, "ver:%X ver0:%"PRIX32"\n", rv->sub_id, + ((uint32_t *) avctx->extradata)[0]); } avctx->pix_fmt = AV_PIX_FMT_YUV420P; @@ -527,10 +544,10 @@ static av_cold int rv10_decode_end(AVCodecContext *avctx) return 0; } -static int rv10_decode_packet(AVCodecContext *avctx, - const uint8_t *buf, int buf_size, int buf_size2) +static int rv10_decode_packet(AVCodecContext *avctx, const uint8_t *buf, + int buf_size, int buf_size2) { - RVDecContext *rv = avctx->priv_data; + RVDecContext *rv = avctx->priv_data; MpegEncContext *s = &rv->m; int mb_count, mb_pos, left, start_mb_x, active_bits_size, ret; @@ -552,14 +569,15 @@ static int rv10_decode_packet(AVCodecContext *avctx, return AVERROR_INVALIDDATA; } mb_pos = s->mb_y * s->mb_width + s->mb_x; - left = s->mb_width * s->mb_height - mb_pos; + left = s->mb_width * s->mb_height - mb_pos; if (mb_count > left) { av_log(s->avctx, AV_LOG_ERROR, "COUNT ERROR\n"); return AVERROR_INVALIDDATA; } if ((s->mb_x == 0 && s->mb_y == 0) || s->current_picture_ptr == NULL) { - if (s->current_picture_ptr) { // FIXME write parser so we always have complete frames? + // FIXME write parser so we always have complete frames? + if (s->current_picture_ptr) { ff_er_frame_end(&s->er); ff_MPV_frame_end(s); s->mb_x = s->mb_y = s->resync_mb_x = s->resync_mb_y = 0; @@ -568,7 +586,7 @@ static int rv10_decode_packet(AVCodecContext *avctx, return ret; ff_mpeg_er_frame_start(s); } else { - if (s->current_picture_ptr->f.pict_type != s->pict_type) { + if (s->current_picture_ptr->f->pict_type != s->pict_type) { av_log(s->avctx, AV_LOG_ERROR, "Slice type mismatch\n"); return AVERROR_INVALIDDATA; } @@ -588,9 +606,11 @@ static int rv10_decode_packet(AVCodecContext *avctx, start_mb_x = s->mb_x; s->resync_mb_y = s->mb_y; if (s->h263_aic) { - s->y_dc_scale_table = s->c_dc_scale_table = ff_aic_dc_scale_table; + 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; + s->y_dc_scale_table = + s->c_dc_scale_table = ff_mpeg1_dc_scale_table; } if (s->modified_quant) @@ -639,7 +659,8 @@ static int rv10_decode_packet(AVCodecContext *avctx, } if (ret == SLICE_ERROR || active_bits_size < get_bits_count(&s->gb)) { - av_log(s->avctx, AV_LOG_ERROR, "ERROR at MB %d %d\n", s->mb_x, s->mb_y); + av_log(s->avctx, AV_LOG_ERROR, "ERROR at MB %d %d\n", s->mb_x, + s->mb_y); return AVERROR_INVALIDDATA; } if (s->pict_type != AV_PICTURE_TYPE_B) @@ -659,7 +680,7 @@ static int rv10_decode_packet(AVCodecContext *avctx, break; } - ff_er_add_slice(&s->er, start_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, + ff_er_add_slice(&s->er, start_mb_x, s->resync_mb_y, s->mb_x - 1, s->mb_y, ER_MB_END); return active_bits_size; @@ -673,14 +694,13 @@ static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n) return AV_RL32(buf + n * 8); } -static int rv10_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, +static int rv10_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - MpegEncContext *s = avctx->priv_data; - AVFrame *pict = data; + MpegEncContext *s = avctx->priv_data; + AVFrame *pict = data; int i, ret; int slice_count; const uint8_t *slices_hdr = NULL; @@ -699,7 +719,8 @@ static int rv10_decode_frame(AVCodecContext *avctx, buf_size--; if (!slice_count || buf_size <= 8 * slice_count) { - av_log(avctx, AV_LOG_ERROR, "Invalid slice count: %d.\n", slice_count); + av_log(avctx, AV_LOG_ERROR, "Invalid slice count: %d.\n", + slice_count); return AVERROR_INVALIDDATA; } @@ -742,12 +763,12 @@ static int rv10_decode_frame(AVCodecContext *avctx, ff_MPV_frame_end(s); if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { - if ((ret = av_frame_ref(pict, &s->current_picture_ptr->f)) < 0) + if ((ret = av_frame_ref(pict, s->current_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->current_picture_ptr, pict); ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_QSCALE_TYPE_MPEG1); } else if (s->last_picture_ptr != NULL) { - if ((ret = av_frame_ref(pict, &s->last_picture_ptr->f)) < 0) + if ((ret = av_frame_ref(pict, s->last_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->last_picture_ptr, pict); ff_mpv_export_qp_table(s, pict,s->last_picture_ptr, FF_QSCALE_TYPE_MPEG1); @@ -775,7 +796,10 @@ AVCodec ff_rv10_decoder = { .decode = rv10_decode_frame, .capabilities = CODEC_CAP_DR1, .max_lowres = 3, - .pix_fmts = ff_pixfmt_list_420, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, }; AVCodec ff_rv20_decoder = { @@ -790,5 +814,8 @@ AVCodec ff_rv20_decoder = { .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, .flush = ff_mpeg_flush, .max_lowres = 3, - .pix_fmts = ff_pixfmt_list_420, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, }; diff --git a/libavcodec/rv30.c b/libavcodec/rv30.c index dff4117df..fd8fd4f98 100644 --- a/libavcodec/rv30.c +++ b/libavcodec/rv30.c @@ -25,6 +25,7 @@ */ #include "avcodec.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "golomb.h" @@ -132,7 +133,7 @@ static int rv30_decode_mb_info(RV34DecContext *r) static inline void rv30_weak_loop_filter(uint8_t *src, const int step, const int stride, const int lim) { - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; int i, diff; for(i = 0; i < 4; i++){ @@ -170,7 +171,7 @@ static void rv30_loop_filter(RV34DecContext *r, int row) if(mb_x) left_lim = rv30_loop_filt_lim[s->current_picture_ptr->qscale_table[mb_pos - 1]]; for(j = 0; j < 16; j += 4){ - Y = s->current_picture_ptr->f.data[0] + mb_x*16 + (row*16 + j) * s->linesize + 4 * !mb_x; + Y = s->current_picture_ptr->f->data[0] + mb_x*16 + (row*16 + j) * s->linesize + 4 * !mb_x; for(i = !mb_x; i < 4; i++, Y += 4){ int ij = i + j; loc_lim = 0; @@ -190,7 +191,7 @@ static void rv30_loop_filter(RV34DecContext *r, int row) if(mb_x) left_cbp = (r->cbp_chroma[mb_pos - 1] >> (k*4)) & 0xF; for(j = 0; j < 8; j += 4){ - C = s->current_picture_ptr->f.data[k + 1] + mb_x*8 + (row*8 + j) * s->uvlinesize + 4 * !mb_x; + C = s->current_picture_ptr->f->data[k + 1] + mb_x*8 + (row*8 + j) * s->uvlinesize + 4 * !mb_x; for(i = !mb_x; i < 2; i++, C += 4){ int ij = i + (j >> 1); loc_lim = 0; @@ -212,7 +213,7 @@ static void rv30_loop_filter(RV34DecContext *r, int row) if(row) top_lim = rv30_loop_filt_lim[s->current_picture_ptr->qscale_table[mb_pos - s->mb_stride]]; for(j = 4*!row; j < 16; j += 4){ - Y = s->current_picture_ptr->f.data[0] + mb_x*16 + (row*16 + j) * s->linesize; + Y = s->current_picture_ptr->f->data[0] + mb_x*16 + (row*16 + j) * s->linesize; for(i = 0; i < 4; i++, Y += 4){ int ij = i + j; loc_lim = 0; @@ -232,7 +233,7 @@ static void rv30_loop_filter(RV34DecContext *r, int row) if(row) top_cbp = (r->cbp_chroma[mb_pos - s->mb_stride] >> (k*4)) & 0xF; for(j = 4*!row; j < 8; j += 4){ - C = s->current_picture_ptr->f.data[k+1] + mb_x*8 + (row*8 + j) * s->uvlinesize; + C = s->current_picture_ptr->f->data[k+1] + mb_x*8 + (row*8 + j) * s->uvlinesize; for(i = 0; i < 2; i++, C += 4){ int ij = i + (j >> 1); loc_lim = 0; @@ -293,7 +294,10 @@ AVCodec ff_rv30_decoder = { .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_FRAME_THREADS, .flush = ff_mpeg_flush, - .pix_fmts = ff_pixfmt_list_420, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, .init_thread_copy = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_update_thread_context), }; diff --git a/libavcodec/rv30data.h b/libavcodec/rv30data.h index 9cc48a6a3..5c4cb9710 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 5e47b647c..bd084bff7 100644 --- a/libavcodec/rv30dsp.c +++ b/libavcodec/rv30dsp.c @@ -27,12 +27,13 @@ #include "avcodec.h" #include "h264chroma.h" #include "h264qpel.h" +#include "mathops.h" #include "rv34dsp.h" #define RV30_LOWPASS(OPNAME, OP) \ static av_unused void OPNAME ## rv30_tpel8_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, const int C1, const int C2){\ const int h = 8;\ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i;\ for(i = 0; i < h; i++)\ {\ @@ -51,7 +52,7 @@ static av_unused void OPNAME ## rv30_tpel8_h_lowpass(uint8_t *dst, uint8_t *src, \ static void OPNAME ## rv30_tpel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, const int C1, const int C2){\ const int w = 8;\ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i;\ for(i = 0; i < w; i++)\ {\ @@ -82,7 +83,7 @@ static void OPNAME ## rv30_tpel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstSt static void OPNAME ## rv30_tpel8_hv_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ const int w = 8;\ const int h = 8;\ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i, j;\ for(j = 0; j < h; j++){\ for(i = 0; i < w; i++){\ @@ -101,7 +102,7 @@ static void OPNAME ## rv30_tpel8_hv_lowpass(uint8_t *dst, uint8_t *src, int dstS static void OPNAME ## rv30_tpel8_hhv_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ const int w = 8;\ const int h = 8;\ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i, j;\ for(j = 0; j < h; j++){\ for(i = 0; i < w; i++){\ @@ -120,7 +121,7 @@ static void OPNAME ## rv30_tpel8_hhv_lowpass(uint8_t *dst, uint8_t *src, int dst static void OPNAME ## rv30_tpel8_hvv_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ const int w = 8;\ const int h = 8;\ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i, j;\ for(j = 0; j < h; j++){\ for(i = 0; i < w; i++){\ @@ -139,7 +140,7 @@ static void OPNAME ## rv30_tpel8_hvv_lowpass(uint8_t *dst, uint8_t *src, int dst static void OPNAME ## rv30_tpel8_hhvv_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ const int w = 8;\ const int h = 8;\ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i, j;\ for(j = 0; j < h; j++){\ for(i = 0; i < w; i++){\ diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c index 45c7b225a..d82b41e2a 100644 --- a/libavcodec/rv34.c +++ b/libavcodec/rv34.c @@ -29,10 +29,13 @@ #include "avcodec.h" #include "error_resilience.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "golomb.h" #include "internal.h" #include "mathops.h" +#include "mpeg_er.h" +#include "qpeldsp.h" #include "rectangle.h" #include "thread.h" @@ -508,7 +511,7 @@ static void rv34_pred_mv(RV34DecContext *r, int block_type, int subblock_no, int } } -#define GET_PTS_DIFF(a, b) ((a - b + 8192) & 0x1FFF) +#define GET_PTS_DIFF(a, b) (((a) - (b) + 8192) & 0x1FFF) /** * Calculate motion vector component that should be added for direct blocks. @@ -670,6 +673,7 @@ static inline void rv34_mc(RV34DecContext *r, const int block_type, int dxy, mx, my, umx, umy, lx, ly, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y; int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride + mv_off; int is16x16 = 1; + int emu = 0; if(thirdpel){ int chroma_mx, chroma_my; @@ -708,9 +712,9 @@ static inline void rv34_mc(RV34DecContext *r, const int block_type, } dxy = ly*4 + lx; - srcY = dir ? s->next_picture_ptr->f.data[0] : s->last_picture_ptr->f.data[0]; - srcU = dir ? s->next_picture_ptr->f.data[1] : s->last_picture_ptr->f.data[1]; - srcV = dir ? s->next_picture_ptr->f.data[2] : s->last_picture_ptr->f.data[2]; + srcY = dir ? s->next_picture_ptr->f->data[0] : s->last_picture_ptr->f->data[0]; + srcU = dir ? s->next_picture_ptr->f->data[1] : s->last_picture_ptr->f->data[1]; + srcV = dir ? s->next_picture_ptr->f->data[2] : s->last_picture_ptr->f->data[2]; src_x = s->mb_x * 16 + xoff + mx; src_y = s->mb_y * 16 + yoff + my; uvsrc_x = s->mb_x * 8 + (xoff >> 1) + umx; @@ -721,8 +725,6 @@ 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; - srcY -= 2 + 2*s->linesize; s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY, s->linesize, s->linesize, @@ -730,18 +732,7 @@ static inline void rv34_mc(RV34DecContext *r, const int block_type, src_x - 2, src_y - 2, s->h_edge_pos, s->v_edge_pos); srcY = s->edge_emu_buffer + 2 + 2*s->linesize; - s->vdsp.emulated_edge_mc(uvbuf, srcU, - s->uvlinesize, s->uvlinesize, - (width << 2) + 1, (height << 2) + 1, - uvsrc_x, uvsrc_y, - s->h_edge_pos >> 1, s->v_edge_pos >> 1); - s->vdsp.emulated_edge_mc(uvbuf + 16, srcV, - s->uvlinesize, s->uvlinesize, - (width << 2) + 1, (height << 2) + 1, - uvsrc_x, uvsrc_y, - s->h_edge_pos >> 1, s->v_edge_pos >> 1); - srcU = uvbuf; - srcV = uvbuf + 16; + emu = 1; } if(!weighted){ Y = s->dest[0] + xoff + yoff *s->linesize; @@ -764,6 +755,24 @@ static inline void rv34_mc(RV34DecContext *r, const int block_type, } is16x16 = (block_type != RV34_MB_P_8x8) && (block_type != RV34_MB_P_16x8) && (block_type != RV34_MB_P_8x16); qpel_mc[!is16x16][dxy](Y, srcY, s->linesize); + if (emu) { + uint8_t *uvbuf = s->edge_emu_buffer; + + s->vdsp.emulated_edge_mc(uvbuf, srcU, + s->uvlinesize, s->uvlinesize, + (width << 2) + 1, (height << 2) + 1, + uvsrc_x, uvsrc_y, + s->h_edge_pos >> 1, s->v_edge_pos >> 1); + srcU = uvbuf; + uvbuf += 9*s->uvlinesize; + + s->vdsp.emulated_edge_mc(uvbuf, srcV, + s->uvlinesize, s->uvlinesize, + (width << 2) + 1, (height << 2) + 1, + uvsrc_x, uvsrc_y, + s->h_edge_pos >> 1, s->v_edge_pos >> 1); + srcV = uvbuf; + } chroma_mc[2-width] (U, srcU, s->uvlinesize, height*4, uvmx, uvmy); chroma_mc[2-width] (V, srcV, s->uvlinesize, height*4, uvmx, uvmy); } @@ -1590,13 +1599,13 @@ static int finish_frame(AVCodecContext *avctx, AVFrame *pict) ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { - if ((ret = av_frame_ref(pict, &s->current_picture_ptr->f)) < 0) + if ((ret = av_frame_ref(pict, s->current_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->current_picture_ptr, pict); ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_QSCALE_TYPE_MPEG1); got_picture = 1; } else if (s->last_picture_ptr != NULL) { - if ((ret = av_frame_ref(pict, &s->last_picture_ptr->f)) < 0) + if ((ret = av_frame_ref(pict, s->last_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->last_picture_ptr, pict); ff_mpv_export_qp_table(s, pict, s->last_picture_ptr, FF_QSCALE_TYPE_MPEG1); @@ -1635,7 +1644,7 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, if (buf_size == 0) { /* special case for last picture */ if (s->low_delay==0 && s->next_picture_ptr) { - if ((ret = av_frame_ref(pict, &s->next_picture_ptr->f)) < 0) + if ((ret = av_frame_ref(pict, s->next_picture_ptr->f)) < 0) return ret; s->next_picture_ptr = NULL; @@ -1663,7 +1672,7 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "First slice header is incorrect\n"); return AVERROR_INVALIDDATA; } - if ((!s->last_picture_ptr || !s->last_picture_ptr->f.data[0]) && + if ((!s->last_picture_ptr || !s->last_picture_ptr->f->data[0]) && si.type == AV_PICTURE_TYPE_B) { av_log(avctx, AV_LOG_ERROR, "Invalid decoder state: B-frame without " "reference data.\n"); @@ -1676,7 +1685,7 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, /* first slice */ if (si.start == 0) { - if (s->mb_num_left > 0) { + if (s->mb_num_left > 0 && s->current_picture_ptr) { av_log(avctx, AV_LOG_ERROR, "New frame but still %d MB left.\n", s->mb_num_left); ff_er_frame_end(&s->er); diff --git a/libavcodec/rv34dsp.h b/libavcodec/rv34dsp.h index 75f9ff8e6..2e9ec4eee 100644 --- a/libavcodec/rv34dsp.h +++ b/libavcodec/rv34dsp.h @@ -27,8 +27,8 @@ #ifndef AVCODEC_RV34DSP_H #define AVCODEC_RV34DSP_H -#include "dsputil.h" #include "h264chroma.h" +#include "qpeldsp.h" typedef void (*rv40_weight_func)(uint8_t *dst/*align width (8 or 16)*/, uint8_t *src1/*align width (8 or 16)*/, diff --git a/libavcodec/rv40.c b/libavcodec/rv40.c index 17a2f9172..043fd724a 100644 --- a/libavcodec/rv40.c +++ b/libavcodec/rv40.c @@ -27,6 +27,7 @@ #include "libavutil/imgutils.h" #include "avcodec.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "golomb.h" @@ -455,7 +456,7 @@ static void rv40_loop_filter(RV34DecContext *r, int row) } for(j = 0; j < 16; j += 4){ - Y = s->current_picture_ptr->f.data[0] + mb_x*16 + (row*16 + j) * s->linesize; + Y = s->current_picture_ptr->f->data[0] + mb_x*16 + (row*16 + j) * s->linesize; for(i = 0; i < 4; i++, Y += 4){ int ij = i + j; int clip_cur = y_to_deblock & (MASK_CUR << ij) ? clip[POS_CUR] : 0; @@ -500,7 +501,7 @@ static void rv40_loop_filter(RV34DecContext *r, int row) } for(k = 0; k < 2; k++){ for(j = 0; j < 2; j++){ - C = s->current_picture_ptr->f.data[k + 1] + mb_x*8 + (row*8 + j*4) * s->uvlinesize; + C = s->current_picture_ptr->f->data[k + 1] + mb_x*8 + (row*8 + j*4) * s->uvlinesize; for(i = 0; i < 2; i++, C += 4){ int ij = i + j*2; int clip_cur = c_to_deblock[k] & (MASK_CUR << ij) ? clip[POS_CUR] : 0; @@ -575,7 +576,10 @@ AVCodec ff_rv40_decoder = { .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_FRAME_THREADS, .flush = ff_mpeg_flush, - .pix_fmts = ff_pixfmt_list_420, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, .init_thread_copy = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_update_thread_context), }; diff --git a/libavcodec/rv40dsp.c b/libavcodec/rv40dsp.c index 62dd5b57b..7df554962 100644 --- a/libavcodec/rv40dsp.c +++ b/libavcodec/rv40dsp.c @@ -24,16 +24,20 @@ * RV40 decoder motion compensation functions */ +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" #include "avcodec.h" #include "h264qpel.h" +#include "mathops.h" +#include "pixels.h" +#include "rnd_avg.h" #include "rv34dsp.h" #include "libavutil/avassert.h" -#include "libavutil/common.h" #define RV40_LOWPASS(OPNAME, OP) \ static av_unused void OPNAME ## rv40_qpel8_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride,\ const int h, const int C1, const int C2, const int SHIFT){\ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i;\ for(i = 0; i < h; i++)\ {\ @@ -52,7 +56,7 @@ static av_unused void OPNAME ## rv40_qpel8_h_lowpass(uint8_t *dst, uint8_t *src, \ static void OPNAME ## rv40_qpel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride,\ const int w, const int C1, const int C2, const int SHIFT){\ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i;\ for(i = 0; i < w; i++)\ {\ @@ -203,6 +207,83 @@ RV40_MC(put_, 16) RV40_MC(avg_, 8) RV40_MC(avg_, 16) +#define PIXOP2(OPNAME, OP) \ +static inline void OPNAME ## _pixels8_xy2_8_c(uint8_t *block, \ + const uint8_t *pixels, \ + ptrdiff_t line_size, \ + int h) \ +{ \ + /* FIXME HIGH BIT DEPTH */ \ + int j; \ + \ + for (j = 0; j < 2; j++) { \ + int i; \ + const uint32_t a = AV_RN32(pixels); \ + const uint32_t b = AV_RN32(pixels + 1); \ + uint32_t l0 = (a & 0x03030303UL) + \ + (b & 0x03030303UL) + \ + 0x02020202UL; \ + uint32_t h0 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + uint32_t l1, h1; \ + \ + pixels += line_size; \ + for (i = 0; i < h; i += 2) { \ + uint32_t a = AV_RN32(pixels); \ + uint32_t b = AV_RN32(pixels + 1); \ + l1 = (a & 0x03030303UL) + \ + (b & 0x03030303UL); \ + h1 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + OP(*((uint32_t *) block), \ + h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL)); \ + pixels += line_size; \ + block += line_size; \ + a = AV_RN32(pixels); \ + b = AV_RN32(pixels + 1); \ + l0 = (a & 0x03030303UL) + \ + (b & 0x03030303UL) + \ + 0x02020202UL; \ + h0 = ((a & 0xFCFCFCFCUL) >> 2) + \ + ((b & 0xFCFCFCFCUL) >> 2); \ + OP(*((uint32_t *) block), \ + h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL)); \ + pixels += line_size; \ + block += line_size; \ + } \ + pixels += 4 - line_size * (h + 1); \ + block += 4 - line_size * h; \ + } \ +} \ + \ +CALL_2X_PIXELS(OPNAME ## _pixels16_xy2_8_c, \ + OPNAME ## _pixels8_xy2_8_c, \ + 8) \ + +#define op_avg(a, b) a = rnd_avg32(a, b) +#define op_put(a, b) a = b +PIXOP2(avg, op_avg) +PIXOP2(put, op_put) +#undef op_avg +#undef op_put + +static void put_rv40_qpel16_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + put_pixels16_xy2_8_c(dst, src, stride, 16); +} +static void avg_rv40_qpel16_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + avg_pixels16_xy2_8_c(dst, src, stride, 16); +} +static void put_rv40_qpel8_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + put_pixels8_xy2_8_c(dst, src, stride, 8); +} +static void avg_rv40_qpel8_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + avg_pixels8_xy2_8_c(dst, src, stride, 8); +} + static const int rv40_bias[4][4] = { { 0, 16, 32, 16 }, { 32, 28, 32, 28 }, @@ -351,7 +432,7 @@ static av_always_inline void rv40_weak_loop_filter(uint8_t *src, const int lim_q1, const int lim_p1) { - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; int i, t, u, diff; for (i = 0; i < 4; i++, src += stride) { @@ -552,7 +633,7 @@ av_cold void ff_rv40dsp_init(RV34DSPContext *c) c->put_pixels_tab[0][12] = put_rv40_qpel16_mc03_c; c->put_pixels_tab[0][13] = put_rv40_qpel16_mc13_c; c->put_pixels_tab[0][14] = put_rv40_qpel16_mc23_c; - c->put_pixels_tab[0][15] = ff_put_rv40_qpel16_mc33_c; + c->put_pixels_tab[0][15] = put_rv40_qpel16_mc33_c; c->avg_pixels_tab[0][ 0] = qpel.avg_h264_qpel_pixels_tab[0][0]; c->avg_pixels_tab[0][ 1] = avg_rv40_qpel16_mc10_c; c->avg_pixels_tab[0][ 2] = qpel.avg_h264_qpel_pixels_tab[0][2]; @@ -568,7 +649,7 @@ av_cold void ff_rv40dsp_init(RV34DSPContext *c) c->avg_pixels_tab[0][12] = avg_rv40_qpel16_mc03_c; c->avg_pixels_tab[0][13] = avg_rv40_qpel16_mc13_c; c->avg_pixels_tab[0][14] = avg_rv40_qpel16_mc23_c; - c->avg_pixels_tab[0][15] = ff_avg_rv40_qpel16_mc33_c; + c->avg_pixels_tab[0][15] = avg_rv40_qpel16_mc33_c; c->put_pixels_tab[1][ 0] = qpel.put_h264_qpel_pixels_tab[1][0]; c->put_pixels_tab[1][ 1] = put_rv40_qpel8_mc10_c; c->put_pixels_tab[1][ 2] = qpel.put_h264_qpel_pixels_tab[1][2]; @@ -584,7 +665,7 @@ av_cold void ff_rv40dsp_init(RV34DSPContext *c) c->put_pixels_tab[1][12] = put_rv40_qpel8_mc03_c; c->put_pixels_tab[1][13] = put_rv40_qpel8_mc13_c; c->put_pixels_tab[1][14] = put_rv40_qpel8_mc23_c; - c->put_pixels_tab[1][15] = ff_put_rv40_qpel8_mc33_c; + c->put_pixels_tab[1][15] = put_rv40_qpel8_mc33_c; c->avg_pixels_tab[1][ 0] = qpel.avg_h264_qpel_pixels_tab[1][0]; c->avg_pixels_tab[1][ 1] = avg_rv40_qpel8_mc10_c; c->avg_pixels_tab[1][ 2] = qpel.avg_h264_qpel_pixels_tab[1][2]; @@ -600,7 +681,7 @@ av_cold void ff_rv40dsp_init(RV34DSPContext *c) c->avg_pixels_tab[1][12] = avg_rv40_qpel8_mc03_c; c->avg_pixels_tab[1][13] = avg_rv40_qpel8_mc13_c; c->avg_pixels_tab[1][14] = avg_rv40_qpel8_mc23_c; - c->avg_pixels_tab[1][15] = ff_avg_rv40_qpel8_mc33_c; + c->avg_pixels_tab[1][15] = avg_rv40_qpel8_mc33_c; c->put_chroma_pixels_tab[0] = put_rv40_chroma_mc8_c; c->put_chroma_pixels_tab[1] = put_rv40_chroma_mc4_c; diff --git a/libavcodec/s302menc.c b/libavcodec/s302menc.c index a7e5b1d26..540ac29da 100644 --- a/libavcodec/s302menc.c +++ b/libavcodec/s302menc.c @@ -22,6 +22,7 @@ #include "avcodec.h" #include "internal.h" +#include "mathops.h" #include "put_bits.h" #define AES3_HEADER_LEN 4 diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c index a6c1c01e5..880ef8fa2 100644 --- a/libavcodec/sanm.c +++ b/libavcodec/sanm.c @@ -20,26 +20,253 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -// #define DEBUG 1 - -#include "avcodec.h" -#include "copy_block.h" -#include "bytestream.h" -#include "internal.h" +#include "libavutil/avassert.h" #include "libavutil/bswap.h" #include "libavutil/imgutils.h" -#include "sanm_data.h" -#include "libavutil/avassert.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "copy_block.h" +#include "internal.h" #define NGLYPHS 256 +#define GLYPH_COORD_VECT_SIZE 16 +#define PALETTE_SIZE 256 +#define PALETTE_DELTA 768 -typedef struct { +static const int8_t glyph4_x[GLYPH_COORD_VECT_SIZE] = { + 0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1 +}; + +static const int8_t glyph4_y[GLYPH_COORD_VECT_SIZE] = { + 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2 +}; + +static const int8_t glyph8_x[GLYPH_COORD_VECT_SIZE] = { + 0, 2, 5, 7, 7, 7, 7, 7, 7, 5, 2, 0, 0, 0, 0, 0 +}; + +static const int8_t glyph8_y[GLYPH_COORD_VECT_SIZE] = { + 0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1 +}; + +static const int8_t motion_vectors[256][2] = { + { 0, 0 }, { -1, -43 }, { 6, -43 }, { -9, -42 }, { 13, -41 }, + { -16, -40 }, { 19, -39 }, { -23, -36 }, { 26, -34 }, { -2, -33 }, + { 4, -33 }, { -29, -32 }, { -9, -32 }, { 11, -31 }, { -16, -29 }, + { 32, -29 }, { 18, -28 }, { -34, -26 }, { -22, -25 }, { -1, -25 }, + { 3, -25 }, { -7, -24 }, { 8, -24 }, { 24, -23 }, { 36, -23 }, + { -12, -22 }, { 13, -21 }, { -38, -20 }, { 0, -20 }, { -27, -19 }, + { -4, -19 }, { 4, -19 }, { -17, -18 }, { -8, -17 }, { 8, -17 }, + { 18, -17 }, { 28, -17 }, { 39, -17 }, { -12, -15 }, { 12, -15 }, + { -21, -14 }, { -1, -14 }, { 1, -14 }, { -41, -13 }, { -5, -13 }, + { 5, -13 }, { 21, -13 }, { -31, -12 }, { -15, -11 }, { -8, -11 }, + { 8, -11 }, { 15, -11 }, { -2, -10 }, { 1, -10 }, { 31, -10 }, + { -23, -9 }, { -11, -9 }, { -5, -9 }, { 4, -9 }, { 11, -9 }, + { 42, -9 }, { 6, -8 }, { 24, -8 }, { -18, -7 }, { -7, -7 }, + { -3, -7 }, { -1, -7 }, { 2, -7 }, { 18, -7 }, { -43, -6 }, + { -13, -6 }, { -4, -6 }, { 4, -6 }, { 8, -6 }, { -33, -5 }, + { -9, -5 }, { -2, -5 }, { 0, -5 }, { 2, -5 }, { 5, -5 }, + { 13, -5 }, { -25, -4 }, { -6, -4 }, { -3, -4 }, { 3, -4 }, + { 9, -4 }, { -19, -3 }, { -7, -3 }, { -4, -3 }, { -2, -3 }, + { -1, -3 }, { 0, -3 }, { 1, -3 }, { 2, -3 }, { 4, -3 }, + { 6, -3 }, { 33, -3 }, { -14, -2 }, { -10, -2 }, { -5, -2 }, + { -3, -2 }, { -2, -2 }, { -1, -2 }, { 0, -2 }, { 1, -2 }, + { 2, -2 }, { 3, -2 }, { 5, -2 }, { 7, -2 }, { 14, -2 }, + { 19, -2 }, { 25, -2 }, { 43, -2 }, { -7, -1 }, { -3, -1 }, + { -2, -1 }, { -1, -1 }, { 0, -1 }, { 1, -1 }, { 2, -1 }, + { 3, -1 }, { 10, -1 }, { -5, 0 }, { -3, 0 }, { -2, 0 }, + { -1, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 }, { 5, 0 }, + { 7, 0 }, { -10, 1 }, { -7, 1 }, { -3, 1 }, { -2, 1 }, + { -1, 1 }, { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 }, + { -43, 2 }, { -25, 2 }, { -19, 2 }, { -14, 2 }, { -5, 2 }, + { -3, 2 }, { -2, 2 }, { -1, 2 }, { 0, 2 }, { 1, 2 }, + { 2, 2 }, { 3, 2 }, { 5, 2 }, { 7, 2 }, { 10, 2 }, + { 14, 2 }, { -33, 3 }, { -6, 3 }, { -4, 3 }, { -2, 3 }, + { -1, 3 }, { 0, 3 }, { 1, 3 }, { 2, 3 }, { 4, 3 }, + { 19, 3 }, { -9, 4 }, { -3, 4 }, { 3, 4 }, { 7, 4 }, + { 25, 4 }, { -13, 5 }, { -5, 5 }, { -2, 5 }, { 0, 5 }, + { 2, 5 }, { 5, 5 }, { 9, 5 }, { 33, 5 }, { -8, 6 }, + { -4, 6 }, { 4, 6 }, { 13, 6 }, { 43, 6 }, { -18, 7 }, + { -2, 7 }, { 0, 7 }, { 2, 7 }, { 7, 7 }, { 18, 7 }, + { -24, 8 }, { -6, 8 }, { -42, 9 }, { -11, 9 }, { -4, 9 }, + { 5, 9 }, { 11, 9 }, { 23, 9 }, { -31, 10 }, { -1, 10 }, + { 2, 10 }, { -15, 11 }, { -8, 11 }, { 8, 11 }, { 15, 11 }, + { 31, 12 }, { -21, 13 }, { -5, 13 }, { 5, 13 }, { 41, 13 }, + { -1, 14 }, { 1, 14 }, { 21, 14 }, { -12, 15 }, { 12, 15 }, + { -39, 17 }, { -28, 17 }, { -18, 17 }, { -8, 17 }, { 8, 17 }, + { 17, 18 }, { -4, 19 }, { 0, 19 }, { 4, 19 }, { 27, 19 }, + { 38, 20 }, { -13, 21 }, { 12, 22 }, { -36, 23 }, { -24, 23 }, + { -8, 24 }, { 7, 24 }, { -3, 25 }, { 1, 25 }, { 22, 25 }, + { 34, 26 }, { -18, 28 }, { -32, 29 }, { 16, 29 }, { -11, 31 }, + { 9, 32 }, { 29, 32 }, { -4, 33 }, { 2, 33 }, { -26, 34 }, + { 23, 36 }, { -19, 39 }, { 16, 40 }, { -13, 41 }, { 9, 42 }, + { -6, 43 }, { 1, 43 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, +}; + +static const int8_t c37_mv[] = { + 0, 0, 1, 0, 2, 0, 3, 0, 5, 0, + 8, 0, 13, 0, 21, 0, -1, 0, -2, 0, + -3, 0, -5, 0, -8, 0, -13, 0, -17, 0, + -21, 0, 0, 1, 1, 1, 2, 1, 3, 1, + 5, 1, 8, 1, 13, 1, 21, 1, -1, 1, + -2, 1, -3, 1, -5, 1, -8, 1, -13, 1, + -17, 1, -21, 1, 0, 2, 1, 2, 2, 2, + 3, 2, 5, 2, 8, 2, 13, 2, 21, 2, + -1, 2, -2, 2, -3, 2, -5, 2, -8, 2, + -13, 2, -17, 2, -21, 2, 0, 3, 1, 3, + 2, 3, 3, 3, 5, 3, 8, 3, 13, 3, + 21, 3, -1, 3, -2, 3, -3, 3, -5, 3, + -8, 3, -13, 3, -17, 3, -21, 3, 0, 5, + 1, 5, 2, 5, 3, 5, 5, 5, 8, 5, + 13, 5, 21, 5, -1, 5, -2, 5, -3, 5, + -5, 5, -8, 5, -13, 5, -17, 5, -21, 5, + 0, 8, 1, 8, 2, 8, 3, 8, 5, 8, + 8, 8, 13, 8, 21, 8, -1, 8, -2, 8, + -3, 8, -5, 8, -8, 8, -13, 8, -17, 8, + -21, 8, 0, 13, 1, 13, 2, 13, 3, 13, + 5, 13, 8, 13, 13, 13, 21, 13, -1, 13, + -2, 13, -3, 13, -5, 13, -8, 13, -13, 13, + -17, 13, -21, 13, 0, 21, 1, 21, 2, 21, + 3, 21, 5, 21, 8, 21, 13, 21, 21, 21, + -1, 21, -2, 21, -3, 21, -5, 21, -8, 21, + -13, 21, -17, 21, -21, 21, 0, -1, 1, -1, + 2, -1, 3, -1, 5, -1, 8, -1, 13, -1, + 21, -1, -1, -1, -2, -1, -3, -1, -5, -1, + -8, -1, -13, -1, -17, -1, -21, -1, 0, -2, + 1, -2, 2, -2, 3, -2, 5, -2, 8, -2, + 13, -2, 21, -2, -1, -2, -2, -2, -3, -2, + -5, -2, -8, -2, -13, -2, -17, -2, -21, -2, + 0, -3, 1, -3, 2, -3, 3, -3, 5, -3, + 8, -3, 13, -3, 21, -3, -1, -3, -2, -3, + -3, -3, -5, -3, -8, -3, -13, -3, -17, -3, + -21, -3, 0, -5, 1, -5, 2, -5, 3, -5, + 5, -5, 8, -5, 13, -5, 21, -5, -1, -5, + -2, -5, -3, -5, -5, -5, -8, -5, -13, -5, + -17, -5, -21, -5, 0, -8, 1, -8, 2, -8, + 3, -8, 5, -8, 8, -8, 13, -8, 21, -8, + -1, -8, -2, -8, -3, -8, -5, -8, -8, -8, + -13, -8, -17, -8, -21, -8, 0, -13, 1, -13, + 2, -13, 3, -13, 5, -13, 8, -13, 13, -13, + 21, -13, -1, -13, -2, -13, -3, -13, -5, -13, + -8, -13, -13, -13, -17, -13, -21, -13, 0, -17, + 1, -17, 2, -17, 3, -17, 5, -17, 8, -17, + 13, -17, 21, -17, -1, -17, -2, -17, -3, -17, + -5, -17, -8, -17, -13, -17, -17, -17, -21, -17, + 0, -21, 1, -21, 2, -21, 3, -21, 5, -21, + 8, -21, 13, -21, 21, -21, -1, -21, -2, -21, + -3, -21, -5, -21, -8, -21, -13, -21, -17, -21, + 0, 0, -8, -29, 8, -29, -18, -25, 17, -25, + 0, -23, -6, -22, 6, -22, -13, -19, 12, -19, + 0, -18, 25, -18, -25, -17, -5, -17, 5, -17, + -10, -15, 10, -15, 0, -14, -4, -13, 4, -13, + 19, -13, -19, -12, -8, -11, -2, -11, 0, -11, + 2, -11, 8, -11, -15, -10, -4, -10, 4, -10, + 15, -10, -6, -9, -1, -9, 1, -9, 6, -9, + -29, -8, -11, -8, -8, -8, -3, -8, 3, -8, + 8, -8, 11, -8, 29, -8, -5, -7, -2, -7, + 0, -7, 2, -7, 5, -7, -22, -6, -9, -6, + -6, -6, -3, -6, -1, -6, 1, -6, 3, -6, + 6, -6, 9, -6, 22, -6, -17, -5, -7, -5, + -4, -5, -2, -5, 0, -5, 2, -5, 4, -5, + 7, -5, 17, -5, -13, -4, -10, -4, -5, -4, + -3, -4, -1, -4, 0, -4, 1, -4, 3, -4, + 5, -4, 10, -4, 13, -4, -8, -3, -6, -3, + -4, -3, -3, -3, -2, -3, -1, -3, 0, -3, + 1, -3, 2, -3, 4, -3, 6, -3, 8, -3, + -11, -2, -7, -2, -5, -2, -3, -2, -2, -2, + -1, -2, 0, -2, 1, -2, 2, -2, 3, -2, + 5, -2, 7, -2, 11, -2, -9, -1, -6, -1, + -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, + 1, -1, 2, -1, 3, -1, 4, -1, 6, -1, + 9, -1, -31, 0, -23, 0, -18, 0, -14, 0, + -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, + -2, 0, -1, 0, 0, -31, 1, 0, 2, 0, + 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, + 14, 0, 18, 0, 23, 0, 31, 0, -9, 1, + -6, 1, -4, 1, -3, 1, -2, 1, -1, 1, + 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, + 6, 1, 9, 1, -11, 2, -7, 2, -5, 2, + -3, 2, -2, 2, -1, 2, 0, 2, 1, 2, + 2, 2, 3, 2, 5, 2, 7, 2, 11, 2, + -8, 3, -6, 3, -4, 3, -2, 3, -1, 3, + 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, + 6, 3, 8, 3, -13, 4, -10, 4, -5, 4, + -3, 4, -1, 4, 0, 4, 1, 4, 3, 4, + 5, 4, 10, 4, 13, 4, -17, 5, -7, 5, + -4, 5, -2, 5, 0, 5, 2, 5, 4, 5, + 7, 5, 17, 5, -22, 6, -9, 6, -6, 6, + -3, 6, -1, 6, 1, 6, 3, 6, 6, 6, + 9, 6, 22, 6, -5, 7, -2, 7, 0, 7, + 2, 7, 5, 7, -29, 8, -11, 8, -8, 8, + -3, 8, 3, 8, 8, 8, 11, 8, 29, 8, + -6, 9, -1, 9, 1, 9, 6, 9, -15, 10, + -4, 10, 4, 10, 15, 10, -8, 11, -2, 11, + 0, 11, 2, 11, 8, 11, 19, 12, -19, 13, + -4, 13, 4, 13, 0, 14, -10, 15, 10, 15, + -5, 17, 5, 17, 25, 17, -25, 18, 0, 18, + -12, 19, 13, 19, -6, 22, 6, 22, 0, 23, + -17, 25, 18, 25, -8, 29, 8, 29, 0, 31, + 0, 0, -6, -22, 6, -22, -13, -19, 12, -19, + 0, -18, -5, -17, 5, -17, -10, -15, 10, -15, + 0, -14, -4, -13, 4, -13, 19, -13, -19, -12, + -8, -11, -2, -11, 0, -11, 2, -11, 8, -11, + -15, -10, -4, -10, 4, -10, 15, -10, -6, -9, + -1, -9, 1, -9, 6, -9, -11, -8, -8, -8, + -3, -8, 0, -8, 3, -8, 8, -8, 11, -8, + -5, -7, -2, -7, 0, -7, 2, -7, 5, -7, + -22, -6, -9, -6, -6, -6, -3, -6, -1, -6, + 1, -6, 3, -6, 6, -6, 9, -6, 22, -6, + -17, -5, -7, -5, -4, -5, -2, -5, -1, -5, + 0, -5, 1, -5, 2, -5, 4, -5, 7, -5, + 17, -5, -13, -4, -10, -4, -5, -4, -3, -4, + -2, -4, -1, -4, 0, -4, 1, -4, 2, -4, + 3, -4, 5, -4, 10, -4, 13, -4, -8, -3, + -6, -3, -4, -3, -3, -3, -2, -3, -1, -3, + 0, -3, 1, -3, 2, -3, 3, -3, 4, -3, + 6, -3, 8, -3, -11, -2, -7, -2, -5, -2, + -4, -2, -3, -2, -2, -2, -1, -2, 0, -2, + 1, -2, 2, -2, 3, -2, 4, -2, 5, -2, + 7, -2, 11, -2, -9, -1, -6, -1, -5, -1, + -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, + 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, + 6, -1, 9, -1, -23, 0, -18, 0, -14, 0, + -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, + -2, 0, -1, 0, 0, -23, 1, 0, 2, 0, + 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, + 14, 0, 18, 0, 23, 0, -9, 1, -6, 1, + -5, 1, -4, 1, -3, 1, -2, 1, -1, 1, + 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, + 5, 1, 6, 1, 9, 1, -11, 2, -7, 2, + -5, 2, -4, 2, -3, 2, -2, 2, -1, 2, + 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, + 5, 2, 7, 2, 11, 2, -8, 3, -6, 3, + -4, 3, -3, 3, -2, 3, -1, 3, 0, 3, + 1, 3, 2, 3, 3, 3, 4, 3, 6, 3, + 8, 3, -13, 4, -10, 4, -5, 4, -3, 4, + -2, 4, -1, 4, 0, 4, 1, 4, 2, 4, + 3, 4, 5, 4, 10, 4, 13, 4, -17, 5, + -7, 5, -4, 5, -2, 5, -1, 5, 0, 5, + 1, 5, 2, 5, 4, 5, 7, 5, 17, 5, + -22, 6, -9, 6, -6, 6, -3, 6, -1, 6, + 1, 6, 3, 6, 6, 6, 9, 6, 22, 6, + -5, 7, -2, 7, 0, 7, 2, 7, 5, 7, + -11, 8, -8, 8, -3, 8, 0, 8, 3, 8, + 8, 8, 11, 8, -6, 9, -1, 9, 1, 9, + 6, 9, -15, 10, -4, 10, 4, 10, 15, 10, + -8, 11, -2, 11, 0, 11, 2, 11, 8, 11, + 19, 12, -19, 13, -4, 13, 4, 13, 0, 14, + -10, 15, 10, 15, -5, 17, 5, 17, 0, 18, + -12, 19, 13, 19, -6, 22, 6, 22, 0, 23, +}; + +typedef struct SANMVideoContext { AVCodecContext *avctx; GetByteContext gb; int version, subversion; - uint32_t pal[256]; - int16_t delta_pal[768]; + uint32_t pal[PALETTE_SIZE]; + int16_t delta_pal[PALETTE_DELTA]; int pitch; int width, height; @@ -66,7 +293,7 @@ typedef struct { int8_t p8x8glyphs[NGLYPHS][64]; } SANMVideoContext; -typedef struct { +typedef struct SANMFrameHeader { int seq_num, codec, rotate_code, rle_output_size; uint16_t bg_color; @@ -100,17 +327,16 @@ static enum GlyphEdge which_edge(int x, int y, int edge_size) { const int edge_max = edge_size - 1; - if (!y) { + if (!y) return BOTTOM_EDGE; - } else if (y == edge_max) { + else if (y == edge_max) return TOP_EDGE; - } else if (!x) { + else if (!x) return LEFT_EDGE; - } else if (x == edge_max) { + else if (x == edge_max) return RIGHT_EDGE; - } else { + else return NO_EDGE; - } } static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1) @@ -118,27 +344,24 @@ static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1) if ((edge0 == LEFT_EDGE && edge1 == RIGHT_EDGE) || (edge1 == LEFT_EDGE && edge0 == RIGHT_EDGE) || (edge0 == BOTTOM_EDGE && edge1 != TOP_EDGE) || - (edge1 == BOTTOM_EDGE && edge0 != TOP_EDGE)) { + (edge1 == BOTTOM_EDGE && edge0 != TOP_EDGE)) return DIR_UP; - } else if ((edge0 == TOP_EDGE && edge1 != BOTTOM_EDGE) || - (edge1 == TOP_EDGE && edge0 != BOTTOM_EDGE)) { + else if ((edge0 == TOP_EDGE && edge1 != BOTTOM_EDGE) || + (edge1 == TOP_EDGE && edge0 != BOTTOM_EDGE)) return DIR_DOWN; - } else if ((edge0 == LEFT_EDGE && edge1 != RIGHT_EDGE) || - (edge1 == LEFT_EDGE && edge0 != RIGHT_EDGE)) { + else if ((edge0 == LEFT_EDGE && edge1 != RIGHT_EDGE) || + (edge1 == LEFT_EDGE && edge0 != RIGHT_EDGE)) return DIR_LEFT; - } else if ((edge0 == TOP_EDGE && edge1 == BOTTOM_EDGE) || - (edge1 == TOP_EDGE && edge0 == BOTTOM_EDGE) || - (edge0 == RIGHT_EDGE && edge1 != LEFT_EDGE) || - (edge1 == RIGHT_EDGE && edge0 != LEFT_EDGE)) { + else if ((edge0 == TOP_EDGE && edge1 == BOTTOM_EDGE) || + (edge1 == TOP_EDGE && edge0 == BOTTOM_EDGE) || + (edge0 == RIGHT_EDGE && edge1 != LEFT_EDGE) || + (edge1 == RIGHT_EDGE && edge0 != LEFT_EDGE)) return DIR_RIGHT; - } return NO_DIR; } -/** - * Interpolate two points. - */ +/* Interpolate two points. */ static void interp_point(int8_t *points, int x0, int y0, int x1, int y1, int pos, int npoints) { @@ -152,11 +375,11 @@ static void interp_point(int8_t *points, int x0, int y0, int x1, int y1, } /** - * Construct glyphs by iterating through vectors coordinates. + * Construct glyphs by iterating through vector coordinates. * * @param pglyphs pointer to table where glyphs are stored - * @param xvec pointer to x component of vectors coordinates - * @param yvec pointer to y component of vectors coordinates + * @param xvec pointer to x component of vector coordinates + * @param yvec pointer to y component of vector coordinates * @param side_length glyph width/height. */ static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec, @@ -167,15 +390,15 @@ static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec, int i, j; for (i = 0; i < GLYPH_COORD_VECT_SIZE; i++) { - int x0 = xvec[i]; - int y0 = yvec[i]; + int x0 = xvec[i]; + int y0 = yvec[i]; enum GlyphEdge edge0 = which_edge(x0, y0, side_length); for (j = 0; j < GLYPH_COORD_VECT_SIZE; j++, pglyph += glyph_size) { - int x1 = xvec[j]; - int y1 = yvec[j]; - enum GlyphEdge edge1 = which_edge(x1, y1, side_length); - enum GlyphDir dir = which_direction(edge0, edge1); + int x1 = xvec[j]; + int y1 = yvec[j]; + enum GlyphEdge edge1 = which_edge(x1, y1, side_length); + enum GlyphDir dir = which_direction(edge0, edge1); int npoints = FFMAX(FFABS(x1 - x0), FFABS(y1 - y0)); int ipoint; @@ -217,7 +440,7 @@ static void init_sizes(SANMVideoContext *ctx, int width, int height) ctx->height = height; ctx->npixels = width * height; - ctx->aligned_width = FFALIGN(width, 8); + ctx->aligned_width = FFALIGN(width, 8); ctx->aligned_height = FFALIGN(height, 8); ctx->buf_size = ctx->aligned_width * ctx->aligned_height * sizeof(ctx->frm0[0]); @@ -242,9 +465,11 @@ static av_cold int init_buffers(SANMVideoContext *ctx) av_fast_padded_malloc(&ctx->frm1, &ctx->frm1_size, ctx->buf_size); av_fast_padded_malloc(&ctx->frm2, &ctx->frm2_size, ctx->buf_size); if (!ctx->version) - av_fast_padded_malloc(&ctx->stored_frame, &ctx->stored_frame_size, ctx->buf_size); + av_fast_padded_malloc(&ctx->stored_frame, + &ctx->stored_frame_size, ctx->buf_size); - if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 || (!ctx->stored_frame && !ctx->version)) { + if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 || + (!ctx->stored_frame && !ctx->version)) { destroy_buffers(ctx); return AVERROR(ENOMEM); } @@ -254,7 +479,6 @@ static av_cold int init_buffers(SANMVideoContext *ctx) static void rotate_bufs(SANMVideoContext *ctx, int rotate_code) { - av_dlog(ctx->avctx, "rotate %d\n", rotate_code); if (rotate_code == 2) FFSWAP(uint16_t*, ctx->frm1, ctx->frm2); FFSWAP(uint16_t*, ctx->frm2, ctx->frm0); @@ -264,14 +488,14 @@ static av_cold int decode_init(AVCodecContext *avctx) { SANMVideoContext *ctx = avctx->priv_data; - ctx->avctx = avctx; - ctx->version = !avctx->extradata_size; + ctx->avctx = avctx; + ctx->version = !avctx->extradata_size; avctx->pix_fmt = ctx->version ? AV_PIX_FMT_RGB565 : AV_PIX_FMT_PAL8; init_sizes(ctx, avctx->width, avctx->height); if (init_buffers(ctx)) { - av_log(avctx, AV_LOG_ERROR, "error allocating buffers\n"); + av_log(avctx, AV_LOG_ERROR, "Error allocating buffers.\n"); return AVERROR(ENOMEM); } @@ -282,12 +506,12 @@ static av_cold int decode_init(AVCodecContext *avctx) int i; if (avctx->extradata_size < 1026) { - av_log(avctx, AV_LOG_ERROR, "not enough extradata\n"); + av_log(avctx, AV_LOG_ERROR, "Not enough extradata.\n"); return AVERROR_INVALIDDATA; } ctx->subversion = AV_RL16(avctx->extradata); - for (i = 0; i < 256; i++) + for (i = 0; i < PALETTE_SIZE; i++) ctx->pal[i] = 0xFFU << 24 | AV_RL32(avctx->extradata + 2 + i * 4); } @@ -332,7 +556,7 @@ static int rle_decode(SANMVideoContext *ctx, uint8_t *dst, const int out_size) static int old_codec1(SANMVideoContext *ctx, int top, int left, int width, int height) { - uint8_t *dst = ((uint8_t*)ctx->frm0) + left + top * ctx->pitch; + uint8_t *dst = ((uint8_t *)ctx->frm0) + left + top * ctx->pitch; int i, j, len, flag, code, val, pos, end; for (i = 0; i < height; i++) { @@ -400,22 +624,21 @@ static int old_codec37(SANMVideoContext *ctx, int top, { int stride = ctx->pitch; int i, j, k, t; - int skip_run = 0; - int compr, mvoff, seq, flags; - uint32_t decoded_size; uint8_t *dst, *prev; + int skip_run = 0; + int compr = bytestream2_get_byte(&ctx->gb); + int mvoff = bytestream2_get_byte(&ctx->gb); + int seq = bytestream2_get_le16(&ctx->gb); + uint32_t decoded_size = bytestream2_get_le32(&ctx->gb); + int flags; - compr = bytestream2_get_byte(&ctx->gb); - mvoff = bytestream2_get_byte(&ctx->gb); - seq = bytestream2_get_le16(&ctx->gb); - decoded_size = bytestream2_get_le32(&ctx->gb); bytestream2_skip(&ctx->gb, 4); - flags = bytestream2_get_byte(&ctx->gb); + flags = bytestream2_get_byte(&ctx->gb); bytestream2_skip(&ctx->gb, 3); if (decoded_size > ctx->height * stride - left - top * stride) { decoded_size = ctx->height * stride - left - top * stride; - av_log(ctx->avctx, AV_LOG_WARNING, "decoded size is too large\n"); + av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n"); } ctx->rotate_code = 0; @@ -427,10 +650,10 @@ static int old_codec37(SANMVideoContext *ctx, int top, prev = ((uint8_t*)ctx->frm2) + left + top * stride; if (mvoff > 2) { - av_log(ctx->avctx, AV_LOG_ERROR, "invalid motion base value %d\n", mvoff); + av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvoff); return AVERROR_INVALIDDATA; } - av_dlog(ctx->avctx, "compression %d\n", compr); + switch (compr) { case 0: for (i = 0; i < height; i++) { @@ -489,7 +712,7 @@ static int old_codec37(SANMVideoContext *ctx, int top, } else { int mx, my; - mx = c37_mv[(mvoff * 255 + code) * 2 ]; + mx = c37_mv[(mvoff * 255 + code) * 2]; my = c37_mv[(mvoff * 255 + code) * 2 + 1]; codec37_mv(dst + i, prev + i + mx + my * stride, ctx->height, stride, i + mx, j + my); @@ -534,8 +757,8 @@ static int old_codec37(SANMVideoContext *ctx, int top, } break; default: - av_log(ctx->avctx, AV_LOG_ERROR, - "subcodec 37 compression %d not implemented\n", compr); + avpriv_report_missing_feature(ctx->avctx, + "Subcodec 37 compression %d", compr); return AVERROR_PATCHWELCOME; } @@ -559,10 +782,10 @@ static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1, if (size == 2) { if (bytestream2_get_bytes_left(&ctx->gb) < 4) return AVERROR_INVALIDDATA; - dst[0] = bytestream2_get_byteu(&ctx->gb); - dst[1] = bytestream2_get_byteu(&ctx->gb); - dst[0+stride] = bytestream2_get_byteu(&ctx->gb); - dst[1+stride] = bytestream2_get_byteu(&ctx->gb); + dst[0] = bytestream2_get_byteu(&ctx->gb); + dst[1] = bytestream2_get_byteu(&ctx->gb); + dst[0 + stride] = bytestream2_get_byteu(&ctx->gb); + dst[1 + stride] = bytestream2_get_byteu(&ctx->gb); } else { size >>= 1; if (process_block(ctx, dst, prev1, prev2, stride, tbl, size)) @@ -615,13 +838,13 @@ static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1, } else { int mx = motion_vectors[code][0]; int my = motion_vectors[code][1]; - int index = prev2 - (const uint8_t*)ctx->frm2; + int index = prev2 - (const uint8_t *)ctx->frm2; - av_assert2(index >= 0 && index < (ctx->buf_size>>1)); + av_assert2(index >= 0 && index < (ctx->buf_size >> 1)); - if (index < - mx - my*stride || - (ctx->buf_size>>1) - index < mx + size + (my + size - 1)*stride) { - av_log(ctx->avctx, AV_LOG_ERROR, "MV is invalid \n"); + if (index < -mx - my * stride || + (ctx->buf_size >> 1) - index < mx + size + (my + size - 1) * stride) { + av_log(ctx->avctx, AV_LOG_ERROR, "MV is invalid.\n"); return AVERROR_INVALIDDATA; } @@ -635,25 +858,25 @@ static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1, static int old_codec47(SANMVideoContext *ctx, int top, int left, int width, int height) { - int i, j, seq, compr, new_rot, tbl_pos, skip; - int stride = ctx->pitch; - uint8_t *dst = ((uint8_t*)ctx->frm0) + left + top * stride; - uint8_t *prev1 = (uint8_t*)ctx->frm1; - uint8_t *prev2 = (uint8_t*)ctx->frm2; uint32_t decoded_size; + int i, j; + int stride = ctx->pitch; + uint8_t *dst = (uint8_t *)ctx->frm0 + left + top * stride; + uint8_t *prev1 = (uint8_t *)ctx->frm1; + uint8_t *prev2 = (uint8_t *)ctx->frm2; + int tbl_pos = bytestream2_tell(&ctx->gb); + int seq = bytestream2_get_le16(&ctx->gb); + int compr = bytestream2_get_byte(&ctx->gb); + int new_rot = bytestream2_get_byte(&ctx->gb); + int skip = bytestream2_get_byte(&ctx->gb); - tbl_pos = bytestream2_tell(&ctx->gb); - seq = bytestream2_get_le16(&ctx->gb); - compr = bytestream2_get_byte(&ctx->gb); - new_rot = bytestream2_get_byte(&ctx->gb); - skip = bytestream2_get_byte(&ctx->gb); bytestream2_skip(&ctx->gb, 9); decoded_size = bytestream2_get_le32(&ctx->gb); bytestream2_skip(&ctx->gb, 8); if (decoded_size > ctx->height * stride - left - top * stride) { decoded_size = ctx->height * stride - left - top * stride; - av_log(ctx->avctx, AV_LOG_WARNING, "decoded size is too large\n"); + av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n"); } if (skip & 1) @@ -663,7 +886,7 @@ static int old_codec47(SANMVideoContext *ctx, int top, memset(prev1, 0, ctx->height * stride); memset(prev2, 0, ctx->height * stride); } - av_dlog(ctx->avctx, "compression %d\n", compr); + switch (compr) { case 0: if (bytestream2_get_bytes_left(&ctx->gb) < width * height) @@ -678,8 +901,10 @@ static int old_codec47(SANMVideoContext *ctx, int top, return AVERROR_INVALIDDATA; for (j = 0; j < height; j += 2) { for (i = 0; i < width; i += 2) { - dst[i] = dst[i + 1] = - dst[stride + i] = dst[stride + i + 1] = bytestream2_get_byteu(&ctx->gb); + dst[i] = + dst[i + 1] = + dst[stride + i] = + dst[stride + i + 1] = bytestream2_get_byteu(&ctx->gb); } dst += stride * 2; } @@ -687,11 +912,10 @@ static int old_codec47(SANMVideoContext *ctx, int top, case 2: if (seq == ctx->prev_seq + 1) { for (j = 0; j < height; j += 8) { - for (i = 0; i < width; i += 8) { + for (i = 0; i < width; i += 8) if (process_block(ctx, dst + i, prev1 + i, prev2 + i, stride, tbl_pos + 8, 8)) return AVERROR_INVALIDDATA; - } dst += stride * 8; prev1 += stride * 8; prev2 += stride * 8; @@ -709,8 +933,8 @@ static int old_codec47(SANMVideoContext *ctx, int top, return AVERROR_INVALIDDATA; break; default: - av_log(ctx->avctx, AV_LOG_ERROR, - "subcodec 47 compression %d not implemented\n", compr); + avpriv_report_missing_feature(ctx->avctx, + "Subcodec 47 compression %d", compr); return AVERROR_PATCHWELCOME; } if (seq == ctx->prev_seq + 1) @@ -724,34 +948,31 @@ static int old_codec47(SANMVideoContext *ctx, int top, static int process_frame_obj(SANMVideoContext *ctx) { - uint16_t codec, top, left, w, h; - - codec = bytestream2_get_le16u(&ctx->gb); - left = bytestream2_get_le16u(&ctx->gb); - top = bytestream2_get_le16u(&ctx->gb); - w = bytestream2_get_le16u(&ctx->gb); - h = bytestream2_get_le16u(&ctx->gb); + uint16_t codec = bytestream2_get_le16u(&ctx->gb); + uint16_t left = bytestream2_get_le16u(&ctx->gb); + uint16_t top = bytestream2_get_le16u(&ctx->gb); + uint16_t w = bytestream2_get_le16u(&ctx->gb); + uint16_t h = bytestream2_get_le16u(&ctx->gb); if (!w || !h) { - av_log(ctx->avctx, AV_LOG_ERROR, "dimensions are invalid\n"); + av_log(ctx->avctx, AV_LOG_ERROR, "Dimensions are invalid.\n"); return AVERROR_INVALIDDATA; } if (ctx->width < left + w || ctx->height < top + h) { int ret = ff_set_dimensions(ctx->avctx, FFMAX(left + w, ctx->width), - FFMAX(top + h, ctx->height)); + FFMAX(top + h, ctx->height)); if (ret < 0) return ret; init_sizes(ctx, FFMAX(left + w, ctx->width), - FFMAX(top + h, ctx->height)); + FFMAX(top + h, ctx->height)); if (init_buffers(ctx)) { - av_log(ctx->avctx, AV_LOG_ERROR, "error resizing buffers\n"); + av_log(ctx->avctx, AV_LOG_ERROR, "Error resizing buffers.\n"); return AVERROR(ENOMEM); } } bytestream2_skip(&ctx->gb, 4); - av_dlog(ctx->avctx, "subcodec %d\n", codec); switch (codec) { case 1: case 3: @@ -764,7 +985,7 @@ static int process_frame_obj(SANMVideoContext *ctx) return old_codec47(ctx, top, left, w, h); break; default: - avpriv_request_sample(ctx->avctx, "unknown subcodec %d", codec); + avpriv_request_sample(ctx->avctx, "Subcodec %d", codec); return AVERROR_PATCHWELCOME; } } @@ -775,7 +996,7 @@ static int decode_0(SANMVideoContext *ctx) int x, y; if (bytestream2_get_bytes_left(&ctx->gb) < ctx->width * ctx->height * 2) { - av_log(ctx->avctx, AV_LOG_ERROR, "insufficient data for raw frame\n"); + av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for raw frame.\n"); return AVERROR_INVALIDDATA; } for (y = 0; y < ctx->height; y++) { @@ -788,7 +1009,7 @@ static int decode_0(SANMVideoContext *ctx) static int decode_nop(SANMVideoContext *ctx) { - avpriv_request_sample(ctx->avctx, "unknown/unsupported compression type"); + avpriv_request_sample(ctx->avctx, "Unknown/unsupported compression type"); return AVERROR_PATCHWELCOME; } @@ -821,15 +1042,16 @@ static void fill_block(uint16_t *pdest, uint16_t color, int block_size, int pitc *pdest++ = color; } -static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index, uint16_t fg_color, - uint16_t bg_color, int block_size, int pitch) +static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index, + uint16_t fg_color, uint16_t bg_color, int block_size, + int pitch) { int8_t *pglyph; uint16_t colors[2] = { fg_color, bg_color }; int x, y; if (index >= NGLYPHS) { - av_log(ctx->avctx, AV_LOG_ERROR, "ignoring nonexistent glyph #%u\n", index); + av_log(ctx->avctx, AV_LOG_ERROR, "Ignoring nonexistent glyph #%u.\n", index); return AVERROR_INVALIDDATA; } @@ -853,9 +1075,12 @@ static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, in return AVERROR_INVALIDDATA; indices = bytestream2_get_le32u(&ctx->gb); - dst[0] = ctx->codebook[indices & 0xFF]; indices >>= 8; - dst[1] = ctx->codebook[indices & 0xFF]; indices >>= 8; - dst[pitch] = ctx->codebook[indices & 0xFF]; indices >>= 8; + dst[0] = ctx->codebook[indices & 0xFF]; + indices >>= 8; + dst[1] = ctx->codebook[indices & 0xFF]; + indices >>= 8; + dst[pitch] = ctx->codebook[indices & 0xFF]; + indices >>= 8; dst[pitch + 1] = ctx->codebook[indices & 0xFF]; } else { uint16_t fgcolor, bgcolor; @@ -909,10 +1134,10 @@ static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my, int good = start_pos >= 0 && end_pos < (ctx->buf_size >> 1); - if (!good) { - av_log(ctx->avctx, AV_LOG_ERROR, "ignoring invalid motion vector (%i, %i)->(%u, %u), block size = %u\n", + if (!good) + av_log(ctx->avctx, AV_LOG_ERROR, + "Ignoring invalid motion vector (%i, %i)->(%u, %u), block size = %u\n", cx + mx, cy + my, cx, cy, block_size); - } return good; } @@ -927,7 +1152,6 @@ static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size) opcode = bytestream2_get_byteu(&ctx->gb); - av_dlog(ctx->avctx, "opcode 0x%0X cx %d cy %d blk %d\n", opcode, cx, cy, blk_size); switch (opcode) { default: mx = motion_vectors[opcode][0]; @@ -989,11 +1213,11 @@ static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size) opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch); } else { blk_size >>= 1; - if (codec2subblock(ctx, cx , cy , blk_size)) + if (codec2subblock(ctx, cx, cy, blk_size)) return AVERROR_INVALIDDATA; - if (codec2subblock(ctx, cx + blk_size, cy , blk_size)) + if (codec2subblock(ctx, cx + blk_size, cy, blk_size)) return AVERROR_INVALIDDATA; - if (codec2subblock(ctx, cx , cy + blk_size, blk_size)) + if (codec2subblock(ctx, cx, cy + blk_size, blk_size)) return AVERROR_INVALIDDATA; if (codec2subblock(ctx, cx + blk_size, cy + blk_size, blk_size)) return AVERROR_INVALIDDATA; @@ -1007,12 +1231,10 @@ static int decode_2(SANMVideoContext *ctx) { int cx, cy, ret; - for (cy = 0; cy < ctx->aligned_height; cy += 8) { - for (cx = 0; cx < ctx->aligned_width; cx += 8) { + for (cy = 0; cy < ctx->aligned_height; cy += 8) + for (cx = 0; cx < ctx->aligned_width; cx += 8) if (ret = codec2subblock(ctx, cx, cy, 8)) return ret; - } - } return 0; } @@ -1058,7 +1280,7 @@ static int decode_6(SANMVideoContext *ctx) uint16_t *frm = ctx->frm0; if (bytestream2_get_bytes_left(&ctx->gb) < npixels) { - av_log(ctx->avctx, AV_LOG_ERROR, "insufficient data for frame\n"); + av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for frame.\n"); return AVERROR_INVALIDDATA; } while (npixels--) @@ -1075,7 +1297,7 @@ static int decode_8(SANMVideoContext *ctx) av_fast_malloc(&ctx->rle_buf, &ctx->rle_buf_size, npixels); if (!ctx->rle_buf) { - av_log(ctx->avctx, AV_LOG_ERROR, "RLE buffer allocation failed\n"); + av_log(ctx->avctx, AV_LOG_ERROR, "RLE buffer allocation failed.\n"); return AVERROR(ENOMEM); } rsrc = ctx->rle_buf; @@ -1101,7 +1323,7 @@ static int read_frame_header(SANMVideoContext *ctx, SANMFrameHeader *hdr) int i, ret; if ((ret = bytestream2_get_bytes_left(&ctx->gb)) < 560) { - av_log(ctx->avctx, AV_LOG_ERROR, "too short input frame (%d bytes)\n", + av_log(ctx->avctx, AV_LOG_ERROR, "Input frame too short (%d bytes).\n", ret); return AVERROR_INVALIDDATA; } @@ -1111,7 +1333,7 @@ static int read_frame_header(SANMVideoContext *ctx, SANMFrameHeader *hdr) hdr->height = bytestream2_get_le32u(&ctx->gb); if (hdr->width != ctx->width || hdr->height != ctx->height) { - av_log(ctx->avctx, AV_LOG_ERROR, "variable size frames are not implemented\n"); + avpriv_report_missing_feature(ctx->avctx, "Variable size frames"); return AVERROR_PATCHWELCOME; } @@ -1133,7 +1355,6 @@ static int read_frame_header(SANMVideoContext *ctx, SANMFrameHeader *hdr) bytestream2_skip(&ctx->gb, 8); // skip pad - av_dlog(ctx->avctx, "subcodec %d\n", hdr->codec); return 0; } @@ -1186,17 +1407,17 @@ static int decode_frame(AVCodecContext *avctx, void *data, pos = bytestream2_tell(&ctx->gb); if (bytestream2_get_bytes_left(&ctx->gb) < size) { - av_log(avctx, AV_LOG_ERROR, "incorrect chunk size %d\n", size); + av_log(avctx, AV_LOG_ERROR, "Incorrect chunk size %d.\n", size); break; } switch (sig) { case MKBETAG('N', 'P', 'A', 'L'): - if (size != 256 * 3) { - av_log(avctx, AV_LOG_ERROR, "incorrect palette block size %d\n", - size); + if (size != PALETTE_SIZE * 3) { + av_log(avctx, AV_LOG_ERROR, + "Incorrect palette block size %d.\n", size); return AVERROR_INVALIDDATA; } - for (i = 0; i < 256; i++) + for (i = 0; i < PALETTE_SIZE; i++) ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb); break; case MKBETAG('F', 'O', 'B', 'J'): @@ -1210,7 +1431,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, uint8_t tmp[3]; int j; - for (i = 0; i < 256; i++) { + for (i = 0; i < PALETTE_SIZE; i++) { for (j = 0; j < 3; j++) { int t = (ctx->pal[i] >> (16 - j * 8)) & 0xFF; tmp[j] = av_clip_uint8((t * 129 + ctx->delta_pal[i * 3 + j]) >> 7); @@ -1218,16 +1439,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, ctx->pal[i] = 0xFFU << 24 | AV_RB24(tmp); } } else { - if (size < 768 * 2 + 4) { - av_log(avctx, AV_LOG_ERROR, "incorrect palette change block size %d\n", + if (size < PALETTE_DELTA * 2 + 4) { + av_log(avctx, AV_LOG_ERROR, "Incorrect palette change block size %d.\n", size); return AVERROR_INVALIDDATA; } bytestream2_skipu(&ctx->gb, 4); - for (i = 0; i < 768; i++) + for (i = 0; i < PALETTE_DELTA; i++) ctx->delta_pal[i] = bytestream2_get_le16u(&ctx->gb); - if (size >= 768 * 5 + 4) { - for (i = 0; i < 256; i++) + if (size >= PALETTE_DELTA * 5 + 4) { + for (i = 0; i < PALETTE_SIZE; i++) ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb); } else { memset(ctx->pal, 0, sizeof(ctx->pal)); @@ -1242,7 +1463,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, break; default: bytestream2_skip(&ctx->gb, size); - av_log(avctx, AV_LOG_DEBUG, "unknown/unsupported chunk %x\n", sig); + av_log(avctx, AV_LOG_DEBUG, "Unknown/unsupported chunk %x.\n", sig); break; } @@ -1273,12 +1494,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, if (header.codec < FF_ARRAY_ELEMS(v1_decoders)) { if ((ret = v1_decoders[header.codec](ctx))) { av_log(avctx, AV_LOG_ERROR, - "subcodec %d: error decoding frame\n", header.codec); + "Subcodec %d: error decoding frame.\n", header.codec); return ret; } } else { - avpriv_request_sample(avctx, "subcodec %d", - header.codec); + avpriv_request_sample(avctx, "Subcodec %d", header.codec); return AVERROR_PATCHWELCOME; } @@ -1288,14 +1508,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, if (ctx->rotate_code) rotate_bufs(ctx, ctx->rotate_code); - *got_frame_ptr = 1; + *got_frame_ptr = 1; return pkt->size; } AVCodec ff_sanm_decoder = { .name = "sanm", - .long_name = NULL_IF_CONFIG_SMALL("LucasArts SMUSH video"), + .long_name = NULL_IF_CONFIG_SMALL("LucasArts SANM/Smush video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_SANM, .priv_data_size = sizeof(SANMVideoContext), diff --git a/libavcodec/sanm_data.h b/libavcodec/sanm_data.h deleted file mode 100644 index 8fccf38ee..000000000 --- a/libavcodec/sanm_data.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * LucasArts Smush video decoder - * Copyright (c) 2006 Cyril Zorin - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_SANM_DATA_H -#define AVCODEC_SANM_DATA_H - -#include - -#define GLYPH_COORD_VECT_SIZE 16 - -static const int8_t glyph4_x[GLYPH_COORD_VECT_SIZE] = - { 0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1 }; -static const int8_t glyph4_y[GLYPH_COORD_VECT_SIZE] = - { 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2 }; -static const int8_t glyph8_x[GLYPH_COORD_VECT_SIZE] = - { 0, 2, 5, 7, 7, 7, 7, 7, 7, 5, 2, 0, 0, 0, 0, 0 }; -static const int8_t glyph8_y[GLYPH_COORD_VECT_SIZE] = - { 0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1 }; - -static const int8_t motion_vectors[256][2] = -{ - { 0, 0}, { -1, -43}, { 6, -43}, { -9, -42}, { 13, -41}, - {-16, -40}, { 19, -39}, {-23, -36}, { 26, -34}, { -2, -33}, - { 4, -33}, {-29, -32}, { -9, -32}, { 11, -31}, {-16, -29}, - { 32, -29}, { 18, -28}, {-34, -26}, {-22, -25}, { -1, -25}, - { 3, -25}, { -7, -24}, { 8, -24}, { 24, -23}, { 36, -23}, - {-12, -22}, { 13, -21}, {-38, -20}, { 0, -20}, {-27, -19}, - { -4, -19}, { 4, -19}, {-17, -18}, { -8, -17}, { 8, -17}, - { 18, -17}, { 28, -17}, { 39, -17}, {-12, -15}, { 12, -15}, - {-21, -14}, { -1, -14}, { 1, -14}, {-41, -13}, { -5, -13}, - { 5, -13}, { 21, -13}, {-31, -12}, {-15, -11}, { -8, -11}, - { 8, -11}, { 15, -11}, { -2, -10}, { 1, -10}, { 31, -10}, - {-23, -9}, {-11, -9}, { -5, -9}, { 4, -9}, { 11, -9}, - { 42, -9}, { 6, -8}, { 24, -8}, {-18, -7}, { -7, -7}, - { -3, -7}, { -1, -7}, { 2, -7}, { 18, -7}, {-43, -6}, - {-13, -6}, { -4, -6}, { 4, -6}, { 8, -6}, {-33, -5}, - { -9, -5}, { -2, -5}, { 0, -5}, { 2, -5}, { 5, -5}, - { 13, -5}, {-25, -4}, { -6, -4}, { -3, -4}, { 3, -4}, - { 9, -4}, {-19, -3}, { -7, -3}, { -4, -3}, { -2, -3}, - { -1, -3}, { 0, -3}, { 1, -3}, { 2, -3}, { 4, -3}, - { 6, -3}, { 33, -3}, {-14, -2}, {-10, -2}, { -5, -2}, - { -3, -2}, { -2, -2}, { -1, -2}, { 0, -2}, { 1, -2}, - { 2, -2}, { 3, -2}, { 5, -2}, { 7, -2}, { 14, -2}, - { 19, -2}, { 25, -2}, { 43, -2}, { -7, -1}, { -3, -1}, - { -2, -1}, { -1, -1}, { 0, -1}, { 1, -1}, { 2, -1}, - { 3, -1}, { 10, -1}, { -5, 0}, { -3, 0}, { -2, 0}, - { -1, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 5, 0}, - { 7, 0}, {-10, 1}, { -7, 1}, { -3, 1}, { -2, 1}, - { -1, 1}, { 0, 1}, { 1, 1}, { 2, 1}, { 3, 1}, - {-43, 2}, {-25, 2}, {-19, 2}, {-14, 2}, { -5, 2}, - { -3, 2}, { -2, 2}, { -1, 2}, { 0, 2}, { 1, 2}, - { 2, 2}, { 3, 2}, { 5, 2}, { 7, 2}, { 10, 2}, - { 14, 2}, {-33, 3}, { -6, 3}, { -4, 3}, { -2, 3}, - { -1, 3}, { 0, 3}, { 1, 3}, { 2, 3}, { 4, 3}, - { 19, 3}, { -9, 4}, { -3, 4}, { 3, 4}, { 7, 4}, - { 25, 4}, {-13, 5}, { -5, 5}, { -2, 5}, { 0, 5}, - { 2, 5}, { 5, 5}, { 9, 5}, { 33, 5}, { -8, 6}, - { -4, 6}, { 4, 6}, { 13, 6}, { 43, 6}, {-18, 7}, - { -2, 7}, { 0, 7}, { 2, 7}, { 7, 7}, { 18, 7}, - {-24, 8}, { -6, 8}, {-42, 9}, {-11, 9}, { -4, 9}, - { 5, 9}, { 11, 9}, { 23, 9}, {-31, 10}, { -1, 10}, - { 2, 10}, {-15, 11}, { -8, 11}, { 8, 11}, { 15, 11}, - { 31, 12}, {-21, 13}, { -5, 13}, { 5, 13}, { 41, 13}, - { -1, 14}, { 1, 14}, { 21, 14}, {-12, 15}, { 12, 15}, - {-39, 17}, {-28, 17}, {-18, 17}, { -8, 17}, { 8, 17}, - { 17, 18}, { -4, 19}, { 0, 19}, { 4, 19}, { 27, 19}, - { 38, 20}, {-13, 21}, { 12, 22}, {-36, 23}, {-24, 23}, - { -8, 24}, { 7, 24}, { -3, 25}, { 1, 25}, { 22, 25}, - { 34, 26}, {-18, 28}, {-32, 29}, { 16, 29}, {-11, 31}, - { 9, 32}, { 29, 32}, { -4, 33}, { 2, 33}, {-26, 34}, - { 23, 36}, {-19, 39}, { 16, 40}, {-13, 41}, { 9, 42}, - { -6, 43}, { 1, 43}, { 0, 0}, { 0, 0}, { 0, 0}, -}; - -static const int8_t c37_mv[] = { - 0, 0, 1, 0, 2, 0, 3, 0, 5, 0, - 8, 0, 13, 0, 21, 0, -1, 0, -2, 0, - -3, 0, -5, 0, -8, 0, -13, 0, -17, 0, - -21, 0, 0, 1, 1, 1, 2, 1, 3, 1, - 5, 1, 8, 1, 13, 1, 21, 1, -1, 1, - -2, 1, -3, 1, -5, 1, -8, 1, -13, 1, - -17, 1, -21, 1, 0, 2, 1, 2, 2, 2, - 3, 2, 5, 2, 8, 2, 13, 2, 21, 2, - -1, 2, -2, 2, -3, 2, -5, 2, -8, 2, - -13, 2, -17, 2, -21, 2, 0, 3, 1, 3, - 2, 3, 3, 3, 5, 3, 8, 3, 13, 3, - 21, 3, -1, 3, -2, 3, -3, 3, -5, 3, - -8, 3, -13, 3, -17, 3, -21, 3, 0, 5, - 1, 5, 2, 5, 3, 5, 5, 5, 8, 5, - 13, 5, 21, 5, -1, 5, -2, 5, -3, 5, - -5, 5, -8, 5, -13, 5, -17, 5, -21, 5, - 0, 8, 1, 8, 2, 8, 3, 8, 5, 8, - 8, 8, 13, 8, 21, 8, -1, 8, -2, 8, - -3, 8, -5, 8, -8, 8, -13, 8, -17, 8, - -21, 8, 0, 13, 1, 13, 2, 13, 3, 13, - 5, 13, 8, 13, 13, 13, 21, 13, -1, 13, - -2, 13, -3, 13, -5, 13, -8, 13, -13, 13, - -17, 13, -21, 13, 0, 21, 1, 21, 2, 21, - 3, 21, 5, 21, 8, 21, 13, 21, 21, 21, - -1, 21, -2, 21, -3, 21, -5, 21, -8, 21, - -13, 21, -17, 21, -21, 21, 0, -1, 1, -1, - 2, -1, 3, -1, 5, -1, 8, -1, 13, -1, - 21, -1, -1, -1, -2, -1, -3, -1, -5, -1, - -8, -1, -13, -1, -17, -1, -21, -1, 0, -2, - 1, -2, 2, -2, 3, -2, 5, -2, 8, -2, - 13, -2, 21, -2, -1, -2, -2, -2, -3, -2, - -5, -2, -8, -2, -13, -2, -17, -2, -21, -2, - 0, -3, 1, -3, 2, -3, 3, -3, 5, -3, - 8, -3, 13, -3, 21, -3, -1, -3, -2, -3, - -3, -3, -5, -3, -8, -3, -13, -3, -17, -3, - -21, -3, 0, -5, 1, -5, 2, -5, 3, -5, - 5, -5, 8, -5, 13, -5, 21, -5, -1, -5, - -2, -5, -3, -5, -5, -5, -8, -5, -13, -5, - -17, -5, -21, -5, 0, -8, 1, -8, 2, -8, - 3, -8, 5, -8, 8, -8, 13, -8, 21, -8, - -1, -8, -2, -8, -3, -8, -5, -8, -8, -8, - -13, -8, -17, -8, -21, -8, 0, -13, 1, -13, - 2, -13, 3, -13, 5, -13, 8, -13, 13, -13, - 21, -13, -1, -13, -2, -13, -3, -13, -5, -13, - -8, -13, -13, -13, -17, -13, -21, -13, 0, -17, - 1, -17, 2, -17, 3, -17, 5, -17, 8, -17, - 13, -17, 21, -17, -1, -17, -2, -17, -3, -17, - -5, -17, -8, -17, -13, -17, -17, -17, -21, -17, - 0, -21, 1, -21, 2, -21, 3, -21, 5, -21, - 8, -21, 13, -21, 21, -21, -1, -21, -2, -21, - -3, -21, -5, -21, -8, -21, -13, -21, -17, -21, - 0, 0, -8, -29, 8, -29, -18, -25, 17, -25, - 0, -23, -6, -22, 6, -22, -13, -19, 12, -19, - 0, -18, 25, -18, -25, -17, -5, -17, 5, -17, - -10, -15, 10, -15, 0, -14, -4, -13, 4, -13, - 19, -13, -19, -12, -8, -11, -2, -11, 0, -11, - 2, -11, 8, -11, -15, -10, -4, -10, 4, -10, - 15, -10, -6, -9, -1, -9, 1, -9, 6, -9, - -29, -8, -11, -8, -8, -8, -3, -8, 3, -8, - 8, -8, 11, -8, 29, -8, -5, -7, -2, -7, - 0, -7, 2, -7, 5, -7, -22, -6, -9, -6, - -6, -6, -3, -6, -1, -6, 1, -6, 3, -6, - 6, -6, 9, -6, 22, -6, -17, -5, -7, -5, - -4, -5, -2, -5, 0, -5, 2, -5, 4, -5, - 7, -5, 17, -5, -13, -4, -10, -4, -5, -4, - -3, -4, -1, -4, 0, -4, 1, -4, 3, -4, - 5, -4, 10, -4, 13, -4, -8, -3, -6, -3, - -4, -3, -3, -3, -2, -3, -1, -3, 0, -3, - 1, -3, 2, -3, 4, -3, 6, -3, 8, -3, - -11, -2, -7, -2, -5, -2, -3, -2, -2, -2, - -1, -2, 0, -2, 1, -2, 2, -2, 3, -2, - 5, -2, 7, -2, 11, -2, -9, -1, -6, -1, - -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, - 1, -1, 2, -1, 3, -1, 4, -1, 6, -1, - 9, -1, -31, 0, -23, 0, -18, 0, -14, 0, - -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, - -2, 0, -1, 0, 0, -31, 1, 0, 2, 0, - 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, - 14, 0, 18, 0, 23, 0, 31, 0, -9, 1, - -6, 1, -4, 1, -3, 1, -2, 1, -1, 1, - 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, - 6, 1, 9, 1, -11, 2, -7, 2, -5, 2, - -3, 2, -2, 2, -1, 2, 0, 2, 1, 2, - 2, 2, 3, 2, 5, 2, 7, 2, 11, 2, - -8, 3, -6, 3, -4, 3, -2, 3, -1, 3, - 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, - 6, 3, 8, 3, -13, 4, -10, 4, -5, 4, - -3, 4, -1, 4, 0, 4, 1, 4, 3, 4, - 5, 4, 10, 4, 13, 4, -17, 5, -7, 5, - -4, 5, -2, 5, 0, 5, 2, 5, 4, 5, - 7, 5, 17, 5, -22, 6, -9, 6, -6, 6, - -3, 6, -1, 6, 1, 6, 3, 6, 6, 6, - 9, 6, 22, 6, -5, 7, -2, 7, 0, 7, - 2, 7, 5, 7, -29, 8, -11, 8, -8, 8, - -3, 8, 3, 8, 8, 8, 11, 8, 29, 8, - -6, 9, -1, 9, 1, 9, 6, 9, -15, 10, - -4, 10, 4, 10, 15, 10, -8, 11, -2, 11, - 0, 11, 2, 11, 8, 11, 19, 12, -19, 13, - -4, 13, 4, 13, 0, 14, -10, 15, 10, 15, - -5, 17, 5, 17, 25, 17, -25, 18, 0, 18, - -12, 19, 13, 19, -6, 22, 6, 22, 0, 23, - -17, 25, 18, 25, -8, 29, 8, 29, 0, 31, - 0, 0, -6, -22, 6, -22, -13, -19, 12, -19, - 0, -18, -5, -17, 5, -17, -10, -15, 10, -15, - 0, -14, -4, -13, 4, -13, 19, -13, -19, -12, - -8, -11, -2, -11, 0, -11, 2, -11, 8, -11, - -15, -10, -4, -10, 4, -10, 15, -10, -6, -9, - -1, -9, 1, -9, 6, -9, -11, -8, -8, -8, - -3, -8, 0, -8, 3, -8, 8, -8, 11, -8, - -5, -7, -2, -7, 0, -7, 2, -7, 5, -7, - -22, -6, -9, -6, -6, -6, -3, -6, -1, -6, - 1, -6, 3, -6, 6, -6, 9, -6, 22, -6, - -17, -5, -7, -5, -4, -5, -2, -5, -1, -5, - 0, -5, 1, -5, 2, -5, 4, -5, 7, -5, - 17, -5, -13, -4, -10, -4, -5, -4, -3, -4, - -2, -4, -1, -4, 0, -4, 1, -4, 2, -4, - 3, -4, 5, -4, 10, -4, 13, -4, -8, -3, - -6, -3, -4, -3, -3, -3, -2, -3, -1, -3, - 0, -3, 1, -3, 2, -3, 3, -3, 4, -3, - 6, -3, 8, -3, -11, -2, -7, -2, -5, -2, - -4, -2, -3, -2, -2, -2, -1, -2, 0, -2, - 1, -2, 2, -2, 3, -2, 4, -2, 5, -2, - 7, -2, 11, -2, -9, -1, -6, -1, -5, -1, - -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, - 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, - 6, -1, 9, -1, -23, 0, -18, 0, -14, 0, - -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, - -2, 0, -1, 0, 0, -23, 1, 0, 2, 0, - 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, - 14, 0, 18, 0, 23, 0, -9, 1, -6, 1, - -5, 1, -4, 1, -3, 1, -2, 1, -1, 1, - 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, - 5, 1, 6, 1, 9, 1, -11, 2, -7, 2, - -5, 2, -4, 2, -3, 2, -2, 2, -1, 2, - 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, - 5, 2, 7, 2, 11, 2, -8, 3, -6, 3, - -4, 3, -3, 3, -2, 3, -1, 3, 0, 3, - 1, 3, 2, 3, 3, 3, 4, 3, 6, 3, - 8, 3, -13, 4, -10, 4, -5, 4, -3, 4, - -2, 4, -1, 4, 0, 4, 1, 4, 2, 4, - 3, 4, 5, 4, 10, 4, 13, 4, -17, 5, - -7, 5, -4, 5, -2, 5, -1, 5, 0, 5, - 1, 5, 2, 5, 4, 5, 7, 5, 17, 5, - -22, 6, -9, 6, -6, 6, -3, 6, -1, 6, - 1, 6, 3, 6, 6, 6, 9, 6, 22, 6, - -5, 7, -2, 7, 0, 7, 2, 7, 5, 7, - -11, 8, -8, 8, -3, 8, 0, 8, 3, 8, - 8, 8, 11, 8, -6, 9, -1, 9, 1, 9, - 6, 9, -15, 10, -4, 10, 4, 10, 15, 10, - -8, 11, -2, 11, 0, 11, 2, 11, 8, 11, - 19, 12, -19, 13, -4, 13, 4, 13, 0, 14, - -10, 15, 10, 15, -5, 17, 5, 17, 0, 18, - -12, 19, 13, 19, -6, 22, 6, 22, 0, 23, -}; -#endif /* AVCODEC_SANM_DATA_H */ diff --git a/libavcodec/sbrdsp.c b/libavcodec/sbrdsp.c index b4d5824e9..e4f053b10 100644 --- a/libavcodec/sbrdsp.c +++ b/libavcodec/sbrdsp.c @@ -110,6 +110,11 @@ static void sbr_qmf_deint_bfly_c(float *v, const float *src0, const float *src1) } } + +#if 0 + /* This code is slower because it multiplies memory accesses. + * It is left for educational purposes and because it may offer + * a better reference for writing arch-specific DSP functions. */ static av_always_inline void autocorrelate(const float x[40][2], float phi[3][2][2], int lag) { @@ -138,14 +143,13 @@ static av_always_inline void autocorrelate(const float x[40][2], static void sbr_autocorrelate_c(const float x[40][2], float phi[3][2][2]) { -#if 0 - /* This code is slower because it multiplies memory accesses. - * It is left for educational purposes and because it may offer - * a better reference for writing arch-specific DSP functions. */ autocorrelate(x, phi, 0); autocorrelate(x, phi, 1); autocorrelate(x, phi, 2); +} #else +static void sbr_autocorrelate_c(const float x[40][2], float phi[3][2][2]) +{ float real_sum2 = x[0][0] * x[2][0] + x[0][1] * x[2][1]; float imag_sum2 = x[0][0] * x[2][1] - x[0][1] * x[2][0]; float real_sum1 = 0.0f, imag_sum1 = 0.0f, real_sum0 = 0.0f; diff --git a/libavcodec/sgi.h b/libavcodec/sgi.h index be17f2e23..5ec891e43 100644 --- a/libavcodec/sgi.h +++ b/libavcodec/sgi.h @@ -1,4 +1,4 @@ - /* +/* * SGI image encoder * Xiaohui Sun * diff --git a/libavcodec/sgidec.c b/libavcodec/sgidec.c index 3ce0f7a85..6f51ec353 100644 --- a/libavcodec/sgidec.c +++ b/libavcodec/sgidec.c @@ -44,8 +44,8 @@ typedef struct SgiState { * @param pixelstride pixel stride of input buffer * @return size of output in bytes, else return error code. */ -static int expand_rle_row(SgiState *s, uint8_t *out_buf, - int len, int pixelstride) +static int expand_rle_row8(SgiState *s, uint8_t *out_buf, + int len, int pixelstride) { unsigned char pixel, count; unsigned char *orig = out_buf; @@ -82,6 +82,46 @@ static int expand_rle_row(SgiState *s, uint8_t *out_buf, return (out_buf - orig) / pixelstride; } +static int expand_rle_row16(SgiState *s, uint16_t *out_buf, + int len, int pixelstride) +{ + unsigned short pixel; + unsigned char count; + unsigned short *orig = out_buf; + uint16_t *out_end = out_buf + len; + + while (out_buf < out_end) { + if (bytestream2_get_bytes_left(&s->g) < 2) + return AVERROR_INVALIDDATA; + pixel = bytestream2_get_be16u(&s->g); + if (!(count = (pixel & 0x7f))) + break; + + /* Check for buffer overflow. */ + if (pixelstride * (count - 1) >= len) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid pixel count.\n"); + return AVERROR_INVALIDDATA; + } + + if (pixel & 0x80) { + while (count--) { + pixel = bytestream2_get_ne16(&s->g); + AV_WN16A(out_buf, pixel); + out_buf += pixelstride; + } + } else { + pixel = bytestream2_get_ne16(&s->g); + + while (count--) { + AV_WN16A(out_buf, pixel); + out_buf += pixelstride; + } + } + } + return (out_buf - orig) / pixelstride; +} + + /** * Read a run length encoded SGI image. * @param out_buf output buffer @@ -95,22 +135,26 @@ static int read_rle_sgi(uint8_t *out_buf, SgiState *s) GetByteContext g_table = s->g; unsigned int y, z; unsigned int start_offset; + int linesize, ret; /* size of RLE offset and length tables */ - if (len * 2 > bytestream2_get_bytes_left(&s->g)) { + if (len * 2 > bytestream2_get_bytes_left(&s->g)) { return AVERROR_INVALIDDATA; } for (z = 0; z < s->depth; z++) { dest_row = out_buf; for (y = 0; y < s->height; y++) { + linesize = s->width * s->depth * s->bytes_per_channel; dest_row -= s->linesize; start_offset = bytestream2_get_be32(&g_table); bytestream2_seek(&s->g, start_offset, SEEK_SET); - if (expand_rle_row(s, dest_row + z, s->width*s->depth, - s->depth) != s->width) { + if (s->bytes_per_channel == 1) + ret = expand_rle_row8(s, dest_row + z, linesize, s->depth); + else + ret = expand_rle_row16(s, (uint16_t *)dest_row + z, linesize, s->depth); + if (ret != s->width) return AVERROR_INVALIDDATA; - } } } return 0; @@ -122,7 +166,7 @@ static int read_rle_sgi(uint8_t *out_buf, SgiState *s) * @param s the current image state * @return 0 if read success, else return error code. */ -static int read_uncompressed_sgi(unsigned char* out_buf, SgiState *s) +static int read_uncompressed_sgi(unsigned char *out_buf, SgiState *s) { int x, y, z; unsigned int offset = s->height * s->width * s->bytes_per_channel; @@ -184,7 +228,7 @@ static int decode_frame(AVCodecContext *avctx, s->height = bytestream2_get_be16u(&s->g); s->depth = bytestream2_get_be16u(&s->g); - if (s->bytes_per_channel != 1 && (s->bytes_per_channel != 2 || rle)) { + if (s->bytes_per_channel != 1 && s->bytes_per_channel != 2) { av_log(avctx, AV_LOG_ERROR, "wrong channel number\n"); return AVERROR_INVALIDDATA; } diff --git a/libavcodec/sgienc.c b/libavcodec/sgienc.c index 0e4f304a2..21026afcc 100644 --- a/libavcodec/sgienc.c +++ b/libavcodec/sgienc.c @@ -31,9 +31,12 @@ static av_cold int encode_init(AVCodecContext *avctx) { if (avctx->width > 65535 || avctx->height > 65535) { + av_log(avctx, AV_LOG_ERROR, + "Unsupported resolution %dx%d.\n", avctx->width, avctx->height); av_log(avctx, AV_LOG_ERROR, "SGI does not support resolutions above 65535x65535\n"); - return -1; + return AVERROR_INVALIDDATA; } + avctx->coded_frame = av_frame_alloc(); if (!avctx->coded_frame) return AVERROR(ENOMEM); @@ -47,7 +50,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame * const p = frame; uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf, *buf; int x, y, z, length, tablesize, ret; - unsigned int width, height, depth, dimension, bytes_per_channel, pixmax, put_be; + unsigned int width, height, depth, dimension; + unsigned int bytes_per_channel, pixmax, put_be; unsigned char *end_buf; avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; @@ -132,14 +136,14 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, memset(buf, 0, SGI_HEADER_SIZE); buf += 80; - /* colormap */ + /* colormap */ bytestream_put_be32(&buf, 0L); /* The rest of the 512 byte header is unused. */ buf += 404; offsettab = buf; - if (avctx->coder_type != FF_CODER_TYPE_RAW) { + if (avctx->coder_type != FF_CODER_TYPE_RAW) { /* Skip RLE offset table. */ buf += tablesize; lengthtab = buf; @@ -180,7 +184,7 @@ 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]); + bytestream_put_byte(&buf, in_buf[x]); } else { if (put_be) { bytestream_put_be16(&buf, ((uint16_t *)in_buf)[x]); @@ -195,7 +199,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, } /* total length */ - pkt->size = buf - pkt->data; + pkt->size = buf - pkt->data; pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; @@ -209,18 +213,18 @@ static av_cold int encode_close(AVCodecContext *avctx) } AVCodec ff_sgi_encoder = { - .name = "sgi", - .long_name = NULL_IF_CONFIG_SMALL("SGI image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SGI, - .init = encode_init, - .encode2 = encode_frame, - .close = encode_close, - .pix_fmts = (const enum AVPixelFormat[]){ + .name = "sgi", + .long_name = NULL_IF_CONFIG_SMALL("SGI image"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SGI, + .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, AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_RGBA64BE, - AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE, - AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE + AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_GRAY8, + AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/sgirledec.c b/libavcodec/sgirledec.c index fd3cc5e78..69d012e8e 100644 --- a/libavcodec/sgirledec.c +++ b/libavcodec/sgirledec.c @@ -1,5 +1,5 @@ /* - * SGI RLE 8-bit decoder + * Silicon Graphics RLE 8-bit video decoder * Copyright (c) 2012 Peter Ross * * This file is part of FFmpeg. @@ -21,9 +21,13 @@ /** * @file - * SGI RLE 8-bit decoder + * Silicon Graphics RLE 8-bit video decoder + * @note Data is packed in rbg323 with rle, contained in mv or mov. + * The algorithm and pixfmt are subtly different from SGI images. */ +#include "libavutil/common.h" + #include "avcodec.h" #include "internal.h" @@ -42,39 +46,44 @@ static av_cold int sgirle_decode_init(AVCodecContext *avctx) } /** - * Convert SGI RGB332 pixel into AV_PIX_FMT_BGR8 - * SGI RGB332 is packed RGB 3:3:2, 8bpp, (msb)3R 2B 3G(lsb) + * Convert SGI RBG323 pixel into AV_PIX_FMT_BGR8 + * SGI RGB data is packed as 8bpp, (msb)3R 2B 3G(lsb) */ -#define RGB332_TO_BGR8(x) (((x << 3) & 0xC0) | ((x << 3) & 0x38) | ((x >> 5) & 7)) - -static av_always_inline void memcpy_rgb332_to_bgr8(uint8_t *dst, const uint8_t *src, int size) +#define RBG323_TO_BGR8(x) ((((x) << 3) & 0xC0) | \ + (((x) << 3) & 0x38) | \ + (((x) >> 5) & 7)) +static av_always_inline +void rbg323_to_bgr8(uint8_t *dst, const uint8_t *src, int size) { int i; for (i = 0; i < size; i++) - dst[i] = RGB332_TO_BGR8(src[i]); + dst[i] = RBG323_TO_BGR8(src[i]); } /** * @param[out] dst Destination buffer - * @param[in] src Source buffer + * @param[in] src Source buffer * @param src_size Source buffer size (bytes) - * @param width Width of destination buffer (pixels) - * @param height Height of destination buffer (pixels) + * @param width Width of destination buffer (pixels) + * @param height Height of destination buffer (pixels) * @param linesize Line size of destination buffer (bytes) + * * @return <0 on error */ -static int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize) +static int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst, + const uint8_t *src, int src_size, + int width, int height, ptrdiff_t linesize) { const uint8_t *src_end = src + src_size; int x = 0, y = 0; -#define INC_XY(n) \ - x += n; \ - if (x >= width) { \ - y++; \ - if (y >= height) \ - return 0; \ - x = 0; \ +#define INC_XY(n) \ + x += n; \ + if (x >= width) { \ + y++; \ + if (y >= height) \ + return 0; \ + x = 0; \ } while (src_end - src >= 2) { @@ -84,9 +93,9 @@ static int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst, const uint8_t *sr int length = FFMIN(v, width - x); if (length <= 0) break; - memset(dst + y*linesize + x, RGB332_TO_BGR8(*src), length); + memset(dst + y * linesize + x, RBG323_TO_BGR8(*src), length); INC_XY(length); - v -= length; + v -= length; } while (v > 0); src++; } else if (v >= 0xC1) { @@ -95,7 +104,7 @@ static int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst, const uint8_t *sr int length = FFMIN3(v, width - x, src_end - src); if (src_end - src < length || length <= 0) break; - memcpy_rgb332_to_bgr8(dst + y*linesize + x, src, length); + rbg323_to_bgr8(dst + y * linesize + x, src, length); INC_XY(length); src += length; v -= length; @@ -108,9 +117,8 @@ static int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst, const uint8_t *sr return 0; } -static int sgirle_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int sgirle_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) { SGIRLEContext *s = avctx->priv_data; int ret; @@ -118,11 +126,12 @@ static int sgirle_decode_frame(AVCodecContext *avctx, if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) return ret; - ret = decode_sgirle8(avctx, s->frame->data[0], avpkt->data, avpkt->size, avctx->width, avctx->height, s->frame->linesize[0]); + ret = decode_sgirle8(avctx, s->frame->data[0], avpkt->data, avpkt->size, + avctx->width, avctx->height, s->frame->linesize[0]); if (ret < 0) return ret; - *got_frame = 1; + *got_frame = 1; if ((ret = av_frame_ref(data, s->frame)) < 0) return ret; @@ -140,7 +149,7 @@ static av_cold int sgirle_decode_end(AVCodecContext *avctx) AVCodec ff_sgirle_decoder = { .name = "sgirle", - .long_name = NULL_IF_CONFIG_SMALL("SGI RLE 8-bit"), + .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), diff --git a/libavcodec/sh4/Makefile b/libavcodec/sh4/Makefile deleted file mode 100644 index 01a573b95..000000000 --- a/libavcodec/sh4/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -OBJS += sh4/dsputil_sh4.o \ - sh4/idct_sh4.o \ diff --git a/libavcodec/sh4/README b/libavcodec/sh4/README new file mode 100644 index 000000000..8dd61fe87 --- /dev/null +++ b/libavcodec/sh4/README @@ -0,0 +1,6 @@ +SH4 optimizations have been removed in +commit d6096a67422534918405abb46dafbbac4608cbc3 +The last revission with the optimizations is cbfc9046e1c7e295b74f252902ae6f255eef4e78 + +If you want to maintain these (or other) SH4 optimizations in ffmpeg, then please +contact ffmpeg-devel@ffmpeg.org diff --git a/libavcodec/sh4/dsputil_sh4.c b/libavcodec/sh4/dsputil_sh4.c deleted file mode 100644 index 82b75ae6c..000000000 --- a/libavcodec/sh4/dsputil_sh4.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * sh4 dsputil - * - * Copyright (c) 2003 BERO - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/attributes.h" -#include "libavcodec/avcodec.h" -#include "libavcodec/dsputil.h" -#include "dsputil_sh4.h" -#include "sh4.h" - -static void memzero_align8(void *dst,size_t size) -{ - int fpscr; - fp_single_enter(fpscr); - dst = (char *)dst + size; - size /= 32; - __asm__ volatile ( - " fldi0 fr0\n" - " fldi0 fr1\n" - " fschg\n" // double - "1: \n" \ - " dt %1\n" - " fmov dr0,@-%0\n" - " fmov dr0,@-%0\n" - " fmov dr0,@-%0\n" - " bf.s 1b\n" - " fmov dr0,@-%0\n" - " fschg" //back to single - : "+r"(dst),"+r"(size) :: "memory" ); - fp_single_leave(fpscr); -} - -static void clear_blocks_sh4(int16_t *blocks) -{ - memzero_align8(blocks,sizeof(int16_t)*6*64); -} - -static void idct_put(uint8_t *dest, int line_size, int16_t *block) -{ - int i; - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; - ff_idct_sh4(block); - for(i=0;i<8;i++) { - dest[0] = cm[block[0]]; - dest[1] = cm[block[1]]; - dest[2] = cm[block[2]]; - dest[3] = cm[block[3]]; - dest[4] = cm[block[4]]; - dest[5] = cm[block[5]]; - dest[6] = cm[block[6]]; - dest[7] = cm[block[7]]; - dest+=line_size; - block+=8; - } -} -static void idct_add(uint8_t *dest, int line_size, int16_t *block) -{ - int i; - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; - ff_idct_sh4(block); - for(i=0;i<8;i++) { - dest[0] = cm[dest[0]+block[0]]; - dest[1] = cm[dest[1]+block[1]]; - dest[2] = cm[dest[2]+block[2]]; - dest[3] = cm[dest[3]+block[3]]; - dest[4] = cm[dest[4]+block[4]]; - dest[5] = cm[dest[5]+block[5]]; - dest[6] = cm[dest[6]+block[6]]; - dest[7] = cm[dest[7]+block[7]]; - dest+=line_size; - block+=8; - } -} - -av_cold void ff_dsputil_init_sh4(DSPContext *c, AVCodecContext *avctx) -{ - const int idct_algo= avctx->idct_algo; - const int high_bit_depth = avctx->bits_per_raw_sample > 8; - - if (!high_bit_depth) - c->clear_blocks = clear_blocks_sh4; - if (avctx->bits_per_raw_sample <= 8 && - (idct_algo==FF_IDCT_AUTO || idct_algo==FF_IDCT_SH4)) { - c->idct_put = idct_put; - c->idct_add = idct_add; - c->idct = ff_idct_sh4; - c->idct_permutation_type= FF_NO_IDCT_PERM; - } -} diff --git a/libavcodec/sh4/idct_sh4.c b/libavcodec/sh4/idct_sh4.c deleted file mode 100644 index d4e871109..000000000 --- a/libavcodec/sh4/idct_sh4.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * idct for sh4 - * - * Copyright (c) 2001-2003 BERO - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "dsputil_sh4.h" -#include "sh4.h" - -#define c1 1.38703984532214752434 /* sqrt(2)*cos(1*pi/16) */ -#define c2 1.30656296487637657577 /* sqrt(2)*cos(2*pi/16) */ -#define c3 1.17587560241935884520 /* sqrt(2)*cos(3*pi/16) */ -#define c4 1.00000000000000000000 /* sqrt(2)*cos(4*pi/16) */ -#define c5 0.78569495838710234903 /* sqrt(2)*cos(5*pi/16) */ -#define c6 0.54119610014619712324 /* sqrt(2)*cos(6*pi/16) */ -#define c7 0.27589937928294311353 /* sqrt(2)*cos(7*pi/16) */ - -static const float even_table[] __attribute__ ((aligned(8))) = { - c4, c4, c4, c4, - c2, c6,-c6,-c2, - c4,-c4,-c4, c4, - c6,-c2, c2,-c6 -}; - -static const float odd_table[] __attribute__ ((aligned(8))) = { - c1, c3, c5, c7, - c3,-c7,-c1,-c5, - c5,-c1, c7, c3, - c7,-c5, c3,-c1 -}; - -#undef c1 -#undef c2 -#undef c3 -#undef c4 -#undef c5 -#undef c6 -#undef c7 - -#define load_matrix(table) \ - do { \ - const float *t = table; \ - __asm__ volatile( \ - " fschg\n" \ - " fmov @%0+,xd0\n" \ - " fmov @%0+,xd2\n" \ - " fmov @%0+,xd4\n" \ - " fmov @%0+,xd6\n" \ - " fmov @%0+,xd8\n" \ - " fmov @%0+,xd10\n" \ - " fmov @%0+,xd12\n" \ - " fmov @%0+,xd14\n" \ - " fschg\n" \ - : "+r"(t) \ - ); \ - } while (0) - -#define ftrv() \ - __asm__ volatile("ftrv xmtrx,fv0" \ - : "+f"(fr0),"+f"(fr1),"+f"(fr2),"+f"(fr3)); - -#define DEFREG \ - register float fr0 __asm__("fr0"); \ - register float fr1 __asm__("fr1"); \ - register float fr2 __asm__("fr2"); \ - register float fr3 __asm__("fr3") - -#define DESCALE(x,n) (x)*(1.0f/(1<<(n))) - -/* this code work worse on gcc cvs. 3.2.3 work fine */ - - -//optimized - -void ff_idct_sh4(int16_t *block) -{ - DEFREG; - - int i; - float tblock[8*8],*fblock; - int ofs1,ofs2,ofs3; - int fpscr; - - fp_single_enter(fpscr); - - /* row */ - - /* even part */ - load_matrix(even_table); - - fblock = tblock+4; - i = 8; - do { - fr0 = block[0]; - fr1 = block[2]; - fr2 = block[4]; - fr3 = block[6]; - block+=8; - ftrv(); - *--fblock = fr3; - *--fblock = fr2; - *--fblock = fr1; - *--fblock = fr0; - fblock+=8+4; - } while(--i); - block-=8*8; - fblock-=8*8+4; - - load_matrix(odd_table); - - i = 8; - - do { - float t0,t1,t2,t3; - fr0 = block[1]; - fr1 = block[3]; - fr2 = block[5]; - fr3 = block[7]; - block+=8; - ftrv(); - t0 = *fblock++; - t1 = *fblock++; - t2 = *fblock++; - t3 = *fblock++; - fblock+=4; - *--fblock = t0 - fr0; - *--fblock = t1 - fr1; - *--fblock = t2 - fr2; - *--fblock = t3 - fr3; - *--fblock = t3 + fr3; - *--fblock = t2 + fr2; - *--fblock = t1 + fr1; - *--fblock = t0 + fr0; - fblock+=8; - } while(--i); - block-=8*8; - fblock-=8*8; - - /* col */ - - /* even part */ - load_matrix(even_table); - - ofs1 = sizeof(float)*2*8; - ofs2 = sizeof(float)*4*8; - ofs3 = sizeof(float)*6*8; - - i = 8; - -#define OA(fblock,ofs) *(float*)((char*)fblock + ofs) - - do { - fr0 = OA(fblock, 0); - fr1 = OA(fblock,ofs1); - fr2 = OA(fblock,ofs2); - fr3 = OA(fblock,ofs3); - ftrv(); - OA(fblock,0 ) = fr0; - OA(fblock,ofs1) = fr1; - OA(fblock,ofs2) = fr2; - OA(fblock,ofs3) = fr3; - fblock++; - } while(--i); - fblock-=8; - - load_matrix(odd_table); - - i=8; - do { - float t0,t1,t2,t3; - t0 = OA(fblock, 0); /* [8*0] */ - t1 = OA(fblock,ofs1); /* [8*2] */ - t2 = OA(fblock,ofs2); /* [8*4] */ - t3 = OA(fblock,ofs3); /* [8*6] */ - fblock+=8; - fr0 = OA(fblock, 0); /* [8*1] */ - fr1 = OA(fblock,ofs1); /* [8*3] */ - fr2 = OA(fblock,ofs2); /* [8*5] */ - fr3 = OA(fblock,ofs3); /* [8*7] */ - fblock+=-8+1; - ftrv(); - block[8*0] = DESCALE(t0 + fr0,3); - block[8*7] = DESCALE(t0 - fr0,3); - block[8*1] = DESCALE(t1 + fr1,3); - block[8*6] = DESCALE(t1 - fr1,3); - block[8*2] = DESCALE(t2 + fr2,3); - block[8*5] = DESCALE(t2 - fr2,3); - block[8*3] = DESCALE(t3 + fr3,3); - block[8*4] = DESCALE(t3 - fr3,3); - block++; - } while(--i); - - fp_single_leave(fpscr); -} diff --git a/libavcodec/sh4/sh4.h b/libavcodec/sh4/sh4.h deleted file mode 100644 index 5d46540cb..000000000 --- a/libavcodec/sh4/sh4.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2008 Mans Rullgard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_SH4_SH4_H -#define AVCODEC_SH4_SH4_H - -#ifdef __SH4__ -# define fp_single_enter(fpscr) \ - do { \ - __asm__ volatile ("sts fpscr, %0 \n\t" \ - "and %1, %0 \n\t" \ - "lds %0, fpscr \n\t" \ - : "=&r"(fpscr) : "r"(~(1<<19))); \ - } while (0) - -# define fp_single_leave(fpscr) \ - do { \ - __asm__ volatile ("or %1, %0 \n\t" \ - "lds %0, fpscr \n\t" \ - : "+r"(fpscr) : "r"(1<<19)); \ - } while (0) -#else -# define fp_single_enter(fpscr) ((void)fpscr) -# define fp_single_leave(fpscr) -#endif - -#endif /* AVCODEC_SH4_SH4_H */ diff --git a/libavcodec/shorten.c b/libavcodec/shorten.c index 8b91ed364..5c4bf816b 100644 --- a/libavcodec/shorten.c +++ b/libavcodec/shorten.c @@ -505,9 +505,16 @@ static int shorten_decode_frame(AVCodecContext *avctx, void *data, while (len--) get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE); break; - case FN_BITSHIFT: - s->bitshift = get_ur_golomb_shorten(&s->gb, BITSHIFTSIZE); + case FN_BITSHIFT: { + unsigned bitshift = get_ur_golomb_shorten(&s->gb, BITSHIFTSIZE); + if (bitshift > 31) { + av_log(avctx, AV_LOG_ERROR, "bitshift %d is invalid\n", + bitshift); + return AVERROR_PATCHWELCOME; + } + s->bitshift = bitshift; break; + } case FN_BLOCKSIZE: { unsigned blocksize = get_uint(s, av_log2(s->blocksize)); if (blocksize > s->blocksize) { diff --git a/libavcodec/simple_idct_template.c b/libavcodec/simple_idct_template.c index ac04923d9..789db8d0a 100644 --- a/libavcodec/simple_idct_template.c +++ b/libavcodec/simple_idct_template.c @@ -30,6 +30,8 @@ written by Aaron Holtzman ) */ +#include "simple_idct.h" + #include "bit_depth_template.c" #undef W1 @@ -108,12 +110,12 @@ static inline void FUNC(idctRowCondDC)(int16_t *row, int extra_shift) if (((((uint64_t *)row)[0] & ~ROW0_MASK) | ((uint64_t *)row)[1]) == 0) { uint64_t temp; if (DC_SHIFT - extra_shift >= 0) { - temp = (row[0] << (DC_SHIFT - extra_shift)) & 0xffff; + temp = (row[0] * (1 << (DC_SHIFT - extra_shift))) & 0xffff; } else { temp = ((row[0] + (1<<(extra_shift - DC_SHIFT-1))) >> (extra_shift - DC_SHIFT)) & 0xffff; } - temp += temp << 16; - temp += temp << 32; + temp += temp * (1 << 16); + temp += temp * ((uint64_t) 1 << 32); ((uint64_t *)row)[0] = temp; ((uint64_t *)row)[1] = temp; return; @@ -125,11 +127,11 @@ static inline void FUNC(idctRowCondDC)(int16_t *row, int extra_shift) 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] + (1<<(extra_shift - DC_SHIFT-1))) >> (extra_shift - DC_SHIFT)) & 0xffff; } - temp += temp << 16; + temp += temp * (1 << 16); ((uint32_t*)row)[0]=((uint32_t*)row)[1] = ((uint32_t*)row)[2]=((uint32_t*)row)[3] = temp; return; diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index cd342b9d8..644beb34d 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -271,7 +271,7 @@ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int huff.length = ((size + 3) >> 2) + 4; huff.maxlength = 0; huff.current = 0; - huff.values = av_mallocz(huff.length * sizeof(int)); + huff.values = av_mallocz_array(huff.length, sizeof(int)); if (!huff.values) { err = AVERROR(ENOMEM); goto error; diff --git a/libavcodec/smvjpegdec.c b/libavcodec/smvjpegdec.c index f883ecf80..69327cd79 100644 --- a/libavcodec/smvjpegdec.c +++ b/libavcodec/smvjpegdec.c @@ -153,8 +153,11 @@ static int smvjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_siz /* We shouldn't get here if frames_per_jpeg <= 0 because this was rejected in init */ - avcodec_set_dimensions(avctx, mjpeg_data->width, - mjpeg_data->height / s->frames_per_jpeg); + ret = ff_set_dimensions(avctx, mjpeg_data->width, mjpeg_data->height / s->frames_per_jpeg); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Failed to set dimensions\n"); + return ret; + } if (*data_size) { s->picture[1]->extended_data = NULL; @@ -177,13 +180,14 @@ static av_cold int smvjpeg_decode_end(AVCodecContext *avctx) { SMVJpegDecodeContext *s = avctx->priv_data; MJpegDecodeContext *jpg = &s->jpg; + int ret; jpg->picture_ptr = NULL; av_frame_free(&s->picture[0]); av_frame_free(&s->picture[1]); - ff_codec_close_recursive(s->avctx); + ret = avcodec_close(s->avctx); av_freep(&s->avctx); - return 0; + return ret; } static const AVClass smvjpegdec_class = { diff --git a/libavcodec/snow.c b/libavcodec/snow.c index c645b120f..711d1a4f0 100644 --- a/libavcodec/snow.c +++ b/libavcodec/snow.c @@ -66,6 +66,26 @@ void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_ } } +int ff_snow_get_buffer(SnowContext *s, AVFrame *frame) +{ + int ret, i; + + frame->width = s->avctx->width + 2 * EDGE_WIDTH; + frame->height = s->avctx->height + 2 * EDGE_WIDTH; + if ((ret = ff_get_buffer(s->avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + for (i = 0; frame->data[i]; i++) { + int offset = (EDGE_WIDTH >> (i ? s->chroma_v_shift : 0)) * + frame->linesize[i] + + (EDGE_WIDTH >> (i ? s->chroma_h_shift : 0)); + frame->data[i] += offset; + } + frame->width = s->avctx->width; + frame->height = s->avctx->height; + + return 0; +} + void ff_snow_reset_contexts(SnowContext *s){ //FIXME better initial contexts int plane_index, level, orientation; @@ -88,7 +108,7 @@ int ff_snow_alloc_blocks(SnowContext *s){ s->b_height= h; av_free(s->block); - s->block= av_mallocz(w * h * sizeof(BlockNode) << (s->block_max_depth*2)); + s->block= av_mallocz_array(w * h, sizeof(BlockNode) << (s->block_max_depth*2)); if (!s->block) return AVERROR(ENOMEM); @@ -358,9 +378,13 @@ void ff_snow_pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, ptrdiff_t st av_assert2(s->chroma_h_shift == s->chroma_v_shift); // only one mv_scale - av_assert2(b_w>1 && b_h>1); av_assert2((tab_index>=0 && tab_index<4) || b_w==32); - if((dx&3) || (dy&3) || !(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h) || (b_w&(b_w-1)) || !s->plane[plane_index].fast_mc ) + if( (dx&3) || (dy&3) + || !(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h) + || (b_w&(b_w-1)) + || b_w == 1 + || b_h == 1 + || !s->plane[plane_index].fast_mc ) mc_block(&s->plane[plane_index], dst, src, stride, b_w, b_h, dx, dy); else if(b_w==32){ int y; @@ -409,13 +433,14 @@ av_cold int ff_snow_common_init(AVCodecContext *avctx){ ff_videodsp_init(&s->vdsp, 8); ff_dwt_init(&s->dwt); ff_h264qpel_init(&s->h264qpel, 8); + ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx); #define mcf(dx,dy)\ - s->dsp.put_qpel_pixels_tab [0][dy+dx/4]=\ - s->dsp.put_no_rnd_qpel_pixels_tab[0][dy+dx/4]=\ + s->qdsp.put_qpel_pixels_tab [0][dy+dx/4]=\ + s->qdsp.put_no_rnd_qpel_pixels_tab[0][dy+dx/4]=\ s->h264qpel.put_h264_qpel_pixels_tab[0][dy+dx/4];\ - s->dsp.put_qpel_pixels_tab [1][dy+dx/4]=\ - s->dsp.put_no_rnd_qpel_pixels_tab[1][dy+dx/4]=\ + s->qdsp.put_qpel_pixels_tab [1][dy+dx/4]=\ + s->qdsp.put_no_rnd_qpel_pixels_tab[1][dy+dx/4]=\ s->h264qpel.put_h264_qpel_pixels_tab[1][dy+dx/4]; mcf( 0, 0) @@ -455,11 +480,11 @@ av_cold int ff_snow_common_init(AVCodecContext *avctx){ width= s->avctx->width; height= s->avctx->height; - FF_ALLOCZ_OR_GOTO(avctx, s->spatial_idwt_buffer, width * height * sizeof(IDWTELEM), fail); - FF_ALLOCZ_OR_GOTO(avctx, s->spatial_dwt_buffer, width * height * sizeof(DWTELEM), fail); //FIXME this does not belong here - FF_ALLOCZ_OR_GOTO(avctx, s->temp_dwt_buffer, width * sizeof(DWTELEM), fail); - FF_ALLOCZ_OR_GOTO(avctx, s->temp_idwt_buffer, width * sizeof(IDWTELEM), fail); - FF_ALLOC_OR_GOTO(avctx, s->run_buffer, ((width + 1) >> 1) * ((height + 1) >> 1) * sizeof(*s->run_buffer), fail); + FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->spatial_idwt_buffer, width, height * sizeof(IDWTELEM), fail); + FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->spatial_dwt_buffer, width, height * sizeof(DWTELEM), fail); //FIXME this does not belong here + FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->temp_dwt_buffer, width, sizeof(DWTELEM), fail); + FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->temp_idwt_buffer, width, sizeof(IDWTELEM), fail); + FF_ALLOC_ARRAY_OR_GOTO(avctx, s->run_buffer, ((width + 1) >> 1), ((height + 1) >> 1) * sizeof(*s->run_buffer), fail); for(i=0; iavctx, s->mconly_picture, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; - FF_ALLOCZ_OR_GOTO(avctx, s->scratchbuf, FFMAX(s->mconly_picture->linesize[0], 2*avctx->width+256)*7*MB_SIZE, fail); + FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->scratchbuf, FFMAX(s->mconly_picture->linesize[0], 2*avctx->width+256), 7*MB_SIZE, fail); emu_buf_size = FFMAX(s->mconly_picture->linesize[0], 2*avctx->width+256) * (2 * MB_SIZE + HTAPS_MAX - 1); FF_ALLOC_OR_GOTO(avctx, s->emu_edge_buffer, emu_buf_size, fail); } @@ -537,7 +562,7 @@ int ff_snow_common_init_after_header(AVCodecContext *avctx) { b->parent= &s->plane[plane_index].band[level-1][orientation]; //FIXME avoid this realloc av_freep(&b->x_coeff); - b->x_coeff=av_mallocz(((b->width+1) * b->height+1)*sizeof(x_and_coeff)); + b->x_coeff=av_mallocz_array(((b->width+1) * b->height+1), sizeof(x_and_coeff)); if (!b->x_coeff) goto fail; } @@ -618,16 +643,16 @@ int ff_snow_frame_start(SnowContext *s){ int h= s->avctx->height; if (s->current_picture->data[0] && !(s->avctx->flags&CODEC_FLAG_EMU_EDGE)) { - s->dsp.draw_edges(s->current_picture->data[0], - s->current_picture->linesize[0], w , h , - EDGE_WIDTH , EDGE_WIDTH , EDGE_TOP | EDGE_BOTTOM); + s->mpvencdsp.draw_edges(s->current_picture->data[0], + s->current_picture->linesize[0], w , h , + EDGE_WIDTH , EDGE_WIDTH , EDGE_TOP | EDGE_BOTTOM); if (s->current_picture->data[2]) { - s->dsp.draw_edges(s->current_picture->data[1], - s->current_picture->linesize[1], w>>s->chroma_h_shift, h>>s->chroma_v_shift, - EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM); - s->dsp.draw_edges(s->current_picture->data[2], - s->current_picture->linesize[2], w>>s->chroma_h_shift, h>>s->chroma_v_shift, - EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM); + s->mpvencdsp.draw_edges(s->current_picture->data[1], + s->current_picture->linesize[1], w>>s->chroma_h_shift, h>>s->chroma_v_shift, + EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM); + s->mpvencdsp.draw_edges(s->current_picture->data[2], + s->current_picture->linesize[2], w>>s->chroma_h_shift, h>>s->chroma_v_shift, + EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM); } } @@ -657,8 +682,7 @@ int ff_snow_frame_start(SnowContext *s){ return -1; } } - - if ((ret = ff_get_buffer(s->avctx, s->current_picture, AV_GET_BUFFER_FLAG_REF)) < 0) + if ((ret = ff_snow_get_buffer(s, s->current_picture)) < 0) return ret; s->current_picture->key_frame= s->keyframe; diff --git a/libavcodec/snow.h b/libavcodec/snow.h index 60b00623a..2cda5b323 100644 --- a/libavcodec/snow.h +++ b/libavcodec/snow.h @@ -24,6 +24,7 @@ #include "dsputil.h" #include "hpeldsp.h" +#include "qpeldsp.h" #include "snow_dwt.h" #include "rangecoder.h" @@ -111,8 +112,10 @@ typedef struct SnowContext{ RangeCoder c; DSPContext dsp; HpelDSPContext hdsp; + QpelDSPContext qdsp; VideoDSPContext vdsp; H264QpelContext h264qpel; + MpegvideoEncDSPContext mpvencdsp; SnowDWTContext dwt; AVFrame *new_picture; AVFrame *input_picture; ///< new_picture with the internal linesizes @@ -230,6 +233,7 @@ int ff_snow_frame_start(SnowContext *s); void ff_snow_pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, ptrdiff_t stride, int sx, int sy, int b_w, int b_h, BlockNode *block, int plane_index, int w, int h); +int ff_snow_get_buffer(SnowContext *s, AVFrame *frame); /* common inline functions */ //XXX doublecheck all of them should stay inlined diff --git a/libavcodec/snow_dwt.c b/libavcodec/snow_dwt.c index 28edf6aaf..cd94c1330 100644 --- a/libavcodec/snow_dwt.c +++ b/libavcodec/snow_dwt.c @@ -35,17 +35,17 @@ int ff_slice_buffer_init(slice_buffer *buf, int line_count, buf->line_count = line_count; buf->line_width = line_width; buf->data_count = max_allocated_lines; - buf->line = av_mallocz(sizeof(IDWTELEM *) * line_count); + buf->line = av_mallocz_array(line_count, sizeof(IDWTELEM *)); if (!buf->line) return AVERROR(ENOMEM); - buf->data_stack = av_malloc(sizeof(IDWTELEM *) * max_allocated_lines); + buf->data_stack = av_malloc_array(max_allocated_lines, sizeof(IDWTELEM *)); if (!buf->data_stack) { av_freep(&buf->line); return AVERROR(ENOMEM); } for (i = 0; i < max_allocated_lines; i++) { - buf->data_stack[i] = av_malloc(sizeof(IDWTELEM) * line_width); + buf->data_stack[i] = av_malloc_array(line_width, sizeof(IDWTELEM)); if (!buf->data_stack[i]) { for (i--; i >=0; i--) av_freep(&buf->data_stack[i]); @@ -745,7 +745,7 @@ void ff_spatial_idwt(IDWTELEM *buffer, IDWTELEM *temp, int width, int height, decomposition_count, y); } -static inline int w_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, +static inline int w_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int w, int h, int type) { int s, i, j; @@ -814,32 +814,32 @@ static inline int w_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, return s >> 9; } -static int w53_8_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +static int w53_8_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) { return w_c(v, pix1, pix2, line_size, 8, h, 1); } -static int w97_8_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +static int w97_8_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) { return w_c(v, pix1, pix2, line_size, 8, h, 0); } -static int w53_16_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +static int w53_16_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) { return w_c(v, pix1, pix2, line_size, 16, h, 1); } -static int w97_16_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +static int w97_16_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) { return w_c(v, pix1, pix2, line_size, 16, h, 0); } -int ff_w53_32_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +int ff_w53_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) { return w_c(v, pix1, pix2, line_size, 32, h, 1); } -int ff_w97_32_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +int ff_w97_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) { return w_c(v, pix1, pix2, line_size, 32, h, 0); } diff --git a/libavcodec/snow_dwt.h b/libavcodec/snow_dwt.h index 0806b389e..e92918967 100644 --- a/libavcodec/snow_dwt.h +++ b/libavcodec/snow_dwt.h @@ -105,8 +105,8 @@ void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, int src_y, int src_stride, slice_buffer *sb, int add, uint8_t *dst8); -int ff_w53_32_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); -int ff_w97_32_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); +int ff_w53_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); +int ff_w97_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); void ff_spatial_dwt(int *buffer, int *temp, int width, int height, int stride, int type, int decomposition_count); diff --git a/libavcodec/snowdec.c b/libavcodec/snowdec.c index 79cf5a185..7287a2e64 100644 --- a/libavcodec/snowdec.c +++ b/libavcodec/snowdec.c @@ -262,7 +262,7 @@ static void decode_qlogs(SnowContext *s){ tmp= get_symbol(&s->c, s->header_state, 0);\ if(!(check)){\ av_log(s->avctx, AV_LOG_ERROR, "Error " #dst " is %d\n", tmp);\ - return -1;\ + return AVERROR_INVALIDDATA;\ }\ dst= tmp; @@ -332,7 +332,7 @@ static int decode_header(SnowContext *s){ p->diag_mc= get_rac(&s->c, s->header_state); htaps= get_symbol(&s->c, s->header_state, 0)*2 + 2; if((unsigned)htaps > HTAPS_MAX || htaps==0) - return -1; + return AVERROR_INVALIDDATA; p->htaps= htaps; for(i= htaps/2; i; i--){ p->hcoeff[i]= get_symbol(&s->c, s->header_state, 0) * (1-2*(i&1)); @@ -353,12 +353,12 @@ static int decode_header(SnowContext *s){ s->spatial_decomposition_type+= get_symbol(&s->c, s->header_state, 1); if(s->spatial_decomposition_type > 1U){ av_log(s->avctx, AV_LOG_ERROR, "spatial_decomposition_type %d not supported\n", s->spatial_decomposition_type); - return -1; + return AVERROR_INVALIDDATA; } if(FFMIN(s->avctx-> width>>s->chroma_h_shift, s->avctx->height>>s->chroma_v_shift) >> (s->spatial_decomposition_count-1) <= 1){ av_log(s->avctx, AV_LOG_ERROR, "spatial_decomposition_count %d too large for size\n", s->spatial_decomposition_count); - return -1; + return AVERROR_INVALIDDATA; } @@ -369,7 +369,7 @@ static int decode_header(SnowContext *s){ if(s->block_max_depth > 1 || s->block_max_depth < 0){ av_log(s->avctx, AV_LOG_ERROR, "block_max_depth= %d is too large\n", s->block_max_depth); s->block_max_depth= 0; - return -1; + return AVERROR_INVALIDDATA; } return 0; @@ -418,8 +418,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, ff_build_rac_states(c, 0.05*(1LL<<32), 256-8); s->current_picture->pict_type= AV_PICTURE_TYPE_I; //FIXME I vs. P - if(decode_header(s)<0) - return -1; + if ((res = decode_header(s)) < 0) + return res; if ((res=ff_snow_common_init_after_header(avctx)) < 0) return res; @@ -441,11 +441,17 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, ff_snow_alloc_blocks(s); - if(ff_snow_frame_start(s) < 0) - return -1; + if((res = ff_snow_frame_start(s)) < 0) + return res; //keyframe flag duplication mess FIXME if(avctx->debug&FF_DEBUG_PICT_INFO) - av_log(avctx, AV_LOG_ERROR, "keyframe:%d qlog:%d\n", s->keyframe, s->qlog); + av_log(avctx, AV_LOG_ERROR, + "keyframe:%d qlog:%d qbias: %d mvscale: %d " + "decomposition_type:%d decomposition_count:%d\n", + s->keyframe, s->qlog, s->qbias, s->mv_scale, + s->spatial_decomposition_type, + s->spatial_decomposition_count + ); if ((res = decode_blocks(s)) < 0) return res; diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index ed331de34..cb8382154 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -37,12 +37,7 @@ static av_cold int encode_init(AVCodecContext *avctx) { SnowContext *s = avctx->priv_data; int plane_index, ret; - - if(avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){ - av_log(avctx, AV_LOG_ERROR, "This codec is under development, files encoded with it may not be decodable with future versions!!!\n" - "Use vstrict=-2 / -strict -2 to use it anyway.\n"); - return -1; - } + int i; if(avctx->prediction_method == DWT_97 && (avctx->flags & CODEC_FLAG_QSCALE) @@ -78,7 +73,7 @@ static av_cold int encode_init(AVCodecContext *avctx) s->m.bit_rate= avctx->bit_rate; s->m.me.temp = - s->m.me.scratchpad= av_mallocz((avctx->width+64)*2*16*2*sizeof(uint8_t)); + s->m.me.scratchpad= av_mallocz_array((avctx->width+64), 2*16*2*sizeof(uint8_t)); s->m.me.map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t)); s->m.me.score_map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t)); s->m.obmc_scratchpad= av_mallocz(MB_SIZE*MB_SIZE*12*sizeof(uint32_t)); @@ -130,15 +125,15 @@ static av_cold int encode_init(AVCodecContext *avctx) s->input_picture = av_frame_alloc(); if (!s->input_picture) return AVERROR(ENOMEM); - if ((ret = ff_get_buffer(s->avctx, s->input_picture, AV_GET_BUFFER_FLAG_REF)) < 0) + + if ((ret = ff_snow_get_buffer(s, s->input_picture)) < 0) return ret; if(s->avctx->me_method == ME_ITER){ - int i; int size= s->b_width * s->b_height << 2*s->block_max_depth; for(i=0; imax_ref_frames; i++){ - s->ref_mvs[i]= av_mallocz(size*sizeof(int16_t[2])); - s->ref_scores[i]= av_mallocz(size*sizeof(uint32_t)); + s->ref_mvs[i]= av_mallocz_array(size, sizeof(int16_t[2])); + s->ref_scores[i]= av_mallocz_array(size, sizeof(uint32_t)); if (!s->ref_mvs[i] || !s->ref_scores[i]) return AVERROR(ENOMEM); } @@ -167,7 +162,7 @@ static int pix_sum(uint8_t * pix, int line_size, int w, int h) static int pix_norm1(uint8_t * pix, int line_size, int w) { int s, i, j; - uint32_t *sq = ff_squareTbl + 256; + uint32_t *sq = ff_square_tab + 256; s = 0; for (i = 0; i < w; i++) { @@ -1549,7 +1544,7 @@ static void calculate_visual_weight(SnowContext *s, Plane *p){ } static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, - AVFrame *pict, int *got_packet) + const AVFrame *pict, int *got_packet) { SnowContext *s = avctx->priv_data; RangeCoder * const c= &s->c; @@ -1573,10 +1568,10 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, memcpy(&s->input_picture->data[i][y * s->input_picture->linesize[i]], &pict->data[i][y * pict->linesize[i]], width>>hshift); - s->dsp.draw_edges(s->input_picture->data[i], s->input_picture->linesize[i], - width >> hshift, height >> vshift, - EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, - EDGE_TOP | EDGE_BOTTOM); + s->mpvencdsp.draw_edges(s->input_picture->data[i], s->input_picture->linesize[i], + width >> hshift, height >> vshift, + EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, + EDGE_TOP | EDGE_BOTTOM); } emms_c(); @@ -1611,8 +1606,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, avctx->coded_frame= s->current_picture; s->m.current_picture_ptr= &s->m.current_picture; - s->m.last_picture.f.pts = s->m.current_picture.f.pts; - s->m.current_picture.f.pts = pict->pts; + s->m.current_picture.f = s->current_picture; + s->m.current_picture.f->pts = pict->pts; if(pic->pict_type == AV_PICTURE_TYPE_P){ int block_width = (width +15)>>4; int block_height= (height+15)>>4; @@ -1622,14 +1617,10 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, av_assert0(s->last_picture[0]->data[0]); s->m.avctx= s->avctx; - s->m.current_picture.f.data[0] = s->current_picture->data[0]; - s->m. last_picture.f.data[0] = s->last_picture[0]->data[0]; - s->m. new_picture.f.data[0] = s-> input_picture->data[0]; + s->m. last_picture.f = s->last_picture[0]; + s->m. new_picture.f = s->input_picture; s->m. last_picture_ptr= &s->m. last_picture; - s->m.linesize= - s->m. last_picture.f.linesize[0] = - s->m. new_picture.f.linesize[0] = - s->m.current_picture.f.linesize[0] = stride; + s->m.linesize = stride; s->m.uvlinesize= s->current_picture->linesize[1]; s->m.width = width; s->m.height= height; @@ -1651,6 +1642,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, s->lambda2= s->m.lambda2= (s->m.lambda*s->m.lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT; s->m.dsp= s->dsp; //move + s->m.qdsp= s->qdsp; //move s->m.hdsp = s->hdsp; ff_init_me(&s->m); s->hdsp = s->m.hdsp; @@ -1664,10 +1656,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, redo_frame: - if (pic->pict_type == AV_PICTURE_TYPE_I) - s->spatial_decomposition_count= 5; - else - s->spatial_decomposition_count= 5; + s->spatial_decomposition_count= 5; while( !(width >>(s->chroma_h_shift + s->spatial_decomposition_count)) || !(height>>(s->chroma_v_shift + s->spatial_decomposition_count))) @@ -1824,9 +1813,9 @@ redo_frame: s->current_picture->quality = pict->quality; s->m.frame_bits = 8*(s->c.bytestream - s->c.bytestream_start); s->m.p_tex_bits = s->m.frame_bits - s->m.misc_bits - s->m.mv_bits; - s->m.current_picture.f.display_picture_number = - s->m.current_picture.f.coded_picture_number = avctx->frame_number; - s->m.current_picture.f.quality = pic->quality; + s->m.current_picture.f->display_picture_number = + s->m.current_picture.f->coded_picture_number = avctx->frame_number; + s->m.current_picture.f->quality = pic->quality; s->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start); if(s->pass1_rc) if (ff_rate_estimate_qscale(&s->m, 0) < 0) diff --git a/libavcodec/sparc/Makefile b/libavcodec/sparc/Makefile deleted file mode 100644 index aeb0f4753..000000000 --- a/libavcodec/sparc/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -VIS-OBJS += sparc/dsputil_vis.o \ - sparc/simple_idct_vis.o \ - -VIS-OBJS-$(CONFIG_HPELDSP) += sparc/hpeldsp_vis.o diff --git a/libavcodec/sparc/README b/libavcodec/sparc/README new file mode 100644 index 000000000..f9f2349cd --- /dev/null +++ b/libavcodec/sparc/README @@ -0,0 +1,6 @@ +SPARC optimizations have been removed in +commit b4dd424d96f09f9bafb88e47f37df65dc4529143 +The last revission with the optimizations is fb1b70c1ed50951c5fc1a309c3c446b2eaaf564b + +If you want to maintain these (or other) SPARC optimizations in ffmpeg, then please +contact ffmpeg-devel@ffmpeg.org diff --git a/libavcodec/sparc/hpeldsp_vis.c b/libavcodec/sparc/hpeldsp_vis.c deleted file mode 100644 index be2a85d8f..000000000 --- a/libavcodec/sparc/hpeldsp_vis.c +++ /dev/null @@ -1,3524 +0,0 @@ -/* - * Copyright (C) 2003 David S. Miller - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* The *no_round* functions have been added by James A. Morrison, 2003,2004. - The vis code from libmpeg2 was adapted for libavcodec by James A. Morrison. - */ - -#include -#include - -#include "libavutil/attributes.h" -#include "libavutil/mem.h" -#include "libavcodec/hpeldsp.h" -#include "vis.h" - -/* The trick used in some of this file is the formula from the MMX - * motion comp code, which is: - * - * (x+y+1)>>1 == (x|y)-((x^y)>>1) - * - * This allows us to average 8 bytes at a time in a 64-bit FPU reg. - * We avoid overflows by masking before we do the shift, and we - * implement the shift by multiplying by 1/2 using mul8x16. So in - * VIS this is (assume 'x' is in f0, 'y' is in f2, a repeating mask - * of '0xfe' is in f4, a repeating mask of '0x7f' is in f6, and - * the value 0x80808080 is in f8): - * - * fxor f0, f2, f10 - * fand f10, f4, f10 - * fmul8x16 f8, f10, f10 - * fand f10, f6, f10 - * for f0, f2, f12 - * fpsub16 f12, f10, f10 - */ - -#define DUP4(x) {x, x, x, x} -#define DUP8(x) {x, x, x, x, x, x, x, x} -DECLARE_ALIGNED(8, static const int16_t, constants1)[] = DUP4 (1); -DECLARE_ALIGNED(8, static const int16_t, constants2)[] = DUP4 (2); -DECLARE_ALIGNED(8, static const int16_t, constants3)[] = DUP4 (3); -DECLARE_ALIGNED(8, static const int16_t, constants6)[] = DUP4 (6); -DECLARE_ALIGNED(8, static const int8_t, constants_fe)[] = DUP8 (0xfe); -DECLARE_ALIGNED(8, static const int8_t, constants_7f)[] = DUP8 (0x7f); -DECLARE_ALIGNED(8, static const int8_t, constants128)[] = DUP8 (128); -DECLARE_ALIGNED(8, static const int16_t, constants256_512)[] = - {256, 512, 256, 512}; -DECLARE_ALIGNED(8, static const int16_t, constants256_1024)[] = - {256, 1024, 256, 1024}; - -#define REF_0 0 -#define REF_0_1 1 -#define REF_2 2 -#define REF_2_1 3 -#define REF_4 4 -#define REF_4_1 5 -#define REF_6 6 -#define REF_6_1 7 -#define REF_S0 8 -#define REF_S0_1 9 -#define REF_S2 10 -#define REF_S2_1 11 -#define REF_S4 12 -#define REF_S4_1 13 -#define REF_S6 14 -#define REF_S6_1 15 -#define DST_0 16 -#define DST_1 17 -#define DST_2 18 -#define DST_3 19 -#define CONST_1 20 -#define CONST_2 20 -#define CONST_3 20 -#define CONST_6 20 -#define MASK_fe 20 -#define CONST_128 22 -#define CONST_256 22 -#define CONST_512 22 -#define CONST_1024 22 -#define TMP0 24 -#define TMP1 25 -#define TMP2 26 -#define TMP3 27 -#define TMP4 28 -#define TMP5 29 -#define ZERO 30 -#define MASK_7f 30 - -#define TMP6 32 -#define TMP8 34 -#define TMP10 36 -#define TMP12 38 -#define TMP14 40 -#define TMP16 42 -#define TMP18 44 -#define TMP20 46 -#define TMP22 48 -#define TMP24 50 -#define TMP26 52 -#define TMP28 54 -#define TMP30 56 -#define TMP32 58 - -static void MC_put_o_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - ref = vis_alignaddr(ref); - do { /* 5 cycles */ - vis_ld64(ref[0], TMP0); - - vis_ld64_2(ref, 8, TMP2); - - vis_ld64_2(ref, 16, TMP4); - ref += stride; - - vis_faligndata(TMP0, TMP2, REF_0); - vis_st64(REF_0, dest[0]); - - vis_faligndata(TMP2, TMP4, REF_2); - vis_st64_2(REF_2, dest, 8); - dest += stride; - } while (--height); -} - -static void MC_put_o_8_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - ref = vis_alignaddr(ref); - do { /* 4 cycles */ - vis_ld64(ref[0], TMP0); - - vis_ld64(ref[8], TMP2); - ref += stride; - - /* stall */ - - vis_faligndata(TMP0, TMP2, REF_0); - vis_st64(REF_0, dest[0]); - dest += stride; - } while (--height); -} - - -static void MC_avg_o_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - int stride_8 = stride + 8; - - ref = vis_alignaddr(ref); - - vis_ld64(ref[0], TMP0); - - vis_ld64(ref[8], TMP2); - - vis_ld64(ref[16], TMP4); - - vis_ld64(dest[0], DST_0); - - vis_ld64(dest[8], DST_2); - - vis_ld64(constants_fe[0], MASK_fe); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64(constants_7f[0], MASK_7f); - vis_faligndata(TMP2, TMP4, REF_2); - - vis_ld64(constants128[0], CONST_128); - - ref += stride; - height = (height >> 1) - 1; - - do { /* 24 cycles */ - vis_ld64(ref[0], TMP0); - vis_xor(DST_0, REF_0, TMP6); - - vis_ld64_2(ref, 8, TMP2); - vis_and(TMP6, MASK_fe, TMP6); - - vis_ld64_2(ref, 16, TMP4); - ref += stride; - vis_mul8x16(CONST_128, TMP6, TMP6); - vis_xor(DST_2, REF_2, TMP8); - - vis_and(TMP8, MASK_fe, TMP8); - - vis_or(DST_0, REF_0, TMP10); - vis_ld64_2(dest, stride, DST_0); - vis_mul8x16(CONST_128, TMP8, TMP8); - - vis_or(DST_2, REF_2, TMP12); - vis_ld64_2(dest, stride_8, DST_2); - - vis_ld64(ref[0], TMP14); - vis_and(TMP6, MASK_7f, TMP6); - - vis_and(TMP8, MASK_7f, TMP8); - - vis_psub16(TMP10, TMP6, TMP6); - vis_st64(TMP6, dest[0]); - - vis_psub16(TMP12, TMP8, TMP8); - vis_st64_2(TMP8, dest, 8); - - dest += stride; - vis_ld64_2(ref, 8, TMP16); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(ref, 16, TMP18); - vis_faligndata(TMP2, TMP4, REF_2); - ref += stride; - - vis_xor(DST_0, REF_0, TMP20); - - vis_and(TMP20, MASK_fe, TMP20); - - vis_xor(DST_2, REF_2, TMP22); - vis_mul8x16(CONST_128, TMP20, TMP20); - - vis_and(TMP22, MASK_fe, TMP22); - - vis_or(DST_0, REF_0, TMP24); - vis_mul8x16(CONST_128, TMP22, TMP22); - - vis_or(DST_2, REF_2, TMP26); - - vis_ld64_2(dest, stride, DST_0); - vis_faligndata(TMP14, TMP16, REF_0); - - vis_ld64_2(dest, stride_8, DST_2); - vis_faligndata(TMP16, TMP18, REF_2); - - vis_and(TMP20, MASK_7f, TMP20); - - vis_and(TMP22, MASK_7f, TMP22); - - vis_psub16(TMP24, TMP20, TMP20); - vis_st64(TMP20, dest[0]); - - vis_psub16(TMP26, TMP22, TMP22); - vis_st64_2(TMP22, dest, 8); - dest += stride; - } while (--height); - - vis_ld64(ref[0], TMP0); - vis_xor(DST_0, REF_0, TMP6); - - vis_ld64_2(ref, 8, TMP2); - vis_and(TMP6, MASK_fe, TMP6); - - vis_ld64_2(ref, 16, TMP4); - vis_mul8x16(CONST_128, TMP6, TMP6); - vis_xor(DST_2, REF_2, TMP8); - - vis_and(TMP8, MASK_fe, TMP8); - - vis_or(DST_0, REF_0, TMP10); - vis_ld64_2(dest, stride, DST_0); - vis_mul8x16(CONST_128, TMP8, TMP8); - - vis_or(DST_2, REF_2, TMP12); - vis_ld64_2(dest, stride_8, DST_2); - - vis_ld64(ref[0], TMP14); - vis_and(TMP6, MASK_7f, TMP6); - - vis_and(TMP8, MASK_7f, TMP8); - - vis_psub16(TMP10, TMP6, TMP6); - vis_st64(TMP6, dest[0]); - - vis_psub16(TMP12, TMP8, TMP8); - vis_st64_2(TMP8, dest, 8); - - dest += stride; - vis_faligndata(TMP0, TMP2, REF_0); - - vis_faligndata(TMP2, TMP4, REF_2); - - vis_xor(DST_0, REF_0, TMP20); - - vis_and(TMP20, MASK_fe, TMP20); - - vis_xor(DST_2, REF_2, TMP22); - vis_mul8x16(CONST_128, TMP20, TMP20); - - vis_and(TMP22, MASK_fe, TMP22); - - vis_or(DST_0, REF_0, TMP24); - vis_mul8x16(CONST_128, TMP22, TMP22); - - vis_or(DST_2, REF_2, TMP26); - - vis_and(TMP20, MASK_7f, TMP20); - - vis_and(TMP22, MASK_7f, TMP22); - - vis_psub16(TMP24, TMP20, TMP20); - vis_st64(TMP20, dest[0]); - - vis_psub16(TMP26, TMP22, TMP22); - vis_st64_2(TMP22, dest, 8); -} - -static void MC_avg_o_8_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - ref = vis_alignaddr(ref); - - vis_ld64(ref[0], TMP0); - - vis_ld64(ref[8], TMP2); - - vis_ld64(dest[0], DST_0); - - vis_ld64(constants_fe[0], MASK_fe); - - vis_ld64(constants_7f[0], MASK_7f); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64(constants128[0], CONST_128); - - ref += stride; - height = (height >> 1) - 1; - - do { /* 12 cycles */ - vis_ld64(ref[0], TMP0); - vis_xor(DST_0, REF_0, TMP4); - - vis_ld64(ref[8], TMP2); - vis_and(TMP4, MASK_fe, TMP4); - - vis_or(DST_0, REF_0, TMP6); - vis_ld64_2(dest, stride, DST_0); - ref += stride; - vis_mul8x16(CONST_128, TMP4, TMP4); - - vis_ld64(ref[0], TMP12); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64(ref[8], TMP2); - vis_xor(DST_0, REF_0, TMP0); - ref += stride; - - vis_and(TMP0, MASK_fe, TMP0); - - vis_and(TMP4, MASK_7f, TMP4); - - vis_psub16(TMP6, TMP4, TMP4); - vis_st64(TMP4, dest[0]); - dest += stride; - vis_mul8x16(CONST_128, TMP0, TMP0); - - vis_or(DST_0, REF_0, TMP6); - vis_ld64_2(dest, stride, DST_0); - - vis_faligndata(TMP12, TMP2, REF_0); - - vis_and(TMP0, MASK_7f, TMP0); - - vis_psub16(TMP6, TMP0, TMP4); - vis_st64(TMP4, dest[0]); - dest += stride; - } while (--height); - - vis_ld64(ref[0], TMP0); - vis_xor(DST_0, REF_0, TMP4); - - vis_ld64(ref[8], TMP2); - vis_and(TMP4, MASK_fe, TMP4); - - vis_or(DST_0, REF_0, TMP6); - vis_ld64_2(dest, stride, DST_0); - vis_mul8x16(CONST_128, TMP4, TMP4); - - vis_faligndata(TMP0, TMP2, REF_0); - - vis_xor(DST_0, REF_0, TMP0); - - vis_and(TMP0, MASK_fe, TMP0); - - vis_and(TMP4, MASK_7f, TMP4); - - vis_psub16(TMP6, TMP4, TMP4); - vis_st64(TMP4, dest[0]); - dest += stride; - vis_mul8x16(CONST_128, TMP0, TMP0); - - vis_or(DST_0, REF_0, TMP6); - - vis_and(TMP0, MASK_7f, TMP0); - - vis_psub16(TMP6, TMP0, TMP4); - vis_st64(TMP4, dest[0]); -} - -static void MC_put_x_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - - ref = vis_alignaddr(ref); - - vis_ld64(ref[0], TMP0); - - vis_ld64_2(ref, 8, TMP2); - - vis_ld64_2(ref, 16, TMP4); - - vis_ld64(constants_fe[0], MASK_fe); - - vis_ld64(constants_7f[0], MASK_7f); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64(constants128[0], CONST_128); - vis_faligndata(TMP2, TMP4, REF_4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - vis_faligndata(TMP2, TMP4, REF_6); - } else { - vis_src1(TMP2, REF_2); - vis_src1(TMP4, REF_6); - } - - ref += stride; - height = (height >> 1) - 1; - - do { /* 34 cycles */ - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP6); - - vis_ld64_2(ref, 8, TMP2); - vis_xor(REF_4, REF_6, TMP8); - - vis_ld64_2(ref, 16, TMP4); - vis_and(TMP6, MASK_fe, TMP6); - ref += stride; - - vis_ld64(ref[0], TMP14); - vis_mul8x16(CONST_128, TMP6, TMP6); - vis_and(TMP8, MASK_fe, TMP8); - - vis_ld64_2(ref, 8, TMP16); - vis_mul8x16(CONST_128, TMP8, TMP8); - vis_or(REF_0, REF_2, TMP10); - - vis_ld64_2(ref, 16, TMP18); - ref += stride; - vis_or(REF_4, REF_6, TMP12); - - vis_alignaddr_g0((void *)off); - - vis_faligndata(TMP0, TMP2, REF_0); - - vis_faligndata(TMP2, TMP4, REF_4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - vis_faligndata(TMP2, TMP4, REF_6); - } else { - vis_src1(TMP2, REF_2); - vis_src1(TMP4, REF_6); - } - - vis_and(TMP6, MASK_7f, TMP6); - - vis_and(TMP8, MASK_7f, TMP8); - - vis_psub16(TMP10, TMP6, TMP6); - vis_st64(TMP6, dest[0]); - - vis_psub16(TMP12, TMP8, TMP8); - vis_st64_2(TMP8, dest, 8); - dest += stride; - - vis_xor(REF_0, REF_2, TMP6); - - vis_xor(REF_4, REF_6, TMP8); - - vis_and(TMP6, MASK_fe, TMP6); - - vis_mul8x16(CONST_128, TMP6, TMP6); - vis_and(TMP8, MASK_fe, TMP8); - - vis_mul8x16(CONST_128, TMP8, TMP8); - vis_or(REF_0, REF_2, TMP10); - - vis_or(REF_4, REF_6, TMP12); - - vis_alignaddr_g0((void *)off); - - vis_faligndata(TMP14, TMP16, REF_0); - - vis_faligndata(TMP16, TMP18, REF_4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP14, TMP16, REF_2); - vis_faligndata(TMP16, TMP18, REF_6); - } else { - vis_src1(TMP16, REF_2); - vis_src1(TMP18, REF_6); - } - - vis_and(TMP6, MASK_7f, TMP6); - - vis_and(TMP8, MASK_7f, TMP8); - - vis_psub16(TMP10, TMP6, TMP6); - vis_st64(TMP6, dest[0]); - - vis_psub16(TMP12, TMP8, TMP8); - vis_st64_2(TMP8, dest, 8); - dest += stride; - } while (--height); - - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP6); - - vis_ld64_2(ref, 8, TMP2); - vis_xor(REF_4, REF_6, TMP8); - - vis_ld64_2(ref, 16, TMP4); - vis_and(TMP6, MASK_fe, TMP6); - - vis_mul8x16(CONST_128, TMP6, TMP6); - vis_and(TMP8, MASK_fe, TMP8); - - vis_mul8x16(CONST_128, TMP8, TMP8); - vis_or(REF_0, REF_2, TMP10); - - vis_or(REF_4, REF_6, TMP12); - - vis_alignaddr_g0((void *)off); - - vis_faligndata(TMP0, TMP2, REF_0); - - vis_faligndata(TMP2, TMP4, REF_4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - vis_faligndata(TMP2, TMP4, REF_6); - } else { - vis_src1(TMP2, REF_2); - vis_src1(TMP4, REF_6); - } - - vis_and(TMP6, MASK_7f, TMP6); - - vis_and(TMP8, MASK_7f, TMP8); - - vis_psub16(TMP10, TMP6, TMP6); - vis_st64(TMP6, dest[0]); - - vis_psub16(TMP12, TMP8, TMP8); - vis_st64_2(TMP8, dest, 8); - dest += stride; - - vis_xor(REF_0, REF_2, TMP6); - - vis_xor(REF_4, REF_6, TMP8); - - vis_and(TMP6, MASK_fe, TMP6); - - vis_mul8x16(CONST_128, TMP6, TMP6); - vis_and(TMP8, MASK_fe, TMP8); - - vis_mul8x16(CONST_128, TMP8, TMP8); - vis_or(REF_0, REF_2, TMP10); - - vis_or(REF_4, REF_6, TMP12); - - vis_and(TMP6, MASK_7f, TMP6); - - vis_and(TMP8, MASK_7f, TMP8); - - vis_psub16(TMP10, TMP6, TMP6); - vis_st64(TMP6, dest[0]); - - vis_psub16(TMP12, TMP8, TMP8); - vis_st64_2(TMP8, dest, 8); -} - -static void MC_put_x_8_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - - ref = vis_alignaddr(ref); - - vis_ld64(ref[0], TMP0); - - vis_ld64(ref[8], TMP2); - - vis_ld64(constants_fe[0], MASK_fe); - - vis_ld64(constants_7f[0], MASK_7f); - - vis_ld64(constants128[0], CONST_128); - vis_faligndata(TMP0, TMP2, REF_0); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - } else { - vis_src1(TMP2, REF_2); - } - - ref += stride; - height = (height >> 1) - 1; - - do { /* 20 cycles */ - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP4); - - vis_ld64_2(ref, 8, TMP2); - vis_and(TMP4, MASK_fe, TMP4); - ref += stride; - - vis_ld64(ref[0], TMP8); - vis_or(REF_0, REF_2, TMP6); - vis_mul8x16(CONST_128, TMP4, TMP4); - - vis_alignaddr_g0((void *)off); - - vis_ld64_2(ref, 8, TMP10); - ref += stride; - vis_faligndata(TMP0, TMP2, REF_0); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - } else { - vis_src1(TMP2, REF_2); - } - - vis_and(TMP4, MASK_7f, TMP4); - - vis_psub16(TMP6, TMP4, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; - - vis_xor(REF_0, REF_2, TMP12); - - vis_and(TMP12, MASK_fe, TMP12); - - vis_or(REF_0, REF_2, TMP14); - vis_mul8x16(CONST_128, TMP12, TMP12); - - vis_alignaddr_g0((void *)off); - vis_faligndata(TMP8, TMP10, REF_0); - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP8, TMP10, REF_2); - } else { - vis_src1(TMP10, REF_2); - } - - vis_and(TMP12, MASK_7f, TMP12); - - vis_psub16(TMP14, TMP12, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; - } while (--height); - - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP4); - - vis_ld64_2(ref, 8, TMP2); - vis_and(TMP4, MASK_fe, TMP4); - - vis_or(REF_0, REF_2, TMP6); - vis_mul8x16(CONST_128, TMP4, TMP4); - - vis_alignaddr_g0((void *)off); - - vis_faligndata(TMP0, TMP2, REF_0); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - } else { - vis_src1(TMP2, REF_2); - } - - vis_and(TMP4, MASK_7f, TMP4); - - vis_psub16(TMP6, TMP4, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; - - vis_xor(REF_0, REF_2, TMP12); - - vis_and(TMP12, MASK_fe, TMP12); - - vis_or(REF_0, REF_2, TMP14); - vis_mul8x16(CONST_128, TMP12, TMP12); - - vis_and(TMP12, MASK_7f, TMP12); - - vis_psub16(TMP14, TMP12, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; -} - -static void MC_avg_x_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - - vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); - - vis_ld64(constants3[0], CONST_3); - vis_fzero(ZERO); - vis_ld64(constants256_512[0], CONST_256); - - ref = vis_alignaddr(ref); - do { /* 26 cycles */ - vis_ld64(ref[0], TMP0); - - vis_ld64(ref[8], TMP2); - - vis_alignaddr_g0((void *)off); - - vis_ld64(ref[16], TMP4); - - vis_ld64(dest[0], DST_0); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64(dest[8], DST_2); - vis_faligndata(TMP2, TMP4, REF_4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - vis_faligndata(TMP2, TMP4, REF_6); - } else { - vis_src1(TMP2, REF_2); - vis_src1(TMP4, REF_6); - } - - vis_mul8x16au(REF_0, CONST_256, TMP0); - - vis_pmerge(ZERO, REF_2, TMP4); - vis_mul8x16au(REF_0_1, CONST_256, TMP2); - - vis_pmerge(ZERO, REF_2_1, TMP6); - - vis_padd16(TMP0, TMP4, TMP0); - - vis_mul8x16al(DST_0, CONST_512, TMP4); - vis_padd16(TMP2, TMP6, TMP2); - - vis_mul8x16al(DST_1, CONST_512, TMP6); - - vis_mul8x16au(REF_6, CONST_256, TMP12); - - vis_padd16(TMP0, TMP4, TMP0); - vis_mul8x16au(REF_6_1, CONST_256, TMP14); - - vis_padd16(TMP2, TMP6, TMP2); - vis_mul8x16au(REF_4, CONST_256, TMP16); - - vis_padd16(TMP0, CONST_3, TMP8); - vis_mul8x16au(REF_4_1, CONST_256, TMP18); - - vis_padd16(TMP2, CONST_3, TMP10); - vis_pack16(TMP8, DST_0); - - vis_pack16(TMP10, DST_1); - vis_padd16(TMP16, TMP12, TMP0); - - vis_st64(DST_0, dest[0]); - vis_mul8x16al(DST_2, CONST_512, TMP4); - vis_padd16(TMP18, TMP14, TMP2); - - vis_mul8x16al(DST_3, CONST_512, TMP6); - vis_padd16(TMP0, CONST_3, TMP0); - - vis_padd16(TMP2, CONST_3, TMP2); - - vis_padd16(TMP0, TMP4, TMP0); - - vis_padd16(TMP2, TMP6, TMP2); - vis_pack16(TMP0, DST_2); - - vis_pack16(TMP2, DST_3); - vis_st64(DST_2, dest[8]); - - ref += stride; - dest += stride; - } while (--height); -} - -static void MC_avg_x_8_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - int stride_times_2 = stride << 1; - - vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); - - vis_ld64(constants3[0], CONST_3); - vis_fzero(ZERO); - vis_ld64(constants256_512[0], CONST_256); - - ref = vis_alignaddr(ref); - height >>= 2; - do { /* 47 cycles */ - vis_ld64(ref[0], TMP0); - - vis_ld64_2(ref, 8, TMP2); - ref += stride; - - vis_alignaddr_g0((void *)off); - - vis_ld64(ref[0], TMP4); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(ref, 8, TMP6); - ref += stride; - - vis_ld64(ref[0], TMP8); - - vis_ld64_2(ref, 8, TMP10); - ref += stride; - vis_faligndata(TMP4, TMP6, REF_4); - - vis_ld64(ref[0], TMP12); - - vis_ld64_2(ref, 8, TMP14); - ref += stride; - vis_faligndata(TMP8, TMP10, REF_S0); - - vis_faligndata(TMP12, TMP14, REF_S4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - - vis_ld64(dest[0], DST_0); - vis_faligndata(TMP0, TMP2, REF_2); - - vis_ld64_2(dest, stride, DST_2); - vis_faligndata(TMP4, TMP6, REF_6); - - vis_faligndata(TMP8, TMP10, REF_S2); - - vis_faligndata(TMP12, TMP14, REF_S6); - } else { - vis_ld64(dest[0], DST_0); - vis_src1(TMP2, REF_2); - - vis_ld64_2(dest, stride, DST_2); - vis_src1(TMP6, REF_6); - - vis_src1(TMP10, REF_S2); - - vis_src1(TMP14, REF_S6); - } - - vis_pmerge(ZERO, REF_0, TMP0); - vis_mul8x16au(REF_0_1, CONST_256, TMP2); - - vis_pmerge(ZERO, REF_2, TMP4); - vis_mul8x16au(REF_2_1, CONST_256, TMP6); - - vis_padd16(TMP0, CONST_3, TMP0); - vis_mul8x16al(DST_0, CONST_512, TMP16); - - vis_padd16(TMP2, CONST_3, TMP2); - vis_mul8x16al(DST_1, CONST_512, TMP18); - - vis_padd16(TMP0, TMP4, TMP0); - vis_mul8x16au(REF_4, CONST_256, TMP8); - - vis_padd16(TMP2, TMP6, TMP2); - vis_mul8x16au(REF_4_1, CONST_256, TMP10); - - vis_padd16(TMP0, TMP16, TMP0); - vis_mul8x16au(REF_6, CONST_256, TMP12); - - vis_padd16(TMP2, TMP18, TMP2); - vis_mul8x16au(REF_6_1, CONST_256, TMP14); - - vis_padd16(TMP8, CONST_3, TMP8); - vis_mul8x16al(DST_2, CONST_512, TMP16); - - vis_padd16(TMP8, TMP12, TMP8); - vis_mul8x16al(DST_3, CONST_512, TMP18); - - vis_padd16(TMP10, TMP14, TMP10); - vis_pack16(TMP0, DST_0); - - vis_pack16(TMP2, DST_1); - vis_st64(DST_0, dest[0]); - dest += stride; - vis_padd16(TMP10, CONST_3, TMP10); - - vis_ld64_2(dest, stride, DST_0); - vis_padd16(TMP8, TMP16, TMP8); - - vis_ld64_2(dest, stride_times_2, TMP4/*DST_2*/); - vis_padd16(TMP10, TMP18, TMP10); - vis_pack16(TMP8, DST_2); - - vis_pack16(TMP10, DST_3); - vis_st64(DST_2, dest[0]); - dest += stride; - - vis_mul8x16au(REF_S0_1, CONST_256, TMP2); - vis_pmerge(ZERO, REF_S0, TMP0); - - vis_pmerge(ZERO, REF_S2, TMP24); - vis_mul8x16au(REF_S2_1, CONST_256, TMP6); - - vis_padd16(TMP0, CONST_3, TMP0); - vis_mul8x16au(REF_S4, CONST_256, TMP8); - - vis_padd16(TMP2, CONST_3, TMP2); - vis_mul8x16au(REF_S4_1, CONST_256, TMP10); - - vis_padd16(TMP0, TMP24, TMP0); - vis_mul8x16au(REF_S6, CONST_256, TMP12); - - vis_padd16(TMP2, TMP6, TMP2); - vis_mul8x16au(REF_S6_1, CONST_256, TMP14); - - vis_padd16(TMP8, CONST_3, TMP8); - vis_mul8x16al(DST_0, CONST_512, TMP16); - - vis_padd16(TMP10, CONST_3, TMP10); - vis_mul8x16al(DST_1, CONST_512, TMP18); - - vis_padd16(TMP8, TMP12, TMP8); - vis_mul8x16al(TMP4/*DST_2*/, CONST_512, TMP20); - - vis_mul8x16al(TMP5/*DST_3*/, CONST_512, TMP22); - vis_padd16(TMP0, TMP16, TMP0); - - vis_padd16(TMP2, TMP18, TMP2); - vis_pack16(TMP0, DST_0); - - vis_padd16(TMP10, TMP14, TMP10); - vis_pack16(TMP2, DST_1); - vis_st64(DST_0, dest[0]); - dest += stride; - - vis_padd16(TMP8, TMP20, TMP8); - - vis_padd16(TMP10, TMP22, TMP10); - vis_pack16(TMP8, DST_2); - - vis_pack16(TMP10, DST_3); - vis_st64(DST_2, dest[0]); - dest += stride; - } while (--height); -} - -static void MC_put_y_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - ref = vis_alignaddr(ref); - vis_ld64(ref[0], TMP0); - - vis_ld64_2(ref, 8, TMP2); - - vis_ld64_2(ref, 16, TMP4); - ref += stride; - - vis_ld64(ref[0], TMP6); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(ref, 8, TMP8); - vis_faligndata(TMP2, TMP4, REF_4); - - vis_ld64_2(ref, 16, TMP10); - ref += stride; - - vis_ld64(constants_fe[0], MASK_fe); - vis_faligndata(TMP6, TMP8, REF_2); - - vis_ld64(constants_7f[0], MASK_7f); - vis_faligndata(TMP8, TMP10, REF_6); - - vis_ld64(constants128[0], CONST_128); - height = (height >> 1) - 1; - do { /* 24 cycles */ - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP12); - - vis_ld64_2(ref, 8, TMP2); - vis_xor(REF_4, REF_6, TMP16); - - vis_ld64_2(ref, 16, TMP4); - ref += stride; - vis_or(REF_0, REF_2, TMP14); - - vis_ld64(ref[0], TMP6); - vis_or(REF_4, REF_6, TMP18); - - vis_ld64_2(ref, 8, TMP8); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(ref, 16, TMP10); - ref += stride; - vis_faligndata(TMP2, TMP4, REF_4); - - vis_and(TMP12, MASK_fe, TMP12); - - vis_and(TMP16, MASK_fe, TMP16); - vis_mul8x16(CONST_128, TMP12, TMP12); - - vis_mul8x16(CONST_128, TMP16, TMP16); - vis_xor(REF_0, REF_2, TMP0); - - vis_xor(REF_4, REF_6, TMP2); - - vis_or(REF_0, REF_2, TMP20); - - vis_and(TMP12, MASK_7f, TMP12); - - vis_and(TMP16, MASK_7f, TMP16); - - vis_psub16(TMP14, TMP12, TMP12); - vis_st64(TMP12, dest[0]); - - vis_psub16(TMP18, TMP16, TMP16); - vis_st64_2(TMP16, dest, 8); - dest += stride; - - vis_or(REF_4, REF_6, TMP18); - - vis_and(TMP0, MASK_fe, TMP0); - - vis_and(TMP2, MASK_fe, TMP2); - vis_mul8x16(CONST_128, TMP0, TMP0); - - vis_faligndata(TMP6, TMP8, REF_2); - vis_mul8x16(CONST_128, TMP2, TMP2); - - vis_faligndata(TMP8, TMP10, REF_6); - - vis_and(TMP0, MASK_7f, TMP0); - - vis_and(TMP2, MASK_7f, TMP2); - - vis_psub16(TMP20, TMP0, TMP0); - vis_st64(TMP0, dest[0]); - - vis_psub16(TMP18, TMP2, TMP2); - vis_st64_2(TMP2, dest, 8); - dest += stride; - } while (--height); - - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP12); - - vis_ld64_2(ref, 8, TMP2); - vis_xor(REF_4, REF_6, TMP16); - - vis_ld64_2(ref, 16, TMP4); - vis_or(REF_0, REF_2, TMP14); - - vis_or(REF_4, REF_6, TMP18); - - vis_faligndata(TMP0, TMP2, REF_0); - - vis_faligndata(TMP2, TMP4, REF_4); - - vis_and(TMP12, MASK_fe, TMP12); - - vis_and(TMP16, MASK_fe, TMP16); - vis_mul8x16(CONST_128, TMP12, TMP12); - - vis_mul8x16(CONST_128, TMP16, TMP16); - vis_xor(REF_0, REF_2, TMP0); - - vis_xor(REF_4, REF_6, TMP2); - - vis_or(REF_0, REF_2, TMP20); - - vis_and(TMP12, MASK_7f, TMP12); - - vis_and(TMP16, MASK_7f, TMP16); - - vis_psub16(TMP14, TMP12, TMP12); - vis_st64(TMP12, dest[0]); - - vis_psub16(TMP18, TMP16, TMP16); - vis_st64_2(TMP16, dest, 8); - dest += stride; - - vis_or(REF_4, REF_6, TMP18); - - vis_and(TMP0, MASK_fe, TMP0); - - vis_and(TMP2, MASK_fe, TMP2); - vis_mul8x16(CONST_128, TMP0, TMP0); - - vis_mul8x16(CONST_128, TMP2, TMP2); - - vis_and(TMP0, MASK_7f, TMP0); - - vis_and(TMP2, MASK_7f, TMP2); - - vis_psub16(TMP20, TMP0, TMP0); - vis_st64(TMP0, dest[0]); - - vis_psub16(TMP18, TMP2, TMP2); - vis_st64_2(TMP2, dest, 8); -} - -static void MC_put_y_8_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - ref = vis_alignaddr(ref); - vis_ld64(ref[0], TMP0); - - vis_ld64_2(ref, 8, TMP2); - ref += stride; - - vis_ld64(ref[0], TMP4); - - vis_ld64_2(ref, 8, TMP6); - ref += stride; - - vis_ld64(constants_fe[0], MASK_fe); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64(constants_7f[0], MASK_7f); - vis_faligndata(TMP4, TMP6, REF_2); - - vis_ld64(constants128[0], CONST_128); - height = (height >> 1) - 1; - do { /* 12 cycles */ - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP4); - - vis_ld64_2(ref, 8, TMP2); - ref += stride; - vis_and(TMP4, MASK_fe, TMP4); - - vis_or(REF_0, REF_2, TMP6); - vis_mul8x16(CONST_128, TMP4, TMP4); - - vis_faligndata(TMP0, TMP2, REF_0); - vis_ld64(ref[0], TMP0); - - vis_ld64_2(ref, 8, TMP2); - ref += stride; - vis_xor(REF_0, REF_2, TMP12); - - vis_and(TMP4, MASK_7f, TMP4); - - vis_and(TMP12, MASK_fe, TMP12); - - vis_mul8x16(CONST_128, TMP12, TMP12); - vis_or(REF_0, REF_2, TMP14); - - vis_psub16(TMP6, TMP4, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; - - vis_faligndata(TMP0, TMP2, REF_2); - - vis_and(TMP12, MASK_7f, TMP12); - - vis_psub16(TMP14, TMP12, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; - } while (--height); - - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP4); - - vis_ld64_2(ref, 8, TMP2); - vis_and(TMP4, MASK_fe, TMP4); - - vis_or(REF_0, REF_2, TMP6); - vis_mul8x16(CONST_128, TMP4, TMP4); - - vis_faligndata(TMP0, TMP2, REF_0); - - vis_xor(REF_0, REF_2, TMP12); - - vis_and(TMP4, MASK_7f, TMP4); - - vis_and(TMP12, MASK_fe, TMP12); - - vis_mul8x16(CONST_128, TMP12, TMP12); - vis_or(REF_0, REF_2, TMP14); - - vis_psub16(TMP6, TMP4, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; - - vis_and(TMP12, MASK_7f, TMP12); - - vis_psub16(TMP14, TMP12, DST_0); - vis_st64(DST_0, dest[0]); -} - -static void MC_avg_y_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - int stride_8 = stride + 8; - int stride_16 = stride + 16; - - vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); - - ref = vis_alignaddr(ref); - - vis_ld64(ref[ 0], TMP0); - vis_fzero(ZERO); - - vis_ld64(ref[ 8], TMP2); - - vis_ld64(ref[16], TMP4); - - vis_ld64(constants3[0], CONST_3); - vis_faligndata(TMP0, TMP2, REF_2); - - vis_ld64(constants256_512[0], CONST_256); - vis_faligndata(TMP2, TMP4, REF_6); - height >>= 1; - - do { /* 31 cycles */ - vis_ld64_2(ref, stride, TMP0); - vis_pmerge(ZERO, REF_2, TMP12); - vis_mul8x16au(REF_2_1, CONST_256, TMP14); - - vis_ld64_2(ref, stride_8, TMP2); - vis_pmerge(ZERO, REF_6, TMP16); - vis_mul8x16au(REF_6_1, CONST_256, TMP18); - - vis_ld64_2(ref, stride_16, TMP4); - ref += stride; - - vis_ld64(dest[0], DST_0); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(dest, 8, DST_2); - vis_faligndata(TMP2, TMP4, REF_4); - - vis_ld64_2(ref, stride, TMP6); - vis_pmerge(ZERO, REF_0, TMP0); - vis_mul8x16au(REF_0_1, CONST_256, TMP2); - - vis_ld64_2(ref, stride_8, TMP8); - vis_pmerge(ZERO, REF_4, TMP4); - - vis_ld64_2(ref, stride_16, TMP10); - ref += stride; - - vis_ld64_2(dest, stride, REF_S0/*DST_4*/); - vis_faligndata(TMP6, TMP8, REF_2); - vis_mul8x16au(REF_4_1, CONST_256, TMP6); - - vis_ld64_2(dest, stride_8, REF_S2/*DST_6*/); - vis_faligndata(TMP8, TMP10, REF_6); - vis_mul8x16al(DST_0, CONST_512, TMP20); - - vis_padd16(TMP0, CONST_3, TMP0); - vis_mul8x16al(DST_1, CONST_512, TMP22); - - vis_padd16(TMP2, CONST_3, TMP2); - vis_mul8x16al(DST_2, CONST_512, TMP24); - - vis_padd16(TMP4, CONST_3, TMP4); - vis_mul8x16al(DST_3, CONST_512, TMP26); - - vis_padd16(TMP6, CONST_3, TMP6); - - vis_padd16(TMP12, TMP20, TMP12); - vis_mul8x16al(REF_S0, CONST_512, TMP20); - - vis_padd16(TMP14, TMP22, TMP14); - vis_mul8x16al(REF_S0_1, CONST_512, TMP22); - - vis_padd16(TMP16, TMP24, TMP16); - vis_mul8x16al(REF_S2, CONST_512, TMP24); - - vis_padd16(TMP18, TMP26, TMP18); - vis_mul8x16al(REF_S2_1, CONST_512, TMP26); - - vis_padd16(TMP12, TMP0, TMP12); - vis_mul8x16au(REF_2, CONST_256, TMP28); - - vis_padd16(TMP14, TMP2, TMP14); - vis_mul8x16au(REF_2_1, CONST_256, TMP30); - - vis_padd16(TMP16, TMP4, TMP16); - vis_mul8x16au(REF_6, CONST_256, REF_S4); - - vis_padd16(TMP18, TMP6, TMP18); - vis_mul8x16au(REF_6_1, CONST_256, REF_S6); - - vis_pack16(TMP12, DST_0); - vis_padd16(TMP28, TMP0, TMP12); - - vis_pack16(TMP14, DST_1); - vis_st64(DST_0, dest[0]); - vis_padd16(TMP30, TMP2, TMP14); - - vis_pack16(TMP16, DST_2); - vis_padd16(REF_S4, TMP4, TMP16); - - vis_pack16(TMP18, DST_3); - vis_st64_2(DST_2, dest, 8); - dest += stride; - vis_padd16(REF_S6, TMP6, TMP18); - - vis_padd16(TMP12, TMP20, TMP12); - - vis_padd16(TMP14, TMP22, TMP14); - vis_pack16(TMP12, DST_0); - - vis_padd16(TMP16, TMP24, TMP16); - vis_pack16(TMP14, DST_1); - vis_st64(DST_0, dest[0]); - - vis_padd16(TMP18, TMP26, TMP18); - vis_pack16(TMP16, DST_2); - - vis_pack16(TMP18, DST_3); - vis_st64_2(DST_2, dest, 8); - dest += stride; - } while (--height); -} - -static void MC_avg_y_8_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - int stride_8 = stride + 8; - - vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); - - ref = vis_alignaddr(ref); - - vis_ld64(ref[ 0], TMP0); - vis_fzero(ZERO); - - vis_ld64(ref[ 8], TMP2); - - vis_ld64(constants3[0], CONST_3); - vis_faligndata(TMP0, TMP2, REF_2); - - vis_ld64(constants256_512[0], CONST_256); - - height >>= 1; - do { /* 20 cycles */ - vis_ld64_2(ref, stride, TMP0); - vis_pmerge(ZERO, REF_2, TMP8); - vis_mul8x16au(REF_2_1, CONST_256, TMP10); - - vis_ld64_2(ref, stride_8, TMP2); - ref += stride; - - vis_ld64(dest[0], DST_0); - - vis_ld64_2(dest, stride, DST_2); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(ref, stride, TMP4); - vis_mul8x16al(DST_0, CONST_512, TMP16); - vis_pmerge(ZERO, REF_0, TMP12); - - vis_ld64_2(ref, stride_8, TMP6); - ref += stride; - vis_mul8x16al(DST_1, CONST_512, TMP18); - vis_pmerge(ZERO, REF_0_1, TMP14); - - vis_padd16(TMP12, CONST_3, TMP12); - vis_mul8x16al(DST_2, CONST_512, TMP24); - - vis_padd16(TMP14, CONST_3, TMP14); - vis_mul8x16al(DST_3, CONST_512, TMP26); - - vis_faligndata(TMP4, TMP6, REF_2); - - vis_padd16(TMP8, TMP12, TMP8); - - vis_padd16(TMP10, TMP14, TMP10); - vis_mul8x16au(REF_2, CONST_256, TMP20); - - vis_padd16(TMP8, TMP16, TMP0); - vis_mul8x16au(REF_2_1, CONST_256, TMP22); - - vis_padd16(TMP10, TMP18, TMP2); - vis_pack16(TMP0, DST_0); - - vis_pack16(TMP2, DST_1); - vis_st64(DST_0, dest[0]); - dest += stride; - vis_padd16(TMP12, TMP20, TMP12); - - vis_padd16(TMP14, TMP22, TMP14); - - vis_padd16(TMP12, TMP24, TMP0); - - vis_padd16(TMP14, TMP26, TMP2); - vis_pack16(TMP0, DST_2); - - vis_pack16(TMP2, DST_3); - vis_st64(DST_2, dest[0]); - dest += stride; - } while (--height); -} - -static void MC_put_xy_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - int stride_8 = stride + 8; - int stride_16 = stride + 16; - - vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); - - ref = vis_alignaddr(ref); - - vis_ld64(ref[ 0], TMP0); - vis_fzero(ZERO); - - vis_ld64(ref[ 8], TMP2); - - vis_ld64(ref[16], TMP4); - - vis_ld64(constants2[0], CONST_2); - vis_faligndata(TMP0, TMP2, REF_S0); - - vis_ld64(constants256_512[0], CONST_256); - vis_faligndata(TMP2, TMP4, REF_S4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_S2); - vis_faligndata(TMP2, TMP4, REF_S6); - } else { - vis_src1(TMP2, REF_S2); - vis_src1(TMP4, REF_S6); - } - - height >>= 1; - do { - vis_ld64_2(ref, stride, TMP0); - vis_mul8x16au(REF_S0, CONST_256, TMP12); - vis_pmerge(ZERO, REF_S0_1, TMP14); - - vis_alignaddr_g0((void *)off); - - vis_ld64_2(ref, stride_8, TMP2); - vis_mul8x16au(REF_S2, CONST_256, TMP16); - vis_pmerge(ZERO, REF_S2_1, TMP18); - - vis_ld64_2(ref, stride_16, TMP4); - ref += stride; - vis_mul8x16au(REF_S4, CONST_256, TMP20); - vis_pmerge(ZERO, REF_S4_1, TMP22); - - vis_ld64_2(ref, stride, TMP6); - vis_mul8x16au(REF_S6, CONST_256, TMP24); - vis_pmerge(ZERO, REF_S6_1, TMP26); - - vis_ld64_2(ref, stride_8, TMP8); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(ref, stride_16, TMP10); - ref += stride; - vis_faligndata(TMP2, TMP4, REF_4); - - vis_faligndata(TMP6, TMP8, REF_S0); - - vis_faligndata(TMP8, TMP10, REF_S4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - vis_faligndata(TMP2, TMP4, REF_6); - vis_faligndata(TMP6, TMP8, REF_S2); - vis_faligndata(TMP8, TMP10, REF_S6); - } else { - vis_src1(TMP2, REF_2); - vis_src1(TMP4, REF_6); - vis_src1(TMP8, REF_S2); - vis_src1(TMP10, REF_S6); - } - - vis_mul8x16au(REF_0, CONST_256, TMP0); - vis_pmerge(ZERO, REF_0_1, TMP2); - - vis_mul8x16au(REF_2, CONST_256, TMP4); - vis_pmerge(ZERO, REF_2_1, TMP6); - - vis_padd16(TMP0, CONST_2, TMP8); - vis_mul8x16au(REF_4, CONST_256, TMP0); - - vis_padd16(TMP2, CONST_2, TMP10); - vis_mul8x16au(REF_4_1, CONST_256, TMP2); - - vis_padd16(TMP8, TMP4, TMP8); - vis_mul8x16au(REF_6, CONST_256, TMP4); - - vis_padd16(TMP10, TMP6, TMP10); - vis_mul8x16au(REF_6_1, CONST_256, TMP6); - - vis_padd16(TMP12, TMP8, TMP12); - - vis_padd16(TMP14, TMP10, TMP14); - - vis_padd16(TMP12, TMP16, TMP12); - - vis_padd16(TMP14, TMP18, TMP14); - vis_pack16(TMP12, DST_0); - - vis_pack16(TMP14, DST_1); - vis_st64(DST_0, dest[0]); - vis_padd16(TMP0, CONST_2, TMP12); - - vis_mul8x16au(REF_S0, CONST_256, TMP0); - vis_padd16(TMP2, CONST_2, TMP14); - - vis_mul8x16au(REF_S0_1, CONST_256, TMP2); - vis_padd16(TMP12, TMP4, TMP12); - - vis_mul8x16au(REF_S2, CONST_256, TMP4); - vis_padd16(TMP14, TMP6, TMP14); - - vis_mul8x16au(REF_S2_1, CONST_256, TMP6); - vis_padd16(TMP20, TMP12, TMP20); - - vis_padd16(TMP22, TMP14, TMP22); - - vis_padd16(TMP20, TMP24, TMP20); - - vis_padd16(TMP22, TMP26, TMP22); - vis_pack16(TMP20, DST_2); - - vis_pack16(TMP22, DST_3); - vis_st64_2(DST_2, dest, 8); - dest += stride; - vis_padd16(TMP0, TMP4, TMP24); - - vis_mul8x16au(REF_S4, CONST_256, TMP0); - vis_padd16(TMP2, TMP6, TMP26); - - vis_mul8x16au(REF_S4_1, CONST_256, TMP2); - vis_padd16(TMP24, TMP8, TMP24); - - vis_padd16(TMP26, TMP10, TMP26); - vis_pack16(TMP24, DST_0); - - vis_pack16(TMP26, DST_1); - vis_st64(DST_0, dest[0]); - vis_pmerge(ZERO, REF_S6, TMP4); - - vis_pmerge(ZERO, REF_S6_1, TMP6); - - vis_padd16(TMP0, TMP4, TMP0); - - vis_padd16(TMP2, TMP6, TMP2); - - vis_padd16(TMP0, TMP12, TMP0); - - vis_padd16(TMP2, TMP14, TMP2); - vis_pack16(TMP0, DST_2); - - vis_pack16(TMP2, DST_3); - vis_st64_2(DST_2, dest, 8); - dest += stride; - } while (--height); -} - -static void MC_put_xy_8_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - int stride_8 = stride + 8; - - vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); - - ref = vis_alignaddr(ref); - - vis_ld64(ref[ 0], TMP0); - vis_fzero(ZERO); - - vis_ld64(ref[ 8], TMP2); - - vis_ld64(constants2[0], CONST_2); - - vis_ld64(constants256_512[0], CONST_256); - vis_faligndata(TMP0, TMP2, REF_S0); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_S2); - } else { - vis_src1(TMP2, REF_S2); - } - - height >>= 1; - do { /* 26 cycles */ - vis_ld64_2(ref, stride, TMP0); - vis_mul8x16au(REF_S0, CONST_256, TMP8); - vis_pmerge(ZERO, REF_S2, TMP12); - - vis_alignaddr_g0((void *)off); - - vis_ld64_2(ref, stride_8, TMP2); - ref += stride; - vis_mul8x16au(REF_S0_1, CONST_256, TMP10); - vis_pmerge(ZERO, REF_S2_1, TMP14); - - vis_ld64_2(ref, stride, TMP4); - - vis_ld64_2(ref, stride_8, TMP6); - ref += stride; - vis_faligndata(TMP0, TMP2, REF_S4); - - vis_pmerge(ZERO, REF_S4, TMP18); - - vis_pmerge(ZERO, REF_S4_1, TMP20); - - vis_faligndata(TMP4, TMP6, REF_S0); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_S6); - vis_faligndata(TMP4, TMP6, REF_S2); - } else { - vis_src1(TMP2, REF_S6); - vis_src1(TMP6, REF_S2); - } - - vis_padd16(TMP18, CONST_2, TMP18); - vis_mul8x16au(REF_S6, CONST_256, TMP22); - - vis_padd16(TMP20, CONST_2, TMP20); - vis_mul8x16au(REF_S6_1, CONST_256, TMP24); - - vis_mul8x16au(REF_S0, CONST_256, TMP26); - vis_pmerge(ZERO, REF_S0_1, TMP28); - - vis_mul8x16au(REF_S2, CONST_256, TMP30); - vis_padd16(TMP18, TMP22, TMP18); - - vis_mul8x16au(REF_S2_1, CONST_256, TMP32); - vis_padd16(TMP20, TMP24, TMP20); - - vis_padd16(TMP8, TMP18, TMP8); - - vis_padd16(TMP10, TMP20, TMP10); - - vis_padd16(TMP8, TMP12, TMP8); - - vis_padd16(TMP10, TMP14, TMP10); - vis_pack16(TMP8, DST_0); - - vis_pack16(TMP10, DST_1); - vis_st64(DST_0, dest[0]); - dest += stride; - vis_padd16(TMP18, TMP26, TMP18); - - vis_padd16(TMP20, TMP28, TMP20); - - vis_padd16(TMP18, TMP30, TMP18); - - vis_padd16(TMP20, TMP32, TMP20); - vis_pack16(TMP18, DST_2); - - vis_pack16(TMP20, DST_3); - vis_st64(DST_2, dest[0]); - dest += stride; - } while (--height); -} - -static void MC_avg_xy_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - int stride_8 = stride + 8; - int stride_16 = stride + 16; - - vis_set_gsr(4 << VIS_GSR_SCALEFACT_SHIFT); - - ref = vis_alignaddr(ref); - - vis_ld64(ref[ 0], TMP0); - vis_fzero(ZERO); - - vis_ld64(ref[ 8], TMP2); - - vis_ld64(ref[16], TMP4); - - vis_ld64(constants6[0], CONST_6); - vis_faligndata(TMP0, TMP2, REF_S0); - - vis_ld64(constants256_1024[0], CONST_256); - vis_faligndata(TMP2, TMP4, REF_S4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_S2); - vis_faligndata(TMP2, TMP4, REF_S6); - } else { - vis_src1(TMP2, REF_S2); - vis_src1(TMP4, REF_S6); - } - - height >>= 1; - do { /* 55 cycles */ - vis_ld64_2(ref, stride, TMP0); - vis_mul8x16au(REF_S0, CONST_256, TMP12); - vis_pmerge(ZERO, REF_S0_1, TMP14); - - vis_alignaddr_g0((void *)off); - - vis_ld64_2(ref, stride_8, TMP2); - vis_mul8x16au(REF_S2, CONST_256, TMP16); - vis_pmerge(ZERO, REF_S2_1, TMP18); - - vis_ld64_2(ref, stride_16, TMP4); - ref += stride; - vis_mul8x16au(REF_S4, CONST_256, TMP20); - vis_pmerge(ZERO, REF_S4_1, TMP22); - - vis_ld64_2(ref, stride, TMP6); - vis_mul8x16au(REF_S6, CONST_256, TMP24); - vis_pmerge(ZERO, REF_S6_1, TMP26); - - vis_ld64_2(ref, stride_8, TMP8); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(ref, stride_16, TMP10); - ref += stride; - vis_faligndata(TMP2, TMP4, REF_4); - - vis_ld64(dest[0], DST_0); - vis_faligndata(TMP6, TMP8, REF_S0); - - vis_ld64_2(dest, 8, DST_2); - vis_faligndata(TMP8, TMP10, REF_S4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - vis_faligndata(TMP2, TMP4, REF_6); - vis_faligndata(TMP6, TMP8, REF_S2); - vis_faligndata(TMP8, TMP10, REF_S6); - } else { - vis_src1(TMP2, REF_2); - vis_src1(TMP4, REF_6); - vis_src1(TMP8, REF_S2); - vis_src1(TMP10, REF_S6); - } - - vis_mul8x16al(DST_0, CONST_1024, TMP30); - vis_pmerge(ZERO, REF_0, TMP0); - - vis_mul8x16al(DST_1, CONST_1024, TMP32); - vis_pmerge(ZERO, REF_0_1, TMP2); - - vis_mul8x16au(REF_2, CONST_256, TMP4); - vis_pmerge(ZERO, REF_2_1, TMP6); - - vis_mul8x16al(DST_2, CONST_1024, REF_0); - vis_padd16(TMP0, CONST_6, TMP0); - - vis_mul8x16al(DST_3, CONST_1024, REF_2); - vis_padd16(TMP2, CONST_6, TMP2); - - vis_padd16(TMP0, TMP4, TMP0); - vis_mul8x16au(REF_4, CONST_256, TMP4); - - vis_padd16(TMP2, TMP6, TMP2); - vis_mul8x16au(REF_4_1, CONST_256, TMP6); - - vis_padd16(TMP12, TMP0, TMP12); - vis_mul8x16au(REF_6, CONST_256, TMP8); - - vis_padd16(TMP14, TMP2, TMP14); - vis_mul8x16au(REF_6_1, CONST_256, TMP10); - - vis_padd16(TMP12, TMP16, TMP12); - vis_mul8x16au(REF_S0, CONST_256, REF_4); - - vis_padd16(TMP14, TMP18, TMP14); - vis_mul8x16au(REF_S0_1, CONST_256, REF_6); - - vis_padd16(TMP12, TMP30, TMP12); - - vis_padd16(TMP14, TMP32, TMP14); - vis_pack16(TMP12, DST_0); - - vis_pack16(TMP14, DST_1); - vis_st64(DST_0, dest[0]); - vis_padd16(TMP4, CONST_6, TMP4); - - vis_ld64_2(dest, stride, DST_0); - vis_padd16(TMP6, CONST_6, TMP6); - vis_mul8x16au(REF_S2, CONST_256, TMP12); - - vis_padd16(TMP4, TMP8, TMP4); - vis_mul8x16au(REF_S2_1, CONST_256, TMP14); - - vis_padd16(TMP6, TMP10, TMP6); - - vis_padd16(TMP20, TMP4, TMP20); - - vis_padd16(TMP22, TMP6, TMP22); - - vis_padd16(TMP20, TMP24, TMP20); - - vis_padd16(TMP22, TMP26, TMP22); - - vis_padd16(TMP20, REF_0, TMP20); - vis_mul8x16au(REF_S4, CONST_256, REF_0); - - vis_padd16(TMP22, REF_2, TMP22); - vis_pack16(TMP20, DST_2); - - vis_pack16(TMP22, DST_3); - vis_st64_2(DST_2, dest, 8); - dest += stride; - - vis_ld64_2(dest, 8, DST_2); - vis_mul8x16al(DST_0, CONST_1024, TMP30); - vis_pmerge(ZERO, REF_S4_1, REF_2); - - vis_mul8x16al(DST_1, CONST_1024, TMP32); - vis_padd16(REF_4, TMP0, TMP8); - - vis_mul8x16au(REF_S6, CONST_256, REF_4); - vis_padd16(REF_6, TMP2, TMP10); - - vis_mul8x16au(REF_S6_1, CONST_256, REF_6); - vis_padd16(TMP8, TMP12, TMP8); - - vis_padd16(TMP10, TMP14, TMP10); - - vis_padd16(TMP8, TMP30, TMP8); - - vis_padd16(TMP10, TMP32, TMP10); - vis_pack16(TMP8, DST_0); - - vis_pack16(TMP10, DST_1); - vis_st64(DST_0, dest[0]); - - vis_padd16(REF_0, TMP4, REF_0); - - vis_mul8x16al(DST_2, CONST_1024, TMP30); - vis_padd16(REF_2, TMP6, REF_2); - - vis_mul8x16al(DST_3, CONST_1024, TMP32); - vis_padd16(REF_0, REF_4, REF_0); - - vis_padd16(REF_2, REF_6, REF_2); - - vis_padd16(REF_0, TMP30, REF_0); - - /* stall */ - - vis_padd16(REF_2, TMP32, REF_2); - vis_pack16(REF_0, DST_2); - - vis_pack16(REF_2, DST_3); - vis_st64_2(DST_2, dest, 8); - dest += stride; - } while (--height); -} - -static void MC_avg_xy_8_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - int stride_8 = stride + 8; - - vis_set_gsr(4 << VIS_GSR_SCALEFACT_SHIFT); - - ref = vis_alignaddr(ref); - - vis_ld64(ref[0], TMP0); - vis_fzero(ZERO); - - vis_ld64_2(ref, 8, TMP2); - - vis_ld64(constants6[0], CONST_6); - - vis_ld64(constants256_1024[0], CONST_256); - vis_faligndata(TMP0, TMP2, REF_S0); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_S2); - } else { - vis_src1(TMP2, REF_S2); - } - - height >>= 1; - do { /* 31 cycles */ - vis_ld64_2(ref, stride, TMP0); - vis_mul8x16au(REF_S0, CONST_256, TMP8); - vis_pmerge(ZERO, REF_S0_1, TMP10); - - vis_ld64_2(ref, stride_8, TMP2); - ref += stride; - vis_mul8x16au(REF_S2, CONST_256, TMP12); - vis_pmerge(ZERO, REF_S2_1, TMP14); - - vis_alignaddr_g0((void *)off); - - vis_ld64_2(ref, stride, TMP4); - vis_faligndata(TMP0, TMP2, REF_S4); - - vis_ld64_2(ref, stride_8, TMP6); - ref += stride; - - vis_ld64(dest[0], DST_0); - vis_faligndata(TMP4, TMP6, REF_S0); - - vis_ld64_2(dest, stride, DST_2); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_S6); - vis_faligndata(TMP4, TMP6, REF_S2); - } else { - vis_src1(TMP2, REF_S6); - vis_src1(TMP6, REF_S2); - } - - vis_mul8x16al(DST_0, CONST_1024, TMP30); - vis_pmerge(ZERO, REF_S4, TMP22); - - vis_mul8x16al(DST_1, CONST_1024, TMP32); - vis_pmerge(ZERO, REF_S4_1, TMP24); - - vis_mul8x16au(REF_S6, CONST_256, TMP26); - vis_pmerge(ZERO, REF_S6_1, TMP28); - - vis_mul8x16au(REF_S0, CONST_256, REF_S4); - vis_padd16(TMP22, CONST_6, TMP22); - - vis_mul8x16au(REF_S0_1, CONST_256, REF_S6); - vis_padd16(TMP24, CONST_6, TMP24); - - vis_mul8x16al(DST_2, CONST_1024, REF_0); - vis_padd16(TMP22, TMP26, TMP22); - - vis_mul8x16al(DST_3, CONST_1024, REF_2); - vis_padd16(TMP24, TMP28, TMP24); - - vis_mul8x16au(REF_S2, CONST_256, TMP26); - vis_padd16(TMP8, TMP22, TMP8); - - vis_mul8x16au(REF_S2_1, CONST_256, TMP28); - vis_padd16(TMP10, TMP24, TMP10); - - vis_padd16(TMP8, TMP12, TMP8); - - vis_padd16(TMP10, TMP14, TMP10); - - vis_padd16(TMP8, TMP30, TMP8); - - vis_padd16(TMP10, TMP32, TMP10); - vis_pack16(TMP8, DST_0); - - vis_pack16(TMP10, DST_1); - vis_st64(DST_0, dest[0]); - dest += stride; - - vis_padd16(REF_S4, TMP22, TMP12); - - vis_padd16(REF_S6, TMP24, TMP14); - - vis_padd16(TMP12, TMP26, TMP12); - - vis_padd16(TMP14, TMP28, TMP14); - - vis_padd16(TMP12, REF_0, TMP12); - - vis_padd16(TMP14, REF_2, TMP14); - vis_pack16(TMP12, DST_2); - - vis_pack16(TMP14, DST_3); - vis_st64(DST_2, dest[0]); - dest += stride; - } while (--height); -} - -/* End of rounding code */ - -/* Start of no rounding code */ -/* The trick used in some of this file is the formula from the MMX - * motion comp code, which is: - * - * (x+y)>>1 == (x&y)+((x^y)>>1) - * - * This allows us to average 8 bytes at a time in a 64-bit FPU reg. - * We avoid overflows by masking before we do the shift, and we - * implement the shift by multiplying by 1/2 using mul8x16. So in - * VIS this is (assume 'x' is in f0, 'y' is in f2, a repeating mask - * of '0xfe' is in f4, a repeating mask of '0x7f' is in f6, and - * the value 0x80808080 is in f8): - * - * fxor f0, f2, f10 - * fand f10, f4, f10 - * fmul8x16 f8, f10, f10 - * fand f10, f6, f10 - * fand f0, f2, f12 - * fpadd16 f12, f10, f10 - */ - -static void MC_put_no_round_o_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - ref = vis_alignaddr(ref); - do { /* 5 cycles */ - vis_ld64(ref[0], TMP0); - - vis_ld64_2(ref, 8, TMP2); - - vis_ld64_2(ref, 16, TMP4); - ref += stride; - - vis_faligndata(TMP0, TMP2, REF_0); - vis_st64(REF_0, dest[0]); - - vis_faligndata(TMP2, TMP4, REF_2); - vis_st64_2(REF_2, dest, 8); - dest += stride; - } while (--height); -} - -static void MC_put_no_round_o_8_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - ref = vis_alignaddr(ref); - do { /* 4 cycles */ - vis_ld64(ref[0], TMP0); - - vis_ld64(ref[8], TMP2); - ref += stride; - - /* stall */ - - vis_faligndata(TMP0, TMP2, REF_0); - vis_st64(REF_0, dest[0]); - dest += stride; - } while (--height); -} - - -static void MC_avg_no_round_o_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - int stride_8 = stride + 8; - - ref = vis_alignaddr(ref); - - vis_ld64(ref[0], TMP0); - - vis_ld64(ref[8], TMP2); - - vis_ld64(ref[16], TMP4); - - vis_ld64(dest[0], DST_0); - - vis_ld64(dest[8], DST_2); - - vis_ld64(constants_fe[0], MASK_fe); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64(constants_7f[0], MASK_7f); - vis_faligndata(TMP2, TMP4, REF_2); - - vis_ld64(constants128[0], CONST_128); - - ref += stride; - height = (height >> 1) - 1; - - do { /* 24 cycles */ - vis_ld64(ref[0], TMP0); - vis_xor(DST_0, REF_0, TMP6); - - vis_ld64_2(ref, 8, TMP2); - vis_and(TMP6, MASK_fe, TMP6); - - vis_ld64_2(ref, 16, TMP4); - ref += stride; - vis_mul8x16(CONST_128, TMP6, TMP6); - vis_xor(DST_2, REF_2, TMP8); - - vis_and(TMP8, MASK_fe, TMP8); - - vis_and(DST_0, REF_0, TMP10); - vis_ld64_2(dest, stride, DST_0); - vis_mul8x16(CONST_128, TMP8, TMP8); - - vis_and(DST_2, REF_2, TMP12); - vis_ld64_2(dest, stride_8, DST_2); - - vis_ld64(ref[0], TMP14); - vis_and(TMP6, MASK_7f, TMP6); - - vis_and(TMP8, MASK_7f, TMP8); - - vis_padd16(TMP10, TMP6, TMP6); - vis_st64(TMP6, dest[0]); - - vis_padd16(TMP12, TMP8, TMP8); - vis_st64_2(TMP8, dest, 8); - - dest += stride; - vis_ld64_2(ref, 8, TMP16); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(ref, 16, TMP18); - vis_faligndata(TMP2, TMP4, REF_2); - ref += stride; - - vis_xor(DST_0, REF_0, TMP20); - - vis_and(TMP20, MASK_fe, TMP20); - - vis_xor(DST_2, REF_2, TMP22); - vis_mul8x16(CONST_128, TMP20, TMP20); - - vis_and(TMP22, MASK_fe, TMP22); - - vis_and(DST_0, REF_0, TMP24); - vis_mul8x16(CONST_128, TMP22, TMP22); - - vis_and(DST_2, REF_2, TMP26); - - vis_ld64_2(dest, stride, DST_0); - vis_faligndata(TMP14, TMP16, REF_0); - - vis_ld64_2(dest, stride_8, DST_2); - vis_faligndata(TMP16, TMP18, REF_2); - - vis_and(TMP20, MASK_7f, TMP20); - - vis_and(TMP22, MASK_7f, TMP22); - - vis_padd16(TMP24, TMP20, TMP20); - vis_st64(TMP20, dest[0]); - - vis_padd16(TMP26, TMP22, TMP22); - vis_st64_2(TMP22, dest, 8); - dest += stride; - } while (--height); - - vis_ld64(ref[0], TMP0); - vis_xor(DST_0, REF_0, TMP6); - - vis_ld64_2(ref, 8, TMP2); - vis_and(TMP6, MASK_fe, TMP6); - - vis_ld64_2(ref, 16, TMP4); - vis_mul8x16(CONST_128, TMP6, TMP6); - vis_xor(DST_2, REF_2, TMP8); - - vis_and(TMP8, MASK_fe, TMP8); - - vis_and(DST_0, REF_0, TMP10); - vis_ld64_2(dest, stride, DST_0); - vis_mul8x16(CONST_128, TMP8, TMP8); - - vis_and(DST_2, REF_2, TMP12); - vis_ld64_2(dest, stride_8, DST_2); - - vis_ld64(ref[0], TMP14); - vis_and(TMP6, MASK_7f, TMP6); - - vis_and(TMP8, MASK_7f, TMP8); - - vis_padd16(TMP10, TMP6, TMP6); - vis_st64(TMP6, dest[0]); - - vis_padd16(TMP12, TMP8, TMP8); - vis_st64_2(TMP8, dest, 8); - - dest += stride; - vis_faligndata(TMP0, TMP2, REF_0); - - vis_faligndata(TMP2, TMP4, REF_2); - - vis_xor(DST_0, REF_0, TMP20); - - vis_and(TMP20, MASK_fe, TMP20); - - vis_xor(DST_2, REF_2, TMP22); - vis_mul8x16(CONST_128, TMP20, TMP20); - - vis_and(TMP22, MASK_fe, TMP22); - - vis_and(DST_0, REF_0, TMP24); - vis_mul8x16(CONST_128, TMP22, TMP22); - - vis_and(DST_2, REF_2, TMP26); - - vis_and(TMP20, MASK_7f, TMP20); - - vis_and(TMP22, MASK_7f, TMP22); - - vis_padd16(TMP24, TMP20, TMP20); - vis_st64(TMP20, dest[0]); - - vis_padd16(TMP26, TMP22, TMP22); - vis_st64_2(TMP22, dest, 8); -} - -static void MC_put_no_round_x_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - - ref = vis_alignaddr(ref); - - vis_ld64(ref[0], TMP0); - - vis_ld64_2(ref, 8, TMP2); - - vis_ld64_2(ref, 16, TMP4); - - vis_ld64(constants_fe[0], MASK_fe); - - vis_ld64(constants_7f[0], MASK_7f); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64(constants128[0], CONST_128); - vis_faligndata(TMP2, TMP4, REF_4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - vis_faligndata(TMP2, TMP4, REF_6); - } else { - vis_src1(TMP2, REF_2); - vis_src1(TMP4, REF_6); - } - - ref += stride; - height = (height >> 1) - 1; - - do { /* 34 cycles */ - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP6); - - vis_ld64_2(ref, 8, TMP2); - vis_xor(REF_4, REF_6, TMP8); - - vis_ld64_2(ref, 16, TMP4); - vis_and(TMP6, MASK_fe, TMP6); - ref += stride; - - vis_ld64(ref[0], TMP14); - vis_mul8x16(CONST_128, TMP6, TMP6); - vis_and(TMP8, MASK_fe, TMP8); - - vis_ld64_2(ref, 8, TMP16); - vis_mul8x16(CONST_128, TMP8, TMP8); - vis_and(REF_0, REF_2, TMP10); - - vis_ld64_2(ref, 16, TMP18); - ref += stride; - vis_and(REF_4, REF_6, TMP12); - - vis_alignaddr_g0((void *)off); - - vis_faligndata(TMP0, TMP2, REF_0); - - vis_faligndata(TMP2, TMP4, REF_4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - vis_faligndata(TMP2, TMP4, REF_6); - } else { - vis_src1(TMP2, REF_2); - vis_src1(TMP4, REF_6); - } - - vis_and(TMP6, MASK_7f, TMP6); - - vis_and(TMP8, MASK_7f, TMP8); - - vis_padd16(TMP10, TMP6, TMP6); - vis_st64(TMP6, dest[0]); - - vis_padd16(TMP12, TMP8, TMP8); - vis_st64_2(TMP8, dest, 8); - dest += stride; - - vis_xor(REF_0, REF_2, TMP6); - - vis_xor(REF_4, REF_6, TMP8); - - vis_and(TMP6, MASK_fe, TMP6); - - vis_mul8x16(CONST_128, TMP6, TMP6); - vis_and(TMP8, MASK_fe, TMP8); - - vis_mul8x16(CONST_128, TMP8, TMP8); - vis_and(REF_0, REF_2, TMP10); - - vis_and(REF_4, REF_6, TMP12); - - vis_alignaddr_g0((void *)off); - - vis_faligndata(TMP14, TMP16, REF_0); - - vis_faligndata(TMP16, TMP18, REF_4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP14, TMP16, REF_2); - vis_faligndata(TMP16, TMP18, REF_6); - } else { - vis_src1(TMP16, REF_2); - vis_src1(TMP18, REF_6); - } - - vis_and(TMP6, MASK_7f, TMP6); - - vis_and(TMP8, MASK_7f, TMP8); - - vis_padd16(TMP10, TMP6, TMP6); - vis_st64(TMP6, dest[0]); - - vis_padd16(TMP12, TMP8, TMP8); - vis_st64_2(TMP8, dest, 8); - dest += stride; - } while (--height); - - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP6); - - vis_ld64_2(ref, 8, TMP2); - vis_xor(REF_4, REF_6, TMP8); - - vis_ld64_2(ref, 16, TMP4); - vis_and(TMP6, MASK_fe, TMP6); - - vis_mul8x16(CONST_128, TMP6, TMP6); - vis_and(TMP8, MASK_fe, TMP8); - - vis_mul8x16(CONST_128, TMP8, TMP8); - vis_and(REF_0, REF_2, TMP10); - - vis_and(REF_4, REF_6, TMP12); - - vis_alignaddr_g0((void *)off); - - vis_faligndata(TMP0, TMP2, REF_0); - - vis_faligndata(TMP2, TMP4, REF_4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - vis_faligndata(TMP2, TMP4, REF_6); - } else { - vis_src1(TMP2, REF_2); - vis_src1(TMP4, REF_6); - } - - vis_and(TMP6, MASK_7f, TMP6); - - vis_and(TMP8, MASK_7f, TMP8); - - vis_padd16(TMP10, TMP6, TMP6); - vis_st64(TMP6, dest[0]); - - vis_padd16(TMP12, TMP8, TMP8); - vis_st64_2(TMP8, dest, 8); - dest += stride; - - vis_xor(REF_0, REF_2, TMP6); - - vis_xor(REF_4, REF_6, TMP8); - - vis_and(TMP6, MASK_fe, TMP6); - - vis_mul8x16(CONST_128, TMP6, TMP6); - vis_and(TMP8, MASK_fe, TMP8); - - vis_mul8x16(CONST_128, TMP8, TMP8); - vis_and(REF_0, REF_2, TMP10); - - vis_and(REF_4, REF_6, TMP12); - - vis_and(TMP6, MASK_7f, TMP6); - - vis_and(TMP8, MASK_7f, TMP8); - - vis_padd16(TMP10, TMP6, TMP6); - vis_st64(TMP6, dest[0]); - - vis_padd16(TMP12, TMP8, TMP8); - vis_st64_2(TMP8, dest, 8); -} - -static void MC_put_no_round_x_8_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - - ref = vis_alignaddr(ref); - - vis_ld64(ref[0], TMP0); - - vis_ld64(ref[8], TMP2); - - vis_ld64(constants_fe[0], MASK_fe); - - vis_ld64(constants_7f[0], MASK_7f); - - vis_ld64(constants128[0], CONST_128); - vis_faligndata(TMP0, TMP2, REF_0); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - } else { - vis_src1(TMP2, REF_2); - } - - ref += stride; - height = (height >> 1) - 1; - - do { /* 20 cycles */ - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP4); - - vis_ld64_2(ref, 8, TMP2); - vis_and(TMP4, MASK_fe, TMP4); - ref += stride; - - vis_ld64(ref[0], TMP8); - vis_and(REF_0, REF_2, TMP6); - vis_mul8x16(CONST_128, TMP4, TMP4); - - vis_alignaddr_g0((void *)off); - - vis_ld64_2(ref, 8, TMP10); - ref += stride; - vis_faligndata(TMP0, TMP2, REF_0); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - } else { - vis_src1(TMP2, REF_2); - } - - vis_and(TMP4, MASK_7f, TMP4); - - vis_padd16(TMP6, TMP4, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; - - vis_xor(REF_0, REF_2, TMP12); - - vis_and(TMP12, MASK_fe, TMP12); - - vis_and(REF_0, REF_2, TMP14); - vis_mul8x16(CONST_128, TMP12, TMP12); - - vis_alignaddr_g0((void *)off); - vis_faligndata(TMP8, TMP10, REF_0); - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP8, TMP10, REF_2); - } else { - vis_src1(TMP10, REF_2); - } - - vis_and(TMP12, MASK_7f, TMP12); - - vis_padd16(TMP14, TMP12, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; - } while (--height); - - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP4); - - vis_ld64_2(ref, 8, TMP2); - vis_and(TMP4, MASK_fe, TMP4); - - vis_and(REF_0, REF_2, TMP6); - vis_mul8x16(CONST_128, TMP4, TMP4); - - vis_alignaddr_g0((void *)off); - - vis_faligndata(TMP0, TMP2, REF_0); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - } else { - vis_src1(TMP2, REF_2); - } - - vis_and(TMP4, MASK_7f, TMP4); - - vis_padd16(TMP6, TMP4, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; - - vis_xor(REF_0, REF_2, TMP12); - - vis_and(TMP12, MASK_fe, TMP12); - - vis_and(REF_0, REF_2, TMP14); - vis_mul8x16(CONST_128, TMP12, TMP12); - - vis_and(TMP12, MASK_7f, TMP12); - - vis_padd16(TMP14, TMP12, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; -} - -static void MC_avg_no_round_x_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - - vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); - - vis_ld64(constants3[0], CONST_3); - vis_fzero(ZERO); - vis_ld64(constants256_512[0], CONST_256); - - ref = vis_alignaddr(ref); - do { /* 26 cycles */ - vis_ld64(ref[0], TMP0); - - vis_ld64(ref[8], TMP2); - - vis_alignaddr_g0((void *)off); - - vis_ld64(ref[16], TMP4); - - vis_ld64(dest[0], DST_0); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64(dest[8], DST_2); - vis_faligndata(TMP2, TMP4, REF_4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - vis_faligndata(TMP2, TMP4, REF_6); - } else { - vis_src1(TMP2, REF_2); - vis_src1(TMP4, REF_6); - } - - vis_mul8x16au(REF_0, CONST_256, TMP0); - - vis_pmerge(ZERO, REF_2, TMP4); - vis_mul8x16au(REF_0_1, CONST_256, TMP2); - - vis_pmerge(ZERO, REF_2_1, TMP6); - - vis_padd16(TMP0, TMP4, TMP0); - - vis_mul8x16al(DST_0, CONST_512, TMP4); - vis_padd16(TMP2, TMP6, TMP2); - - vis_mul8x16al(DST_1, CONST_512, TMP6); - - vis_mul8x16au(REF_6, CONST_256, TMP12); - - vis_padd16(TMP0, TMP4, TMP0); - vis_mul8x16au(REF_6_1, CONST_256, TMP14); - - vis_padd16(TMP2, TMP6, TMP2); - vis_mul8x16au(REF_4, CONST_256, TMP16); - - vis_padd16(TMP0, CONST_3, TMP8); - vis_mul8x16au(REF_4_1, CONST_256, TMP18); - - vis_padd16(TMP2, CONST_3, TMP10); - vis_pack16(TMP8, DST_0); - - vis_pack16(TMP10, DST_1); - vis_padd16(TMP16, TMP12, TMP0); - - vis_st64(DST_0, dest[0]); - vis_mul8x16al(DST_2, CONST_512, TMP4); - vis_padd16(TMP18, TMP14, TMP2); - - vis_mul8x16al(DST_3, CONST_512, TMP6); - vis_padd16(TMP0, CONST_3, TMP0); - - vis_padd16(TMP2, CONST_3, TMP2); - - vis_padd16(TMP0, TMP4, TMP0); - - vis_padd16(TMP2, TMP6, TMP2); - vis_pack16(TMP0, DST_2); - - vis_pack16(TMP2, DST_3); - vis_st64(DST_2, dest[8]); - - ref += stride; - dest += stride; - } while (--height); -} - -static void MC_put_no_round_y_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - ref = vis_alignaddr(ref); - vis_ld64(ref[0], TMP0); - - vis_ld64_2(ref, 8, TMP2); - - vis_ld64_2(ref, 16, TMP4); - ref += stride; - - vis_ld64(ref[0], TMP6); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(ref, 8, TMP8); - vis_faligndata(TMP2, TMP4, REF_4); - - vis_ld64_2(ref, 16, TMP10); - ref += stride; - - vis_ld64(constants_fe[0], MASK_fe); - vis_faligndata(TMP6, TMP8, REF_2); - - vis_ld64(constants_7f[0], MASK_7f); - vis_faligndata(TMP8, TMP10, REF_6); - - vis_ld64(constants128[0], CONST_128); - height = (height >> 1) - 1; - do { /* 24 cycles */ - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP12); - - vis_ld64_2(ref, 8, TMP2); - vis_xor(REF_4, REF_6, TMP16); - - vis_ld64_2(ref, 16, TMP4); - ref += stride; - vis_and(REF_0, REF_2, TMP14); - - vis_ld64(ref[0], TMP6); - vis_and(REF_4, REF_6, TMP18); - - vis_ld64_2(ref, 8, TMP8); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(ref, 16, TMP10); - ref += stride; - vis_faligndata(TMP2, TMP4, REF_4); - - vis_and(TMP12, MASK_fe, TMP12); - - vis_and(TMP16, MASK_fe, TMP16); - vis_mul8x16(CONST_128, TMP12, TMP12); - - vis_mul8x16(CONST_128, TMP16, TMP16); - vis_xor(REF_0, REF_2, TMP0); - - vis_xor(REF_4, REF_6, TMP2); - - vis_and(REF_0, REF_2, TMP20); - - vis_and(TMP12, MASK_7f, TMP12); - - vis_and(TMP16, MASK_7f, TMP16); - - vis_padd16(TMP14, TMP12, TMP12); - vis_st64(TMP12, dest[0]); - - vis_padd16(TMP18, TMP16, TMP16); - vis_st64_2(TMP16, dest, 8); - dest += stride; - - vis_and(REF_4, REF_6, TMP18); - - vis_and(TMP0, MASK_fe, TMP0); - - vis_and(TMP2, MASK_fe, TMP2); - vis_mul8x16(CONST_128, TMP0, TMP0); - - vis_faligndata(TMP6, TMP8, REF_2); - vis_mul8x16(CONST_128, TMP2, TMP2); - - vis_faligndata(TMP8, TMP10, REF_6); - - vis_and(TMP0, MASK_7f, TMP0); - - vis_and(TMP2, MASK_7f, TMP2); - - vis_padd16(TMP20, TMP0, TMP0); - vis_st64(TMP0, dest[0]); - - vis_padd16(TMP18, TMP2, TMP2); - vis_st64_2(TMP2, dest, 8); - dest += stride; - } while (--height); - - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP12); - - vis_ld64_2(ref, 8, TMP2); - vis_xor(REF_4, REF_6, TMP16); - - vis_ld64_2(ref, 16, TMP4); - vis_and(REF_0, REF_2, TMP14); - - vis_and(REF_4, REF_6, TMP18); - - vis_faligndata(TMP0, TMP2, REF_0); - - vis_faligndata(TMP2, TMP4, REF_4); - - vis_and(TMP12, MASK_fe, TMP12); - - vis_and(TMP16, MASK_fe, TMP16); - vis_mul8x16(CONST_128, TMP12, TMP12); - - vis_mul8x16(CONST_128, TMP16, TMP16); - vis_xor(REF_0, REF_2, TMP0); - - vis_xor(REF_4, REF_6, TMP2); - - vis_and(REF_0, REF_2, TMP20); - - vis_and(TMP12, MASK_7f, TMP12); - - vis_and(TMP16, MASK_7f, TMP16); - - vis_padd16(TMP14, TMP12, TMP12); - vis_st64(TMP12, dest[0]); - - vis_padd16(TMP18, TMP16, TMP16); - vis_st64_2(TMP16, dest, 8); - dest += stride; - - vis_and(REF_4, REF_6, TMP18); - - vis_and(TMP0, MASK_fe, TMP0); - - vis_and(TMP2, MASK_fe, TMP2); - vis_mul8x16(CONST_128, TMP0, TMP0); - - vis_mul8x16(CONST_128, TMP2, TMP2); - - vis_and(TMP0, MASK_7f, TMP0); - - vis_and(TMP2, MASK_7f, TMP2); - - vis_padd16(TMP20, TMP0, TMP0); - vis_st64(TMP0, dest[0]); - - vis_padd16(TMP18, TMP2, TMP2); - vis_st64_2(TMP2, dest, 8); -} - -static void MC_put_no_round_y_8_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - ref = vis_alignaddr(ref); - vis_ld64(ref[0], TMP0); - - vis_ld64_2(ref, 8, TMP2); - ref += stride; - - vis_ld64(ref[0], TMP4); - - vis_ld64_2(ref, 8, TMP6); - ref += stride; - - vis_ld64(constants_fe[0], MASK_fe); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64(constants_7f[0], MASK_7f); - vis_faligndata(TMP4, TMP6, REF_2); - - vis_ld64(constants128[0], CONST_128); - height = (height >> 1) - 1; - do { /* 12 cycles */ - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP4); - - vis_ld64_2(ref, 8, TMP2); - ref += stride; - vis_and(TMP4, MASK_fe, TMP4); - - vis_and(REF_0, REF_2, TMP6); - vis_mul8x16(CONST_128, TMP4, TMP4); - - vis_faligndata(TMP0, TMP2, REF_0); - vis_ld64(ref[0], TMP0); - - vis_ld64_2(ref, 8, TMP2); - ref += stride; - vis_xor(REF_0, REF_2, TMP12); - - vis_and(TMP4, MASK_7f, TMP4); - - vis_and(TMP12, MASK_fe, TMP12); - - vis_mul8x16(CONST_128, TMP12, TMP12); - vis_and(REF_0, REF_2, TMP14); - - vis_padd16(TMP6, TMP4, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; - - vis_faligndata(TMP0, TMP2, REF_2); - - vis_and(TMP12, MASK_7f, TMP12); - - vis_padd16(TMP14, TMP12, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; - } while (--height); - - vis_ld64(ref[0], TMP0); - vis_xor(REF_0, REF_2, TMP4); - - vis_ld64_2(ref, 8, TMP2); - vis_and(TMP4, MASK_fe, TMP4); - - vis_and(REF_0, REF_2, TMP6); - vis_mul8x16(CONST_128, TMP4, TMP4); - - vis_faligndata(TMP0, TMP2, REF_0); - - vis_xor(REF_0, REF_2, TMP12); - - vis_and(TMP4, MASK_7f, TMP4); - - vis_and(TMP12, MASK_fe, TMP12); - - vis_mul8x16(CONST_128, TMP12, TMP12); - vis_and(REF_0, REF_2, TMP14); - - vis_padd16(TMP6, TMP4, DST_0); - vis_st64(DST_0, dest[0]); - dest += stride; - - vis_and(TMP12, MASK_7f, TMP12); - - vis_padd16(TMP14, TMP12, DST_0); - vis_st64(DST_0, dest[0]); -} - -static void MC_avg_no_round_y_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - int stride_8 = stride + 8; - int stride_16 = stride + 16; - - vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); - - ref = vis_alignaddr(ref); - - vis_ld64(ref[ 0], TMP0); - vis_fzero(ZERO); - - vis_ld64(ref[ 8], TMP2); - - vis_ld64(ref[16], TMP4); - - vis_ld64(constants3[0], CONST_3); - vis_faligndata(TMP0, TMP2, REF_2); - - vis_ld64(constants256_512[0], CONST_256); - vis_faligndata(TMP2, TMP4, REF_6); - height >>= 1; - - do { /* 31 cycles */ - vis_ld64_2(ref, stride, TMP0); - vis_pmerge(ZERO, REF_2, TMP12); - vis_mul8x16au(REF_2_1, CONST_256, TMP14); - - vis_ld64_2(ref, stride_8, TMP2); - vis_pmerge(ZERO, REF_6, TMP16); - vis_mul8x16au(REF_6_1, CONST_256, TMP18); - - vis_ld64_2(ref, stride_16, TMP4); - ref += stride; - - vis_ld64(dest[0], DST_0); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(dest, 8, DST_2); - vis_faligndata(TMP2, TMP4, REF_4); - - vis_ld64_2(ref, stride, TMP6); - vis_pmerge(ZERO, REF_0, TMP0); - vis_mul8x16au(REF_0_1, CONST_256, TMP2); - - vis_ld64_2(ref, stride_8, TMP8); - vis_pmerge(ZERO, REF_4, TMP4); - - vis_ld64_2(ref, stride_16, TMP10); - ref += stride; - - vis_ld64_2(dest, stride, REF_S0/*DST_4*/); - vis_faligndata(TMP6, TMP8, REF_2); - vis_mul8x16au(REF_4_1, CONST_256, TMP6); - - vis_ld64_2(dest, stride_8, REF_S2/*DST_6*/); - vis_faligndata(TMP8, TMP10, REF_6); - vis_mul8x16al(DST_0, CONST_512, TMP20); - - vis_padd16(TMP0, CONST_3, TMP0); - vis_mul8x16al(DST_1, CONST_512, TMP22); - - vis_padd16(TMP2, CONST_3, TMP2); - vis_mul8x16al(DST_2, CONST_512, TMP24); - - vis_padd16(TMP4, CONST_3, TMP4); - vis_mul8x16al(DST_3, CONST_512, TMP26); - - vis_padd16(TMP6, CONST_3, TMP6); - - vis_padd16(TMP12, TMP20, TMP12); - vis_mul8x16al(REF_S0, CONST_512, TMP20); - - vis_padd16(TMP14, TMP22, TMP14); - vis_mul8x16al(REF_S0_1, CONST_512, TMP22); - - vis_padd16(TMP16, TMP24, TMP16); - vis_mul8x16al(REF_S2, CONST_512, TMP24); - - vis_padd16(TMP18, TMP26, TMP18); - vis_mul8x16al(REF_S2_1, CONST_512, TMP26); - - vis_padd16(TMP12, TMP0, TMP12); - vis_mul8x16au(REF_2, CONST_256, TMP28); - - vis_padd16(TMP14, TMP2, TMP14); - vis_mul8x16au(REF_2_1, CONST_256, TMP30); - - vis_padd16(TMP16, TMP4, TMP16); - vis_mul8x16au(REF_6, CONST_256, REF_S4); - - vis_padd16(TMP18, TMP6, TMP18); - vis_mul8x16au(REF_6_1, CONST_256, REF_S6); - - vis_pack16(TMP12, DST_0); - vis_padd16(TMP28, TMP0, TMP12); - - vis_pack16(TMP14, DST_1); - vis_st64(DST_0, dest[0]); - vis_padd16(TMP30, TMP2, TMP14); - - vis_pack16(TMP16, DST_2); - vis_padd16(REF_S4, TMP4, TMP16); - - vis_pack16(TMP18, DST_3); - vis_st64_2(DST_2, dest, 8); - dest += stride; - vis_padd16(REF_S6, TMP6, TMP18); - - vis_padd16(TMP12, TMP20, TMP12); - - vis_padd16(TMP14, TMP22, TMP14); - vis_pack16(TMP12, DST_0); - - vis_padd16(TMP16, TMP24, TMP16); - vis_pack16(TMP14, DST_1); - vis_st64(DST_0, dest[0]); - - vis_padd16(TMP18, TMP26, TMP18); - vis_pack16(TMP16, DST_2); - - vis_pack16(TMP18, DST_3); - vis_st64_2(DST_2, dest, 8); - dest += stride; - } while (--height); -} - -static void MC_put_no_round_xy_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - int stride_8 = stride + 8; - int stride_16 = stride + 16; - - vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); - - ref = vis_alignaddr(ref); - - vis_ld64(ref[ 0], TMP0); - vis_fzero(ZERO); - - vis_ld64(ref[ 8], TMP2); - - vis_ld64(ref[16], TMP4); - - vis_ld64(constants1[0], CONST_1); - vis_faligndata(TMP0, TMP2, REF_S0); - - vis_ld64(constants256_512[0], CONST_256); - vis_faligndata(TMP2, TMP4, REF_S4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_S2); - vis_faligndata(TMP2, TMP4, REF_S6); - } else { - vis_src1(TMP2, REF_S2); - vis_src1(TMP4, REF_S6); - } - - height >>= 1; - do { - vis_ld64_2(ref, stride, TMP0); - vis_mul8x16au(REF_S0, CONST_256, TMP12); - vis_pmerge(ZERO, REF_S0_1, TMP14); - - vis_alignaddr_g0((void *)off); - - vis_ld64_2(ref, stride_8, TMP2); - vis_mul8x16au(REF_S2, CONST_256, TMP16); - vis_pmerge(ZERO, REF_S2_1, TMP18); - - vis_ld64_2(ref, stride_16, TMP4); - ref += stride; - vis_mul8x16au(REF_S4, CONST_256, TMP20); - vis_pmerge(ZERO, REF_S4_1, TMP22); - - vis_ld64_2(ref, stride, TMP6); - vis_mul8x16au(REF_S6, CONST_256, TMP24); - vis_pmerge(ZERO, REF_S6_1, TMP26); - - vis_ld64_2(ref, stride_8, TMP8); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(ref, stride_16, TMP10); - ref += stride; - vis_faligndata(TMP2, TMP4, REF_4); - - vis_faligndata(TMP6, TMP8, REF_S0); - - vis_faligndata(TMP8, TMP10, REF_S4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - vis_faligndata(TMP2, TMP4, REF_6); - vis_faligndata(TMP6, TMP8, REF_S2); - vis_faligndata(TMP8, TMP10, REF_S6); - } else { - vis_src1(TMP2, REF_2); - vis_src1(TMP4, REF_6); - vis_src1(TMP8, REF_S2); - vis_src1(TMP10, REF_S6); - } - - vis_mul8x16au(REF_0, CONST_256, TMP0); - vis_pmerge(ZERO, REF_0_1, TMP2); - - vis_mul8x16au(REF_2, CONST_256, TMP4); - vis_pmerge(ZERO, REF_2_1, TMP6); - - vis_padd16(TMP0, CONST_2, TMP8); - vis_mul8x16au(REF_4, CONST_256, TMP0); - - vis_padd16(TMP2, CONST_1, TMP10); - vis_mul8x16au(REF_4_1, CONST_256, TMP2); - - vis_padd16(TMP8, TMP4, TMP8); - vis_mul8x16au(REF_6, CONST_256, TMP4); - - vis_padd16(TMP10, TMP6, TMP10); - vis_mul8x16au(REF_6_1, CONST_256, TMP6); - - vis_padd16(TMP12, TMP8, TMP12); - - vis_padd16(TMP14, TMP10, TMP14); - - vis_padd16(TMP12, TMP16, TMP12); - - vis_padd16(TMP14, TMP18, TMP14); - vis_pack16(TMP12, DST_0); - - vis_pack16(TMP14, DST_1); - vis_st64(DST_0, dest[0]); - vis_padd16(TMP0, CONST_1, TMP12); - - vis_mul8x16au(REF_S0, CONST_256, TMP0); - vis_padd16(TMP2, CONST_1, TMP14); - - vis_mul8x16au(REF_S0_1, CONST_256, TMP2); - vis_padd16(TMP12, TMP4, TMP12); - - vis_mul8x16au(REF_S2, CONST_256, TMP4); - vis_padd16(TMP14, TMP6, TMP14); - - vis_mul8x16au(REF_S2_1, CONST_256, TMP6); - vis_padd16(TMP20, TMP12, TMP20); - - vis_padd16(TMP22, TMP14, TMP22); - - vis_padd16(TMP20, TMP24, TMP20); - - vis_padd16(TMP22, TMP26, TMP22); - vis_pack16(TMP20, DST_2); - - vis_pack16(TMP22, DST_3); - vis_st64_2(DST_2, dest, 8); - dest += stride; - vis_padd16(TMP0, TMP4, TMP24); - - vis_mul8x16au(REF_S4, CONST_256, TMP0); - vis_padd16(TMP2, TMP6, TMP26); - - vis_mul8x16au(REF_S4_1, CONST_256, TMP2); - vis_padd16(TMP24, TMP8, TMP24); - - vis_padd16(TMP26, TMP10, TMP26); - vis_pack16(TMP24, DST_0); - - vis_pack16(TMP26, DST_1); - vis_st64(DST_0, dest[0]); - vis_pmerge(ZERO, REF_S6, TMP4); - - vis_pmerge(ZERO, REF_S6_1, TMP6); - - vis_padd16(TMP0, TMP4, TMP0); - - vis_padd16(TMP2, TMP6, TMP2); - - vis_padd16(TMP0, TMP12, TMP0); - - vis_padd16(TMP2, TMP14, TMP2); - vis_pack16(TMP0, DST_2); - - vis_pack16(TMP2, DST_3); - vis_st64_2(DST_2, dest, 8); - dest += stride; - } while (--height); -} - -static void MC_put_no_round_xy_8_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - int stride_8 = stride + 8; - - vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); - - ref = vis_alignaddr(ref); - - vis_ld64(ref[ 0], TMP0); - vis_fzero(ZERO); - - vis_ld64(ref[ 8], TMP2); - - vis_ld64(constants1[0], CONST_1); - - vis_ld64(constants256_512[0], CONST_256); - vis_faligndata(TMP0, TMP2, REF_S0); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_S2); - } else { - vis_src1(TMP2, REF_S2); - } - - height >>= 1; - do { /* 26 cycles */ - vis_ld64_2(ref, stride, TMP0); - vis_mul8x16au(REF_S0, CONST_256, TMP8); - vis_pmerge(ZERO, REF_S2, TMP12); - - vis_alignaddr_g0((void *)off); - - vis_ld64_2(ref, stride_8, TMP2); - ref += stride; - vis_mul8x16au(REF_S0_1, CONST_256, TMP10); - vis_pmerge(ZERO, REF_S2_1, TMP14); - - vis_ld64_2(ref, stride, TMP4); - - vis_ld64_2(ref, stride_8, TMP6); - ref += stride; - vis_faligndata(TMP0, TMP2, REF_S4); - - vis_pmerge(ZERO, REF_S4, TMP18); - - vis_pmerge(ZERO, REF_S4_1, TMP20); - - vis_faligndata(TMP4, TMP6, REF_S0); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_S6); - vis_faligndata(TMP4, TMP6, REF_S2); - } else { - vis_src1(TMP2, REF_S6); - vis_src1(TMP6, REF_S2); - } - - vis_padd16(TMP18, CONST_1, TMP18); - vis_mul8x16au(REF_S6, CONST_256, TMP22); - - vis_padd16(TMP20, CONST_1, TMP20); - vis_mul8x16au(REF_S6_1, CONST_256, TMP24); - - vis_mul8x16au(REF_S0, CONST_256, TMP26); - vis_pmerge(ZERO, REF_S0_1, TMP28); - - vis_mul8x16au(REF_S2, CONST_256, TMP30); - vis_padd16(TMP18, TMP22, TMP18); - - vis_mul8x16au(REF_S2_1, CONST_256, TMP32); - vis_padd16(TMP20, TMP24, TMP20); - - vis_padd16(TMP8, TMP18, TMP8); - - vis_padd16(TMP10, TMP20, TMP10); - - vis_padd16(TMP8, TMP12, TMP8); - - vis_padd16(TMP10, TMP14, TMP10); - vis_pack16(TMP8, DST_0); - - vis_pack16(TMP10, DST_1); - vis_st64(DST_0, dest[0]); - dest += stride; - vis_padd16(TMP18, TMP26, TMP18); - - vis_padd16(TMP20, TMP28, TMP20); - - vis_padd16(TMP18, TMP30, TMP18); - - vis_padd16(TMP20, TMP32, TMP20); - vis_pack16(TMP18, DST_2); - - vis_pack16(TMP20, DST_3); - vis_st64(DST_2, dest[0]); - dest += stride; - } while (--height); -} - -static void MC_avg_no_round_xy_16_vis (uint8_t * dest, const uint8_t * ref, - const ptrdiff_t stride, int height) -{ - unsigned long off = (unsigned long) ref & 0x7; - unsigned long off_plus_1 = off + 1; - int stride_8 = stride + 8; - int stride_16 = stride + 16; - - vis_set_gsr(4 << VIS_GSR_SCALEFACT_SHIFT); - - ref = vis_alignaddr(ref); - - vis_ld64(ref[ 0], TMP0); - vis_fzero(ZERO); - - vis_ld64(ref[ 8], TMP2); - - vis_ld64(ref[16], TMP4); - - vis_ld64(constants6[0], CONST_6); - vis_faligndata(TMP0, TMP2, REF_S0); - - vis_ld64(constants256_1024[0], CONST_256); - vis_faligndata(TMP2, TMP4, REF_S4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_S2); - vis_faligndata(TMP2, TMP4, REF_S6); - } else { - vis_src1(TMP2, REF_S2); - vis_src1(TMP4, REF_S6); - } - - height >>= 1; - do { /* 55 cycles */ - vis_ld64_2(ref, stride, TMP0); - vis_mul8x16au(REF_S0, CONST_256, TMP12); - vis_pmerge(ZERO, REF_S0_1, TMP14); - - vis_alignaddr_g0((void *)off); - - vis_ld64_2(ref, stride_8, TMP2); - vis_mul8x16au(REF_S2, CONST_256, TMP16); - vis_pmerge(ZERO, REF_S2_1, TMP18); - - vis_ld64_2(ref, stride_16, TMP4); - ref += stride; - vis_mul8x16au(REF_S4, CONST_256, TMP20); - vis_pmerge(ZERO, REF_S4_1, TMP22); - - vis_ld64_2(ref, stride, TMP6); - vis_mul8x16au(REF_S6, CONST_256, TMP24); - vis_pmerge(ZERO, REF_S6_1, TMP26); - - vis_ld64_2(ref, stride_8, TMP8); - vis_faligndata(TMP0, TMP2, REF_0); - - vis_ld64_2(ref, stride_16, TMP10); - ref += stride; - vis_faligndata(TMP2, TMP4, REF_4); - - vis_ld64(dest[0], DST_0); - vis_faligndata(TMP6, TMP8, REF_S0); - - vis_ld64_2(dest, 8, DST_2); - vis_faligndata(TMP8, TMP10, REF_S4); - - if (off != 0x7) { - vis_alignaddr_g0((void *)off_plus_1); - vis_faligndata(TMP0, TMP2, REF_2); - vis_faligndata(TMP2, TMP4, REF_6); - vis_faligndata(TMP6, TMP8, REF_S2); - vis_faligndata(TMP8, TMP10, REF_S6); - } else { - vis_src1(TMP2, REF_2); - vis_src1(TMP4, REF_6); - vis_src1(TMP8, REF_S2); - vis_src1(TMP10, REF_S6); - } - - vis_mul8x16al(DST_0, CONST_1024, TMP30); - vis_pmerge(ZERO, REF_0, TMP0); - - vis_mul8x16al(DST_1, CONST_1024, TMP32); - vis_pmerge(ZERO, REF_0_1, TMP2); - - vis_mul8x16au(REF_2, CONST_256, TMP4); - vis_pmerge(ZERO, REF_2_1, TMP6); - - vis_mul8x16al(DST_2, CONST_1024, REF_0); - vis_padd16(TMP0, CONST_6, TMP0); - - vis_mul8x16al(DST_3, CONST_1024, REF_2); - vis_padd16(TMP2, CONST_6, TMP2); - - vis_padd16(TMP0, TMP4, TMP0); - vis_mul8x16au(REF_4, CONST_256, TMP4); - - vis_padd16(TMP2, TMP6, TMP2); - vis_mul8x16au(REF_4_1, CONST_256, TMP6); - - vis_padd16(TMP12, TMP0, TMP12); - vis_mul8x16au(REF_6, CONST_256, TMP8); - - vis_padd16(TMP14, TMP2, TMP14); - vis_mul8x16au(REF_6_1, CONST_256, TMP10); - - vis_padd16(TMP12, TMP16, TMP12); - vis_mul8x16au(REF_S0, CONST_256, REF_4); - - vis_padd16(TMP14, TMP18, TMP14); - vis_mul8x16au(REF_S0_1, CONST_256, REF_6); - - vis_padd16(TMP12, TMP30, TMP12); - - vis_padd16(TMP14, TMP32, TMP14); - vis_pack16(TMP12, DST_0); - - vis_pack16(TMP14, DST_1); - vis_st64(DST_0, dest[0]); - vis_padd16(TMP4, CONST_6, TMP4); - - vis_ld64_2(dest, stride, DST_0); - vis_padd16(TMP6, CONST_6, TMP6); - vis_mul8x16au(REF_S2, CONST_256, TMP12); - - vis_padd16(TMP4, TMP8, TMP4); - vis_mul8x16au(REF_S2_1, CONST_256, TMP14); - - vis_padd16(TMP6, TMP10, TMP6); - - vis_padd16(TMP20, TMP4, TMP20); - - vis_padd16(TMP22, TMP6, TMP22); - - vis_padd16(TMP20, TMP24, TMP20); - - vis_padd16(TMP22, TMP26, TMP22); - - vis_padd16(TMP20, REF_0, TMP20); - vis_mul8x16au(REF_S4, CONST_256, REF_0); - - vis_padd16(TMP22, REF_2, TMP22); - vis_pack16(TMP20, DST_2); - - vis_pack16(TMP22, DST_3); - vis_st64_2(DST_2, dest, 8); - dest += stride; - - vis_ld64_2(dest, 8, DST_2); - vis_mul8x16al(DST_0, CONST_1024, TMP30); - vis_pmerge(ZERO, REF_S4_1, REF_2); - - vis_mul8x16al(DST_1, CONST_1024, TMP32); - vis_padd16(REF_4, TMP0, TMP8); - - vis_mul8x16au(REF_S6, CONST_256, REF_4); - vis_padd16(REF_6, TMP2, TMP10); - - vis_mul8x16au(REF_S6_1, CONST_256, REF_6); - vis_padd16(TMP8, TMP12, TMP8); - - vis_padd16(TMP10, TMP14, TMP10); - - vis_padd16(TMP8, TMP30, TMP8); - - vis_padd16(TMP10, TMP32, TMP10); - vis_pack16(TMP8, DST_0); - - vis_pack16(TMP10, DST_1); - vis_st64(DST_0, dest[0]); - - vis_padd16(REF_0, TMP4, REF_0); - - vis_mul8x16al(DST_2, CONST_1024, TMP30); - vis_padd16(REF_2, TMP6, REF_2); - - vis_mul8x16al(DST_3, CONST_1024, TMP32); - vis_padd16(REF_0, REF_4, REF_0); - - vis_padd16(REF_2, REF_6, REF_2); - - vis_padd16(REF_0, TMP30, REF_0); - - /* stall */ - - vis_padd16(REF_2, TMP32, REF_2); - vis_pack16(REF_0, DST_2); - - vis_pack16(REF_2, DST_3); - vis_st64_2(DST_2, dest, 8); - dest += stride; - } while (--height); -} - -/* End of no rounding code */ - -av_cold void ff_hpeldsp_init_vis(HpelDSPContext *c, int flags) -{ - /* VIS-specific optimizations */ - int accel = vis_level (); - - if (accel & ACCEL_SPARC_VIS) { - c->put_pixels_tab[0][0] = MC_put_o_16_vis; - c->put_pixels_tab[0][1] = MC_put_x_16_vis; - c->put_pixels_tab[0][2] = MC_put_y_16_vis; - c->put_pixels_tab[0][3] = MC_put_xy_16_vis; - - c->put_pixels_tab[1][0] = MC_put_o_8_vis; - c->put_pixels_tab[1][1] = MC_put_x_8_vis; - c->put_pixels_tab[1][2] = MC_put_y_8_vis; - c->put_pixels_tab[1][3] = MC_put_xy_8_vis; - - c->avg_pixels_tab[0][0] = MC_avg_o_16_vis; - c->avg_pixels_tab[0][1] = MC_avg_x_16_vis; - c->avg_pixels_tab[0][2] = MC_avg_y_16_vis; - c->avg_pixels_tab[0][3] = MC_avg_xy_16_vis; - - c->avg_pixels_tab[1][0] = MC_avg_o_8_vis; - c->avg_pixels_tab[1][1] = MC_avg_x_8_vis; - c->avg_pixels_tab[1][2] = MC_avg_y_8_vis; - c->avg_pixels_tab[1][3] = MC_avg_xy_8_vis; - - c->put_no_rnd_pixels_tab[0][0] = MC_put_no_round_o_16_vis; - c->put_no_rnd_pixels_tab[0][1] = MC_put_no_round_x_16_vis; - c->put_no_rnd_pixels_tab[0][2] = MC_put_no_round_y_16_vis; - c->put_no_rnd_pixels_tab[0][3] = MC_put_no_round_xy_16_vis; - - c->put_no_rnd_pixels_tab[1][0] = MC_put_no_round_o_8_vis; - c->put_no_rnd_pixels_tab[1][1] = MC_put_no_round_x_8_vis; - c->put_no_rnd_pixels_tab[1][2] = MC_put_no_round_y_8_vis; - c->put_no_rnd_pixels_tab[1][3] = MC_put_no_round_xy_8_vis; - - c->avg_no_rnd_pixels_tab[0] = MC_avg_no_round_o_16_vis; - c->avg_no_rnd_pixels_tab[1] = MC_avg_no_round_x_16_vis; - c->avg_no_rnd_pixels_tab[2] = MC_avg_no_round_y_16_vis; - c->avg_no_rnd_pixels_tab[3] = MC_avg_no_round_xy_16_vis; - } -} diff --git a/libavcodec/sparc/simple_idct_vis.c b/libavcodec/sparc/simple_idct_vis.c deleted file mode 100644 index c9923e092..000000000 --- a/libavcodec/sparc/simple_idct_vis.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * SPARC VIS optimized inverse DCT - * Copyright (c) 2007 Denes Balatoni < dbalatoni XatX interware XdotX hu > - * - * I did consult the following fine web page about dct - * http://www.geocities.com/ssavekar/dct.htm - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "dsputil_vis.h" -#include "libavutil/mem.h" - -static const DECLARE_ALIGNED(8, int16_t, coeffs)[28] = { - - 1259,- 1259,- 1259,- 1259, - - 4989,- 4989,- 4989,- 4989, - -11045,-11045,-11045,-11045, - -19195,-19195,-19195,-19195, - -29126,-29126,-29126,-29126, - 25080, 25080, 25080, 25080, - 12785, 12785, 12785, 12785 -}; -static const DECLARE_ALIGNED(8, uint16_t, scale)[4] = { - 65536>>6, 65536>>6, 65536>>6, 65536>>6 -}; -static const DECLARE_ALIGNED(8, uint16_t, rounder)[4] = { - 1<<5, 1<<5, 1<<5, 1<<5 -}; -static const DECLARE_ALIGNED(8, uint16_t, expand)[4] = { - 1<<14, 1<<14, 1<<14, 1<<14 -}; - -#define INIT_IDCT \ - "ldd [%1], %%f32 \n\t"\ - "ldd [%1+8], %%f34 \n\t"\ - "ldd [%1+16], %%f36 \n\t"\ - "ldd [%1+24], %%f38 \n\t"\ - "ldd [%1+32], %%f40 \n\t"\ - "ldd [%1+40], %%f42 \n\t"\ - "ldd [%1+48], %%f44 \n\t"\ - "ldd [%0], %%f46 \n\t"\ - "fzero %%f62 \n\t"\ - -#define LOADSCALE(in) \ - "ldd [" in "], %%f0 \n\t"\ - "ldd [" in "+16], %%f2 \n\t"\ - "ldd [" in "+32], %%f4 \n\t"\ - "ldd [" in "+48], %%f6 \n\t"\ - "ldd [" in "+64], %%f8 \n\t"\ - "ldd [" in "+80], %%f10 \n\t"\ - "ldd [" in "+96], %%f12 \n\t"\ - "ldd [" in "+112], %%f14 \n\t"\ - "fpadd16 %%f0, %%f0, %%f0 \n\t"\ - "fpadd16 %%f2, %%f2, %%f2 \n\t"\ - "fpadd16 %%f4, %%f4, %%f4 \n\t"\ - "fpadd16 %%f6, %%f6, %%f6 \n\t"\ - "fpadd16 %%f8, %%f8, %%f8 \n\t"\ - "fpadd16 %%f10, %%f10, %%f10 \n\t"\ - "fpadd16 %%f12, %%f12, %%f12 \n\t"\ - "fpadd16 %%f14, %%f14, %%f14 \n\t"\ -\ - "fpadd16 %%f0, %%f0, %%f0 \n\t"\ - "fpadd16 %%f2, %%f2, %%f2 \n\t"\ - "fpadd16 %%f4, %%f4, %%f4 \n\t"\ - "fpadd16 %%f6, %%f6, %%f6 \n\t"\ - "fpadd16 %%f8, %%f8, %%f8 \n\t"\ - "fpadd16 %%f10, %%f10, %%f10 \n\t"\ - "fpadd16 %%f12, %%f12, %%f12 \n\t"\ - "fpadd16 %%f14, %%f14, %%f14 \n\t"\ -\ - "fpadd16 %%f0, %%f0, %%f0 \n\t"\ - "fpadd16 %%f2, %%f2, %%f2 \n\t"\ - "fpadd16 %%f4, %%f4, %%f4 \n\t"\ - "fpadd16 %%f6, %%f6, %%f6 \n\t"\ - "fpadd16 %%f8, %%f8, %%f8 \n\t"\ - "fpadd16 %%f10, %%f10, %%f10 \n\t"\ - "fpadd16 %%f12, %%f12, %%f12 \n\t"\ - "fpadd16 %%f14, %%f14, %%f14 \n\t"\ -\ - "fpadd16 %%f0, %%f0, %%f0 \n\t"\ - "fpadd16 %%f2, %%f2, %%f2 \n\t"\ - "fpadd16 %%f4, %%f4, %%f4 \n\t"\ - "fpadd16 %%f6, %%f6, %%f6 \n\t"\ - "fpadd16 %%f8, %%f8, %%f8 \n\t"\ - "fpadd16 %%f10, %%f10, %%f10 \n\t"\ - "fpadd16 %%f12, %%f12, %%f12 \n\t"\ - "fpadd16 %%f14, %%f14, %%f14 \n\t"\ - -#define LOAD(in) \ - "ldd [" in "], %%f16 \n\t"\ - "ldd [" in "+8], %%f18 \n\t"\ - "ldd [" in "+16], %%f20 \n\t"\ - "ldd [" in "+24], %%f22 \n\t"\ - "ldd [" in "+32], %%f24 \n\t"\ - "ldd [" in "+40], %%f26 \n\t"\ - "ldd [" in "+48], %%f28 \n\t"\ - "ldd [" in "+56], %%f30 \n\t"\ - -#define TRANSPOSE \ - "fpmerge %%f16, %%f24, %%f0 \n\t"\ - "fpmerge %%f20, %%f28, %%f2 \n\t"\ - "fpmerge %%f17, %%f25, %%f4 \n\t"\ - "fpmerge %%f21, %%f29, %%f6 \n\t"\ - "fpmerge %%f18, %%f26, %%f8 \n\t"\ - "fpmerge %%f22, %%f30, %%f10 \n\t"\ - "fpmerge %%f19, %%f27, %%f12 \n\t"\ - "fpmerge %%f23, %%f31, %%f14 \n\t"\ -\ - "fpmerge %%f0, %%f2, %%f16 \n\t"\ - "fpmerge %%f1, %%f3, %%f18 \n\t"\ - "fpmerge %%f4, %%f6, %%f20 \n\t"\ - "fpmerge %%f5, %%f7, %%f22 \n\t"\ - "fpmerge %%f8, %%f10, %%f24 \n\t"\ - "fpmerge %%f9, %%f11, %%f26 \n\t"\ - "fpmerge %%f12, %%f14, %%f28 \n\t"\ - "fpmerge %%f13, %%f15, %%f30 \n\t"\ -\ - "fpmerge %%f16, %%f17, %%f0 \n\t"\ - "fpmerge %%f18, %%f19, %%f2 \n\t"\ - "fpmerge %%f20, %%f21, %%f4 \n\t"\ - "fpmerge %%f22, %%f23, %%f6 \n\t"\ - "fpmerge %%f24, %%f25, %%f8 \n\t"\ - "fpmerge %%f26, %%f27, %%f10 \n\t"\ - "fpmerge %%f28, %%f29, %%f12 \n\t"\ - "fpmerge %%f30, %%f31, %%f14 \n\t"\ - -#define IDCT4ROWS \ - /* 1. column */\ - "fmul8ulx16 %%f0, %%f38, %%f28 \n\t"\ - "for %%f4, %%f6, %%f60 \n\t"\ - "fmul8ulx16 %%f2, %%f32, %%f18 \n\t"\ - "fmul8ulx16 %%f2, %%f36, %%f22 \n\t"\ - "fmul8ulx16 %%f2, %%f40, %%f26 \n\t"\ - "fmul8ulx16 %%f2, %%f44, %%f30 \n\t"\ -\ - ADDROUNDER\ -\ - "fmul8sux16 %%f0, %%f38, %%f48 \n\t"\ - "fcmpd %%fcc0, %%f62, %%f60 \n\t"\ - "for %%f8, %%f10, %%f60 \n\t"\ - "fmul8sux16 %%f2, %%f32, %%f50 \n\t"\ - "fmul8sux16 %%f2, %%f36, %%f52 \n\t"\ - "fmul8sux16 %%f2, %%f40, %%f54 \n\t"\ - "fmul8sux16 %%f2, %%f44, %%f56 \n\t"\ -\ - "fpadd16 %%f48, %%f28, %%f28 \n\t"\ - "fcmpd %%fcc1, %%f62, %%f60 \n\t"\ - "for %%f12, %%f14, %%f60 \n\t"\ - "fpadd16 %%f50, %%f18, %%f18 \n\t"\ - "fpadd16 %%f52, %%f22, %%f22 \n\t"\ - "fpadd16 %%f54, %%f26, %%f26 \n\t"\ - "fpadd16 %%f56, %%f30, %%f30 \n\t"\ -\ - "fpadd16 %%f28, %%f0, %%f16 \n\t"\ - "fcmpd %%fcc2, %%f62, %%f60 \n\t"\ - "fpadd16 %%f28, %%f0, %%f20 \n\t"\ - "fpadd16 %%f28, %%f0, %%f24 \n\t"\ - "fpadd16 %%f28, %%f0, %%f28 \n\t"\ - "fpadd16 %%f18, %%f2, %%f18 \n\t"\ - "fpadd16 %%f22, %%f2, %%f22 \n\t"\ - /* 2. column */\ - "fbe %%fcc0, 3f \n\t"\ - "fpadd16 %%f26, %%f2, %%f26 \n\t"\ - "fmul8ulx16 %%f4, %%f34, %%f48 \n\t"\ - "fmul8ulx16 %%f4, %%f42, %%f50 \n\t"\ - "fmul8ulx16 %%f6, %%f36, %%f52 \n\t"\ - "fmul8ulx16 %%f6, %%f44, %%f54 \n\t"\ - "fmul8ulx16 %%f6, %%f32, %%f56 \n\t"\ - "fmul8ulx16 %%f6, %%f40, %%f58 \n\t"\ -\ - "fpadd16 %%f16, %%f48, %%f16 \n\t"\ - "fpadd16 %%f20, %%f50, %%f20 \n\t"\ - "fpsub16 %%f24, %%f50, %%f24 \n\t"\ - "fpsub16 %%f28, %%f48, %%f28 \n\t"\ - "fpadd16 %%f18, %%f52, %%f18 \n\t"\ - "fpsub16 %%f22, %%f54, %%f22 \n\t"\ - "fpsub16 %%f26, %%f56, %%f26 \n\t"\ - "fpsub16 %%f30, %%f58, %%f30 \n\t"\ -\ - "fmul8sux16 %%f4, %%f34, %%f48 \n\t"\ - "fmul8sux16 %%f4, %%f42, %%f50 \n\t"\ - "fmul8sux16 %%f6, %%f36, %%f52 \n\t"\ - "fmul8sux16 %%f6, %%f44, %%f54 \n\t"\ - "fmul8sux16 %%f6, %%f32, %%f56 \n\t"\ - "fmul8sux16 %%f6, %%f40, %%f58 \n\t"\ -\ - "fpadd16 %%f16, %%f48, %%f16 \n\t"\ - "fpadd16 %%f20, %%f50, %%f20 \n\t"\ - "fpsub16 %%f24, %%f50, %%f24 \n\t"\ - "fpsub16 %%f28, %%f48, %%f28 \n\t"\ - "fpadd16 %%f18, %%f52, %%f18 \n\t"\ - "fpsub16 %%f22, %%f54, %%f22 \n\t"\ - "fpsub16 %%f26, %%f56, %%f26 \n\t"\ - "fpsub16 %%f30, %%f58, %%f30 \n\t"\ -\ - "fpadd16 %%f16, %%f4, %%f16 \n\t"\ - "fpsub16 %%f28, %%f4, %%f28 \n\t"\ - "fpadd16 %%f18, %%f6, %%f18 \n\t"\ - "fpsub16 %%f26, %%f6, %%f26 \n\t"\ - /* 3. column */\ - "3: \n\t"\ - "fbe %%fcc1, 4f \n\t"\ - "fpsub16 %%f30, %%f6, %%f30 \n\t"\ - "fmul8ulx16 %%f8, %%f38, %%f48 \n\t"\ - "fmul8ulx16 %%f10, %%f40, %%f50 \n\t"\ - "fmul8ulx16 %%f10, %%f32, %%f52 \n\t"\ - "fmul8ulx16 %%f10, %%f44, %%f54 \n\t"\ - "fmul8ulx16 %%f10, %%f36, %%f56 \n\t"\ -\ - "fpadd16 %%f16, %%f48, %%f16 \n\t"\ - "fpsub16 %%f20, %%f48, %%f20 \n\t"\ - "fpsub16 %%f24, %%f48, %%f24 \n\t"\ - "fpadd16 %%f28, %%f48, %%f28 \n\t"\ - "fpadd16 %%f18, %%f50, %%f18 \n\t"\ - "fpsub16 %%f22, %%f52, %%f22 \n\t"\ - "fpadd16 %%f26, %%f54, %%f26 \n\t"\ - "fpadd16 %%f30, %%f56, %%f30 \n\t"\ -\ - "fmul8sux16 %%f8, %%f38, %%f48 \n\t"\ - "fmul8sux16 %%f10, %%f40, %%f50 \n\t"\ - "fmul8sux16 %%f10, %%f32, %%f52 \n\t"\ - "fmul8sux16 %%f10, %%f44, %%f54 \n\t"\ - "fmul8sux16 %%f10, %%f36, %%f56 \n\t"\ -\ - "fpadd16 %%f16, %%f48, %%f16 \n\t"\ - "fpsub16 %%f20, %%f48, %%f20 \n\t"\ - "fpsub16 %%f24, %%f48, %%f24 \n\t"\ - "fpadd16 %%f28, %%f48, %%f28 \n\t"\ - "fpadd16 %%f18, %%f50, %%f18 \n\t"\ - "fpsub16 %%f22, %%f52, %%f22 \n\t"\ - "fpadd16 %%f26, %%f54, %%f26 \n\t"\ - "fpadd16 %%f30, %%f56, %%f30 \n\t"\ -\ - "fpadd16 %%f16, %%f8, %%f16 \n\t"\ - "fpsub16 %%f20, %%f8, %%f20 \n\t"\ - "fpsub16 %%f24, %%f8, %%f24 \n\t"\ - "fpadd16 %%f28, %%f8, %%f28 \n\t"\ - "fpadd16 %%f18, %%f10, %%f18 \n\t"\ - "fpsub16 %%f22, %%f10, %%f22 \n\t"\ - /* 4. column */\ - "4: \n\t"\ - "fbe %%fcc2, 5f \n\t"\ - "fpadd16 %%f30, %%f10, %%f30 \n\t"\ - "fmul8ulx16 %%f12, %%f42, %%f48 \n\t"\ - "fmul8ulx16 %%f12, %%f34, %%f50 \n\t"\ - "fmul8ulx16 %%f14, %%f44, %%f52 \n\t"\ - "fmul8ulx16 %%f14, %%f40, %%f54 \n\t"\ - "fmul8ulx16 %%f14, %%f36, %%f56 \n\t"\ - "fmul8ulx16 %%f14, %%f32, %%f58 \n\t"\ -\ - "fpadd16 %%f16, %%f48, %%f16 \n\t"\ - "fpsub16 %%f20, %%f50, %%f20 \n\t"\ - "fpadd16 %%f24, %%f50, %%f24 \n\t"\ - "fpsub16 %%f28, %%f48, %%f28 \n\t"\ - "fpadd16 %%f18, %%f52, %%f18 \n\t"\ - "fpsub16 %%f22, %%f54, %%f22 \n\t"\ - "fpadd16 %%f26, %%f56, %%f26 \n\t"\ - "fpsub16 %%f30, %%f58, %%f30 \n\t"\ -\ - "fmul8sux16 %%f12, %%f42, %%f48 \n\t"\ - "fmul8sux16 %%f12, %%f34, %%f50 \n\t"\ - "fmul8sux16 %%f14, %%f44, %%f52 \n\t"\ - "fmul8sux16 %%f14, %%f40, %%f54 \n\t"\ - "fmul8sux16 %%f14, %%f36, %%f56 \n\t"\ - "fmul8sux16 %%f14, %%f32, %%f58 \n\t"\ -\ - "fpadd16 %%f16, %%f48, %%f16 \n\t"\ - "fpsub16 %%f20, %%f50, %%f20 \n\t"\ - "fpadd16 %%f24, %%f50, %%f24 \n\t"\ - "fpsub16 %%f28, %%f48, %%f28 \n\t"\ - "fpadd16 %%f18, %%f52, %%f18 \n\t"\ - "fpsub16 %%f22, %%f54, %%f22 \n\t"\ - "fpadd16 %%f26, %%f56, %%f26 \n\t"\ - "fpsub16 %%f30, %%f58, %%f30 \n\t"\ -\ - "fpsub16 %%f20, %%f12, %%f20 \n\t"\ - "fpadd16 %%f24, %%f12, %%f24 \n\t"\ - "fpsub16 %%f22, %%f14, %%f22 \n\t"\ - "fpadd16 %%f26, %%f14, %%f26 \n\t"\ - "fpsub16 %%f30, %%f14, %%f30 \n\t"\ - /* final butterfly */\ - "5: \n\t"\ - "fpsub16 %%f16, %%f18, %%f48 \n\t"\ - "fpsub16 %%f20, %%f22, %%f50 \n\t"\ - "fpsub16 %%f24, %%f26, %%f52 \n\t"\ - "fpsub16 %%f28, %%f30, %%f54 \n\t"\ - "fpadd16 %%f16, %%f18, %%f16 \n\t"\ - "fpadd16 %%f20, %%f22, %%f20 \n\t"\ - "fpadd16 %%f24, %%f26, %%f24 \n\t"\ - "fpadd16 %%f28, %%f30, %%f28 \n\t"\ - -#define STOREROWS(out) \ - "std %%f48, [" out "+112] \n\t"\ - "std %%f50, [" out "+96] \n\t"\ - "std %%f52, [" out "+80] \n\t"\ - "std %%f54, [" out "+64] \n\t"\ - "std %%f16, [" out "] \n\t"\ - "std %%f20, [" out "+16] \n\t"\ - "std %%f24, [" out "+32] \n\t"\ - "std %%f28, [" out "+48] \n\t"\ - -#define SCALEROWS \ - "fmul8sux16 %%f46, %%f48, %%f48 \n\t"\ - "fmul8sux16 %%f46, %%f50, %%f50 \n\t"\ - "fmul8sux16 %%f46, %%f52, %%f52 \n\t"\ - "fmul8sux16 %%f46, %%f54, %%f54 \n\t"\ - "fmul8sux16 %%f46, %%f16, %%f16 \n\t"\ - "fmul8sux16 %%f46, %%f20, %%f20 \n\t"\ - "fmul8sux16 %%f46, %%f24, %%f24 \n\t"\ - "fmul8sux16 %%f46, %%f28, %%f28 \n\t"\ - -#define PUTPIXELSCLAMPED(dest) \ - "fpack16 %%f48, %%f14 \n\t"\ - "fpack16 %%f50, %%f12 \n\t"\ - "fpack16 %%f16, %%f0 \n\t"\ - "fpack16 %%f20, %%f2 \n\t"\ - "fpack16 %%f24, %%f4 \n\t"\ - "fpack16 %%f28, %%f6 \n\t"\ - "fpack16 %%f54, %%f8 \n\t"\ - "fpack16 %%f52, %%f10 \n\t"\ - "st %%f0, [%3+" dest "] \n\t"\ - "st %%f2, [%5+" dest "] \n\t"\ - "st %%f4, [%6+" dest "] \n\t"\ - "st %%f6, [%7+" dest "] \n\t"\ - "st %%f8, [%8+" dest "] \n\t"\ - "st %%f10, [%9+" dest "] \n\t"\ - "st %%f12, [%10+" dest "] \n\t"\ - "st %%f14, [%11+" dest "] \n\t"\ - -#define ADDPIXELSCLAMPED(dest) \ - "ldd [%5], %%f18 \n\t"\ - "ld [%3+" dest"], %%f0 \n\t"\ - "ld [%6+" dest"], %%f2 \n\t"\ - "ld [%7+" dest"], %%f4 \n\t"\ - "ld [%8+" dest"], %%f6 \n\t"\ - "ld [%9+" dest"], %%f8 \n\t"\ - "ld [%10+" dest"], %%f10 \n\t"\ - "ld [%11+" dest"], %%f12 \n\t"\ - "ld [%12+" dest"], %%f14 \n\t"\ - "fmul8x16 %%f0, %%f18, %%f0 \n\t"\ - "fmul8x16 %%f2, %%f18, %%f2 \n\t"\ - "fmul8x16 %%f4, %%f18, %%f4 \n\t"\ - "fmul8x16 %%f6, %%f18, %%f6 \n\t"\ - "fmul8x16 %%f8, %%f18, %%f8 \n\t"\ - "fmul8x16 %%f10, %%f18, %%f10 \n\t"\ - "fmul8x16 %%f12, %%f18, %%f12 \n\t"\ - "fmul8x16 %%f14, %%f18, %%f14 \n\t"\ - "fpadd16 %%f0, %%f16, %%f0 \n\t"\ - "fpadd16 %%f2, %%f20, %%f2 \n\t"\ - "fpadd16 %%f4, %%f24, %%f4 \n\t"\ - "fpadd16 %%f6, %%f28, %%f6 \n\t"\ - "fpadd16 %%f8, %%f54, %%f8 \n\t"\ - "fpadd16 %%f10, %%f52, %%f10 \n\t"\ - "fpadd16 %%f12, %%f50, %%f12 \n\t"\ - "fpadd16 %%f14, %%f48, %%f14 \n\t"\ - "fpack16 %%f0, %%f0 \n\t"\ - "fpack16 %%f2, %%f2 \n\t"\ - "fpack16 %%f4, %%f4 \n\t"\ - "fpack16 %%f6, %%f6 \n\t"\ - "fpack16 %%f8, %%f8 \n\t"\ - "fpack16 %%f10, %%f10 \n\t"\ - "fpack16 %%f12, %%f12 \n\t"\ - "fpack16 %%f14, %%f14 \n\t"\ - "st %%f0, [%3+" dest "] \n\t"\ - "st %%f2, [%6+" dest "] \n\t"\ - "st %%f4, [%7+" dest "] \n\t"\ - "st %%f6, [%8+" dest "] \n\t"\ - "st %%f8, [%9+" dest "] \n\t"\ - "st %%f10, [%10+" dest "] \n\t"\ - "st %%f12, [%11+" dest "] \n\t"\ - "st %%f14, [%12+" dest "] \n\t"\ - - -void ff_simple_idct_vis(int16_t *data) { - int out1, out2, out3, out4; - DECLARE_ALIGNED(8, int16_t, temp)[8*8]; - - __asm__ volatile( - INIT_IDCT - -#define ADDROUNDER - - // shift right 16-4=12 - LOADSCALE("%2+8") - IDCT4ROWS - STOREROWS("%3+8") - LOADSCALE("%2+0") - IDCT4ROWS - "std %%f48, [%3+112] \n\t" - "std %%f50, [%3+96] \n\t" - "std %%f52, [%3+80] \n\t" - "std %%f54, [%3+64] \n\t" - - // shift right 16+4 - "ldd [%3+8], %%f18 \n\t" - "ldd [%3+24], %%f22 \n\t" - "ldd [%3+40], %%f26 \n\t" - "ldd [%3+56], %%f30 \n\t" - TRANSPOSE - IDCT4ROWS - SCALEROWS - STOREROWS("%2+0") - LOAD("%3+64") - TRANSPOSE - IDCT4ROWS - SCALEROWS - STOREROWS("%2+8") - - : "=r" (out1), "=r" (out2), "=r" (out3), "=r" (out4) - : "0" (scale), "1" (coeffs), "2" (data), "3" (temp) - ); -} - -void ff_simple_idct_put_vis(uint8_t *dest, int line_size, int16_t *data) { - int out1, out2, out3, out4, out5; - int r1, r2, r3, r4, r5, r6, r7; - - __asm__ volatile( - "wr %%g0, 0x8, %%gsr \n\t" - - INIT_IDCT - - "add %3, %4, %5 \n\t" - "add %5, %4, %6 \n\t" - "add %6, %4, %7 \n\t" - "add %7, %4, %8 \n\t" - "add %8, %4, %9 \n\t" - "add %9, %4, %10 \n\t" - "add %10, %4, %11 \n\t" - - // shift right 16-4=12 - LOADSCALE("%2+8") - IDCT4ROWS - STOREROWS("%2+8") - LOADSCALE("%2+0") - IDCT4ROWS - "std %%f48, [%2+112] \n\t" - "std %%f50, [%2+96] \n\t" - "std %%f52, [%2+80] \n\t" - "std %%f54, [%2+64] \n\t" - -#undef ADDROUNDER -#define ADDROUNDER "fpadd16 %%f28, %%f46, %%f28 \n\t" - - // shift right 16+4 - "ldd [%2+8], %%f18 \n\t" - "ldd [%2+24], %%f22 \n\t" - "ldd [%2+40], %%f26 \n\t" - "ldd [%2+56], %%f30 \n\t" - TRANSPOSE - IDCT4ROWS - PUTPIXELSCLAMPED("0") - LOAD("%2+64") - TRANSPOSE - IDCT4ROWS - PUTPIXELSCLAMPED("4") - - : "=r" (out1), "=r" (out2), "=r" (out3), "=r" (out4), "=r" (out5), - "=r" (r1), "=r" (r2), "=r" (r3), "=r" (r4), "=r" (r5), "=r" (r6), "=r" (r7) - : "0" (rounder), "1" (coeffs), "2" (data), "3" (dest), "4" (line_size) - ); -} - -void ff_simple_idct_add_vis(uint8_t *dest, int line_size, int16_t *data) { - int out1, out2, out3, out4, out5, out6; - int r1, r2, r3, r4, r5, r6, r7; - - __asm__ volatile( - "wr %%g0, 0x8, %%gsr \n\t" - - INIT_IDCT - - "add %3, %4, %6 \n\t" - "add %6, %4, %7 \n\t" - "add %7, %4, %8 \n\t" - "add %8, %4, %9 \n\t" - "add %9, %4, %10 \n\t" - "add %10, %4, %11 \n\t" - "add %11, %4, %12 \n\t" - -#undef ADDROUNDER -#define ADDROUNDER - - // shift right 16-4=12 - LOADSCALE("%2+8") - IDCT4ROWS - STOREROWS("%2+8") - LOADSCALE("%2+0") - IDCT4ROWS - "std %%f48, [%2+112] \n\t" - "std %%f50, [%2+96] \n\t" - "std %%f52, [%2+80] \n\t" - "std %%f54, [%2+64] \n\t" - -#undef ADDROUNDER -#define ADDROUNDER "fpadd16 %%f28, %%f46, %%f28 \n\t" - - // shift right 16+4 - "ldd [%2+8], %%f18 \n\t" - "ldd [%2+24], %%f22 \n\t" - "ldd [%2+40], %%f26 \n\t" - "ldd [%2+56], %%f30 \n\t" - TRANSPOSE - IDCT4ROWS - ADDPIXELSCLAMPED("0") - LOAD("%2+64") - TRANSPOSE - IDCT4ROWS - ADDPIXELSCLAMPED("4") - - : "=r" (out1), "=r" (out2), "=r" (out3), "=r" (out4), "=r" (out5), "=r" (out6), - "=r" (r1), "=r" (r2), "=r" (r3), "=r" (r4), "=r" (r5), "=r" (r6), "=r" (r7) - : "0" (rounder), "1" (coeffs), "2" (data), "3" (dest), "4" (line_size), "5" (expand) - ); -} diff --git a/libavcodec/sparc/vis.h b/libavcodec/sparc/vis.h deleted file mode 100644 index 107ff96d8..000000000 --- a/libavcodec/sparc/vis.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2003 David S. Miller - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* You may be asking why I hard-code the instruction opcodes and don't - * use the normal VIS assembler mnenomics for the VIS instructions. - * - * The reason is that Sun, in their infinite wisdom, decided that a binary - * using a VIS instruction will cause it to be marked (in the ELF headers) - * as doing so, and this prevents the OS from loading such binaries if the - * current cpu doesn't have VIS. There is no way to easily override this - * behavior of the assembler that I am aware of. - * - * This totally defeats what libmpeg2 is trying to do which is allow a - * single binary to be created, and then detect the availability of VIS - * at runtime. - * - * I'm not saying that tainting the binary by default is bad, rather I'm - * saying that not providing a way to override this easily unnecessarily - * ties people's hands. - * - * Thus, we do the opcode encoding by hand and output 32-bit words in - * the assembler to keep the binary from becoming tainted. - */ - -#ifndef AVCODEC_SPARC_VIS_H -#define AVCODEC_SPARC_VIS_H - -#define ACCEL_SPARC_VIS 1 -#define ACCEL_SPARC_VIS2 2 - -static inline int vis_level(void) -{ - int accel = 0; - accel |= ACCEL_SPARC_VIS; - accel |= ACCEL_SPARC_VIS2; - return accel; -} - -#define vis_opc_base ((0x1 << 31) | (0x36 << 19)) -#define vis_opf(X) ((X) << 5) -#define vis_sreg(X) (X) -#define vis_dreg(X) (((X)&0x1f)|((X)>>5)) -#define vis_rs1_s(X) (vis_sreg(X) << 14) -#define vis_rs1_d(X) (vis_dreg(X) << 14) -#define vis_rs2_s(X) (vis_sreg(X) << 0) -#define vis_rs2_d(X) (vis_dreg(X) << 0) -#define vis_rd_s(X) (vis_sreg(X) << 25) -#define vis_rd_d(X) (vis_dreg(X) << 25) - -#define vis_ss2s(opf,rs1,rs2,rd) \ - __asm__ volatile (".word %0" \ - : : "i" (vis_opc_base | vis_opf(opf) | \ - vis_rs1_s(rs1) | \ - vis_rs2_s(rs2) | \ - vis_rd_s(rd))) - -#define vis_dd2d(opf,rs1,rs2,rd) \ - __asm__ volatile (".word %0" \ - : : "i" (vis_opc_base | vis_opf(opf) | \ - vis_rs1_d(rs1) | \ - vis_rs2_d(rs2) | \ - vis_rd_d(rd))) - -#define vis_ss2d(opf,rs1,rs2,rd) \ - __asm__ volatile (".word %0" \ - : : "i" (vis_opc_base | vis_opf(opf) | \ - vis_rs1_s(rs1) | \ - vis_rs2_s(rs2) | \ - vis_rd_d(rd))) - -#define vis_sd2d(opf,rs1,rs2,rd) \ - __asm__ volatile (".word %0" \ - : : "i" (vis_opc_base | vis_opf(opf) | \ - vis_rs1_s(rs1) | \ - vis_rs2_d(rs2) | \ - vis_rd_d(rd))) - -#define vis_d2s(opf,rs2,rd) \ - __asm__ volatile (".word %0" \ - : : "i" (vis_opc_base | vis_opf(opf) | \ - vis_rs2_d(rs2) | \ - vis_rd_s(rd))) - -#define vis_s2d(opf,rs2,rd) \ - __asm__ volatile (".word %0" \ - : : "i" (vis_opc_base | vis_opf(opf) | \ - vis_rs2_s(rs2) | \ - vis_rd_d(rd))) - -#define vis_d12d(opf,rs1,rd) \ - __asm__ volatile (".word %0" \ - : : "i" (vis_opc_base | vis_opf(opf) | \ - vis_rs1_d(rs1) | \ - vis_rd_d(rd))) - -#define vis_d22d(opf,rs2,rd) \ - __asm__ volatile (".word %0" \ - : : "i" (vis_opc_base | vis_opf(opf) | \ - vis_rs2_d(rs2) | \ - vis_rd_d(rd))) - -#define vis_s12s(opf,rs1,rd) \ - __asm__ volatile (".word %0" \ - : : "i" (vis_opc_base | vis_opf(opf) | \ - vis_rs1_s(rs1) | \ - vis_rd_s(rd))) - -#define vis_s22s(opf,rs2,rd) \ - __asm__ volatile (".word %0" \ - : : "i" (vis_opc_base | vis_opf(opf) | \ - vis_rs2_s(rs2) | \ - vis_rd_s(rd))) - -#define vis_s(opf,rd) \ - __asm__ volatile (".word %0" \ - : : "i" (vis_opc_base | vis_opf(opf) | \ - vis_rd_s(rd))) - -#define vis_d(opf,rd) \ - __asm__ volatile (".word %0" \ - : : "i" (vis_opc_base | vis_opf(opf) | \ - vis_rd_d(rd))) - -#define vis_r2m(op,rd,mem) \ - __asm__ volatile (#op "\t%%f" #rd ", [%0]" : : "r" (&(mem)) ) - -#define vis_r2m_2(op,rd,mem1,mem2) \ - __asm__ volatile (#op "\t%%f" #rd ", [%0 + %1]" : : "r" (mem1), "r" (mem2) ) - -#define vis_m2r(op,mem,rd) \ - __asm__ volatile (#op "\t[%0], %%f" #rd : : "r" (&(mem)) ) - -#define vis_m2r_2(op,mem1,mem2,rd) \ - __asm__ volatile (#op "\t[%0 + %1], %%f" #rd : : "r" (mem1), "r" (mem2) ) - -static inline void vis_set_gsr(unsigned int val) -{ - __asm__ volatile("mov %0,%%asr19" - : : "r" (val)); -} - -#define VIS_GSR_ALIGNADDR_MASK 0x0000007 -#define VIS_GSR_ALIGNADDR_SHIFT 0 -#define VIS_GSR_SCALEFACT_MASK 0x0000078 -#define VIS_GSR_SCALEFACT_SHIFT 3 - -#define vis_ld32(mem,rs1) vis_m2r(ld, mem, rs1) -#define vis_ld32_2(mem1,mem2,rs1) vis_m2r_2(ld, mem1, mem2, rs1) -#define vis_st32(rs1,mem) vis_r2m(st, rs1, mem) -#define vis_st32_2(rs1,mem1,mem2) vis_r2m_2(st, rs1, mem1, mem2) -#define vis_ld64(mem,rs1) vis_m2r(ldd, mem, rs1) -#define vis_ld64_2(mem1,mem2,rs1) vis_m2r_2(ldd, mem1, mem2, rs1) -#define vis_st64(rs1,mem) vis_r2m(std, rs1, mem) -#define vis_st64_2(rs1,mem1,mem2) vis_r2m_2(std, rs1, mem1, mem2) - -/* 16 and 32 bit partitioned addition and subtraction. The normal - * versions perform 4 16-bit or 2 32-bit additions or subtractions. - * The 's' versions perform 2 16-bit or 1 32-bit additions or - * subtractions. - */ - -#define vis_padd16(rs1,rs2,rd) vis_dd2d(0x50, rs1, rs2, rd) -#define vis_padd16s(rs1,rs2,rd) vis_ss2s(0x51, rs1, rs2, rd) -#define vis_padd32(rs1,rs2,rd) vis_dd2d(0x52, rs1, rs2, rd) -#define vis_padd32s(rs1,rs2,rd) vis_ss2s(0x53, rs1, rs2, rd) -#define vis_psub16(rs1,rs2,rd) vis_dd2d(0x54, rs1, rs2, rd) -#define vis_psub16s(rs1,rs2,rd) vis_ss2s(0x55, rs1, rs2, rd) -#define vis_psub32(rs1,rs2,rd) vis_dd2d(0x56, rs1, rs2, rd) -#define vis_psub32s(rs1,rs2,rd) vis_ss2s(0x57, rs1, rs2, rd) - -/* Pixel formatting instructions. */ - -#define vis_pack16(rs2,rd) vis_d2s( 0x3b, rs2, rd) -#define vis_pack32(rs1,rs2,rd) vis_dd2d(0x3a, rs1, rs2, rd) -#define vis_packfix(rs2,rd) vis_d2s( 0x3d, rs2, rd) -#define vis_expand(rs2,rd) vis_s2d( 0x4d, rs2, rd) -#define vis_pmerge(rs1,rs2,rd) vis_ss2d(0x4b, rs1, rs2, rd) - -/* Partitioned multiply instructions. */ - -#define vis_mul8x16(rs1,rs2,rd) vis_sd2d(0x31, rs1, rs2, rd) -#define vis_mul8x16au(rs1,rs2,rd) vis_ss2d(0x33, rs1, rs2, rd) -#define vis_mul8x16al(rs1,rs2,rd) vis_ss2d(0x35, rs1, rs2, rd) -#define vis_mul8sux16(rs1,rs2,rd) vis_dd2d(0x36, rs1, rs2, rd) -#define vis_mul8ulx16(rs1,rs2,rd) vis_dd2d(0x37, rs1, rs2, rd) -#define vis_muld8sux16(rs1,rs2,rd) vis_ss2d(0x38, rs1, rs2, rd) -#define vis_muld8ulx16(rs1,rs2,rd) vis_ss2d(0x39, rs1, rs2, rd) - -/* Alignment instructions. */ - -static inline const void *vis_alignaddr(const void *ptr) -{ - __asm__ volatile("alignaddr %0, %%g0, %0" - : "=&r" (ptr) - : "0" (ptr)); - - return ptr; -} - -static inline void vis_alignaddr_g0(void *ptr) -{ - __asm__ volatile("alignaddr %0, %%g0, %%g0" - : : "r" (ptr)); -} - -#define vis_faligndata(rs1,rs2,rd) vis_dd2d(0x48, rs1, rs2, rd) - -/* Logical operate instructions. */ - -#define vis_fzero(rd) vis_d( 0x60, rd) -#define vis_fzeros(rd) vis_s( 0x61, rd) -#define vis_fone(rd) vis_d( 0x7e, rd) -#define vis_fones(rd) vis_s( 0x7f, rd) -#define vis_src1(rs1,rd) vis_d12d(0x74, rs1, rd) -#define vis_src1s(rs1,rd) vis_s12s(0x75, rs1, rd) -#define vis_src2(rs2,rd) vis_d22d(0x78, rs2, rd) -#define vis_src2s(rs2,rd) vis_s22s(0x79, rs2, rd) -#define vis_not1(rs1,rd) vis_d12d(0x6a, rs1, rd) -#define vis_not1s(rs1,rd) vis_s12s(0x6b, rs1, rd) -#define vis_not2(rs2,rd) vis_d22d(0x66, rs2, rd) -#define vis_not2s(rs2,rd) vis_s22s(0x67, rs2, rd) -#define vis_or(rs1,rs2,rd) vis_dd2d(0x7c, rs1, rs2, rd) -#define vis_ors(rs1,rs2,rd) vis_ss2s(0x7d, rs1, rs2, rd) -#define vis_nor(rs1,rs2,rd) vis_dd2d(0x62, rs1, rs2, rd) -#define vis_nors(rs1,rs2,rd) vis_ss2s(0x63, rs1, rs2, rd) -#define vis_and(rs1,rs2,rd) vis_dd2d(0x70, rs1, rs2, rd) -#define vis_ands(rs1,rs2,rd) vis_ss2s(0x71, rs1, rs2, rd) -#define vis_nand(rs1,rs2,rd) vis_dd2d(0x6e, rs1, rs2, rd) -#define vis_nands(rs1,rs2,rd) vis_ss2s(0x6f, rs1, rs2, rd) -#define vis_xor(rs1,rs2,rd) vis_dd2d(0x6c, rs1, rs2, rd) -#define vis_xors(rs1,rs2,rd) vis_ss2s(0x6d, rs1, rs2, rd) -#define vis_xnor(rs1,rs2,rd) vis_dd2d(0x72, rs1, rs2, rd) -#define vis_xnors(rs1,rs2,rd) vis_ss2s(0x73, rs1, rs2, rd) -#define vis_ornot1(rs1,rs2,rd) vis_dd2d(0x7a, rs1, rs2, rd) -#define vis_ornot1s(rs1,rs2,rd) vis_ss2s(0x7b, rs1, rs2, rd) -#define vis_ornot2(rs1,rs2,rd) vis_dd2d(0x76, rs1, rs2, rd) -#define vis_ornot2s(rs1,rs2,rd) vis_ss2s(0x77, rs1, rs2, rd) -#define vis_andnot1(rs1,rs2,rd) vis_dd2d(0x68, rs1, rs2, rd) -#define vis_andnot1s(rs1,rs2,rd) vis_ss2s(0x69, rs1, rs2, rd) -#define vis_andnot2(rs1,rs2,rd) vis_dd2d(0x64, rs1, rs2, rd) -#define vis_andnot2s(rs1,rs2,rd) vis_ss2s(0x65, rs1, rs2, rd) - -/* Pixel component distance. */ - -#define vis_pdist(rs1,rs2,rd) vis_dd2d(0x3e, rs1, rs2, rd) - -#endif /* AVCODEC_SPARC_VIS_H */ diff --git a/libavcodec/startcode.c b/libavcodec/startcode.c new file mode 100644 index 000000000..5df769515 --- /dev/null +++ b/libavcodec/startcode.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003-2010 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Accelerated start code search function for start codes common to + * MPEG-1/2/4 video, VC-1, H.264/5 + * @author Michael Niedermayer + */ + +#include "startcode.h" +#include "config.h" + +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 + * bytes at the end. + */ +# if HAVE_FAST_64BIT + while (i < size && + !((~*(const uint64_t *)(buf + i) & + (*(const uint64_t *)(buf + i) - 0x0101010101010101ULL)) & + 0x8080808080808080ULL)) + i += 8; +# else + while (i < size && + !((~*(const uint32_t *)(buf + i) & + (*(const uint32_t *)(buf + i) - 0x01010101U)) & + 0x80808080U)) + i += 4; +# endif +#endif + for (; i < size; i++) + if (!buf[i]) + break; + return i; +} diff --git a/libavcodec/startcode.h b/libavcodec/startcode.h new file mode 100644 index 000000000..cc55d5f64 --- /dev/null +++ b/libavcodec/startcode.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2003-2010 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Accelerated start code search function for start codes common to + * MPEG-1/2/4 video, VC-1, H.264/5 + * @author Michael Niedermayer + */ + +#ifndef AVCODEC_STARTCODE_H +#define AVCODEC_STARTCODE_H + +#include + +int ff_startcode_find_candidate_c(const uint8_t *buf, int size); + +#endif /* AVCODEC_STARTCODE_H */ diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c index 2d7e848fc..9ff690dce 100644 --- a/libavcodec/svq1enc.c +++ b/libavcodec/svq1enc.c @@ -32,50 +32,14 @@ #include "mpegvideo.h" #include "h263.h" #include "internal.h" -#include "libavutil/avassert.h" +#include "mpegutils.h" #include "svq1.h" +#include "svq1enc.h" #include "svq1enc_cb.h" +#include "libavutil/avassert.h" -typedef struct SVQ1Context { - /* FIXME: Needed for motion estimation, should not be used for anything - * else, the idea is to make the motion estimation eventually independent - * of MpegEncContext, so this will be removed then. */ - MpegEncContext m; - AVCodecContext *avctx; - DSPContext dsp; - HpelDSPContext hdsp; - AVFrame *current_picture; - AVFrame *last_picture; - PutBitContext pb; - GetBitContext gb; - - /* why ooh why this sick breadth first order, - * everything is slower and more complex */ - PutBitContext reorder_pb[6]; - - int frame_width; - int frame_height; - - /* Y plane block dimensions */ - int y_block_width; - int y_block_height; - - /* U & V plane (C planes) block dimensions */ - int c_block_width; - int c_block_height; - - uint16_t *mb_type; - uint32_t *dummy; - int16_t (*motion_val8[3])[2]; - int16_t (*motion_val16[3])[2]; - - int64_t rd_total; - - uint8_t *scratchbuf; -} SVQ1Context; - -static void svq1_write_header(SVQ1Context *s, int frame_type) +static void svq1_write_header(SVQ1EncContext *s, int frame_type) { int i; @@ -112,7 +76,17 @@ static void svq1_write_header(SVQ1Context *s, int frame_type) #define QUALITY_THRESHOLD 100 #define THRESHOLD_MULTIPLIER 0.6 -static int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref, +static int ssd_int8_vs_int16_c(const int8_t *pix1, const int16_t *pix2, + intptr_t size) +{ + int score = 0, i; + + for (i = 0; i < size; i++) + score += (pix1[i] - pix2[i]) * (pix1[i] - pix2[i]); + return score; +} + +static int encode_block(SVQ1EncContext *s, uint8_t *src, uint8_t *ref, uint8_t *decoded, int stride, int level, int threshold, int lambda, int intra) { @@ -173,7 +147,7 @@ static int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref, int sqr, diff, score; vector = codebook + stage * size * 16 + i * size; - sqr = s->dsp.ssd_int8_vs_int16(vector, block[stage], 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 if (score < best_vector_score) { @@ -257,7 +231,16 @@ static int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref, return best_score; } -static int svq1_encode_plane(SVQ1Context *s, int plane, +static void init_block_index(MpegEncContext *s){ + s->block_index[0]= s->b8_stride*(s->mb_y*2 ) + s->mb_x*2; + s->block_index[1]= s->b8_stride*(s->mb_y*2 ) + 1 + s->mb_x*2; + s->block_index[2]= s->b8_stride*(s->mb_y*2 + 1) + s->mb_x*2; + s->block_index[3]= s->b8_stride*(s->mb_y*2 + 1) + 1 + s->mb_x*2; + s->block_index[4]= s->mb_stride*(s->mb_y + 1) + s->b8_stride*s->mb_height*2 + s->mb_x; + s->block_index[5]= s->mb_stride*(s->mb_y + s->mb_height + 2) + s->b8_stride*s->mb_height*2 + s->mb_x; +} + +static int svq1_encode_plane(SVQ1EncContext *s, int plane, unsigned char *src_plane, unsigned char *ref_plane, unsigned char *decoded_plane, @@ -269,7 +252,7 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, int block_width, block_height; int level; int threshold[6]; - uint8_t *src = s->scratchbuf + stride * 16; + uint8_t *src = s->scratchbuf + stride * 32; const int lambda = (f->quality * f->quality) >> (2 * FF_LAMBDA_SHIFT); @@ -285,11 +268,11 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, s->m.avctx = s->avctx; s->m.current_picture_ptr = &s->m.current_picture; s->m.last_picture_ptr = &s->m.last_picture; - s->m.last_picture.f.data[0] = ref_plane; + s->m.last_picture.f->data[0] = ref_plane; s->m.linesize = - s->m.last_picture.f.linesize[0] = - s->m.new_picture.f.linesize[0] = - s->m.current_picture.f.linesize[0] = stride; + s->m.last_picture.f->linesize[0] = + s->m.new_picture.f->linesize[0] = + s->m.current_picture.f->linesize[0] = stride; s->m.width = width; s->m.height = height; s->m.mb_width = block_width; @@ -337,7 +320,7 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, s->m.me.dia_size = s->avctx->dia_size; s->m.first_slice_line = 1; for (y = 0; y < block_height; y++) { - s->m.new_picture.f.data[0] = src - y * 16 * stride; // ugly + s->m.new_picture.f->data[0] = src - y * 16 * stride; // ugly s->m.mb_y = y; for (i = 0; i < 16 && i + 16 * y < height; i++) { @@ -352,8 +335,7 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, for (x = 0; x < block_width; x++) { s->m.mb_x = x; - ff_init_block_index(&s->m); - ff_update_block_index(&s->m); + init_block_index(&s->m); ff_estimate_p_frame_motion(&s->m, x, y); } @@ -393,8 +375,7 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, } s->m.mb_x = x; - ff_init_block_index(&s->m); - ff_update_block_index(&s->m); + init_block_index(&s->m); if (f->pict_type == AV_PICTURE_TYPE_I || (s->m.mb_type[x + y * s->m.mb_stride] & @@ -446,12 +427,12 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, dxy = (mx & 1) + 2 * (my & 1); - s->hdsp.put_pixels_tab[0][dxy](temp + 16, + s->hdsp.put_pixels_tab[0][dxy](temp + 16*stride, ref + (mx >> 1) + stride * (my >> 1), stride, 16); - score[1] += encode_block(s, src + 16 * x, temp + 16, + score[1] += encode_block(s, src + 16 * x, temp + 16*stride, decoded, stride, 5, 64, lambda, 0); best = score[1] <= score[0]; @@ -500,13 +481,16 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, static av_cold int svq1_encode_end(AVCodecContext *avctx) { - SVQ1Context *const s = avctx->priv_data; + SVQ1EncContext *const s = avctx->priv_data; int i; av_log(avctx, AV_LOG_DEBUG, "RD: %f\n", s->rd_total / (double)(avctx->width * avctx->height * avctx->frame_number)); + s->m.mb_type = NULL; + ff_MPV_common_end(&s->m); + av_freep(&s->m.me.scratchpad); av_freep(&s->m.me.map); av_freep(&s->m.me.score_map); @@ -528,10 +512,12 @@ static av_cold int svq1_encode_end(AVCodecContext *avctx) static av_cold int svq1_encode_init(AVCodecContext *avctx) { - SVQ1Context *const s = avctx->priv_data; + SVQ1EncContext *const s = avctx->priv_data; + int ret; ff_dsputil_init(&s->dsp, avctx); ff_hpeldsp_init(&s->hdsp, avctx->flags); + ff_mpegvideoencdsp_init(&s->m.mpvencdsp, avctx); avctx->coded_frame = av_frame_alloc(); s->current_picture = av_frame_alloc(); @@ -552,6 +538,12 @@ static av_cold int svq1_encode_init(AVCodecContext *avctx) s->avctx = avctx; s->m.avctx = avctx; + + if ((ret = ff_MPV_common_init(&s->m)) < 0) { + svq1_encode_end(avctx); + return ret; + } + s->m.picture_structure = PICT_FRAME; s->m.me.temp = s->m.me.scratchpad = av_mallocz((avctx->width + 64) * @@ -562,6 +554,13 @@ static av_cold int svq1_encode_init(AVCodecContext *avctx) s->y_block_height * sizeof(int16_t)); s->dummy = av_mallocz((s->y_block_width + 1) * s->y_block_height * sizeof(int32_t)); + s->ssd_int8_vs_int16 = ssd_int8_vs_int16_c; + + if (ARCH_PPC) + ff_svq1enc_init_ppc(s); + if (ARCH_X86) + ff_svq1enc_init_x86(s); + ff_h263_encode_init(&s->m); // mv_penalty return 0; @@ -570,8 +569,8 @@ static av_cold int svq1_encode_init(AVCodecContext *avctx) static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { - SVQ1Context *const s = avctx->priv_data; - AVFrame *const p = avctx->coded_frame; + SVQ1EncContext *const s = avctx->priv_data; + AVFrame *const p = avctx->coded_frame; int i, ret; if ((ret = ff_alloc_packet2(avctx, pkt, s->y_block_width * s->y_block_height * @@ -588,7 +587,7 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, (ret = ff_get_buffer(avctx, s->last_picture, 0)) < 0) { return ret; } - s->scratchbuf = av_malloc(s->current_picture->linesize[0] * 16 * 2); + s->scratchbuf = av_malloc(s->current_picture->linesize[0] * 16 * 3); } FFSWAP(AVFrame*, s->current_picture, s->last_picture); @@ -631,7 +630,7 @@ AVCodec ff_svq1_encoder = { .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(SVQ1Context), + .priv_data_size = sizeof(SVQ1EncContext), .init = svq1_encode_init, .encode2 = svq1_encode_frame, .close = svq1_encode_end, diff --git a/libavcodec/svq1enc.h b/libavcodec/svq1enc.h new file mode 100644 index 000000000..612b6e2b4 --- /dev/null +++ b/libavcodec/svq1enc.h @@ -0,0 +1,78 @@ +/* + * SVQ1 encoder + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_SVQ1ENC_H +#define AVCODEC_SVQ1ENC_H + +#include + +#include "libavutil/frame.h" +#include "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" +#include "hpeldsp.h" +#include "mpegvideo.h" +#include "put_bits.h" + +typedef struct SVQ1EncContext { + /* FIXME: Needed for motion estimation, should not be used for anything + * else, the idea is to make the motion estimation eventually independent + * of MpegEncContext, so this will be removed then. */ + MpegEncContext m; + AVCodecContext *avctx; + DSPContext dsp; + HpelDSPContext hdsp; + AVFrame *current_picture; + AVFrame *last_picture; + PutBitContext pb; + GetBitContext gb; + + /* why ooh why this sick breadth first order, + * everything is slower and more complex */ + PutBitContext reorder_pb[6]; + + int frame_width; + int frame_height; + + /* Y plane block dimensions */ + int y_block_width; + int y_block_height; + + /* U & V plane (C planes) block dimensions */ + int c_block_width; + int c_block_height; + + uint16_t *mb_type; + uint32_t *dummy; + int16_t (*motion_val8[3])[2]; + int16_t (*motion_val16[3])[2]; + + int64_t rd_total; + + uint8_t *scratchbuf; + + int (*ssd_int8_vs_int16)(const int8_t *pix1, const int16_t *pix2, + intptr_t size); +} SVQ1EncContext; + +void ff_svq1enc_init_ppc(SVQ1EncContext *c); +void ff_svq1enc_init_x86(SVQ1EncContext *c); + +#endif /* AVCODEC_SVQ1ENC_H */ diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index d3c5672d4..97233b19d 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -40,10 +40,12 @@ * http://samples.mplayerhq.hu/V-codecs/SVQ3/Vertical400kbit.sorenson3.mov */ +#include + #include "libavutil/attributes.h" #include "internal.h" #include "avcodec.h" -#include "mpegvideo.h" +#include "mpegutils.h" #include "h264.h" #include "h264data.h" // FIXME FIXME FIXME @@ -52,6 +54,7 @@ #include "golomb.h" #include "hpeldsp.h" #include "rectangle.h" +#include "tpeldsp.h" #include "vdpau_internal.h" #if CONFIG_ZLIB @@ -69,9 +72,10 @@ typedef struct { H264Context h; HpelDSPContext hdsp; - Picture *cur_pic; - Picture *next_pic; - Picture *last_pic; + TpelDSPContext tdsp; + H264Picture *cur_pic; + H264Picture *next_pic; + H264Picture *last_pic; int halfpel_flag; int thirdpel_flag; int unknown_flag; @@ -298,8 +302,8 @@ static inline void svq3_mc_dir_part(SVQ3Context *s, int mx, int my, int dxy, int thirdpel, int dir, int avg) { - H264Context *h = &s->h; - const Picture *pic = (dir == 0) ? s->last_pic : s->next_pic; + H264Context *h = &s->h; + const H264Picture *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 @@ -326,9 +330,9 @@ static inline void svq3_mc_dir_part(SVQ3Context *s, src = h->edge_emu_buffer; } if (thirdpel) - (avg ? h->dsp.avg_tpel_pixels_tab - : h->dsp.put_tpel_pixels_tab)[dxy](dest, src, h->linesize, - width, height); + (avg ? s->tdsp.avg_tpel_pixels_tab + : s->tdsp.put_tpel_pixels_tab)[dxy](dest, src, h->linesize, + width, height); else (avg ? s->hdsp.avg_pixels_tab : s->hdsp.put_pixels_tab)[blocksize][dxy](dest, src, h->linesize, @@ -354,10 +358,10 @@ static inline void svq3_mc_dir_part(SVQ3Context *s, src = h->edge_emu_buffer; } if (thirdpel) - (avg ? h->dsp.avg_tpel_pixels_tab - : h->dsp.put_tpel_pixels_tab)[dxy](dest, src, - h->uvlinesize, - width, height); + (avg ? s->tdsp.avg_tpel_pixels_tab + : s->tdsp.put_tpel_pixels_tab)[dxy](dest, src, + h->uvlinesize, + width, height); else (avg ? s->hdsp.avg_pixels_tab : s->hdsp.put_pixels_tab)[blocksize][dxy](dest, src, @@ -621,7 +625,8 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) vlc = svq3_get_ue_golomb(&h->gb); if (vlc >= 25U) { - av_log(h->avctx, AV_LOG_ERROR, "luma prediction:%d\n", vlc); + av_log(h->avctx, AV_LOG_ERROR, + "luma prediction:%"PRIu32"\n", vlc); return -1; } @@ -690,7 +695,7 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) if (!IS_INTRA16x16(mb_type) && (!IS_SKIP(mb_type) || h->pict_type == AV_PICTURE_TYPE_B)) { if ((vlc = svq3_get_ue_golomb(&h->gb)) >= 48U){ - av_log(h->avctx, AV_LOG_ERROR, "cbp_vlc=%d\n", vlc); + av_log(h->avctx, AV_LOG_ERROR, "cbp_vlc=%"PRIu32"\n", vlc); return -1; } @@ -812,7 +817,7 @@ static int svq3_decode_slice_header(AVCodecContext *avctx) } if ((slice_id = svq3_get_ue_golomb(&h->gb)) >= 3) { - av_log(h->avctx, AV_LOG_ERROR, "illegal slice type %d \n", slice_id); + av_log(h->avctx, AV_LOG_ERROR, "illegal slice type %u \n", slice_id); return -1; } @@ -884,11 +889,14 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx) goto fail; ff_hpeldsp_init(&s->hdsp, avctx->flags); + ff_tpeldsp_init(&s->tdsp); + h->flags = avctx->flags; h->is_complex = 1; h->sps.chroma_format_idc = 1; h->picture_structure = PICT_FRAME; - avctx->pix_fmt = avctx->codec->pix_fmts[0]; + 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; @@ -1000,7 +1008,7 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx) } buf = av_malloc(buf_len); - av_log(avctx, AV_LOG_DEBUG, "watermark size: %dx%d\n", + av_log(avctx, AV_LOG_DEBUG, "watermark size: %ux%u\n", watermark_width, watermark_height); av_log(avctx, AV_LOG_DEBUG, "u1: %x u2: %x u3: %x compressed data size: %d offset: %d\n", @@ -1016,7 +1024,7 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx) s->watermark_key = ff_svq1_packet_checksum(buf, buf_len, 0); s->watermark_key = s->watermark_key << 16 | s->watermark_key; av_log(avctx, AV_LOG_DEBUG, - "watermark key %#x\n", s->watermark_key); + "watermark key %#"PRIx32"\n", s->watermark_key); av_free(buf); #else av_log(avctx, AV_LOG_ERROR, @@ -1048,7 +1056,7 @@ fail: return ret; } -static void free_picture(AVCodecContext *avctx, Picture *pic) +static void free_picture(AVCodecContext *avctx, H264Picture *pic) { int i; for (i = 0; i < 2; i++) { @@ -1060,7 +1068,7 @@ static void free_picture(AVCodecContext *avctx, Picture *pic) av_frame_unref(&pic->f); } -static int get_buffer(AVCodecContext *avctx, Picture *pic) +static int get_buffer(AVCodecContext *avctx, H264Picture *pic) { SVQ3Context *s = avctx->priv_data; H264Context *h = &s->h; @@ -1154,7 +1162,7 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data, h->pict_type = h->slice_type; if (h->pict_type != AV_PICTURE_TYPE_B) - FFSWAP(Picture*, s->next_pic, s->last_pic); + FFSWAP(H264Picture*, s->next_pic, s->last_pic); av_frame_unref(&s->cur_pic->f); @@ -1298,8 +1306,8 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data, (h->pict_type == AV_PICTURE_TYPE_P && mb_type < 8) ? (mb_type - 1) : -1; } - ff_draw_horiz_band(avctx, s->cur_pic, - s->last_pic->f.data[0] ? s->last_pic : NULL, + 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); } @@ -1328,7 +1336,7 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data, *got_frame = 1; if (h->pict_type != AV_PICTURE_TYPE_B) { - FFSWAP(Picture*, s->cur_pic, s->next_pic); + FFSWAP(H264Picture*, s->cur_pic, s->next_pic); } else { av_frame_unref(&s->cur_pic->f); } diff --git a/libavcodec/takdec.c b/libavcodec/takdec.c index 86ca3ac01..9bfbfcc3d 100644 --- a/libavcodec/takdec.c +++ b/libavcodec/takdec.c @@ -28,9 +28,9 @@ #include "libavutil/internal.h" #include "libavutil/samplefmt.h" #include "tak.h" +#include "audiodsp.h" #include "thread.h" #include "avcodec.h" -#include "dsputil.h" #include "internal.h" #include "unary.h" @@ -46,7 +46,7 @@ typedef struct MCDParam { typedef struct TAKDecContext { AVCodecContext *avctx; ///< parent AVCodecContext - DSPContext dsp; + AudioDSPContext adsp; TAKStreamInfo ti; GetBitContext gb; ///< bitstream reader initialized to start at the current frame @@ -171,7 +171,7 @@ static av_cold int tak_decode_init(AVCodecContext *avctx) { TAKDecContext *s = avctx->priv_data; - ff_dsputil_init(&s->dsp, avctx); + ff_audiodsp_init(&s->adsp); s->avctx = avctx; avctx->bits_per_raw_sample = avctx->bits_per_coded_sample; @@ -469,8 +469,8 @@ static int decode_subframe(TAKDecContext *s, int32_t *decoded, int v = 1 << (filter_quant - 1); if (filter_order & -16) - v += s->dsp.scalarproduct_int16(&s->residues[i], s->filter, - filter_order & -16); + v += s->adsp.scalarproduct_int16(&s->residues[i], s->filter, + filter_order & -16); for (j = filter_order & -16; j < filter_order; j += 4) { v += s->residues[i + j + 3] * s->filter[j + 3] + s->residues[i + j + 2] * s->filter[j + 2] + @@ -640,8 +640,8 @@ static int decorrelate(TAKDecContext *s, int c1, int c2, int length) int v = 1 << 9; if (filter_order == 16) { - v += s->dsp.scalarproduct_int16(&s->residues[i], s->filter, - filter_order); + v += s->adsp.scalarproduct_int16(&s->residues[i], s->filter, + filter_order); } else { v += s->residues[i + 7] * s->filter[7] + s->residues[i + 6] * s->filter[6] + @@ -686,8 +686,8 @@ static int tak_decode_frame(AVCodecContext *avctx, void *data, if ((ret = ff_tak_decode_frame_header(avctx, gb, &s->ti, 0)) < 0) return ret; + hsize = get_bits_count(gb) / 8; if (avctx->err_recognition & (AV_EF_CRCCHECK|AV_EF_COMPLIANT)) { - hsize = get_bits_count(gb) / 8; if (ff_tak_check_crc(pkt->data, hsize)) { av_log(avctx, AV_LOG_ERROR, "CRC error\n"); if (avctx->err_recognition & AV_EF_EXPLODE) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index cbc526acc..1caad8484 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -53,11 +53,13 @@ typedef struct TiffContext { int palette_is_set; int le; enum TiffCompr compr; - int invert; + enum TiffPhotometric photometric; int planar; + int subsampling[2]; int fax_opts; int predictor; int fill_order; + uint32_t res[4]; int strips, rps, sstype; int sot; @@ -66,6 +68,8 @@ typedef struct TiffContext { uint8_t *deinvert_buf; int deinvert_buf_size; + uint8_t *yuv_line; + unsigned int yuv_line_size; int geotag_count; TiffGeoTag *geotags; @@ -220,7 +224,7 @@ static int add_metadata(int count, int type, { switch(type) { case TIFF_DOUBLE: return ff_tadd_doubles_metadata(count, name, sep, &s->gb, s->le, avpriv_frame_get_metadatap(frame)); - case TIFF_SHORT : return ff_tadd_shorts_metadata(count, name, sep, &s->gb, s->le, avpriv_frame_get_metadatap(frame)); + case TIFF_SHORT : return ff_tadd_shorts_metadata(count, name, sep, &s->gb, s->le, 0, avpriv_frame_get_metadatap(frame)); case TIFF_STRING: return ff_tadd_string_metadata(count, name, &s->gb, s->le, avpriv_frame_get_metadatap(frame)); default : return AVERROR_INVALIDDATA; }; @@ -379,12 +383,43 @@ static int tiff_unpack_fax(TiffContext *s, uint8_t *dst, int stride, return ret; } -static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride, - const uint8_t *src, int size, int lines) +static void unpack_yuv(TiffContext *s, AVFrame *p, + const uint8_t *src, int lnum) { + int i, j, k; + int w = (s->width - 1) / s->subsampling[0] + 1; + uint8_t *pu = &p->data[1][lnum / s->subsampling[1] * p->linesize[1]]; + uint8_t *pv = &p->data[2][lnum / s->subsampling[1] * p->linesize[2]]; + if (s->width % s->subsampling[0] || s->height % s->subsampling[1]) { + for (i = 0; i < w; i++) { + for (j = 0; j < s->subsampling[1]; j++) + for (k = 0; k < s->subsampling[0]; k++) + p->data[0][FFMIN(lnum + j, s->height-1) * p->linesize[0] + + FFMIN(i * s->subsampling[0] + k, s->width-1)] = *src++; + *pu++ = *src++; + *pv++ = *src++; + } + }else{ + for (i = 0; i < w; i++) { + for (j = 0; j < s->subsampling[1]; j++) + for (k = 0; k < s->subsampling[0]; k++) + p->data[0][(lnum + j) * p->linesize[0] + + i * s->subsampling[0] + k] = *src++; + *pu++ = *src++; + *pv++ = *src++; + } + } +} + + +static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int stride, + const uint8_t *src, int size, int strip_start, int lines) +{ + PutByteContext pb; int c, line, pixels, code, ret; const uint8_t *ssrc = src; - int width = ((s->width * s->bpp) + 7) >> 3; + int width = ((s->width * s->bpp) + 7) >> 3; + int is_yuv = s->photometric == TIFF_PHOTOMETRIC_YCBCR; if (s->planar) width /= s->bppcount; @@ -392,7 +427,26 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride, if (size <= 0) return AVERROR_INVALIDDATA; + if (is_yuv) { + int bytes_per_row = (((s->width - 1) / s->subsampling[0] + 1) * s->bpp * + s->subsampling[0] * s->subsampling[1] + 7) >> 3; + av_fast_padded_malloc(&s->yuv_line, &s->yuv_line_size, bytes_per_row); + if (s->yuv_line == NULL) { + av_log(s->avctx, AV_LOG_ERROR, "Not enough memory\n"); + return AVERROR(ENOMEM); + } + dst = s->yuv_line; + stride = 0; + width = s->width * s->subsampling[1] + 2*(s->width / s->subsampling[0]); + av_assert0(width <= bytes_per_row); + av_assert0(s->bpp == 24); + } + if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE) { + if (is_yuv) { + av_log(s->avctx, AV_LOG_ERROR, "YUV deflate is unsupported"); + return AVERROR_PATCHWELCOME; + } #if CONFIG_ZLIB return tiff_unpack_zlib(s, dst, stride, src, size, width, lines); #else @@ -415,21 +469,49 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride, av_log(s->avctx, AV_LOG_ERROR, "Error initializing LZW decoder\n"); return ret; } + for (line = 0; line < lines; line++) { + pixels = ff_lzw_decode(s->lzw, dst, width); + if (pixels < width) { + av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n", + pixels, width); + return AVERROR_INVALIDDATA; + } + if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8) + horizontal_fill(s->bpp, dst, 1, dst, 0, width, 0); + if (is_yuv) { + unpack_yuv(s, p, dst, strip_start + line); + line += s->subsampling[1] - 1; + } + dst += stride; + } + return 0; } if (s->compr == TIFF_CCITT_RLE || s->compr == TIFF_G3 || s->compr == TIFF_G4) { + if (is_yuv) + return AVERROR_INVALIDDATA; + return tiff_unpack_fax(s, dst, stride, src, size, width, lines); } + + bytestream2_init(&s->gb, src, size); + bytestream2_init_writer(&pb, dst, is_yuv ? s->yuv_line_size : (stride * lines)); + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); return AVERROR_INVALIDDATA; } + + if (bytestream2_get_bytes_left(&s->gb) == 0 || bytestream2_get_eof(&pb)) + break; + bytestream2_seek_p(&pb, stride * line, SEEK_SET); switch (s->compr) { case TIFF_RAW: if (ssrc + size - src < width) return AVERROR_INVALIDDATA; + if (!s->fill_order) { horizontal_fill(s->bpp * (s->avctx->pix_fmt == AV_PIX_FMT_PAL8), dst, 1, src, 0, width, 0); @@ -478,16 +560,10 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride, dst[i] = ff_reverse[dst[i]]; } break; - case TIFF_LZW: - pixels = ff_lzw_decode(s->lzw, dst, width); - if (pixels < width) { - av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n", - pixels, width); - return AVERROR_INVALIDDATA; - } - if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8) - horizontal_fill(s->bpp, dst, 1, dst, 0, width, 0); - break; + } + if (is_yuv) { + unpack_yuv(s, p, dst, strip_start + line); + line += s->subsampling[1] - 1; } dst += stride; } @@ -511,7 +587,25 @@ static int init_image(TiffContext *s, ThreadFrame *frame) s->avctx->pix_fmt = AV_PIX_FMT_PAL8; break; case 243: - s->avctx->pix_fmt = AV_PIX_FMT_RGB24; + if (s->photometric == TIFF_PHOTOMETRIC_YCBCR) { + if (s->subsampling[0] == 1 && s->subsampling[1] == 1) { + s->avctx->pix_fmt = AV_PIX_FMT_YUV444P; + } else if (s->subsampling[0] == 2 && s->subsampling[1] == 1) { + s->avctx->pix_fmt = AV_PIX_FMT_YUV422P; + } else if (s->subsampling[0] == 4 && s->subsampling[1] == 1) { + s->avctx->pix_fmt = AV_PIX_FMT_YUV411P; + } else if (s->subsampling[0] == 1 && s->subsampling[1] == 2) { + s->avctx->pix_fmt = AV_PIX_FMT_YUV440P; + } else if (s->subsampling[0] == 2 && s->subsampling[1] == 2) { + s->avctx->pix_fmt = AV_PIX_FMT_YUV420P; + } else if (s->subsampling[0] == 4 && s->subsampling[1] == 4) { + s->avctx->pix_fmt = AV_PIX_FMT_YUV410P; + } else { + av_log(s->avctx, AV_LOG_ERROR, "Unsupported YCbCr subsampling\n"); + return AVERROR_PATCHWELCOME; + } + } else + s->avctx->pix_fmt = AV_PIX_FMT_RGB24; break; case 161: s->avctx->pix_fmt = s->le ? AV_PIX_FMT_GRAY16LE : AV_PIX_FMT_GRAY16BE; @@ -566,12 +660,22 @@ static int init_image(TiffContext *s, ThreadFrame *frame) return 0; } +static void set_sar(TiffContext *s, unsigned tag, unsigned num, unsigned den) +{ + int offset = tag == TIFF_YRES ? 2 : 0; + s->res[offset++] = num; + s->res[offset] = den; + if (s->res[0] && s->res[1] && s->res[2] && s->res[3]) + av_reduce(&s->avctx->sample_aspect_ratio.num, &s->avctx->sample_aspect_ratio.den, + s->res[2] * (uint64_t)s->res[1], s->res[0] * (uint64_t)s->res[3], INT32_MAX); +} + static int tiff_decode_tag(TiffContext *s, AVFrame *frame) { - unsigned tag, type, count, off, value = 0; - int i, j, k, pos, start; + unsigned tag, type, count, off, value = 0, value2 = 0; + int i, start; + int pos; int ret; - uint32_t *pal; double *dp; ret = ff_tread_tag(&s->gb, s->le, &tag, &type, &count, &start); @@ -587,6 +691,10 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) case TIFF_LONG: value = ff_tget(&s->gb, type, s->le); break; + case TIFF_RATIONAL: + value = ff_tget(&s->gb, TIFF_LONG, s->le); + value2 = ff_tget(&s->gb, TIFF_LONG, s->le); + break; case TIFF_STRING: if (count <= 4) { break; @@ -676,46 +784,35 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) } break; case TIFF_ROWSPERSTRIP: - if (type == TIFF_LONG && value == UINT_MAX) + if (!value || (type == TIFF_LONG && value == UINT_MAX)) value = s->height; - if (value < 1) { - av_log(s->avctx, AV_LOG_ERROR, - "Incorrect value of rows per strip\n"); - return AVERROR_INVALIDDATA; - } - s->rps = value; + s->rps = FFMIN(value, s->height); break; case TIFF_STRIP_OFFS: if (count == 1) { - s->strippos = 0; - s->stripoff = value; + s->strippos = 0; + s->stripoff = value; } else s->strippos = off; s->strips = count; if (s->strips == 1) s->rps = s->height; s->sot = type; - if (s->strippos > bytestream2_size(&s->gb)) { - av_log(s->avctx, AV_LOG_ERROR, - "Tag referencing position outside the image\n"); - return AVERROR_INVALIDDATA; - } break; case TIFF_STRIP_SIZE: if (count == 1) { s->stripsizesoff = 0; - s->stripsize = value; - s->strips = 1; + s->stripsize = value; + s->strips = 1; } else { s->stripsizesoff = off; } s->strips = count; s->sstype = type; - if (s->stripsizesoff > bytestream2_size(&s->gb)) { - av_log(s->avctx, AV_LOG_ERROR, - "Tag referencing position outside the image\n"); - return AVERROR_INVALIDDATA; - } + break; + case TIFF_XRES: + case TIFF_YRES: + set_sar(s, tag, value, value2); break; case TIFF_TILE_BYTE_COUNTS: case TIFF_TILE_LENGTH: @@ -727,20 +824,31 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) case TIFF_PREDICTOR: s->predictor = value; break; - case TIFF_INVERT: + case TIFF_PHOTOMETRIC: switch (value) { - case 0: - s->invert = 1; - break; - case 1: - s->invert = 0; - break; - case 2: - case 3: + case TIFF_PHOTOMETRIC_WHITE_IS_ZERO: + case TIFF_PHOTOMETRIC_BLACK_IS_ZERO: + case TIFF_PHOTOMETRIC_RGB: + case TIFF_PHOTOMETRIC_PALETTE: + case TIFF_PHOTOMETRIC_YCBCR: + s->photometric = value; break; + case TIFF_PHOTOMETRIC_ALPHA_MASK: + case TIFF_PHOTOMETRIC_SEPARATED: + case TIFF_PHOTOMETRIC_CIE_LAB: + case TIFF_PHOTOMETRIC_ICC_LAB: + case TIFF_PHOTOMETRIC_ITU_LAB: + case TIFF_PHOTOMETRIC_CFA: + case TIFF_PHOTOMETRIC_LOG_L: + case TIFF_PHOTOMETRIC_LOG_LUV: + case TIFF_PHOTOMETRIC_LINEAR_RAW: + avpriv_report_missing_feature(s->avctx, + "PhotometricInterpretation 0x%04X", + value); + return AVERROR_PATCHWELCOME; default: - av_log(s->avctx, AV_LOG_ERROR, "Color mode %d is not supported\n", - value); + av_log(s->avctx, AV_LOG_ERROR, "PhotometricInterpretation %u is " + "unknown\n", value); return AVERROR_INVALIDDATA; } break; @@ -752,25 +860,39 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) } s->fill_order = value - 1; break; - case TIFF_PAL: - pal = (uint32_t *) s->palette; + case TIFF_PAL: { + GetByteContext pal_gb[3]; off = type_sizes[type]; - if (count / 3 > 256 || bytestream2_get_bytes_left(&s->gb) < count / 3 * off * 3) + if (count / 3 > 256 || + bytestream2_get_bytes_left(&s->gb) < count / 3 * off * 3) return AVERROR_INVALIDDATA; + + pal_gb[0] = pal_gb[1] = pal_gb[2] = s->gb; + bytestream2_skip(&pal_gb[1], count / 3 * off); + bytestream2_skip(&pal_gb[2], count / 3 * off * 2); + off = (type_sizes[type] - 1) << 3; - for (k = 2; k >= 0; k--) { - for (i = 0; i < count / 3; i++) { - if (k == 2) - pal[i] = 0xFFU << 24; - j = (ff_tget(&s->gb, type, s->le) >> off) << (k * 8); - pal[i] |= j; - } + for (i = 0; i < count / 3; i++) { + uint32_t p = 0xFF000000; + p |= (ff_tget(&pal_gb[0], type, s->le) >> off) << 16; + p |= (ff_tget(&pal_gb[1], type, s->le) >> off) << 8; + p |= ff_tget(&pal_gb[2], type, s->le) >> off; + s->palette[i] = p; } s->palette_is_set = 1; break; + } case TIFF_PLANAR: s->planar = value == 2; break; + case TIFF_YCBCR_SUBSAMPLING: + if (count != 2) { + av_log(s->avctx, AV_LOG_ERROR, "subsample count invalid\n"); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < count; i++) + s->subsampling[i] = ff_tget(&s->gb, type, s->le); + break; case TIFF_T4OPTIONS: if (s->compr == TIFF_G3) s->fax_opts = value; @@ -805,7 +927,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) s->geotag_count = 0; return -1; } - s->geotags = av_mallocz(sizeof(TiffGeoTag) * s->geotag_count); + s->geotags = av_mallocz_array(s->geotag_count, sizeof(TiffGeoTag)); if (!s->geotags) { av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); s->geotag_count = 0; @@ -827,7 +949,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) return AVERROR_INVALIDDATA; if (bytestream2_get_bytes_left(&s->gb) < count * sizeof(int64_t)) return AVERROR_INVALIDDATA; - dp = av_malloc(count * sizeof(double)); + dp = av_malloc_array(count, sizeof(double)); if (!dp) { av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); goto end; @@ -947,12 +1069,12 @@ static int decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "IFD offset is greater than image size\n"); return AVERROR_INVALIDDATA; } - s->le = le; + s->le = le; // TIFF_BPP is not a required tag and defaults to 1 - s->bppcount = s->bpp = 1; - s->invert = 0; - s->compr = TIFF_RAW; - s->fill_order = 0; + s->bppcount = s->bpp = 1; + s->photometric = TIFF_PHOTOMETRIC_NONE; + s->compr = TIFF_RAW; + s->fill_order = 0; free_geotags(s); // Reset these offsets so we can tell if they were set this frame @@ -1000,12 +1122,14 @@ static int decode_frame(AVCodecContext *avctx, if (s->stripsizesoff) { if (s->stripsizesoff >= (unsigned)avpkt->size) return AVERROR_INVALIDDATA; - bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, avpkt->size - s->stripsizesoff); + bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, + avpkt->size - s->stripsizesoff); } if (s->strippos) { if (s->strippos >= (unsigned)avpkt->size) return AVERROR_INVALIDDATA; - bytestream2_init(&stripdata, avpkt->data + s->strippos, avpkt->size - s->strippos); + bytestream2_init(&stripdata, avpkt->data + s->strippos, + avpkt->size - s->strippos); } if (s->rps <= 0) { @@ -1019,12 +1143,12 @@ static int decode_frame(AVCodecContext *avctx, dst = p->data[plane]; for (i = 0; i < s->height; i += s->rps) { if (s->stripsizesoff) - ssize = ff_tget(&stripsizes, s->sstype, s->le); + ssize = ff_tget(&stripsizes, s->sstype, le); else ssize = s->stripsize; if (s->strippos) - soff = ff_tget(&stripdata, s->sot, s->le); + soff = ff_tget(&stripdata, s->sot, le); else soff = s->stripoff; @@ -1032,7 +1156,7 @@ static int decode_frame(AVCodecContext *avctx, 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, + if ((ret = tiff_unpack_strip(s, p, dst, stride, avpkt->data + soff, ssize, i, FFMIN(s->rps, s->height - i))) < 0) { if (avctx->err_recognition & AV_EF_EXPLODE) return ret; @@ -1041,6 +1165,10 @@ static int decode_frame(AVCodecContext *avctx, dst += s->rps * stride; } if (s->predictor == 2) { + if (s->photometric == TIFF_PHOTOMETRIC_YCBCR) { + av_log(s->avctx, AV_LOG_ERROR, "predictor == 2 with YUV is unsupported"); + return AVERROR_PATCHWELCOME; + } dst = p->data[plane]; soff = s->bpp >> 3; if (s->planar) @@ -1073,12 +1201,12 @@ static int decode_frame(AVCodecContext *avctx, } } - if (s->invert) { + if (s->photometric == TIFF_PHOTOMETRIC_WHITE_IS_ZERO) { dst = p->data[plane]; for (i = 0; i < s->height; i++) { for (j = 0; j < p->linesize[plane]; j++) dst[j] = (s->avctx->pix_fmt == AV_PIX_FMT_PAL8 ? (1<bpp) - 1 : 255) - dst[j]; - dst += p->linesize[plane]; + dst += stride; } } } @@ -1101,6 +1229,8 @@ static av_cold int tiff_init(AVCodecContext *avctx) s->width = 0; s->height = 0; + s->subsampling[0] = + s->subsampling[1] = 1; s->avctx = avctx; ff_lzw_decode_open(&s->lzw); ff_ccitt_unpack_init(); diff --git a/libavcodec/tiff.h b/libavcodec/tiff.h index ae189b6fd..11e9f1629 100644 --- a/libavcodec/tiff.h +++ b/libavcodec/tiff.h @@ -40,7 +40,7 @@ enum TiffTags { TIFF_HEIGHT, TIFF_BPP, TIFF_COMPR, - TIFF_INVERT = 0x106, + TIFF_PHOTOMETRIC = 0x106, TIFF_FILL_ORDER = 0x10A, TIFF_DOCUMENT_NAME = 0x10D, TIFF_IMAGE_DESCRIPTION = 0x10E, @@ -146,6 +146,24 @@ enum TiffGeoTagKey { TIFF_VERTICAL_UNITS_GEOKEY = 4099 }; +enum TiffPhotometric { + TIFF_PHOTOMETRIC_NONE = -1, + TIFF_PHOTOMETRIC_WHITE_IS_ZERO, /* mono or grayscale, 0 is white */ + TIFF_PHOTOMETRIC_BLACK_IS_ZERO, /* mono or grayscale, 0 is black */ + TIFF_PHOTOMETRIC_RGB, /* RGB or RGBA*/ + TIFF_PHOTOMETRIC_PALETTE, /* Uses a palette */ + TIFF_PHOTOMETRIC_ALPHA_MASK, /* Transparency mask */ + TIFF_PHOTOMETRIC_SEPARATED, /* CMYK or some other ink set */ + TIFF_PHOTOMETRIC_YCBCR, /* YCbCr */ + TIFF_PHOTOMETRIC_CIE_LAB = 8, /* 1976 CIE L*a*b* */ + TIFF_PHOTOMETRIC_ICC_LAB, /* ICC L*a*b* */ + TIFF_PHOTOMETRIC_ITU_LAB, /* ITU L*a*b* */ + TIFF_PHOTOMETRIC_CFA = 32803, /* Color Filter Array (DNG) */ + TIFF_PHOTOMETRIC_LOG_L = 32844, /* CIE Log2(L) */ + TIFF_PHOTOMETRIC_LOG_LUV, /* CIE Log L*u*v* */ + TIFF_PHOTOMETRIC_LINEAR_RAW = 34892, /* Linear Raw (DNG) */ +}; + enum TiffGeoTagType { GEOTIFF_SHORT = 0, GEOTIFF_DOUBLE = 34736, diff --git a/libavcodec/tiff_common.c b/libavcodec/tiff_common.c index fc34087c6..35119af55 100644 --- a/libavcodec/tiff_common.c +++ b/libavcodec/tiff_common.c @@ -42,15 +42,13 @@ int ff_tis_ifd(unsigned tag) unsigned ff_tget_short(GetByteContext *gb, int le) { - unsigned v = le ? bytestream2_get_le16(gb) : bytestream2_get_be16(gb); - return v; + return le ? bytestream2_get_le16(gb) : bytestream2_get_be16(gb); } unsigned ff_tget_long(GetByteContext *gb, int le) { - unsigned v = le ? bytestream2_get_le32(gb) : bytestream2_get_be32(gb); - return v; + return le ? bytestream2_get_le32(gb) : bytestream2_get_be32(gb); } @@ -64,14 +62,10 @@ double ff_tget_double(GetByteContext *gb, int le) unsigned ff_tget(GetByteContext *gb, int type, int le) { switch (type) { - case TIFF_BYTE: - return bytestream2_get_byte(gb); - case TIFF_SHORT: - return ff_tget_short(gb, le); - case TIFF_LONG: - return ff_tget_long(gb, le); - default: - return UINT_MAX; + case TIFF_BYTE: return bytestream2_get_byte(gb); + case TIFF_SHORT: return ff_tget_short(gb, le); + case TIFF_LONG: return ff_tget_long(gb, le); + default: return UINT_MAX; } } @@ -182,7 +176,7 @@ int ff_tadd_doubles_metadata(int count, const char *name, const char *sep, int ff_tadd_shorts_metadata(int count, const char *name, const char *sep, - GetByteContext *gb, int le, AVDictionary **metadata) + GetByteContext *gb, int le, int is_signed, AVDictionary **metadata) { AVBPrint bp; char *ap; @@ -196,7 +190,8 @@ int ff_tadd_shorts_metadata(int count, const char *name, const char *sep, av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); for (i = 0; i < count; i++) { - av_bprintf(&bp, "%s%5i", auto_sep(count, sep, i, 8), ff_tget_short(gb, le)); + int v = is_signed ? (int16_t)ff_tget_short(gb, le) : ff_tget_short(gb, le); + av_bprintf(&bp, "%s%5i", auto_sep(count, sep, i, 8), v); } if ((i = av_bprint_finalize(&bp, &ap))) { @@ -213,7 +208,7 @@ int ff_tadd_shorts_metadata(int count, const char *name, const char *sep, int ff_tadd_bytes_metadata(int count, const char *name, const char *sep, - GetByteContext *gb, int le, AVDictionary **metadata) + GetByteContext *gb, int le, int is_signed, AVDictionary **metadata) { AVBPrint bp; char *ap; @@ -227,7 +222,8 @@ int ff_tadd_bytes_metadata(int count, const char *name, const char *sep, av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); for (i = 0; i < count; i++) { - av_bprintf(&bp, "%s%3i", auto_sep(count, sep, i, 16), bytestream2_get_byte(gb)); + int v = is_signed ? (int8_t)bytestream2_get_byte(gb) : bytestream2_get_byte(gb); + av_bprintf(&bp, "%s%3i", auto_sep(count, sep, i, 16), v); } if ((i = av_bprint_finalize(&bp, &ap))) { diff --git a/libavcodec/tiff_common.h b/libavcodec/tiff_common.h index 01a7b0891..03558c31a 100644 --- a/libavcodec/tiff_common.h +++ b/libavcodec/tiff_common.h @@ -67,16 +67,16 @@ static const uint16_t ifd_tags[] = { */ int ff_tis_ifd(unsigned tag); -/** Reads a short from the bytestream using given endianess. */ +/** Reads a short from the bytestream using given endianness. */ unsigned ff_tget_short(GetByteContext *gb, int le); -/** Reads a long from the bytestream using given endianess. */ +/** Reads a long from the bytestream using given endianness. */ unsigned ff_tget_long(GetByteContext *gb, int le); -/** Reads a double from the bytestream using given endianess. */ +/** Reads a double from the bytestream using given endianness. */ double ff_tget_double(GetByteContext *gb, int le); -/** Reads a byte from the bytestream using given endianess. */ +/** Reads a byte from the bytestream using given endianness. */ unsigned ff_tget(GetByteContext *gb, int type, int le); /** Returns an allocated string containing count @@ -121,13 +121,13 @@ int ff_tadd_doubles_metadata(int count, const char *name, const char *sep, * into the metadata dictionary. */ int ff_tadd_shorts_metadata(int count, const char *name, const char *sep, - GetByteContext *gb, int le, AVDictionary **metadata); + GetByteContext *gb, int le, int is_signed, AVDictionary **metadata); /** Adds count bytes converted to a string * into the metadata dictionary. */ int ff_tadd_bytes_metadata(int count, const char *name, const char *sep, - GetByteContext *gb, int le, AVDictionary **metadata); + GetByteContext *gb, int le, int is_signed, AVDictionary **metadata); /** Adds a string of count characters * into the metadata dictionary. @@ -136,7 +136,7 @@ int ff_tadd_string_metadata(int count, const char *name, GetByteContext *gb, int le, AVDictionary **metadata); /** Decodes a TIFF header from the input bytestream - * and sets the endianess in *le and the offset to + * and sets the endianness in *le and the offset to * the first IFD in *ifd_offset accordingly. */ int ff_tdecode_header(GetByteContext *gb, int *le, int *ifd_offset); diff --git a/libavcodec/tiffenc.c b/libavcodec/tiffenc.c index 7b1e5104b..5a61f1aef 100644 --- a/libavcodec/tiffenc.c +++ b/libavcodec/tiffenc.c @@ -58,7 +58,7 @@ typedef struct TiffEncoderContext { unsigned int bpp; ///< bits per pixel int compr; ///< compression level int bpp_tab_size; ///< bpp_tab size - int photometric_interpretation; ///< photometric interpretation + enum TiffPhotometric photometric_interpretation; ///< photometric interpretation int strips; ///< number of strips uint32_t *strip_sizes; unsigned int strip_sizes_size; @@ -238,6 +238,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, int ret = -1; int is_yuv = 0, alpha = 0; int shift_h, shift_v; + int packet_size; s->width = avctx->width; s->height = avctx->height; @@ -254,7 +255,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, alpha = 1; case AV_PIX_FMT_RGB48LE: case AV_PIX_FMT_RGB24: - s->photometric_interpretation = 2; + s->photometric_interpretation = TIFF_PHOTOMETRIC_RGB; break; case AV_PIX_FMT_GRAY8: avctx->bits_per_coded_sample = 0x28; @@ -262,13 +263,13 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, alpha = avctx->pix_fmt == AV_PIX_FMT_GRAY8A; case AV_PIX_FMT_GRAY16LE: case AV_PIX_FMT_MONOBLACK: - s->photometric_interpretation = 1; + s->photometric_interpretation = TIFF_PHOTOMETRIC_BLACK_IS_ZERO; break; case AV_PIX_FMT_PAL8: - s->photometric_interpretation = 3; + s->photometric_interpretation = TIFF_PHOTOMETRIC_PALETTE; break; case AV_PIX_FMT_MONOWHITE: - s->photometric_interpretation = 0; + s->photometric_interpretation = TIFF_PHOTOMETRIC_WHITE_IS_ZERO; break; case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUV422P: @@ -277,7 +278,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, case AV_PIX_FMT_YUV410P: case AV_PIX_FMT_YUV411P: av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &shift_h, &shift_v); - s->photometric_interpretation = 6; + s->photometric_interpretation = TIFF_PHOTOMETRIC_YCBCR; s->subsampling[0] = 1 << shift_h; s->subsampling[1] = 1 << shift_v; is_yuv = 1; @@ -304,9 +305,10 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, strips = (s->height - 1) / s->rps + 1; - if ((ret = ff_alloc_packet2(avctx, pkt, - avctx->width * avctx->height * s->bpp * 2 + - avctx->height * 4 + FF_MIN_BUFFER_SIZE)) < 0) + packet_size = avctx->height * ((avctx->width * s->bpp + 7) >> 3) * 2 + + avctx->height * 4 + FF_MIN_BUFFER_SIZE; + + if ((ret = ff_alloc_packet2(avctx, pkt, packet_size)) < 0) return ret; ptr = pkt->data; s->buf_start = pkt->data; @@ -426,9 +428,9 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (s->bpp_tab_size) add_entry(s, TIFF_BPP, TIFF_SHORT, s->bpp_tab_size, bpp_tab); - add_entry1(s, TIFF_COMPR, TIFF_SHORT, s->compr); - add_entry1(s, TIFF_INVERT, TIFF_SHORT, s->photometric_interpretation); - add_entry(s, TIFF_STRIP_OFFS, TIFF_LONG, strips, s->strip_offsets); + add_entry1(s, TIFF_COMPR, TIFF_SHORT, s->compr); + add_entry1(s, TIFF_PHOTOMETRIC, TIFF_SHORT, s->photometric_interpretation); + add_entry(s, TIFF_STRIP_OFFS, TIFF_LONG, strips, s->strip_offsets); if (s->bpp_tab_size) add_entry1(s, TIFF_SAMPLES_PER_PIXEL, TIFF_SHORT, s->bpp_tab_size); @@ -436,6 +438,13 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, add_entry1(s, TIFF_ROWSPERSTRIP, TIFF_LONG, s->rps); add_entry(s, TIFF_STRIP_SIZE, TIFF_LONG, strips, s->strip_sizes); add_entry(s, TIFF_XRES, TIFF_RATIONAL, 1, res); + if (avctx->sample_aspect_ratio.num > 0 && + avctx->sample_aspect_ratio.den > 0) { + AVRational y = av_mul_q(av_make_q(s->dpi, 1), + avctx->sample_aspect_ratio); + res[0] = y.num; + res[1] = y.den; + } add_entry(s, TIFF_YRES, TIFF_RATIONAL, 1, res); add_entry1(s, TIFF_RES_UNIT, TIFF_SHORT, 2); @@ -538,6 +547,7 @@ AVCodec ff_tiff_encoder = { .priv_data_size = sizeof(TiffEncoderContext), .init = encode_init, .close = encode_close, + .capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, .encode2 = encode_frame, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_PAL8, AV_PIX_FMT_GRAY8, diff --git a/libavcodec/tpeldsp.c b/libavcodec/tpeldsp.c new file mode 100644 index 000000000..cc4fed328 --- /dev/null +++ b/libavcodec/tpeldsp.c @@ -0,0 +1,333 @@ +/* + * thirdpel DSP functions + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * thirdpel DSP functions + */ + +#include + +#include "libavutil/attributes.h" +#include "tpeldsp.h" + +#define BIT_DEPTH 8 +#include "pel_template.c" + +static inline void put_tpel_pixels_mc00_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + switch (width) { + case 2: + put_pixels2_8_c(dst, src, stride, height); + break; + case 4: + put_pixels4_8_c(dst, src, stride, height); + break; + case 8: + put_pixels8_8_c(dst, src, stride, height); + break; + case 16: + put_pixels16_8_c(dst, src, stride, height); + break; + } +} + +static inline void put_tpel_pixels_mc10_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = ((2 * src[j] + src[j + 1] + 1) * + 683) >> 11; + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc20_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = ((src[j] + 2 * src[j + 1] + 1) * + 683) >> 11; + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc01_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = ((2 * src[j] + src[j + stride] + 1) * + 683) >> 11; + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc11_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = ((4 * src[j] + 3 * src[j + 1] + + 3 * src[j + stride] + 2 * src[j + stride + 1] + 6) * + 2731) >> 15; + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc12_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = ((3 * src[j] + 2 * src[j + 1] + + 4 * src[j + stride] + 3 * src[j + stride + 1] + 6) * + 2731) >> 15; + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc02_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = ((src[j] + 2 * src[j + stride] + 1) * + 683) >> 11; + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc21_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = ((3 * src[j] + 4 * src[j + 1] + + 2 * src[j + stride] + 3 * src[j + stride + 1] + 6) * + 2731) >> 15; + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc22_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = ((2 * src[j] + 3 * src[j + 1] + + 3 * src[j + stride] + 4 * src[j + stride + 1] + 6) * + 2731) >> 15; + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc00_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + switch (width) { + case 2: + avg_pixels2_8_c(dst, src, stride, height); + break; + case 4: + avg_pixels4_8_c(dst, src, stride, height); + break; + case 8: + avg_pixels8_8_c(dst, src, stride, height); + break; + case 16: + avg_pixels16_8_c(dst, src, stride, height); + break; + } +} + +static inline void avg_tpel_pixels_mc10_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = (dst[j] + + (((2 * src[j] + src[j + 1] + 1) * + 683) >> 11) + 1) >> 1; + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc20_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = (dst[j] + + (((src[j] + 2 * src[j + 1] + 1) * + 683) >> 11) + 1) >> 1; + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc01_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = (dst[j] + + (((2 * src[j] + src[j + stride] + 1) * + 683) >> 11) + 1) >> 1; + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc11_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = (dst[j] + + (((4 * src[j] + 3 * src[j + 1] + + 3 * src[j + stride] + 2 * src[j + stride + 1] + 6) * + 2731) >> 15) + 1) >> 1; + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc12_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = (dst[j] + + (((3 * src[j] + 2 * src[j + 1] + + 4 * src[j + stride] + 3 * src[j + stride + 1] + 6) * + 2731) >> 15) + 1) >> 1; + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc02_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = (dst[j] + + (((src[j] + 2 * src[j + stride] + 1) * + 683) >> 11) + 1) >> 1; + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc21_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = (dst[j] + + (((3 * src[j] + 4 * src[j + 1] + + 2 * src[j + stride] + 3 * src[j + stride + 1] + 6) * + 2731) >> 15) + 1) >> 1; + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc22_c(uint8_t *dst, const uint8_t *src, + int stride, int width, int height) +{ + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = (dst[j] + + (((2 * src[j] + 3 * src[j + 1] + + 3 * src[j + stride] + 4 * src[j + stride + 1] + 6) * + 2731) >> 15) + 1) >> 1; + src += stride; + dst += stride; + } +} + +av_cold void ff_tpeldsp_init(TpelDSPContext *c) +{ + c->put_tpel_pixels_tab[ 0] = put_tpel_pixels_mc00_c; + c->put_tpel_pixels_tab[ 1] = put_tpel_pixels_mc10_c; + c->put_tpel_pixels_tab[ 2] = put_tpel_pixels_mc20_c; + c->put_tpel_pixels_tab[ 4] = put_tpel_pixels_mc01_c; + c->put_tpel_pixels_tab[ 5] = put_tpel_pixels_mc11_c; + c->put_tpel_pixels_tab[ 6] = put_tpel_pixels_mc21_c; + c->put_tpel_pixels_tab[ 8] = put_tpel_pixels_mc02_c; + c->put_tpel_pixels_tab[ 9] = put_tpel_pixels_mc12_c; + c->put_tpel_pixels_tab[10] = put_tpel_pixels_mc22_c; + + c->avg_tpel_pixels_tab[ 0] = avg_tpel_pixels_mc00_c; + c->avg_tpel_pixels_tab[ 1] = avg_tpel_pixels_mc10_c; + c->avg_tpel_pixels_tab[ 2] = avg_tpel_pixels_mc20_c; + c->avg_tpel_pixels_tab[ 4] = avg_tpel_pixels_mc01_c; + c->avg_tpel_pixels_tab[ 5] = avg_tpel_pixels_mc11_c; + c->avg_tpel_pixels_tab[ 6] = avg_tpel_pixels_mc21_c; + c->avg_tpel_pixels_tab[ 8] = avg_tpel_pixels_mc02_c; + c->avg_tpel_pixels_tab[ 9] = avg_tpel_pixels_mc12_c; + c->avg_tpel_pixels_tab[10] = avg_tpel_pixels_mc22_c; +} diff --git a/libavcodec/tpeldsp.h b/libavcodec/tpeldsp.h new file mode 100644 index 000000000..3732f179f --- /dev/null +++ b/libavcodec/tpeldsp.h @@ -0,0 +1,59 @@ +/* + * thirdpel DSP functions + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * thirdpel DSP functions + */ + +#ifndef AVCODEC_TPELDSP_H +#define AVCODEC_TPELDSP_H + +#include + +/* add and put pixel (decoding) */ +// blocksizes for hpel_pixels_func are 8x4,8x8 16x8 16x16 +// h for hpel_pixels_func is limited to {width/2, width} but never larger +// than 16 and never smaller than 4 +typedef void (*tpel_mc_func)(uint8_t *block /* align width (8 or 16) */, + const uint8_t *pixels /* align 1 */, + int line_size, int w, int h); + +/** + * thirdpel DSP context + */ +typedef struct TpelDSPContext { + /** + * Thirdpel motion compensation with rounding (a + b + 1) >> 1. + * this is an array[12] of motion compensation functions for the + * 9 thirdpel positions
+ * *pixels_tab[xthirdpel + 4 * ythirdpel] + * @param block destination where the result is stored + * @param pixels source + * @param line_size number of bytes in a horizontal line of block + * @param h height + */ + tpel_mc_func put_tpel_pixels_tab[11]; // FIXME individual func ptr per width? + tpel_mc_func avg_tpel_pixels_tab[11]; // FIXME individual func ptr per width? +} TpelDSPContext; + +void ff_tpeldsp_init(TpelDSPContext *c); + +#endif /* AVCODEC_TPELDSP_H */ diff --git a/libavcodec/truemotion1.c b/libavcodec/truemotion1.c index ed7995924..660ecf541 100644 --- a/libavcodec/truemotion1.c +++ b/libavcodec/truemotion1.c @@ -412,6 +412,8 @@ static int truemotion1_decode_header(TrueMotion1Context *s) if ((ret = ff_set_dimensions(s->avctx, s->w, s->h)) < 0) return ret; + ff_set_sar(s->avctx, s->avctx->sample_aspect_ratio); + av_fast_malloc(&s->vert_pred, &s->vert_pred_size, s->avctx->width * sizeof(unsigned int)); if (!s->vert_pred) return AVERROR(ENOMEM); diff --git a/libavcodec/truemotion2.c b/libavcodec/truemotion2.c index a1683f5b1..18d7c1e68 100644 --- a/libavcodec/truemotion2.c +++ b/libavcodec/truemotion2.c @@ -24,10 +24,12 @@ * Duck TrueMotion2 decoder. */ +#include + #include "avcodec.h" +#include "bswapdsp.h" #include "bytestream.h" #include "get_bits.h" -#include "dsputil.h" #include "internal.h" #define TM2_ESCAPE 0x80000000 @@ -61,7 +63,7 @@ typedef struct TM2Context { AVFrame *pic; GetBitContext gb; - DSPContext dsp; + BswapDSPContext bdsp; uint8_t *buffer; int buffer_size; @@ -246,7 +248,8 @@ static inline int tm2_read_header(TM2Context *ctx, const uint8_t *buf) case TM2_NEW_HEADER_MAGIC: return 0; default: - av_log(ctx->avctx, AV_LOG_ERROR, "Not a TM2 header: 0x%08X\n", magic); + av_log(ctx->avctx, AV_LOG_ERROR, "Not a TM2 header: 0x%08"PRIX32"\n", + magic); return AVERROR_INVALIDDATA; } } @@ -259,7 +262,8 @@ static int tm2_read_deltas(TM2Context *ctx, int stream_id) d = get_bits(&ctx->gb, 9); mb = get_bits(&ctx->gb, 5); - if ((d < 1) || (d > TM2_DELTAS) || (mb < 1) || (mb > 32)) { + av_assert2(mb < 32); + if ((d < 1) || (d > TM2_DELTAS) || (mb < 1)) { av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect delta table: %i deltas x %i bits\n", d, mb); return AVERROR_INVALIDDATA; } @@ -885,7 +889,8 @@ static int decode_frame(AVCodecContext *avctx, if ((ret = ff_reget_buffer(avctx, p)) < 0) return ret; - l->dsp.bswap_buf((uint32_t*)l->buffer, (const uint32_t*)buf, buf_size >> 2); + l->bdsp.bswap_buf((uint32_t *) l->buffer, (const uint32_t *) buf, + buf_size >> 2); if ((ret = tm2_read_header(l, l->buffer)) < 0) { return ret; @@ -936,7 +941,7 @@ static av_cold int decode_init(AVCodecContext *avctx) if (!l->pic) return AVERROR(ENOMEM); - ff_dsputil_init(&l->dsp, avctx); + ff_bswapdsp_init(&l->bdsp); l->last = av_malloc_array(w >> 2, 4 * sizeof(*l->last) ); l->clast = av_malloc_array(w >> 2, 4 * sizeof(*l->clast)); diff --git a/libavcodec/truespeech.c b/libavcodec/truespeech.c index d3e3b20e9..b00a45fb0 100644 --- a/libavcodec/truespeech.c +++ b/libavcodec/truespeech.c @@ -22,7 +22,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" -#include "dsputil.h" +#include "bswapdsp.h" #include "get_bits.h" #include "internal.h" @@ -36,7 +36,7 @@ * TrueSpeech decoder context */ typedef struct { - DSPContext dsp; + BswapDSPContext bdsp; /* input data */ DECLARE_ALIGNED(16, uint8_t, buffer)[32]; int16_t vector[8]; ///< input vector: 5/5/4/4/4/3/3/3 @@ -70,7 +70,7 @@ static av_cold int truespeech_decode_init(AVCodecContext * avctx) avctx->channel_layout = AV_CH_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_S16; - ff_dsputil_init(&c->dsp, avctx); + ff_bswapdsp_init(&c->bdsp); return 0; } @@ -79,7 +79,7 @@ static void truespeech_read_frame(TSContext *dec, const uint8_t *input) { GetBitContext gb; - dec->dsp.bswap_buf((uint32_t *)dec->buffer, (const uint32_t *)input, 8); + dec->bdsp.bswap_buf((uint32_t *) dec->buffer, (const uint32_t *) input, 8); init_get_bits(&gb, dec->buffer, 32 * 8); dec->vector[7] = ts_codebook[7][get_bits(&gb, 3)]; diff --git a/libavcodec/tscc2.c b/libavcodec/tscc2.c index bdc75256b..92210f7d3 100644 --- a/libavcodec/tscc2.c +++ b/libavcodec/tscc2.c @@ -24,6 +24,8 @@ * TechSmith Screen Codec 2 decoder */ +#include + #define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" @@ -88,14 +90,14 @@ static av_cold int init_vlcs(TSCC2Context *c) return 0; } -#define DEQUANT(val, q) ((q * val + 0x80) >> 8) +#define DEQUANT(val, q) (((q) * (val) + 0x80) >> 8) #define DCT1D(d0, d1, d2, d3, s0, s1, s2, s3, OP) \ OP(d0, 5 * ((s0) + (s1) + (s2)) + 2 * (s3)); \ OP(d1, 5 * ((s0) - (s2) - (s3)) + 2 * (s1)); \ OP(d2, 5 * ((s0) - (s2) + (s3)) - 2 * (s1)); \ OP(d3, 5 * ((s0) - (s1) + (s2)) - 2 * (s3)); \ -#define COL_OP(a, b) a = b +#define COL_OP(a, b) a = (b) #define ROW_OP(a, b) a = ((b) + 0x20) >> 6 static void tscc2_idct4_put(int *in, int q[3], uint8_t *dst, int stride) @@ -227,7 +229,8 @@ static int tscc2_decode_frame(AVCodecContext *avctx, void *data, bytestream2_init(&gb, buf, buf_size); frame_type = bytestream2_get_byte(&gb); if (frame_type > 1) { - av_log(avctx, AV_LOG_ERROR, "Incorrect frame type %d\n", frame_type); + av_log(avctx, AV_LOG_ERROR, "Incorrect frame type %"PRIu32"\n", + frame_type); return AVERROR_INVALIDDATA; } @@ -309,7 +312,7 @@ static int tscc2_decode_frame(AVCodecContext *avctx, void *data, } } if (bytestream2_get_bytes_left(&gb) < size) { - av_log(avctx, AV_LOG_ERROR, "Invalid slice size (%d/%d)\n", + av_log(avctx, AV_LOG_ERROR, "Invalid slice size (%"PRIu32"/%u)\n", size, bytestream2_get_bytes_left(&gb)); return AVERROR_INVALIDDATA; } diff --git a/libavcodec/tta.c b/libavcodec/tta.c index 19cdd8c7b..5fdbac8d4 100644 --- a/libavcodec/tta.c +++ b/libavcodec/tta.c @@ -104,12 +104,12 @@ static int allocate_buffers(AVCodecContext *avctx) TTAContext *s = avctx->priv_data; if (s->bps < 3) { - s->decode_buffer = av_mallocz(sizeof(int32_t)*s->frame_length*s->channels); + s->decode_buffer = av_mallocz_array(sizeof(int32_t)*s->frame_length, s->channels); if (!s->decode_buffer) return AVERROR(ENOMEM); } else s->decode_buffer = NULL; - s->ch_ctx = av_malloc(avctx->channels * sizeof(*s->ch_ctx)); + s->ch_ctx = av_malloc_array(avctx->channels, sizeof(*s->ch_ctx)); if (!s->ch_ctx) { av_freep(&s->decode_buffer); return AVERROR(ENOMEM); @@ -312,7 +312,7 @@ static int tta_decode_frame(AVCodecContext *avctx, void *data, filter->shift, filter->round); // fixed order prediction -#define PRED(x, k) (int32_t)((((uint64_t)x << k) - x) >> k) +#define PRED(x, k) (int32_t)((((uint64_t)(x) << (k)) - (x)) >> (k)) switch (s->bps) { case 1: *p += PRED(*predictor, 4); break; case 2: diff --git a/libavcodec/ttaenc.c b/libavcodec/ttaenc.c index e95dd6b22..ccd41a90c 100644 --- a/libavcodec/ttaenc.c +++ b/libavcodec/ttaenc.c @@ -53,7 +53,7 @@ static av_cold int tta_encode_init(AVCodecContext *avctx) s->bps = avctx->bits_per_raw_sample >> 3; avctx->frame_size = 256 * avctx->sample_rate / 245; - s->ch_ctx = av_malloc(avctx->channels * sizeof(*s->ch_ctx)); + s->ch_ctx = av_malloc_array(avctx->channels, sizeof(*s->ch_ctx)); if (!s->ch_ctx) return AVERROR(ENOMEM); @@ -144,7 +144,7 @@ static int tta_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } temp = value; -#define PRED(x, k) (int32_t)((((uint64_t)x << k) - x) >> k) +#define PRED(x, k) (int32_t)((((uint64_t)(x) << (k)) - (x)) >> (k)) switch (s->bps) { case 1: value -= PRED(c->predictor, 4); break; case 2: diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 7ffe6c652..9fa8e1604 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -43,6 +43,7 @@ #include "avcodec.h" #include "dsputil.h" #include "libavutil/opt.h" +#include "mpegvideo.h" #include "thread.h" #include "frame_thread_encoder.h" #include "internal.h" @@ -255,6 +256,21 @@ int ff_set_dimensions(AVCodecContext *s, int width, int height) return ret; } +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", + sar.num, sar.den); + avctx->sample_aspect_ratio = (AVRational){ 0, 1 }; + return ret; + } else { + avctx->sample_aspect_ratio = sar; + } + return 0; +} + int ff_side_data_update_matrix_encoding(AVFrame *frame, enum AVMatrixEncoding matrix_encoding) { @@ -285,6 +301,7 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, switch (s->pix_fmt) { case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUYV422: + case AV_PIX_FMT_YVYU422: case AV_PIX_FMT_UYVY422: case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUV440P: @@ -473,7 +490,7 @@ int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, planar = av_sample_fmt_is_planar(sample_fmt); if (planar && nb_channels > AV_NUM_DATA_POINTERS) { - if (!(frame->extended_data = av_mallocz(nb_channels * + if (!(frame->extended_data = av_mallocz_array(nb_channels, sizeof(*frame->extended_data)))) return AVERROR(ENOMEM); } else { @@ -514,11 +531,6 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align); - if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) { - w += EDGE_WIDTH * 2; - h += EDGE_WIDTH * 2; - } - do { // NOTE: do not align linesizes individually, this breaks e.g. assumptions // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2 @@ -608,9 +620,9 @@ static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) frame->linesize[0] = pool->linesize[0]; if (planes > AV_NUM_DATA_POINTERS) { - frame->extended_data = av_mallocz(planes * sizeof(*frame->extended_data)); + frame->extended_data = av_mallocz_array(planes, sizeof(*frame->extended_data)); frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS; - frame->extended_buf = av_mallocz(frame->nb_extended_buf * + frame->extended_buf = av_mallocz_array(frame->nb_extended_buf, sizeof(*frame->extended_buf)); if (!frame->extended_data || !frame->extended_buf) { av_freep(&frame->extended_data); @@ -647,9 +659,6 @@ fail: static int video_get_buffer(AVCodecContext *s, AVFrame *pic) { FramePool *pool = s->internal->pool; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format); - int pixel_size = desc->comp[0].step_minus1 + 1; - int h_chroma_shift, v_chroma_shift; int i; if (pic->data[0] != NULL) { @@ -660,27 +669,14 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic) memset(pic->data, 0, sizeof(pic->data)); pic->extended_data = pic->data; - av_pix_fmt_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift); - for (i = 0; i < 4 && pool->pools[i]; i++) { - const int h_shift = i == 0 ? 0 : h_chroma_shift; - const int v_shift = i == 0 ? 0 : v_chroma_shift; - int is_planar = pool->pools[2] || (i==0 && s->pix_fmt == AV_PIX_FMT_GRAY8); - pic->linesize[i] = pool->linesize[i]; pic->buf[i] = av_buffer_pool_get(pool->pools[i]); if (!pic->buf[i]) goto fail; - // no edge if EDGE EMU or not planar YUV - if ((s->flags & CODEC_FLAG_EMU_EDGE) || !is_planar) - pic->data[i] = pic->buf[i]->data; - else { - pic->data[i] = pic->buf[i]->data + - FFALIGN((pic->linesize[i] * EDGE_WIDTH >> v_shift) + - (pixel_size * EDGE_WIDTH >> h_shift), pool->stride_align[i]); - } + pic->data[i] = pic->buf[i]->data; } for (; i < AV_NUM_DATA_POINTERS; i++) { pic->data[i] = NULL; @@ -746,11 +742,36 @@ FF_ENABLE_DEPRECATION_WARNINGS int ff_init_buffer_info(AVCodecContext *avctx, AVFrame *frame) { - if (avctx->internal->pkt) { - frame->pkt_pts = avctx->internal->pkt->pts; - av_frame_set_pkt_pos (frame, avctx->internal->pkt->pos); - av_frame_set_pkt_duration(frame, avctx->internal->pkt->duration); - av_frame_set_pkt_size (frame, avctx->internal->pkt->size); + AVPacket *pkt = avctx->internal->pkt; + + if (pkt) { + uint8_t *packet_sd; + AVFrameSideData *frame_sd; + int size; + frame->pkt_pts = pkt->pts; + av_frame_set_pkt_pos (frame, pkt->pos); + av_frame_set_pkt_duration(frame, pkt->duration); + av_frame_set_pkt_size (frame, pkt->size); + + /* 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); + } } else { frame->pkt_pts = AV_NOPTS_VALUE; av_frame_set_pkt_pos (frame, -1); @@ -759,15 +780,34 @@ int ff_init_buffer_info(AVCodecContext *avctx, AVFrame *frame) } frame->reordered_opaque = avctx->reordered_opaque; +#if FF_API_AVFRAME_COLORSPACE + if (frame->color_primaries == AVCOL_PRI_UNSPECIFIED) + frame->color_primaries = avctx->color_primaries; + if (frame->color_trc == AVCOL_TRC_UNSPECIFIED) + frame->color_trc = avctx->color_trc; + if (av_frame_get_colorspace(frame) == AVCOL_SPC_UNSPECIFIED) + av_frame_set_colorspace(frame, avctx->colorspace); + if (av_frame_get_color_range(frame) == AVCOL_RANGE_UNSPECIFIED) + av_frame_set_color_range(frame, avctx->color_range); + if (frame->chroma_location == AVCHROMA_LOC_UNSPECIFIED) + frame->chroma_location = avctx->chroma_sample_location; +#endif + switch (avctx->codec->type) { case AVMEDIA_TYPE_VIDEO: frame->format = avctx->pix_fmt; if (!frame->sample_aspect_ratio.num) frame->sample_aspect_ratio = avctx->sample_aspect_ratio; - if (av_frame_get_colorspace(frame) == AVCOL_SPC_UNSPECIFIED) - av_frame_set_colorspace(frame, avctx->colorspace); - if (av_frame_get_color_range(frame) == AVCOL_RANGE_UNSPECIFIED) - av_frame_set_color_range(frame, avctx->color_range); + + if (frame->width && frame->height && + av_image_check_sar(frame->width, frame->height, + frame->sample_aspect_ratio) < 0) { + av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\n", + frame->sample_aspect_ratio.num, + frame->sample_aspect_ratio.den); + frame->sample_aspect_ratio = (AVRational){ 0, 1 }; + } + break; case AVMEDIA_TYPE_AUDIO: if (!frame->sample_rate) @@ -827,8 +867,14 @@ static void compat_release_buffer(void *opaque, uint8_t *data) FF_ENABLE_DEPRECATION_WARNINGS #endif +int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) +{ + return ff_init_buffer_info(avctx, frame); +} + static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) { + const AVHWAccel *hwaccel = avctx->hwaccel; int override_dimensions = 1; int ret; @@ -845,9 +891,17 @@ static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) override_dimensions = 0; } } + ret = ff_decode_frame_props(avctx, frame); + if (ret < 0) + return ret; if ((ret = ff_init_buffer_info(avctx, frame)) < 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 /* @@ -874,7 +928,7 @@ FF_DISABLE_DEPRECATION_WARNINGS * avcodec_default_get_buffer */ if (frame->buf[0]) - goto end; + goto end0; priv = av_mallocz(sizeof(*priv)); if (!priv) { @@ -931,7 +985,7 @@ do { \ 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->extended_buf = av_malloc_array(sizeof(*frame->extended_buf), frame->nb_extended_buf); if (!frame->extended_buf) { ret = AVERROR(ENOMEM); @@ -950,7 +1004,7 @@ do { \ av_buffer_unref(&dummy_buf); -end: +end0: frame->width = avctx->width; frame->height = avctx->height; @@ -967,6 +1021,7 @@ FF_ENABLE_DEPRECATION_WARNINGS ret = avctx->get_buffer2(avctx, frame, flags); +end: if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions) { frame->width = avctx->width; frame->height = avctx->height; @@ -1001,11 +1056,8 @@ static int reget_buffer_internal(AVCodecContext *avctx, AVFrame *frame) if (!frame->data[0]) return ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF); - if (av_frame_is_writable(frame)) { - frame->pkt_pts = avctx->internal->pkt ? avctx->internal->pkt->pts : AV_NOPTS_VALUE; - frame->reordered_opaque = avctx->reordered_opaque; - return 0; - } + if (av_frame_is_writable(frame)) + return ff_decode_frame_props(avctx, frame); tmp = av_frame_alloc(); if (!tmp) @@ -1096,6 +1148,65 @@ enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const en return fmt[0]; } +static AVHWAccel *find_hwaccel(enum AVCodecID codec_id, + enum AVPixelFormat pix_fmt) +{ + AVHWAccel *hwaccel = NULL; + + while ((hwaccel = av_hwaccel_next(hwaccel))) + if (hwaccel->id == codec_id + && hwaccel->pix_fmt == pix_fmt) + return hwaccel; + return NULL; +} + + +int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) +{ + const AVPixFmtDescriptor *desc; + enum AVPixelFormat ret = avctx->get_format(avctx, fmt); + + desc = av_pix_fmt_desc_get(ret); + if (!desc) + return AV_PIX_FMT_NONE; + + if (avctx->hwaccel && avctx->hwaccel->uninit) + avctx->hwaccel->uninit(avctx); + av_freep(&avctx->internal->hwaccel_priv_data); + avctx->hwaccel = NULL; + + if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL && + !(avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)) { + AVHWAccel *hwaccel; + int err; + + 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; + } + + 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; + } + + return ret; +} + #if FF_API_AVFRAME_LAVC void avcodec_get_frame_defaults(AVFrame *frame) { @@ -1259,6 +1370,16 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code ff_set_dimensions(avctx, 0, 0); } + if (avctx->width > 0 && avctx->height > 0) { + if (av_image_check_sar(avctx->width, avctx->height, + avctx->sample_aspect_ratio) < 0) { + av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\n", + avctx->sample_aspect_ratio.num, + avctx->sample_aspect_ratio.den); + avctx->sample_aspect_ratio = (AVRational){ 0, 1 }; + } + } + /* if the decoder init function was already called previously, * free the already allocated subtitle_header before overwriting it */ if (av_codec_is_decoder(codec)) @@ -1544,7 +1665,11 @@ int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size) av_fast_padded_malloc(&avctx->internal->byte_buffer, &avctx->internal->byte_buffer_size, size); avpkt->data = avctx->internal->byte_buffer; avpkt->size = avctx->internal->byte_buffer_size; +#if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS avpkt->destruct = NULL; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } } @@ -1716,7 +1841,11 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, } avpkt->buf = user_pkt.buf; avpkt->data = user_pkt.data; +#if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS avpkt->destruct = user_pkt.destruct; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } else { if (av_dup_packet(avpkt) < 0) { ret = AVERROR(ENOMEM); @@ -1917,7 +2046,11 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, } avpkt->buf = user_pkt.buf; avpkt->data = user_pkt.data; +#if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS avpkt->destruct = user_pkt.destruct; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } else { if (av_dup_packet(avpkt) < 0) { ret = AVERROR(ENOMEM); @@ -2445,7 +2578,8 @@ end: iconv_close(cd); return ret; #else - av_assert0(!"requesting subtitles recoding without iconv"); + av_log(avctx, AV_LOG_ERROR, "requesting subtitles recoding without iconv"); + return AVERROR(EINVAL); #endif } @@ -2581,37 +2715,17 @@ void avsubtitle_free(AVSubtitle *sub) memset(sub, 0, sizeof(AVSubtitle)); } -av_cold int ff_codec_close_recursive(AVCodecContext *avctx) -{ - int ret = 0; - - ff_unlock_avcodec(); - - ret = avcodec_close(avctx); - - ff_lock_avcodec(NULL); - return ret; -} - av_cold int avcodec_close(AVCodecContext *avctx) { - int ret; - if (!avctx) return 0; - ret = ff_lock_avcodec(avctx); - if (ret < 0) - return ret; - if (avcodec_is_open(avctx)) { FramePool *pool = avctx->internal->pool; int i; if (CONFIG_FRAME_THREAD_ENCODER && avctx->internal->frame_thread_encoder && avctx->thread_count > 1) { - ff_unlock_avcodec(); ff_frame_thread_encoder_free(avctx); - ff_lock_avcodec(avctx); } if (HAVE_THREADS && avctx->internal->thread_ctx) ff_thread_free(avctx); @@ -2624,6 +2738,11 @@ av_cold int avcodec_close(AVCodecContext *avctx) for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++) av_buffer_pool_uninit(&pool->pools[i]); av_freep(&avctx->internal->pool); + + if (avctx->hwaccel && avctx->hwaccel->uninit) + avctx->hwaccel->uninit(avctx); + av_freep(&avctx->internal->hwaccel_priv_data); + av_freep(&avctx->internal); } @@ -2636,7 +2755,6 @@ av_cold int avcodec_close(AVCodecContext *avctx) avctx->codec = NULL; avctx->active_thread_type = 0; - ff_unlock_avcodec(); return 0; } @@ -2646,15 +2764,25 @@ static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id) //This is for future deprecatec codec ids, its empty since //last major bump but will fill up again over time, please don't remove it // case AV_CODEC_ID_UTVIDEO_DEPRECATED: return AV_CODEC_ID_UTVIDEO; - case AV_CODEC_ID_OPUS_DEPRECATED: return AV_CODEC_ID_OPUS; - case AV_CODEC_ID_TAK_DEPRECATED : return AV_CODEC_ID_TAK; - case AV_CODEC_ID_PCM_S24LE_PLANAR_DEPRECATED : return AV_CODEC_ID_PCM_S24LE_PLANAR; - case AV_CODEC_ID_PCM_S32LE_PLANAR_DEPRECATED : return AV_CODEC_ID_PCM_S32LE_PLANAR; - case AV_CODEC_ID_ESCAPE130_DEPRECATED : return AV_CODEC_ID_ESCAPE130; - case AV_CODEC_ID_G2M_DEPRECATED : return AV_CODEC_ID_G2M; - case AV_CODEC_ID_WEBP_DEPRECATED: return AV_CODEC_ID_WEBP; - case AV_CODEC_ID_HEVC_DEPRECATED: return AV_CODEC_ID_HEVC; - default : return id; + case AV_CODEC_ID_BRENDER_PIX_DEPRECATED : return AV_CODEC_ID_BRENDER_PIX; + case AV_CODEC_ID_OPUS_DEPRECATED : return AV_CODEC_ID_OPUS; + case AV_CODEC_ID_TAK_DEPRECATED : return AV_CODEC_ID_TAK; + case AV_CODEC_ID_PAF_AUDIO_DEPRECATED : return AV_CODEC_ID_PAF_AUDIO; + case AV_CODEC_ID_PCM_S24LE_PLANAR_DEPRECATED : return AV_CODEC_ID_PCM_S24LE_PLANAR; + case AV_CODEC_ID_PCM_S32LE_PLANAR_DEPRECATED : return AV_CODEC_ID_PCM_S32LE_PLANAR; + case AV_CODEC_ID_ADPCM_VIMA_DEPRECATED : return AV_CODEC_ID_ADPCM_VIMA; + case AV_CODEC_ID_ESCAPE130_DEPRECATED : return AV_CODEC_ID_ESCAPE130; + case AV_CODEC_ID_EXR_DEPRECATED : return AV_CODEC_ID_EXR; + case AV_CODEC_ID_G2M_DEPRECATED : return AV_CODEC_ID_G2M; + case AV_CODEC_ID_PAF_VIDEO_DEPRECATED : return AV_CODEC_ID_PAF_VIDEO; + case AV_CODEC_ID_WEBP_DEPRECATED : return AV_CODEC_ID_WEBP; + case AV_CODEC_ID_HEVC_DEPRECATED : return AV_CODEC_ID_HEVC; + case AV_CODEC_ID_MVC1_DEPRECATED : return AV_CODEC_ID_MVC1; + case AV_CODEC_ID_MVC2_DEPRECATED : return AV_CODEC_ID_MVC2; + case AV_CODEC_ID_SANM_DEPRECATED : return AV_CODEC_ID_SANM; + case AV_CODEC_ID_SGIRLE_DEPRECATED : return AV_CODEC_ID_SGIRLE; + case AV_CODEC_ID_VP7_DEPRECATED : return AV_CODEC_ID_VP7; + default : return id; } } @@ -2958,6 +3086,10 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id) case AV_CODEC_ID_ADPCM_G722: case AV_CODEC_ID_ADPCM_YAMAHA: return 4; + case AV_CODEC_ID_DSD_LSBF: + case AV_CODEC_ID_DSD_MSBF: + case AV_CODEC_ID_DSD_LSBF_PLANAR: + case AV_CODEC_ID_DSD_MSBF_PLANAR: case AV_CODEC_ID_PCM_ALAW: case AV_CODEC_ID_PCM_MULAW: case AV_CODEC_ID_PCM_S8: @@ -3249,8 +3381,8 @@ void av_log_ask_for_sample(void *avc, const char *msg, ...) if (msg) av_vlog(avc, AV_LOG_WARNING, msg, argument_list); av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample " - "of this file to ftp://upload.ffmpeg.org/MPlayer/incoming/ " - "and contact the ffmpeg-devel mailing list.\n"); + "of this file to ftp://upload.ffmpeg.org/incoming/ " + "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)\n"); va_end(argument_list); } @@ -3274,20 +3406,6 @@ AVHWAccel *av_hwaccel_next(AVHWAccel *hwaccel) return hwaccel ? hwaccel->next : first_hwaccel; } -AVHWAccel *ff_find_hwaccel(AVCodecContext *avctx) -{ - enum AVCodecID codec_id = avctx->codec->id; - enum AVPixelFormat pix_fmt = avctx->pix_fmt; - - AVHWAccel *hwaccel = NULL; - - while ((hwaccel = av_hwaccel_next(hwaccel))) - if (hwaccel->id == codec_id - && hwaccel->pix_fmt == pix_fmt) - return hwaccel; - return NULL; -} - int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) { if (lockmgr_cb) { @@ -3363,7 +3481,7 @@ unsigned int avpriv_toupper4(unsigned int x) return av_toupper(x & 0xFF) + (av_toupper((x >> 8) & 0xFF) << 8) + (av_toupper((x >> 16) & 0xFF) << 16) + - (av_toupper((x >> 24) & 0xFF) << 24); +((unsigned)av_toupper((x >> 24) & 0xFF) << 24); } int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src) @@ -3389,7 +3507,7 @@ int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src) enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) { - return avctx->get_format(avctx, fmt); + return ff_get_format(avctx, fmt); } int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) @@ -3400,7 +3518,8 @@ int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) { - av_frame_unref(f->f); + if (f->f) + av_frame_unref(f->f); } void ff_thread_finish_setup(AVCodecContext *avctx) diff --git a/libavcodec/utvideo.h b/libavcodec/utvideo.h index c00179ed9..78c3ec54d 100644 --- a/libavcodec/utvideo.h +++ b/libavcodec/utvideo.h @@ -29,7 +29,8 @@ #include "libavutil/common.h" #include "avcodec.h" -#include "dsputil.h" +#include "bswapdsp.h" +#include "huffyuvencdsp.h" enum { PRED_NONE = 0, @@ -65,7 +66,8 @@ extern const int ff_ut_rgb_order[4]; typedef struct UtvideoContext { AVCodecContext *avctx; - DSPContext dsp; + BswapDSPContext bdsp; + HuffYUVEncDSPContext hdsp; uint32_t frame_info_size, flags, frame_info; int planes; diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 1c7677345..afd56ea1b 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -24,13 +24,14 @@ * Ut Video decoder */ +#include #include #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "bswapdsp.h" #include "bytestream.h" #include "get_bits.h" -#include "dsputil.h" #include "thread.h" #include "utvideo.h" @@ -142,8 +143,9 @@ 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); - c->dsp.bswap_buf((uint32_t *) c->slice_bits, (uint32_t *) c->slice_bits, - (slice_data_end - slice_data_start + 3) >> 2); + c->bdsp.bswap_buf((uint32_t *) c->slice_bits, + (uint32_t *) c->slice_bits, + (slice_data_end - slice_data_start + 3) >> 2); init_get_bits(&gb, c->slice_bits, slice_size * 8); prev = 0x80; @@ -154,7 +156,7 @@ static int decode_plane(UtvideoContext *c, int plane_no, "Slice decoding ran out of bits\n"); goto fail; } - pix = get_vlc2(&gb, vlc.table, vlc.bits, 4); + pix = get_vlc2(&gb, vlc.table, vlc.bits, 3); if (pix < 0) { av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n"); goto fail; @@ -367,7 +369,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return AVERROR_INVALIDDATA; } c->frame_info = bytestream2_get_le32u(&gb); - av_log(avctx, AV_LOG_DEBUG, "frame information flags %X\n", c->frame_info); + av_log(avctx, AV_LOG_DEBUG, "frame information flags %"PRIX32"\n", + c->frame_info); c->frame_pred = (c->frame_info >> 8) & 3; @@ -469,7 +472,7 @@ static av_cold int decode_init(AVCodecContext *avctx) c->avctx = avctx; - ff_dsputil_init(&c->dsp, avctx); + ff_bswapdsp_init(&c->bdsp); if (avctx->extradata_size < 16) { av_log(avctx, AV_LOG_ERROR, @@ -481,14 +484,14 @@ static av_cold int decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", avctx->extradata[3], avctx->extradata[2], avctx->extradata[1], avctx->extradata[0]); - av_log(avctx, AV_LOG_DEBUG, "Original format %X\n", + av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", AV_RB32(avctx->extradata + 4)); c->frame_info_size = AV_RL32(avctx->extradata + 8); c->flags = AV_RL32(avctx->extradata + 12); if (c->frame_info_size != 4) avpriv_request_sample(avctx, "Frame info not 4 bytes"); - av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08X\n", c->flags); + av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08"PRIX32"\n", c->flags); c->slices = (c->flags >> 24) + 1; c->compression = c->flags & 1; c->interlaced = c->flags & 0x800; diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c index 0db85a871..cbd34d01f 100644 --- a/libavcodec/utvideoenc.c +++ b/libavcodec/utvideoenc.c @@ -28,9 +28,10 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "internal.h" +#include "bswapdsp.h" #include "bytestream.h" #include "put_bits.h" -#include "dsputil.h" +#include "huffyuvencdsp.h" #include "mathops.h" #include "utvideo.h" #include "huffman.h" @@ -108,7 +109,8 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } - ff_dsputil_init(&c->dsp, avctx); + ff_bswapdsp_init(&c->bdsp); + ff_huffyuvencdsp_init(&c->hdsp); /* Check the prediction method, and error out if unsupported */ if (avctx->prediction_method < 0 || avctx->prediction_method > 4) { @@ -312,7 +314,7 @@ static void median_predict(UtvideoContext *c, uint8_t *src, uint8_t *dst, int st /* Rest of the coded part uses median prediction */ for (j = 1; j < height; j++) { - c->dsp.sub_hfyu_median_prediction(dst, src - stride, src, width, &A, &B); + c->hdsp.sub_hfyu_median_pred(dst, src - stride, src, width, &A, &B); dst += width; src += stride; } @@ -466,7 +468,7 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src, } /* Calculate huffman lengths */ - if ((ret = ff_huff_gen_len_table(lengths, counts, 256)) < 0) + if ((ret = ff_huff_gen_len_table(lengths, counts, 256, 1)) < 0) return ret; /* @@ -500,9 +502,9 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src, slice_len = offset - slice_len; /* Byteswap the written huffman codes */ - c->dsp.bswap_buf((uint32_t *) c->slice_bits, - (uint32_t *) c->slice_bits, - slice_len >> 2); + c->bdsp.bswap_buf((uint32_t *) c->slice_bits, + (uint32_t *) c->slice_bits, + slice_len >> 2); /* Write the offset to the stream */ bytestream2_put_le32(pb, offset); @@ -640,6 +642,7 @@ AVCodec ff_utvideo_encoder = { .init = utvideo_encode_init, .encode2 = utvideo_encode_frame, .close = utvideo_encode_close, + .capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c index 7fdaaf091..8eb8a66f1 100644 --- a/libavcodec/vaapi_h264.c +++ b/libavcodec/vaapi_h264.c @@ -22,6 +22,7 @@ #include "vaapi_internal.h" #include "h264.h" +#include "mpegutils.h" /** * @file @@ -51,14 +52,14 @@ static void init_vaapi_pic(VAPictureH264 *va_pic) * supersedes pic's field type if nonzero. */ static void fill_vaapi_pic(VAPictureH264 *va_pic, - Picture *pic, + 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); + 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; @@ -89,7 +90,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, Picture *pic) +static int dpb_add(DPB *dpb, H264Picture *pic) { int i; @@ -98,7 +99,7 @@ static int dpb_add(DPB *dpb, Picture *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)) { + if (va_pic->picture_id == ff_vaapi_get_surface_id(&pic->f)) { VAPictureH264 temp_va_pic; fill_vaapi_pic(&temp_va_pic, pic, 0); @@ -133,13 +134,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++) { - Picture * const pic = h->short_ref[i]; + H264Picture * const pic = h->short_ref[i]; if (pic && pic->reference && dpb_add(&dpb, pic) < 0) return -1; } for (i = 0; i < 16; i++) { - Picture * const pic = h->long_ref[i]; + H264Picture * const pic = h->long_ref[i]; if (pic && pic->reference && dpb_add(&dpb, pic) < 0) return -1; } @@ -155,7 +156,7 @@ 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], - Picture *ref_list, + H264Picture *ref_list, unsigned int ref_count) { unsigned int i, n = 0; @@ -298,7 +299,7 @@ static int vaapi_h264_end_frame(AVCodecContext *avctx) if (ret < 0) goto finish; - ret = ff_vaapi_render_picture(vactx, ff_vaapi_get_surface_id(h->cur_pic_ptr)); + ret = ff_vaapi_render_picture(vactx, ff_vaapi_get_surface_id(&h->cur_pic_ptr->f)); if (ret < 0) goto finish; diff --git a/libavcodec/vaapi_internal.h b/libavcodec/vaapi_internal.h index 1ac0e9fe3..918c718d1 100644 --- a/libavcodec/vaapi_internal.h +++ b/libavcodec/vaapi_internal.h @@ -35,10 +35,10 @@ * @{ */ -/** Extract VASurfaceID from a Picture */ -static inline VASurfaceID ff_vaapi_get_surface_id(Picture *pic) +/** Extract VASurfaceID from an AVFrame */ +static inline VASurfaceID ff_vaapi_get_surface_id(AVFrame *pic) { - return (uintptr_t)pic->f.data[3]; + return (uintptr_t)pic->data[3]; } /** Common AVHWAccel.end_frame() implementation */ diff --git a/libavcodec/vaapi_mpeg.c b/libavcodec/vaapi_mpeg.c index 5afa40600..63879e5fe 100644 --- a/libavcodec/vaapi_mpeg.c +++ b/libavcodec/vaapi_mpeg.c @@ -35,7 +35,7 @@ int ff_vaapi_mpeg_end_frame(AVCodecContext *avctx) goto finish; ret = ff_vaapi_render_picture(vactx, - ff_vaapi_get_surface_id(s->current_picture_ptr)); + ff_vaapi_get_surface_id(s->current_picture_ptr->f)); if (ret < 0) goto finish; diff --git a/libavcodec/vaapi_mpeg2.c b/libavcodec/vaapi_mpeg2.c index cdc70eefa..0d9059b26 100644 --- a/libavcodec/vaapi_mpeg2.c +++ b/libavcodec/vaapi_mpeg2.c @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "mpegutils.h" #include "vaapi_internal.h" /** Reconstruct bitstream f_code */ @@ -72,10 +73,10 @@ static int vaapi_mpeg2_start_frame(AVCodecContext *avctx, av_unused const uint8_ switch (s->pict_type) { case AV_PICTURE_TYPE_B: - pic_param->backward_reference_picture = ff_vaapi_get_surface_id(&s->next_picture); + pic_param->backward_reference_picture = ff_vaapi_get_surface_id(s->next_picture.f); // fall-through case AV_PICTURE_TYPE_P: - pic_param->forward_reference_picture = ff_vaapi_get_surface_id(&s->last_picture); + pic_param->forward_reference_picture = ff_vaapi_get_surface_id(s->last_picture.f); break; } @@ -89,7 +90,7 @@ static int vaapi_mpeg2_start_frame(AVCodecContext *avctx, av_unused const uint8_ iq_matrix->load_chroma_non_intra_quantiser_matrix = 1; for (i = 0; i < 64; i++) { - int n = s->dsp.idct_permutation[ff_zigzag_direct[i]]; + int n = s->idsp.idct_permutation[ff_zigzag_direct[i]]; iq_matrix->intra_quantiser_matrix[i] = s->intra_matrix[n]; iq_matrix->non_intra_quantiser_matrix[i] = s->inter_matrix[n]; iq_matrix->chroma_intra_quantiser_matrix[i] = s->chroma_intra_matrix[n]; diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c index 9ed007f2d..19adb2b50 100644 --- a/libavcodec/vaapi_mpeg4.c +++ b/libavcodec/vaapi_mpeg4.c @@ -81,7 +81,7 @@ static int vaapi_mpeg4_start_frame(AVCodecContext *avctx, av_unused const uint8_ pic_param->quant_precision = s->quant_precision; pic_param->vop_fields.value = 0; /* reset all bits */ pic_param->vop_fields.bits.vop_coding_type = s->pict_type - AV_PICTURE_TYPE_I; - pic_param->vop_fields.bits.backward_reference_vop_coding_type = s->pict_type == AV_PICTURE_TYPE_B ? s->next_picture.f.pict_type - AV_PICTURE_TYPE_I : 0; + pic_param->vop_fields.bits.backward_reference_vop_coding_type = s->pict_type == AV_PICTURE_TYPE_B ? s->next_picture.f->pict_type - AV_PICTURE_TYPE_I : 0; pic_param->vop_fields.bits.vop_rounding_type = s->no_rounding; pic_param->vop_fields.bits.intra_dc_vlc_thr = mpeg4_get_intra_dc_vlc_thr(ctx); pic_param->vop_fields.bits.top_field_first = s->top_field_first; @@ -95,9 +95,9 @@ static int vaapi_mpeg4_start_frame(AVCodecContext *avctx, av_unused const uint8_ pic_param->TRD = s->pp_time; if (s->pict_type == AV_PICTURE_TYPE_B) - pic_param->backward_reference_picture = ff_vaapi_get_surface_id(&s->next_picture); + pic_param->backward_reference_picture = ff_vaapi_get_surface_id(s->next_picture.f); if (s->pict_type != AV_PICTURE_TYPE_I) - pic_param->forward_reference_picture = ff_vaapi_get_surface_id(&s->last_picture); + pic_param->forward_reference_picture = ff_vaapi_get_surface_id(s->last_picture.f); /* Fill in VAIQMatrixBufferMPEG4 */ /* Only the first inverse quantisation method uses the weighting matrices */ @@ -109,7 +109,7 @@ static int vaapi_mpeg4_start_frame(AVCodecContext *avctx, av_unused const uint8_ iq_matrix->load_non_intra_quant_mat = 1; for (i = 0; i < 64; i++) { - int n = s->dsp.idct_permutation[ff_zigzag_direct[i]]; + int n = s->idsp.idct_permutation[ff_zigzag_direct[i]]; iq_matrix->intra_quant_mat[i] = s->intra_matrix[n]; iq_matrix->non_intra_quant_mat[i] = s->inter_matrix[n]; } diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c index 266fa3c5b..bba46d337 100644 --- a/libavcodec/vaapi_vc1.c +++ b/libavcodec/vaapi_vc1.c @@ -258,10 +258,10 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t switch (s->pict_type) { case AV_PICTURE_TYPE_B: - pic_param->backward_reference_picture = ff_vaapi_get_surface_id(&s->next_picture); + pic_param->backward_reference_picture = ff_vaapi_get_surface_id(s->next_picture.f); // fall-through case AV_PICTURE_TYPE_P: - pic_param->forward_reference_picture = ff_vaapi_get_surface_id(&s->last_picture); + pic_param->forward_reference_picture = ff_vaapi_get_surface_id(s->last_picture.f); break; } diff --git a/libavcodec/vble.c b/libavcodec/vble.c index a8c71ed9c..1bf25ba59 100644 --- a/libavcodec/vble.c +++ b/libavcodec/vble.c @@ -27,14 +27,14 @@ #define BITSTREAM_READER_LE #include "avcodec.h" -#include "dsputil.h" #include "get_bits.h" +#include "huffyuvdsp.h" #include "internal.h" #include "mathops.h" typedef struct { AVCodecContext *avctx; - DSPContext dsp; + HuffYUVDSPContext hdsp; int size; uint8_t *val; ///< This array first holds the lengths of vlc symbols and then their value. @@ -100,7 +100,8 @@ static void vble_restore_plane(VBLEContext *ctx, AVFrame *pic, if (i) { left = 0; left_top = dst[-stride]; - ctx->dsp.add_hfyu_median_prediction(dst, dst-stride, val, width, &left, &left_top); + ctx->hdsp.add_hfyu_median_pred(dst, dst - stride, val, + width, &left, &left_top); } else { dst[0] = val[0]; for (j = 1; j < width; j++) @@ -181,7 +182,7 @@ static av_cold int vble_decode_init(AVCodecContext *avctx) /* Stash for later use */ ctx->avctx = avctx; - ff_dsputil_init(&ctx->dsp, avctx); + ff_huffyuvdsp_init(&ctx->hdsp); avctx->pix_fmt = AV_PIX_FMT_YUV420P; avctx->bits_per_raw_sample = 8; @@ -189,7 +190,7 @@ static av_cold int vble_decode_init(AVCodecContext *avctx) ctx->size = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); - ctx->val = av_malloc(ctx->size * sizeof(*ctx->val)); + ctx->val = av_malloc_array(ctx->size, sizeof(*ctx->val)); if (!ctx->val) { av_log(avctx, AV_LOG_ERROR, "Could not allocate values buffer.\n"); diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c index 49d4885dd..d23efecc1 100644 --- a/libavcodec/vc1.c +++ b/libavcodec/vc1.c @@ -372,7 +372,11 @@ int ff_vc1_decode_sequence_header(AVCodecContext *avctx, VC1Context *v, GetBitCo if (v->res_sprite) { int w = get_bits(gb, 11); int h = get_bits(gb, 11); - avcodec_set_dimensions(v->s.avctx, w, h); + int ret = ff_set_dimensions(v->s.avctx, w, h); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to set dimensions %d %d\n", w, h); + return ret; + } skip_bits(gb, 5); //frame rate v->res_x8 = get_bits1(gb); if (get_bits1(gb)) { // something to do with DC VLC selection @@ -467,6 +471,7 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb) v->s.avctx->width * h, 1 << 30); } + ff_set_sar(v->s.avctx, v->s.avctx->sample_aspect_ratio); av_log(v->s.avctx, AV_LOG_DEBUG, "Aspect: %i:%i\n", v->s.avctx->sample_aspect_ratio.num, v->s.avctx->sample_aspect_ratio.den); @@ -516,6 +521,7 @@ int ff_vc1_decode_entry_point(AVCodecContext *avctx, VC1Context *v, GetBitContex { int i; int w,h; + int ret; av_log(avctx, AV_LOG_DEBUG, "Entry point: %08X\n", show_bits_long(gb, 32)); v->broken_link = get_bits1(gb); @@ -545,7 +551,11 @@ int ff_vc1_decode_entry_point(AVCodecContext *avctx, VC1Context *v, GetBitContex w = v->max_coded_width; h = v->max_coded_height; } - avcodec_set_dimensions(avctx, w, h); + if ((ret = ff_set_dimensions(avctx, w, h)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to set dimensions %d %d\n", w, h); + return ret; + } + if (v->extended_mv) v->extended_dmv = get_bits1(gb); if ((v->range_mapy_flag = get_bits1(gb))) { @@ -859,7 +869,7 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) v->s.pict_type = (v->fptype & 1) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; if (v->fptype & 4) v->s.pict_type = (v->fptype & 1) ? AV_PICTURE_TYPE_BI : AV_PICTURE_TYPE_B; - v->s.current_picture_ptr->f.pict_type = v->s.pict_type; + v->s.current_picture_ptr->f->pict_type = v->s.pict_type; if (!v->pic_header_flag) goto parse_common_info; } @@ -1706,5 +1716,7 @@ av_cold int ff_vc1_init_common(VC1Context *v) v->pq = -1; v->mvrange = 0; /* 7.1.1.18, p80 */ + ff_vc1dsp_init(&v->vc1dsp); + return 0; } diff --git a/libavcodec/vc1_parser.c b/libavcodec/vc1_parser.c index cc29ce148..0021febaf 100644 --- a/libavcodec/vc1_parser.c +++ b/libavcodec/vc1_parser.c @@ -30,122 +30,88 @@ #include "vc1.h" #include "get_bits.h" +/** The maximum number of bytes of a sequence, entry point or + * frame header whose values we pay any attention to */ +#define UNESCAPED_THRESHOLD 37 + +/** The maximum number of bytes of a sequence, entry point or + * frame header which must be valid memory (because they are + * used to update the bitstream cache in skip_bits() calls) + */ +#define UNESCAPED_LIMIT 144 + +typedef enum { + NO_MATCH, + ONE_ZERO, + TWO_ZEROS, + ONE +} VC1ParseSearchState; + typedef struct { ParseContext pc; VC1Context v; + uint8_t prev_start_code; + size_t bytes_to_skip; + uint8_t unesc_buffer[UNESCAPED_LIMIT]; + size_t unesc_index; + VC1ParseSearchState search_state; } VC1ParseContext; -static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx, - const uint8_t *buf, int buf_size) +static void vc1_extract_header(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t *buf, int buf_size) { + /* Parse the header we just finished unescaping */ VC1ParseContext *vpc = s->priv_data; GetBitContext gb; - const uint8_t *start, *end, *next; - uint8_t *buf2 = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); - + int ret; vpc->v.s.avctx = avctx; vpc->v.parse_only = 1; - vpc->v.first_pic_header_flag = 1; - next = buf; - s->repeat_pict = 0; + init_get_bits(&gb, buf, buf_size * 8); + switch (vpc->prev_start_code) { + case VC1_CODE_SEQHDR & 0xFF: + ff_vc1_decode_sequence_header(avctx, &vpc->v, &gb); + break; + case VC1_CODE_ENTRYPOINT & 0xFF: + ff_vc1_decode_entry_point(avctx, &vpc->v, &gb); + break; + case VC1_CODE_FRAME & 0xFF: + if(vpc->v.profile < PROFILE_ADVANCED) + ret = ff_vc1_parse_frame_header (&vpc->v, &gb); + else + ret = ff_vc1_parse_frame_header_adv(&vpc->v, &gb); - for(start = buf, end = buf + buf_size; next < end; start = next){ - int buf2_size, size; - int ret; - - next = find_next_marker(start + 4, end); - size = next - start - 4; - buf2_size = vc1_unescape_buffer(start + 4, size, buf2); - init_get_bits(&gb, buf2, buf2_size * 8); - if(size <= 0) continue; - switch(AV_RB32(start)){ - case VC1_CODE_SEQHDR: - ff_vc1_decode_sequence_header(avctx, &vpc->v, &gb); + if (ret < 0) break; - case VC1_CODE_ENTRYPOINT: - ff_vc1_decode_entry_point(avctx, &vpc->v, &gb); - break; - case VC1_CODE_FRAME: - if(vpc->v.profile < PROFILE_ADVANCED) - ret = ff_vc1_parse_frame_header (&vpc->v, &gb); - else - ret = ff_vc1_parse_frame_header_adv(&vpc->v, &gb); - if (ret < 0) - break; + /* keep AV_PICTURE_TYPE_BI internal to VC1 */ + if (vpc->v.s.pict_type == AV_PICTURE_TYPE_BI) + s->pict_type = AV_PICTURE_TYPE_B; + else + s->pict_type = vpc->v.s.pict_type; - /* keep AV_PICTURE_TYPE_BI internal to VC1 */ - if (vpc->v.s.pict_type == AV_PICTURE_TYPE_BI) - s->pict_type = AV_PICTURE_TYPE_B; - else - s->pict_type = vpc->v.s.pict_type; - - if (avctx->ticks_per_frame > 1){ - // process pulldown flags - s->repeat_pict = 1; - // Pulldown flags are only valid when 'broadcast' has been set. - // So ticks_per_frame will be 2 - if (vpc->v.rff){ - // repeat field - s->repeat_pict = 2; - }else if (vpc->v.rptfrm){ - // repeat frames - s->repeat_pict = vpc->v.rptfrm * 2 + 1; - } + if (avctx->ticks_per_frame > 1){ + // process pulldown flags + s->repeat_pict = 1; + // Pulldown flags are only valid when 'broadcast' has been set. + // So ticks_per_frame will be 2 + if (vpc->v.rff){ + // repeat field + s->repeat_pict = 2; + }else if (vpc->v.rptfrm){ + // repeat frames + s->repeat_pict = vpc->v.rptfrm * 2 + 1; } - - if (vpc->v.broadcast && vpc->v.interlace && !vpc->v.psf) - s->field_order = vpc->v.tff ? AV_FIELD_TT : AV_FIELD_BB; - else - s->field_order = AV_FIELD_PROGRESSIVE; - - break; + }else{ + s->repeat_pict = 0; } + + if (vpc->v.broadcast && vpc->v.interlace && !vpc->v.psf) + s->field_order = vpc->v.tff ? AV_FIELD_TT : AV_FIELD_BB; + else + s->field_order = AV_FIELD_PROGRESSIVE; + + break; } - - av_free(buf2); -} - -/** - * Find the end of the current frame in the bitstream. - * @return the position of the first byte of the next frame, or -1 - */ -static int vc1_find_frame_end(ParseContext *pc, const uint8_t *buf, - int buf_size) { - int pic_found, i; - uint32_t state; - - pic_found= pc->frame_start_found; - state= pc->state; - - i=0; - if(!pic_found){ - for(i=0; iframe_start_found=0; - pc->state=-1; - return i-3; - } - } - } - pc->frame_start_found= pic_found; - pc->state= state; - return END_NOT_FOUND; } static int vc1_parse(AVCodecParserContext *s, @@ -153,22 +119,127 @@ static int vc1_parse(AVCodecParserContext *s, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size) { + /* Here we do the searching for frame boundaries and headers at + * the same time. Only a minimal amount at the start of each + * header is unescaped. */ VC1ParseContext *vpc = s->priv_data; - int next; + int pic_found = vpc->pc.frame_start_found; + uint8_t *unesc_buffer = vpc->unesc_buffer; + size_t unesc_index = vpc->unesc_index; + VC1ParseSearchState search_state = vpc->search_state; + int next = END_NOT_FOUND; + int i = vpc->bytes_to_skip; - if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ - next= buf_size; - }else{ - next= vc1_find_frame_end(&vpc->pc, buf, buf_size); + if (pic_found && buf_size == 0) { + /* EOF considered as end of frame */ + memset(unesc_buffer + unesc_index, 0, UNESCAPED_THRESHOLD - unesc_index); + vc1_extract_header(s, avctx, unesc_buffer, unesc_index); + next = 0; + } + while (i < buf_size) { + int start_code_found = 0; + uint8_t b; + while (i < buf_size && unesc_index < UNESCAPED_THRESHOLD) { + b = buf[i++]; + unesc_buffer[unesc_index++] = b; + if (search_state <= ONE_ZERO) + search_state = b ? NO_MATCH : search_state + 1; + else if (search_state == TWO_ZEROS) { + if (b == 1) + search_state = ONE; + else if (b > 1) { + if (b == 3) + unesc_index--; // swallow emulation prevention byte + search_state = NO_MATCH; + } + } + else { // search_state == ONE + // Header unescaping terminates early due to detection of next start code + search_state = NO_MATCH; + start_code_found = 1; + break; + } + } + if ((s->flags & PARSER_FLAG_COMPLETE_FRAMES) && + unesc_index >= UNESCAPED_THRESHOLD && + vpc->prev_start_code == (VC1_CODE_FRAME & 0xFF)) + { + // No need to keep scanning the rest of the buffer for + // start codes if we know it contains a complete frame and + // we've already unescaped all we need of the frame header + vc1_extract_header(s, avctx, unesc_buffer, unesc_index); + break; + } + if (unesc_index >= UNESCAPED_THRESHOLD && !start_code_found) { + while (i < buf_size) { + if (search_state == NO_MATCH) { + i += vpc->v.vc1dsp.vc1_find_start_code_candidate(buf + i, buf_size - i); + if (i < buf_size) { + search_state = ONE_ZERO; + } + i++; + } else { + b = buf[i++]; + if (search_state == ONE_ZERO) + search_state = b ? NO_MATCH : TWO_ZEROS; + else if (search_state == TWO_ZEROS) { + if (b >= 1) + search_state = b == 1 ? ONE : NO_MATCH; + } + else { // search_state == ONE + search_state = NO_MATCH; + start_code_found = 1; + break; + } + } + } + } + if (start_code_found) { + vc1_extract_header(s, avctx, unesc_buffer, unesc_index); + vpc->prev_start_code = b; + unesc_index = 0; + + if (!(s->flags & PARSER_FLAG_COMPLETE_FRAMES)) { + if (!pic_found && (b == (VC1_CODE_FRAME & 0xFF) || b == (VC1_CODE_FIELD & 0xFF))) { + pic_found = 1; + } + else if (pic_found && b != (VC1_CODE_FIELD & 0xFF) && b != (VC1_CODE_SLICE & 0xFF)) { + next = i - 4; + pic_found = b == (VC1_CODE_FRAME & 0xFF); + break; + } + } + } + } + + vpc->pc.frame_start_found = pic_found; + vpc->unesc_index = unesc_index; + vpc->search_state = search_state; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { if (ff_combine_frame(&vpc->pc, next, &buf, &buf_size) < 0) { + vpc->bytes_to_skip = 0; *poutbuf = NULL; *poutbuf_size = 0; return buf_size; } } - vc1_extract_headers(s, avctx, buf, buf_size); + vpc->v.first_pic_header_flag = 1; + + /* If we return with a valid pointer to a combined frame buffer + * then on the next call then we'll have been unhelpfully rewound + * by up to 4 bytes (depending upon whether the start code + * overlapped the input buffer, and if so by how much). We don't + * want this: it will either cause spurious second detections of + * the start code we've already seen, or cause extra bytes to be + * inserted at the start of the unescaped buffer. */ + vpc->bytes_to_skip = 4; + if (next < 0 && next != END_NOT_FOUND) + vpc->bytes_to_skip += next; *poutbuf = buf; *poutbuf_size = buf_size; @@ -199,6 +270,11 @@ static av_cold int vc1_parse_init(AVCodecParserContext *s) { VC1ParseContext *vpc = s->priv_data; vpc->v.s.slice_context_count = 1; + vpc->v.first_pic_header_flag = 1; + vpc->prev_start_code = 0; + vpc->bytes_to_skip = 0; + vpc->unesc_index = 0; + vpc->search_state = NO_MATCH; return ff_vc1_init_common(&vpc->v); } diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 593e69f9f..06deb7fad 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -29,9 +29,12 @@ #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" @@ -65,9 +68,9 @@ 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]; + 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]; } } @@ -94,24 +97,24 @@ static void vc1_put_signed_blocks_clamped(VC1Context *v) fieldtx = v->fieldtx_plane[topleft_mb_pos]; stride_y = s->linesize << fieldtx; v_dist = (16 - fieldtx) >> (fieldtx == 0); - s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][0], - s->dest[0] - 16 * s->linesize - 16, - stride_y); - s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][1], - s->dest[0] - 16 * s->linesize - 8, - stride_y); - s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][2], - s->dest[0] - v_dist * s->linesize - 16, - stride_y); - s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][3], - s->dest[0] - v_dist * s->linesize - 8, - stride_y); - s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][4], - s->dest[1] - 8 * s->uvlinesize - 8, - s->uvlinesize); - s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][5], - s->dest[2] - 8 * s->uvlinesize - 8, - s->uvlinesize); + 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; @@ -119,24 +122,24 @@ static void vc1_put_signed_blocks_clamped(VC1Context *v) fieldtx = v->fieldtx_plane[top_mb_pos]; stride_y = s->linesize << fieldtx; v_dist = fieldtx ? 15 : 8; - s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][0], - s->dest[0] - 16 * s->linesize, - stride_y); - s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][1], - s->dest[0] - 16 * s->linesize + 8, - stride_y); - s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][2], - s->dest[0] - v_dist * s->linesize, - stride_y); - s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][3], - s->dest[0] - v_dist * s->linesize + 8, - stride_y); - s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][4], - s->dest[1] - 8 * s->uvlinesize, - s->uvlinesize); - s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][5], - s->dest[2] - 8 * s->uvlinesize, - s->uvlinesize); + 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); } } @@ -340,7 +343,7 @@ static void vc1_mc_1mv(VC1Context *v, int dir) if ((!v->field_mode || (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) && - !v->s.last_picture.f.data[0]) + !v->s.last_picture.f->data[0]) return; mx = s->mv[dir][0][0]; @@ -372,24 +375,24 @@ static void vc1_mc_1mv(VC1Context *v, int dir) } 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]; + 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]; + 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]; + 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; @@ -422,9 +425,9 @@ static void vc1_mc_1mv(VC1Context *v, int dir) 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]; + 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 */ @@ -437,7 +440,8 @@ static void vc1_mc_1mv(VC1Context *v, int dir) || 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; + uint8_t *ubuf = s->edge_emu_buffer + 19 * s->linesize; + uint8_t *vbuf = ubuf + 9 * s->uvlinesize; srcY -= s->mspel * (1 + s->linesize); s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY, @@ -446,18 +450,18 @@ static void vc1_mc_1mv(VC1Context *v, int dir) 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->vdsp.emulated_edge_mc(ubuf, 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->vdsp.emulated_edge_mc(vbuf, 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; + srcU = ubuf; + srcV = vbuf; /* if we deal with range reduction we need to scale source blocks */ if (v->rangeredfrm) { int i, j; @@ -509,11 +513,7 @@ static void vc1_mc_1mv(VC1Context *v, int dir) 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); + v->vc1dsp.put_vc1_mspel_pixels_tab[0][dxy](s->dest[0] , srcY , s->linesize, v->rnd); } else { // hpel mc - always used for luma dxy = (my & 2) | ((mx & 2) >> 1); if (!v->rnd) @@ -561,7 +561,7 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg) if ((!v->field_mode || (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) && - !v->s.last_picture.f.data[0]) + !v->s.last_picture.f->data[0]) return; mx = s->mv[dir][n][0]; @@ -569,16 +569,16 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg) 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]; + 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]; + 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]; + srcY = s->next_picture.f->data[0]; luty = v->next_luty; use_ic = v->next_use_ic; } @@ -678,7 +678,7 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg) srcY += src_y * s->linesize + src_x; if (v->field_mode && v->ref_field_type[dir]) - srcY += s->current_picture_ptr->f.linesize[0]; + srcY += s->current_picture_ptr->f->linesize[0]; if (fieldmv && !(src_y & 1)) v_edge_pos--; @@ -727,9 +727,9 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg) 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); + v->vc1dsp.avg_vc1_mspel_pixels_tab[1][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); + v->vc1dsp.put_vc1_mspel_pixels_tab[1][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) @@ -808,7 +808,7 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir) uint8_t (*lutuv)[256]; int use_ic; - if (!v->field_mode && !v->s.last_picture.f.data[0]) + if (!v->field_mode && !v->s.last_picture.f->data[0]) return; if (s->flags & CODEC_FLAG_GRAY) return; @@ -839,7 +839,7 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir) 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]) + 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; @@ -870,19 +870,19 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir) 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]; + 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]; + 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]; + srcU = s->next_picture.f->data[1]; + srcV = s->next_picture.f->data[2]; lutuv = v->next_lutuv; use_ic = v->next_use_ic; } @@ -897,8 +897,8 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir) if (v->field_mode) { if (chroma_ref_type) { - srcU += s->current_picture_ptr->f.linesize[1]; - srcV += s->current_picture_ptr->f.linesize[2]; + srcU += s->current_picture_ptr->f->linesize[1]; + srcV += s->current_picture_ptr->f->linesize[2]; } } @@ -1003,13 +1003,13 @@ static void vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg) 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]; - srcV = s->next_picture.f.data[2]; + srcU = s->next_picture.f->data[1]; + srcV = s->next_picture.f->data[2]; lutuv = v->next_lutuv; use_ic = v->next_use_ic; } else { - srcU = s->last_picture.f.data[1]; - srcV = s->last_picture.f.data[2]; + srcU = s->last_picture.f->data[1]; + srcV = s->last_picture.f->data[2]; lutuv = v->last_lutuv; use_ic = v->last_use_ic; } @@ -1904,7 +1904,7 @@ static void vc1_interp_mc(VC1Context *v) 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]) + if (!v->field_mode && !v->s.next_picture.f->data[0]) return; mx = s->mv[1][0][0]; @@ -1921,9 +1921,9 @@ static void vc1_interp_mc(VC1Context *v) 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]; + 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); @@ -1947,9 +1947,9 @@ static void vc1_interp_mc(VC1Context *v) 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]; + 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 */ @@ -1961,7 +1961,8 @@ static void vc1_interp_mc(VC1Context *v) 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; + uint8_t *ubuf = s->edge_emu_buffer + 19 * s->linesize; + uint8_t *vbuf = ubuf + 9 * s->uvlinesize; srcY -= s->mspel * (1 + s->linesize); s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY, @@ -1970,18 +1971,18 @@ static void vc1_interp_mc(VC1Context *v) 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->vdsp.emulated_edge_mc(ubuf, 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->vdsp.emulated_edge_mc(vbuf, 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; + srcU = ubuf; + srcV = vbuf; /* if we deal with range reduction we need to scale source blocks */ if (v->rangeredfrm) { int i, j; @@ -2038,11 +2039,7 @@ static void vc1_interp_mc(VC1Context *v) 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); + v->vc1dsp.avg_vc1_mspel_pixels_tab[0][dxy](s->dest[0] + off , srcY , s->linesize, v->rnd); } else { // hpel mc dxy = (my & 2) | ((mx & 2) >> 1); @@ -3020,7 +3017,7 @@ static int vc1_decode_intra_block(VC1Context *v, int16_t block[64], int n, int scale; int q1, q2 = 0; - s->dsp.clear_block(block); + s->bdsp.clear_block(block); /* XXX: Guard against dumb values of mquant */ mquant = (mquant < 1) ? 0 : ((mquant > 31) ? 31 : mquant); @@ -3227,7 +3224,7 @@ static int vc1_decode_p_block(VC1Context *v, int16_t block[64], int n, int ttblk = ttmb & 7; int pat = 0; - s->dsp.clear_block(block); + 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)]; @@ -3280,7 +3277,7 @@ static int vc1_decode_p_block(VC1Context *v, int16_t block[64], int n, v->vc1dsp.vc1_inv_trans_8x8_dc(dst, linesize, block); else { v->vc1dsp.vc1_inv_trans_8x8(block); - s->dsp.add_pixels_clamped(block, dst, linesize); + s->idsp.add_pixels_clamped(block, dst, linesize); } } break; @@ -3611,7 +3608,10 @@ static int vc1_decode_p_mb(VC1Context *v) if (v->rangeredfrm) for (j = 0; j < 64; j++) s->block[i][j] <<= 1; - s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); + 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); @@ -3719,8 +3719,10 @@ static int vc1_decode_p_mb(VC1Context *v) if (v->rangeredfrm) for (j = 0; j < 64; j++) s->block[i][j] <<= 1; - s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, - (i & 4) ? s->uvlinesize : s->linesize); + 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); @@ -3869,7 +3871,9 @@ static int vc1_decode_p_mb_intfr(VC1Context *v) stride_y = s->uvlinesize; off = 0; } - s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, stride_y); + s->idsp.put_signed_pixels_clamped(s->block[i], + s->dest[dst_idx] + off, + stride_y); //TODO: loop filter } @@ -4031,7 +4035,10 @@ static int vc1_decode_p_mb_intfi(VC1Context *v) continue; v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); - s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i & 4) ? s->uvlinesize : s->linesize); + s->idsp.put_signed_pixels_clamped(s->block[i], + s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize + : s->linesize); // TODO: loop filter } } else { @@ -4233,7 +4240,10 @@ static void vc1_decode_b_mb(VC1Context *v) if (v->rangeredfrm) for (j = 0; j < 64; j++) s->block[i][j] <<= 1; - s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); + 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, @@ -4305,7 +4315,10 @@ static void vc1_decode_b_mb_intfi(VC1Context *v) for (j = 0; j < 64; j++) s->block[i][j] <<= 1; off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); - s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i & 4) ? s->uvlinesize : s->linesize); + 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 { @@ -4531,7 +4544,9 @@ static int vc1_decode_b_mb_intfr(VC1Context *v) stride_y = s->uvlinesize; off = 0; } - s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, stride_y); + 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; @@ -4805,7 +4820,7 @@ static void vc1_decode_i_blocks(VC1Context *v) dst[3] = dst[2] + 8; dst[4] = s->dest[1]; dst[5] = s->dest[2]; - s->dsp.clear_blocks(s->block[0]); + 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; @@ -4835,12 +4850,16 @@ static void vc1_decode_i_blocks(VC1Context *v) if (v->rangeredfrm) for (j = 0; j < 64; j++) s->block[k][j] <<= 1; - s->dsp.put_signed_pixels_clamped(s->block[k], dst[k], k & 4 ? s->uvlinesize : s->linesize); + 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->dsp.put_pixels_clamped(s->block[k], dst[k], k & 4 ? s->uvlinesize : s->linesize); + s->idsp.put_pixels_clamped(s->block[k], dst[k], + k & 4 ? s->uvlinesize + : s->linesize); } } @@ -4945,7 +4964,7 @@ static void vc1_decode_i_blocks_adv(VC1Context *v) for (;s->mb_x < s->mb_width; s->mb_x++) { int16_t (*block)[64] = v->block[v->cur_blk_idx]; ff_update_block_index(s); - s->dsp.clear_blocks(block[0]); + 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; @@ -5169,7 +5188,7 @@ static void vc1_decode_skip_blocks(VC1Context *v) { MpegEncContext *s = &v->s; - if (!v->s.last_picture.f.data[0]) + 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); @@ -5178,9 +5197,9 @@ static void vc1_decode_skip_blocks(VC1Context *v) 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); + 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; } @@ -5383,15 +5402,15 @@ static void vc1_draw_sprites(VC1Context *v, SpriteData* sd) v->sprite_output_frame->linesize[plane] * row; for (sprite = 0; sprite <= v->two_sprites; sprite++) { - uint8_t *iplane = s->current_picture.f.data[plane]; - int iline = s->current_picture.f.linesize[plane]; + uint8_t *iplane = s->current_picture.f->data[plane]; + int iline = s->current_picture.f->linesize[plane]; int ycoord = yoff[sprite] + yadv[sprite] * row; int yline = ycoord >> 16; int next_line; ysub[sprite] = ycoord & 0xFFFF; if (sprite) { - iplane = s->last_picture.f.data[plane]; - iline = s->last_picture.f.linesize[plane]; + iplane = s->last_picture.f->data[plane]; + iline = s->last_picture.f->linesize[plane]; } next_line = FFMIN(yline + 1, (v->sprite_height >> !!plane) - 1) * iline; if (!(xoff[sprite] & 0xFFFF) && xadv[sprite] == 1 << 16) { @@ -5465,12 +5484,12 @@ static int vc1_decode_sprites(VC1Context *v, GetBitContext* gb) if (ret < 0) return ret; - if (!s->current_picture.f.data[0]) { + if (!s->current_picture.f->data[0]) { av_log(avctx, AV_LOG_ERROR, "Got no sprites\n"); return -1; } - if (v->two_sprites && (!s->last_picture_ptr || !s->last_picture.f.data[0])) { + if (v->two_sprites && (!s->last_picture_ptr || !s->last_picture.f->data[0])) { av_log(avctx, AV_LOG_WARNING, "Need two sprites, only got one\n"); v->two_sprites = 0; } @@ -5488,7 +5507,7 @@ static void vc1_sprite_flush(AVCodecContext *avctx) { VC1Context *v = avctx->priv_data; MpegEncContext *s = &v->s; - AVFrame *f = &s->current_picture.f; + AVFrame *f = s->current_picture.f; int plane, i; /* Windows Media Image codecs have a convergence interval of two keyframes. @@ -5584,7 +5603,7 @@ av_cold void ff_vc1_init_transposed_scantables(VC1Context *v) { int i; for (i = 0; i < 64; i++) { -#define transpose(x) ((x >> 3) | ((x & 7) << 3)) +#define transpose(x) (((x) >> 3) | (((x) & 7) << 3)) v->zz_8x8[0][i] = transpose(ff_wmv1_scantable[0][i]); v->zz_8x8[1][i] = transpose(ff_wmv1_scantable[1][i]); v->zz_8x8[2][i] = transpose(ff_wmv1_scantable[2][i]); @@ -5613,10 +5632,9 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) if (!avctx->extradata_size || !avctx->extradata) return -1; if (!(avctx->flags & CODEC_FLAG_GRAY)) - avctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts); + avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts); else avctx->pix_fmt = AV_PIX_FMT_GRAY8; - avctx->hwaccel = ff_find_hwaccel(avctx); v->s.avctx = avctx; if ((ret = ff_vc1_init_common(v)) < 0) @@ -5631,8 +5649,9 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) // That this is necessary might indicate a bug. ff_vc1_decode_end(avctx); + ff_blockdsp_init(&s->bdsp, avctx); ff_h264chroma_init(&v->h264chroma, 8); - ff_vc1dsp_init(&v->vc1dsp); + ff_qpeldsp_init(&s->qdsp); if (avctx->codec_id == AV_CODEC_ID_WMV3 || avctx->codec_id == AV_CODEC_ID_WMV3IMAGE) { int count = 0; @@ -5808,7 +5827,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == VC1_CODE_ENDOFSEQ)) { /* special case for last picture */ if (s->low_delay == 0 && s->next_picture_ptr) { - if ((ret = av_frame_ref(pict, &s->next_picture_ptr->f)) < 0) + if ((ret = av_frame_ref(pict, s->next_picture_ptr->f)) < 0) return ret; s->next_picture_ptr = NULL; @@ -5853,7 +5872,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, if (avctx->hwaccel || s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) buf_start_second_field = start; - tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1)); + tmp = av_realloc_array(slices, sizeof(*slices), (n_slices+1)); if (!tmp) goto err; slices = tmp; @@ -5878,7 +5897,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, break; case VC1_CODE_SLICE: { int buf_size3; - tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1)); + tmp = av_realloc_array(slices, sizeof(*slices), (n_slices+1)); if (!tmp) goto err; slices = tmp; @@ -5907,7 +5926,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, if (avctx->hwaccel || s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) buf_start_second_field = divider; - tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1)); + tmp = av_realloc_array(slices, sizeof(*slices), (n_slices+1)); if (!tmp) goto err; slices = tmp; @@ -6000,12 +6019,13 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, } // for skipping the frame - s->current_picture.f.pict_type = s->pict_type; - s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; + s->current_picture.f->pict_type = s->pict_type; + s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; /* skip B-frames if we don't have reference frames */ if (s->last_picture_ptr == NULL && (s->pict_type == AV_PICTURE_TYPE_B || s->droppable)) { - goto err; + av_log(v->s.avctx, AV_LOG_DEBUG, "Skipping B frame without reference frames\n"); + goto end; } 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) || @@ -6025,23 +6045,23 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, } v->s.current_picture_ptr->field_picture = v->field_mode; - v->s.current_picture_ptr->f.interlaced_frame = (v->fcm != PROGRESSIVE); - v->s.current_picture_ptr->f.top_field_first = v->tff; + v->s.current_picture_ptr->f->interlaced_frame = (v->fcm != PROGRESSIVE); + v->s.current_picture_ptr->f->top_field_first = v->tff; // process pulldown flags - s->current_picture_ptr->f.repeat_pict = 0; + s->current_picture_ptr->f->repeat_pict = 0; // Pulldown flags are only valid when 'broadcast' has been set. // So ticks_per_frame will be 2 if (v->rff) { // repeat field - s->current_picture_ptr->f.repeat_pict = 1; + s->current_picture_ptr->f->repeat_pict = 1; } else if (v->rptfrm) { // repeat frames - s->current_picture_ptr->f.repeat_pict = v->rptfrm * 2; + s->current_picture_ptr->f->repeat_pict = v->rptfrm * 2; } - s->me.qpel_put = s->dsp.put_qpel_pixels_tab; - s->me.qpel_avg = s->dsp.avg_qpel_pixels_tab; + s->me.qpel_put = s->qdsp.put_qpel_pixels_tab; + s->me.qpel_avg = s->qdsp.avg_qpel_pixels_tab; if ((CONFIG_VC1_VDPAU_DECODER) &&s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) { @@ -6071,7 +6091,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, av_log(avctx, AV_LOG_ERROR, "parsing header for second field failed"); goto err; } - v->s.current_picture_ptr->f.pict_type = v->s.pict_type; + v->s.current_picture_ptr->f->pict_type = v->s.pict_type; if (avctx->hwaccel->start_frame(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field) < 0) goto err; @@ -6096,9 +6116,9 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, v->bits = buf_size * 8; v->end_mb_x = s->mb_width; if (v->field_mode) { - s->current_picture.f.linesize[0] <<= 1; - s->current_picture.f.linesize[1] <<= 1; - s->current_picture.f.linesize[2] <<= 1; + s->current_picture.f->linesize[0] <<= 1; + s->current_picture.f->linesize[1] <<= 1; + s->current_picture.f->linesize[2] <<= 1; s->linesize <<= 1; s->uvlinesize <<= 1; } @@ -6168,9 +6188,9 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, } if (v->field_mode) { v->second_field = 0; - s->current_picture.f.linesize[0] >>= 1; - s->current_picture.f.linesize[1] >>= 1; - s->current_picture.f.linesize[2] >>= 1; + s->current_picture.f->linesize[0] >>= 1; + s->current_picture.f->linesize[1] >>= 1; + s->current_picture.f->linesize[2] >>= 1; s->linesize >>= 1; s->uvlinesize >>= 1; if (v->s.pict_type != AV_PICTURE_TYPE_BI && v->s.pict_type != AV_PICTURE_TYPE_B) { @@ -6205,12 +6225,12 @@ image: *got_frame = 1; } else { if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { - if ((ret = av_frame_ref(pict, &s->current_picture_ptr->f)) < 0) + if ((ret = av_frame_ref(pict, s->current_picture_ptr->f)) < 0) goto err; ff_print_debug_info(s, s->current_picture_ptr, pict); *got_frame = 1; } else if (s->last_picture_ptr != NULL) { - if ((ret = av_frame_ref(pict, &s->last_picture_ptr->f)) < 0) + if ((ret = av_frame_ref(pict, s->last_picture_ptr->f)) < 0) goto err; ff_print_debug_info(s, s->last_picture_ptr, pict); *got_frame = 1; @@ -6242,13 +6262,13 @@ static const AVProfile profiles[] = { }; static const enum AVPixelFormat vc1_hwaccel_pixfmt_list_420[] = { -#if CONFIG_DXVA2 +#if CONFIG_VC1_DXVA2_HWACCEL AV_PIX_FMT_DXVA2_VLD, #endif -#if CONFIG_VAAPI +#if CONFIG_VC1_VAAPI_HWACCEL AV_PIX_FMT_VAAPI_VLD, #endif -#if CONFIG_VDPAU +#if CONFIG_VC1_VDPAU_HWACCEL AV_PIX_FMT_VDPAU, #endif AV_PIX_FMT_YUV420P, @@ -6331,7 +6351,10 @@ AVCodec ff_wmv3image_decoder = { .decode = vc1_decode_frame, .capabilities = CODEC_CAP_DR1, .flush = vc1_sprite_flush, - .pix_fmts = ff_pixfmt_list_420 + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, }; #endif @@ -6347,6 +6370,9 @@ AVCodec ff_vc1image_decoder = { .decode = vc1_decode_frame, .capabilities = CODEC_CAP_DR1, .flush = vc1_sprite_flush, - .pix_fmts = ff_pixfmt_list_420 + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, }; #endif diff --git a/libavcodec/vc1dsp.c b/libavcodec/vc1dsp.c index ec9c17b19..fae9daec6 100644 --- a/libavcodec/vc1dsp.c +++ b/libavcodec/vc1dsp.c @@ -27,9 +27,12 @@ #include "libavutil/avassert.h" #include "libavutil/common.h" +#include "libavutil/intreadwrite.h" #include "h264chroma.h" +#include "qpeldsp.h" #include "rnd_avg.h" #include "vc1dsp.h" +#include "startcode.h" /* Apply overlap transform to horizontal edge */ static void vc1_v_overlap_c(uint8_t *src, int stride) @@ -641,6 +644,64 @@ static av_always_inline void OPNAME ## vc1_mspel_mc(uint8_t *dst, \ src += stride; \ } \ }\ +static av_always_inline void OPNAME ## vc1_mspel_mc_16(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, \ + int hmode, \ + int vmode, \ + int rnd) \ +{ \ + int i, j; \ + \ + if (vmode) { /* Horizontal filter to apply */ \ + int r; \ + \ + if (hmode) { /* Vertical filter to apply, output to tmp */ \ + static const int shift_value[] = { 0, 5, 1, 5 }; \ + int shift = (shift_value[hmode] + shift_value[vmode]) >> 1; \ + int16_t tmp[19 * 16], *tptr = tmp; \ + \ + r = (1 << (shift - 1)) + rnd - 1; \ + \ + src -= 1; \ + for (j = 0; j < 16; j++) { \ + for (i = 0; i < 19; i++) \ + tptr[i] = (vc1_mspel_ver_filter_16bits(src + i, stride, vmode) + r) >> shift; \ + src += stride; \ + tptr += 19; \ + } \ + \ + r = 64 - rnd; \ + tptr = tmp + 1; \ + for (j = 0; j < 16; j++) { \ + for (i = 0; i < 16; i++) \ + OP(dst[i], (vc1_mspel_hor_filter_16bits(tptr + i, 1, hmode) + r) >> 7); \ + dst += stride; \ + tptr += 19; \ + } \ + \ + return; \ + } else { /* No horizontal filter, output 8 lines to dst */ \ + r = 1 - rnd; \ + \ + for (j = 0; j < 16; j++) { \ + for (i = 0; i < 16; i++) \ + OP(dst[i], vc1_mspel_filter(src + i, stride, vmode, r)); \ + src += stride; \ + dst += stride; \ + } \ + return; \ + } \ + } \ + \ + /* Horizontal mode with no vertical mode */ \ + for (j = 0; j < 16; j++) { \ + for (i = 0; i < 16; i++) \ + OP(dst[i], vc1_mspel_filter(src + i, 1, hmode, rnd)); \ + dst += stride; \ + src += stride; \ + } \ +}\ static void OPNAME ## pixels8x8_c(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int rnd){\ int i;\ for(i=0; i<8; i++){\ @@ -649,6 +710,17 @@ static void OPNAME ## pixels8x8_c(uint8_t *block, const uint8_t *pixels, ptrdiff pixels+=line_size;\ block +=line_size;\ }\ +}\ +static void OPNAME ## pixels16x16_c(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int rnd){\ + int i;\ + for(i=0; i<16; i++){\ + OP4(*(uint32_t*)(block ), AV_RN32(pixels ));\ + OP4(*(uint32_t*)(block+ 4), AV_RN32(pixels+ 4));\ + OP4(*(uint32_t*)(block+ 8), AV_RN32(pixels+ 8));\ + OP4(*(uint32_t*)(block+12), AV_RN32(pixels+12));\ + pixels+=line_size;\ + block +=line_size;\ + }\ } #define op_put(a, b) a = av_clip_uint8(b) @@ -673,6 +745,18 @@ static void avg_vc1_mspel_mc ## a ## b ## _c(uint8_t *dst, \ ptrdiff_t stride, int rnd) \ { \ avg_vc1_mspel_mc(dst, src, stride, a, b, rnd); \ +} \ +static void put_vc1_mspel_mc ## a ## b ## _16_c(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + put_vc1_mspel_mc_16(dst, src, stride, a, b, rnd); \ +} \ +static void avg_vc1_mspel_mc ## a ## b ## _16_c(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + avg_vc1_mspel_mc_16(dst, src, stride, a, b, rnd); \ } PUT_VC1_MSPEL(1, 0) @@ -876,6 +960,11 @@ static void sprite_v_double_twoscale_c(uint8_t *dst, } #endif /* CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER */ +#define FN_ASSIGN(X, Y) \ + dsp->put_vc1_mspel_pixels_tab[1][X+4*Y] = put_vc1_mspel_mc##X##Y##_c; \ + dsp->put_vc1_mspel_pixels_tab[0][X+4*Y] = put_vc1_mspel_mc##X##Y##_16_c; \ + dsp->avg_vc1_mspel_pixels_tab[1][X+4*Y] = avg_vc1_mspel_mc##X##Y##_c; \ + dsp->avg_vc1_mspel_pixels_tab[0][X+4*Y] = avg_vc1_mspel_mc##X##Y##_16_c av_cold void ff_vc1dsp_init(VC1DSPContext *dsp) { @@ -900,39 +989,28 @@ av_cold void ff_vc1dsp_init(VC1DSPContext *dsp) dsp->vc1_v_loop_filter16 = vc1_v_loop_filter16_c; dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_c; - dsp->put_vc1_mspel_pixels_tab[0] = put_pixels8x8_c; - dsp->put_vc1_mspel_pixels_tab[1] = put_vc1_mspel_mc10_c; - dsp->put_vc1_mspel_pixels_tab[2] = put_vc1_mspel_mc20_c; - dsp->put_vc1_mspel_pixels_tab[3] = put_vc1_mspel_mc30_c; - dsp->put_vc1_mspel_pixels_tab[4] = put_vc1_mspel_mc01_c; - dsp->put_vc1_mspel_pixels_tab[5] = put_vc1_mspel_mc11_c; - dsp->put_vc1_mspel_pixels_tab[6] = put_vc1_mspel_mc21_c; - dsp->put_vc1_mspel_pixels_tab[7] = put_vc1_mspel_mc31_c; - dsp->put_vc1_mspel_pixels_tab[8] = put_vc1_mspel_mc02_c; - dsp->put_vc1_mspel_pixels_tab[9] = put_vc1_mspel_mc12_c; - dsp->put_vc1_mspel_pixels_tab[10] = put_vc1_mspel_mc22_c; - dsp->put_vc1_mspel_pixels_tab[11] = put_vc1_mspel_mc32_c; - dsp->put_vc1_mspel_pixels_tab[12] = put_vc1_mspel_mc03_c; - dsp->put_vc1_mspel_pixels_tab[13] = put_vc1_mspel_mc13_c; - dsp->put_vc1_mspel_pixels_tab[14] = put_vc1_mspel_mc23_c; - dsp->put_vc1_mspel_pixels_tab[15] = put_vc1_mspel_mc33_c; + dsp->put_vc1_mspel_pixels_tab[0][0] = put_pixels16x16_c; + dsp->avg_vc1_mspel_pixels_tab[0][0] = avg_pixels16x16_c; + dsp->put_vc1_mspel_pixels_tab[1][0] = put_pixels8x8_c; + dsp->avg_vc1_mspel_pixels_tab[1][0] = avg_pixels8x8_c; + FN_ASSIGN(0, 1); + FN_ASSIGN(0, 2); + FN_ASSIGN(0, 3); - dsp->avg_vc1_mspel_pixels_tab[0] = avg_pixels8x8_c; - dsp->avg_vc1_mspel_pixels_tab[1] = avg_vc1_mspel_mc10_c; - dsp->avg_vc1_mspel_pixels_tab[2] = avg_vc1_mspel_mc20_c; - dsp->avg_vc1_mspel_pixels_tab[3] = avg_vc1_mspel_mc30_c; - dsp->avg_vc1_mspel_pixels_tab[4] = avg_vc1_mspel_mc01_c; - dsp->avg_vc1_mspel_pixels_tab[5] = avg_vc1_mspel_mc11_c; - dsp->avg_vc1_mspel_pixels_tab[6] = avg_vc1_mspel_mc21_c; - dsp->avg_vc1_mspel_pixels_tab[7] = avg_vc1_mspel_mc31_c; - dsp->avg_vc1_mspel_pixels_tab[8] = avg_vc1_mspel_mc02_c; - dsp->avg_vc1_mspel_pixels_tab[9] = avg_vc1_mspel_mc12_c; - dsp->avg_vc1_mspel_pixels_tab[10] = avg_vc1_mspel_mc22_c; - dsp->avg_vc1_mspel_pixels_tab[11] = avg_vc1_mspel_mc32_c; - dsp->avg_vc1_mspel_pixels_tab[12] = avg_vc1_mspel_mc03_c; - dsp->avg_vc1_mspel_pixels_tab[13] = avg_vc1_mspel_mc13_c; - dsp->avg_vc1_mspel_pixels_tab[14] = avg_vc1_mspel_mc23_c; - dsp->avg_vc1_mspel_pixels_tab[15] = avg_vc1_mspel_mc33_c; + FN_ASSIGN(1, 0); + FN_ASSIGN(1, 1); + FN_ASSIGN(1, 2); + FN_ASSIGN(1, 3); + + FN_ASSIGN(2, 0); + FN_ASSIGN(2, 1); + FN_ASSIGN(2, 2); + FN_ASSIGN(2, 3); + + FN_ASSIGN(3, 0); + FN_ASSIGN(3, 1); + FN_ASSIGN(3, 2); + FN_ASSIGN(3, 3); dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = put_no_rnd_vc1_chroma_mc8_c; dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = avg_no_rnd_vc1_chroma_mc8_c; @@ -947,6 +1025,8 @@ av_cold void ff_vc1dsp_init(VC1DSPContext *dsp) dsp->sprite_v_double_twoscale = sprite_v_double_twoscale_c; #endif /* CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER */ + dsp->vc1_find_start_code_candidate = ff_startcode_find_candidate_c; + if (ARCH_AARCH64) ff_vc1dsp_init_aarch64(dsp); if (ARCH_ARM) diff --git a/libavcodec/vc1dsp.h b/libavcodec/vc1dsp.h index 990fbc330..aa5b6d34f 100644 --- a/libavcodec/vc1dsp.h +++ b/libavcodec/vc1dsp.h @@ -28,7 +28,6 @@ #ifndef AVCODEC_VC1DSP_H #define AVCODEC_VC1DSP_H -#include "dsputil.h" #include "hpeldsp.h" #include "h264chroma.h" @@ -58,8 +57,8 @@ typedef struct VC1DSPContext { /* put 8x8 block with bicubic interpolation and quarterpel precision * last argument is actually round value instead of height */ - vc1op_pixels_func put_vc1_mspel_pixels_tab[16]; - vc1op_pixels_func avg_vc1_mspel_pixels_tab[16]; + vc1op_pixels_func put_vc1_mspel_pixels_tab[2][16]; + vc1op_pixels_func avg_vc1_mspel_pixels_tab[2][16]; /* This is really one func used in VC-1 decoding */ h264_chroma_mc_func put_no_rnd_vc1_chroma_pixels_tab[3]; @@ -74,6 +73,14 @@ typedef struct VC1DSPContext { void (*sprite_v_double_twoscale)(uint8_t *dst, const uint8_t *src1a, const uint8_t *src1b, int offset1, const uint8_t *src2a, const uint8_t *src2b, int offset2, int alpha, int width); + + /** + * Search buf from the start for up to size bytes. Return the index + * of a zero byte, or >= size if not found. Ideally, use lookahead + * to filter out any zero bytes that are known to not be followed by + * one or more further zero bytes and a one byte. + */ + int (*vc1_find_start_code_candidate)(const uint8_t *buf, int size); } VC1DSPContext; void ff_vc1dsp_init(VC1DSPContext* c); diff --git a/libavcodec/vda.c b/libavcodec/vda.c new file mode 100644 index 000000000..170580f16 --- /dev/null +++ b/libavcodec/vda.c @@ -0,0 +1,72 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/mem.h" + +#include "vda.h" +#include "vda_internal.h" + +#if CONFIG_H264_VDA_HWACCEL +AVVDAContext *av_vda_alloc_context(void) +{ + AVVDAContext *ret = av_mallocz(sizeof(*ret)); + + if (ret) + ret->output_callback = ff_vda_output_callback; + + return ret; +} + +int av_vda_default_init(AVCodecContext *avctx) +{ + avctx->hwaccel_context = av_vda_alloc_context(); + if (!avctx->hwaccel_context) + return AVERROR(ENOMEM); + return ff_vda_default_init(avctx); +} + +void av_vda_default_free(AVCodecContext *avctx) +{ + ff_vda_default_free(avctx); + av_freep(&avctx->hwaccel_context); +} + +void ff_vda_default_free(AVCodecContext *avctx) +{ + AVVDAContext *vda = avctx->hwaccel_context; + if (vda && vda->decoder) + VDADecoderDestroy(vda->decoder); +} + +#else +AVVDAContext *av_vda_alloc_context(void) +{ + return NULL; +} + +int av_vda_default_init(AVCodecContext *avctx) +{ + return AVERROR(ENOSYS); +} + +void av_vda_default_free(AVCodecContext *ctx) +{ +} +#endif diff --git a/libavcodec/vda.h b/libavcodec/vda.h index 2f68188c9..12330aa36 100644 --- a/libavcodec/vda.h +++ b/libavcodec/vda.h @@ -29,6 +29,8 @@ * Public libavcodec VDA header. */ +#include "libavcodec/avcodec.h" + #include // emmintrin.h is unable to compile with -std=c99 -Werror=missing-prototypes @@ -118,26 +120,17 @@ struct vda_context { OSType cv_pix_fmt_type; /** - * The current bitstream buffer. - * - * - encoding: unused - * - decoding: Set/Unset by libavcodec. + * unused */ uint8_t *priv_bitstream; /** - * The current size of the bitstream. - * - * - encoding: unused - * - decoding: Set/Unset by libavcodec. + * unused */ int priv_bitstream_size; /** - * The reference size used for fast reallocation. - * - * - encoding: unused - * - decoding: Set/Unset by libavcodec. + * unused */ int priv_allocated_size; @@ -161,6 +154,58 @@ int ff_vda_create_decoder(struct vda_context *vda_ctx, /** Destroy the video decoder. */ int ff_vda_destroy_decoder(struct vda_context *vda_ctx); +/** + * This struct holds all the information that needs to be passed + * between the caller and libavcodec for initializing VDA decoding. + * Its size is not a part of the public ABI, it must be allocated with + * av_vda_alloc_context() and freed with av_free(). + */ +typedef struct AVVDAContext { + /** + * VDA decoder object. Created and freed by the caller. + */ + VDADecoder decoder; + + /** + * The output callback that must be passed to VDADecoderCreate. + * Set by av_vda_alloc_context(). + */ + VDADecoderOutputCallback output_callback; +} AVVDAContext; + +/** + * Allocate and initialize a VDA context. + * + * This function should be called from the get_format() callback when the caller + * selects the AV_PIX_FMT_VDA format. The caller must then create the decoder + * object (using the output callback provided by libavcodec) that will be used + * for VDA-accelerated decoding. + * + * When decoding with VDA is finished, the caller must destroy the decoder + * object and free the VDA context using av_free(). + * + * @return the newly allocated context or NULL on failure + */ +AVVDAContext *av_vda_alloc_context(void); + +/** + * This is a convenience function that creates and sets up the VDA context using + * an internal implementation. + * + * @param avctx the corresponding codec context + * + * @return >= 0 on success, a negative AVERROR code on failure + */ +int av_vda_default_init(AVCodecContext *avctx); + +/** + * This function must be called to free the VDA context initialized with + * av_vda_default_init(). + * + * @param avctx the corresponding codec context + */ +void av_vda_default_free(AVCodecContext *avctx); + /** * @} */ diff --git a/libavcodec/vda_h264.c b/libavcodec/vda_h264.c index 1eff671f7..61fb3c02c 100644 --- a/libavcodec/vda_h264.c +++ b/libavcodec/vda_h264.c @@ -31,6 +31,21 @@ struct vda_buffer { CVPixelBufferRef cv_buffer; }; +#include "internal.h" +#include "vda_internal.h" + +typedef struct VDAContext { + // The current bitstream buffer. + uint8_t *bitstream; + + // The current size of the bitstream. + int bitstream_size; + + // The reference size used for fast reallocation. + int allocated_size; + + CVImageBufferRef frame; +} VDAContext; /* Decoder callback that adds the vda frame to the queue in display order. */ static void vda_decoder_callback(void *vda_hw_ctx, @@ -53,15 +68,15 @@ static void vda_decoder_callback(void *vda_hw_ctx, vda_ctx->cv_buffer = CVPixelBufferRetain(image_buffer); } -static int vda_sync_decode(struct vda_context *vda_ctx) +static int vda_sync_decode(VDAContext *ctx, struct vda_context *vda_ctx) { OSStatus status; CFDataRef coded_frame; uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames coded_frame = CFDataCreate(kCFAllocatorDefault, - vda_ctx->priv_bitstream, - vda_ctx->priv_bitstream_size); + ctx->bitstream, + ctx->bitstream_size); status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL); @@ -74,42 +89,44 @@ static int vda_sync_decode(struct vda_context *vda_ctx) } -static int vda_h264_start_frame(AVCodecContext *avctx, +static int vda_old_h264_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) { + VDAContext *vda = avctx->internal->hwaccel_priv_data; struct vda_context *vda_ctx = avctx->hwaccel_context; if (!vda_ctx->decoder) return -1; - vda_ctx->priv_bitstream_size = 0; + vda->bitstream_size = 0; return 0; } -static int vda_h264_decode_slice(AVCodecContext *avctx, +static int vda_old_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { + VDAContext *vda = avctx->internal->hwaccel_priv_data; struct vda_context *vda_ctx = avctx->hwaccel_context; void *tmp; if (!vda_ctx->decoder) return -1; - tmp = av_fast_realloc(vda_ctx->priv_bitstream, - &vda_ctx->priv_allocated_size, - vda_ctx->priv_bitstream_size + size + 4); + tmp = av_fast_realloc(vda->bitstream, + &vda->allocated_size, + vda->bitstream_size + size + 4); if (!tmp) return AVERROR(ENOMEM); - vda_ctx->priv_bitstream = tmp; + vda->bitstream = tmp; - AV_WB32(vda_ctx->priv_bitstream + vda_ctx->priv_bitstream_size, size); - memcpy(vda_ctx->priv_bitstream + vda_ctx->priv_bitstream_size + 4, buffer, size); + AV_WB32(vda->bitstream + vda->bitstream_size, size); + memcpy(vda->bitstream + vda->bitstream_size + 4, buffer, size); - vda_ctx->priv_bitstream_size += size + 4; + vda->bitstream_size += size + 4; return 0; } @@ -121,19 +138,20 @@ static void vda_h264_release_buffer(void *opaque, uint8_t *data) av_free(context); } -static int vda_h264_end_frame(AVCodecContext *avctx) +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; struct vda_buffer *context; AVBufferRef *buffer; int status; - if (!vda_ctx->decoder || !vda_ctx->priv_bitstream) + if (!vda_ctx->decoder || !vda->bitstream) return -1; - status = vda_sync_decode(vda_ctx); + status = vda_sync_decode(vda, vda_ctx); frame->data[3] = (void*)vda_ctx->cv_buffer; if (status) @@ -227,7 +245,7 @@ int ff_vda_create_decoder(struct vda_context *vda_ctx, status = VDADecoderCreate(config_info, buffer_attributes, - vda_decoder_callback, + (VDADecoderOutputCallback *)vda_decoder_callback, vda_ctx, &vda_ctx->decoder); @@ -250,17 +268,264 @@ int ff_vda_destroy_decoder(struct vda_context *vda_ctx) if (vda_ctx->decoder) status = VDADecoderDestroy(vda_ctx->decoder); - av_freep(&vda_ctx->priv_bitstream); - return status; } +static int vda_h264_uninit(AVCodecContext *avctx) +{ + VDAContext *vda = avctx->internal->hwaccel_priv_data; + if (vda) { + av_freep(&vda->bitstream); + if (vda->frame) + CVPixelBufferRelease(vda->frame); + } + return 0; +} + +AVHWAccel ff_h264_vda_old_hwaccel = { + .name = "h264_vda", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_VDA_VLD, + .start_frame = vda_old_h264_start_frame, + .decode_slice = vda_old_h264_decode_slice, + .end_frame = vda_old_h264_end_frame, + .uninit = vda_h264_uninit, + .priv_data_size = sizeof(VDAContext), +}; + +void ff_vda_output_callback(void *opaque, + CFDictionaryRef user_info, + OSStatus status, + uint32_t infoFlags, + CVImageBufferRef image_buffer) +{ + AVCodecContext *ctx = opaque; + VDAContext *vda = ctx->internal->hwaccel_priv_data; + + + if (vda->frame) { + CVPixelBufferRelease(vda->frame); + vda->frame = NULL; + } + + if (!image_buffer) + return; + + vda->frame = CVPixelBufferRetain(image_buffer); +} + +static int vda_h264_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + VDAContext *vda = avctx->internal->hwaccel_priv_data; + + vda->bitstream_size = 0; + + return 0; +} + +static int vda_h264_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + VDAContext *vda = avctx->internal->hwaccel_priv_data; + void *tmp; + + tmp = av_fast_realloc(vda->bitstream, + &vda->allocated_size, + vda->bitstream_size + size + 4); + if (!tmp) + return AVERROR(ENOMEM); + + vda->bitstream = tmp; + + AV_WB32(vda->bitstream + vda->bitstream_size, size); + memcpy(vda->bitstream + vda->bitstream_size + 4, buffer, size); + + vda->bitstream_size += size + 4; + + return 0; +} + +static void release_buffer(void *opaque, uint8_t *data) +{ + CVImageBufferRef frame = (CVImageBufferRef)data; + CVPixelBufferRelease(frame); +} + +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; + uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames + CFDataRef coded_frame; + OSStatus status; + + if (!vda->bitstream_size) + return AVERROR_INVALIDDATA; + + + coded_frame = CFDataCreate(kCFAllocatorDefault, + vda->bitstream, + vda->bitstream_size); + + status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL); + + if (status == kVDADecoderNoErr) + status = VDADecoderFlush(vda_ctx->decoder, flush_flags); + + CFRelease(coded_frame); + + 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]); + + 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->data[3] = (uint8_t*)vda->frame; + vda->frame = NULL; + } + + return 0; +} + +int ff_vda_default_init(AVCodecContext *avctx) +{ + AVVDAContext *vda_ctx = avctx->hwaccel_context; + OSStatus status = kVDADecoderNoErr; + CFNumberRef height; + CFNumberRef width; + CFNumberRef format; + CFDataRef avc_data; + CFMutableDictionaryRef config_info; + CFMutableDictionaryRef buffer_attributes; + CFMutableDictionaryRef io_surface_properties; + CFNumberRef cv_pix_fmt; + int32_t fmt = 'avc1', pix_fmt = kCVPixelFormatType_422YpCbCr8; + + // kCVPixelFormatType_420YpCbCr8Planar; + + /* 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) { + uint8_t *rw_extradata; + + if (!(rw_extradata = av_malloc(avctx->extradata_size))) + return AVERROR(ENOMEM); + + memcpy(rw_extradata, avctx->extradata, avctx->extradata_size); + + rw_extradata[4] |= 0x03; + + avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, avctx->extradata_size); + + av_freep(&rw_extradata); + } else { + avc_data = CFDataCreate(kCFAllocatorDefault, + avctx->extradata, avctx->extradata_size); + } + + config_info = CFDictionaryCreateMutable(kCFAllocatorDefault, + 4, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->height); + width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->width); + format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &fmt); + CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height); + CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width); + CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data); + CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format); + + buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, + 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt32Type, + &pix_fmt); + + CFDictionarySetValue(buffer_attributes, + kCVPixelBufferPixelFormatTypeKey, + cv_pix_fmt); + CFDictionarySetValue(buffer_attributes, + kCVPixelBufferIOSurfacePropertiesKey, + io_surface_properties); + + status = VDADecoderCreate(config_info, + buffer_attributes, + (VDADecoderOutputCallback *)ff_vda_output_callback, + avctx, + &vda_ctx->decoder); + + CFRelease(format); + CFRelease(height); + CFRelease(width); + CFRelease(avc_data); + CFRelease(config_info); + CFRelease(cv_pix_fmt); + CFRelease(io_surface_properties); + CFRelease(buffer_attributes); + + if (status != kVDADecoderNoErr) { + av_log(avctx, AV_LOG_ERROR, "Cannot initialize VDA %d\n", status); + } + + switch (status) { + case kVDADecoderHardwareNotSupportedErr: + case kVDADecoderFormatNotSupportedErr: + return AVERROR(ENOSYS); + case kVDADecoderConfigurationError: + return AVERROR(EINVAL); + case kVDADecoderDecoderFailedErr: + return AVERROR_INVALIDDATA; + case kVDADecoderNoErr: + return 0; + default: + return AVERROR_UNKNOWN; + } +} + +static int vda_h264_alloc_frame(AVCodecContext *avctx, AVFrame *frame) +{ + frame->width = avctx->width; + frame->height = avctx->height; + frame->format = avctx->pix_fmt; + frame->buf[0] = av_buffer_alloc(1); + + if (!frame->buf[0]) + return AVERROR(ENOMEM); + return 0; +} + AVHWAccel ff_h264_vda_hwaccel = { .name = "h264_vda", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, - .pix_fmt = AV_PIX_FMT_VDA_VLD, + .pix_fmt = AV_PIX_FMT_VDA, + .alloc_frame = vda_h264_alloc_frame, .start_frame = vda_h264_start_frame, .decode_slice = vda_h264_decode_slice, .end_frame = vda_h264_end_frame, + .uninit = vda_h264_uninit, + .priv_data_size = sizeof(VDAContext), }; diff --git a/libavcodec/vda_internal.h b/libavcodec/vda_internal.h new file mode 100644 index 000000000..457916b05 --- /dev/null +++ b/libavcodec/vda_internal.h @@ -0,0 +1,33 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VDA_INTERNAL_H +#define AVCODEC_VDA_INTERNAL_H + +#include "vda.h" + +void ff_vda_output_callback(void *vda_hw_ctx, + CFDictionaryRef user_info, + OSStatus status, + uint32_t infoFlags, + CVImageBufferRef image_buffer); + +int ff_vda_default_init(AVCodecContext *avctx); +void ff_vda_default_free(AVCodecContext *avctx); + +#endif /* AVCODEC_VDA_INTERNAL_H */ diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c index e294e490d..0dc535526 100644 --- a/libavcodec/vdpau.c +++ b/libavcodec/vdpau.c @@ -45,12 +45,10 @@ AVVDPAUContext *av_alloc_vdpaucontext(void) MAKE_ACCESSORS(AVVDPAUContext, vdpau_hwaccel, AVVDPAU_Render2, render2) -int ff_vdpau_common_start_frame(Picture *pic, +int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic_ctx, av_unused const uint8_t *buffer, av_unused uint32_t size) { - struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; - pic_ctx->bitstream_buffers_allocated = 0; pic_ctx->bitstream_buffers_used = 0; pic_ctx->bitstream_buffers = NULL; @@ -67,7 +65,7 @@ int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx) 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); + VdpVideoSurface surf = ff_vdpau_get_surface_id(pic->f); #if FF_API_BUFS_VDPAU FF_DISABLE_DEPRECATION_WARNINGS @@ -79,7 +77,7 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif if (!hwctx->render) { - res = hwctx->render2(avctx, &pic->f, (void *)&pic_ctx->info, + res = hwctx->render2(avctx, pic->f, (void *)&pic_ctx->info, pic_ctx->bitstream_buffers_used, pic_ctx->bitstream_buffers); } else hwctx->render(hwctx->decoder, surf, (void *)&pic_ctx->info, @@ -100,9 +98,9 @@ FF_ENABLE_DEPRECATION_WARNINGS } #endif -int ff_vdpau_add_buffer(Picture *pic, const uint8_t *buf, uint32_t size) +int ff_vdpau_add_buffer(struct vdpau_picture_context *pic_ctx, + const uint8_t *buf, uint32_t size) { - struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; VdpBitstreamBuffer *buffers = pic_ctx->bitstream_buffers; buffers = av_fast_realloc(buffers, &pic_ctx->bitstream_buffers_allocated, @@ -125,7 +123,7 @@ void ff_vdpau_h264_set_reference_frames(H264Context *h) { struct vdpau_render_state *render, *render_ref; VdpReferenceFrameH264 *rf, *rf2; - Picture *pic; + H264Picture *pic; int i, list, pic_frame_idx; render = (struct vdpau_render_state *)h->cur_pic_ptr->f.data[0]; @@ -135,7 +133,7 @@ void ff_vdpau_h264_set_reference_frames(H264Context *h) #define H264_RF_COUNT FF_ARRAY_ELEMS(render->info.h264.referenceFrames) for (list = 0; list < 2; ++list) { - Picture **lp = list ? h->long_ref : h->short_ref; + H264Picture **lp = list ? h->long_ref : h->short_ref; int ls = list ? 16 : h->short_ref_count; for (i = 0; i < ls; ++i) { @@ -278,7 +276,7 @@ void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf, if (!s->current_picture_ptr) return; - render = (struct vdpau_render_state *)s->current_picture_ptr->f.data[0]; + render = (struct vdpau_render_state *)s->current_picture_ptr->f->data[0]; assert(render); /* fill VdpPictureInfoMPEG1Or2 struct */ @@ -307,18 +305,18 @@ void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf, switch(s->pict_type){ case AV_PICTURE_TYPE_B: - next = (struct vdpau_render_state *)s->next_picture.f.data[0]; + next = (struct vdpau_render_state *)s->next_picture.f->data[0]; assert(next); render->info.mpeg.backward_reference = next->surface; // no return here, going to set forward prediction case AV_PICTURE_TYPE_P: - last = (struct vdpau_render_state *)s->last_picture.f.data[0]; + last = (struct vdpau_render_state *)s->last_picture.f->data[0]; if (!last) // FIXME: Does this test make sense? last = render; // predict second field from the first render->info.mpeg.forward_reference = last->surface; } - ff_vdpau_add_data_chunk(s->current_picture_ptr->f.data[0], buf, buf_size); + ff_vdpau_add_data_chunk(s->current_picture_ptr->f->data[0], buf, buf_size); render->info.mpeg.slice_count = slice_count; @@ -335,7 +333,7 @@ void ff_vdpau_vc1_decode_picture(MpegEncContext *s, const uint8_t *buf, VC1Context *v = s->avctx->priv_data; struct vdpau_render_state *render, *last, *next; - render = (struct vdpau_render_state *)s->current_picture.f.data[0]; + render = (struct vdpau_render_state *)s->current_picture.f->data[0]; assert(render); /* fill LvPictureInfoVC1 struct */ @@ -379,18 +377,18 @@ void ff_vdpau_vc1_decode_picture(MpegEncContext *s, const uint8_t *buf, switch(s->pict_type){ case AV_PICTURE_TYPE_B: - next = (struct vdpau_render_state *)s->next_picture.f.data[0]; + next = (struct vdpau_render_state *)s->next_picture.f->data[0]; assert(next); render->info.vc1.backward_reference = next->surface; // no break here, going to set forward prediction case AV_PICTURE_TYPE_P: - last = (struct vdpau_render_state *)s->last_picture.f.data[0]; + last = (struct vdpau_render_state *)s->last_picture.f->data[0]; if (!last) // FIXME: Does this test make sense? last = render; // predict second field from the first render->info.vc1.forward_reference = last->surface; } - ff_vdpau_add_data_chunk(s->current_picture_ptr->f.data[0], buf, buf_size); + ff_vdpau_add_data_chunk(s->current_picture_ptr->f->data[0], buf, buf_size); render->info.vc1.slice_count = 1; @@ -409,7 +407,7 @@ void ff_vdpau_mpeg4_decode_picture(Mpeg4DecContext *ctx, const uint8_t *buf, if (!s->current_picture_ptr) return; - render = (struct vdpau_render_state *)s->current_picture_ptr->f.data[0]; + render = (struct vdpau_render_state *)s->current_picture_ptr->f->data[0]; assert(render); /* fill VdpPictureInfoMPEG4Part2 struct */ @@ -438,18 +436,18 @@ void ff_vdpau_mpeg4_decode_picture(Mpeg4DecContext *ctx, const uint8_t *buf, switch (s->pict_type) { case AV_PICTURE_TYPE_B: - next = (struct vdpau_render_state *)s->next_picture.f.data[0]; + next = (struct vdpau_render_state *)s->next_picture.f->data[0]; assert(next); render->info.mpeg4.backward_reference = next->surface; render->info.mpeg4.vop_coding_type = 2; // no break here, going to set forward prediction case AV_PICTURE_TYPE_P: - last = (struct vdpau_render_state *)s->last_picture.f.data[0]; + last = (struct vdpau_render_state *)s->last_picture.f->data[0]; assert(last); render->info.mpeg4.forward_reference = last->surface; } - ff_vdpau_add_data_chunk(s->current_picture_ptr->f.data[0], buf, buf_size); + ff_vdpau_add_data_chunk(s->current_picture_ptr->f->data[0], buf, buf_size); ff_mpeg_draw_horiz_band(s, 0, s->avctx->height); render->bitstream_buffers_used = 0; @@ -480,7 +478,7 @@ do { \ default: return AVERROR(EINVAL); } case AV_CODEC_ID_H264: - switch (avctx->profile) { + switch (avctx->profile & ~FF_PROFILE_H264_INTRA) { 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); diff --git a/libavcodec/vdpau_h264.c b/libavcodec/vdpau_h264.c index ea69c147f..05a41d040 100644 --- a/libavcodec/vdpau_h264.c +++ b/libavcodec/vdpau_h264.c @@ -25,6 +25,7 @@ #include "avcodec.h" #include "h264.h" +#include "mpegutils.h" #include "vdpau.h" #include "vdpau_internal.h" @@ -46,10 +47,10 @@ static void vdpau_h264_clear_rf(VdpReferenceFrameH264 *rf) rf->frame_idx = 0; } -static void vdpau_h264_set_rf(VdpReferenceFrameH264 *rf, Picture *pic, +static void vdpau_h264_set_rf(VdpReferenceFrameH264 *rf, H264Picture *pic, int pic_structure) { - VdpVideoSurface surface = ff_vdpau_get_surface_id(pic); + VdpVideoSurface surface = ff_vdpau_get_surface_id(&pic->f); if (pic_structure == 0) pic_structure = pic->reference; @@ -74,11 +75,11 @@ static void vdpau_h264_set_reference_frames(AVCodecContext *avctx) #define H264_RF_COUNT FF_ARRAY_ELEMS(info->referenceFrames) for (list = 0; list < 2; ++list) { - Picture **lp = list ? h->long_ref : h->short_ref; + H264Picture **lp = list ? h->long_ref : h->short_ref; int i, ls = list ? 16 : h->short_ref_count; for (i = 0; i < ls; ++i) { - Picture *pic = lp[i]; + H264Picture *pic = lp[i]; VdpReferenceFrameH264 *rf2; VdpVideoSurface surface_ref; int pic_frame_idx; @@ -86,7 +87,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); + surface_ref = ff_vdpau_get_surface_id(&pic->f); rf2 = &info->referenceFrames[0]; while (rf2 != rf) { @@ -118,7 +119,7 @@ static int vdpau_h264_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { H264Context * const h = avctx->priv_data; - Picture *pic = h->cur_pic_ptr; + H264Picture *pic = h->cur_pic_ptr; struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; VdpPictureInfoH264 *info = &pic_ctx->info.h264; @@ -161,7 +162,7 @@ static int vdpau_h264_start_frame(AVCodecContext *avctx, vdpau_h264_set_reference_frames(avctx); - return ff_vdpau_common_start_frame(pic, buffer, size); + return ff_vdpau_common_start_frame(pic_ctx, buffer, size); } static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 }; @@ -170,15 +171,15 @@ static int vdpau_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { H264Context *h = avctx->priv_data; - Picture *pic = h->cur_pic_ptr; + H264Picture *pic = h->cur_pic_ptr; struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; int val; - val = ff_vdpau_add_buffer(pic, start_code_prefix, 3); + val = ff_vdpau_add_buffer(pic_ctx, start_code_prefix, 3); if (val) return val; - val = ff_vdpau_add_buffer(pic, buffer, size); + val = ff_vdpau_add_buffer(pic_ctx, buffer, size); if (val) return val; @@ -191,9 +192,9 @@ static int vdpau_h264_end_frame(AVCodecContext *avctx) int res = 0; AVVDPAUContext *hwctx = avctx->hwaccel_context; H264Context *h = avctx->priv_data; - Picture *pic = h->cur_pic_ptr; + H264Picture *pic = h->cur_pic_ptr; struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; - VdpVideoSurface surf = ff_vdpau_get_surface_id(pic); + VdpVideoSurface surf = ff_vdpau_get_surface_id(&pic->f); #if FF_API_BUFS_VDPAU FF_DISABLE_DEPRECATION_WARNINGS @@ -233,5 +234,5 @@ AVHWAccel ff_h264_vdpau_hwaccel = { .start_frame = vdpau_h264_start_frame, .end_frame = vdpau_h264_end_frame, .decode_slice = vdpau_h264_decode_slice, - .priv_data_size = sizeof(struct vdpau_picture_context), + .frame_priv_data_size = sizeof(struct vdpau_picture_context), }; diff --git a/libavcodec/vdpau_internal.h b/libavcodec/vdpau_internal.h index cc634111b..0f3652b72 100644 --- a/libavcodec/vdpau_internal.h +++ b/libavcodec/vdpau_internal.h @@ -36,12 +36,13 @@ #include "mpegvideo.h" #include "version.h" -/** Extract VdpVideoSurface from a Picture */ -static inline uintptr_t ff_vdpau_get_surface_id(Picture *pic) +/** Extract VdpVideoSurface from an AVFrame */ +static inline uintptr_t ff_vdpau_get_surface_id(AVFrame *pic) { - return (uintptr_t)pic->f.data[3]; + return (uintptr_t)pic->data[3]; } +struct vdpau_picture_context; #if CONFIG_VDPAU #if !FF_API_BUFS_VDPAU union AVVDPAUPictureInfo { @@ -77,10 +78,11 @@ struct vdpau_picture_context { }; #endif -int ff_vdpau_common_start_frame(Picture *pic, +int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic, const uint8_t *buffer, uint32_t size); int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx); -int ff_vdpau_add_buffer(Picture *pic, const uint8_t *buf, uint32_t buf_size); +int ff_vdpau_add_buffer(struct vdpau_picture_context *pic, const uint8_t *buf, + uint32_t buf_size); void ff_vdpau_add_data_chunk(uint8_t *data, const uint8_t *buf, diff --git a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c index f21b34152..84a971c5b 100644 --- a/libavcodec/vdpau_mpeg12.c +++ b/libavcodec/vdpau_mpeg12.c @@ -43,12 +43,12 @@ static int vdpau_mpeg_start_frame(AVCodecContext *avctx, switch (s->pict_type) { case AV_PICTURE_TYPE_B: - ref = ff_vdpau_get_surface_id(&s->next_picture); + ref = ff_vdpau_get_surface_id(s->next_picture.f); assert(ref != VDP_INVALID_HANDLE); info->backward_reference = ref; /* fall through to forward prediction */ case AV_PICTURE_TYPE_P: - ref = ff_vdpau_get_surface_id(&s->last_picture); + ref = ff_vdpau_get_surface_id(s->last_picture.f); info->forward_reference = ref; } @@ -75,7 +75,7 @@ static int vdpau_mpeg_start_frame(AVCodecContext *avctx, info->non_intra_quantizer_matrix[i] = s->inter_matrix[i]; } - return ff_vdpau_common_start_frame(pic, buffer, size); + return ff_vdpau_common_start_frame(pic_ctx, buffer, size); } static int vdpau_mpeg_decode_slice(AVCodecContext *avctx, @@ -86,7 +86,7 @@ static int vdpau_mpeg_decode_slice(AVCodecContext *avctx, struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; int val; - val = ff_vdpau_add_buffer(pic, buffer, size); + val = ff_vdpau_add_buffer(pic_ctx, buffer, size); if (val < 0) return val; @@ -103,7 +103,7 @@ AVHWAccel ff_mpeg1_vdpau_hwaccel = { .start_frame = vdpau_mpeg_start_frame, .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_mpeg_decode_slice, - .priv_data_size = sizeof(struct vdpau_picture_context), + .frame_priv_data_size = sizeof(struct vdpau_picture_context), }; #endif @@ -116,6 +116,6 @@ AVHWAccel ff_mpeg2_vdpau_hwaccel = { .start_frame = vdpau_mpeg_start_frame, .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_mpeg_decode_slice, - .priv_data_size = sizeof(struct vdpau_picture_context), + .frame_priv_data_size = sizeof(struct vdpau_picture_context), }; #endif diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c index 282796eaf..64669a6e0 100644 --- a/libavcodec/vdpau_mpeg4.c +++ b/libavcodec/vdpau_mpeg4.c @@ -46,13 +46,13 @@ static int vdpau_mpeg4_start_frame(AVCodecContext *avctx, switch (s->pict_type) { case AV_PICTURE_TYPE_B: - ref = ff_vdpau_get_surface_id(&s->next_picture); + ref = ff_vdpau_get_surface_id(s->next_picture.f); assert(ref != VDP_INVALID_HANDLE); info->backward_reference = ref; info->vop_coding_type = 2; /* fall-through */ case AV_PICTURE_TYPE_P: - ref = ff_vdpau_get_surface_id(&s->last_picture); + ref = ff_vdpau_get_surface_id(s->last_picture.f); assert(ref != VDP_INVALID_HANDLE); info->forward_reference = ref; } @@ -77,8 +77,8 @@ static int vdpau_mpeg4_start_frame(AVCodecContext *avctx, info->non_intra_quantizer_matrix[i] = s->inter_matrix[i]; } - ff_vdpau_common_start_frame(pic, buffer, size); - return ff_vdpau_add_buffer(pic, buffer, size); + ff_vdpau_common_start_frame(pic_ctx, buffer, size); + return ff_vdpau_add_buffer(pic_ctx, buffer, size); } static int vdpau_mpeg4_decode_slice(av_unused AVCodecContext *avctx, @@ -97,7 +97,7 @@ AVHWAccel ff_h263_vdpau_hwaccel = { .start_frame = vdpau_mpeg4_start_frame, .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_mpeg4_decode_slice, - .priv_data_size = sizeof(struct vdpau_picture_context), + .frame_priv_data_size = sizeof(struct vdpau_picture_context), }; #endif @@ -110,6 +110,6 @@ AVHWAccel ff_mpeg4_vdpau_hwaccel = { .start_frame = vdpau_mpeg4_start_frame, .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_mpeg4_decode_slice, - .priv_data_size = sizeof(struct vdpau_picture_context), + .frame_priv_data_size = sizeof(struct vdpau_picture_context), }; #endif diff --git a/libavcodec/vdpau_vc1.c b/libavcodec/vdpau_vc1.c index c655529aa..13c41df66 100644 --- a/libavcodec/vdpau_vc1.c +++ b/libavcodec/vdpau_vc1.c @@ -45,14 +45,14 @@ static int vdpau_vc1_start_frame(AVCodecContext *avctx, switch (s->pict_type) { case AV_PICTURE_TYPE_B: if (s->next_picture_ptr) { - ref = ff_vdpau_get_surface_id(&s->next_picture); + ref = ff_vdpau_get_surface_id(s->next_picture.f); assert(ref != VDP_INVALID_HANDLE); info->backward_reference = ref; } /* fall-through */ case AV_PICTURE_TYPE_P: if (s->last_picture_ptr) { - ref = ff_vdpau_get_surface_id(&s->last_picture); + ref = ff_vdpau_get_surface_id(s->last_picture.f); assert(ref != VDP_INVALID_HANDLE); info->forward_reference = ref; } @@ -93,7 +93,7 @@ static int vdpau_vc1_start_frame(AVCodecContext *avctx, info->deblockEnable = v->postprocflag & 1; info->pquant = v->pq; - return ff_vdpau_common_start_frame(pic, buffer, size); + return ff_vdpau_common_start_frame(pic_ctx, buffer, size); } static int vdpau_vc1_decode_slice(AVCodecContext *avctx, @@ -105,7 +105,7 @@ static int vdpau_vc1_decode_slice(AVCodecContext *avctx, struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; int val; - val = ff_vdpau_add_buffer(pic, buffer, size); + val = ff_vdpau_add_buffer(pic_ctx, buffer, size); if (val < 0) return val; @@ -122,7 +122,7 @@ AVHWAccel ff_wmv3_vdpau_hwaccel = { .start_frame = vdpau_vc1_start_frame, .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_vc1_decode_slice, - .priv_data_size = sizeof(struct vdpau_picture_context), + .frame_priv_data_size = sizeof(struct vdpau_picture_context), }; #endif @@ -134,5 +134,5 @@ AVHWAccel ff_vc1_vdpau_hwaccel = { .start_frame = vdpau_vc1_start_frame, .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_vc1_decode_slice, - .priv_data_size = sizeof(struct vdpau_picture_context), + .frame_priv_data_size = sizeof(struct vdpau_picture_context), }; diff --git a/libavcodec/version.h b/libavcodec/version.h index 61a796852..7e5704417 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,8 +29,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 55 -#define LIBAVCODEC_VERSION_MINOR 52 -#define LIBAVCODEC_VERSION_MICRO 102 +#define LIBAVCODEC_VERSION_MINOR 69 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ @@ -141,5 +141,26 @@ #ifndef FF_API_EMU_EDGE #define FF_API_EMU_EDGE (LIBAVCODEC_VERSION_MAJOR < 56) #endif +#ifndef FF_API_ARCH_SH4 +#define FF_API_ARCH_SH4 (LIBAVCODEC_VERSION_MAJOR < 56) +#endif +#ifndef FF_API_ARCH_SPARC +#define FF_API_ARCH_SPARC (LIBAVCODEC_VERSION_MAJOR < 56) +#endif +#ifndef FF_API_INPUT_PRESERVED +#define FF_API_INPUT_PRESERVED (LIBAVCODEC_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_NORMALIZE_AQP +#define FF_API_NORMALIZE_AQP (LIBAVCODEC_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_GMC +#define FF_API_GMC (LIBAVCODEC_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_MV0 +#define FF_API_MV0 (LIBAVCODEC_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_CODEC_NAME +#define FF_API_CODEC_NAME (LIBAVCODEC_VERSION_MAJOR < 57) +#endif #endif /* AVCODEC_VERSION_H */ diff --git a/libavcodec/videodsp.c b/libavcodec/videodsp.c index 13e4a7b4b..ba618a7bb 100644 --- a/libavcodec/videodsp.c +++ b/libavcodec/videodsp.c @@ -44,6 +44,8 @@ av_cold void ff_videodsp_init(VideoDSPContext *ctx, int bpc) ctx->emulated_edge_mc = ff_emulated_edge_mc_16; } + if (ARCH_AARCH64) + ff_videodsp_init_aarch64(ctx, bpc); if (ARCH_ARM) ff_videodsp_init_arm(ctx, bpc); if (ARCH_PPC) diff --git a/libavcodec/videodsp.h b/libavcodec/videodsp.h index 0bb15f2c9..fc01a31dc 100644 --- a/libavcodec/videodsp.h +++ b/libavcodec/videodsp.h @@ -79,6 +79,7 @@ typedef struct VideoDSPContext { void ff_videodsp_init(VideoDSPContext *ctx, int bpc); /* for internal use only (i.e. called by ff_videodsp_init() */ +void ff_videodsp_init_aarch64(VideoDSPContext *ctx, int bpc); void ff_videodsp_init_arm(VideoDSPContext *ctx, int bpc); void ff_videodsp_init_ppc(VideoDSPContext *ctx, int bpc); void ff_videodsp_init_x86(VideoDSPContext *ctx, int bpc); diff --git a/libavcodec/videodsp_template.c b/libavcodec/videodsp_template.c index c569c30d6..f4ff2ba64 100644 --- a/libavcodec/videodsp_template.c +++ b/libavcodec/videodsp_template.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "bit_depth_template.c" void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src, ptrdiff_t buf_linesize, diff --git a/libavcodec/vima.c b/libavcodec/vima.c index f040e1b16..ba3f07aad 100644 --- a/libavcodec/vima.c +++ b/libavcodec/vima.c @@ -26,16 +26,16 @@ */ #include "libavutil/channel_layout.h" + +#include "adpcm_data.h" #include "avcodec.h" #include "get_bits.h" #include "internal.h" -#include "adpcm_data.h" static int predict_table_init = 0; static uint16_t predict_table[5786 * 2]; -static const uint8_t size_table[] = -{ +static const uint8_t size_table[] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, @@ -44,64 +44,42 @@ static const uint8_t size_table[] = 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }; -static const int8_t index_table1[] = -{ +static const int8_t index_table1[] = { -1, 4, -1, 4 }; -static const int8_t index_table2[] = -{ +static const int8_t index_table2[] = { -1, -1, 2, 6, -1, -1, 2, 6 }; -static const int8_t index_table3[] = -{ - -1, -1, -1, -1, 1, 2, 4, 6, - -1, -1, -1, -1, 1, 2, 4, 6 +static const int8_t index_table3[] = { + -1, -1, -1, -1, 1, 2, 4, 6, -1, -1, -1, -1, 1, 2, 4, 6 }; -static const int8_t index_table4[] = -{ - -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 2, 2, 4, 5, 6, - -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 2, 2, 4, 5, 6 +static const int8_t index_table4[] = { + -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 2, 2, 4, 5, 6, + -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 2, 2, 4, 5, 6 }; -static const int8_t index_table5[] = -{ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 2, 2, 2, - 2, 4, 4, 4, 5, 5, 6, 6, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 2, 2, 2, - 2, 4, 4, 4, 5, 5, 6, 6 +static const int8_t index_table5[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 5, 5, 6, 6, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 5, 5, 6, 6 }; -static const int8_t index_table6[] = -{ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 6, 6, 6, 6, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 6, 6, 6, 6 +static const int8_t index_table6[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6 }; -static const int8_t* const step_index_tables[] = -{ +static const int8_t *const step_index_tables[] = { index_table1, index_table2, index_table3, index_table4, index_table5, index_table6 }; @@ -140,12 +118,13 @@ static av_cold int decode_init(AVCodecContext *avctx) static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *pkt) { - GetBitContext gb; - AVFrame *frame = data; - int16_t pcm_data[2]; - uint32_t samples; - int8_t channel_hint[2]; - int ret, chan, channels = 1; + GetBitContext gb; + AVFrame *frame = data; + int16_t pcm_data[2]; + uint32_t samples; + int8_t channel_hint[2]; + int ret, chan; + int channels = 1; if (pkt->size < 13) return AVERROR_INVALIDDATA; @@ -168,12 +147,12 @@ static int decode_frame(AVCodecContext *avctx, void *data, channels = 2; } avctx->channels = channels; - avctx->channel_layout = (channels == 2) ? AV_CH_LAYOUT_STEREO : - AV_CH_LAYOUT_MONO; + avctx->channel_layout = (channels == 2) ? AV_CH_LAYOUT_STEREO + : AV_CH_LAYOUT_MONO; pcm_data[0] = get_sbits(&gb, 16); if (channels > 1) { channel_hint[1] = get_sbits(&gb, 8); - pcm_data[1] = get_sbits(&gb, 16); + pcm_data[1] = get_sbits(&gb, 16); } frame->nb_samples = samples; @@ -181,7 +160,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, return ret; for (chan = 0; chan < channels; chan++) { - uint16_t *dest = (uint16_t*)frame->data[0] + chan; + uint16_t *dest = (uint16_t *)frame->data[0] + chan; int step_index = channel_hint[chan]; int output = pcm_data[chan]; int sample; @@ -211,9 +190,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, if (lookup) diff += ff_adpcm_step_table[step_index] >> (lookup_size - 1); if (highbit) - diff = -diff; + diff = -diff; - output = av_clip_int16(output + diff); + output = av_clip_int16(output + diff); } *dest = output; @@ -223,17 +202,27 @@ static int decode_frame(AVCodecContext *avctx, void *data, } } - *got_frame_ptr = 1; + *got_frame_ptr = 1; return pkt->size; } +AVCodec ff_adpcm_vima_decoder = { + .name = "adpcm_vima", + .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ADPCM_VIMA, + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, +}; + AVCodec ff_vima_decoder = { - .name = "vima", - .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_VIMA, - .init = decode_init, - .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .name = "vima", + .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ADPCM_VIMA, + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, }; diff --git a/libavcodec/vmdaudio.c b/libavcodec/vmdaudio.c new file mode 100644 index 000000000..0090aefda --- /dev/null +++ b/libavcodec/vmdaudio.c @@ -0,0 +1,235 @@ +/* + * Sierra VMD audio decoder + * Copyright (C) 2004 the ffmpeg project + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Sierra VMD audio decoder + * by Vladimir "VAG" Gneushev (vagsoft at mail.ru) + * for more information on the Sierra VMD format, visit: + * http://www.pcisys.net/~melanson/codecs/ + * + * The audio decoder, expects each encoded data + * chunk to be prepended with the appropriate 16-byte frame information + * record from the VMD file. It does not require the 0x330-byte VMD file + * header, but it does need the audio setup parameters passed in through + * normal libavcodec API means. + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + +#include "avcodec.h" +#include "internal.h" + +#define BLOCK_TYPE_AUDIO 1 +#define BLOCK_TYPE_INITIAL 2 +#define BLOCK_TYPE_SILENCE 3 + +typedef struct VmdAudioContext { + int out_bps; + int chunk_size; +} VmdAudioContext; + +static const uint16_t vmdaudio_table[128] = { + 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080, + 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120, + 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, + 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230, + 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280, + 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0, + 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, + 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370, + 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0, + 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480, + 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, + 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00, + 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000 +}; + +static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) +{ + VmdAudioContext *s = avctx->priv_data; + + if (avctx->channels < 1 || avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); + return AVERROR(EINVAL); + } + if (avctx->block_align < 1 || avctx->block_align % avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "invalid block align\n"); + return AVERROR(EINVAL); + } + + avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO : + AV_CH_LAYOUT_STEREO; + + if (avctx->bits_per_coded_sample == 16) + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + else + avctx->sample_fmt = AV_SAMPLE_FMT_U8; + s->out_bps = av_get_bytes_per_sample(avctx->sample_fmt); + + s->chunk_size = avctx->block_align + avctx->channels * (s->out_bps == 2); + + av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, " + "block align = %d, sample rate = %d\n", + avctx->channels, avctx->bits_per_coded_sample, avctx->block_align, + avctx->sample_rate); + + return 0; +} + +static void decode_audio_s16(int16_t *out, const uint8_t *buf, int buf_size, + int channels) +{ + int ch; + const uint8_t *buf_end = buf + buf_size; + int predictor[2]; + int st = channels - 1; + + /* decode initial raw sample */ + for (ch = 0; ch < channels; ch++) { + predictor[ch] = (int16_t)AV_RL16(buf); + buf += 2; + *out++ = predictor[ch]; + } + + /* decode DPCM samples */ + ch = 0; + while (buf < buf_end) { + uint8_t b = *buf++; + if (b & 0x80) + predictor[ch] -= vmdaudio_table[b & 0x7F]; + else + predictor[ch] += vmdaudio_table[b]; + predictor[ch] = av_clip_int16(predictor[ch]); + *out++ = predictor[ch]; + ch ^= st; + } +} + +static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + const uint8_t *buf_end; + int buf_size = avpkt->size; + VmdAudioContext *s = avctx->priv_data; + int block_type, silent_chunks, audio_chunks; + int ret; + uint8_t *output_samples_u8; + int16_t *output_samples_s16; + + if (buf_size < 16) { + av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n"); + *got_frame_ptr = 0; + return buf_size; + } + + block_type = buf[6]; + if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) { + av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type); + return AVERROR(EINVAL); + } + buf += 16; + buf_size -= 16; + + /* get number of silent chunks */ + silent_chunks = 0; + if (block_type == BLOCK_TYPE_INITIAL) { + uint32_t flags; + if (buf_size < 4) { + av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); + return AVERROR(EINVAL); + } + flags = AV_RB32(buf); + silent_chunks = av_popcount(flags); + buf += 4; + buf_size -= 4; + } else if (block_type == BLOCK_TYPE_SILENCE) { + silent_chunks = 1; + buf_size = 0; // should already be zero but set it just to be sure + } + + /* ensure output buffer is large enough */ + audio_chunks = buf_size / s->chunk_size; + + /* drop incomplete chunks */ + buf_size = audio_chunks * s->chunk_size; + + /* get output buffer */ + frame->nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) / + avctx->channels; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + output_samples_u8 = frame->data[0]; + output_samples_s16 = (int16_t *)frame->data[0]; + + /* decode silent chunks */ + if (silent_chunks > 0) { + int silent_size = avctx->block_align * silent_chunks; + av_assert0(avctx->block_align * silent_chunks <= frame->nb_samples * avctx->channels); + + if (s->out_bps == 2) { + memset(output_samples_s16, 0x00, silent_size * 2); + output_samples_s16 += silent_size; + } else { + memset(output_samples_u8, 0x80, silent_size); + output_samples_u8 += silent_size; + } + } + + /* decode audio chunks */ + if (audio_chunks > 0) { + buf_end = buf + buf_size; + av_assert0((buf_size & (avctx->channels > 1)) == 0); + while (buf_end - buf >= s->chunk_size) { + if (s->out_bps == 2) { + decode_audio_s16(output_samples_s16, buf, s->chunk_size, + avctx->channels); + output_samples_s16 += avctx->block_align; + } else { + memcpy(output_samples_u8, buf, s->chunk_size); + output_samples_u8 += avctx->block_align; + } + buf += s->chunk_size; + } + } + + *got_frame_ptr = 1; + + return avpkt->size; +} + +AVCodec ff_vmdaudio_decoder = { + .name = "vmdaudio", + .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_VMDAUDIO, + .priv_data_size = sizeof(VmdAudioContext), + .init = vmdaudio_decode_init, + .decode = vmdaudio_decode_frame, + .capabilities = CODEC_CAP_DR1, +}; diff --git a/libavcodec/vmdav.c b/libavcodec/vmdvideo.c similarity index 68% rename from libavcodec/vmdav.c rename to libavcodec/vmdvideo.c index c1fb80b97..279c56ab4 100644 --- a/libavcodec/vmdav.c +++ b/libavcodec/vmdvideo.c @@ -1,5 +1,5 @@ /* - * Sierra VMD Audio & Video Decoders + * Sierra VMD video decoder * Copyright (C) 2004 the ffmpeg project * * This file is part of FFmpeg. @@ -21,7 +21,7 @@ /** * @file - * Sierra VMD audio & video decoders + * Sierra VMD video decoder * by Vladimir "VAG" Gneushev (vagsoft at mail.ru) * for more information on the Sierra VMD format, visit: * http://www.pcisys.net/~melanson/codecs/ @@ -31,22 +31,13 @@ * codec initialization. Each encoded frame that is sent to this decoder * is expected to be prepended with the appropriate 16-byte frame * information record from the VMD file. - * - * The audio decoder, like the video decoder, expects each encoded data - * chunk to be prepended with the appropriate 16-byte frame information - * record from the VMD file. It does not require the 0x330-byte VMD file - * header, but it does need the audio setup parameters passed in through - * normal libavcodec API means. */ -#include -#include #include -#include "libavutil/avassert.h" -#include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "libavutil/intreadwrite.h" + #include "avcodec.h" #include "internal.h" #include "bytestream.h" @@ -54,10 +45,6 @@ #define VMD_HEADER_SIZE 0x330 #define PALETTE_COUNT 256 -/* - * Video Decoder - */ - typedef struct VmdVideoContext { AVCodecContext *avctx; @@ -472,195 +459,6 @@ static int vmdvideo_decode_frame(AVCodecContext *avctx, return buf_size; } -/* - * Audio Decoder - */ - -#define BLOCK_TYPE_AUDIO 1 -#define BLOCK_TYPE_INITIAL 2 -#define BLOCK_TYPE_SILENCE 3 - -typedef struct VmdAudioContext { - int out_bps; - int chunk_size; -} VmdAudioContext; - -static const uint16_t vmdaudio_table[128] = { - 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080, - 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120, - 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, - 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230, - 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280, - 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0, - 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, - 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370, - 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0, - 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480, - 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, - 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00, - 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000 -}; - -static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) -{ - VmdAudioContext *s = avctx->priv_data; - - if (avctx->channels < 1 || avctx->channels > 2) { - av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); - return AVERROR(EINVAL); - } - if (avctx->block_align < 1 || avctx->block_align % avctx->channels) { - av_log(avctx, AV_LOG_ERROR, "invalid block align\n"); - return AVERROR(EINVAL); - } - - avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO : - AV_CH_LAYOUT_STEREO; - - if (avctx->bits_per_coded_sample == 16) - avctx->sample_fmt = AV_SAMPLE_FMT_S16; - else - avctx->sample_fmt = AV_SAMPLE_FMT_U8; - s->out_bps = av_get_bytes_per_sample(avctx->sample_fmt); - - s->chunk_size = avctx->block_align + avctx->channels * (s->out_bps == 2); - - av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, " - "block align = %d, sample rate = %d\n", - avctx->channels, avctx->bits_per_coded_sample, avctx->block_align, - avctx->sample_rate); - - return 0; -} - -static void decode_audio_s16(int16_t *out, const uint8_t *buf, int buf_size, - int channels) -{ - int ch; - const uint8_t *buf_end = buf + buf_size; - int predictor[2]; - int st = channels - 1; - - /* decode initial raw sample */ - for (ch = 0; ch < channels; ch++) { - predictor[ch] = (int16_t)AV_RL16(buf); - buf += 2; - *out++ = predictor[ch]; - } - - /* decode DPCM samples */ - ch = 0; - while (buf < buf_end) { - uint8_t b = *buf++; - if (b & 0x80) - predictor[ch] -= vmdaudio_table[b & 0x7F]; - else - predictor[ch] += vmdaudio_table[b]; - predictor[ch] = av_clip_int16(predictor[ch]); - *out++ = predictor[ch]; - ch ^= st; - } -} - -static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame_ptr, AVPacket *avpkt) -{ - AVFrame *frame = data; - const uint8_t *buf = avpkt->data; - const uint8_t *buf_end; - int buf_size = avpkt->size; - VmdAudioContext *s = avctx->priv_data; - int block_type, silent_chunks, audio_chunks; - int ret; - uint8_t *output_samples_u8; - int16_t *output_samples_s16; - - if (buf_size < 16) { - av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n"); - *got_frame_ptr = 0; - return buf_size; - } - - block_type = buf[6]; - if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) { - av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type); - return AVERROR(EINVAL); - } - buf += 16; - buf_size -= 16; - - /* get number of silent chunks */ - silent_chunks = 0; - if (block_type == BLOCK_TYPE_INITIAL) { - uint32_t flags; - if (buf_size < 4) { - av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); - return AVERROR(EINVAL); - } - flags = AV_RB32(buf); - silent_chunks = av_popcount(flags); - buf += 4; - buf_size -= 4; - } else if (block_type == BLOCK_TYPE_SILENCE) { - silent_chunks = 1; - buf_size = 0; // should already be zero but set it just to be sure - } - - /* ensure output buffer is large enough */ - audio_chunks = buf_size / s->chunk_size; - - /* drop incomplete chunks */ - buf_size = audio_chunks * s->chunk_size; - - /* get output buffer */ - frame->nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) / - avctx->channels; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; - output_samples_u8 = frame->data[0]; - output_samples_s16 = (int16_t *)frame->data[0]; - - /* decode silent chunks */ - if (silent_chunks > 0) { - int silent_size = avctx->block_align * silent_chunks; - av_assert0(avctx->block_align * silent_chunks <= frame->nb_samples * avctx->channels); - - if (s->out_bps == 2) { - memset(output_samples_s16, 0x00, silent_size * 2); - output_samples_s16 += silent_size; - } else { - memset(output_samples_u8, 0x80, silent_size); - output_samples_u8 += silent_size; - } - } - - /* decode audio chunks */ - if (audio_chunks > 0) { - buf_end = buf + buf_size; - av_assert0((buf_size & (avctx->channels > 1)) == 0); - while (buf_end - buf >= s->chunk_size) { - if (s->out_bps == 2) { - decode_audio_s16(output_samples_s16, buf, s->chunk_size, - avctx->channels); - output_samples_s16 += avctx->block_align; - } else { - memcpy(output_samples_u8, buf, s->chunk_size); - output_samples_u8 += avctx->block_align; - } - buf += s->chunk_size; - } - } - - *got_frame_ptr = 1; - - return avpkt->size; -} - - -/* - * Public Data Structures - */ - AVCodec ff_vmdvideo_decoder = { .name = "vmdvideo", .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"), @@ -672,14 +470,3 @@ AVCodec ff_vmdvideo_decoder = { .decode = vmdvideo_decode_frame, .capabilities = CODEC_CAP_DR1, }; - -AVCodec ff_vmdaudio_decoder = { - .name = "vmdaudio", - .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_VMDAUDIO, - .priv_data_size = sizeof(VmdAudioContext), - .init = vmdaudio_decode_init, - .decode = vmdaudio_decode_frame, - .capabilities = CODEC_CAP_DR1, -}; diff --git a/libavcodec/vorbis.c b/libavcodec/vorbis.c index 05f18b474..86d10407f 100644 --- a/libavcodec/vorbis.c +++ b/libavcodec/vorbis.c @@ -71,7 +71,7 @@ int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) codes[p] = 0; if (bits[p] > 32) - return 1; + return AVERROR_INVALIDDATA; for (i = 0; i < bits[p]; ++i) exit_at_level[i+1] = 1 << i; @@ -92,7 +92,7 @@ int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) for (; p < num; ++p) { if (bits[p] > 32) - return 1; + return AVERROR_INVALIDDATA; if (bits[p] == 0) continue; // find corresponding exit(node which the tree can grow further from) @@ -100,7 +100,7 @@ int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) if (exit_at_level[i]) break; if (!i) // overspecified tree - return 1; + return AVERROR_INVALIDDATA; code = exit_at_level[i]; exit_at_level[i] = 0; // construct code (append 0s to end) and introduce new exits @@ -121,7 +121,7 @@ int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) //no exits should be left (underspecified tree - ie. unused valid vlcs - not allowed by SPEC) for (p = 1; p < 33; p++) if (exit_at_level[p]) - return 1; + return AVERROR_INVALIDDATA; return 0; } diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c index dfffc6f04..87d1bbb97 100644 --- a/libavcodec/vorbisdec.c +++ b/libavcodec/vorbisdec.c @@ -378,7 +378,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) } // Weed out unused vlcs and build codevector vector - codebook_setup->codevectors = used_entries ? av_mallocz(used_entries * + codebook_setup->codevectors = used_entries ? av_mallocz_array(used_entries, codebook_setup->dimensions * sizeof(*codebook_setup->codevectors)) : NULL; @@ -561,7 +561,7 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) for (j = 0; j < floor_setup->data.t1.partitions; ++j) floor_setup->data.t1.x_list_dim+=floor_setup->data.t1.class_dimensions[floor_setup->data.t1.partition_class[j]]; - floor_setup->data.t1.list = av_mallocz(floor_setup->data.t1.x_list_dim * + floor_setup->data.t1.list = av_mallocz_array(floor_setup->data.t1.x_list_dim, sizeof(*floor_setup->data.t1.list)); if (!floor_setup->data.t1.list) return AVERROR(ENOMEM); @@ -640,8 +640,8 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) /* codebook dim is for padding if codebook dim doesn't * * divide order+1 then we need to read more data */ floor_setup->data.t0.lsp = - av_malloc((floor_setup->data.t0.order + 1 + max_codebook_dim) - * sizeof(*floor_setup->data.t0.lsp)); + av_malloc_array((floor_setup->data.t0.order + 1 + max_codebook_dim), + sizeof(*floor_setup->data.t0.lsp)); if (!floor_setup->data.t0.lsp) return AVERROR(ENOMEM); @@ -714,7 +714,7 @@ static int vorbis_parse_setup_hdr_residues(vorbis_context *vc) res_setup->ptns_to_read = (res_setup->end - res_setup->begin) / res_setup->partition_size; - res_setup->classifs = av_malloc(res_setup->ptns_to_read * + res_setup->classifs = av_malloc_array(res_setup->ptns_to_read, vc->audio_channels * sizeof(*res_setup->classifs)); if (!res_setup->classifs) @@ -807,7 +807,7 @@ static int vorbis_parse_setup_hdr_mappings(vorbis_context *vc) } if (mapping_setup->submaps>1) { - mapping_setup->mux = av_mallocz(vc->audio_channels * + mapping_setup->mux = av_mallocz_array(vc->audio_channels, sizeof(*mapping_setup->mux)); if (!mapping_setup->mux) return AVERROR(ENOMEM); @@ -842,7 +842,7 @@ static int create_map(vorbis_context *vc, unsigned floor_number) for (blockflag = 0; blockflag < 2; ++blockflag) { n = vc->blocksize[blockflag] / 2; floors[floor_number].data.t0.map[blockflag] = - av_malloc((n + 1) * sizeof(int32_t)); // n + sentinel + av_malloc_array(n + 1, sizeof(int32_t)); // n + sentinel if (!floors[floor_number].data.t0.map[blockflag]) return AVERROR(ENOMEM); @@ -983,8 +983,8 @@ static int vorbis_parse_id_hdr(vorbis_context *vc) return AVERROR_INVALIDDATA; } - vc->channel_residues = av_malloc((vc->blocksize[1] / 2) * vc->audio_channels * sizeof(*vc->channel_residues)); - vc->saved = av_mallocz((vc->blocksize[1] / 4) * vc->audio_channels * sizeof(*vc->saved)); + vc->channel_residues = av_malloc_array(vc->blocksize[1] / 2, vc->audio_channels * sizeof(*vc->channel_residues)); + vc->saved = av_mallocz_array(vc->blocksize[1] / 4, vc->audio_channels * sizeof(*vc->saved)); if (!vc->channel_residues || !vc->saved) return AVERROR(ENOMEM); @@ -1828,6 +1828,7 @@ static av_cold void vorbis_decode_flush(AVCodecContext *avctx) sizeof(*vc->saved)); } vc->previous_window = -1; + vc->first_frame = 0; } AVCodec ff_vorbis_decoder = { diff --git a/libavcodec/vorbisdsp.c b/libavcodec/vorbisdsp.c index 784375697..362a27629 100644 --- a/libavcodec/vorbisdsp.c +++ b/libavcodec/vorbisdsp.c @@ -25,6 +25,8 @@ av_cold void ff_vorbisdsp_init(VorbisDSPContext *dsp) { dsp->vorbis_inverse_coupling = ff_vorbis_inverse_coupling; + if (ARCH_AARCH64) + ff_vorbisdsp_init_aarch64(dsp); if (ARCH_ARM) ff_vorbisdsp_init_arm(dsp); if (ARCH_PPC) diff --git a/libavcodec/vorbisdsp.h b/libavcodec/vorbisdsp.h index ed14049c8..7abec4e4b 100644 --- a/libavcodec/vorbisdsp.h +++ b/libavcodec/vorbisdsp.h @@ -30,6 +30,7 @@ typedef struct VorbisDSPContext { void ff_vorbisdsp_init(VorbisDSPContext *dsp); /* for internal use only */ +void ff_vorbisdsp_init_aarch64(VorbisDSPContext *dsp); void ff_vorbisdsp_init_x86(VorbisDSPContext *dsp); void ff_vorbisdsp_init_arm(VorbisDSPContext *dsp); void ff_vorbisdsp_init_ppc(VorbisDSPContext *dsp); diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c index 9ef629681..fa6bccc1d 100644 --- a/libavcodec/vorbisenc.c +++ b/libavcodec/vorbisenc.c @@ -25,9 +25,11 @@ */ #include + #include "avcodec.h" #include "internal.h" #include "fft.h" +#include "mathops.h" #include "vorbis.h" #include "vorbis_enc_data.h" diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index 4988fbd33..3f04d8f25 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -34,20 +34,21 @@ #include #include "libavutil/imgutils.h" + #include "avcodec.h" -#include "internal.h" -#include "dsputil.h" #include "get_bits.h" #include "hpeldsp.h" +#include "internal.h" +#include "mathops.h" +#include "thread.h" #include "videodsp.h" #include "vp3data.h" #include "vp3dsp.h" #include "xiph.h" -#include "thread.h" #define FRAGMENT_PIXELS 8 -//FIXME split things out into their own arrays +// FIXME split things out into their own arrays typedef struct Vp3Fragment { int16_t dc; uint8_t coding_method; @@ -81,51 +82,49 @@ static int theora_decode_tables(AVCodecContext *avctx, GetBitContext *gb); /* There are 6 preset schemes, plus a free-form scheme */ -static const int ModeAlphabet[6][CODING_MODE_COUNT] = -{ +static const int ModeAlphabet[6][CODING_MODE_COUNT] = { /* scheme 1: Last motion vector dominates */ - { MODE_INTER_LAST_MV, MODE_INTER_PRIOR_LAST, - MODE_INTER_PLUS_MV, MODE_INTER_NO_MV, - MODE_INTRA, MODE_USING_GOLDEN, - MODE_GOLDEN_MV, MODE_INTER_FOURMV }, + { MODE_INTER_LAST_MV, MODE_INTER_PRIOR_LAST, + MODE_INTER_PLUS_MV, MODE_INTER_NO_MV, + MODE_INTRA, MODE_USING_GOLDEN, + MODE_GOLDEN_MV, MODE_INTER_FOURMV }, /* scheme 2 */ - { MODE_INTER_LAST_MV, MODE_INTER_PRIOR_LAST, - MODE_INTER_NO_MV, MODE_INTER_PLUS_MV, - MODE_INTRA, MODE_USING_GOLDEN, - MODE_GOLDEN_MV, MODE_INTER_FOURMV }, + { MODE_INTER_LAST_MV, MODE_INTER_PRIOR_LAST, + MODE_INTER_NO_MV, MODE_INTER_PLUS_MV, + MODE_INTRA, MODE_USING_GOLDEN, + MODE_GOLDEN_MV, MODE_INTER_FOURMV }, /* scheme 3 */ - { MODE_INTER_LAST_MV, MODE_INTER_PLUS_MV, - MODE_INTER_PRIOR_LAST, MODE_INTER_NO_MV, - MODE_INTRA, MODE_USING_GOLDEN, - MODE_GOLDEN_MV, MODE_INTER_FOURMV }, + { MODE_INTER_LAST_MV, MODE_INTER_PLUS_MV, + MODE_INTER_PRIOR_LAST, MODE_INTER_NO_MV, + MODE_INTRA, MODE_USING_GOLDEN, + MODE_GOLDEN_MV, MODE_INTER_FOURMV }, /* scheme 4 */ - { MODE_INTER_LAST_MV, MODE_INTER_PLUS_MV, - MODE_INTER_NO_MV, MODE_INTER_PRIOR_LAST, - MODE_INTRA, MODE_USING_GOLDEN, - MODE_GOLDEN_MV, MODE_INTER_FOURMV }, + { MODE_INTER_LAST_MV, MODE_INTER_PLUS_MV, + MODE_INTER_NO_MV, MODE_INTER_PRIOR_LAST, + MODE_INTRA, MODE_USING_GOLDEN, + MODE_GOLDEN_MV, MODE_INTER_FOURMV }, /* scheme 5: No motion vector dominates */ - { MODE_INTER_NO_MV, MODE_INTER_LAST_MV, - MODE_INTER_PRIOR_LAST, MODE_INTER_PLUS_MV, - MODE_INTRA, MODE_USING_GOLDEN, - MODE_GOLDEN_MV, MODE_INTER_FOURMV }, + { MODE_INTER_NO_MV, MODE_INTER_LAST_MV, + MODE_INTER_PRIOR_LAST, MODE_INTER_PLUS_MV, + MODE_INTRA, MODE_USING_GOLDEN, + MODE_GOLDEN_MV, MODE_INTER_FOURMV }, /* scheme 6 */ - { MODE_INTER_NO_MV, MODE_USING_GOLDEN, - MODE_INTER_LAST_MV, MODE_INTER_PRIOR_LAST, - MODE_INTER_PLUS_MV, MODE_INTRA, - MODE_GOLDEN_MV, MODE_INTER_FOURMV }, - + { MODE_INTER_NO_MV, MODE_USING_GOLDEN, + MODE_INTER_LAST_MV, MODE_INTER_PRIOR_LAST, + MODE_INTER_PLUS_MV, MODE_INTRA, + MODE_GOLDEN_MV, MODE_INTER_FOURMV }, }; static const uint8_t hilbert_offset[16][2] = { - {0,0}, {1,0}, {1,1}, {0,1}, - {0,2}, {0,3}, {1,3}, {1,2}, - {2,2}, {2,3}, {3,3}, {3,2}, - {3,1}, {2,1}, {2,0}, {3,0} + { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }, + { 0, 2 }, { 0, 3 }, { 1, 3 }, { 1, 2 }, + { 2, 2 }, { 2, 3 }, { 3, 3 }, { 3, 2 }, + { 3, 1 }, { 2, 1 }, { 2, 0 }, { 3, 0 } }; #define MIN_DEQUANT_VAL 2 @@ -184,7 +183,7 @@ typedef struct Vp3DecodeContext { uint32_t coded_ac_scale_factor[64]; uint8_t base_matrix[384][64]; uint8_t qr_count[2][3]; - uint8_t qr_size [2][3][64]; + uint8_t qr_size[2][3][64]; uint16_t qr_base[2][3][64]; /** @@ -211,7 +210,8 @@ typedef struct Vp3DecodeContext { #define TOKEN_COEFF(coeff) (((coeff) << 2) + 2) /** - * number of blocks that contain DCT coefficients at the given level or higher + * number of blocks that contain DCT coefficients at + * the given level or higher */ int num_coded_frags[3][64]; int total_num_coded_frags; @@ -255,13 +255,27 @@ typedef struct Vp3DecodeContext { uint32_t huffman_table[80][32][2]; uint8_t filter_limit_values[64]; - DECLARE_ALIGNED(8, int, bounding_values_array)[256+2]; + DECLARE_ALIGNED(8, int, bounding_values_array)[256 + 2]; } Vp3DecodeContext; /************************************************************************ * VP3 specific functions ************************************************************************/ +static av_cold void free_tables(AVCodecContext *avctx) +{ + Vp3DecodeContext *s = avctx->priv_data; + + av_freep(&s->superblock_coding); + av_freep(&s->all_fragments); + av_freep(&s->coded_fragment_list[0]); + av_freep(&s->dct_tokens_base); + av_freep(&s->superblock_fragments); + av_freep(&s->macroblock_coding); + av_freep(&s->motion_val[0]); + av_freep(&s->motion_val[1]); +} + static void vp3_decode_flush(AVCodecContext *avctx) { Vp3DecodeContext *s = avctx->priv_data; @@ -279,14 +293,7 @@ static av_cold int vp3_decode_end(AVCodecContext *avctx) Vp3DecodeContext *s = avctx->priv_data; int i; - av_freep(&s->superblock_coding); - av_freep(&s->all_fragments); - av_freep(&s->coded_fragment_list[0]); - av_freep(&s->dct_tokens_base); - av_freep(&s->superblock_fragments); - av_freep(&s->macroblock_coding); - av_freep(&s->motion_val[0]); - av_freep(&s->motion_val[1]); + free_tables(avctx); av_freep(&s->edge_emu_buffer); s->theora_tables = 0; @@ -313,7 +320,6 @@ static av_cold int vp3_decode_end(AVCodecContext *avctx) ff_free_vlc(&s->mode_code_vlc); ff_free_vlc(&s->motion_vector_vlc); - return 0; } @@ -330,19 +336,22 @@ static int init_block_mapping(Vp3DecodeContext *s) int x, y, i, j = 0; for (plane = 0; plane < 3; plane++) { - int sb_width = plane ? s->c_superblock_width : s->y_superblock_width; - int sb_height = plane ? s->c_superblock_height : s->y_superblock_height; + int sb_width = plane ? s->c_superblock_width + : s->y_superblock_width; + int sb_height = plane ? s->c_superblock_height + : s->y_superblock_height; int frag_width = s->fragment_width[!!plane]; int frag_height = s->fragment_height[!!plane]; for (sb_y = 0; sb_y < sb_height; sb_y++) for (sb_x = 0; sb_x < sb_width; sb_x++) for (i = 0; i < 16; i++) { - x = 4*sb_x + hilbert_offset[i][0]; - y = 4*sb_y + hilbert_offset[i][1]; + x = 4 * sb_x + hilbert_offset[i][0]; + y = 4 * sb_y + hilbert_offset[i][1]; if (x < frag_width && y < frag_height) - s->superblock_fragments[j++] = s->fragment_start[plane] + y*frag_width + x; + s->superblock_fragments[j++] = s->fragment_start[plane] + + y * frag_width + x; else s->superblock_fragments[j++] = -1; } @@ -361,30 +370,31 @@ static void init_dequantizer(Vp3DecodeContext *s, int qpi) int dc_scale_factor = s->coded_dc_scale_factor[s->qps[qpi]]; int i, plane, inter, qri, bmi, bmj, qistart; - for(inter=0; inter<2; inter++){ - for(plane=0; plane<3; plane++){ - int sum=0; - for(qri=0; qriqr_count[inter][plane]; qri++){ - sum+= s->qr_size[inter][plane][qri]; - if(s->qps[qpi] <= sum) + for (inter = 0; inter < 2; inter++) { + for (plane = 0; plane < 3; plane++) { + int sum = 0; + for (qri = 0; qri < s->qr_count[inter][plane]; qri++) { + sum += s->qr_size[inter][plane][qri]; + if (s->qps[qpi] <= sum) break; } - qistart= sum - s->qr_size[inter][plane][qri]; - bmi= s->qr_base[inter][plane][qri ]; - bmj= s->qr_base[inter][plane][qri+1]; - for(i=0; i<64; i++){ - int coeff= ( 2*(sum -s->qps[qpi])*s->base_matrix[bmi][i] - - 2*(qistart-s->qps[qpi])*s->base_matrix[bmj][i] - + s->qr_size[inter][plane][qri]) - / (2*s->qr_size[inter][plane][qri]); + qistart = sum - s->qr_size[inter][plane][qri]; + bmi = s->qr_base[inter][plane][qri]; + bmj = s->qr_base[inter][plane][qri + 1]; + for (i = 0; i < 64; i++) { + int coeff = (2 * (sum - s->qps[qpi]) * s->base_matrix[bmi][i] - + 2 * (qistart - s->qps[qpi]) * s->base_matrix[bmj][i] + + s->qr_size[inter][plane][qri]) / + (2 * s->qr_size[inter][plane][qri]); - int qmin= 8<<(inter + !i); - int qscale= i ? ac_scale_factor : dc_scale_factor; + int qmin = 8 << (inter + !i); + int qscale = i ? ac_scale_factor : dc_scale_factor; s->qmat[qpi][inter][plane][s->idct_permutation[i]] = av_clip((qscale * coeff) / 100 * 4, qmin, 4096); } - // all DC coefficients use the same quant so as not to interfere with DC prediction + /* all DC coefficients use the same quant so as not to interfere + * with DC prediction */ s->qmat[qpi][inter][plane][0] = s->qmat[0][inter][plane][0]; } } @@ -398,7 +408,7 @@ static void init_dequantizer(Vp3DecodeContext *s, int qpi) */ static void init_loop_filter(Vp3DecodeContext *s) { - int *bounding_values= s->bounding_values_array+127; + int *bounding_values = s->bounding_values_array + 127; int filter_limit; int x; int value; @@ -427,7 +437,9 @@ static void init_loop_filter(Vp3DecodeContext *s) */ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) { - int superblock_starts[3] = { 0, s->u_superblock_start, s->v_superblock_start }; + int superblock_starts[3] = { + 0, s->u_superblock_start, s->v_superblock_start + }; int bit = 0; int current_superblock = 0; int current_run = 0; @@ -439,11 +451,9 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) if (s->keyframe) { memset(s->superblock_coding, SB_FULLY_CODED, s->superblock_count); - } else { - /* unpack the list of partially-coded superblocks */ - bit = get_bits1(gb) ^ 1; + bit = get_bits1(gb) ^ 1; current_run = 0; while (current_superblock < s->superblock_count && get_bits_left(gb) > 0) { @@ -452,13 +462,14 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) else bit ^= 1; - current_run = get_vlc2(gb, - s->superblock_run_length_vlc.table, 6, 2) + 1; - if (current_run == 34) - current_run += get_bits(gb, 12); + current_run = get_vlc2(gb, s->superblock_run_length_vlc.table, + 6, 2) + 1; + if (current_run == 34) + current_run += get_bits(gb, 12); if (current_superblock + current_run > s->superblock_count) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid partially coded superblock run length\n"); + av_log(s->avctx, AV_LOG_ERROR, + "Invalid partially coded superblock run length\n"); return -1; } @@ -475,33 +486,33 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) int superblocks_decoded = 0; current_superblock = 0; - bit = get_bits1(gb) ^ 1; - current_run = 0; - - while (superblocks_decoded < s->superblock_count - num_partial_superblocks - && get_bits_left(gb) > 0) { + bit = get_bits1(gb) ^ 1; + current_run = 0; + while (superblocks_decoded < s->superblock_count - num_partial_superblocks && + get_bits_left(gb) > 0) { if (s->theora && current_run == MAXIMUM_LONG_BIT_RUN) bit = get_bits1(gb); else bit ^= 1; - current_run = get_vlc2(gb, - s->superblock_run_length_vlc.table, 6, 2) + 1; - if (current_run == 34) - current_run += get_bits(gb, 12); + current_run = get_vlc2(gb, s->superblock_run_length_vlc.table, + 6, 2) + 1; + if (current_run == 34) + current_run += get_bits(gb, 12); for (j = 0; j < current_run; current_superblock++) { if (current_superblock >= s->superblock_count) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid fully coded superblock run length\n"); + av_log(s->avctx, AV_LOG_ERROR, + "Invalid fully coded superblock run length\n"); return -1; } - /* skip any superblocks already marked as partially coded */ - if (s->superblock_coding[current_superblock] == SB_NOT_CODED) { - s->superblock_coding[current_superblock] = 2*bit; - j++; - } + /* skip any superblocks already marked as partially coded */ + if (s->superblock_coding[current_superblock] == SB_NOT_CODED) { + s->superblock_coding[current_superblock] = 2 * bit; + j++; + } } superblocks_decoded += current_run; } @@ -510,9 +521,8 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) /* if there were partial blocks, initialize bitstream for * unpacking fragment codings */ if (num_partial_superblocks) { - current_run = 0; - bit = get_bits1(gb); + bit = get_bits1(gb); /* toggle the bit because as soon as the first run length is * fetched the bit will be toggled again */ bit ^= 1; @@ -526,30 +536,27 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) for (plane = 0; plane < 3; plane++) { int sb_start = superblock_starts[plane]; - int sb_end = sb_start + (plane ? s->c_superblock_count : s->y_superblock_count); + int sb_end = sb_start + (plane ? s->c_superblock_count + : s->y_superblock_count); int num_coded_frags = 0; - for (i = sb_start; i < sb_end && get_bits_left(gb) > 0; i++) { + for (i = sb_start; i < sb_end && get_bits_left(gb) > 0; i++) { + /* iterate through all 16 fragments in a superblock */ + for (j = 0; j < 16; j++) { + /* if the fragment is in bounds, check its coding status */ + current_fragment = s->superblock_fragments[i * 16 + j]; + if (current_fragment != -1) { + int coded = s->superblock_coding[i]; - /* iterate through all 16 fragments in a superblock */ - for (j = 0; j < 16; j++) { - - /* if the fragment is in bounds, check its coding status */ - current_fragment = s->superblock_fragments[i * 16 + j]; - if (current_fragment != -1) { - int coded = s->superblock_coding[i]; - - if (s->superblock_coding[i] == SB_PARTIALLY_CODED) { - - /* fragment may or may not be coded; this is the case - * that cares about the fragment coding runs */ - if (current_run-- == 0) { - bit ^= 1; - current_run = get_vlc2(gb, - s->fragment_run_length_vlc.table, 5, 2); + if (s->superblock_coding[i] == SB_PARTIALLY_CODED) { + /* fragment may or may not be coded; this is the case + * that cares about the fragment coding runs */ + if (current_run-- == 0) { + bit ^= 1; + current_run = get_vlc2(gb, s->fragment_run_length_vlc.table, 5, 2); + } + coded = bit; } - coded = bit; - } if (coded) { /* default mode; actual mode will be decoded in @@ -563,14 +570,15 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) s->all_fragments[current_fragment].coding_method = MODE_COPY; } + } } } - } s->total_num_coded_frags += num_coded_frags; for (i = 0; i < 64; i++) s->num_coded_frags[plane][i] = num_coded_frags; if (plane < 2) - s->coded_fragment_list[plane+1] = s->coded_fragment_list[plane] + num_coded_frags; + s->coded_fragment_list[plane + 1] = s->coded_fragment_list[plane] + + num_coded_frags; } return 0; } @@ -593,9 +601,7 @@ static int unpack_modes(Vp3DecodeContext *s, GetBitContext *gb) if (s->keyframe) { for (i = 0; i < s->fragment_count; i++) s->all_fragments[i].coding_method = MODE_INTRA; - } else { - /* fetch the mode coding scheme for this frame */ scheme = get_bits(gb, 3); @@ -607,7 +613,7 @@ static int unpack_modes(Vp3DecodeContext *s, GetBitContext *gb) custom_mode_alphabet[get_bits(gb, 3)] = i; alphabet = custom_mode_alphabet; } else - alphabet = ModeAlphabet[scheme-1]; + alphabet = ModeAlphabet[scheme - 1]; /* iterate through all of the macroblocks that contain 1 or more * coded fragments */ @@ -616,65 +622,70 @@ static int unpack_modes(Vp3DecodeContext *s, GetBitContext *gb) if (get_bits_left(gb) <= 0) return -1; - for (j = 0; j < 4; j++) { - int mb_x = 2*sb_x + (j>>1); - int mb_y = 2*sb_y + (((j>>1)+j)&1); - current_macroblock = mb_y * s->macroblock_width + mb_x; + for (j = 0; j < 4; j++) { + int mb_x = 2 * sb_x + (j >> 1); + int mb_y = 2 * sb_y + (((j >> 1) + j) & 1); + current_macroblock = mb_y * s->macroblock_width + mb_x; - if (mb_x >= s->macroblock_width || mb_y >= s->macroblock_height) - continue; + if (mb_x >= s->macroblock_width || + mb_y >= s->macroblock_height) + continue; -#define BLOCK_X (2*mb_x + (k&1)) -#define BLOCK_Y (2*mb_y + (k>>1)) - /* coding modes are only stored if the macroblock has at least one - * luma block coded, otherwise it must be INTER_NO_MV */ - for (k = 0; k < 4; k++) { - current_fragment = BLOCK_Y*s->fragment_width[0] + BLOCK_X; - if (s->all_fragments[current_fragment].coding_method != MODE_COPY) - break; - } - if (k == 4) { - s->macroblock_coding[current_macroblock] = MODE_INTER_NO_MV; - continue; - } +#define BLOCK_X (2 * mb_x + (k & 1)) +#define BLOCK_Y (2 * mb_y + (k >> 1)) + /* coding modes are only stored if the macroblock has + * at least one luma block coded, otherwise it must be + * INTER_NO_MV */ + for (k = 0; k < 4; k++) { + current_fragment = BLOCK_Y * + s->fragment_width[0] + BLOCK_X; + if (s->all_fragments[current_fragment].coding_method != MODE_COPY) + break; + } + if (k == 4) { + s->macroblock_coding[current_macroblock] = MODE_INTER_NO_MV; + continue; + } - /* mode 7 means get 3 bits for each coding mode */ - if (scheme == 7) - coding_mode = get_bits(gb, 3); - else - coding_mode = alphabet - [get_vlc2(gb, s->mode_code_vlc.table, 3, 3)]; + /* mode 7 means get 3 bits for each coding mode */ + if (scheme == 7) + coding_mode = get_bits(gb, 3); + else + coding_mode = alphabet[get_vlc2(gb, s->mode_code_vlc.table, 3, 3)]; - s->macroblock_coding[current_macroblock] = coding_mode; - for (k = 0; k < 4; k++) { - frag = s->all_fragments + BLOCK_Y*s->fragment_width[0] + BLOCK_X; - if (frag->coding_method != MODE_COPY) - frag->coding_method = coding_mode; - } + s->macroblock_coding[current_macroblock] = coding_mode; + for (k = 0; k < 4; k++) { + frag = s->all_fragments + BLOCK_Y * s->fragment_width[0] + BLOCK_X; + if (frag->coding_method != MODE_COPY) + frag->coding_method = coding_mode; + } -#define SET_CHROMA_MODES \ - if (frag[s->fragment_start[1]].coding_method != MODE_COPY) \ - frag[s->fragment_start[1]].coding_method = coding_mode;\ - if (frag[s->fragment_start[2]].coding_method != MODE_COPY) \ +#define SET_CHROMA_MODES \ + if (frag[s->fragment_start[1]].coding_method != MODE_COPY) \ + frag[s->fragment_start[1]].coding_method = coding_mode; \ + if (frag[s->fragment_start[2]].coding_method != MODE_COPY) \ frag[s->fragment_start[2]].coding_method = coding_mode; - if (s->chroma_y_shift) { - frag = s->all_fragments + mb_y*s->fragment_width[1] + mb_x; - SET_CHROMA_MODES - } else if (s->chroma_x_shift) { - frag = s->all_fragments + 2*mb_y*s->fragment_width[1] + mb_x; - for (k = 0; k < 2; k++) { - SET_CHROMA_MODES - frag += s->fragment_width[1]; - } - } else { - for (k = 0; k < 4; k++) { - frag = s->all_fragments + BLOCK_Y*s->fragment_width[1] + BLOCK_X; + if (s->chroma_y_shift) { + frag = s->all_fragments + mb_y * + s->fragment_width[1] + mb_x; SET_CHROMA_MODES + } else if (s->chroma_x_shift) { + frag = s->all_fragments + + 2 * mb_y * s->fragment_width[1] + mb_x; + for (k = 0; k < 2; k++) { + SET_CHROMA_MODES + frag += s->fragment_width[1]; + } + } else { + for (k = 0; k < 4; k++) { + frag = s->all_fragments + + BLOCK_Y * s->fragment_width[1] + BLOCK_X; + SET_CHROMA_MODES + } } } } - } } } @@ -712,151 +723,152 @@ static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb) if (get_bits_left(gb) <= 0) return -1; - for (j = 0; j < 4; j++) { - int mb_x = 2*sb_x + (j>>1); - int mb_y = 2*sb_y + (((j>>1)+j)&1); - current_macroblock = mb_y * s->macroblock_width + mb_x; + for (j = 0; j < 4; j++) { + int mb_x = 2 * sb_x + (j >> 1); + int mb_y = 2 * sb_y + (((j >> 1) + j) & 1); + current_macroblock = mb_y * s->macroblock_width + mb_x; - if (mb_x >= s->macroblock_width || mb_y >= s->macroblock_height || - (s->macroblock_coding[current_macroblock] == MODE_COPY)) - continue; + if (mb_x >= s->macroblock_width || + mb_y >= s->macroblock_height || + s->macroblock_coding[current_macroblock] == MODE_COPY) + continue; - switch (s->macroblock_coding[current_macroblock]) { + switch (s->macroblock_coding[current_macroblock]) { + case MODE_INTER_PLUS_MV: + case MODE_GOLDEN_MV: + /* all 6 fragments use the same motion vector */ + if (coding_mode == 0) { + motion_x[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; + motion_y[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; + } else { + motion_x[0] = fixed_motion_vector_table[get_bits(gb, 6)]; + motion_y[0] = fixed_motion_vector_table[get_bits(gb, 6)]; + } - case MODE_INTER_PLUS_MV: - case MODE_GOLDEN_MV: - /* all 6 fragments use the same motion vector */ - if (coding_mode == 0) { - motion_x[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; - motion_y[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; - } else { - motion_x[0] = fixed_motion_vector_table[get_bits(gb, 6)]; - motion_y[0] = fixed_motion_vector_table[get_bits(gb, 6)]; - } + /* vector maintenance, only on MODE_INTER_PLUS_MV */ + if (s->macroblock_coding[current_macroblock] == MODE_INTER_PLUS_MV) { + prior_last_motion_x = last_motion_x; + prior_last_motion_y = last_motion_y; + last_motion_x = motion_x[0]; + last_motion_y = motion_y[0]; + } + break; - /* vector maintenance, only on MODE_INTER_PLUS_MV */ - if (s->macroblock_coding[current_macroblock] == - MODE_INTER_PLUS_MV) { + case MODE_INTER_FOURMV: + /* vector maintenance */ prior_last_motion_x = last_motion_x; prior_last_motion_y = last_motion_y; - last_motion_x = motion_x[0]; - last_motion_y = motion_y[0]; - } - break; - case MODE_INTER_FOURMV: - /* vector maintenance */ - prior_last_motion_x = last_motion_x; - prior_last_motion_y = last_motion_y; - - /* fetch 4 vectors from the bitstream, one for each - * Y fragment, then average for the C fragment vectors */ - for (k = 0; k < 4; k++) { - current_fragment = BLOCK_Y*s->fragment_width[0] + BLOCK_X; - if (s->all_fragments[current_fragment].coding_method != MODE_COPY) { - if (coding_mode == 0) { - motion_x[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; - motion_y[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; + /* fetch 4 vectors from the bitstream, one for each + * Y fragment, then average for the C fragment vectors */ + for (k = 0; k < 4; k++) { + current_fragment = BLOCK_Y * s->fragment_width[0] + BLOCK_X; + if (s->all_fragments[current_fragment].coding_method != MODE_COPY) { + if (coding_mode == 0) { + motion_x[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; + motion_y[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; + } else { + motion_x[k] = fixed_motion_vector_table[get_bits(gb, 6)]; + motion_y[k] = fixed_motion_vector_table[get_bits(gb, 6)]; + } + last_motion_x = motion_x[k]; + last_motion_y = motion_y[k]; } else { - motion_x[k] = fixed_motion_vector_table[get_bits(gb, 6)]; - motion_y[k] = fixed_motion_vector_table[get_bits(gb, 6)]; + motion_x[k] = 0; + motion_y[k] = 0; } - last_motion_x = motion_x[k]; - last_motion_y = motion_y[k]; + } + break; + + case MODE_INTER_LAST_MV: + /* all 6 fragments use the last motion vector */ + motion_x[0] = last_motion_x; + motion_y[0] = last_motion_y; + + /* no vector maintenance (last vector remains the + * last vector) */ + break; + + case MODE_INTER_PRIOR_LAST: + /* all 6 fragments use the motion vector prior to the + * last motion vector */ + motion_x[0] = prior_last_motion_x; + motion_y[0] = prior_last_motion_y; + + /* vector maintenance */ + prior_last_motion_x = last_motion_x; + prior_last_motion_y = last_motion_y; + last_motion_x = motion_x[0]; + last_motion_y = motion_y[0]; + break; + + default: + /* covers intra, inter without MV, golden without MV */ + motion_x[0] = 0; + motion_y[0] = 0; + + /* no vector maintenance */ + break; + } + + /* assign the motion vectors to the correct fragments */ + for (k = 0; k < 4; k++) { + current_fragment = + BLOCK_Y * s->fragment_width[0] + BLOCK_X; + if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { + s->motion_val[0][current_fragment][0] = motion_x[k]; + s->motion_val[0][current_fragment][1] = motion_y[k]; } else { - motion_x[k] = 0; - motion_y[k] = 0; + s->motion_val[0][current_fragment][0] = motion_x[0]; + s->motion_val[0][current_fragment][1] = motion_y[0]; } } - break; - case MODE_INTER_LAST_MV: - /* all 6 fragments use the last motion vector */ - motion_x[0] = last_motion_x; - motion_y[0] = last_motion_y; - - /* no vector maintenance (last vector remains the - * last vector) */ - break; - - case MODE_INTER_PRIOR_LAST: - /* all 6 fragments use the motion vector prior to the - * last motion vector */ - motion_x[0] = prior_last_motion_x; - motion_y[0] = prior_last_motion_y; - - /* vector maintenance */ - prior_last_motion_x = last_motion_x; - prior_last_motion_y = last_motion_y; - last_motion_x = motion_x[0]; - last_motion_y = motion_y[0]; - break; - - default: - /* covers intra, inter without MV, golden without MV */ - motion_x[0] = 0; - motion_y[0] = 0; - - /* no vector maintenance */ - break; - } - - /* assign the motion vectors to the correct fragments */ - for (k = 0; k < 4; k++) { - current_fragment = - BLOCK_Y*s->fragment_width[0] + BLOCK_X; - if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { - s->motion_val[0][current_fragment][0] = motion_x[k]; - s->motion_val[0][current_fragment][1] = motion_y[k]; - } else { - s->motion_val[0][current_fragment][0] = motion_x[0]; - s->motion_val[0][current_fragment][1] = motion_y[0]; - } - } - - if (s->chroma_y_shift) { - if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { - motion_x[0] = RSHIFT(motion_x[0] + motion_x[1] + motion_x[2] + motion_x[3], 2); - motion_y[0] = RSHIFT(motion_y[0] + motion_y[1] + motion_y[2] + motion_y[3], 2); - } - motion_x[0] = (motion_x[0]>>1) | (motion_x[0]&1); - motion_y[0] = (motion_y[0]>>1) | (motion_y[0]&1); - frag = mb_y*s->fragment_width[1] + mb_x; - s->motion_val[1][frag][0] = motion_x[0]; - s->motion_val[1][frag][1] = motion_y[0]; - } else if (s->chroma_x_shift) { - if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { - motion_x[0] = RSHIFT(motion_x[0] + motion_x[1], 1); - motion_y[0] = RSHIFT(motion_y[0] + motion_y[1], 1); - motion_x[1] = RSHIFT(motion_x[2] + motion_x[3], 1); - motion_y[1] = RSHIFT(motion_y[2] + motion_y[3], 1); - } else { - motion_x[1] = motion_x[0]; - motion_y[1] = motion_y[0]; - } - motion_x[0] = (motion_x[0]>>1) | (motion_x[0]&1); - motion_x[1] = (motion_x[1]>>1) | (motion_x[1]&1); - - frag = 2*mb_y*s->fragment_width[1] + mb_x; - for (k = 0; k < 2; k++) { - s->motion_val[1][frag][0] = motion_x[k]; - s->motion_val[1][frag][1] = motion_y[k]; - frag += s->fragment_width[1]; - } - } else { - for (k = 0; k < 4; k++) { - frag = BLOCK_Y*s->fragment_width[1] + BLOCK_X; + if (s->chroma_y_shift) { if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { + motion_x[0] = RSHIFT(motion_x[0] + motion_x[1] + + motion_x[2] + motion_x[3], 2); + motion_y[0] = RSHIFT(motion_y[0] + motion_y[1] + + motion_y[2] + motion_y[3], 2); + } + motion_x[0] = (motion_x[0] >> 1) | (motion_x[0] & 1); + motion_y[0] = (motion_y[0] >> 1) | (motion_y[0] & 1); + frag = mb_y * s->fragment_width[1] + mb_x; + s->motion_val[1][frag][0] = motion_x[0]; + s->motion_val[1][frag][1] = motion_y[0]; + } else if (s->chroma_x_shift) { + if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { + motion_x[0] = RSHIFT(motion_x[0] + motion_x[1], 1); + motion_y[0] = RSHIFT(motion_y[0] + motion_y[1], 1); + motion_x[1] = RSHIFT(motion_x[2] + motion_x[3], 1); + motion_y[1] = RSHIFT(motion_y[2] + motion_y[3], 1); + } else { + motion_x[1] = motion_x[0]; + motion_y[1] = motion_y[0]; + } + motion_x[0] = (motion_x[0] >> 1) | (motion_x[0] & 1); + motion_x[1] = (motion_x[1] >> 1) | (motion_x[1] & 1); + + frag = 2 * mb_y * s->fragment_width[1] + mb_x; + for (k = 0; k < 2; k++) { s->motion_val[1][frag][0] = motion_x[k]; s->motion_val[1][frag][1] = motion_y[k]; - } else { - s->motion_val[1][frag][0] = motion_x[0]; - s->motion_val[1][frag][1] = motion_y[0]; + frag += s->fragment_width[1]; + } + } else { + for (k = 0; k < 4; k++) { + frag = BLOCK_Y * s->fragment_width[1] + BLOCK_X; + if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { + s->motion_val[1][frag][0] = motion_x[k]; + s->motion_val[1][frag][1] = motion_y[k]; + } else { + s->motion_val[1][frag][0] = motion_x[0]; + s->motion_val[1][frag][1] = motion_y[0]; + } } } } } - } } return 0; @@ -867,10 +879,10 @@ static int unpack_block_qpis(Vp3DecodeContext *s, GetBitContext *gb) int qpi, i, j, bit, run_length, blocks_decoded, num_blocks_at_qpi; int num_blocks = s->total_num_coded_frags; - for (qpi = 0; qpi < s->nqps-1 && num_blocks > 0; qpi++) { + for (qpi = 0; qpi < s->nqps - 1 && num_blocks > 0; qpi++) { i = blocks_decoded = num_blocks_at_qpi = 0; - bit = get_bits1(gb) ^ 1; + bit = get_bits1(gb) ^ 1; run_length = 0; do { @@ -917,34 +929,37 @@ static int unpack_block_qpis(Vp3DecodeContext *s, GetBitContext *gb) * be passed into the next call to this same function. */ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb, - VLC *table, int coeff_index, - int plane, - int eob_run) + VLC *table, int coeff_index, + int plane, + int eob_run) { int i, j = 0; int token; - int zero_run = 0; + int zero_run = 0; int16_t coeff = 0; int bits_to_get; int blocks_ended; int coeff_i = 0; - int num_coeffs = s->num_coded_frags[plane][coeff_index]; + int num_coeffs = s->num_coded_frags[plane][coeff_index]; int16_t *dct_tokens = s->dct_tokens[plane][coeff_index]; /* local references to structure members to avoid repeated deferences */ - int *coded_fragment_list = s->coded_fragment_list[plane]; + int *coded_fragment_list = s->coded_fragment_list[plane]; Vp3Fragment *all_fragments = s->all_fragments; - VLC_TYPE (*vlc_table)[2] = table->table; + 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); + av_log(s->avctx, AV_LOG_ERROR, + "Invalid number of coefficents at level %d\n", coeff_index); if (eob_run > num_coeffs) { - coeff_i = blocks_ended = num_coeffs; - eob_run -= num_coeffs; + coeff_i = + blocks_ended = num_coeffs; + eob_run -= num_coeffs; } else { - coeff_i = blocks_ended = eob_run; - eob_run = 0; + coeff_i = + blocks_ended = eob_run; + eob_run = 0; } // insert fake EOB token to cover the split between planes or zzi @@ -952,82 +967,82 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb, dct_tokens[j++] = blocks_ended << 2; while (coeff_i < num_coeffs && get_bits_left(gb) > 0) { - /* decode a VLC into a token */ - token = get_vlc2(gb, vlc_table, 11, 3); - /* use the token to get a zero run, a coefficient, and an eob run */ - if ((unsigned) token <= 6U) { - eob_run = eob_run_base[token]; - if (eob_run_get_bits[token]) - eob_run += get_bits(gb, eob_run_get_bits[token]); + /* decode a VLC into a token */ + token = get_vlc2(gb, vlc_table, 11, 3); + /* use the token to get a zero run, a coefficient, and an eob run */ + if ((unsigned) token <= 6U) { + eob_run = eob_run_base[token]; + if (eob_run_get_bits[token]) + eob_run += get_bits(gb, eob_run_get_bits[token]); - // record only the number of blocks ended in this plane, - // any spill will be recorded in the next plane. - if (eob_run > num_coeffs - coeff_i) { - dct_tokens[j++] = TOKEN_EOB(num_coeffs - coeff_i); - blocks_ended += num_coeffs - coeff_i; - eob_run -= num_coeffs - coeff_i; - coeff_i = num_coeffs; - } else { - dct_tokens[j++] = TOKEN_EOB(eob_run); - blocks_ended += eob_run; - coeff_i += eob_run; - eob_run = 0; - } - } else if (token >= 0) { - bits_to_get = coeff_get_bits[token]; - if (bits_to_get) - bits_to_get = get_bits(gb, bits_to_get); - coeff = coeff_tables[token][bits_to_get]; - - zero_run = zero_run_base[token]; - if (zero_run_get_bits[token]) - zero_run += get_bits(gb, zero_run_get_bits[token]); - - if (zero_run) { - dct_tokens[j++] = TOKEN_ZERO_RUN(coeff, zero_run); - } else { - // Save DC into the fragment structure. DC prediction is - // done in raster order, so the actual DC can't be in with - // other tokens. We still need the token in dct_tokens[] - // however, or else the structure collapses on itself. - if (!coeff_index) - all_fragments[coded_fragment_list[coeff_i]].dc = coeff; - - dct_tokens[j++] = TOKEN_COEFF(coeff); - } - - if (coeff_index + zero_run > 64) { - av_log(s->avctx, AV_LOG_DEBUG, "Invalid zero run of %d with" - " %d coeffs left\n", zero_run, 64-coeff_index); - zero_run = 64 - coeff_index; - } - - // zero runs code multiple coefficients, - // so don't try to decode coeffs for those higher levels - for (i = coeff_index+1; i <= coeff_index+zero_run; i++) - s->num_coded_frags[plane][i]--; - coeff_i++; + // record only the number of blocks ended in this plane, + // any spill will be recorded in the next plane. + if (eob_run > num_coeffs - coeff_i) { + dct_tokens[j++] = TOKEN_EOB(num_coeffs - coeff_i); + blocks_ended += num_coeffs - coeff_i; + eob_run -= num_coeffs - coeff_i; + coeff_i = num_coeffs; } else { - av_log(s->avctx, AV_LOG_ERROR, - "Invalid token %d\n", token); - return -1; + dct_tokens[j++] = TOKEN_EOB(eob_run); + blocks_ended += eob_run; + coeff_i += eob_run; + eob_run = 0; } + } else if (token >= 0) { + bits_to_get = coeff_get_bits[token]; + if (bits_to_get) + bits_to_get = get_bits(gb, bits_to_get); + coeff = coeff_tables[token][bits_to_get]; + + zero_run = zero_run_base[token]; + if (zero_run_get_bits[token]) + zero_run += get_bits(gb, zero_run_get_bits[token]); + + if (zero_run) { + dct_tokens[j++] = TOKEN_ZERO_RUN(coeff, zero_run); + } else { + // Save DC into the fragment structure. DC prediction is + // done in raster order, so the actual DC can't be in with + // other tokens. We still need the token in dct_tokens[] + // however, or else the structure collapses on itself. + if (!coeff_index) + all_fragments[coded_fragment_list[coeff_i]].dc = coeff; + + dct_tokens[j++] = TOKEN_COEFF(coeff); + } + + if (coeff_index + zero_run > 64) { + av_log(s->avctx, AV_LOG_DEBUG, + "Invalid zero run of %d with %d coeffs left\n", + zero_run, 64 - coeff_index); + zero_run = 64 - coeff_index; + } + + // zero runs code multiple coefficients, + // so don't try to decode coeffs for those higher levels + for (i = coeff_index + 1; i <= coeff_index + zero_run; i++) + s->num_coded_frags[plane][i]--; + coeff_i++; + } else { + av_log(s->avctx, AV_LOG_ERROR, "Invalid token %d\n", token); + return -1; + } } if (blocks_ended > s->num_coded_frags[plane][coeff_index]) av_log(s->avctx, AV_LOG_ERROR, "More blocks ended than coded!\n"); - // decrement the number of blocks that have higher coeffecients for each + // 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++) + for (i = coeff_index + 1; i < 64; i++) s->num_coded_frags[plane][i] -= blocks_ended; // setup the next buffer if (plane < 2) - s->dct_tokens[plane+1][coeff_index] = dct_tokens + j; + s->dct_tokens[plane + 1][coeff_index] = dct_tokens + j; else if (coeff_index < 63) - s->dct_tokens[0][coeff_index+1] = dct_tokens + j; + s->dct_tokens[0][coeff_index + 1] = dct_tokens + j; return eob_run; } @@ -1059,7 +1074,7 @@ static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb) /* unpack the Y plane DC coefficients */ residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_y_table], 0, - 0, residual_eob_run); + 0, residual_eob_run); if (residual_eob_run < 0) return residual_eob_run; @@ -1068,21 +1083,20 @@ static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb) /* unpack the C plane DC coefficients */ residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_c_table], 0, - 1, residual_eob_run); + 1, residual_eob_run); if (residual_eob_run < 0) return residual_eob_run; residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_c_table], 0, - 2, residual_eob_run); + 2, residual_eob_run); if (residual_eob_run < 0) return residual_eob_run; /* reverse prediction of the C-plane DC coefficients */ - if (!(s->avctx->flags & CODEC_FLAG_GRAY)) - { + if (!(s->avctx->flags & CODEC_FLAG_GRAY)) { reverse_dc_prediction(s, s->fragment_start[1], - s->fragment_width[1], s->fragment_height[1]); + s->fragment_width[1], s->fragment_height[1]); reverse_dc_prediction(s, s->fragment_start[2], - s->fragment_width[1], s->fragment_height[1]); + s->fragment_width[1], s->fragment_height[1]); } /* fetch the AC table indexes */ @@ -1109,19 +1123,19 @@ static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb) /* decode all AC coefficents */ for (i = 1; i <= 63; i++) { - residual_eob_run = unpack_vlcs(s, gb, y_tables[i], i, - 0, residual_eob_run); - if (residual_eob_run < 0) - return residual_eob_run; + residual_eob_run = unpack_vlcs(s, gb, y_tables[i], i, + 0, residual_eob_run); + if (residual_eob_run < 0) + return residual_eob_run; - residual_eob_run = unpack_vlcs(s, gb, c_tables[i], i, - 1, residual_eob_run); - if (residual_eob_run < 0) - return residual_eob_run; - residual_eob_run = unpack_vlcs(s, gb, c_tables[i], i, - 2, residual_eob_run); - if (residual_eob_run < 0) - return residual_eob_run; + residual_eob_run = unpack_vlcs(s, gb, c_tables[i], i, + 1, residual_eob_run); + if (residual_eob_run < 0) + return residual_eob_run; + residual_eob_run = unpack_vlcs(s, gb, c_tables[i], i, + 2, residual_eob_run); + if (residual_eob_run < 0) + return residual_eob_run; } return 0; @@ -1132,8 +1146,8 @@ static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb) * the frame. Much of this function is adapted directly from the original * VP3 source code. */ -#define COMPATIBLE_FRAME(x) \ - (compatible_frame[s->all_fragments[x].coding_method] == current_frame_type) +#define COMPATIBLE_FRAME(x) \ + (compatible_frame[s->all_fragments[x].coding_method] == current_frame_type) #define DC_COEFF(u) s->all_fragments[u].dc static void reverse_dc_prediction(Vp3DecodeContext *s, @@ -1141,7 +1155,6 @@ static void reverse_dc_prediction(Vp3DecodeContext *s, int fragment_width, int fragment_height) { - #define PUL 8 #define PU 4 #define PUR 2 @@ -1166,22 +1179,22 @@ static void reverse_dc_prediction(Vp3DecodeContext *s, * 3: left multiplier */ static const int predictor_transform[16][4] = { - { 0, 0, 0, 0}, - { 0, 0, 0,128}, // PL - { 0, 0,128, 0}, // PUR - { 0, 0, 53, 75}, // PUR|PL - { 0,128, 0, 0}, // PU - { 0, 64, 0, 64}, // PU|PL - { 0,128, 0, 0}, // PU|PUR - { 0, 0, 53, 75}, // PU|PUR|PL - {128, 0, 0, 0}, // PUL - { 0, 0, 0,128}, // PUL|PL - { 64, 0, 64, 0}, // PUL|PUR - { 0, 0, 53, 75}, // PUL|PUR|PL - { 0,128, 0, 0}, // PUL|PU - {-104,116, 0,116}, // PUL|PU|PL - { 24, 80, 24, 0}, // PUL|PU|PUR - {-104,116, 0,116} // PUL|PU|PUR|PL + { 0, 0, 0, 0 }, + { 0, 0, 0, 128 }, // PL + { 0, 0, 128, 0 }, // PUR + { 0, 0, 53, 75 }, // PUR|PL + { 0, 128, 0, 0 }, // PU + { 0, 64, 0, 64 }, // PU |PL + { 0, 128, 0, 0 }, // PU |PUR + { 0, 0, 53, 75 }, // PU |PUR|PL + { 128, 0, 0, 0 }, // PUL + { 0, 0, 0, 128 }, // PUL|PL + { 64, 0, 64, 0 }, // PUL|PUR + { 0, 0, 53, 75 }, // PUL|PUR|PL + { 0, 128, 0, 0 }, // PUL|PU + { -104, 116, 0, 116 }, // PUL|PU |PL + { 24, 80, 24, 0 }, // PUL|PU |PUR + { -104, 116, 0, 116 } // PUL|PU |PUR|PL }; /* This table shows which types of blocks can use other blocks for @@ -1208,54 +1221,55 @@ static void reverse_dc_prediction(Vp3DecodeContext *s, int transform = 0; - vul = vu = vur = vl = 0; - last_dc[0] = last_dc[1] = last_dc[2] = 0; + vul = + vu = + vur = + vl = 0; + last_dc[0] = + last_dc[1] = + last_dc[2] = 0; /* for each fragment row... */ for (y = 0; y < fragment_height; y++) { - /* for each fragment in a row... */ for (x = 0; x < fragment_width; x++, i++) { /* reverse prediction if this block was coded */ if (s->all_fragments[i].coding_method != MODE_COPY) { - current_frame_type = compatible_frame[s->all_fragments[i].coding_method]; - transform= 0; - if(x){ - l= i-1; + transform = 0; + if (x) { + l = i - 1; vl = DC_COEFF(l); - if(COMPATIBLE_FRAME(l)) + if (COMPATIBLE_FRAME(l)) transform |= PL; } - if(y){ - u= i-fragment_width; + if (y) { + u = i - fragment_width; vu = DC_COEFF(u); - if(COMPATIBLE_FRAME(u)) + if (COMPATIBLE_FRAME(u)) transform |= PU; - if(x){ - ul= i-fragment_width-1; + if (x) { + ul = i - fragment_width - 1; vul = DC_COEFF(ul); - if(COMPATIBLE_FRAME(ul)) + if (COMPATIBLE_FRAME(ul)) transform |= PUL; } - if(x + 1 < fragment_width){ - ur= i-fragment_width+1; + if (x + 1 < fragment_width) { + ur = i - fragment_width + 1; vur = DC_COEFF(ur); - if(COMPATIBLE_FRAME(ur)) + if (COMPATIBLE_FRAME(ur)) transform |= PUR; } } if (transform == 0) { - /* if there were no fragments to predict from, use last * DC saved */ predicted_dc = last_dc[current_frame_type]; } else { - /* apply the appropriate predictor transform */ predicted_dc = (predictor_transform[transform][0] * vul) + @@ -1286,39 +1300,39 @@ static void reverse_dc_prediction(Vp3DecodeContext *s, } } -static void apply_loop_filter(Vp3DecodeContext *s, int plane, int ystart, int yend) +static void apply_loop_filter(Vp3DecodeContext *s, int plane, + int ystart, int yend) { int x, y; - int *bounding_values= s->bounding_values_array+127; + int *bounding_values = s->bounding_values_array + 127; int width = s->fragment_width[!!plane]; int height = s->fragment_height[!!plane]; - int fragment = s->fragment_start [plane] + ystart * width; + int fragment = s->fragment_start[plane] + ystart * width; ptrdiff_t stride = s->current_frame.f->linesize[plane]; - uint8_t *plane_data = s->current_frame.f->data [plane]; - if (!s->flipped_image) stride = -stride; - plane_data += s->data_offset[plane] + 8*ystart*stride; + uint8_t *plane_data = s->current_frame.f->data[plane]; + if (!s->flipped_image) + stride = -stride; + plane_data += s->data_offset[plane] + 8 * ystart * stride; for (y = ystart; y < yend; y++) { - for (x = 0; x < width; x++) { /* This code basically just deblocks on the edges of coded blocks. * However, it has to be much more complicated because of the * braindamaged deblock ordering used in VP3/Theora. Order matters * because some pixels get filtered twice. */ - if( s->all_fragments[fragment].coding_method != MODE_COPY ) - { + if (s->all_fragments[fragment].coding_method != MODE_COPY) { /* do not perform left edge filter for left columns frags */ if (x > 0) { s->vp3dsp.h_loop_filter( - plane_data + 8*x, + plane_data + 8 * x, stride, bounding_values); } /* do not perform top edge filter for top row fragments */ if (y > 0) { s->vp3dsp.v_loop_filter( - plane_data + 8*x, + plane_data + 8 * x, stride, bounding_values); } @@ -1328,7 +1342,7 @@ static void apply_loop_filter(Vp3DecodeContext *s, int plane, int ystart, int ye if ((x < width - 1) && (s->all_fragments[fragment + 1].coding_method == MODE_COPY)) { s->vp3dsp.h_loop_filter( - plane_data + 8*x + 8, + plane_data + 8 * x + 8, stride, bounding_values); } @@ -1338,14 +1352,14 @@ static void apply_loop_filter(Vp3DecodeContext *s, int plane, int ystart, int ye if ((y < height - 1) && (s->all_fragments[fragment + width].coding_method == MODE_COPY)) { s->vp3dsp.v_loop_filter( - plane_data + 8*x + 8*stride, + plane_data + 8 * x + 8 * stride, stride, bounding_values); } } fragment++; } - plane_data += 8*stride; + plane_data += 8 * stride; } } @@ -1364,7 +1378,7 @@ static inline int vp3_dequant(Vp3DecodeContext *s, Vp3Fragment *frag, int token = *s->dct_tokens[plane][i]; switch (token & 3) { case 0: // EOB - if (--token < 4) // 0-3 are token types, so the EOB run must now be 0 + if (--token < 4) // 0-3 are token types so the EOB run must now be 0 s->dct_tokens[plane][i]++; else *s->dct_tokens[plane][i] = token & ~3; @@ -1403,30 +1417,32 @@ static void vp3_draw_horiz_band(Vp3DecodeContext *s, int y) int h, cy, i; int offset[AV_NUM_DATA_POINTERS]; - if (HAVE_THREADS && s->avctx->active_thread_type&FF_THREAD_FRAME) { - int y_flipped = s->flipped_image ? s->avctx->height-y : y; + if (HAVE_THREADS && s->avctx->active_thread_type & FF_THREAD_FRAME) { + int y_flipped = s->flipped_image ? s->avctx->height - y : y; - // At the end of the frame, report INT_MAX instead of the height of the frame. - // This makes the other threads' ff_thread_await_progress() calls cheaper, because - // they don't have to clip their values. - ff_thread_report_progress(&s->current_frame, y_flipped==s->avctx->height ? INT_MAX : y_flipped-1, 0); + /* At the end of the frame, report INT_MAX instead of the height of + * the frame. This makes the other threads' ff_thread_await_progress() + * calls cheaper, because they don't have to clip their values. */ + ff_thread_report_progress(&s->current_frame, + y_flipped == s->avctx->height ? INT_MAX + : y_flipped - 1, + 0); } - if(s->avctx->draw_horiz_band==NULL) + if (s->avctx->draw_horiz_band == NULL) return; - h= y - s->last_slice_end; - s->last_slice_end= y; + h = y - s->last_slice_end; + s->last_slice_end = y; y -= h; - if (!s->flipped_image) { + if (!s->flipped_image) y = s->avctx->height - y - h; - } - cy = y >> s->chroma_y_shift; - offset[0] = s->current_frame.f->linesize[0]*y; - offset[1] = s->current_frame.f->linesize[1]*cy; - offset[2] = s->current_frame.f->linesize[2]*cy; + cy = y >> s->chroma_y_shift; + offset[0] = s->current_frame.f->linesize[0] * y; + offset[1] = s->current_frame.f->linesize[1] * cy; + offset[2] = s->current_frame.f->linesize[2] * cy; for (i = 3; i < AV_NUM_DATA_POINTERS; i++) offset[i] = 0; @@ -1438,11 +1454,12 @@ static void vp3_draw_horiz_band(Vp3DecodeContext *s, int y) * Wait for the reference frame of the current fragment. * The progress value is in luma pixel rows. */ -static void await_reference_row(Vp3DecodeContext *s, Vp3Fragment *fragment, int motion_y, int y) +static void await_reference_row(Vp3DecodeContext *s, Vp3Fragment *fragment, + int motion_y, int y) { ThreadFrame *ref_frame; int ref_row; - int border = motion_y&1; + int border = motion_y & 1; if (fragment->coding_method == MODE_USING_GOLDEN || fragment->coding_method == MODE_GOLDEN_MV) @@ -1450,7 +1467,7 @@ static void await_reference_row(Vp3DecodeContext *s, Vp3Fragment *fragment, int else ref_frame = &s->last_frame; - ref_row = y + (motion_y>>1); + ref_row = y + (motion_y >> 1); ref_row = FFMAX(FFABS(ref_row), ref_row + 8 + border); ff_thread_await_progress(ref_frame, ref_row, 0); @@ -1473,38 +1490,43 @@ static void render_slice(Vp3DecodeContext *s, int slice) return; for (plane = 0; plane < 3; plane++) { - uint8_t *output_plane = s->current_frame.f->data [plane] + s->data_offset[plane]; - uint8_t * last_plane = s-> last_frame.f->data [plane] + s->data_offset[plane]; - uint8_t *golden_plane = s-> golden_frame.f->data [plane] + s->data_offset[plane]; - ptrdiff_t stride = s->current_frame.f->linesize[plane]; - int plane_width = s->width >> (plane && s->chroma_x_shift); - int plane_height = s->height >> (plane && s->chroma_y_shift); - int8_t (*motion_val)[2] = s->motion_val[!!plane]; + uint8_t *output_plane = s->current_frame.f->data[plane] + + s->data_offset[plane]; + uint8_t *last_plane = s->last_frame.f->data[plane] + + s->data_offset[plane]; + uint8_t *golden_plane = s->golden_frame.f->data[plane] + + s->data_offset[plane]; + ptrdiff_t stride = s->current_frame.f->linesize[plane]; + int plane_width = s->width >> (plane && s->chroma_x_shift); + int plane_height = s->height >> (plane && s->chroma_y_shift); + int8_t(*motion_val)[2] = s->motion_val[!!plane]; - int sb_x, sb_y = slice << (!plane && s->chroma_y_shift); - int slice_height = sb_y + 1 + (!plane && s->chroma_y_shift); - int slice_width = plane ? s->c_superblock_width : s->y_superblock_width; + int sb_x, sb_y = slice << (!plane && s->chroma_y_shift); + int slice_height = sb_y + 1 + (!plane && s->chroma_y_shift); + int slice_width = plane ? s->c_superblock_width + : s->y_superblock_width; - int fragment_width = s->fragment_width[!!plane]; - int fragment_height = s->fragment_height[!!plane]; - int fragment_start = s->fragment_start[plane]; - int do_await = !plane && HAVE_THREADS && (s->avctx->active_thread_type&FF_THREAD_FRAME); + int fragment_width = s->fragment_width[!!plane]; + int fragment_height = s->fragment_height[!!plane]; + int fragment_start = s->fragment_start[plane]; - if (!s->flipped_image) stride = -stride; + int do_await = !plane && HAVE_THREADS && + (s->avctx->active_thread_type & FF_THREAD_FRAME); + + if (!s->flipped_image) + stride = -stride; if (CONFIG_GRAY && plane && (s->avctx->flags & CODEC_FLAG_GRAY)) continue; /* for each superblock row in the slice (both of them)... */ for (; sb_y < slice_height; sb_y++) { - /* for each superblock in a row... */ for (sb_x = 0; sb_x < slice_width; sb_x++) { - /* for each block in a superblock... */ for (j = 0; j < 16; j++) { - x = 4*sb_x + hilbert_offset[j][0]; - y = 4*sb_y + hilbert_offset[j][1]; - fragment = y*fragment_width + x; + x = 4 * sb_x + hilbert_offset[j][0]; + y = 4 * sb_y + hilbert_offset[j][1]; + fragment = y * fragment_width + x; i = fragment_start + fragment; @@ -1512,119 +1534,126 @@ static void render_slice(Vp3DecodeContext *s, int slice) if (x >= fragment_width || y >= fragment_height) continue; - first_pixel = 8*y*stride + 8*x; + first_pixel = 8 * y * stride + 8 * x; - if (do_await && s->all_fragments[i].coding_method != MODE_INTRA) - await_reference_row(s, &s->all_fragments[i], motion_val[fragment][1], (16*y) >> s->chroma_y_shift); + if (do_await && + s->all_fragments[i].coding_method != MODE_INTRA) + await_reference_row(s, &s->all_fragments[i], + motion_val[fragment][1], + (16 * y) >> s->chroma_y_shift); - /* transform if this block was coded */ - if (s->all_fragments[i].coding_method != MODE_COPY) { - if ((s->all_fragments[i].coding_method == MODE_USING_GOLDEN) || - (s->all_fragments[i].coding_method == MODE_GOLDEN_MV)) - motion_source= golden_plane; - else - motion_source= last_plane; + /* transform if this block was coded */ + if (s->all_fragments[i].coding_method != MODE_COPY) { + if ((s->all_fragments[i].coding_method == MODE_USING_GOLDEN) || + (s->all_fragments[i].coding_method == MODE_GOLDEN_MV)) + motion_source = golden_plane; + else + motion_source = last_plane; - motion_source += first_pixel; - motion_halfpel_index = 0; + motion_source += first_pixel; + motion_halfpel_index = 0; - /* sort out the motion vector if this fragment is coded - * using a motion vector method */ - if ((s->all_fragments[i].coding_method > MODE_INTRA) && - (s->all_fragments[i].coding_method != MODE_USING_GOLDEN)) { - int src_x, src_y; - motion_x = motion_val[fragment][0]; - motion_y = motion_val[fragment][1]; + /* sort out the motion vector if this fragment is coded + * using a motion vector method */ + if ((s->all_fragments[i].coding_method > MODE_INTRA) && + (s->all_fragments[i].coding_method != MODE_USING_GOLDEN)) { + int src_x, src_y; + motion_x = motion_val[fragment][0]; + motion_y = motion_val[fragment][1]; - src_x= (motion_x>>1) + 8*x; - src_y= (motion_y>>1) + 8*y; + src_x = (motion_x >> 1) + 8 * x; + src_y = (motion_y >> 1) + 8 * y; - motion_halfpel_index = motion_x & 0x01; - motion_source += (motion_x >> 1); + motion_halfpel_index = motion_x & 0x01; + motion_source += (motion_x >> 1); - motion_halfpel_index |= (motion_y & 0x01) << 1; - motion_source += ((motion_y >> 1) * stride); + motion_halfpel_index |= (motion_y & 0x01) << 1; + motion_source += ((motion_y >> 1) * stride); - if(src_x<0 || src_y<0 || src_x + 9 >= plane_width || src_y + 9 >= plane_height){ - uint8_t *temp= s->edge_emu_buffer; - if(stride<0) temp -= 8*stride; + if (src_x < 0 || src_y < 0 || + src_x + 9 >= plane_width || + src_y + 9 >= plane_height) { + uint8_t *temp = s->edge_emu_buffer; + if (stride < 0) + temp -= 8 * stride; - s->vdsp.emulated_edge_mc(temp, motion_source, - stride, stride, - 9, 9, src_x, src_y, - plane_width, - plane_height); - motion_source= temp; + s->vdsp.emulated_edge_mc(temp, motion_source, + stride, stride, + 9, 9, src_x, src_y, + plane_width, + plane_height); + motion_source = temp; + } } - } - - /* first, take care of copying a block from either the - * previous or the golden frame */ - if (s->all_fragments[i].coding_method != MODE_INTRA) { - /* Note, it is possible to implement all MC cases with - put_no_rnd_pixels_l2 which would look more like the - VP3 source but this would be slower as - put_no_rnd_pixels_tab is better optimzed */ - if(motion_halfpel_index != 3){ - s->hdsp.put_no_rnd_pixels_tab[1][motion_halfpel_index]( - output_plane + first_pixel, - motion_source, stride, 8); - }else{ - int d= (motion_x ^ motion_y)>>31; // d is 0 if motion_x and _y have the same sign, else -1 - s->vp3dsp.put_no_rnd_pixels_l2( - output_plane + first_pixel, - motion_source - d, - motion_source + stride + 1 + d, - stride, 8); + /* first, take care of copying a block from either the + * previous or the golden frame */ + if (s->all_fragments[i].coding_method != MODE_INTRA) { + /* Note, it is possible to implement all MC cases + * with put_no_rnd_pixels_l2 which would look more + * like the VP3 source but this would be slower as + * put_no_rnd_pixels_tab is better optimzed */ + if (motion_halfpel_index != 3) { + s->hdsp.put_no_rnd_pixels_tab[1][motion_halfpel_index]( + output_plane + first_pixel, + motion_source, stride, 8); + } else { + /* d is 0 if motion_x and _y have the same sign, + * else -1 */ + int d = (motion_x ^ motion_y) >> 31; + s->vp3dsp.put_no_rnd_pixels_l2(output_plane + first_pixel, + motion_source - d, + motion_source + stride + 1 + d, + stride, 8); + } } - } - /* invert DCT and place (or add) in final output */ + /* invert DCT and place (or add) in final output */ - if (s->all_fragments[i].coding_method == MODE_INTRA) { - vp3_dequant(s, s->all_fragments + i, plane, 0, block); - s->vp3dsp.idct_put( - output_plane + first_pixel, - stride, - block); - } else { - if (vp3_dequant(s, s->all_fragments + i, plane, 1, block)) { - s->vp3dsp.idct_add( - output_plane + first_pixel, - stride, - block); + if (s->all_fragments[i].coding_method == MODE_INTRA) { + vp3_dequant(s, s->all_fragments + i, + plane, 0, block); + s->vp3dsp.idct_put(output_plane + first_pixel, + stride, + block); } else { - s->vp3dsp.idct_dc_add(output_plane + first_pixel, stride, block); + if (vp3_dequant(s, s->all_fragments + i, + plane, 1, block)) { + s->vp3dsp.idct_add(output_plane + first_pixel, + stride, + block); + } else { + s->vp3dsp.idct_dc_add(output_plane + first_pixel, + stride, block); + } } + } else { + /* copy directly from the previous frame */ + s->hdsp.put_pixels_tab[1][0]( + output_plane + first_pixel, + last_plane + first_pixel, + stride, 8); } - } else { - - /* copy directly from the previous frame */ - s->hdsp.put_pixels_tab[1][0]( - output_plane + first_pixel, - last_plane + first_pixel, - stride, 8); - - } } } // Filter up to the last row in the superblock row if (!s->skip_loop_filter) - apply_loop_filter(s, plane, 4*sb_y - !!sb_y, FFMIN(4*sb_y+3, fragment_height-1)); + apply_loop_filter(s, plane, 4 * sb_y - !!sb_y, + FFMIN(4 * sb_y + 3, fragment_height - 1)); } } - /* this looks like a good place for slice dispatch... */ - /* algorithm: - * if (slice == s->macroblock_height - 1) - * dispatch (both last slice & 2nd-to-last slice); - * else if (slice > 0) - * dispatch (slice - 1); - */ + /* this looks like a good place for slice dispatch... */ + /* algorithm: + * if (slice == s->macroblock_height - 1) + * dispatch (both last slice & 2nd-to-last slice); + * else if (slice > 0) + * dispatch (slice - 1); + */ - vp3_draw_horiz_band(s, FFMIN((32 << s->chroma_y_shift) * (slice + 1) -16, s->height-16)); + vp3_draw_horiz_band(s, FFMIN((32 << s->chroma_y_shift) * (slice + 1) - 16, + s->height - 16)); } /// Allocate tables for per-frame data in Vp3DecodeContext @@ -1633,23 +1662,29 @@ static av_cold int allocate_tables(AVCodecContext *avctx) Vp3DecodeContext *s = avctx->priv_data; int y_fragment_count, c_fragment_count; + free_tables(avctx); + y_fragment_count = s->fragment_width[0] * s->fragment_height[0]; c_fragment_count = s->fragment_width[1] * s->fragment_height[1]; s->superblock_coding = av_mallocz(s->superblock_count); - s->all_fragments = av_mallocz(s->fragment_count * sizeof(Vp3Fragment)); - s->coded_fragment_list[0] = av_mallocz(s->fragment_count * sizeof(int)); - s->dct_tokens_base = av_mallocz(64*s->fragment_count * sizeof(*s->dct_tokens_base)); - s->motion_val[0] = av_mallocz(y_fragment_count * sizeof(*s->motion_val[0])); - s->motion_val[1] = av_mallocz(c_fragment_count * sizeof(*s->motion_val[1])); + s->all_fragments = av_mallocz_array(s->fragment_count, sizeof(Vp3Fragment)); + + s->coded_fragment_list[0] = av_mallocz_array(s->fragment_count, sizeof(int)); + + s->dct_tokens_base = av_mallocz_array(s->fragment_count, + 64 * sizeof(*s->dct_tokens_base)); + s->motion_val[0] = av_mallocz_array(y_fragment_count, sizeof(*s->motion_val[0])); + s->motion_val[1] = av_mallocz_array(c_fragment_count, sizeof(*s->motion_val[1])); /* work out the block mapping tables */ - s->superblock_fragments = av_mallocz(s->superblock_count * 16 * sizeof(int)); - s->macroblock_coding = av_mallocz(s->macroblock_count + 1); + s->superblock_fragments = av_mallocz_array(s->superblock_count, 16 * sizeof(int)); + s->macroblock_coding = av_mallocz(s->macroblock_count + 1); - if (!s->superblock_coding || !s->all_fragments || !s->dct_tokens_base || - !s->coded_fragment_list[0] || !s->superblock_fragments || !s->macroblock_coding || - !s->motion_val[0] || !s->motion_val[1]) { + if (!s->superblock_coding || !s->all_fragments || + !s->dct_tokens_base || !s->coded_fragment_list[0] || + !s->superblock_fragments || !s->macroblock_coding || + !s->motion_val[0] || !s->motion_val[1]) { vp3_decode_end(avctx); return -1; } @@ -1689,13 +1724,13 @@ static av_cold int vp3_decode_init(AVCodecContext *avctx) avctx->internal->allocate_progress = 1; - if (avctx->codec_tag == MKTAG('V','P','3','0')) + if (avctx->codec_tag == MKTAG('V', 'P', '3', '0')) s->version = 0; else s->version = 1; - s->avctx = avctx; - s->width = FFALIGN(avctx->width, 16); + s->avctx = avctx; + s->width = FFALIGN(avctx->width, 16); s->height = FFALIGN(avctx->height, 16); if (avctx->codec_id != AV_CODEC_ID_THEORA) avctx->pix_fmt = AV_PIX_FMT_YUV420P; @@ -1705,7 +1740,7 @@ static av_cold int vp3_decode_init(AVCodecContext *avctx) ff_vp3dsp_init(&s->vp3dsp, avctx->flags); for (i = 0; i < 64; i++) { -#define TRANSPOSE(x) (x >> 3) | ((x & 7) << 3) +#define TRANSPOSE(x) (((x) >> 3) | (((x) & 7) << 3)) s->idct_permutation[i] = TRANSPOSE(i); s->idct_scantable[i] = TRANSPOSE(ff_zigzag_direct[i]); #undef TRANSPOSE @@ -1718,135 +1753,132 @@ static av_cold int vp3_decode_init(AVCodecContext *avctx) avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift); - s->y_superblock_width = (s->width + 31) / 32; + s->y_superblock_width = (s->width + 31) / 32; s->y_superblock_height = (s->height + 31) / 32; - s->y_superblock_count = s->y_superblock_width * s->y_superblock_height; + s->y_superblock_count = s->y_superblock_width * s->y_superblock_height; /* work out the dimensions for the C planes */ - c_width = s->width >> s->chroma_x_shift; - c_height = s->height >> s->chroma_y_shift; - s->c_superblock_width = (c_width + 31) / 32; + c_width = s->width >> s->chroma_x_shift; + c_height = s->height >> s->chroma_y_shift; + s->c_superblock_width = (c_width + 31) / 32; s->c_superblock_height = (c_height + 31) / 32; - s->c_superblock_count = s->c_superblock_width * s->c_superblock_height; + s->c_superblock_count = s->c_superblock_width * s->c_superblock_height; - s->superblock_count = s->y_superblock_count + (s->c_superblock_count * 2); + s->superblock_count = s->y_superblock_count + (s->c_superblock_count * 2); s->u_superblock_start = s->y_superblock_count; s->v_superblock_start = s->u_superblock_start + s->c_superblock_count; - s->macroblock_width = (s->width + 15) / 16; + s->macroblock_width = (s->width + 15) / 16; s->macroblock_height = (s->height + 15) / 16; - s->macroblock_count = s->macroblock_width * s->macroblock_height; + s->macroblock_count = s->macroblock_width * s->macroblock_height; - s->fragment_width[0] = s->width / FRAGMENT_PIXELS; + s->fragment_width[0] = s->width / FRAGMENT_PIXELS; s->fragment_height[0] = s->height / FRAGMENT_PIXELS; - s->fragment_width[1] = s->fragment_width[0] >> s->chroma_x_shift; + s->fragment_width[1] = s->fragment_width[0] >> s->chroma_x_shift; s->fragment_height[1] = s->fragment_height[0] >> s->chroma_y_shift; /* fragment count covers all 8x8 blocks for all 3 planes */ y_fragment_count = s->fragment_width[0] * s->fragment_height[0]; c_fragment_count = s->fragment_width[1] * s->fragment_height[1]; - s->fragment_count = y_fragment_count + 2*c_fragment_count; + s->fragment_count = y_fragment_count + 2 * c_fragment_count; s->fragment_start[1] = y_fragment_count; s->fragment_start[2] = y_fragment_count + c_fragment_count; - if (!s->theora_tables) - { + if (!s->theora_tables) { for (i = 0; i < 64; i++) { s->coded_dc_scale_factor[i] = vp31_dc_scale_factor[i]; s->coded_ac_scale_factor[i] = vp31_ac_scale_factor[i]; - s->base_matrix[0][i] = vp31_intra_y_dequant[i]; - s->base_matrix[1][i] = vp31_intra_c_dequant[i]; - s->base_matrix[2][i] = vp31_inter_dequant[i]; - s->filter_limit_values[i] = vp31_filter_limit_values[i]; + s->base_matrix[0][i] = vp31_intra_y_dequant[i]; + s->base_matrix[1][i] = vp31_intra_c_dequant[i]; + s->base_matrix[2][i] = vp31_inter_dequant[i]; + s->filter_limit_values[i] = vp31_filter_limit_values[i]; } - for(inter=0; inter<2; inter++){ - for(plane=0; plane<3; plane++){ - s->qr_count[inter][plane]= 1; - s->qr_size [inter][plane][0]= 63; - s->qr_base [inter][plane][0]= - s->qr_base [inter][plane][1]= 2*inter + (!!plane)*!inter; + for (inter = 0; inter < 2; inter++) { + for (plane = 0; plane < 3; plane++) { + s->qr_count[inter][plane] = 1; + s->qr_size[inter][plane][0] = 63; + s->qr_base[inter][plane][0] = + s->qr_base[inter][plane][1] = 2 * inter + (!!plane) * !inter; } } /* init VLC tables */ for (i = 0; i < 16; i++) { - /* DC histograms */ init_vlc(&s->dc_vlc[i], 11, 32, - &dc_bias[i][0][1], 4, 2, - &dc_bias[i][0][0], 4, 2, 0); + &dc_bias[i][0][1], 4, 2, + &dc_bias[i][0][0], 4, 2, 0); /* group 1 AC histograms */ init_vlc(&s->ac_vlc_1[i], 11, 32, - &ac_bias_0[i][0][1], 4, 2, - &ac_bias_0[i][0][0], 4, 2, 0); + &ac_bias_0[i][0][1], 4, 2, + &ac_bias_0[i][0][0], 4, 2, 0); /* group 2 AC histograms */ init_vlc(&s->ac_vlc_2[i], 11, 32, - &ac_bias_1[i][0][1], 4, 2, - &ac_bias_1[i][0][0], 4, 2, 0); + &ac_bias_1[i][0][1], 4, 2, + &ac_bias_1[i][0][0], 4, 2, 0); /* group 3 AC histograms */ init_vlc(&s->ac_vlc_3[i], 11, 32, - &ac_bias_2[i][0][1], 4, 2, - &ac_bias_2[i][0][0], 4, 2, 0); + &ac_bias_2[i][0][1], 4, 2, + &ac_bias_2[i][0][0], 4, 2, 0); /* group 4 AC histograms */ init_vlc(&s->ac_vlc_4[i], 11, 32, - &ac_bias_3[i][0][1], 4, 2, - &ac_bias_3[i][0][0], 4, 2, 0); + &ac_bias_3[i][0][1], 4, 2, + &ac_bias_3[i][0][0], 4, 2, 0); } } else { - for (i = 0; i < 16; i++) { /* DC histograms */ if (init_vlc(&s->dc_vlc[i], 11, 32, - &s->huffman_table[i][0][1], 8, 4, - &s->huffman_table[i][0][0], 8, 4, 0) < 0) + &s->huffman_table[i][0][1], 8, 4, + &s->huffman_table[i][0][0], 8, 4, 0) < 0) goto vlc_fail; /* group 1 AC histograms */ if (init_vlc(&s->ac_vlc_1[i], 11, 32, - &s->huffman_table[i+16][0][1], 8, 4, - &s->huffman_table[i+16][0][0], 8, 4, 0) < 0) + &s->huffman_table[i + 16][0][1], 8, 4, + &s->huffman_table[i + 16][0][0], 8, 4, 0) < 0) goto vlc_fail; /* group 2 AC histograms */ if (init_vlc(&s->ac_vlc_2[i], 11, 32, - &s->huffman_table[i+16*2][0][1], 8, 4, - &s->huffman_table[i+16*2][0][0], 8, 4, 0) < 0) + &s->huffman_table[i + 16 * 2][0][1], 8, 4, + &s->huffman_table[i + 16 * 2][0][0], 8, 4, 0) < 0) goto vlc_fail; /* group 3 AC histograms */ if (init_vlc(&s->ac_vlc_3[i], 11, 32, - &s->huffman_table[i+16*3][0][1], 8, 4, - &s->huffman_table[i+16*3][0][0], 8, 4, 0) < 0) + &s->huffman_table[i + 16 * 3][0][1], 8, 4, + &s->huffman_table[i + 16 * 3][0][0], 8, 4, 0) < 0) goto vlc_fail; /* group 4 AC histograms */ if (init_vlc(&s->ac_vlc_4[i], 11, 32, - &s->huffman_table[i+16*4][0][1], 8, 4, - &s->huffman_table[i+16*4][0][0], 8, 4, 0) < 0) + &s->huffman_table[i + 16 * 4][0][1], 8, 4, + &s->huffman_table[i + 16 * 4][0][0], 8, 4, 0) < 0) goto vlc_fail; } } init_vlc(&s->superblock_run_length_vlc, 6, 34, - &superblock_run_length_vlc_table[0][1], 4, 2, - &superblock_run_length_vlc_table[0][0], 4, 2, 0); + &superblock_run_length_vlc_table[0][1], 4, 2, + &superblock_run_length_vlc_table[0][0], 4, 2, 0); init_vlc(&s->fragment_run_length_vlc, 5, 30, - &fragment_run_length_vlc_table[0][1], 4, 2, - &fragment_run_length_vlc_table[0][0], 4, 2, 0); + &fragment_run_length_vlc_table[0][1], 4, 2, + &fragment_run_length_vlc_table[0][0], 4, 2, 0); init_vlc(&s->mode_code_vlc, 3, 8, - &mode_code_vlc_table[0][1], 2, 1, - &mode_code_vlc_table[0][0], 2, 1, 0); + &mode_code_vlc_table[0][1], 2, 1, + &mode_code_vlc_table[0][0], 2, 1, 0); init_vlc(&s->motion_vector_vlc, 6, 63, - &motion_vector_vlc_table[0][1], 2, 1, - &motion_vector_vlc_table[0][0], 2, 1, 0); + &motion_vector_vlc_table[0][1], 2, 1, + &motion_vector_vlc_table[0][0], 2, 1, 0); return allocate_tables(avctx); @@ -1861,7 +1893,6 @@ static int update_frames(AVCodecContext *avctx) Vp3DecodeContext *s = avctx->priv_data; int ret = 0; - /* shuffle frames (last = current) */ ff_thread_release_buffer(avctx, &s->last_frame); ret = ff_thread_ref_frame(&s->last_frame, &s->current_frame); @@ -1901,11 +1932,12 @@ static int vp3_update_thread_context(AVCodecContext *dst, const AVCodecContext * Vp3DecodeContext *s = dst->priv_data, *s1 = src->priv_data; int qps_changed = 0, i, err; -#define copy_fields(to, from, start_field, end_field) memcpy(&to->start_field, &from->start_field, (char*)&to->end_field - (char*)&to->start_field) +#define copy_fields(to, from, start_field, end_field) \ + memcpy(&to->start_field, &from->start_field, \ + (char *) &to->end_field - (char *) &to->start_field) - if (!s1->current_frame.f->data[0] - ||s->width != s1->width - ||s->height!= s1->height) { + if (!s1->current_frame.f->data[0] || + s->width != s1->width || s->height != s1->height) { if (s != s1) ref_frames(s, s1); return -1; @@ -1921,8 +1953,10 @@ static int vp3_update_thread_context(AVCodecContext *dst, const AVCodecContext * return err; y_fragment_count = s->fragment_width[0] * s->fragment_height[0]; c_fragment_count = s->fragment_width[1] * s->fragment_height[1]; - memcpy(s->motion_val[0], s1->motion_val[0], y_fragment_count * sizeof(*s->motion_val[0])); - memcpy(s->motion_val[1], s1->motion_val[1], c_fragment_count * sizeof(*s->motion_val[1])); + memcpy(s->motion_val[0], s1->motion_val[0], + y_fragment_count * sizeof(*s->motion_val[0])); + memcpy(s->motion_val[1], s1->motion_val[1], + c_fragment_count * sizeof(*s->motion_val[1])); } // copy previous frame data @@ -1940,7 +1974,8 @@ static int vp3_update_thread_context(AVCodecContext *dst, const AVCodecContext * } if (s->qps[0] != s1->qps[0]) - memcpy(&s->bounding_values_array, &s1->bounding_values_array, sizeof(s->bounding_values_array)); + memcpy(&s->bounding_values_array, &s1->bounding_values_array, + sizeof(s->bounding_values_array)); if (qps_changed) copy_fields(s, s1, qps, superblock_count); @@ -1954,8 +1989,8 @@ static int vp3_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; Vp3DecodeContext *s = avctx->priv_data; GetBitContext gb; int i, ret; @@ -1963,8 +1998,7 @@ static int vp3_decode_frame(AVCodecContext *avctx, init_get_bits(&gb, buf, buf_size * 8); #if CONFIG_THEORA_DECODER - if (s->theora && get_bits1(&gb)) - { + if (s->theora && get_bits1(&gb)) { int type = get_bits(&gb, 7); skip_bits_long(&gb, 6*8); /* "theora" */ @@ -1990,7 +2024,8 @@ static int vp3_decode_frame(AVCodecContext *avctx, return ret; } - av_log(avctx, AV_LOG_ERROR, "Header packet passed to frame decoder, skipping\n"); + av_log(avctx, AV_LOG_ERROR, + "Header packet passed to frame decoder, skipping\n"); return -1; } #endif @@ -2005,19 +2040,20 @@ static int vp3_decode_frame(AVCodecContext *avctx, for (i = 0; i < 3; i++) s->last_qps[i] = s->qps[i]; - s->nqps=0; - do{ - s->qps[s->nqps++]= get_bits(&gb, 6); - } while(s->theora >= 0x030200 && s->nqps<3 && get_bits1(&gb)); + s->nqps = 0; + do { + s->qps[s->nqps++] = get_bits(&gb, 6); + } while (s->theora >= 0x030200 && s->nqps < 3 && get_bits1(&gb)); for (i = s->nqps; i < 3; i++) s->qps[i] = -1; if (s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_INFO, " VP3 %sframe #%d: Q index = %d\n", - s->keyframe?"key":"", avctx->frame_number+1, s->qps[0]); + s->keyframe ? "key" : "", avctx->frame_number + 1, s->qps[0]); s->skip_loop_filter = !s->filter_limit_values[s->qps[0]] || - avctx->skip_loop_filter >= (s->keyframe ? AVDISCARD_ALL : AVDISCARD_NONKEY); + avctx->skip_loop_filter >= (s->keyframe ? AVDISCARD_ALL + : AVDISCARD_NONKEY); if (s->qps[0] != s->last_qps[0]) init_loop_filter(s); @@ -2031,41 +2067,44 @@ static int vp3_decode_frame(AVCodecContext *avctx, if (avctx->skip_frame >= AVDISCARD_NONKEY && !s->keyframe) return buf_size; - s->current_frame.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + s->current_frame.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I + : AV_PICTURE_TYPE_P; s->current_frame.f->key_frame = s->keyframe; if (ff_thread_get_buffer(avctx, &s->current_frame, AV_GET_BUFFER_FLAG_REF) < 0) goto error; if (!s->edge_emu_buffer) - s->edge_emu_buffer = av_malloc(9*FFABS(s->current_frame.f->linesize[0])); + s->edge_emu_buffer = av_malloc(9 * FFABS(s->current_frame.f->linesize[0])); if (s->keyframe) { - if (!s->theora) - { + if (!s->theora) { skip_bits(&gb, 4); /* width code */ skip_bits(&gb, 4); /* height code */ - if (s->version) - { + if (s->version) { s->version = get_bits(&gb, 5); if (avctx->frame_number == 0) - av_log(s->avctx, AV_LOG_DEBUG, "VP version: %d\n", s->version); + av_log(s->avctx, AV_LOG_DEBUG, + "VP version: %d\n", s->version); } } - if (s->version || s->theora) - { - if (get_bits1(&gb)) - av_log(s->avctx, AV_LOG_ERROR, "Warning, unsupported keyframe coding type?!\n"); + if (s->version || s->theora) { + if (get_bits1(&gb)) + av_log(s->avctx, AV_LOG_ERROR, + "Warning, unsupported keyframe coding type?!\n"); skip_bits(&gb, 2); /* reserved? */ } } else { if (!s->golden_frame.f->data[0]) { - av_log(s->avctx, AV_LOG_WARNING, "vp3: first frame not a keyframe\n"); + av_log(s->avctx, AV_LOG_WARNING, + "vp3: first frame not a keyframe\n"); s->golden_frame.f->pict_type = AV_PICTURE_TYPE_I; - if (ff_thread_get_buffer(avctx, &s->golden_frame, AV_GET_BUFFER_FLAG_REF) < 0) + if (ff_thread_get_buffer(avctx, &s->golden_frame, + AV_GET_BUFFER_FLAG_REF) < 0) goto error; ff_thread_release_buffer(avctx, &s->last_frame); - if ((ret = ff_thread_ref_frame(&s->last_frame, &s->golden_frame)) < 0) + if ((ret = ff_thread_ref_frame(&s->last_frame, + &s->golden_frame)) < 0) goto error; ff_thread_report_progress(&s->last_frame, INT_MAX, 0); } @@ -2074,23 +2113,23 @@ static int vp3_decode_frame(AVCodecContext *avctx, memset(s->all_fragments, 0, s->fragment_count * sizeof(Vp3Fragment)); ff_thread_finish_setup(avctx); - if (unpack_superblocks(s, &gb)){ + if (unpack_superblocks(s, &gb)) { av_log(s->avctx, AV_LOG_ERROR, "error in unpack_superblocks\n"); goto error; } - if (unpack_modes(s, &gb)){ + if (unpack_modes(s, &gb)) { av_log(s->avctx, AV_LOG_ERROR, "error in unpack_modes\n"); goto error; } - if (unpack_vectors(s, &gb)){ + if (unpack_vectors(s, &gb)) { av_log(s->avctx, AV_LOG_ERROR, "error in unpack_vectors\n"); goto error; } - if (unpack_block_qpis(s, &gb)){ + if (unpack_block_qpis(s, &gb)) { av_log(s->avctx, AV_LOG_ERROR, "error in unpack_block_qpis\n"); goto error; } - if (unpack_dct_coeffs(s, &gb)){ + if (unpack_dct_coeffs(s, &gb)) { av_log(s->avctx, AV_LOG_ERROR, "error in unpack_dct_coeffs\n"); goto error; } @@ -2100,7 +2139,7 @@ static int vp3_decode_frame(AVCodecContext *avctx, if (s->flipped_image) s->data_offset[i] = 0; else - s->data_offset[i] = (height-1) * s->current_frame.f->linesize[i]; + s->data_offset[i] = (height - 1) * s->current_frame.f->linesize[i]; } s->last_slice_end = 0; @@ -2109,8 +2148,8 @@ static int vp3_decode_frame(AVCodecContext *avctx, // filter the last row for (i = 0; i < 3; i++) { - int row = (s->height >> (3+(i && s->chroma_y_shift))) - 1; - apply_loop_filter(s, i, row, row+1); + 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); @@ -2118,7 +2157,7 @@ static int vp3_decode_frame(AVCodecContext *avctx, return ret; *got_frame = 1; - if (!HAVE_THREADS || !(s->avctx->active_thread_type&FF_THREAD_FRAME)) { + if (!HAVE_THREADS || !(s->avctx->active_thread_type & FF_THREAD_FRAME)) { ret = update_frames(avctx); if (ret < 0) return ret; @@ -2129,7 +2168,7 @@ static int vp3_decode_frame(AVCodecContext *avctx, error: ff_thread_report_progress(&s->current_frame, INT_MAX, 0); - if (!HAVE_THREADS || !(s->avctx->active_thread_type&FF_THREAD_FRAME)) + if (!HAVE_THREADS || !(s->avctx->active_thread_type & FF_THREAD_FRAME)) av_frame_unref(s->current_frame.f); return -1; @@ -2151,9 +2190,8 @@ static int read_huffman_tree(AVCodecContext *avctx, GetBitContext *gb) s->huffman_table[s->hti][token][0] = s->hbits; s->huffman_table[s->hti][token][1] = s->huff_code_size; s->entries++; - } - else { - if (s->huff_code_size >= 32) {/* overflow */ + } else { + if (s->huff_code_size >= 32) { /* overflow */ av_log(avctx, AV_LOG_ERROR, "huffman tree overflow\n"); return -1; } @@ -2203,16 +2241,18 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) s->theora = get_bits_long(gb, 24); av_log(avctx, AV_LOG_DEBUG, "Theora bitstream version %X\n", s->theora); - /* 3.2.0 aka alpha3 has the same frame orientation as original vp3 */ - /* but previous versions have the image flipped relative to vp3 */ - if (s->theora < 0x030200) - { + /* 3.2.0 aka alpha3 has the same frame orientation as original vp3 + * but previous versions have the image flipped relative to vp3 */ + if (s->theora < 0x030200) { s->flipped_image = 1; - av_log(avctx, AV_LOG_DEBUG, "Old (width = get_bits(gb, 16) << 4; - visible_height = s->height = get_bits(gb, 16) << 4; + visible_width = + s->width = get_bits(gb, 16) << 4; + visible_height = + s->height = get_bits(gb, 16) << 4; if (s->theora >= 0x030200) { visible_width = get_bits_long(gb, 24); @@ -2230,7 +2270,7 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) return AVERROR_INVALIDDATA; } av_reduce(&avctx->time_base.num, &avctx->time_base.den, - fps.den, fps.num, 1<<30); + fps.den, fps.num, 1 << 30); } aspect.num = get_bits_long(gb, 24); @@ -2238,7 +2278,8 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) if (aspect.num && aspect.den) { av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den, - aspect.num, aspect.den, 1<<30); + aspect.num, aspect.den, 1 << 30); + ff_set_sar(avctx, avctx->sample_aspect_ratio); } if (s->theora < 0x030200) @@ -2248,8 +2289,7 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) skip_bits(gb, 6); /* quality hint */ - if (s->theora >= 0x030200) - { + if (s->theora >= 0x030200) { skip_bits(gb, 5); /* keyframe frequency force */ avctx->pix_fmt = theora_pix_fmts[get_bits(gb, 2)]; if (avctx->pix_fmt == AV_PIX_FMT_NONE) { @@ -2261,20 +2301,20 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) // 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)) + 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); if (ret < 0) return ret; - if (colorspace == 1) { + if (colorspace == 1) avctx->color_primaries = AVCOL_PRI_BT470M; - } else if (colorspace == 2) { + else if (colorspace == 2) avctx->color_primaries = AVCOL_PRI_BT470BG; - } + if (colorspace == 1 || colorspace == 2) { avctx->colorspace = AVCOL_SPC_BT470BG; avctx->color_trc = AVCOL_TRC_BT709; @@ -2317,48 +2357,50 @@ static int theora_decode_tables(AVCodecContext *avctx, GetBitContext *gb) else matrices = 3; - if(matrices > 384){ + if (matrices > 384) { av_log(avctx, AV_LOG_ERROR, "invalid number of base matrixes\n"); return -1; } - for(n=0; nbase_matrix[n][i]= get_bits(gb, 8); - } + s->base_matrix[n][i] = get_bits(gb, 8); for (inter = 0; inter <= 1; inter++) { for (plane = 0; plane <= 2; plane++) { - int newqr= 1; + int newqr = 1; if (inter || plane > 0) newqr = get_bits1(gb); if (!newqr) { int qtj, plj; - if(inter && get_bits1(gb)){ + if (inter && get_bits1(gb)) { qtj = 0; plj = plane; - }else{ - qtj= (3*inter + plane - 1) / 3; - plj= (plane + 2) % 3; + } else { + qtj = (3 * inter + plane - 1) / 3; + plj = (plane + 2) % 3; } - s->qr_count[inter][plane]= s->qr_count[qtj][plj]; - memcpy(s->qr_size[inter][plane], s->qr_size[qtj][plj], sizeof(s->qr_size[0][0])); - memcpy(s->qr_base[inter][plane], s->qr_base[qtj][plj], sizeof(s->qr_base[0][0])); + s->qr_count[inter][plane] = s->qr_count[qtj][plj]; + memcpy(s->qr_size[inter][plane], s->qr_size[qtj][plj], + sizeof(s->qr_size[0][0])); + memcpy(s->qr_base[inter][plane], s->qr_base[qtj][plj], + sizeof(s->qr_base[0][0])); } else { - int qri= 0; - int qi = 0; + int qri = 0; + int qi = 0; - for(;;){ - i= get_bits(gb, av_log2(matrices-1)+1); - if(i>= matrices){ - av_log(avctx, AV_LOG_ERROR, "invalid base matrix index\n"); + for (;;) { + i = get_bits(gb, av_log2(matrices - 1) + 1); + if (i >= matrices) { + av_log(avctx, AV_LOG_ERROR, + "invalid base matrix index\n"); return -1; } - s->qr_base[inter][plane][qri]= i; - if(qi >= 63) + s->qr_base[inter][plane][qri] = i; + if (qi >= 63) break; - i = get_bits(gb, av_log2(63-qi)+1) + 1; - s->qr_size[inter][plane][qri++]= i; + i = get_bits(gb, av_log2(63 - qi) + 1) + 1; + s->qr_size[inter][plane][qri++] = i; qi += i; } @@ -2366,21 +2408,21 @@ static int theora_decode_tables(AVCodecContext *avctx, GetBitContext *gb) av_log(avctx, AV_LOG_ERROR, "invalid qi %d > 63\n", qi); return -1; } - s->qr_count[inter][plane]= qri; + s->qr_count[inter][plane] = qri; } } } /* Huffman tables */ for (s->hti = 0; s->hti < 80; s->hti++) { - s->entries = 0; + s->entries = 0; s->huff_code_size = 1; if (!get_bits1(gb)) { s->hbits = 0; - if(read_huffman_tree(avctx, gb)) + if (read_huffman_tree(avctx, gb)) return -1; s->hbits = 1; - if(read_huffman_tree(avctx, gb)) + if (read_huffman_tree(avctx, gb)) return -1; } } @@ -2403,40 +2445,37 @@ static av_cold int theora_decode_init(AVCodecContext *avctx) s->theora = 1; - if (!avctx->extradata_size) - { + if (!avctx->extradata_size) { av_log(avctx, AV_LOG_ERROR, "Missing extradata!\n"); return -1; } if (avpriv_split_xiph_headers(avctx->extradata, avctx->extradata_size, - 42, header_start, header_len) < 0) { + 42, header_start, header_len) < 0) { av_log(avctx, AV_LOG_ERROR, "Corrupt extradata\n"); return -1; } - for(i=0;i<3;i++) { - if (header_len[i] <= 0) - continue; - init_get_bits(&gb, header_start[i], header_len[i] * 8); + for (i = 0; i < 3; i++) { + if (header_len[i] <= 0) + continue; + init_get_bits(&gb, header_start[i], header_len[i] * 8); - ptype = get_bits(&gb, 8); + ptype = get_bits(&gb, 8); - if (!(ptype & 0x80)) - { - av_log(avctx, AV_LOG_ERROR, "Invalid extradata!\n"); -// return -1; - } + if (!(ptype & 0x80)) { + av_log(avctx, AV_LOG_ERROR, "Invalid extradata!\n"); +// return -1; + } - // FIXME: Check for this as well. - skip_bits_long(&gb, 6*8); /* "theora" */ + // FIXME: Check for this as well. + skip_bits_long(&gb, 6 * 8); /* "theora" */ - switch(ptype) - { + switch (ptype) { case 0x80: if (theora_decode_header(avctx, &gb) < 0) return -1; - break; + break; case 0x81: // FIXME: is this needed? it breaks sometimes // theora_decode_comments(avctx, gb); @@ -2446,14 +2485,17 @@ static av_cold int theora_decode_init(AVCodecContext *avctx) return -1; break; default: - av_log(avctx, AV_LOG_ERROR, "Unknown Theora config packet: %d\n", ptype&~0x80); + av_log(avctx, AV_LOG_ERROR, + "Unknown Theora config packet: %d\n", ptype & ~0x80); + break; + } + if (ptype != 0x81 && 8 * header_len[i] != get_bits_count(&gb)) + av_log(avctx, AV_LOG_WARNING, + "%d bits left in packet %X\n", + 8 * header_len[i] - get_bits_count(&gb), ptype); + if (s->theora < 0x030200) break; } - if(ptype != 0x81 && 8*header_len[i] != get_bits_count(&gb)) - av_log(avctx, AV_LOG_WARNING, "%d bits left in packet %X\n", 8*header_len[i] - get_bits_count(&gb), ptype); - if (s->theora < 0x030200) - break; - } return vp3_decode_init(avctx); } diff --git a/libavcodec/vp3_parser.c b/libavcodec/vp3_parser.c index ce1530935..7ee046c54 100644 --- a/libavcodec/vp3_parser.c +++ b/libavcodec/vp3_parser.c @@ -21,22 +21,24 @@ #include "parser.h" static int parse(AVCodecParserContext *s, - AVCodecContext *avctx, - const uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size) + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) { - if(avctx->codec_id == AV_CODEC_ID_THEORA) - s->pict_type= (buf[0]&0x40) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; + if (avctx->codec_id == AV_CODEC_ID_THEORA) + s->pict_type = (buf[0] & 0x40) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; else - s->pict_type= (buf[0]&0x80) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; + s->pict_type = (buf[0] & 0x80) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; - *poutbuf = buf; + *poutbuf = buf; *poutbuf_size = buf_size; return buf_size; } AVCodecParser ff_vp3_parser = { - .codec_ids = { AV_CODEC_ID_THEORA, AV_CODEC_ID_VP3, AV_CODEC_ID_VP6, - AV_CODEC_ID_VP6F, AV_CODEC_ID_VP6A }, - .parser_parse = parse, + .codec_ids = { + AV_CODEC_ID_THEORA, AV_CODEC_ID_VP3, + AV_CODEC_ID_VP6, AV_CODEC_ID_VP6F, AV_CODEC_ID_VP6A + }, + .parser_parse = parse, }; diff --git a/libavcodec/vp3data.h b/libavcodec/vp3data.h index 904ec6abf..bffc5bcc6 100644 --- a/libavcodec/vp3data.h +++ b/libavcodec/vp3data.h @@ -26,175 +26,175 @@ /* these coefficients dequantize intraframe Y plane coefficients * (note: same as JPEG) */ -static const int16_t vp31_intra_y_dequant[64] = -{ 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 58, 68, 109, 103, 77, - 24, 35, 55, 64, 81, 104, 113, 92, - 49, 64, 78, 87, 103, 121, 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 +static const int16_t vp31_intra_y_dequant[64] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 58, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 }; /* these coefficients dequantize intraframe C plane coefficients * (note: same as JPEG) */ -static const int16_t vp31_intra_c_dequant[64] = -{ 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 +static const int16_t vp31_intra_c_dequant[64] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 }; /* these coefficients dequantize interframe coefficients (all planes) */ -static const int16_t vp31_inter_dequant[64] = -{ 16, 16, 16, 20, 24, 28, 32, 40, - 16, 16, 20, 24, 28, 32, 40, 48, - 16, 20, 24, 28, 32, 40, 48, 64, - 20, 24, 28, 32, 40, 48, 64, 64, - 24, 28, 32, 40, 48, 64, 64, 64, - 28, 32, 40, 48, 64, 64, 64, 96, - 32, 40, 48, 64, 64, 64, 96, 128, - 40, 48, 64, 64, 64, 96, 128, 128 +static const int16_t vp31_inter_dequant[64] = { + 16, 16, 16, 20, 24, 28, 32, 40, + 16, 16, 20, 24, 28, 32, 40, 48, + 16, 20, 24, 28, 32, 40, 48, 64, + 20, 24, 28, 32, 40, 48, 64, 64, + 24, 28, 32, 40, 48, 64, 64, 64, + 28, 32, 40, 48, 64, 64, 64, 96, + 32, 40, 48, 64, 64, 64, 96, 128, + 40, 48, 64, 64, 64, 96, 128, 128 }; -static const int16_t vp31_dc_scale_factor[64] = -{ 220, 200, 190, 180, 170, 170, 160, 160, - 150, 150, 140, 140, 130, 130, 120, 120, - 110, 110, 100, 100, 90, 90, 90, 80, - 80, 80, 70, 70, 70, 60, 60, 60, - 60, 50, 50, 50, 50, 40, 40, 40, - 40, 40, 30, 30, 30, 30, 30, 30, - 30, 20, 20, 20, 20, 20, 20, 20, - 20, 10, 10, 10, 10, 10, 10, 10 +static const int16_t vp31_dc_scale_factor[64] = { + 220, 200, 190, 180, 170, 170, 160, 160, + 150, 150, 140, 140, 130, 130, 120, 120, + 110, 110, 100, 100, 90, 90, 90, 80, + 80, 80, 70, 70, 70, 60, 60, 60, + 60, 50, 50, 50, 50, 40, 40, 40, + 40, 40, 30, 30, 30, 30, 30, 30, + 30, 20, 20, 20, 20, 20, 20, 20, + 20, 10, 10, 10, 10, 10, 10, 10 }; -static const uint32_t vp31_ac_scale_factor[64] = -{ 500, 450, 400, 370, 340, 310, 285, 265, - 245, 225, 210, 195, 185, 180, 170, 160, - 150, 145, 135, 130, 125, 115, 110, 107, - 100, 96, 93, 89, 85, 82, 75, 74, - 70, 68, 64, 60, 57, 56, 52, 50, - 49, 45, 44, 43, 40, 38, 37, 35, - 33, 32, 30, 29, 28, 25, 24, 22, - 21, 19, 18, 17, 15, 13, 12, 10 +static const uint32_t vp31_ac_scale_factor[64] = { + 500, 450, 400, 370, 340, 310, 285, 265, + 245, 225, 210, 195, 185, 180, 170, 160, + 150, 145, 135, 130, 125, 115, 110, 107, + 100, 96, 93, 89, 85, 82, 75, 74, + 70, 68, 64, 60, 57, 56, 52, 50, + 49, 45, 44, 43, 40, 38, 37, 35, + 33, 32, 30, 29, 28, 25, 24, 22, + 21, 19, 18, 17, 15, 13, 12, 10 }; -static const uint8_t vp31_filter_limit_values[64] = -{ 30, 25, 20, 20, 15, 15, 14, 14, - 13, 13, 12, 12, 11, 11, 10, 10, - 9, 9, 8, 8, 7, 7, 7, 7, - 6, 6, 6, 6, 5, 5, 5, 5, - 4, 4, 4, 4, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 +static const uint8_t vp31_filter_limit_values[64] = { + 30, 25, 20, 20, 15, 15, 14, 14, + 13, 13, 12, 12, 11, 11, 10, 10, + 9, 9, 8, 8, 7, 7, 7, 7, + 6, 6, 6, 6, 5, 5, 5, 5, + 4, 4, 4, 4, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; static const uint16_t superblock_run_length_vlc_table[34][2] = { - { 0, 1 }, + { 0, 1 }, - { 4, 3 }, { 5, 3 }, + { 4, 3 }, { 5, 3 }, - { 0xC, 4 }, { 0xD, 4 }, + { 0xC, 4 }, { 0xD, 4 }, - { 0x38, 6 }, { 0x39, 6 }, { 0x3A, 6 }, { 0x3B, 6 }, + { 0x38, 6 }, { 0x39, 6 }, { 0x3A, 6 }, { 0x3B, 6 }, - { 0xF0, 8 }, { 0xF1, 8 }, { 0xF2, 8 }, { 0xF3, 8 }, - { 0xF4, 8 }, { 0xF5, 8 }, { 0xF6, 8 }, { 0xF7, 8 }, + { 0xF0, 8 }, { 0xF1, 8 }, { 0xF2, 8 }, { 0xF3, 8 }, + { 0xF4, 8 }, { 0xF5, 8 }, { 0xF6, 8 }, { 0xF7, 8 }, - { 0x3E0, 10 }, { 0x3E1, 10 }, { 0x3E2, 10 }, { 0x3E3, 10 }, - { 0x3E4, 10 }, { 0x3E5, 10 }, { 0x3E6, 10 }, { 0x3E7, 10 }, - { 0x3E8, 10 }, { 0x3E9, 10 }, { 0x3EA, 10 }, { 0x3EB, 10 }, - { 0x3EC, 10 }, { 0x3ED, 10 }, { 0x3EE, 10 }, { 0x3EF, 10 }, + { 0x3E0, 10 }, { 0x3E1, 10 }, { 0x3E2, 10 }, { 0x3E3, 10 }, + { 0x3E4, 10 }, { 0x3E5, 10 }, { 0x3E6, 10 }, { 0x3E7, 10 }, + { 0x3E8, 10 }, { 0x3E9, 10 }, { 0x3EA, 10 }, { 0x3EB, 10 }, + { 0x3EC, 10 }, { 0x3ED, 10 }, { 0x3EE, 10 }, { 0x3EF, 10 }, - { 0x3F, 6 } /* this last VLC is a special case for reading 12 more - bits from stream and adding the value 34 */ + { 0x3F, 6 } /* this last VLC is a special case for reading 12 more + * bits from stream and adding the value 34 */ }; static const uint16_t fragment_run_length_vlc_table[30][2] = { /* 1 -> 2 */ - { 0x0, 2 }, { 0x1, 2 }, + { 0x0, 2 }, { 0x1, 2 }, /* 3 -> 4 */ - { 0x4, 3 }, { 0x5, 3 }, + { 0x4, 3 }, { 0x5, 3 }, /* 5 -> 6 */ - { 0xC, 4 }, { 0xD, 4 }, + { 0xC, 4 }, { 0xD, 4 }, /* 7 -> 10 */ - { 0x38, 6 }, { 0x39, 6 }, - { 0x3A, 6 }, { 0x3B, 6 }, + { 0x38, 6 }, { 0x39, 6 }, + { 0x3A, 6 }, { 0x3B, 6 }, /* 11 -> 14 */ - { 0x78, 7 }, { 0x79, 7 }, - { 0x7A, 7 }, { 0x7B, 7 }, + { 0x78, 7 }, { 0x79, 7 }, + { 0x7A, 7 }, { 0x7B, 7 }, /* 15 -> 30 */ - { 0x1F0, 9 }, { 0x1F1, 9 }, { 0x1F2, 9 }, { 0x1F3, 9 }, - { 0x1F4, 9 }, { 0x1F5, 9 }, { 0x1F6, 9 }, { 0x1F7, 9 }, - { 0x1F8, 9 }, { 0x1F9, 9 }, { 0x1FA, 9 }, { 0x1FB, 9 }, - { 0x1FC, 9 }, { 0x1FD, 9 }, { 0x1FE, 9 }, { 0x1FF, 9 } + { 0x1F0, 9 }, { 0x1F1, 9 }, { 0x1F2, 9 }, { 0x1F3, 9 }, + { 0x1F4, 9 }, { 0x1F5, 9 }, { 0x1F6, 9 }, { 0x1F7, 9 }, + { 0x1F8, 9 }, { 0x1F9, 9 }, { 0x1FA, 9 }, { 0x1FB, 9 }, + { 0x1FC, 9 }, { 0x1FD, 9 }, { 0x1FE, 9 }, { 0x1FF, 9 } }; static const uint8_t mode_code_vlc_table[8][2] = { - { 0, 1 }, { 2, 2 }, - { 6, 3 }, { 14, 4 }, - { 30, 5 }, { 62, 6 }, - { 126, 7 }, { 127, 7 } + { 0, 1 }, { 2, 2 }, + { 6, 3 }, { 14, 4 }, + { 30, 5 }, { 62, 6 }, + { 126, 7 }, { 127, 7 } }; static const uint8_t motion_vector_vlc_table[63][2] = { - { 0, 3 }, - { 1, 3 }, - { 2, 3 }, + { 0, 3 }, + { 1, 3 }, + { 2, 3 }, - { 6, 4 }, { 7, 4 }, + { 6, 4 }, { 7, 4 }, - { 8, 4 }, { 9, 4 }, + { 8, 4 }, { 9, 4 }, - { 40, 6 }, { 41, 6 }, { 42, 6 }, { 43, 6 }, - { 44, 6 }, { 45, 6 }, { 46, 6 }, { 47, 6 }, + { 40, 6 }, { 41, 6 }, { 42, 6 }, { 43, 6 }, + { 44, 6 }, { 45, 6 }, { 46, 6 }, { 47, 6 }, - { 96, 7 }, { 97, 7 }, { 98, 7 }, { 99, 7 }, - { 100, 7 }, { 101, 7 }, { 102, 7 }, { 103, 7 }, - { 104, 7 }, { 105, 7 }, { 106, 7 }, { 107, 7 }, - { 108, 7 }, { 109, 7 }, { 110, 7 }, { 111, 7 }, + { 96, 7 }, { 97, 7 }, { 98, 7 }, { 99, 7 }, + { 100, 7 }, { 101, 7 }, { 102, 7 }, { 103, 7 }, + { 104, 7 }, { 105, 7 }, { 106, 7 }, { 107, 7 }, + { 108, 7 }, { 109, 7 }, { 110, 7 }, { 111, 7 }, - { 0xE0, 8 }, { 0xE1, 8 }, { 0xE2, 8 }, { 0xE3, 8 }, - { 0xE4, 8 }, { 0xE5, 8 }, { 0xE6, 8 }, { 0xE7, 8 }, - { 0xE8, 8 }, { 0xE9, 8 }, { 0xEA, 8 }, { 0xEB, 8 }, - { 0xEC, 8 }, { 0xED, 8 }, { 0xEE, 8 }, { 0xEF, 8 }, + { 0xE0, 8 }, { 0xE1, 8 }, { 0xE2, 8 }, { 0xE3, 8 }, + { 0xE4, 8 }, { 0xE5, 8 }, { 0xE6, 8 }, { 0xE7, 8 }, + { 0xE8, 8 }, { 0xE9, 8 }, { 0xEA, 8 }, { 0xEB, 8 }, + { 0xEC, 8 }, { 0xED, 8 }, { 0xEE, 8 }, { 0xEF, 8 }, - { 0xF0, 8 }, { 0xF1, 8 }, { 0xF2, 8 }, { 0xF3, 8 }, - { 0xF4, 8 }, { 0xF5, 8 }, { 0xF6, 8 }, { 0xF7, 8 }, - { 0xF8, 8 }, { 0xF9, 8 }, { 0xFA, 8 }, { 0xFB, 8 }, - { 0xFC, 8 }, { 0xFD, 8 }, { 0xFE, 8 }, { 0xFF, 8 } + { 0xF0, 8 }, { 0xF1, 8 }, { 0xF2, 8 }, { 0xF3, 8 }, + { 0xF4, 8 }, { 0xF5, 8 }, { 0xF6, 8 }, { 0xF7, 8 }, + { 0xF8, 8 }, { 0xF9, 8 }, { 0xFA, 8 }, { 0xFB, 8 }, + { 0xFC, 8 }, { 0xFD, 8 }, { 0xFE, 8 }, { 0xFF, 8 } }; static const int motion_vector_table[63] = { - 0, 1, -1, - 2, -2, - 3, -3, - 4, -4, 5, -5, 6, -6, 7, -7, - 8, -8, 9, -9, 10, -10, 11, -11, 12, -12, 13, -13, 14, -14, 15, -15, + 0, 1, -1, + 2, -2, + 3, -3, + 4, -4, 5, -5, 6, -6, 7, -7, + 8, -8, 9, -9, 10, -10, 11, -11, 12, -12, 13, -13, 14, -14, 15, -15, 16, -16, 17, -17, 18, -18, 19, -19, 20, -20, 21, -21, 22, -22, 23, -23, 24, -24, 25, -25, 26, -26, 27, -27, 28, -28, 29, -29, 30, -30, 31, -31 }; static const int8_t fixed_motion_vector_table[64] = { - 0, 0, 1, -1, 2, -2, 3, -3, - 4, -4, 5, -5, 6, -6, 7, -7, - 8, -8, 9, -9, 10, -10, 11, -11, - 12, -12, 13, -13, 14, -14, 15, -15, - 16, -16, 17, -17, 18, -18, 19, -19, - 20, -20, 21, -21, 22, -22, 23, -23, - 24, -24, 25, -25, 26, -26, 27, -27, - 28, -28, 29, -29, 30, -30, 31, -31 + 0, 0, 1, -1, 2, -2, 3, -3, + 4, -4, 5, -5, 6, -6, 7, -7, + 8, -8, 9, -9, 10, -10, 11, -11, + 12, -12, 13, -13, 14, -14, 15, -15, + 16, -16, 17, -17, 18, -18, 19, -19, + 20, -20, 21, -21, 22, -22, 23, -23, + 24, -24, 25, -25, 26, -26, 27, -27, + 28, -28, 29, -29, 30, -30, 31, -31 }; /* only tokens 0..6 indicate eob runs */ @@ -206,27 +206,27 @@ static const int eob_run_get_bits[7] = { }; static const int zero_run_base[32] = { - 0, 0, 0, 0, 0, 0, 0, /* 0..6 are never used */ - 0, 0, /* 7..8 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9..22 */ - 1, 2, 3, 4, 5, /* 23..27 */ - 6, 10, 1, 2 /* 28..31 */ + 0, 0, 0, 0, 0, 0, 0, /* 0..6 are never used */ + 0, 0, /* 7..8 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9..22 */ + 1, 2, 3, 4, 5, /* 23..27 */ + 6, 10, 1, 2 /* 28..31 */ }; static const int zero_run_get_bits[32] = { - 0, 0, 0, 0, 0, 0, 0, /* 0..6 are never used */ - 3, 6, /* 7..8 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9..22 */ - 0, 0, 0, 0, 0, /* 23..27 */ - 2, 3, 0, 1 /* 28..31 */ + 0, 0, 0, 0, 0, 0, 0, /* 0..6 are never used */ + 3, 6, /* 7..8 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9..22 */ + 0, 0, 0, 0, 0, /* 23..27 */ + 2, 3, 0, 1 /* 28..31 */ }; static const int coeff_get_bits[32] = { - 0, 0, 0, 0, 0, 0, 0, /* 0..6 are never used */ - 0, 0, 0, 0, 0, 0, /* 7..12 use constant coeffs */ - 1, 1, 1, 1, /* 13..16 are constants but still need sign bit */ - 2, 3, 4, 5, 6, 10, /* 17..22, for reading large coeffs */ - 1, 1, 1, 1, 1, 1, 1, /* 23..29 are constants but still need sign bit */ - 2, 2 /* 30..31 */ + 0, 0, 0, 0, 0, 0, 0, /* 0..6 are never used */ + 0, 0, 0, 0, 0, 0, /* 7..12 use constant coeffs */ + 1, 1, 1, 1, /* 13..16 are constants but still need sign bit */ + 2, 3, 4, 5, 6,10, /* 17..22, for reading large coeffs */ + 1, 1, 1, 1, 1, 1, 1, /* 23..29 are constants but still need sign bit */ + 2, 2 /* 30..31 */ }; static const int16_t coeff_table_token_7_8[1] = { 0 }; @@ -257,17 +257,17 @@ static const int16_t coeff_table_token_19[16] = { }; static const int16_t coeff_table_token_20[32] = { - 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, + 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, -21, -22, -23, -24, -25, -26, -27, -28, -29, -30, -31, -32, -33, -34, -35, -36 }; static const int16_t coeff_table_token_21[64] = { - 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, + 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, -37, -38, -39, -40, -41, -42, -43, -44, -45, -46, -47, -48, -49, -50, -51, -52, -53, -54, -55, -56, -57, -58, -59, -60, @@ -275,74 +275,74 @@ static const int16_t coeff_table_token_21[64] = { }; static const int16_t coeff_table_token_22[1024] = { - 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 172, - 173, 174, 175, 176, 177, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, - 213, 214, 215, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, - 293, 294, 295, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, - 333, 334, 335, 336, 337, 338, 339, 340, - 341, 342, 343, 344, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, 379, 380, - 381, 382, 383, 384, 385, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 411, 412, - 413, 414, 415, 416, 417, 418, 419, 420, - 421, 422, 423, 424, 425, 426, 427, 428, - 429, 430, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 443, 444, - 445, 446, 447, 448, 449, 450, 451, 452, - 453, 454, 455, 456, 457, 458, 459, 460, - 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, - 477, 478, 479, 480, 481, 482, 483, 484, - 485, 486, 487, 488, 489, 490, 491, 492, - 493, 494, 495, 496, 497, 498, 499, 500, - 501, 502, 503, 504, 505, 506, 507, 508, - 509, 510, 511, 512, 513, 514, 515, 516, - 517, 518, 519, 520, 521, 522, 523, 524, - 525, 526, 527, 528, 529, 530, 531, 532, - 533, 534, 535, 536, 537, 538, 539, 540, - 541, 542, 543, 544, 545, 546, 547, 548, - 549, 550, 551, 552, 553, 554, 555, 556, - 557, 558, 559, 560, 561, 562, 563, 564, - 565, 566, 567, 568, 569, 570, 571, 572, - 573, 574, 575, 576, 577, 578, 579, 580, - -69, -70, -71, -72, -73, -74, -75, -76, - -77, -78, -79, -80, -81, -82, -83, -84, - -85, -86, -87, -88, -89, -90, -91, -92, - -93, -94, -95, -96, -97, -98, -99, -100, + 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, + 173, 174, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 388, + 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 425, 426, 427, 428, + 429, 430, 431, 432, 433, 434, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 447, 448, 449, 450, 451, 452, + 453, 454, 455, 456, 457, 458, 459, 460, + 461, 462, 463, 464, 465, 466, 467, 468, + 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 484, + 485, 486, 487, 488, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 498, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 520, 521, 522, 523, 524, + 525, 526, 527, 528, 529, 530, 531, 532, + 533, 534, 535, 536, 537, 538, 539, 540, + 541, 542, 543, 544, 545, 546, 547, 548, + 549, 550, 551, 552, 553, 554, 555, 556, + 557, 558, 559, 560, 561, 562, 563, 564, + 565, 566, 567, 568, 569, 570, 571, 572, + 573, 574, 575, 576, 577, 578, 579, 580, + -69, -70, -71, -72, -73, -74, -75, -76, + -77, -78, -79, -80, -81, -82, -83, -84, + -85, -86, -87, -88, -89, -90, -91, -92, + -93, -94, -95, -96, -97, -98, -99, -100, -101, -102, -103, -104, -105, -106, -107, -108, -109, -110, -111, -112, -113, -114, -115, -116, -117, -118, -119, -120, -121, -122, -123, -124, @@ -444,2738 +444,2738 @@ static const int16_t *const coeff_tables[32] = { }; static const uint16_t dc_bias[16][32][2] = { - { /* DC bias table 0 */ - { 0x2D, 6 }, - { 0x26, 7 }, - { 0x166, 9 }, - { 0x4E, 8 }, - { 0x2CE, 10 }, - { 0x59E, 11 }, - { 0x27D, 11 }, - { 0x8, 5 }, - { 0x4F9, 12 }, - { 0xF, 4 }, - { 0xE, 4 }, - { 0x1B, 5 }, - { 0x6, 4 }, - { 0x8, 4 }, - { 0x5, 4 }, - { 0x1A, 5 }, - { 0x15, 5 }, - { 0x7, 4 }, - { 0xC, 4 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0x9, 4 }, - { 0x17, 5 }, - { 0x29, 6 }, - { 0x28, 6 }, - { 0xB2, 8 }, - { 0x4F8, 12 }, - { 0x59F, 11 }, - { 0x9E, 9 }, - { 0x13F, 10 }, - { 0x12, 6 }, - { 0x58, 7 } - }, - { /* DC bias table 1 */ - { 0x10, 5 }, - { 0x47, 7 }, - { 0x1FF, 9 }, - { 0x8C, 8 }, - { 0x3FC, 10 }, - { 0x46A, 11 }, - { 0x469, 11 }, - { 0x22, 6 }, - { 0x11A1, 13 }, - { 0xE, 4 }, - { 0xD, 4 }, - { 0x4, 4 }, - { 0x5, 4 }, - { 0x9, 4 }, - { 0x6, 4 }, - { 0x1E, 5 }, - { 0x16, 5 }, - { 0x7, 4 }, - { 0xC, 4 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xA, 4 }, - { 0x17, 5 }, - { 0x7D, 7 }, - { 0x7E, 7 }, - { 0x11B, 9 }, - { 0x8D1, 12 }, - { 0x3FD, 10 }, - { 0x46B, 11 }, - { 0x11A0, 13 }, - { 0x7C, 7 }, - { 0xFE, 8 } - }, - { /* DC bias table 2 */ - { 0x16, 5 }, - { 0x20, 6 }, - { 0x86, 8 }, - { 0x87, 8 }, - { 0x367, 10 }, - { 0x6CC, 11 }, - { 0x6CB, 11 }, - { 0x6E, 7 }, - { 0x366D, 14 }, - { 0xF, 4 }, - { 0xE, 4 }, - { 0x4, 4 }, - { 0x5, 4 }, - { 0xA, 4 }, - { 0x6, 4 }, - { 0x1A, 5 }, - { 0x11, 5 }, - { 0x7, 4 }, - { 0xC, 4 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0x9, 4 }, - { 0x17, 5 }, - { 0x6F, 7 }, - { 0x6D, 7 }, - { 0x364, 10 }, - { 0xD9A, 12 }, - { 0x6CA, 11 }, - { 0x1B37, 13 }, - { 0x366C, 14 }, - { 0x42, 7 }, - { 0xD8, 8 } - }, - { /* DC bias table 3 */ - { 0x0, 4 }, - { 0x2D, 6 }, - { 0xF7, 8 }, - { 0x58, 7 }, - { 0x167, 9 }, - { 0x2CB, 10 }, - { 0x2CA, 10 }, - { 0xE, 6 }, - { 0x1661, 13 }, - { 0x3, 3 }, - { 0x2, 3 }, - { 0x8, 4 }, - { 0x9, 4 }, - { 0xD, 4 }, - { 0x2, 4 }, - { 0x1F, 5 }, - { 0x17, 5 }, - { 0x1, 4 }, - { 0xC, 4 }, - { 0xE, 4 }, - { 0xA, 4 }, - { 0x6, 5 }, - { 0x78, 7 }, - { 0xF, 6 }, - { 0x7A, 7 }, - { 0x164, 9 }, - { 0x599, 11 }, - { 0x2CD, 10 }, - { 0xB31, 12 }, - { 0x1660, 13 }, - { 0x79, 7 }, - { 0xF6, 8 } - }, - { /* DC bias table 4 */ - { 0x3, 4 }, - { 0x3C, 6 }, - { 0xF, 7 }, - { 0x7A, 7 }, - { 0x1D, 8 }, - { 0x20, 9 }, - { 0x72, 10 }, - { 0x6, 6 }, - { 0x399, 13 }, - { 0x4, 3 }, - { 0x5, 3 }, - { 0x5, 4 }, - { 0x6, 4 }, - { 0xE, 4 }, - { 0x4, 4 }, - { 0x0, 4 }, - { 0x19, 5 }, - { 0x2, 4 }, - { 0xD, 4 }, - { 0x7, 4 }, - { 0x1F, 5 }, - { 0x30, 6 }, - { 0x11, 8 }, - { 0x31, 6 }, - { 0x5, 6 }, - { 0x21, 9 }, - { 0xE7, 11 }, - { 0x38, 9 }, - { 0x1CD, 12 }, - { 0x398, 13 }, - { 0x7B, 7 }, - { 0x9, 7 } - }, - { /* DC bias table 5 */ - { 0x9, 4 }, - { 0x2, 5 }, - { 0x74, 7 }, - { 0x7, 6 }, - { 0xEC, 8 }, - { 0xD1, 9 }, - { 0x1A6, 10 }, - { 0x6, 6 }, - { 0xD21, 13 }, - { 0x5, 3 }, - { 0x6, 3 }, - { 0x8, 4 }, - { 0x7, 4 }, - { 0xF, 4 }, - { 0x4, 4 }, - { 0x0, 4 }, - { 0x1C, 5 }, - { 0x2, 4 }, - { 0x5, 4 }, - { 0x3, 4 }, - { 0xC, 5 }, - { 0x35, 7 }, - { 0x1A7, 10 }, - { 0x1B, 6 }, - { 0x77, 7 }, - { 0x1A5, 10 }, - { 0x349, 11 }, - { 0xD0, 9 }, - { 0x691, 12 }, - { 0xD20, 13 }, - { 0x75, 7 }, - { 0xED, 8 } - }, - { /* DC bias table 6 */ - { 0xA, 4 }, - { 0xC, 5 }, - { 0x12, 6 }, - { 0x1B, 6 }, - { 0xB7, 8 }, - { 0x16C, 9 }, - { 0x99, 9 }, - { 0x5A, 7 }, - { 0x16D8, 13 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x0, 3 }, - { 0x5, 4 }, - { 0x17, 5 }, - { 0xE, 5 }, - { 0x2, 4 }, - { 0x3, 4 }, - { 0xF, 5 }, - { 0x1A, 6 }, - { 0x4D, 8 }, - { 0x2DB3, 14 }, - { 0x2C, 6 }, - { 0x11, 6 }, - { 0x2DA, 10 }, - { 0x5B7, 11 }, - { 0x98, 9 }, - { 0xB6D, 12 }, - { 0x2DB2, 14 }, - { 0x10, 6 }, - { 0x27, 7 } - }, - { /* DC bias table 7 */ - { 0xD, 4 }, - { 0xF, 5 }, - { 0x1D, 6 }, - { 0x8, 5 }, - { 0x51, 7 }, - { 0x56, 8 }, - { 0xAF, 9 }, - { 0x2A, 7 }, - { 0x148A, 13 }, - { 0x7, 3 }, - { 0x0, 2 }, - { 0x8, 4 }, - { 0x9, 4 }, - { 0xC, 4 }, - { 0x6, 4 }, - { 0x17, 5 }, - { 0xB, 5 }, - { 0x16, 5 }, - { 0x15, 5 }, - { 0x9, 5 }, - { 0x50, 7 }, - { 0xAE, 9 }, - { 0x2917, 14 }, - { 0x1C, 6 }, - { 0x14, 6 }, - { 0x290, 10 }, - { 0x523, 11 }, - { 0x149, 9 }, - { 0xA44, 12 }, - { 0x2916, 14 }, - { 0x53, 7 }, - { 0xA5, 8 } - }, - { /* DC bias table 8 */ - { 0x1, 4 }, - { 0x1D, 6 }, - { 0xF5, 8 }, - { 0xF4, 8 }, - { 0x24D, 10 }, - { 0x499, 11 }, - { 0x498, 11 }, - { 0x1, 5 }, - { 0x21, 6 }, - { 0x6, 3 }, - { 0x5, 3 }, - { 0x6, 4 }, - { 0x5, 4 }, - { 0x2, 4 }, - { 0x7, 5 }, - { 0x25, 6 }, - { 0x7B, 7 }, - { 0x1C, 6 }, - { 0x20, 6 }, - { 0xD, 6 }, - { 0x48, 7 }, - { 0x92, 8 }, - { 0x127, 9 }, - { 0xE, 4 }, - { 0x4, 4 }, - { 0x11, 5 }, - { 0xC, 6 }, - { 0x3C, 6 }, - { 0xF, 5 }, - { 0x0, 5 }, - { 0x1F, 5 }, - { 0x13, 5 } - }, - { /* DC bias table 9 */ - { 0x5, 4 }, - { 0x3C, 6 }, - { 0x40, 7 }, - { 0xD, 7 }, - { 0x31, 9 }, - { 0x61, 10 }, - { 0x60, 10 }, - { 0x2, 5 }, - { 0xF5, 8 }, - { 0x6, 3 }, - { 0x5, 3 }, - { 0x7, 4 }, - { 0x6, 4 }, - { 0x2, 4 }, - { 0x9, 5 }, - { 0x25, 6 }, - { 0x7, 6 }, - { 0x21, 6 }, - { 0x24, 6 }, - { 0x10, 6 }, - { 0x41, 7 }, - { 0xF4, 8 }, - { 0x19, 8 }, - { 0xE, 4 }, - { 0x3, 4 }, - { 0x11, 5 }, - { 0x11, 6 }, - { 0x3F, 6 }, - { 0x3E, 6 }, - { 0x7B, 7 }, - { 0x0, 4 }, - { 0x13, 5 } - }, - { /* DC bias table 10 */ - { 0xA, 4 }, - { 0x7, 5 }, - { 0x1, 6 }, - { 0x9, 6 }, - { 0x131, 9 }, - { 0x261, 10 }, - { 0x260, 10 }, - { 0x15, 6 }, - { 0x1, 7 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0x8, 4 }, - { 0x7, 4 }, - { 0x6, 4 }, - { 0x12, 5 }, - { 0x2F, 6 }, - { 0x14, 6 }, - { 0x27, 6 }, - { 0x2D, 6 }, - { 0x16, 6 }, - { 0x4D, 7 }, - { 0x99, 8 }, - { 0x0, 7 }, - { 0x4, 4 }, - { 0x1, 4 }, - { 0x5, 5 }, - { 0x17, 6 }, - { 0x2E, 6 }, - { 0x2C, 6 }, - { 0x8, 6 }, - { 0x6, 5 }, - { 0x1, 5 } - }, - { /* DC bias table 11 */ - { 0x0, 3 }, - { 0xE, 5 }, - { 0x17, 6 }, - { 0x2A, 6 }, - { 0x10, 7 }, - { 0xF9, 10 }, - { 0xF8, 10 }, - { 0x1E, 7 }, - { 0x3F, 8 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x6, 4 }, - { 0xF, 5 }, - { 0x5, 5 }, - { 0x16, 6 }, - { 0x29, 6 }, - { 0x2B, 6 }, - { 0x15, 6 }, - { 0x50, 7 }, - { 0x11, 7 }, - { 0x7D, 9 }, - { 0x4, 4 }, - { 0x17, 5 }, - { 0x6, 5 }, - { 0x14, 6 }, - { 0x2C, 6 }, - { 0x2D, 6 }, - { 0xE, 6 }, - { 0x9, 6 }, - { 0x51, 7 } - }, - { /* DC bias table 12 */ - { 0x2, 3 }, - { 0x18, 5 }, - { 0x2F, 6 }, - { 0xD, 5 }, - { 0x53, 7 }, - { 0x295, 10 }, - { 0x294, 10 }, - { 0xA4, 8 }, - { 0x7C, 8 }, - { 0x0, 2 }, - { 0x7, 3 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x1B, 5 }, - { 0xC, 5 }, - { 0x28, 6 }, - { 0x6A, 7 }, - { 0x1E, 6 }, - { 0x1D, 6 }, - { 0x69, 7 }, - { 0xD7, 8 }, - { 0x7D, 8 }, - { 0x14B, 9 }, - { 0x19, 5 }, - { 0x16, 5 }, - { 0x2E, 6 }, - { 0x1C, 6 }, - { 0x2B, 6 }, - { 0x2A, 6 }, - { 0x68, 7 }, - { 0x3F, 7 }, - { 0xD6, 8 } - }, - { /* DC bias table 13 */ - { 0x2, 3 }, - { 0x1B, 5 }, - { 0xC, 5 }, - { 0x18, 5 }, - { 0x29, 6 }, - { 0x7F, 8 }, - { 0x2F0, 10 }, - { 0x198, 9 }, - { 0x179, 9 }, - { 0x0, 2 }, - { 0x7, 3 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x1A, 5 }, - { 0xD, 5 }, - { 0x2A, 6 }, - { 0x64, 7 }, - { 0x1E, 6 }, - { 0x67, 7 }, - { 0x5F, 7 }, - { 0xCD, 8 }, - { 0x7E, 8 }, - { 0x2F1, 10 }, - { 0x16, 5 }, - { 0xE, 5 }, - { 0x2E, 6 }, - { 0x65, 7 }, - { 0x2B, 6 }, - { 0x28, 6 }, - { 0x3E, 7 }, - { 0xBD, 8 }, - { 0x199, 9 } - }, - { /* DC bias table 14 */ - { 0x2, 3 }, - { 0x7, 4 }, - { 0x16, 5 }, - { 0x6, 4 }, - { 0x36, 6 }, - { 0x5C, 7 }, - { 0x15D, 9 }, - { 0x15C, 9 }, - { 0x2BF, 10 }, - { 0x0, 2 }, - { 0x7, 3 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x18, 5 }, - { 0x34, 6 }, - { 0x2A, 6 }, - { 0x5E, 7 }, - { 0x6A, 7 }, - { 0x64, 7 }, - { 0x5D, 7 }, - { 0xCB, 8 }, - { 0xAD, 8 }, - { 0x2BE, 10 }, - { 0x14, 5 }, - { 0x33, 6 }, - { 0x6E, 7 }, - { 0x5F, 7 }, - { 0x6F, 7 }, - { 0x6B, 7 }, - { 0xCA, 8 }, - { 0xAC, 8 }, - { 0x15E, 9 } - }, - { /* DC bias table 15 */ - { 0xF, 4 }, - { 0x1D, 5 }, - { 0x18, 5 }, - { 0xB, 4 }, - { 0x19, 5 }, - { 0x29, 6 }, - { 0xD6, 8 }, - { 0x551, 11 }, - { 0xAA1, 12 }, - { 0x1, 2 }, - { 0x0, 2 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x1B, 5 }, - { 0x38, 6 }, - { 0x28, 6 }, - { 0x57, 7 }, - { 0x6A, 7 }, - { 0x68, 7 }, - { 0x56, 7 }, - { 0xE5, 8 }, - { 0x155, 9 }, - { 0xAA0, 12 }, - { 0x73, 7 }, - { 0x69, 7 }, - { 0xD7, 8 }, - { 0xAB, 8 }, - { 0xE4, 8 }, - { 0xA9, 8 }, - { 0x151, 9 }, - { 0x150, 9 }, - { 0x2A9, 10 } - } + { /* DC bias table 0 */ + { 0x2D, 6 }, + { 0x26, 7 }, + { 0x166, 9 }, + { 0x4E, 8 }, + { 0x2CE, 10 }, + { 0x59E, 11 }, + { 0x27D, 11 }, + { 0x8, 5 }, + { 0x4F9, 12 }, + { 0xF, 4 }, + { 0xE, 4 }, + { 0x1B, 5 }, + { 0x6, 4 }, + { 0x8, 4 }, + { 0x5, 4 }, + { 0x1A, 5 }, + { 0x15, 5 }, + { 0x7, 4 }, + { 0xC, 4 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0x9, 4 }, + { 0x17, 5 }, + { 0x29, 6 }, + { 0x28, 6 }, + { 0xB2, 8 }, + { 0x4F8, 12 }, + { 0x59F, 11 }, + { 0x9E, 9 }, + { 0x13F, 10 }, + { 0x12, 6 }, + { 0x58, 7 } + }, + { /* DC bias table 1 */ + { 0x10, 5 }, + { 0x47, 7 }, + { 0x1FF, 9 }, + { 0x8C, 8 }, + { 0x3FC, 10 }, + { 0x46A, 11 }, + { 0x469, 11 }, + { 0x22, 6 }, + { 0x11A1, 13 }, + { 0xE, 4 }, + { 0xD, 4 }, + { 0x4, 4 }, + { 0x5, 4 }, + { 0x9, 4 }, + { 0x6, 4 }, + { 0x1E, 5 }, + { 0x16, 5 }, + { 0x7, 4 }, + { 0xC, 4 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xA, 4 }, + { 0x17, 5 }, + { 0x7D, 7 }, + { 0x7E, 7 }, + { 0x11B, 9 }, + { 0x8D1, 12 }, + { 0x3FD, 10 }, + { 0x46B, 11 }, + { 0x11A0, 13 }, + { 0x7C, 7 }, + { 0xFE, 8 } + }, + { /* DC bias table 2 */ + { 0x16, 5 }, + { 0x20, 6 }, + { 0x86, 8 }, + { 0x87, 8 }, + { 0x367, 10 }, + { 0x6CC, 11 }, + { 0x6CB, 11 }, + { 0x6E, 7 }, + { 0x366D, 14 }, + { 0xF, 4 }, + { 0xE, 4 }, + { 0x4, 4 }, + { 0x5, 4 }, + { 0xA, 4 }, + { 0x6, 4 }, + { 0x1A, 5 }, + { 0x11, 5 }, + { 0x7, 4 }, + { 0xC, 4 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0x9, 4 }, + { 0x17, 5 }, + { 0x6F, 7 }, + { 0x6D, 7 }, + { 0x364, 10 }, + { 0xD9A, 12 }, + { 0x6CA, 11 }, + { 0x1B37, 13 }, + { 0x366C, 14 }, + { 0x42, 7 }, + { 0xD8, 8 } + }, + { /* DC bias table 3 */ + { 0x0, 4 }, + { 0x2D, 6 }, + { 0xF7, 8 }, + { 0x58, 7 }, + { 0x167, 9 }, + { 0x2CB, 10 }, + { 0x2CA, 10 }, + { 0xE, 6 }, + { 0x1661, 13 }, + { 0x3, 3 }, + { 0x2, 3 }, + { 0x8, 4 }, + { 0x9, 4 }, + { 0xD, 4 }, + { 0x2, 4 }, + { 0x1F, 5 }, + { 0x17, 5 }, + { 0x1, 4 }, + { 0xC, 4 }, + { 0xE, 4 }, + { 0xA, 4 }, + { 0x6, 5 }, + { 0x78, 7 }, + { 0xF, 6 }, + { 0x7A, 7 }, + { 0x164, 9 }, + { 0x599, 11 }, + { 0x2CD, 10 }, + { 0xB31, 12 }, + { 0x1660, 13 }, + { 0x79, 7 }, + { 0xF6, 8 } + }, + { /* DC bias table 4 */ + { 0x3, 4 }, + { 0x3C, 6 }, + { 0xF, 7 }, + { 0x7A, 7 }, + { 0x1D, 8 }, + { 0x20, 9 }, + { 0x72, 10 }, + { 0x6, 6 }, + { 0x399, 13 }, + { 0x4, 3 }, + { 0x5, 3 }, + { 0x5, 4 }, + { 0x6, 4 }, + { 0xE, 4 }, + { 0x4, 4 }, + { 0x0, 4 }, + { 0x19, 5 }, + { 0x2, 4 }, + { 0xD, 4 }, + { 0x7, 4 }, + { 0x1F, 5 }, + { 0x30, 6 }, + { 0x11, 8 }, + { 0x31, 6 }, + { 0x5, 6 }, + { 0x21, 9 }, + { 0xE7, 11 }, + { 0x38, 9 }, + { 0x1CD, 12 }, + { 0x398, 13 }, + { 0x7B, 7 }, + { 0x9, 7 } + }, + { /* DC bias table 5 */ + { 0x9, 4 }, + { 0x2, 5 }, + { 0x74, 7 }, + { 0x7, 6 }, + { 0xEC, 8 }, + { 0xD1, 9 }, + { 0x1A6, 10 }, + { 0x6, 6 }, + { 0xD21, 13 }, + { 0x5, 3 }, + { 0x6, 3 }, + { 0x8, 4 }, + { 0x7, 4 }, + { 0xF, 4 }, + { 0x4, 4 }, + { 0x0, 4 }, + { 0x1C, 5 }, + { 0x2, 4 }, + { 0x5, 4 }, + { 0x3, 4 }, + { 0xC, 5 }, + { 0x35, 7 }, + { 0x1A7, 10 }, + { 0x1B, 6 }, + { 0x77, 7 }, + { 0x1A5, 10 }, + { 0x349, 11 }, + { 0xD0, 9 }, + { 0x691, 12 }, + { 0xD20, 13 }, + { 0x75, 7 }, + { 0xED, 8 } + }, + { /* DC bias table 6 */ + { 0xA, 4 }, + { 0xC, 5 }, + { 0x12, 6 }, + { 0x1B, 6 }, + { 0xB7, 8 }, + { 0x16C, 9 }, + { 0x99, 9 }, + { 0x5A, 7 }, + { 0x16D8, 13 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x0, 3 }, + { 0x5, 4 }, + { 0x17, 5 }, + { 0xE, 5 }, + { 0x2, 4 }, + { 0x3, 4 }, + { 0xF, 5 }, + { 0x1A, 6 }, + { 0x4D, 8 }, + { 0x2DB3, 14 }, + { 0x2C, 6 }, + { 0x11, 6 }, + { 0x2DA, 10 }, + { 0x5B7, 11 }, + { 0x98, 9 }, + { 0xB6D, 12 }, + { 0x2DB2, 14 }, + { 0x10, 6 }, + { 0x27, 7 } + }, + { /* DC bias table 7 */ + { 0xD, 4 }, + { 0xF, 5 }, + { 0x1D, 6 }, + { 0x8, 5 }, + { 0x51, 7 }, + { 0x56, 8 }, + { 0xAF, 9 }, + { 0x2A, 7 }, + { 0x148A, 13 }, + { 0x7, 3 }, + { 0x0, 2 }, + { 0x8, 4 }, + { 0x9, 4 }, + { 0xC, 4 }, + { 0x6, 4 }, + { 0x17, 5 }, + { 0xB, 5 }, + { 0x16, 5 }, + { 0x15, 5 }, + { 0x9, 5 }, + { 0x50, 7 }, + { 0xAE, 9 }, + { 0x2917, 14 }, + { 0x1C, 6 }, + { 0x14, 6 }, + { 0x290, 10 }, + { 0x523, 11 }, + { 0x149, 9 }, + { 0xA44, 12 }, + { 0x2916, 14 }, + { 0x53, 7 }, + { 0xA5, 8 } + }, + { /* DC bias table 8 */ + { 0x1, 4 }, + { 0x1D, 6 }, + { 0xF5, 8 }, + { 0xF4, 8 }, + { 0x24D, 10 }, + { 0x499, 11 }, + { 0x498, 11 }, + { 0x1, 5 }, + { 0x21, 6 }, + { 0x6, 3 }, + { 0x5, 3 }, + { 0x6, 4 }, + { 0x5, 4 }, + { 0x2, 4 }, + { 0x7, 5 }, + { 0x25, 6 }, + { 0x7B, 7 }, + { 0x1C, 6 }, + { 0x20, 6 }, + { 0xD, 6 }, + { 0x48, 7 }, + { 0x92, 8 }, + { 0x127, 9 }, + { 0xE, 4 }, + { 0x4, 4 }, + { 0x11, 5 }, + { 0xC, 6 }, + { 0x3C, 6 }, + { 0xF, 5 }, + { 0x0, 5 }, + { 0x1F, 5 }, + { 0x13, 5 } + }, + { /* DC bias table 9 */ + { 0x5, 4 }, + { 0x3C, 6 }, + { 0x40, 7 }, + { 0xD, 7 }, + { 0x31, 9 }, + { 0x61, 10 }, + { 0x60, 10 }, + { 0x2, 5 }, + { 0xF5, 8 }, + { 0x6, 3 }, + { 0x5, 3 }, + { 0x7, 4 }, + { 0x6, 4 }, + { 0x2, 4 }, + { 0x9, 5 }, + { 0x25, 6 }, + { 0x7, 6 }, + { 0x21, 6 }, + { 0x24, 6 }, + { 0x10, 6 }, + { 0x41, 7 }, + { 0xF4, 8 }, + { 0x19, 8 }, + { 0xE, 4 }, + { 0x3, 4 }, + { 0x11, 5 }, + { 0x11, 6 }, + { 0x3F, 6 }, + { 0x3E, 6 }, + { 0x7B, 7 }, + { 0x0, 4 }, + { 0x13, 5 } + }, + { /* DC bias table 10 */ + { 0xA, 4 }, + { 0x7, 5 }, + { 0x1, 6 }, + { 0x9, 6 }, + { 0x131, 9 }, + { 0x261, 10 }, + { 0x260, 10 }, + { 0x15, 6 }, + { 0x1, 7 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0x8, 4 }, + { 0x7, 4 }, + { 0x6, 4 }, + { 0x12, 5 }, + { 0x2F, 6 }, + { 0x14, 6 }, + { 0x27, 6 }, + { 0x2D, 6 }, + { 0x16, 6 }, + { 0x4D, 7 }, + { 0x99, 8 }, + { 0x0, 7 }, + { 0x4, 4 }, + { 0x1, 4 }, + { 0x5, 5 }, + { 0x17, 6 }, + { 0x2E, 6 }, + { 0x2C, 6 }, + { 0x8, 6 }, + { 0x6, 5 }, + { 0x1, 5 } + }, + { /* DC bias table 11 */ + { 0x0, 3 }, + { 0xE, 5 }, + { 0x17, 6 }, + { 0x2A, 6 }, + { 0x10, 7 }, + { 0xF9, 10 }, + { 0xF8, 10 }, + { 0x1E, 7 }, + { 0x3F, 8 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x6, 4 }, + { 0xF, 5 }, + { 0x5, 5 }, + { 0x16, 6 }, + { 0x29, 6 }, + { 0x2B, 6 }, + { 0x15, 6 }, + { 0x50, 7 }, + { 0x11, 7 }, + { 0x7D, 9 }, + { 0x4, 4 }, + { 0x17, 5 }, + { 0x6, 5 }, + { 0x14, 6 }, + { 0x2C, 6 }, + { 0x2D, 6 }, + { 0xE, 6 }, + { 0x9, 6 }, + { 0x51, 7 } + }, + { /* DC bias table 12 */ + { 0x2, 3 }, + { 0x18, 5 }, + { 0x2F, 6 }, + { 0xD, 5 }, + { 0x53, 7 }, + { 0x295, 10 }, + { 0x294, 10 }, + { 0xA4, 8 }, + { 0x7C, 8 }, + { 0x0, 2 }, + { 0x7, 3 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x1B, 5 }, + { 0xC, 5 }, + { 0x28, 6 }, + { 0x6A, 7 }, + { 0x1E, 6 }, + { 0x1D, 6 }, + { 0x69, 7 }, + { 0xD7, 8 }, + { 0x7D, 8 }, + { 0x14B, 9 }, + { 0x19, 5 }, + { 0x16, 5 }, + { 0x2E, 6 }, + { 0x1C, 6 }, + { 0x2B, 6 }, + { 0x2A, 6 }, + { 0x68, 7 }, + { 0x3F, 7 }, + { 0xD6, 8 } + }, + { /* DC bias table 13 */ + { 0x2, 3 }, + { 0x1B, 5 }, + { 0xC, 5 }, + { 0x18, 5 }, + { 0x29, 6 }, + { 0x7F, 8 }, + { 0x2F0, 10 }, + { 0x198, 9 }, + { 0x179, 9 }, + { 0x0, 2 }, + { 0x7, 3 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x1A, 5 }, + { 0xD, 5 }, + { 0x2A, 6 }, + { 0x64, 7 }, + { 0x1E, 6 }, + { 0x67, 7 }, + { 0x5F, 7 }, + { 0xCD, 8 }, + { 0x7E, 8 }, + { 0x2F1, 10 }, + { 0x16, 5 }, + { 0xE, 5 }, + { 0x2E, 6 }, + { 0x65, 7 }, + { 0x2B, 6 }, + { 0x28, 6 }, + { 0x3E, 7 }, + { 0xBD, 8 }, + { 0x199, 9 } + }, + { /* DC bias table 14 */ + { 0x2, 3 }, + { 0x7, 4 }, + { 0x16, 5 }, + { 0x6, 4 }, + { 0x36, 6 }, + { 0x5C, 7 }, + { 0x15D, 9 }, + { 0x15C, 9 }, + { 0x2BF, 10 }, + { 0x0, 2 }, + { 0x7, 3 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x18, 5 }, + { 0x34, 6 }, + { 0x2A, 6 }, + { 0x5E, 7 }, + { 0x6A, 7 }, + { 0x64, 7 }, + { 0x5D, 7 }, + { 0xCB, 8 }, + { 0xAD, 8 }, + { 0x2BE, 10 }, + { 0x14, 5 }, + { 0x33, 6 }, + { 0x6E, 7 }, + { 0x5F, 7 }, + { 0x6F, 7 }, + { 0x6B, 7 }, + { 0xCA, 8 }, + { 0xAC, 8 }, + { 0x15E, 9 } + }, + { /* DC bias table 15 */ + { 0xF, 4 }, + { 0x1D, 5 }, + { 0x18, 5 }, + { 0xB, 4 }, + { 0x19, 5 }, + { 0x29, 6 }, + { 0xD6, 8 }, + { 0x551, 11 }, + { 0xAA1, 12 }, + { 0x1, 2 }, + { 0x0, 2 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x1B, 5 }, + { 0x38, 6 }, + { 0x28, 6 }, + { 0x57, 7 }, + { 0x6A, 7 }, + { 0x68, 7 }, + { 0x56, 7 }, + { 0xE5, 8 }, + { 0x155, 9 }, + { 0xAA0, 12 }, + { 0x73, 7 }, + { 0x69, 7 }, + { 0xD7, 8 }, + { 0xAB, 8 }, + { 0xE4, 8 }, + { 0xA9, 8 }, + { 0x151, 9 }, + { 0x150, 9 }, + { 0x2A9, 10 } + } }; static const uint16_t ac_bias_0[16][32][2] = { - { /* AC bias group 1, table 0 */ - { 0x8, 5 }, - { 0x25, 7 }, - { 0x17A, 9 }, - { 0x2F7, 10 }, - { 0xBDB, 12 }, - { 0x17B4, 13 }, - { 0x2F6B, 14 }, - { 0x1D, 5 }, - { 0x2F6A, 14 }, - { 0x8, 4 }, - { 0x7, 4 }, - { 0x1, 4 }, - { 0x2, 4 }, - { 0xA, 4 }, - { 0x6, 4 }, - { 0x0, 4 }, - { 0x1C, 5 }, - { 0x9, 4 }, - { 0xD, 4 }, - { 0xF, 4 }, - { 0xC, 4 }, - { 0x3, 4 }, - { 0xA, 5 }, - { 0x16, 5 }, - { 0x13, 6 }, - { 0x5D, 7 }, - { 0x24, 7 }, - { 0xBC, 8 }, - { 0x5C, 7 }, - { 0x5EC, 11 }, - { 0xB, 5 }, - { 0x5F, 7 } - }, - { /* AC bias group 1, table 1 */ - { 0xF, 5 }, - { 0x10, 6 }, - { 0x4B, 8 }, - { 0xC6, 8 }, - { 0x31D, 10 }, - { 0xC71, 12 }, - { 0xC70, 12 }, - { 0x1, 4 }, - { 0xC73, 12 }, - { 0x8, 4 }, - { 0x9, 4 }, - { 0x2, 4 }, - { 0x3, 4 }, - { 0xB, 4 }, - { 0x6, 4 }, - { 0x0, 4 }, - { 0x1C, 5 }, - { 0x5, 4 }, - { 0xD, 4 }, - { 0xF, 4 }, - { 0xA, 4 }, - { 0x19, 5 }, - { 0x13, 6 }, - { 0x1D, 5 }, - { 0x30, 6 }, - { 0x62, 7 }, - { 0x24, 7 }, - { 0x4A, 8 }, - { 0x18F, 9 }, - { 0xC72, 12 }, - { 0xE, 5 }, - { 0x11, 6 } - }, - { /* AC bias group 1, table 2 */ - { 0x1B, 5 }, - { 0x3, 6 }, - { 0x8D, 8 }, - { 0x40, 7 }, - { 0x239, 10 }, - { 0x471, 11 }, - { 0x8E0, 12 }, - { 0x3, 4 }, - { 0x11C3, 13 }, - { 0xA, 4 }, - { 0x9, 4 }, - { 0x4, 4 }, - { 0x5, 4 }, - { 0xE, 4 }, - { 0x7, 4 }, - { 0x1, 4 }, - { 0x1E, 5 }, - { 0x6, 4 }, - { 0xC, 4 }, - { 0xB, 4 }, - { 0x2, 4 }, - { 0x0, 5 }, - { 0x41, 7 }, - { 0x1F, 5 }, - { 0x22, 6 }, - { 0x2, 6 }, - { 0x8F, 8 }, - { 0x8C, 8 }, - { 0x11D, 9 }, - { 0x11C2, 13 }, - { 0x1A, 5 }, - { 0x21, 6 } - }, - { /* AC bias group 1, table 3 */ - { 0x1F, 5 }, - { 0x3, 6 }, - { 0x3, 7 }, - { 0x43, 7 }, - { 0xB, 9 }, - { 0x15, 10 }, - { 0x51, 12 }, - { 0x3, 4 }, - { 0x50, 12 }, - { 0xD, 4 }, - { 0xC, 4 }, - { 0x4, 4 }, - { 0x6, 4 }, - { 0xE, 4 }, - { 0xA, 4 }, - { 0x1, 4 }, - { 0x1E, 5 }, - { 0x5, 4 }, - { 0x9, 4 }, - { 0x7, 4 }, - { 0x11, 5 }, - { 0x2, 6 }, - { 0x4, 8 }, - { 0x2, 4 }, - { 0x2D, 6 }, - { 0x20, 6 }, - { 0x42, 7 }, - { 0x1, 7 }, - { 0x0, 7 }, - { 0x29, 11 }, - { 0x17, 5 }, - { 0x2C, 6 } - }, - { /* AC bias group 1, table 4 */ - { 0x3, 4 }, - { 0x1F, 6 }, - { 0x3A, 7 }, - { 0x5D, 7 }, - { 0x173, 9 }, - { 0x2E4, 10 }, - { 0x172D, 13 }, - { 0x4, 4 }, - { 0x172C, 13 }, - { 0xF, 4 }, - { 0xE, 4 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0xC, 4 }, - { 0xA, 4 }, - { 0x1, 4 }, - { 0x16, 5 }, - { 0x2, 4 }, - { 0x5, 4 }, - { 0x1A, 5 }, - { 0x2F, 6 }, - { 0x38, 7 }, - { 0x5CA, 11 }, - { 0x6, 4 }, - { 0x37, 6 }, - { 0x1E, 6 }, - { 0x3B, 7 }, - { 0x39, 7 }, - { 0xB8, 8 }, - { 0xB97, 12 }, - { 0x0, 4 }, - { 0x36, 6 } - }, - { /* AC bias group 1, table 5 */ - { 0x6, 4 }, - { 0x37, 6 }, - { 0x5D, 7 }, - { 0xC, 6 }, - { 0xB9, 8 }, - { 0x2E3, 10 }, - { 0x5C4, 11 }, - { 0x4, 4 }, - { 0x1715, 13 }, - { 0x0, 3 }, - { 0xF, 4 }, - { 0x8, 4 }, - { 0x7, 4 }, - { 0xC, 4 }, - { 0x9, 4 }, - { 0x1D, 5 }, - { 0x16, 5 }, - { 0x1C, 5 }, - { 0x1A, 5 }, - { 0xB, 5 }, - { 0x5E, 7 }, - { 0x170, 9 }, - { 0x1714, 13 }, - { 0xA, 4 }, - { 0xA, 5 }, - { 0x36, 6 }, - { 0x5F, 7 }, - { 0x1B, 7 }, - { 0x1A, 7 }, - { 0xB8B, 12 }, - { 0x2, 4 }, - { 0x7, 5 } - }, - { /* AC bias group 1, table 6 */ - { 0xC, 4 }, - { 0xB, 5 }, - { 0x79, 7 }, - { 0x22, 6 }, - { 0xF0, 8 }, - { 0x119, 9 }, - { 0x230, 10 }, - { 0x1D, 5 }, - { 0x8C4, 12 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xA, 4 }, - { 0x9, 4 }, - { 0xB, 4 }, - { 0x7, 4 }, - { 0x1C, 5 }, - { 0x3D, 6 }, - { 0xD, 5 }, - { 0x8, 5 }, - { 0x15, 6 }, - { 0x8D, 8 }, - { 0x118B, 13 }, - { 0x118A, 13 }, - { 0xD, 4 }, - { 0x10, 5 }, - { 0x9, 5 }, - { 0x14, 6 }, - { 0x47, 7 }, - { 0xF1, 8 }, - { 0x463, 11 }, - { 0x1F, 5 }, - { 0xC, 5 } - }, - { /* AC bias group 1, table 7 */ - { 0x0, 3 }, - { 0x1A, 5 }, - { 0x33, 6 }, - { 0xC, 5 }, - { 0x46, 7 }, - { 0x1E3, 9 }, - { 0x3C5, 10 }, - { 0x17, 5 }, - { 0x1E21, 13 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x9, 4 }, - { 0xA, 4 }, - { 0x7, 4 }, - { 0x1B, 5 }, - { 0x3D, 6 }, - { 0x1B, 6 }, - { 0x22, 6 }, - { 0x79, 7 }, - { 0xF0, 8 }, - { 0x1E20, 13 }, - { 0x1E23, 13 }, - { 0x1E22, 13 }, - { 0xE, 4 }, - { 0x16, 5 }, - { 0x18, 5 }, - { 0x32, 6 }, - { 0x1A, 6 }, - { 0x47, 7 }, - { 0x789, 11 }, - { 0x1F, 5 }, - { 0x10, 5 } - }, - { /* AC bias group 1, table 8 */ - { 0x1D, 5 }, - { 0x61, 7 }, - { 0x4E, 8 }, - { 0x9E, 9 }, - { 0x27C, 11 }, - { 0x9F5, 13 }, - { 0x9F4, 13 }, - { 0x3, 4 }, - { 0x60, 7 }, - { 0x0, 3 }, - { 0xF, 4 }, - { 0xB, 4 }, - { 0xA, 4 }, - { 0x9, 4 }, - { 0x5, 4 }, - { 0xD, 5 }, - { 0x31, 6 }, - { 0x8, 5 }, - { 0x38, 6 }, - { 0x12, 6 }, - { 0x26, 7 }, - { 0x13F, 10 }, - { 0x4FB, 12 }, - { 0xD, 4 }, - { 0x2, 4 }, - { 0xC, 5 }, - { 0x39, 6 }, - { 0x1C, 6 }, - { 0xF, 5 }, - { 0x1D, 6 }, - { 0x8, 4 }, - { 0x19, 5 } - }, - { /* AC bias group 1, table 9 */ - { 0x7, 4 }, - { 0x19, 6 }, - { 0xAB, 8 }, - { 0xAA, 8 }, - { 0x119, 10 }, - { 0x461, 12 }, - { 0x460, 12 }, - { 0x1B, 5 }, - { 0x47, 8 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xC, 4 }, - { 0xB, 4 }, - { 0x9, 4 }, - { 0x5, 4 }, - { 0xD, 5 }, - { 0x35, 6 }, - { 0x3D, 6 }, - { 0x3C, 6 }, - { 0x18, 6 }, - { 0x22, 7 }, - { 0x8D, 9 }, - { 0x231, 11 }, - { 0xE, 4 }, - { 0x1F, 5 }, - { 0x9, 5 }, - { 0x2B, 6 }, - { 0x10, 6 }, - { 0x34, 6 }, - { 0x54, 7 }, - { 0x8, 4 }, - { 0x14, 5 } - }, - { /* AC bias group 1, table 10 */ - { 0xC, 4 }, - { 0x5, 5 }, - { 0x8, 6 }, - { 0x5B, 7 }, - { 0x4D, 9 }, - { 0x131, 11 }, - { 0x261, 12 }, - { 0x1A, 5 }, - { 0x12, 7 }, - { 0x0, 3 }, - { 0xF, 4 }, - { 0xA, 4 }, - { 0x9, 4 }, - { 0x6, 4 }, - { 0x1B, 5 }, - { 0x6, 5 }, - { 0x1C, 6 }, - { 0x2C, 6 }, - { 0x15, 6 }, - { 0x5A, 7 }, - { 0x27, 8 }, - { 0x99, 10 }, - { 0x260, 12 }, - { 0xE, 4 }, - { 0x4, 4 }, - { 0xF, 5 }, - { 0x7, 5 }, - { 0x1D, 6 }, - { 0xB, 5 }, - { 0x14, 6 }, - { 0x8, 4 }, - { 0x17, 5 } - }, - { /* AC bias group 1, table 11 */ - { 0xF, 4 }, - { 0x13, 5 }, - { 0x75, 7 }, - { 0x24, 6 }, - { 0x95, 8 }, - { 0x251, 10 }, - { 0x4A0, 11 }, - { 0x10, 5 }, - { 0xC8, 8 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x1, 4 }, - { 0x0, 4 }, - { 0x1A, 5 }, - { 0x11, 5 }, - { 0x2C, 6 }, - { 0x65, 7 }, - { 0x74, 7 }, - { 0x4B, 7 }, - { 0xC9, 8 }, - { 0x129, 9 }, - { 0x943, 12 }, - { 0x942, 12 }, - { 0x3, 3 }, - { 0xA, 4 }, - { 0x1C, 5 }, - { 0x18, 5 }, - { 0x33, 6 }, - { 0x17, 5 }, - { 0x2D, 6 }, - { 0x1B, 5 }, - { 0x3B, 6 } - }, - { /* AC bias group 1, table 12 */ - { 0x3, 3 }, - { 0x1A, 5 }, - { 0x2D, 6 }, - { 0x38, 6 }, - { 0x28, 7 }, - { 0x395, 10 }, - { 0xE51, 12 }, - { 0x37, 6 }, - { 0xE4, 8 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0x1F, 5 }, - { 0x1E, 5 }, - { 0x17, 5 }, - { 0x3A, 6 }, - { 0x73, 7 }, - { 0x2A, 7 }, - { 0x2B, 7 }, - { 0x29, 7 }, - { 0x1CB, 9 }, - { 0x729, 11 }, - { 0x1CA1, 13 }, - { 0x1CA0, 13 }, - { 0x4, 3 }, - { 0xA, 4 }, - { 0x4, 4 }, - { 0x18, 5 }, - { 0x36, 6 }, - { 0xB, 5 }, - { 0x2C, 6 }, - { 0x19, 5 }, - { 0x3B, 6 } - }, - { /* AC bias group 1, table 13 */ - { 0x4, 3 }, - { 0x4, 4 }, - { 0x3F, 6 }, - { 0x17, 5 }, - { 0x75, 7 }, - { 0x1F5, 9 }, - { 0x7D1, 11 }, - { 0x17, 6 }, - { 0x1F6, 9 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0x1B, 5 }, - { 0x1A, 5 }, - { 0xA, 5 }, - { 0x32, 6 }, - { 0x74, 7 }, - { 0xF8, 8 }, - { 0xF9, 8 }, - { 0x1F7, 9 }, - { 0x3E9, 10 }, - { 0xFA0, 12 }, - { 0x1F43, 13 }, - { 0x1F42, 13 }, - { 0x3, 3 }, - { 0xA, 4 }, - { 0x1E, 5 }, - { 0x1C, 5 }, - { 0x3B, 6 }, - { 0x18, 5 }, - { 0x16, 6 }, - { 0x16, 5 }, - { 0x33, 6 } - }, - { /* AC bias group 1, table 14 */ - { 0x4, 3 }, - { 0x7, 4 }, - { 0x18, 5 }, - { 0x1E, 5 }, - { 0x36, 6 }, - { 0x31, 7 }, - { 0x177, 9 }, - { 0x77, 7 }, - { 0x176, 9 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0x1A, 5 }, - { 0x19, 5 }, - { 0x3A, 6 }, - { 0x19, 6 }, - { 0x5C, 7 }, - { 0xBA, 8 }, - { 0x61, 8 }, - { 0xC1, 9 }, - { 0x180, 10 }, - { 0x302, 11 }, - { 0x607, 12 }, - { 0x606, 12 }, - { 0x2, 3 }, - { 0xA, 4 }, - { 0x1F, 5 }, - { 0x1C, 5 }, - { 0x37, 6 }, - { 0x16, 5 }, - { 0x76, 7 }, - { 0xD, 5 }, - { 0x2F, 6 } - }, - { /* AC bias group 1, table 15 */ - { 0x0, 3 }, - { 0xA, 4 }, - { 0x1A, 5 }, - { 0xC, 4 }, - { 0x1D, 5 }, - { 0x39, 6 }, - { 0x78, 7 }, - { 0x5E, 7 }, - { 0x393, 11 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x16, 5 }, - { 0xF, 5 }, - { 0x2E, 6 }, - { 0x5F, 7 }, - { 0x73, 8 }, - { 0xE5, 9 }, - { 0x1C8, 10 }, - { 0xE4A, 13 }, - { 0x1C97, 14 }, - { 0x1C96, 14 }, - { 0xE49, 13 }, - { 0xE48, 13 }, - { 0x4, 3 }, - { 0x6, 4 }, - { 0x1F, 5 }, - { 0x1B, 5 }, - { 0x1D, 6 }, - { 0x38, 6 }, - { 0x38, 7 }, - { 0x3D, 6 }, - { 0x79, 7 } - } + { /* AC bias group 1, table 0 */ + { 0x8, 5 }, + { 0x25, 7 }, + { 0x17A, 9 }, + { 0x2F7, 10 }, + { 0xBDB, 12 }, + { 0x17B4, 13 }, + { 0x2F6B, 14 }, + { 0x1D, 5 }, + { 0x2F6A, 14 }, + { 0x8, 4 }, + { 0x7, 4 }, + { 0x1, 4 }, + { 0x2, 4 }, + { 0xA, 4 }, + { 0x6, 4 }, + { 0x0, 4 }, + { 0x1C, 5 }, + { 0x9, 4 }, + { 0xD, 4 }, + { 0xF, 4 }, + { 0xC, 4 }, + { 0x3, 4 }, + { 0xA, 5 }, + { 0x16, 5 }, + { 0x13, 6 }, + { 0x5D, 7 }, + { 0x24, 7 }, + { 0xBC, 8 }, + { 0x5C, 7 }, + { 0x5EC, 11 }, + { 0xB, 5 }, + { 0x5F, 7 } + }, + { /* AC bias group 1, table 1 */ + { 0xF, 5 }, + { 0x10, 6 }, + { 0x4B, 8 }, + { 0xC6, 8 }, + { 0x31D, 10 }, + { 0xC71, 12 }, + { 0xC70, 12 }, + { 0x1, 4 }, + { 0xC73, 12 }, + { 0x8, 4 }, + { 0x9, 4 }, + { 0x2, 4 }, + { 0x3, 4 }, + { 0xB, 4 }, + { 0x6, 4 }, + { 0x0, 4 }, + { 0x1C, 5 }, + { 0x5, 4 }, + { 0xD, 4 }, + { 0xF, 4 }, + { 0xA, 4 }, + { 0x19, 5 }, + { 0x13, 6 }, + { 0x1D, 5 }, + { 0x30, 6 }, + { 0x62, 7 }, + { 0x24, 7 }, + { 0x4A, 8 }, + { 0x18F, 9 }, + { 0xC72, 12 }, + { 0xE, 5 }, + { 0x11, 6 } + }, + { /* AC bias group 1, table 2 */ + { 0x1B, 5 }, + { 0x3, 6 }, + { 0x8D, 8 }, + { 0x40, 7 }, + { 0x239, 10 }, + { 0x471, 11 }, + { 0x8E0, 12 }, + { 0x3, 4 }, + { 0x11C3, 13 }, + { 0xA, 4 }, + { 0x9, 4 }, + { 0x4, 4 }, + { 0x5, 4 }, + { 0xE, 4 }, + { 0x7, 4 }, + { 0x1, 4 }, + { 0x1E, 5 }, + { 0x6, 4 }, + { 0xC, 4 }, + { 0xB, 4 }, + { 0x2, 4 }, + { 0x0, 5 }, + { 0x41, 7 }, + { 0x1F, 5 }, + { 0x22, 6 }, + { 0x2, 6 }, + { 0x8F, 8 }, + { 0x8C, 8 }, + { 0x11D, 9 }, + { 0x11C2, 13 }, + { 0x1A, 5 }, + { 0x21, 6 } + }, + { /* AC bias group 1, table 3 */ + { 0x1F, 5 }, + { 0x3, 6 }, + { 0x3, 7 }, + { 0x43, 7 }, + { 0xB, 9 }, + { 0x15, 10 }, + { 0x51, 12 }, + { 0x3, 4 }, + { 0x50, 12 }, + { 0xD, 4 }, + { 0xC, 4 }, + { 0x4, 4 }, + { 0x6, 4 }, + { 0xE, 4 }, + { 0xA, 4 }, + { 0x1, 4 }, + { 0x1E, 5 }, + { 0x5, 4 }, + { 0x9, 4 }, + { 0x7, 4 }, + { 0x11, 5 }, + { 0x2, 6 }, + { 0x4, 8 }, + { 0x2, 4 }, + { 0x2D, 6 }, + { 0x20, 6 }, + { 0x42, 7 }, + { 0x1, 7 }, + { 0x0, 7 }, + { 0x29, 11 }, + { 0x17, 5 }, + { 0x2C, 6 } + }, + { /* AC bias group 1, table 4 */ + { 0x3, 4 }, + { 0x1F, 6 }, + { 0x3A, 7 }, + { 0x5D, 7 }, + { 0x173, 9 }, + { 0x2E4, 10 }, + { 0x172D, 13 }, + { 0x4, 4 }, + { 0x172C, 13 }, + { 0xF, 4 }, + { 0xE, 4 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0xC, 4 }, + { 0xA, 4 }, + { 0x1, 4 }, + { 0x16, 5 }, + { 0x2, 4 }, + { 0x5, 4 }, + { 0x1A, 5 }, + { 0x2F, 6 }, + { 0x38, 7 }, + { 0x5CA, 11 }, + { 0x6, 4 }, + { 0x37, 6 }, + { 0x1E, 6 }, + { 0x3B, 7 }, + { 0x39, 7 }, + { 0xB8, 8 }, + { 0xB97, 12 }, + { 0x0, 4 }, + { 0x36, 6 } + }, + { /* AC bias group 1, table 5 */ + { 0x6, 4 }, + { 0x37, 6 }, + { 0x5D, 7 }, + { 0xC, 6 }, + { 0xB9, 8 }, + { 0x2E3, 10 }, + { 0x5C4, 11 }, + { 0x4, 4 }, + { 0x1715, 13 }, + { 0x0, 3 }, + { 0xF, 4 }, + { 0x8, 4 }, + { 0x7, 4 }, + { 0xC, 4 }, + { 0x9, 4 }, + { 0x1D, 5 }, + { 0x16, 5 }, + { 0x1C, 5 }, + { 0x1A, 5 }, + { 0xB, 5 }, + { 0x5E, 7 }, + { 0x170, 9 }, + { 0x1714, 13 }, + { 0xA, 4 }, + { 0xA, 5 }, + { 0x36, 6 }, + { 0x5F, 7 }, + { 0x1B, 7 }, + { 0x1A, 7 }, + { 0xB8B, 12 }, + { 0x2, 4 }, + { 0x7, 5 } + }, + { /* AC bias group 1, table 6 */ + { 0xC, 4 }, + { 0xB, 5 }, + { 0x79, 7 }, + { 0x22, 6 }, + { 0xF0, 8 }, + { 0x119, 9 }, + { 0x230, 10 }, + { 0x1D, 5 }, + { 0x8C4, 12 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xA, 4 }, + { 0x9, 4 }, + { 0xB, 4 }, + { 0x7, 4 }, + { 0x1C, 5 }, + { 0x3D, 6 }, + { 0xD, 5 }, + { 0x8, 5 }, + { 0x15, 6 }, + { 0x8D, 8 }, + { 0x118B, 13 }, + { 0x118A, 13 }, + { 0xD, 4 }, + { 0x10, 5 }, + { 0x9, 5 }, + { 0x14, 6 }, + { 0x47, 7 }, + { 0xF1, 8 }, + { 0x463, 11 }, + { 0x1F, 5 }, + { 0xC, 5 } + }, + { /* AC bias group 1, table 7 */ + { 0x0, 3 }, + { 0x1A, 5 }, + { 0x33, 6 }, + { 0xC, 5 }, + { 0x46, 7 }, + { 0x1E3, 9 }, + { 0x3C5, 10 }, + { 0x17, 5 }, + { 0x1E21, 13 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x9, 4 }, + { 0xA, 4 }, + { 0x7, 4 }, + { 0x1B, 5 }, + { 0x3D, 6 }, + { 0x1B, 6 }, + { 0x22, 6 }, + { 0x79, 7 }, + { 0xF0, 8 }, + { 0x1E20, 13 }, + { 0x1E23, 13 }, + { 0x1E22, 13 }, + { 0xE, 4 }, + { 0x16, 5 }, + { 0x18, 5 }, + { 0x32, 6 }, + { 0x1A, 6 }, + { 0x47, 7 }, + { 0x789, 11 }, + { 0x1F, 5 }, + { 0x10, 5 } + }, + { /* AC bias group 1, table 8 */ + { 0x1D, 5 }, + { 0x61, 7 }, + { 0x4E, 8 }, + { 0x9E, 9 }, + { 0x27C, 11 }, + { 0x9F5, 13 }, + { 0x9F4, 13 }, + { 0x3, 4 }, + { 0x60, 7 }, + { 0x0, 3 }, + { 0xF, 4 }, + { 0xB, 4 }, + { 0xA, 4 }, + { 0x9, 4 }, + { 0x5, 4 }, + { 0xD, 5 }, + { 0x31, 6 }, + { 0x8, 5 }, + { 0x38, 6 }, + { 0x12, 6 }, + { 0x26, 7 }, + { 0x13F, 10 }, + { 0x4FB, 12 }, + { 0xD, 4 }, + { 0x2, 4 }, + { 0xC, 5 }, + { 0x39, 6 }, + { 0x1C, 6 }, + { 0xF, 5 }, + { 0x1D, 6 }, + { 0x8, 4 }, + { 0x19, 5 } + }, + { /* AC bias group 1, table 9 */ + { 0x7, 4 }, + { 0x19, 6 }, + { 0xAB, 8 }, + { 0xAA, 8 }, + { 0x119, 10 }, + { 0x461, 12 }, + { 0x460, 12 }, + { 0x1B, 5 }, + { 0x47, 8 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xC, 4 }, + { 0xB, 4 }, + { 0x9, 4 }, + { 0x5, 4 }, + { 0xD, 5 }, + { 0x35, 6 }, + { 0x3D, 6 }, + { 0x3C, 6 }, + { 0x18, 6 }, + { 0x22, 7 }, + { 0x8D, 9 }, + { 0x231, 11 }, + { 0xE, 4 }, + { 0x1F, 5 }, + { 0x9, 5 }, + { 0x2B, 6 }, + { 0x10, 6 }, + { 0x34, 6 }, + { 0x54, 7 }, + { 0x8, 4 }, + { 0x14, 5 } + }, + { /* AC bias group 1, table 10 */ + { 0xC, 4 }, + { 0x5, 5 }, + { 0x8, 6 }, + { 0x5B, 7 }, + { 0x4D, 9 }, + { 0x131, 11 }, + { 0x261, 12 }, + { 0x1A, 5 }, + { 0x12, 7 }, + { 0x0, 3 }, + { 0xF, 4 }, + { 0xA, 4 }, + { 0x9, 4 }, + { 0x6, 4 }, + { 0x1B, 5 }, + { 0x6, 5 }, + { 0x1C, 6 }, + { 0x2C, 6 }, + { 0x15, 6 }, + { 0x5A, 7 }, + { 0x27, 8 }, + { 0x99, 10 }, + { 0x260, 12 }, + { 0xE, 4 }, + { 0x4, 4 }, + { 0xF, 5 }, + { 0x7, 5 }, + { 0x1D, 6 }, + { 0xB, 5 }, + { 0x14, 6 }, + { 0x8, 4 }, + { 0x17, 5 } + }, + { /* AC bias group 1, table 11 */ + { 0xF, 4 }, + { 0x13, 5 }, + { 0x75, 7 }, + { 0x24, 6 }, + { 0x95, 8 }, + { 0x251, 10 }, + { 0x4A0, 11 }, + { 0x10, 5 }, + { 0xC8, 8 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x1, 4 }, + { 0x0, 4 }, + { 0x1A, 5 }, + { 0x11, 5 }, + { 0x2C, 6 }, + { 0x65, 7 }, + { 0x74, 7 }, + { 0x4B, 7 }, + { 0xC9, 8 }, + { 0x129, 9 }, + { 0x943, 12 }, + { 0x942, 12 }, + { 0x3, 3 }, + { 0xA, 4 }, + { 0x1C, 5 }, + { 0x18, 5 }, + { 0x33, 6 }, + { 0x17, 5 }, + { 0x2D, 6 }, + { 0x1B, 5 }, + { 0x3B, 6 } + }, + { /* AC bias group 1, table 12 */ + { 0x3, 3 }, + { 0x1A, 5 }, + { 0x2D, 6 }, + { 0x38, 6 }, + { 0x28, 7 }, + { 0x395, 10 }, + { 0xE51, 12 }, + { 0x37, 6 }, + { 0xE4, 8 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0x1F, 5 }, + { 0x1E, 5 }, + { 0x17, 5 }, + { 0x3A, 6 }, + { 0x73, 7 }, + { 0x2A, 7 }, + { 0x2B, 7 }, + { 0x29, 7 }, + { 0x1CB, 9 }, + { 0x729, 11 }, + { 0x1CA1, 13 }, + { 0x1CA0, 13 }, + { 0x4, 3 }, + { 0xA, 4 }, + { 0x4, 4 }, + { 0x18, 5 }, + { 0x36, 6 }, + { 0xB, 5 }, + { 0x2C, 6 }, + { 0x19, 5 }, + { 0x3B, 6 } + }, + { /* AC bias group 1, table 13 */ + { 0x4, 3 }, + { 0x4, 4 }, + { 0x3F, 6 }, + { 0x17, 5 }, + { 0x75, 7 }, + { 0x1F5, 9 }, + { 0x7D1, 11 }, + { 0x17, 6 }, + { 0x1F6, 9 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0x1B, 5 }, + { 0x1A, 5 }, + { 0xA, 5 }, + { 0x32, 6 }, + { 0x74, 7 }, + { 0xF8, 8 }, + { 0xF9, 8 }, + { 0x1F7, 9 }, + { 0x3E9, 10 }, + { 0xFA0, 12 }, + { 0x1F43, 13 }, + { 0x1F42, 13 }, + { 0x3, 3 }, + { 0xA, 4 }, + { 0x1E, 5 }, + { 0x1C, 5 }, + { 0x3B, 6 }, + { 0x18, 5 }, + { 0x16, 6 }, + { 0x16, 5 }, + { 0x33, 6 } + }, + { /* AC bias group 1, table 14 */ + { 0x4, 3 }, + { 0x7, 4 }, + { 0x18, 5 }, + { 0x1E, 5 }, + { 0x36, 6 }, + { 0x31, 7 }, + { 0x177, 9 }, + { 0x77, 7 }, + { 0x176, 9 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0x1A, 5 }, + { 0x19, 5 }, + { 0x3A, 6 }, + { 0x19, 6 }, + { 0x5C, 7 }, + { 0xBA, 8 }, + { 0x61, 8 }, + { 0xC1, 9 }, + { 0x180, 10 }, + { 0x302, 11 }, + { 0x607, 12 }, + { 0x606, 12 }, + { 0x2, 3 }, + { 0xA, 4 }, + { 0x1F, 5 }, + { 0x1C, 5 }, + { 0x37, 6 }, + { 0x16, 5 }, + { 0x76, 7 }, + { 0xD, 5 }, + { 0x2F, 6 } + }, + { /* AC bias group 1, table 15 */ + { 0x0, 3 }, + { 0xA, 4 }, + { 0x1A, 5 }, + { 0xC, 4 }, + { 0x1D, 5 }, + { 0x39, 6 }, + { 0x78, 7 }, + { 0x5E, 7 }, + { 0x393, 11 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x16, 5 }, + { 0xF, 5 }, + { 0x2E, 6 }, + { 0x5F, 7 }, + { 0x73, 8 }, + { 0xE5, 9 }, + { 0x1C8, 10 }, + { 0xE4A, 13 }, + { 0x1C97, 14 }, + { 0x1C96, 14 }, + { 0xE49, 13 }, + { 0xE48, 13 }, + { 0x4, 3 }, + { 0x6, 4 }, + { 0x1F, 5 }, + { 0x1B, 5 }, + { 0x1D, 6 }, + { 0x38, 6 }, + { 0x38, 7 }, + { 0x3D, 6 }, + { 0x79, 7 } + } }; static const uint16_t ac_bias_1[16][32][2] = { - { /* AC bias group 2, table 0 */ - { 0xB, 5 }, - { 0x2B, 7 }, - { 0x54, 8 }, - { 0x1B7, 9 }, - { 0x6D9, 11 }, - { 0xDB1, 12 }, - { 0xDB0, 12 }, - { 0x2, 4 }, - { 0xAB, 9 }, - { 0x9, 4 }, - { 0xA, 4 }, - { 0x7, 4 }, - { 0x8, 4 }, - { 0xF, 4 }, - { 0xC, 4 }, - { 0x3, 4 }, - { 0x1D, 5 }, - { 0x4, 4 }, - { 0xB, 4 }, - { 0x6, 4 }, - { 0x1A, 5 }, - { 0x3, 6 }, - { 0xAA, 9 }, - { 0x1, 4 }, - { 0x0, 5 }, - { 0x14, 6 }, - { 0x6C, 7 }, - { 0xDA, 8 }, - { 0x2, 6 }, - { 0x36D, 10 }, - { 0x1C, 5 }, - { 0x37, 6 } - }, - { /* AC bias group 2, table 1 */ - { 0x1D, 5 }, - { 0x4, 6 }, - { 0xB6, 8 }, - { 0x6A, 8 }, - { 0x5B9, 11 }, - { 0x16E1, 13 }, - { 0x16E0, 13 }, - { 0x7, 4 }, - { 0x16F, 9 }, - { 0xC, 4 }, - { 0xD, 4 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0xF, 4 }, - { 0xA, 4 }, - { 0x3, 4 }, - { 0x17, 5 }, - { 0x2, 4 }, - { 0x4, 4 }, - { 0x1C, 5 }, - { 0x2C, 6 }, - { 0x6B, 8 }, - { 0xB71, 12 }, - { 0x5, 4 }, - { 0x3, 5 }, - { 0x1B, 6 }, - { 0x5A, 7 }, - { 0x34, 7 }, - { 0x5, 6 }, - { 0x2DD, 10 }, - { 0x0, 4 }, - { 0xC, 5 } - }, - { /* AC bias group 2, table 2 */ - { 0x3, 4 }, - { 0x7F, 7 }, - { 0xA1, 8 }, - { 0xA0, 8 }, - { 0x20C, 10 }, - { 0x834, 12 }, - { 0x106B, 13 }, - { 0x7, 4 }, - { 0x82, 8 }, - { 0xE, 4 }, - { 0xD, 4 }, - { 0xB, 4 }, - { 0xC, 4 }, - { 0x0, 3 }, - { 0x9, 4 }, - { 0x2, 4 }, - { 0x11, 5 }, - { 0x1E, 5 }, - { 0x15, 5 }, - { 0x3E, 6 }, - { 0x40, 7 }, - { 0x41B, 11 }, - { 0x106A, 13 }, - { 0x6, 4 }, - { 0xA, 5 }, - { 0x29, 6 }, - { 0x7E, 7 }, - { 0x51, 7 }, - { 0x21, 6 }, - { 0x107, 9 }, - { 0x4, 4 }, - { 0xB, 5 } - }, - { /* AC bias group 2, table 3 */ - { 0x7, 4 }, - { 0x1B, 6 }, - { 0xF6, 8 }, - { 0xE9, 8 }, - { 0x3A1, 10 }, - { 0x740, 11 }, - { 0xE82, 12 }, - { 0x1F, 5 }, - { 0x1EF, 9 }, - { 0x1, 3 }, - { 0x2, 3 }, - { 0xB, 4 }, - { 0xC, 4 }, - { 0xD, 4 }, - { 0x8, 4 }, - { 0x1C, 5 }, - { 0x3, 5 }, - { 0x12, 5 }, - { 0x2, 5 }, - { 0x75, 7 }, - { 0x1D1, 9 }, - { 0x1D07, 13 }, - { 0x1D06, 13 }, - { 0xA, 4 }, - { 0x13, 5 }, - { 0x3B, 6 }, - { 0x1A, 6 }, - { 0x7A, 7 }, - { 0x3C, 6 }, - { 0x1EE, 9 }, - { 0x0, 4 }, - { 0xC, 5 } - }, - { /* AC bias group 2, table 4 */ - { 0xD, 4 }, - { 0x3D, 6 }, - { 0x42, 7 }, - { 0x37, 7 }, - { 0xD9, 9 }, - { 0x362, 11 }, - { 0x6C6, 12 }, - { 0x1F, 5 }, - { 0x86, 8 }, - { 0x1, 3 }, - { 0x2, 3 }, - { 0xC, 4 }, - { 0xB, 4 }, - { 0xA, 4 }, - { 0x1, 4 }, - { 0xF, 5 }, - { 0x25, 6 }, - { 0x3C, 6 }, - { 0x1A, 6 }, - { 0x87, 8 }, - { 0x1B0, 10 }, - { 0xD8F, 13 }, - { 0xD8E, 13 }, - { 0xE, 4 }, - { 0x13, 5 }, - { 0xC, 5 }, - { 0x24, 6 }, - { 0x20, 6 }, - { 0x11, 5 }, - { 0x6D, 8 }, - { 0x0, 4 }, - { 0xE, 5 } - }, - { /* AC bias group 2, table 5 */ - { 0x0, 3 }, - { 0x12, 5 }, - { 0x76, 7 }, - { 0x77, 7 }, - { 0x14D, 9 }, - { 0x533, 11 }, - { 0x14C9, 13 }, - { 0x13, 5 }, - { 0xA5, 8 }, - { 0x2, 3 }, - { 0x3, 3 }, - { 0xB, 4 }, - { 0xC, 4 }, - { 0x8, 4 }, - { 0x1A, 5 }, - { 0x2B, 6 }, - { 0x75, 7 }, - { 0x74, 7 }, - { 0xA7, 8 }, - { 0x298, 10 }, - { 0x14C8, 13 }, - { 0x14CB, 13 }, - { 0x14CA, 13 }, - { 0xF, 4 }, - { 0x1C, 5 }, - { 0x7, 5 }, - { 0x2A, 6 }, - { 0x28, 6 }, - { 0x1B, 5 }, - { 0xA4, 8 }, - { 0x2, 4 }, - { 0x6, 5 } - }, - { /* AC bias group 2, table 6 */ - { 0x2, 3 }, - { 0x1A, 5 }, - { 0x2B, 6 }, - { 0x3A, 6 }, - { 0xED, 8 }, - { 0x283, 10 }, - { 0xA0A, 12 }, - { 0x4, 5 }, - { 0xA1, 8 }, - { 0x4, 3 }, - { 0x3, 3 }, - { 0xB, 4 }, - { 0xC, 4 }, - { 0x1F, 5 }, - { 0x6, 5 }, - { 0x77, 7 }, - { 0xA3, 8 }, - { 0xA2, 8 }, - { 0x140, 9 }, - { 0x1417, 13 }, - { 0x1416, 13 }, - { 0xA09, 12 }, - { 0xA08, 12 }, - { 0x0, 3 }, - { 0x1E, 5 }, - { 0x7, 5 }, - { 0x2A, 6 }, - { 0x29, 6 }, - { 0x1C, 5 }, - { 0xEC, 8 }, - { 0x1B, 5 }, - { 0x5, 5 } - }, - { /* AC bias group 2, table 7 */ - { 0x2, 3 }, - { 0x2, 4 }, - { 0x18, 5 }, - { 0x1D, 5 }, - { 0x35, 6 }, - { 0xE4, 8 }, - { 0x1CF, 11 }, - { 0x1D, 7 }, - { 0x72, 9 }, - { 0x4, 3 }, - { 0x5, 3 }, - { 0x6, 4 }, - { 0x7, 4 }, - { 0x6, 5 }, - { 0x73, 7 }, - { 0x38, 8 }, - { 0x1CE, 11 }, - { 0x39B, 12 }, - { 0x398, 12 }, - { 0x733, 13 }, - { 0x732, 13 }, - { 0x735, 13 }, - { 0x734, 13 }, - { 0x0, 3 }, - { 0x1F, 5 }, - { 0x1B, 5 }, - { 0x34, 6 }, - { 0xF, 6 }, - { 0x1E, 5 }, - { 0xE5, 8 }, - { 0x19, 5 }, - { 0x38, 6 } - }, - { /* AC bias group 2, table 8 */ - { 0x16, 5 }, - { 0x50, 7 }, - { 0x172, 9 }, - { 0x2E7, 10 }, - { 0x1732, 13 }, - { 0x2E67, 14 }, - { 0x2E66, 14 }, - { 0x6, 4 }, - { 0x51, 7 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xD, 4 }, - { 0xC, 4 }, - { 0x9, 4 }, - { 0x1C, 5 }, - { 0x9, 5 }, - { 0x1C, 6 }, - { 0x1D, 6 }, - { 0x5D, 7 }, - { 0xB8, 8 }, - { 0x5CD, 11 }, - { 0x1731, 13 }, - { 0x1730, 13 }, - { 0xF, 4 }, - { 0x5, 4 }, - { 0xF, 5 }, - { 0x8, 5 }, - { 0x29, 6 }, - { 0x1D, 5 }, - { 0x2F, 6 }, - { 0x8, 4 }, - { 0x15, 5 } - }, - { /* AC bias group 2, table 9 */ - { 0x9, 4 }, - { 0x21, 6 }, - { 0x40, 7 }, - { 0xAD, 8 }, - { 0x2B0, 10 }, - { 0x1589, 13 }, - { 0x1588, 13 }, - { 0x1C, 5 }, - { 0x5F, 7 }, - { 0x0, 3 }, - { 0xF, 4 }, - { 0xD, 4 }, - { 0xC, 4 }, - { 0x6, 4 }, - { 0x11, 5 }, - { 0x2A, 6 }, - { 0x57, 7 }, - { 0x5E, 7 }, - { 0x41, 7 }, - { 0x159, 9 }, - { 0x563, 11 }, - { 0x158B, 13 }, - { 0x158A, 13 }, - { 0x1, 3 }, - { 0x5, 4 }, - { 0x14, 5 }, - { 0x3B, 6 }, - { 0x2E, 6 }, - { 0x4, 4 }, - { 0x3A, 6 }, - { 0x7, 4 }, - { 0x16, 5 } - }, - { /* AC bias group 2, table 10 */ - { 0xE, 4 }, - { 0x7, 5 }, - { 0x46, 7 }, - { 0x45, 7 }, - { 0x64, 9 }, - { 0x32A, 12 }, - { 0x657, 13 }, - { 0x18, 5 }, - { 0xD, 6 }, - { 0x0, 3 }, - { 0xF, 4 }, - { 0xA, 4 }, - { 0xB, 4 }, - { 0x1A, 5 }, - { 0x36, 6 }, - { 0x47, 7 }, - { 0x44, 7 }, - { 0x18, 7 }, - { 0x33, 8 }, - { 0xCB, 10 }, - { 0x656, 13 }, - { 0x329, 12 }, - { 0x328, 12 }, - { 0x2, 3 }, - { 0x6, 4 }, - { 0x19, 5 }, - { 0xE, 5 }, - { 0x37, 6 }, - { 0x9, 4 }, - { 0xF, 5 }, - { 0x2, 4 }, - { 0x10, 5 } - }, - { /* AC bias group 2, table 11 */ - { 0x3, 3 }, - { 0x18, 5 }, - { 0x23, 6 }, - { 0x77, 7 }, - { 0x194, 9 }, - { 0x1956, 13 }, - { 0x32AF, 14 }, - { 0x3A, 6 }, - { 0x76, 7 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x1F, 5 }, - { 0x1E, 5 }, - { 0x14, 5 }, - { 0x22, 6 }, - { 0x64, 7 }, - { 0x197, 9 }, - { 0x196, 9 }, - { 0x32B, 10 }, - { 0x654, 11 }, - { 0x32AE, 14 }, - { 0x1955, 13 }, - { 0x1954, 13 }, - { 0x0, 3 }, - { 0x9, 4 }, - { 0x1C, 5 }, - { 0x15, 5 }, - { 0x10, 5 }, - { 0xD, 4 }, - { 0x17, 5 }, - { 0x16, 5 }, - { 0x33, 6 } - }, - { /* AC bias group 2, table 12 */ - { 0x5, 3 }, - { 0x6, 4 }, - { 0x3E, 6 }, - { 0x10, 5 }, - { 0x48, 7 }, - { 0x93F, 12 }, - { 0x24FA, 14 }, - { 0x32, 6 }, - { 0x67, 7 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x1B, 5 }, - { 0x1E, 5 }, - { 0x34, 6 }, - { 0x66, 7 }, - { 0x92, 8 }, - { 0x126, 9 }, - { 0x24E, 10 }, - { 0x49E, 11 }, - { 0x49F7, 15 }, - { 0x49F6, 15 }, - { 0x24F9, 14 }, - { 0x24F8, 14 }, - { 0x0, 3 }, - { 0x7, 4 }, - { 0x18, 5 }, - { 0x11, 5 }, - { 0x3F, 6 }, - { 0xE, 4 }, - { 0x13, 5 }, - { 0x35, 6 }, - { 0x25, 6 } - }, - { /* AC bias group 2, table 13 */ - { 0x5, 3 }, - { 0x8, 4 }, - { 0x12, 5 }, - { 0x1C, 5 }, - { 0x1C, 6 }, - { 0xEA, 9 }, - { 0x1D75, 14 }, - { 0x1E, 6 }, - { 0x66, 7 }, - { 0x1, 3 }, - { 0x2, 3 }, - { 0x1B, 5 }, - { 0x1A, 5 }, - { 0x1F, 6 }, - { 0x3B, 7 }, - { 0x74, 8 }, - { 0x1D6, 10 }, - { 0x3AF, 11 }, - { 0x1D74, 14 }, - { 0x1D77, 14 }, - { 0x1D76, 14 }, - { 0xEB9, 13 }, - { 0xEB8, 13 }, - { 0xF, 4 }, - { 0x6, 4 }, - { 0x13, 5 }, - { 0x3B, 6 }, - { 0x3A, 6 }, - { 0x0, 3 }, - { 0x18, 5 }, - { 0x32, 6 }, - { 0x67, 7 } - }, - { /* AC bias group 2, table 14 */ - { 0x4, 3 }, - { 0xA, 4 }, - { 0x1B, 5 }, - { 0xC, 4 }, - { 0xD, 5 }, - { 0xE6, 8 }, - { 0x684, 11 }, - { 0x72, 7 }, - { 0xE7, 8 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x17, 5 }, - { 0x16, 5 }, - { 0x18, 6 }, - { 0xD1, 8 }, - { 0x1A0, 9 }, - { 0x686, 11 }, - { 0xD0F, 12 }, - { 0xD0A, 12 }, - { 0x1A17, 13 }, - { 0x1A16, 13 }, - { 0x1A1D, 13 }, - { 0x1A1C, 13 }, - { 0xF, 4 }, - { 0x1D, 5 }, - { 0xE, 5 }, - { 0x35, 6 }, - { 0x38, 6 }, - { 0x0, 3 }, - { 0xF, 5 }, - { 0x19, 6 }, - { 0x69, 7 } - }, - { /* AC bias group 2, table 15 */ - { 0x3, 3 }, - { 0xC, 4 }, - { 0x1B, 5 }, - { 0x0, 3 }, - { 0x3, 4 }, - { 0x2E, 6 }, - { 0x51, 9 }, - { 0xBC, 8 }, - { 0x53, 9 }, - { 0x4, 3 }, - { 0x2, 3 }, - { 0x16, 5 }, - { 0x15, 5 }, - { 0x15, 7 }, - { 0x50, 9 }, - { 0xA4, 10 }, - { 0x294, 12 }, - { 0x52B, 13 }, - { 0x52A, 13 }, - { 0x52D, 13 }, - { 0x52C, 13 }, - { 0x52F, 13 }, - { 0x52E, 13 }, - { 0xE, 4 }, - { 0x1A, 5 }, - { 0x4, 5 }, - { 0x28, 6 }, - { 0x29, 6 }, - { 0xF, 4 }, - { 0xB, 6 }, - { 0x5F, 7 }, - { 0xBD, 8 } - } + { /* AC bias group 2, table 0 */ + { 0xB, 5 }, + { 0x2B, 7 }, + { 0x54, 8 }, + { 0x1B7, 9 }, + { 0x6D9, 11 }, + { 0xDB1, 12 }, + { 0xDB0, 12 }, + { 0x2, 4 }, + { 0xAB, 9 }, + { 0x9, 4 }, + { 0xA, 4 }, + { 0x7, 4 }, + { 0x8, 4 }, + { 0xF, 4 }, + { 0xC, 4 }, + { 0x3, 4 }, + { 0x1D, 5 }, + { 0x4, 4 }, + { 0xB, 4 }, + { 0x6, 4 }, + { 0x1A, 5 }, + { 0x3, 6 }, + { 0xAA, 9 }, + { 0x1, 4 }, + { 0x0, 5 }, + { 0x14, 6 }, + { 0x6C, 7 }, + { 0xDA, 8 }, + { 0x2, 6 }, + { 0x36D, 10 }, + { 0x1C, 5 }, + { 0x37, 6 } + }, + { /* AC bias group 2, table 1 */ + { 0x1D, 5 }, + { 0x4, 6 }, + { 0xB6, 8 }, + { 0x6A, 8 }, + { 0x5B9, 11 }, + { 0x16E1, 13 }, + { 0x16E0, 13 }, + { 0x7, 4 }, + { 0x16F, 9 }, + { 0xC, 4 }, + { 0xD, 4 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0xF, 4 }, + { 0xA, 4 }, + { 0x3, 4 }, + { 0x17, 5 }, + { 0x2, 4 }, + { 0x4, 4 }, + { 0x1C, 5 }, + { 0x2C, 6 }, + { 0x6B, 8 }, + { 0xB71, 12 }, + { 0x5, 4 }, + { 0x3, 5 }, + { 0x1B, 6 }, + { 0x5A, 7 }, + { 0x34, 7 }, + { 0x5, 6 }, + { 0x2DD, 10 }, + { 0x0, 4 }, + { 0xC, 5 } + }, + { /* AC bias group 2, table 2 */ + { 0x3, 4 }, + { 0x7F, 7 }, + { 0xA1, 8 }, + { 0xA0, 8 }, + { 0x20C, 10 }, + { 0x834, 12 }, + { 0x106B, 13 }, + { 0x7, 4 }, + { 0x82, 8 }, + { 0xE, 4 }, + { 0xD, 4 }, + { 0xB, 4 }, + { 0xC, 4 }, + { 0x0, 3 }, + { 0x9, 4 }, + { 0x2, 4 }, + { 0x11, 5 }, + { 0x1E, 5 }, + { 0x15, 5 }, + { 0x3E, 6 }, + { 0x40, 7 }, + { 0x41B, 11 }, + { 0x106A, 13 }, + { 0x6, 4 }, + { 0xA, 5 }, + { 0x29, 6 }, + { 0x7E, 7 }, + { 0x51, 7 }, + { 0x21, 6 }, + { 0x107, 9 }, + { 0x4, 4 }, + { 0xB, 5 } + }, + { /* AC bias group 2, table 3 */ + { 0x7, 4 }, + { 0x1B, 6 }, + { 0xF6, 8 }, + { 0xE9, 8 }, + { 0x3A1, 10 }, + { 0x740, 11 }, + { 0xE82, 12 }, + { 0x1F, 5 }, + { 0x1EF, 9 }, + { 0x1, 3 }, + { 0x2, 3 }, + { 0xB, 4 }, + { 0xC, 4 }, + { 0xD, 4 }, + { 0x8, 4 }, + { 0x1C, 5 }, + { 0x3, 5 }, + { 0x12, 5 }, + { 0x2, 5 }, + { 0x75, 7 }, + { 0x1D1, 9 }, + { 0x1D07, 13 }, + { 0x1D06, 13 }, + { 0xA, 4 }, + { 0x13, 5 }, + { 0x3B, 6 }, + { 0x1A, 6 }, + { 0x7A, 7 }, + { 0x3C, 6 }, + { 0x1EE, 9 }, + { 0x0, 4 }, + { 0xC, 5 } + }, + { /* AC bias group 2, table 4 */ + { 0xD, 4 }, + { 0x3D, 6 }, + { 0x42, 7 }, + { 0x37, 7 }, + { 0xD9, 9 }, + { 0x362, 11 }, + { 0x6C6, 12 }, + { 0x1F, 5 }, + { 0x86, 8 }, + { 0x1, 3 }, + { 0x2, 3 }, + { 0xC, 4 }, + { 0xB, 4 }, + { 0xA, 4 }, + { 0x1, 4 }, + { 0xF, 5 }, + { 0x25, 6 }, + { 0x3C, 6 }, + { 0x1A, 6 }, + { 0x87, 8 }, + { 0x1B0, 10 }, + { 0xD8F, 13 }, + { 0xD8E, 13 }, + { 0xE, 4 }, + { 0x13, 5 }, + { 0xC, 5 }, + { 0x24, 6 }, + { 0x20, 6 }, + { 0x11, 5 }, + { 0x6D, 8 }, + { 0x0, 4 }, + { 0xE, 5 } + }, + { /* AC bias group 2, table 5 */ + { 0x0, 3 }, + { 0x12, 5 }, + { 0x76, 7 }, + { 0x77, 7 }, + { 0x14D, 9 }, + { 0x533, 11 }, + { 0x14C9, 13 }, + { 0x13, 5 }, + { 0xA5, 8 }, + { 0x2, 3 }, + { 0x3, 3 }, + { 0xB, 4 }, + { 0xC, 4 }, + { 0x8, 4 }, + { 0x1A, 5 }, + { 0x2B, 6 }, + { 0x75, 7 }, + { 0x74, 7 }, + { 0xA7, 8 }, + { 0x298, 10 }, + { 0x14C8, 13 }, + { 0x14CB, 13 }, + { 0x14CA, 13 }, + { 0xF, 4 }, + { 0x1C, 5 }, + { 0x7, 5 }, + { 0x2A, 6 }, + { 0x28, 6 }, + { 0x1B, 5 }, + { 0xA4, 8 }, + { 0x2, 4 }, + { 0x6, 5 } + }, + { /* AC bias group 2, table 6 */ + { 0x2, 3 }, + { 0x1A, 5 }, + { 0x2B, 6 }, + { 0x3A, 6 }, + { 0xED, 8 }, + { 0x283, 10 }, + { 0xA0A, 12 }, + { 0x4, 5 }, + { 0xA1, 8 }, + { 0x4, 3 }, + { 0x3, 3 }, + { 0xB, 4 }, + { 0xC, 4 }, + { 0x1F, 5 }, + { 0x6, 5 }, + { 0x77, 7 }, + { 0xA3, 8 }, + { 0xA2, 8 }, + { 0x140, 9 }, + { 0x1417, 13 }, + { 0x1416, 13 }, + { 0xA09, 12 }, + { 0xA08, 12 }, + { 0x0, 3 }, + { 0x1E, 5 }, + { 0x7, 5 }, + { 0x2A, 6 }, + { 0x29, 6 }, + { 0x1C, 5 }, + { 0xEC, 8 }, + { 0x1B, 5 }, + { 0x5, 5 } + }, + { /* AC bias group 2, table 7 */ + { 0x2, 3 }, + { 0x2, 4 }, + { 0x18, 5 }, + { 0x1D, 5 }, + { 0x35, 6 }, + { 0xE4, 8 }, + { 0x1CF, 11 }, + { 0x1D, 7 }, + { 0x72, 9 }, + { 0x4, 3 }, + { 0x5, 3 }, + { 0x6, 4 }, + { 0x7, 4 }, + { 0x6, 5 }, + { 0x73, 7 }, + { 0x38, 8 }, + { 0x1CE, 11 }, + { 0x39B, 12 }, + { 0x398, 12 }, + { 0x733, 13 }, + { 0x732, 13 }, + { 0x735, 13 }, + { 0x734, 13 }, + { 0x0, 3 }, + { 0x1F, 5 }, + { 0x1B, 5 }, + { 0x34, 6 }, + { 0xF, 6 }, + { 0x1E, 5 }, + { 0xE5, 8 }, + { 0x19, 5 }, + { 0x38, 6 } + }, + { /* AC bias group 2, table 8 */ + { 0x16, 5 }, + { 0x50, 7 }, + { 0x172, 9 }, + { 0x2E7, 10 }, + { 0x1732, 13 }, + { 0x2E67, 14 }, + { 0x2E66, 14 }, + { 0x6, 4 }, + { 0x51, 7 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xD, 4 }, + { 0xC, 4 }, + { 0x9, 4 }, + { 0x1C, 5 }, + { 0x9, 5 }, + { 0x1C, 6 }, + { 0x1D, 6 }, + { 0x5D, 7 }, + { 0xB8, 8 }, + { 0x5CD, 11 }, + { 0x1731, 13 }, + { 0x1730, 13 }, + { 0xF, 4 }, + { 0x5, 4 }, + { 0xF, 5 }, + { 0x8, 5 }, + { 0x29, 6 }, + { 0x1D, 5 }, + { 0x2F, 6 }, + { 0x8, 4 }, + { 0x15, 5 } + }, + { /* AC bias group 2, table 9 */ + { 0x9, 4 }, + { 0x21, 6 }, + { 0x40, 7 }, + { 0xAD, 8 }, + { 0x2B0, 10 }, + { 0x1589, 13 }, + { 0x1588, 13 }, + { 0x1C, 5 }, + { 0x5F, 7 }, + { 0x0, 3 }, + { 0xF, 4 }, + { 0xD, 4 }, + { 0xC, 4 }, + { 0x6, 4 }, + { 0x11, 5 }, + { 0x2A, 6 }, + { 0x57, 7 }, + { 0x5E, 7 }, + { 0x41, 7 }, + { 0x159, 9 }, + { 0x563, 11 }, + { 0x158B, 13 }, + { 0x158A, 13 }, + { 0x1, 3 }, + { 0x5, 4 }, + { 0x14, 5 }, + { 0x3B, 6 }, + { 0x2E, 6 }, + { 0x4, 4 }, + { 0x3A, 6 }, + { 0x7, 4 }, + { 0x16, 5 } + }, + { /* AC bias group 2, table 10 */ + { 0xE, 4 }, + { 0x7, 5 }, + { 0x46, 7 }, + { 0x45, 7 }, + { 0x64, 9 }, + { 0x32A, 12 }, + { 0x657, 13 }, + { 0x18, 5 }, + { 0xD, 6 }, + { 0x0, 3 }, + { 0xF, 4 }, + { 0xA, 4 }, + { 0xB, 4 }, + { 0x1A, 5 }, + { 0x36, 6 }, + { 0x47, 7 }, + { 0x44, 7 }, + { 0x18, 7 }, + { 0x33, 8 }, + { 0xCB, 10 }, + { 0x656, 13 }, + { 0x329, 12 }, + { 0x328, 12 }, + { 0x2, 3 }, + { 0x6, 4 }, + { 0x19, 5 }, + { 0xE, 5 }, + { 0x37, 6 }, + { 0x9, 4 }, + { 0xF, 5 }, + { 0x2, 4 }, + { 0x10, 5 } + }, + { /* AC bias group 2, table 11 */ + { 0x3, 3 }, + { 0x18, 5 }, + { 0x23, 6 }, + { 0x77, 7 }, + { 0x194, 9 }, + { 0x1956, 13 }, + { 0x32AF, 14 }, + { 0x3A, 6 }, + { 0x76, 7 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x1F, 5 }, + { 0x1E, 5 }, + { 0x14, 5 }, + { 0x22, 6 }, + { 0x64, 7 }, + { 0x197, 9 }, + { 0x196, 9 }, + { 0x32B, 10 }, + { 0x654, 11 }, + { 0x32AE, 14 }, + { 0x1955, 13 }, + { 0x1954, 13 }, + { 0x0, 3 }, + { 0x9, 4 }, + { 0x1C, 5 }, + { 0x15, 5 }, + { 0x10, 5 }, + { 0xD, 4 }, + { 0x17, 5 }, + { 0x16, 5 }, + { 0x33, 6 } + }, + { /* AC bias group 2, table 12 */ + { 0x5, 3 }, + { 0x6, 4 }, + { 0x3E, 6 }, + { 0x10, 5 }, + { 0x48, 7 }, + { 0x93F, 12 }, + { 0x24FA, 14 }, + { 0x32, 6 }, + { 0x67, 7 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x1B, 5 }, + { 0x1E, 5 }, + { 0x34, 6 }, + { 0x66, 7 }, + { 0x92, 8 }, + { 0x126, 9 }, + { 0x24E, 10 }, + { 0x49E, 11 }, + { 0x49F7, 15 }, + { 0x49F6, 15 }, + { 0x24F9, 14 }, + { 0x24F8, 14 }, + { 0x0, 3 }, + { 0x7, 4 }, + { 0x18, 5 }, + { 0x11, 5 }, + { 0x3F, 6 }, + { 0xE, 4 }, + { 0x13, 5 }, + { 0x35, 6 }, + { 0x25, 6 } + }, + { /* AC bias group 2, table 13 */ + { 0x5, 3 }, + { 0x8, 4 }, + { 0x12, 5 }, + { 0x1C, 5 }, + { 0x1C, 6 }, + { 0xEA, 9 }, + { 0x1D75, 14 }, + { 0x1E, 6 }, + { 0x66, 7 }, + { 0x1, 3 }, + { 0x2, 3 }, + { 0x1B, 5 }, + { 0x1A, 5 }, + { 0x1F, 6 }, + { 0x3B, 7 }, + { 0x74, 8 }, + { 0x1D6, 10 }, + { 0x3AF, 11 }, + { 0x1D74, 14 }, + { 0x1D77, 14 }, + { 0x1D76, 14 }, + { 0xEB9, 13 }, + { 0xEB8, 13 }, + { 0xF, 4 }, + { 0x6, 4 }, + { 0x13, 5 }, + { 0x3B, 6 }, + { 0x3A, 6 }, + { 0x0, 3 }, + { 0x18, 5 }, + { 0x32, 6 }, + { 0x67, 7 } + }, + { /* AC bias group 2, table 14 */ + { 0x4, 3 }, + { 0xA, 4 }, + { 0x1B, 5 }, + { 0xC, 4 }, + { 0xD, 5 }, + { 0xE6, 8 }, + { 0x684, 11 }, + { 0x72, 7 }, + { 0xE7, 8 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x17, 5 }, + { 0x16, 5 }, + { 0x18, 6 }, + { 0xD1, 8 }, + { 0x1A0, 9 }, + { 0x686, 11 }, + { 0xD0F, 12 }, + { 0xD0A, 12 }, + { 0x1A17, 13 }, + { 0x1A16, 13 }, + { 0x1A1D, 13 }, + { 0x1A1C, 13 }, + { 0xF, 4 }, + { 0x1D, 5 }, + { 0xE, 5 }, + { 0x35, 6 }, + { 0x38, 6 }, + { 0x0, 3 }, + { 0xF, 5 }, + { 0x19, 6 }, + { 0x69, 7 } + }, + { /* AC bias group 2, table 15 */ + { 0x3, 3 }, + { 0xC, 4 }, + { 0x1B, 5 }, + { 0x0, 3 }, + { 0x3, 4 }, + { 0x2E, 6 }, + { 0x51, 9 }, + { 0xBC, 8 }, + { 0x53, 9 }, + { 0x4, 3 }, + { 0x2, 3 }, + { 0x16, 5 }, + { 0x15, 5 }, + { 0x15, 7 }, + { 0x50, 9 }, + { 0xA4, 10 }, + { 0x294, 12 }, + { 0x52B, 13 }, + { 0x52A, 13 }, + { 0x52D, 13 }, + { 0x52C, 13 }, + { 0x52F, 13 }, + { 0x52E, 13 }, + { 0xE, 4 }, + { 0x1A, 5 }, + { 0x4, 5 }, + { 0x28, 6 }, + { 0x29, 6 }, + { 0xF, 4 }, + { 0xB, 6 }, + { 0x5F, 7 }, + { 0xBD, 8 } + } }; static const uint16_t ac_bias_2[16][32][2] = { - { /* AC bias group 3, table 0 */ - { 0x3, 4 }, - { 0x9, 6 }, - { 0xD0, 8 }, - { 0x1A3, 9 }, - { 0x344, 10 }, - { 0xD14, 12 }, - { 0x1A2B, 13 }, - { 0x4, 4 }, - { 0x15, 7 }, - { 0x0, 3 }, - { 0xF, 4 }, - { 0xB, 4 }, - { 0xC, 4 }, - { 0xE, 4 }, - { 0x9, 4 }, - { 0x1B, 5 }, - { 0xA, 5 }, - { 0x14, 5 }, - { 0xD, 5 }, - { 0x2A, 6 }, - { 0x14, 7 }, - { 0x68B, 11 }, - { 0x1A2A, 13 }, - { 0x8, 4 }, - { 0xB, 5 }, - { 0x2B, 6 }, - { 0xB, 6 }, - { 0x69, 7 }, - { 0x35, 6 }, - { 0x8, 6 }, - { 0x7, 4 }, - { 0xC, 5 } - }, - { /* AC bias group 3, table 1 */ - { 0xA, 4 }, - { 0x3C, 6 }, - { 0x32, 7 }, - { 0x30, 7 }, - { 0xC5, 9 }, - { 0x621, 12 }, - { 0x620, 12 }, - { 0x1F, 5 }, - { 0x33, 7 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xE, 4 }, - { 0xD, 4 }, - { 0xC, 4 }, - { 0x4, 4 }, - { 0xD, 5 }, - { 0x26, 6 }, - { 0x27, 6 }, - { 0x14, 6 }, - { 0x63, 8 }, - { 0x189, 10 }, - { 0x623, 12 }, - { 0x622, 12 }, - { 0xB, 4 }, - { 0x12, 5 }, - { 0x3D, 6 }, - { 0x22, 6 }, - { 0x15, 6 }, - { 0xB, 5 }, - { 0x23, 6 }, - { 0x7, 4 }, - { 0x10, 5 } - }, - { /* AC bias group 3, table 2 */ - { 0xF, 4 }, - { 0xC, 5 }, - { 0x43, 7 }, - { 0x10, 6 }, - { 0x44, 8 }, - { 0x114, 10 }, - { 0x455, 12 }, - { 0x18, 5 }, - { 0x23, 7 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xE, 4 }, - { 0xD, 4 }, - { 0x9, 4 }, - { 0x19, 5 }, - { 0x9, 5 }, - { 0x17, 6 }, - { 0x16, 6 }, - { 0x42, 7 }, - { 0x8B, 9 }, - { 0x454, 12 }, - { 0x457, 12 }, - { 0x456, 12 }, - { 0xB, 4 }, - { 0x15, 5 }, - { 0xA, 5 }, - { 0x29, 6 }, - { 0x20, 6 }, - { 0xD, 5 }, - { 0x28, 6 }, - { 0x7, 4 }, - { 0x11, 5 } - }, - { /* AC bias group 3, table 3 */ - { 0x1, 3 }, - { 0x1A, 5 }, - { 0x29, 6 }, - { 0x2A, 6 }, - { 0xA0, 8 }, - { 0x285, 10 }, - { 0x1425, 13 }, - { 0x2, 5 }, - { 0x0, 7 }, - { 0x2, 3 }, - { 0x3, 3 }, - { 0xC, 4 }, - { 0xB, 4 }, - { 0x8, 4 }, - { 0x12, 5 }, - { 0x1, 6 }, - { 0x51, 7 }, - { 0x1, 7 }, - { 0x143, 9 }, - { 0x508, 11 }, - { 0x1424, 13 }, - { 0x1427, 13 }, - { 0x1426, 13 }, - { 0xF, 4 }, - { 0x1C, 5 }, - { 0x3, 5 }, - { 0x37, 6 }, - { 0x2B, 6 }, - { 0x13, 5 }, - { 0x36, 6 }, - { 0x1D, 5 }, - { 0x1, 5 } - }, - { /* AC bias group 3, table 4 */ - { 0x4, 3 }, - { 0x1F, 5 }, - { 0x3D, 6 }, - { 0x6, 5 }, - { 0x16, 7 }, - { 0x53, 9 }, - { 0x14A, 11 }, - { 0x34, 6 }, - { 0x2A, 8 }, - { 0x2, 3 }, - { 0x3, 3 }, - { 0xB, 4 }, - { 0xC, 4 }, - { 0x1C, 5 }, - { 0x37, 6 }, - { 0x17, 7 }, - { 0x2B, 8 }, - { 0x28, 8 }, - { 0xA4, 10 }, - { 0x52D, 13 }, - { 0x52C, 13 }, - { 0x52F, 13 }, - { 0x52E, 13 }, - { 0x0, 3 }, - { 0x1D, 5 }, - { 0x7, 5 }, - { 0x4, 5 }, - { 0x35, 6 }, - { 0x14, 5 }, - { 0x36, 6 }, - { 0x15, 5 }, - { 0x3C, 6 } - }, - { /* AC bias group 3, table 5 */ - { 0x4, 3 }, - { 0xA, 4 }, - { 0x7, 5 }, - { 0x1D, 5 }, - { 0x9, 6 }, - { 0x1F3, 9 }, - { 0x7C7, 11 }, - { 0x8, 6 }, - { 0x1F0, 9 }, - { 0x3, 3 }, - { 0x2, 3 }, - { 0xD, 4 }, - { 0xC, 4 }, - { 0x17, 5 }, - { 0x7D, 7 }, - { 0x1F2, 9 }, - { 0x7C6, 11 }, - { 0x7C5, 11 }, - { 0x1F12, 13 }, - { 0x3E27, 14 }, - { 0x3E26, 14 }, - { 0x1F11, 13 }, - { 0x1F10, 13 }, - { 0x0, 3 }, - { 0x1E, 5 }, - { 0x6, 5 }, - { 0x39, 6 }, - { 0x38, 6 }, - { 0x3F, 6 }, - { 0x2C, 6 }, - { 0x5, 5 }, - { 0x2D, 6 } - }, - { /* AC bias group 3, table 6 */ - { 0x2, 3 }, - { 0x7, 4 }, - { 0x18, 5 }, - { 0x3, 4 }, - { 0x5, 5 }, - { 0x35, 7 }, - { 0x4F, 9 }, - { 0x12, 7 }, - { 0x4E5, 13 }, - { 0x5, 3 }, - { 0x4, 3 }, - { 0xD, 4 }, - { 0xE, 4 }, - { 0x33, 6 }, - { 0x26, 8 }, - { 0x9D, 10 }, - { 0x4E4, 13 }, - { 0x4E7, 13 }, - { 0x4E6, 13 }, - { 0x4E1, 13 }, - { 0x4E0, 13 }, - { 0x4E3, 13 }, - { 0x4E2, 13 }, - { 0x0, 3 }, - { 0x1F, 5 }, - { 0xC, 5 }, - { 0x3D, 6 }, - { 0x3C, 6 }, - { 0x32, 6 }, - { 0x34, 7 }, - { 0x1B, 6 }, - { 0x8, 6 } - }, - { /* AC bias group 3, table 7 */ - { 0x0, 3 }, - { 0x4, 4 }, - { 0x1C, 5 }, - { 0xF, 4 }, - { 0x2, 4 }, - { 0x7, 5 }, - { 0x75, 7 }, - { 0xE8, 8 }, - { 0x1D2A, 13 }, - { 0x5, 3 }, - { 0x4, 3 }, - { 0xD, 4 }, - { 0xC, 4 }, - { 0x77, 7 }, - { 0xE96, 12 }, - { 0x3A57, 14 }, - { 0x3A56, 14 }, - { 0x3A5D, 14 }, - { 0x3A5C, 14 }, - { 0x3A5F, 14 }, - { 0x3A5E, 14 }, - { 0x1D29, 13 }, - { 0x1D28, 13 }, - { 0x3, 3 }, - { 0x6, 5 }, - { 0xA, 5 }, - { 0x2C, 7 }, - { 0x17, 6 }, - { 0x76, 7 }, - { 0x1D3, 9 }, - { 0x3A4, 10 }, - { 0x2D, 7 } - }, - { /* AC bias group 3, table 8 */ - { 0xA, 4 }, - { 0x24, 6 }, - { 0xBF, 8 }, - { 0x85, 8 }, - { 0x211, 10 }, - { 0x842, 12 }, - { 0x1087, 13 }, - { 0x18, 5 }, - { 0x20, 6 }, - { 0x1, 3 }, - { 0x2, 3 }, - { 0xE, 4 }, - { 0xD, 4 }, - { 0x7, 4 }, - { 0x13, 5 }, - { 0x25, 6 }, - { 0x5E, 7 }, - { 0x43, 7 }, - { 0xBE, 8 }, - { 0x109, 9 }, - { 0x1086, 13 }, - { 0x841, 12 }, - { 0x840, 12 }, - { 0xF, 4 }, - { 0x1, 4 }, - { 0x11, 5 }, - { 0x0, 5 }, - { 0x2E, 6 }, - { 0x19, 5 }, - { 0x1, 5 }, - { 0x6, 4 }, - { 0x16, 5 } - }, - { /* AC bias group 3, table 9 */ - { 0x2, 3 }, - { 0xF, 5 }, - { 0x6F, 7 }, - { 0x61, 7 }, - { 0x374, 10 }, - { 0x1BA8, 13 }, - { 0x3753, 14 }, - { 0x12, 5 }, - { 0x36, 6 }, - { 0x0, 3 }, - { 0x1, 3 }, - { 0xA, 4 }, - { 0xB, 4 }, - { 0x1A, 5 }, - { 0x31, 6 }, - { 0x60, 7 }, - { 0xDC, 8 }, - { 0x1BB, 9 }, - { 0x6EB, 11 }, - { 0x1BAB, 13 }, - { 0x3752, 14 }, - { 0x3755, 14 }, - { 0x3754, 14 }, - { 0xE, 4 }, - { 0x6, 4 }, - { 0x13, 5 }, - { 0xE, 5 }, - { 0x3E, 6 }, - { 0x8, 4 }, - { 0x1E, 5 }, - { 0x19, 5 }, - { 0x3F, 6 } - }, - { /* AC bias group 3, table 10 */ - { 0x3, 3 }, - { 0x1C, 5 }, - { 0x25, 6 }, - { 0x24, 6 }, - { 0x1DA, 9 }, - { 0x1DBD, 13 }, - { 0x3B7C, 14 }, - { 0x3C, 6 }, - { 0x3D, 6 }, - { 0x0, 3 }, - { 0x1, 3 }, - { 0xB, 4 }, - { 0xA, 4 }, - { 0xB, 5 }, - { 0x77, 7 }, - { 0xEC, 8 }, - { 0x3B6, 10 }, - { 0x76E, 11 }, - { 0x1DBF, 13 }, - { 0x76FB, 15 }, - { 0x76FA, 15 }, - { 0x3B79, 14 }, - { 0x3B78, 14 }, - { 0xD, 4 }, - { 0x1F, 5 }, - { 0x13, 5 }, - { 0xA, 5 }, - { 0x8, 5 }, - { 0xC, 4 }, - { 0x8, 4 }, - { 0x9, 5 }, - { 0x3A, 6 } - }, - { /* AC bias group 3, table 11 */ - { 0x5, 3 }, - { 0x3, 4 }, - { 0x4, 5 }, - { 0x10, 5 }, - { 0x8F, 8 }, - { 0x475, 11 }, - { 0x11D1, 13 }, - { 0x79, 7 }, - { 0x27, 6 }, - { 0x2, 3 }, - { 0x3, 3 }, - { 0x1, 4 }, - { 0x0, 4 }, - { 0x26, 6 }, - { 0x46, 7 }, - { 0x11C, 9 }, - { 0x477, 11 }, - { 0x8ED, 12 }, - { 0x11D0, 13 }, - { 0x11D3, 13 }, - { 0x11D2, 13 }, - { 0x11D9, 13 }, - { 0x11D8, 13 }, - { 0xD, 4 }, - { 0x1F, 5 }, - { 0x12, 5 }, - { 0x5, 5 }, - { 0x3D, 6 }, - { 0xC, 4 }, - { 0xE, 4 }, - { 0x22, 6 }, - { 0x78, 7 } - }, - { /* AC bias group 3, table 12 */ - { 0x5, 3 }, - { 0xC, 4 }, - { 0x1B, 5 }, - { 0x0, 4 }, - { 0x6, 6 }, - { 0x3E2, 10 }, - { 0x3E3D, 14 }, - { 0xF, 7 }, - { 0x34, 6 }, - { 0x3, 3 }, - { 0x2, 3 }, - { 0x1E, 5 }, - { 0x1D, 5 }, - { 0x7D, 7 }, - { 0x1F0, 9 }, - { 0x7C6, 11 }, - { 0x3E3C, 14 }, - { 0x3E3F, 14 }, - { 0x3E3E, 14 }, - { 0x3E39, 14 }, - { 0x3E38, 14 }, - { 0x3E3B, 14 }, - { 0x3E3A, 14 }, - { 0x8, 4 }, - { 0x1C, 5 }, - { 0x2, 5 }, - { 0x3F, 6 }, - { 0x35, 6 }, - { 0x9, 4 }, - { 0x1, 3 }, - { 0xE, 7 }, - { 0xF9, 8 } - }, - { /* AC bias group 3, table 13 */ - { 0x4, 3 }, - { 0xB, 4 }, - { 0x1, 4 }, - { 0xA, 4 }, - { 0x1E, 6 }, - { 0xE0, 9 }, - { 0xE1E, 13 }, - { 0x71, 8 }, - { 0x39, 7 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0xD, 5 }, - { 0xC, 5 }, - { 0x20, 7 }, - { 0x1C2, 10 }, - { 0x1C3F, 14 }, - { 0x1C3E, 14 }, - { 0xE19, 13 }, - { 0xE18, 13 }, - { 0xE1B, 13 }, - { 0xE1A, 13 }, - { 0xE1D, 13 }, - { 0xE1C, 13 }, - { 0x0, 4 }, - { 0x9, 5 }, - { 0x1D, 6 }, - { 0x1F, 6 }, - { 0x11, 6 }, - { 0x5, 4 }, - { 0x1, 3 }, - { 0x43, 8 }, - { 0x42, 8 } - }, - { /* AC bias group 3, table 14 */ - { 0x4, 3 }, - { 0xD, 4 }, - { 0x7, 4 }, - { 0x2, 3 }, - { 0x14, 5 }, - { 0x16C, 9 }, - { 0x16D1, 13 }, - { 0x2DF, 10 }, - { 0x16E, 9 }, - { 0x0, 2 }, - { 0x7, 3 }, - { 0x2C, 6 }, - { 0x2B, 6 }, - { 0x2DE, 10 }, - { 0x16D0, 13 }, - { 0x16D3, 13 }, - { 0x16D2, 13 }, - { 0x2DB5, 14 }, - { 0x2DB4, 14 }, - { 0x2DB7, 14 }, - { 0x2DB6, 14 }, - { 0x16D9, 13 }, - { 0x16D8, 13 }, - { 0xC, 5 }, - { 0x2A, 6 }, - { 0x5A, 7 }, - { 0x1B, 6 }, - { 0x1A, 6 }, - { 0x17, 5 }, - { 0xC, 4 }, - { 0x5B7, 11 }, - { 0x5B5, 11 } - }, - { /* AC bias group 3, table 15 */ - { 0x2, 2 }, - { 0xF, 4 }, - { 0x1C, 5 }, - { 0xC, 4 }, - { 0x3B, 6 }, - { 0x1AC, 9 }, - { 0x1AD8, 13 }, - { 0x35B3, 14 }, - { 0x35B2, 14 }, - { 0x1, 2 }, - { 0x0, 2 }, - { 0x69, 7 }, - { 0x68, 7 }, - { 0x35BD, 14 }, - { 0x35BC, 14 }, - { 0x35BF, 14 }, - { 0x35BE, 14 }, - { 0x35B9, 14 }, - { 0x35B8, 14 }, - { 0x35BB, 14 }, - { 0x35BA, 14 }, - { 0x35B5, 14 }, - { 0x35B4, 14 }, - { 0x1A9, 9 }, - { 0x1A8, 9 }, - { 0x35A, 10 }, - { 0xD7, 8 }, - { 0xD5, 8 }, - { 0x3A, 6 }, - { 0x1B, 5 }, - { 0x35B7, 14 }, - { 0x35B6, 14 } - } + { /* AC bias group 3, table 0 */ + { 0x3, 4 }, + { 0x9, 6 }, + { 0xD0, 8 }, + { 0x1A3, 9 }, + { 0x344, 10 }, + { 0xD14, 12 }, + { 0x1A2B, 13 }, + { 0x4, 4 }, + { 0x15, 7 }, + { 0x0, 3 }, + { 0xF, 4 }, + { 0xB, 4 }, + { 0xC, 4 }, + { 0xE, 4 }, + { 0x9, 4 }, + { 0x1B, 5 }, + { 0xA, 5 }, + { 0x14, 5 }, + { 0xD, 5 }, + { 0x2A, 6 }, + { 0x14, 7 }, + { 0x68B, 11 }, + { 0x1A2A, 13 }, + { 0x8, 4 }, + { 0xB, 5 }, + { 0x2B, 6 }, + { 0xB, 6 }, + { 0x69, 7 }, + { 0x35, 6 }, + { 0x8, 6 }, + { 0x7, 4 }, + { 0xC, 5 } + }, + { /* AC bias group 3, table 1 */ + { 0xA, 4 }, + { 0x3C, 6 }, + { 0x32, 7 }, + { 0x30, 7 }, + { 0xC5, 9 }, + { 0x621, 12 }, + { 0x620, 12 }, + { 0x1F, 5 }, + { 0x33, 7 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xE, 4 }, + { 0xD, 4 }, + { 0xC, 4 }, + { 0x4, 4 }, + { 0xD, 5 }, + { 0x26, 6 }, + { 0x27, 6 }, + { 0x14, 6 }, + { 0x63, 8 }, + { 0x189, 10 }, + { 0x623, 12 }, + { 0x622, 12 }, + { 0xB, 4 }, + { 0x12, 5 }, + { 0x3D, 6 }, + { 0x22, 6 }, + { 0x15, 6 }, + { 0xB, 5 }, + { 0x23, 6 }, + { 0x7, 4 }, + { 0x10, 5 } + }, + { /* AC bias group 3, table 2 */ + { 0xF, 4 }, + { 0xC, 5 }, + { 0x43, 7 }, + { 0x10, 6 }, + { 0x44, 8 }, + { 0x114, 10 }, + { 0x455, 12 }, + { 0x18, 5 }, + { 0x23, 7 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xE, 4 }, + { 0xD, 4 }, + { 0x9, 4 }, + { 0x19, 5 }, + { 0x9, 5 }, + { 0x17, 6 }, + { 0x16, 6 }, + { 0x42, 7 }, + { 0x8B, 9 }, + { 0x454, 12 }, + { 0x457, 12 }, + { 0x456, 12 }, + { 0xB, 4 }, + { 0x15, 5 }, + { 0xA, 5 }, + { 0x29, 6 }, + { 0x20, 6 }, + { 0xD, 5 }, + { 0x28, 6 }, + { 0x7, 4 }, + { 0x11, 5 } + }, + { /* AC bias group 3, table 3 */ + { 0x1, 3 }, + { 0x1A, 5 }, + { 0x29, 6 }, + { 0x2A, 6 }, + { 0xA0, 8 }, + { 0x285, 10 }, + { 0x1425, 13 }, + { 0x2, 5 }, + { 0x0, 7 }, + { 0x2, 3 }, + { 0x3, 3 }, + { 0xC, 4 }, + { 0xB, 4 }, + { 0x8, 4 }, + { 0x12, 5 }, + { 0x1, 6 }, + { 0x51, 7 }, + { 0x1, 7 }, + { 0x143, 9 }, + { 0x508, 11 }, + { 0x1424, 13 }, + { 0x1427, 13 }, + { 0x1426, 13 }, + { 0xF, 4 }, + { 0x1C, 5 }, + { 0x3, 5 }, + { 0x37, 6 }, + { 0x2B, 6 }, + { 0x13, 5 }, + { 0x36, 6 }, + { 0x1D, 5 }, + { 0x1, 5 } + }, + { /* AC bias group 3, table 4 */ + { 0x4, 3 }, + { 0x1F, 5 }, + { 0x3D, 6 }, + { 0x6, 5 }, + { 0x16, 7 }, + { 0x53, 9 }, + { 0x14A, 11 }, + { 0x34, 6 }, + { 0x2A, 8 }, + { 0x2, 3 }, + { 0x3, 3 }, + { 0xB, 4 }, + { 0xC, 4 }, + { 0x1C, 5 }, + { 0x37, 6 }, + { 0x17, 7 }, + { 0x2B, 8 }, + { 0x28, 8 }, + { 0xA4, 10 }, + { 0x52D, 13 }, + { 0x52C, 13 }, + { 0x52F, 13 }, + { 0x52E, 13 }, + { 0x0, 3 }, + { 0x1D, 5 }, + { 0x7, 5 }, + { 0x4, 5 }, + { 0x35, 6 }, + { 0x14, 5 }, + { 0x36, 6 }, + { 0x15, 5 }, + { 0x3C, 6 } + }, + { /* AC bias group 3, table 5 */ + { 0x4, 3 }, + { 0xA, 4 }, + { 0x7, 5 }, + { 0x1D, 5 }, + { 0x9, 6 }, + { 0x1F3, 9 }, + { 0x7C7, 11 }, + { 0x8, 6 }, + { 0x1F0, 9 }, + { 0x3, 3 }, + { 0x2, 3 }, + { 0xD, 4 }, + { 0xC, 4 }, + { 0x17, 5 }, + { 0x7D, 7 }, + { 0x1F2, 9 }, + { 0x7C6, 11 }, + { 0x7C5, 11 }, + { 0x1F12, 13 }, + { 0x3E27, 14 }, + { 0x3E26, 14 }, + { 0x1F11, 13 }, + { 0x1F10, 13 }, + { 0x0, 3 }, + { 0x1E, 5 }, + { 0x6, 5 }, + { 0x39, 6 }, + { 0x38, 6 }, + { 0x3F, 6 }, + { 0x2C, 6 }, + { 0x5, 5 }, + { 0x2D, 6 } + }, + { /* AC bias group 3, table 6 */ + { 0x2, 3 }, + { 0x7, 4 }, + { 0x18, 5 }, + { 0x3, 4 }, + { 0x5, 5 }, + { 0x35, 7 }, + { 0x4F, 9 }, + { 0x12, 7 }, + { 0x4E5, 13 }, + { 0x5, 3 }, + { 0x4, 3 }, + { 0xD, 4 }, + { 0xE, 4 }, + { 0x33, 6 }, + { 0x26, 8 }, + { 0x9D, 10 }, + { 0x4E4, 13 }, + { 0x4E7, 13 }, + { 0x4E6, 13 }, + { 0x4E1, 13 }, + { 0x4E0, 13 }, + { 0x4E3, 13 }, + { 0x4E2, 13 }, + { 0x0, 3 }, + { 0x1F, 5 }, + { 0xC, 5 }, + { 0x3D, 6 }, + { 0x3C, 6 }, + { 0x32, 6 }, + { 0x34, 7 }, + { 0x1B, 6 }, + { 0x8, 6 } + }, + { /* AC bias group 3, table 7 */ + { 0x0, 3 }, + { 0x4, 4 }, + { 0x1C, 5 }, + { 0xF, 4 }, + { 0x2, 4 }, + { 0x7, 5 }, + { 0x75, 7 }, + { 0xE8, 8 }, + { 0x1D2A, 13 }, + { 0x5, 3 }, + { 0x4, 3 }, + { 0xD, 4 }, + { 0xC, 4 }, + { 0x77, 7 }, + { 0xE96, 12 }, + { 0x3A57, 14 }, + { 0x3A56, 14 }, + { 0x3A5D, 14 }, + { 0x3A5C, 14 }, + { 0x3A5F, 14 }, + { 0x3A5E, 14 }, + { 0x1D29, 13 }, + { 0x1D28, 13 }, + { 0x3, 3 }, + { 0x6, 5 }, + { 0xA, 5 }, + { 0x2C, 7 }, + { 0x17, 6 }, + { 0x76, 7 }, + { 0x1D3, 9 }, + { 0x3A4, 10 }, + { 0x2D, 7 } + }, + { /* AC bias group 3, table 8 */ + { 0xA, 4 }, + { 0x24, 6 }, + { 0xBF, 8 }, + { 0x85, 8 }, + { 0x211, 10 }, + { 0x842, 12 }, + { 0x1087, 13 }, + { 0x18, 5 }, + { 0x20, 6 }, + { 0x1, 3 }, + { 0x2, 3 }, + { 0xE, 4 }, + { 0xD, 4 }, + { 0x7, 4 }, + { 0x13, 5 }, + { 0x25, 6 }, + { 0x5E, 7 }, + { 0x43, 7 }, + { 0xBE, 8 }, + { 0x109, 9 }, + { 0x1086, 13 }, + { 0x841, 12 }, + { 0x840, 12 }, + { 0xF, 4 }, + { 0x1, 4 }, + { 0x11, 5 }, + { 0x0, 5 }, + { 0x2E, 6 }, + { 0x19, 5 }, + { 0x1, 5 }, + { 0x6, 4 }, + { 0x16, 5 } + }, + { /* AC bias group 3, table 9 */ + { 0x2, 3 }, + { 0xF, 5 }, + { 0x6F, 7 }, + { 0x61, 7 }, + { 0x374, 10 }, + { 0x1BA8, 13 }, + { 0x3753, 14 }, + { 0x12, 5 }, + { 0x36, 6 }, + { 0x0, 3 }, + { 0x1, 3 }, + { 0xA, 4 }, + { 0xB, 4 }, + { 0x1A, 5 }, + { 0x31, 6 }, + { 0x60, 7 }, + { 0xDC, 8 }, + { 0x1BB, 9 }, + { 0x6EB, 11 }, + { 0x1BAB, 13 }, + { 0x3752, 14 }, + { 0x3755, 14 }, + { 0x3754, 14 }, + { 0xE, 4 }, + { 0x6, 4 }, + { 0x13, 5 }, + { 0xE, 5 }, + { 0x3E, 6 }, + { 0x8, 4 }, + { 0x1E, 5 }, + { 0x19, 5 }, + { 0x3F, 6 } + }, + { /* AC bias group 3, table 10 */ + { 0x3, 3 }, + { 0x1C, 5 }, + { 0x25, 6 }, + { 0x24, 6 }, + { 0x1DA, 9 }, + { 0x1DBD, 13 }, + { 0x3B7C, 14 }, + { 0x3C, 6 }, + { 0x3D, 6 }, + { 0x0, 3 }, + { 0x1, 3 }, + { 0xB, 4 }, + { 0xA, 4 }, + { 0xB, 5 }, + { 0x77, 7 }, + { 0xEC, 8 }, + { 0x3B6, 10 }, + { 0x76E, 11 }, + { 0x1DBF, 13 }, + { 0x76FB, 15 }, + { 0x76FA, 15 }, + { 0x3B79, 14 }, + { 0x3B78, 14 }, + { 0xD, 4 }, + { 0x1F, 5 }, + { 0x13, 5 }, + { 0xA, 5 }, + { 0x8, 5 }, + { 0xC, 4 }, + { 0x8, 4 }, + { 0x9, 5 }, + { 0x3A, 6 } + }, + { /* AC bias group 3, table 11 */ + { 0x5, 3 }, + { 0x3, 4 }, + { 0x4, 5 }, + { 0x10, 5 }, + { 0x8F, 8 }, + { 0x475, 11 }, + { 0x11D1, 13 }, + { 0x79, 7 }, + { 0x27, 6 }, + { 0x2, 3 }, + { 0x3, 3 }, + { 0x1, 4 }, + { 0x0, 4 }, + { 0x26, 6 }, + { 0x46, 7 }, + { 0x11C, 9 }, + { 0x477, 11 }, + { 0x8ED, 12 }, + { 0x11D0, 13 }, + { 0x11D3, 13 }, + { 0x11D2, 13 }, + { 0x11D9, 13 }, + { 0x11D8, 13 }, + { 0xD, 4 }, + { 0x1F, 5 }, + { 0x12, 5 }, + { 0x5, 5 }, + { 0x3D, 6 }, + { 0xC, 4 }, + { 0xE, 4 }, + { 0x22, 6 }, + { 0x78, 7 } + }, + { /* AC bias group 3, table 12 */ + { 0x5, 3 }, + { 0xC, 4 }, + { 0x1B, 5 }, + { 0x0, 4 }, + { 0x6, 6 }, + { 0x3E2, 10 }, + { 0x3E3D, 14 }, + { 0xF, 7 }, + { 0x34, 6 }, + { 0x3, 3 }, + { 0x2, 3 }, + { 0x1E, 5 }, + { 0x1D, 5 }, + { 0x7D, 7 }, + { 0x1F0, 9 }, + { 0x7C6, 11 }, + { 0x3E3C, 14 }, + { 0x3E3F, 14 }, + { 0x3E3E, 14 }, + { 0x3E39, 14 }, + { 0x3E38, 14 }, + { 0x3E3B, 14 }, + { 0x3E3A, 14 }, + { 0x8, 4 }, + { 0x1C, 5 }, + { 0x2, 5 }, + { 0x3F, 6 }, + { 0x35, 6 }, + { 0x9, 4 }, + { 0x1, 3 }, + { 0xE, 7 }, + { 0xF9, 8 } + }, + { /* AC bias group 3, table 13 */ + { 0x4, 3 }, + { 0xB, 4 }, + { 0x1, 4 }, + { 0xA, 4 }, + { 0x1E, 6 }, + { 0xE0, 9 }, + { 0xE1E, 13 }, + { 0x71, 8 }, + { 0x39, 7 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0xD, 5 }, + { 0xC, 5 }, + { 0x20, 7 }, + { 0x1C2, 10 }, + { 0x1C3F, 14 }, + { 0x1C3E, 14 }, + { 0xE19, 13 }, + { 0xE18, 13 }, + { 0xE1B, 13 }, + { 0xE1A, 13 }, + { 0xE1D, 13 }, + { 0xE1C, 13 }, + { 0x0, 4 }, + { 0x9, 5 }, + { 0x1D, 6 }, + { 0x1F, 6 }, + { 0x11, 6 }, + { 0x5, 4 }, + { 0x1, 3 }, + { 0x43, 8 }, + { 0x42, 8 } + }, + { /* AC bias group 3, table 14 */ + { 0x4, 3 }, + { 0xD, 4 }, + { 0x7, 4 }, + { 0x2, 3 }, + { 0x14, 5 }, + { 0x16C, 9 }, + { 0x16D1, 13 }, + { 0x2DF, 10 }, + { 0x16E, 9 }, + { 0x0, 2 }, + { 0x7, 3 }, + { 0x2C, 6 }, + { 0x2B, 6 }, + { 0x2DE, 10 }, + { 0x16D0, 13 }, + { 0x16D3, 13 }, + { 0x16D2, 13 }, + { 0x2DB5, 14 }, + { 0x2DB4, 14 }, + { 0x2DB7, 14 }, + { 0x2DB6, 14 }, + { 0x16D9, 13 }, + { 0x16D8, 13 }, + { 0xC, 5 }, + { 0x2A, 6 }, + { 0x5A, 7 }, + { 0x1B, 6 }, + { 0x1A, 6 }, + { 0x17, 5 }, + { 0xC, 4 }, + { 0x5B7, 11 }, + { 0x5B5, 11 } + }, + { /* AC bias group 3, table 15 */ + { 0x2, 2 }, + { 0xF, 4 }, + { 0x1C, 5 }, + { 0xC, 4 }, + { 0x3B, 6 }, + { 0x1AC, 9 }, + { 0x1AD8, 13 }, + { 0x35B3, 14 }, + { 0x35B2, 14 }, + { 0x1, 2 }, + { 0x0, 2 }, + { 0x69, 7 }, + { 0x68, 7 }, + { 0x35BD, 14 }, + { 0x35BC, 14 }, + { 0x35BF, 14 }, + { 0x35BE, 14 }, + { 0x35B9, 14 }, + { 0x35B8, 14 }, + { 0x35BB, 14 }, + { 0x35BA, 14 }, + { 0x35B5, 14 }, + { 0x35B4, 14 }, + { 0x1A9, 9 }, + { 0x1A8, 9 }, + { 0x35A, 10 }, + { 0xD7, 8 }, + { 0xD5, 8 }, + { 0x3A, 6 }, + { 0x1B, 5 }, + { 0x35B7, 14 }, + { 0x35B6, 14 } + } }; static const uint16_t ac_bias_3[16][32][2] = { - { /* AC bias group 4, table 0 */ - { 0x0, 3 }, - { 0x10, 5 }, - { 0x72, 7 }, - { 0x71, 7 }, - { 0x154, 9 }, - { 0xAAB, 12 }, - { 0xAA8, 12 }, - { 0x14, 5 }, - { 0x70, 7 }, - { 0x2, 3 }, - { 0x3, 3 }, - { 0xC, 4 }, - { 0xB, 4 }, - { 0x3, 4 }, - { 0x11, 5 }, - { 0x73, 7 }, - { 0x54, 7 }, - { 0xAB, 8 }, - { 0x2AB, 10 }, - { 0x1553, 13 }, - { 0x1552, 13 }, - { 0x1555, 13 }, - { 0x1554, 13 }, - { 0xD, 4 }, - { 0x1E, 5 }, - { 0x12, 5 }, - { 0x3E, 6 }, - { 0x2B, 6 }, - { 0x2, 4 }, - { 0x3F, 6 }, - { 0x1D, 5 }, - { 0x13, 5 } - }, - { /* AC bias group 4, table 1 */ - { 0x3, 3 }, - { 0x1F, 5 }, - { 0x29, 6 }, - { 0x3D, 6 }, - { 0xC, 7 }, - { 0x69, 10 }, - { 0x345, 13 }, - { 0x2, 5 }, - { 0x28, 6 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0xE, 4 }, - { 0xC, 4 }, - { 0x15, 5 }, - { 0x7, 6 }, - { 0x1B, 8 }, - { 0x6B, 10 }, - { 0x6A, 10 }, - { 0x344, 13 }, - { 0x347, 13 }, - { 0x346, 13 }, - { 0x1A1, 12 }, - { 0x1A0, 12 }, - { 0xB, 4 }, - { 0x1A, 5 }, - { 0x12, 5 }, - { 0x0, 5 }, - { 0x3C, 6 }, - { 0x8, 4 }, - { 0x1B, 5 }, - { 0x13, 5 }, - { 0x1, 5 } - }, - { /* AC bias group 4, table 2 */ - { 0x4, 3 }, - { 0x4, 4 }, - { 0x3F, 6 }, - { 0x14, 5 }, - { 0x56, 7 }, - { 0x15C, 9 }, - { 0x15D5, 13 }, - { 0x3C, 6 }, - { 0x2A, 6 }, - { 0x0, 3 }, - { 0x1, 3 }, - { 0xE, 4 }, - { 0xD, 4 }, - { 0xC, 5 }, - { 0xAF, 8 }, - { 0x2BB, 10 }, - { 0x15D4, 13 }, - { 0x15D7, 13 }, - { 0x15D6, 13 }, - { 0x15D1, 13 }, - { 0x15D0, 13 }, - { 0x15D3, 13 }, - { 0x15D2, 13 }, - { 0xB, 4 }, - { 0x19, 5 }, - { 0xD, 5 }, - { 0x3E, 6 }, - { 0x31, 6 }, - { 0x7, 4 }, - { 0x5, 4 }, - { 0x3D, 6 }, - { 0x30, 6 } - }, - { /* AC bias group 4, table 3 */ - { 0x5, 3 }, - { 0x8, 4 }, - { 0x1A, 5 }, - { 0x0, 4 }, - { 0x36, 6 }, - { 0x11, 8 }, - { 0x106, 12 }, - { 0xA, 7 }, - { 0x6E, 7 }, - { 0x2, 3 }, - { 0x3, 3 }, - { 0x3, 4 }, - { 0x2, 4 }, - { 0x6F, 7 }, - { 0x21, 9 }, - { 0x20F, 13 }, - { 0x20E, 13 }, - { 0x101, 12 }, - { 0x100, 12 }, - { 0x103, 12 }, - { 0x102, 12 }, - { 0x105, 12 }, - { 0x104, 12 }, - { 0xC, 4 }, - { 0x1E, 5 }, - { 0x3, 5 }, - { 0x3E, 6 }, - { 0x3F, 6 }, - { 0x9, 4 }, - { 0xE, 4 }, - { 0xB, 7 }, - { 0x9, 7 } - }, - { /* AC bias group 4, table 4 */ - { 0x2, 3 }, - { 0xE, 4 }, - { 0x1E, 5 }, - { 0xC, 4 }, - { 0x1F, 5 }, - { 0x6E, 7 }, - { 0xAD, 10 }, - { 0xAF, 10 }, - { 0x14, 7 }, - { 0x4, 3 }, - { 0x3, 3 }, - { 0x1A, 5 }, - { 0x17, 5 }, - { 0x2A, 8 }, - { 0x576, 13 }, - { 0xAEF, 14 }, - { 0xAEE, 14 }, - { 0x571, 13 }, - { 0x570, 13 }, - { 0x573, 13 }, - { 0x572, 13 }, - { 0x575, 13 }, - { 0x574, 13 }, - { 0x3, 4 }, - { 0x16, 5 }, - { 0x4, 5 }, - { 0x36, 6 }, - { 0xB, 6 }, - { 0xA, 4 }, - { 0x0, 3 }, - { 0x6F, 7 }, - { 0xAC, 10 } - }, - { /* AC bias group 4, table 5 */ - { 0x4, 3 }, - { 0x5, 4 }, - { 0x3, 3 }, - { 0x1, 3 }, - { 0x4, 4 }, - { 0x2F, 6 }, - { 0x526, 11 }, - { 0x1495, 13 }, - { 0xA6, 8 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0x2D, 6 }, - { 0x2C, 6 }, - { 0x1494, 13 }, - { 0x1497, 13 }, - { 0x1496, 13 }, - { 0x1491, 13 }, - { 0x1490, 13 }, - { 0x1493, 13 }, - { 0x1492, 13 }, - { 0x293D, 14 }, - { 0x293C, 14 }, - { 0x293F, 14 }, - { 0x0, 3 }, - { 0x28, 6 }, - { 0xA5, 8 }, - { 0x148, 9 }, - { 0xA7, 8 }, - { 0x2E, 6 }, - { 0x15, 5 }, - { 0xA4E, 12 }, - { 0x293E, 14 } - }, - { /* AC bias group 4, table 6 */ - { 0x4, 3 }, - { 0x5, 4 }, - { 0x3, 3 }, - { 0x1, 3 }, - { 0x4, 4 }, - { 0x2F, 6 }, - { 0x526, 11 }, - { 0x1495, 13 }, - { 0xA6, 8 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0x2D, 6 }, - { 0x2C, 6 }, - { 0x1494, 13 }, - { 0x1497, 13 }, - { 0x1496, 13 }, - { 0x1491, 13 }, - { 0x1490, 13 }, - { 0x1493, 13 }, - { 0x1492, 13 }, - { 0x293D, 14 }, - { 0x293C, 14 }, - { 0x293F, 14 }, - { 0x0, 3 }, - { 0x28, 6 }, - { 0xA5, 8 }, - { 0x148, 9 }, - { 0xA7, 8 }, - { 0x2E, 6 }, - { 0x15, 5 }, - { 0xA4E, 12 }, - { 0x293E, 14 } - }, - { /* AC bias group 4, table 7 */ - { 0x4, 3 }, - { 0x5, 4 }, - { 0x3, 3 }, - { 0x1, 3 }, - { 0x4, 4 }, - { 0x2F, 6 }, - { 0x526, 11 }, - { 0x1495, 13 }, - { 0xA6, 8 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0x2D, 6 }, - { 0x2C, 6 }, - { 0x1494, 13 }, - { 0x1497, 13 }, - { 0x1496, 13 }, - { 0x1491, 13 }, - { 0x1490, 13 }, - { 0x1493, 13 }, - { 0x1492, 13 }, - { 0x293D, 14 }, - { 0x293C, 14 }, - { 0x293F, 14 }, - { 0x0, 3 }, - { 0x28, 6 }, - { 0xA5, 8 }, - { 0x148, 9 }, - { 0xA7, 8 }, - { 0x2E, 6 }, - { 0x15, 5 }, - { 0xA4E, 12 }, - { 0x293E, 14 } - }, - { /* AC bias group 4, table 8 */ - { 0x3, 3 }, - { 0x11, 5 }, - { 0x20, 6 }, - { 0x74, 7 }, - { 0x10D, 9 }, - { 0x863, 12 }, - { 0x860, 12 }, - { 0xA, 5 }, - { 0x75, 7 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xB, 4 }, - { 0xA, 4 }, - { 0x18, 5 }, - { 0x38, 6 }, - { 0x42, 7 }, - { 0x10F, 9 }, - { 0x10E, 9 }, - { 0x219, 10 }, - { 0x10C3, 13 }, - { 0x10C2, 13 }, - { 0x10C5, 13 }, - { 0x10C4, 13 }, - { 0xF, 4 }, - { 0x4, 4 }, - { 0x19, 5 }, - { 0xB, 5 }, - { 0x39, 6 }, - { 0x9, 4 }, - { 0x1B, 5 }, - { 0x1A, 5 }, - { 0x3B, 6 } - }, - { /* AC bias group 4, table 9 */ - { 0x5, 3 }, - { 0x1, 4 }, - { 0x3E, 6 }, - { 0x1, 5 }, - { 0xE2, 8 }, - { 0x1C6F, 13 }, - { 0x38D9, 14 }, - { 0x39, 6 }, - { 0x1F, 6 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x0, 5 }, - { 0x70, 7 }, - { 0x1C7, 9 }, - { 0x38C, 10 }, - { 0x71A, 11 }, - { 0x38D8, 14 }, - { 0x38DB, 14 }, - { 0x38DA, 14 }, - { 0x38DD, 14 }, - { 0x38DC, 14 }, - { 0xD, 4 }, - { 0x1D, 5 }, - { 0xE, 5 }, - { 0x3F, 6 }, - { 0x3C, 6 }, - { 0xC, 4 }, - { 0x6, 4 }, - { 0x3D, 6 }, - { 0x1E, 6 } - }, - { /* AC bias group 4, table 10 */ - { 0x6, 3 }, - { 0xB, 4 }, - { 0x11, 5 }, - { 0x1E, 5 }, - { 0x74, 7 }, - { 0x3AA, 10 }, - { 0x1D5C, 13 }, - { 0x1, 6 }, - { 0x21, 6 }, - { 0x1, 3 }, - { 0x2, 3 }, - { 0x7, 4 }, - { 0x6, 4 }, - { 0x3E, 6 }, - { 0xEB, 8 }, - { 0x1D4, 9 }, - { 0xEAF, 12 }, - { 0x3ABB, 14 }, - { 0x3ABA, 14 }, - { 0x1D59, 13 }, - { 0x1D58, 13 }, - { 0x1D5B, 13 }, - { 0x1D5A, 13 }, - { 0xA, 4 }, - { 0x1C, 5 }, - { 0x1, 5 }, - { 0x3F, 6 }, - { 0x3B, 6 }, - { 0x1, 4 }, - { 0x9, 4 }, - { 0x20, 6 }, - { 0x0, 6 } - }, - { /* AC bias group 4, table 11 */ - { 0x4, 3 }, - { 0xA, 4 }, - { 0x17, 5 }, - { 0x4, 4 }, - { 0x16, 6 }, - { 0x16A, 9 }, - { 0x16B1, 13 }, - { 0x17, 7 }, - { 0x5B, 7 }, - { 0x6, 3 }, - { 0x7, 3 }, - { 0x1, 4 }, - { 0x0, 4 }, - { 0xA, 6 }, - { 0x2D7, 10 }, - { 0xB5A, 12 }, - { 0x16B0, 13 }, - { 0x16B3, 13 }, - { 0x16B2, 13 }, - { 0x2D6D, 14 }, - { 0x2D6C, 14 }, - { 0x2D6F, 14 }, - { 0x2D6E, 14 }, - { 0x6, 4 }, - { 0xA, 5 }, - { 0x4, 5 }, - { 0x2C, 6 }, - { 0x17, 6 }, - { 0x3, 4 }, - { 0x7, 4 }, - { 0x16, 7 }, - { 0xB4, 8 } - }, - { /* AC bias group 4, table 12 */ - { 0x5, 3 }, - { 0xD, 4 }, - { 0x5, 4 }, - { 0x9, 4 }, - { 0x33, 6 }, - { 0x193, 9 }, - { 0x192C, 13 }, - { 0x61, 8 }, - { 0x31, 7 }, - { 0x0, 2 }, - { 0x7, 3 }, - { 0x10, 5 }, - { 0x11, 5 }, - { 0xC8, 8 }, - { 0x192F, 13 }, - { 0x325B, 14 }, - { 0x325A, 14 }, - { 0x1929, 13 }, - { 0x1928, 13 }, - { 0x192B, 13 }, - { 0x192A, 13 }, - { 0x325D, 14 }, - { 0x325C, 14 }, - { 0x18, 5 }, - { 0x1A, 6 }, - { 0x1B, 6 }, - { 0x65, 7 }, - { 0x19, 6 }, - { 0x4, 4 }, - { 0x7, 4 }, - { 0x60, 8 }, - { 0x324, 10 } - }, - { /* AC bias group 4, table 13 */ - { 0x6, 3 }, - { 0x0, 3 }, - { 0x2, 4 }, - { 0xF, 4 }, - { 0x39, 6 }, - { 0x1D9, 9 }, - { 0x1D82, 13 }, - { 0x761, 11 }, - { 0x3BE, 10 }, - { 0x1, 2 }, - { 0x2, 2 }, - { 0xF, 6 }, - { 0xE, 6 }, - { 0x762, 11 }, - { 0x3B07, 14 }, - { 0x3B06, 14 }, - { 0x3B1D, 14 }, - { 0x3B1C, 14 }, - { 0x3B1F, 14 }, - { 0x3B1E, 14 }, - { 0x3B19, 14 }, - { 0x3B18, 14 }, - { 0x3B1B, 14 }, - { 0x38, 6 }, - { 0x1DE, 9 }, - { 0xED, 8 }, - { 0x3BF, 10 }, - { 0xEE, 8 }, - { 0x3A, 6 }, - { 0x6, 5 }, - { 0xEC0, 12 }, - { 0x3B1A, 14 } - }, - { /* AC bias group 4, table 14 */ - { 0x0, 2 }, - { 0x2, 3 }, - { 0xF, 5 }, - { 0x6, 4 }, - { 0x1C, 6 }, - { 0x1D0, 10 }, - { 0xE8C, 13 }, - { 0x1D1B, 14 }, - { 0x1D1A, 14 }, - { 0x3, 2 }, - { 0x2, 2 }, - { 0xEA, 9 }, - { 0xE9, 9 }, - { 0xE89, 13 }, - { 0xE88, 13 }, - { 0xE8B, 13 }, - { 0xE8A, 13 }, - { 0x1D65, 14 }, - { 0x1D64, 14 }, - { 0x1D67, 14 }, - { 0x1D66, 14 }, - { 0x1D61, 14 }, - { 0x1D60, 14 }, - { 0x3AD, 11 }, - { 0x1D63, 14 }, - { 0x1D62, 14 }, - { 0x1D1D, 14 }, - { 0x1D1C, 14 }, - { 0x3B, 7 }, - { 0x1D7, 10 }, - { 0x1D1F, 14 }, - { 0x1D1E, 14 } - }, - { /* AC bias group 4, table 15 */ - { 0x2, 2 }, - { 0xF, 4 }, - { 0x1C, 5 }, - { 0xC, 4 }, - { 0x3B, 6 }, - { 0x1AC, 9 }, - { 0x1AD8, 13 }, - { 0x35B3, 14 }, - { 0x35B2, 14 }, - { 0x1, 2 }, - { 0x0, 2 }, - { 0x69, 7 }, - { 0x68, 7 }, - { 0x35BD, 14 }, - { 0x35BC, 14 }, - { 0x35BF, 14 }, - { 0x35BE, 14 }, - { 0x35B9, 14 }, - { 0x35B8, 14 }, - { 0x35BB, 14 }, - { 0x35BA, 14 }, - { 0x35B5, 14 }, - { 0x35B4, 14 }, - { 0x1A9, 9 }, - { 0x1A8, 9 }, - { 0x35A, 10 }, - { 0xD7, 8 }, - { 0xD5, 8 }, - { 0x3A, 6 }, - { 0x1B, 5 }, - { 0x35B7, 14 }, - { 0x35B6, 14 } - } + { /* AC bias group 4, table 0 */ + { 0x0, 3 }, + { 0x10, 5 }, + { 0x72, 7 }, + { 0x71, 7 }, + { 0x154, 9 }, + { 0xAAB, 12 }, + { 0xAA8, 12 }, + { 0x14, 5 }, + { 0x70, 7 }, + { 0x2, 3 }, + { 0x3, 3 }, + { 0xC, 4 }, + { 0xB, 4 }, + { 0x3, 4 }, + { 0x11, 5 }, + { 0x73, 7 }, + { 0x54, 7 }, + { 0xAB, 8 }, + { 0x2AB, 10 }, + { 0x1553, 13 }, + { 0x1552, 13 }, + { 0x1555, 13 }, + { 0x1554, 13 }, + { 0xD, 4 }, + { 0x1E, 5 }, + { 0x12, 5 }, + { 0x3E, 6 }, + { 0x2B, 6 }, + { 0x2, 4 }, + { 0x3F, 6 }, + { 0x1D, 5 }, + { 0x13, 5 } + }, + { /* AC bias group 4, table 1 */ + { 0x3, 3 }, + { 0x1F, 5 }, + { 0x29, 6 }, + { 0x3D, 6 }, + { 0xC, 7 }, + { 0x69, 10 }, + { 0x345, 13 }, + { 0x2, 5 }, + { 0x28, 6 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0xE, 4 }, + { 0xC, 4 }, + { 0x15, 5 }, + { 0x7, 6 }, + { 0x1B, 8 }, + { 0x6B, 10 }, + { 0x6A, 10 }, + { 0x344, 13 }, + { 0x347, 13 }, + { 0x346, 13 }, + { 0x1A1, 12 }, + { 0x1A0, 12 }, + { 0xB, 4 }, + { 0x1A, 5 }, + { 0x12, 5 }, + { 0x0, 5 }, + { 0x3C, 6 }, + { 0x8, 4 }, + { 0x1B, 5 }, + { 0x13, 5 }, + { 0x1, 5 } + }, + { /* AC bias group 4, table 2 */ + { 0x4, 3 }, + { 0x4, 4 }, + { 0x3F, 6 }, + { 0x14, 5 }, + { 0x56, 7 }, + { 0x15C, 9 }, + { 0x15D5, 13 }, + { 0x3C, 6 }, + { 0x2A, 6 }, + { 0x0, 3 }, + { 0x1, 3 }, + { 0xE, 4 }, + { 0xD, 4 }, + { 0xC, 5 }, + { 0xAF, 8 }, + { 0x2BB, 10 }, + { 0x15D4, 13 }, + { 0x15D7, 13 }, + { 0x15D6, 13 }, + { 0x15D1, 13 }, + { 0x15D0, 13 }, + { 0x15D3, 13 }, + { 0x15D2, 13 }, + { 0xB, 4 }, + { 0x19, 5 }, + { 0xD, 5 }, + { 0x3E, 6 }, + { 0x31, 6 }, + { 0x7, 4 }, + { 0x5, 4 }, + { 0x3D, 6 }, + { 0x30, 6 } + }, + { /* AC bias group 4, table 3 */ + { 0x5, 3 }, + { 0x8, 4 }, + { 0x1A, 5 }, + { 0x0, 4 }, + { 0x36, 6 }, + { 0x11, 8 }, + { 0x106, 12 }, + { 0xA, 7 }, + { 0x6E, 7 }, + { 0x2, 3 }, + { 0x3, 3 }, + { 0x3, 4 }, + { 0x2, 4 }, + { 0x6F, 7 }, + { 0x21, 9 }, + { 0x20F, 13 }, + { 0x20E, 13 }, + { 0x101, 12 }, + { 0x100, 12 }, + { 0x103, 12 }, + { 0x102, 12 }, + { 0x105, 12 }, + { 0x104, 12 }, + { 0xC, 4 }, + { 0x1E, 5 }, + { 0x3, 5 }, + { 0x3E, 6 }, + { 0x3F, 6 }, + { 0x9, 4 }, + { 0xE, 4 }, + { 0xB, 7 }, + { 0x9, 7 } + }, + { /* AC bias group 4, table 4 */ + { 0x2, 3 }, + { 0xE, 4 }, + { 0x1E, 5 }, + { 0xC, 4 }, + { 0x1F, 5 }, + { 0x6E, 7 }, + { 0xAD, 10 }, + { 0xAF, 10 }, + { 0x14, 7 }, + { 0x4, 3 }, + { 0x3, 3 }, + { 0x1A, 5 }, + { 0x17, 5 }, + { 0x2A, 8 }, + { 0x576, 13 }, + { 0xAEF, 14 }, + { 0xAEE, 14 }, + { 0x571, 13 }, + { 0x570, 13 }, + { 0x573, 13 }, + { 0x572, 13 }, + { 0x575, 13 }, + { 0x574, 13 }, + { 0x3, 4 }, + { 0x16, 5 }, + { 0x4, 5 }, + { 0x36, 6 }, + { 0xB, 6 }, + { 0xA, 4 }, + { 0x0, 3 }, + { 0x6F, 7 }, + { 0xAC, 10 } + }, + { /* AC bias group 4, table 5 */ + { 0x4, 3 }, + { 0x5, 4 }, + { 0x3, 3 }, + { 0x1, 3 }, + { 0x4, 4 }, + { 0x2F, 6 }, + { 0x526, 11 }, + { 0x1495, 13 }, + { 0xA6, 8 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0x2D, 6 }, + { 0x2C, 6 }, + { 0x1494, 13 }, + { 0x1497, 13 }, + { 0x1496, 13 }, + { 0x1491, 13 }, + { 0x1490, 13 }, + { 0x1493, 13 }, + { 0x1492, 13 }, + { 0x293D, 14 }, + { 0x293C, 14 }, + { 0x293F, 14 }, + { 0x0, 3 }, + { 0x28, 6 }, + { 0xA5, 8 }, + { 0x148, 9 }, + { 0xA7, 8 }, + { 0x2E, 6 }, + { 0x15, 5 }, + { 0xA4E, 12 }, + { 0x293E, 14 } + }, + { /* AC bias group 4, table 6 */ + { 0x4, 3 }, + { 0x5, 4 }, + { 0x3, 3 }, + { 0x1, 3 }, + { 0x4, 4 }, + { 0x2F, 6 }, + { 0x526, 11 }, + { 0x1495, 13 }, + { 0xA6, 8 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0x2D, 6 }, + { 0x2C, 6 }, + { 0x1494, 13 }, + { 0x1497, 13 }, + { 0x1496, 13 }, + { 0x1491, 13 }, + { 0x1490, 13 }, + { 0x1493, 13 }, + { 0x1492, 13 }, + { 0x293D, 14 }, + { 0x293C, 14 }, + { 0x293F, 14 }, + { 0x0, 3 }, + { 0x28, 6 }, + { 0xA5, 8 }, + { 0x148, 9 }, + { 0xA7, 8 }, + { 0x2E, 6 }, + { 0x15, 5 }, + { 0xA4E, 12 }, + { 0x293E, 14 } + }, + { /* AC bias group 4, table 7 */ + { 0x4, 3 }, + { 0x5, 4 }, + { 0x3, 3 }, + { 0x1, 3 }, + { 0x4, 4 }, + { 0x2F, 6 }, + { 0x526, 11 }, + { 0x1495, 13 }, + { 0xA6, 8 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0x2D, 6 }, + { 0x2C, 6 }, + { 0x1494, 13 }, + { 0x1497, 13 }, + { 0x1496, 13 }, + { 0x1491, 13 }, + { 0x1490, 13 }, + { 0x1493, 13 }, + { 0x1492, 13 }, + { 0x293D, 14 }, + { 0x293C, 14 }, + { 0x293F, 14 }, + { 0x0, 3 }, + { 0x28, 6 }, + { 0xA5, 8 }, + { 0x148, 9 }, + { 0xA7, 8 }, + { 0x2E, 6 }, + { 0x15, 5 }, + { 0xA4E, 12 }, + { 0x293E, 14 } + }, + { /* AC bias group 4, table 8 */ + { 0x3, 3 }, + { 0x11, 5 }, + { 0x20, 6 }, + { 0x74, 7 }, + { 0x10D, 9 }, + { 0x863, 12 }, + { 0x860, 12 }, + { 0xA, 5 }, + { 0x75, 7 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xB, 4 }, + { 0xA, 4 }, + { 0x18, 5 }, + { 0x38, 6 }, + { 0x42, 7 }, + { 0x10F, 9 }, + { 0x10E, 9 }, + { 0x219, 10 }, + { 0x10C3, 13 }, + { 0x10C2, 13 }, + { 0x10C5, 13 }, + { 0x10C4, 13 }, + { 0xF, 4 }, + { 0x4, 4 }, + { 0x19, 5 }, + { 0xB, 5 }, + { 0x39, 6 }, + { 0x9, 4 }, + { 0x1B, 5 }, + { 0x1A, 5 }, + { 0x3B, 6 } + }, + { /* AC bias group 4, table 9 */ + { 0x5, 3 }, + { 0x1, 4 }, + { 0x3E, 6 }, + { 0x1, 5 }, + { 0xE2, 8 }, + { 0x1C6F, 13 }, + { 0x38D9, 14 }, + { 0x39, 6 }, + { 0x1F, 6 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x0, 5 }, + { 0x70, 7 }, + { 0x1C7, 9 }, + { 0x38C, 10 }, + { 0x71A, 11 }, + { 0x38D8, 14 }, + { 0x38DB, 14 }, + { 0x38DA, 14 }, + { 0x38DD, 14 }, + { 0x38DC, 14 }, + { 0xD, 4 }, + { 0x1D, 5 }, + { 0xE, 5 }, + { 0x3F, 6 }, + { 0x3C, 6 }, + { 0xC, 4 }, + { 0x6, 4 }, + { 0x3D, 6 }, + { 0x1E, 6 } + }, + { /* AC bias group 4, table 10 */ + { 0x6, 3 }, + { 0xB, 4 }, + { 0x11, 5 }, + { 0x1E, 5 }, + { 0x74, 7 }, + { 0x3AA, 10 }, + { 0x1D5C, 13 }, + { 0x1, 6 }, + { 0x21, 6 }, + { 0x1, 3 }, + { 0x2, 3 }, + { 0x7, 4 }, + { 0x6, 4 }, + { 0x3E, 6 }, + { 0xEB, 8 }, + { 0x1D4, 9 }, + { 0xEAF, 12 }, + { 0x3ABB, 14 }, + { 0x3ABA, 14 }, + { 0x1D59, 13 }, + { 0x1D58, 13 }, + { 0x1D5B, 13 }, + { 0x1D5A, 13 }, + { 0xA, 4 }, + { 0x1C, 5 }, + { 0x1, 5 }, + { 0x3F, 6 }, + { 0x3B, 6 }, + { 0x1, 4 }, + { 0x9, 4 }, + { 0x20, 6 }, + { 0x0, 6 } + }, + { /* AC bias group 4, table 11 */ + { 0x4, 3 }, + { 0xA, 4 }, + { 0x17, 5 }, + { 0x4, 4 }, + { 0x16, 6 }, + { 0x16A, 9 }, + { 0x16B1, 13 }, + { 0x17, 7 }, + { 0x5B, 7 }, + { 0x6, 3 }, + { 0x7, 3 }, + { 0x1, 4 }, + { 0x0, 4 }, + { 0xA, 6 }, + { 0x2D7, 10 }, + { 0xB5A, 12 }, + { 0x16B0, 13 }, + { 0x16B3, 13 }, + { 0x16B2, 13 }, + { 0x2D6D, 14 }, + { 0x2D6C, 14 }, + { 0x2D6F, 14 }, + { 0x2D6E, 14 }, + { 0x6, 4 }, + { 0xA, 5 }, + { 0x4, 5 }, + { 0x2C, 6 }, + { 0x17, 6 }, + { 0x3, 4 }, + { 0x7, 4 }, + { 0x16, 7 }, + { 0xB4, 8 } + }, + { /* AC bias group 4, table 12 */ + { 0x5, 3 }, + { 0xD, 4 }, + { 0x5, 4 }, + { 0x9, 4 }, + { 0x33, 6 }, + { 0x193, 9 }, + { 0x192C, 13 }, + { 0x61, 8 }, + { 0x31, 7 }, + { 0x0, 2 }, + { 0x7, 3 }, + { 0x10, 5 }, + { 0x11, 5 }, + { 0xC8, 8 }, + { 0x192F, 13 }, + { 0x325B, 14 }, + { 0x325A, 14 }, + { 0x1929, 13 }, + { 0x1928, 13 }, + { 0x192B, 13 }, + { 0x192A, 13 }, + { 0x325D, 14 }, + { 0x325C, 14 }, + { 0x18, 5 }, + { 0x1A, 6 }, + { 0x1B, 6 }, + { 0x65, 7 }, + { 0x19, 6 }, + { 0x4, 4 }, + { 0x7, 4 }, + { 0x60, 8 }, + { 0x324, 10 } + }, + { /* AC bias group 4, table 13 */ + { 0x6, 3 }, + { 0x0, 3 }, + { 0x2, 4 }, + { 0xF, 4 }, + { 0x39, 6 }, + { 0x1D9, 9 }, + { 0x1D82, 13 }, + { 0x761, 11 }, + { 0x3BE, 10 }, + { 0x1, 2 }, + { 0x2, 2 }, + { 0xF, 6 }, + { 0xE, 6 }, + { 0x762, 11 }, + { 0x3B07, 14 }, + { 0x3B06, 14 }, + { 0x3B1D, 14 }, + { 0x3B1C, 14 }, + { 0x3B1F, 14 }, + { 0x3B1E, 14 }, + { 0x3B19, 14 }, + { 0x3B18, 14 }, + { 0x3B1B, 14 }, + { 0x38, 6 }, + { 0x1DE, 9 }, + { 0xED, 8 }, + { 0x3BF, 10 }, + { 0xEE, 8 }, + { 0x3A, 6 }, + { 0x6, 5 }, + { 0xEC0, 12 }, + { 0x3B1A, 14 } + }, + { /* AC bias group 4, table 14 */ + { 0x0, 2 }, + { 0x2, 3 }, + { 0xF, 5 }, + { 0x6, 4 }, + { 0x1C, 6 }, + { 0x1D0, 10 }, + { 0xE8C, 13 }, + { 0x1D1B, 14 }, + { 0x1D1A, 14 }, + { 0x3, 2 }, + { 0x2, 2 }, + { 0xEA, 9 }, + { 0xE9, 9 }, + { 0xE89, 13 }, + { 0xE88, 13 }, + { 0xE8B, 13 }, + { 0xE8A, 13 }, + { 0x1D65, 14 }, + { 0x1D64, 14 }, + { 0x1D67, 14 }, + { 0x1D66, 14 }, + { 0x1D61, 14 }, + { 0x1D60, 14 }, + { 0x3AD, 11 }, + { 0x1D63, 14 }, + { 0x1D62, 14 }, + { 0x1D1D, 14 }, + { 0x1D1C, 14 }, + { 0x3B, 7 }, + { 0x1D7, 10 }, + { 0x1D1F, 14 }, + { 0x1D1E, 14 } + }, + { /* AC bias group 4, table 15 */ + { 0x2, 2 }, + { 0xF, 4 }, + { 0x1C, 5 }, + { 0xC, 4 }, + { 0x3B, 6 }, + { 0x1AC, 9 }, + { 0x1AD8, 13 }, + { 0x35B3, 14 }, + { 0x35B2, 14 }, + { 0x1, 2 }, + { 0x0, 2 }, + { 0x69, 7 }, + { 0x68, 7 }, + { 0x35BD, 14 }, + { 0x35BC, 14 }, + { 0x35BF, 14 }, + { 0x35BE, 14 }, + { 0x35B9, 14 }, + { 0x35B8, 14 }, + { 0x35BB, 14 }, + { 0x35BA, 14 }, + { 0x35B5, 14 }, + { 0x35B4, 14 }, + { 0x1A9, 9 }, + { 0x1A8, 9 }, + { 0x35A, 10 }, + { 0xD7, 8 }, + { 0xD5, 8 }, + { 0x3A, 6 }, + { 0x1B, 5 }, + { 0x35B7, 14 }, + { 0x35B6, 14 } + } }; #endif /* AVCODEC_VP3DATA_H */ diff --git a/libavcodec/vp3dsp.c b/libavcodec/vp3dsp.c index 56566293d..6cf7e129f 100644 --- a/libavcodec/vp3dsp.c +++ b/libavcodec/vp3dsp.c @@ -26,8 +26,9 @@ #include "libavutil/attributes.h" #include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + #include "avcodec.h" -#include "dsputil.h" #include "rnd_avg.h" #include "vp3dsp.h" @@ -40,9 +41,10 @@ #define xC6S2 25080 #define xC7S1 12785 -#define M(a,b) (((a) * (b))>>16) +#define M(a, b) (((a) * (b)) >> 16) -static av_always_inline void idct(uint8_t *dst, int stride, int16_t *input, int type) +static av_always_inline void idct(uint8_t *dst, int stride, + int16_t *input, int type) { int16_t *ip = input; @@ -54,8 +56,8 @@ static av_always_inline void idct(uint8_t *dst, int stride, int16_t *input, int /* Inverse DCT on the rows now */ for (i = 0; i < 8; i++) { /* Check for non-zero values */ - if ( ip[0 * 8] | ip[1 * 8] | ip[2 * 8] | ip[3 * 8] | - ip[4 * 8] | ip[5 * 8] | ip[6 * 8] | ip[7 * 8] ) { + if (ip[0 * 8] | ip[1 * 8] | ip[2 * 8] | ip[3 * 8] | + ip[4 * 8] | ip[5 * 8] | ip[6 * 8] | ip[7 * 8]) { A = M(xC1S7, ip[1 * 8]) + M(xC7S1, ip[7 * 8]); B = M(xC7S1, ip[1 * 8]) - M(xC1S7, ip[7 * 8]); C = M(xC3S5, ip[3 * 8]) + M(xC5S3, ip[5 * 8]); @@ -83,14 +85,14 @@ static av_always_inline void idct(uint8_t *dst, int stride, int16_t *input, int Hd = Bd + H; /* Final sequence of operations over-write original inputs. */ - ip[0 * 8] = Gd + Cd ; - ip[7 * 8] = Gd - Cd ; + ip[0 * 8] = Gd + Cd; + ip[7 * 8] = Gd - Cd; ip[1 * 8] = Add + Hd; ip[2 * 8] = Add - Hd; - ip[3 * 8] = Ed + Dd ; - ip[4 * 8] = Ed - Dd ; + ip[3 * 8] = Ed + Dd; + ip[4 * 8] = Ed - Dd; ip[5 * 8] = Fd + Bdd; ip[6 * 8] = Fd - Bdd; @@ -101,11 +103,10 @@ static av_always_inline void idct(uint8_t *dst, int stride, int16_t *input, int ip = input; - for ( i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { /* Check for non-zero values (bitwise or faster than ||) */ - if ( ip[1] | ip[2] | ip[3] | - ip[4] | ip[5] | ip[6] | ip[7] ) { - + if (ip[1] | ip[2] | ip[3] | + ip[4] | ip[5] | ip[6] | ip[7]) { A = M(xC1S7, ip[1]) + M(xC7S1, ip[7]); B = M(xC7S1, ip[1]) - M(xC1S7, ip[7]); C = M(xC3S5, ip[3]) + M(xC5S3, ip[5]); @@ -120,9 +121,9 @@ static av_always_inline void idct(uint8_t *dst, int stride, int16_t *input, int E = M(xC4S4, (ip[0] + ip[4])) + 8; F = M(xC4S4, (ip[0] - ip[4])) + 8; - if(type==1){ //HACK - E += 16*128; - F += 16*128; + if (type == 1) { // HACK + E += 16 * 128; + F += 16 * 128; } G = M(xC2S6, ip[2]) + M(xC6S2, ip[6]); @@ -139,52 +140,51 @@ static av_always_inline void idct(uint8_t *dst, int stride, int16_t *input, int /* Final sequence of operations over-write original inputs. */ if (type == 1) { - dst[0*stride] = av_clip_uint8((Gd + Cd ) >> 4); - dst[7*stride] = av_clip_uint8((Gd - Cd ) >> 4); + dst[0 * stride] = av_clip_uint8((Gd + Cd) >> 4); + dst[7 * stride] = av_clip_uint8((Gd - Cd) >> 4); - dst[1*stride] = av_clip_uint8((Add + Hd ) >> 4); - dst[2*stride] = av_clip_uint8((Add - Hd ) >> 4); + dst[1 * stride] = av_clip_uint8((Add + Hd) >> 4); + dst[2 * stride] = av_clip_uint8((Add - Hd) >> 4); - dst[3*stride] = av_clip_uint8((Ed + Dd ) >> 4); - dst[4*stride] = av_clip_uint8((Ed - Dd ) >> 4); + dst[3 * stride] = av_clip_uint8((Ed + Dd) >> 4); + dst[4 * stride] = av_clip_uint8((Ed - Dd) >> 4); - dst[5*stride] = av_clip_uint8((Fd + Bdd ) >> 4); - dst[6*stride] = av_clip_uint8((Fd - Bdd ) >> 4); - }else{ - dst[0*stride] = av_clip_uint8(dst[0*stride] + ((Gd + Cd ) >> 4)); - dst[7*stride] = av_clip_uint8(dst[7*stride] + ((Gd - Cd ) >> 4)); + dst[5 * stride] = av_clip_uint8((Fd + Bdd) >> 4); + dst[6 * stride] = av_clip_uint8((Fd - Bdd) >> 4); + } else { + dst[0 * stride] = av_clip_uint8(dst[0 * stride] + ((Gd + Cd) >> 4)); + dst[7 * stride] = av_clip_uint8(dst[7 * stride] + ((Gd - Cd) >> 4)); - dst[1*stride] = av_clip_uint8(dst[1*stride] + ((Add + Hd ) >> 4)); - dst[2*stride] = av_clip_uint8(dst[2*stride] + ((Add - Hd ) >> 4)); + dst[1 * stride] = av_clip_uint8(dst[1 * stride] + ((Add + Hd) >> 4)); + dst[2 * stride] = av_clip_uint8(dst[2 * stride] + ((Add - Hd) >> 4)); - dst[3*stride] = av_clip_uint8(dst[3*stride] + ((Ed + Dd ) >> 4)); - dst[4*stride] = av_clip_uint8(dst[4*stride] + ((Ed - Dd ) >> 4)); + dst[3 * stride] = av_clip_uint8(dst[3 * stride] + ((Ed + Dd) >> 4)); + dst[4 * stride] = av_clip_uint8(dst[4 * stride] + ((Ed - Dd) >> 4)); - dst[5*stride] = av_clip_uint8(dst[5*stride] + ((Fd + Bdd ) >> 4)); - dst[6*stride] = av_clip_uint8(dst[6*stride] + ((Fd - Bdd ) >> 4)); + dst[5 * stride] = av_clip_uint8(dst[5 * stride] + ((Fd + Bdd) >> 4)); + dst[6 * stride] = av_clip_uint8(dst[6 * stride] + ((Fd - Bdd) >> 4)); } - } else { if (type == 1) { - dst[0*stride]= - dst[1*stride]= - dst[2*stride]= - dst[3*stride]= - dst[4*stride]= - dst[5*stride]= - dst[6*stride]= - dst[7*stride]= av_clip_uint8(128 + ((xC4S4 * ip[0] + (IdctAdjustBeforeShift<<16))>>20)); - }else{ - if(ip[0]){ - int v= ((xC4S4 * ip[0] + (IdctAdjustBeforeShift<<16))>>20); - dst[0*stride] = av_clip_uint8(dst[0*stride] + v); - dst[1*stride] = av_clip_uint8(dst[1*stride] + v); - dst[2*stride] = av_clip_uint8(dst[2*stride] + v); - dst[3*stride] = av_clip_uint8(dst[3*stride] + v); - dst[4*stride] = av_clip_uint8(dst[4*stride] + v); - dst[5*stride] = av_clip_uint8(dst[5*stride] + v); - dst[6*stride] = av_clip_uint8(dst[6*stride] + v); - dst[7*stride] = av_clip_uint8(dst[7*stride] + v); + dst[0*stride] = + dst[1*stride] = + dst[2*stride] = + dst[3*stride] = + dst[4*stride] = + dst[5*stride] = + dst[6*stride] = + dst[7*stride] = av_clip_uint8(128 + ((xC4S4 * ip[0] + (IdctAdjustBeforeShift << 16)) >> 20)); + } else { + if (ip[0]) { + int v = (xC4S4 * ip[0] + (IdctAdjustBeforeShift << 16)) >> 20; + dst[0 * stride] = av_clip_uint8(dst[0 * stride] + v); + dst[1 * stride] = av_clip_uint8(dst[1 * stride] + v); + dst[2 * stride] = av_clip_uint8(dst[2 * stride] + v); + dst[3 * stride] = av_clip_uint8(dst[3 * stride] + v); + dst[4 * stride] = av_clip_uint8(dst[4 * stride] + v); + dst[5 * stride] = av_clip_uint8(dst[5 * stride] + v); + dst[6 * stride] = av_clip_uint8(dst[6 * stride] + v); + dst[7 * stride] = av_clip_uint8(dst[7 * stride] + v); } } } @@ -194,26 +194,26 @@ static av_always_inline void idct(uint8_t *dst, int stride, int16_t *input, int } } -static void vp3_idct_put_c(uint8_t *dest/*align 8*/, int line_size, - int16_t *block/*align 16*/) +static void vp3_idct_put_c(uint8_t *dest /* align 8 */, int line_size, + int16_t *block /* align 16 */) { idct(dest, line_size, block, 1); memset(block, 0, sizeof(*block) * 64); } -static void vp3_idct_add_c(uint8_t *dest/*align 8*/, int line_size, - int16_t *block/*align 16*/) +static void vp3_idct_add_c(uint8_t *dest /* align 8 */, int line_size, + int16_t *block /* align 16 */) { idct(dest, line_size, block, 2); memset(block, 0, sizeof(*block) * 64); } -static void vp3_idct_dc_add_c(uint8_t *dest/*align 8*/, int line_size, - int16_t *block/*align 16*/) +static void vp3_idct_dc_add_c(uint8_t *dest /* align 8 */, int line_size, + int16_t *block /* align 16 */) { int i, dc = (block[0] + 15) >> 5; - for(i = 0; i < 8; i++){ + for (i = 0; i < 8; i++) { dest[0] = av_clip_uint8(dest[0] + dc); dest[1] = av_clip_uint8(dest[1] + dc); dest[2] = av_clip_uint8(dest[2] + dc); @@ -222,7 +222,7 @@ 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 += line_size; } block[0] = 0; } @@ -232,15 +232,15 @@ static void vp3_v_loop_filter_c(uint8_t *first_pixel, int stride, { unsigned char *end; int filter_value; - const int nstride= -stride; + const int nstride = -stride; - for (end= first_pixel + 8; first_pixel < end; first_pixel++) { - filter_value = - (first_pixel[2 * nstride] - first_pixel[ stride]) - +3*(first_pixel[0 ] - first_pixel[nstride]); + for (end = first_pixel + 8; first_pixel < end; first_pixel++) { + filter_value = (first_pixel[2 * nstride] - first_pixel[stride]) + + (first_pixel[0] - first_pixel[nstride]) * 3; filter_value = bounding_values[(filter_value + 4) >> 3]; + first_pixel[nstride] = av_clip_uint8(first_pixel[nstride] + filter_value); - first_pixel[0] = av_clip_uint8(first_pixel[0] - filter_value); + first_pixel[0] = av_clip_uint8(first_pixel[0] - filter_value); } } @@ -250,11 +250,11 @@ static void vp3_h_loop_filter_c(uint8_t *first_pixel, int stride, unsigned char *end; int filter_value; - for (end= first_pixel + 8*stride; first_pixel != end; first_pixel += stride) { - filter_value = - (first_pixel[-2] - first_pixel[ 1]) - +3*(first_pixel[ 0] - first_pixel[-1]); + for (end = first_pixel + 8 * stride; first_pixel != end; first_pixel += stride) { + filter_value = (first_pixel[-2] - first_pixel[1]) + + (first_pixel[ 0] - first_pixel[-1]) * 3; filter_value = bounding_values[(filter_value + 4) >> 3]; + first_pixel[-1] = av_clip_uint8(first_pixel[-1] + filter_value); first_pixel[ 0] = av_clip_uint8(first_pixel[ 0] - filter_value); } @@ -289,8 +289,6 @@ av_cold void ff_vp3dsp_init(VP3DSPContext *c, int flags) if (ARCH_ARM) ff_vp3dsp_init_arm(c, flags); - if (ARCH_BFIN) - ff_vp3dsp_init_bfin(c, flags); if (ARCH_PPC) ff_vp3dsp_init_ppc(c, flags); if (ARCH_X86) diff --git a/libavcodec/vp3dsp.h b/libavcodec/vp3dsp.h index 3aded9927..b95adae79 100644 --- a/libavcodec/vp3dsp.h +++ b/libavcodec/vp3dsp.h @@ -47,7 +47,6 @@ typedef struct VP3DSPContext { void ff_vp3dsp_init(VP3DSPContext *c, int flags); void ff_vp3dsp_init_arm(VP3DSPContext *c, int flags); -void ff_vp3dsp_init_bfin(VP3DSPContext *c, int flags); void ff_vp3dsp_init_ppc(VP3DSPContext *c, int flags); void ff_vp3dsp_init_x86(VP3DSPContext *c, int flags); diff --git a/libavcodec/vp5.c b/libavcodec/vp5.c index 756dc9270..1923d6335 100644 --- a/libavcodec/vp5.c +++ b/libavcodec/vp5.c @@ -85,7 +85,7 @@ static void vp5_parse_vector_adjustment(VP56Context *s, VP56mv *vect) for (comp=0; comp<2; comp++) { int delta = 0; - if (vp56_rac_get_prob(c, model->vector_dct[comp])) { + if (vp56_rac_get_prob_branchy(c, model->vector_dct[comp])) { int sign = vp56_rac_get_prob(c, model->vector_sig[comp]); di = vp56_rac_get_prob(c, model->vector_pdi[comp][0]); di |= vp56_rac_get_prob(c, model->vector_pdi[comp][1]) << 1; @@ -108,19 +108,19 @@ static void vp5_parse_vector_models(VP56Context *s) int comp, node; for (comp=0; comp<2; comp++) { - if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][0])) + if (vp56_rac_get_prob_branchy(c, vp5_vmc_pct[comp][0])) model->vector_dct[comp] = vp56_rac_gets_nn(c, 7); - if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][1])) + if (vp56_rac_get_prob_branchy(c, vp5_vmc_pct[comp][1])) model->vector_sig[comp] = vp56_rac_gets_nn(c, 7); - if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][2])) + if (vp56_rac_get_prob_branchy(c, vp5_vmc_pct[comp][2])) model->vector_pdi[comp][0] = vp56_rac_gets_nn(c, 7); - if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][3])) + if (vp56_rac_get_prob_branchy(c, vp5_vmc_pct[comp][3])) model->vector_pdi[comp][1] = vp56_rac_gets_nn(c, 7); } for (comp=0; comp<2; comp++) for (node=0; node<7; node++) - if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][4 + node])) + if (vp56_rac_get_prob_branchy(c, vp5_vmc_pct[comp][4 + node])) model->vector_pdv[comp][node] = vp56_rac_gets_nn(c, 7); } @@ -137,7 +137,7 @@ static int vp5_parse_coeff_models(VP56Context *s) for (pt=0; pt<2; pt++) for (node=0; node<11; node++) - if (vp56_rac_get_prob(c, vp5_dccv_pct[pt][node])) { + if (vp56_rac_get_prob_branchy(c, vp5_dccv_pct[pt][node])) { def_prob[node] = vp56_rac_gets_nn(c, 7); model->coeff_dccv[pt][node] = def_prob[node]; } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) { @@ -148,7 +148,7 @@ static int vp5_parse_coeff_models(VP56Context *s) for (pt=0; pt<2; pt++) for (cg=0; cg<6; cg++) for (node=0; node<11; node++) - if (vp56_rac_get_prob(c, vp5_ract_pct[ct][pt][cg][node])) { + if (vp56_rac_get_prob_branchy(c, vp5_ract_pct[ct][pt][cg][node])) { def_prob[node] = vp56_rac_gets_nn(c, 7); model->coeff_ract[pt][ct][cg][node] = def_prob[node]; } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) { @@ -193,9 +193,9 @@ static void vp5_parse_coeff(VP56Context *s) coeff_idx = 0; for (;;) { - if (vp56_rac_get_prob(c, model2[0])) { - if (vp56_rac_get_prob(c, model2[2])) { - if (vp56_rac_get_prob(c, model2[3])) { + if (vp56_rac_get_prob_branchy(c, model2[0])) { + if (vp56_rac_get_prob_branchy(c, model2[2])) { + if (vp56_rac_get_prob_branchy(c, model2[3])) { s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 4; idx = vp56_rac_get_tree(c, ff_vp56_pc_tree, model1); sign = vp56_rac_get(c); @@ -203,7 +203,7 @@ static void vp5_parse_coeff(VP56Context *s) for (i=ff_vp56_coeff_bit_length[idx]; i>=0; i--) coeff += vp56_rac_get_prob(c, ff_vp56_coeff_parse_table[idx][i]) << i; } else { - if (vp56_rac_get_prob(c, model2[4])) { + if (vp56_rac_get_prob_branchy(c, model2[4])) { coeff = 3 + vp56_rac_get_prob(c, model1[5]); s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 3; } else { @@ -224,7 +224,7 @@ static void vp5_parse_coeff(VP56Context *s) coeff *= s->dequant_ac; s->block_coeff[b][permute[coeff_idx]] = coeff; } else { - if (ct && !vp56_rac_get_prob(c, model2[1])) + if (ct && !vp56_rac_get_prob_branchy(c, model2[1])) break; ct = 0; s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 0; diff --git a/libavcodec/vp56.c b/libavcodec/vp56.c index 7c91c5433..ba39b5643 100644 --- a/libavcodec/vp56.c +++ b/libavcodec/vp56.c @@ -83,16 +83,16 @@ static void vp56_parse_mb_type_models(VP56Context *s) int i, ctx, type; for (ctx=0; ctx<3; ctx++) { - if (vp56_rac_get_prob(c, 174)) { + if (vp56_rac_get_prob_branchy(c, 174)) { int idx = vp56_rac_gets(c, 4); memcpy(model->mb_types_stats[ctx], ff_vp56_pre_def_mb_type_stats[idx][ctx], sizeof(model->mb_types_stats[ctx])); } - if (vp56_rac_get_prob(c, 254)) { + if (vp56_rac_get_prob_branchy(c, 254)) { for (type=0; type<10; type++) { for(i=0; i<2; i++) { - if (vp56_rac_get_prob(c, 205)) { + if (vp56_rac_get_prob_branchy(c, 205)) { int delta, sign = vp56_rac_get(c); delta = vp56_rac_get_tree(c, ff_vp56_pmbtm_tree, @@ -153,7 +153,7 @@ static VP56mb vp56_parse_mb_type(VP56Context *s, uint8_t *mb_type_model = s->modelp->mb_type[ctx][prev_type]; VP56RangeCoder *c = &s->c; - if (vp56_rac_get_prob(c, mb_type_model[0])) + if (vp56_rac_get_prob_branchy(c, mb_type_model[0])) return prev_type; else return vp56_rac_get_tree(c, ff_vp56_pmbt_tree, mb_type_model); diff --git a/libavcodec/vp56.h b/libavcodec/vp56.h index 9a9529692..1af5eaf50 100644 --- a/libavcodec/vp56.h +++ b/libavcodec/vp56.h @@ -26,7 +26,6 @@ #ifndef AVCODEC_VP56_H #define AVCODEC_VP56_H -#include "dsputil.h" #include "get_bits.h" #include "hpeldsp.h" #include "bytestream.h" @@ -364,7 +363,7 @@ int vp56_rac_get_tree(VP56RangeCoder *c, const uint8_t *probs) { while (tree->val > 0) { - if (vp56_rac_get_prob(c, probs[tree->prob_idx])) + if (vp56_rac_get_prob_branchy(c, probs[tree->prob_idx])) tree += tree->val; else tree++; diff --git a/libavcodec/vp56rac.c b/libavcodec/vp56rac.c index f11531de2..6061b7ee7 100644 --- a/libavcodec/vp56rac.c +++ b/libavcodec/vp56rac.c @@ -1,6 +1,6 @@ /* * VP5/6/8 decoder - * Copyright (c) 2010 Jason Garrett-Glaser + * Copyright (c) 2010 Fiona Glaser * * This file is part of FFmpeg. * diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c index f552524db..a18b8ff52 100644 --- a/libavcodec/vp6.c +++ b/libavcodec/vp6.c @@ -211,20 +211,20 @@ static void vp6_parse_vector_models(VP56Context *s) int comp, node; for (comp=0; comp<2; comp++) { - if (vp56_rac_get_prob(c, vp6_sig_dct_pct[comp][0])) + if (vp56_rac_get_prob_branchy(c, vp6_sig_dct_pct[comp][0])) model->vector_dct[comp] = vp56_rac_gets_nn(c, 7); - if (vp56_rac_get_prob(c, vp6_sig_dct_pct[comp][1])) + if (vp56_rac_get_prob_branchy(c, vp6_sig_dct_pct[comp][1])) model->vector_sig[comp] = vp56_rac_gets_nn(c, 7); } for (comp=0; comp<2; comp++) for (node=0; node<7; node++) - if (vp56_rac_get_prob(c, vp6_pdv_pct[comp][node])) + if (vp56_rac_get_prob_branchy(c, vp6_pdv_pct[comp][node])) model->vector_pdv[comp][node] = vp56_rac_gets_nn(c, 7); for (comp=0; comp<2; comp++) for (node=0; node<8; node++) - if (vp56_rac_get_prob(c, vp6_fdv_pct[comp][node])) + if (vp56_rac_get_prob_branchy(c, vp6_fdv_pct[comp][node])) model->vector_fdv[comp][node] = vp56_rac_gets_nn(c, 7); } @@ -270,7 +270,7 @@ static int vp6_parse_coeff_models(VP56Context *s) for (pt=0; pt<2; pt++) for (node=0; node<11; node++) - if (vp56_rac_get_prob(c, vp6_dccv_pct[pt][node])) { + if (vp56_rac_get_prob_branchy(c, vp6_dccv_pct[pt][node])) { def_prob[node] = vp56_rac_gets_nn(c, 7); model->coeff_dccv[pt][node] = def_prob[node]; } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) { @@ -279,21 +279,21 @@ static int vp6_parse_coeff_models(VP56Context *s) if (vp56_rac_get(c)) { for (pos=1; pos<64; pos++) - if (vp56_rac_get_prob(c, vp6_coeff_reorder_pct[pos])) + if (vp56_rac_get_prob_branchy(c, vp6_coeff_reorder_pct[pos])) model->coeff_reorder[pos] = vp56_rac_gets(c, 4); vp6_coeff_order_table_init(s); } for (cg=0; cg<2; cg++) for (node=0; node<14; node++) - if (vp56_rac_get_prob(c, vp6_runv_pct[cg][node])) + if (vp56_rac_get_prob_branchy(c, vp6_runv_pct[cg][node])) model->coeff_runv[cg][node] = vp56_rac_gets_nn(c, 7); for (ct=0; ct<3; ct++) for (pt=0; pt<2; pt++) for (cg=0; cg<6; cg++) for (node=0; node<11; node++) - if (vp56_rac_get_prob(c, vp6_ract_pct[ct][pt][cg][node])) { + if (vp56_rac_get_prob_branchy(c, vp6_ract_pct[ct][pt][cg][node])) { def_prob[node] = vp56_rac_gets_nn(c, 7); model->coeff_ract[pt][ct][cg][node] = def_prob[node]; } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) { @@ -339,7 +339,7 @@ static void vp6_parse_vector_adjustment(VP56Context *s, VP56mv *vect) for (comp=0; comp<2; comp++) { int i, delta = 0; - if (vp56_rac_get_prob(c, model->vector_dct[comp])) { + if (vp56_rac_get_prob_branchy(c, model->vector_dct[comp])) { static const uint8_t prob_order[] = {0, 1, 2, 7, 6, 5, 4}; for (i=0; ivector_pdv[comp]); } - if (delta && vp56_rac_get_prob(c, model->vector_sig[comp])) + if (delta && vp56_rac_get_prob_branchy(c, model->vector_sig[comp])) delta = -delta; if (!comp) @@ -462,16 +462,16 @@ static void vp6_parse_coeff(VP56Context *s) coeff_idx = 0; for (;;) { - if ((coeff_idx>1 && ct==0) || vp56_rac_get_prob(c, model2[0])) { + if ((coeff_idx>1 && ct==0) || vp56_rac_get_prob_branchy(c, model2[0])) { /* parse a coeff */ - if (vp56_rac_get_prob(c, model2[2])) { - if (vp56_rac_get_prob(c, model2[3])) { + if (vp56_rac_get_prob_branchy(c, model2[2])) { + if (vp56_rac_get_prob_branchy(c, model2[3])) { idx = vp56_rac_get_tree(c, ff_vp56_pc_tree, model1); coeff = ff_vp56_coeff_bias[idx+5]; for (i=ff_vp56_coeff_bit_length[idx]; i>=0; i--) coeff += vp56_rac_get_prob(c, ff_vp56_coeff_parse_table[idx][i]) << i; } else { - if (vp56_rac_get_prob(c, model2[4])) + if (vp56_rac_get_prob_branchy(c, model2[4])) coeff = 3 + vp56_rac_get_prob(c, model1[5]); else coeff = 2; @@ -492,7 +492,7 @@ static void vp6_parse_coeff(VP56Context *s) /* parse a run */ ct = 0; if (coeff_idx > 0) { - if (!vp56_rac_get_prob(c, model2[1])) + if (!vp56_rac_get_prob_branchy(c, model2[1])) break; model3 = model->coeff_runv[coeff_idx >= 6]; diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index 296eb9820..60accf634 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -1,10 +1,11 @@ /* - * VP8 compatible video decoder + * VP7/VP8 compatible video decoder * * Copyright (C) 2010 David Conrad * Copyright (C) 2010 Ronald S. Bultje - * Copyright (C) 2010 Jason Garrett-Glaser + * Copyright (C) 2010 Fiona Glaser * Copyright (C) 2012 Daniel Kang + * Copyright (C) 2014 Peter Ross * * This file is part of FFmpeg. * @@ -24,17 +25,26 @@ */ #include "libavutil/imgutils.h" + #include "avcodec.h" #include "internal.h" -#include "vp8.h" -#include "vp8data.h" #include "rectangle.h" #include "thread.h" +#include "vp8.h" +#include "vp8data.h" #if ARCH_ARM # include "arm/vp8.h" #endif +#if CONFIG_VP7_DECODER && CONFIG_VP8_DECODER +#define VPX(vp7, f) (vp7 ? vp7_ ## f : vp8_ ## f) +#elif CONFIG_VP7_DECODER +#define VPX(vp7, f) vp7_ ## f +#else // CONFIG_VP8_DECODER +#define VPX(vp7, f) vp8_ ## f +#endif + static void free_buffers(VP8Context *s) { int i; @@ -74,6 +84,7 @@ static void vp8_release_frame(VP8Context *s, VP8Frame *f) ff_thread_release_buffer(s->avctx, &f->tf); } +#if CONFIG_VP8_DECODER static int vp8_ref_frame(VP8Context *s, VP8Frame *dst, VP8Frame *src) { int ret; @@ -90,7 +101,7 @@ static int vp8_ref_frame(VP8Context *s, VP8Frame *dst, VP8Frame *src) return 0; } - +#endif /* CONFIG_VP8_DECODER */ static void vp8_decode_flush_impl(AVCodecContext *avctx, int free_mem) { @@ -110,7 +121,32 @@ static void vp8_decode_flush(AVCodecContext *avctx) vp8_decode_flush_impl(avctx, 0); } -static int update_dimensions(VP8Context *s, int width, int height) +static VP8Frame *vp8_find_free_buffer(VP8Context *s) +{ + VP8Frame *frame = NULL; + int i; + + // find a free buffer + for (i = 0; i < 5; i++) + if (&s->frames[i] != s->framep[VP56_FRAME_CURRENT] && + &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] && + &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] && + &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) { + frame = &s->frames[i]; + break; + } + if (i == 5) { + av_log(s->avctx, AV_LOG_FATAL, "Ran out of free frames!\n"); + abort(); + } + if (frame->tf.f->data[0]) + vp8_release_frame(s, frame); + + return frame; +} + +static av_always_inline +int update_dimensions(VP8Context *s, int width, int height, int is_vp7) { AVCodecContext *avctx = s->avctx; int i, ret; @@ -124,22 +160,25 @@ static int update_dimensions(VP8Context *s, int width, int height) return ret; } - s->mb_width = (s->avctx->coded_width +15) / 16; - s->mb_height = (s->avctx->coded_height+15) / 16; + s->mb_width = (s->avctx->coded_width + 15) / 16; + s->mb_height = (s->avctx->coded_height + 15) / 16; - s->mb_layout = (avctx->active_thread_type == FF_THREAD_SLICE) && (FFMIN(s->num_coeff_partitions, avctx->thread_count) > 1); + s->mb_layout = is_vp7 || avctx->active_thread_type == FF_THREAD_SLICE && + FFMIN(s->num_coeff_partitions, avctx->thread_count) > 1; if (!s->mb_layout) { // Frame threading and one thread - s->macroblocks_base = av_mallocz((s->mb_width+s->mb_height*2+1)*sizeof(*s->macroblocks)); - s->intra4x4_pred_mode_top = av_mallocz(s->mb_width*4); - } - else // Sliced threading - s->macroblocks_base = av_mallocz((s->mb_width+2)*(s->mb_height+2)*sizeof(*s->macroblocks)); - s->top_nnz = av_mallocz(s->mb_width*sizeof(*s->top_nnz)); - s->top_border = av_mallocz((s->mb_width+1)*sizeof(*s->top_border)); - s->thread_data = av_mallocz(MAX_THREADS*sizeof(VP8ThreadData)); + s->macroblocks_base = av_mallocz((s->mb_width + s->mb_height * 2 + 1) * + sizeof(*s->macroblocks)); + s->intra4x4_pred_mode_top = av_mallocz(s->mb_width * 4); + } else // Sliced threading + s->macroblocks_base = av_mallocz((s->mb_width + 2) * (s->mb_height + 2) * + sizeof(*s->macroblocks)); + s->top_nnz = av_mallocz(s->mb_width * sizeof(*s->top_nnz)); + s->top_border = av_mallocz((s->mb_width + 1) * sizeof(*s->top_border)); + s->thread_data = av_mallocz(MAX_THREADS * sizeof(VP8ThreadData)); for (i = 0; i < MAX_THREADS; i++) { - s->thread_data[i].filter_strength = av_mallocz(s->mb_width*sizeof(*s->thread_data[0].filter_strength)); + s->thread_data[i].filter_strength = + av_mallocz(s->mb_width * sizeof(*s->thread_data[0].filter_strength)); #if HAVE_THREADS pthread_mutex_init(&s->thread_data[i].lock, NULL); pthread_cond_init(&s->thread_data[i].cond, NULL); @@ -150,11 +189,22 @@ static int update_dimensions(VP8Context *s, int width, int height) (!s->intra4x4_pred_mode_top && !s->mb_layout)) return AVERROR(ENOMEM); - s->macroblocks = s->macroblocks_base + 1; + s->macroblocks = s->macroblocks_base + 1; return 0; } +static int vp7_update_dimensions(VP8Context *s, int width, int height) +{ + return update_dimensions(s, width, height, IS_VP7); +} + +static int vp8_update_dimensions(VP8Context *s, int width, int height) +{ + return update_dimensions(s, width, height, IS_VP8); +} + + static void parse_segment_info(VP8Context *s) { VP56RangeCoder *c = &s->c; @@ -207,13 +257,13 @@ static int setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size) s->num_coeff_partitions = 1 << vp8_rac_get_uint(&s->c, 2); - buf += 3*(s->num_coeff_partitions-1); - buf_size -= 3*(s->num_coeff_partitions-1); + buf += 3 * (s->num_coeff_partitions - 1); + buf_size -= 3 * (s->num_coeff_partitions - 1); if (buf_size < 0) return -1; - for (i = 0; i < s->num_coeff_partitions-1; i++) { - int size = AV_RL24(sizes + 3*i); + for (i = 0; i < s->num_coeff_partitions - 1; i++) { + int size = AV_RL24(sizes + 3 * i); if (buf_size - size < 0) return -1; @@ -226,7 +276,26 @@ static int setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size) return 0; } -static void get_quants(VP8Context *s) +static void vp7_get_quants(VP8Context *s) +{ + VP56RangeCoder *c = &s->c; + + int yac_qi = vp8_rac_get_uint(c, 7); + int ydc_qi = vp8_rac_get(c) ? vp8_rac_get_uint(c, 7) : yac_qi; + int y2dc_qi = vp8_rac_get(c) ? vp8_rac_get_uint(c, 7) : yac_qi; + int y2ac_qi = vp8_rac_get(c) ? vp8_rac_get_uint(c, 7) : yac_qi; + int uvdc_qi = vp8_rac_get(c) ? vp8_rac_get_uint(c, 7) : yac_qi; + int uvac_qi = vp8_rac_get(c) ? vp8_rac_get_uint(c, 7) : yac_qi; + + s->qmat[0].luma_qmul[0] = vp7_ydc_qlookup[ydc_qi]; + s->qmat[0].luma_qmul[1] = vp7_yac_qlookup[yac_qi]; + s->qmat[0].luma_dc_qmul[0] = vp7_y2dc_qlookup[y2dc_qi]; + s->qmat[0].luma_dc_qmul[1] = vp7_y2ac_qlookup[y2ac_qi]; + s->qmat[0].chroma_qmul[0] = FFMIN(vp7_ydc_qlookup[uvdc_qi], 132); + s->qmat[0].chroma_qmul[1] = vp7_yac_qlookup[uvac_qi]; +} + +static void vp8_get_quants(VP8Context *s) { VP56RangeCoder *c = &s->c; int i, base_qi; @@ -246,13 +315,13 @@ static void get_quants(VP8Context *s) } else base_qi = yac_qi; - s->qmat[i].luma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + ydc_delta , 7)]; - s->qmat[i].luma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi , 7)]; - s->qmat[i].luma_dc_qmul[0] = 2 * vp8_dc_qlookup[av_clip_uintp2(base_qi + y2dc_delta, 7)]; + s->qmat[i].luma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + ydc_delta, 7)]; + s->qmat[i].luma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi, 7)]; + s->qmat[i].luma_dc_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + y2dc_delta, 7)] * 2; /* 101581>>16 is equivalent to 155/100 */ - s->qmat[i].luma_dc_qmul[1] = (101581 * vp8_ac_qlookup[av_clip_uintp2(base_qi + y2ac_delta, 7)]) >> 16; - s->qmat[i].chroma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + uvdc_delta, 7)]; - s->qmat[i].chroma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + uvac_delta, 7)]; + s->qmat[i].luma_dc_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + y2ac_delta, 7)] * 101581 >> 16; + s->qmat[i].chroma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + uvdc_delta, 7)]; + s->qmat[i].chroma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + uvac_delta, 7)]; s->qmat[i].luma_dc_qmul[1] = FFMAX(s->qmat[i].luma_dc_qmul[1], 8); s->qmat[i].chroma_qmul[0] = FFMIN(s->qmat[i].chroma_qmul[0], 132); @@ -288,6 +357,54 @@ static VP56Frame ref_to_update(VP8Context *s, int update, VP56Frame ref) return VP56_FRAME_NONE; } +static void vp78_reset_probability_tables(VP8Context *s) +{ + int i, j; + for (i = 0; i < 4; i++) + for (j = 0; j < 16; j++) + memcpy(s->prob->token[i][j], vp8_token_default_probs[i][vp8_coeff_band[j]], + sizeof(s->prob->token[i][j])); +} + +static void vp78_update_probability_tables(VP8Context *s) +{ + VP56RangeCoder *c = &s->c; + int i, j, k, l, m; + + for (i = 0; i < 4; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 3; k++) + for (l = 0; l < NUM_DCT_TOKENS-1; l++) + if (vp56_rac_get_prob_branchy(c, vp8_token_update_probs[i][j][k][l])) { + int prob = vp8_rac_get_uint(c, 8); + for (m = 0; vp8_coeff_band_indexes[j][m] >= 0; m++) + s->prob->token[i][vp8_coeff_band_indexes[j][m]][k][l] = prob; + } +} + +#define VP7_MVC_SIZE 17 +#define VP8_MVC_SIZE 19 + +static void vp78_update_pred16x16_pred8x8_mvc_probabilities(VP8Context *s, + int mvc_size) +{ + VP56RangeCoder *c = &s->c; + int i, j; + + if (vp8_rac_get(c)) + for (i = 0; i < 4; i++) + s->prob->pred16x16[i] = vp8_rac_get_uint(c, 8); + if (vp8_rac_get(c)) + for (i = 0; i < 3; i++) + s->prob->pred8x8c[i] = vp8_rac_get_uint(c, 8); + + // 17.2 MV probability update + for (i = 0; i < 2; i++) + for (j = 0; j < mvc_size; j++) + if (vp56_rac_get_prob_branchy(c, vp8_mv_update_prob[i][j])) + s->prob->mvc[i][j] = vp8_rac_get_nn(c); +} + static void update_refs(VP8Context *s) { VP56RangeCoder *c = &s->c; @@ -299,10 +416,220 @@ static void update_refs(VP8Context *s) s->update_altref = ref_to_update(s, update_altref, VP56_FRAME_GOLDEN2); } -static int decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size) +static void copy_chroma(AVFrame *dst, AVFrame *src, int width, int height) +{ + int i, j; + + for (j = 1; j < 3; j++) { + for (i = 0; i < height / 2; i++) + memcpy(dst->data[j] + i * dst->linesize[j], + src->data[j] + i * src->linesize[j], width / 2); + } +} + +static void fade(uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, + int width, int height, + int alpha, int beta) +{ + int i, j; + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + uint8_t y = src[j * src_linesize + i]; + dst[j * dst_linesize + i] = av_clip_uint8(y + ((y * beta) >> 8) + alpha); + } + } +} + +static int vp7_fade_frame(VP8Context *s, VP56RangeCoder *c) +{ + int alpha = (int8_t) vp8_rac_get_uint(c, 8); + int beta = (int8_t) vp8_rac_get_uint(c, 8); + int ret; + + if (!s->keyframe && (alpha || beta)) { + int width = s->mb_width * 16; + int height = s->mb_height * 16; + AVFrame *src, *dst; + + if (!s->framep[VP56_FRAME_PREVIOUS] || + !s->framep[VP56_FRAME_GOLDEN]) { + av_log(s->avctx, AV_LOG_WARNING, "Discarding interframe without a prior keyframe!\n"); + return AVERROR_INVALIDDATA; + } + + dst = + src = s->framep[VP56_FRAME_PREVIOUS]->tf.f; + + /* preserve the golden frame, write a new previous frame */ + if (s->framep[VP56_FRAME_GOLDEN] == s->framep[VP56_FRAME_PREVIOUS]) { + s->framep[VP56_FRAME_PREVIOUS] = vp8_find_free_buffer(s); + if ((ret = vp8_alloc_frame(s, s->framep[VP56_FRAME_PREVIOUS], 1)) < 0) + return ret; + + dst = s->framep[VP56_FRAME_PREVIOUS]->tf.f; + + copy_chroma(dst, src, width, height); + } + + fade(dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], + width, height, alpha, beta); + } + + return 0; +} + +static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size) { VP56RangeCoder *c = &s->c; - int header_size, hscale, vscale, i, j, k, l, m, ret; + int part1_size, hscale, vscale, i, j, ret; + int width = s->avctx->width; + int height = s->avctx->height; + + s->profile = (buf[0] >> 1) & 7; + if (s->profile > 1) { + avpriv_request_sample(s->avctx, "Unknown profile %d", s->profile); + return AVERROR_INVALIDDATA; + } + + s->keyframe = !(buf[0] & 1); + s->invisible = 0; + part1_size = AV_RL24(buf) >> 4; + + if (buf_size < 4 - s->profile + part1_size) { + av_log(s->avctx, AV_LOG_ERROR, "Buffer size %d is too small, needed : %d\n", buf_size, 4 - s->profile + part1_size); + return AVERROR_INVALIDDATA; + } + + buf += 4 - s->profile; + buf_size -= 4 - s->profile; + + 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); + buf += part1_size; + buf_size -= part1_size; + + /* A. Dimension information (keyframes only) */ + if (s->keyframe) { + width = vp8_rac_get_uint(c, 12); + height = vp8_rac_get_uint(c, 12); + hscale = vp8_rac_get_uint(c, 2); + vscale = vp8_rac_get_uint(c, 2); + if (hscale || vscale) + avpriv_request_sample(s->avctx, "Upscaling"); + + s->update_golden = s->update_altref = VP56_FRAME_CURRENT; + vp78_reset_probability_tables(s); + memcpy(s->prob->pred16x16, vp8_pred16x16_prob_inter, + sizeof(s->prob->pred16x16)); + memcpy(s->prob->pred8x8c, vp8_pred8x8c_prob_inter, + sizeof(s->prob->pred8x8c)); + for (i = 0; i < 2; i++) + memcpy(s->prob->mvc[i], vp7_mv_default_prob[i], + 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)); + } + + if (s->keyframe || s->profile > 0) + memset(s->inter_dc_pred, 0 , sizeof(s->inter_dc_pred)); + + /* B. Decoding information for all four macroblock-level features */ + for (i = 0; i < 4; i++) { + s->feature_enabled[i] = vp8_rac_get(c); + if (s->feature_enabled[i]) { + s->feature_present_prob[i] = vp8_rac_get_uint(c, 8); + + for (j = 0; j < 3; j++) + s->feature_index_prob[i][j] = + vp8_rac_get(c) ? vp8_rac_get_uint(c, 8) : 255; + + if (vp7_feature_value_size[s->profile][i]) + for (j = 0; j < 4; j++) + s->feature_value[i][j] = + vp8_rac_get(c) ? vp8_rac_get_uint(c, vp7_feature_value_size[s->profile][i]) : 0; + } + } + + s->segmentation.enabled = 0; + s->segmentation.update_map = 0; + s->lf_delta.enabled = 0; + + s->num_coeff_partitions = 1; + ff_vp56_init_range_decoder(&s->coeff_partition[0], buf, buf_size); + + if (!s->macroblocks_base || /* first frame */ + width != s->avctx->width || height != s->avctx->height || + (width + 15) / 16 != s->mb_width || (height + 15) / 16 != s->mb_height) { + if ((ret = vp7_update_dimensions(s, width, height)) < 0) + return ret; + } + + /* C. Dequantization indices */ + vp7_get_quants(s); + + /* D. Golden frame update flag (a Flag) for interframes only */ + if (!s->keyframe) { + s->update_golden = vp8_rac_get(c) ? VP56_FRAME_CURRENT : VP56_FRAME_NONE; + s->sign_bias[VP56_FRAME_GOLDEN] = 0; + } + + s->update_last = 1; + s->update_probabilities = 1; + s->fade_present = 1; + + if (s->profile > 0) { + s->update_probabilities = vp8_rac_get(c); + if (!s->update_probabilities) + s->prob[1] = s->prob[0]; + + if (!s->keyframe) + s->fade_present = vp8_rac_get(c); + } + + /* E. Fading information for previous frame */ + if (s->fade_present && vp8_rac_get(c)) { + if ((ret = vp7_fade_frame(s ,c)) < 0) + return ret; + } + + /* F. Loop filter type */ + if (!s->profile) + s->filter.simple = vp8_rac_get(c); + + /* 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)]; + + /* H. Loop filter levels */ + if (s->profile > 0) + s->filter.simple = vp8_rac_get(c); + s->filter.level = vp8_rac_get_uint(c, 6); + s->filter.sharpness = vp8_rac_get_uint(c, 3); + + /* I. DCT coefficient probability update; 13.3 Token Probability Updates */ + vp78_update_probability_tables(s); + + s->mbskip_enabled = 0; + + /* J. The remaining frame header data occurs ONLY FOR INTERFRAMES */ + if (!s->keyframe) { + s->prob->intra = vp8_rac_get_uint(c, 8); + s->prob->last = vp8_rac_get_uint(c, 8); + vp78_update_pred16x16_pred8x8_mvc_probabilities(s, VP7_MVC_SIZE); + } + + return 0; +} + +static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size) +{ + VP56RangeCoder *c = &s->c; + int header_size, hscale, vscale, ret; int width = s->avctx->width; int height = s->avctx->height; @@ -317,24 +644,27 @@ static int decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size) av_log(s->avctx, AV_LOG_WARNING, "Unknown profile %d\n", s->profile); if (!s->profile) - memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_epel_pixels_tab, sizeof(s->put_pixels_tab)); + memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_epel_pixels_tab, + sizeof(s->put_pixels_tab)); else // profile 1-3 use bilinear, 4+ aren't defined so whatever - memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_bilinear_pixels_tab, sizeof(s->put_pixels_tab)); + memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_bilinear_pixels_tab, + sizeof(s->put_pixels_tab)); - if (header_size > buf_size - 7*s->keyframe) { + if (header_size > buf_size - 7 * s->keyframe) { av_log(s->avctx, AV_LOG_ERROR, "Header size larger than data provided\n"); return AVERROR_INVALIDDATA; } if (s->keyframe) { if (AV_RL24(buf) != 0x2a019d) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid start code 0x%x\n", AV_RL24(buf)); + av_log(s->avctx, AV_LOG_ERROR, + "Invalid start code 0x%x\n", AV_RL24(buf)); return AVERROR_INVALIDDATA; } - width = AV_RL16(buf+3) & 0x3fff; - height = AV_RL16(buf+5) & 0x3fff; - hscale = buf[4] >> 6; - vscale = buf[6] >> 6; + width = AV_RL16(buf + 3) & 0x3fff; + height = AV_RL16(buf + 5) & 0x3fff; + hscale = buf[4] >> 6; + vscale = buf[6] >> 6; buf += 7; buf_size -= 7; @@ -342,13 +672,13 @@ static int decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size) avpriv_request_sample(s->avctx, "Upscaling"); s->update_golden = s->update_altref = VP56_FRAME_CURRENT; - for (i = 0; i < 4; i++) - for (j = 0; j < 16; j++) - memcpy(s->prob->token[i][j], vp8_token_default_probs[i][vp8_coeff_band[j]], - sizeof(s->prob->token[i][j])); - memcpy(s->prob->pred16x16, vp8_pred16x16_prob_inter, sizeof(s->prob->pred16x16)); - memcpy(s->prob->pred8x8c , vp8_pred8x8c_prob_inter , sizeof(s->prob->pred8x8c)); - memcpy(s->prob->mvc , vp8_mv_default_prob , sizeof(s->prob->mvc)); + vp78_reset_probability_tables(s); + memcpy(s->prob->pred16x16, vp8_pred16x16_prob_inter, + sizeof(s->prob->pred16x16)); + memcpy(s->prob->pred8x8c, vp8_pred8x8c_prob_inter, + sizeof(s->prob->pred8x8c)); + memcpy(s->prob->mvc, vp8_mv_default_prob, + sizeof(s->prob->mvc)); memset(&s->segmentation, 0, sizeof(s->segmentation)); memset(&s->lf_delta, 0, sizeof(s->lf_delta)); } @@ -382,12 +712,12 @@ static int decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size) } if (!s->macroblocks_base || /* first frame */ - width != s->avctx->width || height != s->avctx->height || (width+15)/16 != s->mb_width || (height+15)/16 != s->mb_height) { - if ((ret = update_dimensions(s, width, height)) < 0) + width != s->avctx->width || height != s->avctx->height || + (width+15)/16 != s->mb_width || (height+15)/16 != s->mb_height) + if ((ret = vp8_update_dimensions(s, width, height)) < 0) return ret; - } - get_quants(s); + vp8_get_quants(s); if (!s->keyframe) { update_refs(s); @@ -402,15 +732,7 @@ static int decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size) s->update_last = s->keyframe || vp8_rac_get(c); - for (i = 0; i < 4; i++) - for (j = 0; j < 8; j++) - for (k = 0; k < 3; k++) - for (l = 0; l < NUM_DCT_TOKENS-1; l++) - if (vp56_rac_get_prob_branchy(c, vp8_token_update_probs[i][j][k][l])) { - int prob = vp8_rac_get_uint(c, 8); - for (m = 0; vp8_coeff_band_indexes[j][m] >= 0; m++) - s->prob->token[i][vp8_coeff_band_indexes[j][m]][k][l] = prob; - } + vp78_update_probability_tables(s); if ((s->mbskip_enabled = vp8_rac_get(c))) s->prob->mbskip = vp8_rac_get_uint(c, 8); @@ -419,25 +741,14 @@ static int decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size) s->prob->intra = vp8_rac_get_uint(c, 8); s->prob->last = vp8_rac_get_uint(c, 8); s->prob->golden = vp8_rac_get_uint(c, 8); - - if (vp8_rac_get(c)) - for (i = 0; i < 4; i++) - s->prob->pred16x16[i] = vp8_rac_get_uint(c, 8); - if (vp8_rac_get(c)) - for (i = 0; i < 3; i++) - s->prob->pred8x8c[i] = vp8_rac_get_uint(c, 8); - - // 17.2 MV probability update - for (i = 0; i < 2; i++) - for (j = 0; j < 19; j++) - if (vp56_rac_get_prob_branchy(c, vp8_mv_update_prob[i][j])) - s->prob->mvc[i][j] = vp8_rac_get_nn(c); + vp78_update_pred16x16_pred8x8_mvc_probabilities(s, VP8_MVC_SIZE); } return 0; } -static av_always_inline void clamp_mv(VP8Context *s, VP56mv *dst, const VP56mv *src) +static av_always_inline +void clamp_mv(VP8Context *s, VP56mv *dst, const VP56mv *src) { dst->x = av_clip(src->x, s->mv_min.x, s->mv_max.x); dst->y = av_clip(src->y, s->mv_min.y, s->mv_max.y); @@ -446,7 +757,7 @@ static av_always_inline void clamp_mv(VP8Context *s, VP56mv *dst, const VP56mv * /** * Motion vector coding, 17.1. */ -static int read_mv_component(VP56RangeCoder *c, const uint8_t *p) +static av_always_inline int read_mv_component(VP56RangeCoder *c, const uint8_t *p, int vp7) { int bit, x = 0; @@ -455,33 +766,46 @@ static int read_mv_component(VP56RangeCoder *c, const uint8_t *p) for (i = 0; i < 3; i++) x += vp56_rac_get_prob(c, p[9 + i]) << i; - for (i = 9; i > 3; i--) + for (i = (vp7 ? 7 : 9); i > 3; i--) x += vp56_rac_get_prob(c, p[9 + i]) << i; - if (!(x & 0xFFF0) || vp56_rac_get_prob(c, p[12])) + if (!(x & (vp7 ? 0xF0 : 0xFFF0)) || vp56_rac_get_prob(c, p[12])) x += 8; } else { // small_mvtree - const uint8_t *ps = p+2; + const uint8_t *ps = p + 2; bit = vp56_rac_get_prob(c, *ps); - ps += 1 + 3*bit; - x += 4*bit; + ps += 1 + 3 * bit; + x += 4 * bit; bit = vp56_rac_get_prob(c, *ps); ps += 1 + bit; - x += 2*bit; + x += 2 * bit; x += vp56_rac_get_prob(c, *ps); } return (x && vp56_rac_get_prob(c, p[1])) ? -x : x; } -static av_always_inline -const uint8_t *get_submv_prob(uint32_t left, uint32_t top) +static int vp7_read_mv_component(VP56RangeCoder *c, const uint8_t *p) { + return read_mv_component(c, p, 1); +} + +static int vp8_read_mv_component(VP56RangeCoder *c, const uint8_t *p) +{ + return read_mv_component(c, p, 0); +} + +static av_always_inline +const uint8_t *get_submv_prob(uint32_t left, uint32_t top, int is_vp7) +{ + if (is_vp7) + return vp7_submv_prob; + if (left == top) - return vp8_submv_prob[4-!!left]; + return vp8_submv_prob[4 - !!left]; if (!top) return vp8_submv_prob[2]; - return vp8_submv_prob[1-!!left]; + return vp8_submv_prob[1 - !!left]; } /** @@ -489,15 +813,15 @@ const uint8_t *get_submv_prob(uint32_t left, uint32_t top) * @returns the number of motion vectors parsed (2, 4 or 16) */ static av_always_inline -int decode_splitmvs(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb, int layout) +int decode_splitmvs(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb, + int layout, int is_vp7) { int part_idx; int n, num; VP8Macroblock *top_mb; VP8Macroblock *left_mb = &mb[-1]; - const uint8_t *mbsplits_left = vp8_mbsplits[left_mb->partitioning], - *mbsplits_top, - *mbsplits_cur, *firstidx; + const uint8_t *mbsplits_left = vp8_mbsplits[left_mb->partitioning]; + const uint8_t *mbsplits_top, *mbsplits_cur, *firstidx; VP56mv *top_mv; VP56mv *left_mv = left_mb->bmv; VP56mv *cur_mv = mb->bmv; @@ -505,23 +829,22 @@ int decode_splitmvs(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb, int lay if (!layout) // layout is inlined, s->mb_layout is not top_mb = &mb[2]; else - top_mb = &mb[-s->mb_width-1]; + top_mb = &mb[-s->mb_width - 1]; mbsplits_top = vp8_mbsplits[top_mb->partitioning]; - top_mv = top_mb->bmv; + top_mv = top_mb->bmv; if (vp56_rac_get_prob_branchy(c, vp8_mbsplit_prob[0])) { - if (vp56_rac_get_prob_branchy(c, vp8_mbsplit_prob[1])) { + if (vp56_rac_get_prob_branchy(c, vp8_mbsplit_prob[1])) part_idx = VP8_SPLITMVMODE_16x8 + vp56_rac_get_prob(c, vp8_mbsplit_prob[2]); - } else { + else part_idx = VP8_SPLITMVMODE_8x8; - } } else { part_idx = VP8_SPLITMVMODE_4x4; } - num = vp8_mbsplit_count[part_idx]; - mbsplits_cur = vp8_mbsplits[part_idx], - firstidx = vp8_mbfirstidx[part_idx]; + num = vp8_mbsplit_count[part_idx]; + mbsplits_cur = vp8_mbsplits[part_idx], + firstidx = vp8_mbfirstidx[part_idx]; mb->partitioning = part_idx; for (n = 0; n < num; n++) { @@ -532,19 +855,21 @@ int decode_splitmvs(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb, int lay if (!(k & 3)) left = AV_RN32A(&left_mv[mbsplits_left[k + 3]]); else - left = AV_RN32A(&cur_mv[mbsplits_cur[k - 1]]); + left = AV_RN32A(&cur_mv[mbsplits_cur[k - 1]]); if (k <= 3) above = AV_RN32A(&top_mv[mbsplits_top[k + 12]]); else above = AV_RN32A(&cur_mv[mbsplits_cur[k - 4]]); - submv_prob = get_submv_prob(left, above); + submv_prob = get_submv_prob(left, above, is_vp7); if (vp56_rac_get_prob_branchy(c, submv_prob[0])) { if (vp56_rac_get_prob_branchy(c, submv_prob[1])) { if (vp56_rac_get_prob_branchy(c, submv_prob[2])) { - mb->bmv[n].y = mb->mv.y + read_mv_component(c, s->prob->mvc[0]); - mb->bmv[n].x = mb->mv.x + read_mv_component(c, s->prob->mvc[1]); + mb->bmv[n].y = mb->mv.y + + read_mv_component(c, s->prob->mvc[0], is_vp7); + mb->bmv[n].x = mb->mv.x + + read_mv_component(c, s->prob->mvc[1], is_vp7); } else { AV_ZERO32(&mb->bmv[n]); } @@ -559,12 +884,133 @@ int decode_splitmvs(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb, int lay return num; } -static av_always_inline -void decode_mvs(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, int layout) +/** + * The vp7 reference decoder uses a padding macroblock column (added to right + * edge of the frame) to guard against illegal macroblock offsets. The + * algorithm has bugs that permit offsets to straddle the padding column. + * This function replicates those bugs. + * + * @param[out] edge_x macroblock x address + * @param[out] edge_y macroblock y address + * + * @return macroblock offset legal (boolean) + */ +static int vp7_calculate_mb_offset(int mb_x, int mb_y, int mb_width, + int xoffset, int yoffset, int boundary, + int *edge_x, int *edge_y) { - VP8Macroblock *mb_edge[3] = { 0 /* top */, + int vwidth = mb_width + 1; + int new = (mb_y + yoffset) * vwidth + mb_x + xoffset; + if (new < boundary || new % vwidth == vwidth - 1) + return 0; + *edge_y = new / vwidth; + *edge_x = new % vwidth; + return 1; +} + +static const VP56mv *get_bmv_ptr(const VP8Macroblock *mb, int subblock) +{ + return &mb->bmv[mb->mode == VP8_MVMODE_SPLIT ? vp8_mbsplits[mb->partitioning][subblock] : 0]; +} + +static av_always_inline +void vp7_decode_mvs(VP8Context *s, VP8Macroblock *mb, + int mb_x, int mb_y, int layout) +{ + VP8Macroblock *mb_edge[12]; + enum { CNT_ZERO, CNT_NEAREST, CNT_NEAR }; + enum { VP8_EDGE_TOP, VP8_EDGE_LEFT, VP8_EDGE_TOPLEFT }; + int idx = CNT_ZERO; + VP56mv near_mv[3]; + uint8_t cnt[3] = { 0 }; + VP56RangeCoder *c = &s->c; + int i; + + AV_ZERO32(&near_mv[0]); + AV_ZERO32(&near_mv[1]); + AV_ZERO32(&near_mv[2]); + + for (i = 0; i < VP7_MV_PRED_COUNT; i++) { + const VP7MVPred * pred = &vp7_mv_pred[i]; + int edge_x, edge_y; + + if (vp7_calculate_mb_offset(mb_x, mb_y, s->mb_width, pred->xoffset, + pred->yoffset, !s->profile, &edge_x, &edge_y)) { + VP8Macroblock *edge = mb_edge[i] = (s->mb_layout == 1) + ? s->macroblocks_base + 1 + edge_x + + (s->mb_width + 1) * (edge_y + 1) + : s->macroblocks + edge_x + + (s->mb_height - edge_y - 1) * 2; + uint32_t mv = AV_RN32A(get_bmv_ptr(edge, vp7_mv_pred[i].subblock)); + if (mv) { + if (AV_RN32A(&near_mv[CNT_NEAREST])) { + if (mv == AV_RN32A(&near_mv[CNT_NEAREST])) { + idx = CNT_NEAREST; + } else if (AV_RN32A(&near_mv[CNT_NEAR])) { + if (mv != AV_RN32A(&near_mv[CNT_NEAR])) + continue; + idx = CNT_NEAR; + } else { + AV_WN32A(&near_mv[CNT_NEAR], mv); + idx = CNT_NEAR; + } + } else { + AV_WN32A(&near_mv[CNT_NEAREST], mv); + idx = CNT_NEAREST; + } + } else { + idx = CNT_ZERO; + } + } else { + idx = CNT_ZERO; + } + cnt[idx] += vp7_mv_pred[i].score; + } + + mb->partitioning = VP8_SPLITMVMODE_NONE; + + if (vp56_rac_get_prob_branchy(c, vp7_mode_contexts[cnt[CNT_ZERO]][0])) { + mb->mode = VP8_MVMODE_MV; + + if (vp56_rac_get_prob_branchy(c, vp7_mode_contexts[cnt[CNT_NEAREST]][1])) { + + if (vp56_rac_get_prob_branchy(c, vp7_mode_contexts[cnt[CNT_NEAR]][2])) { + + if (cnt[CNT_NEAREST] > cnt[CNT_NEAR]) + AV_WN32A(&mb->mv, cnt[CNT_ZERO] > cnt[CNT_NEAREST] ? 0 : AV_RN32A(&near_mv[CNT_NEAREST])); + else + AV_WN32A(&mb->mv, cnt[CNT_ZERO] > cnt[CNT_NEAR] ? 0 : AV_RN32A(&near_mv[CNT_NEAR])); + + if (vp56_rac_get_prob_branchy(c, vp7_mode_contexts[cnt[CNT_NEAR]][3])) { + mb->mode = VP8_MVMODE_SPLIT; + mb->mv = mb->bmv[decode_splitmvs(s, c, mb, layout, IS_VP7) - 1]; + } else { + mb->mv.y += vp7_read_mv_component(c, s->prob->mvc[0]); + mb->mv.x += vp7_read_mv_component(c, s->prob->mvc[1]); + mb->bmv[0] = mb->mv; + } + } else { + mb->mv = near_mv[CNT_NEAR]; + mb->bmv[0] = mb->mv; + } + } else { + mb->mv = near_mv[CNT_NEAREST]; + mb->bmv[0] = mb->mv; + } + } else { + mb->mode = VP8_MVMODE_ZERO; + AV_ZERO32(&mb->mv); + mb->bmv[0] = mb->mv; + } +} + +static av_always_inline +void vp8_decode_mvs(VP8Context *s, VP8Macroblock *mb, + int mb_x, int mb_y, int layout) +{ + VP8Macroblock *mb_edge[3] = { 0 /* top */, mb - 1 /* left */, - 0 /* top-left */ }; + 0 /* top-left */ }; enum { CNT_ZERO, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV }; enum { VP8_EDGE_TOP, VP8_EDGE_LEFT, VP8_EDGE_TOPLEFT }; int idx = CNT_ZERO; @@ -577,10 +1023,9 @@ void decode_mvs(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, int layout if (!layout) { // layout is inlined (s->mb_layout is not) mb_edge[0] = mb + 2; mb_edge[2] = mb + 1; - } - else { - mb_edge[0] = mb - s->mb_width-1; - mb_edge[2] = mb - s->mb_width-2; + } else { + mb_edge[0] = mb - s->mb_width - 1; + mb_edge[2] = mb - s->mb_width - 2; } AV_ZERO32(&near_mv[0]); @@ -588,24 +1033,25 @@ void decode_mvs(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, int layout AV_ZERO32(&near_mv[2]); /* Process MB on top, left and top-left */ - #define MV_EDGE_CHECK(n)\ - {\ - VP8Macroblock *edge = mb_edge[n];\ - int edge_ref = edge->ref_frame;\ - if (edge_ref != VP56_FRAME_CURRENT) {\ - uint32_t mv = AV_RN32A(&edge->mv);\ - if (mv) {\ - if (cur_sign_bias != sign_bias[edge_ref]) {\ - /* SWAR negate of the values in mv. */\ - mv = ~mv;\ - mv = ((mv&0x7fff7fff) + 0x00010001) ^ (mv&0x80008000);\ - }\ - if (!n || mv != AV_RN32A(&near_mv[idx]))\ - AV_WN32A(&near_mv[++idx], mv);\ - cnt[idx] += 1 + (n != 2);\ - } else\ - cnt[CNT_ZERO] += 1 + (n != 2);\ - }\ +#define MV_EDGE_CHECK(n) \ + { \ + VP8Macroblock *edge = mb_edge[n]; \ + int edge_ref = edge->ref_frame; \ + if (edge_ref != VP56_FRAME_CURRENT) { \ + uint32_t mv = AV_RN32A(&edge->mv); \ + if (mv) { \ + if (cur_sign_bias != sign_bias[edge_ref]) { \ + /* SWAR negate of the values in mv. */ \ + mv = ~mv; \ + mv = ((mv & 0x7fff7fff) + \ + 0x00010001) ^ (mv & 0x80008000); \ + } \ + if (!n || mv != AV_RN32A(&near_mv[idx])) \ + AV_WN32A(&near_mv[++idx], mv); \ + cnt[idx] += 1 + (n != 2); \ + } else \ + cnt[CNT_ZERO] += 1 + (n != 2); \ + } \ } MV_EDGE_CHECK(0) @@ -617,7 +1063,8 @@ void decode_mvs(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, int layout mb->mode = VP8_MVMODE_MV; /* If we have three distinct MVs, merge first and last if they're the same */ - if (cnt[CNT_SPLITMV] && AV_RN32A(&near_mv[1 + VP8_EDGE_TOP]) == AV_RN32A(&near_mv[1 + VP8_EDGE_TOPLEFT])) + if (cnt[CNT_SPLITMV] && + AV_RN32A(&near_mv[1 + VP8_EDGE_TOP]) == AV_RN32A(&near_mv[1 + VP8_EDGE_TOPLEFT])) cnt[CNT_NEAREST] += 1; /* Swap near and nearest if necessary */ @@ -628,7 +1075,6 @@ void decode_mvs(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, int layout if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAREST]][1])) { if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAR]][2])) { - /* Choose the best mv out of 0,0 and the nearest mv */ clamp_mv(s, &mb->mv, &near_mv[CNT_ZERO + (cnt[CNT_NEAREST] >= cnt[CNT_ZERO])]); cnt[CNT_SPLITMV] = ((mb_edge[VP8_EDGE_LEFT]->mode == VP8_MVMODE_SPLIT) + @@ -637,10 +1083,10 @@ void decode_mvs(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, int layout if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_SPLITMV]][3])) { mb->mode = VP8_MVMODE_SPLIT; - mb->mv = mb->bmv[decode_splitmvs(s, c, mb, layout) - 1]; + mb->mv = mb->bmv[decode_splitmvs(s, c, mb, layout, IS_VP8) - 1]; } else { - mb->mv.y += read_mv_component(c, s->prob->mvc[0]); - mb->mv.x += read_mv_component(c, s->prob->mvc[1]); + mb->mv.y += vp8_read_mv_component(c, s->prob->mvc[0]); + mb->mv.x += vp8_read_mv_component(c, s->prob->mvc[1]); mb->bmv[0] = mb->mv; } } else { @@ -670,8 +1116,8 @@ void decode_intra4x4_modes(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb, } if (keyframe) { int x, y; - uint8_t* top; - uint8_t* const left = s->intra4x4_pred_mode_left; + uint8_t *top; + uint8_t *const left = s->intra4x4_pred_mode_left; if (layout) top = mb->intra4x4_pred_mode_top; else @@ -679,26 +1125,44 @@ void decode_intra4x4_modes(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb, for (y = 0; y < 4; y++) { for (x = 0; x < 4; x++) { const uint8_t *ctx; - ctx = vp8_pred4x4_prob_intra[top[x]][left[y]]; + ctx = vp8_pred4x4_prob_intra[top[x]][left[y]]; *intra4x4 = vp8_rac_get_tree(c, vp8_pred4x4_tree, ctx); - left[y] = top[x] = *intra4x4; + left[y] = top[x] = *intra4x4; intra4x4++; } } } else { int i; for (i = 0; i < 16; i++) - intra4x4[i] = vp8_rac_get_tree(c, vp8_pred4x4_tree, vp8_pred4x4_prob_inter); + intra4x4[i] = vp8_rac_get_tree(c, vp8_pred4x4_tree, + vp8_pred4x4_prob_inter); } } static av_always_inline void decode_mb_mode(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, - uint8_t *segment, uint8_t *ref, int layout) + uint8_t *segment, uint8_t *ref, int layout, int is_vp7) { VP56RangeCoder *c = &s->c; - - if (s->segmentation.update_map) { + const char *vp7_feature_name[] = { "q-index", + "lf-delta", + "partial-golden-update", + "blit-pitch" }; + if (is_vp7) { + int i; + *segment = 0; + for (i = 0; i < 4; i++) { + if (s->feature_enabled[i]) { + if (vp56_rac_get_prob_branchy(c, s->feature_present_prob[i])) { + int index = vp8_rac_get_tree(c, vp7_feature_index_tree, + s->feature_index_prob[i]); + av_log(s->avctx, AV_LOG_WARNING, + "Feature %s present in macroblock (value 0x%x)\n", + vp7_feature_name[i], s->feature_value[i][index]); + } + } + } + } else if (s->segmentation.update_map) { int bit = vp56_rac_get_prob(c, s->prob->segmentid[0]); *segment = vp56_rac_get_prob(c, s->prob->segmentid[1+bit]) + 2*bit; } else if (s->segmentation.enabled) @@ -708,32 +1172,39 @@ void decode_mb_mode(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, mb->skip = s->mbskip_enabled ? vp56_rac_get_prob(c, s->prob->mbskip) : 0; if (s->keyframe) { - mb->mode = vp8_rac_get_tree(c, vp8_pred16x16_tree_intra, vp8_pred16x16_prob_intra); + mb->mode = vp8_rac_get_tree(c, vp8_pred16x16_tree_intra, + vp8_pred16x16_prob_intra); if (mb->mode == MODE_I4x4) { decode_intra4x4_modes(s, c, mb, mb_x, 1, layout); } else { - const uint32_t modes = vp8_pred4x4_mode[mb->mode] * 0x01010101u; + const uint32_t modes = (is_vp7 ? vp7_pred4x4_mode + : vp8_pred4x4_mode)[mb->mode] * 0x01010101u; if (s->mb_layout) AV_WN32A(mb->intra4x4_pred_mode_top, modes); else AV_WN32A(s->intra4x4_pred_mode_top + 4 * mb_x, modes); - AV_WN32A( s->intra4x4_pred_mode_left, modes); + AV_WN32A(s->intra4x4_pred_mode_left, modes); } - mb->chroma_pred_mode = vp8_rac_get_tree(c, vp8_pred8x8c_tree, vp8_pred8x8c_prob_intra); - mb->ref_frame = VP56_FRAME_CURRENT; + mb->chroma_pred_mode = vp8_rac_get_tree(c, vp8_pred8x8c_tree, + vp8_pred8x8c_prob_intra); + mb->ref_frame = VP56_FRAME_CURRENT; } else if (vp56_rac_get_prob_branchy(c, s->prob->intra)) { // inter MB, 16.2 if (vp56_rac_get_prob_branchy(c, s->prob->last)) - mb->ref_frame = vp56_rac_get_prob(c, s->prob->golden) ? - VP56_FRAME_GOLDEN2 /* altref */ : VP56_FRAME_GOLDEN; + mb->ref_frame = + (!is_vp7 && vp56_rac_get_prob(c, s->prob->golden)) ? VP56_FRAME_GOLDEN2 /* altref */ + : VP56_FRAME_GOLDEN; else mb->ref_frame = VP56_FRAME_PREVIOUS; - s->ref_count[mb->ref_frame-1]++; + s->ref_count[mb->ref_frame - 1]++; // motion vectors, 16.3 - decode_mvs(s, mb, mb_x, mb_y, layout); + if (is_vp7) + vp7_decode_mvs(s, mb, mb_x, mb_y, layout); + else + vp8_decode_mvs(s, mb, mb_x, mb_y, layout); } else { // intra MB, 16.1 mb->mode = vp8_rac_get_tree(c, vp8_pred16x16_tree_inter, s->prob->pred16x16); @@ -741,31 +1212,35 @@ void decode_mb_mode(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, if (mb->mode == MODE_I4x4) decode_intra4x4_modes(s, c, mb, mb_x, 0, layout); - mb->chroma_pred_mode = vp8_rac_get_tree(c, vp8_pred8x8c_tree, s->prob->pred8x8c); - mb->ref_frame = VP56_FRAME_CURRENT; - mb->partitioning = VP8_SPLITMVMODE_NONE; + mb->chroma_pred_mode = vp8_rac_get_tree(c, vp8_pred8x8c_tree, + s->prob->pred8x8c); + mb->ref_frame = VP56_FRAME_CURRENT; + mb->partitioning = VP8_SPLITMVMODE_NONE; AV_ZERO32(&mb->bmv[0]); } } -#ifndef decode_block_coeffs_internal /** - * @param r arithmetic bitstream reader context + * @param r arithmetic bitstream reader context * @param block destination for block coefficients * @param probs probabilities to use when reading trees from the bitstream - * @param i initial coeff index, 0 unless a separate DC block is coded - * @param qmul array holding the dc/ac dequant factor at position 0/1 + * @param i initial coeff index, 0 unless a separate DC block is coded + * @param qmul array holding the dc/ac dequant factor at position 0/1 + * * @return 0 if no coeffs were decoded * otherwise, the index of the last coeff decoded plus one */ -static int decode_block_coeffs_internal(VP56RangeCoder *r, int16_t block[16], - uint8_t probs[16][3][NUM_DCT_TOKENS-1], - int i, uint8_t *token_prob, int16_t qmul[2]) +static av_always_inline +int decode_block_coeffs_internal(VP56RangeCoder *r, int16_t block[16], + uint8_t probs[16][3][NUM_DCT_TOKENS - 1], + int i, uint8_t *token_prob, int16_t qmul[2], + const uint8_t scan[16], int vp7) { VP56RangeCoder c = *r; goto skip_eob; do { int coeff; +restart: if (!vp56_rac_get_prob_branchy(&c, token_prob[0])) // DCT_EOB break; @@ -774,12 +1249,14 @@ skip_eob: if (++i == 16) break; // invalid input; blocks should end with EOB token_prob = probs[i][0]; + if (vp7) + goto restart; goto skip_eob; } if (!vp56_rac_get_prob_branchy(&c, token_prob[2])) { // DCT_1 coeff = 1; - token_prob = probs[i+1][1]; + token_prob = probs[i + 1][1]; } else { if (!vp56_rac_get_prob_branchy(&c, token_prob[3])) { // DCT 2,3,4 coeff = vp56_rac_get_prob_branchy(&c, token_prob[4]); @@ -790,87 +1267,150 @@ skip_eob: // DCT_CAT* if (!vp56_rac_get_prob_branchy(&c, token_prob[6])) { if (!vp56_rac_get_prob_branchy(&c, token_prob[7])) { // DCT_CAT1 - coeff = 5 + vp56_rac_get_prob(&c, vp8_dct_cat1_prob[0]); + coeff = 5 + vp56_rac_get_prob(&c, vp8_dct_cat1_prob[0]); } else { // DCT_CAT2 coeff = 7; coeff += vp56_rac_get_prob(&c, vp8_dct_cat2_prob[0]) << 1; coeff += vp56_rac_get_prob(&c, vp8_dct_cat2_prob[1]); } } else { // DCT_CAT3 and up - int a = vp56_rac_get_prob(&c, token_prob[8]); - int b = vp56_rac_get_prob(&c, token_prob[9+a]); - int cat = (a<<1) + b; - coeff = 3 + (8< 3) { + dc += pred[0]; + ret = 1; + } + + if (!pred[0] | !dc | ((int32_t)pred[0] ^ (int32_t)dc) >> 31) { + block[0] = pred[0] = dc; + pred[1] = 0; + } else { + if (pred[0] == dc) + pred[1]++; + block[0] = pred[0] = dc; + } + + return ret; +} + +static int vp7_decode_block_coeffs_internal(VP56RangeCoder *r, + int16_t block[16], + uint8_t probs[16][3][NUM_DCT_TOKENS - 1], + int i, uint8_t *token_prob, + int16_t qmul[2], + const uint8_t scan[16]) +{ + return decode_block_coeffs_internal(r, block, probs, i, + token_prob, qmul, scan, IS_VP7); +} + +#ifndef vp8_decode_block_coeffs_internal +static int vp8_decode_block_coeffs_internal(VP56RangeCoder *r, + int16_t block[16], + uint8_t probs[16][3][NUM_DCT_TOKENS - 1], + int i, uint8_t *token_prob, + int16_t qmul[2]) +{ + return decode_block_coeffs_internal(r, block, probs, i, + token_prob, qmul, zigzag_scan, IS_VP8); +} #endif /** - * @param c arithmetic bitstream reader context - * @param block destination for block coefficients - * @param probs probabilities to use when reading trees from the bitstream - * @param i initial coeff index, 0 unless a separate DC block is coded + * @param c arithmetic bitstream reader context + * @param block destination for block coefficients + * @param probs probabilities to use when reading trees from the bitstream + * @param i initial coeff index, 0 unless a separate DC block is coded * @param zero_nhood the initial prediction context for number of surrounding * all-zero blocks (only left/top, so 0-2) - * @param qmul array holding the dc/ac dequant factor at position 0/1 + * @param qmul array holding the dc/ac dequant factor at position 0/1 + * @param scan scan pattern (VP7 only) + * * @return 0 if no coeffs were decoded * otherwise, the index of the last coeff decoded plus one */ static av_always_inline int decode_block_coeffs(VP56RangeCoder *c, int16_t block[16], - uint8_t probs[16][3][NUM_DCT_TOKENS-1], - int i, int zero_nhood, int16_t qmul[2]) + uint8_t probs[16][3][NUM_DCT_TOKENS - 1], + int i, int zero_nhood, int16_t qmul[2], + const uint8_t scan[16], int vp7) { uint8_t *token_prob = probs[i][zero_nhood]; if (!vp56_rac_get_prob_branchy(c, token_prob[0])) // DCT_EOB return 0; - return decode_block_coeffs_internal(c, block, probs, i, token_prob, qmul); + return vp7 ? vp7_decode_block_coeffs_internal(c, block, probs, i, + token_prob, qmul, scan) + : vp8_decode_block_coeffs_internal(c, block, probs, i, + token_prob, qmul); } static av_always_inline -void decode_mb_coeffs(VP8Context *s, VP8ThreadData *td, VP56RangeCoder *c, VP8Macroblock *mb, - uint8_t t_nnz[9], uint8_t l_nnz[9]) +void decode_mb_coeffs(VP8Context *s, VP8ThreadData *td, VP56RangeCoder *c, + VP8Macroblock *mb, uint8_t t_nnz[9], uint8_t l_nnz[9], + int is_vp7) { int i, x, y, luma_start = 0, luma_ctx = 3; int nnz_pred, nnz, nnz_total = 0; int segment = mb->segment; int block_dc = 0; - if (mb->mode != MODE_I4x4 && mb->mode != VP8_MVMODE_SPLIT) { + if (mb->mode != MODE_I4x4 && (is_vp7 || mb->mode != VP8_MVMODE_SPLIT)) { nnz_pred = t_nnz[8] + l_nnz[8]; // decode DC values and do hadamard - nnz = decode_block_coeffs(c, td->block_dc, s->prob->token[1], 0, nnz_pred, - s->qmat[segment].luma_dc_qmul); + 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); l_nnz[8] = t_nnz[8] = !!nnz; + + if (is_vp7 && mb->mode > MODE_I4x4) { + nnz |= inter_predict_dc(td->block_dc, + s->inter_dc_pred[mb->ref_frame - 1]); + } + if (nnz) { nnz_total += nnz; - block_dc = 1; + block_dc = 1; if (nnz == 1) s->vp8dsp.vp8_luma_dc_wht_dc(td->block, td->block_dc); else s->vp8dsp.vp8_luma_dc_wht(td->block, td->block_dc); } luma_start = 1; - luma_ctx = 0; + luma_ctx = 0; } // luma blocks for (y = 0; y < 4; y++) for (x = 0; x < 4; x++) { nnz_pred = l_nnz[y] + t_nnz[x]; - nnz = decode_block_coeffs(c, td->block[y][x], s->prob->token[luma_ctx], luma_start, - nnz_pred, s->qmat[segment].luma_qmul); - // nnz+block_dc may be one more than the actual last index, but we don't care + nnz = decode_block_coeffs(c, td->block[y][x], + s->prob->token[luma_ctx], + luma_start, nnz_pred, + s->qmat[segment].luma_qmul, + s->prob[0].scan, is_vp7); + /* nnz+block_dc may be one more than the actual last index, + * but we don't care */ td->non_zero_count_cache[y][x] = nnz + block_dc; t_nnz[x] = l_nnz[y] = !!nnz; nnz_total += nnz; @@ -882,11 +1422,13 @@ void decode_mb_coeffs(VP8Context *s, VP8ThreadData *td, VP56RangeCoder *c, VP8Ma for (i = 4; i < 6; i++) for (y = 0; y < 2; y++) for (x = 0; x < 2; x++) { - nnz_pred = l_nnz[i+2*y] + t_nnz[i+2*x]; - nnz = decode_block_coeffs(c, td->block[i][(y<<1)+x], s->prob->token[2], 0, - nnz_pred, s->qmat[segment].chroma_qmul); - td->non_zero_count_cache[i][(y<<1)+x] = nnz; - t_nnz[i+2*x] = l_nnz[i+2*y] = !!nnz; + nnz_pred = l_nnz[i + 2 * y] + t_nnz[i + 2 * x]; + nnz = decode_block_coeffs(c, td->block[i][(y << 1) + x], + s->prob->token[2], 0, nnz_pred, + s->qmat[segment].chroma_qmul, + s->prob[0].scan, is_vp7); + td->non_zero_count_cache[i][(y << 1) + x] = nnz; + t_nnz[i + 2 * x] = l_nnz[i + 2 * y] = !!nnz; nnz_total += nnz; } @@ -898,95 +1440,98 @@ void decode_mb_coeffs(VP8Context *s, VP8ThreadData *td, VP56RangeCoder *c, VP8Ma } static av_always_inline -void backup_mb_border(uint8_t *top_border, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, +void backup_mb_border(uint8_t *top_border, uint8_t *src_y, + uint8_t *src_cb, uint8_t *src_cr, int linesize, int uvlinesize, int simple) { - AV_COPY128(top_border, src_y + 15*linesize); + AV_COPY128(top_border, src_y + 15 * linesize); if (!simple) { - AV_COPY64(top_border+16, src_cb + 7*uvlinesize); - AV_COPY64(top_border+24, src_cr + 7*uvlinesize); + AV_COPY64(top_border + 16, src_cb + 7 * uvlinesize); + AV_COPY64(top_border + 24, src_cr + 7 * uvlinesize); } } static av_always_inline -void xchg_mb_border(uint8_t *top_border, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, - int linesize, int uvlinesize, int mb_x, int mb_y, int mb_width, - int simple, int xchg) +void xchg_mb_border(uint8_t *top_border, uint8_t *src_y, uint8_t *src_cb, + uint8_t *src_cr, int linesize, int uvlinesize, int mb_x, + int mb_y, int mb_width, int simple, int xchg) { - uint8_t *top_border_m1 = top_border-32; // for TL prediction - src_y -= linesize; + uint8_t *top_border_m1 = top_border - 32; // for TL prediction + src_y -= linesize; src_cb -= uvlinesize; src_cr -= uvlinesize; -#define XCHG(a,b,xchg) do { \ - if (xchg) AV_SWAP64(b,a); \ - else AV_COPY64(b,a); \ +#define XCHG(a, b, xchg) \ + do { \ + if (xchg) \ + AV_SWAP64(b, a); \ + else \ + AV_COPY64(b, a); \ } while (0) - XCHG(top_border_m1+8, src_y-8, xchg); - XCHG(top_border, src_y, xchg); - XCHG(top_border+8, src_y+8, 1); - if (mb_x < mb_width-1) - XCHG(top_border+32, src_y+16, 1); + XCHG(top_border_m1 + 8, src_y - 8, xchg); + XCHG(top_border, src_y, xchg); + XCHG(top_border + 8, src_y + 8, 1); + if (mb_x < mb_width - 1) + XCHG(top_border + 32, src_y + 16, 1); // only copy chroma for normal loop filter // or to initialize the top row to 127 if (!simple || !mb_y) { - XCHG(top_border_m1+16, src_cb-8, xchg); - XCHG(top_border_m1+24, src_cr-8, xchg); - XCHG(top_border+16, src_cb, 1); - XCHG(top_border+24, src_cr, 1); + XCHG(top_border_m1 + 16, src_cb - 8, xchg); + XCHG(top_border_m1 + 24, src_cr - 8, xchg); + XCHG(top_border + 16, src_cb, 1); + XCHG(top_border + 24, src_cr, 1); } } static av_always_inline int check_dc_pred8x8_mode(int mode, int mb_x, int mb_y) { - if (!mb_x) { + if (!mb_x) return mb_y ? TOP_DC_PRED8x8 : DC_128_PRED8x8; - } else { + else return mb_y ? mode : LEFT_DC_PRED8x8; - } } static av_always_inline -int check_tm_pred8x8_mode(int mode, int mb_x, int mb_y) +int check_tm_pred8x8_mode(int mode, int mb_x, int mb_y, int vp7) { - if (!mb_x) { - return mb_y ? VERT_PRED8x8 : DC_129_PRED8x8; - } else { + if (!mb_x) + return mb_y ? VERT_PRED8x8 : (vp7 ? DC_128_PRED8x8 : DC_129_PRED8x8); + else return mb_y ? mode : HOR_PRED8x8; - } } static av_always_inline -int check_intra_pred8x8_mode_emuedge(int mode, int mb_x, int mb_y) +int check_intra_pred8x8_mode_emuedge(int mode, int mb_x, int mb_y, int vp7) { switch (mode) { case DC_PRED8x8: return check_dc_pred8x8_mode(mode, mb_x, mb_y); case VERT_PRED8x8: - return !mb_y ? DC_127_PRED8x8 : mode; + return !mb_y ? (vp7 ? DC_128_PRED8x8 : DC_127_PRED8x8) : mode; case HOR_PRED8x8: - return !mb_x ? DC_129_PRED8x8 : mode; - case PLANE_PRED8x8 /*TM*/: - return check_tm_pred8x8_mode(mode, mb_x, mb_y); + return !mb_x ? (vp7 ? DC_128_PRED8x8 : DC_129_PRED8x8) : mode; + case PLANE_PRED8x8: /* TM */ + return check_tm_pred8x8_mode(mode, mb_x, mb_y, vp7); } return mode; } static av_always_inline -int check_tm_pred4x4_mode(int mode, int mb_x, int mb_y) +int check_tm_pred4x4_mode(int mode, int mb_x, int mb_y, int vp7) { if (!mb_x) { - return mb_y ? VERT_VP8_PRED : DC_129_PRED; + return mb_y ? VERT_VP8_PRED : (vp7 ? DC_128_PRED : DC_129_PRED); } else { return mb_y ? mode : HOR_VP8_PRED; } } static av_always_inline -int check_intra_pred4x4_mode_emuedge(int mode, int mb_x, int mb_y, int *copy_buf) +int check_intra_pred4x4_mode_emuedge(int mode, int mb_x, int mb_y, + int *copy_buf, int vp7) { switch (mode) { case VERT_PRED: @@ -997,7 +1542,7 @@ int check_intra_pred4x4_mode_emuedge(int mode, int mb_x, int mb_y, int *copy_buf /* fall-through */ case DIAG_DOWN_LEFT_PRED: case VERT_LEFT_PRED: - return !mb_y ? DC_127_PRED : mode; + return !mb_y ? (vp7 ? DC_128_PRED : DC_127_PRED) : mode; case HOR_PRED: if (!mb_y) { *copy_buf = 1; @@ -1005,10 +1550,11 @@ int check_intra_pred4x4_mode_emuedge(int mode, int mb_x, int mb_y, int *copy_buf } /* fall-through */ case HOR_UP_PRED: - return !mb_x ? DC_129_PRED : mode; + return !mb_x ? (vp7 ? DC_128_PRED : DC_129_PRED) : mode; case TM_VP8_PRED: - return check_tm_pred4x4_mode(mode, mb_x, mb_y); - case DC_PRED: // 4x4 DC doesn't use the same "H.264-style" exceptions as 16x16/8x8 DC + return check_tm_pred4x4_mode(mode, mb_x, mb_y, vp7); + case DC_PRED: /* 4x4 DC doesn't use the same "H.264-style" exceptions + * as 16x16/8x8 DC */ case DIAG_DOWN_RIGHT_PRED: case VERT_RIGHT_PRED: case HOR_DOWN_PRED: @@ -1021,25 +1567,27 @@ int check_intra_pred4x4_mode_emuedge(int mode, int mb_x, int mb_y, int *copy_buf static av_always_inline void intra_predict(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], - VP8Macroblock *mb, int mb_x, int mb_y) + VP8Macroblock *mb, int mb_x, int mb_y, int is_vp7) { int x, y, mode, nnz; uint32_t tr; - // for the first row, we need to run xchg_mb_border to init the top edge to 127 - // otherwise, skip it if we aren't going to deblock + /* for the first row, we need to run xchg_mb_border to init the top edge + * to 127 otherwise, skip it if we aren't going to deblock */ if (mb_y && (s->deblock_filter || !mb_y) && td->thread_nr == 0) - xchg_mb_border(s->top_border[mb_x+1], dst[0], dst[1], dst[2], + xchg_mb_border(s->top_border[mb_x + 1], dst[0], dst[1], dst[2], s->linesize, s->uvlinesize, mb_x, mb_y, s->mb_width, s->filter.simple, 1); if (mb->mode < MODE_I4x4) { - mode = check_intra_pred8x8_mode_emuedge(mb->mode, mb_x, mb_y); + mode = check_intra_pred8x8_mode_emuedge(mb->mode, mb_x, mb_y, is_vp7); s->hpc.pred16x16[mode](dst[0], s->linesize); } else { uint8_t *ptr = dst[0]; uint8_t *intra4x4 = mb->intra4x4_pred_mode_mb; - uint8_t tr_top[4] = { 127, 127, 127, 127 }; + const uint8_t lo = is_vp7 ? 128 : 127; + const uint8_t hi = is_vp7 ? 128 : 129; + uint8_t tr_top[4] = { lo, lo, lo, lo }; // all blocks on the right edge of the macroblock use bottom edge // the top macroblock for their topright edge @@ -1047,10 +1595,9 @@ void intra_predict(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], // if we're on the right edge of the frame, said edge is extended // from the top macroblock - if (mb_y && - mb_x == s->mb_width-1) { - tr = tr_right[-1]*0x01010101u; - tr_right = (uint8_t *)&tr; + if (mb_y && mb_x == s->mb_width - 1) { + tr = tr_right[-1] * 0x01010101u; + tr_right = (uint8_t *) &tr; } if (mb->skip) @@ -1060,70 +1607,74 @@ void intra_predict(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], uint8_t *topright = ptr + 4 - s->linesize; for (x = 0; x < 4; x++) { int copy = 0, linesize = s->linesize; - uint8_t *dst = ptr+4*x; - DECLARE_ALIGNED(4, uint8_t, copy_dst)[5*8]; + uint8_t *dst = ptr + 4 * x; + DECLARE_ALIGNED(4, uint8_t, copy_dst)[5 * 8]; if ((y == 0 || x == 3) && mb_y == 0) { topright = tr_top; } else if (x == 3) topright = tr_right; - mode = check_intra_pred4x4_mode_emuedge(intra4x4[x], mb_x + x, mb_y + y, ©); + mode = check_intra_pred4x4_mode_emuedge(intra4x4[x], mb_x + x, + mb_y + y, ©, is_vp7); if (copy) { - dst = copy_dst + 12; + dst = copy_dst + 12; linesize = 8; if (!(mb_y + y)) { - copy_dst[3] = 127U; - AV_WN32A(copy_dst+4, 127U * 0x01010101U); + copy_dst[3] = lo; + AV_WN32A(copy_dst + 4, lo * 0x01010101U); } else { - AV_COPY32(copy_dst+4, ptr+4*x-s->linesize); + AV_COPY32(copy_dst + 4, ptr + 4 * x - s->linesize); if (!(mb_x + x)) { - copy_dst[3] = 129U; + copy_dst[3] = hi; } else { - copy_dst[3] = ptr[4*x-s->linesize-1]; + copy_dst[3] = ptr[4 * x - s->linesize - 1]; } } if (!(mb_x + x)) { copy_dst[11] = copy_dst[19] = copy_dst[27] = - copy_dst[35] = 129U; + copy_dst[35] = hi; } else { - copy_dst[11] = ptr[4*x -1]; - copy_dst[19] = ptr[4*x+s->linesize -1]; - copy_dst[27] = ptr[4*x+s->linesize*2-1]; - copy_dst[35] = ptr[4*x+s->linesize*3-1]; + copy_dst[11] = ptr[4 * x - 1]; + copy_dst[19] = ptr[4 * x + s->linesize - 1]; + copy_dst[27] = ptr[4 * x + s->linesize * 2 - 1]; + copy_dst[35] = ptr[4 * x + s->linesize * 3 - 1]; } } s->hpc.pred4x4[mode](dst, topright, linesize); if (copy) { - AV_COPY32(ptr+4*x , copy_dst+12); - AV_COPY32(ptr+4*x+s->linesize , copy_dst+20); - AV_COPY32(ptr+4*x+s->linesize*2, copy_dst+28); - AV_COPY32(ptr+4*x+s->linesize*3, copy_dst+36); + AV_COPY32(ptr + 4 * x, copy_dst + 12); + AV_COPY32(ptr + 4 * x + s->linesize, copy_dst + 20); + AV_COPY32(ptr + 4 * x + s->linesize * 2, copy_dst + 28); + AV_COPY32(ptr + 4 * x + s->linesize * 3, copy_dst + 36); } nnz = td->non_zero_count_cache[y][x]; if (nnz) { if (nnz == 1) - s->vp8dsp.vp8_idct_dc_add(ptr+4*x, td->block[y][x], s->linesize); + s->vp8dsp.vp8_idct_dc_add(ptr + 4 * x, + td->block[y][x], s->linesize); else - s->vp8dsp.vp8_idct_add(ptr+4*x, td->block[y][x], s->linesize); + s->vp8dsp.vp8_idct_add(ptr + 4 * x, + td->block[y][x], s->linesize); } topright += 4; } - ptr += 4*s->linesize; + ptr += 4 * s->linesize; intra4x4 += 4; } } - mode = check_intra_pred8x8_mode_emuedge(mb->chroma_pred_mode, mb_x, mb_y); + mode = check_intra_pred8x8_mode_emuedge(mb->chroma_pred_mode, + mb_x, mb_y, is_vp7); s->hpc.pred8x8[mode](dst[1], s->uvlinesize); s->hpc.pred8x8[mode](dst[2], s->uvlinesize); if (mb_y && (s->deblock_filter || !mb_y) && td->thread_nr == 0) - xchg_mb_border(s->top_border[mb_x+1], dst[0], dst[1], dst[2], + xchg_mb_border(s->top_border[mb_x + 1], dst[0], dst[1], dst[2], s->linesize, s->uvlinesize, mb_x, mb_y, s->mb_width, s->filter.simple, 0); } @@ -1138,18 +1689,18 @@ static const uint8_t subpel_idx[3][8] = { /** * luma MC function * - * @param s VP8 decoding context - * @param dst target buffer for block data at block position - * @param ref reference picture buffer at origin (0, 0) - * @param mv motion vector (relative to block position) to get pixel data from - * @param x_off horizontal position of block from origin (0, 0) - * @param y_off vertical position of block from origin (0, 0) - * @param block_w width of block (16, 8 or 4) - * @param block_h height of block (always same as block_w) - * @param width width of src/dst plane data - * @param height height of src/dst plane data + * @param s VP8 decoding context + * @param dst target buffer for block data at block position + * @param ref reference picture buffer at origin (0, 0) + * @param mv motion vector (relative to block position) to get pixel data from + * @param x_off horizontal position of block from origin (0, 0) + * @param y_off vertical position of block from origin (0, 0) + * @param block_w width of block (16, 8 or 4) + * @param block_h height of block (always same as block_w) + * @param width width of src/dst plane data + * @param height height of src/dst plane data * @param linesize size of a single line of plane data, including padding - * @param mc_func motion compensation function pointers (bilinear or sixtap MC) + * @param mc_func motion compensation function pointers (bilinear or sixtap MC) */ static av_always_inline void vp8_mc_luma(VP8Context *s, VP8ThreadData *td, uint8_t *dst, @@ -1163,8 +1714,8 @@ void vp8_mc_luma(VP8Context *s, VP8ThreadData *td, uint8_t *dst, if (AV_RN32A(mv)) { int 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]; + int mx = (mv->x << 1) & 7, mx_idx = subpel_idx[0][mx]; + int my = (mv->y << 1) & 7, my_idx = subpel_idx[0][my]; x_off += mv->x >> 2; y_off += mv->y >> 2; @@ -1179,45 +1730,48 @@ void vp8_mc_luma(VP8Context *s, VP8ThreadData *td, uint8_t *dst, EDGE_EMU_LINESIZE, linesize, block_w + subpel_idx[1][mx], block_h + subpel_idx[1][my], - x_off - mx_idx, y_off - my_idx, width, height); + x_off - mx_idx, y_off - my_idx, + width, height); src = td->edge_emu_buffer + mx_idx + EDGE_EMU_LINESIZE * my_idx; src_linesize = EDGE_EMU_LINESIZE; } mc_func[my_idx][mx_idx](dst, linesize, src, src_linesize, block_h, mx, my); } else { ff_thread_await_progress(ref, (3 + y_off + block_h) >> 4, 0); - mc_func[0][0](dst, linesize, src + y_off * linesize + x_off, linesize, block_h, 0, 0); + mc_func[0][0](dst, linesize, src + y_off * linesize + x_off, + linesize, block_h, 0, 0); } } /** * chroma MC function * - * @param s VP8 decoding context - * @param dst1 target buffer for block data at block position (U plane) - * @param dst2 target buffer for block data at block position (V plane) - * @param ref reference picture buffer at origin (0, 0) - * @param mv motion vector (relative to block position) to get pixel data from - * @param x_off horizontal position of block from origin (0, 0) - * @param y_off vertical position of block from origin (0, 0) - * @param block_w width of block (16, 8 or 4) - * @param block_h height of block (always same as block_w) - * @param width width of src/dst plane data - * @param height height of src/dst plane data + * @param s VP8 decoding context + * @param dst1 target buffer for block data at block position (U plane) + * @param dst2 target buffer for block data at block position (V plane) + * @param ref reference picture buffer at origin (0, 0) + * @param mv motion vector (relative to block position) to get pixel data from + * @param x_off horizontal position of block from origin (0, 0) + * @param y_off vertical position of block from origin (0, 0) + * @param block_w width of block (16, 8 or 4) + * @param block_h height of block (always same as block_w) + * @param width width of src/dst plane data + * @param height height of src/dst plane data * @param linesize size of a single line of plane data, including padding - * @param mc_func motion compensation function pointers (bilinear or sixtap MC) + * @param mc_func motion compensation function pointers (bilinear or sixtap MC) */ static av_always_inline -void vp8_mc_chroma(VP8Context *s, VP8ThreadData *td, uint8_t *dst1, uint8_t *dst2, - ThreadFrame *ref, const VP56mv *mv, int x_off, int y_off, - int block_w, int block_h, int width, int height, ptrdiff_t linesize, +void vp8_mc_chroma(VP8Context *s, VP8ThreadData *td, uint8_t *dst1, + uint8_t *dst2, ThreadFrame *ref, const VP56mv *mv, + int x_off, int y_off, int block_w, int block_h, + int width, int height, ptrdiff_t linesize, vp8_mc_func mc_func[3][3]) { uint8_t *src1 = ref->f->data[1], *src2 = ref->f->data[2]; if (AV_RN32A(mv)) { - int mx = mv->x&7, mx_idx = subpel_idx[0][mx]; - int my = mv->y&7, my_idx = subpel_idx[0][my]; + int mx = mv->x & 7, mx_idx = subpel_idx[0][mx]; + int my = mv->y & 7, my_idx = subpel_idx[0][my]; x_off += mv->x >> 3; y_off += mv->y >> 3; @@ -1259,8 +1813,7 @@ void vp8_mc_chroma(VP8Context *s, VP8ThreadData *td, uint8_t *dst1, uint8_t *dst static av_always_inline void vp8_mc_part(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], ThreadFrame *ref_frame, int x_off, int y_off, - int bx_off, int by_off, - int block_w, int block_h, + int bx_off, int by_off, int block_w, int block_h, int width, int height, VP56mv *mv) { VP56mv uvmv = *mv; @@ -1273,13 +1826,19 @@ void vp8_mc_part(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], /* U/V */ if (s->profile == 3) { + /* this block only applies VP8; it is safe to check + * only the profile, as VP7 profile <= 1 */ uvmv.x &= ~7; uvmv.y &= ~7; } - x_off >>= 1; y_off >>= 1; - bx_off >>= 1; by_off >>= 1; - width >>= 1; height >>= 1; - block_w >>= 1; block_h >>= 1; + x_off >>= 1; + y_off >>= 1; + bx_off >>= 1; + by_off >>= 1; + width >>= 1; + height >>= 1; + block_w >>= 1; + block_h >>= 1; vp8_mc_chroma(s, td, dst[1] + by_off * s->uvlinesize + bx_off, dst[2] + by_off * s->uvlinesize + bx_off, ref_frame, &uvmv, x_off + bx_off, y_off + by_off, @@ -1288,22 +1847,24 @@ void vp8_mc_part(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], } /* Fetch pixels for estimated mv 4 macroblocks ahead. - * Optimized for 64-byte cache lines. Inspired by ffh264 prefetch_motion. */ -static av_always_inline void prefetch_motion(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, int mb_xy, int ref) + * Optimized for 64-byte cache lines. Inspired by ffh264 prefetch_motion. */ +static av_always_inline +void prefetch_motion(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, + int mb_xy, int ref) { /* Don't prefetch refs that haven't been used very often this frame. */ - if (s->ref_count[ref-1] > (mb_xy >> 5)) { + if (s->ref_count[ref - 1] > (mb_xy >> 5)) { int x_off = mb_x << 4, y_off = mb_y << 4; - int mx = (mb->mv.x>>2) + x_off + 8; - int my = (mb->mv.y>>2) + y_off; - uint8_t **src= s->framep[ref]->tf.f->data; - int off= mx + (my + (mb_x&3)*4)*s->linesize + 64; + int mx = (mb->mv.x >> 2) + x_off + 8; + int my = (mb->mv.y >> 2) + y_off; + uint8_t **src = s->framep[ref]->tf.f->data; + int off = mx + (my + (mb_x & 3) * 4) * s->linesize + 64; /* For threading, a ff_thread_await_progress here might be useful, but * it actually slows down the decoder. Since a bad prefetch doesn't * generate bad decoder output, we don't run it here. */ - s->vdsp.prefetch(src[0]+off, s->linesize, 4); - off= (mx>>1) + ((my>>1) + (mb_x&7))*s->uvlinesize + 64; - s->vdsp.prefetch(src[1]+off, src[2]-src[1], 2); + s->vdsp.prefetch(src[0] + off, s->linesize, 4); + off = (mx >> 1) + ((my >> 1) + (mb_x & 7)) * s->uvlinesize + 64; + s->vdsp.prefetch(src[1] + off, src[2] - src[1], 2); } } @@ -1315,7 +1876,7 @@ void inter_predict(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], VP8Macroblock *mb, int mb_x, int mb_y) { int x_off = mb_x << 4, y_off = mb_y << 4; - int width = 16*s->mb_width, height = 16*s->mb_height; + int width = 16 * s->mb_width, height = 16 * s->mb_height; ThreadFrame *ref = &s->framep[mb->ref_frame]->tf; VP56mv *bmv = mb->bmv; @@ -1331,35 +1892,38 @@ void inter_predict(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], /* Y */ for (y = 0; y < 4; y++) { for (x = 0; x < 4; x++) { - vp8_mc_luma(s, td, dst[0] + 4*y*s->linesize + x*4, - ref, &bmv[4*y + x], - 4*x + x_off, 4*y + y_off, 4, 4, + vp8_mc_luma(s, td, dst[0] + 4 * y * s->linesize + x * 4, + ref, &bmv[4 * y + x], + 4 * x + x_off, 4 * y + y_off, 4, 4, width, height, s->linesize, s->put_pixels_tab[2]); } } /* U/V */ - x_off >>= 1; y_off >>= 1; width >>= 1; height >>= 1; + x_off >>= 1; + y_off >>= 1; + width >>= 1; + height >>= 1; for (y = 0; y < 2; y++) { for (x = 0; x < 2; x++) { - uvmv.x = mb->bmv[ 2*y * 4 + 2*x ].x + - mb->bmv[ 2*y * 4 + 2*x+1].x + - mb->bmv[(2*y+1) * 4 + 2*x ].x + - mb->bmv[(2*y+1) * 4 + 2*x+1].x; - uvmv.y = mb->bmv[ 2*y * 4 + 2*x ].y + - mb->bmv[ 2*y * 4 + 2*x+1].y + - mb->bmv[(2*y+1) * 4 + 2*x ].y + - mb->bmv[(2*y+1) * 4 + 2*x+1].y; - uvmv.x = (uvmv.x + 2 + (uvmv.x >> (INT_BIT-1))) >> 2; - uvmv.y = (uvmv.y + 2 + (uvmv.y >> (INT_BIT-1))) >> 2; + uvmv.x = mb->bmv[2 * y * 4 + 2 * x ].x + + mb->bmv[2 * y * 4 + 2 * x + 1].x + + mb->bmv[(2 * y + 1) * 4 + 2 * x ].x + + mb->bmv[(2 * y + 1) * 4 + 2 * x + 1].x; + uvmv.y = mb->bmv[2 * y * 4 + 2 * x ].y + + mb->bmv[2 * y * 4 + 2 * x + 1].y + + mb->bmv[(2 * y + 1) * 4 + 2 * x ].y + + mb->bmv[(2 * y + 1) * 4 + 2 * x + 1].y; + uvmv.x = (uvmv.x + 2 + (uvmv.x >> (INT_BIT - 1))) >> 2; + uvmv.y = (uvmv.y + 2 + (uvmv.y >> (INT_BIT - 1))) >> 2; if (s->profile == 3) { uvmv.x &= ~7; uvmv.y &= ~7; } - vp8_mc_chroma(s, td, dst[1] + 4*y*s->uvlinesize + x*4, - dst[2] + 4*y*s->uvlinesize + x*4, ref, &uvmv, - 4*x + x_off, 4*y + y_off, 4, 4, + vp8_mc_chroma(s, td, dst[1] + 4 * y * s->uvlinesize + x * 4, + dst[2] + 4 * y * s->uvlinesize + x * 4, ref, + &uvmv, 4 * x + x_off, 4 * y + y_off, 4, 4, width, height, s->uvlinesize, s->put_pixels_tab[2]); } @@ -1391,8 +1955,8 @@ void inter_predict(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], } } -static av_always_inline void idct_mb(VP8Context *s, VP8ThreadData *td, - uint8_t *dst[3], VP8Macroblock *mb) +static av_always_inline +void idct_mb(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], VP8Macroblock *mb) { int x, y, ch; @@ -1401,12 +1965,16 @@ static av_always_inline void idct_mb(VP8Context *s, VP8ThreadData *td, for (y = 0; y < 4; y++) { uint32_t nnz4 = AV_RL32(td->non_zero_count_cache[y]); if (nnz4) { - if (nnz4&~0x01010101) { + if (nnz4 & ~0x01010101) { for (x = 0; x < 4; x++) { - if ((uint8_t)nnz4 == 1) - s->vp8dsp.vp8_idct_dc_add(y_dst+4*x, td->block[y][x], s->linesize); - else if((uint8_t)nnz4 > 1) - s->vp8dsp.vp8_idct_add(y_dst+4*x, td->block[y][x], s->linesize); + if ((uint8_t) nnz4 == 1) + s->vp8dsp.vp8_idct_dc_add(y_dst + 4 * x, + td->block[y][x], + s->linesize); + else if ((uint8_t) nnz4 > 1) + s->vp8dsp.vp8_idct_add(y_dst + 4 * x, + td->block[y][x], + s->linesize); nnz4 >>= 8; if (!nnz4) break; @@ -1415,36 +1983,43 @@ static av_always_inline void idct_mb(VP8Context *s, VP8ThreadData *td, s->vp8dsp.vp8_idct_dc_add4y(y_dst, td->block[y], s->linesize); } } - y_dst += 4*s->linesize; + y_dst += 4 * s->linesize; } } for (ch = 0; ch < 2; ch++) { - uint32_t nnz4 = AV_RL32(td->non_zero_count_cache[4+ch]); + uint32_t nnz4 = AV_RL32(td->non_zero_count_cache[4 + ch]); if (nnz4) { - uint8_t *ch_dst = dst[1+ch]; - if (nnz4&~0x01010101) { + uint8_t *ch_dst = dst[1 + ch]; + if (nnz4 & ~0x01010101) { for (y = 0; y < 2; y++) { for (x = 0; x < 2; x++) { - if ((uint8_t)nnz4 == 1) - s->vp8dsp.vp8_idct_dc_add(ch_dst+4*x, td->block[4+ch][(y<<1)+x], s->uvlinesize); - else if((uint8_t)nnz4 > 1) - s->vp8dsp.vp8_idct_add(ch_dst+4*x, td->block[4+ch][(y<<1)+x], s->uvlinesize); + if ((uint8_t) nnz4 == 1) + s->vp8dsp.vp8_idct_dc_add(ch_dst + 4 * x, + td->block[4 + ch][(y << 1) + x], + s->uvlinesize); + else if ((uint8_t) nnz4 > 1) + s->vp8dsp.vp8_idct_add(ch_dst + 4 * x, + td->block[4 + ch][(y << 1) + x], + s->uvlinesize); nnz4 >>= 8; if (!nnz4) goto chroma_idct_end; } - ch_dst += 4*s->uvlinesize; + ch_dst += 4 * s->uvlinesize; } } else { - s->vp8dsp.vp8_idct_dc_add4uv(ch_dst, td->block[4+ch], s->uvlinesize); + s->vp8dsp.vp8_idct_dc_add4uv(ch_dst, td->block[4 + ch], s->uvlinesize); } } -chroma_idct_end: ; +chroma_idct_end: + ; } } -static av_always_inline void filter_level_for_mb(VP8Context *s, VP8Macroblock *mb, VP8FilterStrength *f ) +static av_always_inline +void filter_level_for_mb(VP8Context *s, VP8Macroblock *mb, + VP8FilterStrength *f, int is_vp7) { int interior_limit, filter_level; @@ -1471,12 +2046,15 @@ static av_always_inline void filter_level_for_mb(VP8Context *s, VP8Macroblock *m f->filter_level = filter_level; f->inner_limit = interior_limit; - f->inner_filter = !mb->skip || mb->mode == MODE_I4x4 || mb->mode == VP8_MVMODE_SPLIT; + f->inner_filter = is_vp7 || !mb->skip || mb->mode == MODE_I4x4 || + mb->mode == VP8_MVMODE_SPLIT; } -static av_always_inline void filter_mb(VP8Context *s, uint8_t *dst[3], VP8FilterStrength *f, int mb_x, int mb_y) +static av_always_inline +void filter_mb(VP8Context *s, uint8_t *dst[3], VP8FilterStrength *f, + int mb_x, int mb_y, int is_vp7) { - int mbedge_lim, bedge_lim, hev_thresh; + int mbedge_lim, bedge_lim_y, bedge_lim_uv, hev_thresh; int filter_level = f->filter_level; int inner_limit = f->inner_limit; int inner_filter = f->inner_filter; @@ -1496,88 +2074,106 @@ static av_always_inline void filter_mb(VP8Context *s, uint8_t *dst[3], VP8Filter if (!filter_level) return; - bedge_lim = 2*filter_level + inner_limit; - mbedge_lim = bedge_lim + 4; + if (is_vp7) { + bedge_lim_y = filter_level; + bedge_lim_uv = filter_level * 2; + mbedge_lim = filter_level + 2; + } else { + bedge_lim_y = + bedge_lim_uv = filter_level * 2 + inner_limit; + mbedge_lim = bedge_lim_y + 4; + } hev_thresh = hev_thresh_lut[s->keyframe][filter_level]; if (mb_x) { - s->vp8dsp.vp8_h_loop_filter16y(dst[0], linesize, + s->vp8dsp.vp8_h_loop_filter16y(dst[0], linesize, mbedge_lim, inner_limit, hev_thresh); - s->vp8dsp.vp8_h_loop_filter8uv(dst[1], dst[2], uvlinesize, + s->vp8dsp.vp8_h_loop_filter8uv(dst[1], dst[2], uvlinesize, mbedge_lim, inner_limit, hev_thresh); } - if (inner_filter) { - s->vp8dsp.vp8_h_loop_filter16y_inner(dst[0]+ 4, linesize, bedge_lim, - inner_limit, hev_thresh); - s->vp8dsp.vp8_h_loop_filter16y_inner(dst[0]+ 8, linesize, bedge_lim, - inner_limit, hev_thresh); - s->vp8dsp.vp8_h_loop_filter16y_inner(dst[0]+12, linesize, bedge_lim, - inner_limit, hev_thresh); - s->vp8dsp.vp8_h_loop_filter8uv_inner(dst[1] + 4, dst[2] + 4, - uvlinesize, bedge_lim, - inner_limit, hev_thresh); +#define H_LOOP_FILTER_16Y_INNER(cond) \ + if (cond && inner_filter) { \ + s->vp8dsp.vp8_h_loop_filter16y_inner(dst[0] + 4, linesize, \ + bedge_lim_y, inner_limit, \ + hev_thresh); \ + s->vp8dsp.vp8_h_loop_filter16y_inner(dst[0] + 8, linesize, \ + bedge_lim_y, inner_limit, \ + hev_thresh); \ + s->vp8dsp.vp8_h_loop_filter16y_inner(dst[0] + 12, linesize, \ + bedge_lim_y, inner_limit, \ + hev_thresh); \ + s->vp8dsp.vp8_h_loop_filter8uv_inner(dst[1] + 4, dst[2] + 4, \ + uvlinesize, bedge_lim_uv, \ + inner_limit, hev_thresh); \ } + H_LOOP_FILTER_16Y_INNER(!is_vp7) + if (mb_y) { - s->vp8dsp.vp8_v_loop_filter16y(dst[0], linesize, + s->vp8dsp.vp8_v_loop_filter16y(dst[0], linesize, mbedge_lim, inner_limit, hev_thresh); - s->vp8dsp.vp8_v_loop_filter8uv(dst[1], dst[2], uvlinesize, + s->vp8dsp.vp8_v_loop_filter8uv(dst[1], dst[2], uvlinesize, mbedge_lim, inner_limit, hev_thresh); } if (inner_filter) { - s->vp8dsp.vp8_v_loop_filter16y_inner(dst[0]+ 4*linesize, - linesize, bedge_lim, + s->vp8dsp.vp8_v_loop_filter16y_inner(dst[0] + 4 * linesize, + linesize, bedge_lim_y, inner_limit, hev_thresh); - s->vp8dsp.vp8_v_loop_filter16y_inner(dst[0]+ 8*linesize, - linesize, bedge_lim, + s->vp8dsp.vp8_v_loop_filter16y_inner(dst[0] + 8 * linesize, + linesize, bedge_lim_y, inner_limit, hev_thresh); - s->vp8dsp.vp8_v_loop_filter16y_inner(dst[0]+12*linesize, - linesize, bedge_lim, + s->vp8dsp.vp8_v_loop_filter16y_inner(dst[0] + 12 * linesize, + linesize, bedge_lim_y, inner_limit, hev_thresh); - s->vp8dsp.vp8_v_loop_filter8uv_inner(dst[1] + 4 * uvlinesize, - dst[2] + 4 * uvlinesize, - uvlinesize, bedge_lim, + s->vp8dsp.vp8_v_loop_filter8uv_inner(dst[1] + 4 * uvlinesize, + dst[2] + 4 * uvlinesize, + uvlinesize, bedge_lim_uv, inner_limit, hev_thresh); } + + H_LOOP_FILTER_16Y_INNER(is_vp7) } -static av_always_inline void filter_mb_simple(VP8Context *s, uint8_t *dst, VP8FilterStrength *f, int mb_x, int mb_y) +static av_always_inline +void filter_mb_simple(VP8Context *s, uint8_t *dst, VP8FilterStrength *f, + int mb_x, int mb_y) { int mbedge_lim, bedge_lim; int filter_level = f->filter_level; - int inner_limit = f->inner_limit; + int inner_limit = f->inner_limit; int inner_filter = f->inner_filter; - int linesize = s->linesize; + int linesize = s->linesize; if (!filter_level) return; - bedge_lim = 2*filter_level + inner_limit; + bedge_lim = 2 * filter_level + inner_limit; mbedge_lim = bedge_lim + 4; if (mb_x) s->vp8dsp.vp8_h_loop_filter_simple(dst, linesize, mbedge_lim); if (inner_filter) { - s->vp8dsp.vp8_h_loop_filter_simple(dst+ 4, linesize, bedge_lim); - s->vp8dsp.vp8_h_loop_filter_simple(dst+ 8, linesize, bedge_lim); - s->vp8dsp.vp8_h_loop_filter_simple(dst+12, linesize, bedge_lim); + s->vp8dsp.vp8_h_loop_filter_simple(dst + 4, linesize, bedge_lim); + s->vp8dsp.vp8_h_loop_filter_simple(dst + 8, linesize, bedge_lim); + s->vp8dsp.vp8_h_loop_filter_simple(dst + 12, linesize, bedge_lim); } if (mb_y) s->vp8dsp.vp8_v_loop_filter_simple(dst, linesize, mbedge_lim); if (inner_filter) { - s->vp8dsp.vp8_v_loop_filter_simple(dst+ 4*linesize, linesize, bedge_lim); - s->vp8dsp.vp8_v_loop_filter_simple(dst+ 8*linesize, linesize, bedge_lim); - s->vp8dsp.vp8_v_loop_filter_simple(dst+12*linesize, linesize, bedge_lim); + s->vp8dsp.vp8_v_loop_filter_simple(dst + 4 * linesize, linesize, bedge_lim); + s->vp8dsp.vp8_v_loop_filter_simple(dst + 8 * linesize, linesize, bedge_lim); + s->vp8dsp.vp8_v_loop_filter_simple(dst + 12 * linesize, linesize, bedge_lim); } } #define MARGIN (16 << 2) -static void vp8_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *curframe, - VP8Frame *prev_frame) +static av_always_inline +void vp78_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *curframe, + VP8Frame *prev_frame, int is_vp7) { VP8Context *s = avctx->priv_data; int mb_x, mb_y; @@ -1585,19 +2181,21 @@ static void vp8_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *curframe, s->mv_min.y = -MARGIN; s->mv_max.y = ((s->mb_height - 1) << 6) + MARGIN; for (mb_y = 0; mb_y < s->mb_height; mb_y++) { - VP8Macroblock *mb = s->macroblocks_base + ((s->mb_width+1)*(mb_y + 1) + 1); - int mb_xy = mb_y*s->mb_width; + VP8Macroblock *mb = s->macroblocks_base + + ((s->mb_width + 1) * (mb_y + 1) + 1); + int mb_xy = mb_y * s->mb_width; - AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED*0x01010101); + AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED * 0x01010101); s->mv_min.x = -MARGIN; s->mv_max.x = ((s->mb_width - 1) << 6) + MARGIN; for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) { if (mb_y == 0) - AV_WN32A((mb-s->mb_width-1)->intra4x4_pred_mode_top, DC_PRED*0x01010101); + AV_WN32A((mb - s->mb_width - 1)->intra4x4_pred_mode_top, + DC_PRED * 0x01010101); decode_mb_mode(s, mb, mb_x, mb_y, curframe->seg_map->data + mb_xy, prev_frame && prev_frame->seg_map ? - prev_frame->seg_map->data + mb_xy : NULL, 1); + prev_frame->seg_map->data + mb_xy : NULL, 1, is_vp7); s->mv_min.x -= 64; s->mv_max.x -= 64; } @@ -1606,106 +2204,132 @@ static void vp8_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *curframe, } } -#if HAVE_THREADS -#define check_thread_pos(td, otd, mb_x_check, mb_y_check)\ - do {\ - int tmp = (mb_y_check << 16) | (mb_x_check & 0xFFFF);\ - if (otd->thread_mb_pos < tmp) {\ - pthread_mutex_lock(&otd->lock);\ - td->wait_mb_pos = tmp;\ - do {\ - if (otd->thread_mb_pos >= tmp)\ - break;\ - pthread_cond_wait(&otd->cond, &otd->lock);\ - } while (1);\ - td->wait_mb_pos = INT_MAX;\ - pthread_mutex_unlock(&otd->lock);\ - }\ - } while(0); +static void vp7_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *cur_frame, + VP8Frame *prev_frame) +{ + vp78_decode_mv_mb_modes(avctx, cur_frame, prev_frame, IS_VP7); +} -#define update_pos(td, mb_y, mb_x)\ - do {\ - int pos = (mb_y << 16) | (mb_x & 0xFFFF);\ - int sliced_threading = (avctx->active_thread_type == FF_THREAD_SLICE) && (num_jobs > 1);\ - int is_null = (next_td == NULL) || (prev_td == NULL);\ - int pos_check = (is_null) ? 1 :\ - (next_td != td && pos >= next_td->wait_mb_pos) ||\ - (prev_td != td && pos >= prev_td->wait_mb_pos);\ - td->thread_mb_pos = pos;\ - if (sliced_threading && pos_check) {\ - pthread_mutex_lock(&td->lock);\ - pthread_cond_broadcast(&td->cond);\ - pthread_mutex_unlock(&td->lock);\ - }\ - } while(0); +static void vp8_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *cur_frame, + VP8Frame *prev_frame) +{ + vp78_decode_mv_mb_modes(avctx, cur_frame, prev_frame, IS_VP8); +} + +#if HAVE_THREADS +#define check_thread_pos(td, otd, mb_x_check, mb_y_check) \ + do { \ + int tmp = (mb_y_check << 16) | (mb_x_check & 0xFFFF); \ + if (otd->thread_mb_pos < tmp) { \ + pthread_mutex_lock(&otd->lock); \ + td->wait_mb_pos = tmp; \ + do { \ + if (otd->thread_mb_pos >= tmp) \ + break; \ + pthread_cond_wait(&otd->cond, &otd->lock); \ + } while (1); \ + td->wait_mb_pos = INT_MAX; \ + pthread_mutex_unlock(&otd->lock); \ + } \ + } while (0); + +#define update_pos(td, mb_y, mb_x) \ + do { \ + int pos = (mb_y << 16) | (mb_x & 0xFFFF); \ + int sliced_threading = (avctx->active_thread_type == FF_THREAD_SLICE) && \ + (num_jobs > 1); \ + int is_null = (next_td == NULL) || (prev_td == NULL); \ + int pos_check = (is_null) ? 1 \ + : (next_td != td && \ + pos >= next_td->wait_mb_pos) || \ + (prev_td != td && \ + pos >= prev_td->wait_mb_pos); \ + td->thread_mb_pos = pos; \ + if (sliced_threading && pos_check) { \ + pthread_mutex_lock(&td->lock); \ + pthread_cond_broadcast(&td->cond); \ + pthread_mutex_unlock(&td->lock); \ + } \ + } while (0); #else #define check_thread_pos(td, otd, mb_x_check, mb_y_check) #define update_pos(td, mb_y, mb_x) #endif -static void vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, - int jobnr, int threadnr) +static av_always_inline void decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, + int jobnr, int threadnr, int is_vp7) { VP8Context *s = avctx->priv_data; VP8ThreadData *prev_td, *next_td, *td = &s->thread_data[threadnr]; - int mb_y = td->thread_mb_pos>>16; - int mb_x, mb_xy = mb_y*s->mb_width; + int mb_y = td->thread_mb_pos >> 16; + int mb_x, mb_xy = mb_y * s->mb_width; int num_jobs = s->num_jobs; VP8Frame *curframe = s->curframe, *prev_frame = s->prev_frame; - VP56RangeCoder *c = &s->coeff_partition[mb_y & (s->num_coeff_partitions-1)]; + VP56RangeCoder *c = &s->coeff_partition[mb_y & (s->num_coeff_partitions - 1)]; VP8Macroblock *mb; uint8_t *dst[3] = { - curframe->tf.f->data[0] + 16*mb_y*s->linesize, - curframe->tf.f->data[1] + 8*mb_y*s->uvlinesize, - curframe->tf.f->data[2] + 8*mb_y*s->uvlinesize + curframe->tf.f->data[0] + 16 * mb_y * s->linesize, + curframe->tf.f->data[1] + 8 * mb_y * s->uvlinesize, + curframe->tf.f->data[2] + 8 * mb_y * s->uvlinesize }; - if (mb_y == 0) prev_td = td; - else prev_td = &s->thread_data[(jobnr + num_jobs - 1)%num_jobs]; - if (mb_y == s->mb_height-1) next_td = td; - else next_td = &s->thread_data[(jobnr + 1)%num_jobs]; + if (mb_y == 0) + prev_td = td; + else + prev_td = &s->thread_data[(jobnr + num_jobs - 1) % num_jobs]; + if (mb_y == s->mb_height - 1) + next_td = td; + else + next_td = &s->thread_data[(jobnr + 1) % num_jobs]; if (s->mb_layout == 1) - mb = s->macroblocks_base + ((s->mb_width+1)*(mb_y + 1) + 1); + mb = s->macroblocks_base + ((s->mb_width + 1) * (mb_y + 1) + 1); else { // Make sure the previous frame has read its segmentation map, // if we re-use the same map. if (prev_frame && s->segmentation.enabled && !s->segmentation.update_map) ff_thread_await_progress(&prev_frame->tf, mb_y, 0); - mb = s->macroblocks + (s->mb_height - mb_y - 1)*2; + mb = s->macroblocks + (s->mb_height - mb_y - 1) * 2; memset(mb - 1, 0, sizeof(*mb)); // zero left macroblock - AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED*0x01010101); + AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED * 0x01010101); } - memset(td->left_nnz, 0, sizeof(td->left_nnz)); + if (!is_vp7 || mb_y == 0) + memset(td->left_nnz, 0, sizeof(td->left_nnz)); s->mv_min.x = -MARGIN; - s->mv_max.x = ((s->mb_width - 1) << 6) + MARGIN; + s->mv_max.x = ((s->mb_width - 1) << 6) + MARGIN; for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) { // Wait for previous thread to read mb_x+2, and reach mb_y-1. if (prev_td != td) { if (threadnr != 0) { - check_thread_pos(td, prev_td, mb_x+1, mb_y-1); + check_thread_pos(td, prev_td, + mb_x + (is_vp7 ? 2 : 1), + mb_y - (is_vp7 ? 2 : 1)); } else { - check_thread_pos(td, prev_td, (s->mb_width+3) + (mb_x+1), mb_y-1); + check_thread_pos(td, prev_td, + mb_x + (is_vp7 ? 2 : 1) + s->mb_width + 3, + mb_y - (is_vp7 ? 2 : 1)); } } - s->vdsp.prefetch(dst[0] + (mb_x&3)*4*s->linesize + 64, s->linesize, 4); - s->vdsp.prefetch(dst[1] + (mb_x&7)*s->uvlinesize + 64, dst[2] - dst[1], 2); + s->vdsp.prefetch(dst[0] + (mb_x & 3) * 4 * s->linesize + 64, + s->linesize, 4); + s->vdsp.prefetch(dst[1] + (mb_x & 7) * s->uvlinesize + 64, + dst[2] - dst[1], 2); if (!s->mb_layout) decode_mb_mode(s, mb, mb_x, mb_y, curframe->seg_map->data + mb_xy, prev_frame && prev_frame->seg_map ? - prev_frame->seg_map->data + mb_xy : NULL, 0); + prev_frame->seg_map->data + mb_xy : NULL, 0, is_vp7); prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_PREVIOUS); if (!mb->skip) - decode_mb_coeffs(s, td, c, mb, s->top_nnz[mb_x], td->left_nnz); + decode_mb_coeffs(s, td, c, mb, s->top_nnz[mb_x], td->left_nnz, is_vp7); if (mb->mode <= MODE_I4x4) - intra_predict(s, td, dst, mb, mb_x, mb_y); + intra_predict(s, td, dst, mb, mb_x, mb_y, is_vp7); else inter_predict(s, td, dst, mb, mb_x, mb_y); @@ -1717,7 +2341,8 @@ static void vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, AV_ZERO64(td->left_nnz); AV_WN64(s->top_nnz[mb_x], 0); // array of 9, so unaligned - // Reset DC block predictors if they would exist if the mb had coefficients + /* Reset DC block predictors if they would exist + * if the mb had coefficients */ if (mb->mode != MODE_I4x4 && mb->mode != VP8_MVMODE_SPLIT) { td->left_nnz[8] = 0; s->top_nnz[mb_x][8] = 0; @@ -1725,100 +2350,134 @@ static void vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, } if (s->deblock_filter) - filter_level_for_mb(s, mb, &td->filter_strength[mb_x]); + filter_level_for_mb(s, mb, &td->filter_strength[mb_x], is_vp7); - if (s->deblock_filter && num_jobs != 1 && threadnr == num_jobs-1) { + if (s->deblock_filter && num_jobs != 1 && threadnr == num_jobs - 1) { if (s->filter.simple) - backup_mb_border(s->top_border[mb_x+1], dst[0], NULL, NULL, s->linesize, 0, 1); + backup_mb_border(s->top_border[mb_x + 1], dst[0], + NULL, NULL, s->linesize, 0, 1); else - backup_mb_border(s->top_border[mb_x+1], dst[0], dst[1], dst[2], s->linesize, s->uvlinesize, 0); + backup_mb_border(s->top_border[mb_x + 1], dst[0], + dst[1], dst[2], s->linesize, s->uvlinesize, 0); } prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_GOLDEN2); - dst[0] += 16; - dst[1] += 8; - dst[2] += 8; + dst[0] += 16; + dst[1] += 8; + dst[2] += 8; s->mv_min.x -= 64; s->mv_max.x -= 64; - if (mb_x == s->mb_width+1) { - update_pos(td, mb_y, s->mb_width+3); + if (mb_x == s->mb_width + 1) { + update_pos(td, mb_y, s->mb_width + 3); } else { update_pos(td, mb_y, mb_x); } } } -static void vp8_filter_mb_row(AVCodecContext *avctx, void *tdata, - int jobnr, int threadnr) +static void vp7_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, + int jobnr, int threadnr) +{ + decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr, 1); +} + +static void vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, + int jobnr, int threadnr) +{ + decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr, 0); +} + +static av_always_inline void filter_mb_row(AVCodecContext *avctx, void *tdata, + int jobnr, int threadnr, int is_vp7) { VP8Context *s = avctx->priv_data; VP8ThreadData *td = &s->thread_data[threadnr]; - int mb_x, mb_y = td->thread_mb_pos>>16, num_jobs = s->num_jobs; + int mb_x, mb_y = td->thread_mb_pos >> 16, num_jobs = s->num_jobs; AVFrame *curframe = s->curframe->tf.f; VP8Macroblock *mb; VP8ThreadData *prev_td, *next_td; uint8_t *dst[3] = { - curframe->data[0] + 16*mb_y*s->linesize, - curframe->data[1] + 8*mb_y*s->uvlinesize, - curframe->data[2] + 8*mb_y*s->uvlinesize + curframe->data[0] + 16 * mb_y * s->linesize, + curframe->data[1] + 8 * mb_y * s->uvlinesize, + curframe->data[2] + 8 * mb_y * s->uvlinesize }; if (s->mb_layout == 1) - mb = s->macroblocks_base + ((s->mb_width+1)*(mb_y + 1) + 1); + mb = s->macroblocks_base + ((s->mb_width + 1) * (mb_y + 1) + 1); else - mb = s->macroblocks + (s->mb_height - mb_y - 1)*2; + mb = s->macroblocks + (s->mb_height - mb_y - 1) * 2; - if (mb_y == 0) prev_td = td; - else prev_td = &s->thread_data[(jobnr + num_jobs - 1)%num_jobs]; - if (mb_y == s->mb_height-1) next_td = td; - else next_td = &s->thread_data[(jobnr + 1)%num_jobs]; + if (mb_y == 0) + prev_td = td; + else + prev_td = &s->thread_data[(jobnr + num_jobs - 1) % num_jobs]; + if (mb_y == s->mb_height - 1) + next_td = td; + else + next_td = &s->thread_data[(jobnr + 1) % num_jobs]; for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb++) { VP8FilterStrength *f = &td->filter_strength[mb_x]; - if (prev_td != td) { - check_thread_pos(td, prev_td, (mb_x+1) + (s->mb_width+3), mb_y-1); - } + if (prev_td != td) + check_thread_pos(td, prev_td, + (mb_x + 1) + (s->mb_width + 3), mb_y - 1); if (next_td != td) - if (next_td != &s->thread_data[0]) { - check_thread_pos(td, next_td, mb_x+1, mb_y+1); - } + if (next_td != &s->thread_data[0]) + check_thread_pos(td, next_td, mb_x + 1, mb_y + 1); if (num_jobs == 1) { if (s->filter.simple) - backup_mb_border(s->top_border[mb_x+1], dst[0], NULL, NULL, s->linesize, 0, 1); + backup_mb_border(s->top_border[mb_x + 1], dst[0], + NULL, NULL, s->linesize, 0, 1); else - backup_mb_border(s->top_border[mb_x+1], dst[0], dst[1], dst[2], s->linesize, s->uvlinesize, 0); + backup_mb_border(s->top_border[mb_x + 1], dst[0], + dst[1], dst[2], s->linesize, s->uvlinesize, 0); } if (s->filter.simple) filter_mb_simple(s, dst[0], f, mb_x, mb_y); else - filter_mb(s, dst, f, mb_x, mb_y); + filter_mb(s, dst, f, mb_x, mb_y, is_vp7); dst[0] += 16; dst[1] += 8; dst[2] += 8; - update_pos(td, mb_y, (s->mb_width+3) + mb_x); + update_pos(td, mb_y, (s->mb_width + 3) + mb_x); } } -static int vp8_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, - int jobnr, int threadnr) +static void vp7_filter_mb_row(AVCodecContext *avctx, void *tdata, + int jobnr, int threadnr) +{ + filter_mb_row(avctx, tdata, jobnr, threadnr, 1); +} + +static void vp8_filter_mb_row(AVCodecContext *avctx, void *tdata, + int jobnr, int threadnr) +{ + filter_mb_row(avctx, tdata, jobnr, threadnr, 0); +} + +static av_always_inline +int vp78_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, int jobnr, + int threadnr, int is_vp7) { VP8Context *s = avctx->priv_data; VP8ThreadData *td = &s->thread_data[jobnr]; VP8ThreadData *next_td = NULL, *prev_td = NULL; VP8Frame *curframe = s->curframe; int mb_y, num_jobs = s->num_jobs; + td->thread_nr = threadnr; for (mb_y = jobnr; mb_y < s->mb_height; mb_y += num_jobs) { - if (mb_y >= s->mb_height) break; - td->thread_mb_pos = mb_y<<16; - vp8_decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr); + if (mb_y >= s->mb_height) + break; + td->thread_mb_pos = mb_y << 16; + s->decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr); if (s->deblock_filter) - vp8_filter_mb_row(avctx, tdata, jobnr, threadnr); + s->filter_mb_row(avctx, tdata, jobnr, threadnr); update_pos(td, mb_y, INT_MAX & 0xFFFF); s->mv_min.y -= 64; @@ -1831,24 +2490,44 @@ static int vp8_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, return 0; } -int ff_vp8_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int vp7_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, + int jobnr, int threadnr) +{ + return vp78_decode_mb_row_sliced(avctx, tdata, jobnr, threadnr, IS_VP7); +} + +static int vp8_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, + int jobnr, int threadnr) +{ + return vp78_decode_mb_row_sliced(avctx, tdata, jobnr, threadnr, IS_VP8); +} + + +static av_always_inline +int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt, int is_vp7) { VP8Context *s = avctx->priv_data; int ret, i, referenced, num_jobs; enum AVDiscard skip_thresh; VP8Frame *av_uninit(curframe), *prev_frame; - if ((ret = decode_frame_header(s, avpkt->data, avpkt->size)) < 0) + if (is_vp7) + ret = vp7_decode_frame_header(s, avpkt->data, avpkt->size); + else + ret = vp8_decode_frame_header(s, avpkt->data, avpkt->size); + + if (ret < 0) goto err; prev_frame = s->framep[VP56_FRAME_CURRENT]; - referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT - || s->update_altref == VP56_FRAME_CURRENT; + referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT || + s->update_altref == VP56_FRAME_CURRENT; - skip_thresh = !referenced ? AVDISCARD_NONREF : - !s->keyframe ? AVDISCARD_NONKEY : AVDISCARD_ALL; + skip_thresh = !referenced ? AVDISCARD_NONREF + : !s->keyframe ? AVDISCARD_NONKEY + : AVDISCARD_ALL; if (avctx->skip_frame >= skip_thresh) { s->invisible = 1; @@ -1862,82 +2541,76 @@ int ff_vp8_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (s->frames[i].tf.f->data[0] && &s->frames[i] != prev_frame && &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] && - &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] && + &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] && &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) vp8_release_frame(s, &s->frames[i]); - // find a free buffer - for (i = 0; i < 5; i++) - if (&s->frames[i] != prev_frame && - &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] && - &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] && - &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) { - curframe = s->framep[VP56_FRAME_CURRENT] = &s->frames[i]; - break; - } - if (i == 5) { - av_log(avctx, AV_LOG_FATAL, "Ran out of free frames!\n"); - abort(); - } - if (curframe->tf.f->data[0]) - vp8_release_frame(s, curframe); + curframe = s->framep[VP56_FRAME_CURRENT] = vp8_find_free_buffer(s); - // Given that arithmetic probabilities are updated every frame, it's quite likely - // that the values we have on a random interframe are complete junk if we didn't - // start decode on a keyframe. So just don't display anything rather than junk. + /* Given that arithmetic probabilities are updated every frame, it's quite + * likely that the values we have on a random interframe are complete + * junk if we didn't start decode on a keyframe. So just don't display + * anything rather than junk. */ if (!s->keyframe && (!s->framep[VP56_FRAME_PREVIOUS] || - !s->framep[VP56_FRAME_GOLDEN] || + !s->framep[VP56_FRAME_GOLDEN] || !s->framep[VP56_FRAME_GOLDEN2])) { - av_log(avctx, AV_LOG_WARNING, "Discarding interframe without a prior keyframe!\n"); + av_log(avctx, AV_LOG_WARNING, + "Discarding interframe without a prior keyframe!\n"); ret = AVERROR_INVALIDDATA; goto err; } curframe->tf.f->key_frame = s->keyframe; - curframe->tf.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + curframe->tf.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I + : AV_PICTURE_TYPE_P; if ((ret = vp8_alloc_frame(s, curframe, referenced)) < 0) goto err; // check if golden and altref are swapped - if (s->update_altref != VP56_FRAME_NONE) { - s->next_framep[VP56_FRAME_GOLDEN2] = s->framep[s->update_altref]; - } else { - s->next_framep[VP56_FRAME_GOLDEN2] = s->framep[VP56_FRAME_GOLDEN2]; - } - if (s->update_golden != VP56_FRAME_NONE) { - s->next_framep[VP56_FRAME_GOLDEN] = s->framep[s->update_golden]; - } else { - s->next_framep[VP56_FRAME_GOLDEN] = s->framep[VP56_FRAME_GOLDEN]; - } - if (s->update_last) { - s->next_framep[VP56_FRAME_PREVIOUS] = curframe; - } else { - s->next_framep[VP56_FRAME_PREVIOUS] = s->framep[VP56_FRAME_PREVIOUS]; - } - s->next_framep[VP56_FRAME_CURRENT] = curframe; + if (s->update_altref != VP56_FRAME_NONE) + s->next_framep[VP56_FRAME_GOLDEN2] = s->framep[s->update_altref]; + else + s->next_framep[VP56_FRAME_GOLDEN2] = s->framep[VP56_FRAME_GOLDEN2]; - ff_thread_finish_setup(avctx); + if (s->update_golden != VP56_FRAME_NONE) + s->next_framep[VP56_FRAME_GOLDEN] = s->framep[s->update_golden]; + else + s->next_framep[VP56_FRAME_GOLDEN] = s->framep[VP56_FRAME_GOLDEN]; + + if (s->update_last) + s->next_framep[VP56_FRAME_PREVIOUS] = curframe; + else + s->next_framep[VP56_FRAME_PREVIOUS] = s->framep[VP56_FRAME_PREVIOUS]; + + s->next_framep[VP56_FRAME_CURRENT] = curframe; + + if (avctx->codec->update_thread_context) + ff_thread_finish_setup(avctx); s->linesize = curframe->tf.f->linesize[0]; s->uvlinesize = curframe->tf.f->linesize[1]; - memset(s->top_nnz, 0, s->mb_width*sizeof(*s->top_nnz)); - /* Zero macroblock structures for top/top-left prediction from outside the frame. */ + memset(s->top_nnz, 0, s->mb_width * sizeof(*s->top_nnz)); + /* Zero macroblock structures for top/top-left prediction + * from outside the frame. */ if (!s->mb_layout) - memset(s->macroblocks + s->mb_height*2 - 1, 0, (s->mb_width+1)*sizeof(*s->macroblocks)); + memset(s->macroblocks + s->mb_height * 2 - 1, 0, + (s->mb_width + 1) * sizeof(*s->macroblocks)); if (!s->mb_layout && s->keyframe) - memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width*4); + memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width * 4); memset(s->ref_count, 0, sizeof(s->ref_count)); - if (s->mb_layout == 1) { // Make sure the previous frame has read its segmentation map, // if we re-use the same map. if (prev_frame && s->segmentation.enabled && !s->segmentation.update_map) ff_thread_await_progress(&prev_frame->tf, 1, 0); - vp8_decode_mv_mb_modes(avctx, curframe, prev_frame); + if (is_vp7) + vp7_decode_mv_mb_modes(avctx, curframe, prev_frame); + else + vp8_decode_mv_mb_modes(avctx, curframe, prev_frame); } if (avctx->active_thread_type == FF_THREAD_FRAME) @@ -1951,9 +2624,14 @@ int ff_vp8_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->mv_max.y = ((s->mb_height - 1) << 6) + MARGIN; for (i = 0; i < MAX_THREADS; i++) { s->thread_data[i].thread_mb_pos = 0; - s->thread_data[i].wait_mb_pos = INT_MAX; + s->thread_data[i].wait_mb_pos = INT_MAX; } - avctx->execute2(avctx, vp8_decode_mb_row_sliced, s->thread_data, NULL, num_jobs); + if (is_vp7) + avctx->execute2(avctx, vp7_decode_mb_row_sliced, s->thread_data, NULL, + num_jobs); + else + avctx->execute2(avctx, vp8_decode_mb_row_sliced, s->thread_data, NULL, + num_jobs); ff_thread_report_progress(&curframe->tf, INT_MAX, 0); memcpy(&s->framep[0], &s->next_framep[0], sizeof(s->framep[0]) * 4); @@ -1967,7 +2645,7 @@ skip_decode: if (!s->invisible) { if ((ret = av_frame_ref(data, curframe->tf.f)) < 0) return ret; - *got_frame = 1; + *got_frame = 1; } return avpkt->size; @@ -1976,6 +2654,20 @@ err: return ret; } +int ff_vp8_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + return vp78_decode_frame(avctx, data, got_frame, avpkt, IS_VP8); +} + +#if CONFIG_VP7_DECODER +static int vp7_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + return vp78_decode_frame(avctx, data, got_frame, avpkt, IS_VP7); +} +#endif /* CONFIG_VP7_DECODER */ + av_cold int ff_vp8_decode_free(AVCodecContext *avctx) { VP8Context *s = avctx->priv_data; @@ -1999,18 +2691,34 @@ static av_cold int vp8_init_frames(VP8Context *s) return 0; } -av_cold int ff_vp8_decode_init(AVCodecContext *avctx) +static av_always_inline +int vp78_decode_init(AVCodecContext *avctx, int is_vp7) { VP8Context *s = avctx->priv_data; int ret; s->avctx = avctx; + s->vp7 = avctx->codec->id == AV_CODEC_ID_VP7; avctx->pix_fmt = AV_PIX_FMT_YUV420P; avctx->internal->allocate_progress = 1; ff_videodsp_init(&s->vdsp, 8); - ff_h264_pred_init(&s->hpc, AV_CODEC_ID_VP8, 8, 1); - ff_vp8dsp_init(&s->vp8dsp, 0); + + ff_vp78dsp_init(&s->vp8dsp); + if (CONFIG_VP7_DECODER && is_vp7) { + ff_h264_pred_init(&s->hpc, AV_CODEC_ID_VP7, 8, 1); + ff_vp7dsp_init(&s->vp8dsp); + s->decode_mb_row_no_filter = vp7_decode_mb_row_no_filter; + s->filter_mb_row = vp7_filter_mb_row; + } else if (CONFIG_VP8_DECODER && !is_vp7) { + ff_h264_pred_init(&s->hpc, AV_CODEC_ID_VP8, 8, 1); + ff_vp8dsp_init(&s->vp8dsp); + s->decode_mb_row_no_filter = vp8_decode_mb_row_no_filter; + s->filter_mb_row = vp8_filter_mb_row; + } + + /* does not change for VP8 */ + memcpy(s->prob[0].scan, zigzag_scan, sizeof(s->prob[0].scan)); if ((ret = vp8_init_frames(s)) < 0) { ff_vp8_decode_free(avctx); @@ -2020,6 +2728,19 @@ av_cold int ff_vp8_decode_init(AVCodecContext *avctx) return 0; } +#if CONFIG_VP7_DECODER +static int vp7_decode_init(AVCodecContext *avctx) +{ + return vp78_decode_init(avctx, IS_VP7); +} +#endif /* CONFIG_VP7_DECODER */ + +av_cold int ff_vp8_decode_init(AVCodecContext *avctx) +{ + return vp78_decode_init(avctx, IS_VP8); +} + +#if CONFIG_VP8_DECODER static av_cold int vp8_decode_init_thread_copy(AVCodecContext *avctx) { VP8Context *s = avctx->priv_data; @@ -2035,10 +2756,10 @@ static av_cold int vp8_decode_init_thread_copy(AVCodecContext *avctx) return 0; } -#define REBASE(pic) \ - pic ? pic - &s_src->frames[0] + &s->frames[0] : NULL +#define REBASE(pic) ((pic) ? (pic) - &s_src->frames[0] + &s->frames[0] : NULL) -static int vp8_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) +static int vp8_decode_update_thread_context(AVCodecContext *dst, + const AVCodecContext *src) { VP8Context *s = dst->priv_data, *s_src = src->priv_data; int i; @@ -2050,9 +2771,9 @@ static int vp8_decode_update_thread_context(AVCodecContext *dst, const AVCodecCo s->mb_height = s_src->mb_height; } - s->prob[0] = s_src->prob[!s_src->update_probabilities]; + s->prob[0] = s_src->prob[!s_src->update_probabilities]; s->segmentation = s_src->segmentation; - s->lf_delta = s_src->lf_delta; + s->lf_delta = s_src->lf_delta; memcpy(s->sign_bias, s_src->sign_bias, sizeof(s->sign_bias)); for (i = 0; i < FF_ARRAY_ELEMS(s_src->frames); i++) { @@ -2070,7 +2791,24 @@ static int vp8_decode_update_thread_context(AVCodecContext *dst, const AVCodecCo return 0; } +#endif /* CONFIG_VP8_DECODER */ +#if CONFIG_VP7_DECODER +AVCodec ff_vp7_decoder = { + .name = "vp7", + .long_name = NULL_IF_CONFIG_SMALL("On2 VP7"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP7, + .priv_data_size = sizeof(VP8Context), + .init = vp7_decode_init, + .close = ff_vp8_decode_free, + .decode = vp7_decode_frame, + .capabilities = CODEC_CAP_DR1, + .flush = vp8_decode_flush, +}; +#endif /* CONFIG_VP7_DECODER */ + +#if CONFIG_VP8_DECODER AVCodec ff_vp8_decoder = { .name = "vp8", .long_name = NULL_IF_CONFIG_SMALL("On2 VP8"), @@ -2085,4 +2823,4 @@ AVCodec ff_vp8_decoder = { .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context), }; - +#endif /* CONFIG_VP7_DECODER */ diff --git a/libavcodec/vp8.h b/libavcodec/vp8.h index 2f0029882..83729c8b9 100644 --- a/libavcodec/vp8.h +++ b/libavcodec/vp8.h @@ -3,7 +3,7 @@ * * Copyright (C) 2010 David Conrad * Copyright (C) 2010 Ronald S. Bultje - * Copyright (C) 2010 Jason Garrett-Glaser + * Copyright (C) 2010 Fiona Glaser * Copyright (C) 2012 Daniel Kang * * This file is part of FFmpeg. @@ -28,16 +28,17 @@ #include "libavutil/buffer.h" -#include "vp56.h" -#include "vp8dsp.h" #include "h264pred.h" #include "thread.h" +#include "vp56.h" +#include "vp8dsp.h" + #if HAVE_PTHREADS -#include +# include #elif HAVE_OS2THREADS -#include "compat/os2threads.h" +# include "compat/os2threads.h" #elif HAVE_W32THREADS -#include "compat/w32pthreads.h" +# include "compat/w32pthreads.h" #endif #define VP8_MAX_QUANT 127 @@ -84,7 +85,7 @@ typedef struct VP8FilterStrength { typedef struct VP8Macroblock { uint8_t skip; - // todo: make it possible to check for at least (i4x4 or split_mv) + // TODO: make it possible to check for at least (i4x4 or split_mv) // in one op. are others needed? uint8_t mode; uint8_t ref_frame; @@ -92,7 +93,7 @@ typedef struct VP8Macroblock { uint8_t chroma_pred_mode; uint8_t segment; uint8_t intra4x4_pred_mode_mb[16]; - uint8_t intra4x4_pred_mode_top[4]; + DECLARE_ALIGNED(4, uint8_t, intra4x4_pred_mode_top)[4]; VP56mv mv; VP56mv bmv[16]; } VP8Macroblock; @@ -118,7 +119,7 @@ typedef struct VP8ThreadData { int thread_nr; #if HAVE_THREADS pthread_mutex_t lock; - pthread_cond_t cond; + pthread_cond_t cond; #endif int thread_mb_pos; // (mb_y << 16) | (mb_x & 0xFFFF) int wait_mb_pos; // What the current thread is waiting on. @@ -205,7 +206,7 @@ typedef struct VP8Context { * [7] - split mv * i16x16 modes never have any adjustment */ - int8_t mode[VP8_MVMODE_SPLIT+1]; + int8_t mode[VP8_MVMODE_SPLIT + 1]; /** * filter strength adjustment for macroblocks that reference: @@ -217,7 +218,7 @@ typedef struct VP8Context { int8_t ref[4]; } lf_delta; - uint8_t (*top_border)[16+8+8]; + uint8_t (*top_border)[16 + 8 + 8]; uint8_t (*top_nnz)[9]; VP56RangeCoder c; ///< header context, includes mb modes and motion vectors @@ -236,8 +237,9 @@ typedef struct VP8Context { uint8_t golden; uint8_t pred16x16[4]; uint8_t pred8x8c[3]; - uint8_t token[4][16][3][NUM_DCT_TOKENS-1]; + uint8_t token[4][16][3][NUM_DCT_TOKENS - 1]; uint8_t mvc[2][19]; + uint8_t scan[16]; } prob[2]; VP8Macroblock *macroblocks_base; @@ -271,6 +273,31 @@ typedef struct VP8Context { * 1 -> Macroblocks for entire frame alloced (sliced thread). */ int mb_layout; + + void (*decode_mb_row_no_filter)(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr); + void (*filter_mb_row)(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr); + + int vp7; + + /** + * Fade bit present in bitstream (VP7) + */ + int fade_present; + + /** + * Interframe DC prediction (VP7) + * [0] VP56_FRAME_PREVIOUS + * [1] VP56_FRAME_GOLDEN + */ + uint16_t inter_dc_pred[2][2]; + + /** + * Macroblock features (VP7) + */ + uint8_t feature_enabled[4]; + uint8_t feature_present_prob[4]; + uint8_t feature_index_prob[4][3]; + uint8_t feature_value[4][4]; } VP8Context; int ff_vp8_decode_init(AVCodecContext *avctx); diff --git a/libavcodec/vp8_parser.c b/libavcodec/vp8_parser.c index 096961fec..afc7f991e 100644 --- a/libavcodec/vp8_parser.c +++ b/libavcodec/vp8_parser.c @@ -21,18 +21,19 @@ #include "parser.h" static int parse(AVCodecParserContext *s, - AVCodecContext *avctx, - const uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size) + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) { - s->pict_type= (buf[0]&0x01) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; + s->pict_type = (buf[0] & 0x01) ? AV_PICTURE_TYPE_P + : AV_PICTURE_TYPE_I; - *poutbuf = buf; + *poutbuf = buf; *poutbuf_size = buf_size; return buf_size; } AVCodecParser ff_vp8_parser = { - .codec_ids = { AV_CODEC_ID_VP8 }, - .parser_parse = parse, + .codec_ids = { AV_CODEC_ID_VP8 }, + .parser_parse = parse, }; diff --git a/libavcodec/vp8data.h b/libavcodec/vp8data.h index 0ea24d7ed..f9dbf56fe 100644 --- a/libavcodec/vp8data.h +++ b/libavcodec/vp8data.h @@ -30,28 +30,89 @@ #include "vp8.h" #include "h264pred.h" -static const uint8_t vp8_pred4x4_mode[] = -{ +static const uint8_t vp7_pred4x4_mode[] = { + [DC_PRED8x8] = DC_PRED, + [VERT_PRED8x8] = TM_VP8_PRED, + [HOR_PRED8x8] = TM_VP8_PRED, + [PLANE_PRED8x8] = TM_VP8_PRED, +}; + +static const uint8_t vp8_pred4x4_mode[] = { [DC_PRED8x8] = DC_PRED, [VERT_PRED8x8] = VERT_PRED, [HOR_PRED8x8] = HOR_PRED, [PLANE_PRED8x8] = TM_VP8_PRED, }; -static const int8_t vp8_pred16x16_tree_intra[4][2] = -{ - { -MODE_I4x4, 1 }, // '0' - { 2, 3 }, - { -DC_PRED8x8, -VERT_PRED8x8 }, // '100', '101' - { -HOR_PRED8x8, -PLANE_PRED8x8 }, // '110', '111' +static const int8_t vp8_pred16x16_tree_intra[4][2] = { + { -MODE_I4x4, 1 }, // '0' + { 2, 3 }, + { -DC_PRED8x8, -VERT_PRED8x8 }, // '100', '101' + { -HOR_PRED8x8, -PLANE_PRED8x8 }, // '110', '111' }; -static const int8_t vp8_pred16x16_tree_inter[4][2] = -{ - { -DC_PRED8x8, 1 }, // '0' - { 2, 3 }, - { -VERT_PRED8x8, -HOR_PRED8x8 }, // '100', '101' - { -PLANE_PRED8x8, -MODE_I4x4 }, // '110', '111' +static const int8_t vp8_pred16x16_tree_inter[4][2] = { + { -DC_PRED8x8, 1 }, // '0' + { 2, 3 }, + { -VERT_PRED8x8, -HOR_PRED8x8 }, // '100', '101' + { -PLANE_PRED8x8, -MODE_I4x4 }, // '110', '111' +}; + +typedef struct VP7MVPred { + int8_t yoffset; + int8_t xoffset; + uint8_t subblock; + uint8_t score; +} VP7MVPred; + +#define VP7_MV_PRED_COUNT 12 +static const VP7MVPred vp7_mv_pred[VP7_MV_PRED_COUNT] = { + { -1, 0, 12, 8 }, + { 0, -1, 3, 8 }, + { -1, -1, 15, 2 }, + { -1, 1, 12, 2 }, + { -2, 0, 12, 2 }, + { 0, -2, 3, 2 }, + { -1, -2, 15, 1 }, + { -2, -1, 15, 1 }, + { -2, 1, 12, 1 }, + { -1, 2, 12, 1 }, + { -2, -2, 15, 1 }, + { -2, 2, 12, 1 }, +}; + +static const int vp7_mode_contexts[31][4] = { + { 3, 3, 1, 246 }, + { 7, 89, 66, 239 }, + { 10, 90, 78, 238 }, + { 14, 118, 95, 241 }, + { 14, 123, 106, 238 }, + { 20, 140, 109, 240 }, + { 13, 155, 103, 238 }, + { 21, 158, 99, 240 }, + { 27, 82, 108, 232 }, + { 19, 99, 123, 217 }, + { 45, 139, 148, 236 }, + { 50, 117, 144, 235 }, + { 57, 128, 164, 238 }, + { 69, 139, 171, 239 }, + { 74, 154, 179, 238 }, + { 112, 165, 186, 242 }, + { 98, 143, 185, 245 }, + { 105, 153, 190, 250 }, + { 124, 167, 192, 245 }, + { 131, 186, 203, 246 }, + { 59, 184, 222, 224 }, + { 148, 215, 214, 213 }, + { 137, 211, 210, 219 }, + { 190, 227, 128, 228 }, + { 183, 228, 128, 228 }, + { 194, 234, 128, 228 }, + { 202, 236, 128, 228 }, + { 205, 240, 128, 228 }, + { 205, 244, 128, 228 }, + { 225, 246, 128, 228 }, + { 233, 251, 128, 228 }, }; static const int vp8_mode_contexts[6][4] = { @@ -64,26 +125,30 @@ static const int vp8_mode_contexts[6][4] = { }; static const uint8_t vp8_mbsplits[5][16] = { - { 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 1, 1, 0, 0, 1, 1, - 0, 0, 1, 1, 0, 0, 1, 1 }, - { 0, 0, 1, 1, 0, 0, 1, 1, - 2, 2, 3, 3, 2, 2, 3, 3 }, - { 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15 }, - { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 } + { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, + { 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; static const uint8_t vp8_mbfirstidx[4][16] = { - { 0, 8 }, { 0, 2 }, { 0, 2, 8, 10 }, - { 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15 } + { 0, 8 }, + { 0, 2 }, + { 0, 2, 8, 10 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } }; -static const uint8_t vp8_mbsplit_count[4] = { 2, 2, 4, 16 }; -static const uint8_t vp8_mbsplit_prob[3] = { 110, 111, 150 }; +static const uint8_t vp8_mbsplit_count[4] = { + 2, 2, 4, 16 +}; +static const uint8_t vp8_mbsplit_prob[3] = { + 110, 111, 150 +}; + +static const uint8_t vp7_submv_prob[3] = { + 180, 162, 25 +}; static const uint8_t vp8_submv_prob[5][3] = { { 147, 136, 18 }, @@ -93,39 +158,42 @@ static const uint8_t vp8_submv_prob[5][3] = { { 208, 1, 1 } }; -static const uint8_t vp8_pred16x16_prob_intra[4] = { 145, 156, 163, 128 }; -static const uint8_t vp8_pred16x16_prob_inter[4] = { 112, 86, 140, 37 }; - -static const int8_t vp8_pred4x4_tree[9][2] = -{ - { -DC_PRED, 1 }, // '0' - { -TM_VP8_PRED, 2 }, // '10' - { -VERT_PRED, 3 }, // '110' - { 4, 6 }, - { -HOR_PRED, 5 }, // '11100' - { -DIAG_DOWN_RIGHT_PRED, -VERT_RIGHT_PRED }, // '111010', '111011' - { -DIAG_DOWN_LEFT_PRED, 7 }, // '11110' - { -VERT_LEFT_PRED, 8 }, // '111110' - { -HOR_DOWN_PRED, -HOR_UP_PRED }, // '1111110', '1111111' +static const uint8_t vp8_pred16x16_prob_intra[4] = { + 145, 156, 163, 128 +}; +static const uint8_t vp8_pred16x16_prob_inter[4] = { + 112, 86, 140, 37 }; -static const int8_t vp8_pred8x8c_tree[3][2] = -{ - { -DC_PRED8x8, 1 }, // '0' - { -VERT_PRED8x8, 2 }, // '10 - { -HOR_PRED8x8, -PLANE_PRED8x8 }, // '110', '111' +static const int8_t vp8_pred4x4_tree[9][2] = { + { -DC_PRED, 1 }, // '0' + { -TM_VP8_PRED, 2 }, // '10' + { -VERT_PRED, 3 }, // '110' + { 4, 6 }, + { -HOR_PRED, 5 }, // '11100' + { -DIAG_DOWN_RIGHT_PRED, -VERT_RIGHT_PRED }, // '111010', '111011' + { -DIAG_DOWN_LEFT_PRED, 7 }, // '11110' + { -VERT_LEFT_PRED, 8 }, // '111110' + { -HOR_DOWN_PRED, -HOR_UP_PRED }, // '1111110', '1111111' }; -static const uint8_t vp8_pred8x8c_prob_intra[3] = { 142, 114, 183 }; -static const uint8_t vp8_pred8x8c_prob_inter[3] = { 162, 101, 204 }; +static const int8_t vp8_pred8x8c_tree[3][2] = { + { -DC_PRED8x8, 1 }, // '0' + { -VERT_PRED8x8, 2 }, // '10 + { -HOR_PRED8x8, -PLANE_PRED8x8 }, // '110', '111' +}; -static const uint8_t vp8_pred4x4_prob_inter[9] = -{ +static const uint8_t vp8_pred8x8c_prob_intra[3] = { + 142, 114, 183 +}; +static const uint8_t vp8_pred8x8c_prob_inter[3] = { + 162, 101, 204 +}; +static const uint8_t vp8_pred4x4_prob_inter[9] = { 120, 90, 79, 133, 87, 85, 80, 111, 151 }; -static const uint8_t vp8_pred4x4_prob_intra[10][10][9] = -{ +static const uint8_t vp8_pred4x4_prob_intra[10][10][9] = { { { 39, 53, 200, 87, 26, 21, 43, 232, 171 }, { 56, 34, 51, 104, 114, 102, 29, 93, 77 }, @@ -248,50 +316,57 @@ static const uint8_t vp8_pred4x4_prob_intra[10][10][9] = }, }; -static const int8_t vp8_segmentid_tree[][2] = -{ - { 1, 2 }, - { -0, -1 }, // '00', '01' - { -2, -3 }, // '10', '11' +static const int8_t vp8_segmentid_tree[][2] = { + { 1, 2 }, + { -0, -1 }, // '00', '01' + { -2, -3 }, // '10', '11' }; -static const uint8_t vp8_coeff_band[16] = -{ +static const uint8_t vp8_coeff_band[16] = { 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7 }; /* Inverse of vp8_coeff_band: mappings of bands to coefficient indexes. * Each list is -1-terminated. */ -static const int8_t vp8_coeff_band_indexes[8][10] = -{ - {0, -1}, - {1, -1}, - {2, -1}, - {3, -1}, - {5, -1}, - {6, -1}, - {4, 7, 8, 9, 10, 11, 12, 13, 14, -1}, - {15, -1} +static const int8_t vp8_coeff_band_indexes[8][10] = { + { 0, -1 }, + { 1, -1 }, + { 2, -1 }, + { 3, -1 }, + { 5, -1 }, + { 6, -1 }, + { 4, 7, 8, 9, 10, 11, 12, 13, 14, -1 }, + { 15, -1 } }; -static const uint8_t vp8_dct_cat1_prob[] = { 159, 0 }; -static const uint8_t vp8_dct_cat2_prob[] = { 165, 145, 0 }; -static const uint8_t vp8_dct_cat3_prob[] = { 173, 148, 140, 0 }; -static const uint8_t vp8_dct_cat4_prob[] = { 176, 155, 140, 135, 0 }; -static const uint8_t vp8_dct_cat5_prob[] = { 180, 157, 141, 134, 130, 0 }; -static const uint8_t vp8_dct_cat6_prob[] = { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 }; +static const uint8_t vp8_dct_cat1_prob[] = { + 159, 0 +}; +static const uint8_t vp8_dct_cat2_prob[] = { + 165, 145, 0 +}; +static const uint8_t vp8_dct_cat3_prob[] = { + 173, 148, 140, 0 +}; +static const uint8_t vp8_dct_cat4_prob[] = { + 176, 155, 140, 135, 0 +}; +static const uint8_t vp8_dct_cat5_prob[] = { + 180, 157, 141, 134, 130, 0 +}; +static const uint8_t vp8_dct_cat6_prob[] = { + 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 +}; // only used for cat3 and above; cat 1 and 2 are referenced directly -const uint8_t * const ff_vp8_dct_cat_prob[] = -{ +const uint8_t *const ff_vp8_dct_cat_prob[] = { vp8_dct_cat3_prob, vp8_dct_cat4_prob, vp8_dct_cat5_prob, vp8_dct_cat6_prob, }; -static const uint8_t vp8_token_default_probs[4][8][3][NUM_DCT_TOKENS-1] = -{ +static const uint8_t vp8_token_default_probs[4][8][3][NUM_DCT_TOKENS - 1] = { { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, @@ -462,8 +537,7 @@ static const uint8_t vp8_token_default_probs[4][8][3][NUM_DCT_TOKENS-1] = }, }; -static const uint8_t vp8_token_update_probs[4][8][3][NUM_DCT_TOKENS-1] = -{ +static const uint8_t vp8_token_update_probs[4][8][3][NUM_DCT_TOKENS - 1] = { { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, @@ -636,14 +710,13 @@ 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, + 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] = -{ +static const uint8_t vp8_dc_qlookup[VP8_MAX_QUANT + 1] = { 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 17, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, @@ -654,8 +727,7 @@ static const uint8_t vp8_dc_qlookup[VP8_MAX_QUANT+1] = 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 143, 145, 148, 151, 154, 157, }; -static const uint16_t vp8_ac_qlookup[VP8_MAX_QUANT+1] = -{ +static const uint16_t vp8_ac_qlookup[VP8_MAX_QUANT + 1] = { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, @@ -670,11 +742,22 @@ static const uint8_t vp8_mv_update_prob[2][19] = { { 237, 246, 253, 253, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 250, 250, 252, 254, 254 }, + 254, 254, 254, 254, 254, 250, 250, 252, /* VP8 only: */ 254, 254 }, { 231, 243, 245, 253, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 251, 251, 254, 254, 254 } + 254, 254, 254, 254, 254, 251, 251, 254, /* VP8 only: */ 254, 254 } +}; + +static const uint8_t vp7_mv_default_prob[2][17] = { + { 162, + 128, + 225, 146, 172, 147, 214, 39, 156, + 247, 210, 135, 68, 138, 220, 239, 246 }, + { 164, + 128, + 204, 170, 119, 235, 140, 230, 228, + 244, 184, 201, 44, 173, 221, 239, 253 } }; static const uint8_t vp8_mv_default_prob[2][19] = { @@ -688,4 +771,68 @@ static const uint8_t vp8_mv_default_prob[2][19] = { 128, 130, 130, 74, 148, 180, 203, 236, 254, 254 } }; +static const uint8_t vp7_feature_value_size[2][4] = { + { 7, 6, 0, 8 }, + { 7, 6, 0, 5 }, +}; + +static const int8_t vp7_feature_index_tree[4][2] = +{ + { 1, 2 }, + { -0, -1 }, // '00', '01' + { -2, -3 }, // '10', '11' +}; + +static const uint16_t vp7_ydc_qlookup[] = { + 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 39, 39, 40, 41, + 41, 42, 43, 43, 44, 45, 45, 46, 47, 48, 48, 49, 50, 51, 52, + 53, 53, 54, 56, 57, 58, 59, 60, 62, 63, 65, 66, 68, 70, 72, + 74, 76, 79, 81, 84, 87, 90, 93, 96, 100, 104, 108, 112, 116, 121, + 126, 131, 136, 142, 148, 154, 160, 167, 174, 182, 189, 198, 206, 215, 224, + 234, 244, 254, 265, 277, 288, 301, 313, 327, 340, 355, 370, 385, 401, 417, + 434, 452, 470, 489, 509, 529, 550, 572, +}; + +static const uint16_t vp7_yac_qlookup[] = { + 4, 4, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 15, + 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, + 37, 38, 40, 41, 42, 44, 45, 46, 48, 49, 50, 51, 53, 54, + 55, 56, 57, 58, 59, 61, 62, 63, 64, 65, 67, 68, 69, 70, + 72, 73, 75, 76, 78, 80, 82, 84, 86, 88, 91, 93, 96, 99, + 102, 105, 109, 112, 116, 121, 125, 130, 135, 140, 146, 152, 158, 165, + 172, 180, 188, 196, 205, 214, 224, 234, 245, 256, 268, 281, 294, 308, + 322, 337, 353, 369, 386, 404, 423, 443, 463, 484, 506, 529, 553, 578, + 604, 631, 659, 688, 718, 749, 781, 814, 849, 885, 922, 960, 1000, 1041, + 1083, 1127, +}; + +static const uint16_t vp7_y2dc_qlookup[] = { + 7, 9, 11, 13, 15, 17, 19, 21, 23, 26, 28, 30, 33, 35, + 37, 39, 42, 44, 46, 48, 51, 53, 55, 57, 59, 61, 63, 65, + 67, 69, 70, 72, 74, 75, 77, 78, 80, 81, 83, 84, 85, 87, + 88, 89, 90, 92, 93, 94, 95, 96, 97, 99, 100, 101, 102, 104, + 105, 106, 108, 109, 111, 113, 114, 116, 118, 120, 123, 125, 128, 131, + 134, 137, 140, 144, 148, 152, 156, 161, 166, 171, 176, 182, 188, 195, + 202, 209, 217, 225, 234, 243, 253, 263, 274, 285, 297, 309, 322, 336, + 350, 365, 381, 397, 414, 432, 450, 470, 490, 511, 533, 556, 579, 604, + 630, 656, 684, 713, 742, 773, 805, 838, 873, 908, 945, 983, 1022, 1063, + 1105, 1148, +}; + +static const uint16_t vp7_y2ac_qlookup[] = { + 7, 9, 11, 13, 16, 18, 21, 24, 26, 29, 32, 35, + 38, 41, 43, 46, 49, 52, 55, 58, 61, 64, 66, 69, + 72, 74, 77, 79, 82, 84, 86, 88, 91, 93, 95, 97, + 98, 100, 102, 104, 105, 107, 109, 110, 112, 113, 115, 116, + 117, 119, 120, 122, 123, 125, 127, 128, 130, 132, 134, 136, + 138, 141, 143, 146, 149, 152, 155, 158, 162, 166, 171, 175, + 180, 185, 191, 197, 204, 210, 218, 226, 234, 243, 252, 262, + 273, 284, 295, 308, 321, 335, 350, 365, 381, 398, 416, 435, + 455, 476, 497, 520, 544, 569, 595, 622, 650, 680, 711, 743, + 776, 811, 848, 885, 925, 965, 1008, 1052, 1097, 1144, 1193, 1244, + 1297, 1351, 1407, 1466, 1526, 1588, 1652, 1719, +}; + #endif /* AVCODEC_VP8DATA_H */ diff --git a/libavcodec/vp8dsp.c b/libavcodec/vp8dsp.c index 00b4118b5..e1a91bb8c 100644 --- a/libavcodec/vp8dsp.c +++ b/libavcodec/vp8dsp.c @@ -25,25 +25,29 @@ * VP8 compatible video decoder */ -#include "dsputil.h" -#include "vp8dsp.h" #include "libavutil/common.h" +#include "libavutil/intreadwrite.h" -#define MK_IDCT_DC_ADD4_C(name) \ -static void name ## _idct_dc_add4uv_c(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride)\ -{\ - name ## _idct_dc_add_c(dst+stride*0+0, block[0], stride);\ - name ## _idct_dc_add_c(dst+stride*0+4, block[1], stride);\ - name ## _idct_dc_add_c(dst+stride*4+0, block[2], stride);\ - name ## _idct_dc_add_c(dst+stride*4+4, block[3], stride);\ -}\ -\ -static void name ## _idct_dc_add4y_c(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride)\ -{\ - name ## _idct_dc_add_c(dst+ 0, block[0], stride);\ - name ## _idct_dc_add_c(dst+ 4, block[1], stride);\ - name ## _idct_dc_add_c(dst+ 8, block[2], stride);\ - name ## _idct_dc_add_c(dst+12, block[3], stride);\ +#include "mathops.h" +#include "vp8dsp.h" + +#define MK_IDCT_DC_ADD4_C(name) \ +static void name ## _idct_dc_add4uv_c(uint8_t *dst, int16_t block[4][16], \ + ptrdiff_t stride) \ +{ \ + name ## _idct_dc_add_c(dst + stride * 0 + 0, block[0], stride); \ + name ## _idct_dc_add_c(dst + stride * 0 + 4, block[1], stride); \ + name ## _idct_dc_add_c(dst + stride * 4 + 0, block[2], stride); \ + name ## _idct_dc_add_c(dst + stride * 4 + 4, block[3], stride); \ +} \ + \ +static void name ## _idct_dc_add4y_c(uint8_t *dst, int16_t block[4][16], \ + ptrdiff_t stride) \ +{ \ + name ## _idct_dc_add_c(dst + 0, block[0], stride); \ + name ## _idct_dc_add_c(dst + 4, block[1], stride); \ + name ## _idct_dc_add_c(dst + 8, block[2], stride); \ + name ## _idct_dc_add_c(dst + 12, block[3], stride); \ } #if CONFIG_VP7_DECODER @@ -53,14 +57,14 @@ static void vp7_luma_dc_wht_c(int16_t block[4][4][16], int16_t dc[16]) int16_t tmp[16]; for (i = 0; i < 4; i++) { - a1 = (dc[i*4+0] + dc[i*4+2]) * 23170; - b1 = (dc[i*4+0] - dc[i*4+2]) * 23170; - c1 = dc[i*4+1] * 12540 - dc[i*4+3] * 30274; - d1 = dc[i*4+1] * 30274 + dc[i*4+3] * 12540; - tmp[i*4+0] = (a1 + d1) >> 14; - tmp[i*4+3] = (a1 - d1) >> 14; - tmp[i*4+1] = (b1 + c1) >> 14; - tmp[i*4+2] = (b1 - c1) >> 14; + a1 = (dc[i * 4 + 0] + dc[i * 4 + 2]) * 23170; + b1 = (dc[i * 4 + 0] - dc[i * 4 + 2]) * 23170; + c1 = dc[i * 4 + 1] * 12540 - dc[i * 4 + 3] * 30274; + d1 = dc[i * 4 + 1] * 30274 + dc[i * 4 + 3] * 12540; + tmp[i * 4 + 0] = (a1 + d1) >> 14; + tmp[i * 4 + 3] = (a1 - d1) >> 14; + tmp[i * 4 + 1] = (b1 + c1) >> 14; + tmp[i * 4 + 2] = (b1 - c1) >> 14; } for (i = 0; i < 4; i++) { @@ -68,7 +72,7 @@ static void vp7_luma_dc_wht_c(int16_t block[4][4][16], int16_t dc[16]) b1 = (tmp[i + 0] - tmp[i + 8]) * 23170; c1 = tmp[i + 4] * 12540 - tmp[i + 12] * 30274; d1 = tmp[i + 4] * 30274 + tmp[i + 12] * 12540; - AV_ZERO64(dc + i*4); + AV_ZERO64(dc + i * 4); block[0][i][0] = (a1 + d1 + 0x20000) >> 18; block[3][i][0] = (a1 - d1 + 0x20000) >> 18; block[1][i][0] = (b1 + c1 + 0x20000) >> 18; @@ -95,15 +99,15 @@ static void vp7_idct_add_c(uint8_t *dst, int16_t block[16], ptrdiff_t stride) int16_t tmp[16]; for (i = 0; i < 4; i++) { - a1 = (block[i*4+0] + block[i*4+2]) * 23170; - b1 = (block[i*4+0] - block[i*4+2]) * 23170; - c1 = block[i*4+1] * 12540 - block[i*4+3] * 30274; - d1 = block[i*4+1] * 30274 + block[i*4+3] * 12540; - AV_ZERO64(block + i*4); - tmp[i*4+0] = (a1 + d1) >> 14; - tmp[i*4+3] = (a1 - d1) >> 14; - tmp[i*4+1] = (b1 + c1) >> 14; - tmp[i*4+2] = (b1 - c1) >> 14; + a1 = (block[i * 4 + 0] + block[i * 4 + 2]) * 23170; + b1 = (block[i * 4 + 0] - block[i * 4 + 2]) * 23170; + c1 = block[i * 4 + 1] * 12540 - block[i * 4 + 3] * 30274; + d1 = block[i * 4 + 1] * 30274 + block[i * 4 + 3] * 12540; + AV_ZERO64(block + i * 4); + tmp[i * 4 + 0] = (a1 + d1) >> 14; + tmp[i * 4 + 3] = (a1 - d1) >> 14; + tmp[i * 4 + 1] = (b1 + c1) >> 14; + tmp[i * 4 + 2] = (b1 - c1) >> 14; } for (i = 0; i < 4; i++) { @@ -111,10 +115,14 @@ static void vp7_idct_add_c(uint8_t *dst, int16_t block[16], ptrdiff_t stride) b1 = (tmp[i + 0] - tmp[i + 8]) * 23170; c1 = tmp[i + 4] * 12540 - tmp[i + 12] * 30274; d1 = tmp[i + 4] * 30274 + tmp[i + 12] * 12540; - dst[0*stride+i] = av_clip_uint8(dst[0*stride+i] + ((a1 + d1 + 0x20000) >> 18)); - dst[3*stride+i] = av_clip_uint8(dst[3*stride+i] + ((a1 - d1 + 0x20000) >> 18)); - dst[1*stride+i] = av_clip_uint8(dst[1*stride+i] + ((b1 + c1 + 0x20000) >> 18)); - dst[2*stride+i] = av_clip_uint8(dst[2*stride+i] + ((b1 - c1 + 0x20000) >> 18)); + dst[0 * stride + i] = av_clip_uint8(dst[0 * stride + i] + + ((a1 + d1 + 0x20000) >> 18)); + dst[3 * stride + i] = av_clip_uint8(dst[3 * stride + i] + + ((a1 - d1 + 0x20000) >> 18)); + dst[1 * stride + i] = av_clip_uint8(dst[1 * stride + i] + + ((b1 + c1 + 0x20000) >> 18)); + dst[2 * stride + i] = av_clip_uint8(dst[2 * stride + i] + + ((b1 - c1 + 0x20000) >> 18)); } } @@ -128,12 +136,12 @@ static void vp7_idct_dc_add_c(uint8_t *dst, int16_t block[16], ptrdiff_t stride) dst[1] = av_clip_uint8(dst[1] + dc); dst[2] = av_clip_uint8(dst[2] + dc); dst[3] = av_clip_uint8(dst[3] + dc); - dst += stride; + dst += stride; } } MK_IDCT_DC_ADD4_C(vp7) -#endif +#endif /* CONFIG_VP7_DECODER */ // TODO: Maybe add dequant #if CONFIG_VP8_DECODER @@ -142,23 +150,23 @@ static void vp8_luma_dc_wht_c(int16_t block[4][4][16], int16_t dc[16]) int i, t0, t1, t2, t3; for (i = 0; i < 4; i++) { - t0 = dc[0*4+i] + dc[3*4+i]; - t1 = dc[1*4+i] + dc[2*4+i]; - t2 = dc[1*4+i] - dc[2*4+i]; - t3 = dc[0*4+i] - dc[3*4+i]; + t0 = dc[0 * 4 + i] + dc[3 * 4 + i]; + t1 = dc[1 * 4 + i] + dc[2 * 4 + i]; + t2 = dc[1 * 4 + i] - dc[2 * 4 + i]; + t3 = dc[0 * 4 + i] - dc[3 * 4 + i]; - dc[0*4+i] = t0 + t1; - dc[1*4+i] = t3 + t2; - dc[2*4+i] = t0 - t1; - dc[3*4+i] = t3 - t2; + dc[0 * 4 + i] = t0 + t1; + dc[1 * 4 + i] = t3 + t2; + dc[2 * 4 + i] = t0 - t1; + dc[3 * 4 + i] = t3 - t2; } for (i = 0; i < 4; i++) { - t0 = dc[i*4+0] + dc[i*4+3] + 3; // rounding - t1 = dc[i*4+1] + dc[i*4+2]; - t2 = dc[i*4+1] - dc[i*4+2]; - t3 = dc[i*4+0] - dc[i*4+3] + 3; // rounding - AV_ZERO64(dc + i*4); + t0 = dc[i * 4 + 0] + dc[i * 4 + 3] + 3; // rounding + t1 = dc[i * 4 + 1] + dc[i * 4 + 2]; + t2 = dc[i * 4 + 1] - dc[i * 4 + 2]; + t3 = dc[i * 4 + 0] - dc[i * 4 + 3] + 3; // rounding + AV_ZERO64(dc + i * 4); block[i][0][0] = (t0 + t1) >> 3; block[i][1][0] = (t3 + t2) >> 3; @@ -180,8 +188,8 @@ static void vp8_luma_dc_wht_dc_c(int16_t block[4][4][16], int16_t dc[16]) } } -#define MUL_20091(a) ((((a)*20091) >> 16) + (a)) -#define MUL_35468(a) (((a)*35468) >> 16) +#define MUL_20091(a) ((((a) * 20091) >> 16) + (a)) +#define MUL_35468(a) (((a) * 35468) >> 16) static void vp8_idct_add_c(uint8_t *dst, int16_t block[16], ptrdiff_t stride) { @@ -189,32 +197,32 @@ static void vp8_idct_add_c(uint8_t *dst, int16_t block[16], ptrdiff_t stride) int16_t tmp[16]; for (i = 0; i < 4; i++) { - t0 = block[0*4+i] + block[2*4+i]; - t1 = block[0*4+i] - block[2*4+i]; - t2 = MUL_35468(block[1*4+i]) - MUL_20091(block[3*4+i]); - t3 = MUL_20091(block[1*4+i]) + MUL_35468(block[3*4+i]); - block[0*4+i] = 0; - block[1*4+i] = 0; - block[2*4+i] = 0; - block[3*4+i] = 0; + t0 = block[0 * 4 + i] + block[2 * 4 + i]; + t1 = block[0 * 4 + i] - block[2 * 4 + i]; + t2 = MUL_35468(block[1 * 4 + i]) - MUL_20091(block[3 * 4 + i]); + t3 = MUL_20091(block[1 * 4 + i]) + MUL_35468(block[3 * 4 + i]); + block[0 * 4 + i] = 0; + block[1 * 4 + i] = 0; + block[2 * 4 + i] = 0; + block[3 * 4 + i] = 0; - tmp[i*4+0] = t0 + t3; - tmp[i*4+1] = t1 + t2; - tmp[i*4+2] = t1 - t2; - tmp[i*4+3] = t0 - t3; + tmp[i * 4 + 0] = t0 + t3; + tmp[i * 4 + 1] = t1 + t2; + tmp[i * 4 + 2] = t1 - t2; + tmp[i * 4 + 3] = t0 - t3; } for (i = 0; i < 4; i++) { - t0 = tmp[0*4+i] + tmp[2*4+i]; - t1 = tmp[0*4+i] - tmp[2*4+i]; - t2 = MUL_35468(tmp[1*4+i]) - MUL_20091(tmp[3*4+i]); - t3 = MUL_20091(tmp[1*4+i]) + MUL_35468(tmp[3*4+i]); + t0 = tmp[0 * 4 + i] + tmp[2 * 4 + i]; + t1 = tmp[0 * 4 + i] - tmp[2 * 4 + i]; + t2 = MUL_35468(tmp[1 * 4 + i]) - MUL_20091(tmp[3 * 4 + i]); + t3 = MUL_20091(tmp[1 * 4 + i]) + MUL_35468(tmp[3 * 4 + i]); dst[0] = av_clip_uint8(dst[0] + ((t0 + t3 + 4) >> 3)); dst[1] = av_clip_uint8(dst[1] + ((t1 + t2 + 4) >> 3)); dst[2] = av_clip_uint8(dst[2] + ((t1 - t2 + 4) >> 3)); dst[3] = av_clip_uint8(dst[3] + ((t0 - t3 + 4) >> 3)); - dst += stride; + dst += stride; } } @@ -228,33 +236,34 @@ static void vp8_idct_dc_add_c(uint8_t *dst, int16_t block[16], ptrdiff_t stride) dst[1] = av_clip_uint8(dst[1] + dc); dst[2] = av_clip_uint8(dst[2] + dc); dst[3] = av_clip_uint8(dst[3] + dc); - dst += stride; + dst += stride; } } MK_IDCT_DC_ADD4_C(vp8) -#endif +#endif /* CONFIG_VP8_DECODER */ // because I like only having two parameters to pass functions... -#define LOAD_PIXELS\ - int av_unused p3 = p[-4*stride];\ - int av_unused p2 = p[-3*stride];\ - int av_unused p1 = p[-2*stride];\ - int av_unused p0 = p[-1*stride];\ - int av_unused q0 = p[ 0*stride];\ - int av_unused q1 = p[ 1*stride];\ - int av_unused q2 = p[ 2*stride];\ - int av_unused q3 = p[ 3*stride]; +#define LOAD_PIXELS \ + int av_unused p3 = p[-4 * stride]; \ + int av_unused p2 = p[-3 * stride]; \ + int av_unused p1 = p[-2 * stride]; \ + int av_unused p0 = p[-1 * stride]; \ + int av_unused q0 = p[ 0 * stride]; \ + int av_unused q1 = p[ 1 * stride]; \ + int av_unused q2 = p[ 2 * stride]; \ + int av_unused q3 = p[ 3 * stride]; -#define clip_int8(n) (cm[n+0x80]-0x80) +#define clip_int8(n) (cm[(n) + 0x80] - 0x80) -static av_always_inline void filter_common(uint8_t *p, ptrdiff_t stride, int is4tap, int vpn) +static av_always_inline void filter_common(uint8_t *p, ptrdiff_t stride, + int is4tap, int is_vp7) { LOAD_PIXELS int a, f1, f2; - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; - a = 3*(q0 - p0); + a = 3 * (q0 - p0); if (is4tap) a += clip_int8(p1 - q1); @@ -263,49 +272,66 @@ static av_always_inline void filter_common(uint8_t *p, ptrdiff_t stride, int is4 // We deviate from the spec here with c(a+3) >> 3 // since that's what libvpx does. - f1 = FFMIN(a+4, 127) >> 3; + f1 = FFMIN(a + 4, 127) >> 3; - if (vpn == 7) + if (is_vp7) f2 = f1 - ((a & 7) == 4); else - f2 = FFMIN(a+3, 127) >> 3; + f2 = FFMIN(a + 3, 127) >> 3; // Despite what the spec says, we do need to clamp here to // be bitexact with libvpx. - p[-1*stride] = cm[p0 + f2]; - p[ 0*stride] = cm[q0 - f1]; + p[-1 * stride] = cm[p0 + f2]; + p[ 0 * stride] = cm[q0 - f1]; // only used for _inner on blocks without high edge variance if (!is4tap) { - a = (f1+1)>>1; - p[-2*stride] = cm[p1 + a]; - p[ 1*stride] = cm[q1 - a]; + a = (f1 + 1) >> 1; + p[-2 * stride] = cm[p1 + a]; + p[ 1 * stride] = cm[q1 - a]; } } -static av_always_inline int vp7_simple_limit(uint8_t *p, ptrdiff_t stride, int flim) +static av_always_inline void vp7_filter_common(uint8_t *p, ptrdiff_t stride, + int is4tap) { - LOAD_PIXELS - return FFABS(p0-q0) <= flim; + filter_common(p, stride, is4tap, IS_VP7); } -static av_always_inline int vp8_simple_limit(uint8_t *p, ptrdiff_t stride, int flim) +static av_always_inline void vp8_filter_common(uint8_t *p, ptrdiff_t stride, + int is4tap) +{ + filter_common(p, stride, is4tap, IS_VP8); +} + +static av_always_inline int vp7_simple_limit(uint8_t *p, ptrdiff_t stride, + int flim) { LOAD_PIXELS - return 2*FFABS(p0-q0) + (FFABS(p1-q1) >> 1) <= flim; + return FFABS(p0 - q0) <= flim; +} + +static av_always_inline int vp8_simple_limit(uint8_t *p, ptrdiff_t stride, + int flim) +{ + LOAD_PIXELS + return 2 * FFABS(p0 - q0) + (FFABS(p1 - q1) >> 1) <= flim; } /** * E - limit at the macroblock edge * I - limit for interior difference */ -#define NORMAL_LIMIT(vpn) \ -static av_always_inline int vp ## vpn ## _normal_limit(uint8_t *p, ptrdiff_t stride, int E, int I)\ -{\ - LOAD_PIXELS\ - return vp ## vpn ## _simple_limit(p, stride, E)\ - && FFABS(p3-p2) <= I && FFABS(p2-p1) <= I && FFABS(p1-p0) <= I\ - && FFABS(q3-q2) <= I && FFABS(q2-q1) <= I && FFABS(q1-q0) <= I;\ +#define NORMAL_LIMIT(vpn) \ +static av_always_inline int vp ## vpn ## _normal_limit(uint8_t *p, \ + ptrdiff_t stride, \ + int E, int I) \ +{ \ + LOAD_PIXELS \ + return vp ## vpn ## _simple_limit(p, stride, E) && \ + FFABS(p3 - p2) <= I && FFABS(p2 - p1) <= I && \ + FFABS(p1 - p0) <= I && FFABS(q3 - q2) <= I && \ + FFABS(q2 - q1) <= I && FFABS(q1 - q0) <= I; \ } NORMAL_LIMIT(7) @@ -315,195 +341,217 @@ NORMAL_LIMIT(8) static av_always_inline int hev(uint8_t *p, ptrdiff_t stride, int thresh) { LOAD_PIXELS - return FFABS(p1-p0) > thresh || FFABS(q1-q0) > thresh; + return FFABS(p1 - p0) > thresh || FFABS(q1 - q0) > thresh; } static av_always_inline void filter_mbedge(uint8_t *p, ptrdiff_t stride) { int a0, a1, a2, w; - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; LOAD_PIXELS - w = clip_int8(p1-q1); - w = clip_int8(w + 3*(q0-p0)); + w = clip_int8(p1 - q1); + w = clip_int8(w + 3 * (q0 - p0)); - a0 = (27*w + 63) >> 7; - a1 = (18*w + 63) >> 7; - a2 = ( 9*w + 63) >> 7; + a0 = (27 * w + 63) >> 7; + a1 = (18 * w + 63) >> 7; + a2 = (9 * w + 63) >> 7; - p[-3*stride] = cm[p2 + a2]; - p[-2*stride] = cm[p1 + a1]; - p[-1*stride] = cm[p0 + a0]; - p[ 0*stride] = cm[q0 - a0]; - p[ 1*stride] = cm[q1 - a1]; - p[ 2*stride] = cm[q2 - a2]; + p[-3 * stride] = cm[p2 + a2]; + p[-2 * stride] = cm[p1 + a1]; + p[-1 * stride] = cm[p0 + a0]; + p[ 0 * stride] = cm[q0 - a0]; + p[ 1 * stride] = cm[q1 - a1]; + p[ 2 * stride] = cm[q2 - a2]; } -#define LOOP_FILTER(vpn, dir, size, stridea, strideb, maybe_inline) \ -static maybe_inline void vp ## vpn ## _ ## dir ## _loop_filter ## size ## _c(uint8_t *dst, ptrdiff_t stride,\ - int flim_E, int flim_I, int hev_thresh)\ -{\ - int i;\ -\ - for (i = 0; i < size; i++)\ - if (vp ## vpn ## _normal_limit(dst+i*stridea, strideb, flim_E, flim_I)) {\ - if (hev(dst+i*stridea, strideb, hev_thresh))\ - filter_common(dst+i*stridea, strideb, 1, vpn);\ - else\ - filter_mbedge(dst+i*stridea, strideb);\ - }\ -}\ -\ -static maybe_inline void vp ## vpn ## _ ## dir ## _loop_filter ## size ## _inner_c(uint8_t *dst, ptrdiff_t stride,\ - int flim_E, int flim_I, int hev_thresh)\ -{\ - int i;\ -\ - for (i = 0; i < size; i++)\ - if (vp ## vpn ## _normal_limit(dst+i*stridea, strideb, flim_E, flim_I)) {\ - int hv = hev(dst+i*stridea, strideb, hev_thresh);\ - if (hv) \ - filter_common(dst+i*stridea, strideb, 1, vpn);\ - else \ - filter_common(dst+i*stridea, strideb, 0, vpn);\ - }\ +#define LOOP_FILTER(vpn, dir, size, stridea, strideb, maybe_inline) \ +static maybe_inline \ +void vpn ## _ ## dir ## _loop_filter ## size ## _c(uint8_t *dst, \ + ptrdiff_t stride, \ + int flim_E, int flim_I, \ + int hev_thresh) \ +{ \ + int i; \ + for (i = 0; i < size; i++) \ + if (vpn ## _normal_limit(dst + i * stridea, strideb, \ + flim_E, flim_I)) { \ + if (hev(dst + i * stridea, strideb, hev_thresh)) \ + vpn ## _filter_common(dst + i * stridea, strideb, 1); \ + else \ + filter_mbedge(dst + i * stridea, strideb); \ + } \ +} \ + \ +static maybe_inline \ +void vpn ## _ ## dir ## _loop_filter ## size ## _inner_c(uint8_t *dst, \ + ptrdiff_t stride, \ + int flim_E, \ + int flim_I, \ + int hev_thresh) \ +{ \ + int i; \ + for (i = 0; i < size; i++) \ + if (vpn ## _normal_limit(dst + i * stridea, strideb, \ + flim_E, flim_I)) { \ + int hv = hev(dst + i * stridea, strideb, hev_thresh); \ + if (hv) \ + vpn ## _filter_common(dst + i * stridea, strideb, 1); \ + else \ + vpn ## _filter_common(dst + i * stridea, strideb, 0); \ + } \ } -#define UV_LOOP_FILTER(vpn, dir, stridea, strideb) \ -LOOP_FILTER(vpn, dir, 8, stridea, strideb, av_always_inline) \ -static void vp ## vpn ## _ ## dir ## _loop_filter8uv_c(uint8_t *dstU, uint8_t *dstV, ptrdiff_t stride,\ - int fE, int fI, int hev_thresh)\ -{\ - vp ## vpn ## _ ## dir ## _loop_filter8_c(dstU, stride, fE, fI, hev_thresh);\ - vp ## vpn ## _ ## dir ## _loop_filter8_c(dstV, stride, fE, fI, hev_thresh);\ -}\ -static void vp ## vpn ## _ ## dir ## _loop_filter8uv_inner_c(uint8_t *dstU, uint8_t *dstV, ptrdiff_t stride,\ - int fE, int fI, int hev_thresh)\ -{\ - vp ## vpn ## _ ## dir ## _loop_filter8_inner_c(dstU, stride, fE, fI, hev_thresh);\ - vp ## vpn ## _ ## dir ## _loop_filter8_inner_c(dstV, stride, fE, fI, hev_thresh);\ +#define UV_LOOP_FILTER(vpn, dir, stridea, strideb) \ +LOOP_FILTER(vpn, dir, 8, stridea, strideb, av_always_inline) \ +static void vpn ## _ ## dir ## _loop_filter8uv_c(uint8_t *dstU, \ + uint8_t *dstV, \ + ptrdiff_t stride, int fE, \ + int fI, int hev_thresh) \ +{ \ + vpn ## _ ## dir ## _loop_filter8_c(dstU, stride, fE, fI, hev_thresh); \ + vpn ## _ ## dir ## _loop_filter8_c(dstV, stride, fE, fI, hev_thresh); \ +} \ + \ +static void vpn ## _ ## dir ## _loop_filter8uv_inner_c(uint8_t *dstU, \ + uint8_t *dstV, \ + ptrdiff_t stride, \ + int fE, int fI, \ + int hev_thresh) \ +{ \ + vpn ## _ ## dir ## _loop_filter8_inner_c(dstU, stride, fE, fI, \ + hev_thresh); \ + vpn ## _ ## dir ## _loop_filter8_inner_c(dstV, stride, fE, fI, \ + hev_thresh); \ } -#define LOOP_FILTER_SIMPLE(vpn) \ -static void vp ## vpn ## _v_loop_filter_simple_c(uint8_t *dst, ptrdiff_t stride, int flim)\ -{\ - int i;\ -\ - for (i = 0; i < 16; i++)\ - if (vp ## vpn ## _simple_limit(dst+i, stride, flim))\ - filter_common(dst+i, stride, 1, vpn);\ -}\ -\ -static void vp ## vpn ## _h_loop_filter_simple_c(uint8_t *dst, ptrdiff_t stride, int flim)\ -{\ - int i;\ -\ - for (i = 0; i < 16; i++)\ - if (vp ## vpn ## _simple_limit(dst+i*stride, 1, flim))\ - filter_common(dst+i*stride, 1, 1, vpn);\ +#define LOOP_FILTER_SIMPLE(vpn) \ +static void vpn ## _v_loop_filter_simple_c(uint8_t *dst, ptrdiff_t stride, \ + int flim) \ +{ \ + int i; \ + for (i = 0; i < 16; i++) \ + if (vpn ## _simple_limit(dst + i, stride, flim)) \ + vpn ## _filter_common(dst + i, stride, 1); \ +} \ + \ +static void vpn ## _h_loop_filter_simple_c(uint8_t *dst, ptrdiff_t stride, \ + int flim) \ +{ \ + int i; \ + for (i = 0; i < 16; i++) \ + if (vpn ## _simple_limit(dst + i * stride, 1, flim)) \ + vpn ## _filter_common(dst + i * stride, 1, 1); \ } -#if CONFIG_VP7_DECODER -LOOP_FILTER(7, v, 16, 1, stride,) -LOOP_FILTER(7, h, 16, stride, 1,) -UV_LOOP_FILTER(7, v, 1, stride) -UV_LOOP_FILTER(7, h, stride, 1) -LOOP_FILTER_SIMPLE(7) -#endif - -#if CONFIG_VP8_DECODER -LOOP_FILTER(8, v, 16, 1, stride,) -LOOP_FILTER(8, h, 16, stride, 1,) -UV_LOOP_FILTER(8, v, 1, stride) -UV_LOOP_FILTER(8, h, stride, 1) -LOOP_FILTER_SIMPLE(8) -#endif +#define LOOP_FILTERS(vpn) \ + LOOP_FILTER(vpn, v, 16, 1, stride, ) \ + LOOP_FILTER(vpn, h, 16, stride, 1, ) \ + UV_LOOP_FILTER(vpn, v, 1, stride) \ + UV_LOOP_FILTER(vpn, h, stride, 1) \ + LOOP_FILTER_SIMPLE(vpn) \ static const uint8_t subpel_filters[7][6] = { - { 0, 6, 123, 12, 1, 0 }, - { 2, 11, 108, 36, 8, 1 }, - { 0, 9, 93, 50, 6, 0 }, - { 3, 16, 77, 77, 16, 3 }, - { 0, 6, 50, 93, 9, 0 }, - { 1, 8, 36, 108, 11, 2 }, - { 0, 1, 12, 123, 6, 0 }, + { 0, 6, 123, 12, 1, 0 }, + { 2, 11, 108, 36, 8, 1 }, + { 0, 9, 93, 50, 6, 0 }, + { 3, 16, 77, 77, 16, 3 }, + { 0, 6, 50, 93, 9, 0 }, + { 1, 8, 36, 108, 11, 2 }, + { 0, 1, 12, 123, 6, 0 }, }; -#define PUT_PIXELS(WIDTH) \ -static void put_vp8_pixels ## WIDTH ##_c(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, int h, int x, int y) { \ - int i; \ - for (i = 0; i < h; i++, dst+= dststride, src+= srcstride) { \ - memcpy(dst, src, WIDTH); \ - } \ +#define PUT_PIXELS(WIDTH) \ +static void put_vp8_pixels ## WIDTH ## _c(uint8_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int h, int x, int y) \ +{ \ + int i; \ + for (i = 0; i < h; i++, dst += dststride, src += srcstride) \ + memcpy(dst, src, WIDTH); \ } PUT_PIXELS(16) PUT_PIXELS(8) PUT_PIXELS(4) -#define FILTER_6TAP(src, F, stride) \ - cm[(F[2]*src[x+0*stride] - F[1]*src[x-1*stride] + F[0]*src[x-2*stride] + \ - F[3]*src[x+1*stride] - F[4]*src[x+2*stride] + F[5]*src[x+3*stride] + 64) >> 7] +#define FILTER_6TAP(src, F, stride) \ + cm[(F[2] * src[x + 0 * stride] - F[1] * src[x - 1 * stride] + \ + F[0] * src[x - 2 * stride] + F[3] * src[x + 1 * stride] - \ + F[4] * src[x + 2 * stride] + F[5] * src[x + 3 * stride] + 64) >> 7] -#define FILTER_4TAP(src, F, stride) \ - cm[(F[2]*src[x+0*stride] - F[1]*src[x-1*stride] + \ - F[3]*src[x+1*stride] - F[4]*src[x+2*stride] + 64) >> 7] +#define FILTER_4TAP(src, F, stride) \ + cm[(F[2] * src[x + 0 * stride] - F[1] * src[x - 1 * stride] + \ + F[3] * src[x + 1 * stride] - F[4] * src[x + 2 * stride] + 64) >> 7] -#define VP8_EPEL_H(SIZE, TAPS) \ -static void put_vp8_epel ## SIZE ## _h ## TAPS ## _c(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, int h, int mx, int my) \ -{ \ - const uint8_t *filter = subpel_filters[mx-1]; \ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; \ - int x, y; \ -\ - for (y = 0; y < h; y++) { \ - for (x = 0; x < SIZE; x++) \ - dst[x] = FILTER_ ## TAPS ## TAP(src, filter, 1); \ - dst += dststride; \ - src += srcstride; \ - } \ +#define VP8_EPEL_H(SIZE, TAPS) \ +static void put_vp8_epel ## SIZE ## _h ## TAPS ## _c(uint8_t *dst, \ + ptrdiff_t dststride, \ + uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const uint8_t *filter = subpel_filters[mx - 1]; \ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; \ + int x, y; \ + for (y = 0; y < h; y++) { \ + for (x = 0; x < SIZE; x++) \ + dst[x] = FILTER_ ## TAPS ## TAP(src, filter, 1); \ + dst += dststride; \ + src += srcstride; \ + } \ } -#define VP8_EPEL_V(SIZE, TAPS) \ -static void put_vp8_epel ## SIZE ## _v ## TAPS ## _c(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, int h, int mx, int my) \ -{ \ - const uint8_t *filter = subpel_filters[my-1]; \ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; \ - int x, y; \ -\ - for (y = 0; y < h; y++) { \ - for (x = 0; x < SIZE; x++) \ - dst[x] = FILTER_ ## TAPS ## TAP(src, filter, srcstride); \ - dst += dststride; \ - src += srcstride; \ - } \ + +#define VP8_EPEL_V(SIZE, TAPS) \ +static void put_vp8_epel ## SIZE ## _v ## TAPS ## _c(uint8_t *dst, \ + ptrdiff_t dststride, \ + uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const uint8_t *filter = subpel_filters[my - 1]; \ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; \ + int x, y; \ + for (y = 0; y < h; y++) { \ + for (x = 0; x < SIZE; x++) \ + dst[x] = FILTER_ ## TAPS ## TAP(src, filter, srcstride); \ + dst += dststride; \ + src += srcstride; \ + } \ } -#define VP8_EPEL_HV(SIZE, HTAPS, VTAPS) \ -static void put_vp8_epel ## SIZE ## _h ## HTAPS ## v ## VTAPS ## _c(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, int h, int mx, int my) \ -{ \ - const uint8_t *filter = subpel_filters[mx-1]; \ - const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; \ - int x, y; \ - uint8_t tmp_array[(2*SIZE+VTAPS-1)*SIZE]; \ - uint8_t *tmp = tmp_array; \ - src -= (2-(VTAPS==4))*srcstride; \ -\ - for (y = 0; y < h+VTAPS-1; y++) { \ - for (x = 0; x < SIZE; x++) \ - tmp[x] = FILTER_ ## HTAPS ## TAP(src, filter, 1); \ - tmp += SIZE; \ - src += srcstride; \ - } \ -\ - tmp = tmp_array + (2-(VTAPS==4))*SIZE; \ - filter = subpel_filters[my-1]; \ -\ - for (y = 0; y < h; y++) { \ - for (x = 0; x < SIZE; x++) \ - dst[x] = FILTER_ ## VTAPS ## TAP(tmp, filter, SIZE); \ - dst += dststride; \ - tmp += SIZE; \ - } \ + +#define VP8_EPEL_HV(SIZE, HTAPS, VTAPS) \ +static void \ +put_vp8_epel ## SIZE ## _h ## HTAPS ## v ## VTAPS ## _c(uint8_t *dst, \ + ptrdiff_t dststride, \ + uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, \ + int my) \ +{ \ + const uint8_t *filter = subpel_filters[mx - 1]; \ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; \ + int x, y; \ + uint8_t tmp_array[(2 * SIZE + VTAPS - 1) * SIZE]; \ + uint8_t *tmp = tmp_array; \ + src -= (2 - (VTAPS == 4)) * srcstride; \ + \ + for (y = 0; y < h + VTAPS - 1; y++) { \ + for (x = 0; x < SIZE; x++) \ + tmp[x] = FILTER_ ## HTAPS ## TAP(src, filter, 1); \ + tmp += SIZE; \ + src += srcstride; \ + } \ + tmp = tmp_array + (2 - (VTAPS == 4)) * SIZE; \ + filter = subpel_filters[my - 1]; \ + \ + for (y = 0; y < h; y++) { \ + for (x = 0; x < SIZE; x++) \ + dst[x] = FILTER_ ## VTAPS ## TAP(tmp, filter, SIZE); \ + dst += dststride; \ + tmp += SIZE; \ + } \ } VP8_EPEL_H(16, 4) @@ -518,6 +566,7 @@ VP8_EPEL_V(4, 4) VP8_EPEL_V(16, 6) VP8_EPEL_V(8, 6) VP8_EPEL_V(4, 6) + VP8_EPEL_HV(16, 4, 4) VP8_EPEL_HV(8, 4, 4) VP8_EPEL_HV(4, 4, 4) @@ -531,74 +580,78 @@ VP8_EPEL_HV(16, 6, 6) VP8_EPEL_HV(8, 6, 6) VP8_EPEL_HV(4, 6, 6) -#define VP8_BILINEAR(SIZE) \ -static void put_vp8_bilinear ## SIZE ## _h_c(uint8_t *dst, ptrdiff_t dstride, uint8_t *src, ptrdiff_t sstride, int h, int mx, int my) \ -{ \ - int a = 8-mx, b = mx; \ - int x, y; \ -\ - for (y = 0; y < h; y++) { \ - for (x = 0; x < SIZE; x++) \ - dst[x] = (a*src[x] + b*src[x+1] + 4) >> 3; \ - dst += dstride; \ - src += sstride; \ - } \ -} \ -static void put_vp8_bilinear ## SIZE ## _v_c(uint8_t *dst, ptrdiff_t dstride, uint8_t *src, ptrdiff_t sstride, int h, int mx, int my) \ -{ \ - int c = 8-my, d = my; \ - int x, y; \ -\ - for (y = 0; y < h; y++) { \ - for (x = 0; x < SIZE; x++) \ - dst[x] = (c*src[x] + d*src[x+sstride] + 4) >> 3; \ - dst += dstride; \ - src += sstride; \ - } \ -} \ -\ -static void put_vp8_bilinear ## SIZE ## _hv_c(uint8_t *dst, ptrdiff_t dstride, uint8_t *src, ptrdiff_t sstride, int h, int mx, int my) \ -{ \ - int a = 8-mx, b = mx; \ - int c = 8-my, d = my; \ - int x, y; \ - uint8_t tmp_array[(2*SIZE+1)*SIZE]; \ - uint8_t *tmp = tmp_array; \ -\ - for (y = 0; y < h+1; y++) { \ - for (x = 0; x < SIZE; x++) \ - tmp[x] = (a*src[x] + b*src[x+1] + 4) >> 3; \ - tmp += SIZE; \ - src += sstride; \ - } \ -\ - tmp = tmp_array; \ -\ - for (y = 0; y < h; y++) { \ - for (x = 0; x < SIZE; x++) \ - dst[x] = (c*tmp[x] + d*tmp[x+SIZE] + 4) >> 3; \ - dst += dstride; \ - tmp += SIZE; \ - } \ +#define VP8_BILINEAR(SIZE) \ +static void put_vp8_bilinear ## SIZE ## _h_c(uint8_t *dst, ptrdiff_t dstride, \ + uint8_t *src, ptrdiff_t sstride, \ + int h, int mx, int my) \ +{ \ + int a = 8 - mx, b = mx; \ + int x, y; \ + for (y = 0; y < h; y++) { \ + for (x = 0; x < SIZE; x++) \ + dst[x] = (a * src[x] + b * src[x + 1] + 4) >> 3; \ + dst += dstride; \ + src += sstride; \ + } \ +} \ + \ +static void put_vp8_bilinear ## SIZE ## _v_c(uint8_t *dst, ptrdiff_t dstride, \ + uint8_t *src, ptrdiff_t sstride, \ + int h, int mx, int my) \ +{ \ + int c = 8 - my, d = my; \ + int x, y; \ + for (y = 0; y < h; y++) { \ + for (x = 0; x < SIZE; x++) \ + dst[x] = (c * src[x] + d * src[x + sstride] + 4) >> 3; \ + dst += dstride; \ + src += sstride; \ + } \ +} \ + \ +static void put_vp8_bilinear ## SIZE ## _hv_c(uint8_t *dst, \ + ptrdiff_t dstride, \ + uint8_t *src, \ + ptrdiff_t sstride, \ + int h, int mx, int my) \ +{ \ + int a = 8 - mx, b = mx; \ + int c = 8 - my, d = my; \ + int x, y; \ + uint8_t tmp_array[(2 * SIZE + 1) * SIZE]; \ + uint8_t *tmp = tmp_array; \ + for (y = 0; y < h + 1; y++) { \ + for (x = 0; x < SIZE; x++) \ + tmp[x] = (a * src[x] + b * src[x + 1] + 4) >> 3; \ + tmp += SIZE; \ + src += sstride; \ + } \ + tmp = tmp_array; \ + for (y = 0; y < h; y++) { \ + for (x = 0; x < SIZE; x++) \ + dst[x] = (c * tmp[x] + d * tmp[x + SIZE] + 4) >> 3; \ + dst += dstride; \ + tmp += SIZE; \ + } \ } VP8_BILINEAR(16) VP8_BILINEAR(8) VP8_BILINEAR(4) -#define VP8_MC_FUNC(IDX, SIZE) \ - dsp->put_vp8_epel_pixels_tab[IDX][0][0] = put_vp8_pixels ## SIZE ## _c; \ - dsp->put_vp8_epel_pixels_tab[IDX][0][1] = put_vp8_epel ## SIZE ## _h4_c; \ - dsp->put_vp8_epel_pixels_tab[IDX][0][2] = put_vp8_epel ## SIZE ## _h6_c; \ - dsp->put_vp8_epel_pixels_tab[IDX][1][0] = put_vp8_epel ## SIZE ## _v4_c; \ +#define VP78_MC_FUNC(IDX, SIZE) \ + dsp->put_vp8_epel_pixels_tab[IDX][0][0] = put_vp8_pixels ## SIZE ## _c; \ + dsp->put_vp8_epel_pixels_tab[IDX][0][1] = put_vp8_epel ## SIZE ## _h4_c; \ + dsp->put_vp8_epel_pixels_tab[IDX][0][2] = put_vp8_epel ## SIZE ## _h6_c; \ + dsp->put_vp8_epel_pixels_tab[IDX][1][0] = put_vp8_epel ## SIZE ## _v4_c; \ dsp->put_vp8_epel_pixels_tab[IDX][1][1] = put_vp8_epel ## SIZE ## _h4v4_c; \ dsp->put_vp8_epel_pixels_tab[IDX][1][2] = put_vp8_epel ## SIZE ## _h6v4_c; \ - dsp->put_vp8_epel_pixels_tab[IDX][2][0] = put_vp8_epel ## SIZE ## _v6_c; \ + dsp->put_vp8_epel_pixels_tab[IDX][2][0] = put_vp8_epel ## SIZE ## _v6_c; \ dsp->put_vp8_epel_pixels_tab[IDX][2][1] = put_vp8_epel ## SIZE ## _h4v6_c; \ dsp->put_vp8_epel_pixels_tab[IDX][2][2] = put_vp8_epel ## SIZE ## _h6v6_c -#define VP8_BILINEAR_MC_FUNC(IDX, SIZE) \ - dsp->put_vp8_bilinear_pixels_tab[IDX][0][0] = put_vp8_pixels ## SIZE ## _c; \ +#define VP78_BILINEAR_MC_FUNC(IDX, SIZE) \ + dsp->put_vp8_bilinear_pixels_tab[IDX][0][0] = put_vp8_pixels ## SIZE ## _c; \ dsp->put_vp8_bilinear_pixels_tab[IDX][0][1] = put_vp8_bilinear ## SIZE ## _h_c; \ dsp->put_vp8_bilinear_pixels_tab[IDX][0][2] = put_vp8_bilinear ## SIZE ## _h_c; \ dsp->put_vp8_bilinear_pixels_tab[IDX][1][0] = put_vp8_bilinear ## SIZE ## _v_c; \ @@ -608,48 +661,79 @@ VP8_BILINEAR(4) dsp->put_vp8_bilinear_pixels_tab[IDX][2][1] = put_vp8_bilinear ## SIZE ## _hv_c; \ dsp->put_vp8_bilinear_pixels_tab[IDX][2][2] = put_vp8_bilinear ## SIZE ## _hv_c -av_cold void ff_vp8dsp_init(VP8DSPContext *dsp, int vp7) +av_cold void ff_vp78dsp_init(VP8DSPContext *dsp) { -#if CONFIG_VP7_DECODER && CONFIG_VP8_DECODER -#define VPX(f) vp7 ? vp7_ ## f : vp8_ ## f -#elif CONFIG_VP7_DECODER -#define VPX(f) vp7_ ## f -#else // CONFIG_VP8_DECODER -#define VPX(f) vp8_ ## f -#endif + VP78_MC_FUNC(0, 16); + VP78_MC_FUNC(1, 8); + VP78_MC_FUNC(2, 4); - dsp->vp8_luma_dc_wht = VPX(luma_dc_wht_c); - dsp->vp8_luma_dc_wht_dc = VPX(luma_dc_wht_dc_c); - dsp->vp8_idct_add = VPX(idct_add_c); - dsp->vp8_idct_dc_add = VPX(idct_dc_add_c); - dsp->vp8_idct_dc_add4y = VPX(idct_dc_add4y_c); - dsp->vp8_idct_dc_add4uv = VPX(idct_dc_add4uv_c); - - dsp->vp8_v_loop_filter16y = VPX(v_loop_filter16_c); - dsp->vp8_h_loop_filter16y = VPX(h_loop_filter16_c); - dsp->vp8_v_loop_filter8uv = VPX(v_loop_filter8uv_c); - dsp->vp8_h_loop_filter8uv = VPX(h_loop_filter8uv_c); - - dsp->vp8_v_loop_filter16y_inner = VPX(v_loop_filter16_inner_c); - dsp->vp8_h_loop_filter16y_inner = VPX(h_loop_filter16_inner_c); - dsp->vp8_v_loop_filter8uv_inner = VPX(v_loop_filter8uv_inner_c); - dsp->vp8_h_loop_filter8uv_inner = VPX(h_loop_filter8uv_inner_c); - - dsp->vp8_v_loop_filter_simple = VPX(v_loop_filter_simple_c); - dsp->vp8_h_loop_filter_simple = VPX(h_loop_filter_simple_c); - - VP8_MC_FUNC(0, 16); - VP8_MC_FUNC(1, 8); - VP8_MC_FUNC(2, 4); - - VP8_BILINEAR_MC_FUNC(0, 16); - VP8_BILINEAR_MC_FUNC(1, 8); - VP8_BILINEAR_MC_FUNC(2, 4); + VP78_BILINEAR_MC_FUNC(0, 16); + VP78_BILINEAR_MC_FUNC(1, 8); + VP78_BILINEAR_MC_FUNC(2, 4); if (ARCH_ARM) - ff_vp8dsp_init_arm(dsp, vp7); + ff_vp78dsp_init_arm(dsp); if (ARCH_PPC) - ff_vp8dsp_init_ppc(dsp); + ff_vp78dsp_init_ppc(dsp); if (ARCH_X86) - ff_vp8dsp_init_x86(dsp, vp7); + ff_vp78dsp_init_x86(dsp); } + +#if CONFIG_VP7_DECODER +LOOP_FILTERS(vp7) + +av_cold void ff_vp7dsp_init(VP8DSPContext *dsp) +{ + dsp->vp8_luma_dc_wht = vp7_luma_dc_wht_c; + dsp->vp8_luma_dc_wht_dc = vp7_luma_dc_wht_dc_c; + dsp->vp8_idct_add = vp7_idct_add_c; + dsp->vp8_idct_dc_add = vp7_idct_dc_add_c; + dsp->vp8_idct_dc_add4y = vp7_idct_dc_add4y_c; + dsp->vp8_idct_dc_add4uv = vp7_idct_dc_add4uv_c; + + dsp->vp8_v_loop_filter16y = vp7_v_loop_filter16_c; + dsp->vp8_h_loop_filter16y = vp7_h_loop_filter16_c; + dsp->vp8_v_loop_filter8uv = vp7_v_loop_filter8uv_c; + dsp->vp8_h_loop_filter8uv = vp7_h_loop_filter8uv_c; + + dsp->vp8_v_loop_filter16y_inner = vp7_v_loop_filter16_inner_c; + dsp->vp8_h_loop_filter16y_inner = vp7_h_loop_filter16_inner_c; + dsp->vp8_v_loop_filter8uv_inner = vp7_v_loop_filter8uv_inner_c; + dsp->vp8_h_loop_filter8uv_inner = vp7_h_loop_filter8uv_inner_c; + + dsp->vp8_v_loop_filter_simple = vp7_v_loop_filter_simple_c; + dsp->vp8_h_loop_filter_simple = vp7_h_loop_filter_simple_c; +} +#endif /* CONFIG_VP7_DECODER */ + +#if CONFIG_VP8_DECODER +LOOP_FILTERS(vp8) + +av_cold void ff_vp8dsp_init(VP8DSPContext *dsp) +{ + dsp->vp8_luma_dc_wht = vp8_luma_dc_wht_c; + dsp->vp8_luma_dc_wht_dc = vp8_luma_dc_wht_dc_c; + dsp->vp8_idct_add = vp8_idct_add_c; + dsp->vp8_idct_dc_add = vp8_idct_dc_add_c; + dsp->vp8_idct_dc_add4y = vp8_idct_dc_add4y_c; + dsp->vp8_idct_dc_add4uv = vp8_idct_dc_add4uv_c; + + dsp->vp8_v_loop_filter16y = vp8_v_loop_filter16_c; + dsp->vp8_h_loop_filter16y = vp8_h_loop_filter16_c; + dsp->vp8_v_loop_filter8uv = vp8_v_loop_filter8uv_c; + dsp->vp8_h_loop_filter8uv = vp8_h_loop_filter8uv_c; + + dsp->vp8_v_loop_filter16y_inner = vp8_v_loop_filter16_inner_c; + dsp->vp8_h_loop_filter16y_inner = vp8_h_loop_filter16_inner_c; + dsp->vp8_v_loop_filter8uv_inner = vp8_v_loop_filter8uv_inner_c; + dsp->vp8_h_loop_filter8uv_inner = vp8_h_loop_filter8uv_inner_c; + + dsp->vp8_v_loop_filter_simple = vp8_v_loop_filter_simple_c; + dsp->vp8_h_loop_filter_simple = vp8_h_loop_filter_simple_c; + + if (ARCH_ARM) + ff_vp8dsp_init_arm(dsp); + if (ARCH_X86) + ff_vp8dsp_init_x86(dsp); +} +#endif /* CONFIG_VP8_DECODER */ diff --git a/libavcodec/vp8dsp.h b/libavcodec/vp8dsp.h index 02ac77802..5fdd3af70 100644 --- a/libavcodec/vp8dsp.h +++ b/libavcodec/vp8dsp.h @@ -30,8 +30,8 @@ #include #include -typedef void (*vp8_mc_func)(uint8_t *dst/*align 8*/, ptrdiff_t dstStride, - uint8_t *src/*align 1*/, ptrdiff_t srcStride, +typedef void (*vp8_mc_func)(uint8_t *dst /* align 8 */, ptrdiff_t dstStride, + uint8_t *src /* align 1 */, ptrdiff_t srcStride, int h, int x, int y); typedef struct VP8DSPContext { @@ -88,9 +88,18 @@ void ff_put_vp8_pixels8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride, void ff_put_vp8_pixels4_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); -void ff_vp8dsp_init(VP8DSPContext *c, int vp7); -void ff_vp8dsp_init_x86(VP8DSPContext *c, int vp7); -void ff_vp8dsp_init_arm(VP8DSPContext *c, int vp7); -void ff_vp8dsp_init_ppc(VP8DSPContext *c); +void ff_vp7dsp_init(VP8DSPContext *c); + +void ff_vp78dsp_init(VP8DSPContext *c); +void ff_vp78dsp_init_arm(VP8DSPContext *c); +void ff_vp78dsp_init_ppc(VP8DSPContext *c); +void ff_vp78dsp_init_x86(VP8DSPContext *c); + +void ff_vp8dsp_init(VP8DSPContext *c); +void ff_vp8dsp_init_arm(VP8DSPContext *c); +void ff_vp8dsp_init_x86(VP8DSPContext *c); + +#define IS_VP7 1 +#define IS_VP8 0 #endif /* AVCODEC_VP8DSP_H */ diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index cbc885b77..56975bd57 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -325,7 +325,7 @@ static int update_size(AVCodecContext *ctx, int w, int h) s->cols = (w + 7) >> 3; s->rows = (h + 7) >> 3; -#define assign(var, type, n) var = (type) p; p += s->sb_cols * n * sizeof(*var) +#define assign(var, type, n) var = (type) p; p += s->sb_cols * (n) * sizeof(*var) av_freep(&s->intra_pred_data[0]); p = av_malloc(s->sb_cols * (240 + sizeof(*s->lflvl) + 16 * sizeof(*s->above_mv_ctx))); if (!p) @@ -2258,7 +2258,11 @@ static void decode_coeffs(AVCodecContext *ctx) 16 * step * step, c, e, p, a[x] + l[y], \ uvscan, uvnb, uv_band_counts, qmul[1]); \ a[x] = l[y] = !!res; \ - s->uveob[pl][n] = res; \ + if (step >= 4) { \ + AV_WN16A(&s->uveob[pl][n], res); \ + } else { \ + s->uveob[pl][n] = res; \ + } \ } \ } @@ -2448,8 +2452,8 @@ static void intra_recon(AVCodecContext *ctx, ptrdiff_t y_off, ptrdiff_t uv_off) int tx = 4 * s->lossless + b->tx, uvtx = b->uvtx + 4 * s->lossless; int uvstep1d = 1 << b->uvtx, p; uint8_t *dst = s->dst[0], *dst_r = s->frames[CUR_FRAME].tf.f->data[0] + y_off; - LOCAL_ALIGNED_16(uint8_t, a_buf, [48]); - LOCAL_ALIGNED_16(uint8_t, l, [32]); + LOCAL_ALIGNED_32(uint8_t, a_buf, [64]); + LOCAL_ALIGNED_32(uint8_t, l, [32]); for (n = 0, y = 0; y < end_y; y += step1d) { uint8_t *ptr = dst, *ptr_r = dst_r; @@ -2457,7 +2461,7 @@ static void intra_recon(AVCodecContext *ctx, ptrdiff_t y_off, ptrdiff_t uv_off) ptr_r += 4 * step1d, n += step) { int mode = b->mode[b->bs > BS_8x8 && b->tx == TX_4X4 ? y * 2 + x : 0]; - uint8_t *a = &a_buf[16]; + uint8_t *a = &a_buf[32]; enum TxfmType txtp = vp9_intra_txfm_type[mode]; int eob = b->skip ? 0 : b->tx > TX_8X8 ? AV_RN16A(&s->eob[n]) : s->eob[n]; diff --git a/libavcodec/vp9dsp.c b/libavcodec/vp9dsp.c index e2f99f72c..6356adde3 100644 --- a/libavcodec/vp9dsp.c +++ b/libavcodec/vp9dsp.c @@ -896,7 +896,7 @@ itxfm_wrapper(iadst, idct, sz, bits, 0) \ itxfm_wrapper(idct, iadst, sz, bits, 0) \ itxfm_wrapper(iadst, iadst, sz, bits, 0) -#define IN(x) in[x * stride] +#define IN(x) in[(x) * stride] static av_always_inline void idct4_1d(const int16_t *in, ptrdiff_t stride, int16_t *out, int pass) diff --git a/libavcodec/vp9dsp.h b/libavcodec/vp9dsp.h index 74124e44b..db0a92e21 100644 --- a/libavcodec/vp9dsp.h +++ b/libavcodec/vp9dsp.h @@ -104,7 +104,7 @@ typedef struct VP9DSPContext { * dimension 2: filter type (0: smooth, 1: regular, 2: sharp, 3: bilin) * dimension 3: averaging type (0: put, 1: avg) * dimension 4: x subpel interpolation (0: none, 1: 8tap/bilin) - * dimension 5: y subpel interpolation (1: none, 1: 8tap/bilin) + * dimension 5: y subpel interpolation (0: none, 1: 8tap/bilin) * * dst/stride are aligned by hsize */ diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c index 6f60514a2..7c60f78b6 100644 --- a/libavcodec/wavpack.c +++ b/libavcodec/wavpack.c @@ -83,7 +83,7 @@ typedef struct WavpackContext { int ch_offset; } WavpackContext; -#define LEVEL_DECAY(a) ((a + 0x80) >> 8) +#define LEVEL_DECAY(a) (((a) + 0x80) >> 8) static av_always_inline int get_tail(GetBitContext *gb, int k) { @@ -622,7 +622,7 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, ThreadFrame tframe = { .f = frame }; WavpackFrameContext *s; GetByteContext gb; - void *samples_l, *samples_r; + void *samples_l = NULL, *samples_r = NULL; int ret; int got_terms = 0, got_weights = 0, got_samples = 0, got_entropy = 0, got_bs = 0, got_float = 0, got_hybrid = 0; diff --git a/libavcodec/wavpack.h b/libavcodec/wavpack.h index 081b7f714..3a3e8dbd2 100644 --- a/libavcodec/wavpack.h +++ b/libavcodec/wavpack.h @@ -99,8 +99,8 @@ typedef struct WvChannel { // macros for manipulating median values #define GET_MED(n) ((c->median[n] >> 4) + 1) -#define DEC_MED(n) c->median[n] -= ((c->median[n] + (128 >> n) - 2) / (128 >> n)) * 2 -#define INC_MED(n) c->median[n] += ((c->median[n] + (128 >> n) ) / (128 >> n)) * 5 +#define DEC_MED(n) c->median[n] -= ((c->median[n] + (128 >> (n)) - 2) / (128 >> (n))) * 2 +#define INC_MED(n) c->median[n] += ((c->median[n] + (128 >> (n)) ) / (128 >> (n))) * 5 // macros for applying weight #define UPDATE_WEIGHT_CLIP(weight, delta, samples, in) \ diff --git a/libavcodec/wavpackenc.c b/libavcodec/wavpackenc.c index d7a1c61e9..66ebf2fa3 100644 --- a/libavcodec/wavpackenc.c +++ b/libavcodec/wavpackenc.c @@ -30,17 +30,17 @@ #include "wavpack.h" #define UPDATE_WEIGHT(weight, delta, source, result) \ - if (source && result) { \ - int32_t s = (int32_t) (source ^ result) >> 31; \ - weight = (delta ^ s) + (weight - s); \ + if ((source) && (result)) { \ + int32_t s = (int32_t) ((source) ^ (result)) >> 31; \ + weight = ((delta) ^ s) + ((weight) - s); \ } -#define APPLY_WEIGHT_F(weight, sample) (((((sample & 0xffff) * weight) >> 9) + \ - (((sample & ~0xffff) >> 9) * weight) + 1) >> 1) +#define APPLY_WEIGHT_F(weight, sample) ((((((sample) & 0xffff) * (weight)) >> 9) + \ + ((((sample) & ~0xffff) >> 9) * (weight)) + 1) >> 1) -#define APPLY_WEIGHT_I(weight, sample) ((weight * sample + 512) >> 10) +#define APPLY_WEIGHT_I(weight, sample) (((weight) * (sample) + 512) >> 10) -#define APPLY_WEIGHT(weight, sample) (sample != (short) sample ? \ +#define APPLY_WEIGHT(weight, sample) ((sample) != (short) (sample) ? \ APPLY_WEIGHT_F(weight, sample) : APPLY_WEIGHT_I (weight, sample)) #define CLEAR(destin) memset(&destin, 0, sizeof(destin)); diff --git a/libavcodec/webp.c b/libavcodec/webp.c index 89c8f1317..c737f5492 100644 --- a/libavcodec/webp.c +++ b/libavcodec/webp.c @@ -309,7 +309,7 @@ static int huff_reader_build_canonical(HuffReader *r, int *code_lengths, if (max_code_length == 0 || max_code_length > MAX_HUFFMAN_CODE_LENGTH) return AVERROR(EINVAL); - codes = av_malloc(alphabet_size * sizeof(*codes)); + codes = av_malloc_array(alphabet_size, sizeof(*codes)); if (!codes) return AVERROR(ENOMEM); @@ -482,7 +482,9 @@ static int decode_entropy_image(WebPContext *s) max = 0; for (y = 0; y < img->frame->height; y++) { for (x = 0; x < img->frame->width; x++) { - int p = GET_PIXEL_COMP(img->frame, x, y, 2); + int p0 = GET_PIXEL_COMP(img->frame, x, y, 1); + int p1 = GET_PIXEL_COMP(img->frame, x, y, 2); + int p = p0 << 8 | p1; max = FFMAX(max, p); } } @@ -567,7 +569,9 @@ static HuffReader *get_huffman_group(WebPContext *s, ImageContext *img, if (gimg->size_reduction > 0) { int group_x = x >> gimg->size_reduction; int group_y = y >> gimg->size_reduction; - group = GET_PIXEL_COMP(gimg->frame, group_x, group_y, 2); + int g0 = GET_PIXEL_COMP(gimg->frame, group_x, group_y, 1); + int g1 = GET_PIXEL_COMP(gimg->frame, group_x, group_y, 2); + group = g0 << 8 | g1; } return &img->huffman_groups[group * HUFFMAN_CODES_PER_META_CODE]; @@ -1449,7 +1453,7 @@ static int webp_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } bytestream2_seek(&exif_gb, ifd_offset, SEEK_SET); - if (ff_exif_decode_ifd(avctx, &exif_gb, le, 0, &s->exif_metadata) < 0) { + if (avpriv_exif_decode_ifd(avctx, &exif_gb, le, 0, &s->exif_metadata) < 0) { av_log(avctx, AV_LOG_ERROR, "error decoding Exif data\n"); goto exif_end; } diff --git a/libavcodec/webvttenc.c b/libavcodec/webvttenc.c new file mode 100644 index 000000000..9f67a2eab --- /dev/null +++ b/libavcodec/webvttenc.c @@ -0,0 +1,219 @@ +/* + * WebVTT subtitle encoder + * Copyright (c) 2010 Aurelien Jacobs + * Copyright (c) 2014 Aman Gupta + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "avcodec.h" +#include "libavutil/avstring.h" +#include "libavutil/bprint.h" +#include "ass_split.h" +#include "ass.h" + +#define WEBVTT_STACK_SIZE 64 +typedef struct { + AVCodecContext *avctx; + ASSSplitContext *ass_ctx; + AVBPrint buffer; + unsigned timestamp_end; + int count; + char stack[WEBVTT_STACK_SIZE]; + int stack_ptr; +} WebVTTContext; + +#ifdef __GNUC__ +__attribute__ ((__format__ (__printf__, 2, 3))) +#endif +static void webvtt_print(WebVTTContext *s, const char *str, ...) +{ + va_list vargs; + va_start(vargs, str); + av_vbprintf(&s->buffer, str, vargs); + va_end(vargs); +} + +static int webvtt_stack_push(WebVTTContext *s, const char c) +{ + if (s->stack_ptr >= WEBVTT_STACK_SIZE) + return -1; + s->stack[s->stack_ptr++] = c; + return 0; +} + +static char webvtt_stack_pop(WebVTTContext *s) +{ + if (s->stack_ptr <= 0) + return 0; + return s->stack[--s->stack_ptr]; +} + +static int webvtt_stack_find(WebVTTContext *s, const char c) +{ + int i; + for (i = s->stack_ptr-1; i >= 0; i--) + if (s->stack[i] == c) + break; + return i; +} + +static void webvtt_close_tag(WebVTTContext *s, char tag) +{ + webvtt_print(s, "", tag); +} + +static void webvtt_stack_push_pop(WebVTTContext *s, const char c, int close) +{ + if (close) { + int i = c ? webvtt_stack_find(s, c) : 0; + if (i < 0) + return; + while (s->stack_ptr != i) + webvtt_close_tag(s, webvtt_stack_pop(s)); + } else if (webvtt_stack_push(s, c) < 0) + av_log(s->avctx, AV_LOG_ERROR, "tag stack overflow\n"); +} + +static void webvtt_style_apply(WebVTTContext *s, const char *style) +{ + ASSStyle *st = ff_ass_style_get(s->ass_ctx, style); + if (st) { + if (st->bold != ASS_DEFAULT_BOLD) { + webvtt_print(s, ""); + webvtt_stack_push(s, 'b'); + } + if (st->italic != ASS_DEFAULT_ITALIC) { + webvtt_print(s, ""); + webvtt_stack_push(s, 'i'); + } + if (st->underline != ASS_DEFAULT_UNDERLINE) { + webvtt_print(s, ""); + webvtt_stack_push(s, 'u'); + } + } +} + +static void webvtt_text_cb(void *priv, const char *text, int len) +{ + WebVTTContext *s = priv; + av_bprint_append_data(&s->buffer, text, len); +} + +static void webvtt_new_line_cb(void *priv, int forced) +{ + webvtt_print(priv, "\n"); +} + +static void webvtt_style_cb(void *priv, char style, int close) +{ + if (style == 's') // strikethrough unsupported + return; + + webvtt_stack_push_pop(priv, style, close); + if (!close) + webvtt_print(priv, "<%c>", style); +} + +static void webvtt_cancel_overrides_cb(void *priv, const char *style) +{ + webvtt_stack_push_pop(priv, 0, 1); + webvtt_style_apply(priv, style); +} + +static void webvtt_end_cb(void *priv) +{ + webvtt_stack_push_pop(priv, 0, 1); +} + +static const ASSCodesCallbacks webvtt_callbacks = { + .text = webvtt_text_cb, + .new_line = webvtt_new_line_cb, + .style = webvtt_style_cb, + .color = NULL, + .font_name = NULL, + .font_size = NULL, + .alignment = NULL, + .cancel_overrides = webvtt_cancel_overrides_cb, + .move = NULL, + .end = webvtt_end_cb, +}; + +static int webvtt_encode_frame(AVCodecContext *avctx, + unsigned char *buf, int bufsize, const AVSubtitle *sub) +{ + WebVTTContext *s = avctx->priv_data; + ASSDialog *dialog; + int i, num; + + av_bprint_clear(&s->buffer); + + for (i=0; inum_rects; i++) { + if (sub->rects[i]->type != SUBTITLE_ASS) { + av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n"); + return AVERROR(ENOSYS); + } + + dialog = ff_ass_split_dialog(s->ass_ctx, sub->rects[i]->ass, 0, &num); + for (; dialog && num--; dialog++) { + webvtt_style_apply(s, dialog->style); + ff_ass_split_override_codes(&webvtt_callbacks, s, dialog->text); + } + } + + if (!av_bprint_is_complete(&s->buffer)) + return AVERROR(ENOMEM); + if (!s->buffer.len) + return 0; + + if (s->buffer.len > bufsize) { + av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); + return -1; + } + memcpy(buf, s->buffer.str, s->buffer.len); + + return s->buffer.len; +} + +static int webvtt_encode_close(AVCodecContext *avctx) +{ + WebVTTContext *s = avctx->priv_data; + ff_ass_split_free(s->ass_ctx); + av_bprint_finalize(&s->buffer, NULL); + return 0; +} + +static av_cold int webvtt_encode_init(AVCodecContext *avctx) +{ + WebVTTContext *s = avctx->priv_data; + s->avctx = avctx; + s->ass_ctx = ff_ass_split(avctx->subtitle_header); + av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED); + return s->ass_ctx ? 0 : AVERROR_INVALIDDATA; +} + +AVCodec ff_webvtt_encoder = { + .name = "webvtt", + .long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_WEBVTT, + .priv_data_size = sizeof(WebVTTContext), + .init = webvtt_encode_init, + .encode_sub = webvtt_encode_frame, + .close = webvtt_encode_close, +}; diff --git a/libavcodec/wma.c b/libavcodec/wma.c index b6d6351ac..f2519f543 100644 --- a/libavcodec/wma.c +++ b/libavcodec/wma.c @@ -45,10 +45,10 @@ 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)); + run_table = av_malloc_array(n, sizeof(uint16_t)); + level_table = av_malloc_array(n, sizeof(uint16_t)); + flevel_table= av_malloc_array(n, sizeof(*flevel_table)); + int_table = av_malloc_array(n, sizeof(uint16_t)); i = 2; level = 1; k = 0; diff --git a/libavcodec/wmadec.c b/libavcodec/wmadec.c index e6a0b0477..466c1a9a1 100644 --- a/libavcodec/wmadec.c +++ b/libavcodec/wmadec.c @@ -100,6 +100,9 @@ static av_cold int wma_decode_init(AVCodecContext * avctx) } } + for (i=0; imax_exponent[i] = 1.0; + if(ff_wma_init(avctx, flags2)<0) return -1; @@ -924,7 +927,7 @@ 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", + av_dlog(s->avctx, "%d %d %d %d outbytes:%"PTRDIFF_SPECIFIER" 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); diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index f83ba9daa..8e2ac5ffc 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -22,6 +22,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/attributes.h" #include "libavutil/avassert.h" @@ -29,6 +31,7 @@ #include "internal.h" #include "get_bits.h" #include "put_bits.h" +#include "lossless_audiodsp.h" #include "wma.h" #include "wma_common.h" @@ -44,6 +47,7 @@ #define WMALL_BLOCK_MAX_SIZE (1 << WMALL_BLOCK_MAX_BITS) ///< maximum block size #define WMALL_BLOCK_SIZES (WMALL_BLOCK_MAX_BITS - WMALL_BLOCK_MIN_BITS + 1) ///< possible block sizes +#define WMALL_COEFF_PAD_SIZE 16 ///< pad coef buffers with 0 for use with SIMD /** * @brief frame-specific decoder context for a single channel @@ -67,6 +71,7 @@ typedef struct WmallDecodeCtx { /* generic decoder variables */ AVCodecContext *avctx; AVFrame *frame; + LLAudDSPContext dsp; ///< accelerated DSP functions uint8_t frame_data[MAX_FRAMESIZE + FF_INPUT_BUFFER_PADDING_SIZE]; ///< compressed frame data PutBitContext pb; ///< context for filling the frame_data buffer @@ -141,9 +146,9 @@ typedef struct WmallDecodeCtx { int scaling; int coefsend; int bitsend; - int16_t coefs[MAX_ORDER]; - int16_t lms_prevvalues[MAX_ORDER * 2]; - int16_t lms_updates[MAX_ORDER * 2]; + DECLARE_ALIGNED(16, int16_t, coefs)[MAX_ORDER + WMALL_COEFF_PAD_SIZE/sizeof(int16_t)]; + DECLARE_ALIGNED(16, int16_t, lms_prevvalues)[MAX_ORDER * 2]; + DECLARE_ALIGNED(16, int16_t, lms_updates)[MAX_ORDER * 2]; int recent; } cdlms[WMALL_MAX_CHANNELS][9]; @@ -184,6 +189,7 @@ static av_cold int decode_init(AVCodecContext *avctx) } s->avctx = avctx; + ff_llauddsp_init(&s->dsp); init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE); if (avctx->extradata_size >= 18) { @@ -197,7 +203,7 @@ static av_cold int decode_init(AVCodecContext *avctx) avpriv_report_missing_feature(avctx, "Bit-depth higher than 16"); return AVERROR_PATCHWELCOME; } else { - av_log(avctx, AV_LOG_ERROR, "Unknown bit-depth: %d\n", + av_log(avctx, AV_LOG_ERROR, "Unknown bit-depth: %"PRIu8"\n", s->bits_per_sample); return AVERROR_INVALIDDATA; } @@ -239,7 +245,7 @@ static av_cold int decode_init(AVCodecContext *avctx) s->bV3RTM = s->decode_flags & 0x100; if (s->max_num_subframes > MAX_SUBFRAMES) { - av_log(avctx, AV_LOG_ERROR, "invalid number of subframes %i\n", + av_log(avctx, AV_LOG_ERROR, "invalid number of subframes %"PRIu8"\n", s->max_num_subframes); return AVERROR_INVALIDDATA; } @@ -257,7 +263,7 @@ static av_cold int decode_init(AVCodecContext *avctx) } if (s->num_channels < 0) { - av_log(avctx, AV_LOG_ERROR, "invalid number of channels %d\n", + av_log(avctx, AV_LOG_ERROR, "invalid number of channels %"PRId8"\n", s->num_channels); return AVERROR_INVALIDDATA; } else if (s->num_channels > WMALL_MAX_CHANNELS) { @@ -382,7 +388,7 @@ static int decode_tilehdr(WmallDecodeCtx *s) ++chan->num_subframes; if (num_samples[c] > s->samples_per_frame) { av_log(s->avctx, AV_LOG_ERROR, "broken frame: " - "channel len(%d) > samples_per_frame(%d)\n", + "channel len(%"PRIu16") > samples_per_frame(%"PRIu16")\n", num_samples[c], s->samples_per_frame); return AVERROR_INVALIDDATA; } @@ -457,6 +463,13 @@ static int decode_cdlms(WmallDecodeCtx *s) s->cdlms[0][0].order = 0; return AVERROR_INVALIDDATA; } + if(s->cdlms[c][i].order & 8) { + static int warned; + if(!warned) + avpriv_request_sample(s->avctx, "CDLMS of order %d", + s->cdlms[c][i].order); + warned = 1; + } } for (i = 0; i < s->cdlms_ttl[c]; i++) @@ -482,6 +495,10 @@ static int decode_cdlms(WmallDecodeCtx *s) (get_bits(&s->gb, s->cdlms[c][i].bitsend) << shift_l) >> shift_r; } } + + for (i = 0; i < s->cdlms_ttl[c]; i++) + memset(s->cdlms[c][i].coefs + s->cdlms[c][i].order, + 0, WMALL_COEFF_PAD_SIZE); } return 0; @@ -691,35 +708,11 @@ static void revert_mclms(WmallDecodeCtx *s, int tile_size) } } -static int lms_predict(WmallDecodeCtx *s, int ich, int ilms) +static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int input) { - int pred = 0, icoef; - int recent = s->cdlms[ich][ilms].recent; - - for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) - pred += s->cdlms[ich][ilms].coefs[icoef] * - s->cdlms[ich][ilms].lms_prevvalues[icoef + recent]; - - return pred; -} - -static void lms_update(WmallDecodeCtx *s, int ich, int ilms, - int input, int residue) -{ - int icoef; int recent = s->cdlms[ich][ilms].recent; int range = 1 << s->bits_per_sample - 1; - if (residue < 0) { - for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) - s->cdlms[ich][ilms].coefs[icoef] -= - s->cdlms[ich][ilms].lms_updates[icoef + recent]; - } else if (residue > 0) { - for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) - s->cdlms[ich][ilms].coefs[icoef] += - s->cdlms[ich][ilms].lms_updates[icoef + recent]; - } - if (recent) recent--; else { @@ -780,6 +773,9 @@ static void use_normal_update_speed(WmallDecodeCtx *s, int ich) s->update_speed[ich] = 8; } +/** Get sign of integer (1 for positive, -1 for negative and 0 for zero) */ +#define WMASIGN(x) ((x > 0) - (x < 0)) + static void revert_cdlms(WmallDecodeCtx *s, int ch, int coef_begin, int coef_end) { @@ -790,12 +786,19 @@ static void revert_cdlms(WmallDecodeCtx *s, int ch, for (icoef = coef_begin; icoef < coef_end; icoef++) { pred = 1 << (s->cdlms[ch][ilms].scaling - 1); residue = s->channel_residues[ch][icoef]; - pred += lms_predict(s, ch, ilms); + pred += s->dsp.scalarproduct_and_madd_int16(s->cdlms[ch][ilms].coefs, + s->cdlms[ch][ilms].lms_prevvalues + + s->cdlms[ch][ilms].recent, + s->cdlms[ch][ilms].lms_updates + + s->cdlms[ch][ilms].recent, + s->cdlms[ch][ilms].order, + WMASIGN(residue)); input = residue + (pred >> s->cdlms[ch][ilms].scaling); - lms_update(s, ch, ilms, input, residue); + lms_update(s, ch, ilms, input); s->channel_residues[ch][icoef] = input; } } + emms_c(); } static void revert_inter_ch_decorr(WmallDecodeCtx *s, int tile_size) @@ -1094,7 +1097,8 @@ static int decode_frame(WmallDecodeCtx *s) if (len != (get_bits_count(gb) - s->frame_offset) + 2) { /* FIXME: not sure if this is always an error */ av_log(s->avctx, AV_LOG_ERROR, - "frame[%i] would have to skip %i bits\n", s->frame_num, + "frame[%"PRIu32"] would have to skip %i bits\n", + s->frame_num, len - (get_bits_count(gb) - s->frame_offset) - 1); s->packet_loss = 1; return 0; @@ -1213,7 +1217,8 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, if (!s->packet_loss && ((s->packet_sequence_number + 1) & 0xF) != packet_sequence_number) { s->packet_loss = 1; - av_log(avctx, AV_LOG_ERROR, "Packet loss detected! seq %x vs %x\n", + av_log(avctx, AV_LOG_ERROR, + "Packet loss detected! seq %"PRIx8" vs %x\n", s->packet_sequence_number, packet_sequence_number); } s->packet_sequence_number = packet_sequence_number; diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index d57c24ddd..2f6c48589 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -86,6 +86,8 @@ * subframe in order to reconstruct the output samples. */ +#include + #include "libavutil/float_dsp.h" #include "libavutil/intfloat.h" #include "libavutil/intreadwrite.h" @@ -237,7 +239,7 @@ typedef struct WMAProDecodeCtx { static av_cold void dump_context(WMAProDecodeCtx *s) { #define PRINT(a, b) av_log(s->avctx, AV_LOG_DEBUG, " %s = %d\n", a, b); -#define PRINT_HEX(a, b) av_log(s->avctx, AV_LOG_DEBUG, " %s = %x\n", a, b); +#define PRINT_HEX(a, b) av_log(s->avctx, AV_LOG_DEBUG, " %s = %"PRIx32"\n", a, b); PRINT("ed sample bit depth", s->bits_per_sample); PRINT_HEX("ed decode flags", s->decode_flags); @@ -336,7 +338,7 @@ static av_cold int decode_init(AVCodecContext *avctx) s->dynamic_range_compression = (s->decode_flags & 0x80); if (s->max_num_subframes > MAX_SUBFRAMES) { - av_log(avctx, AV_LOG_ERROR, "invalid number of subframes %i\n", + av_log(avctx, AV_LOG_ERROR, "invalid number of subframes %"PRId8"\n", s->max_num_subframes); return AVERROR_INVALIDDATA; } @@ -1421,7 +1423,8 @@ static int decode_frame(WMAProDecodeCtx *s, AVFrame *frame, int *got_frame_ptr) if (len != (get_bits_count(gb) - s->frame_offset) + 2) { /** FIXME: not sure if this is always an error */ av_log(s->avctx, AV_LOG_ERROR, - "frame[%i] would have to skip %i bits\n", s->frame_num, + "frame[%"PRIu32"] would have to skip %i bits\n", + s->frame_num, len - (get_bits_count(gb) - s->frame_offset) - 1); s->packet_loss = 1; return 0; @@ -1553,7 +1556,8 @@ static int decode_packet(AVCodecContext *avctx, void *data, if (!s->packet_loss && ((s->packet_sequence_number + 1) & 0xF) != packet_sequence_number) { s->packet_loss = 1; - av_log(avctx, AV_LOG_ERROR, "Packet loss detected! seq %x vs %x\n", + av_log(avctx, AV_LOG_ERROR, + "Packet loss detected! seq %"PRIx8" vs %x\n", s->packet_sequence_number, packet_sequence_number); } s->packet_sequence_number = packet_sequence_number; diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c index b8df6ca06..d53ba91db 100644 --- a/libavcodec/wmv2.c +++ b/libavcodec/wmv2.c @@ -19,6 +19,7 @@ */ #include "avcodec.h" +#include "idctdsp.h" #include "mpegvideo.h" #include "msmpeg4data.h" #include "simple_idct.h" @@ -28,25 +29,26 @@ 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); - s->dsp.idct_permutation_type = w->wdsp.idct_perm; - ff_init_scantable_permutation(s->dsp.idct_permutation, + s->idsp.idct_permutation_type = w->wdsp.idct_perm; + ff_init_scantable_permutation(s->idsp.idct_permutation, w->wdsp.idct_perm); - ff_init_scantable(s->dsp.idct_permutation, &w->abt_scantable[0], + ff_init_scantable(s->idsp.idct_permutation, &w->abt_scantable[0], ff_wmv2_scantableA); - ff_init_scantable(s->dsp.idct_permutation, &w->abt_scantable[1], + ff_init_scantable(s->idsp.idct_permutation, &w->abt_scantable[1], ff_wmv2_scantableB); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable, + ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_wmv1_scantable[1]); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, + ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_wmv1_scantable[2]); - ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, + ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_wmv1_scantable[3]); - ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable, + ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_wmv1_scantable[0]); - s->dsp.idct_put = w->wdsp.idct_put; - s->dsp.idct_add = w->wdsp.idct_add; - s->dsp.idct = NULL; + s->idsp.idct_put = w->wdsp.idct_put; + s->idsp.idct_add = w->wdsp.idct_add; + s->idsp.idct = NULL; } static void wmv2_add_block(Wmv2Context *w, int16_t *block1, uint8_t *dst, int stride, int n){ @@ -60,12 +62,12 @@ static void wmv2_add_block(Wmv2Context *w, int16_t *block1, uint8_t *dst, int st case 1: ff_simple_idct84_add(dst , stride, block1); ff_simple_idct84_add(dst + 4*stride, stride, w->abt_block2[n]); - s->dsp.clear_block(w->abt_block2[n]); + 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->dsp.clear_block(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"); @@ -129,28 +131,20 @@ void ff_mspel_motion(MpegEncContext *s, emu=1; } - s->dsp.put_mspel_pixels_tab[dxy](dest_y , ptr , linesize); - s->dsp.put_mspel_pixels_tab[dxy](dest_y+8 , ptr+8 , linesize); - s->dsp.put_mspel_pixels_tab[dxy](dest_y +8*linesize, ptr +8*linesize, linesize); - s->dsp.put_mspel_pixels_tab[dxy](dest_y+8+8*linesize, ptr+8+8*linesize, linesize); + w->wdsp.put_mspel_pixels_tab[dxy](dest_y, ptr, linesize); + w->wdsp.put_mspel_pixels_tab[dxy](dest_y + 8, ptr + 8, linesize); + 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->out_format == FMT_H263) { - dxy = 0; - if ((motion_x & 3) != 0) - dxy |= 1; - if ((motion_y & 3) != 0) - dxy |= 2; - mx = motion_x >> 2; - my = motion_y >> 2; - } else { - mx = motion_x / 2; - my = motion_y / 2; - dxy = ((my & 1) << 1) | (mx & 1); - mx >>= 1; - my >>= 1; - } + dxy = 0; + if ((motion_x & 3) != 0) + dxy |= 1; + if ((motion_y & 3) != 0) + dxy |= 2; + mx = motion_x >> 2; + my = motion_y >> 2; src_x = s->mb_x * 8 + mx; src_y = s->mb_y * 8 + my; diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c index 4f2a5e996..54ae165df 100644 --- a/libavcodec/wmv2dec.c +++ b/libavcodec/wmv2dec.c @@ -19,6 +19,7 @@ */ #include "avcodec.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "h263.h" #include "mathops.h" @@ -384,7 +385,7 @@ int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) wmv2_pred_motion(w, &mx, &my); if(cbp){ - s->dsp.clear_blocks(s->block[0]); + s->bdsp.clear_blocks(s->block[0]); if(s->per_mb_rl_table){ s->rl_table_index = decode012(&s->gb); s->rl_chroma_table_index = s->rl_table_index; @@ -430,7 +431,7 @@ int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) s->rl_chroma_table_index = s->rl_table_index; } - s->dsp.clear_blocks(s->block[0]); + 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) { @@ -476,5 +477,8 @@ AVCodec ff_wmv2_decoder = { .close = wmv2_decode_end, .decode = ff_h263_decode_frame, .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, - .pix_fmts = ff_pixfmt_list_420, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE + }, }; diff --git a/libavcodec/wmv2dsp.c b/libavcodec/wmv2dsp.c index 9627442b3..511cc548e 100644 --- a/libavcodec/wmv2dsp.c +++ b/libavcodec/wmv2dsp.c @@ -19,7 +19,8 @@ #include "libavutil/attributes.h" #include "libavutil/common.h" #include "avcodec.h" -#include "dsputil.h" +#include "idctdsp.h" +#include "mathops.h" #include "wmv2dsp.h" #define W0 2048 @@ -138,9 +139,127 @@ static void wmv2_idct_put_c(uint8_t *dest, int line_size, int16_t *block) } } +static void wmv2_mspel8_h_lowpass(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, int h) +{ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; + int i; + + for (i = 0; i < h; i++) { + dst[0] = cm[(9 * (src[0] + src[1]) - (src[-1] + src[2]) + 8) >> 4]; + dst[1] = cm[(9 * (src[1] + src[2]) - (src[0] + src[3]) + 8) >> 4]; + dst[2] = cm[(9 * (src[2] + src[3]) - (src[1] + src[4]) + 8) >> 4]; + dst[3] = cm[(9 * (src[3] + src[4]) - (src[2] + src[5]) + 8) >> 4]; + dst[4] = cm[(9 * (src[4] + src[5]) - (src[3] + src[6]) + 8) >> 4]; + dst[5] = cm[(9 * (src[5] + src[6]) - (src[4] + src[7]) + 8) >> 4]; + dst[6] = cm[(9 * (src[6] + src[7]) - (src[5] + src[8]) + 8) >> 4]; + dst[7] = cm[(9 * (src[7] + src[8]) - (src[6] + src[9]) + 8) >> 4]; + dst += dstStride; + src += srcStride; + } +} + +static void wmv2_mspel8_v_lowpass(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, int w) +{ + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; + int i; + + for (i = 0; i < w; i++) { + const int src_1 = src[-srcStride]; + const int src0 = src[0]; + const int src1 = src[srcStride]; + const int src2 = src[2 * srcStride]; + const int src3 = src[3 * srcStride]; + const int src4 = src[4 * srcStride]; + const int src5 = src[5 * srcStride]; + const int src6 = src[6 * srcStride]; + const int src7 = src[7 * srcStride]; + const int src8 = src[8 * srcStride]; + const int src9 = src[9 * srcStride]; + dst[0 * dstStride] = cm[(9 * (src0 + src1) - (src_1 + src2) + 8) >> 4]; + dst[1 * dstStride] = cm[(9 * (src1 + src2) - (src0 + src3) + 8) >> 4]; + dst[2 * dstStride] = cm[(9 * (src2 + src3) - (src1 + src4) + 8) >> 4]; + dst[3 * dstStride] = cm[(9 * (src3 + src4) - (src2 + src5) + 8) >> 4]; + dst[4 * dstStride] = cm[(9 * (src4 + src5) - (src3 + src6) + 8) >> 4]; + dst[5 * dstStride] = cm[(9 * (src5 + src6) - (src4 + src7) + 8) >> 4]; + dst[6 * dstStride] = cm[(9 * (src6 + src7) - (src5 + src8) + 8) >> 4]; + dst[7 * dstStride] = cm[(9 * (src7 + src8) - (src6 + src9) + 8) >> 4]; + src++; + dst++; + } +} + +static void put_mspel8_mc10_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + uint8_t half[64]; + + wmv2_mspel8_h_lowpass(half, src, 8, stride, 8); + ff_put_pixels8_l2_8(dst, src, half, stride, stride, 8, 8); +} + +static void put_mspel8_mc20_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + wmv2_mspel8_h_lowpass(dst, src, stride, stride, 8); +} + +static void put_mspel8_mc30_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + uint8_t half[64]; + + wmv2_mspel8_h_lowpass(half, src, 8, stride, 8); + ff_put_pixels8_l2_8(dst, src + 1, half, stride, stride, 8, 8); +} + +static void put_mspel8_mc02_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + wmv2_mspel8_v_lowpass(dst, src, stride, stride, 8); +} + +static void put_mspel8_mc12_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + uint8_t halfH[88]; + uint8_t halfV[64]; + uint8_t halfHV[64]; + + wmv2_mspel8_h_lowpass(halfH, src - stride, 8, stride, 11); + wmv2_mspel8_v_lowpass(halfV, src, 8, stride, 8); + wmv2_mspel8_v_lowpass(halfHV, halfH + 8, 8, 8, 8); + ff_put_pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8); +} + +static void put_mspel8_mc32_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + uint8_t halfH[88]; + uint8_t halfV[64]; + uint8_t halfHV[64]; + + wmv2_mspel8_h_lowpass(halfH, src - stride, 8, stride, 11); + wmv2_mspel8_v_lowpass(halfV, src + 1, 8, stride, 8); + wmv2_mspel8_v_lowpass(halfHV, halfH + 8, 8, 8, 8); + ff_put_pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8); +} + +static void put_mspel8_mc22_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + uint8_t halfH[88]; + + wmv2_mspel8_h_lowpass(halfH, src - stride, 8, stride, 11); + wmv2_mspel8_v_lowpass(dst, halfH + 8, stride, 8, 8); +} + av_cold void ff_wmv2dsp_init(WMV2DSPContext *c) { c->idct_add = wmv2_idct_add_c; c->idct_put = wmv2_idct_put_c; c->idct_perm = FF_NO_IDCT_PERM; + + c->put_mspel_pixels_tab[0] = ff_put_pixels8x8_c; + c->put_mspel_pixels_tab[1] = put_mspel8_mc10_c; + c->put_mspel_pixels_tab[2] = put_mspel8_mc20_c; + c->put_mspel_pixels_tab[3] = put_mspel8_mc30_c; + c->put_mspel_pixels_tab[4] = put_mspel8_mc02_c; + c->put_mspel_pixels_tab[5] = put_mspel8_mc12_c; + c->put_mspel_pixels_tab[6] = put_mspel8_mc22_c; + c->put_mspel_pixels_tab[7] = put_mspel8_mc32_c; } diff --git a/libavcodec/wmv2dsp.h b/libavcodec/wmv2dsp.h index 37bee205a..0bf9489b0 100644 --- a/libavcodec/wmv2dsp.h +++ b/libavcodec/wmv2dsp.h @@ -21,10 +21,14 @@ #include +#include "qpeldsp.h" + typedef struct WMV2DSPContext { void (*idct_add)(uint8_t *dest, int line_size, int16_t *block); void (*idct_put)(uint8_t *dest, int line_size, int16_t *block); + qpel_mc_func put_mspel_pixels_tab[8]; + int idct_perm; } WMV2DSPContext; diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c index 6aeee59ab..869b3c7fe 100644 --- a/libavcodec/wmv2enc.c +++ b/libavcodec/wmv2enc.c @@ -60,7 +60,9 @@ static av_cold int wmv2_encode_init(AVCodecContext *avctx){ ff_wmv2_common_init(w); avctx->extradata_size= 4; - avctx->extradata= av_mallocz(avctx->extradata_size + 10); + avctx->extradata= av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) + return AVERROR(ENOMEM); encode_ext_header(w); return 0; diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile index 0d3594f7c..546513bfa 100644 --- a/libavcodec/x86/Makefile +++ b/libavcodec/x86/Makefile @@ -1,17 +1,14 @@ OBJS += x86/constants.o \ x86/fmtconvert_init.o \ -OBJS-$(CONFIG_AAC_DECODER) += x86/sbrdsp_init.o OBJS-$(CONFIG_AC3DSP) += x86/ac3dsp_init.o -OBJS-$(CONFIG_CAVS_DECODER) += x86/cavsdsp.o -OBJS-$(CONFIG_DCA_DECODER) += x86/dcadsp_init.o +OBJS-$(CONFIG_AUDIODSP) += x86/audiodsp_init.o +OBJS-$(CONFIG_BLOCKDSP) += x86/blockdsp_init.o +OBJS-$(CONFIG_BSWAPDSP) += x86/bswapdsp_init.o OBJS-$(CONFIG_DCT) += x86/dct_init.o -OBJS-$(CONFIG_DNXHD_ENCODER) += x86/dnxhdenc.o OBJS-$(CONFIG_DSPUTIL) += x86/dsputil_init.o \ - x86/dsputil_x86.o -OBJS-$(CONFIG_ENCODERS) += x86/dsputilenc_mmx.o \ - x86/fdct.o \ x86/motion_est.o +OBJS-$(CONFIG_FDCTDSP) += x86/fdctdsp_init.o OBJS-$(CONFIG_FFT) += x86/fft_init.o OBJS-$(CONFIG_FLAC_DECODER) += x86/flacdsp_init.o OBJS-$(CONFIG_FLAC_ENCODER) += x86/flacdsp_init.o @@ -20,42 +17,55 @@ OBJS-$(CONFIG_H264CHROMA) += x86/h264chroma_init.o OBJS-$(CONFIG_H264DSP) += x86/h264dsp_init.o OBJS-$(CONFIG_H264PRED) += x86/h264_intrapred_init.o OBJS-$(CONFIG_H264QPEL) += x86/h264_qpel.o +OBJS-$(CONFIG_HEVC_DECODER) += x86/hevcdsp_init.o OBJS-$(CONFIG_HPELDSP) += x86/hpeldsp_init.o +OBJS-$(CONFIG_LLAUDDSP) += x86/lossless_audiodsp_init.o OBJS-$(CONFIG_LLVIDDSP) += x86/lossless_videodsp_init.o +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_MLP_DECODER) += x86/mlpdsp.o OBJS-$(CONFIG_MPEGAUDIODSP) += x86/mpegaudiodsp.o -OBJS-$(CONFIG_MPEGVIDEO) += x86/mpegvideo.o -OBJS-$(CONFIG_MPEGVIDEOENC) += x86/mpegvideoenc.o +OBJS-$(CONFIG_MPEGVIDEO) += x86/mpegvideo.o \ + x86/mpegvideodsp.o +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_VIDEODSP) += x86/videodsp_init.o +OBJS-$(CONFIG_VP3DSP) += x86/vp3dsp_init.o +OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o + +OBJS-$(CONFIG_AAC_DECODER) += x86/sbrdsp_init.o +OBJS-$(CONFIG_CAVS_DECODER) += x86/cavsdsp.o +OBJS-$(CONFIG_DCA_DECODER) += x86/dcadsp_init.o +OBJS-$(CONFIG_DNXHD_ENCODER) += x86/dnxhdenc_init.o +OBJS-$(CONFIG_MLP_DECODER) += x86/mlpdsp.o OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp_init.o OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp_init.o OBJS-$(CONFIG_PRORES_LGPL_DECODER) += x86/proresdsp_init.o OBJS-$(CONFIG_RV30_DECODER) += x86/rv34dsp_init.o OBJS-$(CONFIG_RV40_DECODER) += x86/rv34dsp_init.o \ x86/rv40dsp_init.o +OBJS-$(CONFIG_SVQ1_ENCODER) += x86/svq1enc_init.o OBJS-$(CONFIG_V210_DECODER) += x86/v210-init.o OBJS-$(CONFIG_TTA_DECODER) += x86/ttadsp_init.o OBJS-$(CONFIG_TRUEHD_DECODER) += x86/mlpdsp.o OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp_init.o -OBJS-$(CONFIG_VIDEODSP) += x86/videodsp_init.o OBJS-$(CONFIG_VORBIS_DECODER) += x86/vorbisdsp_init.o -OBJS-$(CONFIG_VP3DSP) += x86/vp3dsp_init.o OBJS-$(CONFIG_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 OBJS-$(CONFIG_WEBP_DECODER) += x86/vp8dsp_init.o -OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o -MMX-OBJS-$(CONFIG_DSPUTIL) += x86/dsputil_mmx.o \ - x86/fpel_mmx.o \ +MMX-OBJS-$(CONFIG_DIRAC_DECODER) += x86/dirac_dwt.o +MMX-OBJS-$(CONFIG_FDCTDSP) += x86/fdct.o +MMX-OBJS-$(CONFIG_IDCTDSP) += x86/idctdsp_mmx.o \ x86/idct_mmx_xvid.o \ x86/idct_sse2_xvid.o \ - x86/rnd_mmx.o \ x86/simple_idct.o -MMX-OBJS-$(CONFIG_DIRAC_DECODER) += x86/dirac_dwt.o -MMX-OBJS-$(CONFIG_HPELDSP) += x86/fpel_mmx.o \ - x86/hpeldsp_mmx.o \ - x86/rnd_mmx.o + MMX-OBJS-$(CONFIG_SNOW_DECODER) += x86/snowdsp.o MMX-OBJS-$(CONFIG_SNOW_ENCODER) += x86/snowdsp.o MMX-OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp_mmx.o @@ -63,17 +73,15 @@ MMX-OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp_mmx.o YASM-OBJS += x86/deinterlace.o \ x86/fmtconvert.o \ -YASM-OBJS-$(CONFIG_AAC_DECODER) += x86/sbrdsp.o YASM-OBJS-$(CONFIG_AC3DSP) += x86/ac3dsp.o -YASM-OBJS-$(CONFIG_DCA_DECODER) += x86/dcadsp.o +YASM-OBJS-$(CONFIG_AUDIODSP) += x86/audiodsp.o +YASM-OBJS-$(CONFIG_BLOCKDSP) += x86/blockdsp.o +YASM-OBJS-$(CONFIG_BSWAPDSP) += x86/bswapdsp.o YASM-OBJS-$(CONFIG_DCT) += x86/dct32.o YASM-OBJS-$(CONFIG_DIRAC_DECODER) += x86/diracdsp_mmx.o x86/diracdsp_yasm.o\ x86/dwt_yasm.o -YASM-OBJS-$(CONFIG_DSPUTIL) += x86/dsputil.o \ - x86/fpel.o \ - x86/mpeg4qpel.o \ - x86/qpel.o -YASM-OBJS-$(CONFIG_ENCODERS) += x86/dsputilenc.o +YASM-OBJS-$(CONFIG_DNXHD_ENCODER) += x86/dnxhdenc.o +YASM-OBJS-$(CONFIG_DSPUTIL) += x86/dsputilenc.o YASM-OBJS-$(CONFIG_FFT) += x86/fft.o YASM-OBJS-$(CONFIG_FLAC_DECODER) += x86/flacdsp.o YASM-OBJS-$(CONFIG_H263DSP) += x86/h263_loopfilter.o @@ -91,23 +99,40 @@ YASM-OBJS-$(CONFIG_H264QPEL) += x86/h264_qpel_8bit.o \ x86/h264_qpel_10bit.o \ x86/fpel.o \ x86/qpel.o +YASM-OBJS-$(CONFIG_HEVC_DECODER) += x86/hevc_mc.o \ + x86/hevc_deblock.o \ + x86/hevc_idct.o YASM-OBJS-$(CONFIG_HPELDSP) += x86/fpel.o \ x86/hpeldsp.o +YASM-OBJS-$(CONFIG_HUFFYUVDSP) += x86/huffyuvdsp.o +YASM-OBJS-$(CONFIG_IDCTDSP) += x86/idctdsp.o +YASM-OBJS-$(CONFIG_LLAUDDSP) += x86/lossless_audiodsp.o YASM-OBJS-$(CONFIG_LLVIDDSP) += x86/lossless_videodsp.o YASM-OBJS-$(CONFIG_MPEGAUDIODSP) += x86/imdct36.o +YASM-OBJS-$(CONFIG_MPEGVIDEOENC) += x86/mpegvideoencdsp.o +YASM-OBJS-$(CONFIG_PIXBLOCKDSP) += x86/pixblockdsp.o +YASM-OBJS-$(CONFIG_QPELDSP) += x86/qpeldsp.o \ + x86/fpel.o \ + x86/qpel.o +YASM-OBJS-$(CONFIG_VIDEODSP) += x86/videodsp.o +YASM-OBJS-$(CONFIG_VP3DSP) += x86/vp3dsp.o + +YASM-OBJS-$(CONFIG_AAC_DECODER) += x86/sbrdsp.o +YASM-OBJS-$(CONFIG_DCA_DECODER) += x86/dcadsp.o YASM-OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp.o YASM-OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp.o YASM-OBJS-$(CONFIG_PRORES_LGPL_DECODER) += x86/proresdsp.o YASM-OBJS-$(CONFIG_RV30_DECODER) += x86/rv34dsp.o YASM-OBJS-$(CONFIG_RV40_DECODER) += x86/rv34dsp.o \ x86/rv40dsp.o +YASM-OBJS-$(CONFIG_SVQ1_ENCODER) += x86/svq1enc.o YASM-OBJS-$(CONFIG_TTA_DECODER) += x86/ttadsp.o YASM-OBJS-$(CONFIG_V210_DECODER) += x86/v210.o YASM-OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp.o -YASM-OBJS-$(CONFIG_VIDEODSP) += x86/videodsp.o YASM-OBJS-$(CONFIG_VORBIS_DECODER) += x86/vorbisdsp.o -YASM-OBJS-$(CONFIG_VP3DSP) += x86/vp3dsp.o YASM-OBJS-$(CONFIG_VP6_DECODER) += x86/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/vp9intrapred.o \ diff --git a/libavcodec/x86/ac3dsp.asm b/libavcodec/x86/ac3dsp.asm index 89a64f50d..b24441614 100644 --- a/libavcodec/x86/ac3dsp.asm +++ b/libavcodec/x86/ac3dsp.asm @@ -1,5 +1,5 @@ ;***************************************************************************** -;* x86-optimized AC-3 DSP utils +;* x86-optimized AC-3 DSP functions ;* Copyright (c) 2011 Justin Ruggles ;* ;* This file is part of FFmpeg. @@ -35,6 +35,10 @@ pw_bap_mul2: dw 5, 7, 0, 7, 5, 7, 0, 7 pd_1: times 4 dd 1 pd_151: times 4 dd 151 +; used in ff_apply_window_int16() +pb_revwords: SHUFFLE_MASK_W 7, 6, 5, 4, 3, 2, 1, 0 +pd_16384: times 4 dd 16384 + SECTION .text ;----------------------------------------------------------------------------- @@ -419,3 +423,130 @@ AC3_EXTRACT_EXPONENTS INIT_XMM ssse3 AC3_EXTRACT_EXPONENTS %endif + +;----------------------------------------------------------------------------- +; void ff_apply_window_int16(int16_t *output, const int16_t *input, +; const int16_t *window, unsigned int len) +;----------------------------------------------------------------------------- + +%macro REVERSE_WORDS 1-2 +%if cpuflag(ssse3) && notcpuflag(atom) + pshufb %1, %2 +%elif cpuflag(sse2) + pshuflw %1, %1, 0x1B + pshufhw %1, %1, 0x1B + pshufd %1, %1, 0x4E +%elif cpuflag(mmxext) + pshufw %1, %1, 0x1B +%endif +%endmacro + +%macro MUL16FIXED 3 +%if cpuflag(ssse3) ; dst, src, unused +; dst = ((dst * src) + (1<<14)) >> 15 + pmulhrsw %1, %2 +%elif cpuflag(mmxext) ; dst, src, temp +; dst = (dst * src) >> 15 +; pmulhw cuts off the bottom bit, so we have to lshift by 1 and add it back +; in from the pmullw result. + mova %3, %1 + pmulhw %1, %2 + pmullw %3, %2 + psrlw %3, 15 + psllw %1, 1 + por %1, %3 +%endif +%endmacro + +%macro APPLY_WINDOW_INT16 1 ; %1 bitexact version +%if %1 +cglobal apply_window_int16, 4,5,6, output, input, window, offset, offset2 +%else +cglobal apply_window_int16_round, 4,5,6, output, input, window, offset, offset2 +%endif + lea offset2q, [offsetq-mmsize] +%if cpuflag(ssse3) && notcpuflag(atom) + mova m5, [pb_revwords] + ALIGN 16 +%elif %1 + mova m5, [pd_16384] +%endif +.loop: +%if cpuflag(ssse3) + ; This version does the 16x16->16 multiplication in-place without expanding + ; to 32-bit. The ssse3 version is bit-identical. + mova m0, [windowq+offset2q] + mova m1, [ inputq+offset2q] + pmulhrsw m1, m0 + REVERSE_WORDS m0, m5 + pmulhrsw m0, [ inputq+offsetq ] + mova [outputq+offset2q], m1 + mova [outputq+offsetq ], m0 +%elif %1 + ; This version expands 16-bit to 32-bit, multiplies by the window, + ; adds 16384 for rounding, right shifts 15, then repacks back to words to + ; save to the output. The window is reversed for the second half. + mova m3, [windowq+offset2q] + mova m4, [ inputq+offset2q] + pxor m0, m0 + punpcklwd m0, m3 + punpcklwd m1, m4 + pmaddwd m0, m1 + paddd m0, m5 + psrad m0, 15 + pxor m2, m2 + punpckhwd m2, m3 + punpckhwd m1, m4 + pmaddwd m2, m1 + paddd m2, m5 + psrad m2, 15 + packssdw m0, m2 + mova [outputq+offset2q], m0 + REVERSE_WORDS m3 + mova m4, [ inputq+offsetq] + pxor m0, m0 + punpcklwd m0, m3 + punpcklwd m1, m4 + pmaddwd m0, m1 + paddd m0, m5 + psrad m0, 15 + pxor m2, m2 + punpckhwd m2, m3 + punpckhwd m1, m4 + pmaddwd m2, m1 + paddd m2, m5 + psrad m2, 15 + packssdw m0, m2 + mova [outputq+offsetq], m0 +%else + ; This version does the 16x16->16 multiplication in-place without expanding + ; to 32-bit. The mmxext and sse2 versions do not use rounding, and + ; therefore are not bit-identical to the C version. + mova m0, [windowq+offset2q] + mova m1, [ inputq+offset2q] + mova m2, [ inputq+offsetq ] + MUL16FIXED m1, m0, m3 + REVERSE_WORDS m0 + MUL16FIXED m2, m0, m3 + mova [outputq+offset2q], m1 + mova [outputq+offsetq ], m2 +%endif + add offsetd, mmsize + sub offset2d, mmsize + jae .loop + REP_RET +%endmacro + +INIT_MMX mmxext +APPLY_WINDOW_INT16 0 +INIT_XMM sse2 +APPLY_WINDOW_INT16 0 + +INIT_MMX mmxext +APPLY_WINDOW_INT16 1 +INIT_XMM sse2 +APPLY_WINDOW_INT16 1 +INIT_XMM ssse3 +APPLY_WINDOW_INT16 1 +INIT_XMM ssse3, atom +APPLY_WINDOW_INT16 1 diff --git a/libavcodec/x86/ac3dsp_init.c b/libavcodec/x86/ac3dsp_init.c index 388fc0c69..30a85f996 100644 --- a/libavcodec/x86/ac3dsp_init.c +++ b/libavcodec/x86/ac3dsp_init.c @@ -1,5 +1,5 @@ /* - * x86-optimized AC-3 DSP utils + * x86-optimized AC-3 DSP functions * Copyright (c) 2011 Justin Ruggles * * This file is part of FFmpeg. @@ -23,7 +23,6 @@ #include "libavutil/mem.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" -#include "dsputil_x86.h" #include "libavcodec/ac3.h" #include "libavcodec/ac3dsp.h" diff --git a/libavcodec/x86/audiodsp.asm b/libavcodec/x86/audiodsp.asm new file mode 100644 index 000000000..273b9ef66 --- /dev/null +++ b/libavcodec/x86/audiodsp.asm @@ -0,0 +1,177 @@ +;****************************************************************************** +;* optimized audio functions +;* Copyright (c) 2008 Loren Merritt +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_TEXT + +%macro 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 v1q, orderq + add v2q, orderq + neg orderq + pxor m2, m2 +.loop: + movu m0, [v1q + orderq] + movu m1, [v1q + orderq + mmsize] + pmaddwd m0, [v2q + orderq] + pmaddwd m1, [v2q + orderq + mmsize] + paddd m2, m0 + paddd m2, m1 + add orderq, mmsize*2 + jl .loop + HADDD m2, m0 + movd eax, m2 +%if mmsize == 8 + emms +%endif + RET +%endmacro + +INIT_MMX mmxext +SCALARPRODUCT +INIT_XMM sse2 +SCALARPRODUCT + + +;----------------------------------------------------------------------------- +; void ff_vector_clip_int32(int32_t *dst, const int32_t *src, int32_t min, +; int32_t max, unsigned int len) +;----------------------------------------------------------------------------- + +; %1 = number of xmm registers used +; %2 = number of inline load/process/store loops per asm loop +; %3 = process 4*mmsize (%3=0) or 8*mmsize (%3=1) bytes per loop +; %4 = CLIPD function takes min/max as float instead of int (CLIPD_SSE2) +; %5 = suffix +%macro VECTOR_CLIP_INT32 4-5 +cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len +%if %4 + cvtsi2ss m4, minm + cvtsi2ss m5, maxm +%else + movd m4, minm + movd m5, maxm +%endif + SPLATD m4 + SPLATD m5 +.loop: +%assign %%i 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)] +%if %3 + mova m7, [srcq+mmsize*(4+%%i)] + mova m8, [srcq+mmsize*(5+%%i)] + mova m9, [srcq+mmsize*(6+%%i)] + mova m10, [srcq+mmsize*(7+%%i)] +%endif + CLIPD m0, m4, m5, m6 + CLIPD m1, m4, m5, m6 + CLIPD m2, m4, m5, m6 + CLIPD m3, m4, m5, m6 +%if %3 + CLIPD m7, m4, m5, m6 + CLIPD m8, m4, m5, m6 + CLIPD m9, m4, m5, m6 + CLIPD m10, m4, m5, m6 +%endif + mova [dstq+mmsize*(0+%%i)], m0 + mova [dstq+mmsize*(1+%%i)], m1 + mova [dstq+mmsize*(2+%%i)], m2 + mova [dstq+mmsize*(3+%%i)], m3 +%if %3 + mova [dstq+mmsize*(4+%%i)], m7 + mova [dstq+mmsize*(5+%%i)], m8 + mova [dstq+mmsize*(6+%%i)], m9 + mova [dstq+mmsize*(7+%%i)], m10 +%endif +%assign %%i %%i+4*(%3+1) +%endrep + add srcq, mmsize*4*(%2+%3) + add dstq, mmsize*4*(%2+%3) + sub lend, mmsize*(%2+%3) + jg .loop + REP_RET +%endmacro + +INIT_MMX mmx +%define CLIPD CLIPD_MMX +VECTOR_CLIP_INT32 0, 1, 0, 0 +INIT_XMM sse2 +VECTOR_CLIP_INT32 6, 1, 0, 0, _int +%define CLIPD CLIPD_SSE2 +VECTOR_CLIP_INT32 6, 2, 0, 1 +INIT_XMM sse4 +%define CLIPD CLIPD_SSE41 +%ifdef m8 +VECTOR_CLIP_INT32 11, 1, 1, 0 +%else +VECTOR_CLIP_INT32 6, 1, 0, 0 +%endif + +;----------------------------------------------------- +;void ff_vector_clipf(float *dst, const float *src, +; float min, float max, int len) +;----------------------------------------------------- +INIT_XMM sse +%if UNIX64 +cglobal vector_clipf, 3,3,6, dst, src, len +%else +cglobal vector_clipf, 5,5,6, dst, src, min, max, len +%endif +%if WIN64 + SWAP 0, 2 + SWAP 1, 3 +%elif ARCH_X86_32 + movss m0, minm + movss m1, maxm +%endif + SPLATD m0 + SPLATD m1 + shl lend, 2 + add srcq, lenq + add dstq, lenq + neg lenq +.loop: + mova m2, [srcq+lenq+mmsize*0] + mova m3, [srcq+lenq+mmsize*1] + mova m4, [srcq+lenq+mmsize*2] + mova m5, [srcq+lenq+mmsize*3] + maxps m2, m0 + maxps m3, m0 + maxps m4, m0 + maxps m5, m0 + minps m2, m1 + minps m3, m1 + minps m4, m1 + minps m5, m1 + mova [dstq+lenq+mmsize*0], m2 + mova [dstq+lenq+mmsize*1], m3 + mova [dstq+lenq+mmsize*2], m4 + mova [dstq+lenq+mmsize*3], m5 + add lenq, mmsize*4 + jl .loop + REP_RET diff --git a/libavcodec/x86/audiodsp_init.c b/libavcodec/x86/audiodsp_init.c new file mode 100644 index 000000000..a2ce231f3 --- /dev/null +++ b/libavcodec/x86/audiodsp_init.c @@ -0,0 +1,67 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/audiodsp.h" + +int32_t ff_scalarproduct_int16_mmxext(const int16_t *v1, const int16_t *v2, + int order); +int32_t ff_scalarproduct_int16_sse2(const int16_t *v1, const int16_t *v2, + int order); + +void ff_vector_clip_int32_mmx(int32_t *dst, const int32_t *src, + int32_t min, int32_t max, unsigned int len); +void ff_vector_clip_int32_sse2(int32_t *dst, const int32_t *src, + int32_t min, int32_t max, unsigned int len); +void ff_vector_clip_int32_int_sse2(int32_t *dst, const int32_t *src, + int32_t min, int32_t max, unsigned int len); +void ff_vector_clip_int32_sse4(int32_t *dst, const int32_t *src, + int32_t min, int32_t max, unsigned int len); +void ff_vector_clipf_sse(float *dst, const float *src, + float min, float max, int len); + +av_cold void ff_audiodsp_init_x86(AudioDSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_MMX(cpu_flags)) + c->vector_clip_int32 = ff_vector_clip_int32_mmx; + + if (EXTERNAL_MMXEXT(cpu_flags)) + c->scalarproduct_int16 = ff_scalarproduct_int16_mmxext; + + if (EXTERNAL_SSE(cpu_flags)) + c->vector_clipf = ff_vector_clipf_sse; + + if (EXTERNAL_SSE2(cpu_flags)) { + c->scalarproduct_int16 = ff_scalarproduct_int16_sse2; + if (cpu_flags & AV_CPU_FLAG_ATOM) + c->vector_clip_int32 = ff_vector_clip_int32_int_sse2; + else + c->vector_clip_int32 = ff_vector_clip_int32_sse2; + } + + if (EXTERNAL_SSE4(cpu_flags)) + c->vector_clip_int32 = ff_vector_clip_int32_sse4; +} diff --git a/libavcodec/x86/blockdsp.asm b/libavcodec/x86/blockdsp.asm new file mode 100644 index 000000000..c79385886 --- /dev/null +++ b/libavcodec/x86/blockdsp.asm @@ -0,0 +1,86 @@ +;****************************************************************************** +;* SIMD-optimized clear block functions +;* Copyright (c) 2002 Michael Niedermayer +;* Copyright (c) 2008 Loren Merritt +;* Copyright (c) 2009 Fiona Glaser +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_TEXT + +;---------------------------------------- +; void ff_clear_block(int16_t *blocks); +;---------------------------------------- +; %1 = number of xmm registers used +; %2 = number of inline store loops +%macro CLEAR_BLOCK 2 +cglobal clear_block, 1, 1, %1, blocks + ZERO m0, m0 +%assign %%i 0 +%rep %2 + mova [blocksq+mmsize*(0+%%i)], m0 + mova [blocksq+mmsize*(1+%%i)], m0 + mova [blocksq+mmsize*(2+%%i)], m0 + mova [blocksq+mmsize*(3+%%i)], m0 + mova [blocksq+mmsize*(4+%%i)], m0 + mova [blocksq+mmsize*(5+%%i)], m0 + mova [blocksq+mmsize*(6+%%i)], m0 + mova [blocksq+mmsize*(7+%%i)], m0 +%assign %%i %%i+8 +%endrep + RET +%endmacro + +INIT_MMX mmx +%define ZERO pxor +CLEAR_BLOCK 0, 2 +INIT_XMM sse +%define ZERO xorps +CLEAR_BLOCK 1, 1 + +;----------------------------------------- +; void ff_clear_blocks(int16_t *blocks); +;----------------------------------------- +; %1 = number of xmm registers used +%macro CLEAR_BLOCKS 1 +cglobal clear_blocks, 1, 2, %1, blocks, len + add blocksq, 768 + mov lenq, -768 + ZERO m0, m0 +.loop + mova [blocksq+lenq+mmsize*0], m0 + mova [blocksq+lenq+mmsize*1], m0 + mova [blocksq+lenq+mmsize*2], m0 + mova [blocksq+lenq+mmsize*3], m0 + mova [blocksq+lenq+mmsize*4], m0 + mova [blocksq+lenq+mmsize*5], m0 + mova [blocksq+lenq+mmsize*6], m0 + mova [blocksq+lenq+mmsize*7], m0 + add lenq, mmsize*8 + js .loop + RET +%endmacro + +INIT_MMX mmx +%define ZERO pxor +CLEAR_BLOCKS 0 +INIT_XMM sse +%define ZERO xorps +CLEAR_BLOCKS 1 diff --git a/libavcodec/x86/blockdsp_init.c b/libavcodec/x86/blockdsp_init.c new file mode 100644 index 000000000..7780184af --- /dev/null +++ b/libavcodec/x86/blockdsp_init.c @@ -0,0 +1,60 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/internal.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/blockdsp.h" +#include "libavcodec/version.h" + +void ff_clear_block_mmx(int16_t *block); +void ff_clear_block_sse(int16_t *block); +void ff_clear_blocks_mmx(int16_t *blocks); +void ff_clear_blocks_sse(int16_t *blocks); + +#if FF_API_XVMC +av_cold void ff_blockdsp_init_x86(BlockDSPContext *c, unsigned high_bit_depth, + AVCodecContext *avctx) +#else +av_cold void ff_blockdsp_init_x86(BlockDSPContext *c, unsigned high_bit_depth) +#endif /* FF_API_XVMC */ +{ +#if HAVE_YASM + int cpu_flags = av_get_cpu_flags(); + + if (!high_bit_depth) { + if (EXTERNAL_MMX(cpu_flags)) { + c->clear_block = ff_clear_block_mmx; + c->clear_blocks = ff_clear_blocks_mmx; + } + + /* XvMCCreateBlocks() may not allocate 16-byte aligned blocks */ + if (CONFIG_XVMC && avctx->hwaccel && avctx->hwaccel->decode_mb) + return; + + if (EXTERNAL_SSE(cpu_flags)) { + c->clear_block = ff_clear_block_sse; + c->clear_blocks = ff_clear_blocks_sse; + } + } +#endif /* HAVE_YASM */ +} diff --git a/libavcodec/x86/bswapdsp.asm b/libavcodec/x86/bswapdsp.asm new file mode 100644 index 000000000..ec060c93b --- /dev/null +++ b/libavcodec/x86/bswapdsp.asm @@ -0,0 +1,140 @@ +;****************************************************************************** +;* optimized bswap buffer functions +;* Copyright (c) 2008 Loren Merritt +;* Copyright (c) 2003-2013 Michael Niedermayer +;* Copyright (c) 2013 Daniel Kang +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA +pb_bswap32: db 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 + +cextern pb_80 + +SECTION_TEXT + +; %1 = aligned/unaligned +%macro BSWAP_LOOPS 1 + mov r3, r2 + sar r2, 3 + jz .left4_%1 +.loop8_%1: + mov%1 m0, [r1 + 0] + mov%1 m1, [r1 + 16] +%if cpuflag(ssse3) + pshufb m0, m2 + pshufb m1, m2 + mov%1 [r0 + 0], m0 + mov%1 [r0 + 16], m1 +%else + pshuflw m0, m0, 10110001b + pshuflw m1, m1, 10110001b + pshufhw m0, m0, 10110001b + pshufhw m1, m1, 10110001b + mova m2, m0 + mova m3, m1 + psllw m0, 8 + psllw m1, 8 + psrlw m2, 8 + psrlw m3, 8 + por m2, m0 + por m3, m1 + mov%1 [r0 + 0], m2 + mov%1 [r0 + 16], m3 +%endif + add r0, 32 + add r1, 32 + dec r2 + jnz .loop8_%1 +.left4_%1: + mov r2, r3 + and r3, 4 + jz .left + mov%1 m0, [r1] +%if cpuflag(ssse3) + pshufb m0, m2 + mov%1 [r0], m0 +%else + pshuflw m0, m0, 10110001b + pshufhw m0, m0, 10110001b + mova m2, m0 + psllw m0, 8 + psrlw m2, 8 + por m2, m0 + mov%1 [r0], m2 +%endif + add r1, 16 + add r0, 16 +%endmacro + +; void ff_bswap_buf(uint32_t *dst, const uint32_t *src, int w); +%macro BSWAP32_BUF 0 +%if cpuflag(ssse3) +cglobal bswap32_buf, 3,4,3 + mov r3, r1 + mova m2, [pb_bswap32] +%else +cglobal bswap32_buf, 3,4,5 + mov r3, r1 +%endif + or r3, r0 + and r3, 15 + jz .start_align + BSWAP_LOOPS u + jmp .left +.start_align: + BSWAP_LOOPS a +.left: +%if cpuflag(ssse3) + mov r3, r2 + and r2, 2 + jz .left1 + movq m0, [r1] + pshufb m0, m2 + movq [r0], m0 + add r1, 8 + add r0, 8 +.left1: + and r3, 1 + jz .end + mov r2d, [r1] + bswap r2d + mov [r0], r2d +%else + and r2, 3 + jz .end +.loop2: + mov r3d, [r1] + bswap r3d + mov [r0], r3d + add r1, 4 + add r0, 4 + dec r2 + jnz .loop2 +%endif +.end: + RET +%endmacro + +INIT_XMM sse2 +BSWAP32_BUF + +INIT_XMM ssse3 +BSWAP32_BUF diff --git a/libavcodec/x86/bswapdsp_init.c b/libavcodec/x86/bswapdsp_init.c new file mode 100644 index 000000000..c042e5637 --- /dev/null +++ b/libavcodec/x86/bswapdsp_init.c @@ -0,0 +1,37 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/bswapdsp.h" + +void ff_bswap32_buf_sse2(uint32_t *dst, const uint32_t *src, int w); +void ff_bswap32_buf_ssse3(uint32_t *dst, const uint32_t *src, int w); + +av_cold void ff_bswapdsp_init_x86(BswapDSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_SSE2(cpu_flags)) + c->bswap_buf = ff_bswap32_buf_sse2; + if (EXTERNAL_SSSE3(cpu_flags)) + c->bswap_buf = ff_bswap32_buf_ssse3; +} diff --git a/libavcodec/x86/cabac.h b/libavcodec/x86/cabac.h index 558d28703..3510336f9 100644 --- a/libavcodec/x86/cabac.h +++ b/libavcodec/x86/cabac.h @@ -23,12 +23,13 @@ #include "libavcodec/cabac.h" #include "libavutil/attributes.h" +#include "libavutil/macros.h" #include "libavutil/x86/asm.h" -#include "libavutil/internal.h" #include "config.h" #if (defined(__i386) && defined(__clang__) && (__clang_major__<2 || (__clang_major__==2 && __clang_minor__<10)))\ - || ( !defined(__clang__) && defined(__llvm__) && __GNUC__==4 && __GNUC_MINOR__==2 && __GNUC_PATCHLEVEL__<=1) + || ( !defined(__clang__) && defined(__llvm__) && __GNUC__==4 && __GNUC_MINOR__==2 && __GNUC_PATCHLEVEL__<=1)\ + || (defined(__INTEL_COMPILER) && defined(_MSC_VER)) # define BROKEN_COMPILER 1 #else # define BROKEN_COMPILER 0 @@ -110,7 +111,7 @@ "2: \n\t" #else /* BROKEN_RELOCATIONS */ -#define TABLES_ARG +#define TABLES_ARG NAMED_CONSTRAINTS_ARRAY_ADD(ff_h264_cabac_tables) #define RIP_ARG #if HAVE_FAST_CMOV @@ -184,6 +185,7 @@ static av_always_inline int get_cabac_inline_x86(CABACContext *c, __asm__ volatile( "lea "MANGLE(ff_h264_cabac_tables)", %0 \n\t" : "=&r"(tables) + : NAMED_CONSTRAINTS_ARRAY(ff_h264_cabac_tables) ); #endif @@ -205,7 +207,7 @@ static av_always_inline int get_cabac_inline_x86(CABACContext *c, ); return bit & 1; } -#endif /* HAVE_7REGS */ +#endif /* HAVE_7REGS && !BROKEN_COMPILER */ #if !BROKEN_COMPILER #define get_cabac_bypass_sign get_cabac_bypass_sign_x86 @@ -218,7 +220,7 @@ static av_always_inline int get_cabac_bypass_sign_x86(CABACContext *c, int val) "shl $17, %k1 \n\t" "add %%eax, %%eax \n\t" "sub %k1, %%eax \n\t" - "cltd \n\t" + "cdq \n\t" "and %%edx, %k1 \n\t" "add %k1, %%eax \n\t" "xor %%edx, %%ecx \n\t" @@ -265,7 +267,7 @@ static av_always_inline int get_cabac_bypass_x86(CABACContext *c) "shl $17, %k1 \n\t" "add %%eax, %%eax \n\t" "sub %k1, %%eax \n\t" - "cltd \n\t" + "cdq \n\t" "and %%edx, %k1 \n\t" "add %k1, %%eax \n\t" "inc %%edx \n\t" diff --git a/libavcodec/x86/cavsdsp.c b/libavcodec/x86/cavsdsp.c index aaa09d178..b80623f23 100644 --- a/libavcodec/x86/cavsdsp.c +++ b/libavcodec/x86/cavsdsp.c @@ -28,8 +28,10 @@ #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/cavsdsp.h" +#include "libavcodec/idctdsp.h" #include "constants.h" -#include "dsputil_x86.h" +#include "fpel.h" +#include "idctdsp.h" #include "config.h" #if HAVE_MMX_INLINE @@ -210,10 +212,10 @@ static void cavs_idct8_add_mmx(uint8_t *dst, int16_t *block, int stride) ****************************************************************************/ /* vertical filter [-1 -2 96 42 -7 0] */ -#define QPEL_CAVSV1(A,B,C,D,E,F,OP,MUL2) \ +#define QPEL_CAVSV1(A,B,C,D,E,F,OP,ADD, MUL1, MUL2) \ "movd (%0), "#F" \n\t"\ "movq "#C", %%mm6 \n\t"\ - "pmullw %5, %%mm6 \n\t"\ + "pmullw "MANGLE(MUL1)", %%mm6\n\t"\ "movq "#D", %%mm7 \n\t"\ "pmullw "MANGLE(MUL2)", %%mm7\n\t"\ "psllw $3, "#E" \n\t"\ @@ -228,35 +230,35 @@ static void cavs_idct8_add_mmx(uint8_t *dst, int16_t *block, int stride) "psubw "#B", %%mm6 \n\t"\ "psraw $1, "#B" \n\t"\ "psubw "#A", %%mm6 \n\t"\ - "paddw %4, %%mm6 \n\t"\ + "paddw "MANGLE(ADD)", %%mm6 \n\t"\ "psraw $7, %%mm6 \n\t"\ "packuswb %%mm6, %%mm6 \n\t"\ OP(%%mm6, (%1), A, d) \ "add %3, %1 \n\t" /* vertical filter [ 0 -1 5 5 -1 0] */ -#define QPEL_CAVSV2(A,B,C,D,E,F,OP,MUL2) \ +#define QPEL_CAVSV2(A,B,C,D,E,F,OP,ADD, MUL1, MUL2) \ "movd (%0), "#F" \n\t"\ "movq "#C", %%mm6 \n\t"\ "paddw "#D", %%mm6 \n\t"\ - "pmullw %5, %%mm6 \n\t"\ + "pmullw "MANGLE(MUL1)", %%mm6\n\t"\ "add %2, %0 \n\t"\ "punpcklbw %%mm7, "#F" \n\t"\ "psubw "#B", %%mm6 \n\t"\ "psubw "#E", %%mm6 \n\t"\ - "paddw %4, %%mm6 \n\t"\ + "paddw "MANGLE(ADD)", %%mm6 \n\t"\ "psraw $3, %%mm6 \n\t"\ "packuswb %%mm6, %%mm6 \n\t"\ OP(%%mm6, (%1), A, d) \ "add %3, %1 \n\t" /* vertical filter [ 0 -7 42 96 -2 -1] */ -#define QPEL_CAVSV3(A,B,C,D,E,F,OP,MUL2) \ +#define QPEL_CAVSV3(A,B,C,D,E,F,OP,ADD, MUL1, MUL2) \ "movd (%0), "#F" \n\t"\ "movq "#C", %%mm6 \n\t"\ "pmullw "MANGLE(MUL2)", %%mm6\n\t"\ "movq "#D", %%mm7 \n\t"\ - "pmullw %5, %%mm7 \n\t"\ + "pmullw "MANGLE(MUL1)", %%mm7\n\t"\ "psllw $3, "#B" \n\t"\ "psubw "#B", %%mm6 \n\t"\ "psraw $3, "#B" \n\t"\ @@ -269,7 +271,7 @@ static void cavs_idct8_add_mmx(uint8_t *dst, int16_t *block, int stride) "psubw "#E", %%mm6 \n\t"\ "psraw $1, "#E" \n\t"\ "psubw "#F", %%mm6 \n\t"\ - "paddw %4, %%mm6 \n\t"\ + "paddw "MANGLE(ADD)", %%mm6 \n\t"\ "psraw $7, %%mm6 \n\t"\ "packuswb %%mm6, %%mm6 \n\t"\ OP(%%mm6, (%1), A, d) \ @@ -298,32 +300,34 @@ static void cavs_idct8_add_mmx(uint8_t *dst, int16_t *block, int stride) "punpcklbw %%mm7, %%mm2 \n\t"\ "punpcklbw %%mm7, %%mm3 \n\t"\ "punpcklbw %%mm7, %%mm4 \n\t"\ - VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP, MUL2)\ - VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP, MUL2)\ - VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP, MUL2)\ - VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP, MUL2)\ - VOP(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, OP, MUL2)\ - VOP(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, OP, MUL2)\ - VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP, MUL2)\ - VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP, MUL2)\ + VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP, ADD, MUL1, MUL2)\ + VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP, ADD, MUL1, MUL2)\ + VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP, ADD, MUL1, MUL2)\ + VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP, ADD, MUL1, MUL2)\ + VOP(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, OP, ADD, MUL1, MUL2)\ + VOP(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, OP, ADD, MUL1, MUL2)\ + VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP, ADD, MUL1, MUL2)\ + VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP, ADD, MUL1, MUL2)\ \ : "+a"(src), "+c"(dst)\ - : "S"((x86_reg)srcStride), "r"((x86_reg)dstStride), "m"(ADD), "m"(MUL1)\ + : "S"((x86_reg)srcStride), "r"((x86_reg)dstStride)\ + NAMED_CONSTRAINTS_ADD(ADD,MUL1,MUL2)\ : "memory"\ );\ if(h==16){\ __asm__ volatile(\ - VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP, MUL2)\ - VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP, MUL2)\ - VOP(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, OP, MUL2)\ - VOP(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, OP, MUL2)\ - VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP, MUL2)\ - VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP, MUL2)\ - VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP, MUL2)\ - VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP, MUL2)\ + VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP, ADD, MUL1, MUL2)\ + VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP, ADD, MUL1, MUL2)\ + VOP(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, OP, ADD, MUL1, MUL2)\ + VOP(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, OP, ADD, MUL1, MUL2)\ + VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP, ADD, MUL1, MUL2)\ + VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP, ADD, MUL1, MUL2)\ + VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP, ADD, MUL1, MUL2)\ + VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP, ADD, MUL1, MUL2)\ \ : "+a"(src), "+c"(dst)\ - : "S"((x86_reg)srcStride), "r"((x86_reg)dstStride), "m"(ADD), "m"(MUL1)\ + : "S"((x86_reg)srcStride), "r"((x86_reg)dstStride)\ + NAMED_CONSTRAINTS_ADD(ADD,MUL1,MUL2)\ : "memory"\ );\ }\ @@ -336,7 +340,7 @@ static void OPNAME ## cavs_qpel8_h_ ## MMX(uint8_t *dst, uint8_t *src, int dstSt int h=8;\ __asm__ volatile(\ "pxor %%mm7, %%mm7 \n\t"\ - "movq %5, %%mm6 \n\t"\ + "movq "MANGLE(ff_pw_5)", %%mm6\n\t"\ "1: \n\t"\ "movq (%0), %%mm0 \n\t"\ "movq 1(%0), %%mm2 \n\t"\ @@ -362,7 +366,7 @@ static void OPNAME ## cavs_qpel8_h_ ## MMX(uint8_t *dst, uint8_t *src, int dstSt "paddw %%mm3, %%mm5 \n\t"\ "psubw %%mm2, %%mm0 \n\t"\ "psubw %%mm5, %%mm1 \n\t"\ - "movq %6, %%mm5 \n\t"\ + "movq "MANGLE(ff_pw_4)", %%mm5\n\t"\ "paddw %%mm5, %%mm0 \n\t"\ "paddw %%mm5, %%mm1 \n\t"\ "psraw $3, %%mm0 \n\t"\ @@ -374,7 +378,8 @@ static void OPNAME ## cavs_qpel8_h_ ## MMX(uint8_t *dst, uint8_t *src, int dstSt "decl %2 \n\t"\ " jnz 1b \n\t"\ : "+a"(src), "+c"(dst), "+m"(h)\ - : "d"((x86_reg)srcStride), "S"((x86_reg)dstStride), "m"(ff_pw_5), "m"(ff_pw_4)\ + : "d"((x86_reg)srcStride), "S"((x86_reg)dstStride)\ + NAMED_CONSTRAINTS_ADD(ff_pw_4,ff_pw_5)\ : "memory"\ );\ }\ @@ -384,7 +389,7 @@ static inline void OPNAME ## cavs_qpel8or16_v1_ ## MMX(uint8_t *dst, uint8_t *sr }\ \ static inline void OPNAME ## cavs_qpel8or16_v2_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\ - QPEL_CAVSVNUM(QPEL_CAVSV2,OP,ff_pw_4,ff_pw_5,ff_pw_5) \ + QPEL_CAVSVNUM(QPEL_CAVSV2,OP,ff_pw_4,ff_pw_5,ff_pw_42) \ }\ \ static inline void OPNAME ## cavs_qpel8or16_v3_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\ @@ -457,7 +462,7 @@ static void OPNAME ## cavs_qpel ## SIZE ## _mc03_ ## MMX(uint8_t *dst, uint8_t * #endif /* (HAVE_MMXEXT_INLINE || HAVE_AMD3DNOW_INLINE) */ -#if HAVE_MMX_INLINE +#if HAVE_MMX_EXTERNAL static void put_cavs_qpel8_mc00_mmx(uint8_t *dst, uint8_t *src, ptrdiff_t stride) { @@ -470,6 +475,12 @@ static void avg_cavs_qpel8_mc00_mmx(uint8_t *dst, uint8_t *src, ff_avg_pixels8_mmx(dst, src, stride, 8); } +static void avg_cavs_qpel8_mc00_mmxext(uint8_t *dst, uint8_t *src, + ptrdiff_t stride) +{ + ff_avg_pixels8_mmxext(dst, src, stride, 8); +} + static void put_cavs_qpel16_mc00_mmx(uint8_t *dst, uint8_t *src, ptrdiff_t stride) { @@ -482,18 +493,40 @@ static void avg_cavs_qpel16_mc00_mmx(uint8_t *dst, uint8_t *src, ff_avg_pixels16_mmx(dst, src, stride, 16); } +static void avg_cavs_qpel16_mc00_mmxext(uint8_t *dst, uint8_t *src, + ptrdiff_t stride) +{ + ff_avg_pixels16_mmxext(dst, src, stride, 16); +} + +static void put_cavs_qpel16_mc00_sse2(uint8_t *dst, uint8_t *src, + ptrdiff_t stride) +{ + ff_put_pixels16_sse2(dst, src, stride, 16); +} + +static void avg_cavs_qpel16_mc00_sse2(uint8_t *dst, uint8_t *src, + ptrdiff_t stride) +{ + ff_avg_pixels16_sse2(dst, src, stride, 16); +} +#endif + static av_cold void cavsdsp_init_mmx(CAVSDSPContext *c, AVCodecContext *avctx) { +#if HAVE_MMX_EXTERNAL c->put_cavs_qpel_pixels_tab[0][0] = put_cavs_qpel16_mc00_mmx; c->put_cavs_qpel_pixels_tab[1][0] = put_cavs_qpel8_mc00_mmx; c->avg_cavs_qpel_pixels_tab[0][0] = avg_cavs_qpel16_mc00_mmx; c->avg_cavs_qpel_pixels_tab[1][0] = avg_cavs_qpel8_mc00_mmx; +#endif +#if HAVE_MMX_INLINE c->cavs_idct8_add = cavs_idct8_add_mmx; c->idct_perm = FF_TRANSPOSE_IDCT_PERM; -} #endif /* HAVE_MMX_INLINE */ +} #define DSPFUNC(PFX, IDX, NUM, EXT) \ c->PFX ## _cavs_qpel_pixels_tab[IDX][ 2] = PFX ## _cavs_qpel ## NUM ## _mc20_ ## EXT; \ @@ -509,15 +542,6 @@ CAVS_MC(put_, 8, mmxext) CAVS_MC(put_, 16, mmxext) CAVS_MC(avg_, 8, mmxext) CAVS_MC(avg_, 16, mmxext) - -static av_cold void cavsdsp_init_mmxext(CAVSDSPContext *c, - AVCodecContext *avctx) -{ - DSPFUNC(put, 0, 16, mmxext); - DSPFUNC(put, 1, 8, mmxext); - DSPFUNC(avg, 0, 16, mmxext); - DSPFUNC(avg, 1, 8, mmxext); -} #endif /* HAVE_MMXEXT_INLINE */ #if HAVE_AMD3DNOW_INLINE @@ -541,18 +565,31 @@ static av_cold void cavsdsp_init_3dnow(CAVSDSPContext *c, av_cold void ff_cavsdsp_init_x86(CAVSDSPContext *c, AVCodecContext *avctx) { -#if HAVE_MMX_INLINE int cpu_flags = av_get_cpu_flags(); - if (INLINE_MMX(cpu_flags)) - cavsdsp_init_mmx(c, avctx); -#endif /* HAVE_MMX_INLINE */ + cavsdsp_init_mmx(c, avctx); #if HAVE_AMD3DNOW_INLINE if (INLINE_AMD3DNOW(cpu_flags)) cavsdsp_init_3dnow(c, avctx); #endif /* HAVE_AMD3DNOW_INLINE */ #if HAVE_MMXEXT_INLINE - if (INLINE_MMXEXT(cpu_flags)) - cavsdsp_init_mmxext(c, avctx); -#endif /* HAVE_MMXEXT_INLINE */ + if (INLINE_MMXEXT(cpu_flags)) { + DSPFUNC(put, 0, 16, mmxext); + DSPFUNC(put, 1, 8, mmxext); + DSPFUNC(avg, 0, 16, mmxext); + DSPFUNC(avg, 1, 8, mmxext); + } +#endif +#if HAVE_MMX_EXTERNAL + if (EXTERNAL_MMXEXT(cpu_flags)) { + c->avg_cavs_qpel_pixels_tab[0][0] = avg_cavs_qpel16_mc00_mmxext; + c->avg_cavs_qpel_pixels_tab[1][0] = avg_cavs_qpel8_mc00_mmxext; + } +#endif +#if HAVE_SSE2_EXTERNAL + if (EXTERNAL_SSE2(cpu_flags)) { + c->put_cavs_qpel_pixels_tab[0][0] = put_cavs_qpel16_mc00_sse2; + c->avg_cavs_qpel_pixels_tab[0][0] = avg_cavs_qpel16_mc00_sse2; + } +#endif } diff --git a/libavcodec/x86/constants.c b/libavcodec/x86/constants.c index 3bba80bd8..7608bb32e 100644 --- a/libavcodec/x86/constants.c +++ b/libavcodec/x86/constants.c @@ -1,5 +1,5 @@ /* - * MMX/SSE constants used across x86 dsp optimizations. + * MMX/SSE/AVX constants used across x86 dsp optimizations. * * This file is part of FFmpeg. * @@ -47,7 +47,9 @@ DECLARE_ALIGNED(16, const xmm_reg, ff_pw_512) = { 0x0200020002000200ULL, 0x020 DECLARE_ALIGNED(16, const xmm_reg, ff_pw_1019) = { 0x03FB03FB03FB03FBULL, 0x03FB03FB03FB03FBULL }; DECLARE_ALIGNED(16, const xmm_reg, ff_pb_0) = { 0x0000000000000000ULL, 0x0000000000000000ULL }; -DECLARE_ALIGNED(16, const xmm_reg, ff_pb_1) = { 0x0101010101010101ULL, 0x0101010101010101ULL }; -DECLARE_ALIGNED(16, const xmm_reg, ff_pb_3) = { 0x0303030303030303ULL, 0x0303030303030303ULL }; +DECLARE_ALIGNED(32, const ymm_reg, ff_pb_1) = { 0x0101010101010101ULL, 0x0101010101010101ULL, + 0x0101010101010101ULL, 0x0101010101010101ULL }; +DECLARE_ALIGNED(32, const ymm_reg, ff_pb_3) = { 0x0303030303030303ULL, 0x0303030303030303ULL, + 0x0303030303030303ULL, 0x0303030303030303ULL }; DECLARE_ALIGNED(16, const xmm_reg, ff_pb_80) = { 0x8080808080808080ULL, 0x8080808080808080ULL }; DECLARE_ALIGNED(8, const uint64_t, ff_pb_FC) = 0xFCFCFCFCFCFCFCFCULL; diff --git a/libavcodec/x86/constants.h b/libavcodec/x86/constants.h index 8097bc49f..3ebf171ad 100644 --- a/libavcodec/x86/constants.h +++ b/libavcodec/x86/constants.h @@ -31,6 +31,7 @@ extern const xmm_reg ff_pw_3; extern const xmm_reg ff_pw_4; extern const xmm_reg ff_pw_5; extern const xmm_reg ff_pw_8; +extern const xmm_reg ff_pw_9; extern const uint64_t ff_pw_15; extern const xmm_reg ff_pw_16; extern const xmm_reg ff_pw_18; @@ -43,8 +44,9 @@ extern const uint64_t ff_pw_96; extern const uint64_t ff_pw_128; extern const uint64_t ff_pw_255; -extern const xmm_reg ff_pb_1; -extern const xmm_reg ff_pb_3; +extern const ymm_reg ff_pb_1; +extern const ymm_reg ff_pb_3; +extern const xmm_reg ff_pb_80; extern const xmm_reg ff_pb_F8; extern const uint64_t ff_pb_FC; diff --git a/libavcodec/x86/dcadsp.asm b/libavcodec/x86/dcadsp.asm index 2b5a96f4e..1ac237885 100644 --- a/libavcodec/x86/dcadsp.asm +++ b/libavcodec/x86/dcadsp.asm @@ -132,10 +132,15 @@ DECODE_HF mulps va, %2 mulps vb, %2 %if %0 == 3 +%if cpuflag(fma3) + fmaddps va, m4, %3, va + fmaddps vb, m0, %3, vb +%else mulps m4, %3 mulps m0, %3 addps va, m4 addps vb, m0 +%endif %endif ; va = va1 va2 va3 va4 ; vb = vb1 vb2 vb3 vb4 @@ -148,7 +153,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 @@ -198,75 +203,131 @@ cglobal dca_lfe_fir%1, 3,3,6-%1, out, in, cf0 INIT_XMM sse DCA_LFE_FIR 0 DCA_LFE_FIR 1 +%if HAVE_FMA3_EXTERNAL +INIT_XMM fma3 +DCA_LFE_FIR 0 +%endif + +%macro SETZERO 1 +%if cpuflag(sse2) && notcpuflag(avx) + pxor %1, %1 +%else + xorps %1, %1, %1 +%endif +%endmacro + +%macro SHUF 3 +%if cpuflag(avx) + mova %3, [%2 - 16] + vperm2f128 %1, %3, %3, 1 + vshufps %1, %1, %1, q0123 +%elif cpuflag(sse2) + pshufd %1, [%2], q0123 +%else + mova %1, [%2] + shufps %1, %1, q0123 +%endif +%endmacro -INIT_XMM sse2 %macro INNER_LOOP 1 ; reading backwards: ptr1 = synth_buf + j + i; ptr2 = synth_buf + j - i ;~ a += window[i + j] * (-synth_buf[15 - i + j]) ;~ b += window[i + j + 16] * (synth_buf[i + j]) - pshufd m5, [ptr2 + j + (15 - 3) * 4], q0123 + SHUF m5, ptr2 + j + (15 - 3) * 4, m6 mova m6, [ptr1 + j] %if ARCH_X86_64 - pshufd m11, [ptr2 + j + (15 - 3) * 4 - mmsize], q0123 + SHUF m11, ptr2 + j + (15 - 3) * 4 - mmsize, m12 mova m12, [ptr1 + j + mmsize] %endif - mulps m6, [win + %1 + j + 16 * 4] - mulps m5, [win + %1 + j] +%if cpuflag(fma3) + fmaddps m2, m6, [win + %1 + j + 16 * 4], m2 + fnmaddps m1, m5, [win + %1 + j], m1 %if ARCH_X86_64 - mulps m12, [win + %1 + j + mmsize + 16 * 4] - mulps m11, [win + %1 + j + mmsize] + fmaddps m8, m12, [win + %1 + j + mmsize + 16 * 4], m8 + fnmaddps m7, m11, [win + %1 + j + mmsize], m7 %endif - addps m2, m6 - subps m1, m5 +%else ; non-FMA + mulps m6, m6, [win + %1 + j + 16 * 4] + mulps m5, m5, [win + %1 + j] %if ARCH_X86_64 - addps m8, m12 - subps m7, m11 + mulps m12, m12, [win + %1 + j + mmsize + 16 * 4] + mulps m11, m11, [win + %1 + j + mmsize] %endif + addps m2, m2, m6 + subps m1, m1, m5 +%if ARCH_X86_64 + addps m8, m8, m12 + subps m7, m7, m11 +%endif +%endif ; cpuflag(fma3) ;~ c += window[i + j + 32] * (synth_buf[16 + i + j]) ;~ d += window[i + j + 48] * (synth_buf[31 - i + j]) - pshufd m6, [ptr2 + j + (31 - 3) * 4], q0123 + SHUF m6, ptr2 + j + (31 - 3) * 4, m5 mova m5, [ptr1 + j + 16 * 4] %if ARCH_X86_64 - pshufd m12, [ptr2 + j + (31 - 3) * 4 - mmsize], q0123 + SHUF m12, ptr2 + j + (31 - 3) * 4 - mmsize, m11 mova m11, [ptr1 + j + mmsize + 16 * 4] %endif - mulps m5, [win + %1 + j + 32 * 4] - mulps m6, [win + %1 + j + 48 * 4] +%if cpuflag(fma3) + fmaddps m3, m5, [win + %1 + j + 32 * 4], m3 + fmaddps m4, m6, [win + %1 + j + 48 * 4], m4 %if ARCH_X86_64 - mulps m11, [win + %1 + j + mmsize + 32 * 4] - mulps m12, [win + %1 + j + mmsize + 48 * 4] + fmaddps m9, m11, [win + %1 + j + mmsize + 32 * 4], m9 + fmaddps m10, m12, [win + %1 + j + mmsize + 48 * 4], m10 %endif - addps m3, m5 - addps m4, m6 +%else ; non-FMA + mulps m5, m5, [win + %1 + j + 32 * 4] + mulps m6, m6, [win + %1 + j + 48 * 4] %if ARCH_X86_64 - addps m9, m11 - addps m10, m12 + mulps m11, m11, [win + %1 + j + mmsize + 32 * 4] + mulps m12, m12, [win + %1 + j + mmsize + 48 * 4] %endif + addps m3, m3, m5 + addps m4, m4, m6 +%if ARCH_X86_64 + addps m9, m9, m11 + addps m10, m10, m12 +%endif +%endif ; cpuflag(fma3) sub j, 64 * 4 %endmacro -; void ff_synth_filter_inner_sse2(float *synth_buf, float synth_buf2[32], -; const float window[512], float out[32], -; intptr_t offset, float scale) +; void ff_synth_filter_inner_(float *synth_buf, float synth_buf2[32], +; const float window[512], float out[32], +; intptr_t offset, float scale) +%macro SYNTH_FILTER 0 cglobal synth_filter_inner, 0, 6 + 4 * ARCH_X86_64, 7 + 6 * ARCH_X86_64, \ synth_buf, synth_buf2, window, out, off, scale %define scale m0 %if ARCH_X86_32 || WIN64 +%if cpuflag(sse2) && notcpuflag(avx) movd scale, scalem + SPLATD m0 +%else + VBROADCASTSS m0, scalem +%endif ; Make sure offset is in a register and not on the stack %define OFFQ r4q %else + SPLATD xmm0 +%if cpuflag(avx) + vinsertf128 m0, m0, xmm0, 1 +%endif %define OFFQ offq %endif - pshufd m0, m0, 0 ; prepare inner counter limit 1 mov r5q, 480 sub r5q, offmp and r5q, -64 shl r5q, 2 +%if ARCH_X86_32 || notcpuflag(avx) mov OFFQ, r5q %define i r5q mov i, 16 * 4 - (ARCH_X86_64 + 1) * mmsize ; main loop counter +%else +%define i 0 +%define OFFQ r5q +%endif %define buf2 synth_buf2q %if ARCH_X86_32 @@ -274,8 +335,8 @@ cglobal synth_filter_inner, 0, 6 + 4 * ARCH_X86_64, 7 + 6 * ARCH_X86_64, \ %endif .mainloop ; m1 = a m2 = b m3 = c m4 = d - pxor m3, m3 - pxor m4, m4 + SETZERO m3 + SETZERO m4 mova m1, [buf2 + i] mova m2, [buf2 + i + 16 * 4] %if ARCH_X86_32 @@ -285,15 +346,17 @@ cglobal synth_filter_inner, 0, 6 + 4 * ARCH_X86_64, 7 + 6 * ARCH_X86_64, \ %define j r3q mov win, windowm mov ptr1, synth_bufm +%if ARCH_X86_32 || notcpuflag(avx) add win, i add ptr1, i +%endif %else ; ARCH_X86_64 %define ptr1 r6q %define ptr2 r7q ; must be loaded %define win r8q %define j r9q - pxor m9, m9 - pxor m10, m10 + SETZERO m9 + SETZERO m10 mova m7, [buf2 + i + mmsize] mova m8, [buf2 + i + mmsize + 16 * 4] lea win, [windowq + i] @@ -302,7 +365,9 @@ cglobal synth_filter_inner, 0, 6 + 4 * ARCH_X86_64, 7 + 6 * ARCH_X86_64, \ mov ptr2, synth_bufmp ; prepare the inner loop counter mov j, OFFQ +%if ARCH_X86_32 || notcpuflag(avx) sub ptr2, i +%endif .loop1: INNER_LOOP 0 jge .loop1 @@ -325,11 +390,11 @@ cglobal synth_filter_inner, 0, 6 + 4 * ARCH_X86_64, 7 + 6 * ARCH_X86_64, \ %endif ;~ out[i] = a * scale; ;~ out[i + 16] = b * scale; - mulps m1, scale - mulps m2, scale + mulps m1, m1, scale + mulps m2, m2, scale %if ARCH_X86_64 - mulps m7, scale - mulps m8, scale + mulps m7, m7, scale + mulps m8, m8, scale %endif ;~ synth_buf2[i] = c; ;~ synth_buf2[i + 16] = d; @@ -347,6 +412,20 @@ cglobal synth_filter_inner, 0, 6 + 4 * ARCH_X86_64, 7 + 6 * ARCH_X86_64, \ mova [outq + i + 0 * 4 + mmsize], m7 mova [outq + i + 16 * 4 + mmsize], m8 %endif +%if ARCH_X86_32 || notcpuflag(avx) sub i, (ARCH_X86_64 + 1) * mmsize jge .mainloop +%endif RET +%endmacro + +%if ARCH_X86_32 +INIT_XMM sse +SYNTH_FILTER +%endif +INIT_XMM sse2 +SYNTH_FILTER +INIT_YMM avx +SYNTH_FILTER +INIT_YMM fma3 +SYNTH_FILTER diff --git a/libavcodec/x86/dcadsp_init.c b/libavcodec/x86/dcadsp_init.c index 9ededac82..bb86c2603 100644 --- a/libavcodec/x86/dcadsp_init.c +++ b/libavcodec/x86/dcadsp_init.c @@ -34,6 +34,7 @@ void ff_decode_hf_sse4(float dst[DCA_SUBBANDS][8], const int vq_num[DCA_SUBBANDS 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); +void ff_dca_lfe_fir0_fma3(float *out, const float *in, const float *coefs); av_cold void ff_dcadsp_init_x86(DCADSPContext *s) { @@ -54,32 +55,59 @@ av_cold void ff_dcadsp_init_x86(DCADSPContext *s) if (EXTERNAL_SSE4(cpu_flags)) { s->decode_hf = ff_decode_hf_sse4; } + + if (EXTERNAL_FMA3(cpu_flags)) { + s->lfe_fir[0] = ff_dca_lfe_fir0_fma3; + } } -void ff_synth_filter_inner_sse2(float *synth_buf_ptr, float synth_buf2[32], - const float window[512], - float out[32], intptr_t offset, float scale); -static void synth_filter_sse2(FFTContext *imdct, - float *synth_buf_ptr, int *synth_buf_offset, - float synth_buf2[32], const float window[512], - float out[32], const float in[32], float scale) -{ - float *synth_buf= synth_buf_ptr + *synth_buf_offset; +#define SYNTH_FILTER_FUNC(opt) \ +void ff_synth_filter_inner_##opt(float *synth_buf_ptr, float synth_buf2[32], \ + const float window[512], \ + float out[32], intptr_t offset, float scale); \ +static void synth_filter_##opt(FFTContext *imdct, \ + float *synth_buf_ptr, int *synth_buf_offset, \ + float synth_buf2[32], const float window[512], \ + float out[32], const float in[32], float scale) \ +{ \ + float *synth_buf= synth_buf_ptr + *synth_buf_offset; \ + \ + imdct->imdct_half(imdct, synth_buf, in); \ + \ + ff_synth_filter_inner_##opt(synth_buf, synth_buf2, window, \ + out, *synth_buf_offset, scale); \ + \ + *synth_buf_offset = (*synth_buf_offset - 32) & 511; \ +} \ - imdct->imdct_half(imdct, synth_buf, in); - - ff_synth_filter_inner_sse2(synth_buf, synth_buf2, window, - out, *synth_buf_offset, scale); - - *synth_buf_offset = (*synth_buf_offset - 32) & 511; -} +#if HAVE_YASM +#if ARCH_X86_32 +SYNTH_FILTER_FUNC(sse) +#endif +SYNTH_FILTER_FUNC(sse2) +SYNTH_FILTER_FUNC(avx) +SYNTH_FILTER_FUNC(fma3) +#endif /* HAVE_YASM */ av_cold void ff_synth_filter_init_x86(SynthFilterContext *s) { +#if HAVE_YASM int cpu_flags = av_get_cpu_flags(); +#if ARCH_X86_32 + if (EXTERNAL_SSE(cpu_flags)) { + s->synth_filter_float = synth_filter_sse; + } +#endif if (EXTERNAL_SSE2(cpu_flags)) { s->synth_filter_float = synth_filter_sse2; } + if (EXTERNAL_AVX(cpu_flags)) { + s->synth_filter_float = synth_filter_avx; + } + if (EXTERNAL_FMA3(cpu_flags)) { + s->synth_filter_float = synth_filter_fma3; + } +#endif /* HAVE_YASM */ } diff --git a/libavcodec/x86/dct32.asm b/libavcodec/x86/dct32.asm index 6fd5ba350..c70f6c9c4 100644 --- a/libavcodec/x86/dct32.asm +++ b/libavcodec/x86/dct32.asm @@ -484,7 +484,9 @@ 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 85e2d0c3e..30c8f12bf 100644 --- a/libavcodec/x86/dct_init.c +++ b/libavcodec/x86/dct_init.c @@ -30,7 +30,7 @@ av_cold void ff_dct_init_x86(DCTContext *s) { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_SSE(cpu_flags)) + if (ARCH_X86_32 && EXTERNAL_SSE(cpu_flags)) s->dct32 = ff_dct32_float_sse; if (EXTERNAL_SSE2(cpu_flags)) s->dct32 = ff_dct32_float_sse2; diff --git a/libavcodec/x86/deinterlace.asm b/libavcodec/x86/deinterlace.asm index 3812dbe60..baa9249db 100644 --- a/libavcodec/x86/deinterlace.asm +++ b/libavcodec/x86/deinterlace.asm @@ -1,5 +1,5 @@ ;****************************************************************************** -;* MMX optimized deinterlacing functions +;* SIMD-optimized deinterlacing functions ;* Copyright (c) 2010 Vitor Sessak ;* Copyright (c) 2002 Michael Niedermayer ;* diff --git a/libavcodec/x86/diracdsp_mmx.c b/libavcodec/x86/diracdsp_mmx.c index a28bb8206..a12f9523d 100644 --- a/libavcodec/x86/diracdsp_mmx.c +++ b/libavcodec/x86/diracdsp_mmx.c @@ -18,8 +18,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/x86/cpu.h" #include "dsputil_x86.h" #include "diracdsp_mmx.h" +#include "fpel.h" void ff_put_rect_clamped_mmx(uint8_t *dst, int dst_stride, const int16_t *src, int src_stride, int width, int height); void ff_put_rect_clamped_sse2(uint8_t *dst, int dst_stride, const int16_t *src, int src_stride, int width, int height); @@ -56,14 +58,73 @@ HPEL_FILTER(16, sse2) c->PFX ## _dirac_pixels_tab[1][IDX] = ff_ ## PFX ## _dirac_pixels16_ ## EXT; \ c->PFX ## _dirac_pixels_tab[2][IDX] = ff_ ## PFX ## _dirac_pixels32_ ## EXT +#define DIRAC_PIXOP(OPNAME2, OPNAME, EXT)\ +void ff_ ## OPNAME2 ## _dirac_pixels8_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + if (h&3)\ + ff_ ## OPNAME2 ## _dirac_pixels8_c(dst, src, stride, h);\ + else\ + OPNAME ## _pixels8_ ## EXT(dst, src[0], stride, h);\ +}\ +void ff_ ## OPNAME2 ## _dirac_pixels16_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + if (h&3)\ + ff_ ## OPNAME2 ## _dirac_pixels16_c(dst, src, stride, h);\ + else\ + OPNAME ## _pixels16_ ## EXT(dst, src[0], stride, h);\ +}\ +void ff_ ## OPNAME2 ## _dirac_pixels32_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + if (h&3) {\ + ff_ ## OPNAME2 ## _dirac_pixels32_c(dst, src, stride, h);\ + } else {\ + OPNAME ## _pixels16_ ## EXT(dst , src[0] , stride, h);\ + OPNAME ## _pixels16_ ## EXT(dst+16, src[0]+16, stride, h);\ + }\ +} + +DIRAC_PIXOP(put, ff_put, mmx) +DIRAC_PIXOP(avg, ff_avg, mmx) +DIRAC_PIXOP(avg, ff_avg, mmxext) + +void ff_put_dirac_pixels16_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h) +{ + if (h&3) + ff_put_dirac_pixels16_c(dst, src, stride, h); + else + ff_put_pixels16_sse2(dst, src[0], stride, h); +} +void ff_avg_dirac_pixels16_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h) +{ + if (h&3) + ff_avg_dirac_pixels16_c(dst, src, stride, h); + else + ff_avg_pixels16_sse2(dst, src[0], stride, h); +} +void ff_put_dirac_pixels32_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h) +{ + if (h&3) { + ff_put_dirac_pixels32_c(dst, src, stride, h); + } else { + ff_put_pixels16_sse2(dst , src[0] , stride, h); + ff_put_pixels16_sse2(dst+16, src[0]+16, stride, h); + } +} +void ff_avg_dirac_pixels32_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h) +{ + if (h&3) { + ff_avg_dirac_pixels32_c(dst, src, stride, h); + } else { + ff_avg_pixels16_sse2(dst , src[0] , stride, h); + ff_avg_pixels16_sse2(dst+16, src[0]+16, stride, h); + } +} + void ff_diracdsp_init_mmx(DiracDSPContext* c) { int mm_flags = av_get_cpu_flags(); - if (!(mm_flags & AV_CPU_FLAG_MMX)) - return; - -#if HAVE_YASM + if (EXTERNAL_MMX(mm_flags)) { c->add_dirac_obmc[0] = ff_add_dirac_obmc8_mmx; #if !ARCH_X86_64 c->add_dirac_obmc[1] = ff_add_dirac_obmc16_mmx; @@ -72,33 +133,25 @@ void ff_diracdsp_init_mmx(DiracDSPContext* c) c->add_rect_clamped = ff_add_rect_clamped_mmx; c->put_signed_rect_clamped = ff_put_signed_rect_clamped_mmx; #endif -#endif - -#if HAVE_MMX_INLINE PIXFUNC(put, 0, mmx); PIXFUNC(avg, 0, mmx); -#endif + } -#if HAVE_MMXEXT_INLINE - if (mm_flags & AV_CPU_FLAG_MMX2) { + if (EXTERNAL_MMXEXT(mm_flags)) { PIXFUNC(avg, 0, mmxext); } -#endif - if (mm_flags & AV_CPU_FLAG_SSE2) { -#if HAVE_YASM + if (EXTERNAL_SSE2(mm_flags)) { c->dirac_hpel_filter = dirac_hpel_filter_sse2; c->add_rect_clamped = ff_add_rect_clamped_sse2; c->put_signed_rect_clamped = ff_put_signed_rect_clamped_sse2; c->add_dirac_obmc[1] = ff_add_dirac_obmc16_sse2; c->add_dirac_obmc[2] = ff_add_dirac_obmc32_sse2; -#endif -#if HAVE_SSE2_INLINE + c->put_dirac_pixels_tab[1][0] = ff_put_dirac_pixels16_sse2; c->avg_dirac_pixels_tab[1][0] = ff_avg_dirac_pixels16_sse2; c->put_dirac_pixels_tab[2][0] = ff_put_dirac_pixels32_sse2; c->avg_dirac_pixels_tab[2][0] = ff_avg_dirac_pixels32_sse2; -#endif } } diff --git a/libavcodec/x86/dnxhdenc.asm b/libavcodec/x86/dnxhdenc.asm new file mode 100644 index 000000000..9dd6d51ee --- /dev/null +++ b/libavcodec/x86/dnxhdenc.asm @@ -0,0 +1,49 @@ +;************************************************************************ +;* VC3/DNxHD SIMD functions +;* Copyright (c) 2007 Baptiste Coudurier +;* Copyright (c) 2014 Tiancheng "Timothy" Gu +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +section .text + +; void get_pixels_8x4_sym_sse2(int16_t *block, const uint8_t *pixels, +; ptrdiff_t line_size) +INIT_XMM sse2 +cglobal get_pixels_8x4_sym, 3,3,5, block, pixels, linesize + pxor m4, m4 + movq m0, [pixelsq] + add pixelsq, linesizeq + movq m1, [pixelsq] + movq m2, [pixelsq+linesizeq] + movq m3, [pixelsq+linesizeq*2] + punpcklbw m0, m4 + punpcklbw m1, m4 + punpcklbw m2, m4 + punpcklbw m3, m4 + mova [blockq ], m0 + mova [blockq+16 ], m1 + mova [blockq+32 ], m2 + mova [blockq+48 ], m3 + mova [blockq+64 ], m3 + mova [blockq+80 ], m2 + mova [blockq+96 ], m1 + mova [blockq+112], m0 + RET diff --git a/libavcodec/x86/dnxhdenc.c b/libavcodec/x86/dnxhdenc.c deleted file mode 100644 index c7e776a4c..000000000 --- a/libavcodec/x86/dnxhdenc.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * VC3/DNxHD SIMD functions - * Copyright (c) 2007 Baptiste Coudurier - * - * VC-3 encoder funded by the British Broadcasting Corporation - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/attributes.h" -#include "libavutil/x86/asm.h" -#include "libavutil/x86/cpu.h" -#include "libavcodec/dnxhdenc.h" - -#if HAVE_SSE2_INLINE - -static void get_pixels_8x4_sym_sse2(int16_t *block, const uint8_t *pixels, int line_size) -{ - __asm__ volatile( - "pxor %%xmm5, %%xmm5 \n\t" - "movq (%0), %%xmm0 \n\t" - "add %2, %0 \n\t" - "movq (%0), %%xmm1 \n\t" - "movq (%0, %2), %%xmm2 \n\t" - "movq (%0, %2,2), %%xmm3 \n\t" - "punpcklbw %%xmm5, %%xmm0 \n\t" - "punpcklbw %%xmm5, %%xmm1 \n\t" - "punpcklbw %%xmm5, %%xmm2 \n\t" - "punpcklbw %%xmm5, %%xmm3 \n\t" - "movdqa %%xmm0, (%1) \n\t" - "movdqa %%xmm1, 16(%1) \n\t" - "movdqa %%xmm2, 32(%1) \n\t" - "movdqa %%xmm3, 48(%1) \n\t" - "movdqa %%xmm3 , 64(%1) \n\t" - "movdqa %%xmm2 , 80(%1) \n\t" - "movdqa %%xmm1 , 96(%1) \n\t" - "movdqa %%xmm0, 112(%1) \n\t" - : "+r" (pixels) - : "r" (block), "r" ((x86_reg)line_size) - ); -} - -#endif /* HAVE_SSE2_INLINE */ - -av_cold void ff_dnxhdenc_init_x86(DNXHDEncContext *ctx) -{ -#if HAVE_SSE2_INLINE - if (INLINE_SSE2(av_get_cpu_flags())) { - if (ctx->cid_table->bit_depth == 8) - ctx->get_pixels_8x4_sym = get_pixels_8x4_sym_sse2; - } -#endif /* HAVE_SSE2_INLINE */ -} diff --git a/libavcodec/sparc/dsputil_vis.c b/libavcodec/x86/dnxhdenc_init.c similarity index 55% rename from libavcodec/sparc/dsputil_vis.c rename to libavcodec/x86/dnxhdenc_init.c index 414d6ca50..3b0226418 100644 --- a/libavcodec/sparc/dsputil_vis.c +++ b/libavcodec/x86/dnxhdenc_init.c @@ -1,5 +1,8 @@ /* - * Copyright (C) 2003 David S. Miller + * VC3/DNxHD SIMD functions + * Copyright (c) 2007 Baptiste Coudurier + * + * VC-3 encoder funded by the British Broadcasting Corporation * * This file is part of FFmpeg. * @@ -19,22 +22,18 @@ */ #include "libavutil/attributes.h" -#include "libavcodec/dsputil.h" -#include "dsputil_vis.h" -#include "vis.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/dnxhdenc.h" -av_cold void ff_dsputil_init_vis(DSPContext *c, AVCodecContext *avctx) +void ff_get_pixels_8x4_sym_sse2(int16_t *block, const uint8_t *pixels, + ptrdiff_t line_size); + +av_cold void ff_dnxhdenc_init_x86(DNXHDEncContext *ctx) { - /* VIS-specific optimizations */ - int accel = vis_level (); - const int high_bit_depth = avctx->bits_per_raw_sample > 8; - - if (accel & ACCEL_SPARC_VIS && !high_bit_depth) { - if (avctx->idct_algo == FF_IDCT_SIMPLEVIS) { - c->idct_put = ff_simple_idct_put_vis; - c->idct_add = ff_simple_idct_add_vis; - c->idct = ff_simple_idct_vis; - c->idct_permutation_type = FF_TRANSPOSE_IDCT_PERM; - } - } +#if HAVE_SSE2_EXTERNAL + if (EXTERNAL_SSE2(av_get_cpu_flags())) { + if (ctx->cid_table->bit_depth == 8) + ctx->get_pixels_8x4_sym = ff_get_pixels_8x4_sym_sse2; + } +#endif /* HAVE_SSE2_EXTERNAL */ } diff --git a/libavcodec/x86/dsputil.asm b/libavcodec/x86/dsputil.asm deleted file mode 100644 index 7162034c6..000000000 --- a/libavcodec/x86/dsputil.asm +++ /dev/null @@ -1,654 +0,0 @@ -;****************************************************************************** -;* MMX optimized DSP utils -;* Copyright (c) 2008 Loren Merritt -;* Copyright (c) 2003-2013 Michael Niedermayer -;* Copyright (c) 2013 Daniel Kang -;* -;* This file is part of FFmpeg. -;* -;* FFmpeg is free software; you can redistribute it and/or -;* modify it under the terms of the GNU Lesser General Public -;* License as published by the Free Software Foundation; either -;* version 2.1 of the License, or (at your option) any later version. -;* -;* FFmpeg is distributed in the hope that it will be useful, -;* but WITHOUT ANY WARRANTY; without even the implied warranty of -;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;* Lesser General Public License for more details. -;* -;* You should have received a copy of the GNU Lesser General Public -;* License along with FFmpeg; if not, write to the Free Software -;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -;****************************************************************************** - -%include "libavutil/x86/x86util.asm" - -SECTION_RODATA -pb_f: times 16 db 15 -pb_zzzzzzzz77777777: times 8 db -1 -pb_7: times 8 db 7 -pb_zzzz3333zzzzbbbb: db -1,-1,-1,-1,3,3,3,3,-1,-1,-1,-1,11,11,11,11 -pb_zz11zz55zz99zzdd: db -1,-1,1,1,-1,-1,5,5,-1,-1,9,9,-1,-1,13,13 -pb_revwords: SHUFFLE_MASK_W 7, 6, 5, 4, 3, 2, 1, 0 -pd_16384: times 4 dd 16384 -pb_bswap32: db 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 - -SECTION_TEXT - -%macro SCALARPRODUCT 0 -; int scalarproduct_int16(int16_t *v1, int16_t *v2, int order) -cglobal scalarproduct_int16, 3,3,3, v1, v2, order - shl orderq, 1 - add v1q, orderq - add v2q, orderq - neg orderq - pxor m2, m2 -.loop: - movu m0, [v1q + orderq] - movu m1, [v1q + orderq + mmsize] - pmaddwd m0, [v2q + orderq] - pmaddwd m1, [v2q + orderq + mmsize] - paddd m2, m0 - paddd m2, m1 - add orderq, mmsize*2 - jl .loop -%if mmsize == 16 - movhlps m0, m2 - paddd m2, m0 - pshuflw m0, m2, 0x4e -%else - pshufw m0, m2, 0x4e -%endif - paddd m2, m0 - movd eax, m2 - RET - -; int scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, int order, int mul) -cglobal scalarproduct_and_madd_int16, 4,4,8, v1, v2, v3, order, mul - shl orderq, 1 - movd m7, mulm -%if mmsize == 16 - pshuflw m7, m7, 0 - punpcklqdq m7, m7 -%else - pshufw m7, m7, 0 -%endif - pxor m6, m6 - add v1q, orderq - add v2q, orderq - add v3q, orderq - neg orderq -.loop: - movu m0, [v2q + orderq] - movu m1, [v2q + orderq + mmsize] - mova m4, [v1q + orderq] - mova m5, [v1q + orderq + mmsize] - movu m2, [v3q + orderq] - movu m3, [v3q + orderq + mmsize] - pmaddwd m0, m4 - pmaddwd m1, m5 - pmullw m2, m7 - pmullw m3, m7 - paddd m6, m0 - paddd m6, m1 - paddw m2, m4 - paddw m3, m5 - mova [v1q + orderq], m2 - mova [v1q + orderq + mmsize], m3 - add orderq, mmsize*2 - jl .loop -%if mmsize == 16 - movhlps m0, m6 - paddd m6, m0 - pshuflw m0, m6, 0x4e -%else - pshufw m0, m6, 0x4e -%endif - paddd m6, m0 - movd eax, m6 - RET -%endmacro - -INIT_MMX mmxext -SCALARPRODUCT -INIT_XMM sse2 -SCALARPRODUCT - -%macro SCALARPRODUCT_LOOP 1 -align 16 -.loop%1: - sub orderq, mmsize*2 -%if %1 - mova m1, m4 - mova m4, [v2q + orderq] - mova m0, [v2q + orderq + mmsize] - palignr m1, m0, %1 - palignr m0, m4, %1 - mova m3, m5 - mova m5, [v3q + orderq] - mova m2, [v3q + orderq + mmsize] - palignr m3, m2, %1 - palignr m2, m5, %1 -%else - mova m0, [v2q + orderq] - mova m1, [v2q + orderq + mmsize] - mova m2, [v3q + orderq] - mova m3, [v3q + orderq + mmsize] -%endif - %define t0 [v1q + orderq] - %define t1 [v1q + orderq + mmsize] -%if ARCH_X86_64 - mova m8, t0 - mova m9, t1 - %define t0 m8 - %define t1 m9 -%endif - pmaddwd m0, t0 - pmaddwd m1, t1 - pmullw m2, m7 - pmullw m3, m7 - paddw m2, t0 - paddw m3, t1 - paddd m6, m0 - paddd m6, m1 - mova [v1q + orderq], m2 - mova [v1q + orderq + mmsize], m3 - jg .loop%1 -%if %1 - jmp .end -%endif -%endmacro - -; int scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, int order, int mul) -INIT_XMM ssse3 -cglobal scalarproduct_and_madd_int16, 4,5,10, v1, v2, v3, order, mul - shl orderq, 1 - movd m7, mulm - pshuflw m7, m7, 0 - punpcklqdq m7, m7 - pxor m6, m6 - mov r4d, v2d - and r4d, 15 - and v2q, ~15 - and v3q, ~15 - mova m4, [v2q + orderq] - mova m5, [v3q + orderq] - ; linear is faster than branch tree or jump table, because the branches taken are cyclic (i.e. predictable) - cmp r4d, 0 - je .loop0 - cmp r4d, 2 - je .loop2 - cmp r4d, 4 - je .loop4 - cmp r4d, 6 - je .loop6 - cmp r4d, 8 - je .loop8 - cmp r4d, 10 - je .loop10 - cmp r4d, 12 - je .loop12 -SCALARPRODUCT_LOOP 14 -SCALARPRODUCT_LOOP 12 -SCALARPRODUCT_LOOP 10 -SCALARPRODUCT_LOOP 8 -SCALARPRODUCT_LOOP 6 -SCALARPRODUCT_LOOP 4 -SCALARPRODUCT_LOOP 2 -SCALARPRODUCT_LOOP 0 -.end: - movhlps m0, m6 - paddd m6, m0 - pshuflw m0, m6, 0x4e - paddd m6, m0 - movd eax, m6 - RET - - -;----------------------------------------------------------------------------- -; void ff_apply_window_int16(int16_t *output, const int16_t *input, -; const int16_t *window, unsigned int len) -;----------------------------------------------------------------------------- - -%macro REVERSE_WORDS 1-2 -%if cpuflag(ssse3) && notcpuflag(atom) - pshufb %1, %2 -%elif cpuflag(sse2) - pshuflw %1, %1, 0x1B - pshufhw %1, %1, 0x1B - pshufd %1, %1, 0x4E -%elif cpuflag(mmxext) - pshufw %1, %1, 0x1B -%endif -%endmacro - -%macro MUL16FIXED 3 -%if cpuflag(ssse3) ; dst, src, unused -; dst = ((dst * src) + (1<<14)) >> 15 - pmulhrsw %1, %2 -%elif cpuflag(mmxext) ; dst, src, temp -; dst = (dst * src) >> 15 -; pmulhw cuts off the bottom bit, so we have to lshift by 1 and add it back -; in from the pmullw result. - mova %3, %1 - pmulhw %1, %2 - pmullw %3, %2 - psrlw %3, 15 - psllw %1, 1 - por %1, %3 -%endif -%endmacro - -%macro APPLY_WINDOW_INT16 1 ; %1 bitexact version -%if %1 -cglobal apply_window_int16, 4,5,6, output, input, window, offset, offset2 -%else -cglobal apply_window_int16_round, 4,5,6, output, input, window, offset, offset2 -%endif - lea offset2q, [offsetq-mmsize] -%if cpuflag(ssse3) && notcpuflag(atom) - mova m5, [pb_revwords] - ALIGN 16 -%elif %1 - mova m5, [pd_16384] -%endif -.loop: -%if cpuflag(ssse3) - ; This version does the 16x16->16 multiplication in-place without expanding - ; to 32-bit. The ssse3 version is bit-identical. - mova m0, [windowq+offset2q] - mova m1, [ inputq+offset2q] - pmulhrsw m1, m0 - REVERSE_WORDS m0, m5 - pmulhrsw m0, [ inputq+offsetq ] - mova [outputq+offset2q], m1 - mova [outputq+offsetq ], m0 -%elif %1 - ; This version expands 16-bit to 32-bit, multiplies by the window, - ; adds 16384 for rounding, right shifts 15, then repacks back to words to - ; save to the output. The window is reversed for the second half. - mova m3, [windowq+offset2q] - mova m4, [ inputq+offset2q] - pxor m0, m0 - punpcklwd m0, m3 - punpcklwd m1, m4 - pmaddwd m0, m1 - paddd m0, m5 - psrad m0, 15 - pxor m2, m2 - punpckhwd m2, m3 - punpckhwd m1, m4 - pmaddwd m2, m1 - paddd m2, m5 - psrad m2, 15 - packssdw m0, m2 - mova [outputq+offset2q], m0 - REVERSE_WORDS m3 - mova m4, [ inputq+offsetq] - pxor m0, m0 - punpcklwd m0, m3 - punpcklwd m1, m4 - pmaddwd m0, m1 - paddd m0, m5 - psrad m0, 15 - pxor m2, m2 - punpckhwd m2, m3 - punpckhwd m1, m4 - pmaddwd m2, m1 - paddd m2, m5 - psrad m2, 15 - packssdw m0, m2 - mova [outputq+offsetq], m0 -%else - ; This version does the 16x16->16 multiplication in-place without expanding - ; to 32-bit. The mmxext and sse2 versions do not use rounding, and - ; therefore are not bit-identical to the C version. - mova m0, [windowq+offset2q] - mova m1, [ inputq+offset2q] - mova m2, [ inputq+offsetq ] - MUL16FIXED m1, m0, m3 - REVERSE_WORDS m0 - MUL16FIXED m2, m0, m3 - mova [outputq+offset2q], m1 - mova [outputq+offsetq ], m2 -%endif - add offsetd, mmsize - sub offset2d, mmsize - jae .loop - REP_RET -%endmacro - -INIT_MMX mmxext -APPLY_WINDOW_INT16 0 -INIT_XMM sse2 -APPLY_WINDOW_INT16 0 - -INIT_MMX mmxext -APPLY_WINDOW_INT16 1 -INIT_XMM sse2 -APPLY_WINDOW_INT16 1 -INIT_XMM ssse3 -APPLY_WINDOW_INT16 1 -INIT_XMM ssse3, atom -APPLY_WINDOW_INT16 1 - - -; void add_hfyu_median_prediction_mmxext(uint8_t *dst, const uint8_t *top, const uint8_t *diff, int w, int *left, int *left_top) -INIT_MMX mmxext -cglobal add_hfyu_median_prediction, 6,6,0, dst, top, diff, w, left, left_top - movq mm0, [topq] - movq mm2, mm0 - movd mm4, [left_topq] - psllq mm2, 8 - movq mm1, mm0 - por mm4, mm2 - movd mm3, [leftq] - psubb mm0, mm4 ; t-tl - add dstq, wq - add topq, wq - add diffq, wq - neg wq - jmp .skip -.loop: - movq mm4, [topq+wq] - movq mm0, mm4 - psllq mm4, 8 - por mm4, mm1 - movq mm1, mm0 ; t - psubb mm0, mm4 ; t-tl -.skip: - movq mm2, [diffq+wq] -%assign i 0 -%rep 8 - movq mm4, mm0 - paddb mm4, mm3 ; t-tl+l - movq mm5, mm3 - pmaxub mm3, mm1 - pminub mm5, mm1 - pminub mm3, mm4 - pmaxub mm3, mm5 ; median - paddb mm3, mm2 ; +residual -%if i==0 - movq mm7, mm3 - psllq mm7, 56 -%else - movq mm6, mm3 - psrlq mm7, 8 - psllq mm6, 56 - por mm7, mm6 -%endif -%if i<7 - psrlq mm0, 8 - psrlq mm1, 8 - psrlq mm2, 8 -%endif -%assign i i+1 -%endrep - movq [dstq+wq], mm7 - add wq, 8 - jl .loop - movzx r2d, byte [dstq-1] - mov [leftq], r2d - movzx r2d, byte [topq-1] - mov [left_topq], r2d - RET - - -%macro ADD_HFYU_LEFT_LOOP 2 ; %1 = dst_is_aligned, %2 = src_is_aligned - add srcq, wq - add dstq, wq - neg wq -%%.loop: -%if %2 - mova m1, [srcq+wq] -%else - movu m1, [srcq+wq] -%endif - mova m2, m1 - psllw m1, 8 - paddb m1, m2 - mova m2, m1 - pshufb m1, m3 - paddb m1, m2 - pshufb m0, m5 - mova m2, m1 - pshufb m1, m4 - paddb m1, m2 -%if mmsize == 16 - mova m2, m1 - pshufb m1, m6 - paddb m1, m2 -%endif - paddb m0, m1 -%if %1 - mova [dstq+wq], m0 -%else - movq [dstq+wq], m0 - movhps [dstq+wq+8], m0 -%endif - add wq, mmsize - jl %%.loop - mov eax, mmsize-1 - sub eax, wd - movd m1, eax - pshufb m0, m1 - movd eax, m0 - RET -%endmacro - -; int add_hfyu_left_prediction(uint8_t *dst, const uint8_t *src, int w, int left) -INIT_MMX ssse3 -cglobal add_hfyu_left_prediction, 3,3,7, dst, src, w, left -.skip_prologue: - mova m5, [pb_7] - mova m4, [pb_zzzz3333zzzzbbbb] - mova m3, [pb_zz11zz55zz99zzdd] - movd m0, leftm - psllq m0, 56 - ADD_HFYU_LEFT_LOOP 1, 1 - -INIT_XMM sse4 -cglobal add_hfyu_left_prediction, 3,3,7, dst, src, w, left - mova m5, [pb_f] - mova m6, [pb_zzzzzzzz77777777] - mova m4, [pb_zzzz3333zzzzbbbb] - mova m3, [pb_zz11zz55zz99zzdd] - movd m0, leftm - pslldq m0, 15 - test srcq, 15 - jnz .src_unaligned - test dstq, 15 - jnz .dst_unaligned - ADD_HFYU_LEFT_LOOP 1, 1 -.dst_unaligned: - ADD_HFYU_LEFT_LOOP 0, 1 -.src_unaligned: - ADD_HFYU_LEFT_LOOP 0, 0 - - -;----------------------------------------------------------------------------- -; void ff_vector_clip_int32(int32_t *dst, const int32_t *src, int32_t min, -; int32_t max, unsigned int len) -;----------------------------------------------------------------------------- - -; %1 = number of xmm registers used -; %2 = number of inline load/process/store loops per asm loop -; %3 = process 4*mmsize (%3=0) or 8*mmsize (%3=1) bytes per loop -; %4 = CLIPD function takes min/max as float instead of int (CLIPD_SSE2) -; %5 = suffix -%macro VECTOR_CLIP_INT32 4-5 -cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len -%if %4 - cvtsi2ss m4, minm - cvtsi2ss m5, maxm -%else - movd m4, minm - movd m5, maxm -%endif - SPLATD m4 - SPLATD m5 -.loop: -%assign %%i 1 -%rep %2 - mova m0, [srcq+mmsize*0*%%i] - mova m1, [srcq+mmsize*1*%%i] - mova m2, [srcq+mmsize*2*%%i] - mova m3, [srcq+mmsize*3*%%i] -%if %3 - mova m7, [srcq+mmsize*4*%%i] - mova m8, [srcq+mmsize*5*%%i] - mova m9, [srcq+mmsize*6*%%i] - mova m10, [srcq+mmsize*7*%%i] -%endif - CLIPD m0, m4, m5, m6 - CLIPD m1, m4, m5, m6 - CLIPD m2, m4, m5, m6 - CLIPD m3, m4, m5, m6 -%if %3 - CLIPD m7, m4, m5, m6 - CLIPD m8, m4, m5, m6 - CLIPD m9, m4, m5, m6 - CLIPD m10, m4, m5, m6 -%endif - mova [dstq+mmsize*0*%%i], m0 - mova [dstq+mmsize*1*%%i], m1 - mova [dstq+mmsize*2*%%i], m2 - mova [dstq+mmsize*3*%%i], m3 -%if %3 - mova [dstq+mmsize*4*%%i], m7 - mova [dstq+mmsize*5*%%i], m8 - mova [dstq+mmsize*6*%%i], m9 - mova [dstq+mmsize*7*%%i], m10 -%endif -%assign %%i %%i+1 -%endrep - add srcq, mmsize*4*(%2+%3) - add dstq, mmsize*4*(%2+%3) - sub lend, mmsize*(%2+%3) - jg .loop - REP_RET -%endmacro - -INIT_MMX mmx -%define CLIPD CLIPD_MMX -VECTOR_CLIP_INT32 0, 1, 0, 0 -INIT_XMM sse2 -VECTOR_CLIP_INT32 6, 1, 0, 0, _int -%define CLIPD CLIPD_SSE2 -VECTOR_CLIP_INT32 6, 2, 0, 1 -INIT_XMM sse4 -%define CLIPD CLIPD_SSE41 -%ifdef m8 -VECTOR_CLIP_INT32 11, 1, 1, 0 -%else -VECTOR_CLIP_INT32 6, 1, 0, 0 -%endif - -; %1 = aligned/unaligned -%macro BSWAP_LOOPS 1 - mov r3, r2 - sar r2, 3 - jz .left4_%1 -.loop8_%1: - mov%1 m0, [r1 + 0] - mov%1 m1, [r1 + 16] -%if cpuflag(ssse3) - pshufb m0, m2 - pshufb m1, m2 - mov%1 [r0 + 0], m0 - mov%1 [r0 + 16], m1 -%else - pshuflw m0, m0, 10110001b - pshuflw m1, m1, 10110001b - pshufhw m0, m0, 10110001b - pshufhw m1, m1, 10110001b - mova m2, m0 - mova m3, m1 - psllw m0, 8 - psllw m1, 8 - psrlw m2, 8 - psrlw m3, 8 - por m2, m0 - por m3, m1 - mov%1 [r0 + 0], m2 - mov%1 [r0 + 16], m3 -%endif - add r0, 32 - add r1, 32 - dec r2 - jnz .loop8_%1 -.left4_%1: - mov r2, r3 - and r3, 4 - jz .left - mov%1 m0, [r1] -%if cpuflag(ssse3) - pshufb m0, m2 - mov%1 [r0], m0 -%else - pshuflw m0, m0, 10110001b - pshufhw m0, m0, 10110001b - mova m2, m0 - psllw m0, 8 - psrlw m2, 8 - por m2, m0 - mov%1 [r0], m2 -%endif - add r1, 16 - add r0, 16 -%endmacro - -; void bswap_buf(uint32_t *dst, const uint32_t *src, int w); -%macro BSWAP32_BUF 0 -%if cpuflag(ssse3) -cglobal bswap32_buf, 3,4,3 - mov r3, r1 - mova m2, [pb_bswap32] -%else -cglobal bswap32_buf, 3,4,5 - mov r3, r1 -%endif - or r3, r0 - and r3, 15 - jz .start_align - BSWAP_LOOPS u - jmp .left -.start_align: - BSWAP_LOOPS a -.left: -%if cpuflag(ssse3) - mov r3, r2 - and r2, 2 - jz .left1 - movq m0, [r1] - pshufb m0, m2 - movq [r0], m0 - add r1, 8 - add r0, 8 -.left1: - and r3, 1 - jz .end - mov r2d, [r1] - bswap r2d - mov [r0], r2d -%else - and r2, 3 - jz .end -.loop2: - mov r3d, [r1] - bswap r3d - mov [r0], r3d - add r1, 4 - add r0, 4 - dec r2 - jnz .loop2 -%endif -.end: - RET -%endmacro - -INIT_XMM sse2 -BSWAP32_BUF - -INIT_XMM ssse3 -BSWAP32_BUF diff --git a/libavcodec/x86/dsputil_init.c b/libavcodec/x86/dsputil_init.c index e0b40410a..4231f65e5 100644 --- a/libavcodec/x86/dsputil_init.c +++ b/libavcodec/x86/dsputil_init.c @@ -1,7 +1,10 @@ /* + * MMX optimized DSP utils * Copyright (c) 2000, 2001 Fabrice Bellard * Copyright (c) 2002-2004 Michael Niedermayer * + * MMX optimization by Nick Kurshev + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -19,682 +22,382 @@ * 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/internal.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/dsputil.h" -#include "libavcodec/simple_idct.h" -#include "libavcodec/version.h" +#include "libavcodec/mpegvideo.h" #include "dsputil_x86.h" -#include "idct_xvid.h" -void ff_put_pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, - int dstStride, int src1Stride, int h); -void ff_put_no_rnd_pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, - uint8_t *src2, int dstStride, - int src1Stride, int h); -void ff_avg_pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, - int dstStride, int src1Stride, int h); -void ff_put_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, - int dstStride, int src1Stride, int h); -void ff_avg_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, - int dstStride, int src1Stride, int h); -void ff_put_no_rnd_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, - int dstStride, int src1Stride, int h); -void ff_put_mpeg4_qpel16_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, - int dstStride, int srcStride, int h); -void ff_avg_mpeg4_qpel16_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, - int dstStride, int srcStride, int h); -void ff_put_no_rnd_mpeg4_qpel16_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, - int dstStride, int srcStride, - int h); -void ff_put_mpeg4_qpel8_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, - int dstStride, int srcStride, int h); -void ff_avg_mpeg4_qpel8_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, - int dstStride, int srcStride, int h); -void ff_put_no_rnd_mpeg4_qpel8_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, - int dstStride, int srcStride, - int h); -void ff_put_mpeg4_qpel16_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, - int dstStride, int srcStride); -void ff_avg_mpeg4_qpel16_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, - int dstStride, int srcStride); -void ff_put_no_rnd_mpeg4_qpel16_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, - int dstStride, int srcStride); -void ff_put_mpeg4_qpel8_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, - int dstStride, int srcStride); -void ff_avg_mpeg4_qpel8_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, - int dstStride, int srcStride); -void ff_put_no_rnd_mpeg4_qpel8_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, - int dstStride, int srcStride); -#define ff_put_no_rnd_pixels16_mmxext ff_put_pixels16_mmxext -#define ff_put_no_rnd_pixels8_mmxext ff_put_pixels8_mmxext +int ff_sum_abs_dctelem_mmx(int16_t *block); +int ff_sum_abs_dctelem_mmxext(int16_t *block); +int ff_sum_abs_dctelem_sse2(int16_t *block); +int ff_sum_abs_dctelem_ssse3(int16_t *block); +int ff_sse8_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h); +int ff_sse16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h); +int ff_sse16_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h); +int ff_hf_noise8_mmx(uint8_t *pix1, int lsize, int h); +int ff_hf_noise16_mmx(uint8_t *pix1, int lsize, int h); -int32_t ff_scalarproduct_int16_mmxext(const int16_t *v1, const int16_t *v2, - int order); -int32_t ff_scalarproduct_int16_sse2(const int16_t *v1, const int16_t *v2, - int order); -int32_t ff_scalarproduct_and_madd_int16_mmxext(int16_t *v1, const int16_t *v2, - const int16_t *v3, - int order, int mul); -int32_t ff_scalarproduct_and_madd_int16_sse2(int16_t *v1, const int16_t *v2, - const int16_t *v3, - int order, int mul); -int32_t ff_scalarproduct_and_madd_int16_ssse3(int16_t *v1, const int16_t *v2, - const int16_t *v3, - int order, int mul); +#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); -void ff_bswap32_buf_ssse3(uint32_t *dst, const uint32_t *src, int w); -void ff_bswap32_buf_sse2(uint32_t *dst, const uint32_t *src, int w); - -void ff_add_hfyu_median_prediction_mmxext(uint8_t *dst, const uint8_t *top, - const uint8_t *diff, int w, - int *left, int *left_top); -int ff_add_hfyu_left_prediction_ssse3(uint8_t *dst, const uint8_t *src, - int w, int left); -int ff_add_hfyu_left_prediction_sse4(uint8_t *dst, const uint8_t *src, - int w, int left); - -void ff_vector_clip_int32_mmx (int32_t *dst, const int32_t *src, - int32_t min, int32_t max, unsigned int len); -void ff_vector_clip_int32_sse2 (int32_t *dst, const int32_t *src, - int32_t min, int32_t max, unsigned int len); -void ff_vector_clip_int32_int_sse2(int32_t *dst, const int32_t *src, - int32_t min, int32_t max, unsigned int len); -void ff_vector_clip_int32_sse4 (int32_t *dst, const int32_t *src, - int32_t min, int32_t max, unsigned int len); +hadamard_func(mmx) +hadamard_func(mmxext) +hadamard_func(sse2) +hadamard_func(ssse3) #if HAVE_YASM +static int nsse16_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2, + int line_size, int h) +{ + int score1, score2; -PIXELS16(static, ff_avg, , , _mmxext) -PIXELS16(static, ff_put, , , _mmxext) + if (c) + score1 = c->dsp.sse[0](c, pix1, pix2, line_size, h); + else + score1 = ff_sse16_mmx(c, pix1, pix2, line_size, h); + score2 = ff_hf_noise16_mmx(pix1, line_size, h) + ff_hf_noise8_mmx(pix1+8, line_size, h) + - ff_hf_noise16_mmx(pix2, line_size, h) - ff_hf_noise8_mmx(pix2+8, line_size, h); -#define QPEL_OP(OPNAME, RND, MMX) \ -static void OPNAME ## qpel8_mc00_ ## MMX (uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - ff_ ## OPNAME ## pixels8_ ## MMX(dst, src, stride, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc10_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t temp[8]; \ - uint8_t * const half = (uint8_t*)temp; \ - ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, \ - stride, 8); \ - ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, src, half, \ - stride, stride, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc20_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - ff_ ## OPNAME ## mpeg4_qpel8_h_lowpass_ ## MMX(dst, src, stride, \ - stride, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc30_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t temp[8]; \ - uint8_t * const half = (uint8_t*)temp; \ - ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, \ - stride, 8); \ - ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, src + 1, half, stride, \ - stride, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc01_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t temp[8]; \ - uint8_t * const half = (uint8_t*)temp; \ - ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, \ - 8, stride); \ - ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, src, half, \ - stride, stride, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc02_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - ff_ ## OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, src, \ - stride, stride); \ -} \ - \ -static void OPNAME ## qpel8_mc03_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t temp[8]; \ - uint8_t * const half = (uint8_t*)temp; \ - ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, \ - 8, stride); \ - ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, src + stride, half, stride,\ - stride, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc11_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[8 + 9]; \ - uint8_t * const halfH = ((uint8_t*)half) + 64; \ - uint8_t * const halfHV = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ - stride, 9); \ - ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, \ - stride, 9); \ - ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ - ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, \ - stride, 8, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc31_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[8 + 9]; \ - uint8_t * const halfH = ((uint8_t*)half) + 64; \ - uint8_t * const halfHV = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ - stride, 9); \ - ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src + 1, halfH, 8, \ - stride, 9); \ - ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ - ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, \ - stride, 8, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc13_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[8 + 9]; \ - uint8_t * const halfH = ((uint8_t*)half) + 64; \ - uint8_t * const halfHV = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ - stride, 9); \ - ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, \ - stride, 9); \ - ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ - ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH + 8, halfHV, \ - stride, 8, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc33_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[8 + 9]; \ - uint8_t * const halfH = ((uint8_t*)half) + 64; \ - uint8_t * const halfHV = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ - stride, 9); \ - ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src + 1, halfH, 8, \ - stride, 9); \ - ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ - ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH + 8, halfHV, \ - stride, 8, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc21_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[8 + 9]; \ - uint8_t * const halfH = ((uint8_t*)half) + 64; \ - uint8_t * const halfHV = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ - stride, 9); \ - ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ - ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, \ - stride, 8, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc23_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[8 + 9]; \ - uint8_t * const halfH = ((uint8_t*)half) + 64; \ - uint8_t * const halfHV = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ - stride, 9); \ - ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ - ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH + 8, halfHV, \ - stride, 8, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc12_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[8 + 9]; \ - uint8_t * const halfH = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ - stride, 9); \ - ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, \ - 8, stride, 9); \ - ff_ ## OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, \ - stride, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc32_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[8 + 9]; \ - uint8_t * const halfH = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ - stride, 9); \ - ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src + 1, halfH, 8, \ - stride, 9); \ - ff_ ## OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, \ - stride, 8); \ -} \ - \ -static void OPNAME ## qpel8_mc22_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[9]; \ - uint8_t * const halfH = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ - stride, 9); \ - ff_ ## OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, \ - stride, 8); \ -} \ - \ -static void OPNAME ## qpel16_mc00_ ## MMX (uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - ff_ ## OPNAME ## pixels16_ ## MMX(dst, src, stride, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc10_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t temp[32]; \ - uint8_t * const half = (uint8_t*)temp; \ - ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, \ - stride, 16); \ - ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, \ - stride, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc20_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - ff_ ## OPNAME ## mpeg4_qpel16_h_lowpass_ ## MMX(dst, src, \ - stride, stride, 16);\ -} \ - \ -static void OPNAME ## qpel16_mc30_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t temp[32]; \ - uint8_t * const half = (uint8_t*)temp; \ - ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, \ - stride, 16); \ - ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, src + 1, half, \ - stride, stride, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc01_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t temp[32]; \ - uint8_t * const half = (uint8_t*)temp; \ - ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, \ - stride); \ - ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, \ - stride, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc02_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - ff_ ## OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, src, \ - stride, stride); \ -} \ - \ -static void OPNAME ## qpel16_mc03_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t temp[32]; \ - uint8_t * const half = (uint8_t*)temp; \ - ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, \ - stride); \ - ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, src+stride, half, \ - stride, stride, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc11_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[16 * 2 + 17 * 2]; \ - uint8_t * const halfH = ((uint8_t*)half) + 256; \ - uint8_t * const halfHV = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ - stride, 17); \ - ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, \ - stride, 17); \ - ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ - 16, 16); \ - ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, \ - stride, 16, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc31_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[16 * 2 + 17 * 2]; \ - uint8_t * const halfH = ((uint8_t*)half) + 256; \ - uint8_t * const halfHV = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ - stride, 17); \ - ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src + 1, halfH, 16, \ - stride, 17); \ - ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ - 16, 16); \ - ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, \ - stride, 16, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc13_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[16 * 2 + 17 * 2]; \ - uint8_t * const halfH = ((uint8_t*)half) + 256; \ - uint8_t * const halfHV = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ - stride, 17); \ - ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, \ - stride, 17); \ - ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ - 16, 16); \ - ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH + 16, halfHV, \ - stride, 16, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc33_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[16 * 2 + 17 * 2]; \ - uint8_t * const halfH = ((uint8_t*)half) + 256; \ - uint8_t * const halfHV = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ - stride, 17); \ - ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src + 1, halfH, 16, \ - stride, 17); \ - ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ - 16, 16); \ - ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH + 16, halfHV, \ - stride, 16, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc21_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[16 * 2 + 17 * 2]; \ - uint8_t * const halfH = ((uint8_t*)half) + 256; \ - uint8_t * const halfHV = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ - stride, 17); \ - ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ - 16, 16); \ - ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, \ - stride, 16, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc23_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[16 * 2 + 17 * 2]; \ - uint8_t * const halfH = ((uint8_t*)half) + 256; \ - uint8_t * const halfHV = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ - stride, 17); \ - ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ - 16, 16); \ - ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH + 16, halfHV, \ - stride, 16, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc12_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[17 * 2]; \ - uint8_t * const halfH = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ - stride, 17); \ - ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, \ - stride, 17); \ - ff_ ## OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, \ - stride, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc32_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[17 * 2]; \ - uint8_t * const halfH = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ - stride, 17); \ - ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src + 1, halfH, 16, \ - stride, 17); \ - ff_ ## OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, \ - stride, 16); \ -} \ - \ -static void OPNAME ## qpel16_mc22_ ## MMX(uint8_t *dst, uint8_t *src, \ - ptrdiff_t stride) \ -{ \ - uint64_t half[17 * 2]; \ - uint8_t * const halfH = ((uint8_t*)half); \ - ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ - stride, 17); \ - ff_ ## OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, \ - stride, 16); \ + if (c) + return score1 + FFABS(score2) * c->avctx->nsse_weight; + else + return score1 + FFABS(score2) * 8; +} + +static int nsse8_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2, + int line_size, int h) +{ + int score1 = ff_sse8_mmx(c, pix1, pix2, line_size, h); + int score2 = ff_hf_noise8_mmx(pix1, line_size, h) - + ff_hf_noise8_mmx(pix2, line_size, h); + + if (c) + return score1 + FFABS(score2) * c->avctx->nsse_weight; + else + return score1 + FFABS(score2) * 8; } -QPEL_OP(put_, _, mmxext) -QPEL_OP(avg_, _, mmxext) -QPEL_OP(put_no_rnd_, _no_rnd_, mmxext) #endif /* HAVE_YASM */ -#define SET_QPEL_FUNCS(PFX, IDX, SIZE, CPU, PREFIX) \ - do { \ - c->PFX ## _pixels_tab[IDX][ 0] = PREFIX ## PFX ## SIZE ## _mc00_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][ 1] = PREFIX ## PFX ## SIZE ## _mc10_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][ 2] = PREFIX ## PFX ## SIZE ## _mc20_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][ 3] = PREFIX ## PFX ## SIZE ## _mc30_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][ 4] = PREFIX ## PFX ## SIZE ## _mc01_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][ 5] = PREFIX ## PFX ## SIZE ## _mc11_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][ 6] = PREFIX ## PFX ## SIZE ## _mc21_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][ 7] = PREFIX ## PFX ## SIZE ## _mc31_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][ 8] = PREFIX ## PFX ## SIZE ## _mc02_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][ 9] = PREFIX ## PFX ## SIZE ## _mc12_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][10] = PREFIX ## PFX ## SIZE ## _mc22_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][11] = PREFIX ## PFX ## SIZE ## _mc32_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][12] = PREFIX ## PFX ## SIZE ## _mc03_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][13] = PREFIX ## PFX ## SIZE ## _mc13_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][14] = PREFIX ## PFX ## SIZE ## _mc23_ ## CPU; \ - c->PFX ## _pixels_tab[IDX][15] = PREFIX ## PFX ## SIZE ## _mc33_ ## CPU; \ - } while (0) +#if HAVE_INLINE_ASM -static av_cold void dsputil_init_mmx(DSPContext *c, AVCodecContext *avctx, - int cpu_flags) +static int vsad_intra16_mmx(MpegEncContext *v, uint8_t *pix, uint8_t *dummy, + int line_size, int h) { -#if HAVE_MMX_INLINE - const int high_bit_depth = avctx->bits_per_raw_sample > 8; + int tmp; - c->put_pixels_clamped = ff_put_pixels_clamped_mmx; - c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_mmx; - c->add_pixels_clamped = ff_add_pixels_clamped_mmx; + av_assert2((((int) pix) & 7) == 0); + av_assert2((line_size & 7) == 0); - if (!high_bit_depth) { - c->clear_block = ff_clear_block_mmx; - c->clear_blocks = ff_clear_blocks_mmx; - c->draw_edges = ff_draw_edges_mmx; - } +#define SUM(in0, in1, out0, out1) \ + "movq (%0), %%mm2\n" \ + "movq 8(%0), %%mm3\n" \ + "add %2,%0\n" \ + "movq %%mm2, " #out0 "\n" \ + "movq %%mm3, " #out1 "\n" \ + "psubusb " #in0 ", %%mm2\n" \ + "psubusb " #in1 ", %%mm3\n" \ + "psubusb " #out0 ", " #in0 "\n" \ + "psubusb " #out1 ", " #in1 "\n" \ + "por %%mm2, " #in0 "\n" \ + "por %%mm3, " #in1 "\n" \ + "movq " #in0 ", %%mm2\n" \ + "movq " #in1 ", %%mm3\n" \ + "punpcklbw %%mm7, " #in0 "\n" \ + "punpcklbw %%mm7, " #in1 "\n" \ + "punpckhbw %%mm7, %%mm2\n" \ + "punpckhbw %%mm7, %%mm3\n" \ + "paddw " #in1 ", " #in0 "\n" \ + "paddw %%mm3, %%mm2\n" \ + "paddw %%mm2, " #in0 "\n" \ + "paddw " #in0 ", %%mm6\n" -#if CONFIG_VIDEODSP && (ARCH_X86_32 || !HAVE_YASM) - c->gmc = ff_gmc_mmx; -#endif - c->add_bytes = ff_add_bytes_mmx; -#endif /* HAVE_MMX_INLINE */ + __asm__ volatile ( + "movl %3, %%ecx\n" + "pxor %%mm6, %%mm6\n" + "pxor %%mm7, %%mm7\n" + "movq (%0), %%mm0\n" + "movq 8(%0), %%mm1\n" + "add %2, %0\n" + "jmp 2f\n" + "1:\n" -#if HAVE_MMX_EXTERNAL - c->vector_clip_int32 = ff_vector_clip_int32_mmx; -#endif /* HAVE_MMX_EXTERNAL */ + SUM(%%mm4, %%mm5, %%mm0, %%mm1) + "2:\n" + SUM(%%mm0, %%mm1, %%mm4, %%mm5) + + "subl $2, %%ecx\n" + "jnz 1b\n" + + "movq %%mm6, %%mm0\n" + "psrlq $32, %%mm6\n" + "paddw %%mm6, %%mm0\n" + "movq %%mm0, %%mm6\n" + "psrlq $16, %%mm0\n" + "paddw %%mm6, %%mm0\n" + "movd %%mm0, %1\n" + : "+r" (pix), "=r" (tmp) + : "r" ((x86_reg) line_size), "m" (h) + : "%ecx"); + + return tmp & 0xFFFF; } +#undef SUM -static av_cold void dsputil_init_mmxext(DSPContext *c, AVCodecContext *avctx, - int cpu_flags) +static int vsad_intra16_mmxext(MpegEncContext *v, uint8_t *pix, uint8_t *dummy, + int line_size, int h) { -#if HAVE_MMXEXT_INLINE - const int high_bit_depth = avctx->bits_per_raw_sample > 8; + int tmp; - if (!high_bit_depth && avctx->idct_algo == FF_IDCT_XVIDMMX && avctx->lowres == 0) { - c->idct_put = ff_idct_xvid_mmxext_put; - c->idct_add = ff_idct_xvid_mmxext_add; - c->idct = ff_idct_xvid_mmxext; - } -#endif /* HAVE_MMXEXT_INLINE */ + av_assert2((((int) pix) & 7) == 0); + av_assert2((line_size & 7) == 0); -#if HAVE_MMXEXT_EXTERNAL - SET_QPEL_FUNCS(avg_qpel, 0, 16, mmxext, ); - SET_QPEL_FUNCS(avg_qpel, 1, 8, mmxext, ); +#define SUM(in0, in1, out0, out1) \ + "movq (%0), " #out0 "\n" \ + "movq 8(%0), " #out1 "\n" \ + "add %2, %0\n" \ + "psadbw " #out0 ", " #in0 "\n" \ + "psadbw " #out1 ", " #in1 "\n" \ + "paddw " #in1 ", " #in0 "\n" \ + "paddw " #in0 ", %%mm6\n" - SET_QPEL_FUNCS(put_qpel, 0, 16, mmxext, ); - SET_QPEL_FUNCS(put_qpel, 1, 8, mmxext, ); - SET_QPEL_FUNCS(put_no_rnd_qpel, 0, 16, mmxext, ); - SET_QPEL_FUNCS(put_no_rnd_qpel, 1, 8, mmxext, ); + __asm__ volatile ( + "movl %3, %%ecx\n" + "pxor %%mm6, %%mm6\n" + "pxor %%mm7, %%mm7\n" + "movq (%0), %%mm0\n" + "movq 8(%0), %%mm1\n" + "add %2, %0\n" + "jmp 2f\n" + "1:\n" - /* slower than cmov version on AMD */ - if (!(cpu_flags & AV_CPU_FLAG_3DNOW)) - c->add_hfyu_median_prediction = ff_add_hfyu_median_prediction_mmxext; + SUM(%%mm4, %%mm5, %%mm0, %%mm1) + "2:\n" + SUM(%%mm0, %%mm1, %%mm4, %%mm5) - c->scalarproduct_int16 = ff_scalarproduct_int16_mmxext; - c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_mmxext; -#endif /* HAVE_MMXEXT_EXTERNAL */ + "subl $2, %%ecx\n" + "jnz 1b\n" + + "movd %%mm6, %1\n" + : "+r" (pix), "=r" (tmp) + : "r" ((x86_reg) line_size), "m" (h) + : "%ecx"); + + return tmp; } +#undef SUM -static av_cold void dsputil_init_sse(DSPContext *c, AVCodecContext *avctx, - int cpu_flags) +static int vsad16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h) { -#if HAVE_SSE_INLINE - const int high_bit_depth = avctx->bits_per_raw_sample > 8; + int tmp; - c->vector_clipf = ff_vector_clipf_sse; + av_assert2((((int) pix1) & 7) == 0); + av_assert2((((int) pix2) & 7) == 0); + av_assert2((line_size & 7) == 0); - /* XvMCCreateBlocks() may not allocate 16-byte aligned blocks */ - if (CONFIG_XVMC && avctx->hwaccel && avctx->hwaccel->decode_mb) - return; +#define SUM(in0, in1, out0, out1) \ + "movq (%0), %%mm2\n" \ + "movq (%1), " #out0 "\n" \ + "movq 8(%0), %%mm3\n" \ + "movq 8(%1), " #out1 "\n" \ + "add %3, %0\n" \ + "add %3, %1\n" \ + "psubb " #out0 ", %%mm2\n" \ + "psubb " #out1 ", %%mm3\n" \ + "pxor %%mm7, %%mm2\n" \ + "pxor %%mm7, %%mm3\n" \ + "movq %%mm2, " #out0 "\n" \ + "movq %%mm3, " #out1 "\n" \ + "psubusb " #in0 ", %%mm2\n" \ + "psubusb " #in1 ", %%mm3\n" \ + "psubusb " #out0 ", " #in0 "\n" \ + "psubusb " #out1 ", " #in1 "\n" \ + "por %%mm2, " #in0 "\n" \ + "por %%mm3, " #in1 "\n" \ + "movq " #in0 ", %%mm2\n" \ + "movq " #in1 ", %%mm3\n" \ + "punpcklbw %%mm7, " #in0 "\n" \ + "punpcklbw %%mm7, " #in1 "\n" \ + "punpckhbw %%mm7, %%mm2\n" \ + "punpckhbw %%mm7, %%mm3\n" \ + "paddw " #in1 ", " #in0 "\n" \ + "paddw %%mm3, %%mm2\n" \ + "paddw %%mm2, " #in0 "\n" \ + "paddw " #in0 ", %%mm6\n" - if (!high_bit_depth) { - c->clear_block = ff_clear_block_sse; - c->clear_blocks = ff_clear_blocks_sse; - } -#endif /* HAVE_SSE_INLINE */ -#if HAVE_YASM -#if HAVE_INLINE_ASM && CONFIG_VIDEODSP - c->gmc = ff_gmc_sse; -#endif -#endif /* HAVE_YASM */ + __asm__ volatile ( + "movl %4, %%ecx\n" + "pxor %%mm6, %%mm6\n" + "pcmpeqw %%mm7, %%mm7\n" + "psllw $15, %%mm7\n" + "packsswb %%mm7, %%mm7\n" + "movq (%0), %%mm0\n" + "movq (%1), %%mm2\n" + "movq 8(%0), %%mm1\n" + "movq 8(%1), %%mm3\n" + "add %3, %0\n" + "add %3, %1\n" + "psubb %%mm2, %%mm0\n" + "psubb %%mm3, %%mm1\n" + "pxor %%mm7, %%mm0\n" + "pxor %%mm7, %%mm1\n" + "jmp 2f\n" + "1:\n" + + SUM(%%mm4, %%mm5, %%mm0, %%mm1) + "2:\n" + SUM(%%mm0, %%mm1, %%mm4, %%mm5) + + "subl $2, %%ecx\n" + "jnz 1b\n" + + "movq %%mm6, %%mm0\n" + "psrlq $32, %%mm6\n" + "paddw %%mm6, %%mm0\n" + "movq %%mm0, %%mm6\n" + "psrlq $16, %%mm0\n" + "paddw %%mm6, %%mm0\n" + "movd %%mm0, %2\n" + : "+r" (pix1), "+r" (pix2), "=r" (tmp) + : "r" ((x86_reg) line_size), "m" (h) + : "%ecx"); + + return tmp & 0x7FFF; } +#undef SUM -static av_cold void dsputil_init_sse2(DSPContext *c, AVCodecContext *avctx, - int cpu_flags) +static int vsad16_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h) { -#if HAVE_SSE2_INLINE - const int high_bit_depth = avctx->bits_per_raw_sample > 8; + int tmp; - if (!high_bit_depth && avctx->idct_algo == FF_IDCT_XVIDMMX && avctx->lowres == 0) { - c->idct_put = ff_idct_xvid_sse2_put; - c->idct_add = ff_idct_xvid_sse2_add; - c->idct = ff_idct_xvid_sse2; - c->idct_permutation_type = FF_SSE2_IDCT_PERM; - } -#endif /* HAVE_SSE2_INLINE */ + av_assert2((((int) pix1) & 7) == 0); + av_assert2((((int) pix2) & 7) == 0); + av_assert2((line_size & 7) == 0); -#if HAVE_SSE2_EXTERNAL - c->scalarproduct_int16 = ff_scalarproduct_int16_sse2; - c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_sse2; - if (cpu_flags & AV_CPU_FLAG_ATOM) { - c->vector_clip_int32 = ff_vector_clip_int32_int_sse2; - } else { - c->vector_clip_int32 = ff_vector_clip_int32_sse2; - } - c->bswap_buf = ff_bswap32_buf_sse2; -#endif /* HAVE_SSE2_EXTERNAL */ +#define SUM(in0, in1, out0, out1) \ + "movq (%0), " #out0 "\n" \ + "movq (%1), %%mm2\n" \ + "movq 8(%0), " #out1 "\n" \ + "movq 8(%1), %%mm3\n" \ + "add %3, %0\n" \ + "add %3, %1\n" \ + "psubb %%mm2, " #out0 "\n" \ + "psubb %%mm3, " #out1 "\n" \ + "pxor %%mm7, " #out0 "\n" \ + "pxor %%mm7, " #out1 "\n" \ + "psadbw " #out0 ", " #in0 "\n" \ + "psadbw " #out1 ", " #in1 "\n" \ + "paddw " #in1 ", " #in0 "\n" \ + "paddw " #in0 ", %%mm6\n " + + __asm__ volatile ( + "movl %4, %%ecx\n" + "pxor %%mm6, %%mm6\n" + "pcmpeqw %%mm7, %%mm7\n" + "psllw $15, %%mm7\n" + "packsswb %%mm7, %%mm7\n" + "movq (%0), %%mm0\n" + "movq (%1), %%mm2\n" + "movq 8(%0), %%mm1\n" + "movq 8(%1), %%mm3\n" + "add %3, %0\n" + "add %3, %1\n" + "psubb %%mm2, %%mm0\n" + "psubb %%mm3, %%mm1\n" + "pxor %%mm7, %%mm0\n" + "pxor %%mm7, %%mm1\n" + "jmp 2f\n" + "1:\n" + + SUM(%%mm4, %%mm5, %%mm0, %%mm1) + "2:\n" + SUM(%%mm0, %%mm1, %%mm4, %%mm5) + + "subl $2, %%ecx\n" + "jnz 1b\n" + + "movd %%mm6, %2\n" + : "+r" (pix1), "+r" (pix2), "=r" (tmp) + : "r" ((x86_reg) line_size), "m" (h) + : "%ecx"); + + return tmp; } +#undef SUM -static av_cold void dsputil_init_ssse3(DSPContext *c, AVCodecContext *avctx, - int cpu_flags) -{ -#if HAVE_SSSE3_EXTERNAL - c->add_hfyu_left_prediction = ff_add_hfyu_left_prediction_ssse3; - if (cpu_flags & AV_CPU_FLAG_SSE4) // not really SSE4, just slow on Conroe - c->add_hfyu_left_prediction = ff_add_hfyu_left_prediction_sse4; - if (!(cpu_flags & (AV_CPU_FLAG_SSE42 | AV_CPU_FLAG_3DNOW))) // cachesplit - c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_ssse3; - c->bswap_buf = ff_bswap32_buf_ssse3; -#endif /* HAVE_SSSE3_EXTERNAL */ -} - -static av_cold void dsputil_init_sse4(DSPContext *c, AVCodecContext *avctx, - int cpu_flags) -{ -#if HAVE_SSE4_EXTERNAL - c->vector_clip_int32 = ff_vector_clip_int32_sse4; -#endif /* HAVE_SSE4_EXTERNAL */ -} +#endif /* HAVE_INLINE_ASM */ av_cold void ff_dsputil_init_x86(DSPContext *c, AVCodecContext *avctx) { int cpu_flags = av_get_cpu_flags(); -#if HAVE_7REGS && HAVE_INLINE_ASM - if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_CMOV) - c->add_hfyu_median_prediction = ff_add_hfyu_median_prediction_cmov; -#endif - - if (X86_MMX(cpu_flags)) { #if HAVE_INLINE_ASM - const int idct_algo = avctx->idct_algo; + if (INLINE_MMX(cpu_flags)) { + c->vsad[4] = vsad_intra16_mmx; - if (avctx->lowres == 0 && avctx->bits_per_raw_sample <= 8) { - if (idct_algo == FF_IDCT_AUTO || idct_algo == FF_IDCT_SIMPLEMMX) { - c->idct_put = ff_simple_idct_put_mmx; - c->idct_add = ff_simple_idct_add_mmx; - c->idct = ff_simple_idct_mmx; - c->idct_permutation_type = FF_SIMPLE_IDCT_PERM; - } else if (idct_algo == FF_IDCT_XVIDMMX) { - c->idct_put = ff_idct_xvid_mmx_put; - c->idct_add = ff_idct_xvid_mmx_add; - c->idct = ff_idct_xvid_mmx; - } + if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + c->vsad[0] = vsad16_mmx; } -#endif /* HAVE_INLINE_ASM */ - - dsputil_init_mmx(c, avctx, cpu_flags); } - if (X86_MMXEXT(cpu_flags)) - dsputil_init_mmxext(c, avctx, cpu_flags); + if (INLINE_MMXEXT(cpu_flags)) { + c->vsad[4] = vsad_intra16_mmxext; - if (X86_SSE(cpu_flags)) - dsputil_init_sse(c, avctx, cpu_flags); + if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + c->vsad[0] = vsad16_mmxext; + } + } +#endif /* HAVE_INLINE_ASM */ - if (X86_SSE2(cpu_flags)) - dsputil_init_sse2(c, avctx, cpu_flags); + if (EXTERNAL_MMX(cpu_flags)) { + c->hadamard8_diff[0] = ff_hadamard8_diff16_mmx; + c->hadamard8_diff[1] = ff_hadamard8_diff_mmx; + c->sum_abs_dctelem = ff_sum_abs_dctelem_mmx; + c->sse[0] = ff_sse16_mmx; + c->sse[1] = ff_sse8_mmx; +#if HAVE_YASM + c->nsse[0] = nsse16_mmx; + c->nsse[1] = nsse8_mmx; +#endif + } - if (EXTERNAL_SSSE3(cpu_flags)) - dsputil_init_ssse3(c, avctx, cpu_flags); + if (EXTERNAL_MMXEXT(cpu_flags)) { + c->hadamard8_diff[0] = ff_hadamard8_diff16_mmxext; + c->hadamard8_diff[1] = ff_hadamard8_diff_mmxext; + c->sum_abs_dctelem = ff_sum_abs_dctelem_mmxext; + } - if (EXTERNAL_SSE4(cpu_flags)) - dsputil_init_sse4(c, avctx, cpu_flags); + if (EXTERNAL_SSE2(cpu_flags)) { + c->sse[0] = ff_sse16_sse2; + c->sum_abs_dctelem = ff_sum_abs_dctelem_sse2; - if (CONFIG_ENCODERS) - ff_dsputilenc_init_mmx(c, avctx); +#if HAVE_ALIGNED_STACK + c->hadamard8_diff[0] = ff_hadamard8_diff16_sse2; + c->hadamard8_diff[1] = ff_hadamard8_diff_sse2; +#endif + } + + if (EXTERNAL_SSSE3(cpu_flags)) { + c->sum_abs_dctelem = ff_sum_abs_dctelem_ssse3; +#if HAVE_ALIGNED_STACK + c->hadamard8_diff[0] = ff_hadamard8_diff16_ssse3; + c->hadamard8_diff[1] = ff_hadamard8_diff_ssse3; +#endif + } + + ff_dsputil_init_pix_mmx(c, avctx); } diff --git a/libavcodec/x86/dsputil_mmx.c b/libavcodec/x86/dsputil_mmx.c deleted file mode 100644 index df8cfdb46..000000000 --- a/libavcodec/x86/dsputil_mmx.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - * MMX optimized DSP utils - * Copyright (c) 2000, 2001 Fabrice Bellard - * Copyright (c) 2002-2004 Michael Niedermayer - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * MMX optimization by Nick Kurshev - */ - -#include "config.h" -#include "libavutil/avassert.h" -#include "libavutil/cpu.h" -#include "libavutil/x86/asm.h" -#include "libavcodec/videodsp.h" -#include "constants.h" -#include "dsputil_x86.h" -#include "diracdsp_mmx.h" - -#if HAVE_INLINE_ASM - -void ff_put_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, - int line_size) -{ - const int16_t *p; - uint8_t *pix; - - /* read the pixels */ - p = block; - pix = pixels; - /* unrolled loop */ - __asm__ volatile ( - "movq (%3), %%mm0 \n\t" - "movq 8(%3), %%mm1 \n\t" - "movq 16(%3), %%mm2 \n\t" - "movq 24(%3), %%mm3 \n\t" - "movq 32(%3), %%mm4 \n\t" - "movq 40(%3), %%mm5 \n\t" - "movq 48(%3), %%mm6 \n\t" - "movq 56(%3), %%mm7 \n\t" - "packuswb %%mm1, %%mm0 \n\t" - "packuswb %%mm3, %%mm2 \n\t" - "packuswb %%mm5, %%mm4 \n\t" - "packuswb %%mm7, %%mm6 \n\t" - "movq %%mm0, (%0) \n\t" - "movq %%mm2, (%0, %1) \n\t" - "movq %%mm4, (%0, %1, 2) \n\t" - "movq %%mm6, (%0, %2) \n\t" - :: "r"(pix), "r"((x86_reg)line_size), "r"((x86_reg)line_size * 3), - "r"(p) - : "memory"); - pix += line_size * 4; - p += 32; - - // if here would be an exact copy of the code above - // compiler would generate some very strange code - // thus using "r" - __asm__ volatile ( - "movq (%3), %%mm0 \n\t" - "movq 8(%3), %%mm1 \n\t" - "movq 16(%3), %%mm2 \n\t" - "movq 24(%3), %%mm3 \n\t" - "movq 32(%3), %%mm4 \n\t" - "movq 40(%3), %%mm5 \n\t" - "movq 48(%3), %%mm6 \n\t" - "movq 56(%3), %%mm7 \n\t" - "packuswb %%mm1, %%mm0 \n\t" - "packuswb %%mm3, %%mm2 \n\t" - "packuswb %%mm5, %%mm4 \n\t" - "packuswb %%mm7, %%mm6 \n\t" - "movq %%mm0, (%0) \n\t" - "movq %%mm2, (%0, %1) \n\t" - "movq %%mm4, (%0, %1, 2) \n\t" - "movq %%mm6, (%0, %2) \n\t" - :: "r"(pix), "r"((x86_reg)line_size), "r"((x86_reg)line_size * 3), "r"(p) - : "memory"); -} - -#define put_signed_pixels_clamped_mmx_half(off) \ - "movq "#off"(%2), %%mm1 \n\t" \ - "movq 16 + "#off"(%2), %%mm2 \n\t" \ - "movq 32 + "#off"(%2), %%mm3 \n\t" \ - "movq 48 + "#off"(%2), %%mm4 \n\t" \ - "packsswb 8 + "#off"(%2), %%mm1 \n\t" \ - "packsswb 24 + "#off"(%2), %%mm2 \n\t" \ - "packsswb 40 + "#off"(%2), %%mm3 \n\t" \ - "packsswb 56 + "#off"(%2), %%mm4 \n\t" \ - "paddb %%mm0, %%mm1 \n\t" \ - "paddb %%mm0, %%mm2 \n\t" \ - "paddb %%mm0, %%mm3 \n\t" \ - "paddb %%mm0, %%mm4 \n\t" \ - "movq %%mm1, (%0) \n\t" \ - "movq %%mm2, (%0, %3) \n\t" \ - "movq %%mm3, (%0, %3, 2) \n\t" \ - "movq %%mm4, (%0, %1) \n\t" - -void ff_put_signed_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, - int line_size) -{ - x86_reg line_skip = line_size; - x86_reg line_skip3; - - __asm__ volatile ( - "movq "MANGLE(ff_pb_80)", %%mm0 \n\t" - "lea (%3, %3, 2), %1 \n\t" - put_signed_pixels_clamped_mmx_half(0) - "lea (%0, %3, 4), %0 \n\t" - put_signed_pixels_clamped_mmx_half(64) - : "+&r"(pixels), "=&r"(line_skip3) - : "r"(block), "r"(line_skip) - : "memory"); -} - -void ff_add_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, - int line_size) -{ - const int16_t *p; - uint8_t *pix; - int i; - - /* read the pixels */ - p = block; - pix = pixels; - MOVQ_ZERO(mm7); - i = 4; - do { - __asm__ volatile ( - "movq (%2), %%mm0 \n\t" - "movq 8(%2), %%mm1 \n\t" - "movq 16(%2), %%mm2 \n\t" - "movq 24(%2), %%mm3 \n\t" - "movq %0, %%mm4 \n\t" - "movq %1, %%mm6 \n\t" - "movq %%mm4, %%mm5 \n\t" - "punpcklbw %%mm7, %%mm4 \n\t" - "punpckhbw %%mm7, %%mm5 \n\t" - "paddsw %%mm4, %%mm0 \n\t" - "paddsw %%mm5, %%mm1 \n\t" - "movq %%mm6, %%mm5 \n\t" - "punpcklbw %%mm7, %%mm6 \n\t" - "punpckhbw %%mm7, %%mm5 \n\t" - "paddsw %%mm6, %%mm2 \n\t" - "paddsw %%mm5, %%mm3 \n\t" - "packuswb %%mm1, %%mm0 \n\t" - "packuswb %%mm3, %%mm2 \n\t" - "movq %%mm0, %0 \n\t" - "movq %%mm2, %1 \n\t" - : "+m"(*pix), "+m"(*(pix + line_size)) - : "r"(p) - : "memory"); - pix += line_size * 2; - p += 16; - } while (--i); -} - -#define CLEAR_BLOCKS(name, n) \ -void name(int16_t *blocks) \ -{ \ - __asm__ volatile ( \ - "pxor %%mm7, %%mm7 \n\t" \ - "mov %1, %%"REG_a" \n\t" \ - "1: \n\t" \ - "movq %%mm7, (%0, %%"REG_a") \n\t" \ - "movq %%mm7, 8(%0, %%"REG_a") \n\t" \ - "movq %%mm7, 16(%0, %%"REG_a") \n\t" \ - "movq %%mm7, 24(%0, %%"REG_a") \n\t" \ - "add $32, %%"REG_a" \n\t" \ - "js 1b \n\t" \ - :: "r"(((uint8_t *)blocks) + 128 * n), \ - "i"(-128 * n) \ - : "%"REG_a \ - ); \ -} -CLEAR_BLOCKS(ff_clear_blocks_mmx, 6) -CLEAR_BLOCKS(ff_clear_block_mmx, 1) - -void ff_clear_block_sse(int16_t *block) -{ - __asm__ volatile ( - "xorps %%xmm0, %%xmm0 \n" - "movaps %%xmm0, (%0) \n" - "movaps %%xmm0, 16(%0) \n" - "movaps %%xmm0, 32(%0) \n" - "movaps %%xmm0, 48(%0) \n" - "movaps %%xmm0, 64(%0) \n" - "movaps %%xmm0, 80(%0) \n" - "movaps %%xmm0, 96(%0) \n" - "movaps %%xmm0, 112(%0) \n" - :: "r"(block) - : "memory" - ); -} - -void ff_clear_blocks_sse(int16_t *blocks) -{ - __asm__ volatile ( - "xorps %%xmm0, %%xmm0 \n" - "mov %1, %%"REG_a" \n" - "1: \n" - "movaps %%xmm0, (%0, %%"REG_a") \n" - "movaps %%xmm0, 16(%0, %%"REG_a") \n" - "movaps %%xmm0, 32(%0, %%"REG_a") \n" - "movaps %%xmm0, 48(%0, %%"REG_a") \n" - "movaps %%xmm0, 64(%0, %%"REG_a") \n" - "movaps %%xmm0, 80(%0, %%"REG_a") \n" - "movaps %%xmm0, 96(%0, %%"REG_a") \n" - "movaps %%xmm0, 112(%0, %%"REG_a") \n" - "add $128, %%"REG_a" \n" - "js 1b \n" - :: "r"(((uint8_t *)blocks) + 128 * 6), - "i"(-128 * 6) - : "%"REG_a - ); -} - -void ff_add_bytes_mmx(uint8_t *dst, uint8_t *src, int w) -{ - x86_reg i = 0; - __asm__ volatile ( - "jmp 2f \n\t" - "1: \n\t" - "movq (%1, %0), %%mm0 \n\t" - "movq (%2, %0), %%mm1 \n\t" - "paddb %%mm0, %%mm1 \n\t" - "movq %%mm1, (%2, %0) \n\t" - "movq 8(%1, %0), %%mm0 \n\t" - "movq 8(%2, %0), %%mm1 \n\t" - "paddb %%mm0, %%mm1 \n\t" - "movq %%mm1, 8(%2, %0) \n\t" - "add $16, %0 \n\t" - "2: \n\t" - "cmp %3, %0 \n\t" - "js 1b \n\t" - : "+r"(i) - : "r"(src), "r"(dst), "r"((x86_reg)w - 15) - ); - for ( ; i < w; i++) - dst[i + 0] += src[i + 0]; -} - -/* Draw the edges of width 'w' of an image of size width, height - * this MMX version can only handle w == 8 || w == 16. */ -void ff_draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, - int w, int h, int sides) -{ - uint8_t *ptr, *last_line; - int i; - - last_line = buf + (height - 1) * wrap; - /* left and right */ - ptr = buf; - if (w == 8) { - __asm__ volatile ( - "1: \n\t" - "movd (%0), %%mm0 \n\t" - "punpcklbw %%mm0, %%mm0 \n\t" - "punpcklwd %%mm0, %%mm0 \n\t" - "punpckldq %%mm0, %%mm0 \n\t" - "movq %%mm0, -8(%0) \n\t" - "movq -8(%0, %2), %%mm1 \n\t" - "punpckhbw %%mm1, %%mm1 \n\t" - "punpckhwd %%mm1, %%mm1 \n\t" - "punpckhdq %%mm1, %%mm1 \n\t" - "movq %%mm1, (%0, %2) \n\t" - "add %1, %0 \n\t" - "cmp %3, %0 \n\t" - "jb 1b \n\t" - : "+r"(ptr) - : "r"((x86_reg)wrap), "r"((x86_reg)width), "r"(ptr + wrap * height) - ); - } else if(w==16){ - __asm__ volatile ( - "1: \n\t" - "movd (%0), %%mm0 \n\t" - "punpcklbw %%mm0, %%mm0 \n\t" - "punpcklwd %%mm0, %%mm0 \n\t" - "punpckldq %%mm0, %%mm0 \n\t" - "movq %%mm0, -8(%0) \n\t" - "movq %%mm0, -16(%0) \n\t" - "movq -8(%0, %2), %%mm1 \n\t" - "punpckhbw %%mm1, %%mm1 \n\t" - "punpckhwd %%mm1, %%mm1 \n\t" - "punpckhdq %%mm1, %%mm1 \n\t" - "movq %%mm1, (%0, %2) \n\t" - "movq %%mm1, 8(%0, %2) \n\t" - "add %1, %0 \n\t" - "cmp %3, %0 \n\t" - "jb 1b \n\t" - : "+r"(ptr) - : "r"((x86_reg)wrap), "r"((x86_reg)width), "r"(ptr + wrap * height) - ); - } else { - av_assert1(w == 4); - __asm__ volatile ( - "1: \n\t" - "movd (%0), %%mm0 \n\t" - "punpcklbw %%mm0, %%mm0 \n\t" - "punpcklwd %%mm0, %%mm0 \n\t" - "movd %%mm0, -4(%0) \n\t" - "movd -4(%0, %2), %%mm1 \n\t" - "punpcklbw %%mm1, %%mm1 \n\t" - "punpckhwd %%mm1, %%mm1 \n\t" - "punpckhdq %%mm1, %%mm1 \n\t" - "movd %%mm1, (%0, %2) \n\t" - "add %1, %0 \n\t" - "cmp %3, %0 \n\t" - "jb 1b \n\t" - : "+r"(ptr) - : "r"((x86_reg)wrap), "r"((x86_reg)width), "r"(ptr + wrap * height) - ); - } - - /* top and bottom (and hopefully also the corners) */ - if (sides & EDGE_TOP) { - for (i = 0; i < h; i += 4) { - ptr = buf - (i + 1) * wrap - w; - __asm__ volatile ( - "1: \n\t" - "movq (%1, %0), %%mm0 \n\t" - "movq %%mm0, (%0) \n\t" - "movq %%mm0, (%0, %2) \n\t" - "movq %%mm0, (%0, %2, 2) \n\t" - "movq %%mm0, (%0, %3) \n\t" - "add $8, %0 \n\t" - "cmp %4, %0 \n\t" - "jb 1b \n\t" - : "+r"(ptr) - : "r"((x86_reg)buf - (x86_reg)ptr - w), "r"((x86_reg) -wrap), - "r"((x86_reg) -wrap * 3), "r"(ptr + width + 2 * w) - ); - } - } - - if (sides & EDGE_BOTTOM) { - for (i = 0; i < h; i += 4) { - ptr = last_line + (i + 1) * wrap - w; - __asm__ volatile ( - "1: \n\t" - "movq (%1, %0), %%mm0 \n\t" - "movq %%mm0, (%0) \n\t" - "movq %%mm0, (%0, %2) \n\t" - "movq %%mm0, (%0, %2, 2) \n\t" - "movq %%mm0, (%0, %3) \n\t" - "add $8, %0 \n\t" - "cmp %4, %0 \n\t" - "jb 1b \n\t" - : "+r"(ptr) - : "r"((x86_reg)last_line - (x86_reg)ptr - w), - "r"((x86_reg)wrap), "r"((x86_reg)wrap * 3), - "r"(ptr + width + 2 * w) - ); - } - } -} - -typedef void emulated_edge_mc_func(uint8_t *dst, const uint8_t *src, - ptrdiff_t dst_stride, - ptrdiff_t src_linesize, - int block_w, int block_h, - int src_x, int src_y, int w, int h); - -static av_always_inline void gmc(uint8_t *dst, uint8_t *src, - int stride, int h, int ox, int oy, - int dxx, int dxy, int dyx, int dyy, - int shift, int r, int width, int height, - emulated_edge_mc_func *emu_edge_fn) -{ - const int w = 8; - const int ix = ox >> (16 + shift); - const int iy = oy >> (16 + shift); - const int oxs = ox >> 4; - const int oys = oy >> 4; - const int dxxs = dxx >> 4; - const int dxys = dxy >> 4; - const int dyxs = dyx >> 4; - const int dyys = dyy >> 4; - const uint16_t r4[4] = { r, r, r, r }; - const uint16_t dxy4[4] = { dxys, dxys, dxys, dxys }; - const uint16_t dyy4[4] = { dyys, dyys, dyys, dyys }; - const uint64_t shift2 = 2 * shift; -#define MAX_STRIDE 4096U -#define MAX_H 8U - uint8_t edge_buf[(MAX_H + 1) * MAX_STRIDE]; - int x, y; - - const int dxw = (dxx - (1 << (16 + shift))) * (w - 1); - const int dyh = (dyy - (1 << (16 + shift))) * (h - 1); - const int dxh = dxy * (h - 1); - const int dyw = dyx * (w - 1); - int need_emu = (unsigned)ix >= width - w || - (unsigned)iy >= height - h; - - if ( // non-constant fullpel offset (3% of blocks) - ((ox ^ (ox + dxw)) | (ox ^ (ox + dxh)) | (ox ^ (ox + dxw + dxh)) | - (oy ^ (oy + dyw)) | (oy ^ (oy + dyh)) | (oy ^ (oy + dyw + dyh))) >> (16 + shift) - // uses more than 16 bits of subpel mv (only at huge resolution) - || (dxx | dxy | dyx | dyy) & 15 - || (need_emu && (h > MAX_H || stride > MAX_STRIDE))) { - // FIXME could still use mmx for some of the rows - ff_gmc_c(dst, src, stride, h, ox, oy, dxx, dxy, dyx, dyy, - shift, r, width, height); - return; - } - - src += ix + iy * stride; - if (need_emu) { - emu_edge_fn(edge_buf, src, stride, stride, w + 1, h + 1, ix, iy, width, height); - src = edge_buf; - } - - __asm__ volatile ( - "movd %0, %%mm6 \n\t" - "pxor %%mm7, %%mm7 \n\t" - "punpcklwd %%mm6, %%mm6 \n\t" - "punpcklwd %%mm6, %%mm6 \n\t" - :: "r"(1< - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include "libavutil/x86/asm.h" -#include "dsputil_x86.h" - -#if HAVE_INLINE_ASM - -#if HAVE_7REGS -void ff_add_hfyu_median_prediction_cmov(uint8_t *dst, const uint8_t *top, - const uint8_t *diff, int w, - int *left, int *left_top) -{ - x86_reg w2 = -w; - x86_reg x; - int l = *left & 0xff; - int tl = *left_top & 0xff; - int t; - __asm__ volatile ( - "mov %7, %3 \n" - "1: \n" - "movzbl (%3, %4), %2 \n" - "mov %2, %k3 \n" - "sub %b1, %b3 \n" - "add %b0, %b3 \n" - "mov %2, %1 \n" - "cmp %0, %2 \n" - "cmovg %0, %2 \n" - "cmovg %1, %0 \n" - "cmp %k3, %0 \n" - "cmovg %k3, %0 \n" - "mov %7, %3 \n" - "cmp %2, %0 \n" - "cmovl %2, %0 \n" - "add (%6, %4), %b0 \n" - "mov %b0, (%5, %4) \n" - "inc %4 \n" - "jl 1b \n" - : "+&q"(l), "+&q"(tl), "=&r"(t), "=&q"(x), "+&r"(w2) - : "r"(dst + w), "r"(diff + w), "rm"(top + w) - ); - *left = l; - *left_top = tl; -} -#endif - -#endif /* HAVE_INLINE_ASM */ diff --git a/libavcodec/x86/dsputil_x86.h b/libavcodec/x86/dsputil_x86.h index 4f7ac90eb..448863fce 100644 --- a/libavcodec/x86/dsputil_x86.h +++ b/libavcodec/x86/dsputil_x86.h @@ -22,177 +22,14 @@ #ifndef AVCODEC_X86_DSPUTIL_X86_H #define AVCODEC_X86_DSPUTIL_X86_H -#include #include +#include "libavcodec/avcodec.h" #include "libavcodec/dsputil.h" -#include "libavutil/x86/asm.h" -#include "constants.h" -#define MOVQ_WONE(regd) \ - __asm__ volatile ( \ - "pcmpeqd %%" #regd ", %%" #regd " \n\t" \ - "psrlw $15, %%" #regd ::) - -#define JUMPALIGN() __asm__ volatile (".p2align 3"::) -#define MOVQ_ZERO(regd) __asm__ volatile ("pxor %%"#regd", %%"#regd ::) - -#define MOVQ_BFE(regd) \ - __asm__ volatile ( \ - "pcmpeqd %%"#regd", %%"#regd" \n\t" \ - "paddb %%"#regd", %%"#regd" \n\t" ::) - -#ifndef PIC -#define MOVQ_WTWO(regd) __asm__ volatile ("movq %0, %%"#regd" \n\t" :: "m"(ff_wtwo)) -#else -// for shared library it's better to use this way for accessing constants -// pcmpeqd -> -1 -#define MOVQ_WTWO(regd) \ - __asm__ volatile ( \ - "pcmpeqd %%"#regd", %%"#regd" \n\t" \ - "psrlw $15, %%"#regd" \n\t" \ - "psllw $1, %%"#regd" \n\t"::) - -#endif - -// using regr as temporary and for the output result -// first argument is unmodifed and second is trashed -// regfe is supposed to contain 0xfefefefefefefefe -#define PAVGB_MMX_NO_RND(rega, regb, regr, regfe) \ - "movq "#rega", "#regr" \n\t" \ - "pand "#regb", "#regr" \n\t" \ - "pxor "#rega", "#regb" \n\t" \ - "pand "#regfe", "#regb" \n\t" \ - "psrlq $1, "#regb" \n\t" \ - "paddb "#regb", "#regr" \n\t" - -#define PAVGB_MMX(rega, regb, regr, regfe) \ - "movq "#rega", "#regr" \n\t" \ - "por "#regb", "#regr" \n\t" \ - "pxor "#rega", "#regb" \n\t" \ - "pand "#regfe", "#regb" \n\t" \ - "psrlq $1, "#regb" \n\t" \ - "psubb "#regb", "#regr" \n\t" - -// mm6 is supposed to contain 0xfefefefefefefefe -#define PAVGBP_MMX_NO_RND(rega, regb, regr, regc, regd, regp) \ - "movq "#rega", "#regr" \n\t" \ - "movq "#regc", "#regp" \n\t" \ - "pand "#regb", "#regr" \n\t" \ - "pand "#regd", "#regp" \n\t" \ - "pxor "#rega", "#regb" \n\t" \ - "pxor "#regc", "#regd" \n\t" \ - "pand %%mm6, "#regb" \n\t" \ - "pand %%mm6, "#regd" \n\t" \ - "psrlq $1, "#regb" \n\t" \ - "psrlq $1, "#regd" \n\t" \ - "paddb "#regb", "#regr" \n\t" \ - "paddb "#regd", "#regp" \n\t" - -#define PAVGBP_MMX(rega, regb, regr, regc, regd, regp) \ - "movq "#rega", "#regr" \n\t" \ - "movq "#regc", "#regp" \n\t" \ - "por "#regb", "#regr" \n\t" \ - "por "#regd", "#regp" \n\t" \ - "pxor "#rega", "#regb" \n\t" \ - "pxor "#regc", "#regd" \n\t" \ - "pand %%mm6, "#regb" \n\t" \ - "pand %%mm6, "#regd" \n\t" \ - "psrlq $1, "#regd" \n\t" \ - "psrlq $1, "#regb" \n\t" \ - "psubb "#regb", "#regr" \n\t" \ - "psubb "#regd", "#regp" \n\t" - -void ff_dsputilenc_init_mmx(DSPContext* c, AVCodecContext *avctx); -void ff_dsputil_init_pix_mmx(DSPContext* c, AVCodecContext *avctx); - -void ff_add_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, int line_size); -void ff_put_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, int line_size); -void ff_put_signed_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, int line_size); - -void ff_clear_block_mmx(int16_t *block); -void ff_clear_block_sse(int16_t *block); -void ff_clear_blocks_mmx(int16_t *blocks); -void ff_clear_blocks_sse(int16_t *blocks); - -void ff_add_bytes_mmx(uint8_t *dst, uint8_t *src, int w); - -void ff_add_hfyu_median_prediction_cmov(uint8_t *dst, const uint8_t *top, - const uint8_t *diff, int w, - int *left, int *left_top); - -void ff_draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, - int w, int h, int sides); - -void ff_gmc_mmx(uint8_t *dst, uint8_t *src, - int stride, int h, int ox, int oy, - int dxx, int dxy, int dyx, int dyy, - int shift, int r, int width, int height); - -void ff_gmc_sse(uint8_t *dst, uint8_t *src, - int stride, int h, int ox, int oy, - int dxx, int dxy, int dyx, int dyy, - int shift, int r, int width, int height); - -void ff_vector_clipf_sse(float *dst, const float *src, - float min, float max, int len); - -void ff_avg_pixels8_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_avg_pixels16_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_put_pixels8_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_put_pixels16_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_avg_pixels8_mmxext(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_put_pixels8_mmxext(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_avg_pixels16_sse2(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_put_pixels16_sse2(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); - -void ff_avg_pixels8_x2_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); - -void ff_avg_pixels8_xy2_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_avg_pixels16_xy2_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); - -void ff_put_pixels8_xy2_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_put_pixels16_xy2_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); +void ff_dsputil_init_pix_mmx(DSPContext *c, AVCodecContext *avctx); void ff_mmx_idct(int16_t *block); void ff_mmxext_idct(int16_t *block); - -void ff_deinterlace_line_mmx(uint8_t *dst, - const uint8_t *lum_m4, const uint8_t *lum_m3, - const uint8_t *lum_m2, const uint8_t *lum_m1, - const uint8_t *lum, - int size); - -void ff_deinterlace_line_inplace_mmx(const uint8_t *lum_m4, - const uint8_t *lum_m3, - const uint8_t *lum_m2, - const uint8_t *lum_m1, - const uint8_t *lum, int size); - -#define PIXELS16(STATIC, PFX1, PFX2, TYPE, CPUEXT) \ -STATIC void PFX1 ## _pixels16 ## TYPE ## CPUEXT(uint8_t *block, \ - const uint8_t *pixels, \ - ptrdiff_t line_size, \ - int h) \ -{ \ - PFX2 ## PFX1 ## _pixels8 ## TYPE ## CPUEXT(block, pixels, \ - line_size, h); \ - PFX2 ## PFX1 ## _pixels8 ## TYPE ## CPUEXT(block + 8, pixels + 8, \ - line_size, h); \ -} - #endif /* AVCODEC_X86_DSPUTIL_X86_H */ diff --git a/libavcodec/x86/dsputilenc.asm b/libavcodec/x86/dsputilenc.asm index 1839bee24..023f512ed 100644 --- a/libavcodec/x86/dsputilenc.asm +++ b/libavcodec/x86/dsputilenc.asm @@ -209,8 +209,8 @@ hadamard8x8_diff %+ SUFFIX: hadamard8_16_wrapper %1, 3 %elif cpuflag(mmx) ALIGN 16 -; int hadamard8_diff_##cpu(void *s, uint8_t *src1, uint8_t *src2, -; int stride, int h) +; int ff_hadamard8_diff_ ## cpu(MpegEncContext *s, uint8_t *src1, +; uint8_t *src2, int stride, int h) ; r0 = void *s = unused, int h = unused (always 8) ; note how r1, r2 and r3 are not clobbered in this function, so 16x16 ; can simply call this 2x2x (and that's why we access rsp+gprsize @@ -274,18 +274,27 @@ INIT_XMM ssse3 %define ABS_SUM_8x8 ABS_SUM_8x8_64 HADAMARD8_DIFF 9 -INIT_XMM sse2 -; sse16_sse2(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) -cglobal sse16, 5, 5, 8 - shr r4d, 1 +; int ff_sse*_*(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, +; int line_size, int h) + +%macro SUM_SQUARED_ERRORS 1 +cglobal sse%1, 5,5,8, v, pix1, pix2, lsize, h +%if %1 == mmsize + shr hd, 1 +%endif pxor m0, m0 ; mm0 = 0 pxor m7, m7 ; mm7 holds the sum .next2lines: ; FIXME why are these unaligned movs? pix1[] is aligned - movu m1, [r1 ] ; mm1 = pix1[0][0-15] - movu m2, [r2 ] ; mm2 = pix2[0][0-15] - movu m3, [r1+r3] ; mm3 = pix1[1][0-15] - movu m4, [r2+r3] ; mm4 = pix2[1][0-15] + movu m1, [pix1q] ; m1 = pix1[0][0-15], [0-7] for mmx + movu m2, [pix2q] ; m2 = pix2[0][0-15], [0-7] for mmx +%if %1 == mmsize + movu m3, [pix1q+lsizeq] ; m3 = pix1[1][0-15], [0-7] for mmx + movu m4, [pix2q+lsizeq] ; m4 = pix2[1][0-15], [0-7] for mmx +%else ; %1 / 2 == mmsize; mmx only + mova m3, [pix1q+8] ; m3 = pix1[0][8-15] + mova m4, [pix2q+8] ; m4 = pix2[0][8-15] +%endif ; todo: mm1-mm2, mm3-mm4 ; algo: subtract mm1 from mm2 with saturation and vice versa @@ -314,174 +323,145 @@ cglobal sse16, 5, 5, 8 pmaddwd m1, m1 pmaddwd m3, m3 - lea r1, [r1+r3*2] ; pix1 += 2*line_size - lea r2, [r2+r3*2] ; pix2 += 2*line_size - paddd m1, m2 paddd m3, m4 paddd m7, m1 paddd m7, m3 - dec r4 +%if %1 == mmsize + lea pix1q, [pix1q + 2*lsizeq] + lea pix2q, [pix2q + 2*lsizeq] +%else + add pix1q, lsizeq + add pix2q, lsizeq +%endif + dec hd jnz .next2lines - mova m1, m7 - psrldq m7, 8 ; shift hi qword to lo - paddd m7, m1 - mova m1, m7 - psrldq m7, 4 ; shift hi dword to lo - paddd m7, m1 + HADDD m7, m1 movd eax, m7 ; return value RET +%endmacro INIT_MMX mmx -; get_pixels_mmx(int16_t *block, const uint8_t *pixels, int line_size) -cglobal get_pixels, 3,4 - movsxdifnidn r2, r2d - add r0, 128 - mov r3, -128 - pxor m7, m7 -.loop: - mova m0, [r1] - mova m2, [r1+r2] - mova m1, m0 - mova m3, m2 - punpcklbw m0, m7 - punpckhbw m1, m7 - punpcklbw m2, m7 - punpckhbw m3, m7 - mova [r0+r3+ 0], m0 - mova [r0+r3+ 8], m1 - mova [r0+r3+16], m2 - mova [r0+r3+24], m3 - lea r1, [r1+r2*2] - add r3, 32 - js .loop - REP_RET +SUM_SQUARED_ERRORS 8 + +INIT_MMX mmx +SUM_SQUARED_ERRORS 16 INIT_XMM sse2 -cglobal get_pixels, 3, 4 - movsxdifnidn r2, r2d - lea r3, [r2*3] - pxor m4, m4 - movh m0, [r1] - movh m1, [r1+r2] - movh m2, [r1+r2*2] - movh m3, [r1+r3] - lea r1, [r1+r2*4] - punpcklbw m0, m4 - punpcklbw m1, m4 - punpcklbw m2, m4 - punpcklbw m3, m4 - mova [r0], m0 - mova [r0+0x10], m1 - mova [r0+0x20], m2 - mova [r0+0x30], m3 - movh m0, [r1] - movh m1, [r1+r2*1] - movh m2, [r1+r2*2] - movh m3, [r1+r3] - punpcklbw m0, m4 - punpcklbw m1, m4 - punpcklbw m2, m4 - punpcklbw m3, m4 - mova [r0+0x40], m0 - mova [r0+0x50], m1 - mova [r0+0x60], m2 - mova [r0+0x70], m3 +SUM_SQUARED_ERRORS 16 + +;----------------------------------------------- +;int ff_sum_abs_dctelem(int16_t *block) +;----------------------------------------------- +; %1 = number of xmm registers used +; %2 = number of inline loops + +%macro SUM_ABS_DCTELEM 2 +cglobal sum_abs_dctelem, 1, 1, %1, block + pxor m0, m0 + pxor m1, m1 +%assign %%i 0 +%rep %2 + mova m2, [blockq+mmsize*(0+%%i)] + mova m3, [blockq+mmsize*(1+%%i)] + mova m4, [blockq+mmsize*(2+%%i)] + mova m5, [blockq+mmsize*(3+%%i)] + ABS1_SUM m2, m6, m0 + ABS1_SUM m3, m6, m1 + ABS1_SUM m4, m6, m0 + ABS1_SUM m5, m6, m1 +%assign %%i %%i+4 +%endrep + paddusw m0, m1 + HSUM m0, m1, eax + and eax, 0xFFFF RET +%endmacro INIT_MMX mmx -; diff_pixels_mmx(int16_t *block, const uint8_t *s1, const unint8_t *s2, stride) -cglobal diff_pixels, 4,5 - movsxdifnidn r3, r3d - pxor m7, m7 - add r0, 128 - mov r4, -128 +SUM_ABS_DCTELEM 0, 4 +INIT_MMX mmxext +SUM_ABS_DCTELEM 0, 4 +INIT_XMM sse2 +SUM_ABS_DCTELEM 7, 2 +INIT_XMM ssse3 +SUM_ABS_DCTELEM 6, 2 + +;------------------------------------------------------------------------------ +; int ff_hf_noise*_mmx(uint8_t *pix1, int lsize, int h) +;------------------------------------------------------------------------------ +; %1 = 8/16. %2-5=m# +%macro HF_NOISE_PART1 5 + mova m%2, [pix1q] +%if %1 == 8 + mova m%3, m%2 + psllq m%2, 8 + psrlq m%3, 8 + psrlq m%2, 8 +%else + mova m%3, [pix1q+1] +%endif + mova m%4, m%2 + mova m%5, m%3 + punpcklbw m%2, m7 + punpcklbw m%3, m7 + punpckhbw m%4, m7 + punpckhbw m%5, m7 + psubw m%2, m%3 + psubw m%4, m%5 +%endmacro + +; %1-2 = m# +%macro HF_NOISE_PART2 4 + psubw m%1, m%3 + psubw m%2, m%4 + pxor m3, m3 + pxor m1, m1 + pcmpgtw m3, m%1 + pcmpgtw m1, m%2 + pxor m%1, m3 + pxor m%2, m1 + psubw m%1, m3 + psubw m%2, m1 + paddw m%2, m%1 + paddw m6, m%2 +%endmacro + +; %1 = 8/16 +%macro HF_NOISE 1 +cglobal hf_noise%1, 3,3,0, pix1, lsize, h + movsxdifnidn lsizeq, lsized + sub hd, 2 + pxor m7, m7 + pxor m6, m6 + HF_NOISE_PART1 %1, 0, 1, 2, 3 + add pix1q, lsizeq + HF_NOISE_PART1 %1, 4, 1, 5, 3 + HF_NOISE_PART2 0, 2, 4, 5 + add pix1q, lsizeq .loop: - mova m0, [r1] - mova m2, [r2] - mova m1, m0 - mova m3, m2 - punpcklbw m0, m7 - punpckhbw m1, m7 - punpcklbw m2, m7 - punpckhbw m3, m7 - psubw m0, m2 - psubw m1, m3 - mova [r0+r4+0], m0 - mova [r0+r4+8], m1 - add r1, r3 - add r2, r3 - add r4, 16 - jne .loop - REP_RET + HF_NOISE_PART1 %1, 0, 1, 2, 3 + HF_NOISE_PART2 4, 5, 0, 2 + add pix1q, lsizeq + HF_NOISE_PART1 %1, 4, 1, 5, 3 + HF_NOISE_PART2 0, 2, 4, 5 + add pix1q, lsizeq + sub hd, 2 + jne .loop + + mova m0, m6 + punpcklwd m0, m7 + punpckhwd m6, m7 + paddd m6, m0 + mova m0, m6 + psrlq m6, 32 + paddd m0, m6 + movd eax, m0 ; eax = result of hf_noise8; + REP_RET ; return eax; +%endmacro INIT_MMX mmx -; pix_sum16_mmx(uint8_t * pix, int line_size) -cglobal pix_sum16, 2, 3 - movsxdifnidn r1, r1d - mov r2, r1 - neg r2 - shl r2, 4 - sub r0, r2 - pxor m7, m7 - pxor m6, m6 -.loop: - mova m0, [r0+r2+0] - mova m1, [r0+r2+0] - mova m2, [r0+r2+8] - mova m3, [r0+r2+8] - punpcklbw m0, m7 - punpckhbw m1, m7 - punpcklbw m2, m7 - punpckhbw m3, m7 - paddw m1, m0 - paddw m3, m2 - paddw m3, m1 - paddw m6, m3 - add r2, r1 - js .loop - mova m5, m6 - psrlq m6, 32 - paddw m6, m5 - mova m5, m6 - psrlq m6, 16 - paddw m6, m5 - movd eax, m6 - and eax, 0xffff - RET - -INIT_MMX mmx -; pix_norm1_mmx(uint8_t *pix, int line_size) -cglobal pix_norm1, 2, 4 - movsxdifnidn r1, r1d - mov r2, 16 - pxor m0, m0 - pxor m7, m7 -.loop: - mova m2, [r0+0] - mova m3, [r0+8] - mova m1, m2 - punpckhbw m1, m0 - punpcklbw m2, m0 - mova m4, m3 - punpckhbw m3, m0 - punpcklbw m4, m0 - pmaddwd m1, m1 - pmaddwd m2, m2 - pmaddwd m3, m3 - pmaddwd m4, m4 - paddd m2, m1 - paddd m4, m3 - paddd m7, m2 - add r0, r1 - paddd m7, m4 - dec r2 - jne .loop - mova m1, m7 - psrlq m7, 32 - paddd m1, m7 - movd eax, m1 - RET - +HF_NOISE 8 +HF_NOISE 16 diff --git a/libavcodec/x86/dsputilenc_mmx.c b/libavcodec/x86/dsputilenc_mmx.c deleted file mode 100644 index 5de8ade8b..000000000 --- a/libavcodec/x86/dsputilenc_mmx.c +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * MMX optimized DSP utils - * Copyright (c) 2000, 2001 Fabrice Bellard - * Copyright (c) 2002-2004 Michael Niedermayer - * - * MMX optimization by Nick Kurshev - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/attributes.h" -#include "libavutil/cpu.h" -#include "libavutil/x86/asm.h" -#include "libavutil/x86/cpu.h" -#include "libavcodec/dct.h" -#include "libavcodec/dsputil.h" -#include "libavcodec/mpegvideo.h" -#include "libavcodec/mathops.h" -#include "dsputil_x86.h" - -void ff_get_pixels_mmx(int16_t *block, const uint8_t *pixels, int line_size); -void ff_get_pixels_sse2(int16_t *block, const uint8_t *pixels, int line_size); -void ff_diff_pixels_mmx(int16_t *block, const uint8_t *s1, const uint8_t *s2, int stride); -int ff_pix_sum16_mmx(uint8_t * pix, int line_size); -int ff_pix_norm1_mmx(uint8_t *pix, int line_size); - -#if HAVE_INLINE_ASM - -static int sse8_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) { - int tmp; - __asm__ volatile ( - "movl %4,%%ecx\n" - "shr $1,%%ecx\n" - "pxor %%mm0,%%mm0\n" /* mm0 = 0 */ - "pxor %%mm7,%%mm7\n" /* mm7 holds the sum */ - "1:\n" - "movq (%0),%%mm1\n" /* mm1 = pix1[0][0-7] */ - "movq (%1),%%mm2\n" /* mm2 = pix2[0][0-7] */ - "movq (%0,%3),%%mm3\n" /* mm3 = pix1[1][0-7] */ - "movq (%1,%3),%%mm4\n" /* mm4 = pix2[1][0-7] */ - - /* todo: mm1-mm2, mm3-mm4 */ - /* algo: subtract mm1 from mm2 with saturation and vice versa */ - /* OR the results to get absolute difference */ - "movq %%mm1,%%mm5\n" - "movq %%mm3,%%mm6\n" - "psubusb %%mm2,%%mm1\n" - "psubusb %%mm4,%%mm3\n" - "psubusb %%mm5,%%mm2\n" - "psubusb %%mm6,%%mm4\n" - - "por %%mm1,%%mm2\n" - "por %%mm3,%%mm4\n" - - /* now convert to 16-bit vectors so we can square them */ - "movq %%mm2,%%mm1\n" - "movq %%mm4,%%mm3\n" - - "punpckhbw %%mm0,%%mm2\n" - "punpckhbw %%mm0,%%mm4\n" - "punpcklbw %%mm0,%%mm1\n" /* mm1 now spread over (mm1,mm2) */ - "punpcklbw %%mm0,%%mm3\n" /* mm4 now spread over (mm3,mm4) */ - - "pmaddwd %%mm2,%%mm2\n" - "pmaddwd %%mm4,%%mm4\n" - "pmaddwd %%mm1,%%mm1\n" - "pmaddwd %%mm3,%%mm3\n" - - "lea (%0,%3,2), %0\n" /* pix1 += 2*line_size */ - "lea (%1,%3,2), %1\n" /* pix2 += 2*line_size */ - - "paddd %%mm2,%%mm1\n" - "paddd %%mm4,%%mm3\n" - "paddd %%mm1,%%mm7\n" - "paddd %%mm3,%%mm7\n" - - "decl %%ecx\n" - "jnz 1b\n" - - "movq %%mm7,%%mm1\n" - "psrlq $32, %%mm7\n" /* shift hi dword to lo */ - "paddd %%mm7,%%mm1\n" - "movd %%mm1,%2\n" - : "+r" (pix1), "+r" (pix2), "=r"(tmp) - : "r" ((x86_reg)line_size) , "m" (h) - : "%ecx"); - return tmp; -} - -static int sse16_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) { - int tmp; - __asm__ volatile ( - "movl %4,%%ecx\n" - "pxor %%mm0,%%mm0\n" /* mm0 = 0 */ - "pxor %%mm7,%%mm7\n" /* mm7 holds the sum */ - "1:\n" - "movq (%0),%%mm1\n" /* mm1 = pix1[0-7] */ - "movq (%1),%%mm2\n" /* mm2 = pix2[0-7] */ - "movq 8(%0),%%mm3\n" /* mm3 = pix1[8-15] */ - "movq 8(%1),%%mm4\n" /* mm4 = pix2[8-15] */ - - /* todo: mm1-mm2, mm3-mm4 */ - /* algo: subtract mm1 from mm2 with saturation and vice versa */ - /* OR the results to get absolute difference */ - "movq %%mm1,%%mm5\n" - "movq %%mm3,%%mm6\n" - "psubusb %%mm2,%%mm1\n" - "psubusb %%mm4,%%mm3\n" - "psubusb %%mm5,%%mm2\n" - "psubusb %%mm6,%%mm4\n" - - "por %%mm1,%%mm2\n" - "por %%mm3,%%mm4\n" - - /* now convert to 16-bit vectors so we can square them */ - "movq %%mm2,%%mm1\n" - "movq %%mm4,%%mm3\n" - - "punpckhbw %%mm0,%%mm2\n" - "punpckhbw %%mm0,%%mm4\n" - "punpcklbw %%mm0,%%mm1\n" /* mm1 now spread over (mm1,mm2) */ - "punpcklbw %%mm0,%%mm3\n" /* mm4 now spread over (mm3,mm4) */ - - "pmaddwd %%mm2,%%mm2\n" - "pmaddwd %%mm4,%%mm4\n" - "pmaddwd %%mm1,%%mm1\n" - "pmaddwd %%mm3,%%mm3\n" - - "add %3,%0\n" - "add %3,%1\n" - - "paddd %%mm2,%%mm1\n" - "paddd %%mm4,%%mm3\n" - "paddd %%mm1,%%mm7\n" - "paddd %%mm3,%%mm7\n" - - "decl %%ecx\n" - "jnz 1b\n" - - "movq %%mm7,%%mm1\n" - "psrlq $32, %%mm7\n" /* shift hi dword to lo */ - "paddd %%mm7,%%mm1\n" - "movd %%mm1,%2\n" - : "+r" (pix1), "+r" (pix2), "=r"(tmp) - : "r" ((x86_reg)line_size) , "m" (h) - : "%ecx"); - return tmp; -} - -static int hf_noise8_mmx(uint8_t * pix1, int line_size, int h) { - int tmp; - __asm__ volatile ( - "movl %3,%%ecx\n" - "pxor %%mm7,%%mm7\n" - "pxor %%mm6,%%mm6\n" - - "movq (%0),%%mm0\n" - "movq %%mm0, %%mm1\n" - "psllq $8, %%mm0\n" - "psrlq $8, %%mm1\n" - "psrlq $8, %%mm0\n" - "movq %%mm0, %%mm2\n" - "movq %%mm1, %%mm3\n" - "punpcklbw %%mm7,%%mm0\n" - "punpcklbw %%mm7,%%mm1\n" - "punpckhbw %%mm7,%%mm2\n" - "punpckhbw %%mm7,%%mm3\n" - "psubw %%mm1, %%mm0\n" - "psubw %%mm3, %%mm2\n" - - "add %2,%0\n" - - "movq (%0),%%mm4\n" - "movq %%mm4, %%mm1\n" - "psllq $8, %%mm4\n" - "psrlq $8, %%mm1\n" - "psrlq $8, %%mm4\n" - "movq %%mm4, %%mm5\n" - "movq %%mm1, %%mm3\n" - "punpcklbw %%mm7,%%mm4\n" - "punpcklbw %%mm7,%%mm1\n" - "punpckhbw %%mm7,%%mm5\n" - "punpckhbw %%mm7,%%mm3\n" - "psubw %%mm1, %%mm4\n" - "psubw %%mm3, %%mm5\n" - "psubw %%mm4, %%mm0\n" - "psubw %%mm5, %%mm2\n" - "pxor %%mm3, %%mm3\n" - "pxor %%mm1, %%mm1\n" - "pcmpgtw %%mm0, %%mm3\n\t" - "pcmpgtw %%mm2, %%mm1\n\t" - "pxor %%mm3, %%mm0\n" - "pxor %%mm1, %%mm2\n" - "psubw %%mm3, %%mm0\n" - "psubw %%mm1, %%mm2\n" - "paddw %%mm0, %%mm2\n" - "paddw %%mm2, %%mm6\n" - - "add %2,%0\n" - "1:\n" - - "movq (%0),%%mm0\n" - "movq %%mm0, %%mm1\n" - "psllq $8, %%mm0\n" - "psrlq $8, %%mm1\n" - "psrlq $8, %%mm0\n" - "movq %%mm0, %%mm2\n" - "movq %%mm1, %%mm3\n" - "punpcklbw %%mm7,%%mm0\n" - "punpcklbw %%mm7,%%mm1\n" - "punpckhbw %%mm7,%%mm2\n" - "punpckhbw %%mm7,%%mm3\n" - "psubw %%mm1, %%mm0\n" - "psubw %%mm3, %%mm2\n" - "psubw %%mm0, %%mm4\n" - "psubw %%mm2, %%mm5\n" - "pxor %%mm3, %%mm3\n" - "pxor %%mm1, %%mm1\n" - "pcmpgtw %%mm4, %%mm3\n\t" - "pcmpgtw %%mm5, %%mm1\n\t" - "pxor %%mm3, %%mm4\n" - "pxor %%mm1, %%mm5\n" - "psubw %%mm3, %%mm4\n" - "psubw %%mm1, %%mm5\n" - "paddw %%mm4, %%mm5\n" - "paddw %%mm5, %%mm6\n" - - "add %2,%0\n" - - "movq (%0),%%mm4\n" - "movq %%mm4, %%mm1\n" - "psllq $8, %%mm4\n" - "psrlq $8, %%mm1\n" - "psrlq $8, %%mm4\n" - "movq %%mm4, %%mm5\n" - "movq %%mm1, %%mm3\n" - "punpcklbw %%mm7,%%mm4\n" - "punpcklbw %%mm7,%%mm1\n" - "punpckhbw %%mm7,%%mm5\n" - "punpckhbw %%mm7,%%mm3\n" - "psubw %%mm1, %%mm4\n" - "psubw %%mm3, %%mm5\n" - "psubw %%mm4, %%mm0\n" - "psubw %%mm5, %%mm2\n" - "pxor %%mm3, %%mm3\n" - "pxor %%mm1, %%mm1\n" - "pcmpgtw %%mm0, %%mm3\n\t" - "pcmpgtw %%mm2, %%mm1\n\t" - "pxor %%mm3, %%mm0\n" - "pxor %%mm1, %%mm2\n" - "psubw %%mm3, %%mm0\n" - "psubw %%mm1, %%mm2\n" - "paddw %%mm0, %%mm2\n" - "paddw %%mm2, %%mm6\n" - - "add %2,%0\n" - "subl $2, %%ecx\n" - " jnz 1b\n" - - "movq %%mm6, %%mm0\n" - "punpcklwd %%mm7,%%mm0\n" - "punpckhwd %%mm7,%%mm6\n" - "paddd %%mm0, %%mm6\n" - - "movq %%mm6,%%mm0\n" - "psrlq $32, %%mm6\n" - "paddd %%mm6,%%mm0\n" - "movd %%mm0,%1\n" - : "+r" (pix1), "=r"(tmp) - : "r" ((x86_reg)line_size) , "g" (h-2) - : "%ecx"); - return tmp; -} - -static int hf_noise16_mmx(uint8_t * pix1, int line_size, int h) { - int tmp; - uint8_t * pix= pix1; - __asm__ volatile ( - "movl %3,%%ecx\n" - "pxor %%mm7,%%mm7\n" - "pxor %%mm6,%%mm6\n" - - "movq (%0),%%mm0\n" - "movq 1(%0),%%mm1\n" - "movq %%mm0, %%mm2\n" - "movq %%mm1, %%mm3\n" - "punpcklbw %%mm7,%%mm0\n" - "punpcklbw %%mm7,%%mm1\n" - "punpckhbw %%mm7,%%mm2\n" - "punpckhbw %%mm7,%%mm3\n" - "psubw %%mm1, %%mm0\n" - "psubw %%mm3, %%mm2\n" - - "add %2,%0\n" - - "movq (%0),%%mm4\n" - "movq 1(%0),%%mm1\n" - "movq %%mm4, %%mm5\n" - "movq %%mm1, %%mm3\n" - "punpcklbw %%mm7,%%mm4\n" - "punpcklbw %%mm7,%%mm1\n" - "punpckhbw %%mm7,%%mm5\n" - "punpckhbw %%mm7,%%mm3\n" - "psubw %%mm1, %%mm4\n" - "psubw %%mm3, %%mm5\n" - "psubw %%mm4, %%mm0\n" - "psubw %%mm5, %%mm2\n" - "pxor %%mm3, %%mm3\n" - "pxor %%mm1, %%mm1\n" - "pcmpgtw %%mm0, %%mm3\n\t" - "pcmpgtw %%mm2, %%mm1\n\t" - "pxor %%mm3, %%mm0\n" - "pxor %%mm1, %%mm2\n" - "psubw %%mm3, %%mm0\n" - "psubw %%mm1, %%mm2\n" - "paddw %%mm0, %%mm2\n" - "paddw %%mm2, %%mm6\n" - - "add %2,%0\n" - "1:\n" - - "movq (%0),%%mm0\n" - "movq 1(%0),%%mm1\n" - "movq %%mm0, %%mm2\n" - "movq %%mm1, %%mm3\n" - "punpcklbw %%mm7,%%mm0\n" - "punpcklbw %%mm7,%%mm1\n" - "punpckhbw %%mm7,%%mm2\n" - "punpckhbw %%mm7,%%mm3\n" - "psubw %%mm1, %%mm0\n" - "psubw %%mm3, %%mm2\n" - "psubw %%mm0, %%mm4\n" - "psubw %%mm2, %%mm5\n" - "pxor %%mm3, %%mm3\n" - "pxor %%mm1, %%mm1\n" - "pcmpgtw %%mm4, %%mm3\n\t" - "pcmpgtw %%mm5, %%mm1\n\t" - "pxor %%mm3, %%mm4\n" - "pxor %%mm1, %%mm5\n" - "psubw %%mm3, %%mm4\n" - "psubw %%mm1, %%mm5\n" - "paddw %%mm4, %%mm5\n" - "paddw %%mm5, %%mm6\n" - - "add %2,%0\n" - - "movq (%0),%%mm4\n" - "movq 1(%0),%%mm1\n" - "movq %%mm4, %%mm5\n" - "movq %%mm1, %%mm3\n" - "punpcklbw %%mm7,%%mm4\n" - "punpcklbw %%mm7,%%mm1\n" - "punpckhbw %%mm7,%%mm5\n" - "punpckhbw %%mm7,%%mm3\n" - "psubw %%mm1, %%mm4\n" - "psubw %%mm3, %%mm5\n" - "psubw %%mm4, %%mm0\n" - "psubw %%mm5, %%mm2\n" - "pxor %%mm3, %%mm3\n" - "pxor %%mm1, %%mm1\n" - "pcmpgtw %%mm0, %%mm3\n\t" - "pcmpgtw %%mm2, %%mm1\n\t" - "pxor %%mm3, %%mm0\n" - "pxor %%mm1, %%mm2\n" - "psubw %%mm3, %%mm0\n" - "psubw %%mm1, %%mm2\n" - "paddw %%mm0, %%mm2\n" - "paddw %%mm2, %%mm6\n" - - "add %2,%0\n" - "subl $2, %%ecx\n" - " jnz 1b\n" - - "movq %%mm6, %%mm0\n" - "punpcklwd %%mm7,%%mm0\n" - "punpckhwd %%mm7,%%mm6\n" - "paddd %%mm0, %%mm6\n" - - "movq %%mm6,%%mm0\n" - "psrlq $32, %%mm6\n" - "paddd %%mm6,%%mm0\n" - "movd %%mm0,%1\n" - : "+r" (pix1), "=r"(tmp) - : "r" ((x86_reg)line_size) , "g" (h-2) - : "%ecx"); - return tmp + hf_noise8_mmx(pix+8, line_size, h); -} - -static int nsse16_mmx(void *p, uint8_t * pix1, uint8_t * pix2, int line_size, int h) { - MpegEncContext *c = p; - int score1, score2; - - if(c) score1 = c->dsp.sse[0](c, pix1, pix2, line_size, h); - else score1 = sse16_mmx(c, pix1, pix2, line_size, h); - score2= hf_noise16_mmx(pix1, line_size, h) - hf_noise16_mmx(pix2, line_size, h); - - if(c) return score1 + FFABS(score2)*c->avctx->nsse_weight; - else return score1 + FFABS(score2)*8; -} - -static int nsse8_mmx(void *p, uint8_t * pix1, uint8_t * pix2, int line_size, int h) { - MpegEncContext *c = p; - int score1= sse8_mmx(c, pix1, pix2, line_size, h); - int score2= hf_noise8_mmx(pix1, line_size, h) - hf_noise8_mmx(pix2, line_size, h); - - if(c) return score1 + FFABS(score2)*c->avctx->nsse_weight; - else return score1 + FFABS(score2)*8; -} - -static int vsad_intra16_mmx(void *v, uint8_t * pix, uint8_t * dummy, int line_size, int h) { - int tmp; - - av_assert2( (((int)pix) & 7) == 0); - av_assert2((line_size &7) ==0); - -#define SUM(in0, in1, out0, out1) \ - "movq (%0), %%mm2\n"\ - "movq 8(%0), %%mm3\n"\ - "add %2,%0\n"\ - "movq %%mm2, " #out0 "\n"\ - "movq %%mm3, " #out1 "\n"\ - "psubusb " #in0 ", %%mm2\n"\ - "psubusb " #in1 ", %%mm3\n"\ - "psubusb " #out0 ", " #in0 "\n"\ - "psubusb " #out1 ", " #in1 "\n"\ - "por %%mm2, " #in0 "\n"\ - "por %%mm3, " #in1 "\n"\ - "movq " #in0 ", %%mm2\n"\ - "movq " #in1 ", %%mm3\n"\ - "punpcklbw %%mm7, " #in0 "\n"\ - "punpcklbw %%mm7, " #in1 "\n"\ - "punpckhbw %%mm7, %%mm2\n"\ - "punpckhbw %%mm7, %%mm3\n"\ - "paddw " #in1 ", " #in0 "\n"\ - "paddw %%mm3, %%mm2\n"\ - "paddw %%mm2, " #in0 "\n"\ - "paddw " #in0 ", %%mm6\n" - - - __asm__ volatile ( - "movl %3,%%ecx\n" - "pxor %%mm6,%%mm6\n" - "pxor %%mm7,%%mm7\n" - "movq (%0),%%mm0\n" - "movq 8(%0),%%mm1\n" - "add %2,%0\n" - "jmp 2f\n" - "1:\n" - - SUM(%%mm4, %%mm5, %%mm0, %%mm1) - "2:\n" - SUM(%%mm0, %%mm1, %%mm4, %%mm5) - - "subl $2, %%ecx\n" - "jnz 1b\n" - - "movq %%mm6,%%mm0\n" - "psrlq $32, %%mm6\n" - "paddw %%mm6,%%mm0\n" - "movq %%mm0,%%mm6\n" - "psrlq $16, %%mm0\n" - "paddw %%mm6,%%mm0\n" - "movd %%mm0,%1\n" - : "+r" (pix), "=r"(tmp) - : "r" ((x86_reg)line_size) , "m" (h) - : "%ecx"); - return tmp & 0xFFFF; -} -#undef SUM - -static int vsad_intra16_mmxext(void *v, uint8_t *pix, uint8_t *dummy, - int line_size, int h) -{ - int tmp; - - av_assert2( (((int)pix) & 7) == 0); - av_assert2((line_size &7) ==0); - -#define SUM(in0, in1, out0, out1) \ - "movq (%0), " #out0 "\n"\ - "movq 8(%0), " #out1 "\n"\ - "add %2,%0\n"\ - "psadbw " #out0 ", " #in0 "\n"\ - "psadbw " #out1 ", " #in1 "\n"\ - "paddw " #in1 ", " #in0 "\n"\ - "paddw " #in0 ", %%mm6\n" - - __asm__ volatile ( - "movl %3,%%ecx\n" - "pxor %%mm6,%%mm6\n" - "pxor %%mm7,%%mm7\n" - "movq (%0),%%mm0\n" - "movq 8(%0),%%mm1\n" - "add %2,%0\n" - "jmp 2f\n" - "1:\n" - - SUM(%%mm4, %%mm5, %%mm0, %%mm1) - "2:\n" - SUM(%%mm0, %%mm1, %%mm4, %%mm5) - - "subl $2, %%ecx\n" - "jnz 1b\n" - - "movd %%mm6,%1\n" - : "+r" (pix), "=r"(tmp) - : "r" ((x86_reg)line_size) , "m" (h) - : "%ecx"); - return tmp; -} -#undef SUM - -static int vsad16_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) { - int tmp; - - av_assert2( (((int)pix1) & 7) == 0); - av_assert2( (((int)pix2) & 7) == 0); - av_assert2((line_size &7) ==0); - -#define SUM(in0, in1, out0, out1) \ - "movq (%0),%%mm2\n"\ - "movq (%1)," #out0 "\n"\ - "movq 8(%0),%%mm3\n"\ - "movq 8(%1)," #out1 "\n"\ - "add %3,%0\n"\ - "add %3,%1\n"\ - "psubb " #out0 ", %%mm2\n"\ - "psubb " #out1 ", %%mm3\n"\ - "pxor %%mm7, %%mm2\n"\ - "pxor %%mm7, %%mm3\n"\ - "movq %%mm2, " #out0 "\n"\ - "movq %%mm3, " #out1 "\n"\ - "psubusb " #in0 ", %%mm2\n"\ - "psubusb " #in1 ", %%mm3\n"\ - "psubusb " #out0 ", " #in0 "\n"\ - "psubusb " #out1 ", " #in1 "\n"\ - "por %%mm2, " #in0 "\n"\ - "por %%mm3, " #in1 "\n"\ - "movq " #in0 ", %%mm2\n"\ - "movq " #in1 ", %%mm3\n"\ - "punpcklbw %%mm7, " #in0 "\n"\ - "punpcklbw %%mm7, " #in1 "\n"\ - "punpckhbw %%mm7, %%mm2\n"\ - "punpckhbw %%mm7, %%mm3\n"\ - "paddw " #in1 ", " #in0 "\n"\ - "paddw %%mm3, %%mm2\n"\ - "paddw %%mm2, " #in0 "\n"\ - "paddw " #in0 ", %%mm6\n" - - - __asm__ volatile ( - "movl %4,%%ecx\n" - "pxor %%mm6,%%mm6\n" - "pcmpeqw %%mm7,%%mm7\n" - "psllw $15, %%mm7\n" - "packsswb %%mm7, %%mm7\n" - "movq (%0),%%mm0\n" - "movq (%1),%%mm2\n" - "movq 8(%0),%%mm1\n" - "movq 8(%1),%%mm3\n" - "add %3,%0\n" - "add %3,%1\n" - "psubb %%mm2, %%mm0\n" - "psubb %%mm3, %%mm1\n" - "pxor %%mm7, %%mm0\n" - "pxor %%mm7, %%mm1\n" - "jmp 2f\n" - "1:\n" - - SUM(%%mm4, %%mm5, %%mm0, %%mm1) - "2:\n" - SUM(%%mm0, %%mm1, %%mm4, %%mm5) - - "subl $2, %%ecx\n" - "jnz 1b\n" - - "movq %%mm6,%%mm0\n" - "psrlq $32, %%mm6\n" - "paddw %%mm6,%%mm0\n" - "movq %%mm0,%%mm6\n" - "psrlq $16, %%mm0\n" - "paddw %%mm6,%%mm0\n" - "movd %%mm0,%2\n" - : "+r" (pix1), "+r" (pix2), "=r"(tmp) - : "r" ((x86_reg)line_size) , "m" (h) - : "%ecx"); - return tmp & 0x7FFF; -} -#undef SUM - -static int vsad16_mmxext(void *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) -{ - int tmp; - - av_assert2( (((int)pix1) & 7) == 0); - av_assert2( (((int)pix2) & 7) == 0); - av_assert2((line_size &7) ==0); - -#define SUM(in0, in1, out0, out1) \ - "movq (%0)," #out0 "\n"\ - "movq (%1),%%mm2\n"\ - "movq 8(%0)," #out1 "\n"\ - "movq 8(%1),%%mm3\n"\ - "add %3,%0\n"\ - "add %3,%1\n"\ - "psubb %%mm2, " #out0 "\n"\ - "psubb %%mm3, " #out1 "\n"\ - "pxor %%mm7, " #out0 "\n"\ - "pxor %%mm7, " #out1 "\n"\ - "psadbw " #out0 ", " #in0 "\n"\ - "psadbw " #out1 ", " #in1 "\n"\ - "paddw " #in1 ", " #in0 "\n"\ - "paddw " #in0 ", %%mm6\n" - - __asm__ volatile ( - "movl %4,%%ecx\n" - "pxor %%mm6,%%mm6\n" - "pcmpeqw %%mm7,%%mm7\n" - "psllw $15, %%mm7\n" - "packsswb %%mm7, %%mm7\n" - "movq (%0),%%mm0\n" - "movq (%1),%%mm2\n" - "movq 8(%0),%%mm1\n" - "movq 8(%1),%%mm3\n" - "add %3,%0\n" - "add %3,%1\n" - "psubb %%mm2, %%mm0\n" - "psubb %%mm3, %%mm1\n" - "pxor %%mm7, %%mm0\n" - "pxor %%mm7, %%mm1\n" - "jmp 2f\n" - "1:\n" - - SUM(%%mm4, %%mm5, %%mm0, %%mm1) - "2:\n" - SUM(%%mm0, %%mm1, %%mm4, %%mm5) - - "subl $2, %%ecx\n" - "jnz 1b\n" - - "movd %%mm6,%2\n" - : "+r" (pix1), "+r" (pix2), "=r"(tmp) - : "r" ((x86_reg)line_size) , "m" (h) - : "%ecx"); - return tmp; -} -#undef SUM - -static void diff_bytes_mmx(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int w){ - x86_reg i=0; - if(w>=16) - __asm__ volatile( - "1: \n\t" - "movq (%2, %0), %%mm0 \n\t" - "movq (%1, %0), %%mm1 \n\t" - "psubb %%mm0, %%mm1 \n\t" - "movq %%mm1, (%3, %0) \n\t" - "movq 8(%2, %0), %%mm0 \n\t" - "movq 8(%1, %0), %%mm1 \n\t" - "psubb %%mm0, %%mm1 \n\t" - "movq %%mm1, 8(%3, %0) \n\t" - "add $16, %0 \n\t" - "cmp %4, %0 \n\t" - " jb 1b \n\t" - : "+r" (i) - : "r"(src1), "r"(src2), "r"(dst), "r"((x86_reg)w-15) - ); - for(; idct_algo; - -#if HAVE_YASM - int bit_depth = avctx->bits_per_raw_sample; - - if (EXTERNAL_MMX(cpu_flags)) { - if (bit_depth <= 8) - c->get_pixels = ff_get_pixels_mmx; - c->diff_pixels = ff_diff_pixels_mmx; - c->pix_sum = ff_pix_sum16_mmx; - - c->pix_norm1 = ff_pix_norm1_mmx; - } - if (EXTERNAL_SSE2(cpu_flags)) - if (bit_depth <= 8) - c->get_pixels = ff_get_pixels_sse2; -#endif /* HAVE_YASM */ - -#if HAVE_INLINE_ASM - if (INLINE_MMX(cpu_flags)) { - if (avctx->bits_per_raw_sample <= 8 && - (dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX)) - c->fdct = ff_fdct_mmx; - - c->diff_bytes= diff_bytes_mmx; - c->sum_abs_dctelem= sum_abs_dctelem_mmx; - - c->sse[0] = sse16_mmx; - c->sse[1] = sse8_mmx; - c->vsad[4]= vsad_intra16_mmx; - - c->nsse[0] = nsse16_mmx; - c->nsse[1] = nsse8_mmx; - if(!(avctx->flags & CODEC_FLAG_BITEXACT)){ - c->vsad[0] = vsad16_mmx; - } - - if(!(avctx->flags & CODEC_FLAG_BITEXACT)){ - c->try_8x8basis= try_8x8basis_mmx; - } - c->add_8x8basis= add_8x8basis_mmx; - - c->ssd_int8_vs_int16 = ssd_int8_vs_int16_mmx; - } - - if (INLINE_AMD3DNOW(cpu_flags)) { - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { - c->try_8x8basis = try_8x8basis_3dnow; - } - c->add_8x8basis = add_8x8basis_3dnow; - } - - if (INLINE_MMXEXT(cpu_flags)) { - if (avctx->bits_per_raw_sample <= 8 && - (dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX)) - c->fdct = ff_fdct_mmxext; - - c->sum_abs_dctelem = sum_abs_dctelem_mmxext; - c->vsad[4] = vsad_intra16_mmxext; - - if (!(avctx->flags & CODEC_FLAG_BITEXACT)){ - c->vsad[0] = vsad16_mmxext; - } - - c->sub_hfyu_median_prediction = sub_hfyu_median_prediction_mmxext; - } - - if (INLINE_SSE2(cpu_flags)) { - if (avctx->bits_per_raw_sample <= 8 && - (dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX)) - c->fdct = ff_fdct_sse2; - - c->sum_abs_dctelem= sum_abs_dctelem_sse2; - } - -#if HAVE_SSSE3_INLINE - if (INLINE_SSSE3(cpu_flags)) { - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { - c->try_8x8basis = try_8x8basis_ssse3; - } - c->add_8x8basis = add_8x8basis_ssse3; - c->sum_abs_dctelem = sum_abs_dctelem_ssse3; - } -#endif -#endif /* HAVE_INLINE_ASM */ - - if (EXTERNAL_MMX(cpu_flags)) { - c->hadamard8_diff[0] = ff_hadamard8_diff16_mmx; - c->hadamard8_diff[1] = ff_hadamard8_diff_mmx; - } - - if (EXTERNAL_MMXEXT(cpu_flags)) { - c->hadamard8_diff[0] = ff_hadamard8_diff16_mmxext; - c->hadamard8_diff[1] = ff_hadamard8_diff_mmxext; - } - - if (EXTERNAL_SSE2(cpu_flags)) { - c->sse[0] = ff_sse16_sse2; - -#if HAVE_ALIGNED_STACK - c->hadamard8_diff[0] = ff_hadamard8_diff16_sse2; - c->hadamard8_diff[1] = ff_hadamard8_diff_sse2; -#endif - } - - if (EXTERNAL_SSSE3(cpu_flags) && HAVE_ALIGNED_STACK) { - c->hadamard8_diff[0] = ff_hadamard8_diff16_ssse3; - c->hadamard8_diff[1] = ff_hadamard8_diff_ssse3; - } - - ff_dsputil_init_pix_mmx(c, avctx); -} diff --git a/libavcodec/x86/fdct.c b/libavcodec/x86/fdct.c index 11a13bb70..f0cd471d3 100644 --- a/libavcodec/x86/fdct.c +++ b/libavcodec/x86/fdct.c @@ -1,5 +1,5 @@ /* - * MMX optimized forward DCT + * SIMD-optimized forward DCT * The gcc porting is Copyright (c) 2001 Fabrice Bellard. * cleanup/optimizations are Copyright (c) 2002-2004 Michael Niedermayer * SSE2 optimization is Copyright (c) 2004 Denes Balatoni. diff --git a/libavcodec/x86/fdctdsp_init.c b/libavcodec/x86/fdctdsp_init.c new file mode 100644 index 000000000..261db979c --- /dev/null +++ b/libavcodec/x86/fdctdsp_init.c @@ -0,0 +1,44 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/dct.h" +#include "libavcodec/fdctdsp.h" + +av_cold void ff_fdctdsp_init_x86(FDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + const int dct_algo = avctx->dct_algo; + + if (!high_bit_depth) { + if ((dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX)) { + if (INLINE_MMX(cpu_flags)) + c->fdct = ff_fdct_mmx; + + if (INLINE_MMXEXT(cpu_flags)) + c->fdct = ff_fdct_mmxext; + + if (INLINE_SSE2(cpu_flags)) + c->fdct = ff_fdct_sse2; + } + } +} diff --git a/libavcodec/x86/fmtconvert.asm b/libavcodec/x86/fmtconvert.asm index 60078e2c2..0d3f821c9 100644 --- a/libavcodec/x86/fmtconvert.asm +++ b/libavcodec/x86/fmtconvert.asm @@ -31,9 +31,10 @@ SECTION_TEXT %endif %endmacro -;--------------------------------------------------------------------------------- -; void int32_to_float_fmul_scalar(float *dst, const int32_t *src, float mul, int len); -;--------------------------------------------------------------------------------- +;------------------------------------------------------------------------------ +; void ff_int32_to_float_fmul_scalar(float *dst, const int32_t *src, float mul, +; int len); +;------------------------------------------------------------------------------ %macro INT32_TO_FLOAT_FMUL_SCALAR 1 %if UNIX64 cglobal int32_to_float_fmul_scalar, 3, 3, %1, dst, src, len @@ -243,8 +244,10 @@ 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 -; void float_to_int16_interleave6_sse(int16_t *dst, const float **src, int len) cglobal float_to_int16_interleave6, 2, 8, 0, dst, src, src1, src2, src3, src4, src5, len %if ARCH_X86_64 mov lend, r2d diff --git a/libavcodec/x86/fpel.asm b/libavcodec/x86/fpel.asm index dc363d1a6..0e3b444e2 100644 --- a/libavcodec/x86/fpel.asm +++ b/libavcodec/x86/fpel.asm @@ -1,5 +1,5 @@ ;****************************************************************************** -;* MMX optimized DSP utils +;* SIMD-optimized fullpel functions ;* Copyright (c) 2008 Loren Merritt ;* Copyright (c) 2003-2013 Michael Niedermayer ;* Copyright (c) 2013 Daniel Kang @@ -25,82 +25,83 @@ SECTION .text -INIT_MMX mmxext -; void pixels(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -%macro PIXELS48 2 -%if %2 == 4 -%define OP movh +%macro PAVGB_MMX 4 + LOAD %3, %1 + por %3, %2 + pxor %2, %1 + pand %2, %4 + psrlq %2, 1 + psubb %3, %2 + SWAP %2, %3 +%endmacro + +; void ff_put/avg_pixels(uint8_t *block, const uint8_t *pixels, +; ptrdiff_t line_size, int h) +%macro OP_PIXELS 2 +%if %2 == mmsize/2 +%define LOAD movh +%define SAVE movh +%define LEN mmsize %else -%define OP mova +%define LOAD movu +%define SAVE mova +%define LEN %2 %endif -cglobal %1_pixels%2, 4,5 +cglobal %1_pixels%2, 4,5,4 movsxdifnidn r2, r2d lea r4, [r2*3] -.loop: - OP m0, [r1] - OP m1, [r1+r2] - OP m2, [r1+r2*2] - OP m3, [r1+r4] - lea r1, [r1+r2*4] %ifidn %1, avg - pavgb m0, [r0] - pavgb m1, [r0+r2] - pavgb m2, [r0+r2*2] - pavgb m3, [r0+r4] +%if notcpuflag(mmxext) + pcmpeqd m6, m6 + paddb m6, m6 %endif - OP [r0], m0 - OP [r0+r2], m1 - OP [r0+r2*2], m2 - OP [r0+r4], m3 +%endif +.loop: +%assign %%i 0 +%rep LEN/mmsize + LOAD m0, [r1 + %%i] + LOAD m1, [r1+r2 + %%i] + LOAD m2, [r1+r2*2 + %%i] + LOAD m3, [r1+r4 + %%i] +%ifidn %1, avg +%if notcpuflag(mmxext) + PAVGB_MMX [r0 + %%i], m0, m4, m6 + PAVGB_MMX [r0+r2 + %%i], m1, m5, m6 + PAVGB_MMX [r0+r2*2 + %%i], m2, m4, m6 + PAVGB_MMX [r0+r4 + %%i], m3, m5, m6 +%else + pavgb m0, [r0 + %%i] + pavgb m1, [r0+r2 + %%i] + pavgb m2, [r0+r2*2 + %%i] + pavgb m3, [r0+r4 + %%i] +%endif +%endif + SAVE [r0 + %%i], m0 + SAVE [r0+r2 + %%i], m1 + SAVE [r0+r2*2 + %%i], m2 + SAVE [r0+r4 + %%i], m3 +%assign %%i %%i+mmsize +%endrep sub r3d, 4 + lea r1, [r1+r2*4] lea r0, [r0+r2*4] jne .loop RET %endmacro -PIXELS48 put, 4 -PIXELS48 avg, 4 -PIXELS48 put, 8 -PIXELS48 avg, 8 +INIT_MMX mmx +OP_PIXELS put, 4 +OP_PIXELS avg, 4 +OP_PIXELS put, 8 +OP_PIXELS avg, 8 +OP_PIXELS put, 16 +OP_PIXELS avg, 16 +INIT_MMX mmxext +OP_PIXELS avg, 4 +OP_PIXELS avg, 8 +OP_PIXELS avg, 16 INIT_XMM sse2 -; void put_pixels16_sse2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -cglobal put_pixels16, 4,5,4 - lea r4, [r2*3] -.loop: - movu m0, [r1] - movu m1, [r1+r2] - movu m2, [r1+r2*2] - movu m3, [r1+r4] - lea r1, [r1+r2*4] - mova [r0], m0 - mova [r0+r2], m1 - mova [r0+r2*2], m2 - mova [r0+r4], m3 - sub r3d, 4 - lea r0, [r0+r2*4] - jnz .loop - REP_RET - -; void avg_pixels16_sse2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -cglobal avg_pixels16, 4,5,4 - lea r4, [r2*3] -.loop: - movu m0, [r1] - movu m1, [r1+r2] - movu m2, [r1+r2*2] - movu m3, [r1+r4] - lea r1, [r1+r2*4] - pavgb m0, [r0] - pavgb m1, [r0+r2] - pavgb m2, [r0+r2*2] - pavgb m3, [r0+r4] - mova [r0], m0 - mova [r0+r2], m1 - mova [r0+r2*2], m2 - mova [r0+r4], m3 - sub r3d, 4 - lea r0, [r0+r2*4] - jnz .loop - REP_RET +OP_PIXELS put, 16 +OP_PIXELS avg, 16 diff --git a/libavcodec/x86/fpel.h b/libavcodec/x86/fpel.h new file mode 100644 index 000000000..4d93959a9 --- /dev/null +++ b/libavcodec/x86/fpel.h @@ -0,0 +1,45 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_X86_FPEL_H +#define AVCODEC_X86_FPEL_H + +#include +#include + +void ff_avg_pixels8_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels8_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels16_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels16_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels16_sse2(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels8_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels8_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_sse2(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); + + +#endif /* AVCODEC_X86_FPEL_H */ diff --git a/libavcodec/x86/fpel_mmx.c b/libavcodec/x86/fpel_mmx.c deleted file mode 100644 index 384ab89d9..000000000 --- a/libavcodec/x86/fpel_mmx.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * MMX-optimized avg/put pixel routines - * - * Copyright (c) 2000, 2001 Fabrice Bellard - * Copyright (c) 2002-2004 Michael Niedermayer - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include "config.h" -#include "dsputil_x86.h" - -#if HAVE_MMX_INLINE - -// in case more speed is needed - unrolling would certainly help -void ff_avg_pixels8_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h) -{ - MOVQ_BFE(mm6); - JUMPALIGN(); - do { - __asm__ volatile( - "movq %0, %%mm0 \n\t" - "movq %1, %%mm1 \n\t" - PAVGB_MMX(%%mm0, %%mm1, %%mm2, %%mm6) - "movq %%mm2, %0 \n\t" - :"+m"(*block) - :"m"(*pixels) - :"memory"); - pixels += line_size; - block += line_size; - } - while (--h); -} - -void ff_avg_pixels16_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h) -{ - MOVQ_BFE(mm6); - JUMPALIGN(); - do { - __asm__ volatile( - "movq %0, %%mm0 \n\t" - "movq %1, %%mm1 \n\t" - PAVGB_MMX(%%mm0, %%mm1, %%mm2, %%mm6) - "movq %%mm2, %0 \n\t" - "movq 8%0, %%mm0 \n\t" - "movq 8%1, %%mm1 \n\t" - PAVGB_MMX(%%mm0, %%mm1, %%mm2, %%mm6) - "movq %%mm2, 8%0 \n\t" - :"+m"(*block) - :"m"(*pixels) - :"memory"); - pixels += line_size; - block += line_size; - } - while (--h); -} - -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" - ".p2align 3 \n\t" - "1: \n\t" - "movq (%1 ), %%mm0 \n\t" - "movq (%1, %3), %%mm1 \n\t" - "movq %%mm0, (%2) \n\t" - "movq %%mm1, (%2, %3) \n\t" - "add %%"REG_a", %1 \n\t" - "add %%"REG_a", %2 \n\t" - "movq (%1 ), %%mm0 \n\t" - "movq (%1, %3), %%mm1 \n\t" - "movq %%mm0, (%2) \n\t" - "movq %%mm1, (%2, %3) \n\t" - "add %%"REG_a", %1 \n\t" - "add %%"REG_a", %2 \n\t" - "subl $4, %0 \n\t" - "jnz 1b \n\t" - : "+g"(h), "+r"(pixels), "+r"(block) - : "r"((x86_reg)line_size) - : "%"REG_a, "memory" - ); -} - -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" - ".p2align 3 \n\t" - "1: \n\t" - "movq (%1 ), %%mm0 \n\t" - "movq 8(%1 ), %%mm4 \n\t" - "movq (%1, %3), %%mm1 \n\t" - "movq 8(%1, %3), %%mm5 \n\t" - "movq %%mm0, (%2) \n\t" - "movq %%mm4, 8(%2) \n\t" - "movq %%mm1, (%2, %3) \n\t" - "movq %%mm5, 8(%2, %3) \n\t" - "add %%"REG_a", %1 \n\t" - "add %%"REG_a", %2 \n\t" - "movq (%1 ), %%mm0 \n\t" - "movq 8(%1 ), %%mm4 \n\t" - "movq (%1, %3), %%mm1 \n\t" - "movq 8(%1, %3), %%mm5 \n\t" - "movq %%mm0, (%2) \n\t" - "movq %%mm4, 8(%2) \n\t" - "movq %%mm1, (%2, %3) \n\t" - "movq %%mm5, 8(%2, %3) \n\t" - "add %%"REG_a", %1 \n\t" - "add %%"REG_a", %2 \n\t" - "subl $4, %0 \n\t" - "jnz 1b \n\t" - : "+g"(h), "+r"(pixels), "+r"(block) - : "r"((x86_reg)line_size) - : "%"REG_a, "memory" - ); -} - -#endif /* HAVE_MMX_INLINE */ diff --git a/libavcodec/x86/h263_loopfilter.asm b/libavcodec/x86/h263_loopfilter.asm index a21baf162..2fcd1a26e 100644 --- a/libavcodec/x86/h263_loopfilter.asm +++ b/libavcodec/x86/h263_loopfilter.asm @@ -101,7 +101,7 @@ SECTION_TEXT %endmacro INIT_MMX mmx -; void h263_v_loop_filter(uint8_t *src, int stride, int qscale) +; void ff_h263_v_loop_filter_mmx(uint8_t *src, int stride, int qscale) cglobal h263_v_loop_filter, 3,5 movsxdifnidn r1, r1d movsxdifnidn r2, r2d @@ -142,7 +142,7 @@ cglobal h263_v_loop_filter, 3,5 %endmacro -; void h263_h_loop_filter(uint8_t *src, int stride, int qscale) +; void ff_h263_h_loop_filter_mmx(uint8_t *src, int stride, int qscale) INIT_MMX mmx cglobal h263_h_loop_filter, 3,5,0,32 movsxdifnidn r1, r1d diff --git a/libavcodec/x86/h264_chromamc.asm b/libavcodec/x86/h264_chromamc.asm index 32681aafd..107ae51cb 100644 --- a/libavcodec/x86/h264_chromamc.asm +++ b/libavcodec/x86/h264_chromamc.asm @@ -103,8 +103,9 @@ SECTION .text %else %define extra_regs 0 %endif ; rv40 -; put/avg_h264_chroma_mc8_*(uint8_t *dst /*align 8*/, uint8_t *src /*align 1*/, -; int stride, int h, int mx, int my) +; void ff_put/avg_h264_chroma_mc8_*(uint8_t *dst /* align 8 */, +; uint8_t *src /* align 1 */, +; int stride, int h, int mx, int my) cglobal %1_%2_chroma_mc8%3, 6, 7 + extra_regs, 0 %if ARCH_X86_64 movsxd r2, r2d diff --git a/libavcodec/x86/h264_chromamc_10bit.asm b/libavcodec/x86/h264_chromamc_10bit.asm index beb7c0fe2..c35848209 100644 --- a/libavcodec/x86/h264_chromamc_10bit.asm +++ b/libavcodec/x86/h264_chromamc_10bit.asm @@ -57,11 +57,10 @@ SECTION .text %endmacro ;----------------------------------------------------------------------------- -; void put/avg_h264_chroma_mc8(pixel *dst, pixel *src, int stride, int h, int mx, int my) +; void ff_put/avg_h264_chroma_mc8(pixel *dst, pixel *src, int stride, int h, +; int mx, int my) ;----------------------------------------------------------------------------- %macro CHROMA_MC8 1 -; put/avg_h264_chroma_mc8_*(uint8_t *dst /*align 8*/, uint8_t *src /*align 1*/, -; int stride, int h, int mx, int my) cglobal %1_h264_chroma_mc8_10, 6,7,8 movsxdifnidn r2, r2d mov r6d, r5d @@ -150,7 +149,8 @@ cglobal %1_h264_chroma_mc8_10, 6,7,8 %endmacro ;----------------------------------------------------------------------------- -; void put/avg_h264_chroma_mc4(pixel *dst, pixel *src, int stride, int h, int mx, int my) +; void ff_put/avg_h264_chroma_mc4(pixel *dst, pixel *src, int stride, int h, +; int mx, int my) ;----------------------------------------------------------------------------- ;TODO: xmm mc4 %macro MC4_OP 2 @@ -200,7 +200,8 @@ cglobal %1_h264_chroma_mc4_10, 6,6,7 %endmacro ;----------------------------------------------------------------------------- -; void put/avg_h264_chroma_mc2(pixel *dst, pixel *src, int stride, int h, int mx, int my) +; void ff_put/avg_h264_chroma_mc2(pixel *dst, pixel *src, int stride, int h, +; int mx, int my) ;----------------------------------------------------------------------------- %macro CHROMA_MC2 1 cglobal %1_h264_chroma_mc2_10, 6,7 diff --git a/libavcodec/x86/h264_deblock.asm b/libavcodec/x86/h264_deblock.asm index 1317783be..14c8205ba 100644 --- a/libavcodec/x86/h264_deblock.asm +++ b/libavcodec/x86/h264_deblock.asm @@ -4,7 +4,7 @@ ;* Copyright (C) 2005-2011 x264 project ;* ;* Authors: Loren Merritt -;* Jason Garrett-Glaser +;* Fiona Glaser ;* Oskar Arvidsson ;* ;* This file is part of FFmpeg. @@ -283,7 +283,8 @@ cextern pb_3 %if ARCH_X86_64 ;----------------------------------------------------------------------------- -; void deblock_v_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +; void ff_deblock_v_luma(uint8_t *pix, int stride, int alpha, int beta, +; int8_t *tc0) ;----------------------------------------------------------------------------- %macro DEBLOCK_LUMA 0 cglobal deblock_v_luma_8, 5,5,10 @@ -328,7 +329,8 @@ cglobal deblock_v_luma_8, 5,5,10 RET ;----------------------------------------------------------------------------- -; void deblock_h_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +; void ff_deblock_h_luma(uint8_t *pix, int stride, int alpha, int beta, +; int8_t *tc0) ;----------------------------------------------------------------------------- INIT_MMX cpuname cglobal deblock_h_luma_8, 5,9,0,0x60+16*WIN64 @@ -391,7 +393,8 @@ DEBLOCK_LUMA %macro DEBLOCK_LUMA 2 ;----------------------------------------------------------------------------- -; void deblock_v8_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +; void ff_deblock_v8_luma(uint8_t *pix, int stride, int alpha, int beta, +; int8_t *tc0) ;----------------------------------------------------------------------------- cglobal deblock_%1_luma_8, 5,5,8,2*%2 lea r4, [r1*3] @@ -439,7 +442,8 @@ cglobal deblock_%1_luma_8, 5,5,8,2*%2 RET ;----------------------------------------------------------------------------- -; void deblock_h_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +; void ff_deblock_h_luma(uint8_t *pix, int stride, int alpha, int beta, +; int8_t *tc0) ;----------------------------------------------------------------------------- INIT_MMX cpuname cglobal deblock_h_luma_8, 0,5,8,0x60+HAVE_ALIGNED_STACK*12 @@ -639,7 +643,7 @@ DEBLOCK_LUMA v, 16 %endif ;----------------------------------------------------------------------------- -; void deblock_v_luma_intra( uint8_t *pix, int stride, int alpha, int beta ) +; void ff_deblock_v_luma_intra(uint8_t *pix, int stride, int alpha, int beta) ;----------------------------------------------------------------------------- %if WIN64 cglobal deblock_%1_luma_intra_8, 4,6,16,0x10 @@ -699,7 +703,7 @@ cglobal deblock_%1_luma_intra_8, 4,6,16,ARCH_X86_64*0x50-0x50 INIT_MMX cpuname %if ARCH_X86_64 ;----------------------------------------------------------------------------- -; void deblock_h_luma_intra( uint8_t *pix, int stride, int alpha, int beta ) +; void ff_deblock_h_luma_intra(uint8_t *pix, int stride, int alpha, int beta) ;----------------------------------------------------------------------------- cglobal deblock_h_luma_intra_8, 4,9,0,0x80 movsxd r7, r1d @@ -804,7 +808,8 @@ INIT_MMX mmxext %define t6 r6 ;----------------------------------------------------------------------------- -; void ff_deblock_v_chroma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +; void ff_deblock_v_chroma(uint8_t *pix, int stride, int alpha, int beta, +; int8_t *tc0) ;----------------------------------------------------------------------------- cglobal deblock_v_chroma_8, 5,6 CHROMA_V_START @@ -818,13 +823,14 @@ cglobal deblock_v_chroma_8, 5,6 RET ;----------------------------------------------------------------------------- -; void ff_deblock_h_chroma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +; void ff_deblock_h_chroma(uint8_t *pix, int stride, int alpha, int beta, +; int8_t *tc0) ;----------------------------------------------------------------------------- cglobal deblock_h_chroma_8, 5,7 -%if UNIX64 - %define buf0 [rsp-24] - %define buf1 [rsp-16] -%elif WIN64 +%if ARCH_X86_64 + ; This could use the red zone on 64 bit unix to avoid the stack pointer + ; readjustment, but valgrind assumes the red zone is clobbered on + ; function calls and returns. sub rsp, 16 %define buf0 [rsp] %define buf1 [rsp+8] @@ -844,7 +850,7 @@ cglobal deblock_h_chroma_8, 5,7 movq m0, buf0 movq m3, buf1 TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6) -%if WIN64 +%if ARCH_X86_64 add rsp, 16 %endif RET @@ -874,9 +880,9 @@ ff_chroma_inter_body_mmxext: %define t5 r4 %define t6 r5 -;----------------------------------------------------------------------------- -; void ff_deblock_v_chroma_intra( uint8_t *pix, int stride, int alpha, int beta ) -;----------------------------------------------------------------------------- +;------------------------------------------------------------------------------ +; void ff_deblock_v_chroma_intra(uint8_t *pix, int stride, int alpha, int beta) +;------------------------------------------------------------------------------ cglobal deblock_v_chroma_intra_8, 4,5 CHROMA_V_START movq m0, [t5] @@ -888,9 +894,9 @@ cglobal deblock_v_chroma_intra_8, 4,5 movq [r0], m2 RET -;----------------------------------------------------------------------------- -; void ff_deblock_h_chroma_intra( uint8_t *pix, int stride, int alpha, int beta ) -;----------------------------------------------------------------------------- +;------------------------------------------------------------------------------ +; void ff_deblock_h_chroma_intra(uint8_t *pix, int stride, int alpha, int beta) +;------------------------------------------------------------------------------ cglobal deblock_h_chroma_intra_8, 4,6 CHROMA_H_START TRANSPOSE4x8_LOAD bw, wd, dq, PASS8ROWS(t5, r0, r1, t6) @@ -914,10 +920,10 @@ ff_chroma_intra_body_mmxext: ret ;----------------------------------------------------------------------------- -; void h264_loop_filter_strength(int16_t bs[2][4][4], uint8_t nnz[40], -; int8_t ref[2][40], int16_t mv[2][40][2], -; int bidir, int edges, int step, -; int mask_mv0, int mask_mv1, int field); +; void ff_h264_loop_filter_strength(int16_t bs[2][4][4], uint8_t nnz[40], +; int8_t ref[2][40], int16_t mv[2][40][2], +; int bidir, int edges, int step, +; int mask_mv0, int mask_mv1, int field); ; ; bidir is 0 or 1 ; edges is 1 or 4 diff --git a/libavcodec/x86/h264_deblock_10bit.asm b/libavcodec/x86/h264_deblock_10bit.asm index fdaf510bd..d8ace17ec 100644 --- a/libavcodec/x86/h264_deblock_10bit.asm +++ b/libavcodec/x86/h264_deblock_10bit.asm @@ -5,7 +5,7 @@ ;* ;* Authors: Oskar Arvidsson ;* Loren Merritt -;* Jason Garrett-Glaser +;* Fiona Glaser ;* ;* This file is part of FFmpeg. ;* @@ -152,7 +152,8 @@ cextern pw_4 %macro DEBLOCK_LUMA 0 ;----------------------------------------------------------------------------- -; void deblock_v_luma( uint16_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +; void ff_deblock_v_luma_10(uint16_t *pix, int stride, int alpha, int beta, +; int8_t *tc0) ;----------------------------------------------------------------------------- cglobal deblock_v_luma_10, 5,5,8*(mmsize/16) %assign pad 5*mmsize+12-(stack_offset&15) @@ -600,7 +601,8 @@ DEBLOCK_LUMA_64 %if ARCH_X86_64 ;----------------------------------------------------------------------------- -; void deblock_v_luma_intra( uint16_t *pix, int stride, int alpha, int beta ) +; void ff_deblock_v_luma_intra_10(uint16_t *pix, int stride, int alpha, +; int beta) ;----------------------------------------------------------------------------- %macro DEBLOCK_LUMA_INTRA_64 0 cglobal deblock_v_luma_intra_10, 4,7,16 @@ -651,7 +653,8 @@ cglobal deblock_v_luma_intra_10, 4,7,16 REP_RET ;----------------------------------------------------------------------------- -; void deblock_h_luma_intra( uint16_t *pix, int stride, int alpha, int beta ) +; void ff_deblock_h_luma_intra_10(uint16_t *pix, int stride, int alpha, +; int beta) ;----------------------------------------------------------------------------- cglobal deblock_h_luma_intra_10, 4,7,16 %define t0 m15 @@ -723,7 +726,8 @@ DEBLOCK_LUMA_INTRA_64 %macro DEBLOCK_LUMA_INTRA 0 ;----------------------------------------------------------------------------- -; void deblock_v_luma_intra( uint16_t *pix, int stride, int alpha, int beta ) +; void ff_deblock_v_luma_intra_10(uint16_t *pix, int stride, int alpha, +; int beta) ;----------------------------------------------------------------------------- cglobal deblock_v_luma_intra_10, 4,7,8*(mmsize/16) LUMA_INTRA_INIT 3 @@ -751,7 +755,8 @@ cglobal deblock_v_luma_intra_10, 4,7,8*(mmsize/16) RET ;----------------------------------------------------------------------------- -; void deblock_h_luma_intra( uint16_t *pix, int stride, int alpha, int beta ) +; void ff_deblock_h_luma_intra_10(uint16_t *pix, int stride, int alpha, +; int beta) ;----------------------------------------------------------------------------- cglobal deblock_h_luma_intra_10, 4,7,8*(mmsize/16) LUMA_INTRA_INIT 8 @@ -849,7 +854,8 @@ DEBLOCK_LUMA_INTRA %macro DEBLOCK_CHROMA 0 ;----------------------------------------------------------------------------- -; void deblock_v_chroma( uint16_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +; void ff_deblock_v_chroma_10(uint16_t *pix, int stride, int alpha, int beta, +; int8_t *tc0) ;----------------------------------------------------------------------------- cglobal deblock_v_chroma_10, 5,7-(mmsize/16),8*(mmsize/16) mov r5, r0 @@ -883,7 +889,8 @@ cglobal deblock_v_chroma_10, 5,7-(mmsize/16),8*(mmsize/16) %endif ;----------------------------------------------------------------------------- -; void deblock_v_chroma_intra( uint16_t *pix, int stride, int alpha, int beta ) +; void ff_deblock_v_chroma_intra_10(uint16_t *pix, int stride, int alpha, +; int beta) ;----------------------------------------------------------------------------- cglobal deblock_v_chroma_intra_10, 4,6-(mmsize/16),8*(mmsize/16) mov r4, r0 diff --git a/libavcodec/x86/h264_i386.h b/libavcodec/x86/h264_i386.h index 0dc0a7cb0..ef65cf86b 100644 --- a/libavcodec/x86/h264_i386.h +++ b/libavcodec/x86/h264_i386.h @@ -38,7 +38,7 @@ //FIXME use some macros to avoid duplicating get_cabac (cannot be done yet //as that would make optimization work hard) -#if HAVE_7REGS +#if HAVE_7REGS && !BROKEN_COMPILER #define decode_significance decode_significance_x86 static int decode_significance_x86(CABACContext *c, int max_coeff, uint8_t *significant_coeff_ctx_base, @@ -55,6 +55,7 @@ static int decode_significance_x86(CABACContext *c, int max_coeff, __asm__ volatile( "lea "MANGLE(ff_h264_cabac_tables)", %0 \n\t" : "=&r"(tables) + : NAMED_CONSTRAINTS_ARRAY(ff_h264_cabac_tables) ); #endif @@ -130,6 +131,7 @@ static int decode_significance_8x8_x86(CABACContext *c, __asm__ volatile( "lea "MANGLE(ff_h264_cabac_tables)", %0 \n\t" : "=&r"(tables) + : NAMED_CONSTRAINTS_ARRAY(ff_h264_cabac_tables) ); #endif @@ -198,7 +200,7 @@ static int decode_significance_8x8_x86(CABACContext *c, ); return coeff_count; } -#endif /* HAVE_7REGS && !defined(BROKEN_RELOCATIONS) */ +#endif /* HAVE_7REGS && BROKEN_COMPILER */ #endif /* HAVE_INLINE_ASM */ #endif /* AVCODEC_X86_H264_I386_H */ diff --git a/libavcodec/x86/h264_idct.asm b/libavcodec/x86/h264_idct.asm index 9af98a9a0..7fafe195f 100644 --- a/libavcodec/x86/h264_idct.asm +++ b/libavcodec/x86/h264_idct.asm @@ -80,7 +80,7 @@ SECTION .text %endmacro INIT_MMX mmx -; ff_h264_idct_add_8_mmx(uint8_t *dst, int16_t *block, int stride) +; void ff_h264_idct_add_8_mmx(uint8_t *dst, int16_t *block, int stride) cglobal h264_idct_add_8, 3, 3, 0 IDCT4_ADD r0, r1, r2 RET @@ -202,7 +202,7 @@ cglobal h264_idct_add_8, 3, 3, 0 %endmacro INIT_MMX mmx -; ff_h264_idct8_add_8_mmx(uint8_t *dst, int16_t *block, int stride) +; void ff_h264_idct8_add_8_mmx(uint8_t *dst, int16_t *block, int stride) cglobal h264_idct8_add_8, 3, 4, 0 %assign pad 128+4-(stack_offset&7) SUB rsp, pad @@ -270,7 +270,7 @@ cglobal h264_idct8_add_8, 3, 4, 0 %endmacro INIT_XMM sse2 -; ff_h264_idct8_add_8_sse2(uint8_t *dst, int16_t *block, int stride) +; void ff_h264_idct8_add_8_sse2(uint8_t *dst, int16_t *block, int stride) cglobal h264_idct8_add_8, 3, 4, 10 IDCT8_ADD_SSE r0, r1, r2, r3 RET @@ -307,7 +307,7 @@ cglobal h264_idct8_add_8, 3, 4, 10 %endmacro INIT_MMX mmxext -; ff_h264_idct_dc_add_8_mmxext(uint8_t *dst, int16_t *block, int stride) +; 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 movsx r3, word [r1] @@ -316,7 +316,7 @@ cglobal h264_idct_dc_add_8, 3, 4, 0 DC_ADD_MMXEXT_OP movh, r0, r2, r3 RET -; ff_h264_idct8_dc_add_8_mmxext(uint8_t *dst, int16_t *block, int stride) +; 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 movsx r3, word [r1] mov dword [r1], 0 @@ -326,7 +326,7 @@ cglobal h264_idct8_dc_add_8, 3, 4, 0 DC_ADD_MMXEXT_OP mova, r0, r2, r3 RET %else -; ff_h264_idct_dc_add_8_mmxext(uint8_t *dst, int16_t *block, int stride) +; void ff_h264_idct_dc_add_8_mmxext(uint8_t *dst, int16_t *block, int stride) cglobal h264_idct_dc_add_8, 2, 3, 0 movsx r2, word [r1] mov dword [r1], 0 @@ -335,7 +335,7 @@ cglobal h264_idct_dc_add_8, 2, 3, 0 DC_ADD_MMXEXT_OP movh, r0, r1, r2 RET -; ff_h264_idct8_dc_add_8_mmxext(uint8_t *dst, int16_t *block, int stride) +; void ff_h264_idct8_dc_add_8_mmxext(uint8_t *dst, int16_t *block, int stride) cglobal h264_idct8_dc_add_8, 2, 3, 0 movsx r2, word [r1] mov dword [r1], 0 @@ -348,9 +348,9 @@ cglobal h264_idct8_dc_add_8, 2, 3, 0 %endif INIT_MMX mmx -; ff_h264_idct_add16_8_mmx(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) +; void ff_h264_idct_add16_8_mmx(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add16_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, nnzc, cntr, coeff, picreg xor r5, r5 %ifdef PIC @@ -371,9 +371,9 @@ cglobal h264_idct_add16_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, jl .nextblock REP_RET -; ff_h264_idct8_add4_8_mmx(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) +; void ff_h264_idct8_add4_8_mmx(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6 * 8]) cglobal h264_idct8_add4_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, nnzc, cntr, coeff, picreg %assign pad 128+4-(stack_offset&7) SUB rsp, pad @@ -405,9 +405,9 @@ cglobal h264_idct8_add4_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, RET INIT_MMX mmxext -; ff_h264_idct_add16_8_mmxext(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) +; void ff_h264_idct_add16_8_mmxext(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add16_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg xor r5, r5 %ifdef PIC @@ -452,9 +452,9 @@ cglobal h264_idct_add16_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride REP_RET INIT_MMX mmx -; ff_h264_idct_add16intra_8_mmx(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) +; void ff_h264_idct_add16intra_8_mmx(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add16intra_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, nnzc, cntr, coeff, picreg xor r5, r5 %ifdef PIC @@ -477,9 +477,9 @@ cglobal h264_idct_add16intra_8, 5, 7 + npicregs, 0, dst, block_offset, block, st REP_RET INIT_MMX mmxext -; ff_h264_idct_add16intra_8_mmxext(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) +; void ff_h264_idct_add16intra_8_mmxext(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add16intra_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg xor r5, r5 %ifdef PIC @@ -521,9 +521,9 @@ cglobal h264_idct_add16intra_8, 5, 8 + npicregs, 0, dst1, block_offset, block, s jl .nextblock REP_RET -; ff_h264_idct8_add4_8_mmxext(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) +; void ff_h264_idct8_add4_8_mmxext(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6 * 8]) cglobal h264_idct8_add4_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg %assign pad 128+4-(stack_offset&7) SUB rsp, pad @@ -583,9 +583,9 @@ cglobal h264_idct8_add4_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride RET INIT_XMM sse2 -; ff_h264_idct8_add4_8_sse2(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) +; void ff_h264_idct8_add4_8_sse2(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6 * 8]) cglobal h264_idct8_add4_8, 5, 8 + npicregs, 10, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg xor r5, r5 %ifdef PIC @@ -660,8 +660,9 @@ h264_idct_add8_mmx_plane: jnz .nextblock rep ret -; ff_h264_idct_add8_8_mmx(uint8_t **dest, const int *block_offset, -; int16_t *block, int stride, const uint8_t nnzc[6 * 8]) +; void ff_h264_idct_add8_8_mmx(uint8_t **dest, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add8_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg mov r5, 16 add r2, 512 @@ -725,9 +726,9 @@ h264_idct_add8_mmxext_plane: rep ret INIT_MMX mmxext -; ff_h264_idct_add8_8_mmxext(uint8_t **dest, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) +; void ff_h264_idct_add8_8_mmxext(uint8_t **dest, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add8_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg mov r5, 16 add r2, 512 @@ -809,9 +810,9 @@ h264_add8x4_idct_sse2: %endif %endmacro -; ff_h264_idct_add16_8_sse2(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) +; void ff_h264_idct_add16_8_sse2(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add16_8, 5, 5 + ARCH_X86_64, 8 %if ARCH_X86_64 mov r5, r0 @@ -857,9 +858,9 @@ cglobal h264_idct_add16_8, 5, 5 + ARCH_X86_64, 8 %endif %endmacro -; ff_h264_idct_add16intra_8_sse2(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) +; void ff_h264_idct_add16intra_8_sse2(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add16intra_8, 5, 7 + ARCH_X86_64, 8 %if ARCH_X86_64 mov r7, r0 @@ -909,9 +910,9 @@ cglobal h264_idct_add16intra_8, 5, 7 + ARCH_X86_64, 8 %endif %endmacro -; ff_h264_idct_add8_8_sse2(uint8_t **dest, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) +; void ff_h264_idct_add8_8_sse2(uint8_t **dest, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add8_8, 5, 7 + ARCH_X86_64, 8 add r2, 512 %if ARCH_X86_64 diff --git a/libavcodec/x86/h264_idct_10bit.asm b/libavcodec/x86/h264_idct_10bit.asm index df212888d..5c3acb1d3 100644 --- a/libavcodec/x86/h264_idct_10bit.asm +++ b/libavcodec/x86/h264_idct_10bit.asm @@ -32,7 +32,7 @@ pd_32: times 4 dd 32 SECTION .text ;----------------------------------------------------------------------------- -; void h264_idct_add(pixel *dst, dctcoef *block, int stride) +; void ff_h264_idct_add_10(pixel *dst, int16_t *block, int stride) ;----------------------------------------------------------------------------- %macro STORE_DIFFx2 6 psrad %1, 6 @@ -89,7 +89,9 @@ IDCT_ADD_10 %endif ;----------------------------------------------------------------------------- -; h264_idct_add16(pixel *dst, const int *block_offset, dctcoef *block, int stride, const uint8_t nnzc[6*8]) +; void ff_h264_idct_add16_10(pixel *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6*8]) ;----------------------------------------------------------------------------- ;;;;;;; NO FATE SAMPLES TRIGGER THIS %macro ADD4x4IDCT 0 @@ -163,7 +165,7 @@ IDCT_ADD16_10 %endif ;----------------------------------------------------------------------------- -; void h264_idct_dc_add(pixel *dst, dctcoef *block, int stride) +; void ff_h264_idct_dc_add_10(pixel *dst, int16_t *block, int stride) ;----------------------------------------------------------------------------- %macro IDCT_DC_ADD_OP_10 3 pxor m5, m5 @@ -205,7 +207,7 @@ cglobal h264_idct_dc_add_10,3,3 RET ;----------------------------------------------------------------------------- -; void h264_idct8_dc_add(pixel *dst, dctcoef *block, int stride) +; void ff_h264_idct8_dc_add_10(pixel *dst, int16_t *block, int stride) ;----------------------------------------------------------------------------- %macro IDCT8_DC_ADD 0 cglobal h264_idct8_dc_add_10,3,4,7 @@ -230,7 +232,9 @@ IDCT8_DC_ADD %endif ;----------------------------------------------------------------------------- -; h264_idct_add16intra(pixel *dst, const int *block_offset, dctcoef *block, int stride, const uint8_t nnzc[6*8]) +; void ff_h264_idct_add16intra_10(pixel *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6*8]) ;----------------------------------------------------------------------------- %macro AC 1 .ac%1: @@ -304,7 +308,9 @@ IDCT_ADD16INTRA_10 %assign last_block 36 ;----------------------------------------------------------------------------- -; h264_idct_add8(pixel **dst, const int *block_offset, dctcoef *block, int stride, const uint8_t nnzc[6*8]) +; void ff_h264_idct_add8_10(pixel **dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6*8]) ;----------------------------------------------------------------------------- %macro IDCT_ADD8 0 cglobal h264_idct_add8_10,5,8,7 @@ -340,7 +346,7 @@ IDCT_ADD8 %endif ;----------------------------------------------------------------------------- -; void h264_idct8_add(pixel *dst, dctcoef *block, int stride) +; void ff_h264_idct8_add_10(pixel *dst, int16_t *block, int stride) ;----------------------------------------------------------------------------- %macro IDCT8_1D 2 SWAP 0, 1 @@ -549,7 +555,9 @@ IDCT8_ADD %endif ;----------------------------------------------------------------------------- -; h264_idct8_add4(pixel **dst, const int *block_offset, dctcoef *block, int stride, const uint8_t nnzc[6*8]) +; void ff_h264_idct8_add4_10(pixel **dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6*8]) ;----------------------------------------------------------------------------- ;;;;;;; NO FATE SAMPLES TRIGGER THIS %macro IDCT8_ADD4_OP 2 diff --git a/libavcodec/x86/h264_intrapred.asm b/libavcodec/x86/h264_intrapred.asm index 3064ec520..88ba597f1 100644 --- a/libavcodec/x86/h264_intrapred.asm +++ b/libavcodec/x86/h264_intrapred.asm @@ -1,6 +1,6 @@ ;****************************************************************************** ;* H.264 intra prediction asm optimizations -;* Copyright (c) 2010 Jason Garrett-Glaser +;* Copyright (c) 2010 Fiona Glaser ;* Copyright (c) 2010 Holger Lubitz ;* Copyright (c) 2010 Loren Merritt ;* Copyright (c) 2010 Ronald S. Bultje @@ -49,7 +49,7 @@ cextern pw_17 cextern pw_32 ;----------------------------------------------------------------------------- -; void pred16x16_vertical_8(uint8_t *src, int stride) +; void ff_pred16x16_vertical_8(uint8_t *src, int stride) ;----------------------------------------------------------------------------- INIT_MMX mmx @@ -85,7 +85,7 @@ cglobal pred16x16_vertical_8, 2,3 REP_RET ;----------------------------------------------------------------------------- -; void pred16x16_horizontal_8(uint8_t *src, int stride) +; void ff_pred16x16_horizontal_8(uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro PRED16x16_H 0 @@ -126,7 +126,7 @@ INIT_XMM ssse3 PRED16x16_H ;----------------------------------------------------------------------------- -; void pred16x16_dc_8(uint8_t *src, int stride) +; void ff_pred16x16_dc_8(uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro PRED16x16_DC 0 @@ -188,7 +188,7 @@ INIT_XMM ssse3 PRED16x16_DC ;----------------------------------------------------------------------------- -; void pred16x16_tm_vp8_8(uint8_t *src, int stride) +; void ff_pred16x16_tm_vp8_8(uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro PRED16x16_TM 0 @@ -269,7 +269,7 @@ cglobal pred16x16_tm_vp8_8, 2,6,6 REP_RET ;----------------------------------------------------------------------------- -; void pred16x16_plane_*_8(uint8_t *src, int stride) +; void ff_pred16x16_plane_*_8(uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro H264_PRED16x16_PLANE 1 @@ -550,7 +550,7 @@ H264_PRED16x16_PLANE rv40 H264_PRED16x16_PLANE svq3 ;----------------------------------------------------------------------------- -; void pred8x8_plane_8(uint8_t *src, int stride) +; void ff_pred8x8_plane_8(uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro H264_PRED8x8_PLANE 0 @@ -724,7 +724,7 @@ INIT_XMM ssse3 H264_PRED8x8_PLANE ;----------------------------------------------------------------------------- -; void pred8x8_vertical_8(uint8_t *src, int stride) +; void ff_pred8x8_vertical_8(uint8_t *src, int stride) ;----------------------------------------------------------------------------- INIT_MMX mmx @@ -741,7 +741,7 @@ cglobal pred8x8_vertical_8, 2,2 RET ;----------------------------------------------------------------------------- -; void pred8x8_horizontal_8(uint8_t *src, int stride) +; void ff_pred8x8_horizontal_8(uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro PRED8x8_H 0 @@ -769,7 +769,7 @@ INIT_MMX ssse3 PRED8x8_H ;----------------------------------------------------------------------------- -; void pred8x8_top_dc_8_mmxext(uint8_t *src, int stride) +; void ff_pred8x8_top_dc_8_mmxext(uint8_t *src, int stride) ;----------------------------------------------------------------------------- INIT_MMX mmxext cglobal pred8x8_top_dc_8, 2,5 @@ -803,7 +803,7 @@ cglobal pred8x8_top_dc_8, 2,5 RET ;----------------------------------------------------------------------------- -; void pred8x8_dc_8_mmxext(uint8_t *src, int stride) +; void ff_pred8x8_dc_8_mmxext(uint8_t *src, int stride) ;----------------------------------------------------------------------------- INIT_MMX mmxext @@ -864,7 +864,7 @@ cglobal pred8x8_dc_8, 2,5 RET ;----------------------------------------------------------------------------- -; void pred8x8_dc_rv40_8(uint8_t *src, int stride) +; void ff_pred8x8_dc_rv40_8(uint8_t *src, int stride) ;----------------------------------------------------------------------------- INIT_MMX mmxext @@ -901,7 +901,7 @@ cglobal pred8x8_dc_rv40_8, 2,7 REP_RET ;----------------------------------------------------------------------------- -; void pred8x8_tm_vp8_8(uint8_t *src, int stride) +; void ff_pred8x8_tm_vp8_8(uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro PRED8x8_TM 0 @@ -1013,7 +1013,8 @@ cglobal pred8x8_tm_vp8_8, 2,3,6 %endmacro ;----------------------------------------------------------------------------- -; void pred8x8l_top_dc_8(uint8_t *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_top_dc_8(uint8_t *src, int has_topleft, int has_topright, +; int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_TOP_DC 0 cglobal pred8x8l_top_dc_8, 4,4 @@ -1068,7 +1069,8 @@ INIT_MMX ssse3 PRED8x8L_TOP_DC ;----------------------------------------------------------------------------- -;void pred8x8l_dc_8(uint8_t *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_dc_8(uint8_t *src, int has_topleft, int has_topright, +; int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_DC 0 @@ -1171,7 +1173,8 @@ INIT_MMX ssse3 PRED8x8L_DC ;----------------------------------------------------------------------------- -; void pred8x8l_horizontal_8(uint8_t *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_horizontal_8(uint8_t *src, int has_topleft, +; int has_topright, int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_HORIZONTAL 0 @@ -1242,7 +1245,8 @@ INIT_MMX ssse3 PRED8x8L_HORIZONTAL ;----------------------------------------------------------------------------- -; void pred8x8l_vertical_8(uint8_t *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_vertical_8(uint8_t *src, int has_topleft, int has_topright, +; int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_VERTICAL 0 @@ -1292,7 +1296,8 @@ INIT_MMX ssse3 PRED8x8L_VERTICAL ;----------------------------------------------------------------------------- -;void pred8x8l_down_left_8(uint8_t *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_down_left_8(uint8_t *src, int has_topleft, +; int has_topright, int stride) ;----------------------------------------------------------------------------- INIT_MMX mmxext @@ -1492,7 +1497,8 @@ INIT_MMX ssse3 PRED8x8L_DOWN_LEFT ;----------------------------------------------------------------------------- -;void pred8x8l_down_right_8_mmxext(uint8_t *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_down_right_8_mmxext(uint8_t *src, int has_topleft, +; int has_topright, int stride) ;----------------------------------------------------------------------------- INIT_MMX mmxext @@ -1743,7 +1749,8 @@ INIT_MMX ssse3 PRED8x8L_DOWN_RIGHT ;----------------------------------------------------------------------------- -; void pred8x8l_vertical_right_8(uint8_t *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_vertical_right_8(uint8_t *src, int has_topleft, +; int has_topright, int stride) ;----------------------------------------------------------------------------- INIT_MMX mmxext @@ -1970,7 +1977,8 @@ INIT_MMX ssse3 PRED8x8L_VERTICAL_RIGHT ;----------------------------------------------------------------------------- -;void pred8x8l_vertical_left_8(uint8_t *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_vertical_left_8(uint8_t *src, int has_topleft, +; int has_topright, int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_VERTICAL_LEFT 0 @@ -2059,7 +2067,8 @@ INIT_MMX ssse3 PRED8x8L_VERTICAL_LEFT ;----------------------------------------------------------------------------- -; void pred8x8l_horizontal_up_8(uint8_t *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_horizontal_up_8(uint8_t *src, int has_topleft, +; int has_topright, int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_HORIZONTAL_UP 0 @@ -2146,7 +2155,8 @@ INIT_MMX ssse3 PRED8x8L_HORIZONTAL_UP ;----------------------------------------------------------------------------- -;void pred8x8l_horizontal_down_8(uint8_t *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_horizontal_down_8(uint8_t *src, int has_topleft, +; int has_topright, int stride) ;----------------------------------------------------------------------------- INIT_MMX mmxext @@ -2393,9 +2403,9 @@ PRED8x8L_HORIZONTAL_DOWN INIT_MMX ssse3 PRED8x8L_HORIZONTAL_DOWN -;----------------------------------------------------------------------------- -; void pred4x4_dc_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) -;----------------------------------------------------------------------------- +;------------------------------------------------------------------------------- +; void ff_pred4x4_dc_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +;------------------------------------------------------------------------------- INIT_MMX mmxext cglobal pred4x4_dc_8, 3,5 @@ -2424,7 +2434,8 @@ cglobal pred4x4_dc_8, 3,5 RET ;----------------------------------------------------------------------------- -; void pred4x4_tm_vp8_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +; void ff_pred4x4_tm_vp8_8_mmxext(uint8_t *src, const uint8_t *topright, +; int stride) ;----------------------------------------------------------------------------- %macro PRED4x4_TM 0 @@ -2502,7 +2513,8 @@ cglobal pred4x4_tm_vp8_8, 3,3 RET ;----------------------------------------------------------------------------- -; void pred4x4_vertical_vp8_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +; void ff_pred4x4_vertical_vp8_8_mmxext(uint8_t *src, const uint8_t *topright, +; int stride) ;----------------------------------------------------------------------------- INIT_MMX mmxext @@ -2522,7 +2534,8 @@ cglobal pred4x4_vertical_vp8_8, 3,3 RET ;----------------------------------------------------------------------------- -; void pred4x4_down_left_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +; void ff_pred4x4_down_left_8_mmxext(uint8_t *src, const uint8_t *topright, +; int stride) ;----------------------------------------------------------------------------- INIT_MMX mmxext cglobal pred4x4_down_left_8, 3,3 @@ -2547,9 +2560,10 @@ cglobal pred4x4_down_left_8, 3,3 movd [r1+r2*2], m0 RET -;----------------------------------------------------------------------------- -; void pred4x4_vertical_left_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) -;----------------------------------------------------------------------------- +;------------------------------------------------------------------------------ +; void ff_pred4x4_vertical_left_8_mmxext(uint8_t *src, const uint8_t *topright, +; int stride) +;------------------------------------------------------------------------------ INIT_MMX mmxext cglobal pred4x4_vertical_left_8, 3,3 @@ -2572,9 +2586,10 @@ cglobal pred4x4_vertical_left_8, 3,3 movh [r1+r2*2], m0 RET -;----------------------------------------------------------------------------- -; void pred4x4_horizontal_up_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) -;----------------------------------------------------------------------------- +;------------------------------------------------------------------------------ +; void ff_pred4x4_horizontal_up_8_mmxext(uint8_t *src, const uint8_t *topright, +; int stride) +;------------------------------------------------------------------------------ INIT_MMX mmxext cglobal pred4x4_horizontal_up_8, 3,3 @@ -2605,9 +2620,10 @@ cglobal pred4x4_horizontal_up_8, 3,3 movd [r1+r2*2], m1 RET -;----------------------------------------------------------------------------- -; void pred4x4_horizontal_down_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) -;----------------------------------------------------------------------------- +;------------------------------------------------------------------------------ +; void ff_pred4x4_horizontal_down_8_mmxext(uint8_t *src, +; const uint8_t *topright, int stride) +;------------------------------------------------------------------------------ INIT_MMX mmxext cglobal pred4x4_horizontal_down_8, 3,3 @@ -2641,7 +2657,8 @@ cglobal pred4x4_horizontal_down_8, 3,3 RET ;----------------------------------------------------------------------------- -; void pred4x4_vertical_right_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +; void ff_pred4x4_vertical_right_8_mmxext(uint8_t *src, +; const uint8_t *topright, int stride) ;----------------------------------------------------------------------------- INIT_MMX mmxext @@ -2671,7 +2688,8 @@ cglobal pred4x4_vertical_right_8, 3,3 RET ;----------------------------------------------------------------------------- -; void pred4x4_down_right_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +; void ff_pred4x4_down_right_8_mmxext(uint8_t *src, const uint8_t *topright, +; int stride) ;----------------------------------------------------------------------------- INIT_MMX mmxext diff --git a/libavcodec/x86/h264_intrapred_10bit.asm b/libavcodec/x86/h264_intrapred_10bit.asm index 54eaee53c..9dee577e1 100644 --- a/libavcodec/x86/h264_intrapred_10bit.asm +++ b/libavcodec/x86/h264_intrapred_10bit.asm @@ -50,7 +50,7 @@ SECTION .text %endmacro ;----------------------------------------------------------------------------- -; void pred4x4_down_right(pixel *src, const pixel *topright, int stride) +; void ff_pred4x4_down_right(pixel *src, const pixel *topright, int stride) ;----------------------------------------------------------------------------- %macro PRED4x4_DR 0 cglobal pred4x4_down_right_10, 3, 3 @@ -87,9 +87,9 @@ INIT_XMM avx PRED4x4_DR %endif -;----------------------------------------------------------------------------- -; void pred4x4_vertical_right(pixel *src, const pixel *topright, int stride) -;----------------------------------------------------------------------------- +;------------------------------------------------------------------------------ +; void ff_pred4x4_vertical_right(pixel *src, const pixel *topright, int stride) +;------------------------------------------------------------------------------ %macro PRED4x4_VR 0 cglobal pred4x4_vertical_right_10, 3, 3, 6 sub r0, r2 @@ -126,9 +126,9 @@ INIT_XMM avx PRED4x4_VR %endif -;----------------------------------------------------------------------------- -; void pred4x4_horizontal_down(pixel *src, const pixel *topright, int stride) -;----------------------------------------------------------------------------- +;------------------------------------------------------------------------------- +; void ff_pred4x4_horizontal_down(pixel *src, const pixel *topright, int stride) +;------------------------------------------------------------------------------- %macro PRED4x4_HD 0 cglobal pred4x4_horizontal_down_10, 3, 3 sub r0, r2 @@ -169,24 +169,8 @@ PRED4x4_HD %endif ;----------------------------------------------------------------------------- -; void pred4x4_dc(pixel *src, const pixel *topright, int stride) +; void ff_pred4x4_dc(pixel *src, const pixel *topright, int stride) ;----------------------------------------------------------------------------- -%macro HADDD 2 ; sum junk -%if mmsize == 16 - movhlps %2, %1 - paddd %1, %2 - pshuflw %2, %1, 0xE - paddd %1, %2 -%else - pshufw %2, %1, 0xE - paddd %1, %2 -%endif -%endmacro - -%macro HADDW 2 - pmaddwd %1, [pw_1] - HADDD %1, %2 -%endmacro INIT_MMX mmxext cglobal pred4x4_dc_10, 3, 3 @@ -210,7 +194,7 @@ cglobal pred4x4_dc_10, 3, 3 RET ;----------------------------------------------------------------------------- -; void pred4x4_down_left(pixel *src, const pixel *topright, int stride) +; void ff_pred4x4_down_left(pixel *src, const pixel *topright, int stride) ;----------------------------------------------------------------------------- %macro PRED4x4_DL 0 cglobal pred4x4_down_left_10, 3, 3 @@ -240,7 +224,7 @@ PRED4x4_DL %endif ;----------------------------------------------------------------------------- -; void pred4x4_vertical_left(pixel *src, const pixel *topright, int stride) +; void ff_pred4x4_vertical_left(pixel *src, const pixel *topright, int stride) ;----------------------------------------------------------------------------- %macro PRED4x4_VL 0 cglobal pred4x4_vertical_left_10, 3, 3 @@ -269,7 +253,7 @@ PRED4x4_VL %endif ;----------------------------------------------------------------------------- -; void pred4x4_horizontal_up(pixel *src, const pixel *topright, int stride) +; void ff_pred4x4_horizontal_up(pixel *src, const pixel *topright, int stride) ;----------------------------------------------------------------------------- INIT_MMX mmxext cglobal pred4x4_horizontal_up_10, 3, 3 @@ -303,7 +287,7 @@ cglobal pred4x4_horizontal_up_10, 3, 3 ;----------------------------------------------------------------------------- -; void pred8x8_vertical(pixel *src, int stride) +; void ff_pred8x8_vertical(pixel *src, int stride) ;----------------------------------------------------------------------------- INIT_XMM sse2 cglobal pred8x8_vertical_10, 2, 2 @@ -319,7 +303,7 @@ cglobal pred8x8_vertical_10, 2, 2 RET ;----------------------------------------------------------------------------- -; void pred8x8_horizontal(pixel *src, int stride) +; void ff_pred8x8_horizontal(pixel *src, int stride) ;----------------------------------------------------------------------------- INIT_XMM sse2 cglobal pred8x8_horizontal_10, 2, 3 @@ -339,7 +323,7 @@ cglobal pred8x8_horizontal_10, 2, 3 REP_RET ;----------------------------------------------------------------------------- -; void predict_8x8_dc(pixel *src, int stride) +; void ff_predict_8x8_dc(pixel *src, int stride) ;----------------------------------------------------------------------------- %macro MOV8 2-3 ; sort of a hack, but it works @@ -426,7 +410,7 @@ INIT_XMM sse2 PRED8x8_DC pshuflw ;----------------------------------------------------------------------------- -; void pred8x8_top_dc(pixel *src, int stride) +; void ff_pred8x8_top_dc(pixel *src, int stride) ;----------------------------------------------------------------------------- INIT_XMM sse2 cglobal pred8x8_top_dc_10, 2, 4 @@ -453,7 +437,7 @@ cglobal pred8x8_top_dc_10, 2, 4 RET ;----------------------------------------------------------------------------- -; void pred8x8_plane(pixel *src, int stride) +; void ff_pred8x8_plane(pixel *src, int stride) ;----------------------------------------------------------------------------- INIT_XMM sse2 cglobal pred8x8_plane_10, 2, 7, 7 @@ -516,7 +500,8 @@ cglobal pred8x8_plane_10, 2, 7, 7 ;----------------------------------------------------------------------------- -; void pred8x8l_128_dc(pixel *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_128_dc(pixel *src, int has_topleft, int has_topright, +; int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_128_DC 0 cglobal pred8x8l_128_dc_10, 4, 4 @@ -540,7 +525,8 @@ INIT_XMM sse2 PRED8x8L_128_DC ;----------------------------------------------------------------------------- -; void pred8x8l_top_dc(pixel *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_top_dc(pixel *src, int has_topleft, int has_topright, +; int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_TOP_DC 0 cglobal pred8x8l_top_dc_10, 4, 4, 6 @@ -578,9 +564,9 @@ INIT_XMM avx PRED8x8L_TOP_DC %endif -;----------------------------------------------------------------------------- -;void pred8x8l_dc(pixel *src, int has_topleft, int has_topright, int stride) -;----------------------------------------------------------------------------- +;------------------------------------------------------------------------------- +; void ff_pred8x8l_dc(pixel *src, int has_topleft, int has_topright, int stride) +;------------------------------------------------------------------------------- ;TODO: see if scalar is faster %macro PRED8x8L_DC 0 cglobal pred8x8l_dc_10, 4, 6, 6 @@ -638,7 +624,8 @@ PRED8x8L_DC %endif ;----------------------------------------------------------------------------- -; void pred8x8l_vertical(pixel *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_vertical(pixel *src, int has_topleft, int has_topright, +; int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_VERTICAL 0 cglobal pred8x8l_vertical_10, 4, 4, 6 @@ -673,7 +660,8 @@ PRED8x8L_VERTICAL %endif ;----------------------------------------------------------------------------- -; void pred8x8l_horizontal(uint8_t *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_horizontal(uint8_t *src, int has_topleft, int has_topright, +; int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_HORIZONTAL 0 cglobal pred8x8l_horizontal_10, 4, 4, 5 @@ -729,7 +717,8 @@ PRED8x8L_HORIZONTAL %endif ;----------------------------------------------------------------------------- -;void pred8x8l_down_left(pixel *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_down_left(pixel *src, int has_topleft, int has_topright, +; int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_DOWN_LEFT 0 cglobal pred8x8l_down_left_10, 4, 4, 7 @@ -797,7 +786,8 @@ PRED8x8L_DOWN_LEFT %endif ;----------------------------------------------------------------------------- -;void pred8x8l_down_right(pixel *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_down_right(pixel *src, int has_topleft, int has_topright, +; int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_DOWN_RIGHT 0 ; standard forbids this when has_topleft is false @@ -871,7 +861,8 @@ PRED8x8L_DOWN_RIGHT %endif ;----------------------------------------------------------------------------- -; void pred8x8l_vertical_right(pixel *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_vertical_right(pixel *src, int has_topleft, +; int has_topright, int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_VERTICAL_RIGHT 0 ; likewise with 8x8l_down_right @@ -941,7 +932,8 @@ PRED8x8L_VERTICAL_RIGHT %endif ;----------------------------------------------------------------------------- -; void pred8x8l_horizontal_up(pixel *src, int has_topleft, int has_topright, int stride) +; void ff_pred8x8l_horizontal_up(pixel *src, int has_topleft, +; int has_topright, int stride) ;----------------------------------------------------------------------------- %macro PRED8x8L_HORIZONTAL_UP 0 cglobal pred8x8l_horizontal_up_10, 4, 4, 6 @@ -1003,7 +995,7 @@ PRED8x8L_HORIZONTAL_UP ;----------------------------------------------------------------------------- -; void pred16x16_vertical(pixel *src, int stride) +; void ff_pred16x16_vertical(pixel *src, int stride) ;----------------------------------------------------------------------------- %macro MOV16 3-5 mova [%1+ 0], %2 @@ -1039,7 +1031,7 @@ INIT_XMM sse2 PRED16x16_VERTICAL ;----------------------------------------------------------------------------- -; void pred16x16_horizontal(pixel *src, int stride) +; void ff_pred16x16_horizontal(pixel *src, int stride) ;----------------------------------------------------------------------------- %macro PRED16x16_HORIZONTAL 0 cglobal pred16x16_horizontal_10, 2, 3 @@ -1063,7 +1055,7 @@ INIT_XMM sse2 PRED16x16_HORIZONTAL ;----------------------------------------------------------------------------- -; void pred16x16_dc(pixel *src, int stride) +; void ff_pred16x16_dc(pixel *src, int stride) ;----------------------------------------------------------------------------- %macro PRED16x16_DC 0 cglobal pred16x16_dc_10, 2, 6 @@ -1109,7 +1101,7 @@ INIT_XMM sse2 PRED16x16_DC ;----------------------------------------------------------------------------- -; void pred16x16_top_dc(pixel *src, int stride) +; void ff_pred16x16_top_dc(pixel *src, int stride) ;----------------------------------------------------------------------------- %macro PRED16x16_TOP_DC 0 cglobal pred16x16_top_dc_10, 2, 3 @@ -1141,7 +1133,7 @@ INIT_XMM sse2 PRED16x16_TOP_DC ;----------------------------------------------------------------------------- -; void pred16x16_left_dc(pixel *src, int stride) +; void ff_pred16x16_left_dc(pixel *src, int stride) ;----------------------------------------------------------------------------- %macro PRED16x16_LEFT_DC 0 cglobal pred16x16_left_dc_10, 2, 6 @@ -1178,7 +1170,7 @@ INIT_XMM sse2 PRED16x16_LEFT_DC ;----------------------------------------------------------------------------- -; void pred16x16_128_dc(pixel *src, int stride) +; void ff_pred16x16_128_dc(pixel *src, int stride) ;----------------------------------------------------------------------------- %macro PRED16x16_128_DC 0 cglobal pred16x16_128_dc_10, 2,3 diff --git a/libavcodec/x86/h264_intrapred_init.c b/libavcodec/x86/h264_intrapred_init.c index 172415393..528b92e49 100644 --- a/libavcodec/x86/h264_intrapred_init.c +++ b/libavcodec/x86/h264_intrapred_init.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Jason Garrett-Glaser + * Copyright (c) 2010 Fiona Glaser * * This file is part of FFmpeg. * @@ -195,7 +195,7 @@ av_cold void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, h->pred8x8 [VERT_PRED8x8 ] = ff_pred8x8_vertical_8_mmx; h->pred8x8 [HOR_PRED8x8 ] = ff_pred8x8_horizontal_8_mmx; } - if (codec_id == AV_CODEC_ID_VP8) { + if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) { h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_tm_vp8_8_mmx; h->pred8x8 [PLANE_PRED8x8 ] = ff_pred8x8_tm_vp8_8_mmx; h->pred4x4 [TM_VP8_PRED ] = ff_pred4x4_tm_vp8_8_mmx; @@ -231,7 +231,8 @@ av_cold void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, h->pred4x4 [VERT_RIGHT_PRED ] = ff_pred4x4_vertical_right_8_mmxext; h->pred4x4 [HOR_DOWN_PRED ] = ff_pred4x4_horizontal_down_8_mmxext; h->pred4x4 [DC_PRED ] = ff_pred4x4_dc_8_mmxext; - if (codec_id == AV_CODEC_ID_VP8 || codec_id == AV_CODEC_ID_H264) { + if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8 || + codec_id == AV_CODEC_ID_H264) { h->pred4x4 [DIAG_DOWN_LEFT_PRED] = ff_pred4x4_down_left_8_mmxext; } if (codec_id == AV_CODEC_ID_SVQ3 || codec_id == AV_CODEC_ID_H264) { @@ -246,7 +247,7 @@ av_cold void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, h->pred8x8[DC_PRED8x8 ] = ff_pred8x8_dc_8_mmxext; } } - if (codec_id == AV_CODEC_ID_VP8) { + if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) { h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_tm_vp8_8_mmxext; h->pred8x8 [DC_PRED8x8 ] = ff_pred8x8_dc_rv40_8_mmxext; h->pred8x8 [PLANE_PRED8x8 ] = ff_pred8x8_tm_vp8_8_mmxext; @@ -276,7 +277,7 @@ av_cold void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, h->pred8x8l [VERT_RIGHT_PRED ] = ff_pred8x8l_vertical_right_8_sse2; h->pred8x8l [VERT_LEFT_PRED ] = ff_pred8x8l_vertical_left_8_sse2; h->pred8x8l [HOR_DOWN_PRED ] = ff_pred8x8l_horizontal_down_8_sse2; - if (codec_id == AV_CODEC_ID_VP8) { + if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) { h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_tm_vp8_8_sse2; h->pred8x8 [PLANE_PRED8x8 ] = ff_pred8x8_tm_vp8_8_sse2; } else { @@ -307,7 +308,7 @@ av_cold void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, h->pred8x8l [VERT_LEFT_PRED ] = ff_pred8x8l_vertical_left_8_ssse3; h->pred8x8l [HOR_UP_PRED ] = ff_pred8x8l_horizontal_up_8_ssse3; h->pred8x8l [HOR_DOWN_PRED ] = ff_pred8x8l_horizontal_down_8_ssse3; - if (codec_id == AV_CODEC_ID_VP8) { + if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) { h->pred8x8 [PLANE_PRED8x8 ] = ff_pred8x8_tm_vp8_8_ssse3; h->pred4x4 [TM_VP8_PRED ] = ff_pred4x4_tm_vp8_8_ssse3; } else { diff --git a/libavcodec/x86/h264_qpel.c b/libavcodec/x86/h264_qpel.c index fd6068ffb..85a0f6ce6 100644 --- a/libavcodec/x86/h264_qpel.c +++ b/libavcodec/x86/h264_qpel.c @@ -25,11 +25,12 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/h264qpel.h" #include "libavcodec/mpegvideo.h" -#include "dsputil_x86.h" +#include "libavcodec/pixels.h" +#include "fpel.h" #if HAVE_YASM -void ff_put_pixels4_mmxext(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); +void ff_put_pixels4_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); void ff_avg_pixels4_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_put_pixels4_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, @@ -48,9 +49,9 @@ void ff_avg_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, #define ff_avg_pixels8_l2_sse2 ff_avg_pixels8_l2_mmxext #define ff_put_pixels16_l2_sse2 ff_put_pixels16_l2_mmxext #define ff_avg_pixels16_l2_sse2 ff_avg_pixels16_l2_mmxext - -PIXELS16(static, ff_avg, , , _mmxext) -PIXELS16(static, ff_put, , , _mmxext) +#define ff_put_pixels16_mmxext ff_put_pixels16_mmx +#define ff_put_pixels8_mmxext ff_put_pixels8_mmx +#define ff_put_pixels4_mmxext ff_put_pixels4_mmx #define DEF_QPEL(OPNAME)\ void ff_ ## OPNAME ## _h264_qpel4_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, int dstStride, int srcStride);\ @@ -496,7 +497,7 @@ QPEL16_OP(mc31, MMX)\ QPEL16_OP(mc32, MMX)\ QPEL16_OP(mc33, MMX) -#if ARCH_X86_32 && HAVE_YASM && CONFIG_H264QPEL // ARCH_X86_64 implies SSE2+ +#if ARCH_X86_32 // ARCH_X86_64 implies SSE2+ QPEL16(mmxext) #endif diff --git a/libavcodec/x86/h264_qpel_10bit.asm b/libavcodec/x86/h264_qpel_10bit.asm index 456187140..d65660dfb 100644 --- a/libavcodec/x86/h264_qpel_10bit.asm +++ b/libavcodec/x86/h264_qpel_10bit.asm @@ -28,7 +28,7 @@ SECTION_RODATA 32 cextern pw_16 cextern pw_1 -cextern pb_0 +pb_0: times 32 db 0 ; we do not use cextern here as old llvm-gcc fails to align it correctly pw_pixel_max: times 8 dw ((1 << 10)-1) @@ -167,7 +167,7 @@ stub_%1_h264_qpel%3_%2_10 %+ SUFFIX: %endmacro ;----------------------------------------------------------------------------- -; void h264_qpel_mc00(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc00(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro COPY4 0 movu m0, [r1 ] @@ -221,7 +221,7 @@ MC00 put MC00 avg ;----------------------------------------------------------------------------- -; void h264_qpel_mc20(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc20(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro MC_CACHE 1 %define OP_MOV mova @@ -305,7 +305,7 @@ cglobal_mc %1, mc20, %2, 3,4,9 MC_CACHE MC20 ;----------------------------------------------------------------------------- -; void h264_qpel_mc30(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc30(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro MC30 2 cglobal_mc %1, mc30, %2, 3,5,9 @@ -316,7 +316,7 @@ cglobal_mc %1, mc30, %2, 3,5,9 MC_CACHE MC30 ;----------------------------------------------------------------------------- -; void h264_qpel_mc10(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc10(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro MC10 2 cglobal_mc %1, mc10, %2, 3,5,9 @@ -383,7 +383,7 @@ cglobal_mc %1, mc10, %2, 3,5,9 MC_CACHE MC10 ;----------------------------------------------------------------------------- -; void h264_qpel_mc02(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc02(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro V_FILT 10 v_filt%9_%10_10 @@ -432,7 +432,7 @@ cglobal_mc %1, mc02, %2, 3,4,8 MC MC02 ;----------------------------------------------------------------------------- -; void h264_qpel_mc01(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc01(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro MC01 2 cglobal_mc %1, mc01, %2, 3,5,8 @@ -458,7 +458,7 @@ cglobal_mc %1, mc01, %2, 3,5,8 MC MC01 ;----------------------------------------------------------------------------- -; void h264_qpel_mc03(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc03(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro MC03 2 cglobal_mc %1, mc03, %2, 3,5,8 @@ -469,7 +469,7 @@ cglobal_mc %1, mc03, %2, 3,5,8 MC MC03 ;----------------------------------------------------------------------------- -; void h264_qpel_mc11(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc11(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro H_FILT_AVG 2-3 h_filt%1_%2_10: @@ -551,7 +551,7 @@ cglobal_mc %1, mc11, %2, 3,6,8 MC MC11 ;----------------------------------------------------------------------------- -; void h264_qpel_mc31(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc31(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro MC31 2 cglobal_mc %1, mc31, %2, 3,6,8 @@ -563,7 +563,7 @@ cglobal_mc %1, mc31, %2, 3,6,8 MC MC31 ;----------------------------------------------------------------------------- -; void h264_qpel_mc13(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc13(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro MC13 2 cglobal_mc %1, mc13, %2, 3,7,12 @@ -574,7 +574,7 @@ cglobal_mc %1, mc13, %2, 3,7,12 MC MC13 ;----------------------------------------------------------------------------- -; void h264_qpel_mc33(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc33(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro MC33 2 cglobal_mc %1, mc33, %2, 3,6,8 @@ -586,7 +586,7 @@ cglobal_mc %1, mc33, %2, 3,6,8 MC MC33 ;----------------------------------------------------------------------------- -; void h264_qpel_mc22(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc22(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro FILT_H2 3 psubw %1, %2 ; a-b @@ -757,7 +757,7 @@ cglobal_mc %1, mc22, %2, 3,7,12 MC MC22 ;----------------------------------------------------------------------------- -; void h264_qpel_mc12(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc12(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro MC12 2 cglobal_mc %1, mc12, %2, 3,7,12 @@ -802,7 +802,7 @@ cglobal_mc %1, mc12, %2, 3,7,12 MC MC12 ;----------------------------------------------------------------------------- -; void h264_qpel_mc32(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc32(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro MC32 2 cglobal_mc %1, mc32, %2, 3,7,12 @@ -820,7 +820,7 @@ cglobal_mc %1, mc32, %2, 3,7,12 MC MC32 ;----------------------------------------------------------------------------- -; void h264_qpel_mc21(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc21(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro H_NRD 1 put_h%1_10: @@ -873,7 +873,7 @@ cglobal_mc %1, mc21, %2, 3,7,12 MC MC21 ;----------------------------------------------------------------------------- -; void h264_qpel_mc23(uint8_t *dst, uint8_t *src, int stride) +; void ff_h264_qpel_mc23(uint8_t *dst, uint8_t *src, int stride) ;----------------------------------------------------------------------------- %macro MC23 2 cglobal_mc %1, mc23, %2, 3,7,12 diff --git a/libavcodec/x86/h264_weight.asm b/libavcodec/x86/h264_weight.asm index 4759a063a..b4fb9db30 100644 --- a/libavcodec/x86/h264_weight.asm +++ b/libavcodec/x86/h264_weight.asm @@ -28,12 +28,12 @@ SECTION .text ;----------------------------------------------------------------------------- ; biweight pred: ; -; void h264_biweight_16_sse2(uint8_t *dst, uint8_t *src, int stride, -; int height, int log2_denom, int weightd, -; int weights, int offset); +; void ff_h264_biweight_16_sse2(uint8_t *dst, uint8_t *src, int stride, +; int height, int log2_denom, int weightd, +; int weights, int offset); ; and -; void h264_weight_16_sse2(uint8_t *dst, int stride, int height, -; int log2_denom, int weight, int offset); +; void ff_h264_weight_16_sse2(uint8_t *dst, int stride, int height, +; int log2_denom, int weight, int offset); ;----------------------------------------------------------------------------- %macro WEIGHT_SETUP 0 diff --git a/libavcodec/x86/h264_weight_10bit.asm b/libavcodec/x86/h264_weight_10bit.asm index b7845fd74..5d9496224 100644 --- a/libavcodec/x86/h264_weight_10bit.asm +++ b/libavcodec/x86/h264_weight_10bit.asm @@ -35,8 +35,8 @@ cextern pw_1 SECTION .text ;----------------------------------------------------------------------------- -; void h264_weight(uint8_t *dst, int stride, int height, int log2_denom, -; int weight, int offset); +; void ff_h264_weight_16_10(uint8_t *dst, int stride, int height, +; int log2_denom, int weight, int offset); ;----------------------------------------------------------------------------- %macro WEIGHT_PROLOGUE 0 .prologue: @@ -151,8 +151,9 @@ WEIGHT_FUNC_HALF_MM ;----------------------------------------------------------------------------- -; void h264_biweight(uint8_t *dst, uint8_t *src, int stride, int height, -; int log2_denom, int weightd, int weights, int offset); +; void ff_h264_biweight_16_10(uint8_t *dst, uint8_t *src, int stride, +; int height, int log2_denom, int weightd, +; int weights, int offset); ;----------------------------------------------------------------------------- %if ARCH_X86_32 DECLARE_REG_TMP 3 diff --git a/libavcodec/x86/h264chroma_init.c b/libavcodec/x86/h264chroma_init.c index 3d8d5b0fe..e08af2759 100644 --- a/libavcodec/x86/h264chroma_init.c +++ b/libavcodec/x86/h264chroma_init.c @@ -69,7 +69,6 @@ CHROMA_MC(avg, 8, 10, avx) av_cold void ff_h264chroma_init_x86(H264ChromaContext *c, int bit_depth) { -#if HAVE_YASM int high_bit_depth = bit_depth > 8; int cpu_flags = av_get_cpu_flags(); @@ -115,5 +114,4 @@ av_cold void ff_h264chroma_init_x86(H264ChromaContext *c, int bit_depth) c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_10_avx; c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_10_avx; } -#endif } diff --git a/libavcodec/x86/h264dsp_init.c b/libavcodec/x86/h264dsp_init.c index ae449e7e5..35db20014 100644 --- a/libavcodec/x86/h264dsp_init.c +++ b/libavcodec/x86/h264dsp_init.c @@ -23,7 +23,6 @@ #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/h264dsp.h" -#include "dsputil_x86.h" /***********************************/ /* IDCT */ @@ -214,7 +213,7 @@ av_cold void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth, #if HAVE_YASM int cpu_flags = av_get_cpu_flags(); - if (chroma_format_idc <= 1 && EXTERNAL_MMXEXT(cpu_flags)) + if (EXTERNAL_MMXEXT(cpu_flags) && chroma_format_idc <= 1) c->h264_loop_filter_strength = ff_h264_loop_filter_strength_mmxext; if (bit_depth == 8) { diff --git a/libavcodec/x86/hevc_deblock.asm b/libavcodec/x86/hevc_deblock.asm new file mode 100644 index 000000000..c035668ed --- /dev/null +++ b/libavcodec/x86/hevc_deblock.asm @@ -0,0 +1,837 @@ +;***************************************************************************** +;* SSE2-optimized HEVC deblocking code +;***************************************************************************** +;* Copyright (C) 2013 VTT +;* +;* Authors: Seppo Tomperi +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +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 + +SECTION .text +INIT_XMM sse2 + +; expands to [base],...,[base+7*stride] +%define PASS8ROWS(base, base3, stride, stride3) \ + [base], [base+stride], [base+stride*2], [base3], \ + [base3+stride], [base3+stride*2], [base3+stride3], [base3+stride*4] + +; in: 8 rows of 4 bytes in %4..%11 +; out: 4 rows of 8 words in m0..m3 +%macro TRANSPOSE4x8B_LOAD 8 + movd m0, %1 + movd m2, %2 + movd m1, %3 + movd m3, %4 + + punpcklbw m0, m2 + punpcklbw m1, m3 + punpcklwd m0, m1 + + movd m4, %5 + movd m6, %6 + movd m5, %7 + movd m3, %8 + + punpcklbw m4, m6 + punpcklbw m5, m3 + punpcklwd m4, m5 + + punpckhdq m2, m0, m4 + punpckldq m0, m4 + + pxor m5, m5 + punpckhbw m1, m0, m5 + punpcklbw m0, m5 + punpckhbw m3, m2, m5 + punpcklbw m2, m5 +%endmacro + +; in: 4 rows of 8 words in m0..m3 +; out: 8 rows of 4 bytes in %1..%8 +%macro TRANSPOSE8x4B_STORE 8 + packuswb m0, m0 + packuswb m1, m1 + packuswb m2, m2 + packuswb m3, m3 + + punpcklbw m0, m1 + punpcklbw m2, m3 + + punpckhwd m6, m0, m2 + punpcklwd m0, m2 + + movd %1, m0 + pshufd m0, m0, 0x39 + movd %2, m0 + pshufd m0, m0, 0x39 + movd %3, m0 + pshufd m0, m0, 0x39 + movd %4, m0 + + movd %5, m6 + pshufd m6, m6, 0x39 + movd %6, m6 + pshufd m6, m6, 0x39 + movd %7, m6 + pshufd m6, m6, 0x39 + movd %8, m6 +%endmacro + +; in: 8 rows of 4 words in %4..%11 +; out: 4 rows of 8 words in m0..m3 +%macro TRANSPOSE4x8W_LOAD 8 + movq m0, %1 + movq m2, %2 + movq m1, %3 + movq m3, %4 + + punpcklwd m0, m2 + punpcklwd m1, m3 + punpckhdq m2, m0, m1 + punpckldq m0, m1 + + movq m4, %5 + movq m6, %6 + movq m5, %7 + movq m3, %8 + + punpcklwd m4, m6 + punpcklwd m5, m3 + punpckhdq m6, m4, m5 + punpckldq m4, m5 + + punpckhqdq m1, m0, m4 + punpcklqdq m0, m4 + punpckhqdq m3, m2, m6 + punpcklqdq m2, m6 + +%endmacro + +; in: 4 rows of 8 words in m0..m3 +; out: 8 rows of 4 words in %1..%8 +%macro TRANSPOSE8x4W_STORE 8 + pxor m5, m5; zeros reg + CLIPW m0, m5, [pw_pixel_max] + CLIPW m1, m5, [pw_pixel_max] + CLIPW m2, m5, [pw_pixel_max] + CLIPW m3, m5, [pw_pixel_max] + + punpckhwd m4, m0, m1 + punpcklwd m0, m1 + punpckhwd m5, m2, m3 + punpcklwd m2, m3 + punpckhdq m6, m0, m2 + punpckldq m0, m2 + + movq %1, m0 + movhps %2, m0 + movq %3, m6 + movhps %4, m6 + + punpckhdq m6, m4, m5 + punpckldq m4, m5 + + movq %5, m4 + movhps %6, m4 + movq %7, m6 + movhps %8, m6 +%endmacro + +; in: 8 rows of 8 bytes in %1..%8 +; out: 8 rows of 8 words in m0..m7 +%macro TRANSPOSE8x8B_LOAD 8 + movq m7, %1 + movq m2, %2 + movq m1, %3 + movq m3, %4 + + punpcklbw m7, m2 + punpcklbw m1, m3 + punpcklwd m3, m7, m1 + punpckhwd m7, m1 + + movq m4, %5 + movq m6, %6 + movq m5, %7 + movq m15, %8 + + punpcklbw m4, m6 + punpcklbw m5, m15 + punpcklwd m9, m4, m5 + punpckhwd m4, m5 + + punpckldq m1, m3, m9; 0, 1 + punpckhdq m3, m9; 2, 3 + + punpckldq m5, m7, m4; 4, 5 + punpckhdq m7, m4; 6, 7 + + pxor m13, m13 + + punpcklbw m0, m1, m13; 0 in 16 bit + punpckhbw m1, m13; 1 in 16 bit + + punpcklbw m2, m3, m13; 2 + punpckhbw m3, m13; 3 + + punpcklbw m4, m5, m13; 4 + punpckhbw m5, m13; 5 + + punpcklbw m6, m7, m13; 6 + punpckhbw m7, m13; 7 +%endmacro + + +; in: 8 rows of 8 words in m0..m8 +; out: 8 rows of 8 bytes in %1..%8 +%macro TRANSPOSE8x8B_STORE 8 + packuswb m0, m0 + packuswb m1, m1 + packuswb m2, m2 + packuswb m3, m3 + packuswb m4, m4 + packuswb m5, m5 + packuswb m6, m6 + packuswb m7, m7 + + punpcklbw m0, m1 + punpcklbw m2, m3 + + punpckhwd m8, m0, m2 + punpcklwd m0, m2 + + punpcklbw m4, m5 + punpcklbw m6, m7 + + punpckhwd m9, m4, m6 + punpcklwd m4, m6 + + punpckhdq m10, m0, m4; 2, 3 + punpckldq m0, m4; 0, 1 + + punpckldq m11, m8, m9; 4, 5 + punpckhdq m8, m9; 6, 7 + movq %1, m0 + movhps %2, m0 + movq %3, m10 + movhps %4, m10 + movq %5, m11 + movhps %6, m11 + movq %7, m8 + movhps %8, m8 +%endmacro + +; in: 8 rows of 8 words in %1..%8 +; out: 8 rows of 8 words in m0..m7 +%macro TRANSPOSE8x8W_LOAD 8 + movdqu m0, %1 + movdqu m1, %2 + movdqu m2, %3 + movdqu m3, %4 + movdqu m4, %5 + movdqu m5, %6 + movdqu m6, %7 + movdqu m7, %8 + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, 8 +%endmacro + +; in: 8 rows of 8 words in m0..m8 +; out: 8 rows of 8 words in %1..%8 +%macro TRANSPOSE8x8W_STORE 8 + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, 8 + + pxor m8, m8 + CLIPW m0, m8, [pw_pixel_max] + CLIPW m1, m8, [pw_pixel_max] + CLIPW m2, m8, [pw_pixel_max] + CLIPW m3, m8, [pw_pixel_max] + CLIPW m4, m8, [pw_pixel_max] + CLIPW m5, m8, [pw_pixel_max] + CLIPW m6, m8, [pw_pixel_max] + CLIPW m7, m8, [pw_pixel_max] + + movdqu %1, m0 + movdqu %2, m1 + movdqu %3, m2 + movdqu %4, m3 + movdqu %5, m4 + movdqu %6, m5 + movdqu %7, m6 + movdqu %8, m7 +%endmacro + + +; in: %2 clobbered +; out: %1 +; mask in m11 +; clobbers m10 +%macro MASKED_COPY 2 + pand %2, m11 ; and mask + pandn m10, m11, %1; and -mask + por %2, m10 + mova %1, %2 +%endmacro + +; in: %2 clobbered +; out: %1 +; mask in %3, will be clobbered +%macro MASKED_COPY2 3 + pand %2, %3 ; and mask + pandn %3, %1; and -mask + por %2, %3 + mova %1, %2 +%endmacro + +ALIGN 16 +; input in m0 ... m3 and tcs in tc (r2). Output in m1 and m2 +%macro CHROMA_DEBLOCK_BODY 1 + psubw m4, m2, m1; q0 - p0 + psubw m5, m0, m3; p1 - q1 + psllw m4, 2; << 2 + paddw m5, m4; + + ;tc calculations + movd m6, [tcq]; tc0 + punpcklwd m6, m6 + movd m4, [tcq+4]; tc1 + punpcklwd m4, m4 + shufps m6, m4, 0; tc0, tc1 + pmullw m4, m6, [pw_m1]; -tc0, -tc1 + ;end tc calculations + + paddw m5, [pw_4]; +4 + psraw m5, 3; >> 3 + + psllw m4, %1-8; << (BIT_DEPTH - 8) + psllw m6, %1-8; << (BIT_DEPTH - 8) + pmaxsw m5, m4 + pminsw m5, m6 + paddw m1, m5; p0 + delta0 + psubw m2, m5; q0 - delta0 +%endmacro + +; input in m0 ... m7, betas in r2 tcs in r3. Output in m1...m6 +%macro LUMA_DEBLOCK_BODY 2 + psllw m9, m2, 1; *2 + psubw m10, m1, m9 + paddw m10, m3 + ABS1 m10, m11 ; 0dp0, 0dp3 , 1dp0, 1dp3 + + psllw m9, m5, 1; *2 + psubw m11, m6, m9 + paddw m11, m4 + ABS1 m11, m13 ; 0dq0, 0dq3 , 1dq0, 1dq3 + + ;beta calculations + mov r11, [betaq]; + shl r11, %1 - 8 + movd m13, r11d; beta0 + add betaq, 4; + punpcklwd m13, m13 + mov r12, [betaq]; + shl r12, %1 - 8 + movd m14, r12d; beta1 + punpcklwd m14, m14 + pshufd m13, m14, 0; beta0, beta1 + ;end beta calculations + + paddw m9, m10, m11; 0d0, 0d3 , 1d0, 1d3 + + pshufhw m14, m9, 0x0f ;0b00001111; 0d3 0d3 0d0 0d0 in high + pshuflw m14, m14, 0x0f ;0b00001111; 1d3 1d3 1d0 1d0 in low + + pshufhw m9, m9, 0xf0 ;0b11110000; 0d0 0d0 0d3 0d3 + pshuflw m9, m9, 0xf0 ;0b11110000; 1d0 1d0 1d3 1d3 + + paddw m14, m9; 0d0+0d3, 1d0+1d3 + + ;compare + pcmpgtw m15, m13, m14; beta0, beta1 + movmskps r13, m15 ;filtering mask 0d0 + 0d3 < beta0 (bit 2 or 3) , 1d0 + 1d3 < beta1 (bit 0 or 1) + cmp r13, 0 + je .bypassluma + + ;weak / strong decision compare to beta_2 + psraw m15, m13, 2; beta >> 2 + psllw m8, m9, 1; + pcmpgtw m15, m8; (d0 << 1) < beta_2, (d3 << 1) < beta_2 + movmskps r14, m15; + ;end weak / strong decision + + ; weak filter nd_p/q calculation + pshufd m8, m10, 0x31 + psrld m8, 16 + paddw m8, m10 + movd r7d, m8 + and r7, 0xffff; 1dp0 + 1dp3 + pshufd m8, m8, 0x4E + movd r8d, m8 + and r8, 0xffff; 0dp0 + 0dp3 + + pshufd m8, m11, 0x31 + psrld m8, 16 + paddw m8, m11 + movd r9d, m8 + and r9, 0xffff; 1dq0 + 1dq3 + pshufd m8, m8, 0x4E + movd r10d, m8 + and r10, 0xffff; 0dq0 + 0dq3 + ; end calc for weak filter + + ; filtering mask + mov r2, r13 + shr r2, 3 + movd m15, r2d + and r13, 1 + movd m11, r13d + shufps m11, m15, 0 + shl r2, 1 + or r13, r2 + + pcmpeqd m11, [pd_1]; filtering mask + + ;decide between strong and weak filtering + ;tc25 calculations + mov r2d, [tcq]; + shl r2, %1 - 8 + movd m8, r2d; tc0 + add tcq, 4; + mov r3d, [tcq]; + shl r3, %1 - 8 + movd m9, r3d; tc1 + add r2d, r3d; tc0 + tc1 + jz .bypassluma + punpcklwd m8, m8 + punpcklwd m9, m9 + shufps m8, m9, 0; tc0, tc1 + mova m9, m8 + psllw m8, 2; tc << 2 + pavgw m8, m9; tc25 = ((tc * 5 + 1) >> 1) + ;end tc25 calculations + + ;----beta_3 comparison----- + psubw m12, m0, m3; p3 - p0 + ABS1 m12, m14; abs(p3 - p0) + + psubw m15, m7, m4; q3 - q0 + ABS1 m15, m14; abs(q3 - q0) + + paddw m12, m15; abs(p3 - p0) + abs(q3 - q0) + + pshufhw m12, m12, 0xf0 ;0b11110000; + pshuflw m12, m12, 0xf0 ;0b11110000; + + psraw m13, 3; beta >> 3 + pcmpgtw m13, m12; + movmskps r2, m13; + and r14, r2; strong mask , beta_2 and beta_3 comparisons + ;----beta_3 comparison end----- + ;----tc25 comparison--- + psubw m12, m3, m4; p0 - q0 + ABS1 m12, m14; abs(p0 - q0) + + pshufhw m12, m12, 0xf0 ;0b11110000; + pshuflw m12, m12, 0xf0 ;0b11110000; + + pcmpgtw m8, m12; tc25 comparisons + movmskps r2, m8; + and r14, r2; strong mask, beta_2, beta_3 and tc25 comparisons + ;----tc25 comparison end--- + mov r2, r14; + shr r2, 1; + and r14, r2; strong mask, bits 2 and 0 + + pmullw m14, m9, [pw_m2]; -tc * 2 + psllw m9, 1; tc * 2 + + and r14, 5; 0b101 + mov r2, r14; strong mask + shr r14, 2; + movd m12, r14d; store to xmm for mask generation + shl r14, 1 + and r2, 1 + movd m10, r2d; store to xmm for mask generation + or r14, r2; final strong mask, bits 1 and 0 + jz .weakfilter + + shufps m10, m12, 0 + pcmpeqd m10, [pd_1]; strong mask + + mova m13, [pw_4]; 4 in every cell + pand m11, m10; combine filtering mask and strong mask + paddw m12, m2, m3; p1 + p0 + paddw m12, m4; p1 + p0 + q0 + mova m10, m12; copy + psllw m12, 1; 2*p1 + 2*p0 + 2*q0 + paddw m12, m1; p2 + 2*p1 + 2*p0 + 2*q0 + paddw m12, m5; p2 + 2*p1 + 2*p0 + 2*q0 + q1 + paddw m12, m13; p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 + psraw m12, 3; ((p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4) >> 3) + psubw m12, m3; ((p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4) >> 3) - p0 + pmaxsw m12, m14 + pminsw m12, m9; av_clip( , -2 * tc, 2 * tc) + paddw m12, m3; p0' + + paddw m15, m1, m10; p2 + p1 + p0 + q0 + psrlw m13, 1; 2 in every cell + paddw m15, m13; p2 + p1 + p0 + q0 + 2 + psraw m15, 2; (p2 + p1 + p0 + q0 + 2) >> 2 + psubw m15, m2;((p2 + p1 + p0 + q0 + 2) >> 2) - p1 + pmaxsw m15, m14 + pminsw m15, m9; av_clip( , -2 * tc, 2 * tc) + paddw m15, m2; p1' + + paddw m8, m1, m0; p3 + p2 + psllw m8, 1; 2*p3 + 2*p2 + paddw m8, m1; 2*p3 + 3*p2 + paddw m8, m10; 2*p3 + 3*p2 + p1 + p0 + q0 + psllw m13, 1; 4 in every cell + paddw m8, m13; 2*p3 + 3*p2 + p1 + p0 + q0 + 4 + psraw m8, 3; (2*p3 + 3*p2 + p1 + p0 + q0 + 4) >> 3 + psubw m8, m1; ((2*p3 + 3*p2 + p1 + p0 + q0 + 4) >> 3) - p2 + pmaxsw m8, m14 + pminsw m8, m9; av_clip( , -2 * tc, 2 * tc) + paddw m8, m1; p2' + MASKED_COPY m1, m8 + + paddw m8, m3, m4; p0 + q0 + paddw m8, m5; p0 + q0 + q1 + psllw m8, 1; 2*p0 + 2*q0 + 2*q1 + paddw m8, m2; p1 + 2*p0 + 2*q0 + 2*q1 + paddw m8, m6; p1 + 2*p0 + 2*q0 + 2*q1 + q2 + paddw m8, m13; p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 + psraw m8, 3; (p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4) >>3 + psubw m8, m4; + pmaxsw m8, m14 + pminsw m8, m9; av_clip( , -2 * tc, 2 * tc) + paddw m8, m4; q0' + MASKED_COPY m2, m15 + + paddw m15, m3, m4; p0 + q0 + paddw m15, m5; p0 + q0 + q1 + mova m10, m15; + paddw m15, m6; p0 + q0 + q1 + q2 + psrlw m13, 1; 2 in every cell + paddw m15, m13; p0 + q0 + q1 + q2 + 2 + psraw m15, 2; (p0 + q0 + q1 + q2 + 2) >> 2 + psubw m15, m5; ((p0 + q0 + q1 + q2 + 2) >> 2) - q1 + pmaxsw m15, m14 + pminsw m15, m9; av_clip( , -2 * tc, 2 * tc) + paddw m15, m5; q1' + + paddw m13, m7; q3 + 2 + paddw m13, m6; q3 + q2 + 2 + psllw m13, 1; 2*q3 + 2*q2 + 4 + paddw m13, m6; 2*q3 + 3*q2 + 4 + paddw m13, m10; 2*q3 + 3*q2 + q1 + q0 + p0 + 4 + psraw m13, 3; (2*q3 + 3*q2 + q1 + q0 + p0 + 4) >> 3 + psubw m13, m6; ((2*q3 + 3*q2 + q1 + q0 + p0 + 4) >> 3) - q2 + pmaxsw m13, m14 + pminsw m13, m9; av_clip( , -2 * tc, 2 * tc) + paddw m13, m6; q2' + + MASKED_COPY m6, m13 + MASKED_COPY m5, m15 + MASKED_COPY m4, m8 + MASKED_COPY m3, m12 + +.weakfilter: + not r14; strong mask -> weak mask + and r14, r13; final weak filtering mask, bits 0 and 1 + jz .store + + ; weak filtering mask + mov r2, r14 + shr r2, 1 + movd m12, r2d + and r14, 1 + movd m11, r14d + shufps m11, m12, 0 + pcmpeqd m11, [pd_1]; filtering mask + + mov r13, r11; beta0 + shr r13, 1; + add r11, r13 + shr r11, 3; ((beta0+(beta0>>1))>>3)) + + mov r13, r12; beta1 + shr r13, 1; + add r12, r13 + shr r12, 3; ((beta1+(beta1>>1))>>3)) + + mova m13, [pw_8] + psubw m12, m4, m3 ; q0 - p0 + psllw m10, m12, 3; 8 * (q0 - p0) + paddw m12, m10 ; 9 * (q0 - p0) + + psubw m10, m5, m2 ; q1 - p1 + psllw m8, m10, 1; 2 * ( q1 - p1 ) + paddw m10, m8; 3 * ( q1 - p1 ) + psubw m12, m10; 9 * (q0 - p0) - 3 * ( q1 - p1 ) + paddw m12, m13; + 8 + psraw m12, 4; >> 4 , delta0 + PABSW m13, m12; abs(delta0) + + + psllw m10, m9, 2; 8 * tc + paddw m10, m9; 10 * tc + pcmpgtw m10, m13 + pand m11, m10 + + psraw m9, 1; tc * 2 -> tc + psraw m14, 1; -tc * 2 -> -tc + + pmaxsw m12, m14 + pminsw m12, m9; av_clip(delta0, -tc, tc) + + psraw m9, 1; tc -> tc / 2 + pmullw m14, m9, [pw_m1]; -tc / 2 + + pavgw m15, m1, m3; (p2 + p0 + 1) >> 1 + psubw m15, m2; ((p2 + p0 + 1) >> 1) - p1 + paddw m15, m12; ((p2 + p0 + 1) >> 1) - p1 + delta0 + psraw m15, 1; (((p2 + p0 + 1) >> 1) - p1 + delta0) >> 1 + pmaxsw m15, m14 + pminsw m15, m9; av_clip(deltap1, -tc/2, tc/2) + paddw m15, m2; p1' + + ;beta calculations + movd m10, r11d; beta0 + punpcklwd m10, m10 + movd m13, r12d; beta1 + punpcklwd m13, m13 + shufps m10, m13, 0; betax0, betax1 + + movd m13, r7d; 1dp0 + 1dp3 + movd m8, r8d; 0dp0 + 0dp3 + punpcklwd m8, m8 + punpcklwd m13, m13 + shufps m13, m8, 0; + pcmpgtw m8, m10, m13 + pand m8, m11 + ;end beta calculations + MASKED_COPY2 m2, m15, m8; write p1' + + pavgw m8, m6, m4; (q2 + q0 + 1) >> 1 + psubw m8, m5; ((q2 + q0 + 1) >> 1) - q1 + psubw m8, m12; ((q2 + q0 + 1) >> 1) - q1 - delta0) + psraw m8, 1; ((q2 + q0 + 1) >> 1) - q1 - delta0) >> 1 + pmaxsw m8, m14 + pminsw m8, m9; av_clip(deltaq1, -tc/2, tc/2) + paddw m8, m5; q1' + + movd m13, r9d; + movd m15, r10d; + punpcklwd m15, m15 + punpcklwd m13, m13 + shufps m13, m15, 0; dq0 + dq3 + + pcmpgtw m10, m13; compare to ((beta+(beta>>1))>>3) + pand m10, m11 + MASKED_COPY2 m5, m8, m10; write q1' + + paddw m15, m3, m12 ; p0 + delta0 + MASKED_COPY m3, m15 + + psubw m8, m4, m12 ; q0 - delta0 + MASKED_COPY m4, m8 +%endmacro + +INIT_XMM sse2 +;----------------------------------------------------------------------------- +; void ff_hevc_v_loop_filter_chroma(uint8_t *_pix, ptrdiff_t _stride, int *_tc, uint8_t *_no_p, uint8_t *_no_q) +;----------------------------------------------------------------------------- +cglobal hevc_v_loop_filter_chroma_8, 3, 5, 7, pix, stride, tc, pix0, r3stride + sub pixq, 2 + lea r3strideq, [3*strideq] + mov pix0q, pixq + add pixq, r3strideq + TRANSPOSE4x8B_LOAD PASS8ROWS(pix0q, pixq, strideq, r3strideq) + CHROMA_DEBLOCK_BODY 8 + TRANSPOSE8x4B_STORE PASS8ROWS(pix0q, pixq, strideq, r3strideq) + RET + +cglobal hevc_v_loop_filter_chroma_10, 3, 5, 7, pix, stride, tc, pix0, r3stride + sub pixq, 4 + lea r3strideq, [3*strideq] + mov pix0q, pixq + add pixq, r3strideq + TRANSPOSE4x8W_LOAD PASS8ROWS(pix0q, pixq, strideq, r3strideq) + CHROMA_DEBLOCK_BODY 10 + TRANSPOSE8x4W_STORE PASS8ROWS(pix0q, pixq, strideq, r3strideq) + RET + +;----------------------------------------------------------------------------- +; void ff_hevc_h_loop_filter_chroma(uint8_t *_pix, ptrdiff_t _stride, int *_tc, uint8_t *_no_p, uint8_t *_no_q +;----------------------------------------------------------------------------- +cglobal hevc_h_loop_filter_chroma_8, 3, 4, 7, pix, stride, tc, pix0 + mov pix0q, pixq + sub pix0q, strideq + sub pix0q, strideq + movq m0, [pix0q]; p1 + movq m1, [pix0q+strideq]; p0 + movq m2, [pixq]; q0 + movq m3, [pixq+strideq]; q1 + pxor m5, m5; zeros reg + punpcklbw m0, m5 + punpcklbw m1, m5 + punpcklbw m2, m5 + punpcklbw m3, m5 + CHROMA_DEBLOCK_BODY 8 + packuswb m1, m1 ; p0' packed in bytes on low quadword + packuswb m2, m2 ; q0' packed in bytes on low quadword + movq [pix0q+strideq], m1 + movq [pixq], m2 + RET + +cglobal hevc_h_loop_filter_chroma_10, 3, 4, 7, pix, stride, tc, pix0 + mov pix0q, pixq + sub pix0q, strideq + sub pix0q, strideq + movu m0, [pix0q]; p1 + movu m1, [pix0q+strideq]; p0 + movu m2, [pixq]; q0 + movu m3, [pixq+strideq]; q1 + CHROMA_DEBLOCK_BODY 10 + pxor m5, m5; zeros reg + CLIPW m1, m5, [pw_pixel_max] + CLIPW m2, m5, [pw_pixel_max] + movu [pix0q+strideq], m1 + movu [pixq], m2 + RET + +%if ARCH_X86_64 +%macro LOOP_FILTER_LUMA 0 +;----------------------------------------------------------------------------- +; void ff_hevc_v_loop_filter_luma(uint8_t *_pix, ptrdiff_t _stride, int *_beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); +;----------------------------------------------------------------------------- +cglobal hevc_v_loop_filter_luma_8, 4, 15, 16, pix, stride, beta, tc + sub r0, 4 + lea r5, [3*r1] + mov r6, r0 + add r0, r5 + TRANSPOSE8x8B_LOAD PASS8ROWS(r6, r0, r1, r5) + LUMA_DEBLOCK_BODY 8, v +.store: + TRANSPOSE8x8B_STORE PASS8ROWS(r6, r0, r1, r5) +.bypassluma: + RET + +cglobal hevc_v_loop_filter_luma_10, 4, 15, 16, pix, stride, beta, tc + sub pixq, 8 + lea r5, [3*strideq] + mov r6, pixq + add pixq, r5 + TRANSPOSE8x8W_LOAD PASS8ROWS(r6, pixq, strideq, r5) + LUMA_DEBLOCK_BODY 10, v +.store: + TRANSPOSE8x8W_STORE PASS8ROWS(r6, r0, r1, r5) +.bypassluma: + RET + +;----------------------------------------------------------------------------- +; void ff_hevc_h_loop_filter_luma(uint8_t *_pix, ptrdiff_t _stride, int *_beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); +;----------------------------------------------------------------------------- +cglobal hevc_h_loop_filter_luma_8, 4, 15, 16, pix, stride, beta, tc, count, pix0, src3stride + lea src3strideq, [3*strideq] + mov pix0q, pixq + sub pix0q, src3strideq + sub pix0q, strideq + movdqu m0, [pix0q]; p3 + movdqu m1, [pix0q+strideq]; p2 + movdqu m2, [pix0q+2*strideq]; p1 + movdqu m3, [pix0q+src3strideq]; p0 + movdqu m4, [pixq]; q0 + movdqu m5, [pixq+strideq]; q1 + movdqu m6, [pixq+2*strideq]; q2 + movdqu m7, [pixq+src3strideq]; q3 + pxor m8, m8 + punpcklbw m0, m8 + punpcklbw m1, m8 + punpcklbw m2, m8 + punpcklbw m3, m8 + punpcklbw m4, m8 + punpcklbw m5, m8 + punpcklbw m6, m8 + punpcklbw m7, m8 + LUMA_DEBLOCK_BODY 8, h +.store: + packuswb m1, m1; p2 + packuswb m2, m2; p1 + packuswb m3, m3; p0 + packuswb m4, m4; q0 + packuswb m5, m5; q1 + packuswb m6, m6; q2 + movq [r5+r1], m1; p2 + movq [r5+2*r1], m2; p1 + movq [r5+r6], m3; p0 + movq [r0], m4; q0 + movq [r0+r1], m5; q1 + movq [r0+2*r1], m6; q2 +.bypassluma: + RET + +cglobal hevc_h_loop_filter_luma_10, 4, 15, 16, pix, stride, beta, tc, count, pix0, src3stride + lea src3strideq, [3*strideq] + mov pix0q, pixq + sub pix0q, src3strideq + sub pix0q, strideq + movdqu m0, [pix0q]; p3 + movdqu m1, [pix0q+strideq]; p2 + movdqu m2, [pix0q+2*strideq]; p1 + movdqu m3, [pix0q+src3strideq]; p0 + movdqu m4, [pixq]; q0 + movdqu m5, [pixq+strideq]; q1 + movdqu m6, [pixq+2*strideq]; q2 + movdqu m7, [pixq+src3strideq]; q3 + LUMA_DEBLOCK_BODY 10, h +.store: + pxor m8, m8; zeros reg + CLIPW m1, m8, [pw_pixel_max] + CLIPW m2, m8, [pw_pixel_max] + CLIPW m3, m8, [pw_pixel_max] + CLIPW m4, m8, [pw_pixel_max] + CLIPW m5, m8, [pw_pixel_max] + CLIPW m6, m8, [pw_pixel_max] + movdqu [pix0q+strideq], m1; p2 + movdqu [pix0q+2*strideq], m2; p1 + movdqu [pix0q+src3strideq], m3; p0 + movdqu [pixq], m4; q0 + movdqu [pixq+strideq], m5; q1 + movdqu [pixq+2*strideq], m6; q2 +.bypassluma: + RET +%endmacro + +INIT_XMM sse2 +LOOP_FILTER_LUMA +INIT_XMM ssse3 +LOOP_FILTER_LUMA +%endif diff --git a/libavcodec/x86/hevc_idct.asm b/libavcodec/x86/hevc_idct.asm new file mode 100644 index 000000000..c97c82a8e --- /dev/null +++ b/libavcodec/x86/hevc_idct.asm @@ -0,0 +1,225 @@ +; /* +; * Provide SSE & MMX idct functions for HEVC decoding +; * Copyright (c) 2014 Pierre-Edouard LEPERE +; * +; * This file is part of FFmpeg. +; * +; * FFmpeg is free software; you can redistribute it and/or +; * modify it under the terms of the GNU Lesser General Public +; * License as published by the Free Software Foundation; either +; * version 2.1 of the License, or (at your option) any later version. +; * +; * FFmpeg is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; * Lesser General Public License for more details. +; * +; * You should have received a copy of the GNU Lesser General Public +; * License along with FFmpeg; if not, write to the Free Software +; * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +; */ +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA 32 +max_pixels_10: times 16 dw ((1 << 10)-1) +dc_add_10: times 4 dd ((1 << 14-10) + 1) + + +SECTION_TEXT 32 + +;the idct_dc_add macros and functions were largely inspired by x264 project's code in the h264_idct.asm file + +%macro DC_ADD_INIT 2 + add %1w, ((1 << 14-8) + 1) + sar %1w, (15-8) + movd m0, %1d + lea %1, [%2*3] + SPLATW m0, m0, 0 + pxor m1, m1 + psubw m1, m0 + packuswb m0, m0 + packuswb m1, m1 +%endmacro + +%macro DC_ADD_INIT_AVX2 2 + add %1w, ((1 << 14-8) + 1) + sar %1w, (15-8) + movd xm0, %1d + vpbroadcastw m0, xm0 ;SPLATW + lea %1, [%2*3] + pxor m1, m1 + psubw m1, m0 + packuswb m0, m0 + packuswb m1, m1 +%endmacro + +%macro DC_ADD_OP 4 + %1 m2, [%2 ] + %1 m3, [%2+%3 ] + %1 m4, [%2+%3*2] + %1 m5, [%2+%4 ] + paddusb m2, m0 + paddusb m3, m0 + paddusb m4, m0 + paddusb m5, m0 + psubusb m2, m1 + psubusb m3, m1 + psubusb m4, m1 + psubusb m5, m1 + %1 [%2 ], m2 + %1 [%2+%3 ], m3 + %1 [%2+%3*2], m4 + %1 [%2+%4 ], m5 +%endmacro + +INIT_MMX mmxext +; void ff_hevc_idct_dc_add_8_mmxext(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) +%if ARCH_X86_64 +cglobal hevc_idct4_dc_add_8, 3, 4, 0 + movsx r3, word [r1] + DC_ADD_INIT r3, r2 + DC_ADD_OP movh, r0, r2, r3 + RET + +; void ff_hevc_idct8_dc_add_8_mmxext(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) +cglobal hevc_idct8_dc_add_8, 3, 4, 0 + movsx r3, word [r1] + DC_ADD_INIT r3, r2 + DC_ADD_OP mova, r0, r2, r3 + lea r0, [r0+r2*4] + DC_ADD_OP mova, r0, r2, r3 + RET +%else +; void ff_hevc_idct_dc_add_8_mmxext(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) +cglobal hevc_idct4_dc_add_8, 2, 3, 0 + movsx r2, word [r1] + mov r1, r2m + DC_ADD_INIT r2, r1 + DC_ADD_OP movh, r0, r1, r2 + RET + +; void ff_hevc_idct8_dc_add_8_mmxext(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) +cglobal hevc_idct8_dc_add_8, 2, 3, 0 + movsx r2, word [r1] + mov r1, r2m + DC_ADD_INIT r2, r1 + DC_ADD_OP mova, r0, r1, r2 + lea r0, [r0+r1*4] + DC_ADD_OP mova, r0, r1, r2 + RET +%endif + + +INIT_XMM sse2 +; void ff_hevc_idct16_dc_add_8_sse2(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) +cglobal hevc_idct16_dc_add_8, 3, 4, 6 + movsx r3, word [r1] + DC_ADD_INIT r3, r2 + DC_ADD_OP mova, r0, r2, r3 + lea r0, [r0+r2*4] + DC_ADD_OP mova, r0, r2, r3 + lea r0, [r0+r2*4] + DC_ADD_OP mova, r0, r2, r3 + lea r0, [r0+r2*4] + DC_ADD_OP mova, r0, r2, r3 + RET + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +; void ff_hevc_idct32_dc_add_8_avx2(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) +cglobal hevc_idct32_dc_add_8, 3, 4, 6 + movsx r3, word [r1] + DC_ADD_INIT_AVX2 r3, r2 + DC_ADD_OP mova, r0, r2, r3, + %rep 7 + lea r0, [r0+r2*4] + DC_ADD_OP mova, r0, r2, r3 +%endrep + RET +%endif ;HAVE_AVX2_EXTERNAL +;----------------------------------------------------------------------------- +; void ff_hevc_idct_dc_add_10(pixel *dst, int16_t *block, int stride) +;----------------------------------------------------------------------------- +%macro IDCT_DC_ADD_OP_10 3 + pxor m5, m5 +%if avx_enabled + paddw m1, m0, [%1+0 ] + paddw m2, m0, [%1+%2 ] + paddw m3, m0, [%1+%2*2] + paddw m4, m0, [%1+%3 ] +%else + mova m1, [%1+0 ] + mova m2, [%1+%2 ] + mova m3, [%1+%2*2] + mova m4, [%1+%3 ] + paddw m1, m0 + paddw m2, m0 + paddw m3, m0 + paddw m4, m0 +%endif + CLIPW m1, m5, m6 + CLIPW m2, m5, m6 + CLIPW m3, m5, m6 + CLIPW m4, m5, m6 + mova [%1+0 ], m1 + mova [%1+%2 ], m2 + mova [%1+%2*2], m3 + mova [%1+%3 ], m4 +%endmacro + +INIT_MMX mmxext +cglobal hevc_idct4_dc_add_10,3,3 + mov r1w, [r1] + add r1w, ((1 << 4) + 1) + sar r1w, 5 + movd m0, r1d + lea r1, [r2*3] + SPLATW m0, m0, 0 + mova m6, [max_pixels_10] + IDCT_DC_ADD_OP_10 r0, r2, r1 + RET + +;----------------------------------------------------------------------------- +; void ff_hevc_idct8_dc_add_10(pixel *dst, int16_t *block, int stride) +;----------------------------------------------------------------------------- +%macro IDCT8_DC_ADD 0 +cglobal hevc_idct8_dc_add_10,3,4,7 + mov r1w, [r1] + add r1w, ((1 << 4) + 1) + sar r1w, 5 + movd m0, r1d + lea r1, [r2*3] + SPLATW m0, m0, 0 + mova m6, [max_pixels_10] + IDCT_DC_ADD_OP_10 r0, r2, r1 + lea r0, [r0+r2*4] + IDCT_DC_ADD_OP_10 r0, r2, r1 + RET +%endmacro + +INIT_XMM sse2 +IDCT8_DC_ADD +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +IDCT8_DC_ADD +%endif + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +cglobal hevc_idct16_dc_add_10,3,4,7 + mov r1w, [r1] + add r1w, ((1 << 4) + 1) + sar r1w, 5 + movd xm0, r1d + lea r1, [r2*3] + vpbroadcastw m0, xm0 ;SPLATW + mova m6, [max_pixels_10] + IDCT_DC_ADD_OP_10 r0, r2, r1 + lea r0, [r0+r2*4] + IDCT_DC_ADD_OP_10 r0, r2, r1 + lea r0, [r0+r2*4] + IDCT_DC_ADD_OP_10 r0, r2, r1 + lea r0, [r0+r2*4] + IDCT_DC_ADD_OP_10 r0, r2, r1 + RET +%endif ;HAVE_AVX_EXTERNAL diff --git a/libavcodec/x86/hevc_mc.asm b/libavcodec/x86/hevc_mc.asm new file mode 100644 index 000000000..5cf37d019 --- /dev/null +++ b/libavcodec/x86/hevc_mc.asm @@ -0,0 +1,1288 @@ +; /* +; * Provide SSE luma and chroma mc functions for HEVC decoding +; * Copyright (c) 2013 Pierre-Edouard LEPERE +; * +; * This file is part of FFmpeg. +; * +; * FFmpeg is free software; you can redistribute it and/or +; * modify it under the terms of the GNU Lesser General Public +; * License as published by the Free Software Foundation; either +; * version 2.1 of the License, or (at your option) any later version. +; * +; * FFmpeg is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; * Lesser General Public License for more details. +; * +; * You should have received a copy of the GNU Lesser General Public +; * License along with FFmpeg; if not, write to the Free Software +; * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +; */ +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA +pw_8: times 8 dw 512 +pw_10: times 8 dw 2048 +pw_bi_8: times 8 dw 256 +pw_bi_10: times 8 dw 1024 +max_pixels_10: times 8 dw 1023 +zero: times 4 dd 0 +one_per_32: times 4 dd 1 + +SECTION .text +%macro EPEL_TABLE 4 +hevc_epel_filters_%4_%1 times %2 d%3 -2, 58 + times %2 d%3 10, -2 + times %2 d%3 -4, 54 + times %2 d%3 16, -2 + times %2 d%3 -6, 46 + times %2 d%3 28, -4 + times %2 d%3 -4, 36 + times %2 d%3 36, -4 + times %2 d%3 -4, 28 + times %2 d%3 46, -6 + times %2 d%3 -2, 16 + times %2 d%3 54, -4 + times %2 d%3 -2, 10 + times %2 d%3 58, -2 +%endmacro + + + +EPEL_TABLE 8, 8, b, sse4 +EPEL_TABLE 10, 4, w, sse4 + +%macro QPEL_TABLE 4 +hevc_qpel_filters_%4_%1 times %2 d%3 -1, 4 + times %2 d%3 -10, 58 + times %2 d%3 17, -5 + times %2 d%3 1, 0 + times %2 d%3 -1, 4 + times %2 d%3 -11, 40 + times %2 d%3 40,-11 + times %2 d%3 4, -1 + times %2 d%3 0, 1 + times %2 d%3 -5, 17 + times %2 d%3 58,-10 + times %2 d%3 4, -1 +%endmacro + +QPEL_TABLE 8, 8, b, sse4 +QPEL_TABLE 10, 4, w, sse4 + +%define hevc_qpel_filters_sse4_14 hevc_qpel_filters_sse4_10 + +%if ARCH_X86_64 + +%macro SIMPLE_BILOAD 4 ;width, tab, r1, r2 +%if %1 <= 4 + movq %3, [%2] ; load data from source2 +%elif %1 <= 8 + movdqa %3, [%2] ; load data from source2 +%elif %1 <= 12 + movdqa %3, [%2] ; load data from source2 + movq %4, [%2+16] ; load data from source2 +%else + movdqa %3, [%2] ; load data from source2 + movdqa %4, [%2+16] ; load data from source2 +%endif +%endmacro + +%macro SIMPLE_LOAD 4 ;width, bitd, tab, r1 +%if %1 == 2 || (%2 == 8 && %1 <= 4) + movd %4, [%3] ; load data from source +%elif %1 == 4 || (%2 == 8 && %1 <= 8) + movq %4, [%3] ; load data from source +%else + movdqu %4, [%3] ; load data from source +%endif +%endmacro + +%macro SIMPLE_8LOAD 5 ;width, bitd, tab, r1, r2 +%if %1 == 2 || (%2 == 8 && %1 <= 4) + movq %4, [%3] ; load data from source2 +%elif %1 == 4 || (%2 == 8 && %1 <= 8) + movdqa %4, [%3] ; load data from source2 +%elif %1 <= 12 + movdqa %4, [%3] ; load data from source2 + movq %5, [%3+16] ; load data from source2 +%else + movdqa %4, [%3] ; load data from source2 + movdqa %5, [%3+16] ; load data from source2 +%endif +%endmacro + +%macro EPEL_FILTER 2-4 ; bit depth, filter index +%ifdef PIC + lea rfilterq, [hevc_epel_filters_sse4_%1] +%else + %define rfilterq hevc_epel_filters_sse4_%1 +%endif + sub %2q, 1 + shl %2q, 5 ; multiply by 32 +%if %0 == 2 + movdqa m14, [rfilterq + %2q] ; get 2 first values of filters + movdqa m15, [rfilterq + %2q+16] ; get 2 last values of filters +%else + movdqa %3, [rfilterq + %2q] ; get 2 first values of filters + movdqa %4, [rfilterq + %2q+16] ; get 2 last values of filters +%endif +%endmacro + +%macro EPEL_HV_FILTER 1 +%ifdef PIC + lea rfilterq, [hevc_epel_filters_sse4_%1] +%else + %define rfilterq hevc_epel_filters_sse4_%1 +%endif + sub mxq, 1 + sub myq, 1 + shl mxq, 5 ; multiply by 32 + shl myq, 5 ; multiply by 32 + movdqa m14, [rfilterq + mxq] ; get 2 first values of filters + movdqa m15, [rfilterq + mxq+16] ; get 2 last values of filters + lea r3srcq, [srcstrideq*3] + +%ifdef PIC + lea rfilterq, [hevc_epel_filters_sse4_10] +%else + %define rfilterq hevc_epel_filters_sse4_10 +%endif + movdqa m12, [rfilterq + myq] ; get 2 first values of filters + movdqa m13, [rfilterq + myq+16] ; get 2 last values of filters +%endmacro + +%macro QPEL_FILTER 2 +%ifdef PIC + lea rfilterq, [hevc_qpel_filters_sse4_%1] +%else + %define rfilterq hevc_qpel_filters_sse4_%1 +%endif + lea %2q, [%2q*8-8] + movdqa m12, [rfilterq + %2q*8] ; get 4 first values of filters + movdqa m13, [rfilterq + %2q*8 + 16] ; get 4 first values of filters + movdqa m14, [rfilterq + %2q*8 + 32] ; get 4 first values of filters + movdqa m15, [rfilterq + %2q*8 + 48] ; get 4 first values of filters +%endmacro + +%macro EPEL_LOAD 4 +%ifdef PIC + lea rfilterq, [%2] +%else + %define rfilterq %2 +%endif + movdqu m0, [rfilterq ] ;load 128bit of x +%ifnum %3 + movdqu m1, [rfilterq+ %3] ;load 128bit of x+stride + movdqu m2, [rfilterq+2*%3] ;load 128bit of x+2*stride + movdqu m3, [rfilterq+3*%3] ;load 128bit of x+3*stride +%else + movdqu m1, [rfilterq+ %3q] ;load 128bit of x+stride + movdqu m2, [rfilterq+2*%3q] ;load 128bit of x+2*stride + movdqu m3, [rfilterq+r3srcq] ;load 128bit of x+2*stride +%endif + +%if %1 == 8 +%if %4 > 8 + SBUTTERFLY bw, 0, 1, 10 + SBUTTERFLY bw, 2, 3, 10 +%else + punpcklbw m0, m1 + punpcklbw m2, m3 +%endif +%else +%if %4 > 4 + SBUTTERFLY wd, 0, 1, 10 + SBUTTERFLY wd, 2, 3, 10 +%else + punpcklwd m0, m1 + punpcklwd m2, m3 +%endif +%endif +%endmacro + + +%macro QPEL_H_LOAD 4 +%assign %%stride (%1+7)/8 +%if %1 == 8 +%if %3 <= 4 +%define %%load movd +%elif %3 == 8 +%define %%load movq +%else +%define %%load movdqu +%endif +%else +%if %3 == 2 +%define %%load movd +%elif %3 == 4 +%define %%load movq +%else +%define %%load movdqu +%endif +%endif + %%load m0, [%2-3*%%stride] ;load data from source + %%load m1, [%2-2*%%stride] + %%load m2, [%2-%%stride ] + %%load m3, [%2 ] + %%load m4, [%2+%%stride ] + %%load m5, [%2+2*%%stride] + %%load m6, [%2+3*%%stride] + %%load m7, [%2+4*%%stride] + +%if %1 == 8 +%if %3 > 8 + SBUTTERFLY wd, 0, 1, %4 + SBUTTERFLY wd, 2, 3, %4 + SBUTTERFLY wd, 4, 5, %4 + SBUTTERFLY wd, 6, 7, %4 +%else + punpcklwd m0, m1 + punpcklwd m2, m3 + punpcklwd m4, m5 + punpcklwd m6, m7 +%endif +%else +%if %3 > 4 + SBUTTERFLY dq, 0, 1, %4 + SBUTTERFLY dq, 2, 3, %4 + SBUTTERFLY dq, 4, 5, %4 + SBUTTERFLY dq, 6, 7, %4 +%else + punpckldq m0, m1 + punpckldq m2, m3 + punpckldq m4, m5 + punpckldq m6, m7 +%endif +%endif +%endmacro + +%macro QPEL_V_LOAD 4 + lea r12q, [%2] + sub r12q, r3srcq + movdqu m0, [r12 ] ;load x- 3*srcstride + movdqu m1, [r12+ %3q ] ;load x- 2*srcstride + movdqu m2, [r12+ 2*%3q ] ;load x-srcstride + movdqu m3, [%2 ] ;load x + movdqu m4, [%2+ %3q] ;load x+stride + movdqu m5, [%2+ 2*%3q] ;load x+2*stride + movdqu m6, [%2+r3srcq] ;load x+3*stride + movdqu m7, [%2+ 4*%3q] ;load x+4*stride +%if %1 == 8 +%if %4 > 8 + SBUTTERFLY bw, 0, 1, 8 + SBUTTERFLY bw, 2, 3, 8 + SBUTTERFLY bw, 4, 5, 8 + SBUTTERFLY bw, 6, 7, 8 +%else + punpcklbw m0, m1 + punpcklbw m2, m3 + punpcklbw m4, m5 + punpcklbw m6, m7 +%endif +%else +%if %4 > 4 + SBUTTERFLY wd, 0, 1, 8 + SBUTTERFLY wd, 2, 3, 8 + SBUTTERFLY wd, 4, 5, 8 + SBUTTERFLY wd, 6, 7, 8 +%else + punpcklwd m0, m1 + punpcklwd m2, m3 + punpcklwd m4, m5 + punpcklwd m6, m7 +%endif +%endif +%endmacro + +%macro PEL_10STORE2 3 + movd [%1], %2 +%endmacro +%macro PEL_10STORE4 3 + movq [%1], %2 +%endmacro +%macro PEL_10STORE6 3 + movq [%1], %2 + psrldq %2, 8 + movd [%1+8], %2 +%endmacro +%macro PEL_10STORE8 3 + movdqa [%1], %2 +%endmacro +%macro PEL_10STORE12 3 + movdqa [%1], %2 + movq [%1+16], %3 +%endmacro +%macro PEL_10STORE16 3 + PEL_10STORE8 %1, %2, %3 + movdqa [%1+16], %3 +%endmacro + +%macro PEL_8STORE2 3 + pextrw [%1], %2, 0 +%endmacro +%macro PEL_8STORE4 3 + movd [%1], %2 +%endmacro +%macro PEL_8STORE6 3 + movd [%1], %2 + pextrw [%1+4], %2, 2 +%endmacro +%macro PEL_8STORE8 3 + movq [%1], %2 +%endmacro +%macro PEL_8STORE12 3 + movq [%1], %2 + psrldq %2, 8 + movd [%1+8], %2 +%endmacro +%macro PEL_8STORE16 3 + movdqa [%1], %2 +%endmacro + +%macro LOOP_END 4 + lea %1q, [%1q+2*%2q] ; dst += dststride + lea %3q, [%3q+ %4q] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop +%endmacro + + +%macro MC_PIXEL_COMPUTE 2 ;width, bitdepth +%if %2 == 8 +%if %1 > 8 + punpckhbw m1, m0, m2 + psllw m1, 14-%2 +%endif + punpcklbw m0, m2 +%endif + psllw m0, 14-%2 +%endmacro + + +%macro EPEL_COMPUTE 4 ; bitdepth, width, filter1, filter2 +%if %1 == 8 + pmaddubsw m0, %3 ;x1*c1+x2*c2 + pmaddubsw m2, %4 ;x3*c3+x4*c4 + paddw m0, m2 +%if %2 > 8 + pmaddubsw m1, %3 + pmaddubsw m3, %4 + paddw m1, m3 +%endif +%else + pmaddwd m0, %3 + pmaddwd m2, %4 + paddd m0, m2 +%if %2 > 4 + pmaddwd m1, %3 + pmaddwd m3, %4 + paddd m1, m3 +%endif +%if %1 != 8 + psrad m0, %1-8 + psrad m1, %1-8 +%endif + packssdw m0, m1 +%endif +%endmacro + +%macro QPEL_HV_COMPUTE 4 ; width, bitdepth, filter idx +%ifdef PIC + lea rfilterq, [hevc_qpel_filters_sse4_%2] +%else + %define rfilterq hevc_qpel_filters_sse4_%2 +%endif + +%if %2 == 8 + pmaddubsw m0, [rfilterq + %3q*8 ] ;x1*c1+x2*c2 + pmaddubsw m2, [rfilterq + %3q*8+16] ;x3*c3+x4*c4 + pmaddubsw m4, [rfilterq + %3q*8+32] ;x5*c5+x6*c6 + pmaddubsw m6, [rfilterq + %3q*8+48] ;x7*c7+x8*c8 + paddw m0, m2 + paddw m4, m6 + paddw m0, m4 +%else + pmaddwd m0, [rfilterq + %3q*8 ] + pmaddwd m2, [rfilterq + %3q*8+16] + pmaddwd m4, [rfilterq + %3q*8+32] + pmaddwd m6, [rfilterq + %3q*8+48] + paddd m0, m2 + paddd m4, m6 + paddd m0, m4 +%if %2 != 8 + psrad m0, %2-8 +%endif +%if %1 > 4 + pmaddwd m1, [rfilterq + %3q*8 ] + pmaddwd m3, [rfilterq + %3q*8+16] + pmaddwd m5, [rfilterq + %3q*8+32] + pmaddwd m7, [rfilterq + %3q*8+48] + paddd m1, m3 + paddd m5, m7 + paddd m1, m5 +%if %2 != 8 + psrad m1, %2-8 +%endif +%endif + p%4 m0, m1 +%endif +%endmacro + +%macro QPEL_COMPUTE 2 ; width, bitdepth +%if %2 == 8 + pmaddubsw m0, m12 ;x1*c1+x2*c2 + pmaddubsw m2, m13 ;x3*c3+x4*c4 + pmaddubsw m4, m14 ;x5*c5+x6*c6 + pmaddubsw m6, m15 ;x7*c7+x8*c8 + paddw m0, m2 + paddw m4, m6 + paddw m0, m4 +%if %1 > 8 + pmaddubsw m1, m12 + pmaddubsw m3, m13 + pmaddubsw m5, m14 + pmaddubsw m7, m15 + paddw m1, m3 + paddw m5, m7 + paddw m1, m5 +%endif +%else + pmaddwd m0, m12 + pmaddwd m2, m13 + pmaddwd m4, m14 + pmaddwd m6, m15 + paddd m0, m2 + paddd m4, m6 + paddd m0, m4 +%if %2 != 8 + psrad m0, %2-8 +%endif +%if %1 > 4 + pmaddwd m1, m12 + pmaddwd m3, m13 + pmaddwd m5, m14 + pmaddwd m7, m15 + paddd m1, m3 + paddd m5, m7 + paddd m1, m5 +%if %2 != 8 + psrad m1, %2-8 +%endif +%endif +%endif +%endmacro + +%macro BI_COMPUTE 7 ; width, bitd, src1l, src1h, scr2l, scr2h, pw + paddsw %3, %5 +%if %1 > 8 + paddsw %4, %6 +%endif + UNI_COMPUTE %1, %2, %3, %4, %7 +%endmacro + +%macro UNI_COMPUTE 5 + pmulhrsw %3, %5 +%if %1 > 8 || (%2 > 8 && %1 > 4) + pmulhrsw %4, %5 +%endif +%if %2 == 8 + packuswb %3, %4 +%else + pminsw %3, [max_pixels_%2] + pmaxsw %3, [zero] +%if %1 > 8 + pminsw %4, [max_pixels_%2] + pmaxsw %4, [zero] +%endif +%endif +%endmacro + +INIT_XMM sse4 ; adds ff_ and _sse4 to function name +; ****************************** +; void put_hevc_mc_pixels(int16_t *dst, ptrdiff_t dststride, +; uint8_t *_src, ptrdiff_t _srcstride, +; int height, int mx, int my) +; ****************************** + +%macro HEVC_PUT_HEVC_PEL_PIXELS 2 +cglobal hevc_put_hevc_pel_pixels%1_%2, 5, 5, 3, dst, dststride, src, srcstride,height + pxor m2, m2 +.loop + SIMPLE_LOAD %1, %2, srcq, m0 + MC_PIXEL_COMPUTE %1, %2 + PEL_10STORE%1 dstq, m0, m1 + LOOP_END dst, dststride, src, srcstride + RET + +cglobal hevc_put_hevc_uni_pel_pixels%1_%2, 5, 5, 3, dst, dststride, src, srcstride,height + pxor m2, m2 +.loop + SIMPLE_LOAD %1, %2, srcq, m0 + PEL_%2STORE%1 dstq, m0, m1 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET + +cglobal hevc_put_hevc_bi_pel_pixels%1_%2, 7, 7, 6, dst, dststride, src, srcstride, src2, src2stride,height + pxor m2, m2 + movdqa m5, [pw_bi_%2] +.loop + SIMPLE_LOAD %1, %2, srcq, m0 + SIMPLE_BILOAD %1, src2q, m3, m4 + MC_PIXEL_COMPUTE %1, %2 + BI_COMPUTE %1, %2, m0, m1, m3, m4, m5 + PEL_%2STORE%1 dstq, m0, m1 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + lea src2q, [src2q+2*src2strideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET + +%endmacro + + +; ****************************** +; void put_hevc_epel_hX(int16_t *dst, ptrdiff_t dststride, +; uint8_t *_src, ptrdiff_t _srcstride, +; int width, int height, int mx, int my, +; int16_t* mcbuffer) +; ****************************** + + +%macro HEVC_PUT_HEVC_EPEL 2 +cglobal hevc_put_hevc_epel_h%1_%2, 6, 7, 6, dst, dststride, src, srcstride, height, mx, rfilter +%assign %%stride ((%2 + 7)/8) + EPEL_FILTER %2, mx, m4, m5 +.loop + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m4, m5 + PEL_10STORE%1 dstq, m0, m1 + LOOP_END dst, dststride, src, srcstride + RET + +cglobal hevc_put_hevc_uni_epel_h%1_%2, 6, 7, 7, dst, dststride, src, srcstride, height, mx, rfilter +%assign %%stride ((%2 + 7)/8) + movdqa m6, [pw_%2] + EPEL_FILTER %2, mx, m4, m5 +.loop + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m4, m5 + UNI_COMPUTE %1, %2, m0, m1, m6 + PEL_%2STORE%1 dstq, m0, m1 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET + +cglobal hevc_put_hevc_bi_epel_h%1_%2, 8, 9, 7, dst, dststride, src, srcstride, src2, src2stride,height, mx, rfilter + movdqa m6, [pw_bi_%2] + EPEL_FILTER %2, mx, m4, m5 +.loop + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m4, m5 + SIMPLE_BILOAD %1, src2q, m2, m3 + BI_COMPUTE %1, %2, m0, m1, m2, m3, m6 + PEL_%2STORE%1 dstq, m0, m1 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + lea src2q, [src2q+2*src2strideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET + +; ****************************** +; void 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) +; ****************************** + +cglobal hevc_put_hevc_epel_v%1_%2, 7, 8, 6, dst, dststride, src, srcstride, height, r3src, my, rfilter + lea r3srcq, [srcstrideq*3] + sub srcq, srcstrideq + EPEL_FILTER %2, my, m4, m5 +.loop + EPEL_LOAD %2, srcq, srcstride, %1 + EPEL_COMPUTE %2, %1, m4, m5 + PEL_10STORE%1 dstq, m0, m1 + LOOP_END dst, dststride, src, srcstride + RET + +cglobal hevc_put_hevc_uni_epel_v%1_%2, 7, 8, 7, dst, dststride, src, srcstride, height, r3src, my, rfilter + lea r3srcq, [srcstrideq*3] + movdqa m6, [pw_%2] + sub srcq, srcstrideq + EPEL_FILTER %2, my, m4, m5 +.loop + EPEL_LOAD %2, srcq, srcstride, %1 + EPEL_COMPUTE %2, %1, m4, m5 + UNI_COMPUTE %1, %2, m0, m1, m6 + PEL_%2STORE%1 dstq, m0, m1 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET + + +cglobal hevc_put_hevc_bi_epel_v%1_%2, 9, 10, 7, dst, dststride, src, srcstride, src2, src2stride,height, r3src, my, rfilter + lea r3srcq, [srcstrideq*3] + movdqa m6, [pw_bi_%2] + sub srcq, srcstrideq + EPEL_FILTER %2, my, m4, m5 +.loop + EPEL_LOAD %2, srcq, srcstride, %1 + EPEL_COMPUTE %2, %1, m4, m5 + SIMPLE_BILOAD %1, src2q, m2, m3 + BI_COMPUTE %1, %2, m0, m1, m2, m3, m6 + PEL_%2STORE%1 dstq, m0, m1 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + lea src2q, [src2q+2*src2strideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET +%endmacro + + +; ****************************** +; void put_hevc_epel_hv(int16_t *dst, ptrdiff_t dststride, +; uint8_t *_src, ptrdiff_t _srcstride, +; int width, int height, int mx, int my) +; ****************************** + +%macro HEVC_PUT_HEVC_EPEL_HV 2 +cglobal hevc_put_hevc_epel_hv%1_%2, 7, 9, 12 , dst, dststride, src, srcstride, height, mx, my, r3src, rfilter +%assign %%stride ((%2 + 7)/8) + sub srcq, srcstrideq + EPEL_HV_FILTER %2 + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m14, m15 + SWAP m4, m0 + lea srcq, [srcq + srcstrideq] + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m14, m15 + SWAP m5, m0 + lea srcq, [srcq + srcstrideq] + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m14, m15 + SWAP m6, m0 + lea srcq, [srcq + srcstrideq] +.loop + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m14, m15 + SWAP m7, m0 + punpcklwd m0, m4, m5 + punpcklwd m2, m6, m7 +%if %1 > 4 + punpckhwd m1, m4, m5 + punpckhwd m3, m6, m7 +%endif + EPEL_COMPUTE 14, %1, m12, m13 + PEL_10STORE%1 dstq, m0, m1 + movdqa m4, m5 + movdqa m5, m6 + movdqa m6, m7 + LOOP_END dst, dststride, src, srcstride + RET + +cglobal hevc_put_hevc_uni_epel_hv%1_%2, 7, 9, 12 , dst, dststride, src, srcstride, height, mx, my, r3src, rfilter +%assign %%stride ((%2 + 7)/8) + sub srcq, srcstrideq + EPEL_HV_FILTER %2 + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m14, m15 + SWAP m4, m0 + lea srcq, [srcq + srcstrideq] + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m14, m15 + SWAP m5, m0 + lea srcq, [srcq + srcstrideq] + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m14, m15 + SWAP m6, m0 + lea srcq, [srcq + srcstrideq] +.loop + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m14, m15 + SWAP m7, m0 + punpcklwd m0, m4, m5 + punpcklwd m2, m6, m7 +%if %1 > 4 + punpckhwd m1, m4, m5 + punpckhwd m3, m6, m7 +%endif + EPEL_COMPUTE 14, %1, m12, m13 + UNI_COMPUTE %1, %2, m0, m1, [pw_%2] + PEL_%2STORE%1 dstq, m0, m1 + movdqa m4, m5 + movdqa m5, m6 + movdqa m6, m7 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET + + +cglobal hevc_put_hevc_bi_epel_hv%1_%2, 9, 11, 16, dst, dststride, src, srcstride, src2, src2stride, height, mx, my, r3src, rfilter +%assign %%stride ((%2 + 7)/8) + sub srcq, srcstrideq + EPEL_HV_FILTER %2 + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m14, m15 + SWAP m4, m0 + lea srcq, [srcq + srcstrideq] + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m14, m15 + SWAP m5, m0 + lea srcq, [srcq + srcstrideq] + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m14, m15 + SWAP m6, m0 + lea srcq, [srcq + srcstrideq] +.loop + EPEL_LOAD %2, srcq-%%stride, %%stride, %1 + EPEL_COMPUTE %2, %1, m14, m15 + SWAP m7, m0 + punpcklwd m0, m4, m5 + punpcklwd m2, m6, m7 +%if %1 > 4 + punpckhwd m1, m4, m5 + punpckhwd m3, m6, m7 +%endif + EPEL_COMPUTE 14, %1, m12, m13 + SIMPLE_BILOAD %1, src2q, m8, m9 + BI_COMPUTE %1, %2, m0, m1, m8, m9, [pw_bi_%2] + PEL_%2STORE%1 dstq, m0, m1 + movdqa m4, m5 + movdqa m5, m6 + movdqa m6, m7 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + lea src2q, [src2q+2*src2strideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET +%endmacro + +; ****************************** +; void put_hevc_qpel_hX_X_X(int16_t *dst, ptrdiff_t dststride, +; uint8_t *_src, ptrdiff_t _srcstride, +; int width, int height, int mx, int my) +; ****************************** + +%macro HEVC_PUT_HEVC_QPEL 2 +cglobal hevc_put_hevc_qpel_h%1_%2, 6, 7, 15 , dst, dststride, src, srcstride, height, mx, rfilter + QPEL_FILTER %2, mx +.loop + QPEL_H_LOAD %2, srcq, %1, 10 + QPEL_COMPUTE %1, %2 +%if %2 > 8 + packssdw m0, m1 +%endif + PEL_10STORE%1 dstq, m0, m1 + LOOP_END dst, dststride, src, srcstride + RET + +cglobal hevc_put_hevc_uni_qpel_h%1_%2, 6, 7, 15 , dst, dststride, src, srcstride, height, mx, rfilter + movdqa m9, [pw_%2] + QPEL_FILTER %2, mx +.loop + QPEL_H_LOAD %2, srcq, %1, 10 + QPEL_COMPUTE %1, %2 +%if %2 > 8 + packssdw m0, m1 +%endif + UNI_COMPUTE %1, %2, m0, m1, m9 + PEL_%2STORE%1 dstq, m0, m1 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET + +cglobal hevc_put_hevc_bi_qpel_h%1_%2, 8, 9, 16 , dst, dststride, src, srcstride, src2, src2stride, height, mx, rfilter + movdqa m9, [pw_bi_%2] + QPEL_FILTER %2, mx +.loop + QPEL_H_LOAD %2, srcq, %1, 10 + QPEL_COMPUTE %1, %2 +%if %2 > 8 + packssdw m0, m1 +%endif + SIMPLE_BILOAD %1, src2q, m10, m11 + BI_COMPUTE %1, %2, m0, m1, m10, m11, m9 + PEL_%2STORE%1 dstq, m0, m1 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + lea src2q, [src2q+2*src2strideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET + + +; ****************************** +; void put_hevc_qpel_vX_X_X(int16_t *dst, ptrdiff_t dststride, +; uint8_t *_src, ptrdiff_t _srcstride, +; int width, int height, int mx, int my) +; ****************************** + +cglobal hevc_put_hevc_qpel_v%1_%2, 7, 14, 15 , dst, dststride, src, srcstride, height, r3src, my, rfilter + lea r3srcq, [srcstrideq*3] + QPEL_FILTER %2, my +.loop + QPEL_V_LOAD %2, srcq, srcstride, %1 + QPEL_COMPUTE %1, %2 +%if %2 > 8 + packssdw m0, m1 +%endif + PEL_10STORE%1 dstq, m0, m1 + LOOP_END dst, dststride, src, srcstride + RET + +cglobal hevc_put_hevc_uni_qpel_v%1_%2, 7, 14, 15 , dst, dststride, src, srcstride, height, r3src, my, rfilter + movdqa m9, [pw_%2] + lea r3srcq, [srcstrideq*3] + QPEL_FILTER %2, my +.loop + QPEL_V_LOAD %2, srcq, srcstride, %1 + QPEL_COMPUTE %1, %2 +%if %2 > 8 + packusdw m0, m1 +%endif + UNI_COMPUTE %1, %2, m0, m1, m9 + PEL_%2STORE%1 dstq, m0, m1 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET + +cglobal hevc_put_hevc_bi_qpel_v%1_%2, 9, 14, 16 , dst, dststride, src, srcstride, src2, src2stride, height, r3src, my, rfilter + movdqa m9, [pw_bi_%2] + lea r3srcq, [srcstrideq*3] + QPEL_FILTER %2, my +.loop + SIMPLE_BILOAD %1, src2q, m10, m11 + QPEL_V_LOAD %2, srcq, srcstride, %1 + QPEL_COMPUTE %1, %2 +%if %2 > 8 + packssdw m0, m1 +%endif + BI_COMPUTE %1, %2, m0, m1, m10, m11, m9 + PEL_%2STORE%1 dstq, m0, m1 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + lea src2q, [src2q+2*src2strideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET +%endmacro + + +; ****************************** +; void put_hevc_qpel_hvX_X(int16_t *dst, ptrdiff_t dststride, +; uint8_t *_src, ptrdiff_t _srcstride, +; int height, int mx, int my) +; ****************************** +%macro HEVC_PUT_HEVC_QPEL_HV 2 +cglobal hevc_put_hevc_qpel_hv%1_%2, 7, 9, 12 , dst, dststride, src, srcstride, height, mx, my, r3src, rfilter + lea mxq, [mxq*8-8] + lea myq, [myq*8-8] + lea r3srcq, [srcstrideq*3] + sub srcq, r3srcq + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m8, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m9, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m10, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m11, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m12, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m13, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m14, m0 + lea srcq, [srcq + srcstrideq] +.loop + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m15, m0 + punpcklwd m0, m8, m9 + punpcklwd m2, m10, m11 + punpcklwd m4, m12, m13 + punpcklwd m6, m14, m15 +%if %1 > 4 + punpckhwd m1, m8, m9 + punpckhwd m3, m10, m11 + punpckhwd m5, m12, m13 + punpckhwd m7, m14, m15 +%endif + QPEL_HV_COMPUTE %1, 14, my, ackssdw + PEL_10STORE%1 dstq, m0, m1 +%if %1 <= 4 + movq m8, m9 + movq m9, m10 + movq m10, m11 + movq m11, m12 + movq m12, m13 + movq m13, m14 + movq m14, m15 +%else + movdqa m8, m9 + movdqa m9, m10 + movdqa m10, m11 + movdqa m11, m12 + movdqa m12, m13 + movdqa m13, m14 + movdqa m14, m15 +%endif + LOOP_END dst, dststride, src, srcstride + RET + +cglobal hevc_put_hevc_uni_qpel_hv%1_%2, 7, 9, 12 , dst, dststride, src, srcstride, height, mx, my, r3src, rfilter + lea mxq, [mxq*8-8] + lea myq, [myq*8-8] + lea r3srcq, [srcstrideq*3] + sub srcq, r3srcq + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m8, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m9, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m10, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m11, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m12, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m13, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m14, m0 + lea srcq, [srcq + srcstrideq] +.loop + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m15, m0 + punpcklwd m0, m8, m9 + punpcklwd m2, m10, m11 + punpcklwd m4, m12, m13 + punpcklwd m6, m14, m15 +%if %1 > 4 + punpckhwd m1, m8, m9 + punpckhwd m3, m10, m11 + punpckhwd m5, m12, m13 + punpckhwd m7, m14, m15 +%endif + QPEL_HV_COMPUTE %1, 14, my, ackusdw + UNI_COMPUTE %1, %2, m0, m1, [pw_%2] + PEL_%2STORE%1 dstq, m0, m1 + +%if %1 <= 4 + movq m8, m9 + movq m9, m10 + movq m10, m11 + movq m11, m12 + movq m12, m13 + movq m13, m14 + movq m14, m15 +%else + movdqa m8, m9 + movdqa m9, m10 + movdqa m10, m11 + movdqa m11, m12 + movdqa m12, m13 + movdqa m13, m14 + movdqa m14, m15 +%endif + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET + +cglobal hevc_put_hevc_bi_qpel_hv%1_%2, 9, 11, 16, dst, dststride, src, srcstride, src2, src2stride, height, mx, my, r3src, rfilter + lea mxq, [mxq*8-8] + lea myq, [myq*8-8] + lea r3srcq, [srcstrideq*3] + sub srcq, r3srcq + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m8, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m9, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m10, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m11, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m12, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m13, m0 + lea srcq, [srcq + srcstrideq] + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m14, m0 + lea srcq, [srcq + srcstrideq] +.loop + QPEL_H_LOAD %2, srcq, %1, 15 + QPEL_HV_COMPUTE %1, %2, mx, ackssdw + SWAP m15, m0 + punpcklwd m0, m8, m9 + punpcklwd m2, m10, m11 + punpcklwd m4, m12, m13 + punpcklwd m6, m14, m15 +%if %1 > 4 + punpckhwd m1, m8, m9 + punpckhwd m3, m10, m11 + punpckhwd m5, m12, m13 + punpckhwd m7, m14, m15 +%endif + QPEL_HV_COMPUTE %1, 14, my, ackssdw + SIMPLE_BILOAD %1, src2q, m8, m9 ;m9 not used in this case + BI_COMPUTE %1, %2, m0, m1, m8, m9, [pw_bi_%2] + PEL_%2STORE%1 dstq, m0, m1 + +%if %1 <= 4 + movq m8, m9 + movq m9, m10 + movq m10, m11 + movq m11, m12 + movq m12, m13 + movq m13, m14 + movq m14, m15 +%else + movdqa m8, m9 + movdqa m9, m10 + movdqa m10, m11 + movdqa m11, m12 + movdqa m12, m13 + movdqa m13, m14 + movdqa m14, m15 +%endif + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+srcstrideq] ; src += srcstride + lea src2q, [src2q+2*src2strideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET +%endmacro + +%macro WEIGHTING_FUNCS 2 +%if WIN64 || ARCH_X86_32 +cglobal hevc_put_hevc_uni_w%1_%2, 4, 5, 7, dst, dststride, src, srcstride, height, denom, wx, ox + mov r4d, denomm +%define SHIFT r4d +%else +cglobal hevc_put_hevc_uni_w%1_%2, 6, 6, 7, dst, dststride, src, srcstride, height, denom, wx, ox +%define SHIFT denomd +%endif + lea SHIFT, [SHIFT+14-%2] ; shift = 14 - bitd + denom + movd m2, wxm ; WX + movd m4, SHIFT ; shift + punpcklwd m2, m2 + dec SHIFT + movdqu m5, [one_per_32] + movd m6, SHIFT + pshufd m2, m2, 0 + mov SHIFT, oxm + pslld m5, m6 +%if %2 != 8 + shl SHIFT, %2-8 ; ox << (bitd - 8) +%endif + movd m3, SHIFT ; OX + pshufd m3, m3, 0 +%if WIN64 || ARCH_X86_32 + mov SHIFT, heightm +%endif +.loop + SIMPLE_LOAD %1, 10, srcq, m0 + pmulhw m6, m0, m2 + pmullw m0, m2 + punpckhwd m1, m0, m6 + punpcklwd m0, m6 + paddd m0, m5 + paddd m1, m5 + psrad m0, m4 + psrad m1, m4 + paddd m0, m3 + paddd m1, m3 + packusdw m0, m1 +%if %2 == 8 + packuswb m0, m0 +%else + pminsw m0, [max_pixels_%2] +%endif + PEL_%2STORE%1 dstq, m0, m1 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+2*srcstrideq] ; src += srcstride + dec heightd ; cmp height + jnz .loop ; height loop + RET + +cglobal hevc_put_hevc_bi_w%1_%2, 6, 7, 10, dst, dststride, src, srcstride, src2, src2stride, height, denom, wx0, wx1, ox0, ox1 + mov r6d, denomm + movd m2, wx0m ; WX0 + lea r6d, [r6d+14-%2] ; shift = 14 - bitd + denom + movd m3, wx1m ; WX1 + movd m0, r6d ; shift + punpcklwd m2, m2 + inc r6d + punpcklwd m3, m3 + movd m5, r6d ; shift+1 + pshufd m2, m2, 0 + mov r6d, ox0m + pshufd m3, m3, 0 + add r6d, ox1m +%if %2 != 8 + shl r6d, %2-8 ; ox << (bitd - 8) +%endif + inc r6d + movd m4, r6d ; offset + pshufd m4, m4, 0 + mov r6d, heightm + pslld m4, m0 + +.loop + SIMPLE_LOAD %1, 10, srcq, m0 + SIMPLE_LOAD %1, 10, src2q, m8 + pmulhw m6, m0, m3 + pmullw m0, m3 + pmulhw m7, m8, m2 + pmullw m8, m2 + punpckhwd m1, m0, m6 + punpcklwd m0, m6 + punpckhwd m9, m8, m7 + punpcklwd m8, m7 + paddd m0, m8 + paddd m1, m9 + paddd m0, m4 + paddd m1, m4 + psrad m0, m5 + psrad m1, m5 + packusdw m0, m1 +%if %2 == 8 + packuswb m0, m0 +%else + pminsw m0, [max_pixels_%2] +%endif + PEL_%2STORE%1 dstq, m0, m1 + lea dstq, [dstq+dststrideq] ; dst += dststride + lea srcq, [srcq+2*srcstrideq] ; src += srcstride + lea src2q, [src2q+2*src2strideq] ; src2 += srcstride + dec r6d ; cmp height + jnz .loop ; height loop + RET +%endmacro + +WEIGHTING_FUNCS 2, 8 +WEIGHTING_FUNCS 4, 8 +WEIGHTING_FUNCS 6, 8 +WEIGHTING_FUNCS 8, 8 + +WEIGHTING_FUNCS 2, 10 +WEIGHTING_FUNCS 4, 10 +WEIGHTING_FUNCS 6, 10 +WEIGHTING_FUNCS 8, 10 + +HEVC_PUT_HEVC_PEL_PIXELS 2, 8 +HEVC_PUT_HEVC_PEL_PIXELS 4, 8 +HEVC_PUT_HEVC_PEL_PIXELS 6, 8 +HEVC_PUT_HEVC_PEL_PIXELS 8, 8 +HEVC_PUT_HEVC_PEL_PIXELS 12, 8 +HEVC_PUT_HEVC_PEL_PIXELS 16, 8 + +HEVC_PUT_HEVC_PEL_PIXELS 2, 10 +HEVC_PUT_HEVC_PEL_PIXELS 4, 10 +HEVC_PUT_HEVC_PEL_PIXELS 6, 10 +HEVC_PUT_HEVC_PEL_PIXELS 8, 10 + + +HEVC_PUT_HEVC_EPEL 2, 8 +HEVC_PUT_HEVC_EPEL 4, 8 +HEVC_PUT_HEVC_EPEL 6, 8 +HEVC_PUT_HEVC_EPEL 8, 8 +HEVC_PUT_HEVC_EPEL 12, 8 +HEVC_PUT_HEVC_EPEL 16, 8 + + +HEVC_PUT_HEVC_EPEL 2, 10 +HEVC_PUT_HEVC_EPEL 4, 10 +HEVC_PUT_HEVC_EPEL 6, 10 +HEVC_PUT_HEVC_EPEL 8, 10 + + +HEVC_PUT_HEVC_EPEL_HV 2, 8 +HEVC_PUT_HEVC_EPEL_HV 4, 8 +HEVC_PUT_HEVC_EPEL_HV 6, 8 +HEVC_PUT_HEVC_EPEL_HV 8, 8 + +HEVC_PUT_HEVC_EPEL_HV 2, 10 +HEVC_PUT_HEVC_EPEL_HV 4, 10 +HEVC_PUT_HEVC_EPEL_HV 6, 10 +HEVC_PUT_HEVC_EPEL_HV 8, 10 + + +HEVC_PUT_HEVC_QPEL 4, 8 +HEVC_PUT_HEVC_QPEL 8, 8 +HEVC_PUT_HEVC_QPEL 12, 8 +HEVC_PUT_HEVC_QPEL 16, 8 + +HEVC_PUT_HEVC_QPEL 4, 10 +HEVC_PUT_HEVC_QPEL 8, 10 + +HEVC_PUT_HEVC_QPEL_HV 2, 8 +HEVC_PUT_HEVC_QPEL_HV 4, 8 +HEVC_PUT_HEVC_QPEL_HV 6, 8 +HEVC_PUT_HEVC_QPEL_HV 8, 8 + +HEVC_PUT_HEVC_QPEL_HV 2, 10 +HEVC_PUT_HEVC_QPEL_HV 4, 10 +HEVC_PUT_HEVC_QPEL_HV 6, 10 +HEVC_PUT_HEVC_QPEL_HV 8, 10 + +%endif ; ARCH_X86_64 diff --git a/libavcodec/x86/hevcdsp.h b/libavcodec/x86/hevcdsp.h new file mode 100644 index 000000000..661a860bd --- /dev/null +++ b/libavcodec/x86/hevcdsp.h @@ -0,0 +1,154 @@ +/* + * HEVC video decoder + * + * Copyright (C) 2012 - 2013 Guillaume Martres + * Copyright (C) 2013 - 2014 Pierre-Edouard Lepere + * + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_X86_HEVCDSP_H +#define AVCODEC_X86_HEVCDSP_H + +#include +#include + + +#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) + +#define PEL_LINK(dst, idx1, idx2, idx3, name, D, opt) \ +dst[idx1][idx2][idx3] = ff_hevc_put_hevc_ ## name ## _ ## D ## _##opt; \ +dst ## _bi[idx1][idx2][idx3] = ff_hevc_put_hevc_bi_ ## name ## _ ## D ## _##opt; \ +dst ## _uni[idx1][idx2][idx3] = ff_hevc_put_hevc_uni_ ## name ## _ ## D ## _##opt; \ +dst ## _uni_w[idx1][idx2][idx3] = ff_hevc_put_hevc_uni_w_ ## name ## _ ## D ## _##opt; \ +dst ## _bi_w[idx1][idx2][idx3] = ff_hevc_put_hevc_bi_w_ ## name ## _ ## D ## _##opt + + +#define PEL_PROTOTYPE(name, D, opt) \ +void ff_hevc_put_hevc_ ## name ## _ ## D ## _##opt(int16_t *dst, ptrdiff_t dststride,uint8_t *_src, ptrdiff_t _srcstride, int height, intptr_t mx, intptr_t my,int width); \ +void ff_hevc_put_hevc_bi_ ## name ## _ ## D ## _##opt(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, int16_t *src2, ptrdiff_t src2stride, int height, intptr_t mx, intptr_t my, int width); \ +void ff_hevc_put_hevc_uni_ ## name ## _ ## D ## _##opt(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, int height, intptr_t mx, intptr_t my, int width); \ +void ff_hevc_put_hevc_uni_w_ ## name ## _ ## D ## _##opt(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width); \ +void ff_hevc_put_hevc_bi_w_ ## name ## _ ## D ## _##opt(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, int16_t *src2, ptrdiff_t src2stride, int height, int denom, int wx0, int wx1, int ox0, int ox1, intptr_t mx, intptr_t my, int width) + + +/////////////////////////////////////////////////////////////////////////////// +// MC functions +/////////////////////////////////////////////////////////////////////////////// + +#define EPEL_PROTOTYPES(fname, bitd, opt) \ + PEL_PROTOTYPE(fname##4, bitd, opt); \ + PEL_PROTOTYPE(fname##6, bitd, opt); \ + PEL_PROTOTYPE(fname##8, bitd, opt); \ + PEL_PROTOTYPE(fname##12, bitd, opt); \ + PEL_PROTOTYPE(fname##16, bitd, opt); \ + PEL_PROTOTYPE(fname##24, bitd, opt); \ + PEL_PROTOTYPE(fname##32, bitd, opt); \ + PEL_PROTOTYPE(fname##48, bitd, opt); \ + PEL_PROTOTYPE(fname##64, bitd, opt) + +#define QPEL_PROTOTYPES(fname, bitd, opt) \ + PEL_PROTOTYPE(fname##4, bitd, opt); \ + PEL_PROTOTYPE(fname##8, bitd, opt); \ + PEL_PROTOTYPE(fname##12, bitd, opt); \ + PEL_PROTOTYPE(fname##16, bitd, opt); \ + PEL_PROTOTYPE(fname##24, bitd, opt); \ + PEL_PROTOTYPE(fname##32, bitd, opt); \ + PEL_PROTOTYPE(fname##48, bitd, opt); \ + PEL_PROTOTYPE(fname##64, bitd, opt) + +#define WEIGHTING_PROTOTYPE(width, bitd, opt) \ +void ff_hevc_put_hevc_uni_w##width##_##bitd##_##opt(uint8_t *dst, ptrdiff_t dststride, int16_t *_src, ptrdiff_t _srcstride, int height, int denom, int _wx, int _ox); \ +void ff_hevc_put_hevc_bi_w##width##_##bitd##_##opt(uint8_t *dst, ptrdiff_t dststride, int16_t *_src, ptrdiff_t _srcstride, int16_t *_src2, ptrdiff_t _src2stride, int height, int denom, int _wx0, int _wx1, int _ox0, int _ox1) + +#define WEIGHTING_PROTOTYPES(bitd, opt) \ + WEIGHTING_PROTOTYPE(2, bitd, opt); \ + WEIGHTING_PROTOTYPE(4, bitd, opt); \ + WEIGHTING_PROTOTYPE(6, bitd, opt); \ + WEIGHTING_PROTOTYPE(8, bitd, opt); \ + WEIGHTING_PROTOTYPE(12, bitd, opt); \ + WEIGHTING_PROTOTYPE(16, bitd, opt); \ + WEIGHTING_PROTOTYPE(24, bitd, opt); \ + WEIGHTING_PROTOTYPE(32, bitd, opt); \ + WEIGHTING_PROTOTYPE(48, bitd, opt); \ + WEIGHTING_PROTOTYPE(64, bitd, opt) + + +/////////////////////////////////////////////////////////////////////////////// +// QPEL_PIXELS EPEL_PIXELS +/////////////////////////////////////////////////////////////////////////////// +EPEL_PROTOTYPES(pel_pixels , 8, sse4); +EPEL_PROTOTYPES(pel_pixels , 10, sse4); +/////////////////////////////////////////////////////////////////////////////// +// EPEL +/////////////////////////////////////////////////////////////////////////////// +EPEL_PROTOTYPES(epel_h , 8, sse4); +EPEL_PROTOTYPES(epel_h , 10, sse4); + +EPEL_PROTOTYPES(epel_v , 8, sse4); +EPEL_PROTOTYPES(epel_v , 10, sse4); + +EPEL_PROTOTYPES(epel_hv , 8, sse4); +EPEL_PROTOTYPES(epel_hv , 10, sse4); + +/////////////////////////////////////////////////////////////////////////////// +// QPEL +/////////////////////////////////////////////////////////////////////////////// +QPEL_PROTOTYPES(qpel_h , 8, sse4); +QPEL_PROTOTYPES(qpel_h , 10, sse4); + +QPEL_PROTOTYPES(qpel_v, 8, sse4); +QPEL_PROTOTYPES(qpel_v, 10, sse4); + +QPEL_PROTOTYPES(qpel_hv, 8, sse4); +QPEL_PROTOTYPES(qpel_hv, 10, sse4); + + +WEIGHTING_PROTOTYPES(8, sse4); +WEIGHTING_PROTOTYPES(10, sse4); + +/////////////////////////////////////////////////////////////////////////////// +// IDCT +/////////////////////////////////////////////////////////////////////////////// + + +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); + + + + + +#endif // AVCODEC_X86_HEVCDSP_H diff --git a/libavcodec/x86/hevcdsp_init.c b/libavcodec/x86/hevcdsp_init.c new file mode 100644 index 000000000..2c7676648 --- /dev/null +++ b/libavcodec/x86/hevcdsp_init.c @@ -0,0 +1,505 @@ +/* + * Copyright (c) 2013 Seppo Tomperi + * Copyright (c) 2013 - 2014 Pierre-Edouard Lepere + * + * + * This file is part of ffmpeg. + * + * ffmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * ffmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with ffmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/get_bits.h" /* required for hevcdsp.h GetBitContext */ +#include "libavcodec/hevcdsp.h" +#include "libavcodec/x86/hevcdsp.h" + + +#define LFC_FUNC(DIR, DEPTH, OPT) \ +void ff_hevc_ ## DIR ## _loop_filter_chroma_ ## DEPTH ## _ ## OPT(uint8_t *_pix, ptrdiff_t _stride, int *_tc, uint8_t *_no_p, uint8_t *_no_q); + +#define LFL_FUNC(DIR, DEPTH, OPT) \ +void ff_hevc_ ## DIR ## _loop_filter_luma_ ## DEPTH ## _ ## OPT(uint8_t *_pix, ptrdiff_t stride, int *_beta, int *_tc, \ +uint8_t *_no_p, uint8_t *_no_q); + +#define LFC_FUNCS(type, depth, opt) \ +LFC_FUNC(h, depth, opt) \ +LFC_FUNC(v, depth, opt) + +#define LFL_FUNCS(type, depth, opt) \ +LFL_FUNC(h, depth, opt) \ +LFL_FUNC(v, depth, opt) + +LFC_FUNCS(uint8_t, 8, sse2) +LFC_FUNCS(uint8_t, 10, sse2) +LFL_FUNCS(uint8_t, 8, sse2) +LFL_FUNCS(uint8_t, 10, sse2) +LFL_FUNCS(uint8_t, 8, ssse3) +LFL_FUNCS(uint8_t, 10, ssse3) + +#if HAVE_SSE2_EXTERNAL +void ff_hevc_idct32_dc_add_8_sse2(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) +{ + ff_hevc_idct16_dc_add_8_sse2(dst, coeffs, stride); + ff_hevc_idct16_dc_add_8_sse2(dst+16, coeffs, stride); + ff_hevc_idct16_dc_add_8_sse2(dst+16*stride, coeffs, stride); + ff_hevc_idct16_dc_add_8_sse2(dst+16*stride+16, coeffs, stride); +} + +void ff_hevc_idct16_dc_add_10_sse2(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) +{ + ff_hevc_idct8_dc_add_10_sse2(dst, coeffs, stride); + ff_hevc_idct8_dc_add_10_sse2(dst+16, coeffs, stride); + ff_hevc_idct8_dc_add_10_sse2(dst+8*stride, coeffs, stride); + ff_hevc_idct8_dc_add_10_sse2(dst+8*stride+16, coeffs, stride); +} + +void ff_hevc_idct32_dc_add_10_sse2(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) +{ + ff_hevc_idct16_dc_add_10_sse2(dst, coeffs, stride); + ff_hevc_idct16_dc_add_10_sse2(dst+32, coeffs, stride); + ff_hevc_idct16_dc_add_10_sse2(dst+16*stride, coeffs, stride); + ff_hevc_idct16_dc_add_10_sse2(dst+16*stride+32, coeffs, stride); +} +#endif //HAVE_SSE2_EXTERNAL +#if HAVE_AVX_EXTERNAL +void ff_hevc_idct16_dc_add_10_avx(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) +{ + ff_hevc_idct8_dc_add_10_avx(dst, coeffs, stride); + ff_hevc_idct8_dc_add_10_avx(dst+16, coeffs, stride); + ff_hevc_idct8_dc_add_10_avx(dst+8*stride, coeffs, stride); + ff_hevc_idct8_dc_add_10_avx(dst+8*stride+16, coeffs, stride); +} + +void ff_hevc_idct32_dc_add_10_avx(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) +{ + ff_hevc_idct16_dc_add_10_avx(dst, coeffs, stride); + ff_hevc_idct16_dc_add_10_avx(dst+32, coeffs, stride); + ff_hevc_idct16_dc_add_10_avx(dst+16*stride, coeffs, stride); + ff_hevc_idct16_dc_add_10_avx(dst+16*stride+32, coeffs, stride); +} +#endif //HAVE_AVX_EXTERNAL + +#if HAVE_AVX2_EXTERNAL + +void ff_hevc_idct32_dc_add_10_avx2(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) +{ + ff_hevc_idct16_dc_add_10_avx2(dst, coeffs, stride); + ff_hevc_idct16_dc_add_10_avx2(dst+32, coeffs, stride); + ff_hevc_idct16_dc_add_10_avx2(dst+16*stride, coeffs, stride); + ff_hevc_idct16_dc_add_10_avx2(dst+16*stride+32, coeffs, stride); +} +#endif //HAVE_AVX2_EXTERNAL + +#define mc_rep_func(name, bitd, step, W, opt) \ +void ff_hevc_put_hevc_##name##W##_##bitd##_##opt(int16_t *_dst, ptrdiff_t dststride, \ + uint8_t *_src, ptrdiff_t _srcstride, int height, \ + intptr_t mx, intptr_t my, int width) \ +{ \ + int i; \ + uint8_t *src; \ + int16_t *dst; \ + for (i = 0; i < W; i += step) { \ + src = _src + (i * ((bitd + 7) / 8)); \ + dst = _dst + i; \ + ff_hevc_put_hevc_##name##step##_##bitd##_##opt(dst, dststride, src, _srcstride, height, mx, my, width); \ + } \ +} +#define mc_rep_uni_func(name, bitd, step, W, opt) \ +void ff_hevc_put_hevc_uni_##name##W##_##bitd##_##opt(uint8_t *_dst, ptrdiff_t dststride, \ + uint8_t *_src, ptrdiff_t _srcstride, int height, \ + intptr_t mx, intptr_t my, int width) \ +{ \ + int i; \ + uint8_t *src; \ + uint8_t *dst; \ + for (i = 0; i < W; i += step) { \ + src = _src + (i * ((bitd + 7) / 8)); \ + dst = _dst + (i * ((bitd + 7) / 8)); \ + ff_hevc_put_hevc_uni_##name##step##_##bitd##_##opt(dst, dststride, src, _srcstride, \ + height, mx, my, width); \ + } \ +} +#define mc_rep_bi_func(name, bitd, step, W, opt) \ +void ff_hevc_put_hevc_bi_##name##W##_##bitd##_##opt(uint8_t *_dst, ptrdiff_t dststride, uint8_t *_src, \ + ptrdiff_t _srcstride, int16_t* _src2, ptrdiff_t _src2stride, \ + int height, intptr_t mx, intptr_t my, int width) \ +{ \ + int i; \ + uint8_t *src; \ + uint8_t *dst; \ + int16_t *src2; \ + for (i = 0; i < W ; i += step) { \ + src = _src + (i * ((bitd + 7) / 8)); \ + dst = _dst + (i * ((bitd + 7) / 8)); \ + src2 = _src2 + i; \ + ff_hevc_put_hevc_bi_##name##step##_##bitd##_##opt(dst, dststride, src, _srcstride, src2, \ + _src2stride, height, mx, my, width); \ + } \ +} + +#define mc_rep_funcs(name, bitd, step, W, opt) \ + mc_rep_func(name, bitd, step, W, opt); \ + mc_rep_uni_func(name, bitd, step, W, opt); \ + mc_rep_bi_func(name, bitd, step, W, opt) + + +#if ARCH_X86_64 && HAVE_SSE4_EXTERNAL + +mc_rep_funcs(pel_pixels, 8, 16, 64, sse4); +mc_rep_funcs(pel_pixels, 8, 16, 48, sse4); +mc_rep_funcs(pel_pixels, 8, 16, 32, sse4); +mc_rep_funcs(pel_pixels, 8, 8, 24, sse4); + +mc_rep_funcs(pel_pixels,10, 8, 64, sse4); +mc_rep_funcs(pel_pixels,10, 8, 48, sse4); +mc_rep_funcs(pel_pixels,10, 8, 32, sse4); +mc_rep_funcs(pel_pixels,10, 8, 24, sse4); +mc_rep_funcs(pel_pixels,10, 8, 16, sse4); +mc_rep_funcs(pel_pixels,10, 4, 12, sse4); + +mc_rep_funcs(epel_h, 8, 16, 64, sse4); +mc_rep_funcs(epel_h, 8, 16, 48, sse4); +mc_rep_funcs(epel_h, 8, 16, 32, sse4); +mc_rep_funcs(epel_h, 8, 8, 24, sse4); +mc_rep_funcs(epel_h,10, 8, 64, sse4); +mc_rep_funcs(epel_h,10, 8, 48, sse4); +mc_rep_funcs(epel_h,10, 8, 32, sse4); +mc_rep_funcs(epel_h,10, 8, 24, sse4); +mc_rep_funcs(epel_h,10, 8, 16, sse4); +mc_rep_funcs(epel_h,10, 4, 12, sse4); +mc_rep_funcs(epel_v, 8, 16, 64, sse4); +mc_rep_funcs(epel_v, 8, 16, 48, sse4); +mc_rep_funcs(epel_v, 8, 16, 32, sse4); +mc_rep_funcs(epel_v, 8, 8, 24, sse4); +mc_rep_funcs(epel_v,10, 8, 64, sse4); +mc_rep_funcs(epel_v,10, 8, 48, sse4); +mc_rep_funcs(epel_v,10, 8, 32, sse4); +mc_rep_funcs(epel_v,10, 8, 24, sse4); +mc_rep_funcs(epel_v,10, 8, 16, sse4); +mc_rep_funcs(epel_v,10, 4, 12, sse4); +mc_rep_funcs(epel_hv, 8, 8, 64, sse4); +mc_rep_funcs(epel_hv, 8, 8, 48, sse4); +mc_rep_funcs(epel_hv, 8, 8, 32, sse4); +mc_rep_funcs(epel_hv, 8, 8, 24, sse4); +mc_rep_funcs(epel_hv, 8, 8, 16, sse4); +mc_rep_funcs(epel_hv, 8, 4, 12, sse4); +mc_rep_funcs(epel_hv,10, 8, 64, sse4); +mc_rep_funcs(epel_hv,10, 8, 48, sse4); +mc_rep_funcs(epel_hv,10, 8, 32, sse4); +mc_rep_funcs(epel_hv,10, 8, 24, sse4); +mc_rep_funcs(epel_hv,10, 8, 16, sse4); +mc_rep_funcs(epel_hv,10, 4, 12, sse4); + +mc_rep_funcs(qpel_h, 8, 16, 64, sse4); +mc_rep_funcs(qpel_h, 8, 16, 48, sse4); +mc_rep_funcs(qpel_h, 8, 16, 32, sse4); +mc_rep_funcs(qpel_h, 8, 8, 24, sse4); +mc_rep_funcs(qpel_h,10, 8, 64, sse4); +mc_rep_funcs(qpel_h,10, 8, 48, sse4); +mc_rep_funcs(qpel_h,10, 8, 32, sse4); +mc_rep_funcs(qpel_h,10, 8, 24, sse4); +mc_rep_funcs(qpel_h,10, 8, 16, sse4); +mc_rep_funcs(qpel_h,10, 4, 12, sse4); +mc_rep_funcs(qpel_v, 8, 16, 64, sse4); +mc_rep_funcs(qpel_v, 8, 16, 48, sse4); +mc_rep_funcs(qpel_v, 8, 16, 32, sse4); +mc_rep_funcs(qpel_v, 8, 8, 24, sse4); +mc_rep_funcs(qpel_v,10, 8, 64, sse4); +mc_rep_funcs(qpel_v,10, 8, 48, sse4); +mc_rep_funcs(qpel_v,10, 8, 32, sse4); +mc_rep_funcs(qpel_v,10, 8, 24, sse4); +mc_rep_funcs(qpel_v,10, 8, 16, sse4); +mc_rep_funcs(qpel_v,10, 4, 12, sse4); +mc_rep_funcs(qpel_hv, 8, 8, 64, sse4); +mc_rep_funcs(qpel_hv, 8, 8, 48, sse4); +mc_rep_funcs(qpel_hv, 8, 8, 32, sse4); +mc_rep_funcs(qpel_hv, 8, 8, 24, sse4); +mc_rep_funcs(qpel_hv, 8, 8, 16, sse4); +mc_rep_funcs(qpel_hv, 8, 4, 12, sse4); +mc_rep_funcs(qpel_hv,10, 8, 64, sse4); +mc_rep_funcs(qpel_hv,10, 8, 48, sse4); +mc_rep_funcs(qpel_hv,10, 8, 32, sse4); +mc_rep_funcs(qpel_hv,10, 8, 24, sse4); +mc_rep_funcs(qpel_hv,10, 8, 16, sse4); +mc_rep_funcs(qpel_hv,10, 4, 12, sse4); + +#define mc_rep_uni_w(bitd, step, W, opt) \ +void ff_hevc_put_hevc_uni_w##W##_##bitd##_##opt(uint8_t *_dst, ptrdiff_t dststride, int16_t *_src, ptrdiff_t _srcstride,\ + int height, int denom, int _wx, int _ox) \ +{ \ + int i; \ + int16_t *src; \ + uint8_t *dst; \ + for (i = 0; i < W; i += step) { \ + src= _src + i; \ + dst= _dst + (i * ((bitd + 7) / 8)); \ + ff_hevc_put_hevc_uni_w##step##_##bitd##_##opt(dst, dststride, src, _srcstride, \ + height, denom, _wx, _ox); \ + } \ +} + +mc_rep_uni_w(8, 6, 12, sse4); +mc_rep_uni_w(8, 8, 16, sse4); +mc_rep_uni_w(8, 8, 24, sse4); +mc_rep_uni_w(8, 8, 32, sse4); +mc_rep_uni_w(8, 8, 48, sse4); +mc_rep_uni_w(8, 8, 64, sse4); + +mc_rep_uni_w(10, 6, 12, sse4); +mc_rep_uni_w(10, 8, 16, sse4); +mc_rep_uni_w(10, 8, 24, sse4); +mc_rep_uni_w(10, 8, 32, sse4); +mc_rep_uni_w(10, 8, 48, sse4); +mc_rep_uni_w(10, 8, 64, sse4); + +#define mc_rep_bi_w(bitd, step, W, opt) \ +void ff_hevc_put_hevc_bi_w##W##_##bitd##_##opt(uint8_t *_dst, ptrdiff_t dststride, int16_t *_src, ptrdiff_t _srcstride, \ + int16_t *_src2, ptrdiff_t _src2stride, int height, \ + int denom, int _wx0, int _wx1, int _ox0, int _ox1) \ +{ \ + int i; \ + int16_t *src; \ + int16_t *src2; \ + uint8_t *dst; \ + for (i = 0; i < W; i += step) { \ + src = _src + i; \ + src2 = _src2 + i; \ + dst = _dst + (i * ((bitd + 7) / 8)); \ + ff_hevc_put_hevc_bi_w##step##_##bitd##_##opt(dst, dststride, src, _srcstride, src2, _src2stride, \ + height, denom, _wx0, _wx1, _ox0, _ox1); \ + } \ +} + +mc_rep_bi_w(8, 6, 12, sse4); +mc_rep_bi_w(8, 8, 16, sse4); +mc_rep_bi_w(8, 8, 24, sse4); +mc_rep_bi_w(8, 8, 32, sse4); +mc_rep_bi_w(8, 8, 48, sse4); +mc_rep_bi_w(8, 8, 64, sse4); + +mc_rep_bi_w(10, 6, 12, sse4); +mc_rep_bi_w(10, 8, 16, sse4); +mc_rep_bi_w(10, 8, 24, sse4); +mc_rep_bi_w(10, 8, 32, sse4); +mc_rep_bi_w(10, 8, 48, sse4); +mc_rep_bi_w(10, 8, 64, sse4); + +#define mc_uni_w_func(name, bitd, W, opt) \ +void ff_hevc_put_hevc_uni_w_##name##W##_##bitd##_##opt(uint8_t *_dst, ptrdiff_t _dststride, \ + uint8_t *_src, ptrdiff_t _srcstride, \ + int height, int denom, \ + int _wx, int _ox, \ + intptr_t mx, intptr_t my, int width) \ +{ \ + LOCAL_ALIGNED_16(int16_t, temp, [71 * 64]); \ + ff_hevc_put_hevc_##name##W##_##bitd##_##opt(temp, 64, _src, _srcstride, height, mx, my, width); \ + ff_hevc_put_hevc_uni_w##W##_##bitd##_##opt(_dst, _dststride, temp, 64, height, denom, _wx, _ox);\ +} + +#define mc_uni_w_funcs(name, bitd, opt) \ + mc_uni_w_func(name, bitd, 4, opt); \ + mc_uni_w_func(name, bitd, 8, opt); \ + mc_uni_w_func(name, bitd, 12, opt); \ + mc_uni_w_func(name, bitd, 16, opt); \ + mc_uni_w_func(name, bitd, 24, opt); \ + mc_uni_w_func(name, bitd, 32, opt); \ + mc_uni_w_func(name, bitd, 48, opt); \ + mc_uni_w_func(name, bitd, 64, opt) + +mc_uni_w_funcs(pel_pixels, 8, sse4); +mc_uni_w_func(pel_pixels, 8, 6, sse4); +mc_uni_w_funcs(epel_h, 8, sse4); +mc_uni_w_func(epel_h, 8, 6, sse4); +mc_uni_w_funcs(epel_v, 8, sse4); +mc_uni_w_func(epel_v, 8, 6, sse4); +mc_uni_w_funcs(epel_hv, 8, sse4); +mc_uni_w_func(epel_hv, 8, 6, sse4); +mc_uni_w_funcs(qpel_h, 8, sse4); +mc_uni_w_funcs(qpel_v, 8, sse4); +mc_uni_w_funcs(qpel_hv, 8, sse4); + +mc_uni_w_funcs(pel_pixels, 10, sse4); +mc_uni_w_func(pel_pixels, 10, 6, sse4); +mc_uni_w_funcs(epel_h, 10, sse4); +mc_uni_w_func(epel_h, 10, 6, sse4); +mc_uni_w_funcs(epel_v, 10, sse4); +mc_uni_w_func(epel_v, 10, 6, sse4); +mc_uni_w_funcs(epel_hv, 10, sse4); +mc_uni_w_func(epel_hv, 10, 6, sse4); +mc_uni_w_funcs(qpel_h, 10, sse4); +mc_uni_w_funcs(qpel_v, 10, sse4); +mc_uni_w_funcs(qpel_hv, 10, sse4); + + +#define mc_bi_w_func(name, bitd, W, opt) \ +void ff_hevc_put_hevc_bi_w_##name##W##_##bitd##_##opt(uint8_t *_dst, ptrdiff_t _dststride, \ + uint8_t *_src, ptrdiff_t _srcstride, \ + int16_t *_src2, ptrdiff_t _src2stride, \ + int height, int denom, \ + int _wx0, int _wx1, int _ox0, int _ox1, \ + intptr_t mx, intptr_t my, int width) \ +{ \ + LOCAL_ALIGNED_16(int16_t, temp, [71 * 64]); \ + ff_hevc_put_hevc_##name##W##_##bitd##_##opt(temp, 64, _src, _srcstride, height, mx, my, width); \ + ff_hevc_put_hevc_bi_w##W##_##bitd##_##opt(_dst, _dststride, temp, 64, _src2, _src2stride, \ + height, denom, _wx0, _wx1, _ox0, _ox1); \ +} + +#define mc_bi_w_funcs(name, bitd, opt) \ + mc_bi_w_func(name, bitd, 4, opt); \ + mc_bi_w_func(name, bitd, 8, opt); \ + mc_bi_w_func(name, bitd, 12, opt); \ + mc_bi_w_func(name, bitd, 16, opt); \ + mc_bi_w_func(name, bitd, 24, opt); \ + mc_bi_w_func(name, bitd, 32, opt); \ + mc_bi_w_func(name, bitd, 48, opt); \ + mc_bi_w_func(name, bitd, 64, opt) + +mc_bi_w_funcs(pel_pixels, 8, sse4); +mc_bi_w_func(pel_pixels, 8, 6, sse4); +mc_bi_w_funcs(epel_h, 8, sse4); +mc_bi_w_func(epel_h, 8, 6, sse4); +mc_bi_w_funcs(epel_v, 8, sse4); +mc_bi_w_func(epel_v, 8, 6, sse4); +mc_bi_w_funcs(epel_hv, 8, sse4); +mc_bi_w_func(epel_hv, 8, 6, sse4); +mc_bi_w_funcs(qpel_h, 8, sse4); +mc_bi_w_funcs(qpel_v, 8, sse4); +mc_bi_w_funcs(qpel_hv, 8, sse4); + +mc_bi_w_funcs(pel_pixels, 10, sse4); +mc_bi_w_func(pel_pixels, 10, 6, sse4); +mc_bi_w_funcs(epel_h, 10, sse4); +mc_bi_w_func(epel_h, 10, 6, sse4); +mc_bi_w_funcs(epel_v, 10, sse4); +mc_bi_w_func(epel_v, 10, 6, sse4); +mc_bi_w_funcs(epel_hv, 10, sse4); +mc_bi_w_func(epel_hv, 10, 6, sse4); +mc_bi_w_funcs(qpel_h, 10, sse4); +mc_bi_w_funcs(qpel_v, 10, sse4); +mc_bi_w_funcs(qpel_hv, 10, sse4); + +#endif //ARCH_X86_64 && HAVE_SSE4_EXTERNAL + + +#define EPEL_LINKS(pointer, my, mx, fname, bitd, opt ) \ + PEL_LINK(pointer, 1, my , mx , fname##4 , bitd, opt ); \ + PEL_LINK(pointer, 2, my , mx , fname##6 , bitd, opt ); \ + PEL_LINK(pointer, 3, my , mx , fname##8 , bitd, opt ); \ + PEL_LINK(pointer, 4, my , mx , fname##12, bitd, opt ); \ + PEL_LINK(pointer, 5, my , mx , fname##16, bitd, opt ); \ + PEL_LINK(pointer, 6, my , mx , fname##24, bitd, opt ); \ + PEL_LINK(pointer, 7, my , mx , fname##32, bitd, opt ); \ + PEL_LINK(pointer, 8, my , mx , fname##48, bitd, opt ); \ + PEL_LINK(pointer, 9, my , mx , fname##64, bitd, opt ) +#define QPEL_LINKS(pointer, my, mx, fname, bitd, opt) \ + PEL_LINK(pointer, 1, my , mx , fname##4 , bitd, opt ); \ + PEL_LINK(pointer, 3, my , mx , fname##8 , bitd, opt ); \ + PEL_LINK(pointer, 4, my , mx , fname##12, bitd, opt ); \ + PEL_LINK(pointer, 5, my , mx , fname##16, bitd, opt ); \ + PEL_LINK(pointer, 6, my , mx , fname##24, bitd, opt ); \ + PEL_LINK(pointer, 7, my , mx , fname##32, bitd, opt ); \ + PEL_LINK(pointer, 8, my , mx , fname##48, bitd, opt ); \ + PEL_LINK(pointer, 9, my , mx , fname##64, bitd, opt ) + + +void ff_hevcdsp_init_x86(HEVCDSPContext *c, const int bit_depth) +{ + int mm_flags = av_get_cpu_flags(); + + if (bit_depth == 8) { + if (EXTERNAL_MMXEXT(mm_flags)) { + c->transform_dc_add[0] = ff_hevc_idct4_dc_add_8_mmxext; + c->transform_dc_add[1] = ff_hevc_idct8_dc_add_8_mmxext; + + } + if (EXTERNAL_SSE2(mm_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; + if (ARCH_X86_64) { + c->hevc_v_loop_filter_luma = ff_hevc_v_loop_filter_luma_8_sse2; + c->hevc_h_loop_filter_luma = ff_hevc_h_loop_filter_luma_8_sse2; + } + + c->transform_dc_add[2] = ff_hevc_idct16_dc_add_8_sse2; + c->transform_dc_add[3] = ff_hevc_idct32_dc_add_8_sse2; + } + if (EXTERNAL_SSSE3(mm_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_SSE4(mm_flags) && ARCH_X86_64) { + + EPEL_LINKS(c->put_hevc_epel, 0, 0, pel_pixels, 8, sse4); + EPEL_LINKS(c->put_hevc_epel, 0, 1, epel_h, 8, sse4); + EPEL_LINKS(c->put_hevc_epel, 1, 0, epel_v, 8, sse4); + EPEL_LINKS(c->put_hevc_epel, 1, 1, epel_hv, 8, sse4); + + QPEL_LINKS(c->put_hevc_qpel, 0, 0, pel_pixels, 8, sse4); + QPEL_LINKS(c->put_hevc_qpel, 0, 1, qpel_h, 8, sse4); + QPEL_LINKS(c->put_hevc_qpel, 1, 0, qpel_v, 8, sse4); + QPEL_LINKS(c->put_hevc_qpel, 1, 1, qpel_hv, 8, sse4); + } + if (EXTERNAL_AVX2(mm_flags)) { + c->transform_dc_add[3] = ff_hevc_idct32_dc_add_8_avx2; + } + } else if (bit_depth == 10) { + if (EXTERNAL_MMXEXT(mm_flags)) { + c->transform_dc_add[0] = ff_hevc_idct4_dc_add_10_mmxext; + + } + if (EXTERNAL_SSE2(mm_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; + if (ARCH_X86_64) { + c->hevc_v_loop_filter_luma = ff_hevc_v_loop_filter_luma_10_sse2; + c->hevc_h_loop_filter_luma = ff_hevc_h_loop_filter_luma_10_sse2; + } + + c->transform_dc_add[1] = ff_hevc_idct8_dc_add_10_sse2; + c->transform_dc_add[2] = ff_hevc_idct16_dc_add_10_sse2; + c->transform_dc_add[3] = ff_hevc_idct32_dc_add_10_sse2; + } + if (EXTERNAL_SSSE3(mm_flags) && ARCH_X86_64) { + 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(mm_flags) && ARCH_X86_64) { + + EPEL_LINKS(c->put_hevc_epel, 0, 0, pel_pixels, 10, sse4); + EPEL_LINKS(c->put_hevc_epel, 0, 1, epel_h, 10, sse4); + EPEL_LINKS(c->put_hevc_epel, 1, 0, epel_v, 10, sse4); + EPEL_LINKS(c->put_hevc_epel, 1, 1, epel_hv, 10, sse4); + + QPEL_LINKS(c->put_hevc_qpel, 0, 0, pel_pixels, 10, sse4); + QPEL_LINKS(c->put_hevc_qpel, 0, 1, qpel_h, 10, sse4); + QPEL_LINKS(c->put_hevc_qpel, 1, 0, qpel_v, 10, sse4); + QPEL_LINKS(c->put_hevc_qpel, 1, 1, qpel_hv, 10, sse4); + } + if (EXTERNAL_AVX(mm_flags)) { + c->transform_dc_add[1] = ff_hevc_idct8_dc_add_10_avx; + c->transform_dc_add[2] = ff_hevc_idct16_dc_add_10_avx; + c->transform_dc_add[3] = ff_hevc_idct32_dc_add_10_avx; + } + if (EXTERNAL_AVX2(mm_flags)) { + c->transform_dc_add[2] = ff_hevc_idct16_dc_add_10_avx2; + c->transform_dc_add[3] = ff_hevc_idct32_dc_add_10_avx2; + + } + } +} diff --git a/libavcodec/x86/hpeldsp.asm b/libavcodec/x86/hpeldsp.asm index 4eaba6eac..a702b8bc3 100644 --- a/libavcodec/x86/hpeldsp.asm +++ b/libavcodec/x86/hpeldsp.asm @@ -6,7 +6,7 @@ ;* Copyright (c) 2002 Zdenek Kabelac ;* Copyright (c) 2013 Daniel Kang ;* -;* MMX optimized hpel functions +;* SIMD-optimized halfpel functions ;* ;* This file is part of FFmpeg. ;* @@ -29,26 +29,48 @@ SECTION_RODATA cextern pb_1 +cextern pw_2 +pw_8192: times 8 dw (1<<13) +pb_interleave16: db 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 +pb_interleave8: db 0, 4, 1, 5, 2, 6, 3, 7 SECTION_TEXT -; put_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +; void ff_put_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) %macro PUT_PIXELS8_X2 0 +%if cpuflag(sse2) +cglobal put_pixels16_x2, 4,5,4 +%else cglobal put_pixels8_x2, 4,5 +%endif lea r4, [r2*2] .loop: - mova m0, [r1] - mova m1, [r1+r2] - PAVGB m0, [r1+1] - PAVGB m1, [r1+r2+1] + movu m0, [r1+1] + movu m1, [r1+r2+1] +%if cpuflag(sse2) + movu m2, [r1] + movu m3, [r1+r2] + pavgb m0, m2 + pavgb m1, m3 +%else + PAVGB m0, [r1] + PAVGB m1, [r1+r2] +%endif mova [r0], m0 mova [r0+r2], m1 add r1, r4 add r0, r4 - mova m0, [r1] - mova m1, [r1+r2] - PAVGB m0, [r1+1] - PAVGB m1, [r1+r2+1] + movu m0, [r1+1] + movu m1, [r1+r2+1] +%if cpuflag(sse2) + movu m2, [r1] + movu m3, [r1+r2] + pavgb m0, m2 + pavgb m1, m3 +%else + PAVGB m0, [r1] + PAVGB m1, [r1+r2] +%endif add r1, r4 mova [r0], m0 mova [r0+r2], m1 @@ -64,7 +86,7 @@ INIT_MMX 3dnow PUT_PIXELS8_X2 -; put_pixels16_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +; void ff_put_pixels16_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) %macro PUT_PIXELS_16 0 cglobal put_pixels16_x2, 4,5 lea r4, [r2*2] @@ -106,9 +128,12 @@ INIT_MMX mmxext PUT_PIXELS_16 INIT_MMX 3dnow PUT_PIXELS_16 +; The 8_X2 macro can easily be used here +INIT_XMM sse2 +PUT_PIXELS8_X2 -; put_no_rnd_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +; void ff_put_no_rnd_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) %macro PUT_NO_RND_PIXELS8_X2 0 cglobal put_no_rnd_pixels8_x2, 4,5 mova m6, [pb_1] @@ -149,7 +174,7 @@ INIT_MMX 3dnow PUT_NO_RND_PIXELS8_X2 -; put_no_rnd_pixels8_x2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +; 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] @@ -196,22 +221,26 @@ INIT_MMX 3dnow PUT_NO_RND_PIXELS8_X2_EXACT -; put_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +; void ff_put_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) %macro PUT_PIXELS8_Y2 0 +%if cpuflag(sse2) +cglobal put_pixels16_y2, 4,5,3 +%else cglobal put_pixels8_y2, 4,5 +%endif lea r4, [r2*2] - mova m0, [r1] + movu m0, [r1] sub r0, r2 .loop: - mova m1, [r1+r2] - mova m2, [r1+r4] + movu m1, [r1+r2] + movu m2, [r1+r4] add r1, r4 PAVGB m0, m1 PAVGB m1, m2 mova [r0+r2], m0 mova [r0+r4], m1 - mova m1, [r1+r2] - mova m0, [r1+r4] + movu m1, [r1+r2] + movu m0, [r1+r4] add r0, r4 add r1, r4 PAVGB m2, m1 @@ -228,9 +257,12 @@ INIT_MMX mmxext PUT_PIXELS8_Y2 INIT_MMX 3dnow PUT_PIXELS8_Y2 +; actually, put_pixels16_y2_sse2 +INIT_XMM sse2 +PUT_PIXELS8_Y2 -; put_no_rnd_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +; void ff_put_no_rnd_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) %macro PUT_NO_RND_PIXELS8_Y2 0 cglobal put_no_rnd_pixels8_y2, 4,5 mova m6, [pb_1] @@ -267,7 +299,7 @@ INIT_MMX 3dnow PUT_NO_RND_PIXELS8_Y2 -; put_no_rnd_pixels8_y2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +; 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] @@ -309,7 +341,7 @@ INIT_MMX 3dnow PUT_NO_RND_PIXELS8_Y2_EXACT -; avg_pixels8(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +; 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 lea r4, [r2*2] @@ -339,28 +371,50 @@ INIT_MMX 3dnow AVG_PIXELS8 -; avg_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +; void ff_avg_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) %macro AVG_PIXELS8_X2 0 +%if cpuflag(sse2) +cglobal avg_pixels16_x2, 4,5,4 +%else cglobal avg_pixels8_x2, 4,5 +%endif lea r4, [r2*2] +%if notcpuflag(mmxext) + pcmpeqd m5, m5 + paddb m5, m5 +%endif .loop: - mova m0, [r1] - mova m2, [r1+r2] - PAVGB m0, [r1+1] - PAVGB m2, [r1+r2+1] - PAVGB m0, [r0] - PAVGB m2, [r0+r2] + movu m0, [r1] + movu m2, [r1+r2] +%if cpuflag(sse2) + movu m1, [r1+1] + movu m3, [r1+r2+1] + pavgb m0, m1 + pavgb m2, m3 +%else + PAVGB m0, [r1+1], m3, m5 + PAVGB m2, [r1+r2+1], m4, m5 +%endif + PAVGB m0, [r0], m3, m5 + PAVGB m2, [r0+r2], m4, m5 add r1, r4 mova [r0], m0 mova [r0+r2], m2 - mova m0, [r1] - mova m2, [r1+r2] - PAVGB m0, [r1+1] - PAVGB m2, [r1+r2+1] + movu m0, [r1] + movu m2, [r1+r2] +%if cpuflag(sse2) + movu m1, [r1+1] + movu m3, [r1+r2+1] + pavgb m0, m1 + pavgb m2, m3 +%else + PAVGB m0, [r1+1], m3, m5 + PAVGB m2, [r1+r2+1], m4, m5 +%endif add r0, r4 add r1, r4 - PAVGB m0, [r0] - PAVGB m2, [r0+r2] + PAVGB m0, [r0], m3, m5 + PAVGB m2, [r0+r2], m4, m5 mova [r0], m0 mova [r0+r2], m2 add r0, r4 @@ -369,40 +423,45 @@ cglobal avg_pixels8_x2, 4,5 REP_RET %endmacro +INIT_MMX mmx +AVG_PIXELS8_X2 INIT_MMX mmxext AVG_PIXELS8_X2 INIT_MMX 3dnow AVG_PIXELS8_X2 +; actually avg_pixels16_x2 +INIT_XMM sse2 +AVG_PIXELS8_X2 -; avg_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +; void ff_avg_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) %macro AVG_PIXELS8_Y2 0 +%if cpuflag(sse2) +cglobal avg_pixels16_y2, 4,5,3 +%else cglobal avg_pixels8_y2, 4,5 +%endif lea r4, [r2*2] - mova m0, [r1] + movu m0, [r1] sub r0, r2 .loop: - mova m1, [r1+r2] - mova m2, [r1+r4] + movu m1, [r1+r2] + movu m2, [r1+r4] add r1, r4 PAVGB m0, m1 PAVGB m1, m2 - mova m3, [r0+r2] - mova m4, [r0+r4] - PAVGB m0, m3 - PAVGB m1, m4 + PAVGB m0, [r0+r2] + PAVGB m1, [r0+r4] mova [r0+r2], m0 mova [r0+r4], m1 - mova m1, [r1+r2] - mova m0, [r1+r4] + movu m1, [r1+r2] + movu m0, [r1+r4] PAVGB m2, m1 PAVGB m1, m0 add r0, r4 add r1, r4 - mova m3, [r0+r2] - mova m4, [r0+r4] - PAVGB m2, m3 - PAVGB m1, m4 + PAVGB m2, [r0+r2] + PAVGB m1, [r0+r4] mova [r0+r2], m2 mova [r0+r4], m1 add r0, r4 @@ -415,11 +474,16 @@ INIT_MMX mmxext AVG_PIXELS8_Y2 INIT_MMX 3dnow AVG_PIXELS8_Y2 +; actually avg_pixels16_y2 +INIT_XMM sse2 +AVG_PIXELS8_Y2 -; avg_pixels8_xy2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -%macro AVG_PIXELS8_XY2 0 -cglobal avg_pixels8_xy2, 4,5 +; void ff_avg_pixels8_xy2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +; Note this is not correctly rounded, and is therefore used for +; not-bitexact output +%macro AVG_APPROX_PIXELS8_XY2 0 +cglobal avg_approx_pixels8_xy2, 4,5 mova m6, [pb_1] lea r4, [r2*2] mova m0, [r1] @@ -456,6 +520,160 @@ cglobal avg_pixels8_xy2, 4,5 %endmacro INIT_MMX mmxext -AVG_PIXELS8_XY2 +AVG_APPROX_PIXELS8_XY2 INIT_MMX 3dnow -AVG_PIXELS8_XY2 +AVG_APPROX_PIXELS8_XY2 + + +; void ff_avg_pixels16_xy2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro SET_PIXELS_XY2 1 +%if cpuflag(sse2) +cglobal %1_pixels16_xy2, 4,5,8 +%else +cglobal %1_pixels8_xy2, 4,5 +%endif + pxor m7, m7 + mova m6, [pw_2] + movu m0, [r1] + movu m4, [r1+1] + mova m1, m0 + mova m5, m4 + punpcklbw m0, m7 + punpcklbw m4, m7 + punpckhbw m1, m7 + punpckhbw m5, m7 + paddusw m4, m0 + paddusw m5, m1 + xor r4, r4 + add r1, r2 +.loop: + movu m0, [r1+r4] + movu m2, [r1+r4+1] + mova m1, m0 + mova m3, m2 + punpcklbw m0, m7 + punpcklbw m2, m7 + punpckhbw m1, m7 + punpckhbw m3, m7 + paddusw m0, m2 + paddusw m1, m3 + paddusw m4, m6 + paddusw m5, m6 + paddusw m4, m0 + paddusw m5, m1 + psrlw m4, 2 + psrlw m5, 2 +%ifidn %1, avg + mova m3, [r0+r4] + packuswb m4, m5 + PAVGB m4, m3 +%else + packuswb m4, m5 +%endif + mova [r0+r4], m4 + add r4, r2 + + movu m2, [r1+r4] + movu m4, [r1+r4+1] + mova m3, m2 + mova m5, m4 + punpcklbw m2, m7 + punpcklbw m4, m7 + punpckhbw m3, m7 + punpckhbw m5, m7 + paddusw m4, m2 + paddusw m5, m3 + paddusw m0, m6 + paddusw m1, m6 + paddusw m0, m4 + paddusw m1, m5 + psrlw m0, 2 + psrlw m1, 2 +%ifidn %1, avg + mova m3, [r0+r4] + packuswb m0, m1 + PAVGB m0, m3 +%else + packuswb m0, m1 +%endif + mova [r0+r4], m0 + add r4, r2 + sub r3d, 2 + jnz .loop + REP_RET +%endmacro + +INIT_MMX mmxext +SET_PIXELS_XY2 avg +INIT_MMX 3dnow +SET_PIXELS_XY2 avg +INIT_XMM sse2 +SET_PIXELS_XY2 put +SET_PIXELS_XY2 avg + +%macro SSSE3_PIXELS_XY2 1-2 +%if %0 == 2 ; sse2 +cglobal %1_pixels16_xy2, 4,5,%2 + mova m4, [pb_interleave16] +%else +cglobal %1_pixels8_xy2, 4,5 + mova m4, [pb_interleave8] +%endif + mova m5, [pb_1] + movu m0, [r1] + movu m1, [r1+1] + pmaddubsw m0, m5 + pmaddubsw m1, m5 + xor r4, r4 + add r1, r2 +.loop: + movu m2, [r1+r4] + movu m3, [r1+r4+1] + pmaddubsw m2, m5 + pmaddubsw m3, m5 + paddusw m0, m2 + paddusw m1, m3 + pmulhrsw m0, [pw_8192] + pmulhrsw m1, [pw_8192] +%ifidn %1, avg + mova m6, [r0+r4] + packuswb m0, m1 + pshufb m0, m4 + pavgb m0, m6 +%else + packuswb m0, m1 + pshufb m0, m4 +%endif + mova [r0+r4], m0 + add r4, r2 + + movu m0, [r1+r4] + movu m1, [r1+r4+1] + pmaddubsw m0, m5 + pmaddubsw m1, m5 + paddusw m2, m0 + paddusw m3, m1 + pmulhrsw m2, [pw_8192] + pmulhrsw m3, [pw_8192] +%ifidn %1, avg + mova m6, [r0+r4] + packuswb m2, m3 + pshufb m2, m4 + pavgb m2, m6 +%else + packuswb m2, m3 + pshufb m2, m4 +%endif + mova [r0+r4], m2 + add r4, r2 + sub r3d, 2 + jnz .loop + REP_RET +%endmacro + +INIT_MMX ssse3 +SSSE3_PIXELS_XY2 put +SSSE3_PIXELS_XY2 avg +INIT_XMM ssse3 +SSSE3_PIXELS_XY2 put, 6 +SSSE3_PIXELS_XY2 avg, 7 diff --git a/libavcodec/x86/hpeldsp.h b/libavcodec/x86/hpeldsp.h new file mode 100644 index 000000000..5fae990a4 --- /dev/null +++ b/libavcodec/x86/hpeldsp.h @@ -0,0 +1,53 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_X86_HPELDSP_H +#define AVCODEC_X86_HPELDSP_H + +#include +#include + +void ff_avg_pixels8_x2_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); + +void ff_avg_pixels8_xy2_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels8_xy2_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels8_xy2_ssse3(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); + +void ff_avg_pixels16_xy2_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels16_xy2_sse2(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels16_xy2_ssse3(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); + +void ff_put_pixels8_xy2_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels8_xy2_ssse3(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_xy2_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_xy2_sse2(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_xy2_ssse3(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); + +#endif /* AVCODEC_X86_HPELDSP_H */ diff --git a/libavcodec/x86/hpeldsp_init.c b/libavcodec/x86/hpeldsp_init.c index 385f01b4b..bcae22fa4 100644 --- a/libavcodec/x86/hpeldsp_init.c +++ b/libavcodec/x86/hpeldsp_init.c @@ -1,5 +1,5 @@ /* - * MMX optimized DSP utils + * SIMD-optimized halfpel functions * Copyright (c) 2000, 2001 Fabrice Bellard * Copyright (c) 2002-2004 Michael Niedermayer * @@ -26,8 +26,11 @@ #include "libavutil/cpu.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" +#include "libavcodec/avcodec.h" #include "libavcodec/hpeldsp.h" -#include "dsputil_x86.h" +#include "libavcodec/pixels.h" +#include "fpel.h" +#include "hpeldsp.h" void ff_put_pixels8_x2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); @@ -37,6 +40,14 @@ void ff_put_pixels16_x2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_put_pixels16_x2_3dnow(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); +void ff_put_pixels16_x2_sse2(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels16_x2_sse2(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_y2_sse2(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels16_y2_sse2(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); void ff_put_no_rnd_pixels8_x2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_put_no_rnd_pixels8_x2_3dnow(uint8_t *block, const uint8_t *pixels, @@ -71,10 +82,12 @@ void ff_avg_pixels8_y2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_avg_pixels8_y2_3dnow(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_avg_pixels8_xy2_mmxext(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); void ff_avg_pixels8_xy2_3dnow(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); +void ff_avg_approx_pixels8_xy2_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_approx_pixels8_xy2_3dnow(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); #define avg_pixels8_mmx ff_avg_pixels8_mmx #define avg_pixels8_x2_mmx ff_avg_pixels8_x2_mmx @@ -108,11 +121,11 @@ void ff_avg_pixels8_xy2_3dnow(uint8_t *block, const uint8_t *pixels, #undef PAVGB #undef STATIC -PIXELS16(static, avg_no_rnd, , _y2, _mmx) -PIXELS16(static, put_no_rnd, , _y2, _mmx) +CALL_2X_PIXELS(avg_no_rnd_pixels16_y2_mmx, avg_no_rnd_pixels8_y2_mmx, 8) +CALL_2X_PIXELS(put_no_rnd_pixels16_y2_mmx, put_no_rnd_pixels8_y2_mmx, 8) -PIXELS16(static, avg_no_rnd, , _xy2, _mmx) -PIXELS16(static, put_no_rnd, , _xy2, _mmx) +CALL_2X_PIXELS(avg_no_rnd_pixels16_xy2_mmx, avg_no_rnd_pixels8_xy2_mmx, 8) +CALL_2X_PIXELS(put_no_rnd_pixels16_xy2_mmx, put_no_rnd_pixels8_xy2_mmx, 8) /***********************************/ /* MMX rounding */ @@ -124,52 +137,78 @@ PIXELS16(static, put_no_rnd, , _xy2, _mmx) #include "hpeldsp_rnd_template.c" +#undef DEF +#define DEF(x, y) ff_ ## x ## _ ## y ## _mmx +#define STATIC + +#include "rnd_template.c" + #undef DEF #undef SET_RND #undef PAVGBP #undef PAVGB -PIXELS16(static, avg, , _y2, _mmx) -PIXELS16(static, put, , _y2, _mmx) +CALL_2X_PIXELS(avg_pixels16_y2_mmx, avg_pixels8_y2_mmx, 8) +CALL_2X_PIXELS(put_pixels16_y2_mmx, put_pixels8_y2_mmx, 8) + +CALL_2X_PIXELS_EXPORT(ff_avg_pixels16_xy2_mmx, ff_avg_pixels8_xy2_mmx, 8) +CALL_2X_PIXELS_EXPORT(ff_put_pixels16_xy2_mmx, ff_put_pixels8_xy2_mmx, 8) #endif /* HAVE_INLINE_ASM */ #if HAVE_YASM -#define HPELDSP_AVG_PIXELS16(CPUEXT) \ - PIXELS16(static, put_no_rnd, ff_, _x2, CPUEXT) \ - PIXELS16(static, put, ff_, _y2, CPUEXT) \ - PIXELS16(static, put_no_rnd, ff_, _y2, CPUEXT) \ - PIXELS16(static, avg, ff_, , CPUEXT) \ - PIXELS16(static, avg, ff_, _x2, CPUEXT) \ - PIXELS16(static, avg, ff_, _y2, CPUEXT) \ - PIXELS16(static, avg, ff_, _xy2, CPUEXT) +#define HPELDSP_AVG_PIXELS16(CPUEXT) \ + CALL_2X_PIXELS(put_no_rnd_pixels16_x2 ## CPUEXT, ff_put_no_rnd_pixels8_x2 ## CPUEXT, 8) \ + CALL_2X_PIXELS(put_pixels16_y2 ## CPUEXT, ff_put_pixels8_y2 ## CPUEXT, 8) \ + CALL_2X_PIXELS(put_no_rnd_pixels16_y2 ## CPUEXT, ff_put_no_rnd_pixels8_y2 ## CPUEXT, 8) \ + CALL_2X_PIXELS(avg_pixels16 ## CPUEXT, ff_avg_pixels8 ## CPUEXT, 8) \ + CALL_2X_PIXELS(avg_pixels16_x2 ## CPUEXT, ff_avg_pixels8_x2 ## CPUEXT, 8) \ + CALL_2X_PIXELS(avg_pixels16_y2 ## CPUEXT, ff_avg_pixels8_y2 ## CPUEXT, 8) \ + CALL_2X_PIXELS(avg_pixels16_xy2 ## CPUEXT, ff_avg_pixels8_xy2 ## CPUEXT, 8) \ + CALL_2X_PIXELS(avg_approx_pixels16_xy2## CPUEXT, ff_avg_approx_pixels8_xy2## CPUEXT, 8) HPELDSP_AVG_PIXELS16(_3dnow) HPELDSP_AVG_PIXELS16(_mmxext) #endif /* HAVE_YASM */ +#define SET_HPEL_FUNCS_EXT(PFX, IDX, SIZE, CPU) \ + if (HAVE_MMX_EXTERNAL) \ + c->PFX ## _pixels_tab IDX [0] = PFX ## _pixels ## SIZE ## _ ## CPU; + +#if HAVE_MMX_INLINE #define SET_HPEL_FUNCS(PFX, IDX, SIZE, CPU) \ do { \ - c->PFX ## _pixels_tab IDX [0] = PFX ## _pixels ## SIZE ## _ ## CPU; \ + SET_HPEL_FUNCS_EXT(PFX, IDX, SIZE, CPU) \ c->PFX ## _pixels_tab IDX [1] = PFX ## _pixels ## SIZE ## _x2_ ## CPU; \ c->PFX ## _pixels_tab IDX [2] = PFX ## _pixels ## SIZE ## _y2_ ## CPU; \ c->PFX ## _pixels_tab IDX [3] = PFX ## _pixels ## SIZE ## _xy2_ ## CPU; \ } while (0) +#else +#define SET_HPEL_FUNCS(PFX, IDX, SIZE, CPU) \ + do { \ + SET_HPEL_FUNCS_EXT(PFX, IDX, SIZE, CPU) \ + } while (0) +#endif static void hpeldsp_init_mmx(HpelDSPContext *c, int flags, int cpu_flags) { -#if HAVE_MMX_INLINE SET_HPEL_FUNCS(put, [0], 16, mmx); SET_HPEL_FUNCS(put_no_rnd, [0], 16, mmx); SET_HPEL_FUNCS(avg, [0], 16, mmx); SET_HPEL_FUNCS(avg_no_rnd, , 16, mmx); SET_HPEL_FUNCS(put, [1], 8, mmx); SET_HPEL_FUNCS(put_no_rnd, [1], 8, mmx); - SET_HPEL_FUNCS(avg, [1], 8, mmx); -#endif /* HAVE_MMX_INLINE */ + if (HAVE_MMX_EXTERNAL) { + c->avg_pixels_tab[1][0] = ff_avg_pixels8_mmx; + c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_mmx; + } +#if HAVE_MMX_INLINE + c->avg_pixels_tab[1][2] = avg_pixels8_y2_mmx; + c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_mmx; +#endif } static void hpeldsp_init_mmxext(HpelDSPContext *c, int flags, int cpu_flags) @@ -181,6 +220,7 @@ static void hpeldsp_init_mmxext(HpelDSPContext *c, int flags, int cpu_flags) c->avg_pixels_tab[0][0] = avg_pixels16_mmxext; c->avg_pixels_tab[0][1] = avg_pixels16_x2_mmxext; c->avg_pixels_tab[0][2] = avg_pixels16_y2_mmxext; + c->avg_pixels_tab[0][3] = avg_pixels16_xy2_mmxext; c->put_pixels_tab[1][1] = ff_put_pixels8_x2_mmxext; c->put_pixels_tab[1][2] = ff_put_pixels8_y2_mmxext; @@ -188,6 +228,7 @@ static void hpeldsp_init_mmxext(HpelDSPContext *c, int flags, int cpu_flags) c->avg_pixels_tab[1][0] = ff_avg_pixels8_mmxext; c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_mmxext; c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_mmxext; + c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_mmxext; if (!(flags & CODEC_FLAG_BITEXACT)) { c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_mmxext; @@ -195,8 +236,8 @@ static void hpeldsp_init_mmxext(HpelDSPContext *c, int flags, int cpu_flags) c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_mmxext; c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_mmxext; - c->avg_pixels_tab[0][3] = avg_pixels16_xy2_mmxext; - c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_mmxext; + c->avg_pixels_tab[0][3] = avg_approx_pixels16_xy2_mmxext; + c->avg_pixels_tab[1][3] = ff_avg_approx_pixels8_xy2_mmxext; } if (flags & CODEC_FLAG_BITEXACT && CONFIG_VP3_DECODER) { @@ -215,6 +256,7 @@ static void hpeldsp_init_3dnow(HpelDSPContext *c, int flags, int cpu_flags) c->avg_pixels_tab[0][0] = avg_pixels16_3dnow; c->avg_pixels_tab[0][1] = avg_pixels16_x2_3dnow; c->avg_pixels_tab[0][2] = avg_pixels16_y2_3dnow; + c->avg_pixels_tab[0][3] = avg_pixels16_xy2_3dnow; c->put_pixels_tab[1][1] = ff_put_pixels8_x2_3dnow; c->put_pixels_tab[1][2] = ff_put_pixels8_y2_3dnow; @@ -222,6 +264,7 @@ static void hpeldsp_init_3dnow(HpelDSPContext *c, int flags, int cpu_flags) c->avg_pixels_tab[1][0] = ff_avg_pixels8_3dnow; c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_3dnow; c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_3dnow; + c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_3dnow; if (!(flags & CODEC_FLAG_BITEXACT)){ c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_3dnow; @@ -229,8 +272,8 @@ static void hpeldsp_init_3dnow(HpelDSPContext *c, int flags, int cpu_flags) c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_3dnow; c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_3dnow; - c->avg_pixels_tab[0][3] = avg_pixels16_xy2_3dnow; - c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_3dnow; + c->avg_pixels_tab[0][3] = avg_approx_pixels16_xy2_3dnow; + c->avg_pixels_tab[1][3] = ff_avg_approx_pixels8_xy2_3dnow; } if (flags & CODEC_FLAG_BITEXACT && CONFIG_VP3_DECODER) { @@ -247,11 +290,27 @@ static void hpeldsp_init_sse2(HpelDSPContext *c, int flags, int cpu_flags) // 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->put_pixels_tab[0][1] = ff_put_pixels16_x2_sse2; + c->put_pixels_tab[0][2] = ff_put_pixels16_y2_sse2; + c->put_pixels_tab[0][3] = ff_put_pixels16_xy2_sse2; c->avg_pixels_tab[0][0] = ff_avg_pixels16_sse2; + c->avg_pixels_tab[0][1] = ff_avg_pixels16_x2_sse2; + c->avg_pixels_tab[0][2] = ff_avg_pixels16_y2_sse2; + c->avg_pixels_tab[0][3] = ff_avg_pixels16_xy2_sse2; } #endif /* HAVE_SSE2_EXTERNAL */ } +static void hpeldsp_init_ssse3(HpelDSPContext *c, int flags, int cpu_flags) +{ +#if HAVE_SSSE3_EXTERNAL + c->put_pixels_tab[0][3] = ff_put_pixels16_xy2_ssse3; + c->avg_pixels_tab[0][3] = ff_avg_pixels16_xy2_ssse3; + c->put_pixels_tab[1][3] = ff_put_pixels8_xy2_ssse3; + c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_ssse3; +#endif +} + av_cold void ff_hpeldsp_init_x86(HpelDSPContext *c, int flags) { int cpu_flags = av_get_cpu_flags(); @@ -267,4 +326,7 @@ av_cold void ff_hpeldsp_init_x86(HpelDSPContext *c, int flags) if (EXTERNAL_SSE2(cpu_flags)) hpeldsp_init_sse2(c, flags, cpu_flags); + + if (EXTERNAL_SSSE3(cpu_flags)) + hpeldsp_init_ssse3(c, flags, cpu_flags); } diff --git a/libavcodec/x86/hpeldsp_mmx.c b/libavcodec/x86/hpeldsp_mmx.c deleted file mode 100644 index 50db36dc1..000000000 --- a/libavcodec/x86/hpeldsp_mmx.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * MMX-optimized avg/put pixel routines - * - * Copyright (c) 2001 Fabrice Bellard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include "config.h" -#include "dsputil_x86.h" - -#if HAVE_MMX_INLINE - -void ff_avg_pixels8_x2_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h) -{ - MOVQ_BFE(mm6); - JUMPALIGN(); - do { - __asm__ volatile( - "movq %1, %%mm0 \n\t" - "movq 1%1, %%mm1 \n\t" - "movq %0, %%mm3 \n\t" - PAVGB_MMX(%%mm0, %%mm1, %%mm2, %%mm6) - PAVGB_MMX(%%mm3, %%mm2, %%mm0, %%mm6) - "movq %%mm0, %0 \n\t" - :"+m"(*block) - :"m"(*pixels) - :"memory"); - pixels += line_size; - block += line_size; - } while (--h); -} - -#endif /* HAVE_MMX_INLINE */ diff --git a/libavcodec/x86/hpeldsp_rnd_template.c b/libavcodec/x86/hpeldsp_rnd_template.c index 94e06d820..c8a68fdf5 100644 --- a/libavcodec/x86/hpeldsp_rnd_template.c +++ b/libavcodec/x86/hpeldsp_rnd_template.c @@ -1,5 +1,5 @@ /* - * DSP utils mmx functions are compiled twice for rnd/no_rnd + * SIMD-optimized halfpel functions are compiled twice for rnd/no_rnd * Copyright (c) 2000, 2001 Fabrice Bellard * Copyright (c) 2003-2004 Michael Niedermayer * @@ -24,6 +24,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include + // put_pixels static void DEF(put, pixels8_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) { diff --git a/libavcodec/x86/huffyuvdsp.asm b/libavcodec/x86/huffyuvdsp.asm new file mode 100644 index 000000000..cc48556f9 --- /dev/null +++ b/libavcodec/x86/huffyuvdsp.asm @@ -0,0 +1,253 @@ +;****************************************************************************** +;* SIMD-optimized HuffYUV functions +;* Copyright (c) 2008 Loren Merritt +;* Copyright (c) 2014 Christophe Gisquet +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA +pb_f: times 16 db 15 +pb_zzzzzzzz77777777: times 8 db -1 +pb_7: times 8 db 7 +pb_zzzz3333zzzzbbbb: db -1,-1,-1,-1,3,3,3,3,-1,-1,-1,-1,11,11,11,11 +pb_zz11zz55zz99zzdd: db -1,-1,1,1,-1,-1,5,5,-1,-1,9,9,-1,-1,13,13 + +SECTION_TEXT + +; void ff_add_hfyu_median_pred_mmxext(uint8_t *dst, const uint8_t *top, +; const uint8_t *diff, int w, +; int *left, int *left_top) +%macro HFYU_MEDIAN 0 +cglobal add_hfyu_median_pred, 6,6,8, dst, top, diff, w, left, left_top + movu m0, [topq] + mova m2, m0 + movd m4, [left_topq] + LSHIFT m2, 1 + mova m1, m0 + por m4, m2 + movd m3, [leftq] + psubb m0, m4 ; t-tl + add dstq, wq + add topq, wq + add diffq, wq + neg wq + jmp .skip +.loop: + movu m4, [topq+wq] + mova m0, m4 + LSHIFT m4, 1 + por m4, m1 + mova m1, m0 ; t + psubb m0, m4 ; t-tl +.skip: + movu m2, [diffq+wq] +%assign i 0 +%rep mmsize + mova m4, m0 + paddb m4, m3 ; t-tl+l + mova m5, m3 + pmaxub m3, m1 + pminub m5, m1 + pminub m3, m4 + pmaxub m3, m5 ; median + paddb m3, m2 ; +residual +%if i==0 + mova m7, m3 + LSHIFT m7, mmsize-1 +%else + mova m6, m3 + RSHIFT m7, 1 + LSHIFT m6, mmsize-1 + por m7, m6 +%endif +%if i + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/huffyuvdsp.h" + +void ff_add_bytes_mmx(uint8_t *dst, uint8_t *src, intptr_t w); +void ff_add_bytes_sse2(uint8_t *dst, uint8_t *src, intptr_t w); + +void ff_add_hfyu_median_pred_mmxext(uint8_t *dst, const uint8_t *top, + const uint8_t *diff, intptr_t w, + int *left, int *left_top); +void ff_add_hfyu_median_pred_sse2(uint8_t *dst, const uint8_t *top, + const uint8_t *diff, intptr_t w, + int *left, int *left_top); + +int ff_add_hfyu_left_pred_ssse3(uint8_t *dst, const uint8_t *src, + intptr_t w, int left); +int ff_add_hfyu_left_pred_sse4(uint8_t *dst, const uint8_t *src, + intptr_t w, int left); + +void ff_add_hfyu_left_pred_bgr32_mmx(uint8_t *dst, const uint8_t *src, + intptr_t w, uint8_t *left); +void ff_add_hfyu_left_pred_bgr32_sse2(uint8_t *dst, const uint8_t *src, + intptr_t w, uint8_t *left); + +#if HAVE_INLINE_ASM && HAVE_7REGS && ARCH_X86_32 +static void add_hfyu_median_pred_cmov(uint8_t *dst, const uint8_t *top, + const uint8_t *diff, intptr_t w, + int *left, int *left_top) +{ + x86_reg w2 = -w; + x86_reg x; + int l = *left & 0xff; + int tl = *left_top & 0xff; + int t; + __asm__ volatile ( + "mov %7, %3 \n" + "1: \n" + "movzbl (%3, %4), %2 \n" + "mov %2, %k3 \n" + "sub %b1, %b3 \n" + "add %b0, %b3 \n" + "mov %2, %1 \n" + "cmp %0, %2 \n" + "cmovg %0, %2 \n" + "cmovg %1, %0 \n" + "cmp %k3, %0 \n" + "cmovg %k3, %0 \n" + "mov %7, %3 \n" + "cmp %2, %0 \n" + "cmovl %2, %0 \n" + "add (%6, %4), %b0 \n" + "mov %b0, (%5, %4) \n" + "inc %4 \n" + "jl 1b \n" + : "+&q"(l), "+&q"(tl), "=&r"(t), "=&q"(x), "+&r"(w2) + : "r"(dst + w), "r"(diff + w), "rm"(top + w) + ); + *left = l; + *left_top = tl; +} +#endif + +av_cold void ff_huffyuvdsp_init_x86(HuffYUVDSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + +#if HAVE_INLINE_ASM && HAVE_7REGS && ARCH_X86_32 + if (cpu_flags & AV_CPU_FLAG_CMOV) + c->add_hfyu_median_pred = add_hfyu_median_pred_cmov; +#endif + + if (ARCH_X86_32 && EXTERNAL_MMX(cpu_flags)) { + c->add_bytes = ff_add_bytes_mmx; + c->add_hfyu_left_pred_bgr32 = ff_add_hfyu_left_pred_bgr32_mmx; + } + + if (ARCH_X86_32 && EXTERNAL_MMXEXT(cpu_flags)) { + /* slower than cmov version on AMD */ + if (!(cpu_flags & AV_CPU_FLAG_3DNOW)) + c->add_hfyu_median_pred = ff_add_hfyu_median_pred_mmxext; + } + + if (EXTERNAL_SSE2(cpu_flags)) { + c->add_bytes = ff_add_bytes_sse2; + c->add_hfyu_median_pred = ff_add_hfyu_median_pred_sse2; + c->add_hfyu_left_pred_bgr32 = ff_add_hfyu_left_pred_bgr32_sse2; + } + + 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; + } +} diff --git a/libavcodec/x86/huffyuvencdsp_mmx.c b/libavcodec/x86/huffyuvencdsp_mmx.c new file mode 100644 index 000000000..63d8e3cc7 --- /dev/null +++ b/libavcodec/x86/huffyuvencdsp_mmx.c @@ -0,0 +1,114 @@ +/* + * SIMD-optimized HuffYUV encoding functions + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * MMX optimization by Nick Kurshev + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/huffyuvencdsp.h" +#include "libavcodec/mathops.h" + +#if HAVE_INLINE_ASM + +static void diff_bytes_mmx(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int w) +{ + x86_reg i = 0; + + if (w >= 16) + __asm__ volatile ( + "1: \n\t" + "movq (%2, %0), %%mm0 \n\t" + "movq (%1, %0), %%mm1 \n\t" + "psubb %%mm0, %%mm1 \n\t" + "movq %%mm1, (%3, %0) \n\t" + "movq 8(%2, %0), %%mm0 \n\t" + "movq 8(%1, %0), %%mm1 \n\t" + "psubb %%mm0, %%mm1 \n\t" + "movq %%mm1, 8(%3, %0) \n\t" + "add $16, %0 \n\t" + "cmp %4, %0 \n\t" + " jb 1b \n\t" + : "+r" (i) + : "r" (src1), "r" (src2), "r" (dst), "r" ((x86_reg) w - 15)); + + for (; i < w; i++) + dst[i + 0] = src1[i + 0] - src2[i + 0]; +} + +static void sub_hfyu_median_pred_mmxext(uint8_t *dst, const uint8_t *src1, + const uint8_t *src2, int w, + int *left, int *left_top) +{ + x86_reg i = 0; + uint8_t l, lt; + + __asm__ volatile ( + "movq (%1, %0), %%mm0 \n\t" // LT + "psllq $8, %%mm0 \n\t" + "1: \n\t" + "movq (%1, %0), %%mm1 \n\t" // T + "movq -1(%2, %0), %%mm2 \n\t" // L + "movq (%2, %0), %%mm3 \n\t" // X + "movq %%mm2, %%mm4 \n\t" // L + "psubb %%mm0, %%mm2 \n\t" + "paddb %%mm1, %%mm2 \n\t" // L + T - LT + "movq %%mm4, %%mm5 \n\t" // L + "pmaxub %%mm1, %%mm4 \n\t" // max(T, L) + "pminub %%mm5, %%mm1 \n\t" // min(T, L) + "pminub %%mm2, %%mm4 \n\t" + "pmaxub %%mm1, %%mm4 \n\t" + "psubb %%mm4, %%mm3 \n\t" // dst - pred + "movq %%mm3, (%3, %0) \n\t" + "add $8, %0 \n\t" + "movq -1(%1, %0), %%mm0 \n\t" // LT + "cmp %4, %0 \n\t" + " jb 1b \n\t" + : "+r" (i) + : "r" (src1), "r" (src2), "r" (dst), "r" ((x86_reg) w)); + + l = *left; + lt = *left_top; + + dst[0] = src2[0] - mid_pred(l, src1[0], (l + src1[0] - lt) & 0xFF); + + *left_top = src1[w - 1]; + *left = src2[w - 1]; +} + +#endif /* HAVE_INLINE_ASM */ + +av_cold void ff_huffyuvencdsp_init_x86(HuffYUVEncDSPContext *c) +{ +#if HAVE_INLINE_ASM + int cpu_flags = av_get_cpu_flags(); + + if (INLINE_MMX(cpu_flags)) { + c->diff_bytes = diff_bytes_mmx; + } + + if (INLINE_MMXEXT(cpu_flags)) { + c->sub_hfyu_median_pred = sub_hfyu_median_pred_mmxext; + } +#endif /* HAVE_INLINE_ASM */ +} diff --git a/libavcodec/x86/idct_mmx_xvid.c b/libavcodec/x86/idct_mmx_xvid.c index 4cd6de101..289120d3f 100644 --- a/libavcodec/x86/idct_mmx_xvid.c +++ b/libavcodec/x86/idct_mmx_xvid.c @@ -44,8 +44,8 @@ #include "config.h" #include "libavcodec/avcodec.h" #include "libavutil/mem.h" -#include "dsputil_x86.h" #include "idct_xvid.h" +#include "idctdsp.h" #if HAVE_MMX_INLINE diff --git a/libavcodec/x86/idct_sse2_xvid.c b/libavcodec/x86/idct_sse2_xvid.c index 4c5e74b98..ce2abe410 100644 --- a/libavcodec/x86/idct_sse2_xvid.c +++ b/libavcodec/x86/idct_sse2_xvid.c @@ -41,7 +41,7 @@ #include "libavutil/mem.h" #include "libavutil/x86/asm.h" #include "idct_xvid.h" -#include "dsputil_x86.h" +#include "idctdsp.h" #if HAVE_SSE2_INLINE @@ -147,7 +147,7 @@ DECLARE_ASM_CONST(16, int32_t, walkenIdctRounders)[] = { #endif -#define ROUND(x) "paddd "MANGLE(x) +#define ROUND(x) "paddd "x #define JZ(reg, to) \ "testl "reg","reg" \n\t" \ @@ -347,13 +347,13 @@ av_extern_inline void ff_idct_xvid_sse2(short *block) { __asm__ volatile( "movq "MANGLE(m127)", %%mm0 \n\t" - iMTX_MULT("(%0)", MANGLE(iTab1), ROUND(walkenIdctRounders), PUT_EVEN(ROW0)) - iMTX_MULT("1*16(%0)", MANGLE(iTab2), ROUND(walkenIdctRounders+1*16), PUT_ODD(ROW1)) - iMTX_MULT("2*16(%0)", MANGLE(iTab3), ROUND(walkenIdctRounders+2*16), PUT_EVEN(ROW2)) + iMTX_MULT("(%0)", MANGLE(iTab1), ROUND(MANGLE(walkenIdctRounders)), PUT_EVEN(ROW0)) + iMTX_MULT("1*16(%0)", MANGLE(iTab2), ROUND("1*16+"MANGLE(walkenIdctRounders)), PUT_ODD(ROW1)) + iMTX_MULT("2*16(%0)", MANGLE(iTab3), ROUND("2*16+"MANGLE(walkenIdctRounders)), 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)) + iMTX_MULT("3*16(%0)", MANGLE(iTab4), ROUND("3*16+"MANGLE(walkenIdctRounders)), 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)) @@ -368,20 +368,20 @@ av_extern_inline void ff_idct_xvid_sse2(short *block) "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)) + iMTX_MULT("5*16(%0)", MANGLE(iTab4), ROUND("4*16+"MANGLE(walkenIdctRounders)), PUT_ODD(ROW5)) JZ("%%edx", "1f") "4: \n\t" - iMTX_MULT("6*16(%0)", MANGLE(iTab3), ROUND(walkenIdctRounders+5*16), PUT_EVEN(ROW6)) + iMTX_MULT("6*16(%0)", MANGLE(iTab3), ROUND("5*16+"MANGLE(walkenIdctRounders)), PUT_EVEN(ROW6)) JZ("%%esi", "1f") "5: \n\t" - iMTX_MULT("7*16(%0)", MANGLE(iTab2), ROUND(walkenIdctRounders+5*16), PUT_ODD(ROW7)) + iMTX_MULT("7*16(%0)", MANGLE(iTab2), ROUND("5*16+"MANGLE(walkenIdctRounders)), PUT_ODD(ROW7)) #if ARCH_X86_32 iLLM_HEAD #endif iLLM_PASS("%0") "6: \n\t" : "+r"(block) - : + : NAMED_CONSTRAINTS_ARRAY(m127,iTab1,walkenIdctRounders,iTab2,iTab3,iTab4,tan3,tan1,tan2,sqrt2) : XMM_CLOBBERS("%xmm0" , "%xmm1" , "%xmm2" , "%xmm3" , "%xmm4" , "%xmm5" , "%xmm6" , "%xmm7" ,) #if ARCH_X86_64 diff --git a/libavcodec/x86/idctdsp.asm b/libavcodec/x86/idctdsp.asm new file mode 100644 index 000000000..44a1a6ef8 --- /dev/null +++ b/libavcodec/x86/idctdsp.asm @@ -0,0 +1,80 @@ +;****************************************************************************** +;* SIMD-optimized IDCT-related routines +;* Copyright (c) 2008 Loren Merritt +;* Copyright (c) 2003-2013 Michael Niedermayer +;* Copyright (c) 2013 Daniel Kang +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +cextern pb_80 + +SECTION_TEXT + +;-------------------------------------------------------------------------- +;void ff_put_signed_pixels_clamped(const int16_t *block, uint8_t *pixels, +; int line_size) +;-------------------------------------------------------------------------- + +%macro PUT_SIGNED_PIXELS_CLAMPED_HALF 1 + mova m1, [blockq+mmsize*0+%1] + mova m2, [blockq+mmsize*2+%1] +%if mmsize == 8 + mova m3, [blockq+mmsize*4+%1] + mova m4, [blockq+mmsize*6+%1] +%endif + packsswb m1, [blockq+mmsize*1+%1] + packsswb m2, [blockq+mmsize*3+%1] +%if mmsize == 8 + packsswb m3, [blockq+mmsize*5+%1] + packsswb m4, [blockq+mmsize*7+%1] +%endif + paddb m1, m0 + paddb m2, m0 +%if mmsize == 8 + paddb m3, m0 + paddb m4, m0 + movq [pixelsq+lsizeq*0], m1 + movq [pixelsq+lsizeq*1], m2 + movq [pixelsq+lsizeq*2], m3 + movq [pixelsq+lsize3q ], m4 +%else + movq [pixelsq+lsizeq*0], m1 + movhps [pixelsq+lsizeq*1], m1 + movq [pixelsq+lsizeq*2], m2 + movhps [pixelsq+lsize3q ], m2 +%endif +%endmacro + +%macro PUT_SIGNED_PIXELS_CLAMPED 1 +cglobal put_signed_pixels_clamped, 3, 4, %1, block, pixels, lsize, lsize3 + mova m0, [pb_80] + lea lsize3q, [lsizeq*3] + PUT_SIGNED_PIXELS_CLAMPED_HALF 0 + lea pixelsq, [pixelsq+lsizeq*4] + PUT_SIGNED_PIXELS_CLAMPED_HALF 64 + RET +%endmacro + +INIT_MMX mmx +PUT_SIGNED_PIXELS_CLAMPED 0 +INIT_XMM sse2 +PUT_SIGNED_PIXELS_CLAMPED 3 diff --git a/libavcodec/x86/idctdsp.h b/libavcodec/x86/idctdsp.h new file mode 100644 index 000000000..9b7177a58 --- /dev/null +++ b/libavcodec/x86/idctdsp.h @@ -0,0 +1,33 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_X86_IDCTDSP_H +#define AVCODEC_X86_IDCTDSP_H + +#include + +void ff_add_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, + int line_size); +void ff_put_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, + int line_size); +void ff_put_signed_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, + int line_size); +void ff_put_signed_pixels_clamped_sse2(const int16_t *block, uint8_t *pixels, + int line_size); + +#endif /* AVCODEC_X86_IDCTDSP_H */ diff --git a/libavcodec/x86/idctdsp_init.c b/libavcodec/x86/idctdsp_init.c new file mode 100644 index 000000000..b2332b2d4 --- /dev/null +++ b/libavcodec/x86/idctdsp_init.c @@ -0,0 +1,112 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/idctdsp.h" +#include "libavcodec/simple_idct.h" +#include "idct_xvid.h" +#include "idctdsp.h" + +/* Input permutation for the simple_idct_mmx */ +static const uint8_t simple_mmx_permutation[64] = { + 0x00, 0x08, 0x04, 0x09, 0x01, 0x0C, 0x05, 0x0D, + 0x10, 0x18, 0x14, 0x19, 0x11, 0x1C, 0x15, 0x1D, + 0x20, 0x28, 0x24, 0x29, 0x21, 0x2C, 0x25, 0x2D, + 0x12, 0x1A, 0x16, 0x1B, 0x13, 0x1E, 0x17, 0x1F, + 0x02, 0x0A, 0x06, 0x0B, 0x03, 0x0E, 0x07, 0x0F, + 0x30, 0x38, 0x34, 0x39, 0x31, 0x3C, 0x35, 0x3D, + 0x22, 0x2A, 0x26, 0x2B, 0x23, 0x2E, 0x27, 0x2F, + 0x32, 0x3A, 0x36, 0x3B, 0x33, 0x3E, 0x37, 0x3F, +}; + +static const uint8_t idct_sse2_row_perm[8] = { 0, 4, 1, 5, 2, 6, 3, 7 }; + +av_cold int ff_init_scantable_permutation_x86(uint8_t *idct_permutation, + int idct_permutation_type) +{ + int i; + + switch (idct_permutation_type) { + case FF_SIMPLE_IDCT_PERM: + for (i = 0; i < 64; i++) + idct_permutation[i] = simple_mmx_permutation[i]; + return 1; + case FF_SSE2_IDCT_PERM: + for (i = 0; i < 64; i++) + idct_permutation[i] = (i & 0x38) | idct_sse2_row_perm[i & 7]; + return 1; + } + + return 0; +} + +av_cold void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + + if (INLINE_MMX(cpu_flags)) { + c->put_pixels_clamped = ff_put_pixels_clamped_mmx; + c->add_pixels_clamped = ff_add_pixels_clamped_mmx; + + if (avctx->lowres == 0 && !high_bit_depth) { + switch (avctx->idct_algo) { + case FF_IDCT_AUTO: + case FF_IDCT_SIMPLEAUTO: + case FF_IDCT_SIMPLEMMX: + c->idct_put = ff_simple_idct_put_mmx; + c->idct_add = ff_simple_idct_add_mmx; + c->idct = ff_simple_idct_mmx; + c->idct_permutation_type = FF_SIMPLE_IDCT_PERM; + break; + case FF_IDCT_XVIDMMX: + c->idct_put = ff_idct_xvid_mmx_put; + c->idct_add = ff_idct_xvid_mmx_add; + c->idct = ff_idct_xvid_mmx; + break; + } + } + } + if (EXTERNAL_MMX(cpu_flags)) { + c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_mmx; + } + + if (INLINE_MMXEXT(cpu_flags)) { + if (!high_bit_depth && avctx->idct_algo == FF_IDCT_XVIDMMX && avctx->lowres == 0) { + c->idct_put = ff_idct_xvid_mmxext_put; + c->idct_add = ff_idct_xvid_mmxext_add; + c->idct = ff_idct_xvid_mmxext; + } + } + + if (INLINE_SSE2(cpu_flags)) { + if (!high_bit_depth && avctx->idct_algo == FF_IDCT_XVIDMMX && avctx->lowres == 0) { + c->idct_put = ff_idct_xvid_sse2_put; + c->idct_add = ff_idct_xvid_sse2_add; + c->idct = ff_idct_xvid_sse2; + c->idct_permutation_type = FF_SSE2_IDCT_PERM; + } + } + if (EXTERNAL_SSE2(cpu_flags)) { + c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_sse2; + } +} diff --git a/libavcodec/x86/idctdsp_mmx.c b/libavcodec/x86/idctdsp_mmx.c new file mode 100644 index 000000000..a72b9416b --- /dev/null +++ b/libavcodec/x86/idctdsp_mmx.c @@ -0,0 +1,133 @@ +/* + * SIMD-optimized IDCT-related routines + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * MMX optimization by Nick Kurshev + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "idctdsp.h" +#include "inline_asm.h" + +#if HAVE_INLINE_ASM + +void ff_put_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, + int line_size) +{ + const int16_t *p; + uint8_t *pix; + + /* read the pixels */ + p = block; + pix = pixels; + /* unrolled loop */ + __asm__ volatile ( + "movq (%3), %%mm0 \n\t" + "movq 8(%3), %%mm1 \n\t" + "movq 16(%3), %%mm2 \n\t" + "movq 24(%3), %%mm3 \n\t" + "movq 32(%3), %%mm4 \n\t" + "movq 40(%3), %%mm5 \n\t" + "movq 48(%3), %%mm6 \n\t" + "movq 56(%3), %%mm7 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "packuswb %%mm3, %%mm2 \n\t" + "packuswb %%mm5, %%mm4 \n\t" + "packuswb %%mm7, %%mm6 \n\t" + "movq %%mm0, (%0) \n\t" + "movq %%mm2, (%0, %1) \n\t" + "movq %%mm4, (%0, %1, 2) \n\t" + "movq %%mm6, (%0, %2) \n\t" + :: "r" (pix), "r" ((x86_reg) line_size), "r" ((x86_reg) line_size * 3), + "r" (p) + : "memory"); + pix += line_size * 4; + p += 32; + + // if here would be an exact copy of the code above + // compiler would generate some very strange code + // thus using "r" + __asm__ volatile ( + "movq (%3), %%mm0 \n\t" + "movq 8(%3), %%mm1 \n\t" + "movq 16(%3), %%mm2 \n\t" + "movq 24(%3), %%mm3 \n\t" + "movq 32(%3), %%mm4 \n\t" + "movq 40(%3), %%mm5 \n\t" + "movq 48(%3), %%mm6 \n\t" + "movq 56(%3), %%mm7 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "packuswb %%mm3, %%mm2 \n\t" + "packuswb %%mm5, %%mm4 \n\t" + "packuswb %%mm7, %%mm6 \n\t" + "movq %%mm0, (%0) \n\t" + "movq %%mm2, (%0, %1) \n\t" + "movq %%mm4, (%0, %1, 2) \n\t" + "movq %%mm6, (%0, %2) \n\t" + :: "r" (pix), "r" ((x86_reg) line_size), "r" ((x86_reg) line_size * 3), + "r" (p) + : "memory"); +} + +void ff_add_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, + int line_size) +{ + const int16_t *p; + uint8_t *pix; + int i; + + /* read the pixels */ + p = block; + pix = pixels; + MOVQ_ZERO(mm7); + i = 4; + do { + __asm__ volatile ( + "movq (%2), %%mm0 \n\t" + "movq 8(%2), %%mm1 \n\t" + "movq 16(%2), %%mm2 \n\t" + "movq 24(%2), %%mm3 \n\t" + "movq %0, %%mm4 \n\t" + "movq %1, %%mm6 \n\t" + "movq %%mm4, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddsw %%mm4, %%mm0 \n\t" + "paddsw %%mm5, %%mm1 \n\t" + "movq %%mm6, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm6 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddsw %%mm6, %%mm2 \n\t" + "paddsw %%mm5, %%mm3 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "packuswb %%mm3, %%mm2 \n\t" + "movq %%mm0, %0 \n\t" + "movq %%mm2, %1 \n\t" + : "+m" (*pix), "+m" (*(pix + line_size)) + : "r" (p) + : "memory"); + pix += line_size * 2; + p += 16; + } while (--i); +} + +#endif /* HAVE_INLINE_ASM */ diff --git a/libavcodec/x86/inline_asm.h b/libavcodec/x86/inline_asm.h new file mode 100644 index 000000000..c2f1bf0f9 --- /dev/null +++ b/libavcodec/x86/inline_asm.h @@ -0,0 +1,100 @@ +/* + * inline assembly helper macros + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_X86_INLINE_ASM_H +#define AVCODEC_X86_INLINE_ASM_H + +#include "constants.h" + +#define MOVQ_WONE(regd) \ + __asm__ volatile ( \ + "pcmpeqd %%" #regd ", %%" #regd " \n\t" \ + "psrlw $15, %%" #regd ::) + +#define JUMPALIGN() __asm__ volatile (".p2align 3"::) +#define MOVQ_ZERO(regd) __asm__ volatile ("pxor %%"#regd", %%"#regd ::) + +#define MOVQ_BFE(regd) \ + __asm__ volatile ( \ + "pcmpeqd %%"#regd", %%"#regd" \n\t" \ + "paddb %%"#regd", %%"#regd" \n\t" ::) + +#ifndef PIC +#define MOVQ_WTWO(regd) __asm__ volatile ("movq %0, %%"#regd" \n\t" :: "m"(ff_wtwo)) +#else +// for shared library it's better to use this way for accessing constants +// pcmpeqd -> -1 +#define MOVQ_WTWO(regd) \ + __asm__ volatile ( \ + "pcmpeqd %%"#regd", %%"#regd" \n\t" \ + "psrlw $15, %%"#regd" \n\t" \ + "psllw $1, %%"#regd" \n\t"::) + +#endif + +// using regr as temporary and for the output result +// first argument is unmodifed and second is trashed +// regfe is supposed to contain 0xfefefefefefefefe +#define PAVGB_MMX_NO_RND(rega, regb, regr, regfe) \ + "movq "#rega", "#regr" \n\t" \ + "pand "#regb", "#regr" \n\t" \ + "pxor "#rega", "#regb" \n\t" \ + "pand "#regfe", "#regb" \n\t" \ + "psrlq $1, "#regb" \n\t" \ + "paddb "#regb", "#regr" \n\t" + +#define PAVGB_MMX(rega, regb, regr, regfe) \ + "movq "#rega", "#regr" \n\t" \ + "por "#regb", "#regr" \n\t" \ + "pxor "#rega", "#regb" \n\t" \ + "pand "#regfe", "#regb" \n\t" \ + "psrlq $1, "#regb" \n\t" \ + "psubb "#regb", "#regr" \n\t" + +// mm6 is supposed to contain 0xfefefefefefefefe +#define PAVGBP_MMX_NO_RND(rega, regb, regr, regc, regd, regp) \ + "movq "#rega", "#regr" \n\t" \ + "movq "#regc", "#regp" \n\t" \ + "pand "#regb", "#regr" \n\t" \ + "pand "#regd", "#regp" \n\t" \ + "pxor "#rega", "#regb" \n\t" \ + "pxor "#regc", "#regd" \n\t" \ + "pand %%mm6, "#regb" \n\t" \ + "pand %%mm6, "#regd" \n\t" \ + "psrlq $1, "#regb" \n\t" \ + "psrlq $1, "#regd" \n\t" \ + "paddb "#regb", "#regr" \n\t" \ + "paddb "#regd", "#regp" \n\t" + +#define PAVGBP_MMX(rega, regb, regr, regc, regd, regp) \ + "movq "#rega", "#regr" \n\t" \ + "movq "#regc", "#regp" \n\t" \ + "por "#regb", "#regr" \n\t" \ + "por "#regd", "#regp" \n\t" \ + "pxor "#rega", "#regb" \n\t" \ + "pxor "#regc", "#regd" \n\t" \ + "pand %%mm6, "#regb" \n\t" \ + "pand %%mm6, "#regd" \n\t" \ + "psrlq $1, "#regd" \n\t" \ + "psrlq $1, "#regb" \n\t" \ + "psubb "#regb", "#regr" \n\t" \ + "psubb "#regd", "#regp" \n\t" + +#endif /* AVCODEC_X86_INLINE_ASM_H */ diff --git a/libavcodec/x86/lossless_audiodsp.asm b/libavcodec/x86/lossless_audiodsp.asm new file mode 100644 index 000000000..64b769f7d --- /dev/null +++ b/libavcodec/x86/lossless_audiodsp.asm @@ -0,0 +1,157 @@ +;****************************************************************************** +;* Copyright (c) 2008 Loren Merritt +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_TEXT + +%macro SCALARPRODUCT 0 +; int ff_scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, +; int order, int mul) +cglobal scalarproduct_and_madd_int16, 4,4,8, v1, v2, v3, order, mul + shl orderq, 1 + movd m7, mulm +%if mmsize == 16 + pshuflw m7, m7, 0 + punpcklqdq m7, m7 +%else + pshufw m7, m7, 0 +%endif + pxor m6, m6 + add v1q, orderq + add v2q, orderq + add v3q, orderq + neg orderq +.loop: + movu m0, [v2q + orderq] + movu m1, [v2q + orderq + mmsize] + mova m4, [v1q + orderq] + mova m5, [v1q + orderq + mmsize] + movu m2, [v3q + orderq] + movu m3, [v3q + orderq + mmsize] + pmaddwd m0, m4 + pmaddwd m1, m5 + pmullw m2, m7 + pmullw m3, m7 + paddd m6, m0 + paddd m6, m1 + paddw m2, m4 + paddw m3, m5 + mova [v1q + orderq], m2 + mova [v1q + orderq + mmsize], m3 + add orderq, mmsize*2 + jl .loop + HADDD m6, m0 + movd eax, m6 + RET +%endmacro + +INIT_MMX mmxext +SCALARPRODUCT +INIT_XMM sse2 +SCALARPRODUCT + +%macro SCALARPRODUCT_LOOP 1 +align 16 +.loop%1: + sub orderq, mmsize*2 +%if %1 + mova m1, m4 + mova m4, [v2q + orderq] + mova m0, [v2q + orderq + mmsize] + palignr m1, m0, %1 + palignr m0, m4, %1 + mova m3, m5 + mova m5, [v3q + orderq] + mova m2, [v3q + orderq + mmsize] + palignr m3, m2, %1 + palignr m2, m5, %1 +%else + mova m0, [v2q + orderq] + mova m1, [v2q + orderq + mmsize] + mova m2, [v3q + orderq] + mova m3, [v3q + orderq + mmsize] +%endif + %define t0 [v1q + orderq] + %define t1 [v1q + orderq + mmsize] +%if ARCH_X86_64 + mova m8, t0 + mova m9, t1 + %define t0 m8 + %define t1 m9 +%endif + pmaddwd m0, t0 + pmaddwd m1, t1 + pmullw m2, m7 + pmullw m3, m7 + paddw m2, t0 + paddw m3, t1 + paddd m6, m0 + paddd m6, m1 + mova [v1q + orderq], m2 + mova [v1q + orderq + mmsize], m3 + jg .loop%1 +%if %1 + jmp .end +%endif +%endmacro + +; int ff_scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, +; int order, int mul) +INIT_XMM ssse3 +cglobal scalarproduct_and_madd_int16, 4,5,10, v1, v2, v3, order, mul + shl orderq, 1 + movd m7, mulm + pshuflw m7, m7, 0 + punpcklqdq m7, m7 + pxor m6, m6 + mov r4d, v2d + and r4d, 15 + and v2q, ~15 + and v3q, ~15 + mova m4, [v2q + orderq] + mova m5, [v3q + orderq] + ; linear is faster than branch tree or jump table, because the branches taken are cyclic (i.e. predictable) + cmp r4d, 0 + je .loop0 + cmp r4d, 2 + je .loop2 + cmp r4d, 4 + je .loop4 + cmp r4d, 6 + je .loop6 + cmp r4d, 8 + je .loop8 + cmp r4d, 10 + je .loop10 + cmp r4d, 12 + je .loop12 +SCALARPRODUCT_LOOP 14 +SCALARPRODUCT_LOOP 12 +SCALARPRODUCT_LOOP 10 +SCALARPRODUCT_LOOP 8 +SCALARPRODUCT_LOOP 6 +SCALARPRODUCT_LOOP 4 +SCALARPRODUCT_LOOP 2 +SCALARPRODUCT_LOOP 0 +.end: + HADDD m6, m0 + movd eax, m6 + RET diff --git a/libavcodec/x86/lossless_audiodsp_init.c b/libavcodec/x86/lossless_audiodsp_init.c new file mode 100644 index 000000000..4879dff1d --- /dev/null +++ b/libavcodec/x86/lossless_audiodsp_init.c @@ -0,0 +1,47 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/lossless_audiodsp.h" + +int32_t ff_scalarproduct_and_madd_int16_mmxext(int16_t *v1, const int16_t *v2, + const int16_t *v3, + int order, int mul); +int32_t ff_scalarproduct_and_madd_int16_sse2(int16_t *v1, const int16_t *v2, + const int16_t *v3, + int order, int mul); +int32_t ff_scalarproduct_and_madd_int16_ssse3(int16_t *v1, const int16_t *v2, + const int16_t *v3, + int order, int mul); + +av_cold void ff_llauddsp_init_x86(LLAudDSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_MMXEXT(cpu_flags)) + c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_mmxext; + + if (EXTERNAL_SSE2(cpu_flags)) + c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_sse2; + + if (EXTERNAL_SSSE3(cpu_flags) && + !(cpu_flags & (AV_CPU_FLAG_SSE42 | AV_CPU_FLAG_3DNOW))) // cachesplit + c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_ssse3; +} diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index bacc1e927..e6c23e798 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -37,19 +37,21 @@ SECTION_TEXT add wd, wd test wq, 2*mmsize - 1 jz %%.tomainloop + push tmpq %%.wordloop: sub wq, 2 %ifidn %2, add - mov ax, [srcq+wq] - add ax, [dstq+wq] + mov tmpw, [srcq+wq] + add tmpw, [dstq+wq] %else - mov ax, [src1q+wq] - sub ax, [src2q+wq] + mov tmpw, [src1q+wq] + sub tmpw, [src2q+wq] %endif - and ax, maskw - mov [dstq+wq], ax + and tmpw, maskw + mov [dstq+wq], tmpw test wq, 2*mmsize - 1 jnz %%.wordloop + pop tmpq %%.tomainloop: %ifidn %2, add add srcq, wq @@ -85,11 +87,11 @@ SECTION_TEXT %endmacro INIT_MMX mmx -cglobal add_int16, 4,4,5, dst, src, mask, w +cglobal add_int16, 4,4,5, dst, src, mask, w, tmp INT16_LOOP a, add INIT_XMM sse2 -cglobal add_int16, 4,4,5, dst, src, mask, w +cglobal add_int16, 4,4,5, dst, src, mask, w, tmp test srcq, mmsize-1 jnz .unaligned test dstq, mmsize-1 @@ -99,11 +101,11 @@ cglobal add_int16, 4,4,5, dst, src, mask, w INT16_LOOP u, add INIT_MMX mmx -cglobal diff_int16, 5,5,5, dst, src1, src2, mask, w +cglobal diff_int16, 5,5,5, dst, src1, src2, mask, w, tmp INT16_LOOP a, sub INIT_XMM sse2 -cglobal diff_int16, 5,5,5, dst, src1, src2, mask, w +cglobal diff_int16, 5,5,5, dst, src1, src2, mask, w, tmp test src1q, mmsize-1 jnz .unaligned test src2q, mmsize-1 @@ -156,9 +158,9 @@ cglobal diff_int16, 5,5,5, dst, src1, src2, mask, w RET %endmacro -; int add_hfyu_left_prediction_int16(uint16_t *dst, const uint16_t *src, unsigned mask, int w, int left) +; int add_hfyu_left_pred_int16(uint16_t *dst, const uint16_t *src, unsigned mask, int w, int left) INIT_MMX ssse3 -cglobal add_hfyu_left_prediction_int16, 4,4,8, dst, src, mask, w, left +cglobal add_hfyu_left_pred_int16, 4,4,8, dst, src, mask, w, left .skip_prologue: mova m5, [pb_67] mova m3, [pb_zzzz2323zzzzabab] @@ -169,7 +171,7 @@ cglobal add_hfyu_left_prediction_int16, 4,4,8, dst, src, mask, w, left ADD_HFYU_LEFT_LOOP_INT16 a, a INIT_XMM sse4 -cglobal add_hfyu_left_prediction_int16, 4,4,8, dst, src, mask, w, left +cglobal add_hfyu_left_pred_int16, 4,4,8, dst, src, mask, w, left mova m5, [pb_ef] mova m4, [pb_zzzzzzzz67676767] mova m3, [pb_zzzz2323zzzzabab] @@ -189,7 +191,7 @@ cglobal add_hfyu_left_prediction_int16, 4,4,8, dst, src, mask, w, left ; void add_hfyu_median_prediction_mmxext(uint8_t *dst, const uint8_t *top, const uint8_t *diff, int mask, int w, int *left, int *left_top) INIT_MMX mmxext -cglobal add_hfyu_median_prediction_int16, 7,7,0, dst, top, diff, mask, w, left, left_top +cglobal add_hfyu_median_pred_int16, 7,7,0, dst, top, diff, mask, w, left, left_top add wd, wd movd mm6, maskd SPLATW mm6, mm6 @@ -252,7 +254,7 @@ cglobal add_hfyu_median_prediction_int16, 7,7,0, dst, top, diff, mask, w, left, mov [left_topq], r2d RET -cglobal sub_hfyu_median_prediction_int16, 7,7,0, dst, src1, src2, mask, w, left, left_top +cglobal sub_hfyu_median_pred_int16, 7,7,0, dst, src1, src2, mask, w, left, left_top add wd, wd movd mm7, maskd SPLATW mm7, mm7 @@ -285,8 +287,8 @@ cglobal sub_hfyu_median_prediction_int16, 7,7,0, dst, src1, src2, mask, w, left, movq mm2, [src2q + maskq - 2] cmp maskq, wq jb .loop - mov maskd, [src1q + wq - 2] + movzx maskd, word [src1q + wq - 2] mov [left_topq], maskd - mov maskd, [src2q + wq - 2] + movzx maskd, word [src2q + wq - 2] mov [leftq], maskd RET diff --git a/libavcodec/x86/lossless_videodsp_init.c b/libavcodec/x86/lossless_videodsp_init.c index 03ea2dff2..6589024a1 100644 --- a/libavcodec/x86/lossless_videodsp_init.c +++ b/libavcodec/x86/lossless_videodsp_init.c @@ -26,10 +26,10 @@ void ff_add_int16_mmx(uint16_t *dst, const uint16_t *src, unsigned mask, int w); void ff_add_int16_sse2(uint16_t *dst, const uint16_t *src, unsigned mask, int w); void ff_diff_int16_mmx (uint16_t *dst, const uint16_t *src1, const uint16_t *src2, unsigned mask, int w); void ff_diff_int16_sse2(uint16_t *dst, const uint16_t *src1, const uint16_t *src2, unsigned mask, int w); -int ff_add_hfyu_left_prediction_int16_ssse3(uint16_t *dst, const uint16_t *src, unsigned mask, int w, int acc); -int ff_add_hfyu_left_prediction_int16_sse4(uint16_t *dst, const uint16_t *src, unsigned mask, int w, int acc); -void ff_add_hfyu_median_prediction_int16_mmxext(uint16_t *dst, const uint16_t *top, const uint16_t *diff, unsigned mask, int w, int *left, int *left_top); -void ff_sub_hfyu_median_prediction_int16_mmxext(uint16_t *dst, const uint16_t *src1, const uint16_t *src2, unsigned mask, int w, int *left, int *left_top); +int ff_add_hfyu_left_pred_int16_ssse3(uint16_t *dst, const uint16_t *src, unsigned mask, int w, unsigned acc); +int ff_add_hfyu_left_pred_int16_sse4(uint16_t *dst, const uint16_t *src, unsigned mask, int w, unsigned acc); +void ff_add_hfyu_median_pred_int16_mmxext(uint16_t *dst, const uint16_t *top, const uint16_t *diff, unsigned mask, int w, int *left, int *left_top); +void ff_sub_hfyu_median_pred_int16_mmxext(uint16_t *dst, const uint16_t *src1, const uint16_t *src2, unsigned mask, int w, int *left, int *left_top); void ff_llviddsp_init_x86(LLVidDSPContext *c, AVCodecContext *avctx) @@ -43,8 +43,8 @@ void ff_llviddsp_init_x86(LLVidDSPContext *c, AVCodecContext *avctx) } if (EXTERNAL_MMXEXT(cpu_flags) && pix_desc->comp[0].depth_minus1<15) { - c->add_hfyu_median_prediction_int16 = ff_add_hfyu_median_prediction_int16_mmxext; - c->sub_hfyu_median_prediction_int16 = ff_sub_hfyu_median_prediction_int16_mmxext; + c->add_hfyu_median_pred_int16 = ff_add_hfyu_median_pred_int16_mmxext; + c->sub_hfyu_median_pred_int16 = ff_sub_hfyu_median_pred_int16_mmxext; } if (EXTERNAL_SSE2(cpu_flags)) { @@ -53,10 +53,10 @@ void ff_llviddsp_init_x86(LLVidDSPContext *c, AVCodecContext *avctx) } if (EXTERNAL_SSSE3(cpu_flags)) { - c->add_hfyu_left_prediction_int16 = ff_add_hfyu_left_prediction_int16_ssse3; + c->add_hfyu_left_pred_int16 = ff_add_hfyu_left_pred_int16_ssse3; } if (EXTERNAL_SSE4(cpu_flags)) { - c->add_hfyu_left_prediction_int16 = ff_add_hfyu_left_prediction_int16_sse4; + c->add_hfyu_left_pred_int16 = ff_add_hfyu_left_pred_int16_sse4; } } diff --git a/libavcodec/x86/lpc.c b/libavcodec/x86/lpc.c index 8a74755d1..3a9493f72 100644 --- a/libavcodec/x86/lpc.c +++ b/libavcodec/x86/lpc.c @@ -1,5 +1,5 @@ /* - * MMX optimized LPC DSP utils + * SIMD-optimized LPC functions * Copyright (c) 2007 Loren Merritt * * This file is part of FFmpeg. @@ -72,6 +72,7 @@ static void lpc_apply_welch_window_sse2(const int32_t *data, int len, "3: \n\t" :"+&r"(i), "+&r"(j) :"r"(w_data+n2), "r"(data+n2), "m"(c), "r"(len) + NAMED_CONSTRAINTS_ARRAY_ADD(pd_1,pd_2) XMM_CLOBBERS_ONLY("%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm5", "%xmm6", "%xmm7") ); @@ -116,6 +117,7 @@ static void lpc_compute_autocorr_sse2(const double *data, int len, int lag, "movsd %%xmm2, 16(%1) \n\t" :"+&r"(i) :"r"(autoc+j), "r"(data+len), "r"(data+len-j) + NAMED_CONSTRAINTS_ARRAY_ADD(pd_1) :"memory" ); } else { @@ -139,6 +141,7 @@ static void lpc_compute_autocorr_sse2(const double *data, int len, int lag, "movsd %%xmm1, %2 \n\t" :"+&r"(i), "=m"(autoc[j]), "=m"(autoc[j+1]) :"r"(data+len), "r"(data+len-j) + NAMED_CONSTRAINTS_ARRAY_ADD(pd_1) ); } } diff --git a/libavcodec/x86/mathops.h b/libavcodec/x86/mathops.h index 9c48afeb2..1cca05d65 100644 --- a/libavcodec/x86/mathops.h +++ b/libavcodec/x86/mathops.h @@ -24,6 +24,7 @@ #include "config.h" #include "libavutil/common.h" +#include "libavutil/x86/asm.h" #if HAVE_INLINE_ASM @@ -88,6 +89,7 @@ static inline av_const int mid_pred(int a, int b, int c) return i; } +#if HAVE_6REGS #define COPY3_IF_LT(x, y, a, b, c, d)\ __asm__ volatile(\ "cmpl %0, %3 \n\t"\ @@ -97,10 +99,11 @@ __asm__ volatile(\ : "+&r" (x), "+&r" (a), "+r" (c)\ : "r" (y), "r" (b), "r" (d)\ ); +#endif /* HAVE_6REGS */ #endif /* HAVE_I686 */ #define MASK_ABS(mask, level) \ - __asm__ ("cltd \n\t" \ + __asm__ ("cdq \n\t" \ "xorl %1, %0 \n\t" \ "subl %1, %0 \n\t" \ : "+a"(level), "=&d"(mask)) diff --git a/libavcodec/x86/mlpdsp.c b/libavcodec/x86/mlpdsp.c index 94849b7e7..b473625fb 100644 --- a/libavcodec/x86/mlpdsp.c +++ b/libavcodec/x86/mlpdsp.c @@ -26,7 +26,7 @@ #include "libavcodec/mlpdsp.h" #include "libavcodec/mlp.h" -#if HAVE_7REGS && HAVE_INLINE_ASM +#if HAVE_7REGS && HAVE_INLINE_ASM && HAVE_INLINE_ASM_NONLOCAL_LABELS extern char ff_mlp_firorder_8; extern char ff_mlp_firorder_7; @@ -178,7 +178,7 @@ static void mlp_filter_channel_x86(int32_t *state, const int32_t *coeff, av_cold void ff_mlpdsp_init_x86(MLPDSPContext *c) { -#if HAVE_7REGS && HAVE_INLINE_ASM +#if HAVE_7REGS && HAVE_INLINE_ASM && HAVE_INLINE_ASM_NONLOCAL_LABELS int cpu_flags = av_get_cpu_flags(); if (INLINE_MMX(cpu_flags)) c->mlp_filter_channel = mlp_filter_channel_x86; diff --git a/libavcodec/x86/motion_est.c b/libavcodec/x86/motion_est.c index 5f5d93e9b..4071ae535 100644 --- a/libavcodec/x86/motion_est.c +++ b/libavcodec/x86/motion_est.c @@ -27,22 +27,23 @@ #include "libavutil/mem.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" +#include "libavcodec/mpegvideo.h" #include "dsputil_x86.h" #if HAVE_INLINE_ASM -DECLARE_ASM_CONST(8, uint64_t, round_tab)[3]={ -0x0000000000000000ULL, -0x0001000100010001ULL, -0x0002000200020002ULL, +DECLARE_ASM_CONST(8, uint64_t, round_tab)[3] = { + 0x0000000000000000ULL, + 0x0001000100010001ULL, + 0x0002000200020002ULL, }; -DECLARE_ASM_CONST(8, uint64_t, bone)= 0x0101010101010101LL; +DECLARE_ASM_CONST(8, uint64_t, bone) = 0x0101010101010101LL; static inline void sad8_1_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) { - x86_reg len= -(x86_reg)stride*h; - __asm__ volatile( + x86_reg len = -(x86_reg)stride * h; + __asm__ volatile ( ".p2align 4 \n\t" "1: \n\t" "movq (%1, %%"REG_a"), %%mm0 \n\t" @@ -71,14 +72,13 @@ static inline void sad8_1_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) "add %3, %%"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" ((x86_reg) stride)); } static inline void sad8_1_mmxext(uint8_t *blk1, uint8_t *blk2, int stride, int h) { - __asm__ volatile( + __asm__ volatile ( ".p2align 4 \n\t" "1: \n\t" "movq (%1), %%mm0 \n\t" @@ -92,14 +92,14 @@ 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" ((x86_reg) stride)); } -static int sad16_sse2(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h) +static int sad16_sse2(MpegEncContext *v, uint8_t *blk2, uint8_t *blk1, + int stride, int h) { int ret; - __asm__ volatile( + __asm__ volatile ( "pxor %%xmm2, %%xmm2 \n\t" ".p2align 4 \n\t" "1: \n\t" @@ -116,16 +116,15 @@ static int sad16_sse2(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h) "movhlps %%xmm2, %%xmm0 \n\t" "paddw %%xmm0, %%xmm2 \n\t" "movd %%xmm2, %3 \n\t" - : "+r" (h), "+r" (blk1), "+r" (blk2), "=r"(ret) - : "r" ((x86_reg)stride) - ); + : "+r" (h), "+r" (blk1), "+r" (blk2), "=r" (ret) + : "r" ((x86_reg) stride)); return ret; } static inline void sad8_x2a_mmxext(uint8_t *blk1, uint8_t *blk2, int stride, int h) { - __asm__ volatile( + __asm__ volatile ( ".p2align 4 \n\t" "1: \n\t" "movq (%1), %%mm0 \n\t" @@ -141,14 +140,13 @@ 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" ((x86_reg) stride)); } static inline void sad8_y2a_mmxext(uint8_t *blk1, uint8_t *blk2, int stride, int h) { - __asm__ volatile( + __asm__ volatile ( "movq (%1), %%mm0 \n\t" "add %3, %1 \n\t" ".p2align 4 \n\t" @@ -167,14 +165,13 @@ 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" ((x86_reg) stride)); } static inline void sad8_4_mmxext(uint8_t *blk1, uint8_t *blk2, int stride, int h) { - __asm__ volatile( + __asm__ volatile ( "movq "MANGLE(bone)", %%mm5 \n\t" "movq (%1), %%mm0 \n\t" "pavgb 1(%1), %%mm0 \n\t" @@ -198,14 +195,15 @@ 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" ((x86_reg) stride) + NAMED_CONSTRAINTS_ADD(bone)); } -static inline void sad8_2_mmx(uint8_t *blk1a, uint8_t *blk1b, uint8_t *blk2, int stride, int h) +static inline void sad8_2_mmx(uint8_t *blk1a, uint8_t *blk1b, uint8_t *blk2, + int stride, int h) { - x86_reg len= -(x86_reg)stride*h; - __asm__ volatile( + x86_reg len = -(x86_reg)stride * h; + __asm__ volatile ( ".p2align 4 \n\t" "1: \n\t" "movq (%1, %%"REG_a"), %%mm0 \n\t" @@ -236,15 +234,15 @@ static inline void sad8_2_mmx(uint8_t *blk1a, uint8_t *blk1b, uint8_t *blk2, int "add %4, %%"REG_a" \n\t" " js 1b \n\t" : "+a" (len) - : "r" (blk1a - len), "r" (blk1b -len), "r" (blk2 - len), "r" ((x86_reg)stride) - ); + : "r" (blk1a - len), "r" (blk1b - len), "r" (blk2 - len), + "r" ((x86_reg) stride)); } static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) { - x86_reg len= -(x86_reg)stride*h; - __asm__ volatile( - "movq (%1, %%"REG_a"), %%mm0 \n\t" + x86_reg len = -(x86_reg)stride * h; + __asm__ volatile ( + "movq (%1, %%"REG_a"), %%mm0 \n\t" "movq 1(%1, %%"REG_a"), %%mm2 \n\t" "movq %%mm0, %%mm1 \n\t" "movq %%mm2, %%mm3 \n\t" @@ -256,7 +254,7 @@ 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 (%2, %%"REG_a"), %%mm2 \n\t" "movq 1(%2, %%"REG_a"), %%mm4 \n\t" "movq %%mm2, %%mm3 \n\t" "movq %%mm4, %%mm5 \n\t" @@ -266,7 +264,7 @@ static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) "punpckhbw %%mm7, %%mm5 \n\t" "paddw %%mm4, %%mm2 \n\t" "paddw %%mm5, %%mm3 \n\t" - "movq 16+"MANGLE(round_tab)", %%mm5 \n\t" + "movq %5, %%mm5 \n\t" "paddw %%mm2, %%mm0 \n\t" "paddw %%mm3, %%mm1 \n\t" "paddw %%mm5, %%mm0 \n\t" @@ -289,14 +287,14 @@ static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) "add %4, %%"REG_a" \n\t" " js 1b \n\t" : "+a" (len) - : "r" (blk1 - len), "r" (blk1 -len + stride), "r" (blk2 - len), "r" ((x86_reg)stride) - ); + : "r" (blk1 - len), "r" (blk1 - len + stride), "r" (blk2 - len), + "r" ((x86_reg) stride), "m" (round_tab[2])); } static inline int sum_mmx(void) { int ret; - __asm__ volatile( + __asm__ volatile ( "movq %%mm6, %%mm0 \n\t" "psrlq $32, %%mm6 \n\t" "paddw %%mm0, %%mm6 \n\t" @@ -304,129 +302,145 @@ static inline int sum_mmx(void) "psrlq $16, %%mm6 \n\t" "paddw %%mm0, %%mm6 \n\t" "movd %%mm6, %0 \n\t" - : "=r" (ret) - ); - return ret&0xFFFF; + : "=r" (ret)); + return ret & 0xFFFF; } static inline int sum_mmxext(void) { int ret; - __asm__ volatile( + __asm__ volatile ( "movd %%mm6, %0 \n\t" - : "=r" (ret) - ); + : "=r" (ret)); return ret; } static inline void sad8_x2a_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) { - sad8_2_mmx(blk1, blk1+1, blk2, stride, h); + sad8_2_mmx(blk1, blk1 + 1, blk2, stride, h); } + static inline void sad8_y2a_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) { - sad8_2_mmx(blk1, blk1+stride, blk2, stride, h); + sad8_2_mmx(blk1, blk1 + stride, blk2, stride, h); } - -#define PIX_SAD(suf)\ -static int sad8_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ -{\ - av_assert2(h==8);\ - __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ - "pxor %%mm6, %%mm6 \n\t":);\ -\ - sad8_1_ ## suf(blk1, blk2, stride, 8);\ -\ - return sum_ ## suf();\ -}\ -static int sad8_x2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ -{\ - av_assert2(h==8);\ - __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ - "pxor %%mm6, %%mm6 \n\t"\ - "movq %0, %%mm5 \n\t"\ - :: "m"(round_tab[1]) \ - );\ -\ - sad8_x2a_ ## suf(blk1, blk2, stride, 8);\ -\ - return sum_ ## suf();\ -}\ -\ -static int sad8_y2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ -{\ - av_assert2(h==8);\ - __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ - "pxor %%mm6, %%mm6 \n\t"\ - "movq %0, %%mm5 \n\t"\ - :: "m"(round_tab[1]) \ - );\ -\ - sad8_y2a_ ## suf(blk1, blk2, stride, 8);\ -\ - return sum_ ## suf();\ -}\ -\ -static int sad8_xy2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ -{\ - av_assert2(h==8);\ - __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ - "pxor %%mm6, %%mm6 \n\t"\ - ::);\ -\ - sad8_4_ ## suf(blk1, blk2, stride, 8);\ -\ - return sum_ ## suf();\ -}\ -\ -static int sad16_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ -{\ - __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ - "pxor %%mm6, %%mm6 \n\t":);\ -\ - sad8_1_ ## suf(blk1 , blk2 , stride, h);\ - sad8_1_ ## suf(blk1+8, blk2+8, stride, h);\ -\ - return sum_ ## suf();\ -}\ -static int sad16_x2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ -{\ - __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ - "pxor %%mm6, %%mm6 \n\t"\ - "movq %0, %%mm5 \n\t"\ - :: "m"(round_tab[1]) \ - );\ -\ - sad8_x2a_ ## suf(blk1 , blk2 , stride, h);\ - sad8_x2a_ ## suf(blk1+8, blk2+8, stride, h);\ -\ - return sum_ ## suf();\ -}\ -static int sad16_y2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ -{\ - __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ - "pxor %%mm6, %%mm6 \n\t"\ - "movq %0, %%mm5 \n\t"\ - :: "m"(round_tab[1]) \ - );\ -\ - sad8_y2a_ ## suf(blk1 , blk2 , stride, h);\ - sad8_y2a_ ## suf(blk1+8, blk2+8, stride, h);\ -\ - return sum_ ## suf();\ -}\ -static int sad16_xy2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ -{\ - __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ - "pxor %%mm6, %%mm6 \n\t"\ - ::);\ -\ - sad8_4_ ## suf(blk1 , blk2 , stride, h);\ - sad8_4_ ## suf(blk1+8, blk2+8, stride, h);\ -\ - return sum_ ## suf();\ -}\ +#define PIX_SAD(suf) \ +static int sad8_ ## suf(MpegEncContext *v, uint8_t *blk2, \ + uint8_t *blk1, int stride, int h) \ +{ \ + av_assert2(h == 8); \ + __asm__ volatile ( \ + "pxor %%mm7, %%mm7 \n\t" \ + "pxor %%mm6, %%mm6 \n\t" \ + :); \ + \ + sad8_1_ ## suf(blk1, blk2, stride, 8); \ + \ + return sum_ ## suf(); \ +} \ + \ +static int sad8_x2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ + uint8_t *blk1, int stride, int h) \ +{ \ + av_assert2(h == 8); \ + __asm__ volatile ( \ + "pxor %%mm7, %%mm7 \n\t" \ + "pxor %%mm6, %%mm6 \n\t" \ + "movq %0, %%mm5 \n\t" \ + :: "m" (round_tab[1])); \ + \ + sad8_x2a_ ## suf(blk1, blk2, stride, 8); \ + \ + return sum_ ## suf(); \ +} \ + \ +static int sad8_y2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ + uint8_t *blk1, int stride, int h) \ +{ \ + av_assert2(h == 8); \ + __asm__ volatile ( \ + "pxor %%mm7, %%mm7 \n\t" \ + "pxor %%mm6, %%mm6 \n\t" \ + "movq %0, %%mm5 \n\t" \ + :: "m" (round_tab[1])); \ + \ + sad8_y2a_ ## suf(blk1, blk2, stride, 8); \ + \ + return sum_ ## suf(); \ +} \ + \ +static int sad8_xy2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ + uint8_t *blk1, int stride, int h) \ +{ \ + av_assert2(h == 8); \ + __asm__ volatile ( \ + "pxor %%mm7, %%mm7 \n\t" \ + "pxor %%mm6, %%mm6 \n\t" \ + ::); \ + \ + sad8_4_ ## suf(blk1, blk2, stride, 8); \ + \ + return sum_ ## suf(); \ +} \ + \ +static int sad16_ ## suf(MpegEncContext *v, uint8_t *blk2, \ + uint8_t *blk1, int stride, int h) \ +{ \ + __asm__ volatile ( \ + "pxor %%mm7, %%mm7 \n\t" \ + "pxor %%mm6, %%mm6 \n\t" \ + :); \ + \ + sad8_1_ ## suf(blk1, blk2, stride, h); \ + sad8_1_ ## suf(blk1 + 8, blk2 + 8, stride, h); \ + \ + return sum_ ## suf(); \ +} \ + \ +static int sad16_x2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ + uint8_t *blk1, int stride, int h) \ +{ \ + __asm__ volatile ( \ + "pxor %%mm7, %%mm7 \n\t" \ + "pxor %%mm6, %%mm6 \n\t" \ + "movq %0, %%mm5 \n\t" \ + :: "m" (round_tab[1])); \ + \ + sad8_x2a_ ## suf(blk1, blk2, stride, h); \ + sad8_x2a_ ## suf(blk1 + 8, blk2 + 8, stride, h); \ + \ + return sum_ ## suf(); \ +} \ + \ +static int sad16_y2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ + uint8_t *blk1, int stride, int h) \ +{ \ + __asm__ volatile ( \ + "pxor %%mm7, %%mm7 \n\t" \ + "pxor %%mm6, %%mm6 \n\t" \ + "movq %0, %%mm5 \n\t" \ + :: "m" (round_tab[1])); \ + \ + sad8_y2a_ ## suf(blk1, blk2, stride, h); \ + sad8_y2a_ ## suf(blk1 + 8, blk2 + 8, stride, h); \ + \ + return sum_ ## suf(); \ +} \ + \ +static int sad16_xy2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ + uint8_t *blk1, int stride, int h) \ +{ \ + __asm__ volatile ( \ + "pxor %%mm7, %%mm7 \n\t" \ + "pxor %%mm6, %%mm6 \n\t" \ + ::); \ + \ + sad8_4_ ## suf(blk1, blk2, stride, h); \ + sad8_4_ ## suf(blk1 + 8, blk2 + 8, stride, h); \ + \ + return sum_ ## suf(); \ +} \ PIX_SAD(mmx) PIX_SAD(mmxext) @@ -448,27 +462,27 @@ av_cold void ff_dsputil_init_pix_mmx(DSPContext *c, AVCodecContext *avctx) c->pix_abs[1][2] = sad8_y2_mmx; c->pix_abs[1][3] = sad8_xy2_mmx; - c->sad[0]= sad16_mmx; - c->sad[1]= sad8_mmx; + c->sad[0] = sad16_mmx; + c->sad[1] = sad8_mmx; } if (INLINE_MMXEXT(cpu_flags)) { c->pix_abs[0][0] = sad16_mmxext; c->pix_abs[1][0] = sad8_mmxext; - c->sad[0] = sad16_mmxext; - c->sad[1] = sad8_mmxext; + c->sad[0] = sad16_mmxext; + c->sad[1] = sad8_mmxext; - if(!(avctx->flags & CODEC_FLAG_BITEXACT)){ - c->pix_abs[0][1] = sad16_x2_mmxext; - c->pix_abs[0][2] = sad16_y2_mmxext; + c->pix_abs[0][1] = sad16_x2_mmxext; + c->pix_abs[0][2] = sad16_y2_mmxext; + c->pix_abs[1][1] = sad8_x2_mmxext; + c->pix_abs[1][2] = sad8_y2_mmxext; + if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { c->pix_abs[0][3] = sad16_xy2_mmxext; - c->pix_abs[1][1] = sad8_x2_mmxext; - c->pix_abs[1][2] = sad8_y2_mmxext; c->pix_abs[1][3] = sad8_xy2_mmxext; } } - if (INLINE_SSE2(cpu_flags) && !(cpu_flags & AV_CPU_FLAG_3DNOW) && avctx->codec_id != AV_CODEC_ID_SNOW) { - c->sad[0]= sad16_sse2; + if (INLINE_SSE2(cpu_flags) && !(cpu_flags & AV_CPU_FLAG_SSE2SLOW) && avctx->codec_id != AV_CODEC_ID_SNOW) { + c->sad[0] = sad16_sse2; } #endif /* HAVE_INLINE_ASM */ } diff --git a/libavcodec/x86/mpegaudiodsp.c b/libavcodec/x86/mpegaudiodsp.c index 3654c8124..27231674a 100644 --- a/libavcodec/x86/mpegaudiodsp.c +++ b/libavcodec/x86/mpegaudiodsp.c @@ -1,5 +1,5 @@ /* - * MMX optimized MP3 decoding functions + * SIMD-optimized MP3 decoding functions * Copyright (c) 2010 Vitor Sessak * * This file is part of FFmpeg. @@ -45,7 +45,7 @@ void ff_four_imdct36_float_avx(float *out, float *buf, float *in, float *win, DECLARE_ALIGNED(16, static float, mdct_win_sse)[2][4][4*40]; -#if HAVE_SSE2_INLINE +#if HAVE_6REGS && HAVE_SSE_INLINE #define MACS(rt, ra, rb) rt+=(ra)*(rb) #define MLSS(rt, ra, rb) rt-=(ra)*(rb) @@ -189,7 +189,7 @@ static void apply_window_mp3(float *in, float *win, int *unused, float *out, *out = sum; } -#endif /* HAVE_SSE2_INLINE */ +#endif /* HAVE_6REGS && HAVE_SSE_INLINE */ #if HAVE_YASM #define DECL_IMDCT_BLOCKS(CPU1, CPU2) \ @@ -255,13 +255,14 @@ av_cold void ff_mpadsp_init_x86(MPADSPContext *s) } } -#if HAVE_SSE2_INLINE - if (INLINE_SSE2(cpu_flags)) { +#if HAVE_6REGS && HAVE_SSE_INLINE + if (INLINE_SSE(cpu_flags)) { s->apply_window_float = apply_window_mp3; } -#endif /* HAVE_SSE2_INLINE */ +#endif /* HAVE_SSE_INLINE */ #if HAVE_YASM +#if HAVE_SSE #if ARCH_X86_32 if (EXTERNAL_SSE(cpu_flags)) { s->imdct36_blocks_float = imdct36_blocks_sse; @@ -276,8 +277,11 @@ av_cold void ff_mpadsp_init_x86(MPADSPContext *s) if (EXTERNAL_SSSE3(cpu_flags)) { s->imdct36_blocks_float = imdct36_blocks_ssse3; } +#endif +#if HAVE_AVX_EXTERNAL if (EXTERNAL_AVX(cpu_flags)) { s->imdct36_blocks_float = imdct36_blocks_avx; } +#endif #endif /* HAVE_YASM */ } diff --git a/libavcodec/x86/mpegvideo.c b/libavcodec/x86/mpegvideo.c index b2ce68062..9353a8293 100644 --- a/libavcodec/x86/mpegvideo.c +++ b/libavcodec/x86/mpegvideo.c @@ -25,7 +25,6 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/avcodec.h" #include "libavcodec/mpegvideo.h" -#include "dsputil_x86.h" #if HAVE_MMX_INLINE diff --git a/libavcodec/x86/mpegvideodsp.c b/libavcodec/x86/mpegvideodsp.c new file mode 100644 index 000000000..941a8e2e4 --- /dev/null +++ b/libavcodec/x86/mpegvideodsp.c @@ -0,0 +1,161 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/mpegvideodsp.h" +#include "libavcodec/videodsp.h" + +#if HAVE_INLINE_ASM + +static void gmc_mmx(uint8_t *dst, uint8_t *src, + int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, + int shift, int r, int width, int height) +{ + const int w = 8; + const int ix = ox >> (16 + shift); + const int iy = oy >> (16 + shift); + const int oxs = ox >> 4; + const int oys = oy >> 4; + const int dxxs = dxx >> 4; + const int dxys = dxy >> 4; + const int dyxs = dyx >> 4; + const int dyys = dyy >> 4; + const uint16_t r4[4] = { r, r, r, r }; + const uint16_t dxy4[4] = { dxys, dxys, dxys, dxys }; + const uint16_t dyy4[4] = { dyys, dyys, dyys, dyys }; + const uint64_t shift2 = 2 * shift; +#define MAX_STRIDE 4096U +#define MAX_H 8U + uint8_t edge_buf[(MAX_H + 1) * MAX_STRIDE]; + int x, y; + + const int dxw = (dxx - (1 << (16 + shift))) * (w - 1); + const int dyh = (dyy - (1 << (16 + shift))) * (h - 1); + const int dxh = dxy * (h - 1); + const int dyw = dyx * (w - 1); + int need_emu = (unsigned) ix >= width - w || + (unsigned) iy >= height - h; + + if ( // non-constant fullpel offset (3% of blocks) + ((ox ^ (ox + dxw)) | (ox ^ (ox + dxh)) | (ox ^ (ox + dxw + dxh)) | + (oy ^ (oy + dyw)) | (oy ^ (oy + dyh)) | (oy ^ (oy + dyw + dyh))) >> (16 + shift) || + // uses more than 16 bits of subpel mv (only at huge resolution) + (dxx | dxy | dyx | dyy) & 15 || + (need_emu && (h > MAX_H || stride > MAX_STRIDE))) { + // FIXME could still use mmx for some of the rows + ff_gmc_c(dst, src, stride, h, ox, oy, dxx, dxy, dyx, dyy, + shift, r, width, height); + return; + } + + src += ix + iy * stride; + if (need_emu) { + ff_emulated_edge_mc_8(edge_buf, src, stride, stride, w + 1, h + 1, ix, iy, width, height); + src = edge_buf; + } + + __asm__ volatile ( + "movd %0, %%mm6 \n\t" + "pxor %%mm7, %%mm7 \n\t" + "punpcklwd %%mm6, %%mm6 \n\t" + "punpcklwd %%mm6, %%mm6 \n\t" + :: "r" (1 << shift)); + + for (x = 0; x < w; x += 4) { + uint16_t dx4[4] = { oxs - dxys + dxxs * (x + 0), + oxs - dxys + dxxs * (x + 1), + oxs - dxys + dxxs * (x + 2), + oxs - dxys + dxxs * (x + 3) }; + uint16_t dy4[4] = { oys - dyys + dyxs * (x + 0), + oys - dyys + dyxs * (x + 1), + oys - dyys + dyxs * (x + 2), + oys - dyys + dyxs * (x + 3) }; + + for (y = 0; y < h; y++) { + __asm__ volatile ( + "movq %0, %%mm4 \n\t" + "movq %1, %%mm5 \n\t" + "paddw %2, %%mm4 \n\t" + "paddw %3, %%mm5 \n\t" + "movq %%mm4, %0 \n\t" + "movq %%mm5, %1 \n\t" + "psrlw $12, %%mm4 \n\t" + "psrlw $12, %%mm5 \n\t" + : "+m" (*dx4), "+m" (*dy4) + : "m" (*dxy4), "m" (*dyy4)); + + __asm__ volatile ( + "movq %%mm6, %%mm2 \n\t" + "movq %%mm6, %%mm1 \n\t" + "psubw %%mm4, %%mm2 \n\t" + "psubw %%mm5, %%mm1 \n\t" + "movq %%mm2, %%mm0 \n\t" + "movq %%mm4, %%mm3 \n\t" + "pmullw %%mm1, %%mm0 \n\t" // (s - dx) * (s - dy) + "pmullw %%mm5, %%mm3 \n\t" // dx * dy + "pmullw %%mm5, %%mm2 \n\t" // (s - dx) * dy + "pmullw %%mm4, %%mm1 \n\t" // dx * (s - dy) + + "movd %4, %%mm5 \n\t" + "movd %3, %%mm4 \n\t" + "punpcklbw %%mm7, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "pmullw %%mm5, %%mm3 \n\t" // src[1, 1] * dx * dy + "pmullw %%mm4, %%mm2 \n\t" // src[0, 1] * (s - dx) * dy + + "movd %2, %%mm5 \n\t" + "movd %1, %%mm4 \n\t" + "punpcklbw %%mm7, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "pmullw %%mm5, %%mm1 \n\t" // src[1, 0] * dx * (s - dy) + "pmullw %%mm4, %%mm0 \n\t" // src[0, 0] * (s - dx) * (s - dy) + "paddw %5, %%mm1 \n\t" + "paddw %%mm3, %%mm2 \n\t" + "paddw %%mm1, %%mm0 \n\t" + "paddw %%mm2, %%mm0 \n\t" + + "psrlw %6, %%mm0 \n\t" + "packuswb %%mm0, %%mm0 \n\t" + "movd %%mm0, %0 \n\t" + + : "=m" (dst[x + y * stride]) + : "m" (src[0]), "m" (src[1]), + "m" (src[stride]), "m" (src[stride + 1]), + "m" (*r4), "m" (shift2)); + src += stride; + } + src += 4 - h * stride; + } +} + +#endif /* HAVE_INLINE_ASM */ + +av_cold void ff_mpegvideodsp_init_x86(MpegVideoDSPContext *c) +{ +#if HAVE_INLINE_ASM + int cpu_flags = av_get_cpu_flags(); + + if (INLINE_MMX(cpu_flags)) + c->gmc = gmc_mmx; +#endif /* HAVE_INLINE_ASM */ +} diff --git a/libavcodec/x86/mpegvideoenc.c b/libavcodec/x86/mpegvideoenc.c index 7dd995908..b410511c6 100644 --- a/libavcodec/x86/mpegvideoenc.c +++ b/libavcodec/x86/mpegvideoenc.c @@ -26,17 +26,18 @@ #include "libavcodec/avcodec.h" #include "libavcodec/dct.h" #include "libavcodec/mpegvideo.h" -#include "dsputil_x86.h" /* not permutated inverse zigzag_direct + 1 for MMX quantizer */ DECLARE_ALIGNED(16, static uint16_t, inv_zigzag_direct16)[64]; +#if HAVE_6REGS + #if HAVE_MMX_INLINE #define COMPILE_TEMPLATE_MMXEXT 0 #define COMPILE_TEMPLATE_SSE2 0 #define COMPILE_TEMPLATE_SSSE3 0 -#define RENAME(a) a ## _MMX -#define RENAMEl(a) a ## _mmx +#define RENAME(a) a ## _mmx +#define RENAME_FDCT(a) a ## _mmx #include "mpegvideoenc_template.c" #endif /* HAVE_MMX_INLINE */ @@ -48,9 +49,9 @@ DECLARE_ALIGNED(16, static uint16_t, inv_zigzag_direct16)[64]; #define COMPILE_TEMPLATE_SSE2 0 #define COMPILE_TEMPLATE_SSSE3 0 #undef RENAME -#undef RENAMEl -#define RENAME(a) a ## _MMXEXT -#define RENAMEl(a) a ## _mmxext +#undef RENAME_FDCT +#define RENAME(a) a ## _mmxext +#define RENAME_FDCT(a) a ## _mmxext #include "mpegvideoenc_template.c" #endif /* HAVE_MMXEXT_INLINE */ @@ -62,9 +63,9 @@ DECLARE_ALIGNED(16, static uint16_t, inv_zigzag_direct16)[64]; #define COMPILE_TEMPLATE_SSE2 1 #define COMPILE_TEMPLATE_SSSE3 0 #undef RENAME -#undef RENAMEl -#define RENAME(a) a ## _SSE2 -#define RENAMEl(a) a ## _sse2 +#undef RENAME_FDCT +#define RENAME(a) a ## _sse2 +#define RENAME_FDCT(a) a ## _sse2 #include "mpegvideoenc_template.c" #endif /* HAVE_SSE2_INLINE */ @@ -76,12 +77,14 @@ DECLARE_ALIGNED(16, static uint16_t, inv_zigzag_direct16)[64]; #define COMPILE_TEMPLATE_SSE2 1 #define COMPILE_TEMPLATE_SSSE3 1 #undef RENAME -#undef RENAMEl -#define RENAME(a) a ## _SSSE3 -#define RENAMEl(a) a ## _sse2 +#undef RENAME_FDCT +#define RENAME(a) a ## _ssse3 +#define RENAME_FDCT(a) a ## _sse2 #include "mpegvideoenc_template.c" #endif /* HAVE_SSSE3_INLINE */ +#endif /* HAVE_6REGS */ + #if HAVE_INLINE_ASM static void denoise_dct_mmx(MpegEncContext *s, int16_t *block){ const int intra= s->mb_intra; @@ -206,23 +209,27 @@ av_cold void ff_dct_encode_init_x86(MpegEncContext *s) #if HAVE_MMX_INLINE int cpu_flags = av_get_cpu_flags(); if (INLINE_MMX(cpu_flags)) { - s->dct_quantize = dct_quantize_MMX; +#if HAVE_6REGS + s->dct_quantize = dct_quantize_mmx; +#endif s->denoise_dct = denoise_dct_mmx; } #endif -#if HAVE_MMXEXT_INLINE +#if HAVE_6REGS && HAVE_MMXEXT_INLINE if (INLINE_MMXEXT(cpu_flags)) - s->dct_quantize = dct_quantize_MMXEXT; + s->dct_quantize = dct_quantize_mmxext; #endif #if HAVE_SSE2_INLINE if (INLINE_SSE2(cpu_flags)) { - s->dct_quantize = dct_quantize_SSE2; +#if HAVE_6REGS + s->dct_quantize = dct_quantize_sse2; +#endif s->denoise_dct = denoise_dct_sse2; } #endif -#if HAVE_SSSE3_INLINE +#if HAVE_6REGS && HAVE_SSSE3_INLINE if (INLINE_SSSE3(cpu_flags)) - s->dct_quantize = dct_quantize_SSSE3; + s->dct_quantize = dct_quantize_ssse3; #endif } } diff --git a/libavcodec/x86/dsputil_qns_template.c b/libavcodec/x86/mpegvideoenc_qns_template.c similarity index 95% rename from libavcodec/x86/dsputil_qns_template.c rename to libavcodec/x86/mpegvideoenc_qns_template.c index bde6b0a60..882d48620 100644 --- a/libavcodec/x86/dsputil_qns_template.c +++ b/libavcodec/x86/mpegvideoenc_qns_template.c @@ -1,5 +1,5 @@ /* - * DSP utils : QNS functions are compiled 3 times for mmx/3dnow/ssse3 + * QNS functions are compiled 3 times for MMX/3DNOW/SSSE3 * Copyright (c) 2004 Michael Niedermayer * * MMX optimization by Michael Niedermayer @@ -22,6 +22,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/x86/asm.h" + +#include "inline_asm.h" + #define MAX_ABS (512 >> (SCALE_OFFSET>0 ? SCALE_OFFSET : 0)) static int DEF(try_8x8basis)(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale) diff --git a/libavcodec/x86/mpegvideoenc_template.c b/libavcodec/x86/mpegvideoenc_template.c index bbe93e8de..386fbcdf7 100644 --- a/libavcodec/x86/mpegvideoenc_template.c +++ b/libavcodec/x86/mpegvideoenc_template.c @@ -20,6 +20,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + +#include "libavutil/internal.h" +#include "libavutil/x86/asm.h" +#include "libavcodec/mpegvideo.h" + #undef MMREG_WIDTH #undef MM #undef MOVQ @@ -103,7 +109,7 @@ static int RENAME(dct_quantize)(MpegEncContext *s, av_assert2((7&(int)(&temp_block[0])) == 0); //did gcc align it correctly? //s->fdct (block); - RENAMEl(ff_fdct) (block); //cannot be anything else ... + RENAME_FDCT(ff_fdct)(block); // cannot be anything else ... if(s->dct_error_sum) s->denoise_dct(s, block); @@ -168,7 +174,7 @@ static int RENAME(dct_quantize)(MpegEncContext *s, " 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 + "movzbl %%al, %%eax \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) @@ -202,7 +208,7 @@ static int RENAME(dct_quantize)(MpegEncContext *s, " 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 + "movzbl %%al, %%eax \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) @@ -226,7 +232,7 @@ static int RENAME(dct_quantize)(MpegEncContext *s, if(s->mb_intra) block[0]= level; else block[0]= temp_block[0]; - if(s->dsp.idct_permutation_type == FF_SIMPLE_IDCT_PERM){ + if (s->idsp.idct_permutation_type == FF_SIMPLE_IDCT_PERM) { if(last_non_zero_p1 <= 1) goto end; block[0x08] = temp_block[0x01]; block[0x10] = temp_block[0x08]; block[0x20] = temp_block[0x10]; @@ -270,7 +276,7 @@ static int RENAME(dct_quantize)(MpegEncContext *s, block[0x3E] = temp_block[0x3D]; block[0x27] = temp_block[0x36]; block[0x3D] = temp_block[0x2F]; block[0x2F] = temp_block[0x37]; block[0x37] = temp_block[0x3E]; block[0x3F] = temp_block[0x3F]; - }else if(s->dsp.idct_permutation_type == FF_LIBMPEG2_IDCT_PERM){ + }else if(s->idsp.idct_permutation_type == FF_LIBMPEG2_IDCT_PERM){ if(last_non_zero_p1 <= 1) goto end; block[0x04] = temp_block[0x01]; block[0x08] = temp_block[0x08]; block[0x10] = temp_block[0x10]; diff --git a/libavcodec/x86/mpegvideoencdsp.asm b/libavcodec/x86/mpegvideoencdsp.asm new file mode 100644 index 000000000..4fe6cfe5a --- /dev/null +++ b/libavcodec/x86/mpegvideoencdsp.asm @@ -0,0 +1,137 @@ +;***************************************************************************** +;* SIMD-optimized MPEG encoding functions +;***************************************************************************** +;* Copyright (c) 2000, 2001 Fabrice Bellard +;* Copyright (c) 2002-2004 Michael Niedermayer +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;***************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +cextern pw_1 + +SECTION .text +; int ff_pix_sum16_mmx(uint8_t *pix, int line_size) +; %1 = number of xmm registers used +; %2 = number of loops +; %3 = number of GPRs used +%macro PIX_SUM16 4 +cglobal pix_sum16, 2, %3, %1 + movsxdifnidn r1, r1d + mov r2, %2 +%if cpuflag(xop) + lea r3, [r1*3] +%else + pxor m5, m5 +%endif + pxor m4, m4 +.loop: +%if cpuflag(xop) + vphaddubq m0, [r0] + vphaddubq m1, [r0+r1] + vphaddubq m2, [r0+r1*2] + vphaddubq m3, [r0+r3] +%else + mova m0, [r0] +%if mmsize == 8 + mova m1, [r0+8] +%else + mova m1, [r0+r1] +%endif + punpckhbw m2, m0, m5 + punpcklbw m0, m5 + punpckhbw m3, m1, m5 + punpcklbw m1, m5 +%endif ; cpuflag(xop) + paddw m1, m0 + paddw m3, m2 + paddw m3, m1 + paddw m4, m3 +%if mmsize == 8 + add r0, r1 +%else + lea r0, [r0+r1*%4] +%endif + dec r2 + jne .loop +%if cpuflag(xop) + pshufd m0, m4, q0032 + paddd m4, m0 +%else + HADDW m4, m5 +%endif + movd eax, m4 + RET +%endmacro + +INIT_MMX mmx +PIX_SUM16 0, 16, 3, 0 +INIT_XMM sse2 +PIX_SUM16 6, 8, 3, 2 +%if HAVE_XOP_EXTERNAL +INIT_XMM xop +PIX_SUM16 5, 4, 4, 4 +%endif + +; int ff_pix_norm1_mmx(uint8_t *pix, int line_size) +; %1 = number of xmm registers used +; %2 = number of loops +%macro PIX_NORM1 2 +cglobal pix_norm1, 2, 3, %1 + movsxdifnidn r1, r1d + mov r2, %2 + pxor m0, m0 + pxor m5, m5 +.loop: + mova m2, [r0+0] +%if mmsize == 8 + mova m3, [r0+8] +%else + mova m3, [r0+r1] +%endif + punpckhbw m1, m2, m0 + punpcklbw m2, m0 + punpckhbw m4, m3, m0 + punpcklbw m3, m0 + pmaddwd m1, m1 + pmaddwd m2, m2 + pmaddwd m3, m3 + pmaddwd m4, m4 + paddd m2, m1 + paddd m4, m3 + paddd m5, m2 + paddd m5, m4 +%if mmsize == 8 + add r0, r1 +%else + lea r0, [r0+r1*2] +%endif + dec r2 + jne .loop + HADDD m5, m1 + movd eax, m5 + RET +%endmacro + +INIT_MMX mmx +PIX_NORM1 0, 16 +INIT_XMM sse2 +PIX_NORM1 6, 8 + diff --git a/libavcodec/x86/mpegvideoencdsp_init.c b/libavcodec/x86/mpegvideoencdsp_init.c new file mode 100644 index 000000000..d91b90218 --- /dev/null +++ b/libavcodec/x86/mpegvideoencdsp_init.c @@ -0,0 +1,265 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/avassert.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/mpegvideoencdsp.h" + +int ff_pix_sum16_mmx(uint8_t *pix, int line_size); +int ff_pix_sum16_sse2(uint8_t *pix, int line_size); +int ff_pix_sum16_xop(uint8_t *pix, int line_size); +int ff_pix_norm1_mmx(uint8_t *pix, int line_size); +int ff_pix_norm1_sse2(uint8_t *pix, int line_size); + +#if HAVE_INLINE_ASM + +#define PHADDD(a, t) \ + "movq " #a ", " #t " \n\t" \ + "psrlq $32, " #a " \n\t" \ + "paddd " #t ", " #a " \n\t" + +/* + * pmulhw: dst[0 - 15] = (src[0 - 15] * dst[0 - 15])[16 - 31] + * pmulhrw: dst[0 - 15] = (src[0 - 15] * dst[0 - 15] + 0x8000)[16 - 31] + * pmulhrsw: dst[0 - 15] = (src[0 - 15] * dst[0 - 15] + 0x4000)[15 - 30] + */ +#define PMULHRW(x, y, s, o) \ + "pmulhw " #s ", " #x " \n\t" \ + "pmulhw " #s ", " #y " \n\t" \ + "paddw " #o ", " #x " \n\t" \ + "paddw " #o ", " #y " \n\t" \ + "psraw $1, " #x " \n\t" \ + "psraw $1, " #y " \n\t" +#define DEF(x) x ## _mmx +#define SET_RND MOVQ_WONE +#define SCALE_OFFSET 1 + +#include "mpegvideoenc_qns_template.c" + +#undef DEF +#undef SET_RND +#undef SCALE_OFFSET +#undef PMULHRW + +#define DEF(x) x ## _3dnow +#define SET_RND(x) +#define SCALE_OFFSET 0 +#define PMULHRW(x, y, s, o) \ + "pmulhrw " #s ", " #x " \n\t" \ + "pmulhrw " #s ", " #y " \n\t" + +#include "mpegvideoenc_qns_template.c" + +#undef DEF +#undef SET_RND +#undef SCALE_OFFSET +#undef PMULHRW + +#if HAVE_SSSE3_INLINE +#undef PHADDD +#define DEF(x) x ## _ssse3 +#define SET_RND(x) +#define SCALE_OFFSET -1 + +#define PHADDD(a, t) \ + "pshufw $0x0E, " #a ", " #t " \n\t" \ + /* faster than phaddd on core2 */ \ + "paddd " #t ", " #a " \n\t" + +#define PMULHRW(x, y, s, o) \ + "pmulhrsw " #s ", " #x " \n\t" \ + "pmulhrsw " #s ", " #y " \n\t" + +#include "mpegvideoenc_qns_template.c" + +#undef DEF +#undef SET_RND +#undef SCALE_OFFSET +#undef PMULHRW +#undef PHADDD +#endif /* HAVE_SSSE3_INLINE */ + +/* Draw the edges of width 'w' of an image of size width, height + * this MMX version can only handle w == 8 || w == 16. */ +static void draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, + int w, int h, int sides) +{ + uint8_t *ptr, *last_line; + int i; + + last_line = buf + (height - 1) * wrap; + /* left and right */ + ptr = buf; + if (w == 8) { + __asm__ volatile ( + "1: \n\t" + "movd (%0), %%mm0 \n\t" + "punpcklbw %%mm0, %%mm0 \n\t" + "punpcklwd %%mm0, %%mm0 \n\t" + "punpckldq %%mm0, %%mm0 \n\t" + "movq %%mm0, -8(%0) \n\t" + "movq -8(%0, %2), %%mm1 \n\t" + "punpckhbw %%mm1, %%mm1 \n\t" + "punpckhwd %%mm1, %%mm1 \n\t" + "punpckhdq %%mm1, %%mm1 \n\t" + "movq %%mm1, (%0, %2) \n\t" + "add %1, %0 \n\t" + "cmp %3, %0 \n\t" + "jb 1b \n\t" + : "+r" (ptr) + : "r" ((x86_reg) wrap), "r" ((x86_reg) width), + "r" (ptr + wrap * height)); + } else if (w == 16) { + __asm__ volatile ( + "1: \n\t" + "movd (%0), %%mm0 \n\t" + "punpcklbw %%mm0, %%mm0 \n\t" + "punpcklwd %%mm0, %%mm0 \n\t" + "punpckldq %%mm0, %%mm0 \n\t" + "movq %%mm0, -8(%0) \n\t" + "movq %%mm0, -16(%0) \n\t" + "movq -8(%0, %2), %%mm1 \n\t" + "punpckhbw %%mm1, %%mm1 \n\t" + "punpckhwd %%mm1, %%mm1 \n\t" + "punpckhdq %%mm1, %%mm1 \n\t" + "movq %%mm1, (%0, %2) \n\t" + "movq %%mm1, 8(%0, %2) \n\t" + "add %1, %0 \n\t" + "cmp %3, %0 \n\t" + "jb 1b \n\t" + : "+r"(ptr) + : "r"((x86_reg)wrap), "r"((x86_reg)width), "r"(ptr + wrap * height) + ); + } else { + av_assert1(w == 4); + __asm__ volatile ( + "1: \n\t" + "movd (%0), %%mm0 \n\t" + "punpcklbw %%mm0, %%mm0 \n\t" + "punpcklwd %%mm0, %%mm0 \n\t" + "movd %%mm0, -4(%0) \n\t" + "movd -4(%0, %2), %%mm1 \n\t" + "punpcklbw %%mm1, %%mm1 \n\t" + "punpckhwd %%mm1, %%mm1 \n\t" + "punpckhdq %%mm1, %%mm1 \n\t" + "movd %%mm1, (%0, %2) \n\t" + "add %1, %0 \n\t" + "cmp %3, %0 \n\t" + "jb 1b \n\t" + : "+r" (ptr) + : "r" ((x86_reg) wrap), "r" ((x86_reg) width), + "r" (ptr + wrap * height)); + } + + /* top and bottom (and hopefully also the corners) */ + if (sides & EDGE_TOP) { + for (i = 0; i < h; i += 4) { + ptr = buf - (i + 1) * wrap - w; + __asm__ volatile ( + "1: \n\t" + "movq (%1, %0), %%mm0 \n\t" + "movq %%mm0, (%0) \n\t" + "movq %%mm0, (%0, %2) \n\t" + "movq %%mm0, (%0, %2, 2) \n\t" + "movq %%mm0, (%0, %3) \n\t" + "add $8, %0 \n\t" + "cmp %4, %0 \n\t" + "jb 1b \n\t" + : "+r" (ptr) + : "r" ((x86_reg) buf - (x86_reg) ptr - w), + "r" ((x86_reg) - wrap), "r" ((x86_reg) - wrap * 3), + "r" (ptr + width + 2 * w)); + } + } + + if (sides & EDGE_BOTTOM) { + for (i = 0; i < h; i += 4) { + ptr = last_line + (i + 1) * wrap - w; + __asm__ volatile ( + "1: \n\t" + "movq (%1, %0), %%mm0 \n\t" + "movq %%mm0, (%0) \n\t" + "movq %%mm0, (%0, %2) \n\t" + "movq %%mm0, (%0, %2, 2) \n\t" + "movq %%mm0, (%0, %3) \n\t" + "add $8, %0 \n\t" + "cmp %4, %0 \n\t" + "jb 1b \n\t" + : "+r" (ptr) + : "r" ((x86_reg) last_line - (x86_reg) ptr - w), + "r" ((x86_reg) wrap), "r" ((x86_reg) wrap * 3), + "r" (ptr + width + 2 * w)); + } + } +} + +#endif /* HAVE_INLINE_ASM */ + +av_cold void ff_mpegvideoencdsp_init_x86(MpegvideoEncDSPContext *c, + AVCodecContext *avctx) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_MMX(cpu_flags)) { + c->pix_sum = ff_pix_sum16_mmx; + c->pix_norm1 = ff_pix_norm1_mmx; + } + + if (EXTERNAL_SSE2(cpu_flags)) { + c->pix_sum = ff_pix_sum16_sse2; + c->pix_norm1 = ff_pix_norm1_sse2; + } + + if (EXTERNAL_XOP(cpu_flags)) { + c->pix_sum = ff_pix_sum16_xop; + } + +#if HAVE_INLINE_ASM + + if (INLINE_MMX(cpu_flags)) { + if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + c->try_8x8basis = try_8x8basis_mmx; + } + c->add_8x8basis = add_8x8basis_mmx; + + if (avctx->bits_per_raw_sample <= 8) { + c->draw_edges = draw_edges_mmx; + } + } + + if (INLINE_AMD3DNOW(cpu_flags)) { + if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + c->try_8x8basis = try_8x8basis_3dnow; + } + c->add_8x8basis = add_8x8basis_3dnow; + } + +#if HAVE_SSSE3_INLINE + if (INLINE_SSSE3(cpu_flags)) { + if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + c->try_8x8basis = try_8x8basis_ssse3; + } + c->add_8x8basis = add_8x8basis_ssse3; + } +#endif /* HAVE_SSSE3_INLINE */ + +#endif /* HAVE_INLINE_ASM */ +} diff --git a/libavcodec/x86/pixblockdsp.asm b/libavcodec/x86/pixblockdsp.asm new file mode 100644 index 000000000..00ee9b4ac --- /dev/null +++ b/libavcodec/x86/pixblockdsp.asm @@ -0,0 +1,135 @@ +;***************************************************************************** +;* SIMD-optimized pixel operations +;***************************************************************************** +;* Copyright (c) 2000, 2001 Fabrice Bellard +;* Copyright (c) 2002-2004 Michael Niedermayer +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;***************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION .text + +INIT_MMX mmx +; void ff_get_pixels_mmx(int16_t *block, const uint8_t *pixels, int line_size) +cglobal get_pixels, 3,4 + movsxdifnidn r2, r2d + add r0, 128 + mov r3, -128 + pxor m7, m7 +.loop: + mova m0, [r1] + mova m2, [r1+r2] + mova m1, m0 + mova m3, m2 + punpcklbw m0, m7 + punpckhbw m1, m7 + punpcklbw m2, m7 + punpckhbw m3, m7 + mova [r0+r3+ 0], m0 + mova [r0+r3+ 8], m1 + mova [r0+r3+16], m2 + mova [r0+r3+24], m3 + lea r1, [r1+r2*2] + add r3, 32 + js .loop + REP_RET + +INIT_XMM sse2 +cglobal get_pixels, 3, 4, 5 + movsxdifnidn r2, r2d + lea r3, [r2*3] + pxor m4, m4 + movh m0, [r1] + movh m1, [r1+r2] + movh m2, [r1+r2*2] + movh m3, [r1+r3] + lea r1, [r1+r2*4] + punpcklbw m0, m4 + punpcklbw m1, m4 + punpcklbw m2, m4 + punpcklbw m3, m4 + mova [r0], m0 + mova [r0+0x10], m1 + mova [r0+0x20], m2 + mova [r0+0x30], m3 + movh m0, [r1] + movh m1, [r1+r2*1] + movh m2, [r1+r2*2] + movh m3, [r1+r3] + punpcklbw m0, m4 + punpcklbw m1, m4 + punpcklbw m2, m4 + punpcklbw m3, m4 + mova [r0+0x40], m0 + mova [r0+0x50], m1 + mova [r0+0x60], m2 + mova [r0+0x70], m3 + RET + +INIT_MMX mmx +; void ff_diff_pixels_mmx(int16_t *block, const uint8_t *s1, const uint8_t *s2, +; int stride); +cglobal diff_pixels, 4,5 + movsxdifnidn r3, r3d + pxor m7, m7 + add r0, 128 + mov r4, -128 +.loop: + mova m0, [r1] + mova m2, [r2] + mova m1, m0 + mova m3, m2 + punpcklbw m0, m7 + punpckhbw m1, m7 + punpcklbw m2, m7 + punpckhbw m3, m7 + psubw m0, m2 + psubw m1, m3 + mova [r0+r4+0], m0 + mova [r0+r4+8], m1 + add r1, r3 + add r2, r3 + add r4, 16 + jne .loop + REP_RET + +INIT_XMM sse2 +cglobal diff_pixels, 4, 5, 5 + movsxdifnidn r3, r3d + pxor m4, m4 + add r0, 128 + mov r4, -128 +.loop: + movh m0, [r1] + movh m2, [r2] + movh m1, [r1+r3] + movh m3, [r2+r3] + punpcklbw m0, m4 + punpcklbw m1, m4 + punpcklbw m2, m4 + punpcklbw m3, m4 + psubw m0, m2 + psubw m1, m3 + mova [r0+r4+0 ], m0 + mova [r0+r4+16], m1 + lea r1, [r1+r3*2] + lea r2, [r2+r3*2] + add r4, 32 + jne .loop + RET diff --git a/libavcodec/x86/pixblockdsp_init.c b/libavcodec/x86/pixblockdsp_init.c new file mode 100644 index 000000000..4c31b802f --- /dev/null +++ b/libavcodec/x86/pixblockdsp_init.c @@ -0,0 +1,50 @@ +/* + * SIMD-optimized pixel operations + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/pixblockdsp.h" + +void ff_get_pixels_mmx(int16_t *block, const uint8_t *pixels, int line_size); +void ff_get_pixels_sse2(int16_t *block, const uint8_t *pixels, int line_size); +void ff_diff_pixels_mmx(int16_t *block, const uint8_t *s1, const uint8_t *s2, + int stride); +void ff_diff_pixels_sse2(int16_t *block, const uint8_t *s1, const uint8_t *s2, + int stride); + +av_cold void ff_pixblockdsp_init_x86(PixblockDSPContext *c, + AVCodecContext *avctx, + unsigned high_bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_MMX(cpu_flags)) { + if (!high_bit_depth) + c->get_pixels = ff_get_pixels_mmx; + c->diff_pixels = ff_diff_pixels_mmx; + } + + if (EXTERNAL_SSE2(cpu_flags)) { + if (!high_bit_depth) + c->get_pixels = ff_get_pixels_sse2; + c->diff_pixels = ff_diff_pixels_sse2; + } +} diff --git a/libavcodec/x86/proresdsp.asm b/libavcodec/x86/proresdsp.asm index aedacc2cd..255eb2489 100644 --- a/libavcodec/x86/proresdsp.asm +++ b/libavcodec/x86/proresdsp.asm @@ -231,8 +231,8 @@ section .text align=16 SUMSUB_SHPK m2, m3, m4, m5, m6, m7, %2 %endmacro -; void prores_idct_put_10_(uint8_t *pixels, int stride, -; int16_t *block, const int16_t *qmat); +; void ff_prores_idct_put_10_(uint8_t *pixels, int stride, +; int16_t *block, const int16_t *qmat); %macro idct_put_fn 1 cglobal prores_idct_put_10, 4, 4, %1 movsxd r1, r1d diff --git a/libavcodec/x86/proresdsp_init.c b/libavcodec/x86/proresdsp_init.c index 394025b68..6974ca494 100644 --- a/libavcodec/x86/proresdsp_init.c +++ b/libavcodec/x86/proresdsp_init.c @@ -22,7 +22,7 @@ #include "libavutil/attributes.h" #include "libavutil/x86/cpu.h" -#include "libavcodec/dsputil.h" +#include "libavcodec/idctdsp.h" #include "libavcodec/proresdsp.h" void ff_prores_idct_put_10_sse2(uint16_t *dst, int linesize, diff --git a/libavcodec/x86/qpel.asm b/libavcodec/x86/qpel.asm index c2ffb8671..4e72d5084 100644 --- a/libavcodec/x86/qpel.asm +++ b/libavcodec/x86/qpel.asm @@ -1,5 +1,5 @@ ;****************************************************************************** -;* MMX optimized DSP utils +;* SIMD-optimized quarterpel functions ;* Copyright (c) 2008 Loren Merritt ;* Copyright (c) 2003-2013 Michael Niedermayer ;* Copyright (c) 2013 Daniel Kang @@ -44,7 +44,8 @@ SECTION .text mova %2, %1 %endmacro -; void pixels4_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h) +; void ff_put/avg_pixels4_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, +; int dstStride, int src1Stride, int h) %macro PIXELS4_L2 1 %define OP op_%1h cglobal %1_pixels4_l2, 6,6 @@ -87,7 +88,8 @@ INIT_MMX mmxext PIXELS4_L2 put PIXELS4_L2 avg -; void pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h) +; void ff_put/avg_pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, +; int dstStride, int src1Stride, int h) %macro PIXELS8_L2 1 %define OP op_%1 cglobal %1_pixels8_l2, 6,6 @@ -130,7 +132,8 @@ INIT_MMX mmxext PIXELS8_L2 put PIXELS8_L2 avg -; void pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h) +; void ff_put/avg_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, +; int dstStride, int src1Stride, int h) %macro PIXELS16_L2 1 %define OP op_%1 cglobal %1_pixels16_l2, 6,6 diff --git a/libavcodec/x86/mpeg4qpel.asm b/libavcodec/x86/qpeldsp.asm similarity index 98% rename from libavcodec/x86/mpeg4qpel.asm rename to libavcodec/x86/qpeldsp.asm index ca52375a7..dc0f900c5 100644 --- a/libavcodec/x86/mpeg4qpel.asm +++ b/libavcodec/x86/qpeldsp.asm @@ -33,7 +33,7 @@ cextern pw_20 SECTION_TEXT -; put_no_rnd_pixels8_l2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h) +; 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 cglobal put_no_rnd_pixels8_l2, 6,6 movsxdifnidn r4, r4d @@ -99,7 +99,7 @@ INIT_MMX mmxext PUT_NO_RND_PIXELS8_L2 -; put_no_rnd_pixels16_l2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h) +; void ff_put_no_rnd_pixels16_l2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h) %macro PUT_NO_RND_PIXELS16_l2 0 cglobal put_no_rnd_pixels16_l2, 6,6 movsxdifnidn r3, r3d diff --git a/libavcodec/x86/qpeldsp_init.c b/libavcodec/x86/qpeldsp_init.c new file mode 100644 index 000000000..06b896026 --- /dev/null +++ b/libavcodec/x86/qpeldsp_init.c @@ -0,0 +1,503 @@ +/* + * quarterpel DSP functions + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/pixels.h" +#include "libavcodec/qpeldsp.h" +#include "fpel.h" + +void ff_put_pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_put_no_rnd_pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, + uint8_t *src2, int dstStride, + int src1Stride, int h); +void ff_avg_pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_put_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_avg_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_put_no_rnd_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_put_mpeg4_qpel16_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, int h); +void ff_avg_mpeg4_qpel16_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, int h); +void ff_put_no_rnd_mpeg4_qpel16_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, + int h); +void ff_put_mpeg4_qpel8_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, int h); +void ff_avg_mpeg4_qpel8_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, int h); +void ff_put_no_rnd_mpeg4_qpel8_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, + int h); +void ff_put_mpeg4_qpel16_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride); +void ff_avg_mpeg4_qpel16_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride); +void ff_put_no_rnd_mpeg4_qpel16_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride); +void ff_put_mpeg4_qpel8_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride); +void ff_avg_mpeg4_qpel8_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride); +void ff_put_no_rnd_mpeg4_qpel8_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride); +#define ff_put_no_rnd_pixels16_mmxext ff_put_pixels16_mmx +#define ff_put_no_rnd_pixels8_mmxext ff_put_pixels8_mmx + +#if HAVE_YASM + +#define ff_put_pixels16_mmxext ff_put_pixels16_mmx +#define ff_put_pixels8_mmxext ff_put_pixels8_mmx + +#define QPEL_OP(OPNAME, RND, MMX) \ +static void OPNAME ## qpel8_mc00_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_ ## OPNAME ## pixels8_ ## MMX(dst, src, stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc10_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[8]; \ + uint8_t *const half = (uint8_t *) temp; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, \ + stride, 8); \ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, src, half, \ + stride, stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc20_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_ ## OPNAME ## mpeg4_qpel8_h_lowpass_ ## MMX(dst, src, stride, \ + stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc30_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[8]; \ + uint8_t *const half = (uint8_t *) temp; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, \ + stride, 8); \ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, src + 1, half, stride, \ + stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc01_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[8]; \ + uint8_t *const half = (uint8_t *) temp; \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, \ + 8, stride); \ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, src, half, \ + stride, stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc02_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_ ## OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, src, \ + stride, stride); \ +} \ + \ +static void OPNAME ## qpel8_mc03_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[8]; \ + uint8_t *const half = (uint8_t *) temp; \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, \ + 8, stride); \ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, src + stride, half, stride,\ + stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc11_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t *const halfH = (uint8_t *) half + 64; \ + uint8_t *const halfHV = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, \ + stride, 9); \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, \ + stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc31_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t *const halfH = (uint8_t *) half + 64; \ + uint8_t *const halfHV = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src + 1, halfH, 8, \ + stride, 9); \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, \ + stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc13_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t *const halfH = (uint8_t *) half + 64; \ + uint8_t *const halfHV = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, \ + stride, 9); \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH + 8, halfHV, \ + stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc33_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t *const halfH = (uint8_t *) half + 64; \ + uint8_t *const halfHV = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src + 1, halfH, 8, \ + stride, 9); \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH + 8, halfHV, \ + stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc21_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t *const halfH = (uint8_t *) half + 64; \ + uint8_t *const halfHV = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, \ + stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc23_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t *const halfH = (uint8_t *) half + 64; \ + uint8_t *const halfHV = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH + 8, halfHV, \ + stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc12_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t *const halfH = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, \ + 8, stride, 9); \ + ff_ ## OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, \ + stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc32_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t *const halfH = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src + 1, halfH, 8, \ + stride, 9); \ + ff_ ## OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, \ + stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc22_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[9]; \ + uint8_t *const halfH = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_ ## OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, \ + stride, 8); \ +} \ + \ +static void OPNAME ## qpel16_mc00_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_ ## OPNAME ## pixels16_ ## MMX(dst, src, stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc10_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[32]; \ + uint8_t *const half = (uint8_t *) temp; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, \ + stride, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, \ + stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc20_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_ ## OPNAME ## mpeg4_qpel16_h_lowpass_ ## MMX(dst, src, \ + stride, stride, 16);\ +} \ + \ +static void OPNAME ## qpel16_mc30_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[32]; \ + uint8_t *const half = (uint8_t*) temp; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, \ + stride, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, src + 1, half, \ + stride, stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc01_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[32]; \ + uint8_t *const half = (uint8_t *) temp; \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, \ + stride); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, \ + stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc02_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_ ## OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, src, \ + stride, stride); \ +} \ + \ +static void OPNAME ## qpel16_mc03_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[32]; \ + uint8_t *const half = (uint8_t *) temp; \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, \ + stride); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, src+stride, half, \ + stride, stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc11_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[16 * 2 + 17 * 2]; \ + uint8_t *const halfH = (uint8_t *) half + 256; \ + uint8_t *const halfHV = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, \ + stride, 17); \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ + 16, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, \ + stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc31_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[16 * 2 + 17 * 2]; \ + uint8_t *const halfH = (uint8_t *) half + 256; \ + uint8_t *const halfHV = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src + 1, halfH, 16, \ + stride, 17); \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ + 16, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, \ + stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc13_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[16 * 2 + 17 * 2]; \ + uint8_t *const halfH = (uint8_t *) half + 256; \ + uint8_t *const halfHV = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, \ + stride, 17); \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ + 16, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH + 16, halfHV, \ + stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc33_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[16 * 2 + 17 * 2]; \ + uint8_t *const halfH = (uint8_t *) half + 256; \ + uint8_t *const halfHV = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src + 1, halfH, 16, \ + stride, 17); \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ + 16, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH + 16, halfHV, \ + stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc21_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[16 * 2 + 17 * 2]; \ + uint8_t *const halfH = (uint8_t *) half + 256; \ + uint8_t *const halfHV = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ + 16, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, \ + stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc23_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[16 * 2 + 17 * 2]; \ + uint8_t *const halfH = (uint8_t *) half + 256; \ + uint8_t *const halfHV = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ + 16, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH + 16, halfHV, \ + stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc12_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[17 * 2]; \ + uint8_t *const halfH = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, \ + stride, 17); \ + ff_ ## OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, \ + stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc32_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[17 * 2]; \ + uint8_t *const halfH = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src + 1, halfH, 16, \ + stride, 17); \ + ff_ ## OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, \ + stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc22_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[17 * 2]; \ + uint8_t *const halfH = (uint8_t *) half; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_ ## OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, \ + stride, 16); \ +} + +QPEL_OP(put_, _, mmxext) +QPEL_OP(avg_, _, mmxext) +QPEL_OP(put_no_rnd_, _no_rnd_, mmxext) + +#endif /* HAVE_YASM */ + +#define SET_QPEL_FUNCS(PFX, IDX, SIZE, CPU, PREFIX) \ +do { \ + c->PFX ## _pixels_tab[IDX][ 0] = PREFIX ## PFX ## SIZE ## _mc00_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 1] = PREFIX ## PFX ## SIZE ## _mc10_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 2] = PREFIX ## PFX ## SIZE ## _mc20_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 3] = PREFIX ## PFX ## SIZE ## _mc30_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 4] = PREFIX ## PFX ## SIZE ## _mc01_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 5] = PREFIX ## PFX ## SIZE ## _mc11_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 6] = PREFIX ## PFX ## SIZE ## _mc21_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 7] = PREFIX ## PFX ## SIZE ## _mc31_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 8] = PREFIX ## PFX ## SIZE ## _mc02_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 9] = PREFIX ## PFX ## SIZE ## _mc12_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][10] = PREFIX ## PFX ## SIZE ## _mc22_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][11] = PREFIX ## PFX ## SIZE ## _mc32_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][12] = PREFIX ## PFX ## SIZE ## _mc03_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][13] = PREFIX ## PFX ## SIZE ## _mc13_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][14] = PREFIX ## PFX ## SIZE ## _mc23_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][15] = PREFIX ## PFX ## SIZE ## _mc33_ ## CPU; \ +} while (0) + +av_cold void ff_qpeldsp_init_x86(QpelDSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (X86_MMXEXT(cpu_flags)) { +#if HAVE_MMXEXT_EXTERNAL + SET_QPEL_FUNCS(avg_qpel, 0, 16, mmxext, ); + SET_QPEL_FUNCS(avg_qpel, 1, 8, mmxext, ); + + SET_QPEL_FUNCS(put_qpel, 0, 16, mmxext, ); + SET_QPEL_FUNCS(put_qpel, 1, 8, mmxext, ); + SET_QPEL_FUNCS(put_no_rnd_qpel, 0, 16, mmxext, ); + SET_QPEL_FUNCS(put_no_rnd_qpel, 1, 8, mmxext, ); +#endif /* HAVE_MMXEXT_EXTERNAL */ + } +} diff --git a/libavcodec/x86/rnd_template.c b/libavcodec/x86/rnd_template.c index e37fc1950..c9fd71eee 100644 --- a/libavcodec/x86/rnd_template.c +++ b/libavcodec/x86/rnd_template.c @@ -1,5 +1,5 @@ /* - * DSP utils mmx functions are compiled twice for rnd/no_rnd + * SIMD-optimized halfpel functions are compiled twice for rnd/no_rnd * Copyright (c) 2000, 2001 Fabrice Bellard * Copyright (c) 2003-2004 Michael Niedermayer * @@ -27,6 +27,8 @@ #include #include +#include "inline_asm.h" + // put_pixels STATIC void DEF(put, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) diff --git a/libavcodec/x86/rv40dsp.asm b/libavcodec/x86/rv40dsp.asm index 792a54f57..fdd81a0a3 100644 --- a/libavcodec/x86/rv40dsp.asm +++ b/libavcodec/x86/rv40dsp.asm @@ -1,7 +1,7 @@ ;****************************************************************************** ;* MMX/SSE2-optimized functions for the RV40 decoder ;* Copyright (c) 2010 Ronald S. Bultje -;* Copyright (c) 2010 Jason Garrett-Glaser +;* Copyright (c) 2010 Fiona Glaser ;* Copyright (C) 2012 Christophe Gisquet ;* ;* This file is part of FFmpeg. @@ -77,9 +77,9 @@ SECTION .text ;----------------------------------------------------------------------------- ; subpel MC functions: ; -; void [put|rv40]_rv40_qpel_[h|v]_(uint8_t *dst, int deststride, -; uint8_t *src, int srcstride, -; int len, int m); +; void ff_[put|rv40]_rv40_qpel_[h|v]_(uint8_t *dst, int deststride, +; uint8_t *src, int srcstride, +; int len, int m); ;---------------------------------------------------------------------- %macro LOAD 2 %if WIN64 @@ -438,7 +438,7 @@ FILTER_SSSE3 avg %endmacro -; rv40_weight_func_%1(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w1, int w2, int stride) +; void ff_rv40_weight_func_%1(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w1, int w2, int stride) ; %1=size %2=num of xmm regs ; The weights are FP0.14 notation of fractions depending on pts. ; For timebases without rounding error (i.e. PAL), the fractions diff --git a/libavcodec/x86/rv40dsp_init.c b/libavcodec/x86/rv40dsp_init.c index 75ba8ba12..209c3c4a1 100644 --- a/libavcodec/x86/rv40dsp_init.c +++ b/libavcodec/x86/rv40dsp_init.c @@ -30,7 +30,14 @@ #include "libavutil/attributes.h" #include "libavutil/mem.h" #include "libavutil/x86/cpu.h" -#include "dsputil_x86.h" +#include "hpeldsp.h" + +#define DEFINE_FN(op, size, insn) \ +static void op##_rv40_qpel##size##_mc33_##insn(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_##op##_pixels##size##_xy2_##insn(dst, src, stride, size); \ +} #if HAVE_YASM void ff_put_rv40_chroma_mc8_mmx (uint8_t *dst, uint8_t *src, @@ -127,8 +134,8 @@ QPEL_FUNCS_DECL(OP, 3, 2, OPT) /** @} */ #define LOOPSIZE 8 -#define HCOFF(x) (32 * (x - 1)) -#define VCOFF(x) (32 * (x - 1)) +#define HCOFF(x) (32 * ((x) - 1)) +#define VCOFF(x) (32 * ((x) - 1)) QPEL_MC_DECL(put_, _ssse3) QPEL_MC_DECL(avg_, _ssse3) @@ -136,8 +143,8 @@ QPEL_MC_DECL(avg_, _ssse3) #undef HCOFF #undef VCOFF #define LOOPSIZE 8 -#define HCOFF(x) (64 * (x - 1)) -#define VCOFF(x) (64 * (x - 1)) +#define HCOFF(x) (64 * ((x) - 1)) +#define VCOFF(x) (64 * ((x) - 1)) QPEL_MC_DECL(put_, _sse2) QPEL_MC_DECL(avg_, _sse2) @@ -146,8 +153,8 @@ QPEL_MC_DECL(avg_, _sse2) #undef HCOFF #undef VCOFF #define LOOPSIZE 4 -#define HCOFF(x) (64 * (x - 1)) -#define VCOFF(x) (64 * (x - 1)) +#define HCOFF(x) (64 * ((x) - 1)) +#define VCOFF(x) (64 * ((x) - 1)) QPEL_MC_DECL(put_, _mmx) @@ -186,30 +193,24 @@ QPEL_FUNCS_SET (OP, 3, 1, OPT) \ QPEL_FUNCS_SET (OP, 3, 2, OPT) /** @} */ +DEFINE_FN(put, 8, ssse3) + +DEFINE_FN(put, 16, sse2) +DEFINE_FN(put, 16, ssse3) + +DEFINE_FN(avg, 8, mmxext) +DEFINE_FN(avg, 8, ssse3) + +DEFINE_FN(avg, 16, sse2) +DEFINE_FN(avg, 16, ssse3) #endif /* HAVE_YASM */ #if HAVE_MMX_INLINE -static void put_rv40_qpel8_mc33_mmx(uint8_t *dst, uint8_t *src, - ptrdiff_t stride) -{ - ff_put_pixels8_xy2_mmx(dst, src, stride, 8); -} -static void put_rv40_qpel16_mc33_mmx(uint8_t *dst, uint8_t *src, - ptrdiff_t stride) -{ - ff_put_pixels16_xy2_mmx(dst, src, stride, 16); -} -static void avg_rv40_qpel8_mc33_mmx(uint8_t *dst, uint8_t *src, - ptrdiff_t stride) -{ - ff_avg_pixels8_xy2_mmx(dst, src, stride, 8); -} -static void avg_rv40_qpel16_mc33_mmx(uint8_t *dst, uint8_t *src, - ptrdiff_t stride) -{ - ff_avg_pixels16_xy2_mmx(dst, src, stride, 16); -} -#endif /* HAVE_MMX_INLINE */ +DEFINE_FN(put, 8, mmx) +DEFINE_FN(avg, 8, mmx) +DEFINE_FN(put, 16, mmx) +DEFINE_FN(avg, 16, mmx) +#endif av_cold void ff_rv40dsp_init_x86(RV34DSPContext *c) { @@ -240,6 +241,7 @@ av_cold void ff_rv40dsp_init_x86(RV34DSPContext *c) #endif } if (EXTERNAL_MMXEXT(cpu_flags)) { + c->avg_pixels_tab[1][15] = avg_rv40_qpel8_mc33_mmxext; c->avg_chroma_pixels_tab[0] = ff_avg_rv40_chroma_mc8_mmxext; c->avg_chroma_pixels_tab[1] = ff_avg_rv40_chroma_mc4_mmxext; c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_mmxext; @@ -251,6 +253,8 @@ av_cold void ff_rv40dsp_init_x86(RV34DSPContext *c) #endif } if (EXTERNAL_SSE2(cpu_flags)) { + c->put_pixels_tab[0][15] = put_rv40_qpel16_mc33_sse2; + c->avg_pixels_tab[0][15] = avg_rv40_qpel16_mc33_sse2; c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_sse2; c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_sse2; c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_sse2; @@ -259,6 +263,10 @@ av_cold void ff_rv40dsp_init_x86(RV34DSPContext *c) QPEL_MC_SET(avg_, _sse2) } if (EXTERNAL_SSSE3(cpu_flags)) { + c->put_pixels_tab[0][15] = put_rv40_qpel16_mc33_ssse3; + c->put_pixels_tab[1][15] = put_rv40_qpel8_mc33_ssse3; + c->avg_pixels_tab[0][15] = avg_rv40_qpel16_mc33_ssse3; + c->avg_pixels_tab[1][15] = avg_rv40_qpel8_mc33_ssse3; c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_ssse3; c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_ssse3; c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_ssse3; diff --git a/libavcodec/x86/sbrdsp.asm b/libavcodec/x86/sbrdsp.asm index adc13c435..d556f2711 100644 --- a/libavcodec/x86/sbrdsp.asm +++ b/libavcodec/x86/sbrdsp.asm @@ -124,9 +124,9 @@ cglobal sbr_hf_g_filt, 5, 6, 5 .end: RET -; static void sbr_hf_gen_c(float (*X_high)[2], const float (*X_low)[2], -; const float alpha0[2], const float alpha1[2], -; float bw, int start, int end) +; void ff_sbr_hf_gen_sse(float (*X_high)[2], const float (*X_low)[2], +; const float alpha0[2], const float alpha1[2], +; float bw, int start, int end) ; cglobal sbr_hf_gen, 4,4,8, X_high, X_low, alpha0, alpha1, BW, S, E ; load alpha factors @@ -249,7 +249,7 @@ cglobal sbr_neg_odd_64, 1,2,4,z jne .loop REP_RET -; sbr_qmf_deint_bfly(float *v, const float *src0, const float *src1) +; void ff_sbr_qmf_deint_bfly_sse2(float *v, const float *src0, const float *src1) %macro SBR_QMF_DEINT_BFLY 0 cglobal sbr_qmf_deint_bfly, 3,5,8, v,src0,src1,vrev,c mov cq, 64*4-2*mmsize @@ -423,3 +423,25 @@ apply_noise_main: add count, mmsize jl .loop RET + +INIT_XMM sse +cglobal sbr_qmf_deint_neg, 2,4,4,v,src,vrev,c +%define COUNT 32*4 +%define OFFSET 32*4 + mov cq, -COUNT + lea vrevq, [vq + OFFSET + COUNT] + add vq, OFFSET-mmsize + add srcq, 2*COUNT + mova m3, [ps_neg] +.loop: + mova m0, [srcq + 2*cq + 0*mmsize] + mova m1, [srcq + 2*cq + 1*mmsize] + shufps m2, m0, m1, q2020 + shufps m1, m0, q1313 + xorps m2, m3 + mova [vq], m1 + mova [vrevq + cq], m2 + sub vq, mmsize + add cq, mmsize + jl .loop + REP_RET diff --git a/libavcodec/x86/sbrdsp_init.c b/libavcodec/x86/sbrdsp_init.c index 2b912d0e9..a2aca742c 100644 --- a/libavcodec/x86/sbrdsp_init.c +++ b/libavcodec/x86/sbrdsp_init.c @@ -51,6 +51,8 @@ void ff_sbr_hf_apply_noise_3_sse2(float (*Y)[2], const float *s_m, const float *q_filt, int noise, int kx, int m_max); +void ff_sbr_qmf_deint_neg_sse(float *v, const float *src); + av_cold void ff_sbrdsp_init_x86(SBRDSPContext *s) { int cpu_flags = av_get_cpu_flags(); @@ -63,6 +65,7 @@ av_cold void ff_sbrdsp_init_x86(SBRDSPContext *s) s->hf_gen = ff_sbr_hf_gen_sse; s->qmf_post_shuffle = ff_sbr_qmf_post_shuffle_sse; s->qmf_deint_bfly = ff_sbr_qmf_deint_bfly_sse; + s->qmf_deint_neg = ff_sbr_qmf_deint_neg_sse; } if (EXTERNAL_SSE2(cpu_flags)) { diff --git a/libavcodec/x86/simple_idct.c b/libavcodec/x86/simple_idct.c index c666b1a6d..bebc509f6 100644 --- a/libavcodec/x86/simple_idct.c +++ b/libavcodec/x86/simple_idct.c @@ -21,7 +21,8 @@ */ #include "libavcodec/simple_idct.h" #include "libavutil/mem.h" -#include "dsputil_x86.h" +#include "libavutil/x86/asm.h" +#include "idctdsp.h" #if HAVE_INLINE_ASM @@ -1142,6 +1143,7 @@ Temp "9: \n\t" :: "r" (block), "r" (temp), "r" (coeffs) + NAMED_CONSTRAINTS_ADD(wm1010,d40000) : "%eax" ); } diff --git a/libavcodec/x86/snowdsp.c b/libavcodec/x86/snowdsp.c index 735e7905a..67cb868ad 100644 --- a/libavcodec/x86/snowdsp.c +++ b/libavcodec/x86/snowdsp.c @@ -606,6 +606,7 @@ static void ff_snow_vertical_compose97i_mmx(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM } #endif //HAVE_7REGS +#if HAVE_6REGS #define snow_inner_add_yblock_sse2_header \ IDWTELEM * * dst_array = sb->line + src_y;\ x86_reg tmp;\ @@ -671,6 +672,7 @@ static void ff_snow_vertical_compose97i_mmx(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM :"+m"(dst8),"+m"(dst_array),"=&r"(tmp)\ :\ "rm"((x86_reg)(src_x<<1)),"m"(obmc),"a"(block),"m"(b_h),"m"(src_stride):\ + XMM_CLOBBERS("%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", )\ "%"REG_c"","%"REG_S"","%"REG_D"","%"REG_d""); #define snow_inner_add_yblock_sse2_end_8\ @@ -872,6 +874,7 @@ static void ff_snow_inner_add_yblock_mmx(const uint8_t *obmc, const int obmc_str else ff_snow_inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); } +#endif /* HAVE_6REGS */ #endif /* HAVE_INLINE_ASM */ @@ -886,7 +889,9 @@ void ff_dwt_init_x86(SnowDWTContext *c) #if HAVE_7REGS c->vertical_compose97i = ff_snow_vertical_compose97i_sse2; #endif +#if HAVE_6REGS c->inner_add_yblock = ff_snow_inner_add_yblock_sse2; +#endif } else{ if (mm_flags & AV_CPU_FLAG_MMXEXT) { @@ -895,7 +900,9 @@ void ff_dwt_init_x86(SnowDWTContext *c) c->vertical_compose97i = ff_snow_vertical_compose97i_mmx; #endif } +#if HAVE_6REGS c->inner_add_yblock = ff_snow_inner_add_yblock_mmx; +#endif } } #endif /* HAVE_INLINE_ASM */ diff --git a/libavcodec/x86/svq1enc.asm b/libavcodec/x86/svq1enc.asm new file mode 100644 index 000000000..5fb336143 --- /dev/null +++ b/libavcodec/x86/svq1enc.asm @@ -0,0 +1,61 @@ +;****************************************************************************** +;* SIMD-optimized SVQ1 encoder functions +;* Copyright (c) 2007 Loren Merritt +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_TEXT + +%macro SSD_INT8_VS_INT16 0 +cglobal ssd_int8_vs_int16, 3, 3, 3, pix1, pix2, size + pxor m0, m0 +.loop + sub sizeq, 8 + movq m1, [pix1q + sizeq] + movu m2, [pix2q + sizeq*2] +%if mmsize == 8 + movq m3, [pix2q + sizeq*2 + mmsize] + punpckhbw m4, m1 + punpcklbw m1, m1 + psraw m4, 8 + psraw m1, 8 + psubw m3, m4 + psubw m2, m1 + pmaddwd m3, m3 + pmaddwd m2, m2 + paddd m0, m3 + paddd m0, m2 +%else + punpcklbw m1, m1 + psraw m1, 8 + psubw m2, m1 + pmaddwd m2, m2 + paddd m0, m2 +%endif + jg .loop + HADDD m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_MMX mmx +SSD_INT8_VS_INT16 +INIT_XMM sse2 +SSD_INT8_VS_INT16 diff --git a/libavcodec/x86/svq1enc_init.c b/libavcodec/x86/svq1enc_init.c new file mode 100644 index 000000000..40b4b0e18 --- /dev/null +++ b/libavcodec/x86/svq1enc_init.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2007 Loren Merritt + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/svq1enc.h" + +int ff_ssd_int8_vs_int16_mmx(const int8_t *pix1, const int16_t *pix2, + intptr_t size); +int ff_ssd_int8_vs_int16_sse2(const int8_t *pix1, const int16_t *pix2, + intptr_t size); + +av_cold void ff_svq1enc_init_x86(SVQ1EncContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_MMX(cpu_flags)) { + c->ssd_int8_vs_int16 = ff_ssd_int8_vs_int16_mmx; + } + if (EXTERNAL_SSE2(cpu_flags)) { + c->ssd_int8_vs_int16 = ff_ssd_int8_vs_int16_sse2; + } +} diff --git a/libavcodec/x86/vc1dsp_init.c b/libavcodec/x86/vc1dsp_init.c index 9bd5ae366..2bef5f5fb 100644 --- a/libavcodec/x86/vc1dsp_init.c +++ b/libavcodec/x86/vc1dsp_init.c @@ -27,8 +27,9 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/x86/cpu.h" +#include "libavutil/x86/asm.h" #include "libavcodec/vc1dsp.h" -#include "dsputil_x86.h" +#include "fpel.h" #include "vc1dsp.h" #include "config.h" @@ -62,12 +63,17 @@ static void vc1_h_loop_filter16_sse4(uint8_t *src, int stride, int pq) ff_vc1_h_loop_filter8_sse4(src, stride, pq); ff_vc1_h_loop_filter8_sse4(src+8*stride, stride, pq); } - static void avg_vc1_mspel_mc00_mmxext(uint8_t *dst, const uint8_t *src, ptrdiff_t stride, int rnd) { ff_avg_pixels8_mmxext(dst, src, stride, 8); } +static void avg_vc1_mspel_mc00_16_sse2(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int rnd) +{ + ff_avg_pixels16_sse2(dst, src, stride, 16); +} + #endif /* HAVE_YASM */ void ff_put_vc1_chroma_mc8_nornd_mmx (uint8_t *dst, uint8_t *src, @@ -86,10 +92,10 @@ av_cold void ff_vc1dsp_init_x86(VC1DSPContext *dsp) { int cpu_flags = av_get_cpu_flags(); - if (INLINE_MMX(cpu_flags)) + if (HAVE_6REGS && INLINE_MMX(cpu_flags)) ff_vc1dsp_init_mmx(dsp); - if (INLINE_MMXEXT(cpu_flags)) + if (HAVE_6REGS && INLINE_MMXEXT(cpu_flags)) ff_vc1dsp_init_mmxext(dsp); #define ASSIGN_LF(EXT) \ @@ -111,13 +117,14 @@ av_cold void ff_vc1dsp_init_x86(VC1DSPContext *dsp) ASSIGN_LF(mmxext); dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_nornd_mmxext; - dsp->avg_vc1_mspel_pixels_tab[0] = avg_vc1_mspel_mc00_mmxext; + dsp->avg_vc1_mspel_pixels_tab[1][0] = avg_vc1_mspel_mc00_mmxext; } if (EXTERNAL_SSE2(cpu_flags)) { dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_sse2; dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_sse2; dsp->vc1_v_loop_filter16 = vc1_v_loop_filter16_sse2; dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_sse2; + dsp->avg_vc1_mspel_pixels_tab[0][0] = avg_vc1_mspel_mc00_16_sse2; } if (EXTERNAL_SSSE3(cpu_flags)) { ASSIGN_LF(ssse3); diff --git a/libavcodec/x86/vc1dsp_mmx.c b/libavcodec/x86/vc1dsp_mmx.c index 5ceacd348..77a8e359f 100644 --- a/libavcodec/x86/vc1dsp_mmx.c +++ b/libavcodec/x86/vc1dsp_mmx.c @@ -30,10 +30,10 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/vc1dsp.h" #include "constants.h" -#include "dsputil_x86.h" +#include "fpel.h" #include "vc1dsp.h" -#if HAVE_INLINE_ASM +#if HAVE_6REGS && HAVE_INLINE_ASM #define OP_PUT(S,D) #define OP_AVG(S,D) "pavgb " #S ", " #D " \n\t" @@ -110,6 +110,7 @@ static void vc1_put_ver_16b_shift2_mmx(int16_t *dst, : "+r"(src), "+r"(dst) : "r"(stride), "r"(-2*stride), "m"(shift), "m"(rnd), "r"(9*stride-4) + NAMED_CONSTRAINTS_ADD(ff_pw_9) : "%"REG_c, "memory" ); } @@ -154,6 +155,7 @@ static void OPNAME ## vc1_hor_16b_shift2_mmx(uint8_t *dst, x86_reg stride,\ "jnz 1b \n\t"\ : "+r"(h), "+r" (src), "+r" (dst)\ : "r"(stride), "m"(rnd)\ + NAMED_CONSTRAINTS_ADD(ff_pw_128,ff_pw_9)\ : "memory"\ );\ } @@ -212,6 +214,7 @@ static void OPNAME ## vc1_shift2_mmx(uint8_t *dst, const uint8_t *src,\ : "+r"(src), "+r"(dst)\ : "r"(offset), "r"(-2*offset), "g"(stride), "m"(rnd),\ "g"(stride-offset)\ + NAMED_CONSTRAINTS_ADD(ff_pw_9)\ : "%"REG_c, "memory"\ );\ } @@ -314,6 +317,7 @@ vc1_put_ver_16b_ ## NAME ## _mmx(int16_t *dst, const uint8_t *src, \ : "+r"(h), "+r" (src), "+r" (dst) \ : "r"(src_stride), "r"(3*src_stride), \ "m"(rnd), "m"(shift) \ + NAMED_CONSTRAINTS_ADD(ff_pw_3,ff_pw_53,ff_pw_18) \ : "memory" \ ); \ } @@ -351,6 +355,7 @@ OPNAME ## vc1_hor_16b_ ## NAME ## _mmx(uint8_t *dst, x86_reg stride, \ "jnz 1b \n\t" \ : "+r"(h), "+r" (src), "+r" (dst) \ : "r"(stride), "m"(rnd) \ + NAMED_CONSTRAINTS_ADD(ff_pw_3,ff_pw_18,ff_pw_53,ff_pw_128) \ : "memory" \ ); \ } @@ -386,6 +391,7 @@ OPNAME ## vc1_## NAME ## _mmx(uint8_t *dst, const uint8_t *src, \ "jnz 1b \n\t" \ : "+r"(h), "+r" (src), "+r" (dst) \ : "r"(offset), "r"(3*offset), "g"(stride), "m"(rnd) \ + NAMED_CONSTRAINTS_ADD(ff_pw_53,ff_pw_18,ff_pw_3) \ : "memory" \ ); \ } @@ -456,6 +462,15 @@ static void OP ## vc1_mspel_mc(uint8_t *dst, const uint8_t *src, int stride,\ \ /* Horizontal mode with no vertical mode */\ vc1_put_shift_8bits[hmode](dst, src, stride, rnd, 1);\ +} \ +static void OP ## vc1_mspel_mc_16(uint8_t *dst, const uint8_t *src, \ + int stride, int hmode, int vmode, int rnd)\ +{ \ + OP ## vc1_mspel_mc(dst + 0, src + 0, stride, hmode, vmode, rnd); \ + OP ## vc1_mspel_mc(dst + 8, src + 8, stride, hmode, vmode, rnd); \ + dst += 8*stride; src += 8*stride; \ + OP ## vc1_mspel_mc(dst + 0, src + 0, stride, hmode, vmode, rnd); \ + OP ## vc1_mspel_mc(dst + 8, src + 8, stride, hmode, vmode, rnd); \ } VC1_MSPEL_MC(put_) @@ -476,6 +491,20 @@ static void avg_vc1_mspel_mc ## a ## b ## _mmxext(uint8_t *dst, \ int rnd) \ { \ avg_vc1_mspel_mc(dst, src, stride, a, b, rnd); \ +}\ +static void put_vc1_mspel_mc ## a ## b ## _16_mmx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, \ + int rnd) \ +{ \ + put_vc1_mspel_mc_16(dst, src, stride, a, b, rnd); \ +}\ +static void avg_vc1_mspel_mc ## a ## b ## _16_mmxext(uint8_t *dst, \ + const uint8_t *src,\ + ptrdiff_t stride, \ + int rnd) \ +{ \ + avg_vc1_mspel_mc_16(dst, src, stride, a, b, rnd); \ } DECLARE_FUNCTION(0, 1) @@ -699,59 +728,83 @@ static void vc1_inv_trans_8x8_dc_mmxext(uint8_t *dest, int linesize, ); } +#if HAVE_MMX_EXTERNAL static void put_vc1_mspel_mc00_mmx(uint8_t *dst, const uint8_t *src, ptrdiff_t stride, int rnd) { ff_put_pixels8_mmx(dst, src, stride, 8); } +static void put_vc1_mspel_mc00_16_mmx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int rnd) +{ + ff_put_pixels16_mmx(dst, src, stride, 16); +} +static void avg_vc1_mspel_mc00_mmx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int rnd) +{ + ff_avg_pixels8_mmx(dst, src, stride, 8); +} +static void avg_vc1_mspel_mc00_16_mmx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int rnd) +{ + ff_avg_pixels16_mmx(dst, src, stride, 16); +} +#endif + +#define FN_ASSIGN(OP, X, Y, INSN) \ + dsp->OP##vc1_mspel_pixels_tab[1][X+4*Y] = OP##vc1_mspel_mc##X##Y##INSN; \ + dsp->OP##vc1_mspel_pixels_tab[0][X+4*Y] = OP##vc1_mspel_mc##X##Y##_16##INSN av_cold void ff_vc1dsp_init_mmx(VC1DSPContext *dsp) { - dsp->put_vc1_mspel_pixels_tab[ 0] = put_vc1_mspel_mc00_mmx; - dsp->put_vc1_mspel_pixels_tab[ 4] = put_vc1_mspel_mc01_mmx; - dsp->put_vc1_mspel_pixels_tab[ 8] = put_vc1_mspel_mc02_mmx; - dsp->put_vc1_mspel_pixels_tab[12] = put_vc1_mspel_mc03_mmx; +#if HAVE_MMX_EXTERNAL + FN_ASSIGN(put_, 0, 0, _mmx); + FN_ASSIGN(avg_, 0, 0, _mmx); +#endif + FN_ASSIGN(put_, 0, 1, _mmx); + FN_ASSIGN(put_, 0, 2, _mmx); + FN_ASSIGN(put_, 0, 3, _mmx); - dsp->put_vc1_mspel_pixels_tab[ 1] = put_vc1_mspel_mc10_mmx; - dsp->put_vc1_mspel_pixels_tab[ 5] = put_vc1_mspel_mc11_mmx; - dsp->put_vc1_mspel_pixels_tab[ 9] = put_vc1_mspel_mc12_mmx; - dsp->put_vc1_mspel_pixels_tab[13] = put_vc1_mspel_mc13_mmx; + FN_ASSIGN(put_, 1, 0, _mmx); + FN_ASSIGN(put_, 1, 1, _mmx); + FN_ASSIGN(put_, 1, 2, _mmx); + FN_ASSIGN(put_, 1, 3, _mmx); - dsp->put_vc1_mspel_pixels_tab[ 2] = put_vc1_mspel_mc20_mmx; - dsp->put_vc1_mspel_pixels_tab[ 6] = put_vc1_mspel_mc21_mmx; - dsp->put_vc1_mspel_pixels_tab[10] = put_vc1_mspel_mc22_mmx; - dsp->put_vc1_mspel_pixels_tab[14] = put_vc1_mspel_mc23_mmx; + FN_ASSIGN(put_, 2, 0, _mmx); + FN_ASSIGN(put_, 2, 1, _mmx); + FN_ASSIGN(put_, 2, 2, _mmx); + FN_ASSIGN(put_, 2, 3, _mmx); - dsp->put_vc1_mspel_pixels_tab[ 3] = put_vc1_mspel_mc30_mmx; - dsp->put_vc1_mspel_pixels_tab[ 7] = put_vc1_mspel_mc31_mmx; - dsp->put_vc1_mspel_pixels_tab[11] = put_vc1_mspel_mc32_mmx; - dsp->put_vc1_mspel_pixels_tab[15] = put_vc1_mspel_mc33_mmx; + FN_ASSIGN(put_, 3, 0, _mmx); + FN_ASSIGN(put_, 3, 1, _mmx); + FN_ASSIGN(put_, 3, 2, _mmx); + FN_ASSIGN(put_, 3, 3, _mmx); } av_cold void ff_vc1dsp_init_mmxext(VC1DSPContext *dsp) { - dsp->avg_vc1_mspel_pixels_tab[ 4] = avg_vc1_mspel_mc01_mmxext; - dsp->avg_vc1_mspel_pixels_tab[ 8] = avg_vc1_mspel_mc02_mmxext; - dsp->avg_vc1_mspel_pixels_tab[12] = avg_vc1_mspel_mc03_mmxext; + FN_ASSIGN(avg_, 0, 1, _mmxext); + FN_ASSIGN(avg_, 0, 2, _mmxext); + FN_ASSIGN(avg_, 0, 3, _mmxext); - dsp->avg_vc1_mspel_pixels_tab[ 1] = avg_vc1_mspel_mc10_mmxext; - dsp->avg_vc1_mspel_pixels_tab[ 5] = avg_vc1_mspel_mc11_mmxext; - dsp->avg_vc1_mspel_pixels_tab[ 9] = avg_vc1_mspel_mc12_mmxext; - dsp->avg_vc1_mspel_pixels_tab[13] = avg_vc1_mspel_mc13_mmxext; + FN_ASSIGN(avg_, 1, 0, _mmxext); + FN_ASSIGN(avg_, 1, 1, _mmxext); + FN_ASSIGN(avg_, 1, 2, _mmxext); + FN_ASSIGN(avg_, 1, 3, _mmxext); - dsp->avg_vc1_mspel_pixels_tab[ 2] = avg_vc1_mspel_mc20_mmxext; - dsp->avg_vc1_mspel_pixels_tab[ 6] = avg_vc1_mspel_mc21_mmxext; - dsp->avg_vc1_mspel_pixels_tab[10] = avg_vc1_mspel_mc22_mmxext; - dsp->avg_vc1_mspel_pixels_tab[14] = avg_vc1_mspel_mc23_mmxext; + FN_ASSIGN(avg_, 2, 0, _mmxext); + FN_ASSIGN(avg_, 2, 1, _mmxext); + FN_ASSIGN(avg_, 2, 2, _mmxext); + FN_ASSIGN(avg_, 2, 3, _mmxext); - dsp->avg_vc1_mspel_pixels_tab[ 3] = avg_vc1_mspel_mc30_mmxext; - dsp->avg_vc1_mspel_pixels_tab[ 7] = avg_vc1_mspel_mc31_mmxext; - dsp->avg_vc1_mspel_pixels_tab[11] = avg_vc1_mspel_mc32_mmxext; - dsp->avg_vc1_mspel_pixels_tab[15] = avg_vc1_mspel_mc33_mmxext; + FN_ASSIGN(avg_, 3, 0, _mmxext); + FN_ASSIGN(avg_, 3, 1, _mmxext); + FN_ASSIGN(avg_, 3, 2, _mmxext); + FN_ASSIGN(avg_, 3, 3, _mmxext); dsp->vc1_inv_trans_8x8_dc = vc1_inv_trans_8x8_dc_mmxext; dsp->vc1_inv_trans_4x8_dc = vc1_inv_trans_4x8_dc_mmxext; dsp->vc1_inv_trans_8x4_dc = vc1_inv_trans_8x4_dc_mmxext; dsp->vc1_inv_trans_4x4_dc = vc1_inv_trans_4x4_dc_mmxext; } -#endif /* HAVE_INLINE_ASM */ +#endif /* HAVE_6REGS && HAVE_INLINE_ASM */ diff --git a/libavcodec/x86/vorbisdsp_init.c b/libavcodec/x86/vorbisdsp_init.c index 284a528a0..bc1cc43a1 100644 --- a/libavcodec/x86/vorbisdsp_init.c +++ b/libavcodec/x86/vorbisdsp_init.c @@ -31,7 +31,6 @@ void ff_vorbis_inverse_coupling_sse(float *mag, float *ang, av_cold void ff_vorbisdsp_init_x86(VorbisDSPContext *dsp) { -#if HAVE_YASM int cpu_flags = av_get_cpu_flags(); #if ARCH_X86_32 @@ -40,5 +39,4 @@ av_cold void ff_vorbisdsp_init_x86(VorbisDSPContext *dsp) #endif /* ARCH_X86_32 */ if (EXTERNAL_SSE(cpu_flags)) dsp->vorbis_inverse_coupling = ff_vorbis_inverse_coupling_sse; -#endif /* HAVE_YASM */ } diff --git a/libavcodec/x86/vp3dsp_init.c b/libavcodec/x86/vp3dsp_init.c index 1f02a6f70..cc3eba4e9 100644 --- a/libavcodec/x86/vp3dsp_init.c +++ b/libavcodec/x86/vp3dsp_init.c @@ -25,7 +25,6 @@ #include "libavutil/x86/cpu.h" #include "libavutil/x86/asm.h" #include "libavcodec/avcodec.h" -#include "libavcodec/dsputil.h" #include "libavcodec/vp3dsp.h" #include "config.h" @@ -64,6 +63,7 @@ void ff_vp3_h_loop_filter_mmxext(uint8_t *src, int stride, "paddb "#regb", "#regr" \n\t" \ "paddb "#regd", "#regp" \n\t" +#if HAVE_6REGS static void put_vp_no_rnd_pixels8_l2_mmx(uint8_t *dst, const uint8_t *a, const uint8_t *b, ptrdiff_t stride, int h) { // START_TIMER @@ -95,15 +95,16 @@ static void put_vp_no_rnd_pixels8_l2_mmx(uint8_t *dst, const uint8_t *a, const u :"memory"); // STOP_TIMER("put_vp_no_rnd_pixels8_l2_mmx") } +#endif /*HAVE_6REGS */ #endif /* HAVE_MMX_INLINE */ av_cold void ff_vp3dsp_init_x86(VP3DSPContext *c, int flags) { int cpu_flags = av_get_cpu_flags(); -#if HAVE_MMX_INLINE +#if HAVE_6REGS && HAVE_MMX_INLINE c->put_no_rnd_pixels_l2 = put_vp_no_rnd_pixels8_l2_mmx; -#endif /* HAVE_MMX_INLINE */ +#endif /* HAVE_6REGS && HAVE_MMX_INLINE */ #if ARCH_X86_32 if (EXTERNAL_MMX(cpu_flags)) { diff --git a/libavcodec/x86/vp56_arith.h b/libavcodec/x86/vp56_arith.h index e71dbf8ed..810cc8dcd 100644 --- a/libavcodec/x86/vp56_arith.h +++ b/libavcodec/x86/vp56_arith.h @@ -24,29 +24,26 @@ #ifndef AVCODEC_X86_VP56_ARITH_H #define AVCODEC_X86_VP56_ARITH_H -#if HAVE_INLINE_ASM && HAVE_FAST_CMOV +#if HAVE_INLINE_ASM && HAVE_FAST_CMOV && HAVE_6REGS #define vp56_rac_get_prob vp56_rac_get_prob static av_always_inline int vp56_rac_get_prob(VP56RangeCoder *c, uint8_t prob) { unsigned int code_word = vp56_rac_renorm(c); - unsigned int high = c->high; - unsigned int low = 1 + (((high - 1) * prob) >> 8); + unsigned int low = 1 + (((c->high - 1) * prob) >> 8); unsigned int low_shift = low << 16; int bit = 0; + c->code_word = code_word; __asm__( "subl %4, %1 \n\t" "subl %3, %2 \n\t" - "leal (%2, %3), %3 \n\t" "setae %b0 \n\t" "cmovb %4, %1 \n\t" - "cmovb %3, %2 \n\t" - : "+q"(bit), "+r"(high), "+r"(code_word), "+r"(low_shift) - : "r"(low) + "cmovb %5, %2 \n\t" + : "+q"(bit), "+&r"(c->high), "+&r"(c->code_word) + : "r"(low_shift), "r"(low), "r"(code_word) ); - c->high = high; - c->code_word = code_word; return bit; } #endif diff --git a/libavcodec/x86/vp8dsp.asm b/libavcodec/x86/vp8dsp.asm index 85c7e9948..77cc2f304 100644 --- a/libavcodec/x86/vp8dsp.asm +++ b/libavcodec/x86/vp8dsp.asm @@ -1,7 +1,7 @@ ;****************************************************************************** ;* VP8 MMXEXT optimizations ;* Copyright (c) 2010 Ronald S. Bultje -;* Copyright (c) 2010 Jason Garrett-Glaser +;* Copyright (c) 2010 Fiona Glaser ;* ;* This file is part of FFmpeg. ;* @@ -153,13 +153,13 @@ cextern pw_64 SECTION .text -;----------------------------------------------------------------------------- +;------------------------------------------------------------------------------- ; subpel MC functions: ; -; void put_vp8_epel_hv_(uint8_t *dst, int deststride, -; uint8_t *src, int srcstride, -; int height, int mx, int my); -;----------------------------------------------------------------------------- +; void ff_put_vp8_epel_hv_(uint8_t *dst, int deststride, +; uint8_t *src, int srcstride, +; int height, int mx, int my); +;------------------------------------------------------------------------------- %macro FILTER_SSSE3 1 cglobal put_vp8_epel%1_h6, 6, 6 + npicregs, 8, dst, dststride, src, srcstride, height, mx, picreg @@ -884,7 +884,7 @@ cglobal put_vp8_pixels16, 5, 5, 2, dst, dststride, src, srcstride, height REP_RET ;----------------------------------------------------------------------------- -; void 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], int stride); ;----------------------------------------------------------------------------- %macro ADD_DC 4 @@ -962,7 +962,7 @@ cglobal vp8_idct_dc_add, 3, 3, 6, dst, block, stride RET ;----------------------------------------------------------------------------- -; void 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], int stride); ;----------------------------------------------------------------------------- %if ARCH_X86_32 @@ -1035,7 +1035,7 @@ cglobal vp8_idct_dc_add4y, 3, 3, 6, dst, block, stride RET ;----------------------------------------------------------------------------- -; void 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], int stride); ;----------------------------------------------------------------------------- INIT_MMX mmx @@ -1077,7 +1077,7 @@ cglobal vp8_idct_dc_add4uv, 3, 3, 0, dst, block, stride RET ;----------------------------------------------------------------------------- -; void vp8_idct_add_(uint8_t *dst, int16_t block[16], int stride); +; void ff_vp8_idct_add_(uint8_t *dst, int16_t block[16], int stride); ;----------------------------------------------------------------------------- ; calculate %1=mul_35468(%1)-mul_20091(%2); %2=mul_20091(%1)+mul_35468(%2) @@ -1157,7 +1157,7 @@ INIT_MMX sse VP8_IDCT_ADD ;----------------------------------------------------------------------------- -; void vp8_luma_dc_wht_mmxext(int16_t block[4][4][16], int16_t dc[16]) +; void ff_vp8_luma_dc_wht(int16_t block[4][4][16], int16_t dc[16]) ;----------------------------------------------------------------------------- %macro SCATTER_WHT 3 diff --git a/libavcodec/x86/vp8dsp_init.c b/libavcodec/x86/vp8dsp_init.c index d9ce9772e..6668f9116 100644 --- a/libavcodec/x86/vp8dsp_init.c +++ b/libavcodec/x86/vp8dsp_init.c @@ -1,7 +1,7 @@ /* * VP8 DSP functions x86-optimized * Copyright (c) 2010 Ronald S. Bultje - * Copyright (c) 2010 Jason Garrett-Glaser + * Copyright (c) 2010 Fiona Glaser * * This file is part of FFmpeg. * @@ -315,44 +315,18 @@ DECLARE_LOOP_FILTER(sse4) c->put_vp8_bilinear_pixels_tab[IDX][2][2] = ff_put_vp8_bilinear ## SIZE ## _hv_ ## OPT -av_cold void ff_vp8dsp_init_x86(VP8DSPContext* c, int vp7) +av_cold void ff_vp78dsp_init_x86(VP8DSPContext *c) { #if HAVE_YASM int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_MMX(cpu_flags)) { - if (!vp7) { - c->vp8_idct_dc_add = ff_vp8_idct_dc_add_mmx; - c->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_mmx; - } #if ARCH_X86_32 - if (!vp7) { - c->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_mmx; - c->vp8_idct_add = ff_vp8_idct_add_mmx; - c->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_mmx; - } c->put_vp8_epel_pixels_tab[0][0][0] = c->put_vp8_bilinear_pixels_tab[0][0][0] = ff_put_vp8_pixels16_mmx; #endif c->put_vp8_epel_pixels_tab[1][0][0] = c->put_vp8_bilinear_pixels_tab[1][0][0] = ff_put_vp8_pixels8_mmx; - -#if ARCH_X86_32 - if (!vp7) { - c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_mmx; - c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_mmx; - - c->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16y_inner_mmx; - c->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16y_inner_mmx; - c->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_mmx; - c->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_mmx; - - c->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16y_mbedge_mmx; - c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_mmx; - c->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mbedge_mmx; - c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_mmx; - } -#endif } /* note that 4-tap width=16 functions are missing because w=16 @@ -365,8 +339,64 @@ av_cold void ff_vp8dsp_init_x86(VP8DSPContext* c, int vp7) VP8_MC_FUNC(1, 8, mmxext); VP8_BILINEAR_MC_FUNC(0, 16, mmxext); VP8_BILINEAR_MC_FUNC(1, 8, mmxext); +#endif + } - if (!vp7) { + if (EXTERNAL_SSE(cpu_flags)) { + c->put_vp8_epel_pixels_tab[0][0][0] = + c->put_vp8_bilinear_pixels_tab[0][0][0] = ff_put_vp8_pixels16_sse; + } + + if (HAVE_SSE2_EXTERNAL && cpu_flags & (AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_SSE2SLOW)) { + VP8_LUMA_MC_FUNC(0, 16, sse2); + VP8_MC_FUNC(1, 8, sse2); + VP8_BILINEAR_MC_FUNC(0, 16, sse2); + VP8_BILINEAR_MC_FUNC(1, 8, sse2); + } + + if (EXTERNAL_SSSE3(cpu_flags)) { + VP8_LUMA_MC_FUNC(0, 16, ssse3); + VP8_MC_FUNC(1, 8, ssse3); + VP8_MC_FUNC(2, 4, ssse3); + VP8_BILINEAR_MC_FUNC(0, 16, ssse3); + VP8_BILINEAR_MC_FUNC(1, 8, ssse3); + VP8_BILINEAR_MC_FUNC(2, 4, ssse3); + } +#endif /* HAVE_YASM */ +} + +av_cold void ff_vp8dsp_init_x86(VP8DSPContext *c) +{ +#if HAVE_YASM + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_MMX(cpu_flags)) { + c->vp8_idct_dc_add = ff_vp8_idct_dc_add_mmx; + c->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_mmx; +#if ARCH_X86_32 + c->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_mmx; + c->vp8_idct_add = ff_vp8_idct_add_mmx; + c->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_mmx; + + c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_mmx; + c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_mmx; + + c->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16y_inner_mmx; + c->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16y_inner_mmx; + c->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_mmx; + c->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_mmx; + + c->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16y_mbedge_mmx; + c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_mmx; + c->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mbedge_mmx; + c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_mmx; +#endif + } + + /* note that 4-tap width=16 functions are missing because w=16 + * is only used for luma, and luma is always a copy or sixtap. */ + if (EXTERNAL_MMXEXT(cpu_flags)) { +#if ARCH_X86_32 c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_mmxext; c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_mmxext; @@ -379,26 +409,15 @@ av_cold void ff_vp8dsp_init_x86(VP8DSPContext* c, int vp7) c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_mmxext; c->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mbedge_mmxext; c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_mmxext; - } #endif } if (EXTERNAL_SSE(cpu_flags)) { - if (!vp7) { c->vp8_idct_add = ff_vp8_idct_add_sse; c->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_sse; - } - c->put_vp8_epel_pixels_tab[0][0][0] = - c->put_vp8_bilinear_pixels_tab[0][0][0] = ff_put_vp8_pixels16_sse; } if (HAVE_SSE2_EXTERNAL && cpu_flags & (AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_SSE2SLOW)) { - VP8_LUMA_MC_FUNC(0, 16, sse2); - VP8_MC_FUNC(1, 8, sse2); - VP8_BILINEAR_MC_FUNC(0, 16, sse2); - VP8_BILINEAR_MC_FUNC(1, 8, sse2); - - if (!vp7) { 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; @@ -406,32 +425,21 @@ av_cold void ff_vp8dsp_init_x86(VP8DSPContext* c, int vp7) c->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16y_mbedge_sse2; c->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mbedge_sse2; - } } if (EXTERNAL_SSE2(cpu_flags)) { - if (!vp7) { c->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_sse2; - c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_sse2; + c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_sse2; c->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16y_inner_sse2; c->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_sse2; c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_sse2; c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_sse2; - } } if (EXTERNAL_SSSE3(cpu_flags)) { - VP8_LUMA_MC_FUNC(0, 16, ssse3); - VP8_MC_FUNC(1, 8, ssse3); - VP8_MC_FUNC(2, 4, ssse3); - VP8_BILINEAR_MC_FUNC(0, 16, ssse3); - VP8_BILINEAR_MC_FUNC(1, 8, ssse3); - VP8_BILINEAR_MC_FUNC(2, 4, ssse3); - - if (!vp7) { c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_ssse3; c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_ssse3; @@ -444,17 +452,14 @@ av_cold void ff_vp8dsp_init_x86(VP8DSPContext* c, int vp7) c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_ssse3; c->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mbedge_ssse3; c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_ssse3; - } } if (EXTERNAL_SSE4(cpu_flags)) { - if (!vp7) { - c->vp8_idct_dc_add = ff_vp8_idct_dc_add_sse4; + c->vp8_idct_dc_add = ff_vp8_idct_dc_add_sse4; c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_sse4; c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_sse4; c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_sse4; - } } #endif /* HAVE_YASM */ } diff --git a/libavcodec/x86/vp8dsp_loopfilter.asm b/libavcodec/x86/vp8dsp_loopfilter.asm index 45dd54b6a..98bb6696a 100644 --- a/libavcodec/x86/vp8dsp_loopfilter.asm +++ b/libavcodec/x86/vp8dsp_loopfilter.asm @@ -1,7 +1,7 @@ ;****************************************************************************** ;* VP8 MMXEXT optimizations ;* Copyright (c) 2010 Ronald S. Bultje -;* Copyright (c) 2010 Jason Garrett-Glaser +;* Copyright (c) 2010 Fiona Glaser ;* ;* This file is part of FFmpeg. ;* @@ -43,7 +43,7 @@ cextern pb_80 SECTION .text ;----------------------------------------------------------------------------- -; void vp8_h/v_loop_filter_simple_(uint8_t *dst, int stride, int flim); +; void ff_vp8_h/v_loop_filter_simple_(uint8_t *dst, int stride, int flim); ;----------------------------------------------------------------------------- ; macro called with 7 mm register indexes as argument, and 4 regular registers @@ -429,8 +429,8 @@ INIT_XMM sse4 SIMPLE_LOOPFILTER h, 5 ;----------------------------------------------------------------------------- -; void vp8_h/v_loop_filter_inner_(uint8_t *dst, [uint8_t *v,] int stride, -; int flimE, int flimI, int hev_thr); +; void ff_vp8_h/v_loop_filter_inner_(uint8_t *dst, [uint8_t *v,] int stride, +; int flimE, int flimI, int hev_thr); ;----------------------------------------------------------------------------- %macro INNER_LOOPFILTER 2 @@ -921,8 +921,8 @@ INNER_LOOPFILTER v, 8 INNER_LOOPFILTER h, 8 ;----------------------------------------------------------------------------- -; void vp8_h/v_loop_filter_mbedge_(uint8_t *dst, [uint8_t *v,] int stride, -; int flimE, int flimI, int hev_thr); +; void ff_vp8_h/v_loop_filter_mbedge_(uint8_t *dst, [uint8_t *v,] int stride, +; int flimE, int flimI, int hev_thr); ;----------------------------------------------------------------------------- %macro MBEDGE_LOOPFILTER 2 diff --git a/libavcodec/x86/vp9dsp_init.c b/libavcodec/x86/vp9dsp_init.c index 011e13d9d..b04e67811 100644 --- a/libavcodec/x86/vp9dsp_init.c +++ b/libavcodec/x86/vp9dsp_init.c @@ -30,9 +30,9 @@ #if HAVE_YASM #define fpel_func(avg, sz, opt) \ -void ff_##avg##sz##_##opt(uint8_t *dst, ptrdiff_t dst_stride, \ - const uint8_t *src, ptrdiff_t src_stride, \ - int h, int mx, int my) +void ff_vp9_##avg##sz##_##opt(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *src, 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); @@ -46,9 +46,9 @@ fpel_func(avg, 64, sse2); #undef fpel_func #define mc_func(avg, sz, dir, opt) \ -void ff_##avg##_8tap_1d_##dir##_##sz##_##opt(uint8_t *dst, ptrdiff_t dst_stride, \ - const uint8_t *src, ptrdiff_t src_stride, \ - int h, const int8_t (*filter)[16]) +void ff_vp9_##avg##_8tap_1d_##dir##_##sz##_##opt(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *src, 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); \ @@ -66,14 +66,14 @@ mc_funcs(16); #define mc_rep_func(avg, sz, hsz, dir, opt) \ static av_always_inline void \ -ff_##avg##_8tap_1d_##dir##_##sz##_##opt(uint8_t *dst, ptrdiff_t dst_stride, \ - const uint8_t *src, ptrdiff_t src_stride, \ - int h, const int8_t (*filter)[16]) \ +ff_vp9_##avg##_8tap_1d_##dir##_##sz##_##opt(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *src, ptrdiff_t src_stride, \ + int h, const int8_t (*filter)[16]) \ { \ - ff_##avg##_8tap_1d_##dir##_##hsz##_##opt(dst, dst_stride, src, \ - src_stride, h, filter); \ - ff_##avg##_8tap_1d_##dir##_##hsz##_##opt(dst + hsz, dst_stride, src + hsz, \ - src_stride, h, filter); \ + ff_vp9_##avg##_8tap_1d_##dir##_##hsz##_##opt(dst, dst_stride, src, \ + src_stride, h, filter); \ + ff_vp9_##avg##_8tap_1d_##dir##_##hsz##_##opt(dst + hsz, dst_stride, src + hsz, \ + src_stride, h, filter); \ } #define mc_rep_funcs(sz, hsz) \ @@ -99,10 +99,10 @@ static void op##_8tap_##fname##_##sz##hv_ssse3(uint8_t *dst, ptrdiff_t dst_strid int h, int mx, int my) \ { \ LOCAL_ALIGNED_16(uint8_t, temp, [71 * 64]); \ - ff_put_8tap_1d_h_##sz##_ssse3(temp, 64, src - 3 * src_stride, src_stride, \ - h + 7, ff_filters_ssse3[f][mx - 1]); \ - ff_##op##_8tap_1d_v_##sz##_ssse3(dst, dst_stride, temp + 3 * 64, 64, \ - h, ff_filters_ssse3[f][my - 1]); \ + ff_vp9_put_8tap_1d_h_##sz##_ssse3(temp, 64, src - 3 * src_stride, src_stride, \ + h + 7, ff_filters_ssse3[f][mx - 1]); \ + ff_vp9_##op##_8tap_1d_v_##sz##_ssse3(dst, dst_stride, temp + 3 * 64, 64, \ + h, ff_filters_ssse3[f][my - 1]); \ } #define filters_8tap_2d_fn(op, sz) \ @@ -129,8 +129,8 @@ static void op##_8tap_##fname##_##sz##dir##_ssse3(uint8_t *dst, ptrdiff_t dst_st const uint8_t *src, ptrdiff_t src_stride, \ int h, int mx, int my) \ { \ - ff_##op##_8tap_1d_##dir##_##sz##_ssse3(dst, dst_stride, src, src_stride, \ - h, ff_filters_ssse3[f][dvar - 1]); \ + ff_vp9_##op##_8tap_1d_##dir##_##sz##_ssse3(dst, dst_stride, src, src_stride, \ + h, ff_filters_ssse3[f][dvar - 1]); \ } #define filters_8tap_1d_fn(op, sz, dir, dvar) \ @@ -241,6 +241,13 @@ ipred_funcs(hd, ssse3, avx); ipred_funcs(vl, ssse3, avx); ipred_funcs(vr, ssse3, avx); +ipred_func(32, dc, avx2); +ipred_func(32, dc_left, avx2); +ipred_func(32, dc_top, avx2); +ipred_func(32, v, avx2); +ipred_func(32, h, avx2); +ipred_func(32, tm, avx2); + #undef ipred_funcs #undef ipred_func_set #undef ipred_func @@ -256,7 +263,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) \ dsp->mc[idx1][FILTER_8TAP_SMOOTH ][idx2][idxh][idxv] = type##_8tap_smooth_##sz##dir##_##opt; \ @@ -388,6 +395,15 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp) init_ipred(TX_32X32, 32, avx); } + if (EXTERNAL_AVX2(cpu_flags)) { + dsp->intra_pred[TX_32X32][DC_PRED] = ff_vp9_ipred_dc_32x32_avx2; + dsp->intra_pred[TX_32X32][LEFT_DC_PRED] = ff_vp9_ipred_dc_left_32x32_avx2; + dsp->intra_pred[TX_32X32][TOP_DC_PRED] = ff_vp9_ipred_dc_top_32x32_avx2; + dsp->intra_pred[TX_32X32][VERT_PRED] = ff_vp9_ipred_v_32x32_avx2; + dsp->intra_pred[TX_32X32][HOR_PRED] = ff_vp9_ipred_h_32x32_avx2; + dsp->intra_pred[TX_32X32][TM_VP8_PRED] = ff_vp9_ipred_tm_32x32_avx2; + } + #undef init_fpel #undef init_subpel1 #undef init_subpel2 diff --git a/libavcodec/x86/vp9intrapred.asm b/libavcodec/x86/vp9intrapred.asm index a6b5442b0..1d8d219b3 100644 --- a/libavcodec/x86/vp9intrapred.asm +++ b/libavcodec/x86/vp9intrapred.asm @@ -5,7 +5,7 @@ ;* ;* Parts based on: ;* H.264 intra prediction asm optimizations -;* Copyright (c) 2010 Jason Garrett-Glaser +;* Copyright (c) 2010 Fiona Glaser ;* Copyright (c) 2010 Holger Lubitz ;* Copyright (c) 2010 Loren Merritt ;* Copyright (c) 2010 Ronald S. Bultje @@ -29,10 +29,10 @@ %include "libavutil/x86/x86util.asm" -SECTION_RODATA +SECTION_RODATA 32 -pw_m256: times 8 dw -256 -pw_m255: times 8 dw -255 +pw_m256: times 16 dw -256 +pw_m255: times 16 dw -255 pw_512: times 8 dw 512 pw_1024: times 8 dw 1024 pw_2048: times 8 dw 2048 @@ -72,7 +72,7 @@ pb_3to1_5x0: db 3, 2, 1 times 9 db 0 pb_Fto0: db 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 -pb_2: times 16 db 2 +pb_2: times 32 db 2 pb_15: times 16 db 15 cextern pb_1 @@ -180,6 +180,40 @@ cglobal vp9_ipred_dc_32x32, 4, 4, 5, dst, stride, l, a jg .loop RET +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +cglobal vp9_ipred_dc_32x32, 4, 4, 3, dst, stride, l, a + mova m0, [lq] + mova m1, [aq] + DEFINE_ARGS dst, stride, stride3, cnt + lea stride3q, [strideq*3] + pxor m2, m2 + psadbw m0, m2 + psadbw m1, m2 + paddw m0, m1 + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + movhlps xm1, xm0 + paddw xm0, xm1 + pmulhrsw xm0, [pw_512] + vpbroadcastb m0, xm0 + mov cntd, 4 +.loop: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + dec cntd + jg .loop + RET +%endif + ; dc_top/left_NxN(uint8_t *dst, ptrdiff_t stride, const uint8_t *l, const uint8_t *a) %macro DC_1D_FUNCS 2 ; dir (top or left), arg (a or l) @@ -267,6 +301,37 @@ cglobal vp9_ipred_dc_%1_32x32, 4, 4, 3, dst, stride, l, a dec cntd jg .loop RET + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +cglobal vp9_ipred_dc_%1_32x32, 4, 4, 3, dst, stride, l, a + mova m0, [%2q] + DEFINE_ARGS dst, stride, stride3, cnt + lea stride3q, [strideq*3] + pxor m2, m2 + psadbw m0, m2 + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + movhlps xm1, xm0 + paddw xm0, xm1 + pmulhrsw xm0, [pw_1024] + vpbroadcastb m0, xm0 + mov cntd, 4 +.loop: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + dec cntd + jg .loop + RET +%endif %endmacro DC_1D_FUNCS top, a @@ -327,6 +392,29 @@ cglobal vp9_ipred_v_32x32, 4, 4, 2, dst, stride, l, a jg .loop RET +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +cglobal vp9_ipred_v_32x32, 4, 4, 1, dst, stride, l, a + mova m0, [aq] + DEFINE_ARGS dst, stride, stride3, cnt + lea stride3q, [strideq*3] + mov cntd, 4 +.loop: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + dec cntd + jg .loop + RET +%endif + ; h INIT_XMM ssse3 @@ -417,6 +505,32 @@ cglobal vp9_ipred_h_32x32, 3, 5, 8, dst, stride, l, stride3, cnt H_XMM_FUNCS ssse3 H_XMM_FUNCS avx +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +cglobal vp9_ipred_h_32x32, 3, 5, 8, dst, stride, l, stride3, cnt + mova m5, [pb_1] + mova m6, [pb_2] + mova m7, [pb_3] + pxor m4, m4 + lea stride3q, [strideq*3] + mov cntq, 7 +.loop: + movd xm3, [lq+cntq*4] + vinserti128 m3, m3, xm3, 1 + pshufb m0, m3, m7 + pshufb m1, m3, m6 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + pshufb m2, m3, m5 + pshufb m3, m4 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + dec cntq + jge .loop + RET +%endif + ; tm INIT_MMX ssse3 @@ -554,6 +668,41 @@ cglobal vp9_ipred_tm_32x32, 4, 4, 14, dst, stride, l, a TM_XMM_FUNCS ssse3 TM_XMM_FUNCS avx +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +cglobal vp9_ipred_tm_32x32, 4, 4, 8, dst, stride, l, a + pxor m3, m3 + pinsrw xm2, [aq-1], 0 + vinserti128 m2, m2, xm2, 1 + mova m0, [aq] + DEFINE_ARGS dst, stride, l, cnt + mova m4, [pw_m256] + mova m5, [pw_m255] + pshufb m2, m4 + punpckhbw m1, m0, m3 + punpcklbw m0, m3 + psubw m1, m2 + psubw m0, m2 + mov cntq, 15 +.loop: + pinsrw xm7, [lq+cntq*2], 0 + vinserti128 m7, m7, xm7, 1 + pshufb m3, m7, m5 + pshufb m7, m4 + paddw m2, m3, m0 + paddw m3, m1 + paddw m6, m7, m0 + paddw m7, m1 + packuswb m2, m3 + packuswb m6, m7 + mova [dstq+strideq*0], m2 + mova [dstq+strideq*1], m6 + lea dstq, [dstq+strideq*2] + dec cntq + jge .loop + RET +%endif + ; dl %macro LOWPASS 4 ; left [dst], center, right, tmp diff --git a/libavcodec/x86/vp9lpf.asm b/libavcodec/x86/vp9lpf.asm index e41dd2cd4..c5db0caff 100644 --- a/libavcodec/x86/vp9lpf.asm +++ b/libavcodec/x86/vp9lpf.asm @@ -88,24 +88,19 @@ SECTION .text punpck%2bw %3, %6, m0 paddw %1, %3 punpck%2bw %3, %7, m0 - paddw %1, %3 - mova %3, %1 - psraw %1, %8 + paddw %3, %1 + psraw %1, %3, %8 %endmacro -%macro FILTER_INIT 7-8 ; tmp1, tmp2, cacheL, cacheH, dstp, filterid, [source] +%macro FILTER_INIT 8 ; tmp1, tmp2, cacheL, cacheH, dstp, filterid, mask, source FILTER%6_INIT %1, l, %3 FILTER%6_INIT %2, h, %4 packuswb %1, %2 -%if %0 == 8 MASK_APPLY %1, %8, %7, %2 -%else - MASK_APPLY %1, %5, %7, %2 -%endif mova %5, %1 %endmacro -%macro FILTER_UPDATE 11-14 ; tmp1, tmp2, cacheL, cacheH, dstp, -, -, +, +, rshift, [source], [preload reg + value] +%macro FILTER_UPDATE 11-14 ; tmp1, tmp2, cacheL, cacheH, dstp, -, -, +, +, rshift, mask, [source], [preload reg + value] %if %0 == 13 ; no source + preload mova %12, %13 %elif %0 == 14 ; source + preload @@ -158,49 +153,45 @@ SECTION .text %endmacro %macro FILTER6_INIT 3 ; %1=dst %2=h/l %3=cache - punpck%2bw %3, m14, m0 ; p3: B->W - mova %1, %3 ; p3 - paddw %1, %3 ; p3*2 - paddw %1, %3 ; p3*3 - punpck%2bw %3, m15, m0 ; p2: B->W - paddw %1, %3 ; p3*3 + p2 - paddw %1, %3 ; p3*3 + p2*2 - punpck%2bw %3, m10, m0 ; p1: B->W - paddw %1, %3 ; p3*3 + p2*2 + p1 - punpck%2bw %3, m11, m0 ; p0: B->W - paddw %1, %3 ; p3*3 + p2*2 + p1 + p0 - punpck%2bw %3, m12, m0 ; q0: B->W - paddw %1, %3 ; p3*3 + p2*2 + p1 + p0 + q0 - paddw %1, [pw_4] ; p3*3 + p2*2 + p1 + p0 + q0 + 4 - mova %3, %1 ; base for next line (cache) - psraw %1, 3 ; (p3*3 + p2*2 + p1 + p0 + q0 + 4) >> 3 + punpck%2bw %1, m14, m0 ; p3: B->W + paddw %3, %1, %1 ; p3*2 + paddw %3, %1 ; p3*3 + punpck%2bw %1, m15, m0 ; p2: B->W + paddw %3, %1 ; p3*3 + p2 + paddw %3, %1 ; p3*3 + p2*2 + punpck%2bw %1, m10, m0 ; p1: B->W + paddw %3, %1 ; p3*3 + p2*2 + p1 + punpck%2bw %1, m11, m0 ; p0: B->W + paddw %3, %1 ; p3*3 + p2*2 + p1 + p0 + punpck%2bw %1, m12, m0 ; q0: B->W + paddw %3, %1 ; p3*3 + p2*2 + p1 + p0 + q0 + paddw %3, [pw_4] ; p3*3 + p2*2 + p1 + p0 + q0 + 4 + psraw %1, %3, 3 ; (p3*3 + p2*2 + p1 + p0 + q0 + 4) >> 3 %endmacro %macro FILTER14_INIT 3 ; %1=dst %2=h/l %3=cache punpck%2bw %1, m2, m0 ; p7: B->W - mova %3, %1 - psllw %1, 3 ; p7*8 - psubw %1, %3 ; p7*7 - punpck%2bw %3, m3, m0 ; p6: B->W - paddw %1, %3 ; p7*7 + p6 - paddw %1, %3 ; p7*7 + p6*2 - punpck%2bw %3, m8, m0 ; p5: B->W - paddw %1, %3 ; p7*7 + p6*2 + p5 - punpck%2bw %3, m9, m0 ; p4: B->W - paddw %1, %3 ; p7*7 + p6*2 + p5 + p4 - punpck%2bw %3, m14, m0 ; p3: B->W - paddw %1, %3 ; p7*7 + p6*2 + p5 + p4 + p3 - punpck%2bw %3, m15, m0 ; p2: B->W - paddw %1, %3 ; p7*7 + p6*2 + p5 + .. + p2 - punpck%2bw %3, m10, m0 ; p1: B->W - paddw %1, %3 ; p7*7 + p6*2 + p5 + .. + p1 - punpck%2bw %3, m11, m0 ; p0: B->W - paddw %1, %3 ; p7*7 + p6*2 + p5 + .. + p0 - punpck%2bw %3, m12, m0 ; q0: B->W - paddw %1, %3 ; p7*7 + p6*2 + p5 + .. + p0 + q0 - paddw %1, [pw_8] ; p7*7 + p6*2 + p5 + .. + p0 + q0 + 8 - mova %3, %1 ; base for next line (cache) - psraw %1, 4 ; (p7*7 + p6*2 + p5 + .. + p0 + q0 + 8) >> 4 + psllw %3, %1, 3 ; p7*8 + psubw %3, %1 ; p7*7 + punpck%2bw %1, m3, m0 ; p6: B->W + paddw %3, %1 ; p7*7 + p6 + paddw %3, %1 ; p7*7 + p6*2 + punpck%2bw %1, m8, m0 ; p5: B->W + paddw %3, %1 ; p7*7 + p6*2 + p5 + punpck%2bw %1, m9, m0 ; p4: B->W + paddw %3, %1 ; p7*7 + p6*2 + p5 + p4 + punpck%2bw %1, m14, m0 ; p3: B->W + paddw %3, %1 ; p7*7 + p6*2 + p5 + p4 + p3 + punpck%2bw %1, m15, m0 ; p2: B->W + paddw %3, %1 ; p7*7 + p6*2 + p5 + .. + p2 + punpck%2bw %1, m10, m0 ; p1: B->W + paddw %3, %1 ; p7*7 + p6*2 + p5 + .. + p1 + punpck%2bw %1, m11, m0 ; p0: B->W + paddw %3, %1 ; p7*7 + p6*2 + p5 + .. + p0 + punpck%2bw %1, m12, m0 ; q0: B->W + paddw %3, %1 ; p7*7 + p6*2 + p5 + .. + p0 + q0 + paddw %3, [pw_8] ; p7*7 + p6*2 + p5 + .. + p0 + q0 + 8 + psraw %1, %3, 4 ; (p7*7 + p6*2 + p5 + .. + p0 + q0 + 8) >> 4 %endmacro %macro TRANSPOSE16x16B 17 @@ -305,7 +296,8 @@ SECTION .text %define Q7 dst2q + strideq + %1 %endmacro -%macro SPLATB_MASK 2 +; ..............AB -> AAAAAAAABBBBBBBB +%macro SPLATB_MIX 1-2 [mask_mix] %if cpuflag(ssse3) pshufb %1, %2 %else @@ -411,8 +403,8 @@ SECTION .text %endif movd m2, Id movd m3, Ed - SPLATB_MASK m2, m0 - SPLATB_MASK m3, m0 + SPLATB_MIX m2, m0 + SPLATB_MIX m3, m0 %endif mova m0, [pb_80] pxor m2, m0 @@ -427,6 +419,8 @@ SECTION .text mova m14, [Q2] mova m15, [Q3] %else + ; In case of horizontal, P3..Q3 are already present in some registers due + ; to the previous transpose, so we just swap registers. SWAP 8, 4, 12 SWAP 9, 5, 13 SWAP 10, 6, 14 @@ -471,7 +465,7 @@ SECTION .text SPLATB_REG m7, H, m0 ; H H H H ... %else movd m7, Hd - SPLATB_MASK m7, [mask_mix] + SPLATB_MIX m7 %endif pxor m7, m8 pxor m4, m8 @@ -494,7 +488,7 @@ SECTION .text %else mova m6, [pb_80] movd m7, Hd - SPLATB_MASK m7, [mask_mix] + SPLATB_MIX m7 pxor m7, m6 ABSSUB m4, m10, m11, m1 ; abs(p1 - p0) pxor m4, m6 diff --git a/libavcodec/x86/vp9mc.asm b/libavcodec/x86/vp9mc.asm index 154ab2b4f..7c2a38c8b 100644 --- a/libavcodec/x86/vp9mc.asm +++ b/libavcodec/x86/vp9mc.asm @@ -87,7 +87,7 @@ SECTION .text %macro filter_h_fn 1 %assign %%px mmsize/2 -cglobal %1_8tap_1d_h_ %+ %%px, 6, 6, 11, dst, dstride, src, sstride, h, filtery +cglobal vp9_%1_8tap_1d_h_ %+ %%px, 6, 6, 11, dst, dstride, src, sstride, h, filtery mova m6, [pw_256] mova m7, [filteryq+ 0] %if ARCH_X86_64 && mmsize > 8 @@ -148,7 +148,7 @@ filter_h_fn avg %if ARCH_X86_64 %macro filter_hx2_fn 1 %assign %%px mmsize -cglobal %1_8tap_1d_h_ %+ %%px, 6, 6, 14, dst, dstride, src, sstride, h, filtery +cglobal vp9_%1_8tap_1d_h_ %+ %%px, 6, 6, 14, dst, dstride, src, sstride, h, filtery mova m13, [pw_256] mova m8, [filteryq+ 0] mova m9, [filteryq+16] @@ -204,9 +204,9 @@ filter_hx2_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, dstride, src, sstride, h, filtery, src4, sstride3 +cglobal vp9_%1_8tap_1d_v_ %+ %%px, 6, 8, 11, dst, dstride, src, sstride, h, filtery, src4, sstride3 %else -cglobal %1_8tap_1d_v_ %+ %%px, 4, 7, 11, dst, dstride, src, sstride, filtery, src4, sstride3 +cglobal vp9_%1_8tap_1d_v_ %+ %%px, 4, 7, 11, dst, dstride, src, sstride, filtery, src4, sstride3 mov filteryq, r5mp %define hd r4mp %endif @@ -278,7 +278,7 @@ filter_v_fn avg %macro filter_vx2_fn 1 %assign %%px mmsize -cglobal %1_8tap_1d_v_ %+ %%px, 6, 8, 14, dst, dstride, src, sstride, h, filtery, src4, sstride3 +cglobal vp9_%1_8tap_1d_v_ %+ %%px, 6, 8, 14, dst, dstride, src, sstride, h, filtery, src4, sstride3 mova m13, [pw_256] lea sstride3q, [sstrideq*3] lea src4q, [srcq+sstrideq] @@ -348,11 +348,11 @@ filter_vx2_fn avg %endif %if %2 <= 16 -cglobal %1%2, 5, 7, 4, dst, dstride, src, sstride, h, dstride3, sstride3 +cglobal vp9_%1%2, 5, 7, 4, dst, dstride, src, sstride, h, dstride3, sstride3 lea sstride3q, [sstrideq*3] lea dstride3q, [dstrideq*3] %else -cglobal %1%2, 5, 5, 4, dst, dstride, src, sstride, h +cglobal vp9_%1%2, 5, 5, 4, dst, dstride, src, sstride, h %endif .loop: %%srcfn m0, [srcq] diff --git a/libavcodec/xbmdec.c b/libavcodec/xbmdec.c index 2976bec8a..143e3a283 100644 --- a/libavcodec/xbmdec.c +++ b/libavcodec/xbmdec.c @@ -20,17 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avstring.h" + #include "avcodec.h" #include "internal.h" #include "mathops.h" -#include "libavutil/avstring.h" - -static av_cold int xbm_decode_init(AVCodecContext *avctx) -{ - avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; - - return 0; -} static int convert(uint8_t x) { @@ -43,42 +37,57 @@ static int convert(uint8_t x) return x; } +static int parse_str_int(const uint8_t *p, int len, const uint8_t *key) +{ + const uint8_t *end = p + len; + + for(; p= end) + return INT_MIN; + + for(; pdata; - uint8_t *dst; int ret, linesize, i, j; + int width = 0; + int height = 0; + const uint8_t *end, *ptr = avpkt->data; + const uint8_t *next; + uint8_t *dst; + avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; end = avpkt->data + avpkt->size; - while (!avctx->width || !avctx->height) { - char name[256]; - int number, len; - ptr += strcspn(ptr, "#"); - if (sscanf(ptr, "#define %255s %u", name, &number) != 2) { - av_log(avctx, AV_LOG_ERROR, "Unexpected preprocessor directive\n"); - return AVERROR_INVALIDDATA; - } + width = parse_str_int(avpkt->data, avpkt->size, "_width"); + height = parse_str_int(avpkt->data, avpkt->size, "_height"); - len = strlen(name); - if ((len > 6) && !avctx->height && !memcmp(name + len - 7, "_height", 7)) { - avctx->height = number; - } else if ((len > 5) && !avctx->width && !memcmp(name + len - 6, "_width", 6)) { - avctx->width = number; - } else { - av_log(avctx, AV_LOG_ERROR, "Unknown define '%s'\n", name); - return AVERROR_INVALIDDATA; - } - ptr += strcspn(ptr, "\n\r") + 1; - } + if ((ret = ff_set_dimensions(avctx, width, height)) < 0) + return ret; if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; // goto start of image data - ptr += strcspn(ptr, "{") + 1; + next = memchr(ptr, '{', avpkt->size); + if (!next) + next = memchr(ptr, '(', avpkt->size); + if (!next) + return AVERROR_INVALIDDATA; + ptr = next + 1; linesize = (avctx->width + 7) / 8; for (i = 0; i < avctx->height; i++) { @@ -86,15 +95,25 @@ static int xbm_decode_frame(AVCodecContext *avctx, void *data, for (j = 0; j < linesize; j++) { uint8_t val; - ptr += strcspn(ptr, "x") + 1; - if (ptr < end && av_isxdigit(*ptr)) { - val = convert(*ptr); + while (ptr < end && *ptr != 'x' && *ptr != '$') ptr++; + + ptr ++; + if (ptr < end && av_isxdigit(*ptr)) { + val = convert(*ptr++); if (av_isxdigit(*ptr)) - val = (val << 4) + convert(*ptr); + val = (val << 4) + convert(*ptr++); *dst++ = ff_reverse[val]; + if (av_isxdigit(*ptr) && j+1 < linesize) { + j++; + val = convert(*ptr++); + if (av_isxdigit(*ptr)) + val = (val << 4) + convert(*ptr++); + *dst++ = ff_reverse[val]; + } } else { - av_log(avctx, AV_LOG_ERROR, "Unexpected data at '%.8s'\n", ptr); + av_log(avctx, AV_LOG_ERROR, + "Unexpected data at %.8s.\n", ptr); return AVERROR_INVALIDDATA; } } @@ -113,7 +132,6 @@ AVCodec ff_xbm_decoder = { .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_XBM, - .init = xbm_decode_init, .decode = xbm_decode_frame, .capabilities = CODEC_CAP_DR1, }; diff --git a/libavcodec/xwddec.c b/libavcodec/xwddec.c index c28e19fa8..62dfdace1 100644 --- a/libavcodec/xwddec.c +++ b/libavcodec/xwddec.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/imgutils.h" #include "avcodec.h" #include "bytestream.h" @@ -75,11 +77,15 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, ncolors = bytestream2_get_be32u(&gb); bytestream2_skipu(&gb, header_size - (XWD_HEADER_SIZE - 20)); - av_log(avctx, AV_LOG_DEBUG, "pixformat %d, pixdepth %d, bunit %d, bitorder %d, bpad %d\n", + av_log(avctx, AV_LOG_DEBUG, + "pixformat %"PRIu32", pixdepth %"PRIu32", bunit %"PRIu32", bitorder %"PRIu32", bpad %"PRIu32"\n", pixformat, pixdepth, bunit, bitorder, bpad); - av_log(avctx, AV_LOG_DEBUG, "vclass %d, ncolors %d, bpp %d, be %d, lsize %d, xoffset %d\n", + av_log(avctx, AV_LOG_DEBUG, + "vclass %"PRIu32", ncolors %"PRIu32", bpp %"PRIu32", be %"PRIu32", lsize %"PRIu32", xoffset %"PRIu32"\n", vclass, ncolors, bpp, be, lsize, xoffset); - av_log(avctx, AV_LOG_DEBUG, "red %0x, green %0x, blue %0x\n", rgb[0], rgb[1], rgb[2]); + av_log(avctx, AV_LOG_DEBUG, + "red %0"PRIx32", green %0"PRIx32", blue %0"PRIx32"\n", + rgb[0], rgb[1], rgb[2]); if (pixformat > XWD_Z_PIXMAP) { av_log(avctx, AV_LOG_ERROR, "invalid pixmap format\n"); @@ -92,7 +98,7 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, } if (xoffset) { - avpriv_request_sample(avctx, "xoffset %d", xoffset); + avpriv_request_sample(avctx, "xoffset %"PRIu32"", xoffset); return AVERROR_PATCHWELCOME; } @@ -141,7 +147,7 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, } if (pixformat != XWD_Z_PIXMAP) { - avpriv_report_missing_feature(avctx, "Pixmap format %d", pixformat); + avpriv_report_missing_feature(avctx, "Pixmap format %"PRIu32, pixformat); return AVERROR_PATCHWELCOME; } @@ -196,7 +202,7 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, if (avctx->pix_fmt == AV_PIX_FMT_NONE) { avpriv_request_sample(avctx, - "Unknown file: bpp %d, pixdepth %d, vclass %d", + "Unknown file: bpp %"PRIu32", pixdepth %"PRIu32", vclass %"PRIu32"", bpp, pixdepth, vclass); return AVERROR_PATCHWELCOME; } diff --git a/libavcodec/zmbv.c b/libavcodec/zmbv.c index 71e828771..21a9e35c3 100644 --- a/libavcodec/zmbv.c +++ b/libavcodec/zmbv.c @@ -145,7 +145,7 @@ static int zmbv_decode_xor_8(ZmbvContext *c) prev += c->width * c->bh; } if (src - c->decomp_buf != c->decomp_len) - av_log(c->avctx, AV_LOG_ERROR, "Used %ti of %i bytes\n", + av_log(c->avctx, AV_LOG_ERROR, "Used %"PTRDIFF_SPECIFIER" of %i bytes\n", src-c->decomp_buf, c->decomp_len); return 0; } @@ -219,7 +219,7 @@ static int zmbv_decode_xor_16(ZmbvContext *c) prev += c->width * c->bh; } if (src - c->decomp_buf != c->decomp_len) - av_log(c->avctx, AV_LOG_ERROR, "Used %ti of %i bytes\n", + av_log(c->avctx, AV_LOG_ERROR, "Used %"PTRDIFF_SPECIFIER" of %i bytes\n", src-c->decomp_buf, c->decomp_len); return 0; } @@ -377,7 +377,7 @@ static int zmbv_decode_xor_32(ZmbvContext *c) prev += c->width * c->bh; } if (src - c->decomp_buf != c->decomp_len) - av_log(c->avctx, AV_LOG_ERROR, "Used %ti of %i bytes\n", + av_log(c->avctx, AV_LOG_ERROR, "Used %"PTRDIFF_SPECIFIER" of %i bytes\n", src-c->decomp_buf, c->decomp_len); return 0; } diff --git a/libavdevice/Makefile b/libavdevice/Makefile index ba503a391..767df19aa 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -1,8 +1,6 @@ include $(SUBDIR)../config.mak NAME = avdevice -FFLIBS = avformat avcodec avutil -FFLIBS-$(CONFIG_LAVFI_INDEV) += avfilter HEADERS = avdevice.h \ version.h \ @@ -15,6 +13,7 @@ OBJS-$(CONFIG_ALSA_INDEV) += alsa-audio-common.o \ alsa-audio-dec.o timefilter.o OBJS-$(CONFIG_ALSA_OUTDEV) += alsa-audio-common.o \ alsa-audio-enc.o +OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_CACA_OUTDEV) += caca.o OBJS-$(CONFIG_DECKLINK_OUTDEV) += decklink_enc.o decklink_enc_c.o @@ -26,6 +25,7 @@ OBJS-$(CONFIG_FBDEV_INDEV) += fbdev_dec.o \ fbdev_common.o OBJS-$(CONFIG_FBDEV_OUTDEV) += fbdev_enc.o \ fbdev_common.o +OBJS-$(CONFIG_GDIGRAB_INDEV) += gdigrab.o OBJS-$(CONFIG_IEC61883_INDEV) += iec61883.o OBJS-$(CONFIG_JACK_INDEV) += jack_audio.o timefilter.o OBJS-$(CONFIG_LAVFI_INDEV) += lavfi.o @@ -37,6 +37,7 @@ OBJS-$(CONFIG_PULSE_INDEV) += pulse_audio_dec.o \ pulse_audio_common.o OBJS-$(CONFIG_PULSE_OUTDEV) += pulse_audio_enc.o \ pulse_audio_common.o +OBJS-$(CONFIG_QTKIT_INDEV) += qtkit.o OBJS-$(CONFIG_SDL_OUTDEV) += sdl.o OBJS-$(CONFIG_SNDIO_INDEV) += sndio_common.o sndio_dec.o OBJS-$(CONFIG_SNDIO_OUTDEV) += sndio_common.o sndio_enc.o @@ -58,6 +59,8 @@ SLIBOBJS-$(HAVE_GNU_WINDRES) += avdeviceres.o SKIPHEADERS-$(CONFIG_DECKLINK) += decklink_enc.h SKIPHEADERS-$(CONFIG_DSHOW_INDEV) += dshow_capture.h +SKIPHEADERS-$(CONFIG_FBDEV_INDEV) += fbdev_common.h +SKIPHEADERS-$(CONFIG_FBDEV_OUTDEV) += fbdev_common.h SKIPHEADERS-$(CONFIG_LIBPULSE) += pulse_audio_common.h SKIPHEADERS-$(CONFIG_V4L2_INDEV) += v4l2-common.h SKIPHEADERS-$(CONFIG_V4L2_OUTDEV) += v4l2-common.h diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index 005bbc8e0..ca34959ee 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -47,12 +47,14 @@ void avdevice_register_all(void) /* devices */ REGISTER_INOUTDEV(ALSA, alsa); + REGISTER_INDEV (AVFOUNDATION, avfoundation); REGISTER_INDEV (BKTR, bktr); REGISTER_OUTDEV (CACA, caca); REGISTER_OUTDEV (DECKLINK, decklink); REGISTER_INDEV (DSHOW, dshow); REGISTER_INDEV (DV1394, dv1394); REGISTER_INOUTDEV(FBDEV, fbdev); + REGISTER_INDEV (GDIGRAB, gdigrab); REGISTER_INDEV (IEC61883, iec61883); REGISTER_INDEV (JACK, jack); REGISTER_INDEV (LAVFI, lavfi); @@ -60,6 +62,7 @@ void avdevice_register_all(void) REGISTER_OUTDEV (OPENGL, opengl); REGISTER_INOUTDEV(OSS, oss); REGISTER_INOUTDEV(PULSE, pulse); + REGISTER_INDEV (QTKIT, qtkit); REGISTER_OUTDEV (SDL, sdl); REGISTER_INOUTDEV(SNDIO, sndio); REGISTER_INOUTDEV(V4L2, v4l2); diff --git a/libavdevice/alsa-audio-dec.c b/libavdevice/alsa-audio-dec.c index 03154b0b7..2cdf356b9 100644 --- a/libavdevice/alsa-audio-dec.c +++ b/libavdevice/alsa-audio-dec.c @@ -143,6 +143,7 @@ static const AVClass alsa_demuxer_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, }; AVInputFormat ff_alsa_demuxer = { diff --git a/libavdevice/alsa-audio-enc.c b/libavdevice/alsa-audio-enc.c index bf56fc46d..e42cc8f51 100644 --- a/libavdevice/alsa-audio-enc.c +++ b/libavdevice/alsa-audio-enc.c @@ -142,6 +142,13 @@ audio_get_output_timestamp(AVFormatContext *s1, int stream, *dts = s->timestamp - delay; } +static const AVClass alsa_muxer_class = { + .class_name = "ALSA muxer", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, +}; + AVOutputFormat ff_alsa_muxer = { .name = "alsa", .long_name = NULL_IF_CONFIG_SMALL("ALSA audio output"), @@ -154,4 +161,5 @@ AVOutputFormat ff_alsa_muxer = { .write_uncoded_frame = audio_write_frame, .get_output_timestamp = audio_get_output_timestamp, .flags = AVFMT_NOFILE, + .priv_class = &alsa_muxer_class, }; diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c index 9e2b7d52d..6a75bd79d 100644 --- a/libavdevice/avdevice.c +++ b/libavdevice/avdevice.c @@ -17,9 +17,46 @@ */ #include "libavutil/avassert.h" +#include "libavutil/samplefmt.h" +#include "libavutil/pixfmt.h" +#include "libavcodec/avcodec.h" #include "avdevice.h" #include "config.h" +#define E AV_OPT_FLAG_ENCODING_PARAM +#define D AV_OPT_FLAG_DECODING_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM +#define V AV_OPT_FLAG_VIDEO_PARAM +#define OFFSET(x) offsetof(AVDeviceCapabilitiesQuery, x) + +const AVOption av_device_capabilities[] = { + { "codec", "codec", OFFSET(codec), AV_OPT_TYPE_INT, + {.i64 = AV_CODEC_ID_NONE}, AV_CODEC_ID_NONE, INT_MAX, E|D|A|V }, + { "sample_format", "sample format", OFFSET(sample_format), AV_OPT_TYPE_INT, + {.i64 = AV_SAMPLE_FMT_NONE}, -1, INT_MAX, E|D|A }, + { "sample_rate", "sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, + {.i64 = -1}, -1, INT_MAX, E|D|A }, + { "channels", "channels", OFFSET(channels), AV_OPT_TYPE_INT, + {.i64 = -1}, -1, INT_MAX, E|D|A }, + { "channel_layout", "channel layout", OFFSET(channel_layout), AV_OPT_TYPE_INT64, + {.i64 = -1}, -1, INT_MAX, E|D|A }, + { "pixel_format", "pixel format", OFFSET(pixel_format), AV_OPT_TYPE_INT, + {.i64 = AV_PIX_FMT_NONE}, -1, INT_MAX, E|D|V }, + { "window_size", "window size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, + {.str = NULL}, -1, INT_MAX, E|D|V }, + { "frame_size", "frame size", OFFSET(frame_width), AV_OPT_TYPE_IMAGE_SIZE, + {.str = NULL}, -1, INT_MAX, E|D|V }, + { "fps", "fps", OFFSET(fps), AV_OPT_TYPE_RATIONAL, + {.dbl = -1}, -1, INT_MAX, E|D|V }, + { NULL } +}; + +#undef E +#undef D +#undef A +#undef V +#undef OFFSET + unsigned avdevice_version(void) { av_assert0(LIBAVDEVICE_VERSION_MICRO >= 100); @@ -37,6 +74,52 @@ const char * avdevice_license(void) return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; } +static void *av_device_next(void *prev, int output, + AVClassCategory c1, AVClassCategory c2) +{ + const AVClass *pc; + AVClassCategory category = AV_CLASS_CATEGORY_NA; + do { + if (output) { + if (!(prev = av_oformat_next(prev))) + break; + pc = ((AVOutputFormat *)prev)->priv_class; + } else { + if (!(prev = av_iformat_next(prev))) + break; + pc = ((AVInputFormat *)prev)->priv_class; + } + if (!pc) + continue; + category = pc->category; + } while (category != c1 && category != c2); + return prev; +} + +AVInputFormat *av_input_audio_device_next(AVInputFormat *d) +{ + return av_device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT); +} + +AVInputFormat *av_input_video_device_next(AVInputFormat *d) +{ + return av_device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT); +} + +AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d) +{ + return av_device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT); +} + +AVOutputFormat *av_output_video_device_next(AVOutputFormat *d) +{ + return av_device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT); +} + int avdevice_app_to_dev_control_message(struct AVFormatContext *s, enum AVAppToDevMessageType type, void *data, size_t data_size) { @@ -53,8 +136,53 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToA return s->control_message_cb(s, type, data, data_size); } +int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s, + AVDictionary **device_options) +{ + int ret; + av_assert0(s && caps); + av_assert0(s->iformat || s->oformat); + if ((s->oformat && !s->oformat->create_device_capabilities) || + (s->iformat && !s->iformat->create_device_capabilities)) + return AVERROR(ENOSYS); + *caps = av_mallocz(sizeof(**caps)); + if (!(*caps)) + return AVERROR(ENOMEM); + (*caps)->device_context = s; + if (((ret = av_opt_set_dict(s->priv_data, device_options)) < 0)) + goto fail; + if (s->iformat) { + if ((ret = s->iformat->create_device_capabilities(s, *caps)) < 0) + goto fail; + } else { + if ((ret = s->oformat->create_device_capabilities(s, *caps)) < 0) + goto fail; + } + av_opt_set_defaults(*caps); + return 0; + fail: + av_freep(caps); + return ret; +} + +void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s) +{ + if (!s || !caps || !(*caps)) + return; + av_assert0(s->iformat || s->oformat); + if (s->iformat) { + if (s->iformat->free_device_capabilities) + s->iformat->free_device_capabilities(s, *caps); + } else { + if (s->oformat->free_device_capabilities) + s->oformat->free_device_capabilities(s, *caps); + } + av_freep(caps); +} + int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list) { + int ret; av_assert0(s); av_assert0(device_list); av_assert0(s->oformat || s->iformat); @@ -66,9 +194,15 @@ int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list) *device_list = av_mallocz(sizeof(AVDeviceInfoList)); if (!(*device_list)) return AVERROR(ENOMEM); + /* no default device by default */ + (*device_list)->default_device = -1; if (s->oformat) - return s->oformat->get_device_list(s, *device_list); - return s->iformat->get_device_list(s, *device_list); + ret = s->oformat->get_device_list(s, *device_list); + else + ret = s->iformat->get_device_list(s, *device_list); + if (ret < 0) + avdevice_free_list_devices(device_list); + return ret; } void avdevice_free_list_devices(AVDeviceInfoList **device_list) diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h index 28344ca16..a39522819 100644 --- a/libavdevice/avdevice.h +++ b/libavdevice/avdevice.h @@ -43,6 +43,9 @@ * @} */ +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "libavutil/dict.h" #include "libavformat/avformat.h" /** @@ -66,6 +69,42 @@ const char *avdevice_license(void); */ void avdevice_register_all(void); +/** + * Audio input devices iterator. + * + * If d is NULL, returns the first registered input audio/video device, + * if d is non-NULL, returns the next registered input audio/video device after d + * or NULL if d is the last one. + */ +AVInputFormat *av_input_audio_device_next(AVInputFormat *d); + +/** + * Video input devices iterator. + * + * If d is NULL, returns the first registered input audio/video device, + * if d is non-NULL, returns the next registered input audio/video device after d + * or NULL if d is the last one. + */ +AVInputFormat *av_input_video_device_next(AVInputFormat *d); + +/** + * Audio output devices iterator. + * + * If d is NULL, returns the first registered output audio/video device, + * if d is non-NULL, returns the next registered output audio/video device after d + * or NULL if d is the last one. + */ +AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d); + +/** + * Video output devices iterator. + * + * If d is NULL, returns the first registered output audio/video device, + * if d is non-NULL, returns the next registered output audio/video device after d + * or NULL if d is the last one. + */ +AVOutputFormat *av_output_video_device_next(AVOutputFormat *d); + typedef struct AVDeviceRect { int x; /**< x coordinate of top left corner */ int y; /**< y coordinate of top left corner */ @@ -96,12 +135,60 @@ enum AVAppToDevMessageType { /** * Repaint request message. * - * Message is sent to the device when window have to be rapainted. + * Message is sent to the device when window has to be repainted. * * data: AVDeviceRect: area required to be repainted. * NULL: whole area is required to be repainted. */ - AV_APP_TO_DEV_WINDOW_REPAINT = MKBETAG('R','E','P','A') + AV_APP_TO_DEV_WINDOW_REPAINT = MKBETAG('R','E','P','A'), + + /** + * Request pause/play. + * + * Application requests pause/unpause playback. + * Mostly usable with devices that have internal buffer. + * By default devices are not paused. + * + * data: NULL + */ + AV_APP_TO_DEV_PAUSE = MKBETAG('P', 'A', 'U', ' '), + AV_APP_TO_DEV_PLAY = MKBETAG('P', 'L', 'A', 'Y'), + AV_APP_TO_DEV_TOGGLE_PAUSE = MKBETAG('P', 'A', 'U', 'T'), + + /** + * Volume control message. + * + * Set volume level. It may be device-dependent if volume + * is changed per stream or system wide. Per stream volume + * change is expected when possible. + * + * data: double: new volume with range of 0.0 - 1.0. + */ + AV_APP_TO_DEV_SET_VOLUME = MKBETAG('S', 'V', 'O', 'L'), + + /** + * Mute control messages. + * + * Change mute state. It may be device-dependent if mute status + * is changed per stream or system wide. Per stream mute status + * change is expected when possible. + * + * data: NULL. + */ + AV_APP_TO_DEV_MUTE = MKBETAG(' ', 'M', 'U', 'T'), + AV_APP_TO_DEV_UNMUTE = MKBETAG('U', 'M', 'U', 'T'), + AV_APP_TO_DEV_TOGGLE_MUTE = MKBETAG('T', 'M', 'U', 'T'), + + /** + * Get volume/mute messages. + * + * Force the device to send AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED or + * AV_DEV_TO_APP_MUTE_STATE_CHANGED command respectively. + * + * data: NULL. + */ + AV_APP_TO_DEV_GET_VOLUME = MKBETAG('G', 'V', 'O', 'L'), + AV_APP_TO_DEV_GET_MUTE = MKBETAG('G', 'M', 'U', 'T'), }; /** @@ -144,7 +231,7 @@ enum AVDevToAppMessageType { * Display window buffer message. * * Device requests to display a window buffer. - * Message is sent when new frame is ready to be displyed. + * Message is sent when new frame is ready to be displayed. * Usually buffers need to be swapped in handler of this message. * * data: NULL. @@ -160,7 +247,49 @@ enum AVDevToAppMessageType { * * data: NULL. */ - AV_DEV_TO_APP_DESTROY_WINDOW_BUFFER = MKBETAG('B','D','E','S') + AV_DEV_TO_APP_DESTROY_WINDOW_BUFFER = MKBETAG('B','D','E','S'), + + /** + * Buffer fullness status messages. + * + * Device signals buffer overflow/underflow. + * + * data: NULL. + */ + AV_DEV_TO_APP_BUFFER_OVERFLOW = MKBETAG('B','O','F','L'), + AV_DEV_TO_APP_BUFFER_UNDERFLOW = MKBETAG('B','U','F','L'), + + /** + * Buffer readable/writable. + * + * Device informs that buffer is readable/writable. + * When possible, device informs how many bytes can be read/write. + * + * @warning Device may not inform when number of bytes than can be read/write changes. + * + * data: int64_t: amount of bytes available to read/write. + * NULL: amount of bytes available to read/write is not known. + */ + AV_DEV_TO_APP_BUFFER_READABLE = MKBETAG('B','R','D',' '), + AV_DEV_TO_APP_BUFFER_WRITABLE = MKBETAG('B','W','R',' '), + + /** + * Mute state change message. + * + * Device informs that mute state has changed. + * + * data: int: 0 for not muted state, non-zero for muted state. + */ + AV_DEV_TO_APP_MUTE_STATE_CHANGED = MKBETAG('C','M','U','T'), + + /** + * Volume level change message. + * + * Device informs that volume level has changed. + * + * data: double: new volume with range of 0.0 - 1.0. + */ + AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED = MKBETAG('C','V','O','L'), }; /** @@ -191,6 +320,131 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToAppMessageType type, void *data, size_t data_size); +/** + * Following API allows user to probe device capabilities (supported codecs, + * pixel formats, sample formats, resolutions, channel counts, etc). + * It is build on top op AVOption API. + * Queried capabilities allows to set up converters of video or audio + * parameters that fit to the device. + * + * List of capabilities that can be queried: + * - Capabilities valid for both audio and video devices: + * - codec: supported audio/video codecs. + * type: AV_OPT_TYPE_INT (AVCodecID value) + * - Capabilities valid for audio devices: + * - sample_format: supported sample formats. + * type: AV_OPT_TYPE_INT (AVSampleFormat value) + * - sample_rate: supported sample rates. + * type: AV_OPT_TYPE_INT + * - channels: supported number of channels. + * type: AV_OPT_TYPE_INT + * - channel_layout: supported channel layouts. + * type: AV_OPT_TYPE_INT64 + * - Capabilities valid for video devices: + * - pixel_format: supported pixel formats. + * type: AV_OPT_TYPE_INT (AVPixelFormat value) + * - window_size: supported window sizes (describes size of the window size presented to the user). + * type: AV_OPT_TYPE_IMAGE_SIZE + * - frame_size: supported frame sizes (describes size of provided video frames). + * type: AV_OPT_TYPE_IMAGE_SIZE + * - fps: supported fps values + * type: AV_OPT_TYPE_RATIONAL + * + * Value of the capability may be set by user using av_opt_set() function + * and AVDeviceCapabilitiesQuery object. Following queries will + * limit results to the values matching already set capabilities. + * For example, setting a codec may impact number of formats or fps values + * returned during next query. Setting invalid value may limit results to zero. + * + * Example of the usage basing on opengl output device: + * + * @code + * AVFormatContext *oc = NULL; + * AVDeviceCapabilitiesQuery *caps = NULL; + * AVOptionRanges *ranges; + * int ret; + * + * if ((ret = avformat_alloc_output_context2(&oc, NULL, "opengl", NULL)) < 0) + * goto fail; + * if (avdevice_capabilities_create(&caps, oc, NULL) < 0) + * goto fail; + * + * //query codecs + * if (av_opt_query_ranges(&ranges, caps, "codec", AV_OPT_MULTI_COMPONENT_RANGE)) < 0) + * goto fail; + * //pick codec here and set it + * av_opt_set(caps, "codec", AV_CODEC_ID_RAWVIDEO, 0); + * + * //query format + * if (av_opt_query_ranges(&ranges, caps, "pixel_format", AV_OPT_MULTI_COMPONENT_RANGE)) < 0) + * goto fail; + * //pick format here and set it + * av_opt_set(caps, "pixel_format", AV_PIX_FMT_YUV420P, 0); + * + * //query and set more capabilities + * + * fail: + * //clean up code + * avdevice_capabilities_free(&query, oc); + * avformat_free_context(oc); + * @endcode + */ + +/** + * Structure describes device capabilities. + * + * It is used by devices in conjunction with av_device_capabilities AVOption table + * to implement capabilities probing API based on AVOption API. Should not be used directly. + */ +typedef struct AVDeviceCapabilitiesQuery { + const AVClass *av_class; + AVFormatContext *device_context; + enum AVCodecID codec; + enum AVSampleFormat sample_format; + enum AVPixelFormat pixel_format; + int sample_rate; + int channels; + int64_t channel_layout; + int window_width; + int window_height; + int frame_width; + int frame_height; + AVRational fps; +} AVDeviceCapabilitiesQuery; + +/** + * AVOption table used by devices to implement device capabilities API. Should not be used by a user. + */ +extern const AVOption av_device_capabilities[]; + +/** + * Initialize capabilities probing API based on AVOption API. + * + * avdevice_capabilities_free() must be called when query capabilities API is + * not used anymore. + * + * @param[out] caps Device capabilities data. Pointer to a NULL pointer must be passed. + * @param s Context of the device. + * @param device_options An AVDictionary filled with device-private options. + * On return this parameter will be destroyed and replaced with a dict + * containing options that were not found. May be NULL. + * The same options must be passed later to avformat_write_header() for output + * devices or avformat_open_input() for input devices, or at any other place + * that affects device-private options. + * + * @return >= 0 on success, negative otherwise. + */ +int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s, + AVDictionary **device_options); + +/** + * Free resources created by avdevice_capabilities_create() + * + * @param caps Device capabilities data to be freed. + * @param s Context of the device. + */ +void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s); + /** * Structure describes basic parameters of the device. */ @@ -224,7 +478,7 @@ typedef struct AVDeviceInfoList { int avdevice_list_devices(struct AVFormatContext *s, AVDeviceInfoList **device_list); /** - * Convinient function to free result of avdevice_list_devices(). + * Convenient function to free result of avdevice_list_devices(). * * @param devices device list to be freed. */ diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m new file mode 100644 index 000000000..74d781134 --- /dev/null +++ b/libavdevice/avfoundation.m @@ -0,0 +1,465 @@ +/* + * AVFoundation input device + * Copyright (c) 2014 Thilo Borgmann + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * AVFoundation input device + * @author Thilo Borgmann + */ + +#import +#include + +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "libavformat/internal.h" +#include "libavutil/internal.h" +#include "libavutil/time.h" +#include "avdevice.h" + +static const int avf_time_base = 100; + +static const AVRational avf_time_base_q = { + .num = 1, + .den = avf_time_base +}; + +struct AVFPixelFormatSpec { + enum AVPixelFormat ff_id; + OSType avf_id; +}; + +static const struct AVFPixelFormatSpec avf_pixel_formats[] = { + { AV_PIX_FMT_MONOBLACK, kCVPixelFormatType_1Monochrome }, + { 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_RGB24, kCVPixelFormatType_24RGB }, + { AV_PIX_FMT_BGR24, kCVPixelFormatType_24BGR }, + { AV_PIX_FMT_0RGB, kCVPixelFormatType_32ARGB }, + { AV_PIX_FMT_BGR0, kCVPixelFormatType_32BGRA }, + { AV_PIX_FMT_0BGR, kCVPixelFormatType_32ABGR }, + { AV_PIX_FMT_RGB0, kCVPixelFormatType_32RGBA }, + { AV_PIX_FMT_BGR48BE, kCVPixelFormatType_48RGB }, + { AV_PIX_FMT_UYVY422, kCVPixelFormatType_422YpCbCr8 }, + { AV_PIX_FMT_YUVA444P, kCVPixelFormatType_4444YpCbCrA8R }, + { AV_PIX_FMT_YUVA444P16LE, kCVPixelFormatType_4444AYpCbCr16 }, + { AV_PIX_FMT_YUV444P, kCVPixelFormatType_444YpCbCr8 }, + { AV_PIX_FMT_YUV422P16, kCVPixelFormatType_422YpCbCr16 }, + { AV_PIX_FMT_YUV422P10, kCVPixelFormatType_422YpCbCr10 }, + { AV_PIX_FMT_YUV444P10, kCVPixelFormatType_444YpCbCr10 }, + { AV_PIX_FMT_YUV420P, kCVPixelFormatType_420YpCbCr8Planar }, + { AV_PIX_FMT_NV12, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange }, + { 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 } +}; + +typedef struct +{ + AVClass* class; + + float frame_rate; + int frames_captured; + int64_t first_pts; + pthread_mutex_t frame_lock; + pthread_cond_t frame_wait_cond; + id avf_delegate; + + int list_devices; + int video_device_index; + enum AVPixelFormat pixel_format; + + AVCaptureSession *capture_session; + AVCaptureVideoDataOutput *video_output; + CMSampleBufferRef current_frame; +} AVFContext; + +static void lock_frames(AVFContext* ctx) +{ + pthread_mutex_lock(&ctx->frame_lock); +} + +static void unlock_frames(AVFContext* ctx) +{ + pthread_mutex_unlock(&ctx->frame_lock); +} + +/** FrameReciever class - delegate for AVCaptureSession + */ +@interface AVFFrameReceiver : NSObject +{ + AVFContext* _context; +} + +- (id)initWithContext:(AVFContext*)context; + +- (void) captureOutput:(AVCaptureOutput *)captureOutput + didOutputSampleBuffer:(CMSampleBufferRef)videoFrame + fromConnection:(AVCaptureConnection *)connection; + +@end + +@implementation AVFFrameReceiver + +- (id)initWithContext:(AVFContext*)context +{ + if (self = [super init]) { + _context = context; + } + return self; +} + +- (void) captureOutput:(AVCaptureOutput *)captureOutput + didOutputSampleBuffer:(CMSampleBufferRef)videoFrame + fromConnection:(AVCaptureConnection *)connection +{ + lock_frames(_context); + + if (_context->current_frame != nil) { + CFRelease(_context->current_frame); + } + + _context->current_frame = (CMSampleBufferRef)CFRetain(videoFrame); + + pthread_cond_signal(&_context->frame_wait_cond); + + unlock_frames(_context); + + ++_context->frames_captured; +} + +@end + +static void destroy_context(AVFContext* ctx) +{ + [ctx->capture_session stopRunning]; + + [ctx->capture_session release]; + [ctx->video_output release]; + [ctx->avf_delegate release]; + + ctx->capture_session = NULL; + ctx->video_output = NULL; + ctx->avf_delegate = NULL; + + pthread_mutex_destroy(&ctx->frame_lock); + pthread_cond_destroy(&ctx->frame_wait_cond); + + if (ctx->current_frame) { + CFRelease(ctx->current_frame); + } +} + +static int avf_read_header(AVFormatContext *s) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + AVFContext *ctx = (AVFContext*)s->priv_data; + ctx->first_pts = av_gettime(); + + pthread_mutex_init(&ctx->frame_lock, NULL); + pthread_cond_init(&ctx->frame_wait_cond, NULL); + + // List devices if requested + if (ctx->list_devices) { + av_log(ctx, AV_LOG_INFO, "AVFoundation video devices:\n"); + NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; + for (AVCaptureDevice *device in devices) { + const char *name = [[device localizedName] UTF8String]; + int index = [devices indexOfObject:device]; + av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name); + } + goto fail; + } + + // Find capture device + AVCaptureDevice *video_device = nil; + + // check for device index given in filename + if (ctx->video_device_index == -1) { + sscanf(s->filename, "%d", &ctx->video_device_index); + } + + if (ctx->video_device_index >= 0) { + NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; + + if (ctx->video_device_index >= [devices count]) { + av_log(ctx, AV_LOG_ERROR, "Invalid device index\n"); + goto fail; + } + + video_device = [devices objectAtIndex:ctx->video_device_index]; + } else if (strncmp(s->filename, "", 1) && + strncmp(s->filename, "default", 7)) { + NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; + + for (AVCaptureDevice *device in devices) { + if (!strncmp(s->filename, [[device localizedName] UTF8String], strlen(s->filename))) { + video_device = device; + break; + } + } + + if (!video_device) { + av_log(ctx, AV_LOG_ERROR, "Video device not found\n"); + goto fail; + } + } else { + video_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeMuxed]; + } + + // Video capture device not found, looking for AVMediaTypeVideo + if (!video_device) { + video_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + + if (!video_device) { + av_log(s, AV_LOG_ERROR, "No AV capture device found\n"); + goto fail; + } + } + + NSString* dev_display_name = [video_device localizedName]; + av_log(s, AV_LOG_DEBUG, "'%s' opened\n", [dev_display_name UTF8String]); + + // Initialize capture session + ctx->capture_session = [[AVCaptureSession alloc] init]; + + NSError *error = nil; + AVCaptureDeviceInput* capture_dev_input = [[[AVCaptureDeviceInput alloc] initWithDevice:video_device error:&error] autorelease]; + + if (!capture_dev_input) { + av_log(s, AV_LOG_ERROR, "Failed to create AV capture input device: %s\n", + [[error localizedDescription] UTF8String]); + goto fail; + } + + if (!capture_dev_input) { + av_log(s, AV_LOG_ERROR, "Failed to add AV capture input device to session: %s\n", + [[error localizedDescription] UTF8String]); + goto fail; + } + + if ([ctx->capture_session canAddInput:capture_dev_input]) { + [ctx->capture_session addInput:capture_dev_input]; + } else { + av_log(s, AV_LOG_ERROR, "can't add video input to capture session\n"); + goto fail; + } + + // Attaching output + ctx->video_output = [[AVCaptureVideoDataOutput alloc] init]; + + if (!ctx->video_output) { + av_log(s, AV_LOG_ERROR, "Failed to init AV video output\n"); + goto fail; + } + + // select pixel format + struct AVFPixelFormatSpec pxl_fmt_spec; + pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE; + + for (int i = 0; avf_pixel_formats[i].ff_id != AV_PIX_FMT_NONE; i++) { + if (ctx->pixel_format == avf_pixel_formats[i].ff_id) { + pxl_fmt_spec = avf_pixel_formats[i]; + break; + } + } + + // check if selected pixel format is supported by AVFoundation + if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) { + av_log(s, AV_LOG_ERROR, "Selected pixel format (%s) is not supported by AVFoundation.\n", + av_get_pix_fmt_name(pxl_fmt_spec.ff_id)); + goto fail; + } + + // check if the pixel format is available for this device + if ([[ctx->video_output availableVideoCVPixelFormatTypes] indexOfObject:[NSNumber numberWithInt:pxl_fmt_spec.avf_id]] == NSNotFound) { + av_log(s, AV_LOG_ERROR, "Selected pixel format (%s) is not supported by the input device.\n", + av_get_pix_fmt_name(pxl_fmt_spec.ff_id)); + + pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE; + + av_log(s, AV_LOG_ERROR, "Supported pixel formats:\n"); + for (NSNumber *pxl_fmt in [ctx->video_output availableVideoCVPixelFormatTypes]) { + struct AVFPixelFormatSpec pxl_fmt_dummy; + pxl_fmt_dummy.ff_id = AV_PIX_FMT_NONE; + for (int i = 0; avf_pixel_formats[i].ff_id != AV_PIX_FMT_NONE; i++) { + if ([pxl_fmt intValue] == avf_pixel_formats[i].avf_id) { + pxl_fmt_dummy = avf_pixel_formats[i]; + break; + } + } + + if (pxl_fmt_dummy.ff_id != AV_PIX_FMT_NONE) { + av_log(s, AV_LOG_ERROR, " %s\n", av_get_pix_fmt_name(pxl_fmt_dummy.ff_id)); + + // select first supported pixel format instead of user selected (or default) pixel format + if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) { + pxl_fmt_spec = pxl_fmt_dummy; + } + } + } + + // fail if there is no appropriate pixel format or print a warning about overriding the pixel format + if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) { + goto fail; + } else { + av_log(s, AV_LOG_WARNING, "Overriding selected pixel format to use %s instead.\n", + av_get_pix_fmt_name(pxl_fmt_spec.ff_id)); + } + } + + + NSNumber *pixel_format = [NSNumber numberWithUnsignedInt:pxl_fmt_spec.avf_id]; + NSDictionary *capture_dict = [NSDictionary dictionaryWithObject:pixel_format + forKey:(id)kCVPixelBufferPixelFormatTypeKey]; + + [ctx->video_output setVideoSettings:capture_dict]; + [ctx->video_output setAlwaysDiscardsLateVideoFrames:YES]; + + ctx->avf_delegate = [[AVFFrameReceiver alloc] initWithContext:ctx]; + + dispatch_queue_t queue = dispatch_queue_create("avf_queue", NULL); + [ctx->video_output setSampleBufferDelegate:ctx->avf_delegate queue:queue]; + dispatch_release(queue); + + if ([ctx->capture_session canAddOutput:ctx->video_output]) { + [ctx->capture_session addOutput:ctx->video_output]; + } else { + av_log(s, AV_LOG_ERROR, "can't add video output to capture session\n"); + goto fail; + } + + [ctx->capture_session startRunning]; + + // Take stream info from the first frame. + while (ctx->frames_captured < 1) { + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES); + } + + lock_frames(ctx); + + AVStream* stream = avformat_new_stream(s, NULL); + + if (!stream) { + goto fail; + } + + avpriv_set_pts_info(stream, 64, 1, avf_time_base); + + CVImageBufferRef image_buffer = CMSampleBufferGetImageBuffer(ctx->current_frame); + CGSize 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 = pxl_fmt_spec.ff_id; + + CFRelease(ctx->current_frame); + ctx->current_frame = nil; + + unlock_frames(ctx); + [pool release]; + return 0; + +fail: + [pool release]; + destroy_context(ctx); + return AVERROR(EIO); +} + +static int avf_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVFContext* ctx = (AVFContext*)s->priv_data; + + do { + lock_frames(ctx); + + CVImageBufferRef image_buffer = CMSampleBufferGetImageBuffer(ctx->current_frame); + + if (ctx->current_frame != nil) { + if (av_new_packet(pkt, (int)CVPixelBufferGetDataSize(image_buffer)) < 0) { + return AVERROR(EIO); + } + + pkt->pts = pkt->dts = av_rescale_q(av_gettime() - ctx->first_pts, + AV_TIME_BASE_Q, + avf_time_base_q); + pkt->stream_index = 0; + pkt->flags |= AV_PKT_FLAG_KEY; + + CVPixelBufferLockBaseAddress(image_buffer, 0); + + void* data = CVPixelBufferGetBaseAddress(image_buffer); + memcpy(pkt->data, data, pkt->size); + + CVPixelBufferUnlockBaseAddress(image_buffer, 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 avf_close(AVFormatContext *s) +{ + AVFContext* ctx = (AVFContext*)s->priv_data; + destroy_context(ctx); + return 0; +} + +static const AVOption options[] = { + { "frame_rate", "set frame rate", offsetof(AVFContext, frame_rate), AV_OPT_TYPE_FLOAT, { .dbl = 30.0 }, 0.1, 30.0, AV_OPT_TYPE_VIDEO_RATE, NULL }, + { "list_devices", "list available devices", offsetof(AVFContext, list_devices), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM, "list_devices" }, + { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" }, + { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" }, + { "video_device_index", "select video device by index for devices with same name (starts at 0)", offsetof(AVFContext, video_device_index), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { "pixel_format", "set pixel format", offsetof(AVFContext, pixel_format), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_YUV420P}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM}, + { NULL }, +}; + +static const AVClass avf_class = { + .class_name = "AVFoundation input device", + .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 input device"), + .priv_data_size = sizeof(AVFContext), + .read_header = avf_read_header, + .read_packet = avf_read_packet, + .read_close = avf_close, + .flags = AVFMT_NOFILE, + .priv_class = &avf_class, +}; diff --git a/libavdevice/bktr.c b/libavdevice/bktr.c index 4e25aa6ad..50dcc7d21 100644 --- a/libavdevice/bktr.c +++ b/libavdevice/bktr.c @@ -334,6 +334,7 @@ static const AVClass bktr_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, }; AVInputFormat ff_bktr_demuxer = { diff --git a/libavdevice/caca.c b/libavdevice/caca.c index 0a7470120..a11806478 100644 --- a/libavdevice/caca.c +++ b/libavdevice/caca.c @@ -224,6 +224,7 @@ static const AVClass caca_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; AVOutputFormat ff_caca_muxer = { diff --git a/libavdevice/decklink_enc_c.c b/libavdevice/decklink_enc_c.c index b98e0b4fa..7c1804376 100644 --- a/libavdevice/decklink_enc_c.c +++ b/libavdevice/decklink_enc_c.c @@ -38,6 +38,7 @@ static const AVClass decklink_muxer_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; AVOutputFormat ff_decklink_muxer = { diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 5293d263a..adf36a7b3 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -53,7 +53,7 @@ struct dshow_ctx { int eof; - int64_t curbufsize; + int64_t curbufsize[2]; unsigned int video_frame_num; IMediaControl *control; @@ -89,7 +89,7 @@ static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount) case 24: return AV_PIX_FMT_BGR24; case 32: - return AV_PIX_FMT_RGB32; + return AV_PIX_FMT_0RGB32; } } return avpriv_find_pix_fmt(ff_raw_pix_fmt_tags, biCompression); // all others @@ -180,16 +180,16 @@ static char *dup_wchar_to_utf8(wchar_t *w) return s; } -static int shall_we_drop(AVFormatContext *s) +static int shall_we_drop(AVFormatContext *s, int index, enum dshowDeviceType devtype) { struct dshow_ctx *ctx = s->priv_data; static const uint8_t dropscore[] = {62, 75, 87, 100}; const int ndropscores = FF_ARRAY_ELEMS(dropscore); - unsigned int buffer_fullness = (ctx->curbufsize*100)/s->max_picture_buffer; + unsigned int buffer_fullness = (ctx->curbufsize[index]*100)/s->max_picture_buffer; if(dropscore[++ctx->video_frame_num%ndropscores] <= buffer_fullness) { av_log(s, AV_LOG_ERROR, - "real-time buffer %d%% full! frame dropped!\n", buffer_fullness); + "real-time buffer[%s] too full (%d%% of size: %d)! frame dropped!\n", ctx->device_name[devtype], buffer_fullness, s->max_picture_buffer); return 1; } @@ -197,7 +197,7 @@ static int shall_we_drop(AVFormatContext *s) } static void -callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time) +callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType devtype) { AVFormatContext *s = priv_data; struct dshow_ctx *ctx = s->priv_data; @@ -207,7 +207,7 @@ callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time) WaitForSingleObject(ctx->mutex, INFINITE); - if(shall_we_drop(s)) + if(shall_we_drop(s, index, devtype)) goto fail; pktl_next = av_mallocz(sizeof(AVPacketList)); @@ -225,8 +225,7 @@ callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time) for(ppktl = &ctx->pktl ; *ppktl ; ppktl = &(*ppktl)->next); *ppktl = pktl_next; - - ctx->curbufsize += buf_size; + ctx->curbufsize[index] += buf_size; SetEvent(ctx->event[1]); ReleaseMutex(ctx->mutex); @@ -580,8 +579,9 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype, } } if (devtype == AudioDevice && ctx->audio_buffer_size) { - if (dshow_set_audio_buffer_size(avctx, pin) < 0) - goto next; + if (dshow_set_audio_buffer_size(avctx, pin) < 0) { + av_log(avctx, AV_LOG_ERROR, "unable to set audio buffer size %d to pin, using pin anyway...", ctx->audio_buffer_size); + } } if (IPin_EnumMediaTypes(pin, &types) != S_OK) @@ -773,6 +773,7 @@ dshow_add_device(AVFormatContext *avctx, codec->codec_type = AVMEDIA_TYPE_VIDEO; codec->width = bih->biWidth; codec->height = bih->biHeight; + codec->codec_tag = bih->biCompression; codec->pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount); if (bih->biCompression == MKTAG('H', 'D', 'Y', 'C')) { av_log(avctx, AV_LOG_DEBUG, "attempt to use full range for HDYC...\n"); @@ -943,7 +944,8 @@ static int dshow_read_header(AVFormatContext *avctx) goto error; } } - + ctx->curbufsize[0] = 0; + ctx->curbufsize[1] = 0; ctx->mutex = CreateMutex(NULL, 0, NULL); if (!ctx->mutex) { av_log(avctx, AV_LOG_ERROR, "Could not create Mutex\n"); @@ -1037,7 +1039,7 @@ static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt) *pkt = pktl->pkt; ctx->pktl = ctx->pktl->next; av_free(pktl); - ctx->curbufsize -= pkt->size; + ctx->curbufsize[pkt->stream_index] -= pkt->size; } ResetEvent(ctx->event[1]); ReleaseMutex(ctx->mutex); @@ -1081,6 +1083,7 @@ static const AVClass dshow_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, }; AVInputFormat ff_dshow_demuxer = { diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index aff5019b3..e4b4dce3f 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -254,7 +254,7 @@ struct libAVFilter { void *priv_data; int stream_index; int64_t start_time; - void (*callback)(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time); + void (*callback)(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType type); }; long WINAPI libAVFilter_QueryInterface (libAVFilter *, const GUID *, void **); diff --git a/libavdevice/dshow_enummediatypes.c b/libavdevice/dshow_enummediatypes.c index aaed58b44..5b69a5b74 100644 --- a/libavdevice/dshow_enummediatypes.c +++ b/libavdevice/dshow_enummediatypes.c @@ -22,7 +22,7 @@ #include "dshow_capture.h" DECLARE_QUERYINTERFACE(libAVEnumMediaTypes, - { {&IID_IUnknown,0}, {&IID_IEnumPins,0} }) + { {&IID_IUnknown,0}, {&IID_IEnumMediaTypes,0} }) DECLARE_ADDREF(libAVEnumMediaTypes) DECLARE_RELEASE(libAVEnumMediaTypes) @@ -82,7 +82,7 @@ libAVEnumMediaTypes_Clone(libAVEnumMediaTypes *this, libAVEnumMediaTypes **enums static int libAVEnumMediaTypes_Setup(libAVEnumMediaTypes *this, const AM_MEDIA_TYPE *type) { - IEnumPinsVtbl *vtbl = this->vtbl; + IEnumMediaTypesVtbl *vtbl = this->vtbl; SETVTBL(vtbl, libAVEnumMediaTypes, QueryInterface); SETVTBL(vtbl, libAVEnumMediaTypes, AddRef); SETVTBL(vtbl, libAVEnumMediaTypes, Release); diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c index 30e4d9585..1c0dca240 100644 --- a/libavdevice/dshow_pin.c +++ b/libavdevice/dshow_pin.c @@ -328,7 +328,7 @@ libAVMemInputPin_Receive(libAVMemInputPin *this, IMediaSample *sample) priv_data = pin->filter->priv_data; index = pin->filter->stream_index; - pin->filter->callback(priv_data, index, buf, buf_size, curtime); + pin->filter->callback(priv_data, index, buf, buf_size, curtime, devtype); return S_OK; } diff --git a/libavdevice/dv1394.c b/libavdevice/dv1394.c index 0af5ea53c..c8241e33f 100644 --- a/libavdevice/dv1394.c +++ b/libavdevice/dv1394.c @@ -224,6 +224,7 @@ static const AVClass dv1394_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, }; AVInputFormat ff_dv1394_demuxer = { diff --git a/libavdevice/fbdev_common.c b/libavdevice/fbdev_common.c index 45ae08b69..634780d58 100644 --- a/libavdevice/fbdev_common.c +++ b/libavdevice/fbdev_common.c @@ -20,9 +20,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include +#include #include #include "fbdev_common.h" #include "libavutil/common.h" +#include "avdevice.h" struct rgb_pixfmt_map_entry { int bits_per_pixel; @@ -65,3 +69,61 @@ const char* ff_fbdev_default_device() return dev; } +int ff_fbdev_get_device_list(AVDeviceInfoList *device_list) +{ + struct fb_var_screeninfo varinfo; + struct fb_fix_screeninfo fixinfo; + char device_file[12]; + AVDeviceInfo *device = NULL; + int i, fd, ret = 0; + const char *default_device = ff_fbdev_default_device(); + + if (!device_list) + return AVERROR(EINVAL); + + for (i = 0; i <= 31; i++) { + snprintf(device_file, sizeof(device_file), "/dev/fb%d", i); + + if ((fd = avpriv_open(device_file, O_RDWR)) < 0) + continue; + if (ioctl(fd, FBIOGET_VSCREENINFO, &varinfo) == -1) + goto fail_device; + if (ioctl(fd, FBIOGET_FSCREENINFO, &fixinfo) == -1) + goto fail_device; + + device = av_mallocz(sizeof(AVDeviceInfo)); + if (!device) { + ret = AVERROR(ENOMEM); + goto fail_device; + } + device->device_name = av_strdup(device_file); + device->device_description = av_strdup(fixinfo.id); + if (!device->device_name || !device->device_description) { + ret = AVERROR(ENOMEM); + goto fail_device; + } + + if ((ret = av_dynarray_add_nofree(&device_list->devices, + &device_list->nb_devices, device)) < 0) + goto fail_device; + + if (default_device && !strcmp(device->device_name, default_device)) { + device_list->default_device = device_list->nb_devices - 1; + default_device = NULL; + } + close(fd); + continue; + + fail_device: + if (device) { + av_free(device->device_name); + av_free(device->device_description); + av_freep(&device); + } + if (fd >= 0) + close(fd); + if (ret < 0) + return ret; + } + return 0; +} diff --git a/libavdevice/fbdev_common.h b/libavdevice/fbdev_common.h index 40a1ded84..7b81a8dae 100644 --- a/libavdevice/fbdev_common.h +++ b/libavdevice/fbdev_common.h @@ -27,8 +27,12 @@ #include #include "libavutil/pixfmt.h" +struct AVDeviceInfoList; + enum AVPixelFormat ff_get_pixfmt_from_fb_varinfo(struct fb_var_screeninfo *varinfo); const char* ff_fbdev_default_device(void); +int ff_fbdev_get_device_list(struct AVDeviceInfoList *device_list); + #endif /* AVDEVICE_FBDEV_COMMON_H */ diff --git a/libavdevice/fbdev_dec.c b/libavdevice/fbdev_dec.c index 14ebab35c..d53b9e591 100644 --- a/libavdevice/fbdev_dec.c +++ b/libavdevice/fbdev_dec.c @@ -205,6 +205,11 @@ static av_cold int fbdev_read_close(AVFormatContext *avctx) return 0; } +static int fbdev_get_device_list(AVFormatContext *s, AVDeviceInfoList *device_list) +{ + return ff_fbdev_get_device_list(device_list); +} + #define OFFSET(x) offsetof(FBDevContext, x) #define DEC AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { @@ -217,6 +222,7 @@ static const AVClass fbdev_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, }; AVInputFormat ff_fbdev_demuxer = { @@ -226,6 +232,7 @@ AVInputFormat ff_fbdev_demuxer = { .read_header = fbdev_read_header, .read_packet = fbdev_read_packet, .read_close = fbdev_read_close, + .get_device_list = fbdev_get_device_list, .flags = AVFMT_NOFILE, .priv_class = &fbdev_class, }; diff --git a/libavdevice/fbdev_enc.c b/libavdevice/fbdev_enc.c index 8291b5975..28efc7131 100644 --- a/libavdevice/fbdev_enc.c +++ b/libavdevice/fbdev_enc.c @@ -29,6 +29,7 @@ #include "libavutil/opt.h" #include "libavformat/avformat.h" #include "fbdev_common.h" +#include "avdevice.h" typedef struct { AVClass *class; ///< class for private options @@ -183,6 +184,11 @@ static av_cold int fbdev_write_trailer(AVFormatContext *h) return 0; } +static int fbdev_get_device_list(AVFormatContext *s, AVDeviceInfoList *device_list) +{ + return ff_fbdev_get_device_list(device_list); +} + #define OFFSET(x) offsetof(FBDevContext, x) #define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { @@ -196,6 +202,7 @@ static const AVClass fbdev_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; AVOutputFormat ff_fbdev_muxer = { @@ -207,6 +214,7 @@ AVOutputFormat ff_fbdev_muxer = { .write_header = fbdev_write_header, .write_packet = fbdev_write_packet, .write_trailer = fbdev_write_trailer, + .get_device_list = fbdev_get_device_list, .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, .priv_class = &fbdev_class, }; diff --git a/libavdevice/gdigrab.c b/libavdevice/gdigrab.c new file mode 100644 index 000000000..bccfef2c8 --- /dev/null +++ b/libavdevice/gdigrab.c @@ -0,0 +1,630 @@ +/* + * GDI video grab interface + * + * This file is part of FFmpeg. + * + * Copyright (C) 2013 Calvin Walton + * Copyright (C) 2007-2010 Christophe Gisquet + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * GDI frame device demuxer + * @author Calvin Walton + * @author Christophe Gisquet + */ + +#include "config.h" +#include "libavformat/internal.h" +#include "libavutil/opt.h" +#include "libavutil/time.h" +#include + +/** + * GDI Device Demuxer context + */ +struct gdigrab { + const AVClass *class; /**< Class for private options */ + + int frame_size; /**< Size in bytes of the frame pixel data */ + int header_size; /**< Size in bytes of the DIB header */ + AVRational time_base; /**< Time base */ + int64_t time_frame; /**< Current time */ + + int draw_mouse; /**< Draw mouse cursor (private option) */ + int show_region; /**< Draw border (private option) */ + AVRational framerate; /**< Capture framerate (private option) */ + int width; /**< Width of the grab frame (private option) */ + int height; /**< Height of the grab frame (private option) */ + int offset_x; /**< Capture x offset (private option) */ + int offset_y; /**< Capture y offset (private option) */ + + HWND hwnd; /**< Handle of the window for the grab */ + HDC source_hdc; /**< Source device context */ + HDC dest_hdc; /**< Destination, source-compatible DC */ + BITMAPINFO bmi; /**< Information describing DIB format */ + HBITMAP hbmp; /**< Information on the bitmap captured */ + void *buffer; /**< The buffer containing the bitmap image data */ + RECT clip_rect; /**< The subarea of the screen or window to clip */ + + HWND region_hwnd; /**< Handle of the region border window */ + + int cursor_error_printed; +}; + +#define WIN32_API_ERROR(str) \ + av_log(s1, AV_LOG_ERROR, str " (error %li)\n", GetLastError()) + +#define REGION_WND_BORDER 3 + +/** + * Callback to handle Windows messages for the region outline window. + * + * In particular, this handles painting the frame rectangle. + * + * @param hwnd The region outline window handle. + * @param msg The Windows message. + * @param wparam First Windows message parameter. + * @param lparam Second Windows message parameter. + * @return 0 success, !0 failure + */ +static LRESULT CALLBACK +gdigrab_region_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + PAINTSTRUCT ps; + HDC hdc; + RECT rect; + + switch (msg) { + case WM_PAINT: + hdc = BeginPaint(hwnd, &ps); + + GetClientRect(hwnd, &rect); + FrameRect(hdc, &rect, GetStockObject(BLACK_BRUSH)); + + rect.left++; rect.top++; rect.right--; rect.bottom--; + FrameRect(hdc, &rect, GetStockObject(WHITE_BRUSH)); + + rect.left++; rect.top++; rect.right--; rect.bottom--; + FrameRect(hdc, &rect, GetStockObject(BLACK_BRUSH)); + + EndPaint(hwnd, &ps); + break; + default: + return DefWindowProc(hwnd, msg, wparam, lparam); + } + return 0; +} + +/** + * Initialize the region outline window. + * + * @param s1 The format context. + * @param gdigrab gdigrab context. + * @return 0 success, !0 failure + */ +static int +gdigrab_region_wnd_init(AVFormatContext *s1, struct gdigrab *gdigrab) +{ + HWND hwnd; + RECT rect = gdigrab->clip_rect; + HRGN region = NULL; + HRGN region_interior = NULL; + + DWORD style = WS_POPUP | WS_VISIBLE; + DWORD ex = WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_TRANSPARENT; + + rect.left -= REGION_WND_BORDER; rect.top -= REGION_WND_BORDER; + rect.right += REGION_WND_BORDER; rect.bottom += REGION_WND_BORDER; + + AdjustWindowRectEx(&rect, style, FALSE, ex); + + // Create a window with no owner; use WC_DIALOG instead of writing a custom + // window class + hwnd = CreateWindowEx(ex, WC_DIALOG, NULL, style, rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, + NULL, NULL, NULL, NULL); + if (!hwnd) { + WIN32_API_ERROR("Could not create region display window"); + goto error; + } + + // Set the window shape to only include the border area + GetClientRect(hwnd, &rect); + region = CreateRectRgn(0, 0, + rect.right - rect.left, rect.bottom - rect.top); + region_interior = CreateRectRgn(REGION_WND_BORDER, REGION_WND_BORDER, + rect.right - rect.left - REGION_WND_BORDER, + rect.bottom - rect.top - REGION_WND_BORDER); + CombineRgn(region, region, region_interior, RGN_DIFF); + if (!SetWindowRgn(hwnd, region, FALSE)) { + WIN32_API_ERROR("Could not set window region"); + goto error; + } + // The "region" memory is now owned by the window + region = NULL; + DeleteObject(region_interior); + + SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) gdigrab_region_wnd_proc); + + ShowWindow(hwnd, SW_SHOW); + + gdigrab->region_hwnd = hwnd; + + return 0; + +error: + if (region) + DeleteObject(region); + if (region_interior) + DeleteObject(region_interior); + if (hwnd) + DestroyWindow(hwnd); + return 1; +} + +/** + * Cleanup/free the region outline window. + * + * @param s1 The format context. + * @param gdigrab gdigrab context. + */ +static void +gdigrab_region_wnd_destroy(AVFormatContext *s1, struct gdigrab *gdigrab) +{ + if (gdigrab->region_hwnd) + DestroyWindow(gdigrab->region_hwnd); + gdigrab->region_hwnd = NULL; +} + +/** + * Process the Windows message queue. + * + * This is important to prevent Windows from thinking the window has become + * unresponsive. As well, things like WM_PAINT (to actually draw the window + * contents) are handled from the message queue context. + * + * @param s1 The format context. + * @param gdigrab gdigrab context. + */ +static void +gdigrab_region_wnd_update(AVFormatContext *s1, struct gdigrab *gdigrab) +{ + HWND hwnd = gdigrab->region_hwnd; + MSG msg; + + while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)) { + DispatchMessage(&msg); + } +} + +/** + * Initializes the gdi grab device demuxer (public device demuxer API). + * + * @param s1 Context from avformat core + * @return AVERROR_IO error, 0 success + */ +static int +gdigrab_read_header(AVFormatContext *s1) +{ + struct gdigrab *gdigrab = s1->priv_data; + + HWND hwnd; + HDC source_hdc = NULL; + HDC dest_hdc = NULL; + BITMAPINFO bmi; + HBITMAP hbmp = NULL; + void *buffer = NULL; + + const char *filename = s1->filename; + const char *name = NULL; + AVStream *st = NULL; + + int bpp; + RECT virtual_rect; + RECT clip_rect; + BITMAP bmp; + int ret; + + if (!strncmp(filename, "title=", 6)) { + name = filename + 6; + hwnd = FindWindow(NULL, name); + if (!hwnd) { + av_log(s1, AV_LOG_ERROR, + "Can't find window '%s', aborting.\n", name); + ret = AVERROR(EIO); + goto error; + } + if (gdigrab->show_region) { + av_log(s1, AV_LOG_WARNING, + "Can't show region when grabbing a window.\n"); + gdigrab->show_region = 0; + } + } else if (!strcmp(filename, "desktop")) { + hwnd = NULL; + } else { + av_log(s1, AV_LOG_ERROR, + "Please use \"desktop\" or \"title=\" to specify your target.\n"); + ret = AVERROR(EIO); + goto error; + } + + if (hwnd) { + GetClientRect(hwnd, &virtual_rect); + } else { + virtual_rect.left = GetSystemMetrics(SM_XVIRTUALSCREEN); + virtual_rect.top = GetSystemMetrics(SM_YVIRTUALSCREEN); + virtual_rect.right = virtual_rect.left + GetSystemMetrics(SM_CXVIRTUALSCREEN); + virtual_rect.bottom = virtual_rect.top + GetSystemMetrics(SM_CYVIRTUALSCREEN); + } + + /* If no width or height set, use full screen/window area */ + if (!gdigrab->width || !gdigrab->height) { + clip_rect.left = virtual_rect.left; + clip_rect.top = virtual_rect.top; + clip_rect.right = virtual_rect.right; + clip_rect.bottom = virtual_rect.bottom; + } else { + clip_rect.left = gdigrab->offset_x; + clip_rect.top = gdigrab->offset_y; + clip_rect.right = gdigrab->width + gdigrab->offset_x; + clip_rect.bottom = gdigrab->height + gdigrab->offset_y; + } + + if (clip_rect.left < virtual_rect.left || + clip_rect.top < virtual_rect.top || + clip_rect.right > virtual_rect.right || + clip_rect.bottom > virtual_rect.bottom) { + av_log(s1, AV_LOG_ERROR, + "Capture area (%li,%li),(%li,%li) extends outside window area (%li,%li),(%li,%li)", + clip_rect.left, clip_rect.top, + clip_rect.right, clip_rect.bottom, + virtual_rect.left, virtual_rect.top, + virtual_rect.right, virtual_rect.bottom); + ret = AVERROR(EIO); + goto error; + } + + /* This will get the device context for the selected window, or if + * none, the primary screen */ + source_hdc = GetDC(hwnd); + if (!source_hdc) { + WIN32_API_ERROR("Couldn't get window device context"); + ret = AVERROR(EIO); + goto error; + } + bpp = GetDeviceCaps(source_hdc, BITSPIXEL); + + if (name) { + av_log(s1, AV_LOG_INFO, + "Found window %s, capturing %lix%lix%i at (%li,%li)\n", + name, + clip_rect.right - clip_rect.left, + clip_rect.bottom - clip_rect.top, + bpp, clip_rect.left, clip_rect.top); + } else { + av_log(s1, AV_LOG_INFO, + "Capturing whole desktop as %lix%lix%i at (%li,%li)\n", + clip_rect.right - clip_rect.left, + clip_rect.bottom - clip_rect.top, + bpp, clip_rect.left, clip_rect.top); + } + + if (clip_rect.right - clip_rect.left <= 0 || + clip_rect.bottom - clip_rect.top <= 0 || bpp%8) { + av_log(s1, AV_LOG_ERROR, "Invalid properties, aborting\n"); + ret = AVERROR(EIO); + goto error; + } + + dest_hdc = CreateCompatibleDC(source_hdc); + if (!dest_hdc) { + WIN32_API_ERROR("Screen DC CreateCompatibleDC"); + ret = AVERROR(EIO); + goto error; + } + + /* Create a DIB and select it into the dest_hdc */ + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = clip_rect.right - clip_rect.left; + bmi.bmiHeader.biHeight = -(clip_rect.bottom - clip_rect.top); + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = bpp; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = 0; + bmi.bmiHeader.biYPelsPerMeter = 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + hbmp = CreateDIBSection(dest_hdc, &bmi, DIB_RGB_COLORS, + &buffer, NULL, 0); + if (!hbmp) { + WIN32_API_ERROR("Creating DIB Section"); + ret = AVERROR(EIO); + goto error; + } + + if (!SelectObject(dest_hdc, hbmp)) { + WIN32_API_ERROR("SelectObject"); + ret = AVERROR(EIO); + goto error; + } + + /* Get info from the bitmap */ + GetObject(hbmp, sizeof(BITMAP), &bmp); + + st = avformat_new_stream(s1, NULL); + if (!st) { + ret = AVERROR(ENOMEM); + goto error; + } + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ + + gdigrab->frame_size = bmp.bmWidthBytes * bmp.bmHeight * bmp.bmPlanes; + gdigrab->header_size = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + + (bpp <= 8 ? (1 << bpp) : 0) * sizeof(RGBQUAD) /* palette size */; + gdigrab->time_base = av_inv_q(gdigrab->framerate); + gdigrab->time_frame = av_gettime() / av_q2d(gdigrab->time_base); + + gdigrab->hwnd = hwnd; + gdigrab->source_hdc = source_hdc; + gdigrab->dest_hdc = dest_hdc; + gdigrab->hbmp = hbmp; + gdigrab->bmi = bmi; + gdigrab->buffer = buffer; + gdigrab->clip_rect = clip_rect; + + gdigrab->cursor_error_printed = 0; + + if (gdigrab->show_region) { + if (gdigrab_region_wnd_init(s1, gdigrab)) { + ret = AVERROR(EIO); + goto error; + } + } + + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = AV_CODEC_ID_BMP; + st->codec->time_base = gdigrab->time_base; + st->codec->bit_rate = (gdigrab->header_size + gdigrab->frame_size) * 1/av_q2d(gdigrab->time_base) * 8; + + return 0; + +error: + if (source_hdc) + ReleaseDC(hwnd, source_hdc); + if (dest_hdc) + DeleteDC(dest_hdc); + if (hbmp) + DeleteObject(hbmp); + if (source_hdc) + DeleteDC(source_hdc); + return ret; +} + +/** + * Paints a mouse pointer in a Win32 image. + * + * @param s1 Context of the log information + * @param s Current grad structure + */ +static void paint_mouse_pointer(AVFormatContext *s1, struct gdigrab *gdigrab) +{ + CURSORINFO ci = {0}; + +#define CURSOR_ERROR(str) \ + if (!gdigrab->cursor_error_printed) { \ + WIN32_API_ERROR(str); \ + gdigrab->cursor_error_printed = 1; \ + } + + ci.cbSize = sizeof(ci); + + if (GetCursorInfo(&ci)) { + HCURSOR icon = CopyCursor(ci.hCursor); + ICONINFO info; + POINT pos; + RECT clip_rect = gdigrab->clip_rect; + HWND hwnd = gdigrab->hwnd; + + if (ci.flags != CURSOR_SHOWING) + return; + + if (!icon) { + /* Use the standard arrow cursor as a fallback. + * You'll probably only hit this in Wine, which can't fetch + * the current system cursor. */ + icon = CopyCursor(LoadCursor(NULL, IDC_ARROW)); + } + + if (!GetIconInfo(icon, &info)) { + CURSOR_ERROR("Could not get icon info"); + goto icon_error; + } + + pos.x = ci.ptScreenPos.x - clip_rect.left - info.xHotspot; + pos.y = ci.ptScreenPos.y - clip_rect.top - info.yHotspot; + + if (hwnd) { + RECT rect; + + if (GetWindowRect(hwnd, &rect)) { + pos.x -= rect.left; + pos.y -= rect.top; + } else { + CURSOR_ERROR("Couldn't get window rectangle"); + goto icon_error; + } + } + + av_log(s1, AV_LOG_DEBUG, "Cursor pos (%li,%li) -> (%li,%li)\n", + ci.ptScreenPos.x, ci.ptScreenPos.y, pos.x, pos.y); + + if (pos.x >= 0 && pos.x <= clip_rect.right - clip_rect.left && + pos.y >= 0 && pos.y <= clip_rect.bottom - clip_rect.top) { + if (!DrawIcon(gdigrab->dest_hdc, pos.x, pos.y, icon)) + CURSOR_ERROR("Couldn't draw icon"); + } + +icon_error: + if (icon) + DestroyCursor(icon); + } else { + CURSOR_ERROR("Couldn't get cursor info"); + } +} + +/** + * Grabs a frame from gdi (public device demuxer API). + * + * @param s1 Context from avformat core + * @param pkt Packet holding the grabbed frame + * @return frame size in bytes + */ +static int gdigrab_read_packet(AVFormatContext *s1, AVPacket *pkt) +{ + struct gdigrab *gdigrab = s1->priv_data; + + HDC dest_hdc = gdigrab->dest_hdc; + HDC source_hdc = gdigrab->source_hdc; + RECT clip_rect = gdigrab->clip_rect; + AVRational time_base = gdigrab->time_base; + int64_t time_frame = gdigrab->time_frame; + + BITMAPFILEHEADER bfh; + int file_size = gdigrab->header_size + gdigrab->frame_size; + + int64_t curtime, delay; + + /* Calculate the time of the next frame */ + time_frame += INT64_C(1000000); + + /* Run Window message processing queue */ + if (gdigrab->show_region) + gdigrab_region_wnd_update(s1, gdigrab); + + /* wait based on the frame rate */ + for (;;) { + curtime = av_gettime(); + delay = time_frame * av_q2d(time_base) - curtime; + if (delay <= 0) { + if (delay < INT64_C(-1000000) * av_q2d(time_base)) { + time_frame += INT64_C(1000000); + } + break; + } + if (s1->flags & AVFMT_FLAG_NONBLOCK) { + return AVERROR(EAGAIN); + } else { + av_usleep(delay); + } + } + + if (av_new_packet(pkt, file_size) < 0) + return AVERROR(ENOMEM); + pkt->pts = curtime; + + /* Blit screen grab */ + if (!BitBlt(dest_hdc, 0, 0, + clip_rect.right - clip_rect.left, + clip_rect.bottom - clip_rect.top, + source_hdc, + clip_rect.left, clip_rect.top, SRCCOPY | CAPTUREBLT)) { + WIN32_API_ERROR("Failed to capture image"); + return AVERROR(EIO); + } + if (gdigrab->draw_mouse) + paint_mouse_pointer(s1, gdigrab); + + /* Copy bits to packet data */ + + bfh.bfType = 0x4d42; /* "BM" in little-endian */ + bfh.bfSize = file_size; + bfh.bfReserved1 = 0; + bfh.bfReserved2 = 0; + bfh.bfOffBits = gdigrab->header_size; + + memcpy(pkt->data, &bfh, sizeof(bfh)); + + memcpy(pkt->data + sizeof(bfh), &gdigrab->bmi.bmiHeader, sizeof(gdigrab->bmi.bmiHeader)); + + if (gdigrab->bmi.bmiHeader.biBitCount <= 8) + GetDIBColorTable(dest_hdc, 0, 1 << gdigrab->bmi.bmiHeader.biBitCount, + (RGBQUAD *) (pkt->data + sizeof(bfh) + sizeof(gdigrab->bmi.bmiHeader))); + + memcpy(pkt->data + gdigrab->header_size, gdigrab->buffer, gdigrab->frame_size); + + gdigrab->time_frame = time_frame; + + return gdigrab->header_size + gdigrab->frame_size; +} + +/** + * Closes gdi frame grabber (public device demuxer API). + * + * @param s1 Context from avformat core + * @return 0 success, !0 failure + */ +static int gdigrab_read_close(AVFormatContext *s1) +{ + struct gdigrab *s = s1->priv_data; + + if (s->show_region) + gdigrab_region_wnd_destroy(s1, s); + + if (s->source_hdc) + ReleaseDC(s->hwnd, s->source_hdc); + if (s->dest_hdc) + DeleteDC(s->dest_hdc); + if (s->hbmp) + DeleteObject(s->hbmp); + if (s->source_hdc) + DeleteDC(s->source_hdc); + + return 0; +} + +#define OFFSET(x) offsetof(struct gdigrab, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "draw_mouse", "draw the mouse pointer", OFFSET(draw_mouse), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, DEC }, + { "show_region", "draw border around capture area", OFFSET(show_region), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC }, + { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, 0, DEC }, + { "video_size", "set video frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, + { "offset_x", "capture area x offset", OFFSET(offset_x), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, + { "offset_y", "capture area y offset", OFFSET(offset_y), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, + { NULL }, +}; + +static const AVClass gdigrab_class = { + .class_name = "GDIgrab indev", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +/** gdi grabber device demuxer declaration */ +AVInputFormat ff_gdigrab_demuxer = { + .name = "gdigrab", + .long_name = NULL_IF_CONFIG_SMALL("GDI API Windows frame grabber"), + .priv_data_size = sizeof(struct gdigrab), + .read_header = gdigrab_read_header, + .read_packet = gdigrab_read_packet, + .read_close = gdigrab_read_close, + .flags = AVFMT_NOFILE, + .priv_class = &gdigrab_class, +}; diff --git a/libavdevice/iec61883.c b/libavdevice/iec61883.c index 443ca3cd3..401c3dd56 100644 --- a/libavdevice/iec61883.c +++ b/libavdevice/iec61883.c @@ -483,6 +483,7 @@ static const AVClass iec61883_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, }; AVInputFormat ff_iec61883_demuxer = { diff --git a/libavdevice/jack_audio.c b/libavdevice/jack_audio.c index 5ba673168..70aa6ffcc 100644 --- a/libavdevice/jack_audio.c +++ b/libavdevice/jack_audio.c @@ -163,7 +163,7 @@ static int start_jack(AVFormatContext *context) sem_init(&self->packet_count, 0, 0); self->sample_rate = jack_get_sample_rate(self->client); - self->ports = av_malloc(self->nports * sizeof(*self->ports)); + self->ports = av_malloc_array(self->nports, sizeof(*self->ports)); self->buffer_size = jack_get_buffer_size(self->client); /* Register JACK ports */ @@ -194,9 +194,9 @@ static int start_jack(AVFormatContext *context) } /* Create FIFO buffers */ - self->filled_pkts = av_fifo_alloc(FIFO_PACKETS_NUM * sizeof(AVPacket)); + self->filled_pkts = av_fifo_alloc_array(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)); + self->new_pkts = av_fifo_alloc_array((FIFO_PACKETS_NUM + 1), sizeof(AVPacket)); if ((test = supply_new_packets(self, context))) { jack_client_close(self->client); return test; @@ -206,14 +206,14 @@ static int start_jack(AVFormatContext *context) } -static void free_pkt_fifo(AVFifoBuffer *fifo) +static void free_pkt_fifo(AVFifoBuffer **fifo) { AVPacket pkt; - while (av_fifo_size(fifo)) { - av_fifo_generic_read(fifo, &pkt, sizeof(pkt), NULL); + while (av_fifo_size(*fifo)) { + av_fifo_generic_read(*fifo, &pkt, sizeof(pkt), NULL); av_free_packet(&pkt); } - av_fifo_free(fifo); + av_fifo_freep(fifo); } static void stop_jack(JackData *self) @@ -224,8 +224,8 @@ static void stop_jack(JackData *self) jack_client_close(self->client); } sem_destroy(&self->packet_count); - free_pkt_fifo(self->new_pkts); - free_pkt_fifo(self->filled_pkts); + free_pkt_fifo(&self->new_pkts); + free_pkt_fifo(&self->filled_pkts); av_freep(&self->ports); ff_timefilter_destroy(self->timefilter); } @@ -333,6 +333,7 @@ static const AVClass jack_indev_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, }; AVInputFormat ff_jack_demuxer = { diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index a177ad027..d1904dd70 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -211,7 +211,7 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) } /* create a sink for each output and connect them to the graph */ - lavfi->sinks = av_malloc(sizeof(AVFilterContext *) * avctx->nb_streams); + lavfi->sinks = av_malloc_array(avctx->nb_streams, sizeof(AVFilterContext *)); if (!lavfi->sinks) FAIL(AVERROR(ENOMEM)); @@ -425,6 +425,7 @@ static const AVClass lavfi_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_INPUT, }; AVInputFormat ff_lavfi_demuxer = { diff --git a/libavdevice/libcdio.c b/libavdevice/libcdio.c index 91052cc40..16a4b2695 100644 --- a/libavdevice/libcdio.c +++ b/libavdevice/libcdio.c @@ -177,6 +177,7 @@ static const AVClass libcdio_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, }; AVInputFormat ff_libcdio_demuxer = { diff --git a/libavdevice/libdc1394.c b/libavdevice/libdc1394.c index 80cb1bee1..e9bd4c98f 100644 --- a/libavdevice/libdc1394.c +++ b/libavdevice/libdc1394.c @@ -112,6 +112,7 @@ static const AVClass libdc1394_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, }; diff --git a/libavdevice/openal-dec.c b/libavdevice/openal-dec.c index 93633ff7d..4c4ba28c2 100644 --- a/libavdevice/openal-dec.c +++ b/libavdevice/openal-dec.c @@ -236,7 +236,8 @@ static const AVClass class = { .class_name = "openal", .item_name = av_default_item_name, .option = options, - .version = LIBAVUTIL_VERSION_INT + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, }; AVInputFormat ff_openal_demuxer = { diff --git a/libavdevice/opengl_enc.c b/libavdevice/opengl_enc.c index 5ca0c02d0..b5f97e242 100644 --- a/libavdevice/opengl_enc.c +++ b/libavdevice/opengl_enc.c @@ -30,6 +30,9 @@ #include "config.h" +#if HAVE_WINDOWS_H +#include +#endif #if HAVE_OPENGL_GL3_H #include #elif HAVE_ES2_GL_H @@ -41,9 +44,6 @@ #if HAVE_GLXGETPROCADDRESS #include #endif -#if HAVE_WINDOWS_H -#include -#endif #if HAVE_SDL #include @@ -66,7 +66,7 @@ /* FF_GL_RED_COMPONENT is used for plannar pixel types. * Only red component is sampled in shaders. - * On some platforms GL_RED is not availabe and GL_LUMINANCE have to be used, + * On some platforms GL_RED is not available and GL_LUMINANCE have to be used, * but since OpenGL 3.0 GL_LUMINANCE is deprecated. * GL_RED produces RGBA = value, 0, 0, 1. * GL_LUMINANCE produces RGBA = value, value, value, 1. @@ -178,6 +178,7 @@ typedef struct OpenGLContext { #endif FFOpenGLFunctions glprocs; + int inited; ///< Set to 1 when write_header was successfully called. uint8_t background[4]; ///< Background color int no_window; ///< 0 for create default window char *window_title; ///< Title of the window @@ -309,8 +310,7 @@ static int opengl_resize(AVFormatContext *h, int width, int height) OpenGLContext *opengl = h->priv_data; opengl->window_width = width; opengl->window_height = height; - /* max_viewport_width == 0 means write_header was not called yet. */ - if (opengl->max_viewport_width) { + if (opengl->inited) { if (opengl->no_window && (ret = avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_PREPARE_WINDOW_BUFFER, NULL , 0)) < 0) { av_log(opengl, AV_LOG_ERROR, "Application failed to prepare window buffer.\n"); @@ -407,7 +407,8 @@ static int av_cold opengl_sdl_create_window(AVFormatContext *h) av_log(opengl, AV_LOG_ERROR, "Unable to initialize SDL: %s\n", SDL_GetError()); return AVERROR_EXTERNAL; } - if ((ret = opengl_sdl_recreate_window(opengl, opengl->width, opengl->height)) < 0) + if ((ret = opengl_sdl_recreate_window(opengl, opengl->window_width, + opengl->window_height)) < 0) return ret; av_log(opengl, AV_LOG_INFO, "SDL driver: '%s'.\n", SDL_VideoDriverName(buffer, sizeof(buffer))); message.width = opengl->surface->w; @@ -582,7 +583,7 @@ static void opengl_make_ortho(float matrix[16], float left, float right, static av_cold int opengl_read_limits(OpenGLContext *opengl) { static const struct{ - const char *extention; + const char *extension; int major; int minor; } required_extensions[] = { @@ -602,12 +603,12 @@ static av_cold int opengl_read_limits(OpenGLContext *opengl) av_log(opengl, AV_LOG_DEBUG, "OpenGL version: %s\n", version); sscanf(version, "%d.%d", &major, &minor); - for (i = 0; required_extensions[i].extention; i++) { + for (i = 0; required_extensions[i].extension; i++) { if (major < required_extensions[i].major && (major == required_extensions[i].major && minor < required_extensions[i].minor) && - !strstr(extensions, required_extensions[i].extention)) { + !strstr(extensions, required_extensions[i].extension)) { av_log(opengl, AV_LOG_ERROR, "Required extension %s is not supported.\n", - required_extensions[i].extention); + required_extensions[i].extension); av_log(opengl, AV_LOG_DEBUG, "Supported extensions are: %s\n", extensions); return AVERROR(ENOSYS); } @@ -871,8 +872,8 @@ static av_cold int opengl_prepare_vertex(AVFormatContext *s) int tex_w, tex_h; if (opengl->window_width > opengl->max_viewport_width || opengl->window_height > opengl->max_viewport_height) { - opengl->window_width = FFMAX(opengl->window_width, opengl->max_viewport_width); - opengl->window_height = FFMAX(opengl->window_height, opengl->max_viewport_height); + opengl->window_width = FFMIN(opengl->window_width, opengl->max_viewport_width); + opengl->window_height = FFMIN(opengl->window_height, opengl->max_viewport_height); av_log(opengl, AV_LOG_WARNING, "Too big viewport requested, limited to %dx%d", opengl->window_width, opengl->window_height); } glViewport(0, 0, opengl->window_width, opengl->window_height); @@ -951,7 +952,12 @@ static int opengl_create_window(AVFormatContext *h) return AVERROR(ENOSYS); #endif } else { - if ((ret = avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_CREATE_WINDOW_BUFFER, NULL , 0)) < 0) { + AVDeviceRect message; + message.x = message.y = 0; + message.width = opengl->window_width; + message.height = opengl->window_height; + if ((ret = avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_CREATE_WINDOW_BUFFER, + &message , sizeof(message))) < 0) { av_log(opengl, AV_LOG_ERROR, "Application failed to create window buffer.\n"); return ret; } @@ -1067,6 +1073,10 @@ static av_cold int opengl_write_header(AVFormatContext *h) opengl->width = st->codec->width; opengl->height = st->codec->height; opengl->pix_fmt = st->codec->pix_fmt; + if (!opengl->window_width) + opengl->window_width = opengl->width; + if (!opengl->window_height) + opengl->window_height = opengl->height; if (!opengl->window_title && !opengl->no_window) opengl->window_title = av_strdup(h->filename); @@ -1110,6 +1120,8 @@ static av_cold int opengl_write_header(AVFormatContext *h) ret = AVERROR_EXTERNAL; OPENGL_ERROR_CHECK(opengl); + + opengl->inited = 1; return 0; fail: @@ -1266,6 +1278,7 @@ static const AVOption options[] = { { "background", "set background color", OFFSET(background), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, ENC }, { "no_window", "disable default window", OFFSET(no_window), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, ENC }, { "window_title", "set window title", OFFSET(window_title), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, ENC }, + { "window_size", "set window size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, ENC }, { NULL } }; @@ -1274,6 +1287,7 @@ static const AVClass opengl_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; AVOutputFormat ff_opengl_muxer = { diff --git a/libavdevice/oss_audio.c b/libavdevice/oss_audio.c index 916908c42..734e565cc 100644 --- a/libavdevice/oss_audio.c +++ b/libavdevice/oss_audio.c @@ -30,7 +30,9 @@ #else #include #endif +#if HAVE_UNISTD_H #include +#endif #include #include @@ -296,6 +298,7 @@ static const AVClass oss_demuxer_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, }; AVInputFormat ff_oss_demuxer = { @@ -311,6 +314,13 @@ AVInputFormat ff_oss_demuxer = { #endif #if CONFIG_OSS_OUTDEV +static const AVClass oss_muxer_class = { + .class_name = "OSS muxer", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, +}; + AVOutputFormat ff_oss_muxer = { .name = "oss", .long_name = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) playback"), @@ -324,5 +334,6 @@ AVOutputFormat ff_oss_muxer = { .write_packet = audio_write_packet, .write_trailer = audio_write_trailer, .flags = AVFMT_NOFILE, + .priv_class = &oss_muxer_class, }; #endif diff --git a/libavdevice/pulse_audio_common.c b/libavdevice/pulse_audio_common.c index f7227f654..5a2568b82 100644 --- a/libavdevice/pulse_audio_common.c +++ b/libavdevice/pulse_audio_common.c @@ -1,5 +1,6 @@ /* - * Pulseaudio input + * Pulseaudio common + * Copyright (c) 2014 Lukasz Marek * Copyright (c) 2011 Luca Barbato * * This file is part of FFmpeg. @@ -21,6 +22,9 @@ #include "pulse_audio_common.h" #include "libavutil/attributes.h" +#include "libavutil/avstring.h" +#include "libavutil/mem.h" +#include "libavutil/avassert.h" pa_sample_format_t av_cold ff_codec_id_to_pulse_format(enum AVCodecID codec_id) { @@ -39,3 +43,207 @@ pa_sample_format_t av_cold ff_codec_id_to_pulse_format(enum AVCodecID codec_id) default: return PA_SAMPLE_INVALID; } } + +enum PulseAudioContextState { + PULSE_CONTEXT_INITIALIZING, + PULSE_CONTEXT_READY, + PULSE_CONTEXT_FINISHED +}; + +typedef struct PulseAudioDeviceList { + AVDeviceInfoList *devices; + int error_code; + int output; + char *default_device; +} PulseAudioDeviceList; + +static void pa_state_cb(pa_context *c, void *userdata) +{ + enum PulseAudioContextState *context_state = userdata; + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_FAILED: + case PA_CONTEXT_TERMINATED: + *context_state = PULSE_CONTEXT_FINISHED; + break; + case PA_CONTEXT_READY: + *context_state = PULSE_CONTEXT_READY; + break; + default: + break; + } +} + +void ff_pulse_audio_disconnect_context(pa_mainloop **pa_ml, pa_context **pa_ctx) +{ + av_assert0(pa_ml); + av_assert0(pa_ctx); + + if (*pa_ctx) { + pa_context_set_state_callback(*pa_ctx, NULL, NULL); + pa_context_disconnect(*pa_ctx); + pa_context_unref(*pa_ctx); + } + if (*pa_ml) + pa_mainloop_free(*pa_ml); + *pa_ml = NULL; + *pa_ctx = NULL; +} + +int ff_pulse_audio_connect_context(pa_mainloop **pa_ml, pa_context **pa_ctx, + const char *server, const char *description) +{ + int ret; + pa_mainloop_api *pa_mlapi = NULL; + enum PulseAudioContextState context_state = PULSE_CONTEXT_INITIALIZING; + + av_assert0(pa_ml); + av_assert0(pa_ctx); + + *pa_ml = NULL; + *pa_ctx = NULL; + + if (!(*pa_ml = pa_mainloop_new())) + return AVERROR(ENOMEM); + if (!(pa_mlapi = pa_mainloop_get_api(*pa_ml))) { + ret = AVERROR_EXTERNAL; + goto fail; + } + if (!(*pa_ctx = pa_context_new(pa_mlapi, description))) { + ret = AVERROR(ENOMEM); + goto fail; + } + pa_context_set_state_callback(*pa_ctx, pa_state_cb, &context_state); + if (pa_context_connect(*pa_ctx, server, 0, NULL) < 0) { + ret = AVERROR_EXTERNAL; + goto fail; + } + + while (context_state == PULSE_CONTEXT_INITIALIZING) + pa_mainloop_iterate(*pa_ml, 1, NULL); + if (context_state == PULSE_CONTEXT_FINISHED) { + ret = AVERROR_EXTERNAL; + goto fail; + } + return 0; + + fail: + ff_pulse_audio_disconnect_context(pa_ml, pa_ctx); + return ret; +} + +static void pulse_add_detected_device(PulseAudioDeviceList *info, + const char *name, const char *description) +{ + int ret; + AVDeviceInfo *new_device = NULL; + + if (info->error_code) + return; + + new_device = av_mallocz(sizeof(AVDeviceInfo)); + if (!new_device) { + info->error_code = AVERROR(ENOMEM); + return; + } + + new_device->device_description = av_strdup(description); + new_device->device_name = av_strdup(name); + + if (!new_device->device_description || !new_device->device_name) { + info->error_code = AVERROR(ENOMEM); + goto fail; + } + + if ((ret = av_dynarray_add_nofree(&info->devices->devices, + &info->devices->nb_devices, new_device)) < 0) { + info->error_code = ret; + goto fail; + } + return; + + fail: + av_free(new_device->device_description); + av_free(new_device->device_name); + av_free(new_device); + +} + +static void pulse_audio_source_device_cb(pa_context *c, const pa_source_info *dev, + int eol, void *userdata) +{ + if (!eol) + pulse_add_detected_device(userdata, dev->name, dev->description); +} + +static void pulse_audio_sink_device_cb(pa_context *c, const pa_sink_info *dev, + int eol, void *userdata) +{ + if (!eol) + pulse_add_detected_device(userdata, dev->name, dev->description); +} + +static void pulse_server_info_cb(pa_context *c, const pa_server_info *i, void *userdata) +{ + PulseAudioDeviceList *info = userdata; + if (info->output) + info->default_device = av_strdup(i->default_sink_name); + else + info->default_device = av_strdup(i->default_source_name); + if (!info->default_device) + info->error_code = AVERROR(ENOMEM); +} + +int ff_pulse_audio_get_devices(AVDeviceInfoList *devices, const char *server, int output) +{ + pa_mainloop *pa_ml = NULL; + pa_operation *pa_op = NULL; + pa_context *pa_ctx = NULL; + enum pa_operation_state op_state; + PulseAudioDeviceList dev_list = { 0 }; + int i; + + dev_list.output = output; + dev_list.devices = devices; + if (!devices) + return AVERROR(EINVAL); + devices->nb_devices = 0; + devices->devices = NULL; + + if ((dev_list.error_code = ff_pulse_audio_connect_context(&pa_ml, &pa_ctx, server, "Query devices")) < 0) + goto fail; + + if (output) + pa_op = pa_context_get_sink_info_list(pa_ctx, pulse_audio_sink_device_cb, &dev_list); + else + pa_op = pa_context_get_source_info_list(pa_ctx, pulse_audio_source_device_cb, &dev_list); + while ((op_state = pa_operation_get_state(pa_op)) == PA_OPERATION_RUNNING) + pa_mainloop_iterate(pa_ml, 1, NULL); + if (op_state != PA_OPERATION_DONE) + dev_list.error_code = AVERROR_EXTERNAL; + pa_operation_unref(pa_op); + if (dev_list.error_code < 0) + goto fail; + + pa_op = pa_context_get_server_info(pa_ctx, pulse_server_info_cb, &dev_list); + while ((op_state = pa_operation_get_state(pa_op)) == PA_OPERATION_RUNNING) + pa_mainloop_iterate(pa_ml, 1, NULL); + if (op_state != PA_OPERATION_DONE) + dev_list.error_code = AVERROR_EXTERNAL; + pa_operation_unref(pa_op); + if (dev_list.error_code < 0) + goto fail; + + devices->default_device = -1; + for (i = 0; i < devices->nb_devices; i++) { + if (!strcmp(devices->devices[i]->device_name, dev_list.default_device)) { + devices->default_device = i; + break; + } + } + + fail: + av_free(dev_list.default_device); + ff_pulse_audio_disconnect_context(&pa_ml, &pa_ctx); + return dev_list.error_code; +} diff --git a/libavdevice/pulse_audio_common.h b/libavdevice/pulse_audio_common.h index 99ba6a31f..02534f79a 100644 --- a/libavdevice/pulse_audio_common.h +++ b/libavdevice/pulse_audio_common.h @@ -22,9 +22,17 @@ #ifndef AVDEVICE_PULSE_AUDIO_COMMON_H #define AVDEVICE_PULSE_AUDIO_COMMON_H -#include +#include #include "libavcodec/avcodec.h" +#include "avdevice.h" pa_sample_format_t ff_codec_id_to_pulse_format(enum AVCodecID codec_id); +int ff_pulse_audio_get_devices(AVDeviceInfoList *devices, const char *server, int output); + +int ff_pulse_audio_connect_context(pa_mainloop **pa_ml, pa_context **pa_ctx, + const char *server, const char *description); + +void ff_pulse_audio_disconnect_context(pa_mainloop **pa_ml, pa_context **pa_ctx); + #endif /* AVDEVICE_PULSE_AUDIO_COMMON_H */ diff --git a/libavdevice/pulse_audio_dec.c b/libavdevice/pulse_audio_dec.c index 3b5cebb7f..01ff6d171 100644 --- a/libavdevice/pulse_audio_dec.c +++ b/libavdevice/pulse_audio_dec.c @@ -1,6 +1,8 @@ /* * Pulseaudio input * Copyright (c) 2011 Luca Barbato + * Copyright 2004-2006 Lennart Poettering + * Copyright (c) 2014 Michael Niedermayer * * This file is part of FFmpeg. * @@ -19,19 +21,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/** - * @file - * PulseAudio input using the simple API. - * @author Luca Barbato - */ - -#include #include #include #include "libavformat/avformat.h" #include "libavformat/internal.h" #include "libavutil/opt.h" +#include "libavutil/time.h" #include "pulse_audio_common.h" +#include "timefilter.h" #define DEFAULT_CODEC_ID AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE) @@ -44,17 +41,102 @@ typedef struct PulseData { int channels; int frame_size; int fragment_size; - pa_simple *s; - int64_t pts; - int64_t frame_duration; + + pa_threaded_mainloop *mainloop; + pa_context *context; + pa_stream *stream; + + TimeFilter *timefilter; + int last_period; } PulseData; + +#define CHECK_SUCCESS_GOTO(rerror, expression, label) \ + do { \ + if (!(expression)) { \ + rerror = AVERROR_EXTERNAL; \ + goto label; \ + } \ + } while(0); + +#define CHECK_DEAD_GOTO(p, rerror, label) \ + do { \ + if (!(p)->context || !PA_CONTEXT_IS_GOOD(pa_context_get_state((p)->context)) || \ + !(p)->stream || !PA_STREAM_IS_GOOD(pa_stream_get_state((p)->stream))) { \ + rerror = AVERROR_EXTERNAL; \ + goto label; \ + } \ + } while(0); + +static void context_state_cb(pa_context *c, void *userdata) { + PulseData *p = userdata; + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_READY: + case PA_CONTEXT_TERMINATED: + case PA_CONTEXT_FAILED: + pa_threaded_mainloop_signal(p->mainloop, 0); + break; + } +} + +static void stream_state_cb(pa_stream *s, void * userdata) { + PulseData *p = userdata; + + switch (pa_stream_get_state(s)) { + case PA_STREAM_READY: + case PA_STREAM_FAILED: + case PA_STREAM_TERMINATED: + pa_threaded_mainloop_signal(p->mainloop, 0); + break; + } +} + +static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { + PulseData *p = userdata; + + pa_threaded_mainloop_signal(p->mainloop, 0); +} + +static void stream_latency_update_cb(pa_stream *s, void *userdata) { + PulseData *p = userdata; + + pa_threaded_mainloop_signal(p->mainloop, 0); +} + +static av_cold int pulse_close(AVFormatContext *s) +{ + PulseData *pd = s->priv_data; + + if (pd->mainloop) + pa_threaded_mainloop_stop(pd->mainloop); + + if (pd->stream) + pa_stream_unref(pd->stream); + pd->stream = NULL; + + if (pd->context) { + pa_context_disconnect(pd->context); + pa_context_unref(pd->context); + } + pd->context = NULL; + + if (pd->mainloop) + pa_threaded_mainloop_free(pd->mainloop); + pd->mainloop = NULL; + + ff_timefilter_destroy(pd->timefilter); + pd->timefilter = NULL; + + return 0; +} + static av_cold int pulse_read_header(AVFormatContext *s) { PulseData *pd = s->priv_data; AVStream *st; char *device = NULL; - int ret, sample_bytes; + int ret; enum AVCodecID codec_id = s->audio_codec_id == AV_CODEC_ID_NONE ? DEFAULT_CODEC_ID : s->audio_codec_id; const pa_sample_spec ss = { ff_codec_id_to_pulse_format(codec_id), @@ -75,76 +157,182 @@ static av_cold int pulse_read_header(AVFormatContext *s) if (strcmp(s->filename, "default")) device = s->filename; - pd->s = pa_simple_new(pd->server, pd->name, - PA_STREAM_RECORD, - device, pd->stream_name, &ss, - NULL, &attr, &ret); - - if (!pd->s) { - av_log(s, AV_LOG_ERROR, "pa_simple_new failed: %s\n", - pa_strerror(ret)); - return AVERROR(EIO); + if (!(pd->mainloop = pa_threaded_mainloop_new())) { + pulse_close(s); + return AVERROR_EXTERNAL; } + + if (!(pd->context = pa_context_new(pa_threaded_mainloop_get_api(pd->mainloop), pd->name))) { + pulse_close(s); + return AVERROR_EXTERNAL; + } + + pa_context_set_state_callback(pd->context, context_state_cb, pd); + + if (pa_context_connect(pd->context, pd->server, 0, NULL) < 0) { + pulse_close(s); + return AVERROR(pa_context_errno(pd->context)); + } + + pa_threaded_mainloop_lock(pd->mainloop); + + if (pa_threaded_mainloop_start(pd->mainloop) < 0) { + ret = -1; + goto unlock_and_fail; + } + + for (;;) { + pa_context_state_t state; + + state = pa_context_get_state(pd->context); + + if (state == PA_CONTEXT_READY) + break; + + if (!PA_CONTEXT_IS_GOOD(state)) { + ret = AVERROR(pa_context_errno(pd->context)); + goto unlock_and_fail; + } + + /* Wait until the context is ready */ + pa_threaded_mainloop_wait(pd->mainloop); + } + + if (!(pd->stream = pa_stream_new(pd->context, pd->stream_name, &ss, NULL))) { + ret = AVERROR(pa_context_errno(pd->context)); + goto unlock_and_fail; + } + + pa_stream_set_state_callback(pd->stream, stream_state_cb, pd); + pa_stream_set_read_callback(pd->stream, stream_request_cb, pd); + pa_stream_set_write_callback(pd->stream, stream_request_cb, pd); + pa_stream_set_latency_update_callback(pd->stream, stream_latency_update_cb, pd); + + ret = pa_stream_connect_record(pd->stream, device, &attr, + PA_STREAM_INTERPOLATE_TIMING + |PA_STREAM_ADJUST_LATENCY + |PA_STREAM_AUTO_TIMING_UPDATE); + + if (ret < 0) { + ret = AVERROR(pa_context_errno(pd->context)); + goto unlock_and_fail; + } + + for (;;) { + pa_stream_state_t state; + + state = pa_stream_get_state(pd->stream); + + if (state == PA_STREAM_READY) + break; + + if (!PA_STREAM_IS_GOOD(state)) { + ret = AVERROR(pa_context_errno(pd->context)); + goto unlock_and_fail; + } + + /* Wait until the stream is ready */ + pa_threaded_mainloop_wait(pd->mainloop); + } + + pa_threaded_mainloop_unlock(pd->mainloop); + /* 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; - avpriv_set_pts_info(st, 64, 1, pd->sample_rate); /* 64 bits pts in us */ + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ - pd->pts = AV_NOPTS_VALUE; - sample_bytes = (av_get_bits_per_sample(codec_id) >> 3) * pd->channels; + pd->timefilter = ff_timefilter_new(1000000.0 / pd->sample_rate, + 1000, 1.5E-6); - if (pd->frame_size % sample_bytes) { - av_log(s, AV_LOG_WARNING, "frame_size %i is not divisible by %i " - "(channels * bytes_per_sample) \n", pd->frame_size, sample_bytes); + if (!pd->timefilter) { + pulse_close(s); + return AVERROR(ENOMEM); } - pd->frame_duration = pd->frame_size / sample_bytes; - return 0; + +unlock_and_fail: + pa_threaded_mainloop_unlock(pd->mainloop); + + pulse_close(s); + return ret; } static int pulse_read_packet(AVFormatContext *s, AVPacket *pkt) { PulseData *pd = s->priv_data; - int res; + int ret; + size_t read_length; + const void *read_data = NULL; + int64_t dts; + pa_usec_t latency; + int negative; - if (av_new_packet(pkt, pd->frame_size) < 0) { - return AVERROR(ENOMEM); - } + pa_threaded_mainloop_lock(pd->mainloop); - 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); - return AVERROR(EIO); - } + CHECK_DEAD_GOTO(pd, ret, unlock_and_fail); - if (pd->pts == AV_NOPTS_VALUE) { - pa_usec_t latency; + while (!read_data) { + int r; - if ((latency = pa_simple_get_latency(pd->s, &res)) == (pa_usec_t) -1) { - av_log(s, AV_LOG_ERROR, "pa_simple_get_latency() failed: %s\n", - pa_strerror(res)); - return AVERROR(EIO); + r = pa_stream_peek(pd->stream, &read_data, &read_length); + CHECK_SUCCESS_GOTO(ret, r == 0, unlock_and_fail); + + if (read_length <= 0) { + pa_threaded_mainloop_wait(pd->mainloop); + CHECK_DEAD_GOTO(pd, ret, unlock_and_fail); + } else if (!read_data) { + /* There's a hole in the stream, skip it. We could generate + * silence, but that wouldn't work for compressed streams. */ + r = pa_stream_drop(pd->stream); + CHECK_SUCCESS_GOTO(ret, r == 0, unlock_and_fail); } - - pd->pts = -latency; } - pkt->pts = pd->pts; + if (av_new_packet(pkt, read_length) < 0) { + ret = AVERROR(ENOMEM); + goto unlock_and_fail; + } - pd->pts += pd->frame_duration; + dts = av_gettime(); + pa_operation_unref(pa_stream_update_timing_info(pd->stream, NULL, NULL)); + if (pa_stream_get_latency(pd->stream, &latency, &negative) >= 0) { + enum AVCodecID codec_id = + s->audio_codec_id == AV_CODEC_ID_NONE ? DEFAULT_CODEC_ID : s->audio_codec_id; + int frame_size = ((av_get_bits_per_sample(codec_id) >> 3) * pd->channels); + int frame_duration = read_length / frame_size; + + + if (negative) { + dts += latency; + } else + dts -= latency; + pkt->pts = ff_timefilter_update(pd->timefilter, dts, pd->last_period); + + pd->last_period = frame_duration; + } else { + av_log(s, AV_LOG_WARNING, "pa_stream_get_latency() failed\n"); + } + + memcpy(pkt->data, read_data, read_length); + pa_stream_drop(pd->stream); + + pa_threaded_mainloop_unlock(pd->mainloop); return 0; + +unlock_and_fail: + pa_threaded_mainloop_unlock(pd->mainloop); + return ret; } -static av_cold int pulse_close(AVFormatContext *s) +static int pulse_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list) { - PulseData *pd = s->priv_data; - pa_simple_free(pd->s); - return 0; + PulseData *s = h->priv_data; + return ff_pulse_audio_get_devices(device_list, s->server, 0); } #define OFFSET(a) offsetof(PulseData, a) @@ -166,6 +354,7 @@ static const AVClass pulse_demuxer_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, }; AVInputFormat ff_pulse_demuxer = { @@ -175,6 +364,7 @@ AVInputFormat ff_pulse_demuxer = { .read_header = pulse_read_header, .read_packet = pulse_read_packet, .read_close = pulse_close, + .get_device_list = pulse_get_device_list, .flags = AVFMT_NOFILE, .priv_class = &pulse_demuxer_class, }; diff --git a/libavdevice/pulse_audio_enc.c b/libavdevice/pulse_audio_enc.c index e04729939..b07d4c0c8 100644 --- a/libavdevice/pulse_audio_enc.c +++ b/libavdevice/pulse_audio_enc.c @@ -18,13 +18,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +#include +#include #include #include "libavformat/avformat.h" #include "libavformat/internal.h" #include "libavutil/opt.h" #include "libavutil/time.h" #include "libavutil/log.h" +#include "libavutil/attributes.h" #include "pulse_audio_common.h" typedef struct PulseData { @@ -33,20 +35,421 @@ typedef struct PulseData { const char *name; const char *stream_name; const char *device; - pa_simple *pa; int64_t timestamp; - int buffer_size; - int buffer_duration; + int buffer_size; /**< Buffer size in bytes */ + int buffer_duration; /**< Buffer size in ms, recalculated to buffer_size */ + int prebuf; + int minreq; + int last_result; + pa_threaded_mainloop *mainloop; + pa_context *ctx; + pa_stream *stream; + int nonblocking; + int mute; + pa_volume_t base_volume; + pa_volume_t last_volume; } PulseData; +static void pulse_audio_sink_device_cb(pa_context *ctx, const pa_sink_info *dev, + int eol, void *userdata) +{ + PulseData *s = userdata; + + if (s->ctx != ctx) + return; + + if (eol) { + pa_threaded_mainloop_signal(s->mainloop, 0); + } else { + if (dev->flags & PA_SINK_FLAT_VOLUME) + s->base_volume = dev->base_volume; + else + s->base_volume = PA_VOLUME_NORM; + av_log(s, AV_LOG_DEBUG, "base volume: %u\n", s->base_volume); + } +} + +/* Mainloop must be locked before calling this function as it uses pa_threaded_mainloop_wait. */ +static int pulse_update_sink_info(AVFormatContext *h) +{ + PulseData *s = h->priv_data; + pa_operation *op; + if (!(op = pa_context_get_sink_info_by_name(s->ctx, s->device, + pulse_audio_sink_device_cb, s))) { + av_log(s, AV_LOG_ERROR, "pa_context_get_sink_info_by_name failed.\n"); + return AVERROR_EXTERNAL; + } + while (pa_operation_get_state(op) == PA_OPERATION_RUNNING) + pa_threaded_mainloop_wait(s->mainloop); + pa_operation_unref(op); + return 0; +} + +static void pulse_audio_sink_input_cb(pa_context *ctx, const pa_sink_input_info *i, + int eol, void *userdata) +{ + AVFormatContext *h = userdata; + PulseData *s = h->priv_data; + + if (s->ctx != ctx) + return; + + if (!eol) { + double val; + pa_volume_t vol = pa_cvolume_avg(&i->volume); + if (s->mute < 0 || (s->mute && !i->mute) || (!s->mute && i->mute)) { + s->mute = i->mute; + avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_MUTE_STATE_CHANGED, &s->mute, sizeof(s->mute)); + } + + vol = pa_sw_volume_divide(vol, s->base_volume); + if (s->last_volume != vol) { + val = (double)vol / PA_VOLUME_NORM; + avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED, &val, sizeof(val)); + s->last_volume = vol; + } + } +} + +/* This function creates new loop so may be called from PA callbacks. + Mainloop must be locked before calling this function as it operates on streams. */ +static int pulse_update_sink_input_info(AVFormatContext *h) +{ + PulseData *s = h->priv_data; + pa_operation *op; + enum pa_operation_state op_state; + pa_mainloop *ml = NULL; + pa_context *ctx = NULL; + int ret = 0; + + if ((ret = ff_pulse_audio_connect_context(&ml, &ctx, s->server, "Update sink input information")) < 0) + return ret; + + if (!(op = pa_context_get_sink_input_info(ctx, pa_stream_get_index(s->stream), + pulse_audio_sink_input_cb, h))) { + ret = AVERROR_EXTERNAL; + goto fail; + } + + while ((op_state = pa_operation_get_state(op)) == PA_OPERATION_RUNNING) + pa_mainloop_iterate(ml, 1, NULL); + pa_operation_unref(op); + if (op_state != PA_OPERATION_DONE) { + ret = AVERROR_EXTERNAL; + goto fail; + } + + fail: + ff_pulse_audio_disconnect_context(&ml, &ctx); + if (ret) + av_log(s, AV_LOG_ERROR, "pa_context_get_sink_input_info failed.\n"); + return ret; +} + +static void pulse_event(pa_context *ctx, pa_subscription_event_type_t t, + uint32_t idx, void *userdata) +{ + AVFormatContext *h = userdata; + PulseData *s = h->priv_data; + + if (s->ctx != ctx) + return; + + if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) { + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE) + // Calling from mainloop callback. No need to lock mainloop. + pulse_update_sink_input_info(h); + } +} + +static void pulse_stream_writable(pa_stream *stream, size_t nbytes, void *userdata) +{ + AVFormatContext *h = userdata; + PulseData *s = h->priv_data; + int64_t val = nbytes; + + if (stream != s->stream) + return; + + avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_BUFFER_WRITABLE, &val, sizeof(val)); + pa_threaded_mainloop_signal(s->mainloop, 0); +} + +static void pulse_overflow(pa_stream *stream, void *userdata) +{ + AVFormatContext *h = userdata; + avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_BUFFER_OVERFLOW, NULL, 0); +} + +static void pulse_underflow(pa_stream *stream, void *userdata) +{ + AVFormatContext *h = userdata; + avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_BUFFER_UNDERFLOW, NULL, 0); +} + +static void pulse_stream_state(pa_stream *stream, void *userdata) +{ + PulseData *s = userdata; + + if (stream != s->stream) + return; + + switch (pa_stream_get_state(s->stream)) { + case PA_STREAM_READY: + case PA_STREAM_FAILED: + case PA_STREAM_TERMINATED: + pa_threaded_mainloop_signal(s->mainloop, 0); + default: + break; + } +} + +static int pulse_stream_wait(PulseData *s) +{ + pa_stream_state_t state; + + while ((state = pa_stream_get_state(s->stream)) != PA_STREAM_READY) { + if (state == PA_STREAM_FAILED || state == PA_STREAM_TERMINATED) + return AVERROR_EXTERNAL; + pa_threaded_mainloop_wait(s->mainloop); + } + return 0; +} + +static void pulse_context_state(pa_context *ctx, void *userdata) +{ + PulseData *s = userdata; + + if (s->ctx != ctx) + return; + + switch (pa_context_get_state(ctx)) { + case PA_CONTEXT_READY: + case PA_CONTEXT_FAILED: + case PA_CONTEXT_TERMINATED: + pa_threaded_mainloop_signal(s->mainloop, 0); + default: + break; + } +} + +static int pulse_context_wait(PulseData *s) +{ + pa_context_state_t state; + + while ((state = pa_context_get_state(s->ctx)) != PA_CONTEXT_READY) { + if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED) + return AVERROR_EXTERNAL; + pa_threaded_mainloop_wait(s->mainloop); + } + return 0; +} + +static void pulse_stream_result(pa_stream *stream, int success, void *userdata) +{ + PulseData *s = userdata; + + if (stream != s->stream) + return; + + s->last_result = success ? 0 : AVERROR_EXTERNAL; + pa_threaded_mainloop_signal(s->mainloop, 0); +} + +static int pulse_finish_stream_operation(PulseData *s, pa_operation *op, const char *name) +{ + if (!op) { + pa_threaded_mainloop_unlock(s->mainloop); + av_log(s, AV_LOG_ERROR, "%s failed.\n", name); + return AVERROR_EXTERNAL; + } + s->last_result = 2; + while (s->last_result == 2) + pa_threaded_mainloop_wait(s->mainloop); + pa_operation_unref(op); + pa_threaded_mainloop_unlock(s->mainloop); + if (s->last_result != 0) + av_log(s, AV_LOG_ERROR, "%s failed.\n", name); + return s->last_result; +} + +static int pulse_set_pause(PulseData *s, int pause) +{ + pa_operation *op; + pa_threaded_mainloop_lock(s->mainloop); + op = pa_stream_cork(s->stream, pause, pulse_stream_result, s); + return pulse_finish_stream_operation(s, op, "pa_stream_cork"); +} + +static int pulse_flash_stream(PulseData *s) +{ + pa_operation *op; + pa_threaded_mainloop_lock(s->mainloop); + op = pa_stream_flush(s->stream, pulse_stream_result, s); + return pulse_finish_stream_operation(s, op, "pa_stream_flush"); +} + +static void pulse_context_result(pa_context *ctx, int success, void *userdata) +{ + PulseData *s = userdata; + + if (s->ctx != ctx) + return; + + s->last_result = success ? 0 : AVERROR_EXTERNAL; + pa_threaded_mainloop_signal(s->mainloop, 0); +} + +static int pulse_finish_context_operation(PulseData *s, pa_operation *op, const char *name) +{ + if (!op) { + pa_threaded_mainloop_unlock(s->mainloop); + av_log(s, AV_LOG_ERROR, "%s failed.\n", name); + return AVERROR_EXTERNAL; + } + s->last_result = 2; + while (s->last_result == 2) + pa_threaded_mainloop_wait(s->mainloop); + pa_operation_unref(op); + pa_threaded_mainloop_unlock(s->mainloop); + if (s->last_result != 0) + av_log(s, AV_LOG_ERROR, "%s failed.\n", name); + return s->last_result; +} + +static int pulse_set_mute(PulseData *s) +{ + pa_operation *op; + pa_threaded_mainloop_lock(s->mainloop); + op = pa_context_set_sink_input_mute(s->ctx, pa_stream_get_index(s->stream), + s->mute, pulse_context_result, s); + return pulse_finish_context_operation(s, op, "pa_context_set_sink_input_mute"); +} + +static int pulse_set_volume(PulseData *s, double volume) +{ + pa_operation *op; + pa_cvolume cvol; + pa_volume_t vol; + const pa_sample_spec *ss = pa_stream_get_sample_spec(s->stream); + + vol = pa_sw_volume_multiply(lround(volume * PA_VOLUME_NORM), s->base_volume); + pa_cvolume_set(&cvol, ss->channels, PA_VOLUME_NORM); + pa_sw_cvolume_multiply_scalar(&cvol, &cvol, vol); + pa_threaded_mainloop_lock(s->mainloop); + op = pa_context_set_sink_input_volume(s->ctx, pa_stream_get_index(s->stream), + &cvol, pulse_context_result, s); + return pulse_finish_context_operation(s, op, "pa_context_set_sink_input_volume"); +} + +static int pulse_subscribe_events(PulseData *s) +{ + pa_operation *op; + + pa_threaded_mainloop_lock(s->mainloop); + op = pa_context_subscribe(s->ctx, PA_SUBSCRIPTION_MASK_SINK_INPUT, pulse_context_result, s); + return pulse_finish_context_operation(s, op, "pa_context_subscribe"); +} + +static void pulse_map_channels_to_pulse(int64_t channel_layout, pa_channel_map *channel_map) +{ + channel_map->channels = 0; + if (channel_layout & AV_CH_FRONT_LEFT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT; + if (channel_layout & AV_CH_FRONT_RIGHT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT; + if (channel_layout & AV_CH_FRONT_CENTER) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_CENTER; + if (channel_layout & AV_CH_LOW_FREQUENCY) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE; + if (channel_layout & AV_CH_BACK_LEFT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_LEFT; + if (channel_layout & AV_CH_BACK_RIGHT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_RIGHT; + if (channel_layout & AV_CH_FRONT_LEFT_OF_CENTER) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER; + if (channel_layout & AV_CH_FRONT_RIGHT_OF_CENTER) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER; + if (channel_layout & AV_CH_BACK_CENTER) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_CENTER; + if (channel_layout & AV_CH_SIDE_LEFT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_LEFT; + if (channel_layout & AV_CH_SIDE_RIGHT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT; + if (channel_layout & AV_CH_TOP_CENTER) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_CENTER; + if (channel_layout & AV_CH_TOP_FRONT_LEFT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT; + if (channel_layout & AV_CH_TOP_FRONT_CENTER) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER; + if (channel_layout & AV_CH_TOP_FRONT_RIGHT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT; + if (channel_layout & AV_CH_TOP_BACK_LEFT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_LEFT; + if (channel_layout & AV_CH_TOP_BACK_CENTER) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_CENTER; + if (channel_layout & AV_CH_TOP_BACK_RIGHT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT; + if (channel_layout & AV_CH_STEREO_LEFT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT; + if (channel_layout & AV_CH_STEREO_RIGHT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT; + if (channel_layout & AV_CH_WIDE_LEFT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX0; + if (channel_layout & AV_CH_WIDE_RIGHT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX1; + if (channel_layout & AV_CH_SURROUND_DIRECT_LEFT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX2; + if (channel_layout & AV_CH_SURROUND_DIRECT_RIGHT) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX3; + if (channel_layout & AV_CH_LOW_FREQUENCY_2) + channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE; +} + +static av_cold int pulse_write_trailer(AVFormatContext *h) +{ + PulseData *s = h->priv_data; + + if (s->mainloop) { + pa_threaded_mainloop_lock(s->mainloop); + if (s->stream) { + pa_stream_disconnect(s->stream); + pa_stream_set_state_callback(s->stream, NULL, NULL); + pa_stream_set_write_callback(s->stream, NULL, NULL); + pa_stream_set_overflow_callback(s->stream, NULL, NULL); + pa_stream_set_underflow_callback(s->stream, NULL, NULL); + pa_stream_unref(s->stream); + s->stream = NULL; + } + if (s->ctx) { + pa_context_disconnect(s->ctx); + pa_context_set_state_callback(s->ctx, NULL, NULL); + pa_context_set_subscribe_callback(s->ctx, NULL, NULL); + pa_context_unref(s->ctx); + s->ctx = NULL; + } + pa_threaded_mainloop_unlock(s->mainloop); + pa_threaded_mainloop_stop(s->mainloop); + pa_threaded_mainloop_free(s->mainloop); + s->mainloop = NULL; + } + + return 0; +} + static av_cold int pulse_write_header(AVFormatContext *h) { PulseData *s = h->priv_data; AVStream *st = NULL; int ret; - pa_sample_spec ss; - pa_buffer_attr attr = { -1, -1, -1, -1, -1 }; + pa_sample_spec sample_spec; + pa_buffer_attr buffer_attributes = { -1, -1, -1, -1, -1 }; + pa_channel_map channel_map; + pa_mainloop_api *mainloop_api; const char *stream_name = s->stream_name; + static const pa_stream_flags_t stream_flags = PA_STREAM_INTERPOLATE_TIMING | + PA_STREAM_AUTO_TIMING_UPDATE | + PA_STREAM_NOT_MONOTONIC; if (h->nb_streams != 1 || h->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO) { av_log(s, AV_LOG_ERROR, "Only a single audio stream is supported.\n"); @@ -60,65 +463,171 @@ static av_cold int pulse_write_header(AVFormatContext *h) else stream_name = "Playback"; } + s->nonblocking = (h->flags & AVFMT_FLAG_NONBLOCK); if (s->buffer_duration) { int64_t bytes = s->buffer_duration; bytes *= st->codec->channels * st->codec->sample_rate * av_get_bytes_per_sample(st->codec->sample_fmt); bytes /= 1000; - attr.tlength = FFMAX(s->buffer_size, av_clip64(bytes, 0, UINT32_MAX - 1)); + buffer_attributes.tlength = FFMAX(s->buffer_size, av_clip64(bytes, 0, UINT32_MAX - 1)); av_log(s, AV_LOG_DEBUG, "Buffer duration: %ums recalculated into %"PRId64" bytes buffer.\n", s->buffer_duration, bytes); - av_log(s, AV_LOG_DEBUG, "Real buffer length is %u bytes\n", attr.tlength); + av_log(s, AV_LOG_DEBUG, "Real buffer length is %u bytes\n", buffer_attributes.tlength); } else if (s->buffer_size) - attr.tlength = s->buffer_size; + buffer_attributes.tlength = s->buffer_size; + if (s->prebuf) + buffer_attributes.prebuf = s->prebuf; + if (s->minreq) + buffer_attributes.minreq = s->minreq; - ss.format = ff_codec_id_to_pulse_format(st->codec->codec_id); - ss.rate = st->codec->sample_rate; - ss.channels = st->codec->channels; - - s->pa = pa_simple_new(s->server, // Server - s->name, // Application name - PA_STREAM_PLAYBACK, - s->device, // Device - stream_name, // Description of a stream - &ss, // Sample format - NULL, // Use default channel map - &attr, // Buffering attributes - &ret); // Result - - if (!s->pa) { - av_log(s, AV_LOG_ERROR, "pa_simple_new failed: %s\n", pa_strerror(ret)); - return AVERROR(EIO); + sample_spec.format = ff_codec_id_to_pulse_format(st->codec->codec_id); + sample_spec.rate = st->codec->sample_rate; + sample_spec.channels = st->codec->channels; + if (!pa_sample_spec_valid(&sample_spec)) { + av_log(s, AV_LOG_ERROR, "Invalid sample spec.\n"); + return AVERROR(EINVAL); } + if (sample_spec.channels == 1) { + channel_map.channels = 1; + channel_map.map[0] = PA_CHANNEL_POSITION_MONO; + } else if (st->codec->channel_layout) { + if (av_get_channel_layout_nb_channels(st->codec->channel_layout) != st->codec->channels) + return AVERROR(EINVAL); + pulse_map_channels_to_pulse(st->codec->channel_layout, &channel_map); + /* Unknown channel is present in channel_layout, let PulseAudio use its default. */ + if (channel_map.channels != sample_spec.channels) { + av_log(s, AV_LOG_WARNING, "Unknown channel. Using defaul channel map.\n"); + channel_map.channels = 0; + } + } else + channel_map.channels = 0; + + if (!channel_map.channels) + av_log(s, AV_LOG_WARNING, "Using PulseAudio's default channel map.\n"); + else if (!pa_channel_map_valid(&channel_map)) { + av_log(s, AV_LOG_ERROR, "Invalid channel map.\n"); + return AVERROR(EINVAL); + } + + /* start main loop */ + s->mainloop = pa_threaded_mainloop_new(); + if (!s->mainloop) { + av_log(s, AV_LOG_ERROR, "Cannot create threaded mainloop.\n"); + return AVERROR(ENOMEM); + } + if ((ret = pa_threaded_mainloop_start(s->mainloop)) < 0) { + av_log(s, AV_LOG_ERROR, "Cannot start threaded mainloop: %s.\n", pa_strerror(ret)); + pa_threaded_mainloop_free(s->mainloop); + s->mainloop = NULL; + return AVERROR_EXTERNAL; + } + + pa_threaded_mainloop_lock(s->mainloop); + + mainloop_api = pa_threaded_mainloop_get_api(s->mainloop); + if (!mainloop_api) { + av_log(s, AV_LOG_ERROR, "Cannot get mainloop API.\n"); + ret = AVERROR_EXTERNAL; + goto fail; + } + + s->ctx = pa_context_new(mainloop_api, s->name); + if (!s->ctx) { + av_log(s, AV_LOG_ERROR, "Cannot create context.\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + pa_context_set_state_callback(s->ctx, pulse_context_state, s); + pa_context_set_subscribe_callback(s->ctx, pulse_event, h); + + if ((ret = pa_context_connect(s->ctx, s->server, 0, NULL)) < 0) { + av_log(s, AV_LOG_ERROR, "Cannot connect context: %s.\n", pa_strerror(ret)); + ret = AVERROR_EXTERNAL; + goto fail; + } + + if ((ret = pulse_context_wait(s)) < 0) { + av_log(s, AV_LOG_ERROR, "Context failed.\n"); + goto fail; + } + + s->stream = pa_stream_new(s->ctx, stream_name, &sample_spec, + channel_map.channels ? &channel_map : NULL); + + if ((ret = pulse_update_sink_info(h)) < 0) { + av_log(s, AV_LOG_ERROR, "Updating sink info failed.\n"); + goto fail; + } + + if (!s->stream) { + av_log(s, AV_LOG_ERROR, "Cannot create stream.\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + pa_stream_set_state_callback(s->stream, pulse_stream_state, s); + pa_stream_set_write_callback(s->stream, pulse_stream_writable, h); + pa_stream_set_overflow_callback(s->stream, pulse_overflow, h); + pa_stream_set_underflow_callback(s->stream, pulse_underflow, h); + + if ((ret = pa_stream_connect_playback(s->stream, s->device, &buffer_attributes, + stream_flags, NULL, NULL)) < 0) { + av_log(s, AV_LOG_ERROR, "pa_stream_connect_playback failed: %s.\n", pa_strerror(ret)); + ret = AVERROR_EXTERNAL; + goto fail; + } + + if ((ret = pulse_stream_wait(s)) < 0) { + av_log(s, AV_LOG_ERROR, "Stream failed.\n"); + goto fail; + } + + /* read back buffer attributes for future use */ + buffer_attributes = *pa_stream_get_buffer_attr(s->stream); + s->buffer_size = buffer_attributes.tlength; + s->prebuf = buffer_attributes.prebuf; + s->minreq = buffer_attributes.minreq; + av_log(s, AV_LOG_DEBUG, "Real buffer attributes: size: %d, prebuf: %d, minreq: %d\n", + s->buffer_size, s->prebuf, s->minreq); + + pa_threaded_mainloop_unlock(s->mainloop); + + if ((ret = pulse_subscribe_events(s)) < 0) { + av_log(s, AV_LOG_ERROR, "Event subscription failed.\n"); + /* a bit ugly but the simplest to lock here*/ + pa_threaded_mainloop_lock(s->mainloop); + goto fail; + } + + /* force control messages */ + s->mute = -1; + s->last_volume = PA_VOLUME_INVALID; + pa_threaded_mainloop_lock(s->mainloop); + if ((ret = pulse_update_sink_input_info(h)) < 0) { + av_log(s, AV_LOG_ERROR, "Updating sink input info failed.\n"); + goto fail; + } + pa_threaded_mainloop_unlock(s->mainloop); + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ return 0; -} - -static av_cold int pulse_write_trailer(AVFormatContext *h) -{ - PulseData *s = h->priv_data; - pa_simple_flush(s->pa, NULL); - pa_simple_free(s->pa); - s->pa = NULL; - return 0; + fail: + pa_threaded_mainloop_unlock(s->mainloop); + pulse_write_trailer(h); + return ret; } static int pulse_write_packet(AVFormatContext *h, AVPacket *pkt) { PulseData *s = h->priv_data; - int error; + int ret; + int64_t writable_size; - if (!pkt) { - if (pa_simple_flush(s->pa, &error) < 0) { - av_log(s, AV_LOG_ERROR, "pa_simple_flush failed: %s\n", pa_strerror(error)); - return AVERROR(EIO); - } - return 1; - } + if (!pkt) + return pulse_flash_stream(s); if (pkt->dts != AV_NOPTS_VALUE) s->timestamp = pkt->dts; @@ -133,52 +642,155 @@ static int pulse_write_packet(AVFormatContext *h, AVPacket *pkt) s->timestamp += av_rescale_q(samples, r, st->time_base); } - if (pa_simple_write(s->pa, pkt->data, pkt->size, &error) < 0) { - av_log(s, AV_LOG_ERROR, "pa_simple_write failed: %s\n", pa_strerror(error)); - return AVERROR(EIO); + pa_threaded_mainloop_lock(s->mainloop); + if (!PA_STREAM_IS_GOOD(pa_stream_get_state(s->stream))) { + av_log(s, AV_LOG_ERROR, "PulseAudio stream is in invalid state.\n"); + goto fail; + } + while (pa_stream_writable_size(s->stream) < s->minreq) { + if (s->nonblocking) { + pa_threaded_mainloop_unlock(s->mainloop); + return AVERROR(EAGAIN); + } else + pa_threaded_mainloop_wait(s->mainloop); } + if ((ret = pa_stream_write(s->stream, pkt->data, pkt->size, NULL, 0, PA_SEEK_RELATIVE)) < 0) { + av_log(s, AV_LOG_ERROR, "pa_stream_write failed: %s\n", pa_strerror(ret)); + goto fail; + } + if ((writable_size = pa_stream_writable_size(s->stream)) >= s->minreq) + avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_BUFFER_WRITABLE, &writable_size, sizeof(writable_size)); + + pa_threaded_mainloop_unlock(s->mainloop); + return 0; + fail: + pa_threaded_mainloop_unlock(s->mainloop); + return AVERROR_EXTERNAL; } +static int pulse_write_frame(AVFormatContext *h, int stream_index, + AVFrame **frame, unsigned flags) +{ + AVPacket pkt; + + /* Planar formats are not supported yet. */ + if (flags & AV_WRITE_UNCODED_FRAME_QUERY) + return av_sample_fmt_is_planar(h->streams[stream_index]->codec->sample_fmt) ? + AVERROR(EINVAL) : 0; + + pkt.data = (*frame)->data[0]; + pkt.size = (*frame)->nb_samples * av_get_bytes_per_sample((*frame)->format) * (*frame)->channels; + pkt.dts = (*frame)->pkt_dts; + pkt.duration = av_frame_get_pkt_duration(*frame); + return pulse_write_packet(h, &pkt); +} + + static void pulse_get_output_timestamp(AVFormatContext *h, int stream, int64_t *dts, int64_t *wall) { PulseData *s = h->priv_data; - pa_usec_t latency = pa_simple_get_latency(s->pa, NULL); - *wall = av_gettime(); - *dts = s->timestamp - latency; + pa_usec_t latency; + int neg; + pa_threaded_mainloop_lock(s->mainloop); + pa_stream_get_latency(s->stream, &latency, &neg); + pa_threaded_mainloop_unlock(s->mainloop); + if (wall) + *wall = av_gettime(); + if (dts) + *dts = s->timestamp - (neg ? -latency : latency); +} + +static int pulse_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list) +{ + PulseData *s = h->priv_data; + return ff_pulse_audio_get_devices(device_list, s->server, 1); +} + +static int pulse_control_message(AVFormatContext *h, int type, + void *data, size_t data_size) +{ + PulseData *s = h->priv_data; + int ret; + + switch(type) { + case AV_APP_TO_DEV_PAUSE: + return pulse_set_pause(s, 1); + case AV_APP_TO_DEV_PLAY: + return pulse_set_pause(s, 0); + case AV_APP_TO_DEV_TOGGLE_PAUSE: + return pulse_set_pause(s, !pa_stream_is_corked(s->stream)); + case AV_APP_TO_DEV_MUTE: + if (!s->mute) { + s->mute = 1; + return pulse_set_mute(s); + } + return 0; + case AV_APP_TO_DEV_UNMUTE: + if (s->mute) { + s->mute = 0; + return pulse_set_mute(s); + } + return 0; + case AV_APP_TO_DEV_TOGGLE_MUTE: + s->mute = !s->mute; + return pulse_set_mute(s); + case AV_APP_TO_DEV_SET_VOLUME: + return pulse_set_volume(s, *(double *)data); + case AV_APP_TO_DEV_GET_VOLUME: + s->last_volume = PA_VOLUME_INVALID; + pa_threaded_mainloop_lock(s->mainloop); + ret = pulse_update_sink_input_info(h); + pa_threaded_mainloop_unlock(s->mainloop); + return ret; + case AV_APP_TO_DEV_GET_MUTE: + s->mute = -1; + pa_threaded_mainloop_lock(s->mainloop); + ret = pulse_update_sink_input_info(h); + pa_threaded_mainloop_unlock(s->mainloop); + return ret; + default: + break; + } + return AVERROR(ENOSYS); } #define OFFSET(a) offsetof(PulseData, a) #define E AV_OPT_FLAG_ENCODING_PARAM - static const AVOption options[] = { - { "server", "set PulseAudio server", OFFSET(server), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, - { "name", "set application name", OFFSET(name), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, E }, - { "stream_name", "set stream description", OFFSET(stream_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, - { "device", "set device name", OFFSET(device), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, - { "buffer_size", "set buffer size in bytes", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, - { "buffer_duration", "set buffer duration in millisecs", OFFSET(buffer_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, + { "server", "set PulseAudio server", OFFSET(server), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, + { "name", "set application name", OFFSET(name), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, E }, + { "stream_name", "set stream description", OFFSET(stream_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, + { "device", "set device name", OFFSET(device), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, + { "buffer_size", "set buffer size in bytes", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, + { "buffer_duration", "set buffer duration in millisecs", OFFSET(buffer_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, + { "prebuf", "set pre-buffering size", OFFSET(prebuf), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, + { "minreq", "set minimum request size", OFFSET(minreq), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, { NULL } }; static const AVClass pulse_muxer_class = { - .class_name = "Pulse muxer", + .class_name = "PulseAudio muxer", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, }; AVOutputFormat ff_pulse_muxer = { - .name = "pulse", - .long_name = NULL_IF_CONFIG_SMALL("Pulse audio output"), - .priv_data_size = sizeof(PulseData), - .audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), - .video_codec = AV_CODEC_ID_NONE, - .write_header = pulse_write_header, - .write_packet = pulse_write_packet, - .write_trailer = pulse_write_trailer, + .name = "pulse", + .long_name = NULL_IF_CONFIG_SMALL("Pulse audio output"), + .priv_data_size = sizeof(PulseData), + .audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), + .video_codec = AV_CODEC_ID_NONE, + .write_header = pulse_write_header, + .write_packet = pulse_write_packet, + .write_uncoded_frame = pulse_write_frame, + .write_trailer = pulse_write_trailer, .get_output_timestamp = pulse_get_output_timestamp, - .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH, - .priv_class = &pulse_muxer_class, + .get_device_list = pulse_get_device_list, + .control_message = pulse_control_message, + .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH, + .priv_class = &pulse_muxer_class, }; diff --git a/libavdevice/qtkit.m b/libavdevice/qtkit.m new file mode 100644 index 000000000..aa8fa1678 --- /dev/null +++ b/libavdevice/qtkit.m @@ -0,0 +1,358 @@ +/* + * QTKit input device + * Copyright (c) 2013 Vadim Kalinsky + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * QTKit input device + * @author Vadim Kalinsky + */ + +#import +#include + +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "libavformat/internal.h" +#include "libavutil/internal.h" +#include "libavutil/time.h" +#include "avdevice.h" + +#define QTKIT_TIMEBASE 100 + +static const AVRational kQTKitTimeBase_q = { + .num = 1, + .den = QTKIT_TIMEBASE +}; + +typedef struct +{ + AVClass* class; + + float frame_rate; + int frames_captured; + int64_t first_pts; + pthread_mutex_t frame_lock; + pthread_cond_t frame_wait_cond; + id qt_delegate; + + int list_devices; + int video_device_index; + + QTCaptureSession* capture_session; + QTCaptureDecompressedVideoOutput* video_output; + CVImageBufferRef current_frame; +} CaptureContext; + +static void lock_frames(CaptureContext* ctx) +{ + pthread_mutex_lock(&ctx->frame_lock); +} + +static void unlock_frames(CaptureContext* ctx) +{ + pthread_mutex_unlock(&ctx->frame_lock); +} + +/** FrameReciever class - delegate for QTCaptureSession + */ +@interface FFMPEG_FrameReceiver : NSObject +{ + CaptureContext* _context; +} + +- (id)initWithContext:(CaptureContext*)context; + +- (void)captureOutput:(QTCaptureOutput *)captureOutput + didOutputVideoFrame:(CVImageBufferRef)videoFrame + withSampleBuffer:(QTSampleBuffer *)sampleBuffer + fromConnection:(QTCaptureConnection *)connection; + +@end + +@implementation FFMPEG_FrameReceiver + +- (id)initWithContext:(CaptureContext*)context +{ + if (self = [super init]) { + _context = context; + } + return self; +} + +- (void)captureOutput:(QTCaptureOutput *)captureOutput + didOutputVideoFrame:(CVImageBufferRef)videoFrame + withSampleBuffer:(QTSampleBuffer *)sampleBuffer + fromConnection:(QTCaptureConnection *)connection +{ + lock_frames(_context); + if (_context->current_frame != nil) { + CVBufferRelease(_context->current_frame); + } + + _context->current_frame = CVBufferRetain(videoFrame); + + pthread_cond_signal(&_context->frame_wait_cond); + + unlock_frames(_context); + + ++_context->frames_captured; +} + +@end + +static void destroy_context(CaptureContext* ctx) +{ + [ctx->capture_session stopRunning]; + + [ctx->capture_session release]; + [ctx->video_output release]; + [ctx->qt_delegate release]; + + ctx->capture_session = NULL; + ctx->video_output = NULL; + ctx->qt_delegate = NULL; + + pthread_mutex_destroy(&ctx->frame_lock); + pthread_cond_destroy(&ctx->frame_wait_cond); + + if (ctx->current_frame) + CVBufferRelease(ctx->current_frame); +} + +static int qtkit_read_header(AVFormatContext *s) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + CaptureContext* ctx = (CaptureContext*)s->priv_data; + + ctx->first_pts = av_gettime(); + + pthread_mutex_init(&ctx->frame_lock, NULL); + pthread_cond_init(&ctx->frame_wait_cond, NULL); + + // List devices if requested + if (ctx->list_devices) { + av_log(ctx, AV_LOG_INFO, "QTKit video devices:\n"); + NSArray *devices = [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo]; + for (QTCaptureDevice *device in devices) { + const char *name = [[device localizedDisplayName] UTF8String]; + int index = [devices indexOfObject:device]; + av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name); + } + goto fail; + } + + // Find capture device + QTCaptureDevice *video_device = nil; + + // check for device index given in filename + if (ctx->video_device_index == -1) { + sscanf(s->filename, "%d", &ctx->video_device_index); + } + + if (ctx->video_device_index >= 0) { + NSArray *devices = [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo]; + + if (ctx->video_device_index >= [devices count]) { + av_log(ctx, AV_LOG_ERROR, "Invalid device index\n"); + goto fail; + } + + video_device = [devices objectAtIndex:ctx->video_device_index]; + } else if (strncmp(s->filename, "", 1) && + strncmp(s->filename, "default", 7)) { + NSArray *devices = [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo]; + + for (QTCaptureDevice *device in devices) { + if (!strncmp(s->filename, [[device localizedDisplayName] UTF8String], strlen(s->filename))) { + video_device = device; + break; + } + } + if (!video_device) { + av_log(ctx, AV_LOG_ERROR, "Video device not found\n"); + goto fail; + } + } else { + video_device = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeMuxed]; + } + + BOOL success = [video_device open:nil]; + + // Video capture device not found, looking for QTMediaTypeVideo + if (!success) { + video_device = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo]; + success = [video_device open:nil]; + + if (!success) { + av_log(s, AV_LOG_ERROR, "No QT capture device found\n"); + goto fail; + } + } + + NSString* dev_display_name = [video_device localizedDisplayName]; + av_log (s, AV_LOG_DEBUG, "'%s' opened\n", [dev_display_name UTF8String]); + + // Initialize capture session + ctx->capture_session = [[QTCaptureSession alloc] init]; + + QTCaptureDeviceInput* capture_dev_input = [[[QTCaptureDeviceInput alloc] initWithDevice:video_device] autorelease]; + success = [ctx->capture_session addInput:capture_dev_input error:nil]; + + if (!success) { + av_log (s, AV_LOG_ERROR, "Failed to add QT capture device to session\n"); + goto fail; + } + + // Attaching output + // FIXME: Allow for a user defined pixel format + ctx->video_output = [[QTCaptureDecompressedVideoOutput alloc] init]; + + NSDictionary *captureDictionary = [NSDictionary dictionaryWithObject: + [NSNumber numberWithUnsignedInt:kCVPixelFormatType_24RGB] + forKey:(id)kCVPixelBufferPixelFormatTypeKey]; + + [ctx->video_output setPixelBufferAttributes:captureDictionary]; + + ctx->qt_delegate = [[FFMPEG_FrameReceiver alloc] initWithContext:ctx]; + + [ctx->video_output setDelegate:ctx->qt_delegate]; + [ctx->video_output setAutomaticallyDropsLateVideoFrames:YES]; + [ctx->video_output setMinimumVideoFrameInterval:1.0/ctx->frame_rate]; + + success = [ctx->capture_session addOutput:ctx->video_output error:nil]; + + if (!success) { + av_log (s, AV_LOG_ERROR, "can't add video output to capture session\n"); + goto fail; + } + + [ctx->capture_session startRunning]; + + // Take stream info from the first frame. + while (ctx->frames_captured < 1) { + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES); + } + + lock_frames(ctx); + + AVStream* stream = avformat_new_stream(s, NULL); + + if (!stream) { + goto fail; + } + + avpriv_set_pts_info(stream, 64, 1, QTKIT_TIMEBASE); + + stream->codec->codec_id = AV_CODEC_ID_RAWVIDEO; + stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; + stream->codec->width = (int)CVPixelBufferGetWidth (ctx->current_frame); + stream->codec->height = (int)CVPixelBufferGetHeight(ctx->current_frame); + stream->codec->pix_fmt = AV_PIX_FMT_RGB24; + + CVBufferRelease(ctx->current_frame); + ctx->current_frame = nil; + + unlock_frames(ctx); + + [pool release]; + + return 0; + +fail: + [pool release]; + + destroy_context(ctx); + + return AVERROR(EIO); +} + +static int qtkit_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + CaptureContext* ctx = (CaptureContext*)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, kQTKitTimeBase_q); + pkt->stream_index = 0; + 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); + CVBufferRelease(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 qtkit_close(AVFormatContext *s) +{ + CaptureContext* ctx = (CaptureContext*)s->priv_data; + + destroy_context(ctx); + + return 0; +} + +static const AVOption options[] = { + { "frame_rate", "set frame rate", offsetof(CaptureContext, frame_rate), AV_OPT_TYPE_FLOAT, { .dbl = 30.0 }, 0.1, 30.0, AV_OPT_TYPE_VIDEO_RATE, NULL }, + { "list_devices", "list available devices", offsetof(CaptureContext, list_devices), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM, "list_devices" }, + { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" }, + { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" }, + { "video_device_index", "select video device by index for devices with same name (starts at 0)", offsetof(CaptureContext, video_device_index), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass qtkit_class = { + .class_name = "QTKit input device", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, +}; + +AVInputFormat ff_qtkit_demuxer = { + .name = "qtkit", + .long_name = NULL_IF_CONFIG_SMALL("QTKit input device"), + .priv_data_size = sizeof(CaptureContext), + .read_header = qtkit_read_header, + .read_packet = qtkit_read_packet, + .read_close = qtkit_close, + .flags = AVFMT_NOFILE, + .priv_class = &qtkit_class, +}; diff --git a/libavdevice/sdl.c b/libavdevice/sdl.c index bef50417e..b98aae5ee 100644 --- a/libavdevice/sdl.c +++ b/libavdevice/sdl.c @@ -358,6 +358,7 @@ static const AVClass sdl_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; AVOutputFormat ff_sdl_muxer = { diff --git a/libavdevice/sndio_dec.c b/libavdevice/sndio_dec.c index 806f47867..37c698342 100644 --- a/libavdevice/sndio_dec.c +++ b/libavdevice/sndio_dec.c @@ -104,6 +104,7 @@ static const AVClass sndio_demuxer_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, }; AVInputFormat ff_sndio_demuxer = { diff --git a/libavdevice/sndio_enc.c b/libavdevice/sndio_enc.c index 84d070e89..205cf2411 100644 --- a/libavdevice/sndio_enc.c +++ b/libavdevice/sndio_enc.c @@ -76,6 +76,13 @@ static int audio_write_trailer(AVFormatContext *s1) return 0; } +static const AVClass sndio_muxer_class = { + .class_name = "sndio outdev", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, +}; + AVOutputFormat ff_sndio_muxer = { .name = "sndio", .long_name = NULL_IF_CONFIG_SMALL("sndio audio playback"), @@ -89,4 +96,5 @@ AVOutputFormat ff_sndio_muxer = { .write_packet = audio_write_packet, .write_trailer = audio_write_trailer, .flags = AVFMT_NOFILE, + .priv_class = &sndio_muxer_class, }; diff --git a/libavdevice/v4l.c b/libavdevice/v4l.c index bf2c9e372..d33f7142a 100644 --- a/libavdevice/v4l.c +++ b/libavdevice/v4l.c @@ -348,6 +348,7 @@ static const AVClass v4l_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, }; AVInputFormat ff_v4l_demuxer = { diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index 96a272c19..64df0c795 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -351,12 +351,12 @@ static int mmap_init(AVFormatContext *ctx) return AVERROR(ENOMEM); } s->buffers = req.count; - s->buf_start = av_malloc(sizeof(void *) * s->buffers); + s->buf_start = av_malloc_array(s->buffers, sizeof(void *)); if (s->buf_start == NULL) { av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n"); return AVERROR(ENOMEM); } - s->buf_len = av_malloc(sizeof(unsigned int) * s->buffers); + s->buf_len = av_malloc_array(s->buffers, sizeof(unsigned int)); if (s->buf_len == NULL) { av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n"); av_free(s->buf_start); @@ -427,10 +427,7 @@ static void mmap_release_buffer(void *opaque, uint8_t *data) #if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC) static int64_t av_gettime_monotonic(void) { - struct timespec tv; - - clock_gettime(CLOCK_MONOTONIC, &tv); - return (int64_t)tv.tv_sec * 1000000 + tv.tv_nsec / 1000; + return av_gettime_relative(); } #endif @@ -1014,7 +1011,7 @@ static const AVOption options[] = { { "default", "use timestamps from the kernel", OFFSET(ts_mode), AV_OPT_TYPE_CONST, {.i64 = V4L_TS_DEFAULT }, 0, 2, DEC, "timestamps" }, { "abs", "use absolute timestamps (wall clock)", OFFSET(ts_mode), AV_OPT_TYPE_CONST, {.i64 = V4L_TS_ABS }, 0, 2, DEC, "timestamps" }, { "mono2abs", "force conversion from monotonic to absolute timestamps", OFFSET(ts_mode), AV_OPT_TYPE_CONST, {.i64 = V4L_TS_MONO2ABS }, 0, 2, DEC, "timestamps" }, - { "use_libv4l2", "use libv4l2 (v4l-utils) convertion functions", OFFSET(use_libv4l2), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC }, + { "use_libv4l2", "use libv4l2 (v4l-utils) conversion functions", OFFSET(use_libv4l2), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC }, { NULL }, }; @@ -1023,6 +1020,7 @@ static const AVClass v4l2_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, }; AVInputFormat ff_v4l2_demuxer = { diff --git a/libavdevice/v4l2enc.c b/libavdevice/v4l2enc.c index 21f0ef698..efe08b589 100644 --- a/libavdevice/v4l2enc.c +++ b/libavdevice/v4l2enc.c @@ -97,6 +97,13 @@ static int write_trailer(AVFormatContext *s1) return 0; } +static const AVClass v4l2_class = { + .class_name = "V4L2 outdev", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, +}; + AVOutputFormat ff_v4l2_muxer = { .name = "v4l2", .long_name = NULL_IF_CONFIG_SMALL("Video4Linux2 output device"), @@ -107,4 +114,5 @@ AVOutputFormat ff_v4l2_muxer = { .write_packet = write_packet, .write_trailer = write_trailer, .flags = AVFMT_NOFILE, + .priv_class = &v4l2_class, }; diff --git a/libavdevice/version.h b/libavdevice/version.h index 85b3b3766..a09854959 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 55 -#define LIBAVDEVICE_VERSION_MINOR 10 -#define LIBAVDEVICE_VERSION_MICRO 100 +#define LIBAVDEVICE_VERSION_MINOR 13 +#define LIBAVDEVICE_VERSION_MICRO 102 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \ diff --git a/libavdevice/vfwcap.c b/libavdevice/vfwcap.c index 014f18c27..e5d959350 100644 --- a/libavdevice/vfwcap.c +++ b/libavdevice/vfwcap.c @@ -469,6 +469,7 @@ static const AVClass vfw_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT }; AVInputFormat ff_vfwcap_demuxer = { diff --git a/libavdevice/x11grab.c b/libavdevice/x11grab.c index 0e7b6ae5e..d38c55d1c 100644 --- a/libavdevice/x11grab.c +++ b/libavdevice/x11grab.c @@ -633,6 +633,7 @@ static const AVClass x11_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, }; /** x11 grabber device demuxer declaration */ diff --git a/libavdevice/xv.c b/libavdevice/xv.c index fbb941579..aeb3e4114 100644 --- a/libavdevice/xv.c +++ b/libavdevice/xv.c @@ -24,7 +24,6 @@ * * TODO: * - add support to more formats - * - add support to window id specification */ #include @@ -44,9 +43,12 @@ typedef struct { GC gc; Window window; + int64_t window_id; char *window_title; int window_width, window_height; int window_x, window_y; + int dest_x, dest_y; /**< display area position */ + unsigned int dest_w, dest_h; /**< display area dimensions */ Display* display; char *display_name; @@ -56,6 +58,7 @@ typedef struct { int image_width, image_height; XShmSegmentInfo yuv_shminfo; int xv_port; + Atom wm_delete_message; } XVContext; typedef struct XVTagFormatMap @@ -103,6 +106,8 @@ static int xv_write_header(AVFormatContext *s) unsigned int num_adaptors; XvAdaptorInfo *ai; XvImageFormatValues *fv; + XColor fgcolor; + XWindowAttributes window_attrs; int num_formats = 0, j, tag, ret; AVCodecContext *encctx = s->streams[0]->codec; @@ -140,18 +145,23 @@ static int xv_write_header(AVFormatContext *s) xv->window_height = av_rescale(xv->window_height, sar.den, sar.num); } } - xv->window = XCreateSimpleWindow(xv->display, DefaultRootWindow(xv->display), - xv->window_x, xv->window_y, - xv->window_width, xv->window_height, - 0, 0, 0); - if (!xv->window_title) { - if (!(xv->window_title = av_strdup(s->filename))) { - ret = AVERROR(ENOMEM); - goto fail; + if (!xv->window_id) { + xv->window = XCreateSimpleWindow(xv->display, DefaultRootWindow(xv->display), + xv->window_x, xv->window_y, + xv->window_width, xv->window_height, + 0, 0, 0); + if (!xv->window_title) { + if (!(xv->window_title = av_strdup(s->filename))) { + ret = AVERROR(ENOMEM); + goto fail; + } } - } - XStoreName(xv->display, xv->window, xv->window_title); - XMapWindow(xv->display, xv->window); + XStoreName(xv->display, xv->window, xv->window_title); + xv->wm_delete_message = XInternAtom(xv->display, "WM_DELETE_WINDOW", False); + XSetWMProtocols(xv->display, xv->window, &xv->wm_delete_message, 1); + XMapWindow(xv->display, xv->window); + } else + xv->window = xv->window_id; if (XvQueryAdaptors(xv->display, DefaultRootWindow(xv->display), &num_adaptors, &ai) != Success) { ret = AVERROR_EXTERNAL; @@ -199,33 +209,113 @@ static int xv_write_header(AVFormatContext *s) XSync(xv->display, False); shmctl(xv->yuv_shminfo.shmid, IPC_RMID, 0); + XGetWindowAttributes(xv->display, xv->window, &window_attrs); + fgcolor.red = fgcolor.green = fgcolor.blue = 0; + fgcolor.flags = DoRed | DoGreen | DoBlue; + XAllocColor(xv->display, window_attrs.colormap, &fgcolor); + XSetForeground(xv->display, xv->gc, fgcolor.pixel); + //force display area recalculation at first frame + xv->window_width = xv->window_height = 0; + return 0; fail: xv_write_trailer(s); return ret; } +static void compute_display_area(AVFormatContext *s) +{ + XVContext *xv = s->priv_data; + AVRational sar, dar; /* sample and display aspect ratios */ + AVStream *st = s->streams[0]; + AVCodecContext *encctx = st->codec; + + /* compute overlay width and height from the codec context information */ + sar = st->sample_aspect_ratio.num ? st->sample_aspect_ratio : (AVRational){ 1, 1 }; + dar = av_mul_q(sar, (AVRational){ encctx->width, encctx->height }); + + /* we suppose the screen has a 1/1 sample aspect ratio */ + /* fit in the window */ + if (av_cmp_q(dar, (AVRational){ xv->dest_w, xv->dest_h }) > 0) { + /* fit in width */ + xv->dest_y = xv->dest_h; + xv->dest_x = 0; + xv->dest_h = av_rescale(xv->dest_w, dar.den, dar.num); + xv->dest_y -= xv->dest_h; + xv->dest_y /= 2; + } else { + /* fit in height */ + xv->dest_x = xv->dest_w; + xv->dest_y = 0; + xv->dest_w = av_rescale(xv->dest_h, dar.num, dar.den); + xv->dest_x -= xv->dest_w; + xv->dest_x /= 2; + } +} + +static int xv_repaint(AVFormatContext *s) +{ + XVContext *xv = s->priv_data; + XWindowAttributes window_attrs; + + XGetWindowAttributes(xv->display, xv->window, &window_attrs); + if (window_attrs.width != xv->window_width || window_attrs.height != xv->window_height) { + XRectangle rect[2]; + xv->dest_w = window_attrs.width; + xv->dest_h = window_attrs.height; + compute_display_area(s); + if (xv->dest_x) { + rect[0].width = rect[1].width = xv->dest_x; + rect[0].height = rect[1].height = window_attrs.height; + rect[0].y = rect[1].y = 0; + rect[0].x = 0; + rect[1].x = xv->dest_w + xv->dest_x; + XFillRectangles(xv->display, xv->window, xv->gc, rect, 2); + } + if (xv->dest_y) { + rect[0].width = rect[1].width = window_attrs.width; + rect[0].height = rect[1].height = xv->dest_y; + rect[0].x = rect[1].x = 0; + rect[0].y = 0; + rect[1].y = xv->dest_h + xv->dest_y; + XFillRectangles(xv->display, xv->window, xv->gc, rect, 2); + } + } + + if (XvShmPutImage(xv->display, xv->xv_port, xv->window, xv->gc, + xv->yuv_image, 0, 0, xv->image_width, xv->image_height, + xv->dest_x, xv->dest_y, xv->dest_w, xv->dest_h, True) != Success) { + av_log(s, AV_LOG_ERROR, "Could not copy image to XV shared memory buffer\n"); + return AVERROR_EXTERNAL; + } + return 0; +} + static int write_picture(AVFormatContext *s, AVPicture *pict) { XVContext *xv = s->priv_data; XvImage *img = xv->yuv_image; - XWindowAttributes window_attrs; uint8_t *data[3] = { img->data + img->offsets[0], img->data + img->offsets[1], img->data + img->offsets[2] }; + /* Check messages. Window might get closed. */ + if (!xv->window_id) { + XEvent event; + while (XPending(xv->display)) { + XNextEvent(xv->display, &event); + if (event.type == ClientMessage && event.xclient.data.l[0] == xv->wm_delete_message) { + av_log(xv, AV_LOG_DEBUG, "Window close event.\n"); + return AVERROR(EPIPE); + } + } + } + av_image_copy(data, img->pitches, (const uint8_t **)pict->data, pict->linesize, xv->image_format, img->width, img->height); - XGetWindowAttributes(xv->display, xv->window, &window_attrs); - if (XvShmPutImage(xv->display, xv->xv_port, xv->window, xv->gc, - xv->yuv_image, 0, 0, xv->image_width, xv->image_height, 0, 0, - window_attrs.width, window_attrs.height, True) != Success) { - av_log(s, AV_LOG_ERROR, "Could not copy image to XV shared memory buffer\n"); - return AVERROR_EXTERNAL; - } - return 0; + return xv_repaint(s); } static int xv_write_packet(AVFormatContext *s, AVPacket *pkt) @@ -246,9 +336,21 @@ static int xv_write_frame(AVFormatContext *s, int stream_index, AVFrame **frame, return write_picture(s, (AVPicture *)*frame); } +static int xv_control_message(AVFormatContext *s, int type, void *data, size_t data_size) +{ + switch(type) { + case AV_APP_TO_DEV_WINDOW_REPAINT: + return xv_repaint(s); + default: + break; + } + return AVERROR(ENOSYS); +} + #define OFFSET(x) offsetof(XVContext, x) static const AVOption options[] = { { "display_name", "set display name", OFFSET(display_name), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, + { "window_id", "set existing window id", OFFSET(window_id), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM }, { "window_size", "set window forced size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, { "window_title", "set window title", OFFSET(window_title), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, { "window_x", "set window x offset", OFFSET(window_x), AV_OPT_TYPE_INT, {.i64 = 0 }, -INT_MAX, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, @@ -262,6 +364,7 @@ static const AVClass xv_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; AVOutputFormat ff_xv_muxer = { @@ -274,6 +377,7 @@ AVOutputFormat ff_xv_muxer = { .write_packet = xv_write_packet, .write_uncoded_frame = xv_write_frame, .write_trailer = xv_write_trailer, + .control_message = xv_control_message, .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, .priv_class = &xv_class, }; diff --git a/libavfilter/Makefile b/libavfilter/Makefile index c36b67ec5..0f54381ae 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -1,29 +1,6 @@ include $(SUBDIR)../config.mak NAME = avfilter -FFLIBS = avutil -FFLIBS-$(CONFIG_ACONVERT_FILTER) += swresample -FFLIBS-$(CONFIG_AMOVIE_FILTER) += avformat avcodec -FFLIBS-$(CONFIG_ARESAMPLE_FILTER) += swresample -FFLIBS-$(CONFIG_ASYNCTS_FILTER) += avresample -FFLIBS-$(CONFIG_ATEMPO_FILTER) += avcodec -FFLIBS-$(CONFIG_DECIMATE_FILTER) += avcodec -FFLIBS-$(CONFIG_DESHAKE_FILTER) += avcodec -FFLIBS-$(CONFIG_ELBG_FILTER) += avcodec -FFLIBS-$(CONFIG_MCDEINT_FILTER) += avcodec -FFLIBS-$(CONFIG_MOVIE_FILTER) += avformat avcodec -FFLIBS-$(CONFIG_MP_FILTER) += avcodec -FFLIBS-$(CONFIG_PAN_FILTER) += swresample -FFLIBS-$(CONFIG_PP_FILTER) += postproc -FFLIBS-$(CONFIG_REMOVELOGO_FILTER) += avformat avcodec swscale -FFLIBS-$(CONFIG_RESAMPLE_FILTER) += avresample -FFLIBS-$(CONFIG_SAB_FILTER) += swscale -FFLIBS-$(CONFIG_SCALE_FILTER) += swscale -FFLIBS-$(CONFIG_SHOWSPECTRUM_FILTER) += avcodec -FFLIBS-$(CONFIG_SMARTBLUR_FILTER) += swscale -FFLIBS-$(CONFIG_SUBTITLES_FILTER) += avformat avcodec -EBUR128LIBS-$(CONFIG_SWRESAMPLE) = swresample -FFLIBS-$(CONFIG_EBUR128_FILTER) += $(EBUR128LIBS-yes) HEADERS = asrc_abuffer.h \ avcodec.h \ @@ -65,14 +42,14 @@ OBJS-$(CONFIG_AMIX_FILTER) += af_amix.o OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o OBJS-$(CONFIG_APAD_FILTER) += af_apad.o OBJS-$(CONFIG_APERMS_FILTER) += f_perms.o -OBJS-$(CONFIG_APHASER_FILTER) += af_aphaser.o +OBJS-$(CONFIG_APHASER_FILTER) += af_aphaser.o generate_wave_table.o OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o OBJS-$(CONFIG_ASELECT_FILTER) += f_select.o OBJS-$(CONFIG_ASENDCMD_FILTER) += f_sendcmd.o OBJS-$(CONFIG_ASETNSAMPLES_FILTER) += af_asetnsamples.o OBJS-$(CONFIG_ASETPTS_FILTER) += setpts.o OBJS-$(CONFIG_ASETRATE_FILTER) += af_asetrate.o -OBJS-$(CONFIG_ASETTB_FILTER) += f_settb.o +OBJS-$(CONFIG_ASETTB_FILTER) += settb.o OBJS-$(CONFIG_ASHOWINFO_FILTER) += af_ashowinfo.o OBJS-$(CONFIG_ASPLIT_FILTER) += split.o OBJS-$(CONFIG_ASTATS_FILTER) += af_astats.o @@ -85,12 +62,14 @@ OBJS-$(CONFIG_BANDPASS_FILTER) += af_biquads.o OBJS-$(CONFIG_BANDREJECT_FILTER) += af_biquads.o OBJS-$(CONFIG_BASS_FILTER) += af_biquads.o OBJS-$(CONFIG_BIQUAD_FILTER) += af_biquads.o +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_EARWAX_FILTER) += af_earwax.o OBJS-$(CONFIG_EBUR128_FILTER) += f_ebur128.o OBJS-$(CONFIG_EQUALIZER_FILTER) += af_biquads.o +OBJS-$(CONFIG_FLANGER_FILTER) += af_flanger.o generate_wave_table.o OBJS-$(CONFIG_HIGHPASS_FILTER) += af_biquads.o OBJS-$(CONFIG_JOIN_FILTER) += af_join.o OBJS-$(CONFIG_LADSPA_FILTER) += af_ladspa.o @@ -152,6 +131,7 @@ OBJS-$(CONFIG_HFLIP_FILTER) += vf_hflip.o OBJS-$(CONFIG_HISTEQ_FILTER) += vf_histeq.o OBJS-$(CONFIG_HISTOGRAM_FILTER) += vf_histogram.o OBJS-$(CONFIG_HQDN3D_FILTER) += vf_hqdn3d.o +OBJS-$(CONFIG_HQX_FILTER) += vf_hqx.o OBJS-$(CONFIG_HUE_FILTER) += vf_hue.o OBJS-$(CONFIG_IDET_FILTER) += vf_idet.o OBJS-$(CONFIG_IL_FILTER) += vf_il.o @@ -193,8 +173,10 @@ OBJS-$(CONFIG_SETDAR_FILTER) += vf_aspect.o OBJS-$(CONFIG_SETFIELD_FILTER) += vf_setfield.o OBJS-$(CONFIG_SETPTS_FILTER) += setpts.o OBJS-$(CONFIG_SETSAR_FILTER) += vf_aspect.o -OBJS-$(CONFIG_SETTB_FILTER) += f_settb.o +OBJS-$(CONFIG_SETTB_FILTER) += settb.o OBJS-$(CONFIG_SHOWINFO_FILTER) += vf_showinfo.o +OBJS-$(CONFIG_SHUFFLEPLANES_FILTER) += vf_shuffleplanes.o +OBJS-$(CONFIG_SIGNALSTATS_FILTER) += vf_signalstats.o OBJS-$(CONFIG_SMARTBLUR_FILTER) += vf_smartblur.o OBJS-$(CONFIG_SPLIT_FILTER) += split.o OBJS-$(CONFIG_SPP_FILTER) += vf_spp.o @@ -216,6 +198,7 @@ OBJS-$(CONFIG_VIGNETTE_FILTER) += vf_vignette.o OBJS-$(CONFIG_W3FDIF_FILTER) += vf_w3fdif.o OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o OBJS-$(CONFIG_ZMQ_FILTER) += f_zmq.o +OBJS-$(CONFIG_ZOOMPAN_FILTER) += vf_zoompan.o OBJS-$(CONFIG_CELLAUTO_FILTER) += vsrc_cellauto.o OBJS-$(CONFIG_COLOR_FILTER) += vsrc_testsrc.o @@ -245,6 +228,7 @@ OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_uspp.o # multimedia filters OBJS-$(CONFIG_AVECTORSCOPE_FILTER) += avf_avectorscope.o OBJS-$(CONFIG_CONCAT_FILTER) += avf_concat.o +OBJS-$(CONFIG_SHOWCQT_FILTER) += avf_showcqt.o OBJS-$(CONFIG_SHOWSPECTRUM_FILTER) += avf_showspectrum.o OBJS-$(CONFIG_SHOWWAVES_FILTER) += avf_showwaves.o diff --git a/libavfilter/aeval.c b/libavfilter/aeval.c index 2790cee6f..45629a98e 100644 --- a/libavfilter/aeval.c +++ b/libavfilter/aeval.c @@ -105,7 +105,7 @@ static int parse_channel_expressions(AVFilterContext *ctx, { EvalContext *eval = ctx->priv; char *args1 = av_strdup(eval->exprs); - char *expr, *last_expr, *buf; + char *expr, *last_expr = NULL, *buf; double (* const *func1)(void *, double) = NULL; const char * const *func1_names = NULL; int i, ret = 0; diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c index 7140b6c74..1eef70d8c 100644 --- a/libavfilter/af_amix.c +++ b/libavfilter/af_amix.c @@ -249,7 +249,7 @@ static int config_output(AVFilterLink *outlink) memset(s->input_state, INPUT_ON, s->nb_inputs); s->active_inputs = s->nb_inputs; - s->input_scale = av_mallocz(s->nb_inputs * sizeof(*s->input_scale)); + s->input_scale = av_mallocz_array(s->nb_inputs, sizeof(*s->input_scale)); if (!s->input_scale) return AVERROR(ENOMEM); s->scale_norm = s->active_inputs; diff --git a/libavfilter/af_aphaser.c b/libavfilter/af_aphaser.c index 0fc45eab4..9d8f696bd 100644 --- a/libavfilter/af_aphaser.c +++ b/libavfilter/af_aphaser.c @@ -28,12 +28,7 @@ #include "audio.h" #include "avfilter.h" #include "internal.h" - -enum WaveType { - WAVE_SIN, - WAVE_TRI, - WAVE_NB, -}; +#include "generate_wave_table.h" typedef struct AudioPhaserContext { const AVClass *class; @@ -118,65 +113,6 @@ static int query_formats(AVFilterContext *ctx) return 0; } -static void generate_wave_table(enum WaveType wave_type, enum AVSampleFormat sample_fmt, - void *table, int table_size, - double min, double max, double phase) -{ - uint32_t i, phase_offset = phase / M_PI / 2 * table_size + 0.5; - - for (i = 0; i < table_size; i++) { - uint32_t point = (i + phase_offset) % table_size; - double d; - - switch (wave_type) { - case WAVE_SIN: - d = (sin((double)point / table_size * 2 * M_PI) + 1) / 2; - break; - case WAVE_TRI: - d = (double)point * 2 / table_size; - switch (4 * point / table_size) { - case 0: d = d + 0.5; break; - case 1: - case 2: d = 1.5 - d; break; - case 3: d = d - 1.5; break; - } - break; - default: - av_assert0(0); - } - - d = d * (max - min) + min; - switch (sample_fmt) { - case AV_SAMPLE_FMT_FLT: { - float *fp = (float *)table; - *fp++ = (float)d; - table = fp; - continue; } - case AV_SAMPLE_FMT_DBL: { - double *dp = (double *)table; - *dp++ = d; - table = dp; - continue; } - } - - d += d < 0 ? -0.5 : 0.5; - switch (sample_fmt) { - case AV_SAMPLE_FMT_S16: { - int16_t *sp = table; - *sp++ = (int16_t)d; - table = sp; - continue; } - case AV_SAMPLE_FMT_S32: { - int32_t *ip = table; - *ip++ = (int32_t)d; - table = ip; - continue; } - default: - av_assert0(0); - } - } -} - #define MOD(a, b) (((a) >= (b)) ? (a) - (b) : (a)) #define PHASER_PLANAR(name, type) \ @@ -269,14 +205,14 @@ static int config_output(AVFilterLink *outlink) p->delay_buffer_length = p->delay * 0.001 * inlink->sample_rate + 0.5; p->delay_buffer = av_calloc(p->delay_buffer_length, sizeof(*p->delay_buffer) * inlink->channels); p->modulation_buffer_length = inlink->sample_rate / p->speed + 0.5; - p->modulation_buffer = av_malloc(p->modulation_buffer_length * sizeof(*p->modulation_buffer)); + p->modulation_buffer = av_malloc_array(p->modulation_buffer_length, sizeof(*p->modulation_buffer)); if (!p->modulation_buffer || !p->delay_buffer) return AVERROR(ENOMEM); - generate_wave_table(p->type, AV_SAMPLE_FMT_S32, - p->modulation_buffer, p->modulation_buffer_length, - 1., p->delay_buffer_length, M_PI / 2.0); + ff_generate_wave_table(p->type, AV_SAMPLE_FMT_S32, + p->modulation_buffer, p->modulation_buffer_length, + 1., p->delay_buffer_length, M_PI / 2.0); p->delay_pos = p->modulation_pos = 0; diff --git a/libavfilter/af_asetnsamples.c b/libavfilter/af_asetnsamples.c index fbcf27574..e83064311 100644 --- a/libavfilter/af_asetnsamples.c +++ b/libavfilter/af_asetnsamples.c @@ -116,7 +116,7 @@ static int push_samples(AVFilterLink *outlink) outsamples->pts = asns->next_out_pts; if (asns->next_out_pts != AV_NOPTS_VALUE) - asns->next_out_pts += nb_out_samples; + asns->next_out_pts += av_rescale_q(nb_out_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); ret = ff_filter_frame(outlink, outsamples); if (ret < 0) diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c index 783f9a6e3..ee95029a3 100644 --- a/libavfilter/af_ashowinfo.c +++ b/libavfilter/af_ashowinfo.c @@ -30,7 +30,10 @@ #include "libavutil/attributes.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" +#include "libavutil/downmix_info.h" +#include "libavutil/intreadwrite.h" #include "libavutil/mem.h" +#include "libavutil/replaygain.h" #include "libavutil/timestamp.h" #include "libavutil/samplefmt.h" @@ -51,6 +54,99 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->plane_checksums); } +static void dump_matrixenc(AVFilterContext *ctx, AVFrameSideData *sd) +{ + enum AVMatrixEncoding enc; + + av_log(ctx, AV_LOG_INFO, "matrix encoding: "); + + if (sd->size < sizeof(enum AVMatrixEncoding)) { + av_log(ctx, AV_LOG_INFO, "invalid data"); + return; + } + + enc = *(enum AVMatrixEncoding *)sd->data; + switch (enc) { + case AV_MATRIX_ENCODING_NONE: av_log(ctx, AV_LOG_INFO, "none"); break; + case AV_MATRIX_ENCODING_DOLBY: av_log(ctx, AV_LOG_INFO, "Dolby Surround"); break; + case AV_MATRIX_ENCODING_DPLII: av_log(ctx, AV_LOG_INFO, "Dolby Pro Logic II"); break; + case AV_MATRIX_ENCODING_DPLIIX: av_log(ctx, AV_LOG_INFO, "Dolby Pro Logic IIx"); break; + case AV_MATRIX_ENCODING_DPLIIZ: av_log(ctx, AV_LOG_INFO, "Dolby Pro Logic IIz"); break; + case AV_MATRIX_ENCODING_DOLBYEX: av_log(ctx, AV_LOG_INFO, "Dolby EX"); break; + case AV_MATRIX_ENCODING_DOLBYHEADPHONE: av_log(ctx, AV_LOG_INFO, "Dolby Headphone"); break; + default: av_log(ctx, AV_LOG_WARNING, "unknown"); break; + } +} + +static void dump_downmix(AVFilterContext *ctx, AVFrameSideData *sd) +{ + AVDownmixInfo *di; + + av_log(ctx, AV_LOG_INFO, "downmix: "); + if (sd->size < sizeof(*di)) { + av_log(ctx, AV_LOG_INFO, "invalid data"); + return; + } + + di = (AVDownmixInfo *)sd->data; + + av_log(ctx, AV_LOG_INFO, "preferred downmix type - "); + switch (di->preferred_downmix_type) { + case AV_DOWNMIX_TYPE_LORO: av_log(ctx, AV_LOG_INFO, "Lo/Ro"); break; + case AV_DOWNMIX_TYPE_LTRT: av_log(ctx, AV_LOG_INFO, "Lt/Rt"); break; + case AV_DOWNMIX_TYPE_DPLII: av_log(ctx, AV_LOG_INFO, "Dolby Pro Logic II"); break; + default: av_log(ctx, AV_LOG_WARNING, "unknown"); break; + } + + av_log(ctx, AV_LOG_INFO, " Mix levels: center %f (%f ltrt) - " + "surround %f (%f ltrt) - lfe %f", + di->center_mix_level, di->center_mix_level_ltrt, + di->surround_mix_level, di->surround_mix_level_ltrt, + di->lfe_mix_level); +} + +static void print_gain(AVFilterContext *ctx, const char *str, int32_t gain) +{ + av_log(ctx, AV_LOG_INFO, "%s - ", str); + if (gain == INT32_MIN) + av_log(ctx, AV_LOG_INFO, "unknown"); + else + av_log(ctx, AV_LOG_INFO, "%f", gain / 100000.0f); + av_log(ctx, AV_LOG_INFO, ", "); +} + +static void print_peak(AVFilterContext *ctx, const char *str, uint32_t peak) +{ + av_log(ctx, AV_LOG_INFO, "%s - ", str); + if (!peak) + av_log(ctx, AV_LOG_INFO, "unknown"); + else + av_log(ctx, AV_LOG_INFO, "%f", (float)peak / UINT32_MAX); + av_log(ctx, AV_LOG_INFO, ", "); +} + +static void dump_replaygain(AVFilterContext *ctx, AVFrameSideData *sd) +{ + AVReplayGain *rg; + + av_log(ctx, AV_LOG_INFO, "replaygain: "); + if (sd->size < sizeof(*rg)) { + av_log(ctx, AV_LOG_INFO, "invalid data"); + return; + } + rg = (AVReplayGain*)sd->data; + + print_gain(ctx, "track gain", rg->track_gain); + print_peak(ctx, "track peak", rg->track_peak); + print_gain(ctx, "album gain", rg->album_gain); + print_peak(ctx, "album peak", rg->album_peak); +} + +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); +} + static int filter_frame(AVFilterLink *inlink, AVFrame *buf) { AVFilterContext *ctx = inlink->dst; @@ -83,7 +179,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) av_log(ctx, AV_LOG_INFO, "n:%"PRId64" pts:%s pts_time:%s pos:%"PRId64" " "fmt:%s channels:%d chlayout:%s rate:%d nb_samples:%d " - "checksum:%08X ", + "checksum:%08"PRIX32" ", inlink->frame_count, av_ts2str(buf->pts), av_ts2timestr(buf->pts, &inlink->time_base), av_frame_get_pkt_pos(buf), @@ -93,9 +189,23 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) av_log(ctx, AV_LOG_INFO, "plane_checksums: [ "); for (i = 0; i < planes; i++) - av_log(ctx, AV_LOG_INFO, "%08X ", s->plane_checksums[i]); + av_log(ctx, AV_LOG_INFO, "%08"PRIX32" ", s->plane_checksums[i]); av_log(ctx, AV_LOG_INFO, "]\n"); + for (i = 0; i < buf->nb_side_data; i++) { + AVFrameSideData *sd = buf->side_data[i]; + + av_log(ctx, AV_LOG_INFO, " side data - "); + switch (sd->type) { + 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; + default: dump_unknown (ctx, sd); break; + } + + av_log(ctx, AV_LOG_INFO, "\n"); + } + return ff_filter_frame(inlink->dst->outputs[0], buf); } diff --git a/libavfilter/af_bs2b.c b/libavfilter/af_bs2b.c new file mode 100644 index 000000000..3dd0bcd99 --- /dev/null +++ b/libavfilter/af_bs2b.c @@ -0,0 +1,222 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Bauer stereo-to-binaural filter + */ + +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "audio.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" + +typedef struct Bs2bContext { + const AVClass *class; + + int profile; + int fcut; + int feed; + + t_bs2bdp bs2bp; + + void (*filter)(t_bs2bdp bs2bdp, uint8_t *sample, int n); +} Bs2bContext; + +#define OFFSET(x) offsetof(Bs2bContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM + +static const AVOption options[] = { + { "profile", "Apply a pre-defined crossfeed level", + OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = BS2B_DEFAULT_CLEVEL }, 0, INT_MAX, A, "profile" }, + { "default", "default profile", 0, AV_OPT_TYPE_CONST, { .i64 = BS2B_DEFAULT_CLEVEL }, 0, 0, A, "profile" }, + { "cmoy", "Chu Moy circuit", 0, AV_OPT_TYPE_CONST, { .i64 = BS2B_CMOY_CLEVEL }, 0, 0, A, "profile" }, + { "jmeier", "Jan Meier circuit", 0, AV_OPT_TYPE_CONST, { .i64 = BS2B_JMEIER_CLEVEL }, 0, 0, A, "profile" }, + { "fcut", "Set cut frequency (in Hz)", + OFFSET(fcut), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BS2B_MAXFCUT, A }, + { "feed", "Set feed level (in Hz)", + OFFSET(feed), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BS2B_MAXFEED, A }, + { NULL }, +}; + +static const AVClass bs2b_class = { + .class_name = "bs2b filter", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static av_cold int init(AVFilterContext *ctx) +{ + Bs2bContext *bs2b = ctx->priv; + + if (!(bs2b->bs2bp = bs2b_open())) + return AVERROR(ENOMEM); + + bs2b_set_level(bs2b->bs2bp, bs2b->profile); + + if (bs2b->fcut) + bs2b_set_level_fcut(bs2b->bs2bp, bs2b->fcut); + + if (bs2b->feed) + bs2b_set_level_feed(bs2b->bs2bp, bs2b->feed); + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + Bs2bContext *bs2b = ctx->priv; + + if (bs2b->bs2bp) + bs2b_close(bs2b->bs2bp); +} + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *layouts = NULL; + + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_U8, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_S32, + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_DBL, + AV_SAMPLE_FMT_NONE, + }; + + if (ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO) != 0) + return AVERROR(ENOMEM); + ff_set_common_channel_layouts(ctx, layouts); + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ff_set_common_formats(ctx, formats); + + formats = ff_all_samplerates(); + if (!formats) + return AVERROR(ENOMEM); + ff_set_common_samplerates(ctx, formats); + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + int ret; + AVFrame *out_frame; + + Bs2bContext *bs2b = inlink->dst->priv; + AVFilterLink *outlink = inlink->dst->outputs[0]; + + if (av_frame_is_writable(frame)) { + out_frame = frame; + } else { + out_frame = ff_get_audio_buffer(inlink, frame->nb_samples); + if (!out_frame) + return AVERROR(ENOMEM); + av_frame_copy(out_frame, frame); + ret = av_frame_copy_props(out_frame, frame); + if (ret < 0) { + av_frame_free(&out_frame); + av_frame_free(&frame); + return ret; + } + } + + bs2b->filter(bs2b->bs2bp, out_frame->extended_data[0], out_frame->nb_samples); + + if (frame != out_frame) + av_frame_free(&frame); + + return ff_filter_frame(outlink, out_frame); +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + Bs2bContext *bs2b = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + + int srate = inlink->sample_rate; + + switch (inlink->format) { + case AV_SAMPLE_FMT_U8: + bs2b->filter = bs2b_cross_feed_u8; + break; + case AV_SAMPLE_FMT_S16: + bs2b->filter = (void*)bs2b_cross_feed_s16; + break; + case AV_SAMPLE_FMT_S32: + bs2b->filter = (void*)bs2b_cross_feed_s32; + break; + case AV_SAMPLE_FMT_FLT: + bs2b->filter = (void*)bs2b_cross_feed_f; + break; + case AV_SAMPLE_FMT_DBL: + bs2b->filter = (void*)bs2b_cross_feed_d; + break; + default: + return AVERROR_BUG; + } + + if ((srate < BS2B_MINSRATE) || (srate > BS2B_MAXSRATE)) + return AVERROR(ENOSYS); + + bs2b_set_srate(bs2b->bs2bp, srate); + + return 0; +} + +static const AVFilterPad bs2b_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad bs2b_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_af_bs2b = { + .name = "bs2b", + .description = NULL_IF_CONFIG_SMALL("Bauer stereo-to-binaural filter."), + .query_formats = query_formats, + .priv_size = sizeof(Bs2bContext), + .priv_class = &bs2b_class, + .init = init, + .uninit = uninit, + .inputs = bs2b_inputs, + .outputs = bs2b_outputs, +}; diff --git a/libavfilter/af_channelmap.c b/libavfilter/af_channelmap.c index dac19b129..b3b5aca02 100644 --- a/libavfilter/af_channelmap.c +++ b/libavfilter/af_channelmap.c @@ -312,7 +312,7 @@ static int channelmap_filter_frame(AVFilterLink *inlink, AVFrame *buf) if (nch_out > nch_in) { if (nch_out > FF_ARRAY_ELEMS(buf->data)) { uint8_t **new_extended_data = - av_mallocz(nch_out * sizeof(*buf->extended_data)); + av_mallocz_array(nch_out, sizeof(*buf->extended_data)); if (!new_extended_data) { av_frame_free(&buf); return AVERROR(ENOMEM); diff --git a/libavfilter/af_compand.c b/libavfilter/af_compand.c index 60f8abe20..4ca73c452 100644 --- a/libavfilter/af_compand.c +++ b/libavfilter/af_compand.c @@ -303,6 +303,7 @@ static int compand_drain(AVFilterLink *outlink) s->pts += av_rescale_q(frame->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); + av_assert0(channels > 0); for (chan = 0; chan < channels; chan++) { AVFrame *delay_frame = s->delay_frame; double *dbuf = (double *)delay_frame->extended_data[chan]; diff --git a/libavfilter/af_flanger.c b/libavfilter/af_flanger.c new file mode 100644 index 000000000..5ff378667 --- /dev/null +++ b/libavfilter/af_flanger.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2006 Rob Sykes + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/opt.h" +#include "libavutil/samplefmt.h" +#include "avfilter.h" +#include "audio.h" +#include "internal.h" +#include "generate_wave_table.h" + +#define INTERPOLATION_LINEAR 0 +#define INTERPOLATION_QUADRATIC 1 + +typedef struct FlangerContext { + const AVClass *class; + double delay_min; + double delay_depth; + double feedback_gain; + double delay_gain; + double speed; + int wave_shape; + double channel_phase; + int interpolation; + double in_gain; + int max_samples; + uint8_t **delay_buffer; + int delay_buf_pos; + double *delay_last; + float *lfo; + int lfo_length; + int lfo_pos; +} FlangerContext; + +#define OFFSET(x) offsetof(FlangerContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption flanger_options[] = { + { "delay", "base delay in milliseconds", OFFSET(delay_min), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 30, A }, + { "depth", "added swept delay in milliseconds", OFFSET(delay_depth), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, 10, A }, + { "regen", "percentage regeneration (delayed signal feedback)", OFFSET(feedback_gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -95, 95, A }, + { "width", "percentage of delayed signal mixed with original", OFFSET(delay_gain), AV_OPT_TYPE_DOUBLE, {.dbl=71}, 0, 100, A }, + { "speed", "sweeps per second (Hz)", OFFSET(speed), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0.1, 10, A }, + { "shape", "swept wave shape", OFFSET(wave_shape), AV_OPT_TYPE_INT, {.i64=WAVE_SIN}, WAVE_SIN, WAVE_NB-1, A, "type" }, + { "triangular", NULL, 0, AV_OPT_TYPE_CONST, {.i64=WAVE_TRI}, 0, 0, A, "type" }, + { "t", NULL, 0, AV_OPT_TYPE_CONST, {.i64=WAVE_TRI}, 0, 0, A, "type" }, + { "sinusoidal", NULL, 0, AV_OPT_TYPE_CONST, {.i64=WAVE_SIN}, 0, 0, A, "type" }, + { "s", NULL, 0, AV_OPT_TYPE_CONST, {.i64=WAVE_SIN}, 0, 0, A, "type" }, + { "phase", "swept wave percentage phase-shift for multi-channel", OFFSET(channel_phase), AV_OPT_TYPE_DOUBLE, {.dbl=25}, 0, 100, A }, + { "interp", "delay-line interpolation", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, A, "itype" }, + { "linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATION_LINEAR}, 0, 0, A, "itype" }, + { "quadratic", NULL, 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATION_QUADRATIC}, 0, 0, A, "itype" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(flanger); + +static int init(AVFilterContext *ctx) +{ + FlangerContext *s = ctx->priv; + + s->feedback_gain /= 100; + s->delay_gain /= 100; + s->channel_phase /= 100; + s->delay_min /= 1000; + s->delay_depth /= 1000; + s->in_gain = 1 / (1 + s->delay_gain); + s->delay_gain /= 1 + s->delay_gain; + s->delay_gain *= 1 - fabs(s->feedback_gain); + + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterChannelLayouts *layouts; + AVFilterFormats *formats; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE + }; + + layouts = ff_all_channel_layouts(); + if (!layouts) + return AVERROR(ENOMEM); + ff_set_common_channel_layouts(ctx, layouts); + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ff_set_common_formats(ctx, formats); + + formats = ff_all_samplerates(); + if (!formats) + return AVERROR(ENOMEM); + ff_set_common_samplerates(ctx, formats); + + return 0; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + FlangerContext *s = ctx->priv; + + s->max_samples = (s->delay_min + s->delay_depth) * inlink->sample_rate + 2.5; + s->lfo_length = inlink->sample_rate / s->speed; + s->delay_last = av_calloc(inlink->channels, sizeof(*s->delay_last)); + s->lfo = av_calloc(s->lfo_length, sizeof(*s->lfo)); + if (!s->lfo || !s->delay_last) + return AVERROR(ENOMEM); + + ff_generate_wave_table(s->wave_shape, AV_SAMPLE_FMT_FLT, s->lfo, s->lfo_length, + floor(s->delay_min * inlink->sample_rate + 0.5), + s->max_samples - 2., 3 * M_PI_2); + + return av_samples_alloc_array_and_samples(&s->delay_buffer, NULL, + inlink->channels, s->max_samples, + inlink->format, 0); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + FlangerContext *s = ctx->priv; + AVFrame *out_frame; + int chan, i; + + if (av_frame_is_writable(frame)) { + out_frame = frame; + } else { + out_frame = ff_get_audio_buffer(inlink, frame->nb_samples); + if (!out_frame) + return AVERROR(ENOMEM); + av_frame_copy_props(out_frame, frame); + } + + for (i = 0; i < frame->nb_samples; i++) { + + s->delay_buf_pos = (s->delay_buf_pos + s->max_samples - 1) % s->max_samples; + + for (chan = 0; chan < inlink->channels; chan++) { + double *src = (double *)frame->extended_data[chan]; + double *dst = (double *)out_frame->extended_data[chan]; + double delayed_0, delayed_1; + double delayed; + double in, out; + int channel_phase = chan * s->lfo_length * s->channel_phase + .5; + double delay = s->lfo[(s->lfo_pos + channel_phase) % s->lfo_length]; + int int_delay = (int)delay; + double frac_delay = modf(delay, &delay); + double *delay_buffer = (double *)s->delay_buffer[chan]; + + in = src[i]; + delay_buffer[s->delay_buf_pos] = in + s->delay_last[chan] * + s->feedback_gain; + delayed_0 = delay_buffer[(s->delay_buf_pos + int_delay++) % s->max_samples]; + delayed_1 = delay_buffer[(s->delay_buf_pos + int_delay++) % s->max_samples]; + + if (s->interpolation == INTERPOLATION_LINEAR) { + delayed = delayed_0 + (delayed_1 - delayed_0) * frac_delay; + } else { + double a, b; + double delayed_2 = delay_buffer[(s->delay_buf_pos + int_delay++) % s->max_samples]; + delayed_2 -= delayed_0; + delayed_1 -= delayed_0; + a = delayed_2 * .5 - delayed_1; + b = delayed_1 * 2 - delayed_2 *.5; + delayed = delayed_0 + (a * frac_delay + b) * frac_delay; + } + + s->delay_last[chan] = delayed; + out = in * s->in_gain + delayed * s->delay_gain; + dst[i] = out; + } + s->lfo_pos = (s->lfo_pos + 1) % s->lfo_length; + } + + if (frame != out_frame) + av_frame_free(&frame); + + return ff_filter_frame(ctx->outputs[0], out_frame); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + FlangerContext *s = ctx->priv; + + av_freep(&s->lfo); + av_freep(&s->delay_last); + + if (s->delay_buffer) + av_freep(&s->delay_buffer[0]); + av_freep(&s->delay_buffer); +} + +static const AVFilterPad flanger_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_input, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad flanger_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_flanger = { + .name = "flanger", + .description = NULL_IF_CONFIG_SMALL("Apply a flanging effect to the audio."), + .query_formats = query_formats, + .priv_size = sizeof(FlangerContext), + .priv_class = &flanger_class, + .init = init, + .uninit = uninit, + .inputs = flanger_inputs, + .outputs = flanger_outputs, +}; diff --git a/libavfilter/af_resample.c b/libavfilter/af_resample.c index 9d1b1c456..03467a747 100644 --- a/libavfilter/af_resample.c +++ b/libavfilter/af_resample.c @@ -179,10 +179,7 @@ static int request_frame(AVFilterLink *outlink) /* flush the lavr delay buffer */ if (ret == AVERROR_EOF && s->avr) { AVFrame *frame; - int nb_samples = av_rescale_rnd(avresample_get_delay(s->avr), - outlink->sample_rate, - ctx->inputs[0]->sample_rate, - AV_ROUND_UP); + int nb_samples = avresample_get_out_samples(s->avr, 0); if (!nb_samples) return ret; @@ -218,9 +215,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) /* maximum possible samples lavr can output */ delay = avresample_get_delay(s->avr); - nb_samples = av_rescale_rnd(in->nb_samples + delay, - outlink->sample_rate, inlink->sample_rate, - AV_ROUND_UP); + nb_samples = avresample_get_out_samples(s->avr, in->nb_samples); out = ff_get_audio_buffer(outlink, nb_samples); if (!out) { diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c index 4ec78b148..e06c3b395 100644 --- a/libavfilter/af_volume.c +++ b/libavfilter/af_volume.c @@ -28,7 +28,10 @@ #include "libavutil/common.h" #include "libavutil/eval.h" #include "libavutil/float_dsp.h" +#include "libavutil/intreadwrite.h" #include "libavutil/opt.h" +#include "libavutil/replaygain.h" + #include "audio.h" #include "avfilter.h" #include "formats.h" @@ -70,7 +73,17 @@ static const AVOption volume_options[] = { { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_ONCE}, 0, EVAL_MODE_NB-1, .flags = A|F, "eval" }, { "once", "eval volume expression once", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_ONCE}, .flags = A|F, .unit = "eval" }, { "frame", "eval volume expression per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = A|F, .unit = "eval" }, - { NULL } + { "replaygain", "Apply replaygain side data when present", + OFFSET(replaygain), AV_OPT_TYPE_INT, { .i64 = REPLAYGAIN_DROP }, REPLAYGAIN_DROP, REPLAYGAIN_ALBUM, A, "replaygain" }, + { "drop", "replaygain side data is dropped", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_DROP }, 0, 0, A, "replaygain" }, + { "ignore", "replaygain side data is ignored", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_IGNORE }, 0, 0, A, "replaygain" }, + { "track", "track gain is preferred", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_TRACK }, 0, 0, A, "replaygain" }, + { "album", "album gain is preferred", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_ALBUM }, 0, 0, A, "replaygain" }, + { "replaygain_preamp", "Apply replaygain pre-amplification", + OFFSET(replaygain_preamp), AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, -15.0, 15.0, A }, + { "replaygain_noclip", "Apply replaygain clipping prevention", + OFFSET(replaygain_noclip), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, A }, + { NULL }, }; AVFILTER_DEFINE_CLASS(volume); @@ -325,8 +338,47 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) int nb_samples = buf->nb_samples; AVFrame *out_buf; int64_t pos; + AVFrameSideData *sd = av_frame_get_side_data(buf, AV_FRAME_DATA_REPLAYGAIN); int ret; + if (sd && vol->replaygain != REPLAYGAIN_IGNORE) { + if (vol->replaygain != REPLAYGAIN_DROP) { + AVReplayGain *replaygain = (AVReplayGain*)sd->data; + int32_t gain = 100000; + uint32_t peak = 100000; + float g, p; + + if (vol->replaygain == REPLAYGAIN_TRACK && + replaygain->track_gain != INT32_MIN) { + gain = replaygain->track_gain; + + if (replaygain->track_peak != 0) + peak = replaygain->track_peak; + } else if (replaygain->album_gain != INT32_MIN) { + gain = replaygain->album_gain; + + if (replaygain->album_peak != 0) + peak = replaygain->album_peak; + } else { + av_log(inlink->dst, AV_LOG_WARNING, "Both ReplayGain gain " + "values are unknown.\n"); + } + g = gain / 100000.0f; + p = peak / 100000.0f; + + av_log(inlink->dst, AV_LOG_VERBOSE, + "Using gain %f dB from replaygain side data.\n", g); + + vol->volume = pow(10, (g + vol->replaygain_preamp) / 20); + if (vol->replaygain_noclip) + vol->volume = FFMIN(vol->volume, 1.0 / p); + vol->volume_i = (int)(vol->volume * 256 + 0.5); + + volume_init(vol); + } + av_frame_remove_side_data(buf, AV_FRAME_DATA_REPLAYGAIN); + } + if (isnan(vol->var_values[VAR_STARTPTS])) { vol->var_values[VAR_STARTPTS] = TS2D(buf->pts); vol->var_values[VAR_STARTT ] = TS2T(buf->pts, inlink->time_base); diff --git a/libavfilter/af_volume.h b/libavfilter/af_volume.h index 10ef6fbda..e78e042d0 100644 --- a/libavfilter/af_volume.h +++ b/libavfilter/af_volume.h @@ -58,6 +58,13 @@ enum VolumeVarName { VAR_VARS_NB }; +enum ReplayGainType { + REPLAYGAIN_DROP, + REPLAYGAIN_IGNORE, + REPLAYGAIN_TRACK, + REPLAYGAIN_ALBUM, +}; + typedef struct VolumeContext { const AVClass *class; AVFloatDSPContext fdsp; @@ -67,6 +74,9 @@ typedef struct VolumeContext { AVExpr *volume_pexpr; double var_values[VAR_VARS_NB]; + enum ReplayGainType replaygain; + double replaygain_preamp; + int replaygain_noclip; double volume; int volume_i; int channels; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index d042b64ce..18775572e 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -80,12 +80,14 @@ void avfilter_register_all(void) REGISTER_FILTER(BANDREJECT, bandreject, af); REGISTER_FILTER(BASS, bass, af); REGISTER_FILTER(BIQUAD, biquad, af); + REGISTER_FILTER(BS2B, bs2b, af); REGISTER_FILTER(CHANNELMAP, channelmap, af); REGISTER_FILTER(CHANNELSPLIT, channelsplit, af); REGISTER_FILTER(COMPAND, compand, af); REGISTER_FILTER(EARWAX, earwax, af); REGISTER_FILTER(EBUR128, ebur128, af); REGISTER_FILTER(EQUALIZER, equalizer, af); + REGISTER_FILTER(FLANGER, flanger, af); REGISTER_FILTER(HIGHPASS, highpass, af); REGISTER_FILTER(JOIN, join, af); REGISTER_FILTER(LADSPA, ladspa, af); @@ -147,6 +149,7 @@ void avfilter_register_all(void) REGISTER_FILTER(HISTEQ, histeq, vf); REGISTER_FILTER(HISTOGRAM, histogram, vf); REGISTER_FILTER(HQDN3D, hqdn3d, vf); + REGISTER_FILTER(HQX, hqx, vf); REGISTER_FILTER(HUE, hue, vf); REGISTER_FILTER(IDET, idet, vf); REGISTER_FILTER(IL, il, vf); @@ -189,6 +192,8 @@ void avfilter_register_all(void) REGISTER_FILTER(SETSAR, setsar, vf); REGISTER_FILTER(SETTB, settb, vf); REGISTER_FILTER(SHOWINFO, showinfo, vf); + REGISTER_FILTER(SHUFFLEPLANES, shuffleplanes, vf); + REGISTER_FILTER(SIGNALSTATS, signalstats, vf); REGISTER_FILTER(SMARTBLUR, smartblur, vf); REGISTER_FILTER(SPLIT, split, vf); REGISTER_FILTER(SPP, spp, vf); @@ -210,6 +215,7 @@ void avfilter_register_all(void) REGISTER_FILTER(W3FDIF, w3fdif, vf); REGISTER_FILTER(YADIF, yadif, vf); REGISTER_FILTER(ZMQ, zmq, vf); + REGISTER_FILTER(ZOOMPAN, zoompan, vf); REGISTER_FILTER(CELLAUTO, cellauto, vsrc); REGISTER_FILTER(COLOR, color, vsrc); @@ -229,6 +235,7 @@ void avfilter_register_all(void) /* multimedia filters */ REGISTER_FILTER(AVECTORSCOPE, avectorscope, avf); REGISTER_FILTER(CONCAT, concat, avf); + REGISTER_FILTER(SHOWCQT, showcqt, avf); REGISTER_FILTER(SHOWSPECTRUM, showspectrum, avf); REGISTER_FILTER(SHOWWAVES, showwaves, avf); diff --git a/libavfilter/audio.c b/libavfilter/audio.c index 315c273c2..1e1d8e04d 100644 --- a/libavfilter/audio.c +++ b/libavfilter/audio.c @@ -124,9 +124,9 @@ AVFilterBufferRef* avfilter_get_audio_buffer_ref_from_arrays_channels(uint8_t ** samples->linesize[0] = samplesref->linesize[0] = linesize; if (planes > FF_ARRAY_ELEMS(samples->data)) { - samples-> extended_data = av_mallocz(sizeof(*samples->extended_data) * + samples-> extended_data = av_mallocz_array(sizeof(*samples->extended_data), planes); - samplesref->extended_data = av_mallocz(sizeof(*samplesref->extended_data) * + samplesref->extended_data = av_mallocz_array(sizeof(*samplesref->extended_data), planes); if (!samples->extended_data || !samplesref->extended_data) diff --git a/libavfilter/avcodec.c b/libavfilter/avcodec.c index 605e5d24d..ba11a2549 100644 --- a/libavfilter/avcodec.c +++ b/libavfilter/avcodec.c @@ -116,7 +116,7 @@ int avfilter_copy_buf_props(AVFrame *dst, const AVFilterBufferRef *src) 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)); + dst->extended_data = av_mallocz_array(planes, sizeof(*dst->extended_data)); if (!dst->extended_data) return AVERROR(ENOMEM); memcpy(dst->extended_data, src->extended_data, diff --git a/libavfilter/avf_showcqt.c b/libavfilter/avf_showcqt.c new file mode 100644 index 000000000..60e8129cb --- /dev/null +++ b/libavfilter/avf_showcqt.c @@ -0,0 +1,696 @@ +/* + * Copyright (c) 2014 Muhammad Faiz + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavcodec/avfft.h" +#include "libavutil/avassert.h" +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" +#include "libavutil/xga_font_data.h" +#include "libavutil/qsort.h" +#include "libavutil/time.h" +#include "avfilter.h" +#include "internal.h" + +#include +#include + +#if CONFIG_LIBFREETYPE +#include +#include FT_FREETYPE_H +#endif + +/* this filter is designed to do 16 bins/semitones constant Q transform with Brown-Puckette algorithm + * start from E0 to D#10 (10 octaves) + * so there are 16 bins/semitones * 12 semitones/octaves * 10 octaves = 1920 bins + * match with full HD resolution */ + +#define VIDEO_WIDTH 1920 +#define VIDEO_HEIGHT 1080 +#define FONT_HEIGHT 32 +#define SPECTOGRAM_HEIGHT ((VIDEO_HEIGHT-FONT_HEIGHT)/2) +#define SPECTOGRAM_START (VIDEO_HEIGHT-SPECTOGRAM_HEIGHT) +#define BASE_FREQ 20.051392800492 +#define COEFF_CLAMP 1.0e-4 + +typedef struct { + FFTSample value; + int index; +} SparseCoeff; + +typedef struct { + const AVClass *class; + AVFrame *outpicref; + FFTContext *fft_context; + FFTComplex *fft_data; + FFTComplex *fft_result_left; + FFTComplex *fft_result_right; + uint8_t *spectogram; + SparseCoeff *coeff_sort; + SparseCoeff *coeffs[VIDEO_WIDTH]; + uint8_t *font_alpha; + char *fontfile; /* using freetype */ + int coeffs_len[VIDEO_WIDTH]; + uint8_t font_color[VIDEO_WIDTH]; + int64_t frame_count; + int spectogram_count; + int spectogram_index; + int fft_bits; + int req_fullfilled; + int remaining_fill; + double volume; + double timeclamp; /* lower timeclamp, time-accurate, higher timeclamp, freq-accurate (at low freq)*/ + float coeffclamp; /* lower coeffclamp, more precise, higher coeffclamp, faster */ + int fullhd; /* if true, output video is at full HD resolution, otherwise it will be halved */ + float gamma; /* lower gamma, more contrast, higher gamma, more range */ + int fps; /* the required fps is so strict, so it's enough to be int, but 24000/1001 etc cannot be encoded */ + int count; /* fps * count = transform rate */ +} ShowCQTContext; + +#define OFFSET(x) offsetof(ShowCQTContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption showcqt_options[] = { + { "volume", "set volume", OFFSET(volume), AV_OPT_TYPE_DOUBLE, { .dbl = 16 }, 0.1, 100, FLAGS }, + { "timeclamp", "set timeclamp", OFFSET(timeclamp), AV_OPT_TYPE_DOUBLE, { .dbl = 0.17 }, 0.1, 1.0, FLAGS }, + { "coeffclamp", "set coeffclamp", OFFSET(coeffclamp), AV_OPT_TYPE_FLOAT, { .dbl = 1 }, 0.1, 10, FLAGS }, + { "gamma", "set gamma", OFFSET(gamma), AV_OPT_TYPE_FLOAT, { .dbl = 3 }, 1, 7, FLAGS }, + { "fullhd", "set full HD resolution", OFFSET(fullhd), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS }, + { "fps", "set video fps", OFFSET(fps), AV_OPT_TYPE_INT, { .i64 = 25 }, 10, 100, FLAGS }, + { "count", "set number of transform per frame", OFFSET(count), AV_OPT_TYPE_INT, { .i64 = 6 }, 1, 30, FLAGS }, + { "fontfile", "set font file", OFFSET(fontfile), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(showcqt); + +static av_cold void uninit(AVFilterContext *ctx) +{ + int k; + + ShowCQTContext *s = ctx->priv; + av_fft_end(s->fft_context); + s->fft_context = NULL; + for (k = 0; k < VIDEO_WIDTH; k++) + av_freep(&s->coeffs[k]); + av_freep(&s->fft_data); + av_freep(&s->fft_result_left); + av_freep(&s->fft_result_right); + av_freep(&s->coeff_sort); + av_freep(&s->spectogram); + av_freep(&s->font_alpha); + av_frame_free(&s->outpicref); +} + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *layouts = NULL; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }; + static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE }; + static const int64_t channel_layouts[] = { AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_STEREO_DOWNMIX, -1 }; + static const int samplerates[] = { 44100, 48000, -1 }; + + /* set input audio formats */ + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ff_formats_ref(formats, &inlink->out_formats); + + layouts = avfilter_make_format64_list(channel_layouts); + if (!layouts) + return AVERROR(ENOMEM); + ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts); + + formats = ff_make_format_list(samplerates); + if (!formats) + return AVERROR(ENOMEM); + ff_formats_ref(formats, &inlink->out_samplerates); + + /* set output video format */ + formats = ff_make_format_list(pix_fmts); + if (!formats) + return AVERROR(ENOMEM); + ff_formats_ref(formats, &outlink->in_formats); + + return 0; +} + +#if CONFIG_LIBFREETYPE +static void load_freetype_font(AVFilterContext *ctx) +{ + static const char str[] = "EF G A BC D "; + ShowCQTContext *s = ctx->priv; + FT_Library lib = NULL; + FT_Face face = NULL; + int video_scale = s->fullhd ? 2 : 1; + int video_width = (VIDEO_WIDTH/2) * video_scale; + int font_height = (FONT_HEIGHT/2) * video_scale; + int font_width = 8 * video_scale; + int font_repeat = font_width * 12; + int linear_hori_advance = font_width * 65536; + int non_monospace_warning = 0; + int x; + + s->font_alpha = NULL; + + if (!s->fontfile) + return; + + if (FT_Init_FreeType(&lib)) + goto fail; + + if (FT_New_Face(lib, s->fontfile, 0, &face)) + goto fail; + + if (FT_Set_Char_Size(face, 16*64, 0, 0, 0)) + goto fail; + + if (FT_Load_Char(face, 'A', FT_LOAD_RENDER)) + goto fail; + + if (FT_Set_Char_Size(face, 16*64 * linear_hori_advance / face->glyph->linearHoriAdvance, 0, 0, 0)) + goto fail; + + s->font_alpha = av_malloc(font_height * video_width); + if (!s->font_alpha) + goto fail; + + memset(s->font_alpha, 0, font_height * video_width); + + for (x = 0; x < 12; x++) { + int sx, sy, rx, bx, by, dx, dy; + + if (str[x] == ' ') + continue; + + if (FT_Load_Char(face, str[x], FT_LOAD_RENDER)) + goto fail; + + if (face->glyph->advance.x != font_width*64 && !non_monospace_warning) { + av_log(ctx, AV_LOG_WARNING, "Font is not monospace\n"); + non_monospace_warning = 1; + } + + sy = font_height - 4*video_scale - face->glyph->bitmap_top; + for (rx = 0; rx < 10; rx++) { + sx = rx * font_repeat + x * font_width + face->glyph->bitmap_left; + for (by = 0; by < face->glyph->bitmap.rows; by++) { + dy = by + sy; + if (dy < 0) + continue; + if (dy >= font_height) + break; + + for (bx = 0; bx < face->glyph->bitmap.width; bx++) { + dx = bx + sx; + if (dx < 0) + continue; + if (dx >= video_width) + break; + s->font_alpha[dy*video_width+dx] = face->glyph->bitmap.buffer[by*face->glyph->bitmap.width+bx]; + } + } + } + } + + FT_Done_Face(face); + FT_Done_FreeType(lib); + return; + + fail: + av_log(ctx, AV_LOG_WARNING, "Error while loading freetype font, using default font instead\n"); + FT_Done_Face(face); + FT_Done_FreeType(lib); + av_freep(&s->font_alpha); + return; +} +#endif + +static inline int qsort_sparsecoeff(const SparseCoeff *a, const SparseCoeff *b) +{ + if (fabsf(a->value) >= fabsf(b->value)) + return 1; + else + return -1; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; + ShowCQTContext *s = ctx->priv; + int fft_len, k, x, y; + int num_coeffs = 0; + int rate = inlink->sample_rate; + double max_len = rate * (double) s->timeclamp; + int64_t start_time, end_time; + int video_scale = s->fullhd ? 2 : 1; + int video_width = (VIDEO_WIDTH/2) * video_scale; + int video_height = (VIDEO_HEIGHT/2) * video_scale; + int spectogram_height = (SPECTOGRAM_HEIGHT/2) * video_scale; + + s->fft_bits = ceil(log2(max_len)); + fft_len = 1 << s->fft_bits; + + if (rate % (s->fps * s->count)) { + av_log(ctx, AV_LOG_ERROR, "Rate (%u) is not divisible by fps*count (%u*%u)\n", rate, s->fps, s->count); + return AVERROR(EINVAL); + } + + s->fft_data = av_malloc_array(fft_len, sizeof(*s->fft_data)); + s->coeff_sort = av_malloc_array(fft_len, sizeof(*s->coeff_sort)); + s->fft_result_left = av_malloc_array(fft_len, sizeof(*s->fft_result_left)); + s->fft_result_right = av_malloc_array(fft_len, sizeof(*s->fft_result_right)); + s->fft_context = av_fft_init(s->fft_bits, 0); + + if (!s->fft_data || !s->coeff_sort || !s->fft_result_left || !s->fft_result_right || !s->fft_context) + return AVERROR(ENOMEM); + + /* initializing font */ + for (x = 0; x < video_width; x++) { + if (x >= (12*3+8)*8*video_scale && x < (12*4+8)*8*video_scale) { + float fx = (x-(12*3+8)*8*video_scale) * (2.0f/(192.0f*video_scale)); + float sv = sinf(M_PI*fx); + s->font_color[x] = sv*sv*255.0f + 0.5f; + } else { + s->font_color[x] = 0; + } + } + +#if CONFIG_LIBFREETYPE + load_freetype_font(ctx); +#else + if (s->fontfile) + av_log(ctx, AV_LOG_WARNING, "Freetype is not available, ignoring fontfile option\n"); + s->font_alpha = NULL; +#endif + + av_log(ctx, AV_LOG_INFO, "Calculating spectral kernel, please wait\n"); + start_time = av_gettime_relative(); + for (k = 0; k < VIDEO_WIDTH; k++) { + int hlen = fft_len >> 1; + float total = 0; + float partial = 0; + double freq = BASE_FREQ * exp2(k * (1.0/192.0)); + double tlen = rate * (24.0 * 16.0) /freq; + /* a window function from Albert H. Nuttall, + * "Some Windows with Very Good Sidelobe Behavior" + * -93.32 dB peak sidelobe and 18 dB/octave asymptotic decay + * coefficient normalized to a0 = 1 */ + double a0 = 0.355768; + double a1 = 0.487396/a0; + double a2 = 0.144232/a0; + double a3 = 0.012604/a0; + double sv_step, cv_step, sv, cv; + double sw_step, cw_step, sw, cw, w; + + tlen = tlen * max_len / (tlen + max_len); + s->fft_data[0].re = 0; + s->fft_data[0].im = 0; + s->fft_data[hlen].re = (1.0 + a1 + a2 + a3) * (1.0/tlen) * s->volume * (1.0/fft_len); + s->fft_data[hlen].im = 0; + sv_step = sv = sin(2.0*M_PI*freq*(1.0/rate)); + cv_step = cv = cos(2.0*M_PI*freq*(1.0/rate)); + /* also optimizing window func */ + sw_step = sw = sin(2.0*M_PI*(1.0/tlen)); + cw_step = cw = cos(2.0*M_PI*(1.0/tlen)); + for (x = 1; x < 0.5 * tlen; x++) { + double cv_tmp, cw_tmp; + double cw2, cw3, sw2; + + cw2 = cw * cw - sw * sw; + sw2 = cw * sw + sw * cw; + cw3 = cw * cw2 - sw * sw2; + w = (1.0 + a1 * cw + a2 * cw2 + a3 * cw3) * (1.0/tlen) * s->volume * (1.0/fft_len); + s->fft_data[hlen + x].re = w * cv; + s->fft_data[hlen + x].im = w * sv; + s->fft_data[hlen - x].re = s->fft_data[hlen + x].re; + s->fft_data[hlen - x].im = -s->fft_data[hlen + x].im; + + cv_tmp = cv * cv_step - sv * sv_step; + sv = sv * cv_step + cv * sv_step; + cv = cv_tmp; + cw_tmp = cw * cw_step - sw * sw_step; + sw = sw * cw_step + cw * sw_step; + cw = cw_tmp; + } + for (; x < hlen; x++) { + s->fft_data[hlen + x].re = 0; + s->fft_data[hlen + x].im = 0; + s->fft_data[hlen - x].re = 0; + s->fft_data[hlen - x].im = 0; + } + av_fft_permute(s->fft_context, s->fft_data); + av_fft_calc(s->fft_context, s->fft_data); + + for (x = 0; x < fft_len; x++) { + s->coeff_sort[x].index = x; + s->coeff_sort[x].value = s->fft_data[x].re; + } + + AV_QSORT(s->coeff_sort, fft_len, SparseCoeff, qsort_sparsecoeff); + for (x = 0; x < fft_len; x++) + total += fabsf(s->coeff_sort[x].value); + + for (x = 0; x < fft_len; x++) { + partial += fabsf(s->coeff_sort[x].value); + if (partial > total * s->coeffclamp * COEFF_CLAMP) { + s->coeffs_len[k] = fft_len - x; + num_coeffs += s->coeffs_len[k]; + s->coeffs[k] = av_malloc_array(s->coeffs_len[k], sizeof(*s->coeffs[k])); + if (!s->coeffs[k]) + return AVERROR(ENOMEM); + for (y = 0; y < s->coeffs_len[k]; y++) + s->coeffs[k][y] = s->coeff_sort[x+y]; + break; + } + } + } + end_time = av_gettime_relative(); + av_log(ctx, AV_LOG_INFO, "Elapsed time %.6f s (fft_len=%u, num_coeffs=%u)\n", 1e-6 * (end_time-start_time), fft_len, num_coeffs); + + outlink->w = video_width; + outlink->h = video_height; + + s->req_fullfilled = 0; + s->spectogram_index = 0; + s->frame_count = 0; + s->spectogram_count = 0; + s->remaining_fill = fft_len >> 1; + memset(s->fft_data, 0, fft_len * sizeof(*s->fft_data)); + + s->outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!s->outpicref) + return AVERROR(ENOMEM); + + s->spectogram = av_calloc(spectogram_height, s->outpicref->linesize[0]); + if (!s->spectogram) + return AVERROR(ENOMEM); + + outlink->sample_aspect_ratio = av_make_q(1, 1); + outlink->time_base = av_make_q(1, s->fps); + outlink->frame_rate = av_make_q(s->fps, 1); + return 0; +} + +static int plot_cqt(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ShowCQTContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + int fft_len = 1 << s->fft_bits; + FFTSample result[VIDEO_WIDTH][4]; + int x, y, ret = 0; + int linesize = s->outpicref->linesize[0]; + int video_scale = s->fullhd ? 2 : 1; + int video_width = (VIDEO_WIDTH/2) * video_scale; + int spectogram_height = (SPECTOGRAM_HEIGHT/2) * video_scale; + int spectogram_start = (SPECTOGRAM_START/2) * video_scale; + int font_height = (FONT_HEIGHT/2) * video_scale; + + /* real part contains left samples, imaginary part contains right samples */ + memcpy(s->fft_result_left, s->fft_data, fft_len * sizeof(*s->fft_data)); + av_fft_permute(s->fft_context, s->fft_result_left); + av_fft_calc(s->fft_context, s->fft_result_left); + + /* separate left and right, (and multiply by 2.0) */ + s->fft_result_right[0].re = 2.0f * s->fft_result_left[0].im; + s->fft_result_right[0].im = 0; + s->fft_result_left[0].re = 2.0f * s->fft_result_left[0].re; + s->fft_result_left[0].im = 0; + for (x = 1; x <= fft_len >> 1; x++) { + FFTSample tmpy = s->fft_result_left[fft_len-x].im - s->fft_result_left[x].im; + + s->fft_result_right[x].re = s->fft_result_left[x].im + s->fft_result_left[fft_len-x].im; + s->fft_result_right[x].im = s->fft_result_left[x].re - s->fft_result_left[fft_len-x].re; + s->fft_result_right[fft_len-x].re = s->fft_result_right[x].re; + s->fft_result_right[fft_len-x].im = -s->fft_result_right[x].im; + + s->fft_result_left[x].re = s->fft_result_left[x].re + s->fft_result_left[fft_len-x].re; + s->fft_result_left[x].im = tmpy; + s->fft_result_left[fft_len-x].re = s->fft_result_left[x].re; + s->fft_result_left[fft_len-x].im = -s->fft_result_left[x].im; + } + + /* calculating cqt */ + for (x = 0; x < VIDEO_WIDTH; x++) { + int u; + float g = 1.0f / s->gamma; + FFTComplex l = {0,0}; + FFTComplex r = {0,0}; + + for (u = 0; u < s->coeffs_len[x]; u++) { + FFTSample value = s->coeffs[x][u].value; + int index = s->coeffs[x][u].index; + l.re += value * s->fft_result_left[index].re; + l.im += value * s->fft_result_left[index].im; + r.re += value * s->fft_result_right[index].re; + r.im += value * s->fft_result_right[index].im; + } + /* result is power, not amplitude */ + result[x][0] = l.re * l.re + l.im * l.im; + result[x][2] = r.re * r.re + r.im * r.im; + result[x][1] = 0.5f * (result[x][0] + result[x][2]); + result[x][3] = result[x][1]; + result[x][0] = 255.0f * powf(FFMIN(1.0f,result[x][0]), g); + result[x][1] = 255.0f * powf(FFMIN(1.0f,result[x][1]), g); + result[x][2] = 255.0f * powf(FFMIN(1.0f,result[x][2]), g); + } + + if (!s->fullhd) { + for (x = 0; x < video_width; x++) { + result[x][0] = 0.5f * (result[2*x][0] + result[2*x+1][0]); + result[x][1] = 0.5f * (result[2*x][1] + result[2*x+1][1]); + result[x][2] = 0.5f * (result[2*x][2] + result[2*x+1][2]); + result[x][3] = 0.5f * (result[2*x][3] + result[2*x+1][3]); + } + } + + for (x = 0; x < video_width; x++) { + s->spectogram[s->spectogram_index*linesize + 3*x] = result[x][0] + 0.5f; + s->spectogram[s->spectogram_index*linesize + 3*x + 1] = result[x][1] + 0.5f; + s->spectogram[s->spectogram_index*linesize + 3*x + 2] = result[x][2] + 0.5f; + } + + /* drawing */ + if (!s->spectogram_count) { + uint8_t *data = (uint8_t*) s->outpicref->data[0]; + float rcp_result[VIDEO_WIDTH]; + int total_length = linesize * spectogram_height; + int back_length = linesize * s->spectogram_index; + + for (x = 0; x < video_width; x++) + rcp_result[x] = 1.0f / (result[x][3]+0.0001f); + + /* drawing bar */ + for (y = 0; y < spectogram_height; y++) { + float height = (spectogram_height - y) * (1.0f/spectogram_height); + uint8_t *lineptr = data + y * linesize; + for (x = 0; x < video_width; x++) { + float mul; + if (result[x][3] <= height) { + *lineptr++ = 0; + *lineptr++ = 0; + *lineptr++ = 0; + } else { + mul = (result[x][3] - height) * rcp_result[x]; + *lineptr++ = mul * result[x][0] + 0.5f; + *lineptr++ = mul * result[x][1] + 0.5f; + *lineptr++ = mul * result[x][2] + 0.5f; + } + } + } + + /* drawing font */ + if (s->font_alpha) { + for (y = 0; y < font_height; y++) { + uint8_t *lineptr = data + (spectogram_height + y) * linesize; + uint8_t *spectogram_src = s->spectogram + s->spectogram_index * linesize; + for (x = 0; x < video_width; x++) { + uint8_t alpha = s->font_alpha[y*video_width+x]; + uint8_t color = s->font_color[x]; + lineptr[3*x] = (spectogram_src[3*x] * (255-alpha) + (255-color) * alpha + 255) >> 8; + lineptr[3*x+1] = (spectogram_src[3*x+1] * (255-alpha) + 255) >> 8; + lineptr[3*x+2] = (spectogram_src[3*x+2] * (255-alpha) + color * alpha + 255) >> 8; + } + } + } else { + for (y = 0; y < font_height; y++) { + uint8_t *lineptr = data + (spectogram_height + y) * linesize; + memcpy(lineptr, s->spectogram + s->spectogram_index * linesize, video_width*3); + } + for (x = 0; x < video_width; x += video_width/10) { + int u; + static const char str[] = "EF G A BC D "; + uint8_t *startptr = data + spectogram_height * linesize + x * 3; + for (u = 0; str[u]; u++) { + int v; + for (v = 0; v < 16; v++) { + uint8_t *p = startptr + v * linesize * video_scale + 8 * 3 * u * video_scale; + int ux = x + 8 * u * video_scale; + int mask; + for (mask = 0x80; mask; mask >>= 1) { + if (mask & avpriv_vga16_font[str[u] * 16 + v]) { + p[0] = 255 - s->font_color[ux]; + p[1] = 0; + p[2] = s->font_color[ux]; + if (video_scale == 2) { + p[linesize] = p[0]; + p[linesize+1] = p[1]; + p[linesize+2] = p[2]; + p[3] = p[linesize+3] = 255 - s->font_color[ux+1]; + p[4] = p[linesize+4] = 0; + p[5] = p[linesize+5] = s->font_color[ux+1]; + } + } + p += 3 * video_scale; + ux += video_scale; + } + } + } + } + } + + /* drawing spectogram/sonogram */ + data += spectogram_start * linesize; + memcpy(data, s->spectogram + s->spectogram_index*linesize, total_length - back_length); + + data += total_length - back_length; + if (back_length) + memcpy(data, s->spectogram, back_length); + + s->outpicref->pts = s->frame_count; + ret = ff_filter_frame(outlink, av_frame_clone(s->outpicref)); + s->req_fullfilled = 1; + s->frame_count++; + } + s->spectogram_count = (s->spectogram_count + 1) % s->count; + s->spectogram_index = (s->spectogram_index + spectogram_height - 1) % spectogram_height; + return ret; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) +{ + AVFilterContext *ctx = inlink->dst; + ShowCQTContext *s = ctx->priv; + int step = inlink->sample_rate / (s->fps * s->count); + int fft_len = 1 << s->fft_bits; + int remaining; + float *audio_data; + + if (!insamples) { + while (s->remaining_fill < (fft_len >> 1)) { + int ret, x; + memset(&s->fft_data[fft_len - s->remaining_fill], 0, sizeof(*s->fft_data) * s->remaining_fill); + ret = plot_cqt(inlink); + if (ret < 0) + return ret; + for (x = 0; x < (fft_len-step); x++) + s->fft_data[x] = s->fft_data[x+step]; + s->remaining_fill += step; + } + return AVERROR(EOF); + } + + remaining = insamples->nb_samples; + audio_data = (float*) insamples->data[0]; + + while (remaining) { + if (remaining >= s->remaining_fill) { + int i = insamples->nb_samples - remaining; + int j = fft_len - s->remaining_fill; + int m, ret; + for (m = 0; m < s->remaining_fill; m++) { + s->fft_data[j+m].re = audio_data[2*(i+m)]; + s->fft_data[j+m].im = audio_data[2*(i+m)+1]; + } + ret = plot_cqt(inlink); + if (ret < 0) { + av_frame_free(&insamples); + return ret; + } + remaining -= s->remaining_fill; + for (m = 0; m < fft_len-step; m++) + s->fft_data[m] = s->fft_data[m+step]; + s->remaining_fill = step; + } else { + int i = insamples->nb_samples - remaining; + int j = fft_len - s->remaining_fill; + int m; + for (m = 0; m < remaining; m++) { + s->fft_data[m+j].re = audio_data[2*(i+m)]; + s->fft_data[m+j].im = audio_data[2*(i+m)+1]; + } + s->remaining_fill -= remaining; + remaining = 0; + } + } + av_frame_free(&insamples); + return 0; +} + +static int request_frame(AVFilterLink *outlink) +{ + ShowCQTContext *s = outlink->src->priv; + AVFilterLink *inlink = outlink->src->inputs[0]; + int ret; + + s->req_fullfilled = 0; + do { + ret = ff_request_frame(inlink); + } while (!s->req_fullfilled && ret >= 0); + + if (ret == AVERROR_EOF && s->outpicref) + filter_frame(inlink, NULL); + return ret; +} + +static const AVFilterPad showcqt_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad showcqt_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + .request_frame = request_frame, + }, + { NULL } +}; + +AVFilter ff_avf_showcqt = { + .name = "showcqt", + .description = NULL_IF_CONFIG_SMALL("Convert input audio to a CQT (Constant Q Transform) spectrum video output."), + .uninit = uninit, + .query_formats = query_formats, + .priv_size = sizeof(ShowCQTContext), + .inputs = showcqt_inputs, + .outputs = showcqt_outputs, + .priv_class = &showcqt_class, +}; diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c index fc32834e5..4a4b4f4c7 100644 --- a/libavfilter/avf_showspectrum.c +++ b/libavfilter/avf_showspectrum.c @@ -323,8 +323,8 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples, int nb av_rdft_calc(s->rdft, s->rdft_data[ch]); /* fill a new spectrum column */ -#define RE(y, ch) s->rdft_data[ch][2 * y + 0] -#define IM(y, ch) s->rdft_data[ch][2 * y + 1] +#define RE(y, ch) s->rdft_data[ch][2 * (y) + 0] +#define IM(y, ch) s->rdft_data[ch][2 * (y) + 1] #define MAGNITUDE(y, ch) hypot(RE(y, ch), IM(y, ch)) /* initialize buffer for combining to black */ diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 46f81f2d9..7e166e04f 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -295,7 +295,7 @@ int avfilter_config_links(AVFilterContext *filter) if ((config_link = link->dstpad->config_props)) if ((ret = config_link(link)) < 0) { - av_log(link->src, AV_LOG_ERROR, + av_log(link->dst, AV_LOG_ERROR, "Failed to configure input pad on %s\n", link->dst->name); return ret; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index ef7e8cadc..b5220b96d 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -199,7 +199,7 @@ typedef struct AVFilterBufferRef { * Copy properties of src to dst, without copying the actual data */ attribute_deprecated -void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, AVFilterBufferRef *src); +void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, const AVFilterBufferRef *src); /** * Add a new reference to a buffer. @@ -668,7 +668,7 @@ struct AVFilterContext { * allowed threading types. I.e. a threading type needs to be set in both * to be allowed. * - * After the filter is initialzed, libavfilter sets this field to the + * After the filter is initialized, libavfilter sets this field to the * threading type that is actually used (0 for no multithreading). */ int thread_type; @@ -830,7 +830,7 @@ struct AVFilterLink { /** * True if the link is closed. - * If set, all attemps of start_frame, filter_frame or request_frame + * If set, all attempts of start_frame, filter_frame or request_frame * will fail with AVERROR_EOF, and if necessary the reference will be * destroyed. * If request_frame returns AVERROR_EOF, this flag is set on the @@ -1260,19 +1260,21 @@ AVFilterGraph *avfilter_graph_alloc(void); * * @return the context of the newly created filter instance (note that it is * also retrievable directly through AVFilterGraph.filters or with - * avfilter_graph_get_filter()) on success or NULL or failure. + * avfilter_graph_get_filter()) on success or NULL on failure. */ AVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph, const AVFilter *filter, const char *name); /** - * Get a filter instance with name name from graph. + * Get a filter instance identified by instance name from graph. * + * @param graph filter graph to search through. + * @param name filter instance name (should be unique in the graph). * @return the pointer to the found filter instance or NULL if it * cannot be found. */ -AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name); +AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, const char *name); #if FF_API_AVFILTER_OPEN /** @@ -1384,7 +1386,7 @@ void avfilter_inout_free(AVFilterInOut **inout); * outputs of the already existing filters, which are provided as * inputs to the parsed filters. * - * @param graph the filter graph where to link the parsed grap context + * @param graph the filter graph where to link the parsed graph context * @param filters string to be parsed * @param inputs linked list to the inputs of the graph * @param outputs linked list to the outputs of the graph @@ -1482,7 +1484,7 @@ int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const * "all" sends to all filters * otherwise it can be a filter or filter instance name * which will send the command to all matching filters. - * @param cmd the command to sent, for handling simplicity all commands must be alphanummeric only + * @param cmd the command to sent, for handling simplicity all commands must be alphanumeric only * @param arg the argument for the command * @param ts time at which the command should be sent to the filter * diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 1fb83c487..f12491ea1 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -31,7 +31,6 @@ #include "libavutil/internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" -#include "libavcodec/avcodec.h" // avcodec_find_best_pix_fmt_of_2() #include "avfilter.h" #include "formats.h" @@ -281,7 +280,7 @@ static int graph_config_links(AVFilterGraph *graph, AVClass *log_ctx) return 0; } -AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name) +AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, const char *name) { int i; @@ -565,19 +564,19 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) outlink = convert->outputs[0]; if (!ff_merge_formats( inlink->in_formats, inlink->out_formats, inlink->type) || !ff_merge_formats(outlink->in_formats, outlink->out_formats, outlink->type)) - ret |= AVERROR(ENOSYS); + ret = AVERROR(ENOSYS); if (inlink->type == AVMEDIA_TYPE_AUDIO && (!ff_merge_samplerates(inlink->in_samplerates, inlink->out_samplerates) || !ff_merge_channel_layouts(inlink->in_channel_layouts, inlink->out_channel_layouts))) - ret |= AVERROR(ENOSYS); + ret = AVERROR(ENOSYS); if (outlink->type == AVMEDIA_TYPE_AUDIO && (!ff_merge_samplerates(outlink->in_samplerates, outlink->out_samplerates) || !ff_merge_channel_layouts(outlink->in_channel_layouts, outlink->out_channel_layouts))) - ret |= AVERROR(ENOSYS); + ret = AVERROR(ENOSYS); if (ret < 0) { av_log(log_ctx, AV_LOG_ERROR, @@ -628,7 +627,7 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) int i; for (i=0; iin_formats->nb_formats; i++) { enum AVPixelFormat p = link->in_formats->formats[i]; - best= avcodec_find_best_pix_fmt_of_2(best, p, ref->format, has_alpha, NULL); + best= av_find_best_pix_fmt_of_2(best, p, ref->format, has_alpha, NULL); } av_log(link->src,AV_LOG_DEBUG, "picking %s out of %d ref:%s alpha:%d\n", av_get_pix_fmt_name(best), link->in_formats->nb_formats, diff --git a/libavfilter/buffer.c b/libavfilter/buffer.c index a62618440..0327952e7 100644 --- a/libavfilter/buffer.c +++ b/libavfilter/buffer.c @@ -79,7 +79,7 @@ AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) if (ref->extended_data && 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) * + if (!(ret->extended_data = av_malloc_array(sizeof(*ret->extended_data), nb_channels))) { av_freep(&ret->audio); av_freep(&ret); @@ -150,7 +150,7 @@ int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src) return 0; } -void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, AVFilterBufferRef *src) +void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, const AVFilterBufferRef *src) { // copy common properties dst->pts = src->pts; diff --git a/libavfilter/bufferqueue.h b/libavfilter/bufferqueue.h index adbc0fd89..f5e5df2d7 100644 --- a/libavfilter/bufferqueue.h +++ b/libavfilter/bufferqueue.h @@ -37,7 +37,7 @@ * Powers of 2 are recommended. */ #ifndef FF_BUFQUEUE_SIZE -#define FF_BUFQUEUE_SIZE 32 +#define FF_BUFQUEUE_SIZE 64 #endif #include "avfilter.h" diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c index a6b24adff..525f97bfb 100644 --- a/libavfilter/buffersink.c +++ b/libavfilter/buffersink.c @@ -36,7 +36,7 @@ #include "buffersink.h" #include "internal.h" -typedef struct { +typedef struct BufferSinkContext { const AVClass *class; AVFifoBuffer *fifo; ///< FIFO buffer of video frame references unsigned warning_limit; @@ -76,8 +76,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_fifo_generic_read(sink->fifo, &frame, sizeof(frame), NULL); av_frame_free(&frame); } - av_fifo_free(sink->fifo); - sink->fifo = NULL; + av_fifo_freep(&sink->fifo); } } @@ -247,7 +246,7 @@ static av_cold int common_init(AVFilterContext *ctx) { BufferSinkContext *buf = ctx->priv; - buf->fifo = av_fifo_alloc(FIFO_INIT_SIZE*sizeof(AVFilterBufferRef *)); + buf->fifo = av_fifo_alloc_array(FIFO_INIT_SIZE, sizeof(AVFilterBufferRef *)); if (!buf->fifo) { av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo\n"); return AVERROR(ENOMEM); diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index ae7cea2c6..27d3db085 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -41,7 +41,7 @@ #include "video.h" #include "avcodec.h" -typedef struct { +typedef struct BufferSourceContext { const AVClass *class; AVFifoBuffer *fifo; AVRational time_base; ///< time_base to set in the output link @@ -271,7 +271,7 @@ do { \ 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->extended_buf = av_mallocz_array(sizeof(*frame->extended_buf), frame->nb_extended_buf); if (!frame->extended_buf) { ret = AVERROR(ENOMEM); @@ -379,13 +379,13 @@ static av_cold int init_audio(AVFilterContext *ctx) if (s->channel_layout_str) { int n; - /* TODO reindent */ - 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); - return AVERROR(EINVAL); - } + + 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); + return AVERROR(EINVAL); + } n = av_get_channel_layout_nb_channels(s->channel_layout); if (s->channels) { if (n != s->channels) { @@ -426,8 +426,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_fifo_generic_read(s->fifo, &frame, sizeof(frame), NULL); av_frame_free(&frame); } - av_fifo_free(s->fifo); - s->fifo = NULL; + av_fifo_freep(&s->fifo); } static int query_formats(AVFilterContext *ctx) diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h index 5d124337b..ea34c04ee 100644 --- a/libavfilter/buffersrc.h +++ b/libavfilter/buffersrc.h @@ -138,7 +138,7 @@ int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame); * Add a frame to the buffer source. * * By default, if the frame is reference-counted, this function will take - * ownership of the reference(s) and reset the frame. This can be controled + * ownership of the reference(s) and reset the frame. This can be controlled * using the flags. * * If this function returns an error, the input frame is not touched. diff --git a/libavfilter/deshake_opencl.c b/libavfilter/deshake_opencl.c index caf2bf2e2..c66103cb7 100644 --- a/libavfilter/deshake_opencl.c +++ b/libavfilter/deshake_opencl.c @@ -31,7 +31,7 @@ #include "libavutil/opencl_internal.h" #define PLANE_NUM 3 -#define ROUND_TO_16(a) ((((a - 1)/16)+1)*16) +#define ROUND_TO_16(a) (((((a) - 1)/16)+1)*16) int ff_opencl_transform(AVFilterContext *ctx, int width, int height, int cw, int ch, diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index a5064f8e7..4437c2cfc 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -517,15 +517,14 @@ int ff_draw_round_to_sub(FFDrawContext *draw, int sub_dir, int round_dir, AVFilterFormats *ff_draw_supported_pixel_formats(unsigned flags) { - enum AVPixelFormat i, pix_fmts[AV_PIX_FMT_NB + 1]; - unsigned n = 0; + enum AVPixelFormat i; FFDrawContext draw; + AVFilterFormats *fmts = NULL; - for (i = 0; i < AV_PIX_FMT_NB; i++) + for (i = 0; av_pix_fmt_desc_get(i); i++) if (ff_draw_init(&draw, i, flags) >= 0) - pix_fmts[n++] = i; - pix_fmts[n++] = AV_PIX_FMT_NONE; - return ff_make_format_list(pix_fmts); + ff_add_format(&fmts, i); + return fmts; } #ifdef TEST @@ -540,7 +539,7 @@ int main(void) FFDrawColor color; int r, i; - for (f = 0; f < AV_PIX_FMT_NB; f++) { + for (f = 0; av_pix_fmt_desc_get(f); f++) { desc = av_pix_fmt_desc_get(f); if (!desc->name) continue; diff --git a/libavfilter/f_select.c b/libavfilter/f_select.c index 1ffc00652..c7c53b43e 100644 --- a/libavfilter/f_select.c +++ b/libavfilter/f_select.c @@ -138,7 +138,7 @@ enum var_name { VAR_VARS_NB }; -typedef struct { +typedef struct SelectContext { const AVClass *class; char *expr_str; AVExpr *expr; @@ -271,7 +271,7 @@ static double get_scene_score(AVFilterContext *ctx, AVFrame *frame) for (y = 0; y < frame->height - 8; y += 8) { for (x = 0; x < frame->width*3 - 8; x += 8) { - sad += select->c.sad[1](select, p1 + x, p2 + x, + sad += select->c.sad[1](NULL, p1 + x, p2 + x, linesize, 8); nb_sad += 8 * 8; } diff --git a/libavfilter/fifo.c b/libavfilter/fifo.c index 5310af24d..e477cff4c 100644 --- a/libavfilter/fifo.c +++ b/libavfilter/fifo.c @@ -39,7 +39,7 @@ typedef struct Buf { struct Buf *next; } Buf; -typedef struct { +typedef struct FifoContext { Buf root; Buf *last; ///< last buffered frame diff --git a/libavfilter/filtfmts.c b/libavfilter/filtfmts.c index b3efa7834..dd757a527 100644 --- a/libavfilter/filtfmts.c +++ b/libavfilter/filtfmts.c @@ -20,7 +20,7 @@ #include -#include "libavformat/avformat.h" +#include "libavutil/channel_layout.h" #include "libavutil/pixdesc.h" #include "libavutil/samplefmt.h" #include "libavfilter/avfilter.h" diff --git a/libavfilter/formats.c b/libavfilter/formats.c index 581603274..816042987 100644 --- a/libavfilter/formats.c +++ b/libavfilter/formats.c @@ -39,8 +39,8 @@ do { \ type ***tmp; \ int i; \ \ - if (!(tmp = av_realloc(ret->refs, \ - sizeof(*tmp) * (ret->refcount + a->refcount)))) \ + if (!(tmp = av_realloc_array(ret->refs, ret->refcount + a->refcount, \ + sizeof(*tmp)))) \ goto fail; \ ret->refs = tmp; \ \ @@ -66,7 +66,7 @@ do { goto fail; \ \ if (count) { \ - if (!(ret->fmts = av_malloc(sizeof(*ret->fmts) * count))) \ + if (!(ret->fmts = av_malloc_array(count, sizeof(*ret->fmts)))) \ goto fail; \ for (i = 0; i < a->nb; i++) \ for (j = 0; j < b->nb; j++) \ @@ -196,8 +196,8 @@ AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a, ret_max = a->nb_channel_layouts + b->nb_channel_layouts; if (!(ret = av_mallocz(sizeof(*ret))) || - !(ret->channel_layouts = av_malloc(sizeof(*ret->channel_layouts) * - ret_max))) + !(ret->channel_layouts = av_malloc_array(ret_max, + sizeof(*ret->channel_layouts)))) goto fail; /* a[known] intersect b[known] */ @@ -284,7 +284,7 @@ int ff_fmt_is_in(int fmt, const int *fmts) if (!formats) return NULL; \ formats->count_field = count; \ if (count) { \ - formats->field = av_malloc(sizeof(*formats->field)*count); \ + formats->field = av_malloc_array(count, sizeof(*formats->field)); \ if (!formats->field) { \ av_free(formats); \ return NULL; \ @@ -343,15 +343,19 @@ int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout) AVFilterFormats *ff_all_formats(enum AVMediaType type) { AVFilterFormats *ret = NULL; - int fmt; - int num_formats = type == AVMEDIA_TYPE_VIDEO ? AV_PIX_FMT_NB : - type == AVMEDIA_TYPE_AUDIO ? AV_SAMPLE_FMT_NB : 0; - for (fmt = 0; fmt < num_formats; fmt++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); - if ((type != AVMEDIA_TYPE_VIDEO) || - (type == AVMEDIA_TYPE_VIDEO && !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))) + 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)); + } + } else if (type == AVMEDIA_TYPE_AUDIO) { + enum AVSampleFormat fmt = 0; + while (av_get_sample_fmt_name(fmt)) { ff_add_format(&ret, fmt); + fmt++; + } } return ret; @@ -372,7 +376,7 @@ AVFilterFormats *ff_planar_sample_fmts(void) AVFilterFormats *ret = NULL; int fmt; - for (fmt = 0; fmt < AV_SAMPLE_FMT_NB; fmt++) + for (fmt = 0; av_get_bytes_per_sample(fmt)>0; fmt++) if (av_sample_fmt_is_planar(fmt)) ff_add_format(&ret, fmt); @@ -568,7 +572,7 @@ int ff_parse_pixel_format(enum AVPixelFormat *ret, const char *arg, void *log_ct int pix_fmt = av_get_pix_fmt(arg); if (pix_fmt == AV_PIX_FMT_NONE) { pix_fmt = strtol(arg, &tail, 0); - if (*tail || (unsigned)pix_fmt >= AV_PIX_FMT_NB) { + if (*tail || !av_pix_fmt_desc_get(pix_fmt)) { av_log(log_ctx, AV_LOG_ERROR, "Invalid pixel format '%s'\n", arg); return AVERROR(EINVAL); } @@ -583,7 +587,7 @@ int ff_parse_sample_format(int *ret, const char *arg, void *log_ctx) int sfmt = av_get_sample_fmt(arg); if (sfmt == AV_SAMPLE_FMT_NONE) { sfmt = strtol(arg, &tail, 0); - if (*tail || (unsigned)sfmt >= AV_SAMPLE_FMT_NB) { + if (*tail || av_get_bytes_per_sample(sfmt)<=0) { av_log(log_ctx, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg); return AVERROR(EINVAL); } diff --git a/libavfilter/generate_wave_table.c b/libavfilter/generate_wave_table.c new file mode 100644 index 000000000..bee9c0098 --- /dev/null +++ b/libavfilter/generate_wave_table.c @@ -0,0 +1,84 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "libavutil/avassert.h" +#include "avfilter.h" +#include "generate_wave_table.h" + +void ff_generate_wave_table(enum WaveType wave_type, + enum AVSampleFormat sample_fmt, + void *table, int table_size, + double min, double max, double phase) +{ + uint32_t i, phase_offset = phase / M_PI / 2 * table_size + 0.5; + + for (i = 0; i < table_size; i++) { + uint32_t point = (i + phase_offset) % table_size; + double d; + + switch (wave_type) { + case WAVE_SIN: + d = (sin((double)point / table_size * 2 * M_PI) + 1) / 2; + break; + case WAVE_TRI: + d = (double)point * 2 / table_size; + switch (4 * point / table_size) { + case 0: d = d + 0.5; break; + case 1: + case 2: d = 1.5 - d; break; + case 3: d = d - 1.5; break; + } + break; + default: + av_assert0(0); + } + + d = d * (max - min) + min; + switch (sample_fmt) { + case AV_SAMPLE_FMT_FLT: { + float *fp = (float *)table; + *fp++ = (float)d; + table = fp; + continue; } + case AV_SAMPLE_FMT_DBL: { + double *dp = (double *)table; + *dp++ = d; + table = dp; + continue; } + } + + d += d < 0 ? -0.5 : 0.5; + switch (sample_fmt) { + case AV_SAMPLE_FMT_S16: { + int16_t *sp = table; + *sp++ = (int16_t)d; + table = sp; + continue; } + case AV_SAMPLE_FMT_S32: { + int32_t *ip = table; + *ip++ = (int32_t)d; + table = ip; + continue; } + default: + av_assert0(0); + } + } +} + + diff --git a/libavfilter/generate_wave_table.h b/libavfilter/generate_wave_table.h new file mode 100644 index 000000000..37ea2aa79 --- /dev/null +++ b/libavfilter/generate_wave_table.h @@ -0,0 +1,33 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_GENERATE_WAVE_TABLE_H +#define AVFILTER_GENERATE_WAVE_TABLE_H + +enum WaveType { + WAVE_SIN, + WAVE_TRI, + WAVE_NB, +}; + +void ff_generate_wave_table(enum WaveType wave_type, + enum AVSampleFormat sample_fmt, + void *table, int table_size, + double min, double max, double phase); + +#endif /* AVFILTER_GENERATE_WAVE_TABLE_H */ diff --git a/libavfilter/lavfutils.c b/libavfilter/lavfutils.c index 58d98cfdb..93f1ef331 100644 --- a/libavfilter/lavfutils.c +++ b/libavfilter/lavfutils.c @@ -44,6 +44,11 @@ int ff_load_image(uint8_t *data[4], int linesize[4], return ret; } + if ((ret = avformat_find_stream_info(format_ctx, NULL)) < 0) { + av_log(log_ctx, AV_LOG_ERROR, "Find stream info failed\n"); + return ret; + } + codec_ctx = format_ctx->streams[0]->codec; codec = avcodec_find_decoder(codec_ctx->codec_id); if (!codec) { diff --git a/libavfilter/libmpcodecs/img_format.c b/libavfilter/libmpcodecs/img_format.c index 61bf89880..dd07f00a0 100644 --- a/libavfilter/libmpcodecs/img_format.c +++ b/libavfilter/libmpcodecs/img_format.c @@ -52,6 +52,8 @@ const char *ff_vo_format_name(int format) case IMGFMT_BGRA: return "BGRA"; case IMGFMT_ARGB: return "ARGB"; case IMGFMT_RGBA: return "RGBA"; + case IMGFMT_XYZ12LE: return "XYZ 36-bit LE"; + case IMGFMT_XYZ12BE: return "XYZ 36-bit BE"; case IMGFMT_GBR24P: return "Planar GBR 24-bit"; case IMGFMT_GBR12P: return "Planar GBR 36-bit"; case IMGFMT_GBR14P: return "Planar GBR 42-bit"; @@ -102,6 +104,7 @@ const char *ff_vo_format_name(int format) case IMGFMT_422P: return "Planar 422P"; case IMGFMT_422A: return "Planar 422P with alpha"; case IMGFMT_411P: return "Planar 411P"; + case IMGFMT_440P: return "Planar 440P"; case IMGFMT_NV12: return "Planar NV12"; case IMGFMT_NV21: return "Planar NV21"; case IMGFMT_HM12: return "Planar NV12 Macroblock"; @@ -218,6 +221,14 @@ int ff_mp_get_chroma_shift(int format, int *x_shift, int *y_shift, int *componen xs = 31; ys = 31; break; + case IMGFMT_NV12: + case IMGFMT_NV21: + xs = 1; + ys = 1; + // TODO: allowing this though currently breaks + // things all over the place. + err = 1; + break; default: err = 1; break; diff --git a/libavfilter/libmpcodecs/img_format.h b/libavfilter/libmpcodecs/img_format.h index d4d64d8d3..b5c0b9007 100644 --- a/libavfilter/libmpcodecs/img_format.h +++ b/libavfilter/libmpcodecs/img_format.h @@ -51,6 +51,11 @@ #define IMGFMT_BGR24 (IMGFMT_BGR|24) #define IMGFMT_BGR32 (IMGFMT_BGR|32) +#define IMGFMT_XYZ_MASK 0xFFFFFF00 +#define IMGFMT_XYZ (('X'<<24)|('Y'<<16)|('Z'<<8)) +#define IMGFMT_XYZ12LE (IMGFMT_XYZ|12) +#define IMGFMT_XYZ12BE (IMGFMT_XYZ|12|128) + #define IMGFMT_GBR24P (('G'<<24)|('B'<<16)|('R'<<8)|24) #define IMGFMT_GBR12PLE (('G'<<24)|('B'<<16)|('R'<<8)|36) #define IMGFMT_GBR12PBE (('G'<<24)|('B'<<16)|('R'<<8)|36|128) @@ -76,6 +81,7 @@ #define IMGFMT_BGR15LE (IMGFMT_BGR15|128) #define IMGFMT_BGR16BE IMGFMT_BGR16 #define IMGFMT_BGR16LE (IMGFMT_BGR16|128) +#define IMGFMT_XYZ12 IMGFMT_XYZ12BE #define IMGFMT_GBR12P IMGFMT_GBR12PBE #define IMGFMT_GBR14P IMGFMT_GBR14PBE #else @@ -97,6 +103,7 @@ #define IMGFMT_BGR15LE IMGFMT_BGR15 #define IMGFMT_BGR16BE (IMGFMT_BGR16|128) #define IMGFMT_BGR16LE IMGFMT_BGR16 +#define IMGFMT_XYZ12 IMGFMT_XYZ12LE #define IMGFMT_GBR12P IMGFMT_GBR12PLE #define IMGFMT_GBR14P IMGFMT_GBR14PLE #endif @@ -107,9 +114,11 @@ #define IMGFMT_IS_RGB(fmt) (((fmt)&IMGFMT_RGB_MASK)==IMGFMT_RGB) #define IMGFMT_IS_BGR(fmt) (((fmt)&IMGFMT_BGR_MASK)==IMGFMT_BGR) +#define IMGFMT_IS_XYZ(fmt) (((fmt)&IMGFMT_XYZ_MASK)==IMGFMT_XYZ) #define IMGFMT_RGB_DEPTH(fmt) ((fmt)&0x7F) #define IMGFMT_BGR_DEPTH(fmt) ((fmt)&0x7F) +#define IMGFMT_XYZ_DEPTH(fmt) ((fmt)&0x7F) /* Planar YUV Formats */ diff --git a/libavfilter/libmpcodecs/libvo/video_out.h b/libavfilter/libmpcodecs/libvo/video_out.h index 2a3a0facc..49d30987f 100644 --- a/libavfilter/libmpcodecs/libvo/video_out.h +++ b/libavfilter/libmpcodecs/libvo/video_out.h @@ -30,11 +30,19 @@ #include "../img_format.h" //#include "vidix/vidix.h" + +#define ROTATE(t, x, y) do { \ + t rot_tmp = x; \ + x = y; \ + y = -rot_tmp; \ +} while(0) + #define VO_EVENT_EXPOSE 1 #define VO_EVENT_RESIZE 2 #define VO_EVENT_KEYPRESS 4 #define VO_EVENT_REINIT 8 #define VO_EVENT_MOVE 16 +#define VO_EVENT_MOUSE 32 /* Obsolete: VOCTRL_QUERY_VAA 1 */ /* does the device support the required format */ @@ -43,7 +51,6 @@ #define VOCTRL_RESET 3 /* true if vo driver can use GUI created windows */ #define VOCTRL_GUISUPPORT 4 -#define VOCTRL_GUI_NOWINDOW 19 /* used to switch to fullscreen */ #define VOCTRL_FULLSCREEN 5 /* signal a device pause */ @@ -63,7 +70,6 @@ /* equalizer controls */ #define VOCTRL_SET_EQUALIZER 17 #define VOCTRL_GET_EQUALIZER 18 -//#define VOCTRL_GUI_NOWINDOW 19 /* Frame duplication */ #define VOCTRL_DUPLICATE_FRAME 20 // ... 21 @@ -107,6 +113,7 @@ typedef struct { #define VOFLAG_FLIPPING 0x08 #define VOFLAG_HIDDEN 0x10 //< Use to create a hidden window #define VOFLAG_STEREO 0x20 //< Use to create a stereo-capable window +#define VOFLAG_DEPTH 0x40 //< Request a depth buffer #define VOFLAG_XOVERLAY_SUB_VO 0x10000 typedef struct vo_info_s @@ -223,6 +230,9 @@ extern int vo_directrendering; extern int vo_vsync; extern int vo_fsmode; extern float vo_panscan; +extern float vo_border_pos_x; +extern float vo_border_pos_y; +extern int vo_rotate; extern int vo_adapter_num; extern int vo_refresh_rate; extern int vo_keepaspect; @@ -278,4 +288,13 @@ void calc_src_dst_rects(int src_width, int src_height, struct vo_rect *src, stru struct vo_rect *borders, const struct vo_rect *crop); void vo_mouse_movement(int posx, int posy); +static inline int apply_border_pos(int full, int part, float pos) { + if (pos >= 0.0 && pos <= 1.0) { + return pos*(full - part); + } + if (pos < 0) + return pos * part; + return full - part + (pos - 1) * part; +} + #endif /* MPLAYER_VIDEO_OUT_H */ diff --git a/libavfilter/libmpcodecs/mp_image.c b/libavfilter/libmpcodecs/mp_image.c index 100ace92c..0e4d6d759 100644 --- a/libavfilter/libmpcodecs/mp_image.c +++ b/libavfilter/libmpcodecs/mp_image.c @@ -128,6 +128,10 @@ void ff_mp_image_setfmt(mp_image_t* mpi,unsigned int out_fmt){ mpi->flags|=MP_IMGFLAG_SWAPPED; return; } + if (IMGFMT_IS_XYZ(out_fmt)) { + mpi->bpp=3*((IMGFMT_XYZ_DEPTH(out_fmt) + 7) & ~7); + return; + } mpi->num_planes=3; if (out_fmt == IMGFMT_GBR24P) { mpi->bpp=24; @@ -243,7 +247,7 @@ mp_image_t* ff_new_mp_image(int w,int h){ void ff_free_mp_image(mp_image_t* mpi){ if(!mpi) return; if(mpi->flags&MP_IMGFLAG_ALLOCATED){ - /* becouse we allocate the whole image in once */ + /* because we allocate the whole image at once */ av_free(mpi->planes[0]); if (mpi->flags & MP_IMGFLAG_RGB_PALETTE) av_free(mpi->planes[1]); diff --git a/libavfilter/libmpcodecs/vf.h b/libavfilter/libmpcodecs/vf.h index 0d26296f2..d8fc66be4 100644 --- a/libavfilter/libmpcodecs/vf.h +++ b/libavfilter/libmpcodecs/vf.h @@ -103,7 +103,7 @@ typedef struct vf_seteq_s #define VFCTRL_CHANGE_RECTANGLE 9 /* Change the rectangle boundaries */ #define VFCTRL_FLIP_PAGE 10 /* Tell the vo to flip pages */ #define VFCTRL_DUPLICATE_FRAME 11 /* For encoding - encode zero-change frame */ -#define VFCTRL_SKIP_NEXT_FRAME 12 /* For encoding - drop the next frame that passes thru */ +#define VFCTRL_SKIP_NEXT_FRAME 12 /* For encoding - drop the next frame that passes through */ #define VFCTRL_FLUSH_FRAMES 13 /* For encoding - flush delayed frames */ #define VFCTRL_SCREENSHOT 14 /* Make a screenshot */ #define VFCTRL_INIT_EOSD 15 /* Select EOSD renderer */ diff --git a/libavfilter/libmpcodecs/vf_eq.c b/libavfilter/libmpcodecs/vf_eq.c index c926c5180..f8efa846c 100644 --- a/libavfilter/libmpcodecs/vf_eq.c +++ b/libavfilter/libmpcodecs/vf_eq.c @@ -37,7 +37,7 @@ struct vf_priv_s { int contrast; }; -#if HAVE_MMX +#if HAVE_MMX && HAVE_6REGS static void process_MMX(unsigned char *dest, int dstride, unsigned char *src, int sstride, int w, int h, int brightness, int contrast) { @@ -224,7 +224,7 @@ static int vf_open(vf_instance_t *vf, char *args) if (args) sscanf(args, "%d:%d", &vf->priv->brightness, &vf->priv->contrast); process = process_C; -#if HAVE_MMX +#if HAVE_MMX && HAVE_6REGS if(ff_gCpuCaps.hasMMX) process = process_MMX; #endif diff --git a/libavfilter/libmpcodecs/vf_eq2.c b/libavfilter/libmpcodecs/vf_eq2.c index 7a3ef312a..c9c3ff69f 100644 --- a/libavfilter/libmpcodecs/vf_eq2.c +++ b/libavfilter/libmpcodecs/vf_eq2.c @@ -120,7 +120,7 @@ void create_lut (eq2_param_t *par) par->lut_clean = 1; } -#if HAVE_MMX +#if HAVE_MMX && HAVE_6REGS static void affine_1d_MMX (eq2_param_t *par, unsigned char *dst, unsigned char *src, unsigned w, unsigned h, unsigned dstride, unsigned sstride) @@ -289,7 +289,7 @@ void check_values (eq2_param_t *par) if ((par->c == 1.0) && (par->b == 0.0) && (par->g == 1.0)) { par->adjust = NULL; } -#if HAVE_MMX +#if HAVE_MMX && HAVE_6REGS else if (par->g == 1.0 && ff_gCpuCaps.hasMMX) { par->adjust = &affine_1d_MMX; } diff --git a/libavfilter/libmpcodecs/vf_fspp.c b/libavfilter/libmpcodecs/vf_fspp.c index a8a33e264..e1b26bc62 100644 --- a/libavfilter/libmpcodecs/vf_fspp.c +++ b/libavfilter/libmpcodecs/vf_fspp.c @@ -24,7 +24,7 @@ * "Aria Nosratinia Embedded Post-Processing for * Enhancement of Compressed Images (1999)" * (http://citeseer.nj.nec.com/nosratinia99embedded.html) - * Futher, with splitting (i)dct into hor/ver passes, one of them can be + * Further, with splitting (i)dct into hor/ver passes, one of them can be * performed once per block, not pixel. This allows for much better speed. */ @@ -75,7 +75,7 @@ static const short custom_threshold[64]= 20, 27, 26, 23, 20, 15, 11, 5 }; -static const uint8_t __attribute__((aligned(32))) dither[8][8]={ +DECLARE_ALIGNED(32, static const uint8_t, dither)[8][8] = { { 0, 48, 12, 60, 3, 51, 15, 63, }, { 32, 16, 44, 28, 35, 19, 47, 31, }, { 8, 56, 4, 52, 11, 59, 7, 55, }, @@ -215,11 +215,11 @@ static void store_slice_mmx(uint8_t *dst, int16_t *src, long dst_stride, long sr "psraw %%mm5, %%mm3 \n\t" "psraw %%mm5, %%mm4 \n\t" "1: \n\t" - "movq %%mm7, (%%"REG_S",%%"REG_a",) \n\t" + "movq %%mm7, (%%"REG_S",%%"REG_a") \n\t" "movq (%%"REG_S"), %%mm0 \n\t" "movq 8(%%"REG_S"), %%mm1 \n\t" - "movq %%mm7, 8(%%"REG_S",%%"REG_a",) \n\t" + "movq %%mm7, 8(%%"REG_S",%%"REG_a") \n\t" "paddw %%mm3, %%mm0 \n\t" "paddw %%mm4, %%mm1 \n\t" @@ -286,15 +286,15 @@ static void store_slice2_mmx(uint8_t *dst, int16_t *src, long dst_stride, long s "movq 8(%%"REG_S"), %%mm1 \n\t" "paddw %%mm3, %%mm0 \n\t" - "paddw (%%"REG_S",%%"REG_a",), %%mm0 \n\t" + "paddw (%%"REG_S",%%"REG_a"), %%mm0 \n\t" "paddw %%mm4, %%mm1 \n\t" - "movq 8(%%"REG_S",%%"REG_a",), %%mm6 \n\t" + "movq 8(%%"REG_S",%%"REG_a"), %%mm6 \n\t" - "movq %%mm7, (%%"REG_S",%%"REG_a",) \n\t" + "movq %%mm7, (%%"REG_S",%%"REG_a") \n\t" "psraw %%mm2, %%mm0 \n\t" "paddw %%mm6, %%mm1 \n\t" - "movq %%mm7, 8(%%"REG_S",%%"REG_a",) \n\t" + "movq %%mm7, 8(%%"REG_S",%%"REG_a") \n\t" "psraw %%mm2, %%mm1 \n\t" "packuswb %%mm1, %%mm0 \n\t" @@ -416,7 +416,7 @@ static void filter(struct vf_priv_s *p, uint8_t *dst, uint8_t *src, const int stride= is_luma ? p->temp_stride : (width+16);//((width+16+15)&(~15)) const int step=6-p->log2_count; const int qps= 3 + is_luma; - int32_t __attribute__((aligned(32))) block_align[4*8*BLOCKSZ+ 4*8*BLOCKSZ]; + DECLARE_ALIGNED(32, int32_t, block_align)[4*8*BLOCKSZ+ 4*8*BLOCKSZ]; int16_t *block= (int16_t *)block_align; int16_t *block3=(int16_t *)(block_align+4*8*BLOCKSZ); @@ -873,7 +873,7 @@ static void column_fidct_c(int16_t* thr_adr, int16_t *data, int16_t *output, int static void column_fidct_mmx(int16_t* thr_adr, int16_t *data, int16_t *output, int cnt) { - uint64_t __attribute__((aligned(8))) temps[4]; + DECLARE_ALIGNED(8, uint64_t, temps)[4]; __asm__ volatile( ASMALIGN(4) "1: \n\t" @@ -1598,6 +1598,10 @@ static void column_fidct_mmx(int16_t* thr_adr, int16_t *data, int16_t *output, : "+S"(data), "+D"(output), "+c"(cnt), "=o"(temps) : "d"(thr_adr) + NAMED_CONSTRAINTS_ADD(ff_MM_FIX_0_707106781,MM_2,MM_FIX_1_414213562_A,MM_FIX_1_414213562,MM_FIX_0_382683433, + ff_MM_FIX_0_541196100,MM_FIX_1_306562965,MM_FIX_0_847759065) + NAMED_CONSTRAINTS_ADD(MM_FIX_0_566454497,MM_FIX_0_198912367,MM_FIX_2_613125930,MM_FIX_1_847759065, + MM_FIX_1_082392200) : "%"REG_a ); } @@ -1674,7 +1678,7 @@ static void row_idct_c(int16_t* workspace, static void row_idct_mmx (int16_t* workspace, int16_t* output_adr, int output_stride, int cnt) { - uint64_t __attribute__((aligned(8))) temps[4]; + DECLARE_ALIGNED(8, uint64_t, temps)[4]; __asm__ volatile( "lea (%%"REG_a",%%"REG_a",2), %%"REG_d" \n\t" "1: \n\t" @@ -1816,7 +1820,7 @@ static void row_idct_mmx (int16_t* workspace, "paddw (%%"REG_D"), %%mm5 \n\t" "psraw $3, %%mm7 \n\t" - "paddw (%%"REG_D",%%"REG_a",), %%mm1 \n\t" + "paddw (%%"REG_D",%%"REG_a"), %%mm1 \n\t" "paddw %%mm2, %%mm0 \n\t" "paddw (%%"REG_D",%%"REG_a",2), %%mm7 \n\t" @@ -1825,7 +1829,7 @@ static void row_idct_mmx (int16_t* workspace, "movq %%mm5, (%%"REG_D") \n\t" "paddw %%mm2, %%mm6 \n\t" - "movq %%mm1, (%%"REG_D",%%"REG_a",) \n\t" + "movq %%mm1, (%%"REG_D",%%"REG_a") \n\t" "psraw $3, %%mm0 \n\t" "movq %%mm7, (%%"REG_D",%%"REG_a",2) \n\t" @@ -1837,7 +1841,7 @@ static void row_idct_mmx (int16_t* workspace, "paddw (%%"REG_D",%%"REG_a",2), %%mm0 \n\t" "psubw %%mm4, %%mm5 \n\t" //d3 - "paddw (%%"REG_D",%%"REG_d",), %%mm3 \n\t" + "paddw (%%"REG_D",%%"REG_d"), %%mm3 \n\t" "psraw $3, %%mm6 \n\t" "paddw 1*8+%3, %%mm4 \n\t" //d4 @@ -1852,13 +1856,13 @@ static void row_idct_mmx (int16_t* workspace, "paddw (%%"REG_D"), %%mm5 \n\t" "psraw $3, %%mm4 \n\t" - "paddw (%%"REG_D",%%"REG_a",), %%mm4 \n\t" + "paddw (%%"REG_D",%%"REG_a"), %%mm4 \n\t" "add $"DCTSIZE_S"*2*4, %%"REG_S" \n\t" //4 rows - "movq %%mm3, (%%"REG_D",%%"REG_d",) \n\t" + "movq %%mm3, (%%"REG_D",%%"REG_d") \n\t" "movq %%mm6, (%%"REG_D",%%"REG_a",4) \n\t" "movq %%mm5, (%%"REG_D") \n\t" - "movq %%mm4, (%%"REG_D",%%"REG_a",) \n\t" + "movq %%mm4, (%%"REG_D",%%"REG_a") \n\t" "sub %%"REG_d", %%"REG_D" \n\t" "add $8, %%"REG_D" \n\t" @@ -1867,6 +1871,8 @@ static void row_idct_mmx (int16_t* workspace, : "+S"(workspace), "+D"(output_adr), "+c"(cnt), "=o"(temps) : "a"(output_stride*sizeof(short)) + NAMED_CONSTRAINTS_ADD(MM_FIX_1_414213562_A,MM_FIX_2_613125930,MM_FIX_1_847759065,MM_FIX_1_082392200, + MM_FIX_1_414213562,MM_DESCALE_RND) : "%"REG_d ); } @@ -1940,14 +1946,14 @@ static void row_fdct_c(int16_t *data, const uint8_t *pixels, int line_size, int static void row_fdct_mmx(int16_t *data, const uint8_t *pixels, int line_size, int cnt) { - uint64_t __attribute__((aligned(8))) temps[4]; + DECLARE_ALIGNED(8, uint64_t, temps)[4]; __asm__ volatile( "lea (%%"REG_a",%%"REG_a",2), %%"REG_d" \n\t" "6: \n\t" "movd (%%"REG_S"), %%mm0 \n\t" "pxor %%mm7, %%mm7 \n\t" - "movd (%%"REG_S",%%"REG_a",), %%mm1 \n\t" + "movd (%%"REG_S",%%"REG_a"), %%mm1 \n\t" "punpcklbw %%mm7, %%mm0 \n\t" "movd (%%"REG_S",%%"REG_a",2), %%mm2 \n\t" @@ -1962,7 +1968,7 @@ static void row_fdct_mmx(int16_t *data, const uint8_t *pixels, int line_size, "movd (%%"REG_S",%%"REG_a",4), %%mm3 \n\t" //7 ;prefetch! "movq %%mm1, %%mm6 \n\t" - "movd (%%"REG_S",%%"REG_d",), %%mm4 \n\t" //6 + "movd (%%"REG_S",%%"REG_d"), %%mm4 \n\t" //6 "punpcklbw %%mm7, %%mm3 \n\t" "psubw %%mm3, %%mm5 \n\t" @@ -1974,16 +1980,16 @@ static void row_fdct_mmx(int16_t *data, const uint8_t *pixels, int line_size, "movd (%%"REG_S",%%"REG_a",2), %%mm3 \n\t" //5 "paddw %%mm4, %%mm1 \n\t" - "movq %%mm5, 0*8+%3 \n\t" //t7 + "movq %%mm5, %3 \n\t" //t7 "punpcklbw %%mm7, %%mm3 \n\t" - "movq %%mm6, 1*8+%3 \n\t" //t6 + "movq %%mm6, %4 \n\t" //t6 "movq %%mm2, %%mm4 \n\t" "movd (%%"REG_S"), %%mm5 \n\t" //3 "paddw %%mm3, %%mm2 \n\t" - "movd (%%"REG_S",%%"REG_a",), %%mm6 \n\t" //4 + "movd (%%"REG_S",%%"REG_a"), %%mm6 \n\t" //4 "punpcklbw %%mm7, %%mm5 \n\t" "psubw %%mm3, %%mm4 \n\t" @@ -2023,7 +2029,7 @@ static void row_fdct_mmx(int16_t *data, const uint8_t *pixels, int line_size, "psubw %%mm1, %%mm5 \n\t" //d1 "movq %%mm0, %%mm6 \n\t" - "movq 1*8+%3, %%mm1 \n\t" + "movq %4, %%mm1 \n\t" "punpcklwd %%mm5, %%mm0 \n\t" "punpckhwd %%mm5, %%mm6 \n\t" @@ -2047,7 +2053,7 @@ static void row_fdct_mmx(int16_t *data, const uint8_t *pixels, int line_size, "movq %%mm7, "DCTSIZE_S"*3*2(%%"REG_D") \n\t" "psllw $2, %%mm3 \n\t" //t10 - "movq 0*8+%3, %%mm2 \n\t" + "movq %3, %%mm2 \n\t" "psllw $2, %%mm4 \n\t" //t11 "pmulhw "MANGLE(ff_MM_FIX_0_707106781)", %%mm4 \n\t" //z3 @@ -2110,8 +2116,9 @@ static void row_fdct_mmx(int16_t *data, const uint8_t *pixels, int line_size, "dec %%"REG_c" \n\t" "jnz 6b \n\t" - : "+S"(pixels), "+D"(data), "+c"(cnt), "=o"(temps) + : "+S"(pixels), "+D"(data), "+c"(cnt), "=o"(temps), "=o"(temps[1]) : "a"(line_size) + NAMED_CONSTRAINTS_ADD(ff_MM_FIX_0_707106781,ff_MM_FIX_0_541196100,MM_FIX_0_382683433,MM_FIX_1_306562965) : "%"REG_d); } diff --git a/libavfilter/libmpcodecs/vf_ilpack.c b/libavfilter/libmpcodecs/vf_ilpack.c index 4db6c0a8b..fbf581706 100644 --- a/libavfilter/libmpcodecs/vf_ilpack.c +++ b/libavfilter/libmpcodecs/vf_ilpack.c @@ -125,7 +125,7 @@ static void pack_li_0_MMX(unsigned char *dst, unsigned char *y, "pxor %%mm0, %%mm0 \n\t" ASMALIGN(4) - ".Lli0: \n\t" + "2: \n\t" "movq (%%"REG_S"), %%mm1 \n\t" "movq (%%"REG_S"), %%mm2 \n\t" @@ -204,7 +204,7 @@ static void pack_li_0_MMX(unsigned char *dst, unsigned char *y, "add $32, %%"REG_D" \n\t" "decl %%ecx \n\t" - "jnz .Lli0 \n\t" + "jnz 2b \n\t" "emms \n\t" "pop %%"REG_BP" \n\t" : @@ -233,7 +233,7 @@ static void pack_li_1_MMX(unsigned char *dst, unsigned char *y, "pxor %%mm0, %%mm0 \n\t" ASMALIGN(4) - ".Lli1: \n\t" + "3: \n\t" "movq (%%"REG_S"), %%mm1 \n\t" "movq (%%"REG_S"), %%mm2 \n\t" @@ -316,7 +316,7 @@ static void pack_li_1_MMX(unsigned char *dst, unsigned char *y, "add $32, %%"REG_D" \n\t" "decl %%ecx \n\t" - "jnz .Lli1 \n\t" + "jnz 3b \n\t" "emms \n\t" "pop %%"REG_BP" \n\t" : diff --git a/libavfilter/libmpcodecs/vf_pp7.c b/libavfilter/libmpcodecs/vf_pp7.c index 30f95307b..89ed4fe67 100644 --- a/libavfilter/libmpcodecs/vf_pp7.c +++ b/libavfilter/libmpcodecs/vf_pp7.c @@ -45,7 +45,7 @@ #define XMAX(a,b) ((a) > (b) ? (a) : (b)) //===========================================================================// -static const uint8_t __attribute__((aligned(8))) dither[8][8]={ +DECLARE_ALIGNED(8, static const uint8_t, dither)[8][8] = { { 0, 48, 12, 60, 3, 51, 15, 63, }, { 32, 16, 44, 28, 35, 19, 47, 31, }, { 8, 56, 4, 52, 11, 59, 7, 55, }, diff --git a/libavfilter/libmpcodecs/vf_uspp.c b/libavfilter/libmpcodecs/vf_uspp.c index 1fb252386..c9d9c1fd1 100644 --- a/libavfilter/libmpcodecs/vf_uspp.c +++ b/libavfilter/libmpcodecs/vf_uspp.c @@ -44,7 +44,7 @@ #define BLOCK 16 //===========================================================================// -static const uint8_t __attribute__((aligned(8))) dither[8][8]={ +DECLARE_ALIGNED(8, static const uint8_t, dither)[8][8] = { { 0*4, 48*4, 12*4, 60*4, 3*4, 51*4, 15*4, 63*4, }, { 32*4, 16*4, 44*4, 28*4, 35*4, 19*4, 47*4, 31*4, }, { 8*4, 56*4, 4*4, 52*4, 11*4, 59*4, 7*4, 55*4, }, @@ -241,7 +241,8 @@ static int config(struct vf_instance *vf, avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; avctx_enc->global_quality= 123; av_dict_set(&opts, "no_bitstream", "1", 0); - avcodec_open2(avctx_enc, enc, &opts); + if (avcodec_open2(avctx_enc, enc, &opts) < 0) + return 0; av_dict_free(&opts); assert(avctx_enc->codec); } diff --git a/libavfilter/pthread.c b/libavfilter/pthread.c index 92c4d08b4..070b3bded 100644 --- a/libavfilter/pthread.c +++ b/libavfilter/pthread.c @@ -170,7 +170,7 @@ static int thread_init_internal(ThreadContext *c, int nb_threads) return 1; c->nb_threads = nb_threads; - c->workers = av_mallocz(sizeof(*c->workers) * nb_threads); + c->workers = av_mallocz_array(sizeof(*c->workers), nb_threads); if (!c->workers) return AVERROR(ENOMEM); diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c index cb6b2b9aa..0db021814 100644 --- a/libavfilter/setpts.c +++ b/libavfilter/setpts.c @@ -82,7 +82,7 @@ enum var_name { VAR_VARS_NB }; -typedef struct { +typedef struct SetPTSContext { const AVClass *class; char *expr_str; AVExpr *expr; diff --git a/libavfilter/f_settb.c b/libavfilter/settb.c similarity index 98% rename from libavfilter/f_settb.c rename to libavfilter/settb.c index d511c14ce..83616c136 100644 --- a/libavfilter/f_settb.c +++ b/libavfilter/settb.c @@ -32,9 +32,9 @@ #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "libavutil/rational.h" +#include "audio.h" #include "avfilter.h" #include "internal.h" -#include "audio.h" #include "video.h" static const char *const var_names[] = { @@ -51,7 +51,7 @@ enum var_name { VAR_VARS_NB }; -typedef struct { +typedef struct SetTBContext { const AVClass *class; char *tb_expr; double var_values[VAR_VARS_NB]; @@ -151,7 +151,7 @@ AVFilter ff_vf_settb = { .inputs = avfilter_vf_settb_inputs, .outputs = avfilter_vf_settb_outputs, }; -#endif +#endif /* CONFIG_SETTB_FILTER */ #if CONFIG_ASETTB_FILTER @@ -184,4 +184,4 @@ AVFilter ff_af_asettb = { .outputs = avfilter_af_asettb_outputs, .priv_class = &asettb_class, }; -#endif +#endif /* CONFIG_ASETTB_FILTER */ diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c index a1bb84316..bcc8e0549 100644 --- a/libavfilter/src_movie.c +++ b/libavfilter/src_movie.c @@ -44,12 +44,12 @@ #include "internal.h" #include "video.h" -typedef struct { +typedef struct MovieStream { AVStream *st; int done; } MovieStream; -typedef struct { +typedef struct MovieContext { /* common A/V fields */ const AVClass *class; int64_t seek_point; ///< seekpoint in microseconds @@ -540,6 +540,16 @@ static int movie_push_frame(AVFilterContext *ctx, unsigned out_id) av_dlog(ctx, "movie_push_frame(): file:'%s' %s\n", movie->file_name, describe_frame_to_str((char[1024]){0}, 1024, movie->frame, frame_type, outlink)); + if (st->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (movie->frame->format != outlink->format) { + av_log(ctx, AV_LOG_ERROR, "Format changed %s -> %s, discarding frame\n", + av_get_pix_fmt_name(outlink->format), + av_get_pix_fmt_name(movie->frame->format) + ); + av_frame_free(&movie->frame); + return 0; + } + } ret = ff_filter_frame(outlink, movie->frame); movie->frame = NULL; diff --git a/libavfilter/unsharp.h b/libavfilter/unsharp.h index 867892085..c2aed64a0 100644 --- a/libavfilter/unsharp.h +++ b/libavfilter/unsharp.h @@ -64,7 +64,7 @@ typedef struct UnsharpFilterParam { uint32_t *sc[MAX_MATRIX_SIZE - 1]; ///< finite state machine storage } UnsharpFilterParam; -typedef struct { +typedef struct UnsharpContext { const AVClass *class; int lmsize_x, lmsize_y, cmsize_x, cmsize_y; float lamount, camount; diff --git a/libavfilter/unsharp_opencl.c b/libavfilter/unsharp_opencl.c index fff16ab52..e619cefde 100644 --- a/libavfilter/unsharp_opencl.c +++ b/libavfilter/unsharp_opencl.c @@ -29,7 +29,7 @@ #include "libavutil/opencl_internal.h" #define PLANE_NUM 3 -#define ROUND_TO_16(a) ((((a- 1)/16)+1)*16) +#define ROUND_TO_16(a) (((((a) - 1)/16)+1)*16) static inline void add_mask_counter(uint32_t *dst, uint32_t *counter1, uint32_t *counter2, int len) { @@ -54,7 +54,7 @@ static int compute_mask(int step, uint32_t *mask) ret = AVERROR(ENOMEM); goto end; } - counter = av_mallocz(sizeof(uint32_t *) * (2 * step + 1)); + counter = av_mallocz_array(2 * step + 1, sizeof(uint32_t *)); if (!counter) { ret = AVERROR(ENOMEM); goto end; @@ -92,12 +92,12 @@ static int compute_mask_matrix(cl_mem cl_mask_matrix, int step_x, int step_y) int i, j, ret = 0; uint32_t *mask_matrix, *mask_x, *mask_y; size_t size_matrix = sizeof(uint32_t) * (2 * step_x + 1) * (2 * step_y + 1); - mask_x = av_mallocz(sizeof(uint32_t) * (2 * step_x + 1)); + mask_x = av_mallocz_array(2 * step_x + 1, sizeof(uint32_t)); if (!mask_x) { ret = AVERROR(ENOMEM); goto end; } - mask_y = av_mallocz(sizeof(uint32_t) * (2 * step_y + 1)); + mask_y = av_mallocz_array(2 * step_y + 1, sizeof(uint32_t)); if (!mask_y) { ret = AVERROR(ENOMEM); goto end; diff --git a/libavfilter/version.h b/libavfilter/version.h index a33ab490d..227d3203f 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 4 -#define LIBAVFILTER_VERSION_MINOR 2 +#define LIBAVFILTER_VERSION_MINOR 11 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_aspect.c b/libavfilter/vf_aspect.c index 97fb21692..84dbee95d 100644 --- a/libavfilter/vf_aspect.c +++ b/libavfilter/vf_aspect.c @@ -56,7 +56,7 @@ enum var_name { VARS_NB }; -typedef struct { +typedef struct AspectContext { const AVClass *class; AVRational dar; AVRational sar; diff --git a/libavfilter/vf_blackdetect.c b/libavfilter/vf_blackdetect.c index 90a28a942..94af61346 100644 --- a/libavfilter/vf_blackdetect.c +++ b/libavfilter/vf_blackdetect.c @@ -134,6 +134,7 @@ static int request_frame(AVFilterLink *outlink) return ret; } +// TODO: document metadata static int filter_frame(AVFilterLink *inlink, AVFrame *picref) { AVFilterContext *ctx = inlink->dst; @@ -161,12 +162,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) /* black starts here */ blackdetect->black_started = 1; blackdetect->black_start = picref->pts; + av_dict_set(avpriv_frame_get_metadatap(picref), "lavfi.black_start", + av_ts2timestr(blackdetect->black_start, &inlink->time_base), 0); } } else if (blackdetect->black_started) { /* black ends here */ blackdetect->black_started = 0; blackdetect->black_end = picref->pts; check_black_end(ctx); + av_dict_set(avpriv_frame_get_metadatap(picref), "lavfi.black_end", + av_ts2timestr(blackdetect->black_end, &inlink->time_base), 0); } blackdetect->last_picref_pts = picref->pts; diff --git a/libavfilter/vf_blackframe.c b/libavfilter/vf_blackframe.c index 9b0c97352..1be9fcca9 100644 --- a/libavfilter/vf_blackframe.c +++ b/libavfilter/vf_blackframe.c @@ -37,7 +37,7 @@ #include "internal.h" #include "video.h" -typedef struct { +typedef struct BlackFrameContext { const AVClass *class; int bamount; ///< black amount int bthresh; ///< black threshold @@ -58,6 +58,10 @@ static int query_formats(AVFilterContext *ctx) return 0; } +#define SET_META(key, format, value) \ + snprintf(buf, sizeof(buf), format, value); \ + av_dict_set(metadata, key, buf, 0) + static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; @@ -65,6 +69,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) int x, i; int pblack = 0; uint8_t *p = frame->data[0]; + AVDictionary **metadata; + char buf[32]; for (i = 0; i < frame->height; i++) { for (x = 0; x < inlink->w; x++) @@ -76,13 +82,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) s->last_keyframe = s->frame; pblack = s->nblack * 100 / (inlink->w * inlink->h); - if (pblack >= s->bamount) + if (pblack >= s->bamount) { + metadata = avpriv_frame_get_metadatap(frame); + av_log(ctx, AV_LOG_INFO, "frame:%u pblack:%u pts:%"PRId64" t:%f " "type:%c last_keyframe:%d\n", s->frame, pblack, frame->pts, frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base), av_get_picture_type_char(frame->pict_type), s->last_keyframe); + SET_META("lavfi.blackframe.pblack", "%u", pblack); + } + s->frame++; s->nblack = 0; return ff_filter_frame(inlink->dst->outputs[0], frame); diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c index d422a9c94..8bf19ffd5 100644 --- a/libavfilter/vf_blend.c +++ b/libavfilter/vf_blend.c @@ -179,10 +179,10 @@ static void blend_## name(const uint8_t *top, int top_linesize, \ #define A top[j] #define B bottom[j] -#define MULTIPLY(x, a, b) (x * ((a * b) / 255)) -#define SCREEN(x, a, b) (255 - x * ((255 - a) * (255 - b) / 255)) -#define BURN(a, b) ((a == 0) ? a : FFMAX(0, 255 - ((255 - b) << 8) / a)) -#define DODGE(a, b) ((a == 255) ? a : FFMIN(255, ((b << 8) / (255 - a)))) +#define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / 255)) +#define SCREEN(x, a, b) (255 - (x) * ((255 - (a)) * (255 - (b)) / 255)) +#define BURN(a, b) (((a) == 0) ? (a) : FFMAX(0, 255 - ((255 - (b)) << 8) / (a))) +#define DODGE(a, b) (((a) == 255) ? (a) : FFMIN(255, (((b) << 8) / (255 - (a))))) DEFINE_BLEND(addition, FFMIN(255, A + B)) DEFINE_BLEND(average, (A + B) / 2) diff --git a/libavfilter/vf_boxblur.c b/libavfilter/vf_boxblur.c index 3183f435f..1fa5135d9 100644 --- a/libavfilter/vf_boxblur.c +++ b/libavfilter/vf_boxblur.c @@ -55,13 +55,13 @@ enum var_name { VARS_NB }; -typedef struct { +typedef struct FilterParam { int radius; int power; char *radius_expr; } FilterParam; -typedef struct { +typedef struct BoxBlurContext { const AVClass *class; FilterParam luma_param; FilterParam chroma_param; diff --git a/libavfilter/vf_colormatrix.c b/libavfilter/vf_colormatrix.c index 43654ae36..91ca057fd 100644 --- a/libavfilter/vf_colormatrix.c +++ b/libavfilter/vf_colormatrix.c @@ -37,7 +37,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/avstring.h" -#define NS(n) n < 0 ? (int)(n*65536.0-0.5+DBL_EPSILON) : (int)(n*65536.0+0.5) +#define NS(n) ((n) < 0 ? (int)((n)*65536.0-0.5+DBL_EPSILON) : (int)((n)*65536.0+0.5)) #define CB(n) av_clip_uint8(n) static const double yuv_coeff[4][3][3] = { @@ -353,6 +353,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) case AVCOL_SPC_BT470BG : source = COLOR_MODE_BT601 ; break; default : av_log(ctx, AV_LOG_ERROR, "Input frame does not specify a supported colorspace, and none has been specified as source either\n"); + av_frame_free(&out); return AVERROR(EINVAL); } color->mode = source * 4 + color->dest; diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c index 261db3377..a2f029a2f 100644 --- a/libavfilter/vf_crop.c +++ b/libavfilter/vf_crop.c @@ -73,7 +73,7 @@ enum var_name { VAR_VARS_NB }; -typedef struct { +typedef struct CropContext { const AVClass *class; int x; ///< x offset of the non-cropped area with respect to the input area int y; ///< y offset of the non-cropped area with respect to the input area @@ -95,7 +95,7 @@ static int query_formats(AVFilterContext *ctx) AVFilterFormats *formats = NULL; int fmt; - for (fmt = 0; fmt < AV_PIX_FMT_NB; fmt++) { + for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); if (!(desc->flags & (AV_PIX_FMT_FLAG_HWACCEL | AV_PIX_FMT_FLAG_BITSTREAM)) && !((desc->log2_chroma_w || desc->log2_chroma_h) && !(desc->flags & AV_PIX_FMT_FLAG_PLANAR))) diff --git a/libavfilter/vf_cropdetect.c b/libavfilter/vf_cropdetect.c index 4a6b658e0..ed8e7a8c1 100644 --- a/libavfilter/vf_cropdetect.c +++ b/libavfilter/vf_cropdetect.c @@ -32,7 +32,7 @@ #include "internal.h" #include "video.h" -typedef struct { +typedef struct CropDetectContext { const AVClass *class; int x1, y1, x2, y2; int limit; diff --git a/libavfilter/vf_curves.c b/libavfilter/vf_curves.c index 93799b0b1..b17c391ff 100644 --- a/libavfilter/vf_curves.c +++ b/libavfilter/vf_curves.c @@ -331,8 +331,10 @@ static int parse_psfile(AVFilterContext *ctx, const char *fname) return ret; #define READ16(dst) do { \ - if (size < 2) \ - return AVERROR_INVALIDDATA; \ + if (size < 2) { \ + ret = AVERROR_INVALIDDATA; \ + goto end; \ + } \ dst = AV_RB16(buf); \ buf += 2; \ size -= 2; \ diff --git a/libavfilter/vf_decimate.c b/libavfilter/vf_decimate.c index 5efafe9f7..ffb9320c1 100644 --- a/libavfilter/vf_decimate.c +++ b/libavfilter/vf_decimate.c @@ -246,7 +246,7 @@ static int config_input(AVFilterLink *inlink) dm->nxblocks = (w + dm->blockx/2 - 1) / (dm->blockx/2); dm->nyblocks = (h + dm->blocky/2 - 1) / (dm->blocky/2); dm->bdiffsize = dm->nxblocks * dm->nyblocks; - dm->bdiffs = av_malloc(dm->bdiffsize * sizeof(*dm->bdiffs)); + dm->bdiffs = av_malloc_array(dm->bdiffsize, sizeof(*dm->bdiffs)); dm->queue = av_calloc(dm->cycle, sizeof(*dm->queue)); if (!dm->bdiffs || !dm->queue) diff --git a/libavfilter/vf_dejudder.c b/libavfilter/vf_dejudder.c index 1d96c394e..ab525b666 100644 --- a/libavfilter/vf_dejudder.c +++ b/libavfilter/vf_dejudder.c @@ -95,7 +95,7 @@ static av_cold int dejudder_init(AVFilterContext *ctx) { DejudderContext *dj = ctx->priv; - dj->ringbuff = av_mallocz(sizeof(*dj->ringbuff) * (dj->cycle+2)); + dj->ringbuff = av_mallocz_array(dj->cycle+2, sizeof(*dj->ringbuff)); if (!dj->ringbuff) return AVERROR(ENOMEM); diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c index fbc898387..6ccdfb21d 100644 --- a/libavfilter/vf_delogo.c +++ b/libavfilter/vf_delogo.c @@ -148,7 +148,7 @@ static void apply_delogo(uint8_t *dst, int dst_linesize, } } -typedef struct { +typedef struct DelogoContext { const AVClass *class; int x, y, w, h, band, show; } DelogoContext; diff --git a/libavfilter/vf_deshake.c b/libavfilter/vf_deshake.c index f77a9bd44..50aa451a3 100644 --- a/libavfilter/vf_deshake.c +++ b/libavfilter/vf_deshake.c @@ -62,8 +62,8 @@ #include "deshake.h" #include "deshake_opencl.h" -#define CHROMA_WIDTH(link) -((-link->w) >> av_pix_fmt_desc_get(link->format)->log2_chroma_w) -#define CHROMA_HEIGHT(link) -((-link->h) >> av_pix_fmt_desc_get(link->format)->log2_chroma_h) +#define CHROMA_WIDTH(link) (-((-(link)->w) >> av_pix_fmt_desc_get((link)->format)->log2_chroma_w)) +#define CHROMA_HEIGHT(link) (-((-(link)->h) >> av_pix_fmt_desc_get((link)->format)->log2_chroma_h)) #define OFFSET(x) offsetof(DeshakeContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM @@ -132,7 +132,7 @@ static void find_block_motion(DeshakeContext *deshake, uint8_t *src1, int smallest = INT_MAX; int tmp, tmp2; - #define CMP(i, j) deshake->c.sad[0](deshake, src1 + cy * stride + cx, \ + #define CMP(i, j) deshake->c.sad[0](NULL, src1 + cy * stride + cx, \ src2 + (j) * stride + (i), stride, \ deshake->blocksize) @@ -249,7 +249,7 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2, int contrast; int pos; - double *angles = av_malloc(sizeof(*angles) * width * height / (16 * deshake->blocksize)); + double *angles = av_malloc_array(width * height / (16 * deshake->blocksize), sizeof(*angles)); int center_x = 0, center_y = 0; double p_x, p_y; diff --git a/libavfilter/vf_drawbox.c b/libavfilter/vf_drawbox.c index dd884a744..115df884e 100644 --- a/libavfilter/vf_drawbox.c +++ b/libavfilter/vf_drawbox.c @@ -66,7 +66,7 @@ enum var_name { VARS_NB }; -typedef struct { +typedef struct DrawBoxContext { const AVClass *class; int x, y, w, h; int thickness; diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 1690b3896..0b93d1453 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -27,10 +27,20 @@ */ #include "config.h" + #if HAVE_SYS_TIME_H #include #endif +#include +#include #include +#if HAVE_UNISTD_H +#include +#endif + +#if CONFIG_LIBFONTCONFIG +#include +#endif #include "libavutil/avstring.h" #include "libavutil/bprint.h" @@ -49,13 +59,14 @@ #include "internal.h" #include "video.h" +#if CONFIG_LIBFRIBIDI +#include +#endif + #include #include FT_FREETYPE_H #include FT_GLYPH_H #include FT_STROKER_H -#if CONFIG_FONTCONFIG -#include -#endif static const char *const var_names[] = { "dar", @@ -121,10 +132,13 @@ enum expansion_mode { EXP_STRFTIME, }; -typedef struct { +typedef struct DrawTextContext { const AVClass *class; enum expansion_mode exp_mode; ///< expansion mode to use for the text int reinit; ///< tells if the filter is being reinited +#if CONFIG_LIBFONTCONFIG + uint8_t *font; ///< font to be used +#endif uint8_t *fontfile; ///< font to be used uint8_t *text; ///< text to be drawn AVBPrint expanded_text; ///< used to contain the expanded text @@ -172,6 +186,9 @@ typedef struct { int tc24hmax; ///< 1 if timecode is wrapped to 24 hours, 0 otherwise int reload; ///< reload text file for each frame int start_number; ///< starting frame number for n/frame_num var +#if CONFIG_LIBFRIBIDI + int text_shaping; ///< 1 to shape the text before drawing it +#endif AVDictionary *metadata; } DrawTextContext; @@ -198,6 +215,9 @@ static const AVOption drawtext_options[]= { #if FF_API_DRAWTEXT_OLD_TIMELINE {"draw", "if false do not draw (deprecated)", OFFSET(draw_expr), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS}, #endif +#if CONFIG_LIBFONTCONFIG + { "font", "Font name", OFFSET(font), AV_OPT_TYPE_STRING, { .str = "Sans" }, .flags = FLAGS }, +#endif {"expansion", "set the expansion mode", OFFSET(exp_mode), AV_OPT_TYPE_INT, {.i64=EXP_NORMAL}, 0, 2, FLAGS, "expansion"}, {"none", "set no expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NONE}, 0, 0, FLAGS, "expansion"}, @@ -213,6 +233,10 @@ static const AVOption drawtext_options[]= { {"fix_bounds", "if true, check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS}, {"start_number", "start frame number for n/frame_num variable", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, +#if CONFIG_LIBFRIBIDI + {"text_shaping", "attempt to shape text before drawing", OFFSET(text_shaping), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS}, +#endif + /* FT_LOAD_* flags */ { "ft_load_flags", "set font loading flags for libfreetype", OFFSET(ft_load_flags), AV_OPT_TYPE_FLAGS, { .i64 = FT_LOAD_DEFAULT }, 0, INT_MAX, FLAGS, "ft_load_flags" }, { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_DEFAULT }, .flags = FLAGS, .unit = "ft_load_flags" }, @@ -249,8 +273,9 @@ struct ft_error #define FT_ERRMSG(e) ft_errors[e].err_msg -typedef struct { - FT_Glyph *glyph; +typedef struct Glyph { + FT_Glyph glyph; + FT_Glyph border_glyph; uint32_t code; FT_Bitmap bitmap; ///< array holding bitmaps of font FT_Bitmap border_bitmap; ///< array holding bitmaps of font border @@ -282,33 +307,32 @@ static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code) if (FT_Load_Char(s->face, code, s->ft_load_flags)) return AVERROR(EINVAL); - /* save glyph */ - if (!(glyph = av_mallocz(sizeof(*glyph))) || - !(glyph->glyph = av_mallocz(sizeof(*glyph->glyph)))) { + glyph = av_mallocz(sizeof(*glyph)); + if (!glyph) { ret = AVERROR(ENOMEM); goto error; } glyph->code = code; - if (FT_Get_Glyph(s->face->glyph, glyph->glyph)) { + if (FT_Get_Glyph(s->face->glyph, &glyph->glyph)) { ret = AVERROR(EINVAL); goto error; } if (s->borderw) { - FT_Glyph border_glyph = *glyph->glyph; - if (FT_Glyph_StrokeBorder(&border_glyph, s->stroker, 0, 0) || - FT_Glyph_To_Bitmap(&border_glyph, FT_RENDER_MODE_NORMAL, 0, 1)) { + glyph->border_glyph = glyph->glyph; + if (FT_Glyph_StrokeBorder(&glyph->border_glyph, s->stroker, 0, 0) || + FT_Glyph_To_Bitmap(&glyph->border_glyph, FT_RENDER_MODE_NORMAL, 0, 1)) { ret = AVERROR_EXTERNAL; goto error; } - bitmapglyph = (FT_BitmapGlyph) border_glyph; + bitmapglyph = (FT_BitmapGlyph) glyph->border_glyph; glyph->border_bitmap = bitmapglyph->bitmap; } - if (FT_Glyph_To_Bitmap(glyph->glyph, FT_RENDER_MODE_NORMAL, 0, 1)) { + if (FT_Glyph_To_Bitmap(&glyph->glyph, FT_RENDER_MODE_NORMAL, 0, 1)) { ret = AVERROR_EXTERNAL; goto error; } - bitmapglyph = (FT_BitmapGlyph) *glyph->glyph; + bitmapglyph = (FT_BitmapGlyph) glyph->glyph; glyph->bitmap = bitmapglyph->bitmap; glyph->bitmap_left = bitmapglyph->left; @@ -316,7 +340,7 @@ static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code) glyph->advance = s->face->glyph->advance.x >> 6; /* measure text height to calculate text_height (or the maximum text height) */ - FT_Glyph_Get_CBox(*glyph->glyph, ft_glyph_bbox_pixels, &glyph->bbox); + FT_Glyph_Get_CBox(glyph->glyph, ft_glyph_bbox_pixels, &glyph->bbox); /* cache the newly created glyph */ if (!(node = av_tree_node_alloc())) { @@ -332,73 +356,96 @@ static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code) error: if (glyph) av_freep(&glyph->glyph); + av_freep(&glyph); av_freep(&node); return ret; } -static int load_font_file(AVFilterContext *ctx, const char *path, int index, - const char **error) +static int load_font_file(AVFilterContext *ctx, const char *path, int index) { DrawTextContext *s = ctx->priv; int err; err = FT_New_Face(s->library, path, index, &s->face); if (err) { - *error = FT_ERRMSG(err); + av_log(ctx, AV_LOG_ERROR, "Could not load font \"%s\": %s\n", + s->fontfile, FT_ERRMSG(err)); return AVERROR(EINVAL); } return 0; } -#if CONFIG_FONTCONFIG -static int load_font_fontconfig(AVFilterContext *ctx, const char **error) +#if CONFIG_LIBFONTCONFIG +static int load_font_fontconfig(AVFilterContext *ctx) { DrawTextContext *s = ctx->priv; FcConfig *fontconfig; - FcPattern *pattern, *fpat; + FcPattern *pat, *best; FcResult result = FcResultMatch; FcChar8 *filename; - int err, index; + int index; double size; + int err = AVERROR(ENOENT); fontconfig = FcInitLoadConfigAndFonts(); if (!fontconfig) { - *error = "impossible to init fontconfig\n"; - return AVERROR(EINVAL); + av_log(ctx, AV_LOG_ERROR, "impossible to init fontconfig\n"); + return AVERROR_UNKNOWN; } - pattern = FcNameParse(s->fontfile ? s->fontfile : + pat = FcNameParse(s->fontfile ? s->fontfile : (uint8_t *)(intptr_t)"default"); - if (!pattern) { - *error = "could not parse fontconfig pattern"; + if (!pat) { + av_log(ctx, AV_LOG_ERROR, "could not parse fontconfig pat"); return AVERROR(EINVAL); } - if (!FcConfigSubstitute(fontconfig, pattern, FcMatchPattern)) { - *error = "could not substitue fontconfig options"; /* very unlikely */ + + FcPatternAddString(pat, FC_FAMILY, s->font); + if (s->fontsize) + FcPatternAddDouble(pat, FC_SIZE, (double)s->fontsize); + + FcDefaultSubstitute(pat); + + if (!FcConfigSubstitute(fontconfig, pat, FcMatchPattern)) { + av_log(ctx, AV_LOG_ERROR, "could not substitue fontconfig options"); /* very unlikely */ + FcPatternDestroy(pat); + return AVERROR(ENOMEM); + } + + best = FcFontMatch(fontconfig, pat, &result); + FcPatternDestroy(pat); + + if (!best || result != FcResultMatch) { + av_log(ctx, AV_LOG_ERROR, + "Cannot find a valid font for the family %s\n", + s->font); + goto fail; + } + + if ( + FcPatternGetInteger(best, FC_INDEX, 0, &index ) != FcResultMatch || + FcPatternGetDouble (best, FC_SIZE, 0, &size ) != FcResultMatch) { + av_log(ctx, AV_LOG_ERROR, "impossible to find font information"); return AVERROR(EINVAL); } - FcDefaultSubstitute(pattern); - fpat = FcFontMatch(fontconfig, pattern, &result); - if (!fpat || result != FcResultMatch) { - *error = "impossible to find a matching font"; - return AVERROR(EINVAL); - } - if (FcPatternGetString (fpat, FC_FILE, 0, &filename) != FcResultMatch || - FcPatternGetInteger(fpat, FC_INDEX, 0, &index ) != FcResultMatch || - FcPatternGetDouble (fpat, FC_SIZE, 0, &size ) != FcResultMatch) { - *error = "impossible to find font information"; - return AVERROR(EINVAL); + + if (FcPatternGetString(best, FC_FILE, 0, &filename) != FcResultMatch) { + av_log(ctx, AV_LOG_ERROR, "No file path for %s\n", + s->font); + goto fail; } + av_log(ctx, AV_LOG_INFO, "Using \"%s\"\n", filename); if (!s->fontsize) s->fontsize = size + 0.5; - err = load_font_file(ctx, filename, index, error); + + err = load_font_file(ctx, filename, index); if (err) return err; - FcPatternDestroy(fpat); - FcPatternDestroy(pattern); FcConfigDestroy(fontconfig); - return 0; +fail: + FcPatternDestroy(best); + return err; } #endif @@ -406,19 +453,16 @@ static int load_font(AVFilterContext *ctx) { DrawTextContext *s = ctx->priv; int err; - const char *error = "unknown error\n"; /* load the face, and set up the encoding, which is by default UTF-8 */ - err = load_font_file(ctx, s->fontfile, 0, &error); + err = load_font_file(ctx, s->fontfile, 0); if (!err) return 0; -#if CONFIG_FONTCONFIG - err = load_font_fontconfig(ctx, &error); +#if CONFIG_LIBFONTCONFIG + err = load_font_fontconfig(ctx); if (!err) return 0; #endif - av_log(ctx, AV_LOG_ERROR, "Could not load font \"%s\": %s\n", - s->fontfile, error); return err; } @@ -427,6 +471,7 @@ static int load_textfile(AVFilterContext *ctx) DrawTextContext *s = ctx->priv; int err; uint8_t *textbuf; + uint8_t *tmp; size_t textbuf_size; if ((err = av_file_map(s->textfile, &textbuf, &textbuf_size, 0, ctx)) < 0) { @@ -436,8 +481,11 @@ static int load_textfile(AVFilterContext *ctx) return err; } - if (!(s->text = av_realloc(s->text, textbuf_size + 1))) + if (!(tmp = av_realloc(s->text, textbuf_size + 1))) { + av_file_unmap(textbuf, textbuf_size); return AVERROR(ENOMEM); + } + s->text = tmp; memcpy(s->text, textbuf, textbuf_size); s->text[textbuf_size] = 0; av_file_unmap(textbuf, textbuf_size); @@ -445,6 +493,99 @@ static int load_textfile(AVFilterContext *ctx) return 0; } +static inline int is_newline(uint32_t c) +{ + return c == '\n' || c == '\r' || c == '\f' || c == '\v'; +} + +#if CONFIG_LIBFRIBIDI +static int shape_text(AVFilterContext *ctx) +{ + DrawTextContext *s = ctx->priv; + uint8_t *tmp; + int ret = AVERROR(ENOMEM); + static const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | + FRIBIDI_FLAGS_ARABIC; + FriBidiChar *unicodestr = NULL; + FriBidiStrIndex len; + FriBidiParType direction = FRIBIDI_PAR_LTR; + FriBidiStrIndex line_start = 0; + FriBidiStrIndex line_end = 0; + FriBidiLevel *embedding_levels = NULL; + FriBidiArabicProp *ar_props = NULL; + FriBidiCharType *bidi_types = NULL; + FriBidiStrIndex i,j; + + len = strlen(s->text); + if (!(unicodestr = av_malloc_array(len, sizeof(*unicodestr)))) { + goto out; + } + len = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, + s->text, len, unicodestr); + + bidi_types = av_malloc_array(len, sizeof(*bidi_types)); + if (!bidi_types) { + goto out; + } + + fribidi_get_bidi_types(unicodestr, len, bidi_types); + + embedding_levels = av_malloc_array(len, sizeof(*embedding_levels)); + if (!embedding_levels) { + goto out; + } + + if (!fribidi_get_par_embedding_levels(bidi_types, len, &direction, + embedding_levels)) { + goto out; + } + + ar_props = av_malloc_array(len, sizeof(*ar_props)); + if (!ar_props) { + goto out; + } + + fribidi_get_joining_types(unicodestr, len, ar_props); + fribidi_join_arabic(bidi_types, len, embedding_levels, ar_props); + fribidi_shape(flags, embedding_levels, len, ar_props, unicodestr); + + for (line_end = 0, line_start = 0; line_end < len; line_end++) { + if (is_newline(unicodestr[line_end]) || line_end == len - 1) { + if (!fribidi_reorder_line(flags, bidi_types, + line_end - line_start + 1, line_start, + direction, embedding_levels, unicodestr, + NULL)) { + goto out; + } + line_start = line_end + 1; + } + } + + /* Remove zero-width fill chars put in by libfribidi */ + for (i = 0, j = 0; i < len; i++) + if (unicodestr[i] != FRIBIDI_CHAR_FILL) + unicodestr[j++] = unicodestr[i]; + len = j; + + if (!(tmp = av_realloc(s->text, (len * 4 + 1) * sizeof(*s->text)))) { + /* Use len * 4, as a unicode character can be up to 4 bytes in UTF-8 */ + goto out; + } + + s->text = tmp; + len = fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8, + unicodestr, len, s->text); + ret = 0; + +out: + av_free(unicodestr); + av_free(embedding_levels); + av_free(ar_props); + av_free(bidi_types); + return ret; +} +#endif + static av_cold int init(AVFilterContext *ctx) { int err; @@ -457,7 +598,7 @@ static av_cold int init(AVFilterContext *ctx) "you are encouraged to use the generic timeline support through the 'enable' option\n"); #endif - if (!s->fontfile && !CONFIG_FONTCONFIG) { + if (!s->fontfile && !CONFIG_LIBFONTCONFIG) { av_log(ctx, AV_LOG_ERROR, "No font filename provided\n"); return AVERROR(EINVAL); } @@ -472,6 +613,12 @@ static av_cold int init(AVFilterContext *ctx) return err; } +#if CONFIG_LIBFRIBIDI + if (s->text_shaping) + if ((err = shape_text(ctx)) < 0) + return err; +#endif + if (s->reload && !s->textfile) av_log(ctx, AV_LOG_WARNING, "No file to reload\n"); @@ -549,8 +696,8 @@ static int glyph_enu_free(void *opaque, void *elem) { Glyph *glyph = elem; - FT_Done_Glyph(*glyph->glyph); - av_freep(&glyph->glyph); + FT_Done_Glyph(glyph->glyph); + FT_Done_Glyph(glyph->border_glyph); av_free(elem); return 0; } @@ -580,11 +727,6 @@ static av_cold void uninit(AVFilterContext *ctx) av_bprint_finalize(&s->expanded_text, NULL); } -static inline int is_newline(uint32_t c) -{ - return c == '\n' || c == '\r' || c == '\f' || c == '\v'; -} - static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -665,8 +807,41 @@ static int func_pts(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag) { DrawTextContext *s = ctx->priv; + const char *fmt; + double pts = s->var_values[VAR_T]; + int ret; - av_bprintf(bp, "%.6f", s->var_values[VAR_T]); + fmt = argc >= 1 ? argv[0] : "flt"; + if (argc >= 2) { + int64_t delta; + if ((ret = av_parse_time(&delta, argv[1], 1)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid delta '%s'\n", argv[1]); + return ret; + } + pts += (double)delta / AV_TIME_BASE; + } + if (!strcmp(fmt, "flt")) { + av_bprintf(bp, "%.6f", s->var_values[VAR_T]); + } else if (!strcmp(fmt, "hms")) { + if (isnan(pts)) { + av_bprintf(bp, " ??:??:??.???"); + } else { + int64_t ms = round(pts * 1000); + char sign = ' '; + if (ms < 0) { + sign = '-'; + ms = -ms; + } + av_bprintf(bp, "%c%02d:%02d:%02d.%03d", sign, + (int)(ms / (60 * 60 * 1000)), + (int)(ms / (60 * 1000)) % 60, + (int)(ms / 1000) % 60, + (int)ms % 1000); + } + } else { + av_log(ctx, AV_LOG_ERROR, "Invalid format '%s'\n", fmt); + return AVERROR(EINVAL); + } return 0; } @@ -742,7 +917,7 @@ static const struct drawtext_function { { "expr", 1, 1, 0, func_eval_expr }, { "e", 1, 1, 0, func_eval_expr }, { "pict_type", 0, 0, 0, func_pict_type }, - { "pts", 0, 0, 0, func_pts }, + { "pts", 0, 2, 0, func_pts }, { "gmtime", 0, 1, 'G', func_strftime }, { "localtime", 0, 1, 'L', func_strftime }, { "frame_num", 0, 0, 0, func_frame_num }, @@ -844,7 +1019,7 @@ static int expand_text(AVFilterContext *ctx) } static int draw_glyphs(DrawTextContext *s, AVFrame *frame, - int width, int height, const uint8_t rgbcolor[4], + int width, int height, FFDrawColor *color, int x, int y, int borderw) { char *text = s->expanded_text.str; @@ -1038,17 +1213,17 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame, s->x, s->y, box_w, box_h); if (s->shadowx || s->shadowy) { - if ((ret = draw_glyphs(s, frame, width, height, s->shadowcolor.rgba, + if ((ret = draw_glyphs(s, frame, width, height, &s->shadowcolor, s->shadowx, s->shadowy, 0)) < 0) return ret; } if (s->borderw) { - if ((ret = draw_glyphs(s, frame, width, height, s->bordercolor.rgba, + if ((ret = draw_glyphs(s, frame, width, height, &s->bordercolor, 0, 0, s->borderw)) < 0) return ret; } - if ((ret = draw_glyphs(s, frame, width, height, s->fontcolor.rgba, + if ((ret = draw_glyphs(s, frame, width, height, &s->fontcolor, 0, 0, 0)) < 0) return ret; @@ -1062,9 +1237,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) DrawTextContext *s = ctx->priv; int ret; - if (s->reload) + if (s->reload) { if ((ret = load_textfile(ctx)) < 0) return ret; +#if CONFIG_LIBFRIBIDI + if (s->text_shaping) + if ((ret = shape_text(ctx)) < 0) + return ret; +#endif + } s->var_values[VAR_N] = inlink->frame_count+s->start_number; s->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ? diff --git a/libavfilter/vf_edgedetect.c b/libavfilter/vf_edgedetect.c index c8ec73473..7316412ed 100644 --- a/libavfilter/vf_edgedetect.c +++ b/libavfilter/vf_edgedetect.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Clément Bœsch + * Copyright (c) 2012-2014 Clément Bœsch * * This file is part of FFmpeg. * @@ -25,19 +25,32 @@ * @see https://en.wikipedia.org/wiki/Canny_edge_detector */ +#include "libavutil/avassert.h" #include "libavutil/opt.h" #include "avfilter.h" #include "formats.h" #include "internal.h" #include "video.h" -typedef struct { - const AVClass *class; +enum FilterMode { + MODE_WIRES, + MODE_COLORMIX, + NB_MODE +}; + +struct plane_info { uint8_t *tmpbuf; uint16_t *gradients; char *directions; +}; + +typedef struct { + const AVClass *class; + struct plane_info planes[3]; + int nb_planes; double low, high; uint8_t low_u8, high_u8; + enum FilterMode mode; } EdgeDetectContext; #define OFFSET(x) offsetof(EdgeDetectContext, x) @@ -45,6 +58,9 @@ typedef struct { static const AVOption edgedetect_options[] = { { "high", "set high threshold", OFFSET(high), AV_OPT_TYPE_DOUBLE, {.dbl=50/255.}, 0, 1, FLAGS }, { "low", "set low threshold", OFFSET(low), AV_OPT_TYPE_DOUBLE, {.dbl=20/255.}, 0, 1, FLAGS }, + { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=MODE_WIRES}, 0, NB_MODE-1, FLAGS, "mode" }, + { "wires", "white/gray wires on black", 0, AV_OPT_TYPE_CONST, {.i64=MODE_WIRES}, INT_MIN, INT_MAX, FLAGS, "mode" }, + { "colormix", "mix colors", 0, AV_OPT_TYPE_CONST, {.i64=MODE_COLORMIX}, INT_MIN, INT_MAX, FLAGS, "mode" }, { NULL } }; @@ -61,21 +77,36 @@ static av_cold int init(AVFilterContext *ctx) static int query_formats(AVFilterContext *ctx) { - static const enum AVPixelFormat pix_fmts[] = {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}; - ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); + const EdgeDetectContext *edgedetect = ctx->priv; + + if (edgedetect->mode == MODE_WIRES) { + static const enum AVPixelFormat pix_fmts[] = {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}; + ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); + } else if (edgedetect->mode == MODE_COLORMIX) { + static const enum AVPixelFormat pix_fmts[] = {AV_PIX_FMT_GBRP, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}; + ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); + } else { + av_assert0(0); + } return 0; } static int config_props(AVFilterLink *inlink) { + int p; AVFilterContext *ctx = inlink->dst; EdgeDetectContext *edgedetect = ctx->priv; - edgedetect->tmpbuf = av_malloc(inlink->w * inlink->h); - edgedetect->gradients = av_calloc(inlink->w * inlink->h, sizeof(*edgedetect->gradients)); - edgedetect->directions = av_malloc(inlink->w * inlink->h); - if (!edgedetect->tmpbuf || !edgedetect->gradients || !edgedetect->directions) - return AVERROR(ENOMEM); + edgedetect->nb_planes = inlink->format == AV_PIX_FMT_GRAY8 ? 1 : 3; + for (p = 0; p < edgedetect->nb_planes; p++) { + struct plane_info *plane = &edgedetect->planes[p]; + + plane->tmpbuf = av_malloc(inlink->w * inlink->h); + plane->gradients = av_calloc(inlink->w * inlink->h, sizeof(*plane->gradients)); + plane->directions = av_malloc(inlink->w * inlink->h); + if (!plane->tmpbuf || !plane->gradients || !plane->directions) + return AVERROR(ENOMEM); + } return 0; } @@ -154,15 +185,16 @@ static int get_rounded_direction(int gx, int gy) return DIRECTION_VERTICAL; } -static void sobel(AVFilterContext *ctx, int w, int h, - uint16_t *dst, int dst_linesize, - const uint8_t *src, int src_linesize) +static void sobel(int w, int h, + uint16_t *dst, int dst_linesize, + int8_t *dir, int dir_linesize, + const uint8_t *src, int src_linesize) { int i, j; - EdgeDetectContext *edgedetect = ctx->priv; for (j = 1; j < h - 1; j++) { dst += dst_linesize; + dir += dir_linesize; src += src_linesize; for (i = 1; i < w - 1; i++) { const int gx = @@ -175,17 +207,17 @@ static void sobel(AVFilterContext *ctx, int w, int h, -1*src[-src_linesize + i+1] + 1*src[ src_linesize + i+1]; dst[i] = FFABS(gx) + FFABS(gy); - edgedetect->directions[j*w + i] = get_rounded_direction(gx, gy); + dir[i] = get_rounded_direction(gx, gy); } } } -static void non_maximum_suppression(AVFilterContext *ctx, int w, int h, +static void non_maximum_suppression(int w, int h, uint8_t *dst, int dst_linesize, + const int8_t *dir, int dir_linesize, const uint16_t *src, int src_linesize) { int i, j; - EdgeDetectContext *edgedetect = ctx->priv; #define COPY_MAXIMA(ay, ax, by, bx) do { \ if (src[i] > src[(ay)*src_linesize + i+(ax)] && \ @@ -195,9 +227,10 @@ static void non_maximum_suppression(AVFilterContext *ctx, int w, int h, for (j = 1; j < h - 1; j++) { dst += dst_linesize; + dir += dir_linesize; src += src_linesize; for (i = 1; i < w - 1; i++) { - switch (edgedetect->directions[j*w + i]) { + switch (dir[i]) { case DIRECTION_45UP: COPY_MAXIMA( 1, -1, -1, 1); break; case DIRECTION_45DOWN: COPY_MAXIMA(-1, -1, 1, 1); break; case DIRECTION_HORIZONTAL: COPY_MAXIMA( 0, -1, 0, 1); break; @@ -207,14 +240,11 @@ static void non_maximum_suppression(AVFilterContext *ctx, int w, int h, } } -static void double_threshold(AVFilterContext *ctx, int w, int h, +static void double_threshold(int low, int high, int w, int h, uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize) { int i, j; - EdgeDetectContext *edgedetect = ctx->priv; - const int low = edgedetect->low_u8; - const int high = edgedetect->high_u8; for (j = 0; j < h; j++) { for (i = 0; i < w; i++) { @@ -242,17 +272,29 @@ static void double_threshold(AVFilterContext *ctx, int w, int h, } } +static void color_mix(int w, int h, + uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize) +{ + int i, j; + + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) + dst[i] = (dst[i] + src[i]) >> 1; + dst += dst_linesize; + src += src_linesize; + } +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; EdgeDetectContext *edgedetect = ctx->priv; - AVFilterLink *outlink = inlink->dst->outputs[0]; - uint8_t *tmpbuf = edgedetect->tmpbuf; - uint16_t *gradients = edgedetect->gradients; - int direct = 0; + AVFilterLink *outlink = ctx->outputs[0]; + int p, direct = 0; AVFrame *out; - if (av_frame_is_writable(in)) { + if (edgedetect->mode != MODE_COLORMIX && av_frame_is_writable(in)) { direct = 1; out = in; } else { @@ -264,27 +306,43 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); } - /* gaussian filter to reduce noise */ - gaussian_blur(ctx, inlink->w, inlink->h, - tmpbuf, inlink->w, - in->data[0], in->linesize[0]); + for (p = 0; p < edgedetect->nb_planes; p++) { + struct plane_info *plane = &edgedetect->planes[p]; + uint8_t *tmpbuf = plane->tmpbuf; + uint16_t *gradients = plane->gradients; + int8_t *directions = plane->directions; - /* compute the 16-bits gradients and directions for the next step */ - sobel(ctx, inlink->w, inlink->h, - gradients, inlink->w, - tmpbuf, inlink->w); + /* gaussian filter to reduce noise */ + gaussian_blur(ctx, inlink->w, inlink->h, + tmpbuf, inlink->w, + in->data[p], in->linesize[p]); - /* non_maximum_suppression() will actually keep & clip what's necessary and - * ignore the rest, so we need a clean output buffer */ - memset(tmpbuf, 0, inlink->w * inlink->h); - non_maximum_suppression(ctx, inlink->w, inlink->h, - tmpbuf, inlink->w, - gradients, inlink->w); + /* compute the 16-bits gradients and directions for the next step */ + sobel(inlink->w, inlink->h, + gradients, inlink->w, + directions,inlink->w, + tmpbuf, inlink->w); - /* keep high values, or low values surrounded by high values */ - double_threshold(ctx, inlink->w, inlink->h, - out->data[0], out->linesize[0], - tmpbuf, inlink->w); + /* non_maximum_suppression() will actually keep & clip what's necessary and + * ignore the rest, so we need a clean output buffer */ + memset(tmpbuf, 0, inlink->w * inlink->h); + non_maximum_suppression(inlink->w, inlink->h, + tmpbuf, inlink->w, + directions,inlink->w, + gradients, inlink->w); + + /* keep high values, or low values surrounded by high values */ + double_threshold(edgedetect->low_u8, edgedetect->high_u8, + inlink->w, inlink->h, + out->data[p], out->linesize[p], + tmpbuf, inlink->w); + + if (edgedetect->mode == MODE_COLORMIX) { + color_mix(inlink->w, inlink->h, + out->data[p], out->linesize[p], + in->data[p], in->linesize[p]); + } + } if (!direct) av_frame_free(&in); @@ -293,10 +351,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) static av_cold void uninit(AVFilterContext *ctx) { + int p; EdgeDetectContext *edgedetect = ctx->priv; - av_freep(&edgedetect->tmpbuf); - av_freep(&edgedetect->gradients); - av_freep(&edgedetect->directions); + + for (p = 0; p < edgedetect->nb_planes; p++) { + struct plane_info *plane = &edgedetect->planes[p]; + av_freep(&plane->tmpbuf); + av_freep(&plane->gradients); + av_freep(&plane->directions); + } } static const AVFilterPad edgedetect_inputs[] = { diff --git a/libavfilter/vf_elbg.c b/libavfilter/vf_elbg.c index f92d93671..be0885d30 100644 --- a/libavfilter/vf_elbg.c +++ b/libavfilter/vf_elbg.c @@ -33,7 +33,7 @@ #include "internal.h" #include "video.h" -typedef struct { +typedef struct ColorContext { const AVClass *class; AVLFG lfg; unsigned int lfg_seed; diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c index cc10b122c..80ce75dcd 100644 --- a/libavfilter/vf_fade.c +++ b/libavfilter/vf_fade.c @@ -49,7 +49,7 @@ #define FADE_IN 0 #define FADE_OUT 1 -typedef struct { +typedef struct FadeContext { const AVClass *class; int type; int factor, fade_per_frame; diff --git a/libavfilter/vf_fieldorder.c b/libavfilter/vf_fieldorder.c index 84088a042..5cc612ccd 100644 --- a/libavfilter/vf_fieldorder.c +++ b/libavfilter/vf_fieldorder.c @@ -32,7 +32,7 @@ #include "internal.h" #include "video.h" -typedef struct { +typedef struct FieldOrderContext { const AVClass *class; int dst_tff; ///< output bff/tff int line_size[4]; ///< bytes of pixel data per line for each plane @@ -47,9 +47,10 @@ static int query_formats(AVFilterContext *ctx) /** accept any input pixel format that is not hardware accelerated, not * a bitstream format, and does not have vertically sub-sampled chroma */ if (ctx->inputs[0]) { + const AVPixFmtDescriptor *desc = NULL; formats = NULL; - for (pix_fmt = 0; pix_fmt < AV_PIX_FMT_NB; pix_fmt++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + while ((desc = av_pix_fmt_desc_next(desc))) { + pix_fmt = av_pix_fmt_desc_get_id(desc); if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL || desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) && diff --git a/libavfilter/vf_format.c b/libavfilter/vf_format.c index 98061e915..13b41e466 100644 --- a/libavfilter/vf_format.c +++ b/libavfilter/vf_format.c @@ -35,69 +35,108 @@ #include "internal.h" #include "video.h" -typedef struct { +typedef struct FormatContext { const AVClass *class; char *pix_fmts; + /** - * List of flags telling if a given image format has been listed - * as argument to the filter. + * pix_fmts parsed into AVPixelFormats and terminated with + * AV_PIX_FMT_NONE */ - int listed_pix_fmt_flags[AV_PIX_FMT_NB]; + enum AVPixelFormat *formats; } FormatContext; -#define AV_PIX_FMT_NAME_MAXSIZE 32 +static av_cold void uninit(AVFilterContext *ctx) +{ + FormatContext *s = ctx->priv; + av_freep(&s->formats); +} static av_cold int init(AVFilterContext *ctx) { FormatContext *s = ctx->priv; - const char *cur, *sep; - char pix_fmt_name[AV_PIX_FMT_NAME_MAXSIZE]; - int pix_fmt_name_len, ret; - enum AVPixelFormat pix_fmt; + char *cur, *sep; + int nb_formats = 1; + int i; + int ret; if (!s->pix_fmts) return AVERROR(EINVAL); + /* count the formats */ + cur = s->pix_fmts; + while ((cur = strchr(cur, '|'))) { + nb_formats++; + if (*cur) + cur++; + } + + s->formats = av_malloc_array(nb_formats + 1, sizeof(*s->formats)); + if (!s->formats) + return AVERROR(ENOMEM); + /* parse the list of formats */ - for (cur = s->pix_fmts; cur; cur = sep ? sep + 1 : NULL) { - if (!(sep = strchr(cur, '|'))) - pix_fmt_name_len = strlen(cur); - else - pix_fmt_name_len = sep - cur; - if (pix_fmt_name_len >= AV_PIX_FMT_NAME_MAXSIZE) { - av_log(ctx, AV_LOG_ERROR, "Format name too long\n"); - return -1; - } + cur = s->pix_fmts; + for (i = 0; i < nb_formats; i++) { + sep = strchr(cur, '|'); + if (sep) + *sep++ = 0; - memcpy(pix_fmt_name, cur, pix_fmt_name_len); - pix_fmt_name[pix_fmt_name_len] = 0; - - if ((ret = ff_parse_pixel_format(&pix_fmt, pix_fmt_name, ctx)) < 0) + if ((ret = ff_parse_pixel_format(&s->formats[i], cur, ctx)) < 0) return ret; - s->listed_pix_fmt_flags[pix_fmt] = 1; + cur = sep; + } + s->formats[nb_formats] = AV_PIX_FMT_NONE; + + if (!strcmp(ctx->filter->name, "noformat")) { + const AVPixFmtDescriptor *desc = NULL; + enum AVPixelFormat *formats_allowed; + int nb_formats_lavu = 0, nb_formats_allowed = 0; + + /* count the formats known to lavu */ + while ((desc = av_pix_fmt_desc_next(desc))) + nb_formats_lavu++; + + formats_allowed = av_malloc_array(nb_formats_lavu + 1, sizeof(*formats_allowed)); + if (!formats_allowed) + return AVERROR(ENOMEM); + + /* for each format known to lavu, check if it's in the list of + * forbidden formats */ + while ((desc = av_pix_fmt_desc_next(desc))) { + enum AVPixelFormat pix_fmt = av_pix_fmt_desc_get_id(desc); + + for (i = 0; i < nb_formats; i++) { + if (s->formats[i] == pix_fmt) + break; + } + if (i < nb_formats) + continue; + + formats_allowed[nb_formats_allowed++] = pix_fmt; + } + formats_allowed[nb_formats_allowed] = AV_PIX_FMT_NONE; + av_freep(&s->formats); + s->formats = formats_allowed; } return 0; } -static AVFilterFormats *make_format_list(FormatContext *s, int flag) +static int query_formats(AVFilterContext *ctx) { - AVFilterFormats *formats = NULL; - enum AVPixelFormat pix_fmt; + FormatContext *s = ctx->priv; + AVFilterFormats *formats = ff_make_format_list(s->formats); - for (pix_fmt = 0; pix_fmt < AV_PIX_FMT_NB; pix_fmt++) - if (s->listed_pix_fmt_flags[pix_fmt] == flag) { - int ret = ff_add_format(&formats, pix_fmt); - if (ret < 0) { - ff_formats_unref(&formats); - return NULL; - } - } + if (!formats) + return AVERROR(ENOMEM); - return formats; + ff_set_common_formats(ctx, formats); + return 0; } + #define OFFSET(x) offsetof(FormatContext, x) static const AVOption options[] = { { "pix_fmts", "A '|'-separated list of pixel formats", OFFSET(pix_fmts), AV_OPT_TYPE_STRING, .flags = AV_OPT_FLAG_VIDEO_PARAM }, @@ -105,11 +144,6 @@ static const AVOption options[] = { }; #if CONFIG_FORMAT_FILTER -static int query_formats_format(AVFilterContext *ctx) -{ - ff_set_common_formats(ctx, make_format_list(ctx->priv, 1)); - return 0; -} #define format_options options AVFILTER_DEFINE_CLASS(format); @@ -134,21 +168,21 @@ static const AVFilterPad avfilter_vf_format_outputs[] = { AVFilter ff_vf_format = { .name = "format", .description = NULL_IF_CONFIG_SMALL("Convert the input video to one of the specified pixel formats."), + .init = init, - .query_formats = query_formats_format, + .uninit = uninit, + + .query_formats = query_formats, + .priv_size = sizeof(FormatContext), .priv_class = &format_class, + .inputs = avfilter_vf_format_inputs, .outputs = avfilter_vf_format_outputs, }; #endif /* CONFIG_FORMAT_FILTER */ #if CONFIG_NOFORMAT_FILTER -static int query_formats_noformat(AVFilterContext *ctx) -{ - ff_set_common_formats(ctx, make_format_list(ctx->priv, 0)); - return 0; -} #define noformat_options options AVFILTER_DEFINE_CLASS(noformat); @@ -173,10 +207,15 @@ static const AVFilterPad avfilter_vf_noformat_outputs[] = { AVFilter ff_vf_noformat = { .name = "noformat", .description = NULL_IF_CONFIG_SMALL("Force libavfilter not to use any of the specified pixel formats for the input to the next filter."), + .init = init, - .query_formats = query_formats_noformat, + .uninit = uninit, + + .query_formats = query_formats, + .priv_size = sizeof(FormatContext), .priv_class = &noformat_class, + .inputs = avfilter_vf_noformat_inputs, .outputs = avfilter_vf_noformat_outputs, }; diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c index af3d410b8..a38633d50 100644 --- a/libavfilter/vf_fps.c +++ b/libavfilter/vf_fps.c @@ -79,7 +79,7 @@ static av_cold int init(AVFilterContext *ctx) { FPSContext *s = ctx->priv; - if (!(s->fifo = av_fifo_alloc(2*sizeof(AVFrame*)))) + if (!(s->fifo = av_fifo_alloc_array(2, sizeof(AVFrame*)))) return AVERROR(ENOMEM); s->first_pts = AV_NOPTS_VALUE; @@ -103,7 +103,7 @@ static av_cold void uninit(AVFilterContext *ctx) if (s->fifo) { s->drop += av_fifo_size(s->fifo) / sizeof(AVFrame*); flush_fifo(s->fifo); - av_fifo_free(s->fifo); + av_fifo_freep(&s->fifo); } av_log(ctx, AV_LOG_VERBOSE, "%d frames in, %d frames out; %d frames dropped, " diff --git a/libavfilter/vf_framestep.c b/libavfilter/vf_framestep.c index 9087f4620..09945e17a 100644 --- a/libavfilter/vf_framestep.c +++ b/libavfilter/vf_framestep.c @@ -28,7 +28,7 @@ #include "internal.h" #include "video.h" -typedef struct { +typedef struct NullContext { const AVClass *class; int frame_step; } FrameStepContext; diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c index 19b66062d..519a609fd 100644 --- a/libavfilter/vf_hflip.c +++ b/libavfilter/vf_hflip.c @@ -35,7 +35,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" -typedef struct { +typedef struct FlipContext { int max_step[4]; ///< max pixel step for each plane, expressed as a number of bytes int planewidth[4]; ///< width of each plane int planeheight[4]; ///< height of each plane @@ -46,7 +46,7 @@ static int query_formats(AVFilterContext *ctx) AVFilterFormats *pix_fmts = NULL; int fmt; - for (fmt = 0; fmt < AV_PIX_FMT_NB; fmt++) { + for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL || desc->flags & AV_PIX_FMT_FLAG_BITSTREAM || diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c index f96f2384c..0448c0d1e 100644 --- a/libavfilter/vf_hqdn3d.c +++ b/libavfilter/vf_hqdn3d.c @@ -133,7 +133,7 @@ static void denoise_depth(HQDN3DContext *s, 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)); + *frame_ant_ptr = frame_ant = av_malloc_array(w, h*sizeof(uint16_t)); for (y = 0; y < h; y++, src += sstride, frame_ant += w) for (x = 0; x < w; x++) frame_ant[x] = LOAD(x); @@ -259,7 +259,7 @@ static int config_input(AVFilterLink *inlink) s->vsub = desc->log2_chroma_h; s->depth = desc->comp[0].depth_minus1+1; - s->line = av_malloc(inlink->w * sizeof(*s->line)); + s->line = av_malloc_array(inlink->w, sizeof(*s->line)); if (!s->line) return AVERROR(ENOMEM); diff --git a/libavfilter/vf_hqdn3d.h b/libavfilter/vf_hqdn3d.h index 268ac9a25..be55400f0 100644 --- a/libavfilter/vf_hqdn3d.h +++ b/libavfilter/vf_hqdn3d.h @@ -28,7 +28,7 @@ #include "libavutil/opt.h" -typedef struct { +typedef struct HQDN3DContext { const AVClass *class; int16_t *coefs[4]; uint16_t *line; diff --git a/libavfilter/vf_hqx.c b/libavfilter/vf_hqx.c new file mode 100644 index 000000000..478338156 --- /dev/null +++ b/libavfilter/vf_hqx.c @@ -0,0 +1,562 @@ +/* + * Copyright (c) 2014 Clément Bœsch + * + * This file is part of FFmpeg. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * @file + * hqx magnification filters (hq2x, hq3x, hq4x) + * + * Originally designed by Maxim Stephin. + * + * @see http://en.wikipedia.org/wiki/Hqx + * @see http://web.archive.org/web/20131114143602/http://www.hiend3d.com/hq3x.html + * @see http://blog.pkh.me/p/19-butchering-hqx-scaling-filters.html + */ + +#include "libavutil/opt.h" +#include "libavutil/avassert.h" +#include "libavutil/pixdesc.h" +#include "internal.h" + +typedef int (*hqxfunc_t)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + +typedef struct { + const AVClass *class; + int n; + hqxfunc_t func; + uint32_t rgbtoyuv[1<<24]; +} HQXContext; + +typedef struct ThreadData { + AVFrame *in, *out; + const uint32_t *rgbtoyuv; +} ThreadData; + +#define OFFSET(x) offsetof(HQXContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +static const AVOption hqx_options[] = { + { "n", "set scale factor", OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 3}, 2, 4, .flags = FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(hqx); + +static av_always_inline uint32_t rgb2yuv(const uint32_t *r2y, uint32_t c) +{ + return r2y[c & 0xffffff]; +} + +static av_always_inline int yuv_diff(uint32_t yuv1, uint32_t yuv2) +{ +#define YMASK 0xff0000 +#define UMASK 0x00ff00 +#define VMASK 0x0000ff + return abs((yuv1 & YMASK) - (yuv2 & YMASK)) > (48 << 16) || + abs((yuv1 & UMASK) - (yuv2 & UMASK)) > ( 7 << 8) || + abs((yuv1 & VMASK) - (yuv2 & VMASK)) > ( 6 << 0); +} + +/* (c1*w1 + c2*w2) >> s */ +static av_always_inline uint32_t interp_2px(uint32_t c1, int w1, uint32_t c2, int w2, int s) +{ + return (((((c1 & 0xff00ff00) >> 8) * w1 + ((c2 & 0xff00ff00) >> 8) * w2) << (8 - s)) & 0xff00ff00) | + (((((c1 & 0x00ff00ff) ) * w1 + ((c2 & 0x00ff00ff) ) * w2) >> s ) & 0x00ff00ff); +} + +/* (c1*w1 + c2*w2 + c3*w3) >> s */ +static av_always_inline uint32_t interp_3px(uint32_t c1, int w1, uint32_t c2, int w2, uint32_t c3, int w3, int s) +{ + return (((((c1 & 0xff00ff00) >> 8) * w1 + ((c2 & 0xff00ff00) >> 8) * w2 + ((c3 & 0xff00ff00) >> 8) * w3) << (8 - s)) & 0xff00ff00) | + (((((c1 & 0x00ff00ff) ) * w1 + ((c2 & 0x00ff00ff) ) * w2 + ((c3 & 0x00ff00ff) ) * w3) >> s ) & 0x00ff00ff); +} + +/* m is the mask of diff with the center pixel that matters in the pattern, and + * r is the expected result (bit set to 1 if there is difference with the + * center, 0 otherwise) */ +#define P(m, r) ((k_shuffled & (m)) == (r)) + +/* adjust 012345678 to 01235678: the mask doesn't contain the (null) diff + * between the center/current pixel and itself */ +#define DROP4(z) ((z) > 4 ? (z)-1 : (z)) + +/* shuffle the input mask: move bit n (4-adjusted) to position stored in p */ +#define SHF(x, rot, n) (((x) >> ((rot) ? 7-DROP4(n) : DROP4(n)) & 1) << DROP4(p##n)) + +/* used to check if there is YUV difference between 2 pixels */ +#define WDIFF(c1, c2) yuv_diff(rgb2yuv(r2y, c1), rgb2yuv(r2y, c2)) + +/* bootstrap template for every interpolation code. It defines the shuffled + * masks and surrounding pixels. The rot flag is used to indicate if it's a + * rotation; its basic effect is to shuffle k using p8..p0 instead of p0..p8 */ +#define INTERP_BOOTSTRAP(rot) \ + const int k_shuffled = SHF(k,rot,0) | SHF(k,rot,1) | SHF(k,rot,2) \ + | SHF(k,rot,3) | 0 | SHF(k,rot,5) \ + | SHF(k,rot,6) | SHF(k,rot,7) | SHF(k,rot,8); \ + \ + const uint32_t w0 = w[p0], w1 = w[p1], \ + w3 = w[p3], w4 = w[p4], w5 = w[p5], \ + w7 = w[p7] + +/* Assuming p0..p8 is mapped to pixels 0..8, this function interpolates the + * top-left pixel in the total of the 2x2 pixels to interpolates. The function + * is also used for the 3 other pixels */ +static av_always_inline uint32_t hq2x_interp_1x1(const uint32_t *r2y, int k, + const uint32_t *w, + int p0, int p1, int p2, + int p3, int p4, int p5, + int p6, int p7, int p8) +{ + INTERP_BOOTSTRAP(0); + + if ((P(0xbf,0x37) || P(0xdb,0x13)) && WDIFF(w1, w5)) + return interp_2px(w4, 3, w3, 1, 2); + if ((P(0xdb,0x49) || P(0xef,0x6d)) && WDIFF(w7, w3)) + return interp_2px(w4, 3, w1, 1, 2); + if ((P(0x0b,0x0b) || P(0xfe,0x4a) || P(0xfe,0x1a)) && WDIFF(w3, w1)) + return w4; + if ((P(0x6f,0x2a) || P(0x5b,0x0a) || P(0xbf,0x3a) || P(0xdf,0x5a) || + P(0x9f,0x8a) || P(0xcf,0x8a) || P(0xef,0x4e) || P(0x3f,0x0e) || + P(0xfb,0x5a) || P(0xbb,0x8a) || P(0x7f,0x5a) || P(0xaf,0x8a) || + P(0xeb,0x8a)) && WDIFF(w3, w1)) + return interp_2px(w4, 3, w0, 1, 2); + if (P(0x0b,0x08)) + return interp_3px(w4, 2, w0, 1, w1, 1, 2); + if (P(0x0b,0x02)) + return interp_3px(w4, 2, w0, 1, w3, 1, 2); + if (P(0x2f,0x2f)) + return interp_3px(w4, 14, w3, 1, w1, 1, 4); + if (P(0xbf,0x37) || P(0xdb,0x13)) + return interp_3px(w4, 5, w1, 2, w3, 1, 3); + if (P(0xdb,0x49) || P(0xef,0x6d)) + return interp_3px(w4, 5, w3, 2, w1, 1, 3); + if (P(0x1b,0x03) || P(0x4f,0x43) || P(0x8b,0x83) || P(0x6b,0x43)) + return interp_2px(w4, 3, w3, 1, 2); + if (P(0x4b,0x09) || P(0x8b,0x89) || P(0x1f,0x19) || P(0x3b,0x19)) + return interp_2px(w4, 3, w1, 1, 2); + if (P(0x7e,0x2a) || P(0xef,0xab) || P(0xbf,0x8f) || P(0x7e,0x0e)) + return interp_3px(w4, 2, w3, 3, w1, 3, 3); + if (P(0xfb,0x6a) || P(0x6f,0x6e) || P(0x3f,0x3e) || P(0xfb,0xfa) || + P(0xdf,0xde) || P(0xdf,0x1e)) + return interp_2px(w4, 3, w0, 1, 2); + if (P(0x0a,0x00) || P(0x4f,0x4b) || P(0x9f,0x1b) || P(0x2f,0x0b) || + P(0xbe,0x0a) || P(0xee,0x0a) || P(0x7e,0x0a) || P(0xeb,0x4b) || + P(0x3b,0x1b)) + return interp_3px(w4, 2, w3, 1, w1, 1, 2); + return interp_3px(w4, 6, w3, 1, w1, 1, 3); +} + +/* Assuming p0..p8 is mapped to pixels 0..8, this function interpolates the + * top-left and top-center pixel in the total of the 3x3 pixels to + * interpolates. The function is also used for the 3 other couples of pixels + * defining the outline. The center pixel is not defined through this function, + * since it's just the same as the original value. */ +static av_always_inline void hq3x_interp_2x1(uint32_t *dst, int dst_linesize, + const uint32_t *r2y, int k, + const uint32_t *w, + int pos00, int pos01, + int p0, int p1, int p2, + int p3, int p4, int p5, + int p6, int p7, int p8, + int rotate) +{ + INTERP_BOOTSTRAP(rotate); + + uint32_t *dst00 = &dst[dst_linesize*(pos00>>1) + (pos00&1)]; + uint32_t *dst01 = &dst[dst_linesize*(pos01>>1) + (pos01&1)]; + + if ((P(0xdb,0x49) || P(0xef,0x6d)) && WDIFF(w7, w3)) + *dst00 = interp_2px(w4, 3, w1, 1, 2); + else if ((P(0xbf,0x37) || P(0xdb,0x13)) && WDIFF(w1, w5)) + *dst00 = interp_2px(w4, 3, w3, 1, 2); + else if ((P(0x0b,0x0b) || P(0xfe,0x4a) || P(0xfe,0x1a)) && WDIFF(w3, w1)) + *dst00 = w4; + else if ((P(0x6f,0x2a) || P(0x5b,0x0a) || P(0xbf,0x3a) || P(0xdf,0x5a) || + P(0x9f,0x8a) || P(0xcf,0x8a) || P(0xef,0x4e) || P(0x3f,0x0e) || + P(0xfb,0x5a) || P(0xbb,0x8a) || P(0x7f,0x5a) || P(0xaf,0x8a) || + P(0xeb,0x8a)) && WDIFF(w3, w1)) + *dst00 = interp_2px(w4, 3, w0, 1, 2); + else if (P(0x4b,0x09) || P(0x8b,0x89) || P(0x1f,0x19) || P(0x3b,0x19)) + *dst00 = interp_2px(w4, 3, w1, 1, 2); + else if (P(0x1b,0x03) || P(0x4f,0x43) || P(0x8b,0x83) || P(0x6b,0x43)) + *dst00 = interp_2px(w4, 3, w3, 1, 2); + else if (P(0x7e,0x2a) || P(0xef,0xab) || P(0xbf,0x8f) || P(0x7e,0x0e)) + *dst00 = interp_2px(w3, 1, w1, 1, 1); + else if (P(0x4f,0x4b) || P(0x9f,0x1b) || P(0x2f,0x0b) || P(0xbe,0x0a) || + P(0xee,0x0a) || P(0x7e,0x0a) || P(0xeb,0x4b) || P(0x3b,0x1b)) + *dst00 = interp_3px(w4, 2, w3, 7, w1, 7, 4); + else if (P(0x0b,0x08) || P(0xf9,0x68) || P(0xf3,0x62) || P(0x6d,0x6c) || + P(0x67,0x66) || P(0x3d,0x3c) || P(0x37,0x36) || P(0xf9,0xf8) || + P(0xdd,0xdc) || P(0xf3,0xf2) || P(0xd7,0xd6) || P(0xdd,0x1c) || + P(0xd7,0x16) || P(0x0b,0x02)) + *dst00 = interp_2px(w4, 3, w0, 1, 2); + else + *dst00 = interp_3px(w4, 2, w3, 1, w1, 1, 2); + + if ((P(0xfe,0xde) || P(0x9e,0x16) || P(0xda,0x12) || P(0x17,0x16) || + P(0x5b,0x12) || P(0xbb,0x12)) && WDIFF(w1, w5)) + *dst01 = w4; + else if ((P(0x0f,0x0b) || P(0x5e,0x0a) || P(0xfb,0x7b) || P(0x3b,0x0b) || + P(0xbe,0x0a) || P(0x7a,0x0a)) && WDIFF(w3, w1)) + *dst01 = w4; + else if (P(0xbf,0x8f) || P(0x7e,0x0e) || P(0xbf,0x37) || P(0xdb,0x13)) + *dst01 = interp_2px(w1, 3, w4, 1, 2); + else if (P(0x02,0x00) || P(0x7c,0x28) || P(0xed,0xa9) || P(0xf5,0xb4) || + P(0xd9,0x90)) + *dst01 = interp_2px(w4, 3, w1, 1, 2); + else if (P(0x4f,0x4b) || P(0xfb,0x7b) || P(0xfe,0x7e) || P(0x9f,0x1b) || + P(0x2f,0x0b) || P(0xbe,0x0a) || P(0x7e,0x0a) || P(0xfb,0x4b) || + P(0xfb,0xdb) || P(0xfe,0xde) || P(0xfe,0x56) || P(0x57,0x56) || + P(0x97,0x16) || P(0x3f,0x1e) || P(0xdb,0x12) || P(0xbb,0x12)) + *dst01 = interp_2px(w4, 7, w1, 1, 3); + else + *dst01 = w4; +} + +/* Assuming p0..p8 is mapped to pixels 0..8, this function interpolates the + * top-left block of 2x2 pixels in the total of the 4x4 pixels (or 4 blocks) to + * interpolates. The function is also used for the 3 other blocks of 2x2 + * pixels. */ +static av_always_inline void hq4x_interp_2x2(uint32_t *dst, int dst_linesize, + const uint32_t *r2y, int k, + const uint32_t *w, + int pos00, int pos01, + int pos10, int pos11, + int p0, int p1, int p2, + int p3, int p4, int p5, + int p6, int p7, int p8) +{ + INTERP_BOOTSTRAP(0); + + uint32_t *dst00 = &dst[dst_linesize*(pos00>>1) + (pos00&1)]; + uint32_t *dst01 = &dst[dst_linesize*(pos01>>1) + (pos01&1)]; + uint32_t *dst10 = &dst[dst_linesize*(pos10>>1) + (pos10&1)]; + uint32_t *dst11 = &dst[dst_linesize*(pos11>>1) + (pos11&1)]; + + const int cond00 = (P(0xbf,0x37) || P(0xdb,0x13)) && WDIFF(w1, w5); + const int cond01 = (P(0xdb,0x49) || P(0xef,0x6d)) && WDIFF(w7, w3); + const int cond02 = (P(0x6f,0x2a) || P(0x5b,0x0a) || P(0xbf,0x3a) || + P(0xdf,0x5a) || P(0x9f,0x8a) || P(0xcf,0x8a) || + P(0xef,0x4e) || P(0x3f,0x0e) || P(0xfb,0x5a) || + P(0xbb,0x8a) || P(0x7f,0x5a) || P(0xaf,0x8a) || + P(0xeb,0x8a)) && WDIFF(w3, w1); + const int cond03 = P(0xdb,0x49) || P(0xef,0x6d); + const int cond04 = P(0xbf,0x37) || P(0xdb,0x13); + const int cond05 = P(0x1b,0x03) || P(0x4f,0x43) || P(0x8b,0x83) || + P(0x6b,0x43); + const int cond06 = P(0x4b,0x09) || P(0x8b,0x89) || P(0x1f,0x19) || + P(0x3b,0x19); + const int cond07 = P(0x0b,0x08) || P(0xf9,0x68) || P(0xf3,0x62) || + P(0x6d,0x6c) || P(0x67,0x66) || P(0x3d,0x3c) || + P(0x37,0x36) || P(0xf9,0xf8) || P(0xdd,0xdc) || + P(0xf3,0xf2) || P(0xd7,0xd6) || P(0xdd,0x1c) || + P(0xd7,0x16) || P(0x0b,0x02); + const int cond08 = (P(0x0f,0x0b) || P(0x2b,0x0b) || P(0xfe,0x4a) || + P(0xfe,0x1a)) && WDIFF(w3, w1); + const int cond09 = P(0x2f,0x2f); + const int cond10 = P(0x0a,0x00); + const int cond11 = P(0x0b,0x09); + const int cond12 = P(0x7e,0x2a) || P(0xef,0xab); + const int cond13 = P(0xbf,0x8f) || P(0x7e,0x0e); + const int cond14 = P(0x4f,0x4b) || P(0x9f,0x1b) || P(0x2f,0x0b) || + P(0xbe,0x0a) || P(0xee,0x0a) || P(0x7e,0x0a) || + P(0xeb,0x4b) || P(0x3b,0x1b); + const int cond15 = P(0x0b,0x03); + + if (cond00) + *dst00 = interp_2px(w4, 5, w3, 3, 3); + else if (cond01) + *dst00 = interp_2px(w4, 5, w1, 3, 3); + else if ((P(0x0b,0x0b) || P(0xfe,0x4a) || P(0xfe,0x1a)) && WDIFF(w3, w1)) + *dst00 = w4; + else if (cond02) + *dst00 = interp_2px(w4, 5, w0, 3, 3); + else if (cond03) + *dst00 = interp_2px(w4, 3, w3, 1, 2); + else if (cond04) + *dst00 = interp_2px(w4, 3, w1, 1, 2); + else if (cond05) + *dst00 = interp_2px(w4, 5, w3, 3, 3); + else if (cond06) + *dst00 = interp_2px(w4, 5, w1, 3, 3); + else if (P(0x0f,0x0b) || P(0x5e,0x0a) || P(0x2b,0x0b) || P(0xbe,0x0a) || + P(0x7a,0x0a) || P(0xee,0x0a)) + *dst00 = interp_2px(w1, 1, w3, 1, 1); + else if (cond07) + *dst00 = interp_2px(w4, 5, w0, 3, 3); + else + *dst00 = interp_3px(w4, 2, w1, 1, w3, 1, 2); + + if (cond00) + *dst01 = interp_2px(w4, 7, w3, 1, 3); + else if (cond08) + *dst01 = w4; + else if (cond02) + *dst01 = interp_2px(w4, 3, w0, 1, 2); + else if (cond09) + *dst01 = w4; + else if (cond10) + *dst01 = interp_3px(w4, 5, w1, 2, w3, 1, 3); + else if (P(0x0b,0x08)) + *dst01 = interp_3px(w4, 5, w1, 2, w0, 1, 3); + else if (cond11) + *dst01 = interp_2px(w4, 5, w1, 3, 3); + else if (cond04) + *dst01 = interp_2px(w1, 3, w4, 1, 2); + else if (cond12) + *dst01 = interp_3px(w1, 2, w4, 1, w3, 1, 2); + else if (cond13) + *dst01 = interp_2px(w1, 5, w3, 3, 3); + else if (cond05) + *dst01 = interp_2px(w4, 7, w3, 1, 3); + else if (P(0xf3,0x62) || P(0x67,0x66) || P(0x37,0x36) || P(0xf3,0xf2) || + P(0xd7,0xd6) || P(0xd7,0x16) || P(0x0b,0x02)) + *dst01 = interp_2px(w4, 3, w0, 1, 2); + else if (cond14) + *dst01 = interp_2px(w1, 1, w4, 1, 1); + else + *dst01 = interp_2px(w4, 3, w1, 1, 2); + + if (cond01) + *dst10 = interp_2px(w4, 7, w1, 1, 3); + else if (cond08) + *dst10 = w4; + else if (cond02) + *dst10 = interp_2px(w4, 3, w0, 1, 2); + else if (cond09) + *dst10 = w4; + else if (cond10) + *dst10 = interp_3px(w4, 5, w3, 2, w1, 1, 3); + else if (P(0x0b,0x02)) + *dst10 = interp_3px(w4, 5, w3, 2, w0, 1, 3); + else if (cond15) + *dst10 = interp_2px(w4, 5, w3, 3, 3); + else if (cond03) + *dst10 = interp_2px(w3, 3, w4, 1, 2); + else if (cond13) + *dst10 = interp_3px(w3, 2, w4, 1, w1, 1, 2); + else if (cond12) + *dst10 = interp_2px(w3, 5, w1, 3, 3); + else if (cond06) + *dst10 = interp_2px(w4, 7, w1, 1, 3); + else if (P(0x0b,0x08) || P(0xf9,0x68) || P(0x6d,0x6c) || P(0x3d,0x3c) || + P(0xf9,0xf8) || P(0xdd,0xdc) || P(0xdd,0x1c)) + *dst10 = interp_2px(w4, 3, w0, 1, 2); + else if (cond14) + *dst10 = interp_2px(w3, 1, w4, 1, 1); + else + *dst10 = interp_2px(w4, 3, w3, 1, 2); + + if ((P(0x7f,0x2b) || P(0xef,0xab) || P(0xbf,0x8f) || P(0x7f,0x0f)) && + WDIFF(w3, w1)) + *dst11 = w4; + else if (cond02) + *dst11 = interp_2px(w4, 7, w0, 1, 3); + else if (cond15) + *dst11 = interp_2px(w4, 7, w3, 1, 3); + else if (cond11) + *dst11 = interp_2px(w4, 7, w1, 1, 3); + else if (P(0x0a,0x00) || P(0x7e,0x2a) || P(0xef,0xab) || P(0xbf,0x8f) || + P(0x7e,0x0e)) + *dst11 = interp_3px(w4, 6, w3, 1, w1, 1, 3); + else if (cond07) + *dst11 = interp_2px(w4, 7, w0, 1, 3); + else + *dst11 = w4; +} + +static av_always_inline void hqx_filter(const ThreadData *td, int jobnr, int nb_jobs, int n) +{ + int x, y; + AVFrame *in = td->in, *out = td->out; + const uint32_t *r2y = td->rgbtoyuv; + const int height = in->height; + const int width = in->width; + const int slice_start = (height * jobnr ) / nb_jobs; + const int slice_end = (height * (jobnr+1)) / nb_jobs; + const int dst_linesize = out->linesize[0]; + const int src_linesize = in->linesize[0]; + uint8_t *dst = out->data[0] + slice_start * dst_linesize * n; + const uint8_t *src = in->data[0] + slice_start * src_linesize; + + const int dst32_linesize = dst_linesize >> 2; + const int src32_linesize = src_linesize >> 2; + + for (y = slice_start; y < slice_end; y++) { + const uint32_t *src32 = (const uint32_t *)src; + uint32_t *dst32 = (uint32_t *)dst; + const int prevline = y > 0 ? -src32_linesize : 0; + const int nextline = y < height - 1 ? src32_linesize : 0; + + for (x = 0; x < width; x++) { + const int prevcol = x > 0 ? -1 : 0; + const int nextcol = x < width -1 ? 1 : 0; + const uint32_t w[3*3] = { + src32[prevcol + prevline], src32[prevline], src32[prevline + nextcol], + src32[prevcol ], src32[ 0], src32[ nextcol], + src32[prevcol + nextline], src32[nextline], src32[nextline + nextcol] + }; + const uint32_t yuv1 = rgb2yuv(r2y, w[4]); + const int pattern = (w[4] != w[0] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[0]))) : 0) + | (w[4] != w[1] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[1]))) : 0) << 1 + | (w[4] != w[2] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[2]))) : 0) << 2 + | (w[4] != w[3] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[3]))) : 0) << 3 + | (w[4] != w[5] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[5]))) : 0) << 4 + | (w[4] != w[6] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[6]))) : 0) << 5 + | (w[4] != w[7] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[7]))) : 0) << 6 + | (w[4] != w[8] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[8]))) : 0) << 7; + + if (n == 2) { + dst32[dst32_linesize*0 + 0] = hq2x_interp_1x1(r2y, pattern, w, 0,1,2,3,4,5,6,7,8); // 00 + dst32[dst32_linesize*0 + 1] = hq2x_interp_1x1(r2y, pattern, w, 2,1,0,5,4,3,8,7,6); // 01 (vert mirrored) + dst32[dst32_linesize*1 + 0] = hq2x_interp_1x1(r2y, pattern, w, 6,7,8,3,4,5,0,1,2); // 10 (horiz mirrored) + dst32[dst32_linesize*1 + 1] = hq2x_interp_1x1(r2y, pattern, w, 8,7,6,5,4,3,2,1,0); // 11 (center mirrored) + } else if (n == 3) { + hq3x_interp_2x1(dst32, dst32_linesize, r2y, pattern, w, 0,1, 0,1,2,3,4,5,6,7,8, 0); // 00 01 + hq3x_interp_2x1(dst32 + 1, dst32_linesize, r2y, pattern, w, 1,3, 2,5,8,1,4,7,0,3,6, 1); // 02 12 (rotated to the right) + hq3x_interp_2x1(dst32 + 1*dst32_linesize, dst32_linesize, r2y, pattern, w, 2,0, 6,3,0,7,4,1,8,5,2, 1); // 20 10 (rotated to the left) + hq3x_interp_2x1(dst32 + 1*dst32_linesize + 1, dst32_linesize, r2y, pattern, w, 3,2, 8,7,6,5,4,3,2,1,0, 0); // 22 21 (center mirrored) + dst32[dst32_linesize + 1] = w[4]; // 11 + } else if (n == 4) { + hq4x_interp_2x2(dst32, dst32_linesize, r2y, pattern, w, 0,1,2,3, 0,1,2,3,4,5,6,7,8); // 00 01 10 11 + hq4x_interp_2x2(dst32 + 2, dst32_linesize, r2y, pattern, w, 1,0,3,2, 2,1,0,5,4,3,8,7,6); // 02 03 12 13 (vert mirrored) + hq4x_interp_2x2(dst32 + 2*dst32_linesize, dst32_linesize, r2y, pattern, w, 2,3,0,1, 6,7,8,3,4,5,0,1,2); // 20 21 30 31 (horiz mirrored) + hq4x_interp_2x2(dst32 + 2*dst32_linesize + 2, dst32_linesize, r2y, pattern, w, 3,2,1,0, 8,7,6,5,4,3,2,1,0); // 22 23 32 33 (center mirrored) + } else { + av_assert0(0); + } + + src32 += 1; + dst32 += n; + } + + src += src_linesize; + dst += dst_linesize * n; + } +} + +#define HQX_FUNC(size) \ +static int hq##size##x(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ +{ \ + hqx_filter(arg, jobnr, nb_jobs, size); \ + return 0; \ +} + +HQX_FUNC(2) +HQX_FUNC(3) +HQX_FUNC(4) + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = {AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE}; + ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + HQXContext *hqx = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + + outlink->w = inlink->w * hqx->n; + outlink->h = inlink->h * hqx->n; + av_log(inlink->dst, AV_LOG_VERBOSE, "fmt:%s size:%dx%d -> size:%dx%d\n", + av_get_pix_fmt_name(inlink->format), + inlink->w, inlink->h, outlink->w, outlink->h); + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + HQXContext *hqx = ctx->priv; + ThreadData td; + AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + out->width = outlink->w; + out->height = outlink->h; + + td.in = in; + td.out = out; + td.rgbtoyuv = hqx->rgbtoyuv; + ctx->internal->execute(ctx, hqx->func, &td, NULL, FFMIN(inlink->h, ctx->graph->nb_threads)); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static av_cold int init(AVFilterContext *ctx) +{ + HQXContext *hqx = ctx->priv; + static const hqxfunc_t hqxfuncs[] = {hq2x, hq3x, hq4x}; + + uint32_t c; + int bg, rg, g; + + for (bg=-255; bg<256; bg++) { + for (rg=-255; rg<256; rg++) { + const uint32_t u = (uint32_t)((-169*rg + 500*bg)/1000) + 128; + const uint32_t v = (uint32_t)(( 500*rg - 81*bg)/1000) + 128; + int startg = FFMAX3(-bg, -rg, 0); + int endg = FFMIN3(255-bg, 255-rg, 255); + uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000); + c = bg + (rg<<16) + 0x010101 * startg; + for (g = startg; g <= endg; g++) { + hqx->rgbtoyuv[c] = ((y++) << 16) + (u << 8) + v; + c+= 0x010101; + } + } + } + + hqx->func = hqxfuncs[hqx->n - 2]; + return 0; +} + +static const AVFilterPad hqx_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad hqx_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vf_hqx = { + .name = "hqx", + .description = NULL_IF_CONFIG_SMALL("Scale the input by 2, 3 or 4 using the hq*x magnification algorithm."), + .priv_size = sizeof(HQXContext), + .init = init, + .query_formats = query_formats, + .inputs = hqx_inputs, + .outputs = hqx_outputs, + .priv_class = &hqx_class, + .flags = AVFILTER_FLAG_SLICE_THREADS, +}; diff --git a/libavfilter/vf_il.c b/libavfilter/vf_il.c index e755caa6e..b19fea1b6 100644 --- a/libavfilter/vf_il.c +++ b/libavfilter/vf_il.c @@ -86,7 +86,7 @@ static int query_formats(AVFilterContext *ctx) AVFilterFormats *formats = NULL; int fmt; - for (fmt = 0; fmt < AV_PIX_FMT_NB; fmt++) { + for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); if (!(desc->flags & AV_PIX_FMT_FLAG_PAL) && !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) ff_add_format(&formats, fmt); diff --git a/libavfilter/vf_interlace.c b/libavfilter/vf_interlace.c index aff979bb0..0929a7107 100644 --- a/libavfilter/vf_interlace.c +++ b/libavfilter/vf_interlace.c @@ -47,7 +47,7 @@ enum FieldType { FIELD_LOWER = 1, }; -typedef struct { +typedef struct InterlaceContext { const AVClass *class; enum ScanMode scan; // top or bottom field first scanning #if FF_API_INTERLACE_LOWPASS_SET diff --git a/libavfilter/vf_libopencv.c b/libavfilter/vf_libopencv.c index 2306b09bd..f55f552ec 100644 --- a/libavfilter/vf_libopencv.c +++ b/libavfilter/vf_libopencv.c @@ -68,7 +68,7 @@ static int query_formats(AVFilterContext *ctx) return 0; } -typedef struct { +typedef struct OCVContext { const AVClass *class; char *name; char *params; @@ -78,7 +78,7 @@ typedef struct { void *priv; } OCVContext; -typedef struct { +typedef struct SmoothContext { int type; int param1, param2; double param3, param4; @@ -166,7 +166,7 @@ static int read_shape_from_file(int *cols, int *rows, int **values, const char * *rows, *cols); return AVERROR_INVALIDDATA; } - if (!(*values = av_mallocz(sizeof(int) * *rows * *cols))) + if (!(*values = av_mallocz_array(sizeof(int) * *rows, *cols))) return AVERROR(ENOMEM); /* fill *values */ @@ -245,7 +245,7 @@ static int parse_iplconvkernel(IplConvKernel **kernel, char *buf, void *log_ctx) return 0; } -typedef struct { +typedef struct DilateContext { int nb_iterations; IplConvKernel *kernel; } DilateContext; @@ -302,7 +302,7 @@ static void erode_end_frame_filter(AVFilterContext *ctx, IplImage *inimg, IplIma cvErode(inimg, outimg, dilate->kernel, dilate->nb_iterations); } -typedef struct { +typedef struct OCVFilterEntry { const char *name; size_t priv_size; int (*init)(AVFilterContext *ctx, const char *args); diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c index 9f30ae0cd..fff5a2ba3 100644 --- a/libavfilter/vf_lut.c +++ b/libavfilter/vf_lut.c @@ -57,7 +57,7 @@ enum var_name { VAR_VARS_NB }; -typedef struct { +typedef struct LutContext { const AVClass *class; uint8_t lut[4][256]; ///< lookup table for each component char *comp_expr_str[4]; diff --git a/libavfilter/vf_lut3d.c b/libavfilter/vf_lut3d.c index 67cdb17ee..862dddeac 100644 --- a/libavfilter/vf_lut3d.c +++ b/libavfilter/vf_lut3d.c @@ -216,12 +216,12 @@ static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, i const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \ uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \ const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \ + const float scale = (1. / ((1<lutsize - 1); \ \ for (y = slice_start; y < slice_end; y++) { \ uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \ const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \ for (x = 0; x < in->width * step; x += step) { \ - const float scale = (1. / ((1<lutsize - 1); \ const struct rgbvec scaled_rgb = {src[x + r] * scale, \ src[x + g] * scale, \ src[x + b] * scale}; \ @@ -262,21 +262,34 @@ static int skip_line(const char *p) } \ } while (loop_cond) -/* Basically r g and b float values on each line; seems to be generated by - * Davinci */ +/* Basically r g and b float values on each line, with a facultative 3DLUTSIZE + * directive; seems to be generated by Davinci */ static int parse_dat(AVFilterContext *ctx, FILE *f) { LUT3DContext *lut3d = ctx->priv; - const int size = lut3d->lutsize; - int i, j, k; + char line[MAX_LINE_SIZE]; + int i, j, k, size; + lut3d->lutsize = size = 33; + + NEXT_LINE(skip_line(line)); + if (!strncmp(line, "3DLUTSIZE ", 10)) { + size = strtol(line + 10, NULL, 0); + if (size < 2 || size > MAX_LEVEL) { + av_log(ctx, AV_LOG_ERROR, "Too large or invalid 3D LUT size\n"); + return AVERROR(EINVAL); + } + lut3d->lutsize = size; + NEXT_LINE(skip_line(line)); + } for (k = 0; k < size; k++) { for (j = 0; j < size; j++) { for (i = 0; i < size; i++) { - char line[MAX_LINE_SIZE]; struct rgbvec *vec = &lut3d->lut[k][j][i]; - NEXT_LINE(skip_line(line)); - sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b); + if (k != 0 || j != 0 || i != 0) + NEXT_LINE(skip_line(line)); + if (sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3) + return AVERROR_INVALIDDATA; } } } @@ -569,7 +582,6 @@ static av_cold int lut3d_init(AVFilterContext *ctx) ext++; if (!av_strcasecmp(ext, "dat")) { - lut3d->lutsize = 33; ret = parse_dat(ctx, f); } else if (!av_strcasecmp(ext, "3dl")) { ret = parse_3dl(ctx, f); @@ -642,7 +654,7 @@ static void update_clut(LUT3DContext *lut3d, const AVFrame *frame) for (i = 0; i < level; i++) { \ const uint##nbits##_t *src = (const uint##nbits##_t *) \ (data + y*linesize + x*step); \ - struct rgbvec *vec = &lut3d->lut[k][j][i]; \ + struct rgbvec *vec = &lut3d->lut[i][j][k]; \ vec->r = src[rgba_map[0]] / (float)((1<<(nbits)) - 1); \ vec->g = src[rgba_map[1]] / (float)((1<<(nbits)) - 1); \ vec->b = src[rgba_map[2]] / (float)((1<<(nbits)) - 1); \ diff --git a/libavfilter/vf_mergeplanes.c b/libavfilter/vf_mergeplanes.c index 6fec816a4..c76e82a41 100644 --- a/libavfilter/vf_mergeplanes.c +++ b/libavfilter/vf_mergeplanes.c @@ -120,7 +120,7 @@ static int query_formats(AVFilterContext *ctx) int i; s->outdesc = av_pix_fmt_desc_get(s->out_fmt); - for (i = 0; i < AV_PIX_FMT_NB; i++) { + for (i = 0; av_pix_fmt_desc_get(i); i++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i); if (desc->comp[0].depth_minus1 == s->outdesc->comp[0].depth_minus1 && av_pix_fmt_count_planes(i) == desc->nb_components) diff --git a/libavfilter/vf_mp.c b/libavfilter/vf_mp.c index 2c145ab85..9f0fbf641 100644 --- a/libavfilter/vf_mp.c +++ b/libavfilter/vf_mp.c @@ -210,7 +210,7 @@ int ff_mp_msg_test(int mod, int lev){ void ff_init_avcodec(void) { - //we maybe should init but its kinda 1. unneeded 2. a bit inpolite from here + //we maybe should init but its kinda 1. unneeded 2. a bit impolite from here } //Exact copy of vf.c diff --git a/libavfilter/vf_mpdecimate.c b/libavfilter/vf_mpdecimate.c index 099622a02..c667a9f4c 100644 --- a/libavfilter/vf_mpdecimate.c +++ b/libavfilter/vf_mpdecimate.c @@ -28,6 +28,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/timestamp.h" #include "libavcodec/dsputil.h" +#include "libavcodec/pixblockdsp.h" #include "avfilter.h" #include "internal.h" #include "formats.h" @@ -49,6 +50,7 @@ typedef struct { int hsub, vsub; ///< chroma subsampling values AVFrame *ref; ///< reference picture DSPContext dspctx; ///< context providing optimized diff routines + PixblockDSPContext pdsp; AVCodecContext *avctx; ///< codec context required for the DSPContext } DecimateContext; @@ -75,6 +77,7 @@ static int diff_planes(AVFilterContext *ctx, { DecimateContext *decimate = ctx->priv; DSPContext *dspctx = &decimate->dspctx; + PixblockDSPContext *pdsp = &decimate->pdsp; int x, y; int d, c = 0; @@ -84,7 +87,7 @@ static int diff_planes(AVFilterContext *ctx, /* compute difference for blocks of 8x8 bytes */ for (y = 0; y < h-7; y += 4) { for (x = 8; x < w-7; x += 4) { - dspctx->diff_pixels(block, + pdsp->diff_pixels(block, cur+x+y*linesize, ref+x+y*linesize, linesize); d = dspctx->sum_abs_dctelem(block); @@ -141,6 +144,7 @@ static av_cold int init(AVFilterContext *ctx) if (!decimate->avctx) return AVERROR(ENOMEM); avpriv_dsputil_init(&decimate->dspctx, decimate->avctx); + ff_pixblockdsp_init(&decimate->pdsp, decimate->avctx); return 0; } diff --git a/libavfilter/vf_noise.c b/libavfilter/vf_noise.c index c29afa272..934cbcb30 100644 --- a/libavfilter/vf_noise.c +++ b/libavfilter/vf_noise.c @@ -172,7 +172,7 @@ static int query_formats(AVFilterContext *ctx) AVFilterFormats *formats = NULL; int fmt; - for (fmt = 0; fmt < AV_PIX_FMT_NB; fmt++) { + for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); if (desc->flags & AV_PIX_FMT_FLAG_PLANAR && !((desc->comp[0].depth_minus1 + 1) & 7)) ff_add_format(&formats, fmt); @@ -289,7 +289,7 @@ static inline void line_noise_avg_c(uint8_t *dst, const uint8_t *src, static inline void line_noise_avg_mmx(uint8_t *dst, const uint8_t *src, int len, int8_t **shift) { -#if HAVE_MMX_INLINE +#if HAVE_MMX_INLINE && HAVE_6REGS x86_reg mmx_len= len&(~7); __asm__ volatile( @@ -438,7 +438,9 @@ static av_cold int init(AVFilterContext *ctx) if (HAVE_MMX_INLINE && cpu_flags & AV_CPU_FLAG_MMX) { n->line_noise = line_noise_mmx; +#if HAVE_6REGS n->line_noise_avg = line_noise_avg_mmx; +#endif } if (HAVE_MMXEXT_INLINE && cpu_flags & AV_CPU_FLAG_MMXEXT) diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index 56b2484da..1d9240cc9 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -34,6 +34,7 @@ #include "libavutil/imgutils.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" +#include "libavutil/timestamp.h" #include "internal.h" #include "dualinput.h" #include "drawutils.h" @@ -91,7 +92,7 @@ static const char *eof_action_str[] = { #define U 1 #define V 2 -typedef struct { +typedef struct OverlayContext { const AVClass *class; int x, y; ///< position of overlayed picture @@ -554,21 +555,20 @@ static AVFrame *do_blend(AVFilterContext *ctx, AVFrame *mainpic, OverlayContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - /* TODO: reindent */ - if (s->eval_mode == EVAL_MODE_FRAME) { - int64_t pos = av_frame_get_pkt_pos(mainpic); + if (s->eval_mode == EVAL_MODE_FRAME) { + int64_t pos = av_frame_get_pkt_pos(mainpic); - s->var_values[VAR_N] = inlink->frame_count; - s->var_values[VAR_T] = mainpic->pts == AV_NOPTS_VALUE ? - NAN : mainpic->pts * av_q2d(inlink->time_base); - s->var_values[VAR_POS] = pos == -1 ? NAN : pos; + s->var_values[VAR_N] = inlink->frame_count; + s->var_values[VAR_T] = mainpic->pts == AV_NOPTS_VALUE ? + NAN : mainpic->pts * av_q2d(inlink->time_base); + s->var_values[VAR_POS] = pos == -1 ? NAN : pos; - eval_expr(ctx); - av_log(ctx, AV_LOG_DEBUG, "n:%f t:%f pos:%f x:%f xi:%d y:%f yi:%d\n", - s->var_values[VAR_N], s->var_values[VAR_T], s->var_values[VAR_POS], - s->var_values[VAR_X], s->x, - s->var_values[VAR_Y], s->y); - } + eval_expr(ctx); + av_log(ctx, AV_LOG_DEBUG, "n:%f t:%f pos:%f x:%f xi:%d y:%f yi:%d\n", + s->var_values[VAR_N], s->var_values[VAR_T], s->var_values[VAR_POS], + s->var_values[VAR_X], s->x, + s->var_values[VAR_Y], s->y); + } blend_image(ctx, mainpic, second, s->x, s->y); return mainpic; @@ -577,6 +577,7 @@ static AVFrame *do_blend(AVFilterContext *ctx, AVFrame *mainpic, static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) { OverlayContext *s = inlink->dst->priv; + av_log(inlink->dst, AV_LOG_DEBUG, "Incoming frame (time:%s) from link #%d\n", av_ts2timestr(inpicref->pts, &inlink->time_base), FF_INLINK_IDX(inlink)); return ff_dualinput_filter_frame(&s->dinput, inlink, inpicref); } diff --git a/libavfilter/vf_pad.c b/libavfilter/vf_pad.c index 2962e204f..2d9b9d036 100644 --- a/libavfilter/vf_pad.c +++ b/libavfilter/vf_pad.c @@ -77,7 +77,7 @@ static int query_formats(AVFilterContext *ctx) return 0; } -typedef struct { +typedef struct PadContext { const AVClass *class; int w, h; ///< output dimensions, a value of 0 will result in the input size int x, y; ///< offsets of the input area with respect to the padded area diff --git a/libavfilter/vf_phase.c b/libavfilter/vf_phase.c index 2dcc6faa4..82dc603ef 100644 --- a/libavfilter/vf_phase.c +++ b/libavfilter/vf_phase.c @@ -42,7 +42,7 @@ enum PhaseMode { typedef struct PhaseContext { const AVClass *class; enum PhaseMode mode; - AVFrame *frame; + AVFrame *frame; /* previous frame */ int nb_planes; int planeheight[4]; int linesize[4]; @@ -112,20 +112,16 @@ static int config_input(AVFilterLink *inlink) * Find which field combination has the smallest average squared difference * between the fields. */ -static enum PhaseMode analyze_plane(AVFilterContext *ctx, PhaseContext *s, - AVFrame *old, AVFrame *new) +static enum PhaseMode analyze_plane(void *ctx, enum PhaseMode mode, AVFrame *old, AVFrame *new) { double bdiff, tdiff, pdiff, scale; const int ns = new->linesize[0]; const int os = old->linesize[0]; - uint8_t *nptr = new->data[0]; - uint8_t *optr = old->data[0]; + const uint8_t *nptr = new->data[0]; + const uint8_t *optr = old->data[0]; const int h = new->height; const int w = new->width; int bdif, tdif, pdif; - enum PhaseMode mode = s->mode; - uint8_t *end, *rend; - int top, t; if (mode == AUTO) { mode = new->interlaced_frame ? new->top_field_first ? @@ -138,10 +134,14 @@ static enum PhaseMode analyze_plane(AVFilterContext *ctx, PhaseContext *s, if (mode <= BOTTOM_FIRST) { bdiff = pdiff = tdiff = 65536.0; } else { + int top = 0, t; + const uint8_t *rend, *end = nptr + (h - 2) * ns; + bdiff = pdiff = tdiff = 0.0; - for (end = nptr + (h - 2) * ns, nptr += ns, optr += os, top = 0; - nptr < end; nptr += ns - w, optr += os - w, top ^= 1) { + nptr += ns; + optr += os; + while (nptr < end) { pdif = tdif = bdif = 0; switch (mode) { @@ -206,6 +206,9 @@ static enum PhaseMode analyze_plane(AVFilterContext *ctx, PhaseContext *s, pdiff += (double)pdif; tdiff += (double)tdif; bdiff += (double)bdif; + nptr += ns - w; + optr += os - w; + top ^= 1; } scale = 1.0 / (w * (h - 3)) / 25.0; @@ -245,6 +248,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) int plane, top, y; AVFrame *out; + if (ctx->is_disabled) { + av_frame_free(&s->frame); + /* we keep a reference to the previous frame so the filter can start + * being useful as soon as it's not disabled, avoiding the 1-frame + * delay. */ + s->frame = av_frame_clone(in); + return ff_filter_frame(outlink, in); + } + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); @@ -253,25 +265,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); if (!s->frame) { + s->frame = in; mode = PROGRESSIVE; - s->frame = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!s->frame) { - av_frame_free(&in); - av_frame_free(&out); - return AVERROR(ENOMEM); - } } else { - mode = analyze_plane(ctx, s, s->frame, in); + mode = analyze_plane(ctx, s->mode, s->frame, in); } for (plane = 0; plane < s->nb_planes; plane++) { - uint8_t *buf = s->frame->data[plane]; - uint8_t *from = in->data[plane]; + const uint8_t *buf = s->frame->data[plane]; + const uint8_t *from = in->data[plane]; uint8_t *to = out->data[plane]; for (y = 0, top = 1; y < s->planeheight[plane]; y++, top ^= 1) { memcpy(to, mode == (top ? BOTTOM_FIRST : TOP_FIRST) ? buf : from, s->linesize[plane]); - memcpy(buf, from, s->linesize[plane]); buf += s->frame->linesize[plane]; from += in->linesize[plane]; @@ -279,7 +285,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } } - av_frame_free(&in); + if (in != s->frame) + av_frame_free(&s->frame); + s->frame = in; return ff_filter_frame(outlink, out); } @@ -317,4 +325,5 @@ AVFilter ff_vf_phase = { .query_formats = query_formats, .inputs = phase_inputs, .outputs = phase_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; diff --git a/libavfilter/vf_pixdesctest.c b/libavfilter/vf_pixdesctest.c index 54ddf8976..790dd0d9c 100644 --- a/libavfilter/vf_pixdesctest.c +++ b/libavfilter/vf_pixdesctest.c @@ -29,7 +29,7 @@ #include "internal.h" #include "video.h" -typedef struct { +typedef struct PixdescTestContext { const AVPixFmtDescriptor *pix_desc; uint16_t *line; } PixdescTestContext; @@ -47,7 +47,7 @@ static int config_props(AVFilterLink *inlink) priv->pix_desc = av_pix_fmt_desc_get(inlink->format); av_freep(&priv->line); - if (!(priv->line = av_malloc(sizeof(*priv->line) * inlink->w))) + if (!(priv->line = av_malloc_array(sizeof(*priv->line), inlink->w))) return AVERROR(ENOMEM); return 0; diff --git a/libavfilter/vf_pullup.c b/libavfilter/vf_pullup.c index c87b4b380..ac67de674 100644 --- a/libavfilter/vf_pullup.c +++ b/libavfilter/vf_pullup.c @@ -67,7 +67,7 @@ static int query_formats(AVFilterContext *ctx) return 0; } -#define ABS(a) (((a) ^ ((a) >> 31)) - ((a) >> 31)) +#define ABS(a) ((a) > 0 ? (a) : -(a)) static int diff_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s) { @@ -137,7 +137,7 @@ static void free_field_queue(PullupField *head) av_free(f->combs); av_free(f->vars); next = f->next; - memset(f, 0, sizeof(*f)); + memset(f, 0, sizeof(*f)); // clear all pointers to avoid stale ones av_free(f); f = next; } while (f != head); diff --git a/libavfilter/vf_removelogo.c b/libavfilter/vf_removelogo.c index 01a585c21..555517f83 100644 --- a/libavfilter/vf_removelogo.c +++ b/libavfilter/vf_removelogo.c @@ -312,18 +312,22 @@ static av_cold int init(AVFilterContext *ctx) the filter is applied, the mask size is determined on a pixel by pixel basis, with pixels nearer the edge of the logo getting smaller mask sizes. */ - mask = (int ***)av_malloc(sizeof(int **) * (s->max_mask_size + 1)); + mask = (int ***)av_malloc_array(s->max_mask_size + 1, sizeof(int **)); if (!mask) return AVERROR(ENOMEM); for (a = 0; a <= s->max_mask_size; a++) { - mask[a] = (int **)av_malloc(sizeof(int *) * ((a * 2) + 1)); - if (!mask[a]) + mask[a] = (int **)av_malloc_array((a * 2) + 1, sizeof(int *)); + if (!mask[a]) { + av_free(mask); return AVERROR(ENOMEM); + } for (b = -a; b <= a; b++) { - mask[a][b + a] = (int *)av_malloc(sizeof(int) * ((a * 2) + 1)); - if (!mask[a][b + a]) + mask[a][b + a] = (int *)av_malloc_array((a * 2) + 1, sizeof(int)); + if (!mask[a][b + a]) { + av_free(mask); return AVERROR(ENOMEM); + } for (c = -a; c <= a; c++) { if ((b * b) + (c * c) <= (a * a)) /* Circular 0/1 mask. */ mask[a][b + a][c + a] = 1; diff --git a/libavfilter/vf_rotate.c b/libavfilter/vf_rotate.c index e242ee2df..7e5b12b42 100644 --- a/libavfilter/vf_rotate.c +++ b/libavfilter/vf_rotate.c @@ -36,6 +36,8 @@ #include "internal.h" #include "video.h" +#include + static const char *var_names[] = { "in_w" , "iw", ///< width of the input video "in_h" , "ih", ///< height of the input video @@ -252,11 +254,12 @@ static int config_props(AVFilterLink *outlink) } #define FIXP (1<<16) -#define INT_PI 205887 //(M_PI * FIXP) +#define FIXP2 (1<<20) +#define INT_PI 3294199 //(M_PI * FIXP2) /** * Compute the sin of a using integer values. - * Input and output values are scaled by FIXP. + * Input is scaled by FIXP2 and output values are scaled by FIXP. */ static int64_t int_sin(int64_t a) { @@ -268,13 +271,13 @@ static int64_t int_sin(int64_t a) if (a >= INT_PI*3/2) a -= 2*INT_PI; // -PI/2 .. 3PI/2 if (a >= INT_PI/2 ) a = INT_PI - a; // -PI/2 .. PI/2 - /* compute sin using Taylor series approximated to the third term */ - a2 = (a*a)/FIXP; - for (i = 2; i < 7; i += 2) { + /* compute sin using Taylor series approximated to the fifth term */ + a2 = (a*a)/(FIXP2); + for (i = 2; i < 11; i += 2) { res += a; - a = -a*a2 / (FIXP*i*(i+1)); + a = -a*a2 / (FIXP2*i*(i+1)); } - return res; + return (res + 8)>>4; } /** @@ -307,6 +310,62 @@ static uint8_t *interpolate_bilinear(uint8_t *dst_color, return dst_color; } +static av_always_inline void copy_elem(uint8_t *pout, const uint8_t *pin, int elem_size) +{ + int v; + switch (elem_size) { + case 1: + *pout = *pin; + break; + case 2: + *((uint16_t *)pout) = *((uint16_t *)pin); + break; + case 3: + v = AV_RB24(pin); + AV_WB24(pout, v); + break; + case 4: + *((uint32_t *)pout) = *((uint32_t *)pin); + break; + default: + memcpy(pout, pin, elem_size); + break; + } +} + +static av_always_inline void simple_rotate_internal(uint8_t *dst, const uint8_t *src, int src_linesize, int angle, int elem_size, int len) +{ + int i; + switch(angle) { + case 0: + memcpy(dst, src, elem_size * len); + break; + case 1: + for (i = 0; iangle - 0) < FLT_EPSILON && outw == inw && outh == inh) { + simple_rotate(out->data[plane] + j * out->linesize[plane], + in->data[plane] + j * in->linesize[plane], + in->linesize[plane], 0, rot->draw.pixelstep[plane], outw); + } else if (fabs(rot->angle - M_PI/2) < FLT_EPSILON && outw == inh && outh == inw) { + simple_rotate(out->data[plane] + j * out->linesize[plane], + in->data[plane] + j * rot->draw.pixelstep[plane], + in->linesize[plane], 1, rot->draw.pixelstep[plane], outw); + } else if (fabs(rot->angle - M_PI) < FLT_EPSILON && outw == inw && outh == inh) { + simple_rotate(out->data[plane] + j * out->linesize[plane], + in->data[plane] + (outh-j-1) * in->linesize[plane], + in->linesize[plane], 2, rot->draw.pixelstep[plane], outw); + } else if (fabs(rot->angle - 3*M_PI/2) < FLT_EPSILON && outw == inh && outh == inw) { + simple_rotate(out->data[plane] + j * out->linesize[plane], + in->data[plane] + (outh-j-1) * rot->draw.pixelstep[plane], + in->linesize[plane], 3, rot->draw.pixelstep[plane], outw); + } else { for (i = 0; i < outw; i++) { int32_t v; int x1, y1; uint8_t *pin, *pout; - x += c; - y -= s; x1 = x>>16; y1 = y>>16; @@ -371,6 +446,9 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) break; } } + x += c; + y -= s; + } } xprime += s; yprime += c; @@ -402,7 +480,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_log(ctx, AV_LOG_DEBUG, "n:%f time:%f angle:%f/PI\n", rot->var_values[VAR_N], rot->var_values[VAR_T], rot->angle/M_PI); - angle_int = res * FIXP; + angle_int = res * FIXP * 16; s = int_sin(angle_int); c = int_sin(angle_int + INT_PI/2); @@ -420,9 +498,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) .inw = FF_CEIL_RSHIFT(inlink->w, hsub), .inh = FF_CEIL_RSHIFT(inlink->h, vsub), .outh = outh, .outw = outw, - .xi = -outw/2 * c, .yi = outw/2 * s, - .xprime = -outh/2 * s, - .yprime = -outh/2 * c, + .xi = -(outw-1) * c / 2, .yi = (outw-1) * s / 2, + .xprime = -(outh-1) * s / 2, + .yprime = -(outh-1) * c / 2, .plane = plane, .c = c, .s = s }; diff --git a/libavfilter/vf_sab.c b/libavfilter/vf_sab.c index 51bbc5aed..aa38b533f 100644 --- a/libavfilter/vf_sab.c +++ b/libavfilter/vf_sab.c @@ -180,7 +180,7 @@ static int open_filter_param(FilterParam *f, int width, int height, unsigned int vec = sws_getGaussianVec(f->radius, f->quality); f->dist_width = vec->length; f->dist_linesize = FFALIGN(vec->length, 8); - f->dist_coeff = av_malloc(f->dist_width * f->dist_linesize * sizeof(*f->dist_coeff)); + f->dist_coeff = av_malloc_array(f->dist_width, f->dist_linesize * sizeof(*f->dist_coeff)); if (!f->dist_coeff) { sws_freeVec(vec); return AVERROR(ENOMEM); diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 6b7d474af..c4605c72c 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -71,7 +71,7 @@ enum var_name { VARS_NB }; -typedef struct { +typedef struct ScaleContext { const AVClass *class; struct SwsContext *sws; ///< software scaler context struct SwsContext *isws[2]; ///< software scaler context for interlaced material @@ -178,25 +178,31 @@ static int query_formats(AVFilterContext *ctx) int ret; if (ctx->inputs[0]) { + const AVPixFmtDescriptor *desc = NULL; formats = NULL; - for (pix_fmt = 0; pix_fmt < AV_PIX_FMT_NB; pix_fmt++) + while ((desc = av_pix_fmt_desc_next(desc))) { + pix_fmt = av_pix_fmt_desc_get_id(desc); if ((sws_isSupportedInput(pix_fmt) || sws_isSupportedEndiannessConversion(pix_fmt)) && (ret = ff_add_format(&formats, pix_fmt)) < 0) { ff_formats_unref(&formats); return ret; } + } ff_formats_ref(formats, &ctx->inputs[0]->out_formats); } if (ctx->outputs[0]) { + const AVPixFmtDescriptor *desc = NULL; formats = NULL; - for (pix_fmt = 0; pix_fmt < AV_PIX_FMT_NB; pix_fmt++) + while ((desc = av_pix_fmt_desc_next(desc))) { + pix_fmt = av_pix_fmt_desc_get_id(desc); if ((sws_isSupportedOutput(pix_fmt) || pix_fmt == AV_PIX_FMT_PAL8 || sws_isSupportedEndiannessConversion(pix_fmt)) && (ret = ff_add_format(&formats, pix_fmt)) < 0) { ff_formats_unref(&formats); return ret; } + } ff_formats_ref(formats, &ctx->outputs[0]->in_formats); } diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index ade3e1ae0..323cf7762 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -22,20 +22,67 @@ * filter for showing textual video frame information */ +#include + #include "libavutil/adler32.h" +#include "libavutil/display.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/pixdesc.h" +#include "libavutil/stereo3d.h" #include "libavutil/timestamp.h" + #include "avfilter.h" #include "internal.h" #include "video.h" +static void dump_stereo3d(AVFilterContext *ctx, AVFrameSideData *sd) +{ + AVStereo3D *stereo; + + av_log(ctx, AV_LOG_INFO, "stereoscopic information: "); + if (sd->size < sizeof(*stereo)) { + av_log(ctx, AV_LOG_INFO, "invalid data"); + return; + } + + stereo = (AVStereo3D *)sd->data; + + av_log(ctx, AV_LOG_INFO, "type - "); + switch (stereo->type) { + case AV_STEREO3D_2D: av_log(ctx, AV_LOG_INFO, "2D"); break; + case AV_STEREO3D_SIDEBYSIDE: av_log(ctx, AV_LOG_INFO, "side by side"); break; + case AV_STEREO3D_TOPBOTTOM: av_log(ctx, AV_LOG_INFO, "top and bottom"); break; + case AV_STEREO3D_FRAMESEQUENCE: av_log(ctx, AV_LOG_INFO, "frame alternate"); break; + case AV_STEREO3D_CHECKERBOARD: av_log(ctx, AV_LOG_INFO, "checkerboard"); break; + case AV_STEREO3D_LINES: av_log(ctx, AV_LOG_INFO, "interleaved lines"); break; + case AV_STEREO3D_COLUMNS: av_log(ctx, AV_LOG_INFO, "interleaved columns"); break; + case AV_STEREO3D_SIDEBYSIDE_QUINCUNX: av_log(ctx, AV_LOG_INFO, "side by side " + "(quincunx subsampling)"); 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 update_sample_stats(const uint8_t *src, int len, int64_t *sum, int64_t *sum2) +{ + int i; + + for (i = 0; i < len; i++) { + *sum += src[i]; + *sum2 += src[i] * src[i]; + } +} + static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); uint32_t plane_checksum[4] = {0}, checksum = 0; + int64_t sum[4] = {0}, sum2[4] = {0}; + int32_t pixelcount[4] = {0}; int i, plane, vsub = desc->log2_chroma_h; for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) { @@ -49,6 +96,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) for (i = 0; i < h; i++) { plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize); checksum = av_adler32_update(checksum, data, linesize); + + update_sample_stats(data, linesize, sum+plane, sum2+plane); + pixelcount[plane] += linesize; data += frame->linesize[plane]; } } @@ -56,7 +106,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) av_log(ctx, AV_LOG_INFO, "n:%"PRId64" pts:%s pts_time:%s pos:%"PRId64" " "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c " - "checksum:%08X plane_checksum:[%08X", + "checksum:%08"PRIX32" plane_checksum:[%08"PRIX32, inlink->frame_count, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &inlink->time_base), av_frame_get_pkt_pos(frame), desc->name, @@ -69,8 +119,42 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) checksum, plane_checksum[0]); for (plane = 1; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) - av_log(ctx, AV_LOG_INFO, " %08X", plane_checksum[plane]); - av_log(ctx, AV_LOG_INFO, "]\n"); + av_log(ctx, AV_LOG_INFO, " %08"PRIX32, plane_checksum[plane]); + av_log(ctx, AV_LOG_INFO, "] mean:["); + for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) + av_log(ctx, AV_LOG_INFO, "%"PRId64" ", (sum[plane] + pixelcount[plane]/2) / pixelcount[plane]); + av_log(ctx, AV_LOG_INFO, "\b] stdev:["); + for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) + av_log(ctx, AV_LOG_INFO, "%3.1f ", + sqrt((sum2[plane] - sum[plane]*(double)sum[plane]/pixelcount[plane])/pixelcount[plane])); + av_log(ctx, AV_LOG_INFO, "\b]\n"); + + for (i = 0; i < frame->nb_side_data; i++) { + AVFrameSideData *sd = frame->side_data[i]; + + av_log(ctx, AV_LOG_INFO, " side data - "); + switch (sd->type) { + case AV_FRAME_DATA_PANSCAN: + av_log(ctx, AV_LOG_INFO, "pan/scan"); + break; + case AV_FRAME_DATA_A53_CC: + av_log(ctx, AV_LOG_INFO, "A/53 closed captions (%d bytes)", sd->size); + break; + case AV_FRAME_DATA_STEREO3D: + dump_stereo3d(ctx, sd); + break; + case AV_FRAME_DATA_DISPLAYMATRIX: + av_log(ctx, AV_LOG_INFO, "displaymatrix: rotation of %.2f degrees", + av_display_rotation_get((int32_t *)sd->data)); + break; + default: + av_log(ctx, AV_LOG_WARNING, "unknown side data type %d (%d bytes)", + sd->type, sd->size); + break; + } + + av_log(ctx, AV_LOG_INFO, "\n"); + } return ff_filter_frame(inlink->dst->outputs[0], frame); } diff --git a/libavfilter/vf_shuffleplanes.c b/libavfilter/vf_shuffleplanes.c new file mode 100644 index 000000000..80085cd71 --- /dev/null +++ b/libavfilter/vf_shuffleplanes.c @@ -0,0 +1,172 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/pixfmt.h" + +#include "avfilter.h" +#include "internal.h" +#include "video.h" + +typedef struct ShufflePlanesContext { + const AVClass *class; + + /* number of planes in the selected pixel format */ + int planes; + + /* mapping indices */ + int map[4]; + + /* set to 1 if some plane is used more than once, so we need to make a copy */ + int copy; +} ShufflePlanesContext; + +static av_cold int shuffleplanes_config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ShufflePlanesContext *s = ctx->priv; + const AVPixFmtDescriptor *desc; + int used[4] = { 0 }; + int i; + + s->copy = 0; + s->planes = av_pix_fmt_count_planes(inlink->format); + desc = av_pix_fmt_desc_get(inlink->format); + + for (i = 0; i < s->planes; i++) { + if (s->map[i] >= s->planes) { + av_log(ctx, AV_LOG_ERROR, + "Non-existing input plane #%d mapped to output plane #%d.\n", + s->map[i], i); + return AVERROR(EINVAL); + } + + if ((desc->log2_chroma_h || desc->log2_chroma_w) && + (i == 1 || i == 2) != (s->map[i] == 1 || s->map[i] == 2)) { + av_log(ctx, AV_LOG_ERROR, + "Cannot map between a subsampled chroma plane and a luma " + "or alpha plane.\n"); + return AVERROR(EINVAL); + } + + if ((desc->flags & AV_PIX_FMT_FLAG_PAL || + desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) && + (i == 1) != (s->map[i] == 1)) { + av_log(ctx, AV_LOG_ERROR, + "Cannot map between a palette plane and a data plane.\n"); + return AVERROR(EINVAL); + } + if (used[s->map[i]]) + s->copy = 1; + used[s->map[i]]++; + } + + return 0; +} + +static int shuffleplanes_filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + ShufflePlanesContext *s = ctx->priv; + uint8_t *shuffled_data[4] = { NULL }; + int shuffled_linesize[4] = { 0 }; + int i, ret; + + for (i = 0; i < s->planes; i++) { + shuffled_data[i] = frame->data[s->map[i]]; + shuffled_linesize[i] = frame->linesize[s->map[i]]; + } + memcpy(frame->data, shuffled_data, sizeof(shuffled_data)); + memcpy(frame->linesize, shuffled_linesize, sizeof(shuffled_linesize)); + + if (s->copy) { + AVFrame *copy = ff_get_video_buffer(ctx->outputs[0], frame->width, frame->height); + + if (!copy) { + ret = AVERROR(ENOMEM); + goto fail; + } + + av_frame_copy(copy, frame); + + ret = av_frame_copy_props(copy, frame); + if (ret < 0) { + av_frame_free(©); + goto fail; + } + + av_frame_free(&frame); + frame = copy; + } + + return ff_filter_frame(ctx->outputs[0], frame); +fail: + av_frame_free(&frame); + return ret; +} + +#define OFFSET(x) offsetof(ShufflePlanesContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption shuffleplanes_options[] = { + { "map0", "Index of the input plane to be used as the first output plane ", OFFSET(map[0]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 4, FLAGS }, + { "map1", "Index of the input plane to be used as the second output plane ", OFFSET(map[1]), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 4, FLAGS }, + { "map2", "Index of the input plane to be used as the third output plane ", OFFSET(map[2]), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 4, FLAGS }, + { "map3", "Index of the input plane to be used as the fourth output plane ", OFFSET(map[3]), AV_OPT_TYPE_INT, { .i64 = 3 }, 0, 4, FLAGS }, + { NULL }, +}; + +static const AVClass shuffleplanes_class = { + .class_name = "shuffleplanes", + .item_name = av_default_item_name, + .option = shuffleplanes_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVFilterPad shuffleplanes_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = shuffleplanes_config_input, + .filter_frame = shuffleplanes_filter_frame, + .get_video_buffer = ff_null_get_video_buffer, + }, + { NULL }, +}; + +static const AVFilterPad shuffleplanes_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL }, +}; + +AVFilter ff_vf_shuffleplanes = { + .name = "shuffleplanes", + .description = NULL_IF_CONFIG_SMALL("Shuffle video planes"), + + .priv_size = sizeof(ShufflePlanesContext), + .priv_class = &shuffleplanes_class, + + .inputs = shuffleplanes_inputs, + .outputs = shuffleplanes_outputs, +}; diff --git a/libavfilter/vf_signalstats.c b/libavfilter/vf_signalstats.c new file mode 100644 index 000000000..263de2351 --- /dev/null +++ b/libavfilter/vf_signalstats.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2010 Mark Heath mjpeg0 @ silicontrip dot org + * Copyright (c) 2014 Clément Bœsch + * Copyright (c) 2014 Dave Rice @dericed + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "internal.h" + +enum FilterMode { + FILTER_NONE = -1, + FILTER_TOUT, + FILTER_VREP, + FILTER_BRNG, + FILT_NUMB +}; + +typedef struct { + const AVClass *class; + int chromah; // height of chroma plane + int chromaw; // width of chroma plane + int hsub; // horizontal subsampling + int vsub; // vertical subsampling + int fs; // pixel count per frame + int cfs; // pixel count per frame of chroma planes + enum FilterMode outfilter; + int filters; + AVFrame *frame_prev; + char *vrep_line; + uint8_t rgba_color[4]; + int yuv_color[3]; +} SignalstatsContext; + +#define OFFSET(x) offsetof(SignalstatsContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption signalstats_options[] = { + {"stat", "set statistics filters", OFFSET(filters), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "filters"}, + {"tout", "analyze pixels for temporal outliers", 0, AV_OPT_TYPE_CONST, {.i64=1<priv; + + if (s->outfilter != FILTER_NONE) + s->filters |= 1 << s->outfilter; + + r = s->rgba_color[0]; + g = s->rgba_color[1]; + b = s->rgba_color[2]; + s->yuv_color[0] = (( 66*r + 129*g + 25*b + (1<<7)) >> 8) + 16; + s->yuv_color[1] = ((-38*r + -74*g + 112*b + (1<<7)) >> 8) + 128; + s->yuv_color[2] = ((112*r + -94*g + -18*b + (1<<7)) >> 8) + 128; + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + SignalstatsContext *s = ctx->priv; + av_frame_free(&s->frame_prev); + av_freep(&s->vrep_line); +} + +static int query_formats(AVFilterContext *ctx) +{ + // TODO: add more + enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_NONE + }; + + ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); + return 0; +} + +static int config_props(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + SignalstatsContext *s = ctx->priv; + AVFilterLink *inlink = outlink->src->inputs[0]; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); + s->hsub = desc->log2_chroma_w; + s->vsub = desc->log2_chroma_h; + + outlink->w = inlink->w; + outlink->h = inlink->h; + + s->chromaw = FF_CEIL_RSHIFT(inlink->w, s->hsub); + s->chromah = FF_CEIL_RSHIFT(inlink->h, s->vsub); + + s->fs = inlink->w * inlink->h; + s->cfs = s->chromaw * s->chromah; + + if (s->filters & 1<vrep_line = av_malloc(inlink->h * sizeof(*s->vrep_line)); + if (!s->vrep_line) + return AVERROR(ENOMEM); + } + + return 0; +} + +static void burn_frame(SignalstatsContext *s, AVFrame *f, int x, int y) +{ + const int chromax = x >> s->hsub; + const int chromay = y >> s->vsub; + f->data[0][y * f->linesize[0] + x] = s->yuv_color[0]; + f->data[1][chromay * f->linesize[1] + chromax] = s->yuv_color[1]; + f->data[2][chromay * f->linesize[2] + chromax] = s->yuv_color[2]; +} + +static int filter_brng(SignalstatsContext *s, const AVFrame *in, AVFrame *out, int y, int w, int h) +{ + int x, score = 0; + const int yc = y >> s->vsub; + const uint8_t *pluma = &in->data[0][y * in->linesize[0]]; + const uint8_t *pchromau = &in->data[1][yc * in->linesize[1]]; + const uint8_t *pchromav = &in->data[2][yc * in->linesize[2]]; + + for (x = 0; x < w; x++) { + const int xc = x >> s->hsub; + const int luma = pluma[x]; + const int chromau = pchromau[xc]; + const int chromav = pchromav[xc]; + const int filt = luma < 16 || luma > 235 || + chromau < 16 || chromau > 240 || + chromav < 16 || chromav > 240; + score += filt; + if (out && filt) + burn_frame(s, out, x, y); + } + return score; +} + +static int filter_tout_outlier(uint8_t x, uint8_t y, uint8_t z) +{ + return ((abs(x - y) + abs (z - y)) / 2) - abs(z - x) > 4; // make 4 configurable? +} + +static int filter_tout(SignalstatsContext *s, const AVFrame *in, AVFrame *out, int y, int w, int h) +{ + const uint8_t *p = in->data[0]; + int lw = in->linesize[0]; + int x, score = 0, filt; + + if (y - 1 < 0 || y + 1 >= h) + return 0; + + // detect two pixels above and below (to eliminate interlace artefacts) + // should check that video format is infact interlaced. + +#define FILTER(i, j) \ +filter_tout_outlier(p[(y-j) * lw + x + i], \ + p[ y * lw + x + i], \ + p[(y+j) * lw + x + i]) + +#define FILTER3(j) (FILTER(-1, j) && FILTER(0, j) && FILTER(1, j)) + + if (y - 2 >= 0 && y + 2 < h) { + for (x = 1; x < w - 1; x++) { + filt = FILTER3(2) && FILTER3(1); + score += filt; + if (filt && out) + burn_frame(s, out, x, y); + } + } else { + for (x = 1; x < w - 1; x++) { + filt = FILTER3(1); + score += filt; + if (filt && out) + burn_frame(s, out, x, y); + } + } + return score; +} + +#define VREP_START 4 + +static void filter_init_vrep(SignalstatsContext *s, const AVFrame *p, int w, int h) +{ + int i, y; + int lw = p->linesize[0]; + + for (y = VREP_START; y < h; y++) { + int totdiff = 0; + int y2lw = (y - VREP_START) * lw; + int ylw = y * lw; + + for (i = 0; i < w; i++) + totdiff += abs(p->data[0][y2lw + i] - p->data[0][ylw + i]); + + /* this value should be definable */ + s->vrep_line[y] = totdiff < w; + } +} + +static int filter_vrep(SignalstatsContext *s, const AVFrame *in, AVFrame *out, int y, int w, int h) +{ + int x, score = 0; + + if (y < VREP_START) + return 0; + + for (x = 0; x < w; x++) { + if (s->vrep_line[y]) { + score++; + if (out) + burn_frame(s, out, x, y); + } + } + return score; +} + +static const struct { + const char *name; + void (*init)(SignalstatsContext *s, const AVFrame *p, int w, int h); + int (*process)(SignalstatsContext *s, const AVFrame *in, AVFrame *out, int y, int w, int h); +} filters_def[] = { + {"TOUT", NULL, filter_tout}, + {"VREP", filter_init_vrep, filter_vrep}, + {"BRNG", NULL, filter_brng}, + {NULL} +}; + +#define DEPTH 256 + +static int filter_frame(AVFilterLink *link, AVFrame *in) +{ + SignalstatsContext *s = link->dst->priv; + AVFilterLink *outlink = link->dst->outputs[0]; + AVFrame *out = in; + int i, j; + int w = 0, cw = 0, // in + pw = 0, cpw = 0; // prev + int yuv, yuvu, yuvv; + int fil; + char metabuf[128]; + unsigned int histy[DEPTH] = {0}, + histu[DEPTH] = {0}, + histv[DEPTH] = {0}, + histhue[360] = {0}, + histsat[DEPTH] = {0}; // limited to 8 bit data. + int miny = -1, minu = -1, minv = -1; + int maxy = -1, maxu = -1, maxv = -1; + int lowy = -1, lowu = -1, lowv = -1; + int highy = -1, highu = -1, highv = -1; + int minsat = -1, maxsat = -1, lowsat = -1, highsat = -1; + int lowp, highp, clowp, chighp; + int accy, accu, accv; + int accsat, acchue = 0; + int medhue, maxhue; + int toty = 0, totu = 0, totv = 0, totsat=0; + int tothue = 0; + int dify = 0, difu = 0, difv = 0; + + int filtot[FILT_NUMB] = {0}; + AVFrame *prev; + + if (!s->frame_prev) + s->frame_prev = av_frame_clone(in); + + prev = s->frame_prev; + + if (s->outfilter != FILTER_NONE) + out = av_frame_clone(in); + + for (fil = 0; fil < FILT_NUMB; fil ++) + if ((s->filters & 1<w, link->h); + + // Calculate luma histogram and difference with previous frame or field. + for (j = 0; j < link->h; j++) { + for (i = 0; i < link->w; i++) { + yuv = in->data[0][w + i]; + histy[yuv]++; + dify += abs(in->data[0][w + i] - prev->data[0][pw + i]); + } + w += in->linesize[0]; + pw += prev->linesize[0]; + } + + // Calculate chroma histogram and difference with previous frame or field. + for (j = 0; j < s->chromah; j++) { + for (i = 0; i < s->chromaw; i++) { + int sat, hue; + + yuvu = in->data[1][cw+i]; + yuvv = in->data[2][cw+i]; + histu[yuvu]++; + difu += abs(in->data[1][cw+i] - prev->data[1][cpw+i]); + histv[yuvv]++; + difv += abs(in->data[2][cw+i] - prev->data[2][cpw+i]); + + // int or round? + sat = hypot(yuvu - 128, yuvv - 128); + histsat[sat]++; + hue = floor((180 / M_PI) * atan2f(yuvu-128, yuvv-128) + 180); + histhue[hue]++; + } + cw += in->linesize[1]; + cpw += prev->linesize[1]; + } + + for (j = 0; j < link->h; j++) { + for (fil = 0; fil < FILT_NUMB; fil ++) { + if (s->filters & 1<outfilter == fil ? out : NULL; + filtot[fil] += filters_def[fil].process(s, in, dbg, j, link->w, link->h); + } + } + } + + // find low / high based on histogram percentile + // these only need to be calculated once. + + lowp = lrint(s->fs * 10 / 100.); + highp = lrint(s->fs * 90 / 100.); + clowp = lrint(s->cfs * 10 / 100.); + chighp = lrint(s->cfs * 90 / 100.); + + accy = accu = accv = accsat = 0; + for (fil = 0; fil < DEPTH; fil++) { + if (miny < 0 && histy[fil]) miny = fil; + if (minu < 0 && histu[fil]) minu = fil; + if (minv < 0 && histv[fil]) minv = fil; + if (minsat < 0 && histsat[fil]) minsat = fil; + + if (histy[fil]) maxy = fil; + if (histu[fil]) maxu = fil; + if (histv[fil]) maxv = fil; + if (histsat[fil]) maxsat = fil; + + toty += histy[fil] * fil; + totu += histu[fil] * fil; + totv += histv[fil] * fil; + totsat += histsat[fil] * fil; + + accy += histy[fil]; + accu += histu[fil]; + accv += histv[fil]; + accsat += histsat[fil]; + + if (lowy == -1 && accy >= lowp) lowy = fil; + if (lowu == -1 && accu >= clowp) lowu = fil; + if (lowv == -1 && accv >= clowp) lowv = fil; + if (lowsat == -1 && accsat >= clowp) lowsat = fil; + + if (highy == -1 && accy >= highp) highy = fil; + if (highu == -1 && accu >= chighp) highu = fil; + if (highv == -1 && accv >= chighp) highv = fil; + if (highsat == -1 && accsat >= chighp) highsat = fil; + } + + maxhue = histhue[0]; + medhue = -1; + for (fil = 0; fil < 360; fil++) { + tothue += histhue[fil] * fil; + acchue += histhue[fil]; + + if (medhue == -1 && acchue > s->cfs / 2) + medhue = fil; + if (histhue[fil] > maxhue) { + maxhue = histhue[fil]; + } + } + + av_frame_free(&s->frame_prev); + s->frame_prev = av_frame_clone(in); + +#define SET_META(key, fmt, val) do { \ + snprintf(metabuf, sizeof(metabuf), fmt, val); \ + av_dict_set(&out->metadata, "lavfi.signalstats." key, metabuf, 0); \ +} while (0) + + SET_META("YMIN", "%d", miny); + SET_META("YLOW", "%d", lowy); + SET_META("YAVG", "%g", 1.0 * toty / s->fs); + SET_META("YHIGH", "%d", highy); + SET_META("YMAX", "%d", maxy); + + SET_META("UMIN", "%d", minu); + SET_META("ULOW", "%d", lowu); + SET_META("UAVG", "%g", 1.0 * totu / s->cfs); + SET_META("UHIGH", "%d", highu); + SET_META("UMAX", "%d", maxu); + + SET_META("VMIN", "%d", minv); + SET_META("VLOW", "%d", lowv); + SET_META("VAVG", "%g", 1.0 * totv / s->cfs); + SET_META("VHIGH", "%d", highv); + SET_META("VMAX", "%d", maxv); + + SET_META("SATMIN", "%d", minsat); + SET_META("SATLOW", "%d", lowsat); + SET_META("SATAVG", "%g", 1.0 * totsat / s->cfs); + SET_META("SATHIGH", "%d", highsat); + SET_META("SATMAX", "%d", maxsat); + + SET_META("HUEMED", "%d", medhue); + SET_META("HUEAVG", "%g", 1.0 * tothue / s->cfs); + + SET_META("YDIF", "%g", 1.0 * dify / s->fs); + SET_META("UDIF", "%g", 1.0 * difu / s->cfs); + SET_META("VDIF", "%g", 1.0 * difv / s->cfs); + + for (fil = 0; fil < FILT_NUMB; fil ++) { + if (s->filters & 1<fs); + snprintf(metaname, sizeof(metaname), "lavfi.signalstats.%s", filters_def[fil].name); + av_dict_set(&out->metadata, metaname, metabuf, 0); + } + } + + if (in != out) + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static const AVFilterPad signalstats_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad signalstats_outputs[] = { + { + .name = "default", + .config_props = config_props, + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_signalstats = { + .name = "signalstats", + .description = "Generate statistics from video analysis.", + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .priv_size = sizeof(SignalstatsContext), + .inputs = signalstats_inputs, + .outputs = signalstats_outputs, + .priv_class = &signalstats_class, +}; diff --git a/libavfilter/vf_smartblur.c b/libavfilter/vf_smartblur.c index 114ac6f6d..b09ec90ec 100644 --- a/libavfilter/vf_smartblur.c +++ b/libavfilter/vf_smartblur.c @@ -201,7 +201,7 @@ static void blur(uint8_t *dst, const int dst_linesize, if (diff > 2 * threshold) dst[x + y * dst_linesize] = orig; else if (diff > threshold) - /* add 'diff' and substract 'threshold' from 'filtered' */ + /* add 'diff' and subtract 'threshold' from 'filtered' */ dst[x + y * dst_linesize] = orig - threshold; } else { if (-diff > 2 * threshold) @@ -223,13 +223,13 @@ static void blur(uint8_t *dst, const int dst_linesize, if (diff <= -threshold) dst[x + y * dst_linesize] = orig; else if (diff <= -2 * threshold) - /* substract 'diff' and 'threshold' from 'orig' */ + /* subtract 'diff' and 'threshold' from 'orig' */ dst[x + y * dst_linesize] = filtered - threshold; } else { if (diff >= threshold) dst[x + y * dst_linesize] = orig; else if (diff >= 2 * threshold) - /* add 'threshold' and substract 'diff' from 'orig' */ + /* add 'threshold' and subtract 'diff' from 'orig' */ dst[x + y * dst_linesize] = filtered + threshold; } } diff --git a/libavfilter/vf_spp.c b/libavfilter/vf_spp.c index 683e333db..4e4a5795f 100644 --- a/libavfilter/vf_spp.c +++ b/libavfilter/vf_spp.c @@ -232,10 +232,10 @@ static void filter(SPPContext *p, uint8_t *dst, uint8_t *src, const int x1 = x + offset[i + count - 1][0]; const int y1 = y + offset[i + count - 1][1]; const int index = x1 + y1*linesize; - p->dsp.get_pixels(block, p->src + index, linesize); - p->dsp.fdct(block); - p->requantize(block2, block, qp, p->dsp.idct_permutation); - p->dsp.idct(block2); + p->pdsp.get_pixels(block, p->src + index, linesize); + p->fdsp.fdct(block); + p->requantize(block2, block, qp, p->idsp.idct_permutation); + p->idsp.idct(block2); add_block(p->temp + index, linesize, block2); } } @@ -270,8 +270,8 @@ static int config_input(AVFilterLink *inlink) spp->hsub = desc->log2_chroma_w; spp->vsub = desc->log2_chroma_h; spp->temp_linesize = FFALIGN(inlink->w + 16, 16); - spp->temp = av_malloc(spp->temp_linesize * h * sizeof(*spp->temp)); - spp->src = av_malloc(spp->temp_linesize * h * sizeof(*spp->src)); + spp->temp = av_malloc_array(spp->temp_linesize, h * sizeof(*spp->temp)); + spp->src = av_malloc_array(spp->temp_linesize, h * sizeof(*spp->src)); if (!spp->use_bframe_qp) { /* we are assuming here the qp blocks will not be smaller that 16x16 */ spp->non_b_qp_alloc_size = FF_CEIL_RSHIFT(inlink->w, 4) * FF_CEIL_RSHIFT(inlink->h, 4); @@ -380,7 +380,9 @@ static av_cold int init(AVFilterContext *ctx) spp->avctx = avcodec_alloc_context3(NULL); if (!spp->avctx) return AVERROR(ENOMEM); - avpriv_dsputil_init(&spp->dsp, spp->avctx); + ff_idctdsp_init(&spp->idsp, spp->avctx); + ff_fdctdsp_init(&spp->fdsp, spp->avctx); + ff_pixblockdsp_init(&spp->pdsp, spp->avctx); spp->store_slice = store_slice_c; switch (spp->mode) { case MODE_HARD: spp->requantize = hardthresh_c; break; diff --git a/libavfilter/vf_spp.h b/libavfilter/vf_spp.h index c4293b6fc..c8eac3caf 100644 --- a/libavfilter/vf_spp.h +++ b/libavfilter/vf_spp.h @@ -23,7 +23,9 @@ #define AVFILTER_SPP_H #include "libavcodec/avcodec.h" -#include "libavcodec/dsputil.h" +#include "libavcodec/pixblockdsp.h" +#include "libavcodec/idctdsp.h" +#include "libavcodec/fdctdsp.h" #include "avfilter.h" #define MAX_LEVEL 6 /* quality levels */ @@ -39,7 +41,9 @@ typedef struct { uint8_t *src; int16_t *temp; AVCodecContext *avctx; - DSPContext dsp; + IDCTDSPContext idsp; + FDCTDSPContext fdsp; + PixblockDSPContext pdsp; int8_t *non_b_qp_table; int non_b_qp_alloc_size; int use_bframe_qp; diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c index e44f61ddc..558e509e4 100644 --- a/libavfilter/vf_subtitles.c +++ b/libavfilter/vf_subtitles.c @@ -51,6 +51,7 @@ typedef struct { ASS_Track *track; char *filename; char *charenc; + int stream_index; uint8_t rgba_map[4]; int pix_step[4]; ///< steps per pixel for each plane of the main output int original_w, original_h; @@ -107,7 +108,6 @@ static av_cold int init(AVFilterContext *ctx) return AVERROR(EINVAL); } - ass_set_fonts(ass->renderer, NULL, NULL, 1, NULL, 1); return 0; } @@ -218,6 +218,9 @@ static av_cold int init_ass(AVFilterContext *ctx) if (ret < 0) return ret; + /* Initialize fonts */ + ass_set_fonts(ass->renderer, NULL, NULL, 1, NULL, 1); + ass->track = ass_read_file(ass->library, ass->filename, NULL); if (!ass->track) { av_log(ctx, AV_LOG_ERROR, @@ -245,15 +248,41 @@ AVFilter ff_vf_ass = { static const AVOption subtitles_options[] = { COMMON_OPTIONS - {"charenc", "set input character encoding", OFFSET(charenc), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, FLAGS}, + {"charenc", "set input character encoding", OFFSET(charenc), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, FLAGS}, + {"stream_index", "set stream index", OFFSET(stream_index), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS}, + {"si", "set stream index", OFFSET(stream_index), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS}, {NULL}, }; +static const char *font_mimetypes[] = { + "application/x-truetype-font", + "application/vnd.ms-opentype", + "application/x-font-ttf", + NULL +}; + +static int attachment_is_font(AVStream * st) +{ + const AVDictionaryEntry *tag = NULL; + int n; + + tag = av_dict_get(st->metadata, "mimetype", NULL, AV_DICT_MATCH_CASE); + + if (tag) { + for (n = 0; font_mimetypes[n]; n++) { + if (av_strcasecmp(font_mimetypes[n], tag->value) == 0) + return 1; + } + } + return 0; +} + AVFILTER_DEFINE_CLASS(subtitles); static av_cold int init_subtitles(AVFilterContext *ctx) { - int ret, sid; + int j, ret, sid; + int k = 0; AVDictionary *codec_opts = NULL; AVFormatContext *fmt = NULL; AVCodecContext *dec_ctx = NULL; @@ -284,7 +313,23 @@ static av_cold int init_subtitles(AVFilterContext *ctx) goto end; /* Locate subtitles stream */ - ret = av_find_best_stream(fmt, AVMEDIA_TYPE_SUBTITLE, -1, -1, NULL, 0); + if (ass->stream_index < 0) + ret = av_find_best_stream(fmt, AVMEDIA_TYPE_SUBTITLE, -1, -1, NULL, 0); + else { + ret = -1; + if (ass->stream_index < fmt->nb_streams) { + for (j = 0; j < fmt->nb_streams; j++) { + if (fmt->streams[j]->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { + if (ass->stream_index == k) { + ret = j; + break; + } + k++; + } + } + } + } + if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to locate subtitle stream in %s\n", ass->filename); @@ -293,6 +338,31 @@ static av_cold int init_subtitles(AVFilterContext *ctx) sid = ret; st = fmt->streams[sid]; + /* Load attached fonts */ + for (j = 0; j < fmt->nb_streams; j++) { + AVStream *st = fmt->streams[j]; + if (st->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT && + attachment_is_font(st)) { + const AVDictionaryEntry *tag = NULL; + tag = av_dict_get(st->metadata, "filename", NULL, + AV_DICT_MATCH_CASE); + + if (tag) { + av_log(ctx, AV_LOG_DEBUG, "Loading attached font: %s\n", + tag->value); + ass_add_font(ass->library, tag->value, + st->codec->extradata, + st->codec->extradata_size); + } else { + av_log(ctx, AV_LOG_WARNING, + "Font attachment has no filename, ignored.\n"); + } + } + } + + /* Initialize fonts */ + ass_set_fonts(ass->renderer, NULL, NULL, 1, NULL, 1); + /* Open decoder */ dec_ctx = st->codec; dec = avcodec_find_decoder(dec_ctx->codec_id); diff --git a/libavfilter/vf_swapuv.c b/libavfilter/vf_swapuv.c index 71ae243a3..175e39c63 100644 --- a/libavfilter/vf_swapuv.c +++ b/libavfilter/vf_swapuv.c @@ -73,7 +73,7 @@ static int query_formats(AVFilterContext *ctx) AVFilterFormats *formats = NULL; int fmt; - for (fmt = 0; fmt < AV_PIX_FMT_NB; fmt++) { + for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); if (is_planar_yuv(desc)) ff_add_format(&formats, fmt); diff --git a/libavfilter/vf_telecine.c b/libavfilter/vf_telecine.c index 811ae2773..aea63ab7a 100644 --- a/libavfilter/vf_telecine.c +++ b/libavfilter/vf_telecine.c @@ -101,7 +101,7 @@ static int query_formats(AVFilterContext *ctx) AVFilterFormats *pix_fmts = NULL; int fmt; - for (fmt = 0; fmt < AV_PIX_FMT_NB; fmt++) { + for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL || desc->flags & AV_PIX_FMT_FLAG_PAL || diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c index db8239311..3ebb97164 100644 --- a/libavfilter/vf_tinterlace.c +++ b/libavfilter/vf_tinterlace.c @@ -145,6 +145,12 @@ static int config_out_props(AVFilterLink *outlink) tinterlace->mode); tinterlace->flags &= ~TINTERLACE_FLAG_VLPF; } + if (tinterlace->mode == MODE_INTERLACEX2) { + outlink->time_base.num = inlink->time_base.num; + outlink->time_base.den = inlink->time_base.den * 2; + outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2,1}); + } + av_log(ctx, AV_LOG_VERBOSE, "mode:%d filter:%s h:%d -> h:%d\n", tinterlace->mode, (tinterlace->flags & TINTERLACE_FLAG_VLPF) ? "on" : "off", inlink->h, outlink->h); @@ -321,6 +327,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) if (!out) return AVERROR(ENOMEM); out->interlaced_frame = 1; + if (cur->pts != AV_NOPTS_VALUE) + out->pts = cur->pts*2; if ((ret = ff_filter_frame(outlink, out)) < 0) return ret; @@ -333,6 +341,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) av_frame_copy_props(out, next); out->interlaced_frame = 1; + if (next->pts != AV_NOPTS_VALUE && cur->pts != AV_NOPTS_VALUE) + out->pts = cur->pts + next->pts; + else + out->pts = AV_NOPTS_VALUE; /* write current frame second field lines into the second field of the new frame */ copy_picture_field(out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c index 7e471d49a..d9b165cfe 100644 --- a/libavfilter/vf_transpose.c +++ b/libavfilter/vf_transpose.c @@ -27,11 +27,12 @@ #include -#include "libavutil/intreadwrite.h" -#include "libavutil/pixdesc.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" #include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + #include "avfilter.h" #include "formats.h" #include "internal.h" @@ -50,7 +51,7 @@ enum TransposeDir { TRANSPOSE_CLOCK_FLIP, }; -typedef struct { +typedef struct TransContext { const AVClass *class; int hsub, vsub; int pixsteps[4]; @@ -64,7 +65,7 @@ static int query_formats(AVFilterContext *ctx) AVFilterFormats *pix_fmts = NULL; int fmt; - for (fmt = 0; fmt < AV_PIX_FMT_NB; fmt++) { + for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_HWACCEL || @@ -111,12 +112,14 @@ static int config_props_output(AVFilterLink *outlink) outlink->w = inlink->h; outlink->h = inlink->w; - if (inlink->sample_aspect_ratio.num){ - outlink->sample_aspect_ratio = av_div_q((AVRational){1,1}, inlink->sample_aspect_ratio); - } else + if (inlink->sample_aspect_ratio.num) + outlink->sample_aspect_ratio = av_div_q((AVRational) { 1, 1 }, + inlink->sample_aspect_ratio); + else outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; - av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d dir:%d -> w:%d h:%d rotation:%s vflip:%d\n", + av_log(ctx, AV_LOG_VERBOSE, + "w:%d h:%d dir:%d -> w:%d h:%d rotation:%s vflip:%d\n", inlink->w, inlink->h, trans->dir, outlink->w, outlink->h, trans->dir == 1 || trans->dir == 3 ? "clockwise" : "counterclockwise", trans->dir == 0 || trans->dir == 3); @@ -146,30 +149,30 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int plane; for (plane = 0; out->data[plane]; plane++) { - int hsub = plane == 1 || plane == 2 ? trans->hsub : 0; - int vsub = plane == 1 || plane == 2 ? trans->vsub : 0; + int hsub = plane == 1 || plane == 2 ? trans->hsub : 0; + int vsub = plane == 1 || plane == 2 ? trans->vsub : 0; int pixstep = trans->pixsteps[plane]; - int inh = in->height >> vsub; - int outw = FF_CEIL_RSHIFT(out->width, hsub); - int outh = FF_CEIL_RSHIFT(out->height, vsub); - int start = (outh * jobnr ) / nb_jobs; - int end = (outh * (jobnr+1)) / nb_jobs; + int inh = in->height >> vsub; + int outw = FF_CEIL_RSHIFT(out->width, hsub); + int outh = FF_CEIL_RSHIFT(out->height, vsub); + int start = (outh * jobnr ) / nb_jobs; + int end = (outh * (jobnr+1)) / nb_jobs; uint8_t *dst, *src; int dstlinesize, srclinesize; int x, y; dstlinesize = out->linesize[plane]; - dst = out->data[plane] + start * dstlinesize; - src = in->data[plane]; + dst = out->data[plane] + start * dstlinesize; + src = in->data[plane]; srclinesize = in->linesize[plane]; - if (trans->dir&1) { - src += in->linesize[plane] * (inh-1); + if (trans->dir & 1) { + src += in->linesize[plane] * (inh - 1); srclinesize *= -1; } - if (trans->dir&2) { - dst = out->data[plane] + dstlinesize * (outh-start-1); + if (trans->dir & 2) { + dst = out->data[plane] + dstlinesize * (outh - start - 1); dstlinesize *= -1; } @@ -177,32 +180,34 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, case 1: for (y = start; y < end; y++, dst += dstlinesize) for (x = 0; x < outw; x++) - dst[x] = src[x*srclinesize + y]; + dst[x] = src[x * srclinesize + y]; break; case 2: for (y = start; y < end; y++, dst += dstlinesize) { for (x = 0; x < outw; x++) - *((uint16_t *)(dst + 2*x)) = *((uint16_t *)(src + x*srclinesize + y*2)); + *((uint16_t *)(dst + 2 * x)) = + *((uint16_t *)(src + x * srclinesize + y * 2)); } break; case 3: for (y = start; y < end; y++, dst += dstlinesize) { for (x = 0; x < outw; x++) { - int32_t v = AV_RB24(src + x*srclinesize + y*3); - AV_WB24(dst + 3*x, v); + int32_t v = AV_RB24(src + x * srclinesize + y * 3); + AV_WB24(dst + 3 * x, v); } } break; case 4: for (y = start; y < end; y++, dst += dstlinesize) { for (x = 0; x < outw; x++) - *((uint32_t *)(dst + 4*x)) = *((uint32_t *)(src + x*srclinesize + y*4)); + *((uint32_t *)(dst + 4 * x)) = + *((uint32_t *)(src + x * srclinesize + y * 4)); } break; case 6: for (y = start; y < end; y++, dst += dstlinesize) { for (x = 0; x < outw; x++) { - int64_t v = AV_RB48(src + x*srclinesize + y*6); + int64_t v = AV_RB48(src + x * srclinesize + y*6); AV_WB48(dst + 6*x, v); } } @@ -210,7 +215,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, case 8: for (y = start; y < end; y++, dst += dstlinesize) { for (x = 0; x < outw; x++) - *((uint64_t *)(dst + 8*x)) = *((uint64_t *)(src + x*srclinesize + y*8)); + *((uint64_t *)(dst + 8*x)) = *((uint64_t *)(src + x * srclinesize + y*8)); } break; } @@ -273,10 +278,10 @@ AVFILTER_DEFINE_CLASS(transpose); static const AVFilterPad avfilter_vf_transpose_inputs[] = { { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = get_video_buffer, - .filter_frame = filter_frame, + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/vf_unsharp.c b/libavfilter/vf_unsharp.c index b9f6821b0..37053d98e 100644 --- a/libavfilter/vf_unsharp.c +++ b/libavfilter/vf_unsharp.c @@ -184,7 +184,8 @@ static int init_filter_param(AVFilterContext *ctx, UnsharpFilterParam *fp, const effect, effect_type, fp->msize_x, fp->msize_y, fp->amount / 65535.0); for (z = 0; z < 2 * fp->steps_y; z++) - if (!(fp->sc[z] = av_malloc(sizeof(*(fp->sc[z])) * (width + 2 * fp->steps_x)))) + if (!(fp->sc[z] = av_malloc_array(width + 2 * fp->steps_x, + sizeof(*(fp->sc[z]))))) return AVERROR(ENOMEM); return 0; diff --git a/libavfilter/vf_vflip.c b/libavfilter/vf_vflip.c index f6908e46a..4a4ae0e5e 100644 --- a/libavfilter/vf_vflip.c +++ b/libavfilter/vf_vflip.c @@ -29,7 +29,7 @@ #include "internal.h" #include "video.h" -typedef struct { +typedef struct FlipContext { int vsub; ///< vertical chroma subsampling } FlipContext; diff --git a/libavfilter/vf_vignette.c b/libavfilter/vf_vignette.c index 8ce7b7e6c..806bd72b5 100644 --- a/libavfilter/vf_vignette.c +++ b/libavfilter/vf_vignette.c @@ -197,18 +197,23 @@ static inline double get_dither_value(VignetteContext *s) static int filter_frame(AVFilterLink *inlink, AVFrame *in) { - unsigned x, y; + unsigned x, y, direct = 0; AVFilterContext *ctx = inlink->dst; VignetteContext *s = ctx->priv; - AVFilterLink *outlink = inlink->dst->outputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); + if (av_frame_is_writable(in)) { + direct = 1; + out = in; + } else { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); } - av_frame_copy_props(out, in); if (s->eval_mode == EVAL_MODE_FRAME) update_context(s, inlink, in); @@ -268,6 +273,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } } + if (!direct) + av_frame_free(&in); return ff_filter_frame(outlink, out); } @@ -297,7 +304,7 @@ static int config_props(AVFilterLink *inlink) s->xscale, s->yscale, s->dmax); s->fmap_linesize = FFALIGN(inlink->w, 32); - s->fmap = av_malloc(s->fmap_linesize * inlink->h * sizeof(*s->fmap)); + s->fmap = av_malloc_array(s->fmap_linesize, inlink->h * sizeof(*s->fmap)); if (!s->fmap) return AVERROR(ENOMEM); diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index 9427994f3..70670c3eb 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -325,8 +325,9 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) yadif->cur = yadif->next; yadif->next = frame; - if (!yadif->cur) - return 0; + if (!yadif->cur && + !(yadif->cur = av_frame_clone(yadif->next))) + return AVERROR(ENOMEM); if (checkstride(yadif, yadif->next, yadif->cur)) { av_log(ctx, AV_LOG_VERBOSE, "Reallocating frame due to differing stride\n"); @@ -352,9 +353,8 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) return ff_filter_frame(ctx->outputs[0], yadif->out); } - if (!yadif->prev && - !(yadif->prev = av_frame_clone(yadif->cur))) - return AVERROR(ENOMEM); + if (!yadif->prev) + return 0; yadif->out = ff_get_video_buffer(ctx->outputs[0], link->w, link->h); if (!yadif->out) @@ -400,7 +400,7 @@ static int request_frame(AVFilterLink *link) } else if (ret < 0) { return ret; } - } while (!yadif->cur); + } while (!yadif->prev); return 0; } diff --git a/libavfilter/vf_zoompan.c b/libavfilter/vf_zoompan.c new file mode 100644 index 000000000..8f179e669 --- /dev/null +++ b/libavfilter/vf_zoompan.c @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2013 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/eval.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" +#include "libswscale/swscale.h" + +static const char *const var_names[] = { + "in_w", "iw", + "in_h", "ih", + "out_w", "ow", + "out_h", "oh", + "in", + "on", + "duration", + "pduration", + "time", + "frame", + "zoom", + "pzoom", + "x", "px", + "y", "py", + "a", + "sar", + "dar", + "hsub", + "vsub", + NULL +}; + +enum var_name { + VAR_IN_W, VAR_IW, + VAR_IN_H, VAR_IH, + VAR_OUT_W, VAR_OW, + VAR_OUT_H, VAR_OH, + VAR_IN, + VAR_ON, + VAR_DURATION, + VAR_PDURATION, + VAR_TIME, + VAR_FRAME, + VAR_ZOOM, + VAR_PZOOM, + VAR_X, VAR_PX, + VAR_Y, VAR_PY, + VAR_A, + VAR_SAR, + VAR_DAR, + VAR_HSUB, + VAR_VSUB, + VARS_NB +}; + +typedef struct ZPcontext { + const AVClass *class; + char *zoom_expr_str; + char *x_expr_str; + char *y_expr_str; + char *duration_expr_str; + int w, h; + double x, y; + double prev_zoom; + int prev_nb_frames; + struct SwsContext *sws; + int64_t frame_count; +} ZPContext; + +#define OFFSET(x) offsetof(ZPContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +static const AVOption zoompan_options[] = { + { "zoom", "set the zoom expression", OFFSET(zoom_expr_str), AV_OPT_TYPE_STRING, {.str = "1" }, .flags = FLAGS }, + { "z", "set the zoom expression", OFFSET(zoom_expr_str), AV_OPT_TYPE_STRING, {.str = "1" }, .flags = FLAGS }, + { "x", "set the x expression", OFFSET(x_expr_str), AV_OPT_TYPE_STRING, {.str="0"}, .flags = FLAGS }, + { "y", "set the y expression", OFFSET(y_expr_str), AV_OPT_TYPE_STRING, {.str="0"}, .flags = FLAGS }, + { "d", "set the duration expression", OFFSET(duration_expr_str), AV_OPT_TYPE_STRING, {.str="90"}, .flags = FLAGS }, + { "s", "set the output image size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, .flags = FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(zoompan); + +static av_cold int init(AVFilterContext *ctx) +{ + ZPContext *s = ctx->priv; + + s->prev_zoom = 1; + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + ZPContext *s = ctx->priv; + + outlink->w = s->w; + outlink->h = s->h; + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + ZPContext *s = ctx->priv; + double var_values[VARS_NB], nb_frames, zoom, dx, dy; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(in->format); + AVFrame *out; + int i, k, x, y, w, h, ret = 0; + + var_values[VAR_IN_W] = var_values[VAR_IW] = in->width; + var_values[VAR_IN_H] = var_values[VAR_IH] = in->height; + var_values[VAR_OUT_W] = var_values[VAR_OW] = s->w; + var_values[VAR_OUT_H] = var_values[VAR_OH] = s->h; + var_values[VAR_IN] = inlink->frame_count + 1; + var_values[VAR_ON] = outlink->frame_count + 1; + var_values[VAR_PX] = s->x; + var_values[VAR_PY] = s->y; + var_values[VAR_X] = 0; + var_values[VAR_Y] = 0; + var_values[VAR_PZOOM] = s->prev_zoom; + var_values[VAR_ZOOM] = 1; + var_values[VAR_PDURATION] = s->prev_nb_frames; + var_values[VAR_A] = (double) in->width / in->height; + 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]; + var_values[VAR_HSUB] = 1 << desc->log2_chroma_w; + var_values[VAR_VSUB] = 1 << desc->log2_chroma_h; + + if ((ret = av_expr_parse_and_eval(&nb_frames, s->duration_expr_str, + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) + goto fail; + + var_values[VAR_DURATION] = nb_frames; + for (i = 0; i < nb_frames; i++) { + int px[4]; + int py[4]; + uint8_t *input[4]; + int64_t pts = av_rescale_q(in->pts, inlink->time_base, + outlink->time_base) + s->frame_count; + + var_values[VAR_TIME] = pts * av_q2d(outlink->time_base); + var_values[VAR_FRAME] = i; + var_values[VAR_ON] = outlink->frame_count + 1; + if ((ret = av_expr_parse_and_eval(&zoom, s->zoom_expr_str, + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) + goto fail; + + zoom = av_clipd(zoom, 1, 10); + var_values[VAR_ZOOM] = zoom; + w = in->width * (1.0 / zoom); + h = in->height * (1.0 / zoom); + + if ((ret = av_expr_parse_and_eval(&dx, s->x_expr_str, + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) + goto fail; + x = dx = av_clipd(dx, 0, FFMAX(in->width - w, 0)); + var_values[VAR_X] = dx; + x &= ~((1 << desc->log2_chroma_w) - 1); + + if ((ret = av_expr_parse_and_eval(&dy, s->y_expr_str, + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) + goto fail; + y = dy = av_clipd(dy, 0, FFMAX(in->height - h, 0)); + var_values[VAR_Y] = dy; + y &= ~((1 << desc->log2_chroma_h) - 1); + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + ret = AVERROR(ENOMEM); + goto fail; + } + + px[1] = px[2] = FF_CEIL_RSHIFT(x, desc->log2_chroma_w); + px[0] = px[3] = x; + + py[1] = py[2] = FF_CEIL_RSHIFT(y, desc->log2_chroma_h); + py[0] = py[3] = y; + + s->sws = sws_alloc_context(); + if (!s->sws) { + ret = AVERROR(ENOMEM); + goto fail; + } + + for (k = 0; in->data[k]; k++) + input[k] = in->data[k] + py[k] * in->linesize[k] + px[k]; + + av_opt_set_int(s->sws, "srcw", w, 0); + av_opt_set_int(s->sws, "srch", h, 0); + av_opt_set_int(s->sws, "src_format", in->format, 0); + av_opt_set_int(s->sws, "dstw", outlink->w, 0); + av_opt_set_int(s->sws, "dsth", outlink->h, 0); + av_opt_set_int(s->sws, "dst_format", outlink->format, 0); + av_opt_set_int(s->sws, "sws_flags", SWS_BICUBIC, 0); + + if ((ret = sws_init_context(s->sws, NULL, NULL)) < 0) + goto fail; + + sws_scale(s->sws, (const uint8_t *const *)&input, in->linesize, 0, h, out->data, out->linesize); + + out->pts = pts; + s->frame_count++; + + ret = ff_filter_frame(outlink, out); + if (ret < 0) + break; + + sws_freeContext(s->sws); + s->sws = NULL; + } + + s->x = dx; + s->y = dy; + s->prev_zoom = zoom; + s->prev_nb_frames = nb_frames; + +fail: + sws_freeContext(s->sws); + s->sws = NULL; + av_frame_free(&in); + return ret; +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, + AV_PIX_FMT_YUVA420P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_GRAY8, + AV_PIX_FMT_NONE + }; + + + ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + ZPContext *s = ctx->priv; + + sws_freeContext(s->sws); + s->sws = NULL; +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vf_zoompan = { + .name = "zoompan", + .description = NULL_IF_CONFIG_SMALL("Apply Zoom & Pan effect."), + .priv_size = sizeof(ZPContext), + .priv_class = &zoompan_class, + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .inputs = inputs, + .outputs = outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, +}; diff --git a/libavfilter/vsrc_cellauto.c b/libavfilter/vsrc_cellauto.c index 95eabc14f..5e2df2df0 100644 --- a/libavfilter/vsrc_cellauto.c +++ b/libavfilter/vsrc_cellauto.c @@ -122,7 +122,7 @@ static int init_pattern_from_string(AVFilterContext *ctx) cellauto->h = (double)cellauto->w * M_PHI; } - cellauto->buf = av_mallocz(sizeof(uint8_t) * cellauto->w * cellauto->h); + cellauto->buf = av_mallocz_array(sizeof(uint8_t) * cellauto->w, cellauto->h); if (!cellauto->buf) return AVERROR(ENOMEM); @@ -182,7 +182,7 @@ static av_cold int init(AVFilterContext *ctx) /* fill the first row randomly */ int i; - cellauto->buf = av_mallocz(sizeof(uint8_t) * cellauto->w * cellauto->h); + cellauto->buf = av_mallocz_array(sizeof(uint8_t) * cellauto->w, cellauto->h); if (!cellauto->buf) return AVERROR(ENOMEM); if (cellauto->random_seed == -1) diff --git a/libavfilter/vsrc_mandelbrot.c b/libavfilter/vsrc_mandelbrot.c index 19dddf972..255f2db6a 100644 --- a/libavfilter/vsrc_mandelbrot.c +++ b/libavfilter/vsrc_mandelbrot.c @@ -130,9 +130,9 @@ static av_cold int init(AVFilterContext *ctx) mb->cache_allocated = mb->w * mb->h * 3; mb->cache_used = 0; - mb->point_cache= av_malloc(sizeof(*mb->point_cache)*mb->cache_allocated); - mb-> next_cache= av_malloc(sizeof(*mb-> next_cache)*mb->cache_allocated); - mb-> zyklus = av_malloc(sizeof(*mb->zyklus) * (mb->maxiter+16)); + mb->point_cache= av_malloc_array(mb->cache_allocated, sizeof(*mb->point_cache)); + mb-> next_cache= av_malloc_array(mb->cache_allocated, sizeof(*mb-> next_cache)); + mb-> zyklus = av_malloc_array(mb->maxiter + 16, sizeof(*mb->zyklus)); return 0; } diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index 0ad147419..881444076 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -47,7 +47,7 @@ #include "internal.h" #include "video.h" -typedef struct { +typedef struct TestSourceContext { const AVClass *class; int w, h; unsigned int nb_frame; @@ -488,7 +488,7 @@ static void draw_digit(int digit, uint8_t *dst, int dst_linesize, #define LEFT_BOT_VBAR 16 #define RIGHT_TOP_VBAR 32 #define RIGHT_BOT_VBAR 64 - struct { + struct segments { int x, y, w, h; } segments[] = { { 1, 0, 5, 1 }, /* TOP_HBAR */ diff --git a/libavfilter/x86/vf_pullup.asm b/libavfilter/x86/vf_pullup.asm index 4ce8b9b6f..d3a195511 100644 --- a/libavfilter/x86/vf_pullup.asm +++ b/libavfilter/x86/vf_pullup.asm @@ -56,7 +56,7 @@ cglobal pullup_filter_diff, 3, 5, 8, first, second, size paddd m3, m4 movd eax, m3 psrlq m3, 32 - movd r4, m3 + movd r4d, m3 add eax, r4d RET @@ -135,7 +135,7 @@ cglobal pullup_filter_comb, 3, 5, 8, first, second, size paddd m5, m6 movd eax, m5 psrlq m5, 32 - movd r4, m5 + movd r4d, m5 add eax, r4d RET @@ -172,7 +172,7 @@ cglobal pullup_filter_var, 3, 5, 8, first, second, size paddd m3, m4 movd eax, m3 psrlq m3, 32 - movd r4, m3 + movd r4d, m3 add eax, r4d shl eax, 2 RET diff --git a/libavfilter/x86/vf_yadif.asm b/libavfilter/x86/vf_yadif.asm index 4b80bf3d7..a29620ce5 100644 --- a/libavfilter/x86/vf_yadif.asm +++ b/libavfilter/x86/vf_yadif.asm @@ -39,11 +39,7 @@ SECTION .text pavgb m5, m3 pand m4, [pb_1] psubusb m5, m4 -%if mmsize == 16 - psrldq m5, 1 -%else - psrlq m5, 8 -%endif + RSHIFT m5, 1 punpcklbw m5, m7 mova m4, m2 psubusb m2, m3 @@ -51,13 +47,8 @@ SECTION .text pmaxub m2, m3 mova m3, m2 mova m4, m2 -%if mmsize == 16 - psrldq m3, 1 - psrldq m4, 2 -%else - psrlq m3, 8 - psrlq m4, 16 -%endif + RSHIFT m3, 1 + RSHIFT m4, 2 punpcklbw m2, m7 punpcklbw m3, m7 punpcklbw m4, m7 diff --git a/libavfilter/x86/vf_yadif_init.c b/libavfilter/x86/vf_yadif_init.c index 10ebd230d..1460a642c 100644 --- a/libavfilter/x86/vf_yadif_init.c +++ b/libavfilter/x86/vf_yadif_init.c @@ -60,7 +60,6 @@ void ff_yadif_filter_line_10bit_ssse3(void *dst, void *prev, void *cur, av_cold void ff_yadif_init_x86(YADIFContext *yadif) { -#if HAVE_YASM int cpu_flags = av_get_cpu_flags(); int bit_depth = (!yadif->csp) ? 8 : yadif->csp->comp[0].depth_minus1 + 1; @@ -95,5 +94,4 @@ av_cold void ff_yadif_init_x86(YADIFContext *yadif) if (EXTERNAL_SSSE3(cpu_flags)) yadif->filter_line = ff_yadif_filter_line_ssse3; } -#endif /* HAVE_YASM */ } diff --git a/libavfilter/x86/yadif-10.asm b/libavfilter/x86/yadif-10.asm index 9a6385ac4..8853e0d2c 100644 --- a/libavfilter/x86/yadif-10.asm +++ b/libavfilter/x86/yadif-10.asm @@ -30,17 +30,6 @@ pw_1: times 8 dw 1 SECTION .text -%macro PABS 2 -%if cpuflag(ssse3) - pabsw %1, %1 -%else - pxor %2, %2 - pcmpgtw %2, %1 - pxor %1, %2 - psubw %1, %2 -%endif -%endmacro - %macro PMAXUW 2 %if cpuflag(sse4) pmaxuw %1, %2 @@ -59,24 +48,15 @@ SECTION .text pavgw m5, m3 pand m4, [pw_1] psubusw m5, m4 -%if mmsize == 16 - psrldq m5, 2 -%else - psrlq m5, 16 -%endif + RSHIFT m5, 2 mova m4, m2 psubusw m2, m3 psubusw m3, m4 PMAXUW m2, m3 mova m3, m2 mova m4, m2 -%if mmsize == 16 - psrldq m3, 2 - psrldq m4, 4 -%else - psrlq m3, 16 - psrlq m4, 32 -%endif + RSHIFT m3, 2 + RSHIFT m4, 4 paddw m2, m3 paddw m2, m4 %endmacro @@ -140,13 +120,12 @@ SECTION .text mova [rsp+16], m3 mova [rsp+32], m1 psubw m2, m4 - PABS m2, m4 + ABS1 m2, m4 LOAD m3, [prevq+t1] LOAD m4, [prevq+t0] psubw m3, m0 psubw m4, m1 - PABS m3, m5 - PABS m4, m5 + ABS2 m3, m4, m5, m6 paddw m3, m4 psrlw m2, 1 psrlw m3, 1 @@ -155,8 +134,7 @@ SECTION .text LOAD m4, [nextq+t0] psubw m3, m0 psubw m4, m1 - PABS m3, m5 - PABS m4, m5 + ABS2 m3, m4, m5, m6 paddw m3, m4 psrlw m3, 1 pmaxsw m2, m3 @@ -166,7 +144,7 @@ SECTION .text paddw m0, m0 psubw m0, m1 psrlw m1, 1 - PABS m0, m2 + ABS1 m0, m2 movu m2, [curq+t1-1*2] movu m3, [curq+t0-1*2] @@ -174,13 +152,8 @@ SECTION .text psubusw m2, m3 psubusw m3, m4 PMAXUW m2, m3 -%if mmsize == 16 mova m3, m2 - psrldq m3, 4 -%else - mova m3, m2 - psrlq m3, 32 -%endif + RSHIFT m3, 4 paddw m0, m2 paddw m0, m3 psubw m0, [pw_1] diff --git a/libavfilter/x86/yadif-16.asm b/libavfilter/x86/yadif-16.asm index d6dcd3a40..79d127dfa 100644 --- a/libavfilter/x86/yadif-16.asm +++ b/libavfilter/x86/yadif-16.asm @@ -33,22 +33,6 @@ pd_8000: times 4 dd 0x8000 SECTION .text -%macro PIXSHIFT1 1 -%if cpuflag(sse2) - psrldq %1, 2 -%else - psrlq %1, 16 -%endif -%endmacro - -%macro PIXSHIFT2 1 -%if cpuflag(sse2) - psrldq %1, 4 -%else - psrlq %1, 32 -%endif -%endmacro - %macro PABS 2 %if cpuflag(ssse3) pabsd %1, %1 @@ -112,11 +96,7 @@ SECTION .text pavgw m5, m3 pand m4, [pw_1] psubusw m5, m4 -%if mmsize == 16 - psrldq m5, 2 -%else - psrlq m5, 16 -%endif + RSHIFT m5, 2 punpcklwd m5, m7 mova m4, m2 psubusw m2, m3 @@ -124,13 +104,8 @@ SECTION .text PMAXUW m2, m3 mova m3, m2 mova m4, m2 -%if mmsize == 16 - psrldq m3, 2 - psrldq m4, 4 -%else - psrlq m3, 16 - psrlq m4, 32 -%endif + RSHIFT m3, 2 + RSHIFT m4, 4 punpcklwd m2, m7 punpcklwd m3, m7 punpcklwd m4, m7 @@ -164,7 +139,7 @@ SECTION .text ; This version of CHECK2 has 3 fewer instructions on sets older than SSE4 but I ; am not sure whether it is any faster. A rewrite or refactor of the filter -; code should make it possible to eliminate the move intruction at the end. It +; code should make it possible to eliminate the move instruction at the end. It ; exists to satisfy the expectation that the "score" values are in m1. ; %macro CHECK2 0 @@ -234,13 +209,8 @@ SECTION .text psubusw m2, m3 psubusw m3, m4 PMAXUW m2, m3 -%if mmsize == 16 mova m3, m2 - psrldq m3, 4 -%else - mova m3, m2 - psrlq m3, 32 -%endif + RSHIFT m3, 4 punpcklwd m2, m7 punpcklwd m3, m7 paddd m0, m2 diff --git a/libavformat/4xm.c b/libavformat/4xm.c index 23279c42f..0b4ddfabf 100644 --- a/libavformat/4xm.c +++ b/libavformat/4xm.c @@ -110,8 +110,11 @@ static int parse_vtrk(AVFormatContext *s, st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = AV_CODEC_ID_4XM; + + st->codec->extradata = av_mallocz(4 + FF_INPUT_BUFFER_PADDING_SIZE); + if (!st->codec->extradata) + return AVERROR(ENOMEM); st->codec->extradata_size = 4; - st->codec->extradata = av_malloc(4); AV_WL32(st->codec->extradata, AV_RL32(buf + 16)); st->codec->width = AV_RL32(buf + 36); st->codec->height = AV_RL32(buf + 40); diff --git a/libavformat/Makefile b/libavformat/Makefile index 09045e5bd..9017e06f7 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -1,7 +1,6 @@ include $(SUBDIR)../config.mak NAME = avformat -FFLIBS = avcodec avutil HEADERS = avformat.h \ avio.h \ @@ -11,6 +10,7 @@ OBJS = allformats.o \ avio.o \ aviobuf.o \ cutils.o \ + dump.o \ format.o \ id3v1.o \ id3v2.o \ @@ -84,7 +84,7 @@ OBJS-$(CONFIG_AST_MUXER) += ast.o astenc.o OBJS-$(CONFIG_AU_DEMUXER) += au.o pcm.o OBJS-$(CONFIG_AU_MUXER) += au.o rawenc.o OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o -OBJS-$(CONFIG_AVI_MUXER) += avienc.o avlanguage.o +OBJS-$(CONFIG_AVI_MUXER) += avienc.o mpegtsenc.o avlanguage.o OBJS-$(CONFIG_AVISYNTH) += avisynth.o OBJS-$(CONFIG_AVM2_MUXER) += swfenc.o swf.o OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o @@ -100,23 +100,25 @@ OBJS-$(CONFIG_BOA_DEMUXER) += boadec.o OBJS-$(CONFIG_BRSTM_DEMUXER) += brstm.o OBJS-$(CONFIG_C93_DEMUXER) += c93.o vocdec.o voc.o OBJS-$(CONFIG_CAF_DEMUXER) += cafdec.o caf.o mov.o mov_chan.o \ - isom.o + isom.o replaygain.o OBJS-$(CONFIG_CAF_MUXER) += cafenc.o caf.o riff.o isom.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_CINE_DEMUXER) += cinedec.o OBJS-$(CONFIG_CONCAT_DEMUXER) += concatdec.o OBJS-$(CONFIG_CRC_MUXER) += crcenc.o OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o OBJS-$(CONFIG_DATA_MUXER) += rawdec.o -OBJS-$(CONFIG_DAUD_DEMUXER) += daud.o -OBJS-$(CONFIG_DAUD_MUXER) += daud.o +OBJS-$(CONFIG_DAUD_DEMUXER) += dauddec.o +OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o OBJS-$(CONFIG_DFA_DEMUXER) += dfa.o OBJS-$(CONFIG_DIRAC_DEMUXER) += diracdec.o rawdec.o OBJS-$(CONFIG_DIRAC_MUXER) += rawenc.o OBJS-$(CONFIG_DNXHD_DEMUXER) += dnxhddec.o rawdec.o OBJS-$(CONFIG_DNXHD_MUXER) += rawenc.o +OBJS-$(CONFIG_DSF_DEMUXER) += dsfdec.o OBJS-$(CONFIG_DSICIN_DEMUXER) += dsicin.o OBJS-$(CONFIG_DTSHD_DEMUXER) += dtshddec.o OBJS-$(CONFIG_DTS_DEMUXER) += dtsdec.o rawdec.o @@ -138,11 +140,13 @@ OBJS-$(CONFIG_FILMSTRIP_MUXER) += filmstripenc.o OBJS-$(CONFIG_FLAC_DEMUXER) += flacdec.o rawdec.o \ flac_picture.o \ oggparsevorbis.o \ + replaygain.o \ vorbiscomment.o OBJS-$(CONFIG_FLAC_MUXER) += flacenc.o flacenc_header.o \ vorbiscomment.o OBJS-$(CONFIG_FLIC_DEMUXER) += flic.o OBJS-$(CONFIG_FLV_DEMUXER) += flvdec.o +OBJS-$(CONFIG_LIVE_FLV_DEMUXER) += flvdec.o OBJS-$(CONFIG_FLV_MUXER) += flvenc.o avc.o OBJS-$(CONFIG_FOURXM_DEMUXER) += 4xm.o OBJS-$(CONFIG_FRAMECRC_MUXER) += framecrcenc.o framehash.o @@ -181,6 +185,17 @@ OBJS-$(CONFIG_IMAGE2_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE2_MUXER) += img2enc.o img2.o OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE2PIPE_MUXER) += img2enc.o img2.o +OBJS-$(CONFIG_IMAGE2_ALIAS_PIX_DEMUXER) += img2_alias_pix.o +OBJS-$(CONFIG_IMAGE2_BRENDER_PIX_DEMUXER) += img2_brender_pix.o +OBJS-$(CONFIG_IMAGE_BMP_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_DPX_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_EXR_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_J2K_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_PICTOR_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_PNG_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_SGI_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_SUNRAST_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_TIFF_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_INGENIENT_DEMUXER) += ingenientdec.o rawdec.o OBJS-$(CONFIG_IPMOVIE_DEMUXER) += ipmovie.o OBJS-$(CONFIG_IRCAM_DEMUXER) += ircamdec.o ircam.o pcm.o @@ -196,15 +211,20 @@ OBJS-$(CONFIG_LATM_DEMUXER) += rawdec.o OBJS-$(CONFIG_LATM_MUXER) += latmenc.o rawenc.o OBJS-$(CONFIG_LMLM4_DEMUXER) += lmlm4.o OBJS-$(CONFIG_LOAS_DEMUXER) += loasdec.o rawdec.o +OBJS-$(CONFIG_LRC_DEMUXER) += lrcdec.o lrc.o subtitles.o +OBJS-$(CONFIG_LRC_MUXER) += lrcenc.o lrc.o OBJS-$(CONFIG_LVF_DEMUXER) += lvfdec.o 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 + isom.o rmsipr.o flac_picture.o \ + oggparsevorbis.o vorbiscomment.o \ + flac_picture.o replaygain.o OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \ isom.o avc.o hevc.o \ - flacenc_header.o avlanguage.o wv.o + flacenc_header.o avlanguage.o vorbiscomment.o wv.o \ + webmdashenc.o OBJS-$(CONFIG_MD5_MUXER) += md5enc.o OBJS-$(CONFIG_MGSTS_DEMUXER) += mgsts.o OBJS-$(CONFIG_MICRODVD_DEMUXER) += microdvddec.o subtitles.o @@ -213,14 +233,15 @@ OBJS-$(CONFIG_MJPEG_DEMUXER) += rawdec.o OBJS-$(CONFIG_MJPEG_MUXER) += rawenc.o OBJS-$(CONFIG_MLP_DEMUXER) += rawdec.o OBJS-$(CONFIG_MLP_MUXER) += rawenc.o +OBJS-$(CONFIG_MLV_DEMUXER) += mlvdec.o riffdec.o OBJS-$(CONFIG_MM_DEMUXER) += mm.o OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o OBJS-$(CONFIG_MMF_MUXER) += mmf.o rawenc.o -OBJS-$(CONFIG_MOV_DEMUXER) += mov.o isom.o mov_chan.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 \ movenchint.o mov_chan.o rtp.o OBJS-$(CONFIG_MP2_MUXER) += mp3enc.o rawenc.o id3v2enc.o -OBJS-$(CONFIG_MP3_DEMUXER) += mp3dec.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 @@ -240,8 +261,8 @@ OBJS-$(CONFIG_MPL2_DEMUXER) += mpl2dec.o subtitles.o OBJS-$(CONFIG_MPSUB_DEMUXER) += mpsubdec.o subtitles.o OBJS-$(CONFIG_MSNWC_TCP_DEMUXER) += msnwc_tcp.o OBJS-$(CONFIG_MTV_DEMUXER) += mtv.o -OBJS-$(CONFIG_MVI_DEMUXER) += mvi.o OBJS-$(CONFIG_MV_DEMUXER) += mvdec.o +OBJS-$(CONFIG_MVI_DEMUXER) += mvi.o OBJS-$(CONFIG_MXF_DEMUXER) += mxfdec.o mxf.o OBJS-$(CONFIG_MXF_MUXER) += mxfenc.o mxf.o audiointerleave.o OBJS-$(CONFIG_MXG_DEMUXER) += mxg.o @@ -263,8 +284,11 @@ OBJS-$(CONFIG_OGG_DEMUXER) += oggdec.o \ oggparsetheora.o \ oggparsevorbis.o \ oggparsevp8.o \ + replaygain.o \ vorbiscomment.o \ flac_picture.o +OBJS-$(CONFIG_OGA_MUXER) += oggenc.o \ + vorbiscomment.o OBJS-$(CONFIG_OGG_MUXER) += oggenc.o \ vorbiscomment.o OBJS-$(CONFIG_OMA_DEMUXER) += omadec.o pcm.o oma.o @@ -407,15 +431,23 @@ 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 \ - flacenc_header.o avlanguage.o wv.o + isom.o avc.o hevc.o \ + flacenc_header.o avlanguage.o \ + wv.o vorbiscomment.o \ + webmdashenc.o +OBJS-$(CONFIG_WEBM_DASH_MANIFEST_DEMUXER)+= matroskadec.o matroska.o \ + isom.o rmsipr.o flac_picture.o \ + oggparsevorbis.o vorbiscomment.o \ + flac_picture.o replaygain.o +OBJS-$(CONFIG_WEBM_DASH_MANIFEST_MUXER) += webmdashenc.o matroska.o OBJS-$(CONFIG_WEBVTT_DEMUXER) += webvttdec.o subtitles.o OBJS-$(CONFIG_WEBVTT_MUXER) += webvttenc.o OBJS-$(CONFIG_WSAUD_DEMUXER) += westwood_aud.o OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood_vqa.o OBJS-$(CONFIG_WTV_DEMUXER) += wtvdec.o wtv_common.o asfdec.o asf.o asfcrypt.o \ avlanguage.o mpegts.o isom.o -OBJS-$(CONFIG_WTV_MUXER) += wtvenc.o wtv_common.o +OBJS-$(CONFIG_WTV_MUXER) += wtvenc.o wtv_common.o \ + mpegtsenc.o asf.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 @@ -423,8 +455,8 @@ OBJS-$(CONFIG_XBIN_DEMUXER) += bintext.o sauce.o OBJS-$(CONFIG_XMV_DEMUXER) += xmv.o OBJS-$(CONFIG_XWMA_DEMUXER) += xwma.o OBJS-$(CONFIG_YOP_DEMUXER) += yop.o -OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpeg.o -OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER) += yuv4mpeg.o +OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpegenc.o +OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER) += yuv4mpegdec.o # external libraries OBJS-$(CONFIG_LIBGME_DEMUXER) += libgme.o @@ -434,6 +466,7 @@ OBJS-$(CONFIG_LIBNUT_MUXER) += libnut.o OBJS-$(CONFIG_LIBQUVI_DEMUXER) += libquvi.o OBJS-$(CONFIG_LIBRTMP) += librtmp.o OBJS-$(CONFIG_LIBSSH_PROTOCOL) += libssh.o +OBJS-$(CONFIG_LIBSMBCLIENT_PROTOCOL) += libsmbclient.o # protocols I/O OBJS-$(CONFIG_APPLEHTTP_PROTOCOL) += hlsproto.o @@ -464,6 +497,7 @@ OBJS-$(CONFIG_RTMPTS_PROTOCOL) += rtmpproto.o rtmppkt.o OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o OBJS-$(CONFIG_SCTP_PROTOCOL) += sctp.o OBJS-$(CONFIG_SRTP_PROTOCOL) += srtpproto.o srtp.o +OBJS-$(CONFIG_SUBFILE_PROTOCOL) += subfile.o OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o OBJS-$(CONFIG_TLS_PROTOCOL) += tls.o OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o diff --git a/libavformat/a64.c b/libavformat/a64.c index 786c75cc9..802235f40 100644 --- a/libavformat/a64.c +++ b/libavformat/a64.c @@ -24,7 +24,7 @@ #include "avformat.h" #include "rawenc.h" -static int a64_write_header(struct AVFormatContext *s) +static int a64_write_header(AVFormatContext *s) { AVCodecContext *avctx = s->streams[0]->codec; uint8_t header[5] = { @@ -34,6 +34,12 @@ static int a64_write_header(struct AVFormatContext *s) 0x00, //charset_lifetime (multi only) 0x00 //fps in 50/fps; }; + + if (avctx->extradata_size < 4) { + av_log(s, AV_LOG_ERROR, "Missing extradata\n"); + return AVERROR(EINVAL); + } + switch (avctx->codec->id) { case AV_CODEC_ID_A64_MULTI: header[2] = 0x00; diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c index d93e75ec5..05cbaf78a 100644 --- a/libavformat/aacdec.c +++ b/libavformat/aacdec.c @@ -38,28 +38,42 @@ static int adts_aac_probe(AVProbeData *p) buf = buf0; - for(; buf < end; buf= buf2+1) { + for (; buf < end; buf = buf2 + 1) { buf2 = buf; - for(frames = 0; buf2 < end; frames++) { + for (frames = 0; buf2 < end; frames++) { uint32_t header = AV_RB16(buf2); - if((header&0xFFF6) != 0xFFF0) + if ((header & 0xFFF6) != 0xFFF0) { + if (buf != buf0) { + // Found something that isn't an ADTS header, starting + // from a position other than the start of the buffer. + // Discard the count we've accumulated so far since it + // probably was a false positive. + frames = 0; + } break; + } fsize = (AV_RB32(buf2 + 3) >> 13) & 0x1FFF; - if(fsize < 7) + if (fsize < 7) break; fsize = FFMIN(fsize, end - buf2); buf2 += fsize; } max_frames = FFMAX(max_frames, frames); - if(buf == buf0) - first_frames= frames; + if (buf == buf0) + first_frames = frames; } - if (first_frames>=3) return AVPROBE_SCORE_EXTENSION + 1; - else if(max_frames>500)return AVPROBE_SCORE_EXTENSION; - else if(max_frames>=3) return AVPROBE_SCORE_EXTENSION / 2; - else if(max_frames>=1) return 1; - else return 0; + + if (first_frames >= 3) + return AVPROBE_SCORE_EXTENSION + 1; + else if (max_frames > 100) + return AVPROBE_SCORE_EXTENSION; + else if (max_frames >= 3) + return AVPROBE_SCORE_EXTENSION / 2; + else if (max_frames >= 1) + return 1; + else + return 0; } static int adts_aac_read_header(AVFormatContext *s) @@ -71,8 +85,8 @@ static int adts_aac_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = s->iformat->raw_codec_id; - st->need_parsing = AVSTREAM_PARSE_FULL_RAW; + st->codec->codec_id = s->iformat->raw_codec_id; + st->need_parsing = AVSTREAM_PARSE_FULL_RAW; ff_id3v1_read(s); if (s->pb->seekable && @@ -82,19 +96,19 @@ static int adts_aac_read_header(AVFormatContext *s) avio_seek(s->pb, cur, SEEK_SET); } - //LCM of all possible ADTS sample rates + // LCM of all possible ADTS sample rates avpriv_set_pts_info(st, 64, 1, 28224000); return 0; } AVInputFormat ff_aac_demuxer = { - .name = "aac", - .long_name = NULL_IF_CONFIG_SMALL("raw ADTS AAC (Advanced Audio Coding)"), - .read_probe = adts_aac_probe, - .read_header = adts_aac_read_header, - .read_packet = ff_raw_read_partial_packet, - .flags = AVFMT_GENERIC_INDEX, - .extensions = "aac", - .raw_codec_id = AV_CODEC_ID_AAC, + .name = "aac", + .long_name = NULL_IF_CONFIG_SMALL("raw ADTS AAC (Advanced Audio Coding)"), + .read_probe = adts_aac_probe, + .read_header = adts_aac_read_header, + .read_packet = ff_raw_read_partial_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "aac", + .raw_codec_id = AV_CODEC_ID_AAC, }; diff --git a/libavformat/adtsenc.c b/libavformat/adtsenc.c index f25f96612..58a7f2d89 100644 --- a/libavformat/adtsenc.c +++ b/libavformat/adtsenc.c @@ -202,4 +202,5 @@ AVOutputFormat ff_adts_muxer = { .write_packet = adts_write_packet, .write_trailer = adts_write_trailer, .priv_class = &adts_muxer_class, + .flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/adxdec.c b/libavformat/adxdec.c index fe22c3ae6..ddaa20117 100644 --- a/libavformat/adxdec.c +++ b/libavformat/adxdec.c @@ -24,7 +24,6 @@ */ #include "libavutil/intreadwrite.h" -#include "libavcodec/adx.h" #include "avformat.h" #include "internal.h" @@ -66,7 +65,6 @@ static int adx_read_header(AVFormatContext *s) { ADXDemuxerContext *c = s->priv_data; AVCodecContext *avctx; - int ret; AVStream *st = avformat_new_stream(s, NULL); if (!st) @@ -81,11 +79,11 @@ static int adx_read_header(AVFormatContext *s) if (ff_get_extradata(avctx, s->pb, c->header_size) < 0) return AVERROR(ENOMEM); - ret = avpriv_adx_decode_header(avctx, avctx->extradata, - avctx->extradata_size, &c->header_size, - NULL); - if (ret) - return ret; + if (avctx->extradata_size < 12) { + av_log(s, AV_LOG_ERROR, "Invalid extradata size.\n"); + return AVERROR_INVALIDDATA; + } + avctx->sample_rate = AV_RB32(avctx->extradata + 8); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = s->iformat->raw_codec_id; diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 0e70b6e42..00de81777 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -98,6 +98,7 @@ void av_register_all(void) REGISTER_MUXDEMUX(CAVSVIDEO, cavsvideo); REGISTER_DEMUXER (CDG, cdg); REGISTER_DEMUXER (CDXL, cdxl); + REGISTER_DEMUXER (CINE, cine); REGISTER_DEMUXER (CONCAT, concat); REGISTER_MUXER (CRC, crc); REGISTER_MUXDEMUX(DATA, data); @@ -105,6 +106,7 @@ void av_register_all(void) REGISTER_DEMUXER (DFA, dfa); REGISTER_MUXDEMUX(DIRAC, dirac); REGISTER_MUXDEMUX(DNXHD, dnxhd); + REGISTER_DEMUXER (DSF, dsf); REGISTER_DEMUXER (DSICIN, dsicin); REGISTER_MUXDEMUX(DTS, dts); REGISTER_DEMUXER (DTSHD, dtshd); @@ -121,6 +123,7 @@ void av_register_all(void) REGISTER_MUXDEMUX(FLAC, flac); REGISTER_DEMUXER (FLIC, flic); REGISTER_MUXDEMUX(FLV, flv); + REGISTER_DEMUXER (LIVE_FLV, live_flv); REGISTER_DEMUXER (FOURXM, fourxm); REGISTER_MUXER (FRAMECRC, framecrc); REGISTER_MUXER (FRAMEMD5, framemd5); @@ -145,6 +148,8 @@ void av_register_all(void) REGISTER_MUXDEMUX(ILBC, ilbc); REGISTER_MUXDEMUX(IMAGE2, image2); REGISTER_MUXDEMUX(IMAGE2PIPE, image2pipe); + REGISTER_DEMUXER (IMAGE2_ALIAS_PIX, image2_alias_pix); + REGISTER_DEMUXER (IMAGE2_BRENDER_PIX, image2_brender_pix); REGISTER_DEMUXER (INGENIENT, ingenient); REGISTER_DEMUXER (IPMOVIE, ipmovie); REGISTER_MUXER (IPOD, ipod); @@ -158,6 +163,7 @@ void av_register_all(void) REGISTER_MUXDEMUX(LATM, latm); REGISTER_DEMUXER (LMLM4, lmlm4); REGISTER_DEMUXER (LOAS, loas); + REGISTER_MUXDEMUX(LRC, lrc); REGISTER_DEMUXER (LVF, lvf); REGISTER_DEMUXER (LXF, lxf); REGISTER_MUXDEMUX(M4V, m4v); @@ -168,6 +174,7 @@ void av_register_all(void) REGISTER_MUXDEMUX(MICRODVD, microdvd); REGISTER_MUXDEMUX(MJPEG, mjpeg); REGISTER_MUXDEMUX(MLP, mlp); + REGISTER_DEMUXER (MLV, mlv); REGISTER_DEMUXER (MM, mm); REGISTER_MUXDEMUX(MMF, mmf); REGISTER_MUXDEMUX(MOV, mov); @@ -203,6 +210,7 @@ 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); @@ -259,6 +267,7 @@ void av_register_all(void) REGISTER_MUXER (SEGMENT, stream_segment); REGISTER_DEMUXER (SHORTEN, shorten); REGISTER_DEMUXER (SIFF, siff); + REGISTER_DEMUXER (SLN, sln); REGISTER_DEMUXER (SMACKER, smacker); REGISTER_MUXDEMUX(SMJPEG, smjpeg); REGISTER_MUXER (SMOOTHSTREAMING, smoothstreaming); @@ -298,6 +307,7 @@ void av_register_all(void) REGISTER_MUXDEMUX(WAV, wav); REGISTER_DEMUXER (WC3, wc3); REGISTER_MUXER (WEBM, webm); + REGISTER_MUXDEMUX(WEBM_DASH_MANIFEST, webm_dash_manifest); REGISTER_MUXDEMUX(WEBVTT, webvtt); REGISTER_DEMUXER (WSAUD, wsaud); REGISTER_DEMUXER (WSVQA, wsvqa); @@ -310,6 +320,18 @@ void av_register_all(void) REGISTER_DEMUXER (YOP, yop); REGISTER_MUXDEMUX(YUV4MPEGPIPE, yuv4mpegpipe); + /* image demuxers */ + REGISTER_DEMUXER (IMAGE_BMP_PIPE, image_bmp_pipe); + REGISTER_DEMUXER (IMAGE_DPX_PIPE, image_dpx_pipe); + REGISTER_DEMUXER (IMAGE_EXR_PIPE, image_exr_pipe); + REGISTER_DEMUXER (IMAGE_J2K_PIPE, image_j2k_pipe); + REGISTER_DEMUXER (IMAGE_PICTOR_PIPE, image_pictor_pipe); + REGISTER_DEMUXER (IMAGE_PNG_PIPE, image_png_pipe); + REGISTER_DEMUXER (IMAGE_SGI_PIPE, image_sgi_pipe); + REGISTER_DEMUXER (IMAGE_SUNRAST_PIPE, image_sunrast_pipe); + REGISTER_DEMUXER (IMAGE_TIFF_PIPE, image_tiff_pipe); + + /* protocols */ REGISTER_PROTOCOL(BLURAY, bluray); REGISTER_PROTOCOL(CACHE, cache); @@ -338,6 +360,7 @@ void av_register_all(void) REGISTER_PROTOCOL(RTP, rtp); REGISTER_PROTOCOL(SCTP, sctp); REGISTER_PROTOCOL(SRTP, srtp); + REGISTER_PROTOCOL(SUBFILE, subfile); REGISTER_PROTOCOL(TCP, tcp); REGISTER_PROTOCOL(TLS, tls); REGISTER_PROTOCOL(UDP, udp); @@ -354,4 +377,5 @@ void av_register_all(void) REGISTER_PROTOCOL(LIBRTMPT, librtmpt); REGISTER_PROTOCOL(LIBRTMPTE, librtmpte); REGISTER_PROTOCOL(LIBSSH, libssh); + REGISTER_PROTOCOL(LIBSMBCLIENT, libsmbclient); } diff --git a/libavformat/amr.c b/libavformat/amr.c index db9bb4e59..24d5ce0d7 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -26,11 +26,15 @@ Only mono files are supported. */ -#include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "avformat.h" #include "internal.h" +typedef struct { + uint64_t cumulated_size; + uint64_t block_count; +} AMRContext; + static const char AMR_header[] = "#!AMR\n"; static const char AMRWB_header[] = "#!AMR-WB\n"; @@ -111,12 +115,13 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt) AVCodecContext *enc = s->streams[0]->codec; int read, size = 0, toc, mode; int64_t pos = avio_tell(s->pb); + AMRContext *amr = s->priv_data; if (url_feof(s->pb)) { return AVERROR(EIO); } - // FIXME this is wrong, this should rather be in a AVParset + // FIXME this is wrong, this should rather be in a AVParser toc = avio_r8(s->pb); mode = (toc >> 3) & 0x0F; @@ -137,8 +142,11 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt) if (!size || av_new_packet(pkt, size)) return AVERROR(EIO); - /* Both AMR formats have 50 frames per second */ - s->streams[0]->codec->bit_rate = size*8*50; + if (amr->cumulated_size < UINT64_MAX - size) { + amr->cumulated_size += size; + /* Both AMR formats have 50 frames per second */ + s->streams[0]->codec->bit_rate = amr->cumulated_size / ++amr->block_count * 8 * 50; + } pkt->stream_index = 0; pkt->pos = pos; @@ -158,6 +166,7 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt) AVInputFormat ff_amr_demuxer = { .name = "amr", .long_name = NULL_IF_CONFIG_SMALL("3GPP AMR"), + .priv_data_size = sizeof(AMRContext), .read_probe = amr_probe, .read_header = amr_read_header, .read_packet = amr_read_packet, @@ -175,5 +184,6 @@ AVOutputFormat ff_amr_muxer = { .video_codec = AV_CODEC_ID_NONE, .write_header = amr_write_header, .write_packet = amr_write_packet, + .flags = AVFMT_NOTIMESTAMPS, }; #endif diff --git a/libavformat/ape.c b/libavformat/ape.c index b677ba959..d5a786a19 100644 --- a/libavformat/ape.c +++ b/libavformat/ape.c @@ -264,7 +264,7 @@ static int ape_read_header(AVFormatContext * s) } if (ape->seektablelength / sizeof(*ape->seektable) < ape->totalframes) { av_log(s, AV_LOG_ERROR, - "Number of seek entries is less than number of frames: %zu vs. %"PRIu32"\n", + "Number of seek entries is less than number of frames: %"SIZE_SPECIFIER" vs. %"PRIu32"\n", ape->seektablelength / sizeof(*ape->seektable), ape->totalframes); return AVERROR_INVALIDDATA; } diff --git a/libavformat/apetag.c b/libavformat/apetag.c index 6e59bc7de..7d2f0b322 100644 --- a/libavformat/apetag.c +++ b/libavformat/apetag.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "avformat.h" @@ -139,14 +141,14 @@ int64_t ff_ape_parse_tag(AVFormatContext *s) } if (tag_bytes > file_size - APE_TAG_FOOTER_BYTES) { - av_log(s, AV_LOG_ERROR, "Invalid tag size %u.\n", tag_bytes); + 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) { - av_log(s, AV_LOG_ERROR, "Too many tag fields (%d)\n", fields); + av_log(s, AV_LOG_ERROR, "Too many tag fields (%"PRIu32")\n", fields); return 0; } diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c index 9bbc70467..978b9562a 100644 --- a/libavformat/asfdec.c +++ b/libavformat/asfdec.c @@ -19,6 +19,8 @@ * 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" @@ -67,6 +69,7 @@ typedef struct { unsigned int packet_frag_offset; unsigned int packet_frag_size; int64_t packet_frag_timestamp; + int ts_is_pts; int packet_multi_size; int packet_time_delta; int packet_time_start; @@ -500,6 +503,8 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) } if (st->codec->codec_id == AV_CODEC_ID_H264) st->need_parsing = AVSTREAM_PARSE_FULL_ONCE; + if (st->codec->codec_id == AV_CODEC_ID_MPEG4) + st->need_parsing = AVSTREAM_PARSE_FULL_ONCE; } pos2 = avio_tell(pb); avio_skip(pb, size - (pos2 - pos1 + 24)); @@ -944,13 +949,13 @@ static int asf_get_packet(AVFormatContext *s, AVIOContext *pb) // the following checks prevent overflows and infinite loops if (!packet_length || packet_length >= (1U << 29)) { av_log(s, AV_LOG_ERROR, - "invalid packet_length %d at:%"PRId64"\n", + "invalid packet_length %"PRIu32" at:%"PRId64"\n", packet_length, avio_tell(pb)); return AVERROR_INVALIDDATA; } if (padsize >= packet_length) { av_log(s, AV_LOG_ERROR, - "invalid padsize %d at:%"PRId64"\n", padsize, avio_tell(pb)); + "invalid padsize %"PRIu32" at:%"PRId64"\n", padsize, avio_tell(pb)); return AVERROR_INVALIDDATA; } @@ -969,7 +974,7 @@ static int asf_get_packet(AVFormatContext *s, AVIOContext *pb) if (rsize > packet_length - padsize) { asf->packet_size_left = 0; av_log(s, AV_LOG_ERROR, - "invalid packet header length %d for pktlen %d-%d at %"PRId64"\n", + "invalid packet header length %d for pktlen %"PRIu32"-%"PRIu32" at %"PRId64"\n", rsize, packet_length, padsize, avio_tell(pb)); return AVERROR_INVALIDDATA; } @@ -1049,6 +1054,7 @@ static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb) ts1 = avio_rl64(pb); if (ts0!= -1) asf->packet_frag_timestamp = ts0/10000; else asf->packet_frag_timestamp = AV_NOPTS_VALUE; + asf->ts_is_pts = 1; break; case 0x5B: case 0xB7: @@ -1122,8 +1128,8 @@ static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt) int ret; if (url_feof(pb)) return AVERROR_EOF; - - if (asf->packet_size_left < FRAME_HEADER_SIZE) { + if (asf->packet_size_left < FRAME_HEADER_SIZE || + asf->packet_segments < 1 && asf->packet_time_start == 0) { int ret = asf->packet_size_left + asf->packet_padsize; assert(ret >= 0); @@ -1199,7 +1205,10 @@ static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt) /* new packet */ av_new_packet(&asf_st->pkt, asf_st->packet_obj_size); asf_st->seq = asf->packet_seq; - asf_st->pkt.dts = asf->packet_frag_timestamp - asf->hdr.preroll; + if (asf->ts_is_pts) { + asf_st->pkt.pts = asf->packet_frag_timestamp - asf->hdr.preroll; + } else + 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; asf_st->pkt_clean = 0; diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c index 8f7297734..cccbf858c 100644 --- a/libavformat/asfenc.c +++ b/libavformat/asfenc.c @@ -34,6 +34,7 @@ #define ASF_INDEXED_INTERVAL 10000000 #define ASF_INDEX_BLOCK (1<<9) +#define ASF_PAYLOADS_PER_PACKET 63 #define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2 #define ASF_PACKET_ERROR_CORRECTION_FLAGS \ @@ -352,7 +353,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, AVIOContext *pb = s->pb; AVDictionaryEntry *tags[5]; int header_size, n, extra_size, extra_size2, wav_extra_size, file_time; - int has_title; + int has_title, has_aspect_ratio = 0; int metadata_count; AVCodecContext *enc; int64_t header_offset, cur_pos, hpos; @@ -378,6 +379,10 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */ bit_rate += enc->bit_rate; + if ( enc->codec_type == AVMEDIA_TYPE_VIDEO + && enc->sample_aspect_ratio.num > 0 + && enc->sample_aspect_ratio.den > 0) + has_aspect_ratio++; } if (asf->is_streamed) { @@ -404,14 +409,46 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, avio_wl32(pb, (asf->is_streamed || !pb->seekable) ? 3 : 2); /* ??? */ avio_wl32(pb, s->packet_size); /* packet size */ avio_wl32(pb, s->packet_size); /* packet size */ - avio_wl32(pb, bit_rate); /* Nominal data rate in bps */ + avio_wl32(pb, bit_rate ? bit_rate : -1); /* Maximum data rate in bps */ end_header(pb, hpos); /* unknown headers */ hpos = put_header(pb, &ff_asf_head1_guid); ff_put_guid(pb, &ff_asf_head2_guid); - avio_wl32(pb, 6); - avio_wl16(pb, 0); + avio_wl16(pb, 6); + if (has_aspect_ratio) { + int64_t hpos2; + avio_wl32(pb, 26 + has_aspect_ratio * 84); + hpos2 = put_header(pb, &ff_asf_metadata_header); + avio_wl16(pb, 2 * has_aspect_ratio); + for (n = 0; n < s->nb_streams; n++) { + enc = s->streams[n]->codec; + if ( enc->codec_type == AVMEDIA_TYPE_VIDEO + && enc->sample_aspect_ratio.num > 0 + && enc->sample_aspect_ratio.den > 0) { + AVRational sar = enc->sample_aspect_ratio; + avio_wl16(pb, 0); + // the stream number is set like this below + avio_wl16(pb, n + 1); + avio_wl16(pb, 26); // name_len + avio_wl16(pb, 3); // value_type + avio_wl32(pb, 4); // value_len + avio_put_str16le(pb, "AspectRatioX"); + avio_wl32(pb, sar.num); + avio_wl16(pb, 0); + // the stream number is set like this below + avio_wl16(pb, n + 1); + avio_wl16(pb, 26); // name_len + avio_wl16(pb, 3); // value_type + avio_wl32(pb, 4); // value_len + avio_put_str16le(pb, "AspectRatioY"); + avio_wl32(pb, sar.den); + } + } + end_header(pb, hpos2); + } else { + avio_wl32(pb, 0); + } end_header(pb, hpos); /* title and other infos */ @@ -491,7 +528,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { /* WAVEFORMATEX header */ - int wavsize = ff_put_wav_header(pb, enc); + int wavsize = ff_put_wav_header(pb, enc, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX); if (wavsize < 0) return -1; @@ -530,14 +567,11 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, ff_put_guid(pb, &ff_asf_codec_comment1_header); avio_wl32(pb, s->nb_streams); for (n = 0; n < s->nb_streams; n++) { - AVCodec *p; + const AVCodecDescriptor *codec_desc; const char *desc; - int len; - uint8_t *buf; - AVIOContext *dyn_buf; - enc = s->streams[n]->codec; - p = avcodec_find_encoder(enc->codec_id); + enc = s->streams[n]->codec; + codec_desc = avcodec_descriptor_get(enc->codec_id); if (enc->codec_type == AVMEDIA_TYPE_AUDIO) avio_wl16(pb, 2); @@ -549,17 +583,24 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, if (enc->codec_id == AV_CODEC_ID_WMAV2) desc = "Windows Media Audio V8"; else - desc = p ? p->name : enc->codec_name; + desc = codec_desc ? codec_desc->name : NULL; - if (avio_open_dyn_buf(&dyn_buf) < 0) - return AVERROR(ENOMEM); + if (desc) { + AVIOContext *dyn_buf; + uint8_t *buf; + int len; - avio_put_str16le(dyn_buf, desc); - len = avio_close_dyn_buf(dyn_buf, &buf); - avio_wl16(pb, len / 2); // "number of characters" = length in bytes / 2 + if (avio_open_dyn_buf(&dyn_buf) < 0) + return AVERROR(ENOMEM); - avio_write(pb, buf, len); - av_freep(&buf); + avio_put_str16le(dyn_buf, desc); + len = avio_close_dyn_buf(dyn_buf, &buf); + avio_wl16(pb, len / 2); // "number of characters" = length in bytes / 2 + + avio_write(pb, buf, len); + av_freep(&buf); + } else + avio_wl16(pb, 0); avio_wl16(pb, 0); /* no parameters */ @@ -818,6 +859,8 @@ static void put_frame(AVFormatContext *s, ASFStream *stream, AVStream *avst, flush_packet(s); else if (asf->packet_size_left <= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS + PACKET_HEADER_MIN_SIZE + 1)) flush_packet(s); + else if (asf->packet_nb_payloads == ASF_PAYLOADS_PER_PACKET) + flush_packet(s); } stream->seq++; } diff --git a/libavformat/assdec.c b/libavformat/assdec.c index c9bd63b3c..bb953c727 100644 --- a/libavformat/assdec.c +++ b/libavformat/assdec.c @@ -27,16 +27,16 @@ #include "libavcodec/internal.h" #include "libavutil/bprint.h" -typedef struct ASSContext{ +typedef struct ASSContext { FFDemuxSubtitlesQueue q; -}ASSContext; +} ASSContext; static int ass_probe(AVProbeData *p) { - const char *header= "[Script Info]"; + const char *header = "[Script Info]"; - if( !memcmp(p->buf , header, strlen(header)) - || !memcmp(p->buf+3, header, strlen(header))) + if (!memcmp(p->buf, header, strlen(header)) || + !memcmp(p->buf + 3, header, strlen(header))) return AVPROBE_SCORE_MAX; return 0; @@ -94,9 +94,9 @@ static int ass_read_header(AVFormatContext *s) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 64, 1, 100); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - st->codec->codec_id= AV_CODEC_ID_SSA; + st->codec->codec_id = AV_CODEC_ID_SSA; - header_remaining= INT_MAX; + header_remaining = INT_MAX; av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED); av_bprint_init(&line, 0, AV_BPRINT_SIZE_UNLIMITED); @@ -108,9 +108,9 @@ static int ass_read_header(AVFormatContext *s) break; if (!memcmp(line.str, "[Events]", 8)) - header_remaining= 2; - else if (line.str[0]=='[') - header_remaining= INT_MAX; + header_remaining = 2; + else if (line.str[0] == '[') + header_remaining = INT_MAX; if (header_remaining) { av_bprintf(&header, "%s", line.str); diff --git a/libavformat/astenc.c b/libavformat/astenc.c index edd802cbf..cf7a12c95 100644 --- a/libavformat/astenc.c +++ b/libavformat/astenc.c @@ -113,7 +113,7 @@ static int ast_write_packet(AVFormatContext *s, AVPacket *pkt) AVCodecContext *enc = s->streams[0]->codec; int size = pkt->size / enc->channels; - if (enc->frame_number == 1) + if (s->streams[0]->nb_frames == 0) ast->fbs = size; ffio_wfourcc(pb, "BLCK"); @@ -135,7 +135,7 @@ static int ast_write_trailer(AVFormatContext *s) ASTMuxContext *ast = s->priv_data; AVCodecContext *enc = s->streams[0]->codec; int64_t file_size = avio_tell(pb); - int64_t samples = (file_size - 64 - (32 * enc->frame_number)) / enc->block_align; /* PCM_S16BE_PLANAR */ + int64_t samples = (file_size - 64 - (32 * s->streams[0]->nb_frames)) / enc->block_align; /* PCM_S16BE_PLANAR */ av_log(s, AV_LOG_DEBUG, "total samples: %"PRId64"\n", samples); diff --git a/libavformat/au.c b/libavformat/au.c index edf0f32f0..53702bcb4 100644 --- a/libavformat/au.c +++ b/libavformat/au.c @@ -220,6 +220,7 @@ AVOutputFormat ff_au_muxer = { .write_packet = ff_raw_write_packet, .write_trailer = au_write_trailer, .codec_tag = (const AVCodecTag* const []) { codec_au_tags, 0 }, + .flags = AVFMT_NOTIMESTAMPS, }; #endif /* CONFIG_AU_MUXER */ diff --git a/libavformat/audiointerleave.c b/libavformat/audiointerleave.c index 2aa95f3dc..7f580b970 100644 --- a/libavformat/audiointerleave.c +++ b/libavformat/audiointerleave.c @@ -34,7 +34,7 @@ void ff_audio_interleave_close(AVFormatContext *s) AudioInterleaveContext *aic = st->priv_data; if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) - av_fifo_free(aic->fifo); + av_fifo_freep(&aic->fifo); } } @@ -45,11 +45,11 @@ int ff_audio_interleave_init(AVFormatContext *s, int i; if (!samples_per_frame) - return -1; + return AVERROR(EINVAL); if (!time_base.num) { av_log(s, AV_LOG_ERROR, "timebase not set for audio interleave\n"); - return -1; + return AVERROR(EINVAL); } for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; @@ -60,14 +60,15 @@ int ff_audio_interleave_init(AVFormatContext *s, av_get_bits_per_sample(st->codec->codec_id)) / 8; if (!aic->sample_size) { av_log(s, AV_LOG_ERROR, "could not compute sample size\n"); - return -1; + return AVERROR(EINVAL); } aic->samples_per_frame = samples_per_frame; aic->samples = aic->samples_per_frame; aic->time_base = time_base; aic->fifo_size = 100* *aic->samples; - aic->fifo= av_fifo_alloc(100 * *aic->samples); + if (!(aic->fifo= av_fifo_alloc_array(100, *aic->samples))) + return AVERROR(ENOMEM); } } @@ -113,7 +114,7 @@ int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt 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) - return -1; + return AVERROR(ENOMEM); aic->fifo_size = new_size; } av_fifo_generic_write(aic->fifo, pkt->data, pkt->size, NULL); diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 158705902..a9abfbd4c 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -194,7 +194,7 @@ * the @ref AVStream.codec "stream codec context" information, such as the * codec @ref AVCodecContext.codec_type "type", @ref AVCodecContext.codec_id * "id" and other parameters (e.g. width / height, the pixel or sample format, - * etc.) as known. The @ref AVCodecContext.time_base "codec timebase" should + * 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). @@ -218,8 +218,8 @@ * a single muxing context, they should not be mixed). Do note that the timing * information on the packets sent to the muxer must be in the corresponding * AVStream's timebase. That timebase is set by the muxer (in the - * avformat_write_header() step) and may be different from the timebase the - * caller set on the codec context. + * avformat_write_header() step) and may be different from the timebase + * requested by the caller. * * Once all the data has been written, the caller must call av_write_trailer() * to flush any buffered packets and finalize the output file, then close the IO @@ -262,6 +262,7 @@ struct AVFormatContext; struct AVDeviceInfoList; +struct AVDeviceCapabilitiesQuery; /** * @defgroup metadata_api Public Metadata API @@ -367,6 +368,7 @@ int av_get_packet(AVIOContext *s, AVPacket *pkt, int size); */ int av_append_packet(AVIOContext *s, AVPacket *pkt, int size); +#if FF_API_LAVF_FRAC /*************************************************/ /* fractional numbers for exact pts handling */ @@ -377,6 +379,7 @@ int av_append_packet(AVIOContext *s, AVPacket *pkt, int size); typedef struct AVFrac { int64_t val, num, den; } AVFrac; +#endif /*************************************************/ /* input/output formats */ @@ -531,6 +534,16 @@ typedef struct AVOutputFormat { * @see avdevice_list_devices() for more details. */ int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list); + /** + * Initialize device capabilities submodule. + * @see avdevice_capabilities_create() for more details. + */ + int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps); + /** + * Free device capabilities submodule. + * @see avdevice_capabilities_free() for more details. + */ + int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps); } AVOutputFormat; /** * @} @@ -665,6 +678,18 @@ typedef struct AVInputFormat { * @see avdevice_list_devices() for more details. */ int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list); + + /** + * Initialize device capabilities submodule. + * @see avdevice_capabilities_create() for more details. + */ + int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps); + + /** + * Free device capabilities submodule. + * @see avdevice_capabilities_free() for more details. + */ + int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps); } AVInputFormat; /** * @} @@ -762,19 +787,25 @@ typedef struct AVStream { AVCodecContext *codec; void *priv_data; +#if FF_API_LAVF_FRAC /** - * encoding: pts generation when outputting stream + * @deprecated this field is unused */ + attribute_deprecated struct AVFrac pts; +#endif /** * This is the fundamental unit of time (in seconds) in terms * of which frame timestamps are represented. * * decoding: set by libavformat - * encoding: set by libavformat in avformat_write_header. The muxer may use the - * user-provided value of @ref AVCodecContext.time_base "codec->time_base" - * as a hint. + * encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the desired timebase. In + * avformat_write_header(), the muxer will overwrite this field + * with the timebase that will actually be used for the timestamps + * written into the file (which may or may not be related to the + * user-provided one, depending on the format). */ AVRational time_base; @@ -812,6 +843,10 @@ typedef struct AVStream { /** * Average framerate + * + * - demuxing: May be set by libavformat when creating the stream or in + * avformat_find_stream_info(). + * - muxing: May be set by the caller before avformat_write_header(). */ AVRational avg_frame_rate; @@ -824,6 +859,30 @@ typedef struct AVStream { */ AVPacket attached_pic; + /** + * An array of side data that applies to the whole stream (i.e. the + * container does not allow it to change between packets). + * + * There may be no overlap between the side data in this array and side data + * in the packets. I.e. a given side data is either exported by the muxer + * (demuxing) / set by the caller (muxing) in this array, then it never + * appears in the packets, or the side data is exported / sent through + * the packets (always in the first packet where the value becomes known or + * changes), then it does not appear in this array. + * + * - demuxing: Set by libavformat when the stream is created. + * - muxing: May be set by the caller before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + * + * @see av_format_inject_global_side_data() + */ + AVPacketSideData *side_data; + /** + * The number of elements in the AVStream.side_data array. + */ + int nb_side_data; + /***************************************************************** * 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 @@ -1001,12 +1060,24 @@ typedef struct AVStream { uint8_t dts_ordered; uint8_t dts_misordered; + /** + * Internal data to inject global side data + */ + int inject_global_side_data; + } AVStream; AVRational av_stream_get_r_frame_rate(const AVStream *s); void av_stream_set_r_frame_rate(AVStream *s, AVRational r); struct AVCodecParserContext *av_stream_get_parser(const AVStream *s); +/** + * Returns the pts of the last muxed packet + its duration + * + * the retuned value is undefined when used with a demuxer. + */ +int64_t av_stream_get_end_pts(const AVStream *st); + #define AV_PROGRAM_RUNNING 1 /** @@ -1124,7 +1195,11 @@ typedef struct AVFormatContext { AVIOContext *pb; /* stream info */ - int ctx_flags; /**< Format-specific flags, see AVFMTCTX_xx */ + /** + * Flags signalling stream properties. A combination of AVFMTCTX_*. + * Set by libavformat. + */ + int ctx_flags; /** * Number of elements in AVFormatContext.streams. @@ -1182,6 +1257,10 @@ typedef struct AVFormatContext { unsigned int packet_size; int max_delay; + /** + * Flags modifying the (de)muxer behaviour. A combination of AVFMT_FLAG_*. + * Set by the user before avformat_open_input() / avformat_write_header(). + */ int flags; #define AVFMT_FLAG_GENPTS 0x0001 ///< Generate missing pts even if it requires parsing future frames. #define AVFMT_FLAG_IGNIDX 0x0002 ///< Ignore index. @@ -1193,6 +1272,13 @@ typedef struct AVFormatContext { #define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it. #define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted #define AVFMT_FLAG_FLUSH_PACKETS 0x0200 ///< Flush the AVIOContext every packet. +/** + * When muxing, try to avoid writing any random/volatile data to the output. + * This includes any random IDs, real-time timestamps/dates, muxer version, etc. + * + * This flag is mainly intended for testing. + */ +#define AVFMT_FLAG_BITEXACT 0x0400 #define AVFMT_FLAG_MP4A_LATM 0x8000 ///< Enable RTP MP4A-LATM payload #define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down) #define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (this could be made default once all code is converted) @@ -1206,10 +1292,9 @@ typedef struct AVFormatContext { unsigned int probesize; /** - * Maximum duration (in AV_TIME_BASE units) of the data read - * from input in avformat_find_stream_info(). - * Demuxing only, set by the caller before avformat_find_stream_info(). + * @deprecated deprecated in favor of max_analyze_duration2 */ + attribute_deprecated int max_analyze_duration; const uint8_t *key; @@ -1282,7 +1367,12 @@ typedef struct AVFormatContext { * Start time of the stream in real world time, in microseconds * since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the * stream was captured at this real world time. - * Muxing only, set by the caller before avformat_write_header(). + * - muxing: Set by the caller before avformat_write_header(). If set to + * either 0 or AV_NOPTS_VALUE, then the current wall-time will + * be used. + * - demuxing: Set by libavformat. AV_NOPTS_VALUE if unknown. Note that + * the value may become known after some number of frames + * have been received. */ int64_t start_time_realtime; @@ -1335,6 +1425,12 @@ typedef struct AVFormatContext { */ int64_t max_interleave_delta; + /** + * Allow non-standard and experimental extension + * @see AVCodecContext.strict_std_compliance + */ + int strict_std_compliance; + /** * Transport stream id. * This will be moved into demuxer private options. Thus no API/ABI compatibility @@ -1404,7 +1500,7 @@ typedef struct AVFormatContext { * - encoding: unused * - decoding: Set by user via AVOptions (NO direct access) */ - unsigned int skip_initial_bytes; + int64_t skip_initial_bytes; /** * Correct single timestamp overflows @@ -1436,6 +1532,13 @@ typedef struct AVFormatContext { */ int probe_score; + /** + * number of bytes to read maximally to identify format. + * - encoding: unused + * - decoding: set by user through AVOPtions (NO direct access) + */ + int format_probesize; + /***************************************************************** * 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 @@ -1548,6 +1651,15 @@ typedef struct AVFormatContext { * Muxing: set by user via AVOptions (NO direct access) */ int64_t output_ts_offset; + + /** + * Maximum duration (in AV_TIME_BASE units) of the data read + * from input in avformat_find_stream_info(). + * Demuxing only, set by the caller before avformat_find_stream_info() + * via AVOptions (NO direct access). + * Can be set to 0 to let avformat choose using a heuristic. + */ + int64_t max_analyze_duration2; } AVFormatContext; int av_format_get_probe_score(const AVFormatContext *s); @@ -1564,6 +1676,12 @@ void av_format_set_opaque(AVFormatContext *s, void *opaque); av_format_control_message av_format_get_control_message_cb(const AVFormatContext *s); void av_format_set_control_message_cb(AVFormatContext *s, av_format_control_message callback); +/** + * This function will cause global side data to be injected in the next packet + * of each stream as well as after any subsequent seek. + */ +void av_format_inject_global_side_data(AVFormatContext *s); + /** * Returns the method used to set ctx->duration. * @@ -1685,6 +1803,17 @@ const AVClass *avformat_get_class(void); */ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c); +/** + * Get side information from stream. + * + * @param stream stream + * @param type desired side information type + * @param size pointer for side information size to store (optional) + * @return pointer to data if present or NULL otherwise + */ +uint8_t *av_stream_get_side_data(AVStream *stream, + enum AVPacketSideDataType type, int *size); + AVProgram *av_new_program(AVFormatContext *s, int id); /** @@ -2278,7 +2407,7 @@ void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size); * @param dump_payload True if the payload must be displayed, too. * @param st AVStream that the packet belongs to */ -void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st); +void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st); /** @@ -2292,8 +2421,8 @@ void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st); * @param dump_payload True if the payload must be displayed, too. * @param st AVStream that the packet belongs to */ -void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload, - AVStream *st); +void av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload, + const AVStream *st); /** * Get the AVCodecID for the given codec tag tag. @@ -2379,6 +2508,16 @@ void av_url_split(char *proto, int proto_size, const char *url); +/** + * Print detailed information about the input or output format, such as + * duration, bitrate, streams, container, programs, metadata, side data, + * codec and time base. + * + * @param ic the context to analyze + * @param index index of the stream to dump information about + * @param url the URL to print, such as source or destination file + * @param is_output Select whether the specified context is an input(0) or output(1) + */ void av_dump_format(AVFormatContext *ic, int index, const char *url, diff --git a/libavformat/avidec.c b/libavformat/avidec.c index a7e1c5b8d..8c70649b4 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +#include #include "libavutil/avassert.h" #include "libavutil/avstring.h" @@ -34,6 +34,8 @@ #include "dv.h" #include "internal.h" #include "riff.h" +#include "libavcodec/bytestream.h" +#include "libavcodec/exif.h" typedef struct AVIStream { int64_t frame_offset; /* current frame (video) or byte (audio) counter @@ -222,7 +224,7 @@ static int read_braindead_odml_indx(AVFormatContext *s, int frame_num) if (last_pos == pos || pos == base - 8) avi->non_interleaved = 1; - if (last_pos != pos && (len || !ast->sample_size)) + if (last_pos != pos && len) av_add_index_entry(st, pos, ast->cum_len, len, 0, key ? AVINDEX_KEYFRAME : 0); @@ -379,6 +381,84 @@ static void avi_read_nikon(AVFormatContext *s, uint64_t end) } } +static int avi_extract_stream_metadata(AVStream *st) +{ + GetByteContext gb; + uint8_t *data = st->codec->extradata; + int data_size = st->codec->extradata_size; + int tag, offset; + + if (!data || data_size < 8) { + return AVERROR_INVALIDDATA; + } + + bytestream2_init(&gb, data, data_size); + + tag = bytestream2_get_le32(&gb); + + switch (tag) { + case MKTAG('A', 'V', 'I', 'F'): + // skip 4 byte padding + bytestream2_skip(&gb, 4); + offset = bytestream2_tell(&gb); + bytestream2_init(&gb, data + offset, data_size - offset); + + // decode EXIF tags from IFD, AVI is always little-endian + return avpriv_exif_decode_ifd(st->codec, &gb, 1, 0, &st->metadata); + break; + case MKTAG('C', 'A', 'S', 'I'): + avpriv_request_sample(st->codec, "RIFF stream data tag type CASI (%u)", tag); + break; + case MKTAG('Z', 'o', 'r', 'a'): + avpriv_request_sample(st->codec, "RIFF stream data tag type Zora (%u)", tag); + break; + default: + break; + } + + return 0; +} + +static int calculate_bitrate(AVFormatContext *s) +{ + AVIContext *avi = s->priv_data; + int i, j; + int64_t lensum = 0; + int64_t maxpos = 0; + + for (i = 0; inb_streams; i++) { + int64_t len = 0; + AVStream *st = s->streams[i]; + + if (!st->nb_index_entries) + continue; + + for (j = 0; j < st->nb_index_entries; j++) + len += st->index_entries[j].size; + maxpos = FFMAX(maxpos, st->index_entries[j-1].pos); + lensum += len; + } + if (maxpos < avi->io_fsize*9/10) // index does not cover the whole file + return 0; + if (lensum*9/10 > maxpos || lensum < maxpos*9/10) // frame sum and filesize mismatch + return 0; + + for (i = 0; inb_streams; i++) { + int64_t len = 0; + AVStream *st = s->streams[i]; + int64_t duration; + + for (j = 0; j < st->nb_index_entries; j++) + len += st->index_entries[j].size; + + if (st->nb_index_entries < 2 || st->codec->bit_rate > 0) + continue; + duration = st->index_entries[j-1].timestamp - st->index_entries[0].timestamp; + st->codec->bit_rate = av_rescale(8*len, st->time_base.den, duration * st->time_base.num); + } + return 1; +} + static int avi_read_header(AVFormatContext *s) { AVIContext *avi = s->priv_data; @@ -557,7 +637,7 @@ static int avi_read_header(AVFormatContext *s) ast->rate = avio_rl32(pb); if (!(ast->scale && ast->rate)) { av_log(s, AV_LOG_WARNING, - "scale/rate is %u/%u which is invalid. " + "scale/rate is %"PRIu32"/%"PRIu32" which is invalid. " "(This file has been generated by broken software.)\n", ast->scale, ast->rate); @@ -591,6 +671,7 @@ static int avi_read_header(AVFormatContext *s) codec_type = AVMEDIA_TYPE_VIDEO; ast->sample_size = 0; + st->avg_frame_rate = av_inv_q(st->time_base); break; case MKTAG('a', 'u', 'd', 's'): codec_type = AVMEDIA_TYPE_AUDIO; @@ -789,6 +870,11 @@ static int avi_read_header(AVFormatContext *s) if (st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly avio_r8(pb); + + ret = avi_extract_stream_metadata(st); + if (ret < 0) { + av_log(s, AV_LOG_WARNING, "could not decoding EXIF data in stream header.\n"); + } } break; case MKTAG('i', 'n', 'd', 'x'): @@ -863,6 +949,7 @@ fail: if (!avi->index_loaded && pb->seekable) avi_load_index(s); + calculate_bitrate(s); avi->index_loaded |= 1; if ((ret = guess_ni_flag(s)) < 0) @@ -908,12 +995,14 @@ fail: static int read_gab2_sub(AVStream *st, AVPacket *pkt) { if (pkt->size >= 7 && + pkt->size < INT_MAX - AVPROBE_PADDING_SIZE && !strcmp(pkt->data, "GAB2") && AV_RL16(pkt->data + 5) == 2) { uint8_t desc[256]; int score = AVPROBE_SCORE_EXTENSION, ret; AVIStream *ast = st->priv_data; AVInputFormat *sub_demuxer; AVRational time_base; + int size; AVIOContext *pb = avio_alloc_context(pkt->data + 7, pkt->size - 7, 0, NULL, NULL, NULL, NULL); @@ -931,9 +1020,15 @@ static int read_gab2_sub(AVStream *st, AVPacket *pkt) avio_rl16(pb); /* flags? */ avio_rl32(pb); /* data size */ - pd = (AVProbeData) { .buf = pb->buf_ptr, - .buf_size = pb->buf_end - pb->buf_ptr }; - if (!(sub_demuxer = av_probe_input_format2(&pd, 1, &score))) + size = pb->buf_end - pb->buf_ptr; + pd = (AVProbeData) { .buf = av_mallocz(size + AVPROBE_PADDING_SIZE), + .buf_size = size }; + if (!pd.buf) + goto error; + memcpy(pd.buf, pb->buf_ptr, size); + sub_demuxer = av_probe_input_format2(&pd, 1, &score); + av_freep(&pd.buf); + if (!sub_demuxer) goto error; if (!(ast->sub_ctx = avformat_alloc_context())) @@ -1066,7 +1161,7 @@ start_sync: ast = st->priv_data; if (!ast) { - av_log(s, AV_LOG_WARNING, "Skiping foreign stream %d packet\n", n); + av_log(s, AV_LOG_WARNING, "Skipping foreign stream %d packet\n", n); continue; } @@ -1132,7 +1227,7 @@ start_sync: ast->packet_size = size + 8; ast->remaining = size; - if (size || !ast->sample_size) { + if (size) { uint64_t pos = avio_tell(pb) - 8; if (!st->index_entries || !st->nb_index_entries || st->index_entries[st->nb_index_entries - 1].pos < pos) { @@ -1767,6 +1862,7 @@ AVInputFormat ff_avi_demuxer = { .name = "avi", .long_name = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"), .priv_data_size = sizeof(AVIContext), + .extensions = "avi", .read_probe = avi_probe, .read_header = avi_read_header, .read_packet = avi_read_packet, diff --git a/libavformat/avienc.c b/libavformat/avienc.c index 311aad2b7..c45bac28c 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -26,12 +26,15 @@ #include "avi.h" #include "avio_internal.h" #include "riff.h" +#include "mpegts.h" #include "libavformat/avlanguage.h" #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "libavutil/avassert.h" #include "libavutil/timestamp.h" +#include "libavutil/pixdesc.h" +#include "libavcodec/raw.h" /* * TODO: @@ -62,11 +65,12 @@ typedef struct { int64_t audio_strm_length; int packet_count; int entry; + int max_size; AVIIndex indexes; -} AVIStream ; +} AVIStream; -static inline AVIIentry* avi_get_ientry(AVIIndex* idx, int ent_id) +static inline AVIIentry *avi_get_ientry(AVIIndex *idx, int ent_id) { int cl = ent_id / AVI_INDEX_CLUSTER_SIZE; int id = ent_id % AVI_INDEX_CLUSTER_SIZE; @@ -74,15 +78,15 @@ static inline AVIIentry* avi_get_ientry(AVIIndex* idx, int ent_id) } static int64_t avi_start_new_riff(AVFormatContext *s, AVIOContext *pb, - const char* riff_tag, const char* list_tag) + const char *riff_tag, const char *list_tag) { - AVIContext *avi= s->priv_data; + AVIContext *avi = s->priv_data; int64_t loff; int i; avi->riff_id++; - for (i=0; inb_streams; i++){ - AVIStream *avist= s->streams[i]->priv_data; + for (i = 0; i < s->nb_streams; i++) { + AVIStream *avist = s->streams[i]->priv_data; avist->indexes.entry = 0; } @@ -93,10 +97,10 @@ static int64_t avi_start_new_riff(AVFormatContext *s, AVIOContext *pb, return loff; } -static char* avi_stream2fourcc(char* tag, int index, enum AVMediaType type) +static char *avi_stream2fourcc(char *tag, int index, enum AVMediaType type) { - tag[0] = '0' + index/10; - tag[1] = '0' + index%10; + tag[0] = '0' + index / 10; + tag[1] = '0' + index % 10; if (type == AVMEDIA_TYPE_VIDEO) { tag[2] = 'd'; tag[3] = 'c'; @@ -112,31 +116,30 @@ static char* avi_stream2fourcc(char* tag, int index, enum AVMediaType type) return tag; } -static int avi_write_counters(AVFormatContext* s, int riff_id) +static int avi_write_counters(AVFormatContext *s, int riff_id) { AVIOContext *pb = s->pb; AVIContext *avi = s->priv_data; int n, au_byterate, au_ssize, au_scale, nb_frames = 0; int64_t file_size; - AVCodecContext* stream; + AVCodecContext *stream; file_size = avio_tell(pb); - for(n = 0; n < s->nb_streams; n++) { - AVIStream *avist= s->streams[n]->priv_data; + for (n = 0; n < s->nb_streams; n++) { + AVIStream *avist = s->streams[n]->priv_data; av_assert0(avist->frames_hdr_strm); stream = s->streams[n]->codec; avio_seek(pb, avist->frames_hdr_strm, SEEK_SET); - ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale); - if(au_ssize == 0) { + ff_parse_specific_params(s->streams[n], &au_byterate, &au_ssize, &au_scale); + if (au_ssize == 0) avio_wl32(pb, avist->packet_count); - } else { + else avio_wl32(pb, avist->audio_strm_length / au_ssize); - } - if(stream->codec_type == AVMEDIA_TYPE_VIDEO) + if (stream->codec_type == AVMEDIA_TYPE_VIDEO) nb_frames = FFMAX(nb_frames, avist->packet_count); } - if(riff_id == 1) { + if (riff_id == 1) { av_assert0(avi->frames_hdr_all); avio_seek(pb, avi->frames_hdr_all, SEEK_SET); avio_wl32(pb, nb_frames); @@ -151,7 +154,8 @@ 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 *stream, *video_enc; + AVCodecContext *video_enc; + AVStream *video_st = NULL; int64_t list1, list2, strh, strf; AVDictionaryEntry *t = NULL; int padding; @@ -162,9 +166,9 @@ static int avi_write_header(AVFormatContext *s) return AVERROR(EINVAL); } - for(n=0;nnb_streams;n++) { - s->streams[n]->priv_data= av_mallocz(sizeof(AVIStream)); - if(!s->streams[n]->priv_data) + for (n = 0; n < s->nb_streams; n++) { + s->streams[n]->priv_data = av_mallocz(sizeof(AVIStream)); + if (!s->streams[n]->priv_data) return AVERROR(ENOMEM); } @@ -178,32 +182,35 @@ static int avi_write_header(AVFormatContext *s) bitrate = 0; video_enc = NULL; - for(n=0;nnb_streams;n++) { - stream = s->streams[n]->codec; - bitrate += stream->bit_rate; - if (stream->codec_type == AVMEDIA_TYPE_VIDEO) - video_enc = stream; + 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; + video_st = s->streams[n]; + } } nb_frames = 0; - if(video_enc){ - avio_wl32(pb, (uint32_t)(INT64_C(1000000) * video_enc->time_base.num / video_enc->time_base.den)); - } else { + // TODO: should be avg_frame_rate + if (video_st) + avio_wl32(pb, (uint32_t) (INT64_C(1000000) * video_st->time_base.num / + video_st->time_base.den)); + else avio_wl32(pb, 0); - } avio_wl32(pb, bitrate / 8); /* XXX: not quite exact */ avio_wl32(pb, 0); /* padding */ if (!pb->seekable) - avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */ + avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */ else - avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */ + avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */ avi->frames_hdr_all = avio_tell(pb); /* remember this offset to fill later */ avio_wl32(pb, nb_frames); /* nb frames, filled later */ 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){ + if (video_enc) { avio_wl32(pb, video_enc->width); avio_wl32(pb, video_enc->height); } else { @@ -216,31 +223,40 @@ static int avi_write_header(AVFormatContext *s) avio_wl32(pb, 0); /* reserved */ /* stream list */ - for(i=0;istreams[i]->priv_data; + for (i = 0; i < n; i++) { + AVStream *st = s->streams[i]; + AVCodecContext *enc = st->codec; + AVIStream *avist = st->priv_data; list2 = ff_start_tag(pb, "LIST"); ffio_wfourcc(pb, "strl"); - stream = s->streams[i]->codec; - /* stream generic header */ strh = ff_start_tag(pb, "strh"); - switch(stream->codec_type) { + switch (enc->codec_type) { case AVMEDIA_TYPE_SUBTITLE: // XSUB subtitles behave like video tracks, other subtitles // are not (yet) supported. - if (stream->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"); + if (enc->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; } - case AVMEDIA_TYPE_VIDEO: ffio_wfourcc(pb, "vids"); break; - case AVMEDIA_TYPE_AUDIO: ffio_wfourcc(pb, "auds"); break; -// case AVMEDIA_TYPE_TEXT : ffio_wfourcc(pb, "txts"); break; - case AVMEDIA_TYPE_DATA : ffio_wfourcc(pb, "dats"); break; + case AVMEDIA_TYPE_VIDEO: + ffio_wfourcc(pb, "vids"); + break; + case AVMEDIA_TYPE_AUDIO: + ffio_wfourcc(pb, "auds"); + break; +// case AVMEDIA_TYPE_TEXT: +// ffio_wfourcc(pb, "txts"); +// break; + case AVMEDIA_TYPE_DATA: + ffio_wfourcc(pb, "dats"); + break; } - if(stream->codec_type == AVMEDIA_TYPE_VIDEO || - stream->codec_id == AV_CODEC_ID_XSUB) - avio_wl32(pb, stream->codec_tag); + if (enc->codec_type == AVMEDIA_TYPE_VIDEO || + enc->codec_id == AV_CODEC_ID_XSUB) + avio_wl32(pb, enc->codec_tag); else avio_wl32(pb, 1); avio_wl32(pb, 0); /* flags */ @@ -248,81 +264,98 @@ static int avi_write_header(AVFormatContext *s) avio_wl16(pb, 0); /* language */ avio_wl32(pb, 0); /* initial frame */ - ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale); + ff_parse_specific_params(st, &au_byterate, &au_ssize, &au_scale); - if ( stream->codec_type == AVMEDIA_TYPE_VIDEO - && stream->codec_id != AV_CODEC_ID_XSUB + if ( enc->codec_type == AVMEDIA_TYPE_VIDEO + && enc->codec_id != AV_CODEC_ID_XSUB && au_byterate > 1000LL*au_scale) { au_byterate = 600; au_scale = 1; } - avpriv_set_pts_info(s->streams[i], 64, au_scale, au_byterate); - if(stream->codec_id == AV_CODEC_ID_XSUB) + avpriv_set_pts_info(st, 64, au_scale, au_byterate); + if (enc->codec_id == AV_CODEC_ID_XSUB) au_scale = au_byterate = 0; avio_wl32(pb, au_scale); /* scale */ avio_wl32(pb, au_byterate); /* rate */ avio_wl32(pb, 0); /* start */ - avist->frames_hdr_strm = avio_tell(pb); /* remember this offset to fill later */ + /* remember this offset to fill later */ + avist->frames_hdr_strm = avio_tell(pb); if (!pb->seekable) - avio_wl32(pb, AVI_MAX_RIFF_SIZE); /* FIXME: this may be broken, but who cares */ + /* FIXME: this may be broken, but who cares */ + avio_wl32(pb, AVI_MAX_RIFF_SIZE); else - avio_wl32(pb, 0); /* length, XXX: filled later */ + avio_wl32(pb, 0); /* length, XXX: filled later */ - /* suggested buffer size */ //FIXME set at the end to largest chunk - if(stream->codec_type == AVMEDIA_TYPE_VIDEO) + /* suggested buffer size, is set to largest chunk size in avi_write_trailer */ + if (enc->codec_type == AVMEDIA_TYPE_VIDEO) avio_wl32(pb, 1024 * 1024); - else if(stream->codec_type == AVMEDIA_TYPE_AUDIO) + else if (enc->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, stream->width); - avio_wl16(pb, stream->height); + avio_wl16(pb, enc->width); + avio_wl16(pb, enc->height); ff_end_tag(pb, strh); - if(stream->codec_type != AVMEDIA_TYPE_DATA){ - int ret; + if (enc->codec_type != AVMEDIA_TYPE_DATA) { + int ret; + enum AVPixelFormat pix_fmt; - strf = ff_start_tag(pb, "strf"); - switch(stream->codec_type) { - case AVMEDIA_TYPE_SUBTITLE: - // XSUB subtitles behave like video tracks, other subtitles - // are not (yet) supported. - if (stream->codec_id != AV_CODEC_ID_XSUB) break; - case AVMEDIA_TYPE_VIDEO: - ff_put_bmp_header(pb, stream, ff_codec_bmp_tags, 0, 0); - break; - case AVMEDIA_TYPE_AUDIO: - if ((ret = ff_put_wav_header(pb, stream)) < 0) { - return ret; + strf = ff_start_tag(pb, "strf"); + switch (enc->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) + break; + case AVMEDIA_TYPE_VIDEO: + /* WMP expects RGB 5:5:5 rawvideo in avi to have bpp set to 16. */ + if ( !enc->codec_tag + && enc->codec_id == AV_CODEC_ID_RAWVIDEO + && enc->pix_fmt == AV_PIX_FMT_RGB555LE + && enc->bits_per_coded_sample == 15) + enc->bits_per_coded_sample = 16; + ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 0, 0); + pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, + enc->bits_per_coded_sample); + if ( !enc->codec_tag + && enc->codec_id == AV_CODEC_ID_RAWVIDEO + && enc->pix_fmt != pix_fmt + && enc->pix_fmt != AV_PIX_FMT_NONE) + av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to avi, output file will be unreadable\n", + av_get_pix_fmt_name(enc->pix_fmt)); + break; + case AVMEDIA_TYPE_AUDIO: + if ((ret = ff_put_wav_header(pb, enc, 0)) < 0) + return ret; + break; + default: + av_log(s, AV_LOG_ERROR, + "Invalid or not supported codec type '%s' found in the input\n", + (char *)av_x_if_null(av_get_media_type_string(enc->codec_type), "?")); + return AVERROR(EINVAL); } - break; - default: - av_log(s, AV_LOG_ERROR, - "Invalid or not supported codec type '%s' found in the input\n", - (char *)av_x_if_null(av_get_media_type_string(stream->codec_type), "?")); - return AVERROR(EINVAL); - } - ff_end_tag(pb, strf); - if ((t = av_dict_get(s->streams[i]->metadata, "title", NULL, 0))) { - ff_riff_write_info_tag(s->pb, "strn", t->value); - t = NULL; - } - if(stream->codec_id == AV_CODEC_ID_XSUB - && (t = av_dict_get(s->streams[i]->metadata, "language", NULL, 0))) { - const char* langstr = av_convert_lang_to(t->value, AV_LANG_ISO639_1); - t = NULL; - if (langstr) { - char* str = av_asprintf("Subtitle - %s-xx;02", langstr); - ff_riff_write_info_tag(s->pb, "strn", str); - av_free(str); + ff_end_tag(pb, strf); + if ((t = av_dict_get(st->metadata, "title", NULL, 0))) { + ff_riff_write_info_tag(s->pb, "strn", t->value); + t = NULL; + } + if (enc->codec_id == AV_CODEC_ID_XSUB + && (t = av_dict_get(s->streams[i]->metadata, "language", NULL, 0))) { + const char* langstr = av_convert_lang_to(t->value, AV_LANG_ISO639_1); + t = NULL; + if (langstr) { + char* str = av_asprintf("Subtitle - %s-xx;02", langstr); + ff_riff_write_info_tag(s->pb, "strn", str); + av_free(str); + } } } - } if (pb->seekable) { unsigned char tag[5]; @@ -331,47 +364,48 @@ static int avi_write_header(AVFormatContext *s) /* Starting to lay out AVI OpenDML master index. * We want to make it JUNK entry for now, since we'd * like to get away without making AVI an OpenDML one - * for compatibility reasons. - */ - avist->indexes.entry = avist->indexes.ents_allocated = 0; + * for compatibility reasons. */ + avist->indexes.entry = avist->indexes.ents_allocated = 0; avist->indexes.indx_start = ff_start_tag(pb, "JUNK"); - avio_wl16(pb, 4); /* wLongsPerEntry */ - 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, stream->codec_type)); - /* dwChunkId */ - avio_wl64(pb, 0); /* dwReserved[3] - avio_wl32(pb, 0); Must be 0. */ - for (j=0; j < AVI_MASTER_INDEX_SIZE * 2; j++) - avio_wl64(pb, 0); + avio_wl16(pb, 4); /* wLongsPerEntry */ + 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)); + /* dwChunkId */ + avio_wl64(pb, 0); /* dwReserved[3] */ + // avio_wl32(pb, 0); /* Must be 0. */ + for (j = 0; j < AVI_MASTER_INDEX_SIZE * 2; j++) + avio_wl64(pb, 0); ff_end_tag(pb, avist->indexes.indx_start); } - if( stream->codec_type == AVMEDIA_TYPE_VIDEO - && s->streams[i]->sample_aspect_ratio.num>0 - && s->streams[i]->sample_aspect_ratio.den>0){ - int vprp= ff_start_tag(pb, "vprp"); - AVRational dar = av_mul_q(s->streams[i]->sample_aspect_ratio, - (AVRational){stream->width, stream->height}); + if (enc->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 }); int num, den; av_reduce(&num, &den, dar.num, dar.den, 0xFFFF); - avio_wl32(pb, 0); //video format = unknown - avio_wl32(pb, 0); //video standard= unknown - avio_wl32(pb, lrintf(1.0/av_q2d(stream->time_base))); - avio_wl32(pb, stream->width ); - avio_wl32(pb, stream->height); + avio_wl32(pb, 0); // video format = unknown + 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_wl16(pb, den); avio_wl16(pb, num); - avio_wl32(pb, stream->width ); - avio_wl32(pb, stream->height); - avio_wl32(pb, 1); //progressive FIXME + avio_wl32(pb, enc->width); + avio_wl32(pb, enc->height); + avio_wl32(pb, 1); // progressive FIXME - avio_wl32(pb, stream->height); - avio_wl32(pb, stream->width ); - avio_wl32(pb, stream->height); - avio_wl32(pb, stream->width ); + avio_wl32(pb, enc->height); + avio_wl32(pb, enc->width); + avio_wl32(pb, enc->height); + avio_wl32(pb, enc->width); avio_wl32(pb, 0); avio_wl32(pb, 0); @@ -389,8 +423,8 @@ static int avi_write_header(AVFormatContext *s) ffio_wfourcc(pb, "odml"); ffio_wfourcc(pb, "dmlh"); avio_wl32(pb, 248); - for (i = 0; i < 248; i+= 4) - avio_wl32(pb, 0); + for (i = 0; i < 248; i += 4) + avio_wl32(pb, 0); ff_end_tag(pb, avi->odml_list); } @@ -435,47 +469,47 @@ static int avi_write_ix(AVFormatContext *s) return AVERROR(EINVAL); } - for (i=0;inb_streams;i++) { - AVIStream *avist= s->streams[i]->priv_data; - int64_t ix, pos; + for (i = 0; i < s->nb_streams; i++) { + AVIStream *avist = s->streams[i]->priv_data; + int64_t ix, pos; - avi_stream2fourcc(tag, i, s->streams[i]->codec->codec_type); - ix_tag[3] = '0' + i; + avi_stream2fourcc(tag, i, s->streams[i]->codec->codec_type); + ix_tag[3] = '0' + i; - /* Writing AVI OpenDML leaf index chunk */ - ix = avio_tell(pb); - ffio_wfourcc(pb, ix_tag); /* ix?? */ - avio_wl32(pb, avist->indexes.entry * 8 + 24); - /* chunk size */ - avio_wl16(pb, 2); /* wLongsPerEntry */ - avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */ - avio_w8(pb, 1); /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */ - avio_wl32(pb, avist->indexes.entry); - /* nEntriesInUse */ - ffio_wfourcc(pb, tag); /* dwChunkId */ - avio_wl64(pb, avi->movi_list);/* qwBaseOffset */ - avio_wl32(pb, 0); /* dwReserved_3 (must be 0) */ + /* Writing AVI OpenDML leaf index chunk */ + ix = avio_tell(pb); + ffio_wfourcc(pb, ix_tag); /* ix?? */ + avio_wl32(pb, avist->indexes.entry * 8 + 24); + /* chunk size */ + avio_wl16(pb, 2); /* wLongsPerEntry */ + avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */ + avio_w8(pb, 1); /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */ + avio_wl32(pb, avist->indexes.entry); + /* nEntriesInUse */ + ffio_wfourcc(pb, tag); /* dwChunkId */ + avio_wl64(pb, avi->movi_list); /* qwBaseOffset */ + avio_wl32(pb, 0); /* dwReserved_3 (must be 0) */ - for (j=0; jindexes.entry; j++) { - AVIIentry* ie = avi_get_ientry(&avist->indexes, j); - avio_wl32(pb, ie->pos + 8); - avio_wl32(pb, ((uint32_t)ie->len & ~0x80000000) | + for (j = 0; j < avist->indexes.entry; j++) { + AVIIentry *ie = avi_get_ientry(&avist->indexes, j); + avio_wl32(pb, ie->pos + 8); + avio_wl32(pb, ((uint32_t) ie->len & ~0x80000000) | (ie->flags & 0x10 ? 0 : 0x80000000)); - } - avio_flush(pb); - pos = avio_tell(pb); + } + avio_flush(pb); + pos = avio_tell(pb); - /* Updating one entry in the AVI OpenDML master index */ - avio_seek(pb, avist->indexes.indx_start - 8, SEEK_SET); - ffio_wfourcc(pb, "indx"); /* enabling this entry */ - avio_skip(pb, 8); - avio_wl32(pb, avi->riff_id); /* nEntriesInUse */ - avio_skip(pb, 16*avi->riff_id); - avio_wl64(pb, ix); /* qwOffset */ - avio_wl32(pb, pos - ix); /* dwSize */ - avio_wl32(pb, avist->indexes.entry); /* dwDuration */ + /* Updating one entry in the AVI OpenDML master index */ + avio_seek(pb, avist->indexes.indx_start - 8, SEEK_SET); + ffio_wfourcc(pb, "indx"); /* enabling this entry */ + avio_skip(pb, 8); + avio_wl32(pb, avi->riff_id); /* nEntriesInUse */ + avio_skip(pb, 16 * avi->riff_id); + avio_wl64(pb, ix); /* qwOffset */ + avio_wl32(pb, pos - ix); /* dwSize */ + avio_wl32(pb, avist->indexes.entry); /* dwDuration */ - avio_seek(pb, pos, SEEK_SET); + avio_seek(pb, pos, SEEK_SET); } return 0; } @@ -490,31 +524,31 @@ static int avi_write_idx1(AVFormatContext *s) if (pb->seekable) { AVIStream *avist; - AVIIentry* ie = 0, *tie; + AVIIentry *ie = 0, *tie; int empty, stream_id = -1; idx_chunk = ff_start_tag(pb, "idx1"); - for(i=0; inb_streams; i++){ - avist= s->streams[i]->priv_data; - avist->entry=0; + for (i = 0; i < s->nb_streams; i++) { + avist = s->streams[i]->priv_data; + avist->entry = 0; } do { empty = 1; - for (i=0; inb_streams; i++) { - avist= s->streams[i]->priv_data; - if (avist->indexes.entry <= avist->entry) - continue; + for (i = 0; i < s->nb_streams; i++) { + avist = s->streams[i]->priv_data; + if (avist->indexes.entry <= avist->entry) + continue; - tie = avi_get_ientry(&avist->indexes, avist->entry); - if (empty || tie->pos < ie->pos) { - ie = tie; - stream_id = i; - } - empty = 0; + tie = avi_get_ientry(&avist->indexes, avist->entry); + if (empty || tie->pos < ie->pos) { + ie = tie; + stream_id = i; + } + empty = 0; } if (!empty) { - avist= s->streams[stream_id]->priv_data; + avist = s->streams[stream_id]->priv_data; avi_stream2fourcc(tag, stream_id, s->streams[stream_id]->codec->codec_type); ffio_wfourcc(pb, tag); @@ -533,28 +567,34 @@ static int avi_write_idx1(AVFormatContext *s) static int avi_write_packet(AVFormatContext *s, AVPacket *pkt) { - AVIContext *avi = s->priv_data; - AVIOContext *pb = s->pb; unsigned char tag[5]; - unsigned int flags=0; - const int stream_index= pkt->stream_index; - AVIStream *avist= s->streams[stream_index]->priv_data; - AVCodecContext *enc= s->streams[stream_index]->codec; - int size= pkt->size; + unsigned int flags = 0; + const int stream_index = pkt->stream_index; + int size = pkt->size; + AVIContext *avi = s->priv_data; + AVIOContext *pb = s->pb; + AVIStream *avist = s->streams[stream_index]->priv_data; + AVCodecContext *enc = s->streams[stream_index]->codec; + if (enc->codec_id == AV_CODEC_ID_H264 && enc->codec_tag == MKTAG('H','2','6','4')) { + int ret = ff_check_h264_startcode(s, s->streams[stream_index], pkt); + if (ret < 0) + return ret; + } av_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(pkt->dts), avist->packet_count, stream_index); - while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count){ + while (enc->block_align == 0 && pkt->dts != AV_NOPTS_VALUE && + pkt->dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count) { AVPacket empty_packet; - if(pkt->dts - avist->packet_count > 60000){ + if (pkt->dts - avist->packet_count > 60000) { av_log(s, AV_LOG_ERROR, "Too large number of skipped frames %"PRId64" > 60000\n", pkt->dts - avist->packet_count); return AVERROR(EINVAL); } av_init_packet(&empty_packet); - empty_packet.size= 0; - empty_packet.data= NULL; - empty_packet.stream_index= stream_index; + empty_packet.size = 0; + empty_packet.data = NULL; + empty_packet.stream_index = stream_index; avi_write_packet(s, &empty_packet); av_dlog(s, "dup dts:%s packet_count:%d\n", av_ts2str(pkt->dts), avist->packet_count); } @@ -563,7 +603,6 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt) // Make sure to put an OpenDML chunk when the file size exceeds the limits if (pb->seekable && (avio_tell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) { - avi_write_ix(s); ff_end_tag(pb, avi->movi_list); @@ -575,32 +614,33 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt) } avi_stream2fourcc(tag, stream_index, enc->codec_type); - if(pkt->flags&AV_PKT_FLAG_KEY) + if (pkt->flags & AV_PKT_FLAG_KEY) flags = 0x10; - if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { - avist->audio_strm_length += size; - } + if (enc->codec_type == AVMEDIA_TYPE_AUDIO) + avist->audio_strm_length += size; if (s->pb->seekable) { - AVIIndex* idx = &avist->indexes; + AVIIndex *idx = &avist->indexes; int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE; int id = idx->entry % AVI_INDEX_CLUSTER_SIZE; if (idx->ents_allocated <= idx->entry) { idx->cluster = av_realloc_f(idx->cluster, sizeof(void*), cl+1); if (!idx->cluster) { idx->ents_allocated = 0; - idx->entry = 0; + idx->entry = 0; return AVERROR(ENOMEM); } - idx->cluster[cl] = av_malloc(AVI_INDEX_CLUSTER_SIZE*sizeof(AVIIentry)); + idx->cluster[cl] = + av_malloc(AVI_INDEX_CLUSTER_SIZE * sizeof(AVIIentry)); if (!idx->cluster[cl]) return AVERROR(ENOMEM); idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE; } idx->cluster[cl][id].flags = flags; - idx->cluster[cl][id].pos = avio_tell(pb) - avi->movi_list; - idx->cluster[cl][id].len = size; + idx->cluster[cl][id].pos = avio_tell(pb) - avi->movi_list; + idx->cluster[cl][id].len = size; + avist->max_size = FFMAX(avist->max_size, size); idx->entry++; } @@ -621,7 +661,7 @@ static int avi_write_trailer(AVFormatContext *s) int i, j, n, nb_frames; int64_t file_size; - if (pb->seekable){ + if (pb->seekable) { if (avi->riff_id == 1) { ff_end_tag(pb, avi->movi_list); res = avi_write_idx1(s); @@ -636,17 +676,17 @@ static int avi_write_trailer(AVFormatContext *s) ffio_wfourcc(pb, "LIST"); /* Making this AVI OpenDML one */ avio_skip(pb, 16); - for (n=nb_frames=0;nnb_streams;n++) { + for (n = nb_frames = 0; n < s->nb_streams; n++) { AVCodecContext *stream = s->streams[n]->codec; - AVIStream *avist= s->streams[n]->priv_data; + AVIStream *avist = s->streams[n]->priv_data; if (stream->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 (stream->codec_id == AV_CODEC_ID_MP2 || + stream->codec_id == AV_CODEC_ID_MP3) nb_frames += avist->packet_count; - } } } avio_wl32(pb, nb_frames); @@ -656,29 +696,33 @@ static int avi_write_trailer(AVFormatContext *s) } } - for (i=0; inb_streams; i++) { - AVIStream *avist= s->streams[i]->priv_data; - for (j=0; jindexes.ents_allocated/AVI_INDEX_CLUSTER_SIZE; j++) - av_freep(&avist->indexes.cluster[j]); - av_freep(&avist->indexes.cluster); - avist->indexes.ents_allocated = avist->indexes.entry = 0; + for (i = 0; i < s->nb_streams; i++) { + AVIStream *avist = s->streams[i]->priv_data; + for (j = 0; j < avist->indexes.ents_allocated / AVI_INDEX_CLUSTER_SIZE; j++) + av_freep(&avist->indexes.cluster[j]); + av_freep(&avist->indexes.cluster); + avist->indexes.ents_allocated = avist->indexes.entry = 0; + if (pb->seekable) { + avio_seek(pb, avist->frames_hdr_strm + 4, SEEK_SET); + avio_wl32(pb, avist->max_size); + } } return res; } AVOutputFormat ff_avi_muxer = { - .name = "avi", - .long_name = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"), - .mime_type = "video/x-msvideo", - .extensions = "avi", - .priv_data_size = sizeof(AVIContext), - .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_AC3, - .video_codec = AV_CODEC_ID_MPEG4, - .write_header = avi_write_header, - .write_packet = avi_write_packet, - .write_trailer = avi_write_trailer, - .codec_tag = (const AVCodecTag* const []){ + .name = "avi", + .long_name = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"), + .mime_type = "video/x-msvideo", + .extensions = "avi", + .priv_data_size = sizeof(AVIContext), + .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_AC3, + .video_codec = AV_CODEC_ID_MPEG4, + .write_header = avi_write_header, + .write_packet = avi_write_packet, + .write_trailer = avi_write_trailer, + .codec_tag = (const AVCodecTag * const []) { ff_codec_bmp_tags, ff_codec_wav_tags, 0 }, }; diff --git a/libavformat/avio.c b/libavformat/avio.c index a76f9db3b..0a2a0a9aa 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -270,11 +270,13 @@ int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options) { int ret = ffurl_alloc(puc, filename, flags, int_cb); - if (ret) + if (ret < 0) return ret; if (options && (*puc)->prot->priv_data_class && (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0) goto fail; + if ((ret = av_opt_set_dict(*puc, options)) < 0) + goto fail; ret = ffurl_connect(*puc, options); if (!ret) return 0; @@ -310,8 +312,8 @@ static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf, } else { if (h->rw_timeout) { if (!wait_since) - wait_since = av_gettime(); - else if (av_gettime() > wait_since + h->rw_timeout) + wait_since = av_gettime_relative(); + else if (av_gettime_relative() > wait_since + h->rw_timeout) return AVERROR(EIO); } av_usleep(1000); @@ -399,7 +401,7 @@ int avio_check(const char *url, int flags) { URLContext *h; int ret = ffurl_alloc(&h, url, flags, NULL); - if (ret) + if (ret < 0) return ret; if (h->prot->url_check) { diff --git a/libavformat/avio.h b/libavformat/avio.h index defd6172b..4004b6fda 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -146,6 +146,13 @@ typedef struct AVIOContext { * This field is internal to libavformat and access from outside is not allowed. */ int writeout_count; + + /** + * Original buffer size + * used internally after probing and ensure seekback to reset the buffer size + * This field is internal to libavformat and access from outside is not allowed. + */ + int orig_buffer_size; } AVIOContext; /* unbuffered I/O */ diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index 8441d4997..bb2512707 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -93,7 +93,7 @@ int ffio_set_buf_size(AVIOContext *s, int buf_size); * * Will ensure that when reading sequentially up to buf_size, seeking * within the current pos and pos+buf_size is possible. - * Once the stream position moves outside this window this gurantee is lost. + * Once the stream position moves outside this window this guarantee is lost. */ int ffio_ensure_seekback(AVIOContext *s, int buf_size); @@ -105,6 +105,8 @@ void ffio_init_checksum(AVIOContext *s, unsigned long ffio_get_checksum(AVIOContext *s); unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, unsigned int len); +unsigned long ff_crcA001_update(unsigned long checksum, const uint8_t *buf, + unsigned int len); /** * Open a write only packetized memory stream with a maximum packet diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 95fdf200e..738459e83 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -78,6 +78,7 @@ int ffio_init_context(AVIOContext *s, int64_t (*seek)(void *opaque, int64_t offset, int whence)) { s->buffer = buffer; + s->orig_buffer_size = s->buffer_size = buffer_size; s->buf_ptr = buffer; s->opaque = opaque; @@ -434,14 +435,14 @@ static void fill_buffer(AVIOContext *s) } /* make buffer smaller in case it ended up large after probing */ - if (s->read_packet && s->buffer_size > max_buffer_size) { + if (s->read_packet && s->orig_buffer_size && s->buffer_size > s->orig_buffer_size) { if (dst == s->buffer) { - ffio_set_buf_size(s, max_buffer_size); + ffio_set_buf_size(s, s->orig_buffer_size); s->checksum_ptr = dst = s->buffer; } - av_assert0(len >= max_buffer_size); - len = max_buffer_size; + av_assert0(len >= s->orig_buffer_size); + len = s->orig_buffer_size; } if (s->read_packet) @@ -468,6 +469,12 @@ unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len); } +unsigned long ff_crcA001_update(unsigned long checksum, const uint8_t *buf, + unsigned int len) +{ + return av_crc(av_crc_get_table(AV_CRC_16_ANSI_LE), checksum, buf, len); +} + unsigned long ffio_get_checksum(AVIOContext *s) { s->checksum = s->update_checksum(s->checksum, s->checksum_ptr, @@ -658,7 +665,9 @@ int ff_get_line(AVIOContext *s, char *buf, int maxlen) c = avio_r8(s); if (c && i < maxlen-1) buf[i++] = c; - } while (c != '\n' && c); + } while (c != '\n' && c != '\r' && c); + if (c == '\r' && avio_r8(s) != '\n') + avio_skip(s, -1); buf[i] = 0; return i; @@ -762,10 +771,11 @@ int ffio_ensure_seekback(AVIOContext *s, int buf_size) uint8_t *buffer; int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE; + int filled = s->buf_end - s->buffer; buf_size += s->buf_ptr - s->buffer + max_buffer_size; - if (buf_size < s->buffer_size || s->seekable) + if (buf_size < filled || s->seekable) return 0; av_assert0(!s->write_flag); @@ -773,7 +783,7 @@ int ffio_ensure_seekback(AVIOContext *s, int buf_size) if (!buffer) return AVERROR(ENOMEM); - memcpy(buffer, s->buffer, s->buffer_size); + memcpy(buffer, s->buffer, filled); av_free(s->buffer); s->buf_ptr = buffer + (s->buf_ptr - s->buffer); s->buf_end = buffer + (s->buf_end - s->buffer); @@ -791,6 +801,7 @@ int ffio_set_buf_size(AVIOContext *s, int buf_size) av_free(s->buffer); s->buffer = buffer; + s->orig_buffer_size = s->buffer_size = buf_size; s->buf_ptr = buffer; url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ); diff --git a/libavformat/avisynth.c b/libavformat/avisynth.c index b837bd9ab..c01d7e484 100644 --- a/libavformat/avisynth.c +++ b/libavformat/avisynth.c @@ -294,6 +294,7 @@ static int avisynth_create_stream_audio(AVFormatContext *s, AVStream *st) st->codec->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: diff --git a/libavformat/bink.c b/libavformat/bink.c index ec9257bca..395c8d9aa 100644 --- a/libavformat/bink.c +++ b/libavformat/bink.c @@ -28,6 +28,8 @@ * http://wiki.multimedia.cx/index.php?title=Bink_Container */ +#include + #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "avformat.h" @@ -111,7 +113,9 @@ static int read_header(AVFormatContext *s) fps_num = avio_rl32(pb); fps_den = avio_rl32(pb); if (fps_num == 0 || fps_den == 0) { - av_log(s, AV_LOG_ERROR, "invalid header: invalid fps (%d/%d)\n", fps_num, fps_den); + av_log(s, AV_LOG_ERROR, + "invalid header: invalid fps (%"PRIu32"/%"PRIu32")\n", + fps_num, fps_den); return AVERROR(EIO); } avpriv_set_pts_info(vst, 64, fps_den, fps_num); @@ -132,7 +136,7 @@ static int read_header(AVFormatContext *s) if (bink->num_audio_tracks > BINK_MAX_AUDIO_TRACKS) { av_log(s, AV_LOG_ERROR, - "invalid header: more than "AV_STRINGIFY(BINK_MAX_AUDIO_TRACKS)" audio tracks (%d)\n", + "invalid header: more than "AV_STRINGIFY(BINK_MAX_AUDIO_TRACKS)" audio tracks (%"PRIu32")\n", bink->num_audio_tracks); return AVERROR(EIO); } @@ -226,7 +230,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) uint32_t audio_size = avio_rl32(pb); if (audio_size > bink->remain_packet_size - 4) { av_log(s, AV_LOG_ERROR, - "frame %"PRId64": audio size in header (%u) > size of packet left (%u)\n", + "frame %"PRId64": audio size in header (%"PRIu32") > size of packet left (%"PRIu32")\n", bink->video_pts, audio_size, bink->remain_packet_size); return AVERROR(EIO); } diff --git a/libavformat/brstm.c b/libavformat/brstm.c index 7781b3c55..8e4dae6f0 100644 --- a/libavformat/brstm.c +++ b/libavformat/brstm.c @@ -200,7 +200,7 @@ static int read_header(AVFormatContext *s) goto fail; } if (b->adpc) { - av_log(s, AV_LOG_WARNING, "skipping additonal ADPC chunk\n"); + av_log(s, AV_LOG_WARNING, "skipping additional ADPC chunk\n"); goto skip; } else { b->adpc = av_mallocz(asize); diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c index 0b5d59cda..a8edbca03 100644 --- a/libavformat/cafdec.c +++ b/libavformat/cafdec.c @@ -25,6 +25,8 @@ * Core Audio Format demuxer */ +#include + #include "avformat.h" #include "internal.h" #include "isom.h" @@ -285,7 +287,8 @@ static int read_header(AVFormatContext *s) default: #define _(x) ((x) >= ' ' ? (x) : ' ') - av_log(s, AV_LOG_WARNING, "skipping CAF chunk: %08X (%c%c%c%c), size %"PRId64"\n", + av_log(s, AV_LOG_WARNING, + "skipping CAF chunk: %08"PRIX32" (%c%c%c%c), size %"PRId64"\n", tag, _(tag>>24), _((tag>>16)&0xFF), _((tag>>8)&0xFF), _(tag&0xFF), size); #undef _ case MKBETAG('f','r','e','e'): diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index ae36b85cb..1708275e1 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -51,7 +51,7 @@ static uint32_t codec_flags(enum AVCodecID codec_id) { } } -static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels) { +static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels, int block_align) { switch (codec_id) { case AV_CODEC_ID_PCM_S8: case AV_CODEC_ID_PCM_S16LE: @@ -91,9 +91,9 @@ static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels) { case AV_CODEC_ID_ALAC: return 4096; case AV_CODEC_ID_ADPCM_IMA_WAV: - return (1024 - 4 * channels) * 8 / (4 * channels) + 1; + return (block_align - 4 * channels) * 8 / (4 * channels) + 1; case AV_CODEC_ID_ADPCM_MS: - return (1024 - 7 * channels) * 2 / channels + 2; + return (block_align - 7 * channels) * 2 / channels + 2; default: return 0; } @@ -107,6 +107,7 @@ static int caf_write_header(AVFormatContext *s) AVDictionaryEntry *t = NULL; unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, enc->codec_id); int64_t chunk_size = 0; + int frame_size = enc->frame_size; if (s->nb_streams != 1) { av_log(s, AV_LOG_ERROR, "CAF files have exactly one stream\n"); @@ -115,7 +116,6 @@ static int caf_write_header(AVFormatContext *s) switch (enc->codec_id) { case AV_CODEC_ID_AAC: - case AV_CODEC_ID_AC3: av_log(s, AV_LOG_ERROR, "muxing codec currently unsupported\n"); return AVERROR_PATCHWELCOME; } @@ -132,8 +132,6 @@ static int caf_write_header(AVFormatContext *s) case AV_CODEC_ID_PCM_F32BE: case AV_CODEC_ID_PCM_F64LE: case AV_CODEC_ID_PCM_F64BE: - case AV_CODEC_ID_PCM_ALAW: - case AV_CODEC_ID_PCM_MULAW: codec_tag = MKTAG('l','p','c','m'); } @@ -147,6 +145,9 @@ static int caf_write_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } + if (enc->codec_id != AV_CODEC_ID_MP3 || frame_size != 576) + frame_size = samples_per_packet(enc->codec_id, enc->channels, enc->block_align); + ffio_wfourcc(pb, "caff"); //< mFileType avio_wb16(pb, 1); //< mFileVersion avio_wb16(pb, 0); //< mFileFlags @@ -157,7 +158,7 @@ static int caf_write_header(AVFormatContext *s) avio_wl32(pb, codec_tag); //< mFormatID avio_wb32(pb, codec_flags(enc->codec_id)); //< mFormatFlags avio_wb32(pb, enc->block_align); //< mBytesPerPacket - avio_wb32(pb, samples_per_packet(enc->codec_id, enc->channels)); //< mFramesPerPacket + avio_wb32(pb, frame_size); //< mFramesPerPacket avio_wb32(pb, enc->channels); //< mChannelsPerFrame avio_wb32(pb, av_get_bits_per_sample(enc->codec_id)); //< mBitsPerChannel @@ -258,7 +259,7 @@ static int caf_write_trailer(AVFormatContext *s) ffio_wfourcc(pb, "pakt"); avio_wb64(pb, caf->size_entries_used + 24); avio_wb64(pb, caf->packets); ///< mNumberPackets - avio_wb64(pb, caf->packets * samples_per_packet(enc->codec_id, enc->channels)); ///< mNumberValidFrames + avio_wb64(pb, caf->packets * samples_per_packet(enc->codec_id, enc->channels, enc->block_align)); ///< mNumberValidFrames avio_wb32(pb, 0); ///< mPrimingFrames avio_wb32(pb, 0); ///< mRemainderFrames avio_write(pb, caf->pkt_sizes, caf->size_entries_used); diff --git a/libavformat/cdg.c b/libavformat/cdg.c index 2d40d3dc5..baf37d4c6 100644 --- a/libavformat/cdg.c +++ b/libavformat/cdg.c @@ -26,6 +26,10 @@ #define CDG_COMMAND 0x09 #define CDG_MASK 0x3F +typedef struct CDGContext { + int got_first_packet; +} CDGContext; + static int read_header(AVFormatContext *s) { AVStream *vst; @@ -42,7 +46,9 @@ static int read_header(AVFormatContext *s) avpriv_set_pts_info(vst, 32, 1, 300); ret = avio_size(s->pb); - if (ret > 0) + if (ret < 0) { + av_log(s, AV_LOG_WARNING, "Cannot calculate duration as file size cannot be determined\n"); + } else vst->duration = (ret * vst->time_base.den) / (CDG_PACKET_SIZE * 300); return 0; @@ -50,6 +56,7 @@ static int read_header(AVFormatContext *s) static int read_packet(AVFormatContext *s, AVPacket *pkt) { + CDGContext *priv = s->priv_data; int ret; while (1) { @@ -59,6 +66,11 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) av_free_packet(pkt); } + if (!priv->got_first_packet) { + pkt->flags |= AV_PKT_FLAG_KEY; + priv->got_first_packet = 1; + } + pkt->stream_index = 0; pkt->dts= pkt->pts= pkt->pos / CDG_PACKET_SIZE; @@ -72,6 +84,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) AVInputFormat ff_cdg_demuxer = { .name = "cdg", .long_name = NULL_IF_CONFIG_SMALL("CD Graphics"), + .priv_data_size = sizeof(CDGContext), .read_header = read_header, .read_packet = read_packet, .flags = AVFMT_GENERIC_INDEX, diff --git a/libavformat/cinedec.c b/libavformat/cinedec.c new file mode 100644 index 000000000..372088495 --- /dev/null +++ b/libavformat/cinedec.c @@ -0,0 +1,301 @@ +/* + * Phanton Cine demuxer + * Copyright (c) 2010-2011 Peter Ross + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Phantom Cine demuxer + * @author Peter Ross + */ + +#include "libavutil/intreadwrite.h" +#include "libavcodec/bmp.h" +#include "avformat.h" +#include "internal.h" + +typedef struct { + uint64_t pts; +} CineDemuxContext; + +/** Compression */ +enum { + CC_RGB = 0, /**< Gray */ + CC_LEAD = 1, /**< LEAD (M)JPEG */ + CC_UNINT = 2 /**< Uninterpolated color image (CFA field indicates color ordering) */ +}; + +/** Color Filter Array */ +enum { + CFA_NONE = 0, /**< GRAY */ + CFA_VRI = 1, /**< GBRG/RGGB */ + CFA_VRIV6 = 2, /**< BGGR/GRBG */ + CFA_BAYER = 3, /**< GB/RG */ + CFA_BAYERFLIP = 4, /**< RG/GB */ + + CFA_TLGRAY = 0x80000000, + CFA_TRGRAY = 0x40000000, + CFA_BLGRAY = 0x20000000, + CFA_BRGRAY = 0x10000000 +}; + +static int cine_read_probe(AVProbeData *p) +{ + int HeaderSize; + if (p->buf[0] == 'C' && p->buf[1] == 'I' && // Type + (HeaderSize = AV_RL16(p->buf + 2)) >= 0x2C && // HeaderSize + AV_RL16(p->buf + 4) <= CC_UNINT && // Compression + AV_RL16(p->buf + 6) <= 1 && // Version + AV_RL32(p->buf + 20) && // ImageCount + AV_RL32(p->buf + 24) >= HeaderSize && // OffImageHeader + AV_RL32(p->buf + 28) >= HeaderSize && // OffSetup + AV_RL32(p->buf + 32) >= HeaderSize) // OffImageOffsets + return AVPROBE_SCORE_MAX; + return 0; +} + +static int set_metadata_int(AVDictionary **dict, const char *key, int value) +{ + if (value) { + char buf[64]; + snprintf(buf, sizeof(buf), "%i", value); + return av_dict_set(dict, key, buf, 0); + } + return 0; +} + +static int cine_read_header(AVFormatContext *avctx) +{ + AVIOContext *pb = avctx->pb; + AVStream *st; + unsigned int version, compression, offImageHeader, offSetup, offImageOffsets, biBitCount, length, CFA; + int vflip; + char *description; + uint64_t i; + + st = avformat_new_stream(avctx, NULL); + if (!st) + return AVERROR(ENOMEM); + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = AV_CODEC_ID_RAWVIDEO; + st->codec->codec_tag = 0; + + /* CINEFILEHEADER structure */ + avio_skip(pb, 4); // Type, Headersize + + compression = avio_rl16(pb); + version = avio_rl16(pb); + if (version != 1) { + avpriv_request_sample(avctx, "uknown version %i", version); + return AVERROR_INVALIDDATA; + } + + avio_skip(pb, 12); // FirstMovieImage, TotalImageCount, FirstImageNumber + + st->duration = avio_rl32(pb); + offImageHeader = avio_rl32(pb); + offSetup = avio_rl32(pb); + offImageOffsets = avio_rl32(pb); + + avio_skip(pb, 8); // TriggerTime + + /* BITMAPINFOHEADER structure */ + avio_seek(pb, offImageHeader, SEEK_SET); + avio_skip(pb, 4); //biSize + st->codec->width = avio_rl32(pb); + st->codec->height = avio_rl32(pb); + + if (avio_rl16(pb) != 1) // biPlanes + return AVERROR_INVALIDDATA; + + biBitCount = avio_rl16(pb); + if (biBitCount != 8 && biBitCount != 16 && biBitCount != 24 && biBitCount != 48) { + avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount); + return AVERROR_INVALIDDATA; + } + + switch (avio_rl32(pb)) { + case BMP_RGB: + vflip = 0; + break; + case 0x100: /* BI_PACKED */ + st->codec->codec_tag = MKTAG('B', 'I', 'T', 0); + vflip = 1; + break; + default: + avpriv_request_sample(avctx, "unknown bitmap compression"); + return AVERROR_INVALIDDATA; + } + + avio_skip(pb, 4); // biSizeImage + + /* parse SETUP structure */ + avio_seek(pb, offSetup, SEEK_SET); + avio_skip(pb, 140); // FrameRatae16 .. descriptionOld + if (avio_rl16(pb) != 0x5453) + return AVERROR_INVALIDDATA; + length = avio_rl16(pb); + if (length < 0x163C) { + avpriv_request_sample(avctx, "short SETUP header"); + return AVERROR_INVALIDDATA; + } + + avio_skip(pb, 616); // Binning .. bFlipH + if (!avio_rl32(pb) ^ vflip) { + st->codec->extradata = av_strdup("BottomUp"); + st->codec->extradata_size = 9; + } + + avio_skip(pb, 4); // Grid + + avpriv_set_pts_info(st, 64, 1, avio_rl32(pb)); + + avio_skip(pb, 20); // Shutter .. bEnableColor + + set_metadata_int(&st->metadata, "camera_version", avio_rl32(pb)); + set_metadata_int(&st->metadata, "firmware_version", avio_rl32(pb)); + set_metadata_int(&st->metadata, "software_version", avio_rl32(pb)); + set_metadata_int(&st->metadata, "recording_timezone", avio_rl32(pb)); + + CFA = avio_rl32(pb); + + set_metadata_int(&st->metadata, "brightness", avio_rl32(pb)); + set_metadata_int(&st->metadata, "contrast", avio_rl32(pb)); + set_metadata_int(&st->metadata, "gamma", avio_rl32(pb)); + + avio_skip(pb, 72); // Reserved1 .. WBView + + st->codec->bits_per_coded_sample = avio_rl32(pb); + + if (compression == CC_RGB) { + if (biBitCount == 8) { + st->codec->pix_fmt = AV_PIX_FMT_GRAY8; + } else if (biBitCount == 16) { + st->codec->pix_fmt = AV_PIX_FMT_GRAY16LE; + } else if (biBitCount == 24) { + st->codec->pix_fmt = AV_PIX_FMT_BGR24; + } else if (biBitCount == 48) { + st->codec->pix_fmt = AV_PIX_FMT_BGR48LE; + } else { + avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount); + return AVERROR_INVALIDDATA; + } + } else if (compression == CC_UNINT) { + switch (CFA & 0xFFFFFF) { + case CFA_BAYER: + if (biBitCount == 8) { + st->codec->pix_fmt = AV_PIX_FMT_BAYER_GBRG8; + } else if (biBitCount == 16) { + st->codec->pix_fmt = AV_PIX_FMT_BAYER_GBRG16LE; + } else { + avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount); + return AVERROR_INVALIDDATA; + } + break; + case CFA_BAYERFLIP: + if (biBitCount == 8) { + st->codec->pix_fmt = AV_PIX_FMT_BAYER_RGGB8; + } else if (biBitCount == 16) { + st->codec->pix_fmt = AV_PIX_FMT_BAYER_RGGB16LE; + } else { + avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount); + return AVERROR_INVALIDDATA; + } + break; + default: + avpriv_request_sample(avctx, "unsupported Color Field Array (CFA) %i", CFA & 0xFFFFFF); + return AVERROR_INVALIDDATA; + } + } else { //CC_LEAD + avpriv_request_sample(avctx, "unsupported compression %i", compression); + return AVERROR_INVALIDDATA; + } + + avio_skip(pb, 696); // Conv8Min ... ImHeightAcq + +#define DESCRIPTION_SIZE 4096 + description = av_malloc(DESCRIPTION_SIZE + 1); + if (!description) + return AVERROR(ENOMEM); + i = avio_get_str(pb, DESCRIPTION_SIZE, description, DESCRIPTION_SIZE + 1); + if (i < DESCRIPTION_SIZE) + avio_skip(pb, DESCRIPTION_SIZE - i); + if (description[0]) + av_dict_set(&st->metadata, "description", description, AV_DICT_DONT_STRDUP_VAL); + else + av_free(description); + + /* parse image offsets */ + avio_seek(pb, offImageOffsets, SEEK_SET); + for (i = 0; i < st->duration; i++) + av_add_index_entry(st, avio_rl64(pb), i, 0, 0, AVINDEX_KEYFRAME); + + return 0; +} + +static int cine_read_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + CineDemuxContext *cine = avctx->priv_data; + AVStream *st = avctx->streams[0]; + AVIOContext *pb = avctx->pb; + int n, size, ret; + + if (cine->pts >= st->duration) + return AVERROR_EOF; + + avio_seek(pb, st->index_entries[cine->pts].pos, SEEK_SET); + n = avio_rl32(pb); + if (n < 8) + return AVERROR_INVALIDDATA; + avio_skip(pb, n - 8); + size = avio_rl32(pb); + + ret = av_get_packet(pb, pkt, size); + if (ret < 0) + return ret; + + pkt->pts = cine->pts++; + pkt->stream_index = 0; + pkt->flags |= AV_PKT_FLAG_KEY; + return 0; +} + +static int cine_read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags) +{ + CineDemuxContext *cine = avctx->priv_data; + + if ((flags & AVSEEK_FLAG_FRAME) || (flags & AVSEEK_FLAG_BYTE)) + return AVERROR(ENOSYS); + + if (!avctx->pb->seekable) + return AVERROR(EIO); + + cine->pts = timestamp; + return 0; +} + +AVInputFormat ff_cine_demuxer = { + .name = "cine", + .long_name = NULL_IF_CONFIG_SMALL("Phantom Cine"), + .priv_data_size = sizeof(CineDemuxContext), + .read_probe = cine_read_probe, + .read_header = cine_read_header, + .read_packet = cine_read_packet, + .read_seek = cine_read_seek, +}; diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 979499af0..4590dc592 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -18,17 +18,31 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" #include "avformat.h" #include "internal.h" #include "url.h" +typedef enum ConcatMatchMode { + MATCH_ONE_TO_ONE, + MATCH_EXACT_ID, +} ConcatMatchMode; + +typedef struct ConcatStream { + AVBitStreamFilterContext *bsf; + int out_stream_index; +} ConcatStream; + typedef struct { char *url; int64_t start_time; int64_t duration; + ConcatStream *streams; + int nb_streams; } ConcatFile; typedef struct { @@ -39,6 +53,8 @@ typedef struct { AVFormatContext *avf; int safe; int seekable; + ConcatMatchMode stream_match_mode; + unsigned auto_convert; } ConcatContext; static int concat_probe(AVProbeData *probe) @@ -85,18 +101,28 @@ static int add_file(AVFormatContext *avf, char *filename, ConcatFile **rfile, ConcatContext *cat = avf->priv_data; ConcatFile *file; char *url = NULL; - size_t url_len; + const char *proto; + size_t url_len, proto_len; int ret; if (cat->safe > 0 && !safe_filename(filename)) { av_log(avf, AV_LOG_ERROR, "Unsafe file name '%s'\n", filename); FAIL(AVERROR(EPERM)); } - url_len = strlen(avf->filename) + strlen(filename) + 16; - if (!(url = av_malloc(url_len))) - FAIL(AVERROR(ENOMEM)); - ff_make_absolute_url(url, url_len, avf->filename, filename); - av_freep(&filename); + + proto = avio_find_protocol_name(filename); + proto_len = proto ? strlen(proto) : 0; + if (!memcmp(filename, proto, proto_len) && + (filename[proto_len] == ':' || filename[proto_len] == ',')) { + url = filename; + filename = NULL; + } else { + url_len = strlen(avf->filename) + strlen(filename) + 16; + if (!(url = av_malloc(url_len))) + FAIL(AVERROR(ENOMEM)); + ff_make_absolute_url(url, url_len, avf->filename, filename); + av_freep(&filename); + } if (cat->nb_files >= *nb_files_alloc) { size_t n = FFMAX(*nb_files_alloc * 2, 16); @@ -124,6 +150,130 @@ fail: return ret; } +static int copy_stream_props(AVStream *st, AVStream *source_st) +{ + int ret; + + if (st->codec->codec_id || !source_st->codec->codec_id) { + if (st->codec->extradata_size < source_st->codec->extradata_size) { + ret = ff_alloc_extradata(st->codec, + source_st->codec->extradata_size); + if (ret < 0) + return ret; + } + memcpy(st->codec->extradata, source_st->codec->extradata, + source_st->codec->extradata_size); + return 0; + } + if ((ret = avcodec_copy_context(st->codec, source_st->codec)) < 0) + return ret; + st->r_frame_rate = source_st->r_frame_rate; + st->avg_frame_rate = source_st->avg_frame_rate; + st->time_base = source_st->time_base; + st->sample_aspect_ratio = source_st->sample_aspect_ratio; + return 0; +} + +static int detect_stream_specific(AVFormatContext *avf, int idx) +{ + ConcatContext *cat = avf->priv_data; + AVStream *st = cat->avf->streams[idx]; + ConcatStream *cs = &cat->cur_file->streams[idx]; + AVBitStreamFilterContext *bsf; + + if (cat->auto_convert && st->codec->codec_id == AV_CODEC_ID_H264 && + (st->codec->extradata_size < 4 || AV_RB32(st->codec->extradata) != 1)) { + av_log(cat->avf, AV_LOG_INFO, + "Auto-inserting h264_mp4toannexb bitstream filter\n"); + if (!(bsf = av_bitstream_filter_init("h264_mp4toannexb"))) { + av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb bitstream filter " + "required for H.264 streams\n"); + return AVERROR_BSF_NOT_FOUND; + } + cs->bsf = bsf; + } + return 0; +} + +static int match_streams_one_to_one(AVFormatContext *avf) +{ + ConcatContext *cat = avf->priv_data; + AVStream *st; + int i, ret; + + for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) { + if (i < avf->nb_streams) { + st = avf->streams[i]; + } else { + if (!(st = avformat_new_stream(avf, NULL))) + return AVERROR(ENOMEM); + } + if ((ret = copy_stream_props(st, cat->avf->streams[i])) < 0) + return ret; + cat->cur_file->streams[i].out_stream_index = i; + } + return 0; +} + +static int match_streams_exact_id(AVFormatContext *avf) +{ + ConcatContext *cat = avf->priv_data; + AVStream *st; + int i, j, ret; + + for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) { + st = cat->avf->streams[i]; + for (j = 0; j < avf->nb_streams; j++) { + if (avf->streams[j]->id == st->id) { + av_log(avf, AV_LOG_VERBOSE, + "Match slave stream #%d with stream #%d id 0x%x\n", + i, j, st->id); + if ((ret = copy_stream_props(avf->streams[j], st)) < 0) + return ret; + cat->cur_file->streams[i].out_stream_index = j; + } + } + } + return 0; +} + +static int match_streams(AVFormatContext *avf) +{ + ConcatContext *cat = avf->priv_data; + ConcatStream *map; + int i, ret; + + if (cat->cur_file->nb_streams >= cat->avf->nb_streams) + return 0; + map = av_realloc(cat->cur_file->streams, + cat->avf->nb_streams * sizeof(*map)); + if (!map) + return AVERROR(ENOMEM); + cat->cur_file->streams = map; + memset(map + cat->cur_file->nb_streams, 0, + (cat->avf->nb_streams - cat->cur_file->nb_streams) * sizeof(*map)); + + for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) + map[i].out_stream_index = -1; + switch (cat->stream_match_mode) { + case MATCH_ONE_TO_ONE: + ret = match_streams_one_to_one(avf); + break; + case MATCH_EXACT_ID: + ret = match_streams_exact_id(avf); + break; + default: + ret = AVERROR_BUG; + } + if (ret < 0) + return ret; + for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) + if ((ret = detect_stream_specific(avf, i)) < 0) + return ret; + cat->cur_file->nb_streams = cat->avf->nb_streams; + return 0; +} + static int open_file(AVFormatContext *avf, unsigned fileno) { ConcatContext *cat = avf->priv_data; @@ -149,6 +299,8 @@ static int open_file(AVFormatContext *avf, unsigned fileno) file->start_time = !fileno ? 0 : cat->files[fileno - 1].start_time + cat->files[fileno - 1].duration; + if ((ret = match_streams(avf)) < 0) + return ret; return 0; } @@ -159,8 +311,10 @@ static int concat_read_close(AVFormatContext *avf) if (cat->avf) avformat_close_input(&cat->avf); - for (i = 0; i < cat->nb_files; i++) + for (i = 0; i < cat->nb_files; i++) { av_freep(&cat->files[i].url); + av_freep(&cat->files[i].streams); + } av_freep(&cat->files); return 0; } @@ -173,7 +327,6 @@ static int concat_read_header(AVFormatContext *avf) int ret, line = 0, i; unsigned nb_files_alloc = 0; ConcatFile *file = NULL; - AVStream *st, *source_st; int64_t time = 0; while (1) { @@ -207,6 +360,17 @@ static int concat_read_header(AVFormatContext *avf) FAIL(ret); } file->duration = dur; + } else if (!strcmp(keyword, "stream")) { + if (!avformat_new_stream(avf, NULL)) + FAIL(AVERROR(ENOMEM)); + } else if (!strcmp(keyword, "exact_stream_id")) { + if (!avf->nb_streams) { + av_log(avf, AV_LOG_ERROR, "Line %d: exact_stream_id without stream\n", + line); + FAIL(AVERROR_INVALIDDATA); + } + avf->streams[avf->nb_streams - 1]->id = + strtol(get_keyword(&cursor), NULL, 0); } else if (!strcmp(keyword, "ffconcat")) { char *ver_kw = get_keyword(&cursor); char *ver_val = get_keyword(&cursor); @@ -241,20 +405,10 @@ static int concat_read_header(AVFormatContext *avf) cat->seekable = 1; } + cat->stream_match_mode = avf->nb_streams ? MATCH_EXACT_ID : + MATCH_ONE_TO_ONE; if ((ret = open_file(avf, 0)) < 0) FAIL(ret); - for (i = 0; i < cat->avf->nb_streams; i++) { - if (!(st = avformat_new_stream(avf, NULL))) - FAIL(AVERROR(ENOMEM)); - source_st = cat->avf->streams[i]; - if ((ret = avcodec_copy_context(st->codec, source_st->codec)) < 0) - FAIL(ret); - st->r_frame_rate = source_st->r_frame_rate; - st->avg_frame_rate = source_st->avg_frame_rate; - st->time_base = source_st->time_base; - st->sample_aspect_ratio = source_st->sample_aspect_ratio; - } - return 0; fail: @@ -275,18 +429,75 @@ static int open_next_file(AVFormatContext *avf) return open_file(avf, fileno); } +static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt) +{ + AVStream *st = avf->streams[cs->out_stream_index]; + AVBitStreamFilterContext *bsf; + AVPacket pkt2; + int ret; + + av_assert0(cs->out_stream_index >= 0); + for (bsf = cs->bsf; bsf; bsf = bsf->next) { + pkt2 = *pkt; + ret = av_bitstream_filter_filter(bsf, st->codec, NULL, + &pkt2.data, &pkt2.size, + pkt->data, pkt->size, + !!(pkt->flags & AV_PKT_FLAG_KEY)); + if (ret < 0) { + av_packet_unref(pkt); + return ret; + } + av_assert0(pkt2.buf); + if (ret == 0 && pkt2.data != pkt->data) { + if ((ret = av_copy_packet(&pkt2, pkt)) < 0) { + av_free(pkt2.data); + return ret; + } + ret = 1; + } + if (ret > 0) { + av_free_packet(pkt); + pkt2.buf = av_buffer_create(pkt2.data, pkt2.size, + av_buffer_default_free, NULL, 0); + if (!pkt2.buf) { + av_free(pkt2.data); + return AVERROR(ENOMEM); + } + } + *pkt = pkt2; + } + return 0; +} + static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) { ConcatContext *cat = avf->priv_data; int ret; int64_t delta; + ConcatStream *cs; while (1) { - if ((ret = av_read_frame(cat->avf, pkt)) != AVERROR_EOF || - (ret = open_next_file(avf)) < 0) - break; + ret = av_read_frame(cat->avf, pkt); + if (ret == AVERROR_EOF) { + if ((ret = open_next_file(avf)) < 0) + return ret; + continue; + } + if (ret < 0) + return ret; + if ((ret = match_streams(avf)) < 0) { + av_packet_unref(pkt); + return ret; + } + cs = &cat->cur_file->streams[pkt->stream_index]; + if (cs->out_stream_index < 0) { + av_packet_unref(pkt); + continue; + } + pkt->stream_index = cs->out_stream_index; + break; } - if (ret < 0) + if ((ret = filter_packet(avf, cs, pkt))) return ret; delta = av_rescale_q(cat->cur_file->start_time - cat->avf->start_time, @@ -394,6 +605,8 @@ static int concat_seek(AVFormatContext *avf, int stream, static const AVOption options[] = { { "safe", "enable safe mode", OFFSET(safe), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, DEC }, + { "auto_convert", "automatically convert bitstream format", + OFFSET(auto_convert), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC }, { NULL } }; diff --git a/libavformat/crcenc.c b/libavformat/crcenc.c index ac0638037..3fdfea520 100644 --- a/libavformat/crcenc.c +++ b/libavformat/crcenc.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/adler32.h" #include "avformat.h" @@ -48,7 +50,7 @@ static int crc_write_trailer(struct AVFormatContext *s) CRCState *crc = s->priv_data; char buf[64]; - snprintf(buf, sizeof(buf), "CRC=0x%08x\n", crc->crcval); + snprintf(buf, sizeof(buf), "CRC=0x%08"PRIx32"\n", crc->crcval); avio_write(s->pb, buf, strlen(buf)); return 0; diff --git a/libavformat/daud.c b/libavformat/dauddec.c similarity index 66% rename from libavformat/daud.c rename to libavformat/dauddec.c index 6983785f3..30d1200c0 100644 --- a/libavformat/daud.c +++ b/libavformat/dauddec.c @@ -50,28 +50,6 @@ static int daud_packet(AVFormatContext *s, AVPacket *pkt) { return ret; } -static int daud_write_header(struct AVFormatContext *s) -{ - AVCodecContext *codec = s->streams[0]->codec; - if (codec->channels!=6 || codec->sample_rate!=96000) - return -1; - return 0; -} - -static int daud_write_packet(struct AVFormatContext *s, AVPacket *pkt) -{ - if (pkt->size > 65535) { - av_log(s, AV_LOG_ERROR, - "Packet size too large for s302m. (%d > 65535)\n", pkt->size); - return -1; - } - avio_wb16(s->pb, pkt->size); - avio_wb16(s->pb, 0x8010); // unknown - avio_write(s->pb, pkt->data, pkt->size); - return 0; -} - -#if CONFIG_DAUD_DEMUXER AVInputFormat ff_daud_demuxer = { .name = "daud", .long_name = NULL_IF_CONFIG_SMALL("D-Cinema audio"), @@ -79,17 +57,3 @@ AVInputFormat ff_daud_demuxer = { .read_packet = daud_packet, .extensions = "302,daud", }; -#endif - -#if CONFIG_DAUD_MUXER -AVOutputFormat ff_daud_muxer = { - .name = "daud", - .long_name = NULL_IF_CONFIG_SMALL("D-Cinema audio"), - .extensions = "302", - .audio_codec = AV_CODEC_ID_PCM_S24DAUD, - .video_codec = AV_CODEC_ID_NONE, - .write_header = daud_write_header, - .write_packet = daud_write_packet, - .flags = AVFMT_NOTIMESTAMPS, -}; -#endif diff --git a/libavformat/daudenc.c b/libavformat/daudenc.c new file mode 100644 index 000000000..99b18d35a --- /dev/null +++ b/libavformat/daudenc.c @@ -0,0 +1,54 @@ +/* + * D-Cinema audio muxer + * Copyright (c) 2005 Reimar Döffinger + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" + +static int daud_write_header(struct AVFormatContext *s) +{ + AVCodecContext *codec = s->streams[0]->codec; + if (codec->channels!=6 || codec->sample_rate!=96000) + return -1; + return 0; +} + +static int daud_write_packet(struct AVFormatContext *s, AVPacket *pkt) +{ + if (pkt->size > 65535) { + av_log(s, AV_LOG_ERROR, + "Packet size too large for s302m. (%d > 65535)\n", pkt->size); + return -1; + } + avio_wb16(s->pb, pkt->size); + avio_wb16(s->pb, 0x8010); // unknown + avio_write(s->pb, pkt->data, pkt->size); + return 0; +} + +AVOutputFormat ff_daud_muxer = { + .name = "daud", + .long_name = NULL_IF_CONFIG_SMALL("D-Cinema audio"), + .extensions = "302", + .audio_codec = AV_CODEC_ID_PCM_S24DAUD, + .video_codec = AV_CODEC_ID_NONE, + .write_header = daud_write_header, + .write_packet = daud_write_packet, + .flags = AVFMT_NOTIMESTAMPS, +}; diff --git a/libavformat/dfa.c b/libavformat/dfa.c index 9cd13e24d..dfa0590e2 100644 --- a/libavformat/dfa.c +++ b/libavformat/dfa.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/intreadwrite.h" #include "avformat.h" #include "internal.h" @@ -98,12 +100,13 @@ static int dfa_read_packet(AVFormatContext *s, AVPacket *pkt) first = 0; frame_size = AV_RL32(pkt->data + pkt->size - 8); if (frame_size > INT_MAX - 4) { - av_log(s, AV_LOG_ERROR, "Too large chunk size: %d\n", frame_size); + av_log(s, AV_LOG_ERROR, "Too large chunk size: %"PRIu32"\n", frame_size); return AVERROR(EIO); } if (AV_RL32(pkt->data + pkt->size - 12) == MKTAG('E', 'O', 'F', 'R')) { if (frame_size) { - av_log(s, AV_LOG_WARNING, "skipping %d bytes of end-of-frame marker chunk\n", + av_log(s, AV_LOG_WARNING, + "skipping %"PRIu32" bytes of end-of-frame marker chunk\n", frame_size); avio_skip(pb, frame_size); } diff --git a/libavformat/dsfdec.c b/libavformat/dsfdec.c new file mode 100644 index 000000000..ae198b2e9 --- /dev/null +++ b/libavformat/dsfdec.c @@ -0,0 +1,159 @@ +/* + * DSD Stream File (DSF) demuxer + * Copyright (c) 2014 Peter Ross + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "internal.h" +#include "id3v2.h" + +typedef struct { + uint64_t data_end; +} DSFContext; + +static int dsf_probe(AVProbeData *p) +{ + if (p->buf_size < 12 || memcmp(p->buf, "DSD ", 4) || AV_RL64(p->buf + 4) != 28) + return 0; + return AVPROBE_SCORE_MAX; +} + +static const uint64_t dsf_channel_layout[] = { + 0, + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_QUAD, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_5POINT1_BACK, +}; + +static void read_id3(AVFormatContext *s, uint64_t id3pos) +{ + ID3v2ExtraMeta *id3v2_extra_meta = NULL; + if (avio_seek(s->pb, id3pos, SEEK_SET) < 0) + return; + + ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, 0); + if (id3v2_extra_meta) + ff_id3v2_parse_apic(s, &id3v2_extra_meta); + ff_id3v2_free_extra_meta(&id3v2_extra_meta); +} + +static int dsf_read_header(AVFormatContext *s) +{ + DSFContext *dsf = s->priv_data; + AVIOContext *pb = s->pb; + AVStream *st; + uint64_t id3pos; + unsigned int channel_type; + + avio_skip(pb, 4); + if (avio_rl64(pb) != 28) + return AVERROR_INVALIDDATA; + + /* create primary stream before any id3 coverart streams */ + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + avio_skip(pb, 8); + id3pos = avio_rl64(pb); + if (pb->seekable) { + read_id3(s, id3pos); + avio_seek(pb, 28, SEEK_SET); + } + + /* fmt chunk */ + + if (avio_rl32(pb) != MKTAG('f', 'm', 't', ' ') || avio_rl64(pb) != 52) + return AVERROR_INVALIDDATA; + + if (avio_rl32(pb) != 1) { + avpriv_request_sample(s, "unknown format version"); + return AVERROR_INVALIDDATA; + } + + if (avio_rl32(pb)) { + avpriv_request_sample(s, "unknown format id"); + return AVERROR_INVALIDDATA; + } + + channel_type = avio_rl32(pb); + if (channel_type < FF_ARRAY_ELEMS(dsf_channel_layout)) + st->codec->channel_layout = dsf_channel_layout[channel_type]; + if (!st->codec->channel_layout) + avpriv_request_sample(s, "channel type %i", channel_type); + + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->channels = avio_rl32(pb); + st->codec->sample_rate = avio_rl32(pb) / 8; + + switch(avio_rl32(pb)) { + case 1: st->codec->codec_id = AV_CODEC_ID_DSD_LSBF_PLANAR; break; + case 8: st->codec->codec_id = AV_CODEC_ID_DSD_MSBF_PLANAR; break; + default: + avpriv_request_sample(s, "unknown most significant bit"); + return AVERROR_INVALIDDATA; + } + + avio_skip(pb, 8); + st->codec->block_align = avio_rl32(pb); + if (st->codec->block_align > INT_MAX / st->codec->channels) { + avpriv_request_sample(s, "block_align overflow"); + return AVERROR_INVALIDDATA; + } + st->codec->block_align *= st->codec->channels; + avio_skip(pb, 4); + + /* data chunk */ + + dsf->data_end = avio_tell(pb); + if (avio_rl32(pb) != MKTAG('d', 'a', 't', 'a')) + return AVERROR_INVALIDDATA; + dsf->data_end += avio_rl64(pb); + + return 0; +} + +static int dsf_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + DSFContext *dsf = s->priv_data; + AVIOContext *pb = s->pb; + AVStream *st = s->streams[0]; + int64_t pos = avio_tell(pb); + + if (pos >= dsf->data_end) + return AVERROR_EOF; + + pkt->stream_index = 0; + return av_get_packet(pb, pkt, FFMIN(dsf->data_end - pos, st->codec->block_align)); +} + +AVInputFormat ff_dsf_demuxer = { + .name = "dsf", + .long_name = NULL_IF_CONFIG_SMALL("DSD Stream File (DSF)"), + .priv_data_size = sizeof(DSFContext), + .read_probe = dsf_probe, + .read_header = dsf_read_header, + .read_packet = dsf_read_packet, + .flags = AVFMT_GENERIC_INDEX | AVFMT_NO_BYTE_SEEK, +}; diff --git a/libavformat/dump.c b/libavformat/dump.c new file mode 100644 index 000000000..8beabce59 --- /dev/null +++ b/libavformat/dump.c @@ -0,0 +1,446 @@ +/* + * Various pretty-printing functions for use within FFmpeg + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/display.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/log.h" +#include "libavutil/mathematics.h" +#include "libavutil/avstring.h" +#include "libavutil/replaygain.h" + +#include "avformat.h" + +#define HEXDUMP_PRINT(...) \ + do { \ + if (!f) \ + av_log(avcl, level, __VA_ARGS__); \ + else \ + fprintf(f, __VA_ARGS__); \ + } while (0) + +static void hex_dump_internal(void *avcl, FILE *f, int level, + const uint8_t *buf, int size) +{ + int len, i, j, c; + + for (i = 0; i < size; i += 16) { + len = size - i; + if (len > 16) + len = 16; + HEXDUMP_PRINT("%08x ", i); + for (j = 0; j < 16; j++) { + if (j < len) + HEXDUMP_PRINT(" %02x", buf[i + j]); + else + HEXDUMP_PRINT(" "); + } + HEXDUMP_PRINT(" "); + for (j = 0; j < len; j++) { + c = buf[i + j]; + if (c < ' ' || c > '~') + c = '.'; + HEXDUMP_PRINT("%c", c); + } + HEXDUMP_PRINT("\n"); + } +} + +void av_hex_dump(FILE *f, const uint8_t *buf, int size) +{ + hex_dump_internal(NULL, f, 0, buf, size); +} + +void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size) +{ + hex_dump_internal(avcl, NULL, level, buf, size); +} + +static void pkt_dump_internal(void *avcl, FILE *f, int level, const AVPacket *pkt, + int dump_payload, AVRational time_base) +{ + HEXDUMP_PRINT("stream #%d:\n", pkt->stream_index); + HEXDUMP_PRINT(" keyframe=%d\n", (pkt->flags & AV_PKT_FLAG_KEY) != 0); + HEXDUMP_PRINT(" duration=%0.3f\n", pkt->duration * av_q2d(time_base)); + /* DTS is _always_ valid after av_read_frame() */ + HEXDUMP_PRINT(" dts="); + if (pkt->dts == AV_NOPTS_VALUE) + HEXDUMP_PRINT("N/A"); + else + HEXDUMP_PRINT("%0.3f", pkt->dts * av_q2d(time_base)); + /* PTS may not be known if B-frames are present. */ + HEXDUMP_PRINT(" pts="); + if (pkt->pts == AV_NOPTS_VALUE) + HEXDUMP_PRINT("N/A"); + else + HEXDUMP_PRINT("%0.3f", pkt->pts * av_q2d(time_base)); + HEXDUMP_PRINT("\n"); + HEXDUMP_PRINT(" size=%d\n", pkt->size); + if (dump_payload) + av_hex_dump(f, pkt->data, pkt->size); +} + +void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st) +{ + pkt_dump_internal(NULL, f, 0, pkt, dump_payload, st->time_base); +} + +void av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload, + const AVStream *st) +{ + pkt_dump_internal(avcl, NULL, level, pkt, dump_payload, st->time_base); +} + + +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); + else if (v % (100 * 1000)) + av_log(NULL, AV_LOG_INFO, ", %1.0f %s", d, postfix); + else + av_log(NULL, AV_LOG_INFO, ", %1.0fk %s", d / 1000, postfix); +} + +static void dump_metadata(void *ctx, AVDictionary *m, const char *indent) +{ + if (m && !(av_dict_count(m) == 1 && av_dict_get(m, "language", NULL, 0))) { + AVDictionaryEntry *tag = NULL; + + av_log(ctx, AV_LOG_INFO, "%sMetadata:\n", indent); + while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) + if (strcmp("language", tag->key)) { + const char *p = tag->value; + av_log(ctx, AV_LOG_INFO, + "%s %-16s: ", indent, tag->key); + while (*p) { + char tmp[256]; + size_t len = strcspn(p, "\x8\xa\xb\xc\xd"); + av_strlcpy(tmp, p, FFMIN(sizeof(tmp), len+1)); + av_log(ctx, AV_LOG_INFO, "%s", tmp); + p += len; + if (*p == 0xd) av_log(ctx, AV_LOG_INFO, " "); + if (*p == 0xa) av_log(ctx, AV_LOG_INFO, "\n%s %-16s: ", indent, ""); + if (*p) p++; + } + av_log(ctx, AV_LOG_INFO, "\n"); + } + } +} + +/* param change side data*/ +static void dump_paramchange(void *ctx, AVPacketSideData *sd) +{ + int size = sd->size; + const uint8_t *data = sd->data; + uint32_t flags, channels, sample_rate, width, height; + uint64_t layout; + + if (!data || sd->size < 4) + goto fail; + + flags = AV_RL32(data); + data += 4; + size -= 4; + + if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) { + if (size < 4) + goto fail; + channels = AV_RL32(data); + data += 4; + size -= 4; + av_log(ctx, AV_LOG_INFO, "channel count %d, ", channels); + } + if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) { + if (size < 8) + goto fail; + layout = AV_RL64(data); + data += 8; + size -= 8; + av_log(ctx, AV_LOG_INFO, + "channel layout: %s, ", av_get_channel_name(layout)); + } + if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) { + if (size < 4) + goto fail; + sample_rate = AV_RL32(data); + data += 4; + size -= 4; + av_log(ctx, AV_LOG_INFO, "sample_rate %d, ", sample_rate); + } + if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) { + if (size < 8) + goto fail; + width = AV_RL32(data); + data += 4; + size -= 4; + height = AV_RL32(data); + data += 4; + size -= 4; + av_log(ctx, AV_LOG_INFO, "width %d height %d", width, height); + } + + return; +fail: + av_log(ctx, AV_LOG_INFO, "unknown param"); +} + +/* replaygain side data*/ +static void print_gain(void *ctx, const char *str, int32_t gain) +{ + av_log(ctx, AV_LOG_INFO, "%s - ", str); + if (gain == INT32_MIN) + av_log(ctx, AV_LOG_INFO, "unknown"); + else + av_log(ctx, AV_LOG_INFO, "%f", gain / 100000.0f); + av_log(ctx, AV_LOG_INFO, ", "); +} + +static void print_peak(void *ctx, const char *str, uint32_t peak) +{ + av_log(ctx, AV_LOG_INFO, "%s - ", str); + if (!peak) + av_log(ctx, AV_LOG_INFO, "unknown"); + else + av_log(ctx, AV_LOG_INFO, "%f", (float) peak / UINT32_MAX); + av_log(ctx, AV_LOG_INFO, ", "); +} + +static void dump_replaygain(void *ctx, AVPacketSideData *sd) +{ + AVReplayGain *rg; + + if (sd->size < sizeof(*rg)) { + av_log(ctx, AV_LOG_INFO, "invalid data"); + return; + } + rg = (AVReplayGain*)sd->data; + + print_gain(ctx, "track gain", rg->track_gain); + print_peak(ctx, "track peak", rg->track_peak); + print_gain(ctx, "album gain", rg->album_gain); + print_peak(ctx, "album peak", rg->album_peak); +} + +static void dump_sidedata(void *ctx, AVStream *st, const char *indent) +{ + int i; + + if (st->nb_side_data) + av_log(ctx, AV_LOG_INFO, "%sSide data:\n", indent); + + for (i = 0; i < st->nb_side_data; i++) { + AVPacketSideData sd = st->side_data[i]; + av_log(ctx, AV_LOG_INFO, "%s ", indent); + + switch (sd.type) { + case AV_PKT_DATA_PALETTE: + av_log(ctx, AV_LOG_INFO, "palette"); + break; + case AV_PKT_DATA_NEW_EXTRADATA: + av_log(ctx, AV_LOG_INFO, "new extradata"); + break; + case AV_PKT_DATA_PARAM_CHANGE: + av_log(ctx, AV_LOG_INFO, "paramchange: "); + dump_paramchange(ctx, &sd); + break; + case AV_PKT_DATA_H263_MB_INFO: + av_log(ctx, AV_LOG_INFO, "h263 macroblock info"); + break; + case AV_PKT_DATA_REPLAYGAIN: + av_log(ctx, AV_LOG_INFO, "replaygain: "); + dump_replaygain(ctx, &sd); + break; + case AV_PKT_DATA_DISPLAYMATRIX: + av_log(ctx, AV_LOG_INFO, "displaymatrix: rotation of %.2f degrees", + av_display_rotation_get((int32_t *)sd.data)); + break; + default: + av_log(ctx, AV_LOG_WARNING, + "unknown side data type %d (%d bytes)", sd.type, sd.size); + break; + } + + av_log(ctx, AV_LOG_INFO, "\n"); + } +} + +/* "user interface" functions */ +static void dump_stream_format(AVFormatContext *ic, int i, + int index, int is_output) +{ + char buf[256]; + 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); + + avcodec_string(buf, sizeof(buf), st->codec, is_output); + av_log(NULL, AV_LOG_INFO, " Stream #%d:%d", index, i); + + /* the pid is an important information, so we display it */ + /* XXX: add a generic system */ + if (flags & AVFMT_SHOW_IDS) + av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id); + if (lang) + av_log(NULL, AV_LOG_INFO, "(%s)", lang->value); + av_log(NULL, AV_LOG_DEBUG, ", %d, %d/%d", st->codec_info_nb_frames, + 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)) { + 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, + 1024 * 1024); + av_log(NULL, AV_LOG_INFO, ", SAR %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 FF_API_R_FRAME_RATE + if (st->r_frame_rate.den && st->r_frame_rate.num) + print_fps(av_q2d(st->r_frame_rate), "tbr"); +#endif + if (st->time_base.den && st->time_base.num) + 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) + av_log(NULL, AV_LOG_INFO, " (default)"); + if (st->disposition & AV_DISPOSITION_DUB) + av_log(NULL, AV_LOG_INFO, " (dub)"); + if (st->disposition & AV_DISPOSITION_ORIGINAL) + av_log(NULL, AV_LOG_INFO, " (original)"); + if (st->disposition & AV_DISPOSITION_COMMENT) + av_log(NULL, AV_LOG_INFO, " (comment)"); + if (st->disposition & AV_DISPOSITION_LYRICS) + av_log(NULL, AV_LOG_INFO, " (lyrics)"); + if (st->disposition & AV_DISPOSITION_KARAOKE) + av_log(NULL, AV_LOG_INFO, " (karaoke)"); + if (st->disposition & AV_DISPOSITION_FORCED) + av_log(NULL, AV_LOG_INFO, " (forced)"); + if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED) + av_log(NULL, AV_LOG_INFO, " (hearing impaired)"); + if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED) + av_log(NULL, AV_LOG_INFO, " (visual impaired)"); + if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS) + av_log(NULL, AV_LOG_INFO, " (clean effects)"); + av_log(NULL, AV_LOG_INFO, "\n"); + + dump_metadata(NULL, st->metadata, " "); + + dump_sidedata(NULL, st, " "); +} + +void av_dump_format(AVFormatContext *ic, int index, + const char *url, int is_output) +{ + int i; + uint8_t *printed = ic->nb_streams ? av_mallocz(ic->nb_streams) : NULL; + if (ic->nb_streams && !printed) + return; + + av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n", + is_output ? "Output" : "Input", + index, + is_output ? ic->oformat->name : ic->iformat->name, + is_output ? "to" : "from", url); + dump_metadata(NULL, ic->metadata, " "); + + if (!is_output) { + av_log(NULL, AV_LOG_INFO, " Duration: "); + if (ic->duration != AV_NOPTS_VALUE) { + int hours, mins, secs, us; + int64_t duration = ic->duration + 5000; + secs = duration / AV_TIME_BASE; + us = duration % AV_TIME_BASE; + mins = secs / 60; + secs %= 60; + hours = mins / 60; + mins %= 60; + av_log(NULL, AV_LOG_INFO, "%02d:%02d:%02d.%02d", hours, mins, secs, + (100 * us) / AV_TIME_BASE); + } else { + av_log(NULL, AV_LOG_INFO, "N/A"); + } + if (ic->start_time != AV_NOPTS_VALUE) { + int secs, us; + av_log(NULL, AV_LOG_INFO, ", start: "); + secs = ic->start_time / AV_TIME_BASE; + us = abs(ic->start_time % AV_TIME_BASE); + av_log(NULL, AV_LOG_INFO, "%d.%06d", + secs, (int) av_rescale(us, 1000000, AV_TIME_BASE)); + } + av_log(NULL, AV_LOG_INFO, ", bitrate: "); + if (ic->bit_rate) + av_log(NULL, AV_LOG_INFO, "%d kb/s", ic->bit_rate / 1000); + else + av_log(NULL, AV_LOG_INFO, "N/A"); + av_log(NULL, AV_LOG_INFO, "\n"); + } + + for (i = 0; i < ic->nb_chapters; i++) { + AVChapter *ch = ic->chapters[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, + "end %f\n", ch->end * av_q2d(ch->time_base)); + + dump_metadata(NULL, ch->metadata, " "); + } + + if (ic->nb_programs) { + int j, k, total = 0; + for (j = 0; j < ic->nb_programs; j++) { + AVDictionaryEntry *name = av_dict_get(ic->programs[j]->metadata, + "name", NULL, 0); + av_log(NULL, AV_LOG_INFO, " Program %d %s\n", ic->programs[j]->id, + name ? name->value : ""); + dump_metadata(NULL, ic->programs[j]->metadata, " "); + for (k = 0; k < ic->programs[j]->nb_stream_indexes; k++) { + dump_stream_format(ic, ic->programs[j]->stream_index[k], + index, is_output); + printed[ic->programs[j]->stream_index[k]] = 1; + } + total += ic->programs[j]->nb_stream_indexes; + } + if (total < ic->nb_streams) + av_log(NULL, AV_LOG_INFO, " No Program\n"); + } + + for (i = 0; i < ic->nb_streams; i++) + if (!printed[i]) + dump_stream_format(ic, i, index, is_output); + + av_free(printed); +} diff --git a/libavformat/dv.c b/libavformat/dv.c index f972478f6..4f7b062f8 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -1,5 +1,5 @@ /* - * General DV muxer/demuxer + * General DV demuxer * Copyright (c) 2003 Roman Shaposhnik * * Many thanks to Dan Dennedy for providing wealth @@ -41,7 +41,7 @@ #include "libavutil/avassert.h" struct DVDemuxContext { - const DVprofile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */ + const AVDVProfile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */ AVFormatContext* fctx; AVStream* vst; AVStream* ast[4]; @@ -114,7 +114,7 @@ static const int dv_audio_frequency[3] = { * are converted into 16bit linear ones. */ static int dv_extract_audio(uint8_t *frame, uint8_t **ppcm, - const DVprofile *sys) + const AVDVProfile *sys) { int size, chan, i, j, d, of, smpls, freq, quant, half_ch; uint16_t lc, rc; @@ -288,7 +288,7 @@ static int dv_extract_video_info(DVDemuxContext *c, uint8_t *frame) avpriv_set_pts_info(c->vst, 64, c->sys->time_base.num, c->sys->time_base.den); - avctx->time_base = c->sys->time_base; + c->vst->avg_frame_rate = av_inv_q(c->vst->time_base); /* finding out SAR is a little bit messy */ vsc_pack = dv_extract_pack(frame, dv_video_control); @@ -369,7 +369,7 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, uint8_t *ppcm[5] = { 0 }; if (buf_size < DV_PROFILE_BYTES || - !(c->sys = avpriv_dv_frame_profile(c->sys, buf, buf_size)) || + !(c->sys = av_dv_frame_profile(c->sys, buf, buf_size)) || buf_size < c->sys->frame_size) { return -1; /* Broken frame, or not enough data */ } @@ -419,7 +419,8 @@ static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c, int64_t timestamp, int flags) { // FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk) - const DVprofile *sys = avpriv_dv_codec_profile(c->vst->codec); + const AVDVProfile *sys = av_dv_codec_profile(c->vst->codec->width, c->vst->codec->height, + c->vst->codec->pix_fmt); int64_t offset; int64_t size = avio_size(s->pb) - s->data_offset; int64_t max_offset = ((size - 1) / sys->frame_size) * sys->frame_size; @@ -519,9 +520,9 @@ static int dv_read_header(AVFormatContext *s) avio_seek(s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0) return AVERROR(EIO); - c->dv_demux->sys = avpriv_dv_frame_profile(c->dv_demux->sys, - c->buf, - DV_PROFILE_BYTES); + c->dv_demux->sys = av_dv_frame_profile(c->dv_demux->sys, + c->buf, + DV_PROFILE_BYTES); if (!c->dv_demux->sys) { av_log(s, AV_LOG_ERROR, "Can't determine profile of DV input stream.\n"); @@ -622,7 +623,6 @@ static int dv_probe(AVProbeData *p) return 0; } -#if CONFIG_DV_DEMUXER AVInputFormat ff_dv_demuxer = { .name = "dv", .long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), @@ -634,4 +634,3 @@ AVInputFormat ff_dv_demuxer = { .read_seek = dv_read_seek, .extensions = "dv,dif", }; -#endif diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c index 43f65c37b..8f5277dca 100644 --- a/libavformat/dvenc.c +++ b/libavformat/dvenc.c @@ -45,7 +45,7 @@ struct DVMuxContext { AVClass *av_class; - const DVprofile* sys; /* current DV profile, e.g.: 525/60, 625/50 */ + const AVDVProfile* sys; /* current DV profile, e.g.: 525/60, 625/50 */ int n_ast; /* number of stereo audio streams (up to 2) */ AVStream *ast[2]; /* stereo audio streams */ AVFifoBuffer *audio_data[2]; /* FIFO for storing excessive amounts of PCM */ @@ -72,7 +72,7 @@ static const int dv_aaux_packs_dist[12][9] = { { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff }, }; -static int dv_audio_frame_size(const DVprofile* sys, int frame) +static int dv_audio_frame_size(const AVDVProfile* sys, int frame) { return sys->audio_samples_dist[frame % (sizeof(sys->audio_samples_dist) / sizeof(sys->audio_samples_dist[0]))]; @@ -314,7 +314,7 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s) c->ast[i]->codec->channels != 2)) goto bail_out; } - c->sys = avpriv_dv_codec_profile(vst->codec); + c->sys = av_dv_codec_profile(vst->codec->width, vst->codec->height, vst->codec->pix_fmt); if (!c->sys) goto bail_out; @@ -331,10 +331,10 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s) c->start_time = ff_iso8601_to_unix_time(t->value); for (i=0; i < c->n_ast; i++) { - if (c->ast[i] && !(c->audio_data[i]=av_fifo_alloc(100*MAX_AUDIO_FRAME_SIZE))) { + if (c->ast[i] && !(c->audio_data[i]=av_fifo_alloc_array(100, MAX_AUDIO_FRAME_SIZE))) { while (i > 0) { i--; - av_fifo_free(c->audio_data[i]); + av_fifo_freep(&c->audio_data[i]); } goto bail_out; } @@ -350,7 +350,7 @@ static void dv_delete_mux(DVMuxContext *c) { int i; for (i=0; i < c->n_ast; i++) - av_fifo_free(c->audio_data[i]); + av_fifo_freep(&c->audio_data[i]); } static int dv_write_header(AVFormatContext *s) diff --git a/libavformat/dxa.c b/libavformat/dxa.c index 5b2d7c0cb..ea5b4f716 100644 --- a/libavformat/dxa.c +++ b/libavformat/dxa.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/intreadwrite.h" #include "avformat.h" #include "internal.h" @@ -196,7 +198,8 @@ static int dxa_read_packet(AVFormatContext *s, AVPacket *pkt) } size = AV_RB32(buf + 5); if(size > 0xFFFFFF){ - av_log(s, AV_LOG_ERROR, "Frame size is too big: %d\n", size); + av_log(s, AV_LOG_ERROR, "Frame size is too big: %"PRIu32"\n", + size); return AVERROR_INVALIDDATA; } if(av_new_packet(pkt, size + DXA_EXTRA_SIZE + pal_size) < 0) diff --git a/libavformat/electronicarts.c b/libavformat/electronicarts.c index 4ba0fa0b6..1acaa14c8 100644 --- a/libavformat/electronicarts.c +++ b/libavformat/electronicarts.c @@ -25,6 +25,8 @@ * by Robin Kay (komadori at gekkou.co.uk) */ +#include + #include "libavutil/intreadwrite.h" #include "avformat.h" #include "internal.h" @@ -152,7 +154,7 @@ static int process_audio_header_elements(AVFormatContext *s) break; case 0x8A: av_log(s, AV_LOG_DEBUG, - "element 0x%02x set to 0x%08x\n", + "element 0x%02x set to 0x%08"PRIx32"\n", subbyte, read_arbitrary(pb)); av_log(s, AV_LOG_DEBUG, "exited audio subheader\n"); in_subheader = 0; @@ -171,7 +173,7 @@ static int process_audio_header_elements(AVFormatContext *s) break; default: av_log(s, AV_LOG_DEBUG, - "element 0x%02x set to 0x%08x\n", + "element 0x%02x set to 0x%08"PRIx32"\n", subbyte, read_arbitrary(pb)); break; } @@ -183,7 +185,7 @@ static int process_audio_header_elements(AVFormatContext *s) break; default: av_log(s, AV_LOG_DEBUG, - "header element 0x%02x set to 0x%08x\n", + "header element 0x%02x set to 0x%08"PRIx32"\n", byte, read_arbitrary(pb)); break; } diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c index 9d89b1664..d296ca7eb 100644 --- a/libavformat/ffmdec.c +++ b/libavformat/ffmdec.c @@ -510,7 +510,7 @@ static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt) if (ffm_read_data(s, ffm->header+16, 4, 1) != 4) return -1; ffm->read_state = READ_DATA; - /* fall thru */ + /* fall through */ case READ_DATA: size = AV_RB24(ffm->header + 2); if ((ret = ffm_is_avail_data(s, size)) < 0) diff --git a/libavformat/filmstripenc.c b/libavformat/filmstripenc.c index 85d49beec..7c9bc6dcc 100644 --- a/libavformat/filmstripenc.c +++ b/libavformat/filmstripenc.c @@ -64,7 +64,8 @@ static int write_trailer(AVFormatContext *s) avio_wb16(pb, st->codec->width); avio_wb16(pb, st->codec->height); avio_wb16(pb, 0); // leading - avio_wb16(pb, st->codec->time_base.den / st->codec->time_base.num); + // TODO: should be avg_frame_rate + avio_wb16(pb, st->time_base.den / st->time_base.num); for (i = 0; i < 16; i++) avio_w8(pb, 0x00); // reserved diff --git a/libavformat/flacdec.c b/libavformat/flacdec.c index 29310b831..d601c753a 100644 --- a/libavformat/flacdec.c +++ b/libavformat/flacdec.c @@ -26,6 +26,7 @@ #include "rawdec.h" #include "oggdec.h" #include "vorbiscomment.h" +#include "replaygain.h" #include "libavcodec/bytestream.h" static int flac_read_header(AVFormatContext *s) @@ -50,7 +51,7 @@ static int flac_read_header(AVFormatContext *s) /* process metadata blocks */ while (!url_feof(s->pb) && !metadata_last) { avio_read(s->pb, header, 4); - avpriv_flac_parse_block_header(header, &metadata_last, &metadata_type, + flac_parse_block_header(header, &metadata_last, &metadata_type, &metadata_size); switch (metadata_type) { /* allocate and read metadata block for supported types */ @@ -135,14 +136,33 @@ static int flac_read_header(AVFormatContext *s) } /* process supported blocks other than STREAMINFO */ if (metadata_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) { - if (ff_vorbis_comment(s, &s->metadata, buffer, metadata_size)) { + AVDictionaryEntry *chmask; + + if (ff_vorbis_comment(s, &s->metadata, buffer, metadata_size, 1)) { av_log(s, AV_LOG_WARNING, "error parsing VorbisComment metadata\n"); } + + /* parse the channels mask if present */ + chmask = av_dict_get(s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0); + if (chmask) { + uint64_t mask = strtol(chmask->value, NULL, 0); + if (!mask || mask & ~0x3ffffULL) { + av_log(s, AV_LOG_WARNING, + "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n"); + } else { + st->codec->channel_layout = mask; + av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0); + } + } } av_freep(&buffer); } } + ret = ff_replaygain_export(st, s->metadata); + if (ret < 0) + return ret; + return 0; fail: @@ -157,12 +177,61 @@ static int flac_probe(AVProbeData *p) return AVPROBE_SCORE_EXTENSION; } +static av_unused int64_t flac_read_timestamp(AVFormatContext *s, int stream_index, + int64_t *ppos, int64_t pos_limit) +{ + AVPacket pkt, out_pkt; + AVStream *st = s->streams[stream_index]; + AVCodecParserContext *parser; + int ret; + int64_t pts = AV_NOPTS_VALUE; + + if (avio_seek(s->pb, *ppos, SEEK_SET) < 0) + return AV_NOPTS_VALUE; + + av_init_packet(&pkt); + parser = av_parser_init(st->codec->codec_id); + if (!parser){ + return AV_NOPTS_VALUE; + } + parser->flags |= PARSER_FLAG_USE_CODEC_TS; + + for (;;){ + ret = ff_raw_read_partial_packet(s, &pkt); + if (ret < 0){ + if (ret == AVERROR(EAGAIN)) + continue; + else + break; + } + av_init_packet(&out_pkt); + ret = av_parser_parse2(parser, st->codec, + &out_pkt.data, &out_pkt.size, pkt.data, pkt.size, + pkt.pts, pkt.dts, *ppos); + + av_free_packet(&pkt); + if (out_pkt.size){ + int size = out_pkt.size; + if (parser->pts != AV_NOPTS_VALUE){ + // seeking may not have started from beginning of a frame + // calculate frame start position from next frame backwards + *ppos = parser->next_frame_offset - size; + pts = parser->pts; + break; + } + } + } + av_parser_close(parser); + return pts; +} + AVInputFormat ff_flac_demuxer = { .name = "flac", .long_name = NULL_IF_CONFIG_SMALL("raw FLAC"), .read_probe = flac_probe, .read_header = flac_read_header, .read_packet = ff_raw_read_partial_packet, + .read_timestamp = flac_read_timestamp, .flags = AVFMT_GENERIC_INDEX, .extensions = "flac", .raw_codec_id = AV_CODEC_ID_FLAC, diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index 0eca5aacc..b3695a27b 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/channel_layout.h" #include "libavutil/opt.h" #include "libavcodec/flac.h" #include "avformat.h" @@ -31,6 +32,9 @@ typedef struct FlacMuxerContext { const AVClass *class; int write_header; + + /* updated streaminfo sent by the encoder at the end */ + uint8_t *streaminfo; } FlacMuxerContext; static int flac_write_block_padding(AVIOContext *pb, unsigned int n_padding_bytes, @@ -46,12 +50,12 @@ static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m, int last_block, int bitexact) { const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT; - unsigned int len, count; + unsigned int len; uint8_t *p, *p0; ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL); - len = ff_vorbiscomment_length(*m, vendor, &count); + len = ff_vorbiscomment_length(*m, vendor); p0 = av_malloc(len+4); if (!p0) return AVERROR(ENOMEM); @@ -59,7 +63,7 @@ static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m, bytestream_put_byte(&p, last_block ? 0x84 : 0x04); bytestream_put_be24(&p, len); - ff_vorbiscomment_write(&p, m, vendor, count); + ff_vorbiscomment_write(&p, m, vendor); avio_write(pb, p0, len+4); av_freep(&p0); @@ -93,12 +97,30 @@ static int flac_write_header(struct AVFormatContext *s) * size of a metadata block so we must clip this value to 2^24-1. */ padding = av_clip_c(padding, 0, 16777215); - ret = ff_flac_write_header(s->pb, codec, 0); + ret = ff_flac_write_header(s->pb, codec->extradata, + codec->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)) { + AVDictionaryEntry *chmask = av_dict_get(s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", + NULL, 0); + + if (chmask) { + av_log(s, AV_LOG_WARNING, "A WAVEFORMATEXTENSIBLE_CHANNEL_MASK is " + "already present, this muxer will not overwrite it.\n"); + } else { + uint8_t buf[32]; + snprintf(buf, sizeof(buf), "0x%"PRIx64, codec->channel_layout); + av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0); + } + } + ret = flac_write_block_comment(s->pb, &s->metadata, !padding, - codec->flags & CODEC_FLAG_BITEXACT); + s->flags & AVFMT_FLAG_BITEXACT); if (ret) return ret; @@ -115,17 +137,14 @@ static int flac_write_header(struct AVFormatContext *s) static int flac_write_trailer(struct AVFormatContext *s) { AVIOContext *pb = s->pb; - uint8_t *streaminfo; - enum FLACExtradataFormat format; int64_t file_size; FlacMuxerContext *c = s->priv_data; + uint8_t *streaminfo = c->streaminfo ? c->streaminfo : + s->streams[0]->codec->extradata; - if (!c->write_header) + if (!c->write_header || !streaminfo) return 0; - if (!avpriv_flac_is_extradata_valid(s->streams[0]->codec, &format, &streaminfo)) - return -1; - if (pb->seekable) { /* rewrite the STREAMINFO header block data */ file_size = avio_tell(pb); @@ -136,12 +155,32 @@ static int flac_write_trailer(struct AVFormatContext *s) } else { av_log(s, AV_LOG_WARNING, "unable to rewrite FLAC header.\n"); } + + av_freep(&c->streaminfo); + return 0; } static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt) { - avio_write(s->pb, pkt->data, pkt->size); + FlacMuxerContext *c = s->priv_data; + uint8_t *streaminfo; + int streaminfo_size; + + /* check for updated streaminfo */ + streaminfo = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, + &streaminfo_size); + if (streaminfo && streaminfo_size == FLAC_STREAMINFO_SIZE) { + av_freep(&c->streaminfo); + + c->streaminfo = av_malloc(FLAC_STREAMINFO_SIZE); + if (!c->streaminfo) + return AVERROR(ENOMEM); + memcpy(c->streaminfo, streaminfo, FLAC_STREAMINFO_SIZE); + } + + if (pkt->size) + avio_write(s->pb, pkt->data, pkt->size); return 0; } diff --git a/libavformat/flacenc.h b/libavformat/flacenc.h index e83ee32ae..d5d53a5dc 100644 --- a/libavformat/flacenc.h +++ b/libavformat/flacenc.h @@ -26,7 +26,9 @@ #include "libavcodec/bytestream.h" #include "avformat.h" -int ff_flac_write_header(AVIOContext *pb, AVCodecContext *codec, - int last_block); +int ff_flac_write_header(AVIOContext *pb, uint8_t *extradata, + int extradata_size, int last_block); + +int ff_flac_is_native_layout(uint64_t channel_layout); #endif /* AVFORMAT_FLACENC_H */ diff --git a/libavformat/flacenc_header.c b/libavformat/flacenc_header.c index e16c14bf5..61833cc8b 100644 --- a/libavformat/flacenc_header.c +++ b/libavformat/flacenc_header.c @@ -19,29 +19,44 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/channel_layout.h" + #include "libavcodec/flac.h" -#include "libavcodec/bytestream.h" + #include "avformat.h" #include "flacenc.h" -int ff_flac_write_header(AVIOContext *pb, AVCodecContext *codec, - int last_block) +int ff_flac_write_header(AVIOContext *pb, uint8_t *extradata, + int extradata_size, int last_block) { uint8_t header[8] = { 0x66, 0x4C, 0x61, 0x43, 0x00, 0x00, 0x00, 0x22 }; - uint8_t *streaminfo; - enum FLACExtradataFormat format; header[4] = last_block ? 0x80 : 0x00; - if (!avpriv_flac_is_extradata_valid(codec, &format, &streaminfo)) - return -1; + + if (extradata_size < FLAC_STREAMINFO_SIZE) + return AVERROR_INVALIDDATA; /* write "fLaC" stream marker and first metadata block header */ avio_write(pb, header, 8); /* write STREAMINFO */ - avio_write(pb, streaminfo, FLAC_STREAMINFO_SIZE); + avio_write(pb, extradata, FLAC_STREAMINFO_SIZE); return 0; } + +int ff_flac_is_native_layout(uint64_t channel_layout) +{ + if (channel_layout == AV_CH_LAYOUT_MONO || + channel_layout == AV_CH_LAYOUT_STEREO || + channel_layout == AV_CH_LAYOUT_SURROUND || + channel_layout == AV_CH_LAYOUT_QUAD || + channel_layout == AV_CH_LAYOUT_5POINT0 || + channel_layout == AV_CH_LAYOUT_5POINT1 || + channel_layout == AV_CH_LAYOUT_6POINT1 || + channel_layout == AV_CH_LAYOUT_7POINT1) + return 1; + return 0; +} diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index b11e3352c..899a0368f 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -56,21 +56,35 @@ typedef struct { int searched_for_end; } FLVContext; -static int flv_probe(AVProbeData *p) +static int probe(AVProbeData *p, int live) { - const uint8_t *d; + const uint8_t *d = p->buf; + unsigned offset = AV_RB32(d + 5); - d = p->buf; if (d[0] == 'F' && d[1] == 'L' && d[2] == 'V' && d[3] < 5 && d[5] == 0 && - AV_RB32(d + 5) > 8) { - return AVPROBE_SCORE_MAX; + offset + 100 < p->buf_size && + offset > 8) { + int is_live = !memcmp(d + offset + 40, "NGINX RTMP", 10); + + if (live == is_live) + return AVPROBE_SCORE_MAX; } return 0; } +static int flv_probe(AVProbeData *p) +{ + return probe(p, 0); +} + +static int live_flv_probe(AVProbeData *p) +{ + return probe(p, 1); +} + static AVStream *create_stream(AVFormatContext *s, int codec_type) { AVStream *st = avformat_new_stream(s, NULL); @@ -296,7 +310,7 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, int64_t initial_pos = avio_tell(ioc); if (vstream->nb_index_entries>0) { - av_log(s, AV_LOG_WARNING, "Skiping duplicate index\n"); + av_log(s, AV_LOG_WARNING, "Skipping duplicate index\n"); return 0; } @@ -574,14 +588,6 @@ static int flv_read_header(AVFormatContext *s) avio_skip(s->pb, 4); flags = avio_r8(s->pb); - /* old flvtool cleared this field */ - /* FIXME: better fix needed */ - if (!flags) { - flags = FLV_HEADER_FLAG_HASVIDEO | FLV_HEADER_FLAG_HASAUDIO; - av_log(s, AV_LOG_WARNING, - "Broken FLV file, which says no streams present, " - "this might fail\n"); - } s->ctx_flags |= AVFMTCTX_NOHEADER; @@ -772,7 +778,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_dlog(s, "type:%d, size:%d, dts:%"PRId64" pos:%"PRId64"\n", type, size, dts, avio_tell(s->pb)); if (url_feof(s->pb)) return AVERROR_EOF; avio_skip(s->pb, 3); /* stream id, always 0 */ @@ -820,7 +826,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) } } else { av_log(s, AV_LOG_DEBUG, - "skipping flv packet: type %d, size %d, flags %d\n", + "Skipping flv packet: type %d, size %d, flags %d.\n", type, size, flags); skip: avio_seek(s->pb, next, SEEK_SET); @@ -934,13 +940,16 @@ retry_duration: // sign extension int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000; pts = dts + cts; - if (cts < 0) { // dts are wrong + if (cts < 0) { // dts might be wrong + if (!flv->wrong_dts) + av_log(s, AV_LOG_WARNING, + "Negative cts, previous timestamps might be wrong.\n"); flv->wrong_dts = 1; + } else if (FFABS(dts - pts) > 1000*60*15) { av_log(s, AV_LOG_WARNING, - "negative cts, previous timestamps might be wrong\n"); + "invalid timestamps %"PRId64" %"PRId64"\n", dts, pts); + dts = pts = AV_NOPTS_VALUE; } - if (flv->wrong_dts) - dts = AV_NOPTS_VALUE; } if (type == 0 && (!st->codec->extradata || st->codec->codec_id == AV_CODEC_ID_AAC)) { AVDictionaryEntry *t; @@ -1054,3 +1063,24 @@ AVInputFormat ff_flv_demuxer = { .extensions = "flv", .priv_class = &flv_class, }; + +static const AVClass live_flv_class = { + .class_name = "live_flvdec", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_live_flv_demuxer = { + .name = "live_flv", + .long_name = NULL_IF_CONFIG_SMALL("live RTMP FLV (Flash Video)"), + .priv_data_size = sizeof(FLVContext), + .read_probe = live_flv_probe, + .read_header = flv_read_header, + .read_packet = flv_read_packet, + .read_seek = flv_read_seek, + .read_close = flv_read_close, + .extensions = "flv", + .priv_class = &live_flv_class, + .flags = AVFMT_TS_DISCONT +}; diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 9778719a3..dd74d4c4d 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -209,8 +209,6 @@ static int flv_write_header(AVFormatContext *s) if (s->streams[i]->avg_frame_rate.den && s->streams[i]->avg_frame_rate.num) { framerate = av_q2d(s->streams[i]->avg_frame_rate); - } else { - framerate = 1 / av_q2d(s->streams[i]->codec->time_base); } if (video_enc) { av_log(s, AV_LOG_ERROR, @@ -306,7 +304,7 @@ 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 = 5 * !!video_enc + + metadata_count = 4 * !!video_enc + 5 * !!audio_enc + 1 * !!data_enc + 2; // +2 for duration and file size @@ -329,8 +327,11 @@ static int flv_write_header(AVFormatContext *s) put_amf_string(pb, "videodatarate"); put_amf_double(pb, video_enc->bit_rate / 1024.0); - put_amf_string(pb, "framerate"); - put_amf_double(pb, framerate); + if (framerate != 0.0) { + put_amf_string(pb, "framerate"); + put_amf_double(pb, framerate); + metadata_count++; + } put_amf_string(pb, "videocodecid"); put_amf_double(pb, video_enc->codec_tag); diff --git a/libavformat/framecrcenc.c b/libavformat/framecrcenc.c index dbe49b5ba..805b5428f 100644 --- a/libavformat/framecrcenc.c +++ b/libavformat/framecrcenc.c @@ -19,17 +19,35 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/adler32.h" #include "libavutil/avstring.h" #include "avformat.h" #include "internal.h" +static int framecrc_write_header(struct AVFormatContext *s) +{ + int i; + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + AVCodecContext *avctx = st->codec; + if (avctx->extradata) { + uint32_t crc = av_adler32_update(0, avctx->extradata, avctx->extradata_size); + avio_printf(s->pb, "#extradata %d: %8d, 0x%08"PRIx32"\n", + i, avctx->extradata_size, crc); + } + } + + return ff_framehash_write_header(s); +} + 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%08x", + snprintf(buf, sizeof(buf), "%d, %10"PRId64", %10"PRId64", %8d, %8d, 0x%08"PRIx32, pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size, crc); if (pkt->flags != AV_PKT_FLAG_KEY) av_strlcatf(buf, sizeof(buf), ", F=0x%0X", pkt->flags); @@ -63,7 +81,7 @@ AVOutputFormat ff_framecrc_muxer = { .long_name = NULL_IF_CONFIG_SMALL("framecrc testing"), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_RAWVIDEO, - .write_header = ff_framehash_write_header, + .write_header = framecrc_write_header, .write_packet = framecrc_write_packet, .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_TS_NEGATIVE, diff --git a/libavformat/framehash.c b/libavformat/framehash.c index f97f59b9b..a8357b04a 100644 --- a/libavformat/framehash.c +++ b/libavformat/framehash.c @@ -24,11 +24,10 @@ int ff_framehash_write_header(AVFormatContext *s) { int i; - if (s->nb_streams && !(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) + if (s->nb_streams && !(s->flags & AVFMT_FLAG_BITEXACT)) avio_printf(s->pb, "#software: %s\n", LIBAVFORMAT_IDENT); for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - avpriv_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den); avio_printf(s->pb, "#tb %d: %d/%d\n", i, st->time_base.num, st->time_base.den); avio_flush(s->pb); } diff --git a/libavformat/ftp.c b/libavformat/ftp.c index dae8aa086..66c066549 100644 --- a/libavformat/ftp.c +++ b/libavformat/ftp.c @@ -119,7 +119,7 @@ static int ftp_get_line(FTPContext *s, char *line, int line_size) */ static int ftp_status(FTPContext *s, char **line, const int response_codes[]) { - int err, i, dash = 0, result = 0, code_found = 0; + int err, i, dash = 0, result = 0, code_found = 0, linesize; char buf[CONTROL_BUFFER_SIZE]; AVBPrint line_buffer; @@ -135,25 +135,40 @@ static int ftp_status(FTPContext *s, char **line, const int response_codes[]) av_log(s, AV_LOG_DEBUG, "%s\n", buf); - if (strlen(buf) < 4) - continue; - + linesize = strlen(buf); err = 0; - for (i = 0; i < 3; ++i) { - if (buf[i] < '0' || buf[i] > '9') - continue; - err *= 10; - err += buf[i] - '0'; + if (linesize >= 3) { + for (i = 0; i < 3; ++i) { + if (buf[i] < '0' || buf[i] > '9') { + err = 0; + break; + } + err *= 10; + err += buf[i] - '0'; + } } - dash = !!(buf[3] == '-'); - for (i = 0; response_codes[i]; ++i) { - if (err == response_codes[i]) { - if (line) - av_bprintf(&line_buffer, "%s", buf); + if (!code_found) { + if (err >= 500) { code_found = 1; result = err; - break; + } else + for (i = 0; response_codes[i]; ++i) { + if (err == response_codes[i]) { + code_found = 1; + result = err; + break; + } + } + } + if (code_found) { + if (line) + av_bprintf(&line_buffer, "%s\r\n", buf); + if (linesize >= 4) { + if (!dash && buf[3] == '-') + dash = err; + else if (err == dash && buf[3] == ' ') + dash = 0; } } } @@ -198,8 +213,8 @@ static int ftp_auth(FTPContext *s) const char *user = NULL, *pass = NULL; char *end = NULL, buf[CONTROL_BUFFER_SIZE], credencials[CREDENTIALS_BUFFER_SIZE]; int err; - static const int user_codes[] = {331, 230, 500, 530, 0}; /* 500, 530 are incorrect codes */ - static const int pass_codes[] = {230, 503, 530, 0}; /* 503, 530 are incorrect codes */ + static const int user_codes[] = {331, 230, 0}; + static const int pass_codes[] = {230, 0}; /* Authentication may be repeated, original string has to be saved */ av_strlcpy(credencials, s->credencials, sizeof(credencials)); @@ -227,12 +242,54 @@ static int ftp_auth(FTPContext *s) return 0; } +static int ftp_passive_mode_epsv(FTPContext *s) +{ + char *res = NULL, *start = NULL, *end = NULL; + int i; + static const char d = '|'; + static const char *command = "EPSV\r\n"; + static const int epsv_codes[] = {229, 0}; + + if (ftp_send_command(s, command, epsv_codes, &res) != 229 || !res) + goto fail; + + for (i = 0; res[i]; ++i) { + if (res[i] == '(') { + start = res + i + 1; + } else if (res[i] == ')') { + end = res + i; + break; + } + } + if (!start || !end) + goto fail; + + *end = '\0'; + if (strlen(start) < 5) + goto fail; + if (start[0] != d || start[1] != d || start[2] != d || end[-1] != d) + goto fail; + start += 3; + end[-1] = '\0'; + + s->server_data_port = atoi(start); + av_dlog(s, "Server data port: %d\n", s->server_data_port); + + av_free(res); + return 0; + + fail: + av_free(res); + s->server_data_port = -1; + return AVERROR(ENOSYS); +} + static int ftp_passive_mode(FTPContext *s) { char *res = NULL, *start = NULL, *end = NULL; int i; static const char *command = "PASV\r\n"; - static const int pasv_codes[] = {227, 501, 0}; /* 501 is incorrect code */ + static const int pasv_codes[] = {227, 0}; if (ftp_send_command(s, command, pasv_codes, &res) != 227 || !res) goto fail; @@ -270,8 +327,6 @@ static int ftp_passive_mode(FTPContext *s) fail: av_free(res); s->server_data_port = -1; - av_log(s, AV_LOG_ERROR, "Set passive mode failed\n" - "Your FTP server may use IPv6 which is not supported yet.\n"); return AVERROR(EIO); } @@ -317,7 +372,7 @@ static int ftp_file_size(FTPContext *s) { char command[CONTROL_BUFFER_SIZE]; char *res = NULL; - static const int size_codes[] = {213, 501, 550, 0}; /* 501, 550 are incorrect codes */ + static const int size_codes[] = {213, 0}; snprintf(command, sizeof(command), "SIZE %s\r\n", s->path); if (ftp_send_command(s, command, size_codes, &res) == 213 && res) { @@ -335,7 +390,7 @@ static int ftp_file_size(FTPContext *s) static int ftp_retrieve(FTPContext *s) { char command[CONTROL_BUFFER_SIZE]; - static const int retr_codes[] = {150, 550, 554, 0}; /* 550, 554 are incorrect codes */ + static const int retr_codes[] = {150, 0}; snprintf(command, sizeof(command), "RETR %s\r\n", s->path); if (ftp_send_command(s, command, retr_codes, NULL) != 150) @@ -363,7 +418,7 @@ static int ftp_store(FTPContext *s) static int ftp_type(FTPContext *s) { static const char *command = "TYPE I\r\n"; - static const int type_codes[] = {200, 500, 504, 0}; /* 500, 504 are incorrect codes */ + static const int type_codes[] = {200, 0}; if (ftp_send_command(s, command, type_codes, NULL) != 200) return AVERROR(EIO); @@ -374,7 +429,7 @@ static int ftp_type(FTPContext *s) static int ftp_restart(FTPContext *s, int64_t pos) { char command[CONTROL_BUFFER_SIZE]; - static const int rest_codes[] = {350, 500, 501, 0}; /* 500, 501 are incorrect codes */ + static const int rest_codes[] = {350, 0}; snprintf(command, sizeof(command), "REST %"PRId64"\r\n", pos); if (ftp_send_command(s, command, rest_codes, NULL) != 350) @@ -383,6 +438,21 @@ static int ftp_restart(FTPContext *s, int64_t pos) return 0; } +static int ftp_features(FTPContext *s) +{ + static const char *feat_command = "FEAT\r\n"; + static const char *enable_utf8_command = "OPTS UTF8 ON\r\n"; + static const int feat_codes[] = {211, 0}; + static const int opts_codes[] = {200, 451}; + char *feat; + + if (ftp_send_command(s, feat_command, feat_codes, &feat) == 211) { + if (av_stristr(feat, "UTF8")) + ftp_send_command(s, enable_utf8_command, opts_codes, NULL); + } + return 0; +} + static int ftp_connect_control_connection(URLContext *h) { char buf[CONTROL_BUFFER_SIZE], opts_format[20], *response = NULL; @@ -426,6 +496,8 @@ static int ftp_connect_control_connection(URLContext *h) av_log(h, AV_LOG_ERROR, "Set content type failed\n"); return err; } + + ftp_features(s); } return 0; } @@ -439,8 +511,11 @@ static int ftp_connect_data_connection(URLContext *h) if (!s->conn_data) { /* Enter passive mode */ - if ((err = ftp_passive_mode(s)) < 0) - return err; + if (ftp_passive_mode_epsv(s) < 0) { + /* Use PASV as fallback */ + if ((err = ftp_passive_mode(s)) < 0) + return err; + } /* Open data connection */ ff_url_join(buf, sizeof(buf), "tcp", NULL, s->hostname, s->server_data_port, NULL); if (s->rw_timeout != -1) { diff --git a/libavformat/gif.c b/libavformat/gif.c index e52498d42..e81712144 100644 --- a/libavformat/gif.c +++ b/libavformat/gif.c @@ -28,10 +28,19 @@ #include "libavutil/log.h" #include "libavutil/opt.h" -static int gif_image_write_header(AVIOContext *pb, int width, int height, +static int gif_image_write_header(AVFormatContext *s, int width, int height, int loop_count, uint32_t *palette) { + AVIOContext *pb = s->pb; + AVRational sar = s->streams[0]->codec->sample_aspect_ratio; int i; + int64_t aspect = 0; + + if (sar.num > 0 && sar.den > 0) { + aspect = sar.num * 64LL / sar.den - 15; + if (aspect < 0 || aspect > 255) + aspect = 0; + } avio_write(pb, "GIF", 3); avio_write(pb, "89a", 3); @@ -41,7 +50,7 @@ static int gif_image_write_header(AVIOContext *pb, int width, int height, if (palette) { avio_w8(pb, 0xf7); /* flags: global clut, 256 entries */ avio_w8(pb, 0x1f); /* background color index */ - avio_w8(pb, 0); /* aspect ratio */ + avio_w8(pb, aspect); for (i = 0; i < 256; i++) { const uint32_t v = palette[i] & 0xffffff; avio_wb24(pb, v); @@ -49,7 +58,7 @@ static int gif_image_write_header(AVIOContext *pb, int width, int height, } else { avio_w8(pb, 0); /* flags */ avio_w8(pb, 0); /* background color index */ - avio_w8(pb, 0); /* aspect ratio */ + avio_w8(pb, aspect); } @@ -79,7 +88,6 @@ typedef struct { static int gif_write_header(AVFormatContext *s) { GIFContext *gif = s->priv_data; - AVIOContext *pb = s->pb; AVCodecContext *video_enc; int width, height; uint32_t palette[AVPALETTE_COUNT]; @@ -99,9 +107,9 @@ static int gif_write_header(AVFormatContext *s) avpriv_set_pts_info(s->streams[0], 64, 1, 100); if (avpriv_set_systematic_pal2(palette, video_enc->pix_fmt) < 0) { av_assert0(video_enc->pix_fmt == AV_PIX_FMT_PAL8); - gif_image_write_header(pb, width, height, gif->loop, NULL); + gif_image_write_header(s, width, height, gif->loop, NULL); } else { - gif_image_write_header(pb, width, height, gif->loop, palette); + gif_image_write_header(s, width, height, gif->loop, palette); } avio_flush(s->pb); diff --git a/libavformat/gxf.c b/libavformat/gxf.c index c36479a82..479a8fb39 100644 --- a/libavformat/gxf.c +++ b/libavformat/gxf.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "avformat.h" @@ -293,7 +295,9 @@ static void gxf_read_index(AVFormatContext *s, int pkt_len) { } st = s->streams[0]; if (map_cnt > 1000) { - av_log(s, AV_LOG_ERROR, "too many index entries %u (%x)\n", map_cnt, map_cnt); + av_log(s, AV_LOG_ERROR, + "too many index entries %"PRIu32" (%"PRIx32")\n", + map_cnt, map_cnt); map_cnt = 1000; } if (pkt_len < 4 * map_cnt) { diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c index fb0a94892..20b4b1213 100644 --- a/libavformat/hdsenc.c +++ b/libavformat/hdsenc.c @@ -344,7 +344,7 @@ static int hds_write_header(AVFormatContext *s) goto fail; } - c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams); + c->streams = av_mallocz_array(s->nb_streams, sizeof(*c->streams)); if (!c->streams) { ret = AVERROR(ENOMEM); goto fail; diff --git a/libavformat/hevc.c b/libavformat/hevc.c index 963238615..45b00c45b 100644 --- a/libavformat/hevc.c +++ b/libavformat/hevc.c @@ -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; } diff --git a/libavformat/hls.c b/libavformat/hls.c index e29195059..3897723b7 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1,6 +1,7 @@ /* * Apple HTTP Live Streaming demuxer * Copyright (c) 2010 Martin Storsjo + * Copyright (c) 2013 Anssi Hannula * * This file is part of FFmpeg. * @@ -26,6 +27,7 @@ */ #include "libavutil/avstring.h" +#include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" @@ -35,9 +37,16 @@ #include "internal.h" #include "avio_internal.h" #include "url.h" +#include "id3v2.h" #define INITIAL_BUFFER_SIZE 32768 +#define MAX_FIELD_LEN 64 +#define MAX_CHARACTERISTICS_LEN 512 + +#define MPEG_TIME_BASE 90000 +#define MPEG_TIME_BASE_Q (AVRational){1, MPEG_TIME_BASE} + /* * An apple http stream consists of a playlist with media segment files, * played sequentially. There may be several playlists with the same @@ -57,12 +66,22 @@ enum KeyType { struct segment { int64_t duration; - char url[MAX_URL_SIZE]; - char key[MAX_URL_SIZE]; + int64_t url_offset; + int64_t size; + char *url; + char *key; enum KeyType key_type; uint8_t iv[16]; }; +struct rendition; + +enum PlaylistType { + PLS_TYPE_UNSPECIFIED, + PLS_TYPE_EVENT, + PLS_TYPE_VOD +}; + /* * Each playlist has its own demuxer. If it currently is active, * it has an open AVIOContext too, and potentially an AVPacket @@ -80,22 +99,68 @@ struct playlist { int stream_offset; int finished; + enum PlaylistType type; int64_t target_duration; int start_seq_no; int n_segments; struct segment **segments; int needed, cur_needed; int cur_seq_no; + int64_t cur_seg_offset; int64_t last_load_time; char key_url[MAX_URL_SIZE]; uint8_t key[16]; + + /* ID3 timestamp handling (elementary audio streams have ID3 timestamps + * (and possibly other ID3 tags) in the beginning of each segment) */ + int is_id3_timestamped; /* -1: not yet known */ + int64_t id3_mpegts_timestamp; /* in mpegts tb */ + int64_t id3_offset; /* in stream original tb */ + uint8_t* id3_buf; /* temp buffer for id3 parsing */ + unsigned int id3_buf_size; + AVDictionary *id3_initial; /* data from first id3 tag */ + int id3_found; /* ID3 tag found at some point */ + int id3_changed; /* ID3 tag data has changed at some point */ + ID3v2ExtraMeta *id3_deferred_extra; /* stored here until subdemuxer is opened */ + + int64_t seek_timestamp; + int seek_flags; + int seek_stream_index; /* into subdemuxer stream array */ + + /* Renditions associated with this playlist, if any. + * Alternative rendition playlists have a single rendition associated + * with them, and variant main Media Playlists may have + * multiple (playlist-less) renditions associated with them. */ + int n_renditions; + struct rendition **renditions; +}; + +/* + * Renditions are e.g. alternative subtitle or audio streams. + * The rendition may either be an external playlist or it may be + * contained in the main Media Playlist of the variant (in which case + * playlist is NULL). + */ +struct rendition { + enum AVMediaType type; + struct playlist *playlist; + char group_id[MAX_FIELD_LEN]; + char language[MAX_FIELD_LEN]; + char name[MAX_FIELD_LEN]; + int disposition; }; struct variant { int bandwidth; + + /* every variant contains at least the main Media Playlist in index 0 */ int n_playlists; struct playlist **playlists; + + char audio_group[MAX_FIELD_LEN]; + char video_group[MAX_FIELD_LEN]; + char subtitles_group[MAX_FIELD_LEN]; }; typedef struct HLSContext { @@ -103,13 +168,13 @@ typedef struct HLSContext { struct variant **variants; int n_playlists; struct playlist **playlists; + int n_renditions; + struct rendition **renditions; int cur_seq_no; - int end_of_segment; int first_packet; int64_t first_timestamp; - int64_t seek_timestamp; - int seek_flags; + int64_t cur_timestamp; AVIOInterruptCB *interrupt_callback; char *user_agent; ///< holds HTTP user agent set as an AVOption to the HTTP protocol context char *cookies; ///< holds HTTP cookie values set in either the initial response or as an AVOption to the HTTP protocol context @@ -127,8 +192,11 @@ static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) static void free_segment_list(struct playlist *pls) { int i; - for (i = 0; i < pls->n_segments; i++) + for (i = 0; i < pls->n_segments; i++) { + av_free(pls->segments[i]->key); + av_free(pls->segments[i]->url); av_free(pls->segments[i]); + } av_freep(&pls->segments); pls->n_segments = 0; } @@ -139,6 +207,10 @@ static void free_playlist_list(HLSContext *c) for (i = 0; i < c->n_playlists; i++) { struct playlist *pls = c->playlists[i]; free_segment_list(pls); + av_freep(&pls->renditions); + av_freep(&pls->id3_buf); + av_dict_free(&pls->id3_initial); + ff_id3v2_free_extra_meta(&pls->id3_deferred_extra); av_free_packet(&pls->pkt); av_free(pls->pb.buffer); if (pls->input) @@ -167,6 +239,15 @@ static void free_variant_list(HLSContext *c) c->n_variants = 0; } +static void free_rendition_list(HLSContext *c) +{ + int i; + for (i = 0; i < c->n_renditions; i++) + av_free(c->renditions[i]); + av_freep(&c->renditions); + c->n_renditions = 0; +} + /* * Used to reset a statically allocated AVPacket to a clean slate, * containing no data. @@ -185,11 +266,24 @@ static struct playlist *new_playlist(HLSContext *c, const char *url, return NULL; reset_packet(&pls->pkt); ff_make_absolute_url(pls->url, sizeof(pls->url), base, url); + pls->seek_timestamp = AV_NOPTS_VALUE; + + pls->is_id3_timestamped = -1; + pls->id3_mpegts_timestamp = AV_NOPTS_VALUE; + dynarray_add(&c->playlists, &c->n_playlists, pls); return pls; } -static struct variant *new_variant(HLSContext *c, int bandwidth, +struct variant_info { + char bandwidth[20]; + /* variant group ids: */ + char audio[MAX_FIELD_LEN]; + char video[MAX_FIELD_LEN]; + char subtitles[MAX_FIELD_LEN]; +}; + +static struct variant *new_variant(HLSContext *c, struct variant_info *info, const char *url, const char *base) { struct variant *var; @@ -203,22 +297,33 @@ static struct variant *new_variant(HLSContext *c, int bandwidth, if (!var) return NULL; - var->bandwidth = bandwidth; + if (info) { + var->bandwidth = atoi(info->bandwidth); + strcpy(var->audio_group, info->audio); + strcpy(var->video_group, info->video); + strcpy(var->subtitles_group, info->subtitles); + } + dynarray_add(&c->variants, &c->n_variants, var); dynarray_add(&var->playlists, &var->n_playlists, pls); return var; } -struct variant_info { - char bandwidth[20]; -}; - static void handle_variant_args(struct variant_info *info, const char *key, int key_len, char **dest, int *dest_len) { if (!strncmp(key, "BANDWIDTH=", key_len)) { *dest = info->bandwidth; *dest_len = sizeof(info->bandwidth); + } else if (!strncmp(key, "AUDIO=", key_len)) { + *dest = info->audio; + *dest_len = sizeof(info->audio); + } else if (!strncmp(key, "VIDEO=", key_len)) { + *dest = info->video; + *dest_len = sizeof(info->video); + } else if (!strncmp(key, "SUBTITLES=", key_len)) { + *dest = info->subtitles; + *dest_len = sizeof(info->subtitles); } } @@ -243,10 +348,153 @@ static void handle_key_args(struct key_info *info, const char *key, } } +struct rendition_info { + char type[16]; + char uri[MAX_URL_SIZE]; + char group_id[MAX_FIELD_LEN]; + char language[MAX_FIELD_LEN]; + char assoc_language[MAX_FIELD_LEN]; + char name[MAX_FIELD_LEN]; + char defaultr[4]; + char forced[4]; + char characteristics[MAX_CHARACTERISTICS_LEN]; +}; + +static struct rendition *new_rendition(HLSContext *c, struct rendition_info *info, + const char *url_base) +{ + struct rendition *rend; + enum AVMediaType type = AVMEDIA_TYPE_UNKNOWN; + char *characteristic; + char *chr_ptr; + char *saveptr; + + if (!strcmp(info->type, "AUDIO")) + type = AVMEDIA_TYPE_AUDIO; + else if (!strcmp(info->type, "VIDEO")) + type = AVMEDIA_TYPE_VIDEO; + else if (!strcmp(info->type, "SUBTITLES")) + type = AVMEDIA_TYPE_SUBTITLE; + else if (!strcmp(info->type, "CLOSED-CAPTIONS")) + /* CLOSED-CAPTIONS is ignored since we do not support CEA-608 CC in + * AVC SEI RBSP anyway */ + return NULL; + + if (type == AVMEDIA_TYPE_UNKNOWN) + return NULL; + + /* URI is mandatory for subtitles as per spec */ + if (type == AVMEDIA_TYPE_SUBTITLE && !info->uri[0]) + return NULL; + + /* TODO: handle subtitles (each segment has to parsed separately) */ + if (type == AVMEDIA_TYPE_SUBTITLE) + return NULL; + + rend = av_mallocz(sizeof(struct rendition)); + if (!rend) + return NULL; + + dynarray_add(&c->renditions, &c->n_renditions, rend); + + rend->type = type; + strcpy(rend->group_id, info->group_id); + strcpy(rend->language, info->language); + strcpy(rend->name, info->name); + + /* add the playlist if this is an external rendition */ + if (info->uri[0]) { + rend->playlist = new_playlist(c, info->uri, url_base); + if (rend->playlist) + dynarray_add(&rend->playlist->renditions, + &rend->playlist->n_renditions, rend); + } + + if (info->assoc_language[0]) { + int langlen = strlen(rend->language); + if (langlen < sizeof(rend->language) - 3) { + rend->language[langlen] = ','; + strncpy(rend->language + langlen + 1, info->assoc_language, + sizeof(rend->language) - langlen - 2); + } + } + + if (!strcmp(info->defaultr, "YES")) + rend->disposition |= AV_DISPOSITION_DEFAULT; + if (!strcmp(info->forced, "YES")) + rend->disposition |= AV_DISPOSITION_FORCED; + + chr_ptr = info->characteristics; + while ((characteristic = av_strtok(chr_ptr, ",", &saveptr))) { + if (!strcmp(characteristic, "public.accessibility.describes-music-and-sound")) + rend->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; + else if (!strcmp(characteristic, "public.accessibility.describes-video")) + rend->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; + + chr_ptr = NULL; + } + + return rend; +} + +static void handle_rendition_args(struct rendition_info *info, const char *key, + int key_len, char **dest, int *dest_len) +{ + if (!strncmp(key, "TYPE=", key_len)) { + *dest = info->type; + *dest_len = sizeof(info->type); + } else if (!strncmp(key, "URI=", key_len)) { + *dest = info->uri; + *dest_len = sizeof(info->uri); + } else if (!strncmp(key, "GROUP-ID=", key_len)) { + *dest = info->group_id; + *dest_len = sizeof(info->group_id); + } else if (!strncmp(key, "LANGUAGE=", key_len)) { + *dest = info->language; + *dest_len = sizeof(info->language); + } else if (!strncmp(key, "ASSOC-LANGUAGE=", key_len)) { + *dest = info->assoc_language; + *dest_len = sizeof(info->assoc_language); + } else if (!strncmp(key, "NAME=", key_len)) { + *dest = info->name; + *dest_len = sizeof(info->name); + } else if (!strncmp(key, "DEFAULT=", key_len)) { + *dest = info->defaultr; + *dest_len = sizeof(info->defaultr); + } else if (!strncmp(key, "FORCED=", key_len)) { + *dest = info->forced; + *dest_len = sizeof(info->forced); + } else if (!strncmp(key, "CHARACTERISTICS=", key_len)) { + *dest = info->characteristics; + *dest_len = sizeof(info->characteristics); + } + /* + * ignored: + * - AUTOSELECT: client may autoselect based on e.g. system language + * - INSTREAM-ID: EIA-608 closed caption number ("CC1".."CC4") + */ +} + +/* used by parse_playlist to allocate a new variant+playlist when the + * playlist is detected to be a Media Playlist (not Master Playlist) + * and we have no parent Master Playlist (parsing of which would have + * allocated the variant and playlist already) */ +static int ensure_playlist(HLSContext *c, struct playlist **pls, const char *url) +{ + if (*pls) + return 0; + if (!new_variant(c, NULL, url, NULL)) + return AVERROR(ENOMEM); + *pls = c->playlists[c->n_playlists - 1]; + return 0; +} + +/* pls = NULL => Master Playlist or parentless Media Playlist + * pls = !NULL => parented Media Playlist, playlist+variant allocated */ static int parse_playlist(HLSContext *c, const char *url, struct playlist *pls, AVIOContext *in) { - int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0; + int ret = 0, is_segment = 0, is_variant = 0; int64_t duration = 0; enum KeyType key_type = KEY_NONE; uint8_t iv[16] = ""; @@ -255,7 +503,11 @@ static int parse_playlist(HLSContext *c, const char *url, char line[MAX_URL_SIZE]; const char *ptr; int close_in = 0; + int64_t seg_offset = 0; + int64_t seg_size = -1; uint8_t *new_url = NULL; + struct variant_info variant_info; + char tmp_str[MAX_URL_SIZE]; if (!in) { AVDictionary *opts = NULL; @@ -287,15 +539,15 @@ static int parse_playlist(HLSContext *c, const char *url, if (pls) { free_segment_list(pls); pls->finished = 0; + pls->type = PLS_TYPE_UNSPECIFIED; } while (!url_feof(in)) { read_chomp_line(in, line, sizeof(line)); if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) { - struct variant_info info = {{0}}; is_variant = 1; + memset(&variant_info, 0, sizeof(variant_info)); ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args, - &info); - bandwidth = atoi(info.bandwidth); + &variant_info); } else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) { struct key_info info = {{0}}; ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args, @@ -309,40 +561,49 @@ static int parse_playlist(HLSContext *c, const char *url, has_iv = 1; } av_strlcpy(key, info.uri, sizeof(key)); + } else if (av_strstart(line, "#EXT-X-MEDIA:", &ptr)) { + struct rendition_info info = {{0}}; + ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_rendition_args, + &info); + new_rendition(c, &info, url); } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) { - if (!pls) { - if (!new_variant(c, 0, url, NULL)) { - ret = AVERROR(ENOMEM); - goto fail; - } - pls = c->playlists[c->n_playlists - 1]; - } + ret = ensure_playlist(c, &pls, url); + if (ret < 0) + goto fail; pls->target_duration = atoi(ptr) * AV_TIME_BASE; } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { - if (!pls) { - if (!new_variant(c, 0, url, NULL)) { - ret = AVERROR(ENOMEM); - goto fail; - } - pls = c->playlists[c->n_playlists - 1]; - } + ret = ensure_playlist(c, &pls, url); + if (ret < 0) + goto fail; pls->start_seq_no = atoi(ptr); + } else if (av_strstart(line, "#EXT-X-PLAYLIST-TYPE:", &ptr)) { + ret = ensure_playlist(c, &pls, url); + if (ret < 0) + goto fail; + if (!strcmp(ptr, "EVENT")) + pls->type = PLS_TYPE_EVENT; + else if (!strcmp(ptr, "VOD")) + pls->type = PLS_TYPE_VOD; } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { if (pls) pls->finished = 1; } else if (av_strstart(line, "#EXTINF:", &ptr)) { is_segment = 1; duration = atof(ptr) * AV_TIME_BASE; + } else if (av_strstart(line, "#EXT-X-BYTERANGE:", &ptr)) { + seg_size = atoi(ptr); + ptr = strchr(ptr, '@'); + if (ptr) + seg_offset = atoi(ptr+1); } else if (av_strstart(line, "#", NULL)) { continue; } else if (line[0]) { if (is_variant) { - if (!new_variant(c, bandwidth, line, url)) { + if (!new_variant(c, &variant_info, line, url)) { ret = AVERROR(ENOMEM); goto fail; } is_variant = 0; - bandwidth = 0; } if (is_segment) { struct segment *seg; @@ -367,10 +628,40 @@ static int parse_playlist(HLSContext *c, const char *url, memset(seg->iv, 0, sizeof(seg->iv)); AV_WB32(seg->iv + 12, seq); } - ff_make_absolute_url(seg->key, sizeof(seg->key), url, key); - ff_make_absolute_url(seg->url, sizeof(seg->url), url, line); + + if (key_type != KEY_NONE) { + ff_make_absolute_url(tmp_str, sizeof(tmp_str), url, key); + seg->key = av_strdup(tmp_str); + if (!seg->key) { + av_free(seg); + ret = AVERROR(ENOMEM); + goto fail; + } + } else { + seg->key = NULL; + } + + ff_make_absolute_url(tmp_str, sizeof(tmp_str), url, line); + seg->url = av_strdup(tmp_str); + if (!seg->url) { + av_free(seg->key); + av_free(seg); + ret = AVERROR(ENOMEM); + goto fail; + } + dynarray_add(&pls->segments, &pls->n_segments, seg); is_segment = 0; + + seg->size = seg_size; + if (seg_size >= 0) { + seg->url_offset = seg_offset; + seg_offset += seg_size; + seg_size = -1; + } else { + seg->url_offset = 0; + seg_offset = 0; + } } } } @@ -384,6 +675,231 @@ fail: return ret; } +enum ReadFromURLMode { + READ_NORMAL, + READ_COMPLETE, +}; + +/* read from URLContext, limiting read to current segment */ +static int read_from_url(struct playlist *pls, uint8_t *buf, int buf_size, + enum ReadFromURLMode mode) +{ + int ret; + struct segment *seg = pls->segments[pls->cur_seq_no - pls->start_seq_no]; + + /* limit read if the segment was only a part of a file */ + if (seg->size >= 0) + buf_size = FFMIN(buf_size, seg->size - pls->cur_seg_offset); + + if (mode == READ_COMPLETE) + ret = ffurl_read_complete(pls->input, buf, buf_size); + else + ret = ffurl_read(pls->input, buf, buf_size); + + if (ret > 0) + pls->cur_seg_offset += ret; + + return ret; +} + +/* Parse the raw ID3 data and pass contents to caller */ +static void parse_id3(AVFormatContext *s, AVIOContext *pb, + AVDictionary **metadata, int64_t *dts, + ID3v2ExtraMetaAPIC **apic, ID3v2ExtraMeta **extra_meta) +{ + static const char id3_priv_owner_ts[] = "com.apple.streaming.transportStreamTimestamp"; + ID3v2ExtraMeta *meta; + + ff_id3v2_read_dict(pb, metadata, ID3v2_DEFAULT_MAGIC, extra_meta); + for (meta = *extra_meta; meta; meta = meta->next) { + if (!strcmp(meta->tag, "PRIV")) { + ID3v2ExtraMetaPRIV *priv = meta->data; + if (priv->datasize == 8 && !strcmp(priv->owner, id3_priv_owner_ts)) { + /* 33-bit MPEG timestamp */ + int64_t ts = AV_RB64(priv->data); + av_log(s, AV_LOG_DEBUG, "HLS ID3 audio timestamp %"PRId64"\n", ts); + if ((ts & ~((1ULL << 33) - 1)) == 0) + *dts = ts; + else + av_log(s, AV_LOG_ERROR, "Invalid HLS ID3 audio timestamp %"PRId64"\n", ts); + } + } else if (!strcmp(meta->tag, "APIC") && apic) + *apic = meta->data; + } +} + +/* Check if the ID3 metadata contents have changed */ +static int id3_has_changed_values(struct playlist *pls, AVDictionary *metadata, + ID3v2ExtraMetaAPIC *apic) +{ + AVDictionaryEntry *entry = NULL; + AVDictionaryEntry *oldentry; + /* check that no keys have changed values */ + while ((entry = av_dict_get(metadata, "", entry, AV_DICT_IGNORE_SUFFIX))) { + oldentry = av_dict_get(pls->id3_initial, entry->key, NULL, AV_DICT_MATCH_CASE); + if (!oldentry || strcmp(oldentry->value, entry->value) != 0) + return 1; + } + + /* check if apic appeared */ + if (apic && (pls->ctx->nb_streams != 2 || !pls->ctx->streams[1]->attached_pic.data)) + return 1; + + if (apic) { + int size = pls->ctx->streams[1]->attached_pic.size; + if (size != apic->buf->size - FF_INPUT_BUFFER_PADDING_SIZE) + return 1; + + if (memcmp(apic->buf->data, pls->ctx->streams[1]->attached_pic.data, size) != 0) + return 1; + } + + return 0; +} + +/* Parse ID3 data and handle the found data */ +static void handle_id3(AVIOContext *pb, struct playlist *pls) +{ + AVDictionary *metadata = NULL; + ID3v2ExtraMetaAPIC *apic = NULL; + ID3v2ExtraMeta *extra_meta = NULL; + int64_t timestamp = AV_NOPTS_VALUE; + + parse_id3(pls->ctx, pb, &metadata, ×tamp, &apic, &extra_meta); + + if (timestamp != AV_NOPTS_VALUE) { + pls->id3_mpegts_timestamp = timestamp; + pls->id3_offset = 0; + } + + if (!pls->id3_found) { + /* initial ID3 tags */ + av_assert0(!pls->id3_deferred_extra); + pls->id3_found = 1; + + /* get picture attachment and set text metadata */ + if (pls->ctx->nb_streams) + ff_id3v2_parse_apic(pls->ctx, &extra_meta); + else + /* demuxer not yet opened, defer picture attachment */ + pls->id3_deferred_extra = extra_meta; + + av_dict_copy(&pls->ctx->metadata, metadata, 0); + pls->id3_initial = metadata; + + } else { + if (!pls->id3_changed && id3_has_changed_values(pls, metadata, apic)) { + avpriv_report_missing_feature(pls->ctx, "Changing ID3 metadata in HLS audio elementary stream"); + pls->id3_changed = 1; + } + av_dict_free(&metadata); + } + + if (!pls->id3_deferred_extra) + ff_id3v2_free_extra_meta(&extra_meta); +} + +/* Intercept and handle ID3 tags between URLContext and AVIOContext */ +static void intercept_id3(struct playlist *pls, uint8_t *buf, + int buf_size, int *len) +{ + /* intercept id3 tags, we do not want to pass them to the raw + * demuxer on all segment switches */ + int bytes; + int id3_buf_pos = 0; + int fill_buf = 0; + + /* gather all the id3 tags */ + while (1) { + /* see if we can retrieve enough data for ID3 header */ + if (*len < ID3v2_HEADER_SIZE && buf_size >= ID3v2_HEADER_SIZE) { + bytes = read_from_url(pls, buf + *len, ID3v2_HEADER_SIZE - *len, READ_COMPLETE); + if (bytes > 0) { + + if (bytes == ID3v2_HEADER_SIZE - *len) + /* no EOF yet, so fill the caller buffer again after + * we have stripped the ID3 tags */ + fill_buf = 1; + + *len += bytes; + + } else if (*len <= 0) { + /* error/EOF */ + *len = bytes; + fill_buf = 0; + } + } + + if (*len < ID3v2_HEADER_SIZE) + break; + + if (ff_id3v2_match(buf, ID3v2_DEFAULT_MAGIC)) { + struct segment *seg = pls->segments[pls->cur_seq_no - pls->start_seq_no]; + int64_t maxsize = seg->size >= 0 ? seg->size : 1024*1024; + int taglen = ff_id3v2_tag_len(buf); + int tag_got_bytes = FFMIN(taglen, *len); + int remaining = taglen - tag_got_bytes; + + if (taglen > maxsize) { + av_log(pls->ctx, AV_LOG_ERROR, "Too large HLS ID3 tag (%d > %"PRId64" bytes)\n", + taglen, maxsize); + break; + } + + /* + * Copy the id3 tag to our temporary id3 buffer. + * We could read a small id3 tag directly without memcpy, but + * we would still need to copy the large tags, and handling + * both of those cases together with the possibility for multiple + * tags would make the handling a bit complex. + */ + pls->id3_buf = av_fast_realloc(pls->id3_buf, &pls->id3_buf_size, id3_buf_pos + taglen); + if (!pls->id3_buf) + break; + memcpy(pls->id3_buf + id3_buf_pos, buf, tag_got_bytes); + id3_buf_pos += tag_got_bytes; + + /* strip the intercepted bytes */ + *len -= tag_got_bytes; + memmove(buf, buf + tag_got_bytes, *len); + av_log(pls->ctx, AV_LOG_DEBUG, "Stripped %d HLS ID3 bytes\n", tag_got_bytes); + + if (remaining > 0) { + /* read the rest of the tag in */ + if (read_from_url(pls, pls->id3_buf + id3_buf_pos, remaining, READ_COMPLETE) != remaining) + break; + id3_buf_pos += remaining; + av_log(pls->ctx, AV_LOG_DEBUG, "Stripped additional %d HLS ID3 bytes\n", remaining); + } + + } else { + /* no more ID3 tags */ + break; + } + } + + /* re-fill buffer for the caller unless EOF */ + if (*len >= 0 && (fill_buf || *len == 0)) { + bytes = read_from_url(pls, buf + *len, buf_size - *len, READ_NORMAL); + + /* ignore error if we already had some data */ + if (bytes >= 0) + *len += bytes; + else if (*len == 0) + *len = bytes; + } + + if (pls->id3_buf) { + /* Now parse all the ID3 tags */ + AVIOContext id3ioctx; + ffio_init_context(&id3ioctx, pls->id3_buf, id3_buf_pos, 0, NULL, NULL, NULL, NULL); + handle_id3(&id3ioctx, pls); + } + + if (pls->is_id3_timestamped == -1) + pls->is_id3_timestamped = (pls->id3_mpegts_timestamp != AV_NOPTS_VALUE); +} + static int open_input(HLSContext *c, struct playlist *pls) { AVDictionary *opts = NULL; @@ -400,10 +916,26 @@ static int open_input(HLSContext *c, struct playlist *pls) // Same opts for key request (ffurl_open mutilates the opts so it cannot be used twice) av_dict_copy(&opts2, opts, 0); + if (seg->size >= 0) { + /* try to restrict the HTTP request to the part we want + * (if this is in fact a HTTP request) */ + char offset[24] = { 0 }; + char end_offset[24] = { 0 }; + snprintf(offset, sizeof(offset) - 1, "%"PRId64, + seg->url_offset); + snprintf(end_offset, sizeof(end_offset) - 1, "%"PRId64, + seg->url_offset + seg->size); + av_dict_set(&opts, "offset", offset, 0); + av_dict_set(&opts, "end_offset", end_offset, 0); + } + + av_log(pls->parent, AV_LOG_VERBOSE, "HLS request for url '%s', offset %"PRId64", playlist %d\n", + seg->url, seg->url_offset, pls->index); + if (seg->key_type == KEY_NONE) { ret = ffurl_open(&pls->input, seg->url, AVIO_FLAG_READ, &pls->parent->interrupt_callback, &opts); - goto cleanup; + } else if (seg->key_type == KEY_AES_128) { char iv[33], key[33], url[MAX_URL_SIZE]; if (strcmp(seg->key, pls->key_url)) { @@ -445,31 +977,76 @@ static int open_input(HLSContext *c, struct playlist *pls) else ret = AVERROR(ENOSYS); + /* Seek to the requested position. If this was a HTTP request, the offset + * should already be where want it to, but this allows e.g. local testing + * without a HTTP server. */ + if (ret == 0 && seg->key_type == KEY_NONE) { + int seekret = ffurl_seek(pls->input, seg->url_offset, SEEK_SET); + if (seekret < 0) { + av_log(pls->parent, AV_LOG_ERROR, "Unable to seek to offset %"PRId64" of HLS segment '%s'\n", seg->url_offset, seg->url); + ret = seekret; + ffurl_close(pls->input); + pls->input = NULL; + } + } + cleanup: av_dict_free(&opts); av_dict_free(&opts2); + pls->cur_seg_offset = 0; return ret; } +static int64_t default_reload_interval(struct playlist *pls) +{ + return pls->n_segments > 0 ? + pls->segments[pls->n_segments - 1]->duration : + pls->target_duration; +} + static int read_data(void *opaque, uint8_t *buf, int buf_size) { struct playlist *v = opaque; HLSContext *c = v->parent->priv_data; int ret, i; + int just_opened = 0; restart: + if (!v->needed) + return AVERROR_EOF; + if (!v->input) { + int64_t reload_interval; + + /* Check that the playlist is still needed before opening a new + * segment. */ + if (v->ctx && v->ctx->nb_streams && + v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) { + v->needed = 0; + for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams; + i++) { + if (v->parent->streams[i]->discard < AVDISCARD_ALL) + v->needed = 1; + } + } + if (!v->needed) { + av_log(v->parent, AV_LOG_INFO, "No longer receiving playlist %d\n", + v->index); + return AVERROR_EOF; + } + /* If this is a live stream and the reload interval has elapsed since * the last playlist reload, reload the playlists now. */ - int64_t reload_interval = v->n_segments > 0 ? - v->segments[v->n_segments - 1]->duration : - v->target_duration; + reload_interval = default_reload_interval(v); reload: if (!v->finished && av_gettime() - v->last_load_time >= reload_interval) { - if ((ret = parse_playlist(c, v->url, v, NULL)) < 0) + if ((ret = parse_playlist(c, v->url, v, NULL)) < 0) { + av_log(v->parent, AV_LOG_WARNING, "Failed to reload playlist %d\n", + v->index); return ret; + } /* If we need to reload the playlist again below (if * there's still no more segments), switch to a reload * interval of half the target duration. */ @@ -494,33 +1071,30 @@ reload: } ret = open_input(c, v); - if (ret < 0) + if (ret < 0) { + av_log(v->parent, AV_LOG_WARNING, "Failed to open segment of playlist %d\n", + v->index); return ret; + } + just_opened = 1; } - ret = ffurl_read(v->input, buf, buf_size); - if (ret > 0) + + ret = read_from_url(v, buf, buf_size, READ_NORMAL); + if (ret > 0) { + if (just_opened && v->is_id3_timestamped != 0) { + /* Intercept ID3 tags here, elementary audio streams are required + * to convey timestamps using them in the beginning of each segment. */ + intercept_id3(v, buf, buf_size, &ret); + } + return ret; + } ffurl_close(v->input); v->input = NULL; v->cur_seq_no++; - c->end_of_segment = 1; c->cur_seq_no = v->cur_seq_no; - if (v->ctx && v->ctx->nb_streams && - v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) { - v->needed = 0; - for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams; - i++) { - if (v->parent->streams[i]->discard < AVDISCARD_ALL) - v->needed = 1; - } - } - if (!v->needed) { - av_log(v->parent, AV_LOG_INFO, "No longer receiving playlist %d\n", - v->index); - return AVERROR_EOF; - } goto restart; } @@ -543,6 +1117,125 @@ static int playlist_in_multiple_variants(HLSContext *c, struct playlist *pls) return variant_count >= 2; } +static void add_renditions_to_variant(HLSContext *c, struct variant *var, + enum AVMediaType type, const char *group_id) +{ + int i; + + for (i = 0; i < c->n_renditions; i++) { + struct rendition *rend = c->renditions[i]; + + if (rend->type == type && !strcmp(rend->group_id, group_id)) { + + if (rend->playlist) + /* rendition is an external playlist + * => add the playlist to the variant */ + dynarray_add(&var->playlists, &var->n_playlists, rend->playlist); + else + /* rendition is part of the variant main Media Playlist + * => add the rendition to the main Media Playlist */ + dynarray_add(&var->playlists[0]->renditions, + &var->playlists[0]->n_renditions, + rend); + } + } +} + +static void add_metadata_from_renditions(AVFormatContext *s, struct playlist *pls, + enum AVMediaType type) +{ + int rend_idx = 0; + int i; + + for (i = 0; i < pls->ctx->nb_streams; i++) { + AVStream *st = s->streams[pls->stream_offset + i]; + + if (st->codec->codec_type != type) + continue; + + for (; rend_idx < pls->n_renditions; rend_idx++) { + struct rendition *rend = pls->renditions[rend_idx]; + + if (rend->type != type) + continue; + + if (rend->language[0]) + av_dict_set(&st->metadata, "language", rend->language, 0); + if (rend->name[0]) + av_dict_set(&st->metadata, "comment", rend->name, 0); + + st->disposition |= rend->disposition; + } + if (rend_idx >=pls->n_renditions) + break; + } +} + +/* if timestamp was in valid range: returns 1 and sets seq_no + * if not: returns 0 and sets seq_no to closest segment */ +static int find_timestamp_in_playlist(HLSContext *c, struct playlist *pls, + int64_t timestamp, int *seq_no) +{ + int i; + int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? + 0 : c->first_timestamp; + + if (timestamp < pos) { + *seq_no = pls->start_seq_no; + return 0; + } + + for (i = 0; i < pls->n_segments; i++) { + int64_t diff = pos + pls->segments[i]->duration - timestamp; + if (diff > 0) { + *seq_no = pls->start_seq_no + i; + return 1; + } + pos += pls->segments[i]->duration; + } + + *seq_no = pls->start_seq_no + pls->n_segments - 1; + + return 0; +} + +static int select_cur_seq_no(HLSContext *c, struct playlist *pls) +{ + int seq_no; + + if (!pls->finished && !c->first_packet && + av_gettime() - pls->last_load_time >= default_reload_interval(pls)) + /* reload the playlist since it was suspended */ + parse_playlist(c, pls->url, pls, NULL); + + /* If playback is already in progress (we are just selecting a new + * playlist) and this is a complete file, find the matching segment + * by counting durations. */ + if (pls->finished && c->cur_timestamp != AV_NOPTS_VALUE) { + find_timestamp_in_playlist(c, pls, c->cur_timestamp, &seq_no); + return seq_no; + } + + if (!pls->finished) { + if (!c->first_packet && /* we are doing a segment selection during playback */ + c->cur_seq_no >= pls->start_seq_no && + c->cur_seq_no < pls->start_seq_no + pls->n_segments) + /* While spec 3.4.3 says that we cannot assume anything about the + * content at the same sequence number on different playlists, + * in practice this seems to work and doing it otherwise would + * require us to download a segment to inspect its timestamps. */ + return c->cur_seq_no; + + /* If this is a live stream with more than 3 segments, start at the + * third last segment. */ + if (pls->n_segments > 3) + return pls->start_seq_no + pls->n_segments - 3; + } + + /* Otherwise just start on the first segment. */ + return pls->start_seq_no; +} + static int hls_read_header(AVFormatContext *s) { URLContext *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb->opaque; @@ -551,6 +1244,10 @@ static int hls_read_header(AVFormatContext *s) c->interrupt_callback = &s->interrupt_callback; + c->first_packet = 1; + c->first_timestamp = AV_NOPTS_VALUE; + c->cur_timestamp = AV_NOPTS_VALUE; + // if the URL context is good, read important options we must broker later if (u && u->prot->priv_data_class) { // get the previous user agent & set back to null if string size is zero @@ -605,6 +1302,18 @@ static int hls_read_header(AVFormatContext *s) s->duration = duration; } + /* Associate renditions with variants */ + for (i = 0; i < c->n_variants; i++) { + struct variant *var = c->variants[i]; + + if (var->audio_group[0]) + add_renditions_to_variant(c, var, AVMEDIA_TYPE_AUDIO, var->audio_group); + if (var->video_group[0]) + add_renditions_to_variant(c, var, AVMEDIA_TYPE_VIDEO, var->video_group); + if (var->subtitles_group[0]) + add_renditions_to_variant(c, var, AVMEDIA_TYPE_SUBTITLE, var->subtitles_group); + } + /* Open the demuxer for each playlist */ for (i = 0; i < c->n_playlists; i++) { struct playlist *pls = c->playlists[i]; @@ -621,12 +1330,7 @@ static int hls_read_header(AVFormatContext *s) pls->index = i; pls->needed = 1; pls->parent = s; - - /* If this is a live stream with more than 3 segments, start at the - * third last segment. */ - pls->cur_seq_no = pls->start_seq_no; - if (!pls->finished && pls->n_segments > 3) - pls->cur_seq_no = pls->start_seq_no + pls->n_segments - 3; + pls->cur_seq_no = select_cur_seq_no(c, pls); pls->read_buffer = av_malloc(INITIAL_BUFFER_SIZE); ffio_init_context(&pls->pb, pls->read_buffer, INITIAL_BUFFER_SIZE, 0, pls, @@ -650,11 +1354,21 @@ static int hls_read_header(AVFormatContext *s) if (ret < 0) goto fail; + if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) { + ff_id3v2_parse_apic(pls->ctx, &pls->id3_deferred_extra); + avformat_queue_attached_pictures(pls->ctx); + ff_id3v2_free_extra_meta(&pls->id3_deferred_extra); + pls->id3_deferred_extra = NULL; + } + pls->ctx->ctx_flags &= ~AVFMTCTX_NOHEADER; ret = avformat_find_stream_info(pls->ctx, NULL); if (ret < 0) goto fail; + if (pls->is_id3_timestamped == -1) + av_log(s, AV_LOG_WARNING, "No expected HTTP requests have been made\n"); + /* Create new AVStreams for each stream in this playlist */ for (j = 0; j < pls->ctx->nb_streams; j++) { AVStream *st = avformat_new_stream(s, NULL); @@ -664,10 +1378,19 @@ static int hls_read_header(AVFormatContext *s) goto fail; } 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, pls->ctx->streams[j]->codec); + + if (pls->is_id3_timestamped) /* custom timestamps via id3 */ + avpriv_set_pts_info(st, 33, 1, MPEG_TIME_BASE); + else + avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den); } + add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_AUDIO); + add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_VIDEO); + add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_SUBTITLE); + stream_offset += pls->ctx->nb_streams; } @@ -701,14 +1424,11 @@ static int hls_read_header(AVFormatContext *s) } } - c->first_packet = 1; - c->first_timestamp = AV_NOPTS_VALUE; - c->seek_timestamp = AV_NOPTS_VALUE; - return 0; fail: free_playlist_list(c); free_variant_list(c); + free_rendition_list(c); return ret; } @@ -732,9 +1452,15 @@ static int recheck_discard_flags(AVFormatContext *s, int first) if (pls->cur_needed && !pls->needed) { pls->needed = 1; changed = 1; - pls->cur_seq_no = c->cur_seq_no; + pls->cur_seq_no = select_cur_seq_no(c, pls); pls->pb.eof_reached = 0; - av_log(s, AV_LOG_INFO, "Now receiving playlist %d\n", i); + if (c->cur_timestamp != AV_NOPTS_VALUE) { + /* catch up */ + pls->seek_timestamp = c->cur_timestamp; + pls->seek_flags = AVSEEK_FLAG_ANY; + pls->seek_stream_index = -1; + } + av_log(s, AV_LOG_INFO, "Now receiving playlist %d, segment %d\n", i, pls->cur_seq_no); } else if (first && !pls->cur_needed && pls->needed) { if (pls->input) ffurl_close(pls->input); @@ -747,18 +1473,55 @@ static int recheck_discard_flags(AVFormatContext *s, int first) return changed; } +static void fill_timing_for_id3_timestamped_stream(struct playlist *pls) +{ + if (pls->id3_offset >= 0) { + pls->pkt.dts = pls->id3_mpegts_timestamp + + av_rescale_q(pls->id3_offset, + pls->ctx->streams[pls->pkt.stream_index]->time_base, + MPEG_TIME_BASE_Q); + if (pls->pkt.duration) + pls->id3_offset += pls->pkt.duration; + else + pls->id3_offset = -1; + } else { + /* there have been packets with unknown duration + * since the last id3 tag, should not normally happen */ + pls->pkt.dts = AV_NOPTS_VALUE; + } + + if (pls->pkt.duration) + pls->pkt.duration = av_rescale_q(pls->pkt.duration, + pls->ctx->streams[pls->pkt.stream_index]->time_base, + MPEG_TIME_BASE_Q); + + pls->pkt.pts = AV_NOPTS_VALUE; +} + +static AVRational get_timebase(struct playlist *pls) +{ + if (pls->is_id3_timestamped) + return MPEG_TIME_BASE_Q; + + return pls->ctx->streams[pls->pkt.stream_index]->time_base; +} + +static int compare_ts_with_wrapdetect(int64_t ts_a, struct playlist *pls_a, + int64_t ts_b, struct playlist *pls_b) +{ + int64_t scaled_ts_a = av_rescale_q(ts_a, get_timebase(pls_a), MPEG_TIME_BASE_Q); + int64_t scaled_ts_b = av_rescale_q(ts_b, get_timebase(pls_b), MPEG_TIME_BASE_Q); + + return av_compare_mod(scaled_ts_a, scaled_ts_b, 1LL << 33); +} + static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) { HLSContext *c = s->priv_data; int ret, i, minplaylist = -1; - if (c->first_packet) { - recheck_discard_flags(s, 1); - c->first_packet = 0; - } + recheck_discard_flags(s, c->first_packet); -start: - c->end_of_segment = 0; for (i = 0; i < c->n_playlists; i++) { struct playlist *pls = c->playlists[i]; /* Make sure we've got one buffered packet from each open playlist @@ -766,7 +1529,7 @@ start: if (pls->needed && !pls->pkt.data) { while (1) { int64_t ts_diff; - AVStream *st; + AVRational tb; ret = av_read_frame(pls->ctx, &pls->pkt); if (ret < 0) { if (!url_feof(&pls->pb) && ret != AVERROR_EOF) @@ -774,71 +1537,72 @@ start: reset_packet(&pls->pkt); break; } else { + /* stream_index check prevents matching picture attachments etc. */ + if (pls->is_id3_timestamped && pls->pkt.stream_index == 0) { + /* audio elementary streams are id3 timestamped */ + fill_timing_for_id3_timestamped_stream(pls); + } + if (c->first_timestamp == AV_NOPTS_VALUE && pls->pkt.dts != AV_NOPTS_VALUE) c->first_timestamp = av_rescale_q(pls->pkt.dts, - pls->ctx->streams[pls->pkt.stream_index]->time_base, - AV_TIME_BASE_Q); + get_timebase(pls), AV_TIME_BASE_Q); } - if (c->seek_timestamp == AV_NOPTS_VALUE) + if (pls->seek_timestamp == AV_NOPTS_VALUE) break; - if (pls->pkt.dts == AV_NOPTS_VALUE) { - c->seek_timestamp = AV_NOPTS_VALUE; - break; - } + if (pls->seek_stream_index < 0 || + pls->seek_stream_index == pls->pkt.stream_index) { - st = pls->ctx->streams[pls->pkt.stream_index]; - ts_diff = av_rescale_rnd(pls->pkt.dts, AV_TIME_BASE, - st->time_base.den, AV_ROUND_DOWN) - - c->seek_timestamp; - if (ts_diff >= 0 && (c->seek_flags & AVSEEK_FLAG_ANY || - pls->pkt.flags & AV_PKT_FLAG_KEY)) { - c->seek_timestamp = AV_NOPTS_VALUE; - break; + if (pls->pkt.dts == AV_NOPTS_VALUE) { + pls->seek_timestamp = AV_NOPTS_VALUE; + break; + } + + tb = get_timebase(pls); + ts_diff = av_rescale_rnd(pls->pkt.dts, AV_TIME_BASE, + tb.den, AV_ROUND_DOWN) - + pls->seek_timestamp; + if (ts_diff >= 0 && (pls->seek_flags & AVSEEK_FLAG_ANY || + pls->pkt.flags & AV_PKT_FLAG_KEY)) { + pls->seek_timestamp = AV_NOPTS_VALUE; + break; + } } av_free_packet(&pls->pkt); reset_packet(&pls->pkt); } } - /* Check if this stream still is on an earlier segment number, or - * has the packet with the lowest dts */ + /* Check if this stream has the packet with the lowest dts */ if (pls->pkt.data) { struct playlist *minpls = minplaylist < 0 ? NULL : c->playlists[minplaylist]; - if (minplaylist < 0 || pls->cur_seq_no < minpls->cur_seq_no) { + if (minplaylist < 0) { minplaylist = i; - } else if (pls->cur_seq_no == minpls->cur_seq_no) { + } else { int64_t dts = pls->pkt.dts; int64_t mindts = minpls->pkt.dts; - AVStream *st = pls->ctx->streams[pls->pkt.stream_index]; - AVStream *minst = minpls->ctx->streams[minpls->pkt.stream_index]; - if (dts == AV_NOPTS_VALUE) { + if (dts == AV_NOPTS_VALUE || + (mindts != AV_NOPTS_VALUE && compare_ts_with_wrapdetect(dts, pls, mindts, minpls) < 0)) minplaylist = i; - } else if (mindts != AV_NOPTS_VALUE) { - if (st->start_time != AV_NOPTS_VALUE) - dts -= st->start_time; - if (minst->start_time != AV_NOPTS_VALUE) - mindts -= minst->start_time; - - if (av_compare_ts(dts, st->time_base, - mindts, minst->time_base) < 0) - minplaylist = i; - } } } } - if (c->end_of_segment) { - if (recheck_discard_flags(s, 0)) - goto start; - } + /* If we got a packet, return it */ if (minplaylist >= 0) { - *pkt = c->playlists[minplaylist]->pkt; - pkt->stream_index += c->playlists[minplaylist]->stream_offset; + struct playlist *pls = c->playlists[minplaylist]; + *pkt = pls->pkt; + pkt->stream_index += pls->stream_offset; reset_packet(&c->playlists[minplaylist]->pkt); + + if (pkt->dts != AV_NOPTS_VALUE) + c->cur_timestamp = av_rescale_q(pkt->dts, + pls->ctx->streams[pls->pkt.stream_index]->time_base, + AV_TIME_BASE_Q); + return 0; } return AVERROR_EOF; @@ -850,6 +1614,7 @@ static int hls_close(AVFormatContext *s) free_playlist_list(c); free_variant_list(c); + free_rendition_list(c); return 0; } @@ -857,32 +1622,49 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { HLSContext *c = s->priv_data; - int i, j, ret; + struct playlist *seek_pls = NULL; + int i, seq_no; + int64_t first_timestamp, seek_timestamp, duration; - if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->playlists[0]->finished) + if ((flags & AVSEEK_FLAG_BYTE) || + !(c->variants[0]->playlists[0]->finished || c->variants[0]->playlists[0]->type == PLS_TYPE_EVENT)) return AVERROR(ENOSYS); - c->seek_flags = flags; - c->seek_timestamp = stream_index < 0 ? timestamp : - av_rescale_rnd(timestamp, AV_TIME_BASE, - s->streams[stream_index]->time_base.den, - flags & AVSEEK_FLAG_BACKWARD ? - AV_ROUND_DOWN : AV_ROUND_UP); - timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE, stream_index >= 0 ? - s->streams[stream_index]->time_base.den : - AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? - AV_ROUND_DOWN : AV_ROUND_UP); - if (s->duration < c->seek_timestamp) { - c->seek_timestamp = AV_NOPTS_VALUE; + first_timestamp = c->first_timestamp == AV_NOPTS_VALUE ? + 0 : c->first_timestamp; + + seek_timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE, + s->streams[stream_index]->time_base.den, + flags & AVSEEK_FLAG_BACKWARD ? + AV_ROUND_DOWN : AV_ROUND_UP); + + duration = s->duration == AV_NOPTS_VALUE ? + 0 : s->duration; + + if (0 < duration && duration < seek_timestamp - first_timestamp) return AVERROR(EIO); + + /* find the playlist with the specified stream */ + for (i = 0; i < c->n_playlists; i++) { + struct playlist *pls = c->playlists[i]; + if (stream_index >= pls->stream_offset && + stream_index - pls->stream_offset < pls->ctx->nb_streams) { + seek_pls = pls; + break; + } } + /* check if the timestamp is valid for the playlist with the + * specified stream index */ + if (!seek_pls || !find_timestamp_in_playlist(c, seek_pls, seek_timestamp, &seq_no)) + return AVERROR(EIO); + + /* set segment now so we do not need to search again below */ + seek_pls->cur_seq_no = seq_no; + seek_pls->seek_stream_index = stream_index - seek_pls->stream_offset; - ret = AVERROR(EIO); for (i = 0; i < c->n_playlists; i++) { /* Reset reading */ struct playlist *pls = c->playlists[i]; - int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? - 0 : c->first_timestamp; if (pls->input) { ffurl_close(pls->input); pls->input = NULL; @@ -894,21 +1676,26 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, pls->pb.buf_end = pls->pb.buf_ptr = pls->pb.buffer; /* Reset the pos, to let the mpegts demuxer know we've seeked. */ pls->pb.pos = 0; + /* Flush the packet queue of the subdemuxer. */ + ff_read_frame_flush(pls->ctx); - /* Locate the segment that contains the target timestamp */ - for (j = 0; j < pls->n_segments; j++) { - if (timestamp >= pos && - timestamp < pos + pls->segments[j]->duration) { - pls->cur_seq_no = pls->start_seq_no + j; - ret = 0; - break; - } - pos += pls->segments[j]->duration; + pls->seek_timestamp = seek_timestamp; + pls->seek_flags = flags; + + if (pls != seek_pls) { + /* set closest segment seq_no for playlists not handled above */ + find_timestamp_in_playlist(c, pls, seek_timestamp, &pls->cur_seq_no); + /* seek the playlist to the given position without taking + * keyframes into account since this playlist does not have the + * specified stream where we should look for the keyframes */ + pls->seek_stream_index = -1; + pls->seek_flags |= AVSEEK_FLAG_ANY; } - if (ret) - c->seek_timestamp = AV_NOPTS_VALUE; } - return ret; + + c->cur_timestamp = seek_timestamp; + + return 0; } static int hls_probe(AVProbeData *p) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 3b5039701..388a23a18 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -33,7 +33,7 @@ typedef struct ListEntry { char name[1024]; - int duration; + double duration; struct ListEntry *next; } ListEntry; @@ -41,6 +41,7 @@ typedef struct HLSContext { const AVClass *class; // Class for private options. unsigned number; int64_t sequence; + int64_t start_sequence; AVOutputFormat *oformat; AVFormatContext *avf; float time; // Set by a private option. @@ -50,11 +51,12 @@ typedef struct HLSContext { int has_video; int64_t start_pts; int64_t end_pts; - int64_t duration; // last segment duration computed so far, in seconds + double duration; // last segment duration computed so far, in seconds int nb_entries; ListEntry *list; ListEntry *end_list; char *basename; + char *baseurl; AVIOContext *pb; } HLSContext; @@ -83,7 +85,7 @@ static int hls_mux_init(AVFormatContext *s) return 0; } -static int append_entry(HLSContext *hls, uint64_t duration) +static int append_entry(HLSContext *hls, double duration) { ListEntry *en = av_malloc(sizeof(*en)); @@ -102,7 +104,7 @@ static int append_entry(HLSContext *hls, uint64_t duration) hls->end_list = en; - if (hls->nb_entries >= hls->size) { + if (hls->size && hls->nb_entries >= hls->size) { en = hls->list; hls->list = en->next; av_free(en); @@ -131,6 +133,7 @@ static int hls_window(AVFormatContext *s, int last) ListEntry *en; int target_duration = 0; int ret = 0; + int64_t sequence = FFMAX(hls->start_sequence, hls->sequence - hls->nb_entries); if ((ret = avio_open2(&hls->pb, s->filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL)) < 0) @@ -138,17 +141,21 @@ static int hls_window(AVFormatContext *s, int last) for (en = hls->list; en; en = en->next) { if (target_duration < en->duration) - target_duration = en->duration; + target_duration = ceil(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", - FFMAX(0, hls->sequence - hls->size)); + avio_printf(hls->pb, "#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); + avio_printf(hls->pb, "#EXTINF:%f,\n", en->duration); + if (hls->baseurl) + avio_printf(hls->pb, "%s", hls->baseurl); avio_printf(hls->pb, "%s\n", en->name); } @@ -167,7 +174,7 @@ static int hls_start(AVFormatContext *s) int err = 0; if (av_get_frame_filename(oc->filename, sizeof(oc->filename), - c->basename, c->wrap ? c->number % c->wrap : c->number) < 0) { + c->basename, c->wrap ? c->sequence % c->wrap : c->sequence) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->basename); return AVERROR(EINVAL); } @@ -191,8 +198,7 @@ static int hls_write_header(AVFormatContext *s) const char *pattern = "%d.ts"; int basename_size = strlen(s->filename) + strlen(pattern) + 1; - hls->number = 0; - + hls->sequence = hls->start_sequence; hls->recording_time = hls->time * AV_TIME_BASE; hls->start_pts = AV_NOPTS_VALUE; @@ -270,8 +276,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) is_ref_pkt = can_split = 0; if (is_ref_pkt) - hls->duration = av_rescale(pkt->pts - hls->end_pts, - st->time_base.num, st->time_base.den); + hls->duration = (double)(pkt->pts - hls->end_pts) + * st->time_base.num / st->time_base.den; if (can_split && av_compare_ts(pkt->pts - hls->start_pts, st->time_base, end_pts, AV_TIME_BASE_Q) >= 0) { @@ -321,10 +327,11 @@ static int hls_write_trailer(struct AVFormatContext *s) #define OFFSET(x) offsetof(HLSContext, x) #define E AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - {"start_number", "set first number in the sequence", OFFSET(sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E}, + {"start_number", "set first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E}, {"hls_time", "set segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E}, {"hls_list_size", "set maximum number of playlist entries", OFFSET(size), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E}, {"hls_wrap", "set number after which the index wraps", OFFSET(wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E}, + {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, { NULL }, }; @@ -341,8 +348,8 @@ AVOutputFormat ff_hls_muxer = { .long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"), .extensions = "m3u8", .priv_data_size = sizeof(HLSContext), - .audio_codec = AV_CODEC_ID_MP2, - .video_codec = AV_CODEC_ID_MPEG2VIDEO, + .audio_codec = AV_CODEC_ID_AAC, + .video_codec = AV_CODEC_ID_H264, .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH, .write_header = hls_write_header, .write_packet = hls_write_packet, diff --git a/libavformat/hnm.c b/libavformat/hnm.c index 47a1808af..1320fa520 100644 --- a/libavformat/hnm.c +++ b/libavformat/hnm.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/intreadwrite.h" #include "avformat.h" #include "internal.h" @@ -90,7 +92,7 @@ static int hnm_read_header(AVFormatContext *s) hnm->currentframe = 0; - if (hnm->width < 320 || hnm->width > 640 || + if (hnm->width < 256 || hnm->width > 640 || hnm->height < 150 || hnm->height > 480) { av_log(s, AV_LOG_ERROR, "invalid resolution: %ux%u\n", hnm->width, hnm->height); @@ -149,8 +151,9 @@ static int hnm_read_packet(AVFormatContext *s, AVPacket *pkt) avio_skip(pb, 2); if (chunk_size > hnm->superchunk_remaining || !chunk_size) { - av_log(s, AV_LOG_ERROR, "invalid chunk size: %u, offset: %u\n", - chunk_size, (int) avio_tell(pb)); + av_log(s, AV_LOG_ERROR, + "invalid chunk size: %"PRIu32", offset: %"PRId64"\n", + chunk_size, avio_tell(pb)); avio_skip(pb, hnm->superchunk_remaining - 8); hnm->superchunk_remaining = 0; } @@ -172,8 +175,8 @@ static int hnm_read_packet(AVFormatContext *s, AVPacket *pkt) break; default: - av_log(s, AV_LOG_WARNING, "unknown chunk found: %d, offset: %d\n", - chunk_id, (int) avio_tell(pb)); + av_log(s, AV_LOG_WARNING, "unknown chunk found: %"PRIu16", offset: %"PRId64"\n", + chunk_id, avio_tell(pb)); avio_skip(pb, chunk_size - 8); hnm->superchunk_remaining -= chunk_size; break; diff --git a/libavformat/http.c b/libavformat/http.c index a78de945b..3e172e364 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -746,7 +746,7 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, "Content-Type: %s\r\n", s->content_type); if (!has_header(s->headers, "\r\nCookie: ") && s->cookies) { char *cookies = NULL; - if (!get_cookies(s, &cookies, path, hoststr)) { + if (!get_cookies(s, &cookies, path, hoststr) && cookies) { len += av_strlcatf(headers + len, sizeof(headers) - len, "Cookie: %s\r\n", cookies); av_free(cookies); @@ -775,17 +775,14 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, authstr ? authstr : "", proxyauthstr ? "Proxy-" : "", proxyauthstr ? proxyauthstr : ""); - av_freep(&authstr); - av_freep(&proxyauthstr); - av_log(h, AV_LOG_DEBUG, "request: %s\n", s->buffer); if ((err = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0) - return err; + goto done; if (s->post_data) if ((err = ffurl_write(s->hd, s->post_data, s->post_datalen)) < 0) - return err; + goto done; /* init input buffer */ s->buf_ptr = s->buffer; @@ -802,15 +799,20 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, * we've still to send the POST data, but the code calling this * function will check http_code after we return. */ s->http_code = 200; - return 0; + err = 0; + goto done; } /* wait for header */ err = http_read_header(h, new_location); if (err < 0) - return err; + goto done; - return (off == s->off) ? 0 : -1; + err = (off == s->off) ? 0 : -1; +done: + av_freep(&authstr); + av_freep(&proxyauthstr); + return err; } @@ -888,7 +890,6 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) if (!s->chunksize) { char line[32]; - for(;;) { do { if ((err = http_get_line(s, line, sizeof(line))) < 0) return err; @@ -900,8 +901,6 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) if (!s->chunksize) return 0; - break; - } } size = FFMIN(size, s->chunksize); } @@ -1059,16 +1058,21 @@ static int64_t http_seek(URLContext *h, int64_t off, int whence) else if ((s->filesize == -1 && whence == SEEK_END) || h->is_streamed) return AVERROR(ENOSYS); - /* we save the old context in case the seek fails */ - old_buf_size = s->buf_end - s->buf_ptr; - memcpy(old_buf, s->buf_ptr, old_buf_size); - s->hd = NULL; if (whence == SEEK_CUR) off += s->off; else if (whence == SEEK_END) off += s->filesize; + else if (whence != SEEK_SET) + return AVERROR(EINVAL); + if (off < 0) + return AVERROR(EINVAL); s->off = off; + /* we save the old context in case the seek fails */ + old_buf_size = s->buf_end - s->buf_ptr; + memcpy(old_buf, s->buf_ptr, old_buf_size); + s->hd = NULL; + /* if it fails, continue on old connection */ av_dict_copy(&options, s->chained_options, 0); if ((ret = http_open_cnx(h, &options)) < 0) { diff --git a/libavformat/httpauth.c b/libavformat/httpauth.c index 3f90975ff..dbe3eff48 100644 --- a/libavformat/httpauth.c +++ b/libavformat/httpauth.c @@ -224,8 +224,11 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username, av_strlcatf(authstr, len, ",nonce=\"%s\"", digest->nonce); av_strlcatf(authstr, len, ",uri=\"%s\"", uri); av_strlcatf(authstr, len, ",response=\"%s\"", response); + + // we are violating the RFC and use "" because all others seem to do that too. if (digest->algorithm[0]) av_strlcatf(authstr, len, ",algorithm=\"%s\"", digest->algorithm); + if (digest->opaque[0]) av_strlcatf(authstr, len, ",opaque=\"%s\"", digest->opaque); if (digest->qop[0]) { diff --git a/libavformat/icodec.c b/libavformat/icodec.c index 4c038e961..847f0eea2 100644 --- a/libavformat/icodec.c +++ b/libavformat/icodec.c @@ -58,7 +58,7 @@ static int read_header(AVFormatContext *s) avio_skip(pb, 4); ico->nb_images = avio_rl16(pb); - ico->images = av_malloc(ico->nb_images * sizeof(IcoImage)); + ico->images = av_malloc_array(ico->nb_images, sizeof(IcoImage)); if (!ico->images) return AVERROR(ENOMEM); diff --git a/libavformat/icoenc.c b/libavformat/icoenc.c index 561c6cadc..dcf906513 100644 --- a/libavformat/icoenc.c +++ b/libavformat/icoenc.c @@ -101,7 +101,7 @@ static int ico_write_header(AVFormatContext *s) avio_skip(pb, 16); } - ico->images = av_mallocz(ico->nb_images * sizeof(IcoMuxContext)); + ico->images = av_mallocz_array(ico->nb_images, sizeof(IcoMuxContext)); if (!ico->images) return AVERROR(ENOMEM); diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 43636ec9e..fb89e8394 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -59,6 +59,7 @@ const AVMetadataConv ff_id3v2_34_metadata_conv[] = { }; const AVMetadataConv ff_id3v2_4_metadata_conv[] = { + { "TCMP", "compilation" }, { "TDRL", "date" }, { "TDRC", "date" }, { "TDEN", "creation_time" }, @@ -71,6 +72,7 @@ const AVMetadataConv ff_id3v2_4_metadata_conv[] = { static const AVMetadataConv id3v2_2_metadata_conv[] = { { "TAL", "album" }, { "TCO", "genre" }, + { "TCP", "compilation" }, { "TT2", "title" }, { "TEN", "encoded_by" }, { "TP1", "artist" }, @@ -325,14 +327,14 @@ static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, geob_data = av_mallocz(sizeof(ID3v2ExtraMetaGEOB)); if (!geob_data) { - av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n", + av_log(s, AV_LOG_ERROR, "Failed to alloc %"SIZE_SPECIFIER" bytes\n", sizeof(ID3v2ExtraMetaGEOB)); return; } new_extra = av_mallocz(sizeof(ID3v2ExtraMeta)); if (!new_extra) { - av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n", + av_log(s, AV_LOG_ERROR, "Failed to alloc %"SIZE_SPECIFIER" bytes\n", sizeof(ID3v2ExtraMeta)); goto fail; } diff --git a/libavformat/id3v2enc.c b/libavformat/id3v2enc.c index 4d555b3d2..8b804c4d4 100644 --- a/libavformat/id3v2enc.c +++ b/libavformat/id3v2enc.c @@ -283,7 +283,7 @@ int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt) /* get the picture type */ e = av_dict_get(st->metadata, "comment", NULL, 0); for (i = 0; e && i < FF_ARRAY_ELEMS(ff_id3v2_picture_types); i++) { - if (strstr(ff_id3v2_picture_types[i], e->value) == ff_id3v2_picture_types[i]) { + if (!av_strcasecmp(e->value, ff_id3v2_picture_types[i])) { type = i; break; } diff --git a/libavformat/iff.c b/libavformat/iff.c index 3838db116..62f0b8387 100644 --- a/libavformat/iff.c +++ b/libavformat/iff.c @@ -28,12 +28,15 @@ * http://wiki.multimedia.cx/index.php?title=IFF */ +#include + #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "libavcodec/bytestream.h" #include "avformat.h" +#include "id3v2.h" #include "internal.h" #define ID_8SVX MKTAG('8','S','V','X') @@ -55,8 +58,10 @@ #define ID_DEEP MKTAG('D','E','E','P') #define ID_RGB8 MKTAG('R','G','B','8') #define ID_RGBN MKTAG('R','G','B','N') +#define ID_DSD MKTAG('D','S','D',' ') #define ID_FORM MKTAG('F','O','R','M') +#define ID_FRM8 MKTAG('F','R','M','8') #define ID_ANNO MKTAG('A','N','N','O') #define ID_AUTH MKTAG('A','U','T','H') #define ID_CHRS MKTAG('C','H','R','S') @@ -93,6 +98,7 @@ typedef enum { } svx8_compression_type; typedef struct { + int is_64bit; ///< chunk size is 64-bit int64_t body_pos; int64_t body_end; uint32_t body_size; @@ -131,7 +137,7 @@ static int iff_probe(AVProbeData *p) { const uint8_t *d = p->buf; - if ( AV_RL32(d) == ID_FORM && + if ( (AV_RL32(d) == ID_FORM && (AV_RL32(d+8) == ID_8SVX || AV_RL32(d+8) == ID_16SV || AV_RL32(d+8) == ID_MAUD || @@ -140,11 +146,188 @@ static int iff_probe(AVProbeData *p) AV_RL32(d+8) == ID_DEEP || AV_RL32(d+8) == ID_ILBM || AV_RL32(d+8) == ID_RGB8 || - AV_RL32(d+8) == ID_RGBN) ) + AV_RL32(d+8) == ID_RGB8 || + AV_RL32(d+8) == ID_RGBN)) || + (AV_RL32(d) == ID_FRM8 && AV_RL32(d+12) == ID_DSD)) return AVPROBE_SCORE_MAX; return 0; } +static const AVCodecTag dsd_codec_tags[] = { + { AV_CODEC_ID_DSD_MSBF, ID_DSD }, + { AV_CODEC_ID_NONE, 0 }, +}; + + +#define DSD_SLFT MKTAG('S','L','F','T') +#define DSD_SRGT MKTAG('S','R','G','T') +#define DSD_MLFT MKTAG('M','L','F','T') +#define DSD_MRGT MKTAG('M','R','G','T') +#define DSD_C MKTAG('C',' ',' ',' ') +#define DSD_LS MKTAG('L','S',' ',' ') +#define DSD_RS MKTAG('R','S',' ',' ') +#define DSD_LFE MKTAG('L','F','E',' ') + +static const uint32_t dsd_stereo[] = { DSD_SLFT, DSD_SRGT }; +static const uint32_t dsd_5point0[] = { DSD_MLFT, DSD_MRGT, DSD_C, DSD_LS, DSD_RS }; +static const uint32_t dsd_5point1[] = { DSD_MLFT, DSD_MRGT, DSD_C, DSD_LFE, DSD_LS, DSD_RS }; + +typedef struct { + uint64_t layout; + const uint32_t * dsd_layout; +} DSDLayoutDesc; + +static const DSDLayoutDesc dsd_channel_layout[] = { + { AV_CH_LAYOUT_STEREO, dsd_stereo }, + { AV_CH_LAYOUT_5POINT0, dsd_5point0 }, + { AV_CH_LAYOUT_5POINT1, dsd_5point1 }, +}; + +static const uint64_t dsd_loudspeaker_config[] = { + AV_CH_LAYOUT_STEREO, + 0, 0, + AV_CH_LAYOUT_5POINT0, AV_CH_LAYOUT_5POINT1, +}; + +static const char * dsd_source_comment[] = { + "dsd_source_comment", + "analogue_source_comment", + "pcm_source_comment", +}; + +static const char * dsd_history_comment[] = { + "general_remark", + "operator_name", + "creating_machine", + "timezone", + "file_revision" +}; + +static int parse_dsd_diin(AVFormatContext *s, AVStream *st, uint64_t eof) +{ + AVIOContext *pb = s->pb; + + while (avio_tell(pb) + 12 <= eof) { + uint32_t tag = avio_rl32(pb); + uint64_t size = avio_rb64(pb); + uint64_t orig_pos = avio_tell(pb); + const char * metadata_tag = NULL; + + switch(tag) { + case MKTAG('D','I','A','R'): metadata_tag = "artist"; break; + case MKTAG('D','I','T','I'): metadata_tag = "title"; break; + } + + if (metadata_tag && size > 4) { + unsigned int tag_size = avio_rb32(pb); + int ret = get_metadata(s, metadata_tag, FFMIN(tag_size, size - 4)); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", metadata_tag); + return ret; + } + } + + avio_skip(pb, size - (avio_tell(pb) - orig_pos) + (size & 1)); + } + + return 0; +} + +static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof) +{ + AVIOContext *pb = s->pb; + char abss[24]; + int hour, min, sec, i, ret, config; + int dsd_layout[6]; + ID3v2ExtraMeta *id3v2_extra_meta; + + while (avio_tell(pb) + 12 <= eof) { + uint32_t tag = avio_rl32(pb); + uint64_t size = avio_rb64(pb); + uint64_t orig_pos = avio_tell(pb); + + switch(tag) { + case MKTAG('A','B','S','S'): + if (size < 8) + return AVERROR_INVALIDDATA; + hour = avio_rb16(pb); + min = avio_r8(pb); + sec = avio_r8(pb); + snprintf(abss, sizeof(abss), "%02dh:%02dm:%02ds:%d", hour, min, sec, avio_rb32(pb)); + av_dict_set(&st->metadata, "absolute_start_time", abss, 0); + break; + + case MKTAG('C','H','N','L'): + if (size < 2) + return AVERROR_INVALIDDATA; + st->codec->channels = avio_rb16(pb); + if (size < 2 + st->codec->channels * 4) + return AVERROR_INVALIDDATA; + st->codec->channel_layout = 0; + if (st->codec->channels > FF_ARRAY_ELEMS(dsd_layout)) { + avpriv_request_sample(s, "channel layout"); + break; + } + for (i = 0; i < st->codec->channels; i++) + dsd_layout[i] = avio_rl32(pb); + for (i = 0; i < FF_ARRAY_ELEMS(dsd_channel_layout); i++) { + const DSDLayoutDesc * d = &dsd_channel_layout[i]; + if (av_get_channel_layout_nb_channels(d->layout) == st->codec->channels && + !memcmp(d->dsd_layout, dsd_layout, st->codec->channels * sizeof(uint32_t))) { + st->codec->channel_layout = d->layout; + break; + } + } + break; + + case MKTAG('C','M','P','R'): + if (size < 4) + return AVERROR_INVALIDDATA; + st->codec->codec_id = ff_codec_get_id(dsd_codec_tags, avio_rl32(pb)); + break; + + case MKTAG('F','S',' ',' '): + if (size < 4) + return AVERROR_INVALIDDATA; + st->codec->sample_rate = avio_rb32(pb) / 8; + break; + + case MKTAG('I','D','3',' '): + id3v2_extra_meta = NULL; + ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size); + if (id3v2_extra_meta) { + if ((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0) { + ff_id3v2_free_extra_meta(&id3v2_extra_meta); + return ret; + } + ff_id3v2_free_extra_meta(&id3v2_extra_meta); + } + + if (size < avio_tell(pb) - orig_pos) { + av_log(s, AV_LOG_ERROR, "id3 exceeds chunk size\n"); + return AVERROR_INVALIDDATA; + } + break; + + case MKTAG('L','S','C','O'): + if (size < 2) + return AVERROR_INVALIDDATA; + config = avio_rb16(pb); + if (config != 0xFFFF) { + if (config < FF_ARRAY_ELEMS(dsd_loudspeaker_config)) + st->codec->channel_layout = dsd_loudspeaker_config[config]; + if (!st->codec->channel_layout) + avpriv_request_sample(s, "loudspeaker configuration %d", config); + } + break; + } + + avio_skip(pb, size - (avio_tell(pb) - orig_pos) + (size & 1)); + } + + return 0; +} + static const uint8_t deep_rgb24[] = {0, 0, 0, 3, 0, 1, 0, 8, 0, 2, 0, 8, 0, 3, 0, 8}; static const uint8_t deep_rgba[] = {0, 0, 0, 4, 0, 1, 0, 8, 0, 2, 0, 8, 0, 3, 0, 8}; static const uint8_t deep_bgra[] = {0, 0, 0, 4, 0, 3, 0, 8, 0, 2, 0, 8, 0, 1, 0, 8}; @@ -157,7 +340,8 @@ static int iff_read_header(AVFormatContext *s) AVIOContext *pb = s->pb; AVStream *st; uint8_t *buf; - uint32_t chunk_id, data_size; + uint32_t chunk_id; + uint64_t data_size; uint32_t screenmode = 0, num, den; unsigned transparency = 0; unsigned masking = 0; // no mask @@ -170,7 +354,8 @@ static int iff_read_header(AVFormatContext *s) st->codec->channels = 1; st->codec->channel_layout = AV_CH_LAYOUT_MONO; - avio_skip(pb, 8); + iff->is_64bit = avio_rl32(pb) == ID_FRM8; + avio_skip(pb, iff->is_64bit ? 8 : 4); // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content st->codec->codec_tag = avio_rl32(pb); iff->bitmap_compression = -1; @@ -182,8 +367,9 @@ static int iff_read_header(AVFormatContext *s) uint64_t orig_pos; int res; const char *metadata_tag = NULL; + int version, nb_comments, i; chunk_id = avio_rl32(pb); - data_size = avio_rb32(pb); + data_size = iff->is_64bit ? avio_rb64(pb) : avio_rb32(pb); orig_pos = avio_tell(pb); switch(chunk_id) { @@ -225,6 +411,7 @@ static int iff_read_header(AVFormatContext *s) case ID_ABIT: case ID_BODY: case ID_DBOD: + case ID_DSD: case ID_MDAT: iff->body_pos = avio_tell(pb); iff->body_end = iff->body_pos + data_size; @@ -251,7 +438,7 @@ static int iff_read_header(AVFormatContext *s) case ID_CMAP: if (data_size < 3 || data_size > 768 || data_size % 3) { - av_log(s, AV_LOG_ERROR, "Invalid CMAP chunk size %d\n", + av_log(s, AV_LOG_ERROR, "Invalid CMAP chunk size %"PRIu64"\n", data_size); return AVERROR_INVALIDDATA; } @@ -338,6 +525,84 @@ static int iff_read_header(AVFormatContext *s) case ID_AUTH: metadata_tag = "artist"; break; case ID_COPYRIGHT: metadata_tag = "copyright"; break; case ID_NAME: metadata_tag = "title"; break; + + /* DSD tags */ + + case MKTAG('F','V','E','R'): + if (data_size < 4) + return AVERROR_INVALIDDATA; + version = avio_rb32(pb); + av_log(s, AV_LOG_DEBUG, "DSIFF v%d.%d.%d.%d\n",version >> 24, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF); + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + break; + + case MKTAG('D','I','I','N'): + res = parse_dsd_diin(s, st, orig_pos + data_size); + if (res < 0) + return res; + break; + + case MKTAG('P','R','O','P'): + if (data_size < 4) + return AVERROR_INVALIDDATA; + if (avio_rl32(pb) != MKTAG('S','N','D',' ')) { + avpriv_request_sample(s, "unknown property type"); + break; + } + res = parse_dsd_prop(s, st, orig_pos + data_size); + if (res < 0) + return res; + break; + + case MKTAG('C','O','M','T'): + if (data_size < 2) + return AVERROR_INVALIDDATA; + nb_comments = avio_rb16(pb); + for (i = 0; i < nb_comments; i++) { + int year, mon, day, hour, min, type, ref; + char tmp[24]; + const char *tag; + int metadata_size; + + year = avio_rb16(pb); + mon = avio_r8(pb); + day = avio_r8(pb); + hour = avio_r8(pb); + min = avio_r8(pb); + snprintf(tmp, sizeof(tmp), "%04d-%02d-%02d %02d:%02d", year, mon, day, hour, min); + av_dict_set(&st->metadata, "comment_time", tmp, 0); + + type = avio_rb16(pb); + ref = avio_rb16(pb); + switch (type) { + case 1: + if (!i) + tag = "channel_comment"; + else { + snprintf(tmp, sizeof(tmp), "channel%d_comment", ref); + tag = tmp; + } + break; + case 2: + tag = ref < FF_ARRAY_ELEMS(dsd_source_comment) ? dsd_history_comment[ref] : "source_comment"; + break; + case 3: + tag = ref < FF_ARRAY_ELEMS(dsd_history_comment) ? dsd_history_comment[ref] : "file_history"; + break; + default: + tag = "comment"; + } + + metadata_size = avio_rb32(pb); + if ((res = get_metadata(s, tag, metadata_size)) < 0) { + av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", tag); + return res; + } + + if (metadata_size & 1) + avio_skip(pb, 1); + } + break; } if (metadata_tag) { @@ -370,28 +635,22 @@ static int iff_read_header(AVFormatContext *s) avpriv_request_sample(s, "compression %d and bit depth %d", iff->maud_compression, iff->maud_bits); return AVERROR_PATCHWELCOME; } - - st->codec->bits_per_coded_sample = - av_get_bits_per_sample(st->codec->codec_id); - - st->codec->block_align = - st->codec->bits_per_coded_sample * st->codec->channels / 8; - } else { - switch (iff->svx8_compression) { - case COMP_NONE: - st->codec->codec_id = AV_CODEC_ID_PCM_S8_PLANAR; - break; - case COMP_FIB: - st->codec->codec_id = AV_CODEC_ID_8SVX_FIB; - break; - case COMP_EXP: - st->codec->codec_id = AV_CODEC_ID_8SVX_EXP; - break; - default: - av_log(s, AV_LOG_ERROR, - "Unknown SVX8 compression method '%d'\n", iff->svx8_compression); - return -1; - } + } else if (st->codec->codec_tag != ID_DSD) { + switch (iff->svx8_compression) { + case COMP_NONE: + st->codec->codec_id = AV_CODEC_ID_PCM_S8_PLANAR; + break; + case COMP_FIB: + st->codec->codec_id = AV_CODEC_ID_8SVX_FIB; + break; + case COMP_EXP: + st->codec->codec_id = AV_CODEC_ID_8SVX_EXP; + break; + default: + av_log(s, AV_LOG_ERROR, + "Unknown SVX8 compression method '%d'\n", iff->svx8_compression); + return -1; + } } st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id); @@ -447,7 +706,7 @@ static int iff_read_packet(AVFormatContext *s, return AVERROR_EOF; if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - if (st->codec->codec_tag == ID_MAUD) { + if (st->codec->codec_tag == ID_DSD || st->codec->codec_tag == ID_MAUD) { ret = av_get_packet(pb, pkt, FFMIN(iff->body_end - pos, 1024 * st->codec->block_align)); } else { ret = av_get_packet(pb, pkt, iff->body_size); diff --git a/libavformat/img2.c b/libavformat/img2.c index 4fd4fd228..80020549f 100644 --- a/libavformat/img2.c +++ b/libavformat/img2.c @@ -44,6 +44,7 @@ static const IdStrMap img_tags[] = { { AV_CODEC_ID_PGMYUV, "pgmyuv" }, { AV_CODEC_ID_PBM, "pbm" }, { AV_CODEC_ID_PAM, "pam" }, + { AV_CODEC_ID_ALIAS_PIX, "pix" }, { AV_CODEC_ID_MPEG1VIDEO, "mpg1-img" }, { AV_CODEC_ID_MPEG2VIDEO, "mpg2-img" }, { AV_CODEC_ID_MPEG4, "mpg4-img" }, @@ -56,8 +57,8 @@ static const IdStrMap img_tags[] = { { AV_CODEC_ID_TIFF, "tif" }, { AV_CODEC_ID_SGI, "sgi" }, { AV_CODEC_ID_PTX, "ptx" }, + { AV_CODEC_ID_BRENDER_PIX,"pix" }, { AV_CODEC_ID_PCX, "pcx" }, - { AV_CODEC_ID_BRENDER_PIX, "pix" }, { AV_CODEC_ID_SUNRAST, "sun" }, { AV_CODEC_ID_SUNRAST, "ras" }, { AV_CODEC_ID_SUNRAST, "rs" }, diff --git a/libavformat/img2.h b/libavformat/img2.h new file mode 100644 index 000000000..dc53c5cc5 --- /dev/null +++ b/libavformat/img2.h @@ -0,0 +1,61 @@ +/* + * Image format + * Copyright (c) 2014 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_IMG2_H +#define AVFORMAT_IMG2_H + +#include +#include "avformat.h" + +#if HAVE_GLOB +#include +#endif + +typedef struct { + const AVClass *class; /**< Class for private options. */ + int img_first; + int img_last; + int img_number; + int64_t pts; + int img_count; + int is_pipe; + int split_planes; /**< use independent file for each Y, U, V plane */ + char path[1024]; + char *pixel_format; /**< Set by a private option. */ + int width, height; /**< Set by a private option. */ + AVRational framerate; /**< Set by a private option. */ + int loop; + enum { PT_GLOB_SEQUENCE, PT_GLOB, PT_SEQUENCE } pattern_type; + int use_glob; +#if HAVE_GLOB + glob_t globstate; +#endif + int start_number; + int start_number_range; + int frame_size; + int ts_from_file; +} VideoDemuxData; + +int ff_img_read_header(AVFormatContext *s1); + +int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt); + +#endif diff --git a/libavformat/img2_alias_pix.c b/libavformat/img2_alias_pix.c new file mode 100644 index 000000000..a3d5cfa0c --- /dev/null +++ b/libavformat/img2_alias_pix.c @@ -0,0 +1,65 @@ +/* + * Alias PIX image demuxer + * Copyright (c) 2014 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "img2.h" +#include "libavcodec/bytestream.h" + +static int brender_read_probe(AVProbeData *p) +{ + const uint8_t *b = p->buf; + const uint8_t *end = b + p->buf_size; + int width = bytestream_get_be16(&b); + int height = bytestream_get_be16(&b); + av_unused int ox = bytestream_get_be16(&b); + av_unused int oy = bytestream_get_be16(&b); + int bpp = bytestream_get_be16(&b); + int x, y; + + if (!width || !height) + return 0; + + if (bpp != 24 && bpp != 8) + return 0; + + for (y=0; y<2 && y width) + return 0; + if (b > end) + return AVPROBE_SCORE_MAX / 8; + b += bpp / 8; + x += count; + } + } + + return AVPROBE_SCORE_EXTENSION + 1; +} + +AVInputFormat ff_image2_alias_pix_demuxer = { + .name = "alias_pix", + .long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"), + .priv_data_size = sizeof(VideoDemuxData), + .read_probe = brender_read_probe, + .read_header = ff_img_read_header, + .read_packet = ff_img_read_packet, + .raw_codec_id = AV_CODEC_ID_ALIAS_PIX, +}; diff --git a/libavformat/img2_brender_pix.c b/libavformat/img2_brender_pix.c new file mode 100644 index 000000000..f7306267c --- /dev/null +++ b/libavformat/img2_brender_pix.c @@ -0,0 +1,49 @@ +/* + * BRender PIX image demuxer + * Copyright (c) 2014 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "img2.h" +#include "libavutil/intreadwrite.h" + +static int aliaspix_read_probe(AVProbeData *p) +{ + static const uint8_t brender_magic[16] = { + 0,0,0,0x12,0,0,0,8,0,0,0,2,0,0,0,2 + }; + + if (memcmp(p->buf, brender_magic, sizeof(brender_magic))) + return 0; + + if (AV_RB32(p->buf+16) != 0x03 && + AV_RB32(p->buf+16) != 0x3D) + return 0; + + return AVPROBE_SCORE_MAX-10; +} + +AVInputFormat ff_image2_brender_pix_demuxer = { + .name = "brender_pix", + .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"), + .priv_data_size = sizeof(VideoDemuxData), + .read_probe = aliaspix_read_probe, + .read_header = ff_img_read_header, + .read_packet = ff_img_read_packet, + .raw_codec_id = AV_CODEC_ID_BRENDER_PIX, +}; diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c index 5163e69f6..cda499656 100644 --- a/libavformat/img2dec.c +++ b/libavformat/img2dec.c @@ -20,17 +20,20 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define _BSD_SOURCE #include #include "libavutil/avstring.h" #include "libavutil/log.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/parseutils.h" +#include "libavutil/intreadwrite.h" #include "avformat.h" +#include "avio_internal.h" #include "internal.h" -#if HAVE_GLOB -#include +#include "img2.h" +#if HAVE_GLOB /* Locally define as 0 (bitwise-OR no-op) any missing glob options that are non-posix glibc/bsd extensions. */ #ifndef GLOB_NOMAGIC @@ -42,31 +45,6 @@ #endif /* HAVE_GLOB */ -typedef struct { - const AVClass *class; /**< Class for private options. */ - int img_first; - int img_last; - int img_number; - int64_t pts; - int img_count; - int is_pipe; - int split_planes; /**< use independent file for each Y, U, V plane */ - char path[1024]; - char *pixel_format; /**< Set by a private option. */ - int width, height; /**< Set by a private option. */ - AVRational framerate; /**< Set by a private option. */ - int loop; - enum { PT_GLOB_SEQUENCE, PT_GLOB, PT_SEQUENCE } pattern_type; - int use_glob; -#if HAVE_GLOB - glob_t globstate; -#endif - int start_number; - int start_number_range; - int frame_size; - int ts_from_file; -} VideoDemuxData; - static const int sizes[][2] = { { 640, 480 }, { 720, 480 }, @@ -192,7 +170,7 @@ static int img_read_probe(AVProbeData *p) return 0; } -static int img_read_header(AVFormatContext *s1) +int ff_img_read_header(AVFormatContext *s1) { VideoDemuxData *s = s1->priv_data; int first_index, last_index; @@ -225,7 +203,13 @@ static int img_read_header(AVFormatContext *s1) st->need_parsing = AVSTREAM_PARSE_FULL; } - if (s->ts_from_file) + if (s->ts_from_file == 2) { +#if !HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + av_log(s1, AV_LOG_ERROR, "POSIX.1-2008 not supported, nanosecond file timestamps unavailable\n"); + return AVERROR(ENOSYS); +#endif + avpriv_set_pts_info(st, 64, 1, 1000000000); + } else if (s->ts_from_file) avpriv_set_pts_info(st, 64, 1, 1); else avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num); @@ -313,13 +297,52 @@ static int img_read_header(AVFormatContext *s1) } else if (s1->audio_codec_id) { st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = s1->audio_codec_id; + } else if (s1->iformat->raw_codec_id) { + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = s1->iformat->raw_codec_id; } else { const char *str = strrchr(s->path, '.'); s->split_planes = str && !av_strcasecmp(str + 1, "y"); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = ff_guess_image2_codec(s->path); + if (s1->pb) { + int probe_buffer_size = 2048; + uint8_t *probe_buffer = av_realloc(NULL, probe_buffer_size + AVPROBE_PADDING_SIZE); + AVInputFormat *fmt = NULL; + AVProbeData pd; + + if (!probe_buffer) + return AVERROR(ENOMEM); + + probe_buffer_size = avio_read(s1->pb, probe_buffer, probe_buffer_size); + if (probe_buffer_size < 0) { + av_free(probe_buffer); + return probe_buffer_size; + } + memset(probe_buffer + probe_buffer_size, 0, AVPROBE_PADDING_SIZE); + + pd.buf = probe_buffer; + pd.buf_size = probe_buffer_size; + pd.filename = s1->filename; + + while ((fmt = av_iformat_next(fmt))) { + if (fmt->read_header != ff_img_read_header || + !fmt->read_probe || + (fmt->flags & AVFMT_NOFILE) || + !fmt->raw_codec_id) + continue; + if (fmt->read_probe(&pd) > 0) { + st->codec->codec_id = fmt->raw_codec_id; + break; + } + } + ffio_rewind_with_probe_data(s1->pb, &probe_buffer, probe_buffer_size); + } + if (st->codec->codec_id == AV_CODEC_ID_NONE) + st->codec->codec_id = ff_guess_image2_codec(s->path); if (st->codec->codec_id == AV_CODEC_ID_LJPEG) st->codec->codec_id = AV_CODEC_ID_MJPEG; + if (st->codec->codec_id == AV_CODEC_ID_ALIAS_PIX) // we cannot distingiush this from BRENDER_PIX + st->codec->codec_id = AV_CODEC_ID_NONE; } if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pix_fmt != AV_PIX_FMT_NONE) @@ -328,7 +351,7 @@ static int img_read_header(AVFormatContext *s1) return 0; } -static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) +int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt) { VideoDemuxData *s = s1->priv_data; char filename_bytes[1024]; @@ -371,6 +394,27 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) filename[strlen(filename) - 1] = 'U' + i; } + if (codec->codec_id == AV_CODEC_ID_NONE) { + AVProbeData pd; + AVInputFormat *ifmt; + uint8_t header[PROBE_BUF_MIN + AVPROBE_PADDING_SIZE]; + int ret; + int score = 0; + + ret = avio_read(f[0], header, PROBE_BUF_MIN); + if (ret < 0) + return ret; + memset(header + ret, 0, sizeof(header) - ret); + avio_skip(f[0], -ret); + pd.buf = header; + pd.buf_size = ret; + pd.filename = filename; + + ifmt = av_probe_input_format3(&pd, 1, &score); + if (ifmt && ifmt->read_packet == ff_img_read_packet && ifmt->raw_codec_id) + codec->codec_id = ifmt->raw_codec_id; + } + if (codec->codec_id == AV_CODEC_ID_RAWVIDEO && !codec->width) infer_size(&codec->width, &codec->height, size[0]); } else { @@ -379,6 +423,8 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) return AVERROR(EIO); if (s->frame_size > 0) { size[0] = s->frame_size; + } else if (!s1->streams[0]->parser) { + size[0] = avio_size(s1->pb); } else { size[0] = 4096; } @@ -393,6 +439,10 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) if (stat(filename, &img_stat)) return AVERROR(EIO); pkt->pts = (int64_t)img_stat.st_mtime; +#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + if (s->ts_from_file == 2) + pkt->pts = 1000000000*pkt->pts + img_stat.st_mtim.tv_nsec; +#endif av_add_index_entry(s1->streams[0], s->img_number, pkt->pts, 0, 0, AVINDEX_KEYFRAME); } else if (!s->is_pipe) { pkt->pts = s->pts; @@ -467,7 +517,10 @@ static const AVOption options[] = { { "start_number_range", "set range for looking at the first sequence number", OFFSET(start_number_range), AV_OPT_TYPE_INT, {.i64 = 5}, 1, INT_MAX, DEC }, { "video_size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, { "frame_size", "force frame size in bytes", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, DEC }, - { "ts_from_file", "set frame timestamp from file's one", OFFSET(ts_from_file), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, DEC }, + { "ts_from_file", "set frame timestamp from file's one", OFFSET(ts_from_file), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, DEC, "ts_type" }, + { "none", "none", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 2, DEC, "ts_type" }, + { "sec", "second precision", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 2, DEC, "ts_type" }, + { "ns", "nano second precision", 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 2, DEC, "ts_type" }, { NULL }, }; @@ -483,8 +536,8 @@ AVInputFormat ff_image2_demuxer = { .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"), .priv_data_size = sizeof(VideoDemuxData), .read_probe = img_read_probe, - .read_header = img_read_header, - .read_packet = img_read_packet, + .read_header = ff_img_read_header, + .read_packet = ff_img_read_packet, .read_close = img_read_close, .read_seek = img_read_seek, .flags = AVFMT_NOFILE, @@ -502,8 +555,131 @@ AVInputFormat ff_image2pipe_demuxer = { .name = "image2pipe", .long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"), .priv_data_size = sizeof(VideoDemuxData), - .read_header = img_read_header, - .read_packet = img_read_packet, + .read_header = ff_img_read_header, + .read_packet = ff_img_read_packet, .priv_class = &img2pipe_class, }; #endif + +static int bmp_probe(AVProbeData *p) +{ + const uint8_t *b = p->buf; + int ihsize; + + if (AV_RB16(b) != 0x424d) + return 0; + + ihsize = AV_RL32(b+14); + if (ihsize < 12 || ihsize > 255) + return 0; + + if (!AV_RN32(b + 6)) { + return AVPROBE_SCORE_EXTENSION + 1; + } else { + return AVPROBE_SCORE_EXTENSION / 4; + } + return 0; +} + +static int dpx_probe(AVProbeData *p) +{ + const uint8_t *b = p->buf; + + if (AV_RN32(b) == AV_RN32("SDPX") || AV_RN32(b) == AV_RN32("XPDS")) + return AVPROBE_SCORE_EXTENSION + 1; + return 0; +} + +static int exr_probe(AVProbeData *p) +{ + const uint8_t *b = p->buf; + + if (AV_RL32(b) == 20000630) + return AVPROBE_SCORE_EXTENSION + 1; + return 0; +} + +static int j2k_probe(AVProbeData *p) +{ + const uint8_t *b = p->buf; + + if (AV_RB64(b) == 0x0000000c6a502020 || + AV_RB32(b) == 0xff4fff51) + return AVPROBE_SCORE_EXTENSION + 1; + return 0; +} + +static int pictor_probe(AVProbeData *p) +{ + const uint8_t *b = p->buf; + + if (AV_RL16(b) == 0x1234) + return AVPROBE_SCORE_EXTENSION / 4; + return 0; +} + +static int png_probe(AVProbeData *p) +{ + const uint8_t *b = p->buf; + + if (AV_RB64(b) == 0x89504e470d0a1a0a) + return AVPROBE_SCORE_MAX - 1; + return 0; +} + +static int sgi_probe(AVProbeData *p) +{ + const uint8_t *b = p->buf; + + if (AV_RB16(b) == 474 && + (b[2] & ~1) == 0 && + (b[3] & ~3) == 0 && b[3] && + (AV_RB16(b + 4) & ~7) == 0 && AV_RB16(b + 4)) + return AVPROBE_SCORE_EXTENSION + 1; + return 0; +} + +static int sunrast_probe(AVProbeData *p) +{ + const uint8_t *b = p->buf; + + if (AV_RB32(b) == 0x59a66a95) + return AVPROBE_SCORE_EXTENSION + 1; + return 0; +} + +static int tiff_probe(AVProbeData *p) +{ + const uint8_t *b = p->buf; + + if (AV_RB32(b) == 0x49492a00) + return AVPROBE_SCORE_EXTENSION + 1; + return 0; +} + +#define IMAGEAUTO_DEMUXER(imgname, codecid)\ +static const AVClass imgname ## _class = {\ + .class_name = AV_STRINGIFY(imgname) " demuxer",\ + .item_name = av_default_item_name,\ + .option = options,\ + .version = LIBAVUTIL_VERSION_INT,\ +};\ +AVInputFormat ff_image_ ## imgname ## _pipe_demuxer = {\ + .name = AV_STRINGIFY(imgname) "_pipe",\ + .priv_data_size = sizeof(VideoDemuxData),\ + .read_probe = imgname ## _probe,\ + .read_header = ff_img_read_header,\ + .read_packet = ff_img_read_packet,\ + .priv_class = & imgname ## _class,\ + .raw_codec_id = codecid,\ +}; + +IMAGEAUTO_DEMUXER(bmp, AV_CODEC_ID_BMP) +IMAGEAUTO_DEMUXER(dpx, AV_CODEC_ID_DPX) +IMAGEAUTO_DEMUXER(exr, AV_CODEC_ID_EXR) +IMAGEAUTO_DEMUXER(j2k, AV_CODEC_ID_JPEG2000) +IMAGEAUTO_DEMUXER(pictor, AV_CODEC_ID_PICTOR) +IMAGEAUTO_DEMUXER(png, AV_CODEC_ID_PNG) +IMAGEAUTO_DEMUXER(sgi, AV_CODEC_ID_SGI) +IMAGEAUTO_DEMUXER(sunrast, AV_CODEC_ID_SUNRAST) +IMAGEAUTO_DEMUXER(tiff, AV_CODEC_ID_TIFF) diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index f61b0ca30..37dfbecce 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -194,7 +194,7 @@ AVOutputFormat ff_image2_muxer = { .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"), .extensions = "bmp,dpx,jls,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png," "ppm,sgi,tga,tif,tiff,jp2,j2c,j2k,xwd,sun,ras,rs,im1,im8,im24," - "sunras,webp,xbm,xface", + "sunras,webp,xbm,xface,pix,y", .priv_data_size = sizeof(VideoMuxData), .video_codec = AV_CODEC_ID_MJPEG, .write_header = write_header, diff --git a/libavformat/internal.h b/libavformat/internal.h index f19cebf22..66fb5d64a 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -52,6 +52,8 @@ struct AVFormatInternal { * Muxing only. */ int nb_interleaved_streams; + + int inject_global_side_data; }; #ifdef __GNUC__ @@ -358,11 +360,11 @@ enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags); /** * Chooses a timebase for muxing the specified stream. * - * The choosen timebase allows sample accurate timestamps based + * The chosen timebase allows sample accurate timestamps based * on the framerate or sample rate for audio streams. It also is - * at least as precisse as 1/min_precission would be. + * at least as precise as 1/min_precision would be. */ -AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precission); +AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precision); /** * Generate standard extradata for AVC-Intra based on width/height and field diff --git a/libavformat/isom.c b/libavformat/isom.c index 957ee5b27..d768c32b6 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -26,6 +26,8 @@ #include "isom.h" #include "libavcodec/mpeg4audio.h" #include "libavcodec/mpegaudiodata.h" +#include "libavutil/avstring.h" +#include "libavutil/intreadwrite.h" /* http://www.mp4ra.org */ /* ordered by muxing preference */ @@ -81,7 +83,7 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'B', 'G', 'R') }, { AV_CODEC_ID_RAWVIDEO, MKTAG('b', '1', '6', 'g') }, { AV_CODEC_ID_RAWVIDEO, MKTAG('b', '4', '8', 'r') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'b', 'g') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'b', 'g') }, /* BOXX */ { AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'r', 'g') }, { AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'y', 'v') }, { AV_CODEC_ID_RAWVIDEO, MKTAG('N', 'O', '1', '6') }, @@ -168,12 +170,12 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '3') }, /* AVC-Intra 100M 1080p24/30/60 */ { 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', 'i', 'v', 'x') }, /* XAVC 4:2:2 10bit */ { 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_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', '1', 'v', ' ') }, { 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 */ @@ -301,7 +303,7 @@ const AVCodecTag ff_codec_movaudio_tags[] = { { AV_CODEC_ID_QDM2, MKTAG('Q', 'D', 'M', '2') }, { AV_CODEC_ID_QDMC, MKTAG('Q', 'D', 'M', 'C') }, { AV_CODEC_ID_SPEEX, MKTAG('s', 'p', 'e', 'x') }, /* Flash Media Server */ - { AV_CODEC_ID_SPEEX, MKTAG('S', 'P', 'X', 'N') }, + { AV_CODEC_ID_SPEEX, MKTAG('S', 'P', 'X', 'N') }, /* ZygoAudio (quality 10 mode) */ { AV_CODEC_ID_WMAV2, MKTAG('W', 'M', 'A', '2') }, { AV_CODEC_ID_EVRC, MKTAG('s', 'e', 'v', 'c') }, /* 3GPP2 */ { AV_CODEC_ID_SMV, MKTAG('s', 's', 'm', 'v') }, /* 3GPP2 */ @@ -439,6 +441,7 @@ static const AVCodecTag mp4_audio_types[] = { int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext *pb) { + enum AVCodecID codec_id; int len, tag; int ret; int object_type_id = avio_r8(pb); @@ -452,7 +455,9 @@ int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext return -1; } - st->codec->codec_id= ff_codec_get_id(ff_mp4_obj_type, object_type_id); + codec_id= ff_codec_get_id(ff_mp4_obj_type, object_type_id); + if (codec_id) + st->codec->codec_id= codec_id; av_dlog(fc, "esds object type id 0x%02x\n", object_type_id); len = ff_mp4_read_descr(fc, pb, &tag); if (tag == MP4DecSpecificDescrTag) { diff --git a/libavformat/isom.h b/libavformat/isom.h index a929ebf05..414b87cc9 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -73,6 +73,7 @@ typedef struct MOVFragment { unsigned track_id; uint64_t base_data_offset; uint64_t moof_offset; + uint64_t implicit_offset; unsigned stsd_id; unsigned duration; unsigned size; @@ -145,6 +146,8 @@ typedef struct MOVStreamContext { int nb_frames_for_fps; int64_t duration_for_fps; + + int32_t *display_matrix; } MOVStreamContext; typedef struct MOVContext { @@ -167,6 +170,7 @@ typedef struct MOVContext { int64_t next_root_atom; ///< offset of the next root atom int *bitrates; ///< bitrates read before streams creation int bitrates_count; + int moov_retry; } MOVContext; int ff_mp4_read_descr_len(AVIOContext *pb); @@ -187,6 +191,7 @@ void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id); #define MOV_TFHD_DEFAULT_SIZE 0x10 #define MOV_TFHD_DEFAULT_FLAGS 0x20 #define MOV_TFHD_DURATION_IS_EMPTY 0x010000 +#define MOV_TFHD_DEFAULT_BASE_IS_MOOF 0x020000 #define MOV_TRUN_DATA_OFFSET 0x01 #define MOV_TRUN_FIRST_SAMPLE_FLAGS 0x04 diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c index 45bae2209..5700f01d3 100644 --- a/libavformat/ivfenc.c +++ b/libavformat/ivfenc.c @@ -30,8 +30,9 @@ static int ivf_write_header(AVFormatContext *s) return AVERROR(EINVAL); } ctx = s->streams[0]->codec; - if (ctx->codec_type != AVMEDIA_TYPE_VIDEO || ctx->codec_id != AV_CODEC_ID_VP8) { - av_log(s, AV_LOG_ERROR, "Currently only VP8 is supported!\n"); + if (ctx->codec_type != AVMEDIA_TYPE_VIDEO || + !(ctx->codec_id == AV_CODEC_ID_VP8 || ctx->codec_id == AV_CODEC_ID_VP9)) { + av_log(s, AV_LOG_ERROR, "Currently only VP8 and VP9 are supported!\n"); return AVERROR(EINVAL); } avio_write(pb, "DKIF", 4); diff --git a/libavformat/latmenc.c b/libavformat/latmenc.c index e69de2b12..cb79e84a9 100644 --- a/libavformat/latmenc.c +++ b/libavformat/latmenc.c @@ -227,4 +227,5 @@ AVOutputFormat ff_latm_muxer = { .write_header = latm_write_header, .write_packet = latm_write_packet, .priv_class = &latm_muxer_class, + .flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/libnut.c b/libavformat/libnut.c index be8f3cb28..4a9a21a76 100644 --- a/libavformat/libnut.c +++ b/libavformat/libnut.c @@ -70,7 +70,7 @@ static int nut_write_header(AVFormatContext * avf) { nut_stream_header_tt * s; int i; - priv->s = s = av_mallocz((avf->nb_streams + 1) * sizeof*s); + priv->s = s = av_mallocz_array(avf->nb_streams + 1, sizeof*s); if(!s) return AVERROR(ENOMEM); diff --git a/libavformat/librtmp.c b/libavformat/librtmp.c index f0b5929e6..c57699cc9 100644 --- a/libavformat/librtmp.c +++ b/libavformat/librtmp.c @@ -37,7 +37,17 @@ typedef struct LibRTMPContext { const AVClass *class; RTMP rtmp; char *app; + char *conn; + char *subscribe; char *playpath; + char *tcurl; + char *flashver; + char *swfurl; + char *swfverify; + char *pageurl; + char *client_buffer_time; + int live; + char *temp_filename; } LibRTMPContext; static void rtmp_log(int level, const char *fmt, va_list args) @@ -62,6 +72,7 @@ static int rtmp_close(URLContext *s) RTMP *r = &ctx->rtmp; RTMP_Close(r); + av_freep(&ctx->temp_filename); return 0; } @@ -83,6 +94,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) RTMP *r = &ctx->rtmp; int rc = 0, level; char *filename = s->filename; + int len = strlen(s->filename) + 1; switch (av_log_get_level()) { default: @@ -96,22 +108,111 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) RTMP_LogSetLevel(level); RTMP_LogSetCallback(rtmp_log); - if (ctx->app || ctx->playpath) { - int len = strlen(s->filename) + 1; - if (ctx->app) len += strlen(ctx->app) + sizeof(" app="); - if (ctx->playpath) len += strlen(ctx->playpath) + sizeof(" playpath="); + if (ctx->app) len += strlen(ctx->app) + sizeof(" app="); + if (ctx->tcurl) len += strlen(ctx->tcurl) + sizeof(" tcUrl="); + if (ctx->pageurl) len += strlen(ctx->pageurl) + sizeof(" pageUrl="); + if (ctx->flashver) len += strlen(ctx->flashver) + sizeof(" flashver="); - if (!(filename = av_malloc(len))) - return AVERROR(ENOMEM); + if (ctx->conn) { + char *sep, *p = ctx->conn; + int options = 0; - av_strlcpy(filename, s->filename, len); - if (ctx->app) { - av_strlcat(filename, " app=", len); - av_strlcat(filename, ctx->app, len); + while (p) { + options++; + p += strspn(p, " "); + if (!*p) + break; + sep = strchr(p, ' '); + if (sep) + p = sep + 1; + else + break; } - if (ctx->playpath) { - av_strlcat(filename, " playpath=", len); - av_strlcat(filename, ctx->playpath, len); + len += options * sizeof(" conn="); + len += strlen(ctx->conn); + } + + if (ctx->playpath) + len += strlen(ctx->playpath) + sizeof(" playpath="); + if (ctx->live) + len += sizeof(" live=1"); + if (ctx->subscribe) + len += strlen(ctx->subscribe) + sizeof(" subscribe="); + + if (ctx->client_buffer_time) + len += strlen(ctx->client_buffer_time) + sizeof(" buffer="); + + if (ctx->swfurl || ctx->swfverify) { + len += sizeof(" swfUrl="); + + if (ctx->swfverify) + len += strlen(ctx->swfverify) + sizeof(" swfVfy=1"); + else + len += strlen(ctx->swfurl); + } + + if (!(ctx->temp_filename = filename = av_malloc(len))) + return AVERROR(ENOMEM); + + av_strlcpy(filename, s->filename, len); + if (ctx->app) { + av_strlcat(filename, " app=", len); + av_strlcat(filename, ctx->app, len); + } + if (ctx->tcurl) { + av_strlcat(filename, " tcUrl=", len); + av_strlcat(filename, ctx->tcurl, len); + } + if (ctx->pageurl) { + av_strlcat(filename, " pageUrl=", len); + av_strlcat(filename, ctx->pageurl, len); + } + if (ctx->swfurl) { + av_strlcat(filename, " swfUrl=", len); + av_strlcat(filename, ctx->pageurl, len); + } + if (ctx->flashver) { + av_strlcat(filename, " flashVer=", len); + av_strlcat(filename, ctx->flashver, len); + } + if (ctx->conn) { + char *sep, *p = ctx->conn; + while (p) { + av_strlcat(filename, " conn=", len); + p += strspn(p, " "); + if (!*p) + break; + sep = strchr(p, ' '); + if (sep) + *sep = '\0'; + av_strlcat(filename, p, len); + + if (sep) + p = sep + 1; + } + } + if (ctx->playpath) { + av_strlcat(filename, " playpath=", len); + av_strlcat(filename, ctx->playpath, len); + } + if (ctx->live) + av_strlcat(filename, " live=1", len); + if (ctx->subscribe) { + av_strlcat(filename, " subscribe=", len); + av_strlcat(filename, ctx->subscribe, len); + } + if (ctx->client_buffer_time) { + av_strlcat(filename, " buffer=", len); + av_strlcat(filename, ctx->client_buffer_time, len); + } + if (ctx->swfurl || ctx->swfverify) { + av_strlcat(filename, " swfUrl=", len); + + if (ctx->swfverify) { + av_strlcat(filename, ctx->swfverify, len); + av_strlcat(filename, " swfVfy=1", len); + } else { + av_strlcat(filename, ctx->swfurl, len); } } @@ -130,10 +231,9 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) } s->is_streamed = 1; - rc = 0; + return 0; fail: - if (filename != s->filename) - av_freep(&filename); + av_freep(&ctx->temp_filename); if (rc) RTMP_Close(r); @@ -197,8 +297,20 @@ static int rtmp_get_file_handle(URLContext *s) #define DEC AV_OPT_FLAG_DECODING_PARAM #define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, - {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, + {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, + {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_STRING, {.str = "3000"}, 0, 0, DEC|ENC}, + {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, + {"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, + {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_live"}, + {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"}, + {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"}, + {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"}, + {"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC}, + {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, + {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC}, + {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, + {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically. (unimplemented)", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC}, + {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, { NULL }, }; diff --git a/libavformat/libsmbclient.c b/libavformat/libsmbclient.c new file mode 100644 index 000000000..892d2db8a --- /dev/null +++ b/libavformat/libsmbclient.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2014 Lukasz Marek + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "libavutil/avstring.h" +#include "libavutil/opt.h" +#include "avformat.h" +#include "internal.h" +#include "url.h" + +typedef struct { + const AVClass *class; + SMBCCTX *ctx; + int fd; + int64_t filesize; + int trunc; + int timeout; + char *workgroup; +} LIBSMBContext; + +static void libsmbc_get_auth_data(SMBCCTX *c, const char *server, const char *share, + char *workgroup, int workgroup_len, + char *username, int username_len, + char *password, int password_len) +{ + /* Do nothing yet. Credentials are passed via url. + * Callback must exists, there might be a segmentation fault otherwise. */ +} + +static av_cold int libsmbc_connect(URLContext *h) +{ + LIBSMBContext *libsmbc = h->priv_data; + + libsmbc->ctx = smbc_new_context(); + if (!libsmbc->ctx) { + av_log(h, AV_LOG_ERROR, "Cannot create context: %s.\n", strerror(errno)); + return AVERROR(errno); + } + if (!smbc_init_context(libsmbc->ctx)) { + av_log(h, AV_LOG_ERROR, "Cannot initialize context: %s.\n", strerror(errno)); + return AVERROR(errno); + } + smbc_set_context(libsmbc->ctx); + + smbc_setOptionUserData(libsmbc->ctx, h); + smbc_setFunctionAuthDataWithContext(libsmbc->ctx, libsmbc_get_auth_data); + + if (libsmbc->timeout != -1) + smbc_setTimeout(libsmbc->ctx, libsmbc->timeout); + if (libsmbc->workgroup) + smbc_setWorkgroup(libsmbc->ctx, libsmbc->workgroup); + + if (smbc_init(NULL, 0) < 0) { + av_log(h, AV_LOG_ERROR, "Initialization failed: %s\n", strerror(errno)); + return AVERROR(errno); + } + return 0; +} + +static av_cold int libsmbc_close(URLContext *h) +{ + LIBSMBContext *libsmbc = h->priv_data; + if (libsmbc->fd >= 0) { + smbc_close(libsmbc->fd); + libsmbc->fd = -1; + } + if (libsmbc->ctx) { + smbc_free_context(libsmbc->ctx, 1); + libsmbc->ctx = NULL; + } + return 0; +} + +static av_cold int libsmbc_open(URLContext *h, const char *url, int flags) +{ + LIBSMBContext *libsmbc = h->priv_data; + int access, ret; + struct stat st; + + libsmbc->fd = -1; + libsmbc->filesize = -1; + + if ((ret = libsmbc_connect(h)) < 0) + goto fail; + + if ((flags & AVIO_FLAG_WRITE) && (flags & AVIO_FLAG_READ)) { + access = O_CREAT | O_RDWR; + if (libsmbc->trunc) + access |= O_TRUNC; + } else if (flags & AVIO_FLAG_WRITE) { + access = O_CREAT | O_WRONLY; + if (libsmbc->trunc) + access |= O_TRUNC; + } else + access = O_RDONLY; + + /* 0666 = -rw-rw-rw- = read+write for everyone, minus umask */ + if ((libsmbc->fd = smbc_open(url, access, 0666)) < 0) { + ret = AVERROR(errno); + av_log(h, AV_LOG_ERROR, "File open failed: %s\n", strerror(errno)); + goto fail; + } + + if (smbc_fstat(libsmbc->fd, &st) < 0) + av_log(h, AV_LOG_WARNING, "Cannot stat file: %s\n", strerror(errno)); + else + libsmbc->filesize = st.st_size; + + return 0; + fail: + libsmbc_close(h); + return ret; +} + +static int64_t libsmbc_seek(URLContext *h, int64_t pos, int whence) +{ + LIBSMBContext *libsmbc = h->priv_data; + int64_t newpos; + + if (whence == AVSEEK_SIZE) { + if (libsmbc->filesize == -1) { + av_log(h, AV_LOG_ERROR, "Error during seeking: filesize is unknown.\n"); + return AVERROR(EIO); + } else + return libsmbc->filesize; + } + + if ((newpos = smbc_lseek(libsmbc->fd, pos, whence)) < 0) { + int err = errno; + av_log(h, AV_LOG_ERROR, "Error during seeking: %s\n", strerror(err)); + return AVERROR(err); + } + + return newpos; +} + +static int libsmbc_read(URLContext *h, unsigned char *buf, int size) +{ + LIBSMBContext *libsmbc = h->priv_data; + int bytes_read; + + if ((bytes_read = smbc_read(libsmbc->fd, buf, size)) < 0) { + av_log(h, AV_LOG_ERROR, "Read error: %s\n", strerror(errno)); + return AVERROR(errno); + } + + return bytes_read; +} + +static int libsmbc_write(URLContext *h, const unsigned char *buf, int size) +{ + LIBSMBContext *libsmbc = h->priv_data; + int bytes_written; + + if ((bytes_written = smbc_write(libsmbc->fd, buf, size)) < 0) { + av_log(h, AV_LOG_ERROR, "Write error: %s\n", strerror(errno)); + return AVERROR(errno); + } + + return bytes_written; +} + +#define OFFSET(x) offsetof(LIBSMBContext, x) +#define D AV_OPT_FLAG_DECODING_PARAM +#define E AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + {"timeout", "set timeout in ms of socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E }, + {"truncate", "truncate existing files on write", OFFSET(trunc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, E }, + {"workgroup", "set the workgroup used for making connections", OFFSET(workgroup), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E }, + {NULL} +}; + +static const AVClass libsmbclient_context_class = { + .class_name = "libsmbc", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +URLProtocol ff_libsmbclient_protocol = { + .name = "smb", + .url_open = libsmbc_open, + .url_read = libsmbc_read, + .url_write = libsmbc_write, + .url_seek = libsmbc_seek, + .url_close = libsmbc_close, + .priv_data_size = sizeof(LIBSMBContext), + .priv_data_class = &libsmbclient_context_class, + .flags = URL_PROTOCOL_FLAG_NETWORK, +}; diff --git a/libavformat/libssh.c b/libavformat/libssh.c index b20e93bba..3ec60cb8f 100644 --- a/libavformat/libssh.c +++ b/libavformat/libssh.c @@ -71,6 +71,9 @@ static av_cold int libssh_authentication(LIBSSHContext *libssh, const char *user if (user) ssh_options_set(libssh->session, SSH_OPTIONS_USER, user); + if (ssh_userauth_none(libssh->session, NULL) == SSH_AUTH_SUCCESS) + return 0; + auth_methods = ssh_userauth_list(libssh->session, NULL); if (auth_methods & SSH_AUTH_METHOD_PUBLICKEY) { @@ -164,13 +167,18 @@ static av_cold void libssh_stat_file(LIBSSHContext *libssh) static av_cold int libssh_close(URLContext *h) { LIBSSHContext *libssh = h->priv_data; - if (libssh->file) + if (libssh->file) { sftp_close(libssh->file); - if (libssh->sftp) + libssh->file = NULL; + } + if (libssh->sftp) { sftp_free(libssh->sftp); + libssh->sftp = NULL; + } if (libssh->session) { ssh_disconnect(libssh->session); ssh_free(libssh->session); + libssh->session = NULL; } return 0; } diff --git a/libavformat/loasdec.c b/libavformat/loasdec.c index 05ef0fe3a..c41809be0 100644 --- a/libavformat/loasdec.c +++ b/libavformat/loasdec.c @@ -25,6 +25,8 @@ #include "internal.h" #include "rawdec.h" +#define LOAS_SYNC_WORD 0x2b7 + static int loas_probe(AVProbeData *p) { int max_frames = 0, first_frames = 0; @@ -35,27 +37,32 @@ static int loas_probe(AVProbeData *p) const uint8_t *end = buf0 + p->buf_size - 3; buf = buf0; - for(; buf < end; buf= buf2+1) { + for (; buf < end; buf = buf2 + 1) { buf2 = buf; - for(frames = 0; buf2 < end; frames++) { + for (frames = 0; buf2 < end; frames++) { uint32_t header = AV_RB24(buf2); - if((header >> 13) != 0x2B7) + if ((header >> 13) != LOAS_SYNC_WORD) break; fsize = (header & 0x1FFF) + 3; - if(fsize < 7) + if (fsize < 7) break; fsize = FFMIN(fsize, end - buf2); buf2 += fsize; } max_frames = FFMAX(max_frames, frames); - if(buf == buf0) - first_frames= frames; + if (buf == buf0) + first_frames = frames; } - if (first_frames>=3) return AVPROBE_SCORE_EXTENSION+1; - else if(max_frames>100)return AVPROBE_SCORE_EXTENSION; - else if(max_frames>=3) return AVPROBE_SCORE_EXTENSION / 2; - else return 0; + + if (first_frames >= 3) + return AVPROBE_SCORE_EXTENSION + 1; + else if (max_frames > 100) + return AVPROBE_SCORE_EXTENSION; + else if (max_frames >= 3) + return AVPROBE_SCORE_EXTENSION / 2; + else + return 0; } static int loas_read_header(AVFormatContext *s) diff --git a/libavformat/lrc.c b/libavformat/lrc.c new file mode 100644 index 000000000..139c6506e --- /dev/null +++ b/libavformat/lrc.c @@ -0,0 +1,34 @@ +/* + * LRC lyrics file format decoder + * Copyright (c) 2014 StarBrilliant + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "metadata.h" +#include "lrc.h" + +const AVMetadataConv ff_lrc_metadata_conv[] = { + {"ti", "title"}, + {"al", "album"}, + {"ar", "artist"}, + {"au", "author"}, + {"by", "creator"}, + {"re", "encoder"}, + {"ve", "encoder_version"}, + {0, 0} +}; diff --git a/libavformat/lrc.h b/libavformat/lrc.h new file mode 100644 index 000000000..0297bc1eb --- /dev/null +++ b/libavformat/lrc.h @@ -0,0 +1,29 @@ +/* + * LRC lyrics file format decoder + * Copyright (c) 2014 StarBrilliant + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_LRC_H +#define AVFORMAT_LRC_H + +#include "metadata.h" + +extern const AVMetadataConv ff_lrc_metadata_conv[]; + +#endif diff --git a/libavformat/lrcdec.c b/libavformat/lrcdec.c new file mode 100644 index 000000000..3b02e3492 --- /dev/null +++ b/libavformat/lrcdec.c @@ -0,0 +1,248 @@ +/* + * LRC lyrics file format decoder + * Copyright (c) 2014 StarBrilliant + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "avformat.h" +#include "internal.h" +#include "lrc.h" +#include "metadata.h" +#include "subtitles.h" +#include "libavutil/bprint.h" +#include "libavutil/dict.h" + +typedef struct LRCContext { + FFDemuxSubtitlesQueue q; + int64_t ts_offset; // offset metadata item +} LRCContext; + +static int64_t find_header(const char *p) +{ + int64_t offset = 0; + while(p[offset] == ' ' || p[offset] == '\t') { + offset++; + } + if(p[offset] == '[' && p[offset + 1] >= 'a' && p[offset + 1] <= 'z') { + return offset; + } else { + return -1; + } +} + +static int64_t count_ts(const char *p) +{ + int64_t offset = 0; + int in_brackets = 0; + + for(;;) { + if(p[offset] == ' ' || p[offset] == '\t') { + offset++; + } else if(p[offset] == '[') { + offset++; + in_brackets++; + } else if (p[offset] == ']' && in_brackets) { + offset++; + in_brackets--; + } else if(in_brackets && + (p[offset] == ':' || p[offset] == '.' || p[offset] == '-' || + (p[offset] >= '0' && p[offset] <= '9'))) { + offset++; + } else { + break; + } + } + return offset; +} + +static int64_t read_ts(const char *p, int64_t *start) +{ + int64_t offset = 0; + uint64_t mm, ss, cs; + + while(p[offset] == ' ' || p[offset] == '\t') { + offset++; + } + if(p[offset] != '[') { + return 0; + } + if(sscanf(p, "[-%"SCNu64":%"SCNu64".%"SCNu64"]", &mm, &ss, &cs) == 3) { + /* Just in case negative pts, players may drop it but we won't. */ + *start = -(int64_t) (mm*60000 + ss*1000 + cs*10); + } else if(sscanf(p, "[%"SCNu64":%"SCNu64".%"SCNu64"]", &mm, &ss, &cs) == 3) { + *start = mm*60000 + ss*1000 + cs*10; + } else { + return 0; + } + do { + offset++; + } while(p[offset] && p[offset-1] != ']'); + return offset; +} + +static int64_t read_line(AVBPrint *buf, AVIOContext *pb) +{ + int64_t pos = avio_tell(pb); + + av_bprint_clear(buf); + while(!url_feof(pb)) { + int c = avio_r8(pb); + if(c != '\r') { + av_bprint_chars(buf, c, 1); + } + if(c == '\n') { + break; + } + } + return pos; +} + +static int lrc_probe(AVProbeData *p) +{ + int64_t offset = 0; + int64_t mm; + uint64_t ss, cs; + const AVMetadataConv *metadata_item; + + if(!memcmp(p->buf, "\xef\xbb\xbf", 3)) { // Skip UTF-8 BOM header + offset += 3; + } + while(p->buf[offset] == '\n' || p->buf[offset] == '\r') { + offset++; + } + if(p->buf[offset] != '[') { + return 0; + } + offset++; + // Common metadata item but not exist in ff_lrc_metadata_conv + if(!memcmp(p->buf + offset, "offset:", 7)) { + return 40; + } + if(sscanf(p->buf + offset, "%"SCNd64":%"SCNu64".%"SCNu64"]", + &mm, &ss, &cs) == 3) { + return 50; + } + // Metadata items exist in ff_lrc_metadata_conv + for(metadata_item = ff_lrc_metadata_conv; + metadata_item->native; metadata_item++) { + size_t metadata_item_len = strlen(metadata_item->native); + if(p->buf[offset + metadata_item_len] == ':' && + !memcmp(p->buf + offset, metadata_item->native, metadata_item_len)) { + return 40; + } + } + return 5; // Give it 5 scores since it starts with a bracket +} + +static int lrc_read_header(AVFormatContext *s) +{ + LRCContext *lrc = s->priv_data; + AVBPrint line; + AVStream *st; + + st = avformat_new_stream(s, NULL); + if(!st) { + return AVERROR(ENOMEM); + } + avpriv_set_pts_info(st, 64, 1, 1000); + lrc->ts_offset = 0; + st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codec->codec_id = AV_CODEC_ID_TEXT; + av_bprint_init(&line, 0, AV_BPRINT_SIZE_UNLIMITED); + + while(!url_feof(s->pb)) { + int64_t pos = read_line(&line, s->pb); + int64_t header_offset = find_header(line.str); + if(header_offset >= 0) { + char *comma_offset = strchr(line.str, ':'); + if(comma_offset) { + char *right_bracket_offset = strchr(line.str, ']'); + if(!right_bracket_offset) { + continue; + } + + *right_bracket_offset = *comma_offset = '\0'; + if(strcmp(line.str + 1, "offset") || + sscanf(comma_offset + 1, "%"SCNd64, &lrc->ts_offset) != 1) { + av_dict_set(&s->metadata, line.str + 1, comma_offset + 1, 0); + } + *comma_offset = ':'; + *right_bracket_offset = ']'; + } + + } else { + AVPacket *sub; + int64_t ts_start = AV_NOPTS_VALUE; + int64_t ts_stroffset = 0; + int64_t ts_stroffset_incr = 0; + int64_t ts_strlength = count_ts(line.str); + + while((ts_stroffset_incr = read_ts(line.str + ts_stroffset, + &ts_start)) != 0) { + ts_stroffset += ts_stroffset_incr; + sub = ff_subtitles_queue_insert(&lrc->q, line.str + ts_strlength, + line.len - ts_strlength, 0); + if(!sub) { + return AVERROR(ENOMEM); + } + sub->pos = pos; + sub->pts = ts_start - lrc->ts_offset; + sub->duration = -1; + } + } + } + ff_subtitles_queue_finalize(&lrc->q); + ff_metadata_conv_ctx(s, NULL, ff_lrc_metadata_conv); + return 0; +} + +static int lrc_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + LRCContext *lrc = s->priv_data; + return ff_subtitles_queue_read_packet(&lrc->q, pkt); +} + +static int lrc_read_seek(AVFormatContext *s, int stream_index, + int64_t min_ts, int64_t ts, int64_t max_ts, int flags) +{ + LRCContext *lrc = s->priv_data; + return ff_subtitles_queue_seek(&lrc->q, s, stream_index, + min_ts, ts, max_ts, flags); +} + +static int lrc_read_close(AVFormatContext *s) +{ + LRCContext *lrc = s->priv_data; + ff_subtitles_queue_clean(&lrc->q); + return 0; +} + +AVInputFormat ff_lrc_demuxer = { + .name = "lrc", + .long_name = NULL_IF_CONFIG_SMALL("LRC lyrics"), + .priv_data_size = sizeof (LRCContext), + .read_probe = lrc_probe, + .read_header = lrc_read_header, + .read_packet = lrc_read_packet, + .read_close = lrc_read_close, + .read_seek2 = lrc_read_seek +}; diff --git a/libavformat/lrcenc.c b/libavformat/lrcenc.c new file mode 100644 index 000000000..c1afc2cca --- /dev/null +++ b/libavformat/lrcenc.c @@ -0,0 +1,152 @@ +/* + * LRC lyrics file format decoder + * Copyright (c) 2014 StarBrilliant + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "avformat.h" +#include "internal.h" +#include "lrc.h" +#include "metadata.h" +#include "subtitles.h" +#include "version.h" +#include "libavutil/bprint.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" +#include "libavutil/macros.h" + +static int lrc_write_header(AVFormatContext *s) +{ + const AVDictionaryEntry *metadata_item; + + if(s->nb_streams != 1 || + s->streams[0]->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) { + av_log(s, AV_LOG_ERROR, + "LRC supports only a single subtitle stream.\n"); + return AVERROR(EINVAL); + } + if(s->streams[0]->codec->codec_id != AV_CODEC_ID_SUBRIP && + s->streams[0]->codec->codec_id != AV_CODEC_ID_TEXT) { + av_log(s, AV_LOG_ERROR, "Unsupported subtitle codec: %s\n", + avcodec_get_name(s->streams[0]->codec->codec_id)); + return AVERROR(EINVAL); + } + avpriv_set_pts_info(s->streams[0], 64, 1, 100); + + ff_metadata_conv_ctx(s, ff_lrc_metadata_conv, NULL); + if(!(s->flags & AVFMT_FLAG_BITEXACT)) { // avoid breaking regression tests + /* LRC provides a metadata slot for specifying encoder version + * in addition to encoder name. We will store LIBAVFORMAT_VERSION + * to it. + */ + av_dict_set(&s->metadata, "ve", AV_STRINGIFY(LIBAVFORMAT_VERSION), 0); + } else { + av_dict_set(&s->metadata, "ve", NULL, 0); + } + for(metadata_item = NULL; + (metadata_item = av_dict_get(s->metadata, "", metadata_item, + AV_DICT_IGNORE_SUFFIX)) != NULL;) { + char *delim; + if(!metadata_item->value[0]) { + continue; + } + while((delim = strchr(metadata_item->value, '\n')) != NULL) { + *delim = ' '; + } + while((delim = strchr(metadata_item->value, '\r')) != NULL) { + *delim = ' '; + } + avio_printf(s->pb, "[%s:%s]\n", + metadata_item->key, metadata_item->value); + } + avio_printf(s->pb, "\n"); + return 0; +} + +static int lrc_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + if(pkt->pts != AV_NOPTS_VALUE) { + char *data = av_malloc(pkt->size + 1); + char *line; + char *delim; + + if(!data) { + return AVERROR(ENOMEM); + } + memcpy(data, pkt->data, pkt->size); + data[pkt->size] = '\0'; + + for(delim = data + pkt->size - 1; + delim >= data && (delim[0] == '\n' || delim[0] == '\r'); delim--) { + delim[0] = '\0'; // Strip last empty lines + } + line = data; + while(line[0] == '\n' || line[0] == '\r') { + line++; // Skip first empty lines + } + + while(line) { + delim = strchr(line, '\n'); + if(delim) { + if(delim > line && delim[-1] == '\r') { + delim[-1] = '\0'; + } + delim[0] = '\0'; + delim++; + } + if(line[0] == '[') { + av_log(s, AV_LOG_WARNING, + "Subtitle starts with '[', may cause problems with LRC format.\n"); + } + + if(pkt->pts >= 0) { + avio_printf(s->pb, "[%02"PRId64":%02"PRId64".%02"PRId64"]", + (pkt->pts / 6000), + ((pkt->pts / 100) % 60), + (pkt->pts % 100)); + } else { + /* Offset feature of LRC can easily make pts negative, + * we just output it directly and let the player drop it. */ + avio_printf(s->pb, "[-%02"PRId64":%02"PRId64".%02"PRId64"]", + (-pkt->pts) / 6000, + ((-pkt->pts) / 100) % 60, + (-pkt->pts) % 100); + } + avio_printf(s->pb, "%s\n", line); + line = delim; + } + av_free(data); + } + return 0; +} + +AVOutputFormat ff_lrc_muxer = { + .name = "lrc", + .long_name = NULL_IF_CONFIG_SMALL("LRC lyrics"), + .extensions = "lrc", + .priv_data_size = 0, + .write_header = lrc_write_header, + .write_packet = lrc_write_packet, + .flags = AVFMT_VARIABLE_FPS | AVFMT_GLOBALHEADER | + AVFMT_TS_NEGATIVE | AVFMT_TS_NONSTRICT, + .subtitle_codec = AV_CODEC_ID_SUBRIP +}; diff --git a/libavformat/lxfdec.c b/libavformat/lxfdec.c index f0a96396b..19f7f2738 100644 --- a/libavformat/lxfdec.c +++ b/libavformat/lxfdec.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/intreadwrite.h" #include "libavcodec/bytestream.h" #include "avformat.h" @@ -128,12 +130,12 @@ 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 %i\n", version); + avpriv_request_sample(s, "Unknown format version %"PRIu32"\n", version); if (header_size < (version ? 72 : 60) || header_size > LXF_MAX_PACKET_HEADER_SIZE || (header_size & 3)) { - av_log(s, AV_LOG_ERROR, "Invalid header size 0x%x\n", header_size); + av_log(s, AV_LOG_ERROR, "Invalid header size 0x%"PRIx32"\n", header_size); return AVERROR_INVALIDDATA; } @@ -301,7 +303,8 @@ static int lxf_read_packet(AVFormatContext *s, AVPacket *pkt) stream = lxf->packet_type; if (stream > 1) { - av_log(s, AV_LOG_WARNING, "got packet with illegal stream index %u\n", stream); + av_log(s, AV_LOG_WARNING, + "got packet with illegal stream index %"PRIu32"\n", stream); return AVERROR(EAGAIN); } diff --git a/libavformat/m4vdec.c b/libavformat/m4vdec.c index c2fd4d7ab..ead0066cc 100644 --- a/libavformat/m4vdec.c +++ b/libavformat/m4vdec.c @@ -45,7 +45,7 @@ static int mpeg4video_probe(AVProbeData *probe_packet) } if (VOP >= VISO && VOP >= VOL && VO >= VOL && VOL > 0 && res==0) - return VOP+VO > 3 ? AVPROBE_SCORE_EXTENSION : AVPROBE_SCORE_EXTENSION/2; + return VOP+VO > 4 ? AVPROBE_SCORE_EXTENSION : AVPROBE_SCORE_EXTENSION/2; return 0; } diff --git a/libavformat/matroska.c b/libavformat/matroska.c index 5f5d25ad9..d281ef4fd 100644 --- a/libavformat/matroska.c +++ b/libavformat/matroska.c @@ -113,6 +113,7 @@ const CodecMime ff_mkv_mime_tags[] = { {"application/x-truetype-font", AV_CODEC_ID_TTF}, {"application/x-font" , AV_CODEC_ID_TTF}, {"application/vnd.ms-opentype", AV_CODEC_ID_OTF}, + {"binary" , AV_CODEC_ID_BIN_DATA}, {"" , AV_CODEC_ID_NONE} }; diff --git a/libavformat/matroska.h b/libavformat/matroska.h index 3bb5aee08..e01b9de22 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -284,4 +284,16 @@ extern const AVMetadataConv ff_mkv_metadata_conv[]; extern const char * const ff_matroska_video_stereo_mode[MATROSKA_VIDEO_STEREO_MODE_COUNT]; extern const char * const ff_matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_PLANE_COUNT]; +/* AVStream Metadata tag keys for WebM Dash Manifest */ +#define INITIALIZATION_RANGE "webm_dash_manifest_initialization_range" +#define CUES_START "webm_dash_manifest_cues_start" +#define CUES_END "webm_dash_manifest_cues_end" +#define FILENAME "webm_dash_manifest_file_name" +#define BANDWIDTH "webm_dash_manifest_bandwidth" +#define DURATION "webm_dash_manifest_duration" +#define CLUSTER_KEYFRAME "webm_dash_manifest_cluster_keyframe" +#define CUE_TIMESTAMPS "webm_dash_manifest_cue_timestamps" +#define TRACK_NUMBER "webm_dash_manifest_track_number" +#define CODEC_PRIVATE_SIZE "webm_dash_manifest_codec_priv_size" + #endif /* AVFORMAT_MATROSKA_H */ diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 4726e94d8..ec4352672 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -28,30 +28,38 @@ * @see specs available on the Matroska project page: http://www.matroska.org/ */ +#include "config.h" + +#include #include -#include "avformat.h" -#include "internal.h" -#include "avio_internal.h" -/* For ff_codec_get_id(). */ -#include "riff.h" -#include "isom.h" -#include "rmsipr.h" -#include "matroska.h" -#include "libavcodec/bytestream.h" -#include "libavcodec/mpeg4audio.h" -#include "libavutil/base64.h" -#include "libavutil/intfloat.h" -#include "libavutil/intreadwrite.h" -#include "libavutil/avstring.h" -#include "libavutil/lzo.h" -#include "libavutil/mathematics.h" -#include "libavutil/dict.h" -#if CONFIG_ZLIB -#include -#endif #if CONFIG_BZLIB #include #endif +#if CONFIG_ZLIB +#include +#endif + +#include "libavutil/avstring.h" +#include "libavutil/base64.h" +#include "libavutil/dict.h" +#include "libavutil/intfloat.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/lzo.h" +#include "libavutil/mathematics.h" + +#include "libavcodec/bytestream.h" +#include "libavcodec/flac.h" +#include "libavcodec/mpeg4audio.h" + +#include "avformat.h" +#include "avio_internal.h" +#include "internal.h" +#include "isom.h" +#include "matroska.h" +#include "oggdec.h" +/* For ff_codec_get_id(). */ +#include "riff.h" +#include "rmsipr.h" typedef enum { EBML_NONE, @@ -185,7 +193,7 @@ typedef struct { EbmlBin bin; AVStream *stream; -} MatroskaAttachement; +} MatroskaAttachment; typedef struct { uint64_t start; @@ -299,67 +307,67 @@ typedef struct { } MatroskaBlock; static EbmlSyntax ebml_header[] = { - { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, offsetof(Ebml,version), {.u=EBML_VERSION} }, - { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, offsetof(Ebml,max_size), {.u=8} }, - { EBML_ID_EBMLMAXIDLENGTH, EBML_UINT, 0, offsetof(Ebml,id_length), {.u=4} }, - { EBML_ID_DOCTYPE, EBML_STR, 0, offsetof(Ebml,doctype), {.s="(none)"} }, - { EBML_ID_DOCTYPEREADVERSION, EBML_UINT, 0, offsetof(Ebml,doctype_version), {.u=1} }, - { EBML_ID_EBMLVERSION, EBML_NONE }, - { EBML_ID_DOCTYPEVERSION, EBML_NONE }, + { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, offsetof(Ebml, version), { .u = EBML_VERSION } }, + { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, offsetof(Ebml, max_size), { .u = 8 } }, + { EBML_ID_EBMLMAXIDLENGTH, EBML_UINT, 0, offsetof(Ebml, id_length), { .u = 4 } }, + { EBML_ID_DOCTYPE, EBML_STR, 0, offsetof(Ebml, doctype), { .s = "(none)" } }, + { EBML_ID_DOCTYPEREADVERSION, EBML_UINT, 0, offsetof(Ebml, doctype_version), { .u = 1 } }, + { EBML_ID_EBMLVERSION, EBML_NONE }, + { EBML_ID_DOCTYPEVERSION, EBML_NONE }, { 0 } }; static EbmlSyntax ebml_syntax[] = { - { EBML_ID_HEADER, EBML_NEST, 0, 0, {.n=ebml_header} }, + { EBML_ID_HEADER, EBML_NEST, 0, 0, { .n = ebml_header } }, { 0 } }; static EbmlSyntax matroska_info[] = { - { MATROSKA_ID_TIMECODESCALE, EBML_UINT, 0, offsetof(MatroskaDemuxContext,time_scale), {.u=1000000} }, - { MATROSKA_ID_DURATION, EBML_FLOAT, 0, offsetof(MatroskaDemuxContext,duration) }, - { MATROSKA_ID_TITLE, EBML_UTF8, 0, offsetof(MatroskaDemuxContext,title) }, - { MATROSKA_ID_WRITINGAPP, EBML_NONE }, - { MATROSKA_ID_MUXINGAPP, EBML_UTF8, 0, offsetof(MatroskaDemuxContext,muxingapp) }, - { MATROSKA_ID_DATEUTC, EBML_BIN, 0, offsetof(MatroskaDemuxContext,date_utc) }, - { MATROSKA_ID_SEGMENTUID, EBML_NONE }, + { MATROSKA_ID_TIMECODESCALE, EBML_UINT, 0, offsetof(MatroskaDemuxContext, time_scale), { .u = 1000000 } }, + { MATROSKA_ID_DURATION, EBML_FLOAT, 0, offsetof(MatroskaDemuxContext, duration) }, + { MATROSKA_ID_TITLE, EBML_UTF8, 0, offsetof(MatroskaDemuxContext, title) }, + { MATROSKA_ID_WRITINGAPP, EBML_NONE }, + { MATROSKA_ID_MUXINGAPP, EBML_UTF8, 0, offsetof(MatroskaDemuxContext, muxingapp) }, + { MATROSKA_ID_DATEUTC, EBML_BIN, 0, offsetof(MatroskaDemuxContext, date_utc) }, + { MATROSKA_ID_SEGMENTUID, EBML_NONE }, { 0 } }; static EbmlSyntax matroska_track_video[] = { - { MATROSKA_ID_VIDEOFRAMERATE, EBML_FLOAT,0, offsetof(MatroskaTrackVideo,frame_rate) }, - { MATROSKA_ID_VIDEODISPLAYWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo,display_width), {.u=-1} }, - { MATROSKA_ID_VIDEODISPLAYHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo,display_height), {.u=-1} }, - { MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo,pixel_width) }, - { MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo,pixel_height) }, - { MATROSKA_ID_VIDEOCOLORSPACE, EBML_BIN, 0, offsetof(MatroskaTrackVideo,color_space) }, - { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo,stereo_mode) }, - { MATROSKA_ID_VIDEOALPHAMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo,alpha_mode) }, - { MATROSKA_ID_VIDEOPIXELCROPB, EBML_NONE }, - { MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE }, - { MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE }, - { MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE }, - { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_NONE }, - { MATROSKA_ID_VIDEOFLAGINTERLACED,EBML_NONE }, - { MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE }, + { MATROSKA_ID_VIDEOFRAMERATE, EBML_FLOAT, 0, offsetof(MatroskaTrackVideo, frame_rate) }, + { MATROSKA_ID_VIDEODISPLAYWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo, display_width), { .u=-1 } }, + { MATROSKA_ID_VIDEODISPLAYHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo, display_height), { .u=-1 } }, + { MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo, pixel_width) }, + { MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo, pixel_height) }, + { MATROSKA_ID_VIDEOCOLORSPACE, EBML_BIN, 0, offsetof(MatroskaTrackVideo, color_space) }, + { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo, stereo_mode) }, + { MATROSKA_ID_VIDEOALPHAMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo, alpha_mode) }, + { MATROSKA_ID_VIDEOPIXELCROPB, EBML_NONE }, + { MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE }, + { MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE }, + { MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE }, + { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_NONE }, + { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_NONE }, + { MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE }, { 0 } }; static EbmlSyntax matroska_track_audio[] = { - { MATROSKA_ID_AUDIOSAMPLINGFREQ, EBML_FLOAT,0, offsetof(MatroskaTrackAudio,samplerate), {.f=8000.0} }, - { MATROSKA_ID_AUDIOOUTSAMPLINGFREQ,EBML_FLOAT,0,offsetof(MatroskaTrackAudio,out_samplerate) }, - { MATROSKA_ID_AUDIOBITDEPTH, EBML_UINT, 0, offsetof(MatroskaTrackAudio,bitdepth) }, - { MATROSKA_ID_AUDIOCHANNELS, EBML_UINT, 0, offsetof(MatroskaTrackAudio,channels), {.u=1} }, + { MATROSKA_ID_AUDIOSAMPLINGFREQ, EBML_FLOAT, 0, offsetof(MatroskaTrackAudio, samplerate), { .f = 8000.0 } }, + { MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, EBML_FLOAT, 0, offsetof(MatroskaTrackAudio, out_samplerate) }, + { MATROSKA_ID_AUDIOBITDEPTH, EBML_UINT, 0, offsetof(MatroskaTrackAudio, bitdepth) }, + { MATROSKA_ID_AUDIOCHANNELS, EBML_UINT, 0, offsetof(MatroskaTrackAudio, channels), { .u = 1 } }, { 0 } }; static EbmlSyntax matroska_track_encoding_compression[] = { - { MATROSKA_ID_ENCODINGCOMPALGO, EBML_UINT, 0, offsetof(MatroskaTrackCompression,algo), {.u=0} }, - { MATROSKA_ID_ENCODINGCOMPSETTINGS,EBML_BIN, 0, offsetof(MatroskaTrackCompression,settings) }, + { MATROSKA_ID_ENCODINGCOMPALGO, EBML_UINT, 0, offsetof(MatroskaTrackCompression, algo), { .u = 0 } }, + { MATROSKA_ID_ENCODINGCOMPSETTINGS, EBML_BIN, 0, offsetof(MatroskaTrackCompression, settings) }, { 0 } }; static EbmlSyntax matroska_track_encoding_encryption[] = { - { MATROSKA_ID_ENCODINGENCALGO, EBML_UINT, 0, offsetof(MatroskaTrackEncryption,algo), {.u=0} }, + { MATROSKA_ID_ENCODINGENCALGO, EBML_UINT, 0, offsetof(MatroskaTrackEncryption,algo), {.u = 0} }, { MATROSKA_ID_ENCODINGENCKEYID, EBML_BIN, 0, offsetof(MatroskaTrackEncryption,key_id) }, { MATROSKA_ID_ENCODINGENCAESSETTINGS, EBML_NONE }, { MATROSKA_ID_ENCODINGSIGALGO, EBML_NONE }, @@ -369,16 +377,16 @@ static EbmlSyntax matroska_track_encoding_encryption[] = { { 0 } }; static EbmlSyntax matroska_track_encoding[] = { - { MATROSKA_ID_ENCODINGSCOPE, EBML_UINT, 0, offsetof(MatroskaTrackEncoding,scope), {.u=1} }, - { MATROSKA_ID_ENCODINGTYPE, EBML_UINT, 0, offsetof(MatroskaTrackEncoding,type), {.u=0} }, - { MATROSKA_ID_ENCODINGCOMPRESSION,EBML_NEST, 0, offsetof(MatroskaTrackEncoding,compression), {.n=matroska_track_encoding_compression} }, - { MATROSKA_ID_ENCODINGENCRYPTION, EBML_NEST, 0, offsetof(MatroskaTrackEncoding,encryption), {.n=matroska_track_encoding_encryption} }, - { MATROSKA_ID_ENCODINGORDER, EBML_NONE }, + { MATROSKA_ID_ENCODINGSCOPE, EBML_UINT, 0, offsetof(MatroskaTrackEncoding, scope), { .u = 1 } }, + { MATROSKA_ID_ENCODINGTYPE, EBML_UINT, 0, offsetof(MatroskaTrackEncoding, type), { .u = 0 } }, + { MATROSKA_ID_ENCODINGCOMPRESSION, EBML_NEST, 0, offsetof(MatroskaTrackEncoding, compression), { .n = matroska_track_encoding_compression } }, + { MATROSKA_ID_ENCODINGENCRYPTION, EBML_NEST, 0, offsetof(MatroskaTrackEncoding, encryption), { .n = matroska_track_encoding_encryption } }, + { MATROSKA_ID_ENCODINGORDER, EBML_NONE }, { 0 } }; static EbmlSyntax matroska_track_encodings[] = { - { MATROSKA_ID_TRACKCONTENTENCODING, EBML_NEST, sizeof(MatroskaTrackEncoding), offsetof(MatroskaTrack,encodings), {.n=matroska_track_encoding} }, + { MATROSKA_ID_TRACKCONTENTENCODING, EBML_NEST, sizeof(MatroskaTrackEncoding), offsetof(MatroskaTrack, encodings), { .n = matroska_track_encoding } }, { 0 } }; @@ -389,75 +397,75 @@ static EbmlSyntax matroska_track_plane[] = { }; static EbmlSyntax matroska_track_combine_planes[] = { - { MATROSKA_ID_TRACKPLANE, EBML_NEST, sizeof(MatroskaTrackPlane), offsetof(MatroskaTrackOperation,combine_planes), {.n=matroska_track_plane} }, + { MATROSKA_ID_TRACKPLANE, EBML_NEST, sizeof(MatroskaTrackPlane), offsetof(MatroskaTrackOperation,combine_planes), {.n = matroska_track_plane} }, { 0 } }; static EbmlSyntax matroska_track_operation[] = { - { MATROSKA_ID_TRACKCOMBINEPLANES, EBML_NEST, 0, 0, {.n=matroska_track_combine_planes} }, + { MATROSKA_ID_TRACKCOMBINEPLANES, EBML_NEST, 0, 0, {.n = matroska_track_combine_planes} }, { 0 } }; static EbmlSyntax matroska_track[] = { - { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, offsetof(MatroskaTrack,num) }, - { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, offsetof(MatroskaTrack,name) }, - { MATROSKA_ID_TRACKUID, EBML_UINT, 0, offsetof(MatroskaTrack,uid) }, - { MATROSKA_ID_TRACKTYPE, EBML_UINT, 0, offsetof(MatroskaTrack,type) }, - { MATROSKA_ID_CODECID, EBML_STR, 0, offsetof(MatroskaTrack,codec_id) }, - { MATROSKA_ID_CODECPRIVATE, EBML_BIN, 0, offsetof(MatroskaTrack,codec_priv) }, - { MATROSKA_ID_CODECDELAY, EBML_UINT, 0, offsetof(MatroskaTrack,codec_delay) }, - { MATROSKA_ID_TRACKLANGUAGE, EBML_UTF8, 0, offsetof(MatroskaTrack,language), {.s="eng"} }, - { MATROSKA_ID_TRACKDEFAULTDURATION, EBML_UINT, 0, offsetof(MatroskaTrack,default_duration) }, - { MATROSKA_ID_TRACKTIMECODESCALE, EBML_FLOAT,0, offsetof(MatroskaTrack,time_scale), {.f=1.0} }, - { MATROSKA_ID_TRACKFLAGDEFAULT, EBML_UINT, 0, offsetof(MatroskaTrack,flag_default), {.u=1} }, - { MATROSKA_ID_TRACKFLAGFORCED, EBML_UINT, 0, offsetof(MatroskaTrack,flag_forced), {.u=0} }, - { MATROSKA_ID_TRACKVIDEO, EBML_NEST, 0, offsetof(MatroskaTrack,video), {.n=matroska_track_video} }, - { MATROSKA_ID_TRACKAUDIO, EBML_NEST, 0, offsetof(MatroskaTrack,audio), {.n=matroska_track_audio} }, - { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, offsetof(MatroskaTrack,operation), {.n=matroska_track_operation} }, - { MATROSKA_ID_TRACKCONTENTENCODINGS,EBML_NEST, 0, 0, {.n=matroska_track_encodings} }, - { MATROSKA_ID_TRACKMAXBLKADDID, EBML_UINT, 0, offsetof(MatroskaTrack,max_block_additional_id) }, - { MATROSKA_ID_SEEKPREROLL, EBML_UINT, 0, offsetof(MatroskaTrack,seek_preroll) }, - { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE }, - { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE }, - { MATROSKA_ID_CODECNAME, EBML_NONE }, - { MATROSKA_ID_CODECDECODEALL, EBML_NONE }, - { MATROSKA_ID_CODECINFOURL, EBML_NONE }, - { MATROSKA_ID_CODECDOWNLOADURL, EBML_NONE }, - { MATROSKA_ID_TRACKMINCACHE, EBML_NONE }, - { MATROSKA_ID_TRACKMAXCACHE, EBML_NONE }, + { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, offsetof(MatroskaTrack, num) }, + { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, offsetof(MatroskaTrack, name) }, + { MATROSKA_ID_TRACKUID, EBML_UINT, 0, offsetof(MatroskaTrack, uid) }, + { MATROSKA_ID_TRACKTYPE, EBML_UINT, 0, offsetof(MatroskaTrack, type) }, + { MATROSKA_ID_CODECID, EBML_STR, 0, offsetof(MatroskaTrack, codec_id) }, + { MATROSKA_ID_CODECPRIVATE, EBML_BIN, 0, offsetof(MatroskaTrack, codec_priv) }, + { MATROSKA_ID_CODECDELAY, EBML_UINT, 0, offsetof(MatroskaTrack, codec_delay) }, + { MATROSKA_ID_TRACKLANGUAGE, EBML_UTF8, 0, offsetof(MatroskaTrack, language), { .s = "eng" } }, + { MATROSKA_ID_TRACKDEFAULTDURATION, EBML_UINT, 0, offsetof(MatroskaTrack, default_duration) }, + { MATROSKA_ID_TRACKTIMECODESCALE, EBML_FLOAT, 0, offsetof(MatroskaTrack, time_scale), { .f = 1.0 } }, + { MATROSKA_ID_TRACKFLAGDEFAULT, EBML_UINT, 0, offsetof(MatroskaTrack, flag_default), { .u = 1 } }, + { MATROSKA_ID_TRACKFLAGFORCED, EBML_UINT, 0, offsetof(MatroskaTrack, flag_forced), { .u = 0 } }, + { MATROSKA_ID_TRACKVIDEO, EBML_NEST, 0, offsetof(MatroskaTrack, video), { .n = matroska_track_video } }, + { MATROSKA_ID_TRACKAUDIO, EBML_NEST, 0, offsetof(MatroskaTrack, audio), { .n = matroska_track_audio } }, + { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, offsetof(MatroskaTrack, operation), { .n = matroska_track_operation } }, + { MATROSKA_ID_TRACKCONTENTENCODINGS, EBML_NEST, 0, 0, { .n = matroska_track_encodings } }, + { MATROSKA_ID_TRACKMAXBLKADDID, EBML_UINT, 0, offsetof(MatroskaTrack, max_block_additional_id) }, + { MATROSKA_ID_SEEKPREROLL, EBML_UINT, 0, offsetof(MatroskaTrack, seek_preroll) }, + { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE }, + { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE }, + { MATROSKA_ID_CODECNAME, EBML_NONE }, + { MATROSKA_ID_CODECDECODEALL, EBML_NONE }, + { MATROSKA_ID_CODECINFOURL, EBML_NONE }, + { MATROSKA_ID_CODECDOWNLOADURL, EBML_NONE }, + { MATROSKA_ID_TRACKMINCACHE, EBML_NONE }, + { MATROSKA_ID_TRACKMAXCACHE, EBML_NONE }, { 0 } }; static EbmlSyntax matroska_tracks[] = { - { MATROSKA_ID_TRACKENTRY, EBML_NEST, sizeof(MatroskaTrack), offsetof(MatroskaDemuxContext,tracks), {.n=matroska_track} }, + { MATROSKA_ID_TRACKENTRY, EBML_NEST, sizeof(MatroskaTrack), offsetof(MatroskaDemuxContext, tracks), { .n = matroska_track } }, { 0 } }; static EbmlSyntax matroska_attachment[] = { - { MATROSKA_ID_FILEUID, EBML_UINT, 0, offsetof(MatroskaAttachement,uid) }, - { MATROSKA_ID_FILENAME, EBML_UTF8, 0, offsetof(MatroskaAttachement,filename) }, - { MATROSKA_ID_FILEMIMETYPE, EBML_STR, 0, offsetof(MatroskaAttachement,mime) }, - { MATROSKA_ID_FILEDATA, EBML_BIN, 0, offsetof(MatroskaAttachement,bin) }, - { MATROSKA_ID_FILEDESC, EBML_NONE }, + { MATROSKA_ID_FILEUID, EBML_UINT, 0, offsetof(MatroskaAttachment, uid) }, + { MATROSKA_ID_FILENAME, EBML_UTF8, 0, offsetof(MatroskaAttachment, filename) }, + { MATROSKA_ID_FILEMIMETYPE, EBML_STR, 0, offsetof(MatroskaAttachment, mime) }, + { MATROSKA_ID_FILEDATA, EBML_BIN, 0, offsetof(MatroskaAttachment, bin) }, + { MATROSKA_ID_FILEDESC, EBML_NONE }, { 0 } }; static EbmlSyntax matroska_attachments[] = { - { MATROSKA_ID_ATTACHEDFILE, EBML_NEST, sizeof(MatroskaAttachement), offsetof(MatroskaDemuxContext,attachments), {.n=matroska_attachment} }, + { MATROSKA_ID_ATTACHEDFILE, EBML_NEST, sizeof(MatroskaAttachment), offsetof(MatroskaDemuxContext, attachments), { .n = matroska_attachment } }, { 0 } }; static EbmlSyntax matroska_chapter_display[] = { - { MATROSKA_ID_CHAPSTRING, EBML_UTF8, 0, offsetof(MatroskaChapter,title) }, - { MATROSKA_ID_CHAPLANG, EBML_NONE }, + { MATROSKA_ID_CHAPSTRING, EBML_UTF8, 0, offsetof(MatroskaChapter, title) }, + { MATROSKA_ID_CHAPLANG, EBML_NONE }, { 0 } }; static EbmlSyntax matroska_chapter_entry[] = { - { MATROSKA_ID_CHAPTERTIMESTART, EBML_UINT, 0, offsetof(MatroskaChapter,start), {.u=AV_NOPTS_VALUE} }, - { MATROSKA_ID_CHAPTERTIMEEND, EBML_UINT, 0, offsetof(MatroskaChapter,end), {.u=AV_NOPTS_VALUE} }, - { MATROSKA_ID_CHAPTERUID, EBML_UINT, 0, offsetof(MatroskaChapter,uid) }, - { MATROSKA_ID_CHAPTERDISPLAY, EBML_NEST, 0, 0, {.n=matroska_chapter_display} }, + { MATROSKA_ID_CHAPTERTIMESTART, EBML_UINT, 0, offsetof(MatroskaChapter, start), { .u = AV_NOPTS_VALUE } }, + { MATROSKA_ID_CHAPTERTIMEEND, EBML_UINT, 0, offsetof(MatroskaChapter, end), { .u = AV_NOPTS_VALUE } }, + { MATROSKA_ID_CHAPTERUID, EBML_UINT, 0, offsetof(MatroskaChapter, uid) }, + { MATROSKA_ID_CHAPTERDISPLAY, EBML_NEST, 0, 0, { .n = matroska_chapter_display } }, { MATROSKA_ID_CHAPTERFLAGHIDDEN, EBML_NONE }, { MATROSKA_ID_CHAPTERFLAGENABLED, EBML_NONE }, { MATROSKA_ID_CHAPTERPHYSEQUIV, EBML_NONE }, @@ -466,7 +474,7 @@ static EbmlSyntax matroska_chapter_entry[] = { }; static EbmlSyntax matroska_chapter[] = { - { MATROSKA_ID_CHAPTERATOM, EBML_NEST, sizeof(MatroskaChapter), offsetof(MatroskaDemuxContext,chapters), {.n=matroska_chapter_entry} }, + { MATROSKA_ID_CHAPTERATOM, EBML_NEST, sizeof(MatroskaChapter), offsetof(MatroskaDemuxContext, chapters), { .n = matroska_chapter_entry } }, { MATROSKA_ID_EDITIONUID, EBML_NONE }, { MATROSKA_ID_EDITIONFLAGHIDDEN, EBML_NONE }, { MATROSKA_ID_EDITIONFLAGDEFAULT, EBML_NONE }, @@ -475,13 +483,13 @@ static EbmlSyntax matroska_chapter[] = { }; static EbmlSyntax matroska_chapters[] = { - { MATROSKA_ID_EDITIONENTRY, EBML_NEST, 0, 0, {.n=matroska_chapter} }, + { MATROSKA_ID_EDITIONENTRY, EBML_NEST, 0, 0, { .n = matroska_chapter } }, { 0 } }; static EbmlSyntax matroska_index_pos[] = { - { MATROSKA_ID_CUETRACK, EBML_UINT, 0, offsetof(MatroskaIndexPos,track) }, - { MATROSKA_ID_CUECLUSTERPOSITION, EBML_UINT, 0, offsetof(MatroskaIndexPos,pos) }, + { MATROSKA_ID_CUETRACK, EBML_UINT, 0, offsetof(MatroskaIndexPos, track) }, + { MATROSKA_ID_CUECLUSTERPOSITION, EBML_UINT, 0, offsetof(MatroskaIndexPos, pos) }, { MATROSKA_ID_CUERELATIVEPOSITION,EBML_NONE }, { MATROSKA_ID_CUEDURATION, EBML_NONE }, { MATROSKA_ID_CUEBLOCKNUMBER, EBML_NONE }, @@ -489,71 +497,71 @@ static EbmlSyntax matroska_index_pos[] = { }; static EbmlSyntax matroska_index_entry[] = { - { MATROSKA_ID_CUETIME, EBML_UINT, 0, offsetof(MatroskaIndex,time) }, - { MATROSKA_ID_CUETRACKPOSITION, EBML_NEST, sizeof(MatroskaIndexPos), offsetof(MatroskaIndex,pos), {.n=matroska_index_pos} }, + { MATROSKA_ID_CUETIME, EBML_UINT, 0, offsetof(MatroskaIndex, time) }, + { MATROSKA_ID_CUETRACKPOSITION, EBML_NEST, sizeof(MatroskaIndexPos), offsetof(MatroskaIndex, pos), { .n = matroska_index_pos } }, { 0 } }; static EbmlSyntax matroska_index[] = { - { MATROSKA_ID_POINTENTRY, EBML_NEST, sizeof(MatroskaIndex), offsetof(MatroskaDemuxContext,index), {.n=matroska_index_entry} }, + { MATROSKA_ID_POINTENTRY, EBML_NEST, sizeof(MatroskaIndex), offsetof(MatroskaDemuxContext, index), { .n = matroska_index_entry } }, { 0 } }; static EbmlSyntax matroska_simpletag[] = { - { MATROSKA_ID_TAGNAME, EBML_UTF8, 0, offsetof(MatroskaTag,name) }, - { MATROSKA_ID_TAGSTRING, EBML_UTF8, 0, offsetof(MatroskaTag,string) }, - { MATROSKA_ID_TAGLANG, EBML_STR, 0, offsetof(MatroskaTag,lang), {.s="und"} }, - { MATROSKA_ID_TAGDEFAULT, EBML_UINT, 0, offsetof(MatroskaTag,def) }, - { MATROSKA_ID_TAGDEFAULT_BUG, EBML_UINT, 0, offsetof(MatroskaTag,def) }, - { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTag,sub), {.n=matroska_simpletag} }, + { MATROSKA_ID_TAGNAME, EBML_UTF8, 0, offsetof(MatroskaTag, name) }, + { MATROSKA_ID_TAGSTRING, EBML_UTF8, 0, offsetof(MatroskaTag, string) }, + { MATROSKA_ID_TAGLANG, EBML_STR, 0, offsetof(MatroskaTag, lang), { .s = "und" } }, + { MATROSKA_ID_TAGDEFAULT, EBML_UINT, 0, offsetof(MatroskaTag, def) }, + { MATROSKA_ID_TAGDEFAULT_BUG, EBML_UINT, 0, offsetof(MatroskaTag, def) }, + { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTag, sub), { .n = matroska_simpletag } }, { 0 } }; static EbmlSyntax matroska_tagtargets[] = { - { MATROSKA_ID_TAGTARGETS_TYPE, EBML_STR, 0, offsetof(MatroskaTagTarget,type) }, - { MATROSKA_ID_TAGTARGETS_TYPEVALUE, EBML_UINT, 0, offsetof(MatroskaTagTarget,typevalue), {.u=50} }, - { MATROSKA_ID_TAGTARGETS_TRACKUID, EBML_UINT, 0, offsetof(MatroskaTagTarget,trackuid) }, - { MATROSKA_ID_TAGTARGETS_CHAPTERUID,EBML_UINT, 0, offsetof(MatroskaTagTarget,chapteruid) }, - { MATROSKA_ID_TAGTARGETS_ATTACHUID, EBML_UINT, 0, offsetof(MatroskaTagTarget,attachuid) }, + { MATROSKA_ID_TAGTARGETS_TYPE, EBML_STR, 0, offsetof(MatroskaTagTarget, type) }, + { MATROSKA_ID_TAGTARGETS_TYPEVALUE, EBML_UINT, 0, offsetof(MatroskaTagTarget, typevalue), { .u = 50 } }, + { MATROSKA_ID_TAGTARGETS_TRACKUID, EBML_UINT, 0, offsetof(MatroskaTagTarget, trackuid) }, + { MATROSKA_ID_TAGTARGETS_CHAPTERUID, EBML_UINT, 0, offsetof(MatroskaTagTarget, chapteruid) }, + { MATROSKA_ID_TAGTARGETS_ATTACHUID, EBML_UINT, 0, offsetof(MatroskaTagTarget, attachuid) }, { 0 } }; static EbmlSyntax matroska_tag[] = { - { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTags,tag), {.n=matroska_simpletag} }, - { MATROSKA_ID_TAGTARGETS, EBML_NEST, 0, offsetof(MatroskaTags,target), {.n=matroska_tagtargets} }, + { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTags, tag), { .n = matroska_simpletag } }, + { MATROSKA_ID_TAGTARGETS, EBML_NEST, 0, offsetof(MatroskaTags, target), { .n = matroska_tagtargets } }, { 0 } }; static EbmlSyntax matroska_tags[] = { - { MATROSKA_ID_TAG, EBML_NEST, sizeof(MatroskaTags), offsetof(MatroskaDemuxContext,tags), {.n=matroska_tag} }, + { MATROSKA_ID_TAG, EBML_NEST, sizeof(MatroskaTags), offsetof(MatroskaDemuxContext, tags), { .n = matroska_tag } }, { 0 } }; static EbmlSyntax matroska_seekhead_entry[] = { - { MATROSKA_ID_SEEKID, EBML_UINT, 0, offsetof(MatroskaSeekhead,id) }, - { MATROSKA_ID_SEEKPOSITION, EBML_UINT, 0, offsetof(MatroskaSeekhead,pos), {.u=-1} }, + { MATROSKA_ID_SEEKID, EBML_UINT, 0, offsetof(MatroskaSeekhead, id) }, + { MATROSKA_ID_SEEKPOSITION, EBML_UINT, 0, offsetof(MatroskaSeekhead, pos), { .u = -1 } }, { 0 } }; static EbmlSyntax matroska_seekhead[] = { - { MATROSKA_ID_SEEKENTRY, EBML_NEST, sizeof(MatroskaSeekhead), offsetof(MatroskaDemuxContext,seekhead), {.n=matroska_seekhead_entry} }, + { MATROSKA_ID_SEEKENTRY, EBML_NEST, sizeof(MatroskaSeekhead), offsetof(MatroskaDemuxContext, seekhead), { .n = matroska_seekhead_entry } }, { 0 } }; static EbmlSyntax matroska_segment[] = { - { MATROSKA_ID_INFO, EBML_NEST, 0, 0, {.n=matroska_info } }, - { MATROSKA_ID_TRACKS, EBML_NEST, 0, 0, {.n=matroska_tracks } }, - { MATROSKA_ID_ATTACHMENTS, EBML_NEST, 0, 0, {.n=matroska_attachments} }, - { MATROSKA_ID_CHAPTERS, EBML_NEST, 0, 0, {.n=matroska_chapters } }, - { MATROSKA_ID_CUES, EBML_NEST, 0, 0, {.n=matroska_index } }, - { MATROSKA_ID_TAGS, EBML_NEST, 0, 0, {.n=matroska_tags } }, - { MATROSKA_ID_SEEKHEAD, EBML_NEST, 0, 0, {.n=matroska_seekhead } }, - { MATROSKA_ID_CLUSTER, EBML_STOP }, + { MATROSKA_ID_INFO, EBML_NEST, 0, 0, { .n = matroska_info } }, + { MATROSKA_ID_TRACKS, EBML_NEST, 0, 0, { .n = matroska_tracks } }, + { MATROSKA_ID_ATTACHMENTS, EBML_NEST, 0, 0, { .n = matroska_attachments } }, + { MATROSKA_ID_CHAPTERS, EBML_NEST, 0, 0, { .n = matroska_chapters } }, + { MATROSKA_ID_CUES, EBML_NEST, 0, 0, { .n = matroska_index } }, + { MATROSKA_ID_TAGS, EBML_NEST, 0, 0, { .n = matroska_tags } }, + { MATROSKA_ID_SEEKHEAD, EBML_NEST, 0, 0, { .n = matroska_seekhead } }, + { MATROSKA_ID_CLUSTER, EBML_STOP }, { 0 } }; static EbmlSyntax matroska_segments[] = { - { MATROSKA_ID_SEGMENT, EBML_NEST, 0, 0, {.n=matroska_segment } }, + { MATROSKA_ID_SEGMENT, EBML_NEST, 0, 0, { .n = matroska_segment } }, { 0 } }; @@ -564,69 +572,69 @@ static EbmlSyntax matroska_blockmore[] = { }; static EbmlSyntax matroska_blockadditions[] = { - { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, 0, {.n=matroska_blockmore} }, + { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, 0, {.n = matroska_blockmore} }, { 0 } }; static EbmlSyntax matroska_blockgroup[] = { - { MATROSKA_ID_BLOCK, EBML_BIN, 0, offsetof(MatroskaBlock,bin) }, - { MATROSKA_ID_BLOCKADDITIONS, EBML_NEST, 0, 0, {.n=matroska_blockadditions} }, - { MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, offsetof(MatroskaBlock,bin) }, - { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, offsetof(MatroskaBlock,duration) }, - { MATROSKA_ID_DISCARDPADDING, EBML_SINT, 0, offsetof(MatroskaBlock,discard_padding) }, - { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 0, offsetof(MatroskaBlock,reference) }, + { MATROSKA_ID_BLOCK, EBML_BIN, 0, offsetof(MatroskaBlock, bin) }, + { MATROSKA_ID_BLOCKADDITIONS, EBML_NEST, 0, 0, { .n = matroska_blockadditions} }, + { MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, offsetof(MatroskaBlock, bin) }, + { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, offsetof(MatroskaBlock, duration) }, + { MATROSKA_ID_DISCARDPADDING, EBML_SINT, 0, offsetof(MatroskaBlock, discard_padding) }, + { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 0, offsetof(MatroskaBlock, reference) }, { MATROSKA_ID_CODECSTATE, EBML_NONE }, - { 1, EBML_UINT, 0, offsetof(MatroskaBlock,non_simple), {.u=1} }, + { 1, EBML_UINT, 0, offsetof(MatroskaBlock, non_simple), { .u = 1 } }, { 0 } }; static EbmlSyntax matroska_cluster[] = { - { MATROSKA_ID_CLUSTERTIMECODE,EBML_UINT,0, offsetof(MatroskaCluster,timecode) }, - { MATROSKA_ID_BLOCKGROUP, EBML_NEST, sizeof(MatroskaBlock), offsetof(MatroskaCluster,blocks), {.n=matroska_blockgroup} }, - { MATROSKA_ID_SIMPLEBLOCK, EBML_PASS, sizeof(MatroskaBlock), offsetof(MatroskaCluster,blocks), {.n=matroska_blockgroup} }, - { MATROSKA_ID_CLUSTERPOSITION,EBML_NONE }, - { MATROSKA_ID_CLUSTERPREVSIZE,EBML_NONE }, + { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, offsetof(MatroskaCluster, timecode) }, + { MATROSKA_ID_BLOCKGROUP, EBML_NEST, sizeof(MatroskaBlock), offsetof(MatroskaCluster, blocks), { .n = matroska_blockgroup } }, + { MATROSKA_ID_SIMPLEBLOCK, EBML_PASS, sizeof(MatroskaBlock), offsetof(MatroskaCluster, blocks), { .n = matroska_blockgroup } }, + { MATROSKA_ID_CLUSTERPOSITION, EBML_NONE }, + { MATROSKA_ID_CLUSTERPREVSIZE, EBML_NONE }, { 0 } }; static EbmlSyntax matroska_clusters[] = { - { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, {.n=matroska_cluster} }, - { MATROSKA_ID_INFO, EBML_NONE }, - { MATROSKA_ID_CUES, EBML_NONE }, - { MATROSKA_ID_TAGS, EBML_NONE }, - { MATROSKA_ID_SEEKHEAD, EBML_NONE }, + { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, { .n = matroska_cluster } }, + { MATROSKA_ID_INFO, EBML_NONE }, + { MATROSKA_ID_CUES, EBML_NONE }, + { MATROSKA_ID_TAGS, EBML_NONE }, + { MATROSKA_ID_SEEKHEAD, EBML_NONE }, { 0 } }; static EbmlSyntax matroska_cluster_incremental_parsing[] = { - { MATROSKA_ID_CLUSTERTIMECODE,EBML_UINT,0, offsetof(MatroskaCluster,timecode) }, - { MATROSKA_ID_BLOCKGROUP, EBML_NEST, sizeof(MatroskaBlock), offsetof(MatroskaCluster,blocks), {.n=matroska_blockgroup} }, - { MATROSKA_ID_SIMPLEBLOCK, EBML_PASS, sizeof(MatroskaBlock), offsetof(MatroskaCluster,blocks), {.n=matroska_blockgroup} }, - { MATROSKA_ID_CLUSTERPOSITION,EBML_NONE }, - { MATROSKA_ID_CLUSTERPREVSIZE,EBML_NONE }, - { MATROSKA_ID_INFO, EBML_NONE }, - { MATROSKA_ID_CUES, EBML_NONE }, - { MATROSKA_ID_TAGS, EBML_NONE }, - { MATROSKA_ID_SEEKHEAD, EBML_NONE }, - { MATROSKA_ID_CLUSTER, EBML_STOP }, + { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, offsetof(MatroskaCluster, timecode) }, + { MATROSKA_ID_BLOCKGROUP, EBML_NEST, sizeof(MatroskaBlock), offsetof(MatroskaCluster, blocks), { .n = matroska_blockgroup } }, + { MATROSKA_ID_SIMPLEBLOCK, EBML_PASS, sizeof(MatroskaBlock), offsetof(MatroskaCluster, blocks), { .n = matroska_blockgroup } }, + { MATROSKA_ID_CLUSTERPOSITION, EBML_NONE }, + { MATROSKA_ID_CLUSTERPREVSIZE, EBML_NONE }, + { MATROSKA_ID_INFO, EBML_NONE }, + { MATROSKA_ID_CUES, EBML_NONE }, + { MATROSKA_ID_TAGS, EBML_NONE }, + { MATROSKA_ID_SEEKHEAD, EBML_NONE }, + { MATROSKA_ID_CLUSTER, EBML_STOP }, { 0 } }; static EbmlSyntax matroska_cluster_incremental[] = { - { MATROSKA_ID_CLUSTERTIMECODE,EBML_UINT,0, offsetof(MatroskaCluster,timecode) }, - { MATROSKA_ID_BLOCKGROUP, EBML_STOP }, - { MATROSKA_ID_SIMPLEBLOCK, EBML_STOP }, - { MATROSKA_ID_CLUSTERPOSITION,EBML_NONE }, - { MATROSKA_ID_CLUSTERPREVSIZE,EBML_NONE }, + { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, offsetof(MatroskaCluster, timecode) }, + { MATROSKA_ID_BLOCKGROUP, EBML_STOP }, + { MATROSKA_ID_SIMPLEBLOCK, EBML_STOP }, + { MATROSKA_ID_CLUSTERPOSITION, EBML_NONE }, + { MATROSKA_ID_CLUSTERPREVSIZE, EBML_NONE }, { 0 } }; static EbmlSyntax matroska_clusters_incremental[] = { - { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, {.n=matroska_cluster_incremental} }, - { MATROSKA_ID_INFO, EBML_NONE }, - { MATROSKA_ID_CUES, EBML_NONE }, - { MATROSKA_ID_TAGS, EBML_NONE }, - { MATROSKA_ID_SEEKHEAD, EBML_NONE }, + { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, { .n = matroska_cluster_incremental } }, + { MATROSKA_ID_INFO, EBML_NONE }, + { MATROSKA_ID_CUES, EBML_NONE }, + { MATROSKA_ID_TAGS, EBML_NONE }, + { MATROSKA_ID_SEEKHEAD, EBML_NONE }, { 0 } }; @@ -651,11 +659,12 @@ static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos) id == MATROSKA_ID_CUES || id == MATROSKA_ID_TAGS || id == MATROSKA_ID_SEEKHEAD || id == MATROSKA_ID_ATTACHMENTS || id == MATROSKA_ID_CLUSTER || id == MATROSKA_ID_CHAPTERS) { - matroska->current_id = id; - return 0; + matroska->current_id = id; + return 0; } id = (id << 8) | avio_r8(pb); } + eof: matroska->done = 1; return AVERROR_EOF; @@ -791,13 +800,13 @@ static int ebml_read_sint(AVIOContext *pb, int size, int64_t *num) */ static int ebml_read_float(AVIOContext *pb, int size, double *num) { - if (size == 0) { + if (size == 0) *num = 0; - } else if (size == 4) { + else if (size == 4) *num = av_int2float(avio_rb32(pb)); - } else if (size == 8){ + else if (size == 8) *num = av_int2double(avio_rb64(pb)); - } else + else return AVERROR_INVALIDDATA; return 0; @@ -863,8 +872,8 @@ static int ebml_read_master(MatroskaDemuxContext *matroska, uint64_t length) return AVERROR(ENOSYS); } - level = &matroska->levels[matroska->num_levels++]; - level->start = avio_tell(pb); + level = &matroska->levels[matroska->num_levels++]; + level->start = avio_tell(pb); level->length = length; return 0; @@ -896,7 +905,7 @@ static int matroska_ebmlnum_sint(MatroskaDemuxContext *matroska, return res; /* make signed (weird way) */ - *num = unum - ((1LL << (7*res - 1)) - 1); + *num = unum - ((1LL << (7 * res - 1)) - 1); return res; } @@ -908,15 +917,15 @@ static int ebml_parse_id(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, uint32_t id, void *data) { int i; - for (i=0; syntax[i].id; i++) + for (i = 0; syntax[i].id; i++) if (id == syntax[i].id) break; if (!syntax[i].id && id == MATROSKA_ID_CLUSTER && - matroska->num_levels > 0 && - matroska->levels[matroska->num_levels-1].length == 0xffffffffffffff) + matroska->num_levels > 0 && + matroska->levels[matroska->num_levels - 1].length == 0xffffffffffffff) return 0; // we reached the end of an unknown size cluster if (!syntax[i].id && id != EBML_ID_VOID && id != EBML_ID_CRC32) { - av_log(matroska->ctx, AV_LOG_INFO, "Unknown entry 0x%X\n", id); + av_log(matroska->ctx, AV_LOG_INFO, "Unknown entry 0x%"PRIX32"\n", id); if (matroska->ctx->error_recognition & AV_EF_EXPLODE) return AVERROR_INVALIDDATA; } @@ -931,7 +940,7 @@ static int ebml_parse(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, int res = ebml_read_num(matroska, matroska->ctx->pb, 4, &id); if (res < 0) return res; - matroska->current_id = id | 1 << 7*res; + matroska->current_id = id | 1 << 7 * res; } return ebml_parse_id(matroska, syntax, matroska->current_id, data); } @@ -941,19 +950,19 @@ static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, { int i, res = 0; - for (i=0; syntax[i].id; i++) + for (i = 0; syntax[i].id; i++) switch (syntax[i].type) { case EBML_UINT: - *(uint64_t *)((char *)data+syntax[i].data_offset) = syntax[i].def.u; + *(uint64_t *) ((char *) data + syntax[i].data_offset) = syntax[i].def.u; break; case EBML_FLOAT: - *(double *)((char *)data+syntax[i].data_offset) = syntax[i].def.f; + *(double *) ((char *) data + syntax[i].data_offset) = syntax[i].def.f; break; case EBML_STR: case EBML_UTF8: // the default may be NULL if (syntax[i].def.s) { - uint8_t **dst = (uint8_t**)((uint8_t*)data + syntax[i].data_offset); + uint8_t **dst = (uint8_t **) ((uint8_t *) data + syntax[i].data_offset); *dst = av_strdup(syntax[i].def.s); if (!*dst) return AVERROR(ENOMEM); @@ -986,14 +995,14 @@ static int ebml_parse_elem(MatroskaDemuxContext *matroska, int res; void *newelem; - data = (char *)data + syntax->data_offset; + data = (char *) data + syntax->data_offset; if (syntax->list_elem_size) { EbmlList *list = data; - newelem = av_realloc_array(list->elem, list->nb_elem+1, syntax->list_elem_size); + newelem = av_realloc_array(list->elem, list->nb_elem + 1, syntax->list_elem_size); if (!newelem) return AVERROR(ENOMEM); list->elem = newelem; - data = (char*)list->elem + list->nb_elem*syntax->list_elem_size; + data = (char *) list->elem + list->nb_elem * syntax->list_elem_size; memset(data, 0, syntax->list_elem_size); list->nb_elem++; } @@ -1011,23 +1020,36 @@ static int ebml_parse_elem(MatroskaDemuxContext *matroska, } switch (syntax->type) { - case EBML_UINT: res = ebml_read_uint (pb, length, data); break; - case EBML_SINT: res = ebml_read_sint (pb, length, data); break; - case EBML_FLOAT: res = ebml_read_float (pb, length, data); break; + case EBML_UINT: + res = ebml_read_uint(pb, length, data); + break; + case EBML_SINT: + res = ebml_read_sint(pb, length, data); + break; + case EBML_FLOAT: + res = ebml_read_float(pb, length, data); + break; case EBML_STR: - case EBML_UTF8: res = ebml_read_ascii (pb, length, data); break; - case EBML_BIN: res = ebml_read_binary(pb, length, data); break; - case EBML_NEST: if ((res=ebml_read_master(matroska, length)) < 0) - return res; - if (id == MATROSKA_ID_SEGMENT) - matroska->segment_start = avio_tell(matroska->ctx->pb); - return ebml_parse_nest(matroska, syntax->def.n, data); - case EBML_PASS: return ebml_parse_id(matroska, syntax->def.n, id, data); - case EBML_STOP: return 1; + case EBML_UTF8: + res = ebml_read_ascii(pb, length, data); + break; + case EBML_BIN: + res = ebml_read_binary(pb, length, data); + break; + case EBML_NEST: + if ((res = ebml_read_master(matroska, length)) < 0) + return res; + if (id == MATROSKA_ID_SEGMENT) + matroska->segment_start = avio_tell(matroska->ctx->pb); + return ebml_parse_nest(matroska, syntax->def.n, data); + case EBML_PASS: + return ebml_parse_id(matroska, syntax->def.n, id, data); + case EBML_STOP: + return 1; default: - if(ffio_limit(pb, length) != length) + if (ffio_limit(pb, length) != length) return AVERROR(EIO); - return avio_skip(pb,length)<0 ? AVERROR(EIO) : 0; + return avio_skip(pb, length) < 0 ? AVERROR(EIO) : 0; } if (res == AVERROR_INVALIDDATA) av_log(matroska->ctx, AV_LOG_ERROR, "Invalid element\n"); @@ -1039,27 +1061,32 @@ static int ebml_parse_elem(MatroskaDemuxContext *matroska, static void ebml_free(EbmlSyntax *syntax, void *data) { int i, j; - for (i=0; syntax[i].id; i++) { - void *data_off = (char *)data + syntax[i].data_offset; + for (i = 0; syntax[i].id; i++) { + void *data_off = (char *) data + syntax[i].data_offset; switch (syntax[i].type) { case EBML_STR: - case EBML_UTF8: av_freep(data_off); break; - case EBML_BIN: av_freep(&((EbmlBin *)data_off)->data); break; + case EBML_UTF8: + av_freep(data_off); + break; + case EBML_BIN: + av_freep(&((EbmlBin *) data_off)->data); + break; case EBML_NEST: if (syntax[i].list_elem_size) { EbmlList *list = data_off; char *ptr = list->elem; - for (j=0; jnb_elem; j++, ptr+=syntax[i].list_elem_size) + for (j = 0; j < list->nb_elem; + j++, ptr += syntax[i].list_elem_size) ebml_free(syntax[i].def.n, ptr); av_free(list->elem); } else ebml_free(syntax[i].def.n, data_off); - default: break; + default: + break; } } } - /* * Autodetecting... */ @@ -1079,14 +1106,14 @@ static int matroska_probe(AVProbeData *p) len_mask >>= 1; } if (size > 8) - return 0; + return 0; total &= (len_mask - 1); while (n < size) total = (total << 8) | p->buf[4 + n++]; /* Does the probe data contain the whole header? */ if (p->buf_size < 4 + size + total) - return 0; + return 0; /* The header should contain a known document type. For now, * we don't parse the whole header but simply check for the @@ -1096,8 +1123,8 @@ static int matroska_probe(AVProbeData *p) int probelen = strlen(matroska_doctypes[i]); if (total < probelen) continue; - for (n = 4+size; n <= 4+size+total-probelen; n++) - if (!memcmp(p->buf+n, matroska_doctypes[i], probelen)) + for (n = 4 + size; n <= 4 + size + total - probelen; n++) + if (!memcmp(p->buf + n, matroska_doctypes[i], probelen)) return AVPROBE_SCORE_MAX; } @@ -1111,7 +1138,7 @@ static MatroskaTrack *matroska_find_track_by_num(MatroskaDemuxContext *matroska, MatroskaTrack *tracks = matroska->tracks.elem; int i; - for (i=0; i < matroska->tracks.nb_elem; i++) + for (i = 0; i < matroska->tracks.nb_elem; i++) if (tracks[i].num == num) return &tracks[i]; @@ -1119,13 +1146,13 @@ static MatroskaTrack *matroska_find_track_by_num(MatroskaDemuxContext *matroska, return NULL; } -static int matroska_decode_buffer(uint8_t** buf, int* buf_size, +static int matroska_decode_buffer(uint8_t **buf, int *buf_size, MatroskaTrack *track) { MatroskaTrackEncoding *encodings = track->encodings.elem; - uint8_t* data = *buf; + uint8_t *data = *buf; int isize = *buf_size; - uint8_t* pkt_data = NULL; + uint8_t *pkt_data = NULL; uint8_t av_unused *newpktdata; int pkt_size = isize; int result = 0; @@ -1135,7 +1162,8 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size, return AVERROR_INVALIDDATA; switch (encodings[0].compression.algo) { - case MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP: { + case MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP: + { int header_size = encodings[0].compression.settings.size; uint8_t *header = encodings[0].compression.settings.data; @@ -1159,15 +1187,15 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size, #if CONFIG_LZO case MATROSKA_TRACK_ENCODING_COMP_LZO: do { - olen = pkt_size *= 3; + olen = pkt_size *= 3; newpktdata = av_realloc(pkt_data, pkt_size + AV_LZO_OUTPUT_PADDING); if (!newpktdata) { result = AVERROR(ENOMEM); goto failed; } pkt_data = newpktdata; - result = av_lzo1x_decode(pkt_data, &olen, data, &isize); - } while (result==AV_LZO_OUTPUT_FULL && pkt_size<10000000); + result = av_lzo1x_decode(pkt_data, &olen, data, &isize); + } while (result == AV_LZO_OUTPUT_FULL && pkt_size < 10000000); if (result) { result = AVERROR_INVALIDDATA; goto failed; @@ -1176,27 +1204,28 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size, break; #endif #if CONFIG_ZLIB - case MATROSKA_TRACK_ENCODING_COMP_ZLIB: { - z_stream zstream = {0}; + case MATROSKA_TRACK_ENCODING_COMP_ZLIB: + { + z_stream zstream = { 0 }; if (inflateInit(&zstream) != Z_OK) return -1; - zstream.next_in = data; + zstream.next_in = data; zstream.avail_in = isize; do { - pkt_size *= 3; + pkt_size *= 3; newpktdata = av_realloc(pkt_data, pkt_size); if (!newpktdata) { inflateEnd(&zstream); goto failed; } - pkt_data = newpktdata; + pkt_data = newpktdata; zstream.avail_out = pkt_size - zstream.total_out; - zstream.next_out = pkt_data + zstream.total_out; + zstream.next_out = pkt_data + zstream.total_out; if (pkt_data) { result = inflate(&zstream, Z_NO_FLUSH); } else result = Z_MEM_ERROR; - } while (result==Z_OK && pkt_size<10000000); + } while (result == Z_OK && pkt_size < 10000000); pkt_size = zstream.total_out; inflateEnd(&zstream); if (result != Z_STREAM_END) { @@ -1210,27 +1239,28 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size, } #endif #if CONFIG_BZLIB - case MATROSKA_TRACK_ENCODING_COMP_BZLIB: { - bz_stream bzstream = {0}; + case MATROSKA_TRACK_ENCODING_COMP_BZLIB: + { + bz_stream bzstream = { 0 }; if (BZ2_bzDecompressInit(&bzstream, 0, 0) != BZ_OK) return -1; - bzstream.next_in = data; + bzstream.next_in = data; bzstream.avail_in = isize; do { - pkt_size *= 3; + pkt_size *= 3; newpktdata = av_realloc(pkt_data, pkt_size); if (!newpktdata) { BZ2_bzDecompressEnd(&bzstream); goto failed; } - pkt_data = newpktdata; + pkt_data = newpktdata; bzstream.avail_out = pkt_size - bzstream.total_out_lo32; - bzstream.next_out = pkt_data + bzstream.total_out_lo32; + bzstream.next_out = pkt_data + bzstream.total_out_lo32; if (pkt_data) { result = BZ2_bzDecompress(&bzstream); } else result = BZ_MEM_ERROR; - } while (result==BZ_OK && pkt_size<10000000); + } while (result == BZ_OK && pkt_size < 10000000); pkt_size = bzstream.total_out_lo32; BZ2_bzDecompressEnd(&bzstream); if (result != BZ_STREAM_END) { @@ -1247,10 +1277,11 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size, return AVERROR_INVALIDDATA; } - *buf = pkt_data; + *buf = pkt_data; *buf_size = pkt_size; return 0; - failed: + +failed: av_free(pkt_data); return result; } @@ -1260,28 +1291,38 @@ static void matroska_fix_ass_packet(MatroskaDemuxContext *matroska, AVPacket *pkt, uint64_t display_duration) { AVBufferRef *line; - char *layer, *ptr = pkt->data, *end = ptr+pkt->size; - for (; *ptr!=',' && ptrdata, *end = ptr + pkt->size; + + for (; *ptr != ',' && ptr < end - 1; ptr++) + ; if (*ptr == ',') ptr++; layer = ptr; - for (; *ptr!=',' && ptrpts + display_duration; int sc = matroska->time_scale * pkt->pts / 10000000; int ec = matroska->time_scale * end_pts / 10000000; int sh, sm, ss, eh, em, es, len; - sh = sc/360000; sc -= 360000*sh; - sm = sc/ 6000; sc -= 6000*sm; - ss = sc/ 100; sc -= 100*ss; - eh = ec/360000; ec -= 360000*eh; - em = ec/ 6000; ec -= 6000*em; - es = ec/ 100; ec -= 100*es; + sh = sc / 360000; + sc -= 360000 * sh; + sm = sc / 6000; + sc -= 6000 * sm; + ss = sc / 100; + sc -= 100 * ss; + eh = ec / 360000; + ec -= 360000 * eh; + em = ec / 6000; + ec -= 6000 * em; + es = ec / 100; + ec -= 100 * es; *ptr++ = '\0'; - len = 50 + end-ptr + FF_INPUT_BUFFER_PADDING_SIZE; + len = 50 + end - ptr + FF_INPUT_BUFFER_PADDING_SIZE; if (!(line = av_buffer_alloc(len))) return; - snprintf(line->data, len,"Dialogue: %s,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s\r\n", + snprintf(line->data, len, + "Dialogue: %s,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s\r\n", layer, sh, sm, ss, sc, eh, em, es, ec, ptr); av_buffer_unref(&pkt->buf); pkt->buf = line; @@ -1311,20 +1352,22 @@ static void matroska_convert_tag(AVFormatContext *s, EbmlList *list, char key[1024]; int i; - for (i=0; i < list->nb_elem; i++) { - const char *lang = tags[i].lang && strcmp(tags[i].lang, "und") ? - tags[i].lang : NULL; + for (i = 0; i < list->nb_elem; i++) { + const char *lang = tags[i].lang && + strcmp(tags[i].lang, "und") ? tags[i].lang : NULL; if (!tags[i].name) { av_log(s, AV_LOG_WARNING, "Skipping invalid tag with no TagName.\n"); continue; } - if (prefix) snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name); - else av_strlcpy(key, tags[i].name, sizeof(key)); + if (prefix) + snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name); + else + av_strlcpy(key, tags[i].name, sizeof(key)); if (tags[i].def || !lang) { - av_dict_set(metadata, key, tags[i].string, 0); - if (tags[i].sub.nb_elem) - matroska_convert_tag(s, &tags[i].sub, metadata, key); + av_dict_set(metadata, key, tags[i].string, 0); + if (tags[i].sub.nb_elem) + matroska_convert_tag(s, &tags[i].sub, metadata, key); } if (lang) { av_strlcat(key, "-", sizeof(key)); @@ -1343,24 +1386,24 @@ static void matroska_convert_tags(AVFormatContext *s) MatroskaTags *tags = matroska->tags.elem; int i, j; - for (i=0; i < matroska->tags.nb_elem; i++) { + for (i = 0; i < matroska->tags.nb_elem; i++) { if (tags[i].target.attachuid) { - MatroskaAttachement *attachment = matroska->attachments.elem; - for (j=0; jattachments.nb_elem; j++) - if (attachment[j].uid == tags[i].target.attachuid - && attachment[j].stream) + MatroskaAttachment *attachment = matroska->attachments.elem; + for (j = 0; j < matroska->attachments.nb_elem; j++) + if (attachment[j].uid == tags[i].target.attachuid && + attachment[j].stream) matroska_convert_tag(s, &tags[i].tag, &attachment[j].stream->metadata, NULL); } else if (tags[i].target.chapteruid) { MatroskaChapter *chapter = matroska->chapters.elem; - for (j=0; jchapters.nb_elem; j++) - if (chapter[j].uid == tags[i].target.chapteruid - && chapter[j].chapter) + for (j = 0; j < matroska->chapters.nb_elem; j++) + if (chapter[j].uid == tags[i].target.chapteruid && + chapter[j].chapter) matroska_convert_tag(s, &tags[i].tag, &chapter[j].chapter->metadata, NULL); } else if (tags[i].target.trackuid) { MatroskaTrack *track = matroska->tracks.elem; - for (j=0; jtracks.nb_elem; j++) + 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); @@ -1371,20 +1414,21 @@ static void matroska_convert_tags(AVFormatContext *s) } } -static int matroska_parse_seekhead_entry(MatroskaDemuxContext *matroska, int idx) +static int matroska_parse_seekhead_entry(MatroskaDemuxContext *matroska, + int idx) { EbmlList *seekhead_list = &matroska->seekhead; + uint32_t level_up = matroska->level_up; + uint32_t saved_id = matroska->current_id; MatroskaSeekhead *seekhead = seekhead_list->elem; - uint32_t level_up = matroska->level_up; int64_t before_pos = avio_tell(matroska->ctx->pb); - uint32_t saved_id = matroska->current_id; MatroskaLevel level; int64_t offset; int ret = 0; - if (idx >= seekhead_list->nb_elem - || seekhead[idx].id == MATROSKA_ID_SEEKHEAD - || seekhead[idx].id == MATROSKA_ID_CLUSTER) + if (idx >= seekhead_list->nb_elem || + seekhead[idx].id == MATROSKA_ID_SEEKHEAD || + seekhead[idx].id == MATROSKA_ID_CLUSTER) return 0; /* seek */ @@ -1398,25 +1442,25 @@ static int matroska_parse_seekhead_entry(MatroskaDemuxContext *matroska, int idx "cannot parse further.\n", EBML_MAX_DEPTH); ret = AVERROR_INVALIDDATA; } else { - level.start = 0; - level.length = (uint64_t)-1; + level.start = 0; + level.length = (uint64_t) -1; matroska->levels[matroska->num_levels] = level; matroska->num_levels++; - matroska->current_id = 0; + matroska->current_id = 0; ret = ebml_parse(matroska, matroska_segment, matroska); /* remove dummy level */ while (matroska->num_levels) { uint64_t length = matroska->levels[--matroska->num_levels].length; - if (length == (uint64_t)-1) + if (length == (uint64_t) -1) break; } } } /* seek back */ avio_seek(matroska->ctx->pb, before_pos, SEEK_SET); - matroska->level_up = level_up; + matroska->level_up = level_up; matroska->current_id = saved_id; return ret; @@ -1452,28 +1496,30 @@ static void matroska_execute_seekhead(MatroskaDemuxContext *matroska) } } -static void matroska_add_index_entries(MatroskaDemuxContext *matroska) { +static void matroska_add_index_entries(MatroskaDemuxContext *matroska) +{ EbmlList *index_list; MatroskaIndex *index; int index_scale = 1; int i, j; index_list = &matroska->index; - index = index_list->elem; - if (index_list->nb_elem - && index[0].time > 1E14/matroska->time_scale) { + index = index_list->elem; + if (index_list->nb_elem && + index[0].time > 1E14 / matroska->time_scale) { av_log(matroska->ctx, AV_LOG_WARNING, "Working around broken index.\n"); index_scale = matroska->time_scale; } for (i = 0; i < index_list->nb_elem; i++) { - EbmlList *pos_list = &index[i].pos; + EbmlList *pos_list = &index[i].pos; MatroskaIndexPos *pos = pos_list->elem; for (j = 0; j < pos_list->nb_elem; j++) { - MatroskaTrack *track = matroska_find_track_by_num(matroska, pos[j].track); + MatroskaTrack *track = matroska_find_track_by_num(matroska, + pos[j].track); if (track && track->stream) av_add_index_entry(track->stream, pos[j].pos + matroska->segment_start, - index[i].time/index_scale, 0, 0, + index[i].time / index_scale, 0, 0, AVINDEX_KEYFRAME); } } @@ -1496,10 +1542,10 @@ static void matroska_parse_cues(MatroskaDemuxContext *matroska) { static int matroska_aac_profile(char *codec_id) { - static const char * const aac_profiles[] = { "MAIN", "LC", "SSR" }; + static const char *const aac_profiles[] = { "MAIN", "LC", "SSR" }; int profile; - for (profile=0; profilestream; + uint8_t *p = track->codec_priv.data; + int size = track->codec_priv.size; + + if (size < 8 + FLAC_STREAMINFO_SIZE || p[4] & 0x7f) { + av_log(s, AV_LOG_WARNING, "Invalid FLAC private data\n"); + track->codec_priv.size = 0; + return 0; + } + *offset = 8; + track->codec_priv.size = 8 + FLAC_STREAMINFO_SIZE; + + p += track->codec_priv.size; + size -= track->codec_priv.size; + + /* parse the remaining metadata blocks if present */ + while (size >= 4) { + int block_last, block_type, block_size; + + flac_parse_block_header(p, &block_last, &block_type, &block_size); + + p += 4; + size -= 4; + if (block_size > size) + return 0; + + /* check for the channel mask */ + if (block_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) { + AVDictionary *dict = NULL; + AVDictionaryEntry *chmask; + + ff_vorbis_comment(s, &dict, p, block_size, 0); + chmask = av_dict_get(dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0); + if (chmask) { + uint64_t mask = strtol(chmask->value, NULL, 0); + if (!mask || mask & ~0x3ffffULL) { + av_log(s, AV_LOG_WARNING, + "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n"); + } else + st->codec->channel_layout = mask; + } + av_dict_free(&dict); + } + + p += block_size; + size -= block_size; + } + + return 0; +} + +static int matroska_parse_tracks(AVFormatContext *s) +{ + MatroskaDemuxContext *matroska = s->priv_data; + MatroskaTrack *tracks = matroska->tracks.elem; + AVStream *st; + int i, j, ret; + int k; + + for (i = 0; i < matroska->tracks.nb_elem; i++) { + MatroskaTrack *track = &tracks[i]; + enum AVCodecID codec_id = AV_CODEC_ID_NONE; + EbmlList *encodings_list = &track->encodings; + MatroskaTrackEncoding *encodings = encodings_list->elem; + uint8_t *extradata = NULL; + int extradata_size = 0; + int extradata_offset = 0; + uint32_t fourcc = 0; + AVIOContext b; + char* key_id_base64 = NULL; + int bit_depth = -1; + + /* Apply some sanity checks. */ + if (track->type != MATROSKA_TRACK_TYPE_VIDEO && + track->type != MATROSKA_TRACK_TYPE_AUDIO && + track->type != MATROSKA_TRACK_TYPE_SUBTITLE && + track->type != MATROSKA_TRACK_TYPE_METADATA) { + av_log(matroska->ctx, AV_LOG_INFO, + "Unknown or unsupported track type %"PRIu64"\n", + track->type); + continue; + } + if (track->codec_id == NULL) + continue; + + if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { + if (!track->default_duration && track->video.frame_rate > 0) + track->default_duration = 1000000000 / track->video.frame_rate; + if (track->video.display_width == -1) + track->video.display_width = track->video.pixel_width; + if (track->video.display_height == -1) + track->video.display_height = track->video.pixel_height; + if (track->video.color_space.size == 4) + fourcc = AV_RL32(track->video.color_space.data); + } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { + if (!track->audio.out_samplerate) + track->audio.out_samplerate = track->audio.samplerate; + } + if (encodings_list->nb_elem > 1) { + av_log(matroska->ctx, AV_LOG_ERROR, + "Multiple combined encodings not supported"); + } else if (encodings_list->nb_elem == 1) { + if (encodings[0].type) { + if (encodings[0].encryption.key_id.size > 0) { + /* Save the encryption key id to be stored later as a + metadata tag. */ + const int b64_size = AV_BASE64_SIZE(encodings[0].encryption.key_id.size); + key_id_base64 = av_malloc(b64_size); + if (key_id_base64 == NULL) + return AVERROR(ENOMEM); + + av_base64_encode(key_id_base64, b64_size, + encodings[0].encryption.key_id.data, + encodings[0].encryption.key_id.size); + } else { + encodings[0].scope = 0; + av_log(matroska->ctx, AV_LOG_ERROR, + "Unsupported encoding type"); + } + } else if ( +#if CONFIG_ZLIB + encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_ZLIB && +#endif +#if CONFIG_BZLIB + encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_BZLIB && +#endif +#if CONFIG_LZO + encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO && +#endif + encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP) { + encodings[0].scope = 0; + av_log(matroska->ctx, AV_LOG_ERROR, + "Unsupported encoding type"); + } else if (track->codec_priv.size && encodings[0].scope & 2) { + uint8_t *codec_priv = track->codec_priv.data; + int ret = matroska_decode_buffer(&track->codec_priv.data, + &track->codec_priv.size, + track); + if (ret < 0) { + track->codec_priv.data = NULL; + track->codec_priv.size = 0; + av_log(matroska->ctx, AV_LOG_ERROR, + "Failed to decode codec private data\n"); + } + + if (codec_priv != track->codec_priv.data) + av_free(codec_priv); + } + } + + for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) { + if (!strncmp(ff_mkv_codec_tags[j].str, track->codec_id, + strlen(ff_mkv_codec_tags[j].str))) { + codec_id = ff_mkv_codec_tags[j].id; + break; + } + } + + st = track->stream = avformat_new_stream(s, NULL); + if (st == NULL) { + av_free(key_id_base64); + return AVERROR(ENOMEM); + } + + if (key_id_base64) { + /* export encryption key id as base64 metadata tag */ + av_dict_set(&st->metadata, "enc_key_id", key_id_base64, 0); + av_freep(&key_id_base64); + } + + if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") && + track->codec_priv.size >= 40 && + track->codec_priv.data != NULL) { + track->ms_compat = 1; + bit_depth = AV_RL16(track->codec_priv.data + 14); + fourcc = AV_RL32(track->codec_priv.data + 16); + codec_id = ff_codec_get_id(ff_codec_bmp_tags, + fourcc); + if (!codec_id) + codec_id = ff_codec_get_id(ff_codec_movvideo_tags, + fourcc); + extradata_offset = 40; + } else if (!strcmp(track->codec_id, "A_MS/ACM") && + track->codec_priv.size >= 14 && + track->codec_priv.data != NULL) { + int ret; + 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); + if (ret < 0) + return ret; + codec_id = st->codec->codec_id; + extradata_offset = FFMIN(track->codec_priv.size, 18); + } else if (!strcmp(track->codec_id, "A_QUICKTIME") + && (track->codec_priv.size >= 86) + && (track->codec_priv.data != NULL)) { + fourcc = AV_RL32(track->codec_priv.data + 4); + codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc); + if (ff_codec_get_id(ff_codec_movaudio_tags, AV_RL32(track->codec_priv.data))) { + fourcc = AV_RL32(track->codec_priv.data); + codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc); + } + } else if (!strcmp(track->codec_id, "V_QUICKTIME") && + (track->codec_priv.size >= 21) && + (track->codec_priv.data != NULL)) { + fourcc = AV_RL32(track->codec_priv.data + 4); + codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc); + if (ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(track->codec_priv.data))) { + fourcc = AV_RL32(track->codec_priv.data); + codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc); + } + if (codec_id == AV_CODEC_ID_NONE && AV_RL32(track->codec_priv.data+4) == AV_RL32("SMI ")) + codec_id = AV_CODEC_ID_SVQ3; + } else if (codec_id == AV_CODEC_ID_PCM_S16BE) { + switch (track->audio.bitdepth) { + case 8: + codec_id = AV_CODEC_ID_PCM_U8; + break; + case 24: + codec_id = AV_CODEC_ID_PCM_S24BE; + break; + case 32: + codec_id = AV_CODEC_ID_PCM_S32BE; + break; + } + } else if (codec_id == AV_CODEC_ID_PCM_S16LE) { + switch (track->audio.bitdepth) { + case 8: + codec_id = AV_CODEC_ID_PCM_U8; + break; + case 24: + codec_id = AV_CODEC_ID_PCM_S24LE; + break; + case 32: + codec_id = AV_CODEC_ID_PCM_S32LE; + break; + } + } else if (codec_id == AV_CODEC_ID_PCM_F32LE && + track->audio.bitdepth == 64) { + codec_id = AV_CODEC_ID_PCM_F64LE; + } 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); + if (extradata == NULL) + return AVERROR(ENOMEM); + extradata[0] = (profile << 3) | ((sri & 0x0E) >> 1); + extradata[1] = ((sri & 0x01) << 7) | (track->audio.channels << 3); + if (strstr(track->codec_id, "SBR")) { + sri = matroska_aac_sri(track->audio.out_samplerate); + extradata[2] = 0x56; + extradata[3] = 0xE5; + extradata[4] = 0x80 | (sri << 3); + extradata_size = 5; + } else + extradata_size = 2; + } else if (codec_id == AV_CODEC_ID_ALAC && track->codec_priv.size && track->codec_priv.size < INT_MAX - 12 - FF_INPUT_BUFFER_PADDING_SIZE) { + /* Only ALAC's magic cookie is stored in Matroska's track headers. + * Create the "atom size", "tag", and "tag version" fields the + * decoder expects manually. */ + extradata_size = 12 + track->codec_priv.size; + extradata = av_mallocz(extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + if (extradata == NULL) + return AVERROR(ENOMEM); + AV_WB32(extradata, extradata_size); + memcpy(&extradata[4], "alac", 4); + AV_WB32(&extradata[8], 0); + memcpy(&extradata[12], track->codec_priv.data, + track->codec_priv.size); + } else if (codec_id == AV_CODEC_ID_TTA) { + extradata_size = 30; + extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (extradata == NULL) + return AVERROR(ENOMEM); + ffio_init_context(&b, extradata, extradata_size, 1, + NULL, NULL, NULL, NULL); + avio_write(&b, "TTA1", 4); + avio_wl16(&b, 1); + avio_wl16(&b, track->audio.channels); + avio_wl16(&b, track->audio.bitdepth); + if (track->audio.out_samplerate < 0 || track->audio.out_samplerate > INT_MAX) + return AVERROR_INVALIDDATA; + avio_wl32(&b, track->audio.out_samplerate); + avio_wl32(&b, av_rescale((matroska->duration * matroska->time_scale), + track->audio.out_samplerate, + AV_TIME_BASE * 1000)); + } else if (codec_id == AV_CODEC_ID_RV10 || + codec_id == AV_CODEC_ID_RV20 || + codec_id == AV_CODEC_ID_RV30 || + codec_id == AV_CODEC_ID_RV40) { + extradata_offset = 26; + } else if (codec_id == AV_CODEC_ID_RA_144) { + track->audio.out_samplerate = 8000; + track->audio.channels = 1; + } else if ((codec_id == AV_CODEC_ID_RA_288 || + codec_id == AV_CODEC_ID_COOK || + codec_id == AV_CODEC_ID_ATRAC3 || + codec_id == AV_CODEC_ID_SIPR) + && track->codec_priv.data) { + int flavor; + + ffio_init_context(&b, track->codec_priv.data, + track->codec_priv.size, + 0, NULL, NULL, NULL, NULL); + avio_skip(&b, 22); + flavor = avio_rb16(&b); + track->audio.coded_framesize = avio_rb32(&b); + avio_skip(&b, 12); + track->audio.sub_packet_h = avio_rb16(&b); + track->audio.frame_size = avio_rb16(&b); + track->audio.sub_packet_size = avio_rb16(&b); + if (flavor < 0 || + track->audio.coded_framesize <= 0 || + track->audio.sub_packet_h <= 0 || + track->audio.frame_size <= 0 || + track->audio.sub_packet_size <= 0) + return AVERROR_INVALIDDATA; + track->audio.buf = av_malloc_array(track->audio.sub_packet_h, + track->audio.frame_size); + if (!track->audio.buf) + return AVERROR(ENOMEM); + if (codec_id == AV_CODEC_ID_RA_288) { + st->codec->block_align = track->audio.coded_framesize; + track->codec_priv.size = 0; + } else { + if (codec_id == AV_CODEC_ID_SIPR && flavor < 4) { + 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->codec->block_align = track->audio.sub_packet_size; + extradata_offset = 78; + } + } else if (codec_id == AV_CODEC_ID_FLAC && track->codec_priv.size) { + ret = matroska_parse_flac(s, track, &extradata_offset); + if (ret < 0) + return ret; + } else if (codec_id == AV_CODEC_ID_PRORES && track->codec_priv.size == 4) { + fourcc = AV_RL32(track->codec_priv.data); + } + track->codec_priv.size -= extradata_offset; + + if (codec_id == AV_CODEC_ID_NONE) + av_log(matroska->ctx, AV_LOG_INFO, + "Unknown/unsupported AVCodecID %s.\n", track->codec_id); + + if (track->time_scale < 0.01) + track->time_scale = 1.0; + avpriv_set_pts_info(st, 64, matroska->time_scale * track->time_scale, + 1000 * 1000 * 1000); /* 64 bit pts in ns */ + + /* 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; + + if (strcmp(track->language, "und")) + av_dict_set(&st->metadata, "language", track->language, 0); + av_dict_set(&st->metadata, "title", track->name, 0); + + if (track->flag_default) + st->disposition |= AV_DISPOSITION_DEFAULT; + if (track->flag_forced) + st->disposition |= AV_DISPOSITION_FORCED; + + if (!st->codec->extradata) { + if (extradata) { + st->codec->extradata = extradata; + st->codec->extradata_size = extradata_size; + } else if (track->codec_priv.data && track->codec_priv.size > 0) { + if (ff_alloc_extradata(st->codec, track->codec_priv.size)) + return AVERROR(ENOMEM); + memcpy(st->codec->extradata, + track->codec_priv.data + extradata_offset, + track->codec_priv.size); + } + } + + if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { + MatroskaTrackPlane *planes = track->operation.combine_planes.elem; + + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_tag = fourcc; + if (bit_depth >= 0) + st->codec->bits_per_coded_sample = bit_depth; + st->codec->width = track->video.pixel_width; + st->codec->height = track->video.pixel_height; + 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, + 255); + if (st->codec->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, + 1000000000, track->default_duration, 30000); +#if FF_API_R_FRAME_RATE + if (st->avg_frame_rate.num < st->avg_frame_rate.den * 1000L) + st->r_frame_rate = st->avg_frame_rate; +#endif + } + + /* export stereo mode flag as metadata tag */ + if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREO_MODE_COUNT) + av_dict_set(&st->metadata, "stereo_mode", ff_matroska_video_stereo_mode[track->video.stereo_mode], 0); + + /* export alpha mode flag as metadata tag */ + if (track->video.alpha_mode) + av_dict_set(&st->metadata, "alpha_mode", "1", 0); + + /* if we have virtual track, mark the real tracks */ + for (j=0; j < track->operation.combine_planes.nb_elem; j++) { + char buf[32]; + if (planes[j].type >= MATROSKA_VIDEO_STEREO_PLANE_COUNT) + continue; + snprintf(buf, sizeof(buf), "%s_%d", + ff_matroska_video_stereo_plane[planes[j].type], i); + for (k=0; k < matroska->tracks.nb_elem; k++) + if (planes[j].uid == tracks[k].uid) { + av_dict_set(&s->streams[k]->metadata, + "stereo_mode", buf, 0); + break; + } + } + } 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->bits_per_coded_sample) + st->codec->bits_per_coded_sample = track->audio.bitdepth; + if (st->codec->codec_id != AV_CODEC_ID_AAC) + st->need_parsing = AVSTREAM_PARSE_HEADERS; + if (track->codec_delay > 0) { + st->codec->delay = av_rescale_q(track->codec_delay, + st->time_base, + (AVRational){1, st->codec->sample_rate}); + } + if (track->seek_preroll > 0) { + av_codec_set_seek_preroll(st->codec, + av_rescale_q(track->seek_preroll, + (AVRational){1, 1000000000}, + (AVRational){1, st->codec->sample_rate})); + } + } else if (codec_id == AV_CODEC_ID_WEBVTT) { + st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; + + if (!strcmp(track->codec_id, "D_WEBVTT/CAPTIONS")) { + st->disposition |= AV_DISPOSITION_CAPTIONS; + } else if (!strcmp(track->codec_id, "D_WEBVTT/DESCRIPTIONS")) { + st->disposition |= AV_DISPOSITION_DESCRIPTIONS; + } else if (!strcmp(track->codec_id, "D_WEBVTT/METADATA")) { + st->disposition |= AV_DISPOSITION_METADATA; + } + } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) { + st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; +#if FF_API_ASS_SSA + if (st->codec->codec_id == AV_CODEC_ID_SSA || + st->codec->codec_id == AV_CODEC_ID_ASS) +#else + if (st->codec->codec_id == AV_CODEC_ID_ASS) +#endif + matroska->contains_ssa = 1; + } + } + + return 0; +} + static int matroska_read_header(AVFormatContext *s) { MatroskaDemuxContext *matroska = s->priv_data; - EbmlList *attachements_list = &matroska->attachments; - MatroskaAttachement *attachements; - EbmlList *chapters_list = &matroska->chapters; + EbmlList *attachments_list = &matroska->attachments; + EbmlList *chapters_list = &matroska->chapters; + MatroskaAttachment *attachments; MatroskaChapter *chapters; - MatroskaTrack *tracks; uint64_t max_start = 0; int64_t pos; Ebml ebml = { 0 }; - AVStream *st; - int i, j, k, res; + int i, j, res; matroska->ctx = s; /* First read the EBML header. */ - if (ebml_parse(matroska, ebml_syntax, &ebml) - || ebml.version > EBML_VERSION || ebml.max_size > sizeof(uint64_t) - || ebml.id_length > sizeof(uint32_t) || ebml.doctype_version > 3 || !ebml.doctype) { + if (ebml_parse(matroska, ebml_syntax, &ebml) || + ebml.version > EBML_VERSION || + ebml.max_size > sizeof(uint64_t) || + ebml.id_length > sizeof(uint32_t) || + ebml.doctype_version > 3 || + !ebml.doctype) { av_log(matroska->ctx, AV_LOG_ERROR, "EBML header using unsupported features\n" "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n", @@ -1586,429 +2111,58 @@ static int matroska_read_header(AVFormatContext *s) if (!matroska->time_scale) matroska->time_scale = 1000000; if (matroska->duration) - matroska->ctx->duration = matroska->duration * matroska->time_scale - * 1000 / AV_TIME_BASE; + matroska->ctx->duration = matroska->duration * matroska->time_scale * + 1000 / AV_TIME_BASE; av_dict_set(&s->metadata, "title", matroska->title, 0); av_dict_set(&s->metadata, "encoder", matroska->muxingapp, 0); if (matroska->date_utc.size == 8) matroska_metadata_creation_time(&s->metadata, AV_RB64(matroska->date_utc.data)); - tracks = matroska->tracks.elem; - for (i=0; i < matroska->tracks.nb_elem; i++) { - MatroskaTrack *track = &tracks[i]; - enum AVCodecID codec_id = AV_CODEC_ID_NONE; - EbmlList *encodings_list = &track->encodings; - MatroskaTrackEncoding *encodings = encodings_list->elem; - uint8_t *extradata = NULL; - int extradata_size = 0; - int extradata_offset = 0; - uint32_t fourcc = 0; - AVIOContext b; - char* key_id_base64 = NULL; - int bit_depth = -1; + res = matroska_parse_tracks(s); + if (res < 0) + return res; - /* Apply some sanity checks. */ - if (track->type != MATROSKA_TRACK_TYPE_VIDEO && - track->type != MATROSKA_TRACK_TYPE_AUDIO && - track->type != MATROSKA_TRACK_TYPE_SUBTITLE && - track->type != MATROSKA_TRACK_TYPE_METADATA) { - av_log(matroska->ctx, AV_LOG_INFO, - "Unknown or unsupported track type %"PRIu64"\n", - track->type); - continue; - } - if (track->codec_id == NULL) - continue; - - if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { - if (!track->default_duration && track->video.frame_rate > 0) - track->default_duration = 1000000000/track->video.frame_rate; - if (track->video.display_width == -1) - track->video.display_width = track->video.pixel_width; - if (track->video.display_height == -1) - track->video.display_height = track->video.pixel_height; - if (track->video.color_space.size == 4) - fourcc = AV_RL32(track->video.color_space.data); - } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { - if (!track->audio.out_samplerate) - track->audio.out_samplerate = track->audio.samplerate; - } - if (encodings_list->nb_elem > 1) { - av_log(matroska->ctx, AV_LOG_ERROR, - "Multiple combined encodings not supported"); - } else if (encodings_list->nb_elem == 1) { - if (encodings[0].type) { - if (encodings[0].encryption.key_id.size > 0) { - /* Save the encryption key id to be stored later as a - metadata tag. */ - const int b64_size = AV_BASE64_SIZE(encodings[0].encryption.key_id.size); - key_id_base64 = av_malloc(b64_size); - if (key_id_base64 == NULL) - return AVERROR(ENOMEM); - - av_base64_encode(key_id_base64, b64_size, - encodings[0].encryption.key_id.data, - encodings[0].encryption.key_id.size); - } else { - encodings[0].scope = 0; - av_log(matroska->ctx, AV_LOG_ERROR, - "Unsupported encoding type"); - } - } else if ( -#if CONFIG_ZLIB - encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_ZLIB && -#endif -#if CONFIG_BZLIB - encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_BZLIB && -#endif -#if CONFIG_LZO - encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO && -#endif - encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP) { - encodings[0].scope = 0; - av_log(matroska->ctx, AV_LOG_ERROR, - "Unsupported encoding type"); - } else if (track->codec_priv.size && encodings[0].scope&2) { - uint8_t *codec_priv = track->codec_priv.data; - int ret = matroska_decode_buffer(&track->codec_priv.data, - &track->codec_priv.size, - track); - if (ret < 0) { - track->codec_priv.data = NULL; - track->codec_priv.size = 0; - av_log(matroska->ctx, AV_LOG_ERROR, - "Failed to decode codec private data\n"); - } - - if (codec_priv != track->codec_priv.data) - av_free(codec_priv); - } - } - - for(j=0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++){ - if(!strncmp(ff_mkv_codec_tags[j].str, track->codec_id, - strlen(ff_mkv_codec_tags[j].str))){ - codec_id= ff_mkv_codec_tags[j].id; - break; - } - } - - st = track->stream = avformat_new_stream(s, NULL); - if (st == NULL) { - av_free(key_id_base64); - return AVERROR(ENOMEM); - } - - if (key_id_base64) { - /* export encryption key id as base64 metadata tag */ - av_dict_set(&st->metadata, "enc_key_id", key_id_base64, 0); - av_freep(&key_id_base64); - } - - if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") - && track->codec_priv.size >= 40 - && track->codec_priv.data != NULL) { - track->ms_compat = 1; - bit_depth = AV_RL16(track->codec_priv.data + 14); - fourcc = AV_RL32(track->codec_priv.data + 16); - codec_id = ff_codec_get_id(ff_codec_bmp_tags, fourcc); - extradata_offset = 40; - } else if (!strcmp(track->codec_id, "A_MS/ACM") - && track->codec_priv.size >= 14 - && track->codec_priv.data != NULL) { - int ret; - 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); - if (ret < 0) - return ret; - codec_id = st->codec->codec_id; - extradata_offset = FFMIN(track->codec_priv.size, 18); - } else if (!strcmp(track->codec_id, "A_QUICKTIME") - && (track->codec_priv.size >= 86) - && (track->codec_priv.data != NULL)) { - fourcc = AV_RL32(track->codec_priv.data + 4); - codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc); - if (ff_codec_get_id(ff_codec_movaudio_tags, AV_RL32(track->codec_priv.data))) { - fourcc = AV_RL32(track->codec_priv.data); - codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc); - } - } else if (!strcmp(track->codec_id, "V_QUICKTIME") - && (track->codec_priv.size >= 21) - && (track->codec_priv.data != NULL)) { - fourcc = AV_RL32(track->codec_priv.data + 4); - codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc); - if (ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(track->codec_priv.data))) { - fourcc = AV_RL32(track->codec_priv.data); - codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc); - } - if (codec_id == AV_CODEC_ID_NONE && AV_RL32(track->codec_priv.data+4) == AV_RL32("SMI ")) - codec_id = AV_CODEC_ID_SVQ3; - } else if (codec_id == AV_CODEC_ID_PCM_S16BE) { - switch (track->audio.bitdepth) { - case 8: codec_id = AV_CODEC_ID_PCM_U8; break; - case 24: codec_id = AV_CODEC_ID_PCM_S24BE; break; - case 32: codec_id = AV_CODEC_ID_PCM_S32BE; break; - } - } else if (codec_id == AV_CODEC_ID_PCM_S16LE) { - switch (track->audio.bitdepth) { - case 8: codec_id = AV_CODEC_ID_PCM_U8; break; - case 24: codec_id = AV_CODEC_ID_PCM_S24LE; break; - case 32: codec_id = AV_CODEC_ID_PCM_S32LE; break; - } - } else if (codec_id==AV_CODEC_ID_PCM_F32LE && track->audio.bitdepth==64) { - codec_id = AV_CODEC_ID_PCM_F64LE; - } 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); - if (extradata == NULL) - return AVERROR(ENOMEM); - extradata[0] = (profile << 3) | ((sri&0x0E) >> 1); - extradata[1] = ((sri&0x01) << 7) | (track->audio.channels<<3); - if (strstr(track->codec_id, "SBR")) { - sri = matroska_aac_sri(track->audio.out_samplerate); - extradata[2] = 0x56; - extradata[3] = 0xE5; - extradata[4] = 0x80 | (sri<<3); - extradata_size = 5; - } else - extradata_size = 2; - } else if (codec_id == AV_CODEC_ID_ALAC && track->codec_priv.size && track->codec_priv.size < INT_MAX - 12 - FF_INPUT_BUFFER_PADDING_SIZE) { - /* Only ALAC's magic cookie is stored in Matroska's track headers. - Create the "atom size", "tag", and "tag version" fields the - decoder expects manually. */ - extradata_size = 12 + track->codec_priv.size; - extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); - if (extradata == NULL) - return AVERROR(ENOMEM); - AV_WB32(extradata, extradata_size); - memcpy(&extradata[4], "alac", 4); - AV_WB32(&extradata[8], 0); - memcpy(&extradata[12], track->codec_priv.data, - track->codec_priv.size); - } else if (codec_id == AV_CODEC_ID_TTA) { - extradata_size = 30; - extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); - if (extradata == NULL) - return AVERROR(ENOMEM); - ffio_init_context(&b, extradata, extradata_size, 1, - NULL, NULL, NULL, NULL); - avio_write(&b, "TTA1", 4); - avio_wl16(&b, 1); - avio_wl16(&b, track->audio.channels); - avio_wl16(&b, track->audio.bitdepth); - if (track->audio.out_samplerate < 0 || track->audio.out_samplerate > INT_MAX) - return AVERROR_INVALIDDATA; - avio_wl32(&b, track->audio.out_samplerate); - avio_wl32(&b, av_rescale((matroska->duration * matroska->time_scale), track->audio.out_samplerate, AV_TIME_BASE * 1000)); - } else if (codec_id == AV_CODEC_ID_RV10 || codec_id == AV_CODEC_ID_RV20 || - codec_id == AV_CODEC_ID_RV30 || codec_id == AV_CODEC_ID_RV40) { - extradata_offset = 26; - } else if (codec_id == AV_CODEC_ID_RA_144) { - track->audio.out_samplerate = 8000; - track->audio.channels = 1; - } else if ((codec_id == AV_CODEC_ID_RA_288 || codec_id == AV_CODEC_ID_COOK || - codec_id == AV_CODEC_ID_ATRAC3 || codec_id == AV_CODEC_ID_SIPR) - && track->codec_priv.data) { - int flavor; - - ffio_init_context(&b, track->codec_priv.data,track->codec_priv.size, - 0, NULL, NULL, NULL, NULL); - avio_skip(&b, 22); - flavor = avio_rb16(&b); - track->audio.coded_framesize = avio_rb32(&b); - avio_skip(&b, 12); - track->audio.sub_packet_h = avio_rb16(&b); - track->audio.frame_size = avio_rb16(&b); - track->audio.sub_packet_size = avio_rb16(&b); - if (flavor < 0 || track->audio.coded_framesize <= 0 || - track->audio.sub_packet_h <= 0 || track->audio.frame_size <= 0 || - track->audio.sub_packet_size <= 0) - return AVERROR_INVALIDDATA; - track->audio.buf = av_malloc_array(track->audio.sub_packet_h, track->audio.frame_size); - if (!track->audio.buf) - return AVERROR(ENOMEM); - if (codec_id == AV_CODEC_ID_RA_288) { - st->codec->block_align = track->audio.coded_framesize; - track->codec_priv.size = 0; - } else { - if (codec_id == AV_CODEC_ID_SIPR && flavor < 4) { - 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->codec->block_align = track->audio.sub_packet_size; - extradata_offset = 78; - } - } - track->codec_priv.size -= extradata_offset; - - if (codec_id == AV_CODEC_ID_NONE) - av_log(matroska->ctx, AV_LOG_INFO, - "Unknown/unsupported AVCodecID %s.\n", track->codec_id); - - if (track->time_scale < 0.01) - track->time_scale = 1.0; - avpriv_set_pts_info(st, 64, matroska->time_scale*track->time_scale, 1000*1000*1000); /* 64 bit pts in ns */ - - /* 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; - - if (strcmp(track->language, "und")) - av_dict_set(&st->metadata, "language", track->language, 0); - av_dict_set(&st->metadata, "title", track->name, 0); - - if (track->flag_default) - st->disposition |= AV_DISPOSITION_DEFAULT; - if (track->flag_forced) - st->disposition |= AV_DISPOSITION_FORCED; - - if (!st->codec->extradata) { - if(extradata){ - st->codec->extradata = extradata; - st->codec->extradata_size = extradata_size; - } else if(track->codec_priv.data && track->codec_priv.size > 0){ - if (ff_alloc_extradata(st->codec, track->codec_priv.size)) - return AVERROR(ENOMEM); - memcpy(st->codec->extradata, - track->codec_priv.data + extradata_offset, - track->codec_priv.size); - } - } - - if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { - MatroskaTrackPlane *planes = track->operation.combine_planes.elem; - - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_tag = fourcc; - if (bit_depth >= 0) - st->codec->bits_per_coded_sample = bit_depth; - st->codec->width = track->video.pixel_width; - st->codec->height = track->video.pixel_height; - 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, - 255); - if (st->codec->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, - 1000000000, track->default_duration, 30000); -#if FF_API_R_FRAME_RATE - if (st->avg_frame_rate.num < st->avg_frame_rate.den * 1000L) - st->r_frame_rate = st->avg_frame_rate; -#endif - } - - /* export stereo mode flag as metadata tag */ - if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREO_MODE_COUNT) - av_dict_set(&st->metadata, "stereo_mode", ff_matroska_video_stereo_mode[track->video.stereo_mode], 0); - - /* export alpha mode flag as metadata tag */ - if (track->video.alpha_mode) - av_dict_set(&st->metadata, "alpha_mode", "1", 0); - - /* if we have virtual track, mark the real tracks */ - for (j=0; j < track->operation.combine_planes.nb_elem; j++) { - char buf[32]; - if (planes[j].type >= MATROSKA_VIDEO_STEREO_PLANE_COUNT) - continue; - snprintf(buf, sizeof(buf), "%s_%d", - ff_matroska_video_stereo_plane[planes[j].type], i); - for (k=0; k < matroska->tracks.nb_elem; k++) - if (planes[j].uid == tracks[k].uid) { - av_dict_set(&s->streams[k]->metadata, - "stereo_mode", buf, 0); - break; - } - } - } 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->bits_per_coded_sample) - st->codec->bits_per_coded_sample = track->audio.bitdepth; - if (st->codec->codec_id != AV_CODEC_ID_AAC) - st->need_parsing = AVSTREAM_PARSE_HEADERS; - if (track->codec_delay > 0) { - st->codec->delay = av_rescale_q(track->codec_delay, - st->time_base, - (AVRational){1, st->codec->sample_rate}); - } - if (track->seek_preroll > 0) { - av_codec_set_seek_preroll(st->codec, - av_rescale_q(track->seek_preroll, - (AVRational){1, 1000000000}, - (AVRational){1, st->codec->sample_rate})); - } - } else if (codec_id == AV_CODEC_ID_WEBVTT) { - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - - if (!strcmp(track->codec_id, "D_WEBVTT/CAPTIONS")) { - st->disposition |= AV_DISPOSITION_CAPTIONS; - } else if (!strcmp(track->codec_id, "D_WEBVTT/DESCRIPTIONS")) { - st->disposition |= AV_DISPOSITION_DESCRIPTIONS; - } else if (!strcmp(track->codec_id, "D_WEBVTT/METADATA")) { - st->disposition |= AV_DISPOSITION_METADATA; - } - } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) { - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; -#if FF_API_ASS_SSA - if (st->codec->codec_id == AV_CODEC_ID_SSA || - st->codec->codec_id == AV_CODEC_ID_ASS) -#else - if (st->codec->codec_id == AV_CODEC_ID_ASS) -#endif - matroska->contains_ssa = 1; - } - } - - attachements = attachements_list->elem; - for (j=0; jnb_elem; j++) { - if (!(attachements[j].filename && attachements[j].mime && - attachements[j].bin.data && attachements[j].bin.size > 0)) { + attachments = attachments_list->elem; + for (j = 0; j < attachments_list->nb_elem; j++) { + if (!(attachments[j].filename && attachments[j].mime && + attachments[j].bin.data && attachments[j].bin.size > 0)) { av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n"); } else { AVStream *st = avformat_new_stream(s, NULL); if (st == NULL) break; - av_dict_set(&st->metadata, "filename",attachements[j].filename, 0); - av_dict_set(&st->metadata, "mimetype", attachements[j].mime, 0); - st->codec->codec_id = AV_CODEC_ID_NONE; + 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; - if (ff_alloc_extradata(st->codec, attachements[j].bin.size)) + if (ff_alloc_extradata(st->codec, attachments[j].bin.size)) break; - memcpy(st->codec->extradata, attachements[j].bin.data, attachements[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, attachements[j].mime, + 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; break; } } - attachements[j].stream = st; + attachments[j].stream = st; } } chapters = chapters_list->elem; - for (i=0; inb_elem; i++) - if (chapters[i].start != AV_NOPTS_VALUE && chapters[i].uid - && (max_start==0 || chapters[i].start > max_start)) { + for (i = 0; i < chapters_list->nb_elem; i++) + if (chapters[i].start != AV_NOPTS_VALUE && chapters[i].uid && + (max_start == 0 || chapters[i].start > max_start)) { chapters[i].chapter = - avpriv_new_chapter(s, chapters[i].uid, (AVRational){1, 1000000000}, - chapters[i].start, chapters[i].end, - chapters[i].title); + avpriv_new_chapter(s, chapters[i].uid, + (AVRational) { 1, 1000000000 }, + chapters[i].start, chapters[i].end, + chapters[i].title); av_dict_set(&chapters[i].chapter->metadata, - "title", chapters[i].title, 0); + "title", chapters[i].title, 0); max_start = chapters[i].start; } @@ -2034,7 +2188,8 @@ static int matroska_deliver_packet(MatroskaDemuxContext *matroska, memmove(&matroska->packets[0], &matroska->packets[1], (matroska->num_packets - 1) * sizeof(AVPacket *)); newpackets = av_realloc(matroska->packets, - (matroska->num_packets - 1) * sizeof(AVPacket *)); + (matroska->num_packets - 1) * + sizeof(AVPacket *)); if (newpackets) matroska->packets = newpackets; } else { @@ -2066,7 +2221,7 @@ static void matroska_clear_queue(MatroskaDemuxContext *matroska) } static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, - int* buf_size, int type, + int *buf_size, int type, uint32_t **lace_buf, int *laces) { int res = 0, n, size = *buf_size; @@ -2074,7 +2229,7 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, uint32_t *lace_size; if (!type) { - *laces = 1; + *laces = 1; *lace_buf = av_mallocz(sizeof(int)); if (!*lace_buf) return AVERROR(ENOMEM); @@ -2084,15 +2239,16 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, } av_assert0(size > 0); - *laces = *data + 1; - data += 1; - size -= 1; + *laces = *data + 1; + data += 1; + size -= 1; lace_size = av_mallocz(*laces * sizeof(int)); if (!lace_size) return AVERROR(ENOMEM); switch (type) { - case 0x1: /* Xiph lacing */ { + case 0x1: /* Xiph lacing */ + { uint8_t temp; uint32_t total = 0; for (n = 0; res == 0 && n < *laces - 1; n++) { @@ -2101,11 +2257,11 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, res = AVERROR_INVALIDDATA; break; } - temp = *data; - total += temp; + temp = *data; + total += temp; lace_size[n] += temp; - data += 1; - size -= 1; + data += 1; + size -= 1; if (temp != 0xff) break; } @@ -2128,7 +2284,8 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, lace_size[n] = size / *laces; break; - case 0x3: /* EBML lacing */ { + case 0x3: /* EBML lacing */ + { uint64_t num; uint64_t total; n = matroska_ebmlnum_uint(matroska, data, size, &num); @@ -2151,10 +2308,10 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, res = r<0 ? r : AVERROR_INVALIDDATA; break; } - data += r; - size -= r; + data += r; + size -= r; lace_size[n] = lace_size[n - 1] + snum; - total += lace_size[n]; + total += lace_size[n]; } if (size <= total) { res = AVERROR_INVALIDDATA; @@ -2173,18 +2330,16 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, } static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, - MatroskaTrack *track, - AVStream *st, - uint8_t *data, int size, - uint64_t timecode, + MatroskaTrack *track, AVStream *st, + uint8_t *data, int size, uint64_t timecode, int64_t pos) { int a = st->codec->block_align; int sps = track->audio.sub_packet_size; int cfs = track->audio.coded_framesize; - int h = track->audio.sub_packet_h; - int y = track->audio.sub_packet_cnt; - int w = track->audio.frame_size; + int h = track->audio.sub_packet_h; + int y = track->audio.sub_packet_cnt; + int w = track->audio.frame_size; int x; if (!track->audio.pkt_cnt) { @@ -2196,47 +2351,50 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, "Corrupt int4 RM-style audio packet size\n"); return AVERROR_INVALIDDATA; } - for (x=0; xaudio.buf+x*2*w+y*cfs, - data+x*cfs, cfs); + 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) { if (size < w) { av_log(matroska->ctx, AV_LOG_ERROR, "Corrupt sipr RM-style audio packet size\n"); return AVERROR_INVALIDDATA; } - memcpy(track->audio.buf + y*w, data, w); + memcpy(track->audio.buf + y * w, data, w); } else { if (size < sps * w / sps || h<=0 || w%sps) { av_log(matroska->ctx, AV_LOG_ERROR, "Corrupt generic RM-style audio packet size\n"); return AVERROR_INVALIDDATA; } - for (x=0; xaudio.buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps); + for (x = 0; x < w / sps; x++) + memcpy(track->audio.buf + + sps * (h * x + ((h + 1) / 2) * (y & 1) + (y >> 1)), + data + x * sps, sps); } if (++track->audio.sub_packet_cnt >= h) { if (st->codec->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; + track->audio.pkt_cnt = h * w / a; } } while (track->audio.pkt_cnt) { AVPacket *pkt = NULL; - if (!(pkt = av_mallocz(sizeof(AVPacket))) || av_new_packet(pkt, a) < 0){ + if (!(pkt = av_mallocz(sizeof(AVPacket))) || av_new_packet(pkt, a) < 0) { av_free(pkt); return AVERROR(ENOMEM); } - memcpy(pkt->data, track->audio.buf - + a * (h*w / a - track->audio.pkt_cnt--), a); - pkt->pts = track->audio.buf_timecode; + memcpy(pkt->data, + track->audio.buf + a * (h * w / a - track->audio.pkt_cnt--), + a); + pkt->pts = track->audio.buf_timecode; track->audio.buf_timecode = AV_NOPTS_VALUE; - pkt->pos = pos; - pkt->stream_index = st->index; - dynarray_add(&matroska->packets,&matroska->num_packets,pkt); + pkt->pos = pos; + pkt->stream_index = st->index; + dynarray_add(&matroska->packets, &matroska->num_packets, pkt); } return 0; @@ -2279,8 +2437,8 @@ static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src, goto fail; } blocksize = AV_RL32(src); - src += 4; - srclen -= 4; + src += 4; + srclen -= 4; } else blocksize = srclen; @@ -2297,16 +2455,16 @@ static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src, dst = tmp; dstlen += blocksize + 32; - AV_WL32(dst + offset, MKTAG('w', 'v', 'p', 'k')); // tag - AV_WL32(dst + offset + 4, blocksize + 24); // blocksize - 8 - AV_WL16(dst + offset + 8, ver); // version - AV_WL16(dst + offset + 10, 0); // track/index_no - AV_WL32(dst + offset + 12, 0); // total samples - AV_WL32(dst + offset + 16, 0); // block index - AV_WL32(dst + offset + 20, samples); // number of samples - AV_WL32(dst + offset + 24, flags); // flags - AV_WL32(dst + offset + 28, crc); // crc - memcpy (dst + offset + 32, src, blocksize); // block data + AV_WL32(dst + offset, MKTAG('w', 'v', 'p', 'k')); // tag + AV_WL32(dst + offset + 4, blocksize + 24); // blocksize - 8 + AV_WL16(dst + offset + 8, ver); // version + AV_WL16(dst + offset + 10, 0); // track/index_no + AV_WL32(dst + offset + 12, 0); // total samples + AV_WL32(dst + offset + 16, 0); // block index + AV_WL32(dst + offset + 20, samples); // number of samples + AV_WL32(dst + offset + 24, flags); // flags + AV_WL32(dst + offset + 28, crc); // crc + memcpy(dst + offset + 32, src, blocksize); // block data src += blocksize; srclen -= blocksize; @@ -2438,8 +2596,7 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, } static int matroska_parse_frame(MatroskaDemuxContext *matroska, - MatroskaTrack *track, - AVStream *st, + MatroskaTrack *track, AVStream *st, uint8_t *data, int pkt_size, uint64_t timecode, uint64_t lace_duration, int64_t pos, int is_keyframe, @@ -2461,7 +2618,8 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, uint8_t *wv_data; res = matroska_parse_wavpack(track, pkt_data, &wv_data, &pkt_size); if (res < 0) { - av_log(matroska->ctx, AV_LOG_ERROR, "Error parsing a wavpack block.\n"); + av_log(matroska->ctx, AV_LOG_ERROR, + "Error parsing a wavpack block.\n"); goto fail; } if (pkt_data != data) @@ -2469,7 +2627,8 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, pkt_data = wv_data; } - if (st->codec->codec_id == AV_CODEC_ID_PRORES) + if (st->codec->codec_id == AV_CODEC_ID_PRORES && + AV_RB32(&data[4]) != MKBETAG('i', 'c', 'p', 'f')) offset = 8; pkt = av_mallocz(sizeof(AVPacket)); @@ -2480,7 +2639,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, goto fail; } - if (st->codec->codec_id == AV_CODEC_ID_PRORES) { + if (st->codec->codec_id == AV_CODEC_ID_PRORES && offset == 8) { uint8_t *buf = pkt->data; bytestream_put_be32(&buf, pkt_size); bytestream_put_be32(&buf, MKBETAG('i', 'c', 'p', 'f')); @@ -2491,14 +2650,14 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, if (pkt_data != data) av_freep(&pkt_data); - pkt->flags = is_keyframe; + pkt->flags = is_keyframe; pkt->stream_index = st->index; if (additional_size > 0) { uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, additional_size + 8); - if(side_data == NULL) { + if (side_data == NULL) { av_free_packet(pkt); av_free(pkt); return AVERROR(ENOMEM); @@ -2511,7 +2670,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10); - if(side_data == NULL) { + if (side_data == NULL) { av_free_packet(pkt); av_free(pkt); return AVERROR(ENOMEM); @@ -2555,14 +2714,14 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, if (st->codec->codec_id == AV_CODEC_ID_SSA) matroska_fix_ass_packet(matroska, pkt, lace_duration); - if (matroska->prev_pkt && - timecode != AV_NOPTS_VALUE && - matroska->prev_pkt->pts == timecode && - matroska->prev_pkt->stream_index == st->index && + 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) matroska_merge_packets(matroska->prev_pkt, pkt); else { - dynarray_add(&matroska->packets,&matroska->num_packets,pkt); + dynarray_add(&matroska->packets, &matroska->num_packets, pkt); matroska->prev_pkt = pkt; } #else @@ -2571,6 +2730,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, #endif return 0; + fail: if (pkt_data != data) av_freep(&pkt_data); @@ -2613,23 +2773,25 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, av_assert1(block_duration != AV_NOPTS_VALUE); block_time = sign_extend(AV_RB16(data), 16); - data += 2; - flags = *data++; - size -= 3; + data += 2; + flags = *data++; + size -= 3; if (is_keyframe == -1) is_keyframe = flags & 0x80 ? AV_PKT_FLAG_KEY : 0; - if (cluster_time != (uint64_t)-1 - && (block_time >= 0 || cluster_time >= -block_time)) { + if (cluster_time != (uint64_t) -1 && + (block_time >= 0 || cluster_time >= -block_time)) { timecode = cluster_time + block_time - track->codec_delay; - if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE - && timecode < track->end_timecode) + if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE && + timecode < track->end_timecode) is_keyframe = 0; /* overlapping subtitles are not key frame */ if (is_keyframe) - av_add_index_entry(st, cluster_pos, timecode, 0,0,AVINDEX_KEYFRAME); + av_add_index_entry(st, cluster_pos, timecode, 0, 0, + AVINDEX_KEYFRAME); } - if (matroska->skip_to_keyframe && track->type != MATROSKA_TRACK_TYPE_SUBTITLE) { + if (matroska->skip_to_keyframe && + track->type != MATROSKA_TRACK_TYPE_SUBTITLE) { if (timecode < matroska->skip_to_timecode) return res; if (is_keyframe) @@ -2649,7 +2811,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, if (track->audio.samplerate == 8000) { // If this is needed for more codecs, then add them here if (st->codec->codec_id == AV_CODEC_ID_AC3) { - if(track->audio.samplerate != st->codec->sample_rate || !st->codec->frame_size) + if (track->audio.samplerate != st->codec->sample_rate || !st->codec->frame_size) trust_default_duration = 0; } } @@ -2670,11 +2832,10 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, } 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_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) { - + st->codec->block_align && track->audio.sub_packet_size) { res = matroska_parse_rm_audio(matroska, track, st, data, lace_size[n], timecode, pos); @@ -2688,13 +2849,12 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, pos); if (res) goto end; - } else { res = matroska_parse_frame(matroska, track, st, data, lace_size[n], - timecode, lace_duration, - pos, !n? is_keyframe : 0, - additional, additional_id, additional_size, - discard_padding); + timecode, lace_duration, pos, + !n ? is_keyframe : 0, + additional, additional_id, additional_size, + discard_padding); if (res) goto end; } @@ -2725,8 +2885,8 @@ static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska) ebml_free(matroska_cluster, &matroska->current_cluster); memset(&matroska->current_cluster, 0, sizeof(MatroskaCluster)); matroska->current_cluster_num_blocks = 0; - matroska->current_cluster_pos = avio_tell(matroska->ctx->pb); - matroska->prev_pkt = NULL; + matroska->current_cluster_pos = avio_tell(matroska->ctx->pb); + matroska->prev_pkt = NULL; /* sizeof the ID which was already read */ if (matroska->current_id) matroska->current_cluster_pos -= 4; @@ -2742,21 +2902,20 @@ static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska) if (!res && matroska->current_cluster_num_blocks < - matroska->current_cluster.blocks.nb_elem) { + matroska->current_cluster.blocks.nb_elem) { blocks_list = &matroska->current_cluster.blocks; - blocks = blocks_list->elem; + blocks = blocks_list->elem; matroska->current_cluster_num_blocks = blocks_list->nb_elem; - i = blocks_list->nb_elem - 1; + i = blocks_list->nb_elem - 1; if (blocks[i].bin.size > 0 && blocks[i].bin.data) { int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1; uint8_t* additional = blocks[i].additional.size > 0 ? blocks[i].additional.data : NULL; if (!blocks[i].non_simple) blocks[i].duration = 0; - res = matroska_parse_block(matroska, - blocks[i].bin.data, blocks[i].bin.size, - blocks[i].bin.pos, + res = matroska_parse_block(matroska, blocks[i].bin.data, + blocks[i].bin.size, blocks[i].bin.pos, matroska->current_cluster.timecode, blocks[i].duration, is_keyframe, additional, blocks[i].additional_id, @@ -2776,23 +2935,24 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska) MatroskaBlock *blocks; int i, res; int64_t pos; + if (!matroska->contains_ssa) return matroska_parse_cluster_incremental(matroska); pos = avio_tell(matroska->ctx->pb); matroska->prev_pkt = NULL; if (matroska->current_id) pos -= 4; /* sizeof the ID which was already read */ - res = ebml_parse(matroska, matroska_clusters, &cluster); + res = ebml_parse(matroska, matroska_clusters, &cluster); blocks_list = &cluster.blocks; - blocks = blocks_list->elem; - for (i=0; inb_elem; i++) + blocks = blocks_list->elem; + for (i = 0; i < blocks_list->nb_elem; i++) if (blocks[i].bin.size > 0 && blocks[i].bin.data) { int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1; - res=matroska_parse_block(matroska, - blocks[i].bin.data, blocks[i].bin.size, - blocks[i].bin.pos, cluster.timecode, - blocks[i].duration, is_keyframe, NULL, 0, 0, - pos, blocks[i].discard_padding); + res = matroska_parse_block(matroska, blocks[i].bin.data, + blocks[i].bin.size, blocks[i].bin.pos, + cluster.timecode, blocks[i].duration, + is_keyframe, NULL, 0, 0, pos, + blocks[i].discard_padding); } ebml_free(matroska_cluster, &cluster); return res; @@ -2832,7 +2992,8 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index, timestamp = FFMAX(timestamp, st->index_entries[0].timestamp); if ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) { - avio_seek(s->pb, st->index_entries[st->nb_index_entries-1].pos, SEEK_SET); + avio_seek(s->pb, st->index_entries[st->nb_index_entries - 1].pos, + SEEK_SET); matroska->current_id = 0; while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) { matroska_clear_queue(matroska); @@ -2846,24 +3007,26 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index, goto err; index_min = index; - for (i=0; i < matroska->tracks.nb_elem; i++) { - tracks[i].audio.pkt_cnt = 0; + for (i = 0; i < matroska->tracks.nb_elem; i++) { + tracks[i].audio.pkt_cnt = 0; tracks[i].audio.sub_packet_cnt = 0; - tracks[i].audio.buf_timecode = AV_NOPTS_VALUE; - tracks[i].end_timecode = 0; - if (tracks[i].type == MATROSKA_TRACK_TYPE_SUBTITLE - && tracks[i].stream->discard != AVDISCARD_ALL) { - index_sub = av_index_search_timestamp(tracks[i].stream, st->index_entries[index].timestamp, AVSEEK_FLAG_BACKWARD); - while(index_sub >= 0 - && index_min >= 0 - && tracks[i].stream->index_entries[index_sub].pos < st->index_entries[index_min].pos - && st->index_entries[index].timestamp - tracks[i].stream->index_entries[index_sub].timestamp < 30000000000/matroska->time_scale) + tracks[i].audio.buf_timecode = AV_NOPTS_VALUE; + tracks[i].end_timecode = 0; + if (tracks[i].type == MATROSKA_TRACK_TYPE_SUBTITLE && + tracks[i].stream->discard != AVDISCARD_ALL) { + index_sub = av_index_search_timestamp( + tracks[i].stream, st->index_entries[index].timestamp, + AVSEEK_FLAG_BACKWARD); + while (index_sub >= 0 && + index_min > 0 && + tracks[i].stream->index_entries[index_sub].pos < st->index_entries[index_min].pos && + st->index_entries[index].timestamp - tracks[i].stream->index_entries[index_sub].timestamp < 30000000000 / matroska->time_scale) index_min--; } } avio_seek(s->pb, st->index_entries[index_min].pos, SEEK_SET); - matroska->current_id = 0; + matroska->current_id = 0; if (flags & AVSEEK_FLAG_ANY) { st->skip_to_keyframe = 0; matroska->skip_to_timecode = timestamp; @@ -2872,8 +3035,8 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index, matroska->skip_to_timecode = st->index_entries[index].timestamp; } matroska->skip_to_keyframe = 1; - matroska->done = 0; - matroska->num_levels = 0; + matroska->done = 0; + matroska->num_levels = 0; ff_update_cur_dts(s, st, st->index_entries[index].timestamp); return 0; err: @@ -2896,7 +3059,7 @@ static int matroska_read_close(AVFormatContext *s) matroska_clear_queue(matroska); - for (n=0; n < matroska->tracks.nb_elem; n++) + for (n = 0; n < matroska->tracks.nb_elem; n++) if (tracks[n].type == MATROSKA_TRACK_TYPE_AUDIO) av_free(tracks[n].audio.buf); ebml_free(matroska_cluster, &matroska->current_cluster); @@ -2905,6 +3068,367 @@ static int matroska_read_close(AVFormatContext *s) return 0; } +typedef struct { + int64_t start_time_ns; + int64_t end_time_ns; + int64_t start_offset; + int64_t end_offset; +} CueDesc; + +/* This function searches all the Cues and returns the CueDesc corresponding the + * the timestamp ts. Returned CueDesc will be such that start_time_ns <= ts < + * end_time_ns. All 4 fields will be set to -1 if ts >= file's duration. + */ +static CueDesc get_cue_desc(AVFormatContext *s, int64_t ts, int64_t cues_start) { + MatroskaDemuxContext *matroska = s->priv_data; + CueDesc cue_desc; + int i; + int nb_index_entries = s->streams[0]->nb_index_entries; + AVIndexEntry *index_entries = s->streams[0]->index_entries; + if (ts >= matroska->duration * matroska->time_scale) return (CueDesc) {-1, -1, -1, -1}; + for (i = 1; i < nb_index_entries; i++) { + if (index_entries[i - 1].timestamp * matroska->time_scale <= ts && + index_entries[i].timestamp * matroska->time_scale > ts) { + break; + } + } + --i; + cue_desc.start_time_ns = index_entries[i].timestamp * matroska->time_scale; + cue_desc.start_offset = index_entries[i].pos - matroska->segment_start; + if (i != nb_index_entries - 1) { + cue_desc.end_time_ns = index_entries[i + 1].timestamp * matroska->time_scale; + cue_desc.end_offset = index_entries[i + 1].pos - matroska->segment_start; + } else { + cue_desc.end_time_ns = matroska->duration * matroska->time_scale; + // FIXME: this needs special handling for files where Cues appear + // before Clusters. the current logic assumes Cues appear after + // Clusters. + cue_desc.end_offset = cues_start - matroska->segment_start; + } + return cue_desc; +} + +static int webm_clusters_start_with_keyframe(AVFormatContext *s) +{ + MatroskaDemuxContext *matroska = s->priv_data; + int64_t cluster_pos, before_pos; + int index, rv = 1; + if (s->streams[0]->nb_index_entries <= 0) return 0; + // seek to the first cluster using cues. + index = av_index_search_timestamp(s->streams[0], 0, 0); + if (index < 0) return 0; + cluster_pos = s->streams[0]->index_entries[index].pos; + before_pos = avio_tell(s->pb); + while (1) { + int64_t cluster_id = 0, cluster_length = 0; + AVPacket *pkt; + avio_seek(s->pb, cluster_pos, SEEK_SET); + // read cluster id and length + ebml_read_num(matroska, matroska->ctx->pb, 4, &cluster_id); + ebml_read_length(matroska, matroska->ctx->pb, &cluster_length); + if (cluster_id != 0xF43B675) { // done with all clusters + break; + } + avio_seek(s->pb, cluster_pos, SEEK_SET); + matroska->current_id = 0; + matroska_clear_queue(matroska); + if (matroska_parse_cluster(matroska) < 0 || + matroska->num_packets <= 0) { + break; + } + pkt = matroska->packets[0]; + cluster_pos += cluster_length + 12; // 12 is the offset of the cluster id and length. + if (!(pkt->flags & AV_PKT_FLAG_KEY)) { + rv = 0; + break; + } + } + avio_seek(s->pb, before_pos, SEEK_SET); + return rv; +} + +static int buffer_size_after_time_downloaded(int64_t time_ns, double search_sec, int64_t bps, + double min_buffer, double* buffer, + double* sec_to_download, AVFormatContext *s, + int64_t cues_start) +{ + double nano_seconds_per_second = 1000000000.0; + double time_sec = time_ns / nano_seconds_per_second; + int rv = 0; + int64_t time_to_search_ns = (int64_t)(search_sec * nano_seconds_per_second); + int64_t end_time_ns = time_ns + time_to_search_ns; + double sec_downloaded = 0.0; + CueDesc desc_curr = get_cue_desc(s, time_ns, cues_start); + if (desc_curr.start_time_ns == -1) + return -1; + *sec_to_download = 0.0; + + // Check for non cue start time. + if (time_ns > desc_curr.start_time_ns) { + int64_t cue_nano = desc_curr.end_time_ns - time_ns; + double percent = (double)(cue_nano) / (desc_curr.end_time_ns - desc_curr.start_time_ns); + double cueBytes = (desc_curr.end_offset - desc_curr.start_offset) * percent; + double timeToDownload = (cueBytes * 8.0) / bps; + + sec_downloaded += (cue_nano / nano_seconds_per_second) - timeToDownload; + *sec_to_download += timeToDownload; + + // Check if the search ends within the first cue. + if (desc_curr.end_time_ns >= end_time_ns) { + double desc_end_time_sec = desc_curr.end_time_ns / nano_seconds_per_second; + double percent_to_sub = search_sec / (desc_end_time_sec - time_sec); + sec_downloaded = percent_to_sub * sec_downloaded; + *sec_to_download = percent_to_sub * *sec_to_download; + } + + if ((sec_downloaded + *buffer) <= min_buffer) { + return 1; + } + + // Get the next Cue. + desc_curr = get_cue_desc(s, desc_curr.end_time_ns, cues_start); + } + + while (desc_curr.start_time_ns != -1) { + int64_t desc_bytes = desc_curr.end_offset - desc_curr.start_offset; + int64_t desc_ns = desc_curr.end_time_ns - desc_curr.start_time_ns; + double desc_sec = desc_ns / nano_seconds_per_second; + double bits = (desc_bytes * 8.0); + double time_to_download = bits / bps; + + sec_downloaded += desc_sec - time_to_download; + *sec_to_download += time_to_download; + + if (desc_curr.end_time_ns >= end_time_ns) { + double desc_end_time_sec = desc_curr.end_time_ns / nano_seconds_per_second; + double percent_to_sub = search_sec / (desc_end_time_sec - time_sec); + sec_downloaded = percent_to_sub * sec_downloaded; + *sec_to_download = percent_to_sub * *sec_to_download; + + if ((sec_downloaded + *buffer) <= min_buffer) + rv = 1; + break; + } + + if ((sec_downloaded + *buffer) <= min_buffer) { + rv = 1; + break; + } + + desc_curr = get_cue_desc(s, desc_curr.end_time_ns, cues_start); + } + *buffer = *buffer + sec_downloaded; + return rv; +} + +/* This function computes the bandwidth of the WebM file with the help of + * buffer_size_after_time_downloaded() function. Both of these functions are + * adapted from WebM Tools project and are adapted to work with FFmpeg's + * Matroska parsing mechanism. + * + * Returns the bandwidth of the file on success; -1 on error. + * */ +static int64_t webm_dash_manifest_compute_bandwidth(AVFormatContext *s, int64_t cues_start) +{ + MatroskaDemuxContext *matroska = s->priv_data; + AVStream *st = s->streams[0]; + double bandwidth = 0.0; + int i; + + for (i = 0; i < st->nb_index_entries; i++) { + int64_t prebuffer_ns = 1000000000; + int64_t time_ns = st->index_entries[i].timestamp * matroska->time_scale; + double nano_seconds_per_second = 1000000000.0; + int64_t prebuffered_ns = time_ns + prebuffer_ns; + double prebuffer_bytes = 0.0; + int64_t temp_prebuffer_ns = prebuffer_ns; + int64_t pre_bytes, pre_ns; + double pre_sec, prebuffer, bits_per_second; + CueDesc desc_beg = get_cue_desc(s, time_ns, cues_start); + + // Start with the first Cue. + CueDesc desc_end = desc_beg; + + // Figure out how much data we have downloaded for the prebuffer. This will + // be used later to adjust the bits per sample to try. + while (desc_end.start_time_ns != -1 && desc_end.end_time_ns < prebuffered_ns) { + // Prebuffered the entire Cue. + prebuffer_bytes += desc_end.end_offset - desc_end.start_offset; + temp_prebuffer_ns -= desc_end.end_time_ns - desc_end.start_time_ns; + desc_end = get_cue_desc(s, desc_end.end_time_ns, cues_start); + } + if (desc_end.start_time_ns == -1) { + // The prebuffer is larger than the duration. + return (matroska->duration * matroska->time_scale >= prebuffered_ns) ? -1 : 0; + } + + // The prebuffer ends in the last Cue. Estimate how much data was + // prebuffered. + pre_bytes = desc_end.end_offset - desc_end.start_offset; + pre_ns = desc_end.end_time_ns - desc_end.start_time_ns; + pre_sec = pre_ns / nano_seconds_per_second; + prebuffer_bytes += + pre_bytes * ((temp_prebuffer_ns / nano_seconds_per_second) / pre_sec); + + prebuffer = prebuffer_ns / nano_seconds_per_second; + + // Set this to 0.0 in case our prebuffer buffers the entire video. + bits_per_second = 0.0; + do { + int64_t desc_bytes = desc_end.end_offset - desc_beg.start_offset; + int64_t desc_ns = desc_end.end_time_ns - desc_beg.start_time_ns; + double desc_sec = desc_ns / nano_seconds_per_second; + double calc_bits_per_second = (desc_bytes * 8) / desc_sec; + + // Drop the bps by the percentage of bytes buffered. + double percent = (desc_bytes - prebuffer_bytes) / desc_bytes; + double mod_bits_per_second = calc_bits_per_second * percent; + + if (prebuffer < desc_sec) { + double search_sec = + (double)(matroska->duration * matroska->time_scale) / nano_seconds_per_second; + + // Add 1 so the bits per second should be a little bit greater than file + // datarate. + int64_t bps = (int64_t)(mod_bits_per_second) + 1; + const double min_buffer = 0.0; + double buffer = prebuffer; + double sec_to_download = 0.0; + + int rv = buffer_size_after_time_downloaded(prebuffered_ns, search_sec, bps, + min_buffer, &buffer, &sec_to_download, + s, cues_start); + if (rv < 0) { + return -1; + } else if (rv == 0) { + bits_per_second = (double)(bps); + break; + } + } + + desc_end = get_cue_desc(s, desc_end.end_time_ns, cues_start); + } while (desc_end.start_time_ns != -1); + if (bandwidth < bits_per_second) bandwidth = bits_per_second; + } + return (int64_t)bandwidth; +} + +static int webm_dash_manifest_cues(AVFormatContext *s) +{ + MatroskaDemuxContext *matroska = s->priv_data; + EbmlList *seekhead_list = &matroska->seekhead; + MatroskaSeekhead *seekhead = seekhead_list->elem; + char *buf; + int64_t cues_start, cues_end, before_pos, bandwidth; + int i; + + // determine cues start and end positions + for (i = 0; i < seekhead_list->nb_elem; i++) + if (seekhead[i].id == MATROSKA_ID_CUES) + break; + + if (i >= seekhead_list->nb_elem) return -1; + + before_pos = avio_tell(matroska->ctx->pb); + cues_start = seekhead[i].pos + matroska->segment_start; + if (avio_seek(matroska->ctx->pb, cues_start, SEEK_SET) == cues_start) { + uint64_t cues_length = 0, cues_id = 0; + ebml_read_num(matroska, matroska->ctx->pb, 4, &cues_id); + ebml_read_length(matroska, matroska->ctx->pb, &cues_length); + cues_end = cues_start + cues_length + 11; // 11 is the offset of Cues ID. + } + avio_seek(matroska->ctx->pb, before_pos, SEEK_SET); + + // parse the cues + matroska_parse_cues(matroska); + + // cues start + buf = av_asprintf("%" PRId64, cues_start); + if (!buf) return AVERROR(ENOMEM); + av_dict_set(&s->streams[0]->metadata, CUES_START, buf, 0); + av_free(buf); + + // cues end + buf = av_asprintf("%" PRId64, cues_end); + if (!buf) return AVERROR(ENOMEM); + av_dict_set(&s->streams[0]->metadata, CUES_END, buf, 0); + av_free(buf); + + // bandwidth + bandwidth = webm_dash_manifest_compute_bandwidth(s, cues_start); + if (bandwidth < 0) return -1; + buf = av_asprintf("%" PRId64, bandwidth); + if (!buf) return AVERROR(ENOMEM); + av_dict_set(&s->streams[0]->metadata, BANDWIDTH, buf, 0); + av_free(buf); + + // check if all clusters start with key frames + buf = av_asprintf("%d", webm_clusters_start_with_keyframe(s)); + if (!buf) return AVERROR(ENOMEM); + av_dict_set(&s->streams[0]->metadata, CLUSTER_KEYFRAME, buf, 0); + av_free(buf); + + // store cue point timestamps as a comma separated list for checking subsegment alignment in + // the muxer. assumes that each timestamp cannot be more than 20 characters long. + buf = av_malloc(s->streams[0]->nb_index_entries * 20 * sizeof(char)); + if (!buf) return -1; + strcpy(buf, ""); + for (i = 0; i < s->streams[0]->nb_index_entries; i++) { + snprintf(buf, (i + 1) * 20 * sizeof(char), + "%s%" PRId64, buf, s->streams[0]->index_entries[i].timestamp); + if (i != s->streams[0]->nb_index_entries - 1) + strncat(buf, ",", sizeof(char)); + } + av_dict_set(&s->streams[0]->metadata, CUE_TIMESTAMPS, buf, 0); + av_free(buf); + + return 0; +} + +static int webm_dash_manifest_read_header(AVFormatContext *s) +{ + char *buf; + int ret = matroska_read_header(s); + MatroskaTrack *tracks; + MatroskaDemuxContext *matroska = s->priv_data; + if (ret) { + av_log(s, AV_LOG_ERROR, "Failed to read file headers\n"); + return -1; + } + + // initialization range + buf = av_asprintf("%" PRId64, avio_tell(s->pb) - 5); // 5 is the offset of Cluster ID. + if (!buf) return AVERROR(ENOMEM); + av_dict_set(&s->streams[0]->metadata, INITIALIZATION_RANGE, buf, 0); + av_free(buf); + + // basename of the file + buf = strrchr(s->filename, '/'); + if (buf == NULL) return -1; + av_dict_set(&s->streams[0]->metadata, FILENAME, ++buf, 0); + + // duration + buf = av_asprintf("%g", matroska->duration); + if (!buf) return AVERROR(ENOMEM); + av_dict_set(&s->streams[0]->metadata, DURATION, buf, 0); + av_free(buf); + + // track number + tracks = matroska->tracks.elem; + buf = av_asprintf("%" PRId64, tracks[0].num); + if (!buf) return AVERROR(ENOMEM); + av_dict_set(&s->streams[0]->metadata, TRACK_NUMBER, buf, 0); + av_free(buf); + + // parse the cues and populate Cue related fields + return webm_dash_manifest_cues(s); +} + +static int webm_dash_manifest_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + return AVERROR_EOF; +} + AVInputFormat ff_matroska_demuxer = { .name = "matroska,webm", .long_name = NULL_IF_CONFIG_SMALL("Matroska / WebM"), @@ -2915,3 +3439,12 @@ AVInputFormat ff_matroska_demuxer = { .read_close = matroska_read_close, .read_seek = matroska_read_seek, }; + +AVInputFormat ff_webm_dash_manifest_demuxer = { + .name = "webm_dash_manifest", + .long_name = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"), + .priv_data_size = sizeof(MatroskaDemuxContext), + .read_header = webm_dash_manifest_read_header, + .read_packet = webm_dash_manifest_read_packet, + .read_close = matroska_read_close, +}; diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 21cf3336c..92d091f7c 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -32,9 +32,11 @@ #include "matroska.h" #include "riff.h" #include "subtitles.h" +#include "vorbiscomment.h" #include "wv.h" #include "libavutil/avstring.h" +#include "libavutil/channel_layout.h" #include "libavutil/dict.h" #include "libavutil/intfloat.h" #include "libavutil/intreadwrite.h" @@ -70,6 +72,7 @@ typedef struct mkv_seekhead { typedef struct { uint64_t pts; + int stream_idx; int tracknum; int64_t cluster_pos; ///< file offset of the cluster containing the block int64_t relative_pos; ///< relative offset from the position of the cluster containing the block @@ -85,6 +88,7 @@ typedef struct { typedef struct { int write_dts; int has_cue; + int64_t ts_offset; } mkv_track; #define MODE_MATROSKAv2 0x01 @@ -113,6 +117,8 @@ typedef struct MatroskaMuxContext { int cluster_size_limit; int64_t cues_pos; int64_t cluster_time_limit; + int is_dash; + int dash_track_number; uint32_t chapter_id_offset; int wrote_chapters; @@ -128,22 +134,21 @@ typedef struct MatroskaMuxContext { #define MAX_CUETRACKPOS_SIZE 42 /** per-cuepoint - 2 1-byte EBML IDs, 2 1-byte EBML sizes, 8-byte uint max */ -#define MAX_CUEPOINT_SIZE(num_tracks) 12 + MAX_CUETRACKPOS_SIZE*num_tracks +#define MAX_CUEPOINT_SIZE(num_tracks) 12 + MAX_CUETRACKPOS_SIZE * num_tracks /** Seek preroll value for opus */ #define OPUS_SEEK_PREROLL 80000000 - static int ebml_id_size(unsigned int id) { - return (av_log2(id+1)-1)/7+1; + return (av_log2(id + 1) - 1) / 7 + 1; } static void put_ebml_id(AVIOContext *pb, unsigned int id) { int i = ebml_id_size(id); while (i--) - avio_w8(pb, (uint8_t)(id >> (i*8))); + avio_w8(pb, (uint8_t)(id >> (i * 8))); } /** @@ -164,7 +169,8 @@ static void put_ebml_size_unknown(AVIOContext *pb, int bytes) static int ebml_num_size(uint64_t num) { int bytes = 1; - while ((num+1) >> bytes*7) bytes++; + while ((num + 1) >> bytes * 7) + bytes++; return bytes; } @@ -179,7 +185,7 @@ static void put_ebml_num(AVIOContext *pb, uint64_t num, int bytes) int i, needed_bytes = ebml_num_size(num); // sizes larger than this are currently undefined in EBML - av_assert0(num < (1ULL<<56)-1); + av_assert0(num < (1ULL << 56) - 1); if (bytes == 0) // don't care how many bytes are used, so use the min @@ -188,21 +194,22 @@ static void put_ebml_num(AVIOContext *pb, uint64_t num, int bytes) // that we need to use, so write unknown size. This shouldn't happen. av_assert0(bytes >= needed_bytes); - num |= 1ULL << bytes*7; + num |= 1ULL << bytes * 7; for (i = bytes - 1; i >= 0; i--) - avio_w8(pb, (uint8_t)(num >> i*8)); + avio_w8(pb, (uint8_t)(num >> i * 8)); } static void put_ebml_uint(AVIOContext *pb, unsigned int elementid, uint64_t val) { int i, bytes = 1; uint64_t tmp = val; - while (tmp>>=8) bytes++; + while (tmp >>= 8) + bytes++; put_ebml_id(pb, elementid); put_ebml_num(pb, bytes, 0); for (i = bytes - 1; i >= 0; i--) - avio_w8(pb, (uint8_t)(val >> i*8)); + avio_w8(pb, (uint8_t)(val >> i * 8)); } static void put_ebml_sint(AVIOContext *pb, unsigned int elementid, int64_t val) @@ -215,7 +222,7 @@ static void put_ebml_sint(AVIOContext *pb, unsigned int elementid, int64_t val) put_ebml_id(pb, elementid); put_ebml_num(pb, bytes, 0); for (i = bytes - 1; i >= 0; i--) - avio_w8(pb, (uint8_t)(val >> i*8)); + avio_w8(pb, (uint8_t)(val >> i * 8)); } static void put_ebml_float(AVIOContext *pb, unsigned int elementid, double val) @@ -233,7 +240,8 @@ static void put_ebml_binary(AVIOContext *pb, unsigned int elementid, avio_write(pb, buf, size); } -static void put_ebml_string(AVIOContext *pb, unsigned int elementid, const char *str) +static void put_ebml_string(AVIOContext *pb, unsigned int elementid, + const char *str) { put_ebml_binary(pb, elementid, str, strlen(str)); } @@ -255,18 +263,19 @@ static void put_ebml_void(AVIOContext *pb, uint64_t size) // size we need to reserve so 2 cases, we use 8 bytes to store the // size if possible, 1 byte otherwise if (size < 10) - put_ebml_num(pb, size-1, 0); + put_ebml_num(pb, size - 1, 0); else - put_ebml_num(pb, size-9, 8); + put_ebml_num(pb, size - 9, 8); ffio_fill(pb, 0, currentpos + size - avio_tell(pb)); } -static ebml_master start_ebml_master(AVIOContext *pb, unsigned int elementid, uint64_t expectedsize) +static ebml_master start_ebml_master(AVIOContext *pb, unsigned int elementid, + uint64_t expectedsize) { int bytes = expectedsize ? ebml_num_size(expectedsize) : 8; put_ebml_id(pb, elementid); put_ebml_size_unknown(pb, bytes); - return (ebml_master){ avio_tell(pb), bytes }; + return (ebml_master) {avio_tell(pb), bytes }; } static void end_ebml_master(AVIOContext *pb, ebml_master master) @@ -296,7 +305,8 @@ static void put_xiph_size(AVIOContext *pb, int size) * @param numelements The maximum number of elements that will be indexed * by this seek head, 0 if unlimited. */ -static mkv_seekhead * mkv_start_seekhead(AVIOContext *pb, int64_t segment_offset, int numelements) +static mkv_seekhead *mkv_start_seekhead(AVIOContext *pb, int64_t segment_offset, + int numelements) { mkv_seekhead *new_seekhead = av_mallocz(sizeof(mkv_seekhead)); if (new_seekhead == NULL) @@ -310,7 +320,7 @@ static mkv_seekhead * mkv_start_seekhead(AVIOContext *pb, int64_t segment_offset // and size, and 3 bytes to guarantee that an EBML void element // will fit afterwards new_seekhead->reserved_size = numelements * MAX_SEEKENTRY_SIZE + 13; - new_seekhead->max_entries = numelements; + new_seekhead->max_entries = numelements; put_ebml_void(pb, new_seekhead->reserved_size); } return new_seekhead; @@ -388,7 +398,7 @@ fail: return currentpos; } -static mkv_cues * mkv_start_cues(int64_t segment_offset) +static mkv_cues *mkv_start_cues(int64_t segment_offset) { mkv_cues *cues = av_mallocz(sizeof(mkv_cues)); if (cues == NULL) @@ -398,8 +408,8 @@ static mkv_cues * mkv_start_cues(int64_t segment_offset) return cues; } -static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t cluster_pos, int64_t relative_pos, - int64_t duration) +static int mkv_add_cuepoint(mkv_cues *cues, int stream, int tracknum, int64_t ts, + int64_t cluster_pos, int64_t relative_pos, int64_t duration) { mkv_cuepoint *entries = cues->entries; @@ -412,7 +422,8 @@ static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t clus cues->entries = entries; cues->entries[cues->num_entries].pts = ts; - cues->entries[cues->num_entries].tracknum = stream + 1; + cues->entries[cues->num_entries].stream_idx = stream; + cues->entries[cues->num_entries].tracknum = tracknum; cues->entries[cues->num_entries].cluster_pos = cluster_pos - cues->segment_offset; cues->entries[cues->num_entries].relative_pos = relative_pos; cues->entries[cues->num_entries++].duration = duration; @@ -420,8 +431,9 @@ static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t clus return 0; } -static int64_t mkv_write_cues(AVIOContext *pb, mkv_cues *cues, mkv_track *tracks, int num_tracks) +static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tracks, int num_tracks) { + AVIOContext *pb = s->pb; ebml_master cues_element; int64_t currentpos; int i, j; @@ -442,9 +454,9 @@ static int64_t mkv_write_cues(AVIOContext *pb, mkv_cues *cues, mkv_track *tracks for (j = 0; j < num_tracks; j++) tracks[j].has_cue = 0; for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) { - int tracknum = entry[j].tracknum - 1; + int tracknum = entry[j].stream_idx; av_assert0(tracknum>=0 && tracknumstreams[tracknum]->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) continue; tracks[tracknum].has_cue = 1; track_positions = start_ebml_master(pb, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE); @@ -500,13 +512,59 @@ static int put_wv_codecpriv(AVIOContext *pb, AVCodecContext *codec) return 0; } -static void get_aac_sample_rates(AVFormatContext *s, AVCodecContext *codec, int *sample_rate, int *output_sample_rate) +static int put_flac_codecpriv(AVFormatContext *s, + AVIOContext *pb, AVCodecContext *codec) +{ + 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, + !write_comment); + + if (ret < 0) + return ret; + + if (write_comment) { + const char *vendor = (s->flags & AVFMT_FLAG_BITEXACT) ? + "Lavf" : LIBAVFORMAT_IDENT; + AVDictionary *dict = NULL; + uint8_t buf[32], *data, *p; + int len; + + snprintf(buf, sizeof(buf), "0x%"PRIx64, codec->channel_layout); + av_dict_set(&dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0); + + len = ff_vorbiscomment_length(dict, vendor); + data = av_malloc(len + 4); + if (!data) { + av_dict_free(&dict); + return AVERROR(ENOMEM); + } + + data[0] = 0x84; + AV_WB24(data + 1, len); + + p = data + 4; + ff_vorbiscomment_write(&p, &dict, vendor); + + avio_write(pb, data, len + 4); + + av_freep(&data); + av_dict_free(&dict); + } + + return 0; +} + +static void get_aac_sample_rates(AVFormatContext *s, AVCodecContext *codec, + 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, "Error parsing AAC extradata, unable to determine samplerate.\n"); + av_log(s, AV_LOG_WARNING, + "Error parsing AAC extradata, unable to determine samplerate.\n"); return; } @@ -514,51 +572,72 @@ static void get_aac_sample_rates(AVFormatContext *s, AVCodecContext *codec, int *output_sample_rate = mp4ac.ext_sample_rate; } -static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecContext *codec, int native_id, int qt_id) +static int mkv_write_native_codecprivate(AVFormatContext *s, + AVCodecContext *codec, + AVIOContext *dyn_cp) +{ + switch (codec->codec_id) { + case AV_CODEC_ID_VORBIS: + case AV_CODEC_ID_THEORA: + return put_xiph_codecpriv(s, dyn_cp, codec); + case AV_CODEC_ID_FLAC: + return put_flac_codecpriv(s, dyn_cp, codec); + case AV_CODEC_ID_WAVPACK: + return put_wv_codecpriv(dyn_cp, codec); + case AV_CODEC_ID_H264: + return ff_isom_write_avcc(dyn_cp, codec->extradata, + codec->extradata_size); + case AV_CODEC_ID_HEVC: + return ff_isom_write_hvcc(dyn_cp, codec->extradata, + codec->extradata_size, 0); + case AV_CODEC_ID_ALAC: + if (codec->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); + break; + default: + if (codec->codec_id == AV_CODEC_ID_PRORES && + ff_codec_get_id(ff_codec_movvideo_tags, codec->codec_tag) == AV_CODEC_ID_PRORES) { + avio_wl32(dyn_cp, codec->codec_tag); + } else if (codec->extradata_size && codec->codec_id != AV_CODEC_ID_TTA) + avio_write(dyn_cp, codec->extradata, codec->extradata_size); + } + + return 0; +} + +static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, + AVCodecContext *codec, int native_id, + int qt_id) { AVIOContext *dyn_cp; uint8_t *codecpriv; int ret, codecpriv_size; ret = avio_open_dyn_buf(&dyn_cp); - if(ret < 0) + if (ret < 0) return ret; if (native_id) { - if (codec->codec_id == AV_CODEC_ID_VORBIS || codec->codec_id == AV_CODEC_ID_THEORA) - ret = put_xiph_codecpriv(s, dyn_cp, codec); - else if (codec->codec_id == AV_CODEC_ID_FLAC) - ret = ff_flac_write_header(dyn_cp, codec, 1); - else if (codec->codec_id == AV_CODEC_ID_WAVPACK) - ret = put_wv_codecpriv(dyn_cp, codec); - else if (codec->codec_id == AV_CODEC_ID_H264) - ret = ff_isom_write_avcc(dyn_cp, codec->extradata, codec->extradata_size); - else if (codec->codec_id == AV_CODEC_ID_HEVC) - ret = ff_isom_write_hvcc(dyn_cp, codec->extradata, codec->extradata_size, 0); - else if (codec->codec_id == AV_CODEC_ID_ALAC) { - if (codec->extradata_size < 36) { - av_log(s, AV_LOG_ERROR, - "Invalid extradata found, ALAC expects a 36-byte " - "QuickTime atom."); - ret = AVERROR_INVALIDDATA; - } else - avio_write(dyn_cp, codec->extradata + 12, - codec->extradata_size - 12); - } - else if (codec->extradata_size && codec->codec_id != AV_CODEC_ID_TTA) - avio_write(dyn_cp, codec->extradata, codec->extradata_size); + ret = mkv_write_native_codecprivate(s, codec, dyn_cp); } else if (codec->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); + codec->codec_tag = ff_codec_get_tag(ff_codec_movvideo_tags, + codec->codec_id); if (codec->extradata_size) { if ( ff_codec_get_id(ff_codec_movvideo_tags, codec->codec_tag) == codec->codec_id - && ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(codec->extradata+4)) != codec->codec_id + && ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(codec->extradata + 4)) != codec->codec_id ) { int i; avio_wb32(dyn_cp, 0x5a + codec->extradata_size); avio_wl32(dyn_cp, codec->codec_tag); - for(i=0; i<0x5a-8; i++) + for(i = 0; i < 0x5a - 8; i++) avio_w8(dyn_cp, 0); } avio_write(dyn_cp, codec->extradata, codec->extradata_size); @@ -569,7 +648,8 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo avcodec_get_name(codec->codec_id)); if (!codec->codec_tag) - codec->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id); + codec->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags, + codec->codec_id); if (!codec->codec_tag) { av_log(s, AV_LOG_ERROR, "No bmp codec tag found for codec %s\n", avcodec_get_name(codec->codec_id)); @@ -578,7 +658,6 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo ff_put_bmp_header(dyn_cp, codec, ff_codec_bmp_tags, 0, 0); } - } else if (codec->codec_type == AVMEDIA_TYPE_AUDIO) { unsigned int tag; tag = ff_codec_get_tag(ff_codec_wav_tags, codec->codec_id); @@ -590,25 +669,278 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo if (!codec->codec_tag) codec->codec_tag = tag; - ff_put_wav_header(dyn_cp, codec); + ff_put_wav_header(dyn_cp, codec, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX); } codecpriv_size = avio_close_dyn_buf(dyn_cp, &codecpriv); if (codecpriv_size) - put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv, codecpriv_size); + put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv, + codecpriv_size); av_free(codecpriv); return ret; } +static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, int st_mode, + int mode) +{ + if ((mode == MODE_WEBM && st_mode > 3 && st_mode != 11) + || st_mode >= MATROSKA_VIDEO_STEREO_MODE_COUNT) { + av_log(s, AV_LOG_ERROR, + "The specified stereo mode is not valid.\n"); + return AVERROR(EINVAL); + } else + put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, st_mode); + + return 0; +} + +static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, + int i, AVIOContext *pb, int default_stream_exists) +{ + AVStream *st = s->streams[i]; + AVCodecContext *codec = st->codec; + 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 output_sample_rate = 0; + int display_width_div = 1; + int display_height_div = 1; + int j, ret; + AVDictionaryEntry *tag; + + // 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) { + mkv->have_attachments = 1; + return 0; + } + + if (!bit_depth && codec->codec_id != AV_CODEC_ID_ADPCM_G726) + bit_depth = av_get_bytes_per_sample(codec->sample_fmt) << 3; + if (!bit_depth) + bit_depth = codec->bits_per_coded_sample; + + if (codec->codec_id == AV_CODEC_ID_AAC) + get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate); + + track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0); + put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER, + mkv->is_dash ? mkv->dash_track_number : i + 1); + put_ebml_uint (pb, MATROSKA_ID_TRACKUID, + mkv->is_dash ? mkv->dash_track_number : i + 1); + put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet) + + if ((tag = av_dict_get(st->metadata, "title", NULL, 0))) + put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value); + tag = av_dict_get(st->metadata, "language", NULL, 0); + if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) { + put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag ? tag->value:"und"); + } else if (tag && tag->value) { + put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag->value); + } + + // The default value for TRACKFLAGDEFAULT is 1, so add element + // if we need to clear it. + if (default_stream_exists && !(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, 1); + + if (mkv->mode == MODE_WEBM && codec->codec_id == AV_CODEC_ID_WEBVTT) { + const char *codec_id; + if (st->disposition & AV_DISPOSITION_CAPTIONS) { + codec_id = "D_WEBVTT/CAPTIONS"; + native_id = MATROSKA_TRACK_TYPE_SUBTITLE; + } else if (st->disposition & AV_DISPOSITION_DESCRIPTIONS) { + codec_id = "D_WEBVTT/DESCRIPTIONS"; + native_id = MATROSKA_TRACK_TYPE_METADATA; + } else if (st->disposition & AV_DISPOSITION_METADATA) { + codec_id = "D_WEBVTT/METADATA"; + native_id = MATROSKA_TRACK_TYPE_METADATA; + } else { + codec_id = "D_WEBVTT/SUBTITLES"; + native_id = MATROSKA_TRACK_TYPE_SUBTITLE; + } + put_ebml_string(pb, MATROSKA_ID_CODECID, codec_id); + } else { + // 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) { + put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str); + native_id = 1; + break; + } + } + } + + if (codec->codec_type == AVMEDIA_TYPE_AUDIO && codec->delay && codec->codec_id == AV_CODEC_ID_OPUS) { +// mkv->tracks[i].ts_offset = av_rescale_q(codec->delay, +// (AVRational){ 1, codec->sample_rate }, +// st->time_base); + + put_ebml_uint(pb, MATROSKA_ID_CODECDELAY, + av_rescale_q(codec->delay, (AVRational){ 1, codec->sample_rate }, + (AVRational){ 1, 1000000000 })); + } + if (codec->codec_id == AV_CODEC_ID_OPUS) { + put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL); + } + + 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 || + codec->codec_id == AV_CODEC_ID_WEBVTT)) { + av_log(s, AV_LOG_ERROR, + "Only VP8 or VP9 video and Vorbis or Opus audio and WebVTT subtitles are supported for WebM.\n"); + return AVERROR(EINVAL); + } + + switch (codec->codec_type) { + case AVMEDIA_TYPE_VIDEO: + put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO); + + if( st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0 + && 1.0/av_q2d(st->avg_frame_rate) > av_q2d(codec->time_base)) + put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1E9 / av_q2d(st->avg_frame_rate)); + else + put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, av_q2d(codec->time_base)*1E9); + + 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)) + qt_id = 1; + + if (qt_id) + put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME"); + else if (!native_id) { + // if there is no mkv-specific codec ID, use VFW mode + put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC"); + mkv->tracks[i].write_dts = 1; + } + + 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); + + if ((tag = av_dict_get(st->metadata, "stereo_mode", NULL, 0)) || + (tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) { + int st_mode = MATROSKA_VIDEO_STEREO_MODE_COUNT; + + for (j=0; jvalue, ff_matroska_video_stereo_mode[j])){ + st_mode = j; + break; + } + + if (mkv_write_stereo_mode(s, pb, st_mode, mkv->mode) < 0) + return AVERROR(EINVAL); + + switch (st_mode) { + case 1: + case 8: + case 9: + case 11: + display_width_div = 2; + break; + case 2: + case 3: + case 6: + case 7: + display_height_div = 2; + break; + } + } + + if ((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) || + (tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0)) || + (codec->pix_fmt == AV_PIX_FMT_YUVA420P)) { + put_ebml_uint(pb, MATROSKA_ID_VIDEOALPHAMODE, 1); + } + + if (st->sample_aspect_ratio.num) { + int64_t d_width = av_rescale(codec->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); + if (d_width > INT_MAX) { + av_log(s, AV_LOG_ERROR, "Overflow in display width\n"); + return AVERROR(EINVAL); + } + put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width / display_width_div); + put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div); + } else if (display_width_div != 1 || display_height_div != 1) { + put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , codec->width / display_width_div); + put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div); + } + + if (codec->codec_id == AV_CODEC_ID_RAWVIDEO) { + uint32_t color_space = av_le2ne32(codec->codec_tag); + put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space)); + } + end_ebml_master(pb, subinfo); + break; + + case AVMEDIA_TYPE_AUDIO: + put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO); + + if (!native_id) + // no mkv-specific ID, use ACM mode + 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_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate); + if (output_sample_rate) + put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); + if (bit_depth) + put_ebml_uint(pb, MATROSKA_ID_AUDIOBITDEPTH, bit_depth); + end_ebml_master(pb, subinfo); + break; + + case AVMEDIA_TYPE_SUBTITLE: + if (!native_id) { + av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", codec->codec_id); + return AVERROR(ENOSYS); + } + + if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) + native_id = MATROSKA_TRACK_TYPE_SUBTITLE; + + put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, native_id); + break; + default: + av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.\n"); + return AVERROR(EINVAL); + } + + if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) { + ret = mkv_write_codecprivate(s, pb, codec, native_id, qt_id); + if (ret < 0) + return ret; + } + + end_ebml_master(pb, track); + + return 0; +} + static int mkv_write_tracks(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; AVIOContext *pb = s->pb; ebml_master tracks; - int i, j, ret, default_stream_exists = 0; + int i, ret, default_stream_exists = 0; ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_TRACKS, avio_tell(pb)); - if (ret < 0) return ret; + if (ret < 0) + return ret; tracks = start_ebml_master(pb, MATROSKA_ID_TRACKS, 0); for (i = 0; i < s->nb_streams; i++) { @@ -616,232 +948,9 @@ static int mkv_write_tracks(AVFormatContext *s) default_stream_exists |= st->disposition & AV_DISPOSITION_DEFAULT; } for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - AVCodecContext *codec = st->codec; - 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 output_sample_rate = 0; - int display_width_div = 1; - int display_height_div = 1; - AVDictionaryEntry *tag; - - if (codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) { - mkv->have_attachments = 1; - continue; - } - - if (!bit_depth && codec->codec_id != AV_CODEC_ID_ADPCM_G726) - bit_depth = av_get_bytes_per_sample(codec->sample_fmt) << 3; - if (!bit_depth) - bit_depth = codec->bits_per_coded_sample; - - if (codec->codec_id == AV_CODEC_ID_AAC) - get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate); - - track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0); - put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER , i + 1); - put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i + 1); - put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet) - - if ((tag = av_dict_get(st->metadata, "title", NULL, 0))) - put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value); - tag = av_dict_get(st->metadata, "language", NULL, 0); - if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) { - put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag ? tag->value:"und"); - } else if (tag && tag->value) { - put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag->value); - } - - // The default value for TRACKFLAGDEFAULT is 1, so add element - // if we need to clear it. - if (default_stream_exists && !(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, 1); - - if (mkv->mode == MODE_WEBM && codec->codec_id == AV_CODEC_ID_WEBVTT) { - const char *codec_id; - if (st->disposition & AV_DISPOSITION_CAPTIONS) { - codec_id = "D_WEBVTT/CAPTIONS"; - native_id = MATROSKA_TRACK_TYPE_SUBTITLE; - } else if (st->disposition & AV_DISPOSITION_DESCRIPTIONS) { - codec_id = "D_WEBVTT/DESCRIPTIONS"; - native_id = MATROSKA_TRACK_TYPE_METADATA; - } else if (st->disposition & AV_DISPOSITION_METADATA) { - codec_id = "D_WEBVTT/METADATA"; - native_id = MATROSKA_TRACK_TYPE_METADATA; - } else { - codec_id = "D_WEBVTT/SUBTITLES"; - native_id = MATROSKA_TRACK_TYPE_SUBTITLE; - } - put_ebml_string(pb, MATROSKA_ID_CODECID, codec_id); - } else { - // 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) { - put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str); - native_id = 1; - break; - } - } - } - - if (codec->codec_id == AV_CODEC_ID_OPUS) { - uint64_t codec_delay =av_rescale_q(codec->delay, - (AVRational){1, codec->sample_rate}, - (AVRational){1, 1000000000}); - put_ebml_uint(pb, MATROSKA_ID_CODECDELAY, codec_delay); - put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL); - - } - - 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->strict_std_compliance <= FF_COMPLIANCE_EXPERIMENTAL)) || - codec->codec_id == AV_CODEC_ID_VORBIS || - codec->codec_id == AV_CODEC_ID_WEBVTT)) { - av_log(s, AV_LOG_ERROR, - "Only VP8,VP9 video and Vorbis,Opus(experimental, use -strict -2) audio and WebVTT subtitles are supported for WebM.\n"); - return AVERROR(EINVAL); - } - - switch (codec->codec_type) { - case AVMEDIA_TYPE_VIDEO: - put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO); - if(st->avg_frame_rate.num && st->avg_frame_rate.den && 1.0/av_q2d(st->avg_frame_rate) > av_q2d(codec->time_base)) - put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1E9/av_q2d(st->avg_frame_rate)); - else - put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, av_q2d(codec->time_base)*1E9); - - 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)) - qt_id = 1; - - if (qt_id) - put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME"); - else if (!native_id) { - // if there is no mkv-specific codec ID, use VFW mode - put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC"); - mkv->tracks[i].write_dts = 1; - } - - 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); - - if ((tag = av_dict_get(st->metadata, "stereo_mode", NULL, 0)) || - (tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) { - // save stereo mode flag - uint64_t st_mode = MATROSKA_VIDEO_STEREO_MODE_COUNT; - - for (j=0; jvalue, ff_matroska_video_stereo_mode[j])){ - st_mode = j; - break; - } - - if ((mkv->mode == MODE_WEBM && st_mode > 3 && st_mode != 11) - || st_mode >= MATROSKA_VIDEO_STEREO_MODE_COUNT) { - av_log(s, AV_LOG_ERROR, - "The specified stereo mode is not valid.\n"); - return AVERROR(EINVAL); - } else - put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, st_mode); - - switch (st_mode) { - case 1: - case 8: - case 9: - case 11: - display_width_div = 2; - break; - case 2: - case 3: - case 6: - case 7: - display_height_div = 2; - break; - } - } - - if ((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) || - (tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0)) || - (codec->pix_fmt == AV_PIX_FMT_YUVA420P)) { - put_ebml_uint(pb, MATROSKA_ID_VIDEOALPHAMODE, 1); - } - - if (st->sample_aspect_ratio.num) { - int64_t d_width = av_rescale(codec->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); - if (d_width > INT_MAX) { - av_log(s, AV_LOG_ERROR, "Overflow in display width\n"); - return AVERROR(EINVAL); - } - put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width / display_width_div); - put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div); - } else if (display_width_div != 1 || display_height_div != 1) { - put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , codec->width / display_width_div); - put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div); - } - - if (codec->codec_id == AV_CODEC_ID_RAWVIDEO) { - uint32_t color_space = av_le2ne32(codec->codec_tag); - put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space)); - } - end_ebml_master(pb, subinfo); - break; - - case AVMEDIA_TYPE_AUDIO: - put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO); - - if (!native_id) - // no mkv-specific ID, use ACM mode - 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_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate); - if (output_sample_rate) - put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); - if (bit_depth) - put_ebml_uint(pb, MATROSKA_ID_AUDIOBITDEPTH, bit_depth); - end_ebml_master(pb, subinfo); - break; - - case AVMEDIA_TYPE_SUBTITLE: - if (!native_id) { - av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", codec->codec_id); - return AVERROR(ENOSYS); - } - - if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) - native_id = MATROSKA_TRACK_TYPE_SUBTITLE; - - put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, native_id); - break; - default: - av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.\n"); - return AVERROR(EINVAL); - } - - if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) { - ret = mkv_write_codecprivate(s, pb, codec, native_id, qt_id); - if (ret < 0) return ret; - } - - end_ebml_master(pb, track); - - // ms precision is the de-facto standard timescale for mkv files - avpriv_set_pts_info(st, 64, 1, 1000); + ret = mkv_write_track(s, mkv, i, pb, default_stream_exists); + if (ret < 0) + return ret; } end_ebml_master(pb, tracks); return 0; @@ -1056,7 +1165,7 @@ static int mkv_write_attachments(AVFormatContext *s) return AVERROR(EINVAL); } - if (st->codec->flags & CODEC_FLAG_BITEXACT) { + if (s->flags & AVFMT_FLAG_BITEXACT) { struct AVSHA *sha = av_sha_alloc(); uint8_t digest[20]; if (!sha) @@ -1090,8 +1199,10 @@ static int mkv_write_header(AVFormatContext *s) AVDictionaryEntry *tag; int ret, i, version = 2; - if (!strcmp(s->oformat->name, "webm")) mkv->mode = MODE_WEBM; - else mkv->mode = MODE_MATROSKAv2; + if (!strcmp(s->oformat->name, "webm")) + mkv->mode = MODE_WEBM; + else + mkv->mode = MODE_MATROSKAv2; if (s->avoid_negative_ts < 0) s->avoid_negative_ts = 1; @@ -1119,7 +1230,7 @@ static int mkv_write_header(AVFormatContext *s) version = 4; } - mkv->tracks = av_mallocz(s->nb_streams * sizeof(*mkv->tracks)); + mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks)); if (!mkv->tracks) return AVERROR(ENOMEM); @@ -1152,7 +1263,7 @@ static int mkv_write_header(AVFormatContext *s) put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000); if ((tag = av_dict_get(s->metadata, "title", NULL, 0))) put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value); - if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { + if (!(s->flags & AVFMT_FLAG_BITEXACT)) { uint32_t segment_uid[4]; AVLFG lfg; @@ -1161,7 +1272,7 @@ static int mkv_write_header(AVFormatContext *s) for (i = 0; i < 4; i++) segment_uid[i] = av_lfg_get(&lfg); - put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , LIBAVFORMAT_IDENT); + put_ebml_string(pb, MATROSKA_ID_MUXINGAPP, LIBAVFORMAT_IDENT); if ((tag = av_dict_get(s->metadata, "encoding_tool", NULL, 0))) put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, tag->value); else @@ -1188,20 +1299,24 @@ static int mkv_write_header(AVFormatContext *s) end_ebml_master(pb, segment_info); ret = mkv_write_tracks(s); - if (ret < 0) return ret; + if (ret < 0) + return ret; for (i = 0; i < s->nb_chapters; i++) mkv->chapter_id_offset = FFMAX(mkv->chapter_id_offset, 1LL - s->chapters[i]->id); if (mkv->mode != MODE_WEBM) { ret = mkv_write_chapters(s); - if (ret < 0) return ret; + if (ret < 0) + return ret; ret = mkv_write_tags(s); - if (ret < 0) return ret; + if (ret < 0) + return ret; ret = mkv_write_attachments(s); - if (ret < 0) return ret; + if (ret < 0) + return ret; } if (!s->pb->seekable) @@ -1258,55 +1373,60 @@ 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; - start = 3600000LL*sh + 60000LL*sm + 1000LL*ss + 10LL*sc; - end = 3600000LL*eh + 60000LL*em + 1000LL*es + 10LL*ec; + start = 3600000LL * sh + 60000LL * sm + 1000LL * ss + 10LL * sc; + end = 3600000LL * eh + 60000LL * em + 1000LL * es + 10LL * ec; return end - start; } #if FF_API_ASS_SSA -static int mkv_write_ass_blocks(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt) +/* Writes the contents of pkt to a block, using the data starting at *datap. + * If pkt corresponds to more than one block, this writes the contents of the first block + * (starting from *datap) and updates *datap so it points to the beginning of the data + * corresponding to the next block. + */ +static int mkv_write_ass_block(AVFormatContext *s, AVIOContext *pb, + AVPacket *pkt, uint8_t **datap) { MatroskaMuxContext *mkv = s->priv_data; - int i, layer = 0, max_duration = 0, size, line_size, data_size = pkt->size; - uint8_t *start, *end, *data = pkt->data; + int i, layer = 0, size, line_size, data_size = pkt->size - (*datap - pkt->data); + uint8_t *start, *end, *data = *datap; ebml_master blockgroup; char buffer[2048]; - while (data_size) { int duration = ass_get_duration(data); - max_duration = FFMAX(duration, max_duration); - end = memchr(data, '\n', data_size); - size = line_size = end ? end-data+1 : data_size; - size -= end ? (end[-1]=='\r')+1 : 0; - start = data; - for (i=0; i<3; i++, start++) - if (!(start = memchr(start, ',', size-(start-data)))) - return max_duration; + end = memchr(data, '\n', data_size); + size = line_size = end ? end - data + 1 : data_size; + size -= end ? (end[-1] == '\r') + 1 : 0; + start = data; + for (i = 0; i < 3; i++, start++) + if (!(start = memchr(start, ',', size - (start - data)))) + return duration; size -= start - data; sscanf(data, "Dialogue: %d,", &layer); - i = snprintf(buffer, sizeof(buffer), "%"PRId64",%d,", + i = snprintf(buffer, sizeof(buffer), "%" PRId64 ",%d,", s->streams[pkt->stream_index]->nb_frames, layer); - size = FFMIN(i+size, sizeof(buffer)); - memcpy(buffer+i, start, size-i); + size = FFMIN(i + size, sizeof(buffer)); + memcpy(buffer + i, start, size - i); - av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, " + av_log(s, AV_LOG_DEBUG, + "Writing block at offset %" PRIu64 ", size %d, " "pts %" PRId64 ", duration %d\n", avio_tell(pb), size, pkt->pts, duration); - blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(size)); + blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, + mkv_blockgroup_size(size)); put_ebml_id(pb, MATROSKA_ID_BLOCK); - put_ebml_num(pb, size+4, 0); - avio_w8(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 + put_ebml_num(pb, size + 4, 0); + // this assumes stream_index is less than 126 + avio_w8(pb, 0x80 | (pkt->stream_index + 1)); avio_wb16(pb, pkt->pts - mkv->cluster_pts); avio_w8(pb, 0); avio_write(pb, buffer, size); put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration); end_ebml_master(pb, blockgroup); - data += line_size; - data_size -= line_size; - } + *datap += line_size; - return max_duration; + return duration; } #endif @@ -1397,7 +1517,7 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, if (codec->codec_id == AV_CODEC_ID_PRORES) { /* Matroska specification requires to remove the first QuickTime atom */ - size -= 8; + size -= 8; offset = 8; } @@ -1426,8 +1546,9 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, } put_ebml_id(pb, blockid); - put_ebml_num(pb, size+4, 0); - avio_w8(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 + put_ebml_num(pb, size + 4, 0); + // this assumes stream_index is less than 126 + avio_w8(pb, 0x80 | (mkv->is_dash ? mkv->dash_track_number : (pkt->stream_index + 1))); avio_wb16(pb, ts - mkv->cluster_pts); avio_w8(pb, flags); avio_write(pb, data + offset, size); @@ -1457,14 +1578,19 @@ static int srt_get_duration(uint8_t **buf) { int i, duration = 0; - for (i=0; i<2 && !duration; i++) { + for (i = 0; i < 2 && !duration; i++) { int s_hour, s_min, s_sec, s_hsec, e_hour, e_min, e_sec, e_hsec; if (sscanf(*buf, "%d:%2d:%2d%*1[,.]%3d --> %d:%2d:%2d%*1[,.]%3d", &s_hour, &s_min, &s_sec, &s_hsec, &e_hour, &e_min, &e_sec, &e_hsec) == 8) { - s_min += 60*s_hour; e_min += 60*e_hour; - s_sec += 60*s_min; e_sec += 60*e_min; - s_hsec += 1000*s_sec; e_hsec += 1000*e_sec; + s_min += 60 * s_hour; + e_min += 60 * e_hour; + s_sec += 60 * s_min; + + e_sec += 60 * e_min; + s_hsec += 1000 * s_sec; + e_hsec += 1000 * e_sec; + duration = e_hsec - s_hsec; } *buf += ff_subtitles_next_line(*buf); @@ -1472,7 +1598,8 @@ static int srt_get_duration(uint8_t **buf) return duration; } -static int mkv_write_srt_blocks(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt) +static int mkv_write_srt_blocks(AVFormatContext *s, AVIOContext *pb, + AVPacket *pkt) { ebml_master blockgroup; AVPacket pkt2 = *pkt; @@ -1514,7 +1641,7 @@ static int mkv_write_vtt_blocks(AVFormatContext *s, AVIOContext *pb, AVPacket *p blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(size)); put_ebml_id(pb, MATROSKA_ID_BLOCK); - put_ebml_num(pb, size+4, 0); + put_ebml_num(pb, size + 4, 0); avio_w8(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 avio_wb16(pb, ts - mkv->cluster_pts); avio_w8(pb, flags); @@ -1541,21 +1668,24 @@ static void mkv_flush_dynbuf(AVFormatContext *s) mkv->dyn_bc = NULL; } -static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) +static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_cue) { MatroskaMuxContext *mkv = s->priv_data; - AVIOContext *pb = s->pb; - AVCodecContext *codec = s->streams[pkt->stream_index]->codec; - int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY); - int duration = pkt->duration; + AVIOContext *pb = s->pb; + AVCodecContext *codec = s->streams[pkt->stream_index]->codec; + int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY); + int duration = pkt->duration; int ret; int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; int64_t relative_packet_pos; + uint8_t *data_offset = pkt->data; + int dash_tracknum = mkv->is_dash ? mkv->dash_track_number : pkt->stream_index + 1; if (ts == AV_NOPTS_VALUE) { av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n"); return AVERROR(EINVAL); } + ts += mkv->tracks[pkt->stream_index].ts_offset; if (!s->pb->seekable) { if (!mkv->dyn_bc) { @@ -1569,7 +1699,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) if (mkv->cluster_pos == -1) { mkv->cluster_pos = avio_tell(s->pb); - mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0); + mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0); put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts)); mkv->cluster_pts = FFMAX(0, ts); } @@ -1578,16 +1708,27 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) if (codec->codec_type != AVMEDIA_TYPE_SUBTITLE) { mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7); + if (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe || add_cue) { + ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, mkv->cluster_pos, relative_packet_pos, -1); + if (ret < 0) return ret; + } #if FF_API_ASS_SSA } else if (codec->codec_id == AV_CODEC_ID_SSA) { - duration = mkv_write_ass_blocks(s, pb, pkt); + while (data_offset < pkt->data + pkt->size) { + duration = mkv_write_ass_block(s, pb, pkt, &data_offset); + ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, mkv->cluster_pos, relative_packet_pos, duration); + if (ret < 0) return ret; + relative_packet_pos = avio_tell(s->pb) - mkv->cluster.pos; + } #endif - } else if (codec->codec_id == AV_CODEC_ID_SRT) { + } else { + if (codec->codec_id == AV_CODEC_ID_SRT) { duration = mkv_write_srt_blocks(s, pb, pkt); } else if (codec->codec_id == AV_CODEC_ID_WEBVTT) { duration = mkv_write_vtt_blocks(s, pb, pkt); } else { - ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(pkt->size)); + ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, + mkv_blockgroup_size(pkt->size)); /* For backward compatibility, prefer convergence_duration. */ if (pkt->convergence_duration > 0) { duration = pkt->convergence_duration; @@ -1597,10 +1738,10 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) end_ebml_master(pb, blockgroup); } - if ((codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe) || codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { - ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, ts, mkv->cluster_pos, relative_packet_pos, - codec->codec_type == AVMEDIA_TYPE_SUBTITLE ? duration : -1); - if (ret < 0) return ret; + ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, + mkv->cluster_pos, relative_packet_pos, duration); + if (ret < 0) + return ret; } mkv->duration = FFMAX(mkv->duration, ts + duration); @@ -1616,11 +1757,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) int64_t cluster_time; AVIOContext *pb; int ret; + int start_new_cluster; if (mkv->tracks[pkt->stream_index].write_dts) cluster_time = pkt->dts - mkv->cluster_pts; else cluster_time = pkt->pts - mkv->cluster_pts; + cluster_time += mkv->tracks[pkt->stream_index].ts_offset; // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or // after 4k and on a keyframe @@ -1632,13 +1775,29 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) cluster_size = avio_tell(pb); } - if (mkv->cluster_pos != -1 && - (cluster_size > mkv->cluster_size_limit || - cluster_time > mkv->cluster_time_limit || - (codec_type == AVMEDIA_TYPE_VIDEO && keyframe && - cluster_size > 4 * 1024))) { - av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64 - " bytes, pts %" PRIu64 "dts %" PRIu64 "\n", + if (mkv->is_dash && codec_type == AVMEDIA_TYPE_VIDEO) { + // WebM DASH specification states that the first block of every cluster + // has to be a key frame. So for DASH video, we only create a cluster + // on seeing key frames. + start_new_cluster = keyframe; + } else if (mkv->is_dash && codec_type == AVMEDIA_TYPE_AUDIO && + cluster_time > mkv->cluster_time_limit) { + // For DASH audio, we create a Cluster based on cluster_time_limit + start_new_cluster = 1; + } else if (!mkv->is_dash && + (cluster_size > mkv->cluster_size_limit || + cluster_time > mkv->cluster_time_limit || + (codec_type == AVMEDIA_TYPE_VIDEO && keyframe && + cluster_size > 4 * 1024))) { + start_new_cluster = 1; + } else { + start_new_cluster = 0; + } + + if (mkv->cluster_pos != -1 && start_new_cluster) { + av_log(s, AV_LOG_DEBUG, + "Starting new cluster at offset %" PRIu64 " bytes, " + "pts %" PRIu64 "dts %" PRIu64 "\n", avio_tell(pb), pkt->pts, pkt->dts); end_ebml_master(pb, mkv->cluster); mkv->cluster_pos = -1; @@ -1649,10 +1808,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) // 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); + // for DASH audio, a CuePoint has to be added when there is a new cluster. + ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt, + mkv->is_dash ? start_new_cluster : 0); av_free_packet(&mkv->cur_audio_pkt); if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret); + av_log(s, AV_LOG_ERROR, + "Could not write cached audio packet ret:%d\n", ret); return ret; } } @@ -1666,11 +1828,11 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) ret = mkv->cur_audio_pkt.buf ? 0 : AVERROR(ENOMEM); } else ret = av_dup_packet(&mkv->cur_audio_pkt); - if (mkv->cur_audio_pkt.side_data_elems > 0) { - ret = av_copy_packet_side_data(&mkv->cur_audio_pkt, &mkv->cur_audio_pkt); - } + if (mkv->cur_audio_pkt.side_data_elems > 0) { + ret = av_copy_packet_side_data(&mkv->cur_audio_pkt, &mkv->cur_audio_pkt); + } } else - ret = mkv_write_packet_internal(s, pkt); + ret = mkv_write_packet_internal(s, pkt, 0); return ret; } @@ -1684,8 +1846,9 @@ static int mkv_write_flush_packet(AVFormatContext *s, AVPacket *pkt) pb = mkv->dyn_bc; if (!pkt) { if (mkv->cluster_pos != -1) { - av_log(s, AV_LOG_DEBUG, "Flushing cluster at offset %" PRIu64 - " bytes\n", avio_tell(pb)); + av_log(s, AV_LOG_DEBUG, + "Flushing cluster at offset %" PRIu64 " bytes\n", + avio_tell(pb)); end_ebml_master(pb, mkv->cluster); mkv->cluster_pos = -1; if (mkv->dyn_bc) @@ -1706,10 +1869,11 @@ 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); + ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt, 0); av_free_packet(&mkv->cur_audio_pkt); if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret); + av_log(s, AV_LOG_ERROR, + "Could not write cached audio packet ret:%d\n", ret); return ret; } } @@ -1723,7 +1887,8 @@ static int mkv_write_trailer(AVFormatContext *s) if (mkv->mode != MODE_WEBM) { ret = mkv_write_chapters(s); - if (ret < 0) return ret; + if (ret < 0) + return ret; } if (pb->seekable) { @@ -1734,25 +1899,29 @@ static int mkv_write_trailer(AVFormatContext *s) currentpos = avio_tell(pb); avio_seek(pb, mkv->cues_pos, SEEK_SET); - cuespos = mkv_write_cues(pb, mkv->cues, mkv->tracks, s->nb_streams); + cuespos = mkv_write_cues(s, mkv->cues, mkv->tracks, s->nb_streams); cues_end = avio_tell(pb); if (cues_end > cuespos + mkv->reserve_cues_space) { - av_log(s, AV_LOG_ERROR, "Insufficient space reserved for cues: %d " - "(needed: %"PRId64").\n", mkv->reserve_cues_space, - cues_end - cuespos); + av_log(s, AV_LOG_ERROR, + "Insufficient space reserved for cues: %d " + "(needed: %" PRId64 ").\n", + mkv->reserve_cues_space, cues_end - cuespos); return AVERROR(EINVAL); } if (cues_end < cuespos + mkv->reserve_cues_space) - put_ebml_void(pb, mkv->reserve_cues_space - (cues_end - cuespos)); + put_ebml_void(pb, mkv->reserve_cues_space - + (cues_end - cuespos)); avio_seek(pb, currentpos, SEEK_SET); } else { - cuespos = mkv_write_cues(pb, mkv->cues, mkv->tracks, s->nb_streams); + cuespos = mkv_write_cues(s, mkv->cues, mkv->tracks, s->nb_streams); } - ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES, cuespos); - if (ret < 0) return ret; + ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES, + cuespos); + if (ret < 0) + return ret; } mkv_write_seekhead(pb, mkv->main_seekhead); @@ -1781,8 +1950,9 @@ static int mkv_query_codec(enum AVCodecID codec_id, int std_compliance) if (ff_mkv_codec_tags[i].id == codec_id) return 1; - if (std_compliance < FF_COMPLIANCE_NORMAL) { // mkv theoretically supports any - enum AVMediaType type = avcodec_get_type(codec_id); // video/audio through VFW/ACM + if (std_compliance < FF_COMPLIANCE_NORMAL) { + enum AVMediaType type = avcodec_get_type(codec_id); + // mkv theoretically supports any video/audio through VFW/ACM if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) return 1; } @@ -1821,6 +1991,8 @@ static const AVOption options[] = { { "reserve_index_space", "Reserve a given amount of space (in bytes) at the beginning of the file for the index (cues).", OFFSET(reserve_cues_space), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, { "cluster_size_limit", "Store at most the provided amount of bytes in a cluster. ", OFFSET(cluster_size_limit), AV_OPT_TYPE_INT , { .i64 = -1 }, -1, INT_MAX, FLAGS }, { "cluster_time_limit", "Store at most the provided number of milliseconds in a cluster.", OFFSET(cluster_time_limit), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, FLAGS }, + { "dash", "Create a WebM file conforming to WebM DASH specification", OFFSET(is_dash), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, + { "dash_track_number", "Track number for the DASH stream", OFFSET(dash_track_number), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 127, FLAGS }, { NULL }, }; diff --git a/libavformat/microdvddec.c b/libavformat/microdvddec.c index 7b49e4397..49d2b6819 100644 --- a/libavformat/microdvddec.c +++ b/libavformat/microdvddec.c @@ -24,12 +24,15 @@ #include "internal.h" #include "subtitles.h" #include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" #define MAX_LINESIZE 2048 typedef struct { + const AVClass *class; FFDemuxSubtitlesQueue q; + AVRational frame_rate; } MicroDVDContext; @@ -71,22 +74,30 @@ static int get_duration(const char *buf) return -1; } +static const char *bom = "\xEF\xBB\xBF"; + static int microdvd_read_header(AVFormatContext *s) { AVRational pts_info = (AVRational){ 2997, 125 }; /* default: 23.976 fps */ MicroDVDContext *microdvd = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); int i = 0; - char line[MAX_LINESIZE]; + char line_buf[MAX_LINESIZE]; + int has_real_fps = 0; if (!st) return AVERROR(ENOMEM); while (!url_feof(s->pb)) { - char *p = line; + char *p; AVPacket *sub; int64_t pos = avio_tell(s->pb); - int len = ff_get_line(s->pb, line, sizeof(line)); + int len = ff_get_line(s->pb, line_buf, sizeof(line_buf)); + char *line = line_buf; + + if (!strncmp(line, bom, 3)) + line += 3; + p = line; if (!len) break; @@ -98,8 +109,10 @@ static int microdvd_read_header(AVFormatContext *s) if ((sscanf(line, "{%d}{}%6lf", &frame, &fps) == 2 || sscanf(line, "{%d}{%*d}%6lf", &frame, &fps) == 2) - && frame <= 1 && fps > 3 && fps < 100) + && frame <= 1 && fps > 3 && fps < 100) { pts_info = av_d2q(fps, 100000); + has_real_fps = 1; + } if (!st->codec->extradata && sscanf(line, "{DEFAULT}{}%c", &c) == 1) { st->codec->extradata = av_strdup(line + 11); if (!st->codec->extradata) @@ -128,6 +141,13 @@ static int microdvd_read_header(AVFormatContext *s) sub->duration = get_duration(line); } ff_subtitles_queue_finalize(µdvd->q); + if (has_real_fps) { + /* export the FPS info only if set in the file */ + microdvd->frame_rate = pts_info; + } else if (microdvd->frame_rate.num) { + /* fallback on user specified frame rate */ + pts_info = microdvd->frame_rate; + } avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_MICRODVD; @@ -155,6 +175,21 @@ static int microdvd_read_close(AVFormatContext *s) return 0; } + +#define OFFSET(x) offsetof(MicroDVDContext, x) +#define SD AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_DECODING_PARAM +static const AVOption microdvd_options[] = { + { "subfps", "set the movie frame rate fallback", OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, SD }, + { NULL } +}; + +static const AVClass microdvd_class = { + .class_name = "microdvddec", + .item_name = av_default_item_name, + .option = microdvd_options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVInputFormat ff_microdvd_demuxer = { .name = "microdvd", .long_name = NULL_IF_CONFIG_SMALL("MicroDVD subtitle format"), @@ -164,4 +199,5 @@ AVInputFormat ff_microdvd_demuxer = { .read_packet = microdvd_read_packet, .read_seek2 = microdvd_read_seek, .read_close = microdvd_read_close, + .priv_class = µdvd_class, }; diff --git a/libavformat/mlvdec.c b/libavformat/mlvdec.c new file mode 100644 index 000000000..a980ed621 --- /dev/null +++ b/libavformat/mlvdec.c @@ -0,0 +1,471 @@ +/* + * Magic Lantern Video (MLV) demuxer + * Copyright (c) 2014 Peter Ross + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Magic Lantern Video (MLV) demuxer + */ + +#include "libavutil/eval.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/rational.h" +#include "avformat.h" +#include "internal.h" +#include "riff.h" + +#define MLV_VERSION "v2.0" + +#define MLV_VIDEO_CLASS_RAW 1 +#define MLV_VIDEO_CLASS_YUV 2 +#define MLV_VIDEO_CLASS_JPEG 3 +#define MLV_VIDEO_CLASS_H264 4 + +#define MLV_AUDIO_CLASS_WAV 1 + +#define MLV_CLASS_FLAG_DELTA 0x40 +#define MLV_CLASS_FLAG_LZMA 0x80 + +typedef struct { + AVIOContext *pb[101]; + int class[2]; + int stream_index; + uint64_t pts; +} MlvContext; + +static int probe(AVProbeData *p) +{ + if (AV_RL32(p->buf) == MKTAG('M','L','V','I') && + AV_RL32(p->buf + 4) >= 52 && + !memcmp(p->buf + 8, MLV_VERSION, 5)) + return AVPROBE_SCORE_MAX; + return 0; +} + +static int check_file_header(AVIOContext *pb, uint64_t guid) +{ + unsigned int size; + uint8_t version[8]; + + avio_skip(pb, 4); + size = avio_rl32(pb); + if (size < 52) + return AVERROR_INVALIDDATA; + avio_read(pb, version, 8); + if (memcmp(version, MLV_VERSION, 5) || avio_rl64(pb) != guid) + return AVERROR_INVALIDDATA; + avio_skip(pb, size - 24); + return 0; +} + +static void read_string(AVFormatContext *avctx, AVIOContext *pb, const char *tag, int size) +{ + char * value = av_malloc(size + 1); + if (!value) { + avio_skip(pb, size); + return; + } + + avio_read(pb, value, size); + if (!value[0]) { + av_free(value); + return; + } + + value[size] = 0; + av_dict_set(&avctx->metadata, tag, value, AV_DICT_DONT_STRDUP_VAL); +} + +static void read_uint8(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt) +{ + char value[4]; + snprintf(value, sizeof(value), "%i", avio_r8(pb)); + av_dict_set(&avctx->metadata, tag, value, 0); +} + +static void read_uint16(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt) +{ + char value[8]; + snprintf(value, sizeof(value), "%i", avio_rl16(pb)); + av_dict_set(&avctx->metadata, tag, value, 0); +} + +static void read_uint32(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt) +{ + char value[16]; + snprintf(value, sizeof(value), fmt, avio_rl32(pb)); + av_dict_set(&avctx->metadata, tag, value, 0); +} + +static void read_uint64(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt) +{ + char value[32]; + snprintf(value, sizeof(value), fmt, avio_rl64(pb)); + av_dict_set(&avctx->metadata, tag, value, 0); +} + +static int scan_file(AVFormatContext *avctx, AVStream *vst, AVStream *ast, int file) +{ + MlvContext *mlv = avctx->priv_data; + AVIOContext *pb = mlv->pb[file]; + int ret; + while (!url_feof(pb)) { + int type; + unsigned int size; + type = avio_rl32(pb); + size = avio_rl32(pb); + avio_skip(pb, 8); //timestamp + if (size < 16) + break; + size -= 16; + if (vst && type == MKTAG('R','A','W','I') && size >= 164) { + vst->codec->width = avio_rl16(pb); + vst->codec->height = avio_rl16(pb); + if (avio_rl32(pb) != 1) + avpriv_request_sample(avctx, "raw api version"); + avio_skip(pb, 20); // pointer, width, height, pitch, frame_size + vst->codec->bits_per_coded_sample = avio_rl32(pb); + avio_skip(pb, 8 + 16 + 24); // black_level, white_level, xywh, active_area, exposure_bias + if (avio_rl32(pb) != 0x2010100) /* RGGB */ + avpriv_request_sample(avctx, "cfa_pattern"); + avio_skip(pb, 80); // calibration_illuminant1, color_matrix1, dynamic_range + vst->codec->pix_fmt = AV_PIX_FMT_BAYER_RGGB16LE; + vst->codec->codec_tag = MKTAG('B', 'I', 'T', 16); + size -= 164; + } else if (ast && type == MKTAG('W', 'A', 'V', 'I') && size >= 16) { + ret = ff_get_wav_header(pb, ast->codec, 16); + if (ret < 0) + return ret; + size -= 16; + } else if (type == MKTAG('I','N','F','O')) { + if (size > 0) + read_string(avctx, pb, "info", size); + continue; + } else if (type == MKTAG('I','D','N','T') && size >= 36) { + read_string(avctx, pb, "cameraName", 32); + read_uint32(avctx, pb, "cameraModel", "0x%"PRIx32); + size -= 36; + if (size >= 32) { + read_string(avctx, pb, "cameraSerial", 32); + size -= 32; + } + } else if (type == MKTAG('L','E','N','S') && size >= 48) { + read_uint16(avctx, pb, "focalLength", "%i"); + read_uint16(avctx, pb, "focalDist", "%i"); + read_uint16(avctx, pb, "aperture", "%i"); + read_uint8(avctx, pb, "stabilizerMode", "%i"); + read_uint8(avctx, pb, "autofocusMode", "%i"); + read_uint32(avctx, pb, "flags", "0x%"PRIx32); + read_uint32(avctx, pb, "lensID", "%"PRIi32); + read_string(avctx, pb, "lensName", 32); + size -= 48; + if (size >= 32) { + read_string(avctx, pb, "lensSerial", 32); + size -= 32; + } + } else if (vst && type == MKTAG('V', 'I', 'D', 'F') && size >= 4) { + uint64_t pts = avio_rl32(pb); + ff_add_index_entry(&vst->index_entries, &vst->nb_index_entries, &vst->index_entries_allocated_size, + avio_tell(pb) - 20, pts, file, 0, AVINDEX_KEYFRAME); + size -= 4; + } else if (ast && type == MKTAG('A', 'U', 'D', 'F') && size >= 4) { + uint64_t pts = avio_rl32(pb); + ff_add_index_entry(&ast->index_entries, &ast->nb_index_entries, &ast->index_entries_allocated_size, + avio_tell(pb) - 20, pts, file, 0, AVINDEX_KEYFRAME); + size -= 4; + } else if (vst && type == MKTAG('W','B','A','L') && size >= 28) { + read_uint32(avctx, pb, "wb_mode", "%"PRIi32); + read_uint32(avctx, pb, "kelvin", "%"PRIi32); + read_uint32(avctx, pb, "wbgain_r", "%"PRIi32); + read_uint32(avctx, pb, "wbgain_g", "%"PRIi32); + read_uint32(avctx, pb, "wbgain_b", "%"PRIi32); + read_uint32(avctx, pb, "wbs_gm", "%"PRIi32); + read_uint32(avctx, pb, "wbs_ba", "%"PRIi32); + size -= 28; + } else if (type == MKTAG('R','T','C','I') && size >= 20) { + char str[32]; + struct tm time = { 0 }; + time.tm_sec = avio_rl16(pb); + time.tm_min = avio_rl16(pb); + time.tm_hour = avio_rl16(pb); + time.tm_mday = avio_rl16(pb); + time.tm_mon = avio_rl16(pb); + time.tm_year = avio_rl16(pb); + time.tm_wday = avio_rl16(pb); + time.tm_yday = avio_rl16(pb); + time.tm_isdst = avio_rl16(pb); + avio_skip(pb, 2); + strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", &time); + av_dict_set(&avctx->metadata, "time", str, 0); + size -= 20; + } else if (type == MKTAG('E','X','P','O') && size >= 16) { + av_dict_set(&avctx->metadata, "isoMode", avio_rl32(pb) ? "auto" : "manual", 0); + read_uint32(avctx, pb, "isoValue", "%"PRIi32); + read_uint32(avctx, pb, "isoAnalog", "%"PRIi32); + read_uint32(avctx, pb, "digitalGain", "%"PRIi32); + size -= 16; + if (size >= 8) { + read_uint64(avctx, pb, "shutterValue", "%"PRIi64); + size -= 8; + } + } else if (type == MKTAG('S','T','Y','L') && size >= 36) { + read_uint32(avctx, pb, "picStyleId", "%"PRIi32); + read_uint32(avctx, pb, "contrast", "%"PRIi32); + read_uint32(avctx, pb, "sharpness", "%"PRIi32); + read_uint32(avctx, pb, "saturation", "%"PRIi32); + read_uint32(avctx, pb, "colortone", "%"PRIi32); + read_string(avctx, pb, "picStyleName", 16); + size -= 36; + } else if (type == MKTAG('M','A','R','K')) { + } else if (type == MKTAG('N','U','L','L')) { + } else if (type == MKTAG('M','L','V','I')) { /* occurs when MLV and Mnn files are concatenated */ + } else { + av_log(avctx, AV_LOG_INFO, "unsupported tag %c%c%c%c, size %u\n", type&0xFF, (type>>8)&0xFF, (type>>16)&0xFF, (type>>24)&0xFF, size); + } + avio_skip(pb, size); + } + return 0; +} + +static int read_header(AVFormatContext *avctx) +{ + MlvContext *mlv = avctx->priv_data; + AVIOContext *pb = avctx->pb; + AVStream *vst = NULL, *ast = NULL; + int size, ret; + uint64_t guid; + char guidstr[32]; + + avio_skip(pb, 4); + size = avio_rl32(pb); + if (size < 52) + return AVERROR_INVALIDDATA; + + avio_skip(pb, 8); + + guid = avio_rl64(pb); + snprintf(guidstr, sizeof(guidstr), "0x%"PRIx64, guid); + av_dict_set(&avctx->metadata, "guid", guidstr, 0); + + avio_skip(pb, 8); //fileNum, fileCount, fileFlags + + mlv->class[0] = avio_rl16(pb); + if (mlv->class[0]) { + vst = avformat_new_stream(avctx, NULL); + if (!vst) + return AVERROR(ENOMEM); + vst->id = 0; + if ((mlv->class[0] & (MLV_CLASS_FLAG_DELTA|MLV_CLASS_FLAG_LZMA))) + avpriv_request_sample(avctx, "compression"); + vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; + switch (mlv->class[0] & ~(MLV_CLASS_FLAG_DELTA|MLV_CLASS_FLAG_LZMA)) { + case MLV_VIDEO_CLASS_RAW: + vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO; + break; + case MLV_VIDEO_CLASS_YUV: + vst->codec->pix_fmt = AV_PIX_FMT_YUV420P; + vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO; + vst->codec->codec_tag = 0; + break; + case MLV_VIDEO_CLASS_JPEG: + vst->codec->codec_id = AV_CODEC_ID_MJPEG; + vst->codec->codec_tag = 0; + break; + case MLV_VIDEO_CLASS_H264: + vst->codec->codec_id = AV_CODEC_ID_H264; + vst->codec->codec_tag = 0; + break; + default: + avpriv_request_sample(avctx, "unknown video class"); + } + } + + mlv->class[1] = avio_rl16(pb); + if (mlv->class[1]) { + ast = avformat_new_stream(avctx, NULL); + if (!ast) + return AVERROR(ENOMEM); + ast->id = 1; + if ((mlv->class[1] & MLV_CLASS_FLAG_LZMA)) + avpriv_request_sample(avctx, "compression"); + if ((mlv->class[1] & ~MLV_CLASS_FLAG_LZMA) != MLV_AUDIO_CLASS_WAV) + avpriv_request_sample(avctx, "unknown audio class"); + + ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; + avpriv_set_pts_info(ast, 33, 1, ast->codec->sample_rate); + } + + if (vst) + vst->nb_frames = avio_rl32(pb); + else + avio_skip(pb, 4); + + if (ast) + ast->nb_frames = avio_rl32(pb); + else + avio_skip(pb, 4); + + if (vst) { + AVRational framerate; + framerate.num = avio_rl32(pb); + framerate.den = avio_rl32(pb); + avpriv_set_pts_info(vst, 64, framerate.den, framerate.num); + } else + avio_skip(pb, 8); + + avio_skip(pb, size - 52); + + /* scan primary file */ + mlv->pb[100] = avctx->pb; + ret = scan_file(avctx, vst, ast, 100); + if (ret < 0) + return ret; + + /* scan secondary files */ + if (strlen(avctx->filename) > 2) { + int i; + char *filename = av_strdup(avctx->filename); + if (!filename) + return AVERROR(ENOMEM); + for (i = 0; i < 100; i++) { + snprintf(filename + strlen(filename) - 2, 3, "%02d", i); + if (avio_open2(&mlv->pb[i], filename, AVIO_FLAG_READ, &avctx->interrupt_callback, NULL) < 0) + break; + if (check_file_header(mlv->pb[i], guid) < 0) { + av_log(avctx, AV_LOG_WARNING, "ignoring %s; bad format or guid mismatch\n", filename); + avio_close(mlv->pb[i]); + mlv->pb[i] = NULL; + continue; + } + av_log(avctx, AV_LOG_INFO, "scanning %s\n", filename); + ret = scan_file(avctx, vst, ast, i); + if (ret < 0) { + av_log(avctx, AV_LOG_WARNING, "ignoring %s; %s\n", filename, av_err2str(ret)); + avio_close(mlv->pb[i]); + mlv->pb[i] = NULL; + continue; + } + } + av_free(filename); + } + + if (vst) + vst->duration = vst->nb_index_entries; + if (ast) + ast->duration = ast->nb_index_entries; + + if (vst && ast) + avio_seek(pb, FFMIN(vst->index_entries[0].pos, ast->index_entries[0].pos), SEEK_SET); + else if (vst) + avio_seek(pb, vst->index_entries[0].pos, SEEK_SET); + else if (ast) + avio_seek(pb, ast->index_entries[0].pos, SEEK_SET); + + return 0; +} + +static int read_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + MlvContext *mlv = avctx->priv_data; + AVIOContext *pb; + AVStream *st = avctx->streams[mlv->stream_index]; + int index, ret; + unsigned int size, space; + + if (mlv->pts >= st->duration) + return AVERROR_EOF; + + index = av_index_search_timestamp(st, mlv->pts, AVSEEK_FLAG_ANY); + if (index < 0) { + av_log(avctx, AV_LOG_ERROR, "could not find index entry for frame %"PRId64"\n", mlv->pts); + return AVERROR(EIO); + } + + pb = mlv->pb[st->index_entries[index].size]; + avio_seek(pb, st->index_entries[index].pos, SEEK_SET); + + avio_skip(pb, 4); // blockType + size = avio_rl32(pb); + if (size < 16) + return AVERROR_INVALIDDATA; + avio_skip(pb, 12); //timestamp, frameNumber + if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) + avio_skip(pb, 8); // cropPosX, cropPosY, panPosX, panPosY + space = avio_rl32(pb); + avio_skip(pb, space); + + if ((mlv->class[st->id] & (MLV_CLASS_FLAG_DELTA|MLV_CLASS_FLAG_LZMA))) { + ret = AVERROR_PATCHWELCOME; + } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + ret = av_get_packet(pb, pkt, (st->codec->width * st->codec->height * st->codec->bits_per_coded_sample + 7) >> 3); + } else { // AVMEDIA_TYPE_AUDIO + if (space > UINT_MAX - 24 || size < (24 + space)) + return AVERROR_INVALIDDATA; + ret = av_get_packet(pb, pkt, size - (24 + space)); + } + + if (ret < 0) + return ret; + + pkt->stream_index = mlv->stream_index; + pkt->pts = mlv->pts; + + mlv->stream_index++; + if (mlv->stream_index == avctx->nb_streams) { + mlv->stream_index = 0; + mlv->pts++; + } + return 0; +} + +static int read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags) +{ + MlvContext *mlv = avctx->priv_data; + + if ((flags & AVSEEK_FLAG_FRAME) || (flags & AVSEEK_FLAG_BYTE)) + return AVERROR(ENOSYS); + + if (!avctx->pb->seekable) + return AVERROR(EIO); + + mlv->pts = timestamp; + return 0; +} + +static int read_close(AVFormatContext *s) +{ + MlvContext *mlv = s->priv_data; + int i; + for (i = 0; i < 100; i++) + if (mlv->pb[i]) + avio_close(mlv->pb[i]); + return 0; +} + +AVInputFormat ff_mlv_demuxer = { + .name = "mlv", + .long_name = NULL_IF_CONFIG_SMALL("Magic Lantern Video (MLV)"), + .priv_data_size = sizeof(MlvContext), + .read_probe = probe, + .read_header = read_header, + .read_packet = read_packet, + .read_close = read_close, + .read_seek = read_seek, +}; diff --git a/libavformat/mmf.c b/libavformat/mmf.c index cb87a6ddd..a023dd617 100644 --- a/libavformat/mmf.c +++ b/libavformat/mmf.c @@ -69,7 +69,7 @@ static int mmf_write_header(AVFormatContext *s) AVIOContext *pb = s->pb; int64_t pos; int rate; - const char *version = s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT ? + const char *version = s->flags & AVFMT_FLAG_BITEXACT ? "VN:Lavf," : "VN:"LIBAVFORMAT_IDENT","; diff --git a/libavformat/mmsh.c b/libavformat/mmsh.c index 482ece403..dac5d9f65 100644 --- a/libavformat/mmsh.c +++ b/libavformat/mmsh.c @@ -119,7 +119,7 @@ static int read_data_packet(MMSHContext *mmsh, const int len) int res; if (len > sizeof(mms->in_buffer)) { av_log(NULL, AV_LOG_ERROR, - "Data packet length %d exceeds the in_buffer size %zu\n", + "Data packet length %d exceeds the in_buffer size %"SIZE_SPECIFIER"\n", len, sizeof(mms->in_buffer)); return AVERROR(EIO); } @@ -194,7 +194,7 @@ static int get_http_header_data(MMSHContext *mmsh) if (len) { if (len > sizeof(mms->in_buffer)) { av_log(NULL, AV_LOG_ERROR, - "Other packet len = %d exceed the in_buffer size %zu\n", + "Other packet len = %d exceed the in_buffer size %"SIZE_SPECIFIER"\n", len, sizeof(mms->in_buffer)); return AVERROR(EIO); } diff --git a/libavformat/mmst.c b/libavformat/mmst.c index ebef3ef09..c851187da 100644 --- a/libavformat/mmst.c +++ b/libavformat/mmst.c @@ -284,7 +284,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) if (length_remaining < 0 || length_remaining > sizeof(mms->in_buffer) - 12) { av_log(NULL, AV_LOG_ERROR, - "Incoming packet length %d exceeds bufsize %zu\n", + "Incoming packet length %d exceeds bufsize %"SIZE_SPECIFIER"\n", length_remaining, sizeof(mms->in_buffer) - 12); return AVERROR_INVALIDDATA; } @@ -320,7 +320,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) if (length_remaining < 0 || length_remaining > sizeof(mms->in_buffer) - 8) { av_log(NULL, AV_LOG_ERROR, - "Data length %d is invalid or too large (max=%zu)\n", + "Data length %d is invalid or too large (max=%"SIZE_SPECIFIER")\n", length_remaining, sizeof(mms->in_buffer)); return AVERROR_INVALIDDATA; } diff --git a/libavformat/mov.c b/libavformat/mov.c index 3fb774742..9b4832fb3 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -23,6 +23,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include @@ -30,6 +31,7 @@ #include "libavutil/attributes.h" #include "libavutil/channel_layout.h" +#include "libavutil/display.h" #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" #include "libavutil/mathematics.h" @@ -46,6 +48,7 @@ #include "libavcodec/get_bits.h" #include "id3v1.h" #include "mov_chan.h" +#include "replaygain.h" #if CONFIG_ZLIB #include @@ -129,74 +132,6 @@ static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb, return 0; } -static int mov_read_custom_metadata(MOVContext *c, AVIOContext *pb, MOVAtom atom) -{ - char key[1024]={0}, data[1024]={0}; - int i; - AVStream *st; - MOVStreamContext *sc; - - if (c->fc->nb_streams < 1) - return 0; - st = c->fc->streams[c->fc->nb_streams-1]; - sc = st->priv_data; - - if (atom.size <= 8) return 0; - - for (i = 0; i < 3; i++) { // Parse up to three sub-atoms looking for name and data. - int data_size = avio_rb32(pb); - int tag = avio_rl32(pb); - int str_size = 0, skip_size = 0; - char *target = NULL; - - switch (tag) { - case MKTAG('n','a','m','e'): - avio_rb32(pb); // version/flags - str_size = skip_size = data_size - 12; - atom.size -= 12; - target = key; - break; - case MKTAG('d','a','t','a'): - avio_rb32(pb); // version/flags - avio_rb32(pb); // reserved (zero) - str_size = skip_size = data_size - 16; - atom.size -= 16; - target = data; - break; - default: - skip_size = data_size - 8; - str_size = 0; - break; - } - - if (target) { - str_size = FFMIN3(sizeof(data)-1, str_size, atom.size); - avio_read(pb, target, str_size); - target[str_size] = 0; - } - atom.size -= skip_size; - - // If we didn't read the full data chunk for the sub-atom, skip to the end of it. - if (skip_size > str_size) avio_skip(pb, skip_size - str_size); - } - - if (*key && *data) { - if (strcmp(key, "iTunSMPB") == 0) { - int priming, remainder, samples; - if(sscanf(data, "%*X %X %X %X", &priming, &remainder, &samples) == 3){ - if(priming>0 && priming<16384) - sc->start_pad = priming; - return 1; - } - } - if (strcmp(key, "cdec") == 0) { -// av_dict_set(&st->metadata, key, data, 0); - return 1; - } - } - return 0; -} - static const uint32_t mac_to_unicode[128] = { 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1, 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8, @@ -287,6 +222,43 @@ static int mov_metadata_raw(MOVContext *c, AVIOContext *pb, return av_dict_set(&c->fc->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); } +static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len) +{ + char language[4] = { 0 }; + char buf[100]; + uint16_t langcode = 0; + double longitude, latitude; + const char *key = "location"; + + if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) + 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) + return AVERROR_INVALIDDATA; + avio_skip(pb, 1); // role + len -= 1; + + if (len < 14) + return AVERROR_INVALIDDATA; + longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16); + latitude = ((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); + if (*language && strcmp(language, "und")) { + char key2[16]; + snprintf(key2, sizeof(key2), "%s-%s", key, language); + av_dict_set(&c->fc->metadata, key2, buf, 0); + } + return av_dict_set(&c->fc->metadata, key, buf, 0); +} + static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) { #ifdef MOV_EXPORT_ALL_METADATA @@ -298,15 +270,14 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) uint32_t data_type = 0, str_size; int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL; - if (c->itunes_metadata && atom.type == MKTAG('-','-','-','-')) - return mov_read_custom_metadata(c, pb, atom); - 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( 'a','A','R','T'): key = "album_artist"; break; case MKTAG(0xa9,'w','r','t'): key = "composer"; break; + case MKTAG( 'c','p','i','l'): key = "compilation"; + parse = mov_metadata_int8_no_padding; break; case MKTAG( 'c','p','r','t'): case MKTAG(0xa9,'c','p','y'): key = "copyright"; break; case MKTAG(0xa9,'g','r','p'): key = "grouping"; break; @@ -347,6 +318,8 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) return mov_metadata_raw(c, pb, atom.size, "premiere_version"); case MKTAG( '@','P','R','Q'): return mov_metadata_raw(c, pb, atom.size, "quicktime_version"); + case MKTAG( 'l','o','c','i'): + return mov_metadata_loci(c, pb, atom.size); } if (c->itunes_metadata && atom.size > 8) { @@ -362,8 +335,8 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) int ret = mov_read_covr(c, pb, data_type, str_size); if (ret < 0) { av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n"); - return ret; } + return ret; } } else return 0; } else if (atom.size > 4 && key && !c->itunes_metadata) { @@ -767,7 +740,7 @@ static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type); av_dict_set(&c->fc->metadata, "major_brand", type, 0); minor_ver = avio_rb32(pb); /* minor version */ - snprintf(minor_ver_str, sizeof(minor_ver_str), "%d", minor_ver); + snprintf(minor_ver_str, sizeof(minor_ver_str), "%"PRIu32"", minor_ver); av_dict_set(&c->fc->metadata, "minor_version", minor_ver_str, 0); comp_brand_size = atom.size - 8; @@ -805,7 +778,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 = avio_tell(pb) - 8; + c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8; av_dlog(c->fc, "moof offset %"PRIx64"\n", c->fragment.moof_offset); return mov_read_default(c, pb, atom); } @@ -1275,6 +1248,7 @@ static int mov_codec_id(AVStream *st, uint32_t format) static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb, AVStream *st, MOVStreamContext *sc) { + uint8_t codec_name[32]; unsigned int color_depth, len, j; int color_greyscale; int color_table_id; @@ -1296,18 +1270,22 @@ static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb, len = avio_r8(pb); /* codec name, pascal string */ if (len > 31) len = 31; - mov_read_mac_string(c, pb, len, st->codec->codec_name, 32); + mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name)); if (len < 31) avio_skip(pb, 31 - len); + + if (codec_name[0]) + av_dict_set(&st->metadata, "encoder", codec_name, 0); + /* codec_tag YV12 triggers an UV swap in rawdec.c */ - if (!memcmp(st->codec->codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) { + if (!memcmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) { st->codec->codec_tag = MKTAG('I', '4', '2', '0'); st->codec->width &= ~1; st->codec->height &= ~1; } /* Flash Media Server uses tag H263 with Sorenson Spark */ if (st->codec->codec_tag == MKTAG('H','2','6','3') && - !memcmp(st->codec->codec_name, "Sorenson H263", 13)) + !memcmp(codec_name, "Sorenson H263", 13)) st->codec->codec_id = AV_CODEC_ID_FLV1; st->codec->bits_per_coded_sample = avio_rb16(pb); /* depth */ @@ -1486,6 +1464,57 @@ static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb, st->codec->height = sc->height; } +static uint32_t yuv_to_rgba(uint32_t ycbcr) +{ + uint8_t r, g, b; + int y, cb, cr; + + y = (ycbcr >> 16) & 0xFF; + cr = (ycbcr >> 8) & 0xFF; + cb = ycbcr & 0xFF; + + b = av_clip_uint8(1.164 * (y - 16) + 2.018 * (cb - 128)); + g = av_clip_uint8(1.164 * (y - 16) - 0.813 * (cr - 128) - 0.391 * (cb - 128)); + r = av_clip_uint8(1.164 * (y - 16) + 1.596 * (cr - 128)); + + return (r << 16) | (g << 8) | b; +} + +static int mov_rewrite_dvd_sub_extradata(AVStream *st) +{ + char buf[256] = {0}; + uint8_t *src = st->codec->extradata; + int i; + + if (st->codec->extradata_size != 64) + return 0; + + if (st->codec->width > 0 && st->codec->height > 0) + snprintf(buf, sizeof(buf), "size: %dx%d\n", + st->codec->width, st->codec->height); + av_strlcat(buf, "palette: ", sizeof(buf)); + + for (i = 0; i < 16; i++) { + uint32_t yuv = AV_RB32(src + i * 4); + uint32_t rgba = yuv_to_rgba(yuv); + + av_strlcatf(buf, sizeof(buf), "%06"PRIx32"%s", rgba, i != 15 ? ", " : ""); + } + + 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) + return AVERROR(ENOMEM); + st->codec->extradata_size = strlen(buf); + memcpy(st->codec->extradata, buf, st->codec->extradata_size); + + return 0; +} + static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb, AVStream *st, MOVStreamContext *sc, int size) @@ -2454,6 +2483,103 @@ static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom) return ret; } +static int mov_read_custom_2plus(MOVContext *c, AVIOContext *pb, int size) +{ + int64_t end = avio_tell(pb) + size; + uint8_t *key = NULL, *val = NULL; + int i; + AVStream *st; + MOVStreamContext *sc; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams-1]; + sc = st->priv_data; + + for (i = 0; i < 2; i++) { + uint8_t **p; + uint32_t len, tag; + + if (end - avio_tell(pb) <= 12) + break; + + len = avio_rb32(pb); + tag = avio_rl32(pb); + avio_skip(pb, 4); // flags + + if (len < 12 || len - 12 > end - avio_tell(pb)) + break; + len -= 12; + + if (tag == MKTAG('n', 'a', 'm', 'e')) + p = &key; + else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) { + avio_skip(pb, 4); + len -= 4; + p = &val; + } else + break; + + *p = av_malloc(len + 1); + if (!*p) + break; + avio_read(pb, *p, len); + (*p)[len] = 0; + } + + if (key && val) { + if (strcmp(key, "iTunSMPB") == 0) { + int priming, remainder, samples; + if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){ + if(priming>0 && priming<16384) + sc->start_pad = priming; + } + } else if (strcmp(key, "cdec") == 0) { + } else { + av_dict_set(&c->fc->metadata, key, val, + AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); + key = val = NULL; + } + } + + avio_seek(pb, end, SEEK_SET); + av_freep(&key); + av_freep(&val); + return 0; +} + +static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + int64_t end = avio_tell(pb) + atom.size; + uint32_t tag, len; + + if (atom.size < 8) + goto fail; + + len = avio_rb32(pb); + tag = avio_rl32(pb); + + if (len > atom.size) + goto fail; + + if (tag == MKTAG('m', 'e', 'a', 'n') && len > 12) { + uint8_t domain[128]; + int domain_len; + + avio_skip(pb, 4); // flags + len -= 12; + + domain_len = avio_get_str(pb, len, domain, sizeof(domain)); + avio_skip(pb, len - domain_len); + return mov_read_custom_2plus(c, pb, end - avio_tell(pb)); + } + +fail: + av_log(c->fc, AV_LOG_VERBOSE, + "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size); + return 0; +} + static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom) { while (atom.size > 8) { @@ -2474,7 +2600,7 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) int width; int height; int64_t disp_transform[2]; - int display_matrix[3][2]; + int display_matrix[3][3]; AVStream *st; MOVStreamContext *sc; int version; @@ -2511,11 +2637,12 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2) // they're kept in fixed point format through all calculations - // ignore u,v,z b/c we don't need the scale factor to calc aspect ratio + // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX + // side data, but the scale factor is not needed to calculate aspect ratio for (i = 0; i < 3; i++) { display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point - avio_rb32(pb); // 2.30 fixed point (not used) + display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point } width = avio_rb32(pb); // 16.16 fixed point track width @@ -2523,19 +2650,35 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->width = width >> 16; sc->height = height >> 16; - //Assign clockwise rotate values based on transform matrix so that - //we can compensate for iPhone orientation during capture. + // save the matrix and add rotate metadata when it is not the default + // identity + if (display_matrix[0][0] != (1 << 16) || + display_matrix[1][1] != (1 << 16) || + display_matrix[2][2] != (1 << 30) || + display_matrix[0][1] || display_matrix[0][2] || + display_matrix[1][0] || display_matrix[1][2] || + display_matrix[2][0] || display_matrix[2][1]) { + int i, j; + double rotate; - if (display_matrix[1][0] == -65536 && display_matrix[0][1] == 65536) { - av_dict_set(&st->metadata, "rotate", "90", 0); - } + av_freep(&sc->display_matrix); + sc->display_matrix = av_malloc(sizeof(int32_t) * 9); + if (!sc->display_matrix) + return AVERROR(ENOMEM); - if (display_matrix[0][0] == -65536 && display_matrix[1][1] == -65536) { - av_dict_set(&st->metadata, "rotate", "180", 0); - } + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + sc->display_matrix[i * 3 + j] = display_matrix[j][i]; - if (display_matrix[1][0] == 65536 && display_matrix[0][1] == -65536) { - av_dict_set(&st->metadata, "rotate", "270", 0); + rotate = av_display_rotation_get(sc->display_matrix); + if (!isnan(rotate)) { + char rotate_buf[64]; + rotate = -rotate; + if (rotate < 0) // for backward compatibility + rotate += 360; + snprintf(rotate_buf, sizeof(rotate_buf), "%g", rotate); + av_dict_set(&st->metadata, "rotate", rotate_buf, 0); + } } // transform the display width/height according to the matrix @@ -2586,7 +2729,8 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) } frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ? - avio_rb64(pb) : frag->moof_offset; + avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ? + frag->moof_offset : frag->implicit_offset; frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id; frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ? @@ -2728,7 +2872,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (pb->eof_reached) return AVERROR_EOF; - frag->moof_offset = offset; + frag->implicit_offset = offset; st->duration = sc->track_end = dts + sc->time_offset; return 0; } @@ -2997,6 +3141,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('h','v','c','C'), mov_read_glbl }, { MKTAG('u','u','i','d'), mov_read_uuid }, { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 }, +{ MKTAG('-','-','-','-'), mov_read_custom }, { 0, NULL } }; @@ -3015,6 +3160,19 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (atom.size >= 8) { a.size = avio_rb32(pb); a.type = avio_rl32(pb); + if (a.type == MKTAG('f','r','e','e') && + a.size >= 8 && + c->moov_retry) { + uint8_t buf[8]; + uint32_t *type = (uint32_t *)buf + 1; + avio_read(pb, buf, 8); + avio_seek(pb, -8, SEEK_CUR); + if (*type == MKTAG('m','v','h','d') || + *type == MKTAG('c','m','o','v')) { + av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free atom.\n"); + a.type = MKTAG('m','o','o','v'); + } + } if (atom.type != MKTAG('r','o','o','t') && atom.type != MKTAG('m','o','o','v')) { @@ -3105,7 +3263,6 @@ static int mov_probe(AVProbeData *p) /* check for obvious tags */ case MKTAG('m','o','o','v'): moov_offset = offset + 4; - case MKTAG('j','P',' ',' '): /* jpeg 2000 signature */ case MKTAG('m','d','a','t'): case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */ case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */ @@ -3115,6 +3272,9 @@ static int mov_probe(AVProbeData *p) offset + 12 > (unsigned int)p->buf_size || AV_RB64(p->buf+offset + 8) == 0)) { score = FFMAX(score, AVPROBE_SCORE_EXTENSION); + } else if (tag == MKTAG('f','t','y','p') && + AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')) { + score = FFMAX(score, 5); } else { score = AVPROBE_SCORE_MAX; } @@ -3196,6 +3356,11 @@ static void mov_read_chapters(AVFormatContext *s) uint16_t ch; int len, title_len; + if (end < sample->timestamp) { + av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n"); + end = AV_NOPTS_VALUE; + } + if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) { av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i); goto finish; @@ -3294,6 +3459,9 @@ static int mov_read_close(AVFormatContext *s) av_freep(&sc->drefs[j].dir); } av_freep(&sc->drefs); + + sc->drefs_count = 0; + if (!sc->pb_is_copied) avio_close(sc->pb); @@ -3305,15 +3473,12 @@ static int mov_read_close(AVFormatContext *s) av_freep(&sc->stts_data); av_freep(&sc->stps_data); av_freep(&sc->rap_group); + av_freep(&sc->display_matrix); } if (mov->dv_demux) { - for (i = 0; i < mov->dv_fctx->nb_streams; i++) { - av_freep(&mov->dv_fctx->streams[i]->codec); - av_freep(&mov->dv_fctx->streams[i]); - } - av_freep(&mov->dv_fctx); - av_freep(&mov->dv_demux); + avformat_free_context(mov->dv_fctx); + mov->dv_fctx = NULL; } av_freep(&mov->trex_data); @@ -3360,8 +3525,9 @@ static int mov_read_header(AVFormatContext *s) { MOVContext *mov = s->priv_data; AVIOContext *pb = s->pb; - int i, j, err; + int j, err; MOVAtom atom = { AV_RL32("root") }; + int i; mov->fc = s; /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */ @@ -3371,11 +3537,15 @@ static int mov_read_header(AVFormatContext *s) atom.size = INT64_MAX; /* check MOV header */ + do { + if (mov->moov_retry) + avio_seek(pb, 0, SEEK_SET); if ((err = mov_read_default(mov, pb, atom)) < 0) { av_log(s, AV_LOG_ERROR, "error reading header: %d\n", err); mov_read_close(s); return err; } + } while (pb->seekable && !mov->found_moov && !mov->moov_retry++); if (!mov->found_moov) { av_log(s, AV_LOG_ERROR, "moov atom not found\n"); mov_read_close(s); @@ -3422,6 +3592,16 @@ static int mov_read_header(AVFormatContext *s) if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0) av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX); + 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->codec->codec_id == AV_CODEC_ID_DVD_SUBTITLE) { + if ((err = mov_rewrite_dvd_sub_extradata(st)) < 0) + return err; + } + } } if (mov->trex_data) { @@ -3441,6 +3621,40 @@ static int mov_read_header(AVFormatContext *s) ff_rfps_calculate(s); + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + MOVStreamContext *sc = st->priv_data; + + switch (st->codec->codec_type) { + case AVMEDIA_TYPE_AUDIO: + err = ff_replaygain_export(st, s->metadata); + if (err < 0) { + mov_read_close(s); + return err; + } + break; + case AVMEDIA_TYPE_VIDEO: + if (sc->display_matrix) { + AVPacketSideData *sd, *tmp; + + tmp = av_realloc_array(st->side_data, + st->nb_side_data + 1, sizeof(*tmp)); + if (!tmp) + 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_DISPLAYMATRIX; + sd->size = sizeof(int32_t) * 9; + sd->data = (uint8_t*)sc->display_matrix; + sc->display_matrix = NULL; + } + break; + } + } + return 0; } @@ -3644,6 +3858,7 @@ AVInputFormat ff_mov_demuxer = { .name = "mov,mp4,m4a,3gp,3g2,mj2", .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"), .priv_data_size = sizeof(MOVContext), + .extensions = "mov,mp4,m4a,3gp,3g2,mj2", .read_probe = mov_probe, .read_header = mov_read_header, .read_packet = mov_read_packet, diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 01bc3c953..b3287cab9 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -22,6 +22,7 @@ */ #include +#include #include "movenc.h" #include "avformat.h" @@ -33,12 +34,14 @@ #include "libavcodec/get_bits.h" #include "libavcodec/put_bits.h" #include "libavcodec/vc1.h" +#include "libavcodec/raw.h" #include "internal.h" #include "libavutil/avstring.h" #include "libavutil/intfloat.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "libavutil/dict.h" +#include "libavutil/pixdesc.h" #include "hevc.h" #include "rtpenc.h" #include "mov_chan.h" @@ -350,7 +353,9 @@ static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio) // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved) - if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) + if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE) + avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream) + else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) avio_w8(pb, 0x15); // flags (= Audiostream) else avio_w8(pb, 0x11); // flags (= Visualstream) @@ -392,20 +397,24 @@ static int mov_pcm_be_gt16(enum AVCodecID codec_id) static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track) { + int ret; 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); + if ((ret = ff_put_wav_header(pb, track->enc, 0)) < 0) + return ret; return update_size(pb, pos); } static int mov_write_wfex_tag(AVIOContext *pb, MOVTrack *track) { + int ret; int64_t pos = avio_tell(pb); avio_wb32(pb, 0); ffio_wfourcc(pb, "wfex"); - ff_put_wav_header(pb, track->enc); + if ((ret = ff_put_wav_header(pb, track->enc, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX)) < 0) + return ret; return update_size(pb, pos); } @@ -423,6 +432,9 @@ static int mov_write_chan_tag(AVIOContext *pb, MOVTrack *track) return 0; } + if (track->multichannel_as_mono) + return 0; + avio_wb32(pb, 0); // Size ffio_wfourcc(pb, "chan"); // Type avio_w8(pb, 0); // Version @@ -542,7 +554,13 @@ static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf) put_bits(&pbc, 1, !slices); /* no slice code */ put_bits(&pbc, 1, 0); /* no bframe */ put_bits(&pbc, 1, 0); /* reserved */ - put_bits32(&pbc, track->enc->time_base.den); /* framerate */ + + /* framerate */ + if (track->st->avg_frame_rate.num > 0 && track->st->avg_frame_rate.den > 0) + put_bits32(&pbc, track->st->avg_frame_rate.num / track->st->avg_frame_rate.den); + else + put_bits32(&pbc, 0xffffffff); + flush_put_bits(&pbc); av_free(unescaped); @@ -792,7 +810,11 @@ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track) ffio_wfourcc(pb, "ACLR"); ffio_wfourcc(pb, "ACLR"); ffio_wfourcc(pb, "0001"); - avio_wb32(pb, 2); /* yuv range: full 1 / normal 2 */ + if (track->enc->color_range == AVCOL_RANGE_MPEG) { /* Legal range (16-235) */ + avio_wb32(pb, 1); /* Corresponds to 709 in official encoder */ + } else { /* Full range (0-255) */ + avio_wb32(pb, 2); /* Corresponds to RGB in official encoder */ + } avio_wb32(pb, 0); /* unknown */ avio_wb32(pb, 24); /* size */ @@ -847,6 +869,7 @@ static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track) 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'); return tag; } @@ -891,10 +914,10 @@ static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track) else if (track->enc->pix_fmt == 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 */ - if (track->enc->time_base.den == 50) tag = MKTAG('d','v','h','q'); + 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 */ - if (track->enc->time_base.den == 25) tag = MKTAG('d','v','h','5'); + if (track->st->time_base.den == 25) tag = MKTAG('d','v','h','5'); else tag = MKTAG('d','v','h','6'); } else { av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n"); @@ -1005,6 +1028,7 @@ static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track) { int tag = track->enc->codec_tag; int i; + enum AVPixelFormat pix_fmt; for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) { if (track->enc->pix_fmt == mov_pix_fmt_tags[i].pix_fmt) { @@ -1015,6 +1039,13 @@ static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track) } } + pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov, + track->enc->bits_per_coded_sample); + if (tag == MKTAG('r','a','w',' ') && + track->enc->pix_fmt != pix_fmt && + track->enc->pix_fmt != AV_PIX_FMT_NONE) + av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n", + av_get_pix_fmt_name(track->enc->pix_fmt)); return tag; } @@ -1143,7 +1174,9 @@ 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->extradata_size) + if (track->enc->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); return update_size(pb, pos); @@ -1164,12 +1197,14 @@ static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track) static void find_compressor(char * compressor_name, int len, MOVTrack *track) { + AVDictionaryEntry *encoder; int xdcam_res = (track->enc->width == 1280 && track->enc->height == 720) || (track->enc->width == 1440 && track->enc->height == 1080) || (track->enc->width == 1920 && track->enc->height == 1080); - if (track->mode == MODE_MOV && track->enc->codec && track->enc->codec->name) { - av_strlcpy(compressor_name, track->enc->codec->name, 32); + if (track->mode == MODE_MOV && + (encoder = av_dict_get(track->st->metadata, "encoder", NULL, 0))) { + av_strlcpy(compressor_name, encoder->value, 32); } else if (track->enc->codec_id == AV_CODEC_ID_MPEG2VIDEO && xdcam_res) { int interlaced = track->enc->field_order > AV_FIELD_PROGRESSIVE; AVStream *st = track->st; @@ -1353,7 +1388,7 @@ static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track) uint32_t atom_size; int i; - ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries)); /* worst case */ + ctts_entries = av_malloc_array((track->entry + 1), sizeof(*ctts_entries)); /* worst case */ ctts_entries[0].count = 1; ctts_entries[0].duration = track->cluster[0].cts; for (i = 1; i < track->entry; i++) { @@ -1394,7 +1429,7 @@ static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track) entries = 1; } else { stts_entries = track->entry ? - av_malloc(track->entry * sizeof(*stts_entries)) : /* worst case */ + av_malloc_array(track->entry, sizeof(*stts_entries)) : /* worst case */ NULL; for (i = 0; i < track->entry; i++) { int duration = get_cluster_duration(track, i); @@ -1562,6 +1597,12 @@ static int mov_write_vmhd_tag(AVIOContext *pb) return 0x14; } +static int is_clcp_track(MOVTrack *track) +{ + return track->tag == MKTAG('c','7','0','8') || + track->tag == MKTAG('c','6','0','8'); +} + static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track) { const char *hdlr, *descr = NULL, *hdlr_type = NULL; @@ -1580,12 +1621,17 @@ static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track) hdlr_type = "soun"; descr = "SoundHandler"; } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) { - if (track->tag == MKTAG('c','6','0','8')) { + if (is_clcp_track(track)) { hdlr_type = "clcp"; descr = "ClosedCaptionHandler"; } else { - if (track->tag == MKTAG('t','x','3','g')) hdlr_type = "sbtl"; - else hdlr_type = "text"; + if (track->tag == MKTAG('t','x','3','g')) { + hdlr_type = "sbtl"; + } else if (track->tag == MKTAG('m','p','4','s')) { + hdlr_type = "subp"; + } else { + hdlr_type = "text"; + } descr = "SubtitleHandler"; } } else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) { @@ -1646,7 +1692,7 @@ static int mov_write_minf_tag(AVIOContext *pb, MOVTrack *track) else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) mov_write_smhd_tag(pb); else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) { - if (track->tag == MKTAG('t','e','x','t') || track->tag == MKTAG('c','6','0','8')) { + if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) { mov_write_gmhd_tag(pb, track); } else { mov_write_nmhd_tag(pb); @@ -1728,12 +1774,26 @@ static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c, avio_wb32(pb, 1 << 30); /* w in 2.30 format */ } -static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st) +static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, + MOVTrack *track, AVStream *st) { int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE, track->timescale, AV_ROUND_UP); int version = duration < INT32_MAX ? 0 : 1; + int flags = MOV_TKHD_FLAG_IN_MOVIE; int rotation = 0; + int group = 0; + + + if (st) { + if (mov->per_stream_grouping) + group = st->index; + else + group = st->codec->codec_type; + } + + if (track->flags & MOV_TRACK_ENABLED) + flags |= MOV_TKHD_FLAG_ENABLED; if (track->mode == MODE_ISM) version = 1; @@ -1741,9 +1801,7 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st) (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */ ffio_wfourcc(pb, "tkhd"); avio_w8(pb, version); - avio_wb24(pb, (track->flags & MOV_TRACK_ENABLED) ? - MOV_TKHD_FLAG_ENABLED | MOV_TKHD_FLAG_IN_MOVIE : - MOV_TKHD_FLAG_IN_MOVIE); + avio_wb24(pb, flags); if (version == 1) { avio_wb64(pb, track->time); avio_wb64(pb, track->time); @@ -1761,7 +1819,7 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st) avio_wb32(pb, 0); /* reserved */ avio_wb32(pb, 0); /* reserved */ avio_wb16(pb, 0); /* layer */ - avio_wb16(pb, st ? st->codec->codec_type : 0); /* alternate group) */ + avio_wb16(pb, group); /* alternate group) */ /* Volume, only for audio */ if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) avio_wb16(pb, 0x0100); @@ -1942,7 +2000,7 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov, int64_t pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "trak"); - mov_write_tkhd_tag(pb, track, st); + mov_write_tkhd_tag(pb, mov, track, st); if (supports_edts(mov)) mov_write_edts_tag(pb, track); // PSP Movies and several other cases require edts box if (track->tref_tag) @@ -1952,10 +2010,16 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov, 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->enc->codec_type == AVMEDIA_TYPE_VIDEO && track->mode == MODE_MOV) { - double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio); - if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) + if (track->mode == MODE_MOV) { + if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) { + double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio); + if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) { + mov_write_tapt_tag(pb, track); + } + } + if (is_clcp_track(track) && st->sample_aspect_ratio.num) { mov_write_tapt_tag(pb, track); + } } return update_size(pb, pos); } @@ -2226,7 +2290,8 @@ 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)) + if (!mov->exact && + !mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1)) 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); @@ -2243,6 +2308,7 @@ static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_int8_metadata (s, pb, "stik", "media_type",1); mov_write_int8_metadata (s, pb, "hdvd", "hd_video", 1); mov_write_int8_metadata (s, pb, "pgap", "gapless_playback",1); + mov_write_int8_metadata (s, pb, "cpil", "compilation", 1); mov_write_trkn_tag(pb, mov, s, 0); // track number mov_write_trkn_tag(pb, mov, s, 1); // disc number mov_write_tmpo_tag(pb, s); @@ -2345,14 +2411,9 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s) { AVIOContext *pb_buf; - int i, ret, size; + int ret, size; uint8_t *buf; - for (i = 0; i < s->nb_streams; i++) - if (mov->tracks[i].enc->flags & CODEC_FLAG_BITEXACT) { - return 0; - } - ret = avio_open_dyn_buf(&pb_buf); if (ret < 0) return ret; @@ -2412,6 +2473,7 @@ static void mov_write_psp_udta_tag(AVIOContext *pb, static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s) { + MOVMuxContext *mov = s->priv_data; AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0); int64_t pos, pos2; @@ -2436,7 +2498,8 @@ static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s) avio_wb16(pb, 0x0); /* ? */ avio_wb16(pb, 0x021C); /* data */ - mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT, "eng", 0x04); + if (!mov->exact) + mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT, "eng", 0x04); mov_write_psp_udta_tag(pb, title->value, "eng", 0x01); mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03); @@ -2506,7 +2569,10 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov, int src_trk = mov->tracks[i].src_track; mov->tracks[src_trk].tref_tag = mov->tracks[i].tag; mov->tracks[src_trk].tref_id = mov->tracks[i].track_id; - mov->tracks[i].track_duration = mov->tracks[src_trk].track_duration; + //src_trk may have a different timescale than the tmcd track + mov->tracks[i].track_duration = av_rescale(mov->tracks[src_trk].track_duration, + mov->tracks[i].timescale, + mov->tracks[src_trk].timescale); } } @@ -2565,7 +2631,8 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov) avio_printf(pb, "\n"); avio_printf(pb, "\n"); avio_printf(pb, "\n"); - avio_printf(pb, "\n", + if (!mov->exact) + avio_printf(pb, "\n", LIBAVFORMAT_IDENT); avio_printf(pb, "\n"); avio_printf(pb, "\n"); @@ -3009,10 +3076,12 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) 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; - int frame_rate = ((video_codec->time_base.den) * (0x10000)) / (video_codec->time_base.num); + // 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); @@ -3291,6 +3360,10 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) pkt->dts = trk->cluster[trk->entry - 1].dts + 1; pkt->pts = AV_NOPTS_VALUE; } + if (pkt->duration < 0) { + av_log(s, AV_LOG_ERROR, "Application provided duration: %d is invalid\n", pkt->duration); + return AVERROR(EINVAL); + } } if (mov->flags & FF_MOV_FLAG_FRAGMENT) { int ret; @@ -3604,7 +3677,7 @@ static int mov_create_chapter_track(AVFormatContext *s, int tracknum) track->enc->extradata = buf; track->enc->extradata_size = size; } else { - av_free(&buf); + av_freep(&buf); } } #endif @@ -3685,7 +3758,7 @@ static void enable_tracks(AVFormatContext *s) { MOVMuxContext *mov = s->priv_data; int i; - uint8_t enabled[AVMEDIA_TYPE_NB]; + int enabled[AVMEDIA_TYPE_NB]; int first[AVMEDIA_TYPE_NB]; for (i = 0; i < AVMEDIA_TYPE_NB; i++) { @@ -3704,7 +3777,7 @@ static void enable_tracks(AVFormatContext *s) first[st->codec->codec_type] = i; if (st->disposition & AV_DISPOSITION_DEFAULT) { mov->tracks[i].flags |= MOV_TRACK_ENABLED; - enabled[st->codec->codec_type] = 1; + enabled[st->codec->codec_type]++; } } @@ -3713,6 +3786,8 @@ static void enable_tracks(AVFormatContext *s) case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_AUDIO: case AVMEDIA_TYPE_SUBTITLE: + if (enabled[i] > 1) + mov->per_stream_grouping = 1; if (!enabled[i] && first[i] >= 0) mov->tracks[first[i]].flags |= MOV_TRACK_ENABLED; break; @@ -3746,6 +3821,71 @@ static void mov_free(AVFormatContext *s) av_freep(&mov->tracks); } +static uint32_t rgb_to_yuv(uint32_t rgb) +{ + uint8_t r, g, b; + int y, cb, cr; + + r = (rgb >> 16) & 0xFF; + g = (rgb >> 8) & 0xFF; + b = (rgb ) & 0xFF; + + y = av_clip_uint8( 16. + 0.257 * r + 0.504 * g + 0.098 * b); + cb = av_clip_uint8(128. - 0.148 * r - 0.291 * g + 0.439 * b); + cr = av_clip_uint8(128. + 0.439 * r - 0.368 * g - 0.071 * b); + + return (y << 16) | (cr << 8) | cb; +} + +static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track, + AVStream *st) +{ + int i, width = 720, height = 480; + int have_palette = 0, have_size = 0; + uint32_t palette[16]; + char *cur = st->codec->extradata; + + while (cur && *cur) { + if (strncmp("palette:", cur, 8) == 0) { + int i, count; + count = sscanf(cur + 8, + "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", " + "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", " + "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", " + "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32"", + &palette[ 0], &palette[ 1], &palette[ 2], &palette[ 3], + &palette[ 4], &palette[ 5], &palette[ 6], &palette[ 7], + &palette[ 8], &palette[ 9], &palette[10], &palette[11], + &palette[12], &palette[13], &palette[14], &palette[15]); + + for (i = 0; i < count; i++) { + palette[i] = rgb_to_yuv(palette[i]); + } + have_palette = 1; + } else if (!strncmp("size:", cur, 5)) { + sscanf(cur + 5, "%dx%d", &width, &height); + have_size = 1; + } + if (have_palette && have_size) + break; + cur += strcspn(cur, "\n\r"); + cur += strspn(cur, "\n\r"); + } + if (have_palette) { + track->vos_data = av_malloc(16*4); + if (!track->vos_data) + return AVERROR(ENOMEM); + for (i = 0; i < 16; i++) { + AV_WB32(track->vos_data + i * 4, palette[i]); + } + track->vos_len = 16 * 4; + } + st->codec->width = width; + st->codec->height = track->height = height; + + return 0; +} + static int mov_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; @@ -3766,6 +3906,10 @@ static int mov_write_header(AVFormatContext *s) else if (!strcmp("f4v", s->oformat->name)) mov->mode = MODE_F4V; } + for (i = 0; i < s->nb_streams; i++) + if (s->flags & AVFMT_FLAG_BITEXACT) + mov->exact = 1; + /* Set the FRAGMENT flag if any of the fragmentation methods are * enabled. */ if (mov->max_fragment_duration || mov->max_fragment_size || @@ -3866,7 +4010,7 @@ static int mov_write_header(AVFormatContext *s) // Reserve an extra stream for chapters for the case where chapters // are written in the trailer - mov->tracks = av_mallocz((mov->nb_streams + 1) * sizeof(*mov->tracks)); + mov->tracks = av_mallocz_array((mov->nb_streams + 1), sizeof(*mov->tracks)); if (!mov->tracks) return AVERROR(ENOMEM); @@ -3875,8 +4019,8 @@ static int mov_write_header(AVFormatContext *s) MOVTrack *track= &mov->tracks[i]; AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0); + track->st = st; track->enc = st->codec; - track->st = st; track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV); if (track->language < 0) track->language = 0; @@ -3907,10 +4051,15 @@ static int mov_write_header(AVFormatContext *s) if (mov->video_track_timescale) { track->timescale = mov->video_track_timescale; } else { - track->timescale = st->codec->time_base.den; + track->timescale = st->time_base.den; while(track->timescale < 10000) track->timescale *= 2; } + if (st->codec->width > 65535 || st->codec->height > 65535) { + av_log(s, AV_LOG_ERROR, "Resolution %dx%d too large for mov/mp4\n", st->codec->width, st->codec->height); + ret = AVERROR(EINVAL); + goto error; + } if (track->mode == MODE_MOV && track->timescale > 100000) av_log(s, AV_LOG_WARNING, "WARNING codec timebase is very high. If duration is too long,\n" @@ -3947,9 +4096,9 @@ static int mov_write_header(AVFormatContext *s) goto error; } } else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { - track->timescale = st->codec->time_base.den; + track->timescale = st->time_base.den; } else if (st->codec->codec_type == AVMEDIA_TYPE_DATA) { - track->timescale = st->codec->time_base.den; + track->timescale = st->time_base.den; } else { track->timescale = MOV_TIMESCALE; } @@ -3964,9 +4113,38 @@ static int mov_write_header(AVFormatContext *s) /* copy extradata if it exists */ if (st->codec->extradata_size) { - track->vos_len = st->codec->extradata_size; - track->vos_data = av_malloc(track->vos_len); - memcpy(track->vos_data, st->codec->extradata, track->vos_len); + if (st->codec->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_data = av_malloc(track->vos_len); + memcpy(track->vos_data, st->codec->extradata, track->vos_len); + } + } + } + + for (i = 0; i < s->nb_streams; i++) { + int j; + AVStream *st= s->streams[i]; + MOVTrack *track= &mov->tracks[i]; + + if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO || + track->enc->channel_layout != AV_CH_LAYOUT_MONO) + continue; + + for (j = 0; j < s->nb_streams; j++) { + AVStream *stj= s->streams[j]; + MOVTrack *trackj= &mov->tracks[j]; + if (j == i) + continue; + + if (stj->codec->codec_type != AVMEDIA_TYPE_AUDIO || + trackj->enc->channel_layout != AV_CH_LAYOUT_MONO || + trackj->language != track->language || + trackj->tag != track->tag + ) + continue; + track->multichannel_as_mono++; } } diff --git a/libavformat/movenc.h b/libavformat/movenc.h index a72ce53ab..6ebe26544 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -98,8 +98,9 @@ typedef struct MOVTrack { int language; int track_id; int tag; ///< stsd fourcc - AVStream *st; + AVStream *st; AVCodecContext *enc; + int multichannel_as_mono; int vos_len; uint8_t *vos_data; @@ -156,6 +157,7 @@ typedef struct MOVMuxContext { int flags; int rtp_flags; + int exact; int iods_skip; int iods_video_profile; @@ -175,6 +177,8 @@ typedef struct MOVMuxContext { int64_t reserved_moov_pos; char *major_brand; + + int per_stream_grouping; } MOVMuxContext; #define FF_MOV_FLAG_RTP_HINT 1 diff --git a/libavformat/mp3dec.c b/libavformat/mp3dec.c index ba77bce23..833538840 100644 --- a/libavformat/mp3dec.c +++ b/libavformat/mp3dec.c @@ -22,12 +22,16 @@ #include "libavutil/opt.h" #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" +#include "libavutil/crc.h" #include "libavutil/dict.h" #include "libavutil/mathematics.h" #include "avformat.h" #include "internal.h" +#include "avio_internal.h" #include "id3v2.h" #include "id3v1.h" +#include "replaygain.h" + #include "libavcodec/mpegaudiodecheader.h" #define XING_FLAG_FRAMES 0x01 @@ -39,11 +43,12 @@ typedef struct { AVClass *class; int64_t filesize; - int64_t header_filesize; int xing_toc; int start_pad; int end_pad; int usetoc; + unsigned frames; /* Total number of frames in file */ + unsigned header_filesize; /* Total number of bytes in the stream */ int is_cbr; } MP3DecContext; @@ -85,10 +90,10 @@ static int mp3_read_probe(AVProbeData *p) // issues with MPEG-files! if (first_frames>=4) return AVPROBE_SCORE_EXTENSION + 1; else if(max_frames>200)return AVPROBE_SCORE_EXTENSION; - else if(max_frames>=4) return AVPROBE_SCORE_EXTENSION / 2; + else if(max_frames>=4 && max_frames >= p->buf_size/10000) return AVPROBE_SCORE_EXTENSION / 2; else if(ff_id3v2_match(buf0, ID3v2_DEFAULT_MAGIC) && 2*ff_id3v2_tag_len(buf0) >= p->buf_size) return p->buf_size < PROBE_BUF_MAX ? AVPROBE_SCORE_EXTENSION / 4 : AVPROBE_SCORE_EXTENSION - 2; - else if(max_frames>=1) return 1; + else if(max_frames>=1 && max_frames >= p->buf_size/10000) return 1; else return 0; //mpegps_mp3_unrecognized_format.mpg has max_frames=3 } @@ -117,19 +122,153 @@ static void read_xing_toc(AVFormatContext *s, int64_t filesize, int64_t duration mp3->xing_toc = 1; } +static void mp3_parse_info_tag(AVFormatContext *s, AVStream *st, + MPADecodeHeader *c, uint32_t spf) +{ +#define LAST_BITS(k, n) ((k) & ((1 << (n)) - 1)) +#define MIDDLE_BITS(k, m, n) LAST_BITS((k) >> (m), ((n) - (m))) + + uint16_t crc; + uint32_t v; + + char version[10]; + + uint32_t peak = 0; + int32_t r_gain = INT32_MIN, a_gain = INT32_MIN; + + MP3DecContext *mp3 = s->priv_data; + 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]); + v = avio_rb32(s->pb); + mp3->is_cbr = v == MKBETAG('I', 'n', 'f', 'o'); + if (v != MKBETAG('X', 'i', 'n', 'g') && !mp3->is_cbr) + return; + + v = avio_rb32(s->pb); + if (v & XING_FLAG_FRAMES) + mp3->frames = avio_rb32(s->pb); + if (v & XING_FLAG_SIZE) + mp3->header_filesize = avio_rb32(s->pb); + if (v & XING_FLAG_TOC) + read_xing_toc(s, mp3->header_filesize, av_rescale_q(mp3->frames, + (AVRational){spf, c->sample_rate}, + st->time_base)); + /* VBR quality */ + if(v & 8) + avio_skip(s->pb, 4); + + /* Encoder short version string */ + memset(version, 0, sizeof(version)); + avio_read(s->pb, version, 9); + + /* Info Tag revision + VBR method */ + avio_r8(s->pb); + + /* Lowpass filter value */ + avio_r8(s->pb); + + /* ReplayGain peak */ + v = avio_rb32(s->pb); + peak = av_rescale(v, 100000, 1 << 23); + + /* Radio ReplayGain */ + v = avio_rb16(s->pb); + + if (MIDDLE_BITS(v, 13, 15) == 1) { + r_gain = MIDDLE_BITS(v, 0, 8) * 10000; + + if (v & (1 << 9)) + r_gain *= -1; + } + + /* Audiophile ReplayGain */ + v = avio_rb16(s->pb); + + if (MIDDLE_BITS(v, 13, 15) == 2) { + a_gain = MIDDLE_BITS(v, 0, 8) * 10000; + + if (v & (1 << 9)) + a_gain *= -1; + } + + /* Encoding flags + ATH Type */ + avio_r8(s->pb); + + /* if ABR {specified bitrate} else {minimal bitrate} */ + avio_r8(s->pb); + + /* Encoder delays */ + v= avio_rb24(s->pb); + if(AV_RB32(version) == MKBETAG('L', 'A', 'M', 'E') + || AV_RB32(version) == MKBETAG('L', 'a', 'v', 'f')) { + + mp3->start_pad = v>>12; + mp3-> end_pad = v&4095; + st->skip_samples = mp3->start_pad + 528 + 1; + if (!st->start_time) + st->start_time = av_rescale_q(st->skip_samples, + (AVRational){1, c->sample_rate}, + st->time_base); + av_log(s, AV_LOG_DEBUG, "pad %d %d\n", mp3->start_pad, mp3-> end_pad); + } + + /* Misc */ + avio_r8(s->pb); + + /* MP3 gain */ + avio_r8(s->pb); + + /* Preset and surround info */ + avio_rb16(s->pb); + + /* Music length */ + avio_rb32(s->pb); + + /* Music CRC */ + avio_rb16(s->pb); + + /* Info Tag CRC */ + crc = ffio_get_checksum(s->pb); + v = avio_rb16(s->pb); + + if (v == crc) { + ff_replaygain_export_raw(st, r_gain, peak, a_gain, 0); + av_dict_set(&st->metadata, "encoder", version, 0); + } +} + +static void mp3_parse_vbri_tag(AVFormatContext *s, AVStream *st, int64_t base) +{ + uint32_t v; + MP3DecContext *mp3 = s->priv_data; + + /* Check for VBRI tag (always 32 bytes after end of mpegaudio header) */ + avio_seek(s->pb, base + 4 + 32, SEEK_SET); + v = avio_rb32(s->pb); + if (v == MKBETAG('V', 'B', 'R', 'I')) { + /* Check tag version */ + if (avio_rb16(s->pb) == 1) { + /* skip delay and quality */ + avio_skip(s->pb, 4); + mp3->header_filesize = avio_rb32(s->pb); + mp3->frames = avio_rb32(s->pb); + } + } +} + /** * Try to find Xing/Info/VBRI tags and compute duration from info therein */ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base) { - MP3DecContext *mp3 = s->priv_data; uint32_t v, spf; - unsigned frames = 0; /* Total number of frames in file */ - unsigned size = 0; /* Total number of bytes in the stream */ - static const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}}; MPADecodeHeader c; int vbrtag_size = 0; - int is_cbr; + MP3DecContext *mp3 = s->priv_data; + + ffio_init_checksum(s->pb, ff_crcA001_update, 0); v = avio_rb32(s->pb); if(ff_mpa_check_header(v) < 0) @@ -142,64 +281,23 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base) spf = c.lsf ? 576 : 1152; /* Samples per frame, layer 3 */ - /* Check for Xing / Info tag */ - avio_skip(s->pb, xing_offtbl[c.lsf == 1][c.nb_channels == 1]); - v = avio_rb32(s->pb); - is_cbr = v == MKBETAG('I', 'n', 'f', 'o'); - if (v == MKBETAG('X', 'i', 'n', 'g') || is_cbr) { - v = avio_rb32(s->pb); - if(v & XING_FLAG_FRAMES) - frames = avio_rb32(s->pb); - if(v & XING_FLAG_SIZE) - size = avio_rb32(s->pb); - if (v & XING_FLAG_TOC) - read_xing_toc(s, size, av_rescale_q(frames, (AVRational){spf, c.sample_rate}, - st->time_base)); - if(v & 8) - avio_skip(s->pb, 4); + mp3->frames = 0; + mp3->header_filesize = 0; - v = avio_rb32(s->pb); - if(v == MKBETAG('L', 'A', 'M', 'E') || v == MKBETAG('L', 'a', 'v', 'f')) { - avio_skip(s->pb, 21-4); - v= avio_rb24(s->pb); - mp3->start_pad = v>>12; - mp3-> end_pad = v&4095; - st->skip_samples = mp3->start_pad + 528 + 1; - if (!st->start_time) - st->start_time = av_rescale_q(st->skip_samples, - (AVRational){1, c.sample_rate}, - st->time_base); - av_log(s, AV_LOG_DEBUG, "pad %d %d\n", mp3->start_pad, mp3-> end_pad); - } - } + mp3_parse_info_tag(s, st, &c, spf); + mp3_parse_vbri_tag(s, st, base); - /* Check for VBRI tag (always 32 bytes after end of mpegaudio header) */ - avio_seek(s->pb, base + 4 + 32, SEEK_SET); - v = avio_rb32(s->pb); - if(v == MKBETAG('V', 'B', 'R', 'I')) { - /* Check tag version */ - if(avio_rb16(s->pb) == 1) { - /* skip delay and quality */ - avio_skip(s->pb, 4); - size = avio_rb32(s->pb); - frames = avio_rb32(s->pb); - } - } - - if(!frames && !size) + if (!mp3->frames && !mp3->header_filesize) return -1; /* Skip the vbr tag frame */ avio_seek(s->pb, base + vbrtag_size, SEEK_SET); - if(frames) - st->duration = av_rescale_q(frames, (AVRational){spf, c.sample_rate}, + if (mp3->frames) + st->duration = av_rescale_q(mp3->frames, (AVRational){spf, c.sample_rate}, st->time_base); - if (size && frames && !is_cbr) - st->codec->bit_rate = av_rescale(size, 8 * c.sample_rate, frames * (int64_t)spf); - - mp3->is_cbr = is_cbr; - mp3->header_filesize = size; + if (mp3->header_filesize && mp3->frames && !mp3->is_cbr) + st->codec->bit_rate = av_rescale(mp3->header_filesize, 8 * c.sample_rate, mp3->frames * (int64_t)spf); return 0; } @@ -209,6 +307,7 @@ static int mp3_read_header(AVFormatContext *s) MP3DecContext *mp3 = s->priv_data; AVStream *st; int64_t off; + int ret; st = avformat_new_stream(s, NULL); if (!st) @@ -234,6 +333,10 @@ static int mp3_read_header(AVFormatContext *s) if (mp3_parse_vbr_tags(s, st, off) < 0) avio_seek(s->pb, off, SEEK_SET); + ret = ff_replaygain_export(st, s->metadata); + if (ret < 0) + return ret; + /* the parameters will be extracted from the compressed bitstream */ return 0; } diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index a4de0043f..c0270c21d 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -125,7 +125,7 @@ static int mp3_write_xing(AVFormatContext *s) int xing_offset; int ver = 0; int bytes_needed; - const char *vendor = (codec->flags & CODEC_FLAG_BITEXACT) ? "Lavf" : LIBAVFORMAT_IDENT; + const char *vendor = (s->flags & AVFMT_FLAG_BITEXACT) ? "Lavf" : LIBAVFORMAT_IDENT; if (!s->pb->seekable || !mp3->write_xing) return 0; @@ -384,7 +384,7 @@ static int query_codec(enum AVCodecID id, int std_compliance) AVOutputFormat ff_mp2_muxer = { .name = "mp2", .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), - .mime_type = "audio/x-mpeg", + .mime_type = "audio/mpeg", .extensions = "mp2,m2a,mpa", .audio_codec = AV_CODEC_ID_MP2, .video_codec = AV_CODEC_ID_NONE, @@ -526,7 +526,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, diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index 177728393..c53bab3e3 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -37,74 +37,85 @@ #define MAX_SYNC_SIZE 100000 -static int check_pes(const uint8_t *p, const uint8_t *end){ +static int check_pes(const uint8_t *p, const uint8_t *end) +{ int pes1; - int pes2= (p[3] & 0xC0) == 0x80 - && (p[4] & 0xC0) != 0x40 - &&((p[4] & 0xC0) == 0x00 || (p[4]&0xC0)>>2 == (p[6]&0xF0)); + int pes2 = (p[3] & 0xC0) == 0x80 && + (p[4] & 0xC0) != 0x40 && + ((p[4] & 0xC0) == 0x00 || + (p[4] & 0xC0) >> 2 == (p[6] & 0xF0)); - for(p+=3; pbuf_size; i++){ - code = (code<<8) + p->buf[i]; + for (i = 0; i < p->buf_size; i++) { + code = (code << 8) + p->buf[i]; if ((code & 0xffffff00) == 0x100) { - int len= p->buf[i+1] << 8 | p->buf[i+2]; - int pes= check_pes(p->buf+i, p->buf+p->buf_size); - int pack = check_pack_header(p->buf+i); + int len = p->buf[i + 1] << 8 | p->buf[i + 2]; + int pes = check_pes(p->buf + i, p->buf + p->buf_size); + int pack = check_pack_header(p->buf + i); - if(code == SYSTEM_HEADER_START_CODE) sys++; - else if(code == PACK_START_CODE && pack) pspack++; - else if((code & 0xf0) == VIDEO_ID && pes) vid++; + if (code == SYSTEM_HEADER_START_CODE) + sys++; + else if (code == PACK_START_CODE && pack) + pspack++; + else if ((code & 0xf0) == VIDEO_ID && pes) + vid++; // skip pes payload to avoid start code emulation for private // and audio streams - else if((code & 0xe0) == AUDIO_ID && pes) {audio++; i+=len;} - else if(code == PRIVATE_STREAM_1 && pes) {priv1++; i+=len;} - else if(code == 0x1fd && pes) vid++; //VC1 + else if ((code & 0xe0) == AUDIO_ID && pes) {audio++; i+=len;} + else if (code == PRIVATE_STREAM_1 && pes) {priv1++; i+=len;} + else if (code == 0x1fd && pes) vid++; //VC1 - else if((code & 0xf0) == VIDEO_ID && !pes) invalid++; - else if((code & 0xe0) == AUDIO_ID && !pes) invalid++; - else if(code == PRIVATE_STREAM_1 && !pes) invalid++; + else if ((code & 0xf0) == VIDEO_ID && !pes) invalid++; + else if ((code & 0xe0) == AUDIO_ID && !pes) invalid++; + else if (code == PRIVATE_STREAM_1 && !pes) invalid++; } } - if(vid+audio > invalid+1) /* invalid VDR files nd short PES streams */ + if (vid + audio > invalid + 1) /* invalid VDR files nd short PES streams */ score = AVPROBE_SCORE_EXTENSION / 2; - if(sys>invalid && sys*9 <= pspack*10) - return (audio > 12 || vid > 3 || pspack > 2) ? AVPROBE_SCORE_EXTENSION + 2 : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg - if(pspack > invalid && (priv1+vid+audio)*10 >= pspack*9) - return pspack > 2 ? AVPROBE_SCORE_EXTENSION + 2 : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg - if((!!vid ^ !!audio) && (audio > 4 || vid > 1) && !sys && !pspack && p->buf_size>2048 && vid + audio > invalid) /* PES stream */ - return (audio > 12 || vid > 3 + 2*invalid) ? AVPROBE_SCORE_EXTENSION + 2 : AVPROBE_SCORE_EXTENSION / 2; + if (sys > invalid && sys * 9 <= pspack * 10) + return (audio > 12 || vid > 3 || pspack > 2) ? AVPROBE_SCORE_EXTENSION + 2 + : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg + if (pspack > invalid && (priv1 + vid + audio) * 10 >= pspack * 9) + return pspack > 2 ? AVPROBE_SCORE_EXTENSION + 2 + : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg + if ((!!vid ^ !!audio) && (audio > 4 || vid > 1) && !sys && + !pspack && p->buf_size > 2048 && vid + audio > invalid) /* PES stream */ + return (audio > 12 || vid > 3 + 2 * invalid) ? AVPROBE_SCORE_EXTENSION + 2 + : AVPROBE_SCORE_EXTENSION / 2; - //02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1 - //mp3_misidentified_2.mp3 has sys:0 priv1:0 pspack:0 vid:0 audio:6 - //Have\ Yourself\ a\ Merry\ Little\ Christmas.mp3 0 0 0 5 0 1 len:21618 + // 02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1 + // mp3_misidentified_2.mp3 has sys:0 priv1:0 pspack:0 vid:0 audio:6 + // Have\ Yourself\ a\ Merry\ Little\ Christmas.mp3 0 0 0 5 0 1 len:21618 return score; } - typedef struct MpegDemuxContext { int32_t header_state; unsigned char psm_es_type[256]; @@ -124,7 +135,7 @@ static int mpegps_read_header(AVFormatContext *s) int64_t last_pos = avio_tell(s->pb); m->header_state = 0xff; - s->ctx_flags |= AVFMTCTX_NOHEADER; + s->ctx_flags |= AVFMTCTX_NOHEADER; avio_get_str(s->pb, 6, buffer, sizeof(buffer)); if (!memcmp("IMKH", buffer, 4)) { @@ -142,8 +153,8 @@ static int64_t get_pts(AVIOContext *pb, int c) { uint8_t buf[5]; - buf[0] = c<0 ? avio_r8(pb) : c; - avio_read(pb, buf+1, 4); + buf[0] = c < 0 ? avio_r8(pb) : c; + avio_read(pb, buf + 1, 4); return ff_parse_pes_pts(buf); } @@ -155,7 +166,7 @@ static int find_next_start_code(AVIOContext *pb, int *size_ptr, int val, n; state = *header_state; - n = *size_ptr; + n = *size_ptr; while (n > 0) { if (url_feof(pb)) break; @@ -163,15 +174,16 @@ static int find_next_start_code(AVIOContext *pb, int *size_ptr, n--; if (state == 0x000001) { state = ((state << 8) | v) & 0xffffff; - val = state; + val = state; goto found; } state = ((state << 8) | v) & 0xffffff; } val = -1; - found: + +found: *header_state = state; - *size_ptr = n; + *size_ptr = n; return val; } @@ -197,10 +209,11 @@ static long mpegps_psm_parse(MpegDemuxContext *m, AVIOContext *pb) es_map_length = psm_length - ps_info_length - 10; /* at least one es available? */ - while (es_map_length >= 4){ + while (es_map_length >= 4) { unsigned char type = avio_r8(pb); unsigned char es_id = avio_r8(pb); uint16_t es_info_length = avio_rb16(pb); + /* remember mapping from stream id to stream type */ m->psm_es_type[es_id] = type; /* skip program_stream_info */ @@ -212,7 +225,7 @@ static long mpegps_psm_parse(MpegDemuxContext *m, AVIOContext *pb) } /* read the next PES header. Return its position in ppos - (if not NULL), and its start code, pts and dts. + * (if not NULL), and its start code, pts and dts. */ static int mpegps_read_pes_header(AVFormatContext *s, int64_t *ppos, int *pstart_code, @@ -222,20 +235,20 @@ static int mpegps_read_pes_header(AVFormatContext *s, int len, size, startcode, c, flags, header_len; int pes_ext, ext2_len, id_ext, skip; int64_t pts, dts; - int64_t last_sync= avio_tell(s->pb); + int64_t last_sync = avio_tell(s->pb); - error_redo: - avio_seek(s->pb, last_sync, SEEK_SET); - redo: - /* next start code (should be immediately after) */ - m->header_state = 0xff; - size = MAX_SYNC_SIZE; - startcode = find_next_start_code(s->pb, &size, &m->header_state); - last_sync = avio_tell(s->pb); - if (startcode < 0){ - if(url_feof(s->pb)) +error_redo: + avio_seek(s->pb, last_sync, SEEK_SET); +redo: + /* next start code (should be immediately after) */ + m->header_state = 0xff; + size = MAX_SYNC_SIZE; + startcode = find_next_start_code(s->pb, &size, &m->header_state); + last_sync = avio_tell(s->pb); + if (startcode < 0) { + if (url_feof(s->pb)) return AVERROR_EOF; - //FIXME we should remember header_state + // FIXME we should remember header_state return AVERROR(EAGAIN); } @@ -346,7 +359,7 @@ static int mpegps_read_pes_header(AVFormatContext *s, if (startcode != PRIVATE_STREAM_2) { /* stuffing */ - for(;;) { + for (;;) { if (len < 1) goto error_redo; c = avio_r8(s->pb); @@ -358,45 +371,47 @@ static int mpegps_read_pes_header(AVFormatContext *s, if ((c & 0xc0) == 0x40) { /* buffer scale & size */ avio_r8(s->pb); - c = avio_r8(s->pb); + c = avio_r8(s->pb); len -= 2; } if ((c & 0xe0) == 0x20) { - dts = pts = get_pts(s->pb, c); + dts = + pts = get_pts(s->pb, c); len -= 4; - if (c & 0x10){ - dts = get_pts(s->pb, -1); + if (c & 0x10) { + dts = get_pts(s->pb, -1); len -= 5; } } else if ((c & 0xc0) == 0x80) { /* mpeg 2 PES */ - flags = avio_r8(s->pb); + flags = avio_r8(s->pb); header_len = avio_r8(s->pb); - len -= 2; + len -= 2; if (header_len > len) goto error_redo; len -= header_len; if (flags & 0x80) { - dts = pts = get_pts(s->pb, -1); + dts = pts = get_pts(s->pb, -1); header_len -= 5; if (flags & 0x40) { - dts = get_pts(s->pb, -1); + dts = get_pts(s->pb, -1); header_len -= 5; } } - if (flags & 0x3f && header_len == 0){ + if (flags & 0x3f && header_len == 0) { flags &= 0xC0; av_log(s, AV_LOG_WARNING, "Further flags set but no bytes left\n"); } if (flags & 0x01) { /* PES extension */ pes_ext = avio_r8(s->pb); header_len--; - /* Skip PES private data, program packet sequence counter and P-STD buffer */ - skip = (pes_ext >> 4) & 0xb; + /* Skip PES private data, program packet sequence counter + * and P-STD buffer */ + skip = (pes_ext >> 4) & 0xb; skip += skip & 0x9; - if (pes_ext & 0x40 || skip > header_len){ + if (pes_ext & 0x40 || skip > header_len) { av_log(s, AV_LOG_WARNING, "pes_ext %X is invalid\n", pes_ext); - pes_ext=skip=0; + pes_ext = skip = 0; } avio_skip(s->pb, skip); header_len -= skip; @@ -412,11 +427,10 @@ static int mpegps_read_pes_header(AVFormatContext *s, } } } - if(header_len < 0) + if (header_len < 0) goto error_redo; avio_skip(s->pb, header_len); - } - else if( c!= 0xf ) + } else if (c != 0xf) goto redo; } @@ -424,22 +438,23 @@ static int mpegps_read_pes_header(AVFormatContext *s, startcode = avio_r8(s->pb); len--; } - if(len<0) + if (len < 0) goto error_redo; - if(dts != AV_NOPTS_VALUE && ppos){ + if (dts != AV_NOPTS_VALUE && ppos) { int i; - for(i=0; inb_streams; i++){ - if(startcode == s->streams[i]->id && - s->pb->seekable /* index useless on streams anyway */) { + for (i = 0; i < s->nb_streams; i++) { + if (startcode == s->streams[i]->id && + s->pb->seekable /* index useless on streams anyway */) { ff_reduce_index(s, i); - av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */); + av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, + AVINDEX_KEYFRAME /* FIXME keyframe? */); } } } *pstart_code = startcode; - *ppts = pts; - *pdts = dts; + *ppts = pts; + *pdts = dts; return len; } @@ -449,19 +464,19 @@ static int mpegps_read_packet(AVFormatContext *s, MpegDemuxContext *m = s->priv_data; AVStream *st; int len, startcode, i, es_type, ret; - int lpcm_header_len = -1; //Init to supress warning + int lpcm_header_len = -1; //Init to suppress warning int request_probe= 0; enum AVCodecID codec_id = AV_CODEC_ID_NONE; enum AVMediaType type; - int64_t pts, dts, dummy_pos; //dummy_pos is needed for the index building to work + int64_t pts, dts, dummy_pos; // dummy_pos is needed for the index building to work - redo: +redo: len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts); if (len < 0) return len; if (startcode >= 0x80 && startcode <= 0xcf) { - if(len < 4) + if (len < 4) goto skip; /* audio: skip header */ @@ -476,44 +491,45 @@ static int mpegps_read_packet(AVFormatContext *s, } /* now find stream */ - for(i=0;inb_streams;i++) { + for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; if (st->id == startcode) goto found; } es_type = m->psm_es_type[startcode & 0xff]; - if(es_type == STREAM_TYPE_VIDEO_MPEG1){ + if (es_type == STREAM_TYPE_VIDEO_MPEG1) { codec_id = AV_CODEC_ID_MPEG2VIDEO; - type = AVMEDIA_TYPE_VIDEO; - } else if(es_type == STREAM_TYPE_VIDEO_MPEG2){ + type = AVMEDIA_TYPE_VIDEO; + } else if (es_type == STREAM_TYPE_VIDEO_MPEG2) { codec_id = AV_CODEC_ID_MPEG2VIDEO; - type = AVMEDIA_TYPE_VIDEO; - } else if(es_type == STREAM_TYPE_AUDIO_MPEG1 || - es_type == STREAM_TYPE_AUDIO_MPEG2){ + type = AVMEDIA_TYPE_VIDEO; + } else if (es_type == STREAM_TYPE_AUDIO_MPEG1 || + es_type == STREAM_TYPE_AUDIO_MPEG2) { codec_id = AV_CODEC_ID_MP3; - type = AVMEDIA_TYPE_AUDIO; - } else if(es_type == STREAM_TYPE_AUDIO_AAC){ + type = AVMEDIA_TYPE_AUDIO; + } else if (es_type == STREAM_TYPE_AUDIO_AAC) { codec_id = AV_CODEC_ID_AAC; - type = AVMEDIA_TYPE_AUDIO; - } else if(es_type == STREAM_TYPE_VIDEO_MPEG4){ + type = AVMEDIA_TYPE_AUDIO; + } else if (es_type == STREAM_TYPE_VIDEO_MPEG4) { codec_id = AV_CODEC_ID_MPEG4; - type = AVMEDIA_TYPE_VIDEO; - } else if(es_type == STREAM_TYPE_VIDEO_H264){ + type = AVMEDIA_TYPE_VIDEO; + } else if (es_type == STREAM_TYPE_VIDEO_H264) { codec_id = AV_CODEC_ID_H264; - type = AVMEDIA_TYPE_VIDEO; - } else if(es_type == STREAM_TYPE_AUDIO_AC3){ + type = AVMEDIA_TYPE_VIDEO; + } else if (es_type == STREAM_TYPE_AUDIO_AC3) { codec_id = AV_CODEC_ID_AC3; - type = AVMEDIA_TYPE_AUDIO; - } else if(m->imkh_cctv && es_type == 0x91){ + type = AVMEDIA_TYPE_AUDIO; + } else if (m->imkh_cctv && es_type == 0x91) { codec_id = AV_CODEC_ID_PCM_MULAW; - type = AVMEDIA_TYPE_AUDIO; + type = AVMEDIA_TYPE_AUDIO; } else if (startcode >= 0x1e0 && startcode <= 0x1ef) { static const unsigned char avs_seqh[4] = { 0, 0, 1, 0xb0 }; unsigned char buf[8]; + avio_read(s->pb, buf, 8); avio_seek(s->pb, -8, SEEK_CUR); - if(!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1)) + if (!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1)) codec_id = AV_CODEC_ID_CAVS; else request_probe= 1; @@ -522,7 +538,7 @@ static int mpegps_read_packet(AVFormatContext *s, type = AVMEDIA_TYPE_DATA; codec_id = AV_CODEC_ID_DVD_NAV; } else if (startcode >= 0x1c0 && startcode <= 0x1df) { - type = AVMEDIA_TYPE_AUDIO; + type = AVMEDIA_TYPE_AUDIO; if (m->sofdec > 0) { codec_id = AV_CODEC_ID_ADPCM_ADX; // Auto-detect AC-3 @@ -531,35 +547,35 @@ static int mpegps_read_packet(AVFormatContext *s, codec_id = AV_CODEC_ID_MP2; } } else if (startcode >= 0x80 && startcode <= 0x87) { - type = AVMEDIA_TYPE_AUDIO; + type = AVMEDIA_TYPE_AUDIO; codec_id = AV_CODEC_ID_AC3; - } else if ( ( startcode >= 0x88 && startcode <= 0x8f) - ||( startcode >= 0x98 && startcode <= 0x9f)) { + } else if ((startcode >= 0x88 && startcode <= 0x8f) || + (startcode >= 0x98 && startcode <= 0x9f)) { /* 0x90 - 0x97 is reserved for SDDS in DVD specs */ - type = AVMEDIA_TYPE_AUDIO; + type = AVMEDIA_TYPE_AUDIO; codec_id = AV_CODEC_ID_DTS; } else if (startcode >= 0xa0 && startcode <= 0xaf) { - type = AVMEDIA_TYPE_AUDIO; - if(lpcm_header_len == 6) { + type = AVMEDIA_TYPE_AUDIO; + if (lpcm_header_len == 6) { codec_id = AV_CODEC_ID_MLP; } else { codec_id = AV_CODEC_ID_PCM_DVD; } } else if (startcode >= 0xb0 && startcode <= 0xbf) { - type = AVMEDIA_TYPE_AUDIO; + type = AVMEDIA_TYPE_AUDIO; codec_id = AV_CODEC_ID_TRUEHD; } else if (startcode >= 0xc0 && startcode <= 0xcf) { /* Used for both AC-3 and E-AC-3 in EVOB files */ - type = AVMEDIA_TYPE_AUDIO; + type = AVMEDIA_TYPE_AUDIO; codec_id = AV_CODEC_ID_AC3; } else if (startcode >= 0x20 && startcode <= 0x3f) { - type = AVMEDIA_TYPE_SUBTITLE; + type = AVMEDIA_TYPE_SUBTITLE; codec_id = AV_CODEC_ID_DVD_SUBTITLE; } else if (startcode >= 0xfd55 && startcode <= 0xfd5f) { - type = AVMEDIA_TYPE_VIDEO; + type = AVMEDIA_TYPE_VIDEO; codec_id = AV_CODEC_ID_VC1; } else { - skip: +skip: /* skip packet */ avio_skip(s->pb, len); goto redo; @@ -568,18 +584,19 @@ static int mpegps_read_packet(AVFormatContext *s, st = avformat_new_stream(s, NULL); if (!st) goto skip; - st->id = startcode; + st->id = startcode; st->codec->codec_type = type; - st->codec->codec_id = codec_id; + st->codec->codec_id = codec_id; if (st->codec->codec_id == AV_CODEC_ID_PCM_MULAW) { st->codec->channels = 1; st->codec->channel_layout = AV_CH_LAYOUT_MONO; st->codec->sample_rate = 8000; } st->request_probe = request_probe; - st->need_parsing = AVSTREAM_PARSE_FULL; - found: - if(st->discard >= AVDISCARD_ALL) + st->need_parsing = AVSTREAM_PARSE_FULL; + +found: + if (st->discard >= AVDISCARD_ALL) goto skip; if (startcode >= 0xa0 && startcode <= 0xaf) { if (lpcm_header_len == 6 && st->codec->codec_id == AV_CODEC_ID_MLP) { @@ -590,9 +607,10 @@ static int mpegps_read_packet(AVFormatContext *s, } } ret = av_get_packet(s->pb, pkt, len); - pkt->pts = pts; - pkt->dts = dts; - pkt->pos = dummy_pos; + + pkt->pts = pts; + 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", pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0, @@ -611,7 +629,7 @@ static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, if (avio_seek(s->pb, pos, SEEK_SET) < 0) return AV_NOPTS_VALUE; - for(;;) { + for (;;) { len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts); if (len < 0) { av_dlog(s, "none (ret=%d)\n", len); @@ -643,6 +661,7 @@ AVInputFormat ff_mpegps_demuxer = { #if CONFIG_VOBSUB_DEMUXER #define REF_STRING "# VobSub index file," +#define MAX_LINE_SIZE 2048 static int vobsub_probe(AVProbeData *p) { @@ -661,6 +680,9 @@ static int vobsub_read_header(AVFormatContext *s) AVBPrint header; int64_t delay = 0; AVStream *st = NULL; + int stream_id = -1; + char id[64] = {0}; + char alt[MAX_LINE_SIZE] = {0}; sub_name = av_strdup(s->filename); fname_len = strlen(sub_name); @@ -681,7 +703,7 @@ static int vobsub_read_header(AVFormatContext *s) av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED); while (!url_feof(s->pb)) { - char line[2048]; + char line[MAX_LINE_SIZE]; int len = ff_get_line(s->pb, line, sizeof(line)); if (!len) @@ -690,11 +712,7 @@ static int vobsub_read_header(AVFormatContext *s) line[strcspn(line, "\r\n")] = 0; if (!strncmp(line, "id:", 3)) { - int n, stream_id = 0; - char id[64] = {0}; - - n = sscanf(line, "id: %63[^,], index: %u", id, &stream_id); - if (n != 2) { + if (sscanf(line, "id: %63[^,], index: %u", id, &stream_id) != 2) { av_log(s, AV_LOG_WARNING, "Unable to parse index line '%s', " "assuming 'id: und, index: 0'\n", line); strcpy(id, "und"); @@ -707,39 +725,49 @@ static int vobsub_read_header(AVFormatContext *s) goto end; } - st = avformat_new_stream(s, NULL); - if (!st) { - ret = AVERROR(ENOMEM); - goto end; - } - st->id = stream_id; - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - st->codec->codec_id = AV_CODEC_ID_DVD_SUBTITLE; - avpriv_set_pts_info(st, 64, 1, 1000); - av_dict_set(&st->metadata, "language", id, 0); - av_log(s, AV_LOG_DEBUG, "IDX stream[%d] id=%s\n", stream_id, id); header_parsed = 1; + alt[0] = '\0'; + /* We do not create the stream immediately to avoid adding empty + * streams. See the following timestamp entry. */ - } else if (st && !strncmp(line, "timestamp:", 10)) { + av_log(s, AV_LOG_DEBUG, "IDX stream[%d] id=%s\n", stream_id, id); + + } else if (!strncmp(line, "timestamp:", 10)) { AVPacket *sub; int hh, mm, ss, ms; int64_t pos, timestamp; const char *p = line + 10; - if (!s->nb_streams) { + if (stream_id == -1) { av_log(s, AV_LOG_ERROR, "Timestamp declared before any stream\n"); ret = AVERROR_INVALIDDATA; goto end; } + if (!st || st->id != stream_id) { + st = avformat_new_stream(s, NULL); + if (!st) { + ret = AVERROR(ENOMEM); + goto end; + } + st->id = stream_id; + st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codec->codec_id = AV_CODEC_ID_DVD_SUBTITLE; + avpriv_set_pts_info(st, 64, 1, 1000); + av_dict_set(&st->metadata, "language", id, 0); + if (alt[0]) + av_dict_set(&st->metadata, "title", alt, 0); + } + if (sscanf(p, "%02d:%02d:%02d:%03d, filepos: %"SCNx64, &hh, &mm, &ss, &ms, &pos) != 5) { av_log(s, AV_LOG_ERROR, "Unable to parse timestamp line '%s', " "abort parsing\n", line); - break; + ret = AVERROR_INVALIDDATA; + goto end; } timestamp = (hh*3600LL + mm*60LL + ss) * 1000LL + ms + delay; - timestamp = av_rescale_q(timestamp, (AVRational){1,1000}, st->time_base); + timestamp = av_rescale_q(timestamp, av_make_q(1, 1000), st->time_base); sub = ff_subtitles_queue_insert(&vobsub->q[s->nb_streams - 1], "", 0, 0); if (!sub) { @@ -750,13 +778,13 @@ static int vobsub_read_header(AVFormatContext *s) sub->pts = timestamp; sub->stream_index = s->nb_streams - 1; - } else if (st && !strncmp(line, "alt:", 4)) { + } else if (!strncmp(line, "alt:", 4)) { const char *p = line + 4; while (*p == ' ') p++; - av_dict_set(&st->metadata, "title", p, 0); av_log(s, AV_LOG_DEBUG, "IDX stream[%d] name=%s\n", st->id, p); + av_strlcpy(alt, p, sizeof(alt)); header_parsed = 1; } else if (!strncmp(line, "delay:", 6)) { @@ -810,8 +838,6 @@ end: return ret; } -#define FAIL(r) do { ret = r; goto fail; } while (0) - static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt) { MpegDemuxContext *vobsub = s->priv_data; @@ -824,7 +850,9 @@ static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt) int sid = 0; for (i = 0; i < s->nb_streams; i++) { FFDemuxSubtitlesQueue *tmpq = &vobsub->q[i]; - int64_t ts = tmpq->subs[tmpq->current_sub_idx].pts; + int64_t ts; + av_assert0(tmpq->nb_subs); + ts = tmpq->subs[tmpq->current_sub_idx].pts; if (ts < min_ts) { min_ts = ts; sid = i; @@ -860,7 +888,7 @@ static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) { if (pkt->size) // raise packet even if incomplete break; - FAIL(ret); + goto fail; } to_read = ret & 0xffff; new_pos = avio_tell(pb); @@ -877,7 +905,7 @@ static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt) ret = av_grow_packet(pkt, to_read); if (ret < 0) - FAIL(ret); + goto fail; n = avio_read(pb, pkt->data + (pkt->size - to_read), to_read); if (n < to_read) diff --git a/libavformat/mpeg.h b/libavformat/mpeg.h index cf10d6a4c..55f9e0cb5 100644 --- a/libavformat/mpeg.h +++ b/libavformat/mpeg.h @@ -57,7 +57,6 @@ #define STREAM_TYPE_VIDEO_CAVS 0x42 #define STREAM_TYPE_AUDIO_AC3 0x81 -#define STREAM_TYPE_AUDIO_DTS 0x8a static const int lpcm_freq_tab[4] = { 48000, 96000, 44100, 32000 }; diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c index ccf3ec21f..5521f48ce 100644 --- a/libavformat/mpegenc.c +++ b/libavformat/mpegenc.c @@ -387,7 +387,9 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) if (st->codec->rc_buffer_size) stream->max_buffer_size = 6*1024 + st->codec->rc_buffer_size/8; else { - av_log(ctx, AV_LOG_WARNING, "VBV buffer size not set, muxing may fail\n"); + av_log(ctx, AV_LOG_WARNING, "VBV buffer size not set, using default size of 130KB\n" + "If you want the mpeg file to be compliant to some specification\n" + "Like DVD, VCD or others, make sure you set the correct buffer size\n"); stream->max_buffer_size = 230*1024; //FIXME this is probably too small as default } if (stream->max_buffer_size > 1024 * 8191) { @@ -1157,7 +1159,7 @@ static int mpeg_mux_end(AVFormatContext *ctx) stream = ctx->streams[i]->priv_data; assert(av_fifo_size(stream->fifo) == 0); - av_fifo_free(stream->fifo); + av_fifo_freep(&stream->fifo); } return 0; } diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 286b30b4f..71140888a 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -29,7 +29,6 @@ #include "libavutil/avassert.h" #include "libavcodec/bytestream.h" #include "libavcodec/get_bits.h" -#include "libavcodec/mathops.h" #include "avformat.h" #include "mpegts.h" #include "internal.h" @@ -39,37 +38,46 @@ #include "isom.h" /* maximum size in which we look for synchronisation if - synchronisation is lost */ + * synchronisation is lost */ #define MAX_RESYNC_SIZE 65536 -#define MAX_PES_PAYLOAD 200*1024 +#define MAX_PES_PAYLOAD 200 * 1024 #define MAX_MP4_DESCR_COUNT 16 +#define MOD_UNLIKELY(modulus, dividend, divisor, prev_dividend) \ + do { \ + if ((prev_dividend) == 0 || (dividend) - (prev_dividend) != (divisor)) \ + (modulus) = (dividend) % (divisor); \ + (prev_dividend) = (dividend); \ + } while (0) + enum MpegTSFilterType { MPEGTS_PES, MPEGTS_SECTION, + MPEGTS_PCR, }; typedef struct MpegTSFilter MpegTSFilter; -typedef int PESCallback(MpegTSFilter *f, const uint8_t *buf, int len, int is_start, int64_t pos, int64_t cur_pcr); +typedef int PESCallback (MpegTSFilter *f, const uint8_t *buf, int len, + int is_start, int64_t pos); typedef struct MpegTSPESFilter { PESCallback *pes_cb; void *opaque; } MpegTSPESFilter; -typedef void SectionCallback(MpegTSFilter *f, const uint8_t *buf, int len); +typedef void SectionCallback (MpegTSFilter *f, const uint8_t *buf, int len); -typedef void SetServiceCallback(void *opaque, int ret); +typedef void SetServiceCallback (void *opaque, int ret); typedef struct MpegTSSectionFilter { int section_index; int section_h_size; uint8_t *section_buf; - unsigned int check_crc:1; - unsigned int end_of_section_reached:1; + unsigned int check_crc : 1; + unsigned int end_of_section_reached : 1; SectionCallback *section_cb; void *opaque; } MpegTSSectionFilter; @@ -78,6 +86,7 @@ struct MpegTSFilter { int pid; int es_id; int last_cc; /* last cc code (-1 if first packet) */ + int64_t last_pcr; enum MpegTSFilterType type; union { MpegTSPESFilter pes_filter; @@ -87,7 +96,7 @@ struct MpegTSFilter { #define MAX_PIDS_PER_PROGRAM 64 struct Program { - unsigned int id; //program id/service id + unsigned int id; // program id/service id unsigned int nb_pids; unsigned int pids[MAX_PIDS_PER_PROGRAM]; @@ -99,7 +108,7 @@ struct MpegTSContext { const AVClass *class; /* user data */ AVFormatContext *stream; - /** raw packet size, including FEC if present */ + /** raw packet size, including FEC if present */ int raw_packet_size; int size_stat[3]; @@ -108,45 +117,50 @@ struct MpegTSContext { int64_t pos47_full; - /** if true, all pids are analyzed to find streams */ + /** if true, all pids are analyzed to find streams */ int auto_guess; - /** compute exact PCR for each transport stream packet */ + /** compute exact PCR for each transport stream packet */ int mpeg2ts_compute_pcr; /** fix dvb teletext pts */ int fix_teletext_pts; - int64_t cur_pcr; /**< used to estimate the exact PCR */ - int pcr_incr; /**< used to estimate the exact PCR */ + int64_t cur_pcr; /**< used to estimate the exact PCR */ + int pcr_incr; /**< used to estimate the exact PCR */ /* data needed to handle file based ts */ - /** stop parsing loop */ + /** stop parsing loop */ int stop_parse; - /** packet containing Audio/Video data */ + /** packet containing Audio/Video data */ AVPacket *pkt; - /** to detect seek */ + /** to detect seek */ int64_t last_pos; + int skip_changes; + int skip_clear; + /******************************************/ /* private mpegts data */ /* scan context */ - /** structure to keep track of Program->pids mapping */ + /** structure to keep track of Program->pids mapping */ unsigned int nb_prg; struct Program *prg; int8_t crc_validity[NB_PID_MAX]; - /** filters for various streams specified by PMT + for the PAT and PMT */ MpegTSFilter *pids[NB_PID_MAX]; int current_pid; }; static const AVOption mpegtsraw_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 }, - {"ts_packetsize", "Output option carrying the raw packet size.", offsetof(MpegTSContext, raw_packet_size), AV_OPT_TYPE_INT, - {.i64 = 0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY }, + { "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 }, + { "ts_packetsize", "Output option carrying the raw packet size.", + offsetof(MpegTSContext, raw_packet_size), AV_OPT_TYPE_INT, + { .i64 = 0 }, 0, 0, + AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY }, { NULL }, }; @@ -162,6 +176,10 @@ static const AVOption mpegts_options[] = { {.i64 = 1}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, {"ts_packetsize", "Output option carrying the raw packet size.", offsetof(MpegTSContext, raw_packet_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY }, + {"skip_changes", "Skip changing / adding streams / programs.", offsetof(MpegTSContext, skip_changes), AV_OPT_TYPE_INT, + {.i64 = 0}, 0, 1, 0 }, + {"skip_clear", "Skip clearing programs.", offsetof(MpegTSContext, skip_clear), AV_OPT_TYPE_INT, + {.i64 = 0}, 0, 1, 0 }, { NULL }, }; @@ -207,7 +225,6 @@ typedef struct PESContext { uint8_t header[MAX_PES_HEADER_SIZE]; AVBufferRef *buffer; SLConfigDescr sl; - int64_t last_pcr; } PESContext; extern AVInputFormat ff_mpegts_demuxer; @@ -215,8 +232,8 @@ extern AVInputFormat ff_mpegts_demuxer; static struct Program * get_program(MpegTSContext *ts, unsigned int programid) { int i; - for(i=0; inb_prg; i++) { - if(ts->prg[i].id == programid) { + for (i = 0; i < ts->nb_prg; i++) { + if (ts->prg[i].id == programid) { return &ts->prg[i]; } } @@ -227,8 +244,9 @@ static void clear_avprogram(MpegTSContext *ts, unsigned int programid) { AVProgram *prg = NULL; int i; - for(i=0; istream->nb_programs; i++) - if(ts->stream->programs[i]->id == programid){ + + for (i = 0; i < ts->stream->nb_programs; i++) + if (ts->stream->programs[i]->id == programid) { prg = ts->stream->programs[i]; break; } @@ -242,8 +260,8 @@ static void clear_program(MpegTSContext *ts, unsigned int programid) int i; clear_avprogram(ts, programid); - for(i=0; inb_prg; i++) - if(ts->prg[i].id == programid) { + for (i = 0; i < ts->nb_prg; i++) + if (ts->prg[i].id == programid) { ts->prg[i].nb_pids = 0; ts->prg[i].pmt_found = 0; } @@ -252,7 +270,7 @@ static void clear_program(MpegTSContext *ts, unsigned int programid) static void clear_programs(MpegTSContext *ts) { av_freep(&ts->prg); - ts->nb_prg=0; + ts->nb_prg = 0; } static void add_pat_entry(MpegTSContext *ts, unsigned int programid) @@ -269,13 +287,14 @@ static void add_pat_entry(MpegTSContext *ts, unsigned int programid) ts->nb_prg++; } -static void add_pid_to_pmt(MpegTSContext *ts, unsigned int programid, unsigned int pid) +static void add_pid_to_pmt(MpegTSContext *ts, unsigned int programid, + unsigned int pid) { struct Program *p = get_program(ts, programid); - if(!p) + if (!p) return; - if(p->nb_pids >= MAX_PIDS_PER_PROGRAM) + if (p->nb_pids >= MAX_PIDS_PER_PROGRAM) return; p->pids[p->nb_pids++] = pid; } @@ -283,7 +302,7 @@ static void add_pid_to_pmt(MpegTSContext *ts, unsigned int programid, unsigned i static void set_pmt_found(MpegTSContext *ts, unsigned int programid) { struct Program *p = get_program(ts, programid); - if(!p) + if (!p) return; p->pmt_found = 1; @@ -292,8 +311,8 @@ static void set_pmt_found(MpegTSContext *ts, unsigned int programid) static void set_pcr_pid(AVFormatContext *s, unsigned int programid, unsigned int pid) { int i; - for(i=0; inb_programs; i++) { - if(s->programs[i]->id == programid) { + for (i = 0; i < s->nb_programs; i++) { + if (s->programs[i]->id == programid) { s->programs[i]->pcr_pid = pid; break; } @@ -315,24 +334,22 @@ static int discard_pid(MpegTSContext *ts, unsigned int pid) struct Program *p; /* If none of the programs have .discard=AVDISCARD_ALL then there's - * no way we have to discard this packet - */ - for (k = 0; k < ts->stream->nb_programs; k++) { + * no way we have to discard this packet */ + for (k = 0; k < ts->stream->nb_programs; k++) if (ts->stream->programs[k]->discard == AVDISCARD_ALL) break; - } if (k == ts->stream->nb_programs) return 0; - for(i=0; inb_prg; i++) { + for (i = 0; i < ts->nb_prg; i++) { p = &ts->prg[i]; - for(j=0; jnb_pids; j++) { - if(p->pids[j] != pid) + for (j = 0; j < p->nb_pids; j++) { + if (p->pids[j] != pid) continue; - //is program with id p->id set to be discarded? - for(k=0; kstream->nb_programs; k++) { - if(ts->stream->programs[k]->id == p->id) { - if(ts->stream->programs[k]->discard == AVDISCARD_ALL) + // is program with id p->id set to be discarded? + for (k = 0; k < ts->stream->nb_programs; k++) { + if (ts->stream->programs[k]->id == p->id) { + if (ts->stream->programs[k]->discard == AVDISCARD_ALL) discarded++; else used++; @@ -348,10 +365,9 @@ static int discard_pid(MpegTSContext *ts, unsigned int pid) * Assemble PES packets out of TS packets, and then call the "section_cb" * function when they are complete. */ -static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1, +static void write_section_data(MpegTSContext *ts, MpegTSFilter *tss1, const uint8_t *buf, int buf_size, int is_start) { - MpegTSContext *ts = s->priv_data; MpegTSSectionFilter *tss = &tss1->u.section_filter; int len; @@ -378,15 +394,16 @@ static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1, tss->section_h_size = len; } - if (tss->section_h_size != -1 && tss->section_index >= tss->section_h_size) { + if (tss->section_h_size != -1 && + tss->section_index >= tss->section_h_size) { int crc_valid = 1; tss->end_of_section_reached = 1; - if (tss->check_crc){ + if (tss->check_crc) { crc_valid = !av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, tss->section_buf, tss->section_h_size); - if (crc_valid){ + if (crc_valid) { ts->crc_validity[ tss1->pid ] = 100; - }else if(ts->crc_validity[ tss1->pid ] > -10){ + }else if (ts->crc_validity[ tss1->pid ] > -10) { ts->crc_validity[ tss1->pid ]--; }else crc_valid = 2; @@ -396,13 +413,10 @@ static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1, } } -static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int pid, - SectionCallback *section_cb, void *opaque, - int check_crc) - +static MpegTSFilter *mpegts_open_filter(MpegTSContext *ts, unsigned int pid, + enum MpegTSFilterType type) { MpegTSFilter *filter; - MpegTSSectionFilter *sec; av_dlog(ts->stream, "Filter: pid=0x%x\n", pid); @@ -412,15 +426,32 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int if (!filter) return NULL; ts->pids[pid] = filter; - filter->type = MPEGTS_SECTION; - filter->pid = pid; - filter->es_id = -1; + + filter->type = type; + filter->pid = pid; + filter->es_id = -1; filter->last_cc = -1; + filter->last_pcr= -1; + + return filter; +} + +static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, + unsigned int pid, + SectionCallback *section_cb, + void *opaque, + int check_crc) +{ + MpegTSFilter *filter; + MpegTSSectionFilter *sec; + + if (!(filter = mpegts_open_filter(ts, pid, MPEGTS_SECTION))) + return NULL; sec = &filter->u.section_filter; - sec->section_cb = section_cb; - sec->opaque = opaque; + sec->section_cb = section_cb; + sec->opaque = opaque; sec->section_buf = av_malloc(MAX_SECTION_SIZE); - sec->check_crc = check_crc; + sec->check_crc = check_crc; if (!sec->section_buf) { av_free(filter); return NULL; @@ -429,28 +460,26 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int } static MpegTSFilter *mpegts_open_pes_filter(MpegTSContext *ts, unsigned int pid, - PESCallback *pes_cb, - void *opaque) + PESCallback *pes_cb, + void *opaque) { MpegTSFilter *filter; MpegTSPESFilter *pes; - if (pid >= NB_PID_MAX || ts->pids[pid]) + if (!(filter = mpegts_open_filter(ts, pid, MPEGTS_PES))) return NULL; - filter = av_mallocz(sizeof(MpegTSFilter)); - if (!filter) - return NULL; - ts->pids[pid] = filter; - filter->type = MPEGTS_PES; - filter->pid = pid; - filter->es_id = -1; - filter->last_cc = -1; + pes = &filter->u.pes_filter; pes->pes_cb = pes_cb; pes->opaque = opaque; return filter; } +static MpegTSFilter *mpegts_open_pcr_filter(MpegTSContext *ts, unsigned int pid) +{ + return mpegts_open_filter(ts, pid, MPEGTS_PCR); +} + static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter) { int pid; @@ -472,20 +501,22 @@ 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 stat[TS_MAX_PACKET_SIZE]; int i; - int best_score=0; + int best_score = 0; - memset(stat, 0, packet_size*sizeof(*stat)); + memset(stat, 0, packet_size * sizeof(*stat)); - for(i=0; i best_score){ - best_score= stat[x]; - if(index) *index= x; + if (stat[x] > best_score) { + best_score = stat[x]; + if (index) + *index = x; } } } @@ -499,18 +530,22 @@ static int get_packet_size(const uint8_t *buf, int size) int score, fec_score, dvhs_score; if (size < (TS_FEC_PACKET_SIZE * 5 + 1)) - return -1; + 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); + 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, dvhs_score, fec_score); - if (score > fec_score && score > dvhs_score) return TS_PACKET_SIZE; - else if(dvhs_score > score && dvhs_score > fec_score) return TS_DVHS_PACKET_SIZE; - else if(score < fec_score && dvhs_score < fec_score) return TS_FEC_PACKET_SIZE; - else return -1; + if (score > fec_score && score > dvhs_score) + return TS_PACKET_SIZE; + else if (dvhs_score > score && dvhs_score > fec_score) + return TS_DVHS_PACKET_SIZE; + else if (score < fec_score && dvhs_score < fec_score) + return TS_FEC_PACKET_SIZE; + else + return AVERROR_INVALIDDATA; } typedef struct SectionHeader { @@ -528,8 +563,8 @@ static inline int get8(const uint8_t **pp, const uint8_t *p_end) p = *pp; if (p >= p_end) - return -1; - c = *p++; + return AVERROR_INVALIDDATA; + c = *p++; *pp = p; return c; } @@ -541,9 +576,9 @@ static inline int get16(const uint8_t **pp, const uint8_t *p_end) p = *pp; if ((p + 1) >= p_end) - return -1; - c = AV_RB16(p); - p += 2; + return AVERROR_INVALIDDATA; + c = AV_RB16(p); + p += 2; *pp = p; return c; } @@ -555,7 +590,7 @@ static char *getstr8(const uint8_t **pp, const uint8_t *p_end) const uint8_t *p; char *str; - p = *pp; + p = *pp; len = get8(&p, p_end); if (len < 0) return NULL; @@ -566,7 +601,7 @@ static char *getstr8(const uint8_t **pp, const uint8_t *p_end) return NULL; memcpy(str, p, len); str[len] = '\0'; - p += len; + p += len; *pp = p; return str; } @@ -578,24 +613,24 @@ static int parse_section_header(SectionHeader *h, val = get8(pp, p_end); if (val < 0) - return -1; + return val; h->tid = val; *pp += 2; - val = get16(pp, p_end); + val = get16(pp, p_end); if (val < 0) - return -1; + return val; h->id = val; val = get8(pp, p_end); if (val < 0) - return -1; + return val; h->version = (val >> 1) & 0x1f; val = get8(pp, p_end); if (val < 0) - return -1; + return val; h->sec_num = val; val = get8(pp, p_end); if (val < 0) - return -1; + return val; h->last_sec_num = val; return 0; } @@ -609,54 +644,54 @@ typedef struct { static const StreamType ISO_types[] = { { 0x01, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG2VIDEO }, { 0x02, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG2VIDEO }, - { 0x03, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3 }, - { 0x04, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3 }, - { 0x0f, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC }, - { 0x10, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG4 }, + { 0x03, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3 }, + { 0x04, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3 }, + { 0x0f, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC }, + { 0x10, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG4 }, /* Makito encoder sets stream type 0x11 for AAC, * so auto-detect LOAS/LATM instead of hardcoding it. */ #if !CONFIG_LOAS_DEMUXER - { 0x11, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC_LATM }, /* LATM syntax */ + { 0x11, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC_LATM }, /* LATM syntax */ #endif - { 0x1b, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 }, - { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC }, - { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS }, - { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, - { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, + { 0x1b, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 }, + { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC }, + { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS }, + { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, + { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, { 0 }, }; static const StreamType HDMV_types[] = { - { 0x80, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_BLURAY }, - { 0x81, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, - { 0x82, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, - { 0x83, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_TRUEHD }, - { 0x84, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, - { 0x85, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, /* DTS HD */ - { 0x86, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, /* DTS HD MASTER*/ - { 0xa1, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, /* E-AC3 Secondary Audio */ - { 0xa2, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, /* DTS Express Secondary Audio */ + { 0x80, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_BLURAY }, + { 0x81, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, + { 0x82, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, + { 0x83, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_TRUEHD }, + { 0x84, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, + { 0x85, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, /* DTS HD */ + { 0x86, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, /* DTS HD MASTER*/ + { 0xa1, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, /* E-AC3 Secondary Audio */ + { 0xa2, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, /* DTS Express Secondary Audio */ { 0x90, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_HDMV_PGS_SUBTITLE }, { 0 }, }; /* ATSC ? */ static const StreamType MISC_types[] = { - { 0x81, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, - { 0x8a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, + { 0x81, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, + { 0x8a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, { 0 }, }; static const StreamType REGD_types[] = { - { MKTAG('d','r','a','c'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, - { MKTAG('A','C','-','3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, - { MKTAG('B','S','S','D'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_S302M }, - { MKTAG('D','T','S','1'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, - { MKTAG('D','T','S','2'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, - { 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('K','L','V','A'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_KLV }, - { MKTAG('V','C','-','1'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, + { MKTAG('d', 'r', 'a', 'c'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, + { MKTAG('A', 'C', '-', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, + { MKTAG('B', 'S', 'S', 'D'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_S302M }, + { MKTAG('D', 'T', 'S', '1'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, + { MKTAG('D', 'T', 'S', '2'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, + { 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('K', 'L', 'V', 'A'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_KLV }, + { MKTAG('V', 'C', '-', '1'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, { 0 }, }; @@ -668,36 +703,36 @@ static const StreamType METADATA_types[] = { /* descriptor present */ static const StreamType DESC_types[] = { - { 0x6a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, /* AC-3 descriptor */ - { 0x7a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, /* E-AC-3 descriptor */ - { 0x7b, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, + { 0x6a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, /* AC-3 descriptor */ + { 0x7a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, /* E-AC-3 descriptor */ + { 0x7b, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, { 0x56, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_DVB_TELETEXT }, { 0x59, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_DVB_SUBTITLE }, /* subtitling descriptor */ { 0 }, }; static void mpegts_find_stream_type(AVStream *st, - uint32_t stream_type, const StreamType *types) + uint32_t stream_type, + const StreamType *types) { if (avcodec_is_open(st->codec)) { av_log(NULL, AV_LOG_DEBUG, "cannot set stream info, codec is open\n"); return; } - for (; types->stream_type; types++) { + 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->request_probe = 0; return; } - } } static int mpegts_set_stream_info(AVStream *st, PESContext *pes, uint32_t stream_type, uint32_t prog_reg_desc) { - int old_codec_type= st->codec->codec_type; + int old_codec_type = st->codec->codec_type; int old_codec_id = st->codec->codec_id; if (avcodec_is_open(st->codec)) { @@ -706,16 +741,16 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes, } avpriv_set_pts_info(st, 33, 1, 90000); - st->priv_data = pes; + st->priv_data = pes; st->codec->codec_type = AVMEDIA_TYPE_DATA; st->codec->codec_id = AV_CODEC_ID_NONE; - st->need_parsing = AVSTREAM_PARSE_FULL; - pes->st = st; + st->need_parsing = AVSTREAM_PARSE_FULL; + pes->st = st; pes->stream_type = stream_type; av_log(pes->stream, AV_LOG_DEBUG, "stream=%d stream_type=%x pid=%x prog_reg_desc=%.4s\n", - st->index, pes->stream_type, pes->pid, (char*)&prog_reg_desc); + st->index, pes->stream_type, pes->pid, (char *)&prog_reg_desc); st->codec->codec_tag = pes->stream_type; @@ -742,23 +777,32 @@ 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->priv_data = sub_pes; sub_st->codec->codec_type = AVMEDIA_TYPE_AUDIO; sub_st->codec->codec_id = AV_CODEC_ID_AC3; - sub_st->need_parsing = AVSTREAM_PARSE_FULL; - sub_pes->sub_st = pes->sub_st = sub_st; + 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) mpegts_find_stream_type(st, pes->stream_type, MISC_types); - if (st->codec->codec_id == AV_CODEC_ID_NONE){ + if (st->codec->codec_id == AV_CODEC_ID_NONE) { st->codec->codec_id = old_codec_id; - st->codec->codec_type= old_codec_type; + st->codec->codec_type = old_codec_type; } return 0; } +static void reset_pes_packet_state(PESContext *pes) +{ + pes->pts = AV_NOPTS_VALUE; + pes->dts = AV_NOPTS_VALUE; + pes->data_index = 0; + pes->flags = 0; + av_buffer_unref(&pes->buffer); +} + static void new_pes_packet(PESContext *pes, AVPacket *pkt) { av_init_packet(pkt); @@ -767,12 +811,13 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt) pkt->data = pes->buffer->data; pkt->size = pes->data_index; - if(pes->total_size != MAX_PES_PAYLOAD && - pes->pes_header_size + pes->data_index != pes->total_size + PES_START_SIZE) { + if (pes->total_size != MAX_PES_PAYLOAD && + pes->pes_header_size + pes->data_index != pes->total_size + + PES_START_SIZE) { 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, FF_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) @@ -782,15 +827,11 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt) pkt->pts = pes->pts; pkt->dts = pes->dts; /* store position of first TS packet of this PES packet */ - pkt->pos = pes->ts_packet_pos; + pkt->pos = pes->ts_packet_pos; pkt->flags = pes->flags; - /* reset pts values */ - pes->pts = AV_NOPTS_VALUE; - pes->dts = AV_NOPTS_VALUE; pes->buffer = NULL; - pes->data_index = 0; - pes->flags = 0; + reset_pes_packet_state(pes); } static uint64_t get_ts64(GetBitContext *gb, int bits) @@ -800,7 +841,8 @@ static uint64_t get_ts64(GetBitContext *gb, int bits) return get_bits64(gb, bits); } -static int read_sl_header(PESContext *pes, SLConfigDescr *sl, const uint8_t *buf, int buf_size) +static int read_sl_header(PESContext *pes, SLConfigDescr *sl, + const uint8_t *buf, int buf_size) { GetBitContext gb; int au_start_flag = 0, au_end_flag = 0, ocr_flag = 0, idle_flag = 0; @@ -808,7 +850,7 @@ static int read_sl_header(PESContext *pes, SLConfigDescr *sl, const uint8_t *buf int dts_flag = -1, cts_flag = -1; int64_t dts = AV_NOPTS_VALUE, cts = AV_NOPTS_VALUE; - init_get_bits(&gb, buf, buf_size*8); + init_get_bits(&gb, buf, buf_size * 8); if (sl->use_au_start) au_start_flag = get_bits1(&gb); @@ -869,31 +911,29 @@ static int read_sl_header(PESContext *pes, SLConfigDescr *sl, const uint8_t *buf /* return non zero if a packet could be constructed */ static int mpegts_push_data(MpegTSFilter *filter, const uint8_t *buf, int buf_size, int is_start, - int64_t pos, int64_t pcr) + int64_t pos) { - PESContext *pes = filter->u.pes_filter.opaque; + PESContext *pes = filter->u.pes_filter.opaque; MpegTSContext *ts = pes->ts; const uint8_t *p; int len, code; - if(!ts->pkt) + if (!ts->pkt) return 0; - if (pcr != -1) - pes->last_pcr = pcr; - if (is_start) { if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) { new_pes_packet(pes, ts->pkt); ts->stop_parse = 1; + } else { + reset_pes_packet_state(pes); } - pes->state = MPEGTS_HEADER; - pes->data_index = 0; + pes->state = MPEGTS_HEADER; pes->ts_packet_pos = pos; } p = buf; while (buf_size > 0) { - switch(pes->state) { + switch (pes->state) { case MPEGTS_HEADER: len = PES_START_SIZE - pes->data_index; if (len > buf_size) @@ -904,20 +944,25 @@ static int mpegts_push_data(MpegTSFilter *filter, buf_size -= len; if (pes->data_index == PES_START_SIZE) { /* we got all the PES or section header. We can now - decide */ + * decide */ if (pes->header[0] == 0x00 && pes->header[1] == 0x00 && pes->header[2] == 0x01) { /* it must be an mpeg2 PES stream */ code = pes->header[3] | 0x100; - av_dlog(pes->stream, "pid=%x pes_code=%#x\n", pes->pid, code); + av_dlog(pes->stream, "pid=%x pes_code=%#x\n", pes->pid, + code); if ((pes->st && pes->st->discard == AVDISCARD_ALL && - (!pes->sub_st || pes->sub_st->discard == AVDISCARD_ALL)) || + (!pes->sub_st || + pes->sub_st->discard == AVDISCARD_ALL)) || code == 0x1be) /* padding_stream */ goto skip; /* stream not present in PMT */ if (!pes->st) { + if (ts->skip_changes) + goto skip; + pes->st = avformat_new_stream(ts->stream, NULL); if (!pes->st) return AVERROR(ENOMEM); @@ -927,7 +972,7 @@ static int mpegts_push_data(MpegTSFilter *filter, pes->total_size = AV_RB16(pes->header + 4); /* NOTE: a zero total size means the PES size is - unbounded */ + * unbounded */ if (!pes->total_size) pes->total_size = MAX_PES_PAYLOAD; @@ -943,29 +988,31 @@ static int mpegts_push_data(MpegTSFilter *filter, 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 && !pes->st->request_probe) { - av_dlog(pes->stream, "pid=%x stream_type=%x probing\n", - pes->pid, pes->stream_type); - pes->st->request_probe= 1; + av_dlog(pes->stream, + "pid=%x stream_type=%x probing\n", + pes->pid, + pes->stream_type); + pes->st->request_probe = 1; } } else { - pes->state = MPEGTS_PAYLOAD; + pes->state = MPEGTS_PAYLOAD; pes->data_index = 0; } } else { /* otherwise, it should be a table */ /* skip packet */ - skip: +skip: pes->state = MPEGTS_SKIP; continue; } } break; - /**********************************************/ - /* PES packing parsing */ + /**********************************************/ + /* PES packing parsing */ case MPEGTS_PESHEADER: len = PES_HEADER_SIZE - pes->data_index; if (len < 0) - return -1; + return AVERROR_INVALIDDATA; if (len > buf_size) len = buf_size; memcpy(pes->header + pes->data_index, p, len); @@ -974,13 +1021,13 @@ static int mpegts_push_data(MpegTSFilter *filter, buf_size -= len; if (pes->data_index == PES_HEADER_SIZE) { pes->pes_header_size = pes->header[8] + 9; - pes->state = MPEGTS_PESHEADER_FILL; + pes->state = MPEGTS_PESHEADER_FILL; } break; case MPEGTS_PESHEADER_FILL: len = pes->pes_header_size - pes->data_index; if (len < 0) - return -1; + return AVERROR_INVALIDDATA; if (len > buf_size) len = buf_size; memcpy(pes->header + pes->data_index, p, len); @@ -1008,9 +1055,9 @@ static int mpegts_push_data(MpegTSFilter *filter, if (flags & 0x01) { /* PES extension */ pes_ext = *r++; /* Skip PES private data, program packet sequence counter and P-STD buffer */ - skip = (pes_ext >> 4) & 0xb; + skip = (pes_ext >> 4) & 0xb; skip += skip & 0x9; - r += skip; + r += skip; if ((pes_ext & 0x41) == 0x01 && (r + 2) <= (pes->header + pes->pes_header_size)) { /* PES extension 2 */ @@ -1023,7 +1070,8 @@ static int mpegts_push_data(MpegTSFilter *filter, pes->state = MPEGTS_PAYLOAD; pes->data_index = 0; if (pes->stream_type == 0x12 && buf_size > 0) { - int sl_header_bytes = read_sl_header(pes, &pes->sl, p, buf_size); + int sl_header_bytes = read_sl_header(pes, &pes->sl, p, + buf_size); pes->pes_header_size += sl_header_bytes; p += sl_header_bytes; buf_size -= sl_header_bytes; @@ -1039,16 +1087,28 @@ static int mpegts_push_data(MpegTSFilter *filter, while ((p = av_find_program_from_stream(pes->stream, p, pes->st->index))) { if (p->pcr_pid != -1 && p->discard != AVDISCARD_ALL) { MpegTSFilter *f = pes->ts->pids[p->pcr_pid]; - if (f && f->type == MPEGTS_PES) { - PESContext *pcrpes = f->u.pes_filter.opaque; - if (pcrpes && pcrpes->last_pcr != -1 && pcrpes->st && pcrpes->st->discard != AVDISCARD_ALL) { + if (f) { + AVStream *st = NULL; + if (f->type == MPEGTS_PES) { + PESContext *pcrpes = f->u.pes_filter.opaque; + if (pcrpes) + st = pcrpes->st; + } else if (f->type == MPEGTS_PCR) { + int i; + for (i = 0; i < p->nb_stream_indexes; i++) { + AVStream *pst = pes->stream->streams[p->stream_index[i]]; + if (pst->codec->codec_type == AVMEDIA_TYPE_VIDEO) + st = pst; + } + } + if (f->last_pcr != -1 && st && st->discard != AVDISCARD_ALL) { // teletext packets do not always have correct timestamps, // the standard says they should be handled after 40.6 ms at most, // and the pcr error to this packet should be no more than 100 ms. // TODO: we should interpolate the PCR, not just use the last one - int64_t pcr = pcrpes->last_pcr / 300; - pes->st->pts_wrap_reference = pcrpes->st->pts_wrap_reference; - pes->st->pts_wrap_behavior = pcrpes->st->pts_wrap_behavior; + int64_t pcr = f->last_pcr / 300; + pes->st->pts_wrap_reference = st->pts_wrap_reference; + pes->st->pts_wrap_behavior = st->pts_wrap_behavior; if (pes->dts == AV_NOPTS_VALUE || pes->dts < pcr) { pes->pts = pes->dts = pcr; } else if (pes->dts > pcr + 3654 + 9000) { @@ -1063,33 +1123,36 @@ static int mpegts_push_data(MpegTSFilter *filter, } break; case MPEGTS_PAYLOAD: - if (buf_size > 0 && pes->buffer) { - if (pes->data_index > 0 && pes->data_index+buf_size > pes->total_size) { + if (pes->buffer) { + if (pes->data_index > 0 && + pes->data_index + buf_size > pes->total_size) { 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); + pes->buffer = av_buffer_alloc(pes->total_size + + FF_INPUT_BUFFER_PADDING_SIZE); if (!pes->buffer) return AVERROR(ENOMEM); ts->stop_parse = 1; - } else if (pes->data_index == 0 && buf_size > pes->total_size) { + } else if (pes->data_index == 0 && + buf_size > pes->total_size) { // pes packet size is < ts size packet and pes data is padded with 0xff // not sure if this is legal in ts but see issue #2392 buf_size = pes->total_size; } memcpy(pes->buffer->data + pes->data_index, p, buf_size); pes->data_index += buf_size; + /* emit complete packets with known packet size + * decreases demuxer delay for infrequent packets like subtitles from + * a couple of seconds to milliseconds for properly muxed files. + * total_size is the number of bytes following pes_packet_length + * in the pes header, i.e. not counting the first PES_START_SIZE bytes */ + if (!ts->stop_parse && pes->total_size < MAX_PES_PAYLOAD && + pes->pes_header_size + pes->data_index == pes->total_size + PES_START_SIZE) { + ts->stop_parse = 1; + new_pes_packet(pes, ts->pkt); + } } buf_size = 0; - /* emit complete packets with known packet size - * decreases demuxer delay for infrequent packets like subtitles from - * a couple of seconds to milliseconds for properly muxed files. - * total_size is the number of bytes following pes_packet_length - * in the pes header, i.e. not counting the first PES_START_SIZE bytes */ - if (!ts->stop_parse && pes->total_size < MAX_PES_PAYLOAD && - pes->pes_header_size + pes->data_index == pes->total_size + PES_START_SIZE) { - ts->stop_parse = 1; - new_pes_packet(pes, ts->pkt); - } break; case MPEGTS_SKIP: buf_size = 0; @@ -1109,15 +1172,14 @@ static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid) pes = av_mallocz(sizeof(PESContext)); if (!pes) return 0; - pes->ts = ts; - pes->stream = ts->stream; - pes->pid = pid; + pes->ts = ts; + pes->stream = ts->stream; + pes->pid = pid; pes->pcr_pid = pcr_pid; - pes->state = MPEGTS_SKIP; - pes->pts = AV_NOPTS_VALUE; - pes->dts = AV_NOPTS_VALUE; - pes->last_pcr = -1; - tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes); + pes->state = MPEGTS_SKIP; + pes->pts = AV_NOPTS_VALUE; + pes->dts = AV_NOPTS_VALUE; + tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes); if (!tss) { av_free(pes); return 0; @@ -1134,34 +1196,36 @@ typedef struct { int descr_count; int max_descr_count; int level; + int predefined_SLConfigDescriptor_seen; } MP4DescrParseContext; -static int init_MP4DescrParseContext( - MP4DescrParseContext *d, AVFormatContext *s, const uint8_t *buf, - unsigned size, Mp4Descr *descr, int max_descr_count) +static int init_MP4DescrParseContext(MP4DescrParseContext *d, AVFormatContext *s, + const uint8_t *buf, unsigned size, + Mp4Descr *descr, int max_descr_count) { int ret; - if (size > (1<<30)) + if (size > (1 << 30)) return AVERROR_INVALIDDATA; - if ((ret = ffio_init_context(&d->pb, (unsigned char*)buf, size, 0, - NULL, NULL, NULL, NULL)) < 0) + if ((ret = ffio_init_context(&d->pb, (unsigned char *)buf, size, 0, + NULL, NULL, NULL, NULL)) < 0) return ret; - d->s = s; - d->level = 0; - d->descr_count = 0; - d->descr = descr; - d->active_descr = NULL; + d->s = s; + d->level = 0; + d->descr_count = 0; + d->descr = descr; + d->active_descr = NULL; d->max_descr_count = max_descr_count; return 0; } -static void update_offsets(AVIOContext *pb, int64_t *off, int *len) { +static void update_offsets(AVIOContext *pb, int64_t *off, int *len) +{ int64_t new_off = avio_tell(pb); (*len) -= new_off - *off; - *off = new_off; + *off = new_off; } static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, @@ -1170,8 +1234,9 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, static int parse_mp4_descr_arr(MP4DescrParseContext *d, int64_t off, int len) { while (len > 0) { - if (parse_mp4_descr(d, off, len, 0) < 0) - return -1; + int ret = parse_mp4_descr(d, off, len, 0); + if (ret < 0) + return ret; update_offsets(&d->pb, &off, &len); } return 0; @@ -1195,9 +1260,9 @@ static int parse_MP4ODescrTag(MP4DescrParseContext *d, int64_t off, int len) if (len < 2) return 0; id_flags = avio_rb16(&d->pb); - if (!(id_flags & 0x0020)) { //URL_Flag + if (!(id_flags & 0x0020)) { // URL_Flag update_offsets(&d->pb, &off, &len); - return parse_mp4_descr_arr(d, off, len); //ES_Descriptor[] + return parse_mp4_descr_arr(d, off, len); // ES_Descriptor[] } else { return 0; } @@ -1207,7 +1272,7 @@ static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len) { int es_id = 0; if (d->descr_count >= d->max_descr_count) - return -1; + return AVERROR_INVALIDDATA; ff_mp4_parse_es_descr(&d->pb, &es_id); d->active_descr = d->descr + (d->descr_count++); @@ -1221,11 +1286,12 @@ static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len) return 0; } -static int parse_MP4DecConfigDescrTag(MP4DescrParseContext *d, int64_t off, int len) +static int parse_MP4DecConfigDescrTag(MP4DescrParseContext *d, int64_t off, + int len) { Mp4Descr *descr = d->active_descr; if (!descr) - return -1; + return AVERROR_INVALIDDATA; d->active_descr->dec_config_descr = av_malloc(len); if (!descr->dec_config_descr) return AVERROR(ENOMEM); @@ -1239,20 +1305,20 @@ static int parse_MP4SLDescrTag(MP4DescrParseContext *d, int64_t off, int len) Mp4Descr *descr = d->active_descr; int predefined; if (!descr) - return -1; + return AVERROR_INVALIDDATA; predefined = avio_r8(&d->pb); if (!predefined) { int lengths; int flags = avio_r8(&d->pb); - descr->sl.use_au_start = !!(flags & 0x80); - descr->sl.use_au_end = !!(flags & 0x40); - descr->sl.use_rand_acc_pt = !!(flags & 0x20); - descr->sl.use_padding = !!(flags & 0x08); - descr->sl.use_timestamps = !!(flags & 0x04); - descr->sl.use_idle = !!(flags & 0x02); - descr->sl.timestamp_res = avio_rb32(&d->pb); - avio_rb32(&d->pb); + descr->sl.use_au_start = !!(flags & 0x80); + descr->sl.use_au_end = !!(flags & 0x40); + descr->sl.use_rand_acc_pt = !!(flags & 0x20); + descr->sl.use_padding = !!(flags & 0x08); + descr->sl.use_timestamps = !!(flags & 0x04); + descr->sl.use_idle = !!(flags & 0x02); + descr->sl.timestamp_res = avio_rb32(&d->pb); + avio_rb32(&d->pb); descr->sl.timestamp_len = avio_r8(&d->pb); if (descr->sl.timestamp_len > 64) { avpriv_request_sample(NULL, "timestamp_len > 64"); @@ -1266,20 +1332,24 @@ 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; - } else { + } else if (!d->predefined_SLConfigDescriptor_seen){ avpriv_report_missing_feature(d->s, "Predefined SLConfigDescriptor"); + d->predefined_SLConfigDescriptor_seen = 1; } return 0; } static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, - int target_tag) { + int target_tag) +{ int tag; int len1 = ff_mp4_read_descr(d->s, &d->pb, &tag); update_offsets(&d->pb, &off, &len); if (len < 0 || len1 > len || len1 <= 0) { - av_log(d->s, AV_LOG_ERROR, "Tag %x length violation new length %d bytes remaining %d\n", tag, len1, len); - return -1; + av_log(d->s, AV_LOG_ERROR, + "Tag %x length violation new length %d bytes remaining %d\n", + tag, len1, len); + return AVERROR_INVALIDDATA; } if (d->level++ >= MAX_LEVEL) { @@ -1288,7 +1358,8 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, } if (target_tag && tag != target_tag) { - av_log(d->s, AV_LOG_ERROR, "Found tag %x expected %x\n", tag, target_tag); + av_log(d->s, AV_LOG_ERROR, "Found tag %x expected %x\n", tag, + target_tag); goto done; } @@ -1310,6 +1381,7 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, break; } + done: d->level--; avio_seek(&d->pb, off + len1, SEEK_SET); @@ -1320,36 +1392,43 @@ static int mp4_read_iods(AVFormatContext *s, const uint8_t *buf, unsigned size, Mp4Descr *descr, int *descr_count, int max_descr_count) { MP4DescrParseContext d; - if (init_MP4DescrParseContext(&d, s, buf, size, descr, max_descr_count) < 0) - return -1; + int ret; - parse_mp4_descr(&d, avio_tell(&d.pb), size, MP4IODescrTag); + ret = init_MP4DescrParseContext(&d, s, buf, size, descr, max_descr_count); + if (ret < 0) + return ret; + + ret = parse_mp4_descr(&d, avio_tell(&d.pb), size, MP4IODescrTag); *descr_count = d.descr_count; - return 0; + return ret; } static int mp4_read_od(AVFormatContext *s, const uint8_t *buf, unsigned size, Mp4Descr *descr, int *descr_count, int max_descr_count) { MP4DescrParseContext d; - if (init_MP4DescrParseContext(&d, s, buf, size, descr, max_descr_count) < 0) - return -1; + int ret; - parse_mp4_descr_arr(&d, avio_tell(&d.pb), size); + ret = init_MP4DescrParseContext(&d, s, buf, size, descr, max_descr_count); + if (ret < 0) + return ret; + + ret = parse_mp4_descr_arr(&d, avio_tell(&d.pb), size); *descr_count = d.descr_count; - return 0; + return ret; } -static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_len) +static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, + int section_len) { MpegTSContext *ts = filter->u.section_filter.opaque; SectionHeader h; const uint8_t *p, *p_end; AVIOContext pb; - Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = {{ 0 }}; int mp4_descr_count = 0; + Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = { { 0 } }; int i, pid; AVFormatContext *s = ts->stream; @@ -1360,11 +1439,12 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_le if (h.tid != M4OD_TID) return; - mp4_read_od(s, p, (unsigned)(p_end - p), mp4_descr, &mp4_descr_count, MAX_MP4_DESCR_COUNT); + mp4_read_od(s, p, (unsigned) (p_end - p), mp4_descr, &mp4_descr_count, + MAX_MP4_DESCR_COUNT); for (pid = 0; pid < NB_PID_MAX; pid++) { if (!ts->pids[pid]) - continue; + continue; for (i = 0; i < mp4_descr_count; i++) { PESContext *pes; AVStream *st; @@ -1375,15 +1455,15 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_le continue; } pes = ts->pids[pid]->u.pes_filter.opaque; - st = pes->st; - if (!st) { + st = pes->st; + if (!st) continue; - } pes->sl = mp4_descr[i].sl; ffio_init_context(&pb, mp4_descr[i].dec_config_descr, - mp4_descr[i].dec_config_descr_len, 0, NULL, NULL, NULL, NULL); + 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) @@ -1393,13 +1473,13 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_le st->need_parsing = 0; if (st->codec->codec_id <= AV_CODEC_ID_NONE) { - } else if (st->codec->codec_id < AV_CODEC_ID_FIRST_AUDIO) { + // 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) { + 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) { + else if (st->codec->codec_id < AV_CODEC_ID_FIRST_UNKNOWN) st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - } } } for (i = 0; i < mp4_descr_count; i++) @@ -1418,13 +1498,13 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type desc_tag = get8(pp, desc_list_end); if (desc_tag < 0) - return -1; + return AVERROR_INVALIDDATA; desc_len = get8(pp, desc_list_end); if (desc_len < 0) - return -1; + return AVERROR_INVALIDDATA; desc_end = *pp + desc_len; if (desc_end > desc_list_end) - return -1; + return AVERROR_INVALIDDATA; av_dlog(fc, "tag: 0x%02x len=%d\n", desc_tag, desc_len); @@ -1432,37 +1512,40 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type stream_type == STREAM_TYPE_PRIVATE_DATA) mpegts_find_stream_type(st, desc_tag, DESC_types); - switch(desc_tag) { + switch (desc_tag) { case 0x1E: /* SL descriptor */ desc_es_id = get16(pp, desc_end); if (ts && ts->pids[pid]) ts->pids[pid]->es_id = desc_es_id; for (i = 0; i < mp4_descr_count; i++) - if (mp4_descr[i].dec_config_descr_len && - mp4_descr[i].es_id == desc_es_id) { - AVIOContext pb; - ffio_init_context(&pb, mp4_descr[i].dec_config_descr, - 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) - st->need_parsing = 0; - if (st->codec->codec_id == AV_CODEC_ID_MPEG4SYSTEMS) - mpegts_open_section_filter(ts, pid, m4sl_cb, ts, 1); - } + if (mp4_descr[i].dec_config_descr_len && + mp4_descr[i].es_id == desc_es_id) { + AVIOContext pb; + ffio_init_context(&pb, mp4_descr[i].dec_config_descr, + 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) + st->need_parsing = 0; + if (st->codec->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 (mp4_descr_count > 0 && (st->codec->codec_id == AV_CODEC_ID_AAC_LATM || st->request_probe>0) && + if (mp4_descr_count > 0 && + (st->codec->codec_id == AV_CODEC_ID_AAC_LATM || st->request_probe > 0) && 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); + 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){ - st->request_probe= st->need_parsing = 0; - st->codec->codec_type= AVMEDIA_TYPE_AUDIO; + st->codec->extradata_size > 0) { + st->request_probe = st->need_parsing = 0; + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; } } break; @@ -1550,7 +1633,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type language[i * 4 + 3] = ','; /* hearing impaired subtitles detection using subtitling_type */ - switch(*pp[0]) { + switch (*pp[0]) { case 0x20: /* DVB subtitles (for the hard of hearing) with no monitor aspect ratio criticality */ case 0x21: /* DVB subtitles (for the hard of hearing) for display on 4:3 aspect ratio monitor */ case 0x22: /* DVB subtitles (for the hard of hearing) for display on 16:9 aspect ratio monitor */ @@ -1579,11 +1662,17 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type language[i + 1] = get8(pp, desc_end); language[i + 2] = get8(pp, desc_end); language[i + 3] = ','; - switch (get8(pp, desc_end)) { - case 0x01: st->disposition |= AV_DISPOSITION_CLEAN_EFFECTS; break; - case 0x02: st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; break; - case 0x03: st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; break; - } + switch (get8(pp, desc_end)) { + case 0x01: + st->disposition |= AV_DISPOSITION_CLEAN_EFFECTS; + break; + case 0x02: + st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; + break; + case 0x03: + st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; + break; + } } if (i) { language[i - 1] = 0; @@ -1592,7 +1681,7 @@ 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); + 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); break; @@ -1626,8 +1715,8 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len int desc_list_len; uint32_t prog_reg_desc = 0; /* registration descriptor */ - Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = {{ 0 }}; int mp4_descr_count = 0; + Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = { { 0 } }; int i; av_dlog(ts->stream, "PMT: len %i\n", section_len); @@ -1639,10 +1728,12 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len return; av_dlog(ts->stream, "sid=0x%x sec_num=%d/%d\n", - h->id, h->sec_num, h->last_sec_num); + h->id, h->sec_num, h->last_sec_num); if (h->tid != PMT_TID) return; + if (ts->skip_changes) + return; clear_program(ts, h->id); pcr_pid = get16(&p, p_end); @@ -1658,15 +1749,15 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (program_info_length < 0) return; program_info_length &= 0xfff; - while(program_info_length >= 2) { + while (program_info_length >= 2) { uint8_t tag, len; tag = get8(&p, p_end); len = get8(&p, p_end); av_dlog(ts->stream, "program tag: 0x%02x len=%d\n", tag, len); - if(len > program_info_length - 2) - //something else is broken, exit the program_descriptors_loop + if (len > program_info_length - 2) + // something else is broken, exit the program_descriptors_loop break; program_info_length -= len + 2; if (tag == 0x1d) { // IOD descriptor @@ -1691,7 +1782,8 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len set_pmt_found(ts, h->id); - for(;;) { + + for (;;) { st = 0; pes = NULL; stream_type = get8(&p, p_end); @@ -1699,23 +1791,24 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len break; pid = get16(&p, p_end); if (pid < 0) - break; + goto out; pid &= 0x1fff; if (pid == ts->current_pid) - break; + goto out; /* now create stream */ if (ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES) { pes = ts->pids[pid]->u.pes_filter.opaque; if (!pes->st) { - pes->st = avformat_new_stream(pes->stream, NULL); + pes->st = avformat_new_stream(pes->stream, NULL); if (!pes->st) goto out; pes->st->id = pes->pid; } st = pes->st; } else if (stream_type != 0x13) { - if (ts->pids[pid]) mpegts_close_filter(ts, ts->pids[pid]); //wrongly added sdt filter probably + if (ts->pids[pid]) + mpegts_close_filter(ts, ts->pids[pid]); // wrongly added sdt filter probably pes = add_pes_stream(ts, pid, pcr_pid); if (pes) { st = avformat_new_stream(pes->stream, NULL); @@ -1748,25 +1841,31 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len desc_list_len = get16(&p, p_end); if (desc_list_len < 0) - break; + goto out; desc_list_len &= 0xfff; - desc_list_end = p + desc_list_len; + desc_list_end = p + desc_list_len; if (desc_list_end > p_end) - break; - for(;;) { - if (ff_parse_mpeg2_descriptor(ts->stream, st, stream_type, &p, desc_list_end, - mp4_descr, mp4_descr_count, pid, ts) < 0) + goto out; + for (;;) { + if (ff_parse_mpeg2_descriptor(ts->stream, st, stream_type, &p, + desc_list_end, mp4_descr, + mp4_descr_count, pid, ts) < 0) break; - if (pes && prog_reg_desc == AV_RL32("HDMV") && stream_type == 0x83 && pes->sub_st) { - ff_program_add_stream_index(ts->stream, h->id, pes->sub_st->index); + if (pes && prog_reg_desc == AV_RL32("HDMV") && + 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; } } p = desc_list_end; } - out: + if (!ts->pids[pcr_pid]) + mpegts_open_pcr_filter(ts, pcr_pid); + +out: for (i = 0; i < mp4_descr_count; i++) av_free(mp4_descr[i].dec_config_descr); } @@ -1783,16 +1882,18 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len hex_dump_debug(ts->stream, section, section_len); p_end = section + section_len - 4; - p = section; + p = section; if (parse_section_header(h, &p, p_end) < 0) return; if (h->tid != PAT_TID) return; + if (ts->skip_changes) + return; ts->stream->ts_id = h->id; clear_programs(ts); - for(;;) { + for (;;) { sid = get16(&p, p_end); if (sid < 0) break; @@ -1822,7 +1923,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (!ts->pids[pmt_pid]) mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1); add_pat_entry(ts, sid); - add_pid_to_pmt(ts, sid, 0); //add pat pid to program + add_pid_to_pmt(ts, sid, 0); // add pat pid to program add_pid_to_pmt(ts, sid, pmt_pid); } } @@ -1830,10 +1931,10 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (sid < 0) { int i,j; for (j=0; jstream->nb_programs; j++) { - for (i=0; inb_prg; i++) + for (i = 0; i < ts->nb_prg; i++) if (ts->prg[i].id == ts->stream->programs[j]->id) break; - if (i==ts->nb_prg) + if (i==ts->nb_prg && !ts->skip_clear) clear_avprogram(ts, ts->stream->programs[j]->id); } } @@ -1851,18 +1952,20 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len hex_dump_debug(ts->stream, section, section_len); p_end = section + section_len - 4; - p = section; + p = section; if (parse_section_header(h, &p, p_end) < 0) return; if (h->tid != SDT_TID) return; + if (ts->skip_changes) + return; onid = get16(&p, p_end); if (onid < 0) return; val = get8(&p, p_end); if (val < 0) return; - for(;;) { + for (;;) { sid = get16(&p, p_end); if (sid < 0) break; @@ -1873,10 +1976,10 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (desc_list_len < 0) break; desc_list_len &= 0xfff; - desc_list_end = p + desc_list_len; + desc_list_end = p + desc_list_len; if (desc_list_end > p_end) break; - for(;;) { + for (;;) { desc_tag = get8(&p, desc_list_end); if (desc_tag < 0) break; @@ -1886,9 +1989,9 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len break; av_dlog(ts->stream, "tag: 0x%02x len=%d\n", - desc_tag, desc_len); + desc_tag, desc_len); - switch(desc_tag) { + switch (desc_tag) { case 0x48: service_type = get8(&p, p_end); if (service_type < 0) @@ -1899,9 +2002,10 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len name = getstr8(&p, p_end); if (name) { AVProgram *program = av_new_program(ts->stream, sid); - if(program) { + if (program) { av_dict_set(&program->metadata, "service_name", name, 0); - av_dict_set(&program->metadata, "service_provider", provider_name, 0); + av_dict_set(&program->metadata, "service_provider", + provider_name, 0); } } av_free(name); @@ -1922,7 +2026,6 @@ static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, /* handle one TS packet */ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) { - AVFormatContext *s = ts->stream; MpegTSFilter *tss; int len, pid, cc, expected_cc, cc_ok, afc, is_start, is_discontinuity, has_adaptation, has_payload; @@ -1930,7 +2033,7 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) int64_t pos; pid = AV_RB16(packet + 1) & 0x1fff; - if(pid && discard_pid(ts, pid)) + if (pid && discard_pid(ts, pid)) return 0; is_start = packet[1] & 0x40; tss = ts->pids[pid]; @@ -1945,32 +2048,32 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) afc = (packet[3] >> 4) & 3; if (afc == 0) /* reserved value */ return 0; - has_adaptation = afc & 2; - has_payload = afc & 1; - is_discontinuity = has_adaptation - && packet[4] != 0 /* with length > 0 */ - && (packet[5] & 0x80); /* and discontinuity indicated */ + has_adaptation = afc & 2; + has_payload = afc & 1; + is_discontinuity = has_adaptation && + packet[4] != 0 && /* with length > 0 */ + (packet[5] & 0x80); /* and discontinuity indicated */ /* continuity check (currently not used) */ cc = (packet[3] & 0xf); expected_cc = has_payload ? (tss->last_cc + 1) & 0x0f : tss->last_cc; - cc_ok = pid == 0x1FFF // null packet PID - || is_discontinuity - || tss->last_cc < 0 - || expected_cc == cc; + cc_ok = pid == 0x1FFF || // null packet PID + is_discontinuity || + tss->last_cc < 0 || + expected_cc == cc; tss->last_cc = cc; if (!cc_ok) { av_log(ts->stream, AV_LOG_DEBUG, "Continuity check failed for pid %d expected %d got %d\n", pid, expected_cc, cc); - if(tss->type == MPEGTS_PES) { + if (tss->type == MPEGTS_PES) { PESContext *pc = tss->u.pes_filter.opaque; pc->flags |= AV_PKT_FLAG_CORRUPT; } } - if (!has_payload) + if (!has_payload && tss->type != MPEGTS_PCR) return 0; p = packet + 4; if (has_adaptation) { @@ -1979,7 +2082,7 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) } /* if past the end of packet, ignore */ p_end = packet + TS_PACKET_SIZE; - if (p >= p_end) + if (p > p_end || (p == p_end && tss->type != MPEGTS_PCR)) return 0; pos = avio_tell(ts->stream->pb); @@ -1996,7 +2099,7 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) return 0; if (len && cc_ok) { /* write remaining section bytes */ - write_section_data(s, tss, + write_section_data(ts, tss, p, len, 0); /* check whether filter has been closed */ if (!ts->pids[pid]) @@ -2004,21 +2107,21 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) } p += len; if (p < p_end) { - write_section_data(s, tss, + write_section_data(ts, tss, p, p_end - p, 1); } } else { if (cc_ok) { - write_section_data(s, tss, + write_section_data(ts, tss, p, p_end - p, 0); } } // stop find_stream_info from waiting for more streams // when all programs have received a PMT - if(ts->stream->ctx_flags & AVFMTCTX_NOHEADER) { + if (ts->stream->ctx_flags & AVFMTCTX_NOHEADER) { int i; - for(i=0; inb_prg; i++) { + for (i = 0; i < ts->nb_prg; i++) { if (!ts->prg[i].pmt_found) break; } @@ -2032,15 +2135,16 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) } else { int ret; - int64_t pcr = -1; int64_t pcr_h; int pcr_l; if (parse_pcr(&pcr_h, &pcr_l, packet) == 0) - pcr = pcr_h * 300 + pcr_l; + tss->last_pcr = pcr_h * 300 + pcr_l; // Note: The position here points actually behind the current packet. - if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start, - pos - ts->raw_packet_size, pcr)) < 0) - return ret; + if (tss->type == MPEGTS_PES) { + if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start, + pos - ts->raw_packet_size)) < 0) + return ret; + } } return 0; @@ -2049,7 +2153,7 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) static void reanalyze(MpegTSContext *ts) { AVIOContext *pb = ts->stream->pb; int64_t pos = avio_tell(pb); - if(pos < 0) + if (pos < 0) return; pos -= ts->pos47_full; if (pos == TS_PACKET_SIZE) { @@ -2061,7 +2165,7 @@ static void reanalyze(MpegTSContext *ts) { } ts->size_stat_count ++; - if(ts->size_stat_count > SIZE_STAT_THRESHOLD) { + if (ts->size_stat_count > SIZE_STAT_THRESHOLD) { int newsize = 0; if (ts->size_stat[0] > SIZE_STAT_THRESHOLD) { newsize = TS_PACKET_SIZE; @@ -2080,34 +2184,36 @@ static void reanalyze(MpegTSContext *ts) { } /* XXX: try to find a better synchro over several packets (use - get_packet_size() ?) */ + * get_packet_size() ?) */ static int mpegts_resync(AVFormatContext *s) { AVIOContext *pb = s->pb; int c, i; - for(i = 0;i < MAX_RESYNC_SIZE; i++) { + for (i = 0; i < MAX_RESYNC_SIZE; i++) { c = avio_r8(pb); if (url_feof(pb)) - return -1; + return AVERROR_EOF; if (c == 0x47) { avio_seek(pb, -1, SEEK_CUR); reanalyze(s->priv_data); return 0; } } - av_log(s, AV_LOG_ERROR, "max resync size reached, could not find sync byte\n"); + av_log(s, AV_LOG_ERROR, + "max resync size reached, could not find sync byte\n"); /* no sync found */ - return -1; + return AVERROR_INVALIDDATA; } -/* return -1 if error or EOF. Return 0 if OK. */ -static int read_packet(AVFormatContext *s, uint8_t *buf, int raw_packet_size, const uint8_t **data) +/* return AVERROR_something if error or EOF. Return 0 if OK. */ +static int read_packet(AVFormatContext *s, uint8_t *buf, int raw_packet_size, + const uint8_t **data) { AVIOContext *pb = s->pb; int len; - for(;;) { + for (;;) { len = ffio_read_indirect(pb, buf, TS_PACKET_SIZE, data); if (len != TS_PACKET_SIZE) return len < 0 ? len : AVERROR_EOF; @@ -2150,13 +2256,13 @@ static int handle_packets(MpegTSContext *ts, int nb_packets) for (i = 0; i < NB_PID_MAX; i++) { if (ts->pids[i]) { if (ts->pids[i]->type == MPEGTS_PES) { - PESContext *pes = ts->pids[i]->u.pes_filter.opaque; - av_buffer_unref(&pes->buffer); - pes->data_index = 0; - pes->state = MPEGTS_SKIP; /* skip until pes header */ - pes->last_pcr = -1; + PESContext *pes = ts->pids[i]->u.pes_filter.opaque; + av_buffer_unref(&pes->buffer); + pes->data_index = 0; + pes->state = MPEGTS_SKIP; /* skip until pes header */ } ts->pids[i]->last_cc = -1; + ts->pids[i]->last_pcr = -1; } } } @@ -2164,7 +2270,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); - for(;;) { + for (;;) { packet_num++; if (nb_packets != 0 && packet_num >= nb_packets || ts->stop_parse > 1) { @@ -2188,41 +2294,41 @@ static int handle_packets(MpegTSContext *ts, int nb_packets) static int mpegts_probe(AVProbeData *p) { - const int size= p->buf_size; - int maxscore=0; - int sumscore=0; + const int size = p->buf_size; + int maxscore = 0; + int sumscore = 0; int i; - int check_count= size / TS_FEC_PACKET_SIZE; + int check_count = size / TS_FEC_PACKET_SIZE; #define CHECK_COUNT 10 #define CHECK_BLOCK 100 if (check_count < CHECK_COUNT) - return -1; + return AVERROR_INVALIDDATA; - for (i=0; ibuf + TS_PACKET_SIZE *i, TS_PACKET_SIZE *left, TS_PACKET_SIZE , NULL); - int dvhs_score= analyze(p->buf + TS_DVHS_PACKET_SIZE*i, TS_DVHS_PACKET_SIZE*left, TS_DVHS_PACKET_SIZE, NULL); - int fec_score = analyze(p->buf + TS_FEC_PACKET_SIZE *i, TS_FEC_PACKET_SIZE *left, TS_FEC_PACKET_SIZE , NULL); + int score = analyze(p->buf + TS_PACKET_SIZE *i, TS_PACKET_SIZE *left, TS_PACKET_SIZE , NULL); + int dvhs_score = analyze(p->buf + TS_DVHS_PACKET_SIZE*i, TS_DVHS_PACKET_SIZE*left, TS_DVHS_PACKET_SIZE, NULL); + int fec_score = analyze(p->buf + TS_FEC_PACKET_SIZE *i, TS_FEC_PACKET_SIZE *left, TS_FEC_PACKET_SIZE , NULL); score = FFMAX3(score, dvhs_score, fec_score); sumscore += score; maxscore = FFMAX(maxscore, score); } - sumscore = sumscore*CHECK_COUNT/check_count; - maxscore = maxscore*CHECK_COUNT/CHECK_BLOCK; + sumscore = sumscore * CHECK_COUNT / check_count; + maxscore = maxscore * CHECK_COUNT / CHECK_BLOCK; av_dlog(0, "TS score: %d %d\n", sumscore, maxscore); - if (sumscore > 6) return AVPROBE_SCORE_MAX + sumscore - CHECK_COUNT; - else if (maxscore > 6) return AVPROBE_SCORE_MAX/2 + sumscore - CHECK_COUNT; - else return -1; + if (sumscore > 6) return AVPROBE_SCORE_MAX + sumscore - CHECK_COUNT; + else if (maxscore > 6) return AVPROBE_SCORE_MAX/2 + sumscore - CHECK_COUNT; + else + return AVERROR_INVALIDDATA; } /* return the 90kHz PCR and the extension for the 27MHz PCR. return - (-1) if not available */ -static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, - const uint8_t *packet) + * (-1) if not available */ +static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, const uint8_t *packet) { int afc, len, flags; const uint8_t *p; @@ -2230,21 +2336,21 @@ static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, afc = (packet[3] >> 4) & 3; if (afc <= 1) - return -1; - p = packet + 4; + return AVERROR_INVALIDDATA; + p = packet + 4; len = p[0]; p++; if (len == 0) - return -1; + return AVERROR_INVALIDDATA; flags = *p++; len--; if (!(flags & 0x10)) - return -1; + return AVERROR_INVALIDDATA; if (len < 6) - return -1; - v = AV_RB32(p); - *ppcr_high = ((int64_t)v << 1) | (p[4] >> 7); - *ppcr_low = ((p[4] & 1) << 8) | p[5]; + return AVERROR_INVALIDDATA; + v = AV_RB32(p); + *ppcr_high = ((int64_t) v << 1) | (p[4] >> 7); + *ppcr_low = ((p[4] & 1) << 8) | p[5]; return 0; } @@ -2260,8 +2366,8 @@ static void seek_back(AVFormatContext *s, AVIOContext *pb, int64_t pos) { static int mpegts_read_header(AVFormatContext *s) { MpegTSContext *ts = s->priv_data; - AVIOContext *pb = s->pb; - uint8_t buf[8*1024]={0}; + AVIOContext *pb = s->pb; + uint8_t buf[8 * 1024] = {0}; int len; int64_t pos; @@ -2275,7 +2381,7 @@ static int mpegts_read_header(AVFormatContext *s) av_log(s, AV_LOG_WARNING, "Could not detect TS packet size, defaulting to non-FEC/DVHS\n"); ts->raw_packet_size = TS_PACKET_SIZE; } - ts->stream = s; + ts->stream = s; ts->auto_guess = 0; if (s->iformat == &ff_mpegts_demuxer) { @@ -2308,19 +2414,19 @@ static int mpegts_read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) - goto fail; + 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->codec->codec_id = AV_CODEC_ID_MPEG2TS; /* we iterate until we find two PCRs to estimate the bitrate */ - pcr_pid = -1; - nb_pcrs = 0; + pcr_pid = -1; + nb_pcrs = 0; nb_packets = 0; - for(;;) { + for (;;) { ret = read_packet(s, packet, ts->raw_packet_size, &data); if (ret < 0) - goto fail; + return ret; pid = AV_RB16(data + 1) & 0x1fff; if ((pcr_pid == -1 || pcr_pid == pid) && parse_pcr(&pcr_h, &pcr_l, data) == 0) { @@ -2340,24 +2446,21 @@ static int mpegts_read_header(AVFormatContext *s) /* NOTE1: the bitrate is computed without the FEC */ /* NOTE2: it is only the bitrate of the start of the stream */ ts->pcr_incr = (pcrs[1] - pcrs[0]) / (packet_count[1] - packet_count[0]); - ts->cur_pcr = pcrs[0] - ts->pcr_incr * packet_count[0]; - s->bit_rate = (TS_PACKET_SIZE * 8) * 27e6 / ts->pcr_incr; + ts->cur_pcr = pcrs[0] - ts->pcr_incr * packet_count[0]; + s->bit_rate = TS_PACKET_SIZE * 8 * 27e6 / ts->pcr_incr; st->codec->bit_rate = s->bit_rate; - st->start_time = ts->cur_pcr; + st->start_time = ts->cur_pcr; av_dlog(ts->stream, "start=%0.3f pcr=%0.3f incr=%d\n", st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr); } seek_back(s, pb, pos); return 0; - fail: - return -1; } #define MAX_PACKET_READAHEAD ((128 * 1024) / 188) -static int mpegts_raw_read_packet(AVFormatContext *s, - AVPacket *pkt) +static int mpegts_raw_read_packet(AVFormatContext *s, AVPacket *pkt) { MpegTSContext *ts = s->priv_data; int ret, i; @@ -2368,8 +2471,8 @@ static int mpegts_raw_read_packet(AVFormatContext *s, if (av_new_packet(pkt, TS_PACKET_SIZE) < 0) return AVERROR(ENOMEM); - pkt->pos= avio_tell(s->pb); ret = read_packet(s, pkt->data, ts->raw_packet_size, &data); + pkt->pos = avio_tell(s->pb); if (ret < 0) { av_free_packet(pkt); return ret; @@ -2382,12 +2485,13 @@ static int mpegts_raw_read_packet(AVFormatContext *s, if (parse_pcr(&pcr_h, &pcr_l, pkt->data) == 0) { /* we read the next PCR (XXX: optimize it by using a bigger buffer */ pos = avio_tell(s->pb); - for(i = 0; i < MAX_PACKET_READAHEAD; i++) { + for (i = 0; i < MAX_PACKET_READAHEAD; i++) { avio_seek(s->pb, pos + i * ts->raw_packet_size, SEEK_SET); avio_read(s->pb, pcr_buf, 12); if (parse_pcr(&next_pcr_h, &next_pcr_l, pcr_buf) == 0) { /* XXX: not precise enough */ - ts->pcr_incr = ((next_pcr_h - pcr_h) * 300 + (next_pcr_l - pcr_l)) / + ts->pcr_incr = + ((next_pcr_h - pcr_h) * 300 + (next_pcr_l - pcr_l)) / (i + 1); break; } @@ -2396,16 +2500,15 @@ static int mpegts_raw_read_packet(AVFormatContext *s, /* no next PCR found: we use previous increment */ ts->cur_pcr = pcr_h * 300 + pcr_l; } - pkt->pts = ts->cur_pcr; + pkt->pts = ts->cur_pcr; pkt->duration = ts->pcr_incr; - ts->cur_pcr += ts->pcr_incr; + ts->cur_pcr += ts->pcr_incr; } pkt->stream_index = 0; return 0; } -static int mpegts_read_packet(AVFormatContext *s, - AVPacket *pkt) +static int mpegts_read_packet(AVFormatContext *s, AVPacket *pkt) { MpegTSContext *ts = s->priv_data; int ret, i; @@ -2416,7 +2519,7 @@ static int mpegts_read_packet(AVFormatContext *s, if (ret < 0) { av_free_packet(ts->pkt); /* flush pes data left */ - for (i = 0; i < NB_PID_MAX; i++) { + for (i = 0; i < NB_PID_MAX; i++) if (ts->pids[i] && ts->pids[i]->type == MPEGTS_PES) { PESContext *pes = ts->pids[i]->u.pes_filter.opaque; if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) { @@ -2426,7 +2529,6 @@ static int mpegts_read_packet(AVFormatContext *s, break; } } - } } if (!ret && pkt->size < 0) @@ -2440,8 +2542,9 @@ static void mpegts_free(MpegTSContext *ts) clear_programs(ts); - for(i=0;ipids[i]) mpegts_close_filter(ts, ts->pids[i]); + for (i = 0; i < NB_PID_MAX; i++) + if (ts->pids[i]) + mpegts_close_filter(ts, ts->pids[i]); } static int mpegts_read_close(AVFormatContext *s) @@ -2457,9 +2560,12 @@ static av_unused int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index, MpegTSContext *ts = s->priv_data; int64_t pos, timestamp; uint8_t buf[TS_PACKET_SIZE]; - int pcr_l, pcr_pid = ((PESContext*)s->streams[stream_index]->priv_data)->pcr_pid; + int pcr_l, pcr_pid = + ((PESContext *)s->streams[stream_index]->priv_data)->pcr_pid; int pos47 = ts->pos47_full % ts->raw_packet_size; - pos = ((*ppos + ts->raw_packet_size - 1 - pos47) / ts->raw_packet_size) * ts->raw_packet_size + pos47; + pos = + ((*ppos + ts->raw_packet_size - 1 - pos47) / ts->raw_packet_size) * + ts->raw_packet_size + pos47; while(pos < pos_limit) { if (avio_seek(s->pb, pos, SEEK_SET) < 0) return AV_NOPTS_VALUE; @@ -2497,15 +2603,15 @@ static int64_t mpegts_get_dts(AVFormatContext *s, int stream_index, int ret; AVPacket pkt; av_init_packet(&pkt); - ret= av_read_frame(s, &pkt); - if(ret < 0) + ret = av_read_frame(s, &pkt); + if (ret < 0) return AV_NOPTS_VALUE; av_free_packet(&pkt); - if(pkt.dts != AV_NOPTS_VALUE && pkt.pos >= 0){ + if (pkt.dts != AV_NOPTS_VALUE && pkt.pos >= 0) { ff_reduce_index(s, pkt.stream_index); av_add_index_entry(s->streams[pkt.stream_index], pkt.pos, pkt.dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */); - if(pkt.stream_index == stream_index && pkt.pos >= *ppos){ - *ppos= pkt.pos; + if (pkt.stream_index == stream_index && pkt.pos >= *ppos) { + *ppos = pkt.pos; return pkt.dts; } } @@ -2536,18 +2642,18 @@ MpegTSContext *ff_mpegts_parse_open(AVFormatContext *s) } /* return the consumed length if a packet was output, or -1 if no - packet is output */ + * packet is output */ int ff_mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt, - const uint8_t *buf, int len) + const uint8_t *buf, int len) { int len1; len1 = len; ts->pkt = pkt; - for(;;) { + for (;;) { ts->stop_parse = 0; if (len < TS_PACKET_SIZE) - return -1; + return AVERROR_INVALIDDATA; if (buf[0] != 0x47) { buf++; len--; diff --git a/libavformat/mpegts.h b/libavformat/mpegts.h index 269c23b92..7dfe844bd 100644 --- a/libavformat/mpegts.h +++ b/libavformat/mpegts.h @@ -52,12 +52,14 @@ #define STREAM_TYPE_AUDIO_AAC_LATM 0x11 #define STREAM_TYPE_VIDEO_MPEG4 0x10 #define STREAM_TYPE_VIDEO_H264 0x1b +#define STREAM_TYPE_VIDEO_HEVC 0x24 //Definition of 0x24 HEVC video MPEG TS stream type #define STREAM_TYPE_VIDEO_CAVS 0x42 #define STREAM_TYPE_VIDEO_VC1 0xea #define STREAM_TYPE_VIDEO_DIRAC 0xd1 #define STREAM_TYPE_AUDIO_AC3 0x81 -#define STREAM_TYPE_AUDIO_DTS 0x8a +#define STREAM_TYPE_AUDIO_DTS 0x82 +#define STREAM_TYPE_AUDIO_TRUEHD 0x83 typedef struct MpegTSContext MpegTSContext; @@ -104,4 +106,10 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type Mp4Descr *mp4_descr, int mp4_descr_count, int pid, MpegTSContext *ts); +/** + * Check presence of H264 startcode + * @return <0 to stop processing + */ +int ff_check_h264_startcode(AVFormatContext *s, const AVStream *st, const AVPacket *pkt); + #endif /* AVFORMAT_MPEGTS_H */ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index 6f075c5c4..a4a32e0e1 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -81,59 +81,20 @@ typedef struct MpegTSWrite { int reemit_pat_pmt; // backward compatibility + int pcr_period; #define MPEGTS_FLAG_REEMIT_PAT_PMT 0x01 #define MPEGTS_FLAG_AAC_LATM 0x02 int flags; int copyts; int tables_version; + + int omit_video_pes_length; } MpegTSWrite; /* a PES packet header is generated every DEFAULT_PES_HEADER_FREQ packets */ #define DEFAULT_PES_HEADER_FREQ 16 #define DEFAULT_PES_PAYLOAD_SIZE ((DEFAULT_PES_HEADER_FREQ - 1) * 184 + 170) -static const AVOption options[] = { - { "mpegts_transport_stream_id", "Set transport_stream_id field.", - offsetof(MpegTSWrite, transport_stream_id), AV_OPT_TYPE_INT, {.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}, - { "mpegts_service_id", "Set service_id field.", - offsetof(MpegTSWrite, service_id), AV_OPT_TYPE_INT, {.i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM}, - { "mpegts_pmt_start_pid", "Set the first pid of the PMT.", - offsetof(MpegTSWrite, pmt_start_pid), AV_OPT_TYPE_INT, {.i64 = 0x1000 }, 0x0010, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM}, - { "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}, - { "pes_payload_size", "Minimum PES packet payload in bytes", - offsetof(MpegTSWrite, pes_payload_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT_PES_PAYLOAD_SIZE}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, - { "mpegts_flags", "MPEG-TS muxing flags", offsetof(MpegTSWrite, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, - { "resend_headers", "Reemit PAT/PMT before writing the next packet", - 0, AV_OPT_TYPE_CONST, {.i64 = MPEGTS_FLAG_REEMIT_PAT_PMT}, 0, INT_MAX, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags"}, - { "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"}, - // backward compatibility - { "resend_headers", "Reemit PAT/PMT before writing the next packet", - offsetof(MpegTSWrite, reemit_pat_pmt), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, - { "mpegts_copyts", "don't offset dts/pts", - offsetof(MpegTSWrite, copyts), AV_OPT_TYPE_INT, {.i64=-1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, - { "tables_version", "set PAT, PMT and SDT version", - offsetof(MpegTSWrite, tables_version), AV_OPT_TYPE_INT, {.i64=0}, 0, 31, AV_OPT_FLAG_ENCODING_PARAM}, - { NULL }, -}; - -static const AVClass mpegts_muxer_class = { - .class_name = "MPEGTS muxer", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - /* NOTE: 4 bytes must be left at the end for the crc32 */ static void mpegts_write_section(MpegTSSection *s, uint8_t *buf, int len) { @@ -240,6 +201,7 @@ typedef struct MpegTSWriteStream { int payload_flags; uint8_t *payload; AVFormatContext *amux; + AVRational user_tb; } MpegTSWriteStream; static void mpegts_write_pat(AVFormatContext *s) @@ -292,6 +254,9 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) case AV_CODEC_ID_H264: stream_type = STREAM_TYPE_VIDEO_H264; break; + case AV_CODEC_ID_HEVC: + stream_type = STREAM_TYPE_VIDEO_HEVC; + break; case AV_CODEC_ID_CAVS: stream_type = STREAM_TYPE_VIDEO_CAVS; break; @@ -311,6 +276,12 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) case AV_CODEC_ID_AC3: stream_type = STREAM_TYPE_AUDIO_AC3; break; + case AV_CODEC_ID_DTS: + stream_type = STREAM_TYPE_AUDIO_DTS; + break; + case AV_CODEC_ID_TRUEHD: + stream_type = STREAM_TYPE_AUDIO_TRUEHD; + break; default: stream_type = STREAM_TYPE_PRIVATE_DATA; break; @@ -625,20 +596,24 @@ static int mpegts_write_header(AVFormatContext *s) ts->sdt.write_packet = section_write_packet; ts->sdt.opaque = s; - pids = av_malloc(s->nb_streams * sizeof(*pids)); + pids = av_malloc_array(s->nb_streams, sizeof(*pids)); if (!pids) return AVERROR(ENOMEM); /* assign pids to each stream */ for(i = 0;i < s->nb_streams; i++) { st = s->streams[i]; - avpriv_set_pts_info(st, 33, 1, 90000); + ts_st = av_mallocz(sizeof(MpegTSWriteStream)); if (!ts_st) { ret = AVERROR(ENOMEM); goto fail; } st->priv_data = ts_st; + + ts_st->user_tb = st->time_base; + avpriv_set_pts_info(st, 33, 1, 90000); + ts_st->payload = av_mallocz(ts->pes_payload_size); if (!ts_st->payload) { ret = AVERROR(ENOMEM); @@ -693,6 +668,10 @@ static int mpegts_write_header(AVFormatContext *s) goto fail; } ast = avformat_new_stream(ts_st->amux, NULL); + if (!ast) { + ret = AVERROR(ENOMEM); + goto fail; + } ret = avcodec_copy_context(ast->codec, st->codec); if (ret != 0) goto fail; @@ -709,10 +688,11 @@ static int mpegts_write_header(AVFormatContext *s) pcr_st = s->streams[0]; ts_st = pcr_st->priv_data; service->pcr_pid = ts_st->pid; - } + } else + ts_st = pcr_st->priv_data; if (ts->mux_rate > 1) { - service->pcr_packet_period = (ts->mux_rate * PCR_RETRANS_TIME) / + service->pcr_packet_period = (ts->mux_rate * ts->pcr_period) / (TS_PACKET_SIZE * 8 * 1000); ts->sdt_packet_period = (ts->mux_rate * SDT_RETRANS_TIME) / (TS_PACKET_SIZE * 8 * 1000); @@ -736,8 +716,9 @@ static int mpegts_write_header(AVFormatContext *s) } } else { // max delta PCR 0.1s + // TODO: should be avg_frame_rate service->pcr_packet_period = - pcr_st->codec->time_base.den/(10*pcr_st->codec->time_base.num); + ts_st->user_tb.den / (10 * ts_st->user_tb.num); } if(!service->pcr_packet_period) service->pcr_packet_period = 1; @@ -1063,6 +1044,9 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, } if (len > 0xffff) len = 0; + if (ts->omit_video_pes_length && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + len = 0; + } *q++ = len >> 8; *q++ = len; val = 0x80; @@ -1159,6 +1143,19 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, ts_st->prev_payload_key = key; } +int ff_check_h264_startcode(AVFormatContext *s, const AVStream *st, const AVPacket *pkt) +{ + if (pkt->size < 5 || AV_RB32(pkt->data) != 0x0000001) { + if (!st->nb_frames) { + av_log(s, AV_LOG_ERROR, "H.264 bitstream malformed, " + "no startcode found, use the h264_mp4toannexb bitstream filter (-bsf h264_mp4toannexb)\n"); + return AVERROR(EINVAL); + } + av_log(s, AV_LOG_WARNING, "H.264 bitstream error, startcode missing\n"); + } + return 0; +} + static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) { AVStream *st = s->streams[pkt->stream_index]; @@ -1198,15 +1195,9 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) if (st->codec->codec_id == AV_CODEC_ID_H264) { const uint8_t *p = buf, *buf_end = p+size; uint32_t state = -1; - - if (pkt->size < 5 || AV_RB32(pkt->data) != 0x0000001) { - if (!st->nb_frames) { - av_log(s, AV_LOG_ERROR, "H.264 bitstream malformed, " - "no startcode found, use the h264_mp4toannexb bitstream filter (-bsf h264_mp4toannexb)\n"); - return AVERROR(EINVAL); - } - av_log(s, AV_LOG_WARNING, "H.264 bitstream error, startcode missing\n"); - } + int ret = ff_check_h264_startcode(s, st, pkt); + if (ret < 0) + return ret; do { p = avpriv_find_start_code(p, buf_end, &state); @@ -1243,6 +1234,8 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) av_init_packet(&pkt2); pkt2.data = pkt->data; pkt2.size = pkt->size; + av_assert0(pkt->dts != AV_NOPTS_VALUE); + pkt2.dts = av_rescale_q(pkt->dts, st->time_base, ts_st->amux->streams[0]->time_base); ret = avio_open_dyn_buf(&ts_st->amux->pb); if (ret < 0) return AVERROR(ENOMEM); @@ -1361,10 +1354,56 @@ static int mpegts_write_end(AVFormatContext *s) return 0; } +static const AVOption options[] = { + { "mpegts_transport_stream_id", "Set transport_stream_id field.", + offsetof(MpegTSWrite, transport_stream_id), AV_OPT_TYPE_INT, {.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}, + { "mpegts_service_id", "Set service_id field.", + offsetof(MpegTSWrite, service_id), AV_OPT_TYPE_INT, {.i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM}, + { "mpegts_pmt_start_pid", "Set the first pid of the PMT.", + offsetof(MpegTSWrite, pmt_start_pid), AV_OPT_TYPE_INT, {.i64 = 0x1000 }, 0x0010, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM}, + { "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}, + { "pes_payload_size", "Minimum PES packet payload in bytes", + offsetof(MpegTSWrite, pes_payload_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT_PES_PAYLOAD_SIZE}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, + { "mpegts_flags", "MPEG-TS muxing flags", offsetof(MpegTSWrite, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX, + AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + { "resend_headers", "Reemit PAT/PMT before writing the next packet", + 0, AV_OPT_TYPE_CONST, {.i64 = MPEGTS_FLAG_REEMIT_PAT_PMT}, 0, INT_MAX, + AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags"}, + { "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"}, + // backward compatibility + { "resend_headers", "Reemit PAT/PMT before writing the next packet", + offsetof(MpegTSWrite, reemit_pat_pmt), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, + { "mpegts_copyts", "don't offset dts/pts", + offsetof(MpegTSWrite, copyts), AV_OPT_TYPE_INT, {.i64=-1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, + { "tables_version", "set PAT, PMT and SDT version", + offsetof(MpegTSWrite, tables_version), AV_OPT_TYPE_INT, {.i64=0}, 0, 31, AV_OPT_FLAG_ENCODING_PARAM}, + { "omit_video_pes_length", "Omit the PES packet length for video packets", + offsetof(MpegTSWrite, omit_video_pes_length), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, + { "pcr_period", "PCR retransmission time", + offsetof(MpegTSWrite, pcr_period), AV_OPT_TYPE_INT, { .i64 = PCR_RETRANS_TIME }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, + { NULL }, +}; + +static const AVClass mpegts_muxer_class = { + .class_name = "MPEGTS muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVOutputFormat ff_mpegts_muxer = { .name = "mpegts", .long_name = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"), - .mime_type = "video/x-mpegts", + .mime_type = "video/MP2T", .extensions = "ts,m2t,m2ts,mts", .priv_data_size = sizeof(MpegTSWrite), .audio_codec = AV_CODEC_ID_MP2, diff --git a/libavformat/mpjpeg.c b/libavformat/mpjpeg.c index 2586ea8eb..a6e2a89c7 100644 --- a/libavformat/mpjpeg.c +++ b/libavformat/mpjpeg.c @@ -65,4 +65,5 @@ AVOutputFormat ff_mpjpeg_muxer = { .write_header = mpjpeg_write_header, .write_packet = mpjpeg_write_packet, .write_trailer = mpjpeg_write_trailer, + .flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/mtv.c b/libavformat/mtv.c index b449d5886..1d5f26673 100644 --- a/libavformat/mtv.c +++ b/libavformat/mtv.c @@ -170,7 +170,6 @@ static int mtv_read_header(AVFormatContext *s) st->codec->pix_fmt = AV_PIX_FMT_RGB565BE; st->codec->width = mtv->img_width; st->codec->height = mtv->img_height; - st->codec->sample_rate = mtv->video_fps; st->codec->extradata = av_strdup("BottomUp"); st->codec->extradata_size = 9; diff --git a/libavformat/mux.c b/libavformat/mux.c index a5a16e545..687f7043d 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -102,20 +102,17 @@ static void frac_add(AVFrac *f, int64_t incr) f->num = num; } -AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precission) +AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precision) { AVRational q; int j; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - q = (AVRational){1, st->codec->sample_rate}; - } else { - q = st->codec->time_base; - } + q = st->time_base; + for (j=2; j<14; j+= 1+(j>2)) - while (q.den / q.num < min_precission && q.num % j == 0) + while (q.den / q.num < min_precision && q.num % j == 0) q.num /= j; - while (q.den / q.num < min_precission && q.den < (1<<24)) + while (q.den / q.num < min_precision && q.den < (1<<24)) q.den <<= 1; return q; @@ -225,6 +222,7 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) AVDictionary *tmp = NULL; AVCodecContext *codec = NULL; AVOutputFormat *of = s->oformat; + AVDictionaryEntry *e; if (options) av_dict_copy(&tmp, *options, 0); @@ -232,9 +230,14 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) if ((ret = av_opt_set_dict(s, &tmp)) < 0) goto fail; if (s->priv_data && s->oformat->priv_class && *(const AVClass**)s->priv_data==s->oformat->priv_class && - (ret = av_opt_set_dict(s->priv_data, &tmp)) < 0) + (ret = av_opt_set_dict2(s->priv_data, &tmp, AV_OPT_SEARCH_CHILDREN)) < 0) goto fail; +#if FF_API_LAVF_BITEXACT + if (s->nb_streams && s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT) + s->flags |= AVFMT_FLAG_BITEXACT; +#endif + // some sanity checks if (s->nb_streams == 0 && !(of->flags & AVFMT_NOSTREAMS)) { av_log(s, AV_LOG_ERROR, "No streams to mux were specified\n"); @@ -246,6 +249,25 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) st = s->streams[i]; codec = st->codec; +#if FF_API_LAVF_CODEC_TB +FF_DISABLE_DEPRECATION_WARNINGS + if (!st->time_base.num && 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); + } +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); + else + avpriv_set_pts_info(st, 33, 1, 90000); + } + switch (codec->codec_type) { case AVMEDIA_TYPE_AUDIO: if (codec->sample_rate <= 0) { @@ -258,13 +280,6 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) av_get_bits_per_sample(codec->codec_id) >> 3; break; case AVMEDIA_TYPE_VIDEO: - if (codec->time_base.num <= 0 || - codec->time_base.den <= 0) { //FIXME audio too? - av_log(s, AV_LOG_ERROR, "time base not set\n"); - ret = AVERROR(EINVAL); - goto fail; - } - if ((codec->width <= 0 || codec->height <= 0) && !(of->flags & AVFMT_NODIMENSIONS)) { av_log(s, AV_LOG_ERROR, "dimensions not set\n"); @@ -334,18 +349,22 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) if (of->priv_class) { *(const AVClass **)s->priv_data = of->priv_class; av_opt_set_defaults(s->priv_data); - if ((ret = av_opt_set_dict(s->priv_data, &tmp)) < 0) + if ((ret = av_opt_set_dict2(s->priv_data, &tmp, AV_OPT_SEARCH_CHILDREN)) < 0) goto fail; } } /* set muxer identification string */ - if (s->nb_streams && !(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { + if (!(s->flags & AVFMT_FLAG_BITEXACT)) { av_dict_set(&s->metadata, "encoder", LIBAVFORMAT_IDENT, 0); } else { av_dict_set(&s->metadata, "encoder", NULL, 0); } + for (e = NULL; e = av_dict_get(s->metadata, "encoder-", e, AV_DICT_IGNORE_SUFFIX); ) { + av_dict_set(&s->metadata, e->key, NULL, 0); + } + if (options) { av_dict_free(options); *options = tmp; @@ -430,7 +449,8 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options) static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt) { int delay = FFMAX(st->codec->has_b_frames, st->codec->max_b_frames > 0); - int num, den, frame_size, i; + int num, den, i; + int frame_size; av_dlog(s, "compute_pkt_fields2: pts:%s dts:%s cur_dts:%s b:%d size:%d st:%d\n", av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts), delay, pkt->size, pkt->stream_index); @@ -511,8 +531,6 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt) case AVMEDIA_TYPE_VIDEO: frac_add(&st->pts, (int64_t)st->time_base.den * st->codec->time_base.num); break; - default: - break; } return 0; } @@ -614,7 +632,7 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt) if (!pkt) { if (s->oformat->flags & AVFMT_ALLOW_FLUSH) { ret = s->oformat->write_packet(s, NULL); - if (s->flush_packets && s->pb && s->pb->error >= 0) + if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS) avio_flush(s->pb); if (ret >= 0 && s->pb && s->pb->error < 0) ret = s->pb->error; @@ -657,6 +675,8 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif pkt->buf = NULL; + pkt->side_data = NULL; + pkt->side_data_elems = 0; if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) { av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE); av_assert0(((AVFrame *)pkt->data)->buf); @@ -666,7 +686,6 @@ FF_ENABLE_DEPRECATION_WARNINGS av_free(this_pktl); return ret; } - av_copy_packet_side_data(&this_pktl->pkt, &this_pktl->pkt); // copy side data } if (s->streams[pkt->stream_index]->last_in_packet_buffer) { @@ -847,12 +866,6 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) if (pkt) { AVStream *st = s->streams[pkt->stream_index]; - //FIXME/XXX/HACK drop zero sized packets - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->size == 0) { - ret = 0; - goto fail; - } - av_dlog(s, "av_interleaved_write_frame size:%d dts:%s pts:%s\n", pkt->size, av_ts2str(pkt->dts), av_ts2str(pkt->pts)); if ((ret = compute_pkt_fields2(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index 5525233db..6e7c3ffd1 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -24,48 +24,55 @@ * Silicon Graphics Movie demuxer */ +#include "libavutil/channel_layout.h" #include "libavutil/eval.h" #include "libavutil/intreadwrite.h" #include "libavutil/rational.h" + #include "avformat.h" #include "internal.h" -typedef struct { +typedef struct MvContext { int nb_video_tracks; int nb_audio_tracks; - int eof_count; /**< number of streams that have finished */ - int stream_index; /**< current stream index */ - int frame[2]; /**< frame nb for current stream */ + int eof_count; ///< number of streams that have finished + int stream_index; ///< current stream index + int frame[2]; ///< frame nb for current stream + + int acompression; ///< compression level for audio stream + int aformat; ///< audio format } MvContext; #define AUDIO_FORMAT_SIGNED 401 static int mv_probe(AVProbeData *p) { - if (AV_RB32(p->buf) == MKBETAG('M','O','V','I') && AV_RB16(p->buf + 4) < 3) + if (AV_RB32(p->buf) == MKBETAG('M', 'O', 'V', 'I') && + AV_RB16(p->buf + 4) < 3) return AVPROBE_SCORE_MAX; return 0; } -static char * var_read_string(AVIOContext *pb, int size) +static char *var_read_string(AVIOContext *pb, int size) { - char *str = av_malloc(size + 1); int n; + char *str = av_malloc(size + 1); if (!str) return NULL; n = avio_get_str(pb, size, str, size + 1); if (n < size) - avio_skip(pb, size - n); + avio_skip(pb, size - n); return str; } static int var_read_int(AVIOContext *pb, int size) { int v; - char * s = var_read_string(pb, size); - if (!s || sscanf(s, "%d", &v) != 1) - v = 0; + char *s = var_read_string(pb, size); + if (!s) + return 0; + v = strtol(s, NULL, 10); av_free(s); return v; } @@ -73,9 +80,9 @@ static int var_read_int(AVIOContext *pb, int size) static AVRational var_read_float(AVIOContext *pb, int size) { AVRational v; - char * s = var_read_string(pb, size); + char *s = var_read_string(pb, size); if (!s) - return (AVRational){0, 0}; + return (AVRational) { 0, 0 }; v = av_d2q(av_strtod(s, NULL), INT_MAX); av_free(s); return v; @@ -88,13 +95,15 @@ static void var_read_metadata(AVFormatContext *avctx, const char *tag, int size) av_dict_set(&avctx->metadata, tag, value, AV_DICT_DONT_STRDUP_VAL); } -static int set_channels(AVFormatContext *avctx, AVStream *st, int channels) { +static int set_channels(AVFormatContext *avctx, AVStream *st, int channels) +{ if (channels <= 0) { - av_log(avctx, AV_LOG_ERROR, "Channel count %d invalid\n", 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->codec->channels = channels; + st->codec->channel_layout = (st->codec->channels == 1) ? AV_CH_LAYOUT_MONO + : AV_CH_LAYOUT_STEREO; return 0; } @@ -102,7 +111,8 @@ static int set_channels(AVFormatContext *avctx, AVStream *st, int channels) { * Parse global variable * @return < 0 if unknown */ -static int parse_global_var(AVFormatContext *avctx, AVStream *st, const char *name, int size) +static int parse_global_var(AVFormatContext *avctx, AVStream *st, + const char *name, int size) { MvContext *mv = avctx->priv_data; AVIOContext *pb = avctx->pb; @@ -112,10 +122,11 @@ static int parse_global_var(AVFormatContext *avctx, AVStream *st, const char *na mv->nb_audio_tracks = var_read_int(pb, size); } else if (!strcmp(name, "COMMENT") || !strcmp(name, "TITLE")) { var_read_metadata(avctx, name, size); - } else if (!strcmp(name, "LOOP_MODE") || !strcmp(name, "NUM_LOOPS") || !strcmp(name, "OPTIMIZED")) { + } else if (!strcmp(name, "LOOP_MODE") || !strcmp(name, "NUM_LOOPS") || + !strcmp(name, "OPTIMIZED")) { avio_skip(pb, size); // ignore } else - return -1; + return AVERROR_INVALIDDATA; return 0; } @@ -124,15 +135,17 @@ static int parse_global_var(AVFormatContext *avctx, AVStream *st, const char *na * Parse audio variable * @return < 0 if unknown */ -static int parse_audio_var(AVFormatContext *avctx, AVStream *st, const char *name, int size) +static int parse_audio_var(AVFormatContext *avctx, AVStream *st, + const char *name, int size) { + MvContext *mv = avctx->priv_data; AVIOContext *pb = avctx->pb; if (!strcmp(name, "__DIR_COUNT")) { st->nb_frames = var_read_int(pb, size); } else if (!strcmp(name, "AUDIO_FORMAT")) { - st->codec->codec_id = var_read_int(pb, size); + mv->aformat = var_read_int(pb, size); } else if (!strcmp(name, "COMPRESSION")) { - st->codec->codec_tag = var_read_int(pb, size); + mv->acompression = var_read_int(pb, size); } else if (!strcmp(name, "DEFAULT_VOL")) { var_read_metadata(avctx, name, size); } else if (!strcmp(name, "NUM_CHANNELS")) { @@ -143,7 +156,8 @@ static int parse_audio_var(AVFormatContext *avctx, AVStream *st, const char *nam } else if (!strcmp(name, "SAMPLE_WIDTH")) { st->codec->bits_per_coded_sample = var_read_int(pb, size) * 8; } else - return -1; + return AVERROR_INVALIDDATA; + return 0; } @@ -151,13 +165,14 @@ static int parse_audio_var(AVFormatContext *avctx, AVStream *st, const char *nam * Parse video variable * @return < 0 if unknown */ -static int parse_video_var(AVFormatContext *avctx, AVStream *st, const char *name, int size) +static int parse_video_var(AVFormatContext *avctx, AVStream *st, + const char *name, int size) { AVIOContext *pb = avctx->pb; if (!strcmp(name, "__DIR_COUNT")) { st->nb_frames = st->duration = var_read_int(pb, size); } else if (!strcmp(name, "COMPRESSION")) { - char * str = var_read_string(pb, size); + char *str = var_read_string(pb, size); if (!str) return AVERROR_INVALIDDATA; if (!strcmp(str, "1")) { @@ -172,35 +187,40 @@ static int parse_video_var(AVFormatContext *avctx, AVStream *st, const char *nam } else if (!strcmp(str, "MVC2")) { st->codec->codec_id = AV_CODEC_ID_MVC2; } else { - avpriv_request_sample(avctx, "video compression %s", str); + avpriv_request_sample(avctx, "Video compression %s", str); } av_free(str); } else if (!strcmp(name, "FPS")) { AVRational fps = var_read_float(pb, size); 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); } 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); + 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); } else if (!strcmp(name, "ORIENTATION")) { if (var_read_int(pb, size) == 1101) { - st->codec->extradata = av_strdup("BottomUp"); - st->codec->extradata_size = 9; + st->codec->extradata = av_strdup("BottomUp"); + st->codec->extradata_size = 9; } } else if (!strcmp(name, "Q_SPATIAL") || !strcmp(name, "Q_TEMPORAL")) { var_read_metadata(avctx, name, size); } else if (!strcmp(name, "INTERLACING") || !strcmp(name, "PACKING")) { avio_skip(pb, size); // ignore } else - return -1; + return AVERROR_INVALIDDATA; + return 0; } -static void read_table(AVFormatContext *avctx, AVStream *st, int (*parse)(AVFormatContext *avctx, AVStream *st, const char *name, int size)) +static void read_table(AVFormatContext *avctx, AVStream *st, + int (*parse)(AVFormatContext *avctx, AVStream *st, + const char *name, int size)) { int count, i; AVIOContext *pb = avctx->pb; @@ -214,7 +234,7 @@ static void read_table(AVFormatContext *avctx, AVStream *st, int (*parse)(AVForm name[sizeof(name) - 1] = 0; size = avio_rb32(pb); if (parse(avctx, st, name, size) < 0) { - avpriv_request_sample(avctx, "variable %s", name); + avpriv_request_sample(avctx, "Variable %s", name); avio_skip(pb, size); } } @@ -253,7 +273,7 @@ static int mv_read_header(AVFormatContext *avctx) avio_skip(pb, 22); /* allocate audio track first to prevent unnecessary seeking - (audio packet always precede video packet for a given frame) */ + * (audio packet always precede video packet for a given frame) */ ast = avformat_new_stream(avctx, NULL); if (!ast) return AVERROR(ENOMEM); @@ -261,9 +281,10 @@ 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; avpriv_set_pts_info(vst, 64, 1, 15); - vst->nb_frames = avio_rb32(pb); + vst->codec->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: @@ -274,7 +295,7 @@ static int mv_read_header(AVFormatContext *avctx) vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO; break; default: - avpriv_request_sample(avctx, "video compression %i", v); + avpriv_request_sample(avctx, "Video compression %i", v); break; } vst->codec->codec_tag = 0; @@ -282,9 +303,9 @@ static int mv_read_header(AVFormatContext *avctx) vst->codec->height = avio_rb32(pb); avio_skip(pb, 12); - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->nb_frames = vst->nb_frames; - ast->codec->sample_rate = avio_rb32(pb); + ast->codec->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); if (set_channels(avctx, ast, avio_rb32(pb)) < 0) return AVERROR_INVALIDDATA; @@ -293,7 +314,7 @@ static int mv_read_header(AVFormatContext *avctx) if (v == AUDIO_FORMAT_SIGNED) { ast->codec->codec_id = AV_CODEC_ID_PCM_S16BE; } else { - avpriv_request_sample(avctx, "audio compression (format %i)", v); + avpriv_request_sample(avctx, "Audio compression (format %i)", v); } avio_skip(pb, 12); @@ -307,8 +328,8 @@ static int mv_read_header(AVFormatContext *avctx) uint32_t asize = avio_rb32(pb); uint32_t vsize = avio_rb32(pb); 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); + 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); } } else if (!version && avio_rb16(pb) == 3) { @@ -317,31 +338,33 @@ static int mv_read_header(AVFormatContext *avctx) read_table(avctx, NULL, parse_global_var); if (mv->nb_audio_tracks > 1) { - avpriv_request_sample(avctx, "multiple audio streams support"); + avpriv_request_sample(avctx, "Multiple audio streams support"); return AVERROR_PATCHWELCOME; } else if (mv->nb_audio_tracks) { ast = avformat_new_stream(avctx, NULL); if (!ast) return AVERROR(ENOMEM); ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - /* temporarily store compression value in codec_tag; format value in codec_id */ read_table(avctx, ast, parse_audio_var); - if (ast->codec->codec_tag == 100 && ast->codec->codec_id == AUDIO_FORMAT_SIGNED && ast->codec->bits_per_coded_sample == 16) { + 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; } else { - avpriv_request_sample(avctx, "audio compression %i (format %i, width %i)", - ast->codec->codec_tag, ast->codec->codec_id, ast->codec->bits_per_coded_sample); + 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->codec->codec_tag = 0; if (ast->codec->channels <= 0) { - av_log(avctx, AV_LOG_ERROR, "No valid channel count found\n"); + av_log(avctx, AV_LOG_ERROR, "No valid channel count found.\n"); return AVERROR_INVALIDDATA; } } if (mv->nb_video_tracks > 1) { - avpriv_request_sample(avctx, "multiple video streams support"); + avpriv_request_sample(avctx, "Multiple video streams support"); return AVERROR_PATCHWELCOME; } else if (mv->nb_video_tracks) { vst = avformat_new_stream(avctx, NULL); @@ -357,7 +380,7 @@ static int mv_read_header(AVFormatContext *avctx) if (mv->nb_video_tracks) read_index(pb, vst); } else { - avpriv_request_sample(avctx, "version %i", version); + avpriv_request_sample(avctx, "Version %i", version); return AVERROR_PATCHWELCOME; } @@ -374,9 +397,9 @@ static int mv_read_packet(AVFormatContext *avctx, AVPacket *pkt) int ret; uint64_t pos; - if (frame < st->nb_index_entries) { + if (frame < st->nb_index_entries) { index = &st->index_entries[frame]; - pos = avio_tell(pb); + pos = avio_tell(pb); if (index->pos > pos) avio_skip(pb, index->pos - pos); else if (index->pos < pos) { @@ -391,8 +414,8 @@ static int mv_read_packet(AVFormatContext *avctx, AVPacket *pkt) return ret; pkt->stream_index = mv->stream_index; - pkt->pts = index->timestamp; - pkt->flags |= AV_PKT_FLAG_KEY; + pkt->pts = index->timestamp; + pkt->flags |= AV_PKT_FLAG_KEY; mv->frame[mv->stream_index]++; mv->eof_count = 0; @@ -400,6 +423,9 @@ static int mv_read_packet(AVFormatContext *avctx, AVPacket *pkt) mv->eof_count++; if (mv->eof_count >= avctx->nb_streams) return AVERROR_EOF; + + // avoid returning 0 without a packet + return AVERROR(EAGAIN); } mv->stream_index++; @@ -409,7 +435,8 @@ static int mv_read_packet(AVFormatContext *avctx, AVPacket *pkt) return 0; } -static int mv_read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags) +static int mv_read_seek(AVFormatContext *avctx, int stream_index, + int64_t timestamp, int flags) { MvContext *mv = avctx->priv_data; AVStream *st = avctx->streams[stream_index]; @@ -423,7 +450,7 @@ static int mv_read_seek(AVFormatContext *avctx, int stream_index, int64_t timest frame = av_index_search_timestamp(st, timestamp, flags); if (frame < 0) - return -1; + return AVERROR_INVALIDDATA; for (i = 0; i < avctx->nb_streams; i++) mv->frame[i] = frame; diff --git a/libavformat/mvi.c b/libavformat/mvi.c index 5efc44315..a7cfcb9a7 100644 --- a/libavformat/mvi.c +++ b/libavformat/mvi.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/channel_layout.h" #include "avformat.h" #include "internal.h" @@ -95,7 +97,8 @@ static int read_header(AVFormatContext *s) 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) { - av_log(s, AV_LOG_ERROR, "Invalid audio_data_size (%d) or frames_count (%d)\n", + av_log(s, AV_LOG_ERROR, + "Invalid audio_data_size (%"PRIu32") or frames_count (%u)\n", mvi->audio_data_size, frames_count); return AVERROR_INVALIDDATA; } diff --git a/libavformat/mxf.c b/libavformat/mxf.c index 4a4158a1d..d20ed946a 100644 --- a/libavformat/mxf.c +++ b/libavformat/mxf.c @@ -45,6 +45,7 @@ const MXFCodecUL ff_mxf_codec_uls[] = { { { 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,0x01 }, 16, AV_CODEC_ID_V210 }, /* V210 */ /* SoundEssenceCompression */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, 13, AV_CODEC_ID_PCM_S16LE }, /* Uncompressed */ @@ -107,7 +108,7 @@ int ff_mxf_decode_pixel_layout(const char pixel_layout[16], enum AVPixelFormat * return -1; } -static const MXFSamplesPerFrame mxf_samples_per_frames[] = { +static const MXFSamplesPerFrame mxf_spf[] = { { { 1001, 24000 }, { 2002, 0, 0, 0, 0, 0 } }, // FILM 23.976 { { 1, 24}, { 2000, 0, 0, 0, 0, 0 } }, // FILM 24 { { 1001, 30000 }, { 1602, 1601, 1602, 1601, 1602, 0 } }, // NTSC 29.97 @@ -116,22 +117,33 @@ static const MXFSamplesPerFrame mxf_samples_per_frames[] = { { { 1, 50 }, { 960, 0, 0, 0, 0, 0 } }, // PAL 50 }; -const MXFSamplesPerFrame *ff_mxf_get_samples_per_frame(AVFormatContext *s, AVRational time_base) -{ - int i; - for (i = 0; i < FF_ARRAY_ELEMS(mxf_samples_per_frames); i++) { - if (!av_cmp_q(mxf_samples_per_frames[i].time_base, time_base)) - return &mxf_samples_per_frames[i]; - } +static const AVRational mxf_time_base[] = { + { 1001, 24000 }, + { 1, 24}, + { 1001, 30000 }, + { 1001, 60000 }, + { 1, 25 }, + { 1, 50 }, + { 0, 0} +}; - // Find closest container time base for approximative codec time base like 1/29.97, 1/30, ... - for (i = 0; i < FF_ARRAY_ELEMS(mxf_samples_per_frames); i++) { - if (fabs(av_q2d(mxf_samples_per_frames[i].time_base) - av_q2d(time_base)) < 0.0001) { - av_log(s, AV_LOG_WARNING, "%d/%d input time base matched %d/%d container time base\n", - time_base.num, time_base.den, - mxf_samples_per_frames[i].time_base.num, mxf_samples_per_frames[i].time_base.den); - return &mxf_samples_per_frames[i]; - } - } - return NULL; +const MXFSamplesPerFrame *ff_mxf_get_samples_per_frame(AVFormatContext *s, + AVRational time_base) +{ + int idx = av_find_nearest_q_idx(time_base, mxf_time_base); + AVRational diff = av_sub_q(time_base, mxf_time_base[idx]); + + diff.num = abs(diff.num); + + if (av_cmp_q(diff, (AVRational){1, 1000}) >= 0) + return NULL; + + if (av_cmp_q(time_base, mxf_time_base[idx])) + av_log(s, AV_LOG_WARNING, + "%d/%d input time base matched %d/%d container time base\n", + time_base.num, time_base.den, + mxf_spf[idx].time_base.num, + mxf_spf[idx].time_base.den); + + return &mxf_spf[idx]; } diff --git a/libavformat/mxf.h b/libavformat/mxf.h index 4c751e8ee..cf7ec0bab 100644 --- a/libavformat/mxf.h +++ b/libavformat/mxf.h @@ -79,7 +79,32 @@ extern const MXFCodecUL ff_mxf_pixel_format_uls[]; int ff_mxf_decode_pixel_layout(const char pixel_layout[16], enum AVPixelFormat *pix_fmt); const MXFSamplesPerFrame *ff_mxf_get_samples_per_frame(AVFormatContext *s, AVRational time_base); -#define PRINT_KEY(pc, s, x) av_dlog(pc, "%s %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", s, \ - (x)[0], (x)[1], (x)[2], (x)[3], (x)[4], (x)[5], (x)[6], (x)[7], (x)[8], (x)[9], (x)[10], (x)[11], (x)[12], (x)[13], (x)[14], (x)[15]) +#ifdef DEBUG +#define PRINT_KEY(pc, s, x) \ + av_log(pc, AV_LOG_VERBOSE, \ + "%s " \ + "0x%02x,0x%02x,0x%02x,0x%02x," \ + "0x%02x,0x%02x,0x%02x,0x%02x," \ + "0x%02x,0x%02x,0x%02x,0x%02x," \ + "0x%02x,0x%02x,0x%02x,0x%02x ", \ + s, \ + (x)[0], (x)[1], (x)[2], (x)[3], \ + (x)[4], (x)[5], (x)[6], (x)[7], \ + (x)[8], (x)[9], (x)[10], (x)[11], \ + (x)[12], (x)[13], (x)[14], (x)[15]); \ + av_log(pc, AV_LOG_INFO, \ + "%s " \ + "%02x.%02x.%02x.%02x." \ + "%02x.%02x.%02x.%02x." \ + "%02x.%02x.%02x.%02x." \ + "%02x.%02x.%02x.%02x\n", \ + s, \ + (x)[0], (x)[1], (x)[2], (x)[3], \ + (x)[4], (x)[5], (x)[6], (x)[7], \ + (x)[8], (x)[9], (x)[10], (x)[11], \ + (x)[12], (x)[13], (x)[14], (x)[15]) +#else +#define PRINT_KEY(pc, s, x) +#endif #endif /* AVFORMAT_MXF_H */ diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 0e877e396..0d17a0296 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -43,7 +43,7 @@ * Only tracks with associated descriptors will be decoded. "Highly Desirable" SMPTE 377M D.1 */ -#include +#include #include "libavutil/aes.h" #include "libavutil/avassert.h" @@ -135,7 +135,7 @@ typedef struct { AVRational edit_rate; int intra_only; uint64_t sample_count; - int64_t original_duration; ///< duration before multiplying st->duration by SampleRate/EditRate + int64_t original_duration; /* st->duration in SampleRate/EditRate units */ } MXFTrack; typedef struct { @@ -254,13 +254,13 @@ static int mxf_read_close(AVFormatContext *s); static const uint8_t mxf_header_partition_pack_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02 }; static const uint8_t mxf_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 }; static const uint8_t mxf_avid_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0e,0x04,0x03,0x01 }; -static const uint8_t mxf_system_item_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x03,0x01,0x04 }; +static const uint8_t mxf_system_item_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x03,0x01,0x04 }; static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 }; /* complete keys to match */ static const uint8_t mxf_crypto_source_container_ul[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x02,0x02,0x00,0x00,0x00 }; static const uint8_t mxf_encrypted_triplet_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x04,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x7e,0x01,0x00 }; static const uint8_t mxf_encrypted_essence_container[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0b,0x01,0x00 }; -static const uint8_t mxf_random_index_pack_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x11,0x01,0x00 }; +static const uint8_t mxf_random_index_pack_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x11,0x01,0x00 }; static const uint8_t mxf_sony_mpeg4_extradata[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0e,0x06,0x06,0x02,0x02,0x01,0x00,0x00 }; #define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y))) @@ -495,6 +495,26 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size } nb_essence_containers = avio_rb32(pb); + if (partition->this_partition && + partition->previous_partition == partition->this_partition) { + av_log(mxf->fc, AV_LOG_ERROR, + "PreviousPartition equal to ThisPartition %"PRIx64"\n", + partition->previous_partition); + /* override with the actual previous partition offset */ + if (!mxf->parsing_backward && mxf->last_forward_partition > 1) { + MXFPartition *prev = + mxf->partitions + mxf->last_forward_partition - 2; + partition->previous_partition = prev->this_partition; + } + /* if no previous body partition are found point to the header + * partition */ + if (partition->previous_partition == partition->this_partition) + partition->previous_partition = 0; + av_log(mxf->fc, AV_LOG_ERROR, + "Overriding PreviousPartition with %"PRIx64"\n", + partition->previous_partition); + } + /* some files don'thave FooterPartition set in every partition */ if (footer_partition) { if (mxf->footer_partition && mxf->footer_partition != footer_partition) { @@ -542,8 +562,10 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size /* only nag once */ if (!mxf->op) - av_log(mxf->fc, AV_LOG_WARNING, "\"OPAtom\" with %u ECs - assuming %s\n", - nb_essence_containers, op == OP1a ? "OP1a" : "OPAtom"); + av_log(mxf->fc, AV_LOG_WARNING, + "\"OPAtom\" with %"PRIu32" ECs - assuming %s\n", + nb_essence_containers, + op == OP1a ? "OP1a" : "OPAtom"); mxf->op = op; } else @@ -554,14 +576,15 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size } if (partition->kag_size <= 0 || partition->kag_size > (1 << 20)) { - av_log(mxf->fc, AV_LOG_WARNING, "invalid KAGSize %i - guessing ", partition->kag_size); + av_log(mxf->fc, AV_LOG_WARNING, "invalid KAGSize %"PRId32" - guessing ", + partition->kag_size); if (mxf->op == OPSONYOpt) partition->kag_size = 512; else partition->kag_size = 1; - av_log(mxf->fc, AV_LOG_WARNING, "%i\n", partition->kag_size); + av_log(mxf->fc, AV_LOG_WARNING, "%"PRId32"\n", partition->kag_size); } return 0; @@ -671,7 +694,7 @@ static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid case 0x4804: avio_read(pb, track->track_number, 4); break; - case 0x4B01: + case 0x4b01: track->edit_rate.num = avio_rb32(pb); track->edit_rate.den = avio_rb32(pb); break; @@ -930,31 +953,31 @@ 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,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,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 */ { { 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,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 */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; static const MXFCodecUL mxf_sound_essence_container_uls[] = { // sound essence container uls - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, 14, AV_CODEC_ID_PCM_S16LE }, /* BWF Frame wrapped */ - { { 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,0x01,0x0d,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, 14, AV_CODEC_ID_PCM_S16LE }, /* BWF Frame wrapped */ + { { 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 */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; @@ -1475,7 +1498,8 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) } avpriv_set_pts_info(st, 64, material_track->edit_rate.den, material_track->edit_rate.num); - /* ensure SourceTrack EditRate == MaterialTrack EditRate since only the former is accessible via st->priv_data */ + /* ensure SourceTrack EditRate == MaterialTrack EditRate since only + * the former is accessible via st->priv_data */ source_track->edit_rate = material_track->edit_rate; PRINT_KEY(mxf->fc, "data definition ul", source_track->sequence->data_definition_ul); @@ -1615,7 +1639,9 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) /* if duration is set, rescale it from EditRate to SampleRate */ if (st->duration != AV_NOPTS_VALUE) - st->duration = av_rescale_q(st->duration, av_inv_q(material_track->edit_rate), st->time_base); + st->duration = av_rescale_q(st->duration, + av_inv_q(material_track->edit_rate), + st->time_base); /* TODO: implement AV_CODEC_ID_RAWAUDIO */ if (st->codec->codec_id == AV_CODEC_ID_PCM_S16LE) { @@ -1660,7 +1686,7 @@ static int mxf_read_utf16_string(AVIOContext *pb, int size, char** str) if (size < 0) return AVERROR(EINVAL); - buf_size = size + size/2 + 1; + buf_size = size + size / 2 + 1; *str = av_malloc(buf_size); if (!*str) return AVERROR(ENOMEM); @@ -1693,7 +1719,7 @@ static int mxf_uid_to_str(UID uid, char **str) static int mxf_timestamp_to_str(uint64_t timestamp, char **str) { - struct tm time = {0}; + struct tm time = { 0 }; time.tm_year = (timestamp >> 48) - 1900; time.tm_mon = (timestamp >> 40 & 0xFF) - 1; time.tm_mday = (timestamp >> 32 & 0xFF); @@ -1701,9 +1727,14 @@ static int mxf_timestamp_to_str(uint64_t timestamp, char **str) time.tm_min = (timestamp >> 16 & 0xFF); time.tm_sec = (timestamp >> 8 & 0xFF); - /* ensure month/day are valid */ - time.tm_mon = FFMAX(time.tm_mon, 0); - time.tm_mday = FFMAX(time.tm_mday, 1); + /* msvcrt versions of strftime calls the invalid parameter handler + * (aborting the process if one isn't set) if the parameters are out + * of range. */ + time.tm_mon = av_clip(time.tm_mon, 0, 11); + time.tm_mday = av_clip(time.tm_mday, 1, 31); + time.tm_hour = av_clip(time.tm_hour, 0, 23); + time.tm_min = av_clip(time.tm_min, 0, 59); + time.tm_sec = av_clip(time.tm_sec, 0, 59); *str = av_mallocz(32); if (!*str) @@ -1771,35 +1802,35 @@ static int mxf_read_identification_metadata(void *arg, AVIOContext *pb, int tag, } static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = { - { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x05,0x01,0x00 }, mxf_read_primer_pack }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, mxf_read_partition_pack }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x02,0x00 }, mxf_read_partition_pack }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x03,0x00 }, mxf_read_partition_pack }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x04,0x00 }, mxf_read_partition_pack }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x01,0x00 }, mxf_read_partition_pack }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x02,0x00 }, mxf_read_partition_pack }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x03,0x00 }, mxf_read_partition_pack }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x04,0x00 }, mxf_read_partition_pack }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x02,0x00 }, mxf_read_partition_pack }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x04,0x00 }, mxf_read_partition_pack }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x30,0x00 }, mxf_read_identification_metadata }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_content_storage, 0, AnyType }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_source_package, sizeof(MXFPackage), SourcePackage }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_material_package, sizeof(MXFPackage), MaterialPackage }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0F,0x00 }, mxf_read_sequence, sizeof(MXFSequence), Sequence }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_source_clip, sizeof(MXFStructuralComponent), SourceClip }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x44,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), MultipleDescriptor }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Generic Sound */ - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x28,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* CDCI */ - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x29,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* RGBA */ - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x51,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* MPEG 2 Video */ - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Wave */ - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* AES3 */ - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Static Track */ - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Generic Track */ - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x14,0x00 }, mxf_read_timecode_component, sizeof(MXFTimecodeComponent), TimecodeComponent }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x04,0x01,0x02,0x02,0x00,0x00 }, mxf_read_cryptographic_context, sizeof(MXFCryptoContext), CryptoContext }, - { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 }, mxf_read_index_table_segment, sizeof(MXFIndexTableSegment), IndexTableSegment }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x05,0x01,0x00 }, mxf_read_primer_pack }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, mxf_read_partition_pack }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x02,0x00 }, mxf_read_partition_pack }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x03,0x00 }, mxf_read_partition_pack }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x04,0x00 }, mxf_read_partition_pack }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x01,0x00 }, mxf_read_partition_pack }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x02,0x00 }, mxf_read_partition_pack }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x03,0x00 }, mxf_read_partition_pack }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x04,0x00 }, mxf_read_partition_pack }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x02,0x00 }, mxf_read_partition_pack }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x04,0x00 }, mxf_read_partition_pack }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x30,0x00 }, mxf_read_identification_metadata }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_content_storage, 0, AnyType }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_source_package, sizeof(MXFPackage), SourcePackage }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_material_package, sizeof(MXFPackage), MaterialPackage }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0f,0x00 }, mxf_read_sequence, sizeof(MXFSequence), Sequence }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_source_clip, sizeof(MXFStructuralComponent), SourceClip }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x44,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), MultipleDescriptor }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Generic Sound */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x28,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* CDCI */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x29,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* RGBA */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x51,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* MPEG 2 Video */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Wave */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* AES3 */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Static Track */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Generic Track */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x14,0x00 }, mxf_read_timecode_component, sizeof(MXFTimecodeComponent), TimecodeComponent }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x04,0x01,0x02,0x02,0x00,0x00 }, mxf_read_cryptographic_context, sizeof(MXFCryptoContext), CryptoContext }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 }, mxf_read_index_table_segment, sizeof(MXFIndexTableSegment), IndexTableSegment }, { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL, 0, AnyType }, }; @@ -1888,10 +1919,14 @@ static int mxf_parse_handle_essence(MXFContext *mxf) if (mxf->parsing_backward) { return mxf_seek_to_previous_partition(mxf); - } else if (mxf->footer_partition || mxf->last_partition){ - uint64_t offset; + } else { + uint64_t offset = mxf->footer_partition ? mxf->footer_partition + : mxf->last_partition; - offset = mxf->footer_partition ? mxf->footer_partition : mxf->last_partition; + if (!offset) { + av_dlog(mxf->fc, "no last partition\n"); + return 0; + } av_dlog(mxf->fc, "seeking to last partition\n"); @@ -1905,16 +1940,15 @@ static int mxf_parse_handle_essence(MXFContext *mxf) /* seek to last partition and parse backward */ if ((ret = avio_seek(pb, mxf->run_in + offset, SEEK_SET)) < 0) { - av_log(mxf->fc, AV_LOG_ERROR, "failed to seek to last partition @ 0x%"PRIx64" (%"PRId64") - partial file?\n", + av_log(mxf->fc, AV_LOG_ERROR, + "failed to seek to last partition @ 0x%" PRIx64 + " (%"PRId64") - partial file?\n", mxf->run_in + offset, ret); return ret; } mxf->current_partition = NULL; mxf->parsing_backward = 1; - } else { - av_dlog(mxf->fc, "can't find last partition\n"); - return 0; } return 1; @@ -2230,7 +2264,8 @@ static int64_t mxf_set_current_edit_unit(MXFContext *mxf, int64_t current_offset return next_ofs; } -static int mxf_compute_sample_count(MXFContext *mxf, int stream_index, uint64_t *sample_count) +static int mxf_compute_sample_count(MXFContext *mxf, int stream_index, + uint64_t *sample_count) { int i, total = 0, size = 0; AVStream *st = mxf->fc->streams[stream_index]; @@ -2242,13 +2277,16 @@ static int mxf_compute_sample_count(MXFContext *mxf, int stream_index, uint64_t if ((sample_rate.num / sample_rate.den) == 48000) spf = ff_mxf_get_samples_per_frame(mxf->fc, time_base); if (!spf) { - int remainder = (sample_rate.num * time_base.num) % (time_base.den * sample_rate.den); + int remainder = (sample_rate.num * time_base.num) % + (time_base.den * sample_rate.den); *sample_count = av_q2d(av_mul_q((AVRational){mxf->current_edit_unit, 1}, av_mul_q(sample_rate, time_base))); if (remainder) av_log(mxf->fc, AV_LOG_WARNING, - "seeking detected on stream #%d with time base (%d/%d) and sample rate (%d/%d), audio pts won't be accurate.\n", - stream_index, time_base.num, time_base.den, sample_rate.num, sample_rate.den); + "seeking detected on stream #%d with time base (%d/%d) and " + "sample rate (%d/%d), audio pts won't be accurate.\n", + stream_index, time_base.num, time_base.den, + sample_rate.num, sample_rate.den); return 0; } @@ -2267,15 +2305,19 @@ static int mxf_compute_sample_count(MXFContext *mxf, int stream_index, uint64_t return 0; } -static int mxf_set_audio_pts(MXFContext *mxf, AVCodecContext *codec, AVPacket *pkt) +static int mxf_set_audio_pts(MXFContext *mxf, AVCodecContext *codec, + AVPacket *pkt) { MXFTrack *track = mxf->fc->streams[pkt->stream_index]->priv_data; + int64_t bits_per_sample = av_get_bits_per_sample(codec->codec_id); + pkt->pts = track->sample_count; + if ( codec->channels <= 0 - || av_get_bits_per_sample(codec->codec_id) <= 0 - || codec->channels * (int64_t)av_get_bits_per_sample(codec->codec_id) < 8) + || bits_per_sample <= 0 + || codec->channels * (int64_t)bits_per_sample < 8) return AVERROR(EINVAL); - track->sample_count += pkt->size / (codec->channels * (int64_t)av_get_bits_per_sample(codec->codec_id) / 8); + track->sample_count += pkt->size / (codec->channels * (int64_t)bits_per_sample / 8); return 0; } @@ -2283,16 +2325,16 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) { KLVPacket klv; MXFContext *mxf = s->priv_data; + int ret; - while (klv_read_packet(&klv, s->pb) == 0) { - int ret; + while ((ret = klv_read_packet(&klv, s->pb)) == 0) { PRINT_KEY(s, "read packet", klv.key); av_dlog(s, "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) { av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n"); - return AVERROR_INVALIDDATA; + return ret; } return 0; } @@ -2305,7 +2347,9 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) AVCodecContext *codec; if (index < 0) { - av_log(s, AV_LOG_ERROR, "error getting stream index %d\n", AV_RB32(klv.key+12)); + av_log(s, AV_LOG_ERROR, + "error getting stream index %"PRIu32"\n", + AV_RB32(klv.key + 12)); goto skip; } @@ -2331,9 +2375,11 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) /* check for 8 channels AES3 element */ if (klv.key[12] == 0x06 && klv.key[13] == 0x01 && klv.key[14] == 0x10) { - if (mxf_get_d10_aes3_packet(s->pb, s->streams[index], pkt, klv.length) < 0) { + ret = mxf_get_d10_aes3_packet(s->pb, s->streams[index], + pkt, klv.length); + if (ret < 0) { av_log(s, AV_LOG_ERROR, "error reading D-10 aes3 frame\n"); - return AVERROR_INVALIDDATA; + return ret; } } else { ret = av_get_packet(s->pb, pkt, klv.length); @@ -2344,8 +2390,10 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) pkt->pos = klv.offset; codec = s->streams[index]->codec; + if (codec->codec_type == AVMEDIA_TYPE_VIDEO && next_ofs >= 0) { - /* mxf->current_edit_unit good - see if we have an index table to derive timestamps from */ + /* mxf->current_edit_unit good - see if we have an + * index table to derive timestamps from */ MXFIndexTable *t = &mxf->index_tables[0]; if (mxf->nb_index_tables >= 1 && mxf->current_edit_unit < t->nb_ptses) { @@ -2357,7 +2405,7 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) pkt->pts = mxf->current_edit_unit; } } else if (codec->codec_type == AVMEDIA_TYPE_AUDIO) { - int ret = mxf_set_audio_pts(mxf, codec, pkt); + ret = mxf_set_audio_pts(mxf, codec, pkt); if (ret < 0) return ret; } @@ -2370,7 +2418,7 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) skip: avio_skip(s->pb, klv.length); } - return url_feof(s->pb) ? AVERROR_EOF : -1; + return url_feof(s->pb) ? AVERROR_EOF : ret; } static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) @@ -2527,7 +2575,8 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti /* if audio then truncate sample_time to EditRate */ if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) - sample_time = av_rescale_q(sample_time, st->time_base, av_inv_q(source_track->edit_rate)); + sample_time = av_rescale_q(sample_time, st->time_base, + av_inv_q(source_track->edit_rate)); if (mxf->nb_index_tables <= 0) { if (!s->bit_rate) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 5e77a3f06..bba01158f 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -294,6 +294,7 @@ typedef struct MXFContext { uint64_t body_offset; uint32_t instance_number; uint8_t umid[16]; ///< unique material identifier + int channel_count; } MXFContext; static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd }; @@ -618,7 +619,7 @@ static void mxf_write_identification(AVFormatContext *s) mxf_write_metadata_key(pb, 0x013000); PRINT_KEY(s, "identification key", pb->buf_ptr - 16); - version = s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT ? + version = s->flags & AVFMT_FLAG_BITEXACT ? "0.0.0" : AV_STRINGIFY(LIBAVFORMAT_VERSION); length = 84 + (strlen(company)+strlen(product)+strlen(version))*2; // utf-16 klv_encode_ber_length(pb, length); @@ -996,6 +997,8 @@ static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st) static void mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size) { AVIOContext *pb = s->pb; + MXFContext *mxf = s->priv_data; + int show_warnings = !mxf->footer_partition_offset; mxf_write_generic_desc(s, st, key, size+5+12+8+8); @@ -1009,7 +1012,21 @@ static void mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, con avio_wb32(pb, 1); mxf_write_local_tag(pb, 4, 0x3D07); - avio_wb32(pb, st->codec->channels); + if (mxf->channel_count == -1) { + if (show_warnings && (s->oformat == &ff_mxf_d10_muxer) && (st->codec->channels != 4) && (st->codec->channels != 8)) + av_log(s, AV_LOG_WARNING, "the number of audio channels shall be 4 or 8 : the output will not comply to MXF D-10 specs, use -d10_channelcount to fix this\n"); + avio_wb32(pb, st->codec->channels); + } else if (s->oformat == &ff_mxf_d10_muxer) { + if (show_warnings && (mxf->channel_count < st->codec->channels)) + av_log(s, AV_LOG_WARNING, "d10_channelcount < actual number of audio channels : some channels will be discarded\n"); + if (show_warnings && (mxf->channel_count != 4) && (mxf->channel_count != 8)) + av_log(s, AV_LOG_WARNING, "d10_channelcount shall be set to 4 or 8 : the output will not comply to MXF D-10 specs\n"); + avio_wb32(pb, mxf->channel_count); + } else { + if (show_warnings) + av_log(s, AV_LOG_ERROR, "-d10_channelcount requires MXF D-10 and will be ignored\n"); + avio_wb32(pb, st->codec->channels); + } mxf_write_local_tag(pb, 4, 0x3D01); avio_wb32(pb, av_get_bits_per_sample(st->codec->codec_id)); @@ -1689,7 +1706,8 @@ static int mxf_write_header(AVFormatContext *s) } if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - AVRational rate, tbc = st->codec->time_base; + // TODO: should be avg_frame_rate + AVRational rate, tbc = st->time_base; // Default component depth to 8 sc->component_depth = 8; mxf->timecode_base = (tbc.den + tbc.num/2) / tbc.num; @@ -1777,7 +1795,7 @@ static int mxf_write_header(AVFormatContext *s) mxf->essence_container_count = 1; } - if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) + if (!(s->flags & AVFMT_FLAG_BITEXACT)) mxf_gen_umid(s); for (i = 0; i < s->nb_streams; i++) { @@ -2155,6 +2173,19 @@ static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int mxf_interleave_get_packet, mxf_compare_timestamps); } +static const AVOption d10_options[] = { + { "d10_channelcount", "Force/set channelcount in generic sound essence descriptor", + offsetof(MXFContext, channel_count), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 8, AV_OPT_FLAG_ENCODING_PARAM}, + { NULL }, +}; + +static const AVClass mxf_d10_muxer_class = { + .class_name = "MXF-D10 muxer", + .item_name = av_default_item_name, + .option = d10_options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVOutputFormat ff_mxf_muxer = { .name = "mxf", .long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"), @@ -2182,4 +2213,5 @@ AVOutputFormat ff_mxf_d10_muxer = { .write_trailer = mxf_write_footer, .flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, + .priv_class = &mxf_d10_muxer_class, }; diff --git a/libavformat/network.c b/libavformat/network.c index 5e2bcf8d1..9f02ec6c5 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -76,7 +76,7 @@ void ff_tls_init(void) #if HAVE_THREADS if (!CRYPTO_get_locking_callback()) { int i; - openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks()); + openssl_mutexes = av_malloc_array(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); @@ -163,8 +163,8 @@ int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterrupt return ret; if (timeout > 0) { if (!wait_start) - wait_start = av_gettime(); - else if (av_gettime() - wait_start > timeout) + wait_start = av_gettime_relative(); + else if (av_gettime_relative() - wait_start > timeout) return AVERROR(ETIMEDOUT); } } diff --git a/libavformat/nsvdec.c b/libavformat/nsvdec.c index 4a749a2fe..e1fcfee4c 100644 --- a/libavformat/nsvdec.c +++ b/libavformat/nsvdec.c @@ -706,7 +706,6 @@ static int nsv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp static int nsv_read_close(AVFormatContext *s) { -/* int i; */ NSVContext *nsv = s->priv_data; av_freep(&nsv->nsvs_file_offset); @@ -715,20 +714,6 @@ static int nsv_read_close(AVFormatContext *s) av_free_packet(&nsv->ahead[0]); if (nsv->ahead[1].data) av_free_packet(&nsv->ahead[1]); - -#if 0 - - for(i=0;inb_streams;i++) { - AVStream *st = s->streams[i]; - NSVStream *ast = st->priv_data; - if(ast){ - av_free(ast->index_entries); - av_free(ast); - } - av_free(st->codec->palctrl); - } - -#endif return 0; } diff --git a/libavformat/nut.c b/libavformat/nut.c index c36bb6a37..9224a9637 100644 --- a/libavformat/nut.c +++ b/libavformat/nut.c @@ -82,10 +82,10 @@ const AVCodecTag ff_nut_video_tags[] = { { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 48 ) }, { AV_CODEC_ID_RAWVIDEO, MKTAG(48 , 'B', 'G', 'R') }, { AV_CODEC_ID_RAWVIDEO, MKTAG(48 , 'R', 'G', 'B') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'R', 'A', 64 ) }, { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'B', 'A', 64 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(64 , 'B', 'R', 'A') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'R', 'A', 64 ) }, { AV_CODEC_ID_RAWVIDEO, MKTAG(64 , 'R', 'B', 'A') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(64 , 'B', 'R', 'A') }, { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 11 , 10 ) }, { AV_CODEC_ID_RAWVIDEO, MKTAG(10 , 11 , '3', 'Y') }, { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 10 , 10 ) }, @@ -176,7 +176,8 @@ const AVCodecTag ff_nut_video_tags[] = { { AV_CODEC_ID_NONE, 0 } }; -static const AVCodecTag nut_audio_extra_tags[] = { +const AVCodecTag ff_nut_audio_extra_tags[] = { + { AV_CODEC_ID_COMFORT_NOISE, MKTAG('3', '3', '8', '9') }, { AV_CODEC_ID_PCM_ALAW, MKTAG('A', 'L', 'A', 'W') }, { AV_CODEC_ID_PCM_MULAW, MKTAG('U', 'L', 'A', 'W') }, { AV_CODEC_ID_MP3, MKTAG('M', 'P', '3', ' ') }, @@ -212,7 +213,7 @@ const AVCodecTag ff_nut_audio_tags[] = { const AVCodecTag * const ff_nut_codec_tags[] = { ff_nut_video_tags, ff_nut_audio_tags, ff_nut_subtitle_tags, - ff_codec_bmp_tags, ff_codec_wav_tags, nut_audio_extra_tags, ff_nut_data_tags, 0 + ff_codec_bmp_tags, ff_codec_wav_tags, ff_nut_audio_extra_tags, ff_nut_data_tags, 0 }; void ff_nut_reset_ts(NUTContext *nut, AVRational time_base, int64_t val) diff --git a/libavformat/nut.h b/libavformat/nut.h index 29f28e6ab..943081caf 100644 --- a/libavformat/nut.h +++ b/libavformat/nut.h @@ -36,7 +36,9 @@ #define MAX_DISTANCE (1024*32-1) -#define NUT_VERSION 3 +#define NUT_MAX_VERSION 4 +#define NUT_STABLE_VERSION 3 +#define NUT_MIN_VERSION 2 typedef enum{ FLAG_KEY = 1, ///buf_size; i++) { - code = (code << 8) | p->buf[i]; - if (code == MAIN_STARTCODE) + for (i = 0; i < p->buf_size-8; i++) { + if (AV_RB32(p->buf+i) != MAIN_STARTCODE>>32) + continue; + if (AV_RB32(p->buf+i+4) == (MAIN_STARTCODE & 0xFFFFFFFF)) return AVPROBE_SCORE_MAX; } return 0; @@ -228,13 +229,13 @@ static int decode_main_header(NUTContext *nut) end = get_packetheader(nut, bc, 1, MAIN_STARTCODE); end += avio_tell(bc); - tmp = ffio_read_varlen(bc); - if (tmp < 2 && tmp > 4) { - av_log(s, AV_LOG_ERROR, "Version %"PRId64" not supported.\n", - tmp); + nut->version = ffio_read_varlen(bc); + if (nut->version < NUT_MIN_VERSION && + nut->version > NUT_MAX_VERSION) { + av_log(s, AV_LOG_ERROR, "Version %d not supported.\n", + nut->version); return AVERROR(ENOSYS); } - nut->version = tmp; if (nut->version > 3) nut->minor_version = ffio_read_varlen(bc); @@ -340,6 +341,11 @@ static int decode_main_header(NUTContext *nut) av_assert0(nut->header_len[0] == 0); } + // flags had been effectively introduced in version 4 + if (nut->version > 3 && end > avio_tell(bc) + 4) { + nut->flags = ffio_read_varlen(bc); + } + if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { av_log(s, AV_LOG_ERROR, "main header checksum mismatch\n"); return AVERROR_INVALIDDATA; @@ -381,6 +387,7 @@ static int decode_stream_header(NUTContext *nut) st->codec->codec_id = av_codec_get_id((const AVCodecTag * const []) { ff_nut_video_tags, ff_codec_bmp_tags, + ff_codec_movvideo_tags, 0 }, tmp); @@ -390,6 +397,7 @@ static int decode_stream_header(NUTContext *nut) st->codec->codec_id = av_codec_get_id((const AVCodecTag * const []) { ff_nut_audio_tags, ff_codec_wav_tags, + ff_nut_audio_extra_tags, 0 }, tmp); @@ -577,6 +585,14 @@ static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr) ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count], tmp / nut->time_base_count); + if (nut->flags & NUT_BROADCAST) { + tmp = ffio_read_varlen(bc); + av_log(s, AV_LOG_VERBOSE, "Syncpoint wallclock %"PRId64"\n", + av_rescale_q(tmp / nut->time_base_count, + nut->time_base[tmp % nut->time_base_count], + AV_TIME_BASE_Q)); + } + if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n"); return AVERROR_INVALIDDATA; @@ -897,7 +913,8 @@ static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, int size, flags, size_mul, pts_delta, i, reserved_count; uint64_t tmp; - if (avio_tell(bc) > nut->last_syncpoint_pos + nut->max_distance) { + if (!(nut->flags & NUT_PIPE) && + avio_tell(bc) > nut->last_syncpoint_pos + nut->max_distance) { av_log(s, AV_LOG_ERROR, "Last frame must have been damaged %"PRId64" > %"PRId64" + %d\n", avio_tell(bc), nut->last_syncpoint_pos, nut->max_distance); @@ -950,8 +967,9 @@ static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, if (flags & FLAG_CHECKSUM) { avio_rb32(bc); // FIXME check this - } else if (size > 2 * nut->max_distance || FFABS(stc->last_pts - *pts) > - stc->max_pts_distance) { + } else if (!(nut->flags & NUT_PIPE) && + size > 2 * nut->max_distance || + FFABS(stc->last_pts - *pts) > stc->max_pts_distance) { av_log(s, AV_LOG_ERROR, "frame size > 2max_distance and no checksum\n"); return AVERROR_INVALIDDATA; } @@ -1117,6 +1135,10 @@ static int read_seek(AVFormatContext *s, int stream_index, int64_t pos, pos2, ts; int i; + if (nut->flags & NUT_PIPE) { + return AVERROR(ENOSYS); + } + if (st->index_entries) { int index = av_index_search_timestamp(st, pts, flags); if (index < 0) diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c index 604fe760b..5db380f75 100644 --- a/libavformat/nutenc.c +++ b/libavformat/nutenc.c @@ -26,6 +26,8 @@ #include "libavutil/tree.h" #include "libavutil/dict.h" #include "libavutil/avassert.h" +#include "libavutil/time.h" +#include "libavutil/opt.h" #include "libavcodec/bytestream.h" #include "libavcodec/mpegaudiodata.h" #include "nut.h" @@ -338,9 +340,9 @@ static void write_mainheader(NUTContext *nut, AVIOContext *bc) tmp_head_idx; int64_t tmp_match; - ff_put_v(bc, nut->version = NUT_VERSION); + ff_put_v(bc, nut->version); if (nut->version > 3) - ff_put_v(bc, nut->minor_version); + ff_put_v(bc, nut->minor_version = 1); ff_put_v(bc, nut->avf->nb_streams); ff_put_v(bc, nut->max_distance); ff_put_v(bc, nut->time_base_count); @@ -407,6 +409,9 @@ static void write_mainheader(NUTContext *nut, AVIOContext *bc) ff_put_v(bc, nut->header_len[i]); avio_write(bc, nut->header[i], nut->header_len[i]); } + // flags had been effectively introduced in version 4 + if (nut->version > 3) + ff_put_v(bc, nut->flags); } static int write_streamheader(AVFormatContext *avctx, AVIOContext *bc, @@ -692,6 +697,16 @@ static int nut_write_header(AVFormatContext *s) nut->avf = s; + nut->version = FFMAX(NUT_STABLE_VERSION, 3 + !!nut->flags); + if (nut->version > 3 && s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + av_log(s, AV_LOG_ERROR, + "The additional syncpoint modes require version %d, " + "that is currently not finalized, " + "please set -f_strict experimental in order to enable it.\n", + nut->version); + return AVERROR_EXPERIMENTAL; + } + nut->stream = av_calloc(s->nb_streams, sizeof(*nut->stream )); nut->chapter = av_calloc(s->nb_chapters, sizeof(*nut->chapter)); nut->time_base= av_calloc(s->nb_streams + @@ -707,7 +722,7 @@ static int nut_write_header(AVFormatContext *s) AVStream *st = s->streams[i]; int ssize; AVRational time_base; - ff_parse_specific_params(st->codec, &time_base.den, &ssize, &time_base.num); + ff_parse_specific_params(st, &time_base.den, &ssize, &time_base.num); if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->codec->sample_rate) { time_base = (AVRational) {1, st->codec->sample_rate}; @@ -815,7 +830,6 @@ static int find_best_header_idx(NUTContext *nut, AVPacket *pkt) static int write_sm_data(AVFormatContext *s, AVIOContext *bc, AVPacket *pkt, int is_meta) { - AVStream *st = s->streams[pkt->stream_index]; int ret, i, dyn_size; unsigned flags; AVIOContext *dyn_bc; @@ -835,14 +849,18 @@ static int write_sm_data(AVFormatContext *s, AVIOContext *bc, AVPacket *pkt, int if (is_meta) { if ( pkt->side_data[i].type == AV_PKT_DATA_METADATA_UPDATE || pkt->side_data[i].type == AV_PKT_DATA_STRINGS_METADATA) { - if (!size || data[size-1]) - return AVERROR(EINVAL); + if (!size || data[size-1]) { + ret = AVERROR(EINVAL); + goto fail; + } while (data < data_end) { const uint8_t *key = data; const uint8_t *val = data + strlen(key) + 1; - if(val >= data_end) - return AVERROR(EINVAL); + if(val >= data_end) { + ret = AVERROR(EINVAL); + goto fail; + } put_str(dyn_bc, key); put_s(dyn_bc, -1); put_str(dyn_bc, val); @@ -865,7 +883,7 @@ static int write_sm_data(AVFormatContext *s, AVIOContext *bc, AVPacket *pkt, int put_str(dyn_bc, tmp); } else { snprintf(tmp, sizeof(tmp), "UserData%s-SD-%d", - (st->codec->flags & CODEC_FLAG_BITEXACT) ? "Lavf" : LIBAVFORMAT_IDENT, + (s->flags & AVFMT_FLAG_BITEXACT) ? "Lavf" : LIBAVFORMAT_IDENT, pkt->side_data[i].type); put_str(dyn_bc, tmp); } @@ -923,12 +941,13 @@ static int write_sm_data(AVFormatContext *s, AVIOContext *bc, AVPacket *pkt, int } } +fail: ff_put_v(bc, sm_data_count); dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf); avio_write(bc, dyn_buf, dyn_size); av_freep(&dyn_buf); - return 0; + return ret; } static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) @@ -942,15 +961,17 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) int best_header_idx; int key_frame = !!(pkt->flags & AV_PKT_FLAG_KEY); int store_sp = 0; - int ret; + int ret = 0; int sm_size = 0; int data_size = pkt->size; - uint8_t *sm_buf; + uint8_t *sm_buf = NULL; if (pkt->pts < 0) { av_log(s, AV_LOG_ERROR, "Negative pts not supported stream %d, pts %"PRId64"\n", pkt->stream_index, pkt->pts); + if (pkt->pts == AV_NOPTS_VALUE) + av_log(s, AV_LOG_ERROR, "Try to enable the genpts flag\n"); return AVERROR(EINVAL); } @@ -958,9 +979,12 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) ret = avio_open_dyn_buf(&sm_bc); if (ret < 0) return ret; - write_sm_data(s, sm_bc, pkt, 0); - write_sm_data(s, sm_bc, pkt, 1); + ret = write_sm_data(s, sm_bc, pkt, 0); + if (ret >= 0) + ret = write_sm_data(s, sm_bc, pkt, 1); sm_size = avio_close_dyn_buf(sm_bc, &sm_buf); + if (ret < 0) + goto fail; data_size += sm_size; } @@ -975,8 +999,9 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) //FIXME: Ensure store_sp is 1 in the first place. - if (store_sp) { - Syncpoint *sp, dummy = { .pos = INT64_MAX }; + if (store_sp && + (!(nut->flags & NUT_PIPE) || nut->last_syncpoint_pos == INT_MIN)) { + int64_t sp_pos = INT64_MAX; ff_nut_reset_ts(nut, *nus->time_base, pkt->dts); for (i = 0; i < s->nb_streams; i++) { @@ -987,35 +1012,47 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) AV_ROUND_DOWN); int index = av_index_search_timestamp(st, dts_tb, AVSEEK_FLAG_BACKWARD); - if (index >= 0) - dummy.pos = FFMIN(dummy.pos, st->index_entries[index].pos); + if (index >= 0) { + sp_pos = FFMIN(sp_pos, st->index_entries[index].pos); + if (!nut->write_index && 2*index > st->nb_index_entries) { + memmove(st->index_entries, + st->index_entries + index, + sizeof(*st->index_entries) * (st->nb_index_entries - index)); + st->nb_index_entries -= index; + } + } } - if (dummy.pos == INT64_MAX) - dummy.pos = 0; - sp = av_tree_find(nut->syncpoints, &dummy, (void *)ff_nut_sp_pos_cmp, - NULL); nut->last_syncpoint_pos = avio_tell(bc); ret = avio_open_dyn_buf(&dyn_bc); if (ret < 0) - return ret; + goto fail; put_tt(nut, nus->time_base, dyn_bc, pkt->dts); - ff_put_v(dyn_bc, sp ? (nut->last_syncpoint_pos - sp->pos) >> 4 : 0); + ff_put_v(dyn_bc, sp_pos != INT64_MAX ? (nut->last_syncpoint_pos - sp_pos) >> 4 : 0); + + if (nut->flags & NUT_BROADCAST) { + put_tt(nut, nus->time_base, dyn_bc, + av_rescale_q(av_gettime(), AV_TIME_BASE_Q, *nus->time_base)); + } put_packet(nut, bc, dyn_bc, 1, SYNCPOINT_STARTCODE); + if (nut->write_index) { if ((ret = ff_nut_add_sp(nut, nut->last_syncpoint_pos, 0 /*unused*/, pkt->dts)) < 0) - return ret; + goto fail; if ((1ll<<60) % nut->sp_count == 0) for (i=0; inb_streams; i++) { int j; StreamContext *nus = &nut->stream[i]; av_reallocp_array(&nus->keyframe_pts, 2*nut->sp_count, sizeof(*nus->keyframe_pts)); - if (!nus->keyframe_pts) - return AVERROR(ENOMEM); + if (!nus->keyframe_pts) { + ret = AVERROR(ENOMEM); + goto fail; + } for (j=nut->sp_count == 1 ? 0 : nut->sp_count; j<2*nut->sp_count; j++) nus->keyframe_pts[j] = AV_NOPTS_VALUE; } + } } av_assert0(nus->last_pts != AV_NOPTS_VALUE); @@ -1103,7 +1140,6 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) if (flags & FLAG_SM_DATA) { avio_write(bc, sm_buf, sm_size); - av_freep(&sm_buf); } avio_write(bc, pkt->data + nut->header_len[header_idx], pkt->size - nut->header_len[header_idx]); @@ -1111,7 +1147,7 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) nus->last_pts = pkt->pts; //FIXME just store one per syncpoint - if (flags & FLAG_KEY) { + if (flags & FLAG_KEY && !(nut->flags & NUT_PIPE)) { av_add_index_entry( s->streams[pkt->stream_index], nut->last_syncpoint_pos, @@ -1128,7 +1164,10 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) nut->max_pts_tb = nus->time_base; } - return 0; +fail: + av_freep(&sm_buf); + + return ret; } static int nut_write_trailer(AVFormatContext *s) @@ -1142,6 +1181,7 @@ static int nut_write_trailer(AVFormatContext *s) ret = avio_open_dyn_buf(&dyn_bc); if (ret >= 0 && nut->sp_count) { + av_assert1(nut->write_index); write_index(nut, dyn_bc); put_packet(nut, bc, dyn_bc, 1, INDEX_STARTCODE); } @@ -1157,6 +1197,24 @@ static int nut_write_trailer(AVFormatContext *s) return 0; } +#define OFFSET(x) offsetof(NUTContext, x) +#define E AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "syncpoints", "NUT syncpoint behaviour", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, E, "syncpoints" }, + { "default", "", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, INT_MIN, INT_MAX, E, "syncpoints" }, + { "none", "Disable syncpoints, low overhead and unseekable", 0, AV_OPT_TYPE_CONST, {.i64 = NUT_PIPE}, INT_MIN, INT_MAX, E, "syncpoints" }, + { "timestamped", "Extend syncpoints with a wallclock timestamp", 0, AV_OPT_TYPE_CONST, {.i64 = NUT_BROADCAST}, INT_MIN, INT_MAX, E, "syncpoints" }, + { "write_index", "Write index", OFFSET(write_index), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E, }, + { NULL }, +}; + +static const AVClass class = { + .class_name = "nutenc", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVOutputFormat ff_nut_muxer = { .name = "nut", .long_name = NULL_IF_CONFIG_SMALL("NUT"), @@ -1171,4 +1229,5 @@ AVOutputFormat ff_nut_muxer = { .write_trailer = nut_write_trailer, .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS, .codec_tag = ff_nut_codec_tags, + .priv_class = &class, }; diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index fd18e9986..f7d00c1b4 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -647,6 +647,9 @@ static int ogg_read_close(AVFormatContext *s) av_freep(&ogg->streams[i].private); av_freep(&ogg->streams[i].new_metadata); } + + ogg->nstreams = 0; + av_freep(&ogg->streams); return 0; } @@ -793,11 +796,8 @@ retry: uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10); - if(side_data == NULL) { - av_free_packet(pkt); - av_free(pkt); - return AVERROR(ENOMEM); - } + if(side_data == NULL) + goto fail; AV_WL32(side_data + 4, os->end_trimming); os->end_trimming = 0; } @@ -806,12 +806,19 @@ retry: uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_METADATA_UPDATE, os->new_metadata_size); + if(side_data == NULL) + goto fail; + memcpy(side_data, os->new_metadata, os->new_metadata_size); av_freep(&os->new_metadata); os->new_metadata_size = 0; } return psize; +fail: + av_free_packet(pkt); + av_free(pkt); + return AVERROR(ENOMEM); } static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, @@ -830,7 +837,7 @@ static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) { if (i == stream_index) { struct ogg_stream *os = ogg->streams + stream_index; - // Dont trust the last timestamps of a ogm video + // Do not trust the last timestamps of a ogm video if ( (os->flags & OGG_FLAG_EOS) && !(os->flags & OGG_FLAG_BOS) && os->codec == &ff_ogm_video_codec) diff --git a/libavformat/oggdec.h b/libavformat/oggdec.h index 231b58377..22647e131 100644 --- a/libavformat/oggdec.h +++ b/libavformat/oggdec.h @@ -129,7 +129,8 @@ 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 ff_vorbis_comment(AVFormatContext *ms, AVDictionary **m, + const uint8_t *buf, int size, int parse_picture); static inline int ogg_find_stream (struct ogg * ogg, int serial) diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index 9c6475559..f6a6d7d96 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -277,18 +277,17 @@ static uint8_t *ogg_write_vorbiscomment(int offset, int bitexact, const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT; int size; uint8_t *p, *p0; - unsigned int count; ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL); - size = offset + ff_vorbiscomment_length(*m, vendor, &count) + framing_bit; + size = offset + ff_vorbiscomment_length(*m, vendor) + framing_bit; p = av_mallocz(size); if (!p) return NULL; p0 = p; p += offset; - ff_vorbiscomment_write(&p, m, vendor, count); + ff_vorbiscomment_write(&p, m, vendor); if (framing_bit) bytestream_put_byte(&p, 1); @@ -392,6 +391,28 @@ static int ogg_build_opus_headers(AVCodecContext *avctx, return 0; } +static void ogg_write_pages(AVFormatContext *s, int flush) +{ + OGGContext *ogg = s->priv_data; + OGGPageList *next, *p; + + if (!ogg->page_list) + return; + + for (p = ogg->page_list; p; ) { + OGGStreamContext *oggstream = + s->streams[p->page.stream_index]->priv_data; + if (oggstream->page_count < 2 && !flush) + break; + ogg_write_page(s, &p->page, + flush == 1 && oggstream->page_count == 1 ? 4 : 0); // eos + next = p->next; + av_freep(&p); + p = next; + } + ogg->page_list = p; +} + static int ogg_write_header(AVFormatContext *s) { OGGContext *ogg = s->priv_data; @@ -411,8 +432,8 @@ static int ogg_write_header(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, 48000); else avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); - } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) - avpriv_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den); + } + 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 && @@ -427,9 +448,12 @@ static int ogg_write_header(AVFormatContext *s) return -1; } oggstream = av_mallocz(sizeof(*oggstream)); + if (!oggstream) + return AVERROR(ENOMEM); + oggstream->page.stream_index = i; - if (!(st->codec->flags & CODEC_FLAG_BITEXACT)) + if (!(s->flags & AVFMT_FLAG_BITEXACT)) do { serial_num = av_get_random_seed(); for (j = 0; j < i; j++) { @@ -445,7 +469,7 @@ static int ogg_write_header(AVFormatContext *s) st->priv_data = oggstream; if (st->codec->codec_id == AV_CODEC_ID_FLAC) { int err = ogg_build_flac_headers(st->codec, oggstream, - st->codec->flags & CODEC_FLAG_BITEXACT, + s->flags & AVFMT_FLAG_BITEXACT, &st->metadata); if (err) { av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n"); @@ -454,7 +478,7 @@ static int ogg_write_header(AVFormatContext *s) } } else if (st->codec->codec_id == AV_CODEC_ID_SPEEX) { int err = ogg_build_speex_headers(st->codec, oggstream, - st->codec->flags & CODEC_FLAG_BITEXACT, + s->flags & AVFMT_FLAG_BITEXACT, &st->metadata); if (err) { av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n"); @@ -463,7 +487,7 @@ static int ogg_write_header(AVFormatContext *s) } } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) { int err = ogg_build_opus_headers(st->codec, oggstream, - st->codec->flags & CODEC_FLAG_BITEXACT, + s->flags & AVFMT_FLAG_BITEXACT, &st->metadata); if (err) { av_log(s, AV_LOG_ERROR, "Error writing Opus headers\n"); @@ -484,7 +508,7 @@ static int ogg_write_header(AVFormatContext *s) return -1; } - p = ogg_write_vorbiscomment(7, st->codec->flags & CODEC_FLAG_BITEXACT, + p = ogg_write_vorbiscomment(7, s->flags & AVFMT_FLAG_BITEXACT, &oggstream->header_len[1], &st->metadata, framing_bit); oggstream->header[1] = p; @@ -525,32 +549,12 @@ static int ogg_write_header(AVFormatContext *s) oggstream->page.start_granule = AV_NOPTS_VALUE; + ogg_write_pages(s, 2); + return 0; } -static void ogg_write_pages(AVFormatContext *s, int flush) -{ - OGGContext *ogg = s->priv_data; - OGGPageList *next, *p; - - if (!ogg->page_list) - return; - - for (p = ogg->page_list; p; ) { - OGGStreamContext *oggstream = - s->streams[p->page.stream_index]->priv_data; - if (oggstream->page_count < 2 && !flush) - break; - ogg_write_page(s, &p->page, - flush && oggstream->page_count == 1 ? 4 : 0); // eos - next = p->next; - av_freep(&p); - p = next; - } - ogg->page_list = p; -} - -static int ogg_write_packet(AVFormatContext *s, AVPacket *pkt) +static int ogg_write_packet_internal(AVFormatContext *s, AVPacket *pkt) { AVStream *st = s->streams[pkt->stream_index]; OGGStreamContext *oggstream = st->priv_data; @@ -588,6 +592,23 @@ static int ogg_write_packet(AVFormatContext *s, AVPacket *pkt) return 0; } +static int ogg_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + int i; + + if (pkt) + return ogg_write_packet_internal(s, pkt); + + for (i = 0; i < s->nb_streams; i++) { + OGGStreamContext *oggstream = s->streams[i]->priv_data; + if (oggstream->page.segments_count) + ogg_buffer_page(s, oggstream); + } + + ogg_write_pages(s, 2); + return 0; +} + static int ogg_write_trailer(AVFormatContext *s) { int i; @@ -643,11 +664,35 @@ AVOutputFormat ff_ogg_muxer = { .write_header = ogg_write_header, .write_packet = ogg_write_packet, .write_trailer = ogg_write_trailer, - .flags = AVFMT_TS_NEGATIVE, + .flags = AVFMT_TS_NEGATIVE | AVFMT_ALLOW_FLUSH, .priv_class = &ogg_muxer_class, }; #endif +#if CONFIG_OGA_MUXER +static const AVClass oga_muxer_class = { + .class_name = "Ogg audio muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +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 = AV_CODEC_ID_VORBIS, + .video_codec = AV_CODEC_ID_NONE, + .write_header = ogg_write_header, + .write_packet = ogg_write_packet, + .write_trailer = ogg_write_trailer, + .flags = AVFMT_TS_NEGATIVE, + .priv_class = &oga_muxer_class, +}; +#endif + #if CONFIG_SPEEX_MUXER static const AVClass speex_muxer_class = { .class_name = "Speex muxer", diff --git a/libavformat/oggparsecelt.c b/libavformat/oggparsecelt.c index f3c2c1a63..51ebc35e1 100644 --- a/libavformat/oggparsecelt.c +++ b/libavformat/oggparsecelt.c @@ -42,19 +42,20 @@ static int celt_header(AVFormatContext *s, int idx) !memcmp(p, ff_celt_codec.magic, ff_celt_codec.magicsize)) { /* Main header */ - uint32_t version, sample_rate, nb_channels, frame_size; + uint32_t version, sample_rate, nb_channels; uint32_t overlap, extra_headers; priv = av_malloc(sizeof(struct oggcelt_private)); if (!priv) return AVERROR(ENOMEM); - if (ff_alloc_extradata(st->codec, 2 * sizeof(uint32_t)) < 0) + if (ff_alloc_extradata(st->codec, 2 * sizeof(uint32_t)) < 0) { + av_free(priv); return AVERROR(ENOMEM); + } version = AV_RL32(p + 28); /* unused header size field skipped */ sample_rate = AV_RL32(p + 36); nb_channels = AV_RL32(p + 40); - frame_size = AV_RL32(p + 44); overlap = AV_RL32(p + 48); /* unused bytes per packet field skipped */ extra_headers = AV_RL32(p + 56); @@ -62,7 +63,6 @@ static int celt_header(AVFormatContext *s, int idx) st->codec->codec_id = AV_CODEC_ID_CELT; st->codec->sample_rate = sample_rate; st->codec->channels = nb_channels; - st->codec->frame_size = frame_size; if (sample_rate) avpriv_set_pts_info(st, 64, 1, sample_rate); priv->extra_headers_left = 1 + extra_headers; @@ -74,7 +74,7 @@ static int celt_header(AVFormatContext *s, int idx) } else if (priv && priv->extra_headers_left) { /* Extra headers (vorbiscomment) */ - ff_vorbis_comment(s, &st->metadata, p, os->psize); + ff_vorbis_comment(s, &st->metadata, p, os->psize, 1); priv->extra_headers_left--; return 1; } else { diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c index f69533f6c..875de2a3b 100644 --- a/libavformat/oggparseflac.c +++ b/libavformat/oggparseflac.c @@ -68,7 +68,7 @@ flac_header (AVFormatContext * s, int idx) avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); } else if (mdt == FLAC_METADATA_TYPE_VORBIS_COMMENT) { - ff_vorbis_comment (s, &st->metadata, os->buf + os->pstart + 4, os->psize - 4); + ff_vorbis_comment (s, &st->metadata, os->buf + os->pstart + 4, os->psize - 4, 1); } return 1; diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c index 95369df89..508a0dc54 100644 --- a/libavformat/oggparseogm.c +++ b/libavformat/oggparseogm.c @@ -111,7 +111,7 @@ ogm_header(AVFormatContext *s, int idx) } else if (bytestream2_peek_byte(&p) == 3) { bytestream2_skip(&p, 7); if (bytestream2_get_bytes_left(&p) > 1) - ff_vorbis_comment(s, &st->metadata, p.buffer, bytestream2_get_bytes_left(&p) - 1); + ff_vorbis_comment(s, &st->metadata, p.buffer, bytestream2_get_bytes_left(&p) - 1, 1); } return 1; diff --git a/libavformat/oggparseopus.c b/libavformat/oggparseopus.c index 75c611413..7dfb13d5d 100644 --- a/libavformat/oggparseopus.c +++ b/libavformat/oggparseopus.c @@ -78,7 +78,7 @@ static int opus_header(AVFormatContext *avf, int idx) if (priv->need_comments) { if (os->psize < 8 || memcmp(packet, "OpusTags", 8)) return AVERROR_INVALIDDATA; - ff_vorbis_comment(avf, &st->metadata, packet + 8, os->psize - 8); + ff_vorbis_comment(avf, &st->metadata, packet + 8, os->psize - 8, 1); priv->need_comments--; return 1; } diff --git a/libavformat/oggparseskeleton.c b/libavformat/oggparseskeleton.c index d94b0c2e0..6c2105f32 100644 --- a/libavformat/oggparseskeleton.c +++ b/libavformat/oggparseskeleton.c @@ -34,7 +34,6 @@ static int skeleton_header(AVFormatContext *s, int idx) uint64_t start_granule; int target_idx, start_time; - strcpy(st->codec->codec_name, "skeleton"); st->codec->codec_type = AVMEDIA_TYPE_DATA; if ((os->flags & OGG_FLAG_EOS) && os->psize == 0) diff --git a/libavformat/oggparsespeex.c b/libavformat/oggparsespeex.c index 1b9de9c95..69dd62dfd 100644 --- a/libavformat/oggparsespeex.c +++ b/libavformat/oggparsespeex.c @@ -83,7 +83,7 @@ static int speex_header(AVFormatContext *s, int idx) { avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); } else - ff_vorbis_comment(s, &st->metadata, p, os->psize); + ff_vorbis_comment(s, &st->metadata, p, os->psize, 1); spxp->seq++; return 1; diff --git a/libavformat/oggparsetheora.c b/libavformat/oggparsetheora.c index 59df17efb..4a8005f10 100644 --- a/libavformat/oggparsetheora.c +++ b/libavformat/oggparsetheora.c @@ -116,7 +116,7 @@ static int theora_header(AVFormatContext *s, int idx) } break; case 0x81: - ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 7); + ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 7, 1); case 0x82: if (!thp->version) return AVERROR_INVALIDDATA; diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c index 53e69dffa..8103d9dbb 100644 --- a/libavformat/oggparsevorbis.c +++ b/libavformat/oggparsevorbis.c @@ -36,6 +36,7 @@ #include "internal.h" #include "oggdec.h" #include "vorbiscomment.h" +#include "replaygain.h" static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val) { @@ -71,7 +72,8 @@ static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val) } int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m, - const uint8_t *buf, int size) + const uint8_t *buf, int size, + int parse_picture) { const uint8_t *p = buf; const uint8_t *end = buf + size; @@ -136,7 +138,7 @@ int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m, * 'METADATA_BLOCK_PICTURE'. This is the preferred and * recommended way of embedding cover art within VorbisComments." */ - if (!strcmp(tt, "METADATA_BLOCK_PICTURE")) { + if (!strcmp(tt, "METADATA_BLOCK_PICTURE") && parse_picture) { int ret; char *pict = av_malloc(vl); @@ -156,7 +158,7 @@ int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m, continue; } } else if (!ogm_chapter(as, tt, ct)) { - if (m && av_dict_get(*m, tt, NULL, 0)) { + if (av_dict_get(*m, tt, NULL, 0)) { av_dict_set(m, tt, ";", AV_DICT_APPEND); } av_dict_set(m, tt, ct, @@ -169,7 +171,7 @@ int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m, if (p != end) av_log(as, AV_LOG_INFO, - "%ti bytes of comment header remain\n", end - p); + "%"PTRDIFF_SPECIFIER" bytes of comment header remain\n", end - p); if (n > 0) av_log(as, AV_LOG_INFO, "truncated comment header, %i comments not found\n", n); @@ -255,7 +257,7 @@ static int vorbis_update_metadata(AVFormatContext *s, int idx) /* New metadata packet; release old data. */ av_dict_free(&st->metadata); ret = ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, - os->psize - 8); + os->psize - 8, 1); if (ret < 0) return ret; @@ -347,9 +349,15 @@ static int vorbis_header(AVFormatContext *s, int idx) avpriv_set_pts_info(st, 64, 1, srate); } } else if (os->buf[os->pstart] == 3) { - if (vorbis_update_metadata(s, idx) >= 0) { + if (vorbis_update_metadata(s, idx) >= 0 && priv->len[1] > 10) { + unsigned new_len; + + int ret = ff_replaygain_export(st, st->metadata); + if (ret < 0) + return ret; + // drop all metadata we parsed and which is not required by libvorbis - unsigned new_len = 7 + 4 + AV_RL32(priv->packet[1] + 7) + 4 + 1; + new_len = 7 + 4 + AV_RL32(priv->packet[1] + 7) + 4 + 1; if (new_len >= 16 && new_len < os->psize) { AV_WL32(priv->packet[1] + new_len - 5, 0); priv->packet[1][new_len - 1] = 1; @@ -419,6 +427,10 @@ static int vorbis_packet(AVFormatContext *s, int idx) } os->lastpts = os->lastdts = os->granule - duration; + + if (!os->granule && duration) //hack to deal with broken files (Ticket3710) + os->lastpts = os->lastdts = AV_NOPTS_VALUE; + if (s->streams[idx]->start_time == AV_NOPTS_VALUE) { s->streams[idx]->start_time = FFMAX(os->lastpts, 0); if (s->streams[idx]->duration != AV_NOPTS_VALUE) diff --git a/libavformat/oggparsevp8.c b/libavformat/oggparsevp8.c index 89295c86a..b3dd7ab84 100644 --- a/libavformat/oggparsevp8.c +++ b/libavformat/oggparsevp8.c @@ -64,7 +64,7 @@ static int vp8_header(AVFormatContext *s, int idx) case 0x02: if (p[6] != 0x20) return AVERROR_INVALIDDATA; - ff_vorbis_comment(s, &st->metadata, p + 7, os->psize - 7); + ff_vorbis_comment(s, &st->metadata, p + 7, os->psize - 7, 1); break; default: av_log(s, AV_LOG_ERROR, "Unknown VP8 header type 0x%02X\n", p[5]); diff --git a/libavformat/omadec.c b/libavformat/omadec.c index 7542eb1fd..9f3d3aa86 100644 --- a/libavformat/omadec.c +++ b/libavformat/omadec.c @@ -40,6 +40,8 @@ * Supported decoders: ATRAC3, ATRAC3+, MP3, LPCM */ +#include + #include "libavutil/channel_layout.h" #include "avformat.h" #include "internal.h" @@ -215,7 +217,7 @@ static int decrypt_init(AVFormatContext *s, ID3v2ExtraMeta *em, uint8_t *header) if (geob->datasize < 64) { av_log(s, AV_LOG_ERROR, - "Invalid GEOB data size: %u\n", geob->datasize); + "Invalid GEOB data size: %"PRIu32"\n", geob->datasize); return AVERROR_INVALIDDATA; } @@ -239,7 +241,7 @@ static int decrypt_init(AVFormatContext *s, ID3v2ExtraMeta *em, uint8_t *header) return AVERROR_INVALIDDATA; } oc->rid = AV_RB32(&gdata[OMA_ENC_HEADER_SIZE + 28]); - av_log(s, AV_LOG_DEBUG, "RID: %.8x\n", oc->rid); + av_log(s, AV_LOG_DEBUG, "RID: %.8"PRIx32"\n", oc->rid); memcpy(oc->iv, &header[0x58], 8); hex_log(s, AV_LOG_DEBUG, "IV", oc->iv, 8); @@ -366,7 +368,7 @@ static int oma_read_header(AVFormatContext *s) channel_id = (codec_params >> 10) & 7; if (!channel_id) { av_log(s, AV_LOG_ERROR, - "Invalid ATRAC-X channel id: %d\n", channel_id); + "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]; diff --git a/libavformat/omaenc.c b/libavformat/omaenc.c index b94798723..fe0669f5c 100644 --- a/libavformat/omaenc.c +++ b/libavformat/omaenc.c @@ -103,4 +103,5 @@ AVOutputFormat ff_oma_muxer = { .write_header = oma_write_header, .write_packet = ff_raw_write_packet, .codec_tag = (const AVCodecTag* const []){ff_oma_codec_tags, 0}, + .flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/options_table.h b/libavformat/options_table.h index c80309cdb..e3943fd5f 100644 --- a/libavformat/options_table.h +++ b/libavformat/options_table.h @@ -25,6 +25,7 @@ #include "libavutil/opt.h" #include "avformat.h" +#include "internal.h" #define OFFSET(x) offsetof(AVFormatContext,x) #define DEFAULT 0 //should be NAN but it does not work as it is not a constant in glibc as required by ANSI/ISO C @@ -36,9 +37,10 @@ static const AVOption avformat_options[] = { {"avioflags", NULL, OFFSET(avio_flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "avioflags"}, {"direct", "reduce buffering", 0, AV_OPT_TYPE_CONST, {.i64 = AVIO_FLAG_DIRECT }, INT_MIN, INT_MAX, D|E, "avioflags"}, {"probesize", "set probing size", OFFSET(probesize), AV_OPT_TYPE_INT, {.i64 = 5000000 }, 32, INT_MAX, D}, +{"formatprobesize", "number of bytes to probe file format", OFFSET(format_probesize), AV_OPT_TYPE_INT, {.i64 = PROBE_BUF_MAX}, 0, INT_MAX-1, D}, {"packetsize", "set packet size", OFFSET(packet_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, E}, {"fflags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = AVFMT_FLAG_FLUSH_PACKETS }, INT_MIN, INT_MAX, D|E, "fflags"}, -{"flush_packets", "reduce the latency by flushing out packets immediately", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_FLUSH_PACKETS }, INT_MIN, INT_MAX, D, "fflags"}, +{"flush_packets", "reduce the latency by flushing out packets immediately", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_FLUSH_PACKETS }, INT_MIN, INT_MAX, E, "fflags"}, {"ignidx", "ignore index", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_IGNIDX }, INT_MIN, INT_MAX, D, "fflags"}, {"genpts", "generate pts", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_GENPTS }, INT_MIN, INT_MAX, D, "fflags"}, {"nofillin", "do not fill in missing values that can be exactly calculated", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOFILLIN }, INT_MIN, INT_MAX, D, "fflags"}, @@ -50,13 +52,15 @@ static const AVOption avformat_options[] = { {"latm", "enable RTP MP4A-LATM payload", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_MP4A_LATM }, INT_MIN, INT_MAX, E, "fflags"}, {"nobuffer", "reduce the latency introduced by optional buffering", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOBUFFER }, 0, INT_MAX, D, "fflags"}, {"seek2any", "allow seeking to non-keyframes on demuxer level when supported", OFFSET(seek2any), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, D}, -{"analyzeduration", "specify how many microseconds are analyzed to probe the input", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT, {.i64 = 5*AV_TIME_BASE }, 0, INT_MAX, D}, +{"bitexact", "do not write random/volatile data", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_BITEXACT }, 0, 0, E, "fflags" }, +{"analyzeduration", "specify how many microseconds are analyzed to probe the input", OFFSET(max_analyze_duration2), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, D}, {"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D}, {"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), AV_OPT_TYPE_INT, {.i64 = 1<<20 }, 0, INT_MAX, D}, {"rtbufsize", "max memory used for buffering real-time frames", OFFSET(max_picture_buffer), AV_OPT_TYPE_INT, {.i64 = 3041280 }, 0, INT_MAX, D}, /* defaults to 1s of 15fps 352x288 YUYV422 video */ {"fdebug", "print specific debug info", OFFSET(debug), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, E|D, "fdebug"}, {"ts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_FDEBUG_TS }, INT_MIN, INT_MAX, E|D, "fdebug"}, {"max_delay", "maximum muxing or demuxing delay in microseconds", OFFSET(max_delay), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, INT_MAX, E|D}, +{"start_time_realtime", "wall-clock time when stream begins (PTS==0)", OFFSET(start_time_realtime), AV_OPT_TYPE_INT64, {.i64 = AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX, E}, {"fpsprobesize", "number of frames used to probe fps", OFFSET(fps_probe_size), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX-1, D}, {"audio_preload", "microseconds by which audio packets should be interleaved earlier", OFFSET(audio_preload), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, E}, {"chunk_duration", "microseconds for each chunk", OFFSET(max_chunk_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, E}, @@ -69,6 +73,7 @@ static const AVOption avformat_options[] = { {"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, D, "err_detect"}, {"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, D, "err_detect"}, {"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, D, "err_detect"}, +{"ignore_err", "ignore errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_IGNORE_ERR }, INT_MIN, INT_MAX, D, "err_detect"}, {"careful", "consider things that violate the spec, are fast to check and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, D, "err_detect"}, {"compliant", "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, D, "err_detect"}, {"aggressive", "consider things that a sane encoder shouldn't do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, D, "err_detect"}, @@ -78,12 +83,17 @@ static const AVOption avformat_options[] = { {"disabled", "do not change timestamps", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, {"make_zero", "shift timestamps so they start at 0", 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, {"make_non_negative", "shift timestamps so they are non negative", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, -{"skip_initial_bytes", "set number of bytes to skip before reading header and frames", OFFSET(skip_initial_bytes), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, D}, +{"skip_initial_bytes", "set number of bytes to skip before reading header and frames", OFFSET(skip_initial_bytes), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX-1, D}, {"correct_ts_overflow", "correct single timestamp overflows", OFFSET(correct_ts_overflow), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, D}, {"flush_packets", "enable flushing of the I/O context after each packet", OFFSET(flush_packets), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E}, {"metadata_header_padding", "set number of bytes to be written as padding in a metadata header", OFFSET(metadata_header_padding), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, E}, {"output_ts_offset", "set output timestamp offset", OFFSET(output_ts_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, -INT64_MAX, INT64_MAX, E}, {"max_interleave_delta", "maximum buffering duration for interleaving", OFFSET(max_interleave_delta), AV_OPT_TYPE_INT64, { .i64 = 10000000 }, 0, INT64_MAX, E }, +{"f_strict", "how strictly to follow the standards (deprecated; use strict, save via avconv)", OFFSET(strict_std_compliance), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "strict"}, +{"strict", "how strictly to follow the standards", OFFSET(strict_std_compliance), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "strict"}, +{"strict", "strictly conform to all the things in the spec no matter what the consequences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_STRICT }, INT_MIN, INT_MAX, 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"}, {NULL}, }; diff --git a/libavformat/paf.c b/libavformat/paf.c index 09aefe677..88a274fe1 100644 --- a/libavformat/paf.c +++ b/libavformat/paf.c @@ -44,13 +44,13 @@ typedef struct { uint32_t *blocks_offset_table; uint8_t *video_frame; - int video_size; + int video_size; uint8_t *audio_frame; uint8_t *temp_audio_frame; - int audio_size; + int audio_size; - int got_audio; + int got_audio; } PAFDemuxContext; static int read_probe(AVProbeData *p) @@ -87,10 +87,10 @@ static void read_table(AVFormatContext *s, uint32_t *table, uint32_t count) static int read_header(AVFormatContext *s) { - PAFDemuxContext *p = s->priv_data; + PAFDemuxContext *p = s->priv_data; AVIOContext *pb = s->pb; AVStream *ast, *vst; - int ret = 0; + int ret = 0; avio_skip(pb, 132); @@ -101,11 +101,13 @@ static int read_header(AVFormatContext *s) vst->start_time = 0; vst->nb_frames = vst->duration = - p->nb_frames = avio_rl32(pb); + p->nb_frames = avio_rl32(pb); avio_skip(pb, 4); + vst->codec->width = avio_rl32(pb); vst->codec->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; @@ -115,13 +117,13 @@ static int read_header(AVFormatContext *s) if (!ast) 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->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->codec->sample_rate = 22050; avpriv_set_pts_info(ast, 64, 1, 22050); p->buffer_size = avio_rl32(pb); @@ -143,16 +145,19 @@ static int read_header(AVFormatContext *s) p->frame_blks > INT_MAX / sizeof(uint32_t)) return AVERROR_INVALIDDATA; - p->blocks_count_table = av_mallocz(p->nb_frames * sizeof(uint32_t)); - p->frames_offset_table = av_mallocz(p->nb_frames * sizeof(uint32_t)); - p->blocks_offset_table = av_mallocz(p->frame_blks * sizeof(uint32_t)); + p->blocks_count_table = av_mallocz(p->nb_frames * + sizeof(*p->blocks_count_table)); + p->frames_offset_table = av_mallocz(p->nb_frames * + sizeof(*p->frames_offset_table)); + p->blocks_offset_table = av_mallocz(p->frame_blks * + sizeof(*p->blocks_offset_table)); - p->video_size = p->max_video_blks * p->buffer_size; - p->video_frame = av_mallocz(p->video_size); + p->video_size = p->max_video_blks * p->buffer_size; + p->video_frame = av_mallocz(p->video_size); - p->audio_size = p->max_audio_blks * p->buffer_size; - p->audio_frame = av_mallocz(p->audio_size); - p->temp_audio_frame = av_mallocz(p->audio_size); + p->audio_size = p->max_audio_blks * p->buffer_size; + p->audio_frame = av_mallocz(p->audio_size); + p->temp_audio_frame = av_mallocz(p->audio_size); if (!p->blocks_count_table || !p->frames_offset_table || @@ -186,7 +191,7 @@ fail: static int read_packet(AVFormatContext *s, AVPacket *pkt) { - PAFDemuxContext *p = s->priv_data; + PAFDemuxContext *p = s->priv_data; AVIOContext *pb = s->pb; uint32_t count, offset; int size, i; @@ -209,7 +214,8 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) return pkt->size; } - count = (p->current_frame == 0) ? p->preload_count : p->blocks_count_table[p->current_frame - 1]; + count = (p->current_frame == 0) ? p->preload_count + : p->blocks_count_table[p->current_frame - 1]; for (i = 0; i < count; i++) { if (p->current_frame_block >= p->frame_blks) return AVERROR_INVALIDDATA; @@ -245,7 +251,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) pkt->duration = 1; memcpy(pkt->data, p->video_frame + p->frames_offset_table[p->current_frame], size); if (pkt->data[0] & 0x20) - pkt->flags |= AV_PKT_FLAG_KEY; + pkt->flags |= AV_PKT_FLAG_KEY; p->current_frame++; return pkt->size; diff --git a/libavformat/pcm.c b/libavformat/pcm.c index 2fe44dcb4..a57a4b624 100644 --- a/libavformat/pcm.c +++ b/libavformat/pcm.c @@ -37,8 +37,6 @@ int ff_pcm_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->flags &= ~AV_PKT_FLAG_CORRUPT; pkt->stream_index = 0; - if (ret < 0) - return ret; return ret; } diff --git a/libavformat/pcmdec.c b/libavformat/pcmdec.c index f4264d91c..2584c33c2 100644 --- a/libavformat/pcmdec.c +++ b/libavformat/pcmdec.c @@ -144,3 +144,29 @@ PCMDEF(alaw, "PCM A-law", PCMDEF(mulaw, "PCM mu-law", "ul", AV_CODEC_ID_PCM_MULAW) + +static const AVOption sln_options[] = { + { "sample_rate", "", offsetof(PCMAudioDemuxerContext, sample_rate), AV_OPT_TYPE_INT, {.i64 = 8000}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { "channels", "", offsetof(PCMAudioDemuxerContext, channels), AV_OPT_TYPE_INT, {.i64 = 1}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass sln_demuxer_class = { + .class_name = "sln demuxer", + .item_name = av_default_item_name, + .option = sln_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_sln_demuxer = { + .name = "sln", + .long_name = NULL_IF_CONFIG_SMALL("Asterisk raw pcm"), + .priv_data_size = sizeof(PCMAudioDemuxerContext), + .read_header = pcm_read_header, + .read_packet = ff_pcm_read_packet, + .read_seek = ff_pcm_read_seek, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "sln", + .raw_codec_id = AV_CODEC_ID_PCM_S16LE, + .priv_class = &sln_demuxer_class, +}; diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c index a9ff22ae1..ca9b2829d 100644 --- a/libavformat/rawdec.c +++ b/libavformat/rawdec.c @@ -28,6 +28,7 @@ #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" #include "libavutil/avassert.h" +#include "libavutil/intreadwrite.h" #define RAW_PACKET_SIZE 1024 @@ -121,6 +122,7 @@ AVInputFormat ff_data_demuxer = { #endif #if CONFIG_LATM_DEMUXER + AVInputFormat ff_latm_demuxer = { .name = "latm", .long_name = NULL_IF_CONFIG_SMALL("raw LOAS/LATM"), @@ -133,7 +135,73 @@ AVInputFormat ff_latm_demuxer = { #endif #if CONFIG_MJPEG_DEMUXER -FF_DEF_RAWVIDEO_DEMUXER(mjpeg, "raw MJPEG video", NULL, "mjpg,mjpeg,mpo", AV_CODEC_ID_MJPEG) +static int mjpeg_probe(AVProbeData *p) +{ + int i; + int state = -1; + int nb_invalid = 0; + int nb_frames = 0; + + for (i=0; ibuf_size-2; i++) { + int c; + if (p->buf[i] != 0xFF) + continue; + c = p->buf[i+1]; + switch (c) { + case 0xD8: + state = 0xD8; + break; + case 0xC0: + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xF7: + if (state == 0xD8) { + state = 0xC0; + } else + nb_invalid++; + break; + case 0xDA: + if (state == 0xC0) { + state = 0xDA; + } else + nb_invalid++; + break; + case 0xD9: + if (state == 0xDA) { + state = 0xD9; + nb_frames++; + } else + nb_invalid++; + break; + default: + if ( (c >= 0x02 && c <= 0xBF) + || c == 0xC8) { + nb_invalid++; + } + } + } + + if (nb_invalid*4 + 1 < nb_frames) { + static const char ct_jpeg[] = "\r\nContent-Type: image/jpeg\r\n\r\n"; + int i; + + for (i=0; ibuf_size - sizeof(ct_jpeg), 100); i++) + if (!memcmp(p->buf + i, ct_jpeg, sizeof(ct_jpeg) - 1)) + return AVPROBE_SCORE_EXTENSION; + + if (nb_invalid == 0 && nb_frames > 2) + return AVPROBE_SCORE_EXTENSION / 2; + return AVPROBE_SCORE_EXTENSION / 4; + } + + return 0; +} + +FF_DEF_RAWVIDEO_DEMUXER2(mjpeg, "raw MJPEG video", mjpeg_probe, "mjpg,mjpeg,mpo", AV_CODEC_ID_MJPEG, AVFMT_GENERIC_INDEX|AVFMT_NOTIMESTAMPS) #endif #if CONFIG_MLP_DEMUXER @@ -173,5 +241,5 @@ AVInputFormat ff_shorten_demuxer = { #endif #if CONFIG_VC1_DEMUXER -FF_DEF_RAWVIDEO_DEMUXER(vc1, "raw VC-1", NULL, "vc1", AV_CODEC_ID_VC1) +FF_DEF_RAWVIDEO_DEMUXER2(vc1, "raw VC-1", NULL, "vc1", AV_CODEC_ID_VC1, AVFMT_GENERIC_INDEX|AVFMT_NOTIMESTAMPS) #endif diff --git a/libavformat/rawdec.h b/libavformat/rawdec.h index 59108559d..328a4fbd4 100644 --- a/libavformat/rawdec.h +++ b/libavformat/rawdec.h @@ -49,7 +49,7 @@ static const AVClass name ## _demuxer_class = {\ .version = LIBAVUTIL_VERSION_INT,\ }; -#define FF_DEF_RAWVIDEO_DEMUXER(shortname, longname, probe, ext, id)\ +#define FF_DEF_RAWVIDEO_DEMUXER2(shortname, longname, probe, ext, id, flag)\ FF_RAWVIDEO_DEMUXER_CLASS(shortname)\ AVInputFormat ff_ ## shortname ## _demuxer = {\ .name = #shortname,\ @@ -58,10 +58,13 @@ AVInputFormat ff_ ## shortname ## _demuxer = {\ .read_header = ff_raw_video_read_header,\ .read_packet = ff_raw_read_partial_packet,\ .extensions = ext,\ - .flags = AVFMT_GENERIC_INDEX,\ + .flags = flag,\ .raw_codec_id = id,\ .priv_data_size = sizeof(FFRawVideoDemuxerContext),\ .priv_class = &shortname ## _demuxer_class,\ }; +#define FF_DEF_RAWVIDEO_DEMUXER(shortname, longname, probe, ext, id)\ +FF_DEF_RAWVIDEO_DEMUXER2(shortname, longname, probe, ext, id, AVFMT_GENERIC_INDEX) + #endif /* AVFORMAT_RAWDEC_H */ diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index abd7e6697..8b50fe1f1 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -269,7 +269,7 @@ AVOutputFormat ff_mlp_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/rdt.c b/libavformat/rdt.c index 201a3e046..37fcd7603 100644 --- a/libavformat/rdt.c +++ b/libavformat/rdt.c @@ -399,6 +399,8 @@ rdt_parse_b64buf (unsigned int *target_len, const char *p) } *target_len = len * 3 / 4; target = av_mallocz(*target_len + FF_INPUT_BUFFER_PADDING_SIZE); + if (!target) + return NULL; av_base64_decode(target, p, *target_len); return target; } @@ -521,8 +523,10 @@ static PayloadContext * rdt_new_context (void) { PayloadContext *rdt = av_mallocz(sizeof(PayloadContext)); - - int ret = avformat_open_input(&rdt->rmctx, "", &ff_rdt_demuxer, NULL); + int ret; + if (!rdt) + return NULL; + ret = avformat_open_input(&rdt->rmctx, "", &ff_rdt_demuxer, NULL); if (ret < 0) { av_free(rdt); return NULL; diff --git a/libavformat/replaygain.c b/libavformat/replaygain.c new file mode 100644 index 000000000..8b8c81a0c --- /dev/null +++ b/libavformat/replaygain.c @@ -0,0 +1,125 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * replaygain tags parsing + */ + +#include +#include +#include + +#include "libavutil/avstring.h" +#include "libavutil/dict.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" +#include "libavutil/mem.h" +#include "libavutil/replaygain.h" + +#include "avformat.h" +#include "replaygain.h" + +static int32_t parse_value(const char *value, int32_t min) +{ + char *fraction; + int scale = 10000; + int32_t mb = 0; + int sign = 1; + int db; + + if (!value) + return min; + + value += strspn(value, " \t"); + + if (*value == '-') + sign = -1; + + db = strtol(value, &fraction, 0); + if (*fraction++ == '.') { + while (av_isdigit(*fraction) && scale) { + mb += scale * (*fraction - '0'); + scale /= 10; + fraction++; + } + } + + if (abs(db) > (INT32_MAX - mb) / 100000) + return min; + + return db * 100000 + sign * mb; +} + +int ff_replaygain_export_raw(AVStream *st, int32_t tg, uint32_t tp, + int32_t ag, uint32_t ap) +{ + AVPacketSideData *sd, *tmp; + AVReplayGain *replaygain; + int i; + + if (tg == INT32_MIN && ag == INT32_MIN) + return 0; + + for (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)); + 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; + replaygain->album_peak = ap; + + return 0; +} + +int ff_replaygain_export(AVStream *st, AVDictionary *metadata) +{ + const AVDictionaryEntry *tg, *tp, *ag, *ap; + + tg = av_dict_get(metadata, "REPLAYGAIN_TRACK_GAIN", NULL, 0); + tp = av_dict_get(metadata, "REPLAYGAIN_TRACK_PEAK", NULL, 0); + ag = av_dict_get(metadata, "REPLAYGAIN_ALBUM_GAIN", NULL, 0); + ap = av_dict_get(metadata, "REPLAYGAIN_ALBUM_PEAK", NULL, 0); + + return ff_replaygain_export_raw(st, + parse_value(tg ? tg->value : NULL, INT32_MIN), + parse_value(tp ? tp->value : NULL, 0), + parse_value(ag ? ag->value : NULL, INT32_MIN), + parse_value(ap ? ap->value : NULL, 0)); +} diff --git a/libavformat/replaygain.h b/libavformat/replaygain.h new file mode 100644 index 000000000..ceacb2142 --- /dev/null +++ b/libavformat/replaygain.h @@ -0,0 +1,38 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_REPLAYGAIN_H +#define AVFORMAT_REPLAYGAIN_H + +#include "libavutil/dict.h" + +#include "avformat.h" + +/** + * Parse replaygain tags and export them as per-stream side data. + */ +int ff_replaygain_export(AVStream *st, AVDictionary *metadata); + + +/** + * Export already decoded replaygain values as per-stream side data. + */ +int ff_replaygain_export_raw(AVStream *st, int32_t tg, uint32_t tp, + int32_t ag, uint32_t ap); + +#endif /* AVFORMAT_REPLAYGAIN_H */ diff --git a/libavformat/riff.c b/libavformat/riff.c index 2ad9c9f67..735dea0ea 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -39,7 +39,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_H264, MKTAG('S', 'M', 'V', '2') }, { AV_CODEC_ID_H264, MKTAG('V', 'S', 'S', 'H') }, { AV_CODEC_ID_H264, MKTAG('Q', '2', '6', '4') }, /* QNAP surveillance system */ - { AV_CODEC_ID_H264, MKTAG('V', '2', '6', '4') }, + { 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('I', 'N', 'M', 'C') }, @@ -258,6 +258,8 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_VP6A, MKTAG('V', 'P', '6', 'A') }, { AV_CODEC_ID_VP6F, MKTAG('V', 'P', '6', 'F') }, { AV_CODEC_ID_VP6F, MKTAG('F', 'L', 'V', '4') }, + { AV_CODEC_ID_VP7, MKTAG('V', 'P', '7', '0') }, + { AV_CODEC_ID_VP7, MKTAG('V', 'P', '7', '1') }, { AV_CODEC_ID_VP8, MKTAG('V', 'P', '8', '0') }, { AV_CODEC_ID_VP9, MKTAG('V', 'P', '9', '0') }, { AV_CODEC_ID_ASV1, MKTAG('A', 'S', 'V', '1') }, @@ -300,7 +302,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_LOCO, MKTAG('L', 'O', 'C', 'O') }, { AV_CODEC_ID_WNV1, MKTAG('W', 'N', 'V', '1') }, { AV_CODEC_ID_WNV1, MKTAG('Y', 'U', 'V', '8') }, - { AV_CODEC_ID_AASC, MKTAG('A', 'A', 'S', '4') }, + { AV_CODEC_ID_AASC, MKTAG('A', 'A', 'S', '4') }, /* Autodesk 24 bit RLE compressor */ { AV_CODEC_ID_AASC, MKTAG('A', 'A', 'S', 'C') }, { AV_CODEC_ID_INDEO2, MKTAG('R', 'T', '2', '1') }, { AV_CODEC_ID_FRAPS, MKTAG('F', 'P', 'S', '1') }, @@ -408,6 +410,8 @@ const AVCodecTag ff_codec_wav_tags[] = { { AV_CODEC_ID_ADPCM_G722, 0x028F }, { AV_CODEC_ID_IMC, 0x0401 }, { AV_CODEC_ID_IAC, 0x0402 }, + { AV_CODEC_ID_ON2AVC, 0x0500 }, + { AV_CODEC_ID_ON2AVC, 0x0501 }, { AV_CODEC_ID_GSM_MS, 0x1500 }, { AV_CODEC_ID_TRUESPEECH, 0x1501 }, /* ADTS AAC */ @@ -423,7 +427,7 @@ const AVCodecTag ff_codec_wav_tags[] = { { AV_CODEC_ID_AAC, 0x706d }, { AV_CODEC_ID_AAC, 0x4143 }, { AV_CODEC_ID_XAN_DPCM, 0x594a }, - { AV_CODEC_ID_G723_1, 0xA100 }, + { AV_CODEC_ID_G723_1, 0xA100 }, /* Comverse Infosys Ltd. G723 1 */ { AV_CODEC_ID_AAC, 0xA106 }, { AV_CODEC_ID_SPEEX, 0xA109 }, { AV_CODEC_ID_FLAC, 0xF1AC }, diff --git a/libavformat/riff.h b/libavformat/riff.h index dba38034e..88a77b07c 100644 --- a/libavformat/riff.h +++ b/libavformat/riff.h @@ -46,14 +46,28 @@ void ff_end_tag(AVIOContext *pb, int64_t start); int ff_get_bmp_header(AVIOContext *pb, AVStream *st, unsigned *esize); void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, const AVCodecTag *tags, int for_asf, int ignore_extradata); -int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc); + +/** + * Tell ff_put_wav_header() to use WAVEFORMATEX even for PCM codecs. + */ +#define FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX 0x00000001 + +/** + * Write WAVEFORMAT header structure. + * + * @param flags a combination of FF_PUT_WAV_HEADER_* constants + * + * @return the size or -1 on error + */ +int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags); + enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps); int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size); extern const AVCodecTag ff_codec_bmp_tags[]; // exposed through avformat_get_riff_video_tags() extern const AVCodecTag ff_codec_wav_tags[]; -void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssize, int *au_scale); +void ff_parse_specific_params(AVStream *st, int *au_rate, int *au_ssize, int *au_scale); int ff_read_riff_info(AVFormatContext *s, int64_t size); diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c index 2af2b7f9a..ef4d39903 100644 --- a/libavformat/riffenc.c +++ b/libavformat/riffenc.c @@ -31,7 +31,7 @@ int64_t ff_start_tag(AVIOContext *pb, const char *tag) { ffio_wfourcc(pb, tag); - avio_wl32(pb, 0); + avio_wl32(pb, -1); return avio_tell(pb); } @@ -51,10 +51,11 @@ 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(AVIOContext *pb, AVCodecContext *enc, int flags) { int bps, blkalign, bytespersec, frame_size; - int hdrsize = 18; + int hdrsize; + int64_t hdrstart = avio_tell(pb); int waveformatextensible; uint8_t temp[256]; uint8_t *riff_extradata = temp; @@ -66,7 +67,7 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) /* 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, 0); + frame_size = av_get_audio_frame_duration(enc, enc->block_align); if (!frame_size) frame_size = enc->frame_size; @@ -135,14 +136,12 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) avio_wl16(pb, blkalign); /* block align */ avio_wl16(pb, bps); /* bits per sample */ if (enc->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) { - hdrsize += 22; /* fwHeadLayer */ bytestream_put_le16(&riff_extradata, 2); /* dwHeadBitrate */ @@ -160,29 +159,27 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) /* dwPTSHigh */ bytestream_put_le32(&riff_extradata, 0); } else if (enc->codec_id == AV_CODEC_ID_G723_1) { - hdrsize += 20; bytestream_put_le32(&riff_extradata, 0x9ace0002); /* extradata needed for msacm g723.1 codec */ bytestream_put_le32(&riff_extradata, 0xaea2f732); bytestream_put_le16(&riff_extradata, 0xacde); } else if (enc->codec_id == AV_CODEC_ID_GSM_MS || enc->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; } /* write WAVEFORMATEXTENSIBLE extensions */ if (waveformatextensible) { - hdrsize += 22; + int write_channel_mask = enc->strict_std_compliance < FF_COMPLIANCE_NORMAL || + enc->channel_layout < 0x40000; /* 22 is WAVEFORMATEXTENSIBLE size */ avio_wl16(pb, riff_extradata - riff_extradata_start + 22); /* ValidBitsPerSample || SamplesPerBlock || Reserved */ avio_wl16(pb, bps); /* dwChannelMask */ - avio_wl32(pb, enc->channel_layout); + avio_wl32(pb, write_channel_mask ? enc->channel_layout : 0); /* GUID + next 3 */ if (enc->codec_id == AV_CODEC_ID_EAC3) { ff_put_guid(pb, get_codec_guid(enc->codec_id, ff_codec_wav_guids)); @@ -192,10 +189,14 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) avio_wl32(pb, 0xAA000080); avio_wl32(pb, 0x719B3800); } - } else { + } else if ((flags & FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX) || + enc->codec_tag != 0x0001 /* PCM */ || + riff_extradata - riff_extradata_start) { + /* WAVEFORMATEX */ avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */ - } + } /* else PCMWAVEFORMAT */ avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start); + hdrsize = avio_tell(pb) - hdrstart; if (hdrsize & 1) { hdrsize++; avio_w8(pb, 0); @@ -233,32 +234,33 @@ void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, } } -void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, +void ff_parse_specific_params(AVStream *st, int *au_rate, int *au_ssize, int *au_scale) { + AVCodecContext *codec = st->codec; 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(stream, 0); + audio_frame_size = av_get_audio_frame_duration(codec, 0); if (!audio_frame_size) - audio_frame_size = stream->frame_size; + audio_frame_size = codec->frame_size; - *au_ssize = stream->block_align; - if (audio_frame_size && stream->sample_rate) { + *au_ssize = codec->block_align; + if (audio_frame_size && codec->sample_rate) { *au_scale = audio_frame_size; - *au_rate = stream->sample_rate; - } else if (stream->codec_type == AVMEDIA_TYPE_VIDEO || - stream->codec_type == AVMEDIA_TYPE_DATA || - stream->codec_type == AVMEDIA_TYPE_SUBTITLE) { - *au_scale = stream->time_base.num; - *au_rate = stream->time_base.den; + *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_scale = st->time_base.num; + *au_rate = st->time_base.den; } else { - *au_scale = stream->block_align ? stream->block_align * 8 : 8; - *au_rate = stream->bit_rate ? stream->bit_rate : - 8 * stream->sample_rate; + *au_scale = codec->block_align ? codec->block_align * 8 : 8; + *au_rate = codec->bit_rate ? codec->bit_rate : + 8 * codec->sample_rate; } gcd = av_gcd(*au_scale, *au_rate); *au_scale /= gcd; diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index b62f8e062..36764ee9b 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" @@ -252,8 +254,6 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, return ret; } break; - default: - av_strlcpy(st->codec->codec_name, buf, sizeof(st->codec->codec_name)); } switch (ast->deint_id) { case DEINT_ID_INT4: @@ -279,7 +279,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, case DEINT_ID_VBRF: break; default: - av_log(s, AV_LOG_ERROR, "Unknown interleaver %X\n", ast->deint_id); + av_log(s, AV_LOG_ERROR ,"Unknown interleaver %"PRIX32"\n", ast->deint_id); return AVERROR_INVALIDDATA; } if (ast->deint_id == DEINT_ID_INT4 || diff --git a/libavformat/rmenc.c b/libavformat/rmenc.c index 17192ff27..2e50ed338 100644 --- a/libavformat/rmenc.c +++ b/libavformat/rmenc.c @@ -315,6 +315,8 @@ static int rm_write_header(AVFormatContext *s) } for(n=0;nnb_streams;n++) { + AVStream *st = s->streams[n]; + s->streams[n]->id = n; codec = s->streams[n]->codec; stream = &rm->streams[n]; @@ -334,7 +336,8 @@ static int rm_write_header(AVFormatContext *s) break; case AVMEDIA_TYPE_VIDEO: rm->video_stream = stream; - stream->frame_rate = (float)codec->time_base.den / (float)codec->time_base.num; + // TODO: should be avg_frame_rate + stream->frame_rate = (float)st->time_base.den / (float)st->time_base.num; /* XXX: dummy values */ stream->packet_max_size = 4096; stream->nb_packets = 0; diff --git a/libavformat/rpl.c b/libavformat/rpl.c index fb60379d3..46a579641 100644 --- a/libavformat/rpl.c +++ b/libavformat/rpl.c @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +#include #include #include "libavutil/avstring.h" @@ -222,7 +222,8 @@ static int rpl_read_header(AVFormatContext *s) break; } if (ast->codec->codec_id == AV_CODEC_ID_NONE) - avpriv_request_sample(s, "Audio format %i", audio_format); + avpriv_request_sample(s, "Audio format %"PRId32, + audio_format); avpriv_set_pts_info(ast, 32, 1, ast->codec->bit_rate); } else { for (i = 0; i < 3; i++) diff --git a/libavformat/rsoenc.c b/libavformat/rsoenc.c index ee679b68f..6da9594fc 100644 --- a/libavformat/rsoenc.c +++ b/libavformat/rsoenc.c @@ -108,4 +108,5 @@ AVOutputFormat ff_rso_muxer = { .write_packet = rso_write_packet, .write_trailer = rso_write_trailer, .codec_tag = (const AVCodecTag* const []){ff_codec_rso_tags, 0}, + .flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/rtmppkt.c b/libavformat/rtmppkt.c index f99540cd5..92172dc36 100644 --- a/libavformat/rtmppkt.c +++ b/libavformat/rtmppkt.c @@ -102,13 +102,11 @@ int ff_amf_read_number(GetByteContext *bc, double *val) return 0; } -int ff_amf_read_string(GetByteContext *bc, uint8_t *str, - int strsize, int *length) +int ff_amf_get_string(GetByteContext *bc, uint8_t *str, + int strsize, int *length) { int stringlen = 0; int readsize; - if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_STRING) - return AVERROR_INVALIDDATA; stringlen = bytestream2_get_be16(bc); if (stringlen + 1 > strsize) return AVERROR(EINVAL); @@ -122,6 +120,14 @@ int ff_amf_read_string(GetByteContext *bc, uint8_t *str, return 0; } +int ff_amf_read_string(GetByteContext *bc, uint8_t *str, + int strsize, int *length) +{ + if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_STRING) + return AVERROR_INVALIDDATA; + return ff_amf_get_string(bc, str, strsize, length); +} + int ff_amf_read_null(GetByteContext *bc) { if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_NULL) @@ -169,6 +175,7 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p, uint8_t buf[16]; int channel_id, timestamp, size; + uint32_t ts_field; // non-extended timestamp or delta field uint32_t extra = 0; enum RTMPPacketType type; int written = 0; @@ -193,14 +200,14 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p, type = prev_pkt[channel_id].type; extra = prev_pkt[channel_id].extra; - hdr >>= 6; + hdr >>= 6; // header size indicator if (hdr == RTMP_PS_ONEBYTE) { - timestamp = prev_pkt[channel_id].ts_delta; + ts_field = prev_pkt[channel_id].ts_field; } else { if (ffurl_read_complete(h, buf, 3) != 3) return AVERROR(EIO); written += 3; - timestamp = AV_RB24(buf); + ts_field = AV_RB24(buf); if (hdr != RTMP_PS_FOURBYTES) { if (ffurl_read_complete(h, buf, 3) != 3) return AVERROR(EIO); @@ -217,11 +224,13 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p, extra = AV_RL32(buf); } } - if (timestamp == 0xFFFFFF) { - if (ffurl_read_complete(h, buf, 4) != 4) - return AVERROR(EIO); - timestamp = AV_RB32(buf); - } + } + if (ts_field == 0xFFFFFF) { + if (ffurl_read_complete(h, buf, 4) != 4) + return AVERROR(EIO); + timestamp = AV_RB32(buf); + } else { + timestamp = ts_field; } if (hdr != RTMP_PS_TWELVEBYTES) timestamp += prev_pkt[channel_id].timestamp; @@ -232,8 +241,7 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p, return ret; p->read = written; p->offset = 0; - prev_pkt[channel_id].ts_delta = timestamp - - prev_pkt[channel_id].timestamp; + prev_pkt[channel_id].ts_field = ts_field; prev_pkt[channel_id].timestamp = timestamp; } else { // previous packet in this channel hasn't completed reading @@ -242,7 +250,7 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p, p->size = prev->size; p->channel_id = prev->channel_id; p->type = prev->type; - p->ts_delta = prev->ts_delta; + p->ts_field = prev->ts_field; p->extra = prev->extra; p->offset = prev->offset; p->read = prev->read + written; @@ -271,6 +279,7 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p, prev->data = p->data; prev->read = p->read; prev->offset = p->offset; + p->data = NULL; return AVERROR(EAGAIN); } @@ -303,22 +312,34 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, int written = 0; int ret; RTMPPacket *prev_pkt; + int use_delta; // flag if using timestamp delta, not RTMP_PS_TWELVEBYTES + uint32_t timestamp; // full 32-bit timestamp or delta value if ((ret = ff_rtmp_check_alloc_array(prev_pkt_ptr, nb_prev_pkt, pkt->channel_id)) < 0) return ret; prev_pkt = *prev_pkt_ptr; - pkt->ts_delta = pkt->timestamp - prev_pkt[pkt->channel_id].timestamp; - //if channel_id = 0, this is first presentation of prev_pkt, send full hdr. - if (prev_pkt[pkt->channel_id].channel_id && + use_delta = prev_pkt[pkt->channel_id].channel_id && pkt->extra == prev_pkt[pkt->channel_id].extra && - pkt->timestamp >= prev_pkt[pkt->channel_id].timestamp) { + pkt->timestamp >= prev_pkt[pkt->channel_id].timestamp; + + timestamp = pkt->timestamp; + if (use_delta) { + timestamp -= prev_pkt[pkt->channel_id].timestamp; + } + if (timestamp >= 0xFFFFFF) { + pkt->ts_field = 0xFFFFFF; + } else { + pkt->ts_field = timestamp; + } + + if (use_delta) { if (pkt->type == prev_pkt[pkt->channel_id].type && pkt->size == prev_pkt[pkt->channel_id].size) { mode = RTMP_PS_FOURBYTES; - if (pkt->ts_delta == prev_pkt[pkt->channel_id].ts_delta) + if (pkt->ts_field == prev_pkt[pkt->channel_id].ts_field) mode = RTMP_PS_ONEBYTE; } else { mode = RTMP_PS_EIGHTBYTES; @@ -335,29 +356,22 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, bytestream_put_le16(&p, pkt->channel_id - 64); } if (mode != RTMP_PS_ONEBYTE) { - uint32_t timestamp = pkt->timestamp; - if (mode != RTMP_PS_TWELVEBYTES) - timestamp = pkt->ts_delta; - bytestream_put_be24(&p, timestamp >= 0xFFFFFF ? 0xFFFFFF : timestamp); + bytestream_put_be24(&p, pkt->ts_field); if (mode != RTMP_PS_FOURBYTES) { bytestream_put_be24(&p, pkt->size); bytestream_put_byte(&p, pkt->type); if (mode == RTMP_PS_TWELVEBYTES) bytestream_put_le32(&p, pkt->extra); } - if (timestamp >= 0xFFFFFF) - bytestream_put_be32(&p, timestamp); } + if (pkt->ts_field == 0xFFFFFF) + bytestream_put_be32(&p, timestamp); // save history prev_pkt[pkt->channel_id].channel_id = pkt->channel_id; prev_pkt[pkt->channel_id].type = pkt->type; prev_pkt[pkt->channel_id].size = pkt->size; prev_pkt[pkt->channel_id].timestamp = pkt->timestamp; - if (mode != RTMP_PS_TWELVEBYTES) { - prev_pkt[pkt->channel_id].ts_delta = pkt->ts_delta; - } else { - prev_pkt[pkt->channel_id].ts_delta = pkt->timestamp; - } + prev_pkt[pkt->channel_id].ts_field = pkt->ts_field; prev_pkt[pkt->channel_id].extra = pkt->extra; if ((ret = ffurl_write(h, pkt_hdr, p - pkt_hdr)) < 0) @@ -391,7 +405,7 @@ int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type, pkt->type = type; pkt->timestamp = timestamp; pkt->extra = 0; - pkt->ts_delta = 0; + pkt->ts_field = 0; return 0; } diff --git a/libavformat/rtmppkt.h b/libavformat/rtmppkt.h index fb79fedac..a082b45f9 100644 --- a/libavformat/rtmppkt.h +++ b/libavformat/rtmppkt.h @@ -78,7 +78,7 @@ typedef struct RTMPPacket { int channel_id; ///< RTMP channel ID (nothing to do with audio/video channels though) RTMPPacketType type; ///< packet payload type uint32_t timestamp; ///< packet full timestamp - uint32_t ts_delta; ///< timestamp increment to the previous one in milliseconds (latter only for media packets) + uint32_t ts_field; ///< 24-bit timestamp or increment to the previous one, in milliseconds (latter only for media packets). Clipped to a maximum of 0xFFFFFF, indicating an extended timestamp field. uint32_t extra; ///< probably an additional channel ID used during streaming data uint8_t *data; ///< packet payload int size; ///< packet payload size @@ -277,6 +277,23 @@ int ff_amf_read_bool(GetByteContext *gbc, int *val); */ int ff_amf_read_number(GetByteContext *gbc, double *val); +/** + * Get AMF string value. + * + * This function behaves the same as ff_amf_read_string except that + * it does not expect the AMF type prepended to the actual data. + * Appends a trailing null byte to output string in order to + * ease later parsing. + * + *@param[in,out] gbc GetByteContext initialized with AMF-formatted data + *@param[out] str read string + *@param[in] strsize buffer size available to store the read string + *@param[out] length read string length + *@return 0 on success or an AVERROR code on failure +*/ +int ff_amf_get_string(GetByteContext *bc, uint8_t *str, + int strsize, int *length); + /** * Read AMF string value. * diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 26c4d8e0b..3814da8c5 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -97,6 +97,9 @@ typedef struct RTMPContext { uint32_t bytes_read; ///< number of bytes read from server uint32_t last_bytes_read; ///< number of bytes read last reported to server 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 + int received_metadata; ///< Indicates if we have received metadata about the streams uint8_t flv_header[RTMP_HEADER]; ///< partial incoming flv packet header int flv_header_bytes; ///< number of initialized bytes in flv_header int nb_invokes; ///< keeps track of invoke messages @@ -1712,18 +1715,23 @@ static int handle_connect_error(URLContext *s, const char *desc) char *value = strchr(ptr, '='); if (next) *next++ = '\0'; - if (value) + if (value) { *value++ = '\0'; - if (!strcmp(ptr, "user")) { - user = value; - } else if (!strcmp(ptr, "salt")) { - salt = value; - } else if (!strcmp(ptr, "opaque")) { - opaque = value; - } else if (!strcmp(ptr, "challenge")) { - challenge = value; - } else if (!strcmp(ptr, "nonce")) { - nonce = value; + if (!strcmp(ptr, "user")) { + user = value; + } else if (!strcmp(ptr, "salt")) { + salt = value; + } else if (!strcmp(ptr, "opaque")) { + opaque = value; + } else if (!strcmp(ptr, "challenge")) { + challenge = value; + } else if (!strcmp(ptr, "nonce")) { + nonce = value; + } else { + av_log(s, AV_LOG_INFO, "Ignoring unsupported var %s\n", ptr); + } + } else { + av_log(s, AV_LOG_WARNING, "Variable %s has NULL value\n", ptr); } ptr = next; } @@ -2107,6 +2115,12 @@ static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip) const int size = pkt->size - skip; uint32_t ts = pkt->timestamp; + if (pkt->type == RTMP_PT_AUDIO) { + rt->has_audio = 1; + } else if (pkt->type == RTMP_PT_VIDEO) { + rt->has_video = 1; + } + old_flv_size = update_offset(rt, size + 15); if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) { @@ -2139,6 +2153,38 @@ static int handle_notify(URLContext *s, RTMPPacket *pkt) &stringlen)) return AVERROR_INVALIDDATA; + if (!strcmp(commandbuffer, "onMetaData")) { + // metadata properties should be stored in a mixed array + if (bytestream2_get_byte(&gbc) == AMF_DATA_TYPE_MIXEDARRAY) { + // We have found a metaData Array so flv can determine the streams + // from this. + rt->received_metadata = 1; + // skip 32-bit max array index + bytestream2_skip(&gbc, 4); + while (bytestream2_get_bytes_left(&gbc) > 3) { + if (ff_amf_get_string(&gbc, statusmsg, sizeof(statusmsg), + &stringlen)) + return AVERROR_INVALIDDATA; + // We do not care about the content of the property (yet). + stringlen = ff_amf_tag_size(gbc.buffer, gbc.buffer_end); + if (stringlen < 0) + return AVERROR_INVALIDDATA; + bytestream2_skip(&gbc, stringlen); + + // The presence of the following properties indicates that the + // respective streams are present. + if (!strcmp(statusmsg, "videocodecid")) { + rt->has_video = 1; + } + if (!strcmp(statusmsg, "audiocodecid")) { + rt->has_audio = 1; + } + } + if (bytestream2_get_be24(&gbc) != AMF_END_OF_OBJECT) + return AVERROR_INVALIDDATA; + } + } + // Skip the @setDataFrame string and validate it is a notification if (!strcmp(commandbuffer, "@setDataFrame")) { skip = gbc.buffer - pkt->data; @@ -2380,7 +2426,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) { RTMPContext *rt = s->priv_data; char proto[8], hostname[256], path[1024], auth[100], *fname; - char *old_app; + char *old_app, *qmark, fname_buffer[1024]; uint8_t buf[2048]; int port; AVDictionary *opts = NULL; @@ -2478,7 +2524,20 @@ reconnect: } //extract "app" part from path - if (!strncmp(path, "/ondemand/", 10)) { + 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)); + fname = strstr(path, "slist=") + 6; + // Strip any further query parameters from fname + amp = strchr(fname, '&'); + if (amp) { + av_strlcpy(fname_buffer, fname, FFMIN(amp - fname + 1, + sizeof(fname_buffer))); + fname = fname_buffer; + } + } else if (!strncmp(path, "/ondemand/", 10)) { fname = path + 10; memcpy(rt->app, "ondemand", 9); } else { @@ -2560,6 +2619,9 @@ reconnect: rt->client_report_size = 1048576; rt->bytes_read = 0; + rt->has_audio = 0; + rt->has_video = 0; + rt->received_metadata = 0; rt->last_bytes_read = 0; rt->server_bw = 2500000; @@ -2599,7 +2661,27 @@ reconnect: if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) return err; rt->flv_off = 0; - memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size); + memcpy(rt->flv_data, "FLV\1\0\0\0\0\011\0\0\0\0", rt->flv_size); + + // Read packets until we reach the first A/V packet or read metadata. + // If there was a metadata package in front of the A/V packets, we can + // build the FLV header from this. If we do not receive any metadata, + // the FLV decoder will allocate the needed streams when their first + // audio or video packet arrives. + while (!rt->has_audio && !rt->has_video && !rt->received_metadata) { + if ((ret = get_packet(s, 0)) < 0) + return ret; + } + + // Either after we have read the metadata or (if there is none) the + // first packet of an A/V stream, we have a better knowledge about the + // streams, so set the FLV header accordingly. + if (rt->has_audio) { + rt->flv_data[4] |= FLV_HEADER_FLAG_HASAUDIO; + } + if (rt->has_video) { + rt->flv_data[4] |= FLV_HEADER_FLAG_HASVIDEO; + } } else { rt->flv_size = 0; rt->flv_data = NULL; diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index ed118b048..64a1c27f8 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -833,8 +833,10 @@ void ff_rtp_parse_close(RTPDemuxContext *s) av_free(s); } -int ff_parse_fmtp(AVStream *stream, PayloadContext *data, const char *p, - int (*parse_fmtp)(AVStream *stream, +int ff_parse_fmtp(AVFormatContext *s, + AVStream *stream, PayloadContext *data, const char *p, + int (*parse_fmtp)(AVFormatContext *s, + AVStream *stream, PayloadContext *data, char *attr, char *value)) { @@ -859,7 +861,7 @@ int ff_parse_fmtp(AVStream *stream, PayloadContext *data, const char *p, while (ff_rtsp_next_attr_and_value(&p, attr, sizeof(attr), value, value_size)) { - res = parse_fmtp(stream, data, attr, value); + res = parse_fmtp(s, stream, data, attr, value); if (res < 0 && res != AVERROR_PATCHWELCOME) { av_free(value); return res; diff --git a/libavformat/rtpdec.h b/libavformat/rtpdec.h index 9321066ba..7b41cc4b5 100644 --- a/libavformat/rtpdec.h +++ b/libavformat/rtpdec.h @@ -173,9 +173,9 @@ struct RTPDemuxContext { /*@}*/ /* rtcp sender statistics receive */ - int64_t last_rtcp_ntp_time; + uint64_t last_rtcp_ntp_time; int64_t last_rtcp_reception_time; - int64_t first_rtcp_ntp_time; + uint64_t first_rtcp_ntp_time; uint32_t last_rtcp_timestamp; int64_t rtcp_ts_offset; @@ -200,8 +200,10 @@ RTPDynamicProtocolHandler *ff_rtp_handler_find_by_id(int id, int ff_rtsp_next_attr_and_value(const char **p, char *attr, int attr_size, char *value, int value_size); -int ff_parse_fmtp(AVStream *stream, PayloadContext *data, const char *p, - int (*parse_fmtp)(AVStream *stream, +int ff_parse_fmtp(AVFormatContext *s, + AVStream *stream, PayloadContext *data, const char *p, + int (*parse_fmtp)(AVFormatContext *s, + AVStream *stream, PayloadContext *data, char *attr, char *value)); diff --git a/libavformat/rtpdec_amr.c b/libavformat/rtpdec_amr.c index 211cf1798..31acfe7ed 100644 --- a/libavformat/rtpdec_amr.c +++ b/libavformat/rtpdec_amr.c @@ -139,7 +139,8 @@ static int amr_handle_packet(AVFormatContext *ctx, PayloadContext *data, return 0; } -static int amr_parse_fmtp(AVStream *stream, PayloadContext *data, +static int amr_parse_fmtp(AVFormatContext *s, + AVStream *stream, PayloadContext *data, char *attr, char *value) { /* Some AMR SDP configurations contain "octet-align", without @@ -147,8 +148,8 @@ static int amr_parse_fmtp(AVStream *stream, PayloadContext *data, * interpret it as "1". */ if (!strcmp(value, "")) { - av_log(NULL, AV_LOG_WARNING, "AMR fmtp attribute %s had " - "nonstandard empty value\n", attr); + av_log(s, AV_LOG_WARNING, "AMR fmtp attribute %s had " + "nonstandard empty value\n", attr); strcpy(value, "1"); } if (!strcmp(attr, "octet-align")) @@ -177,7 +178,7 @@ static int amr_parse_sdp_line(AVFormatContext *s, int st_index, * separated key/value pairs. */ if (av_strstart(line, "fmtp:", &p)) { - ret = ff_parse_fmtp(s->streams[st_index], data, p, amr_parse_fmtp); + ret = ff_parse_fmtp(s, s->streams[st_index], data, p, amr_parse_fmtp); if (!data->octet_align || data->crc || data->interleaving || data->channels != 1) { av_log(s, AV_LOG_ERROR, "Unsupported RTP/AMR configuration!\n"); diff --git a/libavformat/rtpdec_h264.c b/libavformat/rtpdec_h264.c index 1ca78bc81..51704aaf7 100644 --- a/libavformat/rtpdec_h264.c +++ b/libavformat/rtpdec_h264.c @@ -64,7 +64,8 @@ struct PayloadContext { static const uint8_t start_sequence[] = { 0, 0, 0, 1 }; -static int sdp_parse_fmtp_config_h264(AVStream *stream, +static int sdp_parse_fmtp_config_h264(AVFormatContext *s, + AVStream *stream, PayloadContext *h264_data, char *attr, char *value) { @@ -73,7 +74,7 @@ static int sdp_parse_fmtp_config_h264(AVStream *stream, assert(h264_data != NULL); if (!strcmp(attr, "packetization-mode")) { - av_log(codec, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value)); + av_log(s, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value)); h264_data->packetization_mode = atoi(value); /* * Packetization Mode: @@ -83,7 +84,7 @@ static int sdp_parse_fmtp_config_h264(AVStream *stream, * and 29 (FU-B) are allowed. */ if (h264_data->packetization_mode > 1) - av_log(codec, AV_LOG_ERROR, + 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) { @@ -104,7 +105,7 @@ static int sdp_parse_fmtp_config_h264(AVStream *stream, buffer[1] = value[5]; level_idc = strtol(buffer, NULL, 16); - av_log(codec, AV_LOG_DEBUG, + 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; @@ -137,7 +138,7 @@ static int sdp_parse_fmtp_config_h264(AVStream *stream, codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); if (!dest) { - av_log(codec, AV_LOG_ERROR, + av_log(s, AV_LOG_ERROR, "Unable to allocate memory for extradata!\n"); return AVERROR(ENOMEM); } @@ -157,7 +158,7 @@ static int sdp_parse_fmtp_config_h264(AVStream *stream, codec->extradata_size += sizeof(start_sequence) + packet_size; } } - av_log(codec, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!\n", + av_log(s, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!\n", codec->extradata, codec->extradata_size); } return 0; @@ -385,7 +386,7 @@ static int parse_h264_sdp_line(AVFormatContext *s, int st_index, codec->width = atoi(buf1); codec->height = atoi(p + 1); // skip the - } else if (av_strstart(p, "fmtp:", &p)) { - return ff_parse_fmtp(stream, h264_data, p, sdp_parse_fmtp_config_h264); + return ff_parse_fmtp(s, stream, h264_data, p, sdp_parse_fmtp_config_h264); } else if (av_strstart(p, "cliprect:", &p)) { // could use this if we wanted. } diff --git a/libavformat/rtpdec_ilbc.c b/libavformat/rtpdec_ilbc.c index 2bd86147d..aa1579fa6 100644 --- a/libavformat/rtpdec_ilbc.c +++ b/libavformat/rtpdec_ilbc.c @@ -23,7 +23,8 @@ #include "rtpdec_formats.h" #include "libavutil/avstring.h" -static int ilbc_parse_fmtp(AVStream *stream, PayloadContext *data, +static int ilbc_parse_fmtp(AVFormatContext *s, + AVStream *stream, PayloadContext *data, char *attr, char *value) { if (!strcmp(attr, "mode")) { @@ -36,7 +37,7 @@ static int ilbc_parse_fmtp(AVStream *stream, PayloadContext *data, stream->codec->block_align = 50; break; default: - av_log(NULL, AV_LOG_ERROR, "Unsupported iLBC mode %d\n", mode); + av_log(s, AV_LOG_ERROR, "Unsupported iLBC mode %d\n", mode); return AVERROR(EINVAL); } } @@ -54,7 +55,7 @@ static int ilbc_parse_sdp_line(AVFormatContext *s, int st_index, st = s->streams[st_index]; if (av_strstart(line, "fmtp:", &p)) { - int ret = ff_parse_fmtp(st, data, p, ilbc_parse_fmtp); + int ret = ff_parse_fmtp(s, st, data, p, ilbc_parse_fmtp); if (ret < 0) return ret; if (!st->codec->block_align) { diff --git a/libavformat/rtpdec_latm.c b/libavformat/rtpdec_latm.c index fdeff3a15..389648253 100644 --- a/libavformat/rtpdec_latm.c +++ b/libavformat/rtpdec_latm.c @@ -142,7 +142,8 @@ end: return ret; } -static int parse_fmtp(AVStream *stream, PayloadContext *data, +static int parse_fmtp(AVFormatContext *s, + AVStream *stream, PayloadContext *data, char *attr, char *value) { int res; @@ -154,7 +155,7 @@ static int parse_fmtp(AVStream *stream, PayloadContext *data, } else if (!strcmp(attr, "cpresent")) { int cpresent = atoi(value); if (cpresent != 0) - avpriv_request_sample(NULL, + avpriv_request_sample(s, "RTP MP4A-LATM with in-band configuration"); } @@ -170,7 +171,7 @@ static int latm_parse_sdp_line(AVFormatContext *s, int st_index, return 0; if (av_strstart(line, "fmtp:", &p)) - return ff_parse_fmtp(s->streams[st_index], data, p, parse_fmtp); + return ff_parse_fmtp(s, s->streams[st_index], data, p, parse_fmtp); return 0; } diff --git a/libavformat/rtpdec_mpeg4.c b/libavformat/rtpdec_mpeg4.c index 0ea5594c0..53921f2e9 100644 --- a/libavformat/rtpdec_mpeg4.c +++ b/libavformat/rtpdec_mpeg4.c @@ -208,7 +208,8 @@ static int aac_parse_packet(AVFormatContext *ctx, PayloadContext *data, return 0; } -static int parse_fmtp(AVStream *stream, PayloadContext *data, +static int parse_fmtp(AVFormatContext *s, + AVStream *stream, PayloadContext *data, char *attr, char *value) { AVCodecContext *codec = stream->codec; @@ -246,7 +247,7 @@ static int parse_sdp_line(AVFormatContext *s, int st_index, return 0; if (av_strstart(line, "fmtp:", &p)) - return ff_parse_fmtp(s->streams[st_index], data, p, parse_fmtp); + return ff_parse_fmtp(s, s->streams[st_index], data, p, parse_fmtp); return 0; } diff --git a/libavformat/rtpdec_xiph.c b/libavformat/rtpdec_xiph.c index 887a65ed6..dc34f9e22 100644 --- a/libavformat/rtpdec_xiph.c +++ b/libavformat/rtpdec_xiph.c @@ -256,7 +256,7 @@ parse_packed_headers(const uint8_t * packed_headers, if (packed_headers_end - packed_headers < 9) { av_log(codec, AV_LOG_ERROR, - "Invalid %td byte packed header.", + "Invalid %"PTRDIFF_SPECIFIER" byte packed header.", packed_headers_end - packed_headers); return AVERROR_INVALIDDATA; } @@ -278,7 +278,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, - "Bad packed header lengths (%d,%d,%td,%d)\n", length1, + "Bad packed header lengths (%d,%d,%"PTRDIFF_SPECIFIER",%d)\n", length1, length2, packed_headers_end - packed_headers, length); return AVERROR_INVALIDDATA; } @@ -306,7 +306,8 @@ parse_packed_headers(const uint8_t * packed_headers, return 0; } -static int xiph_parse_fmtp_pair(AVStream* stream, +static int xiph_parse_fmtp_pair(AVFormatContext *s, + AVStream* stream, PayloadContext *xiph_data, char *attr, char *value) { @@ -321,7 +322,7 @@ static int xiph_parse_fmtp_pair(AVStream* stream, } else if (!strcmp(value, "YCbCr-4:4:4")) { codec->pix_fmt = AV_PIX_FMT_YUV444P; } else { - av_log(codec, AV_LOG_ERROR, + av_log(s, AV_LOG_ERROR, "Unsupported pixel format %s\n", attr); return AVERROR_INVALIDDATA; } @@ -360,12 +361,12 @@ static int xiph_parse_fmtp_pair(AVStream* stream, (decoded_packet, decoded_packet + packet_size, codec, xiph_data); } else { - av_log(codec, AV_LOG_ERROR, + av_log(s, AV_LOG_ERROR, "Out of memory while decoding SDP configuration.\n"); result = AVERROR(ENOMEM); } } else { - av_log(codec, AV_LOG_ERROR, "Packet too large\n"); + av_log(s, AV_LOG_ERROR, "Packet too large\n"); result = AVERROR_INVALIDDATA; } av_free(decoded_packet); @@ -382,7 +383,7 @@ static int xiph_parse_sdp_line(AVFormatContext *s, int st_index, return 0; if (av_strstart(line, "fmtp:", &p)) { - return ff_parse_fmtp(s->streams[st_index], data, p, + return ff_parse_fmtp(s, s->streams[st_index], data, p, xiph_parse_fmtp_pair); } diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index f0100083b..e7527c774 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -119,7 +119,7 @@ static int rtp_write_header(AVFormatContext *s1) s->ssrc = av_get_random_seed(); s->first_packet = 1; s->first_rtcp_ntp_time = ff_ntp_time(); - if (s1->start_time_realtime) + if (s1->start_time_realtime != 0 && s1->start_time_realtime != AV_NOPTS_VALUE) /* Round the NTP time to whole milliseconds. */ s->first_rtcp_ntp_time = (s1->start_time_realtime / 1000) * 1000 + NTP_OFFSET_US; @@ -127,7 +127,7 @@ static int rtp_write_header(AVFormatContext *s1) // available range, so that any wraparound doesn't happen immediately. // (Immediate wraparound would be an issue for SRTP.) if (s->seq < 0) { - if (st->codec->flags & CODEC_FLAG_BITEXACT) { + if (s1->flags & AVFMT_FLAG_BITEXACT) { s->seq = 0; } else s->seq = av_get_random_seed() & 0x0fff; @@ -168,7 +168,12 @@ static int rtp_write_header(AVFormatContext *s1) } if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { /* FIXME: We should round down here... */ - s->max_frames_per_packet = av_rescale_q(s1->max_delay, (AVRational){1, 1000000}, st->codec->time_base); + 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; } } diff --git a/libavformat/rtpenc_jpeg.c b/libavformat/rtpenc_jpeg.c index 7eb0e23c6..c35332953 100644 --- a/libavformat/rtpenc_jpeg.c +++ b/libavformat/rtpenc_jpeg.c @@ -29,7 +29,7 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) RTPMuxContext *s = s1->priv_data; const uint8_t *qtables = NULL; int nb_qtables = 0; - uint8_t type = 1; /* default pixel format is AV_PIX_FMT_YUVJ420P */ + uint8_t type; uint8_t w, h; uint8_t *p; int off = 0; /* fragment offset of the current JPEG frame */ @@ -43,10 +43,14 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) w = s1->streams[0]->codec->width >> 3; h = s1->streams[0]->codec->height >> 3; - /* check if pixel format is not the normal 420 case */ - if (s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUVJ422P) { + /* 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)) { type = 0; - } else if (s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUVJ420P) { + } 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)) { type = 1; } else { av_log(s1, AV_LOG_ERROR, "Unsupported pixel format\n"); diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 82ae3bd3e..5212dde6b 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -86,11 +86,12 @@ const AVOption ff_rtsp_options[] = { { "http", "HTTP tunneling", 0, AV_OPT_TYPE_CONST, {.i64 = (1 << RTSP_LOWER_TRANSPORT_HTTP)}, 0, 0, DEC, "rtsp_transport" }, RTSP_FLAG_OPTS("rtsp_flags", "set RTSP flags"), { "listen", "wait for incoming connections", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_LISTEN}, 0, 0, DEC, "rtsp_flags" }, + { "prefer_tcp", "try RTP via TCP first, if available", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_PREFER_TCP}, 0, 0, DEC|ENC, "rtsp_flags" }, RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"), { "min_port", "set minimum local UDP port", OFFSET(rtp_port_min), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MIN}, 0, 65535, DEC|ENC }, { "max_port", "set maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC }, { "timeout", "set maximum timeout (in seconds) to wait for incoming connections (-1 is infinite, imply flag listen)", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC }, - { "stimeout", "set timeout (in micro seconds) of socket TCP I/O operations", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, + { "stimeout", "set timeout (in microseconds) of socket TCP I/O operations", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, RTSP_REORDERING_OPTS(), { "user-agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC }, { NULL }, @@ -295,6 +296,9 @@ typedef struct SDPParseState { struct RTSPSource **default_include_source_addrs; /**< Source-specific multicast include source IP address (from SDP content) */ int nb_default_exclude_source_addrs; /**< Number of source-specific multicast exclude source IP address (from SDP content) */ struct RTSPSource **default_exclude_source_addrs; /**< Source-specific multicast exclude source IP address (from SDP content) */ + int seen_rtpmap; + int seen_fmtp; + char delayed_fmtp[2048]; } SDPParseState; static void copy_default_source_addrs(struct RTSPSource **addrs, int count, @@ -312,6 +316,22 @@ static void copy_default_source_addrs(struct RTSPSource **addrs, int count, } } +static void parse_fmtp(AVFormatContext *s, RTSPState *rt, + int payload_type, const char *line) +{ + int i; + + for (i = 0; i < rt->nb_rtsp_streams; i++) { + RTSPStream *rtsp_st = rt->rtsp_streams[i]; + if (rtsp_st->sdp_payload_type == payload_type && + 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); + } + } +} + static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, int letter, const char *buf) { @@ -319,7 +339,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, char buf1[64], st_type[64]; const char *p; enum AVMediaType codec_type; - int payload_type, i; + int payload_type; AVStream *st; RTSPStream *rtsp_st; RTSPSource *rtsp_src; @@ -368,7 +388,9 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, break; case 'm': /* new stream */ - s1->skip_media = 0; + s1->skip_media = 0; + s1->seen_fmtp = 0; + s1->seen_rtpmap = 0; codec_type = AVMEDIA_TYPE_UNKNOWN; get_word(st_type, sizeof(st_type), &p); if (!strcmp(st_type, "audio")) { @@ -491,19 +513,20 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, st = s->streams[rtsp_st->stream_index]; sdp_parse_rtpmap(s, st, rtsp_st, payload_type, p); } + s1->seen_rtpmap = 1; + if (s1->seen_fmtp) { + parse_fmtp(s, rt, payload_type, s1->delayed_fmtp); + } } else if (av_strstart(p, "fmtp:", &p) || av_strstart(p, "framesize:", &p)) { - /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */ // let dynamic protocol handlers have a stab at the line. get_word(buf1, sizeof(buf1), &p); payload_type = atoi(buf1); - for (i = 0; i < rt->nb_rtsp_streams; i++) { - rtsp_st = rt->rtsp_streams[i]; - if (rtsp_st->sdp_payload_type == payload_type && - 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, buf); + if (s1->seen_rtpmap) { + parse_fmtp(s, rt, payload_type, buf); + } else { + s1->seen_fmtp = 1; + av_strlcpy(s1->delayed_fmtp, buf, sizeof(s1->delayed_fmtp)); } } else if (av_strstart(p, "range:", &p)) { int64_t start, end; @@ -635,7 +658,7 @@ int ff_sdp_parse(AVFormatContext *s, const char *content) av_free(s1->default_exclude_source_addrs[i]); av_freep(&s1->default_exclude_source_addrs); - rt->p = av_malloc(sizeof(struct pollfd)*2*(rt->nb_rtsp_streams+1)); + rt->p = av_malloc_array(rt->nb_rtsp_streams + 1, sizeof(struct pollfd) * 2); if (!rt->p) return AVERROR(ENOMEM); return 0; } @@ -737,6 +760,7 @@ int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) rtsp_st->rtp_handle = NULL; if (ret < 0) return ret; + 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) @@ -1766,6 +1790,10 @@ redirect: int lower_transport = ff_log2_tab[lower_transport_mask & ~(lower_transport_mask - 1)]; + if ((lower_transport_mask & (1 << RTSP_LOWER_TRANSPORT_TCP)) + && (rt->rtsp_flags & RTSP_FLAG_PREFER_TCP)) + lower_transport = RTSP_LOWER_TRANSPORT_TCP; + err = ff_rtsp_make_setup_request(s, host, port, lower_transport, rt->server_type == RTSP_SERVER_REAL ? real_challenge : NULL); @@ -2066,6 +2094,16 @@ redo: st2->time_base); } } + // Make real NTP start time available in AVFormatContext + if (s->start_time_realtime == AV_NOPTS_VALUE) { + s->start_time_realtime = av_rescale (rtpctx->first_rtcp_ntp_time - (NTP_OFFSET << 32), 1000000, 1LL << 32); + if (rtpctx->st) { + s->start_time_realtime -= + av_rescale (rtpctx->rtcp_ts_offset, + (uint64_t) rtpctx->st->time_base.num * 1000000, + rtpctx->st->time_base.den); + } + } } if (ret == -RTCP_BYE) { rt->nb_byes++; diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 76c7f181c..d15979383 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -413,6 +413,7 @@ typedef struct RTSPState { #define RTSP_FLAG_CUSTOM_IO 0x4 /**< Do all IO via the AVIOContext. */ #define RTSP_FLAG_RTCP_TO_SOURCE 0x8 /**< Send RTCP packets to the source address of received packets. */ +#define RTSP_FLAG_PREFER_TCP 0x10 /**< Try RTP via TCP first if possible. */ typedef struct RTSPSource { char addr[128]; /**< Source-specific multicast include source IP address (from SDP content) */ diff --git a/libavformat/rtspcodes.h b/libavformat/rtspcodes.h index 4245e4864..d4f762b00 100644 --- a/libavformat/rtspcodes.h +++ b/libavformat/rtspcodes.h @@ -1,6 +1,8 @@ /* * RTSP definitions * copyright (c) 2002 Fabrice Bellard + * copyright (c) 2014 Samsung Electronics. All rights reserved. + * @Author: Reynaldo H. Verdejo Pinochet * * This file is part of FFmpeg. * @@ -22,21 +24,107 @@ #ifndef AVFORMAT_RTSPCODES_H #define AVFORMAT_RTSPCODES_H +#include "libavutil/common.h" + /** RTSP handling */ enum RTSPStatusCode { -RTSP_STATUS_OK =200, /**< OK */ -RTSP_STATUS_METHOD =405, /**< Method Not Allowed */ -RTSP_STATUS_BANDWIDTH =453, /**< Not Enough Bandwidth */ -RTSP_STATUS_SESSION =454, /**< Session Not Found */ -RTSP_STATUS_STATE =455, /**< Method Not Valid in This State */ -RTSP_STATUS_AGGREGATE =459, /**< Aggregate operation not allowed */ -RTSP_STATUS_ONLY_AGGREGATE =460, /**< Only aggregate operation allowed */ -RTSP_STATUS_TRANSPORT =461, /**< Unsupported transport */ -RTSP_STATUS_INTERNAL =500, /**< Internal Server Error */ -RTSP_STATUS_SERVICE =503, /**< Service Unavailable */ -RTSP_STATUS_VERSION =505, /**< RTSP Version not supported */ +RTSP_STATUS_CONTINUE =100, +RTSP_STATUS_OK =200, +RTSP_STATUS_CREATED =201, +RTSP_STATUS_LOW_ON_STORAGE_SPACE =250, +RTSP_STATUS_MULTIPLE_CHOICES =300, +RTSP_STATUS_MOVED_PERMANENTLY =301, +RTSP_STATUS_MOVED_TEMPORARILY =302, +RTSP_STATUS_SEE_OTHER =303, +RTSP_STATUS_NOT_MODIFIED =304, +RTSP_STATUS_USE_PROXY =305, +RTSP_STATUS_BAD_REQUEST =400, +RTSP_STATUS_UNAUTHORIZED =401, +RTSP_STATUS_PAYMENT_REQUIRED =402, +RTSP_STATUS_FORBIDDEN =403, +RTSP_STATUS_NOT_FOUND =404, +RTSP_STATUS_METHOD =405, +RTSP_STATUS_NOT_ACCEPTABLE =406, +RTSP_STATUS_PROXY_AUTH_REQUIRED =407, +RTSP_STATUS_REQ_TIME_OUT =408, +RTSP_STATUS_GONE =410, +RTSP_STATUS_LENGTH_REQUIRED =411, +RTSP_STATUS_PRECONDITION_FAILED =412, +RTSP_STATUS_REQ_ENTITY_2LARGE =413, +RTSP_STATUS_REQ_URI_2LARGE =414, +RTSP_STATUS_UNSUPPORTED_MTYPE =415, +RTSP_STATUS_PARAM_NOT_UNDERSTOOD =451, +RTSP_STATUS_CONFERENCE_NOT_FOUND =452, +RTSP_STATUS_BANDWIDTH =453, +RTSP_STATUS_SESSION =454, +RTSP_STATUS_STATE =455, +RTSP_STATUS_INVALID_HEADER_FIELD =456, +RTSP_STATUS_INVALID_RANGE =457, +RTSP_STATUS_RONLY_PARAMETER =458, +RTSP_STATUS_AGGREGATE =459, +RTSP_STATUS_ONLY_AGGREGATE =460, +RTSP_STATUS_TRANSPORT =461, +RTSP_STATUS_UNREACHABLE =462, +RTSP_STATUS_INTERNAL =500, +RTSP_STATUS_NOT_IMPLEMENTED =501, +RTSP_STATUS_BAD_GATEWAY =502, +RTSP_STATUS_SERVICE =503, +RTSP_STATUS_GATEWAY_TIME_OUT =504, +RTSP_STATUS_VERSION =505, +RTSP_STATUS_UNSUPPORTED_OPTION =551, }; +static const av_unused char *rtsp_status_strings[] = { +[RTSP_STATUS_CONTINUE] ="Continue", +[RTSP_STATUS_OK] ="OK", +[RTSP_STATUS_CREATED] ="Created", +[RTSP_STATUS_LOW_ON_STORAGE_SPACE] ="Low on Storage Space", +[RTSP_STATUS_MULTIPLE_CHOICES] ="Multiple Choices", +[RTSP_STATUS_MOVED_PERMANENTLY] ="Moved Permanently", +[RTSP_STATUS_MOVED_TEMPORARILY] ="Moved Temporarily", +[RTSP_STATUS_SEE_OTHER] ="See Other", +[RTSP_STATUS_NOT_MODIFIED] ="Not Modified", +[RTSP_STATUS_USE_PROXY] ="Use Proxy", +[RTSP_STATUS_BAD_REQUEST] ="Bad Request", +[RTSP_STATUS_UNAUTHORIZED] ="Unauthorized", +[RTSP_STATUS_PAYMENT_REQUIRED] ="Payment Required", +[RTSP_STATUS_FORBIDDEN] ="Forbidden", +[RTSP_STATUS_NOT_FOUND] ="Not Found", +[RTSP_STATUS_METHOD] ="Method Not Allowed", +[RTSP_STATUS_NOT_ACCEPTABLE] ="Not Acceptable", +[RTSP_STATUS_PROXY_AUTH_REQUIRED] ="Proxy Authentication Required", +[RTSP_STATUS_REQ_TIME_OUT] ="Request Time-out", +[RTSP_STATUS_GONE] ="Gone", +[RTSP_STATUS_LENGTH_REQUIRED] ="Length Required", +[RTSP_STATUS_PRECONDITION_FAILED] ="Precondition Failed", +[RTSP_STATUS_REQ_ENTITY_2LARGE] ="Request Entity Too Large", +[RTSP_STATUS_REQ_URI_2LARGE] ="Request URI Too Large", +[RTSP_STATUS_UNSUPPORTED_MTYPE] ="Unsupported Media Type", +[RTSP_STATUS_PARAM_NOT_UNDERSTOOD] ="Parameter Not Understood", +[RTSP_STATUS_CONFERENCE_NOT_FOUND] ="Conference Not Found", +[RTSP_STATUS_BANDWIDTH] ="Not Enough Bandwidth", +[RTSP_STATUS_SESSION] ="Session Not Found", +[RTSP_STATUS_STATE] ="Method Not Valid in This State", +[RTSP_STATUS_INVALID_HEADER_FIELD] ="Header Field Not Valid for Resource", +[RTSP_STATUS_INVALID_RANGE] ="Invalid Range", +[RTSP_STATUS_RONLY_PARAMETER] ="Parameter Is Read-Only", +[RTSP_STATUS_AGGREGATE] ="Aggregate Operation no Allowed", +[RTSP_STATUS_ONLY_AGGREGATE] ="Only Aggregate Operation Allowed", +[RTSP_STATUS_TRANSPORT] ="Unsupported Transport", +[RTSP_STATUS_UNREACHABLE] ="Destination Unreachable", +[RTSP_STATUS_INTERNAL] ="Internal Server Error", +[RTSP_STATUS_NOT_IMPLEMENTED] ="Not Implemented", +[RTSP_STATUS_BAD_GATEWAY] ="Bad Gateway", +[RTSP_STATUS_SERVICE] ="Service Unavailable", +[RTSP_STATUS_GATEWAY_TIME_OUT] ="Gateway Time-out", +[RTSP_STATUS_VERSION] ="RTSP Version not Supported", +[RTSP_STATUS_UNSUPPORTED_OPTION] ="Option not supported", +}; + +#define RTSP_STATUS_CODE2STRING(x) (\ +x >= 100 && x < FF_ARRAY_ELEMS(rtsp_status_strings) && rtsp_status_strings[x] \ +)? rtsp_status_strings[x] : NULL + enum RTSPMethod { DESCRIBE, ANNOUNCE, diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 74a7bf646..51c80c61e 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -360,6 +360,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) { + av_log(s, AV_LOG_ERROR, "Error parsing method string\n"); + return AVERROR_INVALIDDATA; + } if (linept - line > methodsize - 1) { av_log(s, AV_LOG_ERROR, "Method string too long\n"); return AVERROR(EIO); @@ -692,7 +696,7 @@ static int rtsp_read_header(AVFormatContext *s) return ret; rt->real_setup_cache = !s->nb_streams ? NULL : - av_mallocz(2 * s->nb_streams * sizeof(*rt->real_setup_cache)); + av_mallocz_array(s->nb_streams, 2 * sizeof(*rt->real_setup_cache)); if (!rt->real_setup_cache && s->nb_streams) return AVERROR(ENOMEM); rt->real_setup = rt->real_setup_cache + s->nb_streams; diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index d76ae872e..cc6e729e8 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -51,7 +51,8 @@ int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr) char *sdp; AVFormatContext sdp_ctx, *ctx_array[1]; - s->start_time_realtime = av_gettime(); + if (s->start_time_realtime == 0 || s->start_time_realtime == AV_NOPTS_VALUE) + s->start_time_realtime = av_gettime(); /* Announce the stream */ sdp = av_mallocz(SDP_MAX_SIZE); diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c index 9fc78a83a..82a6ef67f 100644 --- a/libavformat/sapenc.c +++ b/libavformat/sapenc.c @@ -140,7 +140,8 @@ static int sap_write_header(AVFormatContext *s) goto fail; } - s->start_time_realtime = av_gettime(); + if (s->start_time_realtime == 0 || s->start_time_realtime == AV_NOPTS_VALUE) + s->start_time_realtime = av_gettime(); for (i = 0; i < s->nb_streams; i++) { URLContext *fd; @@ -157,6 +158,7 @@ static int sap_write_header(AVFormatContext *s) if (ret < 0) goto fail; s->streams[i]->priv_data = contexts[i]; + s->streams[i]->time_base = contexts[i]->streams[0]->time_base; av_strlcpy(contexts[i]->filename, url, sizeof(contexts[i]->filename)); } @@ -244,7 +246,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/sdp.c b/libavformat/sdp.c index ae2948355..c53de9051 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -217,7 +217,7 @@ static char *extradata2psets(AVCodecContext *c) sps_end = r1; } if (av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r) == NULL) { - av_log(c, AV_LOG_ERROR, "Cannot Base64-encode %td %td!\n", MAX_PSET_SIZE - (p - psets), r1 - r); + av_log(c, AV_LOG_ERROR, "Cannot Base64-encode %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"!\n", MAX_PSET_SIZE - (p - psets), r1 - r); av_free(psets); return NULL; diff --git a/libavformat/segment.c b/libavformat/segment.c index ad313a316..f8227d149 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -27,6 +27,7 @@ /* #define DEBUG */ #include +#include #include "avformat.h" #include "internal.h" @@ -37,6 +38,7 @@ #include "libavutil/avstring.h" #include "libavutil/parseutils.h" #include "libavutil/mathematics.h" +#include "libavutil/time.h" #include "libavutil/timestamp.h" typedef struct SegmentListEntry { @@ -65,6 +67,7 @@ typedef struct { const AVClass *class; /**< Class for private options. */ int segment_idx; ///< index of the segment file to write, starting from 0 int segment_idx_wrap; ///< number after which the index wraps + int segment_idx_wrap_nb; ///< number of time the index has wraped int segment_count; ///< number of segment files already written AVOutputFormat *oformat; AVFormatContext *avf; @@ -72,7 +75,13 @@ typedef struct { char *list; ///< filename for the segment list file int list_flags; ///< flags affecting list generation int list_size; ///< number of entries for the segment list file - char *list_entry_prefix; ///< prefix to add to list entry filenames + + int use_clocktime; ///< flag to cut segments at regular clock time + int64_t last_val; ///< remember last time for wrap around detection + int64_t last_cut; ///< remember last cut + int cut_pending; + + char *entry_prefix; ///< prefix to add to list entry filenames ListType list_type; ///< set the list type AVIOContext *list_pb; ///< list file put-byte context char *time_str; ///< segment duration specification string @@ -171,14 +180,14 @@ static int set_segment_filename(AVFormatContext *s) /* copy modified name in list entry */ size = strlen(av_basename(oc->filename)) + 1; - if (seg->list_entry_prefix) - size += strlen(seg->list_entry_prefix); + if (seg->entry_prefix) + size += strlen(seg->entry_prefix); seg->cur_entry.filename = av_mallocz(size); if (!seg->cur_entry.filename) return AVERROR(ENOMEM); snprintf(seg->cur_entry.filename, size, "%s%s", - seg->list_entry_prefix ? seg->list_entry_prefix : "", + seg->entry_prefix ? seg->entry_prefix : "", av_basename(oc->filename)); return 0; @@ -199,6 +208,9 @@ static int segment_start(AVFormatContext *s, int write_header) } seg->segment_idx++; + if ((seg->segment_idx_wrap) && (seg->segment_idx%seg->segment_idx_wrap == 0)) + seg->segment_idx_wrap_nb++; + if ((err = set_segment_filename(s)) < 0) return err; @@ -242,6 +254,9 @@ static int segment_list_open(AVFormatContext *s) avio_printf(seg->list_pb, "#EXT-X-ALLOW-CACHE:%s\n", seg->list_flags & SEGMENT_LIST_FLAG_CACHE ? "YES" : "NO"); + av_log(s, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%d\n", + seg->segment_list_entries->index); + for (entry = seg->segment_list_entries; entry; entry = entry->next) max_duration = FFMAX(max_duration, entry->end_time - entry->start_time); avio_printf(seg->list_pb, "#EXT-X-TARGETDURATION:%"PRId64"\n", (int64_t)ceil(max_duration)); @@ -366,7 +381,7 @@ static int parse_times(void *log_ctx, int64_t **times, int *nb_times, if (*p == ',') (*nb_times)++; - *times = av_malloc(sizeof(**times) * *nb_times); + *times = av_malloc_array(*nb_times, sizeof(**times)); if (!*times) { av_log(log_ctx, AV_LOG_ERROR, "Could not allocate forced times array\n"); FAIL(AVERROR(ENOMEM)); @@ -424,7 +439,7 @@ static int parse_frames(void *log_ctx, int **frames, int *nb_frames, if (*p == ',') (*nb_frames)++; - *frames = av_malloc(sizeof(**frames) * *nb_frames); + *frames = av_malloc_array(*nb_frames, sizeof(**frames)); if (!*frames) { av_log(log_ctx, AV_LOG_ERROR, "Could not allocate forced frames array\n"); FAIL(AVERROR(ENOMEM)); @@ -661,6 +676,9 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) int64_t end_pts = INT64_MAX, offset; int start_frame = INT_MAX; int ret; + struct tm ti; + int64_t usecs; + int64_t wrapped_val; if (seg->times) { end_pts = seg->segment_count < seg->nb_times ? @@ -669,7 +687,24 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) start_frame = seg->segment_count <= seg->nb_frames ? seg->frames[seg->segment_count] : INT_MAX; } else { - end_pts = seg->time * (seg->segment_count+1); + if (seg->use_clocktime) { + int64_t avgt = av_gettime(); + time_t sec = avgt / 1000000; +#if HAVE_LOCALTIME_R + localtime_r(&sec, &ti); +#else + ti = *localtime(&sec); +#endif + usecs = (int64_t)(ti.tm_hour*3600 + ti.tm_min*60 + ti.tm_sec) * 1000000 + (avgt % 1000000); + wrapped_val = usecs % seg->time; + if (seg->last_cut != usecs && wrapped_val < seg->last_val) { + seg->cut_pending = 1; + seg->last_cut = usecs; + } + seg->last_val = wrapped_val; + } else { + end_pts = seg->time * (seg->segment_count+1); + } } av_dlog(s, "packet stream:%d pts:%s pts_time:%s is_key:%d frame:%d\n", @@ -679,7 +714,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) if (pkt->stream_index == seg->reference_stream_index && pkt->flags & AV_PKT_FLAG_KEY && - (seg->frame_count >= start_frame || + (seg->cut_pending || seg->frame_count >= start_frame || (pkt->pts != AV_NOPTS_VALUE && av_compare_ts(pkt->pts, st->time_base, end_pts-seg->time_delta, AV_TIME_BASE_Q) >= 0))) { @@ -689,7 +724,8 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) if ((ret = segment_start(s, seg->individual_header_trailer)) < 0) goto fail; - seg->cur_entry.index = seg->segment_idx; + seg->cut_pending = 0; + seg->cur_entry.index = seg->segment_idx + seg->segment_idx_wrap*seg->segment_idx_wrap_nb; seg->cur_entry.start_time = (double)pkt->pts * av_q2d(st->time_base); seg->cur_entry.start_pts = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q); } else if (pkt->pts != AV_NOPTS_VALUE) { @@ -779,7 +815,6 @@ static const AVOption options[] = { { "live", "enable live-friendly list generation (useful for HLS)", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_LIST_FLAG_LIVE }, INT_MIN, INT_MAX, E, "list_flags"}, { "segment_list_size", "set the maximum number of playlist entries", OFFSET(list_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, - { "segment_list_entry_prefix", "set prefix to prepend to each list entry filename", OFFSET(list_entry_prefix), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, { "segment_list_type", "set the segment list type", OFFSET(list_type), AV_OPT_TYPE_INT, {.i64 = LIST_TYPE_UNDEFINED}, -1, LIST_TYPE_NB-1, E, "list_type" }, { "flat", "flat format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_FLAT }, INT_MIN, INT_MAX, E, "list_type" }, @@ -789,12 +824,15 @@ static const AVOption options[] = { { "m3u8", "M3U8 format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_M3U8 }, INT_MIN, INT_MAX, E, "list_type" }, { "hls", "Apple HTTP Live Streaming compatible", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_M3U8 }, INT_MIN, INT_MAX, E, "list_type" }, + { "segment_atclocktime", "set segment to be cut at clocktime", OFFSET(use_clocktime), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E}, { "segment_time", "set segment duration", OFFSET(time_str),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, { "segment_time_delta","set approximation value used for the segment times", OFFSET(time_delta), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, 0, E }, { "segment_times", "set segment split time points", OFFSET(times_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E }, { "segment_frames", "set segment split frame numbers", OFFSET(frames_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E }, { "segment_wrap", "set number after which the index wraps", OFFSET(segment_idx_wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, + { "segment_list_entry_prefix", "set base url prefix for segments", OFFSET(entry_prefix), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, { "segment_start_number", "set the sequence number of the first segment", OFFSET(segment_idx), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, + { "segment_wrap_number", "set the number of wrap before the first segment", OFFSET(segment_idx_wrap_nb), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, { "individual_header_trailer", "write header/trailer to each segment", OFFSET(individual_header_trailer), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E }, { "write_header_trailer", "write a header to the first segment and a trailer to the last one", OFFSET(write_header_trailer), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E }, diff --git a/libavformat/smacker.c b/libavformat/smacker.c index 0d38588e2..46215ee73 100644 --- a/libavformat/smacker.c +++ b/libavformat/smacker.c @@ -23,6 +23,8 @@ * Based on http://wiki.multimedia.cx/index.php?title=Smacker */ +#include + #include "libavutil/bswap.h" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" @@ -142,7 +144,7 @@ static int smacker_read_header(AVFormatContext *s) smk->pad = avio_rl32(pb); /* setup data */ if(smk->frames > 0xFFFFFF) { - av_log(s, AV_LOG_ERROR, "Too many frames: %i\n", smk->frames); + av_log(s, AV_LOG_ERROR, "Too many frames: %"PRIu32"\n", smk->frames); return AVERROR_INVALIDDATA; } smk->frm_size = av_malloc_array(smk->frames, sizeof(*smk->frm_size)); @@ -221,7 +223,9 @@ static int smacker_read_header(AVFormatContext *s) /* load trees to extradata, they will be unpacked by decoder */ if(ff_alloc_extradata(st->codec, smk->treesize + 16)){ - av_log(s, AV_LOG_ERROR, "Cannot allocate %i bytes of extradata\n", smk->treesize + 16); + av_log(s, AV_LOG_ERROR, + "Cannot allocate %"PRIu32" bytes of extradata\n", + smk->treesize + 16); av_freep(&smk->frm_size); av_freep(&smk->frm_flags); return AVERROR(ENOMEM); diff --git a/libavformat/smjpegdec.c b/libavformat/smjpegdec.c index 38ac2fb08..e4c7a9b89 100644 --- a/libavformat/smjpegdec.c +++ b/libavformat/smjpegdec.c @@ -24,6 +24,8 @@ * This is a demuxer for Loki SDL Motion JPEG files */ +#include + #include "avformat.h" #include "internal.h" #include "riff.h" @@ -52,7 +54,7 @@ static int smjpeg_read_header(AVFormatContext *s) avio_skip(pb, 8); // magic version = avio_rb32(pb); if (version) - avpriv_request_sample(s, "Unknown version %d", version); + avpriv_request_sample(s, "Unknown version %"PRIu32, version); duration = avio_rb32(pb); // in msec @@ -124,7 +126,7 @@ static int smjpeg_read_header(AVFormatContext *s) case SMJPEG_HEND: return 0; default: - av_log(s, AV_LOG_ERROR, "unknown header %x\n", htype); + av_log(s, AV_LOG_ERROR, "unknown header %"PRIx32"\n", htype); return AVERROR_INVALIDDATA; } } @@ -164,7 +166,7 @@ static int smjpeg_read_packet(AVFormatContext *s, AVPacket *pkt) ret = AVERROR_EOF; break; default: - av_log(s, AV_LOG_ERROR, "unknown chunk %x\n", dtype); + av_log(s, AV_LOG_ERROR, "unknown chunk %"PRIx32"\n", dtype); ret = AVERROR_INVALIDDATA; break; } diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c index fe18a95e4..5a77ec3f7 100644 --- a/libavformat/smoothstreamingenc.c +++ b/libavformat/smoothstreamingenc.c @@ -154,8 +154,11 @@ static void get_private_data(OutputStream *os) if (!ptr) return; os->private_str = av_mallocz(2*size + 1); + if (!os->private_str) + goto fail; for (i = 0; i < size; i++) snprintf(&os->private_str[2*i], 3, "%02x", ptr[i]); +fail: if (ptr != codec->extradata) av_free(ptr); } @@ -301,7 +304,7 @@ static int ism_write_header(AVFormatContext *s) goto fail; } - c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams); + c->streams = av_mallocz_array(s->nb_streams, sizeof(*c->streams)); if (!c->streams) { ret = AVERROR(ENOMEM); goto fail; diff --git a/libavformat/smush.c b/libavformat/smush.c index e9c193739..a33d50915 100644 --- a/libavformat/smush.c +++ b/libavformat/smush.c @@ -20,11 +20,12 @@ */ #include "libavutil/intreadwrite.h" -#include "avformat.h" -#include "internal.h" -#include "avio.h" -typedef struct { +#include "avformat.h" +#include "avio.h" +#include "internal.h" + +typedef struct SMUSHContext { int version; int audio_stream_index; int video_stream_index; @@ -32,9 +33,9 @@ typedef struct { static int smush_read_probe(AVProbeData *p) { - if (((AV_RL32(p->buf) == MKTAG('S', 'A', 'N', 'M') && + if (((AV_RL32(p->buf) == MKTAG('S', 'A', 'N', 'M') && AV_RL32(p->buf + 8) == MKTAG('S', 'H', 'D', 'R')) || - (AV_RL32(p->buf) == MKTAG('A', 'N', 'I', 'M') && + (AV_RL32(p->buf) == MKTAG('A', 'N', 'I', 'M') && AV_RL32(p->buf + 8) == MKTAG('A', 'H', 'D', 'R')))) { return AVPROBE_SCORE_MAX; } @@ -65,6 +66,8 @@ static int smush_read_header(AVFormatContext *ctx) smush->version = 0; subversion = avio_rl16(pb); nframes = avio_rl16(pb); + if (!nframes) + return AVERROR_INVALIDDATA; avio_skip(pb, 2); // skip pad @@ -72,7 +75,7 @@ static int smush_read_header(AVFormatContext *ctx) palette[i] = avio_rb24(pb); avio_skip(pb, size - (3 * 256 + 6)); - } else if (magic == MKBETAG('S', 'A', 'N', 'M') ) { + } else if (magic == MKBETAG('S', 'A', 'N', 'M')) { if (avio_rb32(pb) != MKBETAG('S', 'H', 'D', 'R')) return AVERROR_INVALIDDATA; @@ -81,8 +84,11 @@ static int smush_read_header(AVFormatContext *ctx) return AVERROR_INVALIDDATA; smush->version = 1; - subversion = avio_rl16(pb); + subversion = avio_rl16(pb); nframes = avio_rl32(pb); + if (!nframes) + return AVERROR_INVALIDDATA; + avio_skip(pb, 2); // skip pad width = avio_rl16(pb); height = avio_rl16(pb); @@ -101,12 +107,18 @@ static int smush_read_header(AVFormatContext *ctx) sig = avio_rb32(pb); chunk_size = avio_rb32(pb); - read += 8; + read += 8; switch (sig) { case MKBETAG('W', 'a', 'v', 'e'): got_audio = 1; sample_rate = avio_rl32(pb); - channels = avio_rl32(pb); + if (!sample_rate) + return AVERROR_INVALIDDATA; + + channels = avio_rl32(pb); + if (!channels) + return AVERROR_INVALIDDATA; + avio_skip(pb, chunk_size - 8); read += chunk_size; break; @@ -133,17 +145,18 @@ static int smush_read_header(AVFormatContext *ctx) smush->video_stream_index = vst->index; + avpriv_set_pts_info(vst, 64, 1, 15); + vst->start_time = 0; 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; - avpriv_set_pts_info(vst, 64, 66667, 1000000); - if (!smush->version) { if (ff_alloc_extradata(vst->codec, 1024 + 2)) return AVERROR(ENOMEM); @@ -162,7 +175,7 @@ static int smush_read_header(AVFormatContext *ctx) ast->start_time = 0; ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = AV_CODEC_ID_VIMA; + ast->codec->codec_id = AV_CODEC_ID_ADPCM_VIMA; ast->codec->codec_tag = 0; ast->codec->sample_rate = sample_rate; ast->codec->channels = channels; @@ -178,6 +191,7 @@ static int smush_read_packet(AVFormatContext *ctx, AVPacket *pkt) SMUSHContext *smush = ctx->priv_data; AVIOContext *pb = ctx->pb; int done = 0; + int ret; while (!done) { uint32_t sig, size; @@ -185,22 +199,22 @@ static int smush_read_packet(AVFormatContext *ctx, AVPacket *pkt) if (url_feof(pb)) return AVERROR_EOF; - sig = avio_rb32(pb); - size = avio_rb32(pb); + sig = avio_rb32(pb); + size = avio_rb32(pb); switch (sig) { case MKBETAG('F', 'R', 'M', 'E'): if (smush->version) break; - if (av_get_packet(pb, pkt, size) < 0) - return AVERROR(EIO); + if ((ret = av_get_packet(pb, pkt, size)) < 0) + return ret; pkt->stream_index = smush->video_stream_index; done = 1; break; case MKBETAG('B', 'l', '1', '6'): - if (av_get_packet(pb, pkt, size) < 0) - return AVERROR(EIO); + if ((ret = av_get_packet(pb, pkt, size)) < 0) + return ret; pkt->stream_index = smush->video_stream_index; pkt->duration = 1; @@ -214,7 +228,7 @@ static int smush_read_packet(AVFormatContext *ctx, AVPacket *pkt) pkt->stream_index = smush->audio_stream_index; pkt->flags |= AV_PKT_FLAG_KEY; - pkt->duration = AV_RB32(pkt->data); + pkt->duration = AV_RB32(pkt->data); if (pkt->duration == 0xFFFFFFFFu) pkt->duration = AV_RB32(pkt->data + 8); done = 1; diff --git a/libavformat/soxenc.c b/libavformat/soxenc.c index e219d75b4..01ebe9c6a 100644 --- a/libavformat/soxenc.c +++ b/libavformat/soxenc.c @@ -118,4 +118,5 @@ AVOutputFormat ff_sox_muxer = { .write_header = sox_write_header, .write_packet = ff_raw_write_packet, .write_trailer = sox_write_trailer, + .flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/spdifenc.c b/libavformat/spdifenc.c index 210d63f39..18afd4280 100644 --- a/libavformat/spdifenc.c +++ b/libavformat/spdifenc.c @@ -44,6 +44,8 @@ * dependent from data-type (spaces between packets are filled by zeros) */ +#include + #include "avformat.h" #include "avio_internal.h" #include "spdif.h" @@ -274,7 +276,7 @@ static int spdif_header_dts(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "stray DTS-HD frame\n"); return AVERROR_INVALIDDATA; default: - av_log(s, AV_LOG_ERROR, "bad DTS syncword 0x%x\n", syncword_dts); + av_log(s, AV_LOG_ERROR, "bad DTS syncword 0x%"PRIx32"\n", syncword_dts); return AVERROR_INVALIDDATA; } blocks++; @@ -369,8 +371,8 @@ static int spdif_header_aac(AVFormatContext *s, AVPacket *pkt) ctx->data_type = IEC61937_MPEG2_AAC_LSF_4096; break; default: - av_log(s, AV_LOG_ERROR, "%i samples in AAC frame not supported\n", - hdr.samples); + av_log(s, AV_LOG_ERROR, + "%"PRIu32" samples in AAC frame not supported\n", hdr.samples); return AVERROR(EINVAL); } //TODO Data type dependent info (LC profile/SBR) diff --git a/libavformat/subfile.c b/libavformat/subfile.c new file mode 100644 index 000000000..0e8438460 --- /dev/null +++ b/libavformat/subfile.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014 Nicolas George + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/opt.h" +#include "avformat.h" +#include "url.h" + +typedef struct SubfileContext { + const AVClass *class; + URLContext *h; + int64_t start; + int64_t end; + int64_t pos; +} SubfileContext; + +#define OFFSET(field) offsetof(SubfileContext, field) +#define D AV_OPT_FLAG_DECODING_PARAM + +static const AVOption subfile_options[] = { + { "start", "start offset", OFFSET(start), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, D }, + { "end", "end offset", OFFSET(end), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, D }, + { NULL } +}; + +#undef OFFSET +#undef D + +static const AVClass subfile_class = { + .class_name = "subfile", + .item_name = av_default_item_name, + .option = subfile_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static int slave_seek(URLContext *h) +{ + SubfileContext *c = h->priv_data; + int64_t ret; + + if ((ret = ffurl_seek(c->h, c->pos, SEEK_SET)) != c->pos) { + if (ret >= 0) + ret = AVERROR_BUG; + av_log(h, AV_LOG_ERROR, "Impossible to seek in file: %s\n", + av_err2str(ret)); + return ret; + } + return 0; +} + +static int subfile_open(URLContext *h, const char *filename, int flags, + AVDictionary **options) +{ + SubfileContext *c = h->priv_data; + int ret; + + if (c->end <= c->start) { + av_log(h, AV_LOG_ERROR, "end before start\n"); + return AVERROR(EINVAL); + } + av_strstart(filename, "subfile:", &filename); + ret = ffurl_open(&c->h, filename, flags, &h->interrupt_callback, options); + if (ret < 0) + return ret; + c->pos = c->start; + if ((ret = slave_seek(h)) < 0) { + ffurl_close(c->h); + return ret; + } + return 0; +} + +static int subfile_close(URLContext *h) +{ + SubfileContext *c = h->priv_data; + return ffurl_close(c->h); +} + +static int subfile_read(URLContext *h, unsigned char *buf, int size) +{ + SubfileContext *c = h->priv_data; + int64_t rest = c->end - c->pos; + int ret; + + if (rest <= 0) + return 0; + size = FFMIN(size, rest); + ret = ffurl_read(c->h, buf, size); + if (ret >= 0) + c->pos += ret; + return ret; +} + +static int64_t subfile_seek(URLContext *h, int64_t pos, int whence) +{ + SubfileContext *c = h->priv_data; + int64_t new_pos = -1; + int ret; + + if (whence == AVSEEK_SIZE) + return c->end - c->start; + switch (whence) { + case SEEK_SET: + new_pos = c->start + pos; + break; + case SEEK_CUR: + new_pos += pos; + break; + case SEEK_END: + new_pos = c->end + c->pos; + break; + } + if (new_pos < c->start) + return AVERROR(EINVAL); + c->pos = new_pos; + if ((ret = slave_seek(h)) < 0) + return ret; + return c->pos - c->start; +} + +URLProtocol ff_subfile_protocol = { + .name = "subfile", + .url_open2 = subfile_open, + .url_read = subfile_read, + .url_seek = subfile_seek, + .url_close = subfile_close, + .priv_data_size = sizeof(SubfileContext), + .priv_data_class = &subfile_class, +}; diff --git a/libavformat/swf.h b/libavformat/swf.h index c1667b3c2..93a094c26 100644 --- a/libavformat/swf.h +++ b/libavformat/swf.h @@ -132,6 +132,7 @@ typedef struct SWFContext { int tag; AVFifoBuffer *audio_fifo; AVCodecContext *audio_enc, *video_enc; + AVStream *video_st; #if CONFIG_ZLIB AVIOContext *zpb; #define ZBUF_SIZE 4096 diff --git a/libavformat/swfenc.c b/libavformat/swfenc.c index 8d9cf0c24..3b6f9b3f8 100644 --- a/libavformat/swfenc.c +++ b/libavformat/swfenc.c @@ -212,6 +212,7 @@ static int swf_write_header(AVFormatContext *s) if (enc->codec_id == AV_CODEC_ID_VP6F || enc->codec_id == AV_CODEC_ID_FLV1 || enc->codec_id == AV_CODEC_ID_MJPEG) { + swf->video_st = s->streams[i]; swf->video_enc = enc; } else { av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n"); @@ -229,8 +230,9 @@ static int swf_write_header(AVFormatContext *s) } else { width = swf->video_enc->width; height = swf->video_enc->height; - rate = swf->video_enc->time_base.den; - rate_base = swf->video_enc->time_base.num; + // 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) @@ -490,8 +492,7 @@ static int swf_write_trailer(AVFormatContext *s) if (enc->codec_type == AVMEDIA_TYPE_VIDEO) video_enc = enc; else { - av_fifo_free(swf->audio_fifo); - swf->audio_fifo = NULL; + av_fifo_freep(&swf->audio_fifo); } } diff --git a/libavformat/tee.c b/libavformat/tee.c index 12ea0ea27..f26e15742 100644 --- a/libavformat/tee.c +++ b/libavformat/tee.c @@ -410,18 +410,17 @@ static int filter_packet(void *log_ctx, AVPacket *pkt, if (!new_pkt.buf) break; } + if (ret < 0) { + av_log(log_ctx, AV_LOG_ERROR, + "Failed to filter bitstream with filter %s for stream %d in file '%s' with codec %s\n", + bsf_ctx->filter->name, pkt->stream_index, fmt_ctx->filename, + avcodec_get_name(enc_ctx->codec_id)); + } *pkt = new_pkt; bsf_ctx = bsf_ctx->next; } - if (ret < 0) { - av_log(log_ctx, AV_LOG_ERROR, - "Failed to filter bitstream with filter %s for stream %d in file '%s' with codec %s\n", - bsf_ctx->filter->name, pkt->stream_index, fmt_ctx->filename, - avcodec_get_name(enc_ctx->codec_id)); - } - return ret; } diff --git a/libavformat/txd.c b/libavformat/txd.c index 194945bbc..400f2cc54 100644 --- a/libavformat/txd.c +++ b/libavformat/txd.c @@ -21,6 +21,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "internal.h" #define TXD_FILE 0x16 #define TXD_INFO 0x01 @@ -45,8 +46,8 @@ static int txd_read_header(AVFormatContext *s) { return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = AV_CODEC_ID_TXD; - st->codec->time_base.den = 5; - st->codec->time_base.num = 1; + 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 */ return 0; diff --git a/libavformat/udp.c b/libavformat/udp.c index a61ac33e3..a8baa5bf9 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -62,6 +62,7 @@ typedef struct { int ttl; int buffer_size; int is_multicast; + int is_broadcast; int local_port; int reuse_socket; int overrun_nonfatal; @@ -96,6 +97,7 @@ static const AVOption options[] = { {"localaddr", "choose local IP address", OFFSET(local_addr), AV_OPT_TYPE_STRING, {.str = ""}, 0, 0, D|E }, {"pkt_size", "set size of UDP packets", OFFSET(packet_size), AV_OPT_TYPE_INT, {.i64 = 1472}, 0, INT_MAX, D|E }, {"reuse", "explicitly allow or disallow reusing UDP sockets", OFFSET(reuse_socket), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E }, +{"broadcast", "explicitly allow or disallow broadcast destination", OFFSET(is_broadcast), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E }, {"ttl", "set the time to live value (for multicast only)", OFFSET(ttl), AV_OPT_TYPE_INT, {.i64 = 16}, 0, INT_MAX, E }, {"connect", "set if connect() should be called on socket", OFFSET(is_connected), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E }, /* TODO 'sources', 'block' option */ @@ -602,6 +604,8 @@ static int udp_open(URLContext *h, const char *uri, int flags) } if (!is_output && av_find_info_tag(buf, sizeof(buf), "timeout", p)) s->timeout = strtol(buf, NULL, 10); + if (is_output && av_find_info_tag(buf, sizeof(buf), "broadcast", p)) + s->is_broadcast = strtol(buf, NULL, 10); } /* handling needed to support options picking from both AVOption and URL */ s->circular_buffer_size *= 188; @@ -642,6 +646,13 @@ static int udp_open(URLContext *h, const char *uri, int flags) goto fail; } + if (s->is_broadcast) { +#ifdef SO_BROADCAST + if (setsockopt (udp_fd, SOL_SOCKET, SO_BROADCAST, &(s->is_broadcast), sizeof(s->is_broadcast)) != 0) +#endif + goto fail; + } + /* If multicast, try binding the multicast address first, to avoid * receiving UDP packets from other sources aimed at the same UDP * port. This fails on windows. This makes sending to the same address @@ -695,8 +706,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) goto fail; } } else { - /* set udp recv buffer size to the largest possible udp packet size to - * avoid losing data on OSes that set this too low by default. */ + /* set udp recv buffer size to the requested value (default 64K) */ tmp = s->buffer_size; if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) { log_net_error(h, AV_LOG_WARNING, "setsockopt(SO_RECVBUF)"); @@ -704,8 +714,11 @@ static int udp_open(URLContext *h, const char *uri, int flags) len = sizeof(tmp); if (getsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, &len) < 0) { log_net_error(h, AV_LOG_WARNING, "getsockopt(SO_RCVBUF)"); - } else + } else { av_log(h, AV_LOG_DEBUG, "end receive buffer size reported is %d\n", tmp); + if(tmp < s->buffer_size) + av_log(h, AV_LOG_WARNING, "attempted to set receive buffer to size %d but it only ended up set as %d", s->buffer_size, tmp); + } /* make the socket non-blocking */ ff_socket_nonblock(udp_fd, 1); @@ -759,7 +772,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) fail: if (udp_fd >= 0) closesocket(udp_fd); - av_fifo_free(s->fifo); + av_fifo_freep(&s->fifo); for (i = 0; i < num_include_sources; i++) av_freep(&include_sources[i]); for (i = 0; i < num_exclude_sources; i++) @@ -865,7 +878,7 @@ static int udp_close(URLContext *h) pthread_cond_destroy(&s->cond); } #endif - av_fifo_free(s->fifo); + av_fifo_freep(&s->fifo); return 0; } diff --git a/libavformat/utils.c b/libavformat/utils.c index 75f6639e6..e095d601e 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -110,12 +110,27 @@ MAKE_ACCESSORS(AVFormatContext, format, int, metadata_header_padding) MAKE_ACCESSORS(AVFormatContext, format, void *, opaque) MAKE_ACCESSORS(AVFormatContext, format, av_format_control_message, control_message_cb) +int64_t av_stream_get_end_pts(const AVStream *st) +{ + return st->pts.val; +} + struct AVCodecParserContext *av_stream_get_parser(const AVStream *st) { return st->parser; } -static AVCodec *find_decoder(AVFormatContext *s, AVStream *st, enum AVCodecID codec_id) +void av_format_inject_global_side_data(AVFormatContext *s) +{ + int i; + s->internal->inject_global_side_data = 1; + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + st->inject_global_side_data = 1; + } +} + +static const AVCodec *find_decoder(AVFormatContext *s, AVStream *st, enum AVCodecID codec_id) { if (st->codec->codec) return st->codec->codec; @@ -246,6 +261,8 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, if (lpd.buf_size > id3len + 16) { lpd.buf += id3len; lpd.buf_size -= id3len; + } else if (id3len >= PROBE_BUF_MAX) { + nodat = 2; } else nodat = 1; } @@ -257,8 +274,11 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, score = 0; if (fmt1->read_probe) { score = fmt1->read_probe(&lpd); - if (fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions)) - score = FFMAX(score, nodat ? AVPROBE_SCORE_EXTENSION / 2 - 1 : 1); + if (fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions)) { + if (nodat == 0) score = FFMAX(score, 1); + else if (nodat == 1) score = FFMAX(score, AVPROBE_SCORE_EXTENSION / 2 - 1); + else score = FFMAX(score, AVPROBE_SCORE_EXTENSION); + } } else if (fmt1->extensions) { if (av_match_ext(lpd.filename, fmt1->extensions)) score = AVPROBE_SCORE_EXTENSION; @@ -269,7 +289,7 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, } else if (score == score_max) fmt = NULL; } - if (nodat) + if (nodat == 1) score_max = FFMIN(AVPROBE_SCORE_EXTENSION / 2 - 1, score_max); *score_ret = score_max; @@ -364,8 +384,6 @@ int av_probe_input_buffer2(AVIOContext *pb, AVInputFormat **fmt, if (!max_probe_size) max_probe_size = PROBE_BUF_MAX; - else if (max_probe_size > PROBE_BUF_MAX) - max_probe_size = PROBE_BUF_MAX; else if (max_probe_size < PROBE_BUF_MIN) { av_log(logctx, AV_LOG_ERROR, "Specified probe size value %u cannot be < %u\n", max_probe_size, PROBE_BUF_MIN); @@ -459,7 +477,7 @@ static int init_input(AVFormatContext *s, const char *filename, s->flags |= AVFMT_FLAG_CUSTOM_IO; if (!s->iformat) return av_probe_input_buffer2(s->pb, &s->iformat, filename, - s, 0, s->probesize); + s, 0, s->format_probesize); else if (s->iformat->flags & AVFMT_NOFILE) av_log(s, AV_LOG_WARNING, "Custom AVIOContext makes no sense and " "will be ignored with AVFMT_NOFILE format.\n"); @@ -476,7 +494,7 @@ static int init_input(AVFormatContext *s, const char *filename, if (s->iformat) return 0; return av_probe_input_buffer2(s->pb, &s->iformat, filename, - s, 0, s->probesize); + s, 0, s->format_probesize); } static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, @@ -504,6 +522,12 @@ int avformat_queue_attached_pictures(AVFormatContext *s) if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC && s->streams[i]->discard < AVDISCARD_ALL) { AVPacket copy = s->streams[i]->attached_pic; + if (copy.size <= 0) { + av_log(s, AV_LOG_WARNING, + "Attached picture on stream %d has invalid size, " + "ignoring\n", i); + continue; + } copy.buf = av_buffer_ref(copy.buf); if (!copy.buf) return AVERROR(ENOMEM); @@ -1355,12 +1379,6 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) st->time_base, AV_ROUND_DOWN); } - } else if (st->codec->time_base.num != 0 && - st->codec->time_base.den != 0) { - out_pkt.duration = av_rescale_q_rnd(st->parser->duration, - st->codec->time_base, - st->time_base, - AV_ROUND_DOWN); } out_pkt.stream_index = st->index; @@ -1531,10 +1549,29 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) } st->skip_samples = 0; } - } - if (ret >= 0 && !(s->flags & AVFMT_FLAG_KEEP_SIDE_DATA)) - av_packet_merge_side_data(pkt); + if (st->inject_global_side_data) { + for (i = 0; i < st->nb_side_data; i++) { + AVPacketSideData *src_sd = &st->side_data[i]; + uint8_t *dst_data; + + if (av_packet_get_side_data(pkt, src_sd->type, NULL)) + continue; + + dst_data = av_packet_new_side_data(pkt, src_sd->type, src_sd->size); + if (!dst_data) { + av_log(s, AV_LOG_WARNING, "Could not inject global side data\n"); + continue; + } + + memcpy(dst_data, src_sd->data, src_sd->size); + } + st->inject_global_side_data = 0; + } + + if (!(s->flags & AVFMT_FLAG_KEEP_SIDE_DATA)) + av_packet_merge_side_data(pkt); + } if (s->debug & FF_FDEBUG_TS) av_log(s, AV_LOG_DEBUG, @@ -1703,6 +1740,9 @@ void ff_read_frame_flush(AVFormatContext *s) for (j = 0; j < MAX_REORDER_DELAY + 1; j++) st->pts_buffer[j] = AV_NOPTS_VALUE; + + if (s->internal->inject_global_side_data) + st->inject_global_side_data = 1; } } @@ -2443,8 +2483,9 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) { AVPacket pkt1, *pkt = &pkt1; AVStream *st; - int read_size, i, ret; - int64_t end_time; + int num, den, read_size, i, ret; + int found_duration = 0; + int is_end; int64_t filesize, offset, duration; int retry = 0; @@ -2457,7 +2498,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) st->first_dts == AV_NOPTS_VALUE && st->codec->codec_type != AVMEDIA_TYPE_UNKNOWN) av_log(st->codec, AV_LOG_WARNING, - "start time is not set in estimate_timings_from_pts\n"); + "start time for stream %d is not set in estimate_timings_from_pts\n", i); if (st->parser) { av_parser_close(st->parser); @@ -2465,11 +2506,12 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) } } + av_opt_set(ic, "skip_changes", "1", AV_OPT_SEARCH_CHILDREN); /* estimate the end time (duration) */ /* XXX: may need to support wrapping */ filesize = ic->pb ? avio_size(ic->pb) : 0; - end_time = AV_NOPTS_VALUE; do { + is_end = found_duration; offset = filesize - (DURATION_MAX_READ_SIZE << retry); if (offset < 0) offset = 0; @@ -2490,7 +2532,17 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) if (pkt->pts != AV_NOPTS_VALUE && (st->start_time != AV_NOPTS_VALUE || st->first_dts != AV_NOPTS_VALUE)) { - duration = end_time = pkt->pts; + if (pkt->duration == 0) { + ff_compute_frame_duration(&num, &den, st, st->parser, 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); + } + } + duration = pkt->pts + pkt->duration; + found_duration = 1; if (st->start_time != AV_NOPTS_VALUE) duration -= st->start_time; else @@ -2504,10 +2556,40 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) } av_free_packet(pkt); } - } while (end_time == AV_NOPTS_VALUE && - filesize > (DURATION_MAX_READ_SIZE << retry) && + + /* check if all audio/video streams have valid duration */ + if (!is_end) { + is_end = 1; + for (i = 0; i < ic->nb_streams; i++) { + st = ic->streams[i]; + switch (st->codec->codec_type) { + case AVMEDIA_TYPE_VIDEO: + case AVMEDIA_TYPE_AUDIO: + if (st->duration == AV_NOPTS_VALUE) + is_end = 0; + } + } + } + } while (!is_end && + offset && ++retry <= DURATION_MAX_RETRY); + av_opt_set(ic, "skip_changes", "0", AV_OPT_SEARCH_CHILDREN); + + /* warn about audio/video streams which duration could not be estimated */ + for (i = 0; i < ic->nb_streams; i++) { + st = ic->streams[i]; + if (st->duration == AV_NOPTS_VALUE) { + switch (st->codec->codec_type) { + case AVMEDIA_TYPE_VIDEO: + case AVMEDIA_TYPE_AUDIO: + if (st->start_time != AV_NOPTS_VALUE || st->first_dts != AV_NOPTS_VALUE) { + av_log(ic, AV_LOG_DEBUG, "stream %d : no PTS found at end of file, duration not set\n", i); + } else + av_log(ic, AV_LOG_DEBUG, "stream %d : no TS found at start of file, duration not set\n", i); + } + } + } fill_all_stream_timings(ic); avio_seek(ic->pb, old_offset, SEEK_SET); @@ -2580,6 +2662,9 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr) return 0; \ } while (0) + if ( avctx->codec_id == AV_CODEC_ID_NONE + && avctx->codec_type != AVMEDIA_TYPE_DATA) + FAIL("unknown codec"); switch (avctx->codec_type) { case AVMEDIA_TYPE_AUDIO: if (!avctx->frame_size && determinable_frame_size(avctx)) @@ -2611,8 +2696,6 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr) if (avctx->codec_id == AV_CODEC_ID_NONE) return 1; } - if (avctx->codec_id == AV_CODEC_ID_NONE) - FAIL("unknown codec"); return 1; } @@ -2848,6 +2931,7 @@ static int tb_unreliable(AVCodecContext *c) // c->codec_tag == AV_RL32("XVID") || c->codec_tag == AV_RL32("mp4v") || c->codec_id == AV_CODEC_ID_MPEG2VIDEO || + c->codec_id == AV_CODEC_ID_GIF || c->codec_id == AV_CODEC_ID_H264) return 1; return 0; @@ -2972,6 +3056,7 @@ void ff_rfps_calculate(AVFormatContext *ic) && tb_unreliable(st->codec)) { int num = 0; double best_error= 0.01; + AVRational ref_rate = st->r_frame_rate.num ? st->r_frame_rate : av_inv_q(st->time_base); for (j= 0; jr_frame_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(st->r_frame_rate))) + if (num && (!ref_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(ref_rate))) av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX); } + if ( !st->avg_frame_rate.num + && st->r_frame_rate.num && st->info->rfps_duration_sum + && st->info->codec_info_duration <= 0 + && st->info->duration_count > 2 + && fabs(1.0 / (av_q2d(st->r_frame_rate) * av_q2d(st->time_base)) - st->info->rfps_duration_sum / (double)st->info->duration_count) <= 1.0 + ) { + av_log(ic, AV_LOG_DEBUG, "Setting avg frame rate based on r frame rate\n"); + st->avg_frame_rate = st->r_frame_rate; + } av_freep(&st->info->duration_error); st->info->last_dts = AV_NOPTS_VALUE; @@ -3019,6 +3113,18 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) // new streams might appear, no options for those int orig_nb_streams = ic->nb_streams; int flush_codecs = ic->probesize > 0; + int64_t max_analyze_duration = ic->max_analyze_duration2; + if (!max_analyze_duration) + max_analyze_duration = ic->max_analyze_duration; + + av_opt_set(ic, "skip_clear", "1", AV_OPT_SEARCH_CHILDREN); + + if (!max_analyze_duration) { + if (!strcmp(ic->iformat->name, "flv") && !(ic->ctx_flags & AVFMTCTX_NOHEADER)) { + max_analyze_duration = 10*AV_TIME_BASE; + } else + max_analyze_duration = 5*AV_TIME_BASE; + } if (ic->pb) av_log(ic, AV_LOG_DEBUG, "Before avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d\n", @@ -3105,13 +3211,14 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) * the correct fps. */ if (av_q2d(st->time_base) > 0.0005) fps_analyze_framecount *= 2; + if (!tb_unreliable(st->codec)) + fps_analyze_framecount = 0; if (ic->fps_probe_size >= 0) fps_analyze_framecount = ic->fps_probe_size; if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) fps_analyze_framecount = 0; /* variable fps and no guess at the real fps */ - if (tb_unreliable(st->codec) && - !(st->r_frame_rate.num && st->avg_frame_rate.num) && + if (!(st->r_frame_rate.num && st->avg_frame_rate.num) && st->info->duration_count < fps_analyze_framecount && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) break; @@ -3119,6 +3226,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) !st->codec->extradata) break; if (st->first_dts == AV_NOPTS_VALUE && + !(ic->iformat->flags & AVFMT_NOTIMESTAMPS) && (st->codec->codec_type == AVMEDIA_TYPE_VIDEO || st->codec->codec_type == AVMEDIA_TYPE_AUDIO)) break; @@ -3219,6 +3327,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) } if (st->codec_info_nb_frames>1) { int64_t t = 0; + if (st->time_base.den > 0) t = av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q); if (st->avg_frame_rate.num > 0) @@ -3230,8 +3339,10 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) && st->info->fps_last_dts != AV_NOPTS_VALUE) t = FFMAX(t, av_rescale_q(st->info->fps_last_dts - st->info->fps_first_dts, st->time_base, AV_TIME_BASE_Q)); - if (t >= ic->max_analyze_duration) { - av_log(ic, AV_LOG_VERBOSE, "max_analyze_duration %d reached at %"PRId64" microseconds\n", ic->max_analyze_duration, t); + if (t >= max_analyze_duration) { + av_log(ic, AV_LOG_VERBOSE, "max_analyze_duration %"PRId64" reached at %"PRId64" microseconds\n", + max_analyze_duration, + t); break; } if (pkt->duration) { @@ -3293,6 +3404,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) } } } + av_opt_set(ic, "skip_clear", "0", AV_OPT_SEARCH_CHILDREN); // close codecs which were opened in try_decode_frame() for (i = 0; i < ic->nb_streams; i++) { @@ -3440,7 +3552,7 @@ int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, int i, nb_streams = ic->nb_streams; int ret = AVERROR_STREAM_NOT_FOUND, best_count = -1, best_bitrate = -1, best_multiframe = -1, count, bitrate, multiframe; unsigned *program = NULL; - AVCodec *decoder = NULL, *best_decoder = NULL; + const AVCodec *decoder = NULL, *best_decoder = NULL; if (related_stream >= 0 && wanted_stream_nb < 0) { AVProgram *p = av_find_program_from_stream(ic, NULL, related_stream); @@ -3473,6 +3585,8 @@ int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, } count = st->codec_info_nb_frames; bitrate = avctx->bit_rate; + if (!bitrate) + bitrate = avctx->rc_max_rate; multiframe = FFMIN(5, count); if ((best_multiframe > multiframe) || (best_multiframe == multiframe && best_bitrate > bitrate) || @@ -3491,7 +3605,7 @@ int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, } } if (decoder_ret) - *decoder_ret = best_decoder; + *decoder_ret = (AVCodec*)best_decoder; return ret; } @@ -3516,9 +3630,15 @@ int av_read_pause(AVFormatContext *s) } void ff_free_stream(AVFormatContext *s, AVStream *st) { + int j; av_assert0(s->nb_streams>0); av_assert0(s->streams[ s->nb_streams - 1 ] == st); + 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; + if (st->parser) { av_parser_close(st->parser); } @@ -3547,6 +3667,8 @@ void avformat_free_context(AVFormatContext *s) av_opt_free(s); if (s->iformat && s->iformat->priv_class && s->priv_data) av_opt_free(s->priv_data); + if (s->oformat && s->oformat->priv_class && s->priv_data) + av_opt_free(s->priv_data); for (i = s->nb_streams - 1; i >= 0; i--) { ff_free_stream(s, s->streams[i]); @@ -3637,9 +3759,14 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) st->info->last_dts = AV_NOPTS_VALUE; st->codec = avcodec_alloc_context3(c); - if (s->iformat) + if (s->iformat) { /* no default bitrate if decoding */ st->codec->bit_rate = 0; + + /* default pts setting is MPEG-like */ + avpriv_set_pts_info(st, 33, 1, 90000); + } + st->index = s->nb_streams; st->start_time = AV_NOPTS_VALUE; st->duration = AV_NOPTS_VALUE; @@ -3653,8 +3780,6 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) st->pts_wrap_reference = AV_NOPTS_VALUE; st->pts_wrap_behavior = AV_PTS_WRAP_IGNORE; - /* default pts setting is MPEG-like */ - avpriv_set_pts_info(st, 33, 1, 90000); st->last_IP_pts = AV_NOPTS_VALUE; st->last_dts_for_order_check = AV_NOPTS_VALUE; for (i = 0; i < MAX_REORDER_DELAY + 1; i++) @@ -3668,6 +3793,8 @@ 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; + st->inject_global_side_data = s->internal->inject_global_side_data; + s->streams[s->nb_streams++] = st; return st; } @@ -3706,6 +3833,11 @@ AVChapter *avpriv_new_chapter(AVFormatContext *s, int id, AVRational time_base, AVChapter *chapter = NULL; int i; + if (end != AV_NOPTS_VALUE && start > end) { + av_log(s, AV_LOG_ERROR, "Chapter end time %"PRId64" before start %"PRId64"\n", end, start); + return NULL; + } + for (i = 0; i < s->nb_chapters; i++) if (s->chapters[i]->id == id) chapter = s->chapters[i]; @@ -3753,190 +3885,6 @@ void ff_program_add_stream_index(AVFormatContext *ac, int progid, unsigned idx) } } -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); - else if (v % (100 * 1000)) - av_log(NULL, AV_LOG_INFO, ", %1.0f %s", d, postfix); - else - av_log(NULL, AV_LOG_INFO, ", %1.0fk %s", d / 1000, postfix); -} - -static void dump_metadata(void *ctx, AVDictionary *m, const char *indent) -{ - if (m && !(av_dict_count(m) == 1 && av_dict_get(m, "language", NULL, 0))) { - AVDictionaryEntry *tag = NULL; - - av_log(ctx, AV_LOG_INFO, "%sMetadata:\n", indent); - while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) - if (strcmp("language", tag->key)) { - const char *p = tag->value; - av_log(ctx, AV_LOG_INFO, - "%s %-16s: ", indent, tag->key); - while (*p) { - char tmp[256]; - size_t len = strcspn(p, "\x8\xa\xb\xc\xd"); - av_strlcpy(tmp, p, FFMIN(sizeof(tmp), len+1)); - av_log(ctx, AV_LOG_INFO, "%s", tmp); - p += len; - if (*p == 0xd) av_log(ctx, AV_LOG_INFO, " "); - if (*p == 0xa) av_log(ctx, AV_LOG_INFO, "\n%s %-16s: ", indent, ""); - if (*p) p++; - } - av_log(ctx, AV_LOG_INFO, "\n"); - } - } -} - -/* "user interface" functions */ -static void dump_stream_format(AVFormatContext *ic, int i, - int index, int is_output) -{ - char buf[256]; - int flags = (is_output ? ic->oformat->flags : ic->iformat->flags); - AVStream *st = ic->streams[i]; - int g = av_gcd(st->time_base.num, st->time_base.den); - AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); - avcodec_string(buf, sizeof(buf), st->codec, is_output); - av_log(NULL, AV_LOG_INFO, " Stream #%d:%d", index, i); - /* the pid is an important information, so we display it */ - /* XXX: add a generic system */ - if (flags & AVFMT_SHOW_IDS) - av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id); - if (lang) - av_log(NULL, AV_LOG_INFO, "(%s)", lang->value); - av_log(NULL, AV_LOG_DEBUG, ", %d, %d/%d", st->codec_info_nb_frames, - st->time_base.num / g, st->time_base.den / g); - 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)) { - 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, - 1024 * 1024); - av_log(NULL, AV_LOG_INFO, ", SAR %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 FF_API_R_FRAME_RATE - if (st->r_frame_rate.den && st->r_frame_rate.num) - print_fps(av_q2d(st->r_frame_rate), "tbr"); -#endif - if (st->time_base.den && st->time_base.num) - 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) - av_log(NULL, AV_LOG_INFO, " (default)"); - if (st->disposition & AV_DISPOSITION_DUB) - av_log(NULL, AV_LOG_INFO, " (dub)"); - if (st->disposition & AV_DISPOSITION_ORIGINAL) - av_log(NULL, AV_LOG_INFO, " (original)"); - if (st->disposition & AV_DISPOSITION_COMMENT) - av_log(NULL, AV_LOG_INFO, " (comment)"); - if (st->disposition & AV_DISPOSITION_LYRICS) - av_log(NULL, AV_LOG_INFO, " (lyrics)"); - if (st->disposition & AV_DISPOSITION_KARAOKE) - av_log(NULL, AV_LOG_INFO, " (karaoke)"); - if (st->disposition & AV_DISPOSITION_FORCED) - av_log(NULL, AV_LOG_INFO, " (forced)"); - if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED) - av_log(NULL, AV_LOG_INFO, " (hearing impaired)"); - if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED) - av_log(NULL, AV_LOG_INFO, " (visual impaired)"); - if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS) - av_log(NULL, AV_LOG_INFO, " (clean effects)"); - av_log(NULL, AV_LOG_INFO, "\n"); - dump_metadata(NULL, st->metadata, " "); -} - -void av_dump_format(AVFormatContext *ic, int index, - const char *url, int is_output) -{ - int i; - uint8_t *printed = ic->nb_streams ? av_mallocz(ic->nb_streams) : NULL; - if (ic->nb_streams && !printed) - return; - - av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n", - is_output ? "Output" : "Input", - index, - is_output ? ic->oformat->name : ic->iformat->name, - is_output ? "to" : "from", url); - dump_metadata(NULL, ic->metadata, " "); - if (!is_output) { - av_log(NULL, AV_LOG_INFO, " Duration: "); - if (ic->duration != AV_NOPTS_VALUE) { - int hours, mins, secs, us; - int64_t duration = ic->duration + 5000; - secs = duration / AV_TIME_BASE; - us = duration % AV_TIME_BASE; - mins = secs / 60; - secs %= 60; - hours = mins / 60; - mins %= 60; - av_log(NULL, AV_LOG_INFO, "%02d:%02d:%02d.%02d", hours, mins, secs, - (100 * us) / AV_TIME_BASE); - } else { - av_log(NULL, AV_LOG_INFO, "N/A"); - } - if (ic->start_time != AV_NOPTS_VALUE) { - int secs, us; - av_log(NULL, AV_LOG_INFO, ", start: "); - secs = ic->start_time / AV_TIME_BASE; - us = abs(ic->start_time % AV_TIME_BASE); - av_log(NULL, AV_LOG_INFO, "%d.%06d", - secs, (int) av_rescale(us, 1000000, AV_TIME_BASE)); - } - av_log(NULL, AV_LOG_INFO, ", bitrate: "); - if (ic->bit_rate) - av_log(NULL, AV_LOG_INFO, "%d kb/s", ic->bit_rate / 1000); - else - av_log(NULL, AV_LOG_INFO, "N/A"); - av_log(NULL, AV_LOG_INFO, "\n"); - } - for (i = 0; i < ic->nb_chapters; i++) { - AVChapter *ch = ic->chapters[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, - "end %f\n", ch->end * av_q2d(ch->time_base)); - - dump_metadata(NULL, ch->metadata, " "); - } - if (ic->nb_programs) { - int j, k, total = 0; - for (j = 0; j < ic->nb_programs; j++) { - AVDictionaryEntry *name = av_dict_get(ic->programs[j]->metadata, - "name", NULL, 0); - av_log(NULL, AV_LOG_INFO, " Program %d %s\n", ic->programs[j]->id, - name ? name->value : ""); - dump_metadata(NULL, ic->programs[j]->metadata, " "); - for (k = 0; k < ic->programs[j]->nb_stream_indexes; k++) { - dump_stream_format(ic, ic->programs[j]->stream_index[k], - index, is_output); - printed[ic->programs[j]->stream_index[k]] = 1; - } - total += ic->programs[j]->nb_stream_indexes; - } - if (total < ic->nb_streams) - av_log(NULL, AV_LOG_INFO, " No Program\n"); - } - for (i = 0; i < ic->nb_streams; i++) - if (!printed[i]) - dump_stream_format(ic, i, index, is_output); - - av_free(printed); -} - uint64_t ff_ntp_time(void) { return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; @@ -3995,86 +3943,6 @@ fail: return -1; } -#define HEXDUMP_PRINT(...) \ - do { \ - if (!f) \ - av_log(avcl, level, __VA_ARGS__); \ - else \ - fprintf(f, __VA_ARGS__); \ - } while (0) - -static void hex_dump_internal(void *avcl, FILE *f, int level, - const uint8_t *buf, int size) -{ - int len, i, j, c; - - for (i = 0; i < size; i += 16) { - len = size - i; - if (len > 16) - len = 16; - HEXDUMP_PRINT("%08x ", i); - for (j = 0; j < 16; j++) { - if (j < len) - HEXDUMP_PRINT(" %02x", buf[i + j]); - else - HEXDUMP_PRINT(" "); - } - HEXDUMP_PRINT(" "); - for (j = 0; j < len; j++) { - c = buf[i + j]; - if (c < ' ' || c > '~') - c = '.'; - HEXDUMP_PRINT("%c", c); - } - HEXDUMP_PRINT("\n"); - } -} - -void av_hex_dump(FILE *f, const uint8_t *buf, int size) -{ - hex_dump_internal(NULL, f, 0, buf, size); -} - -void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size) -{ - hex_dump_internal(avcl, NULL, level, buf, size); -} - -static void pkt_dump_internal(void *avcl, FILE *f, int level, AVPacket *pkt, - int dump_payload, AVRational time_base) -{ - HEXDUMP_PRINT("stream #%d:\n", pkt->stream_index); - HEXDUMP_PRINT(" keyframe=%d\n", (pkt->flags & AV_PKT_FLAG_KEY) != 0); - HEXDUMP_PRINT(" duration=%0.3f\n", pkt->duration * av_q2d(time_base)); - /* DTS is _always_ valid after av_read_frame() */ - HEXDUMP_PRINT(" dts="); - if (pkt->dts == AV_NOPTS_VALUE) - HEXDUMP_PRINT("N/A"); - else - HEXDUMP_PRINT("%0.3f", pkt->dts * av_q2d(time_base)); - /* PTS may not be known if B-frames are present. */ - HEXDUMP_PRINT(" pts="); - if (pkt->pts == AV_NOPTS_VALUE) - HEXDUMP_PRINT("N/A"); - else - HEXDUMP_PRINT("%0.3f", pkt->pts * av_q2d(time_base)); - HEXDUMP_PRINT("\n"); - HEXDUMP_PRINT(" size=%d\n", pkt->size); - if (dump_payload) - av_hex_dump(f, pkt->data, pkt->size); -} - -void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st) -{ - pkt_dump_internal(NULL, f, 0, pkt, dump_payload, st->time_base); -} - -void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload, - AVStream *st) -{ - pkt_dump_internal(avcl, NULL, level, pkt, dump_payload, st->time_base); -} - void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, @@ -4475,12 +4343,14 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, return 1; } return 0; - } else if (*spec == '#') { - int sid; + } else if (*spec == '#' || + (*spec == 'i' && *(spec + 1) == ':')) { + int stream_id; char *endptr; - sid = strtol(spec + 1, &endptr, 0); + spec += 1 + (*spec == 'i'); + stream_id = strtol(spec, &endptr, 0); if (!*endptr) - return st->id == sid; + return stream_id == st->id; } else if (!*spec) /* empty specifier, matches everything */ return 1; @@ -4585,3 +4455,18 @@ int ff_generate_avci_extradata(AVStream *st) return 0; } + +uint8_t *av_stream_get_side_data(AVStream *st, enum AVPacketSideDataType type, + int *size) +{ + int i; + + for (i = 0; i < st->nb_side_data; i++) { + if (st->side_data[i].type == type) { + if (size) + *size = st->side_data[i].size; + return st->side_data[i].data; + } + } + return NULL; +} diff --git a/libavformat/vc1test.c b/libavformat/vc1test.c index e5303fa46..e9246669a 100644 --- a/libavformat/vc1test.c +++ b/libavformat/vc1test.c @@ -51,12 +51,12 @@ static int vc1t_read_header(AVFormatContext *s) frames = avio_rl24(pb); if(avio_r8(pb) != 0xC5 || avio_rl32(pb) != 4) - return -1; + return AVERROR_INVALIDDATA; /* init video codec */ st = avformat_new_stream(s, NULL); if (!st) - return -1; + return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = AV_CODEC_ID_WMV3; @@ -66,7 +66,7 @@ static int vc1t_read_header(AVFormatContext *s) st->codec->height = avio_rl32(pb); st->codec->width = avio_rl32(pb); if(avio_rl32(pb) != 0xC) - return -1; + return AVERROR_INVALIDDATA; avio_skip(pb, 8); fps = avio_rl32(pb); if(fps == 0xFFFFFFFF) diff --git a/libavformat/version.h b/libavformat/version.h index 9f0695c86..2889361c8 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFORMAT_VERSION_MAJOR 55 -#define LIBAVFORMAT_VERSION_MINOR 33 +#define LIBAVFORMAT_VERSION_MINOR 48 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ @@ -51,6 +51,15 @@ #ifndef FF_API_REFERENCE_DTS #define FF_API_REFERENCE_DTS (LIBAVFORMAT_VERSION_MAJOR < 56) #endif +#ifndef FF_API_LAVF_BITEXACT +#define FF_API_LAVF_BITEXACT (LIBAVFORMAT_VERSION_MAJOR < 56) +#endif +#ifndef FF_API_LAVF_FRAC +#define FF_API_LAVF_FRAC (LIBAVFORMAT_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_LAVF_CODEC_TB +#define FF_API_LAVF_CODEC_TB (LIBAVFORMAT_VERSION_MAJOR < 57) +#endif #ifndef FF_API_ALLOC_OUTPUT_CONTEXT #define FF_API_ALLOC_OUTPUT_CONTEXT (LIBAVFORMAT_VERSION_MAJOR < 56) diff --git a/libavformat/vocenc.c b/libavformat/vocenc.c index 29e936349..0bb532e0c 100644 --- a/libavformat/vocenc.c +++ b/libavformat/vocenc.c @@ -107,4 +107,5 @@ AVOutputFormat ff_voc_muxer = { .write_packet = voc_write_packet, .write_trailer = voc_write_trailer, .codec_tag = (const AVCodecTag* const []){ ff_voc_codec_tags, 0 }, + .flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/vorbiscomment.c b/libavformat/vorbiscomment.c index f17a0c1d1..cc9b6620e 100644 --- a/libavformat/vorbiscomment.c +++ b/libavformat/vorbiscomment.c @@ -38,28 +38,26 @@ const AVMetadataConv ff_vorbiscomment_metadata_conv[] = { { 0 } }; -int ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string, - unsigned *count) +int ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string) { int len = 8; len += strlen(vendor_string); - *count = 0; if (m) { AVDictionaryEntry *tag = NULL; while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) { len += 4 +strlen(tag->key) + 1 + strlen(tag->value); - (*count)++; } } return len; } int ff_vorbiscomment_write(uint8_t **p, AVDictionary **m, - const char *vendor_string, const unsigned count) + const char *vendor_string) { bytestream_put_le32(p, strlen(vendor_string)); bytestream_put_buffer(p, vendor_string, strlen(vendor_string)); if (*m) { + int count = av_dict_count(*m); AVDictionaryEntry *tag = NULL; bytestream_put_le32(p, count); while ((tag = av_dict_get(*m, "", tag, AV_DICT_IGNORE_SUFFIX))) { diff --git a/libavformat/vorbiscomment.h b/libavformat/vorbiscomment.h index 4e631e355..f4212d263 100644 --- a/libavformat/vorbiscomment.h +++ b/libavformat/vorbiscomment.h @@ -32,11 +32,9 @@ * @param m The metadata structure to be parsed. For no metadata, set to NULL. * @param vendor_string The vendor string to be added into the VorbisComment. * For no string, set to an empty string. - * @param count Pointer to store the number of tags in m because m->count is "not allowed" * @return The length in bytes. */ -int ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string, - unsigned *count); +int ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string); /** * Write a VorbisComment into a buffer. The buffer, p, must have enough @@ -47,10 +45,9 @@ int ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string, * @param p The buffer in which to write. * @param m The metadata struct to write. * @param vendor_string The vendor string to write. - * @param count The number of tags in m because m->count is "not allowed" */ int ff_vorbiscomment_write(uint8_t **p, AVDictionary **m, - const char *vendor_string, const unsigned count); + const char *vendor_string); extern const AVMetadataConv ff_vorbiscomment_metadata_conv[]; diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c index daea64edc..1d7740241 100644 --- a/libavformat/wavdec.c +++ b/libavformat/wavdec.c @@ -114,7 +114,7 @@ static void handle_stream_probing(AVStream *st) { if (st->codec->codec_id == AV_CODEC_ID_PCM_S16LE) { st->request_probe = AVPROBE_SCORE_EXTENSION; - st->probe_packets = FFMIN(st->probe_packets, 4); + st->probe_packets = FFMIN(st->probe_packets, 14); } } @@ -402,6 +402,11 @@ break_loop: avio_seek(pb, data_ofs, SEEK_SET); + if (data_size > 0 && sample_count && data_size / sample_count / st->codec->channels > 8) { + av_log(s, AV_LOG_WARNING, "ignoring wrong sample_count %"PRId64"\n", sample_count); + sample_count = 0; + } + if (!sample_count || av_get_exact_bits_per_sample(st->codec->codec_id) > 0) if ( st->codec->channels && data_size diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c index 0067dfef2..c73c9009d 100644 --- a/libavformat/wavenc.c +++ b/libavformat/wavenc.c @@ -8,6 +8,9 @@ * WAV muxer RF64 support * Copyright (c) 2013 Daniel Verkamp * + * EBU Tech 3285 - Supplement 3 - Peak Envelope Chunk encoder + * Copyright (c) 2014 Georg Lippitsch + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -28,10 +31,13 @@ #include #include +#include "libavutil/avstring.h" #include "libavutil/dict.h" #include "libavutil/common.h" +#include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" +#include "libavutil/time.h" #include "avformat.h" #include "avio.h" @@ -43,6 +49,19 @@ #define RF64_NEVER 0 #define RF64_ALWAYS 1 +#define PEAK_BUFFER_SIZE 1024 + +typedef enum { + PEAK_OFF = 0, + PEAK_ON, + PEAK_ONLY +} PeakType; + +typedef enum { + PEAK_FORMAT_UINT8 = 1, + PEAK_FORMAT_UINT16 +} PeakFormat; + typedef struct WAVMuxContext { const AVClass *class; int64_t data; @@ -50,9 +69,22 @@ typedef struct WAVMuxContext { int64_t ds64; int64_t minpts; int64_t maxpts; + int16_t *peak_maxpos, *peak_maxneg; + uint32_t peak_num_frames; + uint32_t peak_outbuf_size; + uint32_t peak_outbuf_bytes; + uint32_t peak_pos_pop; + uint16_t peak_pop; + uint8_t *peak_output; int last_duration; int write_bext; + int write_peak; int rf64; + int peak_block_size; + PeakFormat peak_format; + int peak_block_pos; + int peak_ppv; + int peak_bps; } WAVMuxContext; #if CONFIG_WAV_MUXER @@ -110,6 +142,157 @@ static void bwf_write_bext_chunk(AVFormatContext *s) ff_end_tag(s->pb, bext); } +static av_cold void peak_free_buffers(AVFormatContext *s) +{ + WAVMuxContext *wav = s->priv_data; + + av_freep(&wav->peak_maxpos); + av_freep(&wav->peak_maxneg); + av_freep(&wav->peak_output); +} + +static av_cold int peak_init_writer(AVFormatContext *s) +{ + WAVMuxContext *wav = s->priv_data; + AVCodecContext *enc = s->streams[0]->codec; + + if (enc->codec_id != AV_CODEC_ID_PCM_S8 && + enc->codec_id != AV_CODEC_ID_PCM_S16LE && + enc->codec_id != AV_CODEC_ID_PCM_U8 && + enc->codec_id != AV_CODEC_ID_PCM_U16LE) { + av_log(s, AV_LOG_ERROR, "%s codec not supported for Peak Chunk\n", + s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE"); + return -1; + } + + wav->peak_bps = av_get_bits_per_sample(enc->codec_id) / 8; + + if (wav->peak_bps == 1 && wav->peak_format == PEAK_FORMAT_UINT16) { + av_log(s, AV_LOG_ERROR, + "Writing 16 bit peak for 8 bit audio does not make sense\n"); + return AVERROR(EINVAL); + } + + wav->peak_maxpos = av_mallocz_array(enc->channels, sizeof(*wav->peak_maxpos)); + wav->peak_maxneg = av_mallocz_array(enc->channels, sizeof(*wav->peak_maxneg)); + wav->peak_output = av_malloc(PEAK_BUFFER_SIZE); + if (!wav->peak_maxpos || !wav->peak_maxneg || !wav->peak_output) + goto nomem; + + wav->peak_outbuf_size = PEAK_BUFFER_SIZE; + + return 0; + +nomem: + av_log(s, AV_LOG_ERROR, "Out of memory\n"); + peak_free_buffers(s); + return AVERROR(ENOMEM); +} + +static void peak_write_frame(AVFormatContext *s) +{ + WAVMuxContext *wav = s->priv_data; + AVCodecContext *enc = s->streams[0]->codec; + int peak_of_peaks; + int c; + + if (!wav->peak_output) + return; + + for (c = 0; c < enc->channels; c++) { + wav->peak_maxneg[c] = -wav->peak_maxneg[c]; + + if (wav->peak_bps == 2 && wav->peak_format == PEAK_FORMAT_UINT8) { + wav->peak_maxpos[c] = wav->peak_maxpos[c] / 256; + wav->peak_maxneg[c] = wav->peak_maxneg[c] / 256; + } + + if (wav->peak_ppv == 1) + wav->peak_maxpos[c] = + FFMAX(wav->peak_maxpos[c], wav->peak_maxneg[c]); + + peak_of_peaks = FFMAX3(wav->peak_maxpos[c], wav->peak_maxneg[c], + wav->peak_pop); + if (peak_of_peaks > wav->peak_pop) + wav->peak_pos_pop = wav->peak_num_frames; + wav->peak_pop = peak_of_peaks; + + if (wav->peak_outbuf_size - wav->peak_outbuf_bytes < + wav->peak_format * wav->peak_ppv) { + wav->peak_outbuf_size += PEAK_BUFFER_SIZE; + wav->peak_output = av_realloc(wav->peak_output, + wav->peak_outbuf_size); + if (!wav->peak_output) { + av_log(s, AV_LOG_ERROR, "No memory for peak data\n"); + return; + } + } + + if (wav->peak_format == PEAK_FORMAT_UINT8) { + wav->peak_output[wav->peak_outbuf_bytes++] = + wav->peak_maxpos[c]; + if (wav->peak_ppv == 2) { + wav->peak_output[wav->peak_outbuf_bytes++] = + wav->peak_maxneg[c]; + } + } else { + AV_WL16(wav->peak_output + wav->peak_outbuf_bytes, + wav->peak_maxpos[c]); + wav->peak_outbuf_bytes += 2; + if (wav->peak_ppv == 2) { + AV_WL16(wav->peak_output + wav->peak_outbuf_bytes, + wav->peak_maxneg[c]); + wav->peak_outbuf_bytes += 2; + } + } + wav->peak_maxpos[c] = 0; + wav->peak_maxneg[c] = 0; + } + wav->peak_num_frames++; +} + +static void peak_write_chunk(AVFormatContext *s) +{ + WAVMuxContext *wav = s->priv_data; + AVIOContext *pb = s->pb; + AVCodecContext *enc = s->streams[0]->codec; + int64_t peak = ff_start_tag(s->pb, "levl"); + int64_t now0; + time_t now_secs; + char timestamp[28]; + + /* Peak frame of incomplete block at end */ + if (wav->peak_block_pos) + peak_write_frame(s); + + memset(timestamp, 0, sizeof(timestamp)); + if (!(s->flags & AVFMT_FLAG_BITEXACT)) { + av_log(s, AV_LOG_INFO, "Writing local time and date to Peak Envelope Chunk\n"); + now0 = av_gettime(); + now_secs = now0 / 1000000; + strftime(timestamp, sizeof(timestamp), "%Y:%m:%d:%H:%M:%S:", localtime(&now_secs)); + av_strlcatf(timestamp, sizeof(timestamp), "%03d", (int)((now0 / 1000) % 1000)); + } + + avio_wl32(pb, 1); /* version */ + avio_wl32(pb, wav->peak_format); /* 8 or 16 bit */ + avio_wl32(pb, wav->peak_ppv); /* positive and negative */ + avio_wl32(pb, wav->peak_block_size); /* frames per value */ + avio_wl32(pb, enc->channels); /* number of channels */ + avio_wl32(pb, wav->peak_num_frames); /* number of peak frames */ + avio_wl32(pb, wav->peak_pos_pop); /* audio sample frame index */ + avio_wl32(pb, 128); /* equal to size of header */ + avio_write(pb, timestamp, 28); /* ASCII time stamp */ + ffio_fill(pb, 0, 60); + + avio_write(pb, wav->peak_output, wav->peak_outbuf_bytes); + + ff_end_tag(pb, peak); + + if (!wav->data) + wav->data = peak; +} + static int wav_write_header(AVFormatContext *s) { WAVMuxContext *wav = s->priv_data; @@ -126,7 +309,7 @@ static int wav_write_header(AVFormatContext *s) avio_wl32(pb, -1); /* RF64 chunk size: use size in ds64 */ } else { ffio_wfourcc(pb, "RIFF"); - avio_wl32(pb, 0); /* file length */ + avio_wl32(pb, -1); /* file length */ } ffio_wfourcc(pb, "WAVE"); @@ -139,14 +322,17 @@ static int wav_write_header(AVFormatContext *s) ffio_fill(pb, 0, 28); } - /* format header */ - fmt = ff_start_tag(pb, "fmt "); - if (ff_put_wav_header(pb, s->streams[0]->codec) < 0) { - av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n", - s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE"); - return -1; + if (wav->write_peak != 2) { + /* format header */ + fmt = ff_start_tag(pb, "fmt "); + if (ff_put_wav_header(pb, s->streams[0]->codec, 0) < 0) { + const AVCodecDescriptor *desc = avcodec_descriptor_get(s->streams[0]->codec->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); } - ff_end_tag(pb, fmt); if (s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */ && s->pb->seekable) { @@ -158,15 +344,23 @@ static int wav_write_header(AVFormatContext *s) if (wav->write_bext) bwf_write_bext_chunk(s); + if (wav->write_peak) { + int ret; + if ((ret = peak_init_writer(s)) < 0) + return ret; + } + avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); wav->maxpts = wav->last_duration = 0; wav->minpts = INT64_MAX; - /* info header */ - ff_riff_write_info(s); + if (wav->write_peak != 2) { + /* info header */ + ff_riff_write_info(s); - /* data header */ - wav->data = ff_start_tag(pb, "data"); + /* data header */ + wav->data = ff_start_tag(pb, "data"); + } avio_flush(pb); @@ -177,7 +371,31 @@ static int wav_write_packet(AVFormatContext *s, AVPacket *pkt) { AVIOContext *pb = s->pb; WAVMuxContext *wav = s->priv_data; - avio_write(pb, pkt->data, pkt->size); + + if (wav->write_peak != 2) + avio_write(pb, pkt->data, pkt->size); + + if (wav->write_peak) { + int c = 0; + int i; + for (i = 0; i < pkt->size; i += wav->peak_bps) { + if (wav->peak_bps == 1) { + wav->peak_maxpos[c] = FFMAX(wav->peak_maxpos[c], *(int8_t*)(pkt->data + i)); + wav->peak_maxneg[c] = FFMIN(wav->peak_maxneg[c], *(int8_t*)(pkt->data + i)); + } else { + wav->peak_maxpos[c] = FFMAX(wav->peak_maxpos[c], (int16_t)AV_RL16(pkt->data + i)); + wav->peak_maxneg[c] = FFMIN(wav->peak_maxneg[c], (int16_t)AV_RL16(pkt->data + i)); + } + if (++c == s->streams[0]->codec->channels) { + c = 0; + if (++wav->peak_block_pos == wav->peak_block_size) { + peak_write_frame(s); + wav->peak_block_pos = 0; + } + } + } + } + if(pkt->pts != AV_NOPTS_VALUE) { wav->minpts = FFMIN(wav->minpts, pkt->pts); wav->maxpts = FFMAX(wav->maxpts, pkt->pts); @@ -198,6 +416,16 @@ static int wav_write_trailer(AVFormatContext *s) avio_flush(pb); if (s->pb->seekable) { + if (wav->write_peak != 2) { + ff_end_tag(pb, wav->data); + avio_flush(pb); + } + + if (wav->write_peak && wav->peak_output) { + peak_write_chunk(s); + avio_flush(pb); + } + /* update file size */ file_size = avio_tell(pb); data_size = file_size - wav->data; @@ -208,7 +436,6 @@ static int wav_write_trailer(AVFormatContext *s) avio_wl32(pb, (uint32_t)(file_size - 8)); avio_seek(pb, file_size, SEEK_SET); - ff_end_tag(pb, wav->data); avio_flush(pb); } @@ -252,6 +479,10 @@ static int wav_write_trailer(AVFormatContext *s) avio_flush(pb); } } + + if (wav->write_peak) + peak_free_buffers(s); + return 0; } @@ -259,10 +490,17 @@ static int wav_write_trailer(AVFormatContext *s) #define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "write_bext", "Write BEXT chunk.", OFFSET(write_bext), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, ENC }, + { "write_peak", "Write Peak Envelope chunk.", OFFSET(write_peak), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, ENC, "peak" }, + { "off", "Do not write peak chunk.", 0, AV_OPT_TYPE_CONST, { .i64 = PEAK_OFF }, 0, 0, ENC, "peak" }, + { "on", "Append peak chunk after wav data.", 0, AV_OPT_TYPE_CONST, { .i64 = PEAK_ON }, 0, 0, ENC, "peak" }, + { "only", "Write only peak chunk, omit wav data.", 0, AV_OPT_TYPE_CONST, { .i64 = PEAK_ONLY }, 0, 0, ENC, "peak" }, { "rf64", "Use RF64 header rather than RIFF for large files.", OFFSET(rf64), AV_OPT_TYPE_INT, { .i64 = RF64_NEVER },-1, 1, ENC, "rf64" }, { "auto", "Write RF64 header if file grows large enough.", 0, AV_OPT_TYPE_CONST, { .i64 = RF64_AUTO }, 0, 0, ENC, "rf64" }, { "always", "Always write RF64 header regardless of file size.", 0, AV_OPT_TYPE_CONST, { .i64 = RF64_ALWAYS }, 0, 0, ENC, "rf64" }, { "never", "Never write RF64 header regardless of file size.", 0, AV_OPT_TYPE_CONST, { .i64 = RF64_NEVER }, 0, 0, ENC, "rf64" }, + { "peak_block_size", "Number of audio samples used to generate each peak frame.", OFFSET(peak_block_size), AV_OPT_TYPE_INT, { .i64 = 256 }, 0, 65536, ENC }, + { "peak_format", "The format of the peak envelope data (1: uint8, 2: uint16).", OFFSET(peak_format), AV_OPT_TYPE_INT, { .i64 = PEAK_FORMAT_UINT16 }, PEAK_FORMAT_UINT8, PEAK_FORMAT_UINT16, ENC }, + { "peak_ppv", "Number of peak points per peak value (1 or 2).", OFFSET(peak_ppv), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, 2, ENC }, { NULL }, }; @@ -323,7 +561,7 @@ static int w64_write_header(AVFormatContext *s) avio_wl64(pb, -1); avio_write(pb, ff_w64_guid_wave, sizeof(ff_w64_guid_wave)); start_guid(pb, ff_w64_guid_fmt, &start); - if ((ret = ff_put_wav_header(pb, s->streams[0]->codec)) < 0) { + if ((ret = ff_put_wav_header(pb, s->streams[0]->codec, 0)) < 0) { av_log(s, AV_LOG_ERROR, "%s codec not supported\n", s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE"); return ret; diff --git a/libavformat/webmdashenc.c b/libavformat/webmdashenc.c new file mode 100644 index 000000000..381efb788 --- /dev/null +++ b/libavformat/webmdashenc.c @@ -0,0 +1,317 @@ +/* + * WebM DASH Manifest XML muxer + * Copyright (c) 2014 Vignesh Venkatasubramanian + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * WebM DASH Specification: + * https://sites.google.com/a/webmproject.org/wiki/adaptive-streaming/webm-dash-specification + */ + +#include +#include + +#include "avformat.h" +#include "avio_internal.h" +#include "matroska.h" + +#include "libavutil/avstring.h" +#include "libavutil/dict.h" +#include "libavutil/opt.h" + +typedef struct AdaptationSet { + char id[10]; + int *streams; + int nb_streams; +} AdaptationSet; + +typedef struct WebMDashMuxContext { + const AVClass *class; + char *adaptation_sets; + AdaptationSet *as; + int nb_as; +} WebMDashMuxContext; + +static const char *get_codec_name(int codec_id) +{ + switch (codec_id) { + case AV_CODEC_ID_VP8: + return "vp8"; + case AV_CODEC_ID_VP9: + return "vp9"; + case AV_CODEC_ID_VORBIS: + return "vorbis"; + case AV_CODEC_ID_OPUS: + return "opus"; + } + return NULL; +} + +static double get_duration(AVFormatContext *s) +{ + int i = 0; + double max = 0.0; + for (i = 0; i < s->nb_streams; i++) { + AVDictionaryEntry *duration = av_dict_get(s->streams[i]->metadata, + DURATION, NULL, 0); + if (duration == NULL || atof(duration->value) < 0) continue; + if (atof(duration->value) > max) max = atof(duration->value); + } + return max / 1000; +} + +static void write_header(AVFormatContext *s) +{ + double min_buffer_time = 1.0; + avio_printf(s->pb, "\n"); + avio_printf(s->pb, "pb, " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"); + avio_printf(s->pb, " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\"\n"); + avio_printf(s->pb, " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011\"\n"); + avio_printf(s->pb, " type=\"static\"\n"); + avio_printf(s->pb, " mediaPresentationDuration=\"PT%gS\"\n", + get_duration(s)); + avio_printf(s->pb, " minBufferTime=\"PT%gS\"\n", + min_buffer_time); + avio_printf(s->pb, " profiles=\"urn:webm:dash:profile:webm-on-demand:2012\""); + avio_printf(s->pb, ">\n"); +} + +static void write_footer(AVFormatContext *s) +{ + avio_printf(s->pb, ""); +} + +static int subsegment_alignment(AVFormatContext *s, AdaptationSet *as) { + int i; + AVDictionaryEntry *gold = av_dict_get(s->streams[as->streams[0]]->metadata, + CUE_TIMESTAMPS, NULL, 0); + if (gold == NULL) return 0; + for (i = 1; i < as->nb_streams; i++) { + AVDictionaryEntry *ts = av_dict_get(s->streams[as->streams[i]]->metadata, + CUE_TIMESTAMPS, NULL, 0); + if (ts == NULL || strncmp(gold->value, ts->value, strlen(gold->value))) return 0; + } + return 1; +} + +static int bitstream_switching(AVFormatContext *s, AdaptationSet *as) { + int i; + AVDictionaryEntry *gold_track_num = av_dict_get(s->streams[as->streams[0]]->metadata, + TRACK_NUMBER, NULL, 0); + AVCodecContext *gold_codec = s->streams[as->streams[0]]->codec; + if (gold_track_num == NULL) return 0; + for (i = 1; i < as->nb_streams; i++) { + AVDictionaryEntry *track_num = av_dict_get(s->streams[as->streams[i]]->metadata, + TRACK_NUMBER, NULL, 0); + AVCodecContext *codec = s->streams[as->streams[i]]->codec; + if (track_num == NULL || + strncmp(gold_track_num->value, track_num->value, strlen(gold_track_num->value)) || + gold_codec->codec_id != codec->codec_id || + gold_codec->extradata_size != codec->extradata_size || + memcmp(gold_codec->extradata, codec->extradata, codec->extradata_size)) { + return 0; + } + } + return 1; +} + +/* + * Writes an Adaptation Set. Returns 0 on success and < 0 on failure. + */ +static int write_adaptation_set(AVFormatContext *s, int as_index) +{ + WebMDashMuxContext *w = s->priv_data; + AdaptationSet *as = &w->as[as_index]; + AVCodecContext *codec = s->streams[as->streams[0]]->codec; + int i; + static const char boolean[2][6] = { "false", "true" }; + int subsegmentStartsWithSAP = 1; + AVDictionaryEntry *lang; + avio_printf(s->pb, "id); + avio_printf(s->pb, " mimeType=\"%s/webm\"", + codec->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); + avio_printf(s->pb, " codecs=\"%s\"", get_codec_name(codec->codec_id)); + + lang = av_dict_get(s->streams[as->streams[0]]->metadata, "language", NULL, 0); + if (lang != NULL) avio_printf(s->pb, " lang=\"%s\"", lang->value); + + if (codec->codec_type == AVMEDIA_TYPE_VIDEO) { + avio_printf(s->pb, " width=\"%d\"", codec->width); + avio_printf(s->pb, " height=\"%d\"", codec->height); + } else { + avio_printf(s->pb, " audioSamplingRate=\"%d\"", codec->sample_rate); + } + + avio_printf(s->pb, " bitstreamSwitching=\"%s\"", + boolean[bitstream_switching(s, as)]); + avio_printf(s->pb, " subsegmentAlignment=\"%s\"", + boolean[subsegment_alignment(s, as)]); + + for (i = 0; i < as->nb_streams; i++) { + AVDictionaryEntry *kf = av_dict_get(s->streams[as->streams[i]]->metadata, + CLUSTER_KEYFRAME, NULL, 0); + if (kf == NULL || !strncmp(kf->value, "0", 1)) subsegmentStartsWithSAP = 0; + } + avio_printf(s->pb, " subsegmentStartsWithSAP=\"%d\"", subsegmentStartsWithSAP); + avio_printf(s->pb, ">\n"); + + for (i = 0; i < as->nb_streams; i++) { + AVStream *stream = s->streams[as->streams[i]]; + AVDictionaryEntry *irange = av_dict_get(stream->metadata, INITIALIZATION_RANGE, NULL, 0); + AVDictionaryEntry *cues_start = av_dict_get(stream->metadata, CUES_START, NULL, 0); + AVDictionaryEntry *cues_end = av_dict_get(stream->metadata, CUES_END, NULL, 0); + AVDictionaryEntry *filename = av_dict_get(stream->metadata, FILENAME, NULL, 0); + AVDictionaryEntry *bandwidth = av_dict_get(stream->metadata, BANDWIDTH, NULL, 0); + if (irange == NULL || cues_start == NULL || cues_end == NULL || filename == NULL || + bandwidth == NULL) { + return -1; + } + avio_printf(s->pb, "pb, " bandwidth=\"%s\"", bandwidth->value); + avio_printf(s->pb, ">\n"); + avio_printf(s->pb, "%s\n", filename->value); + avio_printf(s->pb, "pb, " indexRange=\"%s-%s\">\n", cues_start->value, cues_end->value); + avio_printf(s->pb, "pb, " range=\"0-%s\" />\n", irange->value); + avio_printf(s->pb, "\n"); + avio_printf(s->pb, "\n"); + } + avio_printf(s->pb, "\n"); + return 0; +} + +static int to_integer(char *p, int len) +{ + int ret; + char *q = av_malloc(sizeof(char) * len); + if (q == NULL) return -1; + strncpy(q, p, len); + ret = atoi(q); + av_free(q); + return ret; +} + +static int parse_adaptation_sets(AVFormatContext *s) +{ + WebMDashMuxContext *w = s->priv_data; + char *p = w->adaptation_sets; + char *q; + enum { new_set, parsed_id, parsing_streams } state; + // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on + state = new_set; + while (p < w->adaptation_sets + strlen(w->adaptation_sets)) { + if (*p == ' ') + continue; + else if (state == new_set && !strncmp(p, "id=", 3)) { + w->as = av_realloc(w->as, sizeof(*w->as) * ++w->nb_as); + if (w->as == NULL) return -1; + w->as[w->nb_as - 1].nb_streams = 0; + w->as[w->nb_as - 1].streams = NULL; + p += 3; // consume "id=" + q = w->as[w->nb_as - 1].id; + while (*p != ',') *q++ = *p++; + *q = 0; + p++; + state = parsed_id; + } else if (state == parsed_id && !strncmp(p, "streams=", 8)) { + p += 8; // consume "streams=" + state = parsing_streams; + } else if (state == parsing_streams) { + struct AdaptationSet *as = &w->as[w->nb_as - 1]; + q = p; + while (*q != '\0' && *q != ',' && *q != ' ') q++; + as->streams = av_realloc(as->streams, sizeof(*as->streams) * ++as->nb_streams); + if (as->streams == NULL) return -1; + as->streams[as->nb_streams - 1] = to_integer(p, q - p); + if (as->streams[as->nb_streams - 1] < 0) return -1; + if (*q == '\0') break; + if (*q == ' ') state = new_set; + p = ++q; + } else { + return -1; + } + } + return 0; +} + +static int webm_dash_manifest_write_header(AVFormatContext *s) +{ + int i; + double start = 0.0; + WebMDashMuxContext *w = s->priv_data; + parse_adaptation_sets(s); + write_header(s); + avio_printf(s->pb, "pb, " start=\"PT%gS\"", start); + avio_printf(s->pb, " duration=\"PT%gS\"", get_duration(s)); + avio_printf(s->pb, " >\n"); + + for (i = 0; i < w->nb_as; i++) { + if (write_adaptation_set(s, i) < 0) return -1; + } + + avio_printf(s->pb, "\n"); + write_footer(s); + return 0; +} + +static int webm_dash_manifest_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + return AVERROR_EOF; +} + +static int webm_dash_manifest_write_trailer(AVFormatContext *s) +{ + WebMDashMuxContext *w = s->priv_data; + int i; + for (i = 0; i < w->nb_as; i++) { + av_freep(&w->as[i].streams); + } + av_freep(&w->as); + return 0; +} + +#define OFFSET(x) offsetof(WebMDashMuxContext, x) +static const AVOption options[] = { + { "adaptation_sets", "Adaptation sets. Syntax: id=0,streams=0,1,2 id=1,streams=3,4 and so on", OFFSET(adaptation_sets), AV_OPT_TYPE_STRING, { 0 }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, + { NULL }, +}; + +#if CONFIG_WEBM_DASH_MANIFEST_MUXER +static const AVClass webm_dash_class = { + .class_name = "WebM DASH Manifest muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVOutputFormat ff_webm_dash_manifest_muxer = { + .name = "webm_dash_manifest", + .long_name = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"), + .mime_type = "application/xml", + .extensions = "xml", + .priv_data_size = sizeof(WebMDashMuxContext), + .write_header = webm_dash_manifest_write_header, + .write_packet = webm_dash_manifest_write_packet, + .write_trailer = webm_dash_manifest_write_trailer, + .priv_class = &webm_dash_class, +}; +#endif diff --git a/libavformat/webvttenc.c b/libavformat/webvttenc.c index bd19a8345..b93993d55 100644 --- a/libavformat/webvttenc.c +++ b/libavformat/webvttenc.c @@ -93,6 +93,7 @@ AVOutputFormat ff_webvtt_muxer = { .long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), .extensions = "vtt", .mime_type = "text/vtt", + .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, .subtitle_codec = AV_CODEC_ID_WEBVTT, .write_header = webvtt_write_header, .write_packet = webvtt_write_packet, diff --git a/libavformat/wtvdec.c b/libavformat/wtvdec.c index 21236fa95..cfdc55523 100644 --- a/libavformat/wtvdec.c +++ b/libavformat/wtvdec.c @@ -25,6 +25,8 @@ * @author Peter Ross */ +#include + #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" @@ -35,7 +37,7 @@ /* Macros for formating GUIDs */ #define PRI_PRETTY_GUID \ - "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x" + "%08"PRIx32"-%04"PRIx16"-%04"PRIx16"-%02x%02x%02x%02x%02x%02x%02x%02x" #define ARG_PRETTY_GUID(g) \ AV_RL32(g),AV_RL16(g+4),AV_RL16(g+6),g[8],g[9],g[10],g[11],g[12],g[13],g[14],g[15] #define LEN_PRETTY_GUID 34 @@ -471,7 +473,7 @@ static void get_tag(AVFormatContext *s, AVIOContext *pb, const char *key, int ty return; if (type == 0 && length == 4) { - snprintf(buf, buf_size, "%"PRIi32, avio_rl32(pb)); + snprintf(buf, buf_size, "%u", avio_rl32(pb)); } else if (type == 1) { avio_get_str16le(pb, length, buf, buf_size); if (!strlen(buf)) { @@ -560,7 +562,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, NULL); + st->codec->codec_tag = ff_get_bmp_header(pb, st, NULL); return 72 + 40; } @@ -633,7 +635,7 @@ static AVStream * new_stream(AVFormatContext *s, AVStream *st, int sid, int code */ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, ff_asf_guid mediatype, ff_asf_guid subtype, - ff_asf_guid formattype, int size) + ff_asf_guid formattype, uint64_t size) { WtvContext *wtv = s->priv_data; AVIOContext *pb = wtv->pb; @@ -691,7 +693,8 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, int consumed = parse_videoinfoheader2(s, st); avio_skip(pb, FFMAX(size - consumed, 0)); } else if (!ff_guidcmp(formattype, ff_format_mpeg2_video)) { - int consumed = parse_videoinfoheader2(s, st); + uint64_t consumed = parse_videoinfoheader2(s, st); + /* ignore extradata; files produced by windows media center contain meaningless mpeg1 sequence header */ avio_skip(pb, FFMAX(size - consumed, 0)); } else { if (ff_guidcmp(formattype, ff_format_none)) diff --git a/libavformat/wtvenc.c b/libavformat/wtvenc.c index b82ff0b7a..634545d45 100644 --- a/libavformat/wtvenc.c +++ b/libavformat/wtvenc.c @@ -30,6 +30,7 @@ #include "avformat.h" #include "avio_internal.h" #include "internal.h" +#include "mpegts.h" #include "wtv.h" #define WTV_BIGSECTOR_SIZE (1 << WTV_BIGSECTOR_BITS) @@ -243,14 +244,15 @@ static void put_videoinfoheader2(AVIOContext *pb, AVStream *st) ff_put_bmp_header(pb, st->codec, ff_codec_bmp_tags, 0, 1); if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + int padding = (st->codec->extradata_size & 3) ? 4 - (st->codec->extradata_size & 3) : 0; /* MPEG2VIDEOINFO */ avio_wl32(pb, 0); - avio_wl32(pb, st->codec->extradata_size); + avio_wl32(pb, st->codec->extradata_size + padding); avio_wl32(pb, -1); avio_wl32(pb, -1); avio_wl32(pb, 0); avio_write(pb, st->codec->extradata, st->codec->extradata_size); - avio_wl64(pb, 0); + ffio_fill(pb, 0, padding); } } @@ -287,7 +289,7 @@ static int write_stream_codec_info(AVFormatContext *s, AVStream *st) if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { put_videoinfoheader2(pb, st); } else { - if (ff_put_wav_header(pb, st->codec) < 0) + if (ff_put_wav_header(pb, st->codec, 0) < 0) format_type = &ff_format_none; } hdr_size = avio_tell(pb) - hdr_pos_start; @@ -459,10 +461,15 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) { AVIOContext *pb = s->pb; WtvContext *wctx = s->priv_data; + AVStream *st = s->streams[pkt->stream_index]; - if (s->streams[pkt->stream_index]->codec->codec_id == AV_CODEC_ID_MJPEG && !wctx->thumbnail.size) { + if (st->codec->codec_id == AV_CODEC_ID_MJPEG && !wctx->thumbnail.size) { av_copy_packet(&wctx->thumbnail, pkt); return 0; + } else if (st->codec->codec_id == AV_CODEC_ID_H264) { + int ret = ff_check_h264_startcode(s, st, pkt); + if (ret < 0) + return ret; } /* emit sync chunk and 'timeline.table.0.entries.Event' record every 50 frames */ diff --git a/libavformat/xmv.c b/libavformat/xmv.c index 20f9bea55..6eac4d21e 100644 --- a/libavformat/xmv.c +++ b/libavformat/xmv.c @@ -25,7 +25,7 @@ * Microsoft XMV demuxer */ -#include +#include #include "libavutil/intreadwrite.h" @@ -155,7 +155,7 @@ static int xmv_read_header(AVFormatContext *s) file_version = avio_rl32(pb); if ((file_version != 4) && (file_version != 2)) - avpriv_request_sample(s, "Uncommon version %d", file_version); + avpriv_request_sample(s, "Uncommon version %"PRIu32"", file_version); /* Video track */ @@ -182,7 +182,7 @@ static int xmv_read_header(AVFormatContext *s) avio_skip(pb, 2); /* Unknown (padding?) */ - xmv->audio = av_malloc(xmv->audio_track_count * sizeof(XMVAudioPacket)); + xmv->audio = av_malloc_array(xmv->audio_track_count, sizeof(XMVAudioPacket)); if (!xmv->audio) { ret = AVERROR(ENOMEM); goto fail; @@ -219,7 +219,7 @@ static int xmv_read_header(AVFormatContext *s) if (!packet->channels || !packet->sample_rate || packet->channels >= UINT16_MAX / XMV_BLOCK_ALIGN_SIZE) { - av_log(s, AV_LOG_ERROR, "Invalid parameters for audio track %d.\n", + av_log(s, AV_LOG_ERROR, "Invalid parameters for audio track %"PRIu16".\n", audio_track); ret = AVERROR_INVALIDDATA; goto fail; diff --git a/libavformat/xwma.c b/libavformat/xwma.c index e629b3f38..127c097c4 100644 --- a/libavformat/xwma.c +++ b/libavformat/xwma.c @@ -46,7 +46,7 @@ static int xwma_read_header(AVFormatContext *s) int64_t size; int ret; uint32_t dpds_table_size = 0; - uint32_t *dpds_table = 0; + uint32_t *dpds_table = NULL; unsigned int tag; AVIOContext *pb = s->pb; AVStream *st; @@ -130,8 +130,10 @@ static int xwma_read_header(AVFormatContext *s) /* parse the remaining RIFF chunks */ for (;;) { - if (pb->eof_reached) - return -1; + if (pb->eof_reached) { + ret = AVERROR_EOF; + goto end; + } /* read next chunk tag */ tag = avio_rl32(pb); size = avio_rl32(pb); @@ -152,7 +154,8 @@ static int xwma_read_header(AVFormatContext *s) /* Error out if there is more than one dpds chunk. */ if (dpds_table) { av_log(s, AV_LOG_ERROR, "two dpds chunks present\n"); - return -1; + ret = AVERROR_INVALIDDATA; + goto end; } /* Compute the number of entries in the dpds chunk. */ @@ -164,7 +167,7 @@ static int xwma_read_header(AVFormatContext *s) if (dpds_table_size == 0 || dpds_table_size >= INT_MAX / 4) { av_log(s, AV_LOG_ERROR, "dpds chunk size %"PRId64" invalid\n", size); - return -1; + return AVERROR_INVALIDDATA; } /* Allocate some temporary storage to keep the dpds data around. @@ -184,8 +187,10 @@ static int xwma_read_header(AVFormatContext *s) } /* Determine overall data length */ - if (size < 0) - return -1; + if (size < 0) { + ret = AVERROR_INVALIDDATA; + goto end; + } if (!size) { xwma->data_end = INT64_MAX; } else @@ -204,7 +209,8 @@ static int xwma_read_header(AVFormatContext *s) 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); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto end; } st->duration = total_decoded_bytes / bytes_per_sample; @@ -239,9 +245,10 @@ static int xwma_read_header(AVFormatContext *s) st->duration = (size<<3) * st->codec->sample_rate / st->codec->bit_rate; } +end: av_free(dpds_table); - return 0; + return ret; } static int xwma_read_packet(AVFormatContext *s, AVPacket *pkt) diff --git a/libavformat/yuv4mpeg.h b/libavformat/yuv4mpeg.h new file mode 100644 index 000000000..750f49840 --- /dev/null +++ b/libavformat/yuv4mpeg.h @@ -0,0 +1,27 @@ +/* + * YUV4MPEG common definitions + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_YUV4MPEG_H +#define AVFORMAT_YUV4MPEG_H + +#define Y4M_MAGIC "YUV4MPEG2" +#define Y4M_FRAME_MAGIC "FRAME" + +#endif /* AVFORMAT_YUV4MPEG_H */ diff --git a/libavformat/yuv4mpeg.c b/libavformat/yuv4mpegdec.c similarity index 54% rename from libavformat/yuv4mpeg.c rename to libavformat/yuv4mpegdec.c index bc07b4c55..c02b2911b 100644 --- a/libavformat/yuv4mpeg.c +++ b/libavformat/yuv4mpegdec.c @@ -1,5 +1,5 @@ /* - * YUV4MPEG format + * YUV4MPEG demuxer * Copyright (c) 2001, 2002, 2003 Fabrice Bellard * * This file is part of FFmpeg. @@ -19,297 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/pixdesc.h" #include "avformat.h" #include "internal.h" - -#define Y4M_MAGIC "YUV4MPEG2" -#define Y4M_FRAME_MAGIC "FRAME" -#define Y4M_LINE_MAX 256 - -#if CONFIG_YUV4MPEGPIPE_MUXER -static int yuv4_generate_header(AVFormatContext *s, char* buf) -{ - AVStream *st; - int width, height; - int raten, rated, aspectn, aspectd, n; - char inter; - const char *colorspace = ""; - - st = s->streams[0]; - width = st->codec->width; - height = st->codec->height; - - av_reduce(&raten, &rated, st->codec->time_base.den, - st->codec->time_base.num, (1UL << 31) - 1); - - aspectn = st->sample_aspect_ratio.num; - aspectd = st->sample_aspect_ratio.den; - - if (aspectn == 0 && aspectd == 1) - aspectd = 0; // 0:0 means unknown - - inter = 'p'; /* progressive is the default */ - if (st->codec->coded_frame && st->codec->coded_frame->interlaced_frame) - inter = st->codec->coded_frame->top_field_first ? 't' : 'b'; - if (st->codec->field_order == AV_FIELD_PROGRESSIVE) { - inter = 'p'; - } else if (st->codec->field_order == AV_FIELD_TB || st->codec->field_order == AV_FIELD_TT) { - inter = 't'; - } else if (st->codec->field_order == AV_FIELD_BT || st->codec->field_order == AV_FIELD_BB) { - inter = 'b'; - } - - switch (st->codec->pix_fmt) { - case AV_PIX_FMT_GRAY8: - colorspace = " Cmono"; - break; - case AV_PIX_FMT_GRAY16: - colorspace = " Cmono16"; - break; - case AV_PIX_FMT_YUV411P: - colorspace = " C411 XYSCSS=411"; - break; - case AV_PIX_FMT_YUV420P: - switch (st->codec->chroma_sample_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; - } - break; - case AV_PIX_FMT_YUV422P: - colorspace = " C422 XYSCSS=422"; - break; - case AV_PIX_FMT_YUV444P: - colorspace = " C444 XYSCSS=444"; - break; - case AV_PIX_FMT_YUV420P9: - colorspace = " C420p9 XYSCSS=420P9"; - break; - case AV_PIX_FMT_YUV422P9: - colorspace = " C422p9 XYSCSS=422P9"; - break; - case AV_PIX_FMT_YUV444P9: - colorspace = " C444p9 XYSCSS=444P9"; - break; - case AV_PIX_FMT_YUV420P10: - colorspace = " C420p10 XYSCSS=420P10"; - break; - case AV_PIX_FMT_YUV422P10: - colorspace = " C422p10 XYSCSS=422P10"; - break; - case AV_PIX_FMT_YUV444P10: - colorspace = " C444p10 XYSCSS=444P10"; - break; - case AV_PIX_FMT_YUV420P12: - colorspace = " C420p12 XYSCSS=420P12"; - break; - case AV_PIX_FMT_YUV422P12: - colorspace = " C422p12 XYSCSS=422P12"; - break; - case AV_PIX_FMT_YUV444P12: - colorspace = " C444p12 XYSCSS=444P12"; - break; - case AV_PIX_FMT_YUV420P14: - colorspace = " C420p14 XYSCSS=420P14"; - break; - case AV_PIX_FMT_YUV422P14: - colorspace = " C422p14 XYSCSS=422P14"; - break; - case AV_PIX_FMT_YUV444P14: - colorspace = " C444p14 XYSCSS=444P14"; - break; - case AV_PIX_FMT_YUV420P16: - colorspace = " C420p16 XYSCSS=420P16"; - break; - case AV_PIX_FMT_YUV422P16: - colorspace = " C422p16 XYSCSS=422P16"; - break; - case AV_PIX_FMT_YUV444P16: - colorspace = " C444p16 XYSCSS=444P16"; - break; - } - - /* construct stream header, if this is the first frame */ - n = snprintf(buf, Y4M_LINE_MAX, "%s W%d H%d F%d:%d I%c A%d:%d%s\n", - Y4M_MAGIC, width, height, raten, rated, inter, - aspectn, aspectd, colorspace); - - return n; -} - -static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) -{ - AVStream *st = s->streams[pkt->stream_index]; - AVIOContext *pb = s->pb; - AVPicture *picture, picture_tmp; - int* first_pkt = s->priv_data; - int width, height, h_chroma_shift, v_chroma_shift; - int i; - char buf2[Y4M_LINE_MAX + 1]; - char buf1[20]; - uint8_t *ptr, *ptr1, *ptr2; - - memcpy(&picture_tmp, pkt->data, sizeof(AVPicture)); - picture = &picture_tmp; - - /* for the first packet we have to output the header as well */ - if (*first_pkt) { - *first_pkt = 0; - if (yuv4_generate_header(s, buf2) < 0) { - av_log(s, AV_LOG_ERROR, - "Error. YUV4MPEG stream header write failed.\n"); - return AVERROR(EIO); - } else { - avio_write(pb, buf2, strlen(buf2)); - } - } - - /* construct frame header */ - - snprintf(buf1, sizeof(buf1), "%s\n", Y4M_FRAME_MAGIC); - avio_write(pb, buf1, strlen(buf1)); - - width = st->codec->width; - height = st->codec->height; - - ptr = picture->data[0]; - - switch (st->codec->pix_fmt) { - case AV_PIX_FMT_GRAY8: - case AV_PIX_FMT_YUV411P: - case AV_PIX_FMT_YUV420P: - case AV_PIX_FMT_YUV422P: - case AV_PIX_FMT_YUV444P: - break; - case AV_PIX_FMT_GRAY16: - case AV_PIX_FMT_YUV420P9: - case AV_PIX_FMT_YUV422P9: - case AV_PIX_FMT_YUV444P9: - case AV_PIX_FMT_YUV420P10: - case AV_PIX_FMT_YUV422P10: - case AV_PIX_FMT_YUV444P10: - case AV_PIX_FMT_YUV420P12: - case AV_PIX_FMT_YUV422P12: - case AV_PIX_FMT_YUV444P12: - case AV_PIX_FMT_YUV420P14: - case AV_PIX_FMT_YUV422P14: - case AV_PIX_FMT_YUV444P14: - case AV_PIX_FMT_YUV420P16: - case AV_PIX_FMT_YUV422P16: - case AV_PIX_FMT_YUV444P16: - width *= 2; - break; - default: - av_log(s, AV_LOG_ERROR, "The pixel format '%s' is not supported.\n", - av_get_pix_fmt_name(st->codec->pix_fmt)); - return AVERROR(EINVAL); - } - - for (i = 0; i < height; i++) { - avio_write(pb, ptr, width); - ptr += picture->linesize[0]; - } - - if (st->codec->pix_fmt != AV_PIX_FMT_GRAY8 && - st->codec->pix_fmt != AV_PIX_FMT_GRAY16) { - // Adjust for smaller Cb and Cr planes - av_pix_fmt_get_chroma_sub_sample(st->codec->pix_fmt, &h_chroma_shift, - &v_chroma_shift); - width = FF_CEIL_RSHIFT(width, h_chroma_shift); - height = FF_CEIL_RSHIFT(height, v_chroma_shift); - - ptr1 = picture->data[1]; - ptr2 = picture->data[2]; - for (i = 0; i < height; i++) { /* Cb */ - avio_write(pb, ptr1, width); - ptr1 += picture->linesize[1]; - } - for (i = 0; i < height; i++) { /* Cr */ - avio_write(pb, ptr2, width); - ptr2 += picture->linesize[2]; - } - } - - return 0; -} - -static int yuv4_write_header(AVFormatContext *s) -{ - int *first_pkt = s->priv_data; - - 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"); - return AVERROR_INVALIDDATA; - } - - switch (s->streams[0]->codec->pix_fmt) { - case AV_PIX_FMT_YUV411P: - av_log(s, AV_LOG_WARNING, "Warning: generating rarely used 4:1:1 YUV " - "stream, some mjpegtools might not work.\n"); - break; - case AV_PIX_FMT_GRAY8: - case AV_PIX_FMT_GRAY16: - case AV_PIX_FMT_YUV420P: - case AV_PIX_FMT_YUV422P: - case AV_PIX_FMT_YUV444P: - break; - case AV_PIX_FMT_YUV420P9: - case AV_PIX_FMT_YUV422P9: - case AV_PIX_FMT_YUV444P9: - case AV_PIX_FMT_YUV420P10: - case AV_PIX_FMT_YUV422P10: - case AV_PIX_FMT_YUV444P10: - case AV_PIX_FMT_YUV420P12: - case AV_PIX_FMT_YUV422P12: - case AV_PIX_FMT_YUV444P12: - case AV_PIX_FMT_YUV420P14: - case AV_PIX_FMT_YUV422P14: - case AV_PIX_FMT_YUV444P14: - case AV_PIX_FMT_YUV420P16: - case AV_PIX_FMT_YUV422P16: - case AV_PIX_FMT_YUV444P16: - if (s->streams[0]->codec->strict_std_compliance >= FF_COMPLIANCE_NORMAL) { - av_log(s, AV_LOG_ERROR, "'%s' is not a official yuv4mpegpipe pixel format. " - "Use '-strict -1' to encode to this pixel format.\n", - av_get_pix_fmt_name(s->streams[0]->codec->pix_fmt)); - return AVERROR(EINVAL); - } - av_log(s, AV_LOG_WARNING, "Warning: generating non standard YUV stream. " - "Mjpegtools will not work.\n"); - break; - default: - av_log(s, AV_LOG_ERROR, "ERROR: yuv4mpeg can only handle " - "yuv444p, yuv422p, yuv420p, yuv411p and gray8 pixel formats. " - "And using 'strict -1' also yuv444p9, yuv422p9, yuv420p9, " - "yuv444p10, yuv422p10, yuv420p10, " - "yuv444p12, yuv422p12, yuv420p12, " - "yuv444p14, yuv422p14, yuv420p14, " - "yuv444p16, yuv422p16, yuv420p16 " - "and gray16 pixel formats. " - "Use -pix_fmt to select one.\n"); - return AVERROR(EIO); - } - - *first_pkt = 1; - return 0; -} - -AVOutputFormat ff_yuv4mpegpipe_muxer = { - .name = "yuv4mpegpipe", - .long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"), - .extensions = "y4m", - .priv_data_size = sizeof(int), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_RAWVIDEO, - .write_header = yuv4_write_header, - .write_packet = yuv4_write_packet, - .flags = AVFMT_RAWPICTURE, -}; -#endif +#include "yuv4mpeg.h" /* Header size increased to allow room for optional flags */ #define MAX_YUV4_HEADER 80 @@ -319,7 +31,7 @@ static int yuv4_read_header(AVFormatContext *s) { char header[MAX_YUV4_HEADER + 10]; // Include headroom for // the longest option - char *tokstart, *tokend, *header_end, interlaced = '?'; + char *tokstart, *tokend, *header_end; int i; AVIOContext *pb = s->pb; int width = -1, height = -1, raten = 0, @@ -327,6 +39,7 @@ static int yuv4_read_header(AVFormatContext *s) enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE, alt_pix_fmt = AV_PIX_FMT_NONE; enum AVChromaLocation chroma_sample_location = AVCHROMA_LOC_UNSPECIFIED; AVStream *st; + enum AVFieldOrder field_order; for (i = 0; i < MAX_YUV4_HEADER; i++) { header[i] = avio_r8(pb); @@ -422,7 +135,26 @@ static int yuv4_read_header(AVFormatContext *s) tokstart++; break; case 'I': // Interlace type - interlaced = *tokstart++; + switch (*tokstart++){ + case '?': + field_order = AV_FIELD_UNKNOWN; + break; + case 'p': + field_order = AV_FIELD_PROGRESSIVE; + break; + case 't': + field_order = AV_FIELD_TT; + break; + case 'b': + field_order = AV_FIELD_BB; + break; + case 'm': + av_log(s, AV_LOG_ERROR, "YUV4MPEG stream contains mixed " + "interlaced and non-interlaced frames.\n"); + default: + av_log(s, AV_LOG_ERROR, "YUV4MPEG has invalid header.\n"); + return AVERROR(EINVAL); + } break; case 'F': // Frame rate sscanf(tokstart, "%d:%d", &raten, &rated); // 0:0 if unknown @@ -523,27 +255,7 @@ static int yuv4_read_header(AVFormatContext *s) st->codec->codec_id = AV_CODEC_ID_RAWVIDEO; st->sample_aspect_ratio = (AVRational){ aspectn, aspectd }; st->codec->chroma_sample_location = chroma_sample_location; - - switch (interlaced){ - case 'p': - st->codec->field_order = AV_FIELD_PROGRESSIVE; - break; - case 't': - st->codec->field_order = AV_FIELD_TB; - break; - case 'b': - st->codec->field_order = AV_FIELD_BT; - break; - case 'm': - av_log(s, AV_LOG_ERROR, "YUV4MPEG stream contains mixed " - "interlaced and non-interlaced frames.\n"); - case '?': - st->codec->field_order = AV_FIELD_UNKNOWN; - break; - default: - av_log(s, AV_LOG_ERROR, "YUV4MPEG has invalid header.\n"); - return AVERROR(EINVAL); - } + st->codec->field_order = field_order; return 0; } @@ -598,7 +310,6 @@ static int yuv4_probe(AVProbeData *pd) return 0; } -#if CONFIG_YUV4MPEGPIPE_DEMUXER AVInputFormat ff_yuv4mpegpipe_demuxer = { .name = "yuv4mpegpipe", .long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"), @@ -607,4 +318,3 @@ AVInputFormat ff_yuv4mpegpipe_demuxer = { .read_packet = yuv4_read_packet, .extensions = "y4m", }; -#endif diff --git a/libavformat/yuv4mpegenc.c b/libavformat/yuv4mpegenc.c new file mode 100644 index 000000000..a7f2d8ae9 --- /dev/null +++ b/libavformat/yuv4mpegenc.c @@ -0,0 +1,307 @@ +/* + * YUV4MPEG muxer + * Copyright (c) 2001, 2002, 2003 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/pixdesc.h" +#include "avformat.h" +#include "internal.h" +#include "yuv4mpeg.h" + +#define Y4M_LINE_MAX 256 + +static int yuv4_generate_header(AVFormatContext *s, char* buf) +{ + AVStream *st; + int width, height; + int raten, rated, aspectn, aspectd, n; + char inter; + const char *colorspace = ""; + + st = s->streams[0]; + width = st->codec->width; + height = st->codec->height; + + // TODO: should be avg_frame_rate + av_reduce(&raten, &rated, st->time_base.den, + st->time_base.num, (1UL << 31) - 1); + + aspectn = st->sample_aspect_ratio.num; + aspectd = st->sample_aspect_ratio.den; + + if (aspectn == 0 && aspectd == 1) + aspectd = 0; // 0:0 means unknown + + switch (st->codec->field_order) { + case AV_FIELD_TB: + case AV_FIELD_TT: inter = 't'; break; + case AV_FIELD_BT: + case AV_FIELD_BB: inter = 'b'; break; + default: inter = 'p'; break; + } + + switch (st->codec->pix_fmt) { + case AV_PIX_FMT_GRAY8: + colorspace = " Cmono"; + break; + case AV_PIX_FMT_GRAY16: + colorspace = " Cmono16"; + break; + case AV_PIX_FMT_YUV411P: + colorspace = " C411 XYSCSS=411"; + break; + case AV_PIX_FMT_YUV420P: + switch (st->codec->chroma_sample_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; + } + break; + case AV_PIX_FMT_YUV422P: + colorspace = " C422 XYSCSS=422"; + break; + case AV_PIX_FMT_YUV444P: + colorspace = " C444 XYSCSS=444"; + break; + case AV_PIX_FMT_YUV420P9: + colorspace = " C420p9 XYSCSS=420P9"; + break; + case AV_PIX_FMT_YUV422P9: + colorspace = " C422p9 XYSCSS=422P9"; + break; + case AV_PIX_FMT_YUV444P9: + colorspace = " C444p9 XYSCSS=444P9"; + break; + case AV_PIX_FMT_YUV420P10: + colorspace = " C420p10 XYSCSS=420P10"; + break; + case AV_PIX_FMT_YUV422P10: + colorspace = " C422p10 XYSCSS=422P10"; + break; + case AV_PIX_FMT_YUV444P10: + colorspace = " C444p10 XYSCSS=444P10"; + break; + case AV_PIX_FMT_YUV420P12: + colorspace = " C420p12 XYSCSS=420P12"; + break; + case AV_PIX_FMT_YUV422P12: + colorspace = " C422p12 XYSCSS=422P12"; + break; + case AV_PIX_FMT_YUV444P12: + colorspace = " C444p12 XYSCSS=444P12"; + break; + case AV_PIX_FMT_YUV420P14: + colorspace = " C420p14 XYSCSS=420P14"; + break; + case AV_PIX_FMT_YUV422P14: + colorspace = " C422p14 XYSCSS=422P14"; + break; + case AV_PIX_FMT_YUV444P14: + colorspace = " C444p14 XYSCSS=444P14"; + break; + case AV_PIX_FMT_YUV420P16: + colorspace = " C420p16 XYSCSS=420P16"; + break; + case AV_PIX_FMT_YUV422P16: + colorspace = " C422p16 XYSCSS=422P16"; + break; + case AV_PIX_FMT_YUV444P16: + colorspace = " C444p16 XYSCSS=444P16"; + break; + } + + /* construct stream header, if this is the first frame */ + n = snprintf(buf, Y4M_LINE_MAX, "%s W%d H%d F%d:%d I%c A%d:%d%s\n", + Y4M_MAGIC, width, height, raten, rated, inter, + aspectn, aspectd, colorspace); + + return n; +} + +static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVStream *st = s->streams[pkt->stream_index]; + AVIOContext *pb = s->pb; + AVPicture *picture, picture_tmp; + int* first_pkt = s->priv_data; + int width, height, h_chroma_shift, v_chroma_shift; + int i; + char buf2[Y4M_LINE_MAX + 1]; + char buf1[20]; + uint8_t *ptr, *ptr1, *ptr2; + + memcpy(&picture_tmp, pkt->data, sizeof(AVPicture)); + picture = &picture_tmp; + + /* for the first packet we have to output the header as well */ + if (*first_pkt) { + *first_pkt = 0; + if (yuv4_generate_header(s, buf2) < 0) { + av_log(s, AV_LOG_ERROR, + "Error. YUV4MPEG stream header write failed.\n"); + return AVERROR(EIO); + } else { + avio_write(pb, buf2, strlen(buf2)); + } + } + + /* construct frame header */ + + snprintf(buf1, sizeof(buf1), "%s\n", Y4M_FRAME_MAGIC); + avio_write(pb, buf1, strlen(buf1)); + + width = st->codec->width; + height = st->codec->height; + + ptr = picture->data[0]; + + switch (st->codec->pix_fmt) { + case AV_PIX_FMT_GRAY8: + case AV_PIX_FMT_YUV411P: + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV444P: + break; + case AV_PIX_FMT_GRAY16: + case AV_PIX_FMT_YUV420P9: + case AV_PIX_FMT_YUV422P9: + case AV_PIX_FMT_YUV444P9: + case AV_PIX_FMT_YUV420P10: + case AV_PIX_FMT_YUV422P10: + case AV_PIX_FMT_YUV444P10: + case AV_PIX_FMT_YUV420P12: + case AV_PIX_FMT_YUV422P12: + case AV_PIX_FMT_YUV444P12: + case AV_PIX_FMT_YUV420P14: + case AV_PIX_FMT_YUV422P14: + case AV_PIX_FMT_YUV444P14: + case AV_PIX_FMT_YUV420P16: + case AV_PIX_FMT_YUV422P16: + case AV_PIX_FMT_YUV444P16: + width *= 2; + break; + default: + av_log(s, AV_LOG_ERROR, "The pixel format '%s' is not supported.\n", + av_get_pix_fmt_name(st->codec->pix_fmt)); + return AVERROR(EINVAL); + } + + for (i = 0; i < height; i++) { + avio_write(pb, ptr, width); + ptr += picture->linesize[0]; + } + + if (st->codec->pix_fmt != AV_PIX_FMT_GRAY8 && + st->codec->pix_fmt != AV_PIX_FMT_GRAY16) { + // Adjust for smaller Cb and Cr planes + av_pix_fmt_get_chroma_sub_sample(st->codec->pix_fmt, &h_chroma_shift, + &v_chroma_shift); + width = FF_CEIL_RSHIFT(width, h_chroma_shift); + height = FF_CEIL_RSHIFT(height, v_chroma_shift); + + ptr1 = picture->data[1]; + ptr2 = picture->data[2]; + for (i = 0; i < height; i++) { /* Cb */ + avio_write(pb, ptr1, width); + ptr1 += picture->linesize[1]; + } + for (i = 0; i < height; i++) { /* Cr */ + avio_write(pb, ptr2, width); + ptr2 += picture->linesize[2]; + } + } + + return 0; +} + +static int yuv4_write_header(AVFormatContext *s) +{ + int *first_pkt = s->priv_data; + + 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"); + return AVERROR_INVALIDDATA; + } + + switch (s->streams[0]->codec->pix_fmt) { + case AV_PIX_FMT_YUV411P: + av_log(s, AV_LOG_WARNING, "Warning: generating rarely used 4:1:1 YUV " + "stream, some mjpegtools might not work.\n"); + break; + case AV_PIX_FMT_GRAY8: + case AV_PIX_FMT_GRAY16: + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV444P: + break; + case AV_PIX_FMT_YUV420P9: + case AV_PIX_FMT_YUV422P9: + case AV_PIX_FMT_YUV444P9: + case AV_PIX_FMT_YUV420P10: + case AV_PIX_FMT_YUV422P10: + case AV_PIX_FMT_YUV444P10: + case AV_PIX_FMT_YUV420P12: + case AV_PIX_FMT_YUV422P12: + case AV_PIX_FMT_YUV444P12: + case AV_PIX_FMT_YUV420P14: + case AV_PIX_FMT_YUV422P14: + case AV_PIX_FMT_YUV444P14: + case AV_PIX_FMT_YUV420P16: + case AV_PIX_FMT_YUV422P16: + case AV_PIX_FMT_YUV444P16: + if (s->streams[0]->codec->strict_std_compliance >= FF_COMPLIANCE_NORMAL) { + av_log(s, AV_LOG_ERROR, "'%s' is not a official yuv4mpegpipe pixel format. " + "Use '-strict -1' to encode to this pixel format.\n", + av_get_pix_fmt_name(s->streams[0]->codec->pix_fmt)); + return AVERROR(EINVAL); + } + av_log(s, AV_LOG_WARNING, "Warning: generating non standard YUV stream. " + "Mjpegtools will not work.\n"); + break; + default: + av_log(s, AV_LOG_ERROR, "ERROR: yuv4mpeg can only handle " + "yuv444p, yuv422p, yuv420p, yuv411p and gray8 pixel formats. " + "And using 'strict -1' also yuv444p9, yuv422p9, yuv420p9, " + "yuv444p10, yuv422p10, yuv420p10, " + "yuv444p12, yuv422p12, yuv420p12, " + "yuv444p14, yuv422p14, yuv420p14, " + "yuv444p16, yuv422p16, yuv420p16 " + "and gray16 pixel formats. " + "Use -pix_fmt to select one.\n"); + return AVERROR(EIO); + } + + *first_pkt = 1; + return 0; +} + +AVOutputFormat ff_yuv4mpegpipe_muxer = { + .name = "yuv4mpegpipe", + .long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"), + .extensions = "y4m", + .priv_data_size = sizeof(int), + .audio_codec = AV_CODEC_ID_NONE, + .video_codec = AV_CODEC_ID_RAWVIDEO, + .write_header = yuv4_write_header, + .write_packet = yuv4_write_packet, + .flags = AVFMT_RAWPICTURE, +}; diff --git a/libavresample/Makefile b/libavresample/Makefile index bca23a984..7d857a0e3 100644 --- a/libavresample/Makefile +++ b/libavresample/Makefile @@ -1,5 +1,4 @@ NAME = avresample -FFLIBS = avutil HEADERS = avresample.h \ version.h \ diff --git a/libavresample/aarch64/Makefile b/libavresample/aarch64/Makefile index 13ba193a4..1d9e5f8ca 100644 --- a/libavresample/aarch64/Makefile +++ b/libavresample/aarch64/Makefile @@ -1 +1,7 @@ +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 \ diff --git a/libavresample/aarch64/asm-offsets.h b/libavresample/aarch64/asm-offsets.h new file mode 100644 index 000000000..0b582446f --- /dev/null +++ b/libavresample/aarch64/asm-offsets.h @@ -0,0 +1,28 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVRESAMPLE_AARCH64_ASM_OFFSETS_H +#define AVRESAMPLE_AARCH64_ASM_OFFSETS_H + +/* struct ResampleContext */ +#define FILTER_BANK 0x10 +#define FILTER_LENGTH 0x18 +#define PHASE_SHIFT 0x34 +#define PHASE_MASK (PHASE_SHIFT + 0x04) // loaded as pair + +#endif /* AVRESAMPLE_AARCH64_ASM_OFFSETS_H */ diff --git a/libavresample/aarch64/audio_convert_init.c b/libavresample/aarch64/audio_convert_init.c new file mode 100644 index 000000000..b5b0d1eee --- /dev/null +++ b/libavresample/aarch64/audio_convert_init.c @@ -0,0 +1,49 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/aarch64/cpu.h" +#include "libavutil/samplefmt.h" +#include "libavresample/audio_convert.h" + +void ff_conv_flt_to_s16_neon(int16_t *dst, const float *src, int len); +void ff_conv_fltp_to_s16_neon(int16_t *dst, float *const *src, + int len, int channels); +void ff_conv_fltp_to_s16_2ch_neon(int16_t *dst, float *const *src, + int len, int channels); + +av_cold void ff_audio_convert_init_aarch64(AudioConvert *ac) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT, + 0, 16, 8, "NEON", + ff_conv_flt_to_s16_neon); + ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLTP, + 2, 16, 8, "NEON", + ff_conv_fltp_to_s16_2ch_neon); + ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLTP, + 0, 16, 8, "NEON", + ff_conv_fltp_to_s16_neon); + } +} diff --git a/libavresample/aarch64/audio_convert_neon.S b/libavresample/aarch64/audio_convert_neon.S new file mode 100644 index 000000000..e13e277e6 --- /dev/null +++ b/libavresample/aarch64/audio_convert_neon.S @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2008 Mans Rullgard + * Copyright (c) 2014 Janne Grunau + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/aarch64/asm.S" + +function ff_conv_flt_to_s16_neon, export=1 + subs x2, x2, #8 + ld1 {v0.4s}, [x1], #16 + fcvtzs v4.4s, v0.4s, #31 + ld1 {v1.4s}, [x1], #16 + fcvtzs v5.4s, v1.4s, #31 + b.eq 3f + ands x12, x2, #~15 + b.eq 2f +1: subs x12, x12, #16 + sqrshrn v4.4h, v4.4s, #16 + ld1 {v2.4s}, [x1], #16 + fcvtzs v6.4s, v2.4s, #31 + sqrshrn2 v4.8h, v5.4s, #16 + ld1 {v3.4s}, [x1], #16 + fcvtzs v7.4s, v3.4s, #31 + sqrshrn v6.4h, v6.4s, #16 + st1 {v4.8h}, [x0], #16 + sqrshrn2 v6.8h, v7.4s, #16 + ld1 {v0.4s}, [x1], #16 + fcvtzs v4.4s, v0.4s, #31 + ld1 {v1.4s}, [x1], #16 + fcvtzs v5.4s, v1.4s, #31 + st1 {v6.8h}, [x0], #16 + b.ne 1b + ands x2, x2, #15 + b.eq 3f +2: ld1 {v2.4s}, [x1], #16 + sqrshrn v4.4h, v4.4s, #16 + fcvtzs v6.4s, v2.4s, #31 + ld1 {v3.4s}, [x1], #16 + sqrshrn2 v4.8h, v5.4s, #16 + fcvtzs v7.4s, v3.4s, #31 + sqrshrn v6.4h, v6.4s, #16 + st1 {v4.8h}, [x0], #16 + sqrshrn2 v6.8h, v7.4s, #16 + st1 {v6.8h}, [x0] + ret +3: sqrshrn v4.4h, v4.4s, #16 + sqrshrn2 v4.8h, v5.4s, #16 + st1 {v4.8h}, [x0] + ret +endfunc + +function ff_conv_fltp_to_s16_2ch_neon, export=1 + ldp x4, x5, [x1] + subs x2, x2, #8 + ld1 {v0.4s}, [x4], #16 + fcvtzs v4.4s, v0.4s, #31 + ld1 {v1.4s}, [x4], #16 + fcvtzs v5.4s, v1.4s, #31 + ld1 {v2.4s}, [x5], #16 + fcvtzs v6.4s, v2.4s, #31 + ld1 {v3.4s}, [x5], #16 + fcvtzs v7.4s, v3.4s, #31 + b.eq 3f + ands x12, x2, #~15 + b.eq 2f +1: subs x12, x12, #16 + ld1 {v16.4s}, [x4], #16 + fcvtzs v20.4s, v16.4s, #31 + sri v6.4s, v4.4s, #16 + ld1 {v17.4s}, [x4], #16 + fcvtzs v21.4s, v17.4s, #31 + ld1 {v18.4s}, [x5], #16 + fcvtzs v22.4s, v18.4s, #31 + ld1 {v19.4s}, [x5], #16 + sri v7.4s, v5.4s, #16 + st1 {v6.4s}, [x0], #16 + fcvtzs v23.4s, v19.4s, #31 + st1 {v7.4s}, [x0], #16 + sri v22.4s, v20.4s, #16 + ld1 {v0.4s}, [x4], #16 + sri v23.4s, v21.4s, #16 + st1 {v22.4s}, [x0], #16 + fcvtzs v4.4s, v0.4s, #31 + ld1 {v1.4s}, [x4], #16 + fcvtzs v5.4s, v1.4s, #31 + ld1 {v2.4s}, [x5], #16 + fcvtzs v6.4s, v2.4s, #31 + ld1 {v3.4s}, [x5], #16 + fcvtzs v7.4s, v3.4s, #31 + st1 {v23.4s}, [x0], #16 + b.ne 1b + ands x2, x2, #15 + b.eq 3f +2: sri v6.4s, v4.4s, #16 + ld1 {v0.4s}, [x4], #16 + fcvtzs v0.4s, v0.4s, #31 + ld1 {v1.4s}, [x4], #16 + fcvtzs v1.4s, v1.4s, #31 + ld1 {v2.4s}, [x5], #16 + fcvtzs v2.4s, v2.4s, #31 + sri v7.4s, v5.4s, #16 + ld1 {v3.4s}, [x5], #16 + fcvtzs v3.4s, v3.4s, #31 + sri v2.4s, v0.4s, #16 + st1 {v6.4s,v7.4s}, [x0], #32 + sri v3.4s, v1.4s, #16 + st1 {v2.4s,v3.4s}, [x0], #32 + ret +3: sri v6.4s, v4.4s, #16 + sri v7.4s, v5.4s, #16 + st1 {v6.4s,v7.4s}, [x0] + ret +endfunc + +function ff_conv_fltp_to_s16_neon, export=1 + cmp w3, #2 + b.eq X(ff_conv_fltp_to_s16_2ch_neon) + b.gt 1f + ldr x1, [x1] + b X(ff_conv_flt_to_s16_neon) +1: + cmp w3, #4 + lsl x12, x3, #1 + b.lt 4f + +5: // 4 channels + ldp x4, x5, [x1], #16 + ldp x6, x7, [x1], #16 + mov w9, w2 + mov x8, x0 + ld1 {v4.4s}, [x4], #16 + fcvtzs v4.4s, v4.4s, #31 + ld1 {v5.4s}, [x5], #16 + fcvtzs v5.4s, v5.4s, #31 + ld1 {v6.4s}, [x6], #16 + fcvtzs v6.4s, v6.4s, #31 + ld1 {v7.4s}, [x7], #16 + fcvtzs v7.4s, v7.4s, #31 +6: + subs w9, w9, #8 + ld1 {v0.4s}, [x4], #16 + fcvtzs v0.4s, v0.4s, #31 + sri v5.4s, v4.4s, #16 + ld1 {v1.4s}, [x5], #16 + fcvtzs v1.4s, v1.4s, #31 + sri v7.4s, v6.4s, #16 + ld1 {v2.4s}, [x6], #16 + fcvtzs v2.4s, v2.4s, #31 + zip1 v16.4s, v5.4s, v7.4s + ld1 {v3.4s}, [x7], #16 + fcvtzs v3.4s, v3.4s, #31 + zip2 v17.4s, v5.4s, v7.4s + st1 {v16.d}[0], [x8], x12 + sri v1.4s, v0.4s, #16 + st1 {v16.d}[1], [x8], x12 + sri v3.4s, v2.4s, #16 + st1 {v17.d}[0], [x8], x12 + zip1 v18.4s, v1.4s, v3.4s + st1 {v17.d}[1], [x8], x12 + zip2 v19.4s, v1.4s, v3.4s + b.eq 7f + ld1 {v4.4s}, [x4], #16 + fcvtzs v4.4s, v4.4s, #31 + st1 {v18.d}[0], [x8], x12 + ld1 {v5.4s}, [x5], #16 + fcvtzs v5.4s, v5.4s, #31 + st1 {v18.d}[1], [x8], x12 + ld1 {v6.4s}, [x6], #16 + fcvtzs v6.4s, v6.4s, #31 + st1 {v19.d}[0], [x8], x12 + ld1 {v7.4s}, [x7], #16 + fcvtzs v7.4s, v7.4s, #31 + st1 {v19.d}[1], [x8], x12 + b 6b +7: + st1 {v18.d}[0], [x8], x12 + st1 {v18.d}[1], [x8], x12 + st1 {v19.d}[0], [x8], x12 + st1 {v19.d}[1], [x8], x12 + subs w3, w3, #4 + b.eq end + cmp w3, #4 + add x0, x0, #8 + b.ge 5b + +4: // 2 channels + cmp w3, #2 + b.lt 4f + ldp x4, x5, [x1], #16 + mov w9, w2 + mov x8, x0 + tst w9, #8 + ld1 {v4.4s}, [x4], #16 + fcvtzs v4.4s, v4.4s, #31 + ld1 {v5.4s}, [x5], #16 + fcvtzs v5.4s, v5.4s, #31 + ld1 {v6.4s}, [x4], #16 + fcvtzs v6.4s, v6.4s, #31 + ld1 {v7.4s}, [x5], #16 + fcvtzs v7.4s, v7.4s, #31 + b.eq 6f + subs w9, w9, #8 + b.eq 7f + sri v5.4s, v4.4s, #16 + ld1 {v4.4s}, [x4], #16 + fcvtzs v4.4s, v4.4s, #31 + st1 {v5.s}[0], [x8], x12 + sri v7.4s, v6.4s, #16 + st1 {v5.s}[1], [x8], x12 + ld1 {v6.4s}, [x4], #16 + fcvtzs v6.4s, v6.4s, #31 + st1 {v5.s}[2], [x8], x12 + st1 {v5.s}[3], [x8], x12 + st1 {v7.s}[0], [x8], x12 + st1 {v7.s}[1], [x8], x12 + ld1 {v5.4s}, [x5], #16 + fcvtzs v5.4s, v5.4s, #31 + st1 {v7.s}[2], [x8], x12 + st1 {v7.s}[3], [x8], x12 + ld1 {v7.4s}, [x5], #16 + fcvtzs v7.4s, v7.4s, #31 +6: + subs w9, w9, #16 + ld1 {v0.4s}, [x4], #16 + sri v5.4s, v4.4s, #16 + fcvtzs v0.4s, v0.4s, #31 + ld1 {v1.4s}, [x5], #16 + sri v7.4s, v6.4s, #16 + st1 {v5.s}[0], [x8], x12 + st1 {v5.s}[1], [x8], x12 + fcvtzs v1.4s, v1.4s, #31 + st1 {v5.s}[2], [x8], x12 + st1 {v5.s}[3], [x8], x12 + ld1 {v2.4s}, [x4], #16 + st1 {v7.s}[0], [x8], x12 + fcvtzs v2.4s, v2.4s, #31 + st1 {v7.s}[1], [x8], x12 + ld1 {v3.4s}, [x5], #16 + st1 {v7.s}[2], [x8], x12 + fcvtzs v3.4s, v3.4s, #31 + st1 {v7.s}[3], [x8], x12 + sri v1.4s, v0.4s, #16 + sri v3.4s, v2.4s, #16 + b.eq 6f + ld1 {v4.4s}, [x4], #16 + st1 {v1.s}[0], [x8], x12 + fcvtzs v4.4s, v4.4s, #31 + st1 {v1.s}[1], [x8], x12 + ld1 {v5.4s}, [x5], #16 + st1 {v1.s}[2], [x8], x12 + fcvtzs v5.4s, v5.4s, #31 + st1 {v1.s}[3], [x8], x12 + ld1 {v6.4s}, [x4], #16 + st1 {v3.s}[0], [x8], x12 + fcvtzs v6.4s, v6.4s, #31 + st1 {v3.s}[1], [x8], x12 + ld1 {v7.4s}, [x5], #16 + st1 {v3.s}[2], [x8], x12 + fcvtzs v7.4s, v7.4s, #31 + st1 {v3.s}[3], [x8], x12 + b.gt 6b +6: + st1 {v1.s}[0], [x8], x12 + st1 {v1.s}[1], [x8], x12 + st1 {v1.s}[2], [x8], x12 + st1 {v1.s}[3], [x8], x12 + st1 {v3.s}[0], [x8], x12 + st1 {v3.s}[1], [x8], x12 + st1 {v3.s}[2], [x8], x12 + st1 {v3.s}[3], [x8], x12 + b 8f +7: + sri v5.4s, v4.4s, #16 + sri v7.4s, v6.4s, #16 + st1 {v5.s}[0], [x8], x12 + st1 {v5.s}[1], [x8], x12 + st1 {v5.s}[2], [x8], x12 + st1 {v5.s}[3], [x8], x12 + st1 {v7.s}[0], [x8], x12 + st1 {v7.s}[1], [x8], x12 + st1 {v7.s}[2], [x8], x12 + st1 {v7.s}[3], [x8], x12 +8: + subs w3, w3, #2 + add x0, x0, #4 + b.eq end + +4: // 1 channel + ldr x4, [x1] + tst w2, #8 + mov w9, w2 + mov x5, x0 + ld1 {v0.4s}, [x4], #16 + fcvtzs v0.4s, v0.4s, #31 + ld1 {v1.4s}, [x4], #16 + fcvtzs v1.4s, v1.4s, #31 + b.ne 8f +6: + subs w9, w9, #16 + ld1 {v2.4s}, [x4], #16 + fcvtzs v2.4s, v2.4s, #31 + ld1 {v3.4s}, [x4], #16 + fcvtzs v3.4s, v3.4s, #31 + st1 {v0.h}[1], [x5], x12 + st1 {v0.h}[3], [x5], x12 + st1 {v0.h}[5], [x5], x12 + st1 {v0.h}[7], [x5], x12 + st1 {v1.h}[1], [x5], x12 + st1 {v1.h}[3], [x5], x12 + st1 {v1.h}[5], [x5], x12 + st1 {v1.h}[7], [x5], x12 + b.eq 7f + ld1 {v0.4s}, [x4], #16 + fcvtzs v0.4s, v0.4s, #31 + ld1 {v1.4s}, [x4], #16 + fcvtzs v1.4s, v1.4s, #31 +7: + st1 {v2.h}[1], [x5], x12 + st1 {v2.h}[3], [x5], x12 + st1 {v2.h}[5], [x5], x12 + st1 {v2.h}[7], [x5], x12 + st1 {v3.h}[1], [x5], x12 + st1 {v3.h}[3], [x5], x12 + st1 {v3.h}[5], [x5], x12 + st1 {v3.h}[7], [x5], x12 + b.gt 6b + ret +8: + subs w9, w9, #8 + st1 {v0.h}[1], [x5], x12 + st1 {v0.h}[3], [x5], x12 + st1 {v0.h}[5], [x5], x12 + st1 {v0.h}[7], [x5], x12 + st1 {v1.h}[1], [x5], x12 + st1 {v1.h}[3], [x5], x12 + st1 {v1.h}[5], [x5], x12 + st1 {v1.h}[7], [x5], x12 + b.eq end + ld1 {v0.4s}, [x4], #16 + fcvtzs v0.4s, v0.4s, #31 + ld1 {v1.4s}, [x4], #16 + fcvtzs v1.4s, v1.4s, #31 + b 6b +end: + ret +endfunc diff --git a/libavresample/aarch64/resample_init.c b/libavresample/aarch64/resample_init.c new file mode 100644 index 000000000..d3dfb12a5 --- /dev/null +++ b/libavresample/aarch64/resample_init.c @@ -0,0 +1,71 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" +#include "libavutil/cpu.h" +#include "libavutil/aarch64/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, phase_shift, PHASE_SHIFT); +AV_CHECK_OFFSET(struct ResampleContext, phase_mask, PHASE_MASK); + +void ff_resample_one_dbl_neon(struct ResampleContext *c, void *dst0, + int dst_index, const void *src0, + unsigned int index, int frac); +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_audio_resample_init_aarch64(ResampleContext *c, + enum AVSampleFormat sample_fmt) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + if (!c->linear) { + switch (sample_fmt) { + case AV_SAMPLE_FMT_DBLP: + c->resample_one = ff_resample_one_dbl_neon; + break; + case AV_SAMPLE_FMT_FLTP: + c->resample_one = ff_resample_one_flt_neon; + break; + case AV_SAMPLE_FMT_S16P: + c->resample_one = ff_resample_one_s16_neon; + break; + case AV_SAMPLE_FMT_S32P: + c->resample_one = ff_resample_one_s32_neon; + break; + } + } + } +} diff --git a/libavresample/aarch64/resample_neon.S b/libavresample/aarch64/resample_neon.S new file mode 100644 index 000000000..d3c2cbf56 --- /dev/null +++ b/libavresample/aarch64/resample_neon.S @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2014 Janne Grunau + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" +#include "asm-offsets.h" + +.macro resample_one fmt, es=2 +.ifnc \fmt, dbl + .macro M_MUL2 x:vararg + .endm + .macro M_MLA2 x:vararg + .endm +.endif +function ff_resample_one_\fmt\()_neon, export=1 + sxtw x2, w2 + ldr x9, [x0, #FILTER_BANK] + ldr w6, [x0, #FILTER_LENGTH] + ldp w7, w8, [x0, #PHASE_SHIFT] // and phase_mask + lsr x10, x4, x7 // sample_index + and x4, x4, x8 + lsl x11, x6, #\es // filter_length * elem_size + add x3, x3, x10, lsl #\es // src[sample_index] + madd x9, x11, x4, x9 // filter + cmp w6, #16 + b.lt 5f +8: // remaining filter_length at least 16 + subs w6, w6, #16 + LOAD8 v4, v5, v6, v7, x3 + LOAD8 v16, v17, v18, v19, x9 + M_MUL v0, v4, v16, v1 + M_MUL2 v1, v6, v18 +7: + LOAD8 v20, v21, v22, v23, x3 + M_MLA v0, v5, v17, v1 + M_MLA2 v1, v7, v19 + LOAD8 v24, v25, v26, v27, x9 + M_MLA v0, v20, v24, v1 + M_MLA2 v1, v22, v26 + b.eq 6f + cmp w6, #16 + M_MLA v0, v21, v25, v1 + M_MLA2 v1, v23, v27 + b.lt 4f + subs w6, w6, #16 + LOAD8 v4, v5, v6, v7, x3 + LOAD8 v16, v17, v18, v19, x9 + M_MLA v0, v4, v16, v1 + M_MLA2 v1, v6, v18 + b 7b +6: + M_MLA v0, v21, v25, v1 + M_MLA2 v1, v23, v27 + STORE_ONE 0, x1, x2, v1 + ret +5: + movi v0.16b, #0 + movi v1.16b, #0 +4: // remaining filter_length 1-15 + cmp w6, #4 + b.lt 2f + subs w6, w6, #4 + LOAD4 v4, v5, x3 + LOAD4 v6, v7, x9 + M_MLA v0, v4, v6, v1 + M_MLA2 v1, v5, v7 + b.eq 0f + b 4b +2: // remaining filter_length 1-3 + cmp w6, #2 + b.lt 1f + LOAD2 2, x3 + LOAD2 3, x9 + subs w6, w6, #2 + M_MLA v0, v2, v3 + b.eq 0f +1: // remaining filter_length 1 + LOAD1 6, x3 + LOAD1 7, x9 + M_MLA v0, v6, v7 +0: + STORE_ONE 0, x1, x2, v1 + ret +endfunc + +.purgem LOAD1 +.purgem LOAD2 +.purgem LOAD4 +.purgem LOAD8 +.purgem M_MLA +.purgem M_MLA2 +.purgem M_MUL +.purgem M_MUL2 +.purgem STORE_ONE +.endm + + +.macro LOAD1 d1, addr + ldr d\d1, [\addr], #8 +.endm +.macro LOAD2 d1, addr + ld1 {v\d1\().2d}, [\addr], #16 +.endm +.macro LOAD4 d1, d2, addr + ld1 {\d1\().2d,\d2\().2d}, [\addr], #32 +.endm +.macro LOAD8 d1, d2, d3, d4, addr + ld1 {\d1\().2d,\d2\().2d,\d3\().2d,\d4\().2d}, [\addr], #64 +.endm +.macro M_MLA d, r0, r1, d2:vararg + fmla \d\().2d, \r0\().2d, \r1\().2d +.endm +.macro M_MLA2 second:vararg + M_MLA \second +.endm +.macro M_MUL d, r0, r1, d2:vararg + fmul \d\().2d, \r0\().2d, \r1\().2d +.endm +.macro M_MUL2 second:vararg + M_MUL \second +.endm +.macro STORE_ONE rn, addr, idx, d2 + fadd v\rn\().2d, v\rn\().2d, \d2\().2d + faddp d\rn\(), v\rn\().2d + str d\rn\(), [\addr, \idx, lsl #3] +.endm + +resample_one dbl, 3 + + +.macro LOAD1 d1, addr + ldr s\d1, [\addr], #4 +.endm +.macro LOAD2 d1, addr + ld1 {v\d1\().2s}, [\addr], #8 +.endm +.macro LOAD4 d1, d2, addr + ld1 {\d1\().4s}, [\addr], #16 +.endm +.macro LOAD8 d1, d2, d3, d4, addr + ld1 {\d1\().4s,\d2\().4s}, [\addr], #32 +.endm +.macro M_MLA d, r0, r1, d2:vararg + fmla \d\().4s, \r0\().4s, \r1\().4s +.endm +.macro M_MUL d, r0, r1, d2:vararg + fmul \d\().4s, \r0\().4s, \r1\().4s +.endm +.macro STORE_ONE rn, addr, idx, d2 + faddp v\rn\().4s, v\rn\().4s, v\rn\().4s + faddp s\rn\(), v\rn\().2s + str s\rn\(), [\addr, \idx, lsl #2] +.endm + +resample_one flt + + +.macro LOAD1 d1, addr + ldr h\d1, [\addr], #2 +.endm +.macro LOAD2 d1, addr + ldr s\d1, [\addr], #4 +.endm +.macro LOAD4 d1, d2, addr + ld1 {\d1\().4h}, [\addr], #8 +.endm +.macro LOAD8 d1, d2, d3, d4, addr + ld1 {\d1\().4h,\d2\().4h}, [\addr], #16 +.endm +.macro M_MLA d, r0, r1, d2:vararg + smlal \d\().4s, \r0\().4h, \r1\().4h +.endm +.macro M_MUL d, r0, r1, d2:vararg + smull \d\().4s, \r0\().4h, \r1\().4h +.endm +.macro STORE_ONE rn, addr, idx, d2 + addp v\rn\().4s, v\rn\().4s, v\rn\().4s + addp v\rn\().4s, v\rn\().4s, v\rn\().4s + sqrshrn v\rn\().4h, v\rn\().4s, #15 + str h\rn\(), [\addr, \idx, lsl #1] +.endm + +resample_one s16, 1 + + +.macro LOAD1 d1, addr + ldr s\d1, [\addr], #4 +.endm +.macro LOAD2 d1, addr + ld1 {v\d1\().2s}, [\addr], #8 +.endm +.macro LOAD4 d1, d2, addr + ld1 {\d1\().4s}, [\addr], #16 +.endm +.macro LOAD8 d1, d2, d3, d4, addr + ld1 {\d1\().4s,\d2\().4s}, [\addr], #32 +.endm +.macro M_MLA d1, r0, r1, d2:vararg + smlal \d1\().2d, \r0\().2s, \r1\().2s +.ifnb \d2 + smlal2 \d2\().2d, \r0\().4s, \r1\().4s +.endif +.endm +.macro M_MUL d1, r0, r1, d2:vararg + smull \d1\().2d, \r0\().2s, \r1\().2s +.ifnb \d2 + smull2 \d2\().2d, \r0\().4s, \r1\().4s +.endif +.endm +.macro STORE_ONE rn, addr, idx, d2 + add v\rn\().2d, v\rn\().2d, \d2\().2d + addp d\rn\(), v\rn\().2d + sqrshrn v\rn\().2s, v\rn\().2d, #30 + str s\rn\(), [\addr, \idx, lsl #2] +.endm + +resample_one s32 diff --git a/libavresample/audio_convert.c b/libavresample/audio_convert.c index e73105d54..e68d5727f 100644 --- a/libavresample/audio_convert.c +++ b/libavresample/audio_convert.c @@ -301,6 +301,8 @@ AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, set_generic_function(ac); + if (ARCH_AARCH64) + ff_audio_convert_init_aarch64(ac); if (ARCH_ARM) ff_audio_convert_init_arm(ac); if (ARCH_X86) diff --git a/libavresample/audio_convert.h b/libavresample/audio_convert.h index 5cf6b9df2..df15442c1 100644 --- a/libavresample/audio_convert.h +++ b/libavresample/audio_convert.h @@ -96,6 +96,7 @@ int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in); /* arch-specific initialization functions */ +void ff_audio_convert_init_aarch64(AudioConvert *ac); void ff_audio_convert_init_arm(AudioConvert *ac); void ff_audio_convert_init_x86(AudioConvert *ac); diff --git a/libavresample/avresample.h b/libavresample/avresample.h index dc392ad07..6e3cf35fd 100644 --- a/libavresample/avresample.h +++ b/libavresample/avresample.h @@ -76,9 +76,8 @@ * while (get_input(&input, &in_linesize, &in_samples)) { * uint8_t *output * int out_linesize; - * int out_samples = avresample_available(avr) + - * av_rescale_rnd(avresample_get_delay(avr) + - * in_samples, 44100, 48000, AV_ROUND_UP); + * int out_samples = avresample_get_out_samples(avr, in_samples); + * * av_samples_alloc(&output, &out_linesize, 2, out_samples, * AV_SAMPLE_FMT_S16, 0); * out_samples = avresample_convert(avr, &output, out_linesize, out_samples, @@ -97,6 +96,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/dict.h" #include "libavutil/log.h" +#include "libavutil/mathematics.h" #include "libavresample/version.h" @@ -312,12 +312,24 @@ int avresample_set_channel_mapping(AVAudioResampleContext *avr, int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta, int compensation_distance); +/** + * Provide the upper bound on the number of samples the configured + * conversion would output. + * + * @param avr audio resample context + * @param in_nb_samples number of input samples + * + * @return number of samples or AVERROR(EINVAL) if the value + * would exceed INT_MAX + */ + +int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples); + /** * Convert input samples and write them to the output FIFO. * - * The upper bound on the number of output samples is given by - * avresample_available() + (avresample_get_delay() + number of input samples) * - * output sample rate / input sample rate. + * The upper bound on the number of output samples can be obtained through + * avresample_get_out_samples(). * * The output data can be NULL or have fewer allocated samples than required. * In this case, any remaining samples not written to the output will be added @@ -334,7 +346,7 @@ int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta, * samples. To get this data as output, either call avresample_convert() with * NULL input or call avresample_read(). * - * @see avresample_available() + * @see avresample_get_out_samples() * @see avresample_read() * @see avresample_get_delay() * diff --git a/libavresample/internal.h b/libavresample/internal.h index 2946126c7..fe6bd8fa6 100644 --- a/libavresample/internal.h +++ b/libavresample/internal.h @@ -107,4 +107,7 @@ struct AVAudioResampleContext { ChannelMapInfo ch_map_info; }; + +void ff_audio_resample_init_aarch64(ResampleContext *c, + enum AVSampleFormat sample_fmt); #endif /* AVRESAMPLE_INTERNAL_H */ diff --git a/libavresample/resample.c b/libavresample/resample.c index 525828c52..bdc74a2e0 100644 --- a/libavresample/resample.c +++ b/libavresample/resample.c @@ -26,29 +26,6 @@ #include "resample.h" #include "audio_data.h" -struct ResampleContext { - AVAudioResampleContext *avr; - AudioData *buffer; - uint8_t *filter_bank; - int filter_length; - int ideal_dst_incr; - int dst_incr; - int index; - int frac; - int src_incr; - int compensation_distance; - int phase_shift; - int phase_mask; - int linear; - enum AVResampleFilterType filter_type; - int kaiser_beta; - double factor; - void (*set_filter)(void *filter, double *tab, int phase, int tap_count); - void (*resample_one)(struct ResampleContext *c, int no_filter, void *dst0, - int dst_index, const void *src0, int src_size, - int index, int frac); -}; - /* double template */ #define CONFIG_RESAMPLE_DBL @@ -87,10 +64,10 @@ static double bessel(double x) } /* Build a polyphase filterbank. */ -static int build_filter(ResampleContext *c) +static int build_filter(ResampleContext *c, double factor) { int ph, i; - double x, y, w, factor; + double x, y, w; double *tab; int tap_count = c->filter_length; int phase_count = 1 << c->phase_shift; @@ -100,9 +77,6 @@ static int build_filter(ResampleContext *c) if (!tab) return AVERROR(ENOMEM); - /* if upsampling, only need to interpolate, no filter */ - factor = FFMIN(c->factor, 1.0); - for (ph = 0; ph < phase_count; ph++) { double norm = 0; for (i = 0; i < tap_count; i++) { @@ -169,36 +143,42 @@ ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr) c->phase_shift = avr->phase_shift; c->phase_mask = phase_count - 1; c->linear = avr->linear_interp; - c->factor = factor; c->filter_length = FFMAX((int)ceil(avr->filter_size / factor), 1); c->filter_type = avr->filter_type; c->kaiser_beta = avr->kaiser_beta; switch (avr->internal_sample_fmt) { case AV_SAMPLE_FMT_DBLP: - c->resample_one = resample_one_dbl; + c->resample_one = c->linear ? resample_linear_dbl : resample_one_dbl; + c->resample_nearest = resample_nearest_dbl; c->set_filter = set_filter_dbl; break; case AV_SAMPLE_FMT_FLTP: - c->resample_one = resample_one_flt; + c->resample_one = c->linear ? resample_linear_flt : resample_one_flt; + c->resample_nearest = resample_nearest_flt; c->set_filter = set_filter_flt; break; case AV_SAMPLE_FMT_S32P: - c->resample_one = resample_one_s32; + c->resample_one = c->linear ? resample_linear_s32 : resample_one_s32; + c->resample_nearest = resample_nearest_s32; c->set_filter = set_filter_s32; break; case AV_SAMPLE_FMT_S16P: - c->resample_one = resample_one_s16; + c->resample_one = c->linear ? resample_linear_s16 : resample_one_s16; + c->resample_nearest = resample_nearest_s16; c->set_filter = set_filter_s16; break; } + if (ARCH_AARCH64) + ff_audio_resample_init_aarch64(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); if (!c->filter_bank) goto error; - if (build_filter(c) < 0) + if (build_filter(c, factor) < 0) goto error; memcpy(&c->filter_bank[(c->filter_length * phase_count + 1) * felem_size], @@ -212,15 +192,19 @@ ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr) goto error; c->ideal_dst_incr = c->dst_incr; - c->index = -phase_count * ((c->filter_length - 1) / 2); + c->padding_size = (c->filter_length - 1) / 2; + c->initial_padding_filled = 0; + c->index = 0; c->frac = 0; /* allocate internal buffer */ - c->buffer = ff_audio_data_alloc(avr->resample_channels, 0, + c->buffer = ff_audio_data_alloc(avr->resample_channels, c->padding_size, avr->internal_sample_fmt, "resample buffer"); if (!c->buffer) goto error; + c->buffer->nb_samples = c->padding_size; + c->initial_padding_samples = c->padding_size; av_log(avr, AV_LOG_DEBUG, "resample: %s from %d Hz to %d Hz\n", av_get_sample_fmt_name(avr->internal_sample_fmt), @@ -330,10 +314,11 @@ reinit_fail: } static int resample(ResampleContext *c, void *dst, const void *src, - int *consumed, int src_size, int dst_size, int update_ctx) + int *consumed, int src_size, int dst_size, int update_ctx, + int nearest_neighbour) { int dst_index; - int index = c->index; + unsigned int index = c->index; int frac = c->frac; int dst_incr_frac = c->dst_incr % c->src_incr; int dst_incr = c->dst_incr / c->src_incr; @@ -342,9 +327,8 @@ static int resample(ResampleContext *c, void *dst, const void *src, if (!dst != !src) return AVERROR(EINVAL); - if (compensation_distance == 0 && c->filter_length == 1 && - c->phase_shift == 0) { - int64_t index2 = ((int64_t)index) << 32; + if (nearest_neighbour) { + uint64_t index2 = ((uint64_t)index) << 32; int64_t incr = (1LL << 32) * c->dst_incr / c->src_incr; dst_size = FFMIN(dst_size, (src_size-1-index) * (int64_t)c->src_incr / @@ -352,7 +336,7 @@ static int resample(ResampleContext *c, void *dst, const void *src, if (dst) { for(dst_index = 0; dst_index < dst_size; dst_index++) { - c->resample_one(c, 1, dst, dst_index, src, 0, index2 >> 32, 0); + c->resample_nearest(dst, dst_index, src, index2 >> 32); index2 += incr; } } else { @@ -365,12 +349,11 @@ static int resample(ResampleContext *c, void *dst, const void *src, for (dst_index = 0; dst_index < dst_size; dst_index++) { int sample_index = index >> c->phase_shift; - if (sample_index + c->filter_length > src_size || - -sample_index >= src_size) + if (sample_index + c->filter_length > src_size) break; if (dst) - c->resample_one(c, 0, dst, dst_index, src, src_size, index, frac); + c->resample_one(c, dst, dst_index, src, index, frac); frac += dst_incr_frac; index += dst_incr; @@ -386,11 +369,10 @@ static int resample(ResampleContext *c, void *dst, const void *src, } } if (consumed) - *consumed = FFMAX(index, 0) >> c->phase_shift; + *consumed = index >> c->phase_shift; if (update_ctx) { - if (index >= 0) - index &= c->phase_mask; + index &= c->phase_mask; if (compensation_distance) { compensation_distance -= dst_index; @@ -410,6 +392,9 @@ int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src) { int ch, in_samples, in_leftover, consumed = 0, out_samples = 0; int ret = AVERROR(EINVAL); + int nearest_neighbour = (c->compensation_distance == 0 && + c->filter_length == 1 && + c->phase_shift == 0); in_samples = src ? src->nb_samples : 0; in_leftover = c->buffer->nb_samples; @@ -419,18 +404,62 @@ int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src) ret = ff_audio_data_combine(c->buffer, in_leftover, src, 0, in_samples); if (ret < 0) return ret; - } else if (!in_leftover) { + } else if (in_leftover <= c->final_padding_samples) { /* no remaining samples to flush */ return 0; - } else { - /* TODO: pad buffer to flush completely */ } + if (!c->initial_padding_filled) { + int bps = av_get_bytes_per_sample(c->avr->internal_sample_fmt); + int i; + + if (src && c->buffer->nb_samples < 2 * c->padding_size) + return 0; + + for (i = 0; i < c->padding_size; i++) + for (ch = 0; ch < c->buffer->channels; ch++) { + if (c->buffer->nb_samples > 2 * c->padding_size - i) { + memcpy(c->buffer->data[ch] + bps * i, + c->buffer->data[ch] + bps * (2 * c->padding_size - i), bps); + } else { + memset(c->buffer->data[ch] + bps * i, 0, bps); + } + } + c->initial_padding_filled = 1; + } + + if (!src && !c->final_padding_filled) { + int bps = av_get_bytes_per_sample(c->avr->internal_sample_fmt); + int i; + + ret = ff_audio_data_realloc(c->buffer, in_samples + c->padding_size); + if (ret < 0) { + av_log(c->avr, AV_LOG_ERROR, "Error reallocating resampling buffer\n"); + return AVERROR(ENOMEM); + } + + for (i = 0; i < c->padding_size; i++) + for (ch = 0; ch < c->buffer->channels; ch++) { + if (in_leftover > i) { + memcpy(c->buffer->data[ch] + bps * (in_leftover + i), + c->buffer->data[ch] + bps * (in_leftover - i - 1), + bps); + } else { + memset(c->buffer->data[ch] + bps * (in_leftover + i), + 0, bps); + } + } + c->buffer->nb_samples += c->padding_size; + c->final_padding_samples = c->padding_size; + c->final_padding_filled = 1; + } + + /* calculate output size and reallocate output buffer if needed */ /* TODO: try to calculate this without the dummy resample() run */ if (!dst->read_only && dst->allow_realloc) { out_samples = resample(c, NULL, NULL, NULL, c->buffer->nb_samples, - INT_MAX, 0); + INT_MAX, 0, nearest_neighbour); ret = ff_audio_data_realloc(dst, out_samples); if (ret < 0) { av_log(c->avr, AV_LOG_ERROR, "error reallocating output\n"); @@ -443,7 +472,7 @@ int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src) out_samples = resample(c, (void *)dst->data[ch], (const void *)c->buffer->data[ch], &consumed, c->buffer->nb_samples, dst->allocated_samples, - ch + 1 == c->buffer->channels); + ch + 1 == c->buffer->channels, nearest_neighbour); } if (out_samples < 0) { av_log(c->avr, AV_LOG_ERROR, "error during resampling\n"); @@ -452,6 +481,7 @@ int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src) /* drain consumed samples from the internal buffer */ 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", in_samples, in_leftover, out_samples, c->buffer->nb_samples); @@ -462,8 +492,10 @@ int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src) int avresample_get_delay(AVAudioResampleContext *avr) { + ResampleContext *c = avr->resample; + if (!avr->resample_needed || !avr->resample) return 0; - return avr->resample->buffer->nb_samples; + return FFMAX(c->buffer->nb_samples - c->padding_size, 0); } diff --git a/libavresample/resample.h b/libavresample/resample.h index 3b56baa5c..be9f56279 100644 --- a/libavresample/resample.h +++ b/libavresample/resample.h @@ -25,6 +25,35 @@ #include "internal.h" #include "audio_data.h" +struct ResampleContext { + AVAudioResampleContext *avr; + AudioData *buffer; + uint8_t *filter_bank; + int filter_length; + int ideal_dst_incr; + int dst_incr; + unsigned int index; + int frac; + int src_incr; + int compensation_distance; + int phase_shift; + int phase_mask; + int linear; + enum AVResampleFilterType filter_type; + int kaiser_beta; + void (*set_filter)(void *filter, double *tab, int phase, int tap_count); + void (*resample_one)(struct ResampleContext *c, void *dst0, + int dst_index, const void *src0, + unsigned int index, int frac); + void (*resample_nearest)(void *dst0, int dst_index, + const void *src0, unsigned int index); + int padding_size; + int initial_padding_filled; + int initial_padding_samples; + int final_padding_filled; + int final_padding_samples; +}; + /** * Allocate and initialize a ResampleContext. * diff --git a/libavresample/resample_template.c b/libavresample/resample_template.c index 06da90fe9..863852a3f 100644 --- a/libavresample/resample_template.c +++ b/libavresample/resample_template.c @@ -18,6 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include + +#include "libavutil/common.h" +#include "internal.h" + #if defined(CONFIG_RESAMPLE_DBL) #define SET_TYPE(func) func ## _dbl #define FELEM double @@ -48,40 +54,50 @@ #define DBL_TO_FELEM(d, v) d = av_clip_int16(lrint(v * (1 << 15))) #endif -static void SET_TYPE(resample_one)(ResampleContext *c, int no_filter, - void *dst0, int dst_index, const void *src0, - int src_size, int index, int frac) +static void SET_TYPE(resample_nearest)(void *dst0, int dst_index, const void *src0, unsigned int index) { FELEM *dst = dst0; const FELEM *src = src0; + dst[dst_index] = src[index]; +} - if (no_filter) { - dst[dst_index] = src[index]; - } else { - int i; - int sample_index = index >> c->phase_shift; - FELEM2 val = 0; - FELEM *filter = ((FELEM *)c->filter_bank) + - c->filter_length * (index & c->phase_mask); +static void SET_TYPE(resample_linear)(ResampleContext *c, void *dst0, int dst_index, + const void *src0, unsigned int index, int frac) +{ + FELEM *dst = dst0; + const FELEM *src = src0; + int i; + unsigned int sample_index = index >> c->phase_shift; + FELEM2 val = 0; + FELEM *filter = ((FELEM *)c->filter_bank) + + c->filter_length * (index & c->phase_mask); + FELEM2 v2 = 0; - if (sample_index < 0) { - for (i = 0; i < c->filter_length; i++) - val += src[FFABS(sample_index + i) % src_size] * - (FELEM2)filter[i]; - } else if (c->linear) { - FELEM2 v2 = 0; - for (i = 0; i < c->filter_length; i++) { - val += src[abs(sample_index + i)] * (FELEM2)filter[i]; - v2 += src[abs(sample_index + i)] * (FELEM2)filter[i + c->filter_length]; - } - val += (v2 - val) * (FELEML)frac / c->src_incr; - } else { - for (i = 0; i < c->filter_length; i++) - val += src[sample_index + i] * (FELEM2)filter[i]; - } - - OUT(dst[dst_index], val); + for (i = 0; i < c->filter_length; i++) { + val += src[sample_index + i] * (FELEM2)filter[i]; + v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_length]; } + val += (v2 - val) * (FELEML)frac / c->src_incr; + + OUT(dst[dst_index], val); +} + +static void SET_TYPE(resample_one)(ResampleContext *c, + void *dst0, int dst_index, const void *src0, + unsigned int index, int frac) +{ + FELEM *dst = dst0; + const FELEM *src = src0; + int i; + unsigned int sample_index = index >> c->phase_shift; + FELEM2 val = 0; + FELEM *filter = ((FELEM *)c->filter_bank) + + c->filter_length * (index & c->phase_mask); + + for (i = 0; i < c->filter_length; i++) + val += src[sample_index + i] * (FELEM2)filter[i]; + + OUT(dst[dst_index], val); } static void SET_TYPE(set_filter)(void *filter0, double *tab, int phase, diff --git a/libavresample/utils.c b/libavresample/utils.c index 3a335c058..48874d610 100644 --- a/libavresample/utils.c +++ b/libavresample/utils.c @@ -622,6 +622,25 @@ int avresample_available(AVAudioResampleContext *avr) return av_audio_fifo_size(avr->out_fifo); } +int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples) +{ + int64_t samples = avresample_get_delay(avr) + (int64_t)in_nb_samples; + + if (avr->resample_needed) { + samples = av_rescale_rnd(samples, + avr->out_sample_rate, + avr->in_sample_rate, + AV_ROUND_UP); + } + + samples += avresample_available(avr); + + if (samples > INT_MAX) + return AVERROR(EINVAL); + + return samples; +} + int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_samples) { if (!output) diff --git a/libavresample/version.h b/libavresample/version.h index d865ad2d2..0431badf5 100644 --- a/libavresample/version.h +++ b/libavresample/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVRESAMPLE_VERSION_MAJOR 1 -#define LIBAVRESAMPLE_VERSION_MINOR 2 +#define LIBAVRESAMPLE_VERSION_MINOR 3 #define LIBAVRESAMPLE_VERSION_MICRO 0 #define LIBAVRESAMPLE_VERSION_INT AV_VERSION_INT(LIBAVRESAMPLE_VERSION_MAJOR, \ diff --git a/libavresample/x86/audio_mix_init.c b/libavresample/x86/audio_mix_init.c index bec88b0d3..2f05eee81 100644 --- a/libavresample/x86/audio_mix_init.c +++ b/libavresample/x86/audio_mix_init.c @@ -173,7 +173,6 @@ DEFINE_MIX_3_8_TO_1_2(8) av_cold void ff_audio_mix_init_x86(AudioMix *am) { -#if HAVE_YASM int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_SSE(cpu_flags)) { @@ -211,5 +210,4 @@ av_cold void ff_audio_mix_init_x86(AudioMix *am) SET_MIX_3_8_TO_1_2(6) SET_MIX_3_8_TO_1_2(7) SET_MIX_3_8_TO_1_2(8) -#endif /* HAVE_YASM */ } diff --git a/libavutil/Makefile b/libavutil/Makefile index e4ee47cc1..91751dc4c 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -19,12 +19,14 @@ HEADERS = adler32.h \ common.h \ cpu.h \ crc.h \ + display.h \ downmix_info.h \ error.h \ eval.h \ fifo.h \ file.h \ frame.h \ + hash.h \ hmac.h \ imgutils.h \ intfloat.h \ @@ -44,12 +46,14 @@ HEADERS = adler32.h \ pixdesc.h \ pixfmt.h \ random_seed.h \ + replaygain.h \ rational.h \ ripemd.h \ samplefmt.h \ sha.h \ sha512.h \ stereo3d.h \ + threadmessage.h \ time.h \ timecode.h \ timestamp.h \ @@ -81,6 +85,7 @@ OBJS = adler32.o \ cpu.o \ crc.o \ des.o \ + display.o \ downmix_info.o \ error.o \ eval.o \ @@ -88,6 +93,7 @@ OBJS = adler32.o \ file.o \ file_open.o \ float_dsp.o \ + fixed_dsp.o \ frame.o \ hash.o \ hmac.o \ @@ -115,6 +121,7 @@ OBJS = adler32.o \ sha.o \ sha512.o \ stereo3d.o \ + threadmessage.o \ time.o \ timecode.o \ tree.o \ @@ -151,15 +158,18 @@ TESTPROGS = adler32 \ eval \ file \ fifo \ + float_dsp \ hmac \ lfg \ lls1 \ lls2 \ + log \ md5 \ murmur3 \ opt \ pca \ parseutils \ + pixdesc \ random_seed \ rational \ ripemd \ diff --git a/libavutil/aarch64/Makefile b/libavutil/aarch64/Makefile index 13d26a152..5613813ba 100644 --- a/libavutil/aarch64/Makefile +++ b/libavutil/aarch64/Makefile @@ -1 +1,4 @@ -OBJS += aarch64/cpu.o +OBJS += aarch64/cpu.o \ + aarch64/float_dsp_init.o \ + +NEON-OBJS += aarch64/float_dsp_neon.o diff --git a/libavutil/aarch64/asm.S b/libavutil/aarch64/asm.S index 1f9e784ce..d153df69d 100644 --- a/libavutil/aarch64/asm.S +++ b/libavutil/aarch64/asm.S @@ -23,13 +23,19 @@ #ifdef __ELF__ # define ELF #else -# define ELF // +# define ELF # +#endif + +#if HAVE_AS_FUNC +# define FUNC +#else +# define FUNC # #endif .macro function name, export=0, align=2 .macro endfunc ELF .size \name, . - \name - .endfunc +FUNC .endfunc .purgem endfunc .endm .text @@ -37,11 +43,11 @@ ELF .size \name, . - \name .if \export .global EXTERN_ASM\name ELF .type EXTERN_ASM\name, %function - .func EXTERN_ASM\name +FUNC .func EXTERN_ASM\name EXTERN_ASM\name: .else ELF .type \name, %function - .func \name +FUNC .func \name \name: .endif .endm @@ -57,8 +63,11 @@ ELF .size \name, . - \name .endm .macro movrel rd, val -#if CONFIG_PIC - adrp \rd, :pg_hi21:\val +#if CONFIG_PIC && defined(__APPLE__) + adrp \rd, \val@PAGE + add \rd, \rd, \val@PAGEOFF +#elif CONFIG_PIC + adrp \rd, \val add \rd, \rd, :lo12:\val #else ldr \rd, =\val diff --git a/libavutil/aarch64/cpu.c b/libavutil/aarch64/cpu.c index 87e9d5056..8ef077aae 100644 --- a/libavutil/aarch64/cpu.c +++ b/libavutil/aarch64/cpu.c @@ -22,6 +22,7 @@ int ff_get_cpu_flags_aarch64(void) { - return AV_CPU_FLAG_NEON * HAVE_NEON | - AV_CPU_FLAG_VFP * HAVE_VFP; + return AV_CPU_FLAG_ARMV8 * HAVE_ARMV8 | + AV_CPU_FLAG_NEON * HAVE_NEON | + AV_CPU_FLAG_VFP * HAVE_VFP; } diff --git a/libavutil/aarch64/cpu.h b/libavutil/aarch64/cpu.h index d6af28126..cf1b9cc51 100644 --- a/libavutil/aarch64/cpu.h +++ b/libavutil/aarch64/cpu.h @@ -23,6 +23,7 @@ #include "libavutil/cpu.h" #include "libavutil/cpu_internal.h" +#define have_armv8(flags) CPUEXT(flags, ARMV8) #define have_neon(flags) CPUEXT(flags, NEON) #define have_vfp(flags) CPUEXT(flags, VFP) diff --git a/libavutil/aarch64/float_dsp_init.c b/libavutil/aarch64/float_dsp_init.c new file mode 100644 index 000000000..432507182 --- /dev/null +++ b/libavutil/aarch64/float_dsp_init.c @@ -0,0 +1,69 @@ +/* + * ARM NEON optimised Float DSP functions + * Copyright (c) 2008 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/float_dsp.h" +#include "cpu.h" + +void ff_vector_fmul_neon(float *dst, const float *src0, const float *src1, + int len); + +void ff_vector_fmac_scalar_neon(float *dst, const float *src, float mul, + int len); + +void ff_vector_fmul_scalar_neon(float *dst, const float *src, float mul, + int len); + +void ff_vector_dmul_scalar_neon(double *dst, const double *src, double mul, + int len); + +void ff_vector_fmul_window_neon(float *dst, const float *src0, + const float *src1, const float *win, int len); + +void ff_vector_fmul_add_neon(float *dst, const float *src0, const float *src1, + const float *src2, int len); + +void ff_vector_fmul_reverse_neon(float *dst, const float *src0, + const float *src1, int len); + +void ff_butterflies_float_neon(float *v1, float *v2, int len); + +float ff_scalarproduct_float_neon(const float *v1, const float *v2, int len); + +av_cold void ff_float_dsp_init_aarch64(AVFloatDSPContext *fdsp) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + fdsp->butterflies_float = ff_butterflies_float_neon; + fdsp->scalarproduct_float = ff_scalarproduct_float_neon; + fdsp->vector_dmul_scalar = ff_vector_dmul_scalar_neon; + fdsp->vector_fmul = ff_vector_fmul_neon; + fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_neon; + fdsp->vector_fmul_add = ff_vector_fmul_add_neon; + fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_neon; + fdsp->vector_fmul_scalar = ff_vector_fmul_scalar_neon; + fdsp->vector_fmul_window = ff_vector_fmul_window_neon; + } +} diff --git a/libavutil/aarch64/float_dsp_neon.S b/libavutil/aarch64/float_dsp_neon.S new file mode 100644 index 000000000..02d790c0c --- /dev/null +++ b/libavutil/aarch64/float_dsp_neon.S @@ -0,0 +1,202 @@ +/* + * ARM NEON optimised Float DSP functions + * Copyright (c) 2008 Mans Rullgard + * Copyright (c) 2014 Janne Grunau + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "asm.S" + +function ff_vector_fmul_neon, export=1 +1: subs w3, w3, #16 + ld1 {v0.4S, v1.4S}, [x1], #32 + ld1 {v2.4S, v3.4S}, [x1], #32 + ld1 {v4.4S, v5.4S}, [x2], #32 + ld1 {v6.4S, v7.4S}, [x2], #32 + fmul v16.4S, v0.4S, v4.4S + fmul v17.4S, v1.4S, v5.4S + fmul v18.4S, v2.4S, v6.4S + fmul v19.4S, v3.4S, v7.4S + st1 {v16.4S, v17.4S}, [x0], #32 + st1 {v18.4S, v19.4S}, [x0], #32 + b.ne 1b + ret +endfunc + +function ff_vector_fmac_scalar_neon, export=1 + mov x3, #-32 +1: subs w2, w2, #16 + ld1 {v16.4S, v17.4S}, [x0], #32 + ld1 {v18.4S, v19.4S}, [x0], x3 + ld1 {v4.4S, v5.4S}, [x1], #32 + ld1 {v6.4S, v7.4S}, [x1], #32 + fmla v16.4S, v4.4S, v0.S[0] + fmla v17.4S, v5.4S, v0.S[0] + fmla v18.4S, v6.4S, v0.S[0] + fmla v19.4S, v7.4S, v0.S[0] + st1 {v16.4S, v17.4S}, [x0], #32 + st1 {v18.4S, v19.4S}, [x0], #32 + b.ne 1b + ret +endfunc + +function ff_vector_fmul_scalar_neon, export=1 + mov w4, #15 + bics w3, w2, w4 + dup v16.4S, v0.S[0] + b.eq 3f + ld1 {v0.4S, v1.4S}, [x1], #32 +1: subs w3, w3, #16 + fmul v0.4S, v0.4S, v16.4S + ld1 {v2.4S, v3.4S}, [x1], #32 + fmul v1.4S, v1.4S, v16.4S + fmul v2.4S, v2.4S, v16.4S + st1 {v0.4S, v1.4S}, [x0], #32 + fmul v3.4S, v3.4S, v16.4S + b.eq 2f + ld1 {v0.4S, v1.4S}, [x1], #32 + st1 {v2.4S, v3.4S}, [x0], #32 + b 1b +2: ands w2, w2, #15 + st1 {v2.4S, v3.4S}, [x0], #32 + b.eq 4f +3: ld1 {v0.4S}, [x1], #16 + fmul v0.4S, v0.4S, v16.4S + st1 {v0.4S}, [x0], #16 + subs w2, w2, #4 + b.gt 3b +4: ret +endfunc + +function ff_vector_dmul_scalar_neon, export=1 + dup v16.2D, v0.D[0] + ld1 {v0.2D, v1.2D}, [x1], #32 +1: subs w2, w2, #8 + fmul v0.2D, v0.2D, v16.2D + ld1 {v2.2D, v3.2D}, [x1], #32 + fmul v1.2D, v1.2D, v16.2D + fmul v2.2D, v2.2D, v16.2D + st1 {v0.2D, v1.2D}, [x0], #32 + fmul v3.2D, v3.2D, v16.2D + ld1 {v0.2D, v1.2D}, [x1], #32 + st1 {v2.2D, v3.2D}, [x0], #32 + b.gt 1b + ret +endfunc + +function ff_vector_fmul_window_neon, export=1 + sxtw x4, w4 // len + sub x2, x2, #8 + sub x5, x4, #2 + add x2, x2, x5, lsl #2 // src1 + 4 * (len - 4) + add x6, x3, x5, lsl #3 // win + 8 * (len - 2) + add x5, x0, x5, lsl #3 // dst + 8 * (len - 2) + mov x7, #-16 + ld1 {v0.4S}, [x1], #16 // s0 + ld1 {v2.4S}, [x3], #16 // wi + ld1 {v1.4S}, [x2], x7 // s1 +1: ld1 {v3.4S}, [x6], x7 // wj + subs x4, x4, #4 + fmul v17.4S, v0.4S, v2.4S // s0 * wi + rev64 v4.4S, v1.4S + rev64 v5.4S, v3.4S + rev64 v17.4S, v17.4S + ext v4.16B, v4.16B, v4.16B, #8 // s1_r + ext v5.16B, v5.16B, v5.16B, #8 // wj_r + ext v17.16B, v17.16B, v17.16B, #8 // (s0 * wi)_rev + fmul v16.4S, v0.4S, v5.4S // s0 * wj_r + fmla v17.4S, v1.4S, v3.4S // (s0 * wi)_rev + s1 * wj + b.eq 2f + ld1 {v0.4S}, [x1], #16 + fmls v16.4S, v4.4S, v2.4S // s0 * wj_r - s1_r * wi + st1 {v17.4S}, [x5], x7 + ld1 {v2.4S}, [x3], #16 + ld1 {v1.4S}, [x2], x7 + st1 {v16.4S}, [x0], #16 + b 1b +2: + fmls v16.4S, v4.4S, v2.4S // s0 * wj_r - s1_r * wi + st1 {v17.4S}, [x5], x7 + st1 {v16.4S}, [x0], #16 + ret +endfunc + +function ff_vector_fmul_add_neon, export=1 + ld1 {v0.4S, v1.4S}, [x1], #32 + ld1 {v2.4S, v3.4S}, [x2], #32 + ld1 {v4.4S, v5.4S}, [x3], #32 +1: subs w4, w4, #8 + fmla v4.4S, v0.4S, v2.4S + fmla v5.4S, v1.4S, v3.4S + b.eq 2f + ld1 {v0.4S, v1.4S}, [x1], #32 + ld1 {v2.4S, v3.4S}, [x2], #32 + st1 {v4.4S, v5.4S}, [x0], #32 + ld1 {v4.4S, v5.4S}, [x3], #32 + b 1b +2: st1 {v4.4S, v5.4S}, [x0], #32 + ret +endfunc + +function ff_vector_fmul_reverse_neon, export=1 + sxtw x3, w3 + add x2, x2, x3, lsl #2 + sub x2, x2, #32 + mov x4, #-32 + ld1 {v2.4S, v3.4S}, [x2], x4 + ld1 {v0.4S, v1.4S}, [x1], #32 +1: subs x3, x3, #8 + rev64 v3.4S, v3.4S + rev64 v2.4S, v2.4S + ext v3.16B, v3.16B, v3.16B, #8 + ext v2.16B, v2.16B, v2.16B, #8 + fmul v16.4S, v0.4S, v3.4S + fmul v17.4S, v1.4S, v2.4S + b.eq 2f + ld1 {v2.4S, v3.4S}, [x2], x4 + ld1 {v0.4S, v1.4S}, [x1], #32 + st1 {v16.4S, v17.4S}, [x0], #32 + b 1b +2: st1 {v16.4S, v17.4S}, [x0], #32 + ret +endfunc + +function ff_butterflies_float_neon, export=1 +1: ld1 {v0.4S}, [x0] + ld1 {v1.4S}, [x1] + subs w2, w2, #4 + fsub v2.4S, v0.4S, v1.4S + fadd v3.4S, v0.4S, v1.4S + st1 {v2.4S}, [x1], #16 + st1 {v3.4S}, [x0], #16 + b.gt 1b + ret +endfunc + +function ff_scalarproduct_float_neon, export=1 + movi v2.4S, #0 +1: ld1 {v0.4S}, [x0], #16 + ld1 {v1.4S}, [x1], #16 + subs w2, w2, #4 + fmla v2.4S, v0.4S, v1.4S + b.gt 1b + faddp v0.4S, v2.4S, v2.4S + faddp s0, v0.2S + ret +endfunc diff --git a/libavutil/arm/asm.S b/libavutil/arm/asm.S index 08669f043..35559ce27 100644 --- a/libavutil/arm/asm.S +++ b/libavutil/arm/asm.S @@ -34,6 +34,12 @@ # define T @ #endif +#if HAVE_AS_FUNC +# define FUNC +#else +# define FUNC @ +#endif + #if HAVE_NEON .arch armv7-a #elif HAVE_ARMV6T2 @@ -66,7 +72,7 @@ ELF .section .note.GNU-stack,"",%progbits @ Mark stack as non-executable .noaltmacro .endif ELF .size \name, . - \name - .endfunc +FUNC .endfunc .purgem endfunc .endm .text @@ -74,11 +80,11 @@ ELF .size \name, . - \name .if \export .global EXTERN_ASM\name ELF .type EXTERN_ASM\name, %function - .func EXTERN_ASM\name +FUNC .func EXTERN_ASM\name EXTERN_ASM\name: .else ELF .type \name, %function - .func \name +FUNC .func \name \name: .endif .endm diff --git a/libavutil/arm/cpu.c b/libavutil/arm/cpu.c index 3f7674bfe..f6cf33859 100644 --- a/libavutil/arm/cpu.c +++ b/libavutil/arm/cpu.c @@ -90,8 +90,10 @@ static int get_cpuinfo(uint32_t *hwcap) *hwcap |= HWCAP_VFP; if (strstr(buf, " vfpv3 ")) *hwcap |= HWCAP_VFPv3; - if (strstr(buf, " neon ")) + if (strstr(buf, " neon ") || strstr(buf, " asimd ")) *hwcap |= HWCAP_NEON; + if (strstr(buf, " fp ")) // Listed on 64 bit ARMv8 kernels + *hwcap |= HWCAP_VFP | HWCAP_VFPv3; break; } } diff --git a/libavutil/arm/float_dsp_init_arm.c b/libavutil/arm/float_dsp_init_arm.c index 38148b387..678762862 100644 --- a/libavutil/arm/float_dsp_init_arm.c +++ b/libavutil/arm/float_dsp_init_arm.c @@ -1,6 +1,4 @@ /* - * ARM optimized DSP utils - * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or diff --git a/libavutil/audio_fifo.c b/libavutil/audio_fifo.c index cfbde8992..c3aadfdab 100644 --- a/libavutil/audio_fifo.c +++ b/libavutil/audio_fifo.c @@ -76,7 +76,7 @@ AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels, af->sample_size = buf_size / nb_samples; af->nb_buffers = av_sample_fmt_is_planar(sample_fmt) ? channels : 1; - af->buf = av_mallocz(af->nb_buffers * sizeof(*af->buf)); + af->buf = av_mallocz_array(af->nb_buffers, sizeof(*af->buf)); if (!af->buf) goto error; diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h index 903b8f1cd..d21e6a131 100644 --- a/libavutil/audio_fifo.h +++ b/libavutil/audio_fifo.h @@ -34,6 +34,9 @@ /** * @addtogroup lavu_audio * @{ + * + * @defgroup lavu_audiofifo Audio FIFO Buffer + * @{ */ /** @@ -143,6 +146,7 @@ int av_audio_fifo_size(AVAudioFifo *af); int av_audio_fifo_space(AVAudioFifo *af); /** + * @} * @} */ diff --git a/libavutil/avutil.h b/libavutil/avutil.h index d6566c116..e6ebb6c43 100644 --- a/libavutil/avutil.h +++ b/libavutil/avutil.h @@ -151,6 +151,12 @@ * @{ * * @} + * + * @defgroup version_utils Library Version Macros + * + * @{ + * + * @} */ @@ -282,10 +288,10 @@ char av_get_picture_type_char(enum AVPictureType pict_type); #include "common.h" #include "error.h" +#include "rational.h" #include "version.h" #include "macros.h" #include "mathematics.h" -#include "rational.h" #include "log.h" #include "pixfmt.h" @@ -325,6 +331,11 @@ unsigned av_int_list_length_for_size(unsigned elsize, */ FILE *av_fopen_utf8(const char *path, const char *mode); +/** + * Return the fractional representation of the internal time base. + */ +AVRational av_get_time_base_q(void); + /** * @} * @} diff --git a/libavutil/bprint.c b/libavutil/bprint.c index 7786e3bce..0a0d07861 100644 --- a/libavutil/bprint.c +++ b/libavutil/bprint.c @@ -356,7 +356,7 @@ int main(void) av_bprint_init(&b, 0, 1); bprint_pascal(&b, 25); printf("Long text in automatic buffer: %u/%u\n", (unsigned)strlen(b.str)/8*8, b.len); - /* Note that the size of the automatic buffer is arch-dependant. */ + /* Note that the size of the automatic buffer is arch-dependent. */ av_bprint_init(&b, 0, 0); bprint_pascal(&b, 25); diff --git a/libavutil/channel_layout.h b/libavutil/channel_layout.h index bc6befd8e..dea4d6093 100644 --- a/libavutil/channel_layout.h +++ b/libavutil/channel_layout.h @@ -79,7 +79,7 @@ /** * @} - * @defgroup channel_mask_c Audio channel convenience macros + * @defgroup channel_mask_c Audio channel layouts * @{ * */ #define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER) @@ -121,10 +121,6 @@ enum AVMatrixEncoding { AV_MATRIX_ENCODING_NB }; -/** - * @} - */ - /** * Return a channel layout id that matches name, or 0 if no match is found. * @@ -219,6 +215,7 @@ int av_get_standard_channel_layout(unsigned index, uint64_t *layout, const char **name); /** + * @} * @} */ diff --git a/libavutil/cpu.c b/libavutil/cpu.c index d6d93a35d..2d402117d 100644 --- a/libavutil/cpu.c +++ b/libavutil/cpu.c @@ -40,7 +40,7 @@ #include #include #endif -#if HAVE_SYSCONF +#if HAVE_UNISTD_H #include #endif @@ -150,6 +150,7 @@ int av_parse_cpu_flags(const char *s) { "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 + { "armv8", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV8 }, .unit = "flags" }, { "neon", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON }, .unit = "flags" }, { "vfp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP }, .unit = "flags" }, #endif @@ -283,6 +284,7 @@ static const struct { 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 diff --git a/libavutil/cpu.h b/libavutil/cpu.h index 0ad400fef..8ff14d3ad 100644 --- a/libavutil/cpu.h +++ b/libavutil/cpu.h @@ -63,6 +63,7 @@ #define AV_CPU_FLAG_VFP (1 << 3) #define AV_CPU_FLAG_VFPV3 (1 << 4) #define AV_CPU_FLAG_NEON (1 << 5) +#define AV_CPU_FLAG_ARMV8 (1 << 6) /** * Return the flags which specify extensions supported by the CPU. diff --git a/libavutil/crc.c b/libavutil/crc.c index b429fe1e3..d8b1c99d1 100644 --- a/libavutil/crc.c +++ b/libavutil/crc.c @@ -248,6 +248,41 @@ static const AVCRC av_crc_table[AV_CRC_MAX][257] = { 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, 0x00000001 }, + [AV_CRC_16_ANSI_LE] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040, + 0x0001 + }, }; #else #if CONFIG_SMALL @@ -266,6 +301,7 @@ static struct { [AV_CRC_24_IEEE] = { 0, 24, 0x864CFB }, [AV_CRC_32_IEEE] = { 0, 32, 0x04C11DB7 }, [AV_CRC_32_IEEE_LE] = { 1, 32, 0xEDB88320 }, + [AV_CRC_16_ANSI_LE] = { 1, 16, 0xA001 }, }; static AVCRC av_crc_table[AV_CRC_MAX][CRC_TABLE_SIZE]; #endif @@ -347,9 +383,10 @@ int main(void) { uint8_t buf[1999]; int i; - int p[5][3] = { { AV_CRC_32_IEEE_LE, 0xEDB88320, 0x3D5CDD04 }, + int p[6][3] = { { AV_CRC_32_IEEE_LE, 0xEDB88320, 0x3D5CDD04 }, { AV_CRC_32_IEEE , 0x04C11DB7, 0xC0F5BAE0 }, { AV_CRC_24_IEEE , 0x864CFB , 0xB704CE }, + { AV_CRC_16_ANSI_LE, 0xA001 , 0xBFD8 }, { AV_CRC_16_ANSI , 0x8005 , 0x1FBB }, { AV_CRC_8_ATM , 0x07 , 0xE3 } }; @@ -358,7 +395,7 @@ int main(void) for (i = 0; i < sizeof(buf); i++) buf[i] = i + i * i; - for (i = 0; i < 5; i++) { + for (i = 0; i < 6; i++) { ctx = av_crc_get_table(p[i][0]); printf("crc %08X = %X\n", p[i][1], av_crc(ctx, 0, buf, sizeof(buf))); } diff --git a/libavutil/crc.h b/libavutil/crc.h index f4219ca5b..e86bf1deb 100644 --- a/libavutil/crc.h +++ b/libavutil/crc.h @@ -39,6 +39,7 @@ typedef enum { AV_CRC_16_CCITT, AV_CRC_32_IEEE, AV_CRC_32_IEEE_LE, /*< reversed bitorder version of AV_CRC_32_IEEE */ + AV_CRC_16_ANSI_LE, /*< reversed bitorder version of AV_CRC_16_ANSI */ AV_CRC_24_IEEE = 12, AV_CRC_MAX, /*< Not part of public API! Do not use outside libavutil. */ }AVCRCId; diff --git a/libavutil/dict.c b/libavutil/dict.c index 3a0e84cd4..358958cdc 100644 --- a/libavutil/dict.c +++ b/libavutil/dict.c @@ -35,42 +35,52 @@ int av_dict_count(const AVDictionary *m) return m ? m->count : 0; } -AVDictionaryEntry * -av_dict_get(AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags) +AVDictionaryEntry *av_dict_get(FF_CONST_AVUTIL53 AVDictionary *m, const char *key, + const AVDictionaryEntry *prev, int flags) { unsigned int i, j; - if(!m) + if (!m) return NULL; - if(prev) i= prev - m->elems + 1; - else i= 0; + if (prev) + i = prev - m->elems + 1; + else + i = 0; - for(; icount; i++){ - const char *s= m->elems[i].key; - if(flags & AV_DICT_MATCH_CASE) for(j=0; s[j] == key[j] && key[j]; j++); - else for(j=0; av_toupper(s[j]) == av_toupper(key[j]) && key[j]; j++); - if(key[j]) + for (; i < m->count; i++) { + const char *s = m->elems[i].key; + if (flags & AV_DICT_MATCH_CASE) + for (j = 0; s[j] == key[j] && key[j]; j++) + ; + else + for (j = 0; av_toupper(s[j]) == av_toupper(key[j]) && key[j]; j++) + ; + if (key[j]) continue; - if(s[j] && !(flags & AV_DICT_IGNORE_SUFFIX)) + if (s[j] && !(flags & AV_DICT_IGNORE_SUFFIX)) continue; return &m->elems[i]; } return NULL; } -int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags) +int av_dict_set(AVDictionary **pm, const char *key, const char *value, + int flags) { - AVDictionary *m = *pm; + AVDictionary *m = *pm; AVDictionaryEntry *tag = av_dict_get(m, key, NULL, flags); char *oldval = NULL; - if(!m) + if (!m) m = *pm = av_mallocz(sizeof(*m)); - if(tag) { - if (flags & AV_DICT_DONT_OVERWRITE) + if (tag) { + if (flags & AV_DICT_DONT_OVERWRITE) { + if (flags & AV_DICT_DONT_STRDUP_KEY) av_free(key); + if (flags & AV_DICT_DONT_STRDUP_VAL) av_free(value); return 0; + } if (flags & AV_DICT_APPEND) oldval = tag->value; else @@ -78,16 +88,17 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags av_free(tag->key); *tag = m->elems[--m->count]; } else { - AVDictionaryEntry *tmp = av_realloc(m->elems, (m->count+1) * sizeof(*m->elems)); - if(tmp) { + AVDictionaryEntry *tmp = av_realloc(m->elems, + (m->count + 1) * sizeof(*m->elems)); + if (tmp) m->elems = tmp; - } else + else return AVERROR(ENOMEM); } if (value) { - if (flags & AV_DICT_DONT_STRDUP_KEY) { + if (flags & AV_DICT_DONT_STRDUP_KEY) m->elems[m->count].key = (char*)(intptr_t)key; - } else + else m->elems[m->count].key = av_strdup(key); if (flags & AV_DICT_DONT_STRDUP_VAL) { m->elems[m->count].value = (char*)(intptr_t)value; @@ -164,7 +175,7 @@ void av_dict_free(AVDictionary **pm) AVDictionary *m = *pm; if (m) { - while(m->count--) { + while (m->count--) { av_free(m->elems[m->count].key); av_free(m->elems[m->count].value); } @@ -173,7 +184,7 @@ void av_dict_free(AVDictionary **pm) av_freep(pm); } -void av_dict_copy(AVDictionary **dst, AVDictionary *src, int flags) +void av_dict_copy(AVDictionary **dst, FF_CONST_AVUTIL53 AVDictionary *src, int flags) { AVDictionaryEntry *t = NULL; diff --git a/libavutil/dict.h b/libavutil/dict.h index c23a2d12c..025d86799 100644 --- a/libavutil/dict.h +++ b/libavutil/dict.h @@ -31,6 +31,8 @@ #ifndef AVUTIL_DICT_H #define AVUTIL_DICT_H +#include "version.h" + /** * @addtogroup lavu_dict AVDictionary * @ingroup lavu_data @@ -97,8 +99,8 @@ typedef struct AVDictionary AVDictionary; * @param flags a collection of AV_DICT_* flags controlling how the entry is retrieved * @return found entry or NULL in case no matching entry was found in the dictionary */ -AVDictionaryEntry * -av_dict_get(AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags); +AVDictionaryEntry *av_dict_get(FF_CONST_AVUTIL53 AVDictionary *m, const char *key, + const AVDictionaryEntry *prev, int flags); /** * Get number of entries in dictionary. @@ -148,7 +150,7 @@ int av_dict_parse_string(AVDictionary **pm, const char *str, * @param flags flags to use when setting entries in *dst * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag */ -void av_dict_copy(AVDictionary **dst, AVDictionary *src, int flags); +void av_dict_copy(AVDictionary **dst, FF_CONST_AVUTIL53 AVDictionary *src, int flags); /** * Free all the memory allocated for an AVDictionary struct diff --git a/libavutil/display.c b/libavutil/display.c new file mode 100644 index 000000000..53e8aa255 --- /dev/null +++ b/libavutil/display.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014 Vittorio Giovara + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "display.h" +#include "mathematics.h" + +// fixed point to double +#define CONV_FP(x) ((double) (x)) / (1 << 16) + +// double to fixed point +#define CONV_DB(x) (int32_t) ((x) * (1 << 16)) + +double av_display_rotation_get(const int32_t matrix[9]) +{ + double rotation, scale[2]; + + scale[0] = hypot(CONV_FP(matrix[0]), CONV_FP(matrix[3])); + scale[1] = hypot(CONV_FP(matrix[1]), CONV_FP(matrix[4])); + + if (scale[0] == 0.0 || scale[1] == 0.0) + return NAN; + + rotation = atan2(CONV_FP(matrix[1]) / scale[1], + CONV_FP(matrix[0]) / scale[0]) * 180 / M_PI; + + return rotation; +} + +void av_display_rotation_set(int32_t matrix[9], double angle) +{ + double radians = angle * M_PI / 180.0f; + double c = cos(radians); + double s = sin(radians); + + memset(matrix, 0, 9 * sizeof(int32_t)); + + matrix[0] = CONV_DB(c); + matrix[1] = CONV_DB(-s); + matrix[3] = CONV_DB(s); + matrix[4] = CONV_DB(c); + matrix[8] = 1 << 30; +} + +void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip) +{ + int i; + const int flip[] = { 1 - 2 * (!!hflip), 1 - 2 * (!!vflip), 1 }; + + if (hflip || vflip) + for (i = 0; i < 9; i++) + matrix[i] *= flip[i % 3]; +} diff --git a/libavutil/display.h b/libavutil/display.h new file mode 100644 index 000000000..2cb930dde --- /dev/null +++ b/libavutil/display.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014 Vittorio Giovara + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_DISPLAY_H +#define AVUTIL_DISPLAY_H + +#include + +/** + * The display transformation matrix specifies an affine transformation that + * should be applied to video frames for correct presentation. It is compatible + * with the matrices stored in the ISO/IEC 14496-12 container format. + * + * The data is a 3x3 matrix represented as a 9-element array: + * + * | a b u | + * (a, b, u, c, d, v, x, y, w) -> | c d v | + * | x y w | + * + * All numbers are stored in native endianness, as 16.16 fixed-point values, + * except for u, v and w, which are stored as 2.30 fixed-point values. + * + * The transformation maps a point (p, q) in the source (pre-transformation) + * frame to the point (p', q') in the destination (post-transformation) frame as + * follows: + * | a b u | + * (p, q, 1) . | c d v | = z * (p', q', 1) + * | x y w | + * + * The transformation can also be more explicitly written in components as + * follows: + * p' = (a * p + c * q + x) / z; + * q' = (b * p + d * q + y) / z; + * z = u * p + v * q + w + */ + +/** + * 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. + * + * @note floating point numbers are inherently inexact, so callers are + * recommended to round the return value to nearest integer before use. + */ +double av_display_rotation_get(const int32_t matrix[9]); + +/** + * Initialize a transformation matrix describing a pure rotation by the + * specified angle (in degrees). + * + * @param matrix an allocated transformation matrix (will be fully overwritten + * by this function) + * @param angle rotation angle in degrees. + */ +void av_display_rotation_set(int32_t matrix[9], double angle); + +/** + * Flip the input matrix horizontally and/or vertically. + * + * @param matrix an allocated transformation matrix + * @param hflip whether the matrix should be flipped horizontally + * @param vflip whether the matrix should be flipped vertically + */ +void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip); + +#endif /* AVUTIL_DISPLAY_H */ diff --git a/libavutil/downmix_info.h b/libavutil/downmix_info.h index c369891c0..221cf5bf9 100644 --- a/libavutil/downmix_info.h +++ b/libavutil/downmix_info.h @@ -95,11 +95,12 @@ typedef struct AVDownmixInfo { /** * Get a frame's AV_FRAME_DATA_DOWNMIX_INFO side data for editing. * - * The side data is created and added to the frame if it's absent. + * If the side data is absent, it is created and added to the frame. * - * @param frame the frame for which the side data is to be obtained. + * @param frame the frame for which the side data is to be obtained or created * - * @return the AVDownmixInfo structure to be edited by the caller. + * @return the AVDownmixInfo structure to be edited by the caller, or NULL if + * the structure cannot be allocated. */ AVDownmixInfo *av_downmix_info_update_side_data(AVFrame *frame); diff --git a/libavutil/dynarray.h b/libavutil/dynarray.h new file mode 100644 index 000000000..4947d93dc --- /dev/null +++ b/libavutil/dynarray.h @@ -0,0 +1,70 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_DYNARRAY_H +#define AVUTIL_DYNARRAY_H + +#include "log.h" +#include "mem.h" + +/** + * Add an element of to a dynamic array. + * + * The array is reallocated when its number of elements reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the size is incremented. + * + * @param av_size_max maximum size of the array, usually the MAX macro of + * the type of the size + * @param av_elt_size size of the elements in the array, in bytes + * @param av_array pointer to the array, must be a lvalue + * @param av_size size of the array, must be an integer lvalue + * @param av_success statement to execute on success; at this point, the + * size variable is not yet incremented + * @param av_failure statement to execute on failure; if this happens, the + * array and size are not changed; the statement can end + * with a return or a goto + */ +#define AV_DYNARRAY_ADD(av_size_max, av_elt_size, av_array, av_size, \ + av_success, av_failure) \ + do { \ + size_t av_size_new = (av_size); \ + if (!((av_size) & ((av_size) - 1))) { \ + av_size_new = (av_size) ? (av_size) << 1 : 1; \ + if (av_size_new > (av_size_max) / (av_elt_size)) { \ + av_size_new = 0; \ + } else { \ + void *av_array_new = \ + av_realloc((av_array), av_size_new * (av_elt_size)); \ + if (!av_array_new) \ + av_size_new = 0; \ + else \ + (av_array) = av_array_new; \ + } \ + } \ + if (av_size_new) { \ + { av_success } \ + (av_size)++; \ + } else { \ + av_failure \ + } \ + } while (0) + +#endif /* AVUTIL_DYNARRAY_H */ diff --git a/libavutil/fifo.c b/libavutil/fifo.c index ca25bc523..77391ee7f 100644 --- a/libavutil/fifo.c +++ b/libavutil/fifo.c @@ -24,19 +24,34 @@ #include "common.h" #include "fifo.h" -AVFifoBuffer *av_fifo_alloc(unsigned int size) +static AVFifoBuffer *fifo_alloc_common(void *buffer, size_t size) { - AVFifoBuffer *f = av_mallocz(sizeof(AVFifoBuffer)); - if (!f) + AVFifoBuffer *f; + if (!buffer) return NULL; - f->buffer = av_malloc(size); + f = av_mallocz(sizeof(AVFifoBuffer)); + if (!f) { + av_free(buffer); + return NULL; + } + f->buffer = buffer; f->end = f->buffer + size; av_fifo_reset(f); - if (!f->buffer) - av_freep(&f); return f; } +AVFifoBuffer *av_fifo_alloc(unsigned int size) +{ + void *buffer = av_malloc(size); + return fifo_alloc_common(buffer, size); +} + +AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size) +{ + void *buffer = av_malloc_array(nmemb, size); + return fifo_alloc_common(buffer, nmemb * size); +} + void av_fifo_free(AVFifoBuffer *f) { if (f) { @@ -45,18 +60,26 @@ void av_fifo_free(AVFifoBuffer *f) } } +void av_fifo_freep(AVFifoBuffer **f) +{ + if (f) { + av_fifo_free(*f); + *f = NULL; + } +} + void av_fifo_reset(AVFifoBuffer *f) { f->wptr = f->rptr = f->buffer; f->wndx = f->rndx = 0; } -int av_fifo_size(AVFifoBuffer *f) +int av_fifo_size(FF_CONST_AVUTIL53 AVFifoBuffer *f) { return (uint32_t)(f->wndx - f->rndx); } -int av_fifo_space(AVFifoBuffer *f) +int av_fifo_space(FF_CONST_AVUTIL53 AVFifoBuffer *f) { return f->end - f->buffer - av_fifo_size(f); } diff --git a/libavutil/fifo.h b/libavutil/fifo.h index 849b9a6b8..dda7dd2e9 100644 --- a/libavutil/fifo.h +++ b/libavutil/fifo.h @@ -41,12 +41,26 @@ typedef struct AVFifoBuffer { */ AVFifoBuffer *av_fifo_alloc(unsigned int size); +/** + * Initialize an AVFifoBuffer. + * @param nmemb number of elements + * @param size size of the single element + * @return AVFifoBuffer or NULL in case of memory allocation failure + */ +AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size); + /** * Free an AVFifoBuffer. * @param f AVFifoBuffer to free */ void av_fifo_free(AVFifoBuffer *f); +/** + * Free an AVFifoBuffer and reset pointer to NULL. + * @param f AVFifoBuffer to free + */ +void av_fifo_freep(AVFifoBuffer **f); + /** * Reset the AVFifoBuffer to the state right after av_fifo_alloc, in particular it is emptied. * @param f AVFifoBuffer to reset @@ -59,7 +73,7 @@ void av_fifo_reset(AVFifoBuffer *f); * @param f AVFifoBuffer to read from * @return size */ -int av_fifo_size(AVFifoBuffer *f); +int av_fifo_size(FF_CONST_AVUTIL53 AVFifoBuffer *f); /** * Return the amount of space in bytes in the AVFifoBuffer, that is the @@ -67,7 +81,7 @@ int av_fifo_size(AVFifoBuffer *f); * @param f AVFifoBuffer to write into * @return size */ -int av_fifo_space(AVFifoBuffer *f); +int av_fifo_space(FF_CONST_AVUTIL53 AVFifoBuffer *f); /** * Feed data from an AVFifoBuffer to a user-supplied callback. diff --git a/libavutil/file_open.c b/libavutil/file_open.c index bcdd26ae3..f3164ebe6 100644 --- a/libavutil/file_open.c +++ b/libavutil/file_open.c @@ -48,7 +48,7 @@ static int win32_open(const char *filename_utf8, int oflag, int pmode) 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); + filename_w = av_mallocz_array(num_chars, sizeof(wchar_t)); if (!filename_w) { errno = ENOMEM; return -1; diff --git a/libavutil/fixed_dsp.c b/libavutil/fixed_dsp.c new file mode 100644 index 000000000..b99fea519 --- /dev/null +++ b/libavutil/fixed_dsp.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nedeljko Babic (nbabic@mips.com) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "fixed_dsp.h" + +static void vector_fmul_window_fixed_scaled_c(int16_t *dst, const int32_t *src0, + const int32_t *src1, const int32_t *win, + int len, uint8_t bits) +{ + int32_t s0, s1, wi, wj, i,j, round; + + dst += len; + win += len; + src0+= len; + round = bits? 1 << (bits-1) : 0; + + for (i=-len, j=len-1; i<0; i++, j--) { + s0 = src0[i]; + s1 = src1[j]; + wi = win[i]; + wj = win[j]; + dst[i] = av_clip_int16_c(((((int64_t)s0*wj - (int64_t)s1*wi + 0x40000000) >> 31) + round) >> bits); + dst[j] = av_clip_int16_c(((((int64_t)s0*wi + (int64_t)s1*wj + 0x40000000) >> 31) + round) >> bits); + } +} + +static void vector_fmul_window_fixed_c(int32_t *dst, const int32_t *src0, + const int32_t *src1, const int32_t *win, + int len) +{ + int32_t s0, s1, wi, wj, i, j; + + dst += len; + win += len; + src0+= len; + + for (i=-len, j=len-1; i<0; i++, j--) { + s0 = src0[i]; + s1 = src1[j]; + wi = win[i]; + wj = win[j]; + dst[i] = ((int64_t)s0*wj - (int64_t)s1*wi + 0x40000000) >> 31; + dst[j] = ((int64_t)s0*wi + (int64_t)s1*wj + 0x40000000) >> 31; + } +} + +AVFixedDSPContext * avpriv_alloc_fixed_dsp(int bit_exact) +{ + AVFixedDSPContext * fdsp = av_malloc(sizeof(AVFixedDSPContext)); + fdsp->vector_fmul_window_scaled = vector_fmul_window_fixed_scaled_c; + fdsp->vector_fmul_window = vector_fmul_window_fixed_c; + + return fdsp; +} diff --git a/libavutil/fixed_dsp.h b/libavutil/fixed_dsp.h new file mode 100644 index 000000000..ff6f36599 --- /dev/null +++ b/libavutil/fixed_dsp.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nedeljko Babic (nbabic@mips.com) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_FIXED_DSP_H +#define AVUTIL_FIXED_DSP_H + +#include +#include "attributes.h" +#include "common.h" +#include "libavcodec/mathops.h" + +typedef struct AVFixedDSPContext { + /** + * Overlap/add with window function. + * Used primarily by MDCT-based audio codecs. + * Source and destination vectors must overlap exactly or not at all. + * + * @param dst result vector + * constraints: 16-byte aligned + * @param src0 first source vector + * constraints: 16-byte aligned + * @param src1 second source vector + * constraints: 16-byte aligned + * @param win half-window vector + * constraints: 16-byte aligned + * @param len length of vector + * constraints: multiple of 4 + * @param bits scaling parameter + * + */ + void (*vector_fmul_window_scaled)(int16_t *dst, const int32_t *src0, const int32_t *src1, const int32_t *win, int len, uint8_t bits); + + /** + * Overlap/add with window function. + * Used primarily by MDCT-based audio codecs. + * Source and destination vectors must overlap exactly or not at all. + * + * @param dst result vector + * constraints: 32-byte aligned + * @param src0 first source vector + * constraints: 16-byte aligned + * @param src1 second source vector + * constraints: 16-byte aligned + * @param win half-window vector + * constraints: 16-byte aligned + * @param len length of vector + * constraints: multiple of 4 + */ + void (*vector_fmul_window)(int32_t *dst, const int32_t *src0, const int32_t *src1, const int32_t *win, int len); + +} AVFixedDSPContext; + +/** + * Allocate and initialize a fixed DSP context. + * note: should be freed with a av_free call when no longer needed. + * + * @param strict setting to non-zero avoids using functions which may not be IEEE-754 compliant + */ +AVFixedDSPContext * avpriv_alloc_fixed_dsp(int strict); + +/** + * Calculate the square root + * + * @param x input fixed point number + * + * @param bits format of fixed point number (32 - bits).bits + * + * note: input is normalized to (0, 1) fixed point value + */ + +static av_always_inline int fixed_sqrt(int x, int bits) +{ + int retval, bit_mask, guess, square, i; + int64_t accu; + int shift1 = 30 - bits; + int shift2 = bits - 15; + + if (shift1 > 0) retval = ff_sqrt(x << shift1); + else retval = ff_sqrt(x >> -shift1); + + if (shift2 > 0) { + retval = retval << shift2; + bit_mask = (1 << (shift2 - 1)); + + for (i=0; i> bits); + if (x >= square) + retval += bit_mask; + bit_mask >>= 1; + } + + } + else retval >>= (-shift2); + + return retval; +} + +#endif /* AVUTIL_FIXED_DSP_H */ diff --git a/libavutil/float_dsp.c b/libavutil/float_dsp.c index efff47f89..8ac74800e 100644 --- a/libavutil/float_dsp.c +++ b/libavutil/float_dsp.c @@ -127,13 +127,299 @@ av_cold void avpriv_float_dsp_init(AVFloatDSPContext *fdsp, int bit_exact) fdsp->butterflies_float = butterflies_float_c; fdsp->scalarproduct_float = avpriv_scalarproduct_float_c; -#if ARCH_ARM - ff_float_dsp_init_arm(fdsp); -#elif ARCH_PPC - ff_float_dsp_init_ppc(fdsp, bit_exact); -#elif ARCH_X86 - ff_float_dsp_init_x86(fdsp); -#elif ARCH_MIPS - ff_float_dsp_init_mips(fdsp); -#endif + if (ARCH_AARCH64) + ff_float_dsp_init_aarch64(fdsp); + if (ARCH_ARM) + ff_float_dsp_init_arm(fdsp); + if (ARCH_PPC) + ff_float_dsp_init_ppc(fdsp, bit_exact); + if (ARCH_X86) + ff_float_dsp_init_x86(fdsp); + if (ARCH_MIPS) + ff_float_dsp_init_mips(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/float_dsp.h b/libavutil/float_dsp.h index 3424cb544..7fc851b6e 100644 --- a/libavutil/float_dsp.h +++ b/libavutil/float_dsp.h @@ -179,6 +179,7 @@ float avpriv_scalarproduct_float_c(const float *v1, const float *v2, int len); void avpriv_float_dsp_init(AVFloatDSPContext *fdsp, int strict); +void ff_float_dsp_init_aarch64(AVFloatDSPContext *fdsp); void ff_float_dsp_init_arm(AVFloatDSPContext *fdsp); void ff_float_dsp_init_ppc(AVFloatDSPContext *fdsp, int strict); void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp); diff --git a/libavutil/frame.c b/libavutil/frame.c index 747aa79b8..fdfbc4675 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -103,8 +103,23 @@ static void get_frame_defaults(AVFrame *frame) frame->key_frame = 1; frame->sample_aspect_ratio = (AVRational){ 0, 1 }; frame->format = -1; /* unknown */ - frame->colorspace = AVCOL_SPC_UNSPECIFIED; frame->extended_data = frame->data; +#if FF_API_AVFRAME_COLORSPACE + frame->color_primaries = AVCOL_PRI_UNSPECIFIED; + frame->color_trc = AVCOL_TRC_UNSPECIFIED; + frame->colorspace = AVCOL_SPC_UNSPECIFIED; + frame->color_range = AVCOL_RANGE_UNSPECIFIED; + frame->chroma_location = AVCHROMA_LOC_UNSPECIFIED; +#endif +} + +static void free_side_data(AVFrameSideData **ptr_sd) +{ + AVFrameSideData *sd = *ptr_sd; + + av_freep(&sd->data); + av_dict_free(&sd->metadata); + av_freep(ptr_sd); } AVFrame *av_frame_alloc(void) @@ -204,9 +219,9 @@ static int get_audio_buffer(AVFrame *frame, int align) } if (planes > AV_NUM_DATA_POINTERS) { - frame->extended_data = av_mallocz(planes * + frame->extended_data = av_mallocz_array(planes, sizeof(*frame->extended_data)); - frame->extended_buf = av_mallocz((planes - AV_NUM_DATA_POINTERS) * + frame->extended_buf = av_mallocz_array((planes - AV_NUM_DATA_POINTERS), sizeof(*frame->extended_buf)); if (!frame->extended_data || !frame->extended_buf) { av_freep(&frame->extended_data); @@ -290,7 +305,7 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) } if (src->extended_buf) { - dst->extended_buf = av_mallocz(sizeof(*dst->extended_buf) * + dst->extended_buf = av_mallocz_array(sizeof(*dst->extended_buf), src->nb_extended_buf); if (!dst->extended_buf) { ret = AVERROR(ENOMEM); @@ -317,7 +332,7 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) } CHECK_CHANNELS_CONSISTENCY(src); - dst->extended_data = av_malloc(sizeof(*dst->extended_data) * ch); + dst->extended_data = av_malloc_array(sizeof(*dst->extended_data), ch); if (!dst->extended_data) { ret = AVERROR(ENOMEM); goto fail; @@ -354,9 +369,7 @@ void av_frame_unref(AVFrame *frame) int i; for (i = 0; i < frame->nb_side_data; i++) { - av_freep(&frame->side_data[i]->data); - av_dict_free(&frame->side_data[i]->metadata); - av_freep(&frame->side_data[i]); + free_side_data(&frame->side_data[i]); } av_freep(&frame->side_data); @@ -469,8 +482,13 @@ int av_frame_copy_props(AVFrame *dst, const AVFrame *src) dst->display_picture_number = src->display_picture_number; dst->flags = src->flags; dst->decode_error_flags = src->decode_error_flags; +#if FF_API_AVFRAME_COLORSPACE + dst->color_primaries = src->color_primaries; + dst->color_trc = src->color_trc; dst->colorspace = src->colorspace; dst->color_range = src->color_range; + dst->chroma_location = src->chroma_location; +#endif av_dict_copy(&dst->metadata, src->metadata, 0); @@ -482,9 +500,7 @@ int av_frame_copy_props(AVFrame *dst, const AVFrame *src) sd_src->size); if (!sd_dst) { for (i = 0; i < dst->nb_side_data; i++) { - av_freep(&dst->side_data[i]->data); - av_freep(&dst->side_data[i]); - av_dict_free(&dst->side_data[i]->metadata); + free_side_data(&dst->side_data[i]); } av_freep(&dst->side_data); return AVERROR(ENOMEM); @@ -589,8 +605,8 @@ static int frame_copy_video(AVFrame *dst, const AVFrame *src) const uint8_t *src_data[4]; int i, planes; - if (dst->width != src->width || - dst->height != src->height) + if (dst->width < src->width || + dst->height < src->height) return AVERROR(EINVAL); planes = av_pix_fmt_count_planes(dst->format); @@ -601,7 +617,7 @@ static int frame_copy_video(AVFrame *dst, const AVFrame *src) memcpy(src_data, src->data, sizeof(src_data)); av_image_copy(dst->data, dst->linesize, src_data, src->linesize, - dst->format, dst->width, dst->height); + dst->format, src->width, src->height); return 0; } @@ -642,3 +658,17 @@ int av_frame_copy(AVFrame *dst, const AVFrame *src) return AVERROR(EINVAL); } + +void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type) +{ + int i; + + for (i = 0; i < frame->nb_side_data; i++) { + AVFrameSideData *sd = frame->side_data[i]; + if (sd->type == type) { + free_side_data(&frame->side_data[i]); + frame->side_data[i] = frame->side_data[frame->nb_side_data - 1]; + frame->nb_side_data--; + } + } +} diff --git a/libavutil/frame.h b/libavutil/frame.h index 9fedba863..a39c8d07f 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -33,32 +33,10 @@ #include "dict.h" #include "rational.h" #include "samplefmt.h" +#include "pixfmt.h" #include "version.h" -enum AVColorSpace{ - AVCOL_SPC_RGB = 0, - AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B - AVCOL_SPC_UNSPECIFIED = 2, - AVCOL_SPC_FCC = 4, - AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 - AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above - AVCOL_SPC_SMPTE240M = 7, - AVCOL_SPC_YCOCG = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 - AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system - AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system - AVCOL_SPC_NB , ///< Not part of ABI -}; -#define AVCOL_SPC_YCGCO AVCOL_SPC_YCOCG - -enum AVColorRange{ - AVCOL_RANGE_UNSPECIFIED = 0, - AVCOL_RANGE_MPEG = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges - AVCOL_RANGE_JPEG = 2, ///< the normal 2^n-1 "JPEG" YUV ranges - AVCOL_RANGE_NB , ///< Not part of ABI -}; - - /** * @defgroup lavu_frame AVFrame * @ingroup lavu_data @@ -92,6 +70,18 @@ enum AVFrameSideDataType { * The data is the AVDownmixInfo struct defined in libavutil/downmix_info.h. */ AV_FRAME_DATA_DOWNMIX_INFO, + /** + * ReplayGain information in the form of the AVReplayGain struct. + */ + AV_FRAME_DATA_REPLAYGAIN, + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the frame for correct + * presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_FRAME_DATA_DISPLAYMATRIX, }; typedef struct AVFrameSideData { @@ -224,7 +214,7 @@ typedef struct AVFrame { int64_t pkt_pts; /** - * DTS copied from the AVPacket that triggered returning this frame. (if frame threading isnt used) + * DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used) * This is also the Presentation time of this AVFrame calculated from * only AVPacket.dts values without pts values. */ @@ -279,7 +269,6 @@ typedef struct AVFrame { * motion_val[direction][x + y*mv_stride][0->mv_x, 1->mv_y]; * @endcode */ - attribute_deprecated int16_t (*motion_val[2])[2]; /** @@ -376,7 +365,6 @@ typedef struct AVFrame { * 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 @@ -443,6 +431,32 @@ typedef struct AVFrame { */ int flags; +#if FF_API_AVFRAME_COLORSPACE + /** + * MPEG vs JPEG YUV range. + * It must be accessed using av_frame_get_color_range() and + * av_frame_set_color_range(). + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorRange color_range; + + enum AVColorPrimaries color_primaries; + + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * It must be accessed using av_frame_get_colorspace() and + * av_frame_set_colorspace(). + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + enum AVChromaLocation chroma_location; +#endif + /** * frame timestamp estimated using various heuristics, in stream time base * Code outside libavcodec should access this field using: @@ -512,25 +526,6 @@ typedef struct AVFrame { */ int pkt_size; - /** - * YUV colorspace type. - * It must be accessed using av_frame_get_colorspace() and - * av_frame_set_colorspace(). - * - encoding: Set by user - * - decoding: Set by libavcodec - */ - enum AVColorSpace colorspace; - - /** - * MPEG vs JPEG YUV range. - * It must be accessed using av_frame_get_color_range() and - * av_frame_set_color_range(). - * - encoding: Set by user - * - decoding: Set by libavcodec - */ - enum AVColorRange color_range; - - /** * Not to be accessed directly from outside libavutil */ @@ -726,6 +721,12 @@ AVFrameSideData *av_frame_new_side_data(AVFrame *frame, AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type); +/** + * If side data of the supplied type exists in the frame, free it and remove it + * from the frame. + */ +void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type); + /** * @} */ diff --git a/libavutil/hash.c b/libavutil/hash.c index a8cf80b57..773f29e23 100644 --- a/libavutil/hash.c +++ b/libavutil/hash.c @@ -29,6 +29,7 @@ #include "sha512.h" #include "avstring.h" +#include "base64.h" #include "error.h" #include "intreadwrite.h" #include "mem.h" @@ -196,6 +197,40 @@ void av_hash_final(AVHashContext *ctx, uint8_t *dst) } } +void av_hash_final_bin(struct AVHashContext *ctx, uint8_t *dst, int size) +{ + uint8_t buf[AV_HASH_MAX_SIZE]; + unsigned rsize = av_hash_get_size(ctx); + + av_hash_final(ctx, buf); + memcpy(dst, buf, FFMIN(size, rsize)); + if (size > rsize) + memset(dst + rsize, 0, size - rsize); +} + +void av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size) +{ + uint8_t buf[AV_HASH_MAX_SIZE]; + unsigned rsize = av_hash_get_size(ctx), i; + + av_hash_final(ctx, buf); + for (i = 0; i < FFMIN(rsize, size / 2); i++) + snprintf(dst + i * 2, size - i * 2, "%02x", buf[i]); +} + +void av_hash_final_b64(struct AVHashContext *ctx, uint8_t *dst, int size) +{ + uint8_t buf[AV_HASH_MAX_SIZE], b64[AV_BASE64_SIZE(AV_HASH_MAX_SIZE)]; + unsigned rsize = av_hash_get_size(ctx), osize; + + av_hash_final(ctx, buf); + av_base64_encode(b64, sizeof(b64), buf, rsize); + osize = AV_BASE64_SIZE(rsize); + memcpy(dst, b64, FFMIN(osize, size)); + if (size < osize) + dst[size - 1] = 0; +} + void av_hash_freep(AVHashContext **ctx) { if (*ctx) diff --git a/libavutil/hash.h b/libavutil/hash.h index 9bf715e1a..d4bcbf8cc 100644 --- a/libavutil/hash.h +++ b/libavutil/hash.h @@ -82,6 +82,28 @@ void av_hash_update(struct AVHashContext *ctx, const uint8_t *src, int len); */ void av_hash_final(struct AVHashContext *ctx, uint8_t *dst); +/** + * Finalize a hash context and compute the actual hash value. + * If size is smaller than the hash size, the hash is truncated; + * if size is larger, the buffer is padded with 0. + */ +void av_hash_final_bin(struct AVHashContext *ctx, uint8_t *dst, int size); + +/** + * Finalize a hash context and compute the actual hash value as a hex string. + * The string is always 0-terminated. + * If size is smaller than 2 * hash_size + 1, the hex string is truncated. + */ +void av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size); + +/** + * Finalize a hash context and compute the actual hash value as a base64 string. + * The string is always 0-terminated. + * If size is smaller than AV_BASE64_SIZE(hash_size), the base64 string is + * truncated. + */ +void av_hash_final_b64(struct AVHashContext *ctx, uint8_t *dst, int size); + /** * Free hash context. */ diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c index d8a579fc6..00b203182 100644 --- a/libavutil/imgutils.c +++ b/libavutil/imgutils.c @@ -27,7 +27,9 @@ #include "internal.h" #include "intreadwrite.h" #include "log.h" +#include "mathematics.h" #include "pixdesc.h" +#include "rational.h" void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], const AVPixFmtDescriptor *pixdesc) @@ -181,7 +183,7 @@ int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt) default: return AVERROR(EINVAL); } - pal[i] = b + (g<<8) + (r<<16) + (0xFFU<<24); + pal[i] = b + (g << 8) + (r << 16) + (0xFFU << 24); } return 0; @@ -239,6 +241,27 @@ int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *lo return AVERROR(EINVAL); } +int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar) +{ + int64_t scaled_dim; + + if (!sar.den) + return AVERROR(EINVAL); + + if (!sar.num || sar.num == sar.den) + return 0; + + if (sar.num < sar.den) + scaled_dim = av_rescale_rnd(w, sar.num, sar.den, AV_ROUND_ZERO); + else + scaled_dim = av_rescale_rnd(h, sar.den, sar.num, AV_ROUND_ZERO); + + if (scaled_dim > 0) + return 0; + + return AVERROR(EINVAL); +} + void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height) diff --git a/libavutil/imgutils.h b/libavutil/imgutils.h index ab32d667d..775baaa3b 100644 --- a/libavutil/imgutils.h +++ b/libavutil/imgutils.h @@ -29,6 +29,7 @@ #include "avutil.h" #include "pixdesc.h" +#include "rational.h" /** * Compute the max pixel step for each plane of an image with a @@ -190,6 +191,20 @@ int av_image_copy_to_buffer(uint8_t *dst, int dst_size, */ int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx); +/** + * Check if the given sample aspect ratio of an image is valid. + * + * It is considered invalid if the denominator is 0 or if applying the ratio + * to the image size would make the smaller dimension less than 1. If the + * sar numerator is 0, it is considered unknown and will return as valid. + * + * @param w width of the image + * @param h height of the image + * @param sar sample aspect ratio of the image + * @return 0 if valid, a negative AVERROR code otherwise + */ +int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar); + int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt); /** diff --git a/libavutil/internal.h b/libavutil/internal.h index 9c5546f3b..ea3c31e4f 100644 --- a/libavutil/internal.h +++ b/libavutil/internal.h @@ -93,6 +93,13 @@ // to be forced to tokenize __VA_ARGS__ #define E1(x) x +/* Check if the hard coded offset of a struct member still matches reality. + * Induce a compilation failure if not. + */ +#define AV_CHECK_OFFSET(s, m, o) struct check_##o { \ + int x_##o[offsetof(s, m) == o? 1: -1]; \ + } + #define LOCAL_ALIGNED_A(a, t, v, s, o, ...) \ uint8_t la_##v[sizeof(t s o) + (a)]; \ t (*v) o = (void *)FFALIGN((uintptr_t)la_##v, a) @@ -115,6 +122,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);\ @@ -133,6 +146,24 @@ }\ } +#define FF_ALLOC_ARRAY_OR_GOTO(ctx, p, nelem, elsize, label)\ +{\ + p = av_malloc_array(nelem, elsize);\ + if (p == NULL) {\ + av_log(ctx, AV_LOG_ERROR, "Cannot allocate memory.\n");\ + goto label;\ + }\ +} + +#define FF_ALLOCZ_ARRAY_OR_GOTO(ctx, p, nelem, elsize, label)\ +{\ + p = av_mallocz_array(nelem, elsize);\ + if (p == NULL) {\ + av_log(ctx, AV_LOG_ERROR, "Cannot allocate memory.\n");\ + goto label;\ + }\ +} + #include "libm.h" #if defined(_MSC_VER) @@ -213,6 +244,11 @@ void avpriv_request_sample(void *avc, #if HAVE_LIBC_MSVCRT #define avpriv_open ff_open +#define PTRDIFF_SPECIFIER "Id" +#define SIZE_SPECIFIER "Iu" +#else +#define PTRDIFF_SPECIFIER "td" +#define SIZE_SPECIFIER "zu" #endif /** diff --git a/libavutil/libm.h b/libavutil/libm.h index 6c17b287b..28d5df871 100644 --- a/libavutil/libm.h +++ b/libavutil/libm.h @@ -82,6 +82,16 @@ static av_always_inline float cbrtf(float x) #define exp2f(x) ((float)exp2(x)) #endif /* HAVE_EXP2F */ +#if !HAVE_FMINF +#undef fminf +static av_always_inline av_const float fminf(float x, float y) +{ + //Note, the NaN special case is needed for C spec compliance, it should be + //optimized away if the users compiler is configured to assume no NaN + return x > y ? y : (x == x ? x : y); +} +#endif + #if !HAVE_ISINF static av_always_inline av_const int isinf(float x) { diff --git a/libavutil/log.c b/libavutil/log.c index 38ce1e8fc..209131695 100644 --- a/libavutil/log.c +++ b/libavutil/log.c @@ -50,7 +50,7 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static int av_log_level = AV_LOG_INFO; static int flags; -#if HAVE_SETCONSOLETEXTATTRIBUTE +#if defined(_WIN32) && !defined(__MINGW32CE__) && HAVE_SETCONSOLETEXTATTRIBUTE #include static const uint8_t color[16 + AV_CLASS_CATEGORY_NB] = { [AV_LOG_PANIC /8] = 12, @@ -71,6 +71,12 @@ static const uint8_t color[16 + AV_CLASS_CATEGORY_NB] = { [16+AV_CLASS_CATEGORY_BITSTREAM_FILTER] = 9, [16+AV_CLASS_CATEGORY_SWSCALER ] = 7, [16+AV_CLASS_CATEGORY_SWRESAMPLER ] = 7, + [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT ] = 13, + [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT ] = 5, + [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT ] = 13, + [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT ] = 5, + [16+AV_CLASS_CATEGORY_DEVICE_OUTPUT ] = 13, + [16+AV_CLASS_CATEGORY_DEVICE_INPUT ] = 5, }; static int16_t background, attr_orig; @@ -96,53 +102,74 @@ static const uint32_t color[16 + AV_CLASS_CATEGORY_NB] = { [16+AV_CLASS_CATEGORY_BITSTREAM_FILTER] = 192 << 8 | 0x14, [16+AV_CLASS_CATEGORY_SWSCALER ] = 153 << 8 | 0x14, [16+AV_CLASS_CATEGORY_SWRESAMPLER ] = 147 << 8 | 0x14, + [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT ] = 213 << 8 | 0x15, + [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT ] = 207 << 8 | 0x05, + [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT ] = 213 << 8 | 0x15, + [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT ] = 207 << 8 | 0x05, + [16+AV_CLASS_CATEGORY_DEVICE_OUTPUT ] = 213 << 8 | 0x15, + [16+AV_CLASS_CATEGORY_DEVICE_INPUT ] = 207 << 8 | 0x05, }; #endif static int use_color = -1; -static void colored_fputs(int level, const char *str) +static void check_color_terminal(void) { +#if defined(_WIN32) && !defined(__MINGW32CE__) && HAVE_SETCONSOLETEXTATTRIBUTE + CONSOLE_SCREEN_BUFFER_INFO con_info; + con = GetStdHandle(STD_ERROR_HANDLE); + use_color = (con != INVALID_HANDLE_VALUE) && !getenv("NO_COLOR") && + !getenv("AV_LOG_FORCE_NOCOLOR"); + if (use_color) { + GetConsoleScreenBufferInfo(con, &con_info); + attr_orig = con_info.wAttributes; + background = attr_orig & 0xF0; + } +#elif HAVE_ISATTY + char *term = getenv("TERM"); + use_color = !getenv("NO_COLOR") && !getenv("AV_LOG_FORCE_NOCOLOR") && + (getenv("TERM") && isatty(2) || getenv("AV_LOG_FORCE_COLOR")); + if ( getenv("AV_LOG_FORCE_256COLOR") + || (term && strstr(term, "256color"))) + use_color *= 256; +#else + use_color = getenv("AV_LOG_FORCE_COLOR") && !getenv("NO_COLOR") && + !getenv("AV_LOG_FORCE_NOCOLOR"); +#endif +} + +static void colored_fputs(int level, int tint, const char *str) +{ + int local_use_color; if (!*str) return; - if (use_color < 0) { -#if HAVE_SETCONSOLETEXTATTRIBUTE - CONSOLE_SCREEN_BUFFER_INFO con_info; - con = GetStdHandle(STD_ERROR_HANDLE); - use_color = (con != INVALID_HANDLE_VALUE) && !getenv("NO_COLOR") && - !getenv("AV_LOG_FORCE_NOCOLOR"); - if (use_color) { - GetConsoleScreenBufferInfo(con, &con_info); - attr_orig = con_info.wAttributes; - background = attr_orig & 0xF0; - } -#elif HAVE_ISATTY - use_color = !getenv("NO_COLOR") && !getenv("AV_LOG_FORCE_NOCOLOR") && - (getenv("TERM") && isatty(2) || - getenv("AV_LOG_FORCE_COLOR")); - if (getenv("AV_LOG_FORCE_256COLOR")) - use_color *= 256; -#else - use_color = getenv("AV_LOG_FORCE_COLOR") && !getenv("NO_COLOR") && - !getenv("AV_LOG_FORCE_NOCOLOR"); -#endif - } + if (use_color < 0) + check_color_terminal(); -#if HAVE_SETCONSOLETEXTATTRIBUTE - if (use_color && level != AV_LOG_INFO/8) + if (level == AV_LOG_INFO/8) local_use_color = 0; + else local_use_color = use_color; + +#if defined(_WIN32) && !defined(__MINGW32CE__) && HAVE_SETCONSOLETEXTATTRIBUTE + if (local_use_color) SetConsoleTextAttribute(con, background | color[level]); fputs(str, stderr); - if (use_color && level != AV_LOG_INFO/8) + if (local_use_color) SetConsoleTextAttribute(con, attr_orig); #else - if (use_color == 1 && level != AV_LOG_INFO/8) { + if (local_use_color == 1) { fprintf(stderr, "\033[%d;3%dm%s\033[0m", (color[level] >> 4) & 15, color[level] & 15, str); - } else if (use_color == 256 && level != AV_LOG_INFO/8) { + } else if (tint && use_color == 256) { + fprintf(stderr, + "\033[48;5;%dm\033[38;5;%dm%s\033[0m", + (color[level] >> 16) & 0xff, + tint, + str); + } else if (local_use_color == 256) { fprintf(stderr, "\033[48;5;%dm\033[38;5;%dm%s\033[0m", (color[level] >> 16) & 0xff, @@ -185,13 +212,38 @@ static int get_category(void *ptr){ return avc->category + 16; } +static const char *get_level_str(int level) +{ + switch (level) { + case AV_LOG_QUIET: + return "quiet"; + case AV_LOG_DEBUG: + return "debug"; + case AV_LOG_VERBOSE: + return "verbose"; + case AV_LOG_INFO: + return "info"; + case AV_LOG_WARNING: + return "warning"; + case AV_LOG_ERROR: + return "error"; + case AV_LOG_FATAL: + return "fatal"; + case AV_LOG_PANIC: + return "panic"; + default: + return ""; + } +} + static void format_line(void *avcl, int level, const char *fmt, va_list vl, - AVBPrint part[3], int *print_prefix, int type[2]) + AVBPrint part[4], int *print_prefix, int type[2]) { AVClass* avc = avcl ? *(AVClass **) avcl : NULL; av_bprint_init(part+0, 0, 1); av_bprint_init(part+1, 0, 1); - av_bprint_init(part+2, 0, 65536); + av_bprint_init(part+2, 0, 1); + av_bprint_init(part+3, 0, 65536); if(type) type[0] = type[1] = AV_CLASS_CATEGORY_NA + 16; if (*print_prefix && avc) { @@ -207,12 +259,15 @@ static void format_line(void *avcl, int level, const char *fmt, va_list vl, av_bprintf(part+1, "[%s @ %p] ", avc->item_name(avcl), avcl); if(type) type[1] = get_category(avcl); + + if (flags & AV_LOG_PRINT_LEVEL) + av_bprintf(part+2, "[%s] ", get_level_str(level)); } - av_vbprintf(part+2, fmt, vl); + av_vbprintf(part+3, fmt, vl); - if(*part[0].str || *part[1].str || *part[2].str) { - char lastc = part[2].len && part[2].len <= part[2].size ? part[2].str[part[2].len - 1] : 0; + if(*part[0].str || *part[1].str || *part[2].str || *part[3].str) { + char lastc = part[3].len && part[3].len <= part[3].size ? part[3].str[part[3].len - 1] : 0; *print_prefix = lastc == '\n' || lastc == '\r'; } } @@ -220,10 +275,10 @@ static void format_line(void *avcl, int level, const char *fmt, va_list vl, void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, char *line, int line_size, int *print_prefix) { - AVBPrint part[3]; + AVBPrint part[4]; format_line(ptr, level, fmt, vl, part, print_prefix, NULL); - snprintf(line, line_size, "%s%s%s", part[0].str, part[1].str, part[2].str); - av_bprint_finalize(part+2, NULL); + snprintf(line, line_size, "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str); + av_bprint_finalize(part+3, NULL); } void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl) @@ -231,10 +286,16 @@ void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl) static int print_prefix = 1; static int count; static char prev[LINE_SZ]; - AVBPrint part[3]; + AVBPrint part[4]; char line[LINE_SZ]; static int is_atty; int type[2]; + unsigned tint = 0; + + if (level >= 0) { + tint = level & 0xff00; + level &= 0xff; + } if (level > av_log_level) return; @@ -243,7 +304,7 @@ void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl) #endif format_line(ptr, level, fmt, vl, part, &print_prefix, type); - snprintf(line, sizeof(line), "%s%s%s", part[0].str, part[1].str, part[2].str); + snprintf(line, sizeof(line), "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str); #if HAVE_ISATTY if (!is_atty) @@ -263,13 +324,15 @@ void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl) } strcpy(prev, line); sanitize(part[0].str); - colored_fputs(type[0], part[0].str); + colored_fputs(type[0], 0, part[0].str); sanitize(part[1].str); - colored_fputs(type[1], part[1].str); + colored_fputs(type[1], 0, part[1].str); sanitize(part[2].str); - colored_fputs(av_clip(level >> 3, 0, 6), part[2].str); + colored_fputs(av_clip(level >> 3, 0, 6), tint >> 8, part[2].str); + sanitize(part[3].str); + colored_fputs(av_clip(level >> 3, 0, 6), tint >> 8, part[3].str); end: - av_bprint_finalize(part+2, NULL); + av_bprint_finalize(part+3, NULL); #if HAVE_PTHREADS pthread_mutex_unlock(&mutex); #endif @@ -312,6 +375,11 @@ void av_log_set_flags(int arg) flags = arg; } +int av_log_get_flags(void) +{ + return flags; +} + void av_log_set_callback(void (*callback)(void*, int, const char*, va_list)) { av_log_callback = callback; @@ -327,8 +395,8 @@ static void missing_feature_sample(int sample, void *avc, const char *msg, "been implemented.\n"); if (sample) av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample " - "of this file to ftp://upload.ffmpeg.org/MPlayer/incoming/ " - "and contact the ffmpeg-devel mailing list.\n"); + "of this file to ftp://upload.ffmpeg.org/incoming/ " + "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)\n"); } void avpriv_request_sample(void *avc, const char *msg, ...) @@ -348,3 +416,26 @@ void avpriv_report_missing_feature(void *avc, const char *msg, ...) missing_feature_sample(0, avc, msg, argument_list); va_end(argument_list); } + +#ifdef TEST +// LCOV_EXCL_START +#include + +int main(int argc, char **argv) +{ + int i; + av_log_set_level(AV_LOG_DEBUG); + for (use_color=0; use_color<=256; use_color = 255*use_color+1) { + av_log(NULL, AV_LOG_FATAL, "use_color: %d\n", use_color); + for (i = AV_LOG_DEBUG; i>=AV_LOG_QUIET; i-=8) { + av_log(NULL, i, " %d", i); + av_log(NULL, AV_LOG_INFO, "e "); + av_log(NULL, i + 256*123, "C%d", i); + av_log(NULL, AV_LOG_INFO, "e"); + } + av_log(NULL, AV_LOG_PANIC, "\n"); + } + return 0; +} +// LCOV_EXCL_STOP +#endif diff --git a/libavutil/log.h b/libavutil/log.h index 5fb476f94..a6a07e065 100644 --- a/libavutil/log.h +++ b/libavutil/log.h @@ -37,6 +37,12 @@ typedef enum { AV_CLASS_CATEGORY_BITSTREAM_FILTER, AV_CLASS_CATEGORY_SWSCALER, AV_CLASS_CATEGORY_SWRESAMPLER, + AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT = 40, + AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT, AV_CLASS_CATEGORY_NB, ///< not part of ABI/API }AVClassCategory; @@ -185,6 +191,16 @@ typedef struct AVClass { * @} */ +/** + * Sets additional colors for extended debugging sessions. + * @code + av_log(ctx, AV_LOG_DEBUG|AV_LOG_C(134), "Message in purple\n"); + @endcode + * Requires 256color terminal support. Uses outside debugging is not + * recommended. + */ +#define AV_LOG_C(x) (x << 8) + /** * Send the specified message to the log if the level is less than or equal * to the current av_log_level. By default, all logging messages are sent to @@ -305,7 +321,17 @@ void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, * call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end */ #define AV_LOG_SKIP_REPEATED 1 + +/** + * Include the log severity in messages originating from codecs. + * + * Results in messages such as: + * [rawvideo @ 0xDEADBEEF] [error] encode did not produce valid pts + */ +#define AV_LOG_PRINT_LEVEL 2 + void av_log_set_flags(int arg); +int av_log_get_flags(void); /** * @} diff --git a/libavutil/lzo.c b/libavutil/lzo.c index 6a24a1dfc..7b027eeb3 100644 --- a/libavutil/lzo.c +++ b/libavutil/lzo.c @@ -217,6 +217,7 @@ int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen) int main(int argc, char *argv[]) { FILE *in = fopen(argv[1], "rb"); + int comp_level = argc > 2 ? atoi(argv[2]) : 0; uint8_t *orig = av_malloc(MAXSZ + 16); uint8_t *comp = av_malloc(2*MAXSZ + 16); uint8_t *decomp = av_malloc(MAXSZ + 16); @@ -226,7 +227,16 @@ int main(int argc, char *argv[]) { int inlen, outlen; int i; av_log_set_level(AV_LOG_DEBUG); - lzo1x_999_compress(orig, s, comp, &clen, tmp); + if (comp_level == 0) { + lzo1x_1_compress(orig, s, comp, &clen, tmp); + } else if (comp_level == 11) { + lzo1x_1_11_compress(orig, s, comp, &clen, tmp); + } else if (comp_level == 12) { + lzo1x_1_12_compress(orig, s, comp, &clen, tmp); + } else if (comp_level == 15) { + lzo1x_1_15_compress(orig, s, comp, &clen, tmp); + } else + lzo1x_999_compress(orig, s, comp, &clen, tmp); for (i = 0; i < 300; i++) { START_TIMER inlen = clen; outlen = MAXSZ; diff --git a/libavutil/mathematics.c b/libavutil/mathematics.c index 30963aa07..126cffc3f 100644 --- a/libavutil/mathematics.c +++ b/libavutil/mathematics.c @@ -32,7 +32,7 @@ #include "version.h" #if FF_API_AV_REVERSE -const uint8_t av_reverse[256]={ +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, @@ -52,13 +52,17 @@ const uint8_t av_reverse[256]={ }; #endif -int64_t av_gcd(int64_t a, int64_t b){ - if(b) return av_gcd(b, a%b); - else return a; +int64_t av_gcd(int64_t a, int64_t b) +{ + if (b) + return av_gcd(b, a % b); + else + return a; } -int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd){ - int64_t r=0; +int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) +{ + int64_t r = 0; av_assert2(c > 0); av_assert2(b >=0); av_assert2((unsigned)(rnd&~AV_ROUND_PASS_MINMAX)<=5 && (rnd&~AV_ROUND_PASS_MINMAX)!=4); @@ -72,36 +76,38 @@ int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd){ rnd -= AV_ROUND_PASS_MINMAX; } - if(a<0 && a != INT64_MIN) return -av_rescale_rnd(-a, b, c, rnd ^ ((rnd>>1)&1)); + if (a < 0 && a != INT64_MIN) + return -av_rescale_rnd(-a, b, c, rnd ^ ((rnd >> 1) & 1)); - if(rnd==AV_ROUND_NEAR_INF) r= c/2; - else if(rnd&1) r= c-1; + if (rnd == AV_ROUND_NEAR_INF) + r = c / 2; + else if (rnd & 1) + r = c - 1; - if(b<=INT_MAX && c<=INT_MAX){ - if(a<=INT_MAX) - return (a * b + r)/c; + if (b <= INT_MAX && c <= INT_MAX) { + if (a <= INT_MAX) + return (a * b + r) / c; else - return a/c*b + (a%c*b + r)/c; - }else{ + return a / c * b + (a % c * b + r) / c; + } else { #if 1 - uint64_t a0= a&0xFFFFFFFF; - uint64_t a1= a>>32; - uint64_t b0= b&0xFFFFFFFF; - uint64_t b1= b>>32; - uint64_t t1= a0*b1 + a1*b0; - uint64_t t1a= t1<<32; + uint64_t a0 = a & 0xFFFFFFFF; + uint64_t a1 = a >> 32; + uint64_t b0 = b & 0xFFFFFFFF; + uint64_t b1 = b >> 32; + uint64_t t1 = a0 * b1 + a1 * b0; + uint64_t t1a = t1 << 32; int i; - a0 = a0*b0 + t1a; - a1 = a1*b1 + (t1>>32) + (a0> 32) + (a0 < t1a); a0 += r; - a1 += a0=0; i--){ -// int o= a1 & 0x8000000000000000ULL; - a1+= a1 + ((a0>>i)&1); - t1+=t1; - if(/*o || */c <= a1){ + for (i = 63; i >= 0; i--) { + a1 += a1 + ((a0 >> i) & 1); + t1 += t1; + if (c <= a1) { a1 -= c; t1++; } @@ -110,23 +116,24 @@ int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd){ } #else AVInteger ai; - ai= av_mul_i(av_int2i(a), av_int2i(b)); - ai= av_add_i(ai, av_int2i(r)); + 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){ +int64_t av_rescale(int64_t a, int64_t b, int64_t c) +{ return av_rescale_rnd(a, b, c, AV_ROUND_NEAR_INF); } int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, enum AVRounding rnd) { - int64_t b= bq.num * (int64_t)cq.den; - int64_t c= cq.num * (int64_t)bq.den; + int64_t b = bq.num * (int64_t)cq.den; + int64_t c = cq.num * (int64_t)bq.den; return av_rescale_rnd(a, b, c, rnd); } @@ -135,20 +142,24 @@ int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) return av_rescale_q_rnd(a, bq, cq, AV_ROUND_NEAR_INF); } -int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b){ - int64_t a= tb_a.num * (int64_t)tb_b.den; - int64_t b= tb_b.num * (int64_t)tb_a.den; - if((FFABS(ts_a)|a|FFABS(ts_b)|b)<=INT_MAX) +int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b) +{ + int64_t a = tb_a.num * (int64_t)tb_b.den; + int64_t b = tb_b.num * (int64_t)tb_a.den; + if ((FFABS(ts_a)|a|FFABS(ts_b)|b) <= INT_MAX) return (ts_a*a > ts_b*b) - (ts_a*a < ts_b*b); - if (av_rescale_rnd(ts_a, a, b, AV_ROUND_DOWN) < ts_b) return -1; - if (av_rescale_rnd(ts_b, b, a, AV_ROUND_DOWN) < ts_a) return 1; + if (av_rescale_rnd(ts_a, a, b, AV_ROUND_DOWN) < ts_b) + return -1; + if (av_rescale_rnd(ts_b, b, a, AV_ROUND_DOWN) < ts_a) + return 1; return 0; } -int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod){ - int64_t c= (a-b) & (mod-1); - if(c > (mod>>1)) - c-= mod; +int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod) +{ + int64_t c = (a - b) & (mod - 1); + if (c > (mod >> 1)) + c -= mod; return c; } @@ -177,14 +188,22 @@ simple_round: int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc) { - AVRational step = av_mul_q(inc_tb, (AVRational) {inc, 1}); + int64_t m, d; - if (av_cmp_q(step, ts_tb) < 0) { - //increase step is too small for even 1 step to be representable + if (inc != 1) + inc_tb = av_mul_q(inc_tb, (AVRational) {inc, 1}); + + m = inc_tb.num * (int64_t)ts_tb.den; + d = inc_tb.den * (int64_t)ts_tb.num; + + if (m % d == 0) + return ts + m / d; + if (m < d) return ts; - } else { - int64_t old = av_rescale_q(ts, ts_tb, step); - int64_t old_ts = av_rescale_q(old, step, ts_tb); - return av_rescale_q(old + 1, step, ts_tb) + (ts - old_ts); + + { + int64_t old = av_rescale_q(ts, ts_tb, inc_tb); + int64_t old_ts = av_rescale_q(old, inc_tb, ts_tb); + return av_rescale_q(old + 1, inc_tb, ts_tb) + (ts - old_ts); } } diff --git a/libavutil/mathematics.h b/libavutil/mathematics.h index 88739e80b..ac9448872 100644 --- a/libavutil/mathematics.h +++ b/libavutil/mathematics.h @@ -146,7 +146,7 @@ int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int /** * Add a value to a timestamp. * - * This function gurantees that when the same value is repeatly added that + * This function guarantees that when the same value is repeatly added that * no accumulation of rounding errors occurs. * * @param ts Input timestamp diff --git a/libavutil/mem.c b/libavutil/mem.c index 10b0137a7..8226168ee 100644 --- a/libavutil/mem.c +++ b/libavutil/mem.c @@ -39,6 +39,7 @@ #include "avassert.h" #include "avutil.h" #include "common.h" +#include "dynarray.h" #include "intreadwrite.h" #include "mem.h" @@ -277,67 +278,48 @@ void *av_memdup(const void *p, size_t size) return ptr; } +int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem) +{ + void **tab = *(void ***)tab_ptr; + + AV_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, { + tab[*nb_ptr] = elem; + *(void ***)tab_ptr = tab; + }, { + return AVERROR(ENOMEM); + }); + return 0; +} + void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem) { - /* see similar ffmpeg.c:grow_array() */ - int nb, nb_alloc; - intptr_t *tab; + void **tab = *(void ***)tab_ptr; - nb = *nb_ptr; - tab = *(intptr_t**)tab_ptr; - if ((nb & (nb - 1)) == 0) { - if (nb == 0) { - nb_alloc = 1; - } else { - if (nb > INT_MAX / (2 * sizeof(intptr_t))) - goto fail; - nb_alloc = nb * 2; - } - tab = av_realloc(tab, nb_alloc * sizeof(intptr_t)); - if (!tab) - goto fail; - *(intptr_t**)tab_ptr = tab; - } - tab[nb++] = (intptr_t)elem; - *nb_ptr = nb; - return; - -fail: - av_freep(tab_ptr); - *nb_ptr = 0; + AV_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, { + tab[*nb_ptr] = elem; + *(void ***)tab_ptr = tab; + }, { + *nb_ptr = 0; + av_freep(tab_ptr); + }); } void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, const uint8_t *elem_data) { - int nb = *nb_ptr, nb_alloc; - uint8_t *tab = *tab_ptr, *tab_elem_data; + uint8_t *tab_elem_data = NULL; - if ((nb & (nb - 1)) == 0) { - if (nb == 0) { - nb_alloc = 1; - } else { - if (nb > INT_MAX / (2 * elem_size)) - goto fail; - nb_alloc = nb * 2; - } - tab = av_realloc(tab, nb_alloc * elem_size); - if (!tab) - goto fail; - *tab_ptr = tab; - } - *nb_ptr = nb + 1; - tab_elem_data = tab + nb*elem_size; - if (elem_data) - memcpy(tab_elem_data, elem_data, elem_size); - else if (CONFIG_MEMORY_POISONING) - memset(tab_elem_data, FF_MEMORY_POISON, elem_size); + AV_DYNARRAY_ADD(INT_MAX, elem_size, *tab_ptr, *nb_ptr, { + tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size; + if (elem_data) + memcpy(tab_elem_data, elem_data, elem_size); + else if (CONFIG_MEMORY_POISONING) + memset(tab_elem_data, FF_MEMORY_POISON, elem_size); + }, { + av_freep(tab_ptr); + *nb_ptr = 0; + }); return tab_elem_data; - -fail: - av_freep(tab_ptr); - *nb_ptr = 0; - return NULL; } static void fill16(uint8_t *dst, int len) diff --git a/libavutil/mem.h b/libavutil/mem.h index 703ce8193..801c53ff5 100644 --- a/libavutil/mem.h +++ b/libavutil/mem.h @@ -276,10 +276,25 @@ void av_freep(void *ptr); * @param tab_ptr pointer to the array to grow * @param nb_ptr pointer to the number of elements in the array * @param elem element to add - * @see av_dynarray2_add() + * @see av_dynarray_add_nofree(), av_dynarray2_add() */ void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem); +/** + * Add an element to a dynamic array. + * + * Function has the same functionality as av_dynarray_add(), + * but it doesn't free memory on fails. It returns error code + * instead and leave current buffer untouched. + * + * @param tab_ptr pointer to the array to grow + * @param nb_ptr pointer to the number of elements in the array + * @param elem element to add + * @return >=0 on success, negative otherwise. + * @see av_dynarray_add(), av_dynarray2_add() + */ +int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem); + /** * Add an element of size elem_size to a dynamic array. * @@ -299,7 +314,7 @@ void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem); * the new added element is not filled. * @return pointer to the data of the element to copy in the new allocated space. * If NULL, the new allocated space is left uninitialized." - * @see av_dynarray_add() + * @see av_dynarray_add(), av_dynarray_add_nofree() */ void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, const uint8_t *elem_data); diff --git a/libavutil/opencl.c b/libavutil/opencl.c index 142c6b0bf..a92bce76b 100644 --- a/libavutil/opencl.c +++ b/libavutil/opencl.c @@ -27,15 +27,20 @@ #include "avassert.h" #include "opt.h" +#if HAVE_THREADS #if HAVE_PTHREADS - #include -static pthread_mutex_t atomic_opencl_lock = PTHREAD_MUTEX_INITIALIZER; +#elif HAVE_W32THREADS +#include "compat/w32pthreads.h" +#elif HAVE_OS2THREADS +#include "compat/os2threads.h" +#endif +#include "atomic.h" -#define LOCK_OPENCL pthread_mutex_lock(&atomic_opencl_lock) -#define UNLOCK_OPENCL pthread_mutex_unlock(&atomic_opencl_lock) - -#elif !HAVE_THREADS +static volatile pthread_mutex_t *atomic_opencl_lock = NULL; +#define LOCK_OPENCL pthread_mutex_lock(atomic_opencl_lock) +#define UNLOCK_OPENCL pthread_mutex_unlock(atomic_opencl_lock) +#else #define LOCK_OPENCL #define UNLOCK_OPENCL #endif @@ -169,7 +174,7 @@ static const OpenclErrorMsg opencl_err_msg[] = { const char *av_opencl_errstr(cl_int status) { int i; - for (i = 0; i < sizeof(opencl_err_msg); i++) { + for (i = 0; i < FF_ARRAY_ELEMS(opencl_err_msg); i++) { if (opencl_err_msg[i].err_code == status) return opencl_err_msg[i].err_str; } @@ -321,9 +326,32 @@ void av_opencl_free_device_list(AVOpenCLDeviceList **device_list) av_freep(device_list); } +static inline int init_opencl_mtx(void) +{ +#if HAVE_THREADS + if (!atomic_opencl_lock) { + int err; + pthread_mutex_t *tmp = av_malloc(sizeof(pthread_mutex_t)); + if (!tmp) + return AVERROR(ENOMEM); + if ((err = pthread_mutex_init(tmp, NULL))) { + av_free(tmp); + return AVERROR(err); + } + if (avpriv_atomic_ptr_cas(&atomic_opencl_lock, NULL, tmp)) { + pthread_mutex_destroy(tmp); + av_free(tmp); + } + } +#endif + return 0; +} + int av_opencl_set_option(const char *key, const char *val) { - int ret = 0; + int ret = init_opencl_mtx( ); + if (ret < 0) + return ret; LOCK_OPENCL; if (!opencl_ctx.opt_init_flag) { av_opt_set_defaults(&opencl_ctx); @@ -368,7 +396,9 @@ void av_opencl_free_external_env(AVOpenCLExternalEnv **ext_opencl_env) int av_opencl_register_kernel_code(const char *kernel_code) { - int i, ret = 0; + int i, ret = init_opencl_mtx( ); + if (ret < 0) + return ret; LOCK_OPENCL; if (opencl_ctx.kernel_code_count >= MAX_KERNEL_CODE_NUM) { av_log(&opencl_ctx, AV_LOG_ERROR, @@ -553,7 +583,9 @@ static int init_opencl_env(OpenclContext *opencl_ctx, AVOpenCLExternalEnv *ext_o int av_opencl_init(AVOpenCLExternalEnv *ext_opencl_env) { - int ret = 0; + int ret = init_opencl_mtx( ); + if (ret < 0) + return ret; LOCK_OPENCL; if (!opencl_ctx.init_count) { if (!opencl_ctx.opt_init_flag) { diff --git a/libavutil/opencl.h b/libavutil/opencl.h index cf0abd797..9e6dc55ee 100644 --- a/libavutil/opencl.h +++ b/libavutil/opencl.h @@ -38,6 +38,7 @@ #else #include #endif +#include #include "dict.h" #include "libavutil/version.h" diff --git a/libavutil/opt.c b/libavutil/opt.c index 64901f273..694295dc3 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -1415,14 +1415,17 @@ void av_opt_free(void *obj) av_freep((uint8_t *)obj + o->offset); } -int av_opt_set_dict(void *obj, AVDictionary **options) +int av_opt_set_dict2(void *obj, AVDictionary **options, int search_flags) { AVDictionaryEntry *t = NULL; AVDictionary *tmp = NULL; int ret = 0; + if (!options) + return 0; + while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) { - ret = av_opt_set(obj, t->key, t->value, 0); + ret = av_opt_set(obj, t->key, t->value, search_flags); if (ret == AVERROR_OPTION_NOT_FOUND) av_dict_set(&tmp, t->key, t->value, 0); else if (ret < 0) { @@ -1436,6 +1439,11 @@ int av_opt_set_dict(void *obj, AVDictionary **options) return ret; } +int av_opt_set_dict(void *obj, AVDictionary **options) +{ + return av_opt_set_dict2(obj, options, 0); +} + const AVOption *av_opt_find(void *obj, const char *name, const char *unit, int opt_flags, int search_flags) { @@ -1509,8 +1517,73 @@ void *av_opt_ptr(const AVClass *class, void *obj, const char *name) return (uint8_t*)obj + opt->offset; } +static int opt_size(enum AVOptionType type) +{ + switch(type) { + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_FLAGS: return sizeof(int); + case AV_OPT_TYPE_DURATION: + case AV_OPT_TYPE_CHANNEL_LAYOUT: + 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_VIDEO_RATE: + case AV_OPT_TYPE_RATIONAL: return sizeof(AVRational); + case AV_OPT_TYPE_BINARY: return sizeof(uint8_t*) + sizeof(int); + case AV_OPT_TYPE_IMAGE_SIZE:return sizeof(int[2]); + case AV_OPT_TYPE_PIXEL_FMT: return sizeof(enum AVPixelFormat); + case AV_OPT_TYPE_SAMPLE_FMT:return sizeof(enum AVSampleFormat); + case AV_OPT_TYPE_COLOR: return 4; + } + return 0; +} + +int av_opt_copy(void *dst, void *src) +{ + const AVOption *o = NULL; + const AVClass *c; + int ret = 0; + + if (!src) + return 0; + + c = *(AVClass**)src; + if (*(AVClass**)dst && 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); + *field_dst8 = av_memdup(*field_src8, len); + if (len && !*field_dst8) { + ret = AVERROR(ENOMEM); + len = 0; + } + *(int*)(field_dst8 + 1) = len; + } else if (o->type == AV_OPT_TYPE_CONST) { + // do nothing + } else { + memcpy(field_dst, field_src, opt_size(o->type)); + } + } + return ret; +} + int av_opt_query_ranges(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags) { + int ret; const AVClass *c = *(AVClass**)obj; int (*callback)(AVOptionRanges **, void *obj, const char *key, int flags) = NULL; @@ -1520,7 +1593,13 @@ int av_opt_query_ranges(AVOptionRanges **ranges_arg, void *obj, const char *key, if (!callback) callback = av_opt_query_ranges_default; - return callback(ranges_arg, obj, key, flags); + ret = callback(ranges_arg, obj, key, flags); + if (ret >= 0) { + if (!(flags & AV_OPT_MULTI_COMPONENT_RANGE)) + ret = 1; + (*ranges_arg)->nb_components = ret; + } + return ret; } int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags) @@ -1541,6 +1620,7 @@ int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const ch ranges->range = range_array; ranges->range[0] = range; ranges->nb_ranges = 1; + ranges->nb_components = 1; range->is_range = 1; range->value_min = field->min; range->value_max = field->max; @@ -1584,7 +1664,7 @@ int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const ch } *ranges_arg = ranges; - return 0; + return 1; fail: av_free(ranges); av_free(range); @@ -1597,7 +1677,10 @@ void av_opt_freep_ranges(AVOptionRanges **rangesp) int i; AVOptionRanges *ranges = *rangesp; - for (i = 0; i < ranges->nb_ranges; i++) { + if (!ranges) + return; + + for (i = 0; i < ranges->nb_ranges * ranges->nb_components; i++) { AVOptionRange *range = ranges->range[i]; if (range) { av_freep(&range->str); diff --git a/libavutil/opt.h b/libavutil/opt.h index cd1b18e4c..770599021 100644 --- a/libavutil/opt.h +++ b/libavutil/opt.h @@ -313,17 +313,67 @@ typedef struct AVOption { */ typedef struct AVOptionRange { const char *str; - double value_min, value_max; ///< For string ranges this represents the min/max length, for dimensions this represents the min/max pixel count - double component_min, component_max; ///< For string this represents the unicode range for chars, 0-127 limits to ASCII - int is_range; ///< if set to 1 the struct encodes a range, if set to 0 a single value + /** + * Value range. + * For string ranges this represents the min/max length. + * For dimensions this represents the min/max pixel count or width/height in multi-component case. + */ + double value_min, value_max; + /** + * Value's component range. + * For string this represents the unicode range for chars, 0-127 limits to ASCII. + */ + double component_min, component_max; + /** + * Range flag. + * If set to 1 the struct encodes a range, if set to 0 a single value. + */ + int is_range; } AVOptionRange; /** - * List of AVOptionRange structs + * List of AVOptionRange structs. */ typedef struct AVOptionRanges { + /** + * Array of option ranges. + * + * Most of option types use just one component. + * Following describes multi-component option types: + * + * AV_OPT_TYPE_IMAGE_SIZE: + * component index 0: range of pixel count (width * height). + * component index 1: range of width. + * component index 2: range of height. + * + * @note To obtain multi-component version of this structure, user must + * provide AV_OPT_MULTI_COMPONENT_RANGE to av_opt_query_ranges or + * av_opt_query_ranges_default function. + * + * Multi-component range can be read as in following example: + * + * @code + * int range_index, component_index; + * AVOptionRanges *ranges; + * AVOptionRange *range[3]; //may require more than 3 in the future. + * av_opt_query_ranges(&ranges, obj, key, AV_OPT_MULTI_COMPONENT_RANGE); + * for (range_index = 0; range_index < ranges->nb_ranges; range_index++) { + * for (component_index = 0; component_index < ranges->nb_components; component_index++) + * range[component_index] = ranges->range[ranges->nb_ranges * component_index + range_index]; + * //do something with range here. + * } + * av_opt_freep_ranges(&ranges); + * @endcode + */ AVOptionRange **range; + /** + * Number of ranges per component. + */ int nb_ranges; + /** + * Number of componentes. + */ + int nb_components; } AVOptionRanges; @@ -491,6 +541,24 @@ int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name) */ int av_opt_set_dict(void *obj, struct AVDictionary **options); + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags); + /** * Extract a key-value pair from the beginning of a string. * @@ -558,6 +626,13 @@ int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational */ #define AV_OPT_SEARCH_FAKE_OBJ 0x0002 +/** + * Allows av_opt_query_ranges and av_opt_query_ranges_default to return more than + * one component for certain option types. + * @see AVOptionRanges for details. + */ +#define AV_OPT_MULTI_COMPONENT_RANGE 0x1000 + /** * Look for an option in an object. Consider only options which * have all the specified flags set. @@ -739,13 +814,16 @@ void av_opt_freep_ranges(AVOptionRanges **ranges); * * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges * * The result must be freed with av_opt_freep_ranges. * - * @return >= 0 on success, a negative errro code otherwise + * @return number of compontents returned on success, a negative errro code otherwise */ int av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags); +int av_opt_copy(void *dest, void *src); + /** * Get a default list of allowed ranges for the given option. * @@ -754,10 +832,11 @@ int av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags * * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges * * The result must be freed with av_opt_free_ranges. * - * @return >= 0 on success, a negative errro code otherwise + * @return number of compontents returned on success, a negative errro code otherwise */ int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags); diff --git a/libavutil/pca.c b/libavutil/pca.c index 311b6bc9c..26d5bbb15 100644 --- a/libavutil/pca.c +++ b/libavutil/pca.c @@ -42,7 +42,7 @@ PCA *ff_pca_init(int n){ pca= av_mallocz(sizeof(*pca)); pca->n= n; - pca->z = av_malloc(sizeof(*pca->z) * n); + pca->z = av_malloc_array(n, sizeof(*pca->z)); pca->count=0; pca->covariance= av_calloc(n*n, sizeof(double)); pca->mean= av_calloc(n, sizeof(double)); diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 7d41b2220..f00907dc2 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -154,6 +154,17 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { { 0, 3, 4, 0, 7 }, /* V */ }, }, + [AV_PIX_FMT_YVYU422] = { + .name = "yvyu422", + .nb_components = 3, + .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 */ + }, + }, [AV_PIX_FMT_RGB24] = { .name = "rgb24", .nb_components = 3, @@ -928,22 +939,22 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, [AV_PIX_FMT_RGBA64BE] = { .name = "rgba64be", - .nb_components= 4, - .log2_chroma_w= 0, - .log2_chroma_h= 0, + .nb_components = 4, + .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 */ }, - .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_ALPHA, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, [AV_PIX_FMT_RGBA64LE] = { .name = "rgba64le", - .nb_components= 4, - .log2_chroma_w= 0, - .log2_chroma_h= 0, + .nb_components = 4, + .log2_chroma_w = 0, + .log2_chroma_h = 0, .comp = { { 0, 7, 1, 0, 15 }, /* R */ { 0, 7, 3, 0, 15 }, /* G */ @@ -1050,9 +1061,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, [AV_PIX_FMT_BGRA64BE] = { .name = "bgra64be", - .nb_components= 4, - .log2_chroma_w= 0, - .log2_chroma_h= 0, + .nb_components = 4, + .log2_chroma_w = 0, + .log2_chroma_h = 0, .comp = { { 0, 7, 5, 0, 15 }, /* R */ { 0, 7, 3, 0, 15 }, /* G */ @@ -1063,9 +1074,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, [AV_PIX_FMT_BGRA64LE] = { .name = "bgra64le", - .nb_components= 4, - .log2_chroma_w= 0, - .log2_chroma_h= 0, + .nb_components = 4, + .log2_chroma_w = 0, + .log2_chroma_h = 0, .comp = { { 0, 7, 5, 0, 15 }, /* R */ { 0, 7, 3, 0, 15 }, /* G */ @@ -1863,6 +1874,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, }, + [AV_PIX_FMT_VDA] = { + .name = "vda", + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, }; FF_DISABLE_DEPRECATION_WARNINGS @@ -2071,3 +2086,226 @@ enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt) return get_pix_fmt_internal(name); } + +#define FF_COLOR_NA -1 +#define FF_COLOR_RGB 0 /**< RGB color space */ +#define FF_COLOR_GRAY 1 /**< gray color space */ +#define FF_COLOR_YUV 2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */ +#define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */ + +#define pixdesc_has_alpha(pixdesc) \ + ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & AV_PIX_FMT_FLAG_PAL) + + +static int get_color_type(const AVPixFmtDescriptor *desc) { + if (desc->flags & AV_PIX_FMT_FLAG_PAL) + return FF_COLOR_RGB; + + if(desc->nb_components == 1 || desc->nb_components == 2) + return FF_COLOR_GRAY; + + if(desc->name && !strncmp(desc->name, "yuvj", 4)) + return FF_COLOR_YUV_JPEG; + + if(desc->flags & AV_PIX_FMT_FLAG_RGB) + return FF_COLOR_RGB; + + if(desc->nb_components == 0) + return FF_COLOR_NA; + + return FF_COLOR_YUV; +} + +static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + int i; + + if (!desc || !desc->nb_components) { + *min = *max = 0; + return AVERROR(EINVAL); + } + + *min = INT_MAX, *max = -INT_MAX; + for (i = 0; i < desc->nb_components; i++) { + *min = FFMIN(desc->comp[i].depth_minus1+1, *min); + *max = FFMAX(desc->comp[i].depth_minus1+1, *max); + } + return 0; +} + +static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + unsigned *lossp, unsigned consider) +{ + const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt); + const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt); + int src_color, dst_color; + int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth; + int ret, loss, i, nb_components; + int score = INT_MAX - 1; + + if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE) + return ~0; + + /* compute loss */ + *lossp = loss = 0; + + if (dst_pix_fmt == src_pix_fmt) + return INT_MAX; + + if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0) + return ret; + if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0) + return ret; + + src_color = get_color_type(src_desc); + dst_color = get_color_type(dst_desc); + if (dst_pix_fmt == AV_PIX_FMT_PAL8) + nb_components = FFMIN(src_desc->nb_components, 4); + else + nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components); + + for (i = 0; i < nb_components; i++) { + int depth_minus1 = (dst_pix_fmt == AV_PIX_FMT_PAL8) ? 7/nb_components : dst_desc->comp[i].depth_minus1; + if (src_desc->comp[i].depth_minus1 > depth_minus1 && (consider & FF_LOSS_DEPTH)) { + loss |= FF_LOSS_DEPTH; + score -= 65536 >> depth_minus1; + } + } + + if (consider & FF_LOSS_RESOLUTION) { + if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w) { + loss |= FF_LOSS_RESOLUTION; + score -= 256 << dst_desc->log2_chroma_w; + } + if (dst_desc->log2_chroma_h > src_desc->log2_chroma_h) { + loss |= FF_LOSS_RESOLUTION; + score -= 256 << dst_desc->log2_chroma_h; + } + // don't favor 422 over 420 if downsampling is needed, because 420 has much better support on the decoder side + if (dst_desc->log2_chroma_w == 1 && src_desc->log2_chroma_w == 0 && + dst_desc->log2_chroma_h == 1 && src_desc->log2_chroma_h == 0 ) { + score += 512; + } + } + + if(consider & FF_LOSS_COLORSPACE) + switch(dst_color) { + case FF_COLOR_RGB: + if (src_color != FF_COLOR_RGB && + src_color != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_GRAY: + if (src_color != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_YUV: + if (src_color != FF_COLOR_YUV) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_YUV_JPEG: + if (src_color != FF_COLOR_YUV_JPEG && + src_color != FF_COLOR_YUV && + src_color != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + default: + /* fail safe test */ + if (src_color != dst_color) + loss |= FF_LOSS_COLORSPACE; + break; + } + if(loss & FF_LOSS_COLORSPACE) + score -= (nb_components * 65536) >> FFMIN(dst_desc->comp[0].depth_minus1, src_desc->comp[0].depth_minus1); + + if (dst_color == FF_COLOR_GRAY && + src_color != FF_COLOR_GRAY && (consider & FF_LOSS_CHROMA)) { + loss |= FF_LOSS_CHROMA; + score -= 2 * 65536; + } + if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))) { + loss |= FF_LOSS_ALPHA; + score -= 65536; + } + if (dst_pix_fmt == AV_PIX_FMT_PAL8 && (consider & FF_LOSS_COLORQUANT) && + (src_pix_fmt != AV_PIX_FMT_PAL8 && (src_color != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))))) { + loss |= FF_LOSS_COLORQUANT; + score -= 65536; + } + + *lossp = loss; + return score; +} + +int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + int has_alpha) +{ + int loss; + int ret = get_pix_fmt_score(dst_pix_fmt, src_pix_fmt, &loss, has_alpha ? ~0 : ~FF_LOSS_ALPHA); + if (ret < 0) + return ret; + return loss; +} + +enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr) +{ + enum AVPixelFormat dst_pix_fmt; + int loss1, loss2, loss_mask; + const AVPixFmtDescriptor *desc1 = av_pix_fmt_desc_get(dst_pix_fmt1); + const AVPixFmtDescriptor *desc2 = av_pix_fmt_desc_get(dst_pix_fmt2); + int score1, score2; + + loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */ + if(!has_alpha) + loss_mask &= ~FF_LOSS_ALPHA; + + dst_pix_fmt = AV_PIX_FMT_NONE; + score1 = get_pix_fmt_score(dst_pix_fmt1, src_pix_fmt, &loss1, loss_mask); + score2 = get_pix_fmt_score(dst_pix_fmt2, src_pix_fmt, &loss2, loss_mask); + + if (score1 == score2) { + if(av_get_padded_bits_per_pixel(desc2) != av_get_padded_bits_per_pixel(desc1)) { + dst_pix_fmt = av_get_padded_bits_per_pixel(desc2) < av_get_padded_bits_per_pixel(desc1) ? dst_pix_fmt2 : dst_pix_fmt1; + } else { + dst_pix_fmt = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1; + } + } else { + dst_pix_fmt = score1 < score2 ? dst_pix_fmt2 : dst_pix_fmt1; + } + + if (loss_ptr) + *loss_ptr = av_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); + return dst_pix_fmt; +} + +#ifdef TEST + +int main(void){ + int i; + int err=0; + int skip = 0; + + for (i=0; iname) { + skip ++; + continue; + } + if (skip) { + av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip); + skip = 0; + } + av_log(NULL, AV_LOG_INFO, "pix fmt %s avg_bpp:%d colortype:%d\n", desc->name, av_get_padded_bits_per_pixel(desc), get_color_type(desc)); + if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) { + av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n"); + err = 1; + } + } + return err; +} + +#endif diff --git a/libavutil/pixdesc.h b/libavutil/pixdesc.h index e88bf9b92..3ddd56e3c 100644 --- a/libavutil/pixdesc.h +++ b/libavutil/pixdesc.h @@ -255,9 +255,9 @@ enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); * Utility function to access log2_chroma_w log2_chroma_h from * the pixel format AVPixFmtDescriptor. * - * See avcodec_get_chroma_sub_sample() for a function that asserts a + * See av_get_chroma_sub_sample() for a function that asserts a * valid pixel format instead of returning an error code. - * Its recommanded that you use avcodec_get_chroma_sub_sample unless + * Its recommended that you use avcodec_get_chroma_sub_sample unless * you do check the return code! * * @param[in] pix_fmt the pixel format @@ -287,5 +287,53 @@ void ff_check_pixfmt_descriptors(void); */ enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt); +#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + int has_alpha); + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); #endif /* AVUTIL_PIXDESC_H */ diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 9418c4a2b..3a6211789 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -217,6 +217,21 @@ enum AVPixelFormat { AV_PIX_FMT_NV20LE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian AV_PIX_FMT_NV20BE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + /** + * duplicated pixel formats for compatibility with libav. + * FFmpeg supports these formats since Sat Sep 24 06:01:45 2011 +0200 (commits 9569a3c9f41387a8c7d1ce97d8693520477a66c3) + * also see Fri Nov 25 01:38:21 2011 +0100 92afb431621c79155fcb7171d26f137eb1bee028 + * Libav added them Sun Mar 16 23:05:47 2014 +0100 with incompatible values (commit 1481d24c3a0abf81e1d7a514547bd5305232be30) + */ + AV_PIX_FMT_RGBA64BE_LIBAV, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE_LIBAV, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE_LIBAV, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE_LIBAV, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + + AV_PIX_FMT_YVYU422, ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb + + AV_PIX_FMT_VDA, ///< HW acceleration through VDA, data[3] contains a CVPixelBufferRef + #ifndef AV_PIX_FMT_ABI_GIT_MASTER AV_PIX_FMT_RGBA64BE=0x123, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian @@ -277,6 +292,10 @@ enum AVPixelFormat { #if AV_HAVE_INCOMPATIBLE_LIBAV_ABI #define AV_PIX_FMT_YUVA422P AV_PIX_FMT_YUVA422P_LIBAV #define AV_PIX_FMT_YUVA444P AV_PIX_FMT_YUVA444P_LIBAV +#define AV_PIX_FMT_RGBA64BE AV_PIX_FMT_RGBA64BE_LIBAV +#define AV_PIX_FMT_RGBA64LE AV_PIX_FMT_RGBA64LE_LIBAV +#define AV_PIX_FMT_BGRA64BE AV_PIX_FMT_BGRA64BE_LIBAV +#define AV_PIX_FMT_BGRA64LE AV_PIX_FMT_BGRA64LE_LIBAV #endif @@ -301,10 +320,12 @@ enum AVPixelFormat { #define AV_PIX_FMT_RGB565 AV_PIX_FMT_NE(RGB565BE, RGB565LE) #define AV_PIX_FMT_RGB555 AV_PIX_FMT_NE(RGB555BE, RGB555LE) #define AV_PIX_FMT_RGB444 AV_PIX_FMT_NE(RGB444BE, RGB444LE) +#define AV_PIX_FMT_RGBA64 AV_PIX_FMT_NE(RGBA64BE, RGBA64LE) #define AV_PIX_FMT_BGR48 AV_PIX_FMT_NE(BGR48BE, BGR48LE) #define AV_PIX_FMT_BGR565 AV_PIX_FMT_NE(BGR565BE, BGR565LE) #define AV_PIX_FMT_BGR555 AV_PIX_FMT_NE(BGR555BE, BGR555LE) #define AV_PIX_FMT_BGR444 AV_PIX_FMT_NE(BGR444BE, BGR444LE) +#define AV_PIX_FMT_BGRA64 AV_PIX_FMT_NE(BGRA64BE, BGRA64LE) #define AV_PIX_FMT_YUV420P9 AV_PIX_FMT_NE(YUV420P9BE , YUV420P9LE) #define AV_PIX_FMT_YUV422P9 AV_PIX_FMT_NE(YUV422P9BE , YUV422P9LE) @@ -322,8 +343,6 @@ enum AVPixelFormat { #define AV_PIX_FMT_YUV422P16 AV_PIX_FMT_NE(YUV422P16BE, YUV422P16LE) #define AV_PIX_FMT_YUV444P16 AV_PIX_FMT_NE(YUV444P16BE, YUV444P16LE) -#define AV_PIX_FMT_RGBA64 AV_PIX_FMT_NE(RGBA64BE, RGBA64LE) -#define AV_PIX_FMT_BGRA64 AV_PIX_FMT_NE(BGRA64BE, BGRA64LE) #define AV_PIX_FMT_GBRP9 AV_PIX_FMT_NE(GBRP9BE , GBRP9LE) #define AV_PIX_FMT_GBRP10 AV_PIX_FMT_NE(GBRP10BE, GBRP10LE) #define AV_PIX_FMT_GBRP12 AV_PIX_FMT_NE(GBRP12BE, GBRP12LE) @@ -350,6 +369,7 @@ 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 @@ -400,4 +420,90 @@ enum AVPixelFormat { #define PIX_FMT_GBRP16 AV_PIX_FMT_GBRP16 #endif +/** + * Chromaticity coordinates of the source primaries. + */ +enum AVColorPrimaries { + 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_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_BT2020 = 9, ///< ITU-R BT2020 + AVCOL_PRI_NB, ///< Not part of ABI +}; + +/** + * Color Transfer Characteristic. + */ +enum AVColorTransferCharacteristic { + AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361 + AVCOL_TRC_UNSPECIFIED = 2, + AVCOL_TRC_RESERVED = 3, + AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG + AVCOL_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC + AVCOL_TRC_SMPTE240M = 7, + AVCOL_TRC_LINEAR = 8, ///< "Linear transfer characteristics" + AVCOL_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)" + AVCOL_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" + 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_NB, ///< Not part of ABI +}; + +/** + * YUV colorspace type. + */ +enum AVColorSpace { + AVCOL_SPC_RGB = 0, + AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B + AVCOL_SPC_UNSPECIFIED = 2, + AVCOL_SPC_RESERVED = 3, + AVCOL_SPC_FCC = 4, + AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 + AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above + AVCOL_SPC_SMPTE240M = 7, + AVCOL_SPC_YCOCG = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system + AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system + AVCOL_SPC_NB, ///< Not part of ABI +}; +#define AVCOL_SPC_YCGCO AVCOL_SPC_YCOCG + + +/** + * MPEG vs JPEG YUV range. + */ +enum AVColorRange { + AVCOL_RANGE_UNSPECIFIED = 0, + AVCOL_RANGE_MPEG = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges + AVCOL_RANGE_JPEG = 2, ///< the normal 2^n-1 "JPEG" YUV ranges + AVCOL_RANGE_NB, ///< Not part of ABI +}; + +/** + * Location of chroma samples. + * + * X X 3 4 X X are luma samples, + * 1 2 1-6 are possible chroma positions + * X X 5 6 X 0 is undefined/unknown position + */ +enum AVChromaLocation { + AVCHROMA_LOC_UNSPECIFIED = 0, + AVCHROMA_LOC_LEFT = 1, ///< mpeg2/4, h264 default + AVCHROMA_LOC_CENTER = 2, ///< mpeg1, jpeg, h263 + AVCHROMA_LOC_TOPLEFT = 3, ///< DV + AVCHROMA_LOC_TOP = 4, + AVCHROMA_LOC_BOTTOMLEFT = 5, + AVCHROMA_LOC_BOTTOM = 6, + AVCHROMA_LOC_NB, ///< Not part of ABI +}; + #endif /* AVUTIL_PIXFMT_H */ diff --git a/libavutil/ppc/intreadwrite.h b/libavutil/ppc/intreadwrite.h index 3667703cf..733c01e48 100644 --- a/libavutil/ppc/intreadwrite.h +++ b/libavutil/ppc/intreadwrite.h @@ -26,46 +26,60 @@ #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_RX16 +#define AV_WL16 AV_WX16 +#define AV_RL32 AV_RX32 +#define AV_WL32 AV_WX32 +#else +#define AV_RB16 AV_RX16 +#define AV_WB16 AV_WX16 +#define AV_RB32 AV_RX32 +#define AV_WB32 AV_WX32 +#endif + +static av_always_inline uint16_t AV_RX16(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_WX16(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_RX32(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_WX32(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) +#if HAVE_BIGENDIAN +#define AV_RL64 AV_RX64 +#define AV_WL64 AV_WX64 +#else +#define AV_RB64 AV_RX64 +#define AV_WB64 AV_WX64 +#endif + +static av_always_inline uint64_t AV_RX64(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_WX64(void *p, uint64_t v) { __asm__ ("stdbrx %1, %y0" : "=Z"(*(uint64_t*)p) : "r"(v)); } @@ -102,7 +116,9 @@ static av_always_inline void AV_WL64(void *p, uint64_t v) * default, so we override it here. */ +#if HAVE_BIGENDIAN #define AV_RB64(p) (*(const uint64_t *)(p)) #define AV_WB64(p, v) (*(uint64_t *)(p) = (v)) +#endif #endif /* AVUTIL_PPC_INTREADWRITE_H */ diff --git a/libavutil/ppc/util_altivec.h b/libavutil/ppc/util_altivec.h index fbf6d85b0..2c0ad5f6c 100644 --- a/libavutil/ppc/util_altivec.h +++ b/libavutil/ppc/util_altivec.h @@ -48,17 +48,6 @@ #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 vcii(a,b,c,d) (const vector float){FLOAT_ ## a, FLOAT_ ## b, FLOAT_ ## c, FLOAT_ ## d} - -// vcprmle is used to keep the same index as in the SSE version. -// it's the same as vcprm, with the index inversed -// ('le' is Little Endian) -#define vcprmle(a,b,c,d) vcprm(d,c,b,a) - -// used to build inverse/identity vectors (vcii) -// n is _n_egative, p is _p_ositive -#define FLOAT_n -1. -#define FLOAT_p 1. // Transpose 8x8 matrix of 16-bit elements (in-place) @@ -117,6 +106,9 @@ static inline vec_u8 load_with_perm_vec(int offset, uint8_t *src, vec_u8 perm_ve return vec_perm(a, b, perm_vec); } +#define vec_unaligned_load(b) \ + vec_perm(vec_ld(0, b), vec_ld(15, b), vec_lvsl(0, b)); + #endif /* HAVE_ALTIVEC */ #endif /* AVUTIL_PPC_UTIL_ALTIVEC_H */ diff --git a/libavutil/replaygain.h b/libavutil/replaygain.h new file mode 100644 index 000000000..5c03e1993 --- /dev/null +++ b/libavutil/replaygain.h @@ -0,0 +1,51 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_REPLAYGAIN_H +#define AVUTIL_REPLAYGAIN_H + +#include + +/** + * ReplayGain information (see + * http://wiki.hydrogenaudio.org/index.php?title=ReplayGain_1.0_specification). + * The size of this struct is a part of the public ABI. + */ +typedef struct AVReplayGain { + /** + * Track replay gain in microbels (divide by 100000 to get the value in dB). + * Should be set to INT32_MIN when unknown. + */ + int32_t track_gain; + /** + * Peak track amplitude, with 100000 representing full scale (but values + * may overflow). 0 when unknown. + */ + uint32_t track_peak; + /** + * Same as track_gain, but for the whole album. + */ + int32_t album_gain; + /** + * Same as track_peak, but for the whole album, + */ + uint32_t album_peak; +} AVReplayGain; + +#endif /* AVUTIL_REPLAYGAIN_H */ diff --git a/libavutil/samplefmt.h b/libavutil/samplefmt.h index db17d43bc..2c346a3ce 100644 --- a/libavutil/samplefmt.h +++ b/libavutil/samplefmt.h @@ -25,26 +25,36 @@ #include "attributes.h" /** - * Audio Sample Formats + * @addtogroup lavu_audio + * @{ + * + * @defgroup lavu_sampfmts Audio sample formats + * + * Audio sample format enumeration and related convenience functions. + * @{ + * + */ + +/** + * Audio sample formats + * + * - The data described by the sample format is always in native-endian order. + * Sample values can be expressed by native C types, hence the lack of a signed + * 24-bit sample format even though it is a common raw audio data format. + * + * - The floating-point formats are based on full volume being in the range + * [-1.0, 1.0]. Any values outside this range are beyond full volume level. + * + * - The data layout as used in av_samples_fill_arrays() and elsewhere in FFmpeg + * (such as AVFrame in libavcodec) is as follows: * * @par - * The data described by the sample format is always in native-endian order. - * Sample values can be expressed by native C types, hence the lack of a signed - * 24-bit sample format even though it is a common raw audio data format. - * - * @par - * The floating-point formats are based on full volume being in the range - * [-1.0, 1.0]. Any values outside this range are beyond full volume level. - * - * @par - * The data layout as used in av_samples_fill_arrays() and elsewhere in FFmpeg - * (such as AVFrame in libavcodec) is as follows: - * * For planar sample formats, each audio channel is in a separate data plane, * and linesize is the buffer size, in bytes, for a single plane. All data * planes must be the same size. For packed sample formats, only the first data * plane is used, and samples for each channel are interleaved. In this case, * linesize is the buffer size, in bytes, for the 1 plane. + * */ enum AVSampleFormat { AV_SAMPLE_FMT_NONE = -1, @@ -157,6 +167,15 @@ int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt); int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align); +/** + * @} + * + * @defgroup lavu_sampmanip Samples manipulation + * + * Functions that manipulate audio samples + * @{ + */ + /** * Fill plane data pointers and linesize for samples with sample * format sample_fmt. @@ -253,4 +272,8 @@ int av_samples_copy(uint8_t **dst, uint8_t * const *src, int dst_offset, int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples, int nb_channels, enum AVSampleFormat sample_fmt); +/** + * @} + * @} + */ #endif /* AVUTIL_SAMPLEFMT_H */ diff --git a/libavutil/stereo3d.h b/libavutil/stereo3d.h index 8829da9ff..1135dc9dd 100644 --- a/libavutil/stereo3d.h +++ b/libavutil/stereo3d.h @@ -18,6 +18,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifndef AVUTIL_STEREO3D_H +#define AVUTIL_STEREO3D_H + #include #include "frame.h" @@ -145,3 +148,5 @@ AVStereo3D *av_stereo3d_alloc(void); * @return The AVStereo3D structure to be filled by caller. */ AVStereo3D *av_stereo3d_create_side_data(AVFrame *frame); + +#endif /* AVUTIL_STEREO3D_H */ diff --git a/libavutil/threadmessage.c b/libavutil/threadmessage.c new file mode 100644 index 000000000..b7fcbe28c --- /dev/null +++ b/libavutil/threadmessage.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2014 Nicolas George + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "fifo.h" +#include "threadmessage.h" +#if HAVE_THREADS +#if HAVE_PTHREADS +#include +#elif HAVE_W32THREADS +#include "compat/w32pthreads.h" +#elif HAVE_OS2THREADS +#include "compat/os2threads.h" +#else +#error "Unknown threads implementation" +#endif +#endif + +struct AVThreadMessageQueue { +#if HAVE_THREADS + AVFifoBuffer *fifo; + pthread_mutex_t lock; + pthread_cond_t cond; + int err_send; + int err_recv; + unsigned elsize; +#else + int dummy; +#endif +}; + +int av_thread_message_queue_alloc(AVThreadMessageQueue **mq, + unsigned nelem, + unsigned elsize) +{ +#if HAVE_THREADS + AVThreadMessageQueue *rmq; + int ret = 0; + + if (nelem > INT_MAX / elsize) + return AVERROR(EINVAL); + if (!(rmq = av_mallocz(sizeof(*rmq)))) + return AVERROR(ENOMEM); + if ((ret = pthread_mutex_init(&rmq->lock, NULL))) { + av_free(rmq); + return AVERROR(ret); + } + if ((ret = pthread_cond_init(&rmq->cond, NULL))) { + pthread_mutex_destroy(&rmq->lock); + av_free(rmq); + return AVERROR(ret); + } + if (!(rmq->fifo = av_fifo_alloc(elsize * nelem))) { + pthread_cond_destroy(&rmq->cond); + pthread_mutex_destroy(&rmq->lock); + av_free(rmq); + return AVERROR(ret); + } + rmq->elsize = elsize; + *mq = rmq; + return 0; +#else + *mq = NULL; + return AVERROR(ENOSYS); +#endif /* HAVE_THREADS */ +} + +void av_thread_message_queue_free(AVThreadMessageQueue **mq) +{ +#if HAVE_THREADS + if (*mq) { + av_fifo_freep(&(*mq)->fifo); + pthread_cond_destroy(&(*mq)->cond); + pthread_mutex_destroy(&(*mq)->lock); + av_freep(mq); + } +#endif +} + +#if HAVE_THREADS + +static int av_thread_message_queue_send_locked(AVThreadMessageQueue *mq, + void *msg, + unsigned flags) +{ + while (!mq->err_send && av_fifo_space(mq->fifo) < mq->elsize) { + if ((flags & AV_THREAD_MESSAGE_NONBLOCK)) + return AVERROR(EAGAIN); + pthread_cond_wait(&mq->cond, &mq->lock); + } + if (mq->err_send) + return mq->err_send; + av_fifo_generic_write(mq->fifo, msg, mq->elsize, NULL); + pthread_cond_signal(&mq->cond); + return 0; +} + +static int av_thread_message_queue_recv_locked(AVThreadMessageQueue *mq, + void *msg, + unsigned flags) +{ + while (!mq->err_recv && av_fifo_size(mq->fifo) < mq->elsize) { + if ((flags & AV_THREAD_MESSAGE_NONBLOCK)) + return AVERROR(EAGAIN); + pthread_cond_wait(&mq->cond, &mq->lock); + } + if (av_fifo_size(mq->fifo) < mq->elsize) + return mq->err_recv; + av_fifo_generic_read(mq->fifo, msg, mq->elsize, NULL); + pthread_cond_signal(&mq->cond); + return 0; +} + +#endif /* HAVE_THREADS */ + +int av_thread_message_queue_send(AVThreadMessageQueue *mq, + void *msg, + unsigned flags) +{ +#if HAVE_THREADS + int ret; + + pthread_mutex_lock(&mq->lock); + ret = av_thread_message_queue_send_locked(mq, msg, flags); + pthread_mutex_unlock(&mq->lock); + return ret; +#else + return AVERROR(ENOSYS); +#endif /* HAVE_THREADS */ +} + +int av_thread_message_queue_recv(AVThreadMessageQueue *mq, + void *msg, + unsigned flags) +{ +#if HAVE_THREADS + int ret; + + pthread_mutex_lock(&mq->lock); + ret = av_thread_message_queue_recv_locked(mq, msg, flags); + pthread_mutex_unlock(&mq->lock); + return ret; +#else + return AVERROR(ENOSYS); +#endif /* HAVE_THREADS */ +} + +void av_thread_message_queue_set_err_send(AVThreadMessageQueue *mq, + int err) +{ +#if HAVE_THREADS + pthread_mutex_lock(&mq->lock); + mq->err_send = err; + pthread_cond_broadcast(&mq->cond); + pthread_mutex_unlock(&mq->lock); +#endif /* HAVE_THREADS */ +} + +void av_thread_message_queue_set_err_recv(AVThreadMessageQueue *mq, + int err) +{ +#if HAVE_THREADS + pthread_mutex_lock(&mq->lock); + mq->err_recv = err; + pthread_cond_broadcast(&mq->cond); + pthread_mutex_unlock(&mq->lock); +#endif /* HAVE_THREADS */ +} diff --git a/libavutil/threadmessage.h b/libavutil/threadmessage.h new file mode 100644 index 000000000..a8481d8ec --- /dev/null +++ b/libavutil/threadmessage.h @@ -0,0 +1,91 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_THREADMESSAGE_H +#define AVUTIL_THREADMESSAGE_H + +typedef struct AVThreadMessageQueue AVThreadMessageQueue; + +typedef enum AVThreadMessageFlags { + + /** + * Perform non-blocking operation. + * If this flag is set, send and recv operations are non-blocking and + * return AVERROR(EAGAIN) immediately if they can not proceed. + */ + AV_THREAD_MESSAGE_NONBLOCK = 1, + +} AVThreadMessageFlags; + +/** + * Allocate a new message queue. + * + * @param mq pointer to the message queue + * @param nelem maximum number of elements in the queue + * @param elsize size of each element in the queue + * @return >=0 for success; <0 for error, in particular AVERROR(ENOSYS) if + * lavu was built without thread support + */ +int av_thread_message_queue_alloc(AVThreadMessageQueue **mq, + unsigned nelem, + unsigned elsize); + +/** + * Free a message queue. + * + * The message queue must no longer be in use by another thread. + */ +void av_thread_message_queue_free(AVThreadMessageQueue **mq); + +/** + * Send a message on the queue. + */ +int av_thread_message_queue_send(AVThreadMessageQueue *mq, + void *msg, + unsigned flags); + +/** + * Receive a message from the queue. + */ +int av_thread_message_queue_recv(AVThreadMessageQueue *mq, + void *msg, + unsigned flags); + +/** + * Set the sending error code. + * + * If the error code is set to non-zero, av_thread_message_queue_recv() will + * return it immediately when there are no longer available messages. + * Conventional values, such as AVERROR_EOF or AVERROR(EAGAIN), can be used + * to cause the receiving thread to stop or suspend its operation. + */ +void av_thread_message_queue_set_err_send(AVThreadMessageQueue *mq, + int err); + +/** + * Set the receiving error code. + * + * If the error code is set to non-zero, av_thread_message_queue_send() will + * return it immediately. Conventional values, such as AVERROR_EOF or + * AVERROR(EAGAIN), can be used to cause the sending thread to stop or + * suspend its operation. + */ +void av_thread_message_queue_set_err_recv(AVThreadMessageQueue *mq, + int err); + +#endif /* AVUTIL_THREADMESSAGE_H */ diff --git a/libavutil/time.c b/libavutil/time.c index 5a00e7025..ce4552e76 100644 --- a/libavutil/time.c +++ b/libavutil/time.c @@ -53,6 +53,26 @@ int64_t av_gettime(void) #endif } +int64_t av_gettime_relative(void) +{ +#if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC) + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000; +#else + return av_gettime(); +#endif +} + +int av_gettime_relative_is_monotonic(void) +{ +#if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC) + return 1; +#else + return 0; +#endif +} + int av_usleep(unsigned usec) { #if HAVE_NANOSLEEP diff --git a/libavutil/time.h b/libavutil/time.h index 90eb43694..910d28e85 100644 --- a/libavutil/time.h +++ b/libavutil/time.h @@ -28,6 +28,21 @@ */ 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. + * If a monotonic clock is not available on the targeted platform, the + * implementation fallsback on using av_gettime(). + */ +int64_t av_gettime_relative(void); + +/** + * Indicates with a boolean result if the av_gettime_relative() time source + * is monotonic. + */ +int av_gettime_relative_is_monotonic(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 diff --git a/libavutil/timecode.c b/libavutil/timecode.c index d396032b9..1dfd04086 100644 --- a/libavutil/timecode.c +++ b/libavutil/timecode.c @@ -141,7 +141,7 @@ char *av_timecode_make_mpeg_tc_string(char *buf, uint32_t tc25bit) static int check_fps(int fps) { int i; - static const int supported_fps[] = {24, 25, 30, 50, 60}; + static const int supported_fps[] = {24, 25, 30, 48, 50, 60}; for (i = 0; i < FF_ARRAY_ELEMS(supported_fps); i++) if (fps == supported_fps[i]) diff --git a/libavutil/timer.h b/libavutil/timer.h index 8de67f16d..3fff77ff1 100644 --- a/libavutil/timer.h +++ b/libavutil/timer.h @@ -32,6 +32,10 @@ #include "config.h" +#if HAVE_MACH_MACH_TIME_H +#include +#endif + #include "log.h" #if ARCH_ARM @@ -44,8 +48,16 @@ # include "x86/timer.h" #endif -#if !defined(AV_READ_TIME) && HAVE_GETHRTIME -# define AV_READ_TIME gethrtime +#if !defined(AV_READ_TIME) +# if HAVE_GETHRTIME +# define AV_READ_TIME gethrtime +# elif HAVE_MACH_ABSOLUTE_TIME +# define AV_READ_TIME mach_absolute_time +# endif +#endif + +#ifndef FF_TIMER_UNITS +# define FF_TIMER_UNITS "UNITS" #endif #ifdef AV_READ_TIME @@ -68,7 +80,7 @@ tskip_count++; \ if (((tcount + tskip_count) & (tcount + tskip_count - 1)) == 0) { \ av_log(NULL, AV_LOG_ERROR, \ - "%"PRIu64" decicycles in %s, %d runs, %d skips\n", \ + "%"PRIu64" " FF_TIMER_UNITS " in %s, %d runs, %d skips\n", \ tsum * 10 / tcount, id, tcount, tskip_count); \ } \ } diff --git a/libavutil/utils.c b/libavutil/utils.c index 4c82503d9..aafd3b909 100644 --- a/libavutil/utils.c +++ b/libavutil/utils.c @@ -40,7 +40,7 @@ unsigned avutil_version(void) av_assert0(LIBAVUTIL_VERSION_MICRO >= 100); av_assert0(HAVE_MMX2 == HAVE_MMXEXT); - av_assert0(((size_t)-1) > 0); // C gurantees this but if false on a platform we care about revert at least b284e1ffe343d6697fb950d1ee517bafda8a9844 + av_assert0(((size_t)-1) > 0); // C guarantees this but if false on a platform we care about revert at least b284e1ffe343d6697fb950d1ee517bafda8a9844 if (av_sat_dadd32(1, 2) != 5) { av_log(NULL, AV_LOG_FATAL, "Libavutil has been build with a broken binutils, please upgrade binutils and rebuild\n"); @@ -113,3 +113,8 @@ unsigned av_int_list_length_for_size(unsigned elsize, } return i; } + +AVRational av_get_time_base_q(void) +{ + return (AVRational){1, AV_TIME_BASE}; +} diff --git a/libavutil/version.h b/libavutil/version.h index 7f093cd58..0d254b1a8 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -24,7 +24,7 @@ #include "macros.h" /** - * @defgroup version_utils Library Version Macros + * @addtogroup version_utils * * Useful to check and match library version in order to maintain * backward compatibility. @@ -56,7 +56,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 52 -#define LIBAVUTIL_VERSION_MINOR 66 +#define LIBAVUTIL_VERSION_MINOR 92 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ @@ -137,6 +137,18 @@ #ifndef FF_API_OPT_TYPE_METADATA #define FF_API_OPT_TYPE_METADATA (LIBAVUTIL_VERSION_MAJOR < 54) #endif +#ifndef FF_API_AVFRAME_COLORSPACE +#define FF_API_AVFRAME_COLORSPACE (LIBAVUTIL_VERSION_MAJOR >= 52) +#endif + + +#ifndef FF_CONST_AVUTIL53 +#if LIBAVUTIL_VERSION_MAJOR >= 53 +#define FF_CONST_AVUTIL53 const +#else +#define FF_CONST_AVUTIL53 +#endif +#endif /** * @} diff --git a/libavutil/x86/asm.h b/libavutil/x86/asm.h index 70ccac788..616ad6c96 100644 --- a/libavutil/x86/asm.h +++ b/libavutil/x86/asm.h @@ -25,6 +25,7 @@ #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" @@ -107,6 +108,46 @@ typedef int x86_reg; # define LOCAL_MANGLE(a) #a #endif -#define MANGLE(a) EXTERN_PREFIX LOCAL_MANGLE(a) +#if HAVE_INLINE_ASM_DIRECT_SYMBOL_REFS +# define MANGLE(a) EXTERN_PREFIX LOCAL_MANGLE(a) +# define NAMED_CONSTRAINTS_ADD(...) +# define NAMED_CONSTRAINTS(...) +# define NAMED_CONSTRAINTS_ARRAY_ADD(...) +# define NAMED_CONSTRAINTS_ARRAY(...) +#else + /* When direct symbol references are used in code passed to a compiler that does not support them + * then these references need to be converted to named asm constraints instead. + * Instead of returning a direct symbol MANGLE now returns a named constraint for that specific symbol. + * In order for this to work there must also be a corresponding entry in the asm-interface. To add this + * entry use the macro NAMED_CONSTRAINTS() and pass in a list of each symbol reference used in the + * corresponding block of code. (e.g. NAMED_CONSTRAINTS(var1,var2,var3) where var1 is the first symbol etc. ). + * If there are already existing constraints then use NAMED_CONSTRAINTS_ADD to add to the existing constraint list. + */ +# define MANGLE(a) "%["#a"]" + // Intel/MSVC does not correctly expand va-args so we need a rather ugly hack in order to get it to work +# define FE_0(P,X) P(X) +# define FE_1(P,X,X1) P(X), FE_0(P,X1) +# define FE_2(P,X,X1,X2) P(X), FE_1(P,X1,X2) +# define FE_3(P,X,X1,X2,X3) P(X), FE_2(P,X1,X2,X3) +# define FE_4(P,X,X1,X2,X3,X4) P(X), FE_3(P,X1,X2,X3,X4) +# define FE_5(P,X,X1,X2,X3,X4,X5) P(X), FE_4(P,X1,X2,X3,X4,X5) +# define FE_6(P,X,X1,X2,X3,X4,X5,X6) P(X), FE_5(P,X1,X2,X3,X4,X5,X6) +# define FE_7(P,X,X1,X2,X3,X4,X5,X6,X7) P(X), FE_6(P,X1,X2,X3,X4,X5,X6,X7) +# define FE_8(P,X,X1,X2,X3,X4,X5,X6,X7,X8) P(X), FE_7(P,X1,X2,X3,X4,X5,X6,X7,X8) +# define FE_9(P,X,X1,X2,X3,X4,X5,X6,X7,X8,X9) P(X), FE_8(P,X1,X2,X3,X4,X5,X6,X7,X8,X9) +# define GET_FE_IMPL(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,NAME,...) NAME +# define GET_FE(A) GET_FE_IMPL A +# define GET_FE_GLUE(x, y) x y +# define FOR_EACH_VA(P,...) GET_FE_GLUE(GET_FE((__VA_ARGS__,FE_9,FE_8,FE_7,FE_6,FE_5,FE_4,FE_3,FE_2,FE_1,FE_0)), (P,__VA_ARGS__)) +# define NAME_CONSTRAINT(x) [x] "m"(x) + // Parameters are a list of each symbol reference required +# define NAMED_CONSTRAINTS_ADD(...) , FOR_EACH_VA(NAME_CONSTRAINT,__VA_ARGS__) + // Same but without comma for when there are no previously defined constraints +# define NAMED_CONSTRAINTS(...) FOR_EACH_VA(NAME_CONSTRAINT,__VA_ARGS__) + // Same as above NAMED_CONSTRAINTS except used for passing arrays/pointers instead of normal variables +# define NAME_CONSTRAINT_ARRAY(x) [x] "m"(*x) +# define NAMED_CONSTRAINTS_ARRAY_ADD(...) , FOR_EACH_VA(NAME_CONSTRAINT_ARRAY,__VA_ARGS__) +# define NAMED_CONSTRAINTS_ARRAY(...) FOR_EACH_VA(NAME_CONSTRAINT_ARRAY,__VA_ARGS__) +#endif #endif /* AVUTIL_X86_ASM_H */ diff --git a/libavutil/x86/cpuid.asm b/libavutil/x86/cpuid.asm index 56876a870..c3f7866ec 100644 --- a/libavutil/x86/cpuid.asm +++ b/libavutil/x86/cpuid.asm @@ -2,7 +2,7 @@ ;* Copyright (C) 2005-2010 x264 project ;* ;* Authors: Loren Merritt -;* Jason Garrett-Glaser +;* Fiona Glaser ;* ;* This file is part of FFmpeg. ;* diff --git a/libavutil/x86/float_dsp.asm b/libavutil/x86/float_dsp.asm index f762e34f6..ec3d22b23 100644 --- a/libavutil/x86/float_dsp.asm +++ b/libavutil/x86/float_dsp.asm @@ -61,33 +61,48 @@ VECTOR_FMUL %macro VECTOR_FMAC_SCALAR 0 %if UNIX64 -cglobal vector_fmac_scalar, 3,3,3, dst, src, len +cglobal vector_fmac_scalar, 3,3,5, dst, src, len %else -cglobal vector_fmac_scalar, 4,4,3, dst, src, mul, len +cglobal vector_fmac_scalar, 4,4,5, dst, src, mul, len %endif %if ARCH_X86_32 VBROADCASTSS m0, mulm %else %if WIN64 - mova xmm0, xmm2 + SWAP 0, 2 %endif - shufps xmm0, xmm0, 0 + shufps xm0, xm0, 0 %if cpuflag(avx) - vinsertf128 m0, m0, xmm0, 1 + vinsertf128 m0, m0, xm0, 1 %endif %endif lea lenq, [lend*4-64] .loop: -%assign a 0 -%rep 32/mmsize - mulps m1, m0, [srcq+lenq+(a+0)*mmsize] - mulps m2, m0, [srcq+lenq+(a+1)*mmsize] - addps m1, m1, [dstq+lenq+(a+0)*mmsize] - addps m2, m2, [dstq+lenq+(a+1)*mmsize] - mova [dstq+lenq+(a+0)*mmsize], m1 - mova [dstq+lenq+(a+1)*mmsize], m2 -%assign a a+2 -%endrep +%if cpuflag(fma3) + mova m1, [dstq+lenq] + mova m2, [dstq+lenq+1*mmsize] + fmaddps m1, m0, [srcq+lenq], m1 + fmaddps m2, m0, [srcq+lenq+1*mmsize], m2 +%else ; cpuflag + mulps m1, m0, [srcq+lenq] + mulps m2, m0, [srcq+lenq+1*mmsize] +%if mmsize < 32 + mulps m3, m0, [srcq+lenq+2*mmsize] + mulps m4, m0, [srcq+lenq+3*mmsize] +%endif ; mmsize + addps m1, m1, [dstq+lenq] + addps m2, m2, [dstq+lenq+1*mmsize] +%if mmsize < 32 + addps m3, m3, [dstq+lenq+2*mmsize] + addps m4, m4, [dstq+lenq+3*mmsize] +%endif ; mmsize +%endif ; cpuflag + mova [dstq+lenq], m1 + mova [dstq+lenq+1*mmsize], m2 +%if mmsize < 32 + mova [dstq+lenq+2*mmsize], m3 + mova [dstq+lenq+3*mmsize], m4 +%endif ; mmsize sub lenq, 64 jge .loop REP_RET @@ -99,6 +114,10 @@ VECTOR_FMAC_SCALAR INIT_YMM avx VECTOR_FMAC_SCALAR %endif +%if HAVE_FMA3_EXTERNAL +INIT_YMM fma3 +VECTOR_FMAC_SCALAR +%endif ;------------------------------------------------------------------------------ ; void ff_vector_fmul_scalar(float *dst, const float *src, float mul, int len) @@ -147,16 +166,11 @@ cglobal vector_dmul_scalar, 4,4,3, dst, src, mul, len VBROADCASTSD m0, mulm %else %if WIN64 - movlhps xmm2, xmm2 -%if cpuflag(avx) - vinsertf128 ymm2, ymm2, xmm2, 1 -%endif SWAP 0, 2 -%else - movlhps xmm0, xmm0 -%if cpuflag(avx) - vinsertf128 ymm0, ymm0, xmm0, 1 %endif + movlhps xm0, xm0 +%if cpuflag(avx) + vinsertf128 ym0, ym0, xm0, 1 %endif %endif lea lenq, [lend*8-2*mmsize] @@ -177,21 +191,86 @@ INIT_YMM avx VECTOR_DMUL_SCALAR %endif +;----------------------------------------------------------------------------- +; vector_fmul_window(float *dst, const float *src0, +; const float *src1, const float *win, int len); +;----------------------------------------------------------------------------- +%macro VECTOR_FMUL_WINDOW 0 +cglobal vector_fmul_window, 5, 6, 6, dst, src0, src1, win, len, len1 + shl lend, 2 + lea len1q, [lenq - mmsize] + add src0q, lenq + add dstq, lenq + add winq, lenq + neg lenq +.loop + mova m0, [winq + lenq] + mova m4, [src0q + lenq] +%if cpuflag(sse) + mova m1, [winq + len1q] + mova m5, [src1q + len1q] + shufps m1, m1, 0x1b + shufps m5, m5, 0x1b + mova m2, m0 + mova m3, m1 + mulps m2, m4 + mulps m3, m5 + mulps m1, m4 + mulps m0, m5 + addps m2, m3 + subps m1, m0 + shufps m2, m2, 0x1b +%else + pswapd m1, [winq + len1q] + pswapd m5, [src1q + len1q] + mova m2, m0 + mova m3, m1 + pfmul m2, m4 + pfmul m3, m5 + pfmul m1, m4 + pfmul m0, m5 + pfadd m2, m3 + pfsub m1, m0 + pswapd m2, m2 +%endif + mova [dstq + lenq], m1 + mova [dstq + len1q], m2 + sub len1q, mmsize + add lenq, mmsize + jl .loop +%if mmsize == 8 + femms +%endif + REP_RET +%endmacro + +INIT_MMX 3dnowext +VECTOR_FMUL_WINDOW +INIT_XMM sse +VECTOR_FMUL_WINDOW + ;----------------------------------------------------------------------------- ; vector_fmul_add(float *dst, const float *src0, const float *src1, ; const float *src2, int len) ;----------------------------------------------------------------------------- %macro VECTOR_FMUL_ADD 0 -cglobal vector_fmul_add, 5,5,2, dst, src0, src1, src2, len +cglobal vector_fmul_add, 5,5,4, dst, src0, src1, src2, len lea lenq, [lend*4 - 2*mmsize] ALIGN 16 .loop: mova m0, [src0q + lenq] mova m1, [src0q + lenq + mmsize] +%if cpuflag(fma3) + mova m2, [src2q + lenq] + mova m3, [src2q + lenq + mmsize] + fmaddps m0, m0, [src1q + lenq], m2 + fmaddps m1, m1, [src1q + lenq + mmsize], m3 +%else mulps m0, m0, [src1q + lenq] mulps m1, m1, [src1q + lenq + mmsize] addps m0, m0, [src2q + lenq] addps m1, m1, [src2q + lenq + mmsize] +%endif mova [dstq + lenq], m0 mova [dstq + lenq + mmsize], m1 @@ -206,6 +285,10 @@ VECTOR_FMUL_ADD INIT_YMM avx VECTOR_FMUL_ADD %endif +%if HAVE_FMA3_EXTERNAL +INIT_YMM fma3 +VECTOR_FMUL_ADD +%endif ;----------------------------------------------------------------------------- ; void vector_fmul_reverse(float *dst, const float *src0, const float *src1, diff --git a/libavutil/x86/float_dsp_init.c b/libavutil/x86/float_dsp_init.c index 97f7b7c7c..64b3a4d6b 100644 --- a/libavutil/x86/float_dsp_init.c +++ b/libavutil/x86/float_dsp_init.c @@ -33,6 +33,8 @@ void ff_vector_fmac_scalar_sse(float *dst, const float *src, float mul, int len); void ff_vector_fmac_scalar_avx(float *dst, const float *src, float mul, int len); +void ff_vector_fmac_scalar_fma3(float *dst, const float *src, float mul, + int len); void ff_vector_fmul_scalar_sse(float *dst, const float *src, float mul, int len); @@ -42,10 +44,17 @@ void ff_vector_dmul_scalar_sse2(double *dst, const double *src, void ff_vector_dmul_scalar_avx(double *dst, const double *src, double mul, int len); +void ff_vector_fmul_window_3dnowext(float *dst, const float *src0, + const float *src1, const float *win, int len); +void ff_vector_fmul_window_sse(float *dst, const float *src0, + const float *src1, const float *win, int len); + void ff_vector_fmul_add_sse(float *dst, const float *src0, const float *src1, const float *src2, int len); void ff_vector_fmul_add_avx(float *dst, const float *src0, const float *src1, const float *src2, int len); +void ff_vector_fmul_add_fma3(float *dst, const float *src0, const float *src1, + const float *src2, int len); void ff_vector_fmul_reverse_sse(float *dst, const float *src0, const float *src1, int len); @@ -56,88 +65,18 @@ float ff_scalarproduct_float_sse(const float *v1, const float *v2, int order); void ff_butterflies_float_sse(float *src0, float *src1, int len); -#if HAVE_6REGS && HAVE_INLINE_ASM -static void vector_fmul_window_3dnowext(float *dst, const float *src0, - const float *src1, const float *win, - int len) -{ - x86_reg i = -len * 4; - x86_reg j = len * 4 - 8; - __asm__ volatile ( - "1: \n" - "pswapd (%5, %1), %%mm1 \n" - "movq (%5, %0), %%mm0 \n" - "pswapd (%4, %1), %%mm5 \n" - "movq (%3, %0), %%mm4 \n" - "movq %%mm0, %%mm2 \n" - "movq %%mm1, %%mm3 \n" - "pfmul %%mm4, %%mm2 \n" // src0[len + i] * win[len + i] - "pfmul %%mm5, %%mm3 \n" // src1[j] * win[len + j] - "pfmul %%mm4, %%mm1 \n" // src0[len + i] * win[len + j] - "pfmul %%mm5, %%mm0 \n" // src1[j] * win[len + i] - "pfadd %%mm3, %%mm2 \n" - "pfsub %%mm0, %%mm1 \n" - "pswapd %%mm2, %%mm2 \n" - "movq %%mm1, (%2, %0) \n" - "movq %%mm2, (%2, %1) \n" - "sub $8, %1 \n" - "add $8, %0 \n" - "jl 1b \n" - "femms \n" - : "+r"(i), "+r"(j) - : "r"(dst + len), "r"(src0 + len), "r"(src1), "r"(win + len) - ); -} - -static void vector_fmul_window_sse(float *dst, const float *src0, - const float *src1, const float *win, int len) -{ - x86_reg i = -len * 4; - x86_reg j = len * 4 - 16; - __asm__ volatile ( - "1: \n" - "movaps (%5, %1), %%xmm1 \n" - "movaps (%5, %0), %%xmm0 \n" - "movaps (%4, %1), %%xmm5 \n" - "movaps (%3, %0), %%xmm4 \n" - "shufps $0x1b, %%xmm1, %%xmm1 \n" - "shufps $0x1b, %%xmm5, %%xmm5 \n" - "movaps %%xmm0, %%xmm2 \n" - "movaps %%xmm1, %%xmm3 \n" - "mulps %%xmm4, %%xmm2 \n" // src0[len + i] * win[len + i] - "mulps %%xmm5, %%xmm3 \n" // src1[j] * win[len + j] - "mulps %%xmm4, %%xmm1 \n" // src0[len + i] * win[len + j] - "mulps %%xmm5, %%xmm0 \n" // src1[j] * win[len + i] - "addps %%xmm3, %%xmm2 \n" - "subps %%xmm0, %%xmm1 \n" - "shufps $0x1b, %%xmm2, %%xmm2 \n" - "movaps %%xmm1, (%2, %0) \n" - "movaps %%xmm2, (%2, %1) \n" - "sub $16, %1 \n" - "add $16, %0 \n" - "jl 1b \n" - : "+r"(i), "+r"(j) - : "r"(dst + len), "r"(src0 + len), "r"(src1), "r"(win + len) - ); -} -#endif /* HAVE_6REGS && HAVE_INLINE_ASM */ - av_cold void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp) { int cpu_flags = av_get_cpu_flags(); -#if HAVE_6REGS && HAVE_INLINE_ASM - if (INLINE_AMD3DNOWEXT(cpu_flags)) { - fdsp->vector_fmul_window = vector_fmul_window_3dnowext; + if (EXTERNAL_AMD3DNOWEXT(cpu_flags)) { + fdsp->vector_fmul_window = ff_vector_fmul_window_3dnowext; } - if (INLINE_SSE(cpu_flags)) { - fdsp->vector_fmul_window = vector_fmul_window_sse; - } -#endif if (EXTERNAL_SSE(cpu_flags)) { fdsp->vector_fmul = ff_vector_fmul_sse; fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_sse; fdsp->vector_fmul_scalar = ff_vector_fmul_scalar_sse; + fdsp->vector_fmul_window = ff_vector_fmul_window_sse; fdsp->vector_fmul_add = ff_vector_fmul_add_sse; fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_sse; fdsp->scalarproduct_float = ff_scalarproduct_float_sse; @@ -153,4 +92,8 @@ av_cold void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp) fdsp->vector_fmul_add = ff_vector_fmul_add_avx; fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_avx; } + if (EXTERNAL_FMA3(cpu_flags)) { + fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_fma3; + fdsp->vector_fmul_add = ff_vector_fmul_add_fma3; + } } diff --git a/libavutil/x86/timer.h b/libavutil/x86/timer.h index d812d46ae..5b24b511c 100644 --- a/libavutil/x86/timer.h +++ b/libavutil/x86/timer.h @@ -25,6 +25,7 @@ #if HAVE_INLINE_ASM +#define FF_TIMER_UNITS "decicycles" #define AV_READ_TIME read_time static inline uint64_t read_time(void) diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm index a7f9f5436..1cfb05509 100644 --- a/libavutil/x86/x86inc.asm +++ b/libavutil/x86/x86inc.asm @@ -5,7 +5,7 @@ ;* ;* Authors: Loren Merritt ;* Anton Mitrofanov -;* Jason Garrett-Glaser +;* Fiona Glaser ;* Henrik Gramner ;* ;* Permission to use, copy, modify, and/or distribute this software for any diff --git a/libavutil/x86/x86util.asm b/libavutil/x86/x86util.asm index df58cadf6..9fb477854 100644 --- a/libavutil/x86/x86util.asm +++ b/libavutil/x86/x86util.asm @@ -273,6 +273,44 @@ %endif %endmacro +%macro HADDD 2 ; sum junk +%if sizeof%1 == 32 +%define %2 xmm%2 + vextracti128 %2, %1, 1 +%define %1 xmm%1 + paddd %1, %2 +%endif +%if mmsize >= 16 +%if cpuflag(xop) && sizeof%1 == 16 + vphadddq %1, %1 +%endif + movhlps %2, %1 + paddd %1, %2 +%endif +%if notcpuflag(xop) || sizeof%1 != 16 +%if cpuflag(mmxext) + PSHUFLW %2, %1, q0032 +%else ; mmx + mova %2, %1 + psrlq %2, 32 +%endif + paddd %1, %2 +%endif +%undef %1 +%undef %2 +%endmacro + +%macro HADDW 2 ; reg, tmp +%if cpuflag(xop) && sizeof%1 == 16 + vphaddwq %1, %1 + movhlps %2, %1 + paddd %1, %2 +%else + pmaddwd %1, [pw_1] + HADDD %1, %2 +%endif +%endmacro + %macro PALIGNR 4-5 %if cpuflag(ssse3) %if %0==5 @@ -302,11 +340,19 @@ %endif %endmacro -%macro PAVGB 2 +%macro PAVGB 2-4 %if cpuflag(mmxext) pavgb %1, %2 %elif cpuflag(3dnow) pavgusb %1, %2 +%elif cpuflag(mmx) + movu %3, %2 + por %3, %1 + pxor %1, %2 + pand %1, %4 + psrlq %1, 1 + psubb %3, %1 + SWAP %1, %3 %endif %endmacro @@ -697,3 +743,19 @@ PMA_EMU PMADCSWD, pmadcswd, pmaddwd, paddd addps %1, %4 %endif %endmacro + +%macro LSHIFT 2 +%if mmsize > 8 + pslldq %1, %2 +%else + psllq %1, 8*(%2) +%endif +%endmacro + +%macro RSHIFT 2 +%if mmsize > 8 + psrldq %1, %2 +%else + psrlq %1, 8*(%2) +%endif +%endmacro diff --git a/libpostproc/postprocess_template.c b/libpostproc/postprocess_template.c index 74b0ab4c4..0761c5027 100644 --- a/libpostproc/postprocess_template.c +++ b/libpostproc/postprocess_template.c @@ -490,6 +490,7 @@ static inline void RENAME(vertX1Filter)(uint8_t *src, int stride, PPContext *co) : : "r" (src), "r" ((x86_reg)stride), "m" (co->pQPb) + NAMED_CONSTRAINTS_ADD(b01) : "%"REG_a, "%"REG_c ); #else //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW @@ -755,6 +756,7 @@ static inline void RENAME(doVertDefFilter)(uint8_t src[], int stride, PPContext : : "r" (src), "r" ((x86_reg)stride), "m" (c->pQPb) + NAMED_CONSTRAINTS_ADD(b80,b00,b01) : "%"REG_a, "%"REG_c ); @@ -1042,6 +1044,7 @@ static inline void RENAME(doVertDefFilter)(uint8_t src[], int stride, PPContext : "+r" (src) : "r" ((x86_reg)stride), "m" (c->pQPb), "r"(tmp) + NAMED_CONSTRAINTS_ADD(w05,w20) : "%"REG_a ); #else //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW @@ -1313,6 +1316,7 @@ DERING_CORE((%0, %1, 8) ,(%%REGd, %1, 4),%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1, "1: \n\t" : : "r" (src), "r" ((x86_reg)stride), "m" (c->pQPb), "m"(c->pQPb2), "q"(tmp) + NAMED_CONSTRAINTS_ADD(deringThreshold,b00,b02,b08) : "%"REG_a, "%"REG_d, "%"REG_SP ); #else // HAVE_7REGS && (TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW) @@ -1664,7 +1668,7 @@ DEINT_FF((%%REGd, %1), (%%REGd, %1, 2), (%0, %1, 8) , (%%REGd, %1, 4)) */ static inline void RENAME(deInterlaceL5)(uint8_t src[], int stride, uint8_t *tmp, uint8_t *tmp2) { -#if TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW +#if (TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW) && HAVE_6REGS src+= stride*4; __asm__ volatile( "lea (%0, %1), %%"REG_a" \n\t" @@ -1724,7 +1728,7 @@ DEINT_L5(%%mm1, %%mm0, (%%REGd, %1, 2), (%0, %1, 8) , (%%REGd, %1, 4)) : : "r" (src), "r" ((x86_reg)stride), "r"(tmp), "r"(tmp2) : "%"REG_a, "%"REG_d ); -#else //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW +#else //(TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW) && HAVE_6REGS int x; src+= stride*4; for(x=0; x<8; x++){ @@ -1753,7 +1757,7 @@ DEINT_L5(%%mm1, %%mm0, (%%REGd, %1, 2), (%0, %1, 8) , (%%REGd, %1, 4)) src++; } -#endif //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW +#endif //(TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW) && HAVE_6REGS } /** @@ -2160,7 +2164,7 @@ static inline void RENAME(tempNoiseReducer)(uint8_t *src, int stride, #define FAST_L2_DIFF //#define L1_DIFF //u should change the thresholds too if u try that one -#if TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW +#if (TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW) && HAVE_6REGS __asm__ volatile( "lea (%2, %2, 2), %%"REG_a" \n\t" // 3*stride "lea (%2, %2, 4), %%"REG_d" \n\t" // 5*stride @@ -2446,9 +2450,10 @@ L2_DIFF_CORE((%0, %%REGc) , (%1, %%REGc)) "4: \n\t" :: "r" (src), "r" (tempBlurred), "r"((x86_reg)stride), "m" (tempBlurredPast) + NAMED_CONSTRAINTS_ADD(b80) : "%"REG_a, "%"REG_d, "%"REG_c, "memory" ); -#else //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW +#else //(TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW) && HAVE_6REGS { int y; int d=0; @@ -2531,7 +2536,7 @@ Switch between } } } -#endif //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW +#endif //(TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW) && HAVE_6REGS } #endif //TEMPLATE_PP_ALTIVEC @@ -2790,6 +2795,7 @@ static av_always_inline void RENAME(do_a_deblock)(uint8_t *src, int step, int st : "+&r"(src) : "r" ((x86_reg)step), "m" (c->pQPb), "r"(sums), "g"(src) + NAMED_CONSTRAINTS_ADD(w04) ); src+= step; // src points to begin of the 8x8 Block @@ -3061,6 +3067,7 @@ static av_always_inline void RENAME(do_a_deblock)(uint8_t *src, int step, int st : "+r" (temp_src) : "r" ((x86_reg)step), "m" (c->pQPb), "m"(eq_mask), "r"(tmp) + NAMED_CONSTRAINTS_ADD(w05,w20) : "%"REG_a ); } @@ -3086,11 +3093,11 @@ static void RENAME(postProcess)(const uint8_t src[], int srcStride, uint8_t dst[ static inline void RENAME(blockCopy)(uint8_t dst[], int dstStride, const uint8_t src[], int srcStride, int levelFix, int64_t *packedOffsetAndScale) { -#if !TEMPLATE_PP_MMX +#if !TEMPLATE_PP_MMX || !HAVE_6REGS int i; #endif if(levelFix){ -#if TEMPLATE_PP_MMX +#if TEMPLATE_PP_MMX && HAVE_6REGS __asm__ volatile( "movq (%%"REG_a"), %%mm2 \n\t" // packedYOffset "movq 8(%%"REG_a"), %%mm3 \n\t" // packedYScale @@ -3167,13 +3174,13 @@ SCALED_CPY((%%REGa, %4), (%%REGa, %4, 2), (%%REGd, %5), (%%REGd, %5, 2)) "r" ((x86_reg)dstStride) : "%"REG_d ); -#else //TEMPLATE_PP_MMX +#else //TEMPLATE_PP_MMX && HAVE_6REGS for(i=0; i<8; i++) memcpy( &(dst[dstStride*i]), &(src[srcStride*i]), BLOCK_SIZE); -#endif //TEMPLATE_PP_MMX +#endif //TEMPLATE_PP_MMX && HAVE_6REGS }else{ -#if TEMPLATE_PP_MMX +#if TEMPLATE_PP_MMX && HAVE_6REGS __asm__ volatile( "lea (%0,%2), %%"REG_a" \n\t" "lea (%1,%3), %%"REG_d" \n\t" @@ -3200,11 +3207,11 @@ SIMPLE_CPY((%%REGa, %2), (%%REGa, %2, 2), (%%REGd, %3), (%%REGd, %3, 2)) "r" ((x86_reg)dstStride) : "%"REG_a, "%"REG_d ); -#else //TEMPLATE_PP_MMX +#else //TEMPLATE_PP_MMX && HAVE_6REGS for(i=0; i<8; i++) memcpy( &(dst[dstStride*i]), &(src[srcStride*i]), BLOCK_SIZE); -#endif //TEMPLATE_PP_MMX +#endif //TEMPLATE_PP_MMX && HAVE_6REGS } } @@ -3356,7 +3363,7 @@ static void RENAME(postProcess)(const uint8_t src[], int srcStride, uint8_t dst[ // with the L1 Cache of the P4 ... or only a few blocks at a time or something for(x=0; x>2)&6) + 5)*srcStride + 32); prefetchnta(srcBlock + (((x>>2)&6) + 6)*srcStride + 32); @@ -3492,7 +3499,7 @@ static void RENAME(postProcess)(const uint8_t src[], int srcStride, uint8_t dst[ #endif -#if TEMPLATE_PP_MMXEXT +#if TEMPLATE_PP_MMXEXT && HAVE_6REGS /* prefetchnta(srcBlock + (((x>>2)&6) + 5)*srcStride + 32); prefetchnta(srcBlock + (((x>>2)&6) + 6)*srcStride + 32); diff --git a/libswresample/Makefile b/libswresample/Makefile index 953c9452a..75c6535be 100644 --- a/libswresample/Makefile +++ b/libswresample/Makefile @@ -8,8 +8,10 @@ HEADERS = swresample.h \ OBJS = audioconvert.o \ dither.o \ + options.o \ rematrix.o \ resample.o \ + resample_dsp.o \ swresample.o \ OBJS-$(CONFIG_LIBSOXR) += soxr_resample.o diff --git a/libswresample/audioconvert.c b/libswresample/audioconvert.c index 4ba0ff13b..325bdf4de 100644 --- a/libswresample/audioconvert.c +++ b/libswresample/audioconvert.c @@ -77,7 +77,7 @@ CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(* CONV_FUNC(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_DBL, *(const double*)pi) CONV_FUNC(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_DBL, *(const double*)pi) -#define FMT_PAIR_FUNC(out, in) [out + AV_SAMPLE_FMT_NB*in] = CONV_FUNC_NAME(out, in) +#define FMT_PAIR_FUNC(out, in) [(out) + AV_SAMPLE_FMT_NB*(in)] = CONV_FUNC_NAME(out, in) static conv_func_type * const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB*AV_SAMPLE_FMT_NB] = { FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8 , AV_SAMPLE_FMT_U8 ), diff --git a/libswresample/libswresample.v b/libswresample/libswresample.v index 9b797bde7..0d5efe470 100644 --- a/libswresample/libswresample.v +++ b/libswresample/libswresample.v @@ -1,4 +1,4 @@ LIBSWRESAMPLE_$MAJOR { - global: swr_*; ff_*; swresample_*; + global: swr_*; swresample_*; local: *; }; diff --git a/libswresample/options.c b/libswresample/options.c new file mode 100644 index 000000000..01cdb1e14 --- /dev/null +++ b/libswresample/options.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2011-2013 Michael Niedermayer (michaelni@gmx.at) + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/opt.h" +#include "swresample_internal.h" + +#include + +#define C30DB M_SQRT2 +#define C15DB 1.189207115 +#define C__0DB 1.0 +#define C_15DB 0.840896415 +#define C_30DB M_SQRT1_2 +#define C_45DB 0.594603558 +#define C_60DB 0.5 + +#define OFFSET(x) offsetof(SwrContext,x) +#define PARAM AV_OPT_FLAG_AUDIO_PARAM + +static const AVOption options[]={ +{"ich" , "set input channel count" , OFFSET( in.ch_count ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, +{"in_channel_count" , "set input channel count" , OFFSET( in.ch_count ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, +{"och" , "set output channel count" , OFFSET(out.ch_count ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, +{"out_channel_count" , "set output channel count" , OFFSET(out.ch_count ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, +{"uch" , "set used channel count" , OFFSET(used_ch_count ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, +{"used_channel_count" , "set used channel count" , OFFSET(used_ch_count ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, +{"isr" , "set input sample rate" , OFFSET( in_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, +{"in_sample_rate" , "set input sample rate" , OFFSET( in_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, +{"osr" , "set output sample rate" , OFFSET(out_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, +{"out_sample_rate" , "set output sample rate" , OFFSET(out_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, +{"isf" , "set input sample format" , OFFSET( in_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, +{"in_sample_fmt" , "set input sample format" , OFFSET( in_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, +{"osf" , "set output sample format" , OFFSET(out_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, +{"out_sample_fmt" , "set output sample format" , OFFSET(out_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, +{"tsf" , "set internal sample format" , OFFSET(int_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, +{"internal_sample_fmt" , "set internal sample format" , OFFSET(int_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, +{"icl" , "set input channel layout" , OFFSET( in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, 0 , INT64_MAX , PARAM, "channel_layout"}, +{"in_channel_layout" , "set input channel layout" , OFFSET( in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, 0 , INT64_MAX , PARAM, "channel_layout"}, +{"ocl" , "set output channel layout" , OFFSET(out_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, 0 , INT64_MAX , PARAM, "channel_layout"}, +{"out_channel_layout" , "set output channel layout" , OFFSET(out_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, 0 , INT64_MAX , PARAM, "channel_layout"}, +{"clev" , "set center mix level" , OFFSET(clev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, +{"center_mix_level" , "set center mix level" , OFFSET(clev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, +{"slev" , "set surround mix level" , OFFSET(slev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, +{"surround_mix_level" , "set surround mix Level" , OFFSET(slev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, +{"lfe_mix_level" , "set LFE mix level" , OFFSET(lfe_mix_level ), AV_OPT_TYPE_FLOAT, {.dbl=0 }, -32 , 32 , PARAM}, +{"rmvol" , "set rematrix volume" , OFFSET(rematrix_volume), AV_OPT_TYPE_FLOAT, {.dbl=1.0 }, -1000 , 1000 , PARAM}, +{"rematrix_volume" , "set rematrix volume" , OFFSET(rematrix_volume), AV_OPT_TYPE_FLOAT, {.dbl=1.0 }, -1000 , 1000 , PARAM}, +{"rematrix_maxval" , "set rematrix maxval" , OFFSET(rematrix_maxval), AV_OPT_TYPE_FLOAT, {.dbl=0.0 }, 0 , 1000 , PARAM}, + +{"flags" , "set flags" , OFFSET(flags ), AV_OPT_TYPE_FLAGS, {.i64=0 }, 0 , UINT_MAX , PARAM, "flags"}, +{"swr_flags" , "set flags" , OFFSET(flags ), AV_OPT_TYPE_FLAGS, {.i64=0 }, 0 , UINT_MAX , PARAM, "flags"}, +{"res" , "force resampling" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_FLAG_RESAMPLE }, INT_MIN, INT_MAX , PARAM, "flags"}, + +{"dither_scale" , "set dither scale" , OFFSET(dither.scale ), AV_OPT_TYPE_FLOAT, {.dbl=1 }, 0 , INT_MAX , PARAM}, + +{"dither_method" , "set dither method" , OFFSET(dither.method ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_DITHER_NB-1, PARAM, "dither_method"}, +{"rectangular" , "select rectangular dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_RECTANGULAR}, INT_MIN, INT_MAX , PARAM, "dither_method"}, +{"triangular" , "select triangular dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_TRIANGULAR }, INT_MIN, INT_MAX , PARAM, "dither_method"}, +{"triangular_hp" , "select triangular dither with high pass" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_TRIANGULAR_HIGHPASS }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"lipshitz" , "select lipshitz noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_LIPSHITZ}, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"shibata" , "select shibata noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_SHIBATA }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"low_shibata" , "select low shibata noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_LOW_SHIBATA }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"high_shibata" , "select high shibata noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_HIGH_SHIBATA }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"f_weighted" , "select f-weighted noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_F_WEIGHTED }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"modified_e_weighted" , "select modified-e-weighted noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_MODIFIED_E_WEIGHTED }, INT_MIN, INT_MAX, PARAM, "dither_method"}, +{"improved_e_weighted" , "select improved-e-weighted noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_IMPROVED_E_WEIGHTED }, INT_MIN, INT_MAX, PARAM, "dither_method"}, + +{"filter_size" , "set swr resampling filter size", OFFSET(filter_size) , AV_OPT_TYPE_INT , {.i64=32 }, 0 , INT_MAX , PARAM }, +{"phase_shift" , "set swr resampling phase shift", OFFSET(phase_shift) , AV_OPT_TYPE_INT , {.i64=10 }, 0 , 24 , PARAM }, +{"linear_interp" , "enable linear interpolation" , OFFSET(linear_interp) , AV_OPT_TYPE_INT , {.i64=0 }, 0 , 1 , PARAM }, +{"cutoff" , "set cutoff frequency ratio" , OFFSET(cutoff) , AV_OPT_TYPE_DOUBLE,{.dbl=0. }, 0 , 1 , PARAM }, + +/* duplicate option in order to work with avconv */ +{"resample_cutoff" , "set cutoff frequency ratio" , OFFSET(cutoff) , AV_OPT_TYPE_DOUBLE,{.dbl=0. }, 0 , 1 , PARAM }, + +{"resampler" , "set resampling Engine" , OFFSET(engine) , AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_ENGINE_NB-1, PARAM, "resampler"}, +{"swr" , "select SW Resampler" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_ENGINE_SWR }, INT_MIN, INT_MAX , PARAM, "resampler"}, +{"soxr" , "select SoX Resampler" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_ENGINE_SOXR }, INT_MIN, INT_MAX , PARAM, "resampler"}, +{"precision" , "set soxr resampling precision (in bits)" + , OFFSET(precision) , AV_OPT_TYPE_DOUBLE,{.dbl=20.0 }, 15.0 , 33.0 , PARAM }, +{"cheby" , "enable soxr Chebyshev passband & higher-precision irrational ratio approximation" + , OFFSET(cheby) , AV_OPT_TYPE_INT , {.i64=0 }, 0 , 1 , PARAM }, +{"min_comp" , "set minimum difference between timestamps and audio data (in seconds) below which no timestamp compensation of either kind is applied" + , OFFSET(min_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=FLT_MAX }, 0 , FLT_MAX , PARAM }, +{"min_hard_comp" , "set minimum difference between timestamps and audio data (in seconds) to trigger padding/trimming the data." + , OFFSET(min_hard_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=0.1 }, 0 , INT_MAX , PARAM }, +{"comp_duration" , "set duration (in seconds) over which data is stretched/squeezed to make it match the timestamps." + , OFFSET(soft_compensation_duration),AV_OPT_TYPE_FLOAT ,{.dbl=1 }, 0 , INT_MAX , PARAM }, +{"max_soft_comp" , "set maximum factor by which data is stretched/squeezed to make it match the timestamps." + , OFFSET(max_soft_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=0 }, INT_MIN, INT_MAX , PARAM }, +{"async" , "simplified 1 parameter audio timestamp matching, 0(disabled), 1(filling and trimming), >1(maximum stretch/squeeze in samples per second)" + , OFFSET(async) , AV_OPT_TYPE_FLOAT ,{.dbl=0 }, INT_MIN, INT_MAX , PARAM }, +{"first_pts" , "Assume the first pts should be this value (in samples)." + , OFFSET(firstpts_in_samples), AV_OPT_TYPE_INT64 ,{.i64=AV_NOPTS_VALUE }, INT64_MIN,INT64_MAX, PARAM }, + +{ "matrix_encoding" , "set matrixed stereo encoding" , OFFSET(matrix_encoding), AV_OPT_TYPE_INT ,{.i64 = AV_MATRIX_ENCODING_NONE}, AV_MATRIX_ENCODING_NONE, AV_MATRIX_ENCODING_NB-1, PARAM, "matrix_encoding" }, + { "none", "select none", 0, AV_OPT_TYPE_CONST, { .i64 = AV_MATRIX_ENCODING_NONE }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" }, + { "dolby", "select Dolby", 0, AV_OPT_TYPE_CONST, { .i64 = AV_MATRIX_ENCODING_DOLBY }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" }, + { "dplii", "select Dolby Pro Logic II", 0, AV_OPT_TYPE_CONST, { .i64 = AV_MATRIX_ENCODING_DPLII }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" }, + +{ "filter_type" , "select swr filter type" , OFFSET(filter_type) , AV_OPT_TYPE_INT , { .i64 = SWR_FILTER_TYPE_KAISER }, SWR_FILTER_TYPE_CUBIC, SWR_FILTER_TYPE_KAISER, PARAM, "filter_type" }, + { "cubic" , "select cubic" , 0 , AV_OPT_TYPE_CONST, { .i64 = SWR_FILTER_TYPE_CUBIC }, INT_MIN, INT_MAX, PARAM, "filter_type" }, + { "blackman_nuttall", "select Blackman Nuttall Windowed Sinc", 0 , AV_OPT_TYPE_CONST, { .i64 = SWR_FILTER_TYPE_BLACKMAN_NUTTALL }, INT_MIN, INT_MAX, PARAM, "filter_type" }, + { "kaiser" , "select Kaiser Windowed Sinc" , 0 , AV_OPT_TYPE_CONST, { .i64 = SWR_FILTER_TYPE_KAISER }, INT_MIN, INT_MAX, PARAM, "filter_type" }, + +{ "kaiser_beta" , "set swr Kaiser Window Beta" , OFFSET(kaiser_beta) , AV_OPT_TYPE_INT , {.i64=9 }, 2 , 16 , PARAM }, + +{ "output_sample_bits" , "set swr number of output sample bits", OFFSET(dither.output_sample_bits), AV_OPT_TYPE_INT , {.i64=0 }, 0 , 64 , PARAM }, +{0} +}; + +static const char* context_to_name(void* ptr) { + return "SWR"; +} + +static const AVClass av_class = { + .class_name = "SWResampler", + .item_name = context_to_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, + .log_level_offset_offset = OFFSET(log_level_offset), + .parent_log_context_offset = OFFSET(log_ctx), + .category = AV_CLASS_CATEGORY_SWRESAMPLER, +}; + +const AVClass *swr_get_class(void) +{ + return &av_class; +} + +av_cold struct SwrContext *swr_alloc(void){ + SwrContext *s= av_mallocz(sizeof(SwrContext)); + if(s){ + s->av_class= &av_class; + av_opt_set_defaults(s); + } + return s; +} diff --git a/libswresample/resample.c b/libswresample/resample.c index 65fd817be..2a8aa7e2d 100644 --- a/libswresample/resample.c +++ b/libswresample/resample.c @@ -25,32 +25,8 @@ * @author Michael Niedermayer */ -#include "libavutil/log.h" #include "libavutil/avassert.h" -#include "swresample_internal.h" - - -typedef struct ResampleContext { - const AVClass *av_class; - uint8_t *filter_bank; - int filter_length; - int filter_alloc; - int ideal_dst_incr; - int dst_incr; - int index; - int frac; - int src_incr; - int compensation_distance; - int phase_shift; - int phase_mask; - int linear; - enum SwrFilterType filter_type; - int kaiser_beta; - double factor; - enum AVSampleFormat format; - int felem_size; - int filter_shift; -} ResampleContext; +#include "resample.h" /** * 0th order modified bessel function of the first kind. @@ -197,7 +173,8 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap static ResampleContext *resample_init(ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff0, enum AVSampleFormat format, enum SwrFilterType filter_type, int kaiser_beta, - double precision, int cheby){ + double precision, int cheby) +{ double cutoff = cutoff0? cutoff0 : 0.97; double factor= FFMIN(out_rate * cutoff / in_rate, 1.0); int phase_count= 1<compensation_distance= 0; if(!av_reduce(&c->src_incr, &c->dst_incr, out_rate, in_rate * (int64_t)phase_count, INT32_MAX/2)) goto error; - c->ideal_dst_incr= c->dst_incr; + c->ideal_dst_incr = c->dst_incr; + c->dst_incr_div = c->dst_incr / c->src_incr; + c->dst_incr_mod = c->dst_incr % c->src_incr; c->index= -phase_count*((c->filter_length-1)/2); c->frac= 0; + swri_resample_dsp_init(c); + return c; error: av_freep(&c->filter_bank); @@ -279,65 +260,78 @@ static int set_compensation(ResampleContext *c, int sample_delta, int compensati c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance; else c->dst_incr = c->ideal_dst_incr; + + c->dst_incr_div = c->dst_incr / c->src_incr; + c->dst_incr_mod = c->dst_incr % c->src_incr; + return 0; } -#define TEMPLATE_RESAMPLE_S16 -#include "resample_template.c" -#undef TEMPLATE_RESAMPLE_S16 +static int swri_resample(ResampleContext *c, + uint8_t *dst, const uint8_t *src, int *consumed, + int src_size, int dst_size, int update_ctx) +{ + if (c->filter_length == 1 && c->phase_shift == 0) { + int index= c->index; + int frac= c->frac; + int64_t index2= (1LL<<32)*c->frac/c->src_incr + (1LL<<32)*index; + int64_t incr= (1LL<<32) * c->dst_incr / c->src_incr; + int new_size = (src_size * (int64_t)c->src_incr - frac + c->dst_incr - 1) / c->dst_incr; -#define TEMPLATE_RESAMPLE_S32 -#include "resample_template.c" -#undef TEMPLATE_RESAMPLE_S32 + dst_size= FFMIN(dst_size, new_size); + c->dsp.resample_one(dst, src, dst_size, index2, incr); -#define TEMPLATE_RESAMPLE_FLT -#include "resample_template.c" -#undef TEMPLATE_RESAMPLE_FLT + index += dst_size * c->dst_incr_div; + index += (frac + dst_size * (int64_t)c->dst_incr_mod) / c->src_incr; + av_assert2(index >= 0); + *consumed= index; + if (update_ctx) { + c->frac = (frac + dst_size * (int64_t)c->dst_incr_mod) % c->src_incr; + c->index = 0; + } + } else { + int64_t end_index = (1LL + src_size - c->filter_length) << c->phase_shift; + int64_t delta_frac = (end_index - c->index) * c->src_incr - c->frac; + int delta_n = (delta_frac + c->dst_incr - 1) / c->dst_incr; -#define TEMPLATE_RESAMPLE_DBL -#include "resample_template.c" -#undef TEMPLATE_RESAMPLE_DBL + dst_size = FFMIN(dst_size, delta_n); + if (dst_size > 0) { + *consumed = c->dsp.resample(c, dst, src, dst_size, update_ctx); + } else { + *consumed = 0; + } + } -// XXX FIXME the whole C loop should be written in asm so this x86 specific code here isnt needed -#if HAVE_MMXEXT_INLINE - -#include "x86/resample_mmx.h" - -#define TEMPLATE_RESAMPLE_S16_MMX2 -#include "resample_template.c" -#undef TEMPLATE_RESAMPLE_S16_MMX2 - -#if HAVE_SSSE3_INLINE -#define TEMPLATE_RESAMPLE_S16_SSSE3 -#include "resample_template.c" -#undef TEMPLATE_RESAMPLE_S16_SSSE3 -#endif - -#endif // HAVE_MMXEXT_INLINE + return dst_size; +} static int multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed){ int i, ret= -1; int av_unused mm_flags = av_get_cpu_flags(); - int need_emms= 0; + int need_emms = c->format == AV_SAMPLE_FMT_S16P && ARCH_X86_32 && + (mm_flags & (AV_CPU_FLAG_MMX2 | AV_CPU_FLAG_SSE2)) == AV_CPU_FLAG_MMX2; + int64_t max_src_size = (INT64_MAX >> (c->phase_shift+1)) / c->src_incr; + + if (c->compensation_distance) + dst_size = FFMIN(dst_size, c->compensation_distance); + src_size = FFMIN(src_size, max_src_size); for(i=0; ich_count; i++){ -#if HAVE_MMXEXT_INLINE -#if HAVE_SSSE3_INLINE - if(c->format == AV_SAMPLE_FMT_S16P && (mm_flags&AV_CPU_FLAG_SSSE3)) ret= swri_resample_int16_ssse3(c, (int16_t*)dst->ch[i], (const int16_t*)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); - else -#endif - if(c->format == AV_SAMPLE_FMT_S16P && (mm_flags&AV_CPU_FLAG_MMX2 )){ - ret= swri_resample_int16_mmx2 (c, (int16_t*)dst->ch[i], (const int16_t*)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); - need_emms= 1; - } else -#endif - if(c->format == AV_SAMPLE_FMT_S16P) ret= swri_resample_int16(c, (int16_t*)dst->ch[i], (const int16_t*)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); - else if(c->format == AV_SAMPLE_FMT_S32P) ret= swri_resample_int32(c, (int32_t*)dst->ch[i], (const int32_t*)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); - else if(c->format == AV_SAMPLE_FMT_FLTP) ret= swri_resample_float(c, (float *)dst->ch[i], (const float *)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); - else if(c->format == AV_SAMPLE_FMT_DBLP) ret= swri_resample_double(c,(double *)dst->ch[i], (const double *)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); + ret= swri_resample(c, dst->ch[i], src->ch[i], + consumed, src_size, dst_size, i+1==dst->ch_count); } if(need_emms) emms_c(); + + if (c->compensation_distance) { + c->compensation_distance -= ret; + if (!c->compensation_distance) { + c->dst_incr = c->ideal_dst_incr; + c->dst_incr_div = c->dst_incr / c->src_incr; + c->dst_incr_mod = c->dst_incr % c->src_incr; + } + } + return ret; } @@ -367,6 +361,51 @@ static int resample_flush(struct SwrContext *s) { return 0; } +// in fact the whole handle multiple ridiculously small buffers might need more thinking... +static int invert_initial_buffer(ResampleContext *c, AudioData *dst, const AudioData *src, + int in_count, int *out_idx, int *out_sz) +{ + int n, ch, num = FFMIN(in_count + *out_sz, c->filter_length + 1), res; + + if (c->index >= 0) + return 0; + + if ((res = swri_realloc_audio(dst, c->filter_length * 2 + 1)) < 0) + return res; + + // copy + for (n = *out_sz; n < num; n++) { + for (ch = 0; ch < src->ch_count; ch++) { + memcpy(dst->ch[ch] + ((c->filter_length + n) * c->felem_size), + src->ch[ch] + ((n - *out_sz) * c->felem_size), c->felem_size); + } + } + + // if not enough data is in, return and wait for more + if (num < c->filter_length + 1) { + *out_sz = num; + *out_idx = c->filter_length; + return INT_MAX; + } + + // else invert + for (n = 1; n <= c->filter_length; n++) { + for (ch = 0; ch < src->ch_count; ch++) { + memcpy(dst->ch[ch] + ((c->filter_length - n) * c->felem_size), + dst->ch[ch] + ((c->filter_length + n) * c->felem_size), + c->felem_size); + } + } + + res = num - *out_sz; + *out_idx = c->filter_length + (c->index >> c->phase_shift); + *out_sz = 1 + c->filter_length * 2 - *out_idx; + c->index &= c->phase_mask; + av_assert1(res > 0); + + return res; +} + struct Resampler const swri_resampler={ resample_init, resample_free, @@ -374,4 +413,5 @@ struct Resampler const swri_resampler={ resample_flush, set_compensation, get_delay, + invert_initial_buffer, }; diff --git a/libswresample/resample.h b/libswresample/resample.h new file mode 100644 index 000000000..99a89b794 --- /dev/null +++ b/libswresample/resample.h @@ -0,0 +1,64 @@ +/* + * audio resampling + * Copyright (c) 2004-2012 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_RESAMPLE_H +#define SWRESAMPLE_RESAMPLE_H + +#include "libavutil/log.h" +#include "libavutil/samplefmt.h" + +#include "swresample_internal.h" + +typedef struct ResampleContext { + const AVClass *av_class; + uint8_t *filter_bank; + int filter_length; + int filter_alloc; + int ideal_dst_incr; + int dst_incr; + int dst_incr_div; + int dst_incr_mod; + int index; + int frac; + int src_incr; + int compensation_distance; + int phase_shift; + int phase_mask; + int linear; + enum SwrFilterType filter_type; + int kaiser_beta; + double factor; + enum AVSampleFormat format; + int felem_size; + int filter_shift; + + struct { + void (*resample_one)(void *dst, const void *src, + int n, int64_t index, int64_t incr); + int (*resample)(struct ResampleContext *c, void *dst, + const void *src, int n, int update_ctx); + } dsp; +} ResampleContext; + +void swri_resample_dsp_init(ResampleContext *c); +void swri_resample_dsp_x86_init(ResampleContext *c); + +#endif /* SWRESAMPLE_RESAMPLE_H */ diff --git a/libswresample/resample_dsp.c b/libswresample/resample_dsp.c new file mode 100644 index 000000000..a811b8b6f --- /dev/null +++ b/libswresample/resample_dsp.c @@ -0,0 +1,68 @@ +/* + * audio resampling + * Copyright (c) 2004-2012 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * audio resampling + * @author Michael Niedermayer + */ + +#include "resample.h" + +#define TEMPLATE_RESAMPLE_S16 +#include "resample_template.c" +#undef TEMPLATE_RESAMPLE_S16 + +#define TEMPLATE_RESAMPLE_S32 +#include "resample_template.c" +#undef TEMPLATE_RESAMPLE_S32 + +#define TEMPLATE_RESAMPLE_FLT +#include "resample_template.c" +#undef TEMPLATE_RESAMPLE_FLT + +#define TEMPLATE_RESAMPLE_DBL +#include "resample_template.c" +#undef TEMPLATE_RESAMPLE_DBL + +void swri_resample_dsp_init(ResampleContext *c) +{ + switch(c->format){ + case AV_SAMPLE_FMT_S16P: + c->dsp.resample_one = resample_one_int16; + c->dsp.resample = c->linear ? resample_linear_int16 : resample_common_int16; + break; + case AV_SAMPLE_FMT_S32P: + c->dsp.resample_one = resample_one_int32; + c->dsp.resample = c->linear ? resample_linear_int32 : resample_common_int32; + break; + case AV_SAMPLE_FMT_FLTP: + c->dsp.resample_one = resample_one_float; + c->dsp.resample = c->linear ? resample_linear_float : resample_common_float; + break; + case AV_SAMPLE_FMT_DBLP: + c->dsp.resample_one = resample_one_double; + c->dsp.resample = c->linear ? resample_linear_double : resample_common_double; + break; + } + + if (ARCH_X86) swri_resample_dsp_x86_init(c); +} diff --git a/libswresample/resample_template.c b/libswresample/resample_template.c index 5bc12bcb7..069b19caf 100644 --- a/libswresample/resample_template.c +++ b/libswresample/resample_template.c @@ -26,39 +26,38 @@ */ #if defined(TEMPLATE_RESAMPLE_DBL) + # define RENAME(N) N ## _double # define FILTER_SHIFT 0 # define DELEM double # define FELEM double # define FELEM2 double -# define FELEML double # define OUT(d, v) d = v -#elif defined(TEMPLATE_RESAMPLE_FLT) +#elif defined(TEMPLATE_RESAMPLE_FLT) + # define RENAME(N) N ## _float # define FILTER_SHIFT 0 # define DELEM float # define FELEM float # define FELEM2 float -# define FELEML float # define OUT(d, v) d = v #elif defined(TEMPLATE_RESAMPLE_S32) + # define RENAME(N) N ## _int32 # define FILTER_SHIFT 30 # define DELEM int32_t # define FELEM int32_t # define FELEM2 int64_t -# define FELEML int64_t # define FELEM_MAX INT32_MAX # define FELEM_MIN INT32_MIN # define OUT(d, v) v = (v + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;\ d = (uint64_t)(v + 0x80000000) > 0xFFFFFFFF ? (v>>63) ^ 0x7FFFFFFF : v -#elif defined(TEMPLATE_RESAMPLE_S16) \ - || defined(TEMPLATE_RESAMPLE_S16_MMX2) \ - || defined(TEMPLATE_RESAMPLE_S16_SSSE3) +#elif defined(TEMPLATE_RESAMPLE_S16) +# define RENAME(N) N ## _int16 # define FILTER_SHIFT 15 # define DELEM int16_t # define FELEM int16_t @@ -69,137 +68,114 @@ # define OUT(d, v) v = (v + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;\ d = (unsigned)(v + 32768) > 65535 ? (v>>31) ^ 32767 : v -# if defined(TEMPLATE_RESAMPLE_S16) -# define RENAME(N) N ## _int16 -# elif defined(TEMPLATE_RESAMPLE_S16_MMX2) -# define COMMON_CORE COMMON_CORE_INT16_MMX2 -# define RENAME(N) N ## _int16_mmx2 -# elif defined(TEMPLATE_RESAMPLE_S16_SSSE3) -# define COMMON_CORE COMMON_CORE_INT16_SSSE3 -# define RENAME(N) N ## _int16_ssse3 -# endif - #endif -int RENAME(swri_resample)(ResampleContext *c, DELEM *dst, const DELEM *src, int *consumed, int src_size, int dst_size, int update_ctx){ - int dst_index, i; +static void RENAME(resample_one)(void *dest, const void *source, + int dst_size, int64_t index2, int64_t incr) +{ + DELEM *dst = dest; + const DELEM *src = source; + int dst_index; + + for (dst_index = 0; dst_index < dst_size; dst_index++) { + dst[dst_index] = src[index2 >> 32]; + index2 += incr; + } +} + +static int RENAME(resample_common)(ResampleContext *c, + void *dest, const void *source, + int n, int update_ctx) +{ + DELEM *dst = dest; + const DELEM *src = source; + int dst_index; int index= c->index; int frac= c->frac; - int dst_incr_frac= c->dst_incr % c->src_incr; - int dst_incr= c->dst_incr / c->src_incr; - int compensation_distance= c->compensation_distance; + int sample_index = index >> c->phase_shift; - av_assert1(c->filter_shift == FILTER_SHIFT); - av_assert1(c->felem_size == sizeof(FELEM)); + index &= c->phase_mask; + for (dst_index = 0; dst_index < n; dst_index++) { + FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index; - if(compensation_distance == 0 && c->filter_length == 1 && c->phase_shift==0){ - int64_t index2= ((int64_t)index)<<32; - int64_t incr= (1LL<<32) * c->dst_incr / c->src_incr; - dst_size= FFMIN(dst_size, (src_size-1-index) * (int64_t)c->src_incr / c->dst_incr); - - for(dst_index=0; dst_index < dst_size; dst_index++){ - dst[dst_index] = src[index2>>32]; - index2 += incr; + FELEM2 val=0; + int i; + for (i = 0; i < c->filter_length; i++) { + val += src[sample_index + i] * (FELEM2)filter[i]; } - index += dst_index * dst_incr; - index += (frac + dst_index * (int64_t)dst_incr_frac) / c->src_incr; - frac = (frac + dst_index * (int64_t)dst_incr_frac) % c->src_incr; - av_assert2(index >= 0); - *consumed= index >> c->phase_shift; + OUT(dst[dst_index], val); + + frac += c->dst_incr_mod; + index += c->dst_incr_div; + if (frac >= c->src_incr) { + frac -= c->src_incr; + index++; + } + sample_index += index >> c->phase_shift; index &= c->phase_mask; - }else if(compensation_distance == 0 && !c->linear && index >= 0){ - int sample_index = 0; - for(dst_index=0; dst_index < dst_size; dst_index++){ - FELEM *filter; - sample_index += index >> c->phase_shift; - index &= c->phase_mask; - filter= ((FELEM*)c->filter_bank) + c->filter_alloc*index; - - if(sample_index + c->filter_length > src_size){ - break; - }else{ -#ifdef COMMON_CORE - COMMON_CORE -#else - FELEM2 val=0; - for(i=0; ifilter_length; i++){ - val += src[sample_index + i] * (FELEM2)filter[i]; - } - OUT(dst[dst_index], val); -#endif - } - - frac += dst_incr_frac; - index += dst_incr; - if(frac >= c->src_incr){ - frac -= c->src_incr; - index++; - } - } - *consumed = sample_index; - }else{ - int sample_index = 0; - for(dst_index=0; dst_index < dst_size; dst_index++){ - FELEM *filter; - FELEM2 val=0; - - sample_index += index >> c->phase_shift; - index &= c->phase_mask; - filter = ((FELEM*)c->filter_bank) + c->filter_alloc*index; - - if(sample_index + c->filter_length > src_size || -sample_index >= src_size){ - break; - }else if(sample_index < 0){ - for(i=0; ifilter_length; i++) - val += src[FFABS(sample_index + i)] * (FELEM2)filter[i]; - }else if(c->linear){ - FELEM2 v2=0; - for(i=0; ifilter_length; i++){ - val += src[sample_index + i] * (FELEM2)filter[i]; - v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_alloc]; - } - val+=(v2-val)*(FELEML)frac / c->src_incr; - }else{ - for(i=0; ifilter_length; i++){ - val += src[sample_index + i] * (FELEM2)filter[i]; - } - } - - OUT(dst[dst_index], val); - - frac += dst_incr_frac; - index += dst_incr; - if(frac >= c->src_incr){ - frac -= c->src_incr; - index++; - } - - if(dst_index + 1 == compensation_distance){ - compensation_distance= 0; - dst_incr_frac= c->ideal_dst_incr % c->src_incr; - dst_incr= c->ideal_dst_incr / c->src_incr; - } - } - *consumed= FFMAX(sample_index, 0); - index += FFMIN(sample_index, 0) << c->phase_shift; - - if(compensation_distance){ - compensation_distance -= dst_index; - av_assert1(compensation_distance > 0); - } } if(update_ctx){ c->frac= frac; c->index= index; - c->dst_incr= dst_incr_frac + c->src_incr*dst_incr; - c->compensation_distance= compensation_distance; } - return dst_index; + return sample_index; +} + +static int RENAME(resample_linear)(ResampleContext *c, + void *dest, const void *source, + int n, int update_ctx) +{ + DELEM *dst = dest; + const DELEM *src = source; + int dst_index; + int index= c->index; + int frac= c->frac; + int sample_index = index >> c->phase_shift; +#if FILTER_SHIFT == 0 + double inv_src_incr = 1.0 / c->src_incr; +#endif + + index &= c->phase_mask; + for (dst_index = 0; dst_index < n; dst_index++) { + FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index; + FELEM2 val=0, v2 = 0; + + int i; + for (i = 0; i < c->filter_length; i++) { + val += src[sample_index + i] * (FELEM2)filter[i]; + v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_alloc]; + } +#ifdef FELEML + val += (v2 - val) * (FELEML) frac / c->src_incr; +#else +# if FILTER_SHIFT == 0 + val += (v2 - val) * inv_src_incr * frac; +# else + val += (v2 - val) / c->src_incr * frac; +# endif +#endif + OUT(dst[dst_index], val); + + frac += c->dst_incr_mod; + index += c->dst_incr_div; + if (frac >= c->src_incr) { + frac -= c->src_incr; + index++; + } + sample_index += index >> c->phase_shift; + index &= c->phase_mask; + } + + if(update_ctx){ + c->frac= frac; + c->index= index; + } + + return sample_index; } -#undef COMMON_CORE #undef RENAME #undef FILTER_SHIFT #undef DELEM diff --git a/libswresample/soxr_resample.c b/libswresample/soxr_resample.c index 4c000db0c..064451df4 100644 --- a/libswresample/soxr_resample.c +++ b/libswresample/soxr_resample.c @@ -87,7 +87,14 @@ static int64_t get_delay(struct SwrContext *s, int64_t base){ return (int64_t)(delay_s * base + .5); } +static int invert_initial_buffer(struct ResampleContext *c, AudioData *dst, const AudioData *src, + int in_count, int *out_idx, int *out_sz) +{ + return 0; +} + struct Resampler const soxr_resampler={ create, destroy, process, flush, NULL /* set_compensation */, get_delay, + invert_initial_buffer, }; diff --git a/libswresample/swresample-test.c b/libswresample/swresample-test.c index 379d38531..4987f5faf 100644 --- a/libswresample/swresample-test.c +++ b/libswresample/swresample-test.c @@ -164,7 +164,7 @@ static void audiogen(void *data, enum AVSampleFormat sample_fmt, a += M_PI * 1000.0 * 2.0 / sample_rate; } - /* 1 second of varing frequency between 100 and 10000 Hz */ + /* 1 second of varying frequency between 100 and 10000 Hz */ a = 0; for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) { v = sin(a) * 0.30; diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 54e06e1d0..91baca62d 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -26,126 +26,8 @@ #include -#define C30DB M_SQRT2 -#define C15DB 1.189207115 -#define C__0DB 1.0 -#define C_15DB 0.840896415 -#define C_30DB M_SQRT1_2 -#define C_45DB 0.594603558 -#define C_60DB 0.5 - #define ALIGN 32 -//TODO split options array out? -#define OFFSET(x) offsetof(SwrContext,x) -#define PARAM AV_OPT_FLAG_AUDIO_PARAM - -static const AVOption options[]={ -{"ich" , "set input channel count" , OFFSET( in.ch_count ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"in_channel_count" , "set input channel count" , OFFSET( in.ch_count ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"och" , "set output channel count" , OFFSET(out.ch_count ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"out_channel_count" , "set output channel count" , OFFSET(out.ch_count ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"uch" , "set used channel count" , OFFSET(used_ch_count ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"used_channel_count" , "set used channel count" , OFFSET(used_ch_count ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"isr" , "set input sample rate" , OFFSET( in_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, -{"in_sample_rate" , "set input sample rate" , OFFSET( in_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, -{"osr" , "set output sample rate" , OFFSET(out_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, -{"out_sample_rate" , "set output sample rate" , OFFSET(out_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, -{"isf" , "set input sample format" , OFFSET( in_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, -{"in_sample_fmt" , "set input sample format" , OFFSET( in_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, -{"osf" , "set output sample format" , OFFSET(out_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, -{"out_sample_fmt" , "set output sample format" , OFFSET(out_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, -{"tsf" , "set internal sample format" , OFFSET(int_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, -{"internal_sample_fmt" , "set internal sample format" , OFFSET(int_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, -{"icl" , "set input channel layout" , OFFSET( in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, 0 , INT64_MAX , PARAM, "channel_layout"}, -{"in_channel_layout" , "set input channel layout" , OFFSET( in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, 0 , INT64_MAX , PARAM, "channel_layout"}, -{"ocl" , "set output channel layout" , OFFSET(out_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, 0 , INT64_MAX , PARAM, "channel_layout"}, -{"out_channel_layout" , "set output channel layout" , OFFSET(out_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, 0 , INT64_MAX , PARAM, "channel_layout"}, -{"clev" , "set center mix level" , OFFSET(clev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, -{"center_mix_level" , "set center mix level" , OFFSET(clev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, -{"slev" , "set surround mix level" , OFFSET(slev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, -{"surround_mix_level" , "set surround mix Level" , OFFSET(slev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, -{"lfe_mix_level" , "set LFE mix level" , OFFSET(lfe_mix_level ), AV_OPT_TYPE_FLOAT, {.dbl=0 }, -32 , 32 , PARAM}, -{"rmvol" , "set rematrix volume" , OFFSET(rematrix_volume), AV_OPT_TYPE_FLOAT, {.dbl=1.0 }, -1000 , 1000 , PARAM}, -{"rematrix_volume" , "set rematrix volume" , OFFSET(rematrix_volume), AV_OPT_TYPE_FLOAT, {.dbl=1.0 }, -1000 , 1000 , PARAM}, -{"rematrix_maxval" , "set rematrix maxval" , OFFSET(rematrix_maxval), AV_OPT_TYPE_FLOAT, {.dbl=0.0 }, 0 , 1000 , PARAM}, - -{"flags" , "set flags" , OFFSET(flags ), AV_OPT_TYPE_FLAGS, {.i64=0 }, 0 , UINT_MAX , PARAM, "flags"}, -{"swr_flags" , "set flags" , OFFSET(flags ), AV_OPT_TYPE_FLAGS, {.i64=0 }, 0 , UINT_MAX , PARAM, "flags"}, -{"res" , "force resampling" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_FLAG_RESAMPLE }, INT_MIN, INT_MAX , PARAM, "flags"}, - -{"dither_scale" , "set dither scale" , OFFSET(dither.scale ), AV_OPT_TYPE_FLOAT, {.dbl=1 }, 0 , INT_MAX , PARAM}, - -{"dither_method" , "set dither method" , OFFSET(dither.method ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_DITHER_NB-1, PARAM, "dither_method"}, -{"rectangular" , "select rectangular dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_RECTANGULAR}, INT_MIN, INT_MAX , PARAM, "dither_method"}, -{"triangular" , "select triangular dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_TRIANGULAR }, INT_MIN, INT_MAX , PARAM, "dither_method"}, -{"triangular_hp" , "select triangular dither with high pass" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_TRIANGULAR_HIGHPASS }, INT_MIN, INT_MAX, PARAM, "dither_method"}, -{"lipshitz" , "select lipshitz noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_LIPSHITZ}, INT_MIN, INT_MAX, PARAM, "dither_method"}, -{"shibata" , "select shibata noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_SHIBATA }, INT_MIN, INT_MAX, PARAM, "dither_method"}, -{"low_shibata" , "select low shibata noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_LOW_SHIBATA }, INT_MIN, INT_MAX, PARAM, "dither_method"}, -{"high_shibata" , "select high shibata noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_HIGH_SHIBATA }, INT_MIN, INT_MAX, PARAM, "dither_method"}, -{"f_weighted" , "select f-weighted noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_F_WEIGHTED }, INT_MIN, INT_MAX, PARAM, "dither_method"}, -{"modified_e_weighted" , "select modified-e-weighted noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_MODIFIED_E_WEIGHTED }, INT_MIN, INT_MAX, PARAM, "dither_method"}, -{"improved_e_weighted" , "select improved-e-weighted noise shaping dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_NS_IMPROVED_E_WEIGHTED }, INT_MIN, INT_MAX, PARAM, "dither_method"}, - -{"filter_size" , "set swr resampling filter size", OFFSET(filter_size) , AV_OPT_TYPE_INT , {.i64=32 }, 0 , INT_MAX , PARAM }, -{"phase_shift" , "set swr resampling phase shift", OFFSET(phase_shift) , AV_OPT_TYPE_INT , {.i64=10 }, 0 , 24 , PARAM }, -{"linear_interp" , "enable linear interpolation" , OFFSET(linear_interp) , AV_OPT_TYPE_INT , {.i64=0 }, 0 , 1 , PARAM }, -{"cutoff" , "set cutoff frequency ratio" , OFFSET(cutoff) , AV_OPT_TYPE_DOUBLE,{.dbl=0. }, 0 , 1 , PARAM }, - -/* duplicate option in order to work with avconv */ -{"resample_cutoff" , "set cutoff frequency ratio" , OFFSET(cutoff) , AV_OPT_TYPE_DOUBLE,{.dbl=0. }, 0 , 1 , PARAM }, - -{"resampler" , "set resampling Engine" , OFFSET(engine) , AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_ENGINE_NB-1, PARAM, "resampler"}, -{"swr" , "select SW Resampler" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_ENGINE_SWR }, INT_MIN, INT_MAX , PARAM, "resampler"}, -{"soxr" , "select SoX Resampler" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_ENGINE_SOXR }, INT_MIN, INT_MAX , PARAM, "resampler"}, -{"precision" , "set soxr resampling precision (in bits)" - , OFFSET(precision) , AV_OPT_TYPE_DOUBLE,{.dbl=20.0 }, 15.0 , 33.0 , PARAM }, -{"cheby" , "enable soxr Chebyshev passband & higher-precision irrational ratio approximation" - , OFFSET(cheby) , AV_OPT_TYPE_INT , {.i64=0 }, 0 , 1 , PARAM }, -{"min_comp" , "set minimum difference between timestamps and audio data (in seconds) below which no timestamp compensation of either kind is applied" - , OFFSET(min_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=FLT_MAX }, 0 , FLT_MAX , PARAM }, -{"min_hard_comp" , "set minimum difference between timestamps and audio data (in seconds) to trigger padding/trimming the data." - , OFFSET(min_hard_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=0.1 }, 0 , INT_MAX , PARAM }, -{"comp_duration" , "set duration (in seconds) over which data is stretched/squeezed to make it match the timestamps." - , OFFSET(soft_compensation_duration),AV_OPT_TYPE_FLOAT ,{.dbl=1 }, 0 , INT_MAX , PARAM }, -{"max_soft_comp" , "set maximum factor by which data is stretched/squeezed to make it match the timestamps." - , OFFSET(max_soft_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=0 }, INT_MIN, INT_MAX , PARAM }, -{"async" , "simplified 1 parameter audio timestamp matching, 0(disabled), 1(filling and trimming), >1(maximum stretch/squeeze in samples per second)" - , OFFSET(async) , AV_OPT_TYPE_FLOAT ,{.dbl=0 }, INT_MIN, INT_MAX , PARAM }, -{"first_pts" , "Assume the first pts should be this value (in samples)." - , OFFSET(firstpts_in_samples), AV_OPT_TYPE_INT64 ,{.i64=AV_NOPTS_VALUE }, INT64_MIN,INT64_MAX, PARAM }, - -{ "matrix_encoding" , "set matrixed stereo encoding" , OFFSET(matrix_encoding), AV_OPT_TYPE_INT ,{.i64 = AV_MATRIX_ENCODING_NONE}, AV_MATRIX_ENCODING_NONE, AV_MATRIX_ENCODING_NB-1, PARAM, "matrix_encoding" }, - { "none", "select none", 0, AV_OPT_TYPE_CONST, { .i64 = AV_MATRIX_ENCODING_NONE }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" }, - { "dolby", "select Dolby", 0, AV_OPT_TYPE_CONST, { .i64 = AV_MATRIX_ENCODING_DOLBY }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" }, - { "dplii", "select Dolby Pro Logic II", 0, AV_OPT_TYPE_CONST, { .i64 = AV_MATRIX_ENCODING_DPLII }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" }, - -{ "filter_type" , "select swr filter type" , OFFSET(filter_type) , AV_OPT_TYPE_INT , { .i64 = SWR_FILTER_TYPE_KAISER }, SWR_FILTER_TYPE_CUBIC, SWR_FILTER_TYPE_KAISER, PARAM, "filter_type" }, - { "cubic" , "select cubic" , 0 , AV_OPT_TYPE_CONST, { .i64 = SWR_FILTER_TYPE_CUBIC }, INT_MIN, INT_MAX, PARAM, "filter_type" }, - { "blackman_nuttall", "select Blackman Nuttall Windowed Sinc", 0 , AV_OPT_TYPE_CONST, { .i64 = SWR_FILTER_TYPE_BLACKMAN_NUTTALL }, INT_MIN, INT_MAX, PARAM, "filter_type" }, - { "kaiser" , "select Kaiser Windowed Sinc" , 0 , AV_OPT_TYPE_CONST, { .i64 = SWR_FILTER_TYPE_KAISER }, INT_MIN, INT_MAX, PARAM, "filter_type" }, - -{ "kaiser_beta" , "set swr Kaiser Window Beta" , OFFSET(kaiser_beta) , AV_OPT_TYPE_INT , {.i64=9 }, 2 , 16 , PARAM }, - -{ "output_sample_bits" , "set swr number of output sample bits", OFFSET(dither.output_sample_bits), AV_OPT_TYPE_INT , {.i64=0 }, 0 , 64 , PARAM }, -{0} -}; - -static const char* context_to_name(void* ptr) { - return "SWR"; -} - -static const AVClass av_class = { - .class_name = "SWResampler", - .item_name = context_to_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, - .log_level_offset_offset = OFFSET(log_level_offset), - .parent_log_context_offset = OFFSET(log_ctx), - .category = AV_CLASS_CATEGORY_SWRESAMPLER, -}; - unsigned swresample_version(void) { av_assert0(LIBSWRESAMPLE_VERSION_MICRO >= 100); @@ -170,20 +52,6 @@ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map){ return 0; } -const AVClass *swr_get_class(void) -{ - return &av_class; -} - -av_cold struct SwrContext *swr_alloc(void){ - SwrContext *s= av_mallocz(sizeof(SwrContext)); - if(s){ - s->av_class= &av_class; - av_opt_set_defaults(s); - } - return s; -} - struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, @@ -251,6 +119,10 @@ av_cold void swr_free(SwrContext **ss){ av_freep(ss); } +av_cold void swr_close(SwrContext *s){ + clear_context(s); +} + av_cold int swr_init(struct SwrContext *s){ int ret; @@ -537,6 +409,12 @@ static int resample(SwrContext *s, AudioData *out_param, int out_count, tmp=out=*out_param; in = *in_param; + border = s->resampler->invert_initial_buffer(s->resample, &s->in_buffer, + &in, in_count, &s->in_buffer_index, &s->in_buffer_count); + if (border == INT_MAX) return 0; + else if (border < 0) return border; + else if (border) { buf_set(&in, &in, border); in_count -= border; s->resample_in_constraint = 0; } + do{ int ret, size, consumed; if(!s->resample_in_constraint && s->in_buffer_count){ diff --git a/libswresample/swresample.h b/libswresample/swresample.h index 4ba008e72..e4bbebae1 100644 --- a/libswresample/swresample.h +++ b/libswresample/swresample.h @@ -38,10 +38,16 @@ * allocated with swr_alloc() or swr_alloc_set_opts(). It is opaque, so all parameters * must be set with the @ref avoptions API. * + * The first thing you will need to do in order to use lswr is to allocate + * SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts(). If you + * are using the former, you must set options through the @ref avoptions API. + * The latter function provides the same feature, but it allows you to set some + * common options in the same statement. + * * For example the following code will setup conversion from planar float sample * format to interleaved signed 16-bit integer, downsampling from 48kHz to * 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing - * matrix): + * matrix). This is using the swr_alloc() function. * @code * SwrContext *swr = swr_alloc(); * av_opt_set_channel_layout(swr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0); @@ -52,10 +58,24 @@ * av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); * @endcode * + * The same job can be done using swr_alloc_set_opts() as well: + * @code + * SwrContext *swr = swr_alloc_set_opts(NULL, // we're allocating a new context + * AV_CH_LAYOUT_STEREO, // out_ch_layout + * AV_SAMPLE_FMT_S16, // out_sample_fmt + * 44100, // out_sample_rate + * AV_CH_LAYOUT_5POINT1, // in_ch_layout + * AV_SAMPLE_FMT_FLTP, // in_sample_fmt + * 48000, // in_sample_rate + * 0, // log_offset + * NULL); // log_ctx + * @endcode + * * Once all values have been set, it must be initialized with swr_init(). If * you need to change the conversion parameters, you can change the parameters - * as described above, or by using swr_alloc_set_opts(), then call swr_init() - * again. + * using @ref AVOptions, as described above in the first example; or by using + * swr_alloc_set_opts(), but with the first argument the allocated context. + * You must then call swr_init() again. * * The conversion itself is done by repeatedly calling swr_convert(). * Note that the samples may get buffered in swr if you provide insufficient @@ -65,6 +85,10 @@ * At the end of conversion the resampling buffer can be flushed by calling * swr_convert() with NULL in and 0 in_count. * + * The samples used in the conversion process can be managed with the libavutil + * @ref lavu_sampmanip "samples manipulation" API, including av_samples_alloc() + * function used in the following example. + * * The delay between input and output, can at any time be found by using * swr_get_delay(). * @@ -89,6 +113,9 @@ * * When the conversion is finished, the conversion * context and everything associated with it must be freed with swr_free(). + * A swr_close() function is also available, but it exists mainly for + * compatibility with libavresample, and is not required to be called. + * * There will be no memory leak if the data is not completely flushed before * swr_free(). */ @@ -102,10 +129,18 @@ #define SWR_CH_MAX 32 ///< Maximum number of channels #endif +/** + * @name Option constants + * These constants are used for the @ref avoptions interface for lswr. + * @{ + * + */ + #define SWR_FLAG_RESAMPLE 1 ///< Force resampling even if equal sample rate //TODO use int resample ? //long term TODO can we enable this dynamically? +/** Dithering algorithms */ enum SwrDitherType { SWR_DITHER_NONE = 0, SWR_DITHER_RECTANGULAR, @@ -137,16 +172,32 @@ enum SwrFilterType { SWR_FILTER_TYPE_KAISER, /**< Kaiser Windowed Sinc */ }; +/** + * @} + */ + +/** + * The libswresample context. Unlike libavcodec and libavformat, this structure + * is opaque. This means that if you would like to set options, you must use + * the @ref avoptions API and cannot directly set values to members of the + * structure. + */ typedef struct SwrContext SwrContext; /** - * Get the AVClass for swrContext. It can be used in combination with + * Get the AVClass for SwrContext. It can be used in combination with * AV_OPT_SEARCH_FAKE_OBJ for examining options. * * @see av_opt_find(). + * @return the AVClass of SwrContext */ const AVClass *swr_get_class(void); +/** + * @name SwrContext constructor functions + * @{ + */ + /** * Allocate SwrContext. * @@ -161,6 +212,7 @@ struct SwrContext *swr_alloc(void); /** * Initialize context after user parameters have been set. * + * @param[in,out] s Swr context to initialize * @return AVERROR error code in case of failure. */ int swr_init(struct SwrContext *s); @@ -168,6 +220,8 @@ int swr_init(struct SwrContext *s); /** * Check whether an swr context has been initialized or not. * + * @param[in] s Swr context to check + * @see swr_init() * @return positive if it has been initialized, 0 if not initialized */ int swr_is_initialized(struct SwrContext *s); @@ -179,7 +233,7 @@ int swr_is_initialized(struct SwrContext *s); * other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters * on the allocated context. * - * @param s Swr context, can be NULL + * @param s existing Swr context if available, or NULL if not * @param out_ch_layout output channel layout (AV_CH_LAYOUT_*) * @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*). * @param out_sample_rate output sample rate (frequency in Hz) @@ -197,20 +251,47 @@ struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx); +/** + * @} + * + * @name SwrContext destructor functions + * @{ + */ + /** * Free the given SwrContext and set the pointer to NULL. + * + * @param[in] s a pointer to a pointer to Swr context */ void swr_free(struct SwrContext **s); /** - * Convert audio. + * Closes the context so that swr_is_initialized() returns 0. + * + * The context can be brought back to life by running swr_init(), + * swr_init() can also be used without swr_close(). + * This function is mainly provided for simplifying the usecase + * where one tries to support libavresample and libswresample. + * + * @param[in,out] s Swr context to be closed + */ +void swr_close(struct SwrContext *s); + +/** + * @} + * + * @name Core conversion functions + * @{ + */ + +/** Convert audio. * * in and in_count can be set to 0 to flush the last few samples out at the * end. * * If more input is provided than output space then the input will be buffered. * You can avoid this buffering by providing more output space than input. - * Convertion will run directly without copying whenever possible. + * Conversion will run directly without copying whenever possible. * * @param s allocated Swr context, with parameters set * @param out output buffers, only the first one need be set in case of packed audio @@ -228,28 +309,54 @@ int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, * timestamps are in 1/(in_sample_rate * out_sample_rate) units. * * @note There are 2 slightly differently behaving modes. - * First is when automatic timestamp compensation is not used, (min_compensation >= FLT_MAX) + * @li When automatic timestamp compensation is not used, (min_compensation >= FLT_MAX) * in this case timestamps will be passed through with delays compensated - * Second is when automatic timestamp compensation is used, (min_compensation < FLT_MAX) - * in this case the output timestamps will match output sample numbers + * @li When automatic timestamp compensation is used, (min_compensation < FLT_MAX) + * in this case the output timestamps will match output sample numbers. + * See ffmpeg-resampler(1) for the two modes of compensation. * - * @param pts timestamp for the next input sample, INT64_MIN if unknown + * @param s[in] initialized Swr context + * @param pts[in] timestamp for the next input sample, INT64_MIN if unknown + * @see swr_set_compensation(), swr_drop_output(), and swr_inject_silence() are + * function used internally for timestamp compensation. * @return the output timestamp for the next output sample */ int64_t swr_next_pts(struct SwrContext *s, int64_t pts); /** - * Activate resampling compensation. + * @} + * + * @name Low-level option setting functions + * These functons provide a means to set low-level options that is not possible + * with the AVOption API. + * @{ + */ + +/** + * Activate resampling compensation ("soft" compensation). This function is + * internally called when needed in swr_next_pts(). + * + * @param[in,out] s allocated Swr context. If it is not initialized, + * or SWR_FLAG_RESAMPLE is not set, swr_init() is + * called with the flag set. + * @param[in] sample_delta delta in PTS per sample + * @param[in] compensation_distance number of samples to compensate for + * @return >= 0 on success, AVERROR error codes if: + * @li @c s is NULL, + * @li @c compensation_distance is less than 0, + * @li @c compensation_distance is 0 but sample_delta is not, + * @li compensation unsupported by resampler, or + * @li swr_init() fails when called. */ int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance); /** * Set a customized input channel mapping. * - * @param s allocated Swr context, not yet initialized - * @param channel_map customized input channel mapping (array of channel - * indexes, -1 for a muted channel) - * @return AVERROR error code in case of failure. + * @param[in,out] s allocated Swr context, not yet initialized + * @param[in] channel_map customized input channel mapping (array of channel + * indexes, -1 for a muted channel) + * @return >= 0 on success, or AVERROR error code in case of failure. */ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); @@ -260,17 +367,40 @@ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); * @param matrix remix coefficients; matrix[i + stride * o] is * the weight of input channel i in output channel o * @param stride offset between lines of the matrix - * @return AVERROR error code in case of failure. + * @return >= 0 on success, or AVERROR error code in case of failure. */ int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride); +/** + * @} + * + * @name Sample handling functions + * @{ + */ + /** * Drops the specified number of output samples. + * + * This function, along with swr_inject_silence(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure */ int swr_drop_output(struct SwrContext *s, int count); /** * Injects the specified number of silence samples. + * + * This function, along with swr_drop_output(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure */ int swr_inject_silence(struct SwrContext *s, int count); @@ -286,32 +416,53 @@ int swr_inject_silence(struct SwrContext *s, int count); * for upsampling and the input sample rate. * * @param s swr context - * @param base timebase in which the returned delay will be - * if its set to 1 the returned delay is in seconds - * if its set to 1000 the returned delay is in milli seconds - * if its set to the input sample rate then the returned delay is in input samples - * if its set to the output sample rate then the returned delay is in output samples - * an exact rounding free delay can be found by using LCM(in_sample_rate, out_sample_rate) - * @returns the delay in 1/base units. + * @param base timebase in which the returned delay will be: + * @li if it's set to 1 the returned delay is in seconds + * @li if it's set to 1000 the returned delay is in milliseconds + * @li if it's set to the input sample rate then the returned + * delay is in input samples + * @li if it's set to the output sample rate then the returned + * delay is in output samples + * @li if it's the least common multiple of in_sample_rate and + * out_sample_rate then an exact rounding-free delay will be + * returned + * @returns the delay in 1 / @c base units. */ int64_t swr_get_delay(struct SwrContext *s, int64_t base); /** - * Return the LIBSWRESAMPLE_VERSION_INT constant. + * @} + * + * @name Configuration accessors + * @{ + */ + +/** + * Return the @ref LIBSWRESAMPLE_VERSION_INT constant. + * + * This is useful to check if the build-time libswresample has the same version + * as the run-time one. + * + * @returns the unsigned int-typed version */ unsigned swresample_version(void); /** * Return the swr build-time configuration. + * + * @returns the build-time @c ./configure flags */ const char *swresample_configuration(void); /** * Return the swr license. + * + * @returns the license of libswresample, determined at build-time */ const char *swresample_license(void); /** + * @} * @} */ diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h index ab19f212f..be4b321f7 100644 --- a/libswresample/swresample_internal.h +++ b/libswresample/swresample_internal.h @@ -62,7 +62,7 @@ struct DitherContext { float ns_coeffs[NS_TAPS]; ///< Noise shaping filter coefficients float ns_errors[SWR_CH_MAX][2*NS_TAPS]; AudioData noise; ///< noise used for dithering - AudioData temp; ///< temporary storage when writing into the input buffer isnt possible + AudioData temp; ///< temporary storage when writing into the input buffer isn't possible int output_sample_bits; ///< the number of used output bits, needed to scale dither correctly }; @@ -157,6 +157,7 @@ typedef int (* multiple_resample_func)(struct ResampleContext *c, AudioData typedef int (* resample_flush_func)(struct SwrContext *c); typedef int (* set_compensation_func)(struct ResampleContext *c, int sample_delta, int compensation_distance); typedef int64_t (* get_delay_func)(struct SwrContext *s, int64_t base); +typedef int (* invert_initial_buffer_func)(struct ResampleContext *c, AudioData *dst, const AudioData *src, int src_size, int *dst_idx, int *dst_count); struct Resampler { resample_init_func init; @@ -165,15 +166,12 @@ struct Resampler { resample_flush_func flush; set_compensation_func set_compensation; get_delay_func get_delay; + invert_initial_buffer_func invert_initial_buffer; }; extern struct Resampler const swri_resampler; int swri_realloc_audio(AudioData *a, int count); -int swri_resample_int16(struct ResampleContext *c, int16_t *dst, const int16_t *src, int *consumed, int src_size, int dst_size, int update_ctx); -int swri_resample_int32(struct ResampleContext *c, int32_t *dst, const int32_t *src, int *consumed, int src_size, int dst_size, int update_ctx); -int swri_resample_float(struct ResampleContext *c, float *dst, const float *src, int *consumed, int src_size, int dst_size, int update_ctx); -int swri_resample_double(struct ResampleContext *c,double *dst, const double *src, int *consumed, int src_size, int dst_size, int update_ctx); void swri_noise_shaping_int16 (SwrContext *s, AudioData *dsts, const AudioData *srcs, const AudioData *noises, int count); void swri_noise_shaping_int32 (SwrContext *s, AudioData *dsts, const AudioData *srcs, const AudioData *noises, int count); diff --git a/libswresample/version.h b/libswresample/version.h index 3a9287519..8ca9f5910 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBSWRESAMPLE_VERSION_MAJOR 0 -#define LIBSWRESAMPLE_VERSION_MINOR 18 +#define LIBSWRESAMPLE_VERSION_MINOR 19 #define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ diff --git a/libswresample/x86/Makefile b/libswresample/x86/Makefile index 1d1ab6ead..be44df56a 100644 --- a/libswresample/x86/Makefile +++ b/libswresample/x86/Makefile @@ -1,5 +1,9 @@ -YASM-OBJS += x86/swresample_x86.o\ - x86/audio_convert.o\ +YASM-OBJS += x86/audio_convert.o\ x86/rematrix.o\ + x86/resample.o\ + +OBJS += x86/audio_convert_init.o\ + x86/rematrix_init.o\ + x86/resample_init.o\ OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o diff --git a/libswresample/x86/swresample_x86.c b/libswresample/x86/audio_convert_init.c similarity index 74% rename from libswresample/x86/swresample_x86.c rename to libswresample/x86/audio_convert_init.c index 7483ba0be..a26cdf6ea 100644 --- a/libswresample/x86/swresample_x86.c +++ b/libswresample/x86/audio_convert_init.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/x86/cpu.h" #include "libswresample/swresample_internal.h" #include "libswresample/audioconvert.h" @@ -41,24 +42,24 @@ av_cold void swri_audio_convert_init_x86(struct AudioConvert *ac, //FIXME add memcpy case #define MULTI_CAPS_FUNC(flag, cap) \ - if (mm_flags & flag) {\ + if (EXTERNAL_##flag(mm_flags)) {\ if( out_fmt == AV_SAMPLE_FMT_S32 && in_fmt == AV_SAMPLE_FMT_S16 || out_fmt == AV_SAMPLE_FMT_S32P && in_fmt == AV_SAMPLE_FMT_S16P)\ ac->simd_f = ff_int16_to_int32_a_ ## cap;\ if( out_fmt == AV_SAMPLE_FMT_S16 && in_fmt == AV_SAMPLE_FMT_S32 || out_fmt == AV_SAMPLE_FMT_S16P && in_fmt == AV_SAMPLE_FMT_S32P)\ ac->simd_f = ff_int32_to_int16_a_ ## cap;\ } -MULTI_CAPS_FUNC(AV_CPU_FLAG_MMX, mmx) -MULTI_CAPS_FUNC(AV_CPU_FLAG_SSE2, sse2) +MULTI_CAPS_FUNC(MMX, mmx) +MULTI_CAPS_FUNC(SSE2, sse2) - if(mm_flags & AV_CPU_FLAG_MMX) { + if(EXTERNAL_MMX(mm_flags)) { if(channels == 6) { if( out_fmt == AV_SAMPLE_FMT_FLT && in_fmt == AV_SAMPLE_FMT_FLTP || out_fmt == AV_SAMPLE_FMT_S32 && in_fmt == AV_SAMPLE_FMT_S32P) ac->simd_f = ff_pack_6ch_float_to_float_a_mmx; } } - if(mm_flags & AV_CPU_FLAG_SSE2) { + if(EXTERNAL_SSE2(mm_flags)) { if( out_fmt == AV_SAMPLE_FMT_FLT && in_fmt == AV_SAMPLE_FMT_S32 || out_fmt == AV_SAMPLE_FMT_FLTP && in_fmt == AV_SAMPLE_FMT_S32P) ac->simd_f = ff_int32_to_float_a_sse2; if( out_fmt == AV_SAMPLE_FMT_FLT && in_fmt == AV_SAMPLE_FMT_S16 || out_fmt == AV_SAMPLE_FMT_FLTP && in_fmt == AV_SAMPLE_FMT_S16P) @@ -105,7 +106,7 @@ MULTI_CAPS_FUNC(AV_CPU_FLAG_SSE2, sse2) ac->simd_f = ff_unpack_2ch_float_to_int16_a_sse2; } } - if(mm_flags & AV_CPU_FLAG_SSSE3) { + if(EXTERNAL_SSSE3(mm_flags)) { if(channels == 2) { if( out_fmt == AV_SAMPLE_FMT_S16P && in_fmt == AV_SAMPLE_FMT_S16) ac->simd_f = ff_unpack_2ch_int16_to_int16_a_ssse3; @@ -115,7 +116,7 @@ MULTI_CAPS_FUNC(AV_CPU_FLAG_SSE2, sse2) ac->simd_f = ff_unpack_2ch_int16_to_float_a_ssse3; } } - if(mm_flags & AV_CPU_FLAG_SSE4) { + if(EXTERNAL_SSE4(mm_flags)) { if(channels == 6) { if( out_fmt == AV_SAMPLE_FMT_FLT && in_fmt == AV_SAMPLE_FMT_FLTP || out_fmt == AV_SAMPLE_FMT_S32 && in_fmt == AV_SAMPLE_FMT_S32P) ac->simd_f = ff_pack_6ch_float_to_float_a_sse4; @@ -125,7 +126,7 @@ MULTI_CAPS_FUNC(AV_CPU_FLAG_SSE2, sse2) ac->simd_f = ff_pack_6ch_float_to_int32_a_sse4; } } - if(HAVE_AVX_EXTERNAL && mm_flags & AV_CPU_FLAG_AVX) { + if(EXTERNAL_AVX(mm_flags)) { if( out_fmt == AV_SAMPLE_FMT_FLT && in_fmt == AV_SAMPLE_FMT_S32 || out_fmt == AV_SAMPLE_FMT_FLTP && in_fmt == AV_SAMPLE_FMT_S32P) ac->simd_f = ff_int32_to_float_a_avx; if(channels == 6) { @@ -138,63 +139,3 @@ MULTI_CAPS_FUNC(AV_CPU_FLAG_SSE2, sse2) } } } - -#define D(type, simd) \ -mix_1_1_func_type ff_mix_1_1_a_## type ## _ ## simd;\ -mix_2_1_func_type ff_mix_2_1_a_## type ## _ ## simd; - -D(float, sse) -D(float, avx) -D(int16, mmx) -D(int16, sse2) - - -av_cold void swri_rematrix_init_x86(struct SwrContext *s){ - int mm_flags = av_get_cpu_flags(); - int nb_in = av_get_channel_layout_nb_channels(s->in_ch_layout); - int nb_out = av_get_channel_layout_nb_channels(s->out_ch_layout); - int num = nb_in * nb_out; - int i,j; - - s->mix_1_1_simd = NULL; - s->mix_2_1_simd = NULL; - - if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){ - if(mm_flags & AV_CPU_FLAG_MMX) { - s->mix_1_1_simd = ff_mix_1_1_a_int16_mmx; - s->mix_2_1_simd = ff_mix_2_1_a_int16_mmx; - } - if(mm_flags & AV_CPU_FLAG_SSE2) { - s->mix_1_1_simd = ff_mix_1_1_a_int16_sse2; - s->mix_2_1_simd = ff_mix_2_1_a_int16_sse2; - } - s->native_simd_matrix = av_mallocz(2 * num * sizeof(int16_t)); - s->native_simd_one = av_mallocz(2 * sizeof(int16_t)); - for(i=0; inative_matrix)[i * nb_in + j])); - sh = FFMAX(av_log2(sh) - 14, 0); - for(j=0; jnative_simd_matrix)[2*(i * nb_in + j)+1] = 15 - sh; - ((int16_t*)s->native_simd_matrix)[2*(i * nb_in + j)] = - ((((int*)s->native_matrix)[i * nb_in + j]) + (1<>1)) >> sh; - } - } - ((int16_t*)s->native_simd_one)[1] = 14; - ((int16_t*)s->native_simd_one)[0] = 16384; - } else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){ - if(mm_flags & AV_CPU_FLAG_SSE) { - s->mix_1_1_simd = ff_mix_1_1_a_float_sse; - s->mix_2_1_simd = ff_mix_2_1_a_float_sse; - } - if(HAVE_AVX_EXTERNAL && mm_flags & AV_CPU_FLAG_AVX) { - s->mix_1_1_simd = ff_mix_1_1_a_float_avx; - s->mix_2_1_simd = ff_mix_2_1_a_float_avx; - } - s->native_simd_matrix = av_mallocz(num * sizeof(float)); - memcpy(s->native_simd_matrix, s->native_matrix, num * sizeof(float)); - s->native_simd_one = av_mallocz(sizeof(float)); - memcpy(s->native_simd_one, s->native_one, sizeof(float)); - } -} diff --git a/libswresample/x86/rematrix_init.c b/libswresample/x86/rematrix_init.c new file mode 100644 index 000000000..e2ee29189 --- /dev/null +++ b/libswresample/x86/rematrix_init.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012 Michael Niedermayer (michaelni@gmx.at) + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; 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 "libswresample/swresample_internal.h" + +#define D(type, simd) \ +mix_1_1_func_type ff_mix_1_1_a_## type ## _ ## simd;\ +mix_2_1_func_type ff_mix_2_1_a_## type ## _ ## simd; + +D(float, sse) +D(float, avx) +D(int16, mmx) +D(int16, sse2) + +av_cold void swri_rematrix_init_x86(struct SwrContext *s){ +#if HAVE_YASM + int mm_flags = av_get_cpu_flags(); + int nb_in = av_get_channel_layout_nb_channels(s->in_ch_layout); + int nb_out = av_get_channel_layout_nb_channels(s->out_ch_layout); + int num = nb_in * nb_out; + int i,j; + + s->mix_1_1_simd = NULL; + s->mix_2_1_simd = NULL; + + if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){ + if(EXTERNAL_MMX(mm_flags)) { + s->mix_1_1_simd = ff_mix_1_1_a_int16_mmx; + s->mix_2_1_simd = ff_mix_2_1_a_int16_mmx; + } + if(EXTERNAL_SSE2(mm_flags)) { + s->mix_1_1_simd = ff_mix_1_1_a_int16_sse2; + s->mix_2_1_simd = ff_mix_2_1_a_int16_sse2; + } + s->native_simd_matrix = av_mallocz(2 * num * sizeof(int16_t)); + s->native_simd_one = av_mallocz(2 * sizeof(int16_t)); + for(i=0; inative_matrix)[i * nb_in + j])); + sh = FFMAX(av_log2(sh) - 14, 0); + for(j=0; jnative_simd_matrix)[2*(i * nb_in + j)+1] = 15 - sh; + ((int16_t*)s->native_simd_matrix)[2*(i * nb_in + j)] = + ((((int*)s->native_matrix)[i * nb_in + j]) + (1<>1)) >> sh; + } + } + ((int16_t*)s->native_simd_one)[1] = 14; + ((int16_t*)s->native_simd_one)[0] = 16384; + } else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){ + if(EXTERNAL_SSE(mm_flags)) { + s->mix_1_1_simd = ff_mix_1_1_a_float_sse; + s->mix_2_1_simd = ff_mix_2_1_a_float_sse; + } + if(EXTERNAL_AVX(mm_flags)) { + s->mix_1_1_simd = ff_mix_1_1_a_float_avx; + s->mix_2_1_simd = ff_mix_2_1_a_float_avx; + } + s->native_simd_matrix = av_mallocz(num * sizeof(float)); + memcpy(s->native_simd_matrix, s->native_matrix, num * sizeof(float)); + s->native_simd_one = av_mallocz(sizeof(float)); + memcpy(s->native_simd_one, s->native_one, sizeof(float)); + } +#endif +} diff --git a/libswresample/x86/resample.asm b/libswresample/x86/resample.asm new file mode 100644 index 000000000..a57ff37bb --- /dev/null +++ b/libswresample/x86/resample.asm @@ -0,0 +1,600 @@ +;****************************************************************************** +;* Copyright (c) 2012 Michael Niedermayer +;* Copyright (c) 2014 James Almer gmail.com> +;* Copyright (c) 2014 Ronald S. Bultje +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +%if ARCH_X86_64 +%define pointer resq +%else +%define pointer resd +%endif + +struc ResampleContext + .av_class: pointer 1 + .filter_bank: pointer 1 + .filter_length: resd 1 + .filter_alloc: resd 1 + .ideal_dst_incr: resd 1 + .dst_incr: resd 1 + .dst_incr_div: resd 1 + .dst_incr_mod: resd 1 + .index: resd 1 + .frac: resd 1 + .src_incr: resd 1 + .compensation_distance: resd 1 + .phase_shift: resd 1 + .phase_mask: resd 1 + + ; there's a few more here but we only care about the first few +endstruc + +SECTION_RODATA + +pf_1: dd 1.0 +pdbl_1: dq 1.0 +pd_0x4000: dd 0x4000 + +SECTION .text + +%macro RESAMPLE_FNS 3-5 ; format [float or int16], bps, log2_bps, float op suffix [s or d], 1.0 constant +; int resample_common_$format(ResampleContext *ctx, $format *dst, +; const $format *src, int size, int update_ctx) +%if ARCH_X86_64 ; unix64 and win64 +cglobal resample_common_%1, 0, 15, 2, ctx, dst, src, phase_shift, index, frac, \ + dst_incr_mod, size, min_filter_count_x4, \ + min_filter_len_x4, dst_incr_div, src_incr, \ + phase_mask, dst_end, filter_bank + + ; use red-zone for variable storage +%define ctx_stackq [rsp-0x8] +%define src_stackq [rsp-0x10] +%if WIN64 +%define update_context_stackd r4m +%else ; unix64 +%define update_context_stackd [rsp-0x14] +%endif + + ; load as many variables in registers as possible; for the rest, store + ; on stack so that we have 'ctx' available as one extra register + mov sized, r3d + mov phase_maskd, [ctxq+ResampleContext.phase_mask] +%if UNIX64 + mov update_context_stackd, r4d +%endif + mov indexd, [ctxq+ResampleContext.index] + mov fracd, [ctxq+ResampleContext.frac] + mov dst_incr_modd, [ctxq+ResampleContext.dst_incr_mod] + mov filter_bankq, [ctxq+ResampleContext.filter_bank] + mov src_incrd, [ctxq+ResampleContext.src_incr] + mov ctx_stackq, ctxq + mov min_filter_len_x4d, [ctxq+ResampleContext.filter_length] + mov dst_incr_divd, [ctxq+ResampleContext.dst_incr_div] + shl min_filter_len_x4d, %3 + lea dst_endq, [dstq+sizeq*%2] + +%if UNIX64 + mov ecx, [ctxq+ResampleContext.phase_shift] + mov edi, [ctxq+ResampleContext.filter_alloc] + + DEFINE_ARGS filter_alloc, dst, src, phase_shift, index, frac, dst_incr_mod, \ + filter, min_filter_count_x4, min_filter_len_x4, dst_incr_div, \ + src_incr, phase_mask, dst_end, filter_bank +%elif WIN64 + mov R9d, [ctxq+ResampleContext.filter_alloc] + mov ecx, [ctxq+ResampleContext.phase_shift] + + DEFINE_ARGS phase_shift, dst, src, filter_alloc, index, frac, dst_incr_mod, \ + filter, min_filter_count_x4, min_filter_len_x4, dst_incr_div, \ + src_incr, phase_mask, dst_end, filter_bank +%endif + + neg min_filter_len_x4q + sub filter_bankq, min_filter_len_x4q + sub srcq, min_filter_len_x4q + mov src_stackq, srcq +%else ; x86-32 +cglobal resample_common_%1, 1, 7, 2, ctx, phase_shift, dst, frac, \ + index, min_filter_length_x4, filter_bank + + ; push temp variables to stack +%define ctx_stackq r0mp +%define src_stackq r2mp +%define update_context_stackd r4m + + mov dstq, r1mp + mov r3, r3mp + lea r3, [dstq+r3*%2] + PUSH dword [ctxq+ResampleContext.dst_incr_div] + PUSH dword [ctxq+ResampleContext.dst_incr_mod] + PUSH dword [ctxq+ResampleContext.filter_alloc] + PUSH r3 + PUSH dword [ctxq+ResampleContext.phase_mask] + PUSH dword [ctxq+ResampleContext.src_incr] + mov min_filter_length_x4d, [ctxq+ResampleContext.filter_length] + mov indexd, [ctxq+ResampleContext.index] + shl min_filter_length_x4d, %3 + mov fracd, [ctxq+ResampleContext.frac] + neg min_filter_length_x4q + mov filter_bankq, [ctxq+ResampleContext.filter_bank] + sub r2mp, min_filter_length_x4q + sub filter_bankq, min_filter_length_x4q + PUSH min_filter_length_x4q + PUSH filter_bankq + mov phase_shiftd, [ctxq+ResampleContext.phase_shift] + + DEFINE_ARGS src, phase_shift, dst, frac, index, min_filter_count_x4, filter + +%define filter_bankq dword [rsp+0x0] +%define min_filter_length_x4q dword [rsp+0x4] +%define src_incrd dword [rsp+0x8] +%define phase_maskd dword [rsp+0xc] +%define dst_endq dword [rsp+0x10] +%define filter_allocd dword [rsp+0x14] +%define dst_incr_modd dword [rsp+0x18] +%define dst_incr_divd dword [rsp+0x1c] + + mov srcq, r2mp +%endif + +.loop: + mov filterd, filter_allocd + imul filterd, indexd +%if ARCH_X86_64 + mov min_filter_count_x4q, min_filter_len_x4q + lea filterq, [filter_bankq+filterq*%2] +%else ; x86-32 + mov min_filter_count_x4q, filter_bankq + lea filterq, [min_filter_count_x4q+filterq*%2] + mov min_filter_count_x4q, min_filter_length_x4q +%endif +%ifidn %1, int16 + movd m0, [pd_0x4000] +%else ; float/double + xorps m0, m0, m0 +%endif + + align 16 +.inner_loop: + movu m1, [srcq+min_filter_count_x4q*1] +%ifidn %1, int16 + PMADCSWD m0, m1, [filterq+min_filter_count_x4q*1], m0, m1 +%else ; float/double +%if cpuflag(fma4) || cpuflag(fma3) + fmaddp%4 m0, m1, [filterq+min_filter_count_x4q*1], m0 +%else + mulp%4 m1, m1, [filterq+min_filter_count_x4q*1] + addp%4 m0, m0, m1 +%endif ; cpuflag +%endif + add min_filter_count_x4q, mmsize + js .inner_loop + +%ifidn %1, int16 + HADDD m0, m1 + psrad m0, 15 + add fracd, dst_incr_modd + packssdw m0, m0 + add indexd, dst_incr_divd + movd [dstq], m0 +%else ; float/double + ; horizontal sum & store +%if mmsize == 32 + vextractf128 xm1, m0, 0x1 + addps xm0, xm1 +%endif + movhlps xm1, xm0 +%ifidn %1, float + addps xm0, xm1 + shufps xm1, xm0, xm0, q0001 +%endif + add fracd, dst_incr_modd + addp%4 xm0, xm1 + add indexd, dst_incr_divd + movs%4 [dstq], xm0 +%endif + cmp fracd, src_incrd + jl .skip + sub fracd, src_incrd + inc indexd + +%if UNIX64 + DEFINE_ARGS filter_alloc, dst, src, phase_shift, index, frac, dst_incr_mod, \ + index_incr, min_filter_count_x4, min_filter_len_x4, dst_incr_div, \ + src_incr, phase_mask, dst_end, filter_bank +%elif WIN64 + DEFINE_ARGS phase_shift, dst, src, filter_alloc, index, frac, dst_incr_mod, \ + index_incr, min_filter_count_x4, min_filter_len_x4, dst_incr_div, \ + src_incr, phase_mask, dst_end, filter_bank +%else ; x86-32 + DEFINE_ARGS src, phase_shift, dst, frac, index, index_incr +%endif + +.skip: + mov index_incrd, indexd + add dstq, %2 + and indexd, phase_maskd + sar index_incrd, phase_shiftb + lea srcq, [srcq+index_incrq*%2] + cmp dstq, dst_endq + jne .loop + +%if ARCH_X86_64 + DEFINE_ARGS ctx, dst, src, phase_shift, index, frac +%else ; x86-32 + DEFINE_ARGS src, ctx, update_context, frac, index +%endif + + cmp dword update_context_stackd, 0 + jz .skip_store + ; strictly speaking, the function should always return the consumed + ; number of bytes; however, we only use the value if update_context + ; is true, so let's just leave it uninitialized otherwise + mov ctxq, ctx_stackq + movifnidn rax, srcq + mov [ctxq+ResampleContext.frac ], fracd + sub rax, src_stackq + mov [ctxq+ResampleContext.index], indexd + shr rax, %3 + +.skip_store: +%if ARCH_X86_32 + ADD rsp, 0x20 +%endif + RET + +; int resample_linear_$format(ResampleContext *ctx, float *dst, +; const float *src, int size, int update_ctx) +%if ARCH_X86_64 ; unix64 and win64 +%if UNIX64 +cglobal resample_linear_%1, 0, 15, 5, ctx, dst, phase_mask, phase_shift, index, frac, \ + size, dst_incr_mod, min_filter_count_x4, \ + min_filter_len_x4, dst_incr_div, src_incr, \ + src, dst_end, filter_bank + + mov srcq, r2mp +%else ; win64 +cglobal resample_linear_%1, 0, 15, 5, ctx, phase_mask, src, phase_shift, index, frac, \ + size, dst_incr_mod, min_filter_count_x4, \ + min_filter_len_x4, dst_incr_div, src_incr, \ + dst, dst_end, filter_bank + + mov dstq, r1mp +%endif + + ; use red-zone for variable storage +%define ctx_stackq [rsp-0x8] +%define src_stackq [rsp-0x10] +%define phase_mask_stackd [rsp-0x14] +%if WIN64 +%define update_context_stackd r4m +%else ; unix64 +%define update_context_stackd [rsp-0x18] +%endif + + ; load as many variables in registers as possible; for the rest, store + ; on stack so that we have 'ctx' available as one extra register + mov sized, r3d + mov phase_maskd, [ctxq+ResampleContext.phase_mask] +%if UNIX64 + mov update_context_stackd, r4d +%endif + mov indexd, [ctxq+ResampleContext.index] + mov fracd, [ctxq+ResampleContext.frac] + mov dst_incr_modd, [ctxq+ResampleContext.dst_incr_mod] + mov filter_bankq, [ctxq+ResampleContext.filter_bank] + mov src_incrd, [ctxq+ResampleContext.src_incr] + mov ctx_stackq, ctxq + mov phase_mask_stackd, phase_maskd + mov min_filter_len_x4d, [ctxq+ResampleContext.filter_length] +%ifidn %1, int16 + movd m4, [pd_0x4000] +%else ; float/double + cvtsi2s%4 xm0, src_incrd + movs%4 xm4, [%5] + divs%4 xm4, xm0 +%endif + mov dst_incr_divd, [ctxq+ResampleContext.dst_incr_div] + shl min_filter_len_x4d, %3 + lea dst_endq, [dstq+sizeq*%2] + +%if UNIX64 + mov ecx, [ctxq+ResampleContext.phase_shift] + mov edi, [ctxq+ResampleContext.filter_alloc] + + DEFINE_ARGS filter_alloc, dst, filter2, phase_shift, index, frac, filter1, \ + dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \ + dst_incr_div, src_incr, src, dst_end, filter_bank +%elif WIN64 + mov R9d, [ctxq+ResampleContext.filter_alloc] + mov ecx, [ctxq+ResampleContext.phase_shift] + + DEFINE_ARGS phase_shift, filter2, src, filter_alloc, index, frac, filter1, \ + dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \ + dst_incr_div, src_incr, dst, dst_end, filter_bank +%endif + + neg min_filter_len_x4q + sub filter_bankq, min_filter_len_x4q + sub srcq, min_filter_len_x4q + mov src_stackq, srcq +%else ; x86-32 +cglobal resample_linear_%1, 1, 7, 5, ctx, min_filter_length_x4, filter2, \ + frac, index, dst, filter_bank + + ; push temp variables to stack +%define ctx_stackq r0mp +%define src_stackq r2mp +%define update_context_stackd r4m + + mov dstq, r1mp + mov r3, r3mp + lea r3, [dstq+r3*%2] + PUSH dword [ctxq+ResampleContext.dst_incr_div] + PUSH r3 + mov r3, dword [ctxq+ResampleContext.filter_alloc] + PUSH dword [ctxq+ResampleContext.dst_incr_mod] + PUSH r3 + shl r3, %3 + PUSH r3 + mov r3, dword [ctxq+ResampleContext.src_incr] + PUSH dword [ctxq+ResampleContext.phase_mask] + PUSH r3d +%ifidn %1, int16 + movd m4, [pd_0x4000] +%else ; float/double + cvtsi2s%4 xm0, r3d + movs%4 xm4, [%5] + divs%4 xm4, xm0 +%endif + mov min_filter_length_x4d, [ctxq+ResampleContext.filter_length] + mov indexd, [ctxq+ResampleContext.index] + shl min_filter_length_x4d, %3 + mov fracd, [ctxq+ResampleContext.frac] + neg min_filter_length_x4q + mov filter_bankq, [ctxq+ResampleContext.filter_bank] + sub r2mp, min_filter_length_x4q + sub filter_bankq, min_filter_length_x4q + PUSH min_filter_length_x4q + PUSH filter_bankq + PUSH dword [ctxq+ResampleContext.phase_shift] + + DEFINE_ARGS filter1, min_filter_count_x4, filter2, frac, index, dst, src + +%define phase_shift_stackd dword [rsp+0x0] +%define filter_bankq dword [rsp+0x4] +%define min_filter_length_x4q dword [rsp+0x8] +%define src_incrd dword [rsp+0xc] +%define phase_mask_stackd dword [rsp+0x10] +%define filter_alloc_x4q dword [rsp+0x14] +%define filter_allocd dword [rsp+0x18] +%define dst_incr_modd dword [rsp+0x1c] +%define dst_endq dword [rsp+0x20] +%define dst_incr_divd dword [rsp+0x24] + + mov srcq, r2mp +%endif + +.loop: + mov filter1d, filter_allocd + imul filter1d, indexd +%if ARCH_X86_64 + mov min_filter_count_x4q, min_filter_len_x4q + lea filter1q, [filter_bankq+filter1q*%2] + lea filter2q, [filter1q+filter_allocq*%2] +%else ; x86-32 + mov min_filter_count_x4q, filter_bankq + lea filter1q, [min_filter_count_x4q+filter1q*%2] + mov min_filter_count_x4q, min_filter_length_x4q + mov filter2q, filter1q + add filter2q, filter_alloc_x4q +%endif +%ifidn %1, int16 + mova m0, m4 + mova m2, m4 +%else ; float/double + xorps m0, m0, m0 + xorps m2, m2, m2 +%endif + + align 16 +.inner_loop: + movu m1, [srcq+min_filter_count_x4q*1] +%ifidn %1, int16 +%if cpuflag(xop) + vpmadcswd m2, m1, [filter2q+min_filter_count_x4q*1], m2 + vpmadcswd m0, m1, [filter1q+min_filter_count_x4q*1], m0 +%else + pmaddwd m3, m1, [filter2q+min_filter_count_x4q*1] + pmaddwd m1, [filter1q+min_filter_count_x4q*1] + paddd m2, m3 + paddd m0, m1 +%endif ; cpuflag +%else ; float/double +%if cpuflag(fma4) || cpuflag(fma3) + fmaddp%4 m2, m1, [filter2q+min_filter_count_x4q*1], m2 + fmaddp%4 m0, m1, [filter1q+min_filter_count_x4q*1], m0 +%else + mulp%4 m3, m1, [filter2q+min_filter_count_x4q*1] + mulp%4 m1, m1, [filter1q+min_filter_count_x4q*1] + addp%4 m2, m2, m3 + addp%4 m0, m0, m1 +%endif ; cpuflag +%endif + add min_filter_count_x4q, mmsize + js .inner_loop + +%ifidn %1, int16 +%if mmsize == 16 +%if cpuflag(xop) + vphadddq m2, m2 + vphadddq m0, m0 +%endif + pshufd m3, m2, q0032 + pshufd m1, m0, q0032 + paddd m2, m3 + paddd m0, m1 +%endif +%if notcpuflag(xop) + PSHUFLW m3, m2, q0032 + PSHUFLW m1, m0, q0032 + paddd m2, m3 + paddd m0, m1 +%endif + psubd m2, m0 + ; This is probably a really bad idea on atom and other machines with a + ; long transfer latency between GPRs and XMMs (atom). However, it does + ; make the clip a lot simpler... + movd eax, m2 + add indexd, dst_incr_divd + imul fracd + idiv src_incrd + movd m1, eax + add fracd, dst_incr_modd + paddd m0, m1 + psrad m0, 15 + packssdw m0, m0 + movd [dstq], m0 + + ; note that for imul/idiv, I need to move filter to edx/eax for each: + ; - 32bit: eax=r0[filter1], edx=r2[filter2] + ; - win64: eax=r6[filter1], edx=r1[todo] + ; - unix64: eax=r6[filter1], edx=r2[todo] +%else ; float/double + ; val += (v2 - val) * (FELEML) frac / c->src_incr; +%if mmsize == 32 + vextractf128 xm1, m0, 0x1 + vextractf128 xm3, m2, 0x1 + addps xm0, xm1 + addps xm2, xm3 +%endif + cvtsi2s%4 xm1, fracd + subp%4 xm2, xm0 + mulp%4 xm1, xm4 + shufp%4 xm1, xm1, q0000 +%if cpuflag(fma4) || cpuflag(fma3) + fmaddp%4 xm0, xm2, xm1, xm0 +%else + mulp%4 xm2, xm1 + addp%4 xm0, xm2 +%endif ; cpuflag + + ; horizontal sum & store + movhlps xm1, xm0 +%ifidn %1, float + addps xm0, xm1 + shufps xm1, xm0, xm0, q0001 +%endif + add fracd, dst_incr_modd + addp%4 xm0, xm1 + add indexd, dst_incr_divd + movs%4 [dstq], xm0 +%endif + cmp fracd, src_incrd + jl .skip + sub fracd, src_incrd + inc indexd + +%if UNIX64 + DEFINE_ARGS filter_alloc, dst, filter2, phase_shift, index, frac, index_incr, \ + dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \ + dst_incr_div, src_incr, src, dst_end, filter_bank +%elif WIN64 + DEFINE_ARGS phase_shift, filter2, src, filter_alloc, index, frac, index_incr, \ + dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \ + dst_incr_div, src_incr, dst, dst_end, filter_bank +%else ; x86-32 + DEFINE_ARGS filter1, phase_shift, index_incr, frac, index, dst, src +%endif + +.skip: +%if ARCH_X86_32 + mov phase_shiftd, phase_shift_stackd +%endif + mov index_incrd, indexd + add dstq, %2 + and indexd, phase_mask_stackd + sar index_incrd, phase_shiftb + lea srcq, [srcq+index_incrq*%2] + cmp dstq, dst_endq + jne .loop + +%if UNIX64 + DEFINE_ARGS ctx, dst, filter2, phase_shift, index, frac, index_incr, \ + dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \ + dst_incr_div, src_incr, src, dst_end, filter_bank +%elif WIN64 + DEFINE_ARGS ctx, filter2, src, phase_shift, index, frac, index_incr, \ + dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \ + dst_incr_div, src_incr, dst, dst_end, filter_bank +%else ; x86-32 + DEFINE_ARGS filter1, ctx, update_context, frac, index, dst, src +%endif + + cmp dword update_context_stackd, 0 + jz .skip_store + ; strictly speaking, the function should always return the consumed + ; number of bytes; however, we only use the value if update_context + ; is true, so let's just leave it uninitialized otherwise + mov ctxq, ctx_stackq + movifnidn rax, srcq + mov [ctxq+ResampleContext.frac ], fracd + sub rax, src_stackq + mov [ctxq+ResampleContext.index], indexd + shr rax, %3 + +.skip_store: +%if ARCH_X86_32 + ADD rsp, 0x28 +%endif + RET +%endmacro + +INIT_XMM sse +RESAMPLE_FNS float, 4, 2, s, pf_1 + +%if HAVE_AVX_EXTERNAL +INIT_YMM avx +RESAMPLE_FNS float, 4, 2, s, pf_1 +%endif +%if HAVE_FMA3_EXTERNAL +INIT_YMM fma3 +RESAMPLE_FNS float, 4, 2, s, pf_1 +%endif +%if HAVE_FMA4_EXTERNAL +INIT_XMM fma4 +RESAMPLE_FNS float, 4, 2, s, pf_1 +%endif + +%if ARCH_X86_32 +INIT_MMX mmxext +RESAMPLE_FNS int16, 2, 1 +%endif + +INIT_XMM sse2 +RESAMPLE_FNS int16, 2, 1 +%if HAVE_XOP_EXTERNAL +INIT_XMM xop +RESAMPLE_FNS int16, 2, 1 +%endif + +INIT_XMM sse2 +RESAMPLE_FNS double, 8, 3, d, pdbl_1 diff --git a/libswresample/x86/resample_init.c b/libswresample/x86/resample_init.c new file mode 100644 index 000000000..99f5e1404 --- /dev/null +++ b/libswresample/x86/resample_init.c @@ -0,0 +1,90 @@ +/* + * audio resampling + * Copyright (c) 2004-2012 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * audio resampling + * @author Michael Niedermayer + */ + +#include "libavutil/x86/cpu.h" +#include "libswresample/resample.h" + +#define RESAMPLE_FUNCS(type, opt) \ +int ff_resample_common_##type##_##opt(ResampleContext *c, void *dst, \ + const void *src, int sz, int upd); \ +int ff_resample_linear_##type##_##opt(ResampleContext *c, void *dst, \ + const void *src, int sz, int upd) + +RESAMPLE_FUNCS(int16, mmxext); +RESAMPLE_FUNCS(int16, sse2); +RESAMPLE_FUNCS(int16, xop); +RESAMPLE_FUNCS(float, sse); +RESAMPLE_FUNCS(float, avx); +RESAMPLE_FUNCS(float, fma3); +RESAMPLE_FUNCS(float, fma4); +RESAMPLE_FUNCS(double, sse2); + +void swri_resample_dsp_x86_init(ResampleContext *c) +{ + int av_unused mm_flags = av_get_cpu_flags(); + + switch(c->format){ + case AV_SAMPLE_FMT_S16P: + if (ARCH_X86_32 && EXTERNAL_MMXEXT(mm_flags)) { + c->dsp.resample = c->linear ? ff_resample_linear_int16_mmxext + : ff_resample_common_int16_mmxext; + } + if (EXTERNAL_SSE2(mm_flags)) { + c->dsp.resample = c->linear ? ff_resample_linear_int16_sse2 + : ff_resample_common_int16_sse2; + } + if (EXTERNAL_XOP(mm_flags)) { + c->dsp.resample = c->linear ? ff_resample_linear_int16_xop + : ff_resample_common_int16_xop; + } + break; + case AV_SAMPLE_FMT_FLTP: + if (EXTERNAL_SSE(mm_flags)) { + c->dsp.resample = c->linear ? ff_resample_linear_float_sse + : ff_resample_common_float_sse; + } + if (EXTERNAL_AVX(mm_flags)) { + c->dsp.resample = c->linear ? ff_resample_linear_float_avx + : ff_resample_common_float_avx; + } + if (EXTERNAL_FMA3(mm_flags)) { + c->dsp.resample = c->linear ? ff_resample_linear_float_fma3 + : ff_resample_common_float_fma3; + } + if (EXTERNAL_FMA4(mm_flags)) { + c->dsp.resample = c->linear ? ff_resample_linear_float_fma4 + : ff_resample_common_float_fma4; + } + break; + case AV_SAMPLE_FMT_DBLP: + if (EXTERNAL_SSE2(mm_flags)) { + c->dsp.resample = c->linear ? ff_resample_linear_double_sse2 + : ff_resample_common_double_sse2; + } + break; + } +} diff --git a/libswresample/x86/resample_mmx.h b/libswresample/x86/resample_mmx.h deleted file mode 100644 index d96fd5a9d..000000000 --- a/libswresample/x86/resample_mmx.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2012 Michael Niedermayer - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/x86/asm.h" -#include "libavutil/cpu.h" -#include "libswresample/swresample_internal.h" - -int swri_resample_int16_mmx2 (struct ResampleContext *c, int16_t *dst, const int16_t *src, int *consumed, int src_size, int dst_size, int update_ctx); -int swri_resample_int16_ssse3(struct ResampleContext *c, int16_t *dst, const int16_t *src, int *consumed, int src_size, int dst_size, int update_ctx); - -DECLARE_ALIGNED(16, const uint64_t, ff_resample_int16_rounder)[2] = { 0x0000000000004000ULL, 0x0000000000000000ULL}; - -#define COMMON_CORE_INT16_MMX2 \ - x86_reg len= -2*c->filter_length;\ -__asm__ volatile(\ - "movq "MANGLE(ff_resample_int16_rounder)", %%mm0 \n\t"\ - "1: \n\t"\ - "movq (%1, %0), %%mm1 \n\t"\ - "pmaddwd (%2, %0), %%mm1 \n\t"\ - "paddd %%mm1, %%mm0 \n\t"\ - "add $8, %0 \n\t"\ - " js 1b \n\t"\ - "pshufw $0x0E, %%mm0, %%mm1 \n\t"\ - "paddd %%mm1, %%mm0 \n\t"\ - "psrad $15, %%mm0 \n\t"\ - "packssdw %%mm0, %%mm0 \n\t"\ - "movd %%mm0, (%3) \n\t"\ - : "+r" (len)\ - : "r" (((uint8_t*)(src+sample_index))-len),\ - "r" (((uint8_t*)filter)-len),\ - "r" (dst+dst_index)\ -); - -#define COMMON_CORE_INT16_SSSE3 \ - x86_reg len= -2*c->filter_length;\ -__asm__ volatile(\ - "movdqa "MANGLE(ff_resample_int16_rounder)", %%xmm0 \n\t"\ - "1: \n\t"\ - "movdqu (%1, %0), %%xmm1 \n\t"\ - "pmaddwd (%2, %0), %%xmm1 \n\t"\ - "paddd %%xmm1, %%xmm0 \n\t"\ - "add $16, %0 \n\t"\ - " js 1b \n\t"\ - "phaddd %%xmm0, %%xmm0 \n\t"\ - "phaddd %%xmm0, %%xmm0 \n\t"\ - "psrad $15, %%xmm0 \n\t"\ - "packssdw %%xmm0, %%xmm0 \n\t"\ - "movd %%xmm0, (%3) \n\t"\ - : "+r" (len)\ - : "r" (((uint8_t*)(src+sample_index))-len),\ - "r" (((uint8_t*)filter)-len),\ - "r" (dst+dst_index)\ -); diff --git a/libswscale/Makefile b/libswscale/Makefile index ca6e27d1f..e96837f06 100644 --- a/libswscale/Makefile +++ b/libswscale/Makefile @@ -1,7 +1,6 @@ include $(SUBDIR)../config.mak NAME = swscale -FFLIBS = avutil HEADERS = swscale.h \ version.h \ diff --git a/libswscale/bfin/Makefile b/libswscale/bfin/Makefile deleted file mode 100644 index 5f3455042..000000000 --- a/libswscale/bfin/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -OBJS += bfin/internal_bfin.o \ - bfin/swscale_bfin.o \ - bfin/yuv2rgb_bfin.o \ diff --git a/libswscale/bfin/internal_bfin.S b/libswscale/bfin/internal_bfin.S deleted file mode 100644 index eab30aa6c..000000000 --- a/libswscale/bfin/internal_bfin.S +++ /dev/null @@ -1,613 +0,0 @@ -/* - * Copyright (C) 2007 Marc Hoffman - * April 20, 2007 - * - * Blackfin video color space converter operations - * convert I420 YV12 to RGB in various formats - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -/* -YUV420 to RGB565 conversion. This routine takes a YUV 420 planar macroblock -and converts it to RGB565. R:5 bits, G:6 bits, B:5 bits.. packed into shorts. - - -The following calculation is used for the conversion: - - r = clipz((y - oy) * cy + crv * (v - 128)) - g = clipz((y - oy) * cy + cgv * (v - 128) + cgu * (u - 128)) - b = clipz((y - oy) * cy + cbu * (u - 128)) - -y, u, v are prescaled by a factor of 4 i.e. left-shifted to gain precision. - - -New factorization to eliminate the truncation error which was -occurring due to the byteop3p. - - -1) Use the bytop16m to subtract quad bytes we use this in U8 this - then so the offsets need to be renormalized to 8bits. - -2) Scale operands up by a factor of 4 not 8 because Blackfin - multiplies include a shift. - -3) Compute into the accumulators cy * yx0, cy * yx1. - -4) Compute each of the linear equations: - r = clipz((y - oy) * cy + crv * (v - 128)) - - g = clipz((y - oy) * cy + cgv * (v - 128) + cgu * (u - 128)) - - b = clipz((y - oy) * cy + cbu * (u - 128)) - - Reuse of the accumulators requires that we actually multiply - twice once with addition and the second time with a subtraction. - - Because of this we need to compute the equations in the order R B - then G saving the writes for B in the case of 24/32 bit color - formats. - - API: yuv2rgb_kind (uint8_t *Y, uint8_t *U, uint8_t *V, int *out, - int dW, uint32_t *coeffs); - - A B - --- --- - i2 = cb i3 = cr - i1 = coeff i0 = y - -Where coeffs have the following layout in memory. - -uint32_t oy, oc, zero, cy, crv, rmask, cbu, bmask, cgu, cgv; - -coeffs is a pointer to oy. - -The {rgb} masks are only utilized by the 565 packing algorithm. Note the data -replication is used to simplify the internal algorithms for the dual Mac -architecture of BlackFin. - -All routines are exported with _ff_bfin_ as a symbol prefix. - -Rough performance gain compared against -O3: - -2779809/1484290 187.28% - -which translates to ~33c/pel to ~57c/pel for the reference vs 17.5 -c/pel for the optimized implementations. Not sure why there is such a -huge variation on the reference codes on Blackfin I guess it must have -to do with the memory system. -*/ - -#define mL3 .text -#if defined(__FDPIC__) && CONFIG_SRAM -#define mL1 .l1.text -#else -#define mL1 mL3 -#endif -#define MEM mL1 - -#define DEFUN(fname,where,interface) \ - .section where; \ - .global _ff_bfin_ ## fname; \ - .type _ff_bfin_ ## fname, STT_FUNC; \ - .align 8; \ - _ff_bfin_ ## fname - -#define DEFUN_END(fname) \ - .size _ff_bfin_ ## fname, . - _ff_bfin_ ## fname - - -.text - -#define COEFF_LEN 11*4 -#define COEFF_REL_CY_OFF 4*4 - -#define ARG_OUT 20 -#define ARG_W 24 -#define ARG_COEFF 28 - -DEFUN(yuv2rgb565_line,MEM, - (uint8_t *Y, uint8_t *U, uint8_t *V, int *out, int dW, uint32_t *coeffs)): - link 0; - [--sp] = (r7:4); - p1 = [fp+ARG_OUT]; - r3 = [fp+ARG_W]; - - i0 = r0; - i2 = r1; - i3 = r2; - - r0 = [fp+ARG_COEFF]; - i1 = r0; - b1 = i1; - l1 = COEFF_LEN; - m0 = COEFF_REL_CY_OFF; - p0 = r3; - - r0 = [i0++]; // 2Y - r1.l = w[i2++]; // 2u - r1.h = w[i3++]; // 2v - p0 = p0>>2; - - lsetup (.L0565, .L1565) lc0 = p0; - - /* - uint32_t oy,oc,zero,cy,crv,rmask,cbu,bmask,cgu,cgv - r0 -- used to load 4ys - r1 -- used to load 2us,2vs - r4 -- y3,y2 - r5 -- y1,y0 - r6 -- u1,u0 - r7 -- v1,v0 - */ - r2=[i1++]; // oy -.L0565: - /* - rrrrrrrr gggggggg bbbbbbbb - 5432109876543210 - bbbbb >>3 - gggggggg <<3 - rrrrrrrr <<8 - rrrrrggggggbbbbb - */ - (r4,r5) = byteop16m (r1:0, r3:2) || r3=[i1++]; // oc - (r7,r6) = byteop16m (r1:0, r3:2) (r); - r5 = r5 << 2 (v); // y1,y0 - r4 = r4 << 2 (v); // y3,y2 - r6 = r6 << 2 (v) || r0=[i1++]; // u1,u0, r0=zero - r7 = r7 << 2 (v) || r1=[i1++]; // v1,v0 r1=cy - /* Y' = y*cy */ - a1 = r1.h*r5.h, a0 = r1.l*r5.l || r1=[i1++]; // crv - - /* R = Y+ crv*(Cr-128) */ - r2.h = (a1 += r1.h*r7.l), r2.l = (a0 += r1.l*r7.l); - a1 -= r1.h*r7.l, a0 -= r1.l*r7.l || r5=[i1++]; // rmask - r2 = byteop3p(r3:2, r1:0)(LO) || r1=[i1++]; // cbu - r2 = r2 >> 3 (v); - r3 = r2 & r5; - - /* B = Y+ cbu*(Cb-128) */ - r2.h = (a1 += r1.h*r6.l), r2.l = (a0 += r1.l*r6.l); - a1 -= r1.h*r6.l, a0 -= r1.l*r6.l || r5=[i1++]; // bmask - r2 = byteop3p(r3:2, r1:0)(LO) || r1=[i1++]; // cgu - r2 = r2 << 8 (v); - r2 = r2 & r5; - r3 = r3 | r2; - - /* G = Y+ cgu*(Cb-128)+cgv*(Cr-128) */ - a1 += r1.h*r6.l, a0 += r1.l*r6.l || r1=[i1++]; // cgv - r2.h = (a1 += r1.h*r7.l), r2.l = (a0 += r1.l*r7.l); - r2 = byteop3p(r3:2, r1:0)(LO) || r5=[i1++m0]; // gmask - r2 = r2 << 3 (v); - r2 = r2 & r5; - r3 = r3 | r2; - [p1++]=r3 || r1=[i1++]; // cy - - /* Y' = y*cy */ - - a1 = r1.h*r4.h, a0 = r1.l*r4.l || r1=[i1++]; // crv - - /* R = Y+ crv*(Cr-128) */ - r2.h = (a1 += r1.h*r7.h), r2.l = (a0 += r1.l*r7.h); - a1 -= r1.h*r7.h, a0 -= r1.l*r7.h || r5=[i1++]; // rmask - r2 = byteop3p(r3:2, r1:0)(LO) || r1=[i1++]; // cbu - r2 = r2 >> 3 (v); - r3 = r2 & r5; - - /* B = Y+ cbu*(Cb-128) */ - r2.h = (a1 += r1.h*r6.h), r2.l = (a0 += r1.l*r6.h); - a1 -= r1.h*r6.h, a0 -= r1.l*r6.h || r5=[i1++]; // bmask - r2 = byteop3p(r3:2, r1:0)(LO) || r1=[i1++]; // cgu - r2 = r2 << 8 (v); - r2 = r2 & r5; - r3 = r3 | r2; - - /* G = Y+ cgu*(Cb-128)+cgv*(Cr-128) */ - a1 += r1.h*r6.h, a0 += r1.l*r6.h || r1=[i1++]; // cgv - r2.h = (a1 += r1.h*r7.h), r2.l = (a0 += r1.l*r7.h) || r5=[i1++]; // gmask - r2 = byteop3p(r3:2, r1:0)(LO) || r0 = [i0++]; // 2Y - r2 = r2 << 3 (v) || r1.l = w[i2++]; // 2u - r2 = r2 & r5; - r3 = r3 | r2; - [p1++]=r3 || r1.h = w[i3++]; // 2v -.L1565: r2=[i1++]; // oy - - l1 = 0; - - (r7:4) = [sp++]; - unlink; - rts; -DEFUN_END(yuv2rgb565_line) - -DEFUN(yuv2rgb555_line,MEM, - (uint8_t *Y, uint8_t *U, uint8_t *V, int *out, int dW, uint32_t *coeffs)): - link 0; - [--sp] = (r7:4); - p1 = [fp+ARG_OUT]; - r3 = [fp+ARG_W]; - - i0 = r0; - i2 = r1; - i3 = r2; - - r0 = [fp+ARG_COEFF]; - i1 = r0; - b1 = i1; - l1 = COEFF_LEN; - m0 = COEFF_REL_CY_OFF; - p0 = r3; - - r0 = [i0++]; // 2Y - r1.l = w[i2++]; // 2u - r1.h = w[i3++]; // 2v - p0 = p0>>2; - - lsetup (.L0555, .L1555) lc0 = p0; - - /* - uint32_t oy,oc,zero,cy,crv,rmask,cbu,bmask,cgu,cgv - r0 -- used to load 4ys - r1 -- used to load 2us,2vs - r4 -- y3,y2 - r5 -- y1,y0 - r6 -- u1,u0 - r7 -- v1,v0 - */ - r2=[i1++]; // oy -.L0555: - /* - rrrrrrrr gggggggg bbbbbbbb - 5432109876543210 - bbbbb >>3 - gggggggg <<2 - rrrrrrrr <<7 - xrrrrrgggggbbbbb - */ - - (r4,r5) = byteop16m (r1:0, r3:2) || r3=[i1++]; // oc - (r7,r6) = byteop16m (r1:0, r3:2) (r); - r5 = r5 << 2 (v); // y1,y0 - r4 = r4 << 2 (v); // y3,y2 - r6 = r6 << 2 (v) || r0=[i1++]; // u1,u0, r0=zero - r7 = r7 << 2 (v) || r1=[i1++]; // v1,v0 r1=cy - /* Y' = y*cy */ - a1 = r1.h*r5.h, a0 = r1.l*r5.l || r1=[i1++]; // crv - - /* R = Y+ crv*(Cr-128) */ - r2.h = (a1 += r1.h*r7.l), r2.l = (a0 += r1.l*r7.l); - a1 -= r1.h*r7.l, a0 -= r1.l*r7.l || r5=[i1++]; // rmask - r2 = byteop3p(r3:2, r1:0)(LO) || r1=[i1++]; // cbu - r2 = r2 >> 3 (v); - r3 = r2 & r5; - - /* B = Y+ cbu*(Cb-128) */ - r2.h = (a1 += r1.h*r6.l), r2.l = (a0 += r1.l*r6.l); - a1 -= r1.h*r6.l, a0 -= r1.l*r6.l || r5=[i1++]; // bmask - r2 = byteop3p(r3:2, r1:0)(LO) || r1=[i1++]; // cgu - r2 = r2 << 7 (v); - r2 = r2 & r5; - r3 = r3 | r2; - - /* G = Y+ cgu*(Cb-128)+cgv*(Cr-128) */ - a1 += r1.h*r6.l, a0 += r1.l*r6.l || r1=[i1++]; // cgv - r2.h = (a1 += r1.h*r7.l), r2.l = (a0 += r1.l*r7.l); - r2 = byteop3p(r3:2, r1:0)(LO) || r5=[i1++m0]; // gmask - r2 = r2 << 2 (v); - r2 = r2 & r5; - r3 = r3 | r2; - [p1++]=r3 || r1=[i1++]; // cy - - /* Y' = y*cy */ - - a1 = r1.h*r4.h, a0 = r1.l*r4.l || r1=[i1++]; // crv - - /* R = Y+ crv*(Cr-128) */ - r2.h = (a1 += r1.h*r7.h), r2.l = (a0 += r1.l*r7.h); - a1 -= r1.h*r7.h, a0 -= r1.l*r7.h || r5=[i1++]; // rmask - r2 = byteop3p(r3:2, r1:0)(LO) || r1=[i1++]; // cbu - r2 = r2 >> 3 (v); - r3 = r2 & r5; - - /* B = Y+ cbu*(Cb-128) */ - r2.h = (a1 += r1.h*r6.h), r2.l = (a0 += r1.l*r6.h); - a1 -= r1.h*r6.h, a0 -= r1.l*r6.h || r5=[i1++]; // bmask - r2 = byteop3p(r3:2, r1:0)(LO) || r1=[i1++]; // cgu - r2 = r2 << 7 (v); - r2 = r2 & r5; - r3 = r3 | r2; - - /* G = Y+ cgu*(Cb-128)+cgv*(Cr-128) */ - a1 += r1.h*r6.h, a0 += r1.l*r6.h || r1=[i1++]; // cgv - r2.h = (a1 += r1.h*r7.h), r2.l = (a0 += r1.l*r7.h) || r5=[i1++]; // gmask - r2 = byteop3p(r3:2, r1:0)(LO) || r0=[i0++]; // 4Y - r2 = r2 << 2 (v) || r1.l=w[i2++]; // 2u - r2 = r2 & r5; - r3 = r3 | r2; - [p1++]=r3 || r1.h=w[i3++]; // 2v - -.L1555: r2=[i1++]; // oy - - l1 = 0; - - (r7:4) = [sp++]; - unlink; - rts; -DEFUN_END(yuv2rgb555_line) - -DEFUN(yuv2rgb24_line,MEM, - (uint8_t *Y, uint8_t *U, uint8_t *V, int *out, int dW, uint32_t *coeffs)): - link 0; - [--sp] = (r7:4); - p1 = [fp+ARG_OUT]; - r3 = [fp+ARG_W]; - p2 = p1; - p2 += 3; - - i0 = r0; - i2 = r1; - i3 = r2; - - r0 = [fp+ARG_COEFF]; // coeff buffer - i1 = r0; - b1 = i1; - l1 = COEFF_LEN; - m0 = COEFF_REL_CY_OFF; - p0 = r3; - - r0 = [i0++]; // 2Y - r1.l = w[i2++]; // 2u - r1.h = w[i3++]; // 2v - p0 = p0>>2; - - lsetup (.L0888, .L1888) lc0 = p0; - - /* - uint32_t oy,oc,zero,cy,crv,rmask,cbu,bmask,cgu,cgv - r0 -- used to load 4ys - r1 -- used to load 2us,2vs - r4 -- y3,y2 - r5 -- y1,y0 - r6 -- u1,u0 - r7 -- v1,v0 - */ - r2=[i1++]; // oy -.L0888: - (r4,r5) = byteop16m (r1:0, r3:2) || r3=[i1++]; // oc - (r7,r6) = byteop16m (r1:0, r3:2) (r); - r5 = r5 << 2 (v); // y1,y0 - r4 = r4 << 2 (v); // y3,y2 - r6 = r6 << 2 (v) || r0=[i1++]; // u1,u0, r0=zero - r7 = r7 << 2 (v) || r1=[i1++]; // v1,v0 r1=cy - - /* Y' = y*cy */ - a1 = r1.h*r5.h, a0 = r1.l*r5.l || r1=[i1++]; // crv - - /* R = Y+ crv*(Cr-128) */ - r2.h = (a1 += r1.h*r7.l), r2.l = (a0 += r1.l*r7.l); - a1 -= r1.h*r7.l, a0 -= r1.l*r7.l || r5=[i1++]; // rmask - r2 = byteop3p(r3:2, r1:0)(LO) || r1=[i1++]; // cbu - r2=r2>>16 || B[p1++]=r2; - B[p2++]=r2; - - /* B = Y+ cbu*(Cb-128) */ - r2.h = (a1 += r1.h*r6.l), r2.l = (a0 += r1.l*r6.l); - a1 -= r1.h*r6.l, a0 -= r1.l*r6.l || r5=[i1++]; // bmask - r3 = byteop3p(r3:2, r1:0)(LO) || r1=[i1++]; // cgu - - /* G = Y+ cgu*(Cb-128)+cgv*(Cr-128) */ - a1 += r1.h*r6.l, a0 += r1.l*r6.l || r1=[i1++]; // cgv - r2.h = (a1 += r1.h*r7.l), r2.l = (a0 += r1.l*r7.l); - r2 = byteop3p(r3:2, r1:0)(LO) || r5=[i1++m0]; // gmask, oy,cy,zero - - r2=r2>>16 || B[p1++]=r2; - B[p2++]=r2; - - r3=r3>>16 || B[p1++]=r3; - B[p2++]=r3 || r1=[i1++]; // cy - - p1+=3; - p2+=3; - /* Y' = y*cy */ - a1 = r1.h*r4.h, a0 = r1.l*r4.l || r1=[i1++]; // crv - - /* R = Y+ crv*(Cr-128) */ - r2.h = (a1 += r1.h*r7.h), r2.l = (a0 += r1.l*r7.h); - a1 -= r1.h*r7.h, a0 -= r1.l*r7.h || r5=[i1++]; // rmask - r2 = byteop3p(r3:2, r1:0)(LO) || r1=[i1++]; // cbu - r2=r2>>16 || B[p1++]=r2; - B[p2++]=r2; - - /* B = Y+ cbu*(Cb-128) */ - r2.h = (a1 += r1.h*r6.h), r2.l = (a0 += r1.l*r6.h); - a1 -= r1.h*r6.h, a0 -= r1.l*r6.h || r5=[i1++]; // bmask - r3 = byteop3p(r3:2, r1:0)(LO) || r1=[i1++]; // cgu - - /* G = Y+ cgu*(Cb-128)+cgv*(Cr-128) */ - a1 += r1.h*r6.h, a0 += r1.l*r6.h || r1=[i1++]; // cgv - r2.h = (a1 += r1.h*r7.h), r2.l = (a0 += r1.l*r7.h); - r2 = byteop3p(r3:2, r1:0)(LO) || r5=[i1++]; // gmask - r2=r2>>16 || B[p1++]=r2 || r0 = [i0++]; // 4y - B[p2++]=r2 || r1.l = w[i2++]; // 2u - r3=r3>>16 || B[p1++]=r3 || r1.h = w[i3++]; // 2v - B[p2++]=r3 || r2=[i1++]; // oy - - p1+=3; -.L1888: p2+=3; - - l1 = 0; - - (r7:4) = [sp++]; - unlink; - rts; -DEFUN_END(yuv2rgb24_line) - - - -#define ARG_vdst 20 -#define ARG_width 24 -#define ARG_height 28 -#define ARG_lumStride 32 -#define ARG_chromStride 36 -#define ARG_srcStride 40 - -DEFUN(uyvytoyv12, mL3, (const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, - int width, int height, - int lumStride, int chromStride, int srcStride)): - link 0; - [--sp] = (r7:4,p5:4); - - p0 = r1; // Y top even - - i2 = r2; // *u - r2 = [fp + ARG_vdst]; - i3 = r2; // *v - - r1 = [fp + ARG_srcStride]; - r2 = r0 + r1; - i0 = r0; // uyvy_T even - i1 = r2; // uyvy_B odd - - p2 = [fp + ARG_lumStride]; - p1 = p0 + p2; // Y bot odd - - p5 = [fp + ARG_width]; - p4 = [fp + ARG_height]; - r0 = p5; - p4 = p4 >> 1; - p5 = p5 >> 2; - - r2 = r0 << 1; - r1 = r1 << 1; - r1 = r1 - r2; // srcStride + (srcStride - 2*width) - r1 += -8; // i0,i1 is pre read need to correct - m0 = r1; - - r2 = [fp + ARG_chromStride]; - r0 = r0 >> 1; - r2 = r2 - r0; - m1 = r2; - - /* I0,I1 - src input line pointers - * p0,p1 - luma output line pointers - * I2 - dstU - * I3 - dstV - */ - - lsetup (0f, 1f) lc1 = p4; // H/2 -0: r0 = [i0++] || r2 = [i1++]; - r1 = [i0++] || r3 = [i1++]; - r4 = byteop1p(r1:0, r3:2); - r5 = byteop1p(r1:0, r3:2) (r); - lsetup (2f, 3f) lc0 = p5; // W/4 -2: r0 = r0 >> 8(v); - r1 = r1 >> 8(v); - r2 = r2 >> 8(v); - r3 = r3 >> 8(v); - r0 = bytepack(r0, r1); - r2 = bytepack(r2, r3) || [p0++] = r0; // yyyy - r6 = pack(r5.l, r4.l) || [p1++] = r2; // yyyy - r7 = pack(r5.h, r4.h) || r0 = [i0++] || r2 = [i1++]; - r6 = bytepack(r6, r7) || r1 = [i0++] || r3 = [i1++]; - r4 = byteop1p(r1:0, r3:2) || w[i2++] = r6.l; // uu -3: r5 = byteop1p(r1:0, r3:2) (r) || w[i3++] = r6.h; // vv - - i0 += m0; - i1 += m0; - i2 += m1; - i3 += m1; - p0 = p0 + p2; -1: p1 = p1 + p2; - - (r7:4,p5:4) = [sp++]; - unlink; - rts; -DEFUN_END(uyvytoyv12) - -DEFUN(yuyvtoyv12, mL3, (const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, - int width, int height, - int lumStride, int chromStride, int srcStride)): - link 0; - [--sp] = (r7:4,p5:4); - - p0 = r1; // Y top even - - i2 = r2; // *u - r2 = [fp + ARG_vdst]; - i3 = r2; // *v - - r1 = [fp + ARG_srcStride]; - r2 = r0 + r1; - - i0 = r0; // uyvy_T even - i1 = r2; // uyvy_B odd - - p2 = [fp + ARG_lumStride]; - p1 = p0 + p2; // Y bot odd - - p5 = [fp + ARG_width]; - p4 = [fp + ARG_height]; - r0 = p5; - p4 = p4 >> 1; - p5 = p5 >> 2; - - r2 = r0 << 1; - r1 = r1 << 1; - r1 = r1 - r2; // srcStride + (srcStride - 2*width) - r1 += -8; // i0,i1 is pre read need to correct - m0 = r1; - - r2 = [fp + ARG_chromStride]; - r0 = r0 >> 1; - r2 = r2 - r0; - m1 = r2; - - /* I0,I1 - src input line pointers - * p0,p1 - luma output line pointers - * I2 - dstU - * I3 - dstV - */ - - lsetup (0f, 1f) lc1 = p4; // H/2 -0: r0 = [i0++] || r2 = [i1++]; - r1 = [i0++] || r3 = [i1++]; - r4 = bytepack(r0, r1); - r5 = bytepack(r2, r3); - lsetup (2f, 3f) lc0 = p5; // W/4 -2: r0 = r0 >> 8(v) || [p0++] = r4; // yyyy-even - r1 = r1 >> 8(v) || [p1++] = r5; // yyyy-odd - r2 = r2 >> 8(v); - r3 = r3 >> 8(v); - r4 = byteop1p(r1:0, r3:2); - r5 = byteop1p(r1:0, r3:2) (r); - r6 = pack(r5.l, r4.l); - r7 = pack(r5.h, r4.h) || r0 = [i0++] || r2 = [i1++]; - r6 = bytepack(r6, r7) || r1 = [i0++] || r3 = [i1++]; - r4 = bytepack(r0, r1) || w[i2++] = r6.l; // uu -3: r5 = bytepack(r2, r3) || w[i3++] = r6.h; // vv - - i0 += m0; - i1 += m0; - i2 += m1; - i3 += m1; - p0 = p0 + p2; -1: p1 = p1 + p2; - - (r7:4,p5:4) = [sp++]; - unlink; - rts; -DEFUN_END(yuyvtoyv12) diff --git a/libswscale/bfin/swscale_bfin.c b/libswscale/bfin/swscale_bfin.c deleted file mode 100644 index 33c3ec520..000000000 --- a/libswscale/bfin/swscale_bfin.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2007 Marc Hoffman - * - * Blackfin software video scaler operations - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "config.h" -#include "libavutil/attributes.h" -#include "libswscale/swscale_internal.h" - -#if defined (__FDPIC__) && CONFIG_SRAM -#define L1CODE __attribute__((l1_text)) -#else -#define L1CODE -#endif - -int ff_bfin_uyvytoyv12(const uint8_t *src, uint8_t *ydst, uint8_t *udst, - uint8_t *vdst, int width, int height, - int lumStride, int chromStride, int srcStride) L1CODE; - -int ff_bfin_yuyvtoyv12(const uint8_t *src, uint8_t *ydst, uint8_t *udst, - uint8_t *vdst, int width, int height, - int lumStride, int chromStride, int srcStride) L1CODE; - -static int uyvytoyv12_unscaled(SwsContext *c, const uint8_t *src[], - int srcStride[], int srcSliceY, int srcSliceH, - uint8_t *dst[], int dstStride[]) -{ - uint8_t *dsty = dst[0] + dstStride[0] * srcSliceY; - uint8_t *dstu = dst[1] + dstStride[1] * srcSliceY / 2; - uint8_t *dstv = dst[2] + dstStride[2] * srcSliceY / 2; - const uint8_t *ip = src[0] + srcStride[0] * srcSliceY; - int w = dstStride[0]; - - ff_bfin_uyvytoyv12(ip, dsty, dstu, dstv, w, srcSliceH, - dstStride[0], dstStride[1], srcStride[0]); - - return srcSliceH; -} - -static int yuyvtoyv12_unscaled(SwsContext *c, const uint8_t *src[], - int srcStride[], int srcSliceY, int srcSliceH, - uint8_t *dst[], int dstStride[]) -{ - uint8_t *dsty = dst[0] + dstStride[0] * srcSliceY; - uint8_t *dstu = dst[1] + dstStride[1] * srcSliceY / 2; - uint8_t *dstv = dst[2] + dstStride[2] * srcSliceY / 2; - const uint8_t *ip = src[0] + srcStride[0] * srcSliceY; - int w = dstStride[0]; - - ff_bfin_yuyvtoyv12(ip, dsty, dstu, dstv, w, srcSliceH, - dstStride[0], dstStride[1], srcStride[0]); - - return srcSliceH; -} - -av_cold void ff_get_unscaled_swscale_bfin(SwsContext *c) -{ - if (c->dstFormat == AV_PIX_FMT_YUV420P && c->srcFormat == AV_PIX_FMT_UYVY422) { - av_log(NULL, AV_LOG_VERBOSE, - "selecting Blackfin optimized uyvytoyv12_unscaled\n"); - c->swscale = uyvytoyv12_unscaled; - } - if (c->dstFormat == AV_PIX_FMT_YUV420P && c->srcFormat == AV_PIX_FMT_YUYV422) { - av_log(NULL, AV_LOG_VERBOSE, - "selecting Blackfin optimized yuyvtoyv12_unscaled\n"); - c->swscale = yuyvtoyv12_unscaled; - } -} diff --git a/libswscale/bfin/yuv2rgb_bfin.c b/libswscale/bfin/yuv2rgb_bfin.c deleted file mode 100644 index 2a36ad55f..000000000 --- a/libswscale/bfin/yuv2rgb_bfin.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2007 Marc Hoffman - * - * Blackfin video color space converter operations - * convert I420 YV12 to RGB in various formats - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/pixdesc.h" -#include - -#include "config.h" -#include "libavutil/attributes.h" -#include "libswscale/swscale_internal.h" - -#if defined(__FDPIC__) && CONFIG_SRAM -#define L1CODE __attribute__((l1_text)) -#else -#define L1CODE -#endif - -void ff_bfin_yuv2rgb555_line(const uint8_t *Y, const uint8_t *U, - const uint8_t *V, uint8_t *out, - int w, uint32_t *coeffs) L1CODE; - -void ff_bfin_yuv2rgb565_line(const uint8_t *Y, const uint8_t *U, - const uint8_t *V, uint8_t *out, - int w, uint32_t *coeffs) L1CODE; - -void ff_bfin_yuv2rgb24_line(const uint8_t *Y, const uint8_t *U, - const uint8_t *V, uint8_t *out, - int w, uint32_t *coeffs) L1CODE; - -typedef void (*ltransform)(const uint8_t *Y, const uint8_t *U, const uint8_t *V, - uint8_t *out, int w, uint32_t *coeffs); - -static void bfin_prepare_coefficients(SwsContext *c, int rgb, int masks) -{ - int oy; - oy = c->yOffset & 0xffff; - oy = oy >> 3; // keep everything U8.0 for offset calculation - - c->oc = 128 * 0x01010101U; - c->oy = oy * 0x01010101U; - - /* copy 64bit vector coeffs down to 32bit vector coeffs */ - c->cy = c->yCoeff; - c->zero = 0; - - if (rgb) { - c->crv = c->vrCoeff; - c->cbu = c->ubCoeff; - c->cgu = c->ugCoeff; - c->cgv = c->vgCoeff; - } else { - c->crv = c->ubCoeff; - c->cbu = c->vrCoeff; - c->cgu = c->vgCoeff; - c->cgv = c->ugCoeff; - } - - if (masks == 555) { - c->rmask = 0x001f * 0x00010001U; - c->gmask = 0x03e0 * 0x00010001U; - c->bmask = 0x7c00 * 0x00010001U; - } else if (masks == 565) { - c->rmask = 0x001f * 0x00010001U; - c->gmask = 0x07e0 * 0x00010001U; - c->bmask = 0xf800 * 0x00010001U; - } -} - -static int core_yuv420_rgb(SwsContext *c, const uint8_t **in, int *instrides, - int srcSliceY, int srcSliceH, uint8_t **oplanes, - int *outstrides, ltransform lcscf, - int rgb, int masks) -{ - const uint8_t *py, *pu, *pv; - uint8_t *op; - int w = instrides[0]; - int h2 = srcSliceH >> 1; - int i; - - bfin_prepare_coefficients(c, rgb, masks); - - py = in[0]; - pu = in[1 + (1 ^ rgb)]; - pv = in[1 + (0 ^ rgb)]; - - op = oplanes[0] + srcSliceY * outstrides[0]; - - for (i = 0; i < h2; i++) { - lcscf(py, pu, pv, op, w, &c->oy); - - py += instrides[0]; - op += outstrides[0]; - - lcscf(py, pu, pv, op, w, &c->oy); - - py += instrides[0]; - pu += instrides[1]; - pv += instrides[2]; - op += outstrides[0]; - } - - return srcSliceH; -} - -static int bfin_yuv420_rgb555(SwsContext *c, const uint8_t **in, int *instrides, - int srcSliceY, int srcSliceH, - uint8_t **oplanes, int *outstrides) -{ - return core_yuv420_rgb(c, in, instrides, srcSliceY, srcSliceH, oplanes, - outstrides, ff_bfin_yuv2rgb555_line, 1, 555); -} - -static int bfin_yuv420_bgr555(SwsContext *c, const uint8_t **in, int *instrides, - int srcSliceY, int srcSliceH, - uint8_t **oplanes, int *outstrides) -{ - return core_yuv420_rgb(c, in, instrides, srcSliceY, srcSliceH, oplanes, - outstrides, ff_bfin_yuv2rgb555_line, 0, 555); -} - -static int bfin_yuv420_rgb24(SwsContext *c, const uint8_t **in, int *instrides, - int srcSliceY, int srcSliceH, - uint8_t **oplanes, int *outstrides) -{ - return core_yuv420_rgb(c, in, instrides, srcSliceY, srcSliceH, oplanes, - outstrides, ff_bfin_yuv2rgb24_line, 1, 888); -} - -static int bfin_yuv420_bgr24(SwsContext *c, const uint8_t **in, int *instrides, - int srcSliceY, int srcSliceH, - uint8_t **oplanes, int *outstrides) -{ - return core_yuv420_rgb(c, in, instrides, srcSliceY, srcSliceH, oplanes, - outstrides, ff_bfin_yuv2rgb24_line, 0, 888); -} - -static int bfin_yuv420_rgb565(SwsContext *c, const uint8_t **in, int *instrides, - int srcSliceY, int srcSliceH, - uint8_t **oplanes, int *outstrides) -{ - return core_yuv420_rgb(c, in, instrides, srcSliceY, srcSliceH, oplanes, - outstrides, ff_bfin_yuv2rgb565_line, 1, 565); -} - -static int bfin_yuv420_bgr565(SwsContext *c, const uint8_t **in, int *instrides, - int srcSliceY, int srcSliceH, - uint8_t **oplanes, int *outstrides) -{ - return core_yuv420_rgb(c, in, instrides, srcSliceY, srcSliceH, oplanes, - outstrides, ff_bfin_yuv2rgb565_line, 0, 565); -} - -av_cold SwsFunc ff_yuv2rgb_init_bfin(SwsContext *c) -{ - SwsFunc f; - - switch (c->dstFormat) { - case AV_PIX_FMT_RGB555: - f = bfin_yuv420_rgb555; - break; - case AV_PIX_FMT_BGR555: - f = bfin_yuv420_bgr555; - break; - case AV_PIX_FMT_RGB565: - f = bfin_yuv420_rgb565; - break; - case AV_PIX_FMT_BGR565: - f = bfin_yuv420_bgr565; - break; - case AV_PIX_FMT_RGB24: - f = bfin_yuv420_rgb24; - break; - case AV_PIX_FMT_BGR24: - f = bfin_yuv420_bgr24; - break; - default: - return 0; - } - - av_log(c, AV_LOG_INFO, "BlackFin accelerated color space converter %s\n", - av_get_pix_fmt_name(c->dstFormat)); - - return f; -} diff --git a/libswscale/input.c b/libswscale/input.c index 919b23223..6a39a3011 100644 --- a/libswscale/input.c +++ b/libswscale/input.c @@ -37,8 +37,8 @@ #define input_pixel(pos) (isBE(origin) ? AV_RB16(pos) : AV_RL16(pos)) -#define r ((origin == AV_PIX_FMT_BGR48BE || origin == AV_PIX_FMT_BGR48LE) ? b_r : r_b) -#define b ((origin == AV_PIX_FMT_BGR48BE || origin == AV_PIX_FMT_BGR48LE) ? r_b : b_r) +#define r ((origin == AV_PIX_FMT_BGR48BE || origin == AV_PIX_FMT_BGR48LE || origin == AV_PIX_FMT_BGRA64BE || origin == AV_PIX_FMT_BGRA64LE) ? b_r : r_b) +#define b ((origin == AV_PIX_FMT_BGR48BE || origin == AV_PIX_FMT_BGR48LE || origin == AV_PIX_FMT_BGRA64BE || origin == AV_PIX_FMT_BGRA64LE) ? r_b : b_r) static av_always_inline void rgb64ToY_c_template(uint16_t *dst, const uint16_t *src, int width, @@ -124,6 +124,8 @@ static void pattern ## 64 ## BE_LE ## ToUV_half_c(uint8_t *_dstU, uint8_t *_dstV rgb64funcs(rgb, LE, AV_PIX_FMT_RGBA64LE) rgb64funcs(rgb, BE, AV_PIX_FMT_RGBA64BE) +rgb64funcs(bgr, LE, AV_PIX_FMT_BGRA64LE) +rgb64funcs(bgr, BE, AV_PIX_FMT_BGRA64BE) static av_always_inline void rgb48ToY_c_template(uint16_t *dst, const uint16_t *src, int width, @@ -322,8 +324,8 @@ static av_always_inline void rgb16_32ToUV_half_c_template(int16_t *dstU, maskb |= maskb << 1; maskg |= maskg << 1; for (i = 0; i < width; i++) { - int px0 = input_pixel(2 * i + 0) >> shp; - int px1 = input_pixel(2 * i + 1) >> shp; + unsigned px0 = input_pixel(2 * i + 0) >> shp; + unsigned px1 = input_pixel(2 * i + 1) >> shp; int b, r, g = (px0 & maskgx) + (px1 & maskgx); int rb = px0 + px1 - g; @@ -529,7 +531,18 @@ static void yuy2ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, con av_assert1(src1 == src2); } -static void bswap16Y_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1, const uint8_t *unused2, int width, +static void yvy2ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1, + const uint8_t *src2, int width, uint32_t *unused) +{ + int i; + for (i = 0; i < width; i++) { + dstV[i] = src1[4 * i + 1]; + dstU[i] = src1[4 * i + 3]; + } + av_assert1(src1 == src2); +} + +static void bswap16Y_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1, const uint8_t *unused2, int width, uint32_t *unused) { int i; @@ -816,6 +829,9 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_YUYV422: c->chrToYV12 = yuy2ToUV_c; break; + case AV_PIX_FMT_YVYU422: + c->chrToYV12 = yvy2ToUV_c; + break; case AV_PIX_FMT_UYVY422: c->chrToYV12 = uyvyToUV_c; break; @@ -934,6 +950,12 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_RGBA64LE: c->chrToYV12 = rgb64LEToUV_half_c; break; + case AV_PIX_FMT_BGRA64BE: + c->chrToYV12 = bgr64BEToUV_half_c; + break; + case AV_PIX_FMT_BGRA64LE: + c->chrToYV12 = bgr64LEToUV_half_c; + break; case AV_PIX_FMT_RGB48BE: c->chrToYV12 = rgb48BEToUV_half_c; break; @@ -1013,6 +1035,12 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_RGBA64LE: c->chrToYV12 = rgb64LEToUV_c; break; + case AV_PIX_FMT_BGRA64BE: + c->chrToYV12 = bgr64BEToUV_c; + break; + case AV_PIX_FMT_BGRA64LE: + c->chrToYV12 = bgr64LEToUV_c; + break; case AV_PIX_FMT_RGB48BE: c->chrToYV12 = rgb48BEToUV_c; break; @@ -1188,6 +1216,7 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) break; #endif case AV_PIX_FMT_YUYV422: + case AV_PIX_FMT_YVYU422: case AV_PIX_FMT_Y400A: c->lumToYV12 = yuy2ToY_c; break; @@ -1279,6 +1308,11 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_RGBA64LE: c->lumToYV12 = rgb64LEToY_c; break; + case AV_PIX_FMT_BGRA64BE: + c->lumToYV12 = bgr64BEToY_c; + break; + case AV_PIX_FMT_BGRA64LE: + c->lumToYV12 = bgr64LEToY_c; } if (c->alpPixBuf) { if (is16BPS(srcFormat) || isNBPS(srcFormat)) { @@ -1286,6 +1320,8 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) c->alpToYV12 = bswap16Y_c; } switch (srcFormat) { + case AV_PIX_FMT_BGRA64LE: + case AV_PIX_FMT_BGRA64BE: case AV_PIX_FMT_RGBA64LE: case AV_PIX_FMT_RGBA64BE: c->alpToYV12 = rgba64ToA_c; break; case AV_PIX_FMT_BGRA: diff --git a/libswscale/options.c b/libswscale/options.c index 9e8703ff3..5433d55b9 100644 --- a/libswscale/options.c +++ b/libswscale/options.c @@ -69,10 +69,12 @@ static const AVOption swscale_options[] = { { "dst_v_chr_pos", "destination vertical chroma position in luma grid/256" , OFFSET(dst_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 512, VE }, { "dst_h_chr_pos", "destination horizontal chroma position in luma grid/256", OFFSET(dst_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 512, VE }, - { "sws_dither", "set dithering algorithm", OFFSET(dither), AV_OPT_TYPE_INT, { .i64 = SWS_DITHER_AUTO }, 0, NB_SWS_DITHER, VE, "sws_dither" }, - { "auto", "leave choice to sws", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_AUTO }, INT_MIN, INT_MAX, VE, "sws_dither" }, - { "bayer", "bayer dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_BAYER }, INT_MIN, INT_MAX, VE, "sws_dither" }, - { "ed", "error diffusion", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_ED }, INT_MIN, INT_MAX, VE, "sws_dither" }, + { "sws_dither", "set dithering algorithm", OFFSET(dither), AV_OPT_TYPE_INT, { .i64 = SWS_DITHER_AUTO }, 0, NB_SWS_DITHER, VE, "sws_dither" }, + { "auto", "leave choice to sws", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_AUTO }, INT_MIN, INT_MAX, VE, "sws_dither" }, + { "bayer", "bayer dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_BAYER }, INT_MIN, INT_MAX, VE, "sws_dither" }, + { "ed", "error diffusion", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_ED }, INT_MIN, INT_MAX, VE, "sws_dither" }, + { "a_dither", "arithmetic addition dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_A_DITHER}, INT_MIN, INT_MAX, VE, "sws_dither" }, + { "x_dither", "arithmetic xor dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_X_DITHER}, INT_MIN, INT_MAX, VE, "sws_dither" }, { NULL } }; diff --git a/libswscale/output.c b/libswscale/output.c index ddb0d0c19..eee6b4874 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -526,7 +526,12 @@ YUV2PACKEDWRAPPER(yuv2mono,, black, AV_PIX_FMT_MONOBLACK) dest[pos + 1] = U; \ dest[pos + 2] = Y2; \ dest[pos + 3] = V; \ - } else { \ + } else if (target == AV_PIX_FMT_YVYU422) { \ + dest[pos + 0] = Y1; \ + dest[pos + 1] = V; \ + dest[pos + 2] = Y2; \ + dest[pos + 3] = U; \ + } else { /* AV_PIX_FMT_UYVY422 */ \ dest[pos + 0] = U; \ dest[pos + 1] = Y1; \ dest[pos + 2] = V; \ @@ -661,10 +666,11 @@ yuv2422_1_c_template(SwsContext *c, const int16_t *buf0, #undef output_pixels YUV2PACKEDWRAPPER(yuv2, 422, yuyv422, AV_PIX_FMT_YUYV422) +YUV2PACKEDWRAPPER(yuv2, 422, yvyu422, AV_PIX_FMT_YVYU422) YUV2PACKEDWRAPPER(yuv2, 422, uyvy422, AV_PIX_FMT_UYVY422) -#define R_B ((target == AV_PIX_FMT_RGB48LE || target == AV_PIX_FMT_RGB48BE) ? R : B) -#define B_R ((target == AV_PIX_FMT_RGB48LE || target == AV_PIX_FMT_RGB48BE) ? B : R) +#define R_B ((target == AV_PIX_FMT_RGB48LE || target == AV_PIX_FMT_RGB48BE || target == AV_PIX_FMT_RGBA64LE || target == AV_PIX_FMT_RGBA64BE) ? R : B) +#define B_R ((target == AV_PIX_FMT_RGB48LE || target == AV_PIX_FMT_RGB48BE || target == AV_PIX_FMT_RGBA64LE || target == AV_PIX_FMT_RGBA64BE) ? B : R) #define output_pixel(pos, val) \ if (isBE(target)) { \ AV_WB16(pos, val); \ @@ -735,13 +741,13 @@ yuv2rgba64_X_c_template(SwsContext *c, const int16_t *lumFilter, B = U * c->yuv2rgb_u2b_coeff; // 8bit: 30 - 22 = 8bit, 16bit: 30bit - 14 = 16bit - output_pixel(&dest[0], av_clip_uintp2(B_R + Y1, 30) >> 14); + 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(R_B + Y1, 30) >> 14); + output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14); output_pixel(&dest[3], av_clip_uintp2(A1 , 30) >> 14); - output_pixel(&dest[4], av_clip_uintp2(B_R + Y2, 30) >> 14); + output_pixel(&dest[4], av_clip_uintp2(R_B + Y2, 30) >> 14); output_pixel(&dest[5], av_clip_uintp2( G + Y2, 30) >> 14); - output_pixel(&dest[6], av_clip_uintp2(R_B + Y2, 30) >> 14); + output_pixel(&dest[6], av_clip_uintp2(B_R + Y2, 30) >> 14); output_pixel(&dest[7], av_clip_uintp2(A2 , 30) >> 14); dest += 8; } @@ -790,13 +796,13 @@ yuv2rgba64_2_c_template(SwsContext *c, const int32_t *buf[2], A2 += 1 << 13; } - output_pixel(&dest[0], av_clip_uintp2(B_R + Y1, 30) >> 14); + 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(R_B + Y1, 30) >> 14); + output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14); output_pixel(&dest[3], av_clip_uintp2(A1 , 30) >> 14); - output_pixel(&dest[4], av_clip_uintp2(B_R + Y2, 30) >> 14); + output_pixel(&dest[4], av_clip_uintp2(R_B + Y2, 30) >> 14); output_pixel(&dest[5], av_clip_uintp2( G + Y2, 30) >> 14); - output_pixel(&dest[6], av_clip_uintp2(R_B + Y2, 30) >> 14); + output_pixel(&dest[6], av_clip_uintp2(B_R + Y2, 30) >> 14); output_pixel(&dest[7], av_clip_uintp2(A2 , 30) >> 14); dest += 8; } @@ -839,13 +845,13 @@ yuv2rgba64_1_c_template(SwsContext *c, const int32_t *buf0, G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff; B = U * c->yuv2rgb_u2b_coeff; - output_pixel(&dest[0], av_clip_uintp2(B_R + Y1, 30) >> 14); + 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(R_B + Y1, 30) >> 14); + output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14); output_pixel(&dest[3], av_clip_uintp2(A1 , 30) >> 14); - output_pixel(&dest[4], av_clip_uintp2(B_R + Y2, 30) >> 14); + output_pixel(&dest[4], av_clip_uintp2(R_B + Y2, 30) >> 14); output_pixel(&dest[5], av_clip_uintp2( G + Y2, 30) >> 14); - output_pixel(&dest[6], av_clip_uintp2(R_B + Y2, 30) >> 14); + output_pixel(&dest[6], av_clip_uintp2(B_R + Y2, 30) >> 14); output_pixel(&dest[7], av_clip_uintp2(A2 , 30) >> 14); dest += 8; } @@ -878,13 +884,13 @@ yuv2rgba64_1_c_template(SwsContext *c, const int32_t *buf0, G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff; B = U * c->yuv2rgb_u2b_coeff; - output_pixel(&dest[0], av_clip_uintp2(B_R + Y1, 30) >> 14); + 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(R_B + Y1, 30) >> 14); + output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14); output_pixel(&dest[3], av_clip_uintp2(A1 , 30) >> 14); - output_pixel(&dest[4], av_clip_uintp2(B_R + Y2, 30) >> 14); + output_pixel(&dest[4], av_clip_uintp2(R_B + Y2, 30) >> 14); output_pixel(&dest[5], av_clip_uintp2( G + Y2, 30) >> 14); - output_pixel(&dest[6], av_clip_uintp2(R_B + Y2, 30) >> 14); + output_pixel(&dest[6], av_clip_uintp2(B_R + Y2, 30) >> 14); output_pixel(&dest[7], av_clip_uintp2(A2 , 30) >> 14); dest += 8; } @@ -1117,6 +1123,10 @@ YUV2PACKED16WRAPPER(yuv2, rgba64, rgba64be, AV_PIX_FMT_RGBA64BE, 1) YUV2PACKED16WRAPPER(yuv2, rgba64, rgba64le, AV_PIX_FMT_RGBA64LE, 1) YUV2PACKED16WRAPPER(yuv2, rgba64, rgbx64be, AV_PIX_FMT_RGBA64BE, 0) YUV2PACKED16WRAPPER(yuv2, rgba64, rgbx64le, AV_PIX_FMT_RGBA64LE, 0) +YUV2PACKED16WRAPPER(yuv2, rgba64, bgra64be, AV_PIX_FMT_BGRA64BE, 1) +YUV2PACKED16WRAPPER(yuv2, rgba64, bgra64le, AV_PIX_FMT_BGRA64LE, 1) +YUV2PACKED16WRAPPER(yuv2, rgba64, bgrx64be, AV_PIX_FMT_BGRA64BE, 0) +YUV2PACKED16WRAPPER(yuv2, rgba64, bgrx64le, AV_PIX_FMT_BGRA64LE, 0) /* * Write out 2 RGB pixels in the target pixel format. This function takes a @@ -1508,24 +1518,71 @@ static av_always_inline void yuv2rgb_write_full(SwsContext *c, case AV_PIX_FMT_RGB8: { int r,g,b; - R >>= 22; - G >>= 22; - B >>= 22; - R += (7*err[0] + 1*c->dither_error[0][i] + 5*c->dither_error[0][i+1] + 3*c->dither_error[0][i+2])>>4; - G += (7*err[1] + 1*c->dither_error[1][i] + 5*c->dither_error[1][i+1] + 3*c->dither_error[1][i+2])>>4; - B += (7*err[2] + 1*c->dither_error[2][i] + 5*c->dither_error[2][i+1] + 3*c->dither_error[2][i+2])>>4; - c->dither_error[0][i] = err[0]; - c->dither_error[1][i] = err[1]; - c->dither_error[2][i] = err[2]; - r = R >> (isrgb8 ? 5 : 7); - g = G >> (isrgb8 ? 5 : 6); - b = B >> (isrgb8 ? 6 : 7); - r = av_clip(r, 0, isrgb8 ? 7 : 1); - g = av_clip(g, 0, isrgb8 ? 7 : 3); - b = av_clip(b, 0, isrgb8 ? 3 : 1); - err[0] = R - r*(isrgb8 ? 36 : 255); - err[1] = G - g*(isrgb8 ? 36 : 85); - err[2] = B - b*(isrgb8 ? 85 : 255); + + switch (c->dither) { + default: + case SWS_DITHER_AUTO: + case SWS_DITHER_ED: + R >>= 22; + G >>= 22; + B >>= 22; + R += (7*err[0] + 1*c->dither_error[0][i] + 5*c->dither_error[0][i+1] + 3*c->dither_error[0][i+2])>>4; + G += (7*err[1] + 1*c->dither_error[1][i] + 5*c->dither_error[1][i+1] + 3*c->dither_error[1][i+2])>>4; + B += (7*err[2] + 1*c->dither_error[2][i] + 5*c->dither_error[2][i+1] + 3*c->dither_error[2][i+2])>>4; + c->dither_error[0][i] = err[0]; + c->dither_error[1][i] = err[1]; + c->dither_error[2][i] = err[2]; + r = R >> (isrgb8 ? 5 : 7); + g = G >> (isrgb8 ? 5 : 6); + b = B >> (isrgb8 ? 6 : 7); + r = av_clip(r, 0, isrgb8 ? 7 : 1); + g = av_clip(g, 0, isrgb8 ? 7 : 3); + b = av_clip(b, 0, isrgb8 ? 3 : 1); + err[0] = R - r*(isrgb8 ? 36 : 255); + err[1] = G - g*(isrgb8 ? 36 : 85); + err[2] = B - b*(isrgb8 ? 85 : 255); + break; + case SWS_DITHER_A_DITHER: + if (isrgb8) { + /* see http://pippin.gimp.org/a_dither/ for details/origin */ +#define A_DITHER(u,v) (((((u)+((v)*236))*119)&0xff)) + r = (((R >> 19) + A_DITHER(i,y) -96)>>8); + g = (((G >> 19) + A_DITHER(i + 17,y) - 96)>>8); + b = (((B >> 20) + A_DITHER(i + 17*2,y) -96)>>8); + r = av_clip(r, 0, 7); + g = av_clip(g, 0, 7); + b = av_clip(b, 0, 3); + } else { + r = (((R >> 21) + A_DITHER(i,y)-256)>>8); + g = (((G >> 19) + A_DITHER(i + 17,y)-256)>>8); + b = (((B >> 21) + A_DITHER(i + 17*2,y)-256)>>8); + r = av_clip(r, 0, 1); + g = av_clip(g, 0, 3); + b = av_clip(b, 0, 1); + } + break; + case SWS_DITHER_X_DITHER: + if (isrgb8) { + /* see http://pippin.gimp.org/a_dither/ for details/origin */ +#define X_DITHER(u,v) (((((u)^((v)*237))*181)&0x1ff)/2) + r = (((R >> 19) + X_DITHER(i,y) - 96)>>8); + g = (((G >> 19) + X_DITHER(i + 17,y) - 96)>>8); + b = (((B >> 20) + X_DITHER(i + 17*2,y) - 96)>>8); + r = av_clip(r, 0, 7); + g = av_clip(g, 0, 7); + b = av_clip(b, 0, 3); + } else { + r = (((R >> 21) + X_DITHER(i,y)-256)>>8); + g = (((G >> 19) + X_DITHER(i + 17,y)-256)>>8); + b = (((B >> 21) + X_DITHER(i + 17*2,y)-256)>>8); + r = av_clip(r, 0, 1); + g = av_clip(g, 0, 3); + b = av_clip(b, 0, 1); + } + + break; + } + if(target == AV_PIX_FMT_BGR4_BYTE) { dest[0] = r + 2*g + 8*b; } else if(target == AV_PIX_FMT_RGB4_BYTE) { @@ -1994,6 +2051,34 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, *yuv2packedX = yuv2rgbx64be_X_c; } break; + case AV_PIX_FMT_BGRA64LE: +#if CONFIG_SWSCALE_ALPHA + if (c->alpPixBuf) { + *yuv2packed1 = yuv2bgra64le_1_c; + *yuv2packed2 = yuv2bgra64le_2_c; + *yuv2packedX = yuv2bgra64le_X_c; + } else +#endif /* CONFIG_SWSCALE_ALPHA */ + { + *yuv2packed1 = yuv2bgrx64le_1_c; + *yuv2packed2 = yuv2bgrx64le_2_c; + *yuv2packedX = yuv2bgrx64le_X_c; + } + break; + case AV_PIX_FMT_BGRA64BE: +#if CONFIG_SWSCALE_ALPHA + if (c->alpPixBuf) { + *yuv2packed1 = yuv2bgra64be_1_c; + *yuv2packed2 = yuv2bgra64be_2_c; + *yuv2packedX = yuv2bgra64be_X_c; + } else +#endif /* CONFIG_SWSCALE_ALPHA */ + { + *yuv2packed1 = yuv2bgrx64be_1_c; + *yuv2packed2 = yuv2bgrx64be_2_c; + *yuv2packedX = yuv2bgrx64be_X_c; + } + break; case AV_PIX_FMT_RGB48LE: *yuv2packed1 = yuv2rgb48le_1_c; *yuv2packed2 = yuv2rgb48le_2_c; @@ -2126,6 +2211,11 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, *yuv2packed2 = yuv2yuyv422_2_c; *yuv2packedX = yuv2yuyv422_X_c; break; + case AV_PIX_FMT_YVYU422: + *yuv2packed1 = yuv2yvyu422_1_c; + *yuv2packed2 = yuv2yvyu422_2_c; + *yuv2packedX = yuv2yvyu422_X_c; + break; case AV_PIX_FMT_UYVY422: *yuv2packed1 = yuv2uyvy422_1_c; *yuv2packed2 = yuv2uyvy422_2_c; diff --git a/libswscale/sparc/Makefile b/libswscale/sparc/Makefile deleted file mode 100644 index 2351ba45c..000000000 --- a/libswscale/sparc/Makefile +++ /dev/null @@ -1 +0,0 @@ -VIS-OBJS += sparc/yuv2rgb_vis.o \ diff --git a/libswscale/sparc/yuv2rgb_vis.c b/libswscale/sparc/yuv2rgb_vis.c deleted file mode 100644 index ed008377a..000000000 --- a/libswscale/sparc/yuv2rgb_vis.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * VIS optimized software YUV to RGB converter - * Copyright (c) 2007 Denes Balatoni - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include "libavutil/attributes.h" -#include "libswscale/swscale.h" -#include "libswscale/swscale_internal.h" - -#define YUV2RGB_INIT \ - "wr %%g0, 0x10, %%gsr \n\t" \ - "ldd [%5], %%f32 \n\t" \ - "ldd [%5 + 8], %%f34 \n\t" \ - "ldd [%5 + 16], %%f36 \n\t" \ - "ldd [%5 + 24], %%f38 \n\t" \ - "ldd [%5 + 32], %%f40 \n\t" \ - "ldd [%5 + 40], %%f42 \n\t" \ - "ldd [%5 + 48], %%f44 \n\t" \ - "ldd [%5 + 56], %%f46 \n\t" \ - "ldd [%5 + 64], %%f48 \n\t" \ - "ldd [%5 + 72], %%f50 \n\t" - -#define YUV2RGB_KERNEL \ - /* ^^^^ f0=Y f3=u f5=v */ \ - "fmul8x16 %%f3, %%f48, %%f6 \n\t" \ - "fmul8x16 %%f19, %%f48, %%f22 \n\t" \ - "fmul8x16 %%f5, %%f44, %%f8 \n\t" \ - "fmul8x16 %%f21, %%f44, %%f24 \n\t" \ - "fmul8x16 %%f0, %%f42, %%f0 \n\t" \ - "fmul8x16 %%f16, %%f42, %%f16 \n\t" \ - "fmul8x16 %%f3, %%f50, %%f2 \n\t" \ - "fmul8x16 %%f19, %%f50, %%f18 \n\t" \ - "fmul8x16 %%f5, %%f46, %%f4 \n\t" \ - "fmul8x16 %%f21, %%f46, %%f20 \n\t" \ - \ - "fpsub16 %%f6, %%f34, %%f6 \n\t" /* 1 */ \ - "fpsub16 %%f22, %%f34, %%f22 \n\t" /* 1 */ \ - "fpsub16 %%f8, %%f38, %%f8 \n\t" /* 3 */ \ - "fpsub16 %%f24, %%f38, %%f24 \n\t" /* 3 */ \ - "fpsub16 %%f0, %%f32, %%f0 \n\t" /* 0 */ \ - "fpsub16 %%f16, %%f32, %%f16 \n\t" /* 0 */ \ - "fpsub16 %%f2, %%f36, %%f2 \n\t" /* 2 */ \ - "fpsub16 %%f18, %%f36, %%f18 \n\t" /* 2 */ \ - "fpsub16 %%f4, %%f40, %%f4 \n\t" /* 4 */ \ - "fpsub16 %%f20, %%f40, %%f20 \n\t" /* 4 */ \ - \ - "fpadd16 %%f0, %%f8, %%f8 \n\t" /* Gt */ \ - "fpadd16 %%f16, %%f24, %%f24 \n\t" /* Gt */ \ - "fpadd16 %%f0, %%f4, %%f4 \n\t" /* R */ \ - "fpadd16 %%f16, %%f20, %%f20 \n\t" /* R */ \ - "fpadd16 %%f0, %%f6, %%f6 \n\t" /* B */ \ - "fpadd16 %%f16, %%f22, %%f22 \n\t" /* B */ \ - "fpadd16 %%f8, %%f2, %%f2 \n\t" /* G */ \ - "fpadd16 %%f24, %%f18, %%f18 \n\t" /* G */ \ - \ - "fpack16 %%f4, %%f4 \n\t" \ - "fpack16 %%f20, %%f20 \n\t" \ - "fpack16 %%f6, %%f6 \n\t" \ - "fpack16 %%f22, %%f22 \n\t" \ - "fpack16 %%f2, %%f2 \n\t" \ - "fpack16 %%f18, %%f18 \n\t" - -// FIXME: must be changed to set alpha to 255 instead of 0 -static int vis_420P_ARGB32(SwsContext *c, uint8_t *src[], int srcStride[], - int srcSliceY, int srcSliceH, - uint8_t *dst[], int dstStride[]) -{ - int y, out1, out2, out3, out4, out5, out6; - - for (y = 0; y < srcSliceH; ++y) - __asm__ volatile ( - YUV2RGB_INIT - "wr %%g0, 0xd2, %%asi \n\t" /* ASI_FL16_P */ - "1: \n\t" - "ldda [%1] %%asi, %%f2 \n\t" - "ldda [%1 + 2] %%asi, %%f18 \n\t" - "ldda [%2] %%asi, %%f4 \n\t" - "ldda [%2 + 2] %%asi, %%f20 \n\t" - "ld [%0], %%f0 \n\t" - "ld [%0+4], %%f16 \n\t" - "fpmerge %%f3, %%f3, %%f2 \n\t" - "fpmerge %%f19, %%f19, %%f18 \n\t" - "fpmerge %%f5, %%f5, %%f4 \n\t" - "fpmerge %%f21, %%f21, %%f20 \n\t" - YUV2RGB_KERNEL - "fzero %%f0 \n\t" - "fpmerge %%f4, %%f6, %%f8 \n\t" // r, b, t1 - "fpmerge %%f20, %%f22, %%f24 \n\t" // r, b, t1 - "fpmerge %%f0, %%f2, %%f10 \n\t" // 0, g, t2 - "fpmerge %%f0, %%f18, %%f26 \n\t" // 0, g, t2 - "fpmerge %%f10, %%f8, %%f4 \n\t" // t2, t1, msb - "fpmerge %%f26, %%f24, %%f20 \n\t" // t2, t1, msb - "fpmerge %%f11, %%f9, %%f6 \n\t" // t2, t1, lsb - "fpmerge %%f27, %%f25, %%f22 \n\t" // t2, t1, lsb - "std %%f4, [%3] \n\t" - "std %%f20, [%3 + 16] \n\t" - "std %%f6, [%3 + 8] \n\t" - "std %%f22, [%3 + 24] \n\t" - - "add %0, 8, %0 \n\t" - "add %1, 4, %1 \n\t" - "add %2, 4, %2 \n\t" - "subcc %4, 8, %4 \n\t" - "bne 1b \n\t" - "add %3, 32, %3 \n\t" // delay slot - : "=r" (out1), "=r" (out2), "=r" (out3), "=r" (out4), "=r" (out5), "=r" (out6) - : "0" (src[0] + (y + srcSliceY) * srcStride[0]), "1" (src[1] + ((y + srcSliceY) >> 1) * srcStride[1]), - "2" (src[2] + ((y + srcSliceY) >> 1) * srcStride[2]), "3" (dst[0] + (y + srcSliceY) * dstStride[0]), - "4" (c->dstW), - "5" (c->sparc_coeffs) - ); - - return srcSliceH; -} - -// FIXME: must be changed to set alpha to 255 instead of 0 -static int vis_422P_ARGB32(SwsContext *c, uint8_t *src[], int srcStride[], - int srcSliceY, int srcSliceH, - uint8_t *dst[], int dstStride[]) -{ - int y, out1, out2, out3, out4, out5, out6; - - for (y = 0; y < srcSliceH; ++y) - __asm__ volatile ( - YUV2RGB_INIT - "wr %%g0, 0xd2, %%asi \n\t" /* ASI_FL16_P */ - "1: \n\t" - "ldda [%1] %%asi, %%f2 \n\t" - "ldda [%1 + 2] %%asi, %%f18 \n\t" - "ldda [%2] %%asi, %%f4 \n\t" - "ldda [%2 + 2] %%asi, %%f20 \n\t" - "ld [%0], %%f0 \n\t" - "ld [%0 + 4], %%f16 \n\t" - "fpmerge %%f3, %%f3, %%f2 \n\t" - "fpmerge %%f19, %%f19, %%f18 \n\t" - "fpmerge %%f5, %%f5, %%f4 \n\t" - "fpmerge %%f21, %%f21, %%f20 \n\t" - YUV2RGB_KERNEL - "fzero %%f0 \n\t" - "fpmerge %%f4, %%f6, %%f8 \n\t" // r,b,t1 - "fpmerge %%f20, %%f22, %%f24 \n\t" // r,b,t1 - "fpmerge %%f0, %%f2, %%f10 \n\t" // 0,g,t2 - "fpmerge %%f0, %%f18, %%f26 \n\t" // 0,g,t2 - "fpmerge %%f10, %%f8, %%f4 \n\t" // t2,t1,msb - "fpmerge %%f26, %%f24, %%f20 \n\t" // t2,t1,msb - "fpmerge %%f11, %%f9, %%f6 \n\t" // t2,t1,lsb - "fpmerge %%f27, %%f25, %%f22 \n\t" // t2,t1,lsb - "std %%f4, [%3] \n\t" - "std %%f20, [%3 + 16] \n\t" - "std %%f6, [%3 + 8] \n\t" - "std %%f22, [%3 + 24] \n\t" - - "add %0, 8, %0 \n\t" - "add %1, 4, %1 \n\t" - "add %2, 4, %2 \n\t" - "subcc %4, 8, %4 \n\t" - "bne 1b \n\t" - "add %3, 32, %3 \n\t" //delay slot - : "=r" (out1), "=r" (out2), "=r" (out3), "=r" (out4), "=r" (out5), "=r" (out6) - : "0" (src[0] + (y + srcSliceY) * srcStride[0]), "1" (src[1] + (y + srcSliceY) * srcStride[1]), - "2" (src[2] + (y + srcSliceY) * srcStride[2]), "3" (dst[0] + (y + srcSliceY) * dstStride[0]), - "4" (c->dstW), - "5" (c->sparc_coeffs) - ); - - return srcSliceH; -} - -av_cold SwsFunc ff_yuv2rgb_init_vis(SwsContext *c) -{ - c->sparc_coeffs[5] = c->yCoeff; - c->sparc_coeffs[6] = c->vgCoeff; - c->sparc_coeffs[7] = c->vrCoeff; - c->sparc_coeffs[8] = c->ubCoeff; - c->sparc_coeffs[9] = c->ugCoeff; - - c->sparc_coeffs[0] = (((int16_t)c->yOffset * (int16_t)c->yCoeff >> 11) & 0xffff) * 0x0001000100010001ULL; - c->sparc_coeffs[1] = (((int16_t)c->uOffset * (int16_t)c->ubCoeff >> 11) & 0xffff) * 0x0001000100010001ULL; - c->sparc_coeffs[2] = (((int16_t)c->uOffset * (int16_t)c->ugCoeff >> 11) & 0xffff) * 0x0001000100010001ULL; - c->sparc_coeffs[3] = (((int16_t)c->vOffset * (int16_t)c->vgCoeff >> 11) & 0xffff) * 0x0001000100010001ULL; - c->sparc_coeffs[4] = (((int16_t)c->vOffset * (int16_t)c->vrCoeff >> 11) & 0xffff) * 0x0001000100010001ULL; - - if (c->dstFormat == AV_PIX_FMT_RGB32 && c->srcFormat == AV_PIX_FMT_YUV422P && (c->dstW & 7) == 0) { - av_log(c, AV_LOG_INFO, - "SPARC VIS accelerated YUV422P -> RGB32 (WARNING: alpha value is wrong)\n"); - return vis_422P_ARGB32; - } else if (c->dstFormat == AV_PIX_FMT_RGB32 && c->srcFormat == AV_PIX_FMT_YUV420P && (c->dstW & 7) == 0) { - av_log(c, AV_LOG_INFO, - "SPARC VIS accelerated YUV420P -> RGB32 (WARNING: alpha value is wrong)\n"); - return vis_420P_ARGB32; - } - return NULL; -} diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 4827aa69b..9919d41ad 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -414,8 +414,8 @@ static int swscale(SwsContext *c, const uint8_t *src[], DEBUG_BUFFERS("vLumFilterSize: %d vLumBufSize: %d vChrFilterSize: %d vChrBufSize: %d\n", vLumFilterSize, vLumBufSize, vChrFilterSize, vChrBufSize); - if (dstStride[0]%16 !=0 || dstStride[1]%16 !=0 || - dstStride[2]%16 !=0 || dstStride[3]%16 != 0) { + if (dstStride[0]&15 || dstStride[1]&15 || + dstStride[2]&15 || dstStride[3]&15) { static int warnedAlready = 0; // FIXME maybe move this into the context if (flags & SWS_PRINT_INFO && !warnedAlready) { av_log(c, AV_LOG_WARNING, @@ -425,10 +425,10 @@ static int swscale(SwsContext *c, const uint8_t *src[], } } - if ( (uintptr_t)dst[0]%16 || (uintptr_t)dst[1]%16 || (uintptr_t)dst[2]%16 - || (uintptr_t)src[0]%16 || (uintptr_t)src[1]%16 || (uintptr_t)src[2]%16 - || dstStride[0]%16 || dstStride[1]%16 || dstStride[2]%16 || dstStride[3]%16 - || srcStride[0]%16 || srcStride[1]%16 || srcStride[2]%16 || srcStride[3]%16 + if ( (uintptr_t)dst[0]&15 || (uintptr_t)dst[1]&15 || (uintptr_t)dst[2]&15 + || (uintptr_t)src[0]&15 || (uintptr_t)src[1]&15 || (uintptr_t)src[2]&15 + || dstStride[0]&15 || dstStride[1]&15 || dstStride[2]&15 || dstStride[3]&15 + || srcStride[0]&15 || srcStride[1]&15 || srcStride[2]&15 || srcStride[3]&15 ) { static int warnedAlready=0; int cpu_flags = av_get_cpu_flags(); @@ -705,6 +705,31 @@ static int swscale(SwsContext *c, const uint8_t *src[], return dstY - lastDstY; } +av_cold void ff_sws_init_range_convert(SwsContext *c) +{ + c->lumConvertRange = NULL; + c->chrConvertRange = NULL; + if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) { + if (c->dstBpc <= 14) { + if (c->srcRange) { + c->lumConvertRange = lumRangeFromJpeg_c; + c->chrConvertRange = chrRangeFromJpeg_c; + } else { + c->lumConvertRange = lumRangeToJpeg_c; + c->chrConvertRange = chrRangeToJpeg_c; + } + } else { + if (c->srcRange) { + c->lumConvertRange = lumRangeFromJpeg16_c; + c->chrConvertRange = chrRangeFromJpeg16_c; + } else { + c->lumConvertRange = lumRangeToJpeg16_c; + c->chrConvertRange = chrRangeToJpeg16_c; + } + } + } +} + static av_cold void sws_init_swscale(SwsContext *c) { enum AVPixelFormat srcFormat = c->srcFormat; @@ -731,25 +756,7 @@ static av_cold void sws_init_swscale(SwsContext *c) : hScale16To15_c; } - if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) { - if (c->dstBpc <= 14) { - if (c->srcRange) { - c->lumConvertRange = lumRangeFromJpeg_c; - c->chrConvertRange = chrRangeFromJpeg_c; - } else { - c->lumConvertRange = lumRangeToJpeg_c; - c->chrConvertRange = chrRangeToJpeg_c; - } - } else { - if (c->srcRange) { - c->lumConvertRange = lumRangeFromJpeg16_c; - c->chrConvertRange = chrRangeFromJpeg16_c; - } else { - c->lumConvertRange = lumRangeToJpeg16_c; - c->chrConvertRange = chrRangeToJpeg16_c; - } - } - } + ff_sws_init_range_convert(c); if (!(isGray(srcFormat) || isGray(c->dstFormat) || srcFormat == AV_PIX_FMT_MONOBLACK || srcFormat == AV_PIX_FMT_MONOWHITE)) @@ -952,9 +959,9 @@ int attribute_align_arg sws_scale(struct SwsContext *c, if (usePal(c->srcFormat)) { for (i = 0; i < 256; i++) { - int p, r, g, b, y, u, v, a = 0xff; + int r, g, b, y, u, v, a = 0xff; if (c->srcFormat == AV_PIX_FMT_PAL8) { - p = ((const uint32_t *)(srcSlice[1]))[i]; + uint32_t p = ((const uint32_t *)(srcSlice[1]))[i]; a = (p >> 24) & 0xFF; r = (p >> 16) & 0xFF; g = (p >> 8) & 0xFF; diff --git a/libswscale/swscale.h b/libswscale/swscale.h index 25c8b5e98..e6bb1a84d 100644 --- a/libswscale/swscale.h +++ b/libswscale/swscale.h @@ -92,7 +92,9 @@ const char *swscale_license(void); #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 diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index c2c23a08e..8d2d56acb 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -39,7 +39,7 @@ #define YUVRGB_TABLE_HEADROOM 128 -#define MAX_FILTER_SIZE 256 +#define MAX_FILTER_SIZE SWS_MAX_FILTER_SIZE #define DITHER1XBPP @@ -66,6 +66,8 @@ typedef enum SwsDither { SWS_DITHER_AUTO, SWS_DITHER_BAYER, SWS_DITHER_ED, + SWS_DITHER_A_DITHER, + SWS_DITHER_X_DITHER, NB_SWS_DITHER, } SwsDither; @@ -368,7 +370,7 @@ typedef struct SwsContext { uint8_t *table_rV[256 + 2*YUVRGB_TABLE_HEADROOM]; uint8_t *table_gU[256 + 2*YUVRGB_TABLE_HEADROOM]; uint8_t *table_bU[256 + 2*YUVRGB_TABLE_HEADROOM]; - DECLARE_ALIGNED(16, int32_t, input_rgb2yuv_table)[16+40*4]; // This table can contain both C and SIMD formatted values, teh C vales are always at the XY_IDX points + DECLARE_ALIGNED(16, int32_t, input_rgb2yuv_table)[16+40*4]; // This table can contain both C and SIMD formatted values, the C vales are always at the XY_IDX points #define RY_IDX 0 #define GY_IDX 1 #define BY_IDX 2 @@ -415,18 +417,19 @@ typedef struct SwsContext { #define U_OFFSET "9*8" #define V_OFFSET "10*8" #define LUM_MMX_FILTER_OFFSET "11*8" -#define CHR_MMX_FILTER_OFFSET "11*8+4*4*256" -#define DSTW_OFFSET "11*8+4*4*256*2" //do not change, it is hardcoded in the ASM -#define ESP_OFFSET "11*8+4*4*256*2+8" -#define VROUNDER_OFFSET "11*8+4*4*256*2+16" -#define U_TEMP "11*8+4*4*256*2+24" -#define V_TEMP "11*8+4*4*256*2+32" -#define Y_TEMP "11*8+4*4*256*2+40" -#define ALP_MMX_FILTER_OFFSET "11*8+4*4*256*2+48" -#define UV_OFF_PX "11*8+4*4*256*3+48" -#define UV_OFF_BYTE "11*8+4*4*256*3+56" -#define DITHER16 "11*8+4*4*256*3+64" -#define DITHER32 "11*8+4*4*256*3+80" +#define CHR_MMX_FILTER_OFFSET "11*8+4*4*"AV_STRINGIFY(MAX_FILTER_SIZE) +#define DSTW_OFFSET "11*8+4*4*"AV_STRINGIFY(MAX_FILTER_SIZE)"*2" +#define ESP_OFFSET "11*8+4*4*"AV_STRINGIFY(MAX_FILTER_SIZE)"*2+8" +#define VROUNDER_OFFSET "11*8+4*4*"AV_STRINGIFY(MAX_FILTER_SIZE)"*2+16" +#define U_TEMP "11*8+4*4*"AV_STRINGIFY(MAX_FILTER_SIZE)"*2+24" +#define V_TEMP "11*8+4*4*"AV_STRINGIFY(MAX_FILTER_SIZE)"*2+32" +#define Y_TEMP "11*8+4*4*"AV_STRINGIFY(MAX_FILTER_SIZE)"*2+40" +#define ALP_MMX_FILTER_OFFSET "11*8+4*4*"AV_STRINGIFY(MAX_FILTER_SIZE)"*2+48" +#define UV_OFF_PX "11*8+4*4*"AV_STRINGIFY(MAX_FILTER_SIZE)"*3+48" +#define UV_OFF_BYTE "11*8+4*4*"AV_STRINGIFY(MAX_FILTER_SIZE)"*3+56" +#define DITHER16 "11*8+4*4*"AV_STRINGIFY(MAX_FILTER_SIZE)"*3+64" +#define DITHER32 "11*8+4*4*"AV_STRINGIFY(MAX_FILTER_SIZE)"*3+80" +#define DITHER32_INT (11*8+4*4*MAX_FILTER_SIZE*3+80) // value equal to above, used for checking that the struct hasn't been changed by mistake DECLARE_ALIGNED(8, uint64_t, redDither); DECLARE_ALIGNED(8, uint64_t, greenDither); @@ -470,23 +473,6 @@ typedef struct SwsContext { vector signed short *vYCoeffsBank, *vCCoeffsBank; #endif -#if ARCH_BFIN - DECLARE_ALIGNED(4, uint32_t, oy); - DECLARE_ALIGNED(4, uint32_t, oc); - DECLARE_ALIGNED(4, uint32_t, zero); - DECLARE_ALIGNED(4, uint32_t, cy); - DECLARE_ALIGNED(4, uint32_t, crv); - DECLARE_ALIGNED(4, uint32_t, rmask); - DECLARE_ALIGNED(4, uint32_t, cbu); - DECLARE_ALIGNED(4, uint32_t, bmask); - DECLARE_ALIGNED(4, uint32_t, cgu); - DECLARE_ALIGNED(4, uint32_t, cgv); - DECLARE_ALIGNED(4, uint32_t, gmask); -#endif - -#if HAVE_VIS - DECLARE_ALIGNED(8, uint64_t, sparc_coeffs)[10]; -#endif int use_mmx_vfilter; /* pre defined color-spaces gamma */ @@ -618,10 +604,10 @@ void ff_yuv2rgb_init_tables_ppc(SwsContext *c, const int inv_table[4], void updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrBufIndex, int lastInLumBuf, int lastInChrBuf); +av_cold void ff_sws_init_range_convert(SwsContext *c); + SwsFunc ff_yuv2rgb_init_x86(SwsContext *c); -SwsFunc ff_yuv2rgb_init_vis(SwsContext *c); SwsFunc ff_yuv2rgb_init_ppc(SwsContext *c); -SwsFunc ff_yuv2rgb_init_bfin(SwsContext *c); #if FF_API_SWS_FORMAT_NAME /** @@ -691,8 +677,6 @@ static av_always_inline int isRGB(enum AVPixelFormat pix_fmt) ( \ (x) == AV_PIX_FMT_RGB48BE || \ (x) == AV_PIX_FMT_RGB48LE || \ - (x) == AV_PIX_FMT_RGBA64BE || \ - (x) == AV_PIX_FMT_RGBA64LE || \ (x) == AV_PIX_FMT_RGB32 || \ (x) == AV_PIX_FMT_RGB32_1 || \ (x) == AV_PIX_FMT_RGB24 || \ @@ -705,6 +689,8 @@ static av_always_inline int isRGB(enum AVPixelFormat pix_fmt) (x) == AV_PIX_FMT_RGB8 || \ (x) == AV_PIX_FMT_RGB4 || \ (x) == AV_PIX_FMT_RGB4_BYTE || \ + (x) == AV_PIX_FMT_RGBA64BE || \ + (x) == AV_PIX_FMT_RGBA64LE || \ (x) == AV_PIX_FMT_MONOBLACK || \ (x) == AV_PIX_FMT_MONOWHITE \ ) @@ -712,8 +698,6 @@ static av_always_inline int isRGB(enum AVPixelFormat pix_fmt) ( \ (x) == AV_PIX_FMT_BGR48BE || \ (x) == AV_PIX_FMT_BGR48LE || \ - (x) == AV_PIX_FMT_BGRA64BE || \ - (x) == AV_PIX_FMT_BGRA64LE || \ (x) == AV_PIX_FMT_BGR32 || \ (x) == AV_PIX_FMT_BGR32_1 || \ (x) == AV_PIX_FMT_BGR24 || \ @@ -726,6 +710,8 @@ static av_always_inline int isRGB(enum AVPixelFormat pix_fmt) (x) == AV_PIX_FMT_BGR8 || \ (x) == AV_PIX_FMT_BGR4 || \ (x) == AV_PIX_FMT_BGR4_BYTE || \ + (x) == AV_PIX_FMT_BGRA64BE || \ + (x) == AV_PIX_FMT_BGRA64LE || \ (x) == AV_PIX_FMT_MONOBLACK || \ (x) == AV_PIX_FMT_MONOWHITE \ ) @@ -785,6 +771,7 @@ static av_always_inline int isALPHA(enum AVPixelFormat pix_fmt) #define isPacked(x) ( \ (x)==AV_PIX_FMT_PAL8 \ || (x)==AV_PIX_FMT_YUYV422 \ + || (x)==AV_PIX_FMT_YVYU422 \ || (x)==AV_PIX_FMT_UYVY422 \ || (x)==AV_PIX_FMT_Y400A \ || isRGBinInt(x) \ @@ -849,7 +836,6 @@ extern const AVClass sws_context_class; * source and destination formats, bit depths, flags, etc. */ void ff_get_unscaled_swscale(SwsContext *c); -void ff_get_unscaled_swscale_bfin(SwsContext *c); void ff_get_unscaled_swscale_ppc(SwsContext *c); void ff_get_unscaled_swscale_arm(SwsContext *c); diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 5f1676b75..c5c36e417 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -1666,6 +1666,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_BGR555) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR565) || + 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_GBRP9) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP10) || @@ -1678,6 +1679,7 @@ void ff_get_unscaled_swscale(SwsContext *c) IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB555) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB565) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_XYZ12) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P9) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P10) || @@ -1747,13 +1749,10 @@ void ff_get_unscaled_swscale(SwsContext *c) c->swscale = planarCopyWrapper; } - if (ARCH_BFIN) - ff_get_unscaled_swscale_bfin(c); if (ARCH_PPC) ff_get_unscaled_swscale_ppc(c); // if (ARCH_ARM) // ff_get_unscaled_swscale_arm(c); - } /* Convert the palette to the same packed 32-bit format as the palette */ diff --git a/libswscale/utils.c b/libswscale/utils.c index fb4576a62..727415345 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -97,6 +97,7 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = { [AV_PIX_FMT_YUVJ411P] = { 1, 1 }, [AV_PIX_FMT_YUVJ422P] = { 1, 1 }, [AV_PIX_FMT_YUVJ444P] = { 1, 1 }, + [AV_PIX_FMT_YVYU422] = { 1, 1 }, [AV_PIX_FMT_UYVY422] = { 1, 1 }, [AV_PIX_FMT_UYYVYY411] = { 0, 0 }, [AV_PIX_FMT_BGR8] = { 1, 1 }, @@ -142,8 +143,8 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = { [AV_PIX_FMT_YUVA444P16LE]= { 1, 1 }, [AV_PIX_FMT_RGB48BE] = { 1, 1 }, [AV_PIX_FMT_RGB48LE] = { 1, 1 }, - [AV_PIX_FMT_RGBA64BE] = { 1, 1 }, - [AV_PIX_FMT_RGBA64LE] = { 1, 1 }, + [AV_PIX_FMT_RGBA64BE] = { 1, 1, 1 }, + [AV_PIX_FMT_RGBA64LE] = { 1, 1, 1 }, [AV_PIX_FMT_RGB565BE] = { 1, 1 }, [AV_PIX_FMT_RGB565LE] = { 1, 1 }, [AV_PIX_FMT_RGB555BE] = { 1, 1 }, @@ -165,8 +166,8 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = { [AV_PIX_FMT_Y400A] = { 1, 0 }, [AV_PIX_FMT_BGR48BE] = { 1, 1 }, [AV_PIX_FMT_BGR48LE] = { 1, 1 }, - [AV_PIX_FMT_BGRA64BE] = { 0, 0 }, - [AV_PIX_FMT_BGRA64LE] = { 0, 0 }, + [AV_PIX_FMT_BGRA64BE] = { 1, 1, 1 }, + [AV_PIX_FMT_BGRA64LE] = { 1, 1, 1 }, [AV_PIX_FMT_YUV420P9BE] = { 1, 1 }, [AV_PIX_FMT_YUV420P9LE] = { 1, 1 }, [AV_PIX_FMT_YUV420P10BE] = { 1, 1 }, @@ -311,13 +312,13 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, emms_c(); // FIXME should not be required but IS (even for non-MMX versions) // NOTE: the +3 is for the MMX(+1) / SSE(+3) scaler which reads over the end - FF_ALLOC_OR_GOTO(NULL, *filterPos, (dstW + 3) * sizeof(**filterPos), fail); + FF_ALLOC_ARRAY_OR_GOTO(NULL, *filterPos, (dstW + 3), sizeof(**filterPos), fail); if (FFABS(xInc - 0x10000) < 10 && srcPos == dstPos) { // unscaled int i; filterSize = 1; - FF_ALLOCZ_OR_GOTO(NULL, filter, - dstW * sizeof(*filter) * filterSize, fail); + FF_ALLOCZ_ARRAY_OR_GOTO(NULL, filter, + dstW, sizeof(*filter) * filterSize, fail); for (i = 0; i < dstW; i++) { filter[i * filterSize] = fone; @@ -327,8 +328,8 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, int i; int64_t xDstInSrc; filterSize = 1; - FF_ALLOC_OR_GOTO(NULL, filter, - dstW * sizeof(*filter) * filterSize, fail); + FF_ALLOC_ARRAY_OR_GOTO(NULL, filter, + dstW, sizeof(*filter) * filterSize, fail); xDstInSrc = ((dstPos*(int64_t)xInc)>>8) - ((srcPos*0x8000LL)>>7); for (i = 0; i < dstW; i++) { @@ -343,8 +344,8 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, int i; int64_t xDstInSrc; filterSize = 2; - FF_ALLOC_OR_GOTO(NULL, filter, - dstW * sizeof(*filter) * filterSize, fail); + FF_ALLOC_ARRAY_OR_GOTO(NULL, filter, + dstW, sizeof(*filter) * filterSize, fail); xDstInSrc = ((dstPos*(int64_t)xInc)>>8) - ((srcPos*0x8000LL)>>7); for (i = 0; i < dstW; i++) { @@ -384,8 +385,8 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, filterSize = FFMIN(filterSize, srcW - 2); filterSize = FFMAX(filterSize, 1); - FF_ALLOC_OR_GOTO(NULL, filter, - dstW * sizeof(*filter) * filterSize, fail); + FF_ALLOC_ARRAY_OR_GOTO(NULL, filter, + dstW, sizeof(*filter) * filterSize, fail); xDstInSrc = ((dstPos*(int64_t)xInc)>>7) - ((srcPos*0x10000LL)>>7); for (i = 0; i < dstW; i++) { @@ -492,7 +493,7 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, if (dstFilter) filter2Size += dstFilter->length - 1; av_assert0(filter2Size > 0); - FF_ALLOCZ_OR_GOTO(NULL, filter2, filter2Size * dstW * sizeof(*filter2), fail); + FF_ALLOCZ_ARRAY_OR_GOTO(NULL, filter2, dstW, filter2Size * sizeof(*filter2), fail); for (i = 0; i < dstW; i++) { int j, k; @@ -576,10 +577,13 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, av_assert0(minFilterSize > 0); filterSize = (minFilterSize + (filterAlign - 1)) & (~(filterAlign - 1)); av_assert0(filterSize > 0); - filter = av_malloc(filterSize * dstW * sizeof(*filter)); + filter = av_malloc_array(dstW, filterSize * sizeof(*filter)); + if (!filter) + goto fail; if (filterSize >= MAX_FILTER_SIZE * 16 / - ((flags & SWS_ACCURATE_RND) ? APCK_SIZE : 16) || !filter) { - av_log(NULL, AV_LOG_ERROR, "sws: filterSize %d is too large, try less extreme scaling or increase MAX_FILTER_SIZE and recompile\n", filterSize); + ((flags & SWS_ACCURATE_RND) ? APCK_SIZE : 16)) { + av_log(NULL, AV_LOG_ERROR, "sws: filterSize %d is too large, try less extreme scaling or set --sws-max-filter-size and recompile\n", + FF_CEIL_RSHIFT((filterSize+1) * ((flags & SWS_ACCURATE_RND) ? APCK_SIZE : 16), 4)); goto fail; } *outFilterSize = filterSize; @@ -631,8 +635,8 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, // Note the +1 is for the MMX scaler which reads over the end /* align at 16 for AltiVec (needed by hScale_altivec_real) */ - FF_ALLOCZ_OR_GOTO(NULL, *outFilter, - *outFilterSize * (dstW + 3) * sizeof(int16_t), fail); + FF_ALLOCZ_ARRAY_OR_GOTO(NULL, *outFilter, + (dstW + 3), *outFilterSize * sizeof(int16_t), fail); /* normalize & store in outFilter */ for (i = 0; i < dstW; i++) { @@ -979,6 +983,7 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], { const AVPixFmtDescriptor *desc_dst; const AVPixFmtDescriptor *desc_src; + int need_reinit = 0; memmove(c->srcColorspaceTable, inv_table, sizeof(int) * 4); memmove(c->dstColorspaceTable, table, sizeof(int) * 4); @@ -994,9 +999,16 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], c->brightness = brightness; c->contrast = contrast; c->saturation = saturation; + if (c->srcRange != srcRange || c->dstRange != dstRange) + need_reinit = 1; c->srcRange = srcRange; c->dstRange = dstRange; + //The srcBpc check is possibly wrong but we seem to lack a definitive reference to test this + //and what we have in ticket 2939 looks better with this check + if (need_reinit && c->srcBpc == 8) + ff_sws_init_range_convert(c); + if ((isYUV(c->dstFormat) || isGray(c->dstFormat)) && (isYUV(c->srcFormat) || isGray(c->srcFormat))) return -1; @@ -1097,6 +1109,8 @@ SwsContext *sws_alloc_context(void) { SwsContext *c = av_mallocz(sizeof(SwsContext)); + av_assert0(offsetof(SwsContext, redDither) + DITHER32_INT == offsetof(SwsContext, dither32)); + if (c) { c->av_class = &sws_context_class; av_opt_set_defaults(c); @@ -1250,7 +1264,7 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, if (c->dither == SWS_DITHER_AUTO) c->dither = (flags & SWS_FULL_CHR_H_INT) ? SWS_DITHER_ED : SWS_DITHER_BAYER; if (!(flags & SWS_FULL_CHR_H_INT)) { - if (c->dither == SWS_DITHER_ED) { + if (c->dither == SWS_DITHER_ED || c->dither == SWS_DITHER_A_DITHER || c->dither == SWS_DITHER_X_DITHER) { av_log(c, AV_LOG_DEBUG, "Desired dithering only supported in full chroma interpolation for destination format '%s'\n", av_get_pix_fmt_name(dstFormat)); @@ -1330,20 +1344,6 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, FF_ALLOC_OR_GOTO(c, c->formatConvBuffer, FFALIGN(srcW*2+78, 16) * 2, fail); - /* unscaled special cases */ - if (unscaled && !usesHFilter && !usesVFilter && - (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) { - ff_get_unscaled_swscale(c); - - if (c->swscale) { - if (flags & SWS_PRINT_INFO) - av_log(c, AV_LOG_INFO, - "using unscaled %s -> %s special converter\n", - av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); - return 0; - } - } - c->srcBpc = 1 + desc_src->comp[0].depth_minus1; if (c->srcBpc < 8) c->srcBpc = 8; @@ -1639,6 +1639,20 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, c->chrXInc, c->chrYInc); } + /* unscaled special cases */ + if (unscaled && !usesHFilter && !usesVFilter && + (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) { + ff_get_unscaled_swscale(c); + + if (c->swscale) { + if (flags & SWS_PRINT_INFO) + av_log(c, AV_LOG_INFO, + "using unscaled %s -> %s special converter\n", + av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); + return 0; + } + } + c->swscale = ff_getSwsFunc(c); return 0; fail: // FIXME replace things by appropriate error codes diff --git a/libswscale/version.h b/libswscale/version.h index 6f82d3d05..c0d4f8ab0 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -27,8 +27,8 @@ #include "libavutil/version.h" #define LIBSWSCALE_VERSION_MAJOR 2 -#define LIBSWSCALE_VERSION_MINOR 5 -#define LIBSWSCALE_VERSION_MICRO 102 +#define LIBSWSCALE_VERSION_MINOR 6 +#define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ LIBSWSCALE_VERSION_MINOR, \ @@ -55,5 +55,8 @@ #ifndef FF_API_SWS_FORMAT_NAME #define FF_API_SWS_FORMAT_NAME (LIBSWSCALE_VERSION_MAJOR < 3) #endif +#ifndef FF_API_ARCH_BFIN +#define FF_API_ARCH_BFIN (LIBSWSCALE_VERSION_MAJOR < 3) +#endif #endif /* SWSCALE_VERSION_H */ diff --git a/libswscale/x86/input.asm b/libswscale/x86/input.asm index 0c4f30e6e..af9afcaa5 100644 --- a/libswscale/x86/input.asm +++ b/libswscale/x86/input.asm @@ -347,8 +347,9 @@ cglobal %2%3%4%5 %+ ToY, 6, 6, %1, dst, src, u1, u2, w, table %if ARCH_X86_64 movsxd wq, wd %endif - lea srcq, [srcq+wq*4] add wq, wq + sub wq, mmsize - 1 + lea srcq, [srcq+wq*2] add dstq, wq neg wq mova m4, [rgb_Yrnd] @@ -373,6 +374,23 @@ cglobal %2%3%4%5 %+ ToY, 6, 6, %1, dst, src, u1, u2, w, table mova [dstq+wq], m0 add wq, mmsize jl .loop + sub wq, mmsize - 1 + jz .end + add srcq, 2*mmsize - 2 + add dstq, mmsize - 1 +.loop2: + movd m0, [srcq+wq*2+0] ; (byte) { Bx, Gx, Rx, xx }[0-3] + DEINTB 1, 0, 3, 2, 7 ; (word) { Gx, xx (m0/m2) or Bx, Rx (m1/m3) }[0-3]/[4-7] + pmaddwd m1, m5 ; (dword) { Bx*BY + Rx*RY }[0-3] + pmaddwd m0, m6 ; (dword) { Gx*GY }[0-3] + paddd m0, m4 ; += rgb_Yrnd + paddd m0, m1 ; (dword) { Y[0-3] } + psrad m0, 9 + packssdw m0, m0 ; (word) { Y[0-7] } + movd [dstq+wq], m0 + add wq, 2 + jl .loop2 +.end: REP_RET %endif ; %0 == 3 %endmacro @@ -406,6 +424,7 @@ cglobal %2%3%4%5 %+ ToUV, 7, 7, %1, dstU, dstV, u1, src, u2, w, table mov wq, r5m %endif add wq, wq + sub wq, mmsize - 1 add dstUq, wq add dstVq, wq lea srcq, [srcq+wq*2] @@ -449,6 +468,31 @@ cglobal %2%3%4%5 %+ ToUV, 7, 7, %1, dstU, dstV, u1, src, u2, w, table %endif ; mmsize == 8/16 add wq, mmsize jl .loop + sub wq, mmsize - 1 + jz .end + add srcq , 2*mmsize - 2 + add dstUq, mmsize - 1 + add dstVq, mmsize - 1 +.loop2: + movd m0, [srcq+wq*2] ; (byte) { Bx, Gx, Rx, xx }[0-3] + DEINTB 1, 0, 5, 4, 7 ; (word) { Gx, xx (m0/m4) or Bx, Rx (m1/m5) }[0-3]/[4-7] + pmaddwd m3, m1, coeffV1 ; (dword) { Bx*BV + Rx*RV }[0-3] + pmaddwd m2, m0, coeffV2 ; (dword) { Gx*GV }[0-3] + pmaddwd m1, coeffU1 ; (dword) { Bx*BU + Rx*RU }[0-3] + pmaddwd m0, coeffU2 ; (dword) { Gx*GU }[0-3] + paddd m3, m6 ; += rgb_UVrnd + paddd m1, m6 ; += rgb_UVrnd + paddd m2, m3 ; (dword) { V[0-3] } + paddd m0, m1 ; (dword) { U[0-3] } + psrad m0, 9 + psrad m2, 9 + packssdw m0, m0 ; (word) { U[0-7] } + packssdw m2, m2 ; (word) { V[0-7] } + movd [dstUq+wq], m0 + movd [dstVq+wq], m2 + add wq, 2 + jl .loop2 +.end: REP_RET %endif ; ARCH_X86_64 && %0 == 3 %endmacro diff --git a/libswscale/x86/rgb2rgb.c b/libswscale/x86/rgb2rgb.c index 8cc99c6c5..b80e869e0 100644 --- a/libswscale/x86/rgb2rgb.c +++ b/libswscale/x86/rgb2rgb.c @@ -76,6 +76,10 @@ DECLARE_ASM_CONST(8, uint64_t, mul15_mid) = 0x4200420042004200ULL; DECLARE_ASM_CONST(8, uint64_t, mul15_hi) = 0x0210021002100210ULL; DECLARE_ASM_CONST(8, uint64_t, mul16_mid) = 0x2080208020802080ULL; +DECLARE_ALIGNED(8, extern const uint64_t, ff_bgr2YOffset); +DECLARE_ALIGNED(8, extern const uint64_t, ff_w1111); +DECLARE_ALIGNED(8, extern const uint64_t, ff_bgr2UVOffset); + #define BY ((int)( 0.098*(1< +#include #include "libavutil/attributes.h" +#include "libavutil/x86/asm.h" #undef PREFETCH #undef MOVNTQ @@ -163,6 +165,7 @@ static inline void RENAME(rgb32tobgr24)(const uint8_t *src, uint8_t *dst, int sr "movq %%mm5, %%mm7 \n\t" STORE_BGR24_MMX :: "r"(dest), "r"(s) + NAMED_CONSTRAINTS_ADD(mask24l,mask24h) :"memory"); dest += 24; s += 32; @@ -785,6 +788,7 @@ static inline void RENAME(rgb15tobgr24)(const uint8_t *src, uint8_t *dst, int sr :"=m"(*d) :"r"(s),"m"(mask15b),"m"(mask15g),"m"(mask15r), "m"(mmx_null) + NAMED_CONSTRAINTS_ADD(mul15_mid,mul15_hi) :"memory"); /* borrowed 32 to 24 */ __asm__ volatile( @@ -801,6 +805,7 @@ static inline void RENAME(rgb15tobgr24)(const uint8_t *src, uint8_t *dst, int sr STORE_BGR24_MMX :: "r"(d), "m"(*s) + NAMED_CONSTRAINTS_ADD(mask24l,mask24h) :"memory"); d += 24; s += 8; @@ -890,6 +895,7 @@ static inline void RENAME(rgb16tobgr24)(const uint8_t *src, uint8_t *dst, int sr "por %%mm5, %%mm3 \n\t" :"=m"(*d) :"r"(s),"m"(mask16b),"m"(mask16g),"m"(mask16r),"m"(mmx_null) + NAMED_CONSTRAINTS_ADD(mul15_mid,mul16_mid,mul15_hi) :"memory"); /* borrowed 32 to 24 */ __asm__ volatile( @@ -906,6 +912,7 @@ static inline void RENAME(rgb16tobgr24)(const uint8_t *src, uint8_t *dst, int sr STORE_BGR24_MMX :: "r"(d), "m"(*s) + NAMED_CONSTRAINTS_ADD(mask24l,mask24h) :"memory"); d += 24; s += 8; @@ -966,6 +973,7 @@ static inline void RENAME(rgb15to32)(const uint8_t *src, uint8_t *dst, int src_s "pmulhw "MANGLE(mul15_hi)", %%mm2 \n\t" PACK_RGB32 ::"r"(d),"r"(s),"m"(mask15b),"m"(mask15g),"m"(mask15r) ,"m"(mul15_mid) + NAMED_CONSTRAINTS_ADD(mul15_hi) :"memory"); d += 16; s += 4; @@ -1009,6 +1017,7 @@ static inline void RENAME(rgb16to32)(const uint8_t *src, uint8_t *dst, int src_s "pmulhw "MANGLE(mul15_hi)", %%mm2 \n\t" PACK_RGB32 ::"r"(d),"r"(s),"m"(mask16b),"m"(mask16g),"m"(mask16r),"m"(mul15_mid) + NAMED_CONSTRAINTS_ADD(mul16_mid,mul15_hi) :"memory"); d += 16; s += 4; @@ -1133,6 +1142,7 @@ static inline void RENAME(rgb24tobgr24)(const uint8_t *src, uint8_t *dst, int sr "2: \n\t" : "+a" (mmx_size) : "r" (src-mmx_size), "r"(dst-mmx_size) + NAMED_CONSTRAINTS_ADD(mask24r,mask24g,mask24b) ); __asm__ volatile(SFENCE:::"memory"); @@ -1468,6 +1478,7 @@ static inline void RENAME(planar2x)(const uint8_t *src, uint8_t *dst, int srcWid :: "r" (src + mmxSize ), "r" (src + srcStride + mmxSize ), "r" (dst + mmxSize*2), "r" (dst + dstStride + mmxSize*2), "g" (-mmxSize) + NAMED_CONSTRAINTS_ADD(mmx_ff) : "%"REG_a ); @@ -1689,6 +1700,7 @@ static inline void RENAME(rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_ "add $8, %%"REG_a" \n\t" " js 1b \n\t" : : "r" (src+width*3), "r" (ydst+width), "g" ((x86_reg)-width), "r"(rgb2yuv) + NAMED_CONSTRAINTS_ADD(ff_w1111,ff_bgr2YOffset) : "%"REG_a, "%"REG_d ); ydst += lumStride; @@ -1837,6 +1849,7 @@ static inline void RENAME(rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_ "add $4, %%"REG_a" \n\t" " js 1b \n\t" : : "r" (src+chromWidth*6), "r" (src+srcStride+chromWidth*6), "r" (udst+chromWidth), "r" (vdst+chromWidth), "g" (-chromWidth), "r"(rgb2yuv) + NAMED_CONSTRAINTS_ADD(ff_w1111,ff_bgr2UVOffset) : "%"REG_a, "%"REG_d ); @@ -2173,6 +2186,44 @@ static void RENAME(extract_even)(const uint8_t *src, uint8_t *dst, x86_reg count } } +static void RENAME(extract_odd)(const uint8_t *src, uint8_t *dst, x86_reg count) +{ + src ++; + dst += count; + src += 2*count; + count= - count; + + if(count < -16) { + count += 16; + __asm__ volatile( + "pcmpeqw %%mm7, %%mm7 \n\t" + "psrlw $8, %%mm7 \n\t" + "1: \n\t" + "movq -32(%1, %0, 2), %%mm0 \n\t" + "movq -24(%1, %0, 2), %%mm1 \n\t" + "movq -16(%1, %0, 2), %%mm2 \n\t" + "movq -8(%1, %0, 2), %%mm3 \n\t" + "pand %%mm7, %%mm0 \n\t" + "pand %%mm7, %%mm1 \n\t" + "pand %%mm7, %%mm2 \n\t" + "pand %%mm7, %%mm3 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "packuswb %%mm3, %%mm2 \n\t" + MOVNTQ" %%mm0,-16(%2, %0) \n\t" + MOVNTQ" %%mm2,- 8(%2, %0) \n\t" + "add $16, %0 \n\t" + " js 1b \n\t" + : "+r"(count) + : "r"(src), "r"(dst) + ); + count -= 16; + } + while(count<0) { + dst[count]= src[2*count]; + count++; + } +} + #if !COMPILE_TEMPLATE_AMD3DNOW static void RENAME(extract_even2)(const uint8_t *src, uint8_t *dst0, uint8_t *dst1, x86_reg count) { @@ -2436,7 +2487,7 @@ static void RENAME(uyvytoyuv420)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, co const int chromWidth = FF_CEIL_RSHIFT(width, 1); for (y=0; y + +#include "libavutil/x86/asm.h" +#include "libswscale/swscale_internal.h" + #undef REAL_MOVNTQ #undef MOVNTQ #undef MOVNTQ2 @@ -172,6 +177,7 @@ static void RENAME(yuv2yuvX)(const int16_t *filter, int filterSize, :: "r" (&c->redDither), \ "m" (dummy), "m" (dummy), "m" (dummy),\ "r" (dest), "m" (dstW_reg), "m"(uv_off) \ + NAMED_CONSTRAINTS_ADD(bF8,bFC) \ : "%"REG_a, "%"REG_d, "%"REG_S \ ); @@ -660,6 +666,7 @@ static void RENAME(yuv2rgb555_X)(SwsContext *c, const int16_t *lumFilter, #define WRITEBGR24(dst, dstw, index) WRITEBGR24MMX(dst, dstw, index) #endif +#if HAVE_6REGS static void RENAME(yuv2bgr24_X_ar)(SwsContext *c, const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize, const int16_t *chrFilter, const int16_t **chrUSrc, @@ -680,6 +687,7 @@ static void RENAME(yuv2bgr24_X_ar)(SwsContext *c, const int16_t *lumFilter, :: "r" (&c->redDither), "m" (dummy), "m" (dummy), "m" (dummy), "r" (dest), "m" (dstW_reg), "m"(uv_off) + NAMED_CONSTRAINTS_ADD(ff_M24A,ff_M24C,ff_M24B) : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S ); } @@ -704,9 +712,11 @@ static void RENAME(yuv2bgr24_X)(SwsContext *c, const int16_t *lumFilter, :: "r" (&c->redDither), "m" (dummy), "m" (dummy), "m" (dummy), "r" (dest), "m" (dstW_reg), "m"(uv_off) + NAMED_CONSTRAINTS_ADD(ff_M24A,ff_M24C,ff_M24B) : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S ); } +#endif /* HAVE_6REGS */ #define REAL_WRITEYUY2(dst, dstw, index) \ "packuswb %%mm3, %%mm3 \n\t"\ @@ -930,6 +940,7 @@ static void RENAME(yuv2bgr24_2)(SwsContext *c, const int16_t *buf[2], "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) + NAMED_CONSTRAINTS_ADD(ff_M24A,ff_M24C,ff_M24B) ); } @@ -958,6 +969,7 @@ static void RENAME(yuv2rgb555_2)(SwsContext *c, const int16_t *buf[2], "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) + NAMED_CONSTRAINTS_ADD(bF8) ); } @@ -986,6 +998,7 @@ static void RENAME(yuv2rgb565_2)(SwsContext *c, const int16_t *buf[2], "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) + NAMED_CONSTRAINTS_ADD(bF8,bFC) ); } @@ -1258,6 +1271,7 @@ static void RENAME(yuv2bgr24_1)(SwsContext *c, const int16_t *buf0, "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) + NAMED_CONSTRAINTS_ADD(ff_M24A,ff_M24C,ff_M24B) ); } else { const int16_t *ubuf1 = ubuf[1]; @@ -1272,6 +1286,7 @@ static void RENAME(yuv2bgr24_1)(SwsContext *c, const int16_t *buf0, "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) + NAMED_CONSTRAINTS_ADD(ff_M24A,ff_M24C,ff_M24B) ); } } @@ -1303,6 +1318,7 @@ static void RENAME(yuv2rgb555_1)(SwsContext *c, const int16_t *buf0, "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) + NAMED_CONSTRAINTS_ADD(bF8) ); } else { const int16_t *ubuf1 = ubuf[1]; @@ -1323,6 +1339,7 @@ static void RENAME(yuv2rgb555_1)(SwsContext *c, const int16_t *buf0, "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) + NAMED_CONSTRAINTS_ADD(bF8) ); } } @@ -1354,6 +1371,7 @@ static void RENAME(yuv2rgb565_1)(SwsContext *c, const int16_t *buf0, "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) + NAMED_CONSTRAINTS_ADD(bF8,bFC) ); } else { const int16_t *ubuf1 = ubuf[1]; @@ -1374,6 +1392,7 @@ static void RENAME(yuv2rgb565_1)(SwsContext *c, const int16_t *buf0, "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) + NAMED_CONSTRAINTS_ADD(bF8,bFC) ); } } @@ -1647,7 +1666,9 @@ static av_cold void RENAME(sws_init_swscale)(SwsContext *c) if (!(c->flags & SWS_FULL_CHR_H_INT)) { switch (c->dstFormat) { case AV_PIX_FMT_RGB32: c->yuv2packedX = RENAME(yuv2rgb32_X_ar); break; +#if HAVE_6REGS case AV_PIX_FMT_BGR24: c->yuv2packedX = RENAME(yuv2bgr24_X_ar); break; +#endif case AV_PIX_FMT_RGB555: c->yuv2packedX = RENAME(yuv2rgb555_X_ar); break; case AV_PIX_FMT_RGB565: c->yuv2packedX = RENAME(yuv2rgb565_X_ar); break; case AV_PIX_FMT_YUYV422: c->yuv2packedX = RENAME(yuv2yuyv422_X_ar); break; @@ -1660,7 +1681,9 @@ static av_cold void RENAME(sws_init_swscale)(SwsContext *c) if (!(c->flags & SWS_FULL_CHR_H_INT)) { switch (c->dstFormat) { case AV_PIX_FMT_RGB32: c->yuv2packedX = RENAME(yuv2rgb32_X); break; +#if HAVE_6REGS case AV_PIX_FMT_BGR24: c->yuv2packedX = RENAME(yuv2bgr24_X); break; +#endif case AV_PIX_FMT_RGB555: c->yuv2packedX = RENAME(yuv2rgb555_X); break; case AV_PIX_FMT_RGB565: c->yuv2packedX = RENAME(yuv2rgb565_X); break; case AV_PIX_FMT_YUYV422: c->yuv2packedX = RENAME(yuv2yuyv422_X); break; diff --git a/libswscale/x86/yuv2rgb.c b/libswscale/x86/yuv2rgb.c index a3370eec6..5e2f77c20 100644 --- a/libswscale/x86/yuv2rgb.c +++ b/libswscale/x86/yuv2rgb.c @@ -50,28 +50,28 @@ DECLARE_ASM_CONST(8, uint64_t, pb_03) = 0x0303030303030303ULL; DECLARE_ASM_CONST(8, uint64_t, pb_07) = 0x0707070707070707ULL; //MMX versions -#if HAVE_MMX_INLINE +#if HAVE_MMX_INLINE && HAVE_6REGS #undef RENAME #undef COMPILE_TEMPLATE_MMXEXT #define COMPILE_TEMPLATE_MMXEXT 0 #define RENAME(a) a ## _mmx #include "yuv2rgb_template.c" -#endif /* HAVE_MMX_INLINE */ +#endif /* HAVE_MMX_INLINE && HAVE_6REGS */ // MMXEXT versions -#if HAVE_MMXEXT_INLINE +#if HAVE_MMXEXT_INLINE && HAVE_6REGS #undef RENAME #undef COMPILE_TEMPLATE_MMXEXT #define COMPILE_TEMPLATE_MMXEXT 1 #define RENAME(a) a ## _mmxext #include "yuv2rgb_template.c" -#endif /* HAVE_MMXEXT_INLINE */ +#endif /* HAVE_MMXEXT_INLINE && HAVE_6REGS */ #endif /* HAVE_INLINE_ASM */ av_cold SwsFunc ff_yuv2rgb_init_x86(SwsContext *c) { -#if HAVE_MMX_INLINE +#if HAVE_MMX_INLINE && HAVE_6REGS int cpu_flags = av_get_cpu_flags(); #if HAVE_MMXEXT_INLINE @@ -113,7 +113,7 @@ av_cold SwsFunc ff_yuv2rgb_init_x86(SwsContext *c) return yuv420_rgb15_mmx; } } -#endif /* HAVE_MMX_INLINE */ +#endif /* HAVE_MMX_INLINE && HAVE_6REGS */ return NULL; } diff --git a/libswscale/x86/yuv2rgb_template.c b/libswscale/x86/yuv2rgb_template.c index c879102cc..acb78f520 100644 --- a/libswscale/x86/yuv2rgb_template.c +++ b/libswscale/x86/yuv2rgb_template.c @@ -21,6 +21,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + +#include "libavutil/x86/asm.h" +#include "libswscale/swscale_internal.h" + #undef MOVNTQ #undef EMMS #undef SFENCE @@ -134,10 +139,20 @@ "add $4, %0\n\t" \ "js 1b\n\t" \ +#if COMPILE_TEMPLATE_MMXEXT +#undef RGB_PACK24_B_OPERANDS +#define RGB_PACK24_B_OPERANDS NAMED_CONSTRAINTS_ARRAY_ADD(mask1101,mask0110,mask0100,mask0010,mask1001) +#else +#undef RGB_PACK24_B_OPERANDS +#define RGB_PACK24_B_OPERANDS +#endif + #define YUV2RGB_OPERANDS \ : "+r" (index), "+r" (image) \ : "r" (pu - index), "r" (pv - index), "r"(&c->redDither), \ "r" (py - 2*index) \ + NAMED_CONSTRAINTS_ADD(mmx_00ffw,pb_03,pb_07,mmx_redmask,pb_e0) \ + RGB_PACK24_B_OPERANDS \ : "memory" \ ); \ } \ @@ -146,6 +161,7 @@ : "+r" (index), "+r" (image) \ : "r" (pu - index), "r" (pv - index), "r"(&c->redDither), \ "r" (py - 2*index), "r" (pa - 2*index) \ + NAMED_CONSTRAINTS_ADD(mmx_00ffw) \ : "memory" \ ); \ } \ diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c index 77c56a977..8e92e6da3 100644 --- a/libswscale/yuv2rgb.c +++ b/libswscale/yuv2rgb.c @@ -601,12 +601,8 @@ SwsFunc ff_yuv2rgb_get_func_ptr(SwsContext *c) { SwsFunc t = NULL; - if (ARCH_BFIN) - t = ff_yuv2rgb_init_bfin(c); if (ARCH_PPC) t = ff_yuv2rgb_init_ppc(c); - if (HAVE_VIS) - t = ff_yuv2rgb_init_vis(c); if (ARCH_X86) t = ff_yuv2rgb_init_x86(c); diff --git a/presets/libx264-ipod320.ffpreset b/presets/libx264-ipod320.ffpreset deleted file mode 100644 index 76722bd6d..000000000 --- a/presets/libx264-ipod320.ffpreset +++ /dev/null @@ -1,6 +0,0 @@ -vcodec=libx264 - -vprofile=baseline -level=13 -maxrate=768000 -bufsize=3000000 diff --git a/presets/libx264-ipod640.ffpreset b/presets/libx264-ipod640.ffpreset deleted file mode 100644 index 51f756427..000000000 --- a/presets/libx264-ipod640.ffpreset +++ /dev/null @@ -1,6 +0,0 @@ -vcodec=libx264 - -vprofile=baseline -level=30 -maxrate=10000000 -bufsize=10000000 diff --git a/tests/Makefile b/tests/Makefile index ff5fc2b34..d58505a51 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,6 +3,8 @@ FFSERVER_REFFILE = $(SRC_PATH)/tests/ffserver.regression.ref VREF = tests/vsynth1/00.pgm AREF = tests/data/asynth1.sw +FATEW = 34 +FATEH = 34 $(AREF): CMP= @@ -30,6 +32,9 @@ tests/data/vsynth1.yuv: tests/videogen$(HOSTEXESUF) | tests/data tests/data/vsynth2.yuv: tests/rotozoom$(HOSTEXESUF) | tests/data $(M)$< $(SRC_PATH)/tests/lena.pnm $@ +tests/data/vsynth3.yuv: tests/videogen$(HOSTEXESUF) | tests/data + $(M)$< $@ $(FATEW) $(FATEH) + tests/data/ffprobe-test.nut: ffmpeg$(EXESUF) | tests/data $(M)$(TARGET_EXEC) ./$< \ -f lavfi -i "aevalsrc=sin(400*PI*2*t):d=0.125[out0]; testsrc=d=0.125[out1]; testsrc=s=100x100:d=0.125[out2]" \ @@ -119,6 +124,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/opus.mak include $(SRC_PATH)/tests/fate/pcm.mak include $(SRC_PATH)/tests/fate/probe.mak include $(SRC_PATH)/tests/fate/prores.mak @@ -177,7 +183,7 @@ fate:: $(FATE) $(FATE) $(FATE_TESTS-no): $(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 $@ "$(TARGET_SAMPLES)" "$(TARGET_EXEC)" "$(TARGET_PATH)" '$(CMD)' '$(CMP)' '$(REF)' '$(FUZZ)' '$(THREADS)' '$(THREAD_TYPE)' '$(CPUFLAGS)' '$(CMP_SHIFT)' '$(CMP_TARGET)' '$(SIZE_TOLERANCE)' '$(CMP_UNIT)' '$(GEN)' fate-list: @printf '%s\n' $(sort $(FATE)) diff --git a/tests/fate-run.sh b/tests/fate-run.sh index 48e9dd0bd..60cb569fa 100755 --- a/tests/fate-run.sh +++ b/tests/fate-run.sh @@ -8,7 +8,7 @@ base=$(dirname $0) base64=tests/base64 test="${1#fate-}" -samples=$2 +target_samples=$2 target_exec=$3 target_path=$4 command=$5 @@ -71,6 +71,11 @@ run(){ $target_exec $target_path/"$@" } +runecho(){ + test "${V:-0}" -gt 0 && echo "$target_exec" $target_path/"$@" >&3 + $target_exec $target_path/"$@" >&3 +} + probefmt(){ run ffprobe -show_entries format=format_name -print_format default=nw=1:nk=1 -v 0 "$@" } @@ -122,7 +127,7 @@ enc_dec_pcm(){ ffmpeg -flags +bitexact -i ${encfile} -c:a pcm_${pcm_fmt} -f ${dec_fmt} - } -FLAGS="-flags +bitexact -sws_flags +accurate_rnd+bitexact" +FLAGS="-flags +bitexact -sws_flags +accurate_rnd+bitexact -fflags +bitexact" DEC_OPTS="-threads $threads -idct simple $FLAGS" ENC_OPTS="-threads 1 -idct simple -dct fastint" @@ -153,13 +158,13 @@ enc_dec(){ lavffatetest(){ t="${test#lavf-fate-}" ref=${base}/ref/lavf-fate/$t - ${base}/lavf-regression.sh $t lavf-fate tests/vsynth1 "$target_exec" "$target_path" "$threads" "$thread_type" "$cpuflags" "$samples" + ${base}/lavf-regression.sh $t lavf-fate tests/vsynth1 "$target_exec" "$target_path" "$threads" "$thread_type" "$cpuflags" "$target_samples" } lavftest(){ t="${test#lavf-}" ref=${base}/ref/lavf/$t - ${base}/lavf-regression.sh $t lavf tests/vsynth1 "$target_exec" "$target_path" "$threads" "$thread_type" "$cpuflags" "$samples" + ${base}/lavf-regression.sh $t lavf tests/vsynth1 "$target_exec" "$target_path" "$threads" "$thread_type" "$cpuflags" "$target_samples" } video_filter(){ diff --git a/tests/fate-update.sh b/tests/fate-update.sh deleted file mode 100755 index 6b4668fc0..000000000 --- a/tests/fate-update.sh +++ /dev/null @@ -1,55 +0,0 @@ -#! /bin/sh - -set -e - -base=$(dirname $0) -ref="${base}/ref/fate" - -FATE_DB_URL="http://fate.multimedia.cx/fate-tests.sqlite.bz2" -FATE_DB=$(mktemp fate-db.XXXXXX) -SQL_TESTS='SELECT id,short_name,command FROM test_spec WHERE active=1 ORDER BY short_name' - -do_sql(){ - sqlite3 -noheader -separator ' ' "$FATE_DB" "$@" -} - -wget -q -O - "$FATE_DB_URL" | bunzip2 > "$FATE_DB" -mkdir -p "$ref" -exec 3>"$base/fate.mak" - -do_sql "$SQL_TESTS" | while read id name command; do - case "$name" in - 00-full-regression|ffmpeg-help|binsize-*) continue ;; - esac - case "$command" in - {MD5}*) - command="${command#*ffmpeg}"; command="${command% -}" - command="md5 $command" - ;; - {*}*) continue ;; - *-f\ framecrc\ -) - command="${command#*ffmpeg}"; command="${command% -f *}" - command="framecrc $command" - ;; - *-f\ framemd5\ -) - command="${command#*ffmpeg}"; command="${command% -f *}" - command="framemd5 $command" - ;; - *-f\ crc\ -) - command="${command#*ffmpeg}"; command="${command% -f *}" - command="crc $command" - ;; - *) - echo "Unhandled command '$command'" - exit 1 - ;; - esac - command=$(echo "$command" | sed 's/\$SAMPLES_PATH/$(SAMPLES)/g') - command=$(echo "$command" | sed 's/ *$//') - do_sql "SELECT expected_stdout FROM test_spec WHERE id=$id" | awk '/./{print}' > "$ref/$name" - printf "FATE_TESTS += fate-${name}\n" >&3 - printf "fate-${name}: CMD = %s\n" "$command" >&3 -done - -exec 3<&- -rm -f "$FATE_DB" diff --git a/tests/fate.sh b/tests/fate.sh index f3712911e..38458c748 100755 --- a/tests/fate.sh +++ b/tests/fate.sh @@ -111,8 +111,8 @@ echo ${version} >version-$slot rm -rf "${build}" *.log mkdir -p ${build} -configure >configure.log 2>&1 || fail $? "error configuring" -compile >compile.log 2>&1 || fail $? "error compiling" -fate >test.log 2>&1 || fail $? "error testing" +configure >configure.log 2>&1 || fail 3 "error configuring" +compile >compile.log 2>&1 || fail 2 "error compiling" +fate >test.log 2>&1 || fail 1 "error testing" report 0 success clean diff --git a/tests/fate/aac.mak b/tests/fate/aac.mak index 7ed5b7b38..bc52cadde 100644 --- a/tests/fate/aac.mak +++ b/tests/fate/aac.mak @@ -91,7 +91,7 @@ fate-aac-aref-encode: CMP_TARGET = 1862 fate-aac-aref-encode: SIZE_TOLERANCE = 2464 FATE_AAC_ENCODE += fate-aac-ln-encode -fate-aac-ln-encode: CMD = enc_dec_pcm adts wav s16le $(REF) -strict -2 -c:a aac -b:a 512k +fate-aac-ln-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -strict -2 -c:a aac -b:a 512k fate-aac-ln-encode: CMP = stddev fate-aac-ln-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-ln-encode: CMP_SHIFT = -4096 diff --git a/tests/fate/ac3.mak b/tests/fate/ac3.mak index f38649907..f00c3c4eb 100644 --- a/tests/fate/ac3.mak +++ b/tests/fate/ac3.mak @@ -26,6 +26,14 @@ 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: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_stereo_v2.pcm +FATE_AC3 += fate-ac3-fixed-2.0 +fate-ac3-fixed-2.0: CMD = pcm -c ac3_fixed -i $(TARGET_SAMPLES)/ac3/monsters_inc_2.0_192_small.ac3 +fate-ac3-fixed-2.0: REF = $(SAMPLES)/ac3/monsters_inc_2.0_192_small_v2.pcm + +FATE_AC3 += fate-ac3-fixed-4.0-downmix-mono +fate-ac3-fixed-4.0-downmix-mono: CMD = pcm -c ac3_fixed -request_channels 1 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 +fate-ac3-fixed-4.0-downmix-mono: REF = $(SAMPLES)/ac3/millers_crossing_4.0_mono_v2.pcm + FATE_EAC3 += fate-eac3-1 fate-eac3-1: CMD = pcm -i $(TARGET_SAMPLES)/eac3/csi_miami_5.1_256_spx_small.eac3 fate-eac3-1: REF = $(SAMPLES)/eac3/csi_miami_5.1_256_spx_small_v2.pcm diff --git a/tests/fate/acodec.mak b/tests/fate/acodec.mak index 10d439259..325bbd9e3 100644 --- a/tests/fate/acodec.mak +++ b/tests/fate/acodec.mak @@ -64,9 +64,31 @@ fate-acodec-adpcm-ms: FMT = wav fate-acodec-adpcm-swf: FMT = flv fate-acodec-adpcm-yamaha: FMT = wav +FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_ADX, ADX) += adx +FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_IMA_QT, AIFF) += ima_qt +FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_IMA_WAV, WAV) += ima_wav +FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_MS, WAV) += ms +FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_SWF, FLV) += swf +FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_YAMAHA, WAV) += yamaha + +FATE_ACODEC_ADPCM_TRELLIS := $(FATE_ACODEC_ADPCM_TRELLIS-yes:%=fate-acodec-adpcm-%-trellis) +FATE_ACODEC += $(FATE_ACODEC_ADPCM_TRELLIS) +fate-acodec-adpcm-trellis: $(FATE_ACODEC_ADPCM_TRELLIS) + +fate-acodec-adpcm-%-trellis: CODEC = adpcm_$(@:fate-acodec-adpcm-%-trellis=%) +fate-acodec-adpcm-%-trellis: ENCOPTS = -trellis 5 + +fate-acodec-adpcm-adx-trellis: FMT = adx +fate-acodec-adpcm-ima_qt-trellis: FMT = aiff +fate-acodec-adpcm-ima_wav-trellis: FMT = wav +fate-acodec-adpcm-ms-trellis: FMT = wav +fate-acodec-adpcm-swf-trellis: FMT = flv +fate-acodec-adpcm-yamaha-trellis: FMT = wav + FATE_ACODEC-$(call ENCDEC, MP2, MP2 MP3) += fate-acodec-mp2 fate-acodec-mp2: FMT = mp2 fate-acodec-mp2: CMP_SHIFT = -1924 +fate-acodec-mp2: ENCOPTS = -b:a 128k FATE_ACODEC-$(call ENCDEC, MP2FIXED MP2 , MP2 MP3) += fate-acodec-mp2fixed fate-acodec-mp2fixed: FMT = mp2 diff --git a/tests/fate/adpcm.mak b/tests/fate/adpcm.mak index 6b1dd3cb3..b64920d4f 100644 --- a/tests/fate/adpcm.mak +++ b/tests/fate/adpcm.mak @@ -82,6 +82,9 @@ fate-adpcm_ms-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-L FATE_ADPCM-$(call DEMDEC, THP, ADPCM_THP) += fate-adpcm-thp fate-adpcm-thp: CMD = framecrc -i $(TARGET_SAMPLES)/thp/pikmin2-opening1-partial.thp -vn +FATE_ADPCM-$(call DEMDEC, SMUSH, ADPCM_VIMA) += fate-adpcm-vima +fate-adpcm-vima: CMD = framecrc -i $(TARGET_SAMPLES)/smush/ronin_part.znm -vn + FATE_ADPCM-$(call DEMDEC, STR, ADPCM_XA) += fate-adpcm-xa fate-adpcm-xa: CMD = framecrc -i $(TARGET_SAMPLES)/psx-str/abc000_cut.str -vn diff --git a/tests/fate/audio.mak b/tests/fate/audio.mak index 6b5d1a96d..aa58dfc15 100644 --- a/tests/fate/audio.mak +++ b/tests/fate/audio.mak @@ -24,6 +24,11 @@ fate-dts: CMD = pcm -i $(TARGET_SAMPLES)/dts/dts.ts fate-dts: CMP = oneoff fate-dts: REF = $(SAMPLES)/dts/dts.pcm +FATE_SAMPLES_AUDIO-$(call DEMDEC, DTS, DCA) += fate-dts_es +fate-dts_es: CMD = pcm -i $(TARGET_SAMPLES)/dts/dts_es.dts +fate-dts_es: CMP = oneoff +fate-dts_es: REF = $(SAMPLES)/dts/dts_es.pcm + FATE_SAMPLES_AUDIO-$(call DEMDEC, AVI, IMC) += fate-imc fate-imc: CMD = pcm -i $(TARGET_SAMPLES)/imc/imc.avi fate-imc: CMP = oneoff @@ -43,6 +48,9 @@ fate-nellymoser-aref-encode: CMP_SHIFT = -244 fate-nellymoser-aref-encode: CMP_TARGET = 9612 fate-nellymoser-aref-encode: SIZE_TOLERANCE = 268 +FATE_SAMPLES_AUDIO-$(call DEMDEC, AVI, ON2AVC) += fate-on2avc +fate-on2avc: CMD = framecrc -i $(TARGET_SAMPLES)/vp7/potter-40.vp7 -frames 30 -vn + FATE_SAMPLES_AUDIO-$(call DEMDEC, PAF, PAF_AUDIO) += fate-paf-audio fate-paf-audio: CMD = framecrc -i $(TARGET_SAMPLES)/paf/hod1-partial.paf -vn @@ -52,9 +60,6 @@ fate-sierra-vmd-audio: CMD = framecrc -i $(TARGET_SAMPLES)/vmd/12.vmd -vn FATE_SAMPLES_AUDIO-$(call DEMDEC, SMACKER, SMACKAUD) += fate-smacker-audio fate-smacker-audio: CMD = framecrc -i $(TARGET_SAMPLES)/smacker/wetlogo.smk -vn -FATE_SAMPLES_AUDIO-$(call DEMDEC, SMUSH, VIMA) += fate-vima -fate-vima: CMD = framecrc -i $(TARGET_SAMPLES)/smush/ronin_part.znm -vn - FATE_SAMPLES_AUDIO-$(call DEMDEC, WSVQA, WS_SND1) += fate-ws_snd fate-ws_snd: CMD = md5 -i $(TARGET_SAMPLES)/vqa/ws_snd.vqa -f s16le diff --git a/tests/fate/demux.mak b/tests/fate/demux.mak index 75638a9ea..0eccc9b3c 100644 --- a/tests/fate/demux.mak +++ b/tests/fate/demux.mak @@ -22,6 +22,9 @@ fate-caf: CMD = crc -i $(TARGET_SAMPLES)/caf/caf-pcm16.caf -c copy FATE_SAMPLES_DEMUX-$(CONFIG_CDXL_DEMUXER) += fate-cdxl-demux fate-cdxl-demux: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/mirage.cdxl -vcodec copy -acodec copy +FATE_SAMPLES_DEMUX-$(CONFIG_CINE_DEMUXER) += fate-cine-demux +fate-cine-demux: CMD = crc -i $(TARGET_SAMPLES)/cine/bayer_gbrg8.cine -c copy + FATE_SAMPLES_DEMUX-$(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 @@ -40,9 +43,12 @@ fate-lmlm4-demux: CMD = framecrc -i $(TARGET_SAMPLES)/lmlm4/LMLM4_CIFat30fps.div FATE_SAMPLES_DEMUX-$(CONFIG_XA_DEMUXER) += fate-maxis-xa fate-maxis-xa: CMD = framecrc -i $(TARGET_SAMPLES)/maxis-xa/SC2KBUG.XA -frames:a 30 -c:a copy -FATE_SAMPLES_DEMUX-$(CONFIG_MATROSKA_DEMUXER) += fate-mkv +FATE_SAMPLES_DEMUX-$(call DEMDEC, MATROSKA, H264) += fate-mkv fate-mkv: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/test7_cut.mkv -c copy +FATE_SAMPLES_DEMUX-$(CONFIG_MLV_DEMUXER) += fate-mlv-demux +fate-mlv-demux: CMD = crc -i $(TARGET_SAMPLES)/mlv/M19-0333-cut.MLV -c copy + FATE_SAMPLES_DEMUX-$(CONFIG_MTV_DEMUXER) += fate-mtv fate-mtv: CMD = framecrc -i $(TARGET_SAMPLES)/mtv/comedian_auto-partial.mtv -c copy diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 21cdd5f4a..218f7d842 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -31,18 +31,18 @@ fate-force_key_frames: CMD = enc_dec \ FATE_SAMPLES_FFMPEG-$(call ALLYES, VOBSUB_DEMUXER DVDSUB_DECODER AVFILTER OVERLAY_FILTER DVDSUB_ENCODER) += fate-sub2video fate-sub2video: tests/data/vsynth2.yuv fate-sub2video: CMD = framecrc \ - -f rawvideo -r 5 -s 352x288 -pix_fmt yuv420p -i tests/data/vsynth2.yuv \ - -ss 132 -i $(SAMPLES)/sub/vobsub.idx \ - -filter_complex "sws_flags=+accurate_rnd+bitexact;[0:0]scale=720:480[v];[v][1:0]overlay[v2]" \ + -f rawvideo -r 5 -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth2.yuv \ + -ss 132 -i $(TARGET_SAMPLES)/sub/vobsub.idx \ + -filter_complex "sws_flags=+accurate_rnd+bitexact\;[0:0]scale=720:480[v]\;[v][1:0]overlay[v2]" \ -map "[v2]" -c:v rawvideo -map 1:s -c:s dvdsub FATE_FFMPEG-$(call ALLYES, PCM_S16LE_DEMUXER PCM_S16LE_MUXER PCM_S16LE_DECODER PCM_S16LE_ENCODER) += fate-unknown_layout-pcm fate-unknown_layout-pcm: $(AREF) fate-unknown_layout-pcm: CMD = md5 \ - -guess_layout_max 0 -f s16le -ac 1 -ar 44100 -i $(AREF) -f s16le + -guess_layout_max 0 -f s16le -ac 1 -ar 44100 -i $(TARGET_PATH)/$(AREF) -f s16le FATE_FFMPEG-$(call ALLYES, PCM_S16LE_DEMUXER AC3_MUXER PCM_S16LE_DECODER AC3_FIXED_ENCODER) += fate-unknown_layout-ac3 fate-unknown_layout-ac3: $(AREF) fate-unknown_layout-ac3: CMD = md5 \ - -guess_layout_max 0 -f s16le -ac 1 -ar 44100 -i $(AREF) \ + -guess_layout_max 0 -f s16le -ac 1 -ar 44100 -i $(TARGET_PATH)/$(AREF) \ -f ac3 -flags +bitexact -c ac3_fixed diff --git a/tests/fate/fft.mak b/tests/fate/fft.mak index 1f3a26235..9fdca2b3e 100644 --- a/tests/fate/fft.mak +++ b/tests/fate/fft.mak @@ -1,8 +1,8 @@ define DEF_FFT -FATE_FFT += fate-fft-$(1) fate-ifft-$(1) \ - fate-mdct-$(1) fate-imdct-$(1) \ - fate-rdft-$(1) fate-irdft-$(1) \ - fate-dct1d-$(1) fate-idct1d-$(1) +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-fft-$(N): ARGS = -n$(1) fate-ifft-$(N): ARGS = -n$(1) -i @@ -16,14 +16,14 @@ endef $(foreach N, 4 5 6 7 8 9 10 11 12, $(eval $(call DEF_FFT,$(N)))) -fate-fft-test: $(FATE_FFT) -$(FATE_FFT): libavcodec/fft-test$(EXESUF) -$(FATE_FFT): CMD = run libavcodec/fft-test $(CPUFLAGS:%=-c%) $(ARGS) -$(FATE_FFT): REF = /dev/null +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 define DEF_FFT_FIXED -FATE_FFT_FIXED += fate-fft-fixed-$(1) fate-ifft-fixed-$(1) \ - fate-mdct-fixed-$(1) fate-imdct-fixed-$(1) +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-$(1): ARGS = -n$(1) fate-ifft-fixed-$(1): ARGS = -n$(1) -i @@ -33,10 +33,10 @@ endef $(foreach N, 4 5 6 7 8 9 10 11 12, $(eval $(call DEF_FFT_FIXED,$(N)))) -fate-fft-fixed-test: $(FATE_FFT_FIXED) -$(FATE_FFT_FIXED): libavcodec/fft-fixed-test$(EXESUF) -$(FATE_FFT_FIXED): CMD = run libavcodec/fft-fixed-test $(CPUFLAGS:%=-c%) $(ARGS) -$(FATE_FFT_FIXED): REF = /dev/null +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 define DEF_FFT_FIXED32 FATE_FFT_FIXED32 += fate-fft-fixed32-$(1) fate-ifft-fixed32-$(1) \ @@ -55,5 +55,5 @@ $(FATE_FFT_FIXED32): libavcodec/fft-fixed32-test$(EXESUF) $(FATE_FFT_FIXED32): CMD = run libavcodec/fft-fixed32-test $(CPUFLAGS:%=-c%) $(ARGS) $(FATE_FFT_FIXED32): REF = /dev/null -FATE-$(call ALLYES, AVCODEC FFT MDCT) += $(FATE_FFT) $(FATE_FFT_FIXED) $(FATE_FFT_FIXED32) -fate-fft: $(FATE_FFT) $(FATE_FFT_FIXED) $(FATE_FFT_FIXED32) +FATE-$(call ALLYES, AVCODEC FFT MDCT) += $(FATE_FFT-yes) $(FATE_FFT_FIXED-yes) $(FATE_FFT_FIXED32) +fate-fft: $(FATE_FFT-yes) $(FATE_FFT_FIXED-yes) $(FATE_FFT_FIXED32) diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak index 84c4b0d0d..210b89eb0 100644 --- a/tests/fate/filter-audio.mak +++ b/tests/fate/filter-audio.mak @@ -31,7 +31,7 @@ fate-filter-asyncts: CMP = oneoff fate-filter-asyncts: REF = $(SAMPLES)/nellymoser/nellymoser-discont-async-v3.pcm FATE_FILTER-$(CONFIG_ARESAMPLE_FILTER) += fate-filter-aresample -fate-filter-aresample: SRC = $(SAMPLES)/nellymoser/nellymoser-discont.flv +fate-filter-aresample: SRC = $(TARGET_SAMPLES)/nellymoser/nellymoser-discont.flv fate-filter-aresample: CMD = pcm -analyzeduration 10000000 -i $(SRC) -af aresample=min_comp=0.001:min_hard_comp=0.1:first_pts=0 fate-filter-aresample: CMP = oneoff fate-filter-aresample: REF = $(SAMPLES)/nellymoser/nellymoser-discont.pcm @@ -52,13 +52,23 @@ $(FATE_ATRIM): SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav FATE_FILTER-$(call FILTERDEMDECENCMUX, ATRIM, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_ATRIM) -FATE_AFILTER-$(call FILTERDEMDECENCMUX, CHANNELMAP, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-channelmap -fate-filter-channelmap: tests/data/filtergraphs/channelmap -fate-filter-channelmap: SRC = $(TARGET_PATH)/tests/data/asynth-44100-6.wav -fate-filter-channelmap: tests/data/asynth-44100-6.wav -fate-filter-channelmap: CMD = md5 -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/channelmap -f wav -flags +bitexact -fate-filter-channelmap: CMP = oneline -fate-filter-channelmap: REF = 06168d06085e2c0603e4e118ba4cade2 +FATE_FILTER_CHANNELMAP += fate-filter-channelmap-one-int +fate-filter-channelmap-one-int: tests/data/filtergraphs/channelmap_one_int +fate-filter-channelmap-one-int: SRC = $(TARGET_PATH)/tests/data/asynth-44100-6.wav +fate-filter-channelmap-one-int: tests/data/asynth-44100-6.wav +fate-filter-channelmap-one-int: CMD = md5 -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/channelmap_one_int -f wav -fflags +bitexact +fate-filter-channelmap-one-int: CMP = oneline +fate-filter-channelmap-one-int: REF = 428b8f9fac6d57147069b97335019ef5 + +FATE_FILTER_CHANNELMAP += fate-filter-channelmap-one-str +fate-filter-channelmap-one-str: tests/data/filtergraphs/channelmap_one_str +fate-filter-channelmap-one-str: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav +fate-filter-channelmap-one-str: tests/data/asynth-44100-2.wav +fate-filter-channelmap-one-str: CMD = md5 -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/channelmap_one_str -f wav -fflags +bitexact +fate-filter-channelmap-one-str: CMP = oneline +fate-filter-channelmap-one-str: REF = e788890db6a11c2fb29d7c4229072d49 + +FATE_AFILTER-$(call FILTERDEMDECENCMUX, CHANNELMAP, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_FILTER_CHANNELMAP) FATE_AFILTER-$(call FILTERDEMDECENCMUX, CHANNELSPLIT, WAV, PCM_S16LE, PCM_S16LE, PCM_S16LE) += fate-filter-channelsplit fate-filter-channelsplit: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 68e9f874c..543efb58a 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -7,6 +7,12 @@ fate-filter-yadif-mode0: CMD = framecrc -flags bitexact -idct simple -i $(TARGET FATE_YADIF += fate-filter-yadif-mode1 fate-filter-yadif-mode1: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vframes 59 -vf yadif=1 +FATE_YADIF += fate-filter-yadif10 +fate-filter-yadif10: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p10le -vframes 30 -vf yadif=0 + +FATE_YADIF += fate-filter-yadif16 +fate-filter-yadif16: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p16le -vframes 30 -vf yadif=0 + FATE_FILTER-$(call FILTERDEMDEC, YADIF, MPEGTS, MPEG2VIDEO) += $(FATE_YADIF) FATE_MCDEINT += fate-filter-mcdeint-fast @@ -26,7 +32,8 @@ FATE_FILTER-$(call ALLYES, AVDEVICE TESTSRC_FILTER) += fate-filter-lavd-testsrc fate-filter-lavd-testsrc: CMD = framecrc -f lavfi -i testsrc=r=7:n=2:d=10 FATE_FILTER-$(call ALLYES, AVDEVICE TESTSRC_FILTER FORMAT_FILTER CONCAT_FILTER SCALE_FILTER) += fate-filter-lavd-scalenorm -fate-filter-lavd-scalenorm: CMD = framecrc -f lavfi -graph_file $(SRC_PATH)/tests/filtergraphs/scalenorm -i dummy +fate-filter-lavd-scalenorm: tests/data/filtergraphs/scalenorm +fate-filter-lavd-scalenorm: CMD = framecrc -f lavfi -graph_file $(TARGET_PATH)/tests/data/filtergraphs/scalenorm -i dummy FATE_FILTER_VSYNTH-$(CONFIG_BOXBLUR_FILTER) += fate-filter-boxblur @@ -75,16 +82,20 @@ fate-filter-overlay: tests/data/filtergraphs/overlay fate-filter-overlay: CMD = framecrc -c:v pgmyuv -i $(SRC) -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_rgb -fate-filter-overlay_rgb: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(SRC_PATH)/tests/filtergraphs/overlay_rgb +fate-filter-overlay_rgb: tests/data/filtergraphs/overlay_rgb +fate-filter-overlay_rgb: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_rgb FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv420 -fate-filter-overlay_yuv420: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(SRC_PATH)/tests/filtergraphs/overlay_yuv420 +fate-filter-overlay_yuv420: tests/data/filtergraphs/overlay_yuv420 +fate-filter-overlay_yuv420: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv420 FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv422 -fate-filter-overlay_yuv422: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(SRC_PATH)/tests/filtergraphs/overlay_yuv422 +fate-filter-overlay_yuv422: tests/data/filtergraphs/overlay_yuv422 +fate-filter-overlay_yuv422: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv422 FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv444 -fate-filter-overlay_yuv444: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(SRC_PATH)/tests/filtergraphs/overlay_yuv444 +fate-filter-overlay_yuv444: tests/data/filtergraphs/overlay_yuv444 +fate-filter-overlay_yuv444: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv444 FATE_FILTER_VSYNTH-$(CONFIG_PHASE_FILTER) += fate-filter-phase fate-filter-phase: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf phase @@ -100,6 +111,14 @@ FATE_FILTER_VSYNTH-$(call ALLYES, SETPTS_FILTER SETTB_FILTER) += fate-filter-se fate-filter-setpts: tests/data/filtergraphs/setpts fate-filter-setpts: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_script $(TARGET_PATH)/tests/data/filtergraphs/setpts +FATE_SHUFFLEPLANES += fate-filter-shuffleplanes-dup-luma +fate-filter-shuffleplanes-dup-luma: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf format=yuva444p,shuffleplanes=0:0:0:0 + +FATE_SHUFFLEPLANES += fate-filter-shuffleplanes-swapuv +fate-filter-shuffleplanes-swapuv: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf shuffleplanes=0:2:1 + +FATE_FILTER_VSYNTH-$(CONFIG_SHUFFLEPLANES_FILTER) += $(FATE_SHUFFLEPLANES) + FATE_FILTER_VSYNTH-$(CONFIG_TELECINE_FILTER) += fate-filter-telecine fate-filter-telecine: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf telecine @@ -124,22 +143,34 @@ FATE_FILTER_VSYNTH-$(CONFIG_UNSHARP_FILTER) += fate-filter-unsharp fate-filter-unsharp: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf unsharp=11:11:-1.5:11:11:-1.5 FATE_FILTER-$(call ALLYES, SMJPEG_DEMUXER MJPEG_DECODER PERMS_FILTER HQDN3D_FILTER) += fate-filter-hqdn3d-sample -fate-filter-hqdn3d-sample: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -filter_complex_script $(SRC_PATH)/tests/filtergraphs/hqdn3d -an +fate-filter-hqdn3d-sample: tests/data/filtergraphs/hqdn3d +fate-filter-hqdn3d-sample: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/hqdn3d -an + +FATE_FILTER_HQX-$(call ALLYES, IMAGE2_DEMUXER PNG_DECODER HQX_FILTER) = fate-filter-hq2x fate-filter-hq3x fate-filter-hq4x +FATE_FILTER-yes += $(FATE_FILTER_HQX-yes) +fate-filter-hq2x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf hqx=2 -pix_fmt bgra +fate-filter-hq3x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf hqx=3 -pix_fmt bgra +fate-filter-hq4x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf hqx=4 -pix_fmt bgra +fate-filter-hqx: $(FATE_FILTER_HQX-yes) FATE_FILTER-$(call ALLYES, UTVIDEO_DECODER AVI_DEMUXER PERMS_FILTER CURVES_FILTER) += fate-filter-curves fate-filter-curves: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_rgb_median.avi -vf perms=random,curves=vintage FATE_FILTER-$(call ALLYES, VMD_DEMUXER VMDVIDEO_DECODER FORMAT_FILTER PERMS_FILTER GRADFUN_FILTER) += fate-filter-gradfun-sample -fate-filter-gradfun-sample: CMD = framecrc -i $(TARGET_SAMPLES)/vmd/12.vmd -filter_script $(SRC_PATH)/tests/filtergraphs/gradfun -an -frames:v 20 +fate-filter-gradfun-sample: tests/data/filtergraphs/gradfun +fate-filter-gradfun-sample: CMD = framecrc -i $(TARGET_SAMPLES)/vmd/12.vmd -filter_script $(TARGET_PATH)/tests/data/filtergraphs/gradfun -an -frames:v 20 FATE_FILTER-$(call ALLYES, TESTSRC_FILTER SINE_FILTER CONCAT_FILTER) += fate-filter-concat -fate-filter-concat: CMD = framecrc -filter_complex_script $(SRC_PATH)/tests/filtergraphs/concat +fate-filter-concat: tests/data/filtergraphs/concat +fate-filter-concat: CMD = framecrc -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/concat FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER SPLIT_FILTER ALPHAEXTRACT_FILTER ALPHAMERGE_FILTER) += fate-filter-alphaextract_alphamerge_rgb -fate-filter-alphaextract_alphamerge_rgb: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(SRC_PATH)/tests/filtergraphs/alphamerge_alphaextract_rgb +fate-filter-alphaextract_alphamerge_rgb: tests/data/filtergraphs/alphamerge_alphaextract_rgb +fate-filter-alphaextract_alphamerge_rgb: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/alphamerge_alphaextract_rgb FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER SPLIT_FILTER ALPHAEXTRACT_FILTER ALPHAMERGE_FILTER) += fate-filter-alphaextract_alphamerge_yuv -fate-filter-alphaextract_alphamerge_yuv: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(SRC_PATH)/tests/filtergraphs/alphamerge_alphaextract_yuv +fate-filter-alphaextract_alphamerge_yuv: tests/data/filtergraphs/alphamerge_alphaextract_yuv +fate-filter-alphaextract_alphamerge_yuv: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/alphamerge_alphaextract_yuv FATE_FILTER_VSYNTH-$(CONFIG_CROP_FILTER) += fate-filter-crop fate-filter-crop: CMD = video_filter "crop=iw-100:ih-100:100:100" @@ -180,6 +211,9 @@ fate-filter-vflip_vflip: CMD = video_filter "vflip,vflip" FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER PERMS_FILTER EDGEDETECT_FILTER) += fate-filter-edgedetect fate-filter-edgedetect: CMD = video_filter "format=gray,perms=random,edgedetect" +FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER PERMS_FILTER EDGEDETECT_FILTER) += fate-filter-edgedetect-colormix +fate-filter-edgedetect-colormix: CMD = video_filter "format=gbrp,perms=random,edgedetect=mode=colormix" + FATE_FILTER_VSYNTH-$(call ALLYES, PERMS_FILTER HUE_FILTER) += fate-filter-hue fate-filter-hue: CMD = video_filter "perms=random,hue=s=sin(2*PI*t)+1" @@ -262,6 +296,9 @@ fate-filter-pixfmts-crop: CMD = pixfmts "100:100:100:100" FATE_FILTER_PIXFMTS-$(CONFIG_FIELD_FILTER) += fate-filter-pixfmts-field fate-filter-pixfmts-field: CMD = pixfmts "bottom" +FATE_FILTER_PIXFMTS-$(call ALLYES, TELECINE_FILTER FIELDMATCH_FILTER) += fate-filter-pixfmts-fieldmatch +fate-filter-pixfmts-fieldmatch: CMD = pixfmts "" "telecine," + FATE_FILTER_PIXFMTS-$(CONFIG_FIELDORDER_FILTER) += fate-filter-pixfmts-fieldorder fate-filter-pixfmts-fieldorder: CMD = pixfmts "tff" "setfield=bff," @@ -286,6 +323,9 @@ fate-filter-pixfmts-null: CMD = pixfmts FATE_FILTER_PIXFMTS-$(CONFIG_PAD_FILTER) += fate-filter-pixfmts-pad fate-filter-pixfmts-pad: CMD = pixfmts "500:400:20:20" +FATE_FILTER_PIXFMTS-$(call ALLYES, TELECINE_FILTER PULLUP_FILTER) += fate-filter-pixfmts-pullup +fate-filter-pixfmts-pullup: CMD = pixfmts "" "telecine," + FATE_FILTER_PIXFMTS-$(CONFIG_ROTATE_FILTER) += fate-filter-pixfmts-rotate fate-filter-pixfmts-rotate: CMD = pixfmts "2*PI*n/50" @@ -325,17 +365,17 @@ FILTER_METADATA_COMMAND = ffprobe$(EXESUF) -of compact=p=0 -show_entries frame=p SCENEDETECT_DEPS = FFPROBE LAVFI_INDEV MOVIE_FILTER SELECT_FILTER SCALE_FILTER \ AVCODEC AVDEVICE MOV_DEMUXER SVQ3_DECODER ZLIB FATE_METADATA_FILTER-$(call ALLYES, $(SCENEDETECT_DEPS)) += fate-filter-metadata-scenedetect -fate-filter-metadata-scenedetect: SRC = $(SAMPLES)/svq3/Vertical400kbit.sorenson3.mov +fate-filter-metadata-scenedetect: SRC = $(TARGET_SAMPLES)/svq3/Vertical400kbit.sorenson3.mov fate-filter-metadata-scenedetect: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;movie='$(SRC)',select=gt(scene\,.4)" SILENCEDETECT_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER AMR_DEMUXER AMRWB_DECODER SILENCEDETECT_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(SILENCEDETECT_DEPS)) += fate-filter-metadata-silencedetect -fate-filter-metadata-silencedetect: SRC = $(SAMPLES)/amrwb/seed-12k65.awb +fate-filter-metadata-silencedetect: SRC = $(TARGET_SAMPLES)/amrwb/seed-12k65.awb fate-filter-metadata-silencedetect: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',silencedetect=d=-20dB" EBUR128_METADATA_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER FLAC_DEMUXER FLAC_DECODER EBUR128_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(EBUR128_METADATA_DEPS)) += fate-filter-metadata-ebur128 -fate-filter-metadata-ebur128: SRC = $(SAMPLES)/filter/seq-3341-7_seq-3342-5-24bit.flac +fate-filter-metadata-ebur128: SRC = $(TARGET_SAMPLES)/filter/seq-3341-7_seq-3342-5-24bit.flac fate-filter-metadata-ebur128: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',ebur128=metadata=1" FATE_SAMPLES_FFPROBE += $(FATE_METADATA_FILTER-yes) diff --git a/tests/fate/gif.mak b/tests/fate/gif.mak index feda24062..3dc50b3b5 100644 --- a/tests/fate/gif.mak +++ b/tests/fate/gif.mak @@ -12,7 +12,7 @@ fate-gif-gray: CMD = framecrc -i $(TARGET_SAMPLES)/gif/Newtons_cradle_animation_ fate-gifenc%: fate-gif-color fate-gifenc%: PIXFMT = $(word 3, $(subst -, ,$(@))) -fate-gifenc%: SRC = $(SAMPLES)/gif/tc217.gif +fate-gifenc%: SRC = $(TARGET_SAMPLES)/gif/tc217.gif fate-gifenc%: CMD = framecrc -i $(SRC) -c:v gif -pix_fmt $(PIXFMT) FATE_GIF_ENC_PIXFMT = rgb8 bgr8 rgb4_byte bgr4_byte gray pal8 diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak index 0727882ce..d1c5817d9 100644 --- a/tests/fate/hevc.mak +++ b/tests/fate/hevc.mak @@ -1,12 +1,12 @@ HEVC_SAMPLES = \ AMP_A_Samsung_4 \ AMP_B_Samsung_4 \ - AMVP_C_Samsung_4 \ AMP_D_Hisilicon \ AMP_E_Hisilicon \ AMP_F_Hisilicon_3 \ AMVP_A_MTK_4 \ AMVP_B_MTK_4 \ + AMVP_C_Samsung_4 \ CAINIT_A_SHARP_4 \ CAINIT_B_SHARP_4 \ CAINIT_C_SHARP_3 \ @@ -21,23 +21,23 @@ HEVC_SAMPLES = \ DBLK_A_SONY_3 \ DBLK_B_SONY_3 \ DBLK_C_SONY_3 \ - DBLK_D_VIXS_1 \ DBLK_D_VIXS_2 \ - DBLK_E_VIXS_1 \ DBLK_E_VIXS_2 \ - DBLK_F_VIXS_1 \ DBLK_F_VIXS_2 \ - DBLK_G_VIXS_1 \ DBLK_G_VIXS_2 \ + DELTAQP_A_BRCM_4 \ DELTAQP_B_SONY_3 \ DELTAQP_C_SONY_3 \ DSLICE_A_HHI_5 \ DSLICE_B_HHI_5 \ DSLICE_C_HHI_5 \ - ENTP_A_LG_2 \ - ENTP_B_LG_2 \ - ENTP_C_LG_3 \ + ENTP_A_Qualcomm_1 \ + ENTP_B_Qualcomm_1 \ + ENTP_C_Qualcomm_1 \ EXT_A_ericsson_4 \ + FILLER_A_Sony_1 \ + HRD_A_Fujitsu_2 \ + INITQP_A_Sony_1 \ ipcm_A_NEC_3 \ ipcm_B_NEC_3 \ ipcm_C_NEC_3 \ @@ -45,7 +45,7 @@ HEVC_SAMPLES = \ ipcm_E_NEC_2 \ IPRED_A_docomo_2 \ IPRED_B_Nokia_3 \ - IPRED_C_Mitsubishi_2 \ + IPRED_C_Mitsubishi_3 \ LS_A_Orange_2 \ LS_B_ORANGE_4 \ LTRPSPS_A_Qualcomm_1 \ @@ -62,7 +62,12 @@ HEVC_SAMPLES = \ MVCLIP_A_qualcomm_3 \ MVDL1ZERO_A_docomo_3 \ MVEDGE_A_qualcomm_3 \ + NoOutPrior_A_Qualcomm_1 \ + NoOutPrior_B_Qualcomm_1 \ NUT_A_ericsson_5 \ + OPFLAG_A_Qualcomm_1 \ + OPFLAG_B_Qualcomm_1 \ + OPFLAG_C_Qualcomm_1 \ PICSIZE_A_Bossen_1 \ PICSIZE_B_Bossen_1 \ PICSIZE_C_Bossen_1 \ @@ -74,9 +79,9 @@ HEVC_SAMPLES = \ PMERGE_E_TI_3 \ POC_A_Bossen_3 \ PPS_A_qualcomm_7 \ - RAP_A_docomo_4 \ PS_A_VIDYO_3 \ PS_B_VIDYO_3 \ + RAP_A_docomo_4 \ RAP_B_Bossen_1 \ RPLM_A_qualcomm_4 \ RPLM_B_qualcomm_4 \ @@ -127,7 +132,7 @@ HEVC_SAMPLES = \ WPP_F_ericsson_MAIN_2 \ HEVC_SAMPLES_10BIT = \ - DBLK_A_MAIN10_VIXS_2 \ + DBLK_A_MAIN10_VIXS_3 \ WP_A_MAIN10_Toshiba_3 \ WP_MAIN10_B_Toshiba_3 \ WPP_A_ericsson_MAIN10_2 \ @@ -136,11 +141,18 @@ HEVC_SAMPLES_10BIT = \ WPP_D_ericsson_MAIN10_2 \ WPP_E_ericsson_MAIN10_2 \ WPP_F_ericsson_MAIN10_2 \ + INITQP_B_Sony_1 \ + +# equivalent bitstreams +# AMP_D_Hisilicon_3 -- AMP_D_Hisilicon +# AMP_E_Hisilicon_3 -- AMP_E_Hisilicon +# MVDL1ZERO_A_docomo_4 -- MVDL1ZERO_A_docomo_3 +# RAP_A_docomo_5 -- RAP_A_docomo_4 +# RPS_A_docomo_5 -- RPS_A_docomo_4 +# RPS_F_docomo_2 -- RPS_F_docomo_1 # do not pass: -# DELTAQP_A_BRCM_4.bit -- TODO uses CRC instead of MD5 -# HRD_A_Fujitsu_2.bin -- TODO uses hash 2 ("checksum") -# TSUNEQBD_A_MAIN10_Technicolor_2.bit (segfault) +# TSUNEQBD_A_MAIN10_Technicolor_2.bit (segfault mix 9-10bits) define FATE_HEVC_TEST FATE_HEVC += fate-hevc-conformance-$(1) diff --git a/tests/fate/image.mak b/tests/fate/image.mak index 7c2ac1084..cd589f69c 100644 --- a/tests/fate/image.mak +++ b/tests/fate/image.mak @@ -1,3 +1,35 @@ +FATE_ALIASPIX += fate-aliaspix-bgr +fate-aliaspix-bgr: CMD = framecrc -i $(TARGET_SAMPLES)/aliaspix/first.pix -pix_fmt bgr24 + +FATE_ALIASPIX += fate-aliaspix-gray +fate-aliaspix-gray: CMD = framecrc -i $(TARGET_SAMPLES)/aliaspix/firstgray.pix -pix_fmt gray + +FATE_ALIASPIX-$(call DEMDEC, IMAGE2, ALIAS_PIX) += $(FATE_ALIASPIX) +FATE_IMAGE += $(FATE_ALIASPIX-yes) +fate-aliaspix: $(FATE_ALIASPIX-yes) + +FATE_BRENDERPIX += fate-brenderpix-24 +fate-brenderpix-24: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/sbwheel.pix + +FATE_BRENDERPIX += fate-brenderpix-565 +fate-brenderpix-565: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/maximafront.pix + +FATE_BRENDERPIX += fate-brenderpix-defpal +fate-brenderpix-defpal: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/rivrock1.pix -pix_fmt rgb24 + +FATE_BRENDERPIX += fate-brenderpix-intpal +fate-brenderpix-intpal: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/testtex.pix -pix_fmt rgb24 + +FATE_BRENDERPIX += fate-brenderpix-y400a +fate-brenderpix-y400a: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/gears.pix + +FATE_BRENDERPIX-$(call DEMDEC, IMAGE2, BRENDER_PIX) += $(FATE_BRENDERPIX) +FATE_IMAGE += $(FATE_BRENDERPIX-yes) +fate-brenderpix: $(FATE_BRENDERPIX-yes) + +FATE_IMAGE-$(call PARSERDEMDEC, BMP, IMAGE2PIPE, BMP) += fate-bmpparser +fate-bmpparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/bmp/numbers.bmp -pix_fmt rgb24 + FATE_IMAGE-$(call DEMDEC, IMAGE2, DPX) += fate-dpx fate-dpx: CMD = framecrc -i $(TARGET_SAMPLES)/dpx/lighthouse_rgb48.dpx @@ -30,6 +62,38 @@ fate-pngparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/png1/feed_4x_c FATE_IMAGE-$(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/lena_gray.sgi -pix_fmt gray + +FATE_SGI += fate-sgi-gray16 +fate-sgi-gray16: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/lena_gray16.sgi -pix_fmt gray16le + +FATE_SGI += fate-sgi-rgb24 +fate-sgi-rgb24: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/lena_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/lena_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/lena_rgba.sgi -pix_fmt rgba + +FATE_SGI += fate-sgi-rgba64 +fate-sgi-rgba64: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/lena_rgba64.sgi -pix_fmt rgba64be + +FATE_SGI += fate-sgi-rgba64-rle +fate-sgi-rgba64-rle: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/maya_rgba64_rle.sgi -pix_fmt rgba64be + +FATE_SGI-$(call DEMDEC, IMAGE2, SGI) += $(FATE_SGI) + +FATE_SAMPLES_AVCONV += $(FATE_SGI-yes) +fate-sgi: $(FATE_SGI-yes) + FATE_SUNRASTER += fate-sunraster-1bit-raw fate-sunraster-1bit-raw: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-1bit-raw.sun @@ -102,6 +166,16 @@ fate-tiff: $(FATE_TIFF-yes) FATE_IMAGE-$(call DEMDEC, IMAGE2, XFACE) += fate-xface fate-xface: CMD = framecrc -i $(TARGET_SAMPLES)/xface/lena.xface +FATE_XBM += fate-xbm10 +fate-xbm10: CMD = framecrc -i $(TARGET_SAMPLES)/xbm/xl.xbm + +FATE_XBM += fate-xbm11 +fate-xbm11: CMD = framecrc -i $(TARGET_SAMPLES)/xbm/lbw.xbm + +FATE_XBM-$(call DEMDEC, IMAGE2, XBM) += $(FATE_XBM) +FATE_IMAGE += $(FATE_XBM-yes) +fate-xbm: $(FATE_XBM-yes) + FATE_IMAGE += $(FATE_IMAGE-yes) FATE_SAMPLES_FFMPEG += $(FATE_IMAGE) diff --git a/tests/fate/libavresample.mak b/tests/fate/libavresample.mak index bd4518e7b..c854a477a 100644 --- a/tests/fate/libavresample.mak +++ b/tests/fate/libavresample.mak @@ -38,7 +38,7 @@ fate-lavr-resample-$(3)-$(1)-$(2): CMD = ffmpeg -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) +fate-lavr-resample-$(3)-$(1)-$(2): REF = $(SAMPLES)/lavr/lavr-resample-$(3)-$(1)-$(2)-v2 endef $(call CROSS_TEST,$(SAMPLERATES),RESAMPLE,s16p,s16le,s16) @@ -46,6 +46,20 @@ $(call CROSS_TEST,$(SAMPLERATES),RESAMPLE,s32p,s32le,s16) $(call CROSS_TEST,$(SAMPLERATES),RESAMPLE,fltp,f32le,f32) $(call CROSS_TEST,$(SAMPLERATES),RESAMPLE,dblp,f64le,f64) +FATE_LAVR_RESAMPLE += fate-lavr-resample-linear +fate-lavr-resample-linear: tests/data/asynth-44100-1.wav +fate-lavr-resample-linear: CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-44100-1.wav -ar 48000 -filter_size 32 -linear_interp 1 -f s16le -af atrim=end_sample=10240 - +fate-lavr-resample-linear: CMP = oneoff +fate-lavr-resample-linear: CMP_UNIT = s16 +fate-lavr-resample-linear: REF = $(SAMPLES)/lavr/lavr-resample-linear + +FATE_LAVR_RESAMPLE += fate-lavr-resample-nearest +fate-lavr-resample-nearest: tests/data/asynth-48000-1.wav +fate-lavr-resample-nearest: CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-48000-1.wav -ar 44100 -filter_size 0 -phase_shift 0 -f s16le -af atrim=end_sample=10240 - +fate-lavr-resample-nearest: CMP = oneoff +fate-lavr-resample-nearest: CMP_UNIT = s16 +fate-lavr-resample-nearest: REF = $(SAMPLES)/lavr/lavr-resample-nearest + FATE_LAVR_RESAMPLE-$(call FILTERDEMDECENCMUX, RESAMPLE, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_LAVR_RESAMPLE) fate-lavr-resample: $(FATE_LAVR_RESAMPLE-yes) #FATE_LAVR += $(FATE_LAVR_RESAMPLE-yes) diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak index eeece4716..526ec16fa 100644 --- a/tests/fate/libavutil.mak +++ b/tests/fate/libavutil.mak @@ -29,6 +29,12 @@ FATE_LIBAVUTIL += fate-bprint fate-bprint: libavutil/bprint-test$(EXESUF) fate-bprint: CMD = run libavutil/bprint-test +FATE_LIBAVUTIL += fate-cpu +fate-cpu: libavutil/cpu-test$(EXESUF) +fate-cpu: CMD = runecho libavutil/cpu-test +fate-cpu: REF = /dev/null +fate-cpu: CMP = null + FATE_LIBAVUTIL += fate-crc fate-crc: libavutil/crc-test$(EXESUF) fate-crc: CMD = run libavutil/crc-test @@ -46,6 +52,12 @@ FATE_LIBAVUTIL += fate-fifo fate-fifo: libavutil/fifo-test$(EXESUF) fate-fifo: CMD = run libavutil/fifo-test +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: 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 diff --git a/tests/fate/libswresample.mak b/tests/fate/libswresample.mak index dd47de913..3b479a986 100644 --- a/tests/fate/libswresample.mak +++ b/tests/fate/libswresample.mak @@ -7,6 +7,10 @@ CROSS_TEST = $(foreach I,$(1), \ SAMPLERATES = 2626 8000 44100 48000 96000 +SAMPLERATES_LITE = 8000 44100 48000 + +SAMPLERATES_NN = 8000 44100 + define ARESAMPLE FATE_SWR_RESAMPLE += fate-swr-resample-$(3)-$(1)-$(2) fate-swr-resample-$(3)-$(1)-$(2): tests/data/asynth-$(1)-1.wav @@ -16,6 +20,7 @@ fate-swr-resample-$(3)-$(1)-$(2): CMP = stddev fate-swr-resample-$(3)-$(1)-$(2): CMP_UNIT = $(5) fate-swr-resample-$(3)-$(1)-$(2): FUZZ = 0.1 fate-swr-resample-$(3)-$(1)-$(2): REF = tests/data/asynth-$(1)-1.wav +endef #below list is generated by: #you can use this if you need to update it! @@ -260,14 +265,134 @@ fate-swr-resample-s32p-96000-48000: SIZE_TOLERANCE = 1152000 - 20480 fate-swr-resample-s32p-96000-8000: CMP_TARGET = 58.60 fate-swr-resample-s32p-96000-8000: SIZE_TOLERANCE = 1152000 - 20496 + +define ARESAMPLE_LIN +FATE_SWR_RESAMPLE += fate-swr-resample_lin-$(3)-$(1)-$(2) +fate-swr-resample_lin-$(3)-$(1)-$(2): tests/data/asynth-$(1)-1.wav +fate-swr-resample_lin-$(3)-$(1)-$(2): CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-$(1)-1.wav -af atrim=end_sample=10240,aresample=$(2):linear_interp=1:internal_sample_fmt=$(3),aformat=$(3),aresample=$(1):linear_interp=1:internal_sample_fmt=$(3) -f wav -acodec pcm_s16le - + +fate-swr-resample_lin-$(3)-$(1)-$(2): CMP = stddev +fate-swr-resample_lin-$(3)-$(1)-$(2): CMP_UNIT = $(5) +fate-swr-resample_lin-$(3)-$(1)-$(2): FUZZ = 0.1 +fate-swr-resample_lin-$(3)-$(1)-$(2): REF = tests/data/asynth-$(1)-1.wav endef +fate-swr-resample_lin-s16p-8000-44100: CMP_TARGET = 14.63 +fate-swr-resample_lin-s16p-8000-44100: SIZE_TOLERANCE = 96000 - 20480 + +fate-swr-resample_lin-s16p-8000-48000: CMP_TARGET = 14.53 +fate-swr-resample_lin-s16p-8000-48000: SIZE_TOLERANCE = 96000 - 20480 + +fate-swr-resample_lin-s16p-44100-8000: CMP_TARGET = 75.45 +fate-swr-resample_lin-s16p-44100-8000: SIZE_TOLERANCE = 529200 - 20486 + +fate-swr-resample_lin-s16p-44100-48000: CMP_TARGET = 9.68 +fate-swr-resample_lin-s16p-44100-48000: SIZE_TOLERANCE = 529200 - 20482 + +fate-swr-resample_lin-s16p-48000-8000: CMP_TARGET = 62.41 +fate-swr-resample_lin-s16p-48000-8000: SIZE_TOLERANCE = 576000 - 20484 + +fate-swr-resample_lin-s16p-48000-44100: CMP_TARGET = 0.68 +fate-swr-resample_lin-s16p-48000-44100: SIZE_TOLERANCE = 576000 - 20480 + +fate-swr-resample_lin-fltp-8000-44100: CMP_TARGET = 14.61 +fate-swr-resample_lin-fltp-8000-44100: SIZE_TOLERANCE = 96000 - 20480 + +fate-swr-resample_lin-fltp-8000-48000: CMP_TARGET = 14.50 +fate-swr-resample_lin-fltp-8000-48000: SIZE_TOLERANCE = 96000 - 20480 + +fate-swr-resample_lin-fltp-44100-8000: CMP_TARGET = 75.45 +fate-swr-resample_lin-fltp-44100-8000: SIZE_TOLERANCE = 529200 - 20486 + +fate-swr-resample_lin-fltp-44100-48000: CMP_TARGET = 9.67 +fate-swr-resample_lin-fltp-44100-48000: SIZE_TOLERANCE = 529200 - 20482 + +fate-swr-resample_lin-fltp-48000-8000: CMP_TARGET = 62.41 +fate-swr-resample_lin-fltp-48000-8000: SIZE_TOLERANCE = 576000 - 20484 + +fate-swr-resample_lin-fltp-48000-44100: CMP_TARGET = 0.63 +fate-swr-resample_lin-fltp-48000-44100: SIZE_TOLERANCE = 576000 - 20480 + +fate-swr-resample_lin-dblp-8000-44100: CMP_TARGET = 14.61 +fate-swr-resample_lin-dblp-8000-44100: SIZE_TOLERANCE = 96000 - 20480 + +fate-swr-resample_lin-dblp-8000-48000: CMP_TARGET = 14.50 +fate-swr-resample_lin-dblp-8000-48000: SIZE_TOLERANCE = 96000 - 20480 + +fate-swr-resample_lin-dblp-44100-8000: CMP_TARGET = 75.45 +fate-swr-resample_lin-dblp-44100-8000: SIZE_TOLERANCE = 529200 - 20486 + +fate-swr-resample_lin-dblp-44100-48000: CMP_TARGET = 9.67 +fate-swr-resample_lin-dblp-44100-48000: SIZE_TOLERANCE = 529200 - 20482 + +fate-swr-resample_lin-dblp-48000-8000: CMP_TARGET = 62.41 +fate-swr-resample_lin-dblp-48000-8000: SIZE_TOLERANCE = 576000 - 20484 + +fate-swr-resample_lin-dblp-48000-44100: CMP_TARGET = 0.63 +fate-swr-resample_lin-dblp-48000-44100: SIZE_TOLERANCE = 576000 - 20480 + +define ARESAMPLE_NN +FATE_SWR_RESAMPLE += fate-swr-resample_nn-$(3)-$(1)-$(2) +fate-swr-resample_nn-$(3)-$(1)-$(2): tests/data/asynth-$(1)-1.wav +fate-swr-resample_nn-$(3)-$(1)-$(2): CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-$(1)-1.wav -af atrim=end_sample=10240,aresample=$(2):filter_size=1:phase_shift=0:internal_sample_fmt=$(3),aformat=$(3),aresample=$(1):internal_sample_fmt=$(3) -f wav -acodec pcm_s16le - + +fate-swr-resample_nn-$(3)-$(1)-$(2): CMP = stddev +fate-swr-resample_nn-$(3)-$(1)-$(2): CMP_UNIT = $(5) +fate-swr-resample_nn-$(3)-$(1)-$(2): FUZZ = 0.1 +fate-swr-resample_nn-$(3)-$(1)-$(2): REF = tests/data/asynth-$(1)-1.wav +endef + +fate-swr-resample_nn-fltp-44100-8000: CMP_TARGET = 590.98 +fate-swr-resample_nn-fltp-44100-8000: SIZE_TOLERANCE = 529200 - 20486 + +fate-swr-resample_nn-fltp-8000-44100: CMP_TARGET = 3163.32 +fate-swr-resample_nn-fltp-8000-44100: SIZE_TOLERANCE = 96000 - 20480 + +fate-swr-resample_nn-s16p-44100-8000: CMP_TARGET = 590.97 +fate-swr-resample_nn-s16p-44100-8000: SIZE_TOLERANCE = 529200 - 20486 + +fate-swr-resample_nn-s16p-8000-44100: CMP_TARGET = 3163.39 +fate-swr-resample_nn-s16p-8000-44100: SIZE_TOLERANCE = 96000 - 20480 + +define ARESAMPLE_ASYNC +FATE_SWR_RESAMPLE += fate-swr-resample_async-$(3)-$(1)-$(2) +fate-swr-resample_async-$(3)-$(1)-$(2): tests/data/asynth-$(1)-1.wav +fate-swr-resample_async-$(3)-$(1)-$(2): CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-$(1)-1.wav -af atrim=end_sample=10240,asetpts=PTS+random\(0\)*200-100,aresample=$(2):async=50:min_hard_comp=0.100000:first_pts=0:internal_sample_fmt=$(3),aformat=$(3),aresample=$(1):internal_sample_fmt=$(3) -f wav -acodec pcm_s16le - + +fate-swr-resample_async-$(3)-$(1)-$(2): CMP = stddev +fate-swr-resample_async-$(3)-$(1)-$(2): CMP_UNIT = $(5) +fate-swr-resample_async-$(3)-$(1)-$(2): FUZZ = 0.1 +fate-swr-resample_async-$(3)-$(1)-$(2): REF = tests/data/asynth-$(1)-1.wav +endef + +fate-swr-resample_async-fltp-44100-8000: CMP_TARGET = 4047.25 +fate-swr-resample_async-fltp-44100-8000: SIZE_TOLERANCE = 529200 - 20132 + +fate-swr-resample_async-fltp-8000-44100: CMP_TARGET = 11193.77 +fate-swr-resample_async-fltp-8000-44100: SIZE_TOLERANCE = 96000 - 20312 + +fate-swr-resample_async-s16p-44100-8000: CMP_TARGET = 4047.24 +fate-swr-resample_async-s16p-44100-8000: SIZE_TOLERANCE = 529200 - 20132 + +fate-swr-resample_async-s16p-8000-44100: CMP_TARGET = 11194.08 +fate-swr-resample_async-s16p-8000-44100: SIZE_TOLERANCE = 96000 - 20312 $(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE,s16p,s16le,s16) $(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE,s32p,s32le,s16) $(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE,fltp,f32le,s16) $(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE,dblp,f64le,s16) +$(call CROSS_TEST,$(SAMPLERATES_LITE),ARESAMPLE_LIN,s16p,s16le,s16) +$(call CROSS_TEST,$(SAMPLERATES_LITE),ARESAMPLE_LIN,fltp,f32le,s16) +$(call CROSS_TEST,$(SAMPLERATES_LITE),ARESAMPLE_LIN,dblp,f64le,s16) + +$(call CROSS_TEST,$(SAMPLERATES_NN),ARESAMPLE_NN,s16p,s16le,s16) +$(call CROSS_TEST,$(SAMPLERATES_NN),ARESAMPLE_NN,fltp,f32le,s16) + +$(call CROSS_TEST,$(SAMPLERATES_NN),ARESAMPLE_ASYNC,s16p,s16le,s16) +$(call CROSS_TEST,$(SAMPLERATES_NN),ARESAMPLE_ASYNC,fltp,f32le,s16) + + FATE_SWR_RESAMPLE-$(call FILTERDEMDECENCMUX, ARESAMPLE, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_SWR_RESAMPLE) fate-swr-resample: $(FATE_SWR_RESAMPLE-yes) FATE_SWR += $(FATE_SWR_RESAMPLE-yes) diff --git a/tests/fate/opus.mak b/tests/fate/opus.mak new file mode 100644 index 000000000..b13d86c13 --- /dev/null +++ b/tests/fate/opus.mak @@ -0,0 +1,47 @@ +# The samples were produced by simply rewrapping the official test vectors from +# their custom format into Matroska. +# The reference files were created with our decoder and tested against the +# libopus output with the official opus_compare tool. We cannot use libopus +# output as reference directly, because the use of different resamplers would +# require too high fuzz values, which can hide bugs. +# Before adding new tests here, always make sure they pass opus_compare. + +OPUS_CELT_SAMPLES = $(addprefix testvector, 01 07 11) tron.6ch.tinypkts +OPUS_HYBRID_SAMPLES = $(addprefix testvector, 05 06) +OPUS_SILK_SAMPLES = $(addprefix testvector, 02 03 04) +OPUS_SAMPLES = $(addprefix testvector, 08 09 10 12) + +define FATE_OPUS_TEST +FATE_OPUS += fate-opus-$(1) +FATE_OPUS$(2) += fate-opus-$(1) +fate-opus-$(1): CMD = ffmpeg -i $(TARGET_SAMPLES)/opus/$(1).mka -f s16le - +fate-opus-$(1): REF = $(SAMPLES)/opus/$(1).dec +endef + +$(foreach N,$(OPUS_CELT_SAMPLES), $(eval $(call FATE_OPUS_TEST,$(N),_CELT))) +$(foreach N,$(OPUS_HYBRID_SAMPLES),$(eval $(call FATE_OPUS_TEST,$(N),_HYBRID))) +$(foreach N,$(OPUS_SILK_SAMPLES), $(eval $(call FATE_OPUS_TEST,$(N),_SILK))) +$(foreach N,$(OPUS_SAMPLES), $(eval $(call FATE_OPUS_TEST,$(N),))) + +FATE_OPUS := $(sort $(FATE_OPUS)) + +$(FATE_OPUS): CMP = stddev +$(FATE_OPUS): CMP_UNIT = s16 +$(FATE_OPUS): FUZZ = 3 +fate-opus-testvector02: CMP_TARGET = 191 +fate-opus-testvector03: CMP_TARGET = 139 +fate-opus-testvector04: CMP_TARGET = 119 +fate-opus-testvector05: CMP_TARGET = 108 +fate-opus-testvector06: CMP_TARGET = 106 +fate-opus-testvector08: CMP_TARGET = 6 +fate-opus-testvector10: CMP_TARGET = 38 +fate-opus-testvector12: CMP_TARGET = 160 + +$(FATE_OPUS_CELT): CMP = oneoff +$(FATE_OPUS_CELT): FUZZ = 6 + +FATE_SAMPLES_AVCONV-$(call DEMDEC, MATROSKA, OPUS) += $(FATE_OPUS) +fate-opus-celt: $(FATE_OPUS_CELT) +fate-opus-hybrid: $(FATE_OPUS_HYBRID) +fate-opus-silk: $(FATE_OPUS_SILK) +fate-opus: $(FATE_OPUS) diff --git a/tests/fate/screen.mak b/tests/fate/screen.mak index 12250ca66..72e9b4ccc 100644 --- a/tests/fate/screen.mak +++ b/tests/fate/screen.mak @@ -5,6 +5,9 @@ fate-cscd: CMD = framecrc -i $(TARGET_SAMPLES)/CSCD/sample_video.avi -an -pix_fm FATE_SCREEN-$(call DEMDEC, AVI, DXTORY) += fate-dxtory fate-dxtory: CMD = framecrc -i $(TARGET_SAMPLES)/dxtory/dxtory_mic.avi +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, FIC) += fate-fic-avi +fate-fic-avi: CMD = framecrc -i $(TARGET_SAMPLES)/fic/fic-partial-2MB.avi -an + FATE_FRAPS += fate-fraps-v0 fate-fraps-v0: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/Griffin_Ragdoll01-partial.avi diff --git a/tests/fate/seek.mak b/tests/fate/seek.mak index fe8d3ab91..0dca1fa77 100644 --- a/tests/fate/seek.mak +++ b/tests/fate/seek.mak @@ -1,10 +1,15 @@ # files from fate-acodec -FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_IMA_QT, AIFF) += adpcm-ima_qt -FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_IMA_WAV, WAV) += adpcm-ima_wav -FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_MS, WAV) += adpcm-ms -FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_SWF, FLV) += adpcm-swf -FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_YAMAHA, WAV) += adpcm-yamaha +FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_IMA_QT, AIFF) += adpcm-ima_qt \ + adpcm-ima_qt-trellis +FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_IMA_WAV, WAV) += adpcm-ima_wav \ + adpcm-ima_wav-trellis +FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_MS, WAV) += adpcm-ms \ + adpcm-ms-trellis +FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_SWF, FLV) += adpcm-swf \ + adpcm-swf-trellis +FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_YAMAHA, WAV) += adpcm-yamaha \ + adpcm-yamaha-trellis FATE_SEEK_ACODEC-$(call ENCDEC, ALAC, MOV) += alac FATE_SEEK_ACODEC-$(call ENCDEC, FLAC, FLAC) += flac FATE_SEEK_ACODEC-$(call ENCDEC, MP2, MP2 MP3) += mp2 @@ -28,6 +33,11 @@ fate-seek-acodec-adpcm-ima_wav: SRC = fate/acodec-adpcm-ima_wav.wav fate-seek-acodec-adpcm-ms: SRC = fate/acodec-adpcm-ms.wav fate-seek-acodec-adpcm-swf: SRC = fate/acodec-adpcm-swf.flv fate-seek-acodec-adpcm-yamaha: SRC = fate/acodec-adpcm-yamaha.wav +fate-seek-acodec-adpcm-ima_qt-trellis: SRC = fate/acodec-adpcm-ima_qt-trellis.aiff +fate-seek-acodec-adpcm-ima_wav-trellis: SRC = fate/acodec-adpcm-ima_wav-trellis.wav +fate-seek-acodec-adpcm-ms-trellis: SRC = fate/acodec-adpcm-ms-trellis.wav +fate-seek-acodec-adpcm-swf-trellis: SRC = fate/acodec-adpcm-swf-trellis.flv +fate-seek-acodec-adpcm-yamaha-trellis: SRC = fate/acodec-adpcm-yamaha-trellis.wav fate-seek-acodec-alac: SRC = fate/acodec-alac.mov fate-seek-acodec-flac: SRC = fate/acodec-flac.flac fate-seek-acodec-mp2: SRC = fate/acodec-mp2.mp2 @@ -127,6 +137,7 @@ fate-seek-vsynth2-mpeg4-adap: SRC = fate/vsynth2-mpeg4-adap.avi fate-seek-vsynth2-mpeg4-adv: SRC = fate/vsynth2-mpeg4-adv.avi fate-seek-vsynth2-mpeg4-error: SRC = fate/vsynth2-mpeg4-error.avi fate-seek-vsynth2-mpeg4-nr: SRC = fate/vsynth2-mpeg4-nr.avi +fate-seek-vsynth2-mpeg4-nsse: SRC = fate/vsynth2-mpeg4-nsse.avi fate-seek-vsynth2-mpeg4-qpel: SRC = fate/vsynth2-mpeg4-qpel.avi fate-seek-vsynth2-mpeg4-qprd: SRC = fate/vsynth2-mpeg4-qprd.avi fate-seek-vsynth2-mpeg4-rc: SRC = fate/vsynth2-mpeg4-rc.avi diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak index 33d798e64..0c7188272 100644 --- a/tests/fate/subtitles.mak +++ b/tests/fate/subtitles.mak @@ -52,6 +52,9 @@ fate-sub-vplayer: CMD = md5 -i $(TARGET_SAMPLES)/sub/VPlayer_capability_tester.t FATE_SUBTITLES_ASS-$(call DEMDEC, WEBVTT, WEBVTT) += fate-sub-webvtt fate-sub-webvtt: CMD = md5 -i $(TARGET_SAMPLES)/sub/WebVTT_capability_tester.vtt -f ass +FATE_SUBTITLES_ASS-$(call ENCMUX, WEBVTT, WEBVTT) += fate-sub-webvttenc +fate-sub-webvttenc: CMD = md5 -i $(TARGET_SAMPLES)/sub/SubRip_capability_tester.srt -f webvtt + FATE_SUBTITLES_ASS-$(call ALLYES, MICRODVD_DEMUXER MICRODVD_DECODER ICONV) += fate-sub-charenc fate-sub-charenc: CMD = md5 -sub_charenc cp1251 -i $(TARGET_SAMPLES)/sub/cp1251-subtitles.sub -f ass diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index 5c8c1979b..cefd4d33b 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -1,12 +1,15 @@ fate-vsynth1-%: SRC = tests/data/vsynth1.yuv fate-vsynth2-%: SRC = tests/data/vsynth2.yuv +fate-vsynth3-%: SRC = tests/data/vsynth3.yuv fate-vsynth%: CODEC = $(word 3, $(subst -, ,$(@))) fate-vsynth%: FMT = avi fate-vsynth%: CMD = enc_dec "rawvideo -s 352x288 -pix_fmt yuv420p $(RAWDECOPTS)" $(SRC) $(FMT) "-c $(CODEC) $(ENCOPTS)" rawvideo "-s 352x288 -pix_fmt yuv420p -vsync 0 $(DECOPTS)" -keep "$(DECINOPTS)" +fate-vsynth3-%: CMD = enc_dec "rawvideo -s $(FATEW)x$(FATEH) -pix_fmt yuv420p $(RAWDECOPTS)" $(SRC) $(FMT) "-c $(CODEC) $(ENCOPTS)" rawvideo "-s $(FATEW)x$(FATEH) -pix_fmt yuv420p -vsync 0 $(DECOPTS)" -keep "$(DECINOPTS)" fate-vsynth%: CMP_UNIT = 1 fate-vsynth%: REF = $(SRC_PATH)/tests/ref/vsynth/$(@:fate-%=%) FATE_VCODEC-$(call ENCDEC, AMV, AVI) += amv +fate-vsynth%-amv: ENCOPTS = -strict -1 FATE_VCODEC-$(call ENCDEC, ASV1, AVI) += asv1 fate-vsynth%-asv1: ENCOPTS = -qscale 10 @@ -15,6 +18,7 @@ FATE_VCODEC-$(call ENCDEC, ASV2, AVI) += asv2 fate-vsynth%-asv2: ENCOPTS = -qscale 10 FATE_VCODEC-$(call ENCDEC, CLJR, AVI) += cljr +fate-vsynth%-cljr: ENCOPTS = -strict -1 FATE_VCODEC-$(call ENCDEC, DNXHD, DNXHD) += dnxhd-720p \ dnxhd-720p-rd \ @@ -59,10 +63,10 @@ fate-vsynth%-ffv1: ENCOPTS = -slices 4 fate-vsynth%-ffv1.0: CODEC = ffv1 FATE_VCODEC-$(call ENCDEC, FFVHUFF, AVI) += ffvhuff ffvhuff444 ffvhuff420p12 ffvhuff422p10left ffvhuff444p16 -fate-vsynth%-ffvhuff444: ENCOPTS = -strict -2 -vcodec ffvhuff -pix_fmt yuv444p -fate-vsynth%-ffvhuff420p12: ENCOPTS = -strict -2 -vcodec ffvhuff -pix_fmt yuv420p12le -fate-vsynth%-ffvhuff422p10left: ENCOPTS = -strict -2 -vcodec ffvhuff -pix_fmt yuv422p10le -pred left -fate-vsynth%-ffvhuff444p16: ENCOPTS = -strict -2 -vcodec ffvhuff -pix_fmt yuv444p16le -pred plane +fate-vsynth%-ffvhuff444: ENCOPTS = -vcodec ffvhuff -pix_fmt yuv444p +fate-vsynth%-ffvhuff420p12: ENCOPTS = -vcodec ffvhuff -pix_fmt yuv420p12le +fate-vsynth%-ffvhuff422p10left: ENCOPTS = -vcodec ffvhuff -pix_fmt yuv422p10le -pred left +fate-vsynth%-ffvhuff444p16: ENCOPTS = -vcodec ffvhuff -pix_fmt yuv444p16le -pred plane FATE_VCODEC-$(call ENCDEC, FLASHSV, FLV) += flashsv fate-vsynth%-flashsv: ENCOPTS = -sws_flags neighbor+full_chroma_int @@ -87,9 +91,11 @@ fate-vsynth%-h263: ENCOPTS = -qscale 10 fate-vsynth%-h263-obmc: ENCOPTS = -qscale 10 -obmc 1 fate-vsynth%-h263p: ENCOPTS = -qscale 2 -flags +aic -umv 1 -aiv 1 -ps 300 -FATE_VCODEC-$(call ENCDEC, HUFFYUV, AVI) += huffyuv -fate-vsynth%-huffyuv: ENCOPTS = -pix_fmt yuv422p -sws_flags neighbor -fate-vsynth%-huffyuv: DECOPTS = -strict -2 -sws_flags neighbor +FATE_VCODEC-$(call ENCDEC, HUFFYUV, AVI) += huffyuv huffyuvbgr24 +fate-vsynth%-huffyuv: ENCOPTS = -vcodec huffyuv -pix_fmt yuv422p -sws_flags neighbor +fate-vsynth%-huffyuv: DECOPTS = -sws_flags neighbor +fate-vsynth%-huffyuvbgr24: ENCOPTS = -vcodec huffyuv -pix_fmt bgr24 -sws_flags neighbor +fate-vsynth%-huffyuvbgr24: DECOPTS = -sws_flags neighbor FATE_VCODEC-$(call ENCDEC, JPEGLS, AVI) += jpegls fate-vsynth%-jpegls: ENCOPTS = -sws_flags neighbor+full_chroma_int @@ -163,7 +169,8 @@ FATE_MPEG4_AVI = mpeg4-rc \ mpeg4-qpel \ mpeg4-thread \ mpeg4-error \ - mpeg4-nr + mpeg4-nr \ + mpeg4-nsse FATE_VCODEC-$(call ENCDEC, MPEG4, MP4 MOV) += $(FATE_MPEG4_MP4) FATE_VCODEC-$(call ENCDEC, MPEG4, AVI) += $(FATE_MPEG4_AVI) @@ -185,6 +192,10 @@ fate-vsynth%-mpeg4-error: ENCOPTS = -qscale 7 -flags +mv4+aic \ fate-vsynth%-mpeg4-nr: ENCOPTS = -qscale 8 -flags +mv4 -mbd rd -nr 200 +fate-vsynth%-mpeg4-nsse: ENCOPTS = -qscale 7 -cmp nsse -subcmp nsse \ + -mbcmp nsse -precmp nsse \ + -skipcmp nsse + fate-vsynth%-mpeg4-qpel: ENCOPTS = -qscale 7 -flags +mv4+qpel -mbd 2 \ -bf 2 -cmp 1 -subcmp 2 @@ -242,15 +253,15 @@ fate-vsynth%-rv20: ENCOPTS = -qscale 10 fate-vsynth%-rv20: FMT = rm FATE_VCODEC-$(call ENCDEC, SNOW, AVI) += snow snow-hpel snow-ll -fate-vsynth%-snow: ENCOPTS = -strict -2 -qscale 2 -flags +qpel \ +fate-vsynth%-snow: ENCOPTS = -qscale 2 -flags +qpel \ -me_method iter -dia_size 2 \ -cmp 12 -subcmp 12 -s 128x64 -fate-vsynth%-snow-hpel: ENCOPTS = -strict -2 -qscale 2 \ +fate-vsynth%-snow-hpel: ENCOPTS = -qscale 2 \ -me_method iter -dia_size 2 \ -cmp 12 -subcmp 12 -s 128x64 -fate-vsynth%-snow-ll: ENCOPTS = -strict -2 -qscale .001 -pred 1 \ +fate-vsynth%-snow-ll: ENCOPTS = -qscale .001 -pred 1 \ -flags +mv4+qpel FATE_VCODEC-$(call ENCDEC, SVQ1, MOV) += svq1 @@ -290,12 +301,24 @@ FATE_VCODEC-$(call ENCDEC, ZLIB, AVI) += zlib FATE_VCODEC += $(FATE_VCODEC-yes) FATE_VSYNTH1 = $(FATE_VCODEC:%=fate-vsynth1-%) FATE_VSYNTH2 = $(FATE_VCODEC:%=fate-vsynth2-%) +# Redundant tests because they just resize the input +RESIZE_OFF = dnxhd-720p dnxhd-720p-rd dnxhd-720p-10bit dnxhd-1080i \ + dv dv-411 dv-50 avui snow snow-hpel snow-ll +# Incorrect parameters - usually size or color format restrictions +INC_PAR_OFF = h261 h261-trellis h263 h263p h263-obmc msvideo1 \ + roqvideo rv10 rv20 y41p qtrlegray +VSYNTH3_OFF = $(RESIZE_OFF) $(INC_PAR_OFF) + +FATE_VCODEC3 = $(filter-out $(VSYNTH3_OFF),$(FATE_VCODEC)) +FATE_VSYNTH3 = $(FATE_VCODEC3:%=fate-vsynth3-%) $(FATE_VSYNTH1): tests/data/vsynth1.yuv $(FATE_VSYNTH2): tests/data/vsynth2.yuv +$(FATE_VSYNTH3): tests/data/vsynth3.yuv -FATE_AVCONV += $(FATE_VSYNTH1) $(FATE_VSYNTH2) +FATE_AVCONV += $(FATE_VSYNTH1) $(FATE_VSYNTH2) $(FATE_VSYNTH3) fate-vsynth1: $(FATE_VSYNTH1) fate-vsynth2: $(FATE_VSYNTH2) -fate-vcodec: fate-vsynth1 fate-vsynth2 +fate-vsynth3: $(FATE_VSYNTH3) +fate-vcodec: fate-vsynth1 fate-vsynth2 fate-vsynth3 diff --git a/tests/fate/video.mak b/tests/fate/video.mak index f1e549c2d..7e5416c91 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -10,6 +10,9 @@ fate-4xm: $(FATE_4XM) FATE_VIDEO-$(call DEMDEC, AVI, AASC) += fate-aasc fate-aasc: CMD = framecrc -i $(TARGET_SAMPLES)/aasc/AASC-1.5MB.AVI -pix_fmt rgb24 +FATE_VIDEO-$(call DEMDEC, MOV, AIC) += fate-aic +fate-aic: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/aic/small_apple_intermediate_codec.mov -an -vframes 15 + FATE_VIDEO-$(call DEMDEC, MM, MMVIDEO) += fate-alg-mm fate-alg-mm: CMD = framecrc -i $(TARGET_SAMPLES)/alg-mm/ibmlogo.mm -an -pix_fmt rgb24 @@ -181,7 +184,7 @@ FATE_VIDEO-$(call DEMDEC, MSNWC_TCP, MIMIC) += fate-mimic fate-mimic: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/mimic/mimic2-womanloveffmpeg.cam FATE_VIDEO-$(call DEMDEC, MOV, MJPEGB) += fate-mjpegb -fate-mjpegb: CMD = framecrc -idct simple -flags +bitexact -i $(TARGET_SAMPLES)/mjpegb/mjpegb_part.mov -an +fate-mjpegb: CMD = framecrc -idct simple -fflags +bitexact -i $(TARGET_SAMPLES)/mjpegb/mjpegb_part.mov -an FATE_VIDEO-$(call DEMDEC, MVI, MOTIONPIXELS) += fate-motionpixels fate-motionpixels: CMD = framecrc -i $(TARGET_SAMPLES)/motion-pixels/INTRO-partial.MVI -an -pix_fmt rgb24 -vframes 111 @@ -189,6 +192,15 @@ fate-motionpixels: CMD = framecrc -i $(TARGET_SAMPLES)/motion-pixels/INTRO-parti FATE_VIDEO-$(call DEMDEC, MPEGTS, MPEG2VIDEO) += fate-mpeg2-field-enc fate-mpeg2-field-enc: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -an -vframes 30 +FATE_VIDEO-$(call DEMDEC, MV, MVC1) += fate-mv-mvc1 +fate-mv-mvc1: CMD = framecrc -i $(TARGET_SAMPLES)/mv/posture.mv -an -frames 25 -pix_fmt rgb555le + +FATE_VIDEO-$(call DEMDEC, MV, MVC2) += fate-mv-mvc2 +fate-mv-mvc2: CMD = framecrc -i $(TARGET_SAMPLES)/mv/12345.mv -an -frames 30 -pix_fmt bgra + +FATE_VIDEO-$(call DEMDEC, MV, SGIRLE) += fate-mv-sgirle +fate-mv-sgirle: CMD = framecrc -i $(TARGET_SAMPLES)/mv/pet-rle.movie -an + FATE_VIDEO-$(call DEMDEC, MXG, MXPEG) += fate-mxpeg fate-mxpeg: CMD = framecrc -idct simple -flags +bitexact -i $(TARGET_SAMPLES)/mxpeg/m1.mxg -an @@ -261,7 +273,7 @@ fate-v410dec: CMD = framecrc -i $(TARGET_SAMPLES)/v410/lenav410.mov -pix_fmt yuv FATE_VIDEO-$(call ENCDEC, V410 PGMYUV, AVI IMAGE2) += fate-v410enc fate-v410enc: $(VREF) -fate-v410enc: CMD = md5 -f image2 -vcodec pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -flags +bitexact -vcodec v410 -f avi +fate-v410enc: CMD = md5 -f image2 -vcodec pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -fflags +bitexact -vcodec v410 -f avi FATE_VIDEO-$(call DEMDEC, SIFF, VB) += fate-vb fate-vb: CMD = framecrc -i $(TARGET_SAMPLES)/SIFF/INTRO_B.VB -t 3 -pix_fmt rgb24 -an diff --git a/tests/fate/vpx.mak b/tests/fate/vpx.mak index 89d892453..54be95026 100644 --- a/tests/fate/vpx.mak +++ b/tests/fate/vpx.mak @@ -31,6 +31,9 @@ fate-vp8-alpha: CMD = framecrc -i $(TARGET_SAMPLES)/vp8_alpha/vp8_video_with_alp FATE_SAMPLES_AVCONV += $(FATE_VP6-yes) fate-vp6: $(FATE_VP6-yes) +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, VP7) += fate-vp7 +fate-vp7: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp7/potter-40.vp7 -frames 30 -an + VP8_SUITE = 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 define FATE_VP8_SUITE diff --git a/tests/fate/wavpack.mak b/tests/fate/wavpack.mak index 98e09980f..240f5ead9 100644 --- a/tests/fate/wavpack.mak +++ b/tests/fate/wavpack.mak @@ -89,12 +89,12 @@ FATE_WAVPACK-$(call DEMDEC, MATROSKA, WAVPACK) += fate-wavpack-matroskamode fate-wavpack-matroskamode: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/matroska_mode.mka -f s16le 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 -flags +bitexact -f matroska +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 = a2987e2e51e01a35e47e7da13eb47a35 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 -flags +bitexact -f matroska +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 = ffba4ddea1ba71f7a5901d9ed1a267be diff --git a/tests/filtergraphs/channelmap b/tests/filtergraphs/channelmap_one_int similarity index 100% rename from tests/filtergraphs/channelmap rename to tests/filtergraphs/channelmap_one_int diff --git a/tests/filtergraphs/channelmap_one_str b/tests/filtergraphs/channelmap_one_str new file mode 100644 index 000000000..3c658fc58 --- /dev/null +++ b/tests/filtergraphs/channelmap_one_str @@ -0,0 +1 @@ +channelmap=map=FR|FL:channel_layout=stereo diff --git a/tests/lavf-regression.sh b/tests/lavf-regression.sh index 9b1b69f5a..0efbc9c85 100755 --- a/tests/lavf-regression.sh +++ b/tests/lavf-regression.sh @@ -16,7 +16,7 @@ ENC_OPTS="$ENC_OPTS -metadata title=lavftest" do_lavf_fate() { file=${outfile}lavf.$1 - input="${samples}/$2" + input="${target_samples}/$2" do_avconv $file $DEC_OPTS -i "$input" $ENC_OPTS -vcodec copy -acodec copy do_avconv_crc $file $DEC_OPTS -i $target_path/$file $3 } @@ -64,11 +64,11 @@ do_audio_only() } if [ -n "$do_avi" ] ; then -do_lavf avi "" "-acodec mp2 -ab 64k" +do_lavf avi "" "-acodec mp2 -ar 44100 -ab 64k" fi if [ -n "$do_asf" ] ; then -do_lavf asf "" "-acodec mp2 -ab 64k" "-r 25" +do_lavf asf "" "-acodec mp2 -ar 44100 -ab 64k" "-r 25" fi if [ -n "$do_rm" ] ; then @@ -79,7 +79,7 @@ do_avconv $file $DEC_OPTS -f image2 -vcodec pgmyuv -i $raw_src $DEC_OPTS -ar 441 fi if [ -n "$do_mpg" ] ; then -do_lavf_timecode mpg "-ab 64k" +do_lavf_timecode mpg "-ab 64k -ar 44100" fi if [ -n "$do_mxf" ] ; then @@ -91,7 +91,7 @@ do_lavf mxf_d10 "-ar 48000 -ac 2" "-r 25 -vf scale=720:576,pad=720:608:0:32 -vco fi if [ -n "$do_ts" ] ; then -do_lavf ts "" "-ab 64k -mpegts_transport_stream_id 42" +do_lavf ts "" "-ab 64k -mpegts_transport_stream_id 42 -ar 44100" fi if [ -n "$do_swf" ] ; then @@ -99,7 +99,7 @@ do_lavf swf "" "-an" fi if [ -n "$do_ffm" ] ; then -do_lavf ffm +do_lavf ffm "" "-ar 44100" fi if [ -n "$do_flm" ] ; then @@ -133,13 +133,13 @@ do_lavf gxf "-ar 48000" "-r 25 -s pal -ac 1" fi if [ -n "$do_nut" ] ; then -do_lavf nut "" "-acodec mp2 -ab 64k" +do_lavf nut "" "-acodec mp2 -ab 64k -ar 44100" fi if [ -n "$do_mkv" ] ; then do_lavf mkv "" "-acodec mp2 -ab 64k -vcodec mpeg4 \ -attach ${raw_src%/*}/00.pgm -metadata:s:t mimetype=image/x-portable-greymap" -do_lavf mkv "" "-acodec mp2 -ab 64k -vcodec mpeg4" +do_lavf mkv "" "-acodec mp2 -ab 64k -vcodec mpeg4 -ar 44100" fi if [ -n "$do_mp3" ] ; then diff --git a/tests/ref/acodec/adpcm-adx b/tests/ref/acodec/adpcm-adx index 2bc49ab94..b96d99a73 100644 --- a/tests/ref/acodec/adpcm-adx +++ b/tests/ref/acodec/adpcm-adx @@ -1,4 +1,4 @@ 0a30509d9296b857e134b762b76dbc31 *tests/data/fate/acodec-adpcm-adx.adx 297720 tests/data/fate/acodec-adpcm-adx.adx -2dbc601ed5259f4d74dc48ccd8da7eaf *tests/data/fate/acodec-adpcm-adx.out.wav +7260139001fcac62384dad50a1023e75 *tests/data/fate/acodec-adpcm-adx.out.wav stddev: 6989.46 PSNR: 19.44 MAXDIFF:65398 bytes: 1058400/ 1058432 diff --git a/tests/ref/acodec/adpcm-adx-trellis b/tests/ref/acodec/adpcm-adx-trellis new file mode 100644 index 000000000..fff029122 --- /dev/null +++ b/tests/ref/acodec/adpcm-adx-trellis @@ -0,0 +1,4 @@ +0a30509d9296b857e134b762b76dbc31 *tests/data/fate/acodec-adpcm-adx-trellis.adx +297720 tests/data/fate/acodec-adpcm-adx-trellis.adx +7260139001fcac62384dad50a1023e75 *tests/data/fate/acodec-adpcm-adx-trellis.out.wav +stddev: 6989.46 PSNR: 19.44 MAXDIFF:65398 bytes: 1058400/ 1058432 diff --git a/tests/ref/acodec/adpcm-ima_qt b/tests/ref/acodec/adpcm-ima_qt index ace5325dc..364dfa1e0 100644 --- a/tests/ref/acodec/adpcm-ima_qt +++ b/tests/ref/acodec/adpcm-ima_qt @@ -1,4 +1,4 @@ 44691f14cf5bbef5005df27c692b93ab *tests/data/fate/acodec-adpcm-ima_qt.aiff 281252 tests/data/fate/acodec-adpcm-ima_qt.aiff -b0fafd002c38fb70acaddfda1a31ed61 *tests/data/fate/acodec-adpcm-ima_qt.out.wav +7d2f26ea48731b2399718de0f6c39f0c *tests/data/fate/acodec-adpcm-ima_qt.out.wav stddev: 904.76 PSNR: 37.20 MAXDIFF:34029 bytes: 1058400/ 1058560 diff --git a/tests/ref/acodec/adpcm-ima_qt-trellis b/tests/ref/acodec/adpcm-ima_qt-trellis new file mode 100644 index 000000000..0a09965e1 --- /dev/null +++ b/tests/ref/acodec/adpcm-ima_qt-trellis @@ -0,0 +1,4 @@ +15f895c2e7119714f94333e3214d8426 *tests/data/fate/acodec-adpcm-ima_qt-trellis.aiff +281252 tests/data/fate/acodec-adpcm-ima_qt-trellis.aiff +593d68369c87d4e3b7323b1bea3e9315 *tests/data/fate/acodec-adpcm-ima_qt-trellis.out.wav +stddev: 716.74 PSNR: 39.22 MAXDIFF:29633 bytes: 1058400/ 1058560 diff --git a/tests/ref/acodec/adpcm-ima_wav b/tests/ref/acodec/adpcm-ima_wav index 6d83fd5f1..bd3306dfc 100644 --- a/tests/ref/acodec/adpcm-ima_wav +++ b/tests/ref/acodec/adpcm-ima_wav @@ -1,4 +1,4 @@ 56b75c3a6dacedcf2ce7b0586aa33594 *tests/data/fate/acodec-adpcm-ima_wav.wav 267324 tests/data/fate/acodec-adpcm-ima_wav.wav -ddddfa47302da540abf19224202bef57 *tests/data/fate/acodec-adpcm-ima_wav.out.wav +78a2af1c895792d0c221d127bdd48ece *tests/data/fate/acodec-adpcm-ima_wav.out.wav stddev: 903.51 PSNR: 37.21 MAXDIFF:34026 bytes: 1058400/ 1061748 diff --git a/tests/ref/acodec/adpcm-ima_wav-trellis b/tests/ref/acodec/adpcm-ima_wav-trellis new file mode 100644 index 000000000..10d78c74f --- /dev/null +++ b/tests/ref/acodec/adpcm-ima_wav-trellis @@ -0,0 +1,4 @@ +f9075c7a3adb2cd114b0bac69afcada6 *tests/data/fate/acodec-adpcm-ima_wav-trellis.wav +267324 tests/data/fate/acodec-adpcm-ima_wav-trellis.wav +26a9b280c14737b159c56e60181f1170 *tests/data/fate/acodec-adpcm-ima_wav-trellis.out.wav +stddev: 710.03 PSNR: 39.30 MAXDIFF:25944 bytes: 1058400/ 1061748 diff --git a/tests/ref/acodec/adpcm-ms b/tests/ref/acodec/adpcm-ms index eb8515d98..c760b783c 100644 --- a/tests/ref/acodec/adpcm-ms +++ b/tests/ref/acodec/adpcm-ms @@ -1,4 +1,4 @@ a407b87daeef5b25dfb6c5b3f519e9c1 *tests/data/fate/acodec-adpcm-ms.wav 268378 tests/data/fate/acodec-adpcm-ms.wav -22863fb278c4e0ebe9c34cb15db5dd6b *tests/data/fate/acodec-adpcm-ms.out.wav +7be370f937c51e8a967e6a3d08d5156a *tests/data/fate/acodec-adpcm-ms.out.wav stddev: 1050.01 PSNR: 35.91 MAXDIFF:29806 bytes: 1058400/ 1060576 diff --git a/tests/ref/acodec/adpcm-ms-trellis b/tests/ref/acodec/adpcm-ms-trellis new file mode 100644 index 000000000..8587e703c --- /dev/null +++ b/tests/ref/acodec/adpcm-ms-trellis @@ -0,0 +1,4 @@ +7ed05f7a88046aa4cd547ddf71953637 *tests/data/fate/acodec-adpcm-ms-trellis.wav +268378 tests/data/fate/acodec-adpcm-ms-trellis.wav +ed9d9cdfd264f2ec6c79127c04dd224e *tests/data/fate/acodec-adpcm-ms-trellis.out.wav +stddev: 896.03 PSNR: 37.28 MAXDIFF:28029 bytes: 1058400/ 1060576 diff --git a/tests/ref/acodec/adpcm-swf b/tests/ref/acodec/adpcm-swf index fddb771c8..2cb9e905c 100644 --- a/tests/ref/acodec/adpcm-swf +++ b/tests/ref/acodec/adpcm-swf @@ -1,4 +1,4 @@ 42d4639866ed4d692eaf126228a4fa2a *tests/data/fate/acodec-adpcm-swf.flv 269166 tests/data/fate/acodec-adpcm-swf.flv -f7df69d3fe708303820f2a9d00140a5b *tests/data/fate/acodec-adpcm-swf.out.wav +628089745a7059ae4055c2515b6d668b *tests/data/fate/acodec-adpcm-swf.out.wav stddev: 933.58 PSNR: 36.93 MAXDIFF:51119 bytes: 1058400/ 1064960 diff --git a/tests/ref/acodec/adpcm-swf-trellis b/tests/ref/acodec/adpcm-swf-trellis new file mode 100644 index 000000000..a2bb565e1 --- /dev/null +++ b/tests/ref/acodec/adpcm-swf-trellis @@ -0,0 +1,4 @@ +ec8859b3206ea0c45701fbdcf60dbe48 *tests/data/fate/acodec-adpcm-swf-trellis.flv +269166 tests/data/fate/acodec-adpcm-swf-trellis.flv +29820ce5b95b3b0a2feafa808cc264a7 *tests/data/fate/acodec-adpcm-swf-trellis.out.wav +stddev: 747.92 PSNR: 38.85 MAXDIFF:51119 bytes: 1058400/ 1064960 diff --git a/tests/ref/acodec/adpcm-yamaha b/tests/ref/acodec/adpcm-yamaha index da60f44d5..274105854 100644 --- a/tests/ref/acodec/adpcm-yamaha +++ b/tests/ref/acodec/adpcm-yamaha @@ -1,4 +1,4 @@ e9c14f701d25947317db9367b9dc772d *tests/data/fate/acodec-adpcm-yamaha.wav 265274 tests/data/fate/acodec-adpcm-yamaha.wav -1488b5974fa040a65f0d407fc0224c6a *tests/data/fate/acodec-adpcm-yamaha.out.wav +93b95a663ec8799e0c4db18467b21234 *tests/data/fate/acodec-adpcm-yamaha.out.wav stddev: 1247.60 PSNR: 34.41 MAXDIFF:39895 bytes: 1058400/ 1060864 diff --git a/tests/ref/acodec/adpcm-yamaha-trellis b/tests/ref/acodec/adpcm-yamaha-trellis new file mode 100644 index 000000000..a099ec54c --- /dev/null +++ b/tests/ref/acodec/adpcm-yamaha-trellis @@ -0,0 +1,4 @@ +247a06c3f26c57abd2db1a793174cb66 *tests/data/fate/acodec-adpcm-yamaha-trellis.wav +265274 tests/data/fate/acodec-adpcm-yamaha-trellis.wav +a42b5fa74b39a07691b0df80ce67f77e *tests/data/fate/acodec-adpcm-yamaha-trellis.out.wav +stddev: 928.29 PSNR: 36.98 MAXDIFF:33557 bytes: 1058400/ 1060864 diff --git a/tests/ref/acodec/alac b/tests/ref/acodec/alac index 2739b0184..7d6ebe8c8 100644 --- a/tests/ref/acodec/alac +++ b/tests/ref/acodec/alac @@ -1,4 +1,4 @@ 8d9fb9f5433962e7880b666e6e2e428e *tests/data/fate/acodec-alac.mov 389018 tests/data/fate/acodec-alac.mov -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-alac.out.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-alac.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/flac b/tests/ref/acodec/flac index 1cc377066..c2e7f2099 100644 --- a/tests/ref/acodec/flac +++ b/tests/ref/acodec/flac @@ -1,4 +1,4 @@ 151eef9097f944726968bec48649f00a *tests/data/fate/acodec-flac.flac 361582 tests/data/fate/acodec-flac.flac -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-flac.out.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-flac.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/g723_1 b/tests/ref/acodec/g723_1 index 9f88a76c7..e33fe3d20 100644 --- a/tests/ref/acodec/g723_1 +++ b/tests/ref/acodec/g723_1 @@ -1,4 +1,4 @@ dec0deb2425e908d232d2471acff04a3 *tests/data/fate/acodec-g723_1.g723_1 4800 tests/data/fate/acodec-g723_1.g723_1 -d70776846d77c652bceed281fcca9cc8 *tests/data/fate/acodec-g723_1.out.wav +c3b9055d1830969c10d08762fae0b787 *tests/data/fate/acodec-g723_1.out.wav stddev: 8423.47 PSNR: 17.82 MAXDIFF:53292 bytes: 95992/ 96000 diff --git a/tests/ref/acodec/mp2 b/tests/ref/acodec/mp2 index 42381b478..57b83ac74 100644 --- a/tests/ref/acodec/mp2 +++ b/tests/ref/acodec/mp2 @@ -1,4 +1,4 @@ f6eb0a205350bbd7fb1028a01c7ae8aa *tests/data/fate/acodec-mp2.mp2 96130 tests/data/fate/acodec-mp2.mp2 -5a669ca7321adc6ab66a3eade4035909 *tests/data/fate/acodec-mp2.out.wav +74c7b6b15a001add199619fafe4059a1 *tests/data/fate/acodec-mp2.out.wav stddev: 4384.33 PSNR: 23.49 MAXDIFF:52631 bytes: 1058400/ 1057916 diff --git a/tests/ref/acodec/mp2fixed b/tests/ref/acodec/mp2fixed index 0203014e6..bf8cc7f37 100644 --- a/tests/ref/acodec/mp2fixed +++ b/tests/ref/acodec/mp2fixed @@ -1,4 +1,4 @@ -28fbc7485c7939f40368f79adccb3e3d *tests/data/fate/acodec-mp2fixed.mp2 -96130 tests/data/fate/acodec-mp2fixed.mp2 -87461bd4ce4b0e0cbbf6c43621baf261 *tests/data/fate/acodec-mp2fixed.out.wav -stddev: 4384.26 PSNR: 23.49 MAXDIFF:52632 bytes: 1058400/ 1057916 +05445de0f0305df85db4ed0ce94e5f4c *tests/data/fate/acodec-mp2fixed.mp2 +288391 tests/data/fate/acodec-mp2fixed.mp2 +b1b4a13e42db11e9fb1bd2c93692d548 *tests/data/fate/acodec-mp2fixed.out.wav +stddev: 3653.84 PSNR: 25.07 MAXDIFF:39970 bytes: 1058400/ 1057916 diff --git a/tests/ref/acodec/pcm-alaw b/tests/ref/acodec/pcm-alaw index 28ce960ef..00555e334 100644 --- a/tests/ref/acodec/pcm-alaw +++ b/tests/ref/acodec/pcm-alaw @@ -1,4 +1,4 @@ a2dd6a934ec6d5ec901a211652e85227 *tests/data/fate/acodec-pcm-alaw.wav 529258 tests/data/fate/acodec-pcm-alaw.wav -f323f7551ffad91de8613f44dcb198b6 *tests/data/fate/acodec-pcm-alaw.out.wav +0568b0b9a72e31559e150e7e09d301cd *tests/data/fate/acodec-pcm-alaw.out.wav stddev: 101.67 PSNR: 56.19 MAXDIFF: 515 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-f32be b/tests/ref/acodec/pcm-f32be index 5bd700c6e..b98c0b7a2 100644 --- a/tests/ref/acodec/pcm-f32be +++ b/tests/ref/acodec/pcm-f32be @@ -1,4 +1,4 @@ e74eb6b65cb397ce541bac120b00680a *tests/data/fate/acodec-pcm-f32be.au 2116832 tests/data/fate/acodec-pcm-f32be.au -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-f32be.out.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-f32be.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-f32le b/tests/ref/acodec/pcm-f32le index 681f0836c..c0fdd70cd 100644 --- a/tests/ref/acodec/pcm-f32le +++ b/tests/ref/acodec/pcm-f32le @@ -1,4 +1,4 @@ 653d82a64b7bd96ac193e105e9f92d4c *tests/data/fate/acodec-pcm-f32le.wav 2116880 tests/data/fate/acodec-pcm-f32le.wav -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-f32le.out.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-f32le.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-f64be b/tests/ref/acodec/pcm-f64be index fd0cff6ac..e0e03079d 100644 --- a/tests/ref/acodec/pcm-f64be +++ b/tests/ref/acodec/pcm-f64be @@ -1,4 +1,4 @@ 8c8ba9d2c68384c5f077306e220f1188 *tests/data/fate/acodec-pcm-f64be.au 4233632 tests/data/fate/acodec-pcm-f64be.au -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-f64be.out.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-f64be.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-f64le b/tests/ref/acodec/pcm-f64le index c6cb02722..5c90e7bbb 100644 --- a/tests/ref/acodec/pcm-f64le +++ b/tests/ref/acodec/pcm-f64le @@ -1,4 +1,4 @@ 48b4cd378f47a50dc902aa03cc8280ed *tests/data/fate/acodec-pcm-f64le.wav 4233680 tests/data/fate/acodec-pcm-f64le.wav -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-f64le.out.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-f64le.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-mulaw b/tests/ref/acodec/pcm-mulaw index bd2a1e81b..f5c117de1 100644 --- a/tests/ref/acodec/pcm-mulaw +++ b/tests/ref/acodec/pcm-mulaw @@ -1,4 +1,4 @@ fd10ee54bd298fc29fd6fc70baa71414 *tests/data/fate/acodec-pcm-mulaw.wav 529258 tests/data/fate/acodec-pcm-mulaw.wav -7ae8c3fc804bd574006fd547fe28980c *tests/data/fate/acodec-pcm-mulaw.out.wav +1c3eeaa8814ebd4916780dff80ed6dc5 *tests/data/fate/acodec-pcm-mulaw.out.wav stddev: 103.38 PSNR: 56.04 MAXDIFF: 644 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-s16be b/tests/ref/acodec/pcm-s16be index de7c5c7a4..a9b4593b5 100644 --- a/tests/ref/acodec/pcm-s16be +++ b/tests/ref/acodec/pcm-s16be @@ -1,4 +1,4 @@ d2515f35266ae6dba525c700bb76d893 *tests/data/fate/acodec-pcm-s16be.mov 1059069 tests/data/fate/acodec-pcm-s16be.mov -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s16be.out.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s16be.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-s16be_planar b/tests/ref/acodec/pcm-s16be_planar index 8116480aa..3d7d7b111 100644 --- a/tests/ref/acodec/pcm-s16be_planar +++ b/tests/ref/acodec/pcm-s16be_planar @@ -1,4 +1,4 @@ -cd87e6fc3bddb85c945c050d8c3fba11 *tests/data/fate/acodec-pcm-s16be_planar.nut -1060673 tests/data/fate/acodec-pcm-s16be_planar.nut -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s16be_planar.out.wav +a2d4da448a83dac7cbe11eea96e679fb *tests/data/fate/acodec-pcm-s16be_planar.nut +1060722 tests/data/fate/acodec-pcm-s16be_planar.nut +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s16be_planar.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-s16le b/tests/ref/acodec/pcm-s16le index 51366ad0d..5fa80bd7a 100644 --- a/tests/ref/acodec/pcm-s16le +++ b/tests/ref/acodec/pcm-s16le @@ -1,4 +1,4 @@ -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s16le.wav -1058446 tests/data/fate/acodec-pcm-s16le.wav -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s16le.out.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s16le.wav +1058444 tests/data/fate/acodec-pcm-s16le.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s16le.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-s16le_planar b/tests/ref/acodec/pcm-s16le_planar index c9330010a..c635c727e 100644 --- a/tests/ref/acodec/pcm-s16le_planar +++ b/tests/ref/acodec/pcm-s16le_planar @@ -1,4 +1,4 @@ -74af9a0ae4f68451102a2f7524b2d55f *tests/data/fate/acodec-pcm-s16le_planar.nut -1060673 tests/data/fate/acodec-pcm-s16le_planar.nut -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s16le_planar.out.wav +761404c11c5b4b0a8bba0061704f70a4 *tests/data/fate/acodec-pcm-s16le_planar.nut +1060722 tests/data/fate/acodec-pcm-s16le_planar.nut +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s16le_planar.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-s24be b/tests/ref/acodec/pcm-s24be index 70271d2ed..916aceb01 100644 --- a/tests/ref/acodec/pcm-s24be +++ b/tests/ref/acodec/pcm-s24be @@ -1,4 +1,4 @@ 0f4a37a77619124f486f656f03c53d33 *tests/data/fate/acodec-pcm-s24be.mov 1588323 tests/data/fate/acodec-pcm-s24be.mov -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s24be.out.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s24be.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-s24le b/tests/ref/acodec/pcm-s24le index a7e77e2fc..cf5ae1a2a 100644 --- a/tests/ref/acodec/pcm-s24le +++ b/tests/ref/acodec/pcm-s24le @@ -1,4 +1,4 @@ 18ea73985dbdf59e23f5aba66145e6fe *tests/data/fate/acodec-pcm-s24le.wav 1587668 tests/data/fate/acodec-pcm-s24le.wav -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s24le.out.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s24le.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-s24le_planar b/tests/ref/acodec/pcm-s24le_planar index 14d4cecaf..67393d963 100644 --- a/tests/ref/acodec/pcm-s24le_planar +++ b/tests/ref/acodec/pcm-s24le_planar @@ -1,4 +1,4 @@ -83e315ce8083a6d035f801bb862942bf *tests/data/fate/acodec-pcm-s24le_planar.nut -1590202 tests/data/fate/acodec-pcm-s24le_planar.nut -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s24le_planar.out.wav +aa9f8ca95de20b2e83f66dcbb15cc307 *tests/data/fate/acodec-pcm-s24le_planar.nut +1590251 tests/data/fate/acodec-pcm-s24le_planar.nut +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s24le_planar.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-s32be b/tests/ref/acodec/pcm-s32be index 03f14c16c..5a48bb275 100644 --- a/tests/ref/acodec/pcm-s32be +++ b/tests/ref/acodec/pcm-s32be @@ -1,4 +1,4 @@ d6380bf54ac3e452c190ce302c264bf0 *tests/data/fate/acodec-pcm-s32be.mov 2117527 tests/data/fate/acodec-pcm-s32be.mov -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s32be.out.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s32be.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-s32le b/tests/ref/acodec/pcm-s32le index 1c3e41242..47c736b9c 100644 --- a/tests/ref/acodec/pcm-s32le +++ b/tests/ref/acodec/pcm-s32le @@ -1,4 +1,4 @@ 8d8849fa5c5d91b9cb74f5c74e937faf *tests/data/fate/acodec-pcm-s32le.wav 2116868 tests/data/fate/acodec-pcm-s32le.wav -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s32le.out.wav +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s32le.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-s32le_planar b/tests/ref/acodec/pcm-s32le_planar index 7648766a8..643659f21 100644 --- a/tests/ref/acodec/pcm-s32le_planar +++ b/tests/ref/acodec/pcm-s32le_planar @@ -1,4 +1,4 @@ -f6199b2c698bd5dd1438b53431357bec *tests/data/fate/acodec-pcm-s32le_planar.nut -2120148 tests/data/fate/acodec-pcm-s32le_planar.nut -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s32le_planar.out.wav +d2a712fe08b1792bc65f255f54bb980e *tests/data/fate/acodec-pcm-s32le_planar.nut +2120197 tests/data/fate/acodec-pcm-s32le_planar.nut +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s32le_planar.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-s8 b/tests/ref/acodec/pcm-s8 index a5a459acc..14f4c8562 100644 --- a/tests/ref/acodec/pcm-s8 +++ b/tests/ref/acodec/pcm-s8 @@ -1,4 +1,4 @@ 00a9d90e06e8ecb79e5dd4c6c8460836 *tests/data/fate/acodec-pcm-s8.mov 529853 tests/data/fate/acodec-pcm-s8.mov -651d4eb8d98dfcdda96ae6c43d8f156b *tests/data/fate/acodec-pcm-s8.out.wav +652edf30f35ad89bf27bcc9d2f9c7b53 *tests/data/fate/acodec-pcm-s8.out.wav stddev: 147.89 PSNR: 52.93 MAXDIFF: 255 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-s8_planar b/tests/ref/acodec/pcm-s8_planar index 6ab6ee0b6..301e71538 100644 --- a/tests/ref/acodec/pcm-s8_planar +++ b/tests/ref/acodec/pcm-s8_planar @@ -1,4 +1,4 @@ -ce99d95295ade9945849ef7c1de8c4ca *tests/data/fate/acodec-pcm-s8_planar.nut -531054 tests/data/fate/acodec-pcm-s8_planar.nut -651d4eb8d98dfcdda96ae6c43d8f156b *tests/data/fate/acodec-pcm-s8_planar.out.wav +c0e10e4a5106137082131807b6674a71 *tests/data/fate/acodec-pcm-s8_planar.nut +531100 tests/data/fate/acodec-pcm-s8_planar.nut +652edf30f35ad89bf27bcc9d2f9c7b53 *tests/data/fate/acodec-pcm-s8_planar.out.wav stddev: 147.89 PSNR: 52.93 MAXDIFF: 255 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-u16be b/tests/ref/acodec/pcm-u16be index 0214975b9..3fd831d16 100644 --- a/tests/ref/acodec/pcm-u16be +++ b/tests/ref/acodec/pcm-u16be @@ -1,4 +1,4 @@ -eab6206a2cec3c5a3be47fdaa826faff *tests/data/fate/acodec-pcm-u16be.nut -1060673 tests/data/fate/acodec-pcm-u16be.nut -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-u16be.out.wav +753d5bfdc38d314fa3b1a2eb34449aea *tests/data/fate/acodec-pcm-u16be.nut +1060715 tests/data/fate/acodec-pcm-u16be.nut +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-u16be.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-u16le b/tests/ref/acodec/pcm-u16le index e45fe088d..ea724bbe9 100644 --- a/tests/ref/acodec/pcm-u16le +++ b/tests/ref/acodec/pcm-u16le @@ -1,4 +1,4 @@ -8fceb284cc6a5a114b6ce7a10fd08020 *tests/data/fate/acodec-pcm-u16le.nut -1060673 tests/data/fate/acodec-pcm-u16le.nut -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-u16le.out.wav +cee38dc471b6b72d97e44d1667591362 *tests/data/fate/acodec-pcm-u16le.nut +1060715 tests/data/fate/acodec-pcm-u16le.nut +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-u16le.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-u24be b/tests/ref/acodec/pcm-u24be index ddab6e84f..3c196373a 100644 --- a/tests/ref/acodec/pcm-u24be +++ b/tests/ref/acodec/pcm-u24be @@ -1,4 +1,4 @@ -d1a55f46c88ed1efa77d05b60259675d *tests/data/fate/acodec-pcm-u24be.nut -1590202 tests/data/fate/acodec-pcm-u24be.nut -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-u24be.out.wav +84c2b6f7197840e40c5f646efd8a43a4 *tests/data/fate/acodec-pcm-u24be.nut +1590244 tests/data/fate/acodec-pcm-u24be.nut +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-u24be.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-u24le b/tests/ref/acodec/pcm-u24le index df06ca4e7..b82d6bcb2 100644 --- a/tests/ref/acodec/pcm-u24le +++ b/tests/ref/acodec/pcm-u24le @@ -1,4 +1,4 @@ -6d7df9b7e074548cf18dd16365862f1b *tests/data/fate/acodec-pcm-u24le.nut -1590202 tests/data/fate/acodec-pcm-u24le.nut -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-u24le.out.wav +5afea1f1b1d0590dbae2ac2e0092f434 *tests/data/fate/acodec-pcm-u24le.nut +1590244 tests/data/fate/acodec-pcm-u24le.nut +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-u24le.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-u32be b/tests/ref/acodec/pcm-u32be index 6a5391977..909a130ac 100644 --- a/tests/ref/acodec/pcm-u32be +++ b/tests/ref/acodec/pcm-u32be @@ -1,4 +1,4 @@ -7078e6d7e80247b8531d5cc16d09f385 *tests/data/fate/acodec-pcm-u32be.nut -2120148 tests/data/fate/acodec-pcm-u32be.nut -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-u32be.out.wav +529f523fcd04002791fce9cee797783b *tests/data/fate/acodec-pcm-u32be.nut +2120190 tests/data/fate/acodec-pcm-u32be.nut +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-u32be.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-u32le b/tests/ref/acodec/pcm-u32le index 18a5d1519..16a183f60 100644 --- a/tests/ref/acodec/pcm-u32le +++ b/tests/ref/acodec/pcm-u32le @@ -1,4 +1,4 @@ -34df9a7e1fe60da0bc6ec0485b68726e *tests/data/fate/acodec-pcm-u32le.nut -2120148 tests/data/fate/acodec-pcm-u32le.nut -64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-u32le.out.wav +87f75abd86f84571bafc656e06b63038 *tests/data/fate/acodec-pcm-u32le.nut +2120190 tests/data/fate/acodec-pcm-u32le.nut +95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-u32le.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/pcm-u8 b/tests/ref/acodec/pcm-u8 index 80e70eab0..c9bf04acd 100644 --- a/tests/ref/acodec/pcm-u8 +++ b/tests/ref/acodec/pcm-u8 @@ -1,4 +1,4 @@ -70fecbae732f81143a560c7315eda49a *tests/data/fate/acodec-pcm-u8.wav -529246 tests/data/fate/acodec-pcm-u8.wav -651d4eb8d98dfcdda96ae6c43d8f156b *tests/data/fate/acodec-pcm-u8.out.wav +98cadb3502dbdc99e6e077c28b1a036c *tests/data/fate/acodec-pcm-u8.wav +529244 tests/data/fate/acodec-pcm-u8.wav +652edf30f35ad89bf27bcc9d2f9c7b53 *tests/data/fate/acodec-pcm-u8.out.wav stddev: 147.89 PSNR: 52.93 MAXDIFF: 255 bytes: 1058400/ 1058400 diff --git a/tests/ref/acodec/roqaudio b/tests/ref/acodec/roqaudio index 863250478..61cb27a38 100644 --- a/tests/ref/acodec/roqaudio +++ b/tests/ref/acodec/roqaudio @@ -1,4 +1,4 @@ 75859976d7098588aeaebbc5551484a9 *tests/data/fate/acodec-roqaudio.roq 265992 tests/data/fate/acodec-roqaudio.roq -be6d954adaf984f2dc65a3ff50b55f26 *tests/data/fate/acodec-roqaudio.out.wav +73d5aaaab9488e63f1cf6fc324c7a9a2 *tests/data/fate/acodec-roqaudio.out.wav stddev: 4481.70 PSNR: 23.30 MAXDIFF:46250 bytes: 1058400/ 1058400 diff --git a/tests/ref/fate/vima b/tests/ref/fate/adpcm-vima similarity index 100% rename from tests/ref/fate/vima rename to tests/ref/fate/adpcm-vima diff --git a/tests/ref/fate/aic b/tests/ref/fate/aic new file mode 100644 index 000000000..90692f1d0 --- /dev/null +++ b/tests/ref/fate/aic @@ -0,0 +1,16 @@ +#tb 0: 100/2997 +0, 0, 0, 1, 2332800, 0xd941b42f +0, 1, 1, 1, 2332800, 0xd941b42f +0, 2, 2, 1, 2332800, 0xae0f5983 +0, 3, 3, 1, 2332800, 0x51cfc127 +0, 4, 4, 1, 2332800, 0x24d40447 +0, 5, 5, 1, 2332800, 0x858a9f51 +0, 6, 6, 1, 2332800, 0x533b48e8 +0, 7, 7, 1, 2332800, 0x2fd73267 +0, 8, 8, 1, 2332800, 0x153566c7 +0, 9, 9, 1, 2332800, 0xa1c49c45 +0, 10, 10, 1, 2332800, 0xb966e25a +0, 11, 11, 1, 2332800, 0xd0ce5985 +0, 12, 12, 1, 2332800, 0x0029a52e +0, 13, 13, 1, 2332800, 0x893116c5 +0, 14, 14, 1, 2332800, 0x073d2491 diff --git a/tests/ref/fate/aliaspix-bgr b/tests/ref/fate/aliaspix-bgr new file mode 100644 index 000000000..8671d3ef7 --- /dev/null +++ b/tests/ref/fate/aliaspix-bgr @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 47637, 0xcb77368f diff --git a/tests/ref/fate/aliaspix-gray b/tests/ref/fate/aliaspix-gray new file mode 100644 index 000000000..0433a36eb --- /dev/null +++ b/tests/ref/fate/aliaspix-gray @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16119, 0x3d0785f5 diff --git a/tests/ref/fate/bmpparser b/tests/ref/fate/bmpparser new file mode 100644 index 000000000..3cdd9864a --- /dev/null +++ b/tests/ref/fate/bmpparser @@ -0,0 +1,5 @@ +#tb 0: 1/25 +0, 0, 0, 1, 3600, 0xd3a7c583 +0, 1, 1, 1, 3600, 0x4602bbf9 +0, 2, 2, 1, 3600, 0x3a96b8f8 +0, 3, 3, 1, 3600, 0xb343b17f diff --git a/tests/ref/fate/brenderpix-24 b/tests/ref/fate/brenderpix-24 new file mode 100644 index 000000000..32b29a042 --- /dev/null +++ b/tests/ref/fate/brenderpix-24 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 32768, 0x18bc6caa diff --git a/tests/ref/fate/brenderpix-565 b/tests/ref/fate/brenderpix-565 new file mode 100644 index 000000000..c243a4cf5 --- /dev/null +++ b/tests/ref/fate/brenderpix-565 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 32768, 0xfd855dda diff --git a/tests/ref/fate/brenderpix-defpal b/tests/ref/fate/brenderpix-defpal new file mode 100644 index 000000000..6c5574088 --- /dev/null +++ b/tests/ref/fate/brenderpix-defpal @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 196608, 0xada11d14 diff --git a/tests/ref/fate/brenderpix-intpal b/tests/ref/fate/brenderpix-intpal new file mode 100644 index 000000000..473b1532e --- /dev/null +++ b/tests/ref/fate/brenderpix-intpal @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 196608, 0x9662f917 diff --git a/tests/ref/fate/brenderpix-y400a b/tests/ref/fate/brenderpix-y400a new file mode 100644 index 000000000..00e154009 --- /dev/null +++ b/tests/ref/fate/brenderpix-y400a @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 3072, 0x48280456 diff --git a/tests/ref/fate/cavs b/tests/ref/fate/cavs index f9af8fa88..87cf9ca83 100644 --- a/tests/ref/fate/cavs +++ b/tests/ref/fate/cavs @@ -1,172 +1,172 @@ #tb 0: 1/25 -0, 0, 0, 1, 622080, 0x76183b91 -0, 1, 1, 1, 622080, 0x2ca5e808 -0, 2, 2, 1, 622080, 0xc503eda4 -0, 3, 3, 1, 622080, 0xa0dbf06c -0, 4, 4, 1, 622080, 0xf4363cfa -0, 5, 5, 1, 622080, 0xaa7dd9b8 -0, 6, 6, 1, 622080, 0x3ab6223b -0, 7, 7, 1, 622080, 0xe402644b -0, 8, 8, 1, 622080, 0xd0da3ade -0, 9, 9, 1, 622080, 0x0aff6151 -0, 10, 10, 1, 622080, 0x02aea3d5 -0, 11, 11, 1, 622080, 0x5d8eeccd -0, 12, 12, 1, 622080, 0x54384735 -0, 13, 13, 1, 622080, 0x890d71c2 -0, 14, 14, 1, 622080, 0xc60ae25b -0, 15, 15, 1, 622080, 0xe589e774 -0, 16, 16, 1, 622080, 0x03471e74 -0, 17, 17, 1, 622080, 0x4e22302c -0, 18, 18, 1, 622080, 0x00333583 -0, 19, 19, 1, 622080, 0xd6eae7d9 -0, 20, 20, 1, 622080, 0x72fe94f7 -0, 21, 21, 1, 622080, 0x3ebbad1e -0, 22, 22, 1, 622080, 0x2fb1de4b -0, 23, 23, 1, 622080, 0x3bfea6d2 -0, 24, 24, 1, 622080, 0x0fb551b2 -0, 25, 25, 1, 622080, 0xb203284f -0, 26, 26, 1, 622080, 0xb3baac30 -0, 27, 27, 1, 622080, 0x15f2c1c7 -0, 28, 28, 1, 622080, 0xb2b530ce -0, 29, 29, 1, 622080, 0xbbaaf241 -0, 30, 30, 1, 622080, 0x01bc9dfc -0, 31, 31, 1, 622080, 0x8a449a42 -0, 32, 32, 1, 622080, 0xdc63d73f -0, 33, 33, 1, 622080, 0xf06bc231 -0, 34, 34, 1, 622080, 0x19e04295 -0, 35, 35, 1, 622080, 0x1e7d1acd -0, 36, 36, 1, 622080, 0x43878b48 -0, 37, 37, 1, 622080, 0xcd94b702 -0, 38, 38, 1, 622080, 0xd2706cf1 -0, 39, 39, 1, 622080, 0x47d636f3 -0, 40, 40, 1, 622080, 0x4a516acc -0, 41, 41, 1, 622080, 0x52b7d89a -0, 42, 42, 1, 622080, 0xc9ba03be -0, 43, 43, 1, 622080, 0x6d17785e -0, 44, 44, 1, 622080, 0x8264871b -0, 45, 45, 1, 622080, 0xd59c84c0 -0, 46, 46, 1, 622080, 0x2b86d6cd -0, 47, 47, 1, 622080, 0x9c5a5f51 -0, 48, 48, 1, 622080, 0x221f79ca -0, 49, 49, 1, 622080, 0x98edb3ec -0, 50, 50, 1, 622080, 0x9a31262c -0, 51, 51, 1, 622080, 0x18f48378 -0, 52, 52, 1, 622080, 0x957c3d9c -0, 53, 53, 1, 622080, 0x9cc6866e -0, 54, 54, 1, 622080, 0x45613726 -0, 55, 55, 1, 622080, 0x7a6c5e65 -0, 56, 56, 1, 622080, 0x976d7a11 -0, 57, 57, 1, 622080, 0x192aea08 -0, 58, 58, 1, 622080, 0x8d4fc823 -0, 59, 59, 1, 622080, 0x1f9c55d7 -0, 60, 60, 1, 622080, 0xd4336d41 -0, 61, 61, 1, 622080, 0x7aa650cd -0, 62, 62, 1, 622080, 0x8efaaeb1 -0, 63, 63, 1, 622080, 0x3d8c3053 -0, 64, 64, 1, 622080, 0x1e2b64b0 -0, 65, 65, 1, 622080, 0x0436b1a7 -0, 66, 66, 1, 622080, 0xc5120072 -0, 67, 67, 1, 622080, 0x0203b245 -0, 68, 68, 1, 622080, 0x9815582b -0, 69, 69, 1, 622080, 0x3c60c359 -0, 70, 70, 1, 622080, 0x1a26b948 -0, 71, 71, 1, 622080, 0x56079812 -0, 72, 72, 1, 622080, 0x7b192a55 -0, 73, 73, 1, 622080, 0x335632ab -0, 74, 74, 1, 622080, 0xd0c12eb8 -0, 75, 75, 1, 622080, 0x93bf46cb -0, 76, 76, 1, 622080, 0xce67ce24 -0, 77, 77, 1, 622080, 0xff95bb26 -0, 78, 78, 1, 622080, 0x5e750705 -0, 79, 79, 1, 622080, 0x45a35725 -0, 80, 80, 1, 622080, 0xd8e93c39 -0, 81, 81, 1, 622080, 0xa9f8db50 -0, 82, 82, 1, 622080, 0xf90a862e -0, 83, 83, 1, 622080, 0x5e5a4216 -0, 84, 84, 1, 622080, 0xaaf45ed6 -0, 85, 85, 1, 622080, 0x1933cda5 -0, 86, 86, 1, 622080, 0x7ff68d91 -0, 87, 87, 1, 622080, 0x10038fe9 -0, 88, 88, 1, 622080, 0x9b3425a6 -0, 89, 89, 1, 622080, 0x8d2a141d -0, 90, 90, 1, 622080, 0x698a333e -0, 91, 91, 1, 622080, 0x334685d1 -0, 92, 92, 1, 622080, 0x40317d40 -0, 93, 93, 1, 622080, 0xd3c6f519 -0, 94, 94, 1, 622080, 0xfc2210c2 -0, 95, 95, 1, 622080, 0x3761df34 -0, 96, 96, 1, 622080, 0xef25462a -0, 97, 97, 1, 622080, 0x0fd38121 -0, 98, 98, 1, 622080, 0x184856a6 -0, 99, 99, 1, 622080, 0xc57c9f12 -0, 100, 100, 1, 622080, 0x39874291 -0, 101, 101, 1, 622080, 0x7c13cec4 -0, 102, 102, 1, 622080, 0xc4192a76 -0, 103, 103, 1, 622080, 0x2af404e3 -0, 104, 104, 1, 622080, 0x1ee18f41 -0, 105, 105, 1, 622080, 0xfb4d9ee5 -0, 106, 106, 1, 622080, 0x50aae4ff -0, 107, 107, 1, 622080, 0x030f91fe -0, 108, 108, 1, 622080, 0x3a3ee08c -0, 109, 109, 1, 622080, 0x50121423 -0, 110, 110, 1, 622080, 0xda39e2d6 -0, 111, 111, 1, 622080, 0x9e13ccd6 -0, 112, 112, 1, 622080, 0xb72a22a7 -0, 113, 113, 1, 622080, 0xb76904d5 -0, 114, 114, 1, 622080, 0xcffa04a8 -0, 115, 115, 1, 622080, 0x2984bf3f -0, 116, 116, 1, 622080, 0x274b5778 -0, 117, 117, 1, 622080, 0xf059413a -0, 118, 118, 1, 622080, 0x969fae57 -0, 119, 119, 1, 622080, 0x75c29097 -0, 120, 120, 1, 622080, 0x2bf3b07d -0, 121, 121, 1, 622080, 0x9f43271d -0, 122, 122, 1, 622080, 0x67bf23f3 -0, 123, 123, 1, 622080, 0xa8edcf33 -0, 124, 124, 1, 622080, 0x17a0789e -0, 125, 125, 1, 622080, 0x14b67cc7 -0, 126, 126, 1, 622080, 0x779215cd -0, 127, 127, 1, 622080, 0x8b460a21 -0, 128, 128, 1, 622080, 0x0502ad7d -0, 129, 129, 1, 622080, 0x6860678f -0, 130, 130, 1, 622080, 0xe180469e -0, 131, 131, 1, 622080, 0x9a992835 -0, 132, 132, 1, 622080, 0x2efafa33 -0, 133, 133, 1, 622080, 0xe24e59b2 -0, 134, 134, 1, 622080, 0xfb774d53 -0, 135, 135, 1, 622080, 0x3de4ea81 -0, 136, 136, 1, 622080, 0xaf9aa1d6 -0, 137, 137, 1, 622080, 0xa0e3722f -0, 138, 138, 1, 622080, 0x81684492 -0, 139, 139, 1, 622080, 0xa4e971fb -0, 140, 140, 1, 622080, 0x4a1903c8 -0, 141, 141, 1, 622080, 0x26304e4a -0, 142, 142, 1, 622080, 0x867983a4 -0, 143, 143, 1, 622080, 0x2e7e4d13 -0, 144, 144, 1, 622080, 0x736f4682 -0, 145, 145, 1, 622080, 0x426a95fa -0, 146, 146, 1, 622080, 0x2bc8850c -0, 147, 147, 1, 622080, 0x047e77ab -0, 148, 148, 1, 622080, 0x414ab77f -0, 149, 149, 1, 622080, 0x42681090 -0, 150, 150, 1, 622080, 0x80744ccb -0, 151, 151, 1, 622080, 0x50e2ecc0 -0, 152, 152, 1, 622080, 0x5c9fe70e -0, 153, 153, 1, 622080, 0x016461ee -0, 154, 154, 1, 622080, 0xd42f019a -0, 155, 155, 1, 622080, 0x8171bf41 -0, 156, 156, 1, 622080, 0xf4d8ef7e -0, 157, 157, 1, 622080, 0xf2d513c8 -0, 158, 158, 1, 622080, 0xb5b07704 -0, 159, 159, 1, 622080, 0x2168a07a -0, 160, 160, 1, 622080, 0x840418f9 -0, 161, 161, 1, 622080, 0xd36f1b7c -0, 162, 162, 1, 622080, 0x52532604 -0, 163, 163, 1, 622080, 0x0856d6eb -0, 164, 164, 1, 622080, 0x21748734 -0, 165, 165, 1, 622080, 0xbd315c05 -0, 166, 166, 1, 622080, 0x1cea8103 -0, 167, 167, 1, 622080, 0x71f6e3cb -0, 168, 168, 1, 622080, 0xb12d7aa7 -0, 169, 169, 1, 622080, 0x54dd2acb -0, 170, 170, 1, 622080, 0xe8f93765 +0, 0, 0, 1, 622080, 0x2276bc78 +0, 1, 1, 1, 622080, 0xda1f698a +0, 2, 2, 1, 622080, 0xb9907023 +0, 3, 3, 1, 622080, 0xc1c05e44 +0, 4, 4, 1, 622080, 0x9366d0a7 +0, 5, 5, 1, 622080, 0xbf92812d +0, 6, 6, 1, 622080, 0xd6b1cb3e +0, 7, 7, 1, 622080, 0x8be011f6 +0, 8, 8, 1, 622080, 0xfde1f1de +0, 9, 9, 1, 622080, 0xabad03c3 +0, 10, 10, 1, 622080, 0x74204d0a +0, 11, 11, 1, 622080, 0x220a9de9 +0, 12, 12, 1, 622080, 0x913be934 +0, 13, 13, 1, 622080, 0xab47295b +0, 14, 14, 1, 622080, 0x1938afc3 +0, 15, 15, 1, 622080, 0x3a5fbe19 +0, 16, 16, 1, 622080, 0x8c15f517 +0, 17, 17, 1, 622080, 0x78410c15 +0, 18, 18, 1, 622080, 0xe2861423 +0, 19, 19, 1, 622080, 0x1dfac8aa +0, 20, 20, 1, 622080, 0x07b57615 +0, 21, 21, 1, 622080, 0xe9558e77 +0, 22, 22, 1, 622080, 0x917abfc8 +0, 23, 23, 1, 622080, 0xe13d883b +0, 24, 24, 1, 622080, 0x8abb3304 +0, 25, 25, 1, 622080, 0xc3f10a22 +0, 26, 26, 1, 622080, 0x0ecf8c84 +0, 27, 27, 1, 622080, 0xc3eba1dd +0, 28, 28, 1, 622080, 0x147d28fd +0, 29, 29, 1, 622080, 0xba0be99c +0, 30, 30, 1, 622080, 0xa6d99d9e +0, 31, 31, 1, 622080, 0xf173991c +0, 32, 32, 1, 622080, 0x0779d637 +0, 33, 33, 1, 622080, 0xc1f8c139 +0, 34, 34, 1, 622080, 0x7d3a42fc +0, 35, 35, 1, 622080, 0xcd621bc9 +0, 36, 36, 1, 622080, 0x03cc8d02 +0, 37, 37, 1, 622080, 0xac39b968 +0, 38, 38, 1, 622080, 0xb7896f8c +0, 39, 39, 1, 622080, 0x57c4399d +0, 40, 40, 1, 622080, 0xcdc16dc1 +0, 41, 41, 1, 622080, 0x9621db44 +0, 42, 42, 1, 622080, 0xd59d064c +0, 43, 43, 1, 622080, 0x17a97e5d +0, 44, 44, 1, 622080, 0xde7789e8 +0, 45, 45, 1, 622080, 0xf5708808 +0, 46, 46, 1, 622080, 0x5b94d8fd +0, 47, 47, 1, 622080, 0x98bf5f8f +0, 48, 48, 1, 622080, 0x92107bf6 +0, 49, 49, 1, 622080, 0x86a1b601 +0, 50, 50, 1, 622080, 0x9d7f28c0 +0, 51, 51, 1, 622080, 0x185a85bb +0, 52, 52, 1, 622080, 0x10a34015 +0, 53, 53, 1, 622080, 0xea21890e +0, 54, 54, 1, 622080, 0x9a64399a +0, 55, 55, 1, 622080, 0x2bb460d2 +0, 56, 56, 1, 622080, 0x73ce7c21 +0, 57, 57, 1, 622080, 0x6289ebca +0, 58, 58, 1, 622080, 0x63a2c57e +0, 59, 59, 1, 622080, 0xaf5a5123 +0, 60, 60, 1, 622080, 0xcc3062c7 +0, 61, 61, 1, 622080, 0xac434664 +0, 62, 62, 1, 622080, 0x7d5fa464 +0, 63, 63, 1, 622080, 0xd2c4260a +0, 64, 64, 1, 622080, 0xe2f95a6c +0, 65, 65, 1, 622080, 0xe073a85a +0, 66, 66, 1, 622080, 0x34b9f64b +0, 67, 67, 1, 622080, 0x861da899 +0, 68, 68, 1, 622080, 0x611d4ed5 +0, 69, 69, 1, 622080, 0x3077b9de +0, 70, 70, 1, 622080, 0x4dedaf9f +0, 71, 71, 1, 622080, 0xe48d8e8b +0, 72, 72, 1, 622080, 0x5db2207a +0, 73, 73, 1, 622080, 0xf10128ab +0, 74, 74, 1, 622080, 0xd8fd249e +0, 75, 75, 1, 622080, 0x8f643cc2 +0, 76, 76, 1, 622080, 0xfe1cc433 +0, 77, 77, 1, 622080, 0x3af0b0f4 +0, 78, 78, 1, 622080, 0x4a75fcc8 +0, 79, 79, 1, 622080, 0x48874d71 +0, 80, 80, 1, 622080, 0x3eb5324f +0, 81, 81, 1, 622080, 0xd7a7d172 +0, 82, 82, 1, 622080, 0x32a17c2a +0, 83, 83, 1, 622080, 0xcf1137bb +0, 84, 84, 1, 622080, 0x622e54a2 +0, 85, 85, 1, 622080, 0x0b73c385 +0, 86, 86, 1, 622080, 0x47f082fb +0, 87, 87, 1, 622080, 0xe7e68540 +0, 88, 88, 1, 622080, 0x77551fde +0, 89, 89, 1, 622080, 0xa70b0faf +0, 90, 90, 1, 622080, 0x05ee3436 +0, 91, 91, 1, 622080, 0x2d2f86a9 +0, 92, 92, 1, 622080, 0x78b07e1f +0, 93, 93, 1, 622080, 0x9714f5fc +0, 94, 94, 1, 622080, 0x521d118c +0, 95, 95, 1, 622080, 0x0102e005 +0, 96, 96, 1, 622080, 0x20b1470c +0, 97, 97, 1, 622080, 0x828f8212 +0, 98, 98, 1, 622080, 0x6fbb57b5 +0, 99, 99, 1, 622080, 0x3b19a01f +0, 100, 100, 1, 622080, 0x114d43b2 +0, 101, 101, 1, 622080, 0xeca5cfda +0, 102, 102, 1, 622080, 0x8ca12ba6 +0, 103, 103, 1, 622080, 0xc11e061b +0, 104, 104, 1, 622080, 0xca6c905a +0, 105, 105, 1, 622080, 0x9c2ca00f +0, 106, 106, 1, 622080, 0x8641e615 +0, 107, 107, 1, 622080, 0x90e1930f +0, 108, 108, 1, 622080, 0xa2eae188 +0, 109, 109, 1, 622080, 0x9be41511 +0, 110, 110, 1, 622080, 0x4268e3b3 +0, 111, 111, 1, 622080, 0x69d0cdd5 +0, 112, 112, 1, 622080, 0x437223c2 +0, 113, 113, 1, 622080, 0x669205c5 +0, 114, 114, 1, 622080, 0x85f1059b +0, 115, 115, 1, 622080, 0x1595c0a9 +0, 116, 116, 1, 622080, 0xa7fa58c4 +0, 117, 117, 1, 622080, 0x839c42c2 +0, 118, 118, 1, 622080, 0xfadaa4c1 +0, 119, 119, 1, 622080, 0xdbd08677 +0, 120, 120, 1, 622080, 0xbc529d52 +0, 121, 121, 1, 622080, 0x9c9013f3 +0, 122, 122, 1, 622080, 0x7ea9112f +0, 123, 123, 1, 622080, 0xbb49bc2c +0, 124, 124, 1, 622080, 0x18c9656f +0, 125, 125, 1, 622080, 0x637f698e +0, 126, 126, 1, 622080, 0x4f66028c +0, 127, 127, 1, 622080, 0xaf1bf6eb +0, 128, 128, 1, 622080, 0x22c19a51 +0, 129, 129, 1, 622080, 0x085d547a +0, 130, 130, 1, 622080, 0x11143435 +0, 131, 131, 1, 622080, 0x3a6d15b9 +0, 132, 132, 1, 622080, 0xd380e7cb +0, 133, 133, 1, 622080, 0xfd1247d5 +0, 134, 134, 1, 622080, 0xd0de3b55 +0, 135, 135, 1, 622080, 0xa876d813 +0, 136, 136, 1, 622080, 0xdc8d8f66 +0, 137, 137, 1, 622080, 0x3a8e5ffe +0, 138, 138, 1, 622080, 0x1a8a31da +0, 139, 139, 1, 622080, 0x7e975fba +0, 140, 140, 1, 622080, 0x242ef158 +0, 141, 141, 1, 622080, 0xbcad3b81 +0, 142, 142, 1, 622080, 0x5db0701f +0, 143, 143, 1, 622080, 0x4cbf3ab5 +0, 144, 144, 1, 622080, 0xed603395 +0, 145, 145, 1, 622080, 0xd098834b +0, 146, 146, 1, 622080, 0x92b972e0 +0, 147, 147, 1, 622080, 0xdd4f64d5 +0, 148, 148, 1, 622080, 0x60b1a37b +0, 149, 149, 1, 622080, 0xed6efdba +0, 150, 150, 1, 622080, 0xa30235f6 +0, 151, 151, 1, 622080, 0x3419d5c3 +0, 152, 152, 1, 622080, 0x1adbd052 +0, 153, 153, 1, 622080, 0x88e14b04 +0, 154, 154, 1, 622080, 0xca66eada +0, 155, 155, 1, 622080, 0xa6daa83c +0, 156, 156, 1, 622080, 0x7ea4d899 +0, 157, 157, 1, 622080, 0x4929fce5 +0, 158, 158, 1, 622080, 0x3c2d6009 +0, 159, 159, 1, 622080, 0xa40e8949 +0, 160, 160, 1, 622080, 0x624801ea +0, 161, 161, 1, 622080, 0x7877045d +0, 162, 162, 1, 622080, 0x8dae0e94 +0, 163, 163, 1, 622080, 0xaed5bfd9 +0, 164, 164, 1, 622080, 0x17ab701c +0, 165, 165, 1, 622080, 0x564f44e8 +0, 166, 166, 1, 622080, 0x05496a5d +0, 167, 167, 1, 622080, 0xdcb4cee8 +0, 168, 168, 1, 622080, 0xb41172e5 +0, 169, 169, 1, 622080, 0x56c72478 +0, 170, 170, 1, 622080, 0x84ff3af9 diff --git a/tests/ref/fate/cine-demux b/tests/ref/fate/cine-demux new file mode 100644 index 000000000..bb7ac70d4 --- /dev/null +++ b/tests/ref/fate/cine-demux @@ -0,0 +1 @@ +CRC=0x8555ed33 diff --git a/tests/ref/fate/crc b/tests/ref/fate/crc index 89273d8d3..8aa0dd244 100644 --- a/tests/ref/fate/crc +++ b/tests/ref/fate/crc @@ -1,5 +1,6 @@ crc EDB88320 = 3D5CDD04 crc 04C11DB7 = E0BAF5C0 crc 00864CFB = 326039 +crc 0000A001 = BFD8 crc 00008005 = BB1F crc 00000007 = E3 diff --git a/tests/ref/fate/exif-image-tiff b/tests/ref/fate/exif-image-tiff index 6ccc48e13..515e3f186 100644 --- a/tests/ref/fate/exif-image-tiff +++ b/tests/ref/fate/exif-image-tiff @@ -14,7 +14,7 @@ pkt_size=67604 width=200 height=112 pix_fmt=rgb24 -sample_aspect_ratio=N/A +sample_aspect_ratio=1:1 pict_type=? coded_picture_number=0 display_picture_number=0 diff --git a/tests/ref/fate/ffprobe_compact b/tests/ref/fate/ffprobe_compact index c74454407..ad646aff7 100644 --- a/tests/ref/fate/ffprobe_compact +++ b/tests/ref/fate/ffprobe_compact @@ -1,32 +1,32 @@ -packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=572|flags=K -frame|media_type=audio|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=572|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=video|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=2647|flags=K -frame|media_type=video|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=2647|pkt_size=N/A|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 -packet|codec_type=video|stream_index=2|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=233068|flags=K -frame|media_type=video|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=233068|pkt_size=N/A|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 -packet|codec_type=audio|stream_index=0|pts=1024|pts_time=0.023220|dts=1024|dts_time=0.023220|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=263073|flags=K -frame|media_type=audio|key_frame=1|pkt_pts=1024|pkt_pts_time=0.023220|pkt_dts=1024|pkt_dts_time=0.023220|best_effort_timestamp=1024|best_effort_timestamp_time=0.023220|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=263073|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=video|stream_index=1|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=265151|flags=K -frame|media_type=video|key_frame=1|pkt_pts=2048|pkt_pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=265151|pkt_size=N/A|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 -packet|codec_type=video|stream_index=2|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=495575|flags=K -frame|media_type=video|key_frame=1|pkt_pts=2048|pkt_pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=495575|pkt_size=N/A|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 -packet|codec_type=audio|stream_index=0|pts=2048|pts_time=0.046440|dts=2048|dts_time=0.046440|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=525580|flags=K -frame|media_type=audio|key_frame=1|pkt_pts=2048|pkt_pts_time=0.046440|pkt_dts=2048|pkt_dts_time=0.046440|best_effort_timestamp=2048|best_effort_timestamp_time=0.046440|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=525580|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=3072|pts_time=0.069660|dts=3072|dts_time=0.069660|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=527651|flags=K -frame|media_type=audio|key_frame=1|pkt_pts=3072|pkt_pts_time=0.069660|pkt_dts=3072|pkt_dts_time=0.069660|best_effort_timestamp=3072|best_effort_timestamp_time=0.069660|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=527651|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=video|stream_index=1|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=529729|flags=K -frame|media_type=video|key_frame=1|pkt_pts=4096|pkt_pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=529729|pkt_size=N/A|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 -packet|codec_type=video|stream_index=2|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=760153|flags=K -frame|media_type=video|key_frame=1|pkt_pts=4096|pkt_pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=760153|pkt_size=N/A|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 -packet|codec_type=audio|stream_index=0|pts=4096|pts_time=0.092880|dts=4096|dts_time=0.092880|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=790158|flags=K -frame|media_type=audio|key_frame=1|pkt_pts=4096|pkt_pts_time=0.092880|pkt_dts=4096|pkt_dts_time=0.092880|best_effort_timestamp=4096|best_effort_timestamp_time=0.092880|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=790158|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=792229|flags=K -frame|media_type=audio|key_frame=1|pkt_pts=5120|pkt_pts_time=0.116100|pkt_dts=5120|pkt_dts_time=0.116100|best_effort_timestamp=5120|best_effort_timestamp_time=0.116100|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=792229|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=video|stream_index=1|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=794307|flags=K -frame|media_type=video|key_frame=1|pkt_pts=6144|pkt_pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=794307|pkt_size=N/A|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 -packet|codec_type=video|stream_index=2|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=1024731|flags=K -frame|media_type=video|key_frame=1|pkt_pts=6144|pkt_pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=1024731|pkt_size=N/A|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 -stream|index=0|codec_name=pcm_s16le|profile=unknown|codec_type=audio|codec_time_base=1/44100|codec_tag_string=PSD[16]|codec_tag=0x10445350|sample_fmt=s16|sample_rate=44100|channels=1|channel_layout=unknown|bits_per_sample=16|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/44100|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=705600|nb_frames=N/A|nb_read_frames=6|nb_read_packets=6|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|tag:E=mc² -stream|index=1|codec_name=rawvideo|profile=unknown|codec_type=video|codec_time_base=1/51200|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=320|height=240|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=4:3|pix_fmt=rgb24|level=-99|timecode=N/A|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|tag:title=foobar|tag:duration_ts=field-and-tags-conflict-attempt -stream|index=2|codec_name=rawvideo|profile=unknown|codec_type=video|codec_time_base=1/51200|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=100|height=100|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=1:1|pix_fmt=rgb24|level=-99|timecode=N/A|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0 -format|filename=tests/data/ffprobe-test.nut|nb_streams=3|nb_programs=0|format_name=nut|start_time=0.000000|duration=0.120000|size=1054812|bit_rate=70320800|probe_score=100|tag:title=ffprobe test file|tag:comment='A comment with CSV, XML & JSON special chars': |tag:comment2=I ♥ Üñîçød€ +packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=642|flags=K +frame|media_type=audio|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=642|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=video|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=2717|flags=K +frame|media_type=video|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=2717|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 +packet|codec_type=video|stream_index=2|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=233138|flags=K +frame|media_type=video|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=233138|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 +packet|codec_type=audio|stream_index=0|pts=1024|pts_time=0.023220|dts=1024|dts_time=0.023220|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=263143|flags=K +frame|media_type=audio|key_frame=1|pkt_pts=1024|pkt_pts_time=0.023220|pkt_dts=1024|pkt_dts_time=0.023220|best_effort_timestamp=1024|best_effort_timestamp_time=0.023220|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=263143|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=video|stream_index=1|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=265221|flags=K +frame|media_type=video|key_frame=1|pkt_pts=2048|pkt_pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=265221|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 +packet|codec_type=video|stream_index=2|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=495645|flags=K +frame|media_type=video|key_frame=1|pkt_pts=2048|pkt_pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=495645|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 +packet|codec_type=audio|stream_index=0|pts=2048|pts_time=0.046440|dts=2048|dts_time=0.046440|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=525650|flags=K +frame|media_type=audio|key_frame=1|pkt_pts=2048|pkt_pts_time=0.046440|pkt_dts=2048|pkt_dts_time=0.046440|best_effort_timestamp=2048|best_effort_timestamp_time=0.046440|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=525650|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=audio|stream_index=0|pts=3072|pts_time=0.069660|dts=3072|dts_time=0.069660|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=527721|flags=K +frame|media_type=audio|key_frame=1|pkt_pts=3072|pkt_pts_time=0.069660|pkt_dts=3072|pkt_dts_time=0.069660|best_effort_timestamp=3072|best_effort_timestamp_time=0.069660|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=527721|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=video|stream_index=1|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=529799|flags=K +frame|media_type=video|key_frame=1|pkt_pts=4096|pkt_pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=529799|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 +packet|codec_type=video|stream_index=2|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=760223|flags=K +frame|media_type=video|key_frame=1|pkt_pts=4096|pkt_pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=760223|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 +packet|codec_type=audio|stream_index=0|pts=4096|pts_time=0.092880|dts=4096|dts_time=0.092880|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=790228|flags=K +frame|media_type=audio|key_frame=1|pkt_pts=4096|pkt_pts_time=0.092880|pkt_dts=4096|pkt_dts_time=0.092880|best_effort_timestamp=4096|best_effort_timestamp_time=0.092880|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=790228|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=792299|flags=K +frame|media_type=audio|key_frame=1|pkt_pts=5120|pkt_pts_time=0.116100|pkt_dts=5120|pkt_dts_time=0.116100|best_effort_timestamp=5120|best_effort_timestamp_time=0.116100|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=792299|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=video|stream_index=1|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=794377|flags=K +frame|media_type=video|key_frame=1|pkt_pts=6144|pkt_pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=794377|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 +packet|codec_type=video|stream_index=2|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=1024801|flags=K +frame|media_type=video|key_frame=1|pkt_pts=6144|pkt_pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=1024801|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0 +stream|index=0|codec_name=pcm_s16le|profile=unknown|codec_type=audio|codec_time_base=1/44100|codec_tag_string=PSD[16]|codec_tag=0x10445350|sample_fmt=s16|sample_rate=44100|channels=1|channel_layout=unknown|bits_per_sample=16|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/44100|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=705600|max_bit_rate=N/A|nb_frames=N/A|nb_read_frames=6|nb_read_packets=6|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|tag:E=mc²|tag:encoder=Lavc pcm_s16le +stream|index=1|codec_name=rawvideo|profile=unknown|codec_type=video|codec_time_base=1/51200|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=320|height=240|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=4:3|pix_fmt=rgb24|level=-99|color_range=N/A|color_space=unknown|timecode=N/A|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|tag:title=foobar|tag:duration_ts=field-and-tags-conflict-attempt|tag:encoder=Lavc rawvideo +stream|index=2|codec_name=rawvideo|profile=unknown|codec_type=video|codec_time_base=1/51200|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=100|height=100|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=1:1|pix_fmt=rgb24|level=-99|color_range=N/A|color_space=unknown|timecode=N/A|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|tag:encoder=Lavc rawvideo +format|filename=tests/data/ffprobe-test.nut|nb_streams=3|nb_programs=0|format_name=nut|start_time=0.000000|duration=0.120000|size=1054882|bit_rate=70325466|probe_score=100|tag:title=ffprobe test file|tag:comment='A comment with CSV, XML & JSON special chars': |tag:comment2=I ♥ Üñîçød€ diff --git a/tests/ref/fate/ffprobe_csv b/tests/ref/fate/ffprobe_csv index 88ed221e5..219e571b4 100644 --- a/tests/ref/fate/ffprobe_csv +++ b/tests/ref/fate/ffprobe_csv @@ -1,32 +1,32 @@ -packet,audio,0,0,0.000000,0,0.000000,1024,0.023220,N/A,N/A,2048,572,K -frame,audio,1,0,0.000000,0,0.000000,0,0.000000,1024,0.023220,572,2048,s16,1024,1,unknown -packet,video,1,0,0.000000,0,0.000000,2048,0.040000,N/A,N/A,230400,2647,K -frame,video,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,2647,N/A,320,240,rgb24,1:1,I,0,0,0,0,0 -packet,video,2,0,0.000000,0,0.000000,2048,0.040000,N/A,N/A,30000,233068,K -frame,video,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,233068,N/A,100,100,rgb24,1:1,I,0,0,0,0,0 -packet,audio,0,1024,0.023220,1024,0.023220,1024,0.023220,N/A,N/A,2048,263073,K -frame,audio,1,1024,0.023220,1024,0.023220,1024,0.023220,1024,0.023220,263073,2048,s16,1024,1,unknown -packet,video,1,2048,0.040000,2048,0.040000,2048,0.040000,N/A,N/A,230400,265151,K -frame,video,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,265151,N/A,320,240,rgb24,1:1,I,0,0,0,0,0 -packet,video,2,2048,0.040000,2048,0.040000,2048,0.040000,N/A,N/A,30000,495575,K -frame,video,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,495575,N/A,100,100,rgb24,1:1,I,0,0,0,0,0 -packet,audio,0,2048,0.046440,2048,0.046440,1024,0.023220,N/A,N/A,2048,525580,K -frame,audio,1,2048,0.046440,2048,0.046440,2048,0.046440,1024,0.023220,525580,2048,s16,1024,1,unknown -packet,audio,0,3072,0.069660,3072,0.069660,1024,0.023220,N/A,N/A,2048,527651,K -frame,audio,1,3072,0.069660,3072,0.069660,3072,0.069660,1024,0.023220,527651,2048,s16,1024,1,unknown -packet,video,1,4096,0.080000,4096,0.080000,2048,0.040000,N/A,N/A,230400,529729,K -frame,video,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,529729,N/A,320,240,rgb24,1:1,I,0,0,0,0,0 -packet,video,2,4096,0.080000,4096,0.080000,2048,0.040000,N/A,N/A,30000,760153,K -frame,video,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,760153,N/A,100,100,rgb24,1:1,I,0,0,0,0,0 -packet,audio,0,4096,0.092880,4096,0.092880,1024,0.023220,N/A,N/A,2048,790158,K -frame,audio,1,4096,0.092880,4096,0.092880,4096,0.092880,1024,0.023220,790158,2048,s16,1024,1,unknown -packet,audio,0,5120,0.116100,5120,0.116100,1024,0.023220,N/A,N/A,2048,792229,K -frame,audio,1,5120,0.116100,5120,0.116100,5120,0.116100,1024,0.023220,792229,2048,s16,1024,1,unknown -packet,video,1,6144,0.120000,6144,0.120000,2048,0.040000,N/A,N/A,230400,794307,K -frame,video,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,794307,N/A,320,240,rgb24,1:1,I,0,0,0,0,0 -packet,video,2,6144,0.120000,6144,0.120000,2048,0.040000,N/A,N/A,30000,1024731,K -frame,video,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,1024731,N/A,100,100,rgb24,1:1,I,0,0,0,0,0 -stream,0,pcm_s16le,unknown,audio,1/44100,PSD[16],0x10445350,s16,44100,1,unknown,16,N/A,0/0,0/0,1/44100,0,0.000000,N/A,N/A,705600,N/A,6,6,0,0,0,0,0,0,0,0,0,0,0,mc² -stream,1,rawvideo,unknown,video,1/51200,RGB[24],0x18424752,320,240,0,1:1,4:3,rgb24,-99,N/A,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0,foobar,field-and-tags-conflict-attempt -stream,2,rawvideo,unknown,video,1/51200,RGB[24],0x18424752,100,100,0,1:1,1:1,rgb24,-99,N/A,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0 -format,tests/data/ffprobe-test.nut,3,0,nut,0.000000,0.120000,1054812,70320800,100,ffprobe test file,"'A comment with CSV, XML & JSON special chars': ",I ♥ Üñîçød€ +packet,audio,0,0,0.000000,0,0.000000,1024,0.023220,N/A,N/A,2048,642,K +frame,audio,1,0,0.000000,0,0.000000,0,0.000000,1024,0.023220,642,2048,s16,1024,1,unknown +packet,video,1,0,0.000000,0,0.000000,2048,0.040000,N/A,N/A,230400,2717,K +frame,video,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,2717,230400,320,240,rgb24,1:1,I,0,0,0,0,0 +packet,video,2,0,0.000000,0,0.000000,2048,0.040000,N/A,N/A,30000,233138,K +frame,video,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,233138,30000,100,100,rgb24,1:1,I,0,0,0,0,0 +packet,audio,0,1024,0.023220,1024,0.023220,1024,0.023220,N/A,N/A,2048,263143,K +frame,audio,1,1024,0.023220,1024,0.023220,1024,0.023220,1024,0.023220,263143,2048,s16,1024,1,unknown +packet,video,1,2048,0.040000,2048,0.040000,2048,0.040000,N/A,N/A,230400,265221,K +frame,video,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,265221,230400,320,240,rgb24,1:1,I,0,0,0,0,0 +packet,video,2,2048,0.040000,2048,0.040000,2048,0.040000,N/A,N/A,30000,495645,K +frame,video,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,495645,30000,100,100,rgb24,1:1,I,0,0,0,0,0 +packet,audio,0,2048,0.046440,2048,0.046440,1024,0.023220,N/A,N/A,2048,525650,K +frame,audio,1,2048,0.046440,2048,0.046440,2048,0.046440,1024,0.023220,525650,2048,s16,1024,1,unknown +packet,audio,0,3072,0.069660,3072,0.069660,1024,0.023220,N/A,N/A,2048,527721,K +frame,audio,1,3072,0.069660,3072,0.069660,3072,0.069660,1024,0.023220,527721,2048,s16,1024,1,unknown +packet,video,1,4096,0.080000,4096,0.080000,2048,0.040000,N/A,N/A,230400,529799,K +frame,video,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,529799,230400,320,240,rgb24,1:1,I,0,0,0,0,0 +packet,video,2,4096,0.080000,4096,0.080000,2048,0.040000,N/A,N/A,30000,760223,K +frame,video,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,760223,30000,100,100,rgb24,1:1,I,0,0,0,0,0 +packet,audio,0,4096,0.092880,4096,0.092880,1024,0.023220,N/A,N/A,2048,790228,K +frame,audio,1,4096,0.092880,4096,0.092880,4096,0.092880,1024,0.023220,790228,2048,s16,1024,1,unknown +packet,audio,0,5120,0.116100,5120,0.116100,1024,0.023220,N/A,N/A,2048,792299,K +frame,audio,1,5120,0.116100,5120,0.116100,5120,0.116100,1024,0.023220,792299,2048,s16,1024,1,unknown +packet,video,1,6144,0.120000,6144,0.120000,2048,0.040000,N/A,N/A,230400,794377,K +frame,video,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,794377,230400,320,240,rgb24,1:1,I,0,0,0,0,0 +packet,video,2,6144,0.120000,6144,0.120000,2048,0.040000,N/A,N/A,30000,1024801,K +frame,video,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,1024801,30000,100,100,rgb24,1:1,I,0,0,0,0,0 +stream,0,pcm_s16le,unknown,audio,1/44100,PSD[16],0x10445350,s16,44100,1,unknown,16,N/A,0/0,0/0,1/44100,0,0.000000,N/A,N/A,705600,N/A,N/A,6,6,0,0,0,0,0,0,0,0,0,0,0,mc²,Lavc pcm_s16le +stream,1,rawvideo,unknown,video,1/51200,RGB[24],0x18424752,320,240,0,1:1,4:3,rgb24,-99,N/A,unknown,N/A,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0,foobar,field-and-tags-conflict-attempt,Lavc rawvideo +stream,2,rawvideo,unknown,video,1/51200,RGB[24],0x18424752,100,100,0,1:1,1:1,rgb24,-99,N/A,unknown,N/A,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0,Lavc rawvideo +format,tests/data/ffprobe-test.nut,3,0,nut,0.000000,0.120000,1054882,70325466,100,ffprobe test file,"'A comment with CSV, XML & JSON special chars': ",I ♥ Üñîçød€ diff --git a/tests/ref/fate/ffprobe_default b/tests/ref/fate/ffprobe_default index 76b9ed869..fa0f0319f 100644 --- a/tests/ref/fate/ffprobe_default +++ b/tests/ref/fate/ffprobe_default @@ -10,7 +10,7 @@ duration_time=0.023220 convergence_duration=N/A convergence_duration_time=N/A size=2048 -pos=572 +pos=642 flags=K [/PACKET] [FRAME] @@ -24,7 +24,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=572 +pkt_pos=642 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -43,7 +43,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=230400 -pos=2647 +pos=2717 flags=K [/PACKET] [FRAME] @@ -57,8 +57,8 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=2647 -pkt_size=N/A +pkt_pos=2717 +pkt_size=230400 width=320 height=240 pix_fmt=rgb24 @@ -82,7 +82,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=30000 -pos=233068 +pos=233138 flags=K [/PACKET] [FRAME] @@ -96,8 +96,8 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=233068 -pkt_size=N/A +pkt_pos=233138 +pkt_size=30000 width=100 height=100 pix_fmt=rgb24 @@ -121,7 +121,7 @@ duration_time=0.023220 convergence_duration=N/A convergence_duration_time=N/A size=2048 -pos=263073 +pos=263143 flags=K [/PACKET] [FRAME] @@ -135,7 +135,7 @@ best_effort_timestamp=1024 best_effort_timestamp_time=0.023220 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=263073 +pkt_pos=263143 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -154,7 +154,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=230400 -pos=265151 +pos=265221 flags=K [/PACKET] [FRAME] @@ -168,8 +168,8 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.040000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=265151 -pkt_size=N/A +pkt_pos=265221 +pkt_size=230400 width=320 height=240 pix_fmt=rgb24 @@ -193,7 +193,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=30000 -pos=495575 +pos=495645 flags=K [/PACKET] [FRAME] @@ -207,8 +207,8 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.040000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=495575 -pkt_size=N/A +pkt_pos=495645 +pkt_size=30000 width=100 height=100 pix_fmt=rgb24 @@ -232,7 +232,7 @@ duration_time=0.023220 convergence_duration=N/A convergence_duration_time=N/A size=2048 -pos=525580 +pos=525650 flags=K [/PACKET] [FRAME] @@ -246,7 +246,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.046440 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=525580 +pkt_pos=525650 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -265,7 +265,7 @@ duration_time=0.023220 convergence_duration=N/A convergence_duration_time=N/A size=2048 -pos=527651 +pos=527721 flags=K [/PACKET] [FRAME] @@ -279,7 +279,7 @@ best_effort_timestamp=3072 best_effort_timestamp_time=0.069660 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=527651 +pkt_pos=527721 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -298,7 +298,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=230400 -pos=529729 +pos=529799 flags=K [/PACKET] [FRAME] @@ -312,8 +312,8 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.080000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=529729 -pkt_size=N/A +pkt_pos=529799 +pkt_size=230400 width=320 height=240 pix_fmt=rgb24 @@ -337,7 +337,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=30000 -pos=760153 +pos=760223 flags=K [/PACKET] [FRAME] @@ -351,8 +351,8 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.080000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=760153 -pkt_size=N/A +pkt_pos=760223 +pkt_size=30000 width=100 height=100 pix_fmt=rgb24 @@ -376,7 +376,7 @@ duration_time=0.023220 convergence_duration=N/A convergence_duration_time=N/A size=2048 -pos=790158 +pos=790228 flags=K [/PACKET] [FRAME] @@ -390,7 +390,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.092880 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=790158 +pkt_pos=790228 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -409,7 +409,7 @@ duration_time=0.023220 convergence_duration=N/A convergence_duration_time=N/A size=2048 -pos=792229 +pos=792299 flags=K [/PACKET] [FRAME] @@ -423,7 +423,7 @@ best_effort_timestamp=5120 best_effort_timestamp_time=0.116100 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=792229 +pkt_pos=792299 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -442,7 +442,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=230400 -pos=794307 +pos=794377 flags=K [/PACKET] [FRAME] @@ -456,8 +456,8 @@ best_effort_timestamp=6144 best_effort_timestamp_time=0.120000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=794307 -pkt_size=N/A +pkt_pos=794377 +pkt_size=230400 width=320 height=240 pix_fmt=rgb24 @@ -481,7 +481,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=30000 -pos=1024731 +pos=1024801 flags=K [/PACKET] [FRAME] @@ -495,8 +495,8 @@ best_effort_timestamp=6144 best_effort_timestamp_time=0.120000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=1024731 -pkt_size=N/A +pkt_pos=1024801 +pkt_size=30000 width=100 height=100 pix_fmt=rgb24 @@ -530,6 +530,7 @@ start_time=0.000000 duration_ts=N/A duration=N/A bit_rate=705600 +max_bit_rate=N/A nb_frames=N/A nb_read_frames=6 nb_read_packets=6 @@ -545,6 +546,7 @@ DISPOSITION:visual_impaired=0 DISPOSITION:clean_effects=0 DISPOSITION:attached_pic=0 TAG:E=mc² +TAG:encoder=Lavc pcm_s16le [/STREAM] [STREAM] index=1 @@ -561,6 +563,8 @@ sample_aspect_ratio=1:1 display_aspect_ratio=4:3 pix_fmt=rgb24 level=-99 +color_range=N/A +color_space=unknown timecode=N/A id=N/A r_frame_rate=25/1 @@ -571,6 +575,7 @@ start_time=0.000000 duration_ts=N/A duration=N/A bit_rate=N/A +max_bit_rate=N/A nb_frames=N/A nb_read_frames=4 nb_read_packets=4 @@ -587,6 +592,7 @@ DISPOSITION:clean_effects=0 DISPOSITION:attached_pic=0 TAG:title=foobar TAG:duration_ts=field-and-tags-conflict-attempt +TAG:encoder=Lavc rawvideo [/STREAM] [STREAM] index=2 @@ -603,6 +609,8 @@ sample_aspect_ratio=1:1 display_aspect_ratio=1:1 pix_fmt=rgb24 level=-99 +color_range=N/A +color_space=unknown timecode=N/A id=N/A r_frame_rate=25/1 @@ -613,6 +621,7 @@ start_time=0.000000 duration_ts=N/A duration=N/A bit_rate=N/A +max_bit_rate=N/A nb_frames=N/A nb_read_frames=4 nb_read_packets=4 @@ -627,6 +636,7 @@ DISPOSITION:hearing_impaired=0 DISPOSITION:visual_impaired=0 DISPOSITION:clean_effects=0 DISPOSITION:attached_pic=0 +TAG:encoder=Lavc rawvideo [/STREAM] [FORMAT] filename=tests/data/ffprobe-test.nut @@ -635,8 +645,8 @@ nb_programs=0 format_name=nut start_time=0.000000 duration=0.120000 -size=1054812 -bit_rate=70320800 +size=1054882 +bit_rate=70325466 probe_score=100 TAG:title=ffprobe test file TAG:comment='A comment with CSV, XML & JSON special chars': diff --git a/tests/ref/fate/ffprobe_flat b/tests/ref/fate/ffprobe_flat index 44a1dcf90..e5866d267 100644 --- a/tests/ref/fate/ffprobe_flat +++ b/tests/ref/fate/ffprobe_flat @@ -9,7 +9,7 @@ packets_and_frames.packet.0.duration_time="0.023220" packets_and_frames.packet.0.convergence_duration="N/A" packets_and_frames.packet.0.convergence_duration_time="N/A" packets_and_frames.packet.0.size="2048" -packets_and_frames.packet.0.pos="572" +packets_and_frames.packet.0.pos="642" packets_and_frames.packet.0.flags="K" packets_and_frames.frame.0.media_type="audio" packets_and_frames.frame.0.key_frame=1 @@ -21,7 +21,7 @@ packets_and_frames.frame.0.best_effort_timestamp=0 packets_and_frames.frame.0.best_effort_timestamp_time="0.000000" packets_and_frames.frame.0.pkt_duration=1024 packets_and_frames.frame.0.pkt_duration_time="0.023220" -packets_and_frames.frame.0.pkt_pos="572" +packets_and_frames.frame.0.pkt_pos="642" packets_and_frames.frame.0.pkt_size="2048" packets_and_frames.frame.0.sample_fmt="s16" packets_and_frames.frame.0.nb_samples=1024 @@ -38,7 +38,7 @@ packets_and_frames.packet.1.duration_time="0.040000" packets_and_frames.packet.1.convergence_duration="N/A" packets_and_frames.packet.1.convergence_duration_time="N/A" packets_and_frames.packet.1.size="230400" -packets_and_frames.packet.1.pos="2647" +packets_and_frames.packet.1.pos="2717" packets_and_frames.packet.1.flags="K" packets_and_frames.frame.1.media_type="video" packets_and_frames.frame.1.key_frame=1 @@ -50,8 +50,8 @@ packets_and_frames.frame.1.best_effort_timestamp=0 packets_and_frames.frame.1.best_effort_timestamp_time="0.000000" packets_and_frames.frame.1.pkt_duration=2048 packets_and_frames.frame.1.pkt_duration_time="0.040000" -packets_and_frames.frame.1.pkt_pos="2647" -packets_and_frames.frame.1.pkt_size="N/A" +packets_and_frames.frame.1.pkt_pos="2717" +packets_and_frames.frame.1.pkt_size="230400" packets_and_frames.frame.1.width=320 packets_and_frames.frame.1.height=240 packets_and_frames.frame.1.pix_fmt="rgb24" @@ -73,7 +73,7 @@ packets_and_frames.packet.2.duration_time="0.040000" packets_and_frames.packet.2.convergence_duration="N/A" packets_and_frames.packet.2.convergence_duration_time="N/A" packets_and_frames.packet.2.size="30000" -packets_and_frames.packet.2.pos="233068" +packets_and_frames.packet.2.pos="233138" packets_and_frames.packet.2.flags="K" packets_and_frames.frame.2.media_type="video" packets_and_frames.frame.2.key_frame=1 @@ -85,8 +85,8 @@ packets_and_frames.frame.2.best_effort_timestamp=0 packets_and_frames.frame.2.best_effort_timestamp_time="0.000000" packets_and_frames.frame.2.pkt_duration=2048 packets_and_frames.frame.2.pkt_duration_time="0.040000" -packets_and_frames.frame.2.pkt_pos="233068" -packets_and_frames.frame.2.pkt_size="N/A" +packets_and_frames.frame.2.pkt_pos="233138" +packets_and_frames.frame.2.pkt_size="30000" packets_and_frames.frame.2.width=100 packets_and_frames.frame.2.height=100 packets_and_frames.frame.2.pix_fmt="rgb24" @@ -108,7 +108,7 @@ packets_and_frames.packet.3.duration_time="0.023220" packets_and_frames.packet.3.convergence_duration="N/A" packets_and_frames.packet.3.convergence_duration_time="N/A" packets_and_frames.packet.3.size="2048" -packets_and_frames.packet.3.pos="263073" +packets_and_frames.packet.3.pos="263143" packets_and_frames.packet.3.flags="K" packets_and_frames.frame.3.media_type="audio" packets_and_frames.frame.3.key_frame=1 @@ -120,7 +120,7 @@ packets_and_frames.frame.3.best_effort_timestamp=1024 packets_and_frames.frame.3.best_effort_timestamp_time="0.023220" packets_and_frames.frame.3.pkt_duration=1024 packets_and_frames.frame.3.pkt_duration_time="0.023220" -packets_and_frames.frame.3.pkt_pos="263073" +packets_and_frames.frame.3.pkt_pos="263143" packets_and_frames.frame.3.pkt_size="2048" packets_and_frames.frame.3.sample_fmt="s16" packets_and_frames.frame.3.nb_samples=1024 @@ -137,7 +137,7 @@ packets_and_frames.packet.4.duration_time="0.040000" packets_and_frames.packet.4.convergence_duration="N/A" packets_and_frames.packet.4.convergence_duration_time="N/A" packets_and_frames.packet.4.size="230400" -packets_and_frames.packet.4.pos="265151" +packets_and_frames.packet.4.pos="265221" packets_and_frames.packet.4.flags="K" packets_and_frames.frame.4.media_type="video" packets_and_frames.frame.4.key_frame=1 @@ -149,8 +149,8 @@ packets_and_frames.frame.4.best_effort_timestamp=2048 packets_and_frames.frame.4.best_effort_timestamp_time="0.040000" packets_and_frames.frame.4.pkt_duration=2048 packets_and_frames.frame.4.pkt_duration_time="0.040000" -packets_and_frames.frame.4.pkt_pos="265151" -packets_and_frames.frame.4.pkt_size="N/A" +packets_and_frames.frame.4.pkt_pos="265221" +packets_and_frames.frame.4.pkt_size="230400" packets_and_frames.frame.4.width=320 packets_and_frames.frame.4.height=240 packets_and_frames.frame.4.pix_fmt="rgb24" @@ -172,7 +172,7 @@ packets_and_frames.packet.5.duration_time="0.040000" packets_and_frames.packet.5.convergence_duration="N/A" packets_and_frames.packet.5.convergence_duration_time="N/A" packets_and_frames.packet.5.size="30000" -packets_and_frames.packet.5.pos="495575" +packets_and_frames.packet.5.pos="495645" packets_and_frames.packet.5.flags="K" packets_and_frames.frame.5.media_type="video" packets_and_frames.frame.5.key_frame=1 @@ -184,8 +184,8 @@ packets_and_frames.frame.5.best_effort_timestamp=2048 packets_and_frames.frame.5.best_effort_timestamp_time="0.040000" packets_and_frames.frame.5.pkt_duration=2048 packets_and_frames.frame.5.pkt_duration_time="0.040000" -packets_and_frames.frame.5.pkt_pos="495575" -packets_and_frames.frame.5.pkt_size="N/A" +packets_and_frames.frame.5.pkt_pos="495645" +packets_and_frames.frame.5.pkt_size="30000" packets_and_frames.frame.5.width=100 packets_and_frames.frame.5.height=100 packets_and_frames.frame.5.pix_fmt="rgb24" @@ -207,7 +207,7 @@ packets_and_frames.packet.6.duration_time="0.023220" packets_and_frames.packet.6.convergence_duration="N/A" packets_and_frames.packet.6.convergence_duration_time="N/A" packets_and_frames.packet.6.size="2048" -packets_and_frames.packet.6.pos="525580" +packets_and_frames.packet.6.pos="525650" packets_and_frames.packet.6.flags="K" packets_and_frames.frame.6.media_type="audio" packets_and_frames.frame.6.key_frame=1 @@ -219,7 +219,7 @@ packets_and_frames.frame.6.best_effort_timestamp=2048 packets_and_frames.frame.6.best_effort_timestamp_time="0.046440" packets_and_frames.frame.6.pkt_duration=1024 packets_and_frames.frame.6.pkt_duration_time="0.023220" -packets_and_frames.frame.6.pkt_pos="525580" +packets_and_frames.frame.6.pkt_pos="525650" packets_and_frames.frame.6.pkt_size="2048" packets_and_frames.frame.6.sample_fmt="s16" packets_and_frames.frame.6.nb_samples=1024 @@ -236,7 +236,7 @@ packets_and_frames.packet.7.duration_time="0.023220" packets_and_frames.packet.7.convergence_duration="N/A" packets_and_frames.packet.7.convergence_duration_time="N/A" packets_and_frames.packet.7.size="2048" -packets_and_frames.packet.7.pos="527651" +packets_and_frames.packet.7.pos="527721" packets_and_frames.packet.7.flags="K" packets_and_frames.frame.7.media_type="audio" packets_and_frames.frame.7.key_frame=1 @@ -248,7 +248,7 @@ packets_and_frames.frame.7.best_effort_timestamp=3072 packets_and_frames.frame.7.best_effort_timestamp_time="0.069660" packets_and_frames.frame.7.pkt_duration=1024 packets_and_frames.frame.7.pkt_duration_time="0.023220" -packets_and_frames.frame.7.pkt_pos="527651" +packets_and_frames.frame.7.pkt_pos="527721" packets_and_frames.frame.7.pkt_size="2048" packets_and_frames.frame.7.sample_fmt="s16" packets_and_frames.frame.7.nb_samples=1024 @@ -265,7 +265,7 @@ packets_and_frames.packet.8.duration_time="0.040000" packets_and_frames.packet.8.convergence_duration="N/A" packets_and_frames.packet.8.convergence_duration_time="N/A" packets_and_frames.packet.8.size="230400" -packets_and_frames.packet.8.pos="529729" +packets_and_frames.packet.8.pos="529799" packets_and_frames.packet.8.flags="K" packets_and_frames.frame.8.media_type="video" packets_and_frames.frame.8.key_frame=1 @@ -277,8 +277,8 @@ packets_and_frames.frame.8.best_effort_timestamp=4096 packets_and_frames.frame.8.best_effort_timestamp_time="0.080000" packets_and_frames.frame.8.pkt_duration=2048 packets_and_frames.frame.8.pkt_duration_time="0.040000" -packets_and_frames.frame.8.pkt_pos="529729" -packets_and_frames.frame.8.pkt_size="N/A" +packets_and_frames.frame.8.pkt_pos="529799" +packets_and_frames.frame.8.pkt_size="230400" packets_and_frames.frame.8.width=320 packets_and_frames.frame.8.height=240 packets_and_frames.frame.8.pix_fmt="rgb24" @@ -300,7 +300,7 @@ packets_and_frames.packet.9.duration_time="0.040000" packets_and_frames.packet.9.convergence_duration="N/A" packets_and_frames.packet.9.convergence_duration_time="N/A" packets_and_frames.packet.9.size="30000" -packets_and_frames.packet.9.pos="760153" +packets_and_frames.packet.9.pos="760223" packets_and_frames.packet.9.flags="K" packets_and_frames.frame.9.media_type="video" packets_and_frames.frame.9.key_frame=1 @@ -312,8 +312,8 @@ packets_and_frames.frame.9.best_effort_timestamp=4096 packets_and_frames.frame.9.best_effort_timestamp_time="0.080000" packets_and_frames.frame.9.pkt_duration=2048 packets_and_frames.frame.9.pkt_duration_time="0.040000" -packets_and_frames.frame.9.pkt_pos="760153" -packets_and_frames.frame.9.pkt_size="N/A" +packets_and_frames.frame.9.pkt_pos="760223" +packets_and_frames.frame.9.pkt_size="30000" packets_and_frames.frame.9.width=100 packets_and_frames.frame.9.height=100 packets_and_frames.frame.9.pix_fmt="rgb24" @@ -335,7 +335,7 @@ packets_and_frames.packet.10.duration_time="0.023220" packets_and_frames.packet.10.convergence_duration="N/A" packets_and_frames.packet.10.convergence_duration_time="N/A" packets_and_frames.packet.10.size="2048" -packets_and_frames.packet.10.pos="790158" +packets_and_frames.packet.10.pos="790228" packets_and_frames.packet.10.flags="K" packets_and_frames.frame.10.media_type="audio" packets_and_frames.frame.10.key_frame=1 @@ -347,7 +347,7 @@ packets_and_frames.frame.10.best_effort_timestamp=4096 packets_and_frames.frame.10.best_effort_timestamp_time="0.092880" packets_and_frames.frame.10.pkt_duration=1024 packets_and_frames.frame.10.pkt_duration_time="0.023220" -packets_and_frames.frame.10.pkt_pos="790158" +packets_and_frames.frame.10.pkt_pos="790228" packets_and_frames.frame.10.pkt_size="2048" packets_and_frames.frame.10.sample_fmt="s16" packets_and_frames.frame.10.nb_samples=1024 @@ -364,7 +364,7 @@ packets_and_frames.packet.11.duration_time="0.023220" packets_and_frames.packet.11.convergence_duration="N/A" packets_and_frames.packet.11.convergence_duration_time="N/A" packets_and_frames.packet.11.size="2048" -packets_and_frames.packet.11.pos="792229" +packets_and_frames.packet.11.pos="792299" packets_and_frames.packet.11.flags="K" packets_and_frames.frame.11.media_type="audio" packets_and_frames.frame.11.key_frame=1 @@ -376,7 +376,7 @@ packets_and_frames.frame.11.best_effort_timestamp=5120 packets_and_frames.frame.11.best_effort_timestamp_time="0.116100" packets_and_frames.frame.11.pkt_duration=1024 packets_and_frames.frame.11.pkt_duration_time="0.023220" -packets_and_frames.frame.11.pkt_pos="792229" +packets_and_frames.frame.11.pkt_pos="792299" packets_and_frames.frame.11.pkt_size="2048" packets_and_frames.frame.11.sample_fmt="s16" packets_and_frames.frame.11.nb_samples=1024 @@ -393,7 +393,7 @@ packets_and_frames.packet.12.duration_time="0.040000" packets_and_frames.packet.12.convergence_duration="N/A" packets_and_frames.packet.12.convergence_duration_time="N/A" packets_and_frames.packet.12.size="230400" -packets_and_frames.packet.12.pos="794307" +packets_and_frames.packet.12.pos="794377" packets_and_frames.packet.12.flags="K" packets_and_frames.frame.12.media_type="video" packets_and_frames.frame.12.key_frame=1 @@ -405,8 +405,8 @@ packets_and_frames.frame.12.best_effort_timestamp=6144 packets_and_frames.frame.12.best_effort_timestamp_time="0.120000" packets_and_frames.frame.12.pkt_duration=2048 packets_and_frames.frame.12.pkt_duration_time="0.040000" -packets_and_frames.frame.12.pkt_pos="794307" -packets_and_frames.frame.12.pkt_size="N/A" +packets_and_frames.frame.12.pkt_pos="794377" +packets_and_frames.frame.12.pkt_size="230400" packets_and_frames.frame.12.width=320 packets_and_frames.frame.12.height=240 packets_and_frames.frame.12.pix_fmt="rgb24" @@ -428,7 +428,7 @@ packets_and_frames.packet.13.duration_time="0.040000" packets_and_frames.packet.13.convergence_duration="N/A" packets_and_frames.packet.13.convergence_duration_time="N/A" packets_and_frames.packet.13.size="30000" -packets_and_frames.packet.13.pos="1024731" +packets_and_frames.packet.13.pos="1024801" packets_and_frames.packet.13.flags="K" packets_and_frames.frame.13.media_type="video" packets_and_frames.frame.13.key_frame=1 @@ -440,8 +440,8 @@ packets_and_frames.frame.13.best_effort_timestamp=6144 packets_and_frames.frame.13.best_effort_timestamp_time="0.120000" packets_and_frames.frame.13.pkt_duration=2048 packets_and_frames.frame.13.pkt_duration_time="0.040000" -packets_and_frames.frame.13.pkt_pos="1024731" -packets_and_frames.frame.13.pkt_size="N/A" +packets_and_frames.frame.13.pkt_pos="1024801" +packets_and_frames.frame.13.pkt_size="30000" packets_and_frames.frame.13.width=100 packets_and_frames.frame.13.height=100 packets_and_frames.frame.13.pix_fmt="rgb24" @@ -473,6 +473,7 @@ streams.stream.0.start_time="0.000000" streams.stream.0.duration_ts="N/A" streams.stream.0.duration="N/A" streams.stream.0.bit_rate="705600" +streams.stream.0.max_bit_rate="N/A" streams.stream.0.nb_frames="N/A" streams.stream.0.nb_read_frames="6" streams.stream.0.nb_read_packets="6" @@ -488,6 +489,7 @@ streams.stream.0.disposition.visual_impaired=0 streams.stream.0.disposition.clean_effects=0 streams.stream.0.disposition.attached_pic=0 streams.stream.0.tags.E="mc²" +streams.stream.0.tags.encoder="Lavc pcm_s16le" streams.stream.1.index=1 streams.stream.1.codec_name="rawvideo" streams.stream.1.profile="unknown" @@ -502,6 +504,8 @@ streams.stream.1.sample_aspect_ratio="1:1" streams.stream.1.display_aspect_ratio="4:3" streams.stream.1.pix_fmt="rgb24" streams.stream.1.level=-99 +streams.stream.1.color_range="N/A" +streams.stream.1.color_space="unknown" streams.stream.1.timecode="N/A" streams.stream.1.id="N/A" streams.stream.1.r_frame_rate="25/1" @@ -512,6 +516,7 @@ streams.stream.1.start_time="0.000000" streams.stream.1.duration_ts="N/A" streams.stream.1.duration="N/A" streams.stream.1.bit_rate="N/A" +streams.stream.1.max_bit_rate="N/A" streams.stream.1.nb_frames="N/A" streams.stream.1.nb_read_frames="4" streams.stream.1.nb_read_packets="4" @@ -528,6 +533,7 @@ streams.stream.1.disposition.clean_effects=0 streams.stream.1.disposition.attached_pic=0 streams.stream.1.tags.title="foobar" streams.stream.1.tags.duration_ts="field-and-tags-conflict-attempt" +streams.stream.1.tags.encoder="Lavc rawvideo" streams.stream.2.index=2 streams.stream.2.codec_name="rawvideo" streams.stream.2.profile="unknown" @@ -542,6 +548,8 @@ streams.stream.2.sample_aspect_ratio="1:1" streams.stream.2.display_aspect_ratio="1:1" streams.stream.2.pix_fmt="rgb24" streams.stream.2.level=-99 +streams.stream.2.color_range="N/A" +streams.stream.2.color_space="unknown" streams.stream.2.timecode="N/A" streams.stream.2.id="N/A" streams.stream.2.r_frame_rate="25/1" @@ -552,6 +560,7 @@ streams.stream.2.start_time="0.000000" streams.stream.2.duration_ts="N/A" streams.stream.2.duration="N/A" streams.stream.2.bit_rate="N/A" +streams.stream.2.max_bit_rate="N/A" streams.stream.2.nb_frames="N/A" streams.stream.2.nb_read_frames="4" streams.stream.2.nb_read_packets="4" @@ -566,14 +575,15 @@ streams.stream.2.disposition.hearing_impaired=0 streams.stream.2.disposition.visual_impaired=0 streams.stream.2.disposition.clean_effects=0 streams.stream.2.disposition.attached_pic=0 +streams.stream.2.tags.encoder="Lavc rawvideo" format.filename="tests/data/ffprobe-test.nut" format.nb_streams=3 format.nb_programs=0 format.format_name="nut" format.start_time="0.000000" format.duration="0.120000" -format.size="1054812" -format.bit_rate="70320800" +format.size="1054882" +format.bit_rate="70325466" format.probe_score=100 format.tags.title="ffprobe test file" format.tags.comment="'A comment with CSV, XML & JSON special chars': " diff --git a/tests/ref/fate/ffprobe_ini b/tests/ref/fate/ffprobe_ini index 77f84e822..541022c93 100644 --- a/tests/ref/fate/ffprobe_ini +++ b/tests/ref/fate/ffprobe_ini @@ -12,7 +12,7 @@ duration_time=0.023220 convergence_duration=N/A convergence_duration_time=N/A size=2048 -pos=572 +pos=642 flags=K [packets_and_frames.frame.0] @@ -26,7 +26,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=572 +pkt_pos=642 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -45,7 +45,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=230400 -pos=2647 +pos=2717 flags=K [packets_and_frames.frame.1] @@ -59,8 +59,8 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=2647 -pkt_size=N/A +pkt_pos=2717 +pkt_size=230400 width=320 height=240 pix_fmt=rgb24 @@ -84,7 +84,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=30000 -pos=233068 +pos=233138 flags=K [packets_and_frames.frame.2] @@ -98,8 +98,8 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=233068 -pkt_size=N/A +pkt_pos=233138 +pkt_size=30000 width=100 height=100 pix_fmt=rgb24 @@ -123,7 +123,7 @@ duration_time=0.023220 convergence_duration=N/A convergence_duration_time=N/A size=2048 -pos=263073 +pos=263143 flags=K [packets_and_frames.frame.3] @@ -137,7 +137,7 @@ best_effort_timestamp=1024 best_effort_timestamp_time=0.023220 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=263073 +pkt_pos=263143 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -156,7 +156,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=230400 -pos=265151 +pos=265221 flags=K [packets_and_frames.frame.4] @@ -170,8 +170,8 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.040000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=265151 -pkt_size=N/A +pkt_pos=265221 +pkt_size=230400 width=320 height=240 pix_fmt=rgb24 @@ -195,7 +195,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=30000 -pos=495575 +pos=495645 flags=K [packets_and_frames.frame.5] @@ -209,8 +209,8 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.040000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=495575 -pkt_size=N/A +pkt_pos=495645 +pkt_size=30000 width=100 height=100 pix_fmt=rgb24 @@ -234,7 +234,7 @@ duration_time=0.023220 convergence_duration=N/A convergence_duration_time=N/A size=2048 -pos=525580 +pos=525650 flags=K [packets_and_frames.frame.6] @@ -248,7 +248,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.046440 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=525580 +pkt_pos=525650 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -267,7 +267,7 @@ duration_time=0.023220 convergence_duration=N/A convergence_duration_time=N/A size=2048 -pos=527651 +pos=527721 flags=K [packets_and_frames.frame.7] @@ -281,7 +281,7 @@ best_effort_timestamp=3072 best_effort_timestamp_time=0.069660 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=527651 +pkt_pos=527721 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -300,7 +300,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=230400 -pos=529729 +pos=529799 flags=K [packets_and_frames.frame.8] @@ -314,8 +314,8 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.080000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=529729 -pkt_size=N/A +pkt_pos=529799 +pkt_size=230400 width=320 height=240 pix_fmt=rgb24 @@ -339,7 +339,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=30000 -pos=760153 +pos=760223 flags=K [packets_and_frames.frame.9] @@ -353,8 +353,8 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.080000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=760153 -pkt_size=N/A +pkt_pos=760223 +pkt_size=30000 width=100 height=100 pix_fmt=rgb24 @@ -378,7 +378,7 @@ duration_time=0.023220 convergence_duration=N/A convergence_duration_time=N/A size=2048 -pos=790158 +pos=790228 flags=K [packets_and_frames.frame.10] @@ -392,7 +392,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.092880 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=790158 +pkt_pos=790228 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -411,7 +411,7 @@ duration_time=0.023220 convergence_duration=N/A convergence_duration_time=N/A size=2048 -pos=792229 +pos=792299 flags=K [packets_and_frames.frame.11] @@ -425,7 +425,7 @@ best_effort_timestamp=5120 best_effort_timestamp_time=0.116100 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=792229 +pkt_pos=792299 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -444,7 +444,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=230400 -pos=794307 +pos=794377 flags=K [packets_and_frames.frame.12] @@ -458,8 +458,8 @@ best_effort_timestamp=6144 best_effort_timestamp_time=0.120000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=794307 -pkt_size=N/A +pkt_pos=794377 +pkt_size=230400 width=320 height=240 pix_fmt=rgb24 @@ -483,7 +483,7 @@ duration_time=0.040000 convergence_duration=N/A convergence_duration_time=N/A size=30000 -pos=1024731 +pos=1024801 flags=K [packets_and_frames.frame.13] @@ -497,8 +497,8 @@ best_effort_timestamp=6144 best_effort_timestamp_time=0.120000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=1024731 -pkt_size=N/A +pkt_pos=1024801 +pkt_size=30000 width=100 height=100 pix_fmt=rgb24 @@ -532,6 +532,7 @@ start_time=0.000000 duration_ts=N/A duration=N/A bit_rate=705600 +max_bit_rate=N/A nb_frames=N/A nb_read_frames=6 nb_read_packets=6 @@ -551,6 +552,7 @@ attached_pic=0 [streams.stream.0.tags] E=mc² +encoder=Lavc pcm_s16le [streams.stream.1] index=1 @@ -567,6 +569,8 @@ sample_aspect_ratio=1\:1 display_aspect_ratio=4\:3 pix_fmt=rgb24 level=-99 +color_range=N/A +color_space=unknown timecode=N/A id=N/A r_frame_rate=25/1 @@ -577,6 +581,7 @@ start_time=0.000000 duration_ts=N/A duration=N/A bit_rate=N/A +max_bit_rate=N/A nb_frames=N/A nb_read_frames=4 nb_read_packets=4 @@ -597,6 +602,7 @@ attached_pic=0 [streams.stream.1.tags] title=foobar duration_ts=field-and-tags-conflict-attempt +encoder=Lavc rawvideo [streams.stream.2] index=2 @@ -613,6 +619,8 @@ sample_aspect_ratio=1\:1 display_aspect_ratio=1\:1 pix_fmt=rgb24 level=-99 +color_range=N/A +color_space=unknown timecode=N/A id=N/A r_frame_rate=25/1 @@ -623,6 +631,7 @@ start_time=0.000000 duration_ts=N/A duration=N/A bit_rate=N/A +max_bit_rate=N/A nb_frames=N/A nb_read_frames=4 nb_read_packets=4 @@ -640,6 +649,9 @@ visual_impaired=0 clean_effects=0 attached_pic=0 +[streams.stream.2.tags] +encoder=Lavc rawvideo + [format] filename=tests/data/ffprobe-test.nut nb_streams=3 @@ -647,8 +659,8 @@ nb_programs=0 format_name=nut start_time=0.000000 duration=0.120000 -size=1054812 -bit_rate=70320800 +size=1054882 +bit_rate=70325466 probe_score=100 [format.tags] diff --git a/tests/ref/fate/ffprobe_json b/tests/ref/fate/ffprobe_json index 12bd1a292..29e8fe08a 100644 --- a/tests/ref/fate/ffprobe_json +++ b/tests/ref/fate/ffprobe_json @@ -11,7 +11,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "572", + "pos": "642", "flags": "K" }, { @@ -26,7 +26,7 @@ "best_effort_timestamp_time": "0.000000", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "572", + "pkt_pos": "642", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -43,7 +43,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "230400", - "pos": "2647", + "pos": "2717", "flags": "K" }, { @@ -58,7 +58,8 @@ "best_effort_timestamp_time": "0.000000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "2647", + "pkt_pos": "2717", + "pkt_size": "230400", "width": 320, "height": 240, "pix_fmt": "rgb24", @@ -81,7 +82,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "30000", - "pos": "233068", + "pos": "233138", "flags": "K" }, { @@ -96,7 +97,8 @@ "best_effort_timestamp_time": "0.000000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "233068", + "pkt_pos": "233138", + "pkt_size": "30000", "width": 100, "height": 100, "pix_fmt": "rgb24", @@ -119,7 +121,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "263073", + "pos": "263143", "flags": "K" }, { @@ -134,7 +136,7 @@ "best_effort_timestamp_time": "0.023220", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "263073", + "pkt_pos": "263143", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -151,7 +153,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "230400", - "pos": "265151", + "pos": "265221", "flags": "K" }, { @@ -166,7 +168,8 @@ "best_effort_timestamp_time": "0.040000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "265151", + "pkt_pos": "265221", + "pkt_size": "230400", "width": 320, "height": 240, "pix_fmt": "rgb24", @@ -189,7 +192,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "30000", - "pos": "495575", + "pos": "495645", "flags": "K" }, { @@ -204,7 +207,8 @@ "best_effort_timestamp_time": "0.040000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "495575", + "pkt_pos": "495645", + "pkt_size": "30000", "width": 100, "height": 100, "pix_fmt": "rgb24", @@ -227,7 +231,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "525580", + "pos": "525650", "flags": "K" }, { @@ -242,7 +246,7 @@ "best_effort_timestamp_time": "0.046440", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "525580", + "pkt_pos": "525650", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -259,7 +263,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "527651", + "pos": "527721", "flags": "K" }, { @@ -274,7 +278,7 @@ "best_effort_timestamp_time": "0.069660", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "527651", + "pkt_pos": "527721", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -291,7 +295,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "230400", - "pos": "529729", + "pos": "529799", "flags": "K" }, { @@ -306,7 +310,8 @@ "best_effort_timestamp_time": "0.080000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "529729", + "pkt_pos": "529799", + "pkt_size": "230400", "width": 320, "height": 240, "pix_fmt": "rgb24", @@ -329,7 +334,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "30000", - "pos": "760153", + "pos": "760223", "flags": "K" }, { @@ -344,7 +349,8 @@ "best_effort_timestamp_time": "0.080000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "760153", + "pkt_pos": "760223", + "pkt_size": "30000", "width": 100, "height": 100, "pix_fmt": "rgb24", @@ -367,7 +373,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "790158", + "pos": "790228", "flags": "K" }, { @@ -382,7 +388,7 @@ "best_effort_timestamp_time": "0.092880", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "790158", + "pkt_pos": "790228", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -399,7 +405,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "792229", + "pos": "792299", "flags": "K" }, { @@ -414,7 +420,7 @@ "best_effort_timestamp_time": "0.116100", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "792229", + "pkt_pos": "792299", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -431,7 +437,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "230400", - "pos": "794307", + "pos": "794377", "flags": "K" }, { @@ -446,7 +452,8 @@ "best_effort_timestamp_time": "0.120000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "794307", + "pkt_pos": "794377", + "pkt_size": "230400", "width": 320, "height": 240, "pix_fmt": "rgb24", @@ -469,7 +476,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "30000", - "pos": "1024731", + "pos": "1024801", "flags": "K" }, { @@ -484,7 +491,8 @@ "best_effort_timestamp_time": "0.120000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "1024731", + "pkt_pos": "1024801", + "pkt_size": "30000", "width": 100, "height": 100, "pix_fmt": "rgb24", @@ -531,7 +539,8 @@ "attached_pic": 0 }, "tags": { - "E": "mc²" + "E": "mc²", + "encoder": "Lavc pcm_s16le" } }, { @@ -570,7 +579,8 @@ }, "tags": { "title": "foobar", - "duration_ts": "field-and-tags-conflict-attempt" + "duration_ts": "field-and-tags-conflict-attempt", + "encoder": "Lavc rawvideo" } }, { @@ -606,6 +616,9 @@ "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0 + }, + "tags": { + "encoder": "Lavc rawvideo" } } ], @@ -616,8 +629,8 @@ "format_name": "nut", "start_time": "0.000000", "duration": "0.120000", - "size": "1054812", - "bit_rate": "70320800", + "size": "1054882", + "bit_rate": "70325466", "probe_score": 100, "tags": { "title": "ffprobe test file", diff --git a/tests/ref/fate/ffprobe_xml b/tests/ref/fate/ffprobe_xml index 1da25d74c..90353c4f9 100644 --- a/tests/ref/fate/ffprobe_xml +++ b/tests/ref/fate/ffprobe_xml @@ -1,52 +1,55 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/tests/ref/fate/fic-avi b/tests/ref/fate/fic-avi new file mode 100644 index 000000000..cc4ea5dfc --- /dev/null +++ b/tests/ref/fate/fic-avi @@ -0,0 +1,122 @@ +#tb 0: 1/60 +0, 0, 0, 1, 1566720, 0x7dae32e0 +0, 1, 1, 1, 1566720, 0x7dae32e0 +0, 2, 2, 1, 1566720, 0x6d1a9dc8 +0, 3, 3, 1, 1566720, 0x6d1a9dc8 +0, 4, 4, 1, 1566720, 0x6d1a9dc8 +0, 5, 5, 1, 1566720, 0x6d1a9dc8 +0, 6, 6, 1, 1566720, 0x6d1a9dc8 +0, 7, 7, 1, 1566720, 0x6d1a9dc8 +0, 8, 8, 1, 1566720, 0xa0e89cb5 +0, 9, 9, 1, 1566720, 0xa0e89cb5 +0, 10, 10, 1, 1566720, 0xa0e89cb5 +0, 11, 11, 1, 1566720, 0xa0e89cb5 +0, 12, 12, 1, 1566720, 0xa0e89cb5 +0, 13, 13, 1, 1566720, 0xa0e89cb5 +0, 14, 14, 1, 1566720, 0xb2b6e548 +0, 15, 15, 1, 1566720, 0xb2b6e548 +0, 16, 16, 1, 1566720, 0xb2b6e548 +0, 17, 17, 1, 1566720, 0xb2b6e548 +0, 18, 18, 1, 1566720, 0xb2b6e548 +0, 19, 19, 1, 1566720, 0xb2b6e548 +0, 20, 20, 1, 1566720, 0xb2b6e548 +0, 21, 21, 1, 1566720, 0xb2b6e548 +0, 22, 22, 1, 1566720, 0xb2b6e548 +0, 23, 23, 1, 1566720, 0xb2b6e548 +0, 24, 24, 1, 1566720, 0xb2b6e548 +0, 25, 25, 1, 1566720, 0xb2b6e548 +0, 26, 26, 1, 1566720, 0xb2b6e548 +0, 27, 27, 1, 1566720, 0xcb708c8f +0, 28, 28, 1, 1566720, 0xcb708c8f +0, 29, 29, 1, 1566720, 0x8655dc40 +0, 30, 30, 1, 1566720, 0x72e7f3cc +0, 31, 31, 1, 1566720, 0x7961f524 +0, 32, 32, 1, 1566720, 0xf267e79b +0, 33, 33, 1, 1566720, 0xf267e79b +0, 34, 34, 1, 1566720, 0x132df3a2 +0, 35, 35, 1, 1566720, 0x132df3a2 +0, 36, 36, 1, 1566720, 0x132df3a2 +0, 37, 37, 1, 1566720, 0x132df3a2 +0, 38, 38, 1, 1566720, 0x132df3a2 +0, 39, 39, 1, 1566720, 0x132df3a2 +0, 40, 40, 1, 1566720, 0x132df3a2 +0, 41, 41, 1, 1566720, 0x132df3a2 +0, 42, 42, 1, 1566720, 0x132df3a2 +0, 43, 43, 1, 1566720, 0x132df3a2 +0, 44, 44, 1, 1566720, 0x132df3a2 +0, 45, 45, 1, 1566720, 0x132df3a2 +0, 46, 46, 1, 1566720, 0x132df3a2 +0, 47, 47, 1, 1566720, 0x132df3a2 +0, 48, 48, 1, 1566720, 0x132df3a2 +0, 49, 49, 1, 1566720, 0x132df3a2 +0, 50, 50, 1, 1566720, 0x132df3a2 +0, 51, 51, 1, 1566720, 0x132df3a2 +0, 52, 52, 1, 1566720, 0x132df3a2 +0, 53, 53, 1, 1566720, 0x132df3a2 +0, 54, 54, 1, 1566720, 0x132df3a2 +0, 55, 55, 1, 1566720, 0x132df3a2 +0, 56, 56, 1, 1566720, 0x132df3a2 +0, 57, 57, 1, 1566720, 0x132df3a2 +0, 58, 58, 1, 1566720, 0x132df3a2 +0, 59, 59, 1, 1566720, 0x132df3a2 +0, 60, 60, 1, 1566720, 0x40f7d39a +0, 61, 61, 1, 1566720, 0x40f7d39a +0, 62, 62, 1, 1566720, 0x40f7d39a +0, 63, 63, 1, 1566720, 0x40f7d39a +0, 64, 64, 1, 1566720, 0x40f7d39a +0, 65, 65, 1, 1566720, 0x40f7d39a +0, 66, 66, 1, 1566720, 0x40f7d39a +0, 67, 67, 1, 1566720, 0x40f7d39a +0, 68, 68, 1, 1566720, 0x40f7d39a +0, 69, 69, 1, 1566720, 0x40f7d39a +0, 70, 70, 1, 1566720, 0x40f7d39a +0, 71, 71, 1, 1566720, 0x40f7d39a +0, 72, 72, 1, 1566720, 0x40f7d39a +0, 73, 73, 1, 1566720, 0xa7d6e25f +0, 74, 74, 1, 1566720, 0xa7d6e25f +0, 75, 75, 1, 1566720, 0xa7d6e25f +0, 76, 76, 1, 1566720, 0xa7d6e25f +0, 77, 77, 1, 1566720, 0xa7d6e25f +0, 78, 78, 1, 1566720, 0xa7d6e25f +0, 79, 79, 1, 1566720, 0xa7d6e25f +0, 80, 80, 1, 1566720, 0xa7d6e25f +0, 81, 81, 1, 1566720, 0xa7d6e25f +0, 82, 82, 1, 1566720, 0xa7d6e25f +0, 83, 83, 1, 1566720, 0xa7d6e25f +0, 84, 84, 1, 1566720, 0xa7d6e25f +0, 85, 85, 1, 1566720, 0xa7d6e25f +0, 86, 86, 1, 1566720, 0xa7d6e25f +0, 87, 87, 1, 1566720, 0xa7d6e25f +0, 88, 88, 1, 1566720, 0xa7d6e25f +0, 89, 89, 1, 1566720, 0xa7d6e25f +0, 90, 90, 1, 1566720, 0xa7d6e25f +0, 91, 91, 1, 1566720, 0xa7d6e25f +0, 92, 92, 1, 1566720, 0xa7d6e25f +0, 93, 93, 1, 1566720, 0xa7d6e25f +0, 94, 94, 1, 1566720, 0xa7d6e25f +0, 95, 95, 1, 1566720, 0xa7d6e25f +0, 96, 96, 1, 1566720, 0xa7d6e25f +0, 97, 97, 1, 1566720, 0xa7d6e25f +0, 98, 98, 1, 1566720, 0xa7d6e25f +0, 99, 99, 1, 1566720, 0xa7d6e25f +0, 100, 100, 1, 1566720, 0xeaf8d207 +0, 101, 101, 1, 1566720, 0x6724983e +0, 102, 102, 1, 1566720, 0x0e95d209 +0, 103, 103, 1, 1566720, 0x0e95d209 +0, 104, 104, 1, 1566720, 0x0e95d209 +0, 105, 105, 1, 1566720, 0x0e95d209 +0, 106, 106, 1, 1566720, 0x0e95d209 +0, 107, 107, 1, 1566720, 0xfe83b964 +0, 108, 108, 1, 1566720, 0xfe83b964 +0, 109, 109, 1, 1566720, 0xfe83b964 +0, 110, 110, 1, 1566720, 0xfe83b964 +0, 111, 111, 1, 1566720, 0xfe83b964 +0, 112, 112, 1, 1566720, 0xfe83b964 +0, 113, 113, 1, 1566720, 0xfe83b964 +0, 114, 114, 1, 1566720, 0xfe83b964 +0, 115, 115, 1, 1566720, 0xfe83b964 +0, 116, 116, 1, 1566720, 0xfe83b964 +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-colormatrix1 b/tests/ref/fate/filter-colormatrix1 index 9ec093d90..265f956d9 100644 --- a/tests/ref/fate/filter-colormatrix1 +++ b/tests/ref/fate/filter-colormatrix1 @@ -1 +1 @@ -colormatrix1 600fef16b66cff4ee76540ff2a8f4480 +colormatrix1 a5a26833c0feec3220af855ed36987b0 diff --git a/tests/ref/fate/filter-colormatrix2 b/tests/ref/fate/filter-colormatrix2 index 9961bae4e..4e96587e7 100644 --- a/tests/ref/fate/filter-colormatrix2 +++ b/tests/ref/fate/filter-colormatrix2 @@ -1 +1 @@ -colormatrix2 e4ba95b7dd5e0862aa5f5e3ddc54bda4 +colormatrix2 2c81a2a1bfcba0768e00f0fc5ab7bf5a diff --git a/tests/ref/fate/filter-crop b/tests/ref/fate/filter-crop index dec7f29a8..0295d8df5 100644 --- a/tests/ref/fate/filter-crop +++ b/tests/ref/fate/filter-crop @@ -1 +1 @@ -crop f7b5236ddf88224188051c7c43503a14 +crop 75217686e926f7541a200ecf88aa2c12 diff --git a/tests/ref/fate/filter-crop_scale b/tests/ref/fate/filter-crop_scale index e692a8a1a..4658df4fc 100644 --- a/tests/ref/fate/filter-crop_scale +++ b/tests/ref/fate/filter-crop_scale @@ -1 +1 @@ -crop_scale c298d61e731a97d0a9600e7fde80b6b4 +crop_scale 3aac5217ef443c41ad850959d9c5da6c diff --git a/tests/ref/fate/filter-crop_scale_vflip b/tests/ref/fate/filter-crop_scale_vflip index 9a7d326b7..2afa7b667 100644 --- a/tests/ref/fate/filter-crop_scale_vflip +++ b/tests/ref/fate/filter-crop_scale_vflip @@ -1 +1 @@ -crop_scale_vflip 56b8204e72d0680b139a8d9dd756e332 +crop_scale_vflip 368e9ce823b95ab344bd90fc4d0288b8 diff --git a/tests/ref/fate/filter-crop_vflip b/tests/ref/fate/filter-crop_vflip index d6d6bade6..e13ed4bb1 100644 --- a/tests/ref/fate/filter-crop_vflip +++ b/tests/ref/fate/filter-crop_vflip @@ -1 +1 @@ -crop_vflip 8368eb12fa29acc5826bade961257375 +crop_vflip 23f6190695a24f9d98ba6143623cccd6 diff --git a/tests/ref/fate/filter-edgedetect b/tests/ref/fate/filter-edgedetect index 5044eed0f..fb2a9173f 100644 --- a/tests/ref/fate/filter-edgedetect +++ b/tests/ref/fate/filter-edgedetect @@ -1 +1 @@ -edgedetect 9d67cf98d604f5dbde6f20a88664c683 +edgedetect bcbaea799d3585c4235fc342ecd3591d diff --git a/tests/ref/fate/filter-edgedetect-colormix b/tests/ref/fate/filter-edgedetect-colormix new file mode 100644 index 000000000..f6f9b87a4 --- /dev/null +++ b/tests/ref/fate/filter-edgedetect-colormix @@ -0,0 +1 @@ +edgedetect-colormix 7a25ca606e18344ab4d82382b787e4da diff --git a/tests/ref/fate/filter-hq2x b/tests/ref/fate/filter-hq2x new file mode 100644 index 000000000..dcf2a291c --- /dev/null +++ b/tests/ref/fate/filter-hq2x @@ -0,0 +1,3 @@ +#tb 0: 1/25 +0, 0, 0, 1, 877072, 0x9369339e +0, 1, 1, 1, 877072, 0x32d119a1 diff --git a/tests/ref/fate/filter-hq3x b/tests/ref/fate/filter-hq3x new file mode 100644 index 000000000..82153881d --- /dev/null +++ b/tests/ref/fate/filter-hq3x @@ -0,0 +1,3 @@ +#tb 0: 1/25 +0, 0, 0, 1, 1973412, 0xafc227fa +0, 1, 1, 1, 1973412, 0x93aebf19 diff --git a/tests/ref/fate/filter-hq4x b/tests/ref/fate/filter-hq4x new file mode 100644 index 000000000..c1d6fd8fa --- /dev/null +++ b/tests/ref/fate/filter-hq4x @@ -0,0 +1,3 @@ +#tb 0: 1/25 +0, 0, 0, 1, 3508288, 0x034ef75e +0, 1, 1, 1, 3508288, 0x738e9bbb diff --git a/tests/ref/fate/filter-hue b/tests/ref/fate/filter-hue index ab412a74a..527b202b5 100644 --- a/tests/ref/fate/filter-hue +++ b/tests/ref/fate/filter-hue @@ -1 +1 @@ -hue faddb090f2eefa663b9539fd67451352 +hue 2c8a14eff52333355f59f81fab43aedf diff --git a/tests/ref/fate/filter-idet b/tests/ref/fate/filter-idet index 2c6c2ae66..f1396c533 100644 --- a/tests/ref/fate/filter-idet +++ b/tests/ref/fate/filter-idet @@ -1 +1 @@ -idet 1077e3cb6fc4916b5441dd08cea4c9a8 +idet 1790336872e844c867a53150b8ee8810 diff --git a/tests/ref/fate/filter-null b/tests/ref/fate/filter-null index 0b9b9b86a..b59e1c158 100644 --- a/tests/ref/fate/filter-null +++ b/tests/ref/fate/filter-null @@ -1 +1 @@ -null 61fffd2d8425759a33ae07e718d0242d +null 005e6ddc8a5daf11cf866a1ec76c2572 diff --git a/tests/ref/fate/filter-pad b/tests/ref/fate/filter-pad index 7a6f61e4e..07d2a0792 100644 --- a/tests/ref/fate/filter-pad +++ b/tests/ref/fate/filter-pad @@ -1 +1 @@ -pad 8122d716097523d0875e2d55b0926105 +pad 91fb048d7b2b4b4b5b6b3a46e6240adf diff --git a/tests/ref/fate/filter-pixdesc b/tests/ref/fate/filter-pixdesc index e7a5bc102..cfa17544e 100644 --- a/tests/ref/fate/filter-pixdesc +++ b/tests/ref/fate/filter-pixdesc @@ -1,115 +1,118 @@ -0bgr 2b46a6ce47a19ffc240e4e93f498f491 -0rgb e90e5d377a3e5af69fdf7b60cbf88f51 -abgr 1a147fa04ed70b9a7e67a4c89052f630 -argb 997df0b5c268a0d8f9c611cae4e01e05 -bgr0 b61591a68252e66c576b9bb074a9eaed -bgr24 d6370f6dc34df2ea66e1718baf74137b -bgr444be aba6dfea008ae12c2120a95f54293904 -bgr444le cfb5401e8f076cc8675e17ed1114a3df -bgr48be ab65229b64606f6408cd732b967c0b01 -bgr48le f1b4e718cadee9bd2978289153ce43de -bgr4_byte de96505ef9ad7078f87b4dfdf6fe4b61 -bgr555be 8d5de9e9200d622f27dc73958a85045c -bgr555le 74eb9837706143a40e26305a16a79369 -bgr565be 13a36d6502be88fc0c2aec05b8d2d501 -bgr565le ed027571692aecd522aa65a90cc7e09b -bgr8 71ef789609c746c2e7e4be9dec29062c -bgra 0364b074268682ea46168742a8239f7d -gbrap 412a2449fdfaeb5ebdf5e4196cc7391a -gbrp 4778f8cc2bdbcd65e272ea1761cdca6d -gbrp10be 0be11fe4b2324054be6f949e81966691 -gbrp10le 173f89ae58fd4d01d6a365318e4da3b1 -gbrp12be 1f5231ed7e4589a3ec98fa79134bdc6a -gbrp12le cc4830a263fecadeea535c4938b5cee1 -gbrp14be 6f5143374536e1cf1595260e91c86b7b -gbrp14le 937ff1dd9f498b39f9e882316e371fbf -gbrp9be c76ab5850c9bc72bbbf36caa6d1c5ac7 -gbrp9le 5ad363dc9570187ad3e3f2344fbb30cf -gray 2ee2ea2340d0ecf2dfa6f90f87384799 -gray16be a61507aec1088f5692036e1aabdb4f41 -gray16le 171fbdd46e3737bc865d0185a0006e1c -monob 309b5785a36bd988d17e15d88f4ffad1 -monow 8809a02bc69b58d1114b09ca79ebffad -nv12 75e90c54d858b993e99f4ee6d2a2a38f -nv21 8831a3f411015d45fbc5dd191245ba9c -rgb0 5774780b3c532896300fa326fcde01a8 -rgb24 c71ba90f69f15c8275232bb3f62d0ced -rgb444be 26eaec65d7efd2b0c9c13b47dfd9b241 -rgb444le 5f29863553107110ea817f52151d77b7 -rgb48be a3bc81c46c21818a989f23104a599ab0 -rgb48le e87c661ac49aea1f1e93939802883d92 -rgb4_byte 293b1b84f01efd90bde40cb3faffc127 -rgb555be 5229183fa64d4e5c7e3703d8263ee6ae -rgb555le c3e9978cb2a4129a5575935e8cbc433a -rgb565be bc123b962629ead1a06af0c18cbb6e5f -rgb565le 20757fafe4756e62d845b2ab4c0b8f93 -rgb8 e01614f5416dcc8ad365ad7a57afc9fb -rgba 53796fa4c392a1b2659595b6a284f8c4 -rgba64be c05fbb1ada1b48fb1eb192fc200af2b6 -rgba64le 1b826cc613666f545274e8a7799d69f1 -uyvy422 3f411f947e3ac8f842c88e717d68bd9a -xyz12be 7fb449368615139d47192c4543b5d125 -xyz12le bfa1cde86dece70348e48f6293a7c2ef -yuv410p 7dcf3f4770c8b494290ceacd2c2ce6db -yuv411p 9461b188dab6f8b90d9a27e353a89f58 -yuv420p 61fffd2d8425759a33ae07e718d0242d -yuv420p10be 2abf90242cb021cb6fcf9f2c3c92f6a7 -yuv420p10le 180b7e4de684c7225d2fb37614f842cb -yuv420p12be 256c9e6cfc878a8abf681b30777c0620 -yuv420p12le 8dc8b86c4790da3769d4a62e87608623 -yuv420p14be 8d22756c5d2b9e501924c082bfb22a6c -yuv420p14le c9da19d4818bcb119ad6481b75778f7e -yuv420p16be 4ccdcca6dd6a960f9a3333f0aee095bd -yuv420p16le 9c5847d9b0de258a10ee906dc47e24ea -yuv420p9be fa7ad4f73232aac0e35def62af1e2c39 -yuv420p9le 3720ba1786b56c8f4913e67dddebbb07 -yuv422p eee223e92f1f2e5ad4186b411ebf5816 -yuv422p10be 80fa87750491dcc3e93d175b64835654 -yuv422p10le e1640cd315bd96c6b59f7753825a7306 -yuv422p12be 5c6d86e919515d1af71f8004a6252f9e -yuv422p12le 7f331cadb0ab75d07656d29f47bd8bd9 -yuv422p14be 4f4e186ba683b90fe990cccc4db7e521 -yuv422p14le d78016c9119b1f1d1c922bd5aaf47732 -yuv422p16be 1f3c216927d17966a009a42def124bba -yuv422p16le 90adbdffaeea9b09398339c8a1322b02 -yuv422p9be e46446534dd0821029d3b831c9c1d1b0 -yuv422p9le 520e418a2429f7efee511b7fcbf45ab6 -yuv440p 456d83524b299f2fa1bb988e421554d9 -yuv444p 068bc09d282d18c9fa35c2787943fc2a -yuv444p10be 9f6e1490080a454243daee9229425e1e -yuv444p10le cc183e51041351d9ac06c4df6e8ad5f7 -yuv444p12be 34f63ac6a47ac681016105d3bfb3e118 -yuv444p12le 7964701bfe8d718edf97f6e0002935bd -yuv444p14be 4ad3a9d52fe9c050150c0f7d2f3cf63d -yuv444p14le 69575e5a94b978f159c4fdb1a61587b0 -yuv444p16be 4000b12fa88ed0feef182da31c7e6b96 -yuv444p16le 96a857dba8dc6792c58daec872825b32 -yuv444p9be 07727e5c9040b7f0a17d591288ac330d -yuv444p9le 4d12d20a68dc28618594c96c2ade4ff4 -yuva420p 3a8c5c142e051367c196f95696e0e2c3 -yuva420p10be 1b7c5ec6691498e24676ce6ed97f62f8 -yuva420p10le 4c13322bca914df2727da91cca85ca1a -yuva420p16be 6afcf758f4b66c0b4173c942d42212d7 -yuva420p16le 13e195aa96329eb49921b6f9f07b875c -yuva420p9be 05a78390de312dfd21ac666a9da05fbd -yuva420p9le 78f5593bf51a31841ef83df41d0316eb -yuva422p 45ae66d6f69fd5b77e6831e98d228bf4 -yuva422p10be 18284c58b926fe2389605c692a703145 -yuva422p10le b934d28b615729a24bebf0381c465e37 -yuva422p16be c3f7354b6013b43439e02aa02be5fe69 -yuva422p16le a7ccc43820683ab15061d14cf8efce6c -yuva422p9be 14c55a16d19499b54b4341f135d3e558 -yuva422p9le a8bf168e5d2709222192d0aff46b1373 -yuva444p 86b05da54db8c7e8cf5b6638e19c6fc5 -yuva444p10be 8c417158165c00fbd42def60cbc27d69 -yuva444p10le 5f303ef3fb56faed69b4cc1c760ac6ae -yuva444p16be 52a9591ec0d5059e49b1b2803f8582aa -yuva444p16le a9272ac197e4a4195662ce90f533976c -yuva444p9be f72f646ef07cdab613420585aba041ac -yuva444p9le 6d431b0a27bf4f86ea44ef5f14247a01 -yuvj411p 037accc8e48ac9928a580cddf444f129 -yuvj420p 73661456012f20cda81207b14bb0c0a5 -yuvj422p aa97862b57f47c5a6506156e9aaf129a -yuvj440p ff8b9884a49d546b035f5d2ac1e673df -yuvj444p b8142888d80b8065c54045839e79b331 -yuyv422 f06a4fbbdb32807d05de825daa2c3a1b +0bgr 567bba091d0c8148a892b826c52d1e73 +0rgb 81f013e1d0da78e347aac45e57007187 +abgr 0d93666da1532ca69c1a3e2ee0248430 +argb 86f5041b9245930bc6977d4f2babf74d +bgr0 5f7fdabb606edcd0db80684da021f6c9 +bgr24 fd0c957cabb399b3dda29e1190e6cfac +bgr444be 96d828ff1ea24858100e0afcef6f6201 +bgr444le 5a43d10a7890378368073be08141f967 +bgr48be 65986a0555423c910db4820732565a5e +bgr48le 3050e56ee66fa61d8dd88b12f4b2f956 +bgr4_byte 6d8ea0cb6b4cadace60222063a847630 +bgr555be 90ffbd6a7850f25253977aecf84e229e +bgr555le 9f800958e9c238c9441fef9799ab2a8d +bgr565be 0e7c46857a3bebc2e3bb77ae68cc0bad +bgr565le 31c0b9b6bc009a4bfa4421c3bbb2ff39 +bgr8 775803c35cf19b2fc84f537ce5a7e262 +bgra 020a3623e3ad6ea398d6adfcba9e510c +bgra64be ce8e864307b8f11d1bc4a92f3384416b +bgra64le fa2e6435c1f7f498d5714898e120dd89 +gbrap dcf43e62881e69a873382c12d3afe0a4 +gbrp 78a26e285e0f6ee73f37d70621e659fe +gbrp10be d325f4f209bf460f8ff7d37bc51978dd +gbrp10le c2328ae0384eeb34b1ac83726b385f46 +gbrp12be 8aa22995644b2796ecafc10dec5f3bd8 +gbrp12le df4badcfdf6701e03809ef5a278297b8 +gbrp14be a02a13caee9af458c5039c697ab896a6 +gbrp14le 4f521b6e69078bd0eca8dfcfde0f6ef6 +gbrp9be 397280799d9e78f48670664491e62524 +gbrp9le dbf020fa8423e170f2624ddba9f2c945 +gray 19ae78946e6acc3b552daa61b44a8ca1 +gray16be 2665aebcabc71b30a2252308b1335a81 +gray16le f35d7d9b8cac96c5ac25c2cd4b42443b +monob d2b84b01179f38ce59a7050064d42289 +monow 550a446b7900a42990d76befca7f08a0 +nv12 18aaac3efcb2e389bfa2ade34b917634 +nv21 cb3b54dcc21c72943d496e6368b0c00b +rgb0 62028885ff1adc3368c378748a80be71 +rgb24 273cfae99e5951d567f230beec3e3eeb +rgb444be d90556c864a78c45ca9e2c27130067cd +rgb444le fe271368f267be87eb8f5b46335ba6dc +rgb48be 434c2ce989de629050e53e820b6929b6 +rgb48le e04c4a36ea9f9c5624ebd56463b593fe +rgb4_byte 77c49fda8c97ffc25678d8a51f7056ca +rgb555be cb820a51149ba9944480bad7e1260abc +rgb555le dc18e2fec8f39ebfd5b479fa6c5fe717 +rgb565be 0a7a10645295397cd6cbd6eadce71c8e +rgb565le 7454e27a0e2c2c37c67e5361a82dd445 +rgb8 7b602ac8a68dd95ad639f741be805a0d +rgba 283a6115965814470d50f11bf197c5fe +rgba64be a00ce626e8c94dcc2ebd7b95d7a7d43b +rgba64le 50932da874a5063a595a9428edb187fe +uyvy422 2d479ff414d1c94bf506e48c86f66a02 +xyz12be ff515a5c7277e411c0bf3c8f26d02de8 +xyz12le 63f383905675fd3306a329eb89d6d0f8 +yuv410p 242e22aa812c1db8bff7f8132fb1f6da +yuv411p 9305f8baa6ab955566fbee34391734b3 +yuv420p 005e6ddc8a5daf11cf866a1ec76c2572 +yuv420p10be ac1b6e1050f39464703e78a2ffc1913a +yuv420p10le 5c158075ae335e6bbf4cd3be29bbb62a +yuv420p12be 6a53755f72b37b2a264387dd5604b431 +yuv420p12le 174eb0b1aa668d517c13d6e397577cf9 +yuv420p14be ea8399e9ef8b6aa033ad2f5d6dca0473 +yuv420p14le a63fb4dfb6a7db44a5fd7f35d39d9032 +yuv420p16be fa7a59892b9d15f6e41c24e5f348f303 +yuv420p16le 5b75c822b20189bb0859b05bcf241aec +yuv420p9be d5dabd911d09c9e8fa01fe284dcfd4d6 +yuv420p9le eb1f57241a76ae5d65228adb3aede871 +yuv422p 5afc9b0f6c5cef4a7d0543c03d0fc8a4 +yuv422p10be b83a73824cf37922faa84227ca151b83 +yuv422p10le 64e51f718442560814e74dd1e01d6c94 +yuv422p12be 460ce0ef46387d0ee667664e72dfe6d0 +yuv422p12le 687856619666bc8f8bc6a8e91f7c4e95 +yuv422p14be 461184df05416126fec7c5d2fbad3876 +yuv422p14le e180b189ef2f8448c681d02b478e56cd +yuv422p16be 332fba636d33aea23514392d80602a96 +yuv422p16le 5d8e26fbbc8f25576065106c8820d56a +yuv422p9be e3b364350da35d2ffd431665ed9d3592 +yuv422p9le 0f21976b77781cada504f690d7dc6c15 +yuv440p e6754959dfd9631f2dc1682fa71aa4e0 +yuv444p db3ad634aea336663a2f5c2475b95410 +yuv444p10be e341efd871b34308831113f4b2ff29f9 +yuv444p10le f9666d63623e0d7dceda1a17202579cf +yuv444p12be 151c0e12d45ddf475a293cf9eee4c224 +yuv444p12le e0da5848e54c3ba0dbfa0414ff4a47f3 +yuv444p14be 83d2420dc82158274425c6ea5e396dbf +yuv444p14le 155753892ad8a8957df50033fd21fecb +yuv444p16be 6bb40952bd87aaaf2938cfadd1017a79 +yuv444p16le 9be8c3ca67cb8a778d39c087f008d8c0 +yuv444p9be 5a54227a9e1e12fd297e36e1e9361c52 +yuv444p9le faeeb7f3ff5efc51975d48d49f4ced5d +yuva420p 7b609ede889454d2b89b184c290e9e32 +yuva420p10be 4a0ab3165ccc5cde5f4ef9c27e8ccf82 +yuva420p10le 8fbcc6200060e0710e5a824b86c9c219 +yuva420p16be d149e664c8fce03192d78279472ae2c3 +yuva420p16le 11b9f6b757f98fd4a442983bca8945b1 +yuva420p9be 0aae288a080fb0acfac23610b2d30111 +yuva420p9le fb67be28488cb722d4aea6fe3fdaaa16 +yuva422p 88c582f7c6d7c123198fb707aad2d5b0 +yuva422p10be 465ec369d7e47a71976821fdc31c289c +yuva422p10le 07df8a8fcb3081e89d84359b178d5260 +yuva422p16be 0144a6783d7728a0e66d2b6d1134ecec +yuva422p16le 5b49f7e660c77bafcb03869ea2e1ce02 +yuva422p9be 923a2d718c2dcf62c4c9b573a56f15ad +yuva422p9le 9188e6cef21e89d034d37da1b1702a7d +yuva444p f89cdb4fea764921004e149358d7028a +yuva444p10be 87b0f4d461c40bde0cc85b109103d016 +yuva444p10le 5aed7ca68d5645a3a9acbe14b8eca54f +yuva444p16be 5701a24fa4153d45be9533d7ec00b660 +yuva444p16le c3092fc38248cf96e30dce70208ed360 +yuva444p9be 8ab557ee81eae76cd176d998078d671d +yuva444p9le b599165331bd7fa6b05dbf7b80044856 +yuvj411p ffb1370ebb9e1bb3b7dd4a532fe8eaeb +yuvj420p aaddf557fa39c3b9521bc6afabbc18e6 +yuvj422p 4f46f78ace9176a534aea861ac316441 +yuvj440p d8083286cf699e81113fc8ea04ba3c35 +yuvj444p cad8f07876e62d33caf6c420d0f67a56 +yuyv422 ad9bf7f09f4f8263131649407a778e7b +yvyu422 59f91e478f573d8a305e11da12a87be3 diff --git a/tests/ref/fate/filter-pixfmts-copy b/tests/ref/fate/filter-pixfmts-copy index ac0485781..a42173442 100644 --- a/tests/ref/fate/filter-pixfmts-copy +++ b/tests/ref/fate/filter-pixfmts-copy @@ -1,116 +1,119 @@ -0bgr a06d3a7652e4885c65895e0e168aab28 -0rgb b6b5653d2228cdf2ba3c55a72f2e713f -abgr 1a147fa04ed70b9a7e67a4c89052f630 -argb 997df0b5c268a0d8f9c611cae4e01e05 -bgr0 218df6dc3eb5094a0c16a8bd18bc3999 -bgr24 d6370f6dc34df2ea66e1718baf74137b -bgr444be aba6dfea008ae12c2120a95f54293904 -bgr444le cfb5401e8f076cc8675e17ed1114a3df -bgr48be ab65229b64606f6408cd732b967c0b01 -bgr48le f1b4e718cadee9bd2978289153ce43de -bgr4_byte de96505ef9ad7078f87b4dfdf6fe4b61 -bgr555be 8d5de9e9200d622f27dc73958a85045c -bgr555le 74eb9837706143a40e26305a16a79369 -bgr565be 13a36d6502be88fc0c2aec05b8d2d501 -bgr565le ed027571692aecd522aa65a90cc7e09b -bgr8 71ef789609c746c2e7e4be9dec29062c -bgra 0364b074268682ea46168742a8239f7d -gbrap 412a2449fdfaeb5ebdf5e4196cc7391a -gbrp 4778f8cc2bdbcd65e272ea1761cdca6d -gbrp10be 0be11fe4b2324054be6f949e81966691 -gbrp10le 173f89ae58fd4d01d6a365318e4da3b1 -gbrp12be 1f5231ed7e4589a3ec98fa79134bdc6a -gbrp12le cc4830a263fecadeea535c4938b5cee1 -gbrp14be 6f5143374536e1cf1595260e91c86b7b -gbrp14le 937ff1dd9f498b39f9e882316e371fbf -gbrp9be c76ab5850c9bc72bbbf36caa6d1c5ac7 -gbrp9le 5ad363dc9570187ad3e3f2344fbb30cf -gray 2ee2ea2340d0ecf2dfa6f90f87384799 -gray16be a61507aec1088f5692036e1aabdb4f41 -gray16le 171fbdd46e3737bc865d0185a0006e1c -monob 309b5785a36bd988d17e15d88f4ffad1 -monow 8809a02bc69b58d1114b09ca79ebffad -nv12 75e90c54d858b993e99f4ee6d2a2a38f -nv21 8831a3f411015d45fbc5dd191245ba9c -pal8 13de2a1c3c80cb64d14e2bc4f6f461d0 -rgb0 992f5ad24802cc255edab45c3084db4a -rgb24 c71ba90f69f15c8275232bb3f62d0ced -rgb444be 26eaec65d7efd2b0c9c13b47dfd9b241 -rgb444le 5f29863553107110ea817f52151d77b7 -rgb48be a3bc81c46c21818a989f23104a599ab0 -rgb48le e87c661ac49aea1f1e93939802883d92 -rgb4_byte 293b1b84f01efd90bde40cb3faffc127 -rgb555be 5229183fa64d4e5c7e3703d8263ee6ae -rgb555le c3e9978cb2a4129a5575935e8cbc433a -rgb565be bc123b962629ead1a06af0c18cbb6e5f -rgb565le 20757fafe4756e62d845b2ab4c0b8f93 -rgb8 e01614f5416dcc8ad365ad7a57afc9fb -rgba 53796fa4c392a1b2659595b6a284f8c4 -rgba64be c05fbb1ada1b48fb1eb192fc200af2b6 -rgba64le 1b826cc613666f545274e8a7799d69f1 -uyvy422 3f411f947e3ac8f842c88e717d68bd9a -xyz12be 7fb449368615139d47192c4543b5d125 -xyz12le bfa1cde86dece70348e48f6293a7c2ef -yuv410p 7dcf3f4770c8b494290ceacd2c2ce6db -yuv411p 9461b188dab6f8b90d9a27e353a89f58 -yuv420p 61fffd2d8425759a33ae07e718d0242d -yuv420p10be 2abf90242cb021cb6fcf9f2c3c92f6a7 -yuv420p10le 180b7e4de684c7225d2fb37614f842cb -yuv420p12be 256c9e6cfc878a8abf681b30777c0620 -yuv420p12le 8dc8b86c4790da3769d4a62e87608623 -yuv420p14be 8d22756c5d2b9e501924c082bfb22a6c -yuv420p14le c9da19d4818bcb119ad6481b75778f7e -yuv420p16be 4ccdcca6dd6a960f9a3333f0aee095bd -yuv420p16le 9c5847d9b0de258a10ee906dc47e24ea -yuv420p9be fa7ad4f73232aac0e35def62af1e2c39 -yuv420p9le 3720ba1786b56c8f4913e67dddebbb07 -yuv422p eee223e92f1f2e5ad4186b411ebf5816 -yuv422p10be 80fa87750491dcc3e93d175b64835654 -yuv422p10le e1640cd315bd96c6b59f7753825a7306 -yuv422p12be 5c6d86e919515d1af71f8004a6252f9e -yuv422p12le 7f331cadb0ab75d07656d29f47bd8bd9 -yuv422p14be 4f4e186ba683b90fe990cccc4db7e521 -yuv422p14le d78016c9119b1f1d1c922bd5aaf47732 -yuv422p16be 1f3c216927d17966a009a42def124bba -yuv422p16le 90adbdffaeea9b09398339c8a1322b02 -yuv422p9be e46446534dd0821029d3b831c9c1d1b0 -yuv422p9le 520e418a2429f7efee511b7fcbf45ab6 -yuv440p 456d83524b299f2fa1bb988e421554d9 -yuv444p 068bc09d282d18c9fa35c2787943fc2a -yuv444p10be 9f6e1490080a454243daee9229425e1e -yuv444p10le cc183e51041351d9ac06c4df6e8ad5f7 -yuv444p12be 34f63ac6a47ac681016105d3bfb3e118 -yuv444p12le 7964701bfe8d718edf97f6e0002935bd -yuv444p14be 4ad3a9d52fe9c050150c0f7d2f3cf63d -yuv444p14le 69575e5a94b978f159c4fdb1a61587b0 -yuv444p16be 4000b12fa88ed0feef182da31c7e6b96 -yuv444p16le 96a857dba8dc6792c58daec872825b32 -yuv444p9be 07727e5c9040b7f0a17d591288ac330d -yuv444p9le 4d12d20a68dc28618594c96c2ade4ff4 -yuva420p 3a8c5c142e051367c196f95696e0e2c3 -yuva420p10be 1b7c5ec6691498e24676ce6ed97f62f8 -yuva420p10le 4c13322bca914df2727da91cca85ca1a -yuva420p16be 6afcf758f4b66c0b4173c942d42212d7 -yuva420p16le 13e195aa96329eb49921b6f9f07b875c -yuva420p9be 05a78390de312dfd21ac666a9da05fbd -yuva420p9le 78f5593bf51a31841ef83df41d0316eb -yuva422p 45ae66d6f69fd5b77e6831e98d228bf4 -yuva422p10be 18284c58b926fe2389605c692a703145 -yuva422p10le b934d28b615729a24bebf0381c465e37 -yuva422p16be c3f7354b6013b43439e02aa02be5fe69 -yuva422p16le a7ccc43820683ab15061d14cf8efce6c -yuva422p9be 14c55a16d19499b54b4341f135d3e558 -yuva422p9le a8bf168e5d2709222192d0aff46b1373 -yuva444p 86b05da54db8c7e8cf5b6638e19c6fc5 -yuva444p10be 8c417158165c00fbd42def60cbc27d69 -yuva444p10le 5f303ef3fb56faed69b4cc1c760ac6ae -yuva444p16be 52a9591ec0d5059e49b1b2803f8582aa -yuva444p16le a9272ac197e4a4195662ce90f533976c -yuva444p9be f72f646ef07cdab613420585aba041ac -yuva444p9le 6d431b0a27bf4f86ea44ef5f14247a01 -yuvj411p 037accc8e48ac9928a580cddf444f129 -yuvj420p 73661456012f20cda81207b14bb0c0a5 -yuvj422p aa97862b57f47c5a6506156e9aaf129a -yuvj440p ff8b9884a49d546b035f5d2ac1e673df -yuvj444p b8142888d80b8065c54045839e79b331 -yuyv422 f06a4fbbdb32807d05de825daa2c3a1b +0bgr 7211d3bdeafda12a27b6c586f56369e8 +0rgb dc534ffbcf7b02007a245e6af5bc0bf7 +abgr 0d93666da1532ca69c1a3e2ee0248430 +argb 86f5041b9245930bc6977d4f2babf74d +bgr0 914c5750b13f79908c23d2621bc5d171 +bgr24 fd0c957cabb399b3dda29e1190e6cfac +bgr444be 96d828ff1ea24858100e0afcef6f6201 +bgr444le 5a43d10a7890378368073be08141f967 +bgr48be 65986a0555423c910db4820732565a5e +bgr48le 3050e56ee66fa61d8dd88b12f4b2f956 +bgr4_byte 6d8ea0cb6b4cadace60222063a847630 +bgr555be 90ffbd6a7850f25253977aecf84e229e +bgr555le 9f800958e9c238c9441fef9799ab2a8d +bgr565be 0e7c46857a3bebc2e3bb77ae68cc0bad +bgr565le 31c0b9b6bc009a4bfa4421c3bbb2ff39 +bgr8 775803c35cf19b2fc84f537ce5a7e262 +bgra 020a3623e3ad6ea398d6adfcba9e510c +bgra64be ce8e864307b8f11d1bc4a92f3384416b +bgra64le fa2e6435c1f7f498d5714898e120dd89 +gbrap dcf43e62881e69a873382c12d3afe0a4 +gbrp 78a26e285e0f6ee73f37d70621e659fe +gbrp10be d325f4f209bf460f8ff7d37bc51978dd +gbrp10le c2328ae0384eeb34b1ac83726b385f46 +gbrp12be 8aa22995644b2796ecafc10dec5f3bd8 +gbrp12le df4badcfdf6701e03809ef5a278297b8 +gbrp14be a02a13caee9af458c5039c697ab896a6 +gbrp14le 4f521b6e69078bd0eca8dfcfde0f6ef6 +gbrp9be 397280799d9e78f48670664491e62524 +gbrp9le dbf020fa8423e170f2624ddba9f2c945 +gray 19ae78946e6acc3b552daa61b44a8ca1 +gray16be 2665aebcabc71b30a2252308b1335a81 +gray16le f35d7d9b8cac96c5ac25c2cd4b42443b +monob d2b84b01179f38ce59a7050064d42289 +monow 550a446b7900a42990d76befca7f08a0 +nv12 18aaac3efcb2e389bfa2ade34b917634 +nv21 cb3b54dcc21c72943d496e6368b0c00b +pal8 5ad4084b953f16007faf99f366b2ecae +rgb0 1cb89a77512524197ae6495dc7206a7b +rgb24 273cfae99e5951d567f230beec3e3eeb +rgb444be d90556c864a78c45ca9e2c27130067cd +rgb444le fe271368f267be87eb8f5b46335ba6dc +rgb48be 434c2ce989de629050e53e820b6929b6 +rgb48le e04c4a36ea9f9c5624ebd56463b593fe +rgb4_byte 77c49fda8c97ffc25678d8a51f7056ca +rgb555be cb820a51149ba9944480bad7e1260abc +rgb555le dc18e2fec8f39ebfd5b479fa6c5fe717 +rgb565be 0a7a10645295397cd6cbd6eadce71c8e +rgb565le 7454e27a0e2c2c37c67e5361a82dd445 +rgb8 7b602ac8a68dd95ad639f741be805a0d +rgba 283a6115965814470d50f11bf197c5fe +rgba64be a00ce626e8c94dcc2ebd7b95d7a7d43b +rgba64le 50932da874a5063a595a9428edb187fe +uyvy422 2d479ff414d1c94bf506e48c86f66a02 +xyz12be ff515a5c7277e411c0bf3c8f26d02de8 +xyz12le 63f383905675fd3306a329eb89d6d0f8 +yuv410p 242e22aa812c1db8bff7f8132fb1f6da +yuv411p 9305f8baa6ab955566fbee34391734b3 +yuv420p 005e6ddc8a5daf11cf866a1ec76c2572 +yuv420p10be ac1b6e1050f39464703e78a2ffc1913a +yuv420p10le 5c158075ae335e6bbf4cd3be29bbb62a +yuv420p12be 6a53755f72b37b2a264387dd5604b431 +yuv420p12le 174eb0b1aa668d517c13d6e397577cf9 +yuv420p14be ea8399e9ef8b6aa033ad2f5d6dca0473 +yuv420p14le a63fb4dfb6a7db44a5fd7f35d39d9032 +yuv420p16be fa7a59892b9d15f6e41c24e5f348f303 +yuv420p16le 5b75c822b20189bb0859b05bcf241aec +yuv420p9be d5dabd911d09c9e8fa01fe284dcfd4d6 +yuv420p9le eb1f57241a76ae5d65228adb3aede871 +yuv422p 5afc9b0f6c5cef4a7d0543c03d0fc8a4 +yuv422p10be b83a73824cf37922faa84227ca151b83 +yuv422p10le 64e51f718442560814e74dd1e01d6c94 +yuv422p12be 460ce0ef46387d0ee667664e72dfe6d0 +yuv422p12le 687856619666bc8f8bc6a8e91f7c4e95 +yuv422p14be 461184df05416126fec7c5d2fbad3876 +yuv422p14le e180b189ef2f8448c681d02b478e56cd +yuv422p16be 332fba636d33aea23514392d80602a96 +yuv422p16le 5d8e26fbbc8f25576065106c8820d56a +yuv422p9be e3b364350da35d2ffd431665ed9d3592 +yuv422p9le 0f21976b77781cada504f690d7dc6c15 +yuv440p e6754959dfd9631f2dc1682fa71aa4e0 +yuv444p db3ad634aea336663a2f5c2475b95410 +yuv444p10be e341efd871b34308831113f4b2ff29f9 +yuv444p10le f9666d63623e0d7dceda1a17202579cf +yuv444p12be 151c0e12d45ddf475a293cf9eee4c224 +yuv444p12le e0da5848e54c3ba0dbfa0414ff4a47f3 +yuv444p14be 83d2420dc82158274425c6ea5e396dbf +yuv444p14le 155753892ad8a8957df50033fd21fecb +yuv444p16be 6bb40952bd87aaaf2938cfadd1017a79 +yuv444p16le 9be8c3ca67cb8a778d39c087f008d8c0 +yuv444p9be 5a54227a9e1e12fd297e36e1e9361c52 +yuv444p9le faeeb7f3ff5efc51975d48d49f4ced5d +yuva420p 7b609ede889454d2b89b184c290e9e32 +yuva420p10be 4a0ab3165ccc5cde5f4ef9c27e8ccf82 +yuva420p10le 8fbcc6200060e0710e5a824b86c9c219 +yuva420p16be d149e664c8fce03192d78279472ae2c3 +yuva420p16le 11b9f6b757f98fd4a442983bca8945b1 +yuva420p9be 0aae288a080fb0acfac23610b2d30111 +yuva420p9le fb67be28488cb722d4aea6fe3fdaaa16 +yuva422p 88c582f7c6d7c123198fb707aad2d5b0 +yuva422p10be 465ec369d7e47a71976821fdc31c289c +yuva422p10le 07df8a8fcb3081e89d84359b178d5260 +yuva422p16be 0144a6783d7728a0e66d2b6d1134ecec +yuva422p16le 5b49f7e660c77bafcb03869ea2e1ce02 +yuva422p9be 923a2d718c2dcf62c4c9b573a56f15ad +yuva422p9le 9188e6cef21e89d034d37da1b1702a7d +yuva444p f89cdb4fea764921004e149358d7028a +yuva444p10be 87b0f4d461c40bde0cc85b109103d016 +yuva444p10le 5aed7ca68d5645a3a9acbe14b8eca54f +yuva444p16be 5701a24fa4153d45be9533d7ec00b660 +yuva444p16le c3092fc38248cf96e30dce70208ed360 +yuva444p9be 8ab557ee81eae76cd176d998078d671d +yuva444p9le b599165331bd7fa6b05dbf7b80044856 +yuvj411p ffb1370ebb9e1bb3b7dd4a532fe8eaeb +yuvj420p aaddf557fa39c3b9521bc6afabbc18e6 +yuvj422p 4f46f78ace9176a534aea861ac316441 +yuvj440p d8083286cf699e81113fc8ea04ba3c35 +yuvj444p cad8f07876e62d33caf6c420d0f67a56 +yuyv422 ad9bf7f09f4f8263131649407a778e7b +yvyu422 59f91e478f573d8a305e11da12a87be3 diff --git a/tests/ref/fate/filter-pixfmts-crop b/tests/ref/fate/filter-pixfmts-crop index 91875a5a9..f091a0a81 100644 --- a/tests/ref/fate/filter-pixfmts-crop +++ b/tests/ref/fate/filter-pixfmts-crop @@ -1,112 +1,114 @@ -0bgr ba367adf7943b91cf7f98aefe3f7f9ea -0rgb c83c555fe20def126bf1b8967442aa97 -abgr ef31d9057f6e65a7c3308a1b1daa98fa -argb 5e5e261c4870e0de05d56ff640b9550a -bgr0 c8729ca08c5d29ecd5ca21c0ea8c54ce -bgr24 44bec15f35513de7e957b3d59b53cb7b -bgr444be d56f795721020fc7a598e3b07f3fba1e -bgr444le 53224fc7360806c19fbd873e13fd0c68 -bgr48be 0b5ebce3c48eb8614d79e204b5268603 -bgr48le c4ab61a8b9d502132730c6abb6ffd84c -bgr4_byte cab930dbe1fe77d58b41837ecdcb8460 -bgr555be 67162782fdb86813f446d8e1c21c73e9 -bgr555le 85913cfa8dab465f7dcfcfe7f9001a01 -bgr565be ee9a1debb896d41c53a026f9e6ce006b -bgr565le ab7b6055bc3b6b7edc9a5e4de43ec90d -bgr8 f85ff16e21d922ad6d32648ef3acfbfb -bgra 9f2e37d73ad3b759fc9d6b12ee668c38 -gbrap 32c0326859b41ae1fee015648162c6a0 -gbrp 0f59d3a61d391c3dea6f6e5861e9c2f7 -gbrp10be bc12b34950af11e3f1016acbe2d5dec5 -gbrp10le 0ff56c84154050f992fefc357449da9a -gbrp12be b2154eaa6344a37ace82e42b757585e2 -gbrp12le 77956c63e99444fc61c306643acba403 -gbrp14be 3ab29f18610ce10ce2e5c99b1af78415 -gbrp14le d1465f7280f35aa0a70709e5a7bee1a4 -gbrp9be f17b7ba66ba35ed0fcbbb5c32c7e0f56 -gbrp9le fc11219debfbe8dd8c3d6f0ef92c4d50 -gray 6d34024704f862c75db3ba6989a4a039 -gray16be 27cfdb4b211cad34f66a664cabd754b4 -gray16le 91cb081d457100a60c2d0f54110f064f -nv12 923a313a7013fb0e87608155ef6aa9a4 -nv21 21e6b9273bb74203beabeb9edb9cf95c -pal8 e1fd50b8a8a67fb5abd8b44abc778bbb -rgb0 8bd7785a8421b3f60e5eae2d2968a546 -rgb24 d044123f1fe50f656f2101dd3f091ead -rgb444be 6a076e84d0cdbae2ba29412a28587e81 -rgb444le f82d127ca2a40ec822171b79a11df65d -rgb48be ef5507f88948b54218911d12e1dbef36 -rgb48le 6d045d5990d6ada64a112e3b581a7b38 -rgb4_byte 0f0f9ee31c65dc60da49bf98a1b06dcf -rgb555be 48fa619bfd04f6dee05416b02605c031 -rgb555le 292cff1f824e49076bad50a07ab1c749 -rgb565be 0dd6f6a5a8713bd1c3d9826bb7a88eab -rgb565le 6afd85faa8c6f0f330969539178eb9a2 -rgb8 87cf541b110e35a6f9a983e9cde85e15 -rgba 7abe1af7b97f5b9a7aa5ad3e4bf32f76 -rgba64be 2eed28b61af25790c02cc658e5f86b9b -rgba64le de8bc34c6d573488d87e87ce8c7ad07f -xyz12be c3783bcad9f962049f9992d5c907bbf2 -xyz12le 20a9ebf2256ceda449ba5603f1dab7e3 -yuv410p 126e0da1da4fd89be28087b8367bbb36 -yuv411p b94f0af107fc4796aca70c0a36d374c5 -yuv420p 74c6b331bd30f005e6c75a192423ad90 -yuv420p10be 1321772e0586e9b89386e792ed9f5277 -yuv420p10le 726b637741fe28c26d57a1dd814ef14b -yuv420p12be 5c3bf63a61fe41acb958614d4a7c8923 -yuv420p12le 073c6fa32443c1df26243b598fb5a34e -yuv420p14be 9460b8507137516ae437d00380921cb9 -yuv420p14le fd162a79436a9585ed44814fa3dc02fd -yuv420p16be 2d3c84ebff77479e8c5b6e3e59ec4e45 -yuv420p16le e2c906f2751609bf8cbcbeb2f629319a -yuv420p9be d40531645b7ddecf4778f652549c121c -yuv420p9le fbffd583dd189a546cf4df144a735f66 -yuv422p 124bc8d668072de1bb3b894cc4bae859 -yuv422p10be 3d6195bb0c4cc9498ef42227839db9d5 -yuv422p10le d19bdc9ba4e76b38c076ac93e99e6ef4 -yuv422p12be f2c2f23269fa969e3e3f0ba5e065bc98 -yuv422p12le 6d07ba50dcdaf43bd8b73233ed11e4d9 -yuv422p14be 3115c4c01f6a8b9930b32ec8a12f52ac -yuv422p14le 00ba7302e4e4db2c70ba0712f2fc8574 -yuv422p16be 3ec47e2709107fcc388b5e0abebf7eaf -yuv422p16le a4183a62917bf8568fe11ff446dd18f9 -yuv422p9be 05c2d9a95f329133a9fa03c46eaaf0cd -yuv422p9le ea559e7009aef6c36de0daa8061740f7 -yuv440p 15c81c685fa5b9db95150caff14ff83f -yuv444p 12b752f78af72666627cea2d0c274cdb -yuv444p10be 6a5d1574657bdadd435c59227b6772d0 -yuv444p10le cc6e8453e6ffeeca98055722f9833fb0 -yuv444p12be 39086bcf3ad336391c2a378b32d9cd1b -yuv444p12le ccc98011edecb7c643e6250c34ae9b3d -yuv444p14be b05b5999610b1369d0873212543697f8 -yuv444p14le a4ae35bb8a377d593635126671d1af30 -yuv444p16be f2bf0e22a1d184e37eaa199a76cf22ba -yuv444p16le c11b151dced5c8854d385373fa4dcc8f -yuv444p9be 0b4e2a096a7ada2d6fab3f7d5160326c -yuv444p9le 04b00046c0409849f89bca191298257b -yuva420p 920c5d1b965eeb72e3a0e343696face3 -yuva420p10be c2d580dee6da641c176c6357e74d14bd -yuva420p10le 51781f8328a0ad69466e729cfc31bbc6 -yuva420p16be 1855e36526638e5d364b1d29bd49141b -yuva420p16le 2476b93493a30cce3c8fe07ea3ce3761 -yuva420p9be 7c9d877f0c06529d60beb5fcbe5a6f47 -yuva420p9le 392387fc9b414576e003abed4f8bf389 -yuva422p 1bc930cf64afc7cc99362fee5d8e08d8 -yuva422p10be 3382c54dd78aec916210edef29aa268f -yuva422p10le 93862b68e0dc6ea812fa36fbb1641b48 -yuva422p16be a44509ccee5dd71a67f8138a8dca7620 -yuva422p16le 4a0b4f7cb3fda825acd6eeef7efa4aae -yuva422p9be f3d9d423699ccf369b50ea7dfefb16da -yuva422p9le f65115fd89e0cbabc975a15e764b4d30 -yuva444p 1cf9c2dddb0e2f082eca981b2226bdb1 -yuva444p10be e60f55491f67bb69962e4c2a29868da2 -yuva444p10le 6a7a95f6af4ef3ce47e2b20bc2453746 -yuva444p16be 0caa51254006811d244e150fa34f2e90 -yuva444p16le 5f073f7771254bace1d07279c56c9613 -yuva444p9be 3d64778ebee876c77e77066fd57336b9 -yuva444p9le 85a80221022b5de7cb3233845392d8c6 -yuvj411p 55f4d5f22146e7771ec4e5729a438f48 -yuvj420p f9183e49f42bae31d7d85b92161fa82f -yuvj422p aabeed60a6e1b2cf88665ac627bf531f -yuvj440p 5ae4f404b42f3167f978473d9a3737fc -yuvj444p 6728997f65b879fd5a3175cb449a8f0c +0bgr 2dbfe85133679ec33860be0c6209660f +0rgb ca0c4e07d1d385c56ea72382f2ee9540 +abgr d614480ee1b09b22b0b4f64909d95187 +argb 79132bf1dbdbc2b25be4c28b8828c97d +bgr0 29f32318c36b40445e98954c53ad5fb0 +bgr24 f6f04b3110f2cecd06719fb38965e0dc +bgr444be 95bd8c3e75963f49c447b7273484bc73 +bgr444le 2c9cd030b8865bdf7d402ffc70e2a72b +bgr48be 19aae8f9550d354d718d107a44ac837e +bgr48le 338b82f7b4aac5d517a8a8b2396d78d0 +bgr4_byte 6ef669512505c87d9155848cde78094b +bgr555be 2328e1ebdcc5a675d16409ad94e670f1 +bgr555le b7cbc03dd251298e07fd436ce26271a0 +bgr565be 282650e0b2dc125776a1f6ee8df80cea +bgr565le 3414ba2c28368f39c6e3e52933d51994 +bgr8 ea3c3e7390bff85f70d8e3a59ddced70 +bgra b8bd94fa3040d24cba2c42f94475dbde +bgra64be ec9acb7200a2fcc36d0068585b5e44ca +bgra64le 367049173354f78f9198567d672fbad8 +gbrap 0f62b82e45c6a41e16e15b1f220edacf +gbrp cf6e1617315229a93d4775dcecc3060b +gbrp10be 66e216886535254f85f95d958da447b1 +gbrp10le c4184848c40d8ac1b35efdc438629038 +gbrp12be b74a3b1085ceb7297df79d83e9f0620c +gbrp12le 7a18358bd4b1b2cd2462252022e689da +gbrp14be 09139a87b1bbf3a6aea23e60af322de1 +gbrp14le 885c5014c6314d5689974f45e3761db4 +gbrp9be aa505e48a02e7ca696aafa383311e73f +gbrp9le 3ca0021fbcf8f64605d75c93bd25c9e8 +gray fcdefb797cd029045b14087dd32864df +gray16be 98923eb3c74084b4e5df109c7ed7d5bd +gray16le 5c90c5415f66b8515a1dff86cd57968c +nv12 d92caeeb7a3957ed03db73cbe1238269 +nv21 88575d9d13287e3e494aca95d7658316 +pal8 d8fd9dc03d11c2359422520eaba5c3f8 +rgb0 5ce99f382ae88184b9420b3d12d3b61b +rgb24 2927da0677191eb732927e2ae7a6de49 +rgb444be b4b2edd542bc206ffdc37e43df6dc230 +rgb444le 03df3d8eb5007993d6c532e69a13d978 +rgb48be 511ca3199940d39e3c71640922c2e34c +rgb48le 5026a5cd5c377ed7a39c1a7711a93b80 +rgb4_byte 1aa5e401fbfc91898908bf5524680085 +rgb555be 3f2940a75e77ed606025832c44e0364e +rgb555le 7727c0b88bad1275560816345a41a458 +rgb565be ea41d5778aaa9d771aa3ed732d508ea1 +rgb565le a0ff4142dd837bbfc9ca8ebf0f817028 +rgb8 0c68336442a457e0ecc01af4fe283592 +rgba 1a7347d049f523fdb377d24c209110d1 +rgba64be f0e885fd18aaf45220bdde36df95a172 +rgba64le 7f043d06074c8ac573936df9ea497bf8 +xyz12be 4cb9f4b47d02089b824c7471b24589a6 +xyz12le 1000d2cd841586430c844e3b254a4b7f +yuv410p 27b126789bb0fa0171d67e4bff86057a +yuv411p 0d0d234e2f4417554bfa5c62c2aeee7b +yuv420p 5683e1fe2c3125f140d9dfb025ff4a3a +yuv420p10be 82459e6203ec39c21dfef93ccdb03f97 +yuv420p10le ea104a93f1798a8b7d48a7583077dc46 +yuv420p12be ca90b12e6a67f5470dc7272a6c5af2ba +yuv420p12le 72786a5c34eac7ebd26baa75ff764573 +yuv420p14be 5e085866453f846ac5b41d0045c46371 +yuv420p14le 6825f0f1876303de8576e5203930f49d +yuv420p16be caada8eed18c9b1a3765789412261fea +yuv420p16le 04c49d9a9c6c6d8388a80a037ee124b9 +yuv420p9be 512093cac681bc30a4fe832d149b195e +yuv420p9le 3b77b2c993d19a81a529b5feb661ab04 +yuv422p b0c57e1847ccefade6214359dbba389a +yuv422p10be 36fa87316dc861d0ca28faeb83595a92 +yuv422p10le fa668d15ddfd94d46f4db8a68ee8eb2c +yuv422p12be 1abe2eea053f807702e22c1b2f75a233 +yuv422p12le 44ee5fac430c99cb9f931af7b09e3419 +yuv422p14be 0ee2568ece15da65d2ce21783f2ef9f2 +yuv422p14le 1f04c8f882ad9051fb6464c14f61e78c +yuv422p16be 6350e88697371cb3ba550bfc3d8a4d05 +yuv422p16le 5420bd643996c2fc10709ca58a0323e9 +yuv422p9be 0cf0d2f092b01b86cb8883e5b9ee70fd +yuv422p9le caa7eabbc6cc12b91314d5a03857c3d9 +yuv440p 54ee388cdaf8b1fe88b78348913b18b0 +yuv444p 434403ed452af56f5bc6e96863eaca97 +yuv444p10be d7ef21572858c0071b5c74281ed8cb1b +yuv444p10le 3c293e9a0aacd45fbcf9b6568cddcb4f +yuv444p12be 143a391a1a5722bfb476724c8cb2dd5c +yuv444p12le 570ff3794e15763dd53f54d2eaaee05f +yuv444p14be b3ac16add13002a5cca2668d19a3aebd +yuv444p14le 44eaf3ba7020d3cfb4ab7251dd0343b6 +yuv444p16be 795c309ec568cd4eb9b9cd97fb928dd1 +yuv444p16le 0ff751ac170c039e5c2cea00e9065df2 +yuv444p9be 7e90f7c4008d785c25f5e9379aa20541 +yuv444p9le 1bf226c716813e713f247eb39fdbac31 +yuva420p b805f9fad9e670fb87c2fa254db8a776 +yuva420p10be 9e5118ff02c71aee492948bdaf2ef116 +yuva420p10le 682b1220ef7495e6a70c2c69923416be +yuva420p16be bed3c6cac6f188f7f0b388beeba144f8 +yuva420p16le ac2dbb6a9e3ef79782eca4d7885e5e70 +yuva420p9be ddc6a2ba66a42b2e2d8e9a75e0426073 +yuva420p9le 15d9d336ea76798159309eaf8a81f71b +yuva422p 1f5e5be0a81413ff624e2da3c9b5ff0b +yuva422p10be 27a3bc7e422483ccc84f4ce7afe7fa36 +yuva422p10le 6a5185cf6f174f33577ca44d69f42a39 +yuva422p16be 9f77ac57d045130d4402e52cb5c6fa5f +yuva422p16le efd4b506ad2851c5d11f403f5f79b833 +yuva422p9be a0013b146490bd943c5f989a138c5e2d +yuva422p9le 5440db83cee16f6f1b49130fee76b65a +yuva444p 79c57d621f664142101bf88c3d947776 +yuva444p10be 784547c017774839255831836c3f41cc +yuva444p10le c528063241ed798bbbb1ce9001691519 +yuva444p16be a8d8b0620b92c4dee0385f52d34d401e +yuva444p16le e1f9622ba10c0cf1ca8d8aefe80ad272 +yuva444p9be 1df34b1a5b7ac4d6fb087728a7d2eb0b +yuva444p9le 8471a740d2d7af99802539fdda5297c2 +yuvj411p 71449a14b9528bae023a46f1b23e4cf9 +yuvj420p 1d0b465815230b10ebbf6a7de4475230 +yuvj422p 58815ae40359ca3f0023e724eecf4896 +yuvj440p 4dcc9e6e899b17c5d910ec4d4f265828 +yuvj444p 1387fffb3b61d6dcb6e845fd50ecc667 diff --git a/tests/ref/fate/filter-pixfmts-field b/tests/ref/fate/filter-pixfmts-field index ea3c954bb..4023d1859 100644 --- a/tests/ref/fate/filter-pixfmts-field +++ b/tests/ref/fate/filter-pixfmts-field @@ -1,116 +1,119 @@ -0bgr 57434af4bddb691877f2400c704604eb -0rgb fc2ba950163aeee98590181e31fcd202 -abgr 3c78d0a72484a1ecd3cae245b9fa988c -argb d5057a2be412864719ffb8ba129c1f2c -bgr0 b33c6b58b0d7bf6ce07d5a2d7c267040 -bgr24 bd6620738df19410d5df5f31e7451709 -bgr444be 219e318b7e0e05050181e71df6b9539d -bgr444le 8354f2cf5b30de0233d302a74816649d -bgr48be 22be50bd0aa39f07ad1b1aa57cb741ce -bgr48le c4b0f8057b3eac237e9228e83bdc4c66 -bgr4_byte d4c3304b4b823a130c335379e4d3444d -bgr555be c3072da465233dbfc8f61dc7a9766d2c -bgr555le be83adcf0b802b061442f0c564fd5987 -bgr565be bf955b9a035af0e613cf1de249f55f9d -bgr565le 6dd85cd5e19266c53a54cbcf06d396a7 -bgr8 9669f6974f0fc1c0afa1c7d4df093c0b -bgra f7cabae31dd7465dab2203f45db646f8 -gbrap fdb15f25cd6db3d19a7df727e0f4de3a -gbrp 0867ccbcdf50a02871ad7788e3e0931e -gbrp10be c452475d38b13a4707634eff74001215 -gbrp10le 009a9f7ba2ac9a8c67269bf3a76581c5 -gbrp12be e1e01fbefb6ab400a7eb460aa9ad6acd -gbrp12le cf2fd4db9e69d82acb0aedfc094ebc9a -gbrp14be 52ce4bffdd04a2f51ab2d3ae4e78dfa5 -gbrp14le 775b50257b848007c4ef3441ba772db1 -gbrp9be c293422f1395bfddc788282eef139ed6 -gbrp9le 0d2bb77c25d84611ec6222f3dffe11c0 -gray 42a0ad7625a0481183e375e38679d8d3 -gray16be e10bc0a8b015fdb0776eca402ffe5eff -gray16le 2eb159fb4af25c3b4f033e6414fef63e -monob 1b7fb7e69a913a0a1c0dffc54e5899ea -monow b5d3778a054fc73d515d36f8a6bc693b -nv12 b3829e9ae2a15349432b7efac4236068 -nv21 963cf5780e07301ff2906bf345b6d0ff -pal8 bfedafc3bf19c2c12eeb87125833142a -rgb0 d7481143742ff68abfbac4195edbede0 -rgb24 908d5494062c617bc87149c9daaf2167 -rgb444be 281a8f186a2726c2b31aa7e09e21c865 -rgb444le 93f9ee6265d8ad5e744ab652563f9b78 -rgb48be 0d1d60e1639edb2758ad776cb5583970 -rgb48le c958b5e98324263e97de2bb528f5bda4 -rgb4_byte 2ec97bf65649e3d47eb6812701544593 -rgb555be 21b9138b229d4065b02d38b5b62f18d1 -rgb555le 0307ee34e562b2fb2b1c6988ae18b2b2 -rgb565be e8f3ebcbb9a5fff000eca8a312f89782 -rgb565le 53bbd558fb0dcd82f1fad83ea855c3ad -rgb8 67bfdd4fa88b1ab9be876f42dfc75683 -rgba d0ebdf1495bc6b7e9d3bfbe2813a9d16 -rgba64be 53363baf266592e0ac02b3f8242ec4fb -rgba64le a630eaa38545b2be741f000ab58451e5 -uyvy422 a6a52504a16f09b8f2ec2405bc8190b5 -xyz12be 98775fdf313afa1c20da37b74b57c926 -xyz12le 39edc4f30363a00401a62acd7a65e173 -yuv410p 3feb55b1e2a385b488c82e808a12587b -yuv411p ab3dd8e6cf1452afe2d2e976e4726370 -yuv420p 52e26ad198368e2326bef97cdfa6a2bb -yuv420p10be 04353bfc21e9b88cd7776e83be756742 -yuv420p10le 3f8e7167dbd12976c6ee516b8c952363 -yuv420p12be b058ac076c8a5fe522b9fd9b8422054e -yuv420p12le ad0bf28e69eeb14eac5d8f9ea8b801f1 -yuv420p14be c7a435d42f07928332ecb21a7d96ad7a -yuv420p14le 5507e8db4e58c9517012686a7408996b -yuv420p16be 5241d64e9fa2fd6590fd23ea0e8a6f90 -yuv420p16le 78da606f761a4fb62fdac05aa5092742 -yuv420p9be e4bcaf5d6a7030f950b08501327f6175 -yuv420p9le bbf80e57389578be66d4a7a12335a613 -yuv422p e461a21995da361b88202339a2ebb879 -yuv422p10be a3e13070215f5a016ac9bae7e7115417 -yuv422p10le 8e9e3d9adc8fdb8a0a03d79bdc31eefe -yuv422p12be 6a2aca2ea007534e729203641a82c3a3 -yuv422p12le aef072b55c6e9df8fd9f398d79f864df -yuv422p14be 34e5f31372c0fdb4d77ccb7fd7bddb2f -yuv422p14le c2c50fbea0cff7edad5c5e907380cbad -yuv422p16be 55cfed8fa610f82b6625e16871dab235 -yuv422p16le e2488df0f22987fe7ed12a5ef2adf835 -yuv422p9be 80fcdd7fd9cdd79632104dcc32f78b4b -yuv422p9le e0ec9f94c875297ee5d0546274df40e9 -yuv440p f8e80596babcdb94378ec8bebf2dd46d -yuv444p 572bad9e12ed53e242658fa613412279 -yuv444p10be c5304f086afc4624d4fffb66a3cf3cb8 -yuv444p10le d1754974b936f74028752d49413d30aa -yuv444p12be 7ec8fd2d7986d6e923dfed572589e643 -yuv444p12le 79d0e287e2171a53cf4f285c0d1e83ef -yuv444p14be be021957cd819ca3146f3247138ccae9 -yuv444p14le bac0b0c70bcf72272d724f0cd1ac411e -yuv444p16be 3a67c28325978db734ba03b1828c15da -yuv444p16le c6dc275a4277fd3c65535253bb298263 -yuv444p9be f47357cdd775fc399aeab3ae58712fb9 -yuv444p9le e29799ecb6fac9f5b6d85bc34d248d4b -yuva420p 82ab09bb7a3a24bf95aeb3fa9d939847 -yuva420p10be f4559039e99ecf74a58e7063b1e7c5d3 -yuva420p10le 32b3858b01be5bfe2579dadd1be3ab12 -yuva420p16be c580495d34c6ac6e3e3b81772a0f3070 -yuva420p16le 1c49deeafb8f81e9186f3906c9b1a670 -yuva420p9be a788d7cc6ad67ad52619a08da126569a -yuva420p9le c1579a5c015908f26b76480d82f6a648 -yuva422p c162b37ce05360c47b2a2224ea0748ad -yuva422p10be b7c0adc12a8602ab8b40b611785cc18c -yuva422p10le 97f91d820f8ba642a3f9ae0901d03826 -yuva422p16be 1c61492076be33404894c1d3ec578d87 -yuva422p16le 1c085c9479a57eea35e74c264c947d73 -yuva422p9be 271c6cc091052731373ef5313bc76435 -yuva422p9le b8c2e963ac35371e8aa6a05d5c252b37 -yuva444p 4a85f1f17e95829cd53c9a28928fd8eb -yuva444p10be 04c1026f4328ebf24bd7906291b33464 -yuva444p10le 3e8ea3b211bd7ac99cb96ebf71d0e75a -yuva444p16be ac5c17adeb0ef6730a0de1dbd1d14a1a -yuva444p16le 41f1a82eb686d7191bdb00206f723247 -yuva444p9be 413d01385a8b008031b2ab3ef0b9eff4 -yuva444p9le 33ede0bd20bfd85489d266ac81d035d6 -yuvj411p dbcc5e7ef64335ad30b8b9717bfa63d9 -yuvj420p 762dc6a157d0bee72da3e3d852668aef -yuvj422p 8cec955c1c62b00b6798361ef82962b7 -yuvj440p 7b469444994d8b52766ee461bcb795ea -yuvj444p b395162325af489c465a3e6a31fbb0e7 -yuyv422 1efb17cd0a48d2e956fd574ea6f412e7 +0bgr da40e8ccfd148cf8eaebf7586132d045 +0rgb e247794e532df9e2c70938acc7159812 +abgr 778f96e971a11a4d33db88d9359cf835 +argb 51cef8b83532ff5803413d8264312426 +bgr0 e22ddfc7d7f420955315dbccc19c6f88 +bgr24 bb505cc8b02aabe37ee68e2391fce435 +bgr444be 259ced749e1d94eadf1401d4d1cd92cf +bgr444le 77346fad55a531016553ab6a41203c23 +bgr48be 562116f5ad37cf9a57dc3077276a5c52 +bgr48le 803718e260ff84c8961e2322b0aa77c4 +bgr4_byte c2363d641e39a3b3529c3ff9e625b58d +bgr555be b070a363d939b19ed5e2f8d10935e6df +bgr555le 3c51c7ba5110786bda62b30e94c28d45 +bgr565be b2a3f742b2f4e6d46ec10256537b9f74 +bgr565le 910e1d53030dcb2216e64e63e1683d09 +bgr8 5ae2b998f1ae54a9f1aee8df508fcc16 +bgra 8ec6e2a10c06dea5c83c92316efad900 +bgra64be 5feb3132af84db36b7a2dd99f9185fd2 +bgra64le 77cb5875f094bab68d701d0ebf3902f3 +gbrap a145cc653f0e30df7646c6310a22a270 +gbrp e43a0e1eb1360124f1ef7dc13270767e +gbrp10be 2b94a60221a200c8a017fb13b142306a +gbrp10le b40a0d25fe6695c216e11ffd53f1ef6e +gbrp12be 633ced5d9290577573b3da4b5266dfd7 +gbrp12le d18226724a83b979b41347061ccf8d0c +gbrp14be 3053d53652f6b35a32c53f2d7858215d +gbrp14le 40611b24e43b4f41a14a86501040717c +gbrp9be 50d9e81ff97bfe6dfe21c703d4ec85ba +gbrp9le 33d8622fc0e4244b1c95f14a898e9183 +gray 0ff5c743f41244240c010e39b25a509c +gray16be a35ecebecdb0e4209e38519adad52429 +gray16le 8cf6a024f9bd2034a2ec6ba10eb34ce8 +monob 205fa455f3dbbb46326bc8b93ac1b8b6 +monow 673df03c4dd7371e4e8ddee4fde72691 +nv12 c8bd4d74563cfbe12cea49907d0bbe93 +nv21 75838b092b464f61a1224dba16b6bd28 +pal8 10f7b4ca6b02425dc26809dc1c882b17 +rgb0 90e8bb1e5da4b51d99f28a4573737c0c +rgb24 6073589b0f8498b69955adb2cff5c962 +rgb444be a5020766d8e2b4b02e4f6fb0e4df17eb +rgb444le 812898e56d6a0d939241f9f070a3d05e +rgb48be d66d9652de4104c563e162f5710f551e +rgb48le 5ae3bc8d675d113a85ca4fd8b440e6bc +rgb4_byte aacb867629a017c97269a8739474f5b3 +rgb555be 5fdb26f93e0ccb1bc8d3adcafca53929 +rgb555le 941e33a73b9575ee5a4d037da5d36e86 +rgb565be b43a972ce8b63cee54a398f0b823b310 +rgb565le db624d8125bbbf2711c62b93dbd4cc97 +rgb8 8074e19f6cf4b79e93ba0a5e76e16a21 +rgba 2e855e00c7415f8698f7d332d3ef07c7 +rgba64be 6ca359313c4819215c58137584be9d5c +rgba64le 61586310c6b20e985fda58527c07625e +uyvy422 5091022709f8e2f90d20afada267056b +xyz12be 88f8ba489f0d5d74061508f8b8e5a1e8 +xyz12le b39ce3f7e10f3b8f9c56eb71e48de667 +yuv410p fc15f344ce228b16b6d35ad6668dd6c6 +yuv411p 4763ecedee2d6d951f84e5c84602b64e +yuv420p 8234e4e976b7867eb8fea90d54b08d6d +yuv420p10be b6bae85f66170adffb4939812820c6c9 +yuv420p10le cf714c34cd18d13ab1b348a366d627f2 +yuv420p12be 987c004cf05e500d70823133e30b4101 +yuv420p12le 0c840d9c2456863653332bcf4b764068 +yuv420p14be d3d9d84a772082735940eae6106f1df2 +yuv420p14le 04bcfdcf9ec4d851d4ef7bdd4eae7ec0 +yuv420p16be d84d447fa91aba9368fefab32facb670 +yuv420p16le 9a967ce79ef2b65c05128ca8ce442c3b +yuv420p9be 9f8b1f03b43691e9c9f0f0e6a6cbec94 +yuv420p9le 61897b91251f360c026cf5e1e7de8273 +yuv422p 4ecb3e22f22ce0b7b348ec97ccd4c95f +yuv422p10be a9f828e6c59bb44ea848392e601e74ed +yuv422p10le b90a0531c38a5b3e3cf7f7dccdc3e7ee +yuv422p12be bfc36b487709b2b9964e9ab77c4108e7 +yuv422p12le 2aed4636fbb852272ef4ee62d646b95b +yuv422p14be a8ad6ac7d2b0548f5588cdc90d269893 +yuv422p14le 74abbffdb88ae77b6718987a23cc945a +yuv422p16be 009484dcc7faa2656a3d5049ee1c28ff +yuv422p16le b35565fe10f9a15b71d3706877118d8e +yuv422p9be 41605ec9fb967cc3da4ac88d8c4ca6ba +yuv422p9le 10bf2ae59bb45f5d632afe2fa0788f17 +yuv440p 4558340790744ccad447adcd3c8f041c +yuv444p 018c531ab9b4427f6b3ae863306f7bdf +yuv444p10be d45e1d588191d1e038e88ca3406bfe14 +yuv444p10le 991363b633a740ae2fc48d8cc8bde0b3 +yuv444p12be 106ee7c13eb39c1cf6fac07f0c129e55 +yuv444p12le 964b5dc1055c6faaaff1033791a82859 +yuv444p14be 8d0b2a6c08fb8b62f5ae1745671ef466 +yuv444p14le ba9706bfce142cebf861baa42c609691 +yuv444p16be e894084b5173960f66cdf0be179f8828 +yuv444p16le 34ca4cd51f22eadbb379b116b30e66f8 +yuv444p9be b3715905e1a2b46fa776e2dc6845eae0 +yuv444p9le 0474a78522158eaa049870a84aee9aa3 +yuva420p b3dede844de94db4622f700d8bd43ab3 +yuva420p10be c49dc6be444fda3f719be75125c1af65 +yuva420p10le 8c4cea6082c1566d5240d51eb21b9c21 +yuva420p16be 08347d7eff7b9c0e2e140f7e1ff98392 +yuva420p16le 3d6332129ca396b62fe7013ae60c0ad2 +yuva420p9be 066e66cac039be9c7ea7c4b8e3aeae88 +yuva420p9le c792a6e6ce331f9f2b10c0c6ad944b5d +yuva422p 000da58b14a2a73f2d47267f87581898 +yuva422p10be 782d92de7de5322ff4e950712ec992b2 +yuva422p10le 5c2e0802bb2bfc9e32963d785c3d760f +yuva422p16be c0b197bba30c9a04ebbe09529f996c63 +yuva422p16le f64595d50dc66ce4ef2f8376097561d8 +yuva422p9be 8026e04dcbf11fde5b4236f182dbcaa7 +yuva422p9le 6897400d7317f318f6d14f5488dba413 +yuva444p 152be56f7c6ea8c9ed2c595a84ef9fea +yuva444p10be 6af6c6e15d213c71392bb9871e9eb4b9 +yuva444p10le 3aa47775cc47b2054eb3264a847294f6 +yuva444p16be d7d17d7165a5c8e9bb55f81e3a204d48 +yuva444p16le ee067aaac4fcbb2c2ab728bbeafd6b6f +yuva444p9be 4daf3aeda37b259c63fdea951557786f +yuva444p9le 80fc6a6dacd5b1991b500a9e9c9df7bb +yuvj411p c3b81c898d51924b8864e56ba557e632 +yuvj420p b6d76f36d0014bd00e4a833be0cdfcbe +yuvj422p ba411e3632a9d565b7721233d2c4302c +yuvj440p 7e8f985279ed6e38fee52f06d6648d54 +yuvj444p 4ead7294ec3a6d6a84a208248280acc1 +yuyv422 adfd70357cf0abe7fe6b3139621c9b97 +yvyu422 802a6d0fd0561e872f56d2e25a9a7eca diff --git a/tests/ref/fate/filter-pixfmts-fieldmatch b/tests/ref/fate/filter-pixfmts-fieldmatch new file mode 100644 index 000000000..22d554903 --- /dev/null +++ b/tests/ref/fate/filter-pixfmts-fieldmatch @@ -0,0 +1,5 @@ +yuv410p 08518d1ceaf740696b26eb89325987c1 +yuv411p ca4b3b96c4f487fc293ad8d631f37660 +yuv420p 2069df6ae54ce80f82d591ac753e66cc +yuv422p 7b4fe261becce67a0eeeea0b6886d9f6 +yuv444p 5a0ca602480a00e662017c2ecdfc4e1c diff --git a/tests/ref/fate/filter-pixfmts-fieldorder b/tests/ref/fate/filter-pixfmts-fieldorder index 33bcd8eb7..2f9e29832 100644 --- a/tests/ref/fate/filter-pixfmts-fieldorder +++ b/tests/ref/fate/filter-pixfmts-fieldorder @@ -1,89 +1,92 @@ -0bgr a8559fc1395908cda27a27bf79819d61 -0rgb 704924e65927896b84bd645ca59fb7f2 -abgr f479df06a4b73d348b3af004923d7eb9 -argb c16c9af56802c3b821b30c613c041622 -bgr0 b7ee10fec20508b64dfca22d61533a88 -bgr24 a1c59acf60652578b802e7f6639d1ac5 -bgr444be d41639928d05bdee67fa2a76c7f74533 -bgr444le 45f616b1ec9014f8d618878c4db850c1 -bgr48be 7015ba40d142742e5c6a39113fee58af -bgr48le fd33d4a60a789d170b871784d0859089 -bgr4_byte d1ff07684bc1be194d26cdf598385b8e -bgr555be 2295d642e02f9dcb49c20142bfdd9c1a -bgr555le a95883301ab991a3cf8bb063b7912410 -bgr565be c37ced8fa4951da20831edf9bd46b35c -bgr565le da0ee7f773efa07fdacc62b7deac452b -bgr8 94a043f6d5e01de077a92a9be6f77582 -bgra 02db5e046ced11d3f09d901cae205e2f -gbrap 5317a66b677c943203b2a5e93607dc68 -gbrp b1ffeba90a60e9a23c9f35466c135069 -gbrp10be 07b2842fdf9b92f6cd8e8cf3a8abdfac -gbrp10le 7fa5429bb4bc6f0e1f3c190bc8064b38 -gbrp12be 5ea6cb457c88b4b3d48f6f63b6208828 -gbrp12le f969a3b017a0f46008f81453174f4ecd -gbrp14be b2879b691564f66b88e63efd268de8c5 -gbrp14le 7baa94cd296e6ec8e41446bca95151e4 -gbrp9be a6eb7cde03f19a25bf13627d731a2c9a -gbrp9le 1b6d228b97a370ec76707ed2dcc15a66 -gray 3258910ef8c6f0c4a331368e7af87507 -gray16be 9a4c7e731ce572ad86985b56a653b5c3 -gray16le d10df57cf0de14206c8e354e8f6b732b -rgb0 5f8f8076e2b9a2422cac25a4f0459d79 -rgb24 66ca89ced3ade4c239ad6c5a79a6b8cd -rgb444be 7197a09137ab5630a26226396bb7e313 -rgb444le 2d10d7d2ef4527152a9ba8b2020c8d41 -rgb48be 7aee07b85b137365eb04a7ea4c10dcfe -rgb48le debaa00dfed0234efd1441aea8195026 -rgb4_byte 12d6a5a7ca40c531a4d480546ed766eb -rgb555be 5d36ead35aa8820daab7d84e1ffbb4ac -rgb555le 10f43b4c9b06742abc114f0ff1864111 -rgb565be 998ca430a1173f194d78a92695e097f9 -rgb565le 99be7760861aa9c1d3d743a1ea311689 -rgb8 6303c75883c1e2e7e13644fb5dcd11a7 -rgba af33be882959a2fc963d6e5984d24b6d -rgba64be 9ae73ceaa9d95e7981b4df559b0d3b6d -rgba64le 86997e62f62d2a5351b5ca9c9c93c2d1 -uyvy422 a07829fe630b59855c80d87d0e8f0dbb -xyz12be dcb691784f80fd6b438844e8e30299fd -xyz12le c63cdd81442c37d710da95d9be70a24d -yuv411p 3d3d427999863945aa5ec03edf98c19a -yuv422p 961d8a22bfe8868eb3c743b4241a3c99 -yuv422p10be 845e80406c880f33a384b5ebdd21796d -yuv422p10le 0dbf5d1eb94f10cc4413976fa175fa90 -yuv422p12be 9e96f9324d0a4eac4b45161b02c14209 -yuv422p12le db17368e8cd5409826a088ee26ad2a1b -yuv422p14be e20b379fb17e50f279a5ecd9c895537f -yuv422p14le 9440b0c46dadddc19154054978fce20c -yuv422p16be 09d09b64aa4b6ae8479a833622bf27e8 -yuv422p16le 03dbbf3394ba66cda54ef53772258dae -yuv422p9be 7c59e15cb5e6eac9cd090c6ecab4c6b8 -yuv422p9le 98b6b1fbacdfd4c25dbda89b675b660b -yuv444p 709ffd0e95a9438b14d9ba59c0237a61 -yuv444p10be 5ae7571651faebac6dca2ee4fd24610c -yuv444p10le eb3acb92448d8b0e6f145e9d8af43378 -yuv444p12be df1e9bb90364d874dbac41a8237d6068 -yuv444p12le 7e21d00cb42404df0780317dc135f03d -yuv444p14be 6abf70b4b7ff55552327230e08e3dd52 -yuv444p14le 85597559a748aa5aeed2d7dc49d7f66e -yuv444p16be 2a19a8ca44198d0e90c02fd4db24d0c6 -yuv444p16le 5cb12916afef8c82d1796fdc39b97174 -yuv444p9be fc731b5b0afe0a9de6bd46179c692efa -yuv444p9le 7449c543e528067afed5d3c96f7b8da2 -yuva422p d07e0ed0cb20eee67007b154f02cf37c -yuva422p10be 56bfd0af50b9450f72061c605f6537dd -yuva422p10le bfe1df3aae3e02f0a2ddbd404199e6ac -yuva422p16be db80a2e1ddc93126206ad4864f67b50c -yuva422p16le 847e541568b4bce64f916d42173c93c7 -yuva422p9be 5487d986b52f5744a8adac77e46c08f1 -yuva422p9le 6faa61b431b2e0bd4064e5fcecb7130a -yuva444p 377f65cb10dd8013011e185b6aa66697 -yuva444p10be 5e42b4e4b6b1bfd12aa5869750cd2cce -yuva444p10le c1fddd5f488fd4f8d1e07288f8a49182 -yuva444p16be ba2b267e0cc0c36041f3db4f4072ee9e -yuva444p16le c2cfda36aa173be3a4a5c9a8fd66d8db -yuva444p9be e047805a8f9552a6e0b6d4f772126808 -yuva444p9le 28336905569a55e935d708527a3c9d9d -yuvj411p 09f79c56109a13eefb68ee729d9a624b -yuvj422p 942043a34ac7d0f65edced1f6361259c -yuvj444p 7e4758df8eb9b18ad60e1b69a913f8c8 -yuyv422 6b0c70d5ebf1685857b65456c547ea1c +0bgr 87e4c14d6e3377bae54cb08ee3b527a4 +0rgb 67835d4d5c75f773cf316bf82317f7a9 +abgr 2c35d478cac0fa76e840cd455203f8e8 +argb 7d833ab271baeca42ae82c425d5583a1 +bgr0 3a00a32a238af8b2bfe9ceea3ce5e3a6 +bgr24 f4a6c11d6b49f530f0dfa26196e8cd1b +bgr444be 4c8a1ef65209044402e3fc0a706ab0e7 +bgr444le d62aff0548bd7715c229f37c8f5e2077 +bgr48be 857859896ad2885ce012b1437ee3311e +bgr48le 1a2a9a56bbeaa36493da520e61c9140d +bgr4_byte 47665ea920c2468c250e24579eaec01d +bgr555be 99205a9ce3678daaf552372dcf03678e +bgr555le 05a98219aec9178fdf023578f68597a6 +bgr565be 1cccb7efe4ceb6e15b01d6e091572694 +bgr565le b48ee4ff1d25835c529812b5ce081d2c +bgr8 2e3dec1c1478f205bd263f1d35dbd301 +bgra 736a847ee15006866720df4e8d7cffd0 +bgra64be b1ac6b0ae9fbc1e7485d78d758ae7855 +bgra64le 82017083411b9c78b9de682f95e001a6 +gbrap f5dd667bc2438cb74eb709a4d8c504b4 +gbrp aa6512b64079355b3d6069e8ce257115 +gbrp10be 83f7eb6db542508ab2aa8e4045363498 +gbrp10le d081d44402d3e84a7731a9509e4842d7 +gbrp12be 07549ce0bbfa9d7ebf807925e32cb52c +gbrp12le 723a946919a3a35e6b4a5a6b81affa64 +gbrp14be 904f38b9994d711dabf59edaa3704bd8 +gbrp14le 87935220dedf260e2f26d91304aaeb67 +gbrp9be 0719eee49ac14369e5decccc965d364d +gbrp9le 1663f26a123bfd93a53b83a72853f8fd +gray ca1ae72fd165cb0e793dbf44cd17cb74 +gray16be 5cc58221802f9566613bec7ee27f05be +gray16le ef44719f4375b74a3e562ea0cddc5067 +rgb0 209ccbaf7e193c0d6843fc9c086e0db4 +rgb24 2a9189f9baf29d81371dd73e792fcc1a +rgb444be 3b10f406d79321d77884305cd4026739 +rgb444le ac1b4501e8d5b19e1d51f6948bb109ce +rgb48be 2d443f167878bdd1a93f34d7b01ea766 +rgb48le a2f86eabf14d3b292dd45a060ecdb41c +rgb4_byte 76a55b794d4c652a10a7dba4be89ae33 +rgb555be 983a31785d83f99f32ee6292846cdd9a +rgb555le 9e02ef746849c955ce0dc5c66bf0f77b +rgb565be a47bcfd2efcf1ab824506d0d7952c6ec +rgb565le 18b176356affe3bfec67ec8bf8a63095 +rgb8 6b8a7bb3aa5bbed22b6e7c6b6e566a33 +rgba f216a9c593319dd89d78cdcd97b111a6 +rgba64be a657ad856d26f894ef909f3ac6774079 +rgba64le 700fa5ce375b69fb177da41582e78f60 +uyvy422 a8d8f7f2e799725dad9ab945711bbc84 +xyz12be ccefb77b2fa15dcb925b494a7872cd83 +xyz12le e33e4809336203709b87999ff53a5f1b +yuv411p 63d3858b1ce40c97fe8be19a21886557 +yuv422p 828d0499b48aadfc3d0787eaeec178ae +yuv422p10be 8364845c98449f49feded2c907c26c11 +yuv422p10le 7d64b97a71d6276a44f0a2c0ccb396e4 +yuv422p12be 1f619504129f53a87050443dfd220f29 +yuv422p12le c4597c632fb4dd91af6b3183a569b63d +yuv422p14be 674ee482c19ff53105f9c7ee333a4948 +yuv422p14le b98d87cbdab7456f4e0962c3e7b9a2f1 +yuv422p16be c3e4c5671aae6cbe572995a2a537099f +yuv422p16le 25608d9d2882c24652f4c7277c74b1cf +yuv422p9be 7a3752f28c6e6cc4d3d72a35c57b6da3 +yuv422p9le 377557cf7c12d15d0b0cc4dfaea4d748 +yuv444p a75c960a41e1987fa2b85456411d971f +yuv444p10be a2f74aef9316b56dde187c383cd70273 +yuv444p10le 6ce92cf2129498e049cd41461ad8fc72 +yuv444p12be de3ba0096885b72a50611606265322aa +yuv444p12le 8f6ec998e360298759ec5c4f5788608b +yuv444p14be 6a93535d841807b7f804239a30883e04 +yuv444p14le 4cd381fc8bc7d41debda5ac7aac96117 +yuv444p16be d2bcde1e26bdd53edd9fb6f80418c92c +yuv444p16le db108fcc80db08bf6a3852477c320f39 +yuv444p9be f14a9b7d6265c5bb03e4c908454dc61d +yuv444p9le 7f0fa36975c3935ba83e33cd1076ea55 +yuva422p 0efaf456ea8a75321fb87a7adcf586bc +yuva422p10be a94b98c1cea8c0215c0b27fdc2f66348 +yuva422p10le 2130fd0b256888ea6d235851eba9212f +yuva422p16be d60b712e6ff309606a0a0ba721a93362 +yuva422p16le acdfb43cae949e9cc597f594cbf56170 +yuva422p9be 86f77fe1a26cd223745b86ecd7d3a499 +yuva422p9le ebd5681fc413c2e1cb5612f8a6883aab +yuva444p cf62854472ae46951e74db8b75e760f3 +yuva444p10be 4bc8c4012d17b0821600d90d3d2c1bba +yuva444p10le 8c4347ea6eb51866035b9307bfe552a3 +yuva444p16be b81b586bdddb311933a0c0ab4c468e34 +yuva444p16le 758266b13c9419cf21d704647c44bf07 +yuva444p9be 76cb30498de990bd1f6016ae653033c4 +yuva444p9le 490abec545bbfc8669e24e76412c23d0 +yuvj411p eabc1185ec235305fdbee60d5f9de13e +yuvj422p f290bae9a4a91e42d8c1ad5e4013fca4 +yuvj444p 390ed32d78a59c2fe7303954e198c45c +yuyv422 846de2f21f1433fcd884a210713286ad +yvyu422 75757dbf4a28debe42f44f07f7bbe06c diff --git a/tests/ref/fate/filter-pixfmts-hflip b/tests/ref/fate/filter-pixfmts-hflip index f5ee81fc4..97b41657b 100644 --- a/tests/ref/fate/filter-pixfmts-hflip +++ b/tests/ref/fate/filter-pixfmts-hflip @@ -1,112 +1,114 @@ -0bgr 03d8a8920dbb408218376baee8665649 -0rgb 6ee5f3b85ec38953df0762ddd0bdf561 -abgr 8ab842e280c8b31f66450e8951dfedfa -argb cdb6aa47939d49c0ff72537bfc8c82e0 -bgr0 1b0b59382ddbbf045be6b160b7df5881 -bgr24 5b64fd60e2050946b50da1f4945127fb -bgr444be b52c1b9d9dc02cb46c04e80d97139e60 -bgr444le 48172797fa65a25c0ad30ddc7e8f5bcb -bgr48be 58e292c33eb60708171c3393a5700615 -bgr48le e1be8e6bfe26acdee258e76329d2f03d -bgr4_byte af34e1158edfbc8c6929365d651a9549 -bgr555be c82d7877f7ef25ee1154d05b240cf54c -bgr555le b7a4e2c66807a82bd132dfcf8540bfb5 -bgr565be 3b464a00c619410eac7bdea9c96faf60 -bgr565le 4b4c708d4ad222f41734dce68e9d48b6 -bgr8 ad1db7a17cdfab2ede6f22c2415a3fbf -bgra 85fa06ad9fd156c3179a647a2e741b60 -gbrap 5fbf0a36ee9486161a862a4b2d6f8242 -gbrp 8b00ca96932c9bce5bca01ee621e0957 -gbrp10be df96591083deab8382c1907ea1e99e9e -gbrp10le 98769f5176bd3872f494aea8039d8475 -gbrp12be 9a0ee0322bbd7a25ffd85b0070c5a563 -gbrp12le 2f3899d712ee3e1510b0f442ceaeb505 -gbrp14be 966af80018ebf6b0576004362c1ba395 -gbrp14le 297e71281660b905711330a86eca8a71 -gbrp9be 8268b9a1e9f4d6a42e57db9c81d82fa5 -gbrp9le b3a09bba825e16e6d160328706a9f62f -gray aaa9c2fe3c2a2a43a4b35226ea689b3c -gray16be 5be35a44f0ba85eb8c55b4f062fdb80f -gray16le d9e73f7c4f53d795192ab87649270241 -nv12 719adbc47fa74e92f83150921917483f -nv21 9c833b3ce53539d270e1f21e4319797b -pal8 19c8735b23feeed18ec2d37913a5f3f8 -rgb0 ce26538ebe1ec09dec3dde5e4d8a1405 -rgb24 c2752464ac2b549268e9638745dba857 -rgb444be 85586541cc7eb12e05ff7162b12304c2 -rgb444le 670da20b82403e00609bf2c1f5611223 -rgb48be a9ee2c9946d8d54dba60cebbdbe43886 -rgb48le 28e2cf59b789249dbd0859f58f4ae55d -rgb4_byte 31dca70b4f3537afa9840cea1b062acf -rgb555be c010cc746ce9483b47387ba846670179 -rgb555le a768de014e0908dfa886108da376b2e5 -rgb565be 6727e71974c8e5dad157925c10ee1532 -rgb565le b0a2b4817775289cfc415bb951f9ae0c -rgb8 22fdbd14ce296c1afa9bb4a6ea09b3fe -rgba a37789c4df73c3bd8648ad1fe9d3f991 -rgba64be 286067334e4bca33fba7ebb1706890a2 -rgba64le 2a8b3dd5045df299259636d8e6b62589 -xyz12be 92f8189963a977ee758b77a85d6e99ac -xyz12le d5591761e71436d71e35788b46e873c3 -yuv410p a1280c2b9b562dba3c2d35a1e5fc4b23 -yuv411p 6bf10756ac5c7841db63a97106ff911b -yuv420p 45f4a06481f2cd8e28fb29c7c151e110 -yuv420p10be ddfef981d53de0f808173bb267203ca6 -yuv420p10le 966b8c55de4d8a12bdc8db3d9ad3ae6d -yuv420p12be 735da68f3ac8380a993f46a460c02432 -yuv420p12le 3a71ae4e6a7b106b3e1532c6d148fa61 -yuv420p14be d921d7b364d0a7bde183ba717a77f1d4 -yuv420p14le ab410b636acd41234cc396967f66c859 -yuv420p16be cde798cad650bcb087943442a399c8ea -yuv420p16le b7124c56605eeb12f3d13287ddc77f3a -yuv420p9be b0f6044fb40cf0ef41cc536311566cc6 -yuv420p9le 086f9320167a755faed18c0a3a36c0e6 -yuv422p c3982fbb57e796881efedae11b8346de -yuv422p10be a3db158525c7794fd06b4d20e558e64d -yuv422p10le 31cf611e502584fcf846d3ba2583028a -yuv422p12be 8cafc31b579b168a71f7093a161b8023 -yuv422p12le be83ffe86cb99ecfef76affb2b73d5b2 -yuv422p14be 96870c66856e2669095ccdea034558ab -yuv422p14le 46dcb0160aa8ada4025b365873a78d6c -yuv422p16be 4b96fb571e686185d96b4a97e3413d5f -yuv422p16le 503bc49bace58dae1767173746a16056 -yuv422p9be 0ffc1bfde0b679e6e7b7e0c8c84e686a -yuv422p9le 3c061cdb9f302c8f8806b409bd2b0aca -yuv440p 44f78792c5766ab896fbe0d718976946 -yuv444p a36b8ce12de27971b52e93267fe6583f -yuv444p10be 90e94770d3eb4693b09925f549d7311e -yuv444p10le 8a26fba7c2223d72cd5ad00c1941948f -yuv444p12be 24bdad5d7ddca614da7d105e931c49e8 -yuv444p12le a996cb8a1c062d2238b58a5db9b990dd -yuv444p14be a9f7dd66b6f54bbdbf176894b01d7422 -yuv444p14le 6204f763af4a0d26f41ddca1d1ae9741 -yuv444p16be 9370058632b2582ab7a21725ec4f4e1d -yuv444p16le 0674c63a0e8debbfc010a2730da66a13 -yuv444p9be b1327e7ca47a950ee99bd2a7e05f56d0 -yuv444p9le 2f89171f0470eefa9f89fdc43874dc1d -yuva420p a62cf0a72905b54a7ef10fcaeff723bc -yuva420p10be 602b6a8c0b16ce2b55ddcae443e75dac -yuva420p10le 1c086d4ee0619ac65cb5a69481b981ca -yuva420p16be 51c45f4227ba86159f46c65783d64cef -yuva420p16le e87030429a965f2ddc8f07ca49014573 -yuva420p9be a48309403dc66dc5242cac19cc7598e5 -yuva420p9le ae2dcb326eb3a2ff170f498077ae5624 -yuva422p 6e7c30ea252a41b70d26250f624ab284 -yuva422p10be e0ee8576f9328ca4ec174a8c084f2235 -yuva422p10le b489c203b9b0ebc42adb794bb10a3c4f -yuva422p16be 550b1d2ecbc3d5f50041816090d62a02 -yuva422p16le 73a426eb63685247ea037389595cb43a -yuva422p9be c65251c422cd3c81ff5d97d207312292 -yuva422p9le 3405924773c6bdc42325a8a1ff658595 -yuva444p e32ba5dcb01ba848e7dead04112b1aa5 -yuva444p10be 97549388c7f9fbc1425b1663b46c43d1 -yuva444p10le 0b88bed194caea2fa06f458034b1b90e -yuva444p16be 2dd545e4ddb0f134322eee1c1de4c2ff -yuva444p16le 1e144cc9ea16429c1655c67e2f12f5c9 -yuva444p9be e37fa0743bf720fbe31605714d7f7ad6 -yuva444p9le 9bd4083c1384a55e91f02630161dc4c3 -yuvj411p 042671398bc17a5f52aa9d791b361c5c -yuvj420p 86370b945c5d19d809ee92386d476a53 -yuvj422p d3bda08bd4b92a256a8ec8432c4767d1 -yuvj440p dbae7083c82f20a38fc55e6f8bc374bc -yuvj444p 55ce75c7bd172b28703e82f64186e6b6 +0bgr 62c0dc8407c8bfedc4f7030d90f961fa +0rgb c589d3f9f8ffab05582b3b700d5d11cf +abgr fad9ac424ee86f3fcbf6652565caa006 +argb 7f5454d8a5b4c1b292d055653f44e838 +bgr0 ba29a864dc098b75ab154766463f60f0 +bgr24 fb66bbb185312b51477f0dcec23f9243 +bgr444be a1da1347c242d95e3f491ca2ebced5b6 +bgr444le 8781877c57b87461339e9fab76502e5b +bgr48be 5948b1b36e82c8d39306a331ffaf9b59 +bgr48le fb9a9ecf8e5878c55bc47e50f8ec7472 +bgr4_byte 7a2a195a99a8a64e55b750b66c117523 +bgr555be f869793742746ada03de17e85cba7400 +bgr555le cfffac5557d65e7450240089c628397d +bgr565be 88a7d3ea7cef00c0b992d9894aced78a +bgr565le 520f41f1f6889e2b9ac115810b2fc32a +bgr8 a0a58190f00f9b3cd664df5e5a12a368 +bgra 587390de9dd066995cd7a24cc01411c2 +bgra64be ccd2b9941a8eb6a8578df7ea8d301c55 +bgra64le 2dbc6f9b03c2d2ea385423c97d837aa2 +gbrap 7469feefe6c5e859494bb15be073a4e4 +gbrp 00534ee5f27ac7ccfbf178e19e992dd3 +gbrp10be 4be5e92dd91c9f021c71969119eba6bb +gbrp10le 11f1210504144efa505990975e7b735d +gbrp12be 007145b9703f6890a27fd0ed1384fd2a +gbrp12le 78392fe0d6bea1b64b08ecf00fbc0580 +gbrp14be cf7a394be8a51a42266b092bfe550123 +gbrp14le 23fba36e3b2703ff487d636dcab07629 +gbrp9be a70297de1c2da7d9a1721fbd809d69c5 +gbrp9le c67297e85c1707317f04258bf3a7cc17 +gray 460d0f736a63b70ac1d4331f9ff3380d +gray16be a3c2f891649aa6337682d423a33b3f15 +gray16le ef9f8e6f2bc20a6dda884205d0d3f076 +nv12 b83a552443aa43efde11e7bad47393f5 +nv21 671c206b03ac9d2f56e323ad702689c3 +pal8 b15f61c785b5dd347e126f5316b4b554 +rgb0 88b4288b4dbace449e39675f02948ad4 +rgb24 62afbb93549d4912e800ef8dafa34ed0 +rgb444be 3084118ef48129c38baee4adc3686cd0 +rgb444le 7d6e5e6742761ab4aed0652baa236213 +rgb48be 591737c3d532d721915e43bcc94e9fc6 +rgb48le a5cba08bd5b049738155aff294c5e864 +rgb4_byte 636865fcebe6e87564087ad44e481085 +rgb555be b4d023fb9a5bdcbfd88bb6d0e889128c +rgb555le f81be3135c6186a977cd7a9c37948fdd +rgb565be e1ee3f91358f51841559caff850d7b09 +rgb565le 992aea678a434e5aa46bb6bc6ecad205 +rgb8 618e1f474797a4008fb45e1fecd31571 +rgba 94c432b19055081b0f2c4ef4df83c7c9 +rgba64be 0106f21ee49b5658ca51037a8358b851 +rgba64le 8d634d18a2d6255ee37c9937f9b776c2 +xyz12be 3218766b866b1a958799f2231a1760af +xyz12le d616708c5b8ffbfb960fa112df2c7c02 +yuv410p 3cf18ea881884223e798063d7a6227b4 +yuv411p ba99a290df25bbc99c8da014876c7f8c +yuv420p f4718aad178ced96ff16466fb0454490 +yuv420p10be 9ef247d488ecd4ad9cce0cafb2bd4c03 +yuv420p10le b3b4d183aff923c8992a1076d51f6a14 +yuv420p12be b25dc59d848f87f229767ae041b7836f +yuv420p12le 94fa01559df13f10ac426a410ce7422b +yuv420p14be 984b4d286b5322be557f135fe5902f85 +yuv420p14le 9fc1cfbebf9e7419abd19a323282196e +yuv420p16be cb58423896d429f6b1378e83a9dc35d7 +yuv420p16le c4bdbc33ccfc668e3979d18982d0fd12 +yuv420p9be f14fdf5b9f5ff296fc750d6b9ba6f991 +yuv420p9le 07d07c395c4a17666a69cbe6ddef7fc2 +yuv422p 1855d103d1995a2daa95252226eea394 +yuv422p10be bf32d8d1a96708703ee45942f7770db2 +yuv422p10le 61df19909db569953d4a6efc96e0ad61 +yuv422p12be 4d5428ff5df7eede5fe49891b4271695 +yuv422p12le d8dc60b5d05ccc5419051402462e7c1d +yuv422p14be 5f41c1c701a1fa1d6fc3e08bae35c9cb +yuv422p14le e1ba0c61696b09838d3aa47f3e18223d +yuv422p16be ed22d602c9e6f6a8627d0694a7fdc4ca +yuv422p16le 02975f7af27c35e68684235d185a4828 +yuv422p9be d4fdec159cb4c106a81e407fe1b441be +yuv422p9le 7a19175e5e38a028029cf6c14f5485d8 +yuv440p 18b37e71484029063d41c5716cd0f785 +yuv444p e666141ffbbc8ed5ecfd65bf27b07c72 +yuv444p10be 39437baaba84ff78b152769202566acd +yuv444p10le a8c9900e3593919c029373cc7781e64d +yuv444p12be 323a0510d12d3d473a9751a727aa9da0 +yuv444p12le aea9acf0d37b3c8603c02be733239e79 +yuv444p14be a2d31ca75e52a26a1feeb7b1477b2315 +yuv444p14le f41c19e54da37587a4b6f3ef09e3ccc6 +yuv444p16be 6467f6e5b939afef13353a76b9ae6b4a +yuv444p16le 41f0561edd3c81fd853763cf70d0ea69 +yuv444p9be b049fafb30796f808fb921846b713158 +yuv444p9le 7442e01cde0fd3f477d08ab557acf9e7 +yuva420p 7eca570c9d353f82df64cbb0428bf912 +yuva420p10be 318988d51adb8df54f2db35e30efc01f +yuva420p10le 5a8013321ba7a86097fae24ff898a94a +yuva420p16be 033329cf69ff22f15394645c0bf132a0 +yuva420p16le 744fd628f72cb1c0c9c7493d7cd6def9 +yuva420p9be b2abe1fc6dae3ac013ee1c9da8e77dd5 +yuva420p9le 48f859b2184cae6bef8a820d49d1de6d +yuva422p 7a9753f866cf59a63fefc3b3a6b71a88 +yuva422p10be a7f4c5add41ad5d62e539bd0f30631e1 +yuva422p10le b17312f0335ef77cd96d5097ab6bbef8 +yuva422p16be 95083847b4cee02aabd9ccb6b9b5c5e8 +yuva422p16le a12d042ae5ee2fa4ac6390cca87d8c7c +yuva422p9be c364ee7d2e394de73e139474da5a7642 +yuva422p9le a090cd6be95928567fb0edc9d9438f8f +yuva444p 6a4f6d23d820af40b831bca12ec7e153 +yuva444p10be 8ce49bc46add1d63bc2a0561b11fe36d +yuva444p10le a9247f4c96d3241858d482f4b52e2b3f +yuva444p16be 3b879425868f36b83008b265eeb425f7 +yuva444p16le 6771f76ac929369825b7e9cafa4b7264 +yuva444p9be a240dc0a0fa02177fdeb51571397ba78 +yuva444p9le ff34f13a8fa1c49c24af005d89edcf93 +yuvj411p 242d4306ee7b76e8a8cabae17c6392f1 +yuvj420p 7e74c8ea515cc80b5aacf6d98940840e +yuvj422p 58f001ed095aae9952e885669bc6f0a9 +yuvj440p 13ea331ee29d87af155aa87dec4baa1b +yuvj444p 0560df72ac64519b6c29e5df4c3d4ed2 diff --git a/tests/ref/fate/filter-pixfmts-il b/tests/ref/fate/filter-pixfmts-il index cdbfca1bb..e3992ebe6 100644 --- a/tests/ref/fate/filter-pixfmts-il +++ b/tests/ref/fate/filter-pixfmts-il @@ -1,115 +1,118 @@ -0bgr b85afb77d7c3198ad7ff9ca5cceb970b -0rgb 7ca2257e526092027c67311e273767bf -abgr 4df961441de91db58f5a8a80603de585 -argb db1e1e487a489674fbf260f56ac2705d -bgr0 4335fb9738bb6ca5d6d39d738b934bbd -bgr24 7446301030e6a26853aca2036309fa8a -bgr444be f80a44936b1295d14b0bac1db624d02e -bgr444le cfc1511a390f7ca18516540c31c097c3 -bgr48be 0b1084ac65d328552bd62b4e819ab91d -bgr48le 04e4f510b6d586dc9082af43a59c0ede -bgr4_byte 2dfd29e0705fbb2b590458028cb2939d -bgr555be 5622aa808b389095658a203970bd6028 -bgr555le 6a5ad1e35cbacc45aeb9fd593c6f61ba -bgr565be 5ff7a76d9f58800e38f21a84d88c7129 -bgr565le 485b2b6f589a936d6fb12d0033809dca -bgr8 d7fae34b87a67556c273585d9140ff96 -bgra 7b4abc57f0ee99a0226e9bfd5d25cf9e -gbrap 583131faa19f062f6523321da52066de -gbrp a2db88b8efce6681a3c858be2c229a33 -gbrp10be 714a32d10c27395406f4e4afb20a2216 -gbrp10le e44229ebb1cf96d3ce1960d092e0dfc2 -gbrp12be 09fc9ba31c8c0c8c9cd89767fda92800 -gbrp12le 2c778bcef911d43795e3f6c3b97be09f -gbrp14be 35d6dc9135fe910dc26b64f03de2d42b -gbrp14le 778c97b5ed06b9f1a230840a15771bac -gbrp9be b9fc10ab1ddad0e7945d6b047725d078 -gbrp9le ef3d6bc8069b95cae31100908a7fa967 -gray 2cadbaed81ee12181bda9f4aa87ddbc0 -gray16be 34cd1af8bbdd4266d5f7985ef22cfc9f -gray16le 0eec98b32e4a2a57d9f51aac9ac3cf8d -monob 07cffe7f5f25f39c3aa38866303791c6 -monow f2d1bdb939813a49abd6348ecfbb2703 -nv12 6847b3f7141ca1e3c40d3a494f0e13cb -nv21 e7a8e94001151e2bdd68a0ee7e4ac544 -rgb0 0d1dfb1edc9b4a7ad28dde9a1b0bee23 -rgb24 15781da8615974ed12b18f7439a25d6f -rgb444be 19bc79cdbafee996eb48feea597d761e -rgb444le de61209ae25f005d357b68e0836c4739 -rgb48be fa24415175a0759ac49949a948820f27 -rgb48le 82d5d55b03dfd9a74f0cc087793cdfc6 -rgb4_byte 7ec4d55df1bfb02ffa9956d85ade89f7 -rgb555be 34ef691ed2b6d22136c086d37bb0fefd -rgb555le 04b20c057eed7dcaee1858d45500ba54 -rgb565be 077604cc5dc91008b018264db73c8f0c -rgb565le a97549f25e63dd0dd404db41bbe05c07 -rgb8 a35d3c3b9b87261c7417076a8b18fdb8 -rgba 8ca9c8db589615ebbaa964be4ce62d08 -rgba64be 576dfc2fd1937f9e594c4004fafd83f2 -rgba64le 7938eccc1f05f13710ec351767b47a36 -uyvy422 8be40aded4b407ff66305911ba5ce2ce -xyz12be fe74cfbcd18ada951bfa943e990e0e32 -xyz12le 6a0c4d381f06a6d43a6c1d2e3e87672d -yuv410p 92112d85ba4f74cbd3044945c0f33402 -yuv411p b6b22000e5275c92baf5afc417c32a70 -yuv420p fca7fbbff753612a718ee13e1dfe2af2 -yuv420p10be 15c655b60ff5d212657e0620ed69fadf -yuv420p10le c9c71c78e00034af1b0fdcfe68615c6f -yuv420p12be a5377d262bd05698b2bbcfc8dd2b15ea -yuv420p12le 7d076ea30985ecf2eb590041a45f2cc6 -yuv420p14be 7a33da52fed0ffdc7f90ebcb677dc155 -yuv420p14le f431bf16d8204fb919ba0abf4ea54288 -yuv420p16be 254b78ba00a928d22cba98380546fe9d -yuv420p16le e6c182b47c3b57814d28248dbbaaea35 -yuv420p9be b1eafb2e864fa86c08684d8dd4628535 -yuv420p9le f07b2282c50f8eb6f138029d748eadfe -yuv422p ffc2693b9e1d39b59aabb9a7e1dffe05 -yuv422p10be e83db7f2f485bea0ea808f22ffcdb7bc -yuv422p10le bfd8fbeb5d89ba3904514d835aa6947d -yuv422p12be 5f31197795eda7998a0ec813496e57f1 -yuv422p12le 903939621d457a034c0181032164b3c1 -yuv422p14be 8d08189d27d3a97fbecec7edd690c691 -yuv422p14le 01b717875b85707185acd48ac75dd6f9 -yuv422p16be 0feb24228cc5ec3963dc0bde913d14be -yuv422p16le 0d6fe6924f14e77b2fef02e7ad1c47c8 -yuv422p9be 003b2032a30281845dfb6f9a7ebccc71 -yuv422p9le 427c505eb27af0059aeafffd1a858189 -yuv440p 23b55dcf6c876f0c53cf46960b13e6a3 -yuv444p 7730197c0570d46493d50bc163244754 -yuv444p10be 74b13f67114ac0f92af7bb427d6335ae -yuv444p10le 9ab09ae4acc46a2fa04fdbde1373a9f9 -yuv444p12be 76320bae89f10947e692b6ce1fa22b93 -yuv444p12le a79e40c464df640ba97c13456616b25c -yuv444p14be de7f737796d1de38a8227511b91d3378 -yuv444p14le 7c27d1b7846beb3565ce086c7df1131f -yuv444p16be 1d51af32b9e077bf1ad750c6a1787b2c -yuv444p16le 94a936f571861f25f2539ba099cafd56 -yuv444p9be 384dd0aa411d00b2deb2363a9f345db9 -yuv444p9le 77758bad5ca383b3a698fdcb38a85f20 -yuva420p 24337fc952d7f9c633756549a7b94146 -yuva420p10be f586830e7605b5bbc307f6f5c532958c -yuva420p10le 7bc9e81d18021dbb7c96ceeef4a18090 -yuva420p16be 54362c9d57d26ead878b9eb05a523785 -yuva420p16le af55baa12d11c0ac6c9065df730d81ef -yuva420p9be a290f1b1e1fe18ac22fed3535562ff98 -yuva420p9le 89d0fa6679548757044c0e1971c1cbfd -yuva422p e3fe9f137a37e1b3817fe8579d2d2acc -yuva422p10be 4aa77b690225054f9b5c7ce7c66950e8 -yuva422p10le e7c6538112fc1d9539f4635dedf52eae -yuva422p16be 0e5a1b0b52d42f4f07d7e63dbe4ab83b -yuva422p16le 5b3a1219d7224650929e6272693f1cd3 -yuva422p9be 9d6f936fa9666e2bcbada5188e2a4942 -yuva422p9le 0f97c4d357e103e7263705b918a37824 -yuva444p fe4dbba35f355d68b6c254c06db1cbad -yuva444p10be 3926a29639556a11acc95888e29517d6 -yuva444p10le 1b68842a69b3b9d5a23854217b410c69 -yuva444p16be 45ec67a0828aedf18f1ed54fcfb0ff83 -yuva444p16le 7b8e5963f19e6fe7fd409b34af014489 -yuva444p9be 6d2905a9e61ce4ff5b3d7b972a7333eb -yuva444p9le e2ffdb1d867a1b78f3bd38d600b17193 -yuvj411p 840bb5fc87ba0d3101d5c25b3f480923 -yuvj420p d1a8d9cf6b4035ac5d6439ab2754b09d -yuvj422p d20df6138cdf62d7f3b93eb1277827d6 -yuvj440p 17a24a86f279febaebb66d65509088e8 -yuvj444p 326bb83d1aec23d941894a1324984c56 -yuyv422 f9121733169ca5437e95e7600a7c5aea +0bgr 9eded8f32c68f7ac1a9b193a99ce09ba +0rgb b4dc02b3db8e378029202d8de0c7e2cd +abgr e66274a79478a72e2e6bd14be05950b9 +argb 1fdb247f982a305a5dc95fd662cf583b +bgr0 a0c8efd0fd721d05a87ca41f1156be7c +bgr24 2fee903a9a4c4411656bfe43e845eae4 +bgr444be 4035d08aa7eb0bb9b1165f21db43bf49 +bgr444le 067af68192af9c8b80d529e50ce8c7cc +bgr48be 9712780cef8aa67417a997fb01259f45 +bgr48le 4945f4513ac7aa7da7199f0cb7114ebd +bgr4_byte 1eb031ef7470e7f12f425adc8da54eb1 +bgr555be 77590a767858f467987ce85526164998 +bgr555le 42eef867a53bf544bfb163c3905da40b +bgr565be ddfcb8711b76b548e36f84f847a985a4 +bgr565le 6df28910dfa046a80e2661c13bae393b +bgr8 d560799e113ebf3fac2d006485394c52 +bgra d4755c172ca15a4cb3d26f226c17ef97 +bgra64be 3b38a8f5257e515706b424bf33915a65 +bgra64le df508adc2fd31a1d754c9faf3e9044e3 +gbrap 1b41767ca1de932c654275849a38769f +gbrp 0a1790e275dd089b7ed35eb4917d65ac +gbrp10be f4b749ca22458fcff8c4afe06e8fdd32 +gbrp10le 341a84cdbe06d876c15ec76a75df5c5d +gbrp12be 693a8a9fc7099d6baa716a20ad28feaa +gbrp12le 12e7f0d8eaf54c6e50c1088cfcf7131d +gbrp14be 3cf8e3be290b0558d3d17dc654968fb0 +gbrp14le 122601e60d3298f2720e37fd9ba92d4b +gbrp9be 6e495a6ff70f1008102fe787ec076ba2 +gbrp9le 35cd5c8a66fabe16047251d4384f0ea1 +gray 1ecdbe783136ccecd51ee105efc2a4a9 +gray16be 8bea3fb5ba687fdfcc4340aae268bec9 +gray16le cf250abe6fe20d402f4d672a76c29e39 +monob 08ec835d9c5a90578e05b82a85b4f3b0 +monow 2808420bc8ff291e27daf16dc87990f4 +nv12 13b8f8e86c93e6fc53346884983d1e59 +nv21 b75609c49d74f51f7552a2b3c3e79632 +rgb0 5587b57404a8646071e55e915faade5a +rgb24 1dafaa9b67687772ea55461dc034b28a +rgb444be 39eb5acc4da2829b8c30452b09623f43 +rgb444le f0b41a1162dc303ee441ad28a13c1570 +rgb48be dd92d2605758f944d075819c3d991589 +rgb48le 5b473d5ce25126949412721d0a55ad7d +rgb4_byte 637911d85ed773e6374e4c1cb249ddc4 +rgb555be ca555c54f844dd69c6563af5429ea7bd +rgb555le 6ed06b8d9774e17bee60a625d6f4d937 +rgb565be 06b421fa3e499b3e9d4013574ddeb654 +rgb565le ebcef31d12af8f17bec5a36c379e50b2 +rgb8 c90695c74cb20df324f43e426834aa8e +rgba 38b2c628e167e150e0094038bfb6548b +rgba64be e239083765579fc97e01d1b6caf54dbf +rgba64le 266364e7212cd2fa0882999cd502c7ba +uyvy422 c372c0e3574f92d1fc923da006ca074d +xyz12be 4523aa53eae97de4b5415d3a155e6ee6 +xyz12le e97355f5c22045c4d6aa31e74d2bc411 +yuv410p 55e672ea60e9f0e982bc2f99d4964dff +yuv411p 4e5d919cbbb5c4034824ee777c34e46a +yuv420p e24aa0234e84f6f53caa5d3d10bbc49b +yuv420p10be f858ef2a1ed40ec071d9d794a39401ce +yuv420p10le c4970eb75151077040be61fe8c9572f6 +yuv420p12be 5adc2cd69721f7cd3d436c8e297a483a +yuv420p12le aea48d6faea1f58d559f1dce4e989f6e +yuv420p14be 4b1014dc7f58b17a123b2e21141bb7cb +yuv420p14le 259021fa7ad8e968638b6ade9dcceb9c +yuv420p16be 280439052fa7ba9da4271cbc8e85671d +yuv420p16le a101ec2b87ce10ecc5a622ef7dbd160c +yuv420p9be 8e660afb3e04469c3765c2a719c56099 +yuv420p9le 23b5c65e767e4de3dfbb0f9b6a6c6972 +yuv422p 3a73dd428e915cb01c55ce3913658939 +yuv422p10be e499378daeec408a7ce2c15f869be54a +yuv422p10le 4cb3417eac19ff7e0129c5c915f1046e +yuv422p12be 508c1bcefe3bd1d1de0b44d8ae447474 +yuv422p12le d103d620dbe6ba000044f2c6294bd13a +yuv422p14be 7a39893b1fe54e9e88fae741e6951df7 +yuv422p14le 65d4c2c327a903f6d4b0a435524a7999 +yuv422p16be 850e0d0b4feb48c8c14e172de7e567c1 +yuv422p16le a1dbef3752c0c578e0285980a5859864 +yuv422p9be f3e1b7196d3e17ad5d31d9d200a2457e +yuv422p9le a21cb4b38bbdee136f70c15abecd5f8b +yuv440p f0cfcb6a845fc7f33ab54f04e5f61099 +yuv444p 8bf605570d90a638980e1c11526d99e7 +yuv444p10be 755f929aff54eda092127fca283cf333 +yuv444p10le fe216173a6b4eff5c029d468861b3da6 +yuv444p12be b4378896cdc5d11c0f861384b053c66b +yuv444p12le 18c2b0c8b2782733fd81cf1aecb51ea5 +yuv444p14be 6af38d0fbbed53040c7935665e9f728b +yuv444p14le ccc3ac62e2c7ab69107bd79b132c53a6 +yuv444p16be c392cd118a1813d3d6eb85d37bfe0a75 +yuv444p16le 71aefbed6ddf5c85ec421a7be04c1d36 +yuv444p9be ed5f899b0e9055b87896b2747bfeb3db +yuv444p9le b53e702b8b5506901e09fc150ff96510 +yuva420p 1de168e7f9d7185bcb2724e3c017c75d +yuva420p10be 0d9d69c9689892925b3b9aaa617160cc +yuva420p10le 1abdcbcb7e1e6f5ad5110d6d32223a52 +yuva420p16be af08ba92e1e1622f6bf2b4ec933b916b +yuva420p16le 04f1b058d84b18087307d7f3cca35c33 +yuva420p9be a4e26083fc89e73f2f51e90c414ab44c +yuva420p9le da57847a85dd93a9875c3e03929b7fa8 +yuva422p 9845c629815148c54583343240506f6a +yuva422p10be 80b8a7a7e22632f9a77e24c7e8a6f409 +yuva422p10le 157c25fde7c088e54efadf6e3108f6a0 +yuva422p16be a85e3226731777c94726dbf92b50755c +yuva422p16le 9fd8eda7aba4922c42cf67eb1ad2b6c7 +yuva422p9be 9c0408751c14dd7474ef53faa5d94049 +yuva422p9le bbc2511d505364744014c5df307c8354 +yuva444p df5585dcd8c3ac78789b7ba384528cca +yuva444p10be 2c41bb8c29f917271c14d335440b60d4 +yuva444p10le 79dfa39d248f4845ee8894e3b37ef782 +yuva444p16be 2918483ac55e52492cf7aadc09ea7b9b +yuva444p16le ff3c3b4d415a601140d8eb39c4ce2e91 +yuva444p9be 0d5eedd3cf06dc399ecf1c7d879095fe +yuva444p9le f58eb05ff7d50d732d33cbd78a80c42a +yuvj411p f9cf651e623210cbcd5c0b4ad0ed159f +yuvj420p 048ba7f77ab4bdd1ec3664f7f9cad978 +yuvj422p 209c34ab49969ea811ef915d6141a1ca +yuvj440p bd6510ff3385d4c72ed27cee49565310 +yuvj444p 345d97deced4a2b3b527bcfe178c0a95 +yuyv422 aa7f6cb7b5de1f35269c60c13b9dc415 +yvyu422 da9e97e6bb74f95639069a635738b0cd diff --git a/tests/ref/fate/filter-pixfmts-kerndeint b/tests/ref/fate/filter-pixfmts-kerndeint index 276931981..6fefda383 100644 --- a/tests/ref/fate/filter-pixfmts-kerndeint +++ b/tests/ref/fate/filter-pixfmts-kerndeint @@ -1,10 +1,10 @@ -0bgr 58fb0bda60562ce17e75f1c3459d0504 -0rgb d29f6a7b63ade359ec81f5856633ec06 -abgr 71071045b8ec66a6d0a38bb3fed1ca51 -argb 93ba0daa1e945ad1a6f8c0c1cd2e1858 -bgr0 364b8bcd1c7a384902077bc7190c5ea3 -bgra 81ac8315a4c66e363bc6fa3e99d9cd2b -rgb0 ae0c2afbc266345c1372276755595105 -rgba 42a6cc9b815ca0ee69c29db3616ce25e -yuv420p 40ca042814882b0b791cbec38e289702 -yuyv422 f549c98059ba9ce50e28204256d13b5d +0bgr e179e118e6dc0a5b6f9e80955fedc776 +0rgb 95fa448040fa3f86d23418b857123259 +abgr 1a24de822f91557546c8e9c8236f7814 +argb adc0120d95192942f5c39de1b602b883 +bgr0 33ee8c3df7c05bff51c742fe6beacad1 +bgra 6e8b840001a5f50c0b277fe3d7cafd26 +rgb0 8d63004296dc6db7868aa7163780f5b5 +rgba ebf7aaa65634dcee4289e80d4fb31e50 +yuv420p 8edaf2d52dc7fba910784076b2dbdcfc +yuyv422 07198d8a9f7989bd75d1da94800c69d5 diff --git a/tests/ref/fate/filter-pixfmts-lut b/tests/ref/fate/filter-pixfmts-lut index 387464be2..f52b90af6 100644 --- a/tests/ref/fate/filter-pixfmts-lut +++ b/tests/ref/fate/filter-pixfmts-lut @@ -1,19 +1,19 @@ -abgr c1e31c876e806cbfa8ef58441d1dee6f -argb 1239bf03999d8767c2e03863e22955a8 -bgr24 0ed1377b8c34489e716650edb593494d -bgra 87a4b656459a5f8ee2a0e5a994c61439 -rgb24 a1466d9fc7d1726dda3bfe80dfcc1b44 -rgba 980b5fb376926ca9c5a0a5b82a0ab162 -yuv410p ec9e2e31c1c702676362f5445efd4354 -yuv411p 9caecd7961e1011db685cc4d60220fd1 -yuv420p 8796295e7d132dd0f616fed149633ad9 -yuv422p 2a3f79670546a0e582ab00cb83bb3b79 -yuv440p d7e3ffabdb376f49a02cd641907df726 -yuv444p 13ef53a3dd3f77516e2c5237bf43b0c5 -yuva420p 34c07d6c05233f333a933a50a3dbfa61 -yuva422p 352406873ef88f865af0f27760f37663 -yuva444p 8efb7b3d809946fdf01f3c426a6cdf83 -yuvj420p 5a8771944ba995a831ca272526f440e5 -yuvj422p ab379523c4e79ca1e3c72adc46b918ff -yuvj440p 8e82847ed2f7a3a22ebdb2372e941fc4 -yuvj444p 4a98641643a7a51292c61c71e221ddc4 +abgr ba621149cf836e3040b31f417faae4f5 +argb 38a10f547a116087f4afb161f09f87df +bgr24 0e14a84f8a498ecc61d65f6d7b2f6905 +bgra edc092372e78c03968e247e930687b1a +rgb24 439d60a3995d71d227129f20c8077083 +rgba 2c5eb9b91888657a7ea033b70ed8b7ef +yuv410p 9f25ea872cdc078cd795e5d243fa6956 +yuv411p 726aa70c7c10368e3358f83a274e27bc +yuv420p 026f7be12e833017a7893f2a443adb31 +yuv422p 3a83fd6a45b44460fa53b2131d2b052f +yuv440p e25b242fdf1683b0af3858ce3aa5f74b +yuv444p c73795970622f64ba618f4ff773777dc +yuva420p 144eac0b2d74f93f8a2e6da620282e22 +yuva422p 6831b3672beb871f5158f39f2bb2bcd5 +yuva444p 62fc47a98c133aa3f475f92b02505e06 +yuvj420p 23e02eddd976caa8c9d1840d56b5d6d1 +yuvj422p d536cbaac3a322156103768de3072e69 +yuvj440p 68e4837233bc868bf4f115e5f3b0a459 +yuvj444p fd69499b44f0a118e0f30f46340dda61 diff --git a/tests/ref/fate/filter-pixfmts-null b/tests/ref/fate/filter-pixfmts-null index ac0485781..a42173442 100644 --- a/tests/ref/fate/filter-pixfmts-null +++ b/tests/ref/fate/filter-pixfmts-null @@ -1,116 +1,119 @@ -0bgr a06d3a7652e4885c65895e0e168aab28 -0rgb b6b5653d2228cdf2ba3c55a72f2e713f -abgr 1a147fa04ed70b9a7e67a4c89052f630 -argb 997df0b5c268a0d8f9c611cae4e01e05 -bgr0 218df6dc3eb5094a0c16a8bd18bc3999 -bgr24 d6370f6dc34df2ea66e1718baf74137b -bgr444be aba6dfea008ae12c2120a95f54293904 -bgr444le cfb5401e8f076cc8675e17ed1114a3df -bgr48be ab65229b64606f6408cd732b967c0b01 -bgr48le f1b4e718cadee9bd2978289153ce43de -bgr4_byte de96505ef9ad7078f87b4dfdf6fe4b61 -bgr555be 8d5de9e9200d622f27dc73958a85045c -bgr555le 74eb9837706143a40e26305a16a79369 -bgr565be 13a36d6502be88fc0c2aec05b8d2d501 -bgr565le ed027571692aecd522aa65a90cc7e09b -bgr8 71ef789609c746c2e7e4be9dec29062c -bgra 0364b074268682ea46168742a8239f7d -gbrap 412a2449fdfaeb5ebdf5e4196cc7391a -gbrp 4778f8cc2bdbcd65e272ea1761cdca6d -gbrp10be 0be11fe4b2324054be6f949e81966691 -gbrp10le 173f89ae58fd4d01d6a365318e4da3b1 -gbrp12be 1f5231ed7e4589a3ec98fa79134bdc6a -gbrp12le cc4830a263fecadeea535c4938b5cee1 -gbrp14be 6f5143374536e1cf1595260e91c86b7b -gbrp14le 937ff1dd9f498b39f9e882316e371fbf -gbrp9be c76ab5850c9bc72bbbf36caa6d1c5ac7 -gbrp9le 5ad363dc9570187ad3e3f2344fbb30cf -gray 2ee2ea2340d0ecf2dfa6f90f87384799 -gray16be a61507aec1088f5692036e1aabdb4f41 -gray16le 171fbdd46e3737bc865d0185a0006e1c -monob 309b5785a36bd988d17e15d88f4ffad1 -monow 8809a02bc69b58d1114b09ca79ebffad -nv12 75e90c54d858b993e99f4ee6d2a2a38f -nv21 8831a3f411015d45fbc5dd191245ba9c -pal8 13de2a1c3c80cb64d14e2bc4f6f461d0 -rgb0 992f5ad24802cc255edab45c3084db4a -rgb24 c71ba90f69f15c8275232bb3f62d0ced -rgb444be 26eaec65d7efd2b0c9c13b47dfd9b241 -rgb444le 5f29863553107110ea817f52151d77b7 -rgb48be a3bc81c46c21818a989f23104a599ab0 -rgb48le e87c661ac49aea1f1e93939802883d92 -rgb4_byte 293b1b84f01efd90bde40cb3faffc127 -rgb555be 5229183fa64d4e5c7e3703d8263ee6ae -rgb555le c3e9978cb2a4129a5575935e8cbc433a -rgb565be bc123b962629ead1a06af0c18cbb6e5f -rgb565le 20757fafe4756e62d845b2ab4c0b8f93 -rgb8 e01614f5416dcc8ad365ad7a57afc9fb -rgba 53796fa4c392a1b2659595b6a284f8c4 -rgba64be c05fbb1ada1b48fb1eb192fc200af2b6 -rgba64le 1b826cc613666f545274e8a7799d69f1 -uyvy422 3f411f947e3ac8f842c88e717d68bd9a -xyz12be 7fb449368615139d47192c4543b5d125 -xyz12le bfa1cde86dece70348e48f6293a7c2ef -yuv410p 7dcf3f4770c8b494290ceacd2c2ce6db -yuv411p 9461b188dab6f8b90d9a27e353a89f58 -yuv420p 61fffd2d8425759a33ae07e718d0242d -yuv420p10be 2abf90242cb021cb6fcf9f2c3c92f6a7 -yuv420p10le 180b7e4de684c7225d2fb37614f842cb -yuv420p12be 256c9e6cfc878a8abf681b30777c0620 -yuv420p12le 8dc8b86c4790da3769d4a62e87608623 -yuv420p14be 8d22756c5d2b9e501924c082bfb22a6c -yuv420p14le c9da19d4818bcb119ad6481b75778f7e -yuv420p16be 4ccdcca6dd6a960f9a3333f0aee095bd -yuv420p16le 9c5847d9b0de258a10ee906dc47e24ea -yuv420p9be fa7ad4f73232aac0e35def62af1e2c39 -yuv420p9le 3720ba1786b56c8f4913e67dddebbb07 -yuv422p eee223e92f1f2e5ad4186b411ebf5816 -yuv422p10be 80fa87750491dcc3e93d175b64835654 -yuv422p10le e1640cd315bd96c6b59f7753825a7306 -yuv422p12be 5c6d86e919515d1af71f8004a6252f9e -yuv422p12le 7f331cadb0ab75d07656d29f47bd8bd9 -yuv422p14be 4f4e186ba683b90fe990cccc4db7e521 -yuv422p14le d78016c9119b1f1d1c922bd5aaf47732 -yuv422p16be 1f3c216927d17966a009a42def124bba -yuv422p16le 90adbdffaeea9b09398339c8a1322b02 -yuv422p9be e46446534dd0821029d3b831c9c1d1b0 -yuv422p9le 520e418a2429f7efee511b7fcbf45ab6 -yuv440p 456d83524b299f2fa1bb988e421554d9 -yuv444p 068bc09d282d18c9fa35c2787943fc2a -yuv444p10be 9f6e1490080a454243daee9229425e1e -yuv444p10le cc183e51041351d9ac06c4df6e8ad5f7 -yuv444p12be 34f63ac6a47ac681016105d3bfb3e118 -yuv444p12le 7964701bfe8d718edf97f6e0002935bd -yuv444p14be 4ad3a9d52fe9c050150c0f7d2f3cf63d -yuv444p14le 69575e5a94b978f159c4fdb1a61587b0 -yuv444p16be 4000b12fa88ed0feef182da31c7e6b96 -yuv444p16le 96a857dba8dc6792c58daec872825b32 -yuv444p9be 07727e5c9040b7f0a17d591288ac330d -yuv444p9le 4d12d20a68dc28618594c96c2ade4ff4 -yuva420p 3a8c5c142e051367c196f95696e0e2c3 -yuva420p10be 1b7c5ec6691498e24676ce6ed97f62f8 -yuva420p10le 4c13322bca914df2727da91cca85ca1a -yuva420p16be 6afcf758f4b66c0b4173c942d42212d7 -yuva420p16le 13e195aa96329eb49921b6f9f07b875c -yuva420p9be 05a78390de312dfd21ac666a9da05fbd -yuva420p9le 78f5593bf51a31841ef83df41d0316eb -yuva422p 45ae66d6f69fd5b77e6831e98d228bf4 -yuva422p10be 18284c58b926fe2389605c692a703145 -yuva422p10le b934d28b615729a24bebf0381c465e37 -yuva422p16be c3f7354b6013b43439e02aa02be5fe69 -yuva422p16le a7ccc43820683ab15061d14cf8efce6c -yuva422p9be 14c55a16d19499b54b4341f135d3e558 -yuva422p9le a8bf168e5d2709222192d0aff46b1373 -yuva444p 86b05da54db8c7e8cf5b6638e19c6fc5 -yuva444p10be 8c417158165c00fbd42def60cbc27d69 -yuva444p10le 5f303ef3fb56faed69b4cc1c760ac6ae -yuva444p16be 52a9591ec0d5059e49b1b2803f8582aa -yuva444p16le a9272ac197e4a4195662ce90f533976c -yuva444p9be f72f646ef07cdab613420585aba041ac -yuva444p9le 6d431b0a27bf4f86ea44ef5f14247a01 -yuvj411p 037accc8e48ac9928a580cddf444f129 -yuvj420p 73661456012f20cda81207b14bb0c0a5 -yuvj422p aa97862b57f47c5a6506156e9aaf129a -yuvj440p ff8b9884a49d546b035f5d2ac1e673df -yuvj444p b8142888d80b8065c54045839e79b331 -yuyv422 f06a4fbbdb32807d05de825daa2c3a1b +0bgr 7211d3bdeafda12a27b6c586f56369e8 +0rgb dc534ffbcf7b02007a245e6af5bc0bf7 +abgr 0d93666da1532ca69c1a3e2ee0248430 +argb 86f5041b9245930bc6977d4f2babf74d +bgr0 914c5750b13f79908c23d2621bc5d171 +bgr24 fd0c957cabb399b3dda29e1190e6cfac +bgr444be 96d828ff1ea24858100e0afcef6f6201 +bgr444le 5a43d10a7890378368073be08141f967 +bgr48be 65986a0555423c910db4820732565a5e +bgr48le 3050e56ee66fa61d8dd88b12f4b2f956 +bgr4_byte 6d8ea0cb6b4cadace60222063a847630 +bgr555be 90ffbd6a7850f25253977aecf84e229e +bgr555le 9f800958e9c238c9441fef9799ab2a8d +bgr565be 0e7c46857a3bebc2e3bb77ae68cc0bad +bgr565le 31c0b9b6bc009a4bfa4421c3bbb2ff39 +bgr8 775803c35cf19b2fc84f537ce5a7e262 +bgra 020a3623e3ad6ea398d6adfcba9e510c +bgra64be ce8e864307b8f11d1bc4a92f3384416b +bgra64le fa2e6435c1f7f498d5714898e120dd89 +gbrap dcf43e62881e69a873382c12d3afe0a4 +gbrp 78a26e285e0f6ee73f37d70621e659fe +gbrp10be d325f4f209bf460f8ff7d37bc51978dd +gbrp10le c2328ae0384eeb34b1ac83726b385f46 +gbrp12be 8aa22995644b2796ecafc10dec5f3bd8 +gbrp12le df4badcfdf6701e03809ef5a278297b8 +gbrp14be a02a13caee9af458c5039c697ab896a6 +gbrp14le 4f521b6e69078bd0eca8dfcfde0f6ef6 +gbrp9be 397280799d9e78f48670664491e62524 +gbrp9le dbf020fa8423e170f2624ddba9f2c945 +gray 19ae78946e6acc3b552daa61b44a8ca1 +gray16be 2665aebcabc71b30a2252308b1335a81 +gray16le f35d7d9b8cac96c5ac25c2cd4b42443b +monob d2b84b01179f38ce59a7050064d42289 +monow 550a446b7900a42990d76befca7f08a0 +nv12 18aaac3efcb2e389bfa2ade34b917634 +nv21 cb3b54dcc21c72943d496e6368b0c00b +pal8 5ad4084b953f16007faf99f366b2ecae +rgb0 1cb89a77512524197ae6495dc7206a7b +rgb24 273cfae99e5951d567f230beec3e3eeb +rgb444be d90556c864a78c45ca9e2c27130067cd +rgb444le fe271368f267be87eb8f5b46335ba6dc +rgb48be 434c2ce989de629050e53e820b6929b6 +rgb48le e04c4a36ea9f9c5624ebd56463b593fe +rgb4_byte 77c49fda8c97ffc25678d8a51f7056ca +rgb555be cb820a51149ba9944480bad7e1260abc +rgb555le dc18e2fec8f39ebfd5b479fa6c5fe717 +rgb565be 0a7a10645295397cd6cbd6eadce71c8e +rgb565le 7454e27a0e2c2c37c67e5361a82dd445 +rgb8 7b602ac8a68dd95ad639f741be805a0d +rgba 283a6115965814470d50f11bf197c5fe +rgba64be a00ce626e8c94dcc2ebd7b95d7a7d43b +rgba64le 50932da874a5063a595a9428edb187fe +uyvy422 2d479ff414d1c94bf506e48c86f66a02 +xyz12be ff515a5c7277e411c0bf3c8f26d02de8 +xyz12le 63f383905675fd3306a329eb89d6d0f8 +yuv410p 242e22aa812c1db8bff7f8132fb1f6da +yuv411p 9305f8baa6ab955566fbee34391734b3 +yuv420p 005e6ddc8a5daf11cf866a1ec76c2572 +yuv420p10be ac1b6e1050f39464703e78a2ffc1913a +yuv420p10le 5c158075ae335e6bbf4cd3be29bbb62a +yuv420p12be 6a53755f72b37b2a264387dd5604b431 +yuv420p12le 174eb0b1aa668d517c13d6e397577cf9 +yuv420p14be ea8399e9ef8b6aa033ad2f5d6dca0473 +yuv420p14le a63fb4dfb6a7db44a5fd7f35d39d9032 +yuv420p16be fa7a59892b9d15f6e41c24e5f348f303 +yuv420p16le 5b75c822b20189bb0859b05bcf241aec +yuv420p9be d5dabd911d09c9e8fa01fe284dcfd4d6 +yuv420p9le eb1f57241a76ae5d65228adb3aede871 +yuv422p 5afc9b0f6c5cef4a7d0543c03d0fc8a4 +yuv422p10be b83a73824cf37922faa84227ca151b83 +yuv422p10le 64e51f718442560814e74dd1e01d6c94 +yuv422p12be 460ce0ef46387d0ee667664e72dfe6d0 +yuv422p12le 687856619666bc8f8bc6a8e91f7c4e95 +yuv422p14be 461184df05416126fec7c5d2fbad3876 +yuv422p14le e180b189ef2f8448c681d02b478e56cd +yuv422p16be 332fba636d33aea23514392d80602a96 +yuv422p16le 5d8e26fbbc8f25576065106c8820d56a +yuv422p9be e3b364350da35d2ffd431665ed9d3592 +yuv422p9le 0f21976b77781cada504f690d7dc6c15 +yuv440p e6754959dfd9631f2dc1682fa71aa4e0 +yuv444p db3ad634aea336663a2f5c2475b95410 +yuv444p10be e341efd871b34308831113f4b2ff29f9 +yuv444p10le f9666d63623e0d7dceda1a17202579cf +yuv444p12be 151c0e12d45ddf475a293cf9eee4c224 +yuv444p12le e0da5848e54c3ba0dbfa0414ff4a47f3 +yuv444p14be 83d2420dc82158274425c6ea5e396dbf +yuv444p14le 155753892ad8a8957df50033fd21fecb +yuv444p16be 6bb40952bd87aaaf2938cfadd1017a79 +yuv444p16le 9be8c3ca67cb8a778d39c087f008d8c0 +yuv444p9be 5a54227a9e1e12fd297e36e1e9361c52 +yuv444p9le faeeb7f3ff5efc51975d48d49f4ced5d +yuva420p 7b609ede889454d2b89b184c290e9e32 +yuva420p10be 4a0ab3165ccc5cde5f4ef9c27e8ccf82 +yuva420p10le 8fbcc6200060e0710e5a824b86c9c219 +yuva420p16be d149e664c8fce03192d78279472ae2c3 +yuva420p16le 11b9f6b757f98fd4a442983bca8945b1 +yuva420p9be 0aae288a080fb0acfac23610b2d30111 +yuva420p9le fb67be28488cb722d4aea6fe3fdaaa16 +yuva422p 88c582f7c6d7c123198fb707aad2d5b0 +yuva422p10be 465ec369d7e47a71976821fdc31c289c +yuva422p10le 07df8a8fcb3081e89d84359b178d5260 +yuva422p16be 0144a6783d7728a0e66d2b6d1134ecec +yuva422p16le 5b49f7e660c77bafcb03869ea2e1ce02 +yuva422p9be 923a2d718c2dcf62c4c9b573a56f15ad +yuva422p9le 9188e6cef21e89d034d37da1b1702a7d +yuva444p f89cdb4fea764921004e149358d7028a +yuva444p10be 87b0f4d461c40bde0cc85b109103d016 +yuva444p10le 5aed7ca68d5645a3a9acbe14b8eca54f +yuva444p16be 5701a24fa4153d45be9533d7ec00b660 +yuva444p16le c3092fc38248cf96e30dce70208ed360 +yuva444p9be 8ab557ee81eae76cd176d998078d671d +yuva444p9le b599165331bd7fa6b05dbf7b80044856 +yuvj411p ffb1370ebb9e1bb3b7dd4a532fe8eaeb +yuvj420p aaddf557fa39c3b9521bc6afabbc18e6 +yuvj422p 4f46f78ace9176a534aea861ac316441 +yuvj440p d8083286cf699e81113fc8ea04ba3c35 +yuvj444p cad8f07876e62d33caf6c420d0f67a56 +yuyv422 ad9bf7f09f4f8263131649407a778e7b +yvyu422 59f91e478f573d8a305e11da12a87be3 diff --git a/tests/ref/fate/filter-pixfmts-pad b/tests/ref/fate/filter-pixfmts-pad index 82f30b60b..98ac29c8d 100644 --- a/tests/ref/fate/filter-pixfmts-pad +++ b/tests/ref/fate/filter-pixfmts-pad @@ -1,27 +1,27 @@ -0bgr 36ba5b43e0ac64d8daad4f897efd8cdf -0rgb cc3ca0f63885af19b3daa4504cadcc19 -abgr 9ddb78f395d7d3f75b65b5309223c0c5 -argb e5fbb7bb282a80897b8f730627f68876 -bgr0 c55368036cccbb0af471d6bd82abe02a -bgr24 67f9fd70dc6d9896b7122976b33932b4 -bgra c8dd017b5a3b55e8b9d0ac1cdcf327bd -gbrap 8551b62534034c8aaebaa7d9fdefdfe9 -gbrp 9257834cbecf3842c2a6a820601a7504 -gray ca280f6888a9b66688b5f8ea68fe454a -rgb0 b1977b45634c4db58a183a07feb2acff -rgb24 e73de9dc0fdd78f4853c168603cc7aba -rgba 5a36df3c5ba623b589728a5a442e98e2 -yuv410p ff246b8b41d3d4a3eb90414ae3031123 -yuv411p a82c606c665fa747679aa8bfffa8a5db -yuv420p 0fe4d9031999f83ca96292ec2025f272 -yuv422p 5e0bffdac30b39f1bae9ec54fd9a6a34 -yuv440p 5e338303cd89d1d76ab918e5bec1e90d -yuv444p 248bdf9747d5c3718580dc2279e2e273 -yuva420p b5bdefbb0c5b302b6d18ee4df7c1d7c7 -yuva422p 8b56b36d9eb3c382d2a5a695107e759d -yuva444p 389cf95e98bf24684a42d5d67b913e16 -yuvj411p 5f10066e6a85d4785064ccdbb7259775 -yuvj420p d182ac937d312e4894c1bc548883bf1c -yuvj422p 26ac91b5daf6f2f1f3c22be489e994a3 -yuvj440p 63e2b94f81e0a6f2868055a4c8258b63 -yuvj444p 64f103c7db8fc803d062db7ed2b8dc76 +0bgr 22bc089fc08499837ea10d21a529dd00 +0rgb 1c50d2473acac4b679b2e3fa8e8e7690 +abgr 6220c7c4bbf648671bf626f5f9150ec5 +argb 56b15eb7545a145b2a24046fd0ed4026 +bgr0 3be8817aa08b9da594cd13e568512131 +bgr24 e5de0be1dac9dd4b460734aa4f375e58 +bgra 1053d254d9a0771f73873d87562d39d8 +gbrap a064334f3ca45fcff9e1a8830ddae250 +gbrp 8ed451b460562df4af1264d29b237dbe +gray 830e079c84012915564c4058db1f9324 +rgb0 d98f4dcad3fd8d1ef60a17aa2bbdbe2f +rgb24 2b2f83ba2729eaba0644086591545997 +rgba 8526a8dee19622d7326cb67049e766f3 +yuv410p 0d76230039ba638acca0316ea1f409b8 +yuv411p 30a738023914476182fee34a00f0f6e5 +yuv420p dd819efe6a446392172856c363df4cd5 +yuv422p 93cade68bf90cb752895a05ef9dd5ffc +yuv440p bc947633890872500ea44b29ea5f65e5 +yuv444p 1e9d6e3d58784d515de973cd7d787ec4 +yuva420p e2b891af8868283c7c20b7dd1aa9ffee +yuva422p aba3ab7266a9c9a8fc765674d763ecc7 +yuva444p 552862b03e94f00d742655d0f9945ada +yuvj411p 30b23cf51aba5af35b1215b72fa79dec +yuvj420p 425fd8861231be032bbb624340d426c9 +yuvj422p e57b3ea1e368b3c2655db36a33a5507a +yuvj440p 925b099022d40904533660adcb369f18 +yuvj444p 8ba8860166b0c8150bdd9c6646b957a4 diff --git a/tests/ref/fate/filter-pixfmts-pullup b/tests/ref/fate/filter-pixfmts-pullup new file mode 100644 index 000000000..c406d1c86 --- /dev/null +++ b/tests/ref/fate/filter-pixfmts-pullup @@ -0,0 +1,12 @@ +gray d39e18e32032ff22653df6b166e63d28 +yuv410p 7bf504443a542a45b104c80e84ba71fc +yuv411p 984dc2dd858c112890ec392d67955edc +yuv420p db8bdc0191dd669419fcb28a26bf9acb +yuv422p b255751a646eb12087b1766de0650b52 +yuv440p 421228103ae192db87c05677c8a5c58f +yuv444p b94e5c0a63aedac7efcc8bc5e7800fe7 +yuvj411p 36bf69556c95ec4ff2e6b3d524b7d34b +yuvj420p 2dc343b7d5353b2f769aa41b59885abf +yuvj422p c5bdb2ea53ae3db4c6859d514f6a473c +yuvj440p 9babeadd76a194e37d082ebe7ed11553 +yuvj444p d0170299a3cbc649956e9f31d0898cec diff --git a/tests/ref/fate/filter-pixfmts-rotate b/tests/ref/fate/filter-pixfmts-rotate index 0438aefca..d67bbbfa1 100644 --- a/tests/ref/fate/filter-pixfmts-rotate +++ b/tests/ref/fate/filter-pixfmts-rotate @@ -1,20 +1,20 @@ -0bgr 1040a5c4645582fc271f7be40ea5aaf7 -0rgb 7f21fcf8fd658de854b75dd8c47b0b00 -abgr 24f441d2e6e67cae2d3451aa1dad23a7 -argb 993002f41f621d04cd76278e466c03eb -bgr0 efe11efe2840fa84ee95cdb913463bc1 -bgr24 d0f449e8b38e07c947bd808f441a8ace -bgra 54cebf01881cb63ec3727f7cc23b0a6b -gbrap 6d69c0cd0cba6300065f8d990e35b081 -gbrp db3b6345d2a5c0fb524f93486d97193e -gray 5a896c38449a0fb08129a7394952eb31 -rgb0 c29f92ff5224044c7272c763fa5321e6 -rgb24 739f0eb47e76ce5c87354d5631ac2d5b -rgba f25570a798f24e8174729d978872c272 -yuv410p 22e673170464119cafb1a973c5a8080c -yuv420p afed4567a1b2d54ca9bc87bbdfff9a34 -yuv444p df57aba68928092b54f6b75ab01e3110 -yuva420p ad9bdb4f21855550a6f94e2d96588097 -yuva444p b6a345f46ef75814033f733ccb4da42e -yuvj420p ccc0724c2ff91daa3848db1f4d91d010 -yuvj444p 9165b6e7c647c93cd24011d931890edb +0bgr 7951d539e3ad4a08fed97124e0210f43 +0rgb e8f60a93eacd8238100518df19b740b5 +abgr ae2f3005122aad5563cf7ff12783e3eb +argb b7ae033b85032661be80d8ba01200eec +bgr0 70c6098cbf680a08ff3b29cfab58ffc5 +bgr24 83fc4e817b1fa89944e245f43367802d +bgra bc1461220ce53ae40930332a20e8a8f4 +gbrap db83fee7e30c89e280ce0c7ddafdc649 +gbrp d485c1b9d18b56085a17294c633b32a1 +gray dcef928e5befed02d28107afecd9e904 +rgb0 bf15cfb2c478c50e7a6875db550aedcd +rgb24 77d5f147a56fc9b17a53c7d0abfbe210 +rgba 43b3acb79b05a83964f8fc4542ff3520 +yuv410p 0a5d25ea1feb6a169f1af87089e75dcb +yuv420p 39c2f18ae4a1313b680d281ba7de0b9e +yuv444p 7d6fb967e0da2730c2d6dce701802add +yuva420p 2c2d9b20293a8eba4a98434528e9c10b +yuva444p d4de3db71ebeb0d3266c17391e6f99b3 +yuvj420p cac522bf5672812deaf6716e75388ff6 +yuvj444p ee0bff6744f737012a01343d9df12180 diff --git a/tests/ref/fate/filter-pixfmts-scale b/tests/ref/fate/filter-pixfmts-scale index c772b242f..b691b98e7 100644 --- a/tests/ref/fate/filter-pixfmts-scale +++ b/tests/ref/fate/filter-pixfmts-scale @@ -1,116 +1,119 @@ -0bgr a96ce0c378614d884139ec32d7b17fc0 -0rgb 70414c01ffbd3d420806c21b32a3158c -abgr d507465437881ceea4dac96ad72bcfa8 -argb 95964959d3580719b6df04457ed091ca -bgr0 46c2957c538060d305d82f3890f703e8 -bgr24 1d684e701a851dc502051d064b49552e -bgr444be 9af6abe0bc74cdcc75b4ab2f441f5f67 -bgr444le b8c0e693ae2cbd7c03abcc3aeb4bf7b4 -bgr48be 3aa33b667b9baefe3f17ef44360688cd -bgr48le eaf353ab363fbb279fd72d6c6e3b8855 -bgr4_byte 2f2c6b57017092b981ffcd4a9eb54d3a -bgr555be 9d71206c1a5373b8978126e5f5779726 -bgr555le 025caaa21fed9d14c382cac26af778c8 -bgr565be fca6f07daf23d9dd84381dd4c9afd959 -bgr565le f524e9f16bdd68b247dbcb621e543fc0 -bgr8 2a6509639c181fb7829721bdbf78187c -bgra fec5335edde2f1ee1f40d2fe4305855c -gbrap 76ddf2bedea40c8743f4117b786d4773 -gbrp e2704defddf1cb8d75f0c80fec6491d3 -gbrp10be 7dce0805f7ead7d480bd83323d76bf9c -gbrp10le 24b220d50ffcb3fdffe11ef63f0ea758 -gbrp12be 49ae16b634cd12b108c0ac153f053549 -gbrp12le 889da16199f9cf1449d93cc0ca8c5a15 -gbrp14be e63375705d6915035c7bce0faa4934e5 -gbrp14le eb6cb4555edb175d807fe1b5382d2fc7 -gbrp9be 2c9adb80abc16546cac69b4872aaf557 -gbrp9le fcfa1684553e3e185179462bca347649 -gray c45dcee08887f43dc463f79d7ecd7d68 -gray16be 52a6ff8ba7fe11032f370c0888d87fc4 -gray16le e78f07e83698651639743f2f8501c51c -monob 91ec2a25b13f6ca34d42da778b217de0 -monow a991455fda8f60f373aeb744456996b9 -nv12 0617f1e13ae4a43d4cb49282b9c02f71 -nv21 8a00d5d29766c1251eeda74c0ddee3f2 -pal8 c4101024891e078d67ae480e15c380b5 -rgb0 9bccae1af3f4c3e6a126c98a595a2481 -rgb24 64aeb63d9e9735277255eba4f7a47082 -rgb444be 88f534c5d07ebf5a4374484aed540893 -rgb444le c243685bfad7c243a78892a0dafe2b9f -rgb48be 874c8e2305ce9d82165ffddf2854d1f2 -rgb48le 877075f2ff2d9a0aec6fec843385f126 -rgb4_byte 37dce6bf5eea65cbc8c934a047190048 -rgb555be 8aeefa1fc4eba200abee3b1eb52186af -rgb555le 0495a7c13f9b0d0253379d5ae90cf6c4 -rgb565be 5168b66e69c25351948085e5fc51bb3a -rgb565le 301a4d41f0db3aaed341d812ed0d7927 -rgb8 8f24090953a7616ff319aa981e32c1e2 -rgba aec2346373d91abdc8c0301b44513128 -rgba64be 5ce6f591ac8be4edcf5c3350d2d2d3f5 -rgba64le 12baab5162019de2053db39a3bfca868 -uyvy422 479105bc4c7fbb4a33ca8745aa8c2de8 -xyz12be 8b9767926ff233a5820f99923e8331df -xyz12le a76c6cd0b058ade67104a8bb3217aaef -yuv410p d0daa93f5cee83360e219e39563ab6da -yuv411p e5c8f3ca024a88dd07e0a92db3e2133d -yuv420p 485d9af8608f926ffffbf42230b4150d -yuv420p10be e4f12002b46549779886f27fd3c6c645 -yuv420p10le 698b7a346ae6d1315280d3e28c86b973 -yuv420p12be 10ccb1da4f69f5578e017ffdaa19adf6 -yuv420p12le 4f68fcfeee4fb70ea941979cc6a39d1f -yuv420p14be d7b1183a6ca2f5d80d1bddf609c35995 -yuv420p14le 934dbea61d804e7c66e805a45f1e3914 -yuv420p16be 6ebcf48a9317c6265430cd3ba5f569a2 -yuv420p16le 604a7215f384488a38aa0cffdbcbe17e -yuv420p9be 7b293aec92897bf0a32ec3a02a20acf9 -yuv420p9le f37fdff7d6c62ebe2ab0cf791cd049db -yuv422p b1724528079199908c667b3428a7c01c -yuv422p10be 1c7281254fb980c123148dfd145c4a05 -yuv422p10le 959caa253354e897f01848db21b8006e -yuv422p12be 9e1db2326fb3dd3a8f8d32f3a6f61305 -yuv422p12le 5a4aecf4baf74358551e75fd7f1549cd -yuv422p14be e75088b934f86ddb6a7ff1749b77687c -yuv422p14le 2cdae3e0447b35ddee6161639107205b -yuv422p16be 4ccc3e0bc94eaf3a3350e4d694c3a56c -yuv422p16le dde889032f13fa5f8d76b8484dd73116 -yuv422p9be ba5eae7669d02a13f54a592344612098 -yuv422p9le 2deb39425d924a15c8946df79ceaa579 -yuv440p 19de0ba1fd354b42189e96cdf73ef7cc -yuv444p fba8a00cd0b182af82e9de3b2f4d2c8a -yuv444p10be db89397ac4d33e66b5eab3678661f73a -yuv444p10le 28208677f07d4e4191ef228c096f3297 -yuv444p12be 55d291347d13f98b520c7d0cf7e0bdfe -yuv444p12le fd12d6054262cebda2a9b1a2ac4dac98 -yuv444p14be a078f34e001828d576e748ca0850af56 -yuv444p14le d02ba5c47b0bbb359df8ef478aa4c395 -yuv444p16be 07e27200d2f4382090ca260874f02e92 -yuv444p16le f8bac16bf1f2afbd3626e07bcc815a9f -yuv444p9be db739906e3ae3b8792cdc5a0c3387565 -yuv444p9le 693b8d30958ef1a37296b1690b4b36d2 -yuva420p df46b738bdaf30d3a7f880b5ae45b092 -yuva420p10be 8e5f3b069fdf2f0c14f49ad827991092 -yuva420p10le ce4ac1961e0466c40448353cf76b3282 -yuva420p16be aa8ca29a93936c62ef038ca8a57f47d7 -yuva420p16le ee0cbb31f9cdb897c1982df0caa8ffa0 -yuva420p9be b8ca5603123aeb953b9d4fc8ec8e35e1 -yuva420p9le 220212a81cda0f2d112f7ae96d532ff9 -yuva422p 650755270debb03d2c03b2e93b64c576 -yuva422p10be 8d077362542a73c72aadb885510ea0c7 -yuva422p10le 80f729d9f8f438d2ab87909797c27873 -yuva422p16be 0b8f9385498d2449b18fb15237b0a448 -yuva422p16le ce22b20deb93b4846a5043aa104f22d1 -yuva422p9be 822df465d12916d8852340d6b56247c8 -yuva422p9le f69c09e872838fe392dfe1825263d3f1 -yuva444p 72083e0941cc45af9f97b89d3cd16112 -yuva444p10be 42e159c62771239fa14d06a2db3b357d -yuva444p10le ee9786aee055c39da2dfbdb91ab834b5 -yuva444p16be 36a8797545163c24fc0d73f669c3108c -yuva444p16le c017c229aacb832a12c2297fb080a7a0 -yuva444p9be 8bfb5decfc8b71478b090a5b48c316c3 -yuva444p9le 2c7bfb90f7db9faab6862537801e1143 -yuvj411p 4e37fb8600e001c387bc67cd8cf8ce33 -yuvj420p 31386dce60a2dcc493da5d0ed9d880df -yuvj422p 492452e50a3fe66724840cad29be4098 -yuvj440p 7632893e81d3f4f3ace3755f97479897 -yuvj444p 389388dd5d623f660c30ab840807ce82 -yuyv422 518be9b5ac93c365c0962453770fbe73 +0bgr bfd7734cc0e7183828cbc27a87a74fd1 +0rgb b4048f9039c7d19d4cf629512eab6e49 +abgr 0e21453cd0f400abc65f5c8c5f9a2407 +argb f5f38bf456c4540ddcd6143920b152d7 +bgr0 0d259e56d57f3c345a5a33d2288ddc25 +bgr24 b588ba9ac44e37192d15011289ed9e66 +bgr444be 36ad62c82d433d8a6e67527329cafc8e +bgr444le 267fc56e6ee33cc02b1a19b77a77ec74 +bgr48be 6628a75fc4e34a7dd49f27f91afb0851 +bgr48le 6c75a39868247db041e26147d2e7b53c +bgr4_byte 7fa21e4a5a8c675d013a1e3dc51243ec +bgr555be f2fd3215c29a54eebf522ebf12b4da4b +bgr555le c113e39b478334bf4327abfb75fdbd2d +bgr565be a4aae2855bb89d43174377ff93da3075 +bgr565le 59e98d1560e7368fe2b5b83ebdf44f72 +bgr8 a5e7429398bcb06e65886108236e8be0 +bgra 2cc6f245d3f97c14d8348c26eb864968 +bgra64be 71bcd0f8c5e00a78a5fea6d933a9cdfd +bgra64le 477b5ceda81e963b77af1c347b43a6e8 +gbrap 81d1062009b10394fa2375212d6fa4db +gbrp eda47ef0d0df311e7a7469c7f844c8d3 +gbrp10be a37c7e545f725e0662ba85fddbc854c5 +gbrp10le 4116fd82b3a7e2f6d7c98de6bb9b712f +gbrp12be 9e41ce94896ac589ba4080356cb0a64a +gbrp12le 4efabb781c595c5511c4c64aab121727 +gbrp14be 4340d7cf3beeafded76f4ddfe31072a0 +gbrp14le aaaaee74d2f397ce5cd2d32833926f7c +gbrp9be 7b888a93129d17969b5d7f84d69d8697 +gbrp9le f777b972045bdb016a528468e88e6f28 +gray 056173fc49e4f006a833812d9e32d70f +gray16be e45056dddc12d35477133243494cc8ed +gray16le 292c098ac003086d66a3f22fe0bc6fda +monob 24f12215824e19b3040b5019b2d7df8d +monow 72dda82d40e73d494ba14313b2c6287a +nv12 a44b33111b0d1280abc870151f65388c +nv21 b9c69651861e44a837713f0d5be426da +pal8 58a550701a23eddc83d2a73346c12a72 +rgb0 5e1c18e999682ae5a4389b4e37384138 +rgb24 e4d86fc5656b70ff4935fe2a90cc08cb +rgb444be 006a4118a03c2b71db3921de2ba96893 +rgb444le 455102c8041447df22b5b262ac8d41e5 +rgb48be 18b205f29cec6e90a7e957bff8c6f458 +rgb48le 6801bf7aedb9ec5b8d6e90ac59cc02c1 +rgb4_byte 7ce98c9c289e718169173019a7daa902 +rgb555be 23a2240967bbae4f7073762614288afc +rgb555le 2d16b7cf6948ec88d2d290344b8e7020 +rgb565be 0a2e18eaf3eeb041ad19ca0a0a4983aa +rgb565le 55a54972f5f4e1045b980ecb05765768 +rgb8 15452aa88fafe2e99761f9ef47f498ef +rgba 0914498509b7d34a1f2a788e1f6e5b3c +rgba64be d82f2688636e49920e5a03425aaa8ef3 +rgba64le 63841e2644b9cf4ca1ad2f3b7facb83b +uyvy422 c8fc0f5e8931a2c798b69a02ec715a26 +xyz12be 25f6ba007126c7348050446af457ffdb +xyz12le 6a7a9d76fc51d6c8e433d77421f89157 +yuv410p d189beeef028bfed7a0a376a6d3dda40 +yuv411p f00f59254b3d461804db2d701a2a030b +yuv420p 470647070fc66cda538ac268ec242bcb +yuv420p10be df8f8abee664033b8d1f180996460291 +yuv420p10le 92cb7f81920cbc2a2d6cdbb4bcf3511d +yuv420p12be af2dc0234ca535cf86cbf8ce69589638 +yuv420p12le 6777b6a682ba411c8477463966fb983e +yuv420p14be 3e243028bb2fad0c9297ef1c2bd92734 +yuv420p14le f520370cd5b78d9cd7a06c56cb94d172 +yuv420p16be b99f75e99404c7885d4ccc18fbfce4a6 +yuv420p16le 66c47ba1b3dce2b39ec78d48d9eae792 +yuv420p9be 901c2489ac1ee42d4f59a2272fdb9b0b +yuv420p9le 3191db22046c5dc83cdf163ffa554688 +yuv422p 06acfd062b924ddbf596d693b1d3e162 +yuv422p10be 70f5d4293068457e721fa7f08ec825cc +yuv422p10le 75dc1a6818161c7cf12ef5c3e4136ebe +yuv422p12be a1d5c0b193fbe6afbd4f4df3791c73ff +yuv422p12le e1ec329c42de5a0ec64f1f02f38507e4 +yuv422p14be 2ee37076fddae430fd4b1b60abb28c27 +yuv422p14le 9ce7e04b030801746083b7c14fcc907c +yuv422p16be 3bf45caed6ce686b43095dccfff5f198 +yuv422p16le 7200f2405f7b979bc29f5446653d1fbe +yuv422p9be 4c44d041f51b499fe419c51be0831c12 +yuv422p9le b48e78a8a6a3f88269b4f5f810b75603 +yuv440p a9dd3fab4320c3c9b0eb01d2bf75acb9 +yuv444p 77387910c01eacca94793a9be37c1aa1 +yuv444p10be b4e8cef69cb2ad2c24e795325a1d883c +yuv444p10le 83855dd296a1859c085193c1edbb35e2 +yuv444p12be 9c2bdcb8cf18fadb4123e7e95a4a688e +yuv444p12le 7ebc00148fa0697a62a57954397f80db +yuv444p14be 964671f6fb832031719109404dc24334 +yuv444p14le 938e67a1e1d1d9c24b0b2e31ac8af277 +yuv444p16be f5d62af6faff3ccf7050984449e050fa +yuv444p16le 6a164dc492c5fd3a432bb35bea6e758a +yuv444p9be 33b3de3ce657818af720ca4c68ec1dbf +yuv444p9le 48d58e5f12cc52ac1056819496280cf5 +yuva420p 2d257eab9850cb69ddf0d8038c0c63d7 +yuva420p10be 4728f2b6d43136926602bc0135c2d68c +yuva420p10le 47a7f657d8c011086b19f768a7466811 +yuva420p16be f52db29abe686228ca68283eaf4570d5 +yuva420p16le f04b89a3811e5b0c40963a2428f21890 +yuva420p9be 587f574431d740f7da5a2b2361478e67 +yuva420p9le e1f7165579b963f9f0b4b724f00af4ef +yuva422p dd7818dd6a875ec3d0e38f87a0900850 +yuva422p10be 8a0b5a8e1ac23b3806cd677b4ef5c7ad +yuva422p10le 15c8c0573dc98d2e570d5a395298245a +yuva422p16be 5469c6ea7ff27ee727909724216b10ac +yuva422p16le 11cca9765696bc43617baa0c5fedd28f +yuva422p9be 535ff206a1bfc4dee17d846dba21a6a4 +yuva422p9le 08e3e8819decb2eba909cfb2ac2ebec2 +yuva444p 9bf08cf5f2f711145a78503a68563f41 +yuva444p10be db3d5d341b61bad86f60aaf07e7b2f47 +yuva444p10le d8b4aa64fbb4c6ea51d2d96e8be38884 +yuva444p16be ebfc666db6de2d932e232b4e09fd1c1a +yuva444p16le 0ae0b32da3d398c5ee800727e9b4bdaf +yuva444p9be 7a1fa645240d60ff933bdc2c856ae80a +yuva444p9le af34e0e6168c12cba3e63194c6a8e0b4 +yuvj411p bd702b35d0db2b316d5c9a54ba2fa866 +yuvj420p d5e8943616d2dc0ddf9f64ccf0ec088e +yuvj422p 78314d864e3edd4162db5eabb347503b +yuvj440p 4b6168487de8434d45ecec0c2e9c2278 +yuvj444p 3a8958f4cc6352b6486b25f05db3a982 +yuyv422 8c926b0916e4ae27df8f0d0450712f72 +yvyu422 b4edcd5179382a595efe8286e6dad579 diff --git a/tests/ref/fate/filter-pixfmts-super2xsai b/tests/ref/fate/filter-pixfmts-super2xsai index 964d04a31..a3d7fed50 100644 --- a/tests/ref/fate/filter-pixfmts-super2xsai +++ b/tests/ref/fate/filter-pixfmts-super2xsai @@ -1,14 +1,14 @@ -abgr b04e3dfb0043f6eb04a573d2d13052eb -argb 257e33717d23298430025c0665642cd5 -bgr24 3765d88f93d4ae8baa2cfbc64b0b32e1 -bgr555be 81832e6269c509be55bba49bdd0ebed5 -bgr555le 56772e91aefba4013890d156866730ce -bgr565be 0b3c420fbddcec5a420c285b3c4b8792 -bgr565le 6cbded26d2bab8204afe2115384c09a8 -bgra c81430c3d1465e37b6acaa19cc54e932 -rgb24 9899359a817e705dc5b9cc363d35a625 -rgb555be 9b60d9aa1f3c78edf9936894f37e3243 -rgb555le 917fa8565f35882404a45fee3a947bf7 -rgb565be 12edaab49440fbb3aa4c1835fd697745 -rgb565le 5bf91cb1767066f23f0c672dedb4d476 -rgba 71687289b6c3ab6fa727d468de459026 +abgr 2ef66d92ea295954daec5e60f3c624ed +argb 247bb72c65d9cfb5779b8741dbc332b9 +bgr24 f40a64ec89f99d3ee0fe73437ccd800a +bgr555be e068bb0bc5e18d6072d8acbac1d310c0 +bgr555le bb18c256e2257bedd5e5dca8a121e834 +bgr565be a1eb921b9b4eacd31b616c3e04fccb7a +bgr565le 22a9884160a681efb67d5535a5beb423 +bgra 3a2be01be675daca7cf14e5b3f0e4728 +rgb24 b82659f61dbc5d097c32a2916ba7df8e +rgb555be c05c613110ee7fc595fb2f13a27baa7e +rgb555le 781f83ee441babd51e545e313737b9b2 +rgb565be 4c01aaa3a3622a558b38116f1c5bb31f +rgb565le d40bdd5c32032f9a219e77180795fb8c +rgba f90c2f745598be6d9a6e82cbf264a4ad diff --git a/tests/ref/fate/filter-pixfmts-swapuv b/tests/ref/fate/filter-pixfmts-swapuv index 7bc3e3d3f..a37384e5b 100644 --- a/tests/ref/fate/filter-pixfmts-swapuv +++ b/tests/ref/fate/filter-pixfmts-swapuv @@ -1,62 +1,62 @@ -yuv410p 5b295ab25ea56129be1a901d19b14f94 -yuv411p d764e5278d2745f497a099468ce08f6d -yuv420p 7c44249ab61c7974edd269966884a357 -yuv420p10be ffe06addb7ffe7742ff885bffccda9d9 -yuv420p10le 285d971c468cad73a4d9669939ee942d -yuv420p12be 2f7e4da722d45a757c5fb38031685165 -yuv420p12le 9db66b795b28e654136f8a5170482b4a -yuv420p14be 35b9055f4b92a78a9b312f1471ffa270 -yuv420p14le 61817af578e8c6b5cacb120dca9008b0 -yuv420p16be 75e0bbe9a4f29e96eeae88207208827e -yuv420p16le 340538ba047c5739242cd043d1f6c67b -yuv420p9be 5e5bf3d0249cf5cdbd31bb58746e766b -yuv420p9le 8adc79b7768cc8f7220381c3fe8f3090 -yuv422p 6c2d87652f18bc1b0e40cf794a061bd2 -yuv422p10be 711e7e00ab91aeee82e18ed84117345a -yuv422p10le cdb2c605b45a3ce840dc967bcca5893f -yuv422p12be ff378d3990ef37e6b43aee27880be256 -yuv422p12le 9e023fe6f0fc4626e3b2733326c8ff34 -yuv422p14be f9f144674eb0b6945d9e7c8c3f84e2ee -yuv422p14le dc7fc4fcbc9b571f357df173d3521f98 -yuv422p16be 45a44b3298488c4979a5c184c95720f8 -yuv422p16le 479e36c10a498669ea003192289eee85 -yuv422p9be 37eaf23d5f5a331e949f7b4ec50a44ae -yuv422p9le 267710ff84ef671419982f04cc111ad6 -yuv440p 5cd5fd358c63e130eacb77867c486f7d -yuv444p 22bf5f86ca3e9fff950d2b2ea6da65be -yuv444p10be 97a809d37853acb4864ef75f6e3aff24 -yuv444p10le 5081c59d16157eabc73d49c6b903d530 -yuv444p12be 183bff4f9470a4d4f980aac98a9181e7 -yuv444p12le a57dc2f043659d1d1c7260b76e5d8745 -yuv444p14be a0fd8199b6a05e799c3646e6dacff968 -yuv444p14le 1107f410652e9ecb4540b3d896c1252f -yuv444p16be f285bda960402c031303d8da5ab2f5f6 -yuv444p16le dd72a55624c37d955bc66f54dd7d0770 -yuv444p9be 02fac80656a1aa16573ac89bf3bcb2ae -yuv444p9le f9009efe8e174f7b62edd9496d375af9 -yuva420p 99559efdc598a611e8a445726aae52df -yuva420p10be 5ebfba649292669bf4a42ae812811ac9 -yuva420p10le b3ca09bde07e20e6674390f7946b6e93 -yuva420p16be 10d49b187aa0e9f6980c0fe2583a403f -yuva420p16le 8520c00011f8040ce3d760b4d73bdf40 -yuva420p9be ab70cda1f3ae2822a70e84fec2130f6e -yuva420p9le 70b5fc0e4b4d48c36530ea4ef1e3353b -yuva422p 05fb65386a03cd61094348b15cd4bc8c -yuva422p10be 3ffe3b85704883bbf9666b06afa0e1dc -yuva422p10le 47a89fc53f0777f8cb973ccd25f2f09e -yuva422p16be 805df2b4709283b34002b25e2e229e0a -yuva422p16le 675315e192ded36ccec229a4aea28e89 -yuva422p9be aedf684bcacc4e2375622ba9fd4f3846 -yuva422p9le 41aa087d23cfa8fae5a4e6406442fa8f -yuva444p 70d4cba3980d5a1c16d5c29526e71ee5 -yuva444p10be a0e80fe85810531348352b47ba4b712d -yuva444p10le c0caa122748be4a1467ce0f0600165cc -yuva444p16be 5722e1a5b09b3808e5bbd9a7db1add49 -yuva444p16le 342725e837355d66019ec05ffa5b6c4c -yuva444p9be bcea6ad30ced293dbba9d7a6780d52ec -yuva444p9le bbd56cf86dadd7db8625d3679c6acc45 -yuvj411p 8c6457a0ec6d796884e88f88ae17c9e3 -yuvj420p 06d3226d86dbd01cd359d8a1507d0e6b -yuvj422p 8f87a2f4261297545b53b3f237c5bf1a -yuvj440p 92c7d84f41d703878ae53911d03d23c9 -yuvj444p 1eda19f660d5902e047bb8c43f182fb3 +yuv410p 029701cd3d50df12570653d3b77bf9c8 +yuv411p d5e669b8a135a410296550159eab2bd9 +yuv420p 3c1682586b331a417c62e2632976c6a5 +yuv420p10be 474a2392e5deda2782a6d14f66e28322 +yuv420p10le d6bf2a10e76799c53e342dc95eb2b2fa +yuv420p12be ccc4d59eb775a435210d5144cf213bbb +yuv420p12le 1d46c041c178f7c3ba721c9f0300e5c7 +yuv420p14be d6d90762c9bf75b93a8d0f01bf88e67c +yuv420p14le d382dcc2a618dac825bd42e876e10ef2 +yuv420p16be 837daa01ca24e468ada8f424dcba0baf +yuv420p16le 83ebf761e5ba7c459daf2b3a8044a1d1 +yuv420p9be 009f38d02a5ed45a73eab6ee50cf7ddd +yuv420p9le f4247ce765b00e604198fdda072151f6 +yuv422p 9001a9e63f6f13b8d7e62fd3c7cc76be +yuv422p10be 40c4629543181e284db0c27f79608b5b +yuv422p10le 4e8b6b36ce914fa566f9baea1e191698 +yuv422p12be 1ec959d0dc26928c6fb93925353a7c81 +yuv422p12le 3ef47dc70087949daf4355b62c1adecd +yuv422p14be 5462e9b00c0782893967c3ed2da317a6 +yuv422p14le 8cef92b54ca51982386becad2f2edc0e +yuv422p16be a9021704027340b1f21e62348568657e +yuv422p16le fb8e5aff474eca0b9b4bba0ab5765158 +yuv422p9be 2d27809e85655e5ce9db5f194d617069 +yuv422p9le 13f42a98d4c6c57883d6817329ec3ea7 +yuv440p 44c7ad06592e46b42143756210798d7d +yuv444p 49587b263a4c8da66ddc267f746b7041 +yuv444p10be 6589db276e865800614153e43bad3da8 +yuv444p10le 8e17f00cbc47188e007b59e568bf13aa +yuv444p12be a1b9df9b367da1abaf20058e0946f70d +yuv444p12le 5b0fee31978851ee4b15adda9d09f59d +yuv444p14be eea4f1fd5d04b16b323b2797b6fc5496 +yuv444p14le 824f6014212cd804d7495cdac8accaa2 +yuv444p16be 2c3a255d9260d93b56c3df1a7793b05f +yuv444p16le 51a7e2cbf1c331317fb0768902d8eed2 +yuv444p9be 873e54e3b96b5de22eb55a7e0de8d16e +yuv444p9le 2e0347745b5352669c743df386cf7e8e +yuva420p 382e6ba313b1e5ec8140ba85b67739d9 +yuva420p10be 7fd81a2920475845956f906079bb858c +yuva420p10le 0a443a68ae124617ad8b429285f55707 +yuva420p16be 4bc4032b56eb8c671d3896d743cf9230 +yuva420p16le 8789993f7975cb397b4135c68d2eac47 +yuva420p9be 511a9f068d44504aeafdd024425e27e1 +yuva420p9le 71aedf72c65d0e7d8adf23d4cec0be9a +yuva422p 812466f48c19e6c75eae9f77c7d37146 +yuva422p10be c303a9890caa41a28809a81b96ee9be0 +yuva422p10le 889b8ffc52c49a71452d217cd426e82d +yuva422p16be fabad5519e983469396bf39cbdfdc8e3 +yuva422p16le 7a48c3b8e75b6a9e0817c9c5026795ea +yuva422p9be ea95ab08a41a0f5028293d01b7633099 +yuva422p9le a374569c2cfb4cc29bf699d8a58fab03 +yuva444p 980451d431db7a978ed145b07877a4fb +yuva444p10be b2eb903bfa5aaf4d7ef1a760f5bda4a9 +yuva444p10le 7f08e6e6f9be8bbb685ec073a1c26c0b +yuva444p16be 25853e6375b3b284596db23489e03fac +yuva444p16le 771c8bda1d8d52d4c26e88513b7aa85a +yuva444p9be bb61d7a428671b51f1a3ca2789cc09af +yuva444p9le 901b1d1fd58173437690e371ba5a78e4 +yuvj411p 08f897f81c4532e39415d6b1a473cbb2 +yuvj420p 0abdb9835e118c368a12c7c1b0d9b3e2 +yuvj422p b3e33fd45ddeab175e9719ca10586113 +yuvj440p 128a7ab2aba6f84809a3f36ea671b4dd +yuvj444p 02092a8f68e0e202bb94869d828e32fc diff --git a/tests/ref/fate/filter-pixfmts-tinterlace_merge b/tests/ref/fate/filter-pixfmts-tinterlace_merge index 2dba4ceb7..526b77f40 100644 --- a/tests/ref/fate/filter-pixfmts-tinterlace_merge +++ b/tests/ref/fate/filter-pixfmts-tinterlace_merge @@ -1,14 +1,14 @@ -gray 6575994300fa6c32755e68a9c7398247 -yuv410p c9bad1317b496071d6d895238638e07d -yuv411p aeab23fbe2fa1a509fb45d873759819b -yuv420p 9794d11e59ec7bcdf9e30a433e4137b1 -yuv422p e852e61e455db8ee3981ea942d510b0f -yuv440p 7d74a024260b8676492cec372293c64a -yuv444p a38a3f65d2f358cde5e9547c897cfcd5 -yuva420p c1dc15d6ee78587d9f825acd795673d7 -yuva422p efba80640dc04e9cbb27078ce084d397 -yuva444p 3e4158d682df2da3d07134946d082f67 -yuvj420p 3ee7014727ee64b45292a4f15ba028d8 -yuvj422p 4f990d5473f15571276adb5770b3b773 -yuvj440p 9a005e8b8431aaa762fde8d942fd11a9 -yuvj444p e29bf9f42e3a3632e09df529979e0040 +gray 330feb7cbe8ede999b93ac802012058a +yuv410p c5dac1d3f5a7a51310795daf1ac57992 +yuv411p 2fe635d25d77d7d107ddd9ad2ae1a863 +yuv420p aea7ee5c4dc21d17c833c5390d9f22ba +yuv422p 5820321e6a49c72677003163a8fd5ebb +yuv440p 1011e599e6f2c8095d46ed28d74ae74d +yuv444p 4602f8acdea686aee4c281d7305831c9 +yuva420p b7258aaa6de3492642008fff075ecb2c +yuva422p b4691c4c3b1bfc9adb5b1d855aadec81 +yuva444p a83646df12b4674d732e17b93b538be2 +yuvj420p 40b23e9f290aa5fc536337bda1e55118 +yuvj422p 036400f7fdafc1964582811b11677330 +yuvj440p 572bd7e96fe7fc6df118bb213e168f80 +yuvj444p 867f5851eb22ad7d3032333219e8133b diff --git a/tests/ref/fate/filter-pixfmts-tinterlace_pad b/tests/ref/fate/filter-pixfmts-tinterlace_pad index f642e3d3a..da0eae634 100644 --- a/tests/ref/fate/filter-pixfmts-tinterlace_pad +++ b/tests/ref/fate/filter-pixfmts-tinterlace_pad @@ -1,14 +1,14 @@ -gray 28646014a43963751d1862332972f60d -yuv410p 17163d1b4f21d894598fc62e6aeb8141 -yuv411p f4d71c30c21d6a6f99079f7dd83abc6b -yuv420p f8bbae33295741c1c17d33ff8ee16f7f -yuv422p 4fa67d1580d3453942bb0950c5784f6e -yuv440p e0ee9b11a8cb7b95f82d91235593d49d -yuv444p f0558305fb7ca65b5b86d3ee88c4201e -yuva420p 7c76c0ca03a62275d25e8140c68da2b9 -yuva422p 0e4295715852540e26188a4452d5d215 -yuva444p 59d5236aeac03a6bbef7c536a22d18b6 -yuvj420p b5b7baf11946a2265fc56e48be5b0436 -yuvj422p 2e70ab700851d12a773f926bb1785235 -yuvj440p 93319f9c8a02ee793966fae40f7e42fd -yuvj444p 81a124fffe0214bee5205c90ae0dd201 +gray 7f0b876b010cc2211e0ae44f88c8eb14 +yuv410p 7412fe273dc17de5cf23dc14465b0a99 +yuv411p d41ad065ed5c07a33da876c3ac16fc65 +yuv420p 2d3a4843548f89f2d8855a4f2de76827 +yuv422p 3c0ec17893996a99520a1226a7ea0105 +yuv440p e0474bb9e49906d44c7b2d62d23edc85 +yuv444p f7dc9731dd13fc2de16878444efc52d9 +yuva420p 6b3cd0f2231af767a83090a34f3996fc +yuva422p 7369cf26a49b7711d92f418d10d0dbc4 +yuva444p 33c742fc331cd3bb0599a866a38595da +yuvj420p 287eb3cc6982e43839098fcafe5347b8 +yuvj422p 1d442127a0bc27c8d4c1ed0173d58102 +yuvj440p 1c5dcc66f8bc75104fb7e00078ec85bc +yuvj444p 833430eaf6cca94d98170eb289f4bd28 diff --git a/tests/ref/fate/filter-pixfmts-vflip b/tests/ref/fate/filter-pixfmts-vflip index 07d2bb765..847cc5564 100644 --- a/tests/ref/fate/filter-pixfmts-vflip +++ b/tests/ref/fate/filter-pixfmts-vflip @@ -1,116 +1,119 @@ -0bgr 30d1f7d7081c012556da0373e6d389ee -0rgb 66cd838e9c19f750c61efd73f66c42ac -abgr e6cc18ed21293e455d1dc63f9e1645e4 -argb b5383d783698a0b3d753d01f2498e490 -bgr0 f99729e70a94d1c278c292a7acdddae5 -bgr24 c48ec71c68a9840572a548c2ad141028 -bgr444be ab9253d2f836f58ff8f3f2b4ec76abdc -bgr444le b1bd8245a286b615e75e10d34fda4e62 -bgr48be b5355b4fa578b9422288507cf7fba2b6 -bgr48le 11dc232500b6339f58a9981f46d1d7a9 -bgr4_byte 531fd9a2249a213c89b1afc9788d070e -bgr555be 54ba55dc1dcc5a7f27f2727976be6583 -bgr555le a45c637fe5ce84b238b1e6f66fc8c852 -bgr565be 7100c2ddfee42e7efafec1ccefecf7c6 -bgr565le 9fab295d966386d4ef99d5b43066da47 -bgr8 275ce12eeb05de67a6915f67cbb43ce5 -bgra d29c35871248c476c366e678db580982 -gbrap 29844a8e4334493fdd2d499bcb532535 -gbrp d3f2823513bfdac8f714385513cc396b -gbrp10be 49b93ac01777e4bafcb9afd4d9d74533 -gbrp10le 61c0cbb0978d26494d3a233042e1e256 -gbrp12be 36f58621c2a10141cdae56c82cd99946 -gbrp12le 33dd0c50bc6c9cec92e8afcce076dff3 -gbrp14be 488b314f58b3e41d67c1b093ce19a7fb -gbrp14le 48b4273ff29b6b68a05a6027254ff75e -gbrp9be b4361a1ad66cdff0d32d4af769a8a960 -gbrp9le 5bc148ca18ff1bf7095e78a4e65ed8ab -gray 800813149a825964025e75cf14ec528b -gray16be 03fdfc40a4fd25252f1b03d9358f00ef -gray16le ebcd797559fef441e5baeff4e7a02472 -monob c395a8efb9477b4ec53a77326e41ccd7 -monow efaee1c763ccd5ce1a8519d2ed5aa5a9 -nv12 77373304a9c732b65dab0a33afba9295 -nv21 1e70b3ce8be75f91f465a6d62df550c3 -pal8 be51ffaaad8e8428f2ce1e10d5729d3d -rgb0 84a83e576fc59ffd1ac5549fd7aa0023 -rgb24 a00171a51cbbdcc61ecbd0198b2e2513 -rgb444be 09a819863d3fe75518376cdac01c069f -rgb444le 4ab35fc85b8550be2a9b96dec9bf7306 -rgb48be 97a30a902d26b4840235926dae9028dd -rgb48le 82b33a864bab70d5463d57eaf693e78c -rgb4_byte afbfab537406988eab7460ec748a0389 -rgb555be 95e417e9429622245e2d2e0b1c3ab3e4 -rgb555le e4b35d8e9c1710f6d051fb4bda8700cc -rgb565be c70d86afbd68a073f2d4fe0eee3a9832 -rgb565le 991576c5d3308a73068a826543b3e7af -rgb8 42230235c5a2a66c0f9a2fcd20f9f5cd -rgba a6973a2940a378d2a8284194da26eec0 -rgba64be 52ee01b66ee3d52e4726a12fbb819950 -rgba64le 60541d81afcea71a27629c4e5d137dcb -uyvy422 21c48162379321bb83ec2399535f9253 -xyz12be 3c00294e1e56ac7673226c75faafc247 -xyz12le edfc0b6dd18510d9dd605a83d74ba5b9 -yuv410p 8699f50c04f8ac931aa5a8306827364b -yuv411p 47af34559b92b68851df4c2b170f7736 -yuv420p c59b35b82b5a195128736021913b35a4 -yuv420p10be fc5eed1744cdd033728362772a450e32 -yuv420p10le 141e6b39adac979765c846f3a5a8293c -yuv420p12be 0e0145d3592d56362c1bcc62cbd78a78 -yuv420p12le 8c3a2b27126df203786d4e05fd79e269 -yuv420p14be 6a11c75aa378f9628cd8fc3339474e68 -yuv420p14le e8b683876508bc0371582e2b8c0eb191 -yuv420p16be c467fae3a1936f3f91c19dd1c0c63e49 -yuv420p16le 87f09595ac106e694c538382179bfcc5 -yuv420p9be 31bc440f64fdd8d9e7cba897881345ec -yuv420p9le c6fed3016f03c49aa01bdcd63f846d3a -yuv422p 5e48541d3e659046ac0e1eacb038485f -yuv422p10be 9097b4d06f1fc598375b7c6480a2ba50 -yuv422p10le da7bd36f65cac06bd54bc9857493d835 -yuv422p12be 9c0fd650ec9872fbe06e82dc41a7399f -yuv422p12le 3bdb982268c06b8876e206d8b89b4583 -yuv422p14be bb0fc25212c2aa9f273aad2d562c3384 -yuv422p14le 1f89e82da25ce459db456ed27631054f -yuv422p16be 95ed65e718929dbeb5092bf0d852026d -yuv422p16le c62e554dde4a170177bec2efc3f4f1a2 -yuv422p9be b249cd58eaab5ccac6bae3e184774362 -yuv422p9le 696fc2a55f155edaaa9fc289574b2bb8 -yuv440p fca8395b7e43e2d0f38dd6ba822ef747 -yuv444p 1ef971a434c53e81c578e3c7cb9cbcad -yuv444p10be 3114a7469c2b9c440a9a9ccbd6e167d6 -yuv444p10le 34cb8774a1eb627b5f32825ac7d0ae9a -yuv444p12be 2fd83655c3223d176243d7ff871df3cc -yuv444p12le cfec541fde2894656f6b3401177b7604 -yuv444p14be 11671a128afd177e5eda13bd2e93ac26 -yuv444p14le 5aefe5d3f78e4f3b86ed7041a20f9b8e -yuv444p16be 35340098dc6956c34afce17bc6ffcedd -yuv444p16le 201e3acfa6f7628dfe2a1663de1128b1 -yuv444p9be 6143c321929ade9e0bc93ddea926e936 -yuv444p9le e43ba2026848ec803fabf74d77c10125 -yuva420p dc8fd115eaf203a3eac351b92a7d8f18 -yuva420p10be b3aaa8a5c9b9c3c9d66053159af3ec99 -yuva420p10le f7a8ae85fcac45db1f1689a1ab7cc63e -yuva420p16be b5c54895e87521f65a298d33bab5eb08 -yuva420p16le 95e208bc6644e23a2126ac5fca085f06 -yuva420p9be 1ba55d16f060bf54698dd7200523b44f -yuva420p9le 4b57b8bd1534743f6740502c74bef385 -yuva422p 6091f9c62a121c09eadb02e9173b2da2 -yuva422p10be a6e8352978f263ea89e63ad06a9339b1 -yuva422p10le ee39cfa1d29c294dc096f739bf454478 -yuva422p16be 3fa019b3d5e6dcb7c8e338837b9cffe1 -yuva422p16le 871f244989e14f5d3eda45abb6b3dfd1 -yuva422p9be 923c816778f782ff8a56bcd1b14ef08d -yuva422p9le bd882d40af0369d9ef7891c8e7891024 -yuva444p 9a55e83047abcc7a709f20805070135e -yuva444p10be 6258901ef2ddfdb526a1038d92e8b63c -yuva444p10le 24b8ef0f63e60f0f0a4d47a5870ad773 -yuva444p16be 4699a802e8ea3e74e968122980c0b0b0 -yuva444p16le 6f54a8cff38c54a235b92a0f1314e0aa -yuva444p9be 7472bb4b0c774d5d741035086d5e4330 -yuva444p9le ae11ddd5a3e8d69a36989f6f2a8897a1 -yuvj411p be518349f35aa67e048b854ff2da60c4 -yuvj420p 200b0332de9944e76c94d2e0699a5a2d -yuvj422p a19a89ef145305cf224ef5aa247d075a -yuvj440p 4240c9348d28af5f3edd0e642002bd2c -yuvj444p 9e11298ba9c4faae0f5c81420d2123f2 -yuyv422 867fff568fa4170503779c48e5f25e6e +0bgr d7f264cac771432a25fa943aff095c5a +0rgb 00b65b68edef9ba563f0738453e342da +abgr 97b62a09a7e19e2f1d8a056303ea9b20 +argb c84d9d20e9a88adb2eb1d5c1ff640f5c +bgr0 258027340baeee1dfff2c7cda1a96e01 +bgr24 101889812392a4ed72fd4c49bbe49571 +bgr444be 9de20b03634f0f4755e17a4f5f4d5779 +bgr444le 1034410821ac7ce05f7c4825ae7c436a +bgr48be 9aa28ad8f52b7b4cfd5bec421aac3597 +bgr48le ea833f8f7be21b907d733c1b6cce6f69 +bgr4_byte 18bd6511f1e9699888114b47899bede9 +bgr555be 62c978a01dc9c38d68db62e3e6d50a15 +bgr555le bd86a6180de15d421cad1f3748c0c432 +bgr565be 21f35c3720bac8be76557378af6b4982 +bgr565le 12d65b77a0d88f39fb8e2d410c96a52a +bgr8 0fbbb8598ad9ec69944c7b8c0714eecc +bgra 4e61f5f149d19c964c34fda94958b6ab +bgra64be cbc87591652d5be459cc4afb75cb6ccb +bgra64le 1111426757016491bd790e8fe341418b +gbrap d69032f319b8c5c6427070f4f964fdbe +gbrp 6a1825f47d5301c4756d61bc368f4260 +gbrp10be fe6c50f04325ac990b0e85be64135363 +gbrp10le 7ff6825b3df868263caae7035892dbe9 +gbrp12be 0d9612a71854b2777b2e8549f07bf9d2 +gbrp12le f00801ff735ef409fd9826bb65d56ce6 +gbrp14be 0db0c750faa92da731ed088ee8c046d1 +gbrp14le 8e7f0ac52b130228b43df3eec8ab2c1d +gbrp9be 0cf496a35e029b6c4a547661f3ce6dc8 +gbrp9le d45b29752301b6ddbdcbcf896c7475d8 +gray 49e378255356b1b642cb76ba9c006e0e +gray16be e0e2c9dde127ea410e7d930fd329ef6a +gray16le 877c610baca60a8f64848a94e3b975a4 +monob 1b1830c7283af9696a576c59fb40836e +monow 4ccd9f821466493d918e9834783cb13e +nv12 97d95f7055cdee9f69cee1abe6c8241b +nv21 c9d640860ea278486d0a0fc1c9e10d52 +pal8 b7c18ad02487ab7f8ce8bf14491ff450 +rgb0 acf4913303d81b03ddf7a3c9749922ee +rgb24 a5c724922dc2d431e50a323cfd0246cc +rgb444be 5236f07cbc576b8abd502994cf273493 +rgb444le 75b0f34a04a98857bb0b275d40fbba22 +rgb48be 93dda593c25905b7ddd5532580ffe4e9 +rgb48le e37363ee038eec9fe3c0f87f9bd52871 +rgb4_byte 0d16108350a75b0a530e40058676e269 +rgb555be 0fb532a86368f85a669c5d3d8e63ad38 +rgb555le b135d8d18d276a8c06def67c47ef72df +rgb565be 3c6570ae71c4a43b28a8462eb33e428f +rgb565le 95c7bd6ac8bacad78a2252ac79a15470 +rgb8 2bb00e664b00fbe94d4b589ddb9c74ab +rgba 1484910f0ca35cc686e6ac1fc271c70a +rgba64be ce4e73b7dc6f67693f06ac6baa1d28dc +rgba64le 34f23188309117e0619a16c2535edc98 +uyvy422 8cc384aa6d5eeef990034363337b1639 +xyz12be ca70be1c52a0435b83f815c2d95b0c1b +xyz12le 9a95c4551d3f99f5cf0a54231bc32d33 +yuv410p 4adc2e0d8637002378cd2fe96aaa74cf +yuv411p 5af542946ce00b7e741bbdd3dfd957e4 +yuv420p d5b8595bc10291e6230185904d77ebf9 +yuv420p10be 09a4fa9d5f7b34058045e3707db49717 +yuv420p10le 507501aad32169107ab56dd28bf1d4ce +yuv420p12be dd737564b938565450a717f87d4617f2 +yuv420p12le a8c63f8e6ccf9c216b7b707c41acddeb +yuv420p14be c9f5a477855fd651fb2458b85f7d8abe +yuv420p14le 8a559dd6ec6a27ee736bccdf2cc042ad +yuv420p16be 5780b999dbcee5fdf8d7aaac46e30624 +yuv420p16le b34fa2d224560dc6dcc67f6ee73204a3 +yuv420p9be d97241dbe6747b17377734506090ccd6 +yuv420p9le ce70f75be8a3b8ac128062aa95abd65e +yuv422p ec52f5e684eb3f2304dab75894ef742a +yuv422p10be ee8d61f272aa8700213b504b0e34f16c +yuv422p10le dc7fbc426d2e30ddd21ec4fd7b7f43aa +yuv422p12be 2d8075d3b4ae74f9a9860b170c07d26b +yuv422p12le 2e441892e37e1d3e9b94488723766492 +yuv422p14be b163fa01d688c6bcbb6b77bd6e8a1cb6 +yuv422p14le 06c9cc5e79c1d99ef4d58652c6acc1d5 +yuv422p16be 92e966a93d68ea591cd54730978d7f48 +yuv422p16le d3d1ff9c78b6d1dda8e5529aa881e254 +yuv422p9be b910bf8de09521e2935749fa68fbcf8e +yuv422p9le 98d13d3db47da9be9f666ce773f2eed9 +yuv440p aba0a5eda16ce1050175bb1151900a4c +yuv444p 81a72d37cdfba65c7a2dfccaf21cd0d8 +yuv444p10be a10191d92e5a08983bec906d8fbb505a +yuv444p10le 6367be8bb534416105e450a54ae2efbf +yuv444p12be 54bcddf538435a8cb9873710d5f3f629 +yuv444p12le 6e8be3148d3e9faf993fed042d063f60 +yuv444p14be a960d66036cc20be0f35dfaf69054f17 +yuv444p14le a607ca2fcb3f662cc2059b5f70c8bb03 +yuv444p16be aee08d16e3efdaa7f0bfe73126a11a23 +yuv444p16le 25be0fc8a7081440b1bef9b4398f4364 +yuv444p9be 3ea6ead34f243fb2d776caeda1571b7a +yuv444p9le c6fe7f4a77396035be00add0c4ae0eb7 +yuva420p b5b6c3691ecb4cde7e8fb0db0fa58436 +yuva420p10be 9cec28d706cfa9e4cf687adf38fcb437 +yuva420p10le d865d58d6ec7c385be8939e0fb06dcc5 +yuva420p16be 17e321712b97997551cee0d6c93883b0 +yuva420p16le 587f054f353f3c37c2a6554a546d3e6c +yuva420p9be 2e7fc142cc1c10d5c49db628b745dc6f +yuva420p9le ab44ecd3051398545b492de1b9c6781a +yuva422p 2fa2fbe8e495ef0123d5ae5005c1bb3a +yuva422p10be 8a8553eef2fbbf5ba0a9472f4aaac397 +yuva422p10le 8c84582c47e333d4406b4638a1e9ca28 +yuva422p16be 4b21870437fd45811b42436ec24c22f0 +yuva422p16le c10435c3cae6631c4d5200bb6d4fd427 +yuva422p9be 30fa3a052a24b6eddded347656a820c7 +yuva422p9le 948e60c4e9d5aca07fc2675520da4e1f +yuva444p 9808d67ac9d32ae98aaa7c0e99894a87 +yuva444p10be 9315b16190771ba62ce09f59b6c0424b +yuva444p10le 418ec9aea69613173aadac19097924a3 +yuva444p16be 6cac8b62ee44176f71397b8f42691447 +yuva444p16le 1c5acdf9a2d18e8e5cca7b3ab0393985 +yuva444p9be e72f6776db5d1a9f46df3acb3069f88d +yuva444p9le 09503c3d5f66c5b2d4dede3976121ff9 +yuvj411p 544fb79d4a831b22424fba46e51b6ecc +yuvj420p d55b1e0d10d3cb467488cce54d9adbe9 +yuvj422p d85777d10b281236f6e83a0362f1f69a +yuvj440p 29dc5524ee438c06066905165ba0e1a0 +yuvj444p 847c2ae3a37309b3d88f757dded973f1 +yuyv422 c1cf8865677f66e1b2592229754f4595 +yvyu422 a9df408e5f1963a4187c113ca0416d87 diff --git a/tests/ref/fate/filter-pp b/tests/ref/fate/filter-pp index 1f7efefad..fa37774c3 100644 --- a/tests/ref/fate/filter-pp +++ b/tests/ref/fate/filter-pp @@ -1 +1 @@ -pp 62a6acf1969155f29249fd0757540f9f +pp 3730f1ed7bf244ce059d110e21f39bbd diff --git a/tests/ref/fate/filter-pp2 b/tests/ref/fate/filter-pp2 index b32bd1a7b..257f0a712 100644 --- a/tests/ref/fate/filter-pp2 +++ b/tests/ref/fate/filter-pp2 @@ -1 +1 @@ -pp2 efcfe545df8f869e3a93ae25a3e08967 +pp2 975d4c1d489e42ddbd4a27464e8355af diff --git a/tests/ref/fate/filter-pp3 b/tests/ref/fate/filter-pp3 index ccf2eebc6..00d4595f3 100644 --- a/tests/ref/fate/filter-pp3 +++ b/tests/ref/fate/filter-pp3 @@ -1 +1 @@ -pp3 39af1a30d0ea0e906df264773adfcaa6 +pp3 f38fdc2dfa4c8d889918efe6d7a7ac3a diff --git a/tests/ref/fate/filter-pp4 b/tests/ref/fate/filter-pp4 index 0557ca608..61d2fc8d4 100644 --- a/tests/ref/fate/filter-pp4 +++ b/tests/ref/fate/filter-pp4 @@ -1 +1 @@ -pp4 d79a3727359f62747edb82cc92ed040b +pp4 0a2895c619ab9c6c22fd7cffb25070a8 diff --git a/tests/ref/fate/filter-pp5 b/tests/ref/fate/filter-pp5 index 4265566a6..d528c0984 100644 --- a/tests/ref/fate/filter-pp5 +++ b/tests/ref/fate/filter-pp5 @@ -1 +1 @@ -pp5 5dc5a1f0c67d8a78e32cf50f47d1b27f +pp5 5fc6703d42bd98942e5dd104ce220291 diff --git a/tests/ref/fate/filter-pp6 b/tests/ref/fate/filter-pp6 index ca4002476..46474daca 100644 --- a/tests/ref/fate/filter-pp6 +++ b/tests/ref/fate/filter-pp6 @@ -1 +1 @@ -pp6 40fb584b10082dff87fb947a1bccdbef +pp6 93b508d07bfcf4703aa7dff2d2ef5c03 diff --git a/tests/ref/fate/filter-scale200 b/tests/ref/fate/filter-scale200 index f26752237..45d0a0407 100644 --- a/tests/ref/fate/filter-scale200 +++ b/tests/ref/fate/filter-scale200 @@ -1 +1 @@ -scale200 e84ce966038a9f8f915704959f64278d +scale200 27f58ed67924a4dabf16d9c15cdf9a77 diff --git a/tests/ref/fate/filter-scale500 b/tests/ref/fate/filter-scale500 index ec4a699a9..a885dd43a 100644 --- a/tests/ref/fate/filter-scale500 +++ b/tests/ref/fate/filter-scale500 @@ -1 +1 @@ -scale500 24e89b23ba4286162c2026181db8d2b7 +scale500 fd3a84a8832f7e1f34b714837986de7d diff --git a/tests/ref/fate/filter-select b/tests/ref/fate/filter-select index a9d2be00c..b5913fef0 100644 --- a/tests/ref/fate/filter-select +++ b/tests/ref/fate/filter-select @@ -1 +1 @@ -select 7975bb8d0e326af9369379927324f1a6 +select 01a2ff59ce9f6601b05b853b0d3128c1 diff --git a/tests/ref/fate/filter-setdar b/tests/ref/fate/filter-setdar index 5bc7d5d34..e9ef8352b 100644 --- a/tests/ref/fate/filter-setdar +++ b/tests/ref/fate/filter-setdar @@ -1 +1 @@ -setdar 04b06d4622b116cdae756d4b475b9d5d +setdar 0f778c1cc72a8d03598d7de535fcb4b5 diff --git a/tests/ref/fate/filter-setsar b/tests/ref/fate/filter-setsar index 86592e865..189cf815c 100644 --- a/tests/ref/fate/filter-setsar +++ b/tests/ref/fate/filter-setsar @@ -1 +1 @@ -setsar 04b06d4622b116cdae756d4b475b9d5d +setsar 0f778c1cc72a8d03598d7de535fcb4b5 diff --git a/tests/ref/fate/filter-shuffleplanes-dup-luma b/tests/ref/fate/filter-shuffleplanes-dup-luma new file mode 100644 index 000000000..52041fad2 --- /dev/null +++ b/tests/ref/fate/filter-shuffleplanes-dup-luma @@ -0,0 +1,51 @@ +#tb 0: 1/25 +0, 0, 0, 1, 405504, 0x76625893 +0, 1, 1, 1, 405504, 0x348f0b97 +0, 2, 2, 1, 405504, 0x3de02149 +0, 3, 3, 1, 405504, 0x8f5b309a +0, 4, 4, 1, 405504, 0xf6faac89 +0, 5, 5, 1, 405504, 0x8f562eb6 +0, 6, 6, 1, 405504, 0xeb369913 +0, 7, 7, 1, 405504, 0xa78f1ff6 +0, 8, 8, 1, 405504, 0x8a1f1db6 +0, 9, 9, 1, 405504, 0xde649414 +0, 10, 10, 1, 405504, 0x154073e5 +0, 11, 11, 1, 405504, 0xedd73de2 +0, 12, 12, 1, 405504, 0x603df766 +0, 13, 13, 1, 405504, 0x53bd93be +0, 14, 14, 1, 405504, 0xa4e31e4e +0, 15, 15, 1, 405504, 0x9496c889 +0, 16, 16, 1, 405504, 0xe780a133 +0, 17, 17, 1, 405504, 0xea0d6297 +0, 18, 18, 1, 405504, 0x36f1fa5c +0, 19, 19, 1, 405504, 0x6b6b1138 +0, 20, 20, 1, 405504, 0x4f604471 +0, 21, 21, 1, 405504, 0x60ae7fac +0, 22, 22, 1, 405504, 0x200ae239 +0, 23, 23, 1, 405504, 0x8f2417b7 +0, 24, 24, 1, 405504, 0x360e40dc +0, 25, 25, 1, 405504, 0xef67325e +0, 26, 26, 1, 405504, 0x4cc83a45 +0, 27, 27, 1, 405504, 0x5064bad4 +0, 28, 28, 1, 405504, 0xecfe4d14 +0, 29, 29, 1, 405504, 0x0a848f79 +0, 30, 30, 1, 405504, 0xa92ff299 +0, 31, 31, 1, 405504, 0xa6ce59e7 +0, 32, 32, 1, 405504, 0x9b519b8e +0, 33, 33, 1, 405504, 0xf2d1a500 +0, 34, 34, 1, 405504, 0x51b13a4f +0, 35, 35, 1, 405504, 0xbe4e20dd +0, 36, 36, 1, 405504, 0x1a7af6c9 +0, 37, 37, 1, 405504, 0x34d76fc1 +0, 38, 38, 1, 405504, 0x8f00b0f8 +0, 39, 39, 1, 405504, 0xe1eb6bec +0, 40, 40, 1, 405504, 0xd01880ea +0, 41, 41, 1, 405504, 0xa659a20a +0, 42, 42, 1, 405504, 0xfed88666 +0, 43, 43, 1, 405504, 0xd239109c +0, 44, 44, 1, 405504, 0x54233dd0 +0, 45, 45, 1, 405504, 0x3cc1a86a +0, 46, 46, 1, 405504, 0x0744316d +0, 47, 47, 1, 405504, 0xcc1c8360 +0, 48, 48, 1, 405504, 0x0af419f7 +0, 49, 49, 1, 405504, 0x80e5d952 diff --git a/tests/ref/fate/filter-shuffleplanes-swapuv b/tests/ref/fate/filter-shuffleplanes-swapuv new file mode 100644 index 000000000..95da149ad --- /dev/null +++ b/tests/ref/fate/filter-shuffleplanes-swapuv @@ -0,0 +1,51 @@ +#tb 0: 1/25 +0, 0, 0, 1, 152064, 0x68b189ef +0, 1, 1, 1, 152064, 0x5cc66551 +0, 2, 2, 1, 152064, 0x88f0f64a +0, 3, 3, 1, 152064, 0x195780b0 +0, 4, 4, 1, 152064, 0xeff7b652 +0, 5, 5, 1, 152064, 0x6548a8e6 +0, 6, 6, 1, 152064, 0x48667c23 +0, 7, 7, 1, 152064, 0x7ca88bac +0, 8, 8, 1, 152064, 0xa3dc8026 +0, 9, 9, 1, 152064, 0x51233915 +0, 10, 10, 1, 152064, 0xf8ef4760 +0, 11, 11, 1, 152064, 0x5d51fcd5 +0, 12, 12, 1, 152064, 0x5c56ad61 +0, 13, 13, 1, 152064, 0x96b7a223 +0, 14, 14, 1, 152064, 0xb6ed8ddd +0, 15, 15, 1, 152064, 0xf7f80f05 +0, 16, 16, 1, 152064, 0x695d4e18 +0, 17, 17, 1, 152064, 0x9af438c8 +0, 18, 18, 1, 152064, 0x3fcc6acc +0, 19, 19, 1, 152064, 0xd0ccdbff +0, 20, 20, 1, 152064, 0xe4f5f570 +0, 21, 21, 1, 152064, 0x342c2412 +0, 22, 22, 1, 152064, 0x45a51d59 +0, 23, 23, 1, 152064, 0x58d768ef +0, 24, 24, 1, 152064, 0xebacf9d6 +0, 25, 25, 1, 152064, 0x23ff9936 +0, 26, 26, 1, 152064, 0x7e9196b5 +0, 27, 27, 1, 152064, 0xe862d887 +0, 28, 28, 1, 152064, 0xaf1aa455 +0, 29, 29, 1, 152064, 0xcfca650e +0, 30, 30, 1, 152064, 0xe3506aca +0, 31, 31, 1, 152064, 0xd7f0c51e +0, 32, 32, 1, 152064, 0x1358fc8d +0, 33, 33, 1, 152064, 0xeeb77a30 +0, 34, 34, 1, 152064, 0xa7c34378 +0, 35, 35, 1, 152064, 0x8d6794fb +0, 36, 36, 1, 152064, 0x9c6a37ab +0, 37, 37, 1, 152064, 0xad9b01f8 +0, 38, 38, 1, 152064, 0xa913594c +0, 39, 39, 1, 152064, 0xb6f34edd +0, 40, 40, 1, 152064, 0x4c4a5925 +0, 41, 41, 1, 152064, 0x262a9e08 +0, 42, 42, 1, 152064, 0x1fbdbfa9 +0, 43, 43, 1, 152064, 0xc94620ec +0, 44, 44, 1, 152064, 0x33310471 +0, 45, 45, 1, 152064, 0x02bd7e73 +0, 46, 46, 1, 152064, 0x308c53ff +0, 47, 47, 1, 152064, 0x11b4c5c2 +0, 48, 48, 1, 152064, 0x4fefb483 +0, 49, 49, 1, 152064, 0x9edbd8ea diff --git a/tests/ref/fate/filter-thumbnail b/tests/ref/fate/filter-thumbnail index 5cfbf50e4..36f11f297 100644 --- a/tests/ref/fate/filter-thumbnail +++ b/tests/ref/fate/filter-thumbnail @@ -1 +1 @@ -thumbnail 33c479d5701943253df5e6adc6bc8746 +thumbnail cd429b3d92c33bcc257e8e6a3284dbf7 diff --git a/tests/ref/fate/filter-tile b/tests/ref/fate/filter-tile index 376acfc1c..8319d5b2c 100644 --- a/tests/ref/fate/filter-tile +++ b/tests/ref/fate/filter-tile @@ -1 +1 @@ -tile bfd98570151154d078b14398f867f0e8 +tile c9f419f3b0813d50c85186b776d0bd85 diff --git a/tests/ref/fate/filter-vflip b/tests/ref/fate/filter-vflip index ee492477a..f21976a91 100644 --- a/tests/ref/fate/filter-vflip +++ b/tests/ref/fate/filter-vflip @@ -1 +1 @@ -vflip c59b35b82b5a195128736021913b35a4 +vflip d5b8595bc10291e6230185904d77ebf9 diff --git a/tests/ref/fate/filter-vflip_crop b/tests/ref/fate/filter-vflip_crop index 43c944ada..0e201d6d3 100644 --- a/tests/ref/fate/filter-vflip_crop +++ b/tests/ref/fate/filter-vflip_crop @@ -1 +1 @@ -vflip_crop cd56578bb7e89ca0853467dfecab244b +vflip_crop 4458d2c260df9748524ac0d74d18fdde diff --git a/tests/ref/fate/filter-vflip_vflip b/tests/ref/fate/filter-vflip_vflip index f401fc772..6fe2aa0e4 100644 --- a/tests/ref/fate/filter-vflip_vflip +++ b/tests/ref/fate/filter-vflip_vflip @@ -1 +1 @@ -vflip_vflip 61fffd2d8425759a33ae07e718d0242d +vflip_vflip 005e6ddc8a5daf11cf866a1ec76c2572 diff --git a/tests/ref/fate/filter-yadif10 b/tests/ref/fate/filter-yadif10 new file mode 100644 index 000000000..aa27bfcbb --- /dev/null +++ b/tests/ref/fate/filter-yadif10 @@ -0,0 +1,31 @@ +#tb 0: 1/25 +0, 9, 9, 1, 1244160, 0x5b49e0c0 +0, 10, 10, 1, 1244160, 0x76ba6bab +0, 11, 11, 1, 1244160, 0x0298cb8d +0, 12, 12, 1, 1244160, 0x9c81759a +0, 13, 13, 1, 1244160, 0xa239d1ae +0, 14, 14, 1, 1244160, 0x3e95ada9 +0, 15, 15, 1, 1244160, 0x8b87e8f8 +0, 16, 16, 1, 1244160, 0x64f89653 +0, 17, 17, 1, 1244160, 0x58e5d12e +0, 18, 18, 1, 1244160, 0x38b4003a +0, 19, 19, 1, 1244160, 0xc005c29c +0, 20, 20, 1, 1244160, 0x10c0c60d +0, 21, 21, 1, 1244160, 0x1b550998 +0, 22, 22, 1, 1244160, 0x7aacf6ab +0, 23, 23, 1, 1244160, 0xeb205d98 +0, 24, 24, 1, 1244160, 0x6ad2134c +0, 25, 25, 1, 1244160, 0x8aea4e56 +0, 26, 26, 1, 1244160, 0x0d910a6b +0, 27, 27, 1, 1244160, 0x749ae307 +0, 28, 28, 1, 1244160, 0x8ff7af3c +0, 29, 29, 1, 1244160, 0x9ba51b91 +0, 30, 30, 1, 1244160, 0xad476514 +0, 31, 31, 1, 1244160, 0x674481d6 +0, 32, 32, 1, 1244160, 0x0937e677 +0, 33, 33, 1, 1244160, 0x6c2c53ee +0, 34, 34, 1, 1244160, 0x524a164e +0, 35, 35, 1, 1244160, 0x77a405ab +0, 36, 36, 1, 1244160, 0xaa6b47c4 +0, 37, 37, 1, 1244160, 0x0b5ab556 +0, 38, 38, 1, 1244160, 0xbe1edab9 diff --git a/tests/ref/fate/filter-yadif16 b/tests/ref/fate/filter-yadif16 new file mode 100644 index 000000000..65427a235 --- /dev/null +++ b/tests/ref/fate/filter-yadif16 @@ -0,0 +1,31 @@ +#tb 0: 1/25 +0, 9, 9, 1, 1244160, 0xfb65caee +0, 10, 10, 1, 1244160, 0x6222e690 +0, 11, 11, 1, 1244160, 0x020ac648 +0, 12, 12, 1, 1244160, 0xb76691ca +0, 13, 13, 1, 1244160, 0xe0fd7404 +0, 14, 14, 1, 1244160, 0x3ab29705 +0, 15, 15, 1, 1244160, 0xbe807835 +0, 16, 16, 1, 1244160, 0x77d358fd +0, 17, 17, 1, 1244160, 0x359b174f +0, 18, 18, 1, 1244160, 0xe20f0e7f +0, 19, 19, 1, 1244160, 0x988966ec +0, 20, 20, 1, 1244160, 0xd078da72 +0, 21, 21, 1, 1244160, 0x276d97f7 +0, 22, 22, 1, 1244160, 0xf8ee7ca0 +0, 23, 23, 1, 1244160, 0x776bed72 +0, 24, 24, 1, 1244160, 0xb9bf92b2 +0, 25, 25, 1, 1244160, 0x30e01094 +0, 26, 26, 1, 1244160, 0xbc5f3139 +0, 27, 27, 1, 1244160, 0x44324902 +0, 28, 28, 1, 1244160, 0x64aab8f5 +0, 29, 29, 1, 1244160, 0x0a05aeac +0, 30, 30, 1, 1244160, 0x31e5aa36 +0, 31, 31, 1, 1244160, 0xa685405f +0, 32, 32, 1, 1244160, 0x54a6e776 +0, 33, 33, 1, 1244160, 0x9af4d8c9 +0, 34, 34, 1, 1244160, 0xf709ac9a +0, 35, 35, 1, 1244160, 0x12a9441d +0, 36, 36, 1, 1244160, 0xf3f1bd5e +0, 37, 37, 1, 1244160, 0x7bcef716 +0, 38, 38, 1, 1244160, 0xe3a2f129 diff --git a/tests/ref/fate/force_key_frames b/tests/ref/fate/force_key_frames index b93adcaf1..863e7468c 100644 --- a/tests/ref/fate/force_key_frames +++ b/tests/ref/fate/force_key_frames @@ -1,4 +1,4 @@ -5423335cd809e631a2e03f97585348e0 *tests/data/fate/force_key_frames.avi +74daf0c27174418b74191fd855a631e8 *tests/data/fate/force_key_frames.avi 113308 tests/data/fate/force_key_frames.avi 8f68ad2e602ecd87a3e0c097ba99d773 *tests/data/fate/force_key_frames.out.framecrc stddev:34363.01 PSNR: 5.61 MAXDIFF:56305 bytes: 7603200/ 186 diff --git a/tests/ref/fate/gif-color b/tests/ref/fate/gif-color index 6abb56578..555918653 100644 --- a/tests/ref/fate/gif-color +++ b/tests/ref/fate/gif-color @@ -1,174 +1,174 @@ -#tb 0: 1/100 +#tb 0: 1/10 0, 0, 0, 1, 188356, 0xf0944065 -0, 10, 10, 1, 188356, 0x146ed4c4 -0, 20, 20, 1, 188356, 0x96866a6f -0, 30, 30, 1, 188356, 0xe15e1f1c -0, 40, 40, 1, 188356, 0x0662c1d0 -0, 50, 50, 1, 188356, 0x88fa6cc4 -0, 60, 60, 1, 188356, 0x3cce2f71 -0, 70, 70, 1, 188356, 0x1510f9f3 -0, 80, 80, 1, 188356, 0xf27e9fa8 -0, 90, 90, 1, 188356, 0x0f4b64a2 -0, 100, 100, 1, 188356, 0x3d2714a5 -0, 110, 110, 1, 188356, 0x392ce45d -0, 120, 120, 1, 188356, 0x2eadb79f -0, 130, 130, 1, 188356, 0x68109314 -0, 140, 140, 1, 188356, 0x4eca71ac -0, 150, 150, 1, 188356, 0xa9aa5907 -0, 160, 160, 1, 188356, 0x2a5d08c0 -0, 170, 170, 1, 188356, 0x942bba84 -0, 180, 180, 1, 188356, 0xbee38983 -0, 190, 190, 1, 188356, 0xa0d65a5a -0, 200, 200, 1, 188356, 0x47270bee -0, 210, 210, 1, 188356, 0xc020dc40 -0, 220, 220, 1, 188356, 0x978dbc8f -0, 230, 230, 1, 188356, 0x6b1e9f1b -0, 240, 240, 1, 188356, 0xd8078bf4 -0, 250, 250, 1, 188356, 0x94ca7bd7 -0, 260, 260, 1, 188356, 0xac745e77 -0, 270, 270, 1, 188356, 0x73154f2c -0, 280, 280, 1, 188356, 0x31200601 -0, 290, 290, 1, 188356, 0x6525dd42 -0, 300, 300, 1, 188356, 0xa29b985a -0, 310, 310, 1, 188356, 0xe3e074d8 -0, 320, 320, 1, 188356, 0xb87b3222 -0, 330, 330, 1, 188356, 0x5b9a11f2 -0, 340, 340, 1, 188356, 0x25f7f8c9 -0, 350, 350, 1, 188356, 0x0235e93c -0, 360, 360, 1, 188356, 0x2a42d643 -0, 370, 370, 1, 188356, 0xfb7acddb -0, 380, 380, 1, 188356, 0xecbbbf5e -0, 390, 390, 1, 188356, 0xeba4bc9a -0, 400, 400, 1, 188356, 0x4317b36b -0, 410, 410, 1, 188356, 0x7316ae1a -0, 420, 420, 1, 188356, 0xb5ccad05 -0, 430, 430, 1, 188356, 0x38afb0dc -0, 440, 440, 1, 188356, 0xf11cad55 -0, 450, 450, 1, 188356, 0x3d77b400 -0, 460, 460, 1, 188356, 0xf084b9b9 -0, 470, 470, 1, 188356, 0x02a4c584 -0, 480, 480, 1, 188356, 0x14f4d52e -0, 490, 490, 1, 188356, 0x55118432 -0, 500, 500, 1, 188356, 0x4ad82e9f -0, 510, 510, 1, 188356, 0xc6eafc52 -0, 520, 520, 1, 188356, 0xf4bdc575 -0, 530, 530, 1, 188356, 0x8429689e -0, 540, 540, 1, 188356, 0xaa23019e -0, 550, 550, 1, 188356, 0xaf52c3a5 -0, 560, 560, 1, 188356, 0x1d387c32 -0, 570, 570, 1, 188356, 0x543d5cd2 -0, 580, 580, 1, 188356, 0x8cdb399c -0, 590, 590, 1, 188356, 0xcceb292f -0, 600, 600, 1, 188356, 0xa87115e8 -0, 610, 610, 1, 188356, 0x9665ec8f -0, 620, 620, 1, 188356, 0xad99baf4 -0, 630, 630, 1, 188356, 0xc6e5a2b5 -0, 640, 640, 1, 188356, 0xe2a48359 -0, 650, 650, 1, 188356, 0x3a270df0 -0, 660, 660, 1, 188356, 0xcc34826b -0, 670, 670, 1, 188356, 0x15ec2dcc -0, 680, 680, 1, 188356, 0x8874c5f9 -0, 690, 690, 1, 188356, 0x829966e8 -0, 700, 700, 1, 188356, 0x691f1ebb -0, 710, 710, 1, 188356, 0x00e3e184 -0, 720, 720, 1, 188356, 0x97739332 -0, 730, 730, 1, 188356, 0x507769aa -0, 740, 740, 1, 188356, 0xddfb3069 -0, 750, 750, 1, 188356, 0x7296f749 -0, 760, 760, 1, 188356, 0x0555ca32 -0, 770, 770, 1, 188356, 0x4554c683 -0, 780, 780, 1, 188356, 0x2398c10f -0, 790, 790, 1, 188356, 0x1c5ccfa0 -0, 800, 800, 1, 188356, 0xa580f3c8 -0, 810, 810, 1, 188356, 0x4fadea78 -0, 820, 820, 1, 188356, 0x4a57db38 -0, 830, 830, 1, 188356, 0x9e98df6d -0, 840, 840, 1, 188356, 0xfeb3dec9 -0, 850, 850, 1, 188356, 0xbf16ef7a -0, 860, 860, 1, 188356, 0xdc23fc48 -0, 870, 870, 1, 188356, 0x3bf2e401 -0, 880, 880, 1, 188356, 0xc832bcf4 -0, 890, 890, 1, 188356, 0x977db44f -0, 900, 900, 1, 188356, 0x18d39d96 -0, 910, 910, 1, 188356, 0x9adf60d8 -0, 920, 920, 1, 188356, 0x567b667a -0, 930, 930, 1, 188356, 0xd4a45e8e -0, 940, 940, 1, 188356, 0x94a24cc7 -0, 950, 950, 1, 188356, 0x086f0a53 -0, 960, 960, 1, 188356, 0xcbf3ebcb -0, 970, 970, 1, 188356, 0x1a40a7b9 -0, 980, 980, 1, 188356, 0xe16d8964 -0, 990, 990, 1, 188356, 0x3edd7dfa -0, 1000, 1000, 1, 188356, 0xba417fa5 -0, 1010, 1010, 1, 188356, 0x734a7611 -0, 1020, 1020, 1, 188356, 0xfa1e7b1e -0, 1030, 1030, 1, 188356, 0x1af23355 -0, 1040, 1040, 1, 188356, 0x28d41390 -0, 1050, 1050, 1, 188356, 0x2838c58d -0, 1060, 1060, 1, 188356, 0x4e2ba2a8 -0, 1070, 1070, 1, 188356, 0xcedc99ae -0, 1080, 1080, 1, 188356, 0xb06ba12d -0, 1090, 1090, 1, 188356, 0x38c997b6 -0, 1100, 1100, 1, 188356, 0x12dba0dc -0, 1110, 1110, 1, 188356, 0x5f86496a -0, 1120, 1120, 1, 188356, 0x0b74216d -0, 1130, 1130, 1, 188356, 0xdbddbada -0, 1140, 1140, 1, 188356, 0x7d168af2 -0, 1150, 1150, 1, 188356, 0x22d4462b -0, 1160, 1160, 1, 188356, 0xc248265d -0, 1170, 1170, 1, 188356, 0x37a41b0d -0, 1180, 1180, 1, 188356, 0x9ebd24f1 -0, 1190, 1190, 1, 188356, 0xf21f1633 -0, 1200, 1200, 1, 188356, 0x1db62004 -0, 1210, 1210, 1, 188356, 0xcc241ac1 -0, 1220, 1220, 1, 188356, 0x224d2637 -0, 1230, 1230, 1, 188356, 0x1bd8390c -0, 1240, 1240, 1, 188356, 0xd8e64966 -0, 1250, 1250, 1, 188356, 0x96e66287 -0, 1260, 1260, 1, 188356, 0xa83c9a32 -0, 1270, 1270, 1, 188356, 0x3a5faeba -0, 1280, 1280, 1, 188356, 0x8200cd87 -0, 1290, 1290, 1, 188356, 0x6326e591 -0, 1300, 1300, 1, 188356, 0xb5d70993 -0, 1310, 1310, 1, 188356, 0x954d5da2 -0, 1320, 1320, 1, 188356, 0x38b1788b -0, 1330, 1330, 1, 188356, 0x4aafa131 -0, 1340, 1340, 1, 188356, 0xaff2be78 -0, 1350, 1350, 1, 188356, 0x9bd7eb69 -0, 1360, 1360, 1, 188356, 0x0d2b17c9 -0, 1370, 1370, 1, 188356, 0xf5d8a764 -0, 1380, 1380, 1, 188356, 0xa302dfb2 -0, 1390, 1390, 1, 188356, 0xe8a32ac1 -0, 1400, 1400, 1, 188356, 0x50a8470d -0, 1410, 1410, 1, 188356, 0x52826061 -0, 1420, 1420, 1, 188356, 0x26e88798 -0, 1430, 1430, 1, 188356, 0x1448acb8 -0, 1440, 1440, 1, 188356, 0xfb380972 -0, 1450, 1450, 1, 188356, 0x184976e8 -0, 1460, 1460, 1, 188356, 0xa349a871 -0, 1470, 1470, 1, 188356, 0x617ed8b1 -0, 1480, 1480, 1, 188356, 0xb6bc1425 -0, 1490, 1490, 1, 188356, 0xafe74efd -0, 1500, 1500, 1, 188356, 0x0b8b61e5 -0, 1510, 1510, 1, 188356, 0xc6ad67a7 -0, 1520, 1520, 1, 188356, 0x4da186fe -0, 1530, 1530, 1, 188356, 0xe08f9975 -0, 1540, 1540, 1, 188356, 0xa43f8ba4 -0, 1550, 1550, 1, 188356, 0xcad4b6b5 -0, 1560, 1560, 1, 188356, 0x7e70d51e -0, 1570, 1570, 1, 188356, 0x429b0b5b -0, 1580, 1580, 1, 188356, 0xea92350d -0, 1590, 1590, 1, 188356, 0x9a7440f8 -0, 1600, 1600, 1, 188356, 0x63a2be6e -0, 1610, 1610, 1, 188356, 0x59b64b50 -0, 1620, 1620, 1, 188356, 0x63c4a10e -0, 1630, 1630, 1, 188356, 0x6146e5e0 -0, 1640, 1640, 1, 188356, 0x603b2ae5 -0, 1650, 1650, 1, 188356, 0x818bc774 -0, 1660, 1660, 1, 188356, 0xa5ce278f -0, 1670, 1670, 1, 188356, 0x4d85684d -0, 1680, 1680, 1, 188356, 0xbbda9cad -0, 1690, 1690, 1, 188356, 0xfee2e78e -0, 1700, 1700, 1, 188356, 0x681d2635 -0, 1710, 1710, 1, 188356, 0x05354903 -0, 1720, 1720, 1, 188356, 0x8eecac99 +0, 1, 1, 1, 188356, 0x146ed4c4 +0, 2, 2, 1, 188356, 0x96866a6f +0, 3, 3, 1, 188356, 0xe15e1f1c +0, 4, 4, 1, 188356, 0x0662c1d0 +0, 5, 5, 1, 188356, 0x88fa6cc4 +0, 6, 6, 1, 188356, 0x3cce2f71 +0, 7, 7, 1, 188356, 0x1510f9f3 +0, 8, 8, 1, 188356, 0xf27e9fa8 +0, 9, 9, 1, 188356, 0x0f4b64a2 +0, 10, 10, 1, 188356, 0x3d2714a5 +0, 11, 11, 1, 188356, 0x392ce45d +0, 12, 12, 1, 188356, 0x2eadb79f +0, 13, 13, 1, 188356, 0x68109314 +0, 14, 14, 1, 188356, 0x4eca71ac +0, 15, 15, 1, 188356, 0xa9aa5907 +0, 16, 16, 1, 188356, 0x2a5d08c0 +0, 17, 17, 1, 188356, 0x942bba84 +0, 18, 18, 1, 188356, 0xbee38983 +0, 19, 19, 1, 188356, 0xa0d65a5a +0, 20, 20, 1, 188356, 0x47270bee +0, 21, 21, 1, 188356, 0xc020dc40 +0, 22, 22, 1, 188356, 0x978dbc8f +0, 23, 23, 1, 188356, 0x6b1e9f1b +0, 24, 24, 1, 188356, 0xd8078bf4 +0, 25, 25, 1, 188356, 0x94ca7bd7 +0, 26, 26, 1, 188356, 0xac745e77 +0, 27, 27, 1, 188356, 0x73154f2c +0, 28, 28, 1, 188356, 0x31200601 +0, 29, 29, 1, 188356, 0x6525dd42 +0, 30, 30, 1, 188356, 0xa29b985a +0, 31, 31, 1, 188356, 0xe3e074d8 +0, 32, 32, 1, 188356, 0xb87b3222 +0, 33, 33, 1, 188356, 0x5b9a11f2 +0, 34, 34, 1, 188356, 0x25f7f8c9 +0, 35, 35, 1, 188356, 0x0235e93c +0, 36, 36, 1, 188356, 0x2a42d643 +0, 37, 37, 1, 188356, 0xfb7acddb +0, 38, 38, 1, 188356, 0xecbbbf5e +0, 39, 39, 1, 188356, 0xeba4bc9a +0, 40, 40, 1, 188356, 0x4317b36b +0, 41, 41, 1, 188356, 0x7316ae1a +0, 42, 42, 1, 188356, 0xb5ccad05 +0, 43, 43, 1, 188356, 0x38afb0dc +0, 44, 44, 1, 188356, 0xf11cad55 +0, 45, 45, 1, 188356, 0x3d77b400 +0, 46, 46, 1, 188356, 0xf084b9b9 +0, 47, 47, 1, 188356, 0x02a4c584 +0, 48, 48, 1, 188356, 0x14f4d52e +0, 49, 49, 1, 188356, 0x55118432 +0, 50, 50, 1, 188356, 0x4ad82e9f +0, 51, 51, 1, 188356, 0xc6eafc52 +0, 52, 52, 1, 188356, 0xf4bdc575 +0, 53, 53, 1, 188356, 0x8429689e +0, 54, 54, 1, 188356, 0xaa23019e +0, 55, 55, 1, 188356, 0xaf52c3a5 +0, 56, 56, 1, 188356, 0x1d387c32 +0, 57, 57, 1, 188356, 0x543d5cd2 +0, 58, 58, 1, 188356, 0x8cdb399c +0, 59, 59, 1, 188356, 0xcceb292f +0, 60, 60, 1, 188356, 0xa87115e8 +0, 61, 61, 1, 188356, 0x9665ec8f +0, 62, 62, 1, 188356, 0xad99baf4 +0, 63, 63, 1, 188356, 0xc6e5a2b5 +0, 64, 64, 1, 188356, 0xe2a48359 +0, 65, 65, 1, 188356, 0x3a270df0 +0, 66, 66, 1, 188356, 0xcc34826b +0, 67, 67, 1, 188356, 0x15ec2dcc +0, 68, 68, 1, 188356, 0x8874c5f9 +0, 69, 69, 1, 188356, 0x829966e8 +0, 70, 70, 1, 188356, 0x691f1ebb +0, 71, 71, 1, 188356, 0x00e3e184 +0, 72, 72, 1, 188356, 0x97739332 +0, 73, 73, 1, 188356, 0x507769aa +0, 74, 74, 1, 188356, 0xddfb3069 +0, 75, 75, 1, 188356, 0x7296f749 +0, 76, 76, 1, 188356, 0x0555ca32 +0, 77, 77, 1, 188356, 0x4554c683 +0, 78, 78, 1, 188356, 0x2398c10f +0, 79, 79, 1, 188356, 0x1c5ccfa0 +0, 80, 80, 1, 188356, 0xa580f3c8 +0, 81, 81, 1, 188356, 0x4fadea78 +0, 82, 82, 1, 188356, 0x4a57db38 +0, 83, 83, 1, 188356, 0x9e98df6d +0, 84, 84, 1, 188356, 0xfeb3dec9 +0, 85, 85, 1, 188356, 0xbf16ef7a +0, 86, 86, 1, 188356, 0xdc23fc48 +0, 87, 87, 1, 188356, 0x3bf2e401 +0, 88, 88, 1, 188356, 0xc832bcf4 +0, 89, 89, 1, 188356, 0x977db44f +0, 90, 90, 1, 188356, 0x18d39d96 +0, 91, 91, 1, 188356, 0x9adf60d8 +0, 92, 92, 1, 188356, 0x567b667a +0, 93, 93, 1, 188356, 0xd4a45e8e +0, 94, 94, 1, 188356, 0x94a24cc7 +0, 95, 95, 1, 188356, 0x086f0a53 +0, 96, 96, 1, 188356, 0xcbf3ebcb +0, 97, 97, 1, 188356, 0x1a40a7b9 +0, 98, 98, 1, 188356, 0xe16d8964 +0, 99, 99, 1, 188356, 0x3edd7dfa +0, 100, 100, 1, 188356, 0xba417fa5 +0, 101, 101, 1, 188356, 0x734a7611 +0, 102, 102, 1, 188356, 0xfa1e7b1e +0, 103, 103, 1, 188356, 0x1af23355 +0, 104, 104, 1, 188356, 0x28d41390 +0, 105, 105, 1, 188356, 0x2838c58d +0, 106, 106, 1, 188356, 0x4e2ba2a8 +0, 107, 107, 1, 188356, 0xcedc99ae +0, 108, 108, 1, 188356, 0xb06ba12d +0, 109, 109, 1, 188356, 0x38c997b6 +0, 110, 110, 1, 188356, 0x12dba0dc +0, 111, 111, 1, 188356, 0x5f86496a +0, 112, 112, 1, 188356, 0x0b74216d +0, 113, 113, 1, 188356, 0xdbddbada +0, 114, 114, 1, 188356, 0x7d168af2 +0, 115, 115, 1, 188356, 0x22d4462b +0, 116, 116, 1, 188356, 0xc248265d +0, 117, 117, 1, 188356, 0x37a41b0d +0, 118, 118, 1, 188356, 0x9ebd24f1 +0, 119, 119, 1, 188356, 0xf21f1633 +0, 120, 120, 1, 188356, 0x1db62004 +0, 121, 121, 1, 188356, 0xcc241ac1 +0, 122, 122, 1, 188356, 0x224d2637 +0, 123, 123, 1, 188356, 0x1bd8390c +0, 124, 124, 1, 188356, 0xd8e64966 +0, 125, 125, 1, 188356, 0x96e66287 +0, 126, 126, 1, 188356, 0xa83c9a32 +0, 127, 127, 1, 188356, 0x3a5faeba +0, 128, 128, 1, 188356, 0x8200cd87 +0, 129, 129, 1, 188356, 0x6326e591 +0, 130, 130, 1, 188356, 0xb5d70993 +0, 131, 131, 1, 188356, 0x954d5da2 +0, 132, 132, 1, 188356, 0x38b1788b +0, 133, 133, 1, 188356, 0x4aafa131 +0, 134, 134, 1, 188356, 0xaff2be78 +0, 135, 135, 1, 188356, 0x9bd7eb69 +0, 136, 136, 1, 188356, 0x0d2b17c9 +0, 137, 137, 1, 188356, 0xf5d8a764 +0, 138, 138, 1, 188356, 0xa302dfb2 +0, 139, 139, 1, 188356, 0xe8a32ac1 +0, 140, 140, 1, 188356, 0x50a8470d +0, 141, 141, 1, 188356, 0x52826061 +0, 142, 142, 1, 188356, 0x26e88798 +0, 143, 143, 1, 188356, 0x1448acb8 +0, 144, 144, 1, 188356, 0xfb380972 +0, 145, 145, 1, 188356, 0x184976e8 +0, 146, 146, 1, 188356, 0xa349a871 +0, 147, 147, 1, 188356, 0x617ed8b1 +0, 148, 148, 1, 188356, 0xb6bc1425 +0, 149, 149, 1, 188356, 0xafe74efd +0, 150, 150, 1, 188356, 0x0b8b61e5 +0, 151, 151, 1, 188356, 0xc6ad67a7 +0, 152, 152, 1, 188356, 0x4da186fe +0, 153, 153, 1, 188356, 0xe08f9975 +0, 154, 154, 1, 188356, 0xa43f8ba4 +0, 155, 155, 1, 188356, 0xcad4b6b5 +0, 156, 156, 1, 188356, 0x7e70d51e +0, 157, 157, 1, 188356, 0x429b0b5b +0, 158, 158, 1, 188356, 0xea92350d +0, 159, 159, 1, 188356, 0x9a7440f8 +0, 160, 160, 1, 188356, 0x63a2be6e +0, 161, 161, 1, 188356, 0x59b64b50 +0, 162, 162, 1, 188356, 0x63c4a10e +0, 163, 163, 1, 188356, 0x6146e5e0 +0, 164, 164, 1, 188356, 0x603b2ae5 +0, 165, 165, 1, 188356, 0x818bc774 +0, 166, 166, 1, 188356, 0xa5ce278f +0, 167, 167, 1, 188356, 0x4d85684d +0, 168, 168, 1, 188356, 0xbbda9cad +0, 169, 169, 1, 188356, 0xfee2e78e +0, 170, 170, 1, 188356, 0x681d2635 +0, 171, 171, 1, 188356, 0x05354903 +0, 172, 172, 1, 188356, 0x8eecac99 diff --git a/tests/ref/fate/gif-disposal-background b/tests/ref/fate/gif-disposal-background index dbfaa48f6..838745b79 100644 --- a/tests/ref/fate/gif-disposal-background +++ b/tests/ref/fate/gif-disposal-background @@ -1,6 +1,6 @@ -#tb 0: 1/100 +#tb 0: 1/2 0, 0, 0, 1, 10368, 0x8b200cc8 -0, 50, 50, 1, 10368, 0x4e208e4f -0, 100, 100, 1, 10368, 0x044dba8b -0, 150, 150, 1, 10368, 0x1d617e09 -0, 200, 200, 1, 10368, 0xae38a6d2 +0, 1, 1, 1, 10368, 0x4e208e4f +0, 2, 2, 1, 10368, 0x044dba8b +0, 3, 3, 1, 10368, 0x1d617e09 +0, 4, 4, 1, 10368, 0xae38a6d2 diff --git a/tests/ref/fate/gif-disposal-restore b/tests/ref/fate/gif-disposal-restore index 0ce4112f2..c5ebfcb53 100644 --- a/tests/ref/fate/gif-disposal-restore +++ b/tests/ref/fate/gif-disposal-restore @@ -1,4 +1,3 @@ -#tb 0: 1/100 +#tb 0: 1/1 0, 0, 0, 1, 112320, 0xb8afe429 -0, 10, 10, 1, 112320, 0xae588a4b -0, 310, 310, 1, 112320, 0xccdd27b7 +0, 3, 3, 1, 112320, 0xccdd27b7 diff --git a/tests/ref/fate/gifenc-bgr4_byte b/tests/ref/fate/gifenc-bgr4_byte index dceaf5212..c0d39bdec 100644 --- a/tests/ref/fate/gifenc-bgr4_byte +++ b/tests/ref/fate/gifenc-bgr4_byte @@ -1,174 +1,174 @@ -#tb 0: 1/100 +#tb 0: 1/10 0, 0, 0, 1, 508, 0xa1b80fc0 -0, 10, 10, 1, 213, 0x4f554bd7, S=1, 1024, 0xb6327c81 -0, 20, 20, 1, 131, 0x283b2988, S=1, 1024, 0xae3a7c81 -0, 30, 30, 1, 384, 0xc4fea72a, S=1, 1024, 0xb6327c81 -0, 40, 40, 1, 381, 0x050ba2b8, S=1, 1024, 0x9e4a7c81 -0, 50, 50, 1, 430, 0x00cfb2ae, S=1, 1024, 0x9e4a7c81 -0, 60, 60, 1, 518, 0xc8e5d827, S=1, 1024, 0x9e4a7c81 -0, 70, 70, 1, 535, 0x326ce62a, S=1, 1024, 0x9e4a7c81 -0, 80, 80, 1, 438, 0x34d6b7c0, S=1, 1024, 0xb6327c81 -0, 90, 90, 1, 923, 0x9fb1a37c, S=1, 1024, 0xb6327c81 -0, 100, 100, 1, 694, 0xf20449a5, S=1, 1024, 0xb6327c81 -0, 110, 110, 1, 1194, 0x67cd2ab5, S=1, 1024, 0xb6327c81 -0, 120, 120, 1, 1291, 0x1d23539d, S=1, 1024, 0xb6327c81 -0, 130, 130, 1, 1245, 0x065f32e6, S=1, 1024, 0xb6327c81 -0, 140, 140, 1, 1330, 0x83ec51a4, S=1, 1024, 0xb6327c81 -0, 150, 150, 1, 1276, 0x2acf38dc, S=1, 1024, 0xb6327c81 -0, 160, 160, 1, 1475, 0x4cd197ef, S=1, 1024, 0xb6327c81 -0, 170, 170, 1, 1784, 0xd1e84ae6, S=1, 1024, 0xde0a7c81 -0, 180, 180, 1, 1675, 0x092dfa86, S=1, 1024, 0xde0a7c81 -0, 190, 190, 1, 1509, 0x639aaa00, S=1, 1024, 0xde0a7c81 -0, 200, 200, 1, 1705, 0xfd3719d5, S=1, 1024, 0xde0a7c81 -0, 210, 210, 1, 1745, 0x8a761db4, S=1, 1024, 0xde0a7c81 -0, 220, 220, 1, 1642, 0x18830245, S=1, 1024, 0xde0a7c81 -0, 230, 230, 1, 1718, 0x3c8d1ebe, S=1, 1024, 0xde0a7c81 -0, 240, 240, 1, 1900, 0x2ea879d1, S=1, 1024, 0xde0a7c81 -0, 250, 250, 1, 1807, 0x02b35230, S=1, 1024, 0xde0a7c81 -0, 260, 260, 1, 1915, 0x22d48344, S=1, 1024, 0xde0a7c81 -0, 270, 270, 1, 2100, 0x55fcd063, S=1, 1024, 0xde0a7c81 -0, 280, 280, 1, 2700, 0x7cc5f08b, S=1, 1024, 0xde0a7c81 -0, 290, 290, 1, 2673, 0xb997a80d, S=1, 1024, 0xde0a7c81 -0, 300, 300, 1, 2895, 0xab69484d, S=1, 1024, 0xde0a7c81 -0, 310, 310, 1, 3257, 0xf753cf24, S=1, 1024, 0xde0a7c81 -0, 320, 320, 1, 3179, 0x34f2c13b, S=1, 1024, 0xde0a7c81 -0, 330, 330, 1, 3296, 0x7c06e72f, S=1, 1024, 0xde0a7c81 -0, 340, 340, 1, 3600, 0x4ca67634, S=1, 1024, 0xde0a7c81 -0, 350, 350, 1, 3699, 0xabe89fe3, S=1, 1024, 0xde0a7c81 -0, 360, 360, 1, 3814, 0x1869d3f4, S=1, 1024, 0xde0a7c81 -0, 370, 370, 1, 3627, 0x19bd7da7, S=1, 1024, 0xde0a7c81 -0, 380, 380, 1, 2950, 0x048a6055, S=1, 1024, 0xde0a7c81 -0, 390, 390, 1, 3086, 0x64ec8fc2, S=1, 1024, 0xde0a7c81 -0, 400, 400, 1, 3094, 0x1a388553, S=1, 1024, 0xde0a7c81 -0, 410, 410, 1, 3456, 0x01432c82, S=1, 1024, 0xde0a7c81 -0, 420, 420, 1, 4108, 0xf9505c66, S=1, 1024, 0xde0a7c81 -0, 430, 430, 1, 4217, 0x7f985ba4, S=1, 1024, 0xde0a7c81 -0, 440, 440, 1, 3613, 0xd0684d83, S=1, 1024, 0xde0a7c81 -0, 450, 450, 1, 3910, 0x0070e692, S=1, 1024, 0xde0a7c81 -0, 460, 460, 1, 4461, 0x5cc9e33d, S=1, 1024, 0xde0a7c81 -0, 470, 470, 1, 4593, 0x33a32dd1, S=1, 1024, 0xde0a7c81 -0, 480, 480, 1, 4822, 0x59549883, S=1, 1024, 0xde0a7c81 -0, 490, 490, 1, 5398, 0xb7bac31e, S=1, 1024, 0xde0a7c81 -0, 500, 500, 1, 5266, 0x21c695aa, S=1, 1024, 0xde0a7c81 -0, 510, 510, 1, 5416, 0xf305e3ed, S=1, 1024, 0xde0a7c81 -0, 520, 520, 1, 5519, 0x857d071f, S=1, 1024, 0xde0a7c81 -0, 530, 530, 1, 5701, 0x8f885c9c, S=1, 1024, 0xde0a7c81 -0, 540, 540, 1, 6160, 0x48523e83, S=1, 1024, 0xde0a7c81 -0, 550, 550, 1, 6233, 0x8fd2511e, S=1, 1024, 0xde0a7c81 -0, 560, 560, 1, 5911, 0x92d4c516, S=1, 1024, 0xde0a7c81 -0, 570, 570, 1, 5997, 0xbd7cfa15, S=1, 1024, 0xde0a7c81 -0, 580, 580, 1, 5946, 0x8f5fedff, S=1, 1024, 0xde0a7c81 -0, 590, 590, 1, 6468, 0x45c0cb8c, S=1, 1024, 0xde0a7c81 -0, 600, 600, 1, 6737, 0x4e1e39ac, S=1, 1024, 0xde0a7c81 -0, 610, 610, 1, 6275, 0x1d5e8f4c, S=1, 1024, 0xde0a7c81 -0, 620, 620, 1, 6641, 0x844b3aad, S=1, 1024, 0xde0a7c81 -0, 630, 630, 1, 6378, 0x52568640, S=1, 1024, 0xde0a7c81 -0, 640, 640, 1, 6257, 0xfabc585f, S=1, 1024, 0xde0a7c81 -0, 650, 650, 1, 6908, 0xf261701c, S=1, 1024, 0xde0a7c81 -0, 660, 660, 1, 7230, 0xb4f524ce, S=1, 1024, 0xde0a7c81 -0, 670, 670, 1, 7556, 0x89c1a712, S=1, 1024, 0xde0a7c81 -0, 680, 680, 1, 7413, 0x553970a4, S=1, 1024, 0xde0a7c81 -0, 690, 690, 1, 7476, 0x24d2a761, S=1, 1024, 0xde0a7c81 -0, 700, 700, 1, 7596, 0xf072e431, S=1, 1024, 0xde0a7c81 -0, 710, 710, 1, 7756, 0x131205c0, S=1, 1024, 0xde0a7c81 -0, 720, 720, 1, 8015, 0xf4536a7f, S=1, 1024, 0xde0a7c81 -0, 730, 730, 1, 8128, 0xba80be2b, S=1, 1024, 0xde0a7c81 -0, 740, 740, 1, 8101, 0x44ceb3a2, S=1, 1024, 0xde0a7c81 -0, 750, 750, 1, 7863, 0x55043dfd, S=1, 1024, 0xde0a7c81 -0, 760, 760, 1, 7960, 0x38399182, S=1, 1024, 0xde0a7c81 -0, 770, 770, 1, 8238, 0x1d52ecf3, S=1, 1024, 0xde0a7c81 -0, 780, 780, 1, 8321, 0xd8d24a5c, S=1, 1024, 0xde0a7c81 -0, 790, 790, 1, 8562, 0x4a0cc02b, S=1, 1024, 0xde0a7c81 -0, 800, 800, 1, 8746, 0x2db40da7, S=1, 1024, 0xde0a7c81 -0, 810, 810, 1, 8578, 0x46f9a4c1, S=1, 1024, 0xde0a7c81 -0, 820, 820, 1, 8878, 0xf58d5a19, S=1, 1024, 0xde0a7c81 -0, 830, 830, 1, 9077, 0x78de57f6, S=1, 1024, 0xde0a7c81 -0, 840, 840, 1, 9310, 0x8c10f77a, S=1, 1024, 0xde0a7c81 -0, 850, 850, 1, 9394, 0x741f431e, S=1, 1024, 0xde0a7c81 -0, 860, 860, 1, 9161, 0x6f499587, S=1, 1024, 0xde0a7c81 -0, 870, 870, 1, 9462, 0x628936c3, S=1, 1024, 0xde0a7c81 -0, 880, 880, 1, 9650, 0x4cb4936e, S=1, 1024, 0xde0a7c81 -0, 890, 890, 1, 9701, 0x5e069c40, S=1, 1024, 0xde0a7c81 -0, 900, 900, 1, 9523, 0x66a13c83, S=1, 1024, 0xde0a7c81 -0, 910, 910, 1, 9891, 0x43ea0e93, S=1, 1024, 0xde0a7c81 -0, 920, 920, 1, 10005, 0x96a849e7, S=1, 1024, 0xde0a7c81 -0, 930, 930, 1, 10038, 0x68032d25, S=1, 1024, 0xde0a7c81 -0, 940, 940, 1, 10086, 0xef59458d, S=1, 1024, 0xde0a7c81 -0, 950, 950, 1, 10438, 0x3466fed0, S=1, 1024, 0xde0a7c81 -0, 960, 960, 1, 10583, 0x8bdd5477, S=1, 1024, 0xde0a7c81 -0, 970, 970, 1, 10581, 0x69d27fee, S=1, 1024, 0xde0a7c81 -0, 980, 980, 1, 10807, 0xde62d6e3, S=1, 1024, 0xde0a7c81 -0, 990, 990, 1, 11111, 0x34eb4c13, S=1, 1024, 0xde0a7c81 -0, 1000, 1000, 1, 11194, 0x584f6b73, S=1, 1024, 0xde0a7c81 -0, 1010, 1010, 1, 11240, 0xc90ba13f, S=1, 1024, 0xde0a7c81 -0, 1020, 1020, 1, 11483, 0x59c4f3c5, S=1, 1024, 0xde0a7c81 -0, 1030, 1030, 1, 11680, 0xc62c5bc1, S=1, 1024, 0xde0a7c81 -0, 1040, 1040, 1, 11785, 0xc9bab793, S=1, 1024, 0xde0a7c81 -0, 1050, 1050, 1, 11436, 0xc9c40809, S=1, 1024, 0xde0a7c81 -0, 1060, 1060, 1, 11928, 0x4b77c9a7, S=1, 1024, 0xde0a7c81 -0, 1070, 1070, 1, 11932, 0x722abcbe, S=1, 1024, 0xde0a7c81 -0, 1080, 1080, 1, 12281, 0x0d136f53, S=1, 1024, 0xde0a7c81 -0, 1090, 1090, 1, 12334, 0x04a47f78, S=1, 1024, 0xde0a7c81 -0, 1100, 1100, 1, 12452, 0xa02db188, S=1, 1024, 0xde0a7c81 -0, 1110, 1110, 1, 12695, 0x1a813b2e, S=1, 1024, 0xde0a7c81 -0, 1120, 1120, 1, 12668, 0x81b24f79, S=1, 1024, 0xde0a7c81 -0, 1130, 1130, 1, 12957, 0x4da59f8c, S=1, 1024, 0xde0a7c81 -0, 1140, 1140, 1, 13054, 0x7abedf5a, S=1, 1024, 0xde0a7c81 -0, 1150, 1150, 1, 13147, 0x138f2bbd, S=1, 1024, 0xde0a7c81 -0, 1160, 1160, 1, 13171, 0x43c1195f, S=1, 1024, 0xde0a7c81 -0, 1170, 1170, 1, 13198, 0x2c8d58d4, S=1, 1024, 0xde0a7c81 -0, 1180, 1180, 1, 13211, 0x12c36193, S=1, 1024, 0xde0a7c81 -0, 1190, 1190, 1, 13210, 0xfe496107, S=1, 1024, 0xde0a7c81 -0, 1200, 1200, 1, 13467, 0x4d8ea128, S=1, 1024, 0xde0a7c81 -0, 1210, 1210, 1, 13665, 0x94caddde, S=1, 1024, 0xde0a7c81 -0, 1220, 1220, 1, 13692, 0xe38febd9, S=1, 1024, 0xde0a7c81 -0, 1230, 1230, 1, 13821, 0xee592e62, S=1, 1024, 0xde0a7c81 -0, 1240, 1240, 1, 13946, 0xceb09235, S=1, 1024, 0xde0a7c81 -0, 1250, 1250, 1, 14063, 0x7361d2f5, S=1, 1024, 0xde0a7c81 -0, 1260, 1260, 1, 14124, 0x226bcac1, S=1, 1024, 0xde0a7c81 -0, 1270, 1270, 1, 14331, 0x0649512b, S=1, 1024, 0xde0a7c81 -0, 1280, 1280, 1, 14469, 0x0d7da45b, S=1, 1024, 0xde0a7c81 -0, 1290, 1290, 1, 14536, 0x73cca242, S=1, 1024, 0xde0a7c81 -0, 1300, 1300, 1, 14608, 0x1f3dd14e, S=1, 1024, 0xde0a7c81 -0, 1310, 1310, 1, 14898, 0xd13d258e, S=1, 1024, 0xde0a7c81 -0, 1320, 1320, 1, 14978, 0xfa049fea, S=1, 1024, 0xde0a7c81 -0, 1330, 1330, 1, 15142, 0x1dfad60c, S=1, 1024, 0xde0a7c81 -0, 1340, 1340, 1, 15129, 0x5962bae7, S=1, 1024, 0xde0a7c81 -0, 1350, 1350, 1, 15243, 0x2c2c113b, S=1, 1024, 0xde0a7c81 -0, 1360, 1360, 1, 15337, 0x3cab623b, S=1, 1024, 0xde0a7c81 -0, 1370, 1370, 1, 15638, 0xbff3a100, S=1, 1024, 0xde0a7c81 -0, 1380, 1380, 1, 15912, 0x13bf1fb2, S=1, 1024, 0xde0a7c81 -0, 1390, 1390, 1, 16041, 0x01134246, S=1, 1024, 0xde0a7c81 -0, 1400, 1400, 1, 16228, 0xe2f80035, S=1, 1024, 0xde0a7c81 -0, 1410, 1410, 1, 16262, 0xc8d3ea51, S=1, 1024, 0xde0a7c81 -0, 1420, 1420, 1, 16371, 0xe7da07f2, S=1, 1024, 0xde0a7c81 -0, 1430, 1430, 1, 16661, 0x10ada592, S=1, 1024, 0xde0a7c81 -0, 1440, 1440, 1, 16917, 0xbfb717e5, S=1, 1024, 0xde0a7c81 -0, 1450, 1450, 1, 17149, 0x4074ca41, S=1, 1024, 0xde0a7c81 -0, 1460, 1460, 1, 17172, 0xf749b49f, S=1, 1024, 0xde0a7c81 -0, 1470, 1470, 1, 17315, 0x2abea8a0, S=1, 1024, 0xde0a7c81 -0, 1480, 1480, 1, 17397, 0x14f71122, S=1, 1024, 0xde0a7c81 -0, 1490, 1490, 1, 17431, 0xce49f2d3, S=1, 1024, 0xde0a7c81 -0, 1500, 1500, 1, 17576, 0x7c6552ad, S=1, 1024, 0xde0a7c81 -0, 1510, 1510, 1, 17764, 0x1d198d60, S=1, 1024, 0xde0a7c81 -0, 1520, 1520, 1, 17826, 0xe1727f57, S=1, 1024, 0xde0a7c81 -0, 1530, 1530, 1, 17918, 0xb78d9b9f, S=1, 1024, 0xde0a7c81 -0, 1540, 1540, 1, 17823, 0xc9fabf19, S=1, 1024, 0xde0a7c81 -0, 1550, 1550, 1, 18142, 0xeb5b21a9, S=1, 1024, 0xde0a7c81 -0, 1560, 1560, 1, 18257, 0x7b38822c, S=1, 1024, 0xde0a7c81 -0, 1570, 1570, 1, 18337, 0xd395c279, S=1, 1024, 0xde0a7c81 -0, 1580, 1580, 1, 18293, 0x6c3b3766, S=1, 1024, 0xde0a7c81 -0, 1590, 1590, 1, 18418, 0x2abcbcf8, S=1, 1024, 0xde0a7c81 -0, 1600, 1600, 1, 18607, 0x79424730, S=1, 1024, 0xde0a7c81 -0, 1610, 1610, 1, 18916, 0x8707bbc6, S=1, 1024, 0xde0a7c81 -0, 1620, 1620, 1, 19073, 0xd82c03f6, S=1, 1024, 0xde0a7c81 -0, 1630, 1630, 1, 19168, 0xb7d6fe27, S=1, 1024, 0xde0a7c81 -0, 1640, 1640, 1, 19210, 0x79f301eb, S=1, 1024, 0xde0a7c81 -0, 1650, 1650, 1, 19398, 0x0a5663c6, S=1, 1024, 0xde0a7c81 -0, 1660, 1660, 1, 19480, 0x4fe09e5b, S=1, 1024, 0xde0a7c81 -0, 1670, 1670, 1, 19659, 0xab971088, S=1, 1024, 0xde0a7c81 -0, 1680, 1680, 1, 19672, 0x2e331553, S=1, 1024, 0xde0a7c81 -0, 1690, 1690, 1, 19936, 0x2eea628a, S=1, 1024, 0xde0a7c81 -0, 1700, 1700, 1, 19975, 0xd6bb9ab2, S=1, 1024, 0xde0a7c81 -0, 1710, 1710, 1, 20021, 0xf7e98dc5, S=1, 1024, 0xde0a7c81 -0, 1720, 1720, 1, 20060, 0x20017807, S=1, 1024, 0xde0a7c81 +0, 1, 1, 1, 213, 0x4f554bd7, S=1, 1024, 0xb6327c81 +0, 2, 2, 1, 131, 0x283b2988, S=1, 1024, 0xae3a7c81 +0, 3, 3, 1, 384, 0xc4fea72a, S=1, 1024, 0xb6327c81 +0, 4, 4, 1, 381, 0x050ba2b8, S=1, 1024, 0x9e4a7c81 +0, 5, 5, 1, 430, 0x00cfb2ae, S=1, 1024, 0x9e4a7c81 +0, 6, 6, 1, 518, 0xc8e5d827, S=1, 1024, 0x9e4a7c81 +0, 7, 7, 1, 535, 0x326ce62a, S=1, 1024, 0x9e4a7c81 +0, 8, 8, 1, 438, 0x34d6b7c0, S=1, 1024, 0xb6327c81 +0, 9, 9, 1, 923, 0x9fb1a37c, S=1, 1024, 0xb6327c81 +0, 10, 10, 1, 694, 0xf20449a5, S=1, 1024, 0xb6327c81 +0, 11, 11, 1, 1194, 0x67cd2ab5, S=1, 1024, 0xb6327c81 +0, 12, 12, 1, 1291, 0x1d23539d, S=1, 1024, 0xb6327c81 +0, 13, 13, 1, 1245, 0x065f32e6, S=1, 1024, 0xb6327c81 +0, 14, 14, 1, 1330, 0x83ec51a4, S=1, 1024, 0xb6327c81 +0, 15, 15, 1, 1276, 0x2acf38dc, S=1, 1024, 0xb6327c81 +0, 16, 16, 1, 1475, 0x4cd197ef, S=1, 1024, 0xb6327c81 +0, 17, 17, 1, 1784, 0xd1e84ae6, S=1, 1024, 0xde0a7c81 +0, 18, 18, 1, 1675, 0x092dfa86, S=1, 1024, 0xde0a7c81 +0, 19, 19, 1, 1509, 0x639aaa00, S=1, 1024, 0xde0a7c81 +0, 20, 20, 1, 1705, 0xfd3719d5, S=1, 1024, 0xde0a7c81 +0, 21, 21, 1, 1745, 0x8a761db4, S=1, 1024, 0xde0a7c81 +0, 22, 22, 1, 1642, 0x18830245, S=1, 1024, 0xde0a7c81 +0, 23, 23, 1, 1718, 0x3c8d1ebe, S=1, 1024, 0xde0a7c81 +0, 24, 24, 1, 1900, 0x2ea879d1, S=1, 1024, 0xde0a7c81 +0, 25, 25, 1, 1807, 0x02b35230, S=1, 1024, 0xde0a7c81 +0, 26, 26, 1, 1915, 0x22d48344, S=1, 1024, 0xde0a7c81 +0, 27, 27, 1, 2100, 0x55fcd063, S=1, 1024, 0xde0a7c81 +0, 28, 28, 1, 2700, 0x7cc5f08b, S=1, 1024, 0xde0a7c81 +0, 29, 29, 1, 2673, 0xb997a80d, S=1, 1024, 0xde0a7c81 +0, 30, 30, 1, 2895, 0xab69484d, S=1, 1024, 0xde0a7c81 +0, 31, 31, 1, 3257, 0xf753cf24, S=1, 1024, 0xde0a7c81 +0, 32, 32, 1, 3179, 0x34f2c13b, S=1, 1024, 0xde0a7c81 +0, 33, 33, 1, 3296, 0x7c06e72f, S=1, 1024, 0xde0a7c81 +0, 34, 34, 1, 3600, 0x4ca67634, S=1, 1024, 0xde0a7c81 +0, 35, 35, 1, 3699, 0xabe89fe3, S=1, 1024, 0xde0a7c81 +0, 36, 36, 1, 3814, 0x1869d3f4, S=1, 1024, 0xde0a7c81 +0, 37, 37, 1, 3627, 0x19bd7da7, S=1, 1024, 0xde0a7c81 +0, 38, 38, 1, 2950, 0x048a6055, S=1, 1024, 0xde0a7c81 +0, 39, 39, 1, 3086, 0x64ec8fc2, S=1, 1024, 0xde0a7c81 +0, 40, 40, 1, 3094, 0x1a388553, S=1, 1024, 0xde0a7c81 +0, 41, 41, 1, 3456, 0x01432c82, S=1, 1024, 0xde0a7c81 +0, 42, 42, 1, 4108, 0xf9505c66, S=1, 1024, 0xde0a7c81 +0, 43, 43, 1, 4217, 0x7f985ba4, S=1, 1024, 0xde0a7c81 +0, 44, 44, 1, 3613, 0xd0684d83, S=1, 1024, 0xde0a7c81 +0, 45, 45, 1, 3910, 0x0070e692, S=1, 1024, 0xde0a7c81 +0, 46, 46, 1, 4461, 0x5cc9e33d, S=1, 1024, 0xde0a7c81 +0, 47, 47, 1, 4593, 0x33a32dd1, S=1, 1024, 0xde0a7c81 +0, 48, 48, 1, 4822, 0x59549883, S=1, 1024, 0xde0a7c81 +0, 49, 49, 1, 5398, 0xb7bac31e, S=1, 1024, 0xde0a7c81 +0, 50, 50, 1, 5266, 0x21c695aa, S=1, 1024, 0xde0a7c81 +0, 51, 51, 1, 5416, 0xf305e3ed, S=1, 1024, 0xde0a7c81 +0, 52, 52, 1, 5519, 0x857d071f, S=1, 1024, 0xde0a7c81 +0, 53, 53, 1, 5701, 0x8f885c9c, S=1, 1024, 0xde0a7c81 +0, 54, 54, 1, 6160, 0x48523e83, S=1, 1024, 0xde0a7c81 +0, 55, 55, 1, 6233, 0x8fd2511e, S=1, 1024, 0xde0a7c81 +0, 56, 56, 1, 5911, 0x92d4c516, S=1, 1024, 0xde0a7c81 +0, 57, 57, 1, 5997, 0xbd7cfa15, S=1, 1024, 0xde0a7c81 +0, 58, 58, 1, 5946, 0x8f5fedff, S=1, 1024, 0xde0a7c81 +0, 59, 59, 1, 6468, 0x45c0cb8c, S=1, 1024, 0xde0a7c81 +0, 60, 60, 1, 6737, 0x4e1e39ac, S=1, 1024, 0xde0a7c81 +0, 61, 61, 1, 6275, 0x1d5e8f4c, S=1, 1024, 0xde0a7c81 +0, 62, 62, 1, 6641, 0x844b3aad, S=1, 1024, 0xde0a7c81 +0, 63, 63, 1, 6378, 0x52568640, S=1, 1024, 0xde0a7c81 +0, 64, 64, 1, 6257, 0xfabc585f, S=1, 1024, 0xde0a7c81 +0, 65, 65, 1, 6908, 0xf261701c, S=1, 1024, 0xde0a7c81 +0, 66, 66, 1, 7230, 0xb4f524ce, S=1, 1024, 0xde0a7c81 +0, 67, 67, 1, 7556, 0x89c1a712, S=1, 1024, 0xde0a7c81 +0, 68, 68, 1, 7413, 0x553970a4, S=1, 1024, 0xde0a7c81 +0, 69, 69, 1, 7476, 0x24d2a761, S=1, 1024, 0xde0a7c81 +0, 70, 70, 1, 7596, 0xf072e431, S=1, 1024, 0xde0a7c81 +0, 71, 71, 1, 7756, 0x131205c0, S=1, 1024, 0xde0a7c81 +0, 72, 72, 1, 8015, 0xf4536a7f, S=1, 1024, 0xde0a7c81 +0, 73, 73, 1, 8128, 0xba80be2b, S=1, 1024, 0xde0a7c81 +0, 74, 74, 1, 8101, 0x44ceb3a2, S=1, 1024, 0xde0a7c81 +0, 75, 75, 1, 7863, 0x55043dfd, S=1, 1024, 0xde0a7c81 +0, 76, 76, 1, 7960, 0x38399182, S=1, 1024, 0xde0a7c81 +0, 77, 77, 1, 8238, 0x1d52ecf3, S=1, 1024, 0xde0a7c81 +0, 78, 78, 1, 8321, 0xd8d24a5c, S=1, 1024, 0xde0a7c81 +0, 79, 79, 1, 8562, 0x4a0cc02b, S=1, 1024, 0xde0a7c81 +0, 80, 80, 1, 8746, 0x2db40da7, S=1, 1024, 0xde0a7c81 +0, 81, 81, 1, 8578, 0x46f9a4c1, S=1, 1024, 0xde0a7c81 +0, 82, 82, 1, 8878, 0xf58d5a19, S=1, 1024, 0xde0a7c81 +0, 83, 83, 1, 9077, 0x78de57f6, S=1, 1024, 0xde0a7c81 +0, 84, 84, 1, 9310, 0x8c10f77a, S=1, 1024, 0xde0a7c81 +0, 85, 85, 1, 9394, 0x741f431e, S=1, 1024, 0xde0a7c81 +0, 86, 86, 1, 9161, 0x6f499587, S=1, 1024, 0xde0a7c81 +0, 87, 87, 1, 9462, 0x628936c3, S=1, 1024, 0xde0a7c81 +0, 88, 88, 1, 9650, 0x4cb4936e, S=1, 1024, 0xde0a7c81 +0, 89, 89, 1, 9701, 0x5e069c40, S=1, 1024, 0xde0a7c81 +0, 90, 90, 1, 9523, 0x66a13c83, S=1, 1024, 0xde0a7c81 +0, 91, 91, 1, 9891, 0x43ea0e93, S=1, 1024, 0xde0a7c81 +0, 92, 92, 1, 10005, 0x96a849e7, S=1, 1024, 0xde0a7c81 +0, 93, 93, 1, 10038, 0x68032d25, S=1, 1024, 0xde0a7c81 +0, 94, 94, 1, 10086, 0xef59458d, S=1, 1024, 0xde0a7c81 +0, 95, 95, 1, 10438, 0x3466fed0, S=1, 1024, 0xde0a7c81 +0, 96, 96, 1, 10583, 0x8bdd5477, S=1, 1024, 0xde0a7c81 +0, 97, 97, 1, 10581, 0x69d27fee, S=1, 1024, 0xde0a7c81 +0, 98, 98, 1, 10807, 0xde62d6e3, S=1, 1024, 0xde0a7c81 +0, 99, 99, 1, 11111, 0x34eb4c13, S=1, 1024, 0xde0a7c81 +0, 100, 100, 1, 11194, 0x584f6b73, S=1, 1024, 0xde0a7c81 +0, 101, 101, 1, 11240, 0xc90ba13f, S=1, 1024, 0xde0a7c81 +0, 102, 102, 1, 11483, 0x59c4f3c5, S=1, 1024, 0xde0a7c81 +0, 103, 103, 1, 11680, 0xc62c5bc1, S=1, 1024, 0xde0a7c81 +0, 104, 104, 1, 11785, 0xc9bab793, S=1, 1024, 0xde0a7c81 +0, 105, 105, 1, 11436, 0xc9c40809, S=1, 1024, 0xde0a7c81 +0, 106, 106, 1, 11928, 0x4b77c9a7, S=1, 1024, 0xde0a7c81 +0, 107, 107, 1, 11932, 0x722abcbe, S=1, 1024, 0xde0a7c81 +0, 108, 108, 1, 12281, 0x0d136f53, S=1, 1024, 0xde0a7c81 +0, 109, 109, 1, 12334, 0x04a47f78, S=1, 1024, 0xde0a7c81 +0, 110, 110, 1, 12452, 0xa02db188, S=1, 1024, 0xde0a7c81 +0, 111, 111, 1, 12695, 0x1a813b2e, S=1, 1024, 0xde0a7c81 +0, 112, 112, 1, 12668, 0x81b24f79, S=1, 1024, 0xde0a7c81 +0, 113, 113, 1, 12957, 0x4da59f8c, S=1, 1024, 0xde0a7c81 +0, 114, 114, 1, 13054, 0x7abedf5a, S=1, 1024, 0xde0a7c81 +0, 115, 115, 1, 13147, 0x138f2bbd, S=1, 1024, 0xde0a7c81 +0, 116, 116, 1, 13171, 0x43c1195f, S=1, 1024, 0xde0a7c81 +0, 117, 117, 1, 13198, 0x2c8d58d4, S=1, 1024, 0xde0a7c81 +0, 118, 118, 1, 13211, 0x12c36193, S=1, 1024, 0xde0a7c81 +0, 119, 119, 1, 13210, 0xfe496107, S=1, 1024, 0xde0a7c81 +0, 120, 120, 1, 13467, 0x4d8ea128, S=1, 1024, 0xde0a7c81 +0, 121, 121, 1, 13665, 0x94caddde, S=1, 1024, 0xde0a7c81 +0, 122, 122, 1, 13692, 0xe38febd9, S=1, 1024, 0xde0a7c81 +0, 123, 123, 1, 13821, 0xee592e62, S=1, 1024, 0xde0a7c81 +0, 124, 124, 1, 13946, 0xceb09235, S=1, 1024, 0xde0a7c81 +0, 125, 125, 1, 14063, 0x7361d2f5, S=1, 1024, 0xde0a7c81 +0, 126, 126, 1, 14124, 0x226bcac1, S=1, 1024, 0xde0a7c81 +0, 127, 127, 1, 14331, 0x0649512b, S=1, 1024, 0xde0a7c81 +0, 128, 128, 1, 14469, 0x0d7da45b, S=1, 1024, 0xde0a7c81 +0, 129, 129, 1, 14536, 0x73cca242, S=1, 1024, 0xde0a7c81 +0, 130, 130, 1, 14608, 0x1f3dd14e, S=1, 1024, 0xde0a7c81 +0, 131, 131, 1, 14898, 0xd13d258e, S=1, 1024, 0xde0a7c81 +0, 132, 132, 1, 14978, 0xfa049fea, S=1, 1024, 0xde0a7c81 +0, 133, 133, 1, 15142, 0x1dfad60c, S=1, 1024, 0xde0a7c81 +0, 134, 134, 1, 15129, 0x5962bae7, S=1, 1024, 0xde0a7c81 +0, 135, 135, 1, 15243, 0x2c2c113b, S=1, 1024, 0xde0a7c81 +0, 136, 136, 1, 15337, 0x3cab623b, S=1, 1024, 0xde0a7c81 +0, 137, 137, 1, 15638, 0xbff3a100, S=1, 1024, 0xde0a7c81 +0, 138, 138, 1, 15912, 0x13bf1fb2, S=1, 1024, 0xde0a7c81 +0, 139, 139, 1, 16041, 0x01134246, S=1, 1024, 0xde0a7c81 +0, 140, 140, 1, 16228, 0xe2f80035, S=1, 1024, 0xde0a7c81 +0, 141, 141, 1, 16262, 0xc8d3ea51, S=1, 1024, 0xde0a7c81 +0, 142, 142, 1, 16371, 0xe7da07f2, S=1, 1024, 0xde0a7c81 +0, 143, 143, 1, 16661, 0x10ada592, S=1, 1024, 0xde0a7c81 +0, 144, 144, 1, 16917, 0xbfb717e5, S=1, 1024, 0xde0a7c81 +0, 145, 145, 1, 17149, 0x4074ca41, S=1, 1024, 0xde0a7c81 +0, 146, 146, 1, 17172, 0xf749b49f, S=1, 1024, 0xde0a7c81 +0, 147, 147, 1, 17315, 0x2abea8a0, S=1, 1024, 0xde0a7c81 +0, 148, 148, 1, 17397, 0x14f71122, S=1, 1024, 0xde0a7c81 +0, 149, 149, 1, 17431, 0xce49f2d3, S=1, 1024, 0xde0a7c81 +0, 150, 150, 1, 17576, 0x7c6552ad, S=1, 1024, 0xde0a7c81 +0, 151, 151, 1, 17764, 0x1d198d60, S=1, 1024, 0xde0a7c81 +0, 152, 152, 1, 17826, 0xe1727f57, S=1, 1024, 0xde0a7c81 +0, 153, 153, 1, 17918, 0xb78d9b9f, S=1, 1024, 0xde0a7c81 +0, 154, 154, 1, 17823, 0xc9fabf19, S=1, 1024, 0xde0a7c81 +0, 155, 155, 1, 18142, 0xeb5b21a9, S=1, 1024, 0xde0a7c81 +0, 156, 156, 1, 18257, 0x7b38822c, S=1, 1024, 0xde0a7c81 +0, 157, 157, 1, 18337, 0xd395c279, S=1, 1024, 0xde0a7c81 +0, 158, 158, 1, 18293, 0x6c3b3766, S=1, 1024, 0xde0a7c81 +0, 159, 159, 1, 18418, 0x2abcbcf8, S=1, 1024, 0xde0a7c81 +0, 160, 160, 1, 18607, 0x79424730, S=1, 1024, 0xde0a7c81 +0, 161, 161, 1, 18916, 0x8707bbc6, S=1, 1024, 0xde0a7c81 +0, 162, 162, 1, 19073, 0xd82c03f6, S=1, 1024, 0xde0a7c81 +0, 163, 163, 1, 19168, 0xb7d6fe27, S=1, 1024, 0xde0a7c81 +0, 164, 164, 1, 19210, 0x79f301eb, S=1, 1024, 0xde0a7c81 +0, 165, 165, 1, 19398, 0x0a5663c6, S=1, 1024, 0xde0a7c81 +0, 166, 166, 1, 19480, 0x4fe09e5b, S=1, 1024, 0xde0a7c81 +0, 167, 167, 1, 19659, 0xab971088, S=1, 1024, 0xde0a7c81 +0, 168, 168, 1, 19672, 0x2e331553, S=1, 1024, 0xde0a7c81 +0, 169, 169, 1, 19936, 0x2eea628a, S=1, 1024, 0xde0a7c81 +0, 170, 170, 1, 19975, 0xd6bb9ab2, S=1, 1024, 0xde0a7c81 +0, 171, 171, 1, 20021, 0xf7e98dc5, S=1, 1024, 0xde0a7c81 +0, 172, 172, 1, 20060, 0x20017807, S=1, 1024, 0xde0a7c81 diff --git a/tests/ref/fate/gifenc-bgr8 b/tests/ref/fate/gifenc-bgr8 index 49db7636e..9f4a593f4 100644 --- a/tests/ref/fate/gifenc-bgr8 +++ b/tests/ref/fate/gifenc-bgr8 @@ -1,174 +1,174 @@ -#tb 0: 1/100 +#tb 0: 1/10 0, 0, 0, 1, 552, 0x271a2dd3 -0, 10, 10, 1, 297, 0x90168a95, S=1, 1024, 0xf351799f -0, 20, 20, 1, 438, 0x91efce1b, S=1, 1024, 0xf351799f -0, 30, 30, 1, 450, 0x7c2dcfad, S=1, 1024, 0xf351799f -0, 40, 40, 1, 547, 0xc131fd3b, S=1, 1024, 0xf351799f -0, 50, 50, 1, 614, 0x68182006, S=1, 1024, 0xf351799f -0, 60, 60, 1, 642, 0x78bb1f5f, S=1, 1024, 0xf351799f -0, 70, 70, 1, 660, 0x35c033a2, S=1, 1024, 0xf351799f -0, 80, 80, 1, 821, 0xaf30790b, S=1, 1024, 0xf351799f -0, 90, 90, 1, 1157, 0x741c2da1, S=1, 1024, 0xf351799f -0, 100, 100, 1, 179, 0x3a27517c, S=1, 1024, 0xf351799f -0, 110, 110, 1, 1333, 0x5ee76f3c, S=1, 1024, 0xf351799f -0, 120, 120, 1, 1638, 0x5f640e86, S=1, 1024, 0xf351799f -0, 130, 130, 1, 1531, 0xccb8e437, S=1, 1024, 0xf351799f -0, 140, 140, 1, 1720, 0xc95d45ec, S=1, 1024, 0xf351799f -0, 150, 150, 1, 1910, 0x56cc831e, S=1, 1024, 0xf351799f -0, 160, 160, 1, 2124, 0x9cc8e130, S=1, 1024, 0xf351799f -0, 170, 170, 1, 2248, 0x05a325b1, S=1, 1024, 0xf351799f -0, 180, 180, 1, 2311, 0xdc633703, S=1, 1024, 0xf351799f -0, 190, 190, 1, 2408, 0x91c26f3e, S=1, 1024, 0xf351799f -0, 200, 200, 1, 2601, 0x8cf3c157, S=1, 1024, 0xf351799f -0, 210, 210, 1, 2687, 0x8f6400e6, S=1, 1024, 0xf351799f -0, 220, 220, 1, 2784, 0xaa880e55, S=1, 1024, 0xf351799f -0, 230, 230, 1, 2884, 0x46f546f6, S=1, 1024, 0xf351799f -0, 240, 240, 1, 2982, 0x807c7ad5, S=1, 1024, 0xf351799f -0, 250, 250, 1, 3101, 0xbcc89bec, S=1, 1024, 0xf351799f -0, 260, 260, 1, 3253, 0xd032f3fa, S=1, 1024, 0xf351799f -0, 270, 270, 1, 3329, 0xe4d42430, S=1, 1024, 0xf351799f -0, 280, 280, 1, 3572, 0xf8058aa0, S=1, 1024, 0xf351799f -0, 290, 290, 1, 3807, 0x3d2af9f3, S=1, 1024, 0xf351799f -0, 300, 300, 1, 2750, 0x814d1c33, S=1, 1024, 0xf351799f -0, 310, 310, 1, 4031, 0x3b077006, S=1, 1024, 0xf351799f -0, 320, 320, 1, 3025, 0x86729c1c, S=1, 1024, 0xf351799f -0, 330, 330, 1, 4295, 0xf71b0b38, S=1, 1024, 0xf351799f -0, 340, 340, 1, 2044, 0x5adcb93b, S=1, 1024, 0xf351799f -0, 350, 350, 1, 3212, 0xcf79eeed, S=1, 1024, 0xf351799f -0, 360, 360, 1, 2281, 0x68464d30, S=1, 1024, 0xf351799f -0, 370, 370, 1, 3633, 0x0010992f, S=1, 1024, 0xf351799f -0, 380, 380, 1, 3552, 0x23697490, S=1, 1024, 0xf351799f -0, 390, 390, 1, 3690, 0x62afdbb8, S=1, 1024, 0xf351799f -0, 400, 400, 1, 1558, 0x7a13e53b, S=1, 1024, 0xf351799f -0, 410, 410, 1, 940, 0xb1b6cba2, S=1, 1024, 0xf351799f -0, 420, 420, 1, 273, 0x3687799b, S=1, 1024, 0xf351799f -0, 430, 430, 1, 930, 0x29f3b0c4, S=1, 1024, 0xf351799f -0, 440, 440, 1, 271, 0xe7af807c, S=1, 1024, 0xf351799f -0, 450, 450, 1, 196, 0xf5ab51ee, S=1, 1024, 0xf351799f -0, 460, 460, 1, 4299, 0x67ec0d55, S=1, 1024, 0xf351799f -0, 470, 470, 1, 4895, 0xb394406c, S=1, 1024, 0xf351799f -0, 480, 480, 1, 4928, 0x233919d7, S=1, 1024, 0xf351799f -0, 490, 490, 1, 4941, 0x58a357da, S=1, 1024, 0xf351799f -0, 500, 500, 1, 4154, 0x21f2ac33, S=1, 1024, 0xf351799f -0, 510, 510, 1, 4678, 0xab3cc050, S=1, 1024, 0xf351799f -0, 520, 520, 1, 4741, 0x1974b581, S=1, 1024, 0xf351799f -0, 530, 530, 1, 4982, 0x891456d5, S=1, 1024, 0xf351799f -0, 540, 540, 1, 5179, 0x860fc6a1, S=1, 1024, 0xf351799f -0, 550, 550, 1, 5046, 0xce9183d3, S=1, 1024, 0xf351799f -0, 560, 560, 1, 5140, 0xa6d7b9af, S=1, 1024, 0xf351799f -0, 570, 570, 1, 4289, 0xb415f717, S=1, 1024, 0xf351799f -0, 580, 580, 1, 5079, 0xa8d59e01, S=1, 1024, 0xf351799f -0, 590, 590, 1, 5284, 0xea34e3b3, S=1, 1024, 0xf351799f -0, 600, 600, 1, 5426, 0x556a15cd, S=1, 1024, 0xf351799f -0, 610, 610, 1, 4645, 0x061e8936, S=1, 1024, 0xf351799f -0, 620, 620, 1, 5263, 0x7536cf7d, S=1, 1024, 0xf351799f -0, 630, 630, 1, 5221, 0x9fbac3ca, S=1, 1024, 0xf351799f -0, 640, 640, 1, 5217, 0x02269bd2, S=1, 1024, 0xf351799f -0, 650, 650, 1, 5395, 0x120fff66, S=1, 1024, 0xf351799f -0, 660, 660, 1, 5220, 0x77cedcc5, S=1, 1024, 0xf351799f -0, 670, 670, 1, 5704, 0xba42dd96, S=1, 1024, 0xf351799f -0, 680, 680, 1, 5636, 0xcb91a25b, S=1, 1024, 0xf351799f -0, 690, 690, 1, 5818, 0x8dc0df92, S=1, 1024, 0xf351799f -0, 700, 700, 1, 5763, 0x51d5d5f0, S=1, 1024, 0xf351799f -0, 710, 710, 1, 6116, 0x09558b48, S=1, 1024, 0xf351799f -0, 720, 720, 1, 6069, 0x41926817, S=1, 1024, 0xf351799f -0, 730, 730, 1, 5796, 0x7fbeda44, S=1, 1024, 0xf351799f -0, 740, 740, 1, 5999, 0xe07d3770, S=1, 1024, 0xf351799f -0, 750, 750, 1, 6220, 0x6607b06f, S=1, 1024, 0xf351799f -0, 760, 760, 1, 6374, 0x7628e533, S=1, 1024, 0xf351799f -0, 770, 770, 1, 6465, 0xfe956b15, S=1, 1024, 0xf351799f -0, 780, 780, 1, 7019, 0x6c9a1aef, S=1, 1024, 0xf351799f -0, 790, 790, 1, 7255, 0x5fa5c1bf, S=1, 1024, 0xf351799f -0, 800, 800, 1, 8197, 0xf11d6ef2, S=1, 1024, 0xf351799f -0, 810, 810, 1, 8358, 0x027279e8, S=1, 1024, 0xf351799f -0, 820, 820, 1, 7708, 0x607f8e8b, S=1, 1024, 0xf351799f -0, 830, 830, 1, 7412, 0x6bb2105f, S=1, 1024, 0xf351799f -0, 840, 840, 1, 7541, 0xfdc02154, S=1, 1024, 0xf351799f -0, 850, 850, 1, 7948, 0x916ecd8b, S=1, 1024, 0xf351799f -0, 860, 860, 1, 8408, 0x1f97d414, S=1, 1024, 0xf351799f -0, 870, 870, 1, 8056, 0x9cbf159c, S=1, 1024, 0xf351799f -0, 880, 880, 1, 7401, 0x2625addb, S=1, 1024, 0xf351799f -0, 890, 890, 1, 7494, 0x2877eacb, S=1, 1024, 0xf351799f -0, 900, 900, 1, 7806, 0xe32574a3, S=1, 1024, 0xf351799f -0, 910, 910, 1, 7768, 0x25ed7ee7, S=1, 1024, 0xf351799f -0, 920, 920, 1, 7749, 0x6d8e978e, S=1, 1024, 0xf351799f -0, 930, 930, 1, 8047, 0xec4b150c, S=1, 1024, 0xf351799f -0, 940, 940, 1, 7618, 0x88cf30d5, S=1, 1024, 0xf351799f -0, 950, 950, 1, 7979, 0x0eb1cf2a, S=1, 1024, 0xf351799f -0, 960, 960, 1, 12062, 0xb49d9125, S=1, 1024, 0xf351799f -0, 970, 970, 1, 12317, 0x2d8fd6e9, S=1, 1024, 0xf351799f -0, 980, 980, 1, 12217, 0x9b3be549, S=1, 1024, 0xf351799f -0, 990, 990, 1, 11227, 0x067e9118, S=1, 1024, 0xf351799f -0, 1000, 1000, 1, 11108, 0x5e5b0afd, S=1, 1024, 0xf351799f -0, 1010, 1010, 1, 11366, 0xb38e8d15, S=1, 1024, 0xf351799f -0, 1020, 1020, 1, 11896, 0xeb3e35ca, S=1, 1024, 0xf351799f -0, 1030, 1030, 1, 11479, 0xbf7581e9, S=1, 1024, 0xf351799f -0, 1040, 1040, 1, 13395, 0x415b38d8, S=1, 1024, 0xf351799f -0, 1050, 1050, 1, 12913, 0x61544631, S=1, 1024, 0xf351799f -0, 1060, 1060, 1, 13864, 0xd39fe768, S=1, 1024, 0xf351799f -0, 1070, 1070, 1, 13551, 0x76c167d1, S=1, 1024, 0xf351799f -0, 1080, 1080, 1, 14041, 0x2f206888, S=1, 1024, 0xf351799f -0, 1090, 1090, 1, 14144, 0x9ec030d3, S=1, 1024, 0xf351799f -0, 1100, 1100, 1, 14277, 0xa84b3a9b, S=1, 1024, 0xf351799f -0, 1110, 1110, 1, 14424, 0xf5f1e06e, S=1, 1024, 0xf351799f -0, 1120, 1120, 1, 14689, 0xbca0adb5, S=1, 1024, 0xf351799f -0, 1130, 1130, 1, 14598, 0xc1d45745, S=1, 1024, 0xf351799f -0, 1140, 1140, 1, 15213, 0x8f3080fc, S=1, 1024, 0xf351799f -0, 1150, 1150, 1, 15425, 0xb0aa8f59, S=1, 1024, 0xf351799f -0, 1160, 1160, 1, 15595, 0x1406e5d5, S=1, 1024, 0xf351799f -0, 1170, 1170, 1, 15598, 0x48ec7d08, S=1, 1024, 0xf351799f -0, 1180, 1180, 1, 15863, 0x5381db7b, S=1, 1024, 0xf351799f -0, 1190, 1190, 1, 15717, 0xb87a1b87, S=1, 1024, 0xf351799f -0, 1200, 1200, 1, 16078, 0x5bab2453, S=1, 1024, 0xf351799f -0, 1210, 1210, 1, 16225, 0xa1f88113, S=1, 1024, 0xf351799f -0, 1220, 1220, 1, 16135, 0x6af2f4e1, S=1, 1024, 0xf351799f -0, 1230, 1230, 1, 16661, 0xf02a3343, S=1, 1024, 0xf351799f -0, 1240, 1240, 1, 16619, 0xc71935a4, S=1, 1024, 0xf351799f -0, 1250, 1250, 1, 16829, 0x29849844, S=1, 1024, 0xf351799f -0, 1260, 1260, 1, 16944, 0x3423ae77, S=1, 1024, 0xf351799f -0, 1270, 1270, 1, 17119, 0x609b4409, S=1, 1024, 0xf351799f -0, 1280, 1280, 1, 17150, 0xf85dfd31, S=1, 1024, 0xf351799f -0, 1290, 1290, 1, 17321, 0x38eccb10, S=1, 1024, 0xf351799f -0, 1300, 1300, 1, 17395, 0x0ba08b85, S=1, 1024, 0xf351799f -0, 1310, 1310, 1, 17666, 0x6fbc0264, S=1, 1024, 0xf351799f -0, 1320, 1320, 1, 17730, 0x3dcc64a6, S=1, 1024, 0xf351799f -0, 1330, 1330, 1, 17934, 0xb539974b, S=1, 1024, 0xf351799f -0, 1340, 1340, 1, 17944, 0x2214ec94, S=1, 1024, 0xf351799f -0, 1350, 1350, 1, 18238, 0x70f9ff1d, S=1, 1024, 0xf351799f -0, 1360, 1360, 1, 18391, 0x4b149209, S=1, 1024, 0xf351799f -0, 1370, 1370, 1, 18543, 0x45a1c02f, S=1, 1024, 0xf351799f -0, 1380, 1380, 1, 18939, 0x2789a88c, S=1, 1024, 0xf351799f -0, 1390, 1390, 1, 19145, 0x5daafd7a, S=1, 1024, 0xf351799f -0, 1400, 1400, 1, 19120, 0x565f80e6, S=1, 1024, 0xf351799f -0, 1410, 1410, 1, 19130, 0xff70cc21, S=1, 1024, 0xf351799f -0, 1420, 1420, 1, 19494, 0xbfa284db, S=1, 1024, 0xf351799f -0, 1430, 1430, 1, 19534, 0x3d40743b, S=1, 1024, 0xf351799f -0, 1440, 1440, 1, 19747, 0x33c9b108, S=1, 1024, 0xf351799f -0, 1450, 1450, 1, 20114, 0x9d223e36, S=1, 1024, 0xf351799f -0, 1460, 1460, 1, 20257, 0xe7bdaf43, S=1, 1024, 0xf351799f -0, 1470, 1470, 1, 20370, 0x0c5f1970, S=1, 1024, 0xf351799f -0, 1480, 1480, 1, 20292, 0x6986d20e, S=1, 1024, 0xf351799f -0, 1490, 1490, 1, 20491, 0xd88e4c08, S=1, 1024, 0xf351799f -0, 1500, 1500, 1, 20647, 0x1aefaffc, S=1, 1024, 0xf351799f -0, 1510, 1510, 1, 20666, 0x43e4aaaa, S=1, 1024, 0xf351799f -0, 1520, 1520, 1, 21007, 0xa7ca3ef0, S=1, 1024, 0xf351799f -0, 1530, 1530, 1, 21058, 0x06814351, S=1, 1024, 0xf351799f -0, 1540, 1540, 1, 21153, 0x3c852b10, S=1, 1024, 0xf351799f -0, 1550, 1550, 1, 21078, 0x8df15855, S=1, 1024, 0xf351799f -0, 1560, 1560, 1, 21458, 0xd3a531d6, S=1, 1024, 0xf351799f -0, 1570, 1570, 1, 21669, 0x88baca53, S=1, 1024, 0xf351799f -0, 1580, 1580, 1, 21581, 0xd692fa1f, S=1, 1024, 0xf351799f -0, 1590, 1590, 1, 21654, 0x30fb9061, S=1, 1024, 0xf351799f -0, 1600, 1600, 1, 21987, 0xe7646d8b, S=1, 1024, 0xf351799f -0, 1610, 1610, 1, 22205, 0x0fc55b6a, S=1, 1024, 0xf351799f -0, 1620, 1620, 1, 22475, 0x4bc4c032, S=1, 1024, 0xf351799f -0, 1630, 1630, 1, 22490, 0x58ca23f6, S=1, 1024, 0xf351799f -0, 1640, 1640, 1, 22460, 0xf9ceb0ac, S=1, 1024, 0xf351799f -0, 1650, 1650, 1, 22861, 0xb05f0f84, S=1, 1024, 0xf351799f -0, 1660, 1660, 1, 22746, 0x0df23a5c, S=1, 1024, 0xf351799f -0, 1670, 1670, 1, 23165, 0xbd7147ad, S=1, 1024, 0xf351799f -0, 1680, 1680, 1, 23273, 0x9781a34f, S=1, 1024, 0xf351799f -0, 1690, 1690, 1, 23211, 0x69c7606b, S=1, 1024, 0xf351799f -0, 1700, 1700, 1, 23648, 0xdafde037, S=1, 1024, 0xf351799f -0, 1710, 1710, 1, 23675, 0x2a2147ed, S=1, 1024, 0xf351799f -0, 1720, 1720, 1, 23874, 0x12c184b6, S=1, 1024, 0xf351799f +0, 1, 1, 1, 297, 0x90168a95, S=1, 1024, 0xf351799f +0, 2, 2, 1, 438, 0x91efce1b, S=1, 1024, 0xf351799f +0, 3, 3, 1, 450, 0x7c2dcfad, S=1, 1024, 0xf351799f +0, 4, 4, 1, 547, 0xc131fd3b, S=1, 1024, 0xf351799f +0, 5, 5, 1, 614, 0x68182006, S=1, 1024, 0xf351799f +0, 6, 6, 1, 642, 0x78bb1f5f, S=1, 1024, 0xf351799f +0, 7, 7, 1, 660, 0x35c033a2, S=1, 1024, 0xf351799f +0, 8, 8, 1, 821, 0xaf30790b, S=1, 1024, 0xf351799f +0, 9, 9, 1, 1157, 0x741c2da1, S=1, 1024, 0xf351799f +0, 10, 10, 1, 179, 0x3a27517c, S=1, 1024, 0xf351799f +0, 11, 11, 1, 1333, 0x5ee76f3c, S=1, 1024, 0xf351799f +0, 12, 12, 1, 1638, 0x5f640e86, S=1, 1024, 0xf351799f +0, 13, 13, 1, 1531, 0xccb8e437, S=1, 1024, 0xf351799f +0, 14, 14, 1, 1720, 0xc95d45ec, S=1, 1024, 0xf351799f +0, 15, 15, 1, 1910, 0x56cc831e, S=1, 1024, 0xf351799f +0, 16, 16, 1, 2124, 0x9cc8e130, S=1, 1024, 0xf351799f +0, 17, 17, 1, 2248, 0x05a325b1, S=1, 1024, 0xf351799f +0, 18, 18, 1, 2311, 0xdc633703, S=1, 1024, 0xf351799f +0, 19, 19, 1, 2408, 0x91c26f3e, S=1, 1024, 0xf351799f +0, 20, 20, 1, 2601, 0x8cf3c157, S=1, 1024, 0xf351799f +0, 21, 21, 1, 2687, 0x8f6400e6, S=1, 1024, 0xf351799f +0, 22, 22, 1, 2784, 0xaa880e55, S=1, 1024, 0xf351799f +0, 23, 23, 1, 2884, 0x46f546f6, S=1, 1024, 0xf351799f +0, 24, 24, 1, 2982, 0x807c7ad5, S=1, 1024, 0xf351799f +0, 25, 25, 1, 3101, 0xbcc89bec, S=1, 1024, 0xf351799f +0, 26, 26, 1, 3253, 0xd032f3fa, S=1, 1024, 0xf351799f +0, 27, 27, 1, 3329, 0xe4d42430, S=1, 1024, 0xf351799f +0, 28, 28, 1, 3572, 0xf8058aa0, S=1, 1024, 0xf351799f +0, 29, 29, 1, 3807, 0x3d2af9f3, S=1, 1024, 0xf351799f +0, 30, 30, 1, 2750, 0x814d1c33, S=1, 1024, 0xf351799f +0, 31, 31, 1, 4031, 0x3b077006, S=1, 1024, 0xf351799f +0, 32, 32, 1, 3025, 0x86729c1c, S=1, 1024, 0xf351799f +0, 33, 33, 1, 4295, 0xf71b0b38, S=1, 1024, 0xf351799f +0, 34, 34, 1, 2044, 0x5adcb93b, S=1, 1024, 0xf351799f +0, 35, 35, 1, 3212, 0xcf79eeed, S=1, 1024, 0xf351799f +0, 36, 36, 1, 2281, 0x68464d30, S=1, 1024, 0xf351799f +0, 37, 37, 1, 3633, 0x0010992f, S=1, 1024, 0xf351799f +0, 38, 38, 1, 3552, 0x23697490, S=1, 1024, 0xf351799f +0, 39, 39, 1, 3690, 0x62afdbb8, S=1, 1024, 0xf351799f +0, 40, 40, 1, 1558, 0x7a13e53b, S=1, 1024, 0xf351799f +0, 41, 41, 1, 940, 0xb1b6cba2, S=1, 1024, 0xf351799f +0, 42, 42, 1, 273, 0x3687799b, S=1, 1024, 0xf351799f +0, 43, 43, 1, 930, 0x29f3b0c4, S=1, 1024, 0xf351799f +0, 44, 44, 1, 271, 0xe7af807c, S=1, 1024, 0xf351799f +0, 45, 45, 1, 196, 0xf5ab51ee, S=1, 1024, 0xf351799f +0, 46, 46, 1, 4299, 0x67ec0d55, S=1, 1024, 0xf351799f +0, 47, 47, 1, 4895, 0xb394406c, S=1, 1024, 0xf351799f +0, 48, 48, 1, 4928, 0x233919d7, S=1, 1024, 0xf351799f +0, 49, 49, 1, 4941, 0x58a357da, S=1, 1024, 0xf351799f +0, 50, 50, 1, 4154, 0x21f2ac33, S=1, 1024, 0xf351799f +0, 51, 51, 1, 4678, 0xab3cc050, S=1, 1024, 0xf351799f +0, 52, 52, 1, 4741, 0x1974b581, S=1, 1024, 0xf351799f +0, 53, 53, 1, 4982, 0x891456d5, S=1, 1024, 0xf351799f +0, 54, 54, 1, 5179, 0x860fc6a1, S=1, 1024, 0xf351799f +0, 55, 55, 1, 5046, 0xce9183d3, S=1, 1024, 0xf351799f +0, 56, 56, 1, 5140, 0xa6d7b9af, S=1, 1024, 0xf351799f +0, 57, 57, 1, 4289, 0xb415f717, S=1, 1024, 0xf351799f +0, 58, 58, 1, 5079, 0xa8d59e01, S=1, 1024, 0xf351799f +0, 59, 59, 1, 5284, 0xea34e3b3, S=1, 1024, 0xf351799f +0, 60, 60, 1, 5426, 0x556a15cd, S=1, 1024, 0xf351799f +0, 61, 61, 1, 4645, 0x061e8936, S=1, 1024, 0xf351799f +0, 62, 62, 1, 5263, 0x7536cf7d, S=1, 1024, 0xf351799f +0, 63, 63, 1, 5221, 0x9fbac3ca, S=1, 1024, 0xf351799f +0, 64, 64, 1, 5217, 0x02269bd2, S=1, 1024, 0xf351799f +0, 65, 65, 1, 5395, 0x120fff66, S=1, 1024, 0xf351799f +0, 66, 66, 1, 5220, 0x77cedcc5, S=1, 1024, 0xf351799f +0, 67, 67, 1, 5704, 0xba42dd96, S=1, 1024, 0xf351799f +0, 68, 68, 1, 5636, 0xcb91a25b, S=1, 1024, 0xf351799f +0, 69, 69, 1, 5818, 0x8dc0df92, S=1, 1024, 0xf351799f +0, 70, 70, 1, 5763, 0x51d5d5f0, S=1, 1024, 0xf351799f +0, 71, 71, 1, 6116, 0x09558b48, S=1, 1024, 0xf351799f +0, 72, 72, 1, 6069, 0x41926817, S=1, 1024, 0xf351799f +0, 73, 73, 1, 5796, 0x7fbeda44, S=1, 1024, 0xf351799f +0, 74, 74, 1, 5999, 0xe07d3770, S=1, 1024, 0xf351799f +0, 75, 75, 1, 6220, 0x6607b06f, S=1, 1024, 0xf351799f +0, 76, 76, 1, 6374, 0x7628e533, S=1, 1024, 0xf351799f +0, 77, 77, 1, 6465, 0xfe956b15, S=1, 1024, 0xf351799f +0, 78, 78, 1, 7019, 0x6c9a1aef, S=1, 1024, 0xf351799f +0, 79, 79, 1, 7255, 0x5fa5c1bf, S=1, 1024, 0xf351799f +0, 80, 80, 1, 8197, 0xf11d6ef2, S=1, 1024, 0xf351799f +0, 81, 81, 1, 8358, 0x027279e8, S=1, 1024, 0xf351799f +0, 82, 82, 1, 7708, 0x607f8e8b, S=1, 1024, 0xf351799f +0, 83, 83, 1, 7412, 0x6bb2105f, S=1, 1024, 0xf351799f +0, 84, 84, 1, 7541, 0xfdc02154, S=1, 1024, 0xf351799f +0, 85, 85, 1, 7948, 0x916ecd8b, S=1, 1024, 0xf351799f +0, 86, 86, 1, 8408, 0x1f97d414, S=1, 1024, 0xf351799f +0, 87, 87, 1, 8056, 0x9cbf159c, S=1, 1024, 0xf351799f +0, 88, 88, 1, 7401, 0x2625addb, S=1, 1024, 0xf351799f +0, 89, 89, 1, 7494, 0x2877eacb, S=1, 1024, 0xf351799f +0, 90, 90, 1, 7806, 0xe32574a3, S=1, 1024, 0xf351799f +0, 91, 91, 1, 7768, 0x25ed7ee7, S=1, 1024, 0xf351799f +0, 92, 92, 1, 7749, 0x6d8e978e, S=1, 1024, 0xf351799f +0, 93, 93, 1, 8047, 0xec4b150c, S=1, 1024, 0xf351799f +0, 94, 94, 1, 7618, 0x88cf30d5, S=1, 1024, 0xf351799f +0, 95, 95, 1, 7979, 0x0eb1cf2a, S=1, 1024, 0xf351799f +0, 96, 96, 1, 12062, 0xb49d9125, S=1, 1024, 0xf351799f +0, 97, 97, 1, 12317, 0x2d8fd6e9, S=1, 1024, 0xf351799f +0, 98, 98, 1, 12217, 0x9b3be549, S=1, 1024, 0xf351799f +0, 99, 99, 1, 11227, 0x067e9118, S=1, 1024, 0xf351799f +0, 100, 100, 1, 11108, 0x5e5b0afd, S=1, 1024, 0xf351799f +0, 101, 101, 1, 11366, 0xb38e8d15, S=1, 1024, 0xf351799f +0, 102, 102, 1, 11896, 0xeb3e35ca, S=1, 1024, 0xf351799f +0, 103, 103, 1, 11479, 0xbf7581e9, S=1, 1024, 0xf351799f +0, 104, 104, 1, 13395, 0x415b38d8, S=1, 1024, 0xf351799f +0, 105, 105, 1, 12913, 0x61544631, S=1, 1024, 0xf351799f +0, 106, 106, 1, 13864, 0xd39fe768, S=1, 1024, 0xf351799f +0, 107, 107, 1, 13551, 0x76c167d1, S=1, 1024, 0xf351799f +0, 108, 108, 1, 14041, 0x2f206888, S=1, 1024, 0xf351799f +0, 109, 109, 1, 14144, 0x9ec030d3, S=1, 1024, 0xf351799f +0, 110, 110, 1, 14277, 0xa84b3a9b, S=1, 1024, 0xf351799f +0, 111, 111, 1, 14424, 0xf5f1e06e, S=1, 1024, 0xf351799f +0, 112, 112, 1, 14689, 0xbca0adb5, S=1, 1024, 0xf351799f +0, 113, 113, 1, 14598, 0xc1d45745, S=1, 1024, 0xf351799f +0, 114, 114, 1, 15213, 0x8f3080fc, S=1, 1024, 0xf351799f +0, 115, 115, 1, 15425, 0xb0aa8f59, S=1, 1024, 0xf351799f +0, 116, 116, 1, 15595, 0x1406e5d5, S=1, 1024, 0xf351799f +0, 117, 117, 1, 15598, 0x48ec7d08, S=1, 1024, 0xf351799f +0, 118, 118, 1, 15863, 0x5381db7b, S=1, 1024, 0xf351799f +0, 119, 119, 1, 15717, 0xb87a1b87, S=1, 1024, 0xf351799f +0, 120, 120, 1, 16078, 0x5bab2453, S=1, 1024, 0xf351799f +0, 121, 121, 1, 16225, 0xa1f88113, S=1, 1024, 0xf351799f +0, 122, 122, 1, 16135, 0x6af2f4e1, S=1, 1024, 0xf351799f +0, 123, 123, 1, 16661, 0xf02a3343, S=1, 1024, 0xf351799f +0, 124, 124, 1, 16619, 0xc71935a4, S=1, 1024, 0xf351799f +0, 125, 125, 1, 16829, 0x29849844, S=1, 1024, 0xf351799f +0, 126, 126, 1, 16944, 0x3423ae77, S=1, 1024, 0xf351799f +0, 127, 127, 1, 17119, 0x609b4409, S=1, 1024, 0xf351799f +0, 128, 128, 1, 17150, 0xf85dfd31, S=1, 1024, 0xf351799f +0, 129, 129, 1, 17321, 0x38eccb10, S=1, 1024, 0xf351799f +0, 130, 130, 1, 17395, 0x0ba08b85, S=1, 1024, 0xf351799f +0, 131, 131, 1, 17666, 0x6fbc0264, S=1, 1024, 0xf351799f +0, 132, 132, 1, 17730, 0x3dcc64a6, S=1, 1024, 0xf351799f +0, 133, 133, 1, 17934, 0xb539974b, S=1, 1024, 0xf351799f +0, 134, 134, 1, 17944, 0x2214ec94, S=1, 1024, 0xf351799f +0, 135, 135, 1, 18238, 0x70f9ff1d, S=1, 1024, 0xf351799f +0, 136, 136, 1, 18391, 0x4b149209, S=1, 1024, 0xf351799f +0, 137, 137, 1, 18543, 0x45a1c02f, S=1, 1024, 0xf351799f +0, 138, 138, 1, 18939, 0x2789a88c, S=1, 1024, 0xf351799f +0, 139, 139, 1, 19145, 0x5daafd7a, S=1, 1024, 0xf351799f +0, 140, 140, 1, 19120, 0x565f80e6, S=1, 1024, 0xf351799f +0, 141, 141, 1, 19130, 0xff70cc21, S=1, 1024, 0xf351799f +0, 142, 142, 1, 19494, 0xbfa284db, S=1, 1024, 0xf351799f +0, 143, 143, 1, 19534, 0x3d40743b, S=1, 1024, 0xf351799f +0, 144, 144, 1, 19747, 0x33c9b108, S=1, 1024, 0xf351799f +0, 145, 145, 1, 20114, 0x9d223e36, S=1, 1024, 0xf351799f +0, 146, 146, 1, 20257, 0xe7bdaf43, S=1, 1024, 0xf351799f +0, 147, 147, 1, 20370, 0x0c5f1970, S=1, 1024, 0xf351799f +0, 148, 148, 1, 20292, 0x6986d20e, S=1, 1024, 0xf351799f +0, 149, 149, 1, 20491, 0xd88e4c08, S=1, 1024, 0xf351799f +0, 150, 150, 1, 20647, 0x1aefaffc, S=1, 1024, 0xf351799f +0, 151, 151, 1, 20666, 0x43e4aaaa, S=1, 1024, 0xf351799f +0, 152, 152, 1, 21007, 0xa7ca3ef0, S=1, 1024, 0xf351799f +0, 153, 153, 1, 21058, 0x06814351, S=1, 1024, 0xf351799f +0, 154, 154, 1, 21153, 0x3c852b10, S=1, 1024, 0xf351799f +0, 155, 155, 1, 21078, 0x8df15855, S=1, 1024, 0xf351799f +0, 156, 156, 1, 21458, 0xd3a531d6, S=1, 1024, 0xf351799f +0, 157, 157, 1, 21669, 0x88baca53, S=1, 1024, 0xf351799f +0, 158, 158, 1, 21581, 0xd692fa1f, S=1, 1024, 0xf351799f +0, 159, 159, 1, 21654, 0x30fb9061, S=1, 1024, 0xf351799f +0, 160, 160, 1, 21987, 0xe7646d8b, S=1, 1024, 0xf351799f +0, 161, 161, 1, 22205, 0x0fc55b6a, S=1, 1024, 0xf351799f +0, 162, 162, 1, 22475, 0x4bc4c032, S=1, 1024, 0xf351799f +0, 163, 163, 1, 22490, 0x58ca23f6, S=1, 1024, 0xf351799f +0, 164, 164, 1, 22460, 0xf9ceb0ac, S=1, 1024, 0xf351799f +0, 165, 165, 1, 22861, 0xb05f0f84, S=1, 1024, 0xf351799f +0, 166, 166, 1, 22746, 0x0df23a5c, S=1, 1024, 0xf351799f +0, 167, 167, 1, 23165, 0xbd7147ad, S=1, 1024, 0xf351799f +0, 168, 168, 1, 23273, 0x9781a34f, S=1, 1024, 0xf351799f +0, 169, 169, 1, 23211, 0x69c7606b, S=1, 1024, 0xf351799f +0, 170, 170, 1, 23648, 0xdafde037, S=1, 1024, 0xf351799f +0, 171, 171, 1, 23675, 0x2a2147ed, S=1, 1024, 0xf351799f +0, 172, 172, 1, 23874, 0x12c184b6, S=1, 1024, 0xf351799f diff --git a/tests/ref/fate/gifenc-gray b/tests/ref/fate/gifenc-gray index 8fdc3b33c..c11e132b8 100644 --- a/tests/ref/fate/gifenc-gray +++ b/tests/ref/fate/gifenc-gray @@ -1,174 +1,174 @@ -#tb 0: 1/100 +#tb 0: 1/10 0, 0, 0, 1, 579, 0x0d0e3ab8 -0, 10, 10, 1, 150, 0x178b3a8c, S=1, 1024, 0xc2f67c9f -0, 20, 20, 1, 155, 0x941743f5, S=1, 1024, 0xc2f67c9f -0, 30, 30, 1, 144, 0x68c73711, S=1, 1024, 0xc2f67c9f -0, 40, 40, 1, 152, 0xaf9a3f2e, S=1, 1024, 0xc2f67c9f -0, 50, 50, 1, 136, 0x68593d85, S=1, 1024, 0xc2f67c9f -0, 60, 60, 1, 134, 0x0dcb373f, S=1, 1024, 0xc2f67c9f -0, 70, 70, 1, 129, 0x3baf3279, S=1, 1024, 0xc2f67c9f -0, 80, 80, 1, 123, 0x9c963148, S=1, 1024, 0xc2f67c9f -0, 90, 90, 1, 123, 0x5c272d6b, S=1, 1024, 0xc2f67c9f -0, 100, 100, 1, 150, 0x5f8d41aa, S=1, 1024, 0xc2f67c9f -0, 110, 110, 1, 134, 0x6f582fee, S=1, 1024, 0xc2f67c9f -0, 120, 120, 1, 134, 0x85d53038, S=1, 1024, 0xc2f67c9f -0, 130, 130, 1, 123, 0x6d2a2cb2, S=1, 1024, 0xc2f67c9f -0, 140, 140, 1, 127, 0x1e78327b, S=1, 1024, 0xc2f67c9f -0, 150, 150, 1, 119, 0xbafc2c31, S=1, 1024, 0xc2f67c9f -0, 160, 160, 1, 138, 0x57553638, S=1, 1024, 0xc2f67c9f -0, 170, 170, 1, 140, 0xf7423adb, S=1, 1024, 0xc2f67c9f -0, 180, 180, 1, 122, 0x7e592f8b, S=1, 1024, 0xc2f67c9f -0, 190, 190, 1, 123, 0xaa7d313c, S=1, 1024, 0xc2f67c9f -0, 200, 200, 1, 140, 0x4fd63b34, S=1, 1024, 0xc2f67c9f -0, 210, 210, 1, 123, 0x67753163, S=1, 1024, 0xc2f67c9f -0, 220, 220, 1, 123, 0x02193147, S=1, 1024, 0xc2f67c9f -0, 230, 230, 1, 124, 0xa85131e9, S=1, 1024, 0xc2f67c9f -0, 240, 240, 1, 122, 0xef8731e2, S=1, 1024, 0xc2f67c9f -0, 250, 250, 1, 122, 0x06d432c9, S=1, 1024, 0xc2f67c9f -0, 260, 260, 1, 123, 0xcc8831cd, S=1, 1024, 0xc2f67c9f -0, 270, 270, 1, 118, 0xa1d33166, S=1, 1024, 0xc2f67c9f -0, 280, 280, 1, 159, 0xcc8c454c, S=1, 1024, 0xc2f67c9f -0, 290, 290, 1, 140, 0x8a0231ad, S=1, 1024, 0xc2f67c9f -0, 300, 300, 1, 163, 0xe78248d2, S=1, 1024, 0xc2f67c9f -0, 310, 310, 1, 142, 0x3b293489, S=1, 1024, 0xc2f67c9f -0, 320, 320, 1, 170, 0x5f504b12, S=1, 1024, 0xc2f67c9f -0, 330, 330, 1, 146, 0x38a53693, S=1, 1024, 0xc2f67c9f -0, 340, 340, 1, 132, 0xb18a3499, S=1, 1024, 0xc2f67c9f -0, 350, 350, 1, 113, 0x55182bda, S=1, 1024, 0xc2f67c9f -0, 360, 360, 1, 132, 0xaced3333, S=1, 1024, 0xc2f67c9f -0, 370, 370, 1, 120, 0x9ffe2e4f, S=1, 1024, 0xc2f67c9f -0, 380, 380, 1, 135, 0x6223351e, S=1, 1024, 0xc2f67c9f -0, 390, 390, 1, 123, 0x269b3058, S=1, 1024, 0xc2f67c9f -0, 400, 400, 1, 119, 0x17052def, S=1, 1024, 0xc2f67c9f -0, 410, 410, 1, 119, 0x36da2ee2, S=1, 1024, 0xc2f67c9f -0, 420, 420, 1, 120, 0x984e31be, S=1, 1024, 0xc2f67c9f -0, 430, 430, 1, 114, 0xfd382c9d, S=1, 1024, 0xc2f67c9f -0, 440, 440, 1, 125, 0x926a36c6, S=1, 1024, 0xc2f67c9f -0, 450, 450, 1, 117, 0xbceb3183, S=1, 1024, 0xc2f67c9f -0, 460, 460, 1, 116, 0xf4c72d82, S=1, 1024, 0xc2f67c9f -0, 470, 470, 1, 124, 0x0c19343c, S=1, 1024, 0xc2f67c9f -0, 480, 480, 1, 117, 0x1f032eb1, S=1, 1024, 0xc2f67c9f -0, 490, 490, 1, 135, 0x31a437e6, S=1, 1024, 0xc2f67c9f -0, 500, 500, 1, 131, 0x4c1735fe, S=1, 1024, 0xc2f67c9f -0, 510, 510, 1, 122, 0xb7603463, S=1, 1024, 0xc2f67c9f -0, 520, 520, 1, 122, 0x7f5e34e1, S=1, 1024, 0xc2f67c9f -0, 530, 530, 1, 124, 0x9562350f, S=1, 1024, 0xc2f67c9f -0, 540, 540, 1, 126, 0x18b33759, S=1, 1024, 0xc2f67c9f -0, 550, 550, 1, 117, 0x748f3243, S=1, 1024, 0xc2f67c9f -0, 560, 560, 1, 109, 0x72832fe7, S=1, 1024, 0xc2f67c9f -0, 570, 570, 1, 120, 0x748a2e38, S=1, 1024, 0xc2f67c9f -0, 580, 580, 1, 120, 0x61f82fb2, S=1, 1024, 0xc2f67c9f -0, 590, 590, 1, 122, 0x2a6b3282, S=1, 1024, 0xc2f67c9f -0, 600, 600, 1, 116, 0x8b542de6, S=1, 1024, 0xc2f67c9f -0, 610, 610, 1, 119, 0xf33c318e, S=1, 1024, 0xc2f67c9f -0, 620, 620, 1, 116, 0xff182f36, S=1, 1024, 0xc2f67c9f -0, 630, 630, 1, 119, 0xeb9e2fcc, S=1, 1024, 0xc2f67c9f -0, 640, 640, 1, 118, 0xe82d304e, S=1, 1024, 0xc2f67c9f -0, 650, 650, 1, 137, 0x98303d30, S=1, 1024, 0xc2f67c9f -0, 660, 660, 1, 149, 0x01123fff, S=1, 1024, 0xc2f67c9f -0, 670, 670, 1, 115, 0x4ca92f75, S=1, 1024, 0xc2f67c9f -0, 680, 680, 1, 131, 0xf4193bc0, S=1, 1024, 0xc2f67c9f -0, 690, 690, 1, 115, 0xda5e2f30, S=1, 1024, 0xc2f67c9f -0, 700, 700, 1, 100, 0x9ba32a58, S=1, 1024, 0xc2f67c9f -0, 710, 710, 1, 109, 0xa47e2c91, S=1, 1024, 0xc2f67c9f -0, 720, 720, 1, 120, 0x22452fd6, S=1, 1024, 0xc2f67c9f -0, 730, 730, 1, 116, 0xd3c52c26, S=1, 1024, 0xc2f67c9f -0, 740, 740, 1, 106, 0x95b42c9f, S=1, 1024, 0xc2f67c9f -0, 750, 750, 1, 96, 0xfdc12639, S=1, 1024, 0xc2f67c9f -0, 760, 760, 1, 99, 0x210f251b, S=1, 1024, 0xc2f67c9f -0, 770, 770, 1, 119, 0x173b341c, S=1, 1024, 0xc2f67c9f -0, 780, 780, 1, 119, 0x3bca2f29, S=1, 1024, 0xc2f67c9f -0, 790, 790, 1, 213, 0x9e905d4c, S=1, 1024, 0xc2f67c9f -0, 800, 800, 1, 209, 0xa0015e94, S=1, 1024, 0xc2f67c9f -0, 810, 810, 1, 120, 0x36762bd4, S=1, 1024, 0xc2f67c9f -0, 820, 820, 1, 119, 0x019b2edc, S=1, 1024, 0xc2f67c9f -0, 830, 830, 1, 124, 0x211d30e7, S=1, 1024, 0xc2f67c9f -0, 840, 840, 1, 125, 0x538732ff, S=1, 1024, 0xc2f67c9f -0, 850, 850, 1, 123, 0x2887308a, S=1, 1024, 0xc2f67c9f -0, 860, 860, 1, 119, 0x7ff930f4, S=1, 1024, 0xc2f67c9f -0, 870, 870, 1, 119, 0xa50c2e16, S=1, 1024, 0xc2f67c9f -0, 880, 880, 1, 107, 0x9ed02cea, S=1, 1024, 0xc2f67c9f -0, 890, 890, 1, 119, 0xc234332a, S=1, 1024, 0xc2f67c9f -0, 900, 900, 1, 115, 0x38353092, S=1, 1024, 0xc2f67c9f -0, 910, 910, 1, 162, 0x6cda4644, S=1, 1024, 0xc2f67c9f -0, 920, 920, 1, 124, 0x2f683081, S=1, 1024, 0xc2f67c9f -0, 930, 930, 1, 116, 0x72952d04, S=1, 1024, 0xc2f67c9f -0, 940, 940, 1, 84, 0x1a532301, S=1, 1024, 0xc2f67c9f -0, 950, 950, 1, 176, 0xfb3c5400, S=1, 1024, 0xc2f67c9f -0, 960, 960, 1, 137, 0x253132d1, S=1, 1024, 0xc2f67c9f -0, 970, 970, 1, 179, 0x2b38528b, S=1, 1024, 0xc2f67c9f -0, 980, 980, 1, 150, 0xbe413cbe, S=1, 1024, 0xc2f67c9f -0, 990, 990, 1, 140, 0x9e93392a, S=1, 1024, 0xc2f67c9f -0, 1000, 1000, 1, 129, 0x577e331e, S=1, 1024, 0xc2f67c9f -0, 1010, 1010, 1, 146, 0x16ff3924, S=1, 1024, 0xc2f67c9f -0, 1020, 1020, 1, 133, 0x756a3163, S=1, 1024, 0xc2f67c9f -0, 1030, 1030, 1, 190, 0x3e865b77, S=1, 1024, 0xc2f67c9f -0, 1040, 1040, 1, 159, 0xdf393fc8, S=1, 1024, 0xc2f67c9f -0, 1050, 1050, 1, 188, 0x84be5168, S=1, 1024, 0xc2f67c9f -0, 1060, 1060, 1, 163, 0x4c0e41f0, S=1, 1024, 0xc2f67c9f -0, 1070, 1070, 1, 144, 0x5fda3792, S=1, 1024, 0xc2f67c9f -0, 1080, 1080, 1, 136, 0x028c3800, S=1, 1024, 0xc2f67c9f -0, 1090, 1090, 1, 150, 0x75d43a8d, S=1, 1024, 0xc2f67c9f -0, 1100, 1100, 1, 134, 0x81123999, S=1, 1024, 0xc2f67c9f -0, 1110, 1110, 1, 198, 0x0a875baa, S=1, 1024, 0xc2f67c9f -0, 1120, 1120, 1, 169, 0xfdd7458c, S=1, 1024, 0xc2f67c9f -0, 1130, 1130, 1, 210, 0x9b195be4, S=1, 1024, 0xc2f67c9f -0, 1140, 1140, 1, 174, 0x0a424a76, S=1, 1024, 0xc2f67c9f -0, 1150, 1150, 1, 137, 0xb1b535fd, S=1, 1024, 0xc2f67c9f -0, 1160, 1160, 1, 122, 0x4d3f327b, S=1, 1024, 0xc2f67c9f -0, 1170, 1170, 1, 152, 0x5e423b0c, S=1, 1024, 0xc2f67c9f -0, 1180, 1180, 1, 137, 0xd13a39f7, S=1, 1024, 0xc2f67c9f -0, 1190, 1190, 1, 156, 0x40864321, S=1, 1024, 0xc2f67c9f -0, 1200, 1200, 1, 140, 0xbe1e393c, S=1, 1024, 0xc2f67c9f -0, 1210, 1210, 1, 179, 0xaf204635, S=1, 1024, 0xc2f67c9f -0, 1220, 1220, 1, 116, 0x5ac83123, S=1, 1024, 0xc2f67c9f -0, 1230, 1230, 1, 118, 0x22bc2ec5, S=1, 1024, 0xc2f67c9f -0, 1240, 1240, 1, 123, 0xc9b5302d, S=1, 1024, 0xc2f67c9f -0, 1250, 1250, 1, 125, 0x5cee3077, S=1, 1024, 0xc2f67c9f -0, 1260, 1260, 1, 194, 0xccc159ca, S=1, 1024, 0xc2f67c9f -0, 1270, 1270, 1, 122, 0x4d243229, S=1, 1024, 0xc2f67c9f -0, 1280, 1280, 1, 124, 0x948f330b, S=1, 1024, 0xc2f67c9f -0, 1290, 1290, 1, 133, 0xd53c35ca, S=1, 1024, 0xc2f67c9f -0, 1300, 1300, 1, 126, 0xc5543710, S=1, 1024, 0xc2f67c9f -0, 1310, 1310, 1, 208, 0x6cf15ea2, S=1, 1024, 0xc2f67c9f -0, 1320, 1320, 1, 131, 0xa8d33505, S=1, 1024, 0xc2f67c9f -0, 1330, 1330, 1, 114, 0x0ae53001, S=1, 1024, 0xc2f67c9f -0, 1340, 1340, 1, 129, 0xe9ff37c4, S=1, 1024, 0xc2f67c9f -0, 1350, 1350, 1, 120, 0x02623359, S=1, 1024, 0xc2f67c9f -0, 1360, 1360, 1, 164, 0x9dc545e5, S=1, 1024, 0xc2f67c9f -0, 1370, 1370, 1, 245, 0xc170715a, S=1, 1024, 0xc2f67c9f -0, 1380, 1380, 1, 215, 0xc93d5fbe, S=1, 1024, 0xc2f67c9f -0, 1390, 1390, 1, 225, 0x14866349, S=1, 1024, 0xc2f67c9f -0, 1400, 1400, 1, 123, 0x70cd2b64, S=1, 1024, 0xc2f67c9f -0, 1410, 1410, 1, 124, 0xe9002fb5, S=1, 1024, 0xc2f67c9f -0, 1420, 1420, 1, 125, 0x106e309b, S=1, 1024, 0xc2f67c9f -0, 1430, 1430, 1, 122, 0x050e32b0, S=1, 1024, 0xc2f67c9f -0, 1440, 1440, 1, 224, 0xf548614f, S=1, 1024, 0xc2f67c9f -0, 1450, 1450, 1, 239, 0x125c6ade, S=1, 1024, 0xc2f67c9f -0, 1460, 1460, 1, 127, 0x398734b6, S=1, 1024, 0xc2f67c9f -0, 1470, 1470, 1, 126, 0x2ff431e5, S=1, 1024, 0xc2f67c9f -0, 1480, 1480, 1, 124, 0x9583313b, S=1, 1024, 0xc2f67c9f -0, 1490, 1490, 1, 126, 0xc1fc3692, S=1, 1024, 0xc2f67c9f -0, 1500, 1500, 1, 123, 0xd0bf3170, S=1, 1024, 0xc2f67c9f -0, 1510, 1510, 1, 117, 0x651f3032, S=1, 1024, 0xc2f67c9f -0, 1520, 1520, 1, 119, 0x268a3078, S=1, 1024, 0xc2f67c9f -0, 1530, 1530, 1, 117, 0x9e4d3283, S=1, 1024, 0xc2f67c9f -0, 1540, 1540, 1, 149, 0x8f1043ba, S=1, 1024, 0xc2f67c9f -0, 1550, 1550, 1, 127, 0x352338bc, S=1, 1024, 0xc2f67c9f -0, 1560, 1560, 1, 113, 0xf877314e, S=1, 1024, 0xc2f67c9f -0, 1570, 1570, 1, 128, 0x88103a62, S=1, 1024, 0xc2f67c9f -0, 1580, 1580, 1, 111, 0xbf0630d9, S=1, 1024, 0xc2f67c9f -0, 1590, 1590, 1, 146, 0x159c44f7, S=1, 1024, 0xc2f67c9f -0, 1600, 1600, 1, 237, 0x4e45662e, S=1, 1024, 0xc2f67c9f -0, 1610, 1610, 1, 233, 0x8f9e6354, S=1, 1024, 0xc2f67c9f -0, 1620, 1620, 1, 160, 0x9c3f431f, S=1, 1024, 0xc2f67c9f -0, 1630, 1630, 1, 125, 0xbd2b33c6, S=1, 1024, 0xc2f67c9f -0, 1640, 1640, 1, 131, 0x3ecd3ba5, S=1, 1024, 0xc2f67c9f -0, 1650, 1650, 1, 231, 0xdf286db6, S=1, 1024, 0xc2f67c9f -0, 1660, 1660, 1, 153, 0xb6da408d, S=1, 1024, 0xc2f67c9f -0, 1670, 1670, 1, 126, 0x6741365e, S=1, 1024, 0xc2f67c9f -0, 1680, 1680, 1, 113, 0x658f2c90, S=1, 1024, 0xc2f67c9f -0, 1690, 1690, 1, 125, 0xc0033320, S=1, 1024, 0xc2f67c9f -0, 1700, 1700, 1, 122, 0xe38a2db1, S=1, 1024, 0xc2f67c9f -0, 1710, 1710, 1, 145, 0x29d63e83, S=1, 1024, 0xc2f67c9f -0, 1720, 1720, 1, 171, 0xc0e44b70, S=1, 1024, 0xc2f67c9f +0, 1, 1, 1, 150, 0x178b3a8c, S=1, 1024, 0xc2f67c9f +0, 2, 2, 1, 155, 0x941743f5, S=1, 1024, 0xc2f67c9f +0, 3, 3, 1, 144, 0x68c73711, S=1, 1024, 0xc2f67c9f +0, 4, 4, 1, 152, 0xaf9a3f2e, S=1, 1024, 0xc2f67c9f +0, 5, 5, 1, 136, 0x68593d85, S=1, 1024, 0xc2f67c9f +0, 6, 6, 1, 134, 0x0dcb373f, S=1, 1024, 0xc2f67c9f +0, 7, 7, 1, 129, 0x3baf3279, S=1, 1024, 0xc2f67c9f +0, 8, 8, 1, 123, 0x9c963148, S=1, 1024, 0xc2f67c9f +0, 9, 9, 1, 123, 0x5c272d6b, S=1, 1024, 0xc2f67c9f +0, 10, 10, 1, 150, 0x5f8d41aa, S=1, 1024, 0xc2f67c9f +0, 11, 11, 1, 134, 0x6f582fee, S=1, 1024, 0xc2f67c9f +0, 12, 12, 1, 134, 0x85d53038, S=1, 1024, 0xc2f67c9f +0, 13, 13, 1, 123, 0x6d2a2cb2, S=1, 1024, 0xc2f67c9f +0, 14, 14, 1, 127, 0x1e78327b, S=1, 1024, 0xc2f67c9f +0, 15, 15, 1, 119, 0xbafc2c31, S=1, 1024, 0xc2f67c9f +0, 16, 16, 1, 138, 0x57553638, S=1, 1024, 0xc2f67c9f +0, 17, 17, 1, 140, 0xf7423adb, S=1, 1024, 0xc2f67c9f +0, 18, 18, 1, 122, 0x7e592f8b, S=1, 1024, 0xc2f67c9f +0, 19, 19, 1, 123, 0xaa7d313c, S=1, 1024, 0xc2f67c9f +0, 20, 20, 1, 140, 0x4fd63b34, S=1, 1024, 0xc2f67c9f +0, 21, 21, 1, 123, 0x67753163, S=1, 1024, 0xc2f67c9f +0, 22, 22, 1, 123, 0x02193147, S=1, 1024, 0xc2f67c9f +0, 23, 23, 1, 124, 0xa85131e9, S=1, 1024, 0xc2f67c9f +0, 24, 24, 1, 122, 0xef8731e2, S=1, 1024, 0xc2f67c9f +0, 25, 25, 1, 122, 0x06d432c9, S=1, 1024, 0xc2f67c9f +0, 26, 26, 1, 123, 0xcc8831cd, S=1, 1024, 0xc2f67c9f +0, 27, 27, 1, 118, 0xa1d33166, S=1, 1024, 0xc2f67c9f +0, 28, 28, 1, 159, 0xcc8c454c, S=1, 1024, 0xc2f67c9f +0, 29, 29, 1, 140, 0x8a0231ad, S=1, 1024, 0xc2f67c9f +0, 30, 30, 1, 163, 0xe78248d2, S=1, 1024, 0xc2f67c9f +0, 31, 31, 1, 142, 0x3b293489, S=1, 1024, 0xc2f67c9f +0, 32, 32, 1, 170, 0x5f504b12, S=1, 1024, 0xc2f67c9f +0, 33, 33, 1, 146, 0x38a53693, S=1, 1024, 0xc2f67c9f +0, 34, 34, 1, 132, 0xb18a3499, S=1, 1024, 0xc2f67c9f +0, 35, 35, 1, 113, 0x55182bda, S=1, 1024, 0xc2f67c9f +0, 36, 36, 1, 132, 0xaced3333, S=1, 1024, 0xc2f67c9f +0, 37, 37, 1, 120, 0x9ffe2e4f, S=1, 1024, 0xc2f67c9f +0, 38, 38, 1, 135, 0x6223351e, S=1, 1024, 0xc2f67c9f +0, 39, 39, 1, 123, 0x269b3058, S=1, 1024, 0xc2f67c9f +0, 40, 40, 1, 119, 0x17052def, S=1, 1024, 0xc2f67c9f +0, 41, 41, 1, 119, 0x36da2ee2, S=1, 1024, 0xc2f67c9f +0, 42, 42, 1, 120, 0x984e31be, S=1, 1024, 0xc2f67c9f +0, 43, 43, 1, 114, 0xfd382c9d, S=1, 1024, 0xc2f67c9f +0, 44, 44, 1, 125, 0x926a36c6, S=1, 1024, 0xc2f67c9f +0, 45, 45, 1, 117, 0xbceb3183, S=1, 1024, 0xc2f67c9f +0, 46, 46, 1, 116, 0xf4c72d82, S=1, 1024, 0xc2f67c9f +0, 47, 47, 1, 124, 0x0c19343c, S=1, 1024, 0xc2f67c9f +0, 48, 48, 1, 117, 0x1f032eb1, S=1, 1024, 0xc2f67c9f +0, 49, 49, 1, 135, 0x31a437e6, S=1, 1024, 0xc2f67c9f +0, 50, 50, 1, 131, 0x4c1735fe, S=1, 1024, 0xc2f67c9f +0, 51, 51, 1, 122, 0xb7603463, S=1, 1024, 0xc2f67c9f +0, 52, 52, 1, 122, 0x7f5e34e1, S=1, 1024, 0xc2f67c9f +0, 53, 53, 1, 124, 0x9562350f, S=1, 1024, 0xc2f67c9f +0, 54, 54, 1, 126, 0x18b33759, S=1, 1024, 0xc2f67c9f +0, 55, 55, 1, 117, 0x748f3243, S=1, 1024, 0xc2f67c9f +0, 56, 56, 1, 109, 0x72832fe7, S=1, 1024, 0xc2f67c9f +0, 57, 57, 1, 120, 0x748a2e38, S=1, 1024, 0xc2f67c9f +0, 58, 58, 1, 120, 0x61f82fb2, S=1, 1024, 0xc2f67c9f +0, 59, 59, 1, 122, 0x2a6b3282, S=1, 1024, 0xc2f67c9f +0, 60, 60, 1, 116, 0x8b542de6, S=1, 1024, 0xc2f67c9f +0, 61, 61, 1, 119, 0xf33c318e, S=1, 1024, 0xc2f67c9f +0, 62, 62, 1, 116, 0xff182f36, S=1, 1024, 0xc2f67c9f +0, 63, 63, 1, 119, 0xeb9e2fcc, S=1, 1024, 0xc2f67c9f +0, 64, 64, 1, 118, 0xe82d304e, S=1, 1024, 0xc2f67c9f +0, 65, 65, 1, 137, 0x98303d30, S=1, 1024, 0xc2f67c9f +0, 66, 66, 1, 149, 0x01123fff, S=1, 1024, 0xc2f67c9f +0, 67, 67, 1, 115, 0x4ca92f75, S=1, 1024, 0xc2f67c9f +0, 68, 68, 1, 131, 0xf4193bc0, S=1, 1024, 0xc2f67c9f +0, 69, 69, 1, 115, 0xda5e2f30, S=1, 1024, 0xc2f67c9f +0, 70, 70, 1, 100, 0x9ba32a58, S=1, 1024, 0xc2f67c9f +0, 71, 71, 1, 109, 0xa47e2c91, S=1, 1024, 0xc2f67c9f +0, 72, 72, 1, 120, 0x22452fd6, S=1, 1024, 0xc2f67c9f +0, 73, 73, 1, 116, 0xd3c52c26, S=1, 1024, 0xc2f67c9f +0, 74, 74, 1, 106, 0x95b42c9f, S=1, 1024, 0xc2f67c9f +0, 75, 75, 1, 96, 0xfdc12639, S=1, 1024, 0xc2f67c9f +0, 76, 76, 1, 99, 0x210f251b, S=1, 1024, 0xc2f67c9f +0, 77, 77, 1, 119, 0x173b341c, S=1, 1024, 0xc2f67c9f +0, 78, 78, 1, 119, 0x3bca2f29, S=1, 1024, 0xc2f67c9f +0, 79, 79, 1, 213, 0x9e905d4c, S=1, 1024, 0xc2f67c9f +0, 80, 80, 1, 209, 0xa0015e94, S=1, 1024, 0xc2f67c9f +0, 81, 81, 1, 120, 0x36762bd4, S=1, 1024, 0xc2f67c9f +0, 82, 82, 1, 119, 0x019b2edc, S=1, 1024, 0xc2f67c9f +0, 83, 83, 1, 124, 0x211d30e7, S=1, 1024, 0xc2f67c9f +0, 84, 84, 1, 125, 0x538732ff, S=1, 1024, 0xc2f67c9f +0, 85, 85, 1, 123, 0x2887308a, S=1, 1024, 0xc2f67c9f +0, 86, 86, 1, 119, 0x7ff930f4, S=1, 1024, 0xc2f67c9f +0, 87, 87, 1, 119, 0xa50c2e16, S=1, 1024, 0xc2f67c9f +0, 88, 88, 1, 107, 0x9ed02cea, S=1, 1024, 0xc2f67c9f +0, 89, 89, 1, 119, 0xc234332a, S=1, 1024, 0xc2f67c9f +0, 90, 90, 1, 115, 0x38353092, S=1, 1024, 0xc2f67c9f +0, 91, 91, 1, 162, 0x6cda4644, S=1, 1024, 0xc2f67c9f +0, 92, 92, 1, 124, 0x2f683081, S=1, 1024, 0xc2f67c9f +0, 93, 93, 1, 116, 0x72952d04, S=1, 1024, 0xc2f67c9f +0, 94, 94, 1, 84, 0x1a532301, S=1, 1024, 0xc2f67c9f +0, 95, 95, 1, 176, 0xfb3c5400, S=1, 1024, 0xc2f67c9f +0, 96, 96, 1, 137, 0x253132d1, S=1, 1024, 0xc2f67c9f +0, 97, 97, 1, 179, 0x2b38528b, S=1, 1024, 0xc2f67c9f +0, 98, 98, 1, 150, 0xbe413cbe, S=1, 1024, 0xc2f67c9f +0, 99, 99, 1, 140, 0x9e93392a, S=1, 1024, 0xc2f67c9f +0, 100, 100, 1, 129, 0x577e331e, S=1, 1024, 0xc2f67c9f +0, 101, 101, 1, 146, 0x16ff3924, S=1, 1024, 0xc2f67c9f +0, 102, 102, 1, 133, 0x756a3163, S=1, 1024, 0xc2f67c9f +0, 103, 103, 1, 190, 0x3e865b77, S=1, 1024, 0xc2f67c9f +0, 104, 104, 1, 159, 0xdf393fc8, S=1, 1024, 0xc2f67c9f +0, 105, 105, 1, 188, 0x84be5168, S=1, 1024, 0xc2f67c9f +0, 106, 106, 1, 163, 0x4c0e41f0, S=1, 1024, 0xc2f67c9f +0, 107, 107, 1, 144, 0x5fda3792, S=1, 1024, 0xc2f67c9f +0, 108, 108, 1, 136, 0x028c3800, S=1, 1024, 0xc2f67c9f +0, 109, 109, 1, 150, 0x75d43a8d, S=1, 1024, 0xc2f67c9f +0, 110, 110, 1, 134, 0x81123999, S=1, 1024, 0xc2f67c9f +0, 111, 111, 1, 198, 0x0a875baa, S=1, 1024, 0xc2f67c9f +0, 112, 112, 1, 169, 0xfdd7458c, S=1, 1024, 0xc2f67c9f +0, 113, 113, 1, 210, 0x9b195be4, S=1, 1024, 0xc2f67c9f +0, 114, 114, 1, 174, 0x0a424a76, S=1, 1024, 0xc2f67c9f +0, 115, 115, 1, 137, 0xb1b535fd, S=1, 1024, 0xc2f67c9f +0, 116, 116, 1, 122, 0x4d3f327b, S=1, 1024, 0xc2f67c9f +0, 117, 117, 1, 152, 0x5e423b0c, S=1, 1024, 0xc2f67c9f +0, 118, 118, 1, 137, 0xd13a39f7, S=1, 1024, 0xc2f67c9f +0, 119, 119, 1, 156, 0x40864321, S=1, 1024, 0xc2f67c9f +0, 120, 120, 1, 140, 0xbe1e393c, S=1, 1024, 0xc2f67c9f +0, 121, 121, 1, 179, 0xaf204635, S=1, 1024, 0xc2f67c9f +0, 122, 122, 1, 116, 0x5ac83123, S=1, 1024, 0xc2f67c9f +0, 123, 123, 1, 118, 0x22bc2ec5, S=1, 1024, 0xc2f67c9f +0, 124, 124, 1, 123, 0xc9b5302d, S=1, 1024, 0xc2f67c9f +0, 125, 125, 1, 125, 0x5cee3077, S=1, 1024, 0xc2f67c9f +0, 126, 126, 1, 194, 0xccc159ca, S=1, 1024, 0xc2f67c9f +0, 127, 127, 1, 122, 0x4d243229, S=1, 1024, 0xc2f67c9f +0, 128, 128, 1, 124, 0x948f330b, S=1, 1024, 0xc2f67c9f +0, 129, 129, 1, 133, 0xd53c35ca, S=1, 1024, 0xc2f67c9f +0, 130, 130, 1, 126, 0xc5543710, S=1, 1024, 0xc2f67c9f +0, 131, 131, 1, 208, 0x6cf15ea2, S=1, 1024, 0xc2f67c9f +0, 132, 132, 1, 131, 0xa8d33505, S=1, 1024, 0xc2f67c9f +0, 133, 133, 1, 114, 0x0ae53001, S=1, 1024, 0xc2f67c9f +0, 134, 134, 1, 129, 0xe9ff37c4, S=1, 1024, 0xc2f67c9f +0, 135, 135, 1, 120, 0x02623359, S=1, 1024, 0xc2f67c9f +0, 136, 136, 1, 164, 0x9dc545e5, S=1, 1024, 0xc2f67c9f +0, 137, 137, 1, 245, 0xc170715a, S=1, 1024, 0xc2f67c9f +0, 138, 138, 1, 215, 0xc93d5fbe, S=1, 1024, 0xc2f67c9f +0, 139, 139, 1, 225, 0x14866349, S=1, 1024, 0xc2f67c9f +0, 140, 140, 1, 123, 0x70cd2b64, S=1, 1024, 0xc2f67c9f +0, 141, 141, 1, 124, 0xe9002fb5, S=1, 1024, 0xc2f67c9f +0, 142, 142, 1, 125, 0x106e309b, S=1, 1024, 0xc2f67c9f +0, 143, 143, 1, 122, 0x050e32b0, S=1, 1024, 0xc2f67c9f +0, 144, 144, 1, 224, 0xf548614f, S=1, 1024, 0xc2f67c9f +0, 145, 145, 1, 239, 0x125c6ade, S=1, 1024, 0xc2f67c9f +0, 146, 146, 1, 127, 0x398734b6, S=1, 1024, 0xc2f67c9f +0, 147, 147, 1, 126, 0x2ff431e5, S=1, 1024, 0xc2f67c9f +0, 148, 148, 1, 124, 0x9583313b, S=1, 1024, 0xc2f67c9f +0, 149, 149, 1, 126, 0xc1fc3692, S=1, 1024, 0xc2f67c9f +0, 150, 150, 1, 123, 0xd0bf3170, S=1, 1024, 0xc2f67c9f +0, 151, 151, 1, 117, 0x651f3032, S=1, 1024, 0xc2f67c9f +0, 152, 152, 1, 119, 0x268a3078, S=1, 1024, 0xc2f67c9f +0, 153, 153, 1, 117, 0x9e4d3283, S=1, 1024, 0xc2f67c9f +0, 154, 154, 1, 149, 0x8f1043ba, S=1, 1024, 0xc2f67c9f +0, 155, 155, 1, 127, 0x352338bc, S=1, 1024, 0xc2f67c9f +0, 156, 156, 1, 113, 0xf877314e, S=1, 1024, 0xc2f67c9f +0, 157, 157, 1, 128, 0x88103a62, S=1, 1024, 0xc2f67c9f +0, 158, 158, 1, 111, 0xbf0630d9, S=1, 1024, 0xc2f67c9f +0, 159, 159, 1, 146, 0x159c44f7, S=1, 1024, 0xc2f67c9f +0, 160, 160, 1, 237, 0x4e45662e, S=1, 1024, 0xc2f67c9f +0, 161, 161, 1, 233, 0x8f9e6354, S=1, 1024, 0xc2f67c9f +0, 162, 162, 1, 160, 0x9c3f431f, S=1, 1024, 0xc2f67c9f +0, 163, 163, 1, 125, 0xbd2b33c6, S=1, 1024, 0xc2f67c9f +0, 164, 164, 1, 131, 0x3ecd3ba5, S=1, 1024, 0xc2f67c9f +0, 165, 165, 1, 231, 0xdf286db6, S=1, 1024, 0xc2f67c9f +0, 166, 166, 1, 153, 0xb6da408d, S=1, 1024, 0xc2f67c9f +0, 167, 167, 1, 126, 0x6741365e, S=1, 1024, 0xc2f67c9f +0, 168, 168, 1, 113, 0x658f2c90, S=1, 1024, 0xc2f67c9f +0, 169, 169, 1, 125, 0xc0033320, S=1, 1024, 0xc2f67c9f +0, 170, 170, 1, 122, 0xe38a2db1, S=1, 1024, 0xc2f67c9f +0, 171, 171, 1, 145, 0x29d63e83, S=1, 1024, 0xc2f67c9f +0, 172, 172, 1, 171, 0xc0e44b70, S=1, 1024, 0xc2f67c9f diff --git a/tests/ref/fate/gifenc-pal8 b/tests/ref/fate/gifenc-pal8 index a483dab2e..203a15404 100644 --- a/tests/ref/fate/gifenc-pal8 +++ b/tests/ref/fate/gifenc-pal8 @@ -1,174 +1,174 @@ -#tb 0: 1/100 +#tb 0: 1/10 0, 0, 0, 1, 1320, 0x95d1a9e9, S=1, 1024, 0xec907a9e -0, 10, 10, 1, 1463, 0xa697fe95, S=1, 1024, 0xec907a9e -0, 20, 20, 1, 1638, 0x7ea154fa, S=1, 1024, 0xec907a9e -0, 30, 30, 1, 1755, 0x7e0b9c4d, S=1, 1024, 0xec907a9e -0, 40, 40, 1, 1896, 0x4aacc768, S=1, 1024, 0xec907a9e -0, 50, 50, 1, 2038, 0x209d1490, S=1, 1024, 0xec907a9e -0, 60, 60, 1, 2168, 0x0c405606, S=1, 1024, 0xec907a9e -0, 70, 70, 1, 2258, 0xc2fa9229, S=1, 1024, 0xec907a9e -0, 80, 80, 1, 2442, 0x0d4bec48, S=1, 1024, 0xec907a9e -0, 90, 90, 1, 2565, 0x15742730, S=1, 1024, 0xec907a9e -0, 100, 100, 1, 2733, 0x2eb57d95, S=1, 1024, 0xec907a9e -0, 110, 110, 1, 2849, 0x9f16ad46, S=1, 1024, 0xec907a9e -0, 120, 120, 1, 2981, 0xf139f908, S=1, 1024, 0xec907a9e -0, 130, 130, 1, 3082, 0x57144aec, S=1, 1024, 0xec907a9e -0, 140, 140, 1, 3200, 0x35227f42, S=1, 1024, 0xec907a9e -0, 150, 150, 1, 3316, 0xf6d7c002, S=1, 1024, 0xec907a9e -0, 160, 160, 1, 3462, 0x27a20d23, S=1, 1024, 0xec907a9e -0, 170, 170, 1, 3600, 0xaecb2b02, S=1, 1024, 0xec907a9e -0, 180, 180, 1, 3712, 0x947d49d1, S=1, 1024, 0xec907a9e -0, 190, 190, 1, 3838, 0xf87eb223, S=1, 1024, 0xec907a9e -0, 200, 200, 1, 3949, 0x4152eedf, S=1, 1024, 0xec907a9e -0, 210, 210, 1, 4084, 0x512c1e34, S=1, 1024, 0xec907a9e -0, 220, 220, 1, 4187, 0xc5715a14, S=1, 1024, 0xec907a9e -0, 230, 230, 1, 4323, 0x6326a0f5, S=1, 1024, 0xec907a9e -0, 240, 240, 1, 4426, 0x5f6bd655, S=1, 1024, 0xec907a9e -0, 250, 250, 1, 4564, 0xc62005fd, S=1, 1024, 0xec907a9e -0, 260, 260, 1, 4664, 0x43e97006, S=1, 1024, 0xec907a9e -0, 270, 270, 1, 4808, 0xf6e08d4f, S=1, 1024, 0xec907a9e -0, 280, 280, 1, 4932, 0x2d51e0b5, S=1, 1024, 0xec907a9e -0, 290, 290, 1, 5072, 0x577430c8, S=1, 1024, 0xec907a9e -0, 300, 300, 1, 5247, 0xd9fe945d, S=1, 1024, 0xec907a9e -0, 310, 310, 1, 5353, 0x27eec140, S=1, 1024, 0xec907a9e -0, 320, 320, 1, 5536, 0xde59038d, S=1, 1024, 0xec907a9e -0, 330, 330, 1, 5691, 0x358970e4, S=1, 1024, 0xec907a9e -0, 340, 340, 1, 5835, 0xd89201d8, S=1, 1024, 0xec907a9e -0, 350, 350, 1, 5967, 0x1c2e1fee, S=1, 1024, 0xec907a9e -0, 360, 360, 1, 6082, 0xd4b88e90, S=1, 1024, 0xec907a9e -0, 370, 370, 1, 6277, 0x020fe685, S=1, 1024, 0xec907a9e -0, 380, 380, 1, 6382, 0xc1db2297, S=1, 1024, 0xec907a9e -0, 390, 390, 1, 6509, 0xc65473a6, S=1, 1024, 0xec907a9e -0, 400, 400, 1, 6621, 0xca917a35, S=1, 1024, 0xec907a9e -0, 410, 410, 1, 6714, 0x70f29b1d, S=1, 1024, 0xec907a9e -0, 420, 420, 1, 6822, 0x6f02e7ec, S=1, 1024, 0xec907a9e -0, 430, 430, 1, 6880, 0x95440d97, S=1, 1024, 0xec907a9e -0, 440, 440, 1, 6983, 0xab7a43fb, S=1, 1024, 0xec907a9e -0, 450, 450, 1, 7085, 0xc3427580, S=1, 1024, 0xec907a9e -0, 460, 460, 1, 7242, 0x3d00c5f0, S=1, 1024, 0xec907a9e -0, 470, 470, 1, 7349, 0x453fad59, S=1, 1024, 0xec907a9e -0, 480, 480, 1, 7514, 0xbd862667, S=1, 1024, 0xec907a9e -0, 490, 490, 1, 7575, 0xf8cb3c77, S=1, 1024, 0xec907a9e -0, 500, 500, 1, 7759, 0x1fe6ab40, S=1, 1024, 0xec907a9e -0, 510, 510, 1, 7846, 0x3853fd0f, S=1, 1024, 0xec907a9e -0, 520, 520, 1, 7975, 0x88d02c47, S=1, 1024, 0xec907a9e -0, 530, 530, 1, 8092, 0xe28a3368, S=1, 1024, 0xec907a9e -0, 540, 540, 1, 8188, 0x159a5d3b, S=1, 1024, 0xec907a9e -0, 550, 550, 1, 8307, 0x598cae50, S=1, 1024, 0xec907a9e -0, 560, 560, 1, 8436, 0xd104ee50, S=1, 1024, 0xec907a9e -0, 570, 570, 1, 8498, 0x0b1527ed, S=1, 1024, 0xec907a9e -0, 580, 580, 1, 8559, 0x0f722288, S=1, 1024, 0xec907a9e -0, 590, 590, 1, 8661, 0x3efb2500, S=1, 1024, 0xec907a9e -0, 600, 600, 1, 8774, 0x1e188a8b, S=1, 1024, 0xec907a9e -0, 610, 610, 1, 8848, 0x5b438dbb, S=1, 1024, 0xec907a9e -0, 620, 620, 1, 8968, 0x4b47ecb3, S=1, 1024, 0xec907a9e -0, 630, 630, 1, 9036, 0x7a8e0791, S=1, 1024, 0xec907a9e -0, 640, 640, 1, 9114, 0x7379131a, S=1, 1024, 0xec907a9e -0, 650, 650, 1, 9258, 0x06099246, S=1, 1024, 0xec907a9e -0, 660, 660, 1, 9423, 0x721ac9ab, S=1, 1024, 0xec907a9e -0, 670, 670, 1, 9529, 0xbb1c0d18, S=1, 1024, 0xec907a9e -0, 680, 680, 1, 9608, 0xc29a05f0, S=1, 1024, 0xec907a9e -0, 690, 690, 1, 9668, 0xf35221ff, S=1, 1024, 0xec907a9e -0, 700, 700, 1, 9709, 0x8c6d33f0, S=1, 1024, 0xec907a9e -0, 710, 710, 1, 9810, 0x2d5b59f4, S=1, 1024, 0xec907a9e -0, 720, 720, 1, 9879, 0x110ea6e5, S=1, 1024, 0xec907a9e -0, 730, 730, 1, 10038, 0x5945f5f4, S=1, 1024, 0xec907a9e -0, 740, 740, 1, 10120, 0xab24f519, S=1, 1024, 0xec907a9e -0, 750, 750, 1, 10218, 0x090d305a, S=1, 1024, 0xec907a9e -0, 760, 760, 1, 10231, 0xa77e6a66, S=1, 1024, 0xec907a9e -0, 770, 770, 1, 10313, 0x192254b7, S=1, 1024, 0xec907a9e -0, 780, 780, 1, 10444, 0x36609934, S=1, 1024, 0xec907a9e -0, 790, 790, 1, 10670, 0xfa971206, S=1, 1024, 0xec907a9e -0, 800, 800, 1, 10902, 0x01b59fd5, S=1, 1024, 0xec907a9e -0, 810, 810, 1, 10992, 0x1f2ab0bc, S=1, 1024, 0xec907a9e -0, 820, 820, 1, 11044, 0x7f5b1dc2, S=1, 1024, 0xec907a9e -0, 830, 830, 1, 11170, 0x0beaee49, S=1, 1024, 0xec907a9e -0, 840, 840, 1, 11267, 0xb1ae3808, S=1, 1024, 0xec907a9e -0, 850, 850, 1, 11427, 0x2cc9aa3f, S=1, 1024, 0xec907a9e -0, 860, 860, 1, 11529, 0x654de4f3, S=1, 1024, 0xec907a9e -0, 870, 870, 1, 11632, 0xf4972bdf, S=1, 1024, 0xec907a9e -0, 880, 880, 1, 11825, 0x0cd2548c, S=1, 1024, 0xec907a9e -0, 890, 890, 1, 11864, 0x80758637, S=1, 1024, 0xec907a9e -0, 900, 900, 1, 11950, 0xf8246fba, S=1, 1024, 0xec907a9e -0, 910, 910, 1, 12088, 0x1b99c82b, S=1, 1024, 0xec907a9e -0, 920, 920, 1, 12161, 0x682cf4ad, S=1, 1024, 0xec907a9e -0, 930, 930, 1, 12305, 0x9f62069a, S=1, 1024, 0xec907a9e -0, 940, 940, 1, 12296, 0xe08dd96c, S=1, 1024, 0xec907a9e -0, 950, 950, 1, 12497, 0x9a20b2d0, S=1, 1024, 0xec907a9e -0, 960, 960, 1, 12660, 0x4d1d05ea, S=1, 1024, 0xec907a9e -0, 970, 970, 1, 12763, 0x12542531, S=1, 1024, 0xec907a9e -0, 980, 980, 1, 12917, 0x7d0944dc, S=1, 1024, 0xec907a9e -0, 990, 990, 1, 13021, 0xa1c89f22, S=1, 1024, 0xec907a9e -0, 1000, 1000, 1, 13184, 0xe13ad0be, S=1, 1024, 0xec907a9e -0, 1010, 1010, 1, 13315, 0x11b93a5d, S=1, 1024, 0xec907a9e -0, 1020, 1020, 1, 13337, 0x677e54ef, S=1, 1024, 0xec907a9e -0, 1030, 1030, 1, 13536, 0x48b7b5de, S=1, 1024, 0xec907a9e -0, 1040, 1040, 1, 13728, 0x03f4d302, S=1, 1024, 0xec907a9e -0, 1050, 1050, 1, 13822, 0x973b97ec, S=1, 1024, 0xec907a9e -0, 1060, 1060, 1, 14002, 0x0de77dfc, S=1, 1024, 0xec907a9e -0, 1070, 1070, 1, 14156, 0xf1b1d4e1, S=1, 1024, 0xec907a9e -0, 1080, 1080, 1, 14256, 0x355320cc, S=1, 1024, 0xec907a9e -0, 1090, 1090, 1, 14451, 0x306cb131, S=1, 1024, 0xec907a9e -0, 1100, 1100, 1, 14508, 0xca729c8e, S=1, 1024, 0xec907a9e -0, 1110, 1110, 1, 14683, 0x7abec197, S=1, 1024, 0xec907a9e -0, 1120, 1120, 1, 14852, 0xa5b90496, S=1, 1024, 0xec907a9e -0, 1130, 1130, 1, 15090, 0xcd29839d, S=1, 1024, 0xec907a9e -0, 1140, 1140, 1, 15225, 0xfd85f899, S=1, 1024, 0xec907a9e -0, 1150, 1150, 1, 15340, 0x07411310, S=1, 1024, 0xec907a9e -0, 1160, 1160, 1, 15473, 0xe90086c1, S=1, 1024, 0xec907a9e -0, 1170, 1170, 1, 15583, 0x524da1f3, S=1, 1024, 0xec907a9e -0, 1180, 1180, 1, 15683, 0x404cbd62, S=1, 1024, 0xec907a9e -0, 1190, 1190, 1, 15779, 0x3ec01717, S=1, 1024, 0xec907a9e -0, 1200, 1200, 1, 15934, 0xac8b4c03, S=1, 1024, 0xec907a9e -0, 1210, 1210, 1, 16116, 0xb4fa83c9, S=1, 1024, 0xec907a9e -0, 1220, 1220, 1, 16153, 0x18f669c1, S=1, 1024, 0xec907a9e -0, 1230, 1230, 1, 16303, 0x765b10e4, S=1, 1024, 0xec907a9e -0, 1240, 1240, 1, 16460, 0xc4a8149a, S=1, 1024, 0xec907a9e -0, 1250, 1250, 1, 16475, 0x48664e2d, S=1, 1024, 0xec907a9e -0, 1260, 1260, 1, 16710, 0x8a599742, S=1, 1024, 0xec907a9e -0, 1270, 1270, 1, 16848, 0x8634a3d5, S=1, 1024, 0xec907a9e -0, 1280, 1280, 1, 16955, 0x01f1ebda, S=1, 1024, 0xec907a9e -0, 1290, 1290, 1, 17044, 0xd57b47df, S=1, 1024, 0xec907a9e -0, 1300, 1300, 1, 17153, 0xc5cf7bc7, S=1, 1024, 0xec907a9e -0, 1310, 1310, 1, 17375, 0xbbeea767, S=1, 1024, 0xec907a9e -0, 1320, 1320, 1, 17476, 0xd7a25686, S=1, 1024, 0xec907a9e -0, 1330, 1330, 1, 17602, 0x1c99b228, S=1, 1024, 0xec907a9e -0, 1340, 1340, 1, 17676, 0xd860d1d2, S=1, 1024, 0xec907a9e -0, 1350, 1350, 1, 17799, 0xe4ccb3ae, S=1, 1024, 0xec907a9e -0, 1360, 1360, 1, 17930, 0xf322e416, S=1, 1024, 0xec907a9e -0, 1370, 1370, 1, 18201, 0xc6f1cfa7, S=1, 1024, 0xec907a9e -0, 1380, 1380, 1, 18409, 0x7cdfe609, S=1, 1024, 0xec907a9e -0, 1390, 1390, 1, 18686, 0xf65e5519, S=1, 1024, 0xec907a9e -0, 1400, 1400, 1, 18790, 0x6d5c8a90, S=1, 1024, 0xec907a9e -0, 1410, 1410, 1, 18891, 0x4702a6cf, S=1, 1024, 0xec907a9e -0, 1420, 1420, 1, 18995, 0x69e5e02d, S=1, 1024, 0xec907a9e -0, 1430, 1430, 1, 19058, 0xc56f0272, S=1, 1024, 0xec907a9e -0, 1440, 1440, 1, 19223, 0xe89733f6, S=1, 1024, 0xec907a9e -0, 1450, 1450, 1, 19501, 0xdb80f9e9, S=1, 1024, 0xec907a9e -0, 1460, 1460, 1, 19566, 0xa3952da8, S=1, 1024, 0xec907a9e -0, 1470, 1470, 1, 19692, 0x65925150, S=1, 1024, 0xec907a9e -0, 1480, 1480, 1, 19730, 0x1352599a, S=1, 1024, 0xec907a9e -0, 1490, 1490, 1, 19916, 0xd246bf9b, S=1, 1024, 0xec907a9e -0, 1500, 1500, 1, 20136, 0x1c462eea, S=1, 1024, 0xec907a9e -0, 1510, 1510, 1, 20210, 0xdec93f63, S=1, 1024, 0xec907a9e -0, 1520, 1520, 1, 20311, 0xdff7836e, S=1, 1024, 0xec907a9e -0, 1530, 1530, 1, 20377, 0x753d813f, S=1, 1024, 0xec907a9e -0, 1540, 1540, 1, 20478, 0x7592b1a8, S=1, 1024, 0xec907a9e -0, 1550, 1550, 1, 20597, 0x58313994, S=1, 1024, 0xec907a9e -0, 1560, 1560, 1, 20717, 0xcdd9c665, S=1, 1024, 0xec907a9e -0, 1570, 1570, 1, 20816, 0x803b4b03, S=1, 1024, 0xec907a9e -0, 1580, 1580, 1, 20912, 0xce36ce22, S=1, 1024, 0xec907a9e -0, 1590, 1590, 1, 20975, 0x1d08e543, S=1, 1024, 0xec907a9e -0, 1600, 1600, 1, 21130, 0xc966e24c, S=1, 1024, 0xec907a9e -0, 1610, 1610, 1, 21343, 0x735e614e, S=1, 1024, 0xec907a9e -0, 1620, 1620, 1, 21455, 0x78d7afd1, S=1, 1024, 0xec907a9e -0, 1630, 1630, 1, 21533, 0x62a10f46, S=1, 1024, 0xec907a9e -0, 1640, 1640, 1, 21645, 0x8e53a12f, S=1, 1024, 0xec907a9e -0, 1650, 1650, 1, 21931, 0x3b2f7226, S=1, 1024, 0xec907a9e -0, 1660, 1660, 1, 22009, 0xf06bc58a, S=1, 1024, 0xec907a9e -0, 1670, 1670, 1, 22115, 0xeeb1c5d7, S=1, 1024, 0xec907a9e -0, 1680, 1680, 1, 22211, 0xcbab1084, S=1, 1024, 0xec907a9e -0, 1690, 1690, 1, 22380, 0xf07d5cb7, S=1, 1024, 0xec907a9e -0, 1700, 1700, 1, 22443, 0xcb79441c, S=1, 1024, 0xec907a9e -0, 1710, 1710, 1, 22588, 0xcad49814, S=1, 1024, 0xec907a9e -0, 1720, 1720, 1, 22706, 0x34924e43, S=1, 1024, 0xec907a9e +0, 1, 1, 1, 1463, 0xa697fe95, S=1, 1024, 0xec907a9e +0, 2, 2, 1, 1638, 0x7ea154fa, S=1, 1024, 0xec907a9e +0, 3, 3, 1, 1755, 0x7e0b9c4d, S=1, 1024, 0xec907a9e +0, 4, 4, 1, 1896, 0x4aacc768, S=1, 1024, 0xec907a9e +0, 5, 5, 1, 2038, 0x209d1490, S=1, 1024, 0xec907a9e +0, 6, 6, 1, 2168, 0x0c405606, S=1, 1024, 0xec907a9e +0, 7, 7, 1, 2258, 0xc2fa9229, S=1, 1024, 0xec907a9e +0, 8, 8, 1, 2442, 0x0d4bec48, S=1, 1024, 0xec907a9e +0, 9, 9, 1, 2565, 0x15742730, S=1, 1024, 0xec907a9e +0, 10, 10, 1, 2733, 0x2eb57d95, S=1, 1024, 0xec907a9e +0, 11, 11, 1, 2849, 0x9f16ad46, S=1, 1024, 0xec907a9e +0, 12, 12, 1, 2981, 0xf139f908, S=1, 1024, 0xec907a9e +0, 13, 13, 1, 3082, 0x57144aec, S=1, 1024, 0xec907a9e +0, 14, 14, 1, 3200, 0x35227f42, S=1, 1024, 0xec907a9e +0, 15, 15, 1, 3316, 0xf6d7c002, S=1, 1024, 0xec907a9e +0, 16, 16, 1, 3462, 0x27a20d23, S=1, 1024, 0xec907a9e +0, 17, 17, 1, 3600, 0xaecb2b02, S=1, 1024, 0xec907a9e +0, 18, 18, 1, 3712, 0x947d49d1, S=1, 1024, 0xec907a9e +0, 19, 19, 1, 3838, 0xf87eb223, S=1, 1024, 0xec907a9e +0, 20, 20, 1, 3949, 0x4152eedf, S=1, 1024, 0xec907a9e +0, 21, 21, 1, 4084, 0x512c1e34, S=1, 1024, 0xec907a9e +0, 22, 22, 1, 4187, 0xc5715a14, S=1, 1024, 0xec907a9e +0, 23, 23, 1, 4323, 0x6326a0f5, S=1, 1024, 0xec907a9e +0, 24, 24, 1, 4426, 0x5f6bd655, S=1, 1024, 0xec907a9e +0, 25, 25, 1, 4564, 0xc62005fd, S=1, 1024, 0xec907a9e +0, 26, 26, 1, 4664, 0x43e97006, S=1, 1024, 0xec907a9e +0, 27, 27, 1, 4808, 0xf6e08d4f, S=1, 1024, 0xec907a9e +0, 28, 28, 1, 4932, 0x2d51e0b5, S=1, 1024, 0xec907a9e +0, 29, 29, 1, 5072, 0x577430c8, S=1, 1024, 0xec907a9e +0, 30, 30, 1, 5247, 0xd9fe945d, S=1, 1024, 0xec907a9e +0, 31, 31, 1, 5353, 0x27eec140, S=1, 1024, 0xec907a9e +0, 32, 32, 1, 5536, 0xde59038d, S=1, 1024, 0xec907a9e +0, 33, 33, 1, 5691, 0x358970e4, S=1, 1024, 0xec907a9e +0, 34, 34, 1, 5835, 0xd89201d8, S=1, 1024, 0xec907a9e +0, 35, 35, 1, 5967, 0x1c2e1fee, S=1, 1024, 0xec907a9e +0, 36, 36, 1, 6082, 0xd4b88e90, S=1, 1024, 0xec907a9e +0, 37, 37, 1, 6277, 0x020fe685, S=1, 1024, 0xec907a9e +0, 38, 38, 1, 6382, 0xc1db2297, S=1, 1024, 0xec907a9e +0, 39, 39, 1, 6509, 0xc65473a6, S=1, 1024, 0xec907a9e +0, 40, 40, 1, 6621, 0xca917a35, S=1, 1024, 0xec907a9e +0, 41, 41, 1, 6714, 0x70f29b1d, S=1, 1024, 0xec907a9e +0, 42, 42, 1, 6822, 0x6f02e7ec, S=1, 1024, 0xec907a9e +0, 43, 43, 1, 6880, 0x95440d97, S=1, 1024, 0xec907a9e +0, 44, 44, 1, 6983, 0xab7a43fb, S=1, 1024, 0xec907a9e +0, 45, 45, 1, 7085, 0xc3427580, S=1, 1024, 0xec907a9e +0, 46, 46, 1, 7242, 0x3d00c5f0, S=1, 1024, 0xec907a9e +0, 47, 47, 1, 7349, 0x453fad59, S=1, 1024, 0xec907a9e +0, 48, 48, 1, 7514, 0xbd862667, S=1, 1024, 0xec907a9e +0, 49, 49, 1, 7575, 0xf8cb3c77, S=1, 1024, 0xec907a9e +0, 50, 50, 1, 7759, 0x1fe6ab40, S=1, 1024, 0xec907a9e +0, 51, 51, 1, 7846, 0x3853fd0f, S=1, 1024, 0xec907a9e +0, 52, 52, 1, 7975, 0x88d02c47, S=1, 1024, 0xec907a9e +0, 53, 53, 1, 8092, 0xe28a3368, S=1, 1024, 0xec907a9e +0, 54, 54, 1, 8188, 0x159a5d3b, S=1, 1024, 0xec907a9e +0, 55, 55, 1, 8307, 0x598cae50, S=1, 1024, 0xec907a9e +0, 56, 56, 1, 8436, 0xd104ee50, S=1, 1024, 0xec907a9e +0, 57, 57, 1, 8498, 0x0b1527ed, S=1, 1024, 0xec907a9e +0, 58, 58, 1, 8559, 0x0f722288, S=1, 1024, 0xec907a9e +0, 59, 59, 1, 8661, 0x3efb2500, S=1, 1024, 0xec907a9e +0, 60, 60, 1, 8774, 0x1e188a8b, S=1, 1024, 0xec907a9e +0, 61, 61, 1, 8848, 0x5b438dbb, S=1, 1024, 0xec907a9e +0, 62, 62, 1, 8968, 0x4b47ecb3, S=1, 1024, 0xec907a9e +0, 63, 63, 1, 9036, 0x7a8e0791, S=1, 1024, 0xec907a9e +0, 64, 64, 1, 9114, 0x7379131a, S=1, 1024, 0xec907a9e +0, 65, 65, 1, 9258, 0x06099246, S=1, 1024, 0xec907a9e +0, 66, 66, 1, 9423, 0x721ac9ab, S=1, 1024, 0xec907a9e +0, 67, 67, 1, 9529, 0xbb1c0d18, S=1, 1024, 0xec907a9e +0, 68, 68, 1, 9608, 0xc29a05f0, S=1, 1024, 0xec907a9e +0, 69, 69, 1, 9668, 0xf35221ff, S=1, 1024, 0xec907a9e +0, 70, 70, 1, 9709, 0x8c6d33f0, S=1, 1024, 0xec907a9e +0, 71, 71, 1, 9810, 0x2d5b59f4, S=1, 1024, 0xec907a9e +0, 72, 72, 1, 9879, 0x110ea6e5, S=1, 1024, 0xec907a9e +0, 73, 73, 1, 10038, 0x5945f5f4, S=1, 1024, 0xec907a9e +0, 74, 74, 1, 10120, 0xab24f519, S=1, 1024, 0xec907a9e +0, 75, 75, 1, 10218, 0x090d305a, S=1, 1024, 0xec907a9e +0, 76, 76, 1, 10231, 0xa77e6a66, S=1, 1024, 0xec907a9e +0, 77, 77, 1, 10313, 0x192254b7, S=1, 1024, 0xec907a9e +0, 78, 78, 1, 10444, 0x36609934, S=1, 1024, 0xec907a9e +0, 79, 79, 1, 10670, 0xfa971206, S=1, 1024, 0xec907a9e +0, 80, 80, 1, 10902, 0x01b59fd5, S=1, 1024, 0xec907a9e +0, 81, 81, 1, 10992, 0x1f2ab0bc, S=1, 1024, 0xec907a9e +0, 82, 82, 1, 11044, 0x7f5b1dc2, S=1, 1024, 0xec907a9e +0, 83, 83, 1, 11170, 0x0beaee49, S=1, 1024, 0xec907a9e +0, 84, 84, 1, 11267, 0xb1ae3808, S=1, 1024, 0xec907a9e +0, 85, 85, 1, 11427, 0x2cc9aa3f, S=1, 1024, 0xec907a9e +0, 86, 86, 1, 11529, 0x654de4f3, S=1, 1024, 0xec907a9e +0, 87, 87, 1, 11632, 0xf4972bdf, S=1, 1024, 0xec907a9e +0, 88, 88, 1, 11825, 0x0cd2548c, S=1, 1024, 0xec907a9e +0, 89, 89, 1, 11864, 0x80758637, S=1, 1024, 0xec907a9e +0, 90, 90, 1, 11950, 0xf8246fba, S=1, 1024, 0xec907a9e +0, 91, 91, 1, 12088, 0x1b99c82b, S=1, 1024, 0xec907a9e +0, 92, 92, 1, 12161, 0x682cf4ad, S=1, 1024, 0xec907a9e +0, 93, 93, 1, 12305, 0x9f62069a, S=1, 1024, 0xec907a9e +0, 94, 94, 1, 12296, 0xe08dd96c, S=1, 1024, 0xec907a9e +0, 95, 95, 1, 12497, 0x9a20b2d0, S=1, 1024, 0xec907a9e +0, 96, 96, 1, 12660, 0x4d1d05ea, S=1, 1024, 0xec907a9e +0, 97, 97, 1, 12763, 0x12542531, S=1, 1024, 0xec907a9e +0, 98, 98, 1, 12917, 0x7d0944dc, S=1, 1024, 0xec907a9e +0, 99, 99, 1, 13021, 0xa1c89f22, S=1, 1024, 0xec907a9e +0, 100, 100, 1, 13184, 0xe13ad0be, S=1, 1024, 0xec907a9e +0, 101, 101, 1, 13315, 0x11b93a5d, S=1, 1024, 0xec907a9e +0, 102, 102, 1, 13337, 0x677e54ef, S=1, 1024, 0xec907a9e +0, 103, 103, 1, 13536, 0x48b7b5de, S=1, 1024, 0xec907a9e +0, 104, 104, 1, 13728, 0x03f4d302, S=1, 1024, 0xec907a9e +0, 105, 105, 1, 13822, 0x973b97ec, S=1, 1024, 0xec907a9e +0, 106, 106, 1, 14002, 0x0de77dfc, S=1, 1024, 0xec907a9e +0, 107, 107, 1, 14156, 0xf1b1d4e1, S=1, 1024, 0xec907a9e +0, 108, 108, 1, 14256, 0x355320cc, S=1, 1024, 0xec907a9e +0, 109, 109, 1, 14451, 0x306cb131, S=1, 1024, 0xec907a9e +0, 110, 110, 1, 14508, 0xca729c8e, S=1, 1024, 0xec907a9e +0, 111, 111, 1, 14683, 0x7abec197, S=1, 1024, 0xec907a9e +0, 112, 112, 1, 14852, 0xa5b90496, S=1, 1024, 0xec907a9e +0, 113, 113, 1, 15090, 0xcd29839d, S=1, 1024, 0xec907a9e +0, 114, 114, 1, 15225, 0xfd85f899, S=1, 1024, 0xec907a9e +0, 115, 115, 1, 15340, 0x07411310, S=1, 1024, 0xec907a9e +0, 116, 116, 1, 15473, 0xe90086c1, S=1, 1024, 0xec907a9e +0, 117, 117, 1, 15583, 0x524da1f3, S=1, 1024, 0xec907a9e +0, 118, 118, 1, 15683, 0x404cbd62, S=1, 1024, 0xec907a9e +0, 119, 119, 1, 15779, 0x3ec01717, S=1, 1024, 0xec907a9e +0, 120, 120, 1, 15934, 0xac8b4c03, S=1, 1024, 0xec907a9e +0, 121, 121, 1, 16116, 0xb4fa83c9, S=1, 1024, 0xec907a9e +0, 122, 122, 1, 16153, 0x18f669c1, S=1, 1024, 0xec907a9e +0, 123, 123, 1, 16303, 0x765b10e4, S=1, 1024, 0xec907a9e +0, 124, 124, 1, 16460, 0xc4a8149a, S=1, 1024, 0xec907a9e +0, 125, 125, 1, 16475, 0x48664e2d, S=1, 1024, 0xec907a9e +0, 126, 126, 1, 16710, 0x8a599742, S=1, 1024, 0xec907a9e +0, 127, 127, 1, 16848, 0x8634a3d5, S=1, 1024, 0xec907a9e +0, 128, 128, 1, 16955, 0x01f1ebda, S=1, 1024, 0xec907a9e +0, 129, 129, 1, 17044, 0xd57b47df, S=1, 1024, 0xec907a9e +0, 130, 130, 1, 17153, 0xc5cf7bc7, S=1, 1024, 0xec907a9e +0, 131, 131, 1, 17375, 0xbbeea767, S=1, 1024, 0xec907a9e +0, 132, 132, 1, 17476, 0xd7a25686, S=1, 1024, 0xec907a9e +0, 133, 133, 1, 17602, 0x1c99b228, S=1, 1024, 0xec907a9e +0, 134, 134, 1, 17676, 0xd860d1d2, S=1, 1024, 0xec907a9e +0, 135, 135, 1, 17799, 0xe4ccb3ae, S=1, 1024, 0xec907a9e +0, 136, 136, 1, 17930, 0xf322e416, S=1, 1024, 0xec907a9e +0, 137, 137, 1, 18201, 0xc6f1cfa7, S=1, 1024, 0xec907a9e +0, 138, 138, 1, 18409, 0x7cdfe609, S=1, 1024, 0xec907a9e +0, 139, 139, 1, 18686, 0xf65e5519, S=1, 1024, 0xec907a9e +0, 140, 140, 1, 18790, 0x6d5c8a90, S=1, 1024, 0xec907a9e +0, 141, 141, 1, 18891, 0x4702a6cf, S=1, 1024, 0xec907a9e +0, 142, 142, 1, 18995, 0x69e5e02d, S=1, 1024, 0xec907a9e +0, 143, 143, 1, 19058, 0xc56f0272, S=1, 1024, 0xec907a9e +0, 144, 144, 1, 19223, 0xe89733f6, S=1, 1024, 0xec907a9e +0, 145, 145, 1, 19501, 0xdb80f9e9, S=1, 1024, 0xec907a9e +0, 146, 146, 1, 19566, 0xa3952da8, S=1, 1024, 0xec907a9e +0, 147, 147, 1, 19692, 0x65925150, S=1, 1024, 0xec907a9e +0, 148, 148, 1, 19730, 0x1352599a, S=1, 1024, 0xec907a9e +0, 149, 149, 1, 19916, 0xd246bf9b, S=1, 1024, 0xec907a9e +0, 150, 150, 1, 20136, 0x1c462eea, S=1, 1024, 0xec907a9e +0, 151, 151, 1, 20210, 0xdec93f63, S=1, 1024, 0xec907a9e +0, 152, 152, 1, 20311, 0xdff7836e, S=1, 1024, 0xec907a9e +0, 153, 153, 1, 20377, 0x753d813f, S=1, 1024, 0xec907a9e +0, 154, 154, 1, 20478, 0x7592b1a8, S=1, 1024, 0xec907a9e +0, 155, 155, 1, 20597, 0x58313994, S=1, 1024, 0xec907a9e +0, 156, 156, 1, 20717, 0xcdd9c665, S=1, 1024, 0xec907a9e +0, 157, 157, 1, 20816, 0x803b4b03, S=1, 1024, 0xec907a9e +0, 158, 158, 1, 20912, 0xce36ce22, S=1, 1024, 0xec907a9e +0, 159, 159, 1, 20975, 0x1d08e543, S=1, 1024, 0xec907a9e +0, 160, 160, 1, 21130, 0xc966e24c, S=1, 1024, 0xec907a9e +0, 161, 161, 1, 21343, 0x735e614e, S=1, 1024, 0xec907a9e +0, 162, 162, 1, 21455, 0x78d7afd1, S=1, 1024, 0xec907a9e +0, 163, 163, 1, 21533, 0x62a10f46, S=1, 1024, 0xec907a9e +0, 164, 164, 1, 21645, 0x8e53a12f, S=1, 1024, 0xec907a9e +0, 165, 165, 1, 21931, 0x3b2f7226, S=1, 1024, 0xec907a9e +0, 166, 166, 1, 22009, 0xf06bc58a, S=1, 1024, 0xec907a9e +0, 167, 167, 1, 22115, 0xeeb1c5d7, S=1, 1024, 0xec907a9e +0, 168, 168, 1, 22211, 0xcbab1084, S=1, 1024, 0xec907a9e +0, 169, 169, 1, 22380, 0xf07d5cb7, S=1, 1024, 0xec907a9e +0, 170, 170, 1, 22443, 0xcb79441c, S=1, 1024, 0xec907a9e +0, 171, 171, 1, 22588, 0xcad49814, S=1, 1024, 0xec907a9e +0, 172, 172, 1, 22706, 0x34924e43, S=1, 1024, 0xec907a9e diff --git a/tests/ref/fate/gifenc-rgb4_byte b/tests/ref/fate/gifenc-rgb4_byte index 16696da15..9b00103c6 100644 --- a/tests/ref/fate/gifenc-rgb4_byte +++ b/tests/ref/fate/gifenc-rgb4_byte @@ -1,174 +1,174 @@ -#tb 0: 1/100 +#tb 0: 1/10 0, 0, 0, 1, 508, 0xf04a113b -0, 10, 10, 1, 213, 0x23c24d3d, S=1, 1024, 0xf7700427 -0, 20, 20, 1, 131, 0x56d22a39, S=1, 1024, 0x03730427 -0, 30, 30, 1, 384, 0xb1d8a4bd, S=1, 1024, 0xf7700427 -0, 40, 40, 1, 381, 0x37a3a2c9, S=1, 1024, 0xf3740427 -0, 50, 50, 1, 430, 0x162bb3d3, S=1, 1024, 0xf3740427 -0, 60, 60, 1, 518, 0x195bd738, S=1, 1024, 0xf3740427 -0, 70, 70, 1, 535, 0x12cde6b7, S=1, 1024, 0xf3740427 -0, 80, 80, 1, 438, 0xa653b946, S=1, 1024, 0x0b6b0427 -0, 90, 90, 1, 923, 0xd2e2a35f, S=1, 1024, 0x0b6b0427 -0, 100, 100, 1, 694, 0xe1cf4a1f, S=1, 1024, 0x0b6b0427 -0, 110, 110, 1, 1194, 0xa6152c8a, S=1, 1024, 0x0b6b0427 -0, 120, 120, 1, 1291, 0x94d25581, S=1, 1024, 0x0b6b0427 -0, 130, 130, 1, 1245, 0x5b483525, S=1, 1024, 0x0b6b0427 -0, 140, 140, 1, 1330, 0xfb5351c8, S=1, 1024, 0x0b6b0427 -0, 150, 150, 1, 1276, 0x6f403914, S=1, 1024, 0x0b6b0427 -0, 160, 160, 1, 1475, 0xbf459755, S=1, 1024, 0x0b6b0427 -0, 170, 170, 1, 1784, 0xe9954aa7, S=1, 1024, 0xecb30526 -0, 180, 180, 1, 1675, 0x219dfaf8, S=1, 1024, 0xecb30526 -0, 190, 190, 1, 1509, 0xd7f5abbe, S=1, 1024, 0xecb30526 -0, 200, 200, 1, 1705, 0x44a01729, S=1, 1024, 0xecb30526 -0, 210, 210, 1, 1745, 0x31ff1f89, S=1, 1024, 0xecb30526 -0, 220, 220, 1, 1642, 0x55420147, S=1, 1024, 0xecb30526 -0, 230, 230, 1, 1718, 0x68ef1cb8, S=1, 1024, 0xecb30526 -0, 240, 240, 1, 1900, 0xd7737a09, S=1, 1024, 0xecb30526 -0, 250, 250, 1, 1807, 0x4f6c5140, S=1, 1024, 0xecb30526 -0, 260, 260, 1, 1915, 0x976d80e6, S=1, 1024, 0xecb30526 -0, 270, 270, 1, 2100, 0x0ae6d1ce, S=1, 1024, 0xecb30526 -0, 280, 280, 1, 2700, 0x7a89f104, S=1, 1024, 0xecb30526 -0, 290, 290, 1, 2673, 0xf6b6a71d, S=1, 1024, 0xecb30526 -0, 300, 300, 1, 2895, 0x9079484b, S=1, 1024, 0xecb30526 -0, 310, 310, 1, 3257, 0x0b0cd125, S=1, 1024, 0xecb30526 -0, 320, 320, 1, 3179, 0x3ee2c161, S=1, 1024, 0xecb30526 -0, 330, 330, 1, 3296, 0x6230e506, S=1, 1024, 0xecb30526 -0, 340, 340, 1, 3600, 0x021775d7, S=1, 1024, 0xecb30526 -0, 350, 350, 1, 3699, 0xfb03a043, S=1, 1024, 0xecb30526 -0, 360, 360, 1, 3814, 0x96a8d57e, S=1, 1024, 0xecb30526 -0, 370, 370, 1, 3627, 0x33a37f8f, S=1, 1024, 0xecb30526 -0, 380, 380, 1, 2950, 0x50806197, S=1, 1024, 0xecb30526 -0, 390, 390, 1, 3086, 0x72068d4c, S=1, 1024, 0xecb30526 -0, 400, 400, 1, 3094, 0x2880861f, S=1, 1024, 0xecb30526 -0, 410, 410, 1, 3456, 0x6d232a96, S=1, 1024, 0xecb30526 -0, 420, 420, 1, 4108, 0x46d75ebb, S=1, 1024, 0xecb30526 -0, 430, 430, 1, 4217, 0x04a258f4, S=1, 1024, 0xecb30526 -0, 440, 440, 1, 3613, 0x667f4ff8, S=1, 1024, 0xecb30526 -0, 450, 450, 1, 3910, 0x8f37e73e, S=1, 1024, 0xecb30526 -0, 460, 460, 1, 4461, 0x5db9e0bf, S=1, 1024, 0xecb30526 -0, 470, 470, 1, 4593, 0x883f2f49, S=1, 1024, 0xecb30526 -0, 480, 480, 1, 4822, 0x03d99b73, S=1, 1024, 0xecb30526 -0, 490, 490, 1, 5398, 0x39f7bff4, S=1, 1024, 0xecb30526 -0, 500, 500, 1, 5266, 0xd5ab9630, S=1, 1024, 0xecb30526 -0, 510, 510, 1, 5416, 0x5876e16f, S=1, 1024, 0xecb30526 -0, 520, 520, 1, 5519, 0x30ed05d8, S=1, 1024, 0xecb30526 -0, 530, 530, 1, 5701, 0x5bae5af7, S=1, 1024, 0xecb30526 -0, 540, 540, 1, 6160, 0x98364177, S=1, 1024, 0xecb30526 -0, 550, 550, 1, 6233, 0x52a05075, S=1, 1024, 0xecb30526 -0, 560, 560, 1, 5911, 0x04bfc46a, S=1, 1024, 0xecb30526 -0, 570, 570, 1, 5997, 0xf1e6f586, S=1, 1024, 0xecb30526 -0, 580, 580, 1, 5946, 0xe6f3f055, S=1, 1024, 0xecb30526 -0, 590, 590, 1, 6468, 0xc8a3cf61, S=1, 1024, 0xecb30526 -0, 600, 600, 1, 6737, 0xc27b3b79, S=1, 1024, 0xecb30526 -0, 610, 610, 1, 6275, 0x84d88e2b, S=1, 1024, 0xecb30526 -0, 620, 620, 1, 6641, 0xb44b3534, S=1, 1024, 0xecb30526 -0, 630, 630, 1, 6378, 0x3965888b, S=1, 1024, 0xecb30526 -0, 640, 640, 1, 6257, 0x12115750, S=1, 1024, 0xecb30526 -0, 650, 650, 1, 6908, 0x57137217, S=1, 1024, 0xecb30526 -0, 660, 660, 1, 7230, 0xbacc24ee, S=1, 1024, 0xecb30526 -0, 670, 670, 1, 7556, 0x1aa2a694, S=1, 1024, 0xecb30526 -0, 680, 680, 1, 7413, 0xbc9e7718, S=1, 1024, 0xecb30526 -0, 690, 690, 1, 7476, 0xb2a1aba0, S=1, 1024, 0xecb30526 -0, 700, 700, 1, 7596, 0x3301e56d, S=1, 1024, 0xecb30526 -0, 710, 710, 1, 7756, 0x8f2504f8, S=1, 1024, 0xecb30526 -0, 720, 720, 1, 8015, 0xd4146c80, S=1, 1024, 0xecb30526 -0, 730, 730, 1, 8128, 0x11b2bf4c, S=1, 1024, 0xecb30526 -0, 740, 740, 1, 8101, 0xc627adbe, S=1, 1024, 0xecb30526 -0, 750, 750, 1, 7863, 0xe99f3f3b, S=1, 1024, 0xecb30526 -0, 760, 760, 1, 7960, 0x4bc091b8, S=1, 1024, 0xecb30526 -0, 770, 770, 1, 8238, 0x1086ea8a, S=1, 1024, 0xecb30526 -0, 780, 780, 1, 8321, 0x3a404791, S=1, 1024, 0xecb30526 -0, 790, 790, 1, 8562, 0xcbdcc01e, S=1, 1024, 0xecb30526 -0, 800, 800, 1, 8746, 0xec190b22, S=1, 1024, 0xecb30526 -0, 810, 810, 1, 8578, 0x12e7a4e8, S=1, 1024, 0xecb30526 -0, 820, 820, 1, 8878, 0x51c05771, S=1, 1024, 0xecb30526 -0, 830, 830, 1, 9077, 0xe12b589b, S=1, 1024, 0xecb30526 -0, 840, 840, 1, 9310, 0xde3bf881, S=1, 1024, 0xecb30526 -0, 850, 850, 1, 9394, 0x1eba46cc, S=1, 1024, 0xecb30526 -0, 860, 860, 1, 9161, 0x7c359911, S=1, 1024, 0xecb30526 -0, 870, 870, 1, 9462, 0xccda3664, S=1, 1024, 0xecb30526 -0, 880, 880, 1, 9650, 0x6e6292fc, S=1, 1024, 0xecb30526 -0, 890, 890, 1, 9701, 0x08909b95, S=1, 1024, 0xecb30526 -0, 900, 900, 1, 9523, 0xe61b38bb, S=1, 1024, 0xecb30526 -0, 910, 910, 1, 9891, 0x96b90b98, S=1, 1024, 0xecb30526 -0, 920, 920, 1, 10005, 0x2db84c80, S=1, 1024, 0xecb30526 -0, 930, 930, 1, 10038, 0x37e52a72, S=1, 1024, 0xecb30526 -0, 940, 940, 1, 10086, 0x135a43e4, S=1, 1024, 0xecb30526 -0, 950, 950, 1, 10438, 0x472c0372, S=1, 1024, 0xecb30526 -0, 960, 960, 1, 10583, 0xcf4c5862, S=1, 1024, 0xecb30526 -0, 970, 970, 1, 10581, 0xce658137, S=1, 1024, 0xecb30526 -0, 980, 980, 1, 10807, 0x3954dad9, S=1, 1024, 0xecb30526 -0, 990, 990, 1, 11111, 0x5f8d504f, S=1, 1024, 0xecb30526 -0, 1000, 1000, 1, 11194, 0x3c7e6a77, S=1, 1024, 0xecb30526 -0, 1010, 1010, 1, 11240, 0x5112a0a3, S=1, 1024, 0xecb30526 -0, 1020, 1020, 1, 11483, 0xaf10f4fa, S=1, 1024, 0xecb30526 -0, 1030, 1030, 1, 11680, 0x44a25971, S=1, 1024, 0xecb30526 -0, 1040, 1040, 1, 11785, 0x7350b5db, S=1, 1024, 0xecb30526 -0, 1050, 1050, 1, 11436, 0xe3170ad5, S=1, 1024, 0xecb30526 -0, 1060, 1060, 1, 11928, 0x13d8c885, S=1, 1024, 0xecb30526 -0, 1070, 1070, 1, 11932, 0xecb5bdf7, S=1, 1024, 0xecb30526 -0, 1080, 1080, 1, 12281, 0x18bb76d5, S=1, 1024, 0xecb30526 -0, 1090, 1090, 1, 12334, 0x16147fc3, S=1, 1024, 0xecb30526 -0, 1100, 1100, 1, 12452, 0x61a8b3d7, S=1, 1024, 0xecb30526 -0, 1110, 1110, 1, 12695, 0x8b703e74, S=1, 1024, 0xecb30526 -0, 1120, 1120, 1, 12668, 0x19505176, S=1, 1024, 0xecb30526 -0, 1130, 1130, 1, 12957, 0x3b839f0d, S=1, 1024, 0xecb30526 -0, 1140, 1140, 1, 13054, 0xb8a5e3db, S=1, 1024, 0xecb30526 -0, 1150, 1150, 1, 13147, 0xdf5c2e68, S=1, 1024, 0xecb30526 -0, 1160, 1160, 1, 13171, 0x15961ca2, S=1, 1024, 0xecb30526 -0, 1170, 1170, 1, 13198, 0xfd855718, S=1, 1024, 0xecb30526 -0, 1180, 1180, 1, 13211, 0x1a625e31, S=1, 1024, 0xecb30526 -0, 1190, 1190, 1, 13210, 0x246661c9, S=1, 1024, 0xecb30526 -0, 1200, 1200, 1, 13467, 0xfcaaa461, S=1, 1024, 0xecb30526 -0, 1210, 1210, 1, 13665, 0x8100dbf2, S=1, 1024, 0xecb30526 -0, 1220, 1220, 1, 13692, 0xddd1eab9, S=1, 1024, 0xecb30526 -0, 1230, 1230, 1, 13821, 0xc70e2af0, S=1, 1024, 0xecb30526 -0, 1240, 1240, 1, 13946, 0xe15d9134, S=1, 1024, 0xecb30526 -0, 1250, 1250, 1, 14063, 0xf652d232, S=1, 1024, 0xecb30526 -0, 1260, 1260, 1, 14124, 0x756ccc81, S=1, 1024, 0xecb30526 -0, 1270, 1270, 1, 14331, 0x56d64fe8, S=1, 1024, 0xecb30526 -0, 1280, 1280, 1, 14469, 0x4c3faa7f, S=1, 1024, 0xecb30526 -0, 1290, 1290, 1, 14536, 0xad02a19b, S=1, 1024, 0xecb30526 -0, 1300, 1300, 1, 14608, 0x0971d168, S=1, 1024, 0xecb30526 -0, 1310, 1310, 1, 14898, 0x1a6827b3, S=1, 1024, 0xecb30526 -0, 1320, 1320, 1, 14978, 0xf9709fef, S=1, 1024, 0xecb30526 -0, 1330, 1330, 1, 15142, 0x3598da63, S=1, 1024, 0xecb30526 -0, 1340, 1340, 1, 15129, 0x062fb976, S=1, 1024, 0xecb30526 -0, 1350, 1350, 1, 15243, 0x0a6a12f9, S=1, 1024, 0xecb30526 -0, 1360, 1360, 1, 15337, 0x0f9a65d6, S=1, 1024, 0xecb30526 -0, 1370, 1370, 1, 15638, 0xf7bc9ef5, S=1, 1024, 0xecb30526 -0, 1380, 1380, 1, 15912, 0x2d5b26bb, S=1, 1024, 0xecb30526 -0, 1390, 1390, 1, 16041, 0xbfaf4857, S=1, 1024, 0xecb30526 -0, 1400, 1400, 1, 16228, 0xdac701f0, S=1, 1024, 0xecb30526 -0, 1410, 1410, 1, 16262, 0xcd0ae5e4, S=1, 1024, 0xecb30526 -0, 1420, 1420, 1, 16371, 0x9d4f0e73, S=1, 1024, 0xecb30526 -0, 1430, 1430, 1, 16661, 0xd37ba990, S=1, 1024, 0xecb30526 -0, 1440, 1440, 1, 16917, 0xd5b01774, S=1, 1024, 0xecb30526 -0, 1450, 1450, 1, 17149, 0x435ecdd4, S=1, 1024, 0xecb30526 -0, 1460, 1460, 1, 17172, 0x045fb234, S=1, 1024, 0xecb30526 -0, 1470, 1470, 1, 17315, 0xc5ddadab, S=1, 1024, 0xecb30526 -0, 1480, 1480, 1, 17397, 0xff8e15b6, S=1, 1024, 0xecb30526 -0, 1490, 1490, 1, 17431, 0x6832f8c0, S=1, 1024, 0xecb30526 -0, 1500, 1500, 1, 17576, 0x5c2a5445, S=1, 1024, 0xecb30526 -0, 1510, 1510, 1, 17764, 0x609f8c3b, S=1, 1024, 0xecb30526 -0, 1520, 1520, 1, 17826, 0x538c8532, S=1, 1024, 0xecb30526 -0, 1530, 1530, 1, 17918, 0x84fc9a95, S=1, 1024, 0xecb30526 -0, 1540, 1540, 1, 17823, 0x788fbada, S=1, 1024, 0xecb30526 -0, 1550, 1550, 1, 18142, 0x56881e47, S=1, 1024, 0xecb30526 -0, 1560, 1560, 1, 18257, 0xa35b86cf, S=1, 1024, 0xecb30526 -0, 1570, 1570, 1, 18337, 0x82ddbc21, S=1, 1024, 0xecb30526 -0, 1580, 1580, 1, 18293, 0xf0d838d6, S=1, 1024, 0xecb30526 -0, 1590, 1590, 1, 18418, 0x7ed8bba6, S=1, 1024, 0xecb30526 -0, 1600, 1600, 1, 18607, 0xccea47f6, S=1, 1024, 0xecb30526 -0, 1610, 1610, 1, 18916, 0x880ebd63, S=1, 1024, 0xecb30526 -0, 1620, 1620, 1, 19073, 0x055f02e3, S=1, 1024, 0xecb30526 -0, 1630, 1630, 1, 19168, 0xcc2c02d7, S=1, 1024, 0xecb30526 -0, 1640, 1640, 1, 19210, 0xa538ffc1, S=1, 1024, 0xecb30526 -0, 1650, 1650, 1, 19398, 0x4777644d, S=1, 1024, 0xecb30526 -0, 1660, 1660, 1, 19480, 0xcb2aa0fa, S=1, 1024, 0xecb30526 -0, 1670, 1670, 1, 19659, 0xe3c1122d, S=1, 1024, 0xecb30526 -0, 1680, 1680, 1, 19672, 0x1d1e193f, S=1, 1024, 0xecb30526 -0, 1690, 1690, 1, 19936, 0xcd036346, S=1, 1024, 0xecb30526 -0, 1700, 1700, 1, 19975, 0x96529b21, S=1, 1024, 0xecb30526 -0, 1710, 1710, 1, 20021, 0xcdaf8bb5, S=1, 1024, 0xecb30526 -0, 1720, 1720, 1, 20060, 0x1cea7784, S=1, 1024, 0xecb30526 +0, 1, 1, 1, 213, 0x23c24d3d, S=1, 1024, 0xf7700427 +0, 2, 2, 1, 131, 0x56d22a39, S=1, 1024, 0x03730427 +0, 3, 3, 1, 384, 0xb1d8a4bd, S=1, 1024, 0xf7700427 +0, 4, 4, 1, 381, 0x37a3a2c9, S=1, 1024, 0xf3740427 +0, 5, 5, 1, 430, 0x162bb3d3, S=1, 1024, 0xf3740427 +0, 6, 6, 1, 518, 0x195bd738, S=1, 1024, 0xf3740427 +0, 7, 7, 1, 535, 0x12cde6b7, S=1, 1024, 0xf3740427 +0, 8, 8, 1, 438, 0xa653b946, S=1, 1024, 0x0b6b0427 +0, 9, 9, 1, 923, 0xd2e2a35f, S=1, 1024, 0x0b6b0427 +0, 10, 10, 1, 694, 0xe1cf4a1f, S=1, 1024, 0x0b6b0427 +0, 11, 11, 1, 1194, 0xa6152c8a, S=1, 1024, 0x0b6b0427 +0, 12, 12, 1, 1291, 0x94d25581, S=1, 1024, 0x0b6b0427 +0, 13, 13, 1, 1245, 0x5b483525, S=1, 1024, 0x0b6b0427 +0, 14, 14, 1, 1330, 0xfb5351c8, S=1, 1024, 0x0b6b0427 +0, 15, 15, 1, 1276, 0x6f403914, S=1, 1024, 0x0b6b0427 +0, 16, 16, 1, 1475, 0xbf459755, S=1, 1024, 0x0b6b0427 +0, 17, 17, 1, 1784, 0xe9954aa7, S=1, 1024, 0xecb30526 +0, 18, 18, 1, 1675, 0x219dfaf8, S=1, 1024, 0xecb30526 +0, 19, 19, 1, 1509, 0xd7f5abbe, S=1, 1024, 0xecb30526 +0, 20, 20, 1, 1705, 0x44a01729, S=1, 1024, 0xecb30526 +0, 21, 21, 1, 1745, 0x31ff1f89, S=1, 1024, 0xecb30526 +0, 22, 22, 1, 1642, 0x55420147, S=1, 1024, 0xecb30526 +0, 23, 23, 1, 1718, 0x68ef1cb8, S=1, 1024, 0xecb30526 +0, 24, 24, 1, 1900, 0xd7737a09, S=1, 1024, 0xecb30526 +0, 25, 25, 1, 1807, 0x4f6c5140, S=1, 1024, 0xecb30526 +0, 26, 26, 1, 1915, 0x976d80e6, S=1, 1024, 0xecb30526 +0, 27, 27, 1, 2100, 0x0ae6d1ce, S=1, 1024, 0xecb30526 +0, 28, 28, 1, 2700, 0x7a89f104, S=1, 1024, 0xecb30526 +0, 29, 29, 1, 2673, 0xf6b6a71d, S=1, 1024, 0xecb30526 +0, 30, 30, 1, 2895, 0x9079484b, S=1, 1024, 0xecb30526 +0, 31, 31, 1, 3257, 0x0b0cd125, S=1, 1024, 0xecb30526 +0, 32, 32, 1, 3179, 0x3ee2c161, S=1, 1024, 0xecb30526 +0, 33, 33, 1, 3296, 0x6230e506, S=1, 1024, 0xecb30526 +0, 34, 34, 1, 3600, 0x021775d7, S=1, 1024, 0xecb30526 +0, 35, 35, 1, 3699, 0xfb03a043, S=1, 1024, 0xecb30526 +0, 36, 36, 1, 3814, 0x96a8d57e, S=1, 1024, 0xecb30526 +0, 37, 37, 1, 3627, 0x33a37f8f, S=1, 1024, 0xecb30526 +0, 38, 38, 1, 2950, 0x50806197, S=1, 1024, 0xecb30526 +0, 39, 39, 1, 3086, 0x72068d4c, S=1, 1024, 0xecb30526 +0, 40, 40, 1, 3094, 0x2880861f, S=1, 1024, 0xecb30526 +0, 41, 41, 1, 3456, 0x6d232a96, S=1, 1024, 0xecb30526 +0, 42, 42, 1, 4108, 0x46d75ebb, S=1, 1024, 0xecb30526 +0, 43, 43, 1, 4217, 0x04a258f4, S=1, 1024, 0xecb30526 +0, 44, 44, 1, 3613, 0x667f4ff8, S=1, 1024, 0xecb30526 +0, 45, 45, 1, 3910, 0x8f37e73e, S=1, 1024, 0xecb30526 +0, 46, 46, 1, 4461, 0x5db9e0bf, S=1, 1024, 0xecb30526 +0, 47, 47, 1, 4593, 0x883f2f49, S=1, 1024, 0xecb30526 +0, 48, 48, 1, 4822, 0x03d99b73, S=1, 1024, 0xecb30526 +0, 49, 49, 1, 5398, 0x39f7bff4, S=1, 1024, 0xecb30526 +0, 50, 50, 1, 5266, 0xd5ab9630, S=1, 1024, 0xecb30526 +0, 51, 51, 1, 5416, 0x5876e16f, S=1, 1024, 0xecb30526 +0, 52, 52, 1, 5519, 0x30ed05d8, S=1, 1024, 0xecb30526 +0, 53, 53, 1, 5701, 0x5bae5af7, S=1, 1024, 0xecb30526 +0, 54, 54, 1, 6160, 0x98364177, S=1, 1024, 0xecb30526 +0, 55, 55, 1, 6233, 0x52a05075, S=1, 1024, 0xecb30526 +0, 56, 56, 1, 5911, 0x04bfc46a, S=1, 1024, 0xecb30526 +0, 57, 57, 1, 5997, 0xf1e6f586, S=1, 1024, 0xecb30526 +0, 58, 58, 1, 5946, 0xe6f3f055, S=1, 1024, 0xecb30526 +0, 59, 59, 1, 6468, 0xc8a3cf61, S=1, 1024, 0xecb30526 +0, 60, 60, 1, 6737, 0xc27b3b79, S=1, 1024, 0xecb30526 +0, 61, 61, 1, 6275, 0x84d88e2b, S=1, 1024, 0xecb30526 +0, 62, 62, 1, 6641, 0xb44b3534, S=1, 1024, 0xecb30526 +0, 63, 63, 1, 6378, 0x3965888b, S=1, 1024, 0xecb30526 +0, 64, 64, 1, 6257, 0x12115750, S=1, 1024, 0xecb30526 +0, 65, 65, 1, 6908, 0x57137217, S=1, 1024, 0xecb30526 +0, 66, 66, 1, 7230, 0xbacc24ee, S=1, 1024, 0xecb30526 +0, 67, 67, 1, 7556, 0x1aa2a694, S=1, 1024, 0xecb30526 +0, 68, 68, 1, 7413, 0xbc9e7718, S=1, 1024, 0xecb30526 +0, 69, 69, 1, 7476, 0xb2a1aba0, S=1, 1024, 0xecb30526 +0, 70, 70, 1, 7596, 0x3301e56d, S=1, 1024, 0xecb30526 +0, 71, 71, 1, 7756, 0x8f2504f8, S=1, 1024, 0xecb30526 +0, 72, 72, 1, 8015, 0xd4146c80, S=1, 1024, 0xecb30526 +0, 73, 73, 1, 8128, 0x11b2bf4c, S=1, 1024, 0xecb30526 +0, 74, 74, 1, 8101, 0xc627adbe, S=1, 1024, 0xecb30526 +0, 75, 75, 1, 7863, 0xe99f3f3b, S=1, 1024, 0xecb30526 +0, 76, 76, 1, 7960, 0x4bc091b8, S=1, 1024, 0xecb30526 +0, 77, 77, 1, 8238, 0x1086ea8a, S=1, 1024, 0xecb30526 +0, 78, 78, 1, 8321, 0x3a404791, S=1, 1024, 0xecb30526 +0, 79, 79, 1, 8562, 0xcbdcc01e, S=1, 1024, 0xecb30526 +0, 80, 80, 1, 8746, 0xec190b22, S=1, 1024, 0xecb30526 +0, 81, 81, 1, 8578, 0x12e7a4e8, S=1, 1024, 0xecb30526 +0, 82, 82, 1, 8878, 0x51c05771, S=1, 1024, 0xecb30526 +0, 83, 83, 1, 9077, 0xe12b589b, S=1, 1024, 0xecb30526 +0, 84, 84, 1, 9310, 0xde3bf881, S=1, 1024, 0xecb30526 +0, 85, 85, 1, 9394, 0x1eba46cc, S=1, 1024, 0xecb30526 +0, 86, 86, 1, 9161, 0x7c359911, S=1, 1024, 0xecb30526 +0, 87, 87, 1, 9462, 0xccda3664, S=1, 1024, 0xecb30526 +0, 88, 88, 1, 9650, 0x6e6292fc, S=1, 1024, 0xecb30526 +0, 89, 89, 1, 9701, 0x08909b95, S=1, 1024, 0xecb30526 +0, 90, 90, 1, 9523, 0xe61b38bb, S=1, 1024, 0xecb30526 +0, 91, 91, 1, 9891, 0x96b90b98, S=1, 1024, 0xecb30526 +0, 92, 92, 1, 10005, 0x2db84c80, S=1, 1024, 0xecb30526 +0, 93, 93, 1, 10038, 0x37e52a72, S=1, 1024, 0xecb30526 +0, 94, 94, 1, 10086, 0x135a43e4, S=1, 1024, 0xecb30526 +0, 95, 95, 1, 10438, 0x472c0372, S=1, 1024, 0xecb30526 +0, 96, 96, 1, 10583, 0xcf4c5862, S=1, 1024, 0xecb30526 +0, 97, 97, 1, 10581, 0xce658137, S=1, 1024, 0xecb30526 +0, 98, 98, 1, 10807, 0x3954dad9, S=1, 1024, 0xecb30526 +0, 99, 99, 1, 11111, 0x5f8d504f, S=1, 1024, 0xecb30526 +0, 100, 100, 1, 11194, 0x3c7e6a77, S=1, 1024, 0xecb30526 +0, 101, 101, 1, 11240, 0x5112a0a3, S=1, 1024, 0xecb30526 +0, 102, 102, 1, 11483, 0xaf10f4fa, S=1, 1024, 0xecb30526 +0, 103, 103, 1, 11680, 0x44a25971, S=1, 1024, 0xecb30526 +0, 104, 104, 1, 11785, 0x7350b5db, S=1, 1024, 0xecb30526 +0, 105, 105, 1, 11436, 0xe3170ad5, S=1, 1024, 0xecb30526 +0, 106, 106, 1, 11928, 0x13d8c885, S=1, 1024, 0xecb30526 +0, 107, 107, 1, 11932, 0xecb5bdf7, S=1, 1024, 0xecb30526 +0, 108, 108, 1, 12281, 0x18bb76d5, S=1, 1024, 0xecb30526 +0, 109, 109, 1, 12334, 0x16147fc3, S=1, 1024, 0xecb30526 +0, 110, 110, 1, 12452, 0x61a8b3d7, S=1, 1024, 0xecb30526 +0, 111, 111, 1, 12695, 0x8b703e74, S=1, 1024, 0xecb30526 +0, 112, 112, 1, 12668, 0x19505176, S=1, 1024, 0xecb30526 +0, 113, 113, 1, 12957, 0x3b839f0d, S=1, 1024, 0xecb30526 +0, 114, 114, 1, 13054, 0xb8a5e3db, S=1, 1024, 0xecb30526 +0, 115, 115, 1, 13147, 0xdf5c2e68, S=1, 1024, 0xecb30526 +0, 116, 116, 1, 13171, 0x15961ca2, S=1, 1024, 0xecb30526 +0, 117, 117, 1, 13198, 0xfd855718, S=1, 1024, 0xecb30526 +0, 118, 118, 1, 13211, 0x1a625e31, S=1, 1024, 0xecb30526 +0, 119, 119, 1, 13210, 0x246661c9, S=1, 1024, 0xecb30526 +0, 120, 120, 1, 13467, 0xfcaaa461, S=1, 1024, 0xecb30526 +0, 121, 121, 1, 13665, 0x8100dbf2, S=1, 1024, 0xecb30526 +0, 122, 122, 1, 13692, 0xddd1eab9, S=1, 1024, 0xecb30526 +0, 123, 123, 1, 13821, 0xc70e2af0, S=1, 1024, 0xecb30526 +0, 124, 124, 1, 13946, 0xe15d9134, S=1, 1024, 0xecb30526 +0, 125, 125, 1, 14063, 0xf652d232, S=1, 1024, 0xecb30526 +0, 126, 126, 1, 14124, 0x756ccc81, S=1, 1024, 0xecb30526 +0, 127, 127, 1, 14331, 0x56d64fe8, S=1, 1024, 0xecb30526 +0, 128, 128, 1, 14469, 0x4c3faa7f, S=1, 1024, 0xecb30526 +0, 129, 129, 1, 14536, 0xad02a19b, S=1, 1024, 0xecb30526 +0, 130, 130, 1, 14608, 0x0971d168, S=1, 1024, 0xecb30526 +0, 131, 131, 1, 14898, 0x1a6827b3, S=1, 1024, 0xecb30526 +0, 132, 132, 1, 14978, 0xf9709fef, S=1, 1024, 0xecb30526 +0, 133, 133, 1, 15142, 0x3598da63, S=1, 1024, 0xecb30526 +0, 134, 134, 1, 15129, 0x062fb976, S=1, 1024, 0xecb30526 +0, 135, 135, 1, 15243, 0x0a6a12f9, S=1, 1024, 0xecb30526 +0, 136, 136, 1, 15337, 0x0f9a65d6, S=1, 1024, 0xecb30526 +0, 137, 137, 1, 15638, 0xf7bc9ef5, S=1, 1024, 0xecb30526 +0, 138, 138, 1, 15912, 0x2d5b26bb, S=1, 1024, 0xecb30526 +0, 139, 139, 1, 16041, 0xbfaf4857, S=1, 1024, 0xecb30526 +0, 140, 140, 1, 16228, 0xdac701f0, S=1, 1024, 0xecb30526 +0, 141, 141, 1, 16262, 0xcd0ae5e4, S=1, 1024, 0xecb30526 +0, 142, 142, 1, 16371, 0x9d4f0e73, S=1, 1024, 0xecb30526 +0, 143, 143, 1, 16661, 0xd37ba990, S=1, 1024, 0xecb30526 +0, 144, 144, 1, 16917, 0xd5b01774, S=1, 1024, 0xecb30526 +0, 145, 145, 1, 17149, 0x435ecdd4, S=1, 1024, 0xecb30526 +0, 146, 146, 1, 17172, 0x045fb234, S=1, 1024, 0xecb30526 +0, 147, 147, 1, 17315, 0xc5ddadab, S=1, 1024, 0xecb30526 +0, 148, 148, 1, 17397, 0xff8e15b6, S=1, 1024, 0xecb30526 +0, 149, 149, 1, 17431, 0x6832f8c0, S=1, 1024, 0xecb30526 +0, 150, 150, 1, 17576, 0x5c2a5445, S=1, 1024, 0xecb30526 +0, 151, 151, 1, 17764, 0x609f8c3b, S=1, 1024, 0xecb30526 +0, 152, 152, 1, 17826, 0x538c8532, S=1, 1024, 0xecb30526 +0, 153, 153, 1, 17918, 0x84fc9a95, S=1, 1024, 0xecb30526 +0, 154, 154, 1, 17823, 0x788fbada, S=1, 1024, 0xecb30526 +0, 155, 155, 1, 18142, 0x56881e47, S=1, 1024, 0xecb30526 +0, 156, 156, 1, 18257, 0xa35b86cf, S=1, 1024, 0xecb30526 +0, 157, 157, 1, 18337, 0x82ddbc21, S=1, 1024, 0xecb30526 +0, 158, 158, 1, 18293, 0xf0d838d6, S=1, 1024, 0xecb30526 +0, 159, 159, 1, 18418, 0x7ed8bba6, S=1, 1024, 0xecb30526 +0, 160, 160, 1, 18607, 0xccea47f6, S=1, 1024, 0xecb30526 +0, 161, 161, 1, 18916, 0x880ebd63, S=1, 1024, 0xecb30526 +0, 162, 162, 1, 19073, 0x055f02e3, S=1, 1024, 0xecb30526 +0, 163, 163, 1, 19168, 0xcc2c02d7, S=1, 1024, 0xecb30526 +0, 164, 164, 1, 19210, 0xa538ffc1, S=1, 1024, 0xecb30526 +0, 165, 165, 1, 19398, 0x4777644d, S=1, 1024, 0xecb30526 +0, 166, 166, 1, 19480, 0xcb2aa0fa, S=1, 1024, 0xecb30526 +0, 167, 167, 1, 19659, 0xe3c1122d, S=1, 1024, 0xecb30526 +0, 168, 168, 1, 19672, 0x1d1e193f, S=1, 1024, 0xecb30526 +0, 169, 169, 1, 19936, 0xcd036346, S=1, 1024, 0xecb30526 +0, 170, 170, 1, 19975, 0x96529b21, S=1, 1024, 0xecb30526 +0, 171, 171, 1, 20021, 0xcdaf8bb5, S=1, 1024, 0xecb30526 +0, 172, 172, 1, 20060, 0x1cea7784, S=1, 1024, 0xecb30526 diff --git a/tests/ref/fate/gifenc-rgb8 b/tests/ref/fate/gifenc-rgb8 index 226b26ee1..a89417322 100644 --- a/tests/ref/fate/gifenc-rgb8 +++ b/tests/ref/fate/gifenc-rgb8 @@ -1,174 +1,174 @@ -#tb 0: 1/100 +#tb 0: 1/10 0, 0, 0, 1, 552, 0x47602c6c -0, 10, 10, 1, 297, 0x49dd8847, S=1, 1024, 0xcfc8799f -0, 20, 20, 1, 438, 0x4776d352, S=1, 1024, 0xcfc8799f -0, 30, 30, 1, 450, 0x2254d187, S=1, 1024, 0xcfc8799f -0, 40, 40, 1, 547, 0xe16104bc, S=1, 1024, 0xcfc8799f -0, 50, 50, 1, 614, 0x0fdc2027, S=1, 1024, 0xcfc8799f -0, 60, 60, 1, 642, 0xa0af1edf, S=1, 1024, 0xcfc8799f -0, 70, 70, 1, 660, 0xd0763931, S=1, 1024, 0xcfc8799f -0, 80, 80, 1, 821, 0xc38f7fac, S=1, 1024, 0xcfc8799f -0, 90, 90, 1, 1157, 0x4c112ecd, S=1, 1024, 0xcfc8799f -0, 100, 100, 1, 179, 0x0690541c, S=1, 1024, 0xcfc8799f -0, 110, 110, 1, 1333, 0x216f70a7, S=1, 1024, 0xcfc8799f -0, 120, 120, 1, 1638, 0x901c093d, S=1, 1024, 0xcfc8799f -0, 130, 130, 1, 1531, 0xc9bae5ff, S=1, 1024, 0xcfc8799f -0, 140, 140, 1, 1720, 0xce854743, S=1, 1024, 0xcfc8799f -0, 150, 150, 1, 1910, 0x2690866d, S=1, 1024, 0xcfc8799f -0, 160, 160, 1, 2124, 0xa586dad0, S=1, 1024, 0xcfc8799f -0, 170, 170, 1, 2248, 0x9ddc2a88, S=1, 1024, 0xcfc8799f -0, 180, 180, 1, 2311, 0xd64235af, S=1, 1024, 0xcfc8799f -0, 190, 190, 1, 2408, 0xe2a66cc9, S=1, 1024, 0xcfc8799f -0, 200, 200, 1, 2601, 0xeab6c267, S=1, 1024, 0xcfc8799f -0, 210, 210, 1, 2687, 0xfe1d0311, S=1, 1024, 0xcfc8799f -0, 220, 220, 1, 2784, 0xca600dee, S=1, 1024, 0xcfc8799f -0, 230, 230, 1, 2884, 0xc7134b99, S=1, 1024, 0xcfc8799f -0, 240, 240, 1, 2982, 0x0b1e7825, S=1, 1024, 0xcfc8799f -0, 250, 250, 1, 3101, 0x3e029e0e, S=1, 1024, 0xcfc8799f -0, 260, 260, 1, 3253, 0x846af678, S=1, 1024, 0xcfc8799f -0, 270, 270, 1, 3329, 0x29a81b71, S=1, 1024, 0xcfc8799f -0, 280, 280, 1, 3572, 0xa3e08a52, S=1, 1024, 0xcfc8799f -0, 290, 290, 1, 3807, 0x18e1fed2, S=1, 1024, 0xcfc8799f -0, 300, 300, 1, 2750, 0xff6e1f9e, S=1, 1024, 0xcfc8799f -0, 310, 310, 1, 4031, 0x6d4f7329, S=1, 1024, 0xcfc8799f -0, 320, 320, 1, 3025, 0xb43c9e94, S=1, 1024, 0xcfc8799f -0, 330, 330, 1, 4295, 0xc1850a80, S=1, 1024, 0xcfc8799f -0, 340, 340, 1, 2044, 0x0440c072, S=1, 1024, 0xcfc8799f -0, 350, 350, 1, 3212, 0xe91af08f, S=1, 1024, 0xcfc8799f -0, 360, 360, 1, 2281, 0x6a414aa1, S=1, 1024, 0xcfc8799f -0, 370, 370, 1, 3633, 0xac779aa3, S=1, 1024, 0xcfc8799f -0, 380, 380, 1, 3552, 0xed2c75b2, S=1, 1024, 0xcfc8799f -0, 390, 390, 1, 3690, 0x2020dd0d, S=1, 1024, 0xcfc8799f -0, 400, 400, 1, 1558, 0x2c14e4b2, S=1, 1024, 0xcfc8799f -0, 410, 410, 1, 940, 0x4927cd90, S=1, 1024, 0xcfc8799f -0, 420, 420, 1, 273, 0x138c7831, S=1, 1024, 0xcfc8799f -0, 430, 430, 1, 930, 0xf1c3ae3f, S=1, 1024, 0xcfc8799f -0, 440, 440, 1, 271, 0x6d338044, S=1, 1024, 0xcfc8799f -0, 450, 450, 1, 196, 0xa5de5322, S=1, 1024, 0xcfc8799f -0, 460, 460, 1, 4299, 0x5bac0d86, S=1, 1024, 0xcfc8799f -0, 470, 470, 1, 4895, 0xc43639a6, S=1, 1024, 0xcfc8799f -0, 480, 480, 1, 4928, 0xf17d13e8, S=1, 1024, 0xcfc8799f -0, 490, 490, 1, 4941, 0x71915520, S=1, 1024, 0xcfc8799f -0, 500, 500, 1, 4154, 0xc860b8a6, S=1, 1024, 0xcfc8799f -0, 510, 510, 1, 4678, 0x2651c339, S=1, 1024, 0xcfc8799f -0, 520, 520, 1, 4741, 0xffd6bb45, S=1, 1024, 0xcfc8799f -0, 530, 530, 1, 4982, 0x132c5977, S=1, 1024, 0xcfc8799f -0, 540, 540, 1, 5179, 0x97aac3a1, S=1, 1024, 0xcfc8799f -0, 550, 550, 1, 5046, 0x836a80cd, S=1, 1024, 0xcfc8799f -0, 560, 560, 1, 5140, 0xa725c1e7, S=1, 1024, 0xcfc8799f -0, 570, 570, 1, 4289, 0x7b3afbc0, S=1, 1024, 0xcfc8799f -0, 580, 580, 1, 5079, 0xb2e7a2de, S=1, 1024, 0xcfc8799f -0, 590, 590, 1, 5284, 0xb757dfe1, S=1, 1024, 0xcfc8799f -0, 600, 600, 1, 5426, 0xf9f11e57, S=1, 1024, 0xcfc8799f -0, 610, 610, 1, 4645, 0xf0f289e1, S=1, 1024, 0xcfc8799f -0, 620, 620, 1, 5263, 0x8617d7e9, S=1, 1024, 0xcfc8799f -0, 630, 630, 1, 5221, 0x26e3ca43, S=1, 1024, 0xcfc8799f -0, 640, 640, 1, 5217, 0x90989cfb, S=1, 1024, 0xcfc8799f -0, 650, 650, 1, 5395, 0xe29a01cb, S=1, 1024, 0xcfc8799f -0, 660, 660, 1, 5220, 0xe2dee355, S=1, 1024, 0xcfc8799f -0, 670, 670, 1, 5704, 0xcfbcd55e, S=1, 1024, 0xcfc8799f -0, 680, 680, 1, 5636, 0x7fc2a1e5, S=1, 1024, 0xcfc8799f -0, 690, 690, 1, 5818, 0x6090ebbd, S=1, 1024, 0xcfc8799f -0, 700, 700, 1, 5763, 0xc110c791, S=1, 1024, 0xcfc8799f -0, 710, 710, 1, 6116, 0xb4ee8e30, S=1, 1024, 0xcfc8799f -0, 720, 720, 1, 6069, 0x21b263db, S=1, 1024, 0xcfc8799f -0, 730, 730, 1, 5796, 0x2514df52, S=1, 1024, 0xcfc8799f -0, 740, 740, 1, 5999, 0x1c3c3701, S=1, 1024, 0xcfc8799f -0, 750, 750, 1, 6220, 0x8340b150, S=1, 1024, 0xcfc8799f -0, 760, 760, 1, 6374, 0x00d8eaa5, S=1, 1024, 0xcfc8799f -0, 770, 770, 1, 6465, 0x74c4778a, S=1, 1024, 0xcfc8799f -0, 780, 780, 1, 7019, 0xdb1a28a3, S=1, 1024, 0xcfc8799f -0, 790, 790, 1, 7255, 0x1e19b76e, S=1, 1024, 0xcfc8799f -0, 800, 800, 1, 8197, 0x26bc6a79, S=1, 1024, 0xcfc8799f -0, 810, 810, 1, 8358, 0x118781e0, S=1, 1024, 0xcfc8799f -0, 820, 820, 1, 7708, 0xfc0c963d, S=1, 1024, 0xcfc8799f -0, 830, 830, 1, 7412, 0xdcc311ee, S=1, 1024, 0xcfc8799f -0, 840, 840, 1, 7541, 0x4d2819c1, S=1, 1024, 0xcfc8799f -0, 850, 850, 1, 7948, 0xf12eca3d, S=1, 1024, 0xcfc8799f -0, 860, 860, 1, 8408, 0x43add468, S=1, 1024, 0xcfc8799f -0, 870, 870, 1, 8056, 0x2d162377, S=1, 1024, 0xcfc8799f -0, 880, 880, 1, 7401, 0x26ebb649, S=1, 1024, 0xcfc8799f -0, 890, 890, 1, 7494, 0x35fcf9ae, S=1, 1024, 0xcfc8799f -0, 900, 900, 1, 7806, 0x4238723d, S=1, 1024, 0xcfc8799f -0, 910, 910, 1, 7768, 0xb01e795a, S=1, 1024, 0xcfc8799f -0, 920, 920, 1, 7749, 0x6ab39c12, S=1, 1024, 0xcfc8799f -0, 930, 930, 1, 8047, 0x0e5f24aa, S=1, 1024, 0xcfc8799f -0, 940, 940, 1, 7618, 0xd787340f, S=1, 1024, 0xcfc8799f -0, 950, 950, 1, 7979, 0x0824c4df, S=1, 1024, 0xcfc8799f -0, 960, 960, 1, 12062, 0xc46d9d92, S=1, 1024, 0xcfc8799f -0, 970, 970, 1, 12317, 0x1314dc0c, S=1, 1024, 0xcfc8799f -0, 980, 980, 1, 12217, 0x78c2ed30, S=1, 1024, 0xcfc8799f -0, 990, 990, 1, 11227, 0x2a578eb9, S=1, 1024, 0xcfc8799f -0, 1000, 1000, 1, 11108, 0x4eaa068c, S=1, 1024, 0xcfc8799f -0, 1010, 1010, 1, 11366, 0x48f8993f, S=1, 1024, 0xcfc8799f -0, 1020, 1020, 1, 11896, 0x32414841, S=1, 1024, 0xcfc8799f -0, 1030, 1030, 1, 11479, 0xeaa38225, S=1, 1024, 0xcfc8799f -0, 1040, 1040, 1, 13395, 0xaa9d4c72, S=1, 1024, 0xcfc8799f -0, 1050, 1050, 1, 12913, 0x28854353, S=1, 1024, 0xcfc8799f -0, 1060, 1060, 1, 13864, 0x663df630, S=1, 1024, 0xcfc8799f -0, 1070, 1070, 1, 13551, 0xf7ba7be7, S=1, 1024, 0xcfc8799f -0, 1080, 1080, 1, 14041, 0x2dc071b9, S=1, 1024, 0xcfc8799f -0, 1090, 1090, 1, 14144, 0x33a03d1d, S=1, 1024, 0xcfc8799f -0, 1100, 1100, 1, 14277, 0x6bda5935, S=1, 1024, 0xcfc8799f -0, 1110, 1110, 1, 14424, 0xa696efd8, S=1, 1024, 0xcfc8799f -0, 1120, 1120, 1, 14689, 0x8e3ad12c, S=1, 1024, 0xcfc8799f -0, 1130, 1130, 1, 14598, 0x544668b4, S=1, 1024, 0xcfc8799f -0, 1140, 1140, 1, 15213, 0x60009558, S=1, 1024, 0xcfc8799f -0, 1150, 1150, 1, 15425, 0x86e5adf4, S=1, 1024, 0xcfc8799f -0, 1160, 1160, 1, 15595, 0x878d09b9, S=1, 1024, 0xcfc8799f -0, 1170, 1170, 1, 15598, 0x10daabc4, S=1, 1024, 0xcfc8799f -0, 1180, 1180, 1, 15863, 0x2462016c, S=1, 1024, 0xcfc8799f -0, 1190, 1190, 1, 15717, 0xe05041c4, S=1, 1024, 0xcfc8799f -0, 1200, 1200, 1, 16078, 0x7c8f3a8c, S=1, 1024, 0xcfc8799f -0, 1210, 1210, 1, 16225, 0x9771a52e, S=1, 1024, 0xcfc8799f -0, 1220, 1220, 1, 16135, 0x2dfc1692, S=1, 1024, 0xcfc8799f -0, 1230, 1230, 1, 16661, 0x09c96d7e, S=1, 1024, 0xcfc8799f -0, 1240, 1240, 1, 16619, 0xc4735b56, S=1, 1024, 0xcfc8799f -0, 1250, 1250, 1, 16829, 0x589dc13f, S=1, 1024, 0xcfc8799f -0, 1260, 1260, 1, 16944, 0x997cd18f, S=1, 1024, 0xcfc8799f -0, 1270, 1270, 1, 17119, 0x6c396b60, S=1, 1024, 0xcfc8799f -0, 1280, 1280, 1, 17150, 0x8e603d31, S=1, 1024, 0xcfc8799f -0, 1290, 1290, 1, 17321, 0x0bbcee5a, S=1, 1024, 0xcfc8799f -0, 1300, 1300, 1, 17395, 0x99f0c974, S=1, 1024, 0xcfc8799f -0, 1310, 1310, 1, 17666, 0x37184223, S=1, 1024, 0xcfc8799f -0, 1320, 1320, 1, 17730, 0xa0d385b3, S=1, 1024, 0xcfc8799f -0, 1330, 1330, 1, 17934, 0xb22cc97d, S=1, 1024, 0xcfc8799f -0, 1340, 1340, 1, 17944, 0x0cd309c6, S=1, 1024, 0xcfc8799f -0, 1350, 1350, 1, 18238, 0x6b7e3237, S=1, 1024, 0xcfc8799f -0, 1360, 1360, 1, 18391, 0x4df3c48a, S=1, 1024, 0xcfc8799f -0, 1370, 1370, 1, 18543, 0x90a2f238, S=1, 1024, 0xcfc8799f -0, 1380, 1380, 1, 18939, 0xc57dda5b, S=1, 1024, 0xcfc8799f -0, 1390, 1390, 1, 19145, 0x1267294a, S=1, 1024, 0xcfc8799f -0, 1400, 1400, 1, 19120, 0xeac6a9c3, S=1, 1024, 0xcfc8799f -0, 1410, 1410, 1, 19130, 0x31f3edbc, S=1, 1024, 0xcfc8799f -0, 1420, 1420, 1, 19494, 0x3259a2f3, S=1, 1024, 0xcfc8799f -0, 1430, 1430, 1, 19534, 0xda22a752, S=1, 1024, 0xcfc8799f -0, 1440, 1440, 1, 19747, 0x8805c379, S=1, 1024, 0xcfc8799f -0, 1450, 1450, 1, 20114, 0xaaf96864, S=1, 1024, 0xcfc8799f -0, 1460, 1460, 1, 20257, 0x7223da26, S=1, 1024, 0xcfc8799f -0, 1470, 1470, 1, 20370, 0x08ef382a, S=1, 1024, 0xcfc8799f -0, 1480, 1480, 1, 20292, 0x4b47f207, S=1, 1024, 0xcfc8799f -0, 1490, 1490, 1, 20491, 0xeedd6d1c, S=1, 1024, 0xcfc8799f -0, 1500, 1500, 1, 20647, 0xb0d1dd45, S=1, 1024, 0xcfc8799f -0, 1510, 1510, 1, 20666, 0x382cc8a4, S=1, 1024, 0xcfc8799f -0, 1520, 1520, 1, 21007, 0x398f4f7d, S=1, 1024, 0xcfc8799f -0, 1530, 1530, 1, 21058, 0xd6616a9d, S=1, 1024, 0xcfc8799f -0, 1540, 1540, 1, 21153, 0x988749db, S=1, 1024, 0xcfc8799f -0, 1550, 1550, 1, 21078, 0x1b328059, S=1, 1024, 0xcfc8799f -0, 1560, 1560, 1, 21458, 0x6348529c, S=1, 1024, 0xcfc8799f -0, 1570, 1570, 1, 21669, 0xcf63e2de, S=1, 1024, 0xcfc8799f -0, 1580, 1580, 1, 21581, 0x1fc021af, S=1, 1024, 0xcfc8799f -0, 1590, 1590, 1, 21654, 0x899dab18, S=1, 1024, 0xcfc8799f -0, 1600, 1600, 1, 21987, 0x634086fe, S=1, 1024, 0xcfc8799f -0, 1610, 1610, 1, 22205, 0x617a7335, S=1, 1024, 0xcfc8799f -0, 1620, 1620, 1, 22475, 0x9fa2e01c, S=1, 1024, 0xcfc8799f -0, 1630, 1630, 1, 22490, 0x7dc5376c, S=1, 1024, 0xcfc8799f -0, 1640, 1640, 1, 22460, 0x33e6bbfe, S=1, 1024, 0xcfc8799f -0, 1650, 1650, 1, 22861, 0x18993510, S=1, 1024, 0xcfc8799f -0, 1660, 1660, 1, 22746, 0xdff85615, S=1, 1024, 0xcfc8799f -0, 1670, 1670, 1, 23165, 0xf0ac66a3, S=1, 1024, 0xcfc8799f -0, 1680, 1680, 1, 23273, 0x13869ad9, S=1, 1024, 0xcfc8799f -0, 1690, 1690, 1, 23211, 0xd30b6205, S=1, 1024, 0xcfc8799f -0, 1700, 1700, 1, 23648, 0xa0cef01b, S=1, 1024, 0xcfc8799f -0, 1710, 1710, 1, 23675, 0x760460b9, S=1, 1024, 0xcfc8799f -0, 1720, 1720, 1, 23874, 0xacf998c5, S=1, 1024, 0xcfc8799f +0, 1, 1, 1, 297, 0x49dd8847, S=1, 1024, 0xcfc8799f +0, 2, 2, 1, 438, 0x4776d352, S=1, 1024, 0xcfc8799f +0, 3, 3, 1, 450, 0x2254d187, S=1, 1024, 0xcfc8799f +0, 4, 4, 1, 547, 0xe16104bc, S=1, 1024, 0xcfc8799f +0, 5, 5, 1, 614, 0x0fdc2027, S=1, 1024, 0xcfc8799f +0, 6, 6, 1, 642, 0xa0af1edf, S=1, 1024, 0xcfc8799f +0, 7, 7, 1, 660, 0xd0763931, S=1, 1024, 0xcfc8799f +0, 8, 8, 1, 821, 0xc38f7fac, S=1, 1024, 0xcfc8799f +0, 9, 9, 1, 1157, 0x4c112ecd, S=1, 1024, 0xcfc8799f +0, 10, 10, 1, 179, 0x0690541c, S=1, 1024, 0xcfc8799f +0, 11, 11, 1, 1333, 0x216f70a7, S=1, 1024, 0xcfc8799f +0, 12, 12, 1, 1638, 0x901c093d, S=1, 1024, 0xcfc8799f +0, 13, 13, 1, 1531, 0xc9bae5ff, S=1, 1024, 0xcfc8799f +0, 14, 14, 1, 1720, 0xce854743, S=1, 1024, 0xcfc8799f +0, 15, 15, 1, 1910, 0x2690866d, S=1, 1024, 0xcfc8799f +0, 16, 16, 1, 2124, 0xa586dad0, S=1, 1024, 0xcfc8799f +0, 17, 17, 1, 2248, 0x9ddc2a88, S=1, 1024, 0xcfc8799f +0, 18, 18, 1, 2311, 0xd64235af, S=1, 1024, 0xcfc8799f +0, 19, 19, 1, 2408, 0xe2a66cc9, S=1, 1024, 0xcfc8799f +0, 20, 20, 1, 2601, 0xeab6c267, S=1, 1024, 0xcfc8799f +0, 21, 21, 1, 2687, 0xfe1d0311, S=1, 1024, 0xcfc8799f +0, 22, 22, 1, 2784, 0xca600dee, S=1, 1024, 0xcfc8799f +0, 23, 23, 1, 2884, 0xc7134b99, S=1, 1024, 0xcfc8799f +0, 24, 24, 1, 2982, 0x0b1e7825, S=1, 1024, 0xcfc8799f +0, 25, 25, 1, 3101, 0x3e029e0e, S=1, 1024, 0xcfc8799f +0, 26, 26, 1, 3253, 0x846af678, S=1, 1024, 0xcfc8799f +0, 27, 27, 1, 3329, 0x29a81b71, S=1, 1024, 0xcfc8799f +0, 28, 28, 1, 3572, 0xa3e08a52, S=1, 1024, 0xcfc8799f +0, 29, 29, 1, 3807, 0x18e1fed2, S=1, 1024, 0xcfc8799f +0, 30, 30, 1, 2750, 0xff6e1f9e, S=1, 1024, 0xcfc8799f +0, 31, 31, 1, 4031, 0x6d4f7329, S=1, 1024, 0xcfc8799f +0, 32, 32, 1, 3025, 0xb43c9e94, S=1, 1024, 0xcfc8799f +0, 33, 33, 1, 4295, 0xc1850a80, S=1, 1024, 0xcfc8799f +0, 34, 34, 1, 2044, 0x0440c072, S=1, 1024, 0xcfc8799f +0, 35, 35, 1, 3212, 0xe91af08f, S=1, 1024, 0xcfc8799f +0, 36, 36, 1, 2281, 0x6a414aa1, S=1, 1024, 0xcfc8799f +0, 37, 37, 1, 3633, 0xac779aa3, S=1, 1024, 0xcfc8799f +0, 38, 38, 1, 3552, 0xed2c75b2, S=1, 1024, 0xcfc8799f +0, 39, 39, 1, 3690, 0x2020dd0d, S=1, 1024, 0xcfc8799f +0, 40, 40, 1, 1558, 0x2c14e4b2, S=1, 1024, 0xcfc8799f +0, 41, 41, 1, 940, 0x4927cd90, S=1, 1024, 0xcfc8799f +0, 42, 42, 1, 273, 0x138c7831, S=1, 1024, 0xcfc8799f +0, 43, 43, 1, 930, 0xf1c3ae3f, S=1, 1024, 0xcfc8799f +0, 44, 44, 1, 271, 0x6d338044, S=1, 1024, 0xcfc8799f +0, 45, 45, 1, 196, 0xa5de5322, S=1, 1024, 0xcfc8799f +0, 46, 46, 1, 4299, 0x5bac0d86, S=1, 1024, 0xcfc8799f +0, 47, 47, 1, 4895, 0xc43639a6, S=1, 1024, 0xcfc8799f +0, 48, 48, 1, 4928, 0xf17d13e8, S=1, 1024, 0xcfc8799f +0, 49, 49, 1, 4941, 0x71915520, S=1, 1024, 0xcfc8799f +0, 50, 50, 1, 4154, 0xc860b8a6, S=1, 1024, 0xcfc8799f +0, 51, 51, 1, 4678, 0x2651c339, S=1, 1024, 0xcfc8799f +0, 52, 52, 1, 4741, 0xffd6bb45, S=1, 1024, 0xcfc8799f +0, 53, 53, 1, 4982, 0x132c5977, S=1, 1024, 0xcfc8799f +0, 54, 54, 1, 5179, 0x97aac3a1, S=1, 1024, 0xcfc8799f +0, 55, 55, 1, 5046, 0x836a80cd, S=1, 1024, 0xcfc8799f +0, 56, 56, 1, 5140, 0xa725c1e7, S=1, 1024, 0xcfc8799f +0, 57, 57, 1, 4289, 0x7b3afbc0, S=1, 1024, 0xcfc8799f +0, 58, 58, 1, 5079, 0xb2e7a2de, S=1, 1024, 0xcfc8799f +0, 59, 59, 1, 5284, 0xb757dfe1, S=1, 1024, 0xcfc8799f +0, 60, 60, 1, 5426, 0xf9f11e57, S=1, 1024, 0xcfc8799f +0, 61, 61, 1, 4645, 0xf0f289e1, S=1, 1024, 0xcfc8799f +0, 62, 62, 1, 5263, 0x8617d7e9, S=1, 1024, 0xcfc8799f +0, 63, 63, 1, 5221, 0x26e3ca43, S=1, 1024, 0xcfc8799f +0, 64, 64, 1, 5217, 0x90989cfb, S=1, 1024, 0xcfc8799f +0, 65, 65, 1, 5395, 0xe29a01cb, S=1, 1024, 0xcfc8799f +0, 66, 66, 1, 5220, 0xe2dee355, S=1, 1024, 0xcfc8799f +0, 67, 67, 1, 5704, 0xcfbcd55e, S=1, 1024, 0xcfc8799f +0, 68, 68, 1, 5636, 0x7fc2a1e5, S=1, 1024, 0xcfc8799f +0, 69, 69, 1, 5818, 0x6090ebbd, S=1, 1024, 0xcfc8799f +0, 70, 70, 1, 5763, 0xc110c791, S=1, 1024, 0xcfc8799f +0, 71, 71, 1, 6116, 0xb4ee8e30, S=1, 1024, 0xcfc8799f +0, 72, 72, 1, 6069, 0x21b263db, S=1, 1024, 0xcfc8799f +0, 73, 73, 1, 5796, 0x2514df52, S=1, 1024, 0xcfc8799f +0, 74, 74, 1, 5999, 0x1c3c3701, S=1, 1024, 0xcfc8799f +0, 75, 75, 1, 6220, 0x8340b150, S=1, 1024, 0xcfc8799f +0, 76, 76, 1, 6374, 0x00d8eaa5, S=1, 1024, 0xcfc8799f +0, 77, 77, 1, 6465, 0x74c4778a, S=1, 1024, 0xcfc8799f +0, 78, 78, 1, 7019, 0xdb1a28a3, S=1, 1024, 0xcfc8799f +0, 79, 79, 1, 7255, 0x1e19b76e, S=1, 1024, 0xcfc8799f +0, 80, 80, 1, 8197, 0x26bc6a79, S=1, 1024, 0xcfc8799f +0, 81, 81, 1, 8358, 0x118781e0, S=1, 1024, 0xcfc8799f +0, 82, 82, 1, 7708, 0xfc0c963d, S=1, 1024, 0xcfc8799f +0, 83, 83, 1, 7412, 0xdcc311ee, S=1, 1024, 0xcfc8799f +0, 84, 84, 1, 7541, 0x4d2819c1, S=1, 1024, 0xcfc8799f +0, 85, 85, 1, 7948, 0xf12eca3d, S=1, 1024, 0xcfc8799f +0, 86, 86, 1, 8408, 0x43add468, S=1, 1024, 0xcfc8799f +0, 87, 87, 1, 8056, 0x2d162377, S=1, 1024, 0xcfc8799f +0, 88, 88, 1, 7401, 0x26ebb649, S=1, 1024, 0xcfc8799f +0, 89, 89, 1, 7494, 0x35fcf9ae, S=1, 1024, 0xcfc8799f +0, 90, 90, 1, 7806, 0x4238723d, S=1, 1024, 0xcfc8799f +0, 91, 91, 1, 7768, 0xb01e795a, S=1, 1024, 0xcfc8799f +0, 92, 92, 1, 7749, 0x6ab39c12, S=1, 1024, 0xcfc8799f +0, 93, 93, 1, 8047, 0x0e5f24aa, S=1, 1024, 0xcfc8799f +0, 94, 94, 1, 7618, 0xd787340f, S=1, 1024, 0xcfc8799f +0, 95, 95, 1, 7979, 0x0824c4df, S=1, 1024, 0xcfc8799f +0, 96, 96, 1, 12062, 0xc46d9d92, S=1, 1024, 0xcfc8799f +0, 97, 97, 1, 12317, 0x1314dc0c, S=1, 1024, 0xcfc8799f +0, 98, 98, 1, 12217, 0x78c2ed30, S=1, 1024, 0xcfc8799f +0, 99, 99, 1, 11227, 0x2a578eb9, S=1, 1024, 0xcfc8799f +0, 100, 100, 1, 11108, 0x4eaa068c, S=1, 1024, 0xcfc8799f +0, 101, 101, 1, 11366, 0x48f8993f, S=1, 1024, 0xcfc8799f +0, 102, 102, 1, 11896, 0x32414841, S=1, 1024, 0xcfc8799f +0, 103, 103, 1, 11479, 0xeaa38225, S=1, 1024, 0xcfc8799f +0, 104, 104, 1, 13395, 0xaa9d4c72, S=1, 1024, 0xcfc8799f +0, 105, 105, 1, 12913, 0x28854353, S=1, 1024, 0xcfc8799f +0, 106, 106, 1, 13864, 0x663df630, S=1, 1024, 0xcfc8799f +0, 107, 107, 1, 13551, 0xf7ba7be7, S=1, 1024, 0xcfc8799f +0, 108, 108, 1, 14041, 0x2dc071b9, S=1, 1024, 0xcfc8799f +0, 109, 109, 1, 14144, 0x33a03d1d, S=1, 1024, 0xcfc8799f +0, 110, 110, 1, 14277, 0x6bda5935, S=1, 1024, 0xcfc8799f +0, 111, 111, 1, 14424, 0xa696efd8, S=1, 1024, 0xcfc8799f +0, 112, 112, 1, 14689, 0x8e3ad12c, S=1, 1024, 0xcfc8799f +0, 113, 113, 1, 14598, 0x544668b4, S=1, 1024, 0xcfc8799f +0, 114, 114, 1, 15213, 0x60009558, S=1, 1024, 0xcfc8799f +0, 115, 115, 1, 15425, 0x86e5adf4, S=1, 1024, 0xcfc8799f +0, 116, 116, 1, 15595, 0x878d09b9, S=1, 1024, 0xcfc8799f +0, 117, 117, 1, 15598, 0x10daabc4, S=1, 1024, 0xcfc8799f +0, 118, 118, 1, 15863, 0x2462016c, S=1, 1024, 0xcfc8799f +0, 119, 119, 1, 15717, 0xe05041c4, S=1, 1024, 0xcfc8799f +0, 120, 120, 1, 16078, 0x7c8f3a8c, S=1, 1024, 0xcfc8799f +0, 121, 121, 1, 16225, 0x9771a52e, S=1, 1024, 0xcfc8799f +0, 122, 122, 1, 16135, 0x2dfc1692, S=1, 1024, 0xcfc8799f +0, 123, 123, 1, 16661, 0x09c96d7e, S=1, 1024, 0xcfc8799f +0, 124, 124, 1, 16619, 0xc4735b56, S=1, 1024, 0xcfc8799f +0, 125, 125, 1, 16829, 0x589dc13f, S=1, 1024, 0xcfc8799f +0, 126, 126, 1, 16944, 0x997cd18f, S=1, 1024, 0xcfc8799f +0, 127, 127, 1, 17119, 0x6c396b60, S=1, 1024, 0xcfc8799f +0, 128, 128, 1, 17150, 0x8e603d31, S=1, 1024, 0xcfc8799f +0, 129, 129, 1, 17321, 0x0bbcee5a, S=1, 1024, 0xcfc8799f +0, 130, 130, 1, 17395, 0x99f0c974, S=1, 1024, 0xcfc8799f +0, 131, 131, 1, 17666, 0x37184223, S=1, 1024, 0xcfc8799f +0, 132, 132, 1, 17730, 0xa0d385b3, S=1, 1024, 0xcfc8799f +0, 133, 133, 1, 17934, 0xb22cc97d, S=1, 1024, 0xcfc8799f +0, 134, 134, 1, 17944, 0x0cd309c6, S=1, 1024, 0xcfc8799f +0, 135, 135, 1, 18238, 0x6b7e3237, S=1, 1024, 0xcfc8799f +0, 136, 136, 1, 18391, 0x4df3c48a, S=1, 1024, 0xcfc8799f +0, 137, 137, 1, 18543, 0x90a2f238, S=1, 1024, 0xcfc8799f +0, 138, 138, 1, 18939, 0xc57dda5b, S=1, 1024, 0xcfc8799f +0, 139, 139, 1, 19145, 0x1267294a, S=1, 1024, 0xcfc8799f +0, 140, 140, 1, 19120, 0xeac6a9c3, S=1, 1024, 0xcfc8799f +0, 141, 141, 1, 19130, 0x31f3edbc, S=1, 1024, 0xcfc8799f +0, 142, 142, 1, 19494, 0x3259a2f3, S=1, 1024, 0xcfc8799f +0, 143, 143, 1, 19534, 0xda22a752, S=1, 1024, 0xcfc8799f +0, 144, 144, 1, 19747, 0x8805c379, S=1, 1024, 0xcfc8799f +0, 145, 145, 1, 20114, 0xaaf96864, S=1, 1024, 0xcfc8799f +0, 146, 146, 1, 20257, 0x7223da26, S=1, 1024, 0xcfc8799f +0, 147, 147, 1, 20370, 0x08ef382a, S=1, 1024, 0xcfc8799f +0, 148, 148, 1, 20292, 0x4b47f207, S=1, 1024, 0xcfc8799f +0, 149, 149, 1, 20491, 0xeedd6d1c, S=1, 1024, 0xcfc8799f +0, 150, 150, 1, 20647, 0xb0d1dd45, S=1, 1024, 0xcfc8799f +0, 151, 151, 1, 20666, 0x382cc8a4, S=1, 1024, 0xcfc8799f +0, 152, 152, 1, 21007, 0x398f4f7d, S=1, 1024, 0xcfc8799f +0, 153, 153, 1, 21058, 0xd6616a9d, S=1, 1024, 0xcfc8799f +0, 154, 154, 1, 21153, 0x988749db, S=1, 1024, 0xcfc8799f +0, 155, 155, 1, 21078, 0x1b328059, S=1, 1024, 0xcfc8799f +0, 156, 156, 1, 21458, 0x6348529c, S=1, 1024, 0xcfc8799f +0, 157, 157, 1, 21669, 0xcf63e2de, S=1, 1024, 0xcfc8799f +0, 158, 158, 1, 21581, 0x1fc021af, S=1, 1024, 0xcfc8799f +0, 159, 159, 1, 21654, 0x899dab18, S=1, 1024, 0xcfc8799f +0, 160, 160, 1, 21987, 0x634086fe, S=1, 1024, 0xcfc8799f +0, 161, 161, 1, 22205, 0x617a7335, S=1, 1024, 0xcfc8799f +0, 162, 162, 1, 22475, 0x9fa2e01c, S=1, 1024, 0xcfc8799f +0, 163, 163, 1, 22490, 0x7dc5376c, S=1, 1024, 0xcfc8799f +0, 164, 164, 1, 22460, 0x33e6bbfe, S=1, 1024, 0xcfc8799f +0, 165, 165, 1, 22861, 0x18993510, S=1, 1024, 0xcfc8799f +0, 166, 166, 1, 22746, 0xdff85615, S=1, 1024, 0xcfc8799f +0, 167, 167, 1, 23165, 0xf0ac66a3, S=1, 1024, 0xcfc8799f +0, 168, 168, 1, 23273, 0x13869ad9, S=1, 1024, 0xcfc8799f +0, 169, 169, 1, 23211, 0xd30b6205, S=1, 1024, 0xcfc8799f +0, 170, 170, 1, 23648, 0xa0cef01b, S=1, 1024, 0xcfc8799f +0, 171, 171, 1, 23675, 0x760460b9, S=1, 1024, 0xcfc8799f +0, 172, 172, 1, 23874, 0xacf998c5, S=1, 1024, 0xcfc8799f diff --git a/tests/ref/fate/hevc-conformance-DBLK_A_MAIN10_VIXS_2 b/tests/ref/fate/hevc-conformance-DBLK_A_MAIN10_VIXS_3 similarity index 100% rename from tests/ref/fate/hevc-conformance-DBLK_A_MAIN10_VIXS_2 rename to tests/ref/fate/hevc-conformance-DBLK_A_MAIN10_VIXS_3 diff --git a/tests/ref/fate/hevc-conformance-DBLK_D_VIXS_1 b/tests/ref/fate/hevc-conformance-DBLK_D_VIXS_1 deleted file mode 100644 index 3d9e43b1c..000000000 --- a/tests/ref/fate/hevc-conformance-DBLK_D_VIXS_1 +++ /dev/null @@ -1,9 +0,0 @@ -#tb 0: 1/25 -0, 0, 0, 1, 1382400, 0x6ef5c76e -0, 1, 1, 1, 1382400, 0x975238be -0, 2, 2, 1, 1382400, 0xe5529a79 -0, 3, 3, 1, 1382400, 0x639641d4 -0, 4, 4, 1, 1382400, 0x566eb1df -0, 5, 5, 1, 1382400, 0x4fd4b46a -0, 6, 6, 1, 1382400, 0xfb4a6a0e -0, 7, 7, 1, 1382400, 0x4485af32 diff --git a/tests/ref/fate/hevc-conformance-DBLK_E_VIXS_1 b/tests/ref/fate/hevc-conformance-DBLK_E_VIXS_1 deleted file mode 100644 index c3ebaf208..000000000 --- a/tests/ref/fate/hevc-conformance-DBLK_E_VIXS_1 +++ /dev/null @@ -1,9 +0,0 @@ -#tb 0: 1/25 -0, 0, 0, 1, 1382400, 0x7119bbe5 -0, 1, 1, 1, 1382400, 0xbeda2c83 -0, 2, 2, 1, 1382400, 0x2cbe6669 -0, 3, 3, 1, 1382400, 0x3cee2619 -0, 4, 4, 1, 1382400, 0x93e388e3 -0, 5, 5, 1, 1382400, 0x5e286889 -0, 6, 6, 1, 1382400, 0x4718f29c -0, 7, 7, 1, 1382400, 0xbedf4dbd diff --git a/tests/ref/fate/hevc-conformance-DBLK_F_VIXS_1 b/tests/ref/fate/hevc-conformance-DBLK_F_VIXS_1 deleted file mode 100644 index 59f51efaa..000000000 --- a/tests/ref/fate/hevc-conformance-DBLK_F_VIXS_1 +++ /dev/null @@ -1,9 +0,0 @@ -#tb 0: 1/25 -0, 0, 0, 1, 1382400, 0xea27f7bd -0, 1, 1, 1, 1382400, 0xce3d7b4c -0, 2, 2, 1, 1382400, 0xaea4970e -0, 3, 3, 1, 1382400, 0xcbc7c89f -0, 4, 4, 1, 1382400, 0xe5367019 -0, 5, 5, 1, 1382400, 0xb92ca18e -0, 6, 6, 1, 1382400, 0xde046be1 -0, 7, 7, 1, 1382400, 0x1ae6e393 diff --git a/tests/ref/fate/hevc-conformance-DBLK_G_VIXS_1 b/tests/ref/fate/hevc-conformance-DBLK_G_VIXS_1 deleted file mode 100644 index 4b9793b15..000000000 --- a/tests/ref/fate/hevc-conformance-DBLK_G_VIXS_1 +++ /dev/null @@ -1,9 +0,0 @@ -#tb 0: 1/25 -0, 0, 0, 1, 1382400, 0xecfdf606 -0, 1, 1, 1, 1382400, 0x7607799b -0, 2, 2, 1, 1382400, 0x67fb98e4 -0, 3, 3, 1, 1382400, 0xf2dce07f -0, 4, 4, 1, 1382400, 0x663f991c -0, 5, 5, 1, 1382400, 0x3877aeb0 -0, 6, 6, 1, 1382400, 0x73409282 -0, 7, 7, 1, 1382400, 0x766c10b1 diff --git a/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4 b/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4 new file mode 100644 index 000000000..d2ab0f57f --- /dev/null +++ b/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4 @@ -0,0 +1,97 @@ +#tb 0: 1/25 +0, 0, 0, 1, 3133440, 0xfbd10331 +0, 1, 1, 1, 3133440, 0x7764ad70 +0, 2, 2, 1, 3133440, 0xaeaf44c1 +0, 3, 3, 1, 3133440, 0x0590073b +0, 4, 4, 1, 3133440, 0xc4173137 +0, 5, 5, 1, 3133440, 0xd173b667 +0, 6, 6, 1, 3133440, 0xb70253db +0, 7, 7, 1, 3133440, 0x506ada41 +0, 8, 8, 1, 3133440, 0x7748178b +0, 9, 9, 1, 3133440, 0xd5450415 +0, 10, 10, 1, 3133440, 0x2d1cf084 +0, 11, 11, 1, 3133440, 0xc89fb208 +0, 12, 12, 1, 3133440, 0x3d065c44 +0, 13, 13, 1, 3133440, 0x15a67a95 +0, 14, 14, 1, 3133440, 0xde1684ca +0, 15, 15, 1, 3133440, 0xc3e64367 +0, 16, 16, 1, 3133440, 0x5bf1bd00 +0, 17, 17, 1, 3133440, 0x253703c8 +0, 18, 18, 1, 3133440, 0x5c5fb22b +0, 19, 19, 1, 3133440, 0x5fcd0915 +0, 20, 20, 1, 3133440, 0xb6fe6c0d +0, 21, 21, 1, 3133440, 0x3673f749 +0, 22, 22, 1, 3133440, 0x42535c71 +0, 23, 23, 1, 3133440, 0x889fd32d +0, 24, 24, 1, 3133440, 0x259c6c22 +0, 25, 25, 1, 3133440, 0x128844a2 +0, 26, 26, 1, 3133440, 0x34d9ead6 +0, 27, 27, 1, 3133440, 0x0a68658a +0, 28, 28, 1, 3133440, 0x3aa96f3e +0, 29, 29, 1, 3133440, 0x20249702 +0, 30, 30, 1, 3133440, 0x6d14a401 +0, 31, 31, 1, 3133440, 0xf6acf9ae +0, 32, 32, 1, 3133440, 0x0894adfb +0, 33, 33, 1, 3133440, 0x664178bb +0, 34, 34, 1, 3133440, 0x6b9305df +0, 35, 35, 1, 3133440, 0x8afd4ab4 +0, 36, 36, 1, 3133440, 0x1869c2aa +0, 37, 37, 1, 3133440, 0x004f3a7d +0, 38, 38, 1, 3133440, 0xadeb9a81 +0, 39, 39, 1, 3133440, 0xbeffc378 +0, 40, 40, 1, 3133440, 0x58c34e3c +0, 41, 41, 1, 3133440, 0x5b07ad91 +0, 42, 42, 1, 3133440, 0x41bf5cb6 +0, 43, 43, 1, 3133440, 0x65ebea43 +0, 44, 44, 1, 3133440, 0x9c2462ae +0, 45, 45, 1, 3133440, 0x3cbc1a04 +0, 46, 46, 1, 3133440, 0x0debbeeb +0, 47, 47, 1, 3133440, 0x954399f6 +0, 48, 48, 1, 3133440, 0x3ba1b057 +0, 49, 49, 1, 3133440, 0x3b5a0cae +0, 50, 50, 1, 3133440, 0xfdf6c423 +0, 51, 51, 1, 3133440, 0x08097c97 +0, 52, 52, 1, 3133440, 0x13f06984 +0, 53, 53, 1, 3133440, 0x52a3baec +0, 54, 54, 1, 3133440, 0x7961fb92 +0, 55, 55, 1, 3133440, 0xb6805a96 +0, 56, 56, 1, 3133440, 0xde1c16e9 +0, 57, 57, 1, 3133440, 0x07cb1ffc +0, 58, 58, 1, 3133440, 0xad1a1f91 +0, 59, 59, 1, 3133440, 0x77bb5968 +0, 60, 60, 1, 3133440, 0x85e8074c +0, 61, 61, 1, 3133440, 0x1a2919ef +0, 62, 62, 1, 3133440, 0x81540640 +0, 63, 63, 1, 3133440, 0xd61a3574 +0, 64, 64, 1, 3133440, 0xf875c32c +0, 65, 65, 1, 3133440, 0x50548308 +0, 66, 66, 1, 3133440, 0xf98ee7e9 +0, 67, 67, 1, 3133440, 0xb7b4cb8e +0, 68, 68, 1, 3133440, 0x1c22b2b7 +0, 69, 69, 1, 3133440, 0x2ea55366 +0, 70, 70, 1, 3133440, 0x82e76ac5 +0, 71, 71, 1, 3133440, 0x292af798 +0, 72, 72, 1, 3133440, 0x29508415 +0, 73, 73, 1, 3133440, 0x4ef87b17 +0, 74, 74, 1, 3133440, 0xa6eeb679 +0, 75, 75, 1, 3133440, 0xfe69f819 +0, 76, 76, 1, 3133440, 0x95bb6b49 +0, 77, 77, 1, 3133440, 0x5bf3f8ad +0, 78, 78, 1, 3133440, 0x58113e3a +0, 79, 79, 1, 3133440, 0xd87b6888 +0, 80, 80, 1, 3133440, 0xb3e7a295 +0, 81, 81, 1, 3133440, 0x3c2c7f97 +0, 82, 82, 1, 3133440, 0xe5f5cc48 +0, 83, 83, 1, 3133440, 0xa222f3e6 +0, 84, 84, 1, 3133440, 0x6ae80e0b +0, 85, 85, 1, 3133440, 0x2bc02816 +0, 86, 86, 1, 3133440, 0x2a5043cb +0, 87, 87, 1, 3133440, 0x857089b9 +0, 88, 88, 1, 3133440, 0xf3443ad1 +0, 89, 89, 1, 3133440, 0x7cb10b4c +0, 90, 90, 1, 3133440, 0x75bb32b9 +0, 91, 91, 1, 3133440, 0x6b720e0f +0, 92, 92, 1, 3133440, 0x761571be +0, 93, 93, 1, 3133440, 0x34dc14a1 +0, 94, 94, 1, 3133440, 0xbb94c2d4 +0, 95, 95, 1, 3133440, 0x5300e459 diff --git a/tests/ref/fate/hevc-conformance-ENTP_A_LG_2 b/tests/ref/fate/hevc-conformance-ENTP_A_LG_2 deleted file mode 100644 index 5697619a6..000000000 --- a/tests/ref/fate/hevc-conformance-ENTP_A_LG_2 +++ /dev/null @@ -1,51 +0,0 @@ -#tb 0: 1/25 -0, 0, 0, 1, 599040, 0x866449d5 -0, 1, 1, 1, 599040, 0x6a8919f0 -0, 2, 2, 1, 599040, 0x5bec3742 -0, 3, 3, 1, 599040, 0x0e66f78b -0, 4, 4, 1, 599040, 0x798e543b -0, 5, 5, 1, 599040, 0x342467e0 -0, 6, 6, 1, 599040, 0x2cb393e1 -0, 7, 7, 1, 599040, 0x2f326539 -0, 8, 8, 1, 599040, 0x8ac6eb6a -0, 9, 9, 1, 599040, 0x810a887b -0, 10, 10, 1, 599040, 0x4feb2d60 -0, 11, 11, 1, 599040, 0xd32165ff -0, 12, 12, 1, 599040, 0x46e505e1 -0, 13, 13, 1, 599040, 0x2d917014 -0, 14, 14, 1, 599040, 0xb504f112 -0, 15, 15, 1, 599040, 0x0fca37ce -0, 16, 16, 1, 599040, 0x2d5a269d -0, 17, 17, 1, 599040, 0x3928ef6d -0, 18, 18, 1, 599040, 0x94397312 -0, 19, 19, 1, 599040, 0xc1c1257b -0, 20, 20, 1, 599040, 0x4e23adcc -0, 21, 21, 1, 599040, 0x3eaef1e0 -0, 22, 22, 1, 599040, 0x5e66fa14 -0, 23, 23, 1, 599040, 0x2adfa0c2 -0, 24, 24, 1, 599040, 0xf888db90 -0, 25, 25, 1, 599040, 0xab3a6418 -0, 26, 26, 1, 599040, 0x7689d0a2 -0, 27, 27, 1, 599040, 0x2f5746bf -0, 28, 28, 1, 599040, 0xad2cf3da -0, 29, 29, 1, 599040, 0x32f2854e -0, 30, 30, 1, 599040, 0xb73cf7db -0, 31, 31, 1, 599040, 0xbe996991 -0, 32, 32, 1, 599040, 0xe66501c8 -0, 33, 33, 1, 599040, 0x12d1bc13 -0, 34, 34, 1, 599040, 0x06e103d5 -0, 35, 35, 1, 599040, 0x49af0680 -0, 36, 36, 1, 599040, 0xdbf128b0 -0, 37, 37, 1, 599040, 0xa1ac770d -0, 38, 38, 1, 599040, 0x99156429 -0, 39, 39, 1, 599040, 0x8ce1a9a7 -0, 40, 40, 1, 599040, 0x14067700 -0, 41, 41, 1, 599040, 0xcdedccee -0, 42, 42, 1, 599040, 0x09c12765 -0, 43, 43, 1, 599040, 0x7979a1be -0, 44, 44, 1, 599040, 0xbd3148d1 -0, 45, 45, 1, 599040, 0xc83f9aac -0, 46, 46, 1, 599040, 0x91acbae4 -0, 47, 47, 1, 599040, 0xd230907a -0, 48, 48, 1, 599040, 0x3f6c31f6 -0, 49, 49, 1, 599040, 0x84496e55 diff --git a/tests/ref/fate/hevc-conformance-ENTP_A_Qualcomm_1 b/tests/ref/fate/hevc-conformance-ENTP_A_Qualcomm_1 new file mode 100644 index 000000000..4454bfadf --- /dev/null +++ b/tests/ref/fate/hevc-conformance-ENTP_A_Qualcomm_1 @@ -0,0 +1,25 @@ +#tb 0: 1/25 +0, 0, 0, 1, 3110400, 0x26663e50 +0, 1, 1, 1, 3110400, 0x64ae36c1 +0, 2, 2, 1, 3110400, 0x5c72ac0b +0, 3, 3, 1, 3110400, 0x13617553 +0, 4, 4, 1, 3110400, 0xee94be8a +0, 5, 5, 1, 3110400, 0x6324f8da +0, 6, 6, 1, 3110400, 0xea0dd277 +0, 7, 7, 1, 3110400, 0xdf3e6b85 +0, 8, 8, 1, 3110400, 0xdc754b17 +0, 9, 9, 1, 3110400, 0xbb53a891 +0, 10, 10, 1, 3110400, 0x53c6575a +0, 11, 11, 1, 3110400, 0xda720794 +0, 12, 12, 1, 3110400, 0x21be3522 +0, 13, 13, 1, 3110400, 0x7fd72aa9 +0, 14, 14, 1, 3110400, 0xeb0d104a +0, 15, 15, 1, 3110400, 0xd038405a +0, 16, 16, 1, 3110400, 0xd1f8b9fa +0, 17, 17, 1, 3110400, 0xc96d2b8c +0, 18, 18, 1, 3110400, 0x07f77dcd +0, 19, 19, 1, 3110400, 0x673b444c +0, 20, 20, 1, 3110400, 0x5a8b4836 +0, 21, 21, 1, 3110400, 0x1ce733d3 +0, 22, 22, 1, 3110400, 0xd919ae60 +0, 23, 23, 1, 3110400, 0x5dcc11c0 diff --git a/tests/ref/fate/hevc-conformance-ENTP_B_LG_2 b/tests/ref/fate/hevc-conformance-ENTP_B_LG_2 deleted file mode 100644 index 0251f3070..000000000 --- a/tests/ref/fate/hevc-conformance-ENTP_B_LG_2 +++ /dev/null @@ -1,51 +0,0 @@ -#tb 0: 1/25 -0, 0, 0, 1, 599040, 0x95a24137 -0, 1, 1, 1, 599040, 0x7d7f2b75 -0, 2, 2, 1, 599040, 0xd9fb2120 -0, 3, 3, 1, 599040, 0x14d50590 -0, 4, 4, 1, 599040, 0xe3d1b70e -0, 5, 5, 1, 599040, 0x57708a86 -0, 6, 6, 1, 599040, 0xae56a720 -0, 7, 7, 1, 599040, 0x74c18679 -0, 8, 8, 1, 599040, 0x6422d2a7 -0, 9, 9, 1, 599040, 0xf587702b -0, 10, 10, 1, 599040, 0x0f630fe0 -0, 11, 11, 1, 599040, 0x4e3537dd -0, 12, 12, 1, 599040, 0xa645e9c1 -0, 13, 13, 1, 599040, 0x35ab4155 -0, 14, 14, 1, 599040, 0x4b78ba34 -0, 15, 15, 1, 599040, 0xa9a9e572 -0, 16, 16, 1, 599040, 0x6d57f10f -0, 17, 17, 1, 599040, 0xffb8e333 -0, 18, 18, 1, 599040, 0x7b2d6319 -0, 19, 19, 1, 599040, 0xcf3319aa -0, 20, 20, 1, 599040, 0xb0d097ee -0, 21, 21, 1, 599040, 0xf042f780 -0, 22, 22, 1, 599040, 0xfafafdcb -0, 23, 23, 1, 599040, 0xc8c1c452 -0, 24, 24, 1, 599040, 0x83c4d488 -0, 25, 25, 1, 599040, 0x81a8fd08 -0, 26, 26, 1, 599040, 0x2cb0c333 -0, 27, 27, 1, 599040, 0xa7bf4e52 -0, 28, 28, 1, 599040, 0x5b7ed8e9 -0, 29, 29, 1, 599040, 0x4ff03464 -0, 30, 30, 1, 599040, 0x54a700c2 -0, 31, 31, 1, 599040, 0x7dbb63aa -0, 32, 32, 1, 599040, 0xda26288e -0, 33, 33, 1, 599040, 0x8074da41 -0, 34, 34, 1, 599040, 0xa32b2ab2 -0, 35, 35, 1, 599040, 0x51b457fb -0, 36, 36, 1, 599040, 0x05e34953 -0, 37, 37, 1, 599040, 0x68c762d6 -0, 38, 38, 1, 599040, 0x11bf469e -0, 39, 39, 1, 599040, 0xc2fdadaf -0, 40, 40, 1, 599040, 0x05588da0 -0, 41, 41, 1, 599040, 0x8855f927 -0, 42, 42, 1, 599040, 0x11c85d5a -0, 43, 43, 1, 599040, 0x7a0aede5 -0, 44, 44, 1, 599040, 0x39dc4f7d -0, 45, 45, 1, 599040, 0x388f81d6 -0, 46, 46, 1, 599040, 0x2afa830d -0, 47, 47, 1, 599040, 0xd7f26886 -0, 48, 48, 1, 599040, 0xb8e12aef -0, 49, 49, 1, 599040, 0x73f7582c diff --git a/tests/ref/fate/hevc-conformance-ENTP_B_Qualcomm_1 b/tests/ref/fate/hevc-conformance-ENTP_B_Qualcomm_1 new file mode 100644 index 000000000..547b59011 --- /dev/null +++ b/tests/ref/fate/hevc-conformance-ENTP_B_Qualcomm_1 @@ -0,0 +1,25 @@ +#tb 0: 1/25 +0, 0, 0, 1, 3110400, 0x7d014690 +0, 1, 1, 1, 3110400, 0xe02cd173 +0, 2, 2, 1, 3110400, 0x2f9794c5 +0, 3, 3, 1, 3110400, 0x5df433de +0, 4, 4, 1, 3110400, 0xae409f1d +0, 5, 5, 1, 3110400, 0xb4886e82 +0, 6, 6, 1, 3110400, 0x636ee735 +0, 7, 7, 1, 3110400, 0x4d340b3f +0, 8, 8, 1, 3110400, 0xf11ce983 +0, 9, 9, 1, 3110400, 0x2a1b2094 +0, 10, 10, 1, 3110400, 0x1dee485f +0, 11, 11, 1, 3110400, 0xac329574 +0, 12, 12, 1, 3110400, 0xa0f11f30 +0, 13, 13, 1, 3110400, 0x99d827d3 +0, 14, 14, 1, 3110400, 0xa0b75c5b +0, 15, 15, 1, 3110400, 0xf3f169d8 +0, 16, 16, 1, 3110400, 0xde71892b +0, 17, 17, 1, 3110400, 0xf1129a0e +0, 18, 18, 1, 3110400, 0x02150e54 +0, 19, 19, 1, 3110400, 0xc79d65a4 +0, 20, 20, 1, 3110400, 0x708fc8fb +0, 21, 21, 1, 3110400, 0x5431050b +0, 22, 22, 1, 3110400, 0x237faa60 +0, 23, 23, 1, 3110400, 0xb05ffa7c diff --git a/tests/ref/fate/hevc-conformance-ENTP_C_LG_3 b/tests/ref/fate/hevc-conformance-ENTP_C_LG_3 deleted file mode 100644 index 3c0946e93..000000000 --- a/tests/ref/fate/hevc-conformance-ENTP_C_LG_3 +++ /dev/null @@ -1,51 +0,0 @@ -#tb 0: 1/25 -0, 0, 0, 1, 3110400, 0xaea1c3d6 -0, 1, 1, 1, 3110400, 0x665b4f52 -0, 2, 2, 1, 3110400, 0xc7da58a2 -0, 3, 3, 1, 3110400, 0x1dda6461 -0, 4, 4, 1, 3110400, 0x1d8d6eaf -0, 5, 5, 1, 3110400, 0x7a29911a -0, 6, 6, 1, 3110400, 0x0dce92c9 -0, 7, 7, 1, 3110400, 0x79c84570 -0, 8, 8, 1, 3110400, 0x736ef1e7 -0, 9, 9, 1, 3110400, 0x9dd86492 -0, 10, 10, 1, 3110400, 0x0ea31a1b -0, 11, 11, 1, 3110400, 0x0d84fdc8 -0, 12, 12, 1, 3110400, 0x06ed89a7 -0, 13, 13, 1, 3110400, 0xfaea4fd6 -0, 14, 14, 1, 3110400, 0xe787abe8 -0, 15, 15, 1, 3110400, 0x050b653a -0, 16, 16, 1, 3110400, 0x35cc1ec1 -0, 17, 17, 1, 3110400, 0x86a43e07 -0, 18, 18, 1, 3110400, 0xa6ab021e -0, 19, 19, 1, 3110400, 0x491e0efa -0, 20, 20, 1, 3110400, 0x8f210c38 -0, 21, 21, 1, 3110400, 0x637af0d0 -0, 22, 22, 1, 3110400, 0x47a59197 -0, 23, 23, 1, 3110400, 0x53e04637 -0, 24, 24, 1, 3110400, 0x7b99325e -0, 25, 25, 1, 3110400, 0x972aa252 -0, 26, 26, 1, 3110400, 0xe76ef917 -0, 27, 27, 1, 3110400, 0x7a25babc -0, 28, 28, 1, 3110400, 0x3bee3c5c -0, 29, 29, 1, 3110400, 0xbae82bcb -0, 30, 30, 1, 3110400, 0x5b65c1e5 -0, 31, 31, 1, 3110400, 0xa546266f -0, 32, 32, 1, 3110400, 0x5c5b9b8e -0, 33, 33, 1, 3110400, 0xec29c804 -0, 34, 34, 1, 3110400, 0x384efc7d -0, 35, 35, 1, 3110400, 0x6c1aaa23 -0, 36, 36, 1, 3110400, 0x55494f9f -0, 37, 37, 1, 3110400, 0xa9c56fec -0, 38, 38, 1, 3110400, 0x49c29ef2 -0, 39, 39, 1, 3110400, 0xac24fdd4 -0, 40, 40, 1, 3110400, 0x403d8213 -0, 41, 41, 1, 3110400, 0xf2d8aefe -0, 42, 42, 1, 3110400, 0x2884f0e1 -0, 43, 43, 1, 3110400, 0x69a0a781 -0, 44, 44, 1, 3110400, 0x3ab6114c -0, 45, 45, 1, 3110400, 0x1d4425a2 -0, 46, 46, 1, 3110400, 0x59f8970a -0, 47, 47, 1, 3110400, 0xfe0a05a9 -0, 48, 48, 1, 3110400, 0x50b9be4f -0, 49, 49, 1, 3110400, 0x3e1b65bd diff --git a/tests/ref/fate/hevc-conformance-ENTP_C_Qualcomm_1 b/tests/ref/fate/hevc-conformance-ENTP_C_Qualcomm_1 new file mode 100644 index 000000000..2c21f35d4 --- /dev/null +++ b/tests/ref/fate/hevc-conformance-ENTP_C_Qualcomm_1 @@ -0,0 +1,25 @@ +#tb 0: 1/25 +0, 0, 0, 1, 3110400, 0x4ea3fa57 +0, 1, 1, 1, 3110400, 0xbe33724f +0, 2, 2, 1, 3110400, 0x9011755e +0, 3, 3, 1, 3110400, 0x62de338c +0, 4, 4, 1, 3110400, 0xa49096c5 +0, 5, 5, 1, 3110400, 0xc7af7402 +0, 6, 6, 1, 3110400, 0xd8241f6b +0, 7, 7, 1, 3110400, 0x82ebc552 +0, 8, 8, 1, 3110400, 0x57c07503 +0, 9, 9, 1, 3110400, 0xc302fc68 +0, 10, 10, 1, 3110400, 0x10183476 +0, 11, 11, 1, 3110400, 0xa953ab4b +0, 12, 12, 1, 3110400, 0xe1daee4f +0, 13, 13, 1, 3110400, 0x86828802 +0, 14, 14, 1, 3110400, 0x9bb96175 +0, 15, 15, 1, 3110400, 0xe6c033a0 +0, 16, 16, 1, 3110400, 0x417407dd +0, 17, 17, 1, 3110400, 0x422ef66c +0, 18, 18, 1, 3110400, 0x3d216600 +0, 19, 19, 1, 3110400, 0xdfd83135 +0, 20, 20, 1, 3110400, 0x8deff979 +0, 21, 21, 1, 3110400, 0xbce973f4 +0, 22, 22, 1, 3110400, 0x2ae172e2 +0, 23, 23, 1, 3110400, 0x2aa32f21 diff --git a/tests/ref/fate/hevc-conformance-FILLER_A_Sony_1 b/tests/ref/fate/hevc-conformance-FILLER_A_Sony_1 new file mode 100644 index 000000000..809b4cd4b --- /dev/null +++ b/tests/ref/fate/hevc-conformance-FILLER_A_Sony_1 @@ -0,0 +1,61 @@ +#tb 0: 1001/30000 +0, 0, 0, 1, 149760, 0x83261e41 +0, 1, 1, 1, 149760, 0xa8c02e8e +0, 2, 2, 1, 149760, 0xb89d1fa0 +0, 3, 3, 1, 149760, 0x22f83f2a +0, 4, 4, 1, 149760, 0x0529e619 +0, 5, 5, 1, 149760, 0x18488682 +0, 6, 6, 1, 149760, 0x91c0fde2 +0, 7, 7, 1, 149760, 0xe07355aa +0, 8, 8, 1, 149760, 0x6deca92f +0, 9, 9, 1, 149760, 0xcd16e610 +0, 10, 10, 1, 149760, 0x3fd6cab8 +0, 11, 11, 1, 149760, 0x063e39e4 +0, 12, 12, 1, 149760, 0x8b1fb242 +0, 13, 13, 1, 149760, 0x00ef6987 +0, 14, 14, 1, 149760, 0xdfa7e8ab +0, 15, 15, 1, 149760, 0x315a23a8 +0, 16, 16, 1, 149760, 0xdd655173 +0, 17, 17, 1, 149760, 0x741b9603 +0, 18, 18, 1, 149760, 0x4a3c29a4 +0, 19, 19, 1, 149760, 0xb14b06f4 +0, 20, 20, 1, 149760, 0x5dd7fa14 +0, 21, 21, 1, 149760, 0x60dac9fe +0, 22, 22, 1, 149760, 0x231effa8 +0, 23, 23, 1, 149760, 0x6b0cca33 +0, 24, 24, 1, 149760, 0xb1fc6596 +0, 25, 25, 1, 149760, 0x683fa8b5 +0, 26, 26, 1, 149760, 0xa9da45be +0, 27, 27, 1, 149760, 0x96d69624 +0, 28, 28, 1, 149760, 0xff9e0778 +0, 29, 29, 1, 149760, 0x7410078e +0, 30, 30, 1, 149760, 0x6418b280 +0, 31, 31, 1, 149760, 0xee66b0dd +0, 32, 32, 1, 149760, 0xdf4d06fb +0, 33, 33, 1, 149760, 0xf75c33fd +0, 34, 34, 1, 149760, 0x73e97017 +0, 35, 35, 1, 149760, 0xcc8c4e15 +0, 36, 36, 1, 149760, 0xa494d7f7 +0, 37, 37, 1, 149760, 0x57564b5f +0, 38, 38, 1, 149760, 0x84433b5c +0, 39, 39, 1, 149760, 0x8ec138cf +0, 40, 40, 1, 149760, 0x72a9e2df +0, 41, 41, 1, 149760, 0x69ee26c7 +0, 42, 42, 1, 149760, 0x8d85941b +0, 43, 43, 1, 149760, 0xfa9f41a2 +0, 44, 44, 1, 149760, 0x2ec9d6df +0, 45, 45, 1, 149760, 0xb9a85b2b +0, 46, 46, 1, 149760, 0xea10c86d +0, 47, 47, 1, 149760, 0x2a2d0c1b +0, 48, 48, 1, 149760, 0xb96395d7 +0, 49, 49, 1, 149760, 0xb9abdbde +0, 50, 50, 1, 149760, 0x8aff19ae +0, 51, 51, 1, 149760, 0xa46d1e0b +0, 52, 52, 1, 149760, 0xb5943391 +0, 53, 53, 1, 149760, 0x49aacf5c +0, 54, 54, 1, 149760, 0x837b6b38 +0, 55, 55, 1, 149760, 0x1455d41b +0, 56, 56, 1, 149760, 0xf5b87056 +0, 57, 57, 1, 149760, 0x15ef5ca7 +0, 58, 58, 1, 149760, 0x29edded5 +0, 59, 59, 1, 149760, 0x86f1eb45 diff --git a/tests/ref/fate/hevc-conformance-HRD_A_Fujitsu_2 b/tests/ref/fate/hevc-conformance-HRD_A_Fujitsu_2 new file mode 100644 index 000000000..d887df215 --- /dev/null +++ b/tests/ref/fate/hevc-conformance-HRD_A_Fujitsu_2 @@ -0,0 +1,97 @@ +#tb 0: 1/50 +0, 0, 0, 1, 149760, 0x49bcac59 +0, 1, 1, 1, 149760, 0x30ffadcd +0, 2, 2, 1, 149760, 0x85ccc14a +0, 3, 3, 1, 149760, 0x9e80bab5 +0, 4, 4, 1, 149760, 0xf4d6b065 +0, 5, 5, 1, 149760, 0x3dfea025 +0, 6, 6, 1, 149760, 0x752381f4 +0, 7, 7, 1, 149760, 0x55875176 +0, 8, 8, 1, 149760, 0xaeeceea9 +0, 9, 9, 1, 149760, 0xfa19792b +0, 10, 10, 1, 149760, 0x1f0cfa3c +0, 11, 11, 1, 149760, 0xecc09b1a +0, 12, 12, 1, 149760, 0x816e4e1b +0, 13, 13, 1, 149760, 0x375cef94 +0, 14, 14, 1, 149760, 0xace1a0ff +0, 15, 15, 1, 149760, 0x85827658 +0, 16, 16, 1, 149760, 0x8189237e +0, 17, 17, 1, 149760, 0xec53e171 +0, 18, 18, 1, 149760, 0x0b1bad4a +0, 19, 19, 1, 149760, 0x9d566fd0 +0, 20, 20, 1, 149760, 0x9b323c87 +0, 21, 21, 1, 149760, 0x2d900cb7 +0, 22, 22, 1, 149760, 0x7062ed06 +0, 23, 23, 1, 149760, 0xe687c687 +0, 24, 24, 1, 149760, 0x4767dd46 +0, 25, 25, 1, 149760, 0xf0d04aae +0, 26, 26, 1, 149760, 0x1a9d0640 +0, 27, 27, 1, 149760, 0xc831e356 +0, 28, 28, 1, 149760, 0x3b5ee48b +0, 29, 29, 1, 149760, 0x083f94ec +0, 30, 30, 1, 149760, 0xfd92050f +0, 31, 31, 1, 149760, 0x23ce5764 +0, 32, 32, 1, 149760, 0x98167d17 +0, 33, 33, 1, 149760, 0x458a1e97 +0, 34, 34, 1, 149760, 0x913fe090 +0, 35, 35, 1, 149760, 0xdf87fb99 +0, 36, 36, 1, 149760, 0x2c9ffb76 +0, 37, 37, 1, 149760, 0xe52b1f88 +0, 38, 38, 1, 149760, 0xeb6441b3 +0, 39, 39, 1, 149760, 0x229a3428 +0, 40, 40, 1, 149760, 0xab5dc58c +0, 41, 41, 1, 149760, 0xfdaff77d +0, 42, 42, 1, 149760, 0x120326dc +0, 43, 43, 1, 149760, 0x9a9ff8fd +0, 44, 44, 1, 149760, 0x4e5bb152 +0, 45, 45, 1, 149760, 0x2d16f231 +0, 46, 46, 1, 149760, 0x99a01d57 +0, 47, 47, 1, 149760, 0x3a555c12 +0, 48, 48, 1, 149760, 0x20ad0e79 +0, 49, 49, 1, 149760, 0xc62724f2 +0, 50, 50, 1, 149760, 0x07a81153 +0, 51, 51, 1, 149760, 0x14b9732e +0, 52, 52, 1, 149760, 0xeefa0be1 +0, 53, 53, 1, 149760, 0x95a82b9e +0, 54, 54, 1, 149760, 0xa6ecbed4 +0, 55, 55, 1, 149760, 0xaaec0cf6 +0, 56, 56, 1, 149760, 0x087815ca +0, 57, 57, 1, 149760, 0xff82b221 +0, 58, 58, 1, 149760, 0x709afb9f +0, 59, 59, 1, 149760, 0xb91e712a +0, 60, 60, 1, 149760, 0x66dfbaaa +0, 61, 61, 1, 149760, 0x574501b2 +0, 62, 62, 1, 149760, 0xe1c13daf +0, 63, 63, 1, 149760, 0xdab85ad6 +0, 64, 64, 1, 149760, 0x57e8a455 +0, 65, 65, 1, 149760, 0xfc95db86 +0, 66, 66, 1, 149760, 0xe298f7ee +0, 67, 67, 1, 149760, 0x13302040 +0, 68, 68, 1, 149760, 0x69811199 +0, 69, 69, 1, 149760, 0x64f31874 +0, 70, 70, 1, 149760, 0xc1450115 +0, 71, 71, 1, 149760, 0xf0efc355 +0, 72, 72, 1, 149760, 0xeaee572d +0, 73, 73, 1, 149760, 0xf256fc07 +0, 74, 74, 1, 149760, 0x20d48047 +0, 75, 75, 1, 149760, 0x37a934bf +0, 76, 76, 1, 149760, 0xd14bcc48 +0, 77, 77, 1, 149760, 0x3de67683 +0, 78, 78, 1, 149760, 0x3b3b2edd +0, 79, 79, 1, 149760, 0x8cf00f8d +0, 80, 80, 1, 149760, 0x83d8ddff +0, 81, 81, 1, 149760, 0xf2f36ae4 +0, 82, 82, 1, 149760, 0xf2549f1a +0, 83, 83, 1, 149760, 0x6c5a9443 +0, 84, 84, 1, 149760, 0x071e4d64 +0, 85, 85, 1, 149760, 0x0b160074 +0, 86, 86, 1, 149760, 0x0ebdf969 +0, 87, 87, 1, 149760, 0x0331793d +0, 88, 88, 1, 149760, 0xee7ad61f +0, 89, 89, 1, 149760, 0xb9ba083f +0, 90, 90, 1, 149760, 0x8ecf1f9d +0, 91, 91, 1, 149760, 0x6e861158 +0, 92, 92, 1, 149760, 0x977a203b +0, 93, 93, 1, 149760, 0xa25d1077 +0, 94, 94, 1, 149760, 0xa4d2fca1 +0, 95, 95, 1, 149760, 0x6093084d diff --git a/tests/ref/fate/hevc-conformance-INITQP_A_Sony_1 b/tests/ref/fate/hevc-conformance-INITQP_A_Sony_1 new file mode 100644 index 000000000..e99e3897b --- /dev/null +++ b/tests/ref/fate/hevc-conformance-INITQP_A_Sony_1 @@ -0,0 +1,61 @@ +#tb 0: 1001/30000 +0, 0, 0, 1, 149760, 0x59891e4e +0, 1, 1, 1, 149760, 0x6c152de8 +0, 2, 2, 1, 149760, 0x6f2c0f37 +0, 3, 3, 1, 149760, 0xdc4142e9 +0, 4, 4, 1, 149760, 0x13a6dfe0 +0, 5, 5, 1, 149760, 0xea2b8197 +0, 6, 6, 1, 149760, 0x228207b8 +0, 7, 7, 1, 149760, 0xe6c33dc5 +0, 8, 8, 1, 149760, 0xa488a0f6 +0, 9, 9, 1, 149760, 0xf618c591 +0, 10, 10, 1, 149760, 0x0c96c7eb +0, 11, 11, 1, 149760, 0x347b17b8 +0, 12, 12, 1, 149760, 0xa2379e18 +0, 13, 13, 1, 149760, 0x635a7cbd +0, 14, 14, 1, 149760, 0xa770ed3c +0, 15, 15, 1, 149760, 0x54271b2b +0, 16, 16, 1, 149760, 0xc09751d6 +0, 17, 17, 1, 149760, 0xa33997cb +0, 18, 18, 1, 149760, 0x8f382ef3 +0, 19, 19, 1, 149760, 0x449311d8 +0, 20, 20, 1, 149760, 0x67a2f419 +0, 21, 21, 1, 149760, 0xa025b8a1 +0, 22, 22, 1, 149760, 0xebb7e911 +0, 23, 23, 1, 149760, 0x6decb08e +0, 24, 24, 1, 149760, 0x20a354ef +0, 25, 25, 1, 149760, 0x6d609fc5 +0, 26, 26, 1, 149760, 0x73992f9b +0, 27, 27, 1, 149760, 0x46968752 +0, 28, 28, 1, 149760, 0xd9e9017d +0, 29, 29, 1, 149760, 0xae321b3c +0, 30, 30, 1, 149760, 0x0f53a016 +0, 31, 31, 1, 149760, 0x74a5aacd +0, 32, 32, 1, 149760, 0x893afc39 +0, 33, 33, 1, 149760, 0xbeb13aed +0, 34, 34, 1, 149760, 0xc8658ed9 +0, 35, 35, 1, 149760, 0xcf7d544e +0, 36, 36, 1, 149760, 0x782bd063 +0, 37, 37, 1, 149760, 0x32c53ffa +0, 38, 38, 1, 149760, 0xed3849c2 +0, 39, 39, 1, 149760, 0xda5f336a +0, 40, 40, 1, 149760, 0x0460dbf7 +0, 41, 41, 1, 149760, 0x782f25e3 +0, 42, 42, 1, 149760, 0x1199900a +0, 43, 43, 1, 149760, 0xd51e4dfd +0, 44, 44, 1, 149760, 0xfd32e6d5 +0, 45, 45, 1, 149760, 0x880d5f9b +0, 46, 46, 1, 149760, 0xe1a7b52d +0, 47, 47, 1, 149760, 0x97c4228a +0, 48, 48, 1, 149760, 0x0c539d58 +0, 49, 49, 1, 149760, 0x5edfd99e +0, 50, 50, 1, 149760, 0x92a40dcc +0, 51, 51, 1, 149760, 0xa33dff8d +0, 52, 52, 1, 149760, 0xf9f637ee +0, 53, 53, 1, 149760, 0x4c02c63d +0, 54, 54, 1, 149760, 0x94125eda +0, 55, 55, 1, 149760, 0x0ba6d181 +0, 56, 56, 1, 149760, 0x1c4b7cf1 +0, 57, 57, 1, 149760, 0x3af454c4 +0, 58, 58, 1, 149760, 0x3666e3f4 +0, 59, 59, 1, 149760, 0x1013f2ec diff --git a/tests/ref/fate/hevc-conformance-INITQP_B_Sony_1 b/tests/ref/fate/hevc-conformance-INITQP_B_Sony_1 new file mode 100644 index 000000000..e00c29f1c --- /dev/null +++ b/tests/ref/fate/hevc-conformance-INITQP_B_Sony_1 @@ -0,0 +1,91 @@ +#tb 0: 1001/30000 +0, 0, 0, 1, 299520, 0x5514958a +0, 1, 1, 1, 299520, 0x06725ede +0, 2, 2, 1, 299520, 0xa71d1493 +0, 3, 3, 1, 299520, 0xdd4cde37 +0, 4, 4, 1, 299520, 0x6ea2f981 +0, 5, 5, 1, 299520, 0x34de0d7f +0, 6, 6, 1, 299520, 0xe3555f62 +0, 7, 7, 1, 299520, 0xa56cf8b5 +0, 8, 8, 1, 299520, 0x74f85f70 +0, 9, 9, 1, 299520, 0x7cc4ff3b +0, 10, 10, 1, 299520, 0xacaf62f0 +0, 11, 11, 1, 299520, 0x049aa473 +0, 12, 12, 1, 299520, 0x3d202b52 +0, 13, 13, 1, 299520, 0x530920d5 +0, 14, 14, 1, 299520, 0xcf69e5c8 +0, 15, 15, 1, 299520, 0x18ad9a4f +0, 16, 16, 1, 299520, 0xc8c1bbd9 +0, 17, 17, 1, 299520, 0x6cd37ffc +0, 18, 18, 1, 299520, 0xc8d64c57 +0, 19, 19, 1, 299520, 0xec4679bf +0, 20, 20, 1, 299520, 0xc4228355 +0, 21, 21, 1, 299520, 0x908c71b0 +0, 22, 22, 1, 299520, 0x4c4a92eb +0, 23, 23, 1, 299520, 0x28f7d30d +0, 24, 24, 1, 299520, 0xed2db3da +0, 25, 25, 1, 299520, 0xfb22801f +0, 26, 26, 1, 299520, 0x514de5b9 +0, 27, 27, 1, 299520, 0x7bb8d8f7 +0, 28, 28, 1, 299520, 0x3e43ae30 +0, 29, 29, 1, 299520, 0x45473924 +0, 30, 30, 1, 299520, 0x914a440e +0, 31, 31, 1, 299520, 0x91e74926 +0, 32, 32, 1, 299520, 0xa8a43ffd +0, 33, 33, 1, 299520, 0x1df08075 +0, 34, 34, 1, 299520, 0x84611007 +0, 35, 35, 1, 299520, 0x622d7495 +0, 36, 36, 1, 299520, 0xede897b6 +0, 37, 37, 1, 299520, 0xb14f0650 +0, 38, 38, 1, 299520, 0x74f600f9 +0, 39, 39, 1, 299520, 0xf04e2de3 +0, 40, 40, 1, 299520, 0xaeadd6fc +0, 41, 41, 1, 299520, 0xb5855f8d +0, 42, 42, 1, 299520, 0xbb6c709f +0, 43, 43, 1, 299520, 0x486d66e9 +0, 44, 44, 1, 299520, 0x87e7d165 +0, 45, 45, 1, 299520, 0x1f936d47 +0, 46, 46, 1, 299520, 0x2da721a2 +0, 47, 47, 1, 299520, 0x36caf481 +0, 48, 48, 1, 299520, 0x067e3f4d +0, 49, 49, 1, 299520, 0x1a95c86b +0, 50, 50, 1, 299520, 0x186c1bde +0, 51, 51, 1, 299520, 0xd1552b21 +0, 52, 52, 1, 299520, 0x72521786 +0, 53, 53, 1, 299520, 0xe0f0b1b2 +0, 54, 54, 1, 299520, 0xee8c6751 +0, 55, 55, 1, 299520, 0x281817ef +0, 56, 56, 1, 299520, 0xea98b174 +0, 57, 57, 1, 299520, 0x839575de +0, 58, 58, 1, 299520, 0xd89b6ff1 +0, 59, 59, 1, 299520, 0xee8432a7 +0, 60, 60, 1, 299520, 0x8f262218 +0, 61, 61, 1, 299520, 0xac918f83 +0, 62, 62, 1, 299520, 0x398c23d7 +0, 63, 63, 1, 299520, 0xdc560109 +0, 64, 64, 1, 299520, 0xb4c3cd8b +0, 65, 65, 1, 299520, 0x79824026 +0, 66, 66, 1, 299520, 0xd20f5be8 +0, 67, 67, 1, 299520, 0xc93b32a3 +0, 68, 68, 1, 299520, 0xc1363d67 +0, 69, 69, 1, 299520, 0xeb6d2f0a +0, 70, 70, 1, 299520, 0x29053a08 +0, 71, 71, 1, 299520, 0x8a236752 +0, 72, 72, 1, 299520, 0x5e572146 +0, 73, 73, 1, 299520, 0x4f7ca5cf +0, 74, 74, 1, 299520, 0x62951193 +0, 75, 75, 1, 299520, 0xf163d1cb +0, 76, 76, 1, 299520, 0xb995206c +0, 77, 77, 1, 299520, 0xcf5ebaa3 +0, 78, 78, 1, 299520, 0x22fad89d +0, 79, 79, 1, 299520, 0xc9c25e12 +0, 80, 80, 1, 299520, 0xd5404f45 +0, 81, 81, 1, 299520, 0x484bd02d +0, 82, 82, 1, 299520, 0x5790a1c4 +0, 83, 83, 1, 299520, 0xcbec0fed +0, 84, 84, 1, 299520, 0x36bd1758 +0, 85, 85, 1, 299520, 0x4a133700 +0, 86, 86, 1, 299520, 0x2c582b0a +0, 87, 87, 1, 299520, 0xadd773e1 +0, 88, 88, 1, 299520, 0xe4bbced3 +0, 89, 89, 1, 299520, 0x463b3ff0 diff --git a/tests/ref/fate/hevc-conformance-IPRED_C_Mitsubishi_2 b/tests/ref/fate/hevc-conformance-IPRED_C_Mitsubishi_2 deleted file mode 100644 index bff448bb1..000000000 --- a/tests/ref/fate/hevc-conformance-IPRED_C_Mitsubishi_2 +++ /dev/null @@ -1,5 +0,0 @@ -#tb 0: 1/25 -0, 0, 0, 1, 599040, 0x9a8664e6 -0, 1, 1, 1, 599040, 0x72f15982 -0, 2, 2, 1, 599040, 0xc6610a7b -0, 3, 3, 1, 599040, 0x091d3a93 diff --git a/tests/ref/fate/hevc-conformance-IPRED_C_Mitsubishi_3 b/tests/ref/fate/hevc-conformance-IPRED_C_Mitsubishi_3 new file mode 100644 index 000000000..72a12e8eb --- /dev/null +++ b/tests/ref/fate/hevc-conformance-IPRED_C_Mitsubishi_3 @@ -0,0 +1,5 @@ +#tb 0: 1/25 +0, 0, 0, 1, 599040, 0x6b61371d +0, 1, 1, 1, 599040, 0xd38a2e50 +0, 2, 2, 1, 599040, 0xe8eb34bd +0, 3, 3, 1, 599040, 0xb3ae6401 diff --git a/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 b/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 new file mode 100644 index 000000000..48ca5adb4 --- /dev/null +++ b/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 @@ -0,0 +1,41 @@ +#tb 0: 1/25 +0, 0, 0, 1, 599040, 0x91d452d5 +0, 1, 1, 1, 599040, 0x1b482509 +0, 2, 2, 1, 599040, 0xbc51425c +0, 3, 3, 1, 599040, 0x5777eeee +0, 4, 4, 1, 599040, 0xe274644d +0, 5, 5, 1, 599040, 0x867450b5 +0, 6, 6, 1, 599040, 0x58708122 +0, 7, 7, 1, 599040, 0xeef17206 +0, 8, 8, 1, 599040, 0x97f4dc1e +0, 9, 9, 1, 599040, 0x92c961cc +0, 10, 10, 1, 599040, 0x1c4ffcb0 +0, 11, 11, 1, 599040, 0xc73e34e6 +0, 12, 12, 1, 599040, 0x1991f1f9 +0, 13, 13, 1, 599040, 0x36e54ba2 +0, 14, 14, 1, 599040, 0x698ce0c6 +0, 15, 15, 1, 599040, 0xc6dd131e +0, 16, 16, 1, 599040, 0x0a22f4c5 +0, 17, 17, 1, 599040, 0xd6a0c196 +0, 18, 18, 1, 599040, 0x699a3e69 +0, 19, 19, 1, 599040, 0x4227009b +0, 20, 20, 1, 599040, 0x1bda8be4 +0, 21, 21, 1, 599040, 0xd1d5dcb4 +0, 22, 22, 1, 599040, 0x00a0249f +0, 23, 23, 1, 599040, 0x7263f7cf +0, 24, 24, 1, 599040, 0x47054be4 +0, 25, 25, 1, 599040, 0xda083f52 +0, 26, 26, 1, 599040, 0xf2906ab1 +0, 27, 27, 1, 599040, 0x20936797 +0, 28, 28, 1, 599040, 0x644d7c3e +0, 29, 29, 1, 599040, 0x7c00e8bf +0, 30, 30, 1, 599040, 0x041f8a48 +0, 31, 31, 1, 599040, 0xcef6e936 +0, 32, 32, 1, 599040, 0x361461e9 +0, 33, 33, 1, 599040, 0xf663ba0a +0, 34, 34, 1, 599040, 0x4d3371d3 +0, 35, 35, 1, 599040, 0xed6b5c92 +0, 36, 36, 1, 599040, 0xdec67f6e +0, 37, 37, 1, 599040, 0xbafa50c0 +0, 38, 38, 1, 599040, 0xc9181637 +0, 39, 39, 1, 599040, 0x95834e17 diff --git a/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1 b/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1 new file mode 100644 index 000000000..872c5c22c --- /dev/null +++ b/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1 @@ -0,0 +1,48 @@ +#tb 0: 1/25 +0, 0, 0, 1, 599040, 0x91d452d5 +0, 1, 1, 1, 599040, 0x1b482509 +0, 2, 2, 1, 599040, 0xbc51425c +0, 3, 3, 1, 599040, 0x5777eeee +0, 4, 4, 1, 599040, 0xe274644d +0, 5, 5, 1, 599040, 0x867450b5 +0, 6, 6, 1, 599040, 0x58708122 +0, 7, 7, 1, 599040, 0xeef17206 +0, 8, 8, 1, 599040, 0x97f4dc1e +0, 9, 9, 1, 599040, 0x92c961cc +0, 10, 10, 1, 599040, 0x1c4ffcb0 +0, 11, 11, 1, 599040, 0xc73e34e6 +0, 12, 12, 1, 599040, 0x1991f1f9 +0, 13, 13, 1, 599040, 0x36e54ba2 +0, 14, 14, 1, 599040, 0x698ce0c6 +0, 15, 15, 1, 599040, 0xc6dd131e +0, 16, 16, 1, 599040, 0x0a22f4c5 +0, 17, 17, 1, 599040, 0xd6a0c196 +0, 18, 18, 1, 599040, 0x699a3e69 +0, 19, 19, 1, 599040, 0x4227009b +0, 20, 20, 1, 599040, 0x1bda8be4 +0, 21, 21, 1, 599040, 0xd1d5dcb4 +0, 22, 22, 1, 599040, 0x00d87745 +0, 23, 23, 1, 599040, 0x9b689b16 +0, 24, 24, 1, 599040, 0x40ae530a +0, 25, 25, 1, 599040, 0x8284f649 +0, 26, 26, 1, 599040, 0x37423ae4 +0, 27, 27, 1, 599040, 0xb3f72b02 +0, 28, 28, 1, 599040, 0xc0cc5860 +0, 29, 29, 1, 599040, 0x00a0249f +0, 30, 30, 1, 599040, 0x7263f7cf +0, 31, 31, 1, 599040, 0x47054be4 +0, 32, 32, 1, 599040, 0xda083f52 +0, 33, 33, 1, 599040, 0xf2906ab1 +0, 34, 34, 1, 599040, 0x20936797 +0, 35, 35, 1, 599040, 0x644d7c3e +0, 36, 36, 1, 599040, 0x7c00e8bf +0, 37, 37, 1, 599040, 0x041f8a48 +0, 38, 38, 1, 599040, 0xcef6e936 +0, 39, 39, 1, 599040, 0x361461e9 +0, 40, 40, 1, 599040, 0xf663ba0a +0, 41, 41, 1, 599040, 0x4d3371d3 +0, 42, 42, 1, 599040, 0xed6b5c92 +0, 43, 43, 1, 599040, 0xdec67f6e +0, 44, 44, 1, 599040, 0xbafa50c0 +0, 45, 45, 1, 599040, 0xc9181637 +0, 46, 46, 1, 599040, 0x95834e17 diff --git a/tests/ref/fate/hevc-conformance-OPFLAG_A_Qualcomm_1 b/tests/ref/fate/hevc-conformance-OPFLAG_A_Qualcomm_1 new file mode 100644 index 000000000..74849ebd5 --- /dev/null +++ b/tests/ref/fate/hevc-conformance-OPFLAG_A_Qualcomm_1 @@ -0,0 +1,501 @@ +#tb 0: 1/25 +0, 0, 0, 1, 149760, 0xcfffa013 +0, 1, 1, 1, 149760, 0x8ae80654 +0, 2, 2, 1, 149760, 0xa79915b8 +0, 3, 3, 1, 149760, 0xcc5d4a1e +0, 4, 4, 1, 149760, 0x80636df7 +0, 5, 5, 1, 149760, 0x9cf2c175 +0, 6, 6, 1, 149760, 0xb7c9ecc5 +0, 7, 7, 1, 149760, 0xd038133c +0, 8, 8, 1, 149760, 0x82c62409 +0, 9, 9, 1, 149760, 0xf9ec8f18 +0, 10, 10, 1, 149760, 0x4969ba2d +0, 11, 11, 1, 149760, 0xc4ece232 +0, 12, 12, 1, 149760, 0xc346cab1 +0, 13, 13, 1, 149760, 0xec83e8fd +0, 14, 14, 1, 149760, 0x08e6ee21 +0, 15, 15, 1, 149760, 0x816818ac +0, 16, 16, 1, 149760, 0xc6822627 +0, 17, 17, 1, 149760, 0x2d1d751f +0, 18, 18, 1, 149760, 0xceb8796d +0, 19, 19, 1, 149760, 0xa8919e96 +0, 20, 20, 1, 149760, 0x6fce9abe +0, 21, 21, 1, 149760, 0x66fcbc8b +0, 22, 22, 1, 149760, 0xfc0acbdb +0, 23, 23, 1, 149760, 0x4fa7f7c3 +0, 24, 24, 1, 149760, 0xcc1a00a8 +0, 25, 25, 1, 149760, 0xe3b9aab4 +0, 26, 26, 1, 149760, 0xc064a2a9 +0, 27, 27, 1, 149760, 0x7c29bc1e +0, 28, 28, 1, 149760, 0x54b0a3f2 +0, 29, 29, 1, 149760, 0x4781f75f +0, 30, 30, 1, 149760, 0x3722ec9b +0, 31, 31, 1, 149760, 0xb73fffc8 +0, 32, 32, 1, 149760, 0xd4437e12 +0, 33, 33, 1, 149760, 0xeb8bc09f +0, 34, 34, 1, 149760, 0xe6b0cf24 +0, 35, 35, 1, 149760, 0xffbee400 +0, 36, 36, 1, 149760, 0x71b3d1c2 +0, 37, 37, 1, 149760, 0xeb05fce6 +0, 38, 38, 1, 149760, 0x968a049c +0, 39, 39, 1, 149760, 0xf0b81987 +0, 40, 40, 1, 149760, 0x8ec12318 +0, 41, 41, 1, 149760, 0xb25f6f73 +0, 42, 42, 1, 149760, 0x4d9972ea +0, 43, 43, 1, 149760, 0xb1be9ddd +0, 44, 44, 1, 149760, 0xd8f97724 +0, 45, 45, 1, 149760, 0x88e9a071 +0, 46, 46, 1, 149760, 0xec3a6985 +0, 47, 47, 1, 149760, 0x5eb77758 +0, 48, 48, 1, 149760, 0x7a2d6bc0 +0, 49, 49, 1, 149760, 0x4c108b5a +0, 50, 50, 1, 149760, 0xd1609676 +0, 51, 51, 1, 149760, 0xf497c5f2 +0, 52, 52, 1, 149760, 0x7d52bf67 +0, 53, 53, 1, 149760, 0xa9aeed34 +0, 54, 54, 1, 149760, 0x8a7a03ad +0, 55, 55, 1, 149760, 0x7d6f34ba +0, 56, 56, 1, 149760, 0x3c7a3f33 +0, 57, 57, 1, 149760, 0x220db437 +0, 58, 58, 1, 149760, 0x9098aed1 +0, 59, 59, 1, 149760, 0xba89f864 +0, 60, 60, 1, 149760, 0xc6f0f02a +0, 61, 61, 1, 149760, 0xda71bdce +0, 62, 62, 1, 149760, 0x7532698a +0, 63, 63, 1, 149760, 0x20725283 +0, 64, 64, 1, 149760, 0xd3378be9 +0, 65, 65, 1, 149760, 0x0c449d3b +0, 66, 66, 1, 149760, 0xcb16554e +0, 67, 67, 1, 149760, 0x63bf54fd +0, 68, 68, 1, 149760, 0xc9b8125a +0, 69, 69, 1, 149760, 0x29391d98 +0, 70, 70, 1, 149760, 0xaba92f83 +0, 71, 71, 1, 149760, 0x278360ab +0, 72, 72, 1, 149760, 0x72a17719 +0, 73, 73, 1, 149760, 0xc1057998 +0, 74, 74, 1, 149760, 0x3e3fb884 +0, 75, 75, 1, 149760, 0x4cadfcf5 +0, 76, 76, 1, 149760, 0x265ef61a +0, 77, 77, 1, 149760, 0xc84e8e23 +0, 78, 78, 1, 149760, 0xf23cf3c3 +0, 79, 79, 1, 149760, 0x19280d25 +0, 80, 80, 1, 149760, 0xfc1ed859 +0, 81, 81, 1, 149760, 0x1a4caf70 +0, 82, 82, 1, 149760, 0xcbc3e559 +0, 83, 83, 1, 149760, 0x2284cd25 +0, 84, 84, 1, 149760, 0x4eca841e +0, 85, 85, 1, 149760, 0xc5b2783b +0, 86, 86, 1, 149760, 0x5c07bffe +0, 87, 87, 1, 149760, 0x965b366d +0, 88, 88, 1, 149760, 0x96a87998 +0, 89, 89, 1, 149760, 0x325fb5a8 +0, 90, 90, 1, 149760, 0xfb50de20 +0, 91, 91, 1, 149760, 0x4551ff6f +0, 92, 92, 1, 149760, 0x2c313114 +0, 93, 93, 1, 149760, 0x585fbb08 +0, 94, 94, 1, 149760, 0xab620fbc +0, 95, 95, 1, 149760, 0xac147ed6 +0, 96, 96, 1, 149760, 0x8753dbea +0, 97, 97, 1, 149760, 0x7bd147a4 +0, 98, 98, 1, 149760, 0x09db40f9 +0, 99, 99, 1, 149760, 0x2c1d3e0e +0, 100, 100, 1, 149760, 0xb3678490 +0, 101, 101, 1, 149760, 0xaa1ef03a +0, 102, 102, 1, 149760, 0xaa272a2b +0, 103, 103, 1, 149760, 0x765022ee +0, 104, 104, 1, 149760, 0xa77ae265 +0, 105, 105, 1, 149760, 0xd48ce610 +0, 106, 106, 1, 149760, 0xbbe32786 +0, 107, 107, 1, 149760, 0x2ba067dd +0, 108, 108, 1, 149760, 0x28251c88 +0, 109, 109, 1, 149760, 0xf7073bea +0, 110, 110, 1, 149760, 0x5ada8c9f +0, 111, 111, 1, 149760, 0x0ac5f0c3 +0, 112, 112, 1, 149760, 0x5771b681 +0, 113, 113, 1, 149760, 0x63b1aff4 +0, 114, 114, 1, 149760, 0xe52f1c14 +0, 115, 115, 1, 149760, 0x9fc6a873 +0, 116, 116, 1, 149760, 0xaa7fa136 +0, 117, 117, 1, 149760, 0xea0f1bc3 +0, 118, 118, 1, 149760, 0xb960a92a +0, 119, 119, 1, 149760, 0x8a57440d +0, 120, 120, 1, 149760, 0x0975231e +0, 121, 121, 1, 149760, 0x01f4e2ca +0, 122, 122, 1, 149760, 0x2feba705 +0, 123, 123, 1, 149760, 0xd8c2bb3e +0, 124, 124, 1, 149760, 0x96d8a2a3 +0, 125, 125, 1, 149760, 0xc32ff8d3 +0, 126, 126, 1, 149760, 0x1f8a8edb +0, 127, 127, 1, 149760, 0xc6242875 +0, 128, 128, 1, 149760, 0x3d4df3de +0, 129, 129, 1, 149760, 0x43408010 +0, 130, 130, 1, 149760, 0x2ecd8706 +0, 131, 131, 1, 149760, 0x283c99f9 +0, 132, 132, 1, 149760, 0xa659bde0 +0, 133, 133, 1, 149760, 0x0edc3e70 +0, 134, 134, 1, 149760, 0x9ab3077e +0, 135, 135, 1, 149760, 0x45a2bf0b +0, 136, 136, 1, 149760, 0x67aff7d9 +0, 137, 137, 1, 149760, 0x4395fe6f +0, 138, 138, 1, 149760, 0x84e8ca70 +0, 139, 139, 1, 149760, 0x4089d054 +0, 140, 140, 1, 149760, 0x893bcd2c +0, 141, 141, 1, 149760, 0x36644083 +0, 142, 142, 1, 149760, 0xa0cf4e7d +0, 143, 143, 1, 149760, 0x1ee06750 +0, 144, 144, 1, 149760, 0xef952e66 +0, 145, 145, 1, 149760, 0x7bc3936b +0, 146, 146, 1, 149760, 0x73820f10 +0, 147, 147, 1, 149760, 0xf20e4fa7 +0, 148, 148, 1, 149760, 0xedc2b195 +0, 149, 149, 1, 149760, 0xd5dda892 +0, 150, 150, 1, 149760, 0x065559e4 +0, 151, 151, 1, 149760, 0xd1d1d2f7 +0, 152, 152, 1, 149760, 0x7ea0069e +0, 153, 153, 1, 149760, 0x7eb18a44 +0, 154, 154, 1, 149760, 0x5165627b +0, 155, 155, 1, 149760, 0x2bc02a08 +0, 156, 156, 1, 149760, 0x054f4260 +0, 157, 157, 1, 149760, 0x90206d1a +0, 158, 158, 1, 149760, 0x86a46770 +0, 159, 159, 1, 149760, 0x877956ae +0, 160, 160, 1, 149760, 0xeaee7801 +0, 161, 161, 1, 149760, 0xf5ae2e9d +0, 162, 162, 1, 149760, 0x65ef307b +0, 163, 163, 1, 149760, 0xbcd72d22 +0, 164, 164, 1, 149760, 0x6f5555eb +0, 165, 165, 1, 149760, 0x5c5f43af +0, 166, 166, 1, 149760, 0x13c9fa8e +0, 167, 167, 1, 149760, 0x2236154f +0, 168, 168, 1, 149760, 0x13fdcefc +0, 169, 169, 1, 149760, 0x3e95cea3 +0, 170, 170, 1, 149760, 0x11d73074 +0, 171, 171, 1, 149760, 0x66a68f43 +0, 172, 172, 1, 149760, 0x594ce4d2 +0, 173, 173, 1, 149760, 0xbea4a3de +0, 174, 174, 1, 149760, 0x72258b54 +0, 175, 175, 1, 149760, 0xf7598059 +0, 176, 176, 1, 149760, 0x527b8538 +0, 177, 177, 1, 149760, 0x9150a81a +0, 178, 178, 1, 149760, 0x9c227fd2 +0, 179, 179, 1, 149760, 0x60347245 +0, 180, 180, 1, 149760, 0x3b9f6f64 +0, 181, 181, 1, 149760, 0xd6f37def +0, 182, 182, 1, 149760, 0xa06933dd +0, 183, 183, 1, 149760, 0x19e4ef4d +0, 184, 184, 1, 149760, 0x1fb958cb +0, 185, 185, 1, 149760, 0x3c4e3f19 +0, 186, 186, 1, 149760, 0x98ab1123 +0, 187, 187, 1, 149760, 0x0b4cdf66 +0, 188, 188, 1, 149760, 0x75cd51ef +0, 189, 189, 1, 149760, 0x83e9617d +0, 190, 190, 1, 149760, 0xb97a175b +0, 191, 191, 1, 149760, 0x017520de +0, 192, 192, 1, 149760, 0xa72ecc38 +0, 193, 193, 1, 149760, 0xfb493c45 +0, 194, 194, 1, 149760, 0x6c8e40b4 +0, 195, 195, 1, 149760, 0x4aa6672c +0, 196, 196, 1, 149760, 0x223f68e5 +0, 197, 197, 1, 149760, 0x6257d660 +0, 198, 198, 1, 149760, 0xade0f8af +0, 199, 199, 1, 149760, 0x8543652c +0, 200, 200, 1, 149760, 0x593b7957 +0, 201, 201, 1, 149760, 0x90ce1910 +0, 202, 202, 1, 149760, 0x3d617a3f +0, 203, 203, 1, 149760, 0x9336fbc0 +0, 204, 204, 1, 149760, 0x26f1387b +0, 205, 205, 1, 149760, 0x0273a944 +0, 206, 206, 1, 149760, 0x71b9b110 +0, 207, 207, 1, 149760, 0x123fee6d +0, 208, 208, 1, 149760, 0xc4bde65b +0, 209, 209, 1, 149760, 0x646e3a45 +0, 210, 210, 1, 149760, 0x987e6024 +0, 211, 211, 1, 149760, 0x0bf6c9d4 +0, 212, 212, 1, 149760, 0x20d6e1cf +0, 213, 213, 1, 149760, 0x5e0931df +0, 214, 214, 1, 149760, 0xd96e313c +0, 215, 215, 1, 149760, 0x04bbfcc5 +0, 216, 216, 1, 149760, 0xa764de56 +0, 217, 217, 1, 149760, 0x1e584d95 +0, 218, 218, 1, 149760, 0x1779f283 +0, 219, 219, 1, 149760, 0xfaefbc07 +0, 220, 220, 1, 149760, 0x2e9b4e2b +0, 221, 221, 1, 149760, 0xeb6e3a42 +0, 222, 222, 1, 149760, 0xd2cbe3d4 +0, 223, 223, 1, 149760, 0xb9c4cf8c +0, 224, 224, 1, 149760, 0x167b5401 +0, 225, 225, 1, 149760, 0x37846b87 +0, 226, 226, 1, 149760, 0xd0d66b7c +0, 227, 227, 1, 149760, 0x4d61970e +0, 228, 228, 1, 149760, 0x987cbc29 +0, 229, 229, 1, 149760, 0x3fa00111 +0, 230, 230, 1, 149760, 0x42ba262f +0, 231, 231, 1, 149760, 0x9d40660b +0, 232, 232, 1, 149760, 0x3b678b28 +0, 233, 233, 1, 149760, 0x3c72d081 +0, 234, 234, 1, 149760, 0xd8ad0056 +0, 235, 235, 1, 149760, 0x86052268 +0, 236, 236, 1, 149760, 0x8ac3f213 +0, 237, 237, 1, 149760, 0xe2cfb6fb +0, 238, 238, 1, 149760, 0x412b5544 +0, 239, 239, 1, 149760, 0x468d2f6d +0, 240, 240, 1, 149760, 0x63f5e9d0 +0, 241, 241, 1, 149760, 0x4318f07d +0, 242, 242, 1, 149760, 0xa0c7b7df +0, 243, 243, 1, 149760, 0x8ad37f38 +0, 244, 244, 1, 149760, 0xa6101620 +0, 245, 245, 1, 149760, 0x02b3d774 +0, 246, 246, 1, 149760, 0x541a6c86 +0, 247, 247, 1, 149760, 0xe11148f0 +0, 248, 248, 1, 149760, 0x4a920c7e +0, 249, 249, 1, 149760, 0x878104a9 +0, 250, 250, 1, 149760, 0xbb65dfda +0, 251, 251, 1, 149760, 0xda02bd47 +0, 252, 252, 1, 149760, 0xe0529fd7 +0, 253, 253, 1, 149760, 0x52619028 +0, 254, 254, 1, 149760, 0x4e9c9f32 +0, 255, 255, 1, 149760, 0x9ae49e70 +0, 256, 256, 1, 149760, 0x851e84de +0, 257, 257, 1, 149760, 0x1709a3cd +0, 258, 258, 1, 149760, 0x3dace2eb +0, 259, 259, 1, 149760, 0x46fe3ebf +0, 260, 260, 1, 149760, 0xea53610c +0, 261, 261, 1, 149760, 0x0df3415f +0, 262, 262, 1, 149760, 0x29c57eec +0, 263, 263, 1, 149760, 0x1ed3a882 +0, 264, 264, 1, 149760, 0xf3047aed +0, 265, 265, 1, 149760, 0x7a7d08cd +0, 266, 266, 1, 149760, 0xc69dd2ad +0, 267, 267, 1, 149760, 0x94d1c233 +0, 268, 268, 1, 149760, 0x21d7eab9 +0, 269, 269, 1, 149760, 0xd8755fda +0, 270, 270, 1, 149760, 0xa44fbf4a +0, 271, 271, 1, 149760, 0x624d42cb +0, 272, 272, 1, 149760, 0xf462482d +0, 273, 273, 1, 149760, 0x8dd0641d +0, 274, 274, 1, 149760, 0x9349bc12 +0, 275, 275, 1, 149760, 0x0488137f +0, 276, 276, 1, 149760, 0x8088d83e +0, 277, 277, 1, 149760, 0x051895e4 +0, 278, 278, 1, 149760, 0x0cc16c74 +0, 279, 279, 1, 149760, 0xcdc62942 +0, 280, 280, 1, 149760, 0x6d1392aa +0, 281, 281, 1, 149760, 0x61e2e1da +0, 282, 282, 1, 149760, 0x5cb06ae9 +0, 283, 283, 1, 149760, 0x5110b773 +0, 284, 284, 1, 149760, 0x050db1cb +0, 285, 285, 1, 149760, 0x353dfc85 +0, 286, 286, 1, 149760, 0x96ac57f2 +0, 287, 287, 1, 149760, 0x7e925578 +0, 288, 288, 1, 149760, 0x4eaa64c0 +0, 289, 289, 1, 149760, 0x10b6d8cf +0, 290, 290, 1, 149760, 0x645317c2 +0, 291, 291, 1, 149760, 0xcf60e8e2 +0, 292, 292, 1, 149760, 0x38dc8503 +0, 293, 293, 1, 149760, 0xf88bd43b +0, 294, 294, 1, 149760, 0x284b675e +0, 295, 295, 1, 149760, 0xba9ac819 +0, 296, 296, 1, 149760, 0xd913bba8 +0, 297, 297, 1, 149760, 0x50612c15 +0, 298, 298, 1, 149760, 0x8ec14fb1 +0, 299, 299, 1, 149760, 0x2dd30b7d +0, 300, 300, 1, 149760, 0x5a3f52cf +0, 301, 301, 1, 149760, 0x95169561 +0, 302, 302, 1, 149760, 0x6ede7115 +0, 303, 303, 1, 149760, 0x70e435e0 +0, 304, 304, 1, 149760, 0x496df85a +0, 305, 305, 1, 149760, 0xdd583698 +0, 306, 306, 1, 149760, 0xee46c909 +0, 307, 307, 1, 149760, 0x4b0632ed +0, 308, 308, 1, 149760, 0x744e4d23 +0, 309, 309, 1, 149760, 0xc72d8111 +0, 310, 310, 1, 149760, 0x6d6c62d4 +0, 311, 311, 1, 149760, 0xbc39103c +0, 312, 312, 1, 149760, 0x1b0548e5 +0, 313, 313, 1, 149760, 0xac760971 +0, 314, 314, 1, 149760, 0x0bbfeab1 +0, 315, 315, 1, 149760, 0x843ca731 +0, 316, 316, 1, 149760, 0x6a8dd5c9 +0, 317, 317, 1, 149760, 0xd5e19d6e +0, 318, 318, 1, 149760, 0xde1e9259 +0, 319, 319, 1, 149760, 0xa9c6aecf +0, 320, 320, 1, 149760, 0x4e3c1463 +0, 321, 321, 1, 149760, 0x20e95cd5 +0, 322, 322, 1, 149760, 0x26b9c119 +0, 323, 323, 1, 149760, 0x0284eab3 +0, 324, 324, 1, 149760, 0x128544f3 +0, 325, 325, 1, 149760, 0x5c33579c +0, 326, 326, 1, 149760, 0x58e48fc1 +0, 327, 327, 1, 149760, 0x46d20ba5 +0, 328, 328, 1, 149760, 0x232478d4 +0, 329, 329, 1, 149760, 0x4299f014 +0, 330, 330, 1, 149760, 0x68e08339 +0, 331, 331, 1, 149760, 0x01c0ca97 +0, 332, 332, 1, 149760, 0xad7071d6 +0, 333, 333, 1, 149760, 0xa1efff2e +0, 334, 334, 1, 149760, 0xe788aa06 +0, 335, 335, 1, 149760, 0xa203d648 +0, 336, 336, 1, 149760, 0xdec84349 +0, 337, 337, 1, 149760, 0xb15fc868 +0, 338, 338, 1, 149760, 0x6ca04511 +0, 339, 339, 1, 149760, 0xc4b95d7e +0, 340, 340, 1, 149760, 0xa3d0d178 +0, 341, 341, 1, 149760, 0xb4835e5f +0, 342, 342, 1, 149760, 0xcff22407 +0, 343, 343, 1, 149760, 0x8259ad5a +0, 344, 344, 1, 149760, 0x9cb2f71a +0, 345, 345, 1, 149760, 0xf2d3cae6 +0, 346, 346, 1, 149760, 0xbdaa58c5 +0, 347, 347, 1, 149760, 0x2c0ec9bd +0, 348, 348, 1, 149760, 0x63357b56 +0, 349, 349, 1, 149760, 0xc92b5672 +0, 350, 350, 1, 149760, 0xc2deae0d +0, 351, 351, 1, 149760, 0x111a214d +0, 352, 352, 1, 149760, 0xbb7a0383 +0, 353, 353, 1, 149760, 0x31b6d2ad +0, 354, 354, 1, 149760, 0x87f8b103 +0, 355, 355, 1, 149760, 0xd035ede8 +0, 356, 356, 1, 149760, 0xf021cb64 +0, 357, 357, 1, 149760, 0x18a1c19c +0, 358, 358, 1, 149760, 0xc51980ac +0, 359, 359, 1, 149760, 0x2394c13e +0, 360, 360, 1, 149760, 0x2b27c7ee +0, 361, 361, 1, 149760, 0x40e0670f +0, 362, 362, 1, 149760, 0xbc0f3989 +0, 363, 363, 1, 149760, 0x391048d6 +0, 364, 364, 1, 149760, 0x1bc0e92c +0, 365, 365, 1, 149760, 0xa7e278d9 +0, 366, 366, 1, 149760, 0xb4123421 +0, 367, 367, 1, 149760, 0x106bb0e1 +0, 368, 368, 1, 149760, 0x4c2a61d2 +0, 369, 369, 1, 149760, 0x69aaee6e +0, 370, 370, 1, 149760, 0x925e5432 +0, 371, 371, 1, 149760, 0x06d6d786 +0, 372, 372, 1, 149760, 0xd431fba8 +0, 373, 373, 1, 149760, 0x54092812 +0, 374, 374, 1, 149760, 0xb8e10742 +0, 375, 375, 1, 149760, 0x2ee782d3 +0, 376, 376, 1, 149760, 0x210ff556 +0, 377, 377, 1, 149760, 0xa41cf41e +0, 378, 378, 1, 149760, 0xbe852e5a +0, 379, 379, 1, 149760, 0x4a89b5c5 +0, 380, 380, 1, 149760, 0xe44408d1 +0, 381, 381, 1, 149760, 0x503197f3 +0, 382, 382, 1, 149760, 0x686bf74e +0, 383, 383, 1, 149760, 0xb96fd46b +0, 384, 384, 1, 149760, 0x9a926a62 +0, 385, 385, 1, 149760, 0x97cf58e9 +0, 386, 386, 1, 149760, 0x0e7840af +0, 387, 387, 1, 149760, 0x00aa85e9 +0, 388, 388, 1, 149760, 0x24c4fd96 +0, 389, 389, 1, 149760, 0xe520844b +0, 390, 390, 1, 149760, 0xd4755d80 +0, 391, 391, 1, 149760, 0x9cd4b85c +0, 392, 392, 1, 149760, 0xd01aa4ad +0, 393, 393, 1, 149760, 0xa5479aa5 +0, 394, 394, 1, 149760, 0x74c066d4 +0, 395, 395, 1, 149760, 0xe1a35a46 +0, 396, 396, 1, 149760, 0x714aeafb +0, 397, 397, 1, 149760, 0xb3e0f80e +0, 398, 398, 1, 149760, 0x99663804 +0, 399, 399, 1, 149760, 0x3a40a623 +0, 400, 400, 1, 149760, 0x91b4d995 +0, 401, 401, 1, 149760, 0x6edd8a1f +0, 402, 402, 1, 149760, 0x1f763e9a +0, 403, 403, 1, 149760, 0x932b79d4 +0, 404, 404, 1, 149760, 0x6a1a9755 +0, 405, 405, 1, 149760, 0x403562c8 +0, 406, 406, 1, 149760, 0x6486231b +0, 407, 407, 1, 149760, 0x3c2bfb98 +0, 408, 408, 1, 149760, 0x198a3cee +0, 409, 409, 1, 149760, 0x4d2f7817 +0, 410, 410, 1, 149760, 0xd7b189a7 +0, 411, 411, 1, 149760, 0x9ad0ba76 +0, 412, 412, 1, 149760, 0xea8d8859 +0, 413, 413, 1, 149760, 0x30fae052 +0, 414, 414, 1, 149760, 0x55b1763c +0, 415, 415, 1, 149760, 0x4be39b5b +0, 416, 416, 1, 149760, 0xec332a7f +0, 417, 417, 1, 149760, 0x226f7c74 +0, 418, 418, 1, 149760, 0x0a82fa19 +0, 419, 419, 1, 149760, 0x8bb5ca7d +0, 420, 420, 1, 149760, 0xe59f21e1 +0, 421, 421, 1, 149760, 0x20450c0b +0, 422, 422, 1, 149760, 0xd9fcc726 +0, 423, 423, 1, 149760, 0xf4e9a639 +0, 424, 424, 1, 149760, 0x932602d1 +0, 425, 425, 1, 149760, 0xcdfdb2c6 +0, 426, 426, 1, 149760, 0xc91929b2 +0, 427, 427, 1, 149760, 0x6b24081c +0, 428, 428, 1, 149760, 0xa2e00bd5 +0, 429, 429, 1, 149760, 0x7536baea +0, 430, 430, 1, 149760, 0x5a4279b7 +0, 431, 431, 1, 149760, 0x48741fb4 +0, 432, 432, 1, 149760, 0xe0a71c39 +0, 433, 433, 1, 149760, 0x4422b4cf +0, 434, 434, 1, 149760, 0x3ddc7752 +0, 435, 435, 1, 149760, 0x209ebb6b +0, 436, 436, 1, 149760, 0x47cc746f +0, 437, 437, 1, 149760, 0x159f56a4 +0, 438, 438, 1, 149760, 0x22e39511 +0, 439, 439, 1, 149760, 0x78698fbd +0, 440, 440, 1, 149760, 0x7bc88f86 +0, 441, 441, 1, 149760, 0x44a423d1 +0, 442, 442, 1, 149760, 0x25fadf02 +0, 443, 443, 1, 149760, 0xd360cfee +0, 444, 444, 1, 149760, 0xcd6c409f +0, 445, 445, 1, 149760, 0xd5905aca +0, 446, 446, 1, 149760, 0x621f3edc +0, 447, 447, 1, 149760, 0x79bd347e +0, 448, 448, 1, 149760, 0xdb9d163d +0, 449, 449, 1, 149760, 0x7282e4d6 +0, 450, 450, 1, 149760, 0x8d6dc686 +0, 451, 451, 1, 149760, 0x35132151 +0, 452, 452, 1, 149760, 0x27a05c87 +0, 453, 453, 1, 149760, 0x8e12df27 +0, 454, 454, 1, 149760, 0xf2fb72cd +0, 455, 455, 1, 149760, 0xea71796e +0, 456, 456, 1, 149760, 0xbd2ffeec +0, 457, 457, 1, 149760, 0xdb849b70 +0, 458, 458, 1, 149760, 0xc8193666 +0, 459, 459, 1, 149760, 0x7dab4b05 +0, 460, 460, 1, 149760, 0x83a94327 +0, 461, 461, 1, 149760, 0x56a2ca36 +0, 462, 462, 1, 149760, 0x7d20c938 +0, 463, 463, 1, 149760, 0xfbbfa0bd +0, 464, 464, 1, 149760, 0xea020d13 +0, 465, 465, 1, 149760, 0x2ef8c012 +0, 466, 466, 1, 149760, 0x36a10f18 +0, 467, 467, 1, 149760, 0x56e538e3 +0, 468, 468, 1, 149760, 0xf98d9ca8 +0, 469, 469, 1, 149760, 0xeba06818 +0, 470, 470, 1, 149760, 0x7d9c6f79 +0, 471, 471, 1, 149760, 0xd7173a90 +0, 472, 472, 1, 149760, 0xff4ced8d +0, 473, 473, 1, 149760, 0xe7d92ff8 +0, 474, 474, 1, 149760, 0x4f020382 +0, 475, 475, 1, 149760, 0x4e93292a +0, 476, 476, 1, 149760, 0x08dc52c7 +0, 477, 477, 1, 149760, 0xbff9557e +0, 478, 478, 1, 149760, 0x1caa8bc5 +0, 479, 479, 1, 149760, 0x9b7aaf9a +0, 480, 480, 1, 149760, 0x2cb89025 +0, 481, 481, 1, 149760, 0x18e2a4ad +0, 482, 482, 1, 149760, 0xf50dce5e +0, 483, 483, 1, 149760, 0x9f87c44f +0, 484, 484, 1, 149760, 0xbfdc521d +0, 485, 485, 1, 149760, 0xa06f5b06 +0, 486, 486, 1, 149760, 0xa169a6fe +0, 487, 487, 1, 149760, 0xce6280d4 +0, 488, 488, 1, 149760, 0x056c21d6 +0, 489, 489, 1, 149760, 0x70b068df +0, 490, 490, 1, 149760, 0x1097459b +0, 491, 491, 1, 149760, 0xef1925f1 +0, 492, 492, 1, 149760, 0x6969b893 +0, 493, 493, 1, 149760, 0x0203fc33 +0, 494, 494, 1, 149760, 0x812e46b9 +0, 495, 495, 1, 149760, 0x7379207f +0, 496, 496, 1, 149760, 0xff11e733 +0, 497, 497, 1, 149760, 0xc5af45a8 +0, 498, 498, 1, 149760, 0x3ec6b250 +0, 499, 499, 1, 149760, 0xb90ddf3a diff --git a/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1 b/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1 new file mode 100644 index 000000000..55e4be0d7 --- /dev/null +++ b/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1 @@ -0,0 +1,99 @@ +#tb 0: 1/25 +0, 0, 0, 1, 599040, 0x4246702a +0, 1, 1, 1, 599040, 0x25e02747 +0, 2, 2, 1, 599040, 0x0894b9de +0, 3, 3, 1, 599040, 0x88ea9524 +0, 4, 4, 1, 599040, 0xaff26463 +0, 5, 5, 1, 599040, 0x5fb75697 +0, 6, 6, 1, 599040, 0xbc2f36a3 +0, 7, 7, 1, 599040, 0xb7823c25 +0, 8, 8, 1, 599040, 0x61cb05cb +0, 9, 9, 1, 599040, 0x74bfcc5c +0, 10, 10, 1, 599040, 0x435c4cb3 +0, 11, 11, 1, 599040, 0x34e1a6df +0, 12, 12, 1, 599040, 0x57760c47 +0, 13, 13, 1, 599040, 0xd8c5092c +0, 14, 14, 1, 599040, 0x56d4aeed +0, 15, 15, 1, 599040, 0xda4388c2 +0, 16, 16, 1, 599040, 0x09c82870 +0, 17, 17, 1, 599040, 0x77f63854 +0, 18, 18, 1, 599040, 0xb7ca000b +0, 19, 19, 1, 599040, 0x6ef162db +0, 20, 20, 1, 599040, 0x1a274bec +0, 21, 21, 1, 599040, 0x1a839505 +0, 22, 22, 1, 599040, 0xf78f0c03 +0, 23, 23, 1, 599040, 0x3d395229 +0, 24, 24, 1, 599040, 0x9494b5ac +0, 25, 25, 1, 599040, 0x42560d96 +0, 26, 26, 1, 599040, 0x135f76d8 +0, 27, 27, 1, 599040, 0x3758c2ab +0, 28, 28, 1, 599040, 0x100fb1d8 +0, 29, 29, 1, 599040, 0x9273f18e +0, 30, 30, 1, 599040, 0x41b31734 +0, 31, 31, 1, 599040, 0xb2e140b7 +0, 32, 32, 1, 599040, 0xd35f3451 +0, 33, 33, 1, 599040, 0x6198a3d6 +0, 34, 34, 1, 599040, 0x0253e3fa +0, 35, 35, 1, 599040, 0x421a1cd1 +0, 36, 36, 1, 599040, 0xd2152e6b +0, 37, 37, 1, 599040, 0xe4c37cc7 +0, 38, 38, 1, 599040, 0xec3393c3 +0, 39, 39, 1, 599040, 0x1fe16574 +0, 40, 40, 1, 599040, 0xa3a8c14d +0, 41, 41, 1, 599040, 0x32eb90aa +0, 42, 42, 1, 599040, 0xebca8310 +0, 43, 43, 1, 599040, 0x7888627f +0, 44, 44, 1, 599040, 0xe048335c +0, 45, 45, 1, 599040, 0xe2262b9c +0, 46, 46, 1, 599040, 0xb8c2b115 +0, 47, 47, 1, 599040, 0x2ff4194b +0, 48, 48, 1, 599040, 0x3a9b5520 +0, 49, 49, 1, 599040, 0xbd8c0486 +0, 50, 50, 1, 599040, 0xc8b8f29e +0, 51, 51, 1, 599040, 0xbc12f62c +0, 52, 52, 1, 599040, 0x04bb6438 +0, 53, 53, 1, 599040, 0x07971646 +0, 54, 54, 1, 599040, 0x0193dabe +0, 55, 55, 1, 599040, 0x20f41d9e +0, 56, 56, 1, 599040, 0x04b40718 +0, 57, 57, 1, 599040, 0x75d2c51c +0, 58, 58, 1, 599040, 0x9b8c2c50 +0, 59, 59, 1, 599040, 0x970e39ea +0, 60, 60, 1, 599040, 0x7c4264aa +0, 61, 61, 1, 599040, 0xe939a6fd +0, 62, 62, 1, 599040, 0xc8b95f8d +0, 63, 63, 1, 599040, 0x9e2f384a +0, 64, 64, 1, 599040, 0x7dc74724 +0, 65, 65, 1, 599040, 0x7e93bc5f +0, 66, 66, 1, 599040, 0x99b2c09d +0, 67, 67, 1, 599040, 0x284e436f +0, 68, 68, 1, 599040, 0xaa303eee +0, 69, 69, 1, 599040, 0x65e54342 +0, 70, 70, 1, 599040, 0x2fe183cd +0, 71, 71, 1, 599040, 0x5953c191 +0, 72, 72, 1, 599040, 0x0fc9a701 +0, 73, 73, 1, 599040, 0x0eea5327 +0, 74, 74, 1, 599040, 0x118752f1 +0, 75, 75, 1, 599040, 0x778c7711 +0, 76, 76, 1, 599040, 0x6f3ad6a5 +0, 77, 77, 1, 599040, 0xf70fcd3d +0, 78, 78, 1, 599040, 0x85a366cb +0, 79, 79, 1, 599040, 0xdda47432 +0, 80, 80, 1, 599040, 0x86379004 +0, 81, 81, 1, 599040, 0xfc539512 +0, 82, 82, 1, 599040, 0x04e70786 +0, 83, 83, 1, 599040, 0x7dddc8f7 +0, 84, 84, 1, 599040, 0xa76a3b6e +0, 85, 85, 1, 599040, 0x44183060 +0, 86, 86, 1, 599040, 0x6f691c5a +0, 87, 87, 1, 599040, 0x39d25e12 +0, 88, 88, 1, 599040, 0xfe3aad0d +0, 89, 89, 1, 599040, 0x57f76928 +0, 90, 90, 1, 599040, 0x4e68eed5 +0, 91, 91, 1, 599040, 0x3a589d50 +0, 92, 92, 1, 599040, 0x92ec69b8 +0, 93, 93, 1, 599040, 0x9f78926e +0, 94, 94, 1, 599040, 0xa1ca1b1d +0, 95, 95, 1, 599040, 0x140240eb +0, 96, 96, 1, 599040, 0x61fa01af +0, 97, 97, 1, 599040, 0x79f9e3ae diff --git a/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1 b/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1 new file mode 100644 index 000000000..e45005f39 --- /dev/null +++ b/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1 @@ -0,0 +1,97 @@ +#tb 0: 1/25 +0, 0, 0, 1, 599040, 0x91d452d5 +0, 1, 1, 1, 599040, 0x1b482509 +0, 2, 2, 1, 599040, 0xbc51425c +0, 3, 3, 1, 599040, 0x5777eeee +0, 4, 4, 1, 599040, 0xe274644d +0, 5, 5, 1, 599040, 0x867450b5 +0, 6, 6, 1, 599040, 0x58708122 +0, 7, 7, 1, 599040, 0xeef17206 +0, 8, 8, 1, 599040, 0x97f4dc1e +0, 9, 9, 1, 599040, 0x92c961cc +0, 10, 10, 1, 599040, 0x1c4ffcb0 +0, 11, 11, 1, 599040, 0xc73e34e6 +0, 12, 12, 1, 599040, 0x1991f1f9 +0, 13, 13, 1, 599040, 0x36e54ba2 +0, 14, 14, 1, 599040, 0x698ce0c6 +0, 15, 15, 1, 599040, 0xc6dd131e +0, 16, 16, 1, 599040, 0x0a22f4c5 +0, 17, 17, 1, 599040, 0xd6a0c196 +0, 18, 18, 1, 599040, 0x699a3e69 +0, 19, 19, 1, 599040, 0x4227009b +0, 20, 20, 1, 599040, 0xd1d5dcb4 +0, 21, 21, 1, 599040, 0x58b2edb3 +0, 22, 22, 1, 599040, 0xd1f795d8 +0, 23, 23, 1, 599040, 0x3331d5e6 +0, 24, 24, 1, 599040, 0x5e5ec2c9 +0, 25, 25, 1, 599040, 0x3b907bf5 +0, 26, 26, 1, 599040, 0xefcbf471 +0, 27, 27, 1, 599040, 0x2769a578 +0, 28, 28, 1, 599040, 0x812ce986 +0, 29, 29, 1, 599040, 0xf07c212c +0, 30, 30, 1, 599040, 0x00a0249f +0, 31, 31, 1, 599040, 0x7263f7cf +0, 32, 32, 1, 599040, 0x47054be4 +0, 33, 33, 1, 599040, 0xda083f52 +0, 34, 34, 1, 599040, 0xf2906ab1 +0, 35, 35, 1, 599040, 0x20936797 +0, 36, 36, 1, 599040, 0x644d7c3e +0, 37, 37, 1, 599040, 0x7c00e8bf +0, 38, 38, 1, 599040, 0x041f8a48 +0, 39, 39, 1, 599040, 0xcef6e936 +0, 40, 40, 1, 599040, 0x361461e9 +0, 41, 41, 1, 599040, 0xf663ba0a +0, 42, 42, 1, 599040, 0x4d3371d3 +0, 43, 43, 1, 599040, 0xed6b5c92 +0, 44, 44, 1, 599040, 0xdec67f6e +0, 45, 45, 1, 599040, 0xbafa50c0 +0, 46, 46, 1, 599040, 0xc9181637 +0, 47, 47, 1, 599040, 0x29eadcac +0, 48, 48, 1, 599040, 0xb258430f +0, 49, 49, 1, 599040, 0x49dc8716 +0, 50, 50, 1, 599040, 0x80b0a3b3 +0, 51, 51, 1, 599040, 0x5d8275a7 +0, 52, 52, 1, 599040, 0xe236242d +0, 53, 53, 1, 599040, 0x3e14bb43 +0, 54, 54, 1, 599040, 0x20e6e2d7 +0, 55, 55, 1, 599040, 0x19cad4ee +0, 56, 56, 1, 599040, 0x13fd16f1 +0, 57, 57, 1, 599040, 0x98e56b95 +0, 58, 58, 1, 599040, 0x028e4c6a +0, 59, 59, 1, 599040, 0x5bd1131d +0, 60, 60, 1, 599040, 0x0afe3873 +0, 61, 61, 1, 599040, 0xea93e425 +0, 62, 62, 1, 599040, 0xeb301be1 +0, 63, 63, 1, 599040, 0x443ca0a3 +0, 64, 64, 1, 599040, 0xb68b40a1 +0, 65, 65, 1, 599040, 0xf58f75b9 +0, 66, 66, 1, 599040, 0xefa27c52 +0, 67, 67, 1, 599040, 0xac676fa5 +0, 68, 68, 1, 599040, 0x688d1582 +0, 69, 69, 1, 599040, 0x9067a4ef +0, 70, 70, 1, 599040, 0xdc753d6c +0, 71, 71, 1, 599040, 0x6f6da304 +0, 72, 72, 1, 599040, 0xa7606f97 +0, 73, 73, 1, 599040, 0xb53c8c18 +0, 74, 74, 1, 599040, 0x3572d550 +0, 75, 75, 1, 599040, 0x123d5423 +0, 76, 76, 1, 599040, 0x89f11e50 +0, 77, 77, 1, 599040, 0x702649cc +0, 78, 78, 1, 599040, 0x2b4767c4 +0, 79, 79, 1, 599040, 0xf18b9628 +0, 80, 80, 1, 599040, 0x1ef72a6b +0, 81, 81, 1, 599040, 0x0a8c9641 +0, 82, 82, 1, 599040, 0xf2fa0233 +0, 83, 83, 1, 599040, 0x99385e51 +0, 84, 84, 1, 599040, 0x77b413cf +0, 85, 85, 1, 599040, 0x6360c9e3 +0, 86, 86, 1, 599040, 0xe216b383 +0, 87, 87, 1, 599040, 0x54df8826 +0, 88, 88, 1, 599040, 0x6691e1ee +0, 89, 89, 1, 599040, 0x37bebd20 +0, 90, 90, 1, 599040, 0xf05184e4 +0, 91, 91, 1, 599040, 0xbd7fab4f +0, 92, 92, 1, 599040, 0x70211cdc +0, 93, 93, 1, 599040, 0x4f4c375b +0, 94, 94, 1, 599040, 0x2d645b5a +0, 95, 95, 1, 599040, 0x475d263f diff --git a/tests/ref/fate/idroq-video-encode b/tests/ref/fate/idroq-video-encode index 9d25b13a8..bdb6fedf5 100644 --- a/tests/ref/fate/idroq-video-encode +++ b/tests/ref/fate/idroq-video-encode @@ -1 +1 @@ -50fa863f7820bb22ddeb74d5adf5f0bc +e9ff61023826fce304350ff6e7c63b2f diff --git a/tests/ref/fate/iv8-demux b/tests/ref/fate/iv8-demux index f13e69194..02b6314b4 100644 --- a/tests/ref/fate/iv8-demux +++ b/tests/ref/fate/iv8-demux @@ -1,3 +1,4 @@ +#extradata 0: 19, 0x1f2604b9 #tb 0: 1/90000 0, 0, 0, 0, 20883, 0x347191e2 0, 0, 3600, 0, 20882, 0xe1573905 diff --git a/tests/ref/fate/lmlm4-demux b/tests/ref/fate/lmlm4-demux index f8a6e2103..95df3e612 100644 --- a/tests/ref/fate/lmlm4-demux +++ b/tests/ref/fate/lmlm4-demux @@ -1,3 +1,4 @@ +#extradata 0: 28, 0x2f140538 #tb 0: 1001/30000 #tb 1: 1/90000 0, 0, -9223372036854775808, 1, 5951, 0xe9118e0d diff --git a/tests/ref/fate/mapchan-6ch-extract-2 b/tests/ref/fate/mapchan-6ch-extract-2 index 98c854069..435cbec17 100644 --- a/tests/ref/fate/mapchan-6ch-extract-2 +++ b/tests/ref/fate/mapchan-6ch-extract-2 @@ -1,2 +1,2 @@ -6f091fe8c0be88c75921731dc9f74314 -5c2d162b9024329eb367295d37b8ca0a +955514d4a026a4a48695866d2ec904d0 +498a49e692ee2e3c454863654275c4bb diff --git a/tests/ref/fate/mapchan-6ch-extract-2-downmix-mono b/tests/ref/fate/mapchan-6ch-extract-2-downmix-mono index f42de0c95..a47c85cd6 100644 --- a/tests/ref/fate/mapchan-6ch-extract-2-downmix-mono +++ b/tests/ref/fate/mapchan-6ch-extract-2-downmix-mono @@ -1 +1 @@ -959645ed73e6d08d8f1e947eac5d0b92 +2727e5418eb5b8f89954f140d9f3a19a diff --git a/tests/ref/fate/mapchan-silent-mono b/tests/ref/fate/mapchan-silent-mono index a867e3b43..f720c318f 100644 --- a/tests/ref/fate/mapchan-silent-mono +++ b/tests/ref/fate/mapchan-silent-mono @@ -1 +1 @@ -4f5148f08587a4b9794aa52aec7852ac +16dc73c037897dff9b1d3e3d8561dc73 diff --git a/tests/ref/fate/mkv b/tests/ref/fate/mkv index 78440b2eb..84608fd34 100644 --- a/tests/ref/fate/mkv +++ b/tests/ref/fate/mkv @@ -1,3 +1,5 @@ +#extradata 0: 35, 0xc3b20b70 +#extradata 1: 2, 0x00b200a1 #tb 0: 1/1000 #tb 1: 1/1000 0, -42, 0, 0, 63501, 0x139d4c99 diff --git a/tests/ref/fate/mlv-demux b/tests/ref/fate/mlv-demux new file mode 100644 index 000000000..8c5901280 --- /dev/null +++ b/tests/ref/fate/mlv-demux @@ -0,0 +1 @@ +CRC=0x937f8af3 diff --git a/tests/ref/fate/mtv b/tests/ref/fate/mtv index a781c0835..9e898ff0b 100644 --- a/tests/ref/fate/mtv +++ b/tests/ref/fate/mtv @@ -1,3 +1,4 @@ +#extradata 0: 9, 0x116c033a #tb 0: 1/16 #tb 1: 1/44100 0, 0, 0, 1, 12288, 0xc2258ebc diff --git a/tests/ref/fate/mv-mvc1 b/tests/ref/fate/mv-mvc1 new file mode 100644 index 000000000..073c95a48 --- /dev/null +++ b/tests/ref/fate/mv-mvc1 @@ -0,0 +1,26 @@ +#tb 0: 1/10 +0, 0, 0, 1, 221184, 0x340ab080 +0, 1, 1, 1, 221184, 0xc21105a0 +0, 2, 2, 1, 221184, 0xa7482ab3 +0, 3, 3, 1, 221184, 0x67b0402b +0, 4, 4, 1, 221184, 0xa0b9632a +0, 5, 5, 1, 221184, 0x54e6af93 +0, 6, 6, 1, 221184, 0x90b3f085 +0, 7, 7, 1, 221184, 0x7aea8672 +0, 8, 8, 1, 221184, 0xbf01a23a +0, 9, 9, 1, 221184, 0x1dc692cc +0, 10, 10, 1, 221184, 0xd16bcc43 +0, 11, 11, 1, 221184, 0x103b8c41 +0, 12, 12, 1, 221184, 0xc2c964b6 +0, 13, 13, 1, 221184, 0x2837fbec +0, 14, 14, 1, 221184, 0x16de6390 +0, 15, 15, 1, 221184, 0xbaf0fd33 +0, 16, 16, 1, 221184, 0x7b05cca6 +0, 17, 17, 1, 221184, 0x5b0ae526 +0, 18, 18, 1, 221184, 0xd786f4e2 +0, 19, 19, 1, 221184, 0x21b88d75 +0, 20, 20, 1, 221184, 0xe41e6297 +0, 21, 21, 1, 221184, 0xd075f578 +0, 22, 22, 1, 221184, 0x1eaffc99 +0, 23, 23, 1, 221184, 0xcbd44422 +0, 24, 24, 1, 221184, 0x0e377c8a diff --git a/tests/ref/fate/mv-mvc2 b/tests/ref/fate/mv-mvc2 new file mode 100644 index 000000000..99acdc0fb --- /dev/null +++ b/tests/ref/fate/mv-mvc2 @@ -0,0 +1,31 @@ +#tb 0: 1/60 +0, 0, 0, 1, 126336, 0xb50e8bb0 +0, 1, 1, 1, 126336, 0xdc260cfa +0, 2, 2, 1, 126336, 0x2762f0d9 +0, 3, 3, 1, 126336, 0xec87d823 +0, 4, 4, 1, 126336, 0x1b28b47b +0, 5, 5, 1, 126336, 0x65508be0 +0, 6, 6, 1, 126336, 0x175565f0 +0, 7, 7, 1, 126336, 0x483f5138 +0, 8, 8, 1, 126336, 0xaacd2a7c +0, 9, 9, 1, 126336, 0x170c09f5 +0, 10, 10, 1, 126336, 0x27c0e945 +0, 11, 11, 1, 126336, 0x5555d3fd +0, 12, 12, 1, 126336, 0x7749ad6a +0, 13, 13, 1, 126336, 0xee3096de +0, 14, 14, 1, 126336, 0xe2b27655 +0, 15, 15, 1, 126336, 0x580556e5 +0, 16, 16, 1, 126336, 0x6f912baa +0, 17, 17, 1, 126336, 0xb57e0b94 +0, 18, 18, 1, 126336, 0x2032e017 +0, 19, 19, 1, 126336, 0xe08da60f +0, 20, 20, 1, 126336, 0xb8419e26 +0, 21, 21, 1, 126336, 0xaf58b9d1 +0, 22, 22, 1, 126336, 0x3d88e5ba +0, 23, 23, 1, 126336, 0x83d30a85 +0, 24, 24, 1, 126336, 0x8f2c27af +0, 25, 25, 1, 126336, 0x296c3a7e +0, 26, 26, 1, 126336, 0xf6d458ac +0, 27, 27, 1, 126336, 0x2e2172aa +0, 28, 28, 1, 126336, 0x611c8b2f +0, 29, 29, 1, 126336, 0x64b2c607 diff --git a/tests/ref/fate/mv-sgirle b/tests/ref/fate/mv-sgirle new file mode 100644 index 000000000..60aff0a4b --- /dev/null +++ b/tests/ref/fate/mv-sgirle @@ -0,0 +1,32 @@ +#tb 0: 1/4 +0, 0, 0, 1, 187500, 0xf2c26a39 +0, 1, 1, 1, 187500, 0xf65e6ea5 +0, 2, 2, 1, 187500, 0x804f78d0 +0, 3, 3, 1, 187500, 0x47a69f58 +0, 4, 4, 1, 187500, 0x7286207c +0, 5, 5, 1, 187500, 0x8e4111fc +0, 6, 6, 1, 187500, 0x8e2af3ba +0, 7, 7, 1, 187500, 0xdae8b4e3 +0, 8, 8, 1, 187500, 0x43178cdd +0, 9, 9, 1, 187500, 0xcecdf216 +0, 10, 10, 1, 187500, 0x31a4c772 +0, 11, 11, 1, 187500, 0x7e09b58d +0, 12, 12, 1, 187500, 0x92e9a999 +0, 13, 13, 1, 187500, 0x4fdc7c43 +0, 14, 14, 1, 187500, 0xf03945bd +0, 15, 15, 1, 187500, 0xb87d0fa8 +0, 16, 16, 1, 187500, 0xf85a99ac +0, 17, 17, 1, 187500, 0x08bb0d34 +0, 18, 18, 1, 187500, 0x82216d03 +0, 19, 19, 1, 187500, 0xc4ce0a7b +0, 20, 20, 1, 187500, 0x099863c2 +0, 21, 21, 1, 187500, 0xc5e44d02 +0, 22, 22, 1, 187500, 0x2fa8c68a +0, 23, 23, 1, 187500, 0x8ee13c76 +0, 24, 24, 1, 187500, 0xbd6f9e6a +0, 25, 25, 1, 187500, 0x8017e354 +0, 26, 26, 1, 187500, 0x6d471686 +0, 27, 27, 1, 187500, 0xfb675046 +0, 28, 28, 1, 187500, 0x8c6b8e59 +0, 29, 29, 1, 187500, 0x421bb7a6 +0, 30, 30, 1, 187500, 0x09bb7932 diff --git a/tests/ref/fate/mxf-demux b/tests/ref/fate/mxf-demux index 454722e67..3d9a2dc49 100644 --- a/tests/ref/fate/mxf-demux +++ b/tests/ref/fate/mxf-demux @@ -1,3 +1,4 @@ +#extradata 0: 18, 0x0b150244 #tb 0: 1/25 #tb 1: 1/8000 0, 0, -9223372036854775808, 1, 8468, 0xc0855553 diff --git a/tests/ref/fate/nc-demux b/tests/ref/fate/nc-demux index f03aded86..98318ac87 100644 --- a/tests/ref/fate/nc-demux +++ b/tests/ref/fate/nc-demux @@ -1,3 +1,4 @@ +#extradata 0: 19, 0x1afd0446 #tb 0: 1/100 0, 0, -9223372036854775808, 1, 19787, 0x75e463f3 0, 1, -9223372036854775808, 1, 11913, 0x0f429c34, F=0x0 diff --git a/tests/ref/fate/on2avc b/tests/ref/fate/on2avc new file mode 100644 index 000000000..ac08dae9b --- /dev/null +++ b/tests/ref/fate/on2avc @@ -0,0 +1,31 @@ +#tb 0: 1/16000 +0, 0, 0, 1024, 2048, 0x00000000 +0, 1024, 1024, 1024, 2048, 0x96ee1301 +0, 2048, 2048, 1024, 2048, 0xe2a81605 +0, 3072, 3072, 1024, 2048, 0x3a0e15f9 +0, 4096, 4096, 1024, 2048, 0xcb4515d6 +0, 5120, 5120, 1024, 2048, 0x75021609 +0, 6144, 6144, 1024, 2048, 0xefa91606 +0, 7168, 7168, 1024, 2048, 0x6e8315d0 +0, 8192, 8192, 1024, 2048, 0xd03815fe +0, 9216, 9216, 1024, 2048, 0xb38115cd +0, 10240, 10240, 1024, 2048, 0x4ece15ec +0, 11264, 11264, 1024, 2048, 0x33741600 +0, 12288, 12288, 1024, 2048, 0x97e915d7 +0, 13312, 13312, 1024, 2048, 0xc23815fc +0, 14336, 14336, 1024, 2048, 0x069a15ef +0, 15360, 15360, 1024, 2048, 0x0b3a15e7 +0, 16384, 16384, 1024, 2048, 0x9d2c1616 +0, 17408, 17408, 1024, 2048, 0x810d15d9 +0, 18432, 18432, 1024, 2048, 0x79a215ed +0, 19456, 19456, 1024, 2048, 0x58be15e3 +0, 20480, 20480, 1024, 2048, 0x577415ed +0, 21504, 21504, 1024, 2048, 0x208015ee +0, 22528, 22528, 1024, 2048, 0x2f6815da +0, 23552, 23552, 1024, 2048, 0x42e41609 +0, 24576, 24576, 1024, 2048, 0x85a915d2 +0, 25600, 25600, 1024, 2048, 0x8b8215f0 +0, 26624, 26624, 1024, 2048, 0x92c21602 +0, 27648, 27648, 1024, 2048, 0xb28115db +0, 28672, 28672, 1024, 2048, 0x5e7615f6 +0, 29696, 29696, 1024, 2048, 0x6b1c15f6 diff --git a/tests/ref/fate/sanm b/tests/ref/fate/sanm index 8b6f90372..a882118b1 100644 --- a/tests/ref/fate/sanm +++ b/tests/ref/fate/sanm @@ -1,4 +1,4 @@ -#tb 0: 66667/1000000 +#tb 0: 1/15 0, 0, 0, 1, 921600, 0x00000000 0, 1, 1, 1, 921600, 0x00000000 0, 2, 2, 1, 921600, 0x00000000 diff --git a/tests/ref/fate/sgi-gray b/tests/ref/fate/sgi-gray new file mode 100644 index 000000000..4d4d3494f --- /dev/null +++ b/tests/ref/fate/sgi-gray @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 65536, 0xe36c12e1 diff --git a/tests/ref/fate/sgi-gray16 b/tests/ref/fate/sgi-gray16 new file mode 100644 index 000000000..f56e53eb3 --- /dev/null +++ b/tests/ref/fate/sgi-gray16 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 131072, 0x6855d247 diff --git a/tests/ref/fate/sgi-rgb24 b/tests/ref/fate/sgi-rgb24 new file mode 100644 index 000000000..7a6e85537 --- /dev/null +++ b/tests/ref/fate/sgi-rgb24 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 196608, 0x5b24c51a diff --git a/tests/ref/fate/sgi-rgb24-rle b/tests/ref/fate/sgi-rgb24-rle new file mode 100644 index 000000000..1128de56d --- /dev/null +++ b/tests/ref/fate/sgi-rgb24-rle @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 393216, 0xe96e1de2 diff --git a/tests/ref/fate/sgi-rgb48 b/tests/ref/fate/sgi-rgb48 new file mode 100644 index 000000000..b0521b7fc --- /dev/null +++ b/tests/ref/fate/sgi-rgb48 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 393216, 0xf6b0d73a diff --git a/tests/ref/fate/sgi-rgb48-rle b/tests/ref/fate/sgi-rgb48-rle new file mode 100644 index 000000000..2cf025969 --- /dev/null +++ b/tests/ref/fate/sgi-rgb48-rle @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 786432, 0xbc743bc4 diff --git a/tests/ref/fate/sgi-rgba b/tests/ref/fate/sgi-rgba new file mode 100644 index 000000000..9b3d4cb79 --- /dev/null +++ b/tests/ref/fate/sgi-rgba @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 262144, 0x7b38d40b diff --git a/tests/ref/fate/sgi-rgba64 b/tests/ref/fate/sgi-rgba64 new file mode 100644 index 000000000..94e35afd3 --- /dev/null +++ b/tests/ref/fate/sgi-rgba64 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 524288, 0xce70f51c diff --git a/tests/ref/fate/sgi-rgba64-rle b/tests/ref/fate/sgi-rgba64-rle new file mode 100644 index 000000000..1dfac760f --- /dev/null +++ b/tests/ref/fate/sgi-rgba64-rle @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 614400, 0xb92d409d diff --git a/tests/ref/fate/sub-aqtitle b/tests/ref/fate/sub-aqtitle index c477b0af8..d87194bbd 100644 --- a/tests/ref/fate/sub-aqtitle +++ b/tests/ref/fate/sub-aqtitle @@ -1 +1 @@ -1c68def68db6536c235819cbe0638e00 +47834efc39225264e705dfb885f57df2 diff --git a/tests/ref/fate/sub-charenc b/tests/ref/fate/sub-charenc index ef727546f..5081731a8 100644 --- a/tests/ref/fate/sub-charenc +++ b/tests/ref/fate/sub-charenc @@ -1 +1 @@ -9615088d613931b50fd5016c7535b99a +c088c2924fd7af0a53eeeeb54a3f4456 diff --git a/tests/ref/fate/sub-jacosub b/tests/ref/fate/sub-jacosub index b65aee290..b9b0cf76d 100644 --- a/tests/ref/fate/sub-jacosub +++ b/tests/ref/fate/sub-jacosub @@ -1 +1 @@ -4e8f2d1d4130251163432d2a448680be +3bf9f062bd9825c7d8c3b62451b6d360 diff --git a/tests/ref/fate/sub-microdvd b/tests/ref/fate/sub-microdvd index 205998917..f72308eaf 100644 --- a/tests/ref/fate/sub-microdvd +++ b/tests/ref/fate/sub-microdvd @@ -1 +1 @@ -35e133576aa3881d2de8dbf39a8d6df7 +1741d6776462277430d5e320157f5bf9 diff --git a/tests/ref/fate/sub-movtext b/tests/ref/fate/sub-movtext index d91c24303..327439549 100644 --- a/tests/ref/fate/sub-movtext +++ b/tests/ref/fate/sub-movtext @@ -1 +1 @@ -21453e8ddbbe35d1368a99fe563c969d +24c02caa25c6a82d803171697a10d8f5 diff --git a/tests/ref/fate/sub-movtextenc b/tests/ref/fate/sub-movtextenc index f6f41746a..5d99766a3 100644 --- a/tests/ref/fate/sub-movtextenc +++ b/tests/ref/fate/sub-movtextenc @@ -1 +1 @@ -cf3d43e6de1f97681583ba08d9fe5938 +3c685e807d4961924d0abcc18b3f8fa8 diff --git a/tests/ref/fate/sub-mpl2 b/tests/ref/fate/sub-mpl2 index 8835dd241..39b38bc23 100644 --- a/tests/ref/fate/sub-mpl2 +++ b/tests/ref/fate/sub-mpl2 @@ -1 +1 @@ -3c2fb62002aec3af16d83135a0e3b0fc +28fb7dad61c3394f5edc8b186fdf7dd6 diff --git a/tests/ref/fate/sub-mpsub b/tests/ref/fate/sub-mpsub index 4e3664805..d49ba2acd 100644 --- a/tests/ref/fate/sub-mpsub +++ b/tests/ref/fate/sub-mpsub @@ -1 +1 @@ -2c5fafec41479e1d09a32f85e8927d03 +2f10577c4e2631e9a50495fa2cc9a985 diff --git a/tests/ref/fate/sub-mpsub-frames b/tests/ref/fate/sub-mpsub-frames index d5bb44e28..f78edd0ee 100644 --- a/tests/ref/fate/sub-mpsub-frames +++ b/tests/ref/fate/sub-mpsub-frames @@ -1 +1 @@ -cbe6e45848ef77e3080487a88b122104 +792dab5d9a471e0381e18b705fc408cc diff --git a/tests/ref/fate/sub-pjs b/tests/ref/fate/sub-pjs index 8b382e734..353503917 100644 --- a/tests/ref/fate/sub-pjs +++ b/tests/ref/fate/sub-pjs @@ -1 +1 @@ -d044f6ffdee48e48efff072b33baee0a +a335eefaf09b3b148e65c757bf41af4d diff --git a/tests/ref/fate/sub-realtext b/tests/ref/fate/sub-realtext index 42ac3bb19..4dc5753e8 100644 --- a/tests/ref/fate/sub-realtext +++ b/tests/ref/fate/sub-realtext @@ -1 +1 @@ -5366f62be001f6fd4a7f48893828bf51 +a36977a149ce60eac443e4c9bb329ca2 diff --git a/tests/ref/fate/sub-sami b/tests/ref/fate/sub-sami index 308e00034..0f5dc6d34 100644 --- a/tests/ref/fate/sub-sami +++ b/tests/ref/fate/sub-sami @@ -1 +1 @@ -00642e143339b4ca29dc6e990436387c +04098faede85ddacb40aa12c798cc0cc diff --git a/tests/ref/fate/sub-srt b/tests/ref/fate/sub-srt index ba5e50a65..c5044e380 100644 --- a/tests/ref/fate/sub-srt +++ b/tests/ref/fate/sub-srt @@ -1 +1 @@ -a246a00ed72655cb8db3eaf64a522e0d +be870f5037933b6890d56e614ec4aa75 diff --git a/tests/ref/fate/sub-subviewer b/tests/ref/fate/sub-subviewer index abae1f7bb..a0838685e 100644 --- a/tests/ref/fate/sub-subviewer +++ b/tests/ref/fate/sub-subviewer @@ -1 +1 @@ -aef995d49af4517b40589b72cfa918f7 +848f774195e873ce71febf35b6c9c541 diff --git a/tests/ref/fate/sub-subviewer1 b/tests/ref/fate/sub-subviewer1 index 052431a81..7d2ca53a9 100644 --- a/tests/ref/fate/sub-subviewer1 +++ b/tests/ref/fate/sub-subviewer1 @@ -1 +1 @@ -cbeb015b1125757eed814f212cfc6c9c +040d7880a6621b1661f9d12c5375037f diff --git a/tests/ref/fate/sub-vplayer b/tests/ref/fate/sub-vplayer index b8fc40e1e..70ba787a5 100644 --- a/tests/ref/fate/sub-vplayer +++ b/tests/ref/fate/sub-vplayer @@ -1 +1 @@ -c8201c542f43a9ea42a787ac74d28049 +0bb5d4f72b6dc1b37d2ee7b5579ed87e diff --git a/tests/ref/fate/sub-webvtt b/tests/ref/fate/sub-webvtt index 45cccde4f..528e55c5e 100644 --- a/tests/ref/fate/sub-webvtt +++ b/tests/ref/fate/sub-webvtt @@ -1 +1 @@ -2cf38e2c99f8717f78a91a3f31197fb4 +ee266bd7141df4ea11a9447ab038bb6e diff --git a/tests/ref/fate/sub-webvttenc b/tests/ref/fate/sub-webvttenc new file mode 100644 index 000000000..3fe666937 --- /dev/null +++ b/tests/ref/fate/sub-webvttenc @@ -0,0 +1 @@ +8683216a86e147a98f29dafee33a0987 diff --git a/tests/ref/fate/sub2video b/tests/ref/fate/sub2video index 39d00c774..1c6cdaf12 100644 --- a/tests/ref/fate/sub2video +++ b/tests/ref/fate/sub2video @@ -1,3 +1,4 @@ +#extradata 1: 150, 0x7c99258b #tb 0: 1/5 #tb 1: 1/1000 0, 0, 0, 1, 518400, 0x83c27b82 diff --git a/tests/ref/fate/utvideoenc_rgb_left b/tests/ref/fate/utvideoenc_rgb_left index 87d5f27d6..f6adabe9d 100644 --- a/tests/ref/fate/utvideoenc_rgb_left +++ b/tests/ref/fate/utvideoenc_rgb_left @@ -44,7 +44,7 @@ 0, 38, 38, 1, 179776, 01d407ed0b86eeb2c3ee3c24dd452d8d 0, 39, 39, 1, 180100, 062e4af150100d7accf86a907a4b99b5 0, 40, 40, 1, 180228, 23c617b76ef8f274bd089016fb8516c7 -0, 41, 41, 1, 180592, 55f538ae5e44b60209138b7536d5c199 +0, 41, 41, 1, 180592, 5cd3d93597325196079dc019556f6933 0, 42, 42, 1, 181188, d39d52f5b690661434b1abd8717b3e30 0, 43, 43, 1, 181300, 9e202444287234bafd103fab83b1a974 0, 44, 44, 1, 180812, 602165271de71594132cce98af56a7b2 diff --git a/tests/ref/fate/utvideoenc_rgb_none b/tests/ref/fate/utvideoenc_rgb_none index 207c68837..839766bf4 100644 --- a/tests/ref/fate/utvideoenc_rgb_none +++ b/tests/ref/fate/utvideoenc_rgb_none @@ -3,53 +3,53 @@ #hash: MD5 #tb 0: 1/25 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 301052, 8645cb98470205cceea3c2026223b69f -0, 1, 1, 1, 301068, 9123c3c31ac0bc0832bb07e8c6d5b372 -0, 2, 2, 1, 300840, 394aa034eba2b306efa8171efc5fb960 -0, 3, 3, 1, 300904, 1abc4512d268bb7bb4b9f467aa19e5a8 -0, 4, 4, 1, 300912, e117d6f8d2bbd89bdce86cd5c4cf6206 -0, 5, 5, 1, 300936, d6a6c100e6dfd0e4dcdaa67ec59a757a -0, 6, 6, 1, 300944, 3a0bf05461965bf2e538f5ed1067e784 -0, 7, 7, 1, 301044, 66e2fef970e8d997bb52f28eed9ad6fe -0, 8, 8, 1, 301076, 6ae8f26125255c46be8c6da07d21ba35 -0, 9, 9, 1, 301044, 024d41f9d3b217b58ad6ba2a8f3b680d -0, 10, 10, 1, 300944, 5dc0387f32b68e365c467f9dcc62b923 -0, 11, 11, 1, 300912, 47db16c6118feb2143fe0d1ec909bb51 -0, 12, 12, 1, 301044, 7161af85d2c85529b83548a701c6f5b7 -0, 13, 13, 1, 300964, 2dd90b4edcfc8d2b84168f42c7a47785 -0, 14, 14, 1, 300868, 76b296949227e7b22f204bec90dd02af -0, 15, 15, 1, 300880, 44f9c830be2c9efdda335bf774f3b6c6 -0, 16, 16, 1, 301020, 70c1883ae4ff2ae8b0d5a608a75c839c -0, 17, 17, 1, 301072, bac10cb932595594e4e8146831bbe00b -0, 18, 18, 1, 301192, 46c2aa31dc33baa4d37f71f9873cbe6f -0, 19, 19, 1, 301224, 396c406acf79cbe79c064ccbe7a3b648 -0, 20, 20, 1, 301180, 8d5d2071ddc79335f6785a921851905e -0, 21, 21, 1, 301180, 9767bc30cadd23f0625e665e9b70ac31 -0, 22, 22, 1, 301116, fba702e0ab727d9446a7796790a10545 -0, 23, 23, 1, 301060, 9a08113dd947874b57d4cc85d56343ca -0, 24, 24, 1, 301128, a58b1ebeb28fac3c88f64c8ba15f0591 -0, 25, 25, 1, 301144, e071b28b961f8d9c5da9b1ff41c24c2a -0, 26, 26, 1, 301088, d19bed9054db25a718724d746d22c800 -0, 27, 27, 1, 301232, 70b2832bb0eb5f8a74e0bee411f66a46 -0, 28, 28, 1, 301152, 470bd72096d3ef6b5490b03cfdea438d -0, 29, 29, 1, 301224, f3c285eb28a3c5b820276d3a68976df4 -0, 30, 30, 1, 301224, a432bfc1e022f189a70cbc963d716596 -0, 31, 31, 1, 301160, fbde0ac1bb6e5dbd870c1c6d8f03190c -0, 32, 32, 1, 301120, 61f251db3d73483206609718063cfbb9 -0, 33, 33, 1, 301096, 6c1908eac263c8c3368683ced8078da4 -0, 34, 34, 1, 301000, 4b8df4fa83c085ea36369dbdd37f58bd -0, 35, 35, 1, 301152, e2ceb9ff6b72b815e4b511a85dc0ae38 -0, 36, 36, 1, 301232, 27cc508ff5081f9c901c4eabd62e5835 -0, 37, 37, 1, 301228, bdb62b975b1cfe4ba8be08be1e8b1a5e -0, 38, 38, 1, 301296, 13fc07f3935b70e98922233cf81bc7a4 -0, 39, 39, 1, 301296, 5fe19496257987b809e56e3c11192c43 -0, 40, 40, 1, 301308, a86115cd10e74c795739e8e325403ac6 -0, 41, 41, 1, 301268, 6c1f7bbf077ff58486f256e2ce9d01e6 -0, 42, 42, 1, 301344, 3fda739956dfa07a15cc5bd7e054568d -0, 43, 43, 1, 301308, 54584061bcce46feb19aafa37922f923 -0, 44, 44, 1, 301292, 092e08d230dcfe4abd1460ef26c31421 -0, 45, 45, 1, 301344, 39ca46f9f38434aee15660263921f392 -0, 46, 46, 1, 301432, f7b76bebcfc614537c20bd6b20096d78 -0, 47, 47, 1, 301440, 86c97147d03bf7aee71073127c7fad32 -0, 48, 48, 1, 301460, 3fdbe5ae0b7e6b7ec0bc5668ba50a491 -0, 49, 49, 1, 301444, 8ef2e62af67f91e886b8f25456b38869 +0, 0, 0, 1, 301024, 44de62472f485410819707c44b53f276 +0, 1, 1, 1, 301036, ff3c28c23b15834a84c57b304610924f +0, 2, 2, 1, 300812, 72f02a697464f5fdd54ae2e054c131d1 +0, 3, 3, 1, 300876, 8879becf8b3d5001b196f45b7817ef6b +0, 4, 4, 1, 300880, 2edeed55c4d84dea1fc9386553d7503f +0, 5, 5, 1, 300904, f799f26eae30e1796bd62f9cdbcb2b17 +0, 6, 6, 1, 300908, bc606ee3ab284d3567a3fbd476d674f0 +0, 7, 7, 1, 301012, 404f55be9ec860a1ab3d15711965c9ba +0, 8, 8, 1, 301048, 112394db28656101b4e8ba3621b437ae +0, 9, 9, 1, 301008, 8945bb7668b4a529844e68e1f6b6522b +0, 10, 10, 1, 300908, a9097c5f0bd7ddea711a25aa74696f70 +0, 11, 11, 1, 300876, 579de317d166295088530c78f403611d +0, 12, 12, 1, 301012, d97e3627c494012d6167a30ec8192360 +0, 13, 13, 1, 300928, fd20066b7f31363751328aefedfae04c +0, 14, 14, 1, 300836, d9bdd5606f4426b503f19a674e8058a3 +0, 15, 15, 1, 300848, 6c8f2cbd75646592876f8138a017c1ce +0, 16, 16, 1, 300988, 54e19940011b3bfed809a0edc12c3dd7 +0, 17, 17, 1, 301040, b1d5f39215f305953a846fb01dbc2f24 +0, 18, 18, 1, 301164, 9dde74f0ee3626eeea41c538fd80e1fb +0, 19, 19, 1, 301196, fdf22d2c35c7ab72416a268bf6612650 +0, 20, 20, 1, 301148, 275261bc1c1dec0bf712dcf05213def2 +0, 21, 21, 1, 301144, 66ccea6fce9d6d7016dafb3b349fa163 +0, 22, 22, 1, 301080, d6dc6ce0708dfdf74e936271a98c19e9 +0, 23, 23, 1, 301028, 48e610b9d798e0642825919fab233524 +0, 24, 24, 1, 301100, aed8f8f0a9d96ab9906ea8175e18c9ff +0, 25, 25, 1, 301116, fe9e1eccb9ccc92b4041228ea2c56c8e +0, 26, 26, 1, 301052, 3ec2f76b41fd8a6eafaa6bb14b94c153 +0, 27, 27, 1, 301200, 60d608bbe0ca285a7d8a1a4822a84c4d +0, 28, 28, 1, 301120, 6d2cec50ee32e76eb6dff76a4976d221 +0, 29, 29, 1, 301188, 8faa69fd62e0646e4eb85c1601827364 +0, 30, 30, 1, 301192, eb1fa109c5e9b89f29be7cf363649acd +0, 31, 31, 1, 301128, 32ba1797f5dee6643712688621984326 +0, 32, 32, 1, 301088, a1bfa70314c40f60a0823beef74e233e +0, 33, 33, 1, 301064, b18d84efa0091199dd9167bbdb36b873 +0, 34, 34, 1, 300964, a2ae8d3dd655403bcfdace40aaa1d78b +0, 35, 35, 1, 301124, 8ece60df0f0ef4f3d887eac16c23cad6 +0, 36, 36, 1, 301200, 13eb4b5ec7471837aadce38848e48cb2 +0, 37, 37, 1, 301196, b5fdef211755134f8e7998793a0ab0c0 +0, 38, 38, 1, 301260, 2f7e2046bae9e664e74bc56a3596743c +0, 39, 39, 1, 301264, 2cfc013c9e66a5dd0229c6551febd658 +0, 40, 40, 1, 301272, 47e8ff02a8f054c66687e2b613e46cf5 +0, 41, 41, 1, 301236, f4d766155eeeb7b03687a3141840bf32 +0, 42, 42, 1, 301312, 8fe134aefc02b6910dc2054447fd9c37 +0, 43, 43, 1, 301272, 9ec57db275fca2b596734c48a50c28bc +0, 44, 44, 1, 301256, 17bae207d8d6f5b2b500885e3058185f +0, 45, 45, 1, 301308, 9f8e91f3fbbdd0ca17b2ad0ffe888d5a +0, 46, 46, 1, 301400, 8184e55eb5432516547df512175c15fc +0, 47, 47, 1, 301408, dd0c0aa1426427549e9cbb22ef82f930 +0, 48, 48, 1, 301424, c65025dc3fa21fad98118ab0386b910e +0, 49, 49, 1, 301408, 2982b49e94aa25b8ef30f81769650f15 diff --git a/tests/ref/fate/utvideoenc_rgba_left b/tests/ref/fate/utvideoenc_rgba_left index 79a4ba737..83e3cb48b 100644 --- a/tests/ref/fate/utvideoenc_rgba_left +++ b/tests/ref/fate/utvideoenc_rgba_left @@ -3,53 +3,53 @@ #hash: MD5 #tb 0: 1/25 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 195264, 5869dee2126d98ecc1fab1e69720906a -0, 1, 1, 1, 195272, 1bd08dcde1061b0d9273bdc6dd901382 -0, 2, 2, 1, 195892, 2b3fc3632bcd1cc44f777fb97a56f79b -0, 3, 3, 1, 195320, 792870fc50a4145ad561b1004a8b6451 -0, 4, 4, 1, 194640, c3d4031c46d6dc64e632e2d38b48fc96 -0, 5, 5, 1, 195072, 27e4b09e7f8446a8dd8dd7dcbc578e2b -0, 6, 6, 1, 194488, e44441beb8d3e358112e2776a0116ea9 -0, 7, 7, 1, 195228, 0519afd694512aea2c839fe0456e518c -0, 8, 8, 1, 194360, 7296944c86296fb256188975db6e5620 -0, 9, 9, 1, 195252, 40b53999a36ce413256c7a81c3aa0c44 -0, 10, 10, 1, 195000, 925fe520c460f94ae7a05cf0e6cf8dd8 -0, 11, 11, 1, 195532, af417aac106af9b4e8c04cf1a84d3bd8 -0, 12, 12, 1, 193836, 0eadf04f475a93ebef3979d32c13ee92 -0, 13, 13, 1, 194856, 5814ff44b233d68e4c991703c0fa6f44 -0, 14, 14, 1, 195760, e9a66bbeadeab4ed3f34296346eafc27 -0, 15, 15, 1, 195388, 17d33cd676c8b464d1b97ce0f0234716 -0, 16, 16, 1, 195248, 1054b945cd6e11e70d8b348e540e4dd5 -0, 17, 17, 1, 194792, f0a6ceee9014f6cf8a999f344897ad3e -0, 18, 18, 1, 194044, 4fbf2b9fd8b7e8233f65b5bf61e326c0 -0, 19, 19, 1, 194324, eb90b72edafab7bbe5e9ff561313927c -0, 20, 20, 1, 193872, 6ebc973b9f66e1ebdb3029f1aadd9a24 -0, 21, 21, 1, 193836, cde713fba6bede0361779c45f7a6d80b -0, 22, 22, 1, 194872, 64225b7d92c8371ed0335d7693902f60 -0, 23, 23, 1, 195240, b11e0b10b4e713caffec706d952edb7b -0, 24, 24, 1, 195516, 932244aee01b068f1bfb5132f092675b -0, 25, 25, 1, 195508, 2745faafa2ec34dcf2cec2f5f791f49b -0, 26, 26, 1, 195292, 6ff67783eabad9c72b146d510ffa0b7e -0, 27, 27, 1, 194468, cc5aa248fe507ac3fbb839b9388856bc -0, 28, 28, 1, 192516, 13063bb195380953743ab24a73ff6ddd -0, 29, 29, 1, 192464, a391b0d795b2f565cc3e351975fb528d -0, 30, 30, 1, 193696, 4239c695d1b9eaa44c2d037a9c39da20 -0, 31, 31, 1, 194500, 5857b4c4cc86a9a0f38d833c236e396c -0, 32, 32, 1, 194364, ad0eeec7622c76bd996deac7e99390e5 -0, 33, 33, 1, 195916, b98da9283eef85f6dffe308774161441 -0, 34, 34, 1, 195560, 32f924fc40bb777c951481b623a8f46b -0, 35, 35, 1, 195288, 96a7bb386420902fbb98b8267d4496ca -0, 36, 36, 1, 194272, 98b88d6092708ffff416417d8f628477 -0, 37, 37, 1, 194464, 3c8295490b77415c2e4ebb7ce9b8cc53 -0, 38, 38, 1, 192712, 17798a13ba5f82939d98dfd619a68e18 -0, 39, 39, 1, 193036, b92ab54b363c1bd29042feeb3b9f5631 -0, 40, 40, 1, 193164, a971b68bb49148afdf510be5f5793933 -0, 41, 41, 1, 193528, 6fbf07d240e0073e57d295bdd0d32465 -0, 42, 42, 1, 194124, 4b1ddea464b8e40da48418e77b4fdf7a -0, 43, 43, 1, 194236, d46914a9e2bdda30bf84b3282924bb3d -0, 44, 44, 1, 193748, 3d4587081c6d73366d85e5df42c87810 -0, 45, 45, 1, 191752, 996274b3852ac6af30db8f9e242895e0 -0, 46, 46, 1, 191132, 5a1e47e4d1cc9e18e94041b4357a5de4 -0, 47, 47, 1, 191708, e3048c5ba2b9a494791cad3cbf843780 -0, 48, 48, 1, 191588, dbc63170a9b7be348497162c42a1b9f1 -0, 49, 49, 1, 191448, db923a15f424e69bbf8c8af2a2f7e157 +0, 0, 0, 1, 195260, a8fdb226460f210542e7aca6c12b0874 +0, 1, 1, 1, 195268, 45f098764ccba85dc641b7e401461c0a +0, 2, 2, 1, 195888, e922261672c7de46a302abad3a3fe450 +0, 3, 3, 1, 195316, f8febd5af0fed000fab2943cc649975f +0, 4, 4, 1, 194636, d90985ad8afd2f969afa842510085852 +0, 5, 5, 1, 195068, 909adb44bd049186a959f2803e641520 +0, 6, 6, 1, 194484, 547772233e653daccc6610fcb6369da7 +0, 7, 7, 1, 195224, aa82b75f6230b2e948abdfe36bce1150 +0, 8, 8, 1, 194356, d67fb1208532137252701ddcbf7bfc2e +0, 9, 9, 1, 195248, 7b08698d2a911fba5231c0fef0ded4c2 +0, 10, 10, 1, 194996, 570e7d9caec52975dec1c2a5dbf7cdef +0, 11, 11, 1, 195528, 7309c0531b942902c691781f2a6da1a1 +0, 12, 12, 1, 193832, 40954ceb87370cac3db5c8c2d7c001d1 +0, 13, 13, 1, 194852, 538382c377f0c6e9070ec0b8c5fb3e39 +0, 14, 14, 1, 195756, d002a80346f3460380abb794f2d56a62 +0, 15, 15, 1, 195384, 1a4f58b3c710f2fedaf746c281556b4c +0, 16, 16, 1, 195244, 218832dab1251e1dc852e6839a48b3fc +0, 17, 17, 1, 194788, a035acf428bd9565a4c3fec25dfc6f4f +0, 18, 18, 1, 194040, 6dbfeb949bdeeb055a4f7ebf78af9a85 +0, 19, 19, 1, 194320, 8b4aa3f6f05aa684d9e4adfa4cdce814 +0, 20, 20, 1, 193868, 98cd8b150784f6695f8dea163cecf286 +0, 21, 21, 1, 193832, 27a8db33014c4bc6a8da356c4b1a3e4f +0, 22, 22, 1, 194868, f1e1460dca9127197c0a40e659924616 +0, 23, 23, 1, 195236, a012f8548e92243334edcd7c8f57aa52 +0, 24, 24, 1, 195512, bf3d4e968d126231baa6618d3344ef81 +0, 25, 25, 1, 195504, adf4b49d8721f1b323fa518f2f0d4750 +0, 26, 26, 1, 195288, aa16dd087a73a9cadc5abfc0a46ccdd4 +0, 27, 27, 1, 194464, 2e3f07244999cbe949495b57adcabe69 +0, 28, 28, 1, 192512, 2d6ce0d29a929e0208e1578e95c9d388 +0, 29, 29, 1, 192460, 081d18cd138eead0cd4b25f54a7c7540 +0, 30, 30, 1, 193692, 546b6ad28b612c2f601c7d87b265ba95 +0, 31, 31, 1, 194496, b2b2ae3b1d67e332295456e6c7bdd381 +0, 32, 32, 1, 194360, 0837b122d85abc4d704d40629266c58d +0, 33, 33, 1, 195912, b7a4bbe436d63394cee70d40e8a8a4cf +0, 34, 34, 1, 195556, 1b9a3eb6cda9bbd44bbdd0dc26a74252 +0, 35, 35, 1, 195284, f28d780d43fa6979379dd21fcb12e906 +0, 36, 36, 1, 194268, 5508989dad06fa05ee4054e759cdfd4b +0, 37, 37, 1, 194460, cb65a0e97c03b2fbe69caa6ac1660070 +0, 38, 38, 1, 192708, 4125ee86cf4b8ca6d891c176662e584f +0, 39, 39, 1, 193032, 096ee24b3e35049480e28171693fbd85 +0, 40, 40, 1, 193160, c01aef63b8bc792d08355ce6d68affee +0, 41, 41, 1, 193524, 57af47b7bfe132cf58eab2807996b3fe +0, 42, 42, 1, 194120, 9a4e2d72f4526815b253b3acce2dd49c +0, 43, 43, 1, 194232, e575508ffbd2a53871e817cd8947e2d2 +0, 44, 44, 1, 193744, 95d8eefbfbf5a7354ecbf35835243e44 +0, 45, 45, 1, 191748, de2eedebb28491e59700300635af1f90 +0, 46, 46, 1, 191128, 652670f6881419be5068f2de6ac2d91e +0, 47, 47, 1, 191704, 070f46dc278230528aa6b40256a6d891 +0, 48, 48, 1, 191584, e4b76fcf344e125729c339e360a14b15 +0, 49, 49, 1, 191444, 6a33b374a8b48549094a24543d81d999 diff --git a/tests/ref/fate/utvideoenc_rgba_median b/tests/ref/fate/utvideoenc_rgba_median index 88adb0cd2..1588b6d28 100644 --- a/tests/ref/fate/utvideoenc_rgba_median +++ b/tests/ref/fate/utvideoenc_rgba_median @@ -3,53 +3,53 @@ #hash: MD5 #tb 0: 1/25 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 195096, 29ad3287ab4d7f4d46968c6d38ba049b -0, 1, 1, 1, 195040, 2c7b4f5f0aee96dca6dc30ce01b3c74d -0, 2, 2, 1, 196044, 7ffc6ab3c4a2eee436ef6a59c72ffb04 -0, 3, 3, 1, 195256, f4453470d77c246cbb30d00c13512359 -0, 4, 4, 1, 194856, b84c4d56bf28033db539e4e0cad3d342 -0, 5, 5, 1, 195360, d2d3371b96f679f9b7c62d98b5d54af9 -0, 6, 6, 1, 195184, 8e3782bc12b24023a5899eb4806ffed6 -0, 7, 7, 1, 194812, 4fcf24a0660606304c58c93db2baf7de -0, 8, 8, 1, 195040, 6ab57a9dcb4c99df7848a0971335a6b4 -0, 9, 9, 1, 195476, 66a3d66c3dc2f5b0847266a21927fa77 -0, 10, 10, 1, 195056, 530b251a8497af21bc56cd73af5c7ddf -0, 11, 11, 1, 195072, 2904d24eca3db9734ed78dc8d557a334 -0, 12, 12, 1, 194232, 97566b596b113bf94a12ee1c02058a95 -0, 13, 13, 1, 195072, dceefd5df6efc5fefc8cfa1543b1a20e -0, 14, 14, 1, 195348, d5b75f298fa6d474435333467b3497ae -0, 15, 15, 1, 195668, 519f63be313f311cbb3fb48970a19f15 -0, 16, 16, 1, 194880, ab2da22767f540f8adea7e43dd6c1d0c -0, 17, 17, 1, 195168, 667b85c19dd2d8ae105594f1294297b9 -0, 18, 18, 1, 194448, 575bc4b46f6158e76e503e8028902aaa -0, 19, 19, 1, 194360, 851acbaf04c464689c8e2c4af3b9ed14 -0, 20, 20, 1, 193700, 1a477e0d665dcd088da6edeef77f21b1 -0, 21, 21, 1, 194008, b0d752c2201235e51ba0bbb59046fa60 -0, 22, 22, 1, 194096, 099df2b23c41ee54a6bd11aa6c92c390 -0, 23, 23, 1, 195092, e4d4dc89b8afba245355cec57ddcae40 -0, 24, 24, 1, 195196, 070c27e0499cf0210d729242ebc1a24e -0, 25, 25, 1, 194912, 0fb78b7892035ecbec6ee9be6a13831c -0, 26, 26, 1, 194768, 3ff6a05e68d6e33eeea22232e71bdf9a -0, 27, 27, 1, 194360, 3828288e90a780d0c338ba5ab046aaa5 -0, 28, 28, 1, 193568, 60afb0ae9e6cbc9d8e4081764de7b4e6 -0, 29, 29, 1, 193560, 6b22fcfce4bff96b2afcb891f4fa9cf3 -0, 30, 30, 1, 193960, cae9eddb4464627fdc4413c3b5159575 -0, 31, 31, 1, 194780, 9e3d730fb835d3acaf92b7be368ea89e -0, 32, 32, 1, 194648, 1ac7f5ae1b392ee8630266317a1818df -0, 33, 33, 1, 194944, 374142509500017bbc29e157569bca2f -0, 34, 34, 1, 194736, 0072a43b8de988683340c81e5bd4dba6 -0, 35, 35, 1, 194776, d5add7706f49a6a2f8d6bf3ed0ce3410 -0, 36, 36, 1, 194784, 7a1d38bc73fd293afef5fbcf9d34decd -0, 37, 37, 1, 194912, 695e2d4c5d613245d591ae58100323bd -0, 38, 38, 1, 194152, d4c9adb4f6340bc5f10b5b13f71d07bd -0, 39, 39, 1, 194172, 0c7419c5c550e784e01a8c9927ecf59a -0, 40, 40, 1, 193608, 4abff529172476d76c2956179041b2e4 -0, 41, 41, 1, 194260, dfa07971b01032b6a653d0d6715ffa8c -0, 42, 42, 1, 193916, 6ffe1e68c74d51ea0cba0ede10b0f6f0 -0, 43, 43, 1, 194140, 46e18d23810193dd352fcc49b7c5ef6e -0, 44, 44, 1, 193656, 4339d3e8b9dbeb376a1e19c4b86824f3 -0, 45, 45, 1, 192964, ff4680c71688f9944cd494105d2ab0b5 -0, 46, 46, 1, 192640, 62ce4b6d3311c34c73c6af1399fedfdc -0, 47, 47, 1, 192584, f71b06a232a1a62a45ddac80c6f75090 -0, 48, 48, 1, 192360, 6642b9838eb32ed81d4d10a46ab9f954 -0, 49, 49, 1, 191916, d3ed1686383cfa7130ecc17c1ab52432 +0, 0, 0, 1, 195092, d32d5a3dc88b9aef0826b565ee5dfbc6 +0, 1, 1, 1, 195036, ea13e3522d1f3aeddd47117c91eccc55 +0, 2, 2, 1, 196040, 21c2c9abe791bed2a9bf02e539caa787 +0, 3, 3, 1, 195252, 58d5e081127f246f711f5b8ee1c760ff +0, 4, 4, 1, 194852, 8ceb3824ec628a73e1c08e498f369484 +0, 5, 5, 1, 195356, 30ea64094f29d670e2ff8f43b50578d6 +0, 6, 6, 1, 195180, 08b406b9f3063a54681d7195fb53e953 +0, 7, 7, 1, 194808, e28c43ef3aef174f0f9b9d7a702ca747 +0, 8, 8, 1, 195036, 66247b40b0def9373bf6fdda9ef832f7 +0, 9, 9, 1, 195472, efa8a624d6b0fa69e0c1c746baed0b33 +0, 10, 10, 1, 195052, fdfc784aed661cb76bc5b3ef1863bd89 +0, 11, 11, 1, 195068, 040ad503d18a36d4f1cdaec64998138a +0, 12, 12, 1, 194228, 1cd168427d022825a801b232cb23ca12 +0, 13, 13, 1, 195068, e4082f833d3bf75af24e1bb5f06d94fe +0, 14, 14, 1, 195344, 19638340e93d4f1f7099deda34d28e3f +0, 15, 15, 1, 195664, 001a801c5c5ceb197576c0f7b793850d +0, 16, 16, 1, 194876, 9550b3cf6133997bf7557483f346b036 +0, 17, 17, 1, 195164, eb7220caf48ab2605ec971ca1297a7ae +0, 18, 18, 1, 194444, a2ac812e6307a92ecd09d4282367a9d4 +0, 19, 19, 1, 194356, ee4d250226ab2a34cef0e3ed8920f7b2 +0, 20, 20, 1, 193696, 4bff0fc871969d17ad1f7391bbd543b2 +0, 21, 21, 1, 194004, 080e2a91fe768fd1725a8400bc6a1331 +0, 22, 22, 1, 194092, 5b9d65275695372e1f6b9c0a23f1ffa0 +0, 23, 23, 1, 195088, a4060bf595c877476a5952b335526d57 +0, 24, 24, 1, 195192, 17b55735834f291ecae399c317007d2c +0, 25, 25, 1, 194908, fc78d797bd5740f4fec8f3d34bc2ff1b +0, 26, 26, 1, 194764, d229a9e4d1c782504cad617d2b00802b +0, 27, 27, 1, 194356, f987a587cb9fdcd04e36d9382c4d9139 +0, 28, 28, 1, 193564, bdfa512e3a0a46aabf289c22dbaee0b9 +0, 29, 29, 1, 193556, 341708f3181ba4b37114d6dbffc65e63 +0, 30, 30, 1, 193956, f97693469ae6f49c3995794d00430c4a +0, 31, 31, 1, 194776, 970c96fe0f733683ce4f2b478af21b88 +0, 32, 32, 1, 194644, 8a96248e2821040e4d0d6d32d0a4f1a9 +0, 33, 33, 1, 194940, 70a462d8de0da8b5718bf8fb8034fa38 +0, 34, 34, 1, 194732, 2fb3437abbc0a85b6c46e1b1edd922c9 +0, 35, 35, 1, 194772, 0a0f54e266438e1a840247e1af2fb1f1 +0, 36, 36, 1, 194780, c4d516a459523b1c150d8aad1d5e3a6d +0, 37, 37, 1, 194908, e09db67196513400dd55397a525b73c2 +0, 38, 38, 1, 194148, f3cc9fc8597f8806fbc2a0c13af5b9ba +0, 39, 39, 1, 194168, 2bb82f80c239984fe7c1091ab6afb332 +0, 40, 40, 1, 193604, 6fd128240c540a0655e8f27ff6a50ee9 +0, 41, 41, 1, 194256, 9b49275154b4538abdebbddffe010105 +0, 42, 42, 1, 193912, 6acff798f9cca91347e36ee1ea86183c +0, 43, 43, 1, 194136, f24ca78d9b813ab8bfc720bad2682e7b +0, 44, 44, 1, 193652, d7d927faf59a3b82bd1cce418c13c430 +0, 45, 45, 1, 192960, 8a813fce1d21dd4ad474d06d890a3de5 +0, 46, 46, 1, 192636, 6bbe157ec4f799cfd47a69c5a5cbb0fc +0, 47, 47, 1, 192580, 1c17bf08a3928533a0036bda1fb08ecb +0, 48, 48, 1, 192356, a5b34ac48c82e79ff827f72dddbfc6b0 +0, 49, 49, 1, 191912, afceb467ddffd9697c9566c43f2576f9 diff --git a/tests/ref/fate/utvideoenc_rgba_none b/tests/ref/fate/utvideoenc_rgba_none index 322127797..b8e0b4109 100644 --- a/tests/ref/fate/utvideoenc_rgba_none +++ b/tests/ref/fate/utvideoenc_rgba_none @@ -3,53 +3,53 @@ #hash: MD5 #tb 0: 1/25 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 301312, 6912d70f7c20db0b5079a99443ffe65c -0, 1, 1, 1, 301328, 53f1b7d3c2f87ecfe9c9d305771421c5 -0, 2, 2, 1, 301100, 7040f2b50dc10b2565fa899ba007983d -0, 3, 3, 1, 301164, 2bfe87a43842b21b083c166a5fcae979 -0, 4, 4, 1, 301172, e6535559b9cafb81d0f5312e6982228f -0, 5, 5, 1, 301196, 899d3b7f4daca28b8d08fd80b9732332 -0, 6, 6, 1, 301204, 9ba8d921eb9345b9b90e5ec690cedbc6 -0, 7, 7, 1, 301304, 89d5758e5a4966d28fa3e6811822c9e6 -0, 8, 8, 1, 301336, b3f805d45e2cba1f3273fdc30e3d3d9c -0, 9, 9, 1, 301304, 83c9ce5fdf5b20b29fc787ae20c5aa8f -0, 10, 10, 1, 301204, 2cb730d551309ac307b69fb1e0f0bcbb -0, 11, 11, 1, 301172, dc5d09bbd04e7b0a20521e67dbbad5f2 -0, 12, 12, 1, 301304, 9e08281b8be73b732b2793f7ffcf3bd4 -0, 13, 13, 1, 301224, 430fa7e9cc87e9292811601473bb03f9 -0, 14, 14, 1, 301128, 32eab97914c2f165e270e42e3c348ea0 -0, 15, 15, 1, 301140, c38233a19e22cc41957cd5a2e13bbca0 -0, 16, 16, 1, 301280, b87e1697217b744404d7998ec3dfac80 -0, 17, 17, 1, 301332, 231912bca1a1d4b54bc7ad392ca437c5 -0, 18, 18, 1, 301452, 30ce746afa3750735872fc9f2680e5b0 -0, 19, 19, 1, 301484, 9a56d219bcfb153190d17c8d89a0c5e3 -0, 20, 20, 1, 301440, c864010df06930259e712f7029a428b4 -0, 21, 21, 1, 301440, 1a4b6bf6557c65d5f088829602440819 -0, 22, 22, 1, 301376, f0ce8402bf00fcde4399da2f4088cd9f -0, 23, 23, 1, 301320, 27d296bfd2df72c2fcf790098d2129cd -0, 24, 24, 1, 301388, 0e78fec341c4d137959491e53ab23d92 -0, 25, 25, 1, 301404, 1ec3ca66bd6005cb754c00e346cdd895 -0, 26, 26, 1, 301348, b78ad47e42cfa510ab92d3ffc99371cf -0, 27, 27, 1, 301492, 558f35abf593bf29a82e6353c75052d2 -0, 28, 28, 1, 301412, f44dae5d90ac9907b8847db0966e8d0b -0, 29, 29, 1, 301484, 40d87d4e7c51bc2b3dede754c25e1b7e -0, 30, 30, 1, 301484, 15dda8edd88e97f3db294bce9397e681 -0, 31, 31, 1, 301420, ff1dd12c16b295c83098a6b0135bd951 -0, 32, 32, 1, 301380, a290b1944381632a50fbb680f3f1af9e -0, 33, 33, 1, 301356, 73d66b8546ac0698975af841dcea7a4c -0, 34, 34, 1, 301260, 408ab0a50a74e7aaf196a202fd781892 -0, 35, 35, 1, 301412, bde264649818ed761d74281bf92a871e -0, 36, 36, 1, 301492, c3612f4a8a748ffd6b43ccf24b2db821 -0, 37, 37, 1, 301488, 068ec12d90d1236e367caaf87f14da03 -0, 38, 38, 1, 301556, 000ee987cce47ab701e743d21a6607e6 -0, 39, 39, 1, 301556, 41277aa578fe7367c138a70b532bdf59 -0, 40, 40, 1, 301568, ebf086337aedfac24afc5c17715424d2 -0, 41, 41, 1, 301528, d8f0c31897748dfc761033f237f31f7f -0, 42, 42, 1, 301604, 50b67f1d579eb8e7c5e0bdc438bf0ee2 -0, 43, 43, 1, 301568, 8297516127bb32a4326d6a859b2d8407 -0, 44, 44, 1, 301552, 1f9e1272e7249467631c4b9bd88bddcf -0, 45, 45, 1, 301604, d835d90e9fc37583978c053bab5a96ed -0, 46, 46, 1, 301692, fcb67990a58d25bff135fcc970714c4a -0, 47, 47, 1, 301700, a4b0a26ed1626a4e46effa7987a32034 -0, 48, 48, 1, 301720, 44d53eab1be166c9bcc4b7b8bc3f80c9 -0, 49, 49, 1, 301704, 34314d5b44ea555b7d52958dec489fde +0, 0, 0, 1, 301284, 55e84c6e1f41e48f47dcefb63e3c1efd +0, 1, 1, 1, 301296, 12dab23dfd2c2d5b48bed2292b876688 +0, 2, 2, 1, 301072, cc2e2889403dcc5d8e36868f07918b9d +0, 3, 3, 1, 301136, 9813d60e613a3a14e639f9af0a5b1fe7 +0, 4, 4, 1, 301140, 58554bb6749e8bbd9476335ac1cb0076 +0, 5, 5, 1, 301164, 37a249286019761a4a3e498e977f9da1 +0, 6, 6, 1, 301168, f3aa11b419ec6f683ad906e7f7a36342 +0, 7, 7, 1, 301272, f489654640f0e42225815ea9c9681201 +0, 8, 8, 1, 301308, f10eb3c1d0324b59bd25c8bc6556aca0 +0, 9, 9, 1, 301268, 2163aa992afef5210d677953d81adb17 +0, 10, 10, 1, 301168, 684d19d14212615ebffa1748a9c552ed +0, 11, 11, 1, 301136, a5c47c30d12dbc679ce932a5988b32e5 +0, 12, 12, 1, 301272, 3a51dc37d7e5ecb4a8db948eade2e0fa +0, 13, 13, 1, 301188, f9f9ed41c233e791e6cd75a34e52edf8 +0, 14, 14, 1, 301096, 63bbfbee6f0fa6745e143dfae40ce7ff +0, 15, 15, 1, 301108, 1fb3340dd1804d27fb40aea6b073e9ce +0, 16, 16, 1, 301248, 476d27f29da8e74db696ff38e81743fc +0, 17, 17, 1, 301300, 84a7f5804a856b7ef640838320634568 +0, 18, 18, 1, 301424, f34006fb55745aac29e265e0362434bf +0, 19, 19, 1, 301456, d9207e54e261d184ddd02f3706e63103 +0, 20, 20, 1, 301408, 89b5a6804bad85025a6a3d23dc539426 +0, 21, 21, 1, 301404, 5987d22d6e3bf18cd2ebea98a1915f57 +0, 22, 22, 1, 301340, 43ff13bb237a7899ecb04fa7d27e94ab +0, 23, 23, 1, 301288, 01b3e148ed6b8a0d05ee628fb21fa4a5 +0, 24, 24, 1, 301360, aa7704007e3c437cfcad4fb83a69594a +0, 25, 25, 1, 301376, 4dea983f0b4a012ba6875aa857d02e91 +0, 26, 26, 1, 301312, e263f1cb0fb19b50751e9a214a4c9d81 +0, 27, 27, 1, 301460, 85ad441664c99c591d6dc427910faa19 +0, 28, 28, 1, 301380, 86ffe8273011763d800dbf6c89942a70 +0, 29, 29, 1, 301448, 500862ea62e1982325d653d4853dcbcd +0, 30, 30, 1, 301452, 91c4390a805e02d1924bd75946bc0b63 +0, 31, 31, 1, 301388, 4eb3040d65948355c4506ee8e8e041ca +0, 32, 32, 1, 301348, ece814a764470f1d80973743a7adaa4b +0, 33, 33, 1, 301324, 2ae0b9af5380c8f98087b90c646af813 +0, 34, 34, 1, 301224, d6a3ba0b543534bd7de9dd82107c468c +0, 35, 35, 1, 301384, 4f4919c1b2502c6e03ddaa83f4c03f15 +0, 36, 36, 1, 301460, b45189bc89e6583f4426c390622fa1fc +0, 37, 37, 1, 301456, db0c5e2bc705c825e554c2da54314746 +0, 38, 38, 1, 301520, 8d01037b2dcbba39d4746758fd53323c +0, 39, 39, 1, 301524, 0a78af44bf49520ae8830060e6011898 +0, 40, 40, 1, 301532, da9032ac97b76ec10f94d74ee878cf41 +0, 41, 41, 1, 301496, 9a22b2a9a3ad897406fc7c3137d41a3b +0, 42, 42, 1, 301572, a14a80ab416cf4a9a1ec24bfc72602a1 +0, 43, 43, 1, 301532, 71ea5a240540a2e08ced8ad78c1a0676 +0, 44, 44, 1, 301516, fffe101d036ed5afee9b6f86267c2a0c +0, 45, 45, 1, 301568, 58ea3a6edaee760d98eadb072fb30796 +0, 46, 46, 1, 301660, 9886e77f5df35d8bd164d598d0f87514 +0, 47, 47, 1, 301668, 1f326eb789974fc853e1db57115ef58b +0, 48, 48, 1, 301684, 08b2eb620b9a7be1bded4744cd4c88db +0, 49, 49, 1, 301668, bfcce1ce5f7c30230aae9a2d67fc8a70 diff --git a/tests/ref/fate/utvideoenc_yuv420_left b/tests/ref/fate/utvideoenc_yuv420_left index 0ce4f9d5f..ae79effe5 100644 --- a/tests/ref/fate/utvideoenc_yuv420_left +++ b/tests/ref/fate/utvideoenc_yuv420_left @@ -3,53 +3,53 @@ #hash: MD5 #tb 0: 1/25 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 59796, a7136363bc4b9ac663178e5c7f24bae7 -0, 1, 1, 1, 60012, d296cf24776234599e22526598de838c -0, 2, 2, 1, 61040, e889f81df51b75acf8131de97f9da4e3 -0, 3, 3, 1, 59656, a63c343139b1117260cf6f790ba87968 -0, 4, 4, 1, 58592, e2170222ac38ddc0703f5b537b4beb79 -0, 5, 5, 1, 60248, 0ea350ecf7d8a440b06a60550b5dfa4c -0, 6, 6, 1, 60480, 792694fa65994c407fd76d06fdbbdc34 -0, 7, 7, 1, 59888, eaef81fd1fa459feb9a3b15817c861a4 -0, 8, 8, 1, 60080, 610a75f3c275ffef75006fb862642993 -0, 9, 9, 1, 60320, 1e1cc244d2ea6b259d06384d1a95cc89 -0, 10, 10, 1, 60300, ddbb7eb36b73cd4f1dc28ded5217952e -0, 11, 11, 1, 60288, 13f14eed47e1c4fec9f99b47316f82b6 -0, 12, 12, 1, 59172, c7c205489a3b389290f2c56e66bf8ddb -0, 13, 13, 1, 59664, 81eead1a1fe199e4b66e9bc2f04ac892 -0, 14, 14, 1, 61004, d02e17515451d4259d7179741d208b28 -0, 15, 15, 1, 61088, 4f1c9877caf59dc5ebf5646fe98b3ef5 -0, 16, 16, 1, 60072, 5c4c41d25e9aa0da07da89475275513b -0, 17, 17, 1, 59876, aeeb1f7a68a23f9fd0503831bfeb2ed1 -0, 18, 18, 1, 59396, 154d2a0717aeb78e47e20bbc9d4aa69a -0, 19, 19, 1, 59076, 3fdcb2330689aed91d92d515a9eb015a -0, 20, 20, 1, 58740, 71a054852adaf0da188550fd77ae2069 -0, 21, 21, 1, 58584, 403746356fd559e9bace9bb37557e58e -0, 22, 22, 1, 58952, 1a3d80d21e00ca5ce8c378da373c65d8 -0, 23, 23, 1, 59696, f66ace9c237d6ee91a4c23a957fde2a1 -0, 24, 24, 1, 60664, 69e6f45d9adf351650648b3fd6fc41b8 -0, 25, 25, 1, 59748, ed9e5524584eb0438f88e12af331009e -0, 26, 26, 1, 59088, 4325aa8c838b5793364c6ab6ed904d84 -0, 27, 27, 1, 58752, 46a17359055b7ac3285c845af9701c74 -0, 28, 28, 1, 56928, a1fb544e10ee9806c80b5b80d85ef813 -0, 29, 29, 1, 56960, e17a9082644d542b3d589346d3421c51 -0, 30, 30, 1, 58140, f5ae6688db909252b67c3fbe62d783ff -0, 31, 31, 1, 58980, 71a7053ff0857fa0651e2b8c5626598c -0, 32, 32, 1, 59548, 60b3d97b4f3893b791894968b7586e99 -0, 33, 33, 1, 61248, ceb9cccd0327ae4c52d8a2cf009d15f7 -0, 34, 34, 1, 60032, ea2ce622422c4efa41069707b231fd52 -0, 35, 35, 1, 59252, b891818e1aba1e29c23fecbf405b03c0 -0, 36, 36, 1, 58568, 0aec4492ddb9608bf217f8b828378680 -0, 37, 37, 1, 58744, 0f218bdc62102270393e7973caa251aa -0, 38, 38, 1, 58280, 89c93e37590d56c7c32f4955e59b7c54 -0, 39, 39, 1, 58236, 9575ac5076c1c347069b48aa8cb6381f -0, 40, 40, 1, 57308, e4ede1a1ab344b39399b231fec0cf420 -0, 41, 41, 1, 58964, 9f9c800eddf1fbb093c7ae1320f2ec19 -0, 42, 42, 1, 58800, 9729551ff14d80a3b647bb9688e38cd1 -0, 43, 43, 1, 58716, f0d81b0b287bbe1decd18eac2873166b -0, 44, 44, 1, 58136, e6aa11b60f8be9cd3d3e9d5c22b326ff -0, 45, 45, 1, 56772, c3dd97f5d29511103b80edfcf39d2fe3 -0, 46, 46, 1, 55904, ae67aee10ae3b04ac2dc19158bb9c69f -0, 47, 47, 1, 56344, f3c9c3dd5238c1f29f9204e1efeb6235 -0, 48, 48, 1, 56396, 93b8a198ac7c7118da0b581a50633df9 -0, 49, 49, 1, 55480, b2907ad8da8252dd6403b72eeb49b141 +0, 0, 0, 1, 59796, dedd9623ead257b98e079c6d0479e5a9 +0, 1, 1, 1, 60012, 73ae403590ffc5962ff86b8dcb44ca50 +0, 2, 2, 1, 61040, 0c6baa05c0b1e458fceefc7b833edd71 +0, 3, 3, 1, 59656, 4d8d13a50efc73f6e6962bb234cc9b89 +0, 4, 4, 1, 58592, f9fd7cc56b1874bbe1a554f6150826ed +0, 5, 5, 1, 60248, aa4d8d7f3f5eaead893adce9a7745e1c +0, 6, 6, 1, 60480, 1c972785fefeb3ef6c5899abc75605cc +0, 7, 7, 1, 59888, 6ab8c8eacedbd28b4341ae642f94cd83 +0, 8, 8, 1, 60080, 76f3eb46afdb2ebf83bf6aadc7277ddb +0, 9, 9, 1, 60320, 01932335ef686a759b591ea450a7a802 +0, 10, 10, 1, 60300, 7a1bc0880154dfae83d5c4832d2a0ef4 +0, 11, 11, 1, 60288, 532314d7b508eae13ccb54c021c555eb +0, 12, 12, 1, 59172, 3c307e8f17b27c489f91b609806eeea6 +0, 13, 13, 1, 59664, 070dd129e15219ac626e66279c6e7cdf +0, 14, 14, 1, 61004, e6d8023b1c501fabb43e19d1b27e332e +0, 15, 15, 1, 61088, beffd64b5410a5780481945057259830 +0, 16, 16, 1, 60072, df2ac66ec962c106d241a9e860bbf845 +0, 17, 17, 1, 59876, b4cd630af2b10995be0f46f6c2cb372c +0, 18, 18, 1, 59396, a07393cd44eab3b4c6b2985931d104d7 +0, 19, 19, 1, 59072, 763f7702088fe148009a13b34e8dc0ba +0, 20, 20, 1, 58740, 4b3c67d62bda1e1d41ae8b2a08ffc6ed +0, 21, 21, 1, 58584, 7e696d1e2709d4abbf3777cfb891557b +0, 22, 22, 1, 58952, 748cf0ce599b8f6b79e94fd38bd6f471 +0, 23, 23, 1, 59696, 369d7dd5403834a99af295ba7f7aec15 +0, 24, 24, 1, 60664, a95fc9270a66c79d1777ff6f970fe7cd +0, 25, 25, 1, 59748, a4ae4093c9778f8f817977c1fe210e47 +0, 26, 26, 1, 59088, 5afd7ec014f73740095d7b442bce839e +0, 27, 27, 1, 58752, 415bbfa919f86a4d5d39230749099db9 +0, 28, 28, 1, 56928, b6efa0547ff592c28c141f78e28fac1d +0, 29, 29, 1, 56960, 9d78613a7511878970cd829809f82a77 +0, 30, 30, 1, 58140, fc65008ad890d0ac6b4d31dd87fcb1ba +0, 31, 31, 1, 58980, 51ca202c4696073bbcc59885d6c91a2d +0, 32, 32, 1, 59548, 283da1b559f8a1080df5525266c64963 +0, 33, 33, 1, 61248, 2f8a9fe1e7cac20ed716d2408af5faf2 +0, 34, 34, 1, 60032, 16c1b04dfa06e5896deb412536f82868 +0, 35, 35, 1, 59252, b12c42d343355035e3a80f67eeac29ba +0, 36, 36, 1, 58568, 6958b7ddd22709356136a761bd1e947a +0, 37, 37, 1, 58744, 544f50bf7a513425e0bde91bbb0c1b9f +0, 38, 38, 1, 58280, af0f7e218dedcf8b3a61363cb8b66b80 +0, 39, 39, 1, 58236, 85954d2a24834cff1706f64e2937b84f +0, 40, 40, 1, 57308, 9454333132d25fa15363fed1eadb9c35 +0, 41, 41, 1, 58964, 534643a08971e5bc1ba11a268dcdb0d0 +0, 42, 42, 1, 58800, fd5bc8c4c63f54dc0a062bbb81f464a4 +0, 43, 43, 1, 58716, 5e7a23faa930e4f447100a6cfb38181c +0, 44, 44, 1, 58136, 5238fd231b1afdf11760e49341ff57cc +0, 45, 45, 1, 56772, e82b61e4e6cc3088a482372b2f7af61f +0, 46, 46, 1, 55904, 41e9834f48eafd70fe1d2361e9c84da0 +0, 47, 47, 1, 56344, 8c31cf8d3d938ec44a99de38cc4eaeea +0, 48, 48, 1, 56396, ebe832913656dbd08f41b90a30360f5b +0, 49, 49, 1, 55480, 65956930a7aacdaab5c65324fce90392 diff --git a/tests/ref/fate/utvideoenc_yuv420_median b/tests/ref/fate/utvideoenc_yuv420_median index a730f48fd..21e15b53b 100644 --- a/tests/ref/fate/utvideoenc_yuv420_median +++ b/tests/ref/fate/utvideoenc_yuv420_median @@ -3,53 +3,53 @@ #hash: MD5 #tb 0: 1/25 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 62876, c21650baa099fb2dfd35d4f8ddce16d1 -0, 1, 1, 1, 62832, 034a1996d13c15ee0bf482ddc398aac9 -0, 2, 2, 1, 64076, 1f39fd5fc926195b90a3374682a80eac -0, 3, 3, 1, 62724, 4007f9193b9e3b19e991497bb73679ab -0, 4, 4, 1, 61664, 3e86c3a2cd07807433ed7f46ede959ec -0, 5, 5, 1, 63296, 4e7d334f3713ecc07fca77c945c758b7 -0, 6, 6, 1, 63528, 15b8f92a1d84e77521c539a9a02379ac -0, 7, 7, 1, 62784, 07ead8344bde0c0a060c3313f39cf92e -0, 8, 8, 1, 63176, 0a8d9329d7f66008a0d41c6ba4749b09 -0, 9, 9, 1, 63492, eefa6ba63516dd2ff9fb0a4e81169977 -0, 10, 10, 1, 63328, 991fd8fcb392774d11b1766cc1dbe0d7 -0, 11, 11, 1, 63328, e2745a89e96a7f0c641fa25a6ed2da83 -0, 12, 12, 1, 62384, 2dd300b64a32ae2d6fb65e88128e5147 -0, 13, 13, 1, 62944, 076331793373fe43cd213ae56fc19e0f -0, 14, 14, 1, 63932, 37b6b50e7219ba0e593e4ce1de02a864 -0, 15, 15, 1, 64020, ed66d034f605621266054a54714feec9 -0, 16, 16, 1, 62940, fb6a921a8551db3d33b0a24e7e9a3ced -0, 17, 17, 1, 63052, abac96a9e0128efd4362ec28e66464d2 -0, 18, 18, 1, 62408, 0351d4c9579779dbb398f68f0e4e02e4 -0, 19, 19, 1, 62148, b4f7ed147a1326cf5adae50af6db56ca -0, 20, 20, 1, 61692, 48a9cdf3d4600768feca7616614dc46d -0, 21, 21, 1, 61704, d8e6c2daa6ae50caf7d5ee9324812389 -0, 22, 22, 1, 61964, 3983f0bf566d206cde013982722d4453 -0, 23, 23, 1, 62812, b12b44c4df634f608380e2bfb26b717d -0, 24, 24, 1, 63480, 30ad52da50e0d4f1fc811d24a01e777b -0, 25, 25, 1, 62708, 2827bd4dec0fa603eaf92bae8c4deb72 -0, 26, 26, 1, 62252, fd7c3a5bcaf83701dd7f2da225f3ce69 -0, 27, 27, 1, 61752, ea9740f3a5f52baaa923e245f649f7c7 -0, 28, 28, 1, 60248, cf4a142fc28437cca11ad1d127a2948f -0, 29, 29, 1, 60232, 6cd0b708ec41cd10357f8944ae8288bd -0, 30, 30, 1, 61240, c4a44f902a295f3a6e85276087adcbc0 -0, 31, 31, 1, 62228, a36d5eafa03b784f35303b131ac5d3a0 -0, 32, 32, 1, 62636, e09ca8f58690f991e1ce3986c2864924 -0, 33, 33, 1, 63840, 830de5062cb9c8be8844118c7db4bcef -0, 34, 34, 1, 62996, e008d4add85b595840a2773d01465147 -0, 35, 35, 1, 62480, 04a38e7c231697aa97e5a401d4329105 -0, 36, 36, 1, 61744, 4cb276703869f45a6ab798e53e615fc0 -0, 37, 37, 1, 62012, dfca9b52389b01d750a4b94d10a8e2e0 -0, 38, 38, 1, 61748, bf2ec90514c268440313fecf68e2f41f -0, 39, 39, 1, 61688, 99f1c565dc76bde773ccb91b8dbb3860 -0, 40, 40, 1, 60528, 7b66ad4e019964ead8ed1a9eadad9721 -0, 41, 41, 1, 62248, 795e2a8351ac78bc482e341be3af98bb -0, 42, 42, 1, 61832, d7fc01097c5ec0247d20727aec2adab6 -0, 43, 43, 1, 61688, 4492ffefcaed530fce3221f4bb61ef80 -0, 44, 44, 1, 61216, d9a91c3007686b7166f297bc1dddb9a9 -0, 45, 45, 1, 60192, 7c808c46b376c49fa3d5bd5ba97fce1c -0, 46, 46, 1, 59388, 6d2a2a72d14ff5c800295de6b2e23465 -0, 47, 47, 1, 59620, 5c1aa124bb6ffb9cd33a6430bf07ea9f -0, 48, 48, 1, 59584, efc1012cca50e509856e406622d760fe -0, 49, 49, 1, 58800, fa8563a0bc6022f8f5c5fc70ce0d46f3 +0, 0, 0, 1, 62876, 5e2a5276e10b86511fb8101733bc4795 +0, 1, 1, 1, 62832, fb1e0a7b2bdbcbada9892e3db7be7821 +0, 2, 2, 1, 64076, e0d2af56a9c80e3e8096cf246260f3ca +0, 3, 3, 1, 62724, bceca3c261206308030e2d7ad45e7599 +0, 4, 4, 1, 61664, ca8c005ba88cf1c97d49fe25f4830383 +0, 5, 5, 1, 63296, 7967f2592369b10bcd3ecac43413daeb +0, 6, 6, 1, 63528, 5374d62636243ba8f3fd1d7f31b632a8 +0, 7, 7, 1, 62784, 8c6b4791881433bfa65732ecb5b16866 +0, 8, 8, 1, 63176, 5b63d41ddcb0ab291a0d435d5f581ee8 +0, 9, 9, 1, 63492, e0b3ecdb25bda555ab9b9dfd98179653 +0, 10, 10, 1, 63328, 3dd8397b620d84ca3e7a78f9c8d350d3 +0, 11, 11, 1, 63328, 1af5a1dddff26660e0d7a32e24bd9276 +0, 12, 12, 1, 62384, 1ff3c26a6bac33d80b63c0f8595201ea +0, 13, 13, 1, 62944, 9c02a60be982847673da55180ef2c18d +0, 14, 14, 1, 63932, ad7a22cf139c6e4ab8c5e53d9db3e68e +0, 15, 15, 1, 64020, 53c8612a310d938be1080de4eebb18ba +0, 16, 16, 1, 62940, bb481e1e906a4fdfdafa1cc15ebcbb5c +0, 17, 17, 1, 63052, 0d97caa8514b4344c0ad8115e10b48c1 +0, 18, 18, 1, 62404, 0b05bb86b7bb1deaa3a1f0105adb823a +0, 19, 19, 1, 62148, e70896d0e240f44275ca7d34e4de1b90 +0, 20, 20, 1, 61692, 5811d0049807b3e30bb165c106f121f6 +0, 21, 21, 1, 61704, 7b0714038c38fbaba0f30077e1fff859 +0, 22, 22, 1, 61964, 01e0aa600de8039bcfa29f4855861f72 +0, 23, 23, 1, 62812, a9374a4f24248363aa1011d48f352bea +0, 24, 24, 1, 63480, 9837389866f467888b58d869c6c629c3 +0, 25, 25, 1, 62708, e463497b45db8c805fe8ef6903b1ce9c +0, 26, 26, 1, 62252, 4a386a10f454c4a16314ce824348ccfc +0, 27, 27, 1, 61752, ec17bfb853b0347ed5851adec930ac88 +0, 28, 28, 1, 60248, 2dce5d2345acaebe8d2ffe68248db51b +0, 29, 29, 1, 60232, 69e26cd6734e29179a152271d31ec4d9 +0, 30, 30, 1, 61240, 4eb9641a3a7f96a1db6291ec1208b243 +0, 31, 31, 1, 62228, 6ea9280e5c470a1843e2af7b086270b0 +0, 32, 32, 1, 62636, cab91136cea5c672b970dbc9e1491ea1 +0, 33, 33, 1, 63840, 25dd643075412e90e16fd6732a7cb218 +0, 34, 34, 1, 62996, 173c292ebe568e845835e63ae98064f7 +0, 35, 35, 1, 62476, 4bdc99c66bcd82238d84f478b2be6d6d +0, 36, 36, 1, 61744, fb3161857f91255e2fa3efff1fadfd4e +0, 37, 37, 1, 62012, a7f45644fba6f9d3088800a18a78fe93 +0, 38, 38, 1, 61748, 3c606f8fc6f7535651f1203a0d390a1d +0, 39, 39, 1, 61688, 636f94c06a5af282026aa82010362fd6 +0, 40, 40, 1, 60528, 157ff55e69660cb272c94ef1bf56f510 +0, 41, 41, 1, 62248, 1001e1aa4249cdc55bfc1f7daea931ad +0, 42, 42, 1, 61832, 9435239c2ebe6bfee404c002c1f1a683 +0, 43, 43, 1, 61688, 6bdc7de71e539f50ddc7961e7e56e822 +0, 44, 44, 1, 61216, adf9cb20324a6ea37840aa96cc57f67f +0, 45, 45, 1, 60192, 4d170c4d05a84440c9dbf60902902d70 +0, 46, 46, 1, 59388, f292adfcec971be4dd87e68da7edc662 +0, 47, 47, 1, 59620, ad02e16282fc53a395a3b61c077f56ca +0, 48, 48, 1, 59584, e9cad9e33a2d9508ab4feabfc9545738 +0, 49, 49, 1, 58800, 83eed6619d5fa154a30128761561ff90 diff --git a/tests/ref/fate/utvideoenc_yuv420_none b/tests/ref/fate/utvideoenc_yuv420_none index b960760a8..7f9b58d96 100644 --- a/tests/ref/fate/utvideoenc_yuv420_none +++ b/tests/ref/fate/utvideoenc_yuv420_none @@ -3,53 +3,53 @@ #hash: MD5 #tb 0: 1/25 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 144508, 83af3948090ebb44a0091815e4edc61e -0, 1, 1, 1, 144496, 950742e357ee489fcda4f783b8df3b4c -0, 2, 2, 1, 144376, 4b818cf0a50e9338fea26101073e445e -0, 3, 3, 1, 144420, 0335c3b97dca65e9118a12e3cceb1e24 -0, 4, 4, 1, 144588, a9f7e6cb2d9129d97342c4eb67349aa8 -0, 5, 5, 1, 144444, b956115c6bab18a01594103bcb2ba9e0 -0, 6, 6, 1, 144408, 81761b3135ab3f4d5efd6f2790b6b70f -0, 7, 7, 1, 144408, 566c53ee4126e31b78f6572292f97f55 -0, 8, 8, 1, 144320, 0c24c346a65cb945f8d804817f67f42e -0, 9, 9, 1, 144316, 7920264636a6933c776b41567181f2d9 -0, 10, 10, 1, 144248, c1c1b10356f27fca35e03fdc67dd1638 -0, 11, 11, 1, 144168, 5a590c4f603aaddd01d4efbf5571426e -0, 12, 12, 1, 144452, 10459aa8f48f7e8e0ebc03f15f795acd -0, 13, 13, 1, 144312, 436658612212e706c4ed9f4bdcf45f38 -0, 14, 14, 1, 144252, 7a5612c485c501669e27039c435ac5d3 -0, 15, 15, 1, 144232, 81018c3b49d376d69af71a4ee2c910a9 -0, 16, 16, 1, 144312, 4280abfc59ee6cfddbf45474a42c5cd5 -0, 17, 17, 1, 144348, 0a48ba8ad15f7431830feeb2ac0f2118 -0, 18, 18, 1, 144356, 6c8f0a396195a840a225aca3ada427ff -0, 19, 19, 1, 144360, 4a0a959d9c3ebb293d94ef37b4f7f19e -0, 20, 20, 1, 144380, e61b564126a2d8255a7457b70af74514 -0, 21, 21, 1, 144416, fe434ae640e63fb774d6e7c864d02e49 -0, 22, 22, 1, 144344, 9e106257c640b66ca31919668c4da334 -0, 23, 23, 1, 144376, c0cdd6b2aa1bf4d89c82b602f09fa2e0 -0, 24, 24, 1, 144376, 8be60289a2a4c22355b3bd43f2f85fe4 -0, 25, 25, 1, 144320, 124127b8fcacfa5c5e0ee7f0324da7a0 -0, 26, 26, 1, 144408, a5639aedbdbfff34f36dda8872992cde -0, 27, 27, 1, 144516, fbe3cf39fd764e6a3d05c63be35a4d58 -0, 28, 28, 1, 144676, 6ee82422712e11740d7b003eab69d5bd -0, 29, 29, 1, 144648, e5f446835709b1baaca14af3aa6fbbb7 -0, 30, 30, 1, 144496, 3b23fb07c528ad824e9c8f10143ae06a -0, 31, 31, 1, 144496, 4e4dddd0c72f9d3a555b8d32ae82c10e -0, 32, 32, 1, 144372, 1dfe88fbe0c1193bb04a06840dfab155 -0, 33, 33, 1, 144168, e03b3d67fcbbde71c6985955feebabfe -0, 34, 34, 1, 144180, 5d5a24b49cff98cbb85f69b547b43e87 -0, 35, 35, 1, 144348, bb9172de1a4c7a00fe80bb673484781b -0, 36, 36, 1, 144544, 7824a6c4bb8b919306904be6f67f2736 -0, 37, 37, 1, 144516, 456c3884817909b4cca38f8138c079d4 -0, 38, 38, 1, 144532, 0e63cf833a33a9fac9e5969342817fc2 -0, 39, 39, 1, 144452, 9c0155cdd0a5ae42b79475ab47ba87f7 -0, 40, 40, 1, 144532, eefee218d181e74a80a1d2ec27932e91 -0, 41, 41, 1, 144348, fbd4fd20565350dd927005af590912ff -0, 42, 42, 1, 144332, eac5c49230fb807c81e8a0c9e9721697 -0, 43, 43, 1, 144428, 9ee3fe8be6c4477b0d8ff1d91049634e -0, 44, 44, 1, 144480, b58fb19549e4497e82491a26d67c1567 -0, 45, 45, 1, 144596, 1c8059bf14f4df3da9db6b89f87a52b9 -0, 46, 46, 1, 144592, db8a5750beb049ea835895d23e924cab -0, 47, 47, 1, 144512, 58c69889edb9bdab219d698f6a44d2cf -0, 48, 48, 1, 144468, 3da8e5ae1f1ff9da72abd3d2ac87a7b9 -0, 49, 49, 1, 144500, 4f80ccdb6f9549190ed72407dd7af2c1 +0, 0, 0, 1, 144508, 808a5bf7f8647095ed629c18bcd78c8e +0, 1, 1, 1, 144496, 88d91b5aebecb8e3553dc5d25c11f663 +0, 2, 2, 1, 144376, 979d1dcc8eb2ead071545e4098453ab5 +0, 3, 3, 1, 144420, ce1cca3a2399408b1fd3dc28f2f908ff +0, 4, 4, 1, 144588, f028271d61bc3f7f29eb670b2dc2227d +0, 5, 5, 1, 144444, 4caecb43ab4f98af4bc2d8fc5737165e +0, 6, 6, 1, 144408, 78313642af9937e83d4206cf69423f88 +0, 7, 7, 1, 144408, 02afd3b87e1f4a88236c23613d0bb138 +0, 8, 8, 1, 144316, 677dc12dbff90c9f25bc5b1bcfae0220 +0, 9, 9, 1, 144316, 6dd8385746a3a982dfa7683f7b206d86 +0, 10, 10, 1, 144248, 0611dfc4b3ced7c52b5d014d114e3052 +0, 11, 11, 1, 144168, 7d6d56be15d67c0ef736909080bf6d20 +0, 12, 12, 1, 144452, 3a30b5305b301cd1cedffc44867659a7 +0, 13, 13, 1, 144312, b4f1329701c8284f8907e82e73dc225f +0, 14, 14, 1, 144252, ab4ee9e419d38dca74a22475ffed6b4f +0, 15, 15, 1, 144232, f486e7e950c8e45b881755fbee9ca967 +0, 16, 16, 1, 144312, aa8aa1826a1da8087567c13914fb1f79 +0, 17, 17, 1, 144348, 9c9ce3c86308dcda388645c0ab3b3f37 +0, 18, 18, 1, 144356, d33fd7c7f23e851a17fd0f0f768db726 +0, 19, 19, 1, 144360, a63e8e41686800d60566b19a9f2783fc +0, 20, 20, 1, 144376, c9b694f8df1cb44b42aa902392a18a87 +0, 21, 21, 1, 144416, 5624b1dc448e6e6bee47432df8c2703d +0, 22, 22, 1, 144340, 079128a1838e8fcb718cf4280560e40f +0, 23, 23, 1, 144376, bb67943fd9d91d6a8af9e4b2da2ef52b +0, 24, 24, 1, 144376, b91459d03569354faca2237ffbbdf0a5 +0, 25, 25, 1, 144320, 7a8863d8786eee1b82c7469d79d03156 +0, 26, 26, 1, 144408, 13873c8e8a66d12609864bc2a4127ddb +0, 27, 27, 1, 144516, 09f74425c309920aca58488e8bf9845f +0, 28, 28, 1, 144676, 12441f9a3d8215793b6b38c6e647d10d +0, 29, 29, 1, 144648, 6895219f14106bbc780c654fb9835abc +0, 30, 30, 1, 144488, 0738dc5c283869272bf28bd6a3107808 +0, 31, 31, 1, 144492, 375f99622b54462ef886e66f96998ef3 +0, 32, 32, 1, 144372, effb150140b4d84a3ab6a277992b9da3 +0, 33, 33, 1, 144168, 09677824ee8b6fff8391d6d8fef49459 +0, 34, 34, 1, 144180, ae4b4a60e2fe35f308201a3ace709f2e +0, 35, 35, 1, 144348, 3f8c8eacfbaee2560059c687a037af7a +0, 36, 36, 1, 144544, df5dc52fb501151cf8d0bd997f6b3e17 +0, 37, 37, 1, 144516, a9fdb6284f9b3b6d3cb59ad58897cd82 +0, 38, 38, 1, 144528, b4e82d29344b4ef0d34bf37e36f08cdf +0, 39, 39, 1, 144452, 88516ddef80594babbda3801710bf89b +0, 40, 40, 1, 144532, d9937a226562e3e02d6a6b134f04043a +0, 41, 41, 1, 144348, d8c09a3ce3ff01b1620205d54cf28d39 +0, 42, 42, 1, 144332, 5d79f1d677fe98e21b15821f8b3b5754 +0, 43, 43, 1, 144428, c9717bd43d9ddb4cee7946e725fd54e4 +0, 44, 44, 1, 144476, 18db82ef876bc80d777f801107c45c18 +0, 45, 45, 1, 144596, c62c01892d002dbb75a2020b9d0a1137 +0, 46, 46, 1, 144592, 9faf6283b8753002005c5a04ae345d5b +0, 47, 47, 1, 144512, 8c25deaf7a77b0991861a5c62b4fe5d1 +0, 48, 48, 1, 144468, dcaaa1058c59946691d087c9941ac956 +0, 49, 49, 1, 144500, b36206851f8613bf9cae5296d85eb1c1 diff --git a/tests/ref/fate/utvideoenc_yuv422_left b/tests/ref/fate/utvideoenc_yuv422_left index 069a22194..9da47a4b7 100644 --- a/tests/ref/fate/utvideoenc_yuv422_left +++ b/tests/ref/fate/utvideoenc_yuv422_left @@ -3,53 +3,53 @@ #hash: MD5 #tb 0: 1/25 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 91788, e14e576f1f9abd095f13ceca627adb59 -0, 1, 1, 1, 92140, 4b7db11c2d35fa91ff1b6f65c184e3fa -0, 2, 2, 1, 93268, 6ef5cb83a4db2afbf14467cbc4b6c4f7 -0, 3, 3, 1, 91612, f08ae129a2867a08770bdb61381bf366 -0, 4, 4, 1, 90456, ed3edabe09b9f6cfbf452a08dafa556d -0, 5, 5, 1, 92180, a0760e91b3af27a7c1bb0264f128ca50 -0, 6, 6, 1, 92200, 2fda4c87dfa34206173e852b67841406 -0, 7, 7, 1, 91872, 944e7c88c7ebeae9e1efac859ea4fe7d -0, 8, 8, 1, 91952, 34112ec99382b80c397d26cef93573c7 -0, 9, 9, 1, 92312, 63698686348ccd80cc920e9e73a195aa -0, 10, 10, 1, 92308, 6a675d6678b7b78fac6375d44f325d06 -0, 11, 11, 1, 92272, bc1401e0acd3864ad30711ca4b61578d -0, 12, 12, 1, 90920, cd7ecda23a4f312abe71bd3fc28af3e7 -0, 13, 13, 1, 91612, 91ebce52e2594296349476f3bf6a6408 -0, 14, 14, 1, 93112, 34be111d02130ed7389c0c62768041de -0, 15, 15, 1, 93140, e1b440cad63dbf8ff034f424cd1194cc -0, 16, 16, 1, 92080, 94181fde8563af0b6810f778f6b1d92b -0, 17, 17, 1, 91816, ed0997f9b341fc3ab6a8c5d9a4067bd2 -0, 18, 18, 1, 91204, d833b0c3b3dfe60b079b746c4c3aed7f -0, 19, 19, 1, 90880, 0d4702abb70d7cbc8843a96e3a74117a -0, 20, 20, 1, 90408, 409860b79fe10ffbffd581c19445fa91 -0, 21, 21, 1, 90280, 5360fa4f1afd8c2c55cf33675a928a14 -0, 22, 22, 1, 90808, fe2ca67d315fb1d8806ee04470d06378 -0, 23, 23, 1, 91584, 84168a6fe20ee00ddd9f54ce8f1e1810 -0, 24, 24, 1, 92684, 6fb3d7193d3bb5400c449717358827e0 -0, 25, 25, 1, 91580, acd2aa86dbae6e133183e5bf2ca389a3 -0, 26, 26, 1, 90928, cc0df9c8e00df5985e39ae486eb59eff -0, 27, 27, 1, 90536, 8f9d294190c03435f3cee266cca2a31a -0, 28, 28, 1, 88364, ae9564ad4eb3c1fc03e4befb4b1e719e -0, 29, 29, 1, 88404, 745a16947203cd7017900b137fca70eb -0, 30, 30, 1, 89844, 1b7e75be9edb25ffe91c54e270eb8f46 -0, 31, 31, 1, 90752, 9ff03fa3b28f2c84a4da41779e0a2aa4 -0, 32, 32, 1, 91320, 409ed4c3eced8793760505cf8095f51a -0, 33, 33, 1, 93204, 70865d89c930919474500befe0e2ec3f -0, 34, 34, 1, 92036, 7388d12a6954b9870749ab6a5f05815f -0, 35, 35, 1, 91144, b47bfdaec4c00177a9258a03e864400f -0, 36, 36, 1, 90368, 418df89a063f66cfbb1f806d68aca6a2 -0, 37, 37, 1, 90628, 3f90314ab7311ad0f4bd4808d62a1e80 -0, 38, 38, 1, 89836, 414f90d0efc65b993f6e1fc8f2c1d860 -0, 39, 39, 1, 89792, a07cf9fc580ffee5d61c241dce116ae6 -0, 40, 40, 1, 88896, 3d583229da6b7455b6876843b3b747c7 -0, 41, 41, 1, 90572, cbef36619e7c8e62fc21a735c7701514 -0, 42, 42, 1, 90544, 144816eaeaf0412fca6bf40e6f3e6d3f -0, 43, 43, 1, 90416, 76f0d9dd1f4fd00b68223dd7c6024b2e -0, 44, 44, 1, 89788, ce0b66e45ed3c50124680f84614c5ac0 -0, 45, 45, 1, 88120, 5d59770b187109e2e6824f5cb42b9b73 -0, 46, 46, 1, 87164, bb52ce20f4a21ef82a2cc3316ba69e1c -0, 47, 47, 1, 87632, 87f44c3ecebd09b2ffa94d8ace01f3f3 -0, 48, 48, 1, 87700, cbaed2ac667bdc9aa17ffc68ebaea790 -0, 49, 49, 1, 86624, 21797bc69a89976f9b4b552603a63267 +0, 0, 0, 1, 91788, 2b29ead6a04f08e49c25cd89fe0c0e46 +0, 1, 1, 1, 92140, 011a3c92a1a6659b26db7de3c74cda41 +0, 2, 2, 1, 93268, 69ffde2375949c0124e3f6b46a8bdf1f +0, 3, 3, 1, 91612, a34b1bbbc245a315906085aab9dca284 +0, 4, 4, 1, 90456, 7a1034d99c06d9163116e05dc88de0b8 +0, 5, 5, 1, 92180, cfe398abada0424f7ceab29426d27711 +0, 6, 6, 1, 92200, 1335b1706618dc85d64c3d47a2bf9eab +0, 7, 7, 1, 91872, c37958d720e011c337bf87543e635791 +0, 8, 8, 1, 91952, abdb95aa1c20d4724ec442d876b3ef82 +0, 9, 9, 1, 92312, b346e210e76f3ac350c9026d0421c1a6 +0, 10, 10, 1, 92308, 9b36f5e0085b3e4ef50e6a00aa8e9dd3 +0, 11, 11, 1, 92272, 4880487b34e836fa975fc0c857cae271 +0, 12, 12, 1, 90920, 924850fe3b48417160854234a60ee452 +0, 13, 13, 1, 91612, 34e4e1b6114bd2eef0ac26b4c3a0be5d +0, 14, 14, 1, 93112, 34e98cc2bc42b0cdd12f3b5a8a062a14 +0, 15, 15, 1, 93140, a6163289cc8450b55f82f13a8a372259 +0, 16, 16, 1, 92080, 143e999836a6ebc144c707dd77ce3d6b +0, 17, 17, 1, 91816, 0fcb2542dd7e281b098f2a4a76220286 +0, 18, 18, 1, 91204, fb9f7126d5c37bf48ae3cb7702fd27c5 +0, 19, 19, 1, 90880, d618dad8a7c6c03091a8d72f05ff06a8 +0, 20, 20, 1, 90408, e9de31ec047f7ea8aa2b781c1b8ac0cf +0, 21, 21, 1, 90280, 742f6b57e5014c85bf4ce63c3973ceb5 +0, 22, 22, 1, 90808, 0bde9c976e491dbca37762af1569f05f +0, 23, 23, 1, 91584, f69c98911e98cf1b35fee8c7a17784d6 +0, 24, 24, 1, 92684, 813535f3fddf27ed41475a4a16153407 +0, 25, 25, 1, 91580, 99e840b30697c491a42381278b74060f +0, 26, 26, 1, 90928, 1bb430db061f5ea70f97b0808f6fd0c6 +0, 27, 27, 1, 90532, 8669ea68164d3f9f6e234c24ed4ba6dd +0, 28, 28, 1, 88364, 65c5175d6c6bab9f205ae9b8d52931e8 +0, 29, 29, 1, 88404, cb375b083b2d415d11111b7d0b65d499 +0, 30, 30, 1, 89844, 6b29caf5d67711e4a68f9dc852c89607 +0, 31, 31, 1, 90752, d1d424a5f93970e1bca8e6cc558359bc +0, 32, 32, 1, 91320, 726a9a5fb90b88961f7392028c83cff3 +0, 33, 33, 1, 93204, 0ed7b1760d190df0c84f62f7ee3050c9 +0, 34, 34, 1, 92036, ff3ad470d5195aa00e364f180961b852 +0, 35, 35, 1, 91144, 8a7050fa18088c6dbbf148d7ae047a86 +0, 36, 36, 1, 90368, 0c0252b21de41b75141085a05cdfd462 +0, 37, 37, 1, 90628, 143d503a9e2ca9f5e95ba12e2237a88a +0, 38, 38, 1, 89836, 93fe7527a5681c819c6052b87bca8bb9 +0, 39, 39, 1, 89792, 6c353b6ef1cc14ebdbb2de24faabcfcb +0, 40, 40, 1, 88896, ed7e33a68674399293203e4fef8db0f6 +0, 41, 41, 1, 90572, d70967dd3d556559773980a776836423 +0, 42, 42, 1, 90544, ee7727dd0f3833728b3c557e9775f1ef +0, 43, 43, 1, 90416, 0e4b028286b5b1f7fb902821dd015951 +0, 44, 44, 1, 89788, a4e5d8715ae485f875b80ebcb150692e +0, 45, 45, 1, 88120, 9dce5bc1420f0e67abed693f75023d43 +0, 46, 46, 1, 87164, 89374077f87c8d3639743e17f8583307 +0, 47, 47, 1, 87632, 6ebcb11b9c0263aa82ca4797acd078ff +0, 48, 48, 1, 87696, 9941fc859d6b9e4c057c2a4b40faff98 +0, 49, 49, 1, 86624, a2a157ab69d82eda4f8ab502de62ca55 diff --git a/tests/ref/fate/utvideoenc_yuv422_median b/tests/ref/fate/utvideoenc_yuv422_median index cb9ca4482..8241aae26 100644 --- a/tests/ref/fate/utvideoenc_yuv422_median +++ b/tests/ref/fate/utvideoenc_yuv422_median @@ -3,53 +3,53 @@ #hash: MD5 #tb 0: 1/25 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 89732, 698174b0d0d68e98774363ca7926f6e1 -0, 1, 1, 1, 89652, f0789b7c32ef44207dfc5a454bb5ccee -0, 2, 2, 1, 90868, 6df1dcb1957efca736e88adfbad8557b -0, 3, 3, 1, 89520, 9cee942e7f03a97cd2cdf8cea429fb31 -0, 4, 4, 1, 88508, 798f4e8c00f4d949882cdc3f89be0bf6 -0, 5, 5, 1, 90140, 70fc5f4f240b0ca30332b0f37632d1cb -0, 6, 6, 1, 90176, 1c2747fc56d5eb70ff8f4f361cb70610 -0, 7, 7, 1, 89392, bd8764124753f784d5984cd829c8ca90 -0, 8, 8, 1, 89848, 1dc30ed23a8634f6b2661ac8583fe8cc -0, 9, 9, 1, 90356, 0910ae7c3a6924031453f458009354fa -0, 10, 10, 1, 89984, 61da06bf1ed667b54ee749c69ab031eb -0, 11, 11, 1, 90012, 11d05491f86014f19b34cab3111a95d2 -0, 12, 12, 1, 89072, 4598f16727472daa1710c39b4840efdc -0, 13, 13, 1, 89776, ed6c0da32acf621e9f79b76a3afaa280 -0, 14, 14, 1, 90680, 05f3a9232bc14ca8721ef04243177a20 -0, 15, 15, 1, 90852, e4deff113ea503656efecb227f6b702a -0, 16, 16, 1, 89844, 5ee70abd6f1d2e5c55117b28840327e6 -0, 17, 17, 1, 89852, 6721997ae0563009adbdeed31f437ce4 -0, 18, 18, 1, 89144, 8a40f0af74afb4ff05e6242a41c7789f -0, 19, 19, 1, 88880, 8824c3526629a30fbf9a53abc448844c -0, 20, 20, 1, 88344, 18a656127a16bb50113bb2e98b11a26d -0, 21, 21, 1, 88464, 19a3b9510e6347a7782f695b48736991 -0, 22, 22, 1, 88588, e3d22d15b4812c26214db546ce17c7dd -0, 23, 23, 1, 89720, afe800faa0188dff0899cd83af6301d6 -0, 24, 24, 1, 90216, a9d9ece70c978c595e1d724a0f644f56 -0, 25, 25, 1, 89456, 9bf3e8f87f072d55095acc9351a09f45 -0, 26, 26, 1, 88992, 40d1b1858f1ba0bebd9eb9f5263cda9d -0, 27, 27, 1, 88632, 1df39644ac99bccab4c6bd72498284c4 -0, 28, 28, 1, 87048, 9983cd95307c1bab653170ba2aecdc55 -0, 29, 29, 1, 87120, 006b48403af94a0bc5121900b48af9c1 -0, 30, 30, 1, 88044, 652d17c8805de56cd83824d99888822e -0, 31, 31, 1, 89016, 652a971973d088b5098a06b216137151 -0, 32, 32, 1, 89324, 2775a087358ead0281ce188f4006050d -0, 33, 33, 1, 90328, 564e119bdf5f3c780c0613990ca487db -0, 34, 34, 1, 89684, 1f5fb4ec22234aee771791b71881b630 -0, 35, 35, 1, 89216, dde7a003cfe5b47f9be407f28dcdfb3f -0, 36, 36, 1, 88644, 1fed2d2f72ec9488181a06606aaf4e12 -0, 37, 37, 1, 89000, 8f916bee0ad8efe8d3572e4af4bf4b8e -0, 38, 38, 1, 88628, d802fb5634d3acd72a96bd99c22dd566 -0, 39, 39, 1, 88448, a4d438df349f1f2ff1620fb965d08513 -0, 40, 40, 1, 87332, 18a8527dcfc5c1fa8ae7aa8a83781d2d -0, 41, 41, 1, 88856, 63179f19a5d60d3ea9fa14c00ca5c493 -0, 42, 42, 1, 88556, 92b568c24ed53e823b54fa6c064d16ac -0, 43, 43, 1, 88380, c204b982e3ab7fc1aa6b1b132c4ae462 -0, 44, 44, 1, 87888, 45f1cd55d454a0b611b047b6e5172b30 -0, 45, 45, 1, 86876, c668ac58b31feb51902b78fdfcdc1064 -0, 46, 46, 1, 86272, 24a94950de7065cb236e52502c9c8e67 -0, 47, 47, 1, 86388, 51dad738cd8896616694a4fb52b47fbd -0, 48, 48, 1, 86188, dc6709cd2722eb8dd927f405c6a30915 -0, 49, 49, 1, 85244, 68f40045a250ab0799a7325aa16ec80c +0, 0, 0, 1, 89732, c8dbbbed6c59cff00c7cead39cadd7d4 +0, 1, 1, 1, 89652, f1c995c2bcb13f9de97fd8c5da2637a1 +0, 2, 2, 1, 90868, e126298a564eec5e60518fca891bfd43 +0, 3, 3, 1, 89520, 8694da46ab5672f890d57c741d69d830 +0, 4, 4, 1, 88508, 0e0ae55ba0bcdf6618b7cffae7242d71 +0, 5, 5, 1, 90140, ef59eccdbf3b699a2eb857c6da044fa7 +0, 6, 6, 1, 90176, 95509ddb5a5169900714eaa2aac59703 +0, 7, 7, 1, 89392, 25782fbbf8552e7682cded46b418096b +0, 8, 8, 1, 89848, 46cbfe84ab2c46f045d23fd798dc64b2 +0, 9, 9, 1, 90356, 41cdc2e6dec30172ecccf1aca7b7ab0e +0, 10, 10, 1, 89984, 469be246c63ba4743d9c5ea91c4b849a +0, 11, 11, 1, 90012, 100bc595e92ca6d73525b2e20eaa7d25 +0, 12, 12, 1, 89072, a355e131c150b82d3620fe54ab53b423 +0, 13, 13, 1, 89776, 67e7c8a187157c1827a2e529865ab941 +0, 14, 14, 1, 90676, 7fa956927033cab7c0ae9a0a86d57b59 +0, 15, 15, 1, 90852, d507b175068e9d6c729530b436824436 +0, 16, 16, 1, 89844, ae6b71fe15285387229734fdaaad86d0 +0, 17, 17, 1, 89852, 6ced7f1bc56299e5c7b5169a1e62f4e6 +0, 18, 18, 1, 89144, 09a950b254eb5e7ac061e30a14ef98e8 +0, 19, 19, 1, 88880, acf28ad860b52fb502d22c063689a9d8 +0, 20, 20, 1, 88344, 682436aa7aeffa2cd5daa6adf037eb88 +0, 21, 21, 1, 88464, bbbefa2630e4e5165c9db638ceb730b8 +0, 22, 22, 1, 88588, 71d0e9178794e0ebf414bdd1c532d4fd +0, 23, 23, 1, 89720, f39171093709c90dae1ecc56e1a0d52b +0, 24, 24, 1, 90216, d8a7e85456ed58b86f42120269a62a46 +0, 25, 25, 1, 89456, e6d8b4f4b7c1903d66caea47cde9188a +0, 26, 26, 1, 88992, 226f69483ab481fd48fa2121fa925fc9 +0, 27, 27, 1, 88632, 2ef0ae5d9b35440a540dce11098be40b +0, 28, 28, 1, 87048, 5ed9c2db56db5ab3b5695ff282fbbd00 +0, 29, 29, 1, 87120, afe541aa18fd0fbeb7d623c2e03f7313 +0, 30, 30, 1, 88044, 4783145cbcbac507631d89b4c1b9f657 +0, 31, 31, 1, 89016, b8d2e919eecced0e4e13bab212fe5eaa +0, 32, 32, 1, 89324, 1be1c9ee208834cb150e7dc114b3c3f5 +0, 33, 33, 1, 90328, 9ecb6f9511b869becfc3ae1cac0532c4 +0, 34, 34, 1, 89684, dc56a959ece1d3ea923be523ae4b5f03 +0, 35, 35, 1, 89216, bb1b89d23284a73faaae092e02c35318 +0, 36, 36, 1, 88644, 5a01fba266207f286dd000502144374c +0, 37, 37, 1, 89000, e30493ff019668eaccae12c420a250ea +0, 38, 38, 1, 88628, 0217f6f365739f8c7f1738d369afb2e5 +0, 39, 39, 1, 88448, 9d064836b1b232620da1d470fa314d56 +0, 40, 40, 1, 87332, 9179648b65b4757cd23d732ef96e8685 +0, 41, 41, 1, 88856, 96e0779b5fb5708a73519cc5f8a685b3 +0, 42, 42, 1, 88556, 5586e5b8149eefe271d7d2c4688a57e0 +0, 43, 43, 1, 88380, c8a1962e2c4fc33b303e3e09c87ee1fb +0, 44, 44, 1, 87888, 70f38ebefceec78ec00fc2d190efc633 +0, 45, 45, 1, 86876, f8e0beb98988c19930c2cdd90ecfe867 +0, 46, 46, 1, 86272, fcb7343e281b2d42c81f9b5c4c1e786e +0, 47, 47, 1, 86388, cfa6fce827ac3604ea2124d7332e2226 +0, 48, 48, 1, 86188, 5455b984533d774b8e7f04eea4e4eeaa +0, 49, 49, 1, 85244, 9e4691d5a8be8270d48ef15292aaf0f7 diff --git a/tests/ref/fate/utvideoenc_yuv422_none b/tests/ref/fate/utvideoenc_yuv422_none index d15235cfb..bb97e219a 100644 --- a/tests/ref/fate/utvideoenc_yuv422_none +++ b/tests/ref/fate/utvideoenc_yuv422_none @@ -3,53 +3,53 @@ #hash: MD5 #tb 0: 1/25 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 191800, 0e1d199f87997ba47e98596b6087d7d4 -0, 1, 1, 1, 191820, b35714d0635214095ac06d35da00ed32 -0, 2, 2, 1, 191668, 8336829e44f5b90034e5da33dcd27f1f -0, 3, 3, 1, 191696, ebff701893f27b026fe6fec4a1cbd90b -0, 4, 4, 1, 191976, c2729ecde4337a51192da71b0ef36e7d -0, 5, 5, 1, 191760, e2ef2db5ef30019d5fd24cd32c696318 -0, 6, 6, 1, 191708, 638eb1c1b68bc9f4cc315ebdd3bd86f5 -0, 7, 7, 1, 191688, aca858d2cce189eb60012a33ea74d10b -0, 8, 8, 1, 191576, aa933dea9aac9b61fea004747e3b8e6a -0, 9, 9, 1, 191544, 6c410ec9e2492d464d439a58e6e338c3 -0, 10, 10, 1, 191472, 7c7661ff35671b3912b2b216bc6df478 -0, 11, 11, 1, 191280, 73c1ff53a0cd5c65eb2ae75a45efbf72 -0, 12, 12, 1, 191700, 201b0b4834878513e6e13bd9f5977a28 -0, 13, 13, 1, 191424, 0affff549b2da09c7852c5e8dbd1c84a -0, 14, 14, 1, 191420, e0e80adf520953c4bc4033efc77b9092 -0, 15, 15, 1, 191408, 4fa22efbf2101b7f6bfffae227ce1d23 -0, 16, 16, 1, 191500, fef8df893234b38be36803d5f5656e16 -0, 17, 17, 1, 191580, 3585b500a77344fd87f8f18e3816f1a8 -0, 18, 18, 1, 191608, 419189483180612b72491dab5864c6e7 -0, 19, 19, 1, 191616, 197fa32c8a164eeea73defb7422657d1 -0, 20, 20, 1, 191596, a660a6c630f7e55c3ca2f9a37d599223 -0, 21, 21, 1, 191660, d98445b0387c3d54034f8defe1d03ea6 -0, 22, 22, 1, 191540, ef4522aa762b82d1c715805a779c7c1e -0, 23, 23, 1, 191576, 32d109d2040c69b3944471b0bd399a65 -0, 24, 24, 1, 191636, 58e2f3a01de4175ba7f915e2d065ba36 -0, 25, 25, 1, 191524, 0989a64e78613cfc26124e195cfc0cde -0, 26, 26, 1, 191640, b9e252a5c4583736a8ba248d15c429aa -0, 27, 27, 1, 191800, 1541cccc66cb63d3e1ef675a16a1258e -0, 28, 28, 1, 192028, 5dada6bf987738caebca210067d13c39 -0, 29, 29, 1, 191964, 8d55bb4a1464ac74364d4b1e416d4a0c -0, 30, 30, 1, 191736, 88c279b9f3e96485f85dbca09177fe26 -0, 31, 31, 1, 191788, aa75795116428edb57dea8b54527e13b -0, 32, 32, 1, 191636, aa45e4ec1fcc038ea2e48046e5047417 -0, 33, 33, 1, 191400, 7b2861b3ca8bfcdca010d859c0595e03 -0, 34, 34, 1, 191332, 956acfcc00661d9a9ba7575e8c1a011b -0, 35, 35, 1, 191548, 3b5b7c3b9a6a5ebe10f178077a5fea4d -0, 36, 36, 1, 191852, 835219e1689946f3e26457ffce197181 -0, 37, 37, 1, 191828, f67a1e4640472287baf194c02f24dc29 -0, 38, 38, 1, 191812, 978f44d430859044350ea20913ae4194 -0, 39, 39, 1, 191700, 92e21c9ded61f69f793c649eece071c4 -0, 40, 40, 1, 191812, 0a460bc35daad68e8042917f26dac542 -0, 41, 41, 1, 191548, 7c7a65b9257f9b4439002c5c414c401c -0, 42, 42, 1, 191544, b03d903c46536dc336461827fd4d34db -0, 43, 43, 1, 191700, 75b391d84b120e63ec229fcb48808d19 -0, 44, 44, 1, 191780, c953dcd42a8aa19eb4d4be0149894bbe -0, 45, 45, 1, 191952, 64be44b2e21f8301f4234e32a10cb1c9 -0, 46, 46, 1, 191916, a6c805f651f3f57a84681b1aab6fe3ef -0, 47, 47, 1, 191784, 9cc8db3cb63a026645f634aabc89c37b -0, 48, 48, 1, 191716, e2f0c7543b3484a726411eac4e9a79cd -0, 49, 49, 1, 191728, 50277180199917d1259e0cad42f52d4c +0, 0, 0, 1, 191800, 4a5653458a4206bcbc584d5e6beb61f2 +0, 1, 1, 1, 191820, 2f77ced17c186b507864ea482016c913 +0, 2, 2, 1, 191668, 2dd719b7228e3b38e1e86a0304a599f1 +0, 3, 3, 1, 191696, 4fe7ef1586ef85f3ceb579426ff4077f +0, 4, 4, 1, 191972, 9b9718c63d0b6f6bc293036bcf7a884d +0, 5, 5, 1, 191760, 24fbe86d07c66d4f791533219a6bbca5 +0, 6, 6, 1, 191708, 32f4e266cc3e22e8b5ad354f4685ca9f +0, 7, 7, 1, 191688, 9614c1881c3c2807ac492b1c3d689559 +0, 8, 8, 1, 191568, a4e53b02fdbc66c47e099cb3506a5f27 +0, 9, 9, 1, 191544, c3f2fcb7a299163e72faa93522405def +0, 10, 10, 1, 191468, 598cb568c2e4b651f04511eea480b8f0 +0, 11, 11, 1, 191280, 7ac77492856c214f6266da9eea4cc766 +0, 12, 12, 1, 191700, 5b261fda1cdafc11596fca42e902e8a9 +0, 13, 13, 1, 191424, c31421daddb684ec01a0b8953a340891 +0, 14, 14, 1, 191416, 742171e3f053ffb7f27dd14e9a408e33 +0, 15, 15, 1, 191408, 06efc3afdf3c97c6c6e6f76eeea217b7 +0, 16, 16, 1, 191500, ee9d95219dc34981f1e3a9feee21a12a +0, 17, 17, 1, 191580, 9fd14328b5f304cab54405b2e7b6dd74 +0, 18, 18, 1, 191608, 84374f2e0540d97f4f5a5282397d1fd4 +0, 19, 19, 1, 191616, 6f8d0b3143d78d87209815e4f14e8fde +0, 20, 20, 1, 191596, 4533cb5577bbee750eee21966f3e6b87 +0, 21, 21, 1, 191660, c9cbe09e11e7bb47565d54ec25e407e1 +0, 22, 22, 1, 191536, 3a9168133d91c67219052869bb4a1aa9 +0, 23, 23, 1, 191576, 0df4b9398953fe710b949cc3912927a1 +0, 24, 24, 1, 191636, 5ee06edd617272e33b59da14e9e472b5 +0, 25, 25, 1, 191524, 3e09b926cf3dbed003746d0fc4bb9eb1 +0, 26, 26, 1, 191640, e4f9408633b8cb13578de8caca4afd77 +0, 27, 27, 1, 191800, 7c57ae6d60df4676c132de16ebf1ec24 +0, 28, 28, 1, 192028, 36fd55e15ee357478bdd3085adc5d1f9 +0, 29, 29, 1, 191964, 82a4fd877d4dba1266fc28d9a74e5cf3 +0, 30, 30, 1, 191732, 3d905c393537ccdbdc2bb83cfc9ac1f3 +0, 31, 31, 1, 191788, 92e647f7728fe892c3f97d866aa9e6e7 +0, 32, 32, 1, 191636, d26af69ceee2e7433e04da1eee6a4043 +0, 33, 33, 1, 191400, 9e5d147eea116586d13cec38e59d0e90 +0, 34, 34, 1, 191332, 93419f91d6d4d274344a0f184f03210a +0, 35, 35, 1, 191548, 61c4c7a96c86ccb5189daa63b3219340 +0, 36, 36, 1, 191852, 62fd435d20d032686bf9bad5ac5252b8 +0, 37, 37, 1, 191828, 2487f780f709f38c38a19b1d0e255575 +0, 38, 38, 1, 191808, 5bd0d224585427f2fa6fca1392ea6273 +0, 39, 39, 1, 191700, deaed17ec6cbc863313b7698114d54fd +0, 40, 40, 1, 191812, 296dce78545cf89745c13f117347949b +0, 41, 41, 1, 191548, 0273c1819d7af2f49b1b86b238414702 +0, 42, 42, 1, 191544, e9e29ab1e3f9fd5bff18748f38a3a79d +0, 43, 43, 1, 191700, c211fa96ed541d7d53bc975577bd7bbc +0, 44, 44, 1, 191780, cfcd29e8a289aa0f2d4026189bb0b966 +0, 45, 45, 1, 191952, 0c1f04a3877565eb8bd76b652626a27f +0, 46, 46, 1, 191916, 1e49ee7ea02c2df7e0b6187fcc6cbdbe +0, 47, 47, 1, 191784, 5fa516e0bb264c767e49169cf7accd23 +0, 48, 48, 1, 191716, 3a7abe462356b1020f3c8d496bcbbbdc +0, 49, 49, 1, 191728, cf5fb801291c77b04d9937e4b828f772 diff --git a/tests/ref/fate/v410enc b/tests/ref/fate/v410enc index ab219bbed..b2c728e9b 100644 --- a/tests/ref/fate/v410enc +++ b/tests/ref/fate/v410enc @@ -1 +1 @@ -e5c0b1f17d2a64a416dcf9bf7a38d9d9 +f7cf1b743c18f74d047ce8d6ea05d3d9 diff --git a/tests/ref/fate/vcr2 b/tests/ref/fate/vcr2 index ab70d29db..521e55fd0 100644 --- a/tests/ref/fate/vcr2 +++ b/tests/ref/fate/vcr2 @@ -1,158 +1,158 @@ -#tb 0: 12/539 +#tb 0: 16701/250000 0, 0, 0, 1, 38016, 0x50e93e0d -0, 3, 3, 1, 38016, 0x6ac8627d -0, 6, 6, 1, 38016, 0x6f38661e -0, 9, 9, 1, 38016, 0x18bb3e23 -0, 12, 12, 1, 38016, 0x2029f4da -0, 15, 15, 1, 38016, 0xa981eeb9 -0, 18, 18, 1, 38016, 0x65c636ef -0, 21, 21, 1, 38016, 0x8218f178 -0, 24, 24, 1, 38016, 0xc3986e18 -0, 27, 27, 1, 38016, 0xac871f50 -0, 30, 30, 1, 38016, 0xe83ed617 -0, 33, 33, 1, 38016, 0xe87c4132 -0, 36, 36, 1, 38016, 0x9e03c321 -0, 39, 39, 1, 38016, 0x81f06a6e -0, 42, 42, 1, 38016, 0x4ce15039 -0, 45, 45, 1, 38016, 0x398dfbdd -0, 48, 48, 1, 38016, 0x3049218c -0, 51, 51, 1, 38016, 0x6d90bb3f -0, 54, 54, 1, 38016, 0x5b61ae57 -0, 57, 57, 1, 38016, 0xaf17011d -0, 60, 60, 1, 38016, 0xb6c13da6 -0, 63, 63, 1, 38016, 0xb58135cf -0, 66, 66, 1, 38016, 0x051c33ce -0, 69, 69, 1, 38016, 0xda950393 -0, 72, 72, 1, 38016, 0x76f7ea61 -0, 75, 75, 1, 38016, 0xcba6f5c8 -0, 78, 78, 1, 38016, 0x2ac20405 -0, 81, 81, 1, 38016, 0x6c790a1b -0, 84, 84, 1, 38016, 0x8525413b -0, 87, 87, 1, 38016, 0xef2e46a5 -0, 90, 90, 1, 38016, 0x32c16c28 -0, 93, 93, 1, 38016, 0x9fb0755f -0, 96, 96, 1, 38016, 0xdfd7a1e2 -0, 99, 99, 1, 38016, 0xa91eb2d0 -0, 102, 102, 1, 38016, 0xb7bed869 -0, 105, 105, 1, 38016, 0x0263da70 -0, 108, 108, 1, 38016, 0x1403cf83 -0, 111, 111, 1, 38016, 0xb766f81a -0, 114, 114, 1, 38016, 0x85abd4e0 -0, 117, 117, 1, 38016, 0xfc30c171 -0, 120, 120, 1, 38016, 0xb53bb9e5 -0, 123, 123, 1, 38016, 0xe93ca93c -0, 126, 126, 1, 38016, 0xfa9db507 -0, 129, 129, 1, 38016, 0xd4da8492 -0, 132, 132, 1, 38016, 0x951cb041 -0, 135, 135, 1, 38016, 0x64fb9a09 -0, 138, 138, 1, 38016, 0x8f89b841 -0, 141, 141, 1, 38016, 0x9ee4b6df -0, 144, 144, 1, 38016, 0xd733ae27 -0, 147, 147, 1, 38016, 0x2a1ab87d -0, 150, 150, 1, 38016, 0x4853bf88 -0, 153, 153, 1, 38016, 0x701da865 -0, 156, 156, 1, 38016, 0x074d8248 -0, 159, 159, 1, 38016, 0xa1b4b019 -0, 162, 162, 1, 38016, 0x33f798c7 -0, 165, 165, 1, 38016, 0x5091bd66 -0, 168, 168, 1, 38016, 0x9dc0bf08 -0, 171, 171, 1, 38016, 0x83cff4c3 -0, 174, 174, 1, 38016, 0xce551295 -0, 177, 177, 1, 38016, 0x3c334a45 -0, 180, 180, 1, 38016, 0xd6e669ae -0, 183, 183, 1, 38016, 0x08817cb0 -0, 186, 186, 1, 38016, 0x3d399508 -0, 189, 189, 1, 38016, 0xaf49a306 -0, 192, 192, 1, 38016, 0x6b77e02c -0, 195, 195, 1, 38016, 0x34a6cc72 -0, 198, 198, 1, 38016, 0x0303e6bb -0, 201, 201, 1, 38016, 0x3995eee2 -0, 204, 204, 1, 38016, 0x8eefd136 -0, 207, 207, 1, 38016, 0xd69ad171 -0, 210, 210, 1, 38016, 0xed98bff6 -0, 213, 213, 1, 38016, 0x606ba5ef -0, 216, 216, 1, 38016, 0xbce4afaa -0, 219, 219, 1, 38016, 0xa5baac40 -0, 222, 222, 1, 38016, 0x7a15929f -0, 225, 225, 1, 38016, 0x0374cdec -0, 228, 228, 1, 38016, 0xf482e941 -0, 231, 231, 1, 38016, 0xced1c9e3 -0, 234, 234, 1, 38016, 0x638fd91f -0, 237, 237, 1, 38016, 0xced5d802 -0, 240, 240, 1, 38016, 0x330adeeb -0, 243, 243, 1, 38016, 0x7a70f93e -0, 246, 246, 1, 38016, 0x25c0dac1 -0, 249, 249, 1, 38016, 0x6f9401cf -0, 252, 252, 1, 38016, 0x01632a5b -0, 255, 255, 1, 38016, 0x6eedd857 -0, 258, 258, 1, 38016, 0xcfad1017 -0, 261, 261, 1, 38016, 0x38071e53 -0, 264, 264, 1, 38016, 0xc7c3013f -0, 267, 267, 1, 38016, 0x1f41fe19 -0, 270, 270, 1, 38016, 0x9662e170 -0, 273, 273, 1, 38016, 0xec19ecfc -0, 276, 276, 1, 38016, 0xab419765 -0, 279, 279, 1, 38016, 0xe784d98b -0, 282, 282, 1, 38016, 0x93c1a4bf -0, 285, 285, 1, 38016, 0xf2e4c9b4 -0, 288, 288, 1, 38016, 0x7cb6c1ff -0, 291, 291, 1, 38016, 0x6fb36837 -0, 294, 294, 1, 38016, 0x6fb64665 -0, 297, 297, 1, 38016, 0xf24eaba9 -0, 300, 300, 1, 38016, 0x3866d28b -0, 303, 303, 1, 38016, 0x807e829c -0, 306, 306, 1, 38016, 0xf25fcbbb -0, 309, 309, 1, 38016, 0xc28ba68f -0, 312, 312, 1, 38016, 0x65ef8def -0, 315, 315, 1, 38016, 0xc4646ee4 -0, 318, 318, 1, 38016, 0x3cb76962 -0, 321, 321, 1, 38016, 0xe5500136 -0, 324, 324, 1, 38016, 0xb086aa05 -0, 327, 327, 1, 38016, 0xde9fd4c3 -0, 330, 330, 1, 38016, 0xcae0d11b -0, 333, 333, 1, 38016, 0x6cd3ee1a -0, 336, 336, 1, 38016, 0x38981b85 -0, 339, 339, 1, 38016, 0xbe742f68 -0, 342, 342, 1, 38016, 0x29c41fc7 -0, 345, 345, 1, 38016, 0x43612eaf -0, 348, 348, 1, 38016, 0x199dba2f -0, 351, 351, 1, 38016, 0xb434f64d -0, 354, 354, 1, 38016, 0x36f2fd8c -0, 357, 357, 1, 38016, 0xc1075321 -0, 360, 360, 1, 38016, 0x7eabeab8 -0, 363, 363, 1, 38016, 0x7fcd5127 -0, 366, 366, 1, 38016, 0x37ddb544 -0, 369, 369, 1, 38016, 0x5dee2700 -0, 372, 372, 1, 38016, 0x46deb355 -0, 375, 375, 1, 38016, 0xb2496a7c -0, 378, 378, 1, 38016, 0xfaf3b134 -0, 381, 381, 1, 38016, 0x42e9dbe1 -0, 384, 384, 1, 38016, 0x699fc6e0 -0, 387, 387, 1, 38016, 0x43ba68ae -0, 390, 390, 1, 38016, 0xffd21579 -0, 393, 393, 1, 38016, 0xdd979741 -0, 396, 396, 1, 38016, 0x789c89aa -0, 399, 399, 1, 38016, 0x40be024e -0, 402, 402, 1, 38016, 0xa60c291d -0, 405, 405, 1, 38016, 0xa8d253e9 -0, 408, 408, 1, 38016, 0x16d7f60e -0, 411, 411, 1, 38016, 0xf1d21a57 -0, 414, 414, 1, 38016, 0x5e80e3bd -0, 417, 417, 1, 38016, 0xceec0529 -0, 420, 420, 1, 38016, 0x1ff9c462 -0, 423, 423, 1, 38016, 0x51c168d2 -0, 426, 426, 1, 38016, 0xf61f2059 -0, 429, 429, 1, 38016, 0xb22fa794 -0, 432, 432, 1, 38016, 0xb81ec7d5 -0, 435, 435, 1, 38016, 0x7555d1df -0, 438, 438, 1, 38016, 0x860d9de3 -0, 441, 441, 1, 38016, 0x9b19a66f -0, 444, 444, 1, 38016, 0xec52d405 -0, 447, 447, 1, 38016, 0x2da4d05b -0, 450, 450, 1, 38016, 0xf15bf060 -0, 453, 453, 1, 38016, 0xfabcc24a -0, 456, 456, 1, 38016, 0xc159f63a -0, 459, 459, 1, 38016, 0x0b97fcc1 -0, 462, 462, 1, 38016, 0xe0c063a2 -0, 465, 465, 1, 38016, 0x7bda9bec -0, 468, 468, 1, 38016, 0xbe99a923 +0, 1, 1, 1, 38016, 0x6ac8627d +0, 2, 2, 1, 38016, 0x6f38661e +0, 3, 3, 1, 38016, 0x18bb3e23 +0, 4, 4, 1, 38016, 0x2029f4da +0, 5, 5, 1, 38016, 0xa981eeb9 +0, 6, 6, 1, 38016, 0x65c636ef +0, 7, 7, 1, 38016, 0x8218f178 +0, 8, 8, 1, 38016, 0xc3986e18 +0, 9, 9, 1, 38016, 0xac871f50 +0, 10, 10, 1, 38016, 0xe83ed617 +0, 11, 11, 1, 38016, 0xe87c4132 +0, 12, 12, 1, 38016, 0x9e03c321 +0, 13, 13, 1, 38016, 0x81f06a6e +0, 14, 14, 1, 38016, 0x4ce15039 +0, 15, 15, 1, 38016, 0x398dfbdd +0, 16, 16, 1, 38016, 0x3049218c +0, 17, 17, 1, 38016, 0x6d90bb3f +0, 18, 18, 1, 38016, 0x5b61ae57 +0, 19, 19, 1, 38016, 0xaf17011d +0, 20, 20, 1, 38016, 0xb6c13da6 +0, 21, 21, 1, 38016, 0xb58135cf +0, 22, 22, 1, 38016, 0x051c33ce +0, 23, 23, 1, 38016, 0xda950393 +0, 24, 24, 1, 38016, 0x76f7ea61 +0, 25, 25, 1, 38016, 0xcba6f5c8 +0, 26, 26, 1, 38016, 0x2ac20405 +0, 27, 27, 1, 38016, 0x6c790a1b +0, 28, 28, 1, 38016, 0x8525413b +0, 29, 29, 1, 38016, 0xef2e46a5 +0, 30, 30, 1, 38016, 0x32c16c28 +0, 31, 31, 1, 38016, 0x9fb0755f +0, 32, 32, 1, 38016, 0xdfd7a1e2 +0, 33, 33, 1, 38016, 0xa91eb2d0 +0, 34, 34, 1, 38016, 0xb7bed869 +0, 35, 35, 1, 38016, 0x0263da70 +0, 36, 36, 1, 38016, 0x1403cf83 +0, 37, 37, 1, 38016, 0xb766f81a +0, 38, 38, 1, 38016, 0x85abd4e0 +0, 39, 39, 1, 38016, 0xfc30c171 +0, 40, 40, 1, 38016, 0xb53bb9e5 +0, 41, 41, 1, 38016, 0xe93ca93c +0, 42, 42, 1, 38016, 0xfa9db507 +0, 43, 43, 1, 38016, 0xd4da8492 +0, 44, 44, 1, 38016, 0x951cb041 +0, 45, 45, 1, 38016, 0x64fb9a09 +0, 46, 46, 1, 38016, 0x8f89b841 +0, 47, 47, 1, 38016, 0x9ee4b6df +0, 48, 48, 1, 38016, 0xd733ae27 +0, 49, 49, 1, 38016, 0x2a1ab87d +0, 50, 50, 1, 38016, 0x4853bf88 +0, 51, 51, 1, 38016, 0x701da865 +0, 52, 52, 1, 38016, 0x074d8248 +0, 53, 53, 1, 38016, 0xa1b4b019 +0, 54, 54, 1, 38016, 0x33f798c7 +0, 55, 55, 1, 38016, 0x5091bd66 +0, 56, 56, 1, 38016, 0x9dc0bf08 +0, 57, 57, 1, 38016, 0x83cff4c3 +0, 58, 58, 1, 38016, 0xce551295 +0, 59, 59, 1, 38016, 0x3c334a45 +0, 60, 60, 1, 38016, 0xd6e669ae +0, 61, 61, 1, 38016, 0x08817cb0 +0, 62, 62, 1, 38016, 0x3d399508 +0, 63, 63, 1, 38016, 0xaf49a306 +0, 64, 64, 1, 38016, 0x6b77e02c +0, 65, 65, 1, 38016, 0x34a6cc72 +0, 66, 66, 1, 38016, 0x0303e6bb +0, 67, 67, 1, 38016, 0x3995eee2 +0, 68, 68, 1, 38016, 0x8eefd136 +0, 69, 69, 1, 38016, 0xd69ad171 +0, 70, 70, 1, 38016, 0xed98bff6 +0, 71, 71, 1, 38016, 0x606ba5ef +0, 72, 72, 1, 38016, 0xbce4afaa +0, 73, 73, 1, 38016, 0xa5baac40 +0, 74, 74, 1, 38016, 0x7a15929f +0, 75, 75, 1, 38016, 0x0374cdec +0, 76, 76, 1, 38016, 0xf482e941 +0, 77, 77, 1, 38016, 0xced1c9e3 +0, 78, 78, 1, 38016, 0x638fd91f +0, 79, 79, 1, 38016, 0xced5d802 +0, 80, 80, 1, 38016, 0x330adeeb +0, 81, 81, 1, 38016, 0x7a70f93e +0, 82, 82, 1, 38016, 0x25c0dac1 +0, 83, 83, 1, 38016, 0x6f9401cf +0, 84, 84, 1, 38016, 0x01632a5b +0, 85, 85, 1, 38016, 0x6eedd857 +0, 86, 86, 1, 38016, 0xcfad1017 +0, 87, 87, 1, 38016, 0x38071e53 +0, 88, 88, 1, 38016, 0xc7c3013f +0, 89, 89, 1, 38016, 0x1f41fe19 +0, 90, 90, 1, 38016, 0x9662e170 +0, 91, 91, 1, 38016, 0xec19ecfc +0, 92, 92, 1, 38016, 0xab419765 +0, 93, 93, 1, 38016, 0xe784d98b +0, 94, 94, 1, 38016, 0x93c1a4bf +0, 95, 95, 1, 38016, 0xf2e4c9b4 +0, 96, 96, 1, 38016, 0x7cb6c1ff +0, 97, 97, 1, 38016, 0x6fb36837 +0, 98, 98, 1, 38016, 0x6fb64665 +0, 99, 99, 1, 38016, 0xf24eaba9 +0, 100, 100, 1, 38016, 0x3866d28b +0, 101, 101, 1, 38016, 0x807e829c +0, 102, 102, 1, 38016, 0xf25fcbbb +0, 103, 103, 1, 38016, 0xc28ba68f +0, 104, 104, 1, 38016, 0x65ef8def +0, 105, 105, 1, 38016, 0xc4646ee4 +0, 106, 106, 1, 38016, 0x3cb76962 +0, 107, 107, 1, 38016, 0xe5500136 +0, 108, 108, 1, 38016, 0xb086aa05 +0, 109, 109, 1, 38016, 0xde9fd4c3 +0, 110, 110, 1, 38016, 0xcae0d11b +0, 111, 111, 1, 38016, 0x6cd3ee1a +0, 112, 112, 1, 38016, 0x38981b85 +0, 113, 113, 1, 38016, 0xbe742f68 +0, 114, 114, 1, 38016, 0x29c41fc7 +0, 115, 115, 1, 38016, 0x43612eaf +0, 116, 116, 1, 38016, 0x199dba2f +0, 117, 117, 1, 38016, 0xb434f64d +0, 118, 118, 1, 38016, 0x36f2fd8c +0, 119, 119, 1, 38016, 0xc1075321 +0, 120, 120, 1, 38016, 0x7eabeab8 +0, 121, 121, 1, 38016, 0x7fcd5127 +0, 122, 122, 1, 38016, 0x37ddb544 +0, 123, 123, 1, 38016, 0x5dee2700 +0, 124, 124, 1, 38016, 0x46deb355 +0, 125, 125, 1, 38016, 0xb2496a7c +0, 126, 126, 1, 38016, 0xfaf3b134 +0, 127, 127, 1, 38016, 0x42e9dbe1 +0, 128, 128, 1, 38016, 0x699fc6e0 +0, 129, 129, 1, 38016, 0x43ba68ae +0, 130, 130, 1, 38016, 0xffd21579 +0, 131, 131, 1, 38016, 0xdd979741 +0, 132, 132, 1, 38016, 0x789c89aa +0, 133, 133, 1, 38016, 0x40be024e +0, 134, 134, 1, 38016, 0xa60c291d +0, 135, 135, 1, 38016, 0xa8d253e9 +0, 136, 136, 1, 38016, 0x16d7f60e +0, 137, 137, 1, 38016, 0xf1d21a57 +0, 138, 138, 1, 38016, 0x5e80e3bd +0, 139, 139, 1, 38016, 0xceec0529 +0, 140, 140, 1, 38016, 0x1ff9c462 +0, 141, 141, 1, 38016, 0x51c168d2 +0, 142, 142, 1, 38016, 0xf61f2059 +0, 143, 143, 1, 38016, 0xb22fa794 +0, 144, 144, 1, 38016, 0xb81ec7d5 +0, 145, 145, 1, 38016, 0x7555d1df +0, 146, 146, 1, 38016, 0x860d9de3 +0, 147, 147, 1, 38016, 0x9b19a66f +0, 148, 148, 1, 38016, 0xec52d405 +0, 149, 149, 1, 38016, 0x2da4d05b +0, 150, 150, 1, 38016, 0xf15bf060 +0, 151, 151, 1, 38016, 0xfabcc24a +0, 152, 152, 1, 38016, 0xc159f63a +0, 153, 153, 1, 38016, 0x0b97fcc1 +0, 154, 154, 1, 38016, 0xe0c063a2 +0, 155, 155, 1, 38016, 0x7bda9bec +0, 156, 156, 1, 38016, 0xbe99a923 diff --git a/tests/ref/fate/vp7 b/tests/ref/fate/vp7 new file mode 100644 index 000000000..b01401009 --- /dev/null +++ b/tests/ref/fate/vp7 @@ -0,0 +1,31 @@ +#tb 0: 1001/12000 +0, 0, 0, 1, 84480, 0xa7776101 +0, 1, 1, 1, 84480, 0xeb1560ca +0, 2, 2, 1, 84480, 0x7a4e6123 +0, 3, 3, 1, 84480, 0x7a4e6123 +0, 4, 4, 1, 84480, 0x8ee36111 +0, 5, 5, 1, 84480, 0x3c2a6110 +0, 6, 6, 1, 84480, 0x3c2a6110 +0, 7, 7, 1, 84480, 0x961e607d +0, 8, 8, 1, 84480, 0xb7b5615d +0, 9, 9, 1, 84480, 0x636d6011 +0, 10, 10, 1, 84480, 0x69fd6111 +0, 11, 11, 1, 84480, 0x636d6011 +0, 12, 12, 1, 84480, 0x69fd6111 +0, 13, 13, 1, 84480, 0x636d6011 +0, 14, 14, 1, 84480, 0x69fd6111 +0, 15, 15, 1, 84480, 0x636d6011 +0, 16, 16, 1, 84480, 0x2d1a610a +0, 17, 17, 1, 84480, 0x268a600a +0, 18, 18, 1, 84480, 0x2d1a610a +0, 19, 19, 1, 84480, 0x268a600a +0, 20, 20, 1, 84480, 0x2d1a610a +0, 21, 21, 1, 84480, 0x268a600a +0, 22, 22, 1, 84480, 0x2d1a610a +0, 23, 23, 1, 84480, 0x268a600a +0, 24, 24, 1, 84480, 0xa88261c9 +0, 25, 25, 1, 84480, 0x98e95fc6 +0, 26, 26, 1, 84480, 0x9f7960c6 +0, 27, 27, 1, 84480, 0x98e95fc6 +0, 28, 28, 1, 84480, 0x9f7960c6 +0, 29, 29, 1, 84480, 0x98e95fc6 diff --git a/tests/ref/fate/vqf-demux b/tests/ref/fate/vqf-demux index 3acae60f5..3c1dd3595 100644 --- a/tests/ref/fate/vqf-demux +++ b/tests/ref/fate/vqf-demux @@ -1 +1 @@ -d72fb75fb22f4bcc94a1dc7af5356ec1 +084a9bf92d4096c8156d1fce50dac8b8 diff --git a/tests/ref/fate/wmv8-drm-nodec b/tests/ref/fate/wmv8-drm-nodec index 76c4e75bc..279c8b66a 100644 --- a/tests/ref/fate/wmv8-drm-nodec +++ b/tests/ref/fate/wmv8-drm-nodec @@ -1,3 +1,5 @@ +#extradata 0: 4, 0x021800a2 +#extradata 1: 46, 0x63d9043a #tb 0: 1/1000 #tb 1: 1/1000 0, 0, 0, 0, 282, 0x000d949a diff --git a/tests/ref/fate/wtv-demux b/tests/ref/fate/wtv-demux index 362c55b9d..904d78b06 100644 --- a/tests/ref/fate/wtv-demux +++ b/tests/ref/fate/wtv-demux @@ -1,3 +1,5 @@ +#extradata 0: 86, 0xc7ca09e5 +#extradata 1: 22, 0x12dc010c #tb 0: 1/10000000 #tb 1: 1/10000000 1, -2, -2, 240000, 576, 0x9b6e1638 diff --git a/tests/ref/fate/xbm10 b/tests/ref/fate/xbm10 new file mode 100644 index 000000000..00388916f --- /dev/null +++ b/tests/ref/fate/xbm10 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 32, 0x777f0737 diff --git a/tests/ref/fate/xbm11 b/tests/ref/fate/xbm11 new file mode 100644 index 000000000..77192b3e6 --- /dev/null +++ b/tests/ref/fate/xbm11 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 4750, 0xc85f0b6d diff --git a/tests/ref/fate/xmv-demux b/tests/ref/fate/xmv-demux index 49f22c98d..d13270a6f 100644 --- a/tests/ref/fate/xmv-demux +++ b/tests/ref/fate/xmv-demux @@ -1,3 +1,4 @@ +#extradata 0: 4, 0x015a00ad #tb 0: 1/1000 #tb 1: 16/11025 0, 0, 0, 0, 1508, 0xefceba48 diff --git a/tests/ref/lavf/asf b/tests/ref/lavf/asf index a90e5474f..400278cd9 100644 --- a/tests/ref/lavf/asf +++ b/tests/ref/lavf/asf @@ -1,3 +1,3 @@ -6bc7dc5698c3607fad8937d14560e50c *./tests/data/lavf/lavf.asf -333581 ./tests/data/lavf/lavf.asf +1a8716a0358b8123c02557dfdf6c259b *./tests/data/lavf/lavf.asf +333585 ./tests/data/lavf/lavf.asf ./tests/data/lavf/lavf.asf CRC=0xf6340a10 diff --git a/tests/ref/lavf/avi b/tests/ref/lavf/avi index 3cbb44f58..4068fad86 100644 --- a/tests/ref/lavf/avi +++ b/tests/ref/lavf/avi @@ -1,3 +1,3 @@ -8d3a3554cbe21bc232603ca26b0c4d3e *./tests/data/lavf/lavf.avi +cec38e42ff83343f6a5c300aa3009e7f *./tests/data/lavf/lavf.avi 330806 ./tests/data/lavf/lavf.avi ./tests/data/lavf/lavf.avi CRC=0xec6c3c68 diff --git a/tests/ref/lavf/ffm b/tests/ref/lavf/ffm index 707186685..c11350a9e 100644 --- a/tests/ref/lavf/ffm +++ b/tests/ref/lavf/ffm @@ -1,3 +1,3 @@ -6f1443b952819cff1dae875529675e88 *./tests/data/lavf/lavf.ffm +16cc0ee04b036c210b2fc85182d748e1 *./tests/data/lavf/lavf.ffm 376832 ./tests/data/lavf/lavf.ffm ./tests/data/lavf/lavf.ffm CRC=0x000e23ae diff --git a/tests/ref/lavf/gif b/tests/ref/lavf/gif index 4d90abe38..d2e2f11e9 100644 --- a/tests/ref/lavf/gif +++ b/tests/ref/lavf/gif @@ -1,3 +1,3 @@ -8aef8081e8afa445f63f320f4a1c5edb *./tests/data/lavf/lavf.gif -2030198 ./tests/data/lavf/lavf.gif -./tests/data/lavf/lavf.gif CRC=0x0dc5477c +e35f5ea283bbcb249818e0078ec72664 *./tests/data/lavf/lavf.gif +2011766 ./tests/data/lavf/lavf.gif +./tests/data/lavf/lavf.gif CRC=0x2429faff diff --git a/tests/ref/lavf/gxf b/tests/ref/lavf/gxf index 14a2c87d4..d356f2081 100644 --- a/tests/ref/lavf/gxf +++ b/tests/ref/lavf/gxf @@ -1,9 +1,9 @@ -9c96119322262ed2c43b34fd415233cc *./tests/data/lavf/lavf.gxf +7993da95d8bfe04832e27892c163e562 *./tests/data/lavf/lavf.gxf 795876 ./tests/data/lavf/lavf.gxf ./tests/data/lavf/lavf.gxf CRC=0xda7cebbc -260acc1c88a1706e5aaa74eff99ac389 *./tests/data/lavf/lavf.gxf +9e873074b5c3ef1d80d233a38e7de156 *./tests/data/lavf/lavf.gxf 794656 ./tests/data/lavf/lavf.gxf ./tests/data/lavf/lavf.gxf CRC=0x7f0c9089 -3cb8bab80b73a95f51e50989ccf06817 *./tests/data/lavf/lavf.gxf +0638c4d073ac224608baaba16732b68f *./tests/data/lavf/lavf.gxf 795876 ./tests/data/lavf/lavf.gxf ./tests/data/lavf/lavf.gxf CRC=0x5ade0285 diff --git a/tests/ref/lavf/ismv b/tests/ref/lavf/ismv index 764695e54..2c8d92c29 100644 --- a/tests/ref/lavf/ismv +++ b/tests/ref/lavf/ismv @@ -1,9 +1,9 @@ -df243ab73b33905776bdaefb79d14be8 *./tests/data/lavf/lavf.ismv -312453 ./tests/data/lavf/lavf.ismv +17b0b8eff852edd25fa38aed062689d7 *./tests/data/lavf/lavf.ismv +312546 ./tests/data/lavf/lavf.ismv ./tests/data/lavf/lavf.ismv CRC=0xb7d29d29 -c40d80b3b35c9cd1324dead65dfcdb69 *./tests/data/lavf/lavf.ismv -321359 ./tests/data/lavf/lavf.ismv +543e5146df7bd4b7eb7edc94e0034ad9 *./tests/data/lavf/lavf.ismv +321452 ./tests/data/lavf/lavf.ismv ./tests/data/lavf/lavf.ismv CRC=0x33834815 -df243ab73b33905776bdaefb79d14be8 *./tests/data/lavf/lavf.ismv -312453 ./tests/data/lavf/lavf.ismv +17b0b8eff852edd25fa38aed062689d7 *./tests/data/lavf/lavf.ismv +312546 ./tests/data/lavf/lavf.ismv ./tests/data/lavf/lavf.ismv CRC=0xb7d29d29 diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv index 51fd2e71b..97c9864bb 100644 --- a/tests/ref/lavf/mkv +++ b/tests/ref/lavf/mkv @@ -1,6 +1,6 @@ -5e3e58192b11644477474a25bef2e022 *./tests/data/lavf/lavf.mkv -472559 ./tests/data/lavf/lavf.mkv +bda342503392d517955e1112def7b03a *./tests/data/lavf/lavf.mkv +472671 ./tests/data/lavf/lavf.mkv ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68 -6aac0de39634046f23a3447b08380efe *./tests/data/lavf/lavf.mkv -320288 ./tests/data/lavf/lavf.mkv +c93950920d4ee57eb3ff5ba0cf0c8b19 *./tests/data/lavf/lavf.mkv +320412 ./tests/data/lavf/lavf.mkv ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68 diff --git a/tests/ref/lavf/mov b/tests/ref/lavf/mov index 6c7375393..72d962aad 100644 --- a/tests/ref/lavf/mov +++ b/tests/ref/lavf/mov @@ -1,12 +1,12 @@ -65ba2cff95100a4914b2ff507eb42818 *./tests/data/lavf/lavf.mov -366421 ./tests/data/lavf/lavf.mov +a10d50f2679df92264e1fc21cb8be630 *./tests/data/lavf/lavf.mov +366449 ./tests/data/lavf/lavf.mov ./tests/data/lavf/lavf.mov CRC=0xbb2b949b -b9b988b23b5e5aff8760d0475908f837 *./tests/data/lavf/lavf.mov -357511 ./tests/data/lavf/lavf.mov +6258f70f974e3c802e01d02ac33c7bbd *./tests/data/lavf/lavf.mov +357539 ./tests/data/lavf/lavf.mov ./tests/data/lavf/lavf.mov CRC=0xbb2b949b -5c5c79e09490763a2692c91c5985b7ea *./tests/data/lavf/lavf.mov -366593 ./tests/data/lavf/lavf.mov +ba3b8b49e420510a0d417400dbedfc2d *./tests/data/lavf/lavf.mov +366621 ./tests/data/lavf/lavf.mov ./tests/data/lavf/lavf.mov CRC=0xa9793231 -c1d4ff07ccad169cb6fca003661f0c12 *./tests/data/lavf/lavf.mov -356893 ./tests/data/lavf/lavf.mov +fd0e4de8e7f6d0c8c0681d7020f00f50 *./tests/data/lavf/lavf.mov +356921 ./tests/data/lavf/lavf.mov ./tests/data/lavf/lavf.mov CRC=0xbb2b949b diff --git a/tests/ref/lavf/mpg b/tests/ref/lavf/mpg index 9feff6671..7aab14f84 100644 --- a/tests/ref/lavf/mpg +++ b/tests/ref/lavf/mpg @@ -1,9 +1,9 @@ -0a8c879bf813b6b758806088f29842dc *./tests/data/lavf/lavf.mpg +01bbdea588da51ab4a9d1d26f3443c96 *./tests/data/lavf/lavf.mpg 372736 ./tests/data/lavf/lavf.mpg ./tests/data/lavf/lavf.mpg CRC=0x000e23ae -d9446ae7b49de006a5a0f052ea9333ca *./tests/data/lavf/lavf.mpg +87b447b78a7d1141b9d41bb3aa50434d *./tests/data/lavf/lavf.mpg 389120 ./tests/data/lavf/lavf.mpg ./tests/data/lavf/lavf.mpg CRC=0x60ba4ab9 -edfef790122870cf4652e8a92ca558a0 *./tests/data/lavf/lavf.mpg +284f41c914df75c12de01e223d65f87f *./tests/data/lavf/lavf.mpg 372736 ./tests/data/lavf/lavf.mpg ./tests/data/lavf/lavf.mpg CRC=0x000e23ae diff --git a/tests/ref/lavf/mxf b/tests/ref/lavf/mxf index b1918f58a..27991ffbb 100644 --- a/tests/ref/lavf/mxf +++ b/tests/ref/lavf/mxf @@ -1,9 +1,9 @@ -967f6ee9223c865328f4891465191108 *./tests/data/lavf/lavf.mxf +103403355e6dec356c7342ee2d034691 *./tests/data/lavf/lavf.mxf 525369 ./tests/data/lavf/lavf.mxf ./tests/data/lavf/lavf.mxf CRC=0xdbfff6f1 -a085845074129d732fc6adb5601e3b5e *./tests/data/lavf/lavf.mxf +f61e4c8481610f30b2f5e2279e254f6b *./tests/data/lavf/lavf.mxf 560697 ./tests/data/lavf/lavf.mxf -./tests/data/lavf/lavf.mxf CRC=0x3ff4178e -ce535b606423d117675213b16275206a *./tests/data/lavf/lavf.mxf +./tests/data/lavf/lavf.mxf CRC=0x11a6178e +a586dad4ff94136be460afb02ff6101e *./tests/data/lavf/lavf.mxf 525369 ./tests/data/lavf/lavf.mxf ./tests/data/lavf/lavf.mxf CRC=0xdbfff6f1 diff --git a/tests/ref/lavf/mxf_d10 b/tests/ref/lavf/mxf_d10 index 8e08bddd4..98c2f6f53 100644 --- a/tests/ref/lavf/mxf_d10 +++ b/tests/ref/lavf/mxf_d10 @@ -1,3 +1,3 @@ -28cf73e6d35a8f7aba30c0ed2bd84924 *./tests/data/lavf/lavf.mxf_d10 +838b732d832dcf40b0eb9944bc6d8f55 *./tests/data/lavf/lavf.mxf_d10 5330989 ./tests/data/lavf/lavf.mxf_d10 ./tests/data/lavf/lavf.mxf_d10 CRC=0x6c74d488 diff --git a/tests/ref/lavf/nut b/tests/ref/lavf/nut index 6c42a40d6..1c3d7107d 100644 --- a/tests/ref/lavf/nut +++ b/tests/ref/lavf/nut @@ -1,3 +1,3 @@ -66386a488ee35e4592b605f63ef90a73 *./tests/data/lavf/lavf.nut -319902 ./tests/data/lavf/lavf.nut +424e8037d7b6f3d3c09cf76bf06a63cb *./tests/data/lavf/lavf.nut +319958 ./tests/data/lavf/lavf.nut ./tests/data/lavf/lavf.nut CRC=0xec6c3c68 diff --git a/tests/ref/lavf/ogg b/tests/ref/lavf/ogg index f8b58c4db..a08fb5ed8 100644 --- a/tests/ref/lavf/ogg +++ b/tests/ref/lavf/ogg @@ -1,3 +1,3 @@ -304a201b4afa3583b206bdeef177ce6b *./tests/data/lavf/lavf.ogg -13495 ./tests/data/lavf/lavf.ogg +81b9366cacb23644c2803585dced9996 *./tests/data/lavf/lavf.ogg +13516 ./tests/data/lavf/lavf.ogg ./tests/data/lavf/lavf.ogg CRC=0x3a1da17e diff --git a/tests/ref/lavf/ts b/tests/ref/lavf/ts index 02921edfa..1381f09f1 100644 --- a/tests/ref/lavf/ts +++ b/tests/ref/lavf/ts @@ -1,3 +1,3 @@ -a876e6bde8a2e8c7eca878869433ad3b *./tests/data/lavf/lavf.ts +cca6bca512605bbde20b7aa5cccf4850 *./tests/data/lavf/lavf.ts 407020 ./tests/data/lavf/lavf.ts ./tests/data/lavf/lavf.ts CRC=0x71287e25 diff --git a/tests/ref/lavf/w64 b/tests/ref/lavf/w64 index 7da4f095b..26c68688e 100644 --- a/tests/ref/lavf/w64 +++ b/tests/ref/lavf/w64 @@ -1,3 +1,3 @@ -062b91c34d570a90af8d55427804878e *./tests/data/lavf/lavf.w64 -88312 ./tests/data/lavf/lavf.w64 +82c75c9cb61924fda68d9602ea69c445 *./tests/data/lavf/lavf.w64 +88304 ./tests/data/lavf/lavf.w64 ./tests/data/lavf/lavf.w64 CRC=0x3a1da17e diff --git a/tests/ref/lavf/wav b/tests/ref/lavf/wav index 600c26a4c..da3bfc24e 100644 --- a/tests/ref/lavf/wav +++ b/tests/ref/lavf/wav @@ -1,3 +1,3 @@ -eb5a869456d2e9107bb195c8c99be1a1 *./tests/data/lavf/lavf.wav -88276 ./tests/data/lavf/lavf.wav +fc958a32b4fca7b1c40cbdaef2d1416e *./tests/data/lavf/lavf.wav +88274 ./tests/data/lavf/lavf.wav ./tests/data/lavf/lavf.wav CRC=0x3a1da17e diff --git a/tests/ref/lavf/wtv b/tests/ref/lavf/wtv index 8d69f7998..b0ae7d1db 100644 --- a/tests/ref/lavf/wtv +++ b/tests/ref/lavf/wtv @@ -1,3 +1,3 @@ -13cbdaf2c5e7c97991781cc48d9a958f *./tests/data/lavf/lavf.wtv +b74b14ee41830aed90380bf6252dcfdb *./tests/data/lavf/lavf.wtv 413696 ./tests/data/lavf/lavf.wtv ./tests/data/lavf/lavf.wtv CRC=0x71287e25 diff --git a/tests/ref/seek/acodec-adpcm-ima_qt-trellis b/tests/ref/seek/acodec-adpcm-ima_qt-trellis new file mode 100644 index 000000000..bdaf1f0f0 --- /dev/null +++ b/tests/ref/seek/acodec-adpcm-ima_qt-trellis @@ -0,0 +1,53 @@ +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 72 size: 68 +ret: 0 st:-1 flags:0 ts:-1.000000 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 72 size: 68 +ret: 0 st:-1 flags:1 ts: 1.894167 +ret: 0 st: 0 flags:1 dts: 1.893878 pts: 1.893878 pos: 88812 size: 68 +ret: 0 st: 0 flags:0 ts: 0.788345 +ret: 0 st: 0 flags:1 dts: 0.789478 pts: 0.789478 pos: 37064 size: 68 +ret: 0 st: 0 flags:1 ts:-0.317506 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 72 size: 68 +ret: 0 st:-1 flags:0 ts: 2.576668 +ret: 0 st: 0 flags:1 dts: 2.577438 pts: 2.577438 pos: 120840 size: 68 +ret: 0 st:-1 flags:1 ts: 1.470835 +ret: 0 st: 0 flags:1 dts: 1.470113 pts: 1.470113 pos: 68956 size: 68 +ret: 0 st: 0 flags:0 ts: 0.365011 +ret: 0 st: 0 flags:1 dts: 0.365714 pts: 0.365714 pos: 17208 size: 68 +ret: 0 st: 0 flags:1 ts:-0.740839 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 72 size: 68 +ret: 0 st:-1 flags:0 ts: 2.153336 +ret: 0 st: 0 flags:1 dts: 2.153673 pts: 2.153673 pos: 100984 size: 68 +ret: 0 st:-1 flags:1 ts: 1.047503 +ret: 0 st: 0 flags:1 dts: 1.046349 pts: 1.046349 pos: 49100 size: 68 +ret: 0 st: 0 flags:0 ts:-0.058322 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 72 size: 68 +ret: 0 st: 0 flags:1 ts: 2.835828 +ret: 0 st: 0 flags:1 dts: 2.835760 pts: 2.835760 pos: 132944 size: 68 +ret: 0 st:-1 flags:0 ts: 1.730004 +ret: 0 st: 0 flags:1 dts: 1.731338 pts: 1.731338 pos: 81196 size: 68 +ret: 0 st:-1 flags:1 ts: 0.624171 +ret: 0 st: 0 flags:1 dts: 0.624036 pts: 0.624036 pos: 29312 size: 68 +ret: 0 st: 0 flags:0 ts:-0.481655 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 72 size: 68 +ret: 0 st: 0 flags:1 ts: 2.412494 +ret: 0 st: 0 flags:1 dts: 2.411995 pts: 2.411995 pos: 113088 size: 68 +ret: 0 st:-1 flags:0 ts: 1.306672 +ret: 0 st: 0 flags:1 dts: 1.307574 pts: 1.307574 pos: 61340 size: 68 +ret: 0 st:-1 flags:1 ts: 0.200839 +ret: 0 st: 0 flags:1 dts: 0.200272 pts: 0.200272 pos: 9456 size: 68 +ret: 0 st: 0 flags:0 ts:-0.904989 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 72 size: 68 +ret: 0 st: 0 flags:1 ts: 1.989184 +ret: 0 st: 0 flags:1 dts: 1.988209 pts: 1.988209 pos: 93232 size: 68 +ret: 0 st:-1 flags:0 ts: 0.883340 +ret: 0 st: 0 flags:1 dts: 0.883810 pts: 0.883810 pos: 41484 size: 68 +ret: 0 st:-1 flags:1 ts:-0.222493 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 72 size: 68 +ret: 0 st: 0 flags:0 ts: 2.671678 +ret: 0 st: 0 flags:1 dts: 2.671769 pts: 2.671769 pos: 125260 size: 68 +ret: 0 st: 0 flags:1 ts: 1.565850 +ret: 0 st: 0 flags:1 dts: 1.564444 pts: 1.564444 pos: 73376 size: 68 +ret: 0 st:-1 flags:0 ts: 0.460008 +ret: 0 st: 0 flags:1 dts: 0.460045 pts: 0.460045 pos: 21628 size: 68 +ret: 0 st:-1 flags:1 ts:-0.645825 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 72 size: 68 diff --git a/tests/ref/seek/acodec-adpcm-ima_wav-trellis b/tests/ref/seek/acodec-adpcm-ima_wav-trellis new file mode 100644 index 000000000..b6517c543 --- /dev/null +++ b/tests/ref/seek/acodec-adpcm-ima_wav-trellis @@ -0,0 +1,53 @@ +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 60 size: 4096 +ret: 0 st:-1 flags:0 ts:-1.000000 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 60 size: 4096 +ret: 0 st:-1 flags:1 ts: 1.894167 +ret: 0 st: 0 flags:1 dts: 1.856009 pts: 1.856009 pos: 29756 size: 4096 +ret: 0 st: 0 flags:0 ts: 0.788345 +ret: 0 st: 0 flags:1 dts: 0.831995 pts: 0.831995 pos: 13372 size: 4096 +ret: 0 st: 0 flags:1 ts:-0.317506 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 60 size: 4096 +ret: 0 st:-1 flags:0 ts: 2.576668 +ret: 0 st: 0 flags:1 dts: 2.623991 pts: 2.623991 pos: 42044 size: 4096 +ret: 0 st:-1 flags:1 ts: 1.470835 +ret: 0 st: 0 flags:1 dts: 1.408005 pts: 1.408005 pos: 22588 size: 4096 +ret: 0 st: 0 flags:0 ts: 0.365011 +ret: 0 st: 0 flags:1 dts: 0.383991 pts: 0.383991 pos: 6204 size: 4096 +ret: 0 st: 0 flags:1 ts:-0.740839 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 60 size: 4096 +ret: 0 st:-1 flags:0 ts: 2.153336 +ret: 0 st: 0 flags:1 dts: 2.176009 pts: 2.176009 pos: 34876 size: 4096 +ret: 0 st:-1 flags:1 ts: 1.047503 +ret: 0 st: 0 flags:1 dts: 1.023991 pts: 1.023991 pos: 16444 size: 4096 +ret: 0 st: 0 flags:0 ts:-0.058322 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 60 size: 4096 +ret: 0 st: 0 flags:1 ts: 2.835828 +ret: 0 st: 0 flags:1 dts: 2.816009 pts: 2.816009 pos: 45116 size: 4096 +ret: 0 st:-1 flags:0 ts: 1.730004 +ret: 0 st: 0 flags:1 dts: 1.791995 pts: 1.791995 pos: 28732 size: 4096 +ret: 0 st:-1 flags:1 ts: 0.624171 +ret: 0 st: 0 flags:1 dts: 0.576009 pts: 0.576009 pos: 9276 size: 4096 +ret: 0 st: 0 flags:0 ts:-0.481655 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 60 size: 4096 +ret: 0 st: 0 flags:1 ts: 2.412494 +ret: 0 st: 0 flags:1 dts: 2.368005 pts: 2.368005 pos: 37948 size: 4096 +ret: 0 st:-1 flags:0 ts: 1.306672 +ret: 0 st: 0 flags:1 dts: 1.343991 pts: 1.343991 pos: 21564 size: 4096 +ret: 0 st:-1 flags:1 ts: 0.200839 +ret: 0 st: 0 flags:1 dts: 0.191995 pts: 0.191995 pos: 3132 size: 4096 +ret: 0 st: 0 flags:0 ts:-0.904989 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 60 size: 4096 +ret: 0 st: 0 flags:1 ts: 1.989184 +ret: 0 st: 0 flags:1 dts: 1.983991 pts: 1.983991 pos: 31804 size: 4096 +ret: 0 st:-1 flags:0 ts: 0.883340 +ret: 0 st: 0 flags:1 dts: 0.896009 pts: 0.896009 pos: 14396 size: 4096 +ret: 0 st:-1 flags:1 ts:-0.222493 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 60 size: 4096 +ret: 0 st: 0 flags:0 ts: 2.671678 +ret: 0 st: 0 flags:1 dts: 2.688005 pts: 2.688005 pos: 43068 size: 4096 +ret: 0 st: 0 flags:1 ts: 1.565850 +ret: 0 st: 0 flags:1 dts: 1.536009 pts: 1.536009 pos: 24636 size: 4096 +ret: 0 st:-1 flags:0 ts: 0.460008 +ret: 0 st: 0 flags:1 dts: 0.511995 pts: 0.511995 pos: 8252 size: 4096 +ret: 0 st:-1 flags:1 ts:-0.645825 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 60 size: 4096 diff --git a/tests/ref/seek/acodec-adpcm-ms-trellis b/tests/ref/seek/acodec-adpcm-ms-trellis new file mode 100644 index 000000000..579be7f41 --- /dev/null +++ b/tests/ref/seek/acodec-adpcm-ms-trellis @@ -0,0 +1,53 @@ +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 90 size: 4096 +ret: 0 st:-1 flags:0 ts:-1.000000 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 90 size: 4096 +ret: 0 st:-1 flags:1 ts: 1.894167 +ret: 0 st: 0 flags:1 dts: 1.856009 pts: 1.856009 pos: 29786 size: 4096 +ret: 0 st: 0 flags:0 ts: 0.788345 +ret: 0 st: 0 flags:1 dts: 0.831995 pts: 0.831995 pos: 13402 size: 4096 +ret: 0 st: 0 flags:1 ts:-0.317506 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 90 size: 4096 +ret: 0 st:-1 flags:0 ts: 2.576668 +ret: 0 st: 0 flags:1 dts: 2.623991 pts: 2.623991 pos: 42074 size: 4096 +ret: 0 st:-1 flags:1 ts: 1.470835 +ret: 0 st: 0 flags:1 dts: 1.408005 pts: 1.408005 pos: 22618 size: 4096 +ret: 0 st: 0 flags:0 ts: 0.365011 +ret: 0 st: 0 flags:1 dts: 0.383991 pts: 0.383991 pos: 6234 size: 4096 +ret: 0 st: 0 flags:1 ts:-0.740839 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 90 size: 4096 +ret: 0 st:-1 flags:0 ts: 2.153336 +ret: 0 st: 0 flags:1 dts: 2.176009 pts: 2.176009 pos: 34906 size: 4096 +ret: 0 st:-1 flags:1 ts: 1.047503 +ret: 0 st: 0 flags:1 dts: 1.023991 pts: 1.023991 pos: 16474 size: 4096 +ret: 0 st: 0 flags:0 ts:-0.058322 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 90 size: 4096 +ret: 0 st: 0 flags:1 ts: 2.835828 +ret: 0 st: 0 flags:1 dts: 2.816009 pts: 2.816009 pos: 45146 size: 4096 +ret: 0 st:-1 flags:0 ts: 1.730004 +ret: 0 st: 0 flags:1 dts: 1.791995 pts: 1.791995 pos: 28762 size: 4096 +ret: 0 st:-1 flags:1 ts: 0.624171 +ret: 0 st: 0 flags:1 dts: 0.576009 pts: 0.576009 pos: 9306 size: 4096 +ret: 0 st: 0 flags:0 ts:-0.481655 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 90 size: 4096 +ret: 0 st: 0 flags:1 ts: 2.412494 +ret: 0 st: 0 flags:1 dts: 2.368005 pts: 2.368005 pos: 37978 size: 4096 +ret: 0 st:-1 flags:0 ts: 1.306672 +ret: 0 st: 0 flags:1 dts: 1.343991 pts: 1.343991 pos: 21594 size: 4096 +ret: 0 st:-1 flags:1 ts: 0.200839 +ret: 0 st: 0 flags:1 dts: 0.191995 pts: 0.191995 pos: 3162 size: 4096 +ret: 0 st: 0 flags:0 ts:-0.904989 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 90 size: 4096 +ret: 0 st: 0 flags:1 ts: 1.989184 +ret: 0 st: 0 flags:1 dts: 1.983991 pts: 1.983991 pos: 31834 size: 4096 +ret: 0 st:-1 flags:0 ts: 0.883340 +ret: 0 st: 0 flags:1 dts: 0.896009 pts: 0.896009 pos: 14426 size: 4096 +ret: 0 st:-1 flags:1 ts:-0.222493 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 90 size: 4096 +ret: 0 st: 0 flags:0 ts: 2.671678 +ret: 0 st: 0 flags:1 dts: 2.688005 pts: 2.688005 pos: 43098 size: 4096 +ret: 0 st: 0 flags:1 ts: 1.565850 +ret: 0 st: 0 flags:1 dts: 1.536009 pts: 1.536009 pos: 24666 size: 4096 +ret: 0 st:-1 flags:0 ts: 0.460008 +ret: 0 st: 0 flags:1 dts: 0.511995 pts: 0.511995 pos: 8282 size: 4096 +ret: 0 st:-1 flags:1 ts:-0.645825 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 90 size: 4096 diff --git a/tests/ref/seek/acodec-adpcm-swf-trellis b/tests/ref/seek/acodec-adpcm-swf-trellis new file mode 100644 index 000000000..2f9091325 --- /dev/null +++ b/tests/ref/seek/acodec-adpcm-swf-trellis @@ -0,0 +1,49 @@ +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 208 size: 2053 +ret: 0 st:-1 flags:0 ts:-1.000000 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 208 size: 2053 +ret: 0 st:-1 flags:1 ts: 1.894167 +ret: 0 st: 0 flags:1 dts: 1.858000 pts: 1.858000 pos: 82968 size: 2053 +ret: 0 st: 0 flags:0 ts: 0.788000 +ret: 0 st: 0 flags:1 dts: 0.789000 pts: 0.789000 pos: 35381 size: 2053 +ret:-1 st: 0 flags:1 ts:-0.317000 +ret: 0 st:-1 flags:0 ts: 2.576668 +ret: 0 st: 0 flags:1 dts: 2.601000 pts: 2.601000 pos: 116072 size: 2053 +ret: 0 st:-1 flags:1 ts: 1.470835 +ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 64347 size: 2053 +ret: 0 st: 0 flags:0 ts: 0.365000 +ret: 0 st: 0 flags:1 dts: 0.372000 pts: 0.372000 pos: 16760 size: 2053 +ret:-1 st: 0 flags:1 ts:-0.741000 +ret: 0 st:-1 flags:0 ts: 2.153336 +ret: 0 st: 0 flags:1 dts: 2.183000 pts: 2.183000 pos: 97451 size: 2053 +ret: 0 st:-1 flags:1 ts: 1.047503 +ret: 0 st: 0 flags:1 dts: 1.022000 pts: 1.022000 pos: 45726 size: 2053 +ret: 0 st: 0 flags:0 ts:-0.058000 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 208 size: 2053 +ret: 0 st: 0 flags:1 ts: 2.836000 +ret: 0 st: 0 flags:1 dts: 2.833000 pts: 2.833000 pos: 126417 size: 2053 +ret: 0 st:-1 flags:0 ts: 1.730004 +ret: 0 st: 0 flags:1 dts: 1.765000 pts: 1.765000 pos: 78830 size: 2053 +ret: 0 st:-1 flags:1 ts: 0.624171 +ret: 0 st: 0 flags:1 dts: 0.604000 pts: 0.604000 pos: 27105 size: 2053 +ret: 0 st: 0 flags:0 ts:-0.482000 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 208 size: 2053 +ret: 0 st: 0 flags:1 ts: 2.413000 +ret: 0 st: 0 flags:1 dts: 2.368000 pts: 2.368000 pos: 105727 size: 2053 +ret: 0 st:-1 flags:0 ts: 1.306672 +ret: 0 st: 0 flags:1 dts: 1.347000 pts: 1.347000 pos: 60209 size: 2053 +ret: 0 st:-1 flags:1 ts: 0.200839 +ret: 0 st: 0 flags:1 dts: 0.186000 pts: 0.186000 pos: 8484 size: 2053 +ret: 0 st: 0 flags:0 ts:-0.905000 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 208 size: 2053 +ret: 0 st: 0 flags:1 ts: 1.989000 +ret: 0 st: 0 flags:1 dts: 1.950000 pts: 1.950000 pos: 87106 size: 2053 +ret: 0 st:-1 flags:0 ts: 0.883340 +ret: 0 st: 0 flags:1 dts: 0.929000 pts: 0.929000 pos: 41588 size: 2053 +ret:-1 st:-1 flags:1 ts:-0.222493 +ret: 0 st: 0 flags:0 ts: 2.672000 +ret: 0 st: 0 flags:1 dts: 2.694000 pts: 2.694000 pos: 120210 size: 2053 +ret: 0 st: 0 flags:1 ts: 1.566000 +ret: 0 st: 0 flags:1 dts: 1.533000 pts: 1.533000 pos: 68485 size: 2053 +ret: 0 st:-1 flags:0 ts: 0.460008 +ret: 0 st: 0 flags:1 dts: 0.464000 pts: 0.464000 pos: 20898 size: 2053 +ret:-1 st:-1 flags:1 ts:-0.645825 diff --git a/tests/ref/seek/acodec-adpcm-yamaha-trellis b/tests/ref/seek/acodec-adpcm-yamaha-trellis new file mode 100644 index 000000000..5cbfaed73 --- /dev/null +++ b/tests/ref/seek/acodec-adpcm-yamaha-trellis @@ -0,0 +1,53 @@ +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 58 size: 4096 +ret: 0 st:-1 flags:0 ts:-1.000000 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 58 size: 4096 +ret: 0 st:-1 flags:1 ts: 1.894167 +ret: 0 st: 0 flags:1 dts: 1.856009 pts: 1.856009 pos: 29754 size: 4096 +ret: 0 st: 0 flags:0 ts: 0.788345 +ret: 0 st: 0 flags:1 dts: 0.831995 pts: 0.831995 pos: 13370 size: 4096 +ret: 0 st: 0 flags:1 ts:-0.317506 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 58 size: 4096 +ret: 0 st:-1 flags:0 ts: 2.576668 +ret: 0 st: 0 flags:1 dts: 2.623991 pts: 2.623991 pos: 42042 size: 4096 +ret: 0 st:-1 flags:1 ts: 1.470835 +ret: 0 st: 0 flags:1 dts: 1.408005 pts: 1.408005 pos: 22586 size: 4096 +ret: 0 st: 0 flags:0 ts: 0.365011 +ret: 0 st: 0 flags:1 dts: 0.383991 pts: 0.383991 pos: 6202 size: 4096 +ret: 0 st: 0 flags:1 ts:-0.740839 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 58 size: 4096 +ret: 0 st:-1 flags:0 ts: 2.153336 +ret: 0 st: 0 flags:1 dts: 2.176009 pts: 2.176009 pos: 34874 size: 4096 +ret: 0 st:-1 flags:1 ts: 1.047503 +ret: 0 st: 0 flags:1 dts: 1.023991 pts: 1.023991 pos: 16442 size: 4096 +ret: 0 st: 0 flags:0 ts:-0.058322 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 58 size: 4096 +ret: 0 st: 0 flags:1 ts: 2.835828 +ret: 0 st: 0 flags:1 dts: 2.816009 pts: 2.816009 pos: 45114 size: 4096 +ret: 0 st:-1 flags:0 ts: 1.730004 +ret: 0 st: 0 flags:1 dts: 1.791995 pts: 1.791995 pos: 28730 size: 4096 +ret: 0 st:-1 flags:1 ts: 0.624171 +ret: 0 st: 0 flags:1 dts: 0.576009 pts: 0.576009 pos: 9274 size: 4096 +ret: 0 st: 0 flags:0 ts:-0.481655 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 58 size: 4096 +ret: 0 st: 0 flags:1 ts: 2.412494 +ret: 0 st: 0 flags:1 dts: 2.368005 pts: 2.368005 pos: 37946 size: 4096 +ret: 0 st:-1 flags:0 ts: 1.306672 +ret: 0 st: 0 flags:1 dts: 1.343991 pts: 1.343991 pos: 21562 size: 4096 +ret: 0 st:-1 flags:1 ts: 0.200839 +ret: 0 st: 0 flags:1 dts: 0.191995 pts: 0.191995 pos: 3130 size: 4096 +ret: 0 st: 0 flags:0 ts:-0.904989 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 58 size: 4096 +ret: 0 st: 0 flags:1 ts: 1.989184 +ret: 0 st: 0 flags:1 dts: 1.983991 pts: 1.983991 pos: 31802 size: 4096 +ret: 0 st:-1 flags:0 ts: 0.883340 +ret: 0 st: 0 flags:1 dts: 0.896009 pts: 0.896009 pos: 14394 size: 4096 +ret: 0 st:-1 flags:1 ts:-0.222493 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 58 size: 4096 +ret: 0 st: 0 flags:0 ts: 2.671678 +ret: 0 st: 0 flags:1 dts: 2.688005 pts: 2.688005 pos: 43066 size: 4096 +ret: 0 st: 0 flags:1 ts: 1.565850 +ret: 0 st: 0 flags:1 dts: 1.536009 pts: 1.536009 pos: 24634 size: 4096 +ret: 0 st:-1 flags:0 ts: 0.460008 +ret: 0 st: 0 flags:1 dts: 0.511995 pts: 0.511995 pos: 8250 size: 4096 +ret: 0 st:-1 flags:1 ts:-0.645825 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 58 size: 4096 diff --git a/tests/ref/seek/acodec-flac b/tests/ref/seek/acodec-flac index ab31891f1..f6add9abd 100644 --- a/tests/ref/seek/acodec-flac +++ b/tests/ref/seek/acodec-flac @@ -5,14 +5,16 @@ ret: 0 st:-1 flags:1 ts: 1.894167 ret: 0 st: 0 flags:1 dts: 1.880816 pts: 1.880816 pos: 86742 size: 2191 ret: 0 st: 0 flags:0 ts: 0.788345 ret: 0 st: 0 flags:1 dts: 0.809796 pts: 0.809796 pos: 27366 size: 615 -ret:-1 st: 0 flags:1 ts:-0.317506 +ret: 0 st: 0 flags:1 ts:-0.317506 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 8256 size: 614 ret: 0 st:-1 flags:0 ts: 2.576668 ret: 0 st: 0 flags:1 dts: 2.586122 pts: 2.586122 pos: 145606 size: 2384 ret: 0 st:-1 flags:1 ts: 1.470835 ret: 0 st: 0 flags:1 dts: 1.462857 pts: 1.462857 pos: 53388 size: 1851 ret: 0 st: 0 flags:0 ts: 0.365011 ret: 0 st: 0 flags:1 dts: 0.365714 pts: 0.365714 pos: 16890 size: 614 -ret:-1 st: 0 flags:1 ts:-0.740839 +ret: 0 st: 0 flags:1 ts:-0.740839 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 8256 size: 614 ret: 0 st:-1 flags:0 ts: 2.153336 ret: 0 st: 0 flags:1 dts: 2.168163 pts: 2.168163 pos: 110531 size: 2143 ret: 0 st:-1 flags:1 ts: 1.047503 @@ -39,11 +41,13 @@ ret: 0 st: 0 flags:1 ts: 1.989184 ret: 0 st: 0 flags:1 dts: 1.985306 pts: 1.985306 pos: 95508 size: 2169 ret: 0 st:-1 flags:0 ts: 0.883340 ret: 0 st: 0 flags:1 dts: 0.888163 pts: 0.888163 pos: 29211 size: 620 -ret:-1 st:-1 flags:1 ts:-0.222493 +ret: 0 st:-1 flags:1 ts:-0.222493 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 8256 size: 614 ret: 0 st: 0 flags:0 ts: 2.671678 ret: 0 st: 0 flags:1 dts: 2.690612 pts: 2.690612 pos: 155154 size: 2394 ret: 0 st: 0 flags:1 ts: 1.565850 ret: 0 st: 0 flags:1 dts: 1.541224 pts: 1.541224 pos: 59082 size: 1974 ret: 0 st:-1 flags:0 ts: 0.460008 ret: 0 st: 0 flags:1 dts: 0.470204 pts: 0.470204 pos: 19353 size: 608 -ret:-1 st:-1 flags:1 ts:-0.645825 +ret: 0 st:-1 flags:1 ts:-0.645825 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 8256 size: 614 diff --git a/tests/ref/seek/acodec-pcm-s16le b/tests/ref/seek/acodec-pcm-s16le index 4f1ffc5ac..41acc98d8 100644 --- a/tests/ref/seek/acodec-pcm-s16le +++ b/tests/ref/seek/acodec-pcm-s16le @@ -1,53 +1,53 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 1.894172 pts: 1.894172 pos: 334178 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.894172 pts: 1.894172 pos: 334176 size: 4096 ret: 0 st: 0 flags:0 ts: 0.788345 -ret: 0 st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos: 139110 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos: 139108 size: 4096 ret: 0 st: 0 flags:1 ts:-0.317506 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st:-1 flags:0 ts: 2.576668 -ret: 0 st: 0 flags:1 dts: 2.576667 pts: 2.576667 pos: 454570 size: 4096 +ret: 0 st: 0 flags:1 dts: 2.576667 pts: 2.576667 pos: 454568 size: 4096 ret: 0 st:-1 flags:1 ts: 1.470835 -ret: 0 st: 0 flags:1 dts: 1.470839 pts: 1.470839 pos: 259502 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.470839 pts: 1.470839 pos: 259500 size: 4096 ret: 0 st: 0 flags:0 ts: 0.365011 -ret: 0 st: 0 flags:1 dts: 0.365011 pts: 0.365011 pos: 64434 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.365011 pts: 0.365011 pos: 64432 size: 4096 ret: 0 st: 0 flags:1 ts:-0.740839 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st:-1 flags:0 ts: 2.153336 -ret: 0 st: 0 flags:1 dts: 2.153333 pts: 2.153333 pos: 379894 size: 4096 +ret: 0 st: 0 flags:1 dts: 2.153333 pts: 2.153333 pos: 379892 size: 4096 ret: 0 st:-1 flags:1 ts: 1.047503 -ret: 0 st: 0 flags:1 dts: 1.047506 pts: 1.047506 pos: 184826 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.047506 pts: 1.047506 pos: 184824 size: 4096 ret: 0 st: 0 flags:0 ts:-0.058322 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st: 0 flags:1 ts: 2.835828 -ret: 0 st: 0 flags:1 dts: 2.835828 pts: 2.835828 pos: 500286 size: 4096 +ret: 0 st: 0 flags:1 dts: 2.835828 pts: 2.835828 pos: 500284 size: 4096 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 1.730000 pts: 1.730000 pos: 305218 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.730000 pts: 1.730000 pos: 305216 size: 4096 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.624172 pts: 0.624172 pos: 110150 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.624172 pts: 0.624172 pos: 110148 size: 4096 ret: 0 st: 0 flags:0 ts:-0.481655 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st: 0 flags:1 ts: 2.412494 -ret: 0 st: 0 flags:1 dts: 2.412494 pts: 2.412494 pos: 425610 size: 4096 +ret: 0 st: 0 flags:1 dts: 2.412494 pts: 2.412494 pos: 425608 size: 4096 ret: 0 st:-1 flags:0 ts: 1.306672 -ret: 0 st: 0 flags:1 dts: 1.306667 pts: 1.306667 pos: 230542 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.306667 pts: 1.306667 pos: 230540 size: 4096 ret: 0 st:-1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.200839 pts: 0.200839 pos: 35474 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.200839 pts: 0.200839 pos: 35472 size: 4096 ret: 0 st: 0 flags:0 ts:-0.904989 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st: 0 flags:1 ts: 1.989184 -ret: 0 st: 0 flags:1 dts: 1.989184 pts: 1.989184 pos: 350938 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.989184 pts: 1.989184 pos: 350936 size: 4096 ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.883333 pts: 0.883333 pos: 155866 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.883333 pts: 0.883333 pos: 155864 size: 4096 ret: 0 st:-1 flags:1 ts:-0.222493 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st: 0 flags:0 ts: 2.671678 -ret: 0 st: 0 flags:1 dts: 2.671678 pts: 2.671678 pos: 471330 size: 4096 +ret: 0 st: 0 flags:1 dts: 2.671678 pts: 2.671678 pos: 471328 size: 4096 ret: 0 st: 0 flags:1 ts: 1.565850 -ret: 0 st: 0 flags:1 dts: 1.565850 pts: 1.565850 pos: 276262 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.565850 pts: 1.565850 pos: 276260 size: 4096 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.460000 pts: 0.460000 pos: 81190 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.460000 pts: 0.460000 pos: 81188 size: 4096 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 diff --git a/tests/ref/seek/acodec-pcm-u8 b/tests/ref/seek/acodec-pcm-u8 index 834891643..afa33519d 100644 --- a/tests/ref/seek/acodec-pcm-u8 +++ b/tests/ref/seek/acodec-pcm-u8 @@ -1,53 +1,53 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 1.894172 pts: 1.894172 pos: 167112 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.894172 pts: 1.894172 pos: 167110 size: 4096 ret: 0 st: 0 flags:0 ts: 0.788345 -ret: 0 st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos: 69578 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos: 69576 size: 4096 ret: 0 st: 0 flags:1 ts:-0.317506 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st:-1 flags:0 ts: 2.576668 -ret: 0 st: 0 flags:1 dts: 2.576667 pts: 2.576667 pos: 227308 size: 4096 +ret: 0 st: 0 flags:1 dts: 2.576667 pts: 2.576667 pos: 227306 size: 4096 ret: 0 st:-1 flags:1 ts: 1.470835 -ret: 0 st: 0 flags:1 dts: 1.470839 pts: 1.470839 pos: 129774 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.470839 pts: 1.470839 pos: 129772 size: 4096 ret: 0 st: 0 flags:0 ts: 0.365011 -ret: 0 st: 0 flags:1 dts: 0.365011 pts: 0.365011 pos: 32240 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.365011 pts: 0.365011 pos: 32238 size: 4096 ret: 0 st: 0 flags:1 ts:-0.740839 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st:-1 flags:0 ts: 2.153336 -ret: 0 st: 0 flags:1 dts: 2.153333 pts: 2.153333 pos: 189970 size: 4096 +ret: 0 st: 0 flags:1 dts: 2.153333 pts: 2.153333 pos: 189968 size: 4096 ret: 0 st:-1 flags:1 ts: 1.047503 -ret: 0 st: 0 flags:1 dts: 1.047506 pts: 1.047506 pos: 92436 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.047506 pts: 1.047506 pos: 92434 size: 4096 ret: 0 st: 0 flags:0 ts:-0.058322 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st: 0 flags:1 ts: 2.835828 -ret: 0 st: 0 flags:1 dts: 2.835828 pts: 2.835828 pos: 250166 size: 4096 +ret: 0 st: 0 flags:1 dts: 2.835828 pts: 2.835828 pos: 250164 size: 4096 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 1.730000 pts: 1.730000 pos: 152632 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.730000 pts: 1.730000 pos: 152630 size: 4096 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.624172 pts: 0.624172 pos: 55098 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.624172 pts: 0.624172 pos: 55096 size: 4096 ret: 0 st: 0 flags:0 ts:-0.481655 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st: 0 flags:1 ts: 2.412494 -ret: 0 st: 0 flags:1 dts: 2.412494 pts: 2.412494 pos: 212828 size: 4096 +ret: 0 st: 0 flags:1 dts: 2.412494 pts: 2.412494 pos: 212826 size: 4096 ret: 0 st:-1 flags:0 ts: 1.306672 -ret: 0 st: 0 flags:1 dts: 1.306667 pts: 1.306667 pos: 115294 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.306667 pts: 1.306667 pos: 115292 size: 4096 ret: 0 st:-1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.200839 pts: 0.200839 pos: 17760 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.200839 pts: 0.200839 pos: 17758 size: 4096 ret: 0 st: 0 flags:0 ts:-0.904989 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st: 0 flags:1 ts: 1.989184 -ret: 0 st: 0 flags:1 dts: 1.989184 pts: 1.989184 pos: 175492 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.989184 pts: 1.989184 pos: 175490 size: 4096 ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.883333 pts: 0.883333 pos: 77956 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.883333 pts: 0.883333 pos: 77954 size: 4096 ret: 0 st:-1 flags:1 ts:-0.222493 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 ret: 0 st: 0 flags:0 ts: 2.671678 -ret: 0 st: 0 flags:1 dts: 2.671678 pts: 2.671678 pos: 235688 size: 4096 +ret: 0 st: 0 flags:1 dts: 2.671678 pts: 2.671678 pos: 235686 size: 4096 ret: 0 st: 0 flags:1 ts: 1.565850 -ret: 0 st: 0 flags:1 dts: 1.565850 pts: 1.565850 pos: 138154 size: 4096 +ret: 0 st: 0 flags:1 dts: 1.565850 pts: 1.565850 pos: 138152 size: 4096 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.460000 pts: 0.460000 pos: 40618 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.460000 pts: 0.460000 pos: 40616 size: 4096 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 46 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 44 size: 4096 diff --git a/tests/ref/seek/lavf-asf b/tests/ref/seek/lavf-asf index 9a1489551..b64bec3ac 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: 689 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 693 size: 208 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 689 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 693 size: 208 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147889 size: 209 +ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147893 size: 209 ret: 0 st: 0 flags:0 ts: 0.788000 -ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147889 size: 209 +ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147893 size: 209 ret: 0 st: 0 flags:1 ts:-0.317000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 689 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 693 size: 208 ret: 0 st: 1 flags:0 ts: 2.577000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330289 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330293 size: 209 ret: 0 st: 1 flags:1 ts: 1.471000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330289 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330293 size: 209 ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147889 size: 209 +ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147893 size: 209 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 689 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 693 size: 208 ret: 0 st: 0 flags:0 ts: 2.153000 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301489 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301493 size: 209 ret: 0 st: 0 flags:1 ts: 1.048000 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301489 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301493 size: 209 ret: 0 st: 1 flags:0 ts:-0.058000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 689 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 693 size: 208 ret: 0 st: 1 flags:1 ts: 2.836000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330289 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330293 size: 209 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301489 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301493 size: 209 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 689 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 693 size: 208 ret: 0 st: 0 flags:0 ts:-0.482000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 689 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 693 size: 208 ret: 0 st: 0 flags:1 ts: 2.413000 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301489 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301493 size: 209 ret: 0 st: 1 flags:0 ts: 1.307000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330289 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330293 size: 209 ret: 0 st: 1 flags:1 ts: 0.201000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 689 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 693 size: 208 ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 689 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 693 size: 208 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301489 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301493 size: 209 ret: 0 st: 0 flags:0 ts: 0.883000 -ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147889 size: 209 +ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147893 size: 209 ret: 0 st: 0 flags:1 ts:-0.222000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 689 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 693 size: 208 ret: 0 st: 1 flags:0 ts: 2.672000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330289 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330293 size: 209 ret: 0 st: 1 flags:1 ts: 1.566000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330289 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330293 size: 209 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147889 size: 209 +ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147893 size: 209 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 689 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 693 size: 208 diff --git a/tests/ref/seek/lavf-mkv b/tests/ref/seek/lavf-mkv index bf6cab0ac..11275d6e4 100644 --- a/tests/ref/seek/lavf-mkv +++ b/tests/ref/seek/lavf-mkv @@ -1,48 +1,48 @@ -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 537 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 661 size: 208 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 753 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 877 size: 27837 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292167 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291 size: 27834 ret: 0 st: 0 flags:0 ts: 0.788000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292167 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291 size: 27834 ret: 0 st: 0 flags:1 ts:-0.317000 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 753 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 877 size: 27837 ret:-1 st: 1 flags:0 ts: 2.577000 ret: 0 st: 1 flags:1 ts: 1.471000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320008 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320132 size: 209 ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146720 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146844 size: 27925 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 753 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 877 size: 27837 ret:-1 st: 0 flags:0 ts: 2.153000 ret: 0 st: 0 flags:1 ts: 1.048000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292167 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291 size: 27834 ret: 0 st: 1 flags:0 ts:-0.058000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 537 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 661 size: 208 ret: 0 st: 1 flags:1 ts: 2.836000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320008 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320132 size: 209 ret:-1 st:-1 flags:0 ts: 1.730004 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146720 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146844 size: 27925 ret: 0 st: 0 flags:0 ts:-0.482000 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 753 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 877 size: 27837 ret: 0 st: 0 flags:1 ts: 2.413000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292167 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291 size: 27834 ret:-1 st: 1 flags:0 ts: 1.307000 ret: 0 st: 1 flags:1 ts: 0.201000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 537 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 661 size: 208 ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 753 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 877 size: 27837 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292167 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291 size: 27834 ret: 0 st: 0 flags:0 ts: 0.883000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292167 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291 size: 27834 ret: 0 st: 0 flags:1 ts:-0.222000 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 753 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 877 size: 27837 ret:-1 st: 1 flags:0 ts: 2.672000 ret: 0 st: 1 flags:1 ts: 1.566000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320008 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320132 size: 209 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146720 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146844 size: 27925 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 753 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 877 size: 27837 diff --git a/tests/ref/seek/lavf-mov b/tests/ref/seek/lavf-mov index 93a9a2342..27ea7c773 100644 --- a/tests/ref/seek/lavf-mov +++ b/tests/ref/seek/lavf-mov @@ -1,48 +1,48 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1739 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1767 size: 27837 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1739 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1767 size: 27837 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 1 flags:1 dts: 0.952018 pts: 0.952018 pos: 326943 size: 1024 +ret: 0 st: 1 flags:1 dts: 0.952018 pts: 0.952018 pos: 326971 size: 1024 ret: 0 st: 0 flags:0 ts: 0.788359 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 327967 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 327995 size: 27834 ret: 0 st: 0 flags:1 ts:-0.317500 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1739 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1767 size: 27837 ret:-1 st: 1 flags:0 ts: 2.576667 ret: 0 st: 1 flags:1 ts: 1.470839 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 327967 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 327995 size: 27834 ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 165221 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 165249 size: 27925 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1739 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1767 size: 27837 ret:-1 st: 0 flags:0 ts: 2.153359 ret: 0 st: 0 flags:1 ts: 1.047500 -ret: 0 st: 1 flags:1 dts: 0.952018 pts: 0.952018 pos: 326943 size: 1024 +ret: 0 st: 1 flags:1 dts: 0.952018 pts: 0.952018 pos: 326971 size: 1024 ret: 0 st: 1 flags:0 ts:-0.058322 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1739 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1767 size: 27837 ret: 0 st: 1 flags:1 ts: 2.835828 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 327967 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 327995 size: 27834 ret:-1 st:-1 flags:0 ts: 1.730004 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 1 flags:1 dts: 0.464399 pts: 0.464399 pos: 164197 size: 1024 +ret: 0 st: 1 flags:1 dts: 0.464399 pts: 0.464399 pos: 164225 size: 1024 ret: 0 st: 0 flags:0 ts:-0.481641 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1739 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1767 size: 27837 ret: 0 st: 0 flags:1 ts: 2.412500 -ret: 0 st: 1 flags:1 dts: 0.952018 pts: 0.952018 pos: 326943 size: 1024 +ret: 0 st: 1 flags:1 dts: 0.952018 pts: 0.952018 pos: 326971 size: 1024 ret:-1 st: 1 flags:0 ts: 1.306667 ret: 0 st: 1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1739 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1767 size: 27837 ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1739 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1767 size: 27837 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 1 flags:1 dts: 0.952018 pts: 0.952018 pos: 326943 size: 1024 +ret: 0 st: 1 flags:1 dts: 0.952018 pts: 0.952018 pos: 326971 size: 1024 ret: 0 st: 0 flags:0 ts: 0.883359 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 327967 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 327995 size: 27834 ret: 0 st: 0 flags:1 ts:-0.222500 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1739 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1767 size: 27837 ret:-1 st: 1 flags:0 ts: 2.671678 ret: 0 st: 1 flags:1 ts: 1.565850 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 327967 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 327995 size: 27834 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 165221 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 165249 size: 27925 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1739 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 1767 size: 27837 diff --git a/tests/ref/seek/lavf-nut b/tests/ref/seek/lavf-nut index ef47ceb5f..b2da52629 100644 --- a/tests/ref/seek/lavf-nut +++ b/tests/ref/seek/lavf-nut @@ -1,53 +1,53 @@ -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 339 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 395 size: 208 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 567 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 623 size: 27837 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146434 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146490 size: 27925 ret: 0 st: 0 flags:0 ts: 0.788340 -ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146434 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146490 size: 27925 ret: 0 st: 0 flags:1 ts:-0.317500 -ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 567 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 623 size: 27837 ret: 0 st: 1 flags:0 ts: 2.576667 -ret: 0 st: 1 flags:1 dts: 0.862041 pts: 0.862041 pos: 271259 size: 209 +ret: 0 st: 1 flags:1 dts: 0.862041 pts: 0.862041 pos: 271315 size: 209 ret: 0 st: 1 flags:1 ts: 1.470839 -ret: 0 st: 1 flags:1 dts: 0.862041 pts: 0.862041 pos: 271259 size: 209 +ret: 0 st: 1 flags:1 dts: 0.862041 pts: 0.862041 pos: 271315 size: 209 ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146434 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146490 size: 27925 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 567 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 623 size: 27837 ret: 0 st: 0 flags:0 ts: 2.153340 -ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146434 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146490 size: 27925 ret: 0 st: 0 flags:1 ts: 1.047500 -ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146434 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146490 size: 27925 ret: 0 st: 1 flags:0 ts:-0.058322 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 339 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 395 size: 208 ret: 0 st: 1 flags:1 ts: 2.835828 -ret: 0 st: 1 flags:1 dts: 0.862041 pts: 0.862041 pos: 271259 size: 209 +ret: 0 st: 1 flags:1 dts: 0.862041 pts: 0.862041 pos: 271315 size: 209 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146434 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146490 size: 27925 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146434 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146490 size: 27925 ret: 0 st: 0 flags:0 ts:-0.481660 -ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 567 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 623 size: 27837 ret: 0 st: 0 flags:1 ts: 2.412500 -ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146434 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146490 size: 27925 ret: 0 st: 1 flags:0 ts: 1.306667 -ret: 0 st: 1 flags:1 dts: 0.862041 pts: 0.862041 pos: 271259 size: 209 +ret: 0 st: 1 flags:1 dts: 0.862041 pts: 0.862041 pos: 271315 size: 209 ret: 0 st: 1 flags:1 ts: 0.200839 -ret: 0 st: 1 flags:1 dts: 0.182857 pts: 0.182857 pos: 71901 size: 209 +ret: 0 st: 1 flags:1 dts: 0.182857 pts: 0.182857 pos: 71957 size: 209 ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 567 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 623 size: 27837 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146434 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146490 size: 27925 ret: 0 st: 0 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146434 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146490 size: 27925 ret: 0 st: 0 flags:1 ts:-0.222500 -ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 567 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 623 size: 27837 ret: 0 st: 1 flags:0 ts: 2.671678 -ret: 0 st: 1 flags:1 dts: 0.862041 pts: 0.862041 pos: 271259 size: 209 +ret: 0 st: 1 flags:1 dts: 0.862041 pts: 0.862041 pos: 271315 size: 209 ret: 0 st: 1 flags:1 ts: 1.565850 -ret: 0 st: 1 flags:1 dts: 0.862041 pts: 0.862041 pos: 271259 size: 209 +ret: 0 st: 1 flags:1 dts: 0.862041 pts: 0.862041 pos: 271315 size: 209 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146434 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.490918 pts: 0.490918 pos: 146490 size: 27925 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 567 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.010918 pts: 0.010918 pos: 623 size: 27837 diff --git a/tests/ref/seek/lavf-ogg b/tests/ref/seek/lavf-ogg index 583526ef5..caf487907 100644 --- a/tests/ref/seek/lavf-ogg +++ b/tests/ref/seek/lavf-ogg @@ -1,53 +1,53 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st: 0 flags:0 ts: 0.788345 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st: 0 flags:1 ts:-0.317506 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:0 ts: 2.576668 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:1 ts: 1.470835 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st: 0 flags:0 ts: 0.365011 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st: 0 flags:1 ts:-0.740839 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:0 ts: 2.153336 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:1 ts: 1.047503 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st: 0 flags:0 ts:-0.058322 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st: 0 flags:1 ts: 2.835828 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st: 0 flags:0 ts:-0.481655 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st: 0 flags:1 ts: 2.412494 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:0 ts: 1.306672 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st: 0 flags:0 ts:-0.904989 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st: 0 flags:1 ts: 1.989184 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:1 ts:-0.222493 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st: 0 flags:0 ts: 2.671678 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st: 0 flags:1 ts: 1.565850 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 143 size: 1364 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 164 size: 1364 diff --git a/tests/ref/seek/lavf-wav b/tests/ref/seek/lavf-wav index 16a33bec7..ed2f8d62d 100644 --- a/tests/ref/seek/lavf-wav +++ b/tests/ref/seek/lavf-wav @@ -1,53 +1,53 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 76 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 74 size: 4096 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 76 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 74 size: 4096 ret: 0 st:-1 flags:1 ts: 1.894167 ret:-EOF ret: 0 st: 0 flags:0 ts: 0.788345 -ret: 0 st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos: 69608 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos: 69606 size: 4096 ret: 0 st: 0 flags:1 ts:-0.317506 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 76 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 74 size: 4096 ret: 0 st:-1 flags:0 ts: 2.576668 ret:-EOF ret: 0 st:-1 flags:1 ts: 1.470835 ret:-EOF ret: 0 st: 0 flags:0 ts: 0.365011 -ret: 0 st: 0 flags:1 dts: 0.365011 pts: 0.365011 pos: 32270 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.365011 pts: 0.365011 pos: 32268 size: 4096 ret: 0 st: 0 flags:1 ts:-0.740839 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 76 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 74 size: 4096 ret: 0 st:-1 flags:0 ts: 2.153336 ret:-EOF ret: 0 st:-1 flags:1 ts: 1.047503 ret:-EOF ret: 0 st: 0 flags:0 ts:-0.058322 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 76 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 74 size: 4096 ret: 0 st: 0 flags:1 ts: 2.835828 ret:-EOF 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.624172 pts: 0.624172 pos: 55128 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.624172 pts: 0.624172 pos: 55126 size: 4096 ret: 0 st: 0 flags:0 ts:-0.481655 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 76 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 74 size: 4096 ret: 0 st: 0 flags:1 ts: 2.412494 ret:-EOF ret: 0 st:-1 flags:0 ts: 1.306672 ret:-EOF ret: 0 st:-1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.200839 pts: 0.200839 pos: 17790 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.200839 pts: 0.200839 pos: 17788 size: 4096 ret: 0 st: 0 flags:0 ts:-0.904989 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 76 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 74 size: 4096 ret: 0 st: 0 flags:1 ts: 1.989184 ret:-EOF ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.883333 pts: 0.883333 pos: 77986 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.883333 pts: 0.883333 pos: 77984 size: 4096 ret: 0 st:-1 flags:1 ts:-0.222493 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 76 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 74 size: 4096 ret: 0 st: 0 flags:0 ts: 2.671678 ret:-EOF ret: 0 st: 0 flags:1 ts: 1.565850 ret:-EOF ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.460000 pts: 0.460000 pos: 40648 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.460000 pts: 0.460000 pos: 40646 size: 4096 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 76 size: 4096 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 74 size: 4096 diff --git a/tests/ref/seek/lavf-wtv b/tests/ref/seek/lavf-wtv index 2808c109a..355ab98d8 100644 --- a/tests/ref/seek/lavf-wtv +++ b/tests/ref/seek/lavf-wtv @@ -1,48 +1,48 @@ -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294688 size: 209 +ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294672 size: 209 ret: 0 st: 0 flags:0 ts: 0.788334 -ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294688 size: 209 +ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294672 size: 209 ret: 0 st: 0 flags:1 ts:-0.317499 -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 ret:-1 st: 1 flags:0 ts: 2.576668 ret: 0 st: 1 flags:1 ts: 1.470835 -ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294688 size: 209 +ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294672 size: 209 ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 ret:-1 st: 0 flags:0 ts: 2.153336 ret: 0 st: 0 flags:1 ts: 1.047503 -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 ret: 0 st: 1 flags:0 ts:-0.058330 -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 ret: 0 st: 1 flags:1 ts: 2.835837 -ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294688 size: 209 +ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294672 size: 209 ret:-1 st:-1 flags:0 ts: 1.730004 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 ret: 0 st: 0 flags:0 ts:-0.481662 -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 ret: 0 st: 0 flags:1 ts: 2.412505 -ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294688 size: 209 +ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294672 size: 209 ret:-1 st: 1 flags:0 ts: 1.306672 ret: 0 st: 1 flags:1 ts: 0.200839 -ret: 0 st: 1 flags:1 dts: 0.211950 pts: 0.211950 pos: 99296 size: 209 +ret: 0 st: 1 flags:1 dts: 0.211950 pts: 0.211950 pos: 99280 size: 209 ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294688 size: 209 +ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294672 size: 209 ret: 0 st: 0 flags:0 ts: 0.883340 -ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294688 size: 209 +ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294672 size: 209 ret: 0 st: 0 flags:1 ts:-0.222493 -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 ret:-1 st: 1 flags:0 ts: 2.671674 ret: 0 st: 1 flags:1 ts: 1.565841 -ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294688 size: 209 +ret: 0 st: 1 flags:1 dts: 0.734399 pts: 0.734399 pos: 294672 size: 209 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26288 size: 208 +ret: 0 st: 1 flags:1 dts: 0.029093 pts: 0.029093 pos: 26272 size: 208 diff --git a/tests/ref/seek/vsynth2-huffyuv b/tests/ref/seek/vsynth2-huffyuv index 69a37f559..ad01899f0 100644 --- a/tests/ref/seek/vsynth2-huffyuv +++ b/tests/ref/seek/vsynth2-huffyuv @@ -1,46 +1,46 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5724 size:129760 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5754 size:123508 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5724 size:129760 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5754 size:123508 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 1.880000 pts: 1.880000 pos:6069172 size:128520 +ret: 0 st: 0 flags:1 dts: 1.880000 pts: 1.880000 pos:5744998 size:121152 ret: 0 st: 0 flags:0 ts: 0.800000 -ret: 0 st: 0 flags:1 dts: 0.800000 pts: 0.800000 pos:2579612 size:129192 +ret: 0 st: 0 flags:1 dts: 0.800000 pts: 0.800000 pos:2437994 size:122516 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.480000 pts: 1.480000 pos:4778228 size:129424 +ret: 0 st: 0 flags:1 dts: 1.480000 pts: 1.480000 pos:4523454 size:122784 ret: 0 st: 0 flags:0 ts: 0.360000 -ret: 0 st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos:1160248 size:128504 +ret: 0 st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos:1093870 size:121320 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: 1.040000 pts: 1.040000 pos:3355284 size:129424 +ret: 0 st: 0 flags:1 dts: 1.040000 pts: 1.040000 pos:3173590 size:122784 ret: 0 st: 0 flags:0 ts:-0.040000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5724 size:129760 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5754 size:123508 ret: 0 st: 0 flags:1 ts: 2.840000 -ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:6326124 size:128288 +ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:5987030 size:120672 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 1.720000 pts: 1.720000 pos:5553996 size:129016 +ret: 0 st: 0 flags:1 dts: 1.720000 pts: 1.720000 pos:5258650 size:121992 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.640000 pts: 0.640000 pos:2062492 size:129204 +ret: 0 st: 0 flags:1 dts: 0.640000 pts: 0.640000 pos:1947350 size:122568 ret: 0 st: 0 flags:0 ts:-0.480000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5724 size:129760 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5754 size:123508 ret: 0 st: 0 flags:1 ts: 2.400000 -ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:6326124 size:128288 +ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:5987030 size:120672 ret: 0 st:-1 flags:0 ts: 1.306672 -ret: 0 st: 0 flags:1 dts: 1.320000 pts: 1.320000 pos:4260860 size:129280 +ret: 0 st: 0 flags:1 dts: 1.320000 pts: 1.320000 pos:4032694 size:122544 ret: 0 st:-1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.200000 pts: 0.200000 pos: 646908 size:128204 +ret: 0 st: 0 flags:1 dts: 0.200000 pts: 0.200000 pos: 609906 size:120724 ret: 0 st: 0 flags:0 ts:-0.920000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5724 size:129760 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5754 size:123508 ret: 0 st: 0 flags:1 ts: 2.000000 -ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:6326124 size:128288 +ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:5987030 size:120672 ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.880000 pts: 0.880000 pos:2838068 size:129268 +ret: 0 st: 0 flags:1 dts: 0.880000 pts: 0.880000 pos:2683062 size:122588 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.560000 pts: 1.560000 pos:5037024 size:129284 +ret: 0 st: 0 flags:1 dts: 1.560000 pts: 1.560000 pos:4768978 size:122556 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos:1546172 size:128860 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos:1458406 size:121888 ret:-1 st:-1 flags:1 ts:-0.645825 diff --git a/tests/ref/seek/vsynth2-mpeg4-nsse b/tests/ref/seek/vsynth2-mpeg4-nsse new file mode 100644 index 000000000..8e2a95f27 --- /dev/null +++ b/tests/ref/seek/vsynth2-mpeg4-nsse @@ -0,0 +1,46 @@ +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5648 size: 11937 +ret: 0 st:-1 flags:0 ts:-1.000000 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5648 size: 11937 +ret: 0 st:-1 flags:1 ts: 1.894167 +ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 127872 size: 15054 +ret: 0 st: 0 flags:0 ts: 0.800000 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 81652 size: 13376 +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: 127872 size: 15054 +ret: 0 st: 0 flags:0 ts: 0.360000 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 42638 size: 11805 +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: 81652 size: 13376 +ret: 0 st: 0 flags:0 ts:-0.040000 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5648 size: 11937 +ret: 0 st: 0 flags:1 ts: 2.840000 +ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos: 179512 size: 15553 +ret: 0 st:-1 flags:0 ts: 1.730004 +ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos: 179512 size: 15553 +ret: 0 st:-1 flags:1 ts: 0.624171 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 42638 size: 11805 +ret: 0 st: 0 flags:0 ts:-0.480000 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5648 size: 11937 +ret: 0 st: 0 flags:1 ts: 2.400000 +ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos: 179512 size: 15553 +ret: 0 st:-1 flags:0 ts: 1.306672 +ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 127872 size: 15054 +ret: 0 st:-1 flags:1 ts: 0.200839 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5648 size: 11937 +ret: 0 st: 0 flags:0 ts:-0.920000 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5648 size: 11937 +ret: 0 st: 0 flags:1 ts: 2.000000 +ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos: 179512 size: 15553 +ret: 0 st:-1 flags:0 ts: 0.883340 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 81652 size: 13376 +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: 127872 size: 15054 +ret: 0 st:-1 flags:0 ts: 0.460008 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 42638 size: 11805 +ret:-1 st:-1 flags:1 ts:-0.645825 diff --git a/tests/ref/seek/vsynth2-roqvideo b/tests/ref/seek/vsynth2-roqvideo index d003a3740..50a0a335c 100644 --- a/tests/ref/seek/vsynth2-roqvideo +++ b/tests/ref/seek/vsynth2-roqvideo @@ -1,4 +1,4 @@ -ret: 0 st: 0 flags:0 dts: 0.000000 pts: 0.000000 pos: 24 size: 26082 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 0.000000 pos: 24 size: 26814 ret:-1 st:-1 flags:0 ts:-1.000000 ret:-1 st:-1 flags:1 ts: 1.894167 ret:-1 st: 0 flags:0 ts: 0.800000 diff --git a/tests/ref/vsynth/vsynth1-amv b/tests/ref/vsynth/vsynth1-amv index f7c7f5733..38a34b2a9 100644 --- a/tests/ref/vsynth/vsynth1-amv +++ b/tests/ref/vsynth/vsynth1-amv @@ -1,4 +1,4 @@ -34c4d4033d31c7401d32fee9d6ce0de2 *tests/data/fate/vsynth1-amv.avi +e3e6dcf69be5c598b4eae901034a80e2 *tests/data/fate/vsynth1-amv.avi 1365496 tests/data/fate/vsynth1-amv.avi e38681b9527b6d2531942f8a176a0265 *tests/data/fate/vsynth1-amv.out.rawvideo stddev: 10.07 PSNR: 28.06 MAXDIFF: 98 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-asv1 b/tests/ref/vsynth/vsynth1-asv1 index e640f1c14..b450f0eac 100644 --- a/tests/ref/vsynth/vsynth1-asv1 +++ b/tests/ref/vsynth/vsynth1-asv1 @@ -1,4 +1,4 @@ -41b011551d23ddadaab1083cb2106d9f *tests/data/fate/vsynth1-asv1.avi +992195272b94d8779b6216030b85ae18 *tests/data/fate/vsynth1-asv1.avi 1489644 tests/data/fate/vsynth1-asv1.avi 2dfc5dfc2c1cbbc2543257cd3d2df6af *tests/data/fate/vsynth1-asv1.out.rawvideo stddev: 20.00 PSNR: 22.11 MAXDIFF: 158 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-asv2 b/tests/ref/vsynth/vsynth1-asv2 index 6282ad4ac..7bc1a0d53 100644 --- a/tests/ref/vsynth/vsynth1-asv2 +++ b/tests/ref/vsynth/vsynth1-asv2 @@ -1,4 +1,4 @@ -a0773690d0e772ff832adea1e8c16773 *tests/data/fate/vsynth1-asv2.avi +1e589b4dd70c4a8a7dbf4a466bab31ae *tests/data/fate/vsynth1-asv2.avi 1456044 tests/data/fate/vsynth1-asv2.avi d451be09793cd0f35b6d91fc36e2571a *tests/data/fate/vsynth1-asv2.out.rawvideo stddev: 18.82 PSNR: 22.63 MAXDIFF: 131 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-avui b/tests/ref/vsynth/vsynth1-avui index a4937acd2..53591e1d0 100644 --- a/tests/ref/vsynth/vsynth1-avui +++ b/tests/ref/vsynth/vsynth1-avui @@ -1,4 +1,4 @@ -55af74b378fb938d5ea6e0a37c149f16 *tests/data/fate/vsynth1-avui.mov +87ef06cbd15934c282d4aa83e2a5cf0a *tests/data/fate/vsynth1-avui.mov 42624917 tests/data/fate/vsynth1-avui.mov c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-avui.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-cljr b/tests/ref/vsynth/vsynth1-cljr index 5207d92c4..58191a6a8 100644 --- a/tests/ref/vsynth/vsynth1-cljr +++ b/tests/ref/vsynth/vsynth1-cljr @@ -1,4 +1,4 @@ -eb9131f74c29cda83ba706293c85afb4 *tests/data/fate/vsynth1-cljr.avi +d04d90410c1936ec545e049cb7f0d1e9 *tests/data/fate/vsynth1-cljr.avi 5075648 tests/data/fate/vsynth1-cljr.avi 7bd979b8b397f7bac22a0102c7889452 *tests/data/fate/vsynth1-cljr.out.rawvideo stddev: 6.74 PSNR: 31.55 MAXDIFF: 84 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-dnxhd-1080i b/tests/ref/vsynth/vsynth1-dnxhd-1080i index 62aa0b9bc..f9b7e0e6a 100644 --- a/tests/ref/vsynth/vsynth1-dnxhd-1080i +++ b/tests/ref/vsynth/vsynth1-dnxhd-1080i @@ -1,4 +1,4 @@ -8d0f7b3424ada79f87053022bf888797 *tests/data/fate/vsynth1-dnxhd-1080i.mov +14f1ea20bbd3024ccbfd84c681888d07 *tests/data/fate/vsynth1-dnxhd-1080i.mov 3031911 tests/data/fate/vsynth1-dnxhd-1080i.mov a09132c6db44f415e831dcaa630a351b *tests/data/fate/vsynth1-dnxhd-1080i.out.rawvideo stddev: 6.29 PSNR: 32.15 MAXDIFF: 64 bytes: 7603200/ 760320 diff --git a/tests/ref/vsynth/vsynth1-ffv1 b/tests/ref/vsynth/vsynth1-ffv1 index 22c93415c..dd119964e 100644 --- a/tests/ref/vsynth/vsynth1-ffv1 +++ b/tests/ref/vsynth/vsynth1-ffv1 @@ -1,4 +1,4 @@ -394aa2d2ee50abbc2372e6d126c7eb5a *tests/data/fate/vsynth1-ffv1.avi +7563e82e673db8ca60e79e7e725e174f *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-ffv1.0 b/tests/ref/vsynth/vsynth1-ffv1.0 index 2a4f41c09..346bde854 100644 --- a/tests/ref/vsynth/vsynth1-ffv1.0 +++ b/tests/ref/vsynth/vsynth1-ffv1.0 @@ -1,4 +1,4 @@ -91c237f18bc19975077c85175daed734 *tests/data/fate/vsynth1-ffv1.0.avi +b9ce2f9781613d3380f7036d619af87b *tests/data/fate/vsynth1-ffv1.0.avi 2655364 tests/data/fate/vsynth1-ffv1.0.avi c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-ffv1.0.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-ffvhuff b/tests/ref/vsynth/vsynth1-ffvhuff index d752c4b1f..a8b9e4112 100644 --- a/tests/ref/vsynth/vsynth1-ffvhuff +++ b/tests/ref/vsynth/vsynth1-ffvhuff @@ -1,4 +1,4 @@ -96789e7ed68de5314e65bc496c75e0a5 *tests/data/fate/vsynth1-ffvhuff.avi -5987196 tests/data/fate/vsynth1-ffvhuff.avi +936c7cb29dc7b12a5db8a0217b3486b9 *tests/data/fate/vsynth1-ffvhuff.avi +6809210 tests/data/fate/vsynth1-ffvhuff.avi c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-ffvhuff.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-ffvhuff420p12 b/tests/ref/vsynth/vsynth1-ffvhuff420p12 index 5479896e7..334c84632 100644 --- a/tests/ref/vsynth/vsynth1-ffvhuff420p12 +++ b/tests/ref/vsynth/vsynth1-ffvhuff420p12 @@ -1,4 +1,4 @@ -e37a6ec036bec59880e480df22840f0c *tests/data/fate/vsynth1-ffvhuff420p12.avi -10267454 tests/data/fate/vsynth1-ffvhuff420p12.avi +571a999f4f0e5895be97d9240e036695 *tests/data/fate/vsynth1-ffvhuff420p12.avi +14205352 tests/data/fate/vsynth1-ffvhuff420p12.avi b48f32c140712e8c7bf81cfdd66ae312 *tests/data/fate/vsynth1-ffvhuff420p12.out.rawvideo stddev: 0.68 PSNR: 51.47 MAXDIFF: 1 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-ffvhuff422p10left b/tests/ref/vsynth/vsynth1-ffvhuff422p10left index fd668e901..0d88cdd57 100644 --- a/tests/ref/vsynth/vsynth1-ffvhuff422p10left +++ b/tests/ref/vsynth/vsynth1-ffvhuff422p10left @@ -1,4 +1,4 @@ -efc50fc409f4191001534ef5f186ca25 *tests/data/fate/vsynth1-ffvhuff422p10left.avi -10552692 tests/data/fate/vsynth1-ffvhuff422p10left.avi +43705266ad32d9b98feb54d59c05b83e *tests/data/fate/vsynth1-ffvhuff422p10left.avi +13860680 tests/data/fate/vsynth1-ffvhuff422p10left.avi c31e6caada921ffa3daad3432ef3b754 *tests/data/fate/vsynth1-ffvhuff422p10left.out.rawvideo stddev: 1.85 PSNR: 42.78 MAXDIFF: 29 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-ffvhuff444 b/tests/ref/vsynth/vsynth1-ffvhuff444 index 9b3e3142d..7c518f4e3 100644 --- a/tests/ref/vsynth/vsynth1-ffvhuff444 +++ b/tests/ref/vsynth/vsynth1-ffvhuff444 @@ -1,4 +1,4 @@ -bd5b0acf47a6915c6d0889ca7fe48d0e *tests/data/fate/vsynth1-ffvhuff444.avi -10967556 tests/data/fate/vsynth1-ffvhuff444.avi +962b03019d92658356eb7cdfad857d08 *tests/data/fate/vsynth1-ffvhuff444.avi +11712338 tests/data/fate/vsynth1-ffvhuff444.avi 10fb42f1abf40a289c3edafc0390482c *tests/data/fate/vsynth1-ffvhuff444.out.rawvideo stddev: 2.67 PSNR: 39.60 MAXDIFF: 43 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-ffvhuff444p16 b/tests/ref/vsynth/vsynth1-ffvhuff444p16 index b2df2c46a..76acffdab 100644 --- a/tests/ref/vsynth/vsynth1-ffvhuff444p16 +++ b/tests/ref/vsynth/vsynth1-ffvhuff444p16 @@ -1,4 +1,4 @@ -a891c4e5cfa3fb1f488e23d1b4f77f28 *tests/data/fate/vsynth1-ffvhuff444p16.avi -20610414 tests/data/fate/vsynth1-ffvhuff444p16.avi +9d7ab6d77fb4004512246c2f93f93c29 *tests/data/fate/vsynth1-ffvhuff444p16.avi +24706272 tests/data/fate/vsynth1-ffvhuff444p16.avi ee8379fa217dfd023de3aa6974a14d1e *tests/data/fate/vsynth1-ffvhuff444p16.out.rawvideo stddev: 2.66 PSNR: 39.62 MAXDIFF: 44 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-h261 b/tests/ref/vsynth/vsynth1-h261 index 02b956b44..52372d8c0 100644 --- a/tests/ref/vsynth/vsynth1-h261 +++ b/tests/ref/vsynth/vsynth1-h261 @@ -1,4 +1,4 @@ -2e613918f64c3473b887306fc5eb3c3d *tests/data/fate/vsynth1-h261.avi +364cc6703e90df30631dad52d1d9c909 *tests/data/fate/vsynth1-h261.avi 707546 tests/data/fate/vsynth1-h261.avi 85fde92037c2ccecc02e2d6c21a169b0 *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-h261-trellis b/tests/ref/vsynth/vsynth1-h261-trellis index 77cb589c7..23fa23130 100644 --- a/tests/ref/vsynth/vsynth1-h261-trellis +++ b/tests/ref/vsynth/vsynth1-h261-trellis @@ -1,4 +1,4 @@ -7af82b4b3f99416f839ebc9714306dad *tests/data/fate/vsynth1-h261-trellis.avi +a61e040bbbfc6875e6842ac066a5285b *tests/data/fate/vsynth1-h261-trellis.avi 655412 tests/data/fate/vsynth1-h261-trellis.avi 70ceba944548ba680b1101c91707ea25 *tests/data/fate/vsynth1-h261-trellis.out.rawvideo stddev: 8.75 PSNR: 29.28 MAXDIFF: 90 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-h263 b/tests/ref/vsynth/vsynth1-h263 index f985d6100..a07c597a4 100644 --- a/tests/ref/vsynth/vsynth1-h263 +++ b/tests/ref/vsynth/vsynth1-h263 @@ -1,4 +1,4 @@ -36abb66d2480121f66a23e07d2b903be *tests/data/fate/vsynth1-h263.avi +3975fd5e232267fab6a5f8a5e095e3f9 *tests/data/fate/vsynth1-h263.avi 659674 tests/data/fate/vsynth1-h263.avi aef88517578fa7f53fe5159c4b6754ef *tests/data/fate/vsynth1-h263.out.rawvideo stddev: 8.03 PSNR: 30.03 MAXDIFF: 103 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-h263-obmc b/tests/ref/vsynth/vsynth1-h263-obmc index f60e252f8..ecb7a9a37 100644 --- a/tests/ref/vsynth/vsynth1-h263-obmc +++ b/tests/ref/vsynth/vsynth1-h263-obmc @@ -1,4 +1,4 @@ -ec2262cb7c674fd85afb14d9eb27d9d6 *tests/data/fate/vsynth1-h263-obmc.avi +d66bfd3b2cd4bc59d8ec218391294266 *tests/data/fate/vsynth1-h263-obmc.avi 657316 tests/data/fate/vsynth1-h263-obmc.avi 844f7ee27fa122e199fe20987b41a15c *tests/data/fate/vsynth1-h263-obmc.out.rawvideo stddev: 8.16 PSNR: 29.89 MAXDIFF: 113 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-h263p b/tests/ref/vsynth/vsynth1-h263p index 72ef0ff23..b96913dcc 100644 --- a/tests/ref/vsynth/vsynth1-h263p +++ b/tests/ref/vsynth/vsynth1-h263p @@ -1,4 +1,4 @@ -03ebe03b70ee93524ec30c5abb69205a *tests/data/fate/vsynth1-h263p.avi +15a47620dcf88daaa71d4c679f620b47 *tests/data/fate/vsynth1-h263p.avi 2328362 tests/data/fate/vsynth1-h263p.avi 911330cb57c99c440234392be1588081 *tests/data/fate/vsynth1-h263p.out.rawvideo stddev: 2.06 PSNR: 41.83 MAXDIFF: 20 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-huffyuv b/tests/ref/vsynth/vsynth1-huffyuv index ed0836528..f747d9d64 100644 --- a/tests/ref/vsynth/vsynth1-huffyuv +++ b/tests/ref/vsynth/vsynth1-huffyuv @@ -1,4 +1,4 @@ -829bf3e22e5d1df2aa9a709c9d5aff57 *tests/data/fate/vsynth1-huffyuv.avi -7933788 tests/data/fate/vsynth1-huffyuv.avi +b48b81b3bdd4e24834f9ada6f567b94e *tests/data/fate/vsynth1-huffyuv.avi +8876470 tests/data/fate/vsynth1-huffyuv.avi c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-huffyuv.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-huffyuvbgr24 b/tests/ref/vsynth/vsynth1-huffyuvbgr24 new file mode 100644 index 000000000..c40ad0fd5 --- /dev/null +++ b/tests/ref/vsynth/vsynth1-huffyuvbgr24 @@ -0,0 +1,4 @@ +62748f420e76a0b26886f432074f89a1 *tests/data/fate/vsynth1-huffyuvbgr24.avi +13196986 tests/data/fate/vsynth1-huffyuvbgr24.avi +49c03ab1b73b7cd3cabc3c77a9479c9e *tests/data/fate/vsynth1-huffyuvbgr24.out.rawvideo +stddev: 3.16 PSNR: 38.12 MAXDIFF: 50 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-jpeg2000 b/tests/ref/vsynth/vsynth1-jpeg2000 index cf53feb2e..a6a3e109e 100644 --- a/tests/ref/vsynth/vsynth1-jpeg2000 +++ b/tests/ref/vsynth/vsynth1-jpeg2000 @@ -1,4 +1,4 @@ -e6e3d338eeb394d6fadc7bbb55fa9e6e *tests/data/fate/vsynth1-jpeg2000.avi +b526a22fcc4f710da181617ad06ec523 *tests/data/fate/vsynth1-jpeg2000.avi 2306902 tests/data/fate/vsynth1-jpeg2000.avi 1774b621bd92a53a24712cb77e9f0b28 *tests/data/fate/vsynth1-jpeg2000.out.rawvideo stddev: 5.37 PSNR: 33.52 MAXDIFF: 63 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-jpeg2000-97 b/tests/ref/vsynth/vsynth1-jpeg2000-97 index f8399f2be..cd56149fd 100644 --- a/tests/ref/vsynth/vsynth1-jpeg2000-97 +++ b/tests/ref/vsynth/vsynth1-jpeg2000-97 @@ -1,4 +1,4 @@ -c135eb14e9f219242180270c2a242634 *tests/data/fate/vsynth1-jpeg2000-97.avi +397690bc9f6202c77ce3810640762ca3 *tests/data/fate/vsynth1-jpeg2000-97.avi 2243132 tests/data/fate/vsynth1-jpeg2000-97.avi e1a095b40d7f6440f6c46f2995c4759c *tests/data/fate/vsynth1-jpeg2000-97.out.rawvideo stddev: 6.23 PSNR: 32.23 MAXDIFF: 75 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-jpegls b/tests/ref/vsynth/vsynth1-jpegls index fc2107407..2e4430855 100644 --- a/tests/ref/vsynth/vsynth1-jpegls +++ b/tests/ref/vsynth/vsynth1-jpegls @@ -1,4 +1,4 @@ -f8acf917e24ea6c9200f2cdf99744ca9 *tests/data/fate/vsynth1-jpegls.avi +424107c7919713b422b8e982ae3e4319 *tests/data/fate/vsynth1-jpegls.avi 9089800 tests/data/fate/vsynth1-jpegls.avi 791e1fb999deb2e4156e2286d48c4ed1 *tests/data/fate/vsynth1-jpegls.out.rawvideo stddev: 2.84 PSNR: 39.04 MAXDIFF: 49 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-ljpeg b/tests/ref/vsynth/vsynth1-ljpeg index 7464a385d..99bfade16 100644 --- a/tests/ref/vsynth/vsynth1-ljpeg +++ b/tests/ref/vsynth/vsynth1-ljpeg @@ -1,4 +1,4 @@ -ef0a38e7c24a4d7367a461ad8acac2c1 *tests/data/fate/vsynth1-ljpeg.avi +24d72a5b4c0d3a49a30098369d56b1cc *tests/data/fate/vsynth1-ljpeg.avi 6309478 tests/data/fate/vsynth1-ljpeg.avi c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-ljpeg.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mjpeg b/tests/ref/vsynth/vsynth1-mjpeg index 80f15ca4c..63ad2405d 100644 --- a/tests/ref/vsynth/vsynth1-mjpeg +++ b/tests/ref/vsynth/vsynth1-mjpeg @@ -1,4 +1,4 @@ -3d3a9cef95621e1c153649721c5a8590 *tests/data/fate/vsynth1-mjpeg.avi +c14acfb3472919caa50ed90125ab33a9 *tests/data/fate/vsynth1-mjpeg.avi 1515902 tests/data/fate/vsynth1-mjpeg.avi 9a3b8169c251d19044f7087a95458c55 *tests/data/fate/vsynth1-mjpeg.out.rawvideo stddev: 7.87 PSNR: 30.21 MAXDIFF: 63 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mjpeg-422 b/tests/ref/vsynth/vsynth1-mjpeg-422 index e631a2b15..3356dd397 100644 --- a/tests/ref/vsynth/vsynth1-mjpeg-422 +++ b/tests/ref/vsynth/vsynth1-mjpeg-422 @@ -1,4 +1,4 @@ -cd452cb6a2967b2f3bd2d31de6c95bf1 *tests/data/fate/vsynth1-mjpeg-422.avi +bcd2370d76f32b9eed7842685a04f29f *tests/data/fate/vsynth1-mjpeg-422.avi 1756300 tests/data/fate/vsynth1-mjpeg-422.avi c35eea486c6d72050f4848eab64032b5 *tests/data/fate/vsynth1-mjpeg-422.out.rawvideo stddev: 7.45 PSNR: 30.69 MAXDIFF: 63 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mjpeg-444 b/tests/ref/vsynth/vsynth1-mjpeg-444 index ba2491491..5ebf89549 100644 --- a/tests/ref/vsynth/vsynth1-mjpeg-444 +++ b/tests/ref/vsynth/vsynth1-mjpeg-444 @@ -1,4 +1,4 @@ -94ca37e075ee24047b5dcd8f27b51a9f *tests/data/fate/vsynth1-mjpeg-444.avi +f611f316df9b6890d6dcd3379691c36e *tests/data/fate/vsynth1-mjpeg-444.avi 1989780 tests/data/fate/vsynth1-mjpeg-444.avi 313a4a76af13d5879ea4910107b7ea74 *tests/data/fate/vsynth1-mjpeg-444.out.rawvideo stddev: 7.37 PSNR: 30.77 MAXDIFF: 63 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg1 b/tests/ref/vsynth/vsynth1-mpeg1 index b350cdaaf..902b201eb 100644 --- a/tests/ref/vsynth/vsynth1-mpeg1 +++ b/tests/ref/vsynth/vsynth1-mpeg1 @@ -1,4 +1,4 @@ -490e08209e30f162cf3f2a6f2e49c7ce *tests/data/fate/vsynth1-mpeg1.mpeg1video +746ae4adb7d1921800b9cc30257d7231 *tests/data/fate/vsynth1-mpeg1.mpeg1video 711835 tests/data/fate/vsynth1-mpeg1.mpeg1video c126c7dd12e7161df192d253e3100475 *tests/data/fate/vsynth1-mpeg1.out.rawvideo stddev: 7.63 PSNR: 30.48 MAXDIFF: 84 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg1b b/tests/ref/vsynth/vsynth1-mpeg1b index 5c9e3c1b3..6d7afa491 100644 --- a/tests/ref/vsynth/vsynth1-mpeg1b +++ b/tests/ref/vsynth/vsynth1-mpeg1b @@ -1,4 +1,4 @@ -fc095c7816920052fd0b91329c60cf29 *tests/data/fate/vsynth1-mpeg1b.mpeg1video +f99bb6797faddeb48863a49a244793fc *tests/data/fate/vsynth1-mpeg1b.mpeg1video 1031387 tests/data/fate/vsynth1-mpeg1b.mpeg1video 22289cbbeb1e40c5fd68dcc73a07d8f5 *tests/data/fate/vsynth1-mpeg1b.out.rawvideo stddev: 6.30 PSNR: 32.13 MAXDIFF: 75 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2 b/tests/ref/vsynth/vsynth1-mpeg2 index 8dbc88b06..0f06f380c 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2 +++ b/tests/ref/vsynth/vsynth1-mpeg2 @@ -1,4 +1,4 @@ -5434d2fbac67dc1a910883c9c04644fa *tests/data/fate/vsynth1-mpeg2.mpeg2video +89d9481c12d2342e256b322d317e81c4 *tests/data/fate/vsynth1-mpeg2.mpeg2video 728400 tests/data/fate/vsynth1-mpeg2.mpeg2video 66c2a14725ba0a6f1535b9a62768977b *tests/data/fate/vsynth1-mpeg2.out.rawvideo stddev: 7.65 PSNR: 30.45 MAXDIFF: 84 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-422 b/tests/ref/vsynth/vsynth1-mpeg2-422 index bb0dce7b1..e936ba463 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-422 +++ b/tests/ref/vsynth/vsynth1-mpeg2-422 @@ -1,4 +1,4 @@ -0af0a148bf44bed5d260cafae6cc53e7 *tests/data/fate/vsynth1-mpeg2-422.mpeg2video +6e135a1a27235a320311a932147846b4 *tests/data/fate/vsynth1-mpeg2-422.mpeg2video 730780 tests/data/fate/vsynth1-mpeg2-422.mpeg2video 0273cd8463d1fc115378748239951560 *tests/data/fate/vsynth1-mpeg2-422.out.rawvideo stddev: 10.27 PSNR: 27.90 MAXDIFF: 162 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-idct-int b/tests/ref/vsynth/vsynth1-mpeg2-idct-int index dd72d715b..89356d060 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-idct-int +++ b/tests/ref/vsynth/vsynth1-mpeg2-idct-int @@ -1,4 +1,4 @@ -4c067397b504d65532d7779cd36f3f88 *tests/data/fate/vsynth1-mpeg2-idct-int.mpeg2video +b63161625d83d39c9114c7018cac5e9b *tests/data/fate/vsynth1-mpeg2-idct-int.mpeg2video 725668 tests/data/fate/vsynth1-mpeg2-idct-int.mpeg2video 8130f71a467315c9e7bd1a25a01dbb23 *tests/data/fate/vsynth1-mpeg2-idct-int.out.rawvideo stddev: 7.65 PSNR: 30.45 MAXDIFF: 80 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-ilace b/tests/ref/vsynth/vsynth1-mpeg2-ilace index b83b04cce..b9144b67a 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-ilace +++ b/tests/ref/vsynth/vsynth1-mpeg2-ilace @@ -1,4 +1,4 @@ -8492b04953b04dbef51cbe065f894e47 *tests/data/fate/vsynth1-mpeg2-ilace.mpeg2video +a92e79aa97a2d6b3b48b6cd9ceee1701 *tests/data/fate/vsynth1-mpeg2-ilace.mpeg2video 738127 tests/data/fate/vsynth1-mpeg2-ilace.mpeg2video d0f2fab8d3a3fb8bc67aca068447d2db *tests/data/fate/vsynth1-mpeg2-ilace.out.rawvideo stddev: 7.67 PSNR: 30.43 MAXDIFF: 84 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-ivlc-qprd b/tests/ref/vsynth/vsynth1-mpeg2-ivlc-qprd index 4e00f0afd..392f9bb7f 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-ivlc-qprd +++ b/tests/ref/vsynth/vsynth1-mpeg2-ivlc-qprd @@ -1,4 +1,4 @@ -f5e8917781d576d0721d44a3111d3efa *tests/data/fate/vsynth1-mpeg2-ivlc-qprd.mpeg2video +2e5882eeaaae088750d9854c93bbf68e *tests/data/fate/vsynth1-mpeg2-ivlc-qprd.mpeg2video 783518 tests/data/fate/vsynth1-mpeg2-ivlc-qprd.mpeg2video 0876d78f40971c5a8eb2367cbd27c5a6 *tests/data/fate/vsynth1-mpeg2-ivlc-qprd.out.rawvideo stddev: 10.07 PSNR: 28.07 MAXDIFF: 165 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-thread b/tests/ref/vsynth/vsynth1-mpeg2-thread index fd56bf00b..5f750b914 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-thread +++ b/tests/ref/vsynth/vsynth1-mpeg2-thread @@ -1,4 +1,4 @@ -c52f961dd53263cd9e7785a0d46949b7 *tests/data/fate/vsynth1-mpeg2-thread.mpeg2video +b4026056b8b903c37f6adfe2cd2d1894 *tests/data/fate/vsynth1-mpeg2-thread.mpeg2video 801214 tests/data/fate/vsynth1-mpeg2-thread.mpeg2video d433c9b07b40b0d6c4fd5426699efb7f *tests/data/fate/vsynth1-mpeg2-thread.out.rawvideo stddev: 7.63 PSNR: 30.48 MAXDIFF: 110 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-thread-ivlc b/tests/ref/vsynth/vsynth1-mpeg2-thread-ivlc index 235dfe536..618125c54 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-thread-ivlc +++ b/tests/ref/vsynth/vsynth1-mpeg2-thread-ivlc @@ -1,4 +1,4 @@ -6c5ac0817a7fc501ed6d91e9b9899ed3 *tests/data/fate/vsynth1-mpeg2-thread-ivlc.mpeg2video +08310d12ac77af11a0ac564552322e08 *tests/data/fate/vsynth1-mpeg2-thread-ivlc.mpeg2video 791673 tests/data/fate/vsynth1-mpeg2-thread-ivlc.mpeg2video d433c9b07b40b0d6c4fd5426699efb7f *tests/data/fate/vsynth1-mpeg2-thread-ivlc.out.rawvideo stddev: 7.63 PSNR: 30.48 MAXDIFF: 110 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg4 b/tests/ref/vsynth/vsynth1-mpeg4 index 9a58987f2..4e9b4bd03 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4 +++ b/tests/ref/vsynth/vsynth1-mpeg4 @@ -1,4 +1,4 @@ -a52ff2ce472737e07462d6b51673a886 *tests/data/fate/vsynth1-mpeg4.mp4 -540024 tests/data/fate/vsynth1-mpeg4.mp4 +b4e8871c504a22c8c874c7e845b73da7 *tests/data/fate/vsynth1-mpeg4.mp4 +540085 tests/data/fate/vsynth1-mpeg4.mp4 f80ec173d37f2f91add031e95579a220 *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-mpeg4-adap b/tests/ref/vsynth/vsynth1-mpeg4-adap index 00ea53da2..a9d11b722 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4-adap +++ b/tests/ref/vsynth/vsynth1-mpeg4-adap @@ -1,4 +1,4 @@ -2aa8bfefc09135a9a25dc23e3a14c6a4 *tests/data/fate/vsynth1-mpeg4-adap.avi +82726c84fc7a0b464818bf6e83e0d2db *tests/data/fate/vsynth1-mpeg4-adap.avi 403432 tests/data/fate/vsynth1-mpeg4-adap.avi fad0b9dc08fe4a95b297af1a7411c1e9 *tests/data/fate/vsynth1-mpeg4-adap.out.rawvideo stddev: 14.05 PSNR: 25.17 MAXDIFF: 184 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg4-adv b/tests/ref/vsynth/vsynth1-mpeg4-adv index a67cc14e9..d1d921f27 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4-adv +++ b/tests/ref/vsynth/vsynth1-mpeg4-adv @@ -1,4 +1,4 @@ -b12cf575e8a28975cfeb67c23870afdd *tests/data/fate/vsynth1-mpeg4-adv.avi +8f6e6b9a8242a2342edab58c00900841 *tests/data/fate/vsynth1-mpeg4-adv.avi 589704 tests/data/fate/vsynth1-mpeg4-adv.avi b651bd94456005a1990fb64c28306262 *tests/data/fate/vsynth1-mpeg4-adv.out.rawvideo stddev: 6.98 PSNR: 31.25 MAXDIFF: 84 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg4-error b/tests/ref/vsynth/vsynth1-mpeg4-error index b69436251..3aafd4eca 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4-error +++ b/tests/ref/vsynth/vsynth1-mpeg4-error @@ -1,4 +1,4 @@ -5a6d923425ff437924d4723aa73a817f *tests/data/fate/vsynth1-mpeg4-error.avi +6ea634d8b179098a3ec7f05af1e4a98d *tests/data/fate/vsynth1-mpeg4-error.avi 752346 tests/data/fate/vsynth1-mpeg4-error.avi 5853c8c789f260ae4dcbf37a17d04b66 *tests/data/fate/vsynth1-mpeg4-error.out.rawvideo stddev: 17.33 PSNR: 23.35 MAXDIFF: 229 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg4-nr b/tests/ref/vsynth/vsynth1-mpeg4-nr index e71dd2b0c..a18eabc20 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4-nr +++ b/tests/ref/vsynth/vsynth1-mpeg4-nr @@ -1,4 +1,4 @@ -6515d1676d4d0c92c85c0468c53261aa *tests/data/fate/vsynth1-mpeg4-nr.avi +953407e0e1fd1c99e4b320065f69ad81 *tests/data/fate/vsynth1-mpeg4-nr.avi 675452 tests/data/fate/vsynth1-mpeg4-nr.avi 5fee518cde41e5567f800fbe14210fb8 *tests/data/fate/vsynth1-mpeg4-nr.out.rawvideo stddev: 6.99 PSNR: 31.24 MAXDIFF: 86 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg4-nsse b/tests/ref/vsynth/vsynth1-mpeg4-nsse new file mode 100644 index 000000000..a6065f92f --- /dev/null +++ b/tests/ref/vsynth/vsynth1-mpeg4-nsse @@ -0,0 +1,4 @@ +10fa4b9d835349220908b5ebde9a0e70 *tests/data/fate/vsynth1-mpeg4-nsse.avi +886842 tests/data/fate/vsynth1-mpeg4-nsse.avi +a987cb2e49284ea83174e3a2c6527173 *tests/data/fate/vsynth1-mpeg4-nsse.out.rawvideo +stddev: 6.00 PSNR: 32.57 MAXDIFF: 73 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg4-qpel b/tests/ref/vsynth/vsynth1-mpeg4-qpel index 67b72a1a5..ed53fed83 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4-qpel +++ b/tests/ref/vsynth/vsynth1-mpeg4-qpel @@ -1,4 +1,4 @@ -594626acf31cbfc4a14af4d9b3cd8a6c *tests/data/fate/vsynth1-mpeg4-qpel.avi +b49ff3a036fdb479404f80f1490c6330 *tests/data/fate/vsynth1-mpeg4-qpel.avi 858680 tests/data/fate/vsynth1-mpeg4-qpel.avi 5089090df7169eb482532df5471d7f5f *tests/data/fate/vsynth1-mpeg4-qpel.out.rawvideo stddev: 5.63 PSNR: 33.11 MAXDIFF: 70 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg4-qprd b/tests/ref/vsynth/vsynth1-mpeg4-qprd index 0475e7075..307ff325f 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4-qprd +++ b/tests/ref/vsynth/vsynth1-mpeg4-qprd @@ -1,4 +1,4 @@ -96590e5921628ff84d109624e6124911 *tests/data/fate/vsynth1-mpeg4-qprd.avi +1bcc031a67149a9650d7efb56952c5fa *tests/data/fate/vsynth1-mpeg4-qprd.avi 710672 tests/data/fate/vsynth1-mpeg4-qprd.avi 693231ac7e6fbf8758415f9f2509408d *tests/data/fate/vsynth1-mpeg4-qprd.out.rawvideo stddev: 9.79 PSNR: 28.31 MAXDIFF: 176 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg4-rc b/tests/ref/vsynth/vsynth1-mpeg4-rc index 96e41be91..f41b4581f 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4-rc +++ b/tests/ref/vsynth/vsynth1-mpeg4-rc @@ -1,4 +1,4 @@ -59cf839b030f7df30b95fd300c4defb1 *tests/data/fate/vsynth1-mpeg4-rc.avi +e9ff13628bd5bd138a44f4d4815d8d09 *tests/data/fate/vsynth1-mpeg4-rc.avi 830494 tests/data/fate/vsynth1-mpeg4-rc.avi 9dcd9d022ae14fe1e4a53aa4865464c6 *tests/data/fate/vsynth1-mpeg4-rc.out.rawvideo stddev: 10.24 PSNR: 27.92 MAXDIFF: 196 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg4-thread b/tests/ref/vsynth/vsynth1-mpeg4-thread index a99827343..581897c30 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4-thread +++ b/tests/ref/vsynth/vsynth1-mpeg4-thread @@ -1,4 +1,4 @@ -14059560812963039e852f4f6419c238 *tests/data/fate/vsynth1-mpeg4-thread.avi +fa47e87b4fac7ee7da58cf677d816567 *tests/data/fate/vsynth1-mpeg4-thread.avi 774750 tests/data/fate/vsynth1-mpeg4-thread.avi 9aa327a244d5179acf7fe64dc1459bff *tests/data/fate/vsynth1-mpeg4-thread.out.rawvideo stddev: 10.13 PSNR: 28.02 MAXDIFF: 183 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpng b/tests/ref/vsynth/vsynth1-mpng index 5ca268bf7..7c6b872ca 100644 --- a/tests/ref/vsynth/vsynth1-mpng +++ b/tests/ref/vsynth/vsynth1-mpng @@ -1,4 +1,4 @@ -10bcdf8600d3985aeb57dc774df2b747 *tests/data/fate/vsynth1-mpng.avi +a32e70b1079dff3af0fe1fc339fafce2 *tests/data/fate/vsynth1-mpng.avi 12158276 tests/data/fate/vsynth1-mpng.avi 93695a27c24a61105076ca7b1f010bbd *tests/data/fate/vsynth1-mpng.out.rawvideo stddev: 3.42 PSNR: 37.44 MAXDIFF: 48 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-msmpeg4 b/tests/ref/vsynth/vsynth1-msmpeg4 index 4adabbea7..e0f3c2a77 100644 --- a/tests/ref/vsynth/vsynth1-msmpeg4 +++ b/tests/ref/vsynth/vsynth1-msmpeg4 @@ -1,4 +1,4 @@ -7d9d622b04156246348bde2e3a4d9c9c *tests/data/fate/vsynth1-msmpeg4.avi +391863936d129fef45d855dd0fcf5b8a *tests/data/fate/vsynth1-msmpeg4.avi 624702 tests/data/fate/vsynth1-msmpeg4.avi 4529fee96b8073e02974f5355e5f6c4e *tests/data/fate/vsynth1-msmpeg4.out.rawvideo stddev: 7.98 PSNR: 30.09 MAXDIFF: 104 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-msmpeg4v2 b/tests/ref/vsynth/vsynth1-msmpeg4v2 index 775d57583..150bf30c9 100644 --- a/tests/ref/vsynth/vsynth1-msmpeg4v2 +++ b/tests/ref/vsynth/vsynth1-msmpeg4v2 @@ -1,4 +1,4 @@ -a0539692d72e763448fc0dbe98d92ea3 *tests/data/fate/vsynth1-msmpeg4v2.avi +a1f1ad51642bd8394ea9ad7646d91b85 *tests/data/fate/vsynth1-msmpeg4v2.avi 623766 tests/data/fate/vsynth1-msmpeg4v2.avi 0476d9aafc4358654f411fa9648f9560 *tests/data/fate/vsynth1-msmpeg4v2.out.rawvideo stddev: 7.97 PSNR: 30.10 MAXDIFF: 105 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-msvideo1 b/tests/ref/vsynth/vsynth1-msvideo1 index 0ab886083..dd87a21ae 100644 --- a/tests/ref/vsynth/vsynth1-msvideo1 +++ b/tests/ref/vsynth/vsynth1-msvideo1 @@ -1,4 +1,4 @@ -bea8dd62e64453fb08e4f3d19be23792 *tests/data/fate/vsynth1-msvideo1.avi +e017b7844d81f70cdd6aaad479d9462b *tests/data/fate/vsynth1-msvideo1.avi 2051892 tests/data/fate/vsynth1-msvideo1.avi f4605ac6df556a3ca7053c49aaac04d8 *tests/data/fate/vsynth1-msvideo1.out.rawvideo stddev: 11.89 PSNR: 26.62 MAXDIFF: 159 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-prores b/tests/ref/vsynth/vsynth1-prores index 8cac4bf5b..14de8b9cf 100644 --- a/tests/ref/vsynth/vsynth1-prores +++ b/tests/ref/vsynth/vsynth1-prores @@ -1,4 +1,4 @@ -176b9fa03cc0946c6a41f2dcfad46805 *tests/data/fate/vsynth1-prores.mov +7ca7d2f9f5d8ac2ead691b1b6a70d409 *tests/data/fate/vsynth1-prores.mov 5022821 tests/data/fate/vsynth1-prores.mov fb4a9e025d12afc0dbbca8d82831858f *tests/data/fate/vsynth1-prores.out.rawvideo stddev: 2.47 PSNR: 40.27 MAXDIFF: 31 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-prores_ks b/tests/ref/vsynth/vsynth1-prores_ks index d3c13b5d6..6e5ed172b 100644 --- a/tests/ref/vsynth/vsynth1-prores_ks +++ b/tests/ref/vsynth/vsynth1-prores_ks @@ -1,4 +1,4 @@ -1d5522ee2fb507a66d236a09a172dc16 *tests/data/fate/vsynth1-prores_ks.mov +fe41a284da97ea5ec8866ca9a55b84da *tests/data/fate/vsynth1-prores_ks.mov 3858911 tests/data/fate/vsynth1-prores_ks.mov 100eb002413fe7a632d440dfbdf7e3ff *tests/data/fate/vsynth1-prores_ks.out.rawvideo stddev: 3.17 PSNR: 38.09 MAXDIFF: 39 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-qtrle b/tests/ref/vsynth/vsynth1-qtrle index 25d61ce5c..4b920815c 100644 --- a/tests/ref/vsynth/vsynth1-qtrle +++ b/tests/ref/vsynth/vsynth1-qtrle @@ -1,4 +1,4 @@ -d909610eb8ad5250a73f0be4c9c29b82 *tests/data/fate/vsynth1-qtrle.mov +35d8a1446d886fadcdffae192bed7e4e *tests/data/fate/vsynth1-qtrle.mov 15263158 tests/data/fate/vsynth1-qtrle.mov 93695a27c24a61105076ca7b1f010bbd *tests/data/fate/vsynth1-qtrle.out.rawvideo stddev: 3.42 PSNR: 37.44 MAXDIFF: 48 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-qtrlegray b/tests/ref/vsynth/vsynth1-qtrlegray index 3aaba24c6..c3d571d92 100644 --- a/tests/ref/vsynth/vsynth1-qtrlegray +++ b/tests/ref/vsynth/vsynth1-qtrlegray @@ -1,4 +1,4 @@ -6ef537a90e5295670701bdeaf5eb4ce1 *tests/data/fate/vsynth1-qtrlegray.mov +651b745a37a06ddd52adfe8e0a45b115 *tests/data/fate/vsynth1-qtrlegray.mov 5113293 tests/data/fate/vsynth1-qtrlegray.mov cb20af0e5a65aad7cf47002fcb52288e *tests/data/fate/vsynth1-qtrlegray.out.rawvideo stddev: 25.34 PSNR: 20.05 MAXDIFF: 122 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-r210 b/tests/ref/vsynth/vsynth1-r210 index 15b56a240..477f1a525 100644 --- a/tests/ref/vsynth/vsynth1-r210 +++ b/tests/ref/vsynth/vsynth1-r210 @@ -1,4 +1,4 @@ -80c966b18025897207ab624206a6e7a0 *tests/data/fate/vsynth1-r210.avi +7b674ea381bacc9abe3e3579f9df0e98 *tests/data/fate/vsynth1-r210.avi 22125248 tests/data/fate/vsynth1-r210.avi ecaafa9eec11b5e1453a63ed6d194eed *tests/data/fate/vsynth1-r210.out.rawvideo stddev: 3.23 PSNR: 37.94 MAXDIFF: 48 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-rgb b/tests/ref/vsynth/vsynth1-rgb index 3db33484a..5f436181f 100644 --- a/tests/ref/vsynth/vsynth1-rgb +++ b/tests/ref/vsynth/vsynth1-rgb @@ -1,4 +1,4 @@ -d78bcd5828862c3342388ec8a2c34fef *tests/data/fate/vsynth1-rgb.avi +a955310c1ad92f967fc4e3d38dc0ef91 *tests/data/fate/vsynth1-rgb.avi 15213248 tests/data/fate/vsynth1-rgb.avi 93695a27c24a61105076ca7b1f010bbd *tests/data/fate/vsynth1-rgb.out.rawvideo stddev: 3.42 PSNR: 37.44 MAXDIFF: 48 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-roqvideo b/tests/ref/vsynth/vsynth1-roqvideo index 5adba6949..2cca94224 100644 --- a/tests/ref/vsynth/vsynth1-roqvideo +++ b/tests/ref/vsynth/vsynth1-roqvideo @@ -1,4 +1,4 @@ -cf8b7b0e539bab3169c234ca63d71dd8 *tests/data/fate/vsynth1-roqvideo.roq -101671 tests/data/fate/vsynth1-roqvideo.roq -0ad983c291b1ed373645c5b12a108c61 *tests/data/fate/vsynth1-roqvideo.out.rawvideo -stddev: 7.74 PSNR: 30.35 MAXDIFF: 89 bytes: 7603200/ 760320 +8037e62b2707a246e787bb1723b752b9 *tests/data/fate/vsynth1-roqvideo.roq +102571 tests/data/fate/vsynth1-roqvideo.roq +9e3bb47e5e9708392d7eba8f944b6920 *tests/data/fate/vsynth1-roqvideo.out.rawvideo +stddev: 7.75 PSNR: 30.34 MAXDIFF: 88 bytes: 7603200/ 760320 diff --git a/tests/ref/vsynth/vsynth1-snow b/tests/ref/vsynth/vsynth1-snow index 701b5ccfa..a3d702877 100644 --- a/tests/ref/vsynth/vsynth1-snow +++ b/tests/ref/vsynth/vsynth1-snow @@ -1,4 +1,4 @@ -44fed844eb715fba0cc2433e7d7713bb *tests/data/fate/vsynth1-snow.avi +40c38c87f15a76745fcc1e1c59f80054 *tests/data/fate/vsynth1-snow.avi 136076 tests/data/fate/vsynth1-snow.avi 91021b7d6d7908648fe78cc1975af8c4 *tests/data/fate/vsynth1-snow.out.rawvideo stddev: 22.77 PSNR: 20.98 MAXDIFF: 172 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-snow-hpel b/tests/ref/vsynth/vsynth1-snow-hpel index c22ad0aa7..5ef7de02a 100644 --- a/tests/ref/vsynth/vsynth1-snow-hpel +++ b/tests/ref/vsynth/vsynth1-snow-hpel @@ -1,4 +1,4 @@ -f60c8cb8f41b66bc38df87e9bdb84b34 *tests/data/fate/vsynth1-snow-hpel.avi +6a91c3b8d05cbcc664e357539bd13269 *tests/data/fate/vsynth1-snow-hpel.avi 138700 tests/data/fate/vsynth1-snow-hpel.avi d6845c8f1310e041afdcebc6bbfc449b *tests/data/fate/vsynth1-snow-hpel.out.rawvideo stddev: 22.74 PSNR: 20.99 MAXDIFF: 171 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-snow-ll b/tests/ref/vsynth/vsynth1-snow-ll index 1636af55e..7cb86433b 100644 --- a/tests/ref/vsynth/vsynth1-snow-ll +++ b/tests/ref/vsynth/vsynth1-snow-ll @@ -1,4 +1,4 @@ -bdc7a025cd306f3da0d377b06bbe909b *tests/data/fate/vsynth1-snow-ll.avi +ef9af2fa50b412301aeeaa1aeca09526 *tests/data/fate/vsynth1-snow-ll.avi 3419968 tests/data/fate/vsynth1-snow-ll.avi c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-snow-ll.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-svq1 b/tests/ref/vsynth/vsynth1-svq1 index a7de66e08..9c1b6ff7a 100644 --- a/tests/ref/vsynth/vsynth1-svq1 +++ b/tests/ref/vsynth/vsynth1-svq1 @@ -1,4 +1,4 @@ -69afe0f66844ac3edb83d97994099fc0 *tests/data/fate/vsynth1-svq1.mov +a3206831d34197a2d236d82dd0248646 *tests/data/fate/vsynth1-svq1.mov 1334233 tests/data/fate/vsynth1-svq1.mov 9cc35c54b2c77d36bd7e308b393c1f81 *tests/data/fate/vsynth1-svq1.out.rawvideo stddev: 9.58 PSNR: 28.50 MAXDIFF: 210 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-v210 b/tests/ref/vsynth/vsynth1-v210 index defd2f658..dbafe428f 100644 --- a/tests/ref/vsynth/vsynth1-v210 +++ b/tests/ref/vsynth/vsynth1-v210 @@ -1,4 +1,4 @@ -054d7e903fb4d9e68700c56b93d45916 *tests/data/fate/vsynth1-v210.avi +895d30660eb4da017568141a8d1df4e8 *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 diff --git a/tests/ref/vsynth/vsynth1-v308 b/tests/ref/vsynth/vsynth1-v308 index 7dc5de91f..45b20ed7a 100644 --- a/tests/ref/vsynth/vsynth1-v308 +++ b/tests/ref/vsynth/vsynth1-v308 @@ -1,4 +1,4 @@ -05552ba36d003f8d5fec739c5ed90a67 *tests/data/fate/vsynth1-v308.avi +b1d7f4300e69fc8995188f73b7680481 *tests/data/fate/vsynth1-v308.avi 15213248 tests/data/fate/vsynth1-v308.avi 10fb42f1abf40a289c3edafc0390482c *tests/data/fate/vsynth1-v308.out.rawvideo stddev: 2.67 PSNR: 39.60 MAXDIFF: 43 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-v408 b/tests/ref/vsynth/vsynth1-v408 index f1523d157..e5970e145 100644 --- a/tests/ref/vsynth/vsynth1-v408 +++ b/tests/ref/vsynth/vsynth1-v408 @@ -1,4 +1,4 @@ -415c94a79b0eb58c445221a362e0054e *tests/data/fate/vsynth1-v408.avi +c14aa9857a0ff73130a9fb11cf738c73 *tests/data/fate/vsynth1-v408.avi 20282048 tests/data/fate/vsynth1-v408.avi c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-v408.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-wmv1 b/tests/ref/vsynth/vsynth1-wmv1 index 8d2454381..1759ec101 100644 --- a/tests/ref/vsynth/vsynth1-wmv1 +++ b/tests/ref/vsynth/vsynth1-wmv1 @@ -1,4 +1,4 @@ -2760d19cb77d84bd5bfc588d23306113 *tests/data/fate/vsynth1-wmv1.avi +76024303a316ffe69b4357b220eafc4a *tests/data/fate/vsynth1-wmv1.avi 626870 tests/data/fate/vsynth1-wmv1.avi 3354066ebdd8cd8098394be2384744e7 *tests/data/fate/vsynth1-wmv1.out.rawvideo stddev: 7.97 PSNR: 30.09 MAXDIFF: 110 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-wmv2 b/tests/ref/vsynth/vsynth1-wmv2 index 872ffc919..75d3e2259 100644 --- a/tests/ref/vsynth/vsynth1-wmv2 +++ b/tests/ref/vsynth/vsynth1-wmv2 @@ -1,4 +1,4 @@ -4ab9357e6369c81fecb1ebcbc7551f0c *tests/data/fate/vsynth1-wmv2.avi +818ade4e037d5db8c10f6bce727faec6 *tests/data/fate/vsynth1-wmv2.avi 659138 tests/data/fate/vsynth1-wmv2.avi 8a6061ef825e79d887705db656d51247 *tests/data/fate/vsynth1-wmv2.out.rawvideo stddev: 7.97 PSNR: 30.09 MAXDIFF: 105 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-y41p b/tests/ref/vsynth/vsynth1-y41p index 93fa938ef..6b5b08cf2 100644 --- a/tests/ref/vsynth/vsynth1-y41p +++ b/tests/ref/vsynth/vsynth1-y41p @@ -1,4 +1,4 @@ -c9fce228075067c51511d8b070fde340 *tests/data/fate/vsynth1-y41p.avi +1441e4ca15d9fb1d6b2901cac7938e7f *tests/data/fate/vsynth1-y41p.avi 7610048 tests/data/fate/vsynth1-y41p.avi 3aef1d83732a3f9835ee2523a11c95c1 *tests/data/fate/vsynth1-y41p.out.rawvideo stddev: 5.98 PSNR: 32.59 MAXDIFF: 87 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-yuv b/tests/ref/vsynth/vsynth1-yuv index 2eeff8070..3648e6980 100644 --- a/tests/ref/vsynth/vsynth1-yuv +++ b/tests/ref/vsynth/vsynth1-yuv @@ -1,4 +1,4 @@ -9622cbbe3ced7490f50e74cf088bc7c9 *tests/data/fate/vsynth1-yuv.avi +79738c86c951f7b2f061b3cb238989b0 *tests/data/fate/vsynth1-yuv.avi 7610048 tests/data/fate/vsynth1-yuv.avi c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-yuv.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-yuv4 b/tests/ref/vsynth/vsynth1-yuv4 index 5c473a2cb..dc7981089 100644 --- a/tests/ref/vsynth/vsynth1-yuv4 +++ b/tests/ref/vsynth/vsynth1-yuv4 @@ -1,4 +1,4 @@ -45805be52d9807f0c6f76011a64bf67b *tests/data/fate/vsynth1-yuv4.avi +7fe85091535c7f7db31f9aaa00388d9a *tests/data/fate/vsynth1-yuv4.avi 7610048 tests/data/fate/vsynth1-yuv4.avi c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-yuv4.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-zlib b/tests/ref/vsynth/vsynth1-zlib index f5441e111..9ed0aed6c 100644 --- a/tests/ref/vsynth/vsynth1-zlib +++ b/tests/ref/vsynth/vsynth1-zlib @@ -1,4 +1,4 @@ -fd52fff386f172bb3aef97761b99331c *tests/data/fate/vsynth1-zlib.avi +18a22e378a1a5961663fe76925fee271 *tests/data/fate/vsynth1-zlib.avi 12108632 tests/data/fate/vsynth1-zlib.avi 93695a27c24a61105076ca7b1f010bbd *tests/data/fate/vsynth1-zlib.out.rawvideo stddev: 3.42 PSNR: 37.44 MAXDIFF: 48 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-amv b/tests/ref/vsynth/vsynth2-amv index 6937df3a4..daa589466 100644 --- a/tests/ref/vsynth/vsynth2-amv +++ b/tests/ref/vsynth/vsynth2-amv @@ -1,4 +1,4 @@ -26d039bc37b2186d57522a8e3dc76217 *tests/data/fate/vsynth2-amv.avi +e0d0da8cf786616eff2e88c45644c902 *tests/data/fate/vsynth2-amv.avi 761976 tests/data/fate/vsynth2-amv.avi f256ad9feefb499c6569d06d868eb496 *tests/data/fate/vsynth2-amv.out.rawvideo stddev: 4.30 PSNR: 35.46 MAXDIFF: 65 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-asv1 b/tests/ref/vsynth/vsynth2-asv1 index 282435b06..01fd2bf05 100644 --- a/tests/ref/vsynth/vsynth2-asv1 +++ b/tests/ref/vsynth/vsynth2-asv1 @@ -1,4 +1,4 @@ -ae8d79e0e421138a9a67a148a42c26c5 *tests/data/fate/vsynth2-asv1.avi +9218843465c3396e9b078e63ce7ba17e *tests/data/fate/vsynth2-asv1.avi 832500 tests/data/fate/vsynth2-asv1.avi c96ff7fd17c52f99ddb7922a4cb9168f *tests/data/fate/vsynth2-asv1.out.rawvideo stddev: 10.47 PSNR: 27.73 MAXDIFF: 98 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-asv2 b/tests/ref/vsynth/vsynth2-asv2 index 89428628f..c66f05610 100644 --- a/tests/ref/vsynth/vsynth2-asv2 +++ b/tests/ref/vsynth/vsynth2-asv2 @@ -1,4 +1,4 @@ -ccf6762758395eee9a29ef7a4ef3cd58 *tests/data/fate/vsynth2-asv2.avi +065323f9873c367dd1e371fa47657ae4 *tests/data/fate/vsynth2-asv2.avi 789060 tests/data/fate/vsynth2-asv2.avi 74a78015b64b2cf8cb9da2e44f508a69 *tests/data/fate/vsynth2-asv2.out.rawvideo stddev: 10.28 PSNR: 27.89 MAXDIFF: 95 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-avui b/tests/ref/vsynth/vsynth2-avui index 424a15e10..7976a3649 100644 --- a/tests/ref/vsynth/vsynth2-avui +++ b/tests/ref/vsynth/vsynth2-avui @@ -1,4 +1,4 @@ -ec8425d8916254687ce700c940eb6664 *tests/data/fate/vsynth2-avui.mov +df5efcfd2170df82e466be4deb7ce4a9 *tests/data/fate/vsynth2-avui.mov 42624917 tests/data/fate/vsynth2-avui.mov dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth2-avui.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-cljr b/tests/ref/vsynth/vsynth2-cljr index c93da2ea4..0b6136567 100644 --- a/tests/ref/vsynth/vsynth2-cljr +++ b/tests/ref/vsynth/vsynth2-cljr @@ -1,4 +1,4 @@ -d9da8b1a1e78a8f0438d37c10f975ba3 *tests/data/fate/vsynth2-cljr.avi +7bfd989038611212a80b5b050bb78ea7 *tests/data/fate/vsynth2-cljr.avi 5075648 tests/data/fate/vsynth2-cljr.avi 965c4a134144b30b24d6d138b03ddb8c *tests/data/fate/vsynth2-cljr.out.rawvideo stddev: 3.29 PSNR: 37.76 MAXDIFF: 23 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-dnxhd-1080i b/tests/ref/vsynth/vsynth2-dnxhd-1080i index 1f9b78327..d3cf503a1 100644 --- a/tests/ref/vsynth/vsynth2-dnxhd-1080i +++ b/tests/ref/vsynth/vsynth2-dnxhd-1080i @@ -1,4 +1,4 @@ -4bbed3e8b6bc301d9bbdc83859f3a847 *tests/data/fate/vsynth2-dnxhd-1080i.mov +d680a5eed77c5b8dc6b5ef3bcf6e87e8 *tests/data/fate/vsynth2-dnxhd-1080i.mov 3031911 tests/data/fate/vsynth2-dnxhd-1080i.mov 744ba46da5d4c19a28562ea31061d170 *tests/data/fate/vsynth2-dnxhd-1080i.out.rawvideo stddev: 1.31 PSNR: 45.77 MAXDIFF: 23 bytes: 7603200/ 760320 diff --git a/tests/ref/vsynth/vsynth2-ffv1 b/tests/ref/vsynth/vsynth2-ffv1 index 6caffdd44..d0035e4e1 100644 --- a/tests/ref/vsynth/vsynth2-ffv1 +++ b/tests/ref/vsynth/vsynth2-ffv1 @@ -1,4 +1,4 @@ -0837dc7e6f625e2f6ac16140562c079d *tests/data/fate/vsynth2-ffv1.avi +9e091bee097632ef7106d3bade12b81b *tests/data/fate/vsynth2-ffv1.avi 3547788 tests/data/fate/vsynth2-ffv1.avi dde5895817ad9d219f79a52d0bdfb001 *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-ffv1.0 b/tests/ref/vsynth/vsynth2-ffv1.0 index 962c17c3e..f3877d19b 100644 --- a/tests/ref/vsynth/vsynth2-ffv1.0 +++ b/tests/ref/vsynth/vsynth2-ffv1.0 @@ -1,4 +1,4 @@ -3a757276e299bf88c30e06dfb53f1c99 *tests/data/fate/vsynth2-ffv1.0.avi +114950628c091cd830d9e66e74f6bca2 *tests/data/fate/vsynth2-ffv1.0.avi 3525792 tests/data/fate/vsynth2-ffv1.0.avi dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth2-ffv1.0.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-ffvhuff b/tests/ref/vsynth/vsynth2-ffvhuff index 164e7735f..921d5bf44 100644 --- a/tests/ref/vsynth/vsynth2-ffvhuff +++ b/tests/ref/vsynth/vsynth2-ffvhuff @@ -1,4 +1,4 @@ -6689843a60dcc046fe1d7be3afab2cab *tests/data/fate/vsynth2-ffvhuff.avi -4988044 tests/data/fate/vsynth2-ffvhuff.avi +7cb61df06d2cb4659ceb8d73c4822aaf *tests/data/fate/vsynth2-ffvhuff.avi +4845022 tests/data/fate/vsynth2-ffvhuff.avi dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth2-ffvhuff.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-ffvhuff420p12 b/tests/ref/vsynth/vsynth2-ffvhuff420p12 index 108a33332..1f1279f2b 100644 --- a/tests/ref/vsynth/vsynth2-ffvhuff420p12 +++ b/tests/ref/vsynth/vsynth2-ffvhuff420p12 @@ -1,4 +1,4 @@ -13d0c151dd7700ca102a8720f0560b73 *tests/data/fate/vsynth2-ffvhuff420p12.avi -8601770 tests/data/fate/vsynth2-ffvhuff420p12.avi +e5873a19c7be1cdf25600eb033738b9e *tests/data/fate/vsynth2-ffvhuff420p12.avi +10925576 tests/data/fate/vsynth2-ffvhuff420p12.avi 08b3c6c70eba608bae926608ff253f2a *tests/data/fate/vsynth2-ffvhuff420p12.out.rawvideo stddev: 0.68 PSNR: 51.38 MAXDIFF: 1 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-ffvhuff422p10left b/tests/ref/vsynth/vsynth2-ffvhuff422p10left index 7035d50d0..bb169784a 100644 --- a/tests/ref/vsynth/vsynth2-ffvhuff422p10left +++ b/tests/ref/vsynth/vsynth2-ffvhuff422p10left @@ -1,4 +1,4 @@ -dce07b24072447ae83d8e5e2b121e993 *tests/data/fate/vsynth2-ffvhuff422p10left.avi -8874580 tests/data/fate/vsynth2-ffvhuff422p10left.avi +d7d321c3b1ed3378e03b2f618f248d86 *tests/data/fate/vsynth2-ffvhuff422p10left.avi +10041832 tests/data/fate/vsynth2-ffvhuff422p10left.avi a627fb50c8276200fd71383977d87ca3 *tests/data/fate/vsynth2-ffvhuff422p10left.out.rawvideo stddev: 0.34 PSNR: 57.43 MAXDIFF: 6 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-ffvhuff444 b/tests/ref/vsynth/vsynth2-ffvhuff444 index 0b4d9fc9d..c4ea9cdf5 100644 --- a/tests/ref/vsynth/vsynth2-ffvhuff444 +++ b/tests/ref/vsynth/vsynth2-ffvhuff444 @@ -1,4 +1,4 @@ -50d1d79bcb2e9a9fe70ec0f211d07b09 *tests/data/fate/vsynth2-ffvhuff444.avi -8666652 tests/data/fate/vsynth2-ffvhuff444.avi +68e78dc89bb596f93a14e7f4a7a24365 *tests/data/fate/vsynth2-ffvhuff444.avi +7530714 tests/data/fate/vsynth2-ffvhuff444.avi d43cb310c130c69214332d74f6ee5f9a *tests/data/fate/vsynth2-ffvhuff444.out.rawvideo stddev: 0.41 PSNR: 55.80 MAXDIFF: 7 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-ffvhuff444p16 b/tests/ref/vsynth/vsynth2-ffvhuff444p16 index e2b8c88ee..1f03a0340 100644 --- a/tests/ref/vsynth/vsynth2-ffvhuff444p16 +++ b/tests/ref/vsynth/vsynth2-ffvhuff444p16 @@ -1,4 +1,4 @@ -e264963ec1f69a20be43a43219f8f949 *tests/data/fate/vsynth2-ffvhuff444p16.avi -21648206 tests/data/fate/vsynth2-ffvhuff444p16.avi +db17747292df97d6c62b15b041c378da *tests/data/fate/vsynth2-ffvhuff444p16.avi +26360716 tests/data/fate/vsynth2-ffvhuff444p16.avi 05ccd9a38f9726030b3099c0c99d3a13 *tests/data/fate/vsynth2-ffvhuff444p16.out.rawvideo stddev: 0.45 PSNR: 55.06 MAXDIFF: 7 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-h261 b/tests/ref/vsynth/vsynth2-h261 index f9091c7c6..67a8f0b48 100644 --- a/tests/ref/vsynth/vsynth2-h261 +++ b/tests/ref/vsynth/vsynth2-h261 @@ -1,4 +1,4 @@ -dc32bc8a9e6eae15362ab86f8156f96a *tests/data/fate/vsynth2-h261.avi +6399cb1044e5433c844c21790fc17128 *tests/data/fate/vsynth2-h261.avi 191060 tests/data/fate/vsynth2-h261.avi 08f65e9aeeeaf189548c2bb417d5114f *tests/data/fate/vsynth2-h261.out.rawvideo stddev: 6.37 PSNR: 32.03 MAXDIFF: 77 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-h261-trellis b/tests/ref/vsynth/vsynth2-h261-trellis index 36cab4cd2..8a7cf78f4 100644 --- a/tests/ref/vsynth/vsynth2-h261-trellis +++ b/tests/ref/vsynth/vsynth2-h261-trellis @@ -1,4 +1,4 @@ -5c0670e3d07043b1209136d6fbd6bb8d *tests/data/fate/vsynth2-h261-trellis.avi +616cb40cf84704d177e207ee85a24531 *tests/data/fate/vsynth2-h261-trellis.avi 184582 tests/data/fate/vsynth2-h261-trellis.avi f9df8cd110a2f3d9706dd2f29a1d0a89 *tests/data/fate/vsynth2-h261-trellis.out.rawvideo stddev: 6.32 PSNR: 32.11 MAXDIFF: 89 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-h263 b/tests/ref/vsynth/vsynth2-h263 index 944d8ead2..8feabfed1 100644 --- a/tests/ref/vsynth/vsynth2-h263 +++ b/tests/ref/vsynth/vsynth2-h263 @@ -1,4 +1,4 @@ -949d8c9926914751af5f433af0f8fd65 *tests/data/fate/vsynth2-h263.avi +b5ea141b794ad88019507375ec092ad7 *tests/data/fate/vsynth2-h263.avi 160102 tests/data/fate/vsynth2-h263.avi b7d733ebedbaa04f49bf7493a907e223 *tests/data/fate/vsynth2-h263.out.rawvideo stddev: 5.43 PSNR: 33.42 MAXDIFF: 77 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-h263-obmc b/tests/ref/vsynth/vsynth2-h263-obmc index a704318fa..aa9a60a0f 100644 --- a/tests/ref/vsynth/vsynth2-h263-obmc +++ b/tests/ref/vsynth/vsynth2-h263-obmc @@ -1,4 +1,4 @@ -7825a0bdf024673da2371829e3f01cc3 *tests/data/fate/vsynth2-h263-obmc.avi +d242b7948697014abcaaff50551400ac *tests/data/fate/vsynth2-h263-obmc.avi 154726 tests/data/fate/vsynth2-h263-obmc.avi 588d992d9d8096da8bdc5027268da914 *tests/data/fate/vsynth2-h263-obmc.out.rawvideo stddev: 5.39 PSNR: 33.49 MAXDIFF: 82 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-h263p b/tests/ref/vsynth/vsynth2-h263p index b4ebed900..182e09614 100644 --- a/tests/ref/vsynth/vsynth2-h263p +++ b/tests/ref/vsynth/vsynth2-h263p @@ -1,4 +1,4 @@ -3894234818ed65426b5f20f058d27c73 *tests/data/fate/vsynth2-h263p.avi +000157a2e05709df95e40bd5e2185141 *tests/data/fate/vsynth2-h263p.avi 867998 tests/data/fate/vsynth2-h263p.avi dca18571c05c13dd691d7b0b232e43fc *tests/data/fate/vsynth2-h263p.out.rawvideo stddev: 1.91 PSNR: 42.50 MAXDIFF: 19 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-huffyuv b/tests/ref/vsynth/vsynth2-huffyuv index 9b6781519..a2d2ae3e2 100644 --- a/tests/ref/vsynth/vsynth2-huffyuv +++ b/tests/ref/vsynth/vsynth2-huffyuv @@ -1,4 +1,4 @@ -b5ae95ae03856ee14bbd38784a02f3ca *tests/data/fate/vsynth2-huffyuv.avi -6455220 tests/data/fate/vsynth2-huffyuv.avi +c639e4044a66dc5dffb46d5d82516ef8 *tests/data/fate/vsynth2-huffyuv.avi +6108510 tests/data/fate/vsynth2-huffyuv.avi dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth2-huffyuv.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-huffyuvbgr24 b/tests/ref/vsynth/vsynth2-huffyuvbgr24 new file mode 100644 index 000000000..939eb2fe9 --- /dev/null +++ b/tests/ref/vsynth/vsynth2-huffyuvbgr24 @@ -0,0 +1,4 @@ +d72d98a2847811499028f8997320a38b *tests/data/fate/vsynth2-huffyuvbgr24.avi +8872410 tests/data/fate/vsynth2-huffyuvbgr24.avi +0a8b7ddfec03622e37c869c5b552f9fc *tests/data/fate/vsynth2-huffyuvbgr24.out.rawvideo +stddev: 1.24 PSNR: 46.26 MAXDIFF: 17 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-jpeg2000 b/tests/ref/vsynth/vsynth2-jpeg2000 index cacd467fb..84e90d45a 100644 --- a/tests/ref/vsynth/vsynth2-jpeg2000 +++ b/tests/ref/vsynth/vsynth2-jpeg2000 @@ -1,4 +1,4 @@ -fc49816ba28731689872f5c87ca91c10 *tests/data/fate/vsynth2-jpeg2000.avi +6cf1985f29a7febbb79edf1d5268e203 *tests/data/fate/vsynth2-jpeg2000.avi 1151144 tests/data/fate/vsynth2-jpeg2000.avi e7d79c9e11d0fe97f03e38be66c34e4f *tests/data/fate/vsynth2-jpeg2000.out.rawvideo stddev: 4.41 PSNR: 35.23 MAXDIFF: 63 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-jpeg2000-97 b/tests/ref/vsynth/vsynth2-jpeg2000-97 index e7fce13a2..c053a5d2e 100644 --- a/tests/ref/vsynth/vsynth2-jpeg2000-97 +++ b/tests/ref/vsynth/vsynth2-jpeg2000-97 @@ -1,4 +1,4 @@ -3ac3e49a89136bddde9e44bac3e5b4ed *tests/data/fate/vsynth2-jpeg2000-97.avi +7cdaa014398f52869704dc537983db54 *tests/data/fate/vsynth2-jpeg2000-97.avi 1118952 tests/data/fate/vsynth2-jpeg2000-97.avi 8ac8b9ee81fa73c873668e9f6b78764d *tests/data/fate/vsynth2-jpeg2000-97.out.rawvideo stddev: 4.95 PSNR: 34.23 MAXDIFF: 60 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-jpegls b/tests/ref/vsynth/vsynth2-jpegls index f8f7081ac..e256deac5 100644 --- a/tests/ref/vsynth/vsynth2-jpegls +++ b/tests/ref/vsynth/vsynth2-jpegls @@ -1,4 +1,4 @@ -f34315ed0e30cf4d94dd21ff1d4cea1b *tests/data/fate/vsynth2-jpegls.avi +9840b70886b4fc86512de729e41de979 *tests/data/fate/vsynth2-jpegls.avi 8334618 tests/data/fate/vsynth2-jpegls.avi 3a984506f1ebfc9fb73b6814cab201cc *tests/data/fate/vsynth2-jpegls.out.rawvideo stddev: 0.66 PSNR: 51.73 MAXDIFF: 14 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-ljpeg b/tests/ref/vsynth/vsynth2-ljpeg index 2136fe87b..b59923ebb 100644 --- a/tests/ref/vsynth/vsynth2-ljpeg +++ b/tests/ref/vsynth/vsynth2-ljpeg @@ -1,4 +1,4 @@ -b691d815bb7e40ac4ff8c0e51d8c08ff *tests/data/fate/vsynth2-ljpeg.avi +234a0e54d00829513bdc92fc580b2598 *tests/data/fate/vsynth2-ljpeg.avi 4763454 tests/data/fate/vsynth2-ljpeg.avi dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth2-ljpeg.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mjpeg b/tests/ref/vsynth/vsynth2-mjpeg index f1780c525..eaabc73ad 100644 --- a/tests/ref/vsynth/vsynth2-mjpeg +++ b/tests/ref/vsynth/vsynth2-mjpeg @@ -1,4 +1,4 @@ -302197cccebb4d9797a08d06ca189533 *tests/data/fate/vsynth2-mjpeg.avi +a3c1f9f7887b726bab17dbafa5debdca *tests/data/fate/vsynth2-mjpeg.avi 673174 tests/data/fate/vsynth2-mjpeg.avi 9d4bd90e9abfa18192383b4adc23c8d4 *tests/data/fate/vsynth2-mjpeg.out.rawvideo stddev: 4.32 PSNR: 35.40 MAXDIFF: 49 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mjpeg-422 b/tests/ref/vsynth/vsynth2-mjpeg-422 index fc0a4ba12..61d299705 100644 --- a/tests/ref/vsynth/vsynth2-mjpeg-422 +++ b/tests/ref/vsynth/vsynth2-mjpeg-422 @@ -1,4 +1,4 @@ -1ec800caa1dd2244677220d8a2b342ca *tests/data/fate/vsynth2-mjpeg-422.avi +ebf2e0f17a75119ff86b15e721d16a76 *tests/data/fate/vsynth2-mjpeg-422.avi 746530 tests/data/fate/vsynth2-mjpeg-422.avi 451ac80989c4e14445cf951fd7f83b6d *tests/data/fate/vsynth2-mjpeg-422.out.rawvideo stddev: 4.18 PSNR: 35.70 MAXDIFF: 49 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mjpeg-444 b/tests/ref/vsynth/vsynth2-mjpeg-444 index b09f889ca..ae01a3579 100644 --- a/tests/ref/vsynth/vsynth2-mjpeg-444 +++ b/tests/ref/vsynth/vsynth2-mjpeg-444 @@ -1,4 +1,4 @@ -10abd087833f9bdf3b77c1aa37dc11e5 *tests/data/fate/vsynth2-mjpeg-444.avi +7674eb1aedaad0976c60329f556440d1 *tests/data/fate/vsynth2-mjpeg-444.avi 851442 tests/data/fate/vsynth2-mjpeg-444.avi 34edcb9c87ff7aac456a4fb07f43504b *tests/data/fate/vsynth2-mjpeg-444.out.rawvideo stddev: 4.05 PSNR: 35.96 MAXDIFF: 49 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg1 b/tests/ref/vsynth/vsynth2-mpeg1 index bc94fbce7..9e3e9998b 100644 --- a/tests/ref/vsynth/vsynth2-mpeg1 +++ b/tests/ref/vsynth/vsynth2-mpeg1 @@ -1,4 +1,4 @@ -c6f1a98dd7201b1e5d7f0f69d7e9577d *tests/data/fate/vsynth2-mpeg1.mpeg1video +a77a8eb6e2ad32a5b20b41abda16f4c1 *tests/data/fate/vsynth2-mpeg1.mpeg1video 192794 tests/data/fate/vsynth2-mpeg1.mpeg1video b3584042c60385e0fb988b8ec5b36409 *tests/data/fate/vsynth2-mpeg1.out.rawvideo stddev: 4.95 PSNR: 34.22 MAXDIFF: 57 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg1b b/tests/ref/vsynth/vsynth2-mpeg1b index f4864a5a4..c2fb21790 100644 --- a/tests/ref/vsynth/vsynth2-mpeg1b +++ b/tests/ref/vsynth/vsynth2-mpeg1b @@ -1,4 +1,4 @@ -8300bede250c3987f1c5bc9bbd1d78e1 *tests/data/fate/vsynth2-mpeg1b.mpeg1video +333395b113b8045bac4e3fd90839ca6a *tests/data/fate/vsynth2-mpeg1b.mpeg1video 225201 tests/data/fate/vsynth2-mpeg1b.mpeg1video f17fb3eef4ed3d03eeaaee45b217f7a5 *tests/data/fate/vsynth2-mpeg1b.out.rawvideo stddev: 4.10 PSNR: 35.86 MAXDIFF: 59 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2 b/tests/ref/vsynth/vsynth2-mpeg2 index b5f5af9f4..bceb9543e 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2 +++ b/tests/ref/vsynth/vsynth2-mpeg2 @@ -1,4 +1,4 @@ -81fc934ad6901b6c37a59b94ccda8de7 *tests/data/fate/vsynth2-mpeg2.mpeg2video +6071414a26d41ae9c4cc5477d8ca19eb *tests/data/fate/vsynth2-mpeg2.mpeg2video 198673 tests/data/fate/vsynth2-mpeg2.mpeg2video 9efe4846a75d9b7387d1e3bb1e5db29a *tests/data/fate/vsynth2-mpeg2.out.rawvideo stddev: 4.96 PSNR: 34.20 MAXDIFF: 59 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-422 b/tests/ref/vsynth/vsynth2-mpeg2-422 index 14d751b67..b4a896c5c 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-422 +++ b/tests/ref/vsynth/vsynth2-mpeg2-422 @@ -1,4 +1,4 @@ -99ba26ba009e0172855a9dadaefef2d9 *tests/data/fate/vsynth2-mpeg2-422.mpeg2video +521ec92c0b8672011a43dd13db98c400 *tests/data/fate/vsynth2-mpeg2-422.mpeg2video 356431 tests/data/fate/vsynth2-mpeg2-422.mpeg2video 51ca353620f85db8b5b1c56f1a275add *tests/data/fate/vsynth2-mpeg2-422.out.rawvideo stddev: 3.15 PSNR: 38.14 MAXDIFF: 49 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-idct-int b/tests/ref/vsynth/vsynth2-mpeg2-idct-int index 83874b14d..69d5c8647 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-idct-int +++ b/tests/ref/vsynth/vsynth2-mpeg2-idct-int @@ -1,4 +1,4 @@ -f979bcca866e6e4cad5dc6cb06e56cfb *tests/data/fate/vsynth2-mpeg2-idct-int.mpeg2video +505371e1b10f5af01b63b3f57606b26e *tests/data/fate/vsynth2-mpeg2-idct-int.mpeg2video 198041 tests/data/fate/vsynth2-mpeg2-idct-int.mpeg2video 92794e70e4a19a494f10efe353d9895d *tests/data/fate/vsynth2-mpeg2-idct-int.out.rawvideo stddev: 4.97 PSNR: 34.19 MAXDIFF: 58 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-ilace b/tests/ref/vsynth/vsynth2-mpeg2-ilace index 2f9a306c5..5c37c34c2 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-ilace +++ b/tests/ref/vsynth/vsynth2-mpeg2-ilace @@ -1,4 +1,4 @@ -a6f4c4dbd7f73b73e876fbd7a9650610 *tests/data/fate/vsynth2-mpeg2-ilace.mpeg2video +dbc7dd0272f3711f50722f4753e3bfb0 *tests/data/fate/vsynth2-mpeg2-ilace.mpeg2video 204576 tests/data/fate/vsynth2-mpeg2-ilace.mpeg2video d69be0d4ba1cb9c1fef9fb0d94a912ba *tests/data/fate/vsynth2-mpeg2-ilace.out.rawvideo stddev: 4.98 PSNR: 34.18 MAXDIFF: 65 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-ivlc-qprd b/tests/ref/vsynth/vsynth2-mpeg2-ivlc-qprd index 30e129baf..dea3f9423 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-ivlc-qprd +++ b/tests/ref/vsynth/vsynth2-mpeg2-ivlc-qprd @@ -1,4 +1,4 @@ -1ba5efeb53fab7b4b71edc96d86f6c91 *tests/data/fate/vsynth2-mpeg2-ivlc-qprd.mpeg2video +5731a196498d4e8097c0ebe57e383ef6 *tests/data/fate/vsynth2-mpeg2-ivlc-qprd.mpeg2video 244694 tests/data/fate/vsynth2-mpeg2-ivlc-qprd.mpeg2video b26e21599dee48a174bdbc40b2817e55 *tests/data/fate/vsynth2-mpeg2-ivlc-qprd.out.rawvideo stddev: 4.15 PSNR: 35.76 MAXDIFF: 74 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-thread b/tests/ref/vsynth/vsynth2-mpeg2-thread index 40552fed7..335d1c6db 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-thread +++ b/tests/ref/vsynth/vsynth2-mpeg2-thread @@ -1,4 +1,4 @@ -38af1e2261ae363abea5818db74ea241 *tests/data/fate/vsynth2-mpeg2-thread.mpeg2video +9e734d384b4234d075203dffffa5174c *tests/data/fate/vsynth2-mpeg2-thread.mpeg2video 179656 tests/data/fate/vsynth2-mpeg2-thread.mpeg2video f8f084b7f51fbe4f82d57b8aeec17edf *tests/data/fate/vsynth2-mpeg2-thread.out.rawvideo stddev: 4.72 PSNR: 34.65 MAXDIFF: 72 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-thread-ivlc b/tests/ref/vsynth/vsynth2-mpeg2-thread-ivlc index 9bcac8b59..67a380af3 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-thread-ivlc +++ b/tests/ref/vsynth/vsynth2-mpeg2-thread-ivlc @@ -1,4 +1,4 @@ -9cb6b65e05fa854da2ad08b34fe032aa *tests/data/fate/vsynth2-mpeg2-thread-ivlc.mpeg2video +39ae4e15e3da14218ebf250180badd92 *tests/data/fate/vsynth2-mpeg2-thread-ivlc.mpeg2video 178807 tests/data/fate/vsynth2-mpeg2-thread-ivlc.mpeg2video f8f084b7f51fbe4f82d57b8aeec17edf *tests/data/fate/vsynth2-mpeg2-thread-ivlc.out.rawvideo stddev: 4.72 PSNR: 34.65 MAXDIFF: 72 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4 b/tests/ref/vsynth/vsynth2-mpeg4 index 095654398..ac5ee3903 100644 --- a/tests/ref/vsynth/vsynth2-mpeg4 +++ b/tests/ref/vsynth/vsynth2-mpeg4 @@ -1,4 +1,4 @@ -3d99aa9393f2a1a9319580b78df2bf3d *tests/data/fate/vsynth2-mpeg4.mp4 -119661 tests/data/fate/vsynth2-mpeg4.mp4 +4a029747434d24d128b078a5e6aa1e88 *tests/data/fate/vsynth2-mpeg4.mp4 +119722 tests/data/fate/vsynth2-mpeg4.mp4 9a1e085d9e488c5ead0c940c9612a37a *tests/data/fate/vsynth2-mpeg4.out.rawvideo stddev: 5.34 PSNR: 33.57 MAXDIFF: 83 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4-adap b/tests/ref/vsynth/vsynth2-mpeg4-adap index 175552dd1..7a40c4bc3 100644 --- a/tests/ref/vsynth/vsynth2-mpeg4-adap +++ b/tests/ref/vsynth/vsynth2-mpeg4-adap @@ -1,4 +1,4 @@ -4b39d46a436f1bce59e2902cec3478e9 *tests/data/fate/vsynth2-mpeg4-adap.avi +bbb12e077f858242c1387d23d2ccdae8 *tests/data/fate/vsynth2-mpeg4-adap.avi 198496 tests/data/fate/vsynth2-mpeg4-adap.avi 87b6dbe98d276137fceaae2fa672eced *tests/data/fate/vsynth2-mpeg4-adap.out.rawvideo stddev: 3.75 PSNR: 36.65 MAXDIFF: 71 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4-adv b/tests/ref/vsynth/vsynth2-mpeg4-adv index b3bf2646e..c1385cad3 100644 --- a/tests/ref/vsynth/vsynth2-mpeg4-adv +++ b/tests/ref/vsynth/vsynth2-mpeg4-adv @@ -1,4 +1,4 @@ -1875ae5a45936c08778c4430a22e87eb *tests/data/fate/vsynth2-mpeg4-adv.avi +9fa1b5a68a6128a7160cfc8443a696e1 *tests/data/fate/vsynth2-mpeg4-adv.avi 141534 tests/data/fate/vsynth2-mpeg4-adv.avi 3f3a21e9db85a9c0f7022f557a5374c1 *tests/data/fate/vsynth2-mpeg4-adv.out.rawvideo stddev: 4.94 PSNR: 34.25 MAXDIFF: 69 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4-error b/tests/ref/vsynth/vsynth2-mpeg4-error index c6a221867..a8d93bc80 100644 --- a/tests/ref/vsynth/vsynth2-mpeg4-error +++ b/tests/ref/vsynth/vsynth2-mpeg4-error @@ -1,4 +1,4 @@ -599a21c149a150072db364298dbcdda2 *tests/data/fate/vsynth2-mpeg4-error.avi +82510449a3200b58dbcfbf0a643eb624 *tests/data/fate/vsynth2-mpeg4-error.avi 180364 tests/data/fate/vsynth2-mpeg4-error.avi 4537ba5320f1ae0971cc6e329c366776 *tests/data/fate/vsynth2-mpeg4-error.out.rawvideo stddev: 7.65 PSNR: 30.45 MAXDIFF: 158 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4-nr b/tests/ref/vsynth/vsynth2-mpeg4-nr index 45db4b6e4..05dcc54a5 100644 --- a/tests/ref/vsynth/vsynth2-mpeg4-nr +++ b/tests/ref/vsynth/vsynth2-mpeg4-nr @@ -1,4 +1,4 @@ -e1cf863ec6c0a4975d49326df63342ca *tests/data/fate/vsynth2-mpeg4-nr.avi +cf0cde80515f8bfbd89d33aa51f1c5e1 *tests/data/fate/vsynth2-mpeg4-nr.avi 154994 tests/data/fate/vsynth2-mpeg4-nr.avi d89cd5d0b1707f48fa9c4747c66d2d56 *tests/data/fate/vsynth2-mpeg4-nr.out.rawvideo stddev: 4.73 PSNR: 34.63 MAXDIFF: 64 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4-nsse b/tests/ref/vsynth/vsynth2-mpeg4-nsse new file mode 100644 index 000000000..083351903 --- /dev/null +++ b/tests/ref/vsynth/vsynth2-mpeg4-nsse @@ -0,0 +1,4 @@ +b60bb3d8b942795272f0f0d89cd6351e *tests/data/fate/vsynth2-mpeg4-nsse.avi +198434 tests/data/fate/vsynth2-mpeg4-nsse.avi +59864a1050e641eaed8b0ee077bc780b *tests/data/fate/vsynth2-mpeg4-nsse.out.rawvideo +stddev: 4.32 PSNR: 35.40 MAXDIFF: 60 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4-qpel b/tests/ref/vsynth/vsynth2-mpeg4-qpel index 8705bd518..28225806b 100644 --- a/tests/ref/vsynth/vsynth2-mpeg4-qpel +++ b/tests/ref/vsynth/vsynth2-mpeg4-qpel @@ -1,4 +1,4 @@ -b36ad1ca7ac6e1aff6d69b8df4386011 *tests/data/fate/vsynth2-mpeg4-qpel.avi +ab94d9e56635e100d95e74fc8dc845e5 *tests/data/fate/vsynth2-mpeg4-qpel.avi 163662 tests/data/fate/vsynth2-mpeg4-qpel.avi e2ce994dbb66da51c2e1ad26617d7c2f *tests/data/fate/vsynth2-mpeg4-qpel.out.rawvideo stddev: 3.97 PSNR: 36.14 MAXDIFF: 54 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4-qprd b/tests/ref/vsynth/vsynth2-mpeg4-qprd index 1bbda29f0..287fff22f 100644 --- a/tests/ref/vsynth/vsynth2-mpeg4-qprd +++ b/tests/ref/vsynth/vsynth2-mpeg4-qprd @@ -1,4 +1,4 @@ -ee24ddde5e3c06a6c44093a59e7ac413 *tests/data/fate/vsynth2-mpeg4-qprd.avi +a576ecbf48c33916f2d17cf1bf37f3fe *tests/data/fate/vsynth2-mpeg4-qprd.avi 231450 tests/data/fate/vsynth2-mpeg4-qprd.avi 3071250e0864546c2455c9f9c9b8604e *tests/data/fate/vsynth2-mpeg4-qprd.out.rawvideo stddev: 3.71 PSNR: 36.72 MAXDIFF: 61 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4-rc b/tests/ref/vsynth/vsynth2-mpeg4-rc index 2a26a1622..ccf4400ff 100644 --- a/tests/ref/vsynth/vsynth2-mpeg4-rc +++ b/tests/ref/vsynth/vsynth2-mpeg4-rc @@ -1,4 +1,4 @@ -20028333988bb7a0888a79799ea63b19 *tests/data/fate/vsynth2-mpeg4-rc.avi +ea96539a0bebf70c3c09de0199a53a30 *tests/data/fate/vsynth2-mpeg4-rc.avi 226310 tests/data/fate/vsynth2-mpeg4-rc.avi 6e8b62e8c3bcbfdcc58afb69a0b1c4e3 *tests/data/fate/vsynth2-mpeg4-rc.out.rawvideo stddev: 4.23 PSNR: 35.60 MAXDIFF: 85 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4-thread b/tests/ref/vsynth/vsynth2-mpeg4-thread index d8d87c4bd..f8475df45 100644 --- a/tests/ref/vsynth/vsynth2-mpeg4-thread +++ b/tests/ref/vsynth/vsynth2-mpeg4-thread @@ -1,4 +1,4 @@ -d50954ec2c64c2634d88ba1df879dde0 *tests/data/fate/vsynth2-mpeg4-thread.avi +8d7903d55221035c67866b8c1314c499 *tests/data/fate/vsynth2-mpeg4-thread.avi 250092 tests/data/fate/vsynth2-mpeg4-thread.avi 045fe9f226bbcc3d41644bffaed03b31 *tests/data/fate/vsynth2-mpeg4-thread.out.rawvideo stddev: 3.69 PSNR: 36.78 MAXDIFF: 65 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpng b/tests/ref/vsynth/vsynth2-mpng index 2e6865c78..31fbdcc62 100644 --- a/tests/ref/vsynth/vsynth2-mpng +++ b/tests/ref/vsynth/vsynth2-mpng @@ -1,4 +1,4 @@ -b8f9aa584da89837058c96fc5c3a6562 *tests/data/fate/vsynth2-mpng.avi +aaee9d1ff7dccfc045603c45f0160000 *tests/data/fate/vsynth2-mpng.avi 12558330 tests/data/fate/vsynth2-mpng.avi 98d0e2854731472c5bf13d8638502d0a *tests/data/fate/vsynth2-mpng.out.rawvideo stddev: 1.26 PSNR: 46.10 MAXDIFF: 13 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-msmpeg4 b/tests/ref/vsynth/vsynth2-msmpeg4 index 274cecc54..439bb4e56 100644 --- a/tests/ref/vsynth/vsynth2-msmpeg4 +++ b/tests/ref/vsynth/vsynth2-msmpeg4 @@ -1,4 +1,4 @@ -6eb2a9770c223636befacfba83f72c44 *tests/data/fate/vsynth2-msmpeg4.avi +50b91fe78559c0f5f1e5873cdcc0e6a8 *tests/data/fate/vsynth2-msmpeg4.avi 127660 tests/data/fate/vsynth2-msmpeg4.avi bb14902d5850d6b0ab70fdb017855775 *tests/data/fate/vsynth2-msmpeg4.out.rawvideo stddev: 5.33 PSNR: 33.58 MAXDIFF: 78 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-msmpeg4v2 b/tests/ref/vsynth/vsynth2-msmpeg4v2 index a851a2f6c..985089a70 100644 --- a/tests/ref/vsynth/vsynth2-msmpeg4v2 +++ b/tests/ref/vsynth/vsynth2-msmpeg4v2 @@ -1,4 +1,4 @@ -e0929f2cebefc9f6259870b806829de3 *tests/data/fate/vsynth2-msmpeg4v2.avi +4770bd848f1937a861bf1a72295c6094 *tests/data/fate/vsynth2-msmpeg4v2.avi 129918 tests/data/fate/vsynth2-msmpeg4v2.avi 537c114e1d47c54a4bccd31f4073e9bd *tests/data/fate/vsynth2-msmpeg4v2.out.rawvideo stddev: 5.33 PSNR: 33.59 MAXDIFF: 79 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-msvideo1 b/tests/ref/vsynth/vsynth2-msvideo1 index a915c1311..421ad8799 100644 --- a/tests/ref/vsynth/vsynth2-msvideo1 +++ b/tests/ref/vsynth/vsynth2-msvideo1 @@ -1,4 +1,4 @@ -6c1709d61202ec2e73b467e76cb79f9b *tests/data/fate/vsynth2-msvideo1.avi +e554e31a4a635c924391228b7194d21b *tests/data/fate/vsynth2-msvideo1.avi 914560 tests/data/fate/vsynth2-msvideo1.avi 9a6ac7c0171286f009d159b59fdc1154 *tests/data/fate/vsynth2-msvideo1.out.rawvideo stddev: 7.97 PSNR: 30.10 MAXDIFF: 123 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-prores b/tests/ref/vsynth/vsynth2-prores index 82311b4df..a46fa4831 100644 --- a/tests/ref/vsynth/vsynth2-prores +++ b/tests/ref/vsynth/vsynth2-prores @@ -1,4 +1,4 @@ -af885572d77d28e5ede27932bd68cdde *tests/data/fate/vsynth2-prores.mov +637f34b5fd81f072f76a967595fa6af7 *tests/data/fate/vsynth2-prores.mov 2844076 tests/data/fate/vsynth2-prores.mov 03fd29e3963716a09d232b6f817ecb57 *tests/data/fate/vsynth2-prores.out.rawvideo stddev: 1.31 PSNR: 45.77 MAXDIFF: 11 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-prores_ks b/tests/ref/vsynth/vsynth2-prores_ks index d538a11d0..ff815e52b 100644 --- a/tests/ref/vsynth/vsynth2-prores_ks +++ b/tests/ref/vsynth/vsynth2-prores_ks @@ -1,4 +1,4 @@ -c1c71cf2dbd6e332aacb6ab1c6affa59 *tests/data/fate/vsynth2-prores_ks.mov +b03741c69037cbdcd2809278c00c0350 *tests/data/fate/vsynth2-prores_ks.mov 3884596 tests/data/fate/vsynth2-prores_ks.mov 6cfe987de99cf8ac9d43bdc5cd150838 *tests/data/fate/vsynth2-prores_ks.out.rawvideo stddev: 0.92 PSNR: 48.78 MAXDIFF: 10 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-qtrle b/tests/ref/vsynth/vsynth2-qtrle index 0ae2d00af..c9bf1e363 100644 --- a/tests/ref/vsynth/vsynth2-qtrle +++ b/tests/ref/vsynth/vsynth2-qtrle @@ -1,4 +1,4 @@ -3172f6a2c63e591048fe3309795f2d7a *tests/data/fate/vsynth2-qtrle.mov +4863978263d966d704ffaaa6d23123bb *tests/data/fate/vsynth2-qtrle.mov 14798345 tests/data/fate/vsynth2-qtrle.mov 98d0e2854731472c5bf13d8638502d0a *tests/data/fate/vsynth2-qtrle.out.rawvideo stddev: 1.26 PSNR: 46.10 MAXDIFF: 13 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-qtrlegray b/tests/ref/vsynth/vsynth2-qtrlegray index 8f01304d0..8b83a5ad0 100644 --- a/tests/ref/vsynth/vsynth2-qtrlegray +++ b/tests/ref/vsynth/vsynth2-qtrlegray @@ -1,4 +1,4 @@ -5304bbafd31bb8bf3d274f1d01db81f5 *tests/data/fate/vsynth2-qtrlegray.mov +2c4e69b59d8e8e19903c843575806d5f *tests/data/fate/vsynth2-qtrlegray.mov 5111283 tests/data/fate/vsynth2-qtrlegray.mov d7bfbe259af9ae323bb94b09c33570a5 *tests/data/fate/vsynth2-qtrlegray.out.rawvideo stddev: 18.65 PSNR: 22.72 MAXDIFF: 72 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-r210 b/tests/ref/vsynth/vsynth2-r210 index a91c12a64..e42d7973b 100644 --- a/tests/ref/vsynth/vsynth2-r210 +++ b/tests/ref/vsynth/vsynth2-r210 @@ -1,4 +1,4 @@ -4568992c4f5562be06374519a419d3a3 *tests/data/fate/vsynth2-r210.avi +16717c6cee907554cbeaefbbc116cd66 *tests/data/fate/vsynth2-r210.avi 22125248 tests/data/fate/vsynth2-r210.avi 6ea4fcd93fc83defc8770e85b64b60bb *tests/data/fate/vsynth2-r210.out.rawvideo stddev: 0.70 PSNR: 51.12 MAXDIFF: 12 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-rgb b/tests/ref/vsynth/vsynth2-rgb index 6f5169db5..f86c37c3e 100644 --- a/tests/ref/vsynth/vsynth2-rgb +++ b/tests/ref/vsynth/vsynth2-rgb @@ -1,4 +1,4 @@ -01199075994e44f282fbb6a8e3ccc668 *tests/data/fate/vsynth2-rgb.avi +188bce319523a1c7d24103aab1ed1bda *tests/data/fate/vsynth2-rgb.avi 15213248 tests/data/fate/vsynth2-rgb.avi 98d0e2854731472c5bf13d8638502d0a *tests/data/fate/vsynth2-rgb.out.rawvideo stddev: 1.26 PSNR: 46.10 MAXDIFF: 13 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-roqvideo b/tests/ref/vsynth/vsynth2-roqvideo index d4c075a89..c8b02e740 100644 --- a/tests/ref/vsynth/vsynth2-roqvideo +++ b/tests/ref/vsynth/vsynth2-roqvideo @@ -1,4 +1,4 @@ -b46f899b2363065c60f3782ba1f8b7bd *tests/data/fate/vsynth2-roqvideo.roq -92786 tests/data/fate/vsynth2-roqvideo.roq -e69fca960dd0911e9b8d589c13e11dc1 *tests/data/fate/vsynth2-roqvideo.out.rawvideo -stddev: 3.81 PSNR: 36.49 MAXDIFF: 54 bytes: 7603200/ 760320 +1a43cd71c91f2ef42d11a81419bff3bd *tests/data/fate/vsynth2-roqvideo.roq +94810 tests/data/fate/vsynth2-roqvideo.roq +97cda6096430c0ab7a43a0e120cd3e91 *tests/data/fate/vsynth2-roqvideo.out.rawvideo +stddev: 3.81 PSNR: 36.50 MAXDIFF: 49 bytes: 7603200/ 760320 diff --git a/tests/ref/vsynth/vsynth2-snow b/tests/ref/vsynth/vsynth2-snow index 12f3811d0..74b60682f 100644 --- a/tests/ref/vsynth/vsynth2-snow +++ b/tests/ref/vsynth/vsynth2-snow @@ -1,4 +1,4 @@ -4b6236e23ae4a52655f2c24c5a09380a *tests/data/fate/vsynth2-snow.avi +a7bc7eba6ac50f0b417cb9f829feb7a1 *tests/data/fate/vsynth2-snow.avi 57688 tests/data/fate/vsynth2-snow.avi 8890189af71a0dd3447c4e8424c9a76b *tests/data/fate/vsynth2-snow.out.rawvideo stddev: 10.47 PSNR: 27.72 MAXDIFF: 119 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-snow-hpel b/tests/ref/vsynth/vsynth2-snow-hpel index 955f1bf73..f43263ee0 100644 --- a/tests/ref/vsynth/vsynth2-snow-hpel +++ b/tests/ref/vsynth/vsynth2-snow-hpel @@ -1,4 +1,4 @@ -9872032345c33cf8e8fc26ab655be3d3 *tests/data/fate/vsynth2-snow-hpel.avi +fa6986c9ebaa087b037d099acefa0ade *tests/data/fate/vsynth2-snow-hpel.avi 61760 tests/data/fate/vsynth2-snow-hpel.avi 8680d40905f423999d65b996c4dcb984 *tests/data/fate/vsynth2-snow-hpel.out.rawvideo stddev: 10.45 PSNR: 27.74 MAXDIFF: 123 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-snow-ll b/tests/ref/vsynth/vsynth2-snow-ll index 9a725492e..db2ffa97a 100644 --- a/tests/ref/vsynth/vsynth2-snow-ll +++ b/tests/ref/vsynth/vsynth2-snow-ll @@ -1,4 +1,4 @@ -30b40e0bf64f92b23d6f94056c0c6da5 *tests/data/fate/vsynth2-snow-ll.avi +ed109f21012f92ad5ea19451844ae721 *tests/data/fate/vsynth2-snow-ll.avi 2721746 tests/data/fate/vsynth2-snow-ll.avi dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth2-snow-ll.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-svq1 b/tests/ref/vsynth/vsynth2-svq1 index 72cc6f9e6..afad59cf0 100644 --- a/tests/ref/vsynth/vsynth2-svq1 +++ b/tests/ref/vsynth/vsynth2-svq1 @@ -1,4 +1,4 @@ -ab9b1f922c4ae1b5d602bdeebc8b185d *tests/data/fate/vsynth2-svq1.mov +6e9678439ab7460db1fcc8e41ca1a1e0 *tests/data/fate/vsynth2-svq1.mov 766701 tests/data/fate/vsynth2-svq1.mov aa03471dac3f49455a33a2b19fda1098 *tests/data/fate/vsynth2-svq1.out.rawvideo stddev: 3.23 PSNR: 37.93 MAXDIFF: 61 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-v210 b/tests/ref/vsynth/vsynth2-v210 index eb80b3424..1320c38a5 100644 --- a/tests/ref/vsynth/vsynth2-v210 +++ b/tests/ref/vsynth/vsynth2-v210 @@ -1,4 +1,4 @@ -ddc80f41b9e92c26adbe09567a4c7a1d *tests/data/fate/vsynth2-v210.avi +6fbbcfee1832fe4c62aacb70454cff62 *tests/data/fate/vsynth2-v210.avi 14752448 tests/data/fate/vsynth2-v210.avi a627fb50c8276200fd71383977d87ca3 *tests/data/fate/vsynth2-v210.out.rawvideo stddev: 0.34 PSNR: 57.43 MAXDIFF: 6 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-v308 b/tests/ref/vsynth/vsynth2-v308 index f7c46fcb4..f32dc5d4f 100644 --- a/tests/ref/vsynth/vsynth2-v308 +++ b/tests/ref/vsynth/vsynth2-v308 @@ -1,4 +1,4 @@ -aba17ed2860ac714da0e378ebe47e7bb *tests/data/fate/vsynth2-v308.avi +1ea64cd6ad32dae72963b8fdf89e96d1 *tests/data/fate/vsynth2-v308.avi 15213248 tests/data/fate/vsynth2-v308.avi d43cb310c130c69214332d74f6ee5f9a *tests/data/fate/vsynth2-v308.out.rawvideo stddev: 0.41 PSNR: 55.80 MAXDIFF: 7 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-v408 b/tests/ref/vsynth/vsynth2-v408 index 4c63deca3..333a4e3b2 100644 --- a/tests/ref/vsynth/vsynth2-v408 +++ b/tests/ref/vsynth/vsynth2-v408 @@ -1,4 +1,4 @@ -d689d4a53081765f0fbc965554c06faa *tests/data/fate/vsynth2-v408.avi +b4cdf2351f908fc308d8693d0cee69e1 *tests/data/fate/vsynth2-v408.avi 20282048 tests/data/fate/vsynth2-v408.avi dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth2-v408.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-wmv1 b/tests/ref/vsynth/vsynth2-wmv1 index 6e56b6f34..6e325ba77 100644 --- a/tests/ref/vsynth/vsynth2-wmv1 +++ b/tests/ref/vsynth/vsynth2-wmv1 @@ -1,4 +1,4 @@ -dc2affb9b9a95a09dd69c25c75c50174 *tests/data/fate/vsynth2-wmv1.avi +3099f5514693a609180ab5761dc8d4ca *tests/data/fate/vsynth2-wmv1.avi 129510 tests/data/fate/vsynth2-wmv1.avi dec44e3c04db4fef49a7728f164d9159 *tests/data/fate/vsynth2-wmv1.out.rawvideo stddev: 5.33 PSNR: 33.60 MAXDIFF: 77 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-wmv2 b/tests/ref/vsynth/vsynth2-wmv2 index 5de48986f..72fe406eb 100644 --- a/tests/ref/vsynth/vsynth2-wmv2 +++ b/tests/ref/vsynth/vsynth2-wmv2 @@ -1,4 +1,4 @@ -1b0e968e180346914c11875f4eec57eb *tests/data/fate/vsynth2-wmv2.avi +c8d1d1371bd09add388c32f3259ef555 *tests/data/fate/vsynth2-wmv2.avi 129852 tests/data/fate/vsynth2-wmv2.avi b4de16a0d302c52702f7a4362da989bc *tests/data/fate/vsynth2-wmv2.out.rawvideo stddev: 5.33 PSNR: 33.59 MAXDIFF: 77 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-y41p b/tests/ref/vsynth/vsynth2-y41p index ac9d64aa5..9c782f86e 100644 --- a/tests/ref/vsynth/vsynth2-y41p +++ b/tests/ref/vsynth/vsynth2-y41p @@ -1,4 +1,4 @@ -0689a7a5c4dd6ac6ac515b54d45d249e *tests/data/fate/vsynth2-y41p.avi +522ebf5fbf98aeec5ee6b39de1c1afc0 *tests/data/fate/vsynth2-y41p.avi 7610048 tests/data/fate/vsynth2-y41p.avi d27a84ccdac09055724d122e03fea82a *tests/data/fate/vsynth2-y41p.out.rawvideo stddev: 1.07 PSNR: 47.54 MAXDIFF: 21 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-yuv b/tests/ref/vsynth/vsynth2-yuv index d6b873693..066cfec18 100644 --- a/tests/ref/vsynth/vsynth2-yuv +++ b/tests/ref/vsynth/vsynth2-yuv @@ -1,4 +1,4 @@ -0029ade090172b34687cdc9163748e47 *tests/data/fate/vsynth2-yuv.avi +f48f08c67097b3c35b1105f24ef68a0c *tests/data/fate/vsynth2-yuv.avi 7610048 tests/data/fate/vsynth2-yuv.avi dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth2-yuv.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-yuv4 b/tests/ref/vsynth/vsynth2-yuv4 index 8fa347a2c..b76cee409 100644 --- a/tests/ref/vsynth/vsynth2-yuv4 +++ b/tests/ref/vsynth/vsynth2-yuv4 @@ -1,4 +1,4 @@ -00454056d8560cde37409e0b578209d8 *tests/data/fate/vsynth2-yuv4.avi +1dcf2c21fe3ff1b57f9280a4fd550d14 *tests/data/fate/vsynth2-yuv4.avi 7610048 tests/data/fate/vsynth2-yuv4.avi dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth2-yuv4.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-zlib b/tests/ref/vsynth/vsynth2-zlib index 0a7ed3ced..d956a0444 100644 --- a/tests/ref/vsynth/vsynth2-zlib +++ b/tests/ref/vsynth/vsynth2-zlib @@ -1,4 +1,4 @@ -d0e240b5241c3e0a5f813644d3dc5d9f *tests/data/fate/vsynth2-zlib.avi +f2c6b3c88f07f0ed08dd25ca654854fb *tests/data/fate/vsynth2-zlib.avi 12517176 tests/data/fate/vsynth2-zlib.avi 98d0e2854731472c5bf13d8638502d0a *tests/data/fate/vsynth2-zlib.out.rawvideo stddev: 1.26 PSNR: 46.10 MAXDIFF: 13 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth3-amv b/tests/ref/vsynth/vsynth3-amv new file mode 100644 index 000000000..bbfba3e68 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-amv @@ -0,0 +1,4 @@ +4d0844cd148bd9fa8155b72cc4a6e991 *tests/data/fate/vsynth3-amv.avi +33928 tests/data/fate/vsynth3-amv.avi +f916c620790a9cf2674391610985ae27 *tests/data/fate/vsynth3-amv.out.rawvideo +stddev: 11.58 PSNR: 26.85 MAXDIFF: 89 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-asv1 b/tests/ref/vsynth/vsynth3-asv1 new file mode 100644 index 000000000..fd5f82dc6 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-asv1 @@ -0,0 +1,4 @@ +43c51aa52666de02dfa49fd1c10a558f *tests/data/fate/vsynth3-asv1.avi +36664 tests/data/fate/vsynth3-asv1.avi +fd156079afc2753dde7d6a8418b2a25a *tests/data/fate/vsynth3-asv1.out.rawvideo +stddev: 21.25 PSNR: 21.58 MAXDIFF: 122 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-asv2 b/tests/ref/vsynth/vsynth3-asv2 new file mode 100644 index 000000000..360bb0720 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-asv2 @@ -0,0 +1,4 @@ +8958facfc4853267ece3b7868df80229 *tests/data/fate/vsynth3-asv2.avi +35620 tests/data/fate/vsynth3-asv2.avi +ff711d6341966f03ee32b73ae22493ed *tests/data/fate/vsynth3-asv2.out.rawvideo +stddev: 19.98 PSNR: 22.12 MAXDIFF: 113 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-cljr b/tests/ref/vsynth/vsynth3-cljr new file mode 100644 index 000000000..9a2daa4b7 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-cljr @@ -0,0 +1,4 @@ +c05ee9983a4f8fe62d7270507a87655b *tests/data/fate/vsynth3-cljr.avi +68048 tests/data/fate/vsynth3-cljr.avi +ac4c80dda332b6311beb1e8f723c13ca *tests/data/fate/vsynth3-cljr.out.rawvideo +stddev: 7.51 PSNR: 30.61 MAXDIFF: 84 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-ffv1 b/tests/ref/vsynth/vsynth3-ffv1 new file mode 100644 index 000000000..cdd011a59 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-ffv1 @@ -0,0 +1,4 @@ +b781c01d152c5a040ee71b2421b6d8e6 *tests/data/fate/vsynth3-ffv1.avi +62190 tests/data/fate/vsynth3-ffv1.avi +a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-ffv1.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-ffv1.0 b/tests/ref/vsynth/vsynth3-ffv1.0 new file mode 100644 index 000000000..6e2c4e071 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-ffv1.0 @@ -0,0 +1,4 @@ +aa9187b44d9d8ff4d0ac7b9c5301830c *tests/data/fate/vsynth3-ffv1.0.avi +52252 tests/data/fate/vsynth3-ffv1.0.avi +a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-ffv1.0.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-ffvhuff b/tests/ref/vsynth/vsynth3-ffvhuff new file mode 100644 index 000000000..c89611f27 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-ffvhuff @@ -0,0 +1,4 @@ +bc18700e9ce7947fe4c5ffc71457f3c1 *tests/data/fate/vsynth3-ffvhuff.avi +90206 tests/data/fate/vsynth3-ffvhuff.avi +a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-ffvhuff.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-ffvhuff420p12 b/tests/ref/vsynth/vsynth3-ffvhuff420p12 new file mode 100644 index 000000000..b51882eed --- /dev/null +++ b/tests/ref/vsynth/vsynth3-ffvhuff420p12 @@ -0,0 +1,4 @@ +a6164daa3036ae92eb0b3f0831268165 *tests/data/fate/vsynth3-ffvhuff420p12.avi +172132 tests/data/fate/vsynth3-ffvhuff420p12.avi +eb1a8ff2c33ba5145b5a89727ee5dcb8 *tests/data/fate/vsynth3-ffvhuff420p12.out.rawvideo +stddev: 46.89 PSNR: 14.71 MAXDIFF: 239 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-ffvhuff422p10left b/tests/ref/vsynth/vsynth3-ffvhuff422p10left new file mode 100644 index 000000000..7dca14e9b --- /dev/null +++ b/tests/ref/vsynth/vsynth3-ffvhuff422p10left @@ -0,0 +1,4 @@ +2459272ee10f3b503940324ba5dcc1e5 *tests/data/fate/vsynth3-ffvhuff422p10left.avi +168836 tests/data/fate/vsynth3-ffvhuff422p10left.avi +863818eed035b3fa7b19535927687879 *tests/data/fate/vsynth3-ffvhuff422p10left.out.rawvideo +stddev: 38.45 PSNR: 16.43 MAXDIFF: 225 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-ffvhuff444 b/tests/ref/vsynth/vsynth3-ffvhuff444 new file mode 100644 index 000000000..8446a7f5a --- /dev/null +++ b/tests/ref/vsynth/vsynth3-ffvhuff444 @@ -0,0 +1,4 @@ +134851e6f9702e83c4c9aa6e5ff1eaa4 *tests/data/fate/vsynth3-ffvhuff444.avi +151362 tests/data/fate/vsynth3-ffvhuff444.avi +02a85ec07377df6b483281038f8882ee *tests/data/fate/vsynth3-ffvhuff444.out.rawvideo +stddev: 3.06 PSNR: 38.40 MAXDIFF: 40 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-ffvhuff444p16 b/tests/ref/vsynth/vsynth3-ffvhuff444p16 new file mode 100644 index 000000000..842104f7b --- /dev/null +++ b/tests/ref/vsynth/vsynth3-ffvhuff444p16 @@ -0,0 +1,4 @@ +1a6e53646d0988bd67ced92923439e51 *tests/data/fate/vsynth3-ffvhuff444p16.avi +320084 tests/data/fate/vsynth3-ffvhuff444p16.avi +e5933e1e6dbacddb78e6d90cd5ed2b5d *tests/data/fate/vsynth3-ffvhuff444p16.out.rawvideo +stddev: 3.06 PSNR: 38.40 MAXDIFF: 40 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-flashsv b/tests/ref/vsynth/vsynth3-flashsv new file mode 100644 index 000000000..38a34bd71 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-flashsv @@ -0,0 +1,4 @@ +832fe60169f4d91339458c60a5292924 *tests/data/fate/vsynth3-flashsv.flv +171419 tests/data/fate/vsynth3-flashsv.flv +faa660b0ecaaab1bf9b5d7284019aa01 *tests/data/fate/vsynth3-flashsv.out.rawvideo +stddev: 2.97 PSNR: 38.67 MAXDIFF: 49 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-flashsv2 b/tests/ref/vsynth/vsynth3-flashsv2 new file mode 100644 index 000000000..31d0d3f2b --- /dev/null +++ b/tests/ref/vsynth/vsynth3-flashsv2 @@ -0,0 +1,4 @@ +ba57c9555329e60250905def79fe6257 *tests/data/fate/vsynth3-flashsv2.flv +107956 tests/data/fate/vsynth3-flashsv2.flv +fb6b5134561d86fc05ccce9323553b80 *tests/data/fate/vsynth3-flashsv2.out.rawvideo +stddev: 3.62 PSNR: 36.95 MAXDIFF: 49 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-flv b/tests/ref/vsynth/vsynth3-flv new file mode 100644 index 000000000..7abe2b54c --- /dev/null +++ b/tests/ref/vsynth/vsynth3-flv @@ -0,0 +1,4 @@ +c36dbc8109d1ceed68bd5590084eb375 *tests/data/fate/vsynth3-flv.flv +28496 tests/data/fate/vsynth3-flv.flv +b82944d78d1ee68a36d01933c9602520 *tests/data/fate/vsynth3-flv.out.rawvideo +stddev: 9.71 PSNR: 28.38 MAXDIFF: 86 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-huffyuv b/tests/ref/vsynth/vsynth3-huffyuv new file mode 100644 index 000000000..0a16b6554 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-huffyuv @@ -0,0 +1,4 @@ +27cd1ec1151b7456117f98a8cdf281cd *tests/data/fate/vsynth3-huffyuv.avi +116346 tests/data/fate/vsynth3-huffyuv.avi +a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-huffyuv.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-huffyuvbgr24 b/tests/ref/vsynth/vsynth3-huffyuvbgr24 new file mode 100644 index 000000000..95f4422ac --- /dev/null +++ b/tests/ref/vsynth/vsynth3-huffyuvbgr24 @@ -0,0 +1,4 @@ +a7bf0c82277d59d425ebe4af93f75e27 *tests/data/fate/vsynth3-huffyuvbgr24.avi +165154 tests/data/fate/vsynth3-huffyuvbgr24.avi +5d031d2e891b13593b8cd79e63d083b4 *tests/data/fate/vsynth3-huffyuvbgr24.out.rawvideo +stddev: 3.23 PSNR: 37.92 MAXDIFF: 50 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-jpeg2000 b/tests/ref/vsynth/vsynth3-jpeg2000 new file mode 100644 index 000000000..6b5f110fc --- /dev/null +++ b/tests/ref/vsynth/vsynth3-jpeg2000 @@ -0,0 +1,4 @@ +1c49dca7b2d828b9a551bf66f3324f3d *tests/data/fate/vsynth3-jpeg2000.avi +63768 tests/data/fate/vsynth3-jpeg2000.avi +11b954cc1b0091399fa4342a6bb432b2 *tests/data/fate/vsynth3-jpeg2000.out.rawvideo +stddev: 5.50 PSNR: 33.31 MAXDIFF: 48 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-jpeg2000-97 b/tests/ref/vsynth/vsynth3-jpeg2000-97 new file mode 100644 index 000000000..1087241da --- /dev/null +++ b/tests/ref/vsynth/vsynth3-jpeg2000-97 @@ -0,0 +1,4 @@ +9ce2c4690cbc85aae9e9e5227e74eb94 *tests/data/fate/vsynth3-jpeg2000-97.avi +65360 tests/data/fate/vsynth3-jpeg2000-97.avi +f9dad7a31175e400ca35de60aec826fd *tests/data/fate/vsynth3-jpeg2000-97.out.rawvideo +stddev: 6.27 PSNR: 32.17 MAXDIFF: 52 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-jpegls b/tests/ref/vsynth/vsynth3-jpegls new file mode 100644 index 000000000..b03537342 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-jpegls @@ -0,0 +1,4 @@ +13bf416e04554609ddc2830912ff1d89 *tests/data/fate/vsynth3-jpegls.avi +133164 tests/data/fate/vsynth3-jpegls.avi +faa660b0ecaaab1bf9b5d7284019aa01 *tests/data/fate/vsynth3-jpegls.out.rawvideo +stddev: 2.97 PSNR: 38.67 MAXDIFF: 49 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-ljpeg b/tests/ref/vsynth/vsynth3-ljpeg new file mode 100644 index 000000000..47db0c1d3 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-ljpeg @@ -0,0 +1,4 @@ +39cd774ffe47c804f2f58d5bbcf7b0a5 *tests/data/fate/vsynth3-ljpeg.avi +105840 tests/data/fate/vsynth3-ljpeg.avi +a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-ljpeg.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mjpeg b/tests/ref/vsynth/vsynth3-mjpeg new file mode 100644 index 000000000..25036c8d5 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mjpeg @@ -0,0 +1,4 @@ +cf68ecc19e6c07d2a0c211e6ad1e3d9f *tests/data/fate/vsynth3-mjpeg.avi +64804 tests/data/fate/vsynth3-mjpeg.avi +c4fe7a2669afbd96c640748693fc4e30 *tests/data/fate/vsynth3-mjpeg.out.rawvideo +stddev: 8.60 PSNR: 29.43 MAXDIFF: 58 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mjpeg-422 b/tests/ref/vsynth/vsynth3-mjpeg-422 new file mode 100644 index 000000000..23c58bbcb --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mjpeg-422 @@ -0,0 +1,4 @@ +c1f42031676078a7cfc38a7eb53c89e8 *tests/data/fate/vsynth3-mjpeg-422.avi +69458 tests/data/fate/vsynth3-mjpeg-422.avi +a332893cb0603f2f505fe5d3bf105519 *tests/data/fate/vsynth3-mjpeg-422.out.rawvideo +stddev: 8.23 PSNR: 29.82 MAXDIFF: 58 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mjpeg-444 b/tests/ref/vsynth/vsynth3-mjpeg-444 new file mode 100644 index 000000000..d17df66eb --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mjpeg-444 @@ -0,0 +1,4 @@ +893c830a9635aaf686f53372cbe5e0ed *tests/data/fate/vsynth3-mjpeg-444.avi +70584 tests/data/fate/vsynth3-mjpeg-444.avi +79a901f2ed85d82cf1c674fab3d3ef72 *tests/data/fate/vsynth3-mjpeg-444.out.rawvideo +stddev: 8.21 PSNR: 29.84 MAXDIFF: 58 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg1 b/tests/ref/vsynth/vsynth3-mpeg1 new file mode 100644 index 000000000..7a3b484d6 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg1 @@ -0,0 +1,4 @@ +972ddac6afa89f1344d02b25542fc469 *tests/data/fate/vsynth3-mpeg1.mpeg1video +28028 tests/data/fate/vsynth3-mpeg1.mpeg1video +bffc40252da80b55302666b0046468c2 *tests/data/fate/vsynth3-mpeg1.out.rawvideo +stddev: 9.10 PSNR: 28.94 MAXDIFF: 63 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg1b b/tests/ref/vsynth/vsynth3-mpeg1b new file mode 100644 index 000000000..adfa41887 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg1b @@ -0,0 +1,4 @@ +a2e36336e35f9466c883ade059c6485e *tests/data/fate/vsynth3-mpeg1b.mpeg1video +38251 tests/data/fate/vsynth3-mpeg1b.mpeg1video +c44023d27be27deb7f3793321655ca75 *tests/data/fate/vsynth3-mpeg1b.out.rawvideo +stddev: 7.00 PSNR: 31.22 MAXDIFF: 56 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg2 b/tests/ref/vsynth/vsynth3-mpeg2 new file mode 100644 index 000000000..d2e5b9fff --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg2 @@ -0,0 +1,4 @@ +d95da92e3e77e32e3766ed9a95241f98 *tests/data/fate/vsynth3-mpeg2.mpeg2video +29567 tests/data/fate/vsynth3-mpeg2.mpeg2video +1df6a406c3959c6de7651b4e4fd98a36 *tests/data/fate/vsynth3-mpeg2.out.rawvideo +stddev: 9.12 PSNR: 28.93 MAXDIFF: 63 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg2-422 b/tests/ref/vsynth/vsynth3-mpeg2-422 new file mode 100644 index 000000000..2247f286e --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg2-422 @@ -0,0 +1,4 @@ +4d108b861715f1fa010fd70baea91793 *tests/data/fate/vsynth3-mpeg2-422.mpeg2video +68612 tests/data/fate/vsynth3-mpeg2-422.mpeg2video +73b16e906d07b6bbccf4b00d4a25302c *tests/data/fate/vsynth3-mpeg2-422.out.rawvideo +stddev: 4.02 PSNR: 36.05 MAXDIFF: 46 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg2-idct-int b/tests/ref/vsynth/vsynth3-mpeg2-idct-int new file mode 100644 index 000000000..3b2f71465 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg2-idct-int @@ -0,0 +1,4 @@ +e79b543bed136bca385b2a870d532870 *tests/data/fate/vsynth3-mpeg2-idct-int.mpeg2video +29614 tests/data/fate/vsynth3-mpeg2-idct-int.mpeg2video +aebaf03348e2e114d9f487101f61fe3d *tests/data/fate/vsynth3-mpeg2-idct-int.out.rawvideo +stddev: 9.10 PSNR: 28.94 MAXDIFF: 65 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg2-ilace b/tests/ref/vsynth/vsynth3-mpeg2-ilace new file mode 100644 index 000000000..fe2720ef5 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg2-ilace @@ -0,0 +1,4 @@ +c13776ac25a9a9553847abddabd41915 *tests/data/fate/vsynth3-mpeg2-ilace.mpeg2video +35773 tests/data/fate/vsynth3-mpeg2-ilace.mpeg2video +78861ce7b0d433205e45960e1fadd911 *tests/data/fate/vsynth3-mpeg2-ilace.out.rawvideo +stddev: 9.10 PSNR: 28.95 MAXDIFF: 62 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg2-ivlc-qprd b/tests/ref/vsynth/vsynth3-mpeg2-ivlc-qprd new file mode 100644 index 000000000..d732912b8 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg2-ivlc-qprd @@ -0,0 +1,4 @@ +15a7db418ab54b6827d0bf53999de58f *tests/data/fate/vsynth3-mpeg2-ivlc-qprd.mpeg2video +59765 tests/data/fate/vsynth3-mpeg2-ivlc-qprd.mpeg2video +92048d455345edebc2b21a5ff102c3e4 *tests/data/fate/vsynth3-mpeg2-ivlc-qprd.out.rawvideo +stddev: 2.66 PSNR: 39.61 MAXDIFF: 22 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg2-thread b/tests/ref/vsynth/vsynth3-mpeg2-thread new file mode 100644 index 000000000..faf10716a --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg2-thread @@ -0,0 +1,4 @@ +adceaea1136d072c629d8be517f8d96d *tests/data/fate/vsynth3-mpeg2-thread.mpeg2video +40356 tests/data/fate/vsynth3-mpeg2-thread.mpeg2video +917f425ebc14d29783d184d90f493e86 *tests/data/fate/vsynth3-mpeg2-thread.out.rawvideo +stddev: 8.93 PSNR: 29.11 MAXDIFF: 64 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg2-thread-ivlc b/tests/ref/vsynth/vsynth3-mpeg2-thread-ivlc new file mode 100644 index 000000000..8ac72f1fa --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg2-thread-ivlc @@ -0,0 +1,4 @@ +221231dae1cd87b8c51a8f4772be6632 *tests/data/fate/vsynth3-mpeg2-thread-ivlc.mpeg2video +40091 tests/data/fate/vsynth3-mpeg2-thread-ivlc.mpeg2video +917f425ebc14d29783d184d90f493e86 *tests/data/fate/vsynth3-mpeg2-thread-ivlc.out.rawvideo +stddev: 8.93 PSNR: 29.11 MAXDIFF: 64 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg4 b/tests/ref/vsynth/vsynth3-mpeg4 new file mode 100644 index 000000000..02cf68d55 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg4 @@ -0,0 +1,4 @@ +ddcff996543900496f0b374a2d5cae74 *tests/data/fate/vsynth3-mpeg4.mp4 +26017 tests/data/fate/vsynth3-mpeg4.mp4 +fc0d8c1e58d254031e6207dfcae8f867 *tests/data/fate/vsynth3-mpeg4.out.rawvideo +stddev: 9.66 PSNR: 28.43 MAXDIFF: 79 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg4-adap b/tests/ref/vsynth/vsynth3-mpeg4-adap new file mode 100644 index 000000000..ec5b9e2ad --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg4-adap @@ -0,0 +1,4 @@ +40a36d85d24df09ba8695ab4a16e0843 *tests/data/fate/vsynth3-mpeg4-adap.avi +43702 tests/data/fate/vsynth3-mpeg4-adap.avi +b42b614e19e7c4859fca1af6d4e36eae *tests/data/fate/vsynth3-mpeg4-adap.out.rawvideo +stddev: 5.48 PSNR: 33.34 MAXDIFF: 53 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg4-adv b/tests/ref/vsynth/vsynth3-mpeg4-adv new file mode 100644 index 000000000..72742070e --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg4-adv @@ -0,0 +1,4 @@ +c3b4a5d4d642b6fea981b4f762a8081b *tests/data/fate/vsynth3-mpeg4-adv.avi +32292 tests/data/fate/vsynth3-mpeg4-adv.avi +9f80b96af57556d53ce44008bd687f55 *tests/data/fate/vsynth3-mpeg4-adv.out.rawvideo +stddev: 7.60 PSNR: 30.51 MAXDIFF: 63 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg4-error b/tests/ref/vsynth/vsynth3-mpeg4-error new file mode 100644 index 000000000..4f54a60c7 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg4-error @@ -0,0 +1,4 @@ +cee34cadd91b861d424f493acb9289ab *tests/data/fate/vsynth3-mpeg4-error.avi +38208 tests/data/fate/vsynth3-mpeg4-error.avi +f9fd24e26f4ffb5ed597b9bbf0ea731b *tests/data/fate/vsynth3-mpeg4-error.out.rawvideo +stddev: 6.06 PSNR: 32.47 MAXDIFF: 54 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg4-nr b/tests/ref/vsynth/vsynth3-mpeg4-nr new file mode 100644 index 000000000..8cb103271 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg4-nr @@ -0,0 +1,4 @@ +b0f9c0997901e00ca2582ebe20f120e5 *tests/data/fate/vsynth3-mpeg4-nr.avi +36496 tests/data/fate/vsynth3-mpeg4-nr.avi +d0ad9918a12019dd2eacfb804d1f7e78 *tests/data/fate/vsynth3-mpeg4-nr.out.rawvideo +stddev: 8.27 PSNR: 29.78 MAXDIFF: 70 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg4-nsse b/tests/ref/vsynth/vsynth3-mpeg4-nsse new file mode 100644 index 000000000..f96b1c61f --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg4-nsse @@ -0,0 +1,4 @@ +4b2c5176f1fc2134612f3b512e8f936a *tests/data/fate/vsynth3-mpeg4-nsse.avi +41976 tests/data/fate/vsynth3-mpeg4-nsse.avi +69d86dec0d73e00608e03855a79dbdc0 *tests/data/fate/vsynth3-mpeg4-nsse.out.rawvideo +stddev: 6.70 PSNR: 31.60 MAXDIFF: 68 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg4-qpel b/tests/ref/vsynth/vsynth3-mpeg4-qpel new file mode 100644 index 000000000..f17474f06 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg4-qpel @@ -0,0 +1,4 @@ +5e4bb1c9bd845896891ca5fe418948a3 *tests/data/fate/vsynth3-mpeg4-qpel.avi +42618 tests/data/fate/vsynth3-mpeg4-qpel.avi +50af37a5ae05f0af34bd56dcef997c8d *tests/data/fate/vsynth3-mpeg4-qpel.out.rawvideo +stddev: 6.59 PSNR: 31.75 MAXDIFF: 54 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg4-qprd b/tests/ref/vsynth/vsynth3-mpeg4-qprd new file mode 100644 index 000000000..1691e1fd0 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg4-qprd @@ -0,0 +1,4 @@ +af2517de1718262000b76c1da0bd100d *tests/data/fate/vsynth3-mpeg4-qprd.avi +61826 tests/data/fate/vsynth3-mpeg4-qprd.avi +c59f2bead1c81b23fabc0a740048b110 *tests/data/fate/vsynth3-mpeg4-qprd.out.rawvideo +stddev: 2.68 PSNR: 39.55 MAXDIFF: 27 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg4-rc b/tests/ref/vsynth/vsynth3-mpeg4-rc new file mode 100644 index 000000000..36c771c5e --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg4-rc @@ -0,0 +1,4 @@ +ddc944ea93e7e87bfae36bb85ee36c91 *tests/data/fate/vsynth3-mpeg4-rc.avi +81088 tests/data/fate/vsynth3-mpeg4-rc.avi +07ba5baf141a24561f7dba43645a3400 *tests/data/fate/vsynth3-mpeg4-rc.out.rawvideo +stddev: 2.62 PSNR: 39.74 MAXDIFF: 23 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg4-thread b/tests/ref/vsynth/vsynth3-mpeg4-thread new file mode 100644 index 000000000..2b593227d --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpeg4-thread @@ -0,0 +1,4 @@ +601ac957b2a8cc4d9f5812824b7d1e0d *tests/data/fate/vsynth3-mpeg4-thread.avi +74578 tests/data/fate/vsynth3-mpeg4-thread.avi +7eb4d38b01c71064406ce6705c471439 *tests/data/fate/vsynth3-mpeg4-thread.out.rawvideo +stddev: 1.99 PSNR: 42.12 MAXDIFF: 18 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpng b/tests/ref/vsynth/vsynth3-mpng new file mode 100644 index 000000000..2a112a76d --- /dev/null +++ b/tests/ref/vsynth/vsynth3-mpng @@ -0,0 +1,4 @@ +f1a9b596c743645e5518a41e4fe2b043 *tests/data/fate/vsynth3-mpng.avi +179800 tests/data/fate/vsynth3-mpng.avi +693aff10c094f8bd31693f74cf79d2b2 *tests/data/fate/vsynth3-mpng.out.rawvideo +stddev: 3.67 PSNR: 36.82 MAXDIFF: 43 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-msmpeg4 b/tests/ref/vsynth/vsynth3-msmpeg4 new file mode 100644 index 000000000..dc653fcb0 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-msmpeg4 @@ -0,0 +1,4 @@ +68d0838cf0e66a3092acaf347061cea8 *tests/data/fate/vsynth3-msmpeg4.avi +32440 tests/data/fate/vsynth3-msmpeg4.avi +216b15fb02691b662d0f0112507d5583 *tests/data/fate/vsynth3-msmpeg4.out.rawvideo +stddev: 9.63 PSNR: 28.45 MAXDIFF: 104 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-msmpeg4v2 b/tests/ref/vsynth/vsynth3-msmpeg4v2 new file mode 100644 index 000000000..58d6e4f23 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-msmpeg4v2 @@ -0,0 +1,4 @@ +dfba0b605760d087cb6f5c0ce45f671a *tests/data/fate/vsynth3-msmpeg4v2.avi +32626 tests/data/fate/vsynth3-msmpeg4v2.avi +575bfa06fd3f3944faf92205fabf5f22 *tests/data/fate/vsynth3-msmpeg4v2.out.rawvideo +stddev: 9.66 PSNR: 28.43 MAXDIFF: 86 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-prores b/tests/ref/vsynth/vsynth3-prores new file mode 100644 index 000000000..f63a7a736 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-prores @@ -0,0 +1,4 @@ +b060c59be88b4b089ece5ee8dc4f1c58 *tests/data/fate/vsynth3-prores.mov +105367 tests/data/fate/vsynth3-prores.mov +fff5e7ad21d78501c8fa4749bf4bf289 *tests/data/fate/vsynth3-prores.out.rawvideo +stddev: 2.80 PSNR: 39.17 MAXDIFF: 27 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-prores_ks b/tests/ref/vsynth/vsynth3-prores_ks new file mode 100644 index 000000000..99cfc1397 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-prores_ks @@ -0,0 +1,4 @@ +7ceff8c9cffca766f8a167ba73dad0e2 *tests/data/fate/vsynth3-prores_ks.mov +95053 tests/data/fate/vsynth3-prores_ks.mov +9ab6d3e3cc7749796cd9fa984c60d890 *tests/data/fate/vsynth3-prores_ks.out.rawvideo +stddev: 4.09 PSNR: 35.88 MAXDIFF: 35 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-qtrle b/tests/ref/vsynth/vsynth3-qtrle new file mode 100644 index 000000000..6f9323278 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-qtrle @@ -0,0 +1,4 @@ +33ec7d4f0a18fcf6da3bdacb494e2035 *tests/data/fate/vsynth3-qtrle.mov +179656 tests/data/fate/vsynth3-qtrle.mov +693aff10c094f8bd31693f74cf79d2b2 *tests/data/fate/vsynth3-qtrle.out.rawvideo +stddev: 3.67 PSNR: 36.82 MAXDIFF: 43 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-r210 b/tests/ref/vsynth/vsynth3-r210 new file mode 100644 index 000000000..8362ee52d --- /dev/null +++ b/tests/ref/vsynth/vsynth3-r210 @@ -0,0 +1,4 @@ +5f6e0ba5fc9a1b1440e80aebcb41d57a *tests/data/fate/vsynth3-r210.avi +442048 tests/data/fate/vsynth3-r210.avi +e1d882babc8754f7418aa91ce48f7ab0 *tests/data/fate/vsynth3-r210.out.rawvideo +stddev: 3.48 PSNR: 37.28 MAXDIFF: 42 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-rgb b/tests/ref/vsynth/vsynth3-rgb new file mode 100644 index 000000000..f407523c9 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-rgb @@ -0,0 +1,4 @@ +7b20b20734352d33b18b802513f5fc47 *tests/data/fate/vsynth3-rgb.avi +180248 tests/data/fate/vsynth3-rgb.avi +693aff10c094f8bd31693f74cf79d2b2 *tests/data/fate/vsynth3-rgb.out.rawvideo +stddev: 3.67 PSNR: 36.82 MAXDIFF: 43 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-svq1 b/tests/ref/vsynth/vsynth3-svq1 new file mode 100644 index 000000000..b51fa03e8 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-svq1 @@ -0,0 +1,4 @@ +1eaf318269afd7426406d73397c39a48 *tests/data/fate/vsynth3-svq1.mov +40773 tests/data/fate/vsynth3-svq1.mov +a1e5334cf67649bf8c7d95dc4d1bf148 *tests/data/fate/vsynth3-svq1.out.rawvideo +stddev: 14.49 PSNR: 24.91 MAXDIFF: 183 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-v210 b/tests/ref/vsynth/vsynth3-v210 new file mode 100644 index 000000000..d3275f05a --- /dev/null +++ b/tests/ref/vsynth/vsynth3-v210 @@ -0,0 +1,4 @@ +d2f5e07f0c0e917d80d63f39d683919e *tests/data/fate/vsynth3-v210.avi +224448 tests/data/fate/vsynth3-v210.avi +0cf7cf68724fa5146b1667e4fa08b0e1 *tests/data/fate/vsynth3-v210.out.rawvideo +stddev: 2.12 PSNR: 41.58 MAXDIFF: 26 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-v308 b/tests/ref/vsynth/vsynth3-v308 new file mode 100644 index 000000000..c70678c54 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-v308 @@ -0,0 +1,4 @@ +53dacfdcf280d58b465da71583f4af26 *tests/data/fate/vsynth3-v308.avi +180248 tests/data/fate/vsynth3-v308.avi +02a85ec07377df6b483281038f8882ee *tests/data/fate/vsynth3-v308.out.rawvideo +stddev: 3.06 PSNR: 38.40 MAXDIFF: 40 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-v408 b/tests/ref/vsynth/vsynth3-v408 new file mode 100644 index 000000000..da87e817c --- /dev/null +++ b/tests/ref/vsynth/vsynth3-v408 @@ -0,0 +1,4 @@ +ac8ea8d8f38b5c6b76c2fef9667a172d *tests/data/fate/vsynth3-v408.avi +238048 tests/data/fate/vsynth3-v408.avi +a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-v408.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-wmv1 b/tests/ref/vsynth/vsynth3-wmv1 new file mode 100644 index 000000000..568d3cf14 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-wmv1 @@ -0,0 +1,4 @@ +b13831403f2dfdf3e5e6d33b03dbc687 *tests/data/fate/vsynth3-wmv1.avi +32654 tests/data/fate/vsynth3-wmv1.avi +4dafe3c433c7f48c6c9e56d59ca0f7c3 *tests/data/fate/vsynth3-wmv1.out.rawvideo +stddev: 9.65 PSNR: 28.44 MAXDIFF: 91 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-wmv2 b/tests/ref/vsynth/vsynth3-wmv2 new file mode 100644 index 000000000..9d20b7bfc --- /dev/null +++ b/tests/ref/vsynth/vsynth3-wmv2 @@ -0,0 +1,4 @@ +1a8a90c91240f84d0ceca4f20ae4be27 *tests/data/fate/vsynth3-wmv2.avi +33976 tests/data/fate/vsynth3-wmv2.avi +691e00ebbb56c061f74ade70088102e7 *tests/data/fate/vsynth3-wmv2.out.rawvideo +stddev: 9.60 PSNR: 28.48 MAXDIFF: 81 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-yuv b/tests/ref/vsynth/vsynth3-yuv new file mode 100644 index 000000000..29abb3028 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-yuv @@ -0,0 +1,4 @@ +d0a6f0188d9cc70919865ebc59cc0179 *tests/data/fate/vsynth3-yuv.avi +93548 tests/data/fate/vsynth3-yuv.avi +a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-yuv.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-yuv4 b/tests/ref/vsynth/vsynth3-yuv4 new file mode 100644 index 000000000..70f827452 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-yuv4 @@ -0,0 +1,4 @@ +4b5196292069c5301446b546d0148783 *tests/data/fate/vsynth3-yuv4.avi +93548 tests/data/fate/vsynth3-yuv4.avi +a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-yuv4.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-zlib b/tests/ref/vsynth/vsynth3-zlib new file mode 100644 index 000000000..e69e28908 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-zlib @@ -0,0 +1,4 @@ +278541a159accf11fec8914cad41e85c *tests/data/fate/vsynth3-zlib.avi +174878 tests/data/fate/vsynth3-zlib.avi +693aff10c094f8bd31693f74cf79d2b2 *tests/data/fate/vsynth3-zlib.out.rawvideo +stddev: 3.67 PSNR: 36.82 MAXDIFF: 43 bytes: 86700/ 86700 diff --git a/tests/regression-funcs.sh b/tests/regression-funcs.sh index 75387952e..86bc446a3 100755 --- a/tests/regression-funcs.sh +++ b/tests/regression-funcs.sh @@ -11,7 +11,7 @@ target_exec=$4 target_path=$5 threads=${6:-1} cpuflags=${8:-all} -samples=$9 +target_samples=$9 datadir="./tests/data" target_datadir="${target_path}/${datadir}" @@ -44,7 +44,7 @@ echov(){ . $(dirname $0)/md5.sh AVCONV_OPTS="-nostats -y -cpuflags $cpuflags" -COMMON_OPTS="-flags +bitexact -idct simple -sws_flags +accurate_rnd+bitexact" +COMMON_OPTS="-flags +bitexact -idct simple -sws_flags +accurate_rnd+bitexact -fflags +bitexact" DEC_OPTS="$COMMON_OPTS -threads $threads" ENC_OPTS="$COMMON_OPTS -threads 1 -dct fastint" diff --git a/tests/tiny_psnr.c b/tests/tiny_psnr.c index b4fc02cf9..6da177ab9 100644 --- a/tests/tiny_psnr.c +++ b/tests/tiny_psnr.c @@ -287,14 +287,14 @@ int main(int argc, char *argv[]) char *end; len = strtol(argv[3], &end, 0); if (*end || len < 1 || len > 2) { - fprintf(stderr, "Unsupported sample format: %s\n", argv[3]); + fprintf(stderr, "Unsupported sample format: %s\nSupported: u8, s16, f32, f64\n", argv[3]); return 1; } } } if (argc < 3) { - printf("tiny_psnr [ [ [ []]]]\n"); + printf("tiny_psnr [|u8|s16|f32|f64 [ [ []]]]\n"); printf("WAV headers are skipped automatically.\n"); return 1; } diff --git a/tests/tiny_ssim.c b/tests/tiny_ssim.c index fe65e4753..9f355a3d8 100644 --- a/tests/tiny_ssim.c +++ b/tests/tiny_ssim.c @@ -29,6 +29,7 @@ #include "config.h" #include +#include #include #include #include @@ -195,7 +196,13 @@ int main(int argc, char* argv[]) f[0] = fopen(argv[1], "rb"); f[1] = fopen(argv[2], "rb"); sscanf(argv[3], "%dx%d", &w, &h); - frame_size = w*h*3/2; + + if (w<=0 || h<=0 || w*(int64_t)h >= INT_MAX/3 || 2LL*w+12 >= INT_MAX / sizeof(*temp)) { + fprintf(stderr, "Dimensions are too large, or invalid\n"); + return -2; + } + + frame_size = w*h*3LL/2; for( i=0; i<2; i++ ) { buf[i] = malloc(frame_size); diff --git a/tests/videogen.c b/tests/videogen.c index 94e6e7759..91da8b540 100644 --- a/tests/videogen.c +++ b/tests/videogen.c @@ -141,23 +141,37 @@ static void gen_image(int num, int w, int h) } } +void print_help(const char* name) +{ + printf("usage: %s file|dir [w=%i] [h=%i]\n" + "generate a test video stream\n", + name, DEFAULT_WIDTH, DEFAULT_HEIGHT); + exit(1); +} + int main(int argc, char **argv) { int w, h, i; char buf[1024]; int isdir = 0; - if (argc != 2) { - printf("usage: %s file|dir\n" - "generate a test video stream\n", argv[0]); - exit(1); + if (argc < 2 || argc > 4) { + print_help(argv[0]); } if (!freopen(argv[1], "wb", stdout)) isdir = 1; w = DEFAULT_WIDTH; + if(argc > 2) { + w = atoi(argv[2]); + if (w < 1) print_help(argv[0]); + } h = DEFAULT_HEIGHT; + if(argc > 3) { + h = atoi(argv[3]); + if (h < 1) print_help(argv[0]); + } rgb_tab = malloc(w * h * 3); wrap = w * 3; diff --git a/tools/aviocat.c b/tools/aviocat.c index 56b918e44..3bd62b7b4 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/build_libstagefright b/tools/build_libstagefright index 8b3a0930f..22bb71225 100644 --- a/tools/build_libstagefright +++ b/tools/build_libstagefright @@ -6,8 +6,8 @@ if [ "$NDK" = "" ]; then fi echo "Fetching Android system headers" -git clone --depth=1 --branch gingerbread-release git://github.com/CyanogenMod/android_frameworks_base.git ../android-source/frameworks/base -git clone --depth=1 --branch gingerbread-release git://github.com/CyanogenMod/android_system_core.git ../android-source/system/core +git clone --depth=1 --branch gingerbread-release https://github.com/CyanogenMod/android_frameworks_base.git ../android-source/frameworks/base +git clone --depth=1 --branch gingerbread-release https://github.com/CyanogenMod/android_system_core.git ../android-source/system/core echo "Fetching Android libraries for linking" # Libraries from any froyo/gingerbread device/emulator should work diff --git a/tools/dvd2concat b/tools/dvd2concat new file mode 100755 index 000000000..02371e099 --- /dev/null +++ b/tools/dvd2concat @@ -0,0 +1,127 @@ +#!/usr/bin/env perl + +# Copyright (c) 2014 Nicolas George +# +# This file is part of FFmpeg. +# +# FFmpeg is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# FFmpeg is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with FFmpeg; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +=head1 NAME + +dvd2concat - create a concat script for a DVD title + +=head1 SYNOPSIS + +tools/dvd2concat I > I + +=head1 DESCRIPTION + +This script uses B to produce concat script for a DVD title. +The resulting script can be used to play the DVD using B, to +transcode it using B or any other similar use. + +I is the path to the DVD structure hierarchy; it +normally contains a directory named B. It must not be encrypted +with CSS. + +I is the output file. It can be used a input to ffmpeg. +It will require the B<-safe 0> option. + +=cut + +use strict; +use warnings; +use Getopt::Long ":config" => "require_order"; +use Pod::Usage; + +my $title; + +GetOptions ( + "help|usage|?|h" => sub { pod2usage({ -verbose => 1, -exitval => 0 }) }, + "manpage|m" => sub { pod2usage({ -verbose => 2, -exitval => 0 }) }, + "title|t=i" => \$title, +) and @ARGV == 1 or pod2usage({ -verbose => 1, -exitval => 1 }); +my ($path) = @ARGV; + +my $lsdvd_message = +"Make sure your lsdvd version has the two following patches applied:\n" . +"http://sourceforge.net/p/lsdvd/feature-requests/1/\n" . +"https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=603826\n"; + +my $lsdvd = do { + open my $l, "-|", "lsdvd", "-Op", "-x", $path + or die "You need to install lsdvd for this script to work.\n$lsdvd_message"; + local $/; + <$l>; +}; +my %lsdvd = eval $lsdvd; +die $@ if $@; + +if (!defined $title) { + $title = $lsdvd{longest_track}; + warn "Using longest title $title\n"; +} +my $track = $lsdvd{track}[$title - 1] + or die "Title $title does not exist (1-", scalar(@{$lsdvd{track}}), ")\n"; +my $vts_base = sprintf "%s/VIDEO_TS/VTS_%02d_", $path, $track->{vts}; +my @frag; +for my $i (1 .. 9) { + my $file = sprintf "%s%d.VOB", $vts_base, $i; + my $size = -s $file or last; + push @frag, { file => $file, size => $size >> 11 }; +} + +my $concat = "ffconcat version 1.0\n"; +$concat .= "\nstream\nexact_stream_id 0x1E0\n"; +for my $audio (@{$track->{audio}}) { + $concat .= "\nstream\nexact_stream_id " . $audio->{streamid} . "\n"; +} +for my $subp (@{$track->{subp}}) { + $concat .= "\nstream\nexact_stream_id " . $subp->{streamid} . "\n"; +} +for my $cell (@{$track->{cell}}) { + my $off = $cell->{first_sector}; + die "Your lsdvd version does not print cell sectors.\n$lsdvd_message" + unless defined $off; + my $size = $cell->{last_sector} + 1 - $cell->{first_sector}; + + my $frag = 0; + while ($frag < @frag) { + last if $off < $frag[$frag]->{size}; + $off -= $frag[$frag++]->{size}; + } + die "Cell beyond VOB data\n" unless $frag < @frag; + my $cur_off = $off; + my $cur_size = $size; + my @files; + while ($cur_size > $frag[$frag]->{size} - $cur_off) { + push @files, $frag[$frag]->{file}; + $cur_size -= $frag[$frag]->{size} - $cur_off; + $cur_off = 0; + die "Cell end beyond VOB data\n" unless ++$frag < @frag; + } + push @files, $frag[$frag]->{file}; + my $file = @files == 1 ? $files[0] : "concat:" . join("|", @files); + my $start = $off << 11; + my $end = ($off + $size) << 11; + $file = "subfile,,start,${start},end,${end},,:$file"; + + my $dur = int(1000 * $cell->{length}); + $concat .= sprintf "\nfile '%s'\nduration %02d:%02d:%02d.%03d\n", $file, + int($dur / 3600000), int($dur / 60000) % 60, int($dur / 1000) % 60, + $dur % 1000; +} + +print $concat; diff --git a/tools/ffeval.c b/tools/ffeval.c index 66b103294..944f37472 100644 --- a/tools/ffeval.c +++ b/tools/ffeval.c @@ -124,7 +124,7 @@ int main(int argc, char **argv) if (echo) fprintf(outfile, "%s ", buf); if (ret >= 0) fprintf(outfile, "%s%f\n", prompt, d); - else fprintf(outfile, "%s%s\n", prompt, av_err2str(ret)); + else fprintf(outfile, "%s%f (%s)\n", prompt, d, av_err2str(ret)); } count = 0; } else { diff --git a/tools/ffhash.c b/tools/ffhash.c index 086d48a7a..a9f71c26c 100644 --- a/tools/ffhash.c +++ b/tools/ffhash.c @@ -21,6 +21,7 @@ */ #include "config.h" +#include "libavutil/avstring.h" #include "libavutil/error.h" #include "libavutil/hash.h" #include "libavutil/mem.h" @@ -40,14 +41,14 @@ #define SIZE 65536 static struct AVHashContext *hash; -static uint8_t *res; +static int out_b64; static void usage(void) { int i = 0; const char *name; - printf("usage: ffhash [algorithm] [input]...\n"); + printf("usage: ffhash [b64:]algorithm [input]...\n"); printf("Supported hash algorithms:"); do { name = av_hash_names(i); @@ -60,12 +61,16 @@ static void usage(void) static void finish(void) { - int i, len = av_hash_get_size(hash); + char res[2 * AV_HASH_MAX_SIZE + 4]; - printf("%s=0x", av_hash_get_name(hash)); - av_hash_final(hash, res); - for (i = 0; i < len; i++) - printf("%02x", res[i]); + printf("%s=", av_hash_get_name(hash)); + if (out_b64) { + av_hash_final_b64(hash, res, sizeof(res)); + printf("b64:%s", res); + } else { + av_hash_final_hex(hash, res, sizeof(res)); + printf("0x%s", res); + } } static int check(char *file) @@ -113,16 +118,19 @@ int main(int argc, char **argv) { int i; int ret = 0; + const char *hash_name; if (argc == 1) { usage(); return 0; } - if ((ret = av_hash_alloc(&hash, argv[1])) < 0) { + hash_name = argv[1]; + out_b64 = av_strstart(hash_name, "b64:", &hash_name); + if ((ret = av_hash_alloc(&hash, hash_name)) < 0) { switch(ret) { case AVERROR(EINVAL): - printf("Invalid hash type: %s\n", argv[1]); + printf("Invalid hash type: %s\n", hash_name); break; case AVERROR(ENOMEM): printf("%s\n", strerror(errno)); @@ -130,11 +138,6 @@ int main(int argc, char **argv) } return 1; } - res = av_malloc(av_hash_get_size(hash)); - if (!res) { - printf("%s\n", strerror(errno)); - return 1; - } for (i = 2; i < argc; i++) ret |= check(argv[i]); @@ -143,7 +146,6 @@ int main(int argc, char **argv) ret |= check(NULL); av_hash_freep(&hash); - av_freep(&res); return ret; } diff --git a/tools/fourcc2pixfmt.c b/tools/fourcc2pixfmt.c index 1a653eda2..1cfdf6a90 100644 --- a/tools/fourcc2pixfmt.c +++ b/tools/fourcc2pixfmt.c @@ -100,7 +100,7 @@ int main(int argc, char **argv) } if (list_pix_fmt_fourccs) { - for (i = 0; i < AV_PIX_FMT_NB; i++) { + for (i = 0; av_pix_fmt_desc_get(i); i++) { const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(i); if (!pix_desc->name || pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL) continue; diff --git a/tools/ismindex.c b/tools/ismindex.c index 4dc3e125e..57a909e9b 100644 --- a/tools/ismindex.c +++ b/tools/ismindex.c @@ -25,11 +25,20 @@ * This step creates foo.ism and foo.ismc that is required by IIS for * serving it. * + * 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. + * * To pre-split files for serving as static files by a web server without * any extra server support, create the ismv file as above, and split it: * ismindex -split foo.ismv * This step creates a file Manifest and directories QualityLevel(...), * that can be read directly by a smooth streaming player. + * + * The -output dir option can be used to request that output files + * (both .ism/.ismc, or Manifest/QualityLevels* when splitting) + * should be written to this directory instead of in the current directory. + * (The directory itself isn't created if it doesn't already exist.) */ #include @@ -44,7 +53,8 @@ static int usage(const char *argv0, int ret) { - fprintf(stderr, "%s [-split] [-n basename] file1 [file2] ...\n", argv0); + fprintf(stderr, "%s [-split] [-n basename] [-path-prefix prefix] " + "[-ismc-prefix prefix] [-output dir] file1 [file2] ...\n", argv0); return ret; } @@ -119,15 +129,15 @@ static int write_fragment(const char *filename, AVIOContext *in) } static int write_fragments(struct Tracks *tracks, int start_index, - AVIOContext *in) + AVIOContext *in, const char *output_prefix) { - char dirname[100], filename[500]; + char dirname[2048], filename[2048]; int i, j; 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), "QualityLevels(%d)", track->bitrate); + snprintf(dirname, sizeof(dirname), "%sQualityLevels(%d)", output_prefix, track->bitrate); if (mkdir(dirname, 0777) == -1) return AVERROR(errno); for (j = 0; j < track->chunks; j++) { @@ -163,7 +173,7 @@ static int read_tfra(struct Tracks *tracks, int start_index, AVIOContext *f) } fieldlength = avio_rb32(f); track->chunks = avio_rb32(f); - track->offsets = av_mallocz(sizeof(*track->offsets) * track->chunks); + track->offsets = av_mallocz_array(track->chunks, sizeof(*track->offsets)); if (!track->offsets) { ret = AVERROR(ENOMEM); goto fail; @@ -197,7 +207,7 @@ fail: } static int read_mfra(struct Tracks *tracks, int start_index, - const char *file, int split) + const char *file, int split, const char *output_prefix) { int err = 0; AVIOContext *f = NULL; @@ -221,7 +231,7 @@ static int read_mfra(struct Tracks *tracks, int start_index, } if (split) - err = write_fragments(tracks, start_index, f); + err = write_fragments(tracks, start_index, f, output_prefix); fail: if (f) @@ -273,7 +283,8 @@ fail: return err; } -static int handle_file(struct Tracks *tracks, const char *file, int split) +static int handle_file(struct Tracks *tracks, const char *file, int split, + const char *output_prefix) { AVFormatContext *ctx = NULL; int err = 0, i, orig_tracks = tracks->nb_tracks; @@ -375,7 +386,7 @@ static int handle_file(struct Tracks *tracks, const char *file, int split) avformat_close_input(&ctx); - err = read_mfra(tracks, orig_tracks, file, split); + err = read_mfra(tracks, orig_tracks, file, split, output_prefix); fail: if (ctx) @@ -383,14 +394,16 @@ fail: return err; } -static void output_server_manifest(struct Tracks *tracks, - const char *basename) +static void output_server_manifest(struct Tracks *tracks, const char *basename, + const char *output_prefix, + const char *path_prefix, + const char *ismc_prefix) { char filename[1000]; FILE *out; int i; - snprintf(filename, sizeof(filename), "%s.ism", basename); + snprintf(filename, sizeof(filename), "%s%s.ism", output_prefix, basename); out = fopen(filename, "w"); if (!out) { perror(filename); @@ -400,15 +413,15 @@ static void output_server_manifest(struct Tracks *tracks, fprintf(out, "\n"); fprintf(out, "\t\n"); fprintf(out, "\t\t\n", basename); + "content=\"%s%s.ismc\" />\n", ismc_prefix, basename); fprintf(out, "\t\n"); fprintf(out, "\t\n"); fprintf(out, "\t\t\n"); for (i = 0; i < tracks->nb_tracks; i++) { struct Track *track = tracks->tracks[i]; const char *type = track->is_video ? "video" : "audio"; - fprintf(out, "\t\t\t<%s src=\"%s\" systemBitrate=\"%d\">\n", - type, track->name, track->bitrate); + fprintf(out, "\t\t\t<%s src=\"%s%s\" systemBitrate=\"%d\">\n", + type, path_prefix, track->name, track->bitrate); fprintf(out, "\t\t\t\t\n", track->track_id); fprintf(out, "\t\t\t\n", type); @@ -436,17 +449,17 @@ static void print_track_chunks(FILE *out, struct Tracks *tracks, int main, } } -static void output_client_manifest(struct Tracks *tracks, - const char *basename, int split) +static void output_client_manifest(struct Tracks *tracks, const char *basename, + const char *output_prefix, int split) { char filename[1000]; FILE *out; int i, j; if (split) - snprintf(filename, sizeof(filename), "Manifest"); + snprintf(filename, sizeof(filename), "%sManifest", output_prefix); else - snprintf(filename, sizeof(filename), "%s.ismc", basename); + snprintf(filename, sizeof(filename), "%s%s.ismc", output_prefix, basename); out = fopen(filename, "w"); if (!out) { perror(filename); @@ -534,6 +547,9 @@ static void clean_tracks(struct Tracks *tracks) int main(int argc, char **argv) { const char *basename = NULL; + const char *path_prefix = "", *ismc_prefix = ""; + const char *output_prefix = ""; + char output_prefix_buf[2048]; int split = 0, i; struct Tracks tracks = { 0, .video_track = -1, .audio_track = -1 }; @@ -543,12 +559,26 @@ int main(int argc, char **argv) if (!strcmp(argv[i], "-n")) { basename = argv[i + 1]; i++; + } else if (!strcmp(argv[i], "-path-prefix")) { + path_prefix = argv[i + 1]; + i++; + } else if (!strcmp(argv[i], "-ismc-prefix")) { + ismc_prefix = argv[i + 1]; + i++; + } else if (!strcmp(argv[i], "-output")) { + output_prefix = argv[i + 1]; + i++; + if (output_prefix[strlen(output_prefix) - 1] != '/') { + snprintf(output_prefix_buf, sizeof(output_prefix_buf), + "%s/", output_prefix); + output_prefix = output_prefix_buf; + } } else if (!strcmp(argv[i], "-split")) { split = 1; } else if (argv[i][0] == '-') { return usage(argv[0], 1); } else { - if (handle_file(&tracks, argv[i], split)) + if (handle_file(&tracks, argv[i], split, output_prefix)) return 1; } } @@ -556,8 +586,9 @@ int main(int argc, char **argv) return usage(argv[0], 1); if (!split) - output_server_manifest(&tracks, basename); - output_client_manifest(&tracks, basename, split); + output_server_manifest(&tracks, basename, output_prefix, + path_prefix, ismc_prefix); + output_client_manifest(&tracks, basename, output_prefix, split); clean_tracks(&tracks); diff --git a/tools/missing_codec_desc b/tools/missing_codec_desc index 093d02e02..e1d3d60b4 100755 --- a/tools/missing_codec_desc +++ b/tools/missing_codec_desc @@ -14,7 +14,6 @@ known_AV_CODEC_ID_NONE=1 known_AV_CODEC_ID_FIRST_AUDIO=1 known_AV_CODEC_ID_FIRST_SUBTITLE=1 known_AV_CODEC_ID_FIRST_UNKNOWN=1 -known_AV_CODEC_ID_TTF=1 known_AV_CODEC_ID_PROBE=1 known_AV_CODEC_ID_MPEG2TS=1 known_AV_CODEC_ID_MPEG4SYSTEMS=1 diff --git a/tools/patcheck b/tools/patcheck index 59a16efa9..3342c6a42 100755 --- a/tools/patcheck +++ b/tools/patcheck @@ -67,7 +67,7 @@ $EGREP $OPT '^\+ *(const *|)static' $*| $EGREP --color=always '[^=]= *(0|NULL)[^ cat $TMP hiegrep '# *ifdef * (HAVE|CONFIG)_' 'ifdefs that should be #if' $* -hiegrep '\b(awnser|cant|dont|wont|doesnt|usefull|successfull|occured|teh|alot|wether|skiped|skiping|heigth|informations|colums|loosy|loosing|ouput|seperate|preceed|upto|paket|posible|unkown|inpossible|dimention|acheive|funtions|overriden|outputing|seperation|initalize|compatibilty|bistream|knwon|unknwon)\b' 'common typos' $* +hiegrep '\b(awnser|cant|dont|wont|doesnt|usefull|successfull|occured|teh|alot|wether|skiped|skiping|heigth|informations|colums|loosy|loosing|ouput|seperate|preceed|upto|paket|posible|unkown|inpossible|dimention|acheive|funtions|overriden|outputing|seperation|initalize|compatibilty|bistream|knwon|unknwon|choosen|additonal|gurantee|availble|wich)\b' 'common typos' $* hiegrep 'av_log\( *NULL' 'Missing context in av_log' $* hiegrep '[^sn]printf' 'Please use av_log' $* diff --git a/tools/uncoded_frame.c b/tools/uncoded_frame.c index eafbbfde1..53e71eacb 100644 --- a/tools/uncoded_frame.c +++ b/tools/uncoded_frame.c @@ -177,12 +177,12 @@ int main(int argc, char **argv) st->stream->codec->pix_fmt = st->link->format; break; case AVMEDIA_TYPE_AUDIO: - st->stream->codec->codec_id = - av_get_pcm_codec(st->stream->codec->sample_fmt, -1); st->stream->codec->channel_layout = st->link->channel_layout; st->stream->codec->channels = avfilter_link_get_channels(st->link); st->stream->codec->sample_rate = st->link->sample_rate; st->stream->codec->sample_fmt = st->link->format; + st->stream->codec->codec_id = + av_get_pcm_codec(st->stream->codec->sample_fmt, -1); break; default: av_assert0(!"reached"); diff --git a/tools/yuvcmp.c b/tools/yuvcmp.c index 11585f9b4..65b1794d0 100644 --- a/tools/yuvcmp.c +++ b/tools/yuvcmp.c @@ -9,8 +9,10 @@ #include #include #include -#include +#if HAVE_UNISTD_H +#include +#endif int main(int argc, char **argv)