Compare commits
414 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b1a4534186 | |||
| f4c70a83cf | |||
| b169821e8f | |||
| 68b5f82265 | |||
| 0bd31a8f91 | |||
| 6662b0cdd1 | |||
| a339afbe3c | |||
| 0e3bdf68b2 | |||
| 54aaa70530 | |||
| 586ce3cf95 | |||
| e1af7a6d83 | |||
| d731a88093 | |||
| c7ea86bc16 | |||
| addd5cfee3 | |||
| 04bded41ad | |||
| 5bb8f8e2dd | |||
| f175858f10 | |||
| 4841d48e04 | |||
| 498bfba547 | |||
| cd261553d5 | |||
| da76e55b93 | |||
| 1ec463fc79 | |||
| f65ed0f0e7 | |||
| cdf0627ee5 | |||
| d293771434 | |||
| 479f3e3536 | |||
| 5d62f99b08 | |||
| e4056afd4c | |||
| b83407f983 | |||
| 3a308dffde | |||
| 3b8cb4dc26 | |||
| 7271c1b523 | |||
| fea9688839 | |||
| c16a71e757 | |||
| 3a661757ba | |||
| f60c294f6d | |||
| bab5b22af2 | |||
| 90b99445fb | |||
| 38c029131a | |||
| 05ef164255 | |||
| d10954e620 | |||
| f3a360a00d | |||
| 160ecb2b36 | |||
| c08ff45cb2 | |||
| bc1b078bd1 | |||
| d0ce252930 | |||
| 88336d81fa | |||
| 04885dde13 | |||
| 62a9b53e19 | |||
| 4a554ffb9b | |||
| 573987e8aa | |||
| 74d626d3d5 | |||
| 5743c33946 | |||
| 0b5ef2198b | |||
| 02694abdaf | |||
| 24717b7be6 | |||
| 09c9cc0cc2 | |||
| c3badb1cd8 | |||
| d735717614 | |||
| 769d857430 | |||
| 02606b6ae4 | |||
| 18025bf362 | |||
| 85dbf6d8e4 | |||
| 6498053b90 | |||
| d39d90e510 | |||
| 21d7ac3a07 | |||
| 41c5289c7e | |||
| 99c3834f61 | |||
| 1b0f37bbb6 | |||
| c543847ddd | |||
| d4d971efbb | |||
| 6b20dadc81 | |||
| 0a22787423 | |||
| 343a76e123 | |||
| f99867ef79 | |||
| 05e38d8362 | |||
| ba0c1fc015 | |||
| b92c0e54fc | |||
| f6b059008f | |||
| 5af1fe5693 | |||
| c872336df5 | |||
| ffb0a4c647 | |||
| 00c45302e7 | |||
| b220f7dc94 | |||
| e0a079be2a | |||
| 6c9b507841 | |||
| 1164095eca | |||
| 49d34302a6 | |||
| dfed9fc7bd | |||
| aa1bcef3cc | |||
| 1b0a93466c | |||
| a0c4d98072 | |||
| 25ba51aad7 | |||
| f504e2e9f5 | |||
| 405723c4cd | |||
| ac8ac10e33 | |||
| 40b801870d | |||
| c773ce8435 | |||
| a1b6a6907b | |||
| bdd1a93e4b | |||
| 4d7d183ccb | |||
| bea691ffc1 | |||
| 252464c49b | |||
| 3666a36472 | |||
| 371c42dd81 | |||
| 96a63346ee | |||
| 807b53c191 | |||
| 9c52069b83 | |||
| 002c1b4ddb | |||
| b736844c5f | |||
| adc6730d51 | |||
| 74bacfc00b | |||
| 3e02fd22a3 | |||
| 29852104f5 | |||
| b4d190ca32 | |||
| 2334e8e2d2 | |||
| dad619078e | |||
| a9c838f6f7 | |||
| de3331843c | |||
| aeb81a7fdc | |||
| 60af592bdd | |||
| cc8f0276b5 | |||
| ac9045e993 | |||
| 11ae269072 | |||
| c9d1d0f0d7 | |||
| a9e55f409f | |||
| a412dd1863 | |||
| 4c004c350c | |||
| 4d05988497 | |||
| ed9b67a149 | |||
| aab4eb20ca | |||
| 8cef0f2673 | |||
| 7e634b9731 | |||
| 2b8c96074b | |||
| 0df8b97e09 | |||
| d081214a70 | |||
| bde8a67e92 | |||
| d06f35f285 | |||
| ba5343eefb | |||
| ae964c5851 | |||
| 42d9464f6f | |||
| dcf26aa3a2 | |||
| 6b4165643d | |||
| 22d2a4eb34 | |||
| 18b0e31390 | |||
| 79f7917939 | |||
| ad636886ca | |||
| e04470d816 | |||
| 537a893560 | |||
| 11e8eeca4d | |||
| 6696741957 | |||
| 8d348dc635 | |||
| c630e08d41 | |||
| 846d2f7d71 | |||
| 729c68f86f | |||
| 5477c6dc66 | |||
| 8255f469bf | |||
| 980d1e530e | |||
| c00fd50092 | |||
| d0092f4ef2 | |||
| 18193cfadb | |||
| 2e632394dd | |||
| 47fd81fda3 | |||
| 0241e87624 | |||
| c8907643fb | |||
| 6b89f87fd9 | |||
| 188ffc18ef | |||
| cb2f3ec5cb | |||
| f1de1a9d80 | |||
| 3edd95e79e | |||
| 1b67de255f | |||
| 6feea4ada8 | |||
| 66a140c0c0 | |||
| 59029c2b16 | |||
| 159270e3b2 | |||
| 6a8cf7b383 | |||
| 09c1c0b126 | |||
| 69bcdb4575 | |||
| 07fac14653 | |||
| e3711d18f3 | |||
| c859363910 | |||
| e821e6c21d | |||
| 2ffc47b37d | |||
| 4e53ea496c | |||
| 7cc79bfda9 | |||
| 8174b4206d | |||
| 94849755fb | |||
| d54198256e | |||
| cc78679c84 | |||
| 1b9de6ff28 | |||
| 6db10d3be0 | |||
| 236001ce0b | |||
| 28eb4663d6 | |||
| c10b416087 | |||
| 3ee5567c54 | |||
| 41550b0ebb | |||
| b586ff2768 | |||
| 61f5019a51 | |||
| 2de1f26366 | |||
| 21efa2af53 | |||
| f3931154bb | |||
| bc08dfdf5d | |||
| cc773eba6b | |||
| b91b594dbd | |||
| 36713f42ab | |||
| ff547f5fd4 | |||
| 1cb422a0ad | |||
| e2afcd74ce | |||
| 5017839ca0 | |||
| 6ed54900f7 | |||
| e434c789af | |||
| c42b520ba5 | |||
| 270ad2fd2f | |||
| 77d5f217f3 | |||
| e886fe5542 | |||
| 19e6b871b6 | |||
| 115853a821 | |||
| e67741feea | |||
| b8d75b8ebc | |||
| 554787a53e | |||
| 1f090edd02 | |||
| 69e12a3f43 | |||
| 9493a2d066 | |||
| f72b41c421 | |||
| 66bcc6463e | |||
| 3d742d20ab | |||
| d92ef4f846 | |||
| 057b8d65e3 | |||
| 572985605f | |||
| ab4fcc06ce | |||
| fcce528713 | |||
| 306ed3f301 | |||
| b4681bd6ec | |||
| 2aad37688c | |||
| 66f2cf8958 | |||
| a01ed52733 | |||
| ebb406db7c | |||
| 1606aab99b | |||
| 670c823406 | |||
| f914c18de5 | |||
| 9593b727e2 | |||
| fce9391532 | |||
| eb480d1872 | |||
| 610da8475f | |||
| b94d2dd59a | |||
| b38902646c | |||
| 7c8c94279c | |||
| 58475c6988 | |||
| e85ea8baaa | |||
| 72b27f4f70 | |||
| 2da196b39a | |||
| 93d6513bbe | |||
| 27d48ddd8f | |||
| 56999f9353 | |||
| 38261d8cbd | |||
| ab84c37d63 | |||
| 78e54e1361 | |||
| 5bb9d8affe | |||
| 243359fc78 | |||
| 41f9156856 | |||
| a42a5e692d | |||
| 6d92f9a85e | |||
| d492fc3e5e | |||
| 4a618246cd | |||
| 7af16852cb | |||
| db7a80c3ca | |||
| 6cc785c255 | |||
| 0a64d77be9 | |||
| e709315488 | |||
| 9062d89849 | |||
| 4cbc9bb2c9 | |||
| 9a5f191bfb | |||
| aa4cf7a584 | |||
| 30fe9d3511 | |||
| 435f172b5d | |||
| 21ff582aec | |||
| f0c08506f5 | |||
| 356251d750 | |||
| 9459a45036 | |||
| 521347ee0b | |||
| d66b1af8df | |||
| 19ea7b0409 | |||
| e2a58916b1 | |||
| b171edca3c | |||
| 8464563b80 | |||
| a2ceca5cf6 | |||
| 24367ad563 | |||
| d2f57db3ab | |||
| 13f0a85c2c | |||
| ae0e91150c | |||
| abd835bec7 | |||
| b88210ba04 | |||
| ce35590562 | |||
| 7dbea8ef0b | |||
| e976607831 | |||
| fdc5b25f19 | |||
| c5dcf99399 | |||
| 16bef72c50 | |||
| adfa69aaa9 | |||
| 5e45c27ba9 | |||
| 3834629897 | |||
| 3481f8d99f | |||
| aa5e6017a5 | |||
| 8d1e092b24 | |||
| 0deb010ae7 | |||
| 88127b743f | |||
| f4a6db1222 | |||
| f309408874 | |||
| 888602001f | |||
| 894bebeaf7 | |||
| 3fb9425a75 | |||
| d3145298c0 | |||
| fafdcb2a35 | |||
| 0c4777a569 | |||
| 2af975f2c1 | |||
| 9e0cfc48ac | |||
| 98436c51be | |||
| 33efa50fa4 | |||
| 25abb63bfc | |||
| f9b68bc9a5 | |||
| 192fca4b59 | |||
| adef13da94 | |||
| bebaad4371 | |||
| db36dfc9ba | |||
| 61628a44eb | |||
| d6399d50ae | |||
| a267d4ad4c | |||
| fef22c87ad | |||
| 3e79074c41 | |||
| 9cc7926586 | |||
| 8815d77532 | |||
| bfacb66fc8 | |||
| 61b88b4dda | |||
| e38092ef93 | |||
| e1c2fa6b9a | |||
| c9e6162554 | |||
| ea276a511a | |||
| 41f32f0bc4 | |||
| ef879f02f2 | |||
| f2d836819d | |||
| 2b403b88fc | |||
| 2450e202c4 | |||
| 301100ddfb | |||
| 8e99388c1b | |||
| e43a3d8d30 | |||
| e01a55c528 | |||
| 0c52543781 | |||
| 2bd36ef4c7 | |||
| 2eb597816a | |||
| c02d56b3cf | |||
| 8b8b4bdef3 | |||
| 162b4c60c8 | |||
| e809c23786 | |||
| 3061bf668f | |||
| bf2d7b20ea | |||
| 84f78ac3ea | |||
| 45cd69a276 | |||
| bb84cbfd0c | |||
| 4f879d26e1 | |||
| 0ecd15b839 | |||
| fb724ad64e | |||
| fde01699eb | |||
| d93b0009c4 | |||
| f946c6c2f0 | |||
| ca5ebfb066 | |||
| d596225a57 | |||
| 1a3ec3f2f8 | |||
| a888d21c8c | |||
| 884a660cae | |||
| 2c87aa0b23 | |||
| 111035ccae | |||
| 466799d4f5 | |||
| c7fe7ee8d4 | |||
| af912d80d8 | |||
| d4ff0020b4 | |||
| 61df86efdd | |||
| b8eefd0061 | |||
| e1bbae68fc | |||
| 56b50b945b | |||
| d57ea70234 | |||
| 422ce1f21a | |||
| cf5cdc5a29 | |||
| 37c6124893 | |||
| 9ee0cd2190 | |||
| 962d667964 | |||
| 2929465718 | |||
| d660dd1e0a | |||
| a1d9e28272 | |||
| 597d574480 | |||
| e8541ed9f1 | |||
| 4f863e52dd | |||
| 8904bc8e76 | |||
| c9a9dbfebf | |||
| cebc2b3880 | |||
| 3d1ca4c3ff | |||
| 38dc8767df | |||
| c5ee01d966 | |||
| 3d7c02e4a2 | |||
| 86c4d04051 | |||
| d4041282f4 | |||
| 868aa88d83 | |||
| 5eca8964a9 | |||
| 80daebdfdf | |||
| 4e5f3e6b8e | |||
| 116cb346e3 | |||
| 1cff6e41bf | |||
| 8ccd1593a4 | |||
| 48afb43549 | |||
| 5c5d3e315e | |||
| 4d476677b0 | |||
| efac4e2c44 | |||
| 1e84d9c5da | |||
| 2233b51283 | |||
| bf1e5f2773 |
@@ -1 +1,2 @@
|
||||
*.pnm -diff -text
|
||||
tests/ref/fate/sub-scc eol=crlf
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<jeebjp@gmail.com> <jan.ekstrom@aminocom.com>
|
||||
<sw@jkqxz.net> <mrt@jkqxz.net>
|
||||
<u@pkh.me> <cboesch@gopro.com>
|
||||
<quinkblack@foxmail.com> <wantlamy@gmail.com>
|
||||
<quinkblack@foxmail.com> <zhilizhao@tencent.com>
|
||||
<zhilizhao@tencent.com> <quinkblack@foxmail.com>
|
||||
<zhilizhao@tencent.com> <wantlamy@gmail.com>
|
||||
<modmaker@google.com> <modmaker-at-google.com@ffmpeg.org>
|
||||
<stebbins@jetheaddev.com> <jstebbins@jetheaddev.com>
|
||||
<barryjzhao@tencent.com> <mypopydev@gmail.com>
|
||||
@@ -17,12 +17,8 @@
|
||||
<atomnuker@gmail.com> <rpehlivanov@obe.tv>
|
||||
<lizhong1008@gmail.com> <zhong.li@intel.com>
|
||||
<lizhong1008@gmail.com> <zhongli_dev@126.com>
|
||||
<andreas.rheinhardt@outlook.com> <andreas.rheinhardt@gmail.com>
|
||||
<andreas.rheinhardt@outlook.com> <andreas.rheinhardt@googlemail.com>
|
||||
<andreas.rheinhardt@gmail.com> <andreas.rheinhardt@googlemail.com>
|
||||
rcombs <rcombs@rcombs.me> <rodger.combs@gmail.com>
|
||||
<thilo.borgmann@mail.de> <thilo.borgmann@googlemail.com>
|
||||
<lq@chinaffmpeg.org> <liuqi05@kuaishou.com>
|
||||
<liuqi05@kuaishou.com> <lq@chinaffmpeg.org>
|
||||
<ruiling.song83@gmail.com> <ruiling.song@intel.com>
|
||||
Cosmin Stejerean <cosmin@cosmin.at> Cosmin Stejerean via ffmpeg-devel <ffmpeg-devel@ffmpeg.org>
|
||||
<wutong1208@outlook.com> <tong1.wu-at-intel.com@ffmpeg.org>
|
||||
<wutong1208@outlook.com> <tong1.wu@intel.com>
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
language: c
|
||||
sudo: false
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- nasm
|
||||
- diffutils
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
matrix:
|
||||
exclude:
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
cache:
|
||||
directories:
|
||||
- ffmpeg-samples
|
||||
before_install:
|
||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update; fi
|
||||
install:
|
||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install nasm; fi
|
||||
script:
|
||||
- mkdir -p ffmpeg-samples
|
||||
- ./configure --samples=ffmpeg-samples --cc=$CC
|
||||
- make -j 8
|
||||
- make fate-rsync
|
||||
- make check -j 8
|
||||
@@ -1,80 +1,380 @@
|
||||
Entries are sorted chronologically from oldest to youngest within each release,
|
||||
releases are sorted from youngest to oldest.
|
||||
|
||||
version 7.1:
|
||||
- Raw Captions with Time (RCWT) closed caption demuxer
|
||||
- LC3/LC3plus decoding/encoding using external library liblc3
|
||||
- ffmpeg CLI filtergraph chaining
|
||||
- LC3/LC3plus demuxer and muxer
|
||||
- pad_vaapi, drawbox_vaapi filters
|
||||
- vf_scale supports secondary ref input and framesync options
|
||||
- vf_scale2ref deprecated
|
||||
- qsv_params option added for QSV encoders
|
||||
- VVC decoder compatible with DVB test content
|
||||
- xHE-AAC decoder
|
||||
- removed DEC Alpha DSP and support code
|
||||
- VVC encoding support via libvvenc
|
||||
- perlin video source
|
||||
- D3D12VA HEVC encoder
|
||||
- Cropping metadata parsing and writing in Matroska and MP4/MOV de/muxers
|
||||
- Intel QSV-accelerated VVC decoding
|
||||
- MediaCodec AAC/AMR-NB/AMR-WB/MP3 decoding
|
||||
- YUV colorspace negotiation for codecs and filters, obsoleting the
|
||||
YUVJ pixel format
|
||||
- Vulkan H.264 encoder
|
||||
- Vulkan H.265 encoder
|
||||
- stream specifiers in fftools can now match by stream disposition
|
||||
- LCEVC enhancement data exporting in H.26x and MP4/ISOBMFF
|
||||
- LCEVC filter
|
||||
- MV-HEVC decoding
|
||||
version 6.1.2
|
||||
avcodec/snow: Fix off by 1 error in run_buffer
|
||||
avcodec/utils: apply the same alignment to YUV410 as we do to YUV420 for snow
|
||||
swscale: [loongarch] Fix checkasm-sw_yuv2rgb failure.
|
||||
avcodec/pngenc: fix sBIT writing for indexed-color PNGs
|
||||
avcodec/pngdec: use 8-bit sBIT cap for indexed PNGs per spec
|
||||
avcodec/videotoolboxenc: Fix bitrate doesn't work as expected
|
||||
Changelog: update
|
||||
avdevice/dshow: Don't skip audio devices if no video device is present
|
||||
avcodec/hdrenc: Allocate more space
|
||||
avcodec/cfhdenc: Height of 16 is not supported
|
||||
avcodec/cfhdenc: Allocate more space
|
||||
avcodec/osq: fix integer overflow when applying factor
|
||||
avcodec/osq: avoid using too large numbers for shifts and integers in update_residue_parameter()
|
||||
avcodec/vaapi_encode: Check hwctx
|
||||
avcodec/proresdec: Consider negative bits left
|
||||
avcodec/alsdec: Clear shift_value
|
||||
avcodec/hevc/hevcdec: Do not allow slices to depend on failed slices
|
||||
avfilter/vf_xfade: Check ff_inlink_consume_frame() for failure
|
||||
avutil/slicethread: Check pthread_*_init() for failure
|
||||
avutil/frame: Check log2_crop_align
|
||||
avutil/buffer: Check ff_mutex_init() for failure
|
||||
avformat/xmv: Check this_packet_size
|
||||
avformat/ty: rec_size seems to only need 32bit
|
||||
avformat/tty: Check avio_size()
|
||||
avformat/siff: Basic pkt_size check
|
||||
avformat/sauce: Check avio_size() for failure
|
||||
avformat/sapdec: Check ffurl_get_file_handle() for error
|
||||
avformat/nsvdec: Check asize for PCM
|
||||
avformat/mp3dec: Check header_filesize
|
||||
avformat/mp3dec; Check for avio_size() failure
|
||||
avformat/mov: Use 64bit for str_size
|
||||
avformat/mm: Check length
|
||||
avformat/hnm: Check *chunk_size
|
||||
avformat/hlsenc: Check ret
|
||||
avformat/bintext: Check avio_size() return
|
||||
avformat/asfdec_o: Check size of index object
|
||||
avfilter/vf_scale: Check ff_scale_adjust_dimensions() for failure
|
||||
avfilter/scale_eval: Use 64bit, check values in ff_scale_adjust_dimensions()
|
||||
avfilter/vf_lut3d: Check av_scanf()
|
||||
avfilter/vf_elbg: Use unsigned for shifting into the top bit
|
||||
avfilter/vf_deshake_opencl: Ensure that the first iteration initializes the best variables
|
||||
swscale/output: Fix integer overflows in yuv2rgba64_X_c_template
|
||||
avformat/mxfdec: Reorder elements of expression in bisect loop
|
||||
avutil/timecode: Use a 64bit framenum internally
|
||||
avcodec/pnmdec: Use 64bit for input size check
|
||||
avcodec/mpeg12enc: Use av_rescale() in vbv_buffer_size computation
|
||||
avcodec/utvideoenc: Use unsigned shift to build flags
|
||||
avcodec/j2kenc: Merge dwt_norm into lambda
|
||||
avcodec/vc2enc: Fix overflows with storing large values
|
||||
avcodec/mpegvideo_enc: Do not duplicate pictures on shifting
|
||||
avdevice/dshow_capture: Fix error handling in ff_dshow_##prefix##_Create()
|
||||
avcodec/tiff: Check value on positive signed targets
|
||||
avfilter/vf_convolution_opencl: Assert that the filter name is one of the filters
|
||||
avfilter/vf_bm3d: Dont round MSE2SSE to an integer
|
||||
avdevice/dshow: Remove NULL check on pin
|
||||
avdevice/dshow: check ff_dshow_pin_ConnectionMediaType() for failure
|
||||
avdevice/dshow: Check device_filter_unique_name before use
|
||||
avdevice/dshow: Cleanup also on av_log case
|
||||
avdevice/dshow_filter: Use wcscpy_s()
|
||||
avcodec/flac_parser: Assert that we do not overrun the link_penalty array
|
||||
avcodec/osq: avoid signed overflow in downsample path
|
||||
avcodec/pixlet: Simplify pfx computation
|
||||
avcodec/motion_est: Fix score squaring overflow
|
||||
avcodec/mlpenc: Use 64 for ml, mr
|
||||
avcodec/loco: Check loco_get_rice() for failure
|
||||
avcodec/loco: check get_ur_golomb_jpegls() for failure
|
||||
avcodec/imm4: check cbphi for error
|
||||
avcodec/iff: Use signed count
|
||||
avcodec/golomb: Assert that k is in the supported range for get_ur/sr_golomb()
|
||||
avcodec/golomb: Document return for get_ur_golomb_jpegls() and get_sr_golomb_flac()
|
||||
avcodec/dxv: Fix type in get_opcodes()
|
||||
avcodec/cri: Check length
|
||||
avcodec/xsubdec: Check parse_timecode()
|
||||
avutil/imgutils: av_image_check_size2() ensure width and height fit in 32bit
|
||||
doc/examples/mux: remove nop
|
||||
avcodec/proresenc_kostya: use unsigned alpha for rotation
|
||||
avformat/rtpenc_rfc4175: Use 64bit in computation if copy_offset
|
||||
avformat/rtmppkt: Simplify and deobfuscate amf_tag_skip() slightly
|
||||
avformat/rmdec: use 64bit for audio_framesize checks
|
||||
avutil/wchar_filename: Correct sizeof
|
||||
avutil/hwcontext_d3d11va: correct sizeof IDirect3DSurface9
|
||||
avutil/hwcontext_d3d11va: Free AVD3D11FrameDescriptor on error
|
||||
avutil/hwcontext_d3d11va: correct sizeof AVD3D11FrameDescriptor
|
||||
doc/examples/vaapi_encode: Try to check fwrite() for failure
|
||||
avformat/usmdec: Initialize value
|
||||
avformat/tls_schannel: Initialize ret
|
||||
avformat/subfile: Assert that whence is a known case
|
||||
avformat/subfile: Merge if into switch()
|
||||
avformat/rtsp: Check that lower transport is handled in one of the if()
|
||||
avformat/rtsp: initialize reply1
|
||||
avformat/rtsp: use < 0 for error check
|
||||
avformat/rtpenc_vc2hq: Check sizes
|
||||
avfilter/af_aderivative: Free out on error
|
||||
swscale/swscale: Use ptrdiff_t for linesize computations
|
||||
avfilter/af_afir: Assert format
|
||||
avfilter/af_afftdn: Assert format
|
||||
avfilter/af_pan: check nb_output_channels before use
|
||||
cbs_av1: Reject thirty-two zero bits in uvlc code
|
||||
avfilter/af_mcompand: compute half frequency in double
|
||||
avfilter/af_channelsplit: Assert that av_channel_layout_channel_from_index() succeeds
|
||||
avfilter/af_aresample: Cleanup on av_channel_layout_copy() failure
|
||||
tools/coverity: Phase 1 study of anti-halicogenic for coverity av_rescale()
|
||||
avfilter/vf_avgblur: Check plane instead of AVFrame
|
||||
avfilter/drawutils: Fix depthb computation
|
||||
avfilter/avf_showcwt: Check av_parse_video_rate() for failure
|
||||
avformat/rdt: Check pkt_len
|
||||
avformat/mpeg: Check len in mpegps_probe()
|
||||
avformat/mxfenc: resurrects the error print
|
||||
avdevice/dshow: Check ICaptureGraphBuilder2_SetFiltergraph() for failure
|
||||
avcodec/mfenc: check IMFSample_ConvertToContiguousBuffer() for failure
|
||||
avcodec/vc1_loopfilter: Factor duplicate code in vc1_b_h_intfi_loop_filter()
|
||||
avformat/img2dec: assert no pipe on ts_from_file
|
||||
avcodec/cbs_jpeg: Try to move the read entity to one side in a test
|
||||
fftools/ffmpeg_enc: Initialize fd
|
||||
fftools/ffmpeg_enc: simplify opaque_ref check
|
||||
avformat/mov: Check edit list for overflow
|
||||
fftools/ffmpeg: Check read() for failure
|
||||
MAINTAINERS: Add Timo Rothenpieler to server admins
|
||||
swscale/output: Avoid undefined overflow in yuv2rgb_write_full()
|
||||
swscale/output: alpha can become negative after scaling, use multiply
|
||||
avcodec/targaenc: Allocate space for the palette
|
||||
avcodec/r210enc: Use av_rescale for bitrate
|
||||
avcodec/jfdctint_template: Fewer integer anomalies
|
||||
avcodec/snowenc: MV limits due to mv_penalty table size
|
||||
tools/target_dec_fuzzer: Adjust threshold for MV30
|
||||
tools/target_dec_fuzzer: Adjust threshold for jpeg2000
|
||||
avformat/mxfdec: Check container_ul->desc before use
|
||||
avcodec/libvpxenc: Cleanup on error
|
||||
MAINTAINERS: Update the entries for the release maintainer for FFmpeg
|
||||
configure: update copyright year
|
||||
doc/developer: Provide information about git send-email and gmail
|
||||
avfilter/vf_rotate: Check ff_draw_init2() return value
|
||||
avformat/mov: Use int64_t in intermediate for corrected_dts
|
||||
avformat/mov: Use 64bit in intermediate for current_dts
|
||||
avformat/matroskadec: Assert that num_levels is non negative
|
||||
avformat/libzmq: Check av_strstart()
|
||||
avformat/img2dec: Little JFIF / Exif cleanup
|
||||
avformat/img2dec: Move DQT after unrelated if()
|
||||
avformat/imfdec: Simplify get_next_track_with_minimum_timestamp()
|
||||
avdevice/xcbgrab: Check sscanf() return
|
||||
fftools/cmdutils: Add protective () to FLAGS
|
||||
avformat/sdp: Check before appending ","
|
||||
avcodec/ilbcdec: Remove dead code
|
||||
avcodec/vp8: Check cond init
|
||||
avcodec/vp8: Check mutex init
|
||||
avcodec/proresenc_anatoliy: Assert that AV_PROFILE_UNKNOWN is replaced
|
||||
avcodec/pcm-dvdenc: 64bit pkt-size
|
||||
avcodec/notchlc: Check init_get_bits8() for failure
|
||||
avcodec/tests/dct: Use 64bit in intermediate for error computation
|
||||
avcodec/scpr3: Check add_dec() for failure
|
||||
avcodec/rv34: assert that size is not 0 in rv34_gen_vlc_ext()
|
||||
avcodec/wavpackenc: Use unsigned for potential 31bit shift
|
||||
avcodec/tests/jpeg2000dwt: Use 64bit in comparission
|
||||
avcodec/tests/jpeg2000dwt: Use 64bit in err2 computation
|
||||
avformat/fwse: Remove always false expression
|
||||
avcodec/sga: Make it clear that the return is intentionally not checked
|
||||
avformat/asfdec_f: Use 64bit for preroll computation
|
||||
avformat/argo_asf: Use 64bit in offset intermediate
|
||||
avformat/ape: Use 64bit for final frame size
|
||||
avformat/ac4dec: Check remaining space in ac4_probe()
|
||||
avdevice/pulse_audio_enc: Use av_rescale() to avoid integer overflow
|
||||
avcodec/vlc: Cleanup on multi table alloc failure in ff_vlc_init_multi_from_lengths()
|
||||
avcodec/tiff: Assert init_get_bits8() success in unpack_gray()
|
||||
avcodec/tiff: Assert init_get_bits8() success in horizontal_fill()
|
||||
tools/decode_simple: Check avcodec_send_packet() for errors on flushing
|
||||
swscale/yuv2rgb: Use 64bit for brightness computation
|
||||
swscale/x86/swscale: use a clearer name for INPUT_PLANER_RGB_A_FUNC_CASE
|
||||
avutil/tests/opt: Check av_set_options_string() for failure
|
||||
avutil/tests/dict: Check av_dict_set() before get for failure
|
||||
avdevice/dshow: fix badly indented line
|
||||
avformat/demux: resurrect dead stores
|
||||
avcodec/tests/bitstream_template: Assert bits_init8() return
|
||||
tools/enc_recon_frame_test: Assert that av_image_get_linesize() succeeds
|
||||
fftools/ffmpeg: prefer real errors over EOF in err_merge()
|
||||
avcodec/png: more informative error message for invalid sBIT size
|
||||
avcodec/pngdec: avoid erroring with sBIT on indexed-color images
|
||||
avcodec/nvenc: fix segfault in intra-only mode
|
||||
aarch64: Add OpenBSD runtime detection of dotprod and i8mm using sysctl
|
||||
qsv: Initialize impl_value
|
||||
avutil/hwcontext_qsv: fix GCC 14.1 warnings
|
||||
lavc/vp9: reset segmentation fields when segmentation isn't enabled
|
||||
configure: enable ffnvcodec, nvenc, nvdec for FreeBSD
|
||||
avcodec/mscc & mwsc: Check loop counts before use
|
||||
avcodec/mpegvideo_enc: Fix potential overflow in RD
|
||||
avcodec/mpeg4videodec: assert impossible wrap points
|
||||
avcodec/mpeg12dec: Use 64bit in bit computation
|
||||
avcodec/vqcdec: Check init_get_bits8() for failure
|
||||
avcodec/vble: Check av_image_get_buffer_size() for failure
|
||||
avcodec/vp3: Replace check by assert
|
||||
avcodec/vp8: Forward return of ff_vpx_init_range_decoder()
|
||||
avcodec/jpeg2000dec: remove ST=3 case
|
||||
avcodec/qsvdec: Check av_image_get_buffer_size() for failure
|
||||
avcodec/exr: Fix preview overflow
|
||||
avcodec/decode: decode_simple_internal() only implements audio and video
|
||||
avcodec/fmvc: remove dead assignment
|
||||
avcodec/h2645_sei: Remove dead checks
|
||||
avcodec/h264_slice: Remove dead sps check
|
||||
avcodec/lpc: copy levenson coeffs only when they have been computed
|
||||
avutil/tests/base64: Check with too short output array
|
||||
libavutil/base64: Try not to write over the array end
|
||||
avcodec/cbs_av1: Avoid shift overflow
|
||||
fftools/ffplay: Check return of swr_alloc_set_opts2()
|
||||
tools/opt_common: Check for malloc failure
|
||||
doc/examples/demux_decode: Simplify loop
|
||||
avformat/concatdec: Check file
|
||||
avcodec/mpegvideo_enc: Fix 1 line and one column images
|
||||
avcodec/amrwbdec: assert mode to be valid in decode_fixed_vector()
|
||||
avcodec/wavarc: fix integer overflow in decode_5elp() block type 2
|
||||
swscale/output: Fix integer overflow in yuv2rgba64_full_1_c_template()
|
||||
swscale/output: Fix integer overflow in yuv2rgba64_1_c_template
|
||||
avcodec/av1dec: Change bit_depth to int
|
||||
avcodec/av1dec: bit_depth cannot be another values than 8,10,12
|
||||
avcodec/avs3_parser: assert the return value of init_get_bits()
|
||||
avcodec/avs2_parser: Assert init_get_bits8() success with const size 15
|
||||
avformat/mxfdec: Check body_offset
|
||||
avformat/kvag: Check sample_rate
|
||||
avcodec/atrac9dec: Check init_get_bits8() for failure
|
||||
avcodec/ac3_parser: Check init_get_bits8() for failure
|
||||
avcodec/pngdec: Check last AVFrame before deref
|
||||
avcodec/hevcdec: Check ref frame
|
||||
doc/examples/qsv_transcode: Initialize pointer before free
|
||||
doc/examples/qsv_transcode: Simplify str_to_dict() loop
|
||||
doc/examples/vaapi_transcode: Simplify loop
|
||||
doc/examples/qsv_transcode: Simplify loop
|
||||
avcodec/cbs_h2645: Check NAL space
|
||||
avfilter/vf_thumbnail_cuda: Set ret before checking it
|
||||
avfilter/signature_lookup: Dont copy uninitialized stuff around
|
||||
avfilter/signature_lookup: Fix 2 differences to the refernce SW
|
||||
avcodec/x86/vp3dsp_init: Set correct function pointer, fix crash
|
||||
avformat/mp3dec: change bogus error message if read_header encounters EOF
|
||||
avformat/mp3dec: simplify inner frame size check in mp3_read_header
|
||||
avformat/mp3dec: only call ffio_ensure_seekback once
|
||||
avutil/thread: fix pthread_setname_np parameters for NetBSD and Apple
|
||||
avutil/thread: add support for setting thread name on *bsd and solaris
|
||||
avutil/ppc/cpu: Also use the machdep.altivec sysctl on NetBSD
|
||||
lavd/v4l2: Use proper field type for second parameter of ioctl() with BSD's
|
||||
avfilter/avfilter: fix OOM case for default activate
|
||||
avfilter/buffersrc: switch to activate
|
||||
avcodec/mediacodecenc: set quality in cq mode
|
||||
Update for 6.1.2
|
||||
fate/subtitles: Ignore line endings for sub-scc test
|
||||
avformat/mxfdec: Check index_edit_rate
|
||||
swscale/utils: Fix xInc overflow
|
||||
avcodec/wavarc: fix signed integer overflow in block type 6/19
|
||||
doc/developer: (security) researchers should be credited
|
||||
avformat/isom: Uninit layout in ff_mp4_read_dec_config_descr()
|
||||
avcodec/exr: Dont use 64bits to hold 6bits
|
||||
avcodec/exr: Check for remaining bits in huf_unpack_enc_table()
|
||||
avcodec/apedec: Use NABS to avoid undefined negation
|
||||
avformat/mpegts: Reset local nb_prg on add_program() failure
|
||||
avformat/aiffdec: Check for previously set channels
|
||||
avformat/mxfdec: Make edit_unit_byte_count unsigned
|
||||
avformat/movenc: Check that cts fits in 32bit
|
||||
avformat/mxfdec: Check first case of offset_temp computation for overflow
|
||||
avcodec/jpeg2000htdec: warn about non zero roi shift
|
||||
avcodec/jpeg2000htdec: Check magp before using it in a shift
|
||||
avfilter/vf_signature: Dont crash on no frames
|
||||
avformat/westwood_vqa: Fix 2g packets
|
||||
avformat/matroskadec: Check timescale
|
||||
avformat/wavdec: satuarte next_tag_ofs, data_end
|
||||
avformat/wavdec: sanity check channels and bps before using them for block_align
|
||||
avformat/sbgdec: Check for negative duration
|
||||
avformat/rpl: Use 64bit for total_audio_size and check it
|
||||
avformat/timecode: use 64bit for intermediate for rounding in fps_from_frame_rate()
|
||||
avformat/mov: use 64bit for intermediate for rounding
|
||||
avformat/jacosubdec: Use 64bit for abs
|
||||
avformat/concatdec: Check user_duration sum
|
||||
avcodec/wavarc: avoid signed integer overflow in AC code
|
||||
avcodec/wavarc: Avoid signed integer overflow in sample
|
||||
avcodec/truemotion1: Height not being a multiple of 4 is unsupported
|
||||
avcodec/rtv1: fix undefined FFALIGN
|
||||
avcodec/hcadec: do not allow code to continue after failed init
|
||||
avcodec/hcadec: do not set hfr_group_count to invalid values
|
||||
avformat/concatdec: clip outpoint - inpoint overflow in get_best_effort_duration()
|
||||
avcodec/osq: avoid several signed integer overflows
|
||||
avformat/jacosubdec: clarify code
|
||||
avformat/cafdec: Check that data chunk end fits within 64bit
|
||||
avformat/iff: Saturate avio_tell() + 12
|
||||
avformat/dxa: Adjust order of operations around block align
|
||||
avformat/cafdec: dont seek beyond 64bit
|
||||
avformat/id3v2: read_uslt() check for the amount read
|
||||
avcodec/vmixdec: Check shift before use
|
||||
avformat/mov: Check sample_count and auxiliary_info_default_size to be 0
|
||||
avformat/wady: Check >0 samplerate and channels 1 || 2.
|
||||
avcodec/cbs_h266_syntax_template: Check tile_y
|
||||
avcodec/proresenc_kostya: Remove bug similarity text
|
||||
avcodec/vorbisdec: Check remaining data in vorbis_residue_decode_internal()
|
||||
avformat/concatdec: Check in and outpoints to be to produce a positive representable duration
|
||||
avcodec/8bps: Consider width in the minimal size check
|
||||
libswscale/utils: Fix bayer to yuvj
|
||||
swscale/swscale: Check srcSliceH for bayer
|
||||
swscale/utils: Allocate more dithererror
|
||||
avcodec/indeo3: Round dimensions up in allocate_frame_buffers()
|
||||
avutil/rational: Document what is to be expected from av_d2q() of doubles representing rational numbers
|
||||
avfilter/signature_lookup: Do not dereference NULL pointers after malloc failure
|
||||
avfilter/signature_lookup: dont leave uncleared pointers in sll_free()
|
||||
avcodec/mpegvideo_enc: Use ptrdiff_t for stride
|
||||
libavformat/hlsenc.c: Populate OTI using AAC profile in write_codec_attr.
|
||||
avformat/mov: Check if a key is longer than the atom containing it
|
||||
avcodec/nvenc: support SDK 12.2 bit depth API
|
||||
avcodec/nvenc: stop using long deprecated format specifiers
|
||||
avfilter/buffersrc: fix overriding unknown channel layouts with negotiated one
|
||||
avfilter/af_channelmap: disallow channel index 64
|
||||
avfilter/af_channelmap: fix mapping if in_channel was a string but out_channel was not specified
|
||||
avfilter/af_channelmap: fix error message if FL source channel was missing
|
||||
avcodec/nvdec: reset bitstream_len/nb_slices when resetting bitstream pointer
|
||||
avformat/mov: don't abort on duplicate Mastering Display Metadata boxes
|
||||
fftools/ffplay: use correct buffersink channel layout parameters
|
||||
avformat/mpegts: detect synchronous metadata KLV more reliably
|
||||
swresample/resample: fix rounding errors with filter_size=1 and phase_shift=0
|
||||
avformat/mxfdec: remove resolve_strong_ref usage with AnyType
|
||||
avfilter/vf_convolution: add float user_rdiv[4] to allow user options to apply correctly
|
||||
avformat/libsrt: use SRT_EPOLL_IN for waiting for an incoming connection
|
||||
avformat/mxfdec: do not use AnyType when resolving Descriptors and MultipleDescriptors
|
||||
avformat/mxfdec: move resolving Descriptors to the multi descriptor resolve function
|
||||
avutil/hwcontext_d3d11va: prefer DXGI 1.1 factory when available
|
||||
avcodec/libsvtav1: send the EOS signal without a one frame delay to allow for the library to operate in a low-delay mode
|
||||
avcodec/libsvtav1: add version guard for external param
|
||||
lavc/vvc: Read subpic ID when only one subpicture is present
|
||||
lavc/vvc: Correct sps_num_subpics_minus1 minimum
|
||||
avcodec/cbs_h2645: Avoid function pointer casts, fix UB
|
||||
avcodec/cbs_h266_syntax_template: Don't omit unused function parameter
|
||||
avcodec/cbs_h266_syntax_template: check aps_adaptation_parameter_set_id
|
||||
lavc/vvc: Add check to num_multi_layer_olss
|
||||
avcodec/cbs_h266: fix logic setting num_layers_in_ols when vps_ols_mode_idc is 2
|
||||
avcodec/av1dec: fix matrix coefficients exposed by codec context
|
||||
{avcodec,tests}: rename the bundled Mesa AV1 vulkan video headers
|
||||
avformat/mov_chan: never override number of channels based on chan atom
|
||||
avformat/mov_chan: do not assume channels are in native order
|
||||
avfft: avoid overreads with RDFT API users
|
||||
avcodec/nvdec: don't free NVDECContext->bitstream
|
||||
avcodec/mediacodecdec: fix return EAGAIN after EOF
|
||||
|
||||
|
||||
version 7.0:
|
||||
- DXV DXT1 encoder
|
||||
- LEAD MCMP decoder
|
||||
- EVC decoding using external library libxevd
|
||||
- EVC encoding using external library libxeve
|
||||
- QOA decoder and demuxer
|
||||
- aap filter
|
||||
- demuxing, decoding, filtering, encoding, and muxing in the
|
||||
ffmpeg CLI now all run in parallel
|
||||
- enable gdigrab device to grab a window using the hwnd=HANDLER syntax
|
||||
- IAMF raw demuxer and muxer
|
||||
- D3D12VA hardware accelerated H264, HEVC, VP9, AV1, MPEG-2 and VC1 decoding
|
||||
- tiltandshift filter
|
||||
- qrencode filter and qrencodesrc source
|
||||
- quirc filter
|
||||
- lavu/eval: introduce randomi() function in expressions
|
||||
- VVC decoder (experimental)
|
||||
- fsync filter
|
||||
- Raw Captions with Time (RCWT) closed caption muxer
|
||||
- ffmpeg CLI -bsf option may now be used for input as well as output
|
||||
- ffmpeg CLI options may now be used as -/opt <path>, which is equivalent
|
||||
to -opt <contents of file <path>>
|
||||
- showinfo bitstream filter
|
||||
- a C11-compliant compiler is now required; note that this requirement
|
||||
will be bumped to C17 in the near future, so consider updating your
|
||||
build environment if it lacks C17 support
|
||||
- Change the default bitrate control method from VBR to CQP for QSV encoders.
|
||||
- removed deprecated ffmpeg CLI options -psnr and -map_channel
|
||||
- DVD-Video demuxer, powered by libdvdnav and libdvdread
|
||||
- ffprobe -show_stream_groups option
|
||||
- ffprobe (with -export_side_data film_grain) now prints film grain metadata
|
||||
- AEA muxer
|
||||
- ffmpeg CLI loopback decoders
|
||||
- Support PacketTypeMetadata of PacketType in enhanced flv format
|
||||
- ffplay with hwaccel decoding support (depends on vulkan renderer via libplacebo)
|
||||
- dnn filter libtorch backend
|
||||
- Android content URIs protocol
|
||||
- AOMedia Film Grain Synthesis 1 (AFGS1)
|
||||
- RISC-V optimizations for AAC, FLAC, JPEG-2000, LPC, RV4.0, SVQ, VC1, VP8, and more
|
||||
- Loongarch optimizations for HEVC decoding
|
||||
- Important AArch64 optimizations for HEVC
|
||||
- IAMF support inside MP4/ISOBMFF
|
||||
- Support for HEIF/AVIF still images and tiled still images
|
||||
- Dolby Vision profile 10 support in AV1
|
||||
- Support for Ambient Viewing Environment metadata in MP4/ISOBMFF
|
||||
- HDR10 metadata passthrough when encoding with libx264, libx265, and libsvtav1
|
||||
version 6.1.1
|
||||
- avcodec/mpegvideo_enc: Dont copy beyond the image
|
||||
- avfilter/vf_minterpolate: Check pts before division
|
||||
- avfilter/avf_showwaves: Check history_nb_samples
|
||||
- avformat/flacdec: Avoid double AVERRORS
|
||||
- avfilter/vf_vidstabdetect: Avoid double AVERRORS
|
||||
- avcodec/vaapi_encode: Avoid double AVERRORS
|
||||
- avfilter/vf_swaprect: round coordinates down
|
||||
- avfilter/vf_swaprect: Use height for vertical variables
|
||||
- avfilter/vf_swaprect: assert that rectangles are within memory
|
||||
- avfilter/af_alimiter: Check nextpos before use
|
||||
- avfilter/f_reverse: Apply PTS compensation only when pts is available
|
||||
- avfilter/af_stereowiden: Check length
|
||||
- avformat/mov: Fix MSAN issue with stsd_id
|
||||
- avcodec/jpegxl_parser: Check get_vlc2()
|
||||
- avfilter/vf_weave: Fix odd height handling
|
||||
- avfilter/edge_template: Fix small inputs with gaussian_blur()
|
||||
- avfilter/vf_gradfun: Do not overread last line
|
||||
- avfilter/avf_showspectrum: fix off by 1 error
|
||||
- avcodec/jpegxl_parser: Add padding to cs_buffer
|
||||
- avformat/mov: do not set sign bit for chunk_offsets
|
||||
- avcodec/jpeglsdec: Check Jpeg-LS LSE
|
||||
- avcodec/osq: Implement flush()
|
||||
- configure: Enable section_data_rel_ro for FreeBSD and NetBSD aarch64 / arm
|
||||
- avcodec/cbs_h266: more restrictive check on pps_tile_idx_delta_val
|
||||
- avcodec/jpeg2000htdec: check if block decoding will exceed internal precision
|
||||
- tools/target_dec_fuzzer: Adjust threshold for VMIX
|
||||
- avcodec/av1dec: Fix resolving zero divisor
|
||||
- avformat/mov: Ignore duplicate ftyp
|
||||
- avformat/mov: Fix integer overflow in mov_read_packet().
|
||||
- lavc/qsvdec: return 0 if more data is required
|
||||
- avcodec/jpegxl_parser: check ANS cluster alphabet size vs bundle size
|
||||
- libavformat/vvc: Make probe more conservative
|
||||
- hwcontext_vulkan: guard unistd.h include
|
||||
- lavc/Makefile: build vulkan decode code if vulkan_av1 has been enabled
|
||||
- lavc/dvdsubenc: only check canvas size when it is actually set
|
||||
- avcodec/decode: validate hw_frames_ctx when AVHWAccel.free_frame_priv is used
|
||||
- avcoded/fft: Fix memory leak if ctx2 is used
|
||||
- avcodec/fft: Use av_mallocz to avoid invalid free/uninit
|
||||
|
||||
|
||||
version 6.1:
|
||||
|
||||
+104
-73
@@ -6,26 +6,10 @@ FFmpeg code.
|
||||
|
||||
Please try to keep entries where you are the maintainer up to date!
|
||||
|
||||
*Status*, one of the following:
|
||||
[X] Old code. Something tagged obsolete generally means it has been replaced by a better system and you should be using that.
|
||||
[0] No current maintainer [but maybe you could take the role as you write your new code].
|
||||
[1] It has a maintainer but they don't have time to do much other than throw the odd patch in.
|
||||
[2] Someone actually looks after it.
|
||||
|
||||
Names in () mean that the maintainer currently has no time to maintain the code.
|
||||
A (CC <address>) after the name means that the maintainer prefers to be CC-ed on
|
||||
patches and related discussions.
|
||||
|
||||
(L <address>) *Mailing list* that is relevant to this area
|
||||
(W <address>) *Web-page* with status/info
|
||||
(B <address>) URI for where to file *bugs*. A web-page with detailed bug
|
||||
filing info, a direct bug tracker link, or a mailto: URI.
|
||||
(P <address>) *Subsystem Profile* document for more details submitting
|
||||
patches to the given subsystem. This is either an in-tree file,
|
||||
or a URI. See Documentation/maintainer/maintainer-entry-profile.rst
|
||||
for details.
|
||||
(T <address>) *SCM* tree type and location.
|
||||
Type is one of: git, hg, quilt, stgit, topgit
|
||||
|
||||
|
||||
Applications
|
||||
============
|
||||
@@ -34,10 +18,10 @@ ffmpeg:
|
||||
ffmpeg.c Michael Niedermayer, Anton Khirnov
|
||||
|
||||
ffplay:
|
||||
ffplay.c [2] Marton Balint
|
||||
ffplay.c Marton Balint
|
||||
|
||||
ffprobe:
|
||||
ffprobe.c [2] Stefano Sabatini
|
||||
ffprobe.c Stefano Sabatini
|
||||
|
||||
Commandline utility code:
|
||||
cmdutils.c, cmdutils.h Michael Niedermayer
|
||||
@@ -50,24 +34,25 @@ Miscellaneous Areas
|
||||
===================
|
||||
|
||||
documentation Stefano Sabatini, Mike Melanson, Timothy Gu, Gyan Doshi
|
||||
project server day to day operations (L: root@ffmpeg.org) Árpád Gereöffy, Michael Niedermayer, Reimar Doeffinger, Alexander Strasser, Nikolay Aleksandrov, Timo Rothenpieler
|
||||
project server emergencies (L: root@ffmpeg.org) Árpád Gereöffy, Reimar Doeffinger, Alexander Strasser, Nikolay Aleksandrov, Timo Rothenpieler
|
||||
presets [0]
|
||||
project server day to day operations Árpád Gereöffy, Michael Niedermayer, Reimar Doeffinger, Alexander Strasser, Nikolay Aleksandrov, Timo Rothenpieler
|
||||
project server emergencies Árpád Gereöffy, Reimar Doeffinger, Alexander Strasser, Nikolay Aleksandrov, Timo Rothenpieler
|
||||
presets Robert Swain
|
||||
metadata subsystem Aurelien Jacobs
|
||||
release management Michael Niedermayer
|
||||
API tests [0]
|
||||
API tests Ludmila Glinskih
|
||||
|
||||
|
||||
Communication
|
||||
=============
|
||||
website (T: https://git.ffmpeg.org/ffmpeg-web) Deby Barbara Lepage
|
||||
fate.ffmpeg.org (L: fate-admin@ffmpeg.org) (W: https://fate.ffmpeg.org) (P: https://ffmpeg.org/fate.html) (S: https://git.ffmpeg.org/fateserver) Timo Rothenpieler
|
||||
Trac bug tracker (W: https://trac.ffmpeg.org) Alexander Strasser, Michael Niedermayer, Carl Eugen Hoyos
|
||||
Patchwork [2] (W: https://patchwork.ffmpeg.org) Andriy Gelman
|
||||
mailing lists (W: https://ffmpeg.org/contact.html#MailingLists) Baptiste Coudurier
|
||||
|
||||
website Deby Barbara Lepage
|
||||
fate.ffmpeg.org Timothy Gu
|
||||
Trac bug tracker Alexander Strasser, Michael Niedermayer, Carl Eugen Hoyos
|
||||
Patchwork Andriy Gelman
|
||||
mailing lists Baptiste Coudurier
|
||||
Twitter Reynaldo H. Verdejo Pinochet
|
||||
Launchpad Timothy Gu
|
||||
ffmpeg-security [2] (L: ffmpeg-security@ffmpeg.org) (W: https://ffmpeg.org/security.html) Michael Niedermayer, Reimar Doeffinger
|
||||
ffmpeg-security Andreas Cadhalpun, Carl Eugen Hoyos, Clément Bœsch, Michael Niedermayer, Reimar Doeffinger, rcombs, wm4
|
||||
|
||||
|
||||
libavutil
|
||||
@@ -84,22 +69,22 @@ Other:
|
||||
bswap.h
|
||||
des Reimar Doeffinger
|
||||
dynarray.h Nicolas George
|
||||
eval.c, eval.h [2] Michael Niedermayer
|
||||
eval.c, eval.h Michael Niedermayer
|
||||
float_dsp Loren Merritt
|
||||
hash Reimar Doeffinger
|
||||
hwcontext_cuda* Timo Rothenpieler
|
||||
hwcontext_vulkan* [2] Lynne
|
||||
hwcontext_vulkan* Lynne
|
||||
intfloat* Michael Niedermayer
|
||||
integer.c, integer.h Michael Niedermayer
|
||||
lzo Reimar Doeffinger
|
||||
mathematics.c, mathematics.h [2] Michael Niedermayer
|
||||
mem.c, mem.h [2] Michael Niedermayer
|
||||
mathematics.c, mathematics.h Michael Niedermayer
|
||||
mem.c, mem.h Michael Niedermayer
|
||||
opencl.c, opencl.h Wei Gao
|
||||
opt.c, opt.h Michael Niedermayer
|
||||
rational.c, rational.h [2] Michael Niedermayer
|
||||
rational.c, rational.h Michael Niedermayer
|
||||
rc4 Reimar Doeffinger
|
||||
ripemd.c, ripemd.h James Almer
|
||||
tx* [2] Lynne
|
||||
tx* Lynne
|
||||
|
||||
|
||||
libavcodec
|
||||
@@ -121,20 +106,20 @@ Generic Parts:
|
||||
DSP utilities:
|
||||
dsputils.c, dsputils.h Michael Niedermayer
|
||||
entropy coding:
|
||||
rangecoder.c, rangecoder.h [2] Michael Niedermayer
|
||||
rangecoder.c, rangecoder.h Michael Niedermayer
|
||||
lzw.* Michael Niedermayer
|
||||
floating point AAN DCT:
|
||||
faandct.c, faandct.h [2] Michael Niedermayer
|
||||
faandct.c, faandct.h Michael Niedermayer
|
||||
Golomb coding:
|
||||
golomb.c, golomb.h [2] Michael Niedermayer
|
||||
golomb.c, golomb.h Michael Niedermayer
|
||||
motion estimation:
|
||||
motion* Michael Niedermayer
|
||||
rate control:
|
||||
ratecontrol.c [2] Michael Niedermayer
|
||||
ratecontrol.c Michael Niedermayer
|
||||
simple IDCT:
|
||||
simple_idct.c, simple_idct.h [2] Michael Niedermayer
|
||||
simple_idct.c, simple_idct.h Michael Niedermayer
|
||||
postprocessing:
|
||||
libpostproc/* [2] Michael Niedermayer
|
||||
libpostproc/* Michael Niedermayer
|
||||
table generation:
|
||||
tableprint.c, tableprint.h Reimar Doeffinger
|
||||
fixed point FFT:
|
||||
@@ -142,7 +127,7 @@ Generic Parts:
|
||||
Text Subtitles Clément Bœsch
|
||||
|
||||
Codecs:
|
||||
4xm.c [2] Michael Niedermayer
|
||||
4xm.c Michael Niedermayer
|
||||
8bps.c Roberto Togni
|
||||
8svx.c Jaikrishnan Menon
|
||||
aacenc*, aaccoder.c Rostislav Pehlivanov
|
||||
@@ -159,6 +144,7 @@ Codecs:
|
||||
bgmc.c, bgmc.h Thilo Borgmann
|
||||
binkaudio.c Peter Ross
|
||||
cavs* Stefan Gehrer
|
||||
cdxl.c Paul B Mahol
|
||||
celp_filters.* Vitor Sessak
|
||||
cinepak.c Roberto Togni
|
||||
cinepakenc.c Rl / Aetey G.T. AB
|
||||
@@ -177,8 +163,9 @@ Codecs:
|
||||
dv.c Roman Shaposhnik
|
||||
dvbsubdec.c Anshul Maheshwari
|
||||
eacmv*, eaidct*, eat* Peter Ross
|
||||
evrc* Paul B Mahol
|
||||
exif.c, exif.h Thilo Borgmann
|
||||
ffv1* [2] Michael Niedermayer
|
||||
ffv1* Michael Niedermayer
|
||||
ffwavesynth.c Nicolas George
|
||||
fifo.c Jan Sebechlebsky
|
||||
flicvideo.c Mike Melanson
|
||||
@@ -189,7 +176,6 @@ Codecs:
|
||||
h263* Michael Niedermayer
|
||||
h264* Loren Merritt, Michael Niedermayer
|
||||
hap* Tom Butterworth
|
||||
hevc/* Anton Khirnov
|
||||
huffyuv* Michael Niedermayer
|
||||
idcinvideo.c Mike Melanson
|
||||
interplayvideo.c Mike Melanson
|
||||
@@ -231,6 +217,7 @@ Codecs:
|
||||
nvdec*, nvenc* Timo Rothenpieler
|
||||
omx.c Martin Storsjo, Aman Gupta
|
||||
opus* Rostislav Pehlivanov
|
||||
paf.* Paul B Mahol
|
||||
pcx.c Ivo van Poorten
|
||||
pgssubdec.c Reimar Doeffinger
|
||||
ptx.c Ivo van Poorten
|
||||
@@ -244,6 +231,7 @@ Codecs:
|
||||
rpza.c Roberto Togni
|
||||
rtjpeg.c, rtjpeg.h Reimar Doeffinger
|
||||
rv10.c Michael Niedermayer
|
||||
s3tc* Ivo van Poorten
|
||||
smc.c Mike Melanson
|
||||
snow* Michael Niedermayer, Loren Merritt
|
||||
sonic.c Alex Beregszaszi
|
||||
@@ -251,13 +239,16 @@ Codecs:
|
||||
srt* Aurelien Jacobs
|
||||
sunrast.c Ivo van Poorten
|
||||
svq3.c Michael Niedermayer
|
||||
tak* Paul B Mahol
|
||||
truemotion1* Mike Melanson
|
||||
tta.c Alex Beregszaszi, Jaikrishnan Menon
|
||||
ttaenc.c Paul B Mahol
|
||||
txd.c Ivo van Poorten
|
||||
v4l2_* Jorge Ramirez-Ortiz
|
||||
vc2* Rostislav Pehlivanov
|
||||
vcr1.c Michael Niedermayer
|
||||
videotoolboxenc.c Rick Kern, Aman Gupta
|
||||
vima.c Paul B Mahol
|
||||
vorbisdec.c Denes Balatoni, David Conrad
|
||||
vorbisenc.c Oded Shimon
|
||||
vp3* Mike Melanson
|
||||
@@ -266,22 +257,22 @@ Codecs:
|
||||
vp8 David Conrad, Ronald Bultje
|
||||
vp9 Ronald Bultje
|
||||
vqavideo.c Mike Melanson
|
||||
vvc [2] Nuo Mi
|
||||
wmaprodec.c Sascha Sommer
|
||||
wmavoice.c Ronald S. Bultje
|
||||
wmv2.c Michael Niedermayer
|
||||
xan.c Mike Melanson
|
||||
xbm* Paul B Mahol
|
||||
xface Stefano Sabatini
|
||||
xwd* Paul B Mahol
|
||||
|
||||
Hardware acceleration:
|
||||
dxva2* Hendrik Leppkes, Laurent Aimar, Steve Lhomme
|
||||
d3d11va* Steve Lhomme
|
||||
d3d12va_encode* Tong Wu
|
||||
mediacodec* Matthieu Bouron, Aman Gupta, Zhao Zhili
|
||||
mediacodec* Matthieu Bouron, Aman Gupta
|
||||
vaapi* Haihao Xiang
|
||||
vaapi_encode* Mark Thompson, Haihao Xiang
|
||||
vdpau* Philip Langdale, Carl Eugen Hoyos
|
||||
videotoolbox* Rick Kern, Aman Gupta, Zhao Zhili
|
||||
videotoolbox* Rick Kern, Aman Gupta
|
||||
|
||||
|
||||
libavdevice
|
||||
@@ -316,38 +307,67 @@ Generic parts:
|
||||
motion_estimation.c Davinder Singh
|
||||
|
||||
Filters:
|
||||
f_drawgraph.c Paul B Mahol
|
||||
af_adelay.c Paul B Mahol
|
||||
af_aecho.c Paul B Mahol
|
||||
af_afade.c Paul B Mahol
|
||||
af_amerge.c Nicolas George
|
||||
af_aphaser.c Paul B Mahol
|
||||
af_aresample.c Michael Niedermayer
|
||||
af_astats.c Paul B Mahol
|
||||
af_atempo.c Pavel Koshevoy
|
||||
af_biquads.c Paul B Mahol
|
||||
af_chorus.c Paul B Mahol
|
||||
af_compand.c Paul B Mahol
|
||||
af_firequalizer.c Muhammad Faiz
|
||||
af_hdcd.c Burt P.
|
||||
af_ladspa.c Paul B Mahol
|
||||
af_loudnorm.c Kyle Swanson
|
||||
af_pan.c Nicolas George
|
||||
af_sidechaincompress.c Paul B Mahol
|
||||
af_silenceremove.c Paul B Mahol
|
||||
avf_aphasemeter.c Paul B Mahol
|
||||
avf_avectorscope.c Paul B Mahol
|
||||
avf_showcqt.c Muhammad Faiz
|
||||
vf_blend.c Paul B Mahol
|
||||
vf_bwdif Thomas Mundt (CC <thomas.mundt@hr.de>)
|
||||
vf_chromakey.c Timo Rothenpieler
|
||||
vf_colorchannelmixer.c Paul B Mahol
|
||||
vf_colorconstancy.c Mina Sami (CC <minas.gorgy@gmail.com>)
|
||||
vf_colorbalance.c Paul B Mahol
|
||||
vf_colorkey.c Timo Rothenpieler
|
||||
vf_colorlevels.c Paul B Mahol
|
||||
vf_coreimage.m Thilo Borgmann
|
||||
vf_deband.c Paul B Mahol
|
||||
vf_dejudder.c Nicholas Robbins
|
||||
vf_delogo.c Jean Delvare (CC <jdelvare@suse.com>)
|
||||
vf_drawbox.c/drawgrid Andrey Utkin
|
||||
vf_fsync.c Thilo Borgmann
|
||||
vf_extractplanes.c Paul B Mahol
|
||||
vf_histogram.c Paul B Mahol
|
||||
vf_hqx.c Clément Bœsch
|
||||
vf_idet.c Pascal Massimino
|
||||
vf_il.c Paul B Mahol
|
||||
vf_(t)interlace Thomas Mundt (CC <thomas.mundt@hr.de>)
|
||||
vf_lenscorrection.c Daniel Oberhoff
|
||||
vf_libplacebo.c Niklas Haas
|
||||
vf_mergeplanes.c Paul B Mahol
|
||||
vf_mestimate.c Davinder Singh
|
||||
vf_minterpolate.c Davinder Singh
|
||||
vf_neighbor.c Paul B Mahol
|
||||
vf_psnr.c Paul B Mahol
|
||||
vf_random.c Paul B Mahol
|
||||
vf_readvitc.c Tobias Rapp (CC t.rapp at noa-archive dot com)
|
||||
vf_scale.c [2] Michael Niedermayer
|
||||
vf_scale.c Michael Niedermayer
|
||||
vf_separatefields.c Paul B Mahol
|
||||
vf_ssim.c Paul B Mahol
|
||||
vf_stereo3d.c Paul B Mahol
|
||||
vf_telecine.c Paul B Mahol
|
||||
vf_tonemap_opencl.c Ruiling Song
|
||||
vf_yadif.c [2] Michael Niedermayer
|
||||
vf_xfade_vulkan.c [2] Marvin Scholz (CC <epirat07@gmail.com>)
|
||||
vf_yadif.c Michael Niedermayer
|
||||
vf_zoompan.c Paul B Mahol
|
||||
|
||||
Sources:
|
||||
vsrc_mandelbrot.c [2] Michael Niedermayer
|
||||
vsrc_mandelbrot.c Michael Niedermayer
|
||||
|
||||
dnn Yejun Guo
|
||||
|
||||
@@ -365,7 +385,8 @@ Generic parts:
|
||||
Muxers/Demuxers:
|
||||
4xm.c Mike Melanson
|
||||
aadec.c Vesselin Bontchev (vesselin.bontchev at yandex dot com)
|
||||
adtsenc.c [0]
|
||||
adtsenc.c Robert Swain
|
||||
afc.c Paul B Mahol
|
||||
aiffdec.c Baptiste Coudurier, Matthieu Bouron
|
||||
aiffenc.c Baptiste Coudurier, Matthieu Bouron
|
||||
alp.c Zane van Iperen
|
||||
@@ -376,12 +397,16 @@ Muxers/Demuxers:
|
||||
argo_brp.c Zane van Iperen
|
||||
argo_cvg.c Zane van Iperen
|
||||
ass* Aurelien Jacobs
|
||||
astdec.c Paul B Mahol
|
||||
astenc.c James Almer
|
||||
avi* Michael Niedermayer
|
||||
avisynth.c Stephen Hutchinson
|
||||
avr.c Paul B Mahol
|
||||
bink.c Peter Ross
|
||||
boadec.c Michael Niedermayer
|
||||
brstm.c Paul B Mahol
|
||||
caf* Peter Ross
|
||||
cdxl.c Paul B Mahol
|
||||
codec2.c Tomas Härdin
|
||||
crc.c Michael Niedermayer
|
||||
dashdec.c Steven Liu
|
||||
@@ -390,9 +415,10 @@ Muxers/Demuxers:
|
||||
dfpwmdec.c Jack Bruienne
|
||||
dss.c Oleksij Rempel
|
||||
dtsdec.c foo86
|
||||
dtshddec.c Paul B Mahol
|
||||
dv.c Roman Shaposhnik
|
||||
dvdvideodec.c Marth64
|
||||
electronicarts.c Peter Ross
|
||||
epafdec.c Paul B Mahol
|
||||
evc* Samsung (Dawid Kozinski)
|
||||
ffm* Baptiste Coudurier
|
||||
flic.c Mike Melanson
|
||||
@@ -401,13 +427,13 @@ Muxers/Demuxers:
|
||||
gxf.c Reimar Doeffinger
|
||||
gxfenc.c Baptiste Coudurier
|
||||
hlsenc.c Christian Suloway, Steven Liu
|
||||
iamf* [2] James Almer
|
||||
idcin.c Mike Melanson
|
||||
idroqdec.c Mike Melanson
|
||||
iff.c Jaikrishnan Menon
|
||||
imf* Pierre-Anthony Lemieux
|
||||
img2*.c Michael Niedermayer
|
||||
ipmovie.c Mike Melanson
|
||||
ircam* Paul B Mahol
|
||||
iss.c Stefan Gehrer
|
||||
jpegxl* Leo Izen
|
||||
jvdec.c Peter Ross
|
||||
@@ -415,12 +441,14 @@ Muxers/Demuxers:
|
||||
libmodplug.c Clément Bœsch
|
||||
libopenmpt.c Josh de Kock
|
||||
lmlm4.c Ivo van Poorten
|
||||
lvfdec.c Paul B Mahol
|
||||
lxfdec.c Tomas Härdin
|
||||
matroska.c Andreas Rheinhardt
|
||||
matroskadec.c Andreas Rheinhardt
|
||||
matroskaenc.c Andreas Rheinhardt
|
||||
matroska.c Aurelien Jacobs, Andreas Rheinhardt
|
||||
matroskadec.c Aurelien Jacobs, Andreas Rheinhardt
|
||||
matroskaenc.c David Conrad, Andreas Rheinhardt
|
||||
matroska subtitles (matroskaenc.c) John Peebles
|
||||
metadata* Aurelien Jacobs
|
||||
mgsts.c Paul B Mahol
|
||||
microdvd* Aurelien Jacobs
|
||||
mm.c Peter Ross
|
||||
mov.c Baptiste Coudurier
|
||||
@@ -433,6 +461,7 @@ Muxers/Demuxers:
|
||||
msnwc_tcp.c Ramiro Polla
|
||||
mtv.c Reynaldo H. Verdejo Pinochet
|
||||
mxf* Baptiste Coudurier, Tomas Härdin
|
||||
nistspheredec.c Paul B Mahol
|
||||
nsvdec.c Francois Revol
|
||||
nut* Michael Niedermayer
|
||||
nuv.c Reimar Doeffinger
|
||||
@@ -440,12 +469,13 @@ Muxers/Demuxers:
|
||||
oggenc.c Baptiste Coudurier
|
||||
oggparse*.c David Conrad
|
||||
oma.c Maxim Poliakovski
|
||||
paf.c Paul B Mahol
|
||||
pp_bnk.c Zane van Iperen
|
||||
psxstr.c Mike Melanson
|
||||
pva.c Ivo van Poorten
|
||||
pvfdec.c Paul B Mahol
|
||||
r3d.c Baptiste Coudurier
|
||||
raw.c Michael Niedermayer
|
||||
rcwtenc.c Marth64
|
||||
rdt.c Ronald S. Bultje
|
||||
rl2.c Sascha Sommer
|
||||
rmdec.c, rmenc.c Ronald S. Bultje
|
||||
@@ -464,9 +494,11 @@ Muxers/Demuxers:
|
||||
sdp.c Martin Storsjo
|
||||
segafilm.c Mike Melanson
|
||||
segment.c Stefano Sabatini
|
||||
smjpeg* Paul B Mahol
|
||||
spdif* Anssi Hannula
|
||||
srtdec.c Aurelien Jacobs
|
||||
swf.c Baptiste Coudurier
|
||||
takdec.c Paul B Mahol
|
||||
tta.c Alex Beregszaszi
|
||||
txd.c Ivo van Poorten
|
||||
voc.c Aurelien Jacobs
|
||||
@@ -476,6 +508,7 @@ Muxers/Demuxers:
|
||||
webvtt* Matthew J Heaney
|
||||
westwood.c Mike Melanson
|
||||
wtv.c Peter Ross
|
||||
wvenc.c Paul B Mahol
|
||||
|
||||
Protocols:
|
||||
async.c Zhang Rui
|
||||
@@ -487,37 +520,37 @@ Protocols:
|
||||
libzmq.c Andriy Gelman
|
||||
mms*.c Ronald S. Bultje
|
||||
udp.c Luca Abeni
|
||||
icecast.c [2] Marvin Scholz (CC <epirat07@gmail.com>)
|
||||
icecast.c Marvin Scholz
|
||||
|
||||
|
||||
libswresample
|
||||
=============
|
||||
|
||||
Generic parts:
|
||||
audioconvert.c [2] Michael Niedermayer
|
||||
dither.c [2] Michael Niedermayer
|
||||
rematrix*.c [2] Michael Niedermayer
|
||||
swresample*.c [2] Michael Niedermayer
|
||||
audioconvert.c Michael Niedermayer
|
||||
dither.c Michael Niedermayer
|
||||
rematrix*.c Michael Niedermayer
|
||||
swresample*.c Michael Niedermayer
|
||||
|
||||
Resamplers:
|
||||
resample*.c [2] Michael Niedermayer
|
||||
resample*.c Michael Niedermayer
|
||||
soxr_resample.c Rob Sykes
|
||||
|
||||
|
||||
Operating systems / CPU architectures
|
||||
=====================================
|
||||
|
||||
*BSD [2] Brad Smith
|
||||
Alpha [0]
|
||||
Alpha Falk Hueffner
|
||||
MIPS Manojkumar Bhosale, Shiyou Yin
|
||||
LoongArch [2] Shiyou Yin
|
||||
LoongArch Shiyou Yin
|
||||
Mac OS X / PowerPC Romain Dolbeau, Guillaume Poirier
|
||||
Amiga / PowerPC Colin Ward
|
||||
Linux / PowerPC Lauri Kasanen
|
||||
RISC-V [2] Rémi Denis-Courmont
|
||||
RISC-V Rémi Denis-Courmont
|
||||
Windows MinGW Alex Beregszaszi, Ramiro Polla
|
||||
Windows Cygwin Victor Paesa
|
||||
Windows MSVC Hendrik Leppkes
|
||||
Windows MSVC Matthew Oliver, Hendrik Leppkes
|
||||
Windows ICL Matthew Oliver
|
||||
ADI/Blackfin DSP Marc Hoffman
|
||||
Sparc Roman Shaposhnik
|
||||
OS/2 KO Myung-Hun
|
||||
@@ -533,7 +566,6 @@ Benjamin Larsson
|
||||
Bobby Bingham
|
||||
Daniel Verkamp
|
||||
Derek Buitenhuis
|
||||
Fei Wang
|
||||
Ganesh Ajjanagadde
|
||||
Henrik Gramner
|
||||
Ivan Uskov
|
||||
@@ -589,7 +621,6 @@ Jaikrishnan Menon 61A1 F09F 01C9 2D45 78E1 C862 25DC 8831 AF70 D368
|
||||
James Almer 7751 2E8C FD94 A169 57E6 9A7A 1463 01AD 7376 59E0
|
||||
Jean Delvare 7CA6 9F44 60F1 BDC4 1FD2 C858 A552 6B9B B3CD 4E6A
|
||||
Leo Izen (Traneptora) B6FD 3CFC 7ACF 83FC 9137 6945 5A71 C331 FD2F A19A
|
||||
Leo Izen (Traneptora) 1D83 0A0B CE46 709E 203B 26FC 764E 48EA 4822 1833
|
||||
Loren Merritt ABD9 08F4 C920 3F65 D8BE 35D7 1540 DAA7 060F 56DE
|
||||
Lynne FE50 139C 6805 72CA FD52 1F8D A2FE A5F0 3F03 4464
|
||||
Michael Niedermayer 9FF2 128B 147E F673 0BAD F133 611E C787 040B 0FAB
|
||||
|
||||
@@ -52,9 +52,6 @@ $(TOOLS): %$(EXESUF): %.o
|
||||
target_dec_%_fuzzer$(EXESUF): target_dec_%_fuzzer.o $(FF_DEP_LIBS)
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
|
||||
|
||||
target_enc_%_fuzzer$(EXESUF): target_enc_%_fuzzer.o $(FF_DEP_LIBS)
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
|
||||
|
||||
tools/target_bsf_%_fuzzer$(EXESUF): tools/target_bsf_%_fuzzer.o $(FF_DEP_LIBS)
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
|
||||
|
||||
@@ -67,11 +64,6 @@ tools/target_dem_fuzzer$(EXESUF): tools/target_dem_fuzzer.o $(FF_DEP_LIBS)
|
||||
tools/target_io_dem_fuzzer$(EXESUF): tools/target_io_dem_fuzzer.o $(FF_DEP_LIBS)
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
|
||||
|
||||
tools/target_sws_fuzzer$(EXESUF): tools/target_sws_fuzzer.o $(FF_DEP_LIBS)
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
|
||||
|
||||
tools/target_swr_fuzzer$(EXESUF): tools/target_swr_fuzzer.o $(FF_DEP_LIBS)
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
|
||||
|
||||
tools/enum_options$(EXESUF): ELIBS = $(FF_EXTRALIBS)
|
||||
tools/enum_options$(EXESUF): $(FF_DEP_LIBS)
|
||||
@@ -101,10 +93,10 @@ ffbuild/.config: $(CONFIGURABLE_COMPONENTS)
|
||||
SUBDIR_VARS := CLEANFILES FFLIBS HOSTPROGS TESTPROGS TOOLS \
|
||||
HEADERS ARCH_HEADERS BUILT_HEADERS SKIPHEADERS \
|
||||
ARMV5TE-OBJS ARMV6-OBJS ARMV8-OBJS VFP-OBJS NEON-OBJS \
|
||||
ALTIVEC-OBJS VSX-OBJS MMX-OBJS X86ASM-OBJS \
|
||||
ALTIVEC-OBJS VSX-OBJS RVV-OBJS MMX-OBJS X86ASM-OBJS \
|
||||
MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSP-OBJS MSA-OBJS \
|
||||
MMI-OBJS LSX-OBJS LASX-OBJS RV-OBJS RVV-OBJS RVVB-OBJS \
|
||||
OBJS SLIBOBJS SHLIBOBJS STLIBOBJS HOSTOBJS TESTOBJS
|
||||
MMI-OBJS LSX-OBJS LASX-OBJS OBJS SLIBOBJS SHLIBOBJS \
|
||||
STLIBOBJS HOSTOBJS TESTOBJS
|
||||
|
||||
define RESET
|
||||
$(1) :=
|
||||
@@ -141,18 +133,13 @@ endif
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(OBJS-$*) $(FF_EXTRALIBS)
|
||||
|
||||
VERSION_SH = $(SRC_PATH)/ffbuild/version.sh
|
||||
ifeq ($(VERSION_TRACKING),yes)
|
||||
GIT_LOG = $(SRC_PATH)/.git/logs/HEAD
|
||||
endif
|
||||
|
||||
.version: $(wildcard $(GIT_LOG)) $(VERSION_SH) ffbuild/config.mak
|
||||
.version: M=@
|
||||
|
||||
ifneq ($(VERSION_TRACKING),yes)
|
||||
libavutil/ffversion.h .version: REVISION=unknown
|
||||
endif
|
||||
libavutil/ffversion.h .version:
|
||||
$(M)revision=$(REVISION) $(VERSION_SH) $(SRC_PATH) libavutil/ffversion.h $(EXTRA_VERSION)
|
||||
$(M)$(VERSION_SH) $(SRC_PATH) libavutil/ffversion.h $(EXTRA_VERSION)
|
||||
$(Q)touch .version
|
||||
|
||||
# force version.sh to run whenever version might have changed
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
┌──────────────────────────────────────────┐
|
||||
│ RELEASE NOTES for FFmpeg 6.1 "Heaviside" │
|
||||
└──────────────────────────────────────────┘
|
||||
|
||||
The FFmpeg Project proudly presents FFmpeg 6.1 "Heaviside", about 8
|
||||
months after the release of FFmpeg 6.0.
|
||||
|
||||
A complete Changelog is available at the root of the project, and the
|
||||
complete Git history on https://git.ffmpeg.org/gitweb/ffmpeg.git
|
||||
|
||||
We hope you will like this release as much as we enjoyed working on it, and
|
||||
as usual, if you have any questions about it, or any FFmpeg related topic,
|
||||
feel free to join us on the #ffmpeg IRC channel (on irc.libera.chat) or ask
|
||||
on the mailing-lists.
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* based on vlc_atomic.h from VLC
|
||||
* Copyright (C) 2010 Rémi Denis-Courmont
|
||||
*/
|
||||
|
||||
#ifndef COMPAT_ATOMICS_GCC_STDATOMIC_H
|
||||
#define COMPAT_ATOMICS_GCC_STDATOMIC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define ATOMIC_FLAG_INIT 0
|
||||
|
||||
#define ATOMIC_VAR_INIT(value) (value)
|
||||
|
||||
#define atomic_init(obj, value) \
|
||||
do { \
|
||||
*(obj) = (value); \
|
||||
} while(0)
|
||||
|
||||
#define kill_dependency(y) ((void)0)
|
||||
|
||||
#define atomic_thread_fence(order) \
|
||||
__sync_synchronize()
|
||||
|
||||
#define atomic_signal_fence(order) \
|
||||
((void)0)
|
||||
|
||||
#define atomic_is_lock_free(obj) 0
|
||||
|
||||
typedef _Bool atomic_flag;
|
||||
typedef _Bool atomic_bool;
|
||||
typedef char atomic_char;
|
||||
typedef signed char atomic_schar;
|
||||
typedef unsigned char atomic_uchar;
|
||||
typedef short atomic_short;
|
||||
typedef unsigned short atomic_ushort;
|
||||
typedef int atomic_int;
|
||||
typedef unsigned int atomic_uint;
|
||||
typedef long atomic_long;
|
||||
typedef unsigned long atomic_ulong;
|
||||
typedef long long atomic_llong;
|
||||
typedef unsigned long long atomic_ullong;
|
||||
typedef wchar_t atomic_wchar_t;
|
||||
typedef int_least8_t atomic_int_least8_t;
|
||||
typedef uint_least8_t atomic_uint_least8_t;
|
||||
typedef int_least16_t atomic_int_least16_t;
|
||||
typedef uint_least16_t atomic_uint_least16_t;
|
||||
typedef int_least32_t atomic_int_least32_t;
|
||||
typedef uint_least32_t atomic_uint_least32_t;
|
||||
typedef int_least64_t atomic_int_least64_t;
|
||||
typedef uint_least64_t atomic_uint_least64_t;
|
||||
typedef int_fast8_t atomic_int_fast8_t;
|
||||
typedef uint_fast8_t atomic_uint_fast8_t;
|
||||
typedef int_fast16_t atomic_int_fast16_t;
|
||||
typedef uint_fast16_t atomic_uint_fast16_t;
|
||||
typedef int_fast32_t atomic_int_fast32_t;
|
||||
typedef uint_fast32_t atomic_uint_fast32_t;
|
||||
typedef int_fast64_t atomic_int_fast64_t;
|
||||
typedef uint_fast64_t atomic_uint_fast64_t;
|
||||
typedef intptr_t atomic_intptr_t;
|
||||
typedef uintptr_t atomic_uintptr_t;
|
||||
typedef size_t atomic_size_t;
|
||||
typedef ptrdiff_t atomic_ptrdiff_t;
|
||||
typedef intmax_t atomic_intmax_t;
|
||||
typedef uintmax_t atomic_uintmax_t;
|
||||
|
||||
#define atomic_store(object, desired) \
|
||||
do { \
|
||||
*(object) = (desired); \
|
||||
__sync_synchronize(); \
|
||||
} while (0)
|
||||
|
||||
#define atomic_store_explicit(object, desired, order) \
|
||||
atomic_store(object, desired)
|
||||
|
||||
#define atomic_load(object) \
|
||||
(__sync_synchronize(), *(object))
|
||||
|
||||
#define atomic_load_explicit(object, order) \
|
||||
atomic_load(object)
|
||||
|
||||
#define atomic_exchange(object, desired) \
|
||||
({ \
|
||||
__typeof__(object) _obj = (object); \
|
||||
__typeof__(*object) _old; \
|
||||
do \
|
||||
_old = atomic_load(_obj); \
|
||||
while (!__sync_bool_compare_and_swap(_obj, _old, (desired))); \
|
||||
_old; \
|
||||
})
|
||||
|
||||
#define atomic_exchange_explicit(object, desired, order) \
|
||||
atomic_exchange(object, desired)
|
||||
|
||||
#define atomic_compare_exchange_strong(object, expected, desired) \
|
||||
({ \
|
||||
__typeof__(object) _exp = (expected); \
|
||||
__typeof__(*object) _old = *_exp; \
|
||||
*_exp = __sync_val_compare_and_swap((object), _old, (desired)); \
|
||||
*_exp == _old; \
|
||||
})
|
||||
|
||||
#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
|
||||
atomic_compare_exchange_strong(object, expected, desired)
|
||||
|
||||
#define atomic_compare_exchange_weak(object, expected, desired) \
|
||||
atomic_compare_exchange_strong(object, expected, desired)
|
||||
|
||||
#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
|
||||
atomic_compare_exchange_weak(object, expected, desired)
|
||||
|
||||
#define atomic_fetch_add(object, operand) \
|
||||
__sync_fetch_and_add(object, operand)
|
||||
|
||||
#define atomic_fetch_add_explicit(object, operand, order) \
|
||||
atomic_fetch_add(object, operand)
|
||||
|
||||
#define atomic_fetch_sub(object, operand) \
|
||||
__sync_fetch_and_sub(object, operand)
|
||||
|
||||
#define atomic_fetch_sub_explicit(object, operand, order) \
|
||||
atomic_fetch_sub(object, operand)
|
||||
|
||||
#define atomic_fetch_or(object, operand) \
|
||||
__sync_fetch_and_or(object, operand)
|
||||
|
||||
#define atomic_fetch_or_explicit(object, operand, order) \
|
||||
atomic_fetch_or(object, operand)
|
||||
|
||||
#define atomic_fetch_xor(object, operand) \
|
||||
__sync_fetch_and_xor(object, operand)
|
||||
|
||||
#define atomic_fetch_xor_explicit(object, operand, order) \
|
||||
atomic_fetch_xor(object, operand)
|
||||
|
||||
#define atomic_fetch_and(object, operand) \
|
||||
__sync_fetch_and_and(object, operand)
|
||||
|
||||
#define atomic_fetch_and_explicit(object, operand, order) \
|
||||
atomic_fetch_and(object, operand)
|
||||
|
||||
#define atomic_flag_test_and_set(object) \
|
||||
atomic_exchange(object, 1)
|
||||
|
||||
#define atomic_flag_test_and_set_explicit(object, order) \
|
||||
atomic_flag_test_and_set(object)
|
||||
|
||||
#define atomic_flag_clear(object) \
|
||||
atomic_store(object, 0)
|
||||
|
||||
#define atomic_flag_clear_explicit(object, order) \
|
||||
atomic_flag_clear(object)
|
||||
|
||||
#endif /* COMPAT_ATOMICS_GCC_STDATOMIC_H */
|
||||
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
* Copyright © 2024 Rémi Denis-Courmont.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
@@ -18,16 +16,24 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "libavutil/cpu.h"
|
||||
/*
|
||||
* based on vlc_atomic.h from VLC
|
||||
* Copyright (C) 2010 Rémi Denis-Courmont
|
||||
*/
|
||||
|
||||
#ifndef __riscv_zbb
|
||||
unsigned char ff_rv_zbb_supported = 0;
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __ELF__
|
||||
__attribute__((constructor))
|
||||
static void probe_zbb(void)
|
||||
#include "stdatomic.h"
|
||||
|
||||
static pthread_mutex_t atomic_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void avpriv_atomic_lock(void)
|
||||
{
|
||||
ff_rv_zbb_supported = (av_get_cpu_flags() & AV_CPU_FLAG_RVB_BASIC) != 0;
|
||||
pthread_mutex_lock(&atomic_lock);
|
||||
}
|
||||
|
||||
void avpriv_atomic_unlock(void)
|
||||
{
|
||||
pthread_mutex_unlock(&atomic_lock);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* based on vlc_atomic.h from VLC
|
||||
* Copyright (C) 2010 Rémi Denis-Courmont
|
||||
*/
|
||||
|
||||
#ifndef COMPAT_ATOMICS_PTHREAD_STDATOMIC_H
|
||||
#define COMPAT_ATOMICS_PTHREAD_STDATOMIC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ATOMIC_FLAG_INIT 0
|
||||
|
||||
#define ATOMIC_VAR_INIT(value) (value)
|
||||
|
||||
#define atomic_init(obj, value) \
|
||||
do { \
|
||||
*(obj) = (value); \
|
||||
} while(0)
|
||||
|
||||
#define kill_dependency(y) ((void)0)
|
||||
|
||||
#define atomic_signal_fence(order) \
|
||||
((void)0)
|
||||
|
||||
#define atomic_is_lock_free(obj) 0
|
||||
|
||||
typedef intptr_t atomic_flag;
|
||||
typedef intptr_t atomic_bool;
|
||||
typedef intptr_t atomic_char;
|
||||
typedef intptr_t atomic_schar;
|
||||
typedef intptr_t atomic_uchar;
|
||||
typedef intptr_t atomic_short;
|
||||
typedef intptr_t atomic_ushort;
|
||||
typedef intptr_t atomic_int;
|
||||
typedef intptr_t atomic_uint;
|
||||
typedef intptr_t atomic_long;
|
||||
typedef intptr_t atomic_ulong;
|
||||
typedef intptr_t atomic_llong;
|
||||
typedef intptr_t atomic_ullong;
|
||||
typedef intptr_t atomic_wchar_t;
|
||||
typedef intptr_t atomic_int_least8_t;
|
||||
typedef intptr_t atomic_uint_least8_t;
|
||||
typedef intptr_t atomic_int_least16_t;
|
||||
typedef intptr_t atomic_uint_least16_t;
|
||||
typedef intptr_t atomic_int_least32_t;
|
||||
typedef intptr_t atomic_uint_least32_t;
|
||||
typedef intptr_t atomic_int_least64_t;
|
||||
typedef intptr_t atomic_uint_least64_t;
|
||||
typedef intptr_t atomic_int_fast8_t;
|
||||
typedef intptr_t atomic_uint_fast8_t;
|
||||
typedef intptr_t atomic_int_fast16_t;
|
||||
typedef intptr_t atomic_uint_fast16_t;
|
||||
typedef intptr_t atomic_int_fast32_t;
|
||||
typedef intptr_t atomic_uint_fast32_t;
|
||||
typedef intptr_t atomic_int_fast64_t;
|
||||
typedef intptr_t atomic_uint_fast64_t;
|
||||
typedef intptr_t atomic_intptr_t;
|
||||
typedef intptr_t atomic_uintptr_t;
|
||||
typedef intptr_t atomic_size_t;
|
||||
typedef intptr_t atomic_ptrdiff_t;
|
||||
typedef intptr_t atomic_intmax_t;
|
||||
typedef intptr_t atomic_uintmax_t;
|
||||
|
||||
void avpriv_atomic_lock(void);
|
||||
void avpriv_atomic_unlock(void);
|
||||
|
||||
static inline void atomic_thread_fence(int order)
|
||||
{
|
||||
avpriv_atomic_lock();
|
||||
avpriv_atomic_unlock();
|
||||
}
|
||||
|
||||
static inline void atomic_store(intptr_t *object, intptr_t desired)
|
||||
{
|
||||
avpriv_atomic_lock();
|
||||
*object = desired;
|
||||
avpriv_atomic_unlock();
|
||||
}
|
||||
|
||||
#define atomic_store_explicit(object, desired, order) \
|
||||
atomic_store(object, desired)
|
||||
|
||||
static inline intptr_t atomic_load(intptr_t *object)
|
||||
{
|
||||
intptr_t ret;
|
||||
avpriv_atomic_lock();
|
||||
ret = *object;
|
||||
avpriv_atomic_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define atomic_load_explicit(object, order) \
|
||||
atomic_load(object)
|
||||
|
||||
static inline intptr_t atomic_exchange(intptr_t *object, intptr_t desired)
|
||||
{
|
||||
intptr_t ret;
|
||||
avpriv_atomic_lock();
|
||||
ret = *object;
|
||||
*object = desired;
|
||||
avpriv_atomic_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define atomic_exchange_explicit(object, desired, order) \
|
||||
atomic_exchange(object, desired)
|
||||
|
||||
static inline int atomic_compare_exchange_strong(intptr_t *object, intptr_t *expected,
|
||||
intptr_t desired)
|
||||
{
|
||||
int ret;
|
||||
avpriv_atomic_lock();
|
||||
if (*object == *expected) {
|
||||
ret = 1;
|
||||
*object = desired;
|
||||
} else {
|
||||
ret = 0;
|
||||
*expected = *object;
|
||||
}
|
||||
avpriv_atomic_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
|
||||
atomic_compare_exchange_strong(object, expected, desired)
|
||||
|
||||
#define atomic_compare_exchange_weak(object, expected, desired) \
|
||||
atomic_compare_exchange_strong(object, expected, desired)
|
||||
|
||||
#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
|
||||
atomic_compare_exchange_weak(object, expected, desired)
|
||||
|
||||
#define FETCH_MODIFY(opname, op) \
|
||||
static inline intptr_t atomic_fetch_ ## opname(intptr_t *object, intptr_t operand) \
|
||||
{ \
|
||||
intptr_t ret; \
|
||||
avpriv_atomic_lock(); \
|
||||
ret = *object; \
|
||||
*object = *object op operand; \
|
||||
avpriv_atomic_unlock(); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
FETCH_MODIFY(add, +)
|
||||
FETCH_MODIFY(sub, -)
|
||||
FETCH_MODIFY(or, |)
|
||||
FETCH_MODIFY(xor, ^)
|
||||
FETCH_MODIFY(and, &)
|
||||
|
||||
#undef FETCH_MODIFY
|
||||
|
||||
#define atomic_fetch_add_explicit(object, operand, order) \
|
||||
atomic_fetch_add(object, operand)
|
||||
|
||||
#define atomic_fetch_sub_explicit(object, operand, order) \
|
||||
atomic_fetch_sub(object, operand)
|
||||
|
||||
#define atomic_fetch_or_explicit(object, operand, order) \
|
||||
atomic_fetch_or(object, operand)
|
||||
|
||||
#define atomic_fetch_xor_explicit(object, operand, order) \
|
||||
atomic_fetch_xor(object, operand)
|
||||
|
||||
#define atomic_fetch_and_explicit(object, operand, order) \
|
||||
atomic_fetch_and(object, operand)
|
||||
|
||||
#define atomic_flag_test_and_set(object) \
|
||||
atomic_exchange(object, 1)
|
||||
|
||||
#define atomic_flag_test_and_set_explicit(object, order) \
|
||||
atomic_flag_test_and_set(object)
|
||||
|
||||
#define atomic_flag_clear(object) \
|
||||
atomic_store(object, 0)
|
||||
|
||||
#define atomic_flag_clear_explicit(object, order) \
|
||||
atomic_flag_clear(object)
|
||||
|
||||
#endif /* COMPAT_ATOMICS_PTHREAD_STDATOMIC_H */
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef COMPAT_ATOMICS_SUNCC_STDATOMIC_H
|
||||
#define COMPAT_ATOMICS_SUNCC_STDATOMIC_H
|
||||
|
||||
#include <atomic.h>
|
||||
#include <mbarrier.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define ATOMIC_FLAG_INIT 0
|
||||
|
||||
#define ATOMIC_VAR_INIT(value) (value)
|
||||
|
||||
#define atomic_init(obj, value) \
|
||||
do { \
|
||||
*(obj) = (value); \
|
||||
} while(0)
|
||||
|
||||
#define kill_dependency(y) ((void)0)
|
||||
|
||||
#define atomic_thread_fence(order) \
|
||||
__machine_rw_barrier();
|
||||
|
||||
#define atomic_signal_fence(order) \
|
||||
((void)0)
|
||||
|
||||
#define atomic_is_lock_free(obj) 0
|
||||
|
||||
typedef intptr_t atomic_flag;
|
||||
typedef intptr_t atomic_bool;
|
||||
typedef intptr_t atomic_char;
|
||||
typedef intptr_t atomic_schar;
|
||||
typedef intptr_t atomic_uchar;
|
||||
typedef intptr_t atomic_short;
|
||||
typedef intptr_t atomic_ushort;
|
||||
typedef intptr_t atomic_int;
|
||||
typedef intptr_t atomic_uint;
|
||||
typedef intptr_t atomic_long;
|
||||
typedef intptr_t atomic_ulong;
|
||||
typedef intptr_t atomic_llong;
|
||||
typedef intptr_t atomic_ullong;
|
||||
typedef intptr_t atomic_wchar_t;
|
||||
typedef intptr_t atomic_int_least8_t;
|
||||
typedef intptr_t atomic_uint_least8_t;
|
||||
typedef intptr_t atomic_int_least16_t;
|
||||
typedef intptr_t atomic_uint_least16_t;
|
||||
typedef intptr_t atomic_int_least32_t;
|
||||
typedef intptr_t atomic_uint_least32_t;
|
||||
typedef intptr_t atomic_int_least64_t;
|
||||
typedef intptr_t atomic_uint_least64_t;
|
||||
typedef intptr_t atomic_int_fast8_t;
|
||||
typedef intptr_t atomic_uint_fast8_t;
|
||||
typedef intptr_t atomic_int_fast16_t;
|
||||
typedef intptr_t atomic_uint_fast16_t;
|
||||
typedef intptr_t atomic_int_fast32_t;
|
||||
typedef intptr_t atomic_uint_fast32_t;
|
||||
typedef intptr_t atomic_int_fast64_t;
|
||||
typedef intptr_t atomic_uint_fast64_t;
|
||||
typedef intptr_t atomic_intptr_t;
|
||||
typedef intptr_t atomic_uintptr_t;
|
||||
typedef intptr_t atomic_size_t;
|
||||
typedef intptr_t atomic_ptrdiff_t;
|
||||
typedef intptr_t atomic_intmax_t;
|
||||
typedef intptr_t atomic_uintmax_t;
|
||||
|
||||
static inline void atomic_store(intptr_t *object, intptr_t desired)
|
||||
{
|
||||
*object = desired;
|
||||
__machine_rw_barrier();
|
||||
}
|
||||
|
||||
#define atomic_store_explicit(object, desired, order) \
|
||||
atomic_store(object, desired)
|
||||
|
||||
static inline intptr_t atomic_load(intptr_t *object)
|
||||
{
|
||||
__machine_rw_barrier();
|
||||
return *object;
|
||||
}
|
||||
|
||||
#define atomic_load_explicit(object, order) \
|
||||
atomic_load(object)
|
||||
|
||||
#define atomic_exchange(object, desired) \
|
||||
atomic_swap_ptr(object, desired)
|
||||
|
||||
#define atomic_exchange_explicit(object, desired, order) \
|
||||
atomic_exchange(object, desired)
|
||||
|
||||
static inline int atomic_compare_exchange_strong(intptr_t *object, intptr_t *expected,
|
||||
intptr_t desired)
|
||||
{
|
||||
intptr_t old = *expected;
|
||||
*expected = (intptr_t)atomic_cas_ptr(object, (void *)old, (void *)desired);
|
||||
return *expected == old;
|
||||
}
|
||||
|
||||
#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
|
||||
atomic_compare_exchange_strong(object, expected, desired)
|
||||
|
||||
#define atomic_compare_exchange_weak(object, expected, desired) \
|
||||
atomic_compare_exchange_strong(object, expected, desired)
|
||||
|
||||
#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
|
||||
atomic_compare_exchange_weak(object, expected, desired)
|
||||
|
||||
static inline intptr_t atomic_fetch_add(intptr_t *object, intptr_t operand)
|
||||
{
|
||||
return atomic_add_ptr_nv(object, operand) - operand;
|
||||
}
|
||||
|
||||
#define atomic_fetch_sub(object, operand) \
|
||||
atomic_fetch_add(object, -(operand))
|
||||
|
||||
static inline intptr_t atomic_fetch_or(intptr_t *object, intptr_t operand)
|
||||
{
|
||||
intptr_t old;
|
||||
do {
|
||||
old = atomic_load(object);
|
||||
} while (!atomic_compare_exchange_strong(object, old, old | operand));
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline intptr_t atomic_fetch_xor(intptr_t *object, intptr_t operand)
|
||||
{
|
||||
intptr_t old;
|
||||
do {
|
||||
old = atomic_load(object);
|
||||
} while (!atomic_compare_exchange_strong(object, old, old ^ operand));
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline intptr_t atomic_fetch_and(intptr_t *object, intptr_t operand)
|
||||
{
|
||||
intptr_t old;
|
||||
do {
|
||||
old = atomic_load(object);
|
||||
} while (!atomic_compare_exchange_strong(object, old, old & operand));
|
||||
return old;
|
||||
}
|
||||
|
||||
#define atomic_fetch_add_explicit(object, operand, order) \
|
||||
atomic_fetch_add(object, operand)
|
||||
|
||||
#define atomic_fetch_sub_explicit(object, operand, order) \
|
||||
atomic_fetch_sub(object, operand)
|
||||
|
||||
#define atomic_fetch_or_explicit(object, operand, order) \
|
||||
atomic_fetch_or(object, operand)
|
||||
|
||||
#define atomic_fetch_xor_explicit(object, operand, order) \
|
||||
atomic_fetch_xor(object, operand)
|
||||
|
||||
#define atomic_fetch_and_explicit(object, operand, order) \
|
||||
atomic_fetch_and(object, operand)
|
||||
|
||||
#define atomic_flag_test_and_set(object) \
|
||||
atomic_exchange(object, 1)
|
||||
|
||||
#define atomic_flag_test_and_set_explicit(object, order) \
|
||||
atomic_flag_test_and_set(object)
|
||||
|
||||
#define atomic_flag_clear(object) \
|
||||
atomic_store(object, 0)
|
||||
|
||||
#define atomic_flag_clear_explicit(object, order) \
|
||||
atomic_flag_clear(object)
|
||||
|
||||
#endif /* COMPAT_ATOMICS_SUNCC_STDATOMIC_H */
|
||||
@@ -1,599 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Rémi Denis-Courmont
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __STDC_VERSION_STDBIT_H__
|
||||
#define __STDC_VERSION_STDBIT_H__ 202311L
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <limits.h> /* CHAR_BIT */
|
||||
|
||||
#define __STDC_ENDIAN_LITTLE__ 1234
|
||||
#define __STDC_ENDIAN_BIG__ 4321
|
||||
|
||||
#ifdef __BYTE_ORDER__
|
||||
# if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
# define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_LITTLE__
|
||||
# elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
# define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_BIG__
|
||||
# else
|
||||
# define __STDC_ENDIAN_NATIVE__ 3412
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_LITTLE__
|
||||
#else
|
||||
# error Not implemented.
|
||||
#endif
|
||||
|
||||
#define __stdbit_generic_type_func(func, value) \
|
||||
_Generic (value, \
|
||||
unsigned long long: stdc_##func##_ull((unsigned long long)(value)), \
|
||||
unsigned long: stdc_##func##_ul((unsigned long)(value)), \
|
||||
unsigned int: stdc_##func##_ui((unsigned int)(value)), \
|
||||
unsigned short: stdc_##func##_us((unsigned short)(value)), \
|
||||
unsigned char: stdc_##func##_uc((unsigned char)(value)))
|
||||
|
||||
#if defined (__GNUC__) || defined (__clang__)
|
||||
static inline unsigned int stdc_leading_zeros_ull(unsigned long long value)
|
||||
{
|
||||
return value ? __builtin_clzll(value) : (CHAR_BIT * sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_zeros_ul(unsigned long value)
|
||||
{
|
||||
return value ? __builtin_clzl(value) : (CHAR_BIT * sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_zeros_ui(unsigned int value)
|
||||
{
|
||||
return value ? __builtin_clz(value) : (CHAR_BIT * sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_zeros_us(unsigned short value)
|
||||
{
|
||||
return stdc_leading_zeros_ui(value)
|
||||
- CHAR_BIT * (sizeof (int) - sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_zeros_uc(unsigned char value)
|
||||
{
|
||||
return stdc_leading_zeros_ui(value) - (CHAR_BIT * (sizeof (int) - 1));
|
||||
}
|
||||
#else
|
||||
static inline unsigned int __stdc_leading_zeros(unsigned long long value,
|
||||
unsigned int size)
|
||||
{
|
||||
unsigned int zeros = size * CHAR_BIT;
|
||||
|
||||
while (value != 0) {
|
||||
value >>= 1;
|
||||
zeros--;
|
||||
}
|
||||
|
||||
return zeros;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_zeros_ull(unsigned long long value)
|
||||
{
|
||||
return __stdc_leading_zeros(value, sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_zeros_ul(unsigned long value)
|
||||
{
|
||||
return __stdc_leading_zeros(value, sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_zeros_ui(unsigned int value)
|
||||
{
|
||||
return __stdc_leading_zeros(value, sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_zeros_us(unsigned short value)
|
||||
{
|
||||
return __stdc_leading_zeros(value, sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_zeros_uc(unsigned char value)
|
||||
{
|
||||
return __stdc_leading_zeros(value, sizeof (value));
|
||||
}
|
||||
#endif
|
||||
|
||||
#define stdc_leading_zeros(value) \
|
||||
__stdbit_generic_type_func(leading_zeros, value)
|
||||
|
||||
static inline unsigned int stdc_leading_ones_ull(unsigned long long value)
|
||||
{
|
||||
return stdc_leading_zeros_ull(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_ones_ul(unsigned long value)
|
||||
{
|
||||
return stdc_leading_zeros_ul(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_ones_ui(unsigned int value)
|
||||
{
|
||||
return stdc_leading_zeros_ui(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_ones_us(unsigned short value)
|
||||
{
|
||||
return stdc_leading_zeros_us(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_leading_ones_uc(unsigned char value)
|
||||
{
|
||||
return stdc_leading_zeros_uc(~value);
|
||||
}
|
||||
|
||||
#define stdc_leading_ones(value) \
|
||||
__stdbit_generic_type_func(leading_ones, value)
|
||||
|
||||
#if defined (__GNUC__) || defined (__clang__)
|
||||
static inline unsigned int stdc_trailing_zeros_ull(unsigned long long value)
|
||||
{
|
||||
return value ? (unsigned int)__builtin_ctzll(value)
|
||||
: (CHAR_BIT * sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_zeros_ul(unsigned long value)
|
||||
{
|
||||
return value ? (unsigned int)__builtin_ctzl(value)
|
||||
: (CHAR_BIT * sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_zeros_ui(unsigned int value)
|
||||
{
|
||||
return value ? (unsigned int)__builtin_ctz(value)
|
||||
: (CHAR_BIT * sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_zeros_us(unsigned short value)
|
||||
{
|
||||
return value ? (unsigned int)__builtin_ctz(value)
|
||||
: (CHAR_BIT * sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_zeros_uc(unsigned char value)
|
||||
{
|
||||
return value ? (unsigned int)__builtin_ctz(value)
|
||||
: (CHAR_BIT * sizeof (value));
|
||||
}
|
||||
#else
|
||||
static inline unsigned int __stdc_trailing_zeros(unsigned long long value,
|
||||
unsigned int size)
|
||||
{
|
||||
unsigned int zeros = 0;
|
||||
|
||||
if (!value)
|
||||
return size * CHAR_BIT;
|
||||
|
||||
while ((value & 1) == 0) {
|
||||
value >>= 1;
|
||||
zeros++;
|
||||
}
|
||||
|
||||
return zeros;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_zeros_ull(unsigned long long value)
|
||||
{
|
||||
return __stdc_trailing_zeros(value, sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_zeros_ul(unsigned long value)
|
||||
{
|
||||
return __stdc_trailing_zeros(value, sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_zeros_ui(unsigned int value)
|
||||
{
|
||||
return __stdc_trailing_zeros(value, sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_zeros_us(unsigned short value)
|
||||
{
|
||||
return __stdc_trailing_zeros(value, sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_zeros_uc(unsigned char value)
|
||||
{
|
||||
return __stdc_trailing_zeros(value, sizeof (value));
|
||||
}
|
||||
#endif
|
||||
|
||||
#define stdc_trailing_zeros(value) \
|
||||
__stdbit_generic_type_func(trailing_zeros, value)
|
||||
|
||||
static inline unsigned int stdc_trailing_ones_ull(unsigned long long value)
|
||||
{
|
||||
return stdc_trailing_zeros_ull(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_ones_ul(unsigned long value)
|
||||
{
|
||||
return stdc_trailing_zeros_ul(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_ones_ui(unsigned int value)
|
||||
{
|
||||
return stdc_trailing_zeros_ui(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_ones_us(unsigned short value)
|
||||
{
|
||||
return stdc_trailing_zeros_us(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_trailing_ones_uc(unsigned char value)
|
||||
{
|
||||
return stdc_trailing_zeros_uc(~value);
|
||||
}
|
||||
|
||||
#define stdc_trailing_ones(value) \
|
||||
__stdbit_generic_type_func(trailing_ones, value)
|
||||
|
||||
static inline unsigned int stdc_first_leading_one_ull(unsigned long long value)
|
||||
{
|
||||
return value ? (stdc_leading_zeros_ull(value) + 1) : 0;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_leading_one_ul(unsigned long value)
|
||||
{
|
||||
return value ? (stdc_leading_zeros_ul(value) + 1) : 0;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_leading_one_ui(unsigned int value)
|
||||
{
|
||||
return value ? (stdc_leading_zeros_ui(value) + 1) : 0;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_leading_one_us(unsigned short value)
|
||||
{
|
||||
return value ? (stdc_leading_zeros_us(value) + 1) : 0;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_leading_one_uc(unsigned char value)
|
||||
{
|
||||
return value ? (stdc_leading_zeros_uc(value) + 1) : 0;
|
||||
}
|
||||
|
||||
#define stdc_first_leading_one(value) \
|
||||
__stdbit_generic_type_func(first_leading_one, value)
|
||||
|
||||
static inline unsigned int stdc_first_leading_zero_ull(unsigned long long value)
|
||||
{
|
||||
return stdc_leading_ones_ull(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_leading_zero_ul(unsigned long value)
|
||||
{
|
||||
return stdc_leading_ones_ul(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_leading_zero_ui(unsigned int value)
|
||||
{
|
||||
return stdc_leading_ones_ui(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_leading_zero_us(unsigned short value)
|
||||
{
|
||||
return stdc_leading_ones_us(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_leading_zero_uc(unsigned char value)
|
||||
{
|
||||
return stdc_leading_ones_uc(~value);
|
||||
}
|
||||
|
||||
#define stdc_first_leading_zero(value) \
|
||||
__stdbit_generic_type_func(first_leading_zero, value)
|
||||
|
||||
#if defined (__GNUC__) || defined (__clang__)
|
||||
static inline unsigned int stdc_first_trailing_one_ull(unsigned long long value)
|
||||
{
|
||||
return __builtin_ffsll(value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_trailing_one_ul(unsigned long value)
|
||||
{
|
||||
return __builtin_ffsl(value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_trailing_one_ui(unsigned int value)
|
||||
{
|
||||
return __builtin_ffs(value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_trailing_one_us(unsigned short value)
|
||||
{
|
||||
return __builtin_ffs(value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_trailing_one_uc(unsigned char value)
|
||||
{
|
||||
return __builtin_ffs(value);
|
||||
}
|
||||
#else
|
||||
static inline unsigned int stdc_first_trailing_one_ull(unsigned long long value)
|
||||
{
|
||||
return value ? (1 + stdc_trailing_zeros_ull(value)) : 0;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_trailing_one_ul(unsigned long value)
|
||||
{
|
||||
return value ? (1 + stdc_trailing_zeros_ul(value)) : 0;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_trailing_one_ui(unsigned int value)
|
||||
{
|
||||
return value ? (1 + stdc_trailing_zeros_ui(value)) : 0;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_trailing_one_us(unsigned short value)
|
||||
{
|
||||
return value ? (1 + stdc_trailing_zeros_us(value)) : 0;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_trailing_one_uc(unsigned char value)
|
||||
{
|
||||
return value ? (1 + stdc_trailing_zeros_uc(value)) : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define stdc_first_trailing_one(value) \
|
||||
__stdbit_generic_type_func(first_trailing_one, value)
|
||||
|
||||
static inline unsigned int stdc_first_trailing_zero_ull(unsigned long long value)
|
||||
{
|
||||
return stdc_first_trailing_one_ull(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_trailing_zero_ul(unsigned long value)
|
||||
{
|
||||
return stdc_first_trailing_one_ul(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_trailing_zero_ui(unsigned int value)
|
||||
{
|
||||
return stdc_first_trailing_one_ui(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_trailing_zero_us(unsigned short value)
|
||||
{
|
||||
return stdc_first_trailing_one_us(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_first_trailing_zero_uc(unsigned char value)
|
||||
{
|
||||
return stdc_first_trailing_one_uc(~value);
|
||||
}
|
||||
|
||||
#define stdc_first_trailing_zero(value) \
|
||||
__stdbit_generic_type_func(first_trailing_zero, value)
|
||||
|
||||
#if defined (__GNUC__) || defined (__clang__)
|
||||
static inline unsigned int stdc_count_ones_ull(unsigned long long value)
|
||||
{
|
||||
return __builtin_popcountll(value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_ones_ul(unsigned long value)
|
||||
{
|
||||
return __builtin_popcountl(value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_ones_ui(unsigned int value)
|
||||
{
|
||||
return __builtin_popcount(value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_ones_us(unsigned short value)
|
||||
{
|
||||
return __builtin_popcount(value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_ones_uc(unsigned char value)
|
||||
{
|
||||
return __builtin_popcount(value);
|
||||
}
|
||||
#else
|
||||
static inline unsigned int __stdc_count_ones(unsigned long long value,
|
||||
unsigned int size)
|
||||
{
|
||||
unsigned int ones = 0;
|
||||
|
||||
for (unsigned int c = 0; c < (size * CHAR_BIT); c++) {
|
||||
ones += value & 1;
|
||||
value >>= 1;
|
||||
}
|
||||
|
||||
return ones;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_ones_ull(unsigned long long value)
|
||||
{
|
||||
return __stdc_count_ones(value, sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_ones_ul(unsigned long value)
|
||||
{
|
||||
return __stdc_count_ones(value, sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_ones_ui(unsigned int value)
|
||||
{
|
||||
return __stdc_count_ones(value, sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_ones_us(unsigned short value)
|
||||
{
|
||||
return __stdc_count_ones(value, sizeof (value));
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_ones_uc(unsigned char value)
|
||||
{
|
||||
return __stdc_count_ones(value, sizeof (value));
|
||||
}
|
||||
#endif
|
||||
|
||||
#define stdc_count_ones(value) \
|
||||
__stdbit_generic_type_func(count_ones, value)
|
||||
|
||||
static inline unsigned int stdc_count_zeros_ull(unsigned long long value)
|
||||
{
|
||||
return stdc_count_ones_ull(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_zeros_ul(unsigned long value)
|
||||
{
|
||||
return stdc_count_ones_ul(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_zeros_ui(unsigned int value)
|
||||
{
|
||||
return stdc_count_ones_ui(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_zeros_us(unsigned short value)
|
||||
{
|
||||
return stdc_count_ones_us(~value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_count_zeros_uc(unsigned char value)
|
||||
{
|
||||
return stdc_count_ones_uc(~value);
|
||||
}
|
||||
|
||||
#define stdc_count_zeros(value) \
|
||||
__stdbit_generic_type_func(count_zeros, value)
|
||||
|
||||
static inline bool stdc_has_single_bit_ull(unsigned long long value)
|
||||
{
|
||||
return value && (value & (value - 1)) == 0;
|
||||
}
|
||||
|
||||
static inline bool stdc_has_single_bit_ul(unsigned long value)
|
||||
{
|
||||
return value && (value & (value - 1)) == 0;
|
||||
}
|
||||
|
||||
static inline bool stdc_has_single_bit_ui(unsigned int value)
|
||||
{
|
||||
return value && (value & (value - 1)) == 0;
|
||||
}
|
||||
|
||||
static inline bool stdc_has_single_bit_us(unsigned short value)
|
||||
{
|
||||
return value && (value & (value - 1)) == 0;
|
||||
}
|
||||
|
||||
static inline bool stdc_has_single_bit_uc(unsigned char value)
|
||||
{
|
||||
return value && (value & (value - 1)) == 0;
|
||||
}
|
||||
|
||||
#define stdc_has_single_bit(value) \
|
||||
__stdbit_generic_type_func(has_single_bit, value)
|
||||
|
||||
static inline unsigned int stdc_bit_width_ull(unsigned long long value)
|
||||
{
|
||||
return (CHAR_BIT * sizeof (value)) - stdc_leading_zeros_ull(value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_bit_width_ul(unsigned long value)
|
||||
{
|
||||
return (CHAR_BIT * sizeof (value)) - stdc_leading_zeros_ul(value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_bit_width_ui(unsigned int value)
|
||||
{
|
||||
return (CHAR_BIT * sizeof (value)) - stdc_leading_zeros_ui(value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_bit_width_us(unsigned short value)
|
||||
{
|
||||
return (CHAR_BIT * sizeof (value)) - stdc_leading_zeros_us(value);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_bit_width_uc(unsigned char value)
|
||||
{
|
||||
return (CHAR_BIT * sizeof (value)) - stdc_leading_zeros_uc(value);
|
||||
}
|
||||
|
||||
#define stdc_bit_width(value) \
|
||||
__stdbit_generic_type_func(bit_width, value)
|
||||
|
||||
static inline unsigned long long stdc_bit_floor_ull(unsigned long long value)
|
||||
{
|
||||
return value ? (1ULL << (stdc_bit_width_ull(value) - 1)) : 0ULL;
|
||||
}
|
||||
|
||||
static inline unsigned long stdc_bit_floor_ul(unsigned long value)
|
||||
{
|
||||
return value ? (1UL << (stdc_bit_width_ul(value) - 1)) : 0UL;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_bit_floor_ui(unsigned int value)
|
||||
{
|
||||
return value ? (1U << (stdc_bit_width_ui(value) - 1)) : 0U;
|
||||
}
|
||||
|
||||
static inline unsigned short stdc_bit_floor_us(unsigned short value)
|
||||
{
|
||||
return value ? (1U << (stdc_bit_width_us(value) - 1)) : 0U;
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_bit_floor_uc(unsigned char value)
|
||||
{
|
||||
return value ? (1U << (stdc_bit_width_uc(value) - 1)) : 0U;
|
||||
}
|
||||
|
||||
#define stdc_bit_floor(value) \
|
||||
__stdbit_generic_type_func(bit_floor, value)
|
||||
|
||||
/* NOTE: Bit ceiling undefines overflow. */
|
||||
static inline unsigned long long stdc_bit_ceil_ull(unsigned long long value)
|
||||
{
|
||||
return 1ULL << (value ? stdc_bit_width_ull(value - 1) : 0);
|
||||
}
|
||||
|
||||
static inline unsigned long stdc_bit_ceil_ul(unsigned long value)
|
||||
{
|
||||
return 1UL << (value ? stdc_bit_width_ul(value - 1) : 0);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_bit_ceil_ui(unsigned int value)
|
||||
{
|
||||
return 1U << (value ? stdc_bit_width_ui(value - 1) : 0);
|
||||
}
|
||||
|
||||
static inline unsigned short stdc_bit_ceil_us(unsigned short value)
|
||||
{
|
||||
return 1U << (value ? stdc_bit_width_us(value - 1) : 0);
|
||||
}
|
||||
|
||||
static inline unsigned int stdc_bit_ceil_uc(unsigned char value)
|
||||
{
|
||||
return 1U << (value ? stdc_bit_width_uc(value - 1) : 0);
|
||||
}
|
||||
|
||||
#define stdc_bit_ceil(value) \
|
||||
__stdbit_generic_type_func(bit_ceil, value)
|
||||
|
||||
#endif /* __STDC_VERSION_STDBIT_H__ */
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "libavutil/macros.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/wchar_filename.h"
|
||||
|
||||
static inline wchar_t *get_module_filename(HMODULE module)
|
||||
|
||||
+1
-285
@@ -1,291 +1,7 @@
|
||||
The last version increases of all libraries were on 2024-03-07
|
||||
The last version increases of all libraries were on 2023-02-09
|
||||
|
||||
API changes, most recent first:
|
||||
|
||||
2024-09-23 - 6940a6de2f0 - lavu 59.38.100 - frame.h
|
||||
Add AV_FRAME_DATA_VIEW_ID.
|
||||
|
||||
2024-09-23 - 6147385393a - lavc 61.18.100 - avcodec.h
|
||||
Add a new flag AV_CODEC_EXPORT_DATA_ENHANCEMENTS for export_side_data.
|
||||
|
||||
2024-09-18 - df609af8e44 - lavc 61.17.100 - packet.h
|
||||
Add AV_PKT_DATA_LCEVC.
|
||||
|
||||
2024-09-18 - ba0ef0860f0 - lavf 61.5.100 - avformat.h
|
||||
Add AVStreamGroupLCEVC
|
||||
Add AV_STREAM_GROUP_PARAMS_LCEVC
|
||||
Add AVStreamGroup.params.lcevc
|
||||
|
||||
2024-09-18 - 58963182294 - lavc 61.16.100 - avcodec.h
|
||||
Add AV_CODEC_ID_LCEVC.
|
||||
|
||||
2024-09-18 - 90d12c24c51 - lavu 59.37.100 - frame.h
|
||||
Add AV_FRAME_DATA_LCEVC.
|
||||
|
||||
2024-09-08 - 3305767560a - lavc 61.13.100 - avcodec.h
|
||||
Add avcodec_get_supported_config() and enum AVCodecConfig; deprecate
|
||||
AVCodec.pix_fmts, AVCodec.sample_fmts, AVCodec.supported_framerates,
|
||||
AVCodec.supported_samplerates and AVCodec.ch_layouts.
|
||||
|
||||
2024-09-06 - c35a51f4bb1 - lavc 61.12.100 - defs.h
|
||||
Add AV_PROFILE_HEVC_MULTIVIEW_MAIN
|
||||
|
||||
2024-09-06 - 450a3f58edb - lavu 59.36.100 - opt.h
|
||||
Add av_opt_set_array() and AV_OPT_ARRAY_REPLACE.
|
||||
|
||||
2024-08-27 - d89930f8666 - lavu 59.35.100 - opt.h
|
||||
Add av_opt_get_array_size() and av_opt_get_array().
|
||||
|
||||
2024-08-18 - 8657eb9c3f4 - lavc 61.11.100 - avcodec.h
|
||||
Clarify the documentation for get_buffer*() functions, making it
|
||||
clear that the memory returned by them should not contain sensitive
|
||||
information. This is not a change in the API, it is how it already worked
|
||||
before.
|
||||
|
||||
2024-08-10 - 5f0f1f7b7a6 - lavu 59.34.100 - hwcontext_vulkan.h
|
||||
Add qf and nb_qf to AVVulkanDeviceContext.
|
||||
Deprecate queue_family_index, nb_graphics_queues,
|
||||
queue_family_tx_index, nb_tx_queues.
|
||||
queue_family_comp_index, nb_comp_queues.
|
||||
queue_family_encode_index, nb_encode_queues.
|
||||
queue_family_decode_index, and nb_decode_queues,
|
||||
from AVVulkanDeviceContext.
|
||||
|
||||
2024-07-30 - e0f9f4d4915 - lavu 59.32.100 - cpu.h
|
||||
Deprecate AV_CPU_FLAG_RVF and AV_CPU_FLAG_RVD without replacement.
|
||||
Deprecate AV_CPU_FLAG_RVB_ADDR, subsumed into AV_CPU_FLAG_RVB.
|
||||
|
||||
2024-07-29 - 753f2aeed76 - lavu 59.31.100 - intreadwrite.h
|
||||
Add AV_{R,W}{L,B}{16,32}A and AV_{R,W}B64A.
|
||||
|
||||
2024-07-28 - cbea92c84d4 - lavu 59.30.100 - dovi_meta.h
|
||||
Add AVDOVIDecoderConfigurationRecord.dv_md_compression.
|
||||
|
||||
2024-07-25 - 45d7078a218 - lavu 59.29.100 - cpu.h
|
||||
Add AV_CPU_FLAG_RVB.
|
||||
|
||||
2024-07-xx - xxxxxxxxxx - lavf 61 - avformat.h
|
||||
Deprecate avformat_transfer_internal_stream_timing_info()
|
||||
and av_stream_get_codec_timebase() without replacement.
|
||||
|
||||
2024-07-08 - 1b58f3af30c - lavc 61.10.100 - packet.h
|
||||
Add AV_PKT_DATA_FRAME_CROPPING.
|
||||
|
||||
2024-07-07 - 46f7ea44563 - lavf 61.5.100 - avformat.h
|
||||
Add AV_DISPOSITION_MULTILAYER
|
||||
|
||||
2024-07-02 - d822146f4fc - lavu 59.28.100 - hwcontext_d3d12va.h
|
||||
Add AVD3D12VAFramesContext.flags
|
||||
|
||||
2024-06-28 - 8af0919cc66 - lavu 59.27.100 - stereo3d.h
|
||||
Add AV_STEREO3D_UNSPEC and AV_STEREO3D_VIEW_UNSPEC.
|
||||
|
||||
2024-06-25 - e6baf4f3841 - lavu 59.26.100 - stereo3d.h
|
||||
Add av_stereo3d_alloc_size().
|
||||
|
||||
2024-06-19 - cc587e69c6f - lavu 59.25.100 - dovi_meta.h
|
||||
Add AVDOVIRpuDataHeader.ext_mapping_idc_0_4 and ext_mapping_idc_5_7.
|
||||
|
||||
2024-06-18 - cf2436a0b4d - lavu 59.24.100 - stereo3d.h
|
||||
Add primary_eye, baseline, horizontal_disparity_adjustment, and
|
||||
horizontal_field_of_view fields to AVStereo3D.
|
||||
Add AVStereo3DPrimaryEye.
|
||||
Add av_stereo3d_view_name.
|
||||
Add av_stereo3d_view_from_name.
|
||||
Add av_stereo3d_primary_eye_name.
|
||||
Add av_stereo3d_primary_eye_from_name.
|
||||
|
||||
2024-06-18 - 57bfba35d6b - lavu 59.23.100 - spherical.h
|
||||
Add AV_SPHERICAL_HALF_EQUIRECTANGULAR, AV_SPHERICAL_RECTILINEAR, and
|
||||
AV_SPHERICAL_FISHEYE values to AVSphericalProjection, and initialize
|
||||
to AV_SPHERICAL_RECTILINEAR on alloc.
|
||||
|
||||
2024-06-13 - 39c90d6466a - lavu 59.22.100 - common.h
|
||||
Deprecate av_mod_uintp2[_c]() and replace it with av_zero_extend[_c]().
|
||||
|
||||
2024-06-08 - 91fd6ca000c - lavc 61.7.100 - defs.h
|
||||
Add AV_PROFILE_AAC_USAC.
|
||||
|
||||
2024-06-02 - 63e166d8028 - lavu 59.21.100 - channel_layout.h
|
||||
Add AV_CHAN_SIDE_SURROUND_RIGHT and AV_CH_SIDE_SURROUND_LEFT.
|
||||
Add AV_CHAN_SIDE_SURROUND_RIGHT and AV_CH_SIDE_SURROUND_RIGHT.
|
||||
Add AV_CHAN_TOP_SURROUND_LEFT and AV_CH_TOP_SURROUND_LEFT.
|
||||
Add AV_CHAN_TOP_SURROUND_RIGHT and AV_CH_TOP_SURROUND_RIGHT.
|
||||
|
||||
2024-05-23 - 8c974494822 - lavu 59.20.100 - channel_layout.h
|
||||
Add av_channel_layout_ambisonic_order().
|
||||
|
||||
2024-05-20 - 4c0bb7d4a91 - lavu 59.19.100 - hwcontext_qsv.h
|
||||
Add AVQSVFramesContext.info
|
||||
|
||||
2024-05-10 - 01c5f4ad9fa - lavu 59.18.100 - cpu.h
|
||||
Add AV_CPU_FLAG_RV_ZVBB.
|
||||
|
||||
2024-05-04 - d053290d8dd - lavu 59.17.100 - opt.h
|
||||
Add AV_OPT_TYPE_UINT and av_opt_eval_uint().
|
||||
|
||||
2024-04-24 - 8616cfe0890 - lavu 59.16.100 - opt.h
|
||||
Add AV_OPT_SERIALIZE_SEARCH_CHILDREN.
|
||||
|
||||
2024-04-11 - 6d0c89980c7 - lavc 61.5.102 - avcodec.h
|
||||
AVCodecContext.decoded_side_data may now be set by libavcodec after
|
||||
calling avcodec_open2().
|
||||
|
||||
2024-04-11 - 6d760c666d5 - lavu 59.15.100 - frame.h
|
||||
Add av_mastering_display_metadata_alloc_size().
|
||||
|
||||
2024-04-11 - adb67bba064 - lavu 59.14.100 - frame.h
|
||||
Add av_frame_side_data_add() and av_frame_side_data_remove().
|
||||
Add AV_FRAME_SIDE_DATA_FLAG_REPLACE.
|
||||
|
||||
2024-04-03 - 29561c8e2d4 - lavu 59.13.100 - pixfmt.h
|
||||
Add AVCOL_SPC_IPT_C2, AVCOL_SPC_YCGCO_RE and AVCOL_SPC_YCGCO_RO
|
||||
to map new matrix coefficients defined by H.273 v3.
|
||||
|
||||
2024-04-03 - 4f55e16f2bc - lavu 59.12.100 - dovi_meta.h
|
||||
Add AVDOVIMetadata.ext_block_{offset,size}, AVDOVIMetadata.num_ext_blocks,
|
||||
AVDOVIDmData and AVDOVIDmLevel{1..6,8..11,254..255}, av_dovi_get_ext()
|
||||
and av_dovi_find_level().
|
||||
|
||||
2024-04-03 - 78076ede296 - lavu 59.11.100 - dovi_meta.h
|
||||
Add AVDOVIDataMapping.nlq_pivots.
|
||||
|
||||
2024-03-29 - ed9363052f4 - lavf 61.3.100 - avformat.h
|
||||
Add AVFormatContext.duration_probesize.
|
||||
|
||||
2024-03-27 - 2621be35397 - lavu 59.10.100 - frame.h
|
||||
Add AVSideDataDescriptor, enum AVSideDataProps, and
|
||||
av_frame_side_data_desc().
|
||||
|
||||
-------- 8< --------- FFmpeg 7.0 was cut here -------- 8< ---------
|
||||
|
||||
2024-03-25 - 5df901ffa56 - lavu 59.7.100 - timestamp.h
|
||||
Add av_ts_make_time_string2() for better timestamp precision, the new
|
||||
function accepts AVRational as time base instead of *AVRational, and is not
|
||||
an inline function like its predecessor.
|
||||
|
||||
2024-03-23 - a9023377b22 - lavu 59.6.100 - film_grain_params.h
|
||||
Add av_film_grain_params_select().
|
||||
|
||||
2024-03-23 - 35d2960dcd0 - lavu 59.5.100 - film_grain_params.h
|
||||
Add AVFilmGrainParams.color_range, color_primaries, color_trc, color_space,
|
||||
width, height, subsampling_x, subsampling_y, bit_depth_luma and
|
||||
bit_depth_chroma. Deprecate the corresponding fields from
|
||||
AVFilmGrainH274Params.
|
||||
|
||||
2024-03-23 - f17e18d2922 - lavc 61.3.100 - jni.h
|
||||
Add av_jni_set_android_app_ctx() and av_jni_get_android_app_ctx().
|
||||
|
||||
2024-03-22 - 26398da8f30 - lavu 59.4.100 - frame.h
|
||||
Constified the first-level pointee of av_frame_side_data_get()
|
||||
and renamed it to av_frame_side_data_get_c(). From now on,
|
||||
av_frame_side_data_get() is a wrapper around av_frame_side_data_get_c()
|
||||
that accepts AVFrameSideData * const *sd.
|
||||
|
||||
2024-03-20 - 0d36844ddf9 - lavc 61.2.100 - avcodec.h
|
||||
Add AVCodecContext.[nb_]decoded_side_data.
|
||||
|
||||
2024-03-20 - d9ade14c5c5 - lavu 59.3.100 - frame.h
|
||||
Add av_frame_side_data_free(), av_frame_side_data_new(),
|
||||
av_frame_side_data_clone(), av_frame_side_data_get() as well
|
||||
as AV_FRAME_SIDE_DATA_FLAG_UNIQUE.
|
||||
|
||||
2024-03-16 - ed6207274e6 - lavu 59.2.100 - channel_layout.h
|
||||
Add AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL.
|
||||
|
||||
2024-03-08 - 68a8eca7523 - lavc 61.1.100 - avcodec.h
|
||||
Add AVCodecContext.[nb_]side_data_prefer_packet.
|
||||
|
||||
2024-03-08 - efe44787781 - lavu 59.1.100 - opt.h
|
||||
Add AV_OPT_TYPE_FLAG_ARRAY and AVOptionArrayDef.
|
||||
|
||||
2024-03-08 - c9f5cea9cca - lavc 61.0.100 - vdpau.h
|
||||
Deprecate av_vdpau_alloc_context(), av_alloc_vdpaucontext(),
|
||||
av_vdpau_hwaccel_get_render2() and av_vdpau_hwaccel_set_render2().
|
||||
The former are superseded by av_vdpau_bind_context(), the latter
|
||||
are unneeded as the relevant field is public and can be accessed directly.
|
||||
|
||||
2024-03-06 - 49707b05900 - lavf 60.25.100 - avformat.h
|
||||
Deprecate av_fmt_ctx_get_duration_estimation_method().
|
||||
The relevant field is public and needs no getter to access.
|
||||
|
||||
2024-03-05 - ab15c04dee5 - lavf 60.24.100 - avformat.h
|
||||
Add avformat_stream_group_name().
|
||||
|
||||
2024-02-28 - b295aafb082 - swr 4.14.100 - swresample.h
|
||||
swr_convert() now accepts arrays of const pointers (to input and output).
|
||||
|
||||
2024-02-28 - 58e3ef7f546 - lavu 58.40.100 - timestamp.h
|
||||
av_ts_make_time_string() now accepts a pointer to const AVRational.
|
||||
|
||||
2024-02-28 - dfb9d8a5a2f - lavf 60.23.100 - avio.h
|
||||
avio_print_string_array() now accepts an array of const pointers.
|
||||
|
||||
2024-02-26 - 41e349c24a7 - lavf 60.22.101 - avformat.h
|
||||
AV_DISPOSITION_DEPENDENT may now also be used for video streams
|
||||
intended to be merged with other video streams for presentation.
|
||||
|
||||
2024-02-26 - 25a10677d12 - lavf 60.22.100 - avformat.h
|
||||
Add AVStreamGroupTileGrid
|
||||
Add AV_STREAM_GROUP_PARAMS_TILE_GRID
|
||||
Add AVStreamGroup.params.tile_grid
|
||||
|
||||
2024-02-21 - 1d66a122df9 - lavc 60.40.100 - avcodec.h
|
||||
Deprecate AV_INPUT_BUFFER_MIN_SIZE without replacement.
|
||||
|
||||
2024-02-16 - eea9bd88a5f - lavu 58.39.100 - pixfmt.h
|
||||
Add AV_VIDEO_MAX_PLANES
|
||||
|
||||
2024-02-13 - ec2036454bc - lavf 60.21.100 - avformat.h
|
||||
Add AVStreamGroup.disposition.
|
||||
|
||||
2024-02-12 - 66386bf2a2a - lavu 58.38.100 - channel_layout.h
|
||||
Add av_channel_layout_retype().
|
||||
|
||||
2024-02-12 - 4569b861322 - lavu 58.37.100 - channel_layout.h
|
||||
Add av_channel_layout_custom_init().
|
||||
|
||||
2024-02-04 - 45697e6a512 - lavc 60.39.100 - packet.h
|
||||
Add AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT.
|
||||
|
||||
2023-11-xx - xxxxxxxxxx - lavfi 9.16.100 - buffersink.h buffersrc.h
|
||||
Add av_buffersink_get_colorspace and av_buffersink_get_color_range.
|
||||
Add AVBufferSrcParameters.color_space and AVBufferSrcParameters.color_range.
|
||||
|
||||
2023-11-xx - xxxxxxxxxx - lavfi 9.15.100 - avfilter.h
|
||||
Add AVFilterLink.colorspace, AVFilterLink.color_range
|
||||
|
||||
2023-12-21 - 142f727b9ca - lavu 58.36.100 - pixfmt.h hwcontext.h hwcontext_d3d12va.h
|
||||
Add AV_HWDEVICE_TYPE_D3D12VA and AV_PIX_FMT_D3D12.
|
||||
Add AVD3D12VADeviceContext, AVD3D12VASyncContext, AVD3D12VAFrame and
|
||||
AVD3D12VAFramesContext.
|
||||
|
||||
2023-12-18 - 74279227dd2 - lavc 60.36.100 - packet.h
|
||||
Add AV_PKT_DATA_IAMF_MIX_GAIN_PARAM, AV_PKT_DATA_IAMF_DEMIXING_INFO_PARAM
|
||||
and AV_PKT_DATA_IAMF_RECON_GAIN_INFO_PARAM.
|
||||
|
||||
2023-12-18 - 556b596d1d9 - lavc 60.19.100 - avformat.h
|
||||
Add AVStreamGroup struct.
|
||||
Add AVFormatContext.stream_groups and AVFormatContext.nb_stream_groups
|
||||
Add avformat_stream_group_create(), avformat_stream_group_add_stream(),
|
||||
and av_stream_group_get_class().
|
||||
Add enum AVStreamGroupParamsType with values AV_STREAM_GROUP_PARAMS_NONE,
|
||||
AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT and
|
||||
AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION.
|
||||
|
||||
2023-12-18 - d2af93bbefc - lavu 58.35.100 - iamf.h
|
||||
Add a new API to support Immersive Audio Model and Formats.
|
||||
|
||||
2023-12-13 - 5475f665f60 - lavu 58.33.100 - imgutils.h
|
||||
Add av_image_fill_color().
|
||||
|
||||
2023-11-08 - b82957a66a7 - lavu 58.32.100 - channel_layout.h
|
||||
Add AV_CH_LAYOUT_7POINT2POINT3 and AV_CHANNEL_LAYOUT_7POINT2POINT3.
|
||||
Add AV_CH_LAYOUT_9POINT1POINT4_BACK and AV_CHANNEL_LAYOUT_9POINT1POINT4_BACK.
|
||||
|
||||
2023-10-31 - 57c16323f26 - lavu 58.31.100 - pixdesc.h
|
||||
Add AV_PIX_FMT_FLAG_XYZ.
|
||||
|
||||
-------- 8< --------- FFmpeg 6.1 was cut here -------- 8< ---------
|
||||
|
||||
2023-10-27 - 52a97642604 - lavu 58.28.100 - channel_layout.h
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ PROJECT_NAME = FFmpeg
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_NUMBER = 6.1.2
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ GENTEXI := $(GENTEXI:%=doc/avoptions_%.texi)
|
||||
|
||||
$(GENTEXI): TAG = GENTEXI
|
||||
$(GENTEXI): doc/avoptions_%.texi: doc/print_options$(HOSTEXESUF)
|
||||
$(M)doc/print_options$(HOSTEXESUF) $* > $@
|
||||
$(M)doc/print_options $* > $@
|
||||
|
||||
doc/%.html: TAG = HTML
|
||||
doc/%-all.html: TAG = HTML
|
||||
|
||||
@@ -101,29 +101,6 @@ Remove zero padding at the end of a packet.
|
||||
Extract the core from a DCA/DTS stream, dropping extensions such as
|
||||
DTS-HD.
|
||||
|
||||
@section dovi_rpu
|
||||
|
||||
Manipulate Dolby Vision metadata in a HEVC/AV1 bitstream, optionally enabling
|
||||
metadata compression.
|
||||
|
||||
@table @option
|
||||
@item strip
|
||||
If enabled, strip all Dolby Vision metadata (configuration record + RPU data
|
||||
blocks) from the stream.
|
||||
@item compression
|
||||
Which compression level to enable.
|
||||
@table @samp
|
||||
@item none
|
||||
No metadata compression.
|
||||
@item limited
|
||||
Limited metadata compression scheme. Should be compatible with most devices.
|
||||
This is the default.
|
||||
@item extended
|
||||
Extended metadata compression. Devices are not required to support this. Note
|
||||
that this level currently behaves the same as @samp{limited} in libavcodec.
|
||||
@end table
|
||||
@end table
|
||||
|
||||
@section dump_extra
|
||||
|
||||
Add extradata to the beginning of the filtered packets except when
|
||||
@@ -222,13 +199,6 @@ Identical to @option{pass_types}, except the units in the given set
|
||||
removed and all others passed through.
|
||||
@end table
|
||||
|
||||
The types used by pass_types and remove_types correspond to NAL unit types
|
||||
(nal_unit_type) in H.264, HEVC and H.266 (see Table 7-1 in the H.264
|
||||
and HEVC specifications or Table 5 in the H.266 specification), to
|
||||
marker values for JPEG (without 0xFF prefix) and to start codes without
|
||||
start code prefix (i.e. the byte following the 0x000001) for MPEG-2.
|
||||
For VP8 and VP9, every unit has type zero.
|
||||
|
||||
Extradata is unchanged by this transformation, but note that if the stream
|
||||
contains inline parameter sets then the output may be unusable if they are
|
||||
removed.
|
||||
@@ -243,21 +213,6 @@ To remove all AUDs, SEI and filler from an H.265 stream:
|
||||
ffmpeg -i INPUT -c:v copy -bsf:v 'filter_units=remove_types=35|38-40' OUTPUT
|
||||
@end example
|
||||
|
||||
To remove all user data from a MPEG-2 stream, including Closed Captions:
|
||||
@example
|
||||
ffmpeg -i INPUT -c:v copy -bsf:v 'filter_units=remove_types=178' OUTPUT
|
||||
@end example
|
||||
|
||||
To remove all SEI from a H264 stream, including Closed Captions:
|
||||
@example
|
||||
ffmpeg -i INPUT -c:v copy -bsf:v 'filter_units=remove_types=6' OUTPUT
|
||||
@end example
|
||||
|
||||
To remove all prefix and suffix SEI from a HEVC stream, including Closed Captions and dynamic HDR:
|
||||
@example
|
||||
ffmpeg -i INPUT -c:v copy -bsf:v 'filter_units=remove_types=39|40' OUTPUT
|
||||
@end example
|
||||
|
||||
@section hapqa_extract
|
||||
|
||||
Extract Rgb or Alpha part of an HAPQA file, without recompression, in order to create an HAPQ or an HAPAlphaOnly file.
|
||||
@@ -479,10 +434,6 @@ will replace the current ones if the stream is already cropped.
|
||||
These fields are set in pixels. Note that some sizes may not be
|
||||
representable if the chroma is subsampled (H.265 section 7.4.3.2.1).
|
||||
|
||||
@item width
|
||||
@item height
|
||||
Set width and height after crop.
|
||||
|
||||
@item level
|
||||
Set the level in the VPS and SPS. See H.265 section A.4 and tables
|
||||
A.6 and A.7.
|
||||
@@ -577,6 +528,10 @@ metadata header from each subtitle packet.
|
||||
|
||||
See also the @ref{text2movsub} filter.
|
||||
|
||||
@section mp3decomp
|
||||
|
||||
Decompress non-standard compressed MP3 audio headers.
|
||||
|
||||
@section mpeg2_metadata
|
||||
|
||||
Modify metadata embedded in an MPEG-2 stream.
|
||||
@@ -927,15 +882,6 @@ The sample rate of stream packet belongs.
|
||||
The AV_NOPTS_VALUE constant.
|
||||
@end table
|
||||
|
||||
For example, to set PTS equal to DTS (not recommended if B-frames are involved):
|
||||
@example
|
||||
ffmpeg -i INPUT -c:a copy -bsf:a setts=pts=DTS out.mkv
|
||||
@end example
|
||||
|
||||
@section showinfo
|
||||
Log basic packet information. Mainly useful for testing, debugging,
|
||||
and development.
|
||||
|
||||
@anchor{text2movsub}
|
||||
@section text2movsub
|
||||
|
||||
|
||||
+9
-3
@@ -3,7 +3,7 @@
|
||||
@c man begin CODEC OPTIONS
|
||||
|
||||
libavcodec provides some generic global options, which can be set on
|
||||
all the encoders and decoders. In addition, each codec may support
|
||||
all the encoders and decoders. In addition each codec may support
|
||||
so-called private options, which are specific for a given codec.
|
||||
|
||||
Sometimes, a global option may only affect a specific kind of codec,
|
||||
@@ -767,9 +767,15 @@ Set rate-distortion optimal quantization.
|
||||
@item compression_level @var{integer} (@emph{encoding,audio,video})
|
||||
@item bits_per_raw_sample @var{integer}
|
||||
@item channel_layout @var{integer} (@emph{decoding/encoding,audio})
|
||||
See @ref{channel layout syntax,,the Channel Layout section in the ffmpeg-utils(1) manual,ffmpeg-utils}
|
||||
for the required syntax.
|
||||
|
||||
Possible values:
|
||||
@table @samp
|
||||
@end table
|
||||
@item request_channel_layout @var{integer} (@emph{decoding,audio})
|
||||
|
||||
Possible values:
|
||||
@table @samp
|
||||
@end table
|
||||
@item rc_max_vbv_use @var{float} (@emph{encoding,video})
|
||||
@item rc_min_vbv_use @var{float} (@emph{encoding,video})
|
||||
|
||||
|
||||
+3
-10
@@ -26,9 +26,7 @@ The General Assembly is sovereign and legitimate for all its decisions regarding
|
||||
|
||||
The General Assembly is made up of active contributors.
|
||||
|
||||
Contributors are considered "active contributors" if they have authored more than 20 patches in the last 36 months in the main FFmpeg repository, or if they have been voted in by the GA.
|
||||
|
||||
The list of active contributors is updated twice each year, on 1st January and 1st July, 0:00 UTC.
|
||||
Contributors are considered "active contributors" if they have pushed more than 20 patches in the last 36 months in the main FFmpeg repository, or if they have been voted in by the GA.
|
||||
|
||||
Additional members are added to the General Assembly through a vote after proposal by a member of the General Assembly. They are part of the GA for two years, after which they need a confirmation by the GA.
|
||||
|
||||
@@ -82,6 +80,8 @@ The TC has 2 modes of operation: a RFC one and an internal one.
|
||||
|
||||
If the TC thinks it needs the input from the larger community, the TC can call for a RFC. Else, it can decide by itself.
|
||||
|
||||
If the disagreement involves a member of the TC, that member should recuse themselves from the decision.
|
||||
|
||||
The decision to use a RFC process or an internal discussion is a discretionary decision of the TC.
|
||||
|
||||
The TC can also reject a seizure for a few reasons such as: the matter was not discussed enough previously; it lacks expertise to reach a beneficial decision on the matter; or the matter is too trivial.
|
||||
@@ -121,13 +121,6 @@ The decisions from the TC will be sent on the mailing list, with the [TC] tag.
|
||||
|
||||
Internally, the TC should take decisions with a majority, or using ranked-choice voting.
|
||||
|
||||
Each TC member must vote on such decision according to what is, in their view, best for the project.
|
||||
|
||||
If a TC member feels they are affected by a conflict of interest with regards to the case, they should announce it and recuse themselves from the TC
|
||||
discussion and vote.
|
||||
|
||||
A conflict of interest is presumed to occur when a TC member has a personal interest (e.g. financial) in a specific outcome of the case.
|
||||
|
||||
The decision from the TC should be published with a summary of the reasons that lead to this decision.
|
||||
|
||||
The decisions from the TC are final, until the matters are reopened after no less than one year.
|
||||
|
||||
+1
-70
@@ -38,51 +38,6 @@ Select an operating point of a scalable AV1 bitstream (0 - 31). Default is 0.
|
||||
|
||||
@end table
|
||||
|
||||
@section hevc
|
||||
HEVC (AKA ITU-T H.265 or ISO/IEC 23008-2) decoder.
|
||||
|
||||
The decoder supports MV-HEVC multiview streams with at most two views. Views to
|
||||
be output are selected by supplying a list of view IDs to the decoder (the
|
||||
@option{view_ids} option). This option may be set either statically before
|
||||
decoder init, or from the @code{get_format()} callback - useful for the case
|
||||
when the view count or IDs change dynamically during decoding.
|
||||
|
||||
Only the base layer is decoded by default.
|
||||
|
||||
Note that if you are using the @code{ffmpeg} CLI tool, you should be using view
|
||||
specifiers as documented in its manual, rather than the options documented here.
|
||||
|
||||
@subsection Options
|
||||
|
||||
@table @option
|
||||
|
||||
@item view_ids (MV-HEVC)
|
||||
Specify a list of view IDs that should be output. This option can also be set to
|
||||
a single '-1', which will cause all views defined in the VPS to be decoded and
|
||||
output.
|
||||
|
||||
@item view_ids_available (MV-HEVC)
|
||||
This option may be read by the caller to retrieve an array of view IDs available
|
||||
in the active VPS. The array is empty for single-layer video.
|
||||
|
||||
The value of this option is guaranteed to be accurate when read from the
|
||||
@code{get_format()} callback. It may also be set at other times (e.g. after
|
||||
opening the decoder), but the value is informational only and may be incorrect
|
||||
(e.g. when the stream contains multiple distinct VPS NALUs).
|
||||
|
||||
@item view_pos_available (MV-HEVC)
|
||||
This option may be read by the caller to retrieve an array of view positions
|
||||
(left, right, or unspecified) available in the active VPS, as
|
||||
@code{AVStereo3DView} values. When the array is available, its elements apply to
|
||||
the corresponding elements of @option{view_ids_available}, i.e.
|
||||
@code{view_pos_available[i]} contains the position of view with ID
|
||||
@code{view_ids_available[i]}.
|
||||
|
||||
Same validity restrictions as for @option{view_ids_available} apply to
|
||||
this option.
|
||||
|
||||
@end table
|
||||
|
||||
@section rawvideo
|
||||
|
||||
Raw video decoder.
|
||||
@@ -175,34 +130,10 @@ Set amount of frame threads to use during decoding. The default value is 0 (auto
|
||||
|
||||
@end table
|
||||
|
||||
@section libxevd
|
||||
|
||||
eXtra-fast Essential Video Decoder (XEVD) MPEG-5 EVC decoder wrapper.
|
||||
|
||||
This decoder requires the presence of the libxevd headers and library
|
||||
during configuration. You need to explicitly configure the build with
|
||||
@option{--enable-libxevd}.
|
||||
|
||||
The xevd project website is at @url{https://github.com/mpeg5/xevd}.
|
||||
|
||||
@subsection Options
|
||||
|
||||
The following options are supported by the libxevd wrapper.
|
||||
The xevd-equivalent options or values are listed in parentheses for easy migration.
|
||||
|
||||
To get a more accurate and extensive documentation of the libxevd options,
|
||||
invoke the command @code{xevd_app --help} or consult the libxevd documentation.
|
||||
|
||||
@table @option
|
||||
@item threads (@emph{threads})
|
||||
Force to use a specific number of threads
|
||||
|
||||
@end table
|
||||
|
||||
@section QSV Decoders
|
||||
|
||||
The family of Intel QuickSync Video decoders (VC1, MPEG-2, H.264, HEVC,
|
||||
JPEG/MJPEG, VP8, VP9, AV1, VVC).
|
||||
JPEG/MJPEG, VP8, VP9, AV1).
|
||||
|
||||
@subsection Common Options
|
||||
|
||||
|
||||
+1
-216
@@ -285,168 +285,6 @@ This demuxer accepts the following option:
|
||||
|
||||
@end table
|
||||
|
||||
@section dvdvideo
|
||||
|
||||
DVD-Video demuxer, powered by libdvdnav and libdvdread.
|
||||
|
||||
Can directly ingest DVD titles, specifically sequential PGCs, into
|
||||
a conversion pipeline. Menu assets, such as background video or audio,
|
||||
can also be demuxed given the menu's coordinates (at best effort).
|
||||
Seeking is not supported at this time.
|
||||
|
||||
Block devices (DVD drives), ISO files, and directory structures are accepted.
|
||||
Activate with @code{-f dvdvideo} in front of one of these inputs.
|
||||
|
||||
This demuxer does NOT have decryption code of any kind. You are on your own
|
||||
working with encrypted DVDs, and should not expect support on the matter.
|
||||
|
||||
Underlying playback is handled by libdvdnav, and structure parsing by libdvdread.
|
||||
FFmpeg must be built with GPL library support available as well as the
|
||||
configure switches @code{--enable-libdvdnav} and @code{--enable-libdvdread}.
|
||||
|
||||
You will need to provide either the desired "title number" or exact PGC/PG coordinates.
|
||||
Many open-source DVD players and tools can aid in providing this information.
|
||||
If not specified, the demuxer will default to title 1 which works for many discs.
|
||||
However, due to the flexibility of the format, it is recommended to check manually.
|
||||
There are many discs that are authored strangely or with invalid headers.
|
||||
|
||||
If the input is a real DVD drive, please note that there are some drives which may
|
||||
silently fail on reading bad sectors from the disc, returning random bits instead
|
||||
which is effectively corrupt data. This is especially prominent on aging or rotting discs.
|
||||
A second pass and integrity checks would be needed to detect the corruption.
|
||||
This is not an FFmpeg issue.
|
||||
|
||||
@subsection Background
|
||||
|
||||
DVD-Video is not a directly accessible, linear container format in the
|
||||
traditional sense. Instead, it allows for complex and programmatic playback of
|
||||
carefully muxed MPEG-PS streams that are stored in headerless VOB files.
|
||||
To the end-user, these streams are known simply as "titles", but the actual
|
||||
logical playback sequence is defined by one or more "PGCs", or Program Group Chains,
|
||||
within the title. The PGC is in turn comprised of multiple "PGs", or Programs",
|
||||
which are the actual video segments (and for a typical video feature, sequentially
|
||||
ordered). The PGC structure, along with stream layout and metadata, are stored in
|
||||
IFO files that need to be parsed. PGCs can be thought of as playlists in easier terms.
|
||||
|
||||
An actual DVD player relies on user GUI interaction via menus and an internal VM
|
||||
to drive the direction of demuxing. Generally, the user would either navigate (via menus)
|
||||
or automatically be redirected to the PGC of their choice. During this process and
|
||||
the subsequent playback, the DVD player's internal VM also maintains a state and
|
||||
executes instructions that can create jumps to different sectors during playback.
|
||||
This is why libdvdnav is involved, as a linear read of the MPEG-PS blobs on the
|
||||
disc (VOBs) is not enough to produce the right sequence in many cases.
|
||||
|
||||
There are many other DVD structures (a long subject) that will not be discussed here.
|
||||
NAV packets, in particular, are handled by this demuxer to build accurate timing
|
||||
but not emitted as a stream. For a good high-level understanding, refer to:
|
||||
@url{https://code.videolan.org/videolan/libdvdnav/-/blob/master/doc/dvd_structures}
|
||||
|
||||
@subsection Options
|
||||
|
||||
This demuxer accepts the following options:
|
||||
|
||||
@table @option
|
||||
|
||||
@item title @var{int}
|
||||
The title number to play. Must be set if @option{pgc} and @option{pg} are not set.
|
||||
Not applicable to menus.
|
||||
Default is 0 (auto), which currently only selects the first available title (title 1)
|
||||
and notifies the user about the implications.
|
||||
|
||||
@item chapter_start @var{int}
|
||||
The chapter, or PTT (part-of-title), number to start at. Not applicable to menus.
|
||||
Default is 1.
|
||||
|
||||
@item chapter_end @var{int}
|
||||
The chapter, or PTT (part-of-title), number to end at. Not applicable to menus.
|
||||
Default is 0, which is a special value to signal end at the last possible chapter.
|
||||
|
||||
@item angle @var{int}
|
||||
The video angle number, referring to what is essentially an additional
|
||||
video stream that is composed from alternate frames interleaved in the VOBs.
|
||||
Not applicable to menus.
|
||||
Default is 1.
|
||||
|
||||
@item region @var{int}
|
||||
The region code to use for playback. Some discs may use this to default playback
|
||||
at a particular angle in different regions. This option will not affect the region code
|
||||
of a real DVD drive, if used as an input. Not applicable to menus.
|
||||
Default is 0, "world".
|
||||
|
||||
@item menu @var{bool}
|
||||
Demux menu assets instead of navigating a title. Requires exact coordinates
|
||||
of the menu (@option{menu_lu}, @option{menu_vts}, @option{pgc}, @option{pg}).
|
||||
Default is false.
|
||||
|
||||
@item menu_lu @var{int}
|
||||
The menu language to demux. In DVD, menus are grouped by language.
|
||||
Default is 0, the first language unit.
|
||||
|
||||
@item menu_vts @var{int}
|
||||
The VTS where the menu lives, or 0 if it is a VMG menu (root-level).
|
||||
Default is 0, VMG menu.
|
||||
|
||||
@item pgc @var{int}
|
||||
The entry PGC to start playback, in conjunction with @option{pg}.
|
||||
Alternative to setting @option{title}.
|
||||
Chapter markers are not supported at this time.
|
||||
Must be explicitly set for menus.
|
||||
Default is 0, automatically resolve from value of @option{title}.
|
||||
|
||||
@item pg @var{int}
|
||||
The entry PG to start playback, in conjunction with @option{pgc}.
|
||||
Alternative to setting @option{title}.
|
||||
Chapter markers are not supported at this time.
|
||||
Default is 0, automatically resolve from value of @option{title}, or
|
||||
start from the beginning (PG 1) of the menu.
|
||||
|
||||
@item preindex @var{bool}
|
||||
Enable this to have accurate chapter (PTT) markers and duration measurement,
|
||||
which requires a slow second pass read in order to index the chapter marker
|
||||
timestamps from NAV packets. This is non-ideal extra work for real optical drives.
|
||||
It is recommended and faster to use this option with a backup of the DVD structure
|
||||
stored on a hard drive. Not compatible with @option{pgc} and @option{pg}.
|
||||
Not applicable to menus.
|
||||
Default is 0, false.
|
||||
|
||||
@item trim @var{bool}
|
||||
Skip padding cells (i.e. cells shorter than 1 second) from the beginning.
|
||||
There exist many discs with filler segments at the beginning of the PGC,
|
||||
often with junk data intended for controlling a real DVD player's
|
||||
buffering speed and with no other material data value.
|
||||
Not applicable to menus.
|
||||
Default is 1, true.
|
||||
|
||||
@end table
|
||||
|
||||
@subsection Examples
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Open title 3 from a given DVD structure:
|
||||
@example
|
||||
ffmpeg -f dvdvideo -title 3 -i <path to DVD> ...
|
||||
@end example
|
||||
|
||||
@item
|
||||
Open chapters 3-6 from title 1 from a given DVD structure:
|
||||
@example
|
||||
ffmpeg -f dvdvideo -chapter_start 3 -chapter_end 6 -title 1 -i <path to DVD> ...
|
||||
@end example
|
||||
|
||||
@item
|
||||
Open only chapter 5 from title 1 from a given DVD structure:
|
||||
@example
|
||||
ffmpeg -f dvdvideo -chapter_start 5 -chapter_end 5 -title 1 -i <path to DVD> ...
|
||||
@end example
|
||||
|
||||
@item
|
||||
Demux menu with language 1 from VTS 1, PGC 1, starting at PG 1:
|
||||
@example
|
||||
ffmpeg -f dvdvideo -menu 1 -menu_lu 1 -menu_vts 1 -pgc 1 -pg 1 -i <path to DVD> ...
|
||||
@end example
|
||||
@end itemize
|
||||
|
||||
@section ea
|
||||
|
||||
Electronic Arts Multimedia format demuxer.
|
||||
@@ -939,7 +777,7 @@ error or used to store a negative value for dts correction when treated as signe
|
||||
the user set an upper limit, beyond which the delta is clamped to 1. Values greater than the limit if negative when
|
||||
cast to int32 are used to adjust onward dts.
|
||||
|
||||
Unit is the track time scale. Range is 0 to UINT_MAX. Default is @code{UINT_MAX - 48000*10} which allows up to
|
||||
Unit is the track time scale. Range is 0 to UINT_MAX. Default is @code{UINT_MAX - 48000*10} which allows upto
|
||||
a 10 second dts correction for 48 kHz audio streams while accommodating 99.9% of @code{uint32} range.
|
||||
|
||||
@item interleaved_read
|
||||
@@ -1038,36 +876,6 @@ the command:
|
||||
ffplay -f rawvideo -pixel_format rgb24 -video_size 320x240 -framerate 10 input.raw
|
||||
@end example
|
||||
|
||||
@anchor{rcwtdec}
|
||||
@section rcwt
|
||||
|
||||
RCWT (Raw Captions With Time) is a format native to ccextractor, a commonly
|
||||
used open source tool for processing 608/708 Closed Captions (CC) sources.
|
||||
For more information on the format, see @ref{rcwtenc,,,ffmpeg-formats}.
|
||||
|
||||
This demuxer implements the specification as of March 2024, which has
|
||||
been stable and unchanged since April 2014.
|
||||
|
||||
@subsection Examples
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Render CC to ASS using the built-in decoder:
|
||||
@example
|
||||
ffmpeg -i CC.rcwt.bin CC.ass
|
||||
@end example
|
||||
Note that if your output appears to be empty, you may have to manually
|
||||
set the decoder's @option{data_field} option to pick the desired CC substream.
|
||||
|
||||
@item
|
||||
Convert an RCWT backup to Scenarist (SCC) format:
|
||||
@example
|
||||
ffmpeg -i CC.rcwt.bin -c:s copy CC.scc
|
||||
@end example
|
||||
Note that the SCC format does not support all of the possible CC extensions
|
||||
that can be stored in RCWT (such as EIA-708).
|
||||
@end itemize
|
||||
|
||||
@section sbg
|
||||
|
||||
SBaGen script demuxer.
|
||||
@@ -1135,27 +943,4 @@ which in turn, acts as a ceiling for the size of scripts that can be read.
|
||||
Default is 1 MiB.
|
||||
@end table
|
||||
|
||||
@section w64
|
||||
|
||||
Sony Wave64 Audio demuxer.
|
||||
|
||||
This demuxer accepts the following options:
|
||||
@table @option
|
||||
@item max_size
|
||||
See the same option for the @ref{wav} demuxer.
|
||||
@end table
|
||||
|
||||
@anchor{wav}
|
||||
@section wav
|
||||
|
||||
RIFF Wave Audio demuxer.
|
||||
|
||||
This demuxer accepts the following options:
|
||||
@table @option
|
||||
@item max_size
|
||||
Specify the maximum packet size in bytes for the demuxed packets. By default
|
||||
this is set to 0, which means that a sensible value is chosen based on the
|
||||
input format.
|
||||
@end table
|
||||
|
||||
@c man end DEMUXERS
|
||||
|
||||
+11
-5
@@ -56,8 +56,14 @@ and should try to fix issues their commit causes.
|
||||
|
||||
@section Language
|
||||
|
||||
FFmpeg is mainly programmed in the ISO C11 language, except for the public
|
||||
headers which must stay C99 compatible.
|
||||
FFmpeg is mainly programmed in the ISO C99 language, extended with:
|
||||
@itemize @bullet
|
||||
@item
|
||||
Atomic operations from C11 @file{stdatomic.h}. They are emulated on
|
||||
architectures/compilers that do not support them, so all FFmpeg-internal code
|
||||
may use atomics without any extra checks. However, @file{stdatomic.h} must not
|
||||
be included in public headers, so they stay C99-compatible.
|
||||
@end itemize
|
||||
|
||||
Compiler-specific extensions may be used with good reason, but must not be
|
||||
depended on, i.e. the code must still compile and work with compilers lacking
|
||||
@@ -93,7 +99,7 @@ The specific syntax used for writing assembly is:
|
||||
NASM on x86;
|
||||
|
||||
@item
|
||||
GAS on ARM and RISC-V.
|
||||
GAS on ARM.
|
||||
@end itemize
|
||||
|
||||
A unit testing framework for assembly called @code{checkasm} lives under
|
||||
@@ -687,7 +693,7 @@ number) in @file{libavcodec/version.h} or @file{libavformat/version.h}?
|
||||
Did you register it in @file{allcodecs.c} or @file{allformats.c}?
|
||||
|
||||
@item
|
||||
Did you add the AVCodecID to @file{codec_id.h}?
|
||||
Did you add the AVCodecID to @file{avcodec.h}?
|
||||
When adding new codec IDs, also add an entry to the codec descriptor
|
||||
list in @file{libavcodec/codec_desc.c}.
|
||||
|
||||
@@ -702,7 +708,7 @@ already being compiled by some other rule, like a raw demuxer.
|
||||
|
||||
@item
|
||||
Did you add an entry to the table of supported formats or codecs in
|
||||
@file{doc/general_contents.texi}?
|
||||
@file{doc/general.texi}?
|
||||
|
||||
@item
|
||||
Did you add an entry in the Changelog?
|
||||
|
||||
+39
-272
@@ -144,7 +144,8 @@ If this option is unspecified it is set to @samp{aac_low}.
|
||||
|
||||
AC-3 audio encoders.
|
||||
|
||||
These encoders implement part of ATSC A/52:2010 and ETSI TS 102 366.
|
||||
These encoders implement part of ATSC A/52:2010 and ETSI TS 102 366, as well as
|
||||
the undocumented RealAudio 3 (a.k.a. dnet).
|
||||
|
||||
The @var{ac3} encoder uses floating-point math, while the @var{ac3_fixed}
|
||||
encoder only uses fixed-point integer math. This does not mean that one is
|
||||
@@ -614,7 +615,7 @@ and slightly improves compression.
|
||||
|
||||
Opus encoder.
|
||||
|
||||
This is a native FFmpeg encoder for the Opus format. Currently, it's in development and
|
||||
This is a native FFmpeg encoder for the Opus format. Currently its in development and
|
||||
only implements the CELT part of the codec. Its quality is usually worse and at best
|
||||
is equal to the libopus encoder.
|
||||
|
||||
@@ -813,63 +814,6 @@ ffmpeg -i input.wav -c:a libfdk_aac -profile:a aac_he -b:a 64k output.m4a
|
||||
@end example
|
||||
@end itemize
|
||||
|
||||
@anchor{liblc3-enc}
|
||||
@section liblc3
|
||||
|
||||
liblc3 LC3 (Low Complexity Communication Codec) encoder wrapper.
|
||||
|
||||
Requires the presence of the liblc3 headers and library during configuration.
|
||||
You need to explicitly configure the build with @code{--enable-liblc3}.
|
||||
|
||||
This encoder has support for the Bluetooth SIG LC3 codec for the LE Audio
|
||||
protocol, and the following features of LC3plus:
|
||||
@itemize
|
||||
@item
|
||||
Frame duration of 2.5 and 5ms.
|
||||
@item
|
||||
High-Resolution mode, 48 KHz, and 96 kHz sampling rates.
|
||||
@end itemize
|
||||
|
||||
For more information see the liblc3 project at
|
||||
@url{https://github.com/google/liblc3}.
|
||||
|
||||
@subsection Options
|
||||
|
||||
The following options are mapped on the shared FFmpeg codec options.
|
||||
|
||||
@table @option
|
||||
@item b @var{bitrate}
|
||||
Set the bit rate in bits/s. This will determine the fixed size of the encoded
|
||||
frames, for a selected frame duration.
|
||||
|
||||
@item ar @var{frequency}
|
||||
Set the audio sampling rate (in Hz).
|
||||
|
||||
@item channels
|
||||
Set the number of audio channels.
|
||||
|
||||
@item frame_duration
|
||||
Set the audio frame duration in milliseconds. Default value is 10ms.
|
||||
Allowed frame durations are 2.5ms, 5ms, 7.5ms and 10ms.
|
||||
LC3 (Bluetooth LE Audio), allows 7.5ms and 10ms; and LC3plus 2.5ms, 5ms
|
||||
and 10ms.
|
||||
|
||||
The 10ms frame duration is available in LC3 and LC3 plus standard.
|
||||
In this mode, the produced bitstream can be referenced either as LC3 or LC3plus.
|
||||
|
||||
@item high_resolution @var{boolean}
|
||||
Enable the high-resolution mode if set to 1. The high-resolution mode is
|
||||
available with all LC3plus frame durations and for a sampling rate of 48 KHz,
|
||||
and 96 KHz.
|
||||
|
||||
The encoder automatically turns off this mode at lower sampling rates and
|
||||
activates it at 96 KHz.
|
||||
|
||||
This mode should be preferred at high bitrates. In this mode, the audio
|
||||
bandwidth is always up to the Nyquist frequency, compared to LC3 at 48 KHz,
|
||||
which limits the bandwidth to 20 KHz.
|
||||
@end table
|
||||
|
||||
@anchor{libmp3lame}
|
||||
@section libmp3lame
|
||||
|
||||
@@ -2293,12 +2237,6 @@ the two temporal layer 2 frames within the temporal period.
|
||||
@end table
|
||||
@end table
|
||||
|
||||
@item VP8-specific options
|
||||
@table @option
|
||||
@item screen-content-mode
|
||||
Screen content mode, one of: 0 (off), 1 (screen), 2 (screen with more aggressive rate control).
|
||||
@end table
|
||||
|
||||
@item VP9-specific options
|
||||
@table @option
|
||||
@item lossless
|
||||
@@ -2378,70 +2316,6 @@ Indicates frame duration
|
||||
For more information about libvpx see:
|
||||
@url{http://www.webmproject.org/}
|
||||
|
||||
@section libvvenc
|
||||
|
||||
VVenC H.266/VVC encoder wrapper.
|
||||
|
||||
This encoder requires the presence of the libvvenc headers and library
|
||||
during configuration. You need to explicitly configure the build with
|
||||
@option{--enable-libvvenc}.
|
||||
|
||||
The VVenC project website is at
|
||||
@url{https://github.com/fraunhoferhhi/vvenc}.
|
||||
|
||||
@subsection Supported Pixel Formats
|
||||
|
||||
VVenC supports only 10-bit color spaces as input. But the internal (encoded)
|
||||
bit depth can be set to 8-bit or 10-bit at runtime.
|
||||
|
||||
@subsection Options
|
||||
|
||||
@table @option
|
||||
@item b
|
||||
Sets target video bitrate.
|
||||
|
||||
@item g
|
||||
Set the GOP size. Currently support for g=1 (Intra only) or default.
|
||||
|
||||
@item preset
|
||||
Set the VVenC preset.
|
||||
|
||||
@item levelidc
|
||||
Set level idc.
|
||||
|
||||
@item tier
|
||||
Set vvc tier.
|
||||
|
||||
@item qp
|
||||
Set constant quantization parameter.
|
||||
|
||||
@item subopt @var{boolean}
|
||||
Set subjective (perceptually motivated) optimization. Default is 1 (on).
|
||||
|
||||
@item bitdepth8 @var{boolean}
|
||||
Set 8bit coding mode instead of using 10bit. Default is 0 (off).
|
||||
|
||||
@item period
|
||||
set (intra) refresh period in seconds.
|
||||
|
||||
@item vvenc-params
|
||||
Set vvenc options using a list of @var{key}=@var{value} couples separated
|
||||
by ":". See @command{vvencapp --fullhelp} or @command{vvencFFapp --fullhelp} for a list of options.
|
||||
|
||||
For example, the options might be provided as:
|
||||
|
||||
@example
|
||||
intraperiod=64:decodingrefreshtype=idr:poc0idr=1:internalbitdepth=8
|
||||
@end example
|
||||
|
||||
For example the encoding options might be provided with @option{-vvenc-params}:
|
||||
|
||||
@example
|
||||
ffmpeg -i input -c:v libvvenc -b 1M -vvenc-params intraperiod=64:decodingrefreshtype=idr:poc0idr=1:internalbitdepth=8 output.mp4
|
||||
@end example
|
||||
|
||||
@end table
|
||||
|
||||
@section libwebp
|
||||
|
||||
libwebp WebP Image encoder wrapper
|
||||
@@ -2547,10 +2421,6 @@ To get a more accurate and extensive documentation of the libx264
|
||||
options, invoke the command @command{x264 --fullhelp} or consult
|
||||
the libx264 documentation.
|
||||
|
||||
In the list below, note that the @command{x264} option name is shown
|
||||
in parentheses after the libavcodec corresponding name, in case there
|
||||
is a direct mapping.
|
||||
|
||||
@table @option
|
||||
@item b (@emph{bitrate})
|
||||
Set bitrate in bits/s. Note that FFmpeg's @option{b} option is
|
||||
@@ -2558,19 +2428,17 @@ expressed in bits/s, while @command{x264}'s @option{bitrate} is in
|
||||
kilobits/s.
|
||||
|
||||
@item bf (@emph{bframes})
|
||||
Number of B-frames between I and P-frames
|
||||
|
||||
@item g (@emph{keyint})
|
||||
Maximum GOP size
|
||||
|
||||
@item qmin (@emph{qpmin})
|
||||
Minimum quantizer scale
|
||||
Minimum quantizer scale.
|
||||
|
||||
@item qmax (@emph{qpmax})
|
||||
Maximum quantizer scale
|
||||
Maximum quantizer scale.
|
||||
|
||||
@item qdiff (@emph{qpstep})
|
||||
Maximum difference between quantizer scales
|
||||
Maximum difference between quantizer scales.
|
||||
|
||||
@item qblur (@emph{qblur})
|
||||
Quantizer curve blur
|
||||
@@ -2579,7 +2447,7 @@ Quantizer curve blur
|
||||
Quantizer curve compression factor
|
||||
|
||||
@item refs (@emph{ref})
|
||||
Number of reference frames each P-frame can use. The range is @var{0-16}.
|
||||
Number of reference frames each P-frame can use. The range is from @var{0-16}.
|
||||
|
||||
@item level (@emph{level})
|
||||
Set the @code{x264_param_t.i_level_idc} value in case the value is
|
||||
@@ -2601,8 +2469,7 @@ Sets the threshold for the scene change detection.
|
||||
@item trellis (@emph{trellis})
|
||||
Performs Trellis quantization to increase efficiency. Enabled by default.
|
||||
|
||||
@item nr (@emph{nr})
|
||||
Noise reduction
|
||||
@item nr (@emph{nr})
|
||||
|
||||
@item me_range (@emph{merange})
|
||||
Maximum range of the motion search in pixels.
|
||||
@@ -2683,7 +2550,6 @@ open GOP by setting it to @code{-cgop}. The result is similar to
|
||||
the behavior of @command{x264}'s @option{--open-gop} option.
|
||||
|
||||
@item rc_init_occupancy (@emph{vbv-init})
|
||||
Initial VBV buffer occupancy
|
||||
|
||||
@item preset (@emph{preset})
|
||||
Set the encoding preset.
|
||||
@@ -2729,7 +2595,7 @@ Set AQ strength, reduce blocking and blurring in flat and textured areas.
|
||||
Use psychovisual optimizations when set to 1. When set to 0, it has the
|
||||
same effect as @command{x264}'s @option{--no-psy} option.
|
||||
|
||||
@item psy-rd (@emph{psy-rd})
|
||||
@item psy-rd (@emph{psy-rd})
|
||||
Set strength of psychovisual optimization, in
|
||||
@var{psy-rd}:@var{psy-trellis} format.
|
||||
|
||||
@@ -2761,7 +2627,7 @@ to 1.
|
||||
|
||||
@item avcintra-class (@emph{class})
|
||||
Configure the encoder to generate AVC-Intra.
|
||||
Valid values are 50, 100 and 200
|
||||
Valid values are 50,100 and 200
|
||||
|
||||
@item bluray-compat (@emph{bluray-compat})
|
||||
Configure the encoder to be compatible with the bluray standard.
|
||||
@@ -2812,8 +2678,8 @@ Set loop filter parameters, in @var{alpha}:@var{beta} form.
|
||||
Set fluctuations reduction in QP (before curve compression).
|
||||
|
||||
@item partitions (@emph{partitions})
|
||||
Set partitions to consider as a comma-separated list of values.
|
||||
Possible values in the list:
|
||||
Set partitions to consider as a comma-separated list of. Possible
|
||||
values in the list:
|
||||
|
||||
@table @samp
|
||||
@item p8x8
|
||||
@@ -2869,32 +2735,19 @@ Variable bit rate.
|
||||
Constant bit rate (not allowed in MP4 container).
|
||||
@end table
|
||||
|
||||
@item x264opts @var{opts}
|
||||
@item x264-params @var{opts}
|
||||
Override the x264 configuration using a :-separated list of key=value
|
||||
options.
|
||||
@item x264opts (N.A.)
|
||||
Set any x264 option, see @command{x264 --fullhelp} for a list.
|
||||
|
||||
The argument for both options is a list of @var{key}=@var{value}
|
||||
couples separated by ":". With @option{x264opts} the value can be
|
||||
omitted, and the value @code{1} is assumed in that case.
|
||||
|
||||
For @var{filter} and @var{psy-rd} options values that use ":" as a
|
||||
separator themselves, use "," instead. They accept it as well since
|
||||
long ago but this is kept undocumented for some reason.
|
||||
|
||||
For example, the options might be provided as:
|
||||
@example
|
||||
level=30:bframes=0:weightp=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:subq=6:8x8dct=0:trellis=0
|
||||
@end example
|
||||
Argument is a list of @var{key}=@var{value} couples separated by
|
||||
":". In @var{filter} and @var{psy-rd} options that use ":" as a separator
|
||||
themselves, use "," instead. They accept it as well since long ago but this
|
||||
is kept undocumented for some reason.
|
||||
|
||||
For example to specify libx264 encoding options with @command{ffmpeg}:
|
||||
@example
|
||||
ffmpeg -i foo.mpg -c:v libx264 -x264opts keyint=123:min-keyint=20 -an out.mkv
|
||||
@end example
|
||||
|
||||
To get the complete list of the libx264 options, invoke the command
|
||||
@command{x264 --fullhelp} or consult the libx264 documentation.
|
||||
|
||||
@item a53cc @var{boolean}
|
||||
Import closed captions (which must be ATSC compatible format) into output.
|
||||
Only the mpeg2 and h264 decoders provide these. Default is 1 (on).
|
||||
@@ -2905,6 +2758,20 @@ Import user data unregistered SEI if available into output. Default is 0 (off).
|
||||
@item mb_info @var{boolean}
|
||||
Set mb_info data through AVFrameSideData, only useful when used from the
|
||||
API. Default is 0 (off).
|
||||
|
||||
@item x264-params (N.A.)
|
||||
Override the x264 configuration using a :-separated list of key=value
|
||||
parameters.
|
||||
|
||||
This option is functionally the same as the @option{x264opts}, but is
|
||||
duplicated for compatibility with the Libav fork.
|
||||
|
||||
For example to specify libx264 encoding options with @command{ffmpeg}:
|
||||
@example
|
||||
ffmpeg -i INPUT -c:v libx264 -x264-params level=30:bframes=0:weightp=0:\
|
||||
cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:\
|
||||
no-fast-pskip=1:subq=6:8x8dct=0:trellis=0 OUTPUT
|
||||
@end example
|
||||
@end table
|
||||
|
||||
Encoding ffpresets for common usages are provided so they can be used with the
|
||||
@@ -3044,75 +2911,6 @@ ffmpeg -i input -c:v libxavs2 -xavs2-params RdoqLevel=0 output.avs2
|
||||
@end example
|
||||
@end table
|
||||
|
||||
@section libxeve
|
||||
|
||||
eXtra-fast Essential Video Encoder (XEVE) MPEG-5 EVC encoder wrapper.
|
||||
The xeve-equivalent options or values are listed in parentheses for easy migration.
|
||||
|
||||
This encoder requires the presence of the libxeve headers and library
|
||||
during configuration. You need to explicitly configure the build with
|
||||
@option{--enable-libxeve}.
|
||||
|
||||
@float NOTE
|
||||
Many libxeve encoder options are mapped to FFmpeg global codec options,
|
||||
while unique encoder options are provided through private options.
|
||||
Additionally the xeve-params private options allows one to pass a list
|
||||
of key=value tuples as accepted by the libxeve @code{parse_xeve_params} function.
|
||||
@end float
|
||||
|
||||
The xeve project website is at @url{https://github.com/mpeg5/xeve}.
|
||||
|
||||
@subsection Options
|
||||
|
||||
The following options are supported by the libxeve wrapper.
|
||||
The xeve-equivalent options or values are listed in parentheses for easy migration.
|
||||
|
||||
@float NOTE
|
||||
To reduce the duplication of documentation, only the private options
|
||||
and some others requiring special attention are documented here. For
|
||||
the documentation of the undocumented generic options, see
|
||||
@ref{codec-options,,the Codec Options chapter}.
|
||||
@end float
|
||||
|
||||
@float NOTE
|
||||
To get a more accurate and extensive documentation of the libxeve options,
|
||||
invoke the command @code{xeve_app --help} or consult the libxeve documentation.
|
||||
@end float
|
||||
|
||||
@table @option
|
||||
@item b (@emph{bitrate})
|
||||
Set target video bitrate in bits/s.
|
||||
Note that FFmpeg's b option is expressed in bits/s, while xeve's bitrate is in kilobits/s.
|
||||
|
||||
@item bf (@emph{bframes})
|
||||
Set the maximum number of B frames (1,3,7,15).
|
||||
|
||||
@item g (@emph{keyint})
|
||||
Set the GOP size (I-picture period).
|
||||
|
||||
@item preset (@emph{preset})
|
||||
Set the xeve preset.
|
||||
Set the encoder preset value to determine encoding speed [fast, medium, slow, placebo]
|
||||
|
||||
@item tune (@emph{tune})
|
||||
Set the encoder tune parameter [psnr, zerolatency]
|
||||
|
||||
@item profile (@emph{profile})
|
||||
Set the encoder profile [0: baseline; 1: main]
|
||||
|
||||
@item crf (@emph{crf})
|
||||
Set the quality for constant quality mode.
|
||||
Constant rate factor <10..49> [default: 32]
|
||||
|
||||
@item qp (@emph{qp})
|
||||
Set constant quantization rate control method parameter.
|
||||
Quantization parameter qp <0..51> [default: 32]
|
||||
|
||||
@item threads (@emph{threads})
|
||||
Force to use a specific number of threads
|
||||
|
||||
@end table
|
||||
|
||||
@section libxvid
|
||||
|
||||
Xvid MPEG-4 Part 2 encoder wrapper.
|
||||
@@ -3165,6 +2963,9 @@ Enable high quality AC prediction.
|
||||
@item gray
|
||||
Only encode grayscale.
|
||||
|
||||
@item gmc
|
||||
Enable the use of global motion compensation (GMC).
|
||||
|
||||
@item qpel
|
||||
Enable quarter-pixel motion compensation.
|
||||
|
||||
@@ -3176,9 +2977,7 @@ Place global headers in extradata instead of every keyframe.
|
||||
|
||||
@end table
|
||||
|
||||
@item gmc
|
||||
Enable the use of global motion compensation (GMC). Default is 0
|
||||
(disabled).
|
||||
@item trellis
|
||||
|
||||
@item me_quality
|
||||
Set motion estimation quality level. Possible values in decreasing order of
|
||||
@@ -3233,9 +3032,6 @@ be better than any of the two specified individually. In other
|
||||
words, the resulting quality will be the worse one of the two
|
||||
effects.
|
||||
|
||||
@item trellis
|
||||
Set rate-distortion optimal quantization.
|
||||
|
||||
@item ssim
|
||||
Set structural similarity (SSIM) displaying method. Possible values:
|
||||
|
||||
@@ -3460,8 +3256,8 @@ quality range is 1 to 51, with 1 being the best quality.
|
||||
@end itemize
|
||||
|
||||
@item
|
||||
Otherwise when the desired average bitrate is specified with the @option{b}
|
||||
option, a bitrate-based mode is used.
|
||||
Otherwise, a bitrate-based mode is used. For all of those, you should specify at
|
||||
least the desired average bitrate with the @option{b} option.
|
||||
@itemize @minus
|
||||
@item
|
||||
@var{LA} - VBR with lookahead, when the @option{look_ahead} option is specified.
|
||||
@@ -3482,9 +3278,6 @@ than the average bitrate.
|
||||
@option{avbr_accuracy} and @option{avbr_convergence} are set to non-zero. This
|
||||
mode is available for H264 and HEVC on Windows.
|
||||
@end itemize
|
||||
|
||||
@item
|
||||
Otherwise the default ratecontrol method @var{CQP} is used.
|
||||
@end itemize
|
||||
|
||||
Note that depending on your system, a different mode than the one you specified
|
||||
@@ -3610,20 +3403,6 @@ Change these value to reset qsv codec's bitrate control configuration.
|
||||
@item @var{pic_timing_sei}
|
||||
Supported in h264_qsv and hevc_qsv.
|
||||
Change this value to reset qsv codec's pic_timing_sei configuration.
|
||||
|
||||
@item @var{qsv_params}
|
||||
Set QSV encoder parameters as a colon-separated list of key-value pairs.
|
||||
|
||||
The @option{qsv_params} should be formatted as @code{key1=value1:key2=value2:...}.
|
||||
|
||||
These parameters are passed directly to the underlying Intel Quick Sync Video (QSV) encoder using the MFXSetParameter function.
|
||||
|
||||
Example:
|
||||
@example
|
||||
ffmpeg -i input.mp4 -c:v h264_qsv -qsv_params "CodingOption1=1:CodingOption2=2" output.mp4
|
||||
@end example
|
||||
|
||||
This option allows fine-grained control over various encoder-specific settings provided by the QSV encoder.
|
||||
@end table
|
||||
|
||||
@subsection H264 options
|
||||
@@ -4105,18 +3884,10 @@ Setting this flag turns on or off LowDelayBRC feautre in qsv plugin, which provi
|
||||
more accurate bitrate control to minimize the variance of bitstream size frame
|
||||
by frame. Value: -1-default 0-off 1-on
|
||||
|
||||
@item @var{max_frame_size}
|
||||
@item max_frame_size
|
||||
Set the allowed max size in bytes for each frame. If the frame size exceeds
|
||||
the limitation, encoder will adjust the QP value to control the frame size.
|
||||
Invalid in CQP rate control mode.
|
||||
|
||||
@item @var{max_frame_size_i}
|
||||
Maximum encoded frame size for I frames in bytes. If this value is set as larger
|
||||
than zero, then for I frames the value set by max_frame_size is ignored.
|
||||
|
||||
@item @var{max_frame_size_p}
|
||||
Maximum encoded frame size for P frames in bytes. If this value is set as larger
|
||||
than zero, then for P frames the value set by max_frame_size is ignored.
|
||||
@end table
|
||||
|
||||
@section snow
|
||||
@@ -4233,10 +4004,6 @@ Quality-defined variable-bitrate.
|
||||
Average variable bitrate.
|
||||
@end table
|
||||
|
||||
@item blbrc
|
||||
Enable block level rate control, which assigns different bitrate block by block.
|
||||
Invalid for CQP mode.
|
||||
|
||||
@end table
|
||||
|
||||
Each encoder also has its own specific options:
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavformat/avio.h>
|
||||
#include <libavutil/file.h>
|
||||
#include <libavutil/mem.h>
|
||||
|
||||
struct buffer_data {
|
||||
uint8_t *ptr;
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include <libavfilter/buffersink.h>
|
||||
#include <libavfilter/buffersrc.h>
|
||||
#include <libavutil/channel_layout.h>
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavutil/opt.h>
|
||||
|
||||
static const char *filter_descr = "aresample=8000,aformat=sample_fmts=s16:channel_layouts=mono";
|
||||
@@ -280,25 +279,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
av_packet_unref(packet);
|
||||
}
|
||||
if (ret == AVERROR_EOF) {
|
||||
/* signal EOF to the filtergraph */
|
||||
if (av_buffersrc_add_frame_flags(buffersrc_ctx, NULL, 0) < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Error while closing the filtergraph\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* pull remaining frames from the filtergraph */
|
||||
while (1) {
|
||||
ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
|
||||
break;
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
print_frame(filt_frame);
|
||||
av_frame_unref(filt_frame);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
avfilter_graph_free(&filter_graph);
|
||||
avcodec_free_context(&dec_ctx);
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavfilter/buffersink.h>
|
||||
#include <libavfilter/buffersrc.h>
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavutil/opt.h>
|
||||
|
||||
const char *filter_descr = "scale=78:24,transpose=cclock";
|
||||
@@ -277,25 +276,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
av_packet_unref(packet);
|
||||
}
|
||||
if (ret == AVERROR_EOF) {
|
||||
/* signal EOF to the filtergraph */
|
||||
if (av_buffersrc_add_frame_flags(buffersrc_ctx, NULL, 0) < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Error while closing the filtergraph\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* pull remaining frames from the filtergraph */
|
||||
while (1) {
|
||||
ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
|
||||
break;
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base);
|
||||
av_frame_unref(filt_frame);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
avfilter_graph_free(&filter_graph);
|
||||
avcodec_free_context(&dec_ctx);
|
||||
|
||||
@@ -41,15 +41,15 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <libavutil/channel_layout.h>
|
||||
#include <libavutil/md5.h>
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/samplefmt.h>
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/md5.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "libavutil/samplefmt.h"
|
||||
|
||||
#include <libavfilter/avfilter.h>
|
||||
#include <libavfilter/buffersink.h>
|
||||
#include <libavfilter/buffersrc.h>
|
||||
#include "libavfilter/avfilter.h"
|
||||
#include "libavfilter/buffersink.h"
|
||||
#include "libavfilter/buffersrc.h"
|
||||
|
||||
#define INPUT_SAMPLERATE 48000
|
||||
#define INPUT_FORMAT AV_SAMPLE_FMT_FLTP
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavutil/hwcontext.h>
|
||||
#include <libavutil/opt.h>
|
||||
|
||||
@@ -28,18 +28,20 @@
|
||||
* GPU video surfaces, write the decoded frames to an output file.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavformat/avio.h>
|
||||
#include "libavformat/avformat.h"
|
||||
#include "libavformat/avio.h"
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include "libavcodec/avcodec.h"
|
||||
|
||||
#include <libavutil/buffer.h>
|
||||
#include <libavutil/error.h>
|
||||
#include <libavutil/hwcontext.h>
|
||||
#include <libavutil/hwcontext_qsv.h>
|
||||
#include <libavutil/mem.h>
|
||||
#include "libavutil/buffer.h"
|
||||
#include "libavutil/error.h"
|
||||
#include "libavutil/hwcontext.h"
|
||||
#include "libavutil/hwcontext_qsv.h"
|
||||
#include "libavutil/mem.h"
|
||||
|
||||
static int get_format(AVCodecContext *avctx, const enum AVPixelFormat *pix_fmts)
|
||||
{
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include <libavutil/hwcontext.h>
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/opt.h>
|
||||
@@ -63,10 +62,10 @@ static int str_to_dict(char* optstr, AVDictionary **opt)
|
||||
return 0;
|
||||
key = strtok(optstr, " ");
|
||||
if (key == NULL)
|
||||
return AVERROR(EINVAL);
|
||||
return AVERROR(ENAVAIL);
|
||||
value = strtok(NULL, " ");
|
||||
if (value == NULL)
|
||||
return AVERROR(EINVAL);
|
||||
return AVERROR(ENAVAIL);
|
||||
av_dict_set(opt, key, value, 0);
|
||||
do {
|
||||
key = strtok(NULL, " ");
|
||||
@@ -74,7 +73,7 @@ static int str_to_dict(char* optstr, AVDictionary **opt)
|
||||
return 0;
|
||||
value = strtok(NULL, " ");
|
||||
if (value == NULL)
|
||||
return AVERROR(EINVAL);
|
||||
return AVERROR(ENAVAIL);
|
||||
av_dict_set(opt, key, value, 0);
|
||||
} while(1);
|
||||
}
|
||||
@@ -181,7 +180,7 @@ static int open_input_file(char *filename)
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Codec is not supportted by qsv\n");
|
||||
return AVERROR(EINVAL);
|
||||
return AVERROR(ENAVAIL);
|
||||
}
|
||||
|
||||
if (!(decoder_ctx = avcodec_alloc_context3(decoder)))
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
* input to the output without transcoding.
|
||||
*/
|
||||
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavutil/timestamp.h>
|
||||
#include <libavformat/avformat.h>
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <libavfilter/buffersink.h>
|
||||
#include <libavfilter/buffersrc.h>
|
||||
#include <libavutil/channel_layout.h>
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
|
||||
@@ -197,7 +196,7 @@ static int open_output_file(const char *filename)
|
||||
/* 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 %s encoder for stream #%u\n", encoder->name, i);
|
||||
av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i);
|
||||
return ret;
|
||||
}
|
||||
ret = avcodec_parameters_from_context(out_stream->codecpar, enc_ctx);
|
||||
|
||||
@@ -29,20 +29,19 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavformat/avio.h>
|
||||
#include "libavformat/avformat.h"
|
||||
#include "libavformat/avio.h"
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include "libavcodec/avcodec.h"
|
||||
|
||||
#include <libavutil/audio_fifo.h>
|
||||
#include <libavutil/avassert.h>
|
||||
#include <libavutil/avstring.h>
|
||||
#include <libavutil/channel_layout.h>
|
||||
#include <libavutil/frame.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include "libavutil/audio_fifo.h"
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/frame.h"
|
||||
#include "libavutil/opt.h"
|
||||
|
||||
#include <libswresample/swresample.h>
|
||||
#include "libswresample/swresample.h"
|
||||
|
||||
/* The output bit rate in bit/s */
|
||||
#define OUTPUT_BIT_RATE 96000
|
||||
|
||||
+2
-2
@@ -450,7 +450,7 @@ work with streams that were detected during the initial scan; streams that
|
||||
are detected later are ignored.
|
||||
|
||||
The size of the initial scan is controlled by two options: @code{probesize}
|
||||
(default ~5@tie{}Mo) and @code{analyzeduration} (default 5,000,000@tie{}µs = 5@tie{}s). For
|
||||
(default ~5 Mo) and @code{analyzeduration} (default 5,000,000 µs = 5 s). For
|
||||
the subtitle stream to be detected, both values must be large enough.
|
||||
|
||||
@section Why was the @command{ffmpeg} @option{-sameq} option removed? What to use instead?
|
||||
@@ -467,7 +467,7 @@ point acceptable for your tastes. The most common options to do that are
|
||||
@option{-qscale} and @option{-qmax}, but you should peruse the documentation
|
||||
of the encoder you chose.
|
||||
|
||||
@section I have a stretched video, why does scaling not fix it?
|
||||
@section I have a stretched video, why does scaling does not fix it?
|
||||
|
||||
A lot of video codecs and formats can store the @emph{aspect ratio} of the
|
||||
video: this is the ratio between the width and the height of either the full
|
||||
|
||||
@@ -79,14 +79,6 @@ Do not put a '~' character in the samples path to indicate a home
|
||||
directory. Because of shell nuances, this will cause FATE to fail.
|
||||
@end float
|
||||
|
||||
Beware that some assertions are disabled by default, so mind setting
|
||||
@option{--assert-level=<level>} at configuration time, e.g. when seeking
|
||||
the highest possible test coverage:
|
||||
@example
|
||||
./configure --assert-level=2
|
||||
@end example
|
||||
Note that raising the assert level could have a performance impact.
|
||||
|
||||
To get the complete list of tests, run the command:
|
||||
@example
|
||||
make fate-list
|
||||
|
||||
@@ -31,25 +31,3 @@ makeopts= # extra options passed to 'make'
|
||||
# defaulting to makeopts above if this is not set
|
||||
#tar= # command to create a tar archive from its arguments on stdout,
|
||||
# defaults to 'tar c'
|
||||
#fate_targets= # targets to make when running fate; defaults to "fate",
|
||||
# can be set to run a subset of tests, e.g. "fate-checkasm".
|
||||
|
||||
#fate_environments= # a list of names of configurations to run tests for;
|
||||
# each round is run with variables from ${${name}_env} set.
|
||||
|
||||
# One example of using fate_environments:
|
||||
|
||||
# target_exec="qemu-aarch64-static"
|
||||
# fate_targets="fate-checkasm fate-cpu"
|
||||
# fate_environments="sve128 sve256"
|
||||
# sve128_env="QEMU_CPU=max,sve128=on"
|
||||
# sve256_env="QEMU_CPU=max,sve256=on"
|
||||
|
||||
# The variables set by fate_environments can also be used explicitly
|
||||
# by target_exec, e.g. like this:
|
||||
|
||||
# target_exec="qemu-aarch64-static -cpu \$(MY_CPU)"
|
||||
# fate_targets="fate-checkasm fate-cpu"
|
||||
# fate_environments="sve128 sve256"
|
||||
# sve128_env="MY_CPU=max,sve128=on"
|
||||
# sve256_env="MY_CPU=max,sve256=on"
|
||||
|
||||
+120
-478
@@ -118,7 +118,7 @@ Encoded packets are then passed to the decoder (unless streamcopy is selected
|
||||
for the stream, see further for a description). The decoder produces
|
||||
uncompressed frames (raw video/PCM audio/...) which can be processed further by
|
||||
filtering (see next section). After filtering, the frames are passed to the
|
||||
encoder, which encodes them and outputs encoded packets. Finally, those are
|
||||
encoder, which encodes them and outputs encoded packets. Finally those are
|
||||
passed to the muxer, which writes the encoded packets to the output file.
|
||||
|
||||
@section Filtering
|
||||
@@ -219,46 +219,6 @@ Since there is no decoding or encoding, it is very fast and there is no quality
|
||||
loss. However, it might not work in some cases because of many factors. Applying
|
||||
filters is obviously also impossible, since filters work on uncompressed data.
|
||||
|
||||
@section Loopback decoders
|
||||
While decoders are normally associated with demuxer streams, it is also possible
|
||||
to create "loopback" decoders that decode the output from some encoder and allow
|
||||
it to be fed back to complex filtergraphs. This is done with the @code{-dec}
|
||||
directive, which takes as a parameter the index of the output stream that should
|
||||
be decoded. Every such directive creates a new loopback decoder, indexed with
|
||||
successive integers starting at zero. These indices should then be used to refer
|
||||
to loopback decoders in complex filtergraph link labels, as described in the
|
||||
documentation for @option{-filter_complex}.
|
||||
|
||||
Decoding AVOptions can be passed to loopback decoders by placing them before
|
||||
@code{-dec}, analogously to input/output options.
|
||||
|
||||
E.g. the following example:
|
||||
|
||||
@example
|
||||
ffmpeg -i INPUT \
|
||||
-map 0:v:0 -c:v libx264 -crf 45 -f null - \
|
||||
-threads 3 -dec 0:0 \
|
||||
-filter_complex '[0:v][dec:0]hstack[stack]' \
|
||||
-map '[stack]' -c:v ffv1 OUTPUT
|
||||
@end example
|
||||
|
||||
reads an input video and
|
||||
@itemize
|
||||
@item
|
||||
(line 2) encodes it with @code{libx264} at low quality;
|
||||
|
||||
@item
|
||||
(line 3) decodes this encoded stream using 3 threads;
|
||||
|
||||
@item
|
||||
(line 4) places decoded video side by side with the original input video;
|
||||
|
||||
@item
|
||||
(line 5) combined video is then losslessly encoded and written into
|
||||
@file{OUTPUT}.
|
||||
|
||||
@end itemize
|
||||
|
||||
@c man end DETAILED DESCRIPTION
|
||||
|
||||
@chapter Stream selection
|
||||
@@ -663,228 +623,6 @@ Not all muxers support embedded thumbnails, and those who do, only support a few
|
||||
Creates a program with the specified @var{title}, @var{program_num} and adds the specified
|
||||
@var{stream}(s) to it.
|
||||
|
||||
@item -stream_group [map=@var{input_file_id}=@var{stream_group}][type=@var{type}:]st=@var{stream}[:st=@var{stream}][:stg=@var{stream_group}][:id=@var{stream_group_id}...] (@emph{output})
|
||||
|
||||
Creates a stream group of the specified @var{type} and @var{stream_group_id}, or by
|
||||
@var{map}ping an input group, adding the specified @var{stream}(s) and/or previously
|
||||
defined @var{stream_group}(s) to it.
|
||||
|
||||
@var{type} can be one of the following:
|
||||
@table @option
|
||||
|
||||
@item iamf_audio_element
|
||||
Groups @var{stream}s that belong to the same IAMF Audio Element
|
||||
|
||||
For this group @var{type}, the following options are available
|
||||
@table @option
|
||||
@item audio_element_type
|
||||
The Audio Element type. The following values are supported:
|
||||
|
||||
@table @option
|
||||
@item channel
|
||||
Scalable channel audio representation
|
||||
@item scene
|
||||
Ambisonics representation
|
||||
@end table
|
||||
|
||||
@item demixing
|
||||
Demixing information used to reconstruct a scalable channel audio representation.
|
||||
This option must be separated from the rest with a ',', and takes the following
|
||||
key=value options
|
||||
|
||||
@table @option
|
||||
@item parameter_id
|
||||
An identifier parameters blocks in frames may refer to
|
||||
@item dmixp_mode
|
||||
A pre-defined combination of demixing parameters
|
||||
@end table
|
||||
|
||||
@item recon_gain
|
||||
Recon gain information used to reconstruct a scalable channel audio representation.
|
||||
This option must be separated from the rest with a ',', and takes the following
|
||||
key=value options
|
||||
|
||||
@table @option
|
||||
@item parameter_id
|
||||
An identifier parameters blocks in frames may refer to
|
||||
@end table
|
||||
|
||||
@item layer
|
||||
A layer defining a Channel Layout in the Audio Element.
|
||||
This option must be separated from the rest with a ','. Several ',' separated entries
|
||||
can be defined, and at least one must be set.
|
||||
|
||||
It takes the following ":"-separated key=value options
|
||||
|
||||
@table @option
|
||||
@item ch_layout
|
||||
The layer's channel layout
|
||||
@item flags
|
||||
The following flags are available:
|
||||
|
||||
@table @option
|
||||
@item recon_gain
|
||||
Wether to signal if recon_gain is present as metadata in parameter blocks within frames
|
||||
@end table
|
||||
|
||||
@item output_gain
|
||||
@item output_gain_flags
|
||||
Which channels output_gain applies to. The following flags are available:
|
||||
|
||||
@table @option
|
||||
@item FL
|
||||
@item FR
|
||||
@item BL
|
||||
@item BR
|
||||
@item TFL
|
||||
@item TFR
|
||||
@end table
|
||||
|
||||
@item ambisonics_mode
|
||||
The ambisonics mode. This has no effect if audio_element_type is set to channel.
|
||||
|
||||
The following values are supported:
|
||||
|
||||
@table @option
|
||||
@item mono
|
||||
Each ambisonics channel is coded as an individual mono stream in the group
|
||||
@end table
|
||||
|
||||
@end table
|
||||
|
||||
@item default_w
|
||||
Default weight value
|
||||
|
||||
@end table
|
||||
|
||||
@item iamf_mix_presentation
|
||||
Groups @var{stream}s that belong to all IAMF Audio Element the same
|
||||
IAMF Mix Presentation references
|
||||
|
||||
For this group @var{type}, the following options are available
|
||||
|
||||
@table @option
|
||||
@item submix
|
||||
A sub-mix within the Mix Presentation.
|
||||
This option must be separated from the rest with a ','. Several ',' separated entries
|
||||
can be defined, and at least one must be set.
|
||||
|
||||
It takes the following ":"-separated key=value options
|
||||
|
||||
@table @option
|
||||
@item parameter_id
|
||||
An identifier parameters blocks in frames may refer to, for post-processing the mixed
|
||||
audio signal to generate the audio signal for playback
|
||||
@item parameter_rate
|
||||
The sample rate duration fields in parameters blocks in frames that refer to this
|
||||
@var{parameter_id} are expressed as
|
||||
@item default_mix_gain
|
||||
Default mix gain value to apply when there are no parameter blocks sharing the same
|
||||
@var{parameter_id} for a given frame
|
||||
|
||||
@item element
|
||||
References an Audio Element used in this Mix Presentation to generate the final output
|
||||
audio signal for playback.
|
||||
This option must be separated from the rest with a '|'. Several '|' separated entries
|
||||
can be defined, and at least one must be set.
|
||||
|
||||
It takes the following ":"-separated key=value options:
|
||||
|
||||
@table @option
|
||||
@item stg
|
||||
The @var{stream_group_id} for an Audio Element which this sub-mix refers to
|
||||
@item parameter_id
|
||||
An identifier parameters blocks in frames may refer to, for applying any processing to
|
||||
the referenced and rendered Audio Element before being summed with other processed Audio
|
||||
Elements
|
||||
@item parameter_rate
|
||||
The sample rate duration fields in parameters blocks in frames that refer to this
|
||||
@var{parameter_id} are expressed as
|
||||
@item default_mix_gain
|
||||
Default mix gain value to apply when there are no parameter blocks sharing the same
|
||||
@var{parameter_id} for a given frame
|
||||
@item annotations
|
||||
A key=value string describing the sub-mix element where "key" is a string conforming to
|
||||
BCP-47 that specifies the language for the "value" string. "key" must be the same as the
|
||||
one in the mix's @var{annotations}
|
||||
@item headphones_rendering_mode
|
||||
Indicates whether the input channel-based Audio Element is rendered to stereo loudspeakers
|
||||
or spatialized with a binaural renderer when played back on headphones.
|
||||
This has no effect if the referenced Audio Element's @var{audio_element_type} is set to
|
||||
channel.
|
||||
|
||||
The following values are supported:
|
||||
|
||||
@table @option
|
||||
@item stereo
|
||||
@item binaural
|
||||
@end table
|
||||
|
||||
@end table
|
||||
|
||||
@item layout
|
||||
Specifies the layouts for this sub-mix on which the loudness information was measured.
|
||||
This option must be separated from the rest with a '|'. Several '|' separated entries
|
||||
can be defined, and at least one must be set.
|
||||
|
||||
It takes the following ":"-separated key=value options:
|
||||
|
||||
@table @option
|
||||
@item layout_type
|
||||
|
||||
@table @option
|
||||
@item loudspeakers
|
||||
The layout follows the loudspeaker sound system convention of ITU-2051-3.
|
||||
@item binaural
|
||||
The layout is binaural.
|
||||
@end table
|
||||
|
||||
@item sound_system
|
||||
Channel layout matching one of Sound Systems A to J of ITU-2051-3, plus 7.1.2 and 3.1.2
|
||||
This has no effect if @var{layout_type} is set to binaural.
|
||||
@item integrated_loudness
|
||||
The program integrated loudness information, as defined in ITU-1770-4.
|
||||
@item digital_peak
|
||||
The digital (sampled) peak value of the audio signal, as defined in ITU-1770-4.
|
||||
@item true_peak
|
||||
The true peak of the audio signal, as defined in ITU-1770-4.
|
||||
@item dialog_anchored_loudness
|
||||
The Dialogue loudness information, as defined in ITU-1770-4.
|
||||
@item album_anchored_loudness
|
||||
The Album loudness information, as defined in ITU-1770-4.
|
||||
@end table
|
||||
|
||||
@end table
|
||||
|
||||
@item annotations
|
||||
A key=value string string describing the mix where "key" is a string conforming to BCP-47
|
||||
that specifies the language for the "value" string. "key" must be the same as the ones in
|
||||
all sub-mix element's @var{annotations}s
|
||||
@end table
|
||||
|
||||
@end table
|
||||
|
||||
E.g. to create an scalable 5.1 IAMF file from several WAV input files
|
||||
@example
|
||||
ffmpeg -i front.wav -i back.wav -i center.wav -i lfe.wav
|
||||
-map 0:0 -map 1:0 -map 2:0 -map 3:0 -c:a opus
|
||||
-stream_group type=iamf_audio_element:id=1:st=0:st=1:st=2:st=3,
|
||||
demixing=parameter_id=998,
|
||||
recon_gain=parameter_id=101,
|
||||
layer=ch_layout=stereo,
|
||||
layer=ch_layout=5.1,
|
||||
-stream_group type=iamf_mix_presentation:id=2:stg=0:annotations=en-us=Mix_Presentation,
|
||||
submix=parameter_id=100:parameter_rate=48000|element=stg=0:parameter_id=100:annotations=en-us=Scalable_Submix|layout=sound_system=stereo|layout=sound_system=5.1
|
||||
-streamid 0:0 -streamid 1:1 -streamid 2:2 -streamid 3:3 output.iamf
|
||||
@end example
|
||||
|
||||
To copy the two stream groups (Audio Element and Mix Presentation) from an input IAMF file with four
|
||||
streams into an mp4 output
|
||||
@example
|
||||
ffmpeg -i input.iamf -c:a copy -stream_group map=0=0:st=0:st=1:st=2:st=3 -stream_group map=0=1:stg=0
|
||||
-streamid 0:0 -streamid 1:1 -streamid 2:2 -streamid 3:3 output.mp4
|
||||
@end example
|
||||
|
||||
@item -target @var{type} (@emph{output})
|
||||
Specify target file type (@code{vcd}, @code{svcd}, @code{dvd}, @code{dv},
|
||||
@code{dv50}). @var{type} may be prefixed with @code{pal-}, @code{ntsc-} or
|
||||
@@ -1039,6 +777,12 @@ syntax.
|
||||
See the @ref{filter_complex_option,,-filter_complex option} if you
|
||||
want to create filtergraphs with multiple inputs and/or outputs.
|
||||
|
||||
@anchor{filter_script option}
|
||||
@item -filter_script[:@var{stream_specifier}] @var{filename} (@emph{output,per-stream})
|
||||
This option is similar to @option{-filter}, the only difference is that its
|
||||
argument is the name of the file from which a filtergraph description is to be
|
||||
read.
|
||||
|
||||
@item -reinit_filter[:@var{stream_specifier}] @var{integer} (@emph{input,per-stream})
|
||||
This boolean option determines if the filtergraph(s) to which this stream is fed gets
|
||||
reinitialized when input frame parameters change mid-stream. This option is enabled by
|
||||
@@ -1086,7 +830,7 @@ be achieved with @code{ffmpeg ... < /dev/null} but it requires a
|
||||
shell.
|
||||
|
||||
@item -debug_ts (@emph{global})
|
||||
Print timestamp/latency information. It is off by default. This option is
|
||||
Print timestamp information. It is off by default. This option is
|
||||
mostly useful for testing and debugging purposes, and the output
|
||||
format may change from one version to another, so it should not be
|
||||
employed by portable scripts.
|
||||
@@ -1292,6 +1036,10 @@ list separated with slashes. Two first values are the beginning and
|
||||
end frame numbers, last one is quantizer to use if positive, or quality
|
||||
factor if negative.
|
||||
|
||||
@item -psnr
|
||||
Calculate PSNR of compressed frames. This option is deprecated, pass the
|
||||
PSNR flag to the encoder instead, using @code{-flags +psnr}.
|
||||
|
||||
@item -vstats
|
||||
Dump video coding statistics to @file{vstats_HHMMSS.log}. See the
|
||||
@ref{vstats_file_format,,vstats file format} section for the format description.
|
||||
@@ -1306,6 +1054,8 @@ Specify which version of the vstats format to use. Default is @code{2}. See the
|
||||
|
||||
@item -vtag @var{fourcc/tag} (@emph{output})
|
||||
Force video tag/fourcc. This is an alias for @code{-tag:v}.
|
||||
@item -vbsf @var{bitstream_filter}
|
||||
Deprecated see -bsf
|
||||
|
||||
@item -force_key_frames[:@var{stream_specifier}] @var{time}[,@var{time}...] (@emph{output,per-stream})
|
||||
@item -force_key_frames[:@var{stream_specifier}] expr:@var{expr} (@emph{output,per-stream})
|
||||
@@ -1379,21 +1129,6 @@ Note that forcing too many keyframes is very harmful for the lookahead
|
||||
algorithms of certain encoders: using fixed-GOP options or similar
|
||||
would be more efficient.
|
||||
|
||||
@item -apply_cropping[:@var{stream_specifier}] @var{source} (@emph{input,per-stream})
|
||||
Automatically crop the video after decoding according to file metadata.
|
||||
Default is @emph{all}.
|
||||
|
||||
@table @option
|
||||
@item none (0)
|
||||
Don't apply any cropping metadata.
|
||||
@item all (1)
|
||||
Apply both codec and container level croppping. This is the default mode.
|
||||
@item codec (2)
|
||||
Apply codec level croppping.
|
||||
@item container (3)
|
||||
Apply container level croppping.
|
||||
@end table
|
||||
|
||||
@item -copyinkf[:@var{stream_specifier}] (@emph{output,per-stream})
|
||||
When doing stream copy, copy also non-key frames found at the
|
||||
beginning.
|
||||
@@ -1430,21 +1165,6 @@ Choose the first device and use the primary device context.
|
||||
|
||||
@item d3d11va
|
||||
@var{device} is the number of the Direct3D 11 display adapter.
|
||||
If not specified, it will attempt to use the default Direct3D 11 display adapter
|
||||
or the first Direct3D 11 display adapter whose hardware VendorId is specified
|
||||
by @samp{vendor_id}.
|
||||
|
||||
Examples:
|
||||
@table @emph
|
||||
@item -init_hw_device d3d11va
|
||||
Create a d3d11va device on the default Direct3D 11 display adapter.
|
||||
|
||||
@item -init_hw_device d3d11va:1
|
||||
Create a d3d11va device on the Direct3D 11 display adapter specified by index 1.
|
||||
|
||||
@item -init_hw_device d3d11va:,vendor_id=0x8086
|
||||
Create a d3d11va device on the first Direct3D 11 display adapter whose hardware VendorId is 0x8086.
|
||||
@end table
|
||||
|
||||
@item vaapi
|
||||
@var{device} is either an X11 display name, a DRM render node or a DirectX adapter index.
|
||||
@@ -1452,37 +1172,6 @@ If not specified, it will attempt to open the default X11 display (@emph{$DISPLA
|
||||
and then the first DRM render node (@emph{/dev/dri/renderD128}), or the default
|
||||
DirectX adapter on Windows.
|
||||
|
||||
The following options are recognized:
|
||||
@table @option
|
||||
@item kernel_driver
|
||||
When @var{device} is not specified, use this option to specify the name of the kernel
|
||||
driver associated with the desired device. This option is available only when
|
||||
the hardware acceleration method @emph{drm} and @emph{vaapi} are enabled.
|
||||
@item vendor_id
|
||||
When @var{device} and @var{kernel_driver} are not specified, use this option to specify
|
||||
the vendor id associated with the desired device. This option is available only when the
|
||||
hardware acceleration method @emph{drm} and @emph{vaapi} are enabled and @emph{kernel_driver}
|
||||
is not specified.
|
||||
@end table
|
||||
|
||||
Examples:
|
||||
@table @emph
|
||||
@item -init_hw_device vaapi
|
||||
Create a vaapi device on the default device.
|
||||
|
||||
@item -init_hw_device vaapi:/dev/dri/renderD129
|
||||
Create a vaapi device on DRM render node @file{/dev/dri/renderD129}.
|
||||
|
||||
@item -init_hw_device vaapi:1
|
||||
Create a vaapi device on DirectX adapter 1.
|
||||
|
||||
@item -init_hw_device vaapi:,kernel_driver=i915
|
||||
Create a vaapi device on a device associated with kernel driver @samp{i915}.
|
||||
|
||||
@item -init_hw_device vaapi:,vendor_id=0x8086
|
||||
Create a vaapi device on a device associated with vendor id @samp{0x8086}.
|
||||
@end table
|
||||
|
||||
@item vdpau
|
||||
@var{device} is an X11 display name.
|
||||
If not specified, it will attempt to open the default X11 display (@emph{$DISPLAY}).
|
||||
@@ -1504,38 +1193,16 @@ If not specified, @samp{auto_any} is used.
|
||||
platform-appropriate subdevice (@samp{dxva2} or @samp{d3d11va} or @samp{vaapi}) and then deriving a
|
||||
QSV device from that.)
|
||||
|
||||
The following options are recognized:
|
||||
@table @option
|
||||
@item child_device
|
||||
Specify a DRM render node on Linux or DirectX adapter on Windows.
|
||||
@item child_device_type
|
||||
Choose platform-appropriate subdevice type. On Windows @samp{d3d11va} is used
|
||||
as default subdevice type when @code{--enable-libvpl} is specified at configuration time,
|
||||
@samp{dxva2} is used as default subdevice type when @code{--enable-libmfx} is specified at
|
||||
configuration time. On Linux user can use @samp{vaapi} only as subdevice type.
|
||||
@end table
|
||||
Alternatively, @samp{child_device_type} helps to choose platform-appropriate subdevice type.
|
||||
On Windows @samp{d3d11va} is used as default subdevice type.
|
||||
|
||||
Examples:
|
||||
@table @emph
|
||||
@item -init_hw_device qsv:hw,child_device=/dev/dri/renderD129
|
||||
Create a QSV device with @samp{MFX_IMPL_HARDWARE} on DRM render node @file{/dev/dri/renderD129}.
|
||||
|
||||
@item -init_hw_device qsv:hw,child_device=1
|
||||
Create a QSV device with @samp{MFX_IMPL_HARDWARE} on DirectX adapter 1.
|
||||
|
||||
@item -init_hw_device qsv:hw,child_device_type=d3d11va
|
||||
Choose the GPU subdevice with type @samp{d3d11va} and create QSV device with @samp{MFX_IMPL_HARDWARE}.
|
||||
|
||||
@item -init_hw_device qsv:hw,child_device_type=dxva2
|
||||
Choose the GPU subdevice with type @samp{dxva2} and create QSV device with @samp{MFX_IMPL_HARDWARE}.
|
||||
|
||||
@item -init_hw_device qsv:hw,child_device=1,child_device_type=d3d11va
|
||||
Create a QSV device with @samp{MFX_IMPL_HARDWARE} on DirectX adapter 1 with subdevice type @samp{d3d11va}.
|
||||
|
||||
@item -init_hw_device vaapi=va:/dev/dri/renderD129 -init_hw_device qsv=hw1@@@var{va}
|
||||
Create a VAAPI device called @samp{va} on @file{/dev/dri/renderD129}, then derive a QSV device called @samp{hw1}
|
||||
from device @samp{va}.
|
||||
|
||||
@end table
|
||||
|
||||
@item opencl
|
||||
@@ -1742,21 +1409,14 @@ This is an alias for @code{-filter:a}, see the @ref{filter_option,,-filter optio
|
||||
@table @option
|
||||
@item -atag @var{fourcc/tag} (@emph{output})
|
||||
Force audio tag/fourcc. This is an alias for @code{-tag:a}.
|
||||
@item -ch_layout[:@var{stream_specifier}] @var{layout} (@emph{input/output,per-stream})
|
||||
Alias for @code{-channel_layout}.
|
||||
@item -channel_layout[:@var{stream_specifier}] @var{layout} (@emph{input/output,per-stream})
|
||||
Set the audio channel layout. For output streams it is set by default to the
|
||||
input channel layout. For input streams it overrides the channel layout of the
|
||||
input. Not all decoders respect the overridden channel layout. This option
|
||||
also sets the channel layout for audio grabbing devices and raw demuxers
|
||||
and is mapped to the corresponding demuxer option.
|
||||
@item -absf @var{bitstream_filter}
|
||||
Deprecated, see -bsf
|
||||
@item -guess_layout_max @var{channels} (@emph{input,per-stream})
|
||||
If some input channel layout is not known, try to guess only if it
|
||||
corresponds to at most the specified number of channels. For example, 2
|
||||
tells to @command{ffmpeg} to recognize 1 channel as mono and 2 channels as
|
||||
stereo but not 6 channels as 5.1. The default is to always try to guess. Use
|
||||
0 to disable all guessing. Using the @code{-channel_layout} option to
|
||||
explicitly specify an input layout also disables guessing.
|
||||
0 to disable all guessing.
|
||||
@end table
|
||||
|
||||
@section Subtitle options
|
||||
@@ -1772,6 +1432,8 @@ option to disable streams individually.
|
||||
As an output option, disables subtitle recording i.e. automatic selection or
|
||||
mapping of any subtitle stream. For full manual control see the @code{-map}
|
||||
option.
|
||||
@item -sbsf @var{bitstream_filter}
|
||||
Deprecated, see -bsf
|
||||
@end table
|
||||
|
||||
@section Advanced Subtitle options
|
||||
@@ -1799,12 +1461,13 @@ Set the size of the canvas used to render subtitles.
|
||||
@section Advanced options
|
||||
|
||||
@table @option
|
||||
@item -map [-]@var{input_file_id}[:@var{stream_specifier}][:@var{view_specifier}][?] | @var{[linklabel]} (@emph{output})
|
||||
@item -map [-]@var{input_file_id}[:@var{stream_specifier}][?] | @var{[linklabel]} (@emph{output})
|
||||
|
||||
Create one or more streams in the output file. This option has two forms for
|
||||
specifying the data source(s): the first selects one or more streams from some
|
||||
input file (specified with @code{-i}), the second takes an output from some
|
||||
complex filtergraph (specified with @code{-filter_complex}).
|
||||
complex filtergraph (specified with @code{-filter_complex} or
|
||||
@code{-filter_complex_script}).
|
||||
|
||||
In the first form, an output stream is created for every stream from the input
|
||||
file with the index @var{input_file_id}. If @var{stream_specifier} is given,
|
||||
@@ -1814,26 +1477,6 @@ only those streams that match the specifier are used (see the
|
||||
A @code{-} character before the stream identifier creates a "negative" mapping.
|
||||
It disables matching streams from already created mappings.
|
||||
|
||||
An optional @var{view_specifier} may be given after the stream specifier, which
|
||||
for multiview video specifies the view to be used. The view specifier may have
|
||||
one of the following formats:
|
||||
@table @option
|
||||
@item view:@var{view_id}
|
||||
select a view by its ID; @var{view_id} may be set to 'all' to use all the views
|
||||
interleaved into one stream;
|
||||
|
||||
@item vidx:@var{view_idx}
|
||||
select a view by its index; i.e. 0 is the base view, 1 is the first non-base
|
||||
view, etc.
|
||||
|
||||
@item vpos:@var{position}
|
||||
select a view by its display position; @var{position} may be @code{left} or
|
||||
@code{right}
|
||||
@end table
|
||||
The default for transcoding is to only use the base view, i.e. the equivalent of
|
||||
@code{vidx:0}. For streamcopy, view specifiers are not supported and all views
|
||||
are always copied.
|
||||
|
||||
A trailing @code{?} after the stream index will allow the map to be
|
||||
optional: if the map matches no streams the map will be ignored instead
|
||||
of failing. Note the map will still fail if an invalid input file index
|
||||
@@ -1916,6 +1559,77 @@ such streams is attempted.
|
||||
Allow input streams with unknown type to be copied instead of failing if copying
|
||||
such streams is attempted.
|
||||
|
||||
@item -map_channel [@var{input_file_id}.@var{stream_specifier}.@var{channel_id}|-1][?][:@var{output_file_id}.@var{stream_specifier}]
|
||||
This option is deprecated and will be removed. It can be replaced by the
|
||||
@var{pan} filter. In some cases it may be easier to use some combination of the
|
||||
@var{channelsplit}, @var{channelmap}, or @var{amerge} filters.
|
||||
|
||||
Map an audio channel from a given input to an output. If
|
||||
@var{output_file_id}.@var{stream_specifier} is not set, the audio channel will
|
||||
be mapped on all the audio streams.
|
||||
|
||||
Using "-1" instead of
|
||||
@var{input_file_id}.@var{stream_specifier}.@var{channel_id} will map a muted
|
||||
channel.
|
||||
|
||||
A trailing @code{?} will allow the map_channel to be
|
||||
optional: if the map_channel matches no channel the map_channel will be ignored instead
|
||||
of failing.
|
||||
|
||||
For example, assuming @var{INPUT} is a stereo audio file, you can switch the
|
||||
two audio channels with the following command:
|
||||
@example
|
||||
ffmpeg -i INPUT -map_channel 0.0.1 -map_channel 0.0.0 OUTPUT
|
||||
@end example
|
||||
|
||||
If you want to mute the first channel and keep the second:
|
||||
@example
|
||||
ffmpeg -i INPUT -map_channel -1 -map_channel 0.0.1 OUTPUT
|
||||
@end example
|
||||
|
||||
The order of the "-map_channel" option specifies the order of the channels in
|
||||
the output stream. The output channel layout is guessed from the number of
|
||||
channels mapped (mono if one "-map_channel", stereo if two, etc.). Using "-ac"
|
||||
in combination of "-map_channel" makes the channel gain levels to be updated if
|
||||
input and output channel layouts don't match (for instance two "-map_channel"
|
||||
options and "-ac 6").
|
||||
|
||||
You can also extract each channel of an input to specific outputs; the following
|
||||
command extracts two channels of the @var{INPUT} audio stream (file 0, stream 0)
|
||||
to the respective @var{OUTPUT_CH0} and @var{OUTPUT_CH1} outputs:
|
||||
@example
|
||||
ffmpeg -i INPUT -map_channel 0.0.0 OUTPUT_CH0 -map_channel 0.0.1 OUTPUT_CH1
|
||||
@end example
|
||||
|
||||
The following example splits the channels of a stereo input into two separate
|
||||
streams, which are put into the same output file:
|
||||
@example
|
||||
ffmpeg -i stereo.wav -map 0:0 -map 0:0 -map_channel 0.0.0:0.0 -map_channel 0.0.1:0.1 -y out.ogg
|
||||
@end example
|
||||
|
||||
Note that currently each output stream can only contain channels from a single
|
||||
input stream; you can't for example use "-map_channel" to pick multiple input
|
||||
audio channels contained in different streams (from the same or different files)
|
||||
and merge them into a single output stream. It is therefore not currently
|
||||
possible, for example, to turn two separate mono streams into a single stereo
|
||||
stream. However splitting a stereo stream into two single channel mono streams
|
||||
is possible.
|
||||
|
||||
If you need this feature, a possible workaround is to use the @emph{amerge}
|
||||
filter. For example, if you need to merge a media (here @file{input.mkv}) with 2
|
||||
mono audio streams into one single stereo channel audio stream (and keep the
|
||||
video stream), you can use the following command:
|
||||
@example
|
||||
ffmpeg -i input.mkv -filter_complex "[0:1] [0:2] amerge" -c:a pcm_s16le -c:v copy output.mkv
|
||||
@end example
|
||||
|
||||
To map the first two audio channels from the first input, and using the
|
||||
trailing @code{?}, ignore the audio channel mapping if the first input is
|
||||
mono instead of stereo:
|
||||
@example
|
||||
ffmpeg -i INPUT -map_channel 0.0.0 -map_channel 0.0.1? OUTPUT
|
||||
@end example
|
||||
|
||||
@item -map_metadata[:@var{metadata_spec_out}] @var{infile}[:@var{metadata_spec_in}] (@emph{output,per-metadata})
|
||||
Set metadata information of the next output file from @var{infile}. Note that
|
||||
those are file indices (zero-based), not filenames.
|
||||
@@ -2013,6 +1727,9 @@ constant frame rate.
|
||||
@item vfr (2)
|
||||
Frames are passed through with their timestamp or dropped so as to
|
||||
prevent 2 frames from having the same timestamp.
|
||||
@item drop
|
||||
As passthrough but destroys all timestamps, making the muxer generate
|
||||
fresh timestamps based on frame-rate.
|
||||
@item auto (-1)
|
||||
Chooses between cfr and vfr depending on muxer capabilities. This is the
|
||||
default method.
|
||||
@@ -2128,8 +1845,8 @@ of seconds.
|
||||
|
||||
The timestamp discontinuity correction enabled by this option is only
|
||||
applied to input formats accepting timestamp discontinuity (for which
|
||||
the @code{AVFMT_TS_DISCONT} flag is enabled), e.g. MPEG-TS and HLS, and
|
||||
is automatically disabled when employing the @code{-copyts} option
|
||||
the @code{AV_FMT_DISCONT} flag is enabled), e.g. MPEG-TS and HLS, and
|
||||
is automatically disabled when employing the @code{-copy_ts} option
|
||||
(unless wrapping is detected).
|
||||
|
||||
If a timestamp discontinuity is detected whose absolute value is
|
||||
@@ -2145,7 +1862,7 @@ seconds.
|
||||
|
||||
The timestamp correction enabled by this option is only applied to
|
||||
input formats not accepting timestamp discontinuity (for which the
|
||||
@code{AVFMT_TS_DISCONT} flag is not enabled).
|
||||
@code{AV_FMT_DISCONT} flag is not enabled).
|
||||
|
||||
If a timestamp discontinuity is detected whose absolute value is
|
||||
greater than @var{threshold}, ffmpeg will drop the PTS/DTS timestamp
|
||||
@@ -2170,36 +1887,16 @@ an output mpegts file:
|
||||
ffmpeg -i inurl -streamid 0:33 -streamid 1:36 out.ts
|
||||
@end example
|
||||
|
||||
@item -bsf[:@var{stream_specifier}] @var{bitstream_filters} (@emph{input/output,per-stream})
|
||||
Apply bitstream filters to matching streams. The filters are applied to each
|
||||
packet as it is received from the demuxer (when used as an input option) or
|
||||
before it is sent to the muxer (when used as an output option).
|
||||
|
||||
@var{bitstream_filters} is a comma-separated list of bitstream filter
|
||||
specifications, each of the form
|
||||
@item -bsf[:@var{stream_specifier}] @var{bitstream_filters} (@emph{output,per-stream})
|
||||
Set bitstream filters for matching streams. @var{bitstream_filters} is
|
||||
a comma-separated list of bitstream filters. Use the @code{-bsfs} option
|
||||
to get the list of bitstream filters.
|
||||
@example
|
||||
@var{filter}[=@var{optname0}=@var{optval0}:@var{optname1}=@var{optval1}:...]
|
||||
ffmpeg -i h264.mp4 -c:v copy -bsf:v h264_mp4toannexb -an out.h264
|
||||
@end example
|
||||
Any of the ',=:' characters that are to be a part of an option value need to be
|
||||
escaped with a backslash.
|
||||
|
||||
Use the @code{-bsfs} option to get the list of bitstream filters.
|
||||
|
||||
E.g.
|
||||
@example
|
||||
ffmpeg -bsf:v h264_mp4toannexb -i h264.mp4 -c:v copy -an out.h264
|
||||
@end example
|
||||
applies the @code{h264_mp4toannexb} bitstream filter (which converts
|
||||
MP4-encapsulated H.264 stream to Annex B) to the @emph{input} video stream.
|
||||
|
||||
On the other hand,
|
||||
@example
|
||||
ffmpeg -i file.mov -an -vn -bsf:s mov2textsub -c:s copy -f rawvideo sub.txt
|
||||
@end example
|
||||
applies the @code{mov2textsub} bitstream filter (which extracts text from MOV
|
||||
subtitles) to the @emph{output} subtitle stream. Note, however, that since both
|
||||
examples use @code{-c copy}, it matters little whether the filters are applied
|
||||
on input or output - that would change if transcoding was happening.
|
||||
|
||||
@item -tag[:@var{stream_specifier}] @var{codec_tag} (@emph{input/output,per-stream})
|
||||
Force a tag/fourcc for matching streams.
|
||||
@@ -2217,71 +1914,13 @@ Define a complex filtergraph, i.e. one with arbitrary number of inputs and/or
|
||||
outputs. For simple graphs -- those with one input and one output of the same
|
||||
type -- see the @option{-filter} options. @var{filtergraph} is a description of
|
||||
the filtergraph, as described in the ``Filtergraph syntax'' section of the
|
||||
ffmpeg-filters manual. This option may be specified multiple times - each use
|
||||
creates a new complex filtergraph.
|
||||
ffmpeg-filters manual.
|
||||
|
||||
Inputs to a complex filtergraph may come from different source types,
|
||||
distinguished by the format of the corresponding link label:
|
||||
@itemize
|
||||
@item
|
||||
To connect an input stream, use @code{[file_index:stream_specifier]} (i.e. the
|
||||
same syntax as @option{-map}). If @var{stream_specifier} matches multiple
|
||||
streams, the first one will be used. For multiview video, the stream specifier
|
||||
may be followed by the view specifier, see documentation for the @option{-map}
|
||||
option for its syntax.
|
||||
|
||||
@item
|
||||
To connect a loopback decoder use [dec:@var{dec_idx}], where @var{dec_idx} is
|
||||
the index of the loopback decoder to be connected to given input. For multiview
|
||||
video, the decoder index may be followed by the view specifier, see
|
||||
documentation for the @option{-map} option for its syntax.
|
||||
|
||||
@item
|
||||
To connect an output from another complex filtergraph, use its link label. E.g
|
||||
the following example:
|
||||
|
||||
@example
|
||||
ffmpeg -i input.mkv \
|
||||
-filter_complex '[0:v]scale=size=hd1080,split=outputs=2[for_enc][orig_scaled]' \
|
||||
-c:v libx264 -map '[for_enc]' output.mkv \
|
||||
-dec 0:0 \
|
||||
-filter_complex '[dec:0][orig_scaled]hstack[stacked]' \
|
||||
-map '[stacked]' -c:v ffv1 comparison.mkv
|
||||
@end example
|
||||
|
||||
reads an input video and
|
||||
@itemize
|
||||
@item
|
||||
(line 2) uses a complex filtergraph with one input and two outputs
|
||||
to scale the video to 1920x1080 and duplicate the result to both
|
||||
outputs;
|
||||
|
||||
@item
|
||||
(line 3) encodes one scaled output with @code{libx264} and writes the result to
|
||||
@file{output.mkv};
|
||||
|
||||
@item
|
||||
(line 4) decodes this encoded stream with a loopback decoder;
|
||||
|
||||
@item
|
||||
(line 5) places the output of the loopback decoder (i.e. the
|
||||
@code{libx264}-encoded video) side by side with the scaled original input;
|
||||
|
||||
@item
|
||||
(line 6) combined video is then losslessly encoded and written into
|
||||
@file{comparison.mkv}.
|
||||
|
||||
@end itemize
|
||||
|
||||
Note that the two filtergraphs cannot be combined into one, because then there
|
||||
would be a cycle in the transcoding pipeline (filtergraph output goes to
|
||||
encoding, from there to decoding, then back to the same graph), and such cycles
|
||||
are not allowed.
|
||||
|
||||
@end itemize
|
||||
|
||||
An unlabeled input will be connected to the first unused input stream of the
|
||||
matching type.
|
||||
Input link labels must refer to input streams using the
|
||||
@code{[file_index:stream_specifier]} syntax (i.e. the same as @option{-map}
|
||||
uses). If @var{stream_specifier} matches multiple streams, the first one will be
|
||||
used. An unlabeled input will be connected to the first unused input stream of
|
||||
the matching type.
|
||||
|
||||
Output link labels are referred to with @option{-map}. Unlabeled outputs are
|
||||
added to the first output file.
|
||||
@@ -2342,6 +1981,12 @@ The default is the number of available CPUs.
|
||||
Define a complex filtergraph, i.e. one with arbitrary number of inputs and/or
|
||||
outputs. Equivalent to @option{-filter_complex}.
|
||||
|
||||
@anchor{filter_complex_script option}
|
||||
@item -filter_complex_script @var{filename} (@emph{global})
|
||||
This option is similar to @option{-filter_complex}, the only difference is that
|
||||
its argument is the name of the file from which a complex filtergraph
|
||||
description is to be read.
|
||||
|
||||
@item -accurate_seek (@emph{input})
|
||||
This option enables or disables accurate seeking in input files with the
|
||||
@option{-ss} option. It is enabled by default, so seeking is accurate when
|
||||
@@ -2535,14 +2180,11 @@ Number of audio samples in the frame.
|
||||
Size of the encoded packet in bytes.
|
||||
|
||||
@item br (@emph{packet})
|
||||
Current bitrate in bits per second.
|
||||
Current bitrate in bits per second. Post-encoding only.
|
||||
|
||||
@item abr (@emph{packet})
|
||||
Average bitrate for the whole stream so far, in bits per second, -1 if it cannot
|
||||
be determined at this point.
|
||||
|
||||
@item key (@emph{packet})
|
||||
Character 'K' if the packet contains a keyframe, character 'N' otherwise.
|
||||
be determined at this point. Post-encoding only.
|
||||
@end table
|
||||
|
||||
Directives tagged with @emph{packet} may only be used with
|
||||
|
||||
@@ -196,18 +196,6 @@ will produce a thread pool with this many threads available for parallel
|
||||
processing. The default is 0 which means that the thread count will be
|
||||
determined by the number of available CPUs.
|
||||
|
||||
@item -enable_vulkan
|
||||
Use vulkan renderer rather than SDL builtin renderer. Depends on libplacebo.
|
||||
|
||||
@item -vulkan_params
|
||||
|
||||
Vulkan configuration using a list of @var{key}=@var{value} pairs separated by
|
||||
":".
|
||||
|
||||
@item -hwaccel
|
||||
Use HW accelerated decoding. Enable this option will enable vulkan renderer
|
||||
automatically.
|
||||
|
||||
@end table
|
||||
|
||||
@section While playing
|
||||
|
||||
+4
-12
@@ -48,8 +48,8 @@ name (which may be shared by other sections), and an unique
|
||||
name. See the output of @option{sections}.
|
||||
|
||||
Metadata tags stored in the container or in the streams are recognized
|
||||
and printed in the corresponding "FORMAT", "STREAM", "STREAM_GROUP_STREAM"
|
||||
or "PROGRAM_STREAM" section.
|
||||
and printed in the corresponding "FORMAT", "STREAM" or "PROGRAM_STREAM"
|
||||
section.
|
||||
|
||||
@c man end
|
||||
|
||||
@@ -232,13 +232,6 @@ multimedia stream.
|
||||
Each media stream information is printed within a dedicated section
|
||||
with name "PROGRAM_STREAM".
|
||||
|
||||
@item -show_stream_groups
|
||||
Show information about stream groups and their streams contained in the
|
||||
input multimedia stream.
|
||||
|
||||
Each media stream information is printed within a dedicated section
|
||||
with name "STREAM_GROUP_STREAM".
|
||||
|
||||
@item -show_chapters
|
||||
Show information about chapters stored in the format.
|
||||
|
||||
@@ -422,9 +415,8 @@ keyN=valN
|
||||
[/SECTION]
|
||||
@end example
|
||||
|
||||
Metadata tags are printed as a line in the corresponding FORMAT, STREAM,
|
||||
STREAM_GROUP_STREAM or PROGRAM_STREAM section, and are prefixed by the
|
||||
string "TAG:".
|
||||
Metadata tags are printed as a line in the corresponding FORMAT, STREAM or
|
||||
PROGRAM_STREAM section, and are prefixed by the string "TAG:".
|
||||
|
||||
A description of the accepted options follows.
|
||||
|
||||
|
||||
+4
-123
@@ -15,7 +15,6 @@
|
||||
<xsd:element name="frames" type="ffprobe:framesType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="packets_and_frames" type="ffprobe:packetsAndFramesType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="programs" type="ffprobe:programsType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="stream_groups" type="ffprobe:StreamGroupsType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="streams" type="ffprobe:streamsType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="chapters" type="ffprobe:chaptersType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="format" type="ffprobe:formatType" minOccurs="0" maxOccurs="1" />
|
||||
@@ -106,6 +105,8 @@
|
||||
<xsd:attribute name="pkt_dts_time" type="xsd:float"/>
|
||||
<xsd:attribute name="best_effort_timestamp" type="xsd:long" />
|
||||
<xsd:attribute name="best_effort_timestamp_time" type="xsd:float" />
|
||||
<xsd:attribute name="pkt_duration" type="xsd:long" />
|
||||
<xsd:attribute name="pkt_duration_time" type="xsd:float"/>
|
||||
<xsd:attribute name="duration" type="xsd:long" />
|
||||
<xsd:attribute name="duration_time" type="xsd:float"/>
|
||||
<xsd:attribute name="pkt_pos" type="xsd:long" />
|
||||
@@ -127,6 +128,8 @@
|
||||
<xsd:attribute name="pix_fmt" type="xsd:string"/>
|
||||
<xsd:attribute name="sample_aspect_ratio" type="xsd:string"/>
|
||||
<xsd:attribute name="pict_type" type="xsd:string"/>
|
||||
<xsd:attribute name="coded_picture_number" type="xsd:long" />
|
||||
<xsd:attribute name="display_picture_number" type="xsd:long" />
|
||||
<xsd:attribute name="interlaced_frame" type="xsd:int" />
|
||||
<xsd:attribute name="top_field_first" type="xsd:int" />
|
||||
<xsd:attribute name="repeat_pict" type="xsd:int" />
|
||||
@@ -159,8 +162,6 @@
|
||||
<xsd:complexType name="frameSideDataType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="timecodes" type="ffprobe:frameSideDataTimecodeList" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="components" type="ffprobe:frameSideDataComponentList" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="side_datum" type="ffprobe:frameSideDatumType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
|
||||
<xsd:attribute name="side_data_type" type="xsd:string"/>
|
||||
@@ -168,11 +169,6 @@
|
||||
<xsd:attribute name="timecode" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="frameSideDatumType">
|
||||
<xsd:attribute name="key" type="xsd:string"/>
|
||||
<xsd:attribute name="value" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="frameSideDataTimecodeList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="timecode" type="ffprobe:frameSideDataTimecodeType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
@@ -183,31 +179,6 @@
|
||||
<xsd:attribute name="value" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="frameSideDataComponentList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="component" type="ffprobe:frameSideDataComponentType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="frameSideDataComponentType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="pieces" type="ffprobe:frameSideDataPieceList" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="side_datum" type="ffprobe:frameSideDatumType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="frameSideDataPieceList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="piece" type="ffprobe:frameSideDataPieceType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="frameSideDataPieceType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="side_datum" type="ffprobe:frameSideDatumType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="subtitleType">
|
||||
<xsd:attribute name="media_type" type="xsd:string" fixed="subtitle" use="required"/>
|
||||
<xsd:attribute name="pts" type="xsd:long" />
|
||||
@@ -230,12 +201,6 @@
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="StreamGroupsType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="stream_group" type="ffprobe:streamGroupType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamDispositionType">
|
||||
<xsd:attribute name="default" type="xsd:int" use="required" />
|
||||
<xsd:attribute name="dub" type="xsd:int" use="required" />
|
||||
@@ -255,7 +220,6 @@
|
||||
<xsd:attribute name="metadata" type="xsd:int" use="required" />
|
||||
<xsd:attribute name="dependent" type="xsd:int" use="required" />
|
||||
<xsd:attribute name="still_image" type="xsd:int" use="required" />
|
||||
<xsd:attribute name="multilayer" type="xsd:int" use="required" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamType">
|
||||
@@ -333,88 +297,6 @@
|
||||
<xsd:attribute name="pcr_pid" type="xsd:int" use="required"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamGroupType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="disposition" type="ffprobe:streamDispositionType" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="streams" type="ffprobe:streamsType" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="components" type="ffprobe:streamGroupComponentList" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
|
||||
<xsd:attribute name="index" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="nb_streams" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="type" type="xsd:string" use="required"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamGroupComponentList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="component" type="ffprobe:streamGroupComponentType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamGroupComponentType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="subcomponents" type="ffprobe:streamGroupSubComponentList" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="component_entry" type="ffprobe:streamGroupEntryType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamGroupSubComponentList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="subcomponent" type="ffprobe:streamGroupSubComponentType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamGroupSubComponentType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="pieces" type="ffprobe:streamGroupPieceList" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="subcomponent_entry" type="ffprobe:streamGroupEntryType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamGroupPieceList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="piece" type="ffprobe:streamGroupPieceType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamGroupPieceType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="subpieces" type="ffprobe:streamGroupSubPieceList" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="piece_entry" type="ffprobe:streamGroupEntryType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamGroupSubPieceList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="subpiece" type="ffprobe:streamGroupSubPieceType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamGroupSubPieceType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="blocks" type="ffprobe:streamGroupBlockList" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="subpiece_entry" type="ffprobe:streamGroupEntryType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamGroupBlockList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="block" type="ffprobe:streamGroupBlockType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamGroupBlockType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="block_entry" type="ffprobe:streamGroupEntryType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="streamGroupEntryType">
|
||||
<xsd:attribute name="key" type="xsd:string"/>
|
||||
<xsd:attribute name="value" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="formatType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="1"/>
|
||||
@@ -423,7 +305,6 @@
|
||||
<xsd:attribute name="filename" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="nb_streams" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="nb_programs" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="nb_stream_groups" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="format_name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="format_long_name" type="xsd:string"/>
|
||||
<xsd:attribute name="start_time" type="xsd:float"/>
|
||||
|
||||
@@ -13,15 +13,6 @@ corresponding value to true. They can be set to false by prefixing
|
||||
the option name with "no". For example using "-nofoo"
|
||||
will set the boolean option with name "foo" to false.
|
||||
|
||||
Options that take arguments support a special syntax where the argument given on
|
||||
the command line is interpreted as a path to the file from which the actual
|
||||
argument value is loaded. To use this feature, add a forward slash '/'
|
||||
immediately before the option name (after the leading dash). E.g.
|
||||
@example
|
||||
ffmpeg -i INPUT -/filter:v filter.script OUTPUT
|
||||
@end example
|
||||
will load a filtergraph description from the file named @file{filter.script}.
|
||||
|
||||
@anchor{Stream specifiers}
|
||||
@section Stream specifiers
|
||||
Some options are applied per-stream, e.g. bitrate or codec. Stream specifiers
|
||||
@@ -46,9 +37,9 @@ Matches the stream with this index. E.g. @code{-threads:1 4} would set the
|
||||
thread count for the second stream to 4. If @var{stream_index} is used as an
|
||||
additional stream specifier (see below), then it selects stream number
|
||||
@var{stream_index} from the matching streams. Stream numbering is based on the
|
||||
order of the streams as detected by libavformat except when a stream group
|
||||
specifier or program ID is also specified. In this case it is based on the
|
||||
ordering of the streams in the group or program.
|
||||
order of the streams as detected by libavformat except when a program ID is
|
||||
also specified. In this case it is based on the ordering of the streams in the
|
||||
program.
|
||||
@item @var{stream_type}[:@var{additional_stream_specifier}]
|
||||
@var{stream_type} is one of following: 'v' or 'V' for video, 'a' for audio, 's'
|
||||
for subtitle, 'd' for data, and 't' for attachments. 'v' matches all video
|
||||
@@ -57,17 +48,6 @@ thumbnails or cover arts. If @var{additional_stream_specifier} is used, then
|
||||
it matches streams which both have this type and match the
|
||||
@var{additional_stream_specifier}. Otherwise, it matches all streams of the
|
||||
specified type.
|
||||
@item g:@var{group_specifier}[:@var{additional_stream_specifier}]
|
||||
Matches streams which are in the group with the specifier @var{group_specifier}.
|
||||
if @var{additional_stream_specifier} is used, then it matches streams which both
|
||||
are part of the group and match the @var{additional_stream_specifier}.
|
||||
@var{group_specifier} may be one of the following:
|
||||
@table @option
|
||||
@item @var{group_index}
|
||||
Match the stream with this group index.
|
||||
@item #@var{group_id} or i:@var{group_id}
|
||||
Match the stream with this group id.
|
||||
@end table
|
||||
@item p:@var{program_id}[:@var{additional_stream_specifier}]
|
||||
Matches streams which are in the program with the id @var{program_id}. If
|
||||
@var{additional_stream_specifier} is used, then it matches streams which both
|
||||
@@ -79,10 +59,6 @@ Match the stream by stream id (e.g. PID in MPEG-TS container).
|
||||
Matches streams with the metadata tag @var{key} having the specified value. If
|
||||
@var{value} is not given, matches streams that contain the given tag with any
|
||||
value.
|
||||
@item disp:@var{dispositions}[:@var{additional_stream_specifier}]
|
||||
Matches streams with the given disposition(s). @var{dispositions} is a list of
|
||||
one or more dispositions (as printed by the @option{-dispositions} option)
|
||||
joined with '+'.
|
||||
@item u
|
||||
Matches streams with usable configuration, the codec must be defined and the
|
||||
essential information such as video dimension or audio sample rate must be present.
|
||||
|
||||
+186
-1258
File diff suppressed because it is too large
Load Diff
+2
-20
@@ -46,8 +46,7 @@ Enable fast, but inaccurate seeks for some formats.
|
||||
@item genpts
|
||||
Generate missing PTS if DTS is present.
|
||||
@item igndts
|
||||
Ignore DTS if PTS is also set. In case the PTS is set, the DTS value
|
||||
is set to NOPTS. This is ignored when the @code{nofillin} flag is set.
|
||||
Ignore DTS if PTS is set. Inert when nofillin is set.
|
||||
@item ignidx
|
||||
Ignore index.
|
||||
@item nobuffer
|
||||
@@ -225,26 +224,9 @@ Specifies the maximum number of streams. This can be used to reject files that
|
||||
would require too many resources due to a large number of streams.
|
||||
|
||||
@item skip_estimate_duration_from_pts @var{bool} (@emph{input})
|
||||
Skip estimation of input duration if it requires an additional probing for PTS at end of file.
|
||||
Skip estimation of input duration when calculated using PTS.
|
||||
At present, applicable for MPEG-PS and MPEG-TS.
|
||||
|
||||
@item duration_probesize @var{integer} (@emph{input})
|
||||
Set probing size, in bytes, for input duration estimation when it actually requires
|
||||
an additional probing for PTS at end of file (at present: MPEG-PS and MPEG-TS).
|
||||
It is aimed at users interested in better durations probing for itself, or indirectly
|
||||
because using the concat demuxer, for example.
|
||||
The typical use case is an MPEG-TS CBR with a high bitrate, high video buffering and
|
||||
ending cleaning with similar PTS for video and audio: in such a scenario, the large
|
||||
physical gap between the last video packet and the last audio packet makes it necessary
|
||||
to read many bytes in order to get the video stream duration.
|
||||
Another use case is where the default probing behaviour only reaches a single video frame which is
|
||||
not the last one of the stream due to frame reordering, so the duration is not accurate.
|
||||
Setting this option has a performance impact even for small files because the probing
|
||||
size is fixed.
|
||||
Default behaviour is a general purpose trade-off, largely adaptive, but the probing size
|
||||
will not be extended to get streams durations at all costs.
|
||||
Must be an integer not lesser than 1, or 0 for default behaviour.
|
||||
|
||||
@item strict, f_strict @var{integer} (@emph{input/output})
|
||||
Specify how strictly to follow the standards. @code{f_strict} is deprecated and
|
||||
should be used only via the @command{ffmpeg} tool.
|
||||
|
||||
@@ -160,19 +160,6 @@ Go to @url{http://lame.sourceforge.net/} and follow the
|
||||
instructions for installing the library.
|
||||
Then pass @code{--enable-libmp3lame} to configure to enable it.
|
||||
|
||||
@section LCEVCdec
|
||||
|
||||
FFmpeg can make use of the liblcevc_dec library for LCEVC enhacement layer
|
||||
decoding on supported bitstreams.
|
||||
|
||||
Go to @url{https://github.com/v-novaltd/LCEVCdec} and follow the instructions
|
||||
for installing the library. Then pass @code{--enable-liblcevc-dec} to configure to
|
||||
enable it.
|
||||
|
||||
@float NOTE
|
||||
LCEVCdec is under the BSD-3-Clause-Clear License.
|
||||
@end float
|
||||
|
||||
@section libilbc
|
||||
|
||||
iLBC is a narrowband speech codec that has been made freely available
|
||||
@@ -250,14 +237,6 @@ Go to @url{http://sourceforge.net/projects/opencore-amr/} and follow the
|
||||
instructions for installing the library.
|
||||
Then pass @code{--enable-libfdk-aac} to configure to enable it.
|
||||
|
||||
@subsection LC3 library
|
||||
|
||||
FFmpeg can make use of the Google LC3 library for LC3 decoding & encoding.
|
||||
|
||||
Go to @url{https://github.com/google/liblc3/} and follow the instructions for
|
||||
installing the library.
|
||||
Then pass @code{--enable-liblc3} to configure to enable it.
|
||||
|
||||
@section OpenH264
|
||||
|
||||
FFmpeg can make use of the OpenH264 library for H.264 decoding and encoding.
|
||||
@@ -364,22 +343,6 @@ libxavs2 is under the GNU Public License Version 2 or later
|
||||
details), you must upgrade FFmpeg's license to GPL in order to use it.
|
||||
@end float
|
||||
|
||||
@section eXtra-fast Essential Video Encoder (XEVE)
|
||||
|
||||
FFmpeg can make use of the XEVE library for EVC video encoding.
|
||||
|
||||
Go to @url{https://github.com/mpeg5/xeve} and follow the instructions for
|
||||
installing the XEVE library. Then pass @code{--enable-libxeve} to configure to
|
||||
enable it.
|
||||
|
||||
@section eXtra-fast Essential Video Decoder (XEVD)
|
||||
|
||||
FFmpeg can make use of the XEVD library for EVC video decoding.
|
||||
|
||||
Go to @url{https://github.com/mpeg5/xevd} and follow the instructions for
|
||||
installing the XEVD library. Then pass @code{--enable-libxevd} to configure to
|
||||
enable it.
|
||||
|
||||
@section ZVBI
|
||||
|
||||
ZVBI is a VBI decoding library which can be used by FFmpeg to decode DVB
|
||||
@@ -635,7 +598,6 @@ library:
|
||||
@item raw DTS @tab X @tab X
|
||||
@item raw DTS-HD @tab @tab X
|
||||
@item raw E-AC-3 @tab X @tab X
|
||||
@item raw EVC @tab X @tab X
|
||||
@item raw FLAC @tab X @tab X
|
||||
@item raw GSM @tab @tab X
|
||||
@item raw H.261 @tab X @tab X
|
||||
@@ -691,8 +653,7 @@ library:
|
||||
@item Redirector @tab @tab X
|
||||
@item RedSpark @tab @tab X
|
||||
@item Renderware TeXture Dictionary @tab @tab X
|
||||
@item Resolume DXV @tab X @tab X
|
||||
@tab Encoding is only supported for the DXT1 (Normal Quality, No Alpha) texture format.
|
||||
@item Resolume DXV @tab @tab X
|
||||
@item RF64 @tab @tab X
|
||||
@item RL2 @tab @tab X
|
||||
@tab Audio and video format used in some games by Entertainment Software Partners.
|
||||
@@ -983,8 +944,6 @@ following image formats are supported:
|
||||
@item Electronic Arts TQI video @tab @tab X
|
||||
@item Escape 124 @tab @tab X
|
||||
@item Escape 130 @tab @tab X
|
||||
@item EVC / MPEG-5 Part 1 @tab E @tab E
|
||||
@tab encoding and decoding supported through external libraries libxeve and libxevd
|
||||
@item FFmpeg video codec #1 @tab X @tab X
|
||||
@tab lossless codec (fourcc: FFV1)
|
||||
@item Flash Screen Video v1 @tab X @tab X
|
||||
@@ -1036,11 +995,8 @@ following image formats are supported:
|
||||
@item Kega Game Video (KGV1) @tab @tab X
|
||||
@tab Kega emulator screen capture codec.
|
||||
@item Lagarith @tab @tab X
|
||||
@item LCEVC / MPEG-5 LCEVC / MPEG-5 Part 2 @tab @tab E
|
||||
@tab decoding supported through external library liblcevc-dec
|
||||
@item LCL (LossLess Codec Library) MSZH @tab @tab X
|
||||
@item LCL (LossLess Codec Library) ZLIB @tab E @tab E
|
||||
@item LEAD MCMP @tab @tab X
|
||||
@item LOCO @tab @tab X
|
||||
@item LucasArts SANM/Smush @tab @tab X
|
||||
@tab Used in LucasArts games / SMUSH animations.
|
||||
@@ -1323,8 +1279,7 @@ following image formats are supported:
|
||||
@tab encoding and decoding supported through external library libilbc
|
||||
@item IMC (Intel Music Coder) @tab @tab X
|
||||
@item Interplay ACM @tab @tab X
|
||||
@item LC3 @tab E @tab E
|
||||
@tab supported through external library liblc3
|
||||
@item MACE (Macintosh Audio Compression/Expansion) 3:1 @tab @tab X
|
||||
@item MACE (Macintosh Audio Compression/Expansion) 6:1 @tab @tab X
|
||||
@item Marian's A-pac audio @tab @tab X
|
||||
@item MI-SC4 (Micronas SC-4 Audio) @tab @tab X
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ This will put the FFmpeg sources into the directory @var{<target>} and let
|
||||
you push back your changes to the remote repository.
|
||||
|
||||
@example
|
||||
git clone git@@ffmpeg.org:ffmpeg-web <target>
|
||||
git clone gil@@ffmpeg.org:ffmpeg-web <target>
|
||||
@end example
|
||||
|
||||
This will put the source of the FFmpeg website into the directory
|
||||
|
||||
+5
-26
@@ -222,8 +222,7 @@ $ ffmpeg -f avfoundation -capture_raw_data true -i "zr100:none" out.dv
|
||||
|
||||
@section bktr
|
||||
|
||||
BSD video input device. Deprecated and will be removed - please contact
|
||||
the developers if you are interested in maintaining it.
|
||||
BSD video input device.
|
||||
|
||||
@subsection Options
|
||||
|
||||
@@ -396,22 +395,6 @@ Defaults to @samp{audio}.
|
||||
@item draw_bars
|
||||
If set to @samp{true}, color bars are drawn in the event of a signal loss.
|
||||
Defaults to @samp{true}.
|
||||
This option is deprecated, please use the @code{signal_loss_action} option.
|
||||
|
||||
@item signal_loss_action
|
||||
Sets the action to take in the event of a signal loss. Accepts one of the
|
||||
following values:
|
||||
|
||||
@table @option
|
||||
@item 1, none
|
||||
Do nothing on signal loss. This usually results in black frames.
|
||||
@item 2, bars
|
||||
Draw color bars on signal loss. Only supported for 8-bit input signals.
|
||||
@item 3, repeat
|
||||
Repeat the last video frame on signal loss.
|
||||
@end table
|
||||
|
||||
Defaults to @samp{bars}.
|
||||
|
||||
@item queue_size
|
||||
Sets maximum input buffer size in bytes. If the buffering reaches this value,
|
||||
@@ -739,7 +722,7 @@ Win32 GDI-based screen capture device.
|
||||
|
||||
This device allows you to capture a region of the display on Windows.
|
||||
|
||||
Amongst options for the imput filenames are such elements as:
|
||||
There are two options for the input filename:
|
||||
@example
|
||||
desktop
|
||||
@end example
|
||||
@@ -747,13 +730,9 @@ or
|
||||
@example
|
||||
title=@var{window_title}
|
||||
@end example
|
||||
or
|
||||
@example
|
||||
hwnd=@var{window_hwnd}
|
||||
@end example
|
||||
|
||||
The first option will capture the entire desktop, or a fixed region of the
|
||||
desktop. The second and third options will instead capture the contents of a single
|
||||
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}:
|
||||
@@ -1085,9 +1064,9 @@ ffplay -f lavfi "movie=test.avi[out0];amovie=test.wav[out1]"
|
||||
@end example
|
||||
|
||||
@item
|
||||
Dump decoded frames to images and Closed Captions to an RCWT backup:
|
||||
Dump decoded frames to images and closed captions to a file (experimental):
|
||||
@example
|
||||
ffmpeg -f lavfi -i "movie=test.ts[out0+subcc]" -map v frame%08d.png -map s -c copy -f rcwt subcc.bin
|
||||
ffmpeg -f lavfi -i "movie=test.ts[out0+subcc]" -map v frame%08d.png -map s -c copy -f rawvideo subcc.bin
|
||||
@end example
|
||||
|
||||
@end itemize
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
FFmpeg Infrastructure:
|
||||
======================
|
||||
|
||||
|
||||
|
||||
|
||||
Servers:
|
||||
~~~~~~~~
|
||||
|
||||
|
||||
Main Server:
|
||||
------------
|
||||
Our Main server is hosted at telepoint.bg
|
||||
for more details see: https://www.ffmpeg.org/#thanks_sponsor_0001
|
||||
Nothing runs on our main server directly, instead several VMs run on it.
|
||||
|
||||
|
||||
ffmpeg.org VM:
|
||||
--------------
|
||||
Web, mail, and public facing git, also website git
|
||||
|
||||
|
||||
fftrac VM:
|
||||
----------
|
||||
trac.ffmpeg.org Issue tracking
|
||||
|
||||
|
||||
ffaux VM:
|
||||
---------
|
||||
patchwork.ffmpeg.org Patch tracking
|
||||
vote.ffmpeg.org Condorcet voting
|
||||
|
||||
|
||||
fate:
|
||||
-----
|
||||
fate.ffmpeg.org FFmpeg automated testing environment
|
||||
|
||||
|
||||
coverage:
|
||||
---------
|
||||
coverage.ffmpeg.org Fate code coverage
|
||||
|
||||
|
||||
The main and fate server as well as VMs currently run ubuntu
|
||||
|
||||
|
||||
|
||||
Cronjobs:
|
||||
~~~~~~~~~
|
||||
Part of the docs is in the main ffmpeg repository as texi files, this part is build by a cronjob. So is the
|
||||
doxygen stuff as well as the FFmpeg git snapshot.
|
||||
These 3 scripts are under the ffcron user
|
||||
|
||||
|
||||
|
||||
Git:
|
||||
~~~~
|
||||
Public facing git is provided by our infra, (https://git.ffmpeg.org/gitweb)
|
||||
main developer ffmpeg git repository for historic reasons is provided by (git@source.ffmpeg.org:ffmpeg)
|
||||
Other developer git repositories are provided via git@git.ffmpeg.org:<NAME_OF_REPOSITORY>
|
||||
git mirrors are available on https://github.com/FFmpeg
|
||||
(there are some exceptions where primary repositories are on github or elsewhere instead of the mirrors)
|
||||
|
||||
Github mirrors are redundantly synced by multiple people
|
||||
|
||||
You need a new git repository related to FFmpeg ? contact root at ffmpeg.org
|
||||
|
||||
|
||||
Fate:
|
||||
~~~~~
|
||||
fatesamples are provided via rsync. Every FFmpeg developer who has a shell account in ffmpeg.org
|
||||
should be in the samples group and be able to upload samples.
|
||||
See https://www.ffmpeg.org/fate.html#Uploading-new-samples-to-the-fate-suite
|
||||
|
||||
|
||||
|
||||
Accounts:
|
||||
~~~~~~~~~
|
||||
You need an account for some FFmpeg work? Send mail to root at ffmpeg.org
|
||||
|
||||
|
||||
|
||||
VMs:
|
||||
~~~~
|
||||
You need a VM, docker container for FFmpeg? contact root at ffmpeg.org
|
||||
(for docker, CC Andriy)
|
||||
|
||||
|
||||
|
||||
IRC:
|
||||
~~~~
|
||||
irc channels are at https://libera.chat/
|
||||
irc channel archives are at https://libera.irclog.whitequark.org
|
||||
|
||||
@@ -157,6 +157,9 @@ Perform a site search using your favorite search engine. Example:
|
||||
|
||||
You can ask for help in the official @t{#ffmpeg} IRC channel on Libera Chat.
|
||||
|
||||
Some users prefer the third-party @url{http://www.ffmpeg-archive.org/, Nabble}
|
||||
interface which presents the mailing lists in a typical forum layout.
|
||||
|
||||
There are also numerous third-party help sites such as
|
||||
@url{https://superuser.com/tags/ffmpeg, Super User} and
|
||||
@url{https://www.reddit.com/r/ffmpeg/, r/ffmpeg on reddit}.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
@anchor{metadata}
|
||||
@chapter Metadata
|
||||
@c man begin METADATA
|
||||
|
||||
|
||||
@@ -49,6 +49,11 @@ Files that have MIPS copyright notice in them:
|
||||
libm_mips.h
|
||||
softfloat_tables.h
|
||||
* libavcodec/mips/
|
||||
aacdec_fixed.c
|
||||
aacsbr_fixed.c
|
||||
aacsbr_template.c
|
||||
aaccoder_mips.c
|
||||
aacpsy_mips.h
|
||||
ac3dsp_mips.c
|
||||
acelp_filters_mips.c
|
||||
acelp_vectors_mips.c
|
||||
@@ -59,6 +64,7 @@ Files that have MIPS copyright notice in them:
|
||||
compute_antialias_fixed.h
|
||||
compute_antialias_float.h
|
||||
lsp_mips.h
|
||||
dsputil_mips.c
|
||||
fmtconvert_mips.c
|
||||
iirfilter_mips.c
|
||||
mpegaudiodsp_mips_fixed.c
|
||||
|
||||
@@ -36,9 +36,9 @@ Frame threading -
|
||||
* Codecs similar to ffv1, whose streams don't reset across frames,
|
||||
will not work because their bitstreams cannot be decoded in parallel.
|
||||
|
||||
* The contents of buffers must not be read before ff_progress_frame_await()
|
||||
* The contents of buffers must not be read before ff_thread_await_progress()
|
||||
has been called on them. reget_buffer() and buffer age optimizations no longer work.
|
||||
* The contents of buffers must not be written to after ff_progress_frame_report()
|
||||
* The contents of buffers must not be written to after ff_thread_report_progress()
|
||||
has been called on them. This includes draw_edges().
|
||||
|
||||
Porting codecs to frame threading
|
||||
@@ -53,13 +53,14 @@ thread.
|
||||
Add AV_CODEC_CAP_FRAME_THREADS to the codec capabilities. There will be very little
|
||||
speed gain at this point but it should work.
|
||||
|
||||
Use ff_thread_get_buffer() (or ff_progress_frame_get_buffer()
|
||||
in case you have inter-frame dependencies and use the ProgressFrame API)
|
||||
to allocate frame buffers.
|
||||
If there are inter-frame dependencies, so the codec calls
|
||||
ff_thread_report/await_progress(), set FF_CODEC_CAP_ALLOCATE_PROGRESS in
|
||||
FFCodec.caps_internal and use ff_thread_get_buffer() to allocate frames.
|
||||
Otherwise decode directly into the user-supplied frames.
|
||||
|
||||
Call ff_progress_frame_report() after some part of the current picture has decoded.
|
||||
Call ff_thread_report_progress() after some part of the current picture has decoded.
|
||||
A good place to put this is where draw_horiz_band() is called - add this if it isn't
|
||||
called anywhere, as it's useful too and the implementation is trivial when you're
|
||||
doing this. Note that draw_edges() needs to be called before reporting progress.
|
||||
|
||||
Before accessing a reference frame or its MVs, call ff_progress_frame_await().
|
||||
Before accessing a reference frame or its MVs, call ff_thread_await_progress().
|
||||
|
||||
+842
-1874
File diff suppressed because it is too large
Load Diff
+2
-8
@@ -302,7 +302,7 @@ ffmpeg -re -i INPUT -c:v rawvideo -pix_fmt bgra -f fbdev /dev/fb0
|
||||
See also @url{http://linux-fbdev.sourceforge.net/}, and fbset(1).
|
||||
|
||||
@section opengl
|
||||
OpenGL output device. Deprecated and will be removed.
|
||||
OpenGL output device.
|
||||
|
||||
To enable this output device you need to configure FFmpeg with @code{--enable-opengl}.
|
||||
|
||||
@@ -408,13 +408,7 @@ ffmpeg -i INPUT -f pulse "stream name"
|
||||
|
||||
@section sdl
|
||||
|
||||
SDL (Simple DirectMedia Layer) output device. Deprecated and will be removed.
|
||||
|
||||
For monitoring purposes in FFmpeg, pipes and a video player such as ffplay can be used:
|
||||
|
||||
@example
|
||||
ffmpeg -i INPUT -f nut -c:v rawvideo - | ffplay -
|
||||
@end example
|
||||
SDL (Simple DirectMedia Layer) output device.
|
||||
|
||||
"sdl2" can be used as alias for "sdl".
|
||||
|
||||
|
||||
+55
-88
@@ -442,6 +442,9 @@ value is -1.
|
||||
@item chunked_post
|
||||
If set to 1 use chunked Transfer-Encoding for posts, default is 1.
|
||||
|
||||
@item content_type
|
||||
Set a specific content type for the POST messages or for listen mode.
|
||||
|
||||
@item http_proxy
|
||||
set HTTP proxy to tunnel through e.g. http://example.com:1234
|
||||
|
||||
@@ -449,33 +452,42 @@ set HTTP proxy to tunnel through e.g. http://example.com:1234
|
||||
Set custom HTTP headers, can override built in default headers. The
|
||||
value must be a string encoding the headers.
|
||||
|
||||
@item content_type
|
||||
Set a specific content type for the POST messages or for listen mode.
|
||||
|
||||
@item user_agent
|
||||
Override the User-Agent header. If not specified the protocol will use a
|
||||
string describing the libavformat build. ("Lavf/<version>")
|
||||
|
||||
@item referer
|
||||
Set the Referer header. Include 'Referer: URL' header in HTTP request.
|
||||
|
||||
@item multiple_requests
|
||||
Use persistent connections if set to 1, default is 0.
|
||||
|
||||
@item post_data
|
||||
Set custom HTTP post data.
|
||||
|
||||
@item referer
|
||||
Set the Referer header. Include 'Referer: URL' header in HTTP request.
|
||||
|
||||
@item user_agent
|
||||
Override the User-Agent header. If not specified the protocol will use a
|
||||
string describing the libavformat build. ("Lavf/<version>")
|
||||
|
||||
@item reconnect_at_eof
|
||||
If set then eof is treated like an error and causes reconnection, this is useful
|
||||
for live / endless streams.
|
||||
|
||||
@item reconnect_streamed
|
||||
If set then even streamed/non seekable streams will be reconnected on errors.
|
||||
|
||||
@item reconnect_on_network_error
|
||||
Reconnect automatically in case of TCP/TLS errors during connect.
|
||||
|
||||
@item reconnect_on_http_error
|
||||
A comma separated list of HTTP status codes to reconnect on. The list can
|
||||
include specific status codes (e.g. '503') or the strings '4xx' / '5xx'.
|
||||
|
||||
@item reconnect_delay_max
|
||||
Sets the maximum delay in seconds after which to give up reconnecting
|
||||
|
||||
@item mime_type
|
||||
Export the MIME type.
|
||||
|
||||
@item http_version
|
||||
Exports the HTTP response version number. Usually "1.0" or "1.1".
|
||||
|
||||
@item cookies
|
||||
Set the cookies to be sent in future requests. The format of each cookie is the
|
||||
same as the value of a Set-Cookie HTTP response field. Multiple cookies can be
|
||||
delimited by a newline character.
|
||||
|
||||
@item icy
|
||||
If set to 1 request ICY (SHOUTcast) metadata from the server. If the server
|
||||
supports this, the metadata has to be retrieved by the application by reading
|
||||
@@ -492,40 +504,10 @@ contains the last non-empty metadata packet sent by the server. It should be
|
||||
polled in regular intervals by applications interested in mid-stream metadata
|
||||
updates.
|
||||
|
||||
@item metadata
|
||||
Set an exported dictionary containing Icecast metadata from the bitstream, if present.
|
||||
Only useful with the C API.
|
||||
|
||||
@item auth_type
|
||||
|
||||
Set HTTP authentication type. No option for Digest, since this method requires
|
||||
getting nonce parameters from the server first and can't be used straight away like
|
||||
Basic.
|
||||
|
||||
@table @option
|
||||
@item none
|
||||
Choose the HTTP authentication type automatically. This is the default.
|
||||
@item basic
|
||||
|
||||
Choose the HTTP basic authentication.
|
||||
|
||||
Basic authentication sends a Base64-encoded string that contains a user name and password
|
||||
for the client. Base64 is not a form of encryption and should be considered the same as
|
||||
sending the user name and password in clear text (Base64 is a reversible encoding).
|
||||
If a resource needs to be protected, strongly consider using an authentication scheme
|
||||
other than basic authentication. HTTPS/TLS should be used with basic authentication.
|
||||
Without these additional security enhancements, basic authentication should not be used
|
||||
to protect sensitive or valuable information.
|
||||
@end table
|
||||
|
||||
@item send_expect_100
|
||||
Send an Expect: 100-continue header for POST. If set to 1 it will send, if set
|
||||
to 0 it won't, if set to -1 it will try to send if it is applicable. Default
|
||||
value is -1.
|
||||
|
||||
@item location
|
||||
An exported dictionary containing the content location. Only useful with the C
|
||||
API.
|
||||
@item cookies
|
||||
Set the cookies to be sent in future requests. The format of each cookie is the
|
||||
same as the value of a Set-Cookie HTTP response field. Multiple cookies can be
|
||||
delimited by a newline character.
|
||||
|
||||
@item offset
|
||||
Set initial byte offset.
|
||||
@@ -543,37 +525,6 @@ be given a Bad Request response.
|
||||
When unset the HTTP method is not checked for now. This will be replaced by
|
||||
autodetection in the future.
|
||||
|
||||
@item reconnect
|
||||
Reconnect automatically when disconnected before EOF is hit.
|
||||
|
||||
@item reconnect_at_eof
|
||||
If set then eof is treated like an error and causes reconnection, this is useful
|
||||
for live / endless streams.
|
||||
|
||||
@item reconnect_on_network_error
|
||||
Reconnect automatically in case of TCP/TLS errors during connect.
|
||||
|
||||
@item reconnect_on_http_error
|
||||
A comma separated list of HTTP status codes to reconnect on. The list can
|
||||
include specific status codes (e.g. '503') or the strings '4xx' / '5xx'.
|
||||
|
||||
@item reconnect_streamed
|
||||
If set then even streamed/non seekable streams will be reconnected on errors.
|
||||
|
||||
@item reconnect_delay_max
|
||||
Set the maximum delay in seconds after which to give up reconnecting.
|
||||
|
||||
@item reconnect_max_retries
|
||||
Set the maximum number of times to retry a connection. Default unset.
|
||||
|
||||
@item reconnect_delay_total_max
|
||||
Set the maximum total delay in seconds after which to give up reconnecting.
|
||||
|
||||
@item respect_retry_after
|
||||
If enabled, and a Retry-After header is encountered, its requested reconnection
|
||||
delay will be honored, rather than using exponential backoff. Useful for 429 and
|
||||
503 errors. Default enabled.
|
||||
|
||||
@item listen
|
||||
If set to 1 enables experimental HTTP server. This can be used to send data when
|
||||
used as an output option, or read data from a client with HTTP POST when used as
|
||||
@@ -600,16 +551,32 @@ ffmpeg -i somefile.ogg -chunked_post 0 -c copy -f ogg http://@var{server}:@var{p
|
||||
wget --post-file=somefile.ogg http://@var{server}:@var{port}
|
||||
@end example
|
||||
|
||||
@item resource
|
||||
The resource requested by a client, when the experimental HTTP server is in use.
|
||||
@item send_expect_100
|
||||
Send an Expect: 100-continue header for POST. If set to 1 it will send, if set
|
||||
to 0 it won't, if set to -1 it will try to send if it is applicable. Default
|
||||
value is -1.
|
||||
|
||||
@item reply_code
|
||||
The HTTP code returned to the client, when the experimental HTTP server is in use.
|
||||
@item auth_type
|
||||
|
||||
@item short_seek_size
|
||||
Set the threshold, in bytes, for when a readahead should be prefered over a seek and
|
||||
new HTTP request. This is useful, for example, to make sure the same connection
|
||||
is used for reading large video packets with small audio packets in between.
|
||||
Set HTTP authentication type. No option for Digest, since this method requires
|
||||
getting nonce parameters from the server first and can't be used straight away like
|
||||
Basic.
|
||||
|
||||
@table @option
|
||||
@item none
|
||||
Choose the HTTP authentication type automatically. This is the default.
|
||||
@item basic
|
||||
|
||||
Choose the HTTP basic authentication.
|
||||
|
||||
Basic authentication sends a Base64-encoded string that contains a user name and password
|
||||
for the client. Base64 is not a form of encryption and should be considered the same as
|
||||
sending the user name and password in clear text (Base64 is a reversible encoding).
|
||||
If a resource needs to be protected, strongly consider using an authentication scheme
|
||||
other than basic authentication. HTTPS/TLS should be used with basic authentication.
|
||||
Without these additional security enhancements, basic authentication should not be used
|
||||
to protect sensitive or valuable information.
|
||||
@end table
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env perl
|
||||
#! /usr/bin/env perl
|
||||
|
||||
# This script will print the dependency of a Texinfo file to stdout.
|
||||
# texidep.pl <src-path> <input.texi> <output.ext>
|
||||
|
||||
+26
-54
@@ -727,10 +727,6 @@ FL+FR+FC+LFE+BL+BR+TFL+TFR+TBL+TBR
|
||||
FL+FR+FC+LFE+BL+BR+SL+SR+TFL+TFR
|
||||
@item 7.1.4
|
||||
FL+FR+FC+LFE+BL+BR+SL+SR+TFL+TFR+TBL+TBR
|
||||
@item 7.2.3
|
||||
FL+FR+FC+LFE+BL+BR+SL+SR+TFL+TFR+TBC+LFE2
|
||||
@item 9.1.4
|
||||
FL+FR+FC+LFE+BL+BR+FLC+FRC+SL+SR+TFL+TFR+TBL+TBR
|
||||
@item hexadecagonal
|
||||
FL+FR+FC+BL+BR+BC+SL+SR+WL+WR+TBL+TBR+TBC+TFC+TFL+TFR
|
||||
@item downmix
|
||||
@@ -801,11 +797,6 @@ The following binary operators are available: @code{+}, @code{-},
|
||||
|
||||
The following unary operators are available: @code{+}, @code{-}.
|
||||
|
||||
Some internal variables can be used to store and load intermediary
|
||||
results. They can be accessed using the @code{ld} and @code{st}
|
||||
functions with an index argument varying from 0 to 9 to specify which
|
||||
internal variable to access.
|
||||
|
||||
The following functions are available:
|
||||
@table @option
|
||||
@item abs(x)
|
||||
@@ -820,7 +811,7 @@ Compute arcsine of @var{x}.
|
||||
@item atan(x)
|
||||
Compute arctangent of @var{x}.
|
||||
|
||||
@item atan2(y, x)
|
||||
@item atan2(x, y)
|
||||
Compute principal value of the arc tangent of @var{y}/@var{x}.
|
||||
|
||||
@item between(x, min, max)
|
||||
@@ -903,9 +894,9 @@ Return 1.0 if @var{x} is +/-INFINITY, 0.0 otherwise.
|
||||
@item isnan(x)
|
||||
Return 1.0 if @var{x} is NAN, 0.0 otherwise.
|
||||
|
||||
@item ld(idx)
|
||||
Load the value of the internal variable with index @var{idx}, which was
|
||||
previously stored with st(@var{idx}, @var{expr}).
|
||||
@item ld(var)
|
||||
Load the value of the internal variable with number
|
||||
@var{var}, which was previously stored with st(@var{var}, @var{expr}).
|
||||
The function returns the loaded value.
|
||||
|
||||
@item lerp(x, y, z)
|
||||
@@ -938,31 +929,15 @@ Compute the power of @var{x} elevated @var{y}, it is equivalent to
|
||||
|
||||
@item print(t)
|
||||
@item print(t, l)
|
||||
Print the value of expression @var{t} with loglevel @var{l}. If @var{l} is not
|
||||
specified then a default log level is used.
|
||||
Return the value of the expression printed.
|
||||
Print the value of expression @var{t} with loglevel @var{l}. If
|
||||
@var{l} is not specified then a default log level is used.
|
||||
Returns the value of the expression printed.
|
||||
|
||||
@item random(idx)
|
||||
Return a pseudo random value between 0.0 and 1.0. @var{idx} is the
|
||||
index of the internal variable used to save the seed/state, which can be
|
||||
previously stored with @code{st(idx)}.
|
||||
Prints t with loglevel l
|
||||
|
||||
To initialize the seed, you need to store the seed value as a 64-bit
|
||||
unsigned integer in the internal variable with index @var{idx}.
|
||||
|
||||
For example, to store the seed with value @code{42} in the internal
|
||||
variable with index @code{0} and print a few random values:
|
||||
@example
|
||||
st(0,42); print(random(0)); print(random(0)); print(random(0))
|
||||
@end example
|
||||
|
||||
@item randomi(idx, min, max)
|
||||
Return a pseudo random value in the interval between @var{min} and
|
||||
@var{max}. @var{idx} is the index of the internal variable which will be used to
|
||||
save the seed/state, which can be previously stored with @code{st(idx)}.
|
||||
|
||||
To initialize the seed, you need to store the seed value as a 64-bit
|
||||
unsigned integer in the internal variable with index @var{idx}.
|
||||
@item random(x)
|
||||
Return a pseudo random value between 0.0 and 1.0. @var{x} is the index of the
|
||||
internal variable which will be used to save the seed/state.
|
||||
|
||||
@item root(expr, max)
|
||||
Find an input value for which the function represented by @var{expr}
|
||||
@@ -971,14 +946,14 @@ with argument @var{ld(0)} is 0 in the interval 0..@var{max}.
|
||||
The expression in @var{expr} must denote a continuous function or the
|
||||
result is undefined.
|
||||
|
||||
@var{ld(0)} is used to represent the function input value, which means that the
|
||||
given expression will be evaluated multiple times with various input values that
|
||||
the expression can access through @code{ld(0)}. When the expression evaluates to
|
||||
0 then the corresponding input value will be returned.
|
||||
@var{ld(0)} is used to represent the function input value, which means
|
||||
that the given expression will be evaluated multiple times with
|
||||
various input values that the expression can access through
|
||||
@code{ld(0)}. When the expression evaluates to 0 then the
|
||||
corresponding input value will be returned.
|
||||
|
||||
@item round(expr)
|
||||
Round the value of expression @var{expr} to the nearest integer. For example,
|
||||
"round(1.5)" is "2.0".
|
||||
Round the value of expression @var{expr} to the nearest integer. For example, "round(1.5)" is "2.0".
|
||||
|
||||
@item sgn(x)
|
||||
Compute sign of @var{x}.
|
||||
@@ -996,15 +971,12 @@ Compute the square root of @var{expr}. This is equivalent to
|
||||
@item squish(x)
|
||||
Compute expression @code{1/(1 + exp(4*x))}.
|
||||
|
||||
@item st(idx, expr)
|
||||
@item st(var, expr)
|
||||
Store the value of the expression @var{expr} in an internal
|
||||
variable. @var{idx} specifies the index of the variable where to store
|
||||
the value, and it is a value ranging from 0 to 9. The function returns
|
||||
the value stored in the internal variable.
|
||||
|
||||
The stored value can be retrieved with @code{ld(var)}.
|
||||
|
||||
Note: variables are currently not shared between expressions.
|
||||
variable. @var{var} specifies the number of the variable where to
|
||||
store the value, and it is a value ranging from 0 to 9. The function
|
||||
returns the value stored in the internal variable.
|
||||
Note, Variables are currently not shared between expressions.
|
||||
|
||||
@item tan(x)
|
||||
Compute tangent of @var{x}.
|
||||
@@ -1013,16 +985,16 @@ Compute tangent of @var{x}.
|
||||
Compute hyperbolic tangent of @var{x}.
|
||||
|
||||
@item taylor(expr, x)
|
||||
@item taylor(expr, x, idx)
|
||||
@item taylor(expr, x, id)
|
||||
Evaluate a Taylor series at @var{x}, given an expression representing
|
||||
the @code{ld(idx)}-th derivative of a function at 0.
|
||||
the @code{ld(id)}-th derivative of a function at 0.
|
||||
|
||||
When the series does not converge the result is undefined.
|
||||
|
||||
@var{ld(idx)} is used to represent the derivative order in @var{expr},
|
||||
@var{ld(id)} is used to represent the derivative order in @var{expr},
|
||||
which means that the given expression will be evaluated multiple times
|
||||
with various input values that the expression can access through
|
||||
@code{ld(idx)}. If @var{idx} is not specified then 0 is assumed.
|
||||
@code{ld(id)}. If @var{id} is not specified then 0 is assumed.
|
||||
|
||||
Note, when you have the derivatives at y instead of 0,
|
||||
@code{taylor(expr, x-y)} can be used.
|
||||
|
||||
@@ -15,9 +15,7 @@ OBJS-$(HAVE_LASX) += $(LASX-OBJS) $(LASX-OBJS-yes)
|
||||
OBJS-$(HAVE_ALTIVEC) += $(ALTIVEC-OBJS) $(ALTIVEC-OBJS-yes)
|
||||
OBJS-$(HAVE_VSX) += $(VSX-OBJS) $(VSX-OBJS-yes)
|
||||
|
||||
OBJS-$(HAVE_RV) += $(RV-OBJS) $(RV-OBJS-yes)
|
||||
OBJS-$(HAVE_RVV) += $(RVV-OBJS) $(RVV-OBJS-yes)
|
||||
OBJS-$(HAVE_RV_ZVBB) += $(RVVB-OBJS) $(RVVB-OBJS-yes)
|
||||
|
||||
OBJS-$(HAVE_MMX) += $(MMX-OBJS) $(MMX-OBJS-yes)
|
||||
OBJS-$(HAVE_X86ASM) += $(X86ASM-OBJS) $(X86ASM-OBJS-yes)
|
||||
|
||||
+2
-2
@@ -130,7 +130,7 @@ $(BIN2CEXE): ffbuild/bin2c_host.o
|
||||
ifdef CONFIG_PTX_COMPRESSION
|
||||
%.ptx.gz: TAG = GZIP
|
||||
%.ptx.gz: %.ptx
|
||||
$(M)gzip -nc9 $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) >$@
|
||||
$(M)gzip -c9 $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) >$@
|
||||
|
||||
%.ptx.c: %.ptx.gz $(BIN2CEXE)
|
||||
$(BIN2C) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) $@ $(subst .,_,$(basename $(notdir $@)))
|
||||
@@ -140,7 +140,7 @@ else
|
||||
endif
|
||||
|
||||
clean::
|
||||
$(RM) $(BIN2CEXE) $(CLEANSUFFIXES:%=ffbuild/%)
|
||||
$(RM) $(BIN2CEXE)
|
||||
|
||||
%.c %.h %.pc %.ver %.version: TAG = GEN
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#!/bin/sh
|
||||
toupper(){
|
||||
echo "$@" | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
}
|
||||
|
||||
@@ -18,13 +18,10 @@ OBJS-ffmpeg += \
|
||||
fftools/ffmpeg_mux.o \
|
||||
fftools/ffmpeg_mux_init.o \
|
||||
fftools/ffmpeg_opt.o \
|
||||
fftools/ffmpeg_sched.o \
|
||||
fftools/objpool.o \
|
||||
fftools/sync_queue.o \
|
||||
fftools/thread_queue.o \
|
||||
|
||||
OBJS-ffplay += fftools/ffplay_renderer.o
|
||||
|
||||
define DOFFTOOL
|
||||
OBJS-$(1) += fftools/cmdutils.o fftools/opt_common.o fftools/$(1).o $(OBJS-$(1)-yes)
|
||||
ifdef HAVE_GNU_WINDRES
|
||||
|
||||
+88
-560
@@ -33,14 +33,16 @@
|
||||
#include "compat/va_copy.h"
|
||||
#include "libavformat/avformat.h"
|
||||
#include "libswscale/swscale.h"
|
||||
#include "libswscale/version.h"
|
||||
#include "libswresample/swresample.h"
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/bprint.h"
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/display.h"
|
||||
#include "libavutil/getenv_utf8.h"
|
||||
#include "libavutil/mathematics.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
#include "libavutil/libm.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/parseutils.h"
|
||||
#include "libavutil/eval.h"
|
||||
#include "libavutil/dict.h"
|
||||
@@ -81,7 +83,7 @@ void init_dynload(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
int parse_number(const char *context, const char *numstr, enum OptionType type,
|
||||
int parse_number(const char *context, const char *numstr, int type,
|
||||
double min, double max, double *dst)
|
||||
{
|
||||
char *tail;
|
||||
@@ -91,9 +93,9 @@ int parse_number(const char *context, const char *numstr, enum OptionType type,
|
||||
error = "Expected number for %s but found: %s\n";
|
||||
else if (d < min || d > max)
|
||||
error = "The value for %s was %s which is not within %f - %f\n";
|
||||
else if (type == OPT_TYPE_INT64 && (int64_t)d != d)
|
||||
else if (type == OPT_INT64 && (int64_t)d != d)
|
||||
error = "Expected int64 for %s but found %s\n";
|
||||
else if (type == OPT_TYPE_INT && (int)d != d)
|
||||
else if (type == OPT_INT && (int)d != d)
|
||||
error = "Expected int for %s but found %s\n";
|
||||
else {
|
||||
*dst = d;
|
||||
@@ -105,7 +107,7 @@ int parse_number(const char *context, const char *numstr, enum OptionType type,
|
||||
}
|
||||
|
||||
void show_help_options(const OptionDef *options, const char *msg, int req_flags,
|
||||
int rej_flags)
|
||||
int rej_flags, int alt_flags)
|
||||
{
|
||||
const OptionDef *po;
|
||||
int first;
|
||||
@@ -115,6 +117,7 @@ void show_help_options(const OptionDef *options, const char *msg, int req_flags,
|
||||
char buf[128];
|
||||
|
||||
if (((po->flags & req_flags) != req_flags) ||
|
||||
(alt_flags && !(po->flags & alt_flags)) ||
|
||||
(po->flags & rej_flags))
|
||||
continue;
|
||||
|
||||
@@ -123,15 +126,10 @@ void show_help_options(const OptionDef *options, const char *msg, int req_flags,
|
||||
first = 0;
|
||||
}
|
||||
av_strlcpy(buf, po->name, sizeof(buf));
|
||||
|
||||
if (po->flags & OPT_FLAG_PERSTREAM)
|
||||
av_strlcat(buf, "[:<stream_spec>]", sizeof(buf));
|
||||
else if (po->flags & OPT_FLAG_SPEC)
|
||||
av_strlcat(buf, "[:<spec>]", sizeof(buf));
|
||||
|
||||
if (po->argname)
|
||||
av_strlcatf(buf, sizeof(buf), " <%s>", po->argname);
|
||||
|
||||
if (po->argname) {
|
||||
av_strlcat(buf, " ", sizeof(buf));
|
||||
av_strlcat(buf, po->argname, sizeof(buf));
|
||||
}
|
||||
printf("-%-17s %s\n", buf, po->help);
|
||||
}
|
||||
printf("\n");
|
||||
@@ -152,9 +150,6 @@ void show_help_children(const AVClass *class, int flags)
|
||||
|
||||
static const OptionDef *find_option(const OptionDef *po, const char *name)
|
||||
{
|
||||
if (*name == '/')
|
||||
name++;
|
||||
|
||||
while (po->name) {
|
||||
const char *end;
|
||||
if (av_strstart(name, po->name, &end) && (!*end || *end == ':'))
|
||||
@@ -228,150 +223,85 @@ static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
|
||||
}
|
||||
#endif /* HAVE_COMMANDLINETOARGVW */
|
||||
|
||||
static int opt_has_arg(const OptionDef *o)
|
||||
{
|
||||
if (o->type == OPT_TYPE_BOOL)
|
||||
return 0;
|
||||
if (o->type == OPT_TYPE_FUNC)
|
||||
return !!(o->flags & OPT_FUNC_ARG);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int write_option(void *optctx, const OptionDef *po, const char *opt,
|
||||
const char *arg, const OptionDef *defs)
|
||||
const char *arg)
|
||||
{
|
||||
/* new-style options contain an offset into optctx, old-style address of
|
||||
* a global var*/
|
||||
void *dst = po->flags & OPT_FLAG_OFFSET ?
|
||||
void *dst = po->flags & (OPT_OFFSET | OPT_SPEC) ?
|
||||
(uint8_t *)optctx + po->u.off : po->u.dst_ptr;
|
||||
char *arg_allocated = NULL;
|
||||
|
||||
enum OptionType so_type = po->type;
|
||||
|
||||
SpecifierOptList *sol = NULL;
|
||||
int *dstcount;
|
||||
double num;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
if (*opt == '/') {
|
||||
opt++;
|
||||
|
||||
if (po->type == OPT_TYPE_BOOL) {
|
||||
av_log(NULL, AV_LOG_FATAL,
|
||||
"Requested to load an argument from file for a bool option '%s'\n",
|
||||
po->name);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
arg_allocated = file_read(arg);
|
||||
if (!arg_allocated) {
|
||||
av_log(NULL, AV_LOG_FATAL,
|
||||
"Error reading the value for option '%s' from file: %s\n",
|
||||
opt, arg);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
arg = arg_allocated;
|
||||
}
|
||||
|
||||
if (po->flags & OPT_FLAG_SPEC) {
|
||||
if (po->flags & OPT_SPEC) {
|
||||
SpecifierOpt **so = dst;
|
||||
char *p = strchr(opt, ':');
|
||||
char *str;
|
||||
|
||||
sol = dst;
|
||||
ret = GROW_ARRAY(sol->opt, sol->nb_opt);
|
||||
dstcount = (int *)(so + 1);
|
||||
ret = grow_array((void**)so, sizeof(**so), dstcount, *dstcount + 1);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
return ret;
|
||||
|
||||
str = av_strdup(p ? p + 1 : "");
|
||||
if (!str) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto finish;
|
||||
}
|
||||
sol->opt[sol->nb_opt - 1].specifier = str;
|
||||
|
||||
if (po->flags & OPT_FLAG_PERSTREAM) {
|
||||
ret = stream_specifier_parse(&sol->opt[sol->nb_opt - 1].stream_spec,
|
||||
str, 0, NULL);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
dst = &sol->opt[sol->nb_opt - 1].u;
|
||||
if (!str)
|
||||
return AVERROR(ENOMEM);
|
||||
(*so)[*dstcount - 1].specifier = str;
|
||||
dst = &(*so)[*dstcount - 1].u;
|
||||
}
|
||||
|
||||
if (po->type == OPT_TYPE_STRING) {
|
||||
if (po->flags & OPT_STRING) {
|
||||
char *str;
|
||||
if (arg_allocated) {
|
||||
str = arg_allocated;
|
||||
arg_allocated = NULL;
|
||||
} else
|
||||
str = av_strdup(arg);
|
||||
str = av_strdup(arg);
|
||||
av_freep(dst);
|
||||
|
||||
if (!str) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!str)
|
||||
return AVERROR(ENOMEM);
|
||||
*(char **)dst = str;
|
||||
} else if (po->type == OPT_TYPE_BOOL || po->type == OPT_TYPE_INT) {
|
||||
ret = parse_number(opt, arg, OPT_TYPE_INT64, INT_MIN, INT_MAX, &num);
|
||||
} else if (po->flags & OPT_BOOL || po->flags & OPT_INT) {
|
||||
ret = parse_number(opt, arg, OPT_INT64, INT_MIN, INT_MAX, &num);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
return ret;
|
||||
|
||||
*(int *)dst = num;
|
||||
so_type = OPT_TYPE_INT;
|
||||
} else if (po->type == OPT_TYPE_INT64) {
|
||||
ret = parse_number(opt, arg, OPT_TYPE_INT64, INT64_MIN, (double)INT64_MAX, &num);
|
||||
} else if (po->flags & OPT_INT64) {
|
||||
ret = parse_number(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX, &num);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
return ret;
|
||||
|
||||
*(int64_t *)dst = num;
|
||||
} else if (po->type == OPT_TYPE_TIME) {
|
||||
} else if (po->flags & OPT_TIME) {
|
||||
ret = av_parse_time(dst, arg, 1);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Invalid duration for option %s: %s\n",
|
||||
opt, arg);
|
||||
goto finish;
|
||||
return ret;
|
||||
}
|
||||
so_type = OPT_TYPE_INT64;
|
||||
} else if (po->type == OPT_TYPE_FLOAT) {
|
||||
ret = parse_number(opt, arg, OPT_TYPE_FLOAT, -INFINITY, INFINITY, &num);
|
||||
} else if (po->flags & OPT_FLOAT) {
|
||||
ret = parse_number(opt, arg, OPT_FLOAT, -INFINITY, INFINITY, &num);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
return ret;
|
||||
|
||||
*(float *)dst = num;
|
||||
} else if (po->type == OPT_TYPE_DOUBLE) {
|
||||
ret = parse_number(opt, arg, OPT_TYPE_DOUBLE, -INFINITY, INFINITY, &num);
|
||||
} else if (po->flags & OPT_DOUBLE) {
|
||||
ret = parse_number(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY, &num);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
return ret;
|
||||
|
||||
*(double *)dst = num;
|
||||
} else {
|
||||
av_assert0(po->type == OPT_TYPE_FUNC && po->u.func_arg);
|
||||
|
||||
ret = po->u.func_arg(optctx, opt, arg);
|
||||
} else if (po->u.func_arg) {
|
||||
int ret = po->u.func_arg(optctx, opt, arg);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Failed to set value '%s' for option '%s': %s\n",
|
||||
arg, opt, av_err2str(ret));
|
||||
goto finish;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (po->flags & OPT_EXIT) {
|
||||
ret = AVERROR_EXIT;
|
||||
goto finish;
|
||||
}
|
||||
if (po->flags & OPT_EXIT)
|
||||
return AVERROR_EXIT;
|
||||
|
||||
if (sol) {
|
||||
sol->type = so_type;
|
||||
sol->opt_canon = (po->flags & OPT_HAS_CANON) ?
|
||||
find_option(defs, po->u1.name_canon) : po;
|
||||
}
|
||||
|
||||
finish:
|
||||
av_freep(&arg_allocated);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_option(void *optctx, const char *opt, const char *arg,
|
||||
@@ -379,8 +309,7 @@ int parse_option(void *optctx, const char *opt, const char *arg,
|
||||
{
|
||||
static const OptionDef opt_avoptions = {
|
||||
.name = "AVOption passthrough",
|
||||
.type = OPT_TYPE_FUNC,
|
||||
.flags = OPT_FUNC_ARG,
|
||||
.flags = HAS_ARG,
|
||||
.u.func_arg = opt_default,
|
||||
};
|
||||
|
||||
@@ -391,9 +320,9 @@ int parse_option(void *optctx, const char *opt, const char *arg,
|
||||
if (!po->name && opt[0] == 'n' && opt[1] == 'o') {
|
||||
/* handle 'no' bool option */
|
||||
po = find_option(options, opt + 2);
|
||||
if ((po->name && po->type == OPT_TYPE_BOOL))
|
||||
if ((po->name && (po->flags & OPT_BOOL)))
|
||||
arg = "0";
|
||||
} else if (po->type == OPT_TYPE_BOOL)
|
||||
} else if (po->flags & OPT_BOOL)
|
||||
arg = "1";
|
||||
|
||||
if (!po->name)
|
||||
@@ -402,16 +331,16 @@ int parse_option(void *optctx, const char *opt, const char *arg,
|
||||
av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
if (opt_has_arg(po) && !arg) {
|
||||
if (po->flags & HAS_ARG && !arg) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
ret = write_option(optctx, po, opt, arg, options);
|
||||
ret = write_option(optctx, po, opt, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return opt_has_arg(po);
|
||||
return !!(po->flags & HAS_ARG);
|
||||
}
|
||||
|
||||
int parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
|
||||
@@ -450,7 +379,7 @@ int parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_optgroup(void *optctx, OptionGroup *g, const OptionDef *defs)
|
||||
int parse_optgroup(void *optctx, OptionGroup *g)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
@@ -473,7 +402,7 @@ int parse_optgroup(void *optctx, OptionGroup *g, const OptionDef *defs)
|
||||
av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n",
|
||||
o->key, o->opt->help, o->val);
|
||||
|
||||
ret = write_option(optctx, o->opt, o->key, o->val, defs);
|
||||
ret = write_option(optctx, o->opt, o->key, o->val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@@ -503,7 +432,7 @@ int locate_option(int argc, char **argv, const OptionDef *options,
|
||||
(po->name && !strcmp(optname, po->name)))
|
||||
return i;
|
||||
|
||||
if (!po->name || opt_has_arg(po))
|
||||
if (!po->name || po->flags & HAS_ARG)
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
@@ -537,14 +466,7 @@ static void check_options(const OptionDef *po)
|
||||
{
|
||||
while (po->name) {
|
||||
if (po->flags & OPT_PERFILE)
|
||||
av_assert0(po->flags & (OPT_INPUT | OPT_OUTPUT | OPT_DECODER));
|
||||
|
||||
if (po->type == OPT_TYPE_FUNC)
|
||||
av_assert0(!(po->flags & (OPT_FLAG_OFFSET | OPT_FLAG_SPEC)));
|
||||
|
||||
// OPT_FUNC_ARG can only be ser for OPT_TYPE_FUNC
|
||||
av_assert0((po->type == OPT_TYPE_FUNC) || !(po->flags & OPT_FUNC_ARG));
|
||||
|
||||
av_assert0(po->flags & (OPT_INPUT | OPT_OUTPUT));
|
||||
po++;
|
||||
}
|
||||
}
|
||||
@@ -720,7 +642,7 @@ static int finish_group(OptionParseContext *octx, int group_idx,
|
||||
static int add_opt(OptionParseContext *octx, const OptionDef *opt,
|
||||
const char *key, const char *val)
|
||||
{
|
||||
int global = !(opt->flags & OPT_PERFILE);
|
||||
int global = !(opt->flags & (OPT_PERFILE | OPT_SPEC | OPT_OFFSET));
|
||||
OptionGroup *g = global ? &octx->global_opts : &octx->cur_group;
|
||||
int ret;
|
||||
|
||||
@@ -743,10 +665,10 @@ static int init_parse_context(OptionParseContext *octx,
|
||||
|
||||
memset(octx, 0, sizeof(*octx));
|
||||
|
||||
octx->groups = av_calloc(nb_groups, sizeof(*octx->groups));
|
||||
octx->nb_groups = nb_groups;
|
||||
octx->groups = av_calloc(octx->nb_groups, sizeof(*octx->groups));
|
||||
if (!octx->groups)
|
||||
return AVERROR(ENOMEM);
|
||||
octx->nb_groups = nb_groups;
|
||||
|
||||
for (i = 0; i < octx->nb_groups; i++)
|
||||
octx->groups[i].group_def = &groups[i];
|
||||
@@ -802,7 +724,7 @@ int split_commandline(OptionParseContext *octx, int argc, char *argv[],
|
||||
while (optindex < argc) {
|
||||
const char *opt = argv[optindex++], *arg;
|
||||
const OptionDef *po;
|
||||
int group_idx;
|
||||
int ret;
|
||||
|
||||
av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...", opt);
|
||||
|
||||
@@ -831,15 +753,14 @@ do { \
|
||||
} while (0)
|
||||
|
||||
/* named group separators, e.g. -i */
|
||||
group_idx = match_group_separator(groups, nb_groups, opt);
|
||||
if (group_idx >= 0) {
|
||||
if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) {
|
||||
GET_ARG(arg);
|
||||
ret = finish_group(octx, group_idx, arg);
|
||||
ret = finish_group(octx, ret, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n",
|
||||
groups[group_idx].name, arg);
|
||||
groups[ret].name, arg);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -849,7 +770,7 @@ do { \
|
||||
if (po->flags & OPT_EXIT) {
|
||||
/* optional argument, e.g. -h */
|
||||
arg = argv[optindex++];
|
||||
} else if (opt_has_arg(po)) {
|
||||
} else if (po->flags & HAS_ARG) {
|
||||
GET_ARG(arg);
|
||||
} else {
|
||||
arg = "1";
|
||||
@@ -882,7 +803,7 @@ do { \
|
||||
/* boolean -nofoo options */
|
||||
if (opt[0] == 'n' && opt[1] == 'o' &&
|
||||
(po = find_option(options, opt + 2)) &&
|
||||
po->name && po->type == OPT_TYPE_BOOL) {
|
||||
po->name && po->flags & OPT_BOOL) {
|
||||
ret = add_opt(octx, po, opt, "0");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -905,6 +826,11 @@ do { \
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_error(const char *filename, int err)
|
||||
{
|
||||
av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, av_err2str(err));
|
||||
}
|
||||
|
||||
int read_yesno(void)
|
||||
{
|
||||
int c = getchar();
|
||||
@@ -988,366 +914,17 @@ FILE *get_preset_file(char *filename, size_t filename_size,
|
||||
return f;
|
||||
}
|
||||
|
||||
int cmdutils_isalnum(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
void stream_specifier_uninit(StreamSpecifier *ss)
|
||||
{
|
||||
av_freep(&ss->meta_key);
|
||||
av_freep(&ss->meta_val);
|
||||
av_freep(&ss->remainder);
|
||||
|
||||
memset(ss, 0, sizeof(*ss));
|
||||
}
|
||||
|
||||
int stream_specifier_parse(StreamSpecifier *ss, const char *spec,
|
||||
int allow_remainder, void *logctx)
|
||||
{
|
||||
char *endptr;
|
||||
int ret;
|
||||
|
||||
memset(ss, 0, sizeof(*ss));
|
||||
|
||||
ss->idx = -1;
|
||||
ss->media_type = AVMEDIA_TYPE_UNKNOWN;
|
||||
ss->stream_list = STREAM_LIST_ALL;
|
||||
|
||||
av_log(logctx, AV_LOG_TRACE, "Parsing stream specifier: %s\n", spec);
|
||||
|
||||
while (*spec) {
|
||||
if (*spec <= '9' && *spec >= '0') { /* opt:index */
|
||||
ss->idx = strtol(spec, &endptr, 0);
|
||||
|
||||
av_assert0(endptr > spec);
|
||||
spec = endptr;
|
||||
|
||||
av_log(logctx, AV_LOG_TRACE,
|
||||
"Parsed index: %d; remainder: %s\n", ss->idx, spec);
|
||||
|
||||
// this terminates the specifier
|
||||
break;
|
||||
} else if ((*spec == 'v' || *spec == 'a' || *spec == 's' ||
|
||||
*spec == 'd' || *spec == 't' || *spec == 'V') &&
|
||||
!cmdutils_isalnum(*(spec + 1))) { /* opt:[vasdtV] */
|
||||
if (ss->media_type != AVMEDIA_TYPE_UNKNOWN) {
|
||||
av_log(logctx, AV_LOG_ERROR, "Stream type specified multiple times\n");
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch (*spec++) {
|
||||
case 'v': ss->media_type = AVMEDIA_TYPE_VIDEO; break;
|
||||
case 'a': ss->media_type = AVMEDIA_TYPE_AUDIO; break;
|
||||
case 's': ss->media_type = AVMEDIA_TYPE_SUBTITLE; break;
|
||||
case 'd': ss->media_type = AVMEDIA_TYPE_DATA; break;
|
||||
case 't': ss->media_type = AVMEDIA_TYPE_ATTACHMENT; break;
|
||||
case 'V': ss->media_type = AVMEDIA_TYPE_VIDEO;
|
||||
ss->no_apic = 1; break;
|
||||
default: av_assert0(0);
|
||||
}
|
||||
|
||||
av_log(logctx, AV_LOG_TRACE, "Parsed media type: %s; remainder: %s\n",
|
||||
av_get_media_type_string(ss->media_type), spec);
|
||||
} else if (*spec == 'g' && *(spec + 1) == ':') {
|
||||
if (ss->stream_list != STREAM_LIST_ALL)
|
||||
goto multiple_stream_lists;
|
||||
|
||||
spec += 2;
|
||||
if (*spec == '#' || (*spec == 'i' && *(spec + 1) == ':')) {
|
||||
ss->stream_list = STREAM_LIST_GROUP_ID;
|
||||
|
||||
spec += 1 + (*spec == 'i');
|
||||
} else
|
||||
ss->stream_list = STREAM_LIST_GROUP_IDX;
|
||||
|
||||
ss->list_id = strtol(spec, &endptr, 0);
|
||||
if (spec == endptr) {
|
||||
av_log(logctx, AV_LOG_ERROR, "Expected stream group idx/ID, got: %s\n", spec);
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
}
|
||||
spec = endptr;
|
||||
|
||||
av_log(logctx, AV_LOG_TRACE, "Parsed stream group %s: %"PRId64"; remainder: %s\n",
|
||||
ss->stream_list == STREAM_LIST_GROUP_ID ? "ID" : "index", ss->list_id, spec);
|
||||
} else if (*spec == 'p' && *(spec + 1) == ':') {
|
||||
if (ss->stream_list != STREAM_LIST_ALL)
|
||||
goto multiple_stream_lists;
|
||||
|
||||
ss->stream_list = STREAM_LIST_PROGRAM;
|
||||
|
||||
spec += 2;
|
||||
ss->list_id = strtol(spec, &endptr, 0);
|
||||
if (spec == endptr) {
|
||||
av_log(logctx, AV_LOG_ERROR, "Expected program ID, got: %s\n", spec);
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
}
|
||||
spec = endptr;
|
||||
|
||||
av_log(logctx, AV_LOG_TRACE,
|
||||
"Parsed program ID: %"PRId64"; remainder: %s\n", ss->list_id, spec);
|
||||
} else if (!strncmp(spec, "disp:", 5)) {
|
||||
const AVClass *st_class = av_stream_get_class();
|
||||
const AVOption *o = av_opt_find(&st_class, "disposition", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ);
|
||||
char *disp = NULL;
|
||||
size_t len;
|
||||
|
||||
av_assert0(o);
|
||||
|
||||
if (ss->disposition) {
|
||||
av_log(logctx, AV_LOG_ERROR, "Multiple disposition specifiers\n");
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
spec += 5;
|
||||
|
||||
for (len = 0; cmdutils_isalnum(spec[len]) ||
|
||||
spec[len] == '_' || spec[len] == '+'; len++)
|
||||
continue;
|
||||
|
||||
disp = av_strndup(spec, len);
|
||||
if (!disp) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = av_opt_eval_flags(&st_class, o, disp, &ss->disposition);
|
||||
av_freep(&disp);
|
||||
if (ret < 0) {
|
||||
av_log(logctx, AV_LOG_ERROR, "Invalid disposition specifier\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
spec += len;
|
||||
|
||||
av_log(logctx, AV_LOG_TRACE,
|
||||
"Parsed disposition: 0x%x; remainder: %s\n", ss->disposition, spec);
|
||||
} else if (*spec == '#' ||
|
||||
(*spec == 'i' && *(spec + 1) == ':')) {
|
||||
if (ss->stream_list != STREAM_LIST_ALL)
|
||||
goto multiple_stream_lists;
|
||||
|
||||
ss->stream_list = STREAM_LIST_STREAM_ID;
|
||||
|
||||
spec += 1 + (*spec == 'i');
|
||||
ss->list_id = strtol(spec, &endptr, 0);
|
||||
if (spec == endptr) {
|
||||
av_log(logctx, AV_LOG_ERROR, "Expected stream ID, got: %s\n", spec);
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
}
|
||||
spec = endptr;
|
||||
|
||||
av_log(logctx, AV_LOG_TRACE,
|
||||
"Parsed stream ID: %"PRId64"; remainder: %s\n", ss->list_id, spec);
|
||||
|
||||
// this terminates the specifier
|
||||
break;
|
||||
} else if (*spec == 'm' && *(spec + 1) == ':') {
|
||||
av_assert0(!ss->meta_key && !ss->meta_val);
|
||||
|
||||
spec += 2;
|
||||
ss->meta_key = av_get_token(&spec, ":");
|
||||
if (!ss->meta_key) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
if (*spec == ':') {
|
||||
spec++;
|
||||
ss->meta_val = av_get_token(&spec, ":");
|
||||
if (!ss->meta_val) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
av_log(logctx, AV_LOG_TRACE,
|
||||
"Parsed metadata: %s:%s; remainder: %s", ss->meta_key,
|
||||
ss->meta_val ? ss->meta_val : "<any value>", spec);
|
||||
|
||||
// this terminates the specifier
|
||||
break;
|
||||
} else if (*spec == 'u' && (*(spec + 1) == '\0' || *(spec + 1) == ':')) {
|
||||
ss->usable_only = 1;
|
||||
spec++;
|
||||
av_log(logctx, AV_LOG_ERROR, "Parsed 'usable only'\n");
|
||||
|
||||
// this terminates the specifier
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
|
||||
if (*spec == ':')
|
||||
spec++;
|
||||
}
|
||||
|
||||
if (*spec) {
|
||||
if (!allow_remainder) {
|
||||
av_log(logctx, AV_LOG_ERROR,
|
||||
"Trailing garbage at the end of a stream specifier: %s\n",
|
||||
spec);
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (*spec == ':')
|
||||
spec++;
|
||||
|
||||
ss->remainder = av_strdup(spec);
|
||||
if (!ss->remainder) {
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
multiple_stream_lists:
|
||||
av_log(logctx, AV_LOG_ERROR,
|
||||
"Cannot combine multiple program/group designators in a "
|
||||
"single stream specifier");
|
||||
ret = AVERROR(EINVAL);
|
||||
|
||||
fail:
|
||||
stream_specifier_uninit(ss);
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned stream_specifier_match(const StreamSpecifier *ss,
|
||||
const AVFormatContext *s, const AVStream *st,
|
||||
void *logctx)
|
||||
{
|
||||
const AVStreamGroup *g = NULL;
|
||||
const AVProgram *p = NULL;
|
||||
int start_stream = 0, nb_streams;
|
||||
int nb_matched = 0;
|
||||
|
||||
switch (ss->stream_list) {
|
||||
case STREAM_LIST_STREAM_ID:
|
||||
// <n-th> stream with given ID makes no sense and should be impossible to request
|
||||
av_assert0(ss->idx < 0);
|
||||
// return early if we know for sure the stream does not match
|
||||
if (st->id != ss->list_id)
|
||||
return 0;
|
||||
start_stream = st->index;
|
||||
nb_streams = st->index + 1;
|
||||
break;
|
||||
case STREAM_LIST_ALL:
|
||||
start_stream = ss->idx >= 0 ? 0 : st->index;
|
||||
nb_streams = st->index + 1;
|
||||
break;
|
||||
case STREAM_LIST_PROGRAM:
|
||||
for (unsigned i = 0; i < s->nb_programs; i++) {
|
||||
if (s->programs[i]->id == ss->list_id) {
|
||||
p = s->programs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!p) {
|
||||
av_log(logctx, AV_LOG_WARNING, "No program with ID %"PRId64" exists,"
|
||||
" stream specifier can never match\n", ss->list_id);
|
||||
return 0;
|
||||
}
|
||||
nb_streams = p->nb_stream_indexes;
|
||||
break;
|
||||
case STREAM_LIST_GROUP_ID:
|
||||
for (unsigned i = 0; i < s->nb_stream_groups; i++) {
|
||||
if (ss->list_id == s->stream_groups[i]->id) {
|
||||
g = s->stream_groups[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// fall-through
|
||||
case STREAM_LIST_GROUP_IDX:
|
||||
if (ss->stream_list == STREAM_LIST_GROUP_IDX &&
|
||||
ss->list_id >= 0 && ss->list_id < s->nb_stream_groups)
|
||||
g = s->stream_groups[ss->list_id];
|
||||
|
||||
if (!g) {
|
||||
av_log(logctx, AV_LOG_WARNING, "No stream group with group %s %"
|
||||
PRId64" exists, stream specifier can never match\n",
|
||||
ss->stream_list == STREAM_LIST_GROUP_ID ? "ID" : "index",
|
||||
ss->list_id);
|
||||
return 0;
|
||||
}
|
||||
nb_streams = g->nb_streams;
|
||||
break;
|
||||
default: av_assert0(0);
|
||||
}
|
||||
|
||||
for (int i = start_stream; i < nb_streams; i++) {
|
||||
const AVStream *candidate = s->streams[g ? g->streams[i]->index :
|
||||
p ? p->stream_index[i] : i];
|
||||
|
||||
if (ss->media_type != AVMEDIA_TYPE_UNKNOWN &&
|
||||
(ss->media_type != candidate->codecpar->codec_type ||
|
||||
(ss->no_apic && (candidate->disposition & AV_DISPOSITION_ATTACHED_PIC))))
|
||||
continue;
|
||||
|
||||
if (ss->meta_key) {
|
||||
const AVDictionaryEntry *tag = av_dict_get(candidate->metadata,
|
||||
ss->meta_key, NULL, 0);
|
||||
|
||||
if (!tag)
|
||||
continue;
|
||||
if (ss->meta_val && strcmp(tag->value, ss->meta_val))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ss->usable_only) {
|
||||
const AVCodecParameters *par = candidate->codecpar;
|
||||
|
||||
switch (par->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
if (!par->sample_rate || !par->ch_layout.nb_channels ||
|
||||
par->format == AV_SAMPLE_FMT_NONE)
|
||||
continue;
|
||||
break;
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
if (!par->width || !par->height || par->format == AV_PIX_FMT_NONE)
|
||||
continue;
|
||||
break;
|
||||
case AVMEDIA_TYPE_UNKNOWN:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ss->disposition &&
|
||||
(candidate->disposition & ss->disposition) != ss->disposition)
|
||||
continue;
|
||||
|
||||
if (st == candidate)
|
||||
return ss->idx < 0 || ss->idx == nb_matched;
|
||||
|
||||
nb_matched++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
|
||||
{
|
||||
StreamSpecifier ss;
|
||||
int ret;
|
||||
|
||||
ret = stream_specifier_parse(&ss, spec, 0, NULL);
|
||||
int ret = avformat_match_stream_specifier(s, st, spec);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = stream_specifier_match(&ss, s, st, NULL);
|
||||
stream_specifier_uninit(&ss);
|
||||
av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
||||
AVFormatContext *s, AVStream *st, const AVCodec *codec,
|
||||
AVDictionary **dst, AVDictionary **opts_used)
|
||||
AVDictionary **dst)
|
||||
{
|
||||
AVDictionary *ret = NULL;
|
||||
const AVDictionaryEntry *t = NULL;
|
||||
@@ -1356,6 +933,10 @@ int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
||||
char prefix = 0;
|
||||
const AVClass *cc = avcodec_get_class();
|
||||
|
||||
if (!codec)
|
||||
codec = s->oformat ? avcodec_find_encoder(codec_id)
|
||||
: avcodec_find_decoder(codec_id);
|
||||
|
||||
switch (st->codecpar->codec_type) {
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
prefix = 'v';
|
||||
@@ -1374,7 +955,6 @@ int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
||||
while (t = av_dict_iterate(opts, t)) {
|
||||
const AVClass *priv_class;
|
||||
char *p = strchr(t->key, ':');
|
||||
int used = 0;
|
||||
|
||||
/* check stream specification in opt name */
|
||||
if (p) {
|
||||
@@ -1392,21 +972,15 @@ int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
||||
!codec ||
|
||||
((priv_class = codec->priv_class) &&
|
||||
av_opt_find(&priv_class, t->key, NULL, flags,
|
||||
AV_OPT_SEARCH_FAKE_OBJ))) {
|
||||
AV_OPT_SEARCH_FAKE_OBJ)))
|
||||
av_dict_set(&ret, t->key, t->value, 0);
|
||||
used = 1;
|
||||
} else if (t->key[0] == prefix &&
|
||||
else if (t->key[0] == prefix &&
|
||||
av_opt_find(&cc, t->key + 1, NULL, flags,
|
||||
AV_OPT_SEARCH_FAKE_OBJ)) {
|
||||
AV_OPT_SEARCH_FAKE_OBJ))
|
||||
av_dict_set(&ret, t->key + 1, t->value, 0);
|
||||
used = 1;
|
||||
}
|
||||
|
||||
if (p)
|
||||
*p = ':';
|
||||
|
||||
if (used && opts_used)
|
||||
av_dict_set(opts_used, t->key, "", 0);
|
||||
}
|
||||
|
||||
*dst = ret;
|
||||
@@ -1414,7 +988,7 @@ int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
||||
}
|
||||
|
||||
int setup_find_stream_info_opts(AVFormatContext *s,
|
||||
AVDictionary *local_codec_opts,
|
||||
AVDictionary *codec_opts,
|
||||
AVDictionary ***dst)
|
||||
{
|
||||
int ret;
|
||||
@@ -1430,8 +1004,8 @@ int setup_find_stream_info_opts(AVFormatContext *s,
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
for (int i = 0; i < s->nb_streams; i++) {
|
||||
ret = filter_codec_opts(local_codec_opts, s->streams[i]->codecpar->codec_id,
|
||||
s, s->streams[i], NULL, &opts[i], NULL);
|
||||
ret = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id,
|
||||
s, s->streams[i], NULL, &opts[i]);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
}
|
||||
@@ -1476,7 +1050,7 @@ double get_rotation(const int32_t *displaymatrix)
|
||||
{
|
||||
double theta = 0;
|
||||
if (displaymatrix)
|
||||
theta = -round(av_display_rotation_get(displaymatrix));
|
||||
theta = -round(av_display_rotation_get((int32_t*) displaymatrix));
|
||||
|
||||
theta -= 360*floor(theta/360 + 0.9/360);
|
||||
|
||||
@@ -1488,49 +1062,3 @@ double get_rotation(const int32_t *displaymatrix)
|
||||
|
||||
return theta;
|
||||
}
|
||||
|
||||
/* read file contents into a string */
|
||||
char *file_read(const char *filename)
|
||||
{
|
||||
AVIOContext *pb = NULL;
|
||||
int ret = avio_open(&pb, filename, AVIO_FLAG_READ);
|
||||
AVBPrint bprint;
|
||||
char *str;
|
||||
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
|
||||
ret = avio_read_to_bprint(pb, &bprint, SIZE_MAX);
|
||||
avio_closep(&pb);
|
||||
if (ret < 0) {
|
||||
av_bprint_finalize(&bprint, NULL);
|
||||
return NULL;
|
||||
}
|
||||
ret = av_bprint_finalize(&bprint, &str);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
return str;
|
||||
}
|
||||
|
||||
void remove_avoptions(AVDictionary **a, AVDictionary *b)
|
||||
{
|
||||
const AVDictionaryEntry *t = NULL;
|
||||
|
||||
while ((t = av_dict_iterate(b, t))) {
|
||||
av_dict_set(a, t->key, NULL, AV_DICT_MATCH_CASE);
|
||||
}
|
||||
}
|
||||
|
||||
int check_avoptions(AVDictionary *m)
|
||||
{
|
||||
const AVDictionaryEntry *t = av_dict_iterate(m, NULL);
|
||||
if (t) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Option %s not found.\n", t->key);
|
||||
return AVERROR_OPTION_NOT_FOUND;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+42
-168
@@ -77,17 +77,6 @@ int opt_default(void *optctx, const char *opt, const char *arg);
|
||||
*/
|
||||
int opt_timelimit(void *optctx, const char *opt, const char *arg);
|
||||
|
||||
enum OptionType {
|
||||
OPT_TYPE_FUNC,
|
||||
OPT_TYPE_BOOL,
|
||||
OPT_TYPE_STRING,
|
||||
OPT_TYPE_INT,
|
||||
OPT_TYPE_INT64,
|
||||
OPT_TYPE_FLOAT,
|
||||
OPT_TYPE_DOUBLE,
|
||||
OPT_TYPE_TIME,
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a string and return its corresponding value as a double.
|
||||
*
|
||||
@@ -99,73 +88,11 @@ enum OptionType {
|
||||
* @param min the minimum valid accepted value
|
||||
* @param max the maximum valid accepted value
|
||||
*/
|
||||
int parse_number(const char *context, const char *numstr, enum OptionType type,
|
||||
int parse_number(const char *context, const char *numstr, int type,
|
||||
double min, double max, double *dst);
|
||||
|
||||
enum StreamList {
|
||||
STREAM_LIST_ALL,
|
||||
STREAM_LIST_STREAM_ID,
|
||||
STREAM_LIST_PROGRAM,
|
||||
STREAM_LIST_GROUP_ID,
|
||||
STREAM_LIST_GROUP_IDX,
|
||||
};
|
||||
|
||||
typedef struct StreamSpecifier {
|
||||
// trailing stream index - pick idx-th stream that matches
|
||||
// all the other constraints; -1 when not present
|
||||
int idx;
|
||||
|
||||
// which stream list to consider
|
||||
enum StreamList stream_list;
|
||||
|
||||
// STREAM_LIST_STREAM_ID: stream ID
|
||||
// STREAM_LIST_GROUP_IDX: group index
|
||||
// STREAM_LIST_GROUP_ID: group ID
|
||||
// STREAM_LIST_PROGRAM: program ID
|
||||
int64_t list_id;
|
||||
|
||||
// when not AVMEDIA_TYPE_UNKNOWN, consider only streams of this type
|
||||
enum AVMediaType media_type;
|
||||
uint8_t no_apic;
|
||||
|
||||
uint8_t usable_only;
|
||||
|
||||
int disposition;
|
||||
|
||||
char *meta_key;
|
||||
char *meta_val;
|
||||
|
||||
char *remainder;
|
||||
} StreamSpecifier;
|
||||
|
||||
/**
|
||||
* Parse a stream specifier string into a form suitable for matching.
|
||||
*
|
||||
* @param ss Parsed specifier will be stored here; must be uninitialized
|
||||
* with stream_specifier_uninit() when no longer needed.
|
||||
* @param spec String containing the stream specifier to be parsed.
|
||||
* @param allow_remainder When 1, the part of spec that is left after parsing
|
||||
* the stream specifier is stored into ss->remainder.
|
||||
* When 0, any remainder will cause parsing to fail.
|
||||
*/
|
||||
int stream_specifier_parse(StreamSpecifier *ss, const char *spec,
|
||||
int allow_remainder, void *logctx);
|
||||
|
||||
/**
|
||||
* @return 1 if st matches the parsed specifier, 0 if it does not
|
||||
*/
|
||||
unsigned stream_specifier_match(const StreamSpecifier *ss,
|
||||
const AVFormatContext *s, const AVStream *st,
|
||||
void *logctx);
|
||||
|
||||
void stream_specifier_uninit(StreamSpecifier *ss);
|
||||
|
||||
typedef struct SpecifierOpt {
|
||||
// original specifier or empty string
|
||||
char *specifier;
|
||||
// parsed specifier for OPT_FLAG_PERSTREAM options
|
||||
StreamSpecifier stream_spec;
|
||||
|
||||
char *specifier; /**< stream/chapter/program/... specifier */
|
||||
union {
|
||||
uint8_t *str;
|
||||
int i;
|
||||
@@ -176,73 +103,31 @@ typedef struct SpecifierOpt {
|
||||
} u;
|
||||
} SpecifierOpt;
|
||||
|
||||
typedef struct SpecifierOptList {
|
||||
SpecifierOpt *opt;
|
||||
int nb_opt;
|
||||
|
||||
/* Canonical option definition that was parsed into this list. */
|
||||
const struct OptionDef *opt_canon;
|
||||
/* Type corresponding to the field that should be used from SpecifierOpt.u.
|
||||
* May not match the option type, e.g. OPT_TYPE_BOOL options are stored as
|
||||
* int, so this field would be OPT_TYPE_INT for them */
|
||||
enum OptionType type;
|
||||
} SpecifierOptList;
|
||||
|
||||
typedef struct OptionDef {
|
||||
const char *name;
|
||||
enum OptionType type;
|
||||
int flags;
|
||||
|
||||
/* The OPT_TYPE_FUNC option takes an argument.
|
||||
* Must not be used with other option types, as for those it holds:
|
||||
* - OPT_TYPE_BOOL do not take an argument
|
||||
* - all other types do
|
||||
*/
|
||||
#define OPT_FUNC_ARG (1 << 0)
|
||||
/* Program will immediately exit after processing this option */
|
||||
#define OPT_EXIT (1 << 1)
|
||||
/* Option is intended for advanced users. Only affects
|
||||
* help output.
|
||||
*/
|
||||
#define OPT_EXPERT (1 << 2)
|
||||
#define OPT_VIDEO (1 << 3)
|
||||
#define OPT_AUDIO (1 << 4)
|
||||
#define OPT_SUBTITLE (1 << 5)
|
||||
#define OPT_DATA (1 << 6)
|
||||
/* The option is per-file (currently ffmpeg-only). At least one of OPT_INPUT,
|
||||
* OPT_OUTPUT, OPT_DECODER must be set when this flag is in use.
|
||||
*/
|
||||
#define OPT_PERFILE (1 << 7)
|
||||
|
||||
/* Option is specified as an offset in a passed optctx.
|
||||
* Always use as OPT_OFFSET in option definitions. */
|
||||
#define OPT_FLAG_OFFSET (1 << 8)
|
||||
#define OPT_OFFSET (OPT_FLAG_OFFSET | OPT_PERFILE)
|
||||
|
||||
/* Option is to be stored in a SpecifierOptList.
|
||||
Always use as OPT_SPEC in option definitions. */
|
||||
#define OPT_FLAG_SPEC (1 << 9)
|
||||
#define OPT_SPEC (OPT_FLAG_SPEC | OPT_OFFSET)
|
||||
|
||||
/* Option applies per-stream (implies OPT_SPEC). */
|
||||
#define OPT_FLAG_PERSTREAM (1 << 10)
|
||||
#define OPT_PERSTREAM (OPT_FLAG_PERSTREAM | OPT_SPEC)
|
||||
|
||||
/* ffmpeg-only - specifies whether an OPT_PERFILE option applies to input,
|
||||
* output, or both. */
|
||||
#define OPT_INPUT (1 << 11)
|
||||
#define OPT_OUTPUT (1 << 12)
|
||||
|
||||
/* This option is a "canonical" form, to which one or more alternatives
|
||||
* exist. These alternatives are listed in u1.names_alt. */
|
||||
#define OPT_HAS_ALT (1 << 13)
|
||||
/* This option is an alternative form of some other option, whose
|
||||
* name is stored in u1.name_canon */
|
||||
#define OPT_HAS_CANON (1 << 14)
|
||||
|
||||
/* ffmpeg-only - OPT_PERFILE may apply to standalone decoders */
|
||||
#define OPT_DECODER (1 << 15)
|
||||
|
||||
#define HAS_ARG 0x0001
|
||||
#define OPT_BOOL 0x0002
|
||||
#define OPT_EXPERT 0x0004
|
||||
#define OPT_STRING 0x0008
|
||||
#define OPT_VIDEO 0x0010
|
||||
#define OPT_AUDIO 0x0020
|
||||
#define OPT_INT 0x0080
|
||||
#define OPT_FLOAT 0x0100
|
||||
#define OPT_SUBTITLE 0x0200
|
||||
#define OPT_INT64 0x0400
|
||||
#define OPT_EXIT 0x0800
|
||||
#define OPT_DATA 0x1000
|
||||
#define OPT_PERFILE 0x2000 /* the option is per-file (currently ffmpeg-only).
|
||||
implied by OPT_OFFSET or OPT_SPEC */
|
||||
#define OPT_OFFSET 0x4000 /* option is specified as an offset in a passed optctx */
|
||||
#define OPT_SPEC 0x8000 /* option is to be stored in an array of SpecifierOpt.
|
||||
Implies OPT_OFFSET. Next element after the offset is
|
||||
an int containing element count in the array. */
|
||||
#define OPT_TIME 0x10000
|
||||
#define OPT_DOUBLE 0x20000
|
||||
#define OPT_INPUT 0x40000
|
||||
#define OPT_OUTPUT 0x80000
|
||||
union {
|
||||
void *dst_ptr;
|
||||
int (*func_arg)(void *, const char *, const char *);
|
||||
@@ -250,15 +135,6 @@ typedef struct OptionDef {
|
||||
} u;
|
||||
const char *help;
|
||||
const char *argname;
|
||||
|
||||
union {
|
||||
/* Name of the canonical form of this option.
|
||||
* Is valid when OPT_HAS_CANON is set. */
|
||||
const char *name_canon;
|
||||
/* A NULL-terminated list of alternate forms of this option.
|
||||
* Is valid when OPT_HAS_ALT is set. */
|
||||
const char * const *names_alt;
|
||||
} u1;
|
||||
} OptionDef;
|
||||
|
||||
/**
|
||||
@@ -268,9 +144,10 @@ typedef struct OptionDef {
|
||||
* @param msg title of this group. Only printed if at least one option matches.
|
||||
* @param req_flags print only options which have all those flags set.
|
||||
* @param rej_flags don't print options which have any of those flags set.
|
||||
* @param alt_flags print only options that have at least one of those flags set
|
||||
*/
|
||||
void show_help_options(const OptionDef *options, const char *msg, int req_flags,
|
||||
int rej_flags);
|
||||
int rej_flags, int alt_flags);
|
||||
|
||||
/**
|
||||
* Show help for all options with given flags in class and all its
|
||||
@@ -372,7 +249,7 @@ typedef struct OptionParseContext {
|
||||
*
|
||||
* @param optctx an app-specific options context. NULL for global options group
|
||||
*/
|
||||
int parse_optgroup(void *optctx, OptionGroup *g, const OptionDef *defs);
|
||||
int parse_optgroup(void *optctx, OptionGroup *g);
|
||||
|
||||
/**
|
||||
* Split the commandline into an intermediate form convenient for further
|
||||
@@ -436,13 +313,11 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec);
|
||||
* @param codec The particular codec for which the options should be filtered.
|
||||
* If null, the default one is looked up according to the codec id.
|
||||
* @param dst a pointer to the created dictionary
|
||||
* @param opts_used if non-NULL, every option stored in dst is also stored here,
|
||||
* with specifiers preserved
|
||||
* @return a non-negative number on success, a negative error code on failure
|
||||
*/
|
||||
int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
||||
AVFormatContext *s, AVStream *st, const AVCodec *codec,
|
||||
AVDictionary **dst, AVDictionary **opts_used);
|
||||
AVDictionary **dst);
|
||||
|
||||
/**
|
||||
* Setup AVCodecContext options for avformat_find_stream_info().
|
||||
@@ -465,10 +340,7 @@ int setup_find_stream_info_opts(AVFormatContext *s,
|
||||
*
|
||||
* @see av_strerror()
|
||||
*/
|
||||
static inline void print_error(const char *filename, int err)
|
||||
{
|
||||
av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, av_err2str(err));
|
||||
}
|
||||
void print_error(const char *filename, int err);
|
||||
|
||||
/**
|
||||
* Print the program banner to stderr. The banner contents depend on the
|
||||
@@ -532,17 +404,19 @@ void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems);
|
||||
#define GROW_ARRAY(array, nb_elems)\
|
||||
grow_array((void**)&array, sizeof(*array), &nb_elems, nb_elems + 1)
|
||||
|
||||
#define GET_PIX_FMT_NAME(pix_fmt)\
|
||||
const char *name = av_get_pix_fmt_name(pix_fmt);
|
||||
|
||||
#define GET_CODEC_NAME(id)\
|
||||
const char *name = avcodec_descriptor_get(id)->name;
|
||||
|
||||
#define GET_SAMPLE_FMT_NAME(sample_fmt)\
|
||||
const char *name = av_get_sample_fmt_name(sample_fmt)
|
||||
|
||||
#define GET_SAMPLE_RATE_NAME(rate)\
|
||||
char name[16];\
|
||||
snprintf(name, sizeof(name), "%d", rate);
|
||||
|
||||
double get_rotation(const int32_t *displaymatrix);
|
||||
|
||||
/* read file contents into a string */
|
||||
char *file_read(const char *filename);
|
||||
|
||||
/* Remove keys in dictionary b from dictionary a */
|
||||
void remove_avoptions(AVDictionary **a, AVDictionary *b);
|
||||
|
||||
/* Check if any keys exist in dictionary m */
|
||||
int check_avoptions(AVDictionary *m);
|
||||
|
||||
int cmdutils_isalnum(char c);
|
||||
|
||||
#endif /* FFTOOLS_CMDUTILS_H */
|
||||
|
||||
+535
-199
@@ -68,19 +68,38 @@
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/bprint.h"
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/display.h"
|
||||
#include "libavutil/fifo.h"
|
||||
#include "libavutil/hwcontext.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/libm.h"
|
||||
#include "libavutil/mathematics.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "libavutil/parseutils.h"
|
||||
#include "libavutil/pixdesc.h"
|
||||
#include "libavutil/samplefmt.h"
|
||||
#include "libavutil/thread.h"
|
||||
#include "libavutil/threadmessage.h"
|
||||
#include "libavutil/time.h"
|
||||
#include "libavutil/timestamp.h"
|
||||
|
||||
#include "libavcodec/version.h"
|
||||
|
||||
#include "libavformat/avformat.h"
|
||||
|
||||
#include "libavdevice/avdevice.h"
|
||||
|
||||
#include "libswresample/swresample.h"
|
||||
|
||||
#include "cmdutils.h"
|
||||
#include "ffmpeg.h"
|
||||
#include "ffmpeg_sched.h"
|
||||
#include "ffmpeg_utils.h"
|
||||
#include "sync_queue.h"
|
||||
|
||||
const char program_name[] = "ffmpeg";
|
||||
const int program_birth_year = 2000;
|
||||
@@ -96,7 +115,7 @@ typedef struct BenchmarkTimeStamps {
|
||||
static BenchmarkTimeStamps get_benchmark_time_stamps(void);
|
||||
static int64_t getmaxrss(void);
|
||||
|
||||
atomic_uint nb_output_dumped = 0;
|
||||
unsigned nb_output_dumped = 0;
|
||||
|
||||
static BenchmarkTimeStamps current_time;
|
||||
AVIOContext *progress_avio = NULL;
|
||||
@@ -110,9 +129,6 @@ int nb_output_files = 0;
|
||||
FilterGraph **filtergraphs;
|
||||
int nb_filtergraphs;
|
||||
|
||||
Decoder **decoders;
|
||||
int nb_decoders;
|
||||
|
||||
#if HAVE_TERMIOS_H
|
||||
|
||||
/* init terminal so that we can grab keys */
|
||||
@@ -120,6 +136,30 @@ static struct termios oldtty;
|
||||
static int restore_tty;
|
||||
#endif
|
||||
|
||||
/* sub2video hack:
|
||||
Convert subtitles to video with alpha to insert them in filter graphs.
|
||||
This is a temporary solution until libavfilter gets real subtitles support.
|
||||
*/
|
||||
|
||||
static void sub2video_heartbeat(InputFile *infile, int64_t pts, AVRational tb)
|
||||
{
|
||||
/* When a frame is read from a file, examine all sub2video streams in
|
||||
the same file and send the sub2video frame again. Otherwise, decoded
|
||||
video frames could be accumulating in the filter graph while a filter
|
||||
(possibly overlay) is desperately waiting for a subtitle frame. */
|
||||
for (int i = 0; i < infile->nb_streams; i++) {
|
||||
InputStream *ist = infile->streams[i];
|
||||
|
||||
if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < ist->nb_filters; j++)
|
||||
ifilter_sub2video_heartbeat(ist->filters[j], pts, tb);
|
||||
}
|
||||
}
|
||||
|
||||
/* end of sub2video hack */
|
||||
|
||||
static void term_exit_sigsafe(void)
|
||||
{
|
||||
#if HAVE_TERMIOS_H
|
||||
@@ -136,7 +176,7 @@ void term_exit(void)
|
||||
|
||||
static volatile int received_sigterm = 0;
|
||||
static volatile int received_nb_signals = 0;
|
||||
static atomic_int transcode_init_done = 0;
|
||||
static atomic_int transcode_init_done = ATOMIC_VAR_INIT(0);
|
||||
static volatile int ffmpeg_exited = 0;
|
||||
static int64_t copy_ts_first_pts = AV_NOPTS_VALUE;
|
||||
|
||||
@@ -308,25 +348,23 @@ const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
|
||||
|
||||
static void ffmpeg_cleanup(int ret)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (do_benchmark) {
|
||||
int64_t maxrss = getmaxrss() / 1024;
|
||||
av_log(NULL, AV_LOG_INFO, "bench: maxrss=%"PRId64"KiB\n", maxrss);
|
||||
int maxrss = getmaxrss() / 1024;
|
||||
av_log(NULL, AV_LOG_INFO, "bench: maxrss=%ikB\n", maxrss);
|
||||
}
|
||||
|
||||
for (int i = 0; i < nb_filtergraphs; i++)
|
||||
for (i = 0; i < nb_filtergraphs; i++)
|
||||
fg_free(&filtergraphs[i]);
|
||||
av_freep(&filtergraphs);
|
||||
|
||||
for (int i = 0; i < nb_output_files; i++)
|
||||
for (i = 0; i < nb_output_files; i++)
|
||||
of_free(&output_files[i]);
|
||||
|
||||
for (int i = 0; i < nb_input_files; i++)
|
||||
for (i = 0; i < nb_input_files; i++)
|
||||
ifile_close(&input_files[i]);
|
||||
|
||||
for (int i = 0; i < nb_decoders; i++)
|
||||
dec_free(&decoders[i]);
|
||||
av_freep(&decoders);
|
||||
|
||||
if (vstats_file) {
|
||||
if (fclose(vstats_file))
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
@@ -359,7 +397,7 @@ static void ffmpeg_cleanup(int ret)
|
||||
|
||||
OutputStream *ost_iter(OutputStream *prev)
|
||||
{
|
||||
int of_idx = prev ? prev->file->index : 0;
|
||||
int of_idx = prev ? prev->file_index : 0;
|
||||
int ost_idx = prev ? prev->index + 1 : 0;
|
||||
|
||||
for (; of_idx < nb_output_files; of_idx++) {
|
||||
@@ -375,7 +413,7 @@ OutputStream *ost_iter(OutputStream *prev)
|
||||
|
||||
InputStream *ist_iter(InputStream *prev)
|
||||
{
|
||||
int if_idx = prev ? prev->file->index : 0;
|
||||
int if_idx = prev ? prev->file_index : 0;
|
||||
int ist_idx = prev ? prev->index + 1 : 0;
|
||||
|
||||
for (; if_idx < nb_input_files; if_idx++) {
|
||||
@@ -389,136 +427,38 @@ InputStream *ist_iter(InputStream *prev)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void frame_data_free(void *opaque, uint8_t *data)
|
||||
{
|
||||
FrameData *fd = (FrameData *)data;
|
||||
|
||||
avcodec_parameters_free(&fd->par_enc);
|
||||
|
||||
av_free(data);
|
||||
}
|
||||
|
||||
static int frame_data_ensure(AVBufferRef **dst, int writable)
|
||||
{
|
||||
AVBufferRef *src = *dst;
|
||||
|
||||
if (!src || (writable && !av_buffer_is_writable(src))) {
|
||||
FrameData *fd;
|
||||
|
||||
fd = av_mallocz(sizeof(*fd));
|
||||
if (!fd)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
*dst = av_buffer_create((uint8_t *)fd, sizeof(*fd),
|
||||
frame_data_free, NULL, 0);
|
||||
if (!*dst) {
|
||||
av_buffer_unref(&src);
|
||||
av_freep(&fd);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
if (src) {
|
||||
const FrameData *fd_src = (const FrameData *)src->data;
|
||||
|
||||
memcpy(fd, fd_src, sizeof(*fd));
|
||||
fd->par_enc = NULL;
|
||||
|
||||
if (fd_src->par_enc) {
|
||||
int ret = 0;
|
||||
|
||||
fd->par_enc = avcodec_parameters_alloc();
|
||||
ret = fd->par_enc ?
|
||||
avcodec_parameters_copy(fd->par_enc, fd_src->par_enc) :
|
||||
AVERROR(ENOMEM);
|
||||
if (ret < 0) {
|
||||
av_buffer_unref(dst);
|
||||
av_buffer_unref(&src);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
av_buffer_unref(&src);
|
||||
} else {
|
||||
fd->dec.frame_num = UINT64_MAX;
|
||||
fd->dec.pts = AV_NOPTS_VALUE;
|
||||
|
||||
for (unsigned i = 0; i < FF_ARRAY_ELEMS(fd->wallclock); i++)
|
||||
fd->wallclock[i] = INT64_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FrameData *frame_data(AVFrame *frame)
|
||||
{
|
||||
int ret = frame_data_ensure(&frame->opaque_ref, 1);
|
||||
return ret < 0 ? NULL : (FrameData*)frame->opaque_ref->data;
|
||||
if (!frame->opaque_ref) {
|
||||
FrameData *fd;
|
||||
|
||||
frame->opaque_ref = av_buffer_allocz(sizeof(*fd));
|
||||
if (!frame->opaque_ref)
|
||||
return NULL;
|
||||
fd = (FrameData*)frame->opaque_ref->data;
|
||||
|
||||
fd->dec.frame_num = UINT64_MAX;
|
||||
fd->dec.pts = AV_NOPTS_VALUE;
|
||||
}
|
||||
|
||||
return (FrameData*)frame->opaque_ref->data;
|
||||
}
|
||||
|
||||
const FrameData *frame_data_c(AVFrame *frame)
|
||||
void remove_avoptions(AVDictionary **a, AVDictionary *b)
|
||||
{
|
||||
int ret = frame_data_ensure(&frame->opaque_ref, 0);
|
||||
return ret < 0 ? NULL : (const FrameData*)frame->opaque_ref->data;
|
||||
const AVDictionaryEntry *t = NULL;
|
||||
|
||||
while ((t = av_dict_iterate(b, t))) {
|
||||
av_dict_set(a, t->key, NULL, AV_DICT_MATCH_CASE);
|
||||
}
|
||||
}
|
||||
|
||||
FrameData *packet_data(AVPacket *pkt)
|
||||
int check_avoptions(AVDictionary *m)
|
||||
{
|
||||
int ret = frame_data_ensure(&pkt->opaque_ref, 1);
|
||||
return ret < 0 ? NULL : (FrameData*)pkt->opaque_ref->data;
|
||||
}
|
||||
|
||||
const FrameData *packet_data_c(AVPacket *pkt)
|
||||
{
|
||||
int ret = frame_data_ensure(&pkt->opaque_ref, 0);
|
||||
return ret < 0 ? NULL : (const FrameData*)pkt->opaque_ref->data;
|
||||
}
|
||||
|
||||
int check_avoptions_used(const AVDictionary *opts, const AVDictionary *opts_used,
|
||||
void *logctx, int decode)
|
||||
{
|
||||
const AVClass *class = avcodec_get_class();
|
||||
const AVClass *fclass = avformat_get_class();
|
||||
|
||||
const int flag = decode ? AV_OPT_FLAG_DECODING_PARAM :
|
||||
AV_OPT_FLAG_ENCODING_PARAM;
|
||||
const AVDictionaryEntry *e = NULL;
|
||||
|
||||
while ((e = av_dict_iterate(opts, e))) {
|
||||
const AVOption *option, *foption;
|
||||
char *optname, *p;
|
||||
|
||||
if (av_dict_get(opts_used, e->key, NULL, 0))
|
||||
continue;
|
||||
|
||||
optname = av_strdup(e->key);
|
||||
if (!optname)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
p = strchr(optname, ':');
|
||||
if (p)
|
||||
*p = 0;
|
||||
|
||||
option = av_opt_find(&class, optname, NULL, 0,
|
||||
AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
|
||||
foption = av_opt_find(&fclass, optname, NULL, 0,
|
||||
AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
|
||||
av_freep(&optname);
|
||||
if (!option || foption)
|
||||
continue;
|
||||
|
||||
if (!(option->flags & flag)) {
|
||||
av_log(logctx, AV_LOG_ERROR, "Codec AVOption %s (%s) is not a %s "
|
||||
"option.\n", e->key, option->help ? option->help : "",
|
||||
decode ? "decoding" : "encoding");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
av_log(logctx, AV_LOG_WARNING, "Codec AVOption %s (%s) has not been used "
|
||||
"for any stream. The most likely reason is either wrong type "
|
||||
"(e.g. a video option with no video streams) or that it is a "
|
||||
"private option of some decoder which was not actually used "
|
||||
"for any stream.\n", e->key, option->help ? option->help : "");
|
||||
const AVDictionaryEntry *t;
|
||||
if ((t = av_dict_get(m, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Option %s not found.\n", t->key);
|
||||
return AVERROR_OPTION_NOT_FOUND;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -545,13 +485,23 @@ void update_benchmark(const char *fmt, ...)
|
||||
}
|
||||
}
|
||||
|
||||
static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time, int64_t pts)
|
||||
void close_output_stream(OutputStream *ost)
|
||||
{
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
ost->finished |= ENCODER_FINISHED;
|
||||
|
||||
if (ost->sq_idx_encode >= 0)
|
||||
sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL));
|
||||
}
|
||||
|
||||
static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time)
|
||||
{
|
||||
AVBPrint buf, buf_script;
|
||||
int64_t total_size = of_filesize(output_files[0]);
|
||||
int vid;
|
||||
double bitrate;
|
||||
double speed;
|
||||
int64_t pts = AV_NOPTS_VALUE;
|
||||
static int64_t last_time = -1;
|
||||
static int first_report = 1;
|
||||
uint64_t nb_frames_dup = 0, nb_frames_drop = 0;
|
||||
@@ -569,7 +519,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
|
||||
last_time = cur_time;
|
||||
}
|
||||
if (((cur_time - last_time) < stats_period && !first_report) ||
|
||||
(first_report && atomic_load(&nb_output_dumped) < nb_output_files))
|
||||
(first_report && nb_output_dumped < nb_output_files))
|
||||
return;
|
||||
last_time = cur_time;
|
||||
}
|
||||
@@ -580,14 +530,14 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
|
||||
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
|
||||
av_bprint_init(&buf_script, 0, AV_BPRINT_SIZE_AUTOMATIC);
|
||||
for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
|
||||
const float q = ost->enc ? atomic_load(&ost->quality) / (float) FF_QP2LAMBDA : -1;
|
||||
const float q = ost->enc ? ost->quality / (float) FF_QP2LAMBDA : -1;
|
||||
|
||||
if (vid && ost->type == AVMEDIA_TYPE_VIDEO) {
|
||||
av_bprintf(&buf, "q=%2.1f ", q);
|
||||
av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n",
|
||||
ost->file->index, ost->index, q);
|
||||
ost->file_index, ost->index, q);
|
||||
}
|
||||
if (!vid && ost->type == AVMEDIA_TYPE_VIDEO) {
|
||||
if (!vid && ost->type == AVMEDIA_TYPE_VIDEO && ost->filter) {
|
||||
float fps;
|
||||
uint64_t frame_number = atomic_load(&ost->packets_written);
|
||||
|
||||
@@ -597,24 +547,26 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
|
||||
av_bprintf(&buf_script, "frame=%"PRId64"\n", frame_number);
|
||||
av_bprintf(&buf_script, "fps=%.2f\n", fps);
|
||||
av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n",
|
||||
ost->file->index, ost->index, q);
|
||||
ost->file_index, ost->index, q);
|
||||
if (is_last_report)
|
||||
av_bprintf(&buf, "L");
|
||||
|
||||
if (ost->filter) {
|
||||
nb_frames_dup = atomic_load(&ost->filter->nb_frames_dup);
|
||||
nb_frames_drop = atomic_load(&ost->filter->nb_frames_drop);
|
||||
}
|
||||
nb_frames_dup = ost->filter->nb_frames_dup;
|
||||
nb_frames_drop = ost->filter->nb_frames_drop;
|
||||
|
||||
vid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_ts) {
|
||||
if (copy_ts_first_pts == AV_NOPTS_VALUE && pts > 1)
|
||||
copy_ts_first_pts = pts;
|
||||
if (copy_ts_first_pts != AV_NOPTS_VALUE)
|
||||
pts -= copy_ts_first_pts;
|
||||
/* compute min output value */
|
||||
if (ost->last_mux_dts != AV_NOPTS_VALUE) {
|
||||
if (pts == AV_NOPTS_VALUE || ost->last_mux_dts > pts)
|
||||
pts = ost->last_mux_dts;
|
||||
if (copy_ts) {
|
||||
if (copy_ts_first_pts == AV_NOPTS_VALUE && pts > 1)
|
||||
copy_ts_first_pts = pts;
|
||||
if (copy_ts_first_pts != AV_NOPTS_VALUE)
|
||||
pts -= copy_ts_first_pts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
us = FFABS64U(pts) % AV_TIME_BASE;
|
||||
@@ -627,7 +579,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
|
||||
speed = pts != AV_NOPTS_VALUE && t != 0.0 ? (double)pts / AV_TIME_BASE / t : -1;
|
||||
|
||||
if (total_size < 0) av_bprintf(&buf, "size=N/A time=");
|
||||
else av_bprintf(&buf, "size=%8.0fKiB time=", total_size / 1024.0);
|
||||
else av_bprintf(&buf, "size=%8.0fkB time=", total_size / 1024.0);
|
||||
if (pts == AV_NOPTS_VALUE) {
|
||||
av_bprintf(&buf, "N/A ");
|
||||
} else {
|
||||
@@ -697,6 +649,201 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
|
||||
first_report = 0;
|
||||
}
|
||||
|
||||
int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src)
|
||||
{
|
||||
int ret = AVERROR_BUG;
|
||||
AVSubtitle tmp = {
|
||||
.format = src->format,
|
||||
.start_display_time = src->start_display_time,
|
||||
.end_display_time = src->end_display_time,
|
||||
.num_rects = 0,
|
||||
.rects = NULL,
|
||||
.pts = src->pts
|
||||
};
|
||||
|
||||
if (!src->num_rects)
|
||||
goto success;
|
||||
|
||||
if (!(tmp.rects = av_calloc(src->num_rects, sizeof(*tmp.rects))))
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
for (int i = 0; i < src->num_rects; i++) {
|
||||
AVSubtitleRect *src_rect = src->rects[i];
|
||||
AVSubtitleRect *dst_rect;
|
||||
|
||||
if (!(dst_rect = tmp.rects[i] = av_mallocz(sizeof(*tmp.rects[0])))) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
tmp.num_rects++;
|
||||
|
||||
dst_rect->type = src_rect->type;
|
||||
dst_rect->flags = src_rect->flags;
|
||||
|
||||
dst_rect->x = src_rect->x;
|
||||
dst_rect->y = src_rect->y;
|
||||
dst_rect->w = src_rect->w;
|
||||
dst_rect->h = src_rect->h;
|
||||
dst_rect->nb_colors = src_rect->nb_colors;
|
||||
|
||||
if (src_rect->text)
|
||||
if (!(dst_rect->text = av_strdup(src_rect->text))) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (src_rect->ass)
|
||||
if (!(dst_rect->ass = av_strdup(src_rect->ass))) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
// SUBTITLE_BITMAP images are special in the sense that they
|
||||
// are like PAL8 images. first pointer to data, second to
|
||||
// palette. This makes the size calculation match this.
|
||||
size_t buf_size = src_rect->type == SUBTITLE_BITMAP && j == 1 ?
|
||||
AVPALETTE_SIZE :
|
||||
src_rect->h * src_rect->linesize[j];
|
||||
|
||||
if (!src_rect->data[j])
|
||||
continue;
|
||||
|
||||
if (!(dst_rect->data[j] = av_memdup(src_rect->data[j], buf_size))) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto cleanup;
|
||||
}
|
||||
dst_rect->linesize[j] = src_rect->linesize[j];
|
||||
}
|
||||
}
|
||||
|
||||
success:
|
||||
*dst = tmp;
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
avsubtitle_free(&tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void subtitle_free(void *opaque, uint8_t *data)
|
||||
{
|
||||
AVSubtitle *sub = (AVSubtitle*)data;
|
||||
avsubtitle_free(sub);
|
||||
av_free(sub);
|
||||
}
|
||||
|
||||
int subtitle_wrap_frame(AVFrame *frame, AVSubtitle *subtitle, int copy)
|
||||
{
|
||||
AVBufferRef *buf;
|
||||
AVSubtitle *sub;
|
||||
int ret;
|
||||
|
||||
if (copy) {
|
||||
sub = av_mallocz(sizeof(*sub));
|
||||
ret = sub ? copy_av_subtitle(sub, subtitle) : AVERROR(ENOMEM);
|
||||
if (ret < 0) {
|
||||
av_freep(&sub);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
sub = av_memdup(subtitle, sizeof(*subtitle));
|
||||
if (!sub)
|
||||
return AVERROR(ENOMEM);
|
||||
memset(subtitle, 0, sizeof(*subtitle));
|
||||
}
|
||||
|
||||
buf = av_buffer_create((uint8_t*)sub, sizeof(*sub),
|
||||
subtitle_free, NULL, 0);
|
||||
if (!buf) {
|
||||
avsubtitle_free(sub);
|
||||
av_freep(&sub);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
frame->buf[0] = buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt)
|
||||
{
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
int64_t signal_pts = av_rescale_q(pkt->pts, pkt->time_base,
|
||||
AV_TIME_BASE_Q);
|
||||
|
||||
if (!ost->fix_sub_duration_heartbeat || !(pkt->flags & AV_PKT_FLAG_KEY))
|
||||
// we are only interested in heartbeats on streams configured, and
|
||||
// only on random access points.
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < of->nb_streams; i++) {
|
||||
OutputStream *iter_ost = of->streams[i];
|
||||
InputStream *ist = iter_ost->ist;
|
||||
int ret = AVERROR_BUG;
|
||||
|
||||
if (iter_ost == ost || !ist || !ist->decoding_needed ||
|
||||
ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE)
|
||||
// We wish to skip the stream that causes the heartbeat,
|
||||
// output streams without an input stream, streams not decoded
|
||||
// (as fix_sub_duration is only done for decoded subtitles) as
|
||||
// well as non-subtitle streams.
|
||||
continue;
|
||||
|
||||
if ((ret = fix_sub_duration_heartbeat(ist, signal_pts)) < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pkt = NULL means EOF (needed to flush decoder buffers) */
|
||||
static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof)
|
||||
{
|
||||
InputFile *f = input_files[ist->file_index];
|
||||
int64_t dts_est = AV_NOPTS_VALUE;
|
||||
int ret = 0;
|
||||
int eof_reached = 0;
|
||||
|
||||
if (ist->decoding_needed) {
|
||||
ret = dec_packet(ist, pkt, no_eof);
|
||||
if (ret < 0 && ret != AVERROR_EOF)
|
||||
return ret;
|
||||
}
|
||||
if (ret == AVERROR_EOF || (!pkt && !ist->decoding_needed))
|
||||
eof_reached = 1;
|
||||
|
||||
if (pkt && pkt->opaque_ref) {
|
||||
DemuxPktData *pd = (DemuxPktData*)pkt->opaque_ref->data;
|
||||
dts_est = pd->dts_est;
|
||||
}
|
||||
|
||||
if (f->recording_time != INT64_MAX) {
|
||||
int64_t start_time = 0;
|
||||
if (copy_ts) {
|
||||
start_time += f->start_time != AV_NOPTS_VALUE ? f->start_time : 0;
|
||||
start_time += start_at_zero ? 0 : f->start_time_effective;
|
||||
}
|
||||
if (dts_est >= f->recording_time + start_time)
|
||||
pkt = NULL;
|
||||
}
|
||||
|
||||
for (int oidx = 0; oidx < ist->nb_outputs; oidx++) {
|
||||
OutputStream *ost = ist->outputs[oidx];
|
||||
if (ost->enc || (!pkt && no_eof))
|
||||
continue;
|
||||
|
||||
ret = of_streamcopy(ost, pkt, dts_est);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return !eof_reached;
|
||||
}
|
||||
|
||||
static void print_stream_maps(void)
|
||||
{
|
||||
av_log(NULL, AV_LOG_INFO, "Stream mapping:\n");
|
||||
@@ -704,7 +851,7 @@ static void print_stream_maps(void)
|
||||
for (int j = 0; j < ist->nb_filters; j++) {
|
||||
if (!filtergraph_is_simple(ist->filters[j]->graph)) {
|
||||
av_log(NULL, AV_LOG_INFO, " Stream #%d:%d (%s) -> %s",
|
||||
ist->file->index, ist->index, ist->dec ? ist->dec->name : "?",
|
||||
ist->file_index, ist->index, ist->dec ? ist->dec->name : "?",
|
||||
ist->filters[j]->name);
|
||||
if (nb_filtergraphs > 1)
|
||||
av_log(NULL, AV_LOG_INFO, " (graph %d)", ist->filters[j]->graph->index);
|
||||
@@ -717,7 +864,7 @@ static void print_stream_maps(void)
|
||||
if (ost->attachment_filename) {
|
||||
/* an attached file */
|
||||
av_log(NULL, AV_LOG_INFO, " File %s -> Stream #%d:%d\n",
|
||||
ost->attachment_filename, ost->file->index, ost->index);
|
||||
ost->attachment_filename, ost->file_index, ost->index);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -727,15 +874,15 @@ static void print_stream_maps(void)
|
||||
if (nb_filtergraphs > 1)
|
||||
av_log(NULL, AV_LOG_INFO, " (graph %d)", ost->filter->graph->index);
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, " -> Stream #%d:%d (%s)\n", ost->file->index,
|
||||
av_log(NULL, AV_LOG_INFO, " -> Stream #%d:%d (%s)\n", ost->file_index,
|
||||
ost->index, ost->enc_ctx->codec->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, " Stream #%d:%d -> #%d:%d",
|
||||
ost->ist->file->index,
|
||||
ost->ist->file_index,
|
||||
ost->ist->index,
|
||||
ost->file->index,
|
||||
ost->file_index,
|
||||
ost->index);
|
||||
if (ost->enc_ctx) {
|
||||
const AVCodec *in_codec = ost->ist->dec;
|
||||
@@ -773,6 +920,43 @@ static void print_stream_maps(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the output stream to process.
|
||||
*
|
||||
* @retval 0 an output stream was selected
|
||||
* @retval AVERROR(EAGAIN) need to wait until more input is available
|
||||
* @retval AVERROR_EOF no more streams need output
|
||||
*/
|
||||
static int choose_output(OutputStream **post)
|
||||
{
|
||||
int64_t opts_min = INT64_MAX;
|
||||
OutputStream *ost_min = NULL;
|
||||
|
||||
for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
|
||||
int64_t opts;
|
||||
|
||||
if (ost->filter && ost->filter->last_pts != AV_NOPTS_VALUE) {
|
||||
opts = ost->filter->last_pts;
|
||||
} else {
|
||||
opts = ost->last_mux_dts == AV_NOPTS_VALUE ?
|
||||
INT64_MIN : ost->last_mux_dts;
|
||||
}
|
||||
|
||||
if (!ost->initialized && !ost->finished) {
|
||||
ost_min = ost;
|
||||
break;
|
||||
}
|
||||
if (!ost->finished && opts < opts_min) {
|
||||
opts_min = opts;
|
||||
ost_min = ost;
|
||||
}
|
||||
}
|
||||
if (!ost_min)
|
||||
return AVERROR_EOF;
|
||||
*post = ost_min;
|
||||
return ost_min->unavailable ? AVERROR(EAGAIN) : 0;
|
||||
}
|
||||
|
||||
static void set_tty_echo(int on)
|
||||
{
|
||||
#if HAVE_TERMIOS_H
|
||||
@@ -820,11 +1004,6 @@ static int check_keyboard_interaction(int64_t cur_time)
|
||||
(n = sscanf(buf, "%63[^ ] %lf %255[^ ] %255[^\n]", target, &time, command, arg)) >= 3) {
|
||||
av_log(NULL, AV_LOG_DEBUG, "Processing command target:%s time:%f command:%s arg:%s",
|
||||
target, time, command, arg);
|
||||
for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
|
||||
if (ost->fg_simple)
|
||||
fg_send_command(ost->fg_simple, time, target, command, arg,
|
||||
key == 'C');
|
||||
}
|
||||
for (i = 0; i < nb_filtergraphs; i++)
|
||||
fg_send_command(filtergraphs[i], time, target, command, arg,
|
||||
key == 'C');
|
||||
@@ -849,29 +1028,161 @@ static int check_keyboard_interaction(int64_t cur_time)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void reset_eagain(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nb_input_files; i++)
|
||||
input_files[i]->eagain = 0;
|
||||
for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost))
|
||||
ost->unavailable = 0;
|
||||
}
|
||||
|
||||
static void decode_flush(InputFile *ifile)
|
||||
{
|
||||
for (int i = 0; i < ifile->nb_streams; i++) {
|
||||
InputStream *ist = ifile->streams[i];
|
||||
|
||||
if (ist->discard || !ist->decoding_needed)
|
||||
continue;
|
||||
|
||||
dec_packet(ist, NULL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return
|
||||
* - 0 -- one packet was read and processed
|
||||
* - AVERROR(EAGAIN) -- no packets were available for selected file,
|
||||
* this function should be called again
|
||||
* - AVERROR_EOF -- this function should not be called again
|
||||
*/
|
||||
static int process_input(int file_index)
|
||||
{
|
||||
InputFile *ifile = input_files[file_index];
|
||||
InputStream *ist;
|
||||
AVPacket *pkt;
|
||||
int ret, i;
|
||||
|
||||
ret = ifile_get_packet(ifile, &pkt);
|
||||
|
||||
if (ret == AVERROR(EAGAIN)) {
|
||||
ifile->eagain = 1;
|
||||
return ret;
|
||||
}
|
||||
if (ret == 1) {
|
||||
/* the input file is looped: flush the decoders */
|
||||
decode_flush(ifile);
|
||||
return AVERROR(EAGAIN);
|
||||
}
|
||||
if (ret < 0) {
|
||||
if (ret != AVERROR_EOF) {
|
||||
av_log(ifile, AV_LOG_ERROR,
|
||||
"Error retrieving a packet from demuxer: %s\n", av_err2str(ret));
|
||||
if (exit_on_error)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ifile->nb_streams; i++) {
|
||||
ist = ifile->streams[i];
|
||||
if (!ist->discard) {
|
||||
ret = process_input_packet(ist, NULL, 0);
|
||||
if (ret>0)
|
||||
return 0;
|
||||
else if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* mark all outputs that don't go through lavfi as finished */
|
||||
for (int oidx = 0; oidx < ist->nb_outputs; oidx++) {
|
||||
OutputStream *ost = ist->outputs[oidx];
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
|
||||
ret = of_output_packet(of, ost, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ifile->eof_reached = 1;
|
||||
return AVERROR(EAGAIN);
|
||||
}
|
||||
|
||||
reset_eagain();
|
||||
|
||||
ist = ifile->streams[pkt->stream_index];
|
||||
|
||||
sub2video_heartbeat(ifile, pkt->pts, pkt->time_base);
|
||||
|
||||
ret = process_input_packet(ist, pkt, 0);
|
||||
|
||||
av_packet_free(&pkt);
|
||||
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a single step of transcoding.
|
||||
*
|
||||
* @return 0 for success, <0 for error
|
||||
*/
|
||||
static int transcode_step(OutputStream *ost)
|
||||
{
|
||||
InputStream *ist = NULL;
|
||||
int ret;
|
||||
|
||||
if (ost->filter) {
|
||||
if ((ret = fg_transcode_step(ost->filter->graph, &ist)) < 0)
|
||||
return ret;
|
||||
if (!ist)
|
||||
return 0;
|
||||
} else {
|
||||
ist = ost->ist;
|
||||
av_assert0(ist);
|
||||
}
|
||||
|
||||
ret = process_input(ist->file_index);
|
||||
if (ret == AVERROR(EAGAIN)) {
|
||||
if (input_files[ist->file_index]->eagain)
|
||||
ost->unavailable = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return ret == AVERROR_EOF ? 0 : ret;
|
||||
|
||||
// process_input() above might have caused output to become available
|
||||
// in multiple filtergraphs, so we process all of them
|
||||
for (int i = 0; i < nb_filtergraphs; i++) {
|
||||
ret = reap_filters(filtergraphs[i], 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following code is the main loop of the file converter
|
||||
*/
|
||||
static int transcode(Scheduler *sch)
|
||||
static int transcode(int *err_rate_exceeded)
|
||||
{
|
||||
int ret = 0;
|
||||
int64_t timer_start, transcode_ts = 0;
|
||||
int ret = 0, i;
|
||||
InputStream *ist;
|
||||
int64_t timer_start;
|
||||
|
||||
print_stream_maps();
|
||||
|
||||
*err_rate_exceeded = 0;
|
||||
atomic_store(&transcode_init_done, 1);
|
||||
|
||||
ret = sch_start(sch);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (stdin_interaction) {
|
||||
av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");
|
||||
}
|
||||
|
||||
timer_start = av_gettime_relative();
|
||||
|
||||
while (!sch_wait(sch, stats_period, &transcode_ts)) {
|
||||
while (!received_sigterm) {
|
||||
OutputStream *ost;
|
||||
int64_t cur_time= av_gettime_relative();
|
||||
|
||||
/* if 'q' pressed, exits */
|
||||
@@ -879,22 +1190,58 @@ static int transcode(Scheduler *sch)
|
||||
if (check_keyboard_interaction(cur_time) < 0)
|
||||
break;
|
||||
|
||||
ret = choose_output(&ost);
|
||||
if (ret == AVERROR(EAGAIN)) {
|
||||
reset_eagain();
|
||||
av_usleep(10000);
|
||||
ret = 0;
|
||||
continue;
|
||||
} else if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_VERBOSE, "No more output streams to write to, finishing.\n");
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = transcode_step(ost);
|
||||
if (ret < 0 && ret != AVERROR_EOF) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret));
|
||||
break;
|
||||
}
|
||||
|
||||
/* dump report by using the output first video and audio streams */
|
||||
print_report(0, timer_start, cur_time, transcode_ts);
|
||||
print_report(0, timer_start, cur_time);
|
||||
}
|
||||
|
||||
ret = sch_stop(sch, &transcode_ts);
|
||||
/* at the end of stream, we must flush the decoder buffers */
|
||||
for (ist = ist_iter(NULL); ist; ist = ist_iter(ist)) {
|
||||
float err_rate;
|
||||
|
||||
if (!input_files[ist->file_index]->eof_reached) {
|
||||
int err = process_input_packet(ist, NULL, 0);
|
||||
ret = err_merge(ret, err);
|
||||
}
|
||||
|
||||
err_rate = (ist->frames_decoded || ist->decode_errors) ?
|
||||
ist->decode_errors / (ist->frames_decoded + ist->decode_errors) : 0.f;
|
||||
if (err_rate > max_error_rate) {
|
||||
av_log(ist, AV_LOG_FATAL, "Decode error rate %g exceeds maximum %g\n",
|
||||
err_rate, max_error_rate);
|
||||
*err_rate_exceeded = 1;
|
||||
} else if (err_rate)
|
||||
av_log(ist, AV_LOG_VERBOSE, "Decode error rate %g\n", err_rate);
|
||||
}
|
||||
ret = err_merge(ret, enc_flush());
|
||||
|
||||
term_exit();
|
||||
|
||||
/* write the trailer if needed */
|
||||
for (int i = 0; i < nb_output_files; i++) {
|
||||
for (i = 0; i < nb_output_files; i++) {
|
||||
int err = of_write_trailer(output_files[i]);
|
||||
ret = err_merge(ret, err);
|
||||
}
|
||||
|
||||
term_exit();
|
||||
|
||||
/* dump report by using the first video and audio streams */
|
||||
print_report(1, timer_start, av_gettime_relative(), transcode_ts);
|
||||
print_report(1, timer_start, av_gettime_relative());
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -945,9 +1292,7 @@ static int64_t getmaxrss(void)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Scheduler *sch = NULL;
|
||||
|
||||
int ret;
|
||||
int ret, err_rate_exceeded;
|
||||
BenchmarkTimeStamps ti;
|
||||
|
||||
init_dynload();
|
||||
@@ -964,14 +1309,8 @@ int main(int argc, char **argv)
|
||||
|
||||
show_banner(argc, argv, options);
|
||||
|
||||
sch = sch_alloc();
|
||||
if (!sch) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* parse options and open all input/output files */
|
||||
ret = ffmpeg_parse_options(argc, argv, sch);
|
||||
ret = ffmpeg_parse_options(argc, argv);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
|
||||
@@ -989,7 +1328,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
current_time = ti = get_benchmark_time_stamps();
|
||||
ret = transcode(sch);
|
||||
ret = transcode(&err_rate_exceeded);
|
||||
if (ret >= 0 && do_benchmark) {
|
||||
int64_t utime, stime, rtime;
|
||||
current_time = get_benchmark_time_stamps();
|
||||
@@ -1001,16 +1340,13 @@ int main(int argc, char **argv)
|
||||
utime / 1000000.0, stime / 1000000.0, rtime / 1000000.0);
|
||||
}
|
||||
|
||||
ret = received_nb_signals ? 255 :
|
||||
(ret == FFMPEG_ERROR_RATE_EXCEEDED) ? 69 : ret;
|
||||
ret = received_nb_signals ? 255 :
|
||||
err_rate_exceeded ? 69 : ret;
|
||||
|
||||
finish:
|
||||
if (ret == AVERROR_EXIT)
|
||||
ret = 0;
|
||||
|
||||
ffmpeg_cleanup(ret);
|
||||
|
||||
sch_free(&sch);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+425
-391
File diff suppressed because it is too large
Load Diff
+500
-1115
File diff suppressed because it is too large
Load Diff
+495
-727
File diff suppressed because it is too large
Load Diff
+239
-277
@@ -30,15 +30,20 @@
|
||||
#include "libavutil/frame.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/log.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/pixdesc.h"
|
||||
#include "libavutil/rational.h"
|
||||
#include "libavutil/time.h"
|
||||
#include "libavutil/timestamp.h"
|
||||
|
||||
#include "libavcodec/avcodec.h"
|
||||
|
||||
#include "libavformat/avformat.h"
|
||||
|
||||
struct Encoder {
|
||||
AVFrame *sq_frame;
|
||||
|
||||
// packet for receiving encoded output
|
||||
AVPacket *pkt;
|
||||
|
||||
// combined size of all the packets received from the encoder
|
||||
uint64_t data_size;
|
||||
|
||||
@@ -46,18 +51,8 @@ struct Encoder {
|
||||
uint64_t packets_encoded;
|
||||
|
||||
int opened;
|
||||
int attach_par;
|
||||
|
||||
Scheduler *sch;
|
||||
unsigned sch_idx;
|
||||
};
|
||||
|
||||
// data that is local to the decoder thread and not visible outside of it
|
||||
typedef struct EncoderThread {
|
||||
AVFrame *frame;
|
||||
AVPacket *pkt;
|
||||
} EncoderThread;
|
||||
|
||||
void enc_free(Encoder **penc)
|
||||
{
|
||||
Encoder *enc = *penc;
|
||||
@@ -65,11 +60,14 @@ void enc_free(Encoder **penc)
|
||||
if (!enc)
|
||||
return;
|
||||
|
||||
av_frame_free(&enc->sq_frame);
|
||||
|
||||
av_packet_free(&enc->pkt);
|
||||
|
||||
av_freep(penc);
|
||||
}
|
||||
|
||||
int enc_alloc(Encoder **penc, const AVCodec *codec,
|
||||
Scheduler *sch, unsigned sch_idx)
|
||||
int enc_alloc(Encoder **penc, const AVCodec *codec)
|
||||
{
|
||||
Encoder *enc;
|
||||
|
||||
@@ -79,18 +77,23 @@ int enc_alloc(Encoder **penc, const AVCodec *codec,
|
||||
if (!enc)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
enc->sch = sch;
|
||||
enc->sch_idx = sch_idx;
|
||||
enc->pkt = av_packet_alloc();
|
||||
if (!enc->pkt)
|
||||
goto fail;
|
||||
|
||||
*penc = enc;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
enc_free(&enc);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
static int hw_device_setup_for_encode(OutputStream *ost, AVBufferRef *frames_ref)
|
||||
{
|
||||
const AVCodecHWConfig *config;
|
||||
HWDevice *dev = NULL;
|
||||
int i;
|
||||
|
||||
if (frames_ref &&
|
||||
((AVHWFramesContext*)frames_ref->data)->format ==
|
||||
@@ -100,7 +103,7 @@ static int hw_device_setup_for_encode(OutputStream *ost, AVBufferRef *frames_ref
|
||||
frames_ref = NULL;
|
||||
}
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
for (i = 0;; i++) {
|
||||
config = avcodec_get_hw_config(ost->enc_ctx->codec, i);
|
||||
if (!config)
|
||||
break;
|
||||
@@ -162,17 +165,15 @@ static int set_encoder_id(OutputFile *of, OutputStream *ost)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int enc_open(void *opaque, const AVFrame *frame)
|
||||
int enc_open(OutputStream *ost, const AVFrame *frame)
|
||||
{
|
||||
OutputStream *ost = opaque;
|
||||
InputStream *ist = ost->ist;
|
||||
Encoder *e = ost->enc;
|
||||
AVCodecContext *enc_ctx = ost->enc_ctx;
|
||||
Decoder *dec = NULL;
|
||||
AVCodecContext *dec_ctx = NULL;
|
||||
const AVCodec *enc = enc_ctx->codec;
|
||||
OutputFile *of = ost->file;
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
FrameData *fd;
|
||||
int frame_samples = 0;
|
||||
int ret;
|
||||
|
||||
if (e->opened)
|
||||
@@ -184,28 +185,15 @@ int enc_open(void *opaque, const AVFrame *frame)
|
||||
if (frame) {
|
||||
av_assert0(frame->opaque_ref);
|
||||
fd = (FrameData*)frame->opaque_ref->data;
|
||||
|
||||
for (int i = 0; i < frame->nb_side_data; i++) {
|
||||
const AVSideDataDescriptor *desc = av_frame_side_data_desc(frame->side_data[i]->type);
|
||||
|
||||
if (!(desc->props & AV_SIDE_DATA_PROP_GLOBAL))
|
||||
continue;
|
||||
|
||||
ret = av_frame_side_data_clone(&enc_ctx->decoded_side_data,
|
||||
&enc_ctx->nb_decoded_side_data,
|
||||
frame->side_data[i],
|
||||
AV_FRAME_SIDE_DATA_FLAG_UNIQUE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = set_encoder_id(of, ost);
|
||||
ret = set_encoder_id(output_files[ost->file_index], ost);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ist)
|
||||
dec = ist->decoder;
|
||||
if (ist) {
|
||||
dec_ctx = ist->dec_ctx;
|
||||
}
|
||||
|
||||
// the timebase is chosen by filtering code
|
||||
if (ost->type == AVMEDIA_TYPE_AUDIO || ost->type == AVMEDIA_TYPE_VIDEO) {
|
||||
@@ -216,9 +204,6 @@ int enc_open(void *opaque, const AVFrame *frame)
|
||||
|
||||
switch (enc_ctx->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
av_assert0(frame->format != AV_SAMPLE_FMT_NONE &&
|
||||
frame->sample_rate > 0 &&
|
||||
frame->ch_layout.nb_channels > 0);
|
||||
enc_ctx->sample_fmt = frame->format;
|
||||
enc_ctx->sample_rate = frame->sample_rate;
|
||||
ret = av_channel_layout_copy(&enc_ctx->ch_layout, &frame->ch_layout);
|
||||
@@ -233,9 +218,6 @@ int enc_open(void *opaque, const AVFrame *frame)
|
||||
break;
|
||||
|
||||
case AVMEDIA_TYPE_VIDEO: {
|
||||
av_assert0(frame->format != AV_PIX_FMT_NONE &&
|
||||
frame->width > 0 &&
|
||||
frame->height > 0);
|
||||
enc_ctx->width = frame->width;
|
||||
enc_ctx->height = frame->height;
|
||||
enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio =
|
||||
@@ -280,22 +262,23 @@ int enc_open(void *opaque, const AVFrame *frame)
|
||||
break;
|
||||
}
|
||||
case AVMEDIA_TYPE_SUBTITLE:
|
||||
if (ost->enc_timebase.num)
|
||||
av_log(ost, AV_LOG_WARNING,
|
||||
"-enc_time_base not supported for subtitles, ignoring\n");
|
||||
enc_ctx->time_base = AV_TIME_BASE_Q;
|
||||
|
||||
if (!enc_ctx->width) {
|
||||
enc_ctx->width = ost->ist->par->width;
|
||||
enc_ctx->height = ost->ist->par->height;
|
||||
}
|
||||
|
||||
av_assert0(dec);
|
||||
if (dec->subtitle_header) {
|
||||
if (dec_ctx && dec_ctx->subtitle_header) {
|
||||
/* ASS code assumes this buffer is null terminated so add extra byte. */
|
||||
enc_ctx->subtitle_header = av_mallocz(dec->subtitle_header_size + 1);
|
||||
enc_ctx->subtitle_header = av_mallocz(dec_ctx->subtitle_header_size + 1);
|
||||
if (!enc_ctx->subtitle_header)
|
||||
return AVERROR(ENOMEM);
|
||||
memcpy(enc_ctx->subtitle_header, dec->subtitle_header,
|
||||
dec->subtitle_header_size);
|
||||
enc_ctx->subtitle_header_size = dec->subtitle_header_size;
|
||||
memcpy(enc_ctx->subtitle_header, dec_ctx->subtitle_header,
|
||||
dec_ctx->subtitle_header_size);
|
||||
enc_ctx->subtitle_header_size = dec_ctx->subtitle_header_size;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -307,10 +290,16 @@ int enc_open(void *opaque, const AVFrame *frame)
|
||||
if (ost->bitexact)
|
||||
enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT;
|
||||
|
||||
if (enc->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE)
|
||||
enc_ctx->flags |= AV_CODEC_FLAG_COPY_OPAQUE;
|
||||
if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0))
|
||||
av_dict_set(&ost->encoder_opts, "threads", "auto", 0);
|
||||
|
||||
enc_ctx->flags |= AV_CODEC_FLAG_FRAME_DURATION;
|
||||
if (enc->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE) {
|
||||
ret = av_dict_set(&ost->encoder_opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
av_dict_set(&ost->encoder_opts, "flags", "+frame_duration", AV_DICT_MULTIKEY);
|
||||
|
||||
ret = hw_device_setup_for_encode(ost, frame ? frame->hw_frames_ctx : NULL);
|
||||
if (ret < 0) {
|
||||
@@ -319,7 +308,7 @@ int enc_open(void *opaque, const AVFrame *frame)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = avcodec_open2(ost->enc_ctx, enc, NULL)) < 0) {
|
||||
if ((ret = avcodec_open2(ost->enc_ctx, enc, &ost->encoder_opts)) < 0) {
|
||||
if (ret != AVERROR_EXPERIMENTAL)
|
||||
av_log(ost, AV_LOG_ERROR, "Error while opening encoder - maybe "
|
||||
"incorrect parameters such as bit_rate, rate, width or height.\n");
|
||||
@@ -328,8 +317,21 @@ int enc_open(void *opaque, const AVFrame *frame)
|
||||
|
||||
e->opened = 1;
|
||||
|
||||
if (ost->enc_ctx->frame_size)
|
||||
frame_samples = ost->enc_ctx->frame_size;
|
||||
if (ost->sq_idx_encode >= 0) {
|
||||
e->sq_frame = av_frame_alloc();
|
||||
if (!e->sq_frame)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
if (ost->enc_ctx->frame_size) {
|
||||
av_assert0(ost->sq_idx_encode >= 0);
|
||||
sq_frame_samples(output_files[ost->file_index]->sq_encode,
|
||||
ost->sq_idx_encode, ost->enc_ctx->frame_size);
|
||||
}
|
||||
|
||||
ret = check_avoptions(ost->encoder_opts);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 &&
|
||||
ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */)
|
||||
@@ -343,6 +345,30 @@ int enc_open(void *opaque, const AVFrame *frame)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add global input side data. For now this is naive, and copies it
|
||||
* from the input stream's global side data. All side data should
|
||||
* really be funneled over AVFrame and libavfilter, then added back to
|
||||
* packet side data, and then potentially using the first packet for
|
||||
* global side data.
|
||||
*/
|
||||
if (ist) {
|
||||
int i;
|
||||
for (i = 0; i < ist->st->codecpar->nb_coded_side_data; i++) {
|
||||
AVPacketSideData *sd_src = &ist->st->codecpar->coded_side_data[i];
|
||||
if (sd_src->type != AV_PKT_DATA_CPB_PROPERTIES) {
|
||||
AVPacketSideData *sd_dst = av_packet_side_data_new(&ost->par_in->coded_side_data,
|
||||
&ost->par_in->nb_coded_side_data,
|
||||
sd_src->type, sd_src->size, 0);
|
||||
if (!sd_dst)
|
||||
return AVERROR(ENOMEM);
|
||||
memcpy(sd_dst->data, sd_src->data, sd_src->size);
|
||||
if (ist->autorotate && sd_src->type == AV_PKT_DATA_DISPLAYMATRIX)
|
||||
av_display_rotation_set((int32_t *)sd_dst->data, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy timebase while removing common factors
|
||||
if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0)
|
||||
ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1});
|
||||
@@ -351,34 +377,36 @@ int enc_open(void *opaque, const AVFrame *frame)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return frame_samples;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb)
|
||||
{
|
||||
OutputFile *of = ost->file;
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
|
||||
if (of->recording_time != INT64_MAX &&
|
||||
av_compare_ts(ts, tb, of->recording_time, AV_TIME_BASE_Q) >= 0) {
|
||||
close_output_stream(ost);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *sub,
|
||||
AVPacket *pkt)
|
||||
int enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub)
|
||||
{
|
||||
Encoder *e = ost->enc;
|
||||
int subtitle_out_max_size = 1024 * 1024;
|
||||
int subtitle_out_size, nb, i, ret;
|
||||
AVCodecContext *enc;
|
||||
AVPacket *pkt = e->pkt;
|
||||
int64_t pts;
|
||||
|
||||
if (sub->pts == AV_NOPTS_VALUE) {
|
||||
av_log(ost, AV_LOG_ERROR, "Subtitle packets must have a pts\n");
|
||||
return exit_on_error ? AVERROR(EINVAL) : 0;
|
||||
}
|
||||
if ((of->start_time != AV_NOPTS_VALUE && sub->pts < of->start_time))
|
||||
if (ost->finished ||
|
||||
(of->start_time != AV_NOPTS_VALUE && sub->pts < of->start_time))
|
||||
return 0;
|
||||
|
||||
enc = ost->enc_ctx;
|
||||
@@ -395,13 +423,13 @@ static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *
|
||||
|
||||
/* shift timestamp to honor -ss and make check_recording_time() work with -t */
|
||||
pts = sub->pts;
|
||||
if (of->start_time != AV_NOPTS_VALUE)
|
||||
pts -= of->start_time;
|
||||
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++) {
|
||||
AVSubtitle local_sub = *sub;
|
||||
|
||||
if (!check_recording_time(ost, pts, AV_TIME_BASE_Q))
|
||||
return AVERROR_EOF;
|
||||
return 0;
|
||||
|
||||
ret = av_new_packet(pkt, subtitle_out_max_size);
|
||||
if (ret < 0)
|
||||
@@ -442,11 +470,9 @@ static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *
|
||||
}
|
||||
pkt->dts = pkt->pts;
|
||||
|
||||
ret = sch_enc_send(e->sch, e->sch_idx, pkt);
|
||||
if (ret < 0) {
|
||||
av_packet_unref(pkt);
|
||||
ret = of_output_packet(of, ost, pkt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -472,14 +498,12 @@ void enc_stats_write(OutputStream *ost, EncStats *es,
|
||||
ptsi = fd->dec.pts;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&es->lock);
|
||||
|
||||
for (size_t i = 0; i < es->nb_components; i++) {
|
||||
const EncStatsComponent *c = &es->components[i];
|
||||
|
||||
switch (c->type) {
|
||||
case ENC_STATS_LITERAL: avio_write (io, c->str, c->str_len); continue;
|
||||
case ENC_STATS_FILE_IDX: avio_printf(io, "%d", ost->file->index); continue;
|
||||
case ENC_STATS_FILE_IDX: avio_printf(io, "%d", ost->file_index); continue;
|
||||
case ENC_STATS_STREAM_IDX: avio_printf(io, "%d", ost->index); continue;
|
||||
case ENC_STATS_TIMEBASE: avio_printf(io, "%d/%d", tb.num, tb.den); continue;
|
||||
case ENC_STATS_TIMEBASE_IN: avio_printf(io, "%d/%d", tbi.num, tbi.den); continue;
|
||||
@@ -503,8 +527,6 @@ void enc_stats_write(OutputStream *ost, EncStats *es,
|
||||
case ENC_STATS_DTS: avio_printf(io, "%"PRId64, pkt->dts); continue;
|
||||
case ENC_STATS_DTS_TIME: avio_printf(io, "%g", pkt->dts * av_q2d(tb)); continue;
|
||||
case ENC_STATS_PKT_SIZE: avio_printf(io, "%d", pkt->size); continue;
|
||||
case ENC_STATS_KEYFRAME: avio_write(io, (pkt->flags & AV_PKT_FLAG_KEY) ?
|
||||
"K" : "N", 1); continue;
|
||||
case ENC_STATS_BITRATE: {
|
||||
double duration = FFMAX(pkt->duration, 1) * av_q2d(tb);
|
||||
avio_printf(io, "%g", 8.0 * pkt->size / duration);
|
||||
@@ -521,8 +543,6 @@ void enc_stats_write(OutputStream *ost, EncStats *es,
|
||||
}
|
||||
avio_w8(io, '\n');
|
||||
avio_flush(io);
|
||||
|
||||
pthread_mutex_unlock(&es->lock);
|
||||
}
|
||||
|
||||
static inline double psnr(double d)
|
||||
@@ -540,13 +560,10 @@ static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_
|
||||
int64_t frame_number;
|
||||
double ti1, bitrate, avg_bitrate;
|
||||
double psnr_val = -1;
|
||||
int quality;
|
||||
|
||||
quality = sd ? AV_RL32(sd) : -1;
|
||||
ost->quality = sd ? AV_RL32(sd) : -1;
|
||||
pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE;
|
||||
|
||||
atomic_store(&ost->quality, quality);
|
||||
|
||||
if ((enc->flags & AV_CODEC_FLAG_PSNR) && sd && sd[5]) {
|
||||
// FIXME the scaling assumes 8bit
|
||||
double error = AV_RL64(sd + 8) / (enc->width * enc->height * 255.0 * 255.0);
|
||||
@@ -569,11 +586,10 @@ static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_
|
||||
frame_number = e->packets_encoded;
|
||||
if (vstats_version <= 1) {
|
||||
fprintf(vstats_file, "frame= %5"PRId64" q= %2.1f ", frame_number,
|
||||
quality / (float)FF_QP2LAMBDA);
|
||||
ost->quality / (float)FF_QP2LAMBDA);
|
||||
} else {
|
||||
fprintf(vstats_file, "out= %2d st= %2d frame= %5"PRId64" q= %2.1f ",
|
||||
ost->file->index, ost->index, frame_number,
|
||||
quality / (float)FF_QP2LAMBDA);
|
||||
fprintf(vstats_file, "out= %2d st= %2d frame= %5"PRId64" q= %2.1f ", ost->file_index, ost->index, frame_number,
|
||||
ost->quality / (float)FF_QP2LAMBDA);
|
||||
}
|
||||
|
||||
if (psnr_val >= 0)
|
||||
@@ -587,30 +603,23 @@ static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_
|
||||
|
||||
bitrate = (pkt->size * 8) / av_q2d(enc->time_base) / 1000.0;
|
||||
avg_bitrate = (double)(e->data_size * 8) / ti1 / 1000.0;
|
||||
fprintf(vstats_file, "s_size= %8.0fKiB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
|
||||
fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
|
||||
(double)e->data_size / 1024, ti1, bitrate, avg_bitrate);
|
||||
fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(pict_type));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
|
||||
AVPacket *pkt)
|
||||
static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
|
||||
{
|
||||
Encoder *e = ost->enc;
|
||||
AVCodecContext *enc = ost->enc_ctx;
|
||||
AVPacket *pkt = e->pkt;
|
||||
const char *type_desc = av_get_media_type_string(enc->codec_type);
|
||||
const char *action = frame ? "encode" : "flush";
|
||||
int ret;
|
||||
|
||||
if (frame) {
|
||||
FrameData *fd = frame_data(frame);
|
||||
|
||||
if (!fd)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
fd->wallclock[LATENCY_PROBE_ENC_PRE] = av_gettime_relative();
|
||||
|
||||
if (ost->enc_stats_pre.io)
|
||||
enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL,
|
||||
ost->frames_encoded);
|
||||
@@ -640,13 +649,11 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
|
||||
}
|
||||
|
||||
while (1) {
|
||||
FrameData *fd;
|
||||
|
||||
av_packet_unref(pkt);
|
||||
|
||||
ret = avcodec_receive_packet(enc, pkt);
|
||||
update_benchmark("%s_%s %d.%d", action, type_desc,
|
||||
of->index, ost->index);
|
||||
ost->file_index, ost->index);
|
||||
|
||||
pkt->time_base = enc->time_base;
|
||||
|
||||
@@ -657,31 +664,14 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
|
||||
if (ret == AVERROR(EAGAIN)) {
|
||||
av_assert0(frame); // should never happen during flushing
|
||||
return 0;
|
||||
} else if (ret == AVERROR_EOF) {
|
||||
ret = of_output_packet(of, ost, NULL);
|
||||
return ret < 0 ? ret : AVERROR_EOF;
|
||||
} else if (ret < 0) {
|
||||
if (ret != AVERROR_EOF)
|
||||
av_log(ost, AV_LOG_ERROR, "%s encoding failed\n", type_desc);
|
||||
av_log(ost, AV_LOG_ERROR, "%s encoding failed\n", type_desc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
fd = packet_data(pkt);
|
||||
if (!fd)
|
||||
return AVERROR(ENOMEM);
|
||||
fd->wallclock[LATENCY_PROBE_ENC_POST] = av_gettime_relative();
|
||||
|
||||
// attach stream parameters to first packet if requested
|
||||
avcodec_parameters_free(&fd->par_enc);
|
||||
if (e->attach_par && !e->packets_encoded) {
|
||||
fd->par_enc = avcodec_parameters_alloc();
|
||||
if (!fd->par_enc)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
ret = avcodec_parameters_from_context(fd->par_enc, enc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pkt->flags |= AV_PKT_FLAG_TRUSTED;
|
||||
|
||||
if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
ret = update_video_stats(ost, pkt, !!vstats_filename);
|
||||
if (ret < 0)
|
||||
@@ -702,31 +692,103 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
|
||||
av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base));
|
||||
}
|
||||
|
||||
if ((ret = trigger_fix_sub_duration_heartbeat(ost, pkt)) < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Subtitle heartbeat logic failed in %s! (%s)\n",
|
||||
__func__, av_err2str(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
e->data_size += pkt->size;
|
||||
|
||||
e->packets_encoded++;
|
||||
|
||||
ret = sch_enc_send(e->sch, e->sch_idx, pkt);
|
||||
if (ret < 0) {
|
||||
av_packet_unref(pkt);
|
||||
ret = of_output_packet(of, ost, pkt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
av_assert0(0);
|
||||
}
|
||||
|
||||
static int submit_encode_frame(OutputFile *of, OutputStream *ost,
|
||||
AVFrame *frame)
|
||||
{
|
||||
Encoder *e = ost->enc;
|
||||
int ret;
|
||||
|
||||
if (ost->sq_idx_encode < 0)
|
||||
return encode_frame(of, ost, frame);
|
||||
|
||||
if (frame) {
|
||||
ret = av_frame_ref(e->sq_frame, frame);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
frame = e->sq_frame;
|
||||
}
|
||||
|
||||
ret = sq_send(of->sq_encode, ost->sq_idx_encode,
|
||||
SQFRAME(frame));
|
||||
if (ret < 0) {
|
||||
if (frame)
|
||||
av_frame_unref(frame);
|
||||
if (ret != AVERROR_EOF)
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
AVFrame *enc_frame = e->sq_frame;
|
||||
|
||||
ret = sq_receive(of->sq_encode, ost->sq_idx_encode,
|
||||
SQFRAME(enc_frame));
|
||||
if (ret == AVERROR_EOF) {
|
||||
enc_frame = NULL;
|
||||
} else if (ret < 0) {
|
||||
return (ret == AVERROR(EAGAIN)) ? 0 : ret;
|
||||
}
|
||||
|
||||
ret = encode_frame(of, ost, enc_frame);
|
||||
if (enc_frame)
|
||||
av_frame_unref(enc_frame);
|
||||
if (ret < 0) {
|
||||
if (ret == AVERROR_EOF)
|
||||
close_output_stream(ost);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int do_audio_out(OutputFile *of, OutputStream *ost,
|
||||
AVFrame *frame)
|
||||
{
|
||||
AVCodecContext *enc = ost->enc_ctx;
|
||||
int ret;
|
||||
|
||||
if (!(enc->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) &&
|
||||
enc->ch_layout.nb_channels != frame->ch_layout.nb_channels) {
|
||||
av_log(ost, AV_LOG_ERROR,
|
||||
"Audio channel count changed and encoder does not support parameter changes\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!check_recording_time(ost, frame->pts, frame->time_base))
|
||||
return 0;
|
||||
|
||||
ret = submit_encode_frame(of, ost, frame);
|
||||
return (ret < 0 && ret != AVERROR_EOF) ? ret : 0;
|
||||
}
|
||||
|
||||
static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf,
|
||||
const AVFrame *frame)
|
||||
AVRational tb, const AVFrame *in_picture)
|
||||
{
|
||||
double pts_time;
|
||||
|
||||
if (kf->ref_pts == AV_NOPTS_VALUE)
|
||||
kf->ref_pts = frame->pts;
|
||||
kf->ref_pts = in_picture->pts;
|
||||
|
||||
pts_time = (frame->pts - kf->ref_pts) * av_q2d(frame->time_base);
|
||||
pts_time = (in_picture->pts - kf->ref_pts) * av_q2d(tb);
|
||||
if (kf->index < kf->nb_pts &&
|
||||
av_compare_ts(frame->pts, frame->time_base, kf->pts[kf->index], AV_TIME_BASE_Q) >= 0) {
|
||||
av_compare_ts(in_picture->pts, tb, kf->pts[kf->index], AV_TIME_BASE_Q) >= 0) {
|
||||
kf->index++;
|
||||
goto force_keyframe;
|
||||
} else if (kf->pexpr) {
|
||||
@@ -751,7 +813,7 @@ static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf,
|
||||
kf->expr_const_values[FKF_N_FORCED] += 1;
|
||||
goto force_keyframe;
|
||||
}
|
||||
} else if (kf->type == KF_FORCE_SOURCE && (frame->flags & AV_FRAME_FLAG_KEY)) {
|
||||
} else if (kf->type == KF_FORCE_SOURCE && (in_picture->flags & AV_FRAME_FLAG_KEY)) {
|
||||
goto force_keyframe;
|
||||
}
|
||||
|
||||
@@ -762,165 +824,65 @@ force_keyframe:
|
||||
return AV_PICTURE_TYPE_I;
|
||||
}
|
||||
|
||||
static int frame_encode(OutputStream *ost, AVFrame *frame, AVPacket *pkt)
|
||||
/* May modify/reset frame */
|
||||
static int do_video_out(OutputFile *of, OutputStream *ost, AVFrame *in_picture)
|
||||
{
|
||||
OutputFile *of = ost->file;
|
||||
enum AVMediaType type = ost->type;
|
||||
int ret;
|
||||
AVCodecContext *enc = ost->enc_ctx;
|
||||
|
||||
if (type == AVMEDIA_TYPE_SUBTITLE) {
|
||||
const AVSubtitle *subtitle = frame && frame->buf[0] ?
|
||||
(AVSubtitle*)frame->buf[0]->data : NULL;
|
||||
if (!check_recording_time(ost, in_picture->pts, ost->enc_ctx->time_base))
|
||||
return 0;
|
||||
|
||||
// no flushing for subtitles
|
||||
return subtitle && subtitle->num_rects ?
|
||||
do_subtitle_out(of, ost, subtitle, pkt) : 0;
|
||||
}
|
||||
|
||||
if (frame) {
|
||||
if (!check_recording_time(ost, frame->pts, frame->time_base))
|
||||
return AVERROR_EOF;
|
||||
|
||||
if (type == AVMEDIA_TYPE_VIDEO) {
|
||||
frame->quality = ost->enc_ctx->global_quality;
|
||||
frame->pict_type = forced_kf_apply(ost, &ost->kf, frame);
|
||||
in_picture->quality = enc->global_quality;
|
||||
in_picture->pict_type = forced_kf_apply(ost, &ost->kf, enc->time_base, in_picture);
|
||||
|
||||
#if FFMPEG_OPT_TOP
|
||||
if (ost->top_field_first >= 0) {
|
||||
frame->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST;
|
||||
frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * (!!ost->top_field_first);
|
||||
}
|
||||
if (ost->top_field_first >= 0) {
|
||||
in_picture->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST;
|
||||
in_picture->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * (!!ost->top_field_first);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if (!(ost->enc_ctx->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) &&
|
||||
ost->enc_ctx->ch_layout.nb_channels != frame->ch_layout.nb_channels) {
|
||||
av_log(ost, AV_LOG_ERROR,
|
||||
"Audio channel count changed and encoder does not support parameter changes\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ret = submit_encode_frame(of, ost, in_picture);
|
||||
return (ret == AVERROR_EOF) ? 0 : ret;
|
||||
}
|
||||
|
||||
int enc_frame(OutputStream *ost, AVFrame *frame)
|
||||
{
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
int ret;
|
||||
|
||||
ret = enc_open(ost, frame);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ?
|
||||
do_video_out(of, ost, frame) : do_audio_out(of, ost, frame);
|
||||
}
|
||||
|
||||
int enc_flush(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
if (ost->sq_idx_encode >= 0)
|
||||
sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL));
|
||||
}
|
||||
|
||||
return encode_frame(of, ost, frame, pkt);
|
||||
}
|
||||
for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
|
||||
Encoder *e = ost->enc;
|
||||
AVCodecContext *enc = ost->enc_ctx;
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
|
||||
static void enc_thread_set_name(const OutputStream *ost)
|
||||
{
|
||||
char name[16];
|
||||
snprintf(name, sizeof(name), "enc%d:%d:%s", ost->file->index, ost->index,
|
||||
ost->enc_ctx->codec->name);
|
||||
ff_thread_setname(name);
|
||||
}
|
||||
if (!enc || !e->opened ||
|
||||
(enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO))
|
||||
continue;
|
||||
|
||||
static void enc_thread_uninit(EncoderThread *et)
|
||||
{
|
||||
av_packet_free(&et->pkt);
|
||||
av_frame_free(&et->frame);
|
||||
|
||||
memset(et, 0, sizeof(*et));
|
||||
}
|
||||
|
||||
static int enc_thread_init(EncoderThread *et)
|
||||
{
|
||||
memset(et, 0, sizeof(*et));
|
||||
|
||||
et->frame = av_frame_alloc();
|
||||
if (!et->frame)
|
||||
goto fail;
|
||||
|
||||
et->pkt = av_packet_alloc();
|
||||
if (!et->pkt)
|
||||
goto fail;
|
||||
ret = submit_encode_frame(of, ost, NULL);
|
||||
if (ret != AVERROR_EOF)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
enc_thread_uninit(et);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
int encoder_thread(void *arg)
|
||||
{
|
||||
OutputStream *ost = arg;
|
||||
Encoder *e = ost->enc;
|
||||
EncoderThread et;
|
||||
int ret = 0, input_status = 0;
|
||||
int name_set = 0;
|
||||
|
||||
ret = enc_thread_init(&et);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
|
||||
/* Open the subtitle encoders immediately. AVFrame-based encoders
|
||||
* are opened through a callback from the scheduler once they get
|
||||
* their first frame
|
||||
*
|
||||
* N.B.: because the callback is called from a different thread,
|
||||
* enc_ctx MUST NOT be accessed before sch_enc_receive() returns
|
||||
* for the first time for audio/video. */
|
||||
if (ost->type != AVMEDIA_TYPE_VIDEO && ost->type != AVMEDIA_TYPE_AUDIO) {
|
||||
ret = enc_open(ost, NULL);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
while (!input_status) {
|
||||
input_status = sch_enc_receive(e->sch, e->sch_idx, et.frame);
|
||||
if (input_status < 0) {
|
||||
if (input_status == AVERROR_EOF) {
|
||||
av_log(ost, AV_LOG_VERBOSE, "Encoder thread received EOF\n");
|
||||
if (e->opened)
|
||||
break;
|
||||
|
||||
av_log(ost, AV_LOG_ERROR, "Could not open encoder before EOF\n");
|
||||
ret = AVERROR(EINVAL);
|
||||
} else {
|
||||
av_log(ost, AV_LOG_ERROR, "Error receiving a frame for encoding: %s\n",
|
||||
av_err2str(ret));
|
||||
ret = input_status;
|
||||
}
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!name_set) {
|
||||
enc_thread_set_name(ost);
|
||||
name_set = 1;
|
||||
}
|
||||
|
||||
ret = frame_encode(ost, et.frame, et.pkt);
|
||||
|
||||
av_packet_unref(et.pkt);
|
||||
av_frame_unref(et.frame);
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret == AVERROR_EOF)
|
||||
av_log(ost, AV_LOG_VERBOSE, "Encoder returned EOF, finishing\n");
|
||||
else
|
||||
av_log(ost, AV_LOG_ERROR, "Error encoding a frame: %s\n",
|
||||
av_err2str(ret));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// flush the encoder
|
||||
if (ret == 0 || ret == AVERROR_EOF) {
|
||||
ret = frame_encode(ost, NULL, et.pkt);
|
||||
if (ret < 0 && ret != AVERROR_EOF)
|
||||
av_log(ost, AV_LOG_ERROR, "Error flushing encoder: %s\n",
|
||||
av_err2str(ret));
|
||||
}
|
||||
|
||||
// EOF is normal thread termination
|
||||
if (ret == AVERROR_EOF)
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
enc_thread_uninit(&et);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int enc_loopback(Encoder *enc)
|
||||
{
|
||||
enc->attach_par = 1;
|
||||
return enc->sch_idx;
|
||||
}
|
||||
|
||||
+671
-1223
File diff suppressed because it is too large
Load Diff
+45
-1
@@ -18,7 +18,9 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/pixdesc.h"
|
||||
#include "libavfilter/buffersink.h"
|
||||
|
||||
#include "ffmpeg.h"
|
||||
|
||||
@@ -295,6 +297,48 @@ void hw_device_free_all(void)
|
||||
nb_hw_devices = 0;
|
||||
}
|
||||
|
||||
int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input)
|
||||
{
|
||||
InputStream *ist = avctx->opaque;
|
||||
AVFrame *output = NULL;
|
||||
enum AVPixelFormat output_format = ist->hwaccel_output_format;
|
||||
int err;
|
||||
|
||||
if (input->format == output_format) {
|
||||
// Nothing to do.
|
||||
return 0;
|
||||
}
|
||||
|
||||
output = av_frame_alloc();
|
||||
if (!output)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
output->format = output_format;
|
||||
|
||||
err = av_hwframe_transfer_data(output, input, 0);
|
||||
if (err < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Failed to transfer data to "
|
||||
"output frame: %d.\n", err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = av_frame_copy_props(output, input);
|
||||
if (err < 0) {
|
||||
av_frame_unref(output);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
av_frame_unref(input);
|
||||
av_frame_move_ref(input, output);
|
||||
av_frame_free(&output);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
av_frame_free(&output);
|
||||
return err;
|
||||
}
|
||||
|
||||
AVBufferRef *hw_device_for_filter(void)
|
||||
{
|
||||
// Pick the last hardware device if the user doesn't pick the device for
|
||||
|
||||
+374
-302
@@ -22,26 +22,23 @@
|
||||
|
||||
#include "ffmpeg.h"
|
||||
#include "ffmpeg_mux.h"
|
||||
#include "ffmpeg_utils.h"
|
||||
#include "objpool.h"
|
||||
#include "sync_queue.h"
|
||||
#include "thread_queue.h"
|
||||
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/fifo.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/log.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/time.h"
|
||||
#include "libavutil/timestamp.h"
|
||||
#include "libavutil/thread.h"
|
||||
|
||||
#include "libavcodec/packet.h"
|
||||
|
||||
#include "libavformat/avformat.h"
|
||||
#include "libavformat/avio.h"
|
||||
|
||||
typedef struct MuxThreadContext {
|
||||
AVPacket *pkt;
|
||||
AVPacket *fix_sub_duration_pkt;
|
||||
} MuxThreadContext;
|
||||
int want_sdp = 1;
|
||||
|
||||
static Muxer *mux_from_of(OutputFile *of)
|
||||
{
|
||||
@@ -61,88 +58,23 @@ static int64_t filesize(AVIOContext *pb)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mux_log_debug_ts(OutputStream *ost, const AVPacket *pkt)
|
||||
static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
|
||||
{
|
||||
static const char *desc[] = {
|
||||
[LATENCY_PROBE_DEMUX] = "demux",
|
||||
[LATENCY_PROBE_DEC_PRE] = "decode",
|
||||
[LATENCY_PROBE_DEC_POST] = "decode",
|
||||
[LATENCY_PROBE_FILTER_PRE] = "filter",
|
||||
[LATENCY_PROBE_FILTER_POST] = "filter",
|
||||
[LATENCY_PROBE_ENC_PRE] = "encode",
|
||||
[LATENCY_PROBE_ENC_POST] = "encode",
|
||||
[LATENCY_PROBE_NB] = "mux",
|
||||
};
|
||||
MuxStream *ms = ms_from_ost(ost);
|
||||
AVFormatContext *s = mux->fc;
|
||||
int64_t fs;
|
||||
uint64_t frame_num;
|
||||
int ret;
|
||||
|
||||
char latency[512];
|
||||
|
||||
*latency = 0;
|
||||
if (pkt->opaque_ref) {
|
||||
const FrameData *fd = (FrameData*)pkt->opaque_ref->data;
|
||||
int64_t now = av_gettime_relative();
|
||||
int64_t total = INT64_MIN;
|
||||
|
||||
int next;
|
||||
|
||||
for (unsigned i = 0; i < FF_ARRAY_ELEMS(fd->wallclock); i = next) {
|
||||
int64_t val = fd->wallclock[i];
|
||||
|
||||
next = i + 1;
|
||||
|
||||
if (val == INT64_MIN)
|
||||
continue;
|
||||
|
||||
if (total == INT64_MIN) {
|
||||
total = now - val;
|
||||
snprintf(latency, sizeof(latency), "total:%gms", total / 1e3);
|
||||
}
|
||||
|
||||
// find the next valid entry
|
||||
for (; next <= FF_ARRAY_ELEMS(fd->wallclock); next++) {
|
||||
int64_t val_next = (next == FF_ARRAY_ELEMS(fd->wallclock)) ?
|
||||
now : fd->wallclock[next];
|
||||
int64_t diff;
|
||||
|
||||
if (val_next == INT64_MIN)
|
||||
continue;
|
||||
diff = val_next - val;
|
||||
|
||||
// print those stages that take at least 5% of total
|
||||
if (100. * diff > 5. * total) {
|
||||
av_strlcat(latency, ", ", sizeof(latency));
|
||||
|
||||
if (!strcmp(desc[i], desc[next]))
|
||||
av_strlcat(latency, desc[i], sizeof(latency));
|
||||
else
|
||||
av_strlcatf(latency, sizeof(latency), "%s-%s:",
|
||||
desc[i], desc[next]);
|
||||
|
||||
av_strlcatf(latency, sizeof(latency), " %gms/%d%%",
|
||||
diff / 1e3, (int)(100. * diff / total));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
fs = filesize(s->pb);
|
||||
atomic_store(&mux->last_filesize, fs);
|
||||
if (fs >= mux->limit_filesize) {
|
||||
ret = AVERROR_EOF;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
av_log(ost, AV_LOG_INFO, "muxer <- pts:%s pts_time:%s dts:%s dts_time:%s "
|
||||
"duration:%s duration_time:%s size:%d latency(%s)\n",
|
||||
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base),
|
||||
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base),
|
||||
av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->st->time_base),
|
||||
pkt->size, *latency ? latency : "N/A");
|
||||
}
|
||||
|
||||
static int mux_fixup_ts(Muxer *mux, MuxStream *ms, AVPacket *pkt)
|
||||
{
|
||||
OutputStream *ost = &ms->ost;
|
||||
|
||||
#if FFMPEG_OPT_VSYNC_DROP
|
||||
if (ost->type == AVMEDIA_TYPE_VIDEO && ms->ts_drop)
|
||||
if (ost->type == AVMEDIA_TYPE_VIDEO && ost->vsync_method == VSYNC_DROP)
|
||||
pkt->pts = pkt->dts = AV_NOPTS_VALUE;
|
||||
#endif
|
||||
|
||||
// rescale timestamps to the stream timebase
|
||||
if (ost->type == AVMEDIA_TYPE_AUDIO && !ost->enc) {
|
||||
@@ -163,12 +95,13 @@ static int mux_fixup_ts(Muxer *mux, MuxStream *ms, AVPacket *pkt)
|
||||
av_packet_rescale_ts(pkt, pkt->time_base, ost->st->time_base);
|
||||
pkt->time_base = ost->st->time_base;
|
||||
|
||||
if (!(mux->fc->oformat->flags & AVFMT_NOTIMESTAMPS)) {
|
||||
if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) {
|
||||
if (pkt->dts != AV_NOPTS_VALUE &&
|
||||
pkt->pts != AV_NOPTS_VALUE &&
|
||||
pkt->dts > pkt->pts) {
|
||||
av_log(ost, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64", replacing by guess\n",
|
||||
pkt->dts, pkt->pts);
|
||||
av_log(s, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64" in output stream %d:%d, replacing by guess\n",
|
||||
pkt->dts, pkt->pts,
|
||||
ost->file_index, ost->st->index);
|
||||
pkt->pts =
|
||||
pkt->dts = pkt->pts + pkt->dts + ms->last_mux_dts + 1
|
||||
- FFMIN3(pkt->pts, pkt->dts, ms->last_mux_dts + 1)
|
||||
@@ -177,19 +110,20 @@ static int mux_fixup_ts(Muxer *mux, MuxStream *ms, AVPacket *pkt)
|
||||
if ((ost->type == AVMEDIA_TYPE_AUDIO || ost->type == AVMEDIA_TYPE_VIDEO || ost->type == AVMEDIA_TYPE_SUBTITLE) &&
|
||||
pkt->dts != AV_NOPTS_VALUE &&
|
||||
ms->last_mux_dts != AV_NOPTS_VALUE) {
|
||||
int64_t max = ms->last_mux_dts + !(mux->fc->oformat->flags & AVFMT_TS_NONSTRICT);
|
||||
int64_t max = ms->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT);
|
||||
if (pkt->dts < max) {
|
||||
int loglevel = max - pkt->dts > 2 || ost->type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG;
|
||||
if (exit_on_error)
|
||||
loglevel = AV_LOG_ERROR;
|
||||
av_log(ost, loglevel, "Non-monotonic DTS; "
|
||||
"previous: %"PRId64", current: %"PRId64"; ",
|
||||
ms->last_mux_dts, pkt->dts);
|
||||
av_log(s, loglevel, "Non-monotonic DTS in output stream "
|
||||
"%d:%d; previous: %"PRId64", current: %"PRId64"; ",
|
||||
ost->file_index, ost->st->index, ms->last_mux_dts, pkt->dts);
|
||||
if (exit_on_error) {
|
||||
return AVERROR(EINVAL);
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
av_log(ost, loglevel, "changing to %"PRId64". This may result "
|
||||
av_log(s, loglevel, "changing to %"PRId64". This may result "
|
||||
"in incorrect timestamps in the output file.\n",
|
||||
max);
|
||||
if (pkt->pts >= pkt->dts)
|
||||
@@ -200,36 +134,22 @@ static int mux_fixup_ts(Muxer *mux, MuxStream *ms, AVPacket *pkt)
|
||||
}
|
||||
ms->last_mux_dts = pkt->dts;
|
||||
|
||||
if (debug_ts)
|
||||
mux_log_debug_ts(ost, pkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
|
||||
{
|
||||
MuxStream *ms = ms_from_ost(ost);
|
||||
AVFormatContext *s = mux->fc;
|
||||
int64_t fs;
|
||||
uint64_t frame_num;
|
||||
int ret;
|
||||
|
||||
fs = filesize(s->pb);
|
||||
atomic_store(&mux->last_filesize, fs);
|
||||
if (fs >= mux->limit_filesize) {
|
||||
ret = AVERROR_EOF;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = mux_fixup_ts(mux, ms, pkt);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
ms->data_size_mux += pkt->size;
|
||||
frame_num = atomic_fetch_add(&ost->packets_written, 1);
|
||||
|
||||
pkt->stream_index = ost->index;
|
||||
|
||||
if (debug_ts) {
|
||||
av_log(ost, AV_LOG_INFO, "muxer <- type:%s "
|
||||
"pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s size:%d\n",
|
||||
av_get_media_type_string(ost->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),
|
||||
av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->st->time_base),
|
||||
pkt->size
|
||||
);
|
||||
}
|
||||
|
||||
if (ms->stats.io)
|
||||
enc_stats_write(ost, &ms->stats, NULL, pkt, frame_num);
|
||||
|
||||
@@ -247,12 +167,12 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sync_queue_process(Muxer *mux, MuxStream *ms, AVPacket *pkt, int *stream_eof)
|
||||
static int sync_queue_process(Muxer *mux, OutputStream *ost, AVPacket *pkt, int *stream_eof)
|
||||
{
|
||||
OutputFile *of = &mux->of;
|
||||
|
||||
if (ms->sq_idx_mux >= 0) {
|
||||
int ret = sq_send(mux->sq_mux, ms->sq_idx_mux, SQPKT(pkt));
|
||||
if (ost->sq_idx_mux >= 0) {
|
||||
int ret = sq_send(mux->sq_mux, ost->sq_idx_mux, SQPKT(pkt));
|
||||
if (ret < 0) {
|
||||
if (ret == AVERROR_EOF)
|
||||
*stream_eof = 1;
|
||||
@@ -277,46 +197,166 @@ static int sync_queue_process(Muxer *mux, MuxStream *ms, AVPacket *pkt, int *str
|
||||
return ret;
|
||||
}
|
||||
} else if (pkt)
|
||||
return write_packet(mux, &ms->ost, pkt);
|
||||
return write_packet(mux, ost, pkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int of_streamcopy(OutputFile *of, OutputStream *ost, AVPacket *pkt);
|
||||
static void thread_set_name(OutputFile *of)
|
||||
{
|
||||
char name[16];
|
||||
snprintf(name, sizeof(name), "mux%d:%s", of->index, of->format->name);
|
||||
ff_thread_setname(name);
|
||||
}
|
||||
|
||||
/* apply the output bitstream filters */
|
||||
static int mux_packet_filter(Muxer *mux, MuxThreadContext *mt,
|
||||
OutputStream *ost, AVPacket *pkt, int *stream_eof)
|
||||
static void *muxer_thread(void *arg)
|
||||
{
|
||||
Muxer *mux = arg;
|
||||
OutputFile *of = &mux->of;
|
||||
AVPacket *pkt = NULL;
|
||||
int ret = 0;
|
||||
|
||||
pkt = av_packet_alloc();
|
||||
if (!pkt) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
thread_set_name(of);
|
||||
|
||||
while (1) {
|
||||
OutputStream *ost;
|
||||
int stream_idx, stream_eof = 0;
|
||||
|
||||
ret = tq_receive(mux->tq, &stream_idx, pkt);
|
||||
if (stream_idx < 0) {
|
||||
av_log(mux, AV_LOG_VERBOSE, "All streams finished\n");
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ost = of->streams[stream_idx];
|
||||
ret = sync_queue_process(mux, ost, ret < 0 ? NULL : pkt, &stream_eof);
|
||||
av_packet_unref(pkt);
|
||||
if (ret == AVERROR_EOF) {
|
||||
if (stream_eof) {
|
||||
tq_receive_finish(mux->tq, stream_idx);
|
||||
} else {
|
||||
av_log(mux, AV_LOG_VERBOSE, "Muxer returned EOF\n");
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
} else if (ret < 0) {
|
||||
av_log(mux, AV_LOG_ERROR, "Error muxing a packet\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
finish:
|
||||
av_packet_free(&pkt);
|
||||
|
||||
for (unsigned int i = 0; i < mux->fc->nb_streams; i++)
|
||||
tq_receive_finish(mux->tq, i);
|
||||
|
||||
av_log(mux, AV_LOG_VERBOSE, "Terminating muxer thread\n");
|
||||
|
||||
return (void*)(intptr_t)ret;
|
||||
}
|
||||
|
||||
static int thread_submit_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!pkt || ost->finished & MUXER_FINISHED)
|
||||
goto finish;
|
||||
|
||||
ret = tq_send(mux->tq, ost->index, pkt);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
|
||||
return 0;
|
||||
|
||||
finish:
|
||||
if (pkt)
|
||||
av_packet_unref(pkt);
|
||||
|
||||
ost->finished |= MUXER_FINISHED;
|
||||
tq_send_finish(mux->tq, ost->index);
|
||||
return ret == AVERROR_EOF ? 0 : ret;
|
||||
}
|
||||
|
||||
static int queue_packet(OutputStream *ost, AVPacket *pkt)
|
||||
{
|
||||
MuxStream *ms = ms_from_ost(ost);
|
||||
const char *err_msg;
|
||||
AVPacket *tmp_pkt = NULL;
|
||||
int ret;
|
||||
|
||||
if (pkt && !ost->enc) {
|
||||
ret = of_streamcopy(&mux->of, ost, pkt);
|
||||
if (ret == AVERROR(EAGAIN))
|
||||
return 0;
|
||||
else if (ret == AVERROR_EOF) {
|
||||
av_packet_unref(pkt);
|
||||
pkt = NULL;
|
||||
*stream_eof = 1;
|
||||
} else if (ret < 0)
|
||||
goto fail;
|
||||
}
|
||||
if (!av_fifo_can_write(ms->muxing_queue)) {
|
||||
size_t cur_size = av_fifo_can_read(ms->muxing_queue);
|
||||
size_t pkt_size = pkt ? pkt->size : 0;
|
||||
unsigned int are_we_over_size =
|
||||
(ms->muxing_queue_data_size + pkt_size) > ms->muxing_queue_data_threshold;
|
||||
size_t limit = are_we_over_size ? ms->max_muxing_queue_size : SIZE_MAX;
|
||||
size_t new_size = FFMIN(2 * cur_size, limit);
|
||||
|
||||
// emit heartbeat for -fix_sub_duration;
|
||||
// we are only interested in heartbeats on on random access points.
|
||||
if (pkt && (pkt->flags & AV_PKT_FLAG_KEY)) {
|
||||
mt->fix_sub_duration_pkt->opaque = (void*)(intptr_t)PKT_OPAQUE_FIX_SUB_DURATION;
|
||||
mt->fix_sub_duration_pkt->pts = pkt->pts;
|
||||
mt->fix_sub_duration_pkt->time_base = pkt->time_base;
|
||||
|
||||
ret = sch_mux_sub_heartbeat(mux->sch, mux->sch_idx, ms->sch_idx,
|
||||
mt->fix_sub_duration_pkt);
|
||||
if (new_size <= cur_size) {
|
||||
av_log(ost, AV_LOG_ERROR,
|
||||
"Too many packets buffered for output stream %d:%d.\n",
|
||||
ost->file_index, ost->st->index);
|
||||
return AVERROR(ENOSPC);
|
||||
}
|
||||
ret = av_fifo_grow2(ms->muxing_queue, new_size - cur_size);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pkt) {
|
||||
ret = av_packet_make_refcounted(pkt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
tmp_pkt = av_packet_alloc();
|
||||
if (!tmp_pkt)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
av_packet_move_ref(tmp_pkt, pkt);
|
||||
ms->muxing_queue_data_size += tmp_pkt->size;
|
||||
}
|
||||
av_fifo_write(ms->muxing_queue, &tmp_pkt, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int submit_packet(Muxer *mux, AVPacket *pkt, OutputStream *ost)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (mux->tq) {
|
||||
return thread_submit_packet(mux, ost, pkt);
|
||||
} else {
|
||||
/* the muxer is not initialized yet, buffer the packet */
|
||||
ret = queue_packet(ost, pkt);
|
||||
if (ret < 0) {
|
||||
if (pkt)
|
||||
av_packet_unref(pkt);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int of_output_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
|
||||
{
|
||||
Muxer *mux = mux_from_of(of);
|
||||
MuxStream *ms = ms_from_ost(ost);
|
||||
const char *err_msg;
|
||||
int ret = 0;
|
||||
|
||||
if (pkt && pkt->dts != AV_NOPTS_VALUE)
|
||||
ost->last_mux_dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q);
|
||||
|
||||
/* apply the output bitstream filters */
|
||||
if (ms->bsf_ctx) {
|
||||
int bsf_eof = 0;
|
||||
|
||||
@@ -336,189 +376,180 @@ static int mux_packet_filter(Muxer *mux, MuxThreadContext *mt,
|
||||
else if (ret == AVERROR_EOF)
|
||||
bsf_eof = 1;
|
||||
else if (ret < 0) {
|
||||
av_log(ost, AV_LOG_ERROR,
|
||||
"Error applying bitstream filters to a packet: %s",
|
||||
av_err2str(ret));
|
||||
if (exit_on_error)
|
||||
return ret;
|
||||
continue;
|
||||
err_msg = "applying bitstream filters to a packet";
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!bsf_eof)
|
||||
ms->bsf_pkt->time_base = ms->bsf_ctx->time_base_out;
|
||||
|
||||
ret = sync_queue_process(mux, ms, bsf_eof ? NULL : ms->bsf_pkt, stream_eof);
|
||||
ret = submit_packet(mux, bsf_eof ? NULL : ms->bsf_pkt, ost);
|
||||
if (ret < 0)
|
||||
goto mux_fail;
|
||||
}
|
||||
*stream_eof = 1;
|
||||
} else {
|
||||
ret = sync_queue_process(mux, ms, pkt, stream_eof);
|
||||
ret = submit_packet(mux, pkt, ost);
|
||||
if (ret < 0)
|
||||
goto mux_fail;
|
||||
}
|
||||
|
||||
return *stream_eof ? AVERROR_EOF : 0;
|
||||
return 0;
|
||||
|
||||
mux_fail:
|
||||
err_msg = "submitting a packet to the muxer";
|
||||
|
||||
fail:
|
||||
if (ret != AVERROR_EOF)
|
||||
av_log(ost, AV_LOG_ERROR, "Error %s: %s\n", err_msg, av_err2str(ret));
|
||||
return ret;
|
||||
av_log(ost, AV_LOG_ERROR, "Error %s\n", err_msg);
|
||||
return exit_on_error ? ret : 0;
|
||||
}
|
||||
|
||||
static void thread_set_name(Muxer *mux)
|
||||
{
|
||||
char name[16];
|
||||
snprintf(name, sizeof(name), "mux%d:%s",
|
||||
mux->of.index, mux->fc->oformat->name);
|
||||
ff_thread_setname(name);
|
||||
}
|
||||
|
||||
static void mux_thread_uninit(MuxThreadContext *mt)
|
||||
{
|
||||
av_packet_free(&mt->pkt);
|
||||
av_packet_free(&mt->fix_sub_duration_pkt);
|
||||
|
||||
memset(mt, 0, sizeof(*mt));
|
||||
}
|
||||
|
||||
static int mux_thread_init(MuxThreadContext *mt)
|
||||
{
|
||||
memset(mt, 0, sizeof(*mt));
|
||||
|
||||
mt->pkt = av_packet_alloc();
|
||||
if (!mt->pkt)
|
||||
goto fail;
|
||||
|
||||
mt->fix_sub_duration_pkt = av_packet_alloc();
|
||||
if (!mt->fix_sub_duration_pkt)
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
mux_thread_uninit(mt);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
int muxer_thread(void *arg)
|
||||
{
|
||||
Muxer *mux = arg;
|
||||
OutputFile *of = &mux->of;
|
||||
|
||||
MuxThreadContext mt;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
ret = mux_thread_init(&mt);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
|
||||
thread_set_name(mux);
|
||||
|
||||
while (1) {
|
||||
OutputStream *ost;
|
||||
int stream_idx, stream_eof = 0;
|
||||
|
||||
ret = sch_mux_receive(mux->sch, of->index, mt.pkt);
|
||||
stream_idx = mt.pkt->stream_index;
|
||||
if (stream_idx < 0) {
|
||||
av_log(mux, AV_LOG_VERBOSE, "All streams finished\n");
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ost = of->streams[mux->sch_stream_idx[stream_idx]];
|
||||
mt.pkt->stream_index = ost->index;
|
||||
mt.pkt->flags &= ~AV_PKT_FLAG_TRUSTED;
|
||||
|
||||
ret = mux_packet_filter(mux, &mt, ost, ret < 0 ? NULL : mt.pkt, &stream_eof);
|
||||
av_packet_unref(mt.pkt);
|
||||
if (ret == AVERROR_EOF) {
|
||||
if (stream_eof) {
|
||||
sch_mux_receive_finish(mux->sch, of->index, stream_idx);
|
||||
} else {
|
||||
av_log(mux, AV_LOG_VERBOSE, "Muxer returned EOF\n");
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
} else if (ret < 0) {
|
||||
av_log(mux, AV_LOG_ERROR, "Error muxing a packet\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
finish:
|
||||
mux_thread_uninit(&mt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int of_streamcopy(OutputFile *of, OutputStream *ost, AVPacket *pkt)
|
||||
int of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts)
|
||||
{
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
MuxStream *ms = ms_from_ost(ost);
|
||||
FrameData *fd = pkt->opaque_ref ? (FrameData*)pkt->opaque_ref->data : NULL;
|
||||
int64_t dts = fd ? fd->dts_est : AV_NOPTS_VALUE;
|
||||
int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time;
|
||||
int64_t ts_offset;
|
||||
AVPacket *opkt = ms->pkt;
|
||||
int ret;
|
||||
|
||||
av_packet_unref(opkt);
|
||||
|
||||
if (of->recording_time != INT64_MAX &&
|
||||
dts >= of->recording_time + start_time)
|
||||
return AVERROR_EOF;
|
||||
pkt = NULL;
|
||||
|
||||
// EOF: flush output bitstream filters.
|
||||
if (!pkt)
|
||||
return of_output_packet(of, ost, NULL);
|
||||
|
||||
if (!ms->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) &&
|
||||
!ms->copy_initial_nonkeyframes)
|
||||
return AVERROR(EAGAIN);
|
||||
return 0;
|
||||
|
||||
if (!ms->streamcopy_started) {
|
||||
if (!ms->copy_prior_start &&
|
||||
(pkt->pts == AV_NOPTS_VALUE ?
|
||||
dts < ms->ts_copy_start :
|
||||
pkt->pts < av_rescale_q(ms->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base)))
|
||||
return AVERROR(EAGAIN);
|
||||
return 0;
|
||||
|
||||
if (of->start_time != AV_NOPTS_VALUE && dts < of->start_time)
|
||||
return AVERROR(EAGAIN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ts_offset = av_rescale_q(start_time, AV_TIME_BASE_Q, pkt->time_base);
|
||||
ret = av_packet_ref(opkt, pkt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ts_offset = av_rescale_q(start_time, AV_TIME_BASE_Q, opkt->time_base);
|
||||
|
||||
if (pkt->pts != AV_NOPTS_VALUE)
|
||||
pkt->pts -= ts_offset;
|
||||
opkt->pts -= ts_offset;
|
||||
|
||||
if (pkt->dts == AV_NOPTS_VALUE) {
|
||||
pkt->dts = av_rescale_q(dts, AV_TIME_BASE_Q, pkt->time_base);
|
||||
opkt->dts = av_rescale_q(dts, AV_TIME_BASE_Q, opkt->time_base);
|
||||
} else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
pkt->pts = pkt->dts - ts_offset;
|
||||
opkt->pts = opkt->dts - ts_offset;
|
||||
}
|
||||
opkt->dts -= ts_offset;
|
||||
|
||||
{
|
||||
int ret = trigger_fix_sub_duration_heartbeat(ost, pkt);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Subtitle heartbeat logic failed in %s! (%s)\n",
|
||||
__func__, av_err2str(ret));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
pkt->dts -= ts_offset;
|
||||
ret = of_output_packet(of, ost, opkt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ms->streamcopy_started = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_sdp(const char *filename);
|
||||
static int thread_stop(Muxer *mux)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
int print_sdp(const char *filename)
|
||||
if (!mux || !mux->tq)
|
||||
return 0;
|
||||
|
||||
for (unsigned int i = 0; i < mux->fc->nb_streams; i++)
|
||||
tq_send_finish(mux->tq, i);
|
||||
|
||||
pthread_join(mux->thread, &ret);
|
||||
|
||||
tq_free(&mux->tq);
|
||||
|
||||
return (int)(intptr_t)ret;
|
||||
}
|
||||
|
||||
static int thread_start(Muxer *mux)
|
||||
{
|
||||
AVFormatContext *fc = mux->fc;
|
||||
ObjPool *op;
|
||||
int ret;
|
||||
|
||||
op = objpool_alloc_packets();
|
||||
if (!op)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
mux->tq = tq_alloc(fc->nb_streams, mux->thread_queue_size, op, pkt_move);
|
||||
if (!mux->tq) {
|
||||
objpool_free(&op);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
ret = pthread_create(&mux->thread, NULL, muxer_thread, (void*)mux);
|
||||
if (ret) {
|
||||
tq_free(&mux->tq);
|
||||
return AVERROR(ret);
|
||||
}
|
||||
|
||||
/* flush the muxing queues */
|
||||
for (int i = 0; i < fc->nb_streams; i++) {
|
||||
OutputStream *ost = mux->of.streams[i];
|
||||
MuxStream *ms = ms_from_ost(ost);
|
||||
AVPacket *pkt;
|
||||
|
||||
while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0) {
|
||||
ret = thread_submit_packet(mux, ost, pkt);
|
||||
if (pkt) {
|
||||
ms->muxing_queue_data_size -= pkt->size;
|
||||
av_packet_free(&pkt);
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_sdp(void)
|
||||
{
|
||||
char sdp[16384];
|
||||
int j = 0, ret;
|
||||
int i;
|
||||
int j, ret;
|
||||
AVIOContext *sdp_pb;
|
||||
AVFormatContext **avc;
|
||||
|
||||
for (i = 0; i < nb_output_files; i++) {
|
||||
if (!mux_from_of(output_files[i])->header_written)
|
||||
return 0;
|
||||
}
|
||||
|
||||
avc = av_malloc_array(nb_output_files, sizeof(*avc));
|
||||
if (!avc)
|
||||
return AVERROR(ENOMEM);
|
||||
for (int i = 0; i < nb_output_files; i++) {
|
||||
Muxer *mux = mux_from_of(output_files[i]);
|
||||
|
||||
if (!strcmp(mux->fc->oformat->name, "rtp")) {
|
||||
avc[j] = mux->fc;
|
||||
for (i = 0, j = 0; i < nb_output_files; i++) {
|
||||
if (!strcmp(output_files[i]->format->name, "rtp")) {
|
||||
avc[j] = mux_from_of(output_files[i])->fc;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
@@ -533,31 +564,40 @@ int print_sdp(const char *filename)
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
if (!filename) {
|
||||
if (!sdp_filename) {
|
||||
printf("SDP:\n%s\n", sdp);
|
||||
fflush(stdout);
|
||||
} else {
|
||||
ret = avio_open2(&sdp_pb, filename, AVIO_FLAG_WRITE, &int_cb, NULL);
|
||||
ret = avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", filename);
|
||||
av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
avio_print(sdp_pb, sdp);
|
||||
avio_closep(&sdp_pb);
|
||||
av_freep(&sdp_filename);
|
||||
}
|
||||
|
||||
// SDP successfully written, allow muxer threads to start
|
||||
ret = 1;
|
||||
|
||||
fail:
|
||||
av_freep(&avc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mux_check_init(void *arg)
|
||||
int mux_check_init(Muxer *mux)
|
||||
{
|
||||
Muxer *mux = arg;
|
||||
OutputFile *of = &mux->of;
|
||||
AVFormatContext *fc = mux->fc;
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < fc->nb_streams; i++) {
|
||||
OutputStream *ost = of->streams[i];
|
||||
if (!ost->initialized)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = avformat_write_header(fc, &mux->opts);
|
||||
if (ret < 0) {
|
||||
@@ -569,7 +609,27 @@ int mux_check_init(void *arg)
|
||||
mux->header_written = 1;
|
||||
|
||||
av_dump_format(fc, of->index, fc->url, 1);
|
||||
atomic_fetch_add(&nb_output_dumped, 1);
|
||||
nb_output_dumped++;
|
||||
|
||||
if (sdp_filename || want_sdp) {
|
||||
ret = print_sdp();
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Error writing the SDP.\n");
|
||||
return ret;
|
||||
} else if (ret == 1) {
|
||||
/* SDP is written only after all the muxers are ready, so now we
|
||||
* start ALL the threads */
|
||||
for (i = 0; i < nb_output_files; i++) {
|
||||
ret = thread_start(mux_from_of(output_files[i]));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret = thread_start(mux_from_of(of));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -626,10 +686,9 @@ int of_stream_init(OutputFile *of, OutputStream *ost)
|
||||
ost->st->time_base);
|
||||
}
|
||||
|
||||
if (ms->sch_idx >= 0)
|
||||
return sch_mux_stream_ready(mux->sch, of->index, ms->sch_idx);
|
||||
ost->initialized = 1;
|
||||
|
||||
return 0;
|
||||
return mux_check_init(mux);
|
||||
}
|
||||
|
||||
static int check_written(OutputFile *of)
|
||||
@@ -727,8 +786,8 @@ static void mux_final_stats(Muxer *mux)
|
||||
}
|
||||
|
||||
av_log(of, AV_LOG_INFO,
|
||||
"video:%1.0fKiB audio:%1.0fKiB subtitle:%1.0fKiB other streams:%1.0fKiB "
|
||||
"global headers:%1.0fKiB muxing overhead: %s\n",
|
||||
"video:%1.0fkB audio:%1.0fkB subtitle:%1.0fkB other streams:%1.0fkB "
|
||||
"global headers:%1.0fkB muxing overhead: %s\n",
|
||||
video_size / 1024.0,
|
||||
audio_size / 1024.0,
|
||||
subtitle_size / 1024.0,
|
||||
@@ -743,13 +802,15 @@ int of_write_trailer(OutputFile *of)
|
||||
AVFormatContext *fc = mux->fc;
|
||||
int ret, mux_result = 0;
|
||||
|
||||
if (!mux->header_written) {
|
||||
if (!mux->tq) {
|
||||
av_log(mux, AV_LOG_ERROR,
|
||||
"Nothing was written into output file, because "
|
||||
"at least one of its streams received no packets.\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
mux_result = thread_stop(mux);
|
||||
|
||||
ret = av_write_trailer(fc);
|
||||
if (ret < 0) {
|
||||
av_log(mux, AV_LOG_ERROR, "Error writing trailer: %s\n", av_err2str(ret));
|
||||
@@ -758,7 +819,7 @@ int of_write_trailer(OutputFile *of)
|
||||
|
||||
mux->last_filesize = filesize(fc->pb);
|
||||
|
||||
if (!(fc->oformat->flags & AVFMT_NOFILE)) {
|
||||
if (!(of->format->flags & AVFMT_NOFILE)) {
|
||||
ret = avio_closep(&fc->pb);
|
||||
if (ret < 0) {
|
||||
av_log(mux, AV_LOG_ERROR, "Error closing file: %s\n", av_err2str(ret));
|
||||
@@ -775,17 +836,6 @@ int of_write_trailer(OutputFile *of)
|
||||
return mux_result;
|
||||
}
|
||||
|
||||
static void enc_stats_uninit(EncStats *es)
|
||||
{
|
||||
for (int i = 0; i < es->nb_components; i++)
|
||||
av_freep(&es->components[i].str);
|
||||
av_freep(&es->components);
|
||||
|
||||
if (es->lock_initialized)
|
||||
pthread_mutex_destroy(&es->lock);
|
||||
es->lock_initialized = 0;
|
||||
}
|
||||
|
||||
static void ost_free(OutputStream **post)
|
||||
{
|
||||
OutputStream *ost = *post;
|
||||
@@ -796,7 +846,6 @@ static void ost_free(OutputStream **post)
|
||||
ms = ms_from_ost(ost);
|
||||
|
||||
enc_free(&ost->enc);
|
||||
fg_free(&ost->fg_simple);
|
||||
|
||||
if (ost->logfile) {
|
||||
if (fclose(ost->logfile))
|
||||
@@ -806,27 +855,50 @@ static void ost_free(OutputStream **post)
|
||||
ost->logfile = NULL;
|
||||
}
|
||||
|
||||
if (ms->muxing_queue) {
|
||||
AVPacket *pkt;
|
||||
while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0)
|
||||
av_packet_free(&pkt);
|
||||
av_fifo_freep2(&ms->muxing_queue);
|
||||
}
|
||||
|
||||
avcodec_parameters_free(&ost->par_in);
|
||||
|
||||
av_bsf_free(&ms->bsf_ctx);
|
||||
av_packet_free(&ms->bsf_pkt);
|
||||
|
||||
av_packet_free(&ms->pkt);
|
||||
av_dict_free(&ost->encoder_opts);
|
||||
|
||||
av_freep(&ost->kf.pts);
|
||||
av_expr_free(ost->kf.pexpr);
|
||||
|
||||
av_freep(&ost->logfile_prefix);
|
||||
av_freep(&ost->apad);
|
||||
|
||||
av_freep(&ost->attachment_filename);
|
||||
#if FFMPEG_OPT_MAP_CHANNEL
|
||||
av_freep(&ost->audio_channels_map);
|
||||
ost->audio_channels_mapped = 0;
|
||||
#endif
|
||||
|
||||
av_dict_free(&ost->sws_dict);
|
||||
av_dict_free(&ost->swr_opts);
|
||||
|
||||
if (ost->enc_ctx)
|
||||
av_freep(&ost->enc_ctx->stats_in);
|
||||
avcodec_free_context(&ost->enc_ctx);
|
||||
|
||||
enc_stats_uninit(&ost->enc_stats_pre);
|
||||
enc_stats_uninit(&ost->enc_stats_post);
|
||||
enc_stats_uninit(&ms->stats);
|
||||
for (int i = 0; i < ost->enc_stats_pre.nb_components; i++)
|
||||
av_freep(&ost->enc_stats_pre.components[i].str);
|
||||
av_freep(&ost->enc_stats_pre.components);
|
||||
|
||||
for (int i = 0; i < ost->enc_stats_post.nb_components; i++)
|
||||
av_freep(&ost->enc_stats_post.components[i].str);
|
||||
av_freep(&ost->enc_stats_post.components);
|
||||
|
||||
for (int i = 0; i < ms->stats.nb_components; i++)
|
||||
av_freep(&ms->stats.components[i].str);
|
||||
av_freep(&ms->stats.components);
|
||||
|
||||
av_freep(post);
|
||||
}
|
||||
@@ -854,16 +926,16 @@ void of_free(OutputFile **pof)
|
||||
return;
|
||||
mux = mux_from_of(of);
|
||||
|
||||
thread_stop(mux);
|
||||
|
||||
sq_free(&of->sq_encode);
|
||||
sq_free(&mux->sq_mux);
|
||||
|
||||
for (int i = 0; i < of->nb_streams; i++)
|
||||
ost_free(&of->streams[i]);
|
||||
av_freep(&of->streams);
|
||||
|
||||
av_freep(&mux->sch_stream_idx);
|
||||
|
||||
av_dict_free(&mux->opts);
|
||||
av_dict_free(&mux->enc_opts_used);
|
||||
|
||||
av_packet_free(&mux->sq_pkt);
|
||||
|
||||
|
||||
+46
-44
@@ -24,7 +24,7 @@
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ffmpeg_sched.h"
|
||||
#include "thread_queue.h"
|
||||
|
||||
#include "libavformat/avformat.h"
|
||||
|
||||
@@ -32,86 +32,88 @@
|
||||
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavutil/fifo.h"
|
||||
#include "libavutil/thread.h"
|
||||
|
||||
typedef struct MuxStream {
|
||||
OutputStream ost;
|
||||
OutputStream ost;
|
||||
|
||||
// name used for logging
|
||||
char log_name[32];
|
||||
char log_name[32];
|
||||
|
||||
AVBSFContext *bsf_ctx;
|
||||
AVPacket *bsf_pkt;
|
||||
/* the packets are buffered here until the muxer is ready to be initialized */
|
||||
AVFifo *muxing_queue;
|
||||
|
||||
AVPacket *pkt;
|
||||
AVBSFContext *bsf_ctx;
|
||||
AVPacket *bsf_pkt;
|
||||
|
||||
EncStats stats;
|
||||
AVPacket *pkt;
|
||||
|
||||
int sch_idx;
|
||||
int sch_idx_enc;
|
||||
int sch_idx_src;
|
||||
EncStats stats;
|
||||
|
||||
int sq_idx_mux;
|
||||
int64_t max_frames;
|
||||
|
||||
int64_t max_frames;
|
||||
/*
|
||||
* The size of the AVPackets' buffers in queue.
|
||||
* Updated when a packet is either pushed or pulled from the queue.
|
||||
*/
|
||||
size_t muxing_queue_data_size;
|
||||
|
||||
int max_muxing_queue_size;
|
||||
|
||||
/* Threshold after which max_muxing_queue_size will be in effect */
|
||||
size_t muxing_queue_data_threshold;
|
||||
|
||||
// timestamp from which the streamcopied streams should start,
|
||||
// in AV_TIME_BASE_Q;
|
||||
// everything before it should be discarded
|
||||
int64_t ts_copy_start;
|
||||
int64_t ts_copy_start;
|
||||
|
||||
/* dts of the last packet sent to the muxer, in the stream timebase
|
||||
* used for making up missing dts values */
|
||||
int64_t last_mux_dts;
|
||||
int64_t last_mux_dts;
|
||||
|
||||
int64_t stream_duration;
|
||||
AVRational stream_duration_tb;
|
||||
int64_t stream_duration;
|
||||
AVRational stream_duration_tb;
|
||||
|
||||
// state for av_rescale_delta() call for audio in write_packet()
|
||||
int64_t ts_rescale_delta_last;
|
||||
int64_t ts_rescale_delta_last;
|
||||
|
||||
// combined size of all the packets sent to the muxer
|
||||
uint64_t data_size_mux;
|
||||
uint64_t data_size_mux;
|
||||
|
||||
int copy_initial_nonkeyframes;
|
||||
int copy_prior_start;
|
||||
int streamcopy_started;
|
||||
#if FFMPEG_OPT_VSYNC_DROP
|
||||
int ts_drop;
|
||||
#endif
|
||||
|
||||
const char *apad;
|
||||
int copy_initial_nonkeyframes;
|
||||
int copy_prior_start;
|
||||
int streamcopy_started;
|
||||
} MuxStream;
|
||||
|
||||
typedef struct Muxer {
|
||||
OutputFile of;
|
||||
OutputFile of;
|
||||
|
||||
// name used for logging
|
||||
char log_name[32];
|
||||
char log_name[32];
|
||||
|
||||
AVFormatContext *fc;
|
||||
AVFormatContext *fc;
|
||||
|
||||
Scheduler *sch;
|
||||
unsigned sch_idx;
|
||||
pthread_t thread;
|
||||
ThreadQueue *tq;
|
||||
|
||||
// OutputStream indices indexed by scheduler stream indices
|
||||
int *sch_stream_idx;
|
||||
int nb_sch_stream_idx;
|
||||
AVDictionary *opts;
|
||||
|
||||
AVDictionary *opts;
|
||||
|
||||
// used to validate that all encoder avoptions have been actually used
|
||||
AVDictionary *enc_opts_used;
|
||||
int thread_queue_size;
|
||||
|
||||
/* filesize limit expressed in bytes */
|
||||
int64_t limit_filesize;
|
||||
atomic_int_least64_t last_filesize;
|
||||
int header_written;
|
||||
int64_t limit_filesize;
|
||||
atomic_int_least64_t last_filesize;
|
||||
int header_written;
|
||||
|
||||
SyncQueue *sq_mux;
|
||||
AVPacket *sq_pkt;
|
||||
SyncQueue *sq_mux;
|
||||
AVPacket *sq_pkt;
|
||||
} Muxer;
|
||||
|
||||
int mux_check_init(void *arg);
|
||||
/* whether we want to print an SDP, set in of_open() */
|
||||
extern int want_sdp;
|
||||
|
||||
int mux_check_init(Muxer *mux);
|
||||
|
||||
static MuxStream *ms_from_ost(OutputStream *ost)
|
||||
{
|
||||
|
||||
+468
-1067
File diff suppressed because it is too large
Load Diff
+543
-725
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,504 +0,0 @@
|
||||
/*
|
||||
* Inter-thread scheduling/synchronization.
|
||||
* Copyright (c) 2023 Anton Khirnov
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef FFTOOLS_FFMPEG_SCHED_H
|
||||
#define FFTOOLS_FFMPEG_SCHED_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ffmpeg_utils.h"
|
||||
|
||||
/*
|
||||
* This file contains the API for the transcode scheduler.
|
||||
*
|
||||
* Overall architecture of the transcoding process involves instances of the
|
||||
* following components:
|
||||
* - demuxers, each containing any number of demuxed streams; demuxed packets
|
||||
* belonging to some stream are sent to any number of decoders (transcoding)
|
||||
* and/or muxers (streamcopy);
|
||||
* - decoders, which receive encoded packets from some demuxed stream or
|
||||
* encoder, decode them, and send decoded frames to any number of filtergraph
|
||||
* inputs (audio/video) or encoders (subtitles);
|
||||
* - filtergraphs, each containing zero or more inputs (0 in case the
|
||||
* filtergraph contains a lavfi source filter), and one or more outputs; the
|
||||
* inputs and outputs need not have matching media types;
|
||||
* each filtergraph input receives decoded frames from some decoder or another
|
||||
* filtergraph output;
|
||||
* filtered frames from each output are sent to some encoder;
|
||||
* - encoders, which receive decoded frames from some decoder (subtitles) or
|
||||
* some filtergraph output (audio/video), encode them, and send encoded
|
||||
* packets to any number of muxed streams or decoders;
|
||||
* - muxers, each containing any number of muxed streams; each muxed stream
|
||||
* receives encoded packets from some demuxed stream (streamcopy) or some
|
||||
* encoder (transcoding); those packets are interleaved and written out by the
|
||||
* muxer.
|
||||
*
|
||||
* The structure formed by the above components is a directed acyclic graph
|
||||
* (absence of cycles is checked at startup).
|
||||
*
|
||||
* There must be at least one muxer instance, otherwise the transcode produces
|
||||
* no output and is meaningless. Otherwise, in a generic transcoding scenario
|
||||
* there may be arbitrary number of instances of any of the above components,
|
||||
* interconnected in various ways.
|
||||
*
|
||||
* The code tries to keep all the output streams across all the muxers in sync
|
||||
* (i.e. at the same DTS), which is accomplished by varying the rates at which
|
||||
* packets are read from different demuxers and lavfi sources. Note that the
|
||||
* degree of control we have over synchronization is fundamentally limited - if
|
||||
* some demuxed streams in the same input are interleaved at different rates
|
||||
* than that at which they are to be muxed (e.g. because an input file is badly
|
||||
* interleaved, or the user changed their speed by mismatching amounts), then
|
||||
* there will be increasing amounts of buffering followed by eventual
|
||||
* transcoding failure.
|
||||
*
|
||||
* N.B. 1: there are meaningful transcode scenarios with no demuxers, e.g.
|
||||
* - encoding and muxing output from filtergraph(s) that have no inputs;
|
||||
* - creating a file that contains nothing but attachments and/or metadata.
|
||||
*
|
||||
* N.B. 2: a filtergraph output could, in principle, feed multiple encoders, but
|
||||
* this is unnecessary because the (a)split filter provides the same
|
||||
* functionality.
|
||||
*
|
||||
* The scheduler, in the above model, is the master object that oversees and
|
||||
* facilitates the transcoding process. The basic idea is that all instances
|
||||
* of the abovementioned components communicate only with the scheduler and not
|
||||
* with each other. The scheduler is then the single place containing the
|
||||
* knowledge about the whole transcoding pipeline.
|
||||
*/
|
||||
|
||||
struct AVFrame;
|
||||
struct AVPacket;
|
||||
|
||||
typedef struct Scheduler Scheduler;
|
||||
|
||||
enum SchedulerNodeType {
|
||||
SCH_NODE_TYPE_NONE = 0,
|
||||
SCH_NODE_TYPE_DEMUX,
|
||||
SCH_NODE_TYPE_MUX,
|
||||
SCH_NODE_TYPE_DEC,
|
||||
SCH_NODE_TYPE_ENC,
|
||||
SCH_NODE_TYPE_FILTER_IN,
|
||||
SCH_NODE_TYPE_FILTER_OUT,
|
||||
};
|
||||
|
||||
typedef struct SchedulerNode {
|
||||
enum SchedulerNodeType type;
|
||||
unsigned idx;
|
||||
unsigned idx_stream;
|
||||
} SchedulerNode;
|
||||
|
||||
typedef int (*SchThreadFunc)(void *arg);
|
||||
|
||||
#define SCH_DSTREAM(file, stream) \
|
||||
(SchedulerNode){ .type = SCH_NODE_TYPE_DEMUX, \
|
||||
.idx = file, .idx_stream = stream }
|
||||
#define SCH_MSTREAM(file, stream) \
|
||||
(SchedulerNode){ .type = SCH_NODE_TYPE_MUX, \
|
||||
.idx = file, .idx_stream = stream }
|
||||
#define SCH_DEC_IN(decoder) \
|
||||
(SchedulerNode){ .type = SCH_NODE_TYPE_DEC, \
|
||||
.idx = decoder }
|
||||
#define SCH_DEC_OUT(decoder, out_idx) \
|
||||
(SchedulerNode){ .type = SCH_NODE_TYPE_DEC, \
|
||||
.idx = decoder, .idx_stream = out_idx }
|
||||
#define SCH_ENC(encoder) \
|
||||
(SchedulerNode){ .type = SCH_NODE_TYPE_ENC, \
|
||||
.idx = encoder }
|
||||
#define SCH_FILTER_IN(filter, input) \
|
||||
(SchedulerNode){ .type = SCH_NODE_TYPE_FILTER_IN, \
|
||||
.idx = filter, .idx_stream = input }
|
||||
#define SCH_FILTER_OUT(filter, output) \
|
||||
(SchedulerNode){ .type = SCH_NODE_TYPE_FILTER_OUT, \
|
||||
.idx = filter, .idx_stream = output }
|
||||
|
||||
Scheduler *sch_alloc(void);
|
||||
void sch_free(Scheduler **sch);
|
||||
|
||||
int sch_start(Scheduler *sch);
|
||||
int sch_stop(Scheduler *sch, int64_t *finish_ts);
|
||||
|
||||
/**
|
||||
* Wait until transcoding terminates or the specified timeout elapses.
|
||||
*
|
||||
* @param timeout_us Amount of time in microseconds after which this function
|
||||
* will timeout.
|
||||
* @param transcode_ts Current transcode timestamp in AV_TIME_BASE_Q, for
|
||||
* informational purposes only.
|
||||
*
|
||||
* @retval 0 waiting timed out, transcoding is not finished
|
||||
* @retval 1 transcoding is finished
|
||||
*/
|
||||
int sch_wait(Scheduler *sch, uint64_t timeout_us, int64_t *transcode_ts);
|
||||
|
||||
/**
|
||||
* Add a demuxer to the scheduler.
|
||||
*
|
||||
* @param func Function executed as the demuxer task.
|
||||
* @param ctx Demuxer state; will be passed to func and used for logging.
|
||||
*
|
||||
* @retval ">=0" Index of the newly-created demuxer.
|
||||
* @retval "<0" Error code.
|
||||
*/
|
||||
int sch_add_demux(Scheduler *sch, SchThreadFunc func, void *ctx);
|
||||
/**
|
||||
* Add a demuxed stream for a previously added demuxer.
|
||||
*
|
||||
* @param demux_idx index previously returned by sch_add_demux()
|
||||
*
|
||||
* @retval ">=0" Index of the newly-created demuxed stream.
|
||||
* @retval "<0" Error code.
|
||||
*/
|
||||
int sch_add_demux_stream(Scheduler *sch, unsigned demux_idx);
|
||||
|
||||
/**
|
||||
* Add a decoder to the scheduler.
|
||||
*
|
||||
* @param func Function executed as the decoder task.
|
||||
* @param ctx Decoder state; will be passed to func and used for logging.
|
||||
* @param send_end_ts The decoder will return an end timestamp after flush packets
|
||||
* are delivered to it. See documentation for
|
||||
* sch_dec_receive() for more details.
|
||||
*
|
||||
* @retval ">=0" Index of the newly-created decoder.
|
||||
* @retval "<0" Error code.
|
||||
*/
|
||||
int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx, int send_end_ts);
|
||||
|
||||
/**
|
||||
* Add another output to decoder (e.g. for multiview video).
|
||||
*
|
||||
* @retval ">=0" Index of the newly-added decoder output.
|
||||
* @retval "<0" Error code.
|
||||
*/
|
||||
int sch_add_dec_output(Scheduler *sch, unsigned dec_idx);
|
||||
|
||||
/**
|
||||
* Add a filtergraph to the scheduler.
|
||||
*
|
||||
* @param nb_inputs Number of filtergraph inputs.
|
||||
* @param nb_outputs number of filtergraph outputs
|
||||
* @param func Function executed as the filtering task.
|
||||
* @param ctx Filter state; will be passed to func and used for logging.
|
||||
*
|
||||
* @retval ">=0" Index of the newly-created filtergraph.
|
||||
* @retval "<0" Error code.
|
||||
*/
|
||||
int sch_add_filtergraph(Scheduler *sch, unsigned nb_inputs, unsigned nb_outputs,
|
||||
SchThreadFunc func, void *ctx);
|
||||
|
||||
/**
|
||||
* Add a muxer to the scheduler.
|
||||
*
|
||||
* Note that muxer thread startup is more complicated than for other components,
|
||||
* because
|
||||
* - muxer streams fed by audio/video encoders become initialized dynamically at
|
||||
* runtime, after those encoders receive their first frame and initialize
|
||||
* themselves, followed by calling sch_mux_stream_ready()
|
||||
* - the header can be written after all the streams for a muxer are initialized
|
||||
* - we may need to write an SDP, which must happen
|
||||
* - AFTER all the headers are written
|
||||
* - BEFORE any packets are written by any muxer
|
||||
* - with all the muxers quiescent
|
||||
* To avoid complicated muxer-thread synchronization dances, we postpone
|
||||
* starting the muxer threads until after the SDP is written. The sequence of
|
||||
* events is then as follows:
|
||||
* - After sch_mux_stream_ready() is called for all the streams in a given muxer,
|
||||
* the header for that muxer is written (care is taken that headers for
|
||||
* different muxers are not written concurrently, since they write file
|
||||
* information to stderr). If SDP is not wanted, the muxer thread then starts
|
||||
* and muxing begins.
|
||||
* - When SDP _is_ wanted, no muxer threads start until the header for the last
|
||||
* muxer is written. After that, the SDP is written, after which all the muxer
|
||||
* threads are started at once.
|
||||
*
|
||||
* In order for the above to work, the scheduler needs to be able to invoke
|
||||
* just writing the header, which is the reason the init parameter exists.
|
||||
*
|
||||
* @param func Function executed as the muxing task.
|
||||
* @param init Callback that is called to initialize the muxer and write the
|
||||
* header. Called after sch_mux_stream_ready() is called for all the
|
||||
* streams in the muxer.
|
||||
* @param ctx Muxer state; will be passed to func/init and used for logging.
|
||||
* @param sdp_auto Determines automatic SDP writing - see sch_sdp_filename().
|
||||
* @param thread_queue_size number of packets that can be buffered before
|
||||
* sending to the muxer blocks
|
||||
*
|
||||
* @retval ">=0" Index of the newly-created muxer.
|
||||
* @retval "<0" Error code.
|
||||
*/
|
||||
int sch_add_mux(Scheduler *sch, SchThreadFunc func, int (*init)(void *),
|
||||
void *ctx, int sdp_auto, unsigned thread_queue_size);
|
||||
|
||||
/**
|
||||
* Default size of a packet thread queue. For muxing this can be overridden by
|
||||
* the thread_queue_size option as passed to a call to sch_add_mux().
|
||||
*/
|
||||
#define DEFAULT_PACKET_THREAD_QUEUE_SIZE 8
|
||||
|
||||
/**
|
||||
* Default size of a frame thread queue.
|
||||
*/
|
||||
#define DEFAULT_FRAME_THREAD_QUEUE_SIZE 8
|
||||
|
||||
/**
|
||||
* Add a muxed stream for a previously added muxer.
|
||||
*
|
||||
* @param mux_idx index previously returned by sch_add_mux()
|
||||
*
|
||||
* @retval ">=0" Index of the newly-created muxed stream.
|
||||
* @retval "<0" Error code.
|
||||
*/
|
||||
int sch_add_mux_stream(Scheduler *sch, unsigned mux_idx);
|
||||
|
||||
/**
|
||||
* Configure limits on packet buffering performed before the muxer task is
|
||||
* started.
|
||||
*
|
||||
* @param mux_idx index previously returned by sch_add_mux()
|
||||
* @param stream_idx_idx index previously returned by sch_add_mux_stream()
|
||||
* @param data_threshold Total size of the buffered packets' data after which
|
||||
* max_packets applies.
|
||||
* @param max_packets maximum Maximum number of buffered packets after
|
||||
* data_threshold is reached.
|
||||
*/
|
||||
void sch_mux_stream_buffering(Scheduler *sch, unsigned mux_idx, unsigned stream_idx,
|
||||
size_t data_threshold, int max_packets);
|
||||
|
||||
/**
|
||||
* Signal to the scheduler that the specified muxed stream is initialized and
|
||||
* ready. Muxing is started once all the streams are ready.
|
||||
*/
|
||||
int sch_mux_stream_ready(Scheduler *sch, unsigned mux_idx, unsigned stream_idx);
|
||||
|
||||
/**
|
||||
* Set the file path for the SDP.
|
||||
*
|
||||
* The SDP is written when either of the following is true:
|
||||
* - this function is called at least once
|
||||
* - sdp_auto=1 is passed to EVERY call of sch_add_mux()
|
||||
*/
|
||||
int sch_sdp_filename(Scheduler *sch, const char *sdp_filename);
|
||||
|
||||
/**
|
||||
* Add an encoder to the scheduler.
|
||||
*
|
||||
* @param func Function executed as the encoding task.
|
||||
* @param ctx Encoder state; will be passed to func and used for logging.
|
||||
* @param open_cb This callback, if specified, will be called when the first
|
||||
* frame is obtained for this encoder. For audio encoders with a
|
||||
* fixed frame size (which use a sync queue in the scheduler to
|
||||
* rechunk frames), it must return that frame size on success.
|
||||
* Otherwise (non-audio, variable frame size) it should return 0.
|
||||
*
|
||||
* @retval ">=0" Index of the newly-created encoder.
|
||||
* @retval "<0" Error code.
|
||||
*/
|
||||
int sch_add_enc(Scheduler *sch, SchThreadFunc func, void *ctx,
|
||||
int (*open_cb)(void *func_arg, const struct AVFrame *frame));
|
||||
|
||||
/**
|
||||
* Add an pre-encoding sync queue to the scheduler.
|
||||
*
|
||||
* @param buf_size_us Sync queue buffering size, passed to sq_alloc().
|
||||
* @param logctx Logging context for the sync queue. passed to sq_alloc().
|
||||
*
|
||||
* @retval ">=0" Index of the newly-created sync queue.
|
||||
* @retval "<0" Error code.
|
||||
*/
|
||||
int sch_add_sq_enc(Scheduler *sch, uint64_t buf_size_us, void *logctx);
|
||||
int sch_sq_add_enc(Scheduler *sch, unsigned sq_idx, unsigned enc_idx,
|
||||
int limiting, uint64_t max_frames);
|
||||
|
||||
int sch_connect(Scheduler *sch, SchedulerNode src, SchedulerNode dst);
|
||||
|
||||
enum DemuxSendFlags {
|
||||
/**
|
||||
* Treat the packet as an EOF for SCH_NODE_TYPE_MUX destinations
|
||||
* send normally to other types.
|
||||
*/
|
||||
DEMUX_SEND_STREAMCOPY_EOF = (1 << 0),
|
||||
};
|
||||
|
||||
/**
|
||||
* Called by demuxer tasks to communicate with their downstreams. The following
|
||||
* may be sent:
|
||||
* - a demuxed packet for the stream identified by pkt->stream_index;
|
||||
* - demuxer discontinuity/reset (e.g. after a seek) - this is signalled by an
|
||||
* empty packet with stream_index=-1.
|
||||
*
|
||||
* @param demux_idx demuxer index
|
||||
* @param pkt A demuxed packet to send.
|
||||
* When flushing (i.e. pkt->stream_index=-1 on entry to this
|
||||
* function), on successful return pkt->pts/pkt->time_base will be
|
||||
* set to the maximum end timestamp of any decoded audio stream, or
|
||||
* AV_NOPTS_VALUE if no decoded audio streams are present.
|
||||
*
|
||||
* @retval "non-negative value" success
|
||||
* @retval AVERROR_EOF all consumers for the stream are done
|
||||
* @retval AVERROR_EXIT all consumers are done, should terminate demuxing
|
||||
* @retval "anoter negative error code" other failure
|
||||
*/
|
||||
int sch_demux_send(Scheduler *sch, unsigned demux_idx, struct AVPacket *pkt,
|
||||
unsigned flags);
|
||||
|
||||
/**
|
||||
* Called by decoder tasks to receive a packet for decoding.
|
||||
*
|
||||
* @param dec_idx decoder index
|
||||
* @param pkt Input packet will be written here on success.
|
||||
*
|
||||
* An empty packet signals that the decoder should be flushed, but
|
||||
* more packets will follow (e.g. after seeking). When a decoder
|
||||
* created with send_end_ts=1 receives a flush packet, it must write
|
||||
* the end timestamp of the stream after flushing to
|
||||
* pkt->pts/time_base on the next call to this function (if any).
|
||||
*
|
||||
* @retval "non-negative value" success
|
||||
* @retval AVERROR_EOF no more packets will arrive, should terminate decoding
|
||||
* @retval "another negative error code" other failure
|
||||
*/
|
||||
int sch_dec_receive(Scheduler *sch, unsigned dec_idx, struct AVPacket *pkt);
|
||||
|
||||
/**
|
||||
* Called by decoder tasks to send a decoded frame downstream.
|
||||
*
|
||||
* @param dec_idx Decoder index previously returned by sch_add_dec().
|
||||
* @param frame Decoded frame; on success it is consumed and cleared by this
|
||||
* function
|
||||
*
|
||||
* @retval ">=0" success
|
||||
* @retval AVERROR_EOF all consumers are done, should terminate decoding
|
||||
* @retval "another negative error code" other failure
|
||||
*/
|
||||
int sch_dec_send(Scheduler *sch, unsigned dec_idx,
|
||||
unsigned out_idx, struct AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Called by filtergraph tasks to obtain frames for filtering. Will wait for a
|
||||
* frame to become available and return it in frame.
|
||||
*
|
||||
* Filtergraphs that contain lavfi sources and do not currently require new
|
||||
* input frames should call this function as a means of rate control - then
|
||||
* in_idx should be set equal to nb_inputs on entry to this function.
|
||||
*
|
||||
* @param fg_idx Filtergraph index previously returned by sch_add_filtergraph().
|
||||
* @param[in,out] in_idx On input contains the index of the input on which a frame
|
||||
* is most desired. May be set to nb_inputs to signal that
|
||||
* the filtergraph does not need more input currently.
|
||||
*
|
||||
* On success, will be replaced with the input index of
|
||||
* the actually returned frame or EOF timestamp.
|
||||
*
|
||||
* @retval ">=0" Frame data or EOF timestamp was delivered into frame, in_idx
|
||||
* contains the index of the input it belongs to.
|
||||
* @retval AVERROR(EAGAIN) No frame was returned, the filtergraph should
|
||||
* resume filtering. May only be returned when
|
||||
* in_idx=nb_inputs on entry to this function.
|
||||
* @retval AVERROR_EOF No more frames will arrive, should terminate filtering.
|
||||
*/
|
||||
int sch_filter_receive(Scheduler *sch, unsigned fg_idx,
|
||||
unsigned *in_idx, struct AVFrame *frame);
|
||||
/**
|
||||
* Called by filter tasks to signal that a filter input will no longer accept input.
|
||||
*
|
||||
* @param fg_idx Filtergraph index previously returned from sch_add_filtergraph().
|
||||
* @param in_idx Index of the input to finish.
|
||||
*/
|
||||
void sch_filter_receive_finish(Scheduler *sch, unsigned fg_idx, unsigned in_idx);
|
||||
|
||||
/**
|
||||
* Called by filtergraph tasks to send a filtered frame or EOF to consumers.
|
||||
*
|
||||
* @param fg_idx Filtergraph index previously returned by sch_add_filtergraph().
|
||||
* @param out_idx Index of the output which produced the frame.
|
||||
* @param frame The frame to send to consumers. When NULL, signals that no more
|
||||
* frames will be produced for the specified output. When non-NULL,
|
||||
* the frame is consumed and cleared by this function on success.
|
||||
*
|
||||
* @retval "non-negative value" success
|
||||
* @retval AVERROR_EOF all consumers are done
|
||||
* @retval "anoter negative error code" other failure
|
||||
*/
|
||||
int sch_filter_send(Scheduler *sch, unsigned fg_idx, unsigned out_idx,
|
||||
struct AVFrame *frame);
|
||||
|
||||
int sch_filter_command(Scheduler *sch, unsigned fg_idx, struct AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Called by encoder tasks to obtain frames for encoding. Will wait for a frame
|
||||
* to become available and return it in frame.
|
||||
*
|
||||
* @param enc_idx Encoder index previously returned by sch_add_enc().
|
||||
* @param frame Newly-received frame will be stored here on success. Must be
|
||||
* clean on entrance to this function.
|
||||
*
|
||||
* @retval 0 A frame was successfully delivered into frame.
|
||||
* @retval AVERROR_EOF No more frames will be delivered, the encoder should
|
||||
* flush everything and terminate.
|
||||
*
|
||||
*/
|
||||
int sch_enc_receive(Scheduler *sch, unsigned enc_idx, struct AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Called by encoder tasks to send encoded packets downstream.
|
||||
*
|
||||
* @param enc_idx Encoder index previously returned by sch_add_enc().
|
||||
* @param pkt An encoded packet; it will be consumed and cleared by this
|
||||
* function on success.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval "<0" Error code.
|
||||
*/
|
||||
int sch_enc_send (Scheduler *sch, unsigned enc_idx, struct AVPacket *pkt);
|
||||
|
||||
/**
|
||||
* Called by muxer tasks to obtain packets for muxing. Will wait for a packet
|
||||
* for any muxed stream to become available and return it in pkt.
|
||||
*
|
||||
* @param mux_idx Muxer index previously returned by sch_add_mux().
|
||||
* @param pkt Newly-received packet will be stored here on success. Must be
|
||||
* clean on entrance to this function.
|
||||
*
|
||||
* @retval 0 A packet was successfully delivered into pkt. Its stream_index
|
||||
* corresponds to a stream index previously returned from
|
||||
* sch_add_mux_stream().
|
||||
* @retval AVERROR_EOF When pkt->stream_index is non-negative, this signals that
|
||||
* no more packets will be delivered for this stream index.
|
||||
* Otherwise this indicates that no more packets will be
|
||||
* delivered for any stream and the muxer should therefore
|
||||
* flush everything and terminate.
|
||||
*/
|
||||
int sch_mux_receive(Scheduler *sch, unsigned mux_idx, struct AVPacket *pkt);
|
||||
|
||||
/**
|
||||
* Called by muxer tasks to signal that a stream will no longer accept input.
|
||||
*
|
||||
* @param stream_idx Stream index previously returned from sch_add_mux_stream().
|
||||
*/
|
||||
void sch_mux_receive_finish(Scheduler *sch, unsigned mux_idx, unsigned stream_idx);
|
||||
|
||||
int sch_mux_sub_heartbeat_add(Scheduler *sch, unsigned mux_idx, unsigned stream_idx,
|
||||
unsigned dec_idx);
|
||||
int sch_mux_sub_heartbeat(Scheduler *sch, unsigned mux_idx, unsigned stream_idx,
|
||||
const AVPacket *pkt);
|
||||
|
||||
#endif /* FFTOOLS_FFMPEG_SCHED_H */
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef FFTOOLS_FFMPEG_UTILS_H
|
||||
#define FFTOOLS_FFMPEG_UTILS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavutil/common.h"
|
||||
#include "libavutil/frame.h"
|
||||
#include "libavutil/rational.h"
|
||||
|
||||
#include "libavcodec/packet.h"
|
||||
|
||||
typedef struct Timestamp {
|
||||
int64_t ts;
|
||||
AVRational tb;
|
||||
} Timestamp;
|
||||
|
||||
/**
|
||||
* Merge two return codes - return one of the error codes if at least one of
|
||||
* them was negative, 0 otherwise.
|
||||
*/
|
||||
static inline int err_merge(int err0, int err1)
|
||||
{
|
||||
// prefer "real" errors over EOF
|
||||
if ((err0 >= 0 || err0 == AVERROR_EOF) && err1 < 0)
|
||||
return err1;
|
||||
return (err0 < 0) ? err0 : FFMIN(err1, 0);
|
||||
}
|
||||
|
||||
static inline void pkt_move(void *dst, void *src)
|
||||
{
|
||||
av_packet_move_ref(dst, src);
|
||||
}
|
||||
|
||||
static inline void frame_move(void *dst, void *src)
|
||||
{
|
||||
av_frame_move_ref(dst, src);
|
||||
}
|
||||
|
||||
#endif // FFTOOLS_FFMPEG_UTILS_H
|
||||
+90
-214
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "config_components.h"
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
@@ -32,11 +33,13 @@
|
||||
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/eval.h"
|
||||
#include "libavutil/mathematics.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/pixdesc.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavutil/fifo.h"
|
||||
#include "libavutil/parseutils.h"
|
||||
#include "libavutil/samplefmt.h"
|
||||
#include "libavutil/time.h"
|
||||
#include "libavutil/bprint.h"
|
||||
@@ -55,7 +58,6 @@
|
||||
#include <SDL_thread.h>
|
||||
|
||||
#include "cmdutils.h"
|
||||
#include "ffplay_renderer.h"
|
||||
#include "opt_common.h"
|
||||
|
||||
const char program_name[] = "ffplay";
|
||||
@@ -348,9 +350,6 @@ static char *afilters = NULL;
|
||||
static int autorotate = 1;
|
||||
static int find_stream_info = 1;
|
||||
static int filter_nbthreads = 0;
|
||||
static int enable_vulkan = 0;
|
||||
static char *vulkan_params = NULL;
|
||||
static const char *hwaccel = NULL;
|
||||
|
||||
/* current context */
|
||||
static int is_full_screen;
|
||||
@@ -363,8 +362,6 @@ static SDL_Renderer *renderer;
|
||||
static SDL_RendererInfo renderer_info = {0};
|
||||
static SDL_AudioDeviceID audio_dev;
|
||||
|
||||
static VkRenderer *vk_renderer;
|
||||
|
||||
static const struct TextureFormatEntry {
|
||||
enum AVPixelFormat format;
|
||||
int texture_fmt;
|
||||
@@ -397,10 +394,7 @@ static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
vfilters_list[nb_vfilters - 1] = av_strdup(arg);
|
||||
if (!vfilters_list[nb_vfilters - 1])
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
vfilters_list[nb_vfilters - 1] = arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -937,13 +931,6 @@ static int upload_texture(SDL_Texture **tex, AVFrame *frame)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum AVColorSpace sdl_supported_color_spaces[] = {
|
||||
AVCOL_SPC_BT709,
|
||||
AVCOL_SPC_BT470BG,
|
||||
AVCOL_SPC_SMPTE170M,
|
||||
AVCOL_SPC_UNSPECIFIED,
|
||||
};
|
||||
|
||||
static void set_sdl_yuv_conversion_mode(AVFrame *frame)
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2,0,8)
|
||||
@@ -967,11 +954,6 @@ static void video_image_display(VideoState *is)
|
||||
SDL_Rect rect;
|
||||
|
||||
vp = frame_queue_peek_last(&is->pictq);
|
||||
if (vk_renderer) {
|
||||
vk_renderer_display(vk_renderer, vp->frame);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is->subtitle_st) {
|
||||
if (frame_queue_nb_remaining(&is->subpq) > 0) {
|
||||
sp = frame_queue_peek(&is->subpq);
|
||||
@@ -1307,18 +1289,10 @@ static void do_exit(VideoState *is)
|
||||
}
|
||||
if (renderer)
|
||||
SDL_DestroyRenderer(renderer);
|
||||
if (vk_renderer)
|
||||
vk_renderer_destroy(vk_renderer);
|
||||
if (window)
|
||||
SDL_DestroyWindow(window);
|
||||
uninit_opts();
|
||||
for (int i = 0; i < nb_vfilters; i++)
|
||||
av_freep(&vfilters_list[i]);
|
||||
av_freep(&vfilters_list);
|
||||
av_freep(&video_codec_name);
|
||||
av_freep(&audio_codec_name);
|
||||
av_freep(&subtitle_codec_name);
|
||||
av_freep(&input_filename);
|
||||
avformat_network_deinit();
|
||||
if (show_status)
|
||||
printf("\n");
|
||||
@@ -1728,14 +1702,16 @@ display:
|
||||
|
||||
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
|
||||
av_bprintf(&buf,
|
||||
"%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB \r",
|
||||
"%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r",
|
||||
get_master_clock(is),
|
||||
(is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : " ")),
|
||||
av_diff,
|
||||
is->frame_drops_early + is->frame_drops_late,
|
||||
aqsize / 1024,
|
||||
vqsize / 1024,
|
||||
sqsize);
|
||||
sqsize,
|
||||
is->video_st ? is->viddec.avctx->pts_correction_num_faulty_dts : 0,
|
||||
is->video_st ? is->viddec.avctx->pts_correction_num_faulty_pts : 0);
|
||||
|
||||
if (show_status == 1 && AV_LOG_INFO > av_log_get_level())
|
||||
fprintf(stderr, "%s", buf.str);
|
||||
@@ -1869,10 +1845,6 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
|
||||
const AVDictionaryEntry *e = NULL;
|
||||
int nb_pix_fmts = 0;
|
||||
int i, j;
|
||||
AVBufferSrcParameters *par = av_buffersrc_parameters_alloc();
|
||||
|
||||
if (!par)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
for (i = 0; i < renderer_info.num_texture_formats; i++) {
|
||||
for (j = 0; j < FF_ARRAY_ELEMS(sdl_texture_format_map) - 1; j++) {
|
||||
@@ -1896,12 +1868,10 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
|
||||
graph->scale_sws_opts = av_strdup(sws_flags_str);
|
||||
|
||||
snprintf(buffersrc_args, sizeof(buffersrc_args),
|
||||
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d:"
|
||||
"colorspace=%d:range=%d",
|
||||
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
|
||||
frame->width, frame->height, frame->format,
|
||||
is->video_st->time_base.num, is->video_st->time_base.den,
|
||||
codecpar->sample_aspect_ratio.num, FFMAX(codecpar->sample_aspect_ratio.den, 1),
|
||||
frame->colorspace, frame->color_range);
|
||||
codecpar->sample_aspect_ratio.num, FFMAX(codecpar->sample_aspect_ratio.den, 1));
|
||||
if (fr.num && fr.den)
|
||||
av_strlcatf(buffersrc_args, sizeof(buffersrc_args), ":frame_rate=%d/%d", fr.num, fr.den);
|
||||
|
||||
@@ -1910,10 +1880,6 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
|
||||
"ffplay_buffer", buffersrc_args, NULL,
|
||||
graph)) < 0)
|
||||
goto fail;
|
||||
par->hw_frames_ctx = frame->hw_frames_ctx;
|
||||
ret = av_buffersrc_parameters_set(filt_src, par);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
ret = avfilter_graph_create_filter(&filt_out,
|
||||
avfilter_get_by_name("buffersink"),
|
||||
@@ -1923,9 +1889,6 @@ 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;
|
||||
if (!vk_renderer &&
|
||||
(ret = av_opt_set_int_list(filt_out, "color_spaces", sdl_supported_color_spaces, AVCOL_SPC_UNSPECIFIED, AV_OPT_SEARCH_CHILDREN)) < 0)
|
||||
goto fail;
|
||||
|
||||
last_filter = filt_out;
|
||||
|
||||
@@ -1954,30 +1917,25 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
|
||||
if (sd)
|
||||
displaymatrix = (int32_t *)sd->data;
|
||||
if (!displaymatrix) {
|
||||
const AVPacketSideData *psd = av_packet_side_data_get(is->video_st->codecpar->coded_side_data,
|
||||
is->video_st->codecpar->nb_coded_side_data,
|
||||
AV_PKT_DATA_DISPLAYMATRIX);
|
||||
if (psd)
|
||||
displaymatrix = (int32_t *)psd->data;
|
||||
const AVPacketSideData *sd = av_packet_side_data_get(is->video_st->codecpar->coded_side_data,
|
||||
is->video_st->codecpar->nb_coded_side_data,
|
||||
AV_PKT_DATA_DISPLAYMATRIX);
|
||||
if (sd)
|
||||
displaymatrix = (int32_t *)sd->data;
|
||||
}
|
||||
theta = get_rotation(displaymatrix);
|
||||
|
||||
if (fabs(theta - 90) < 1.0) {
|
||||
INSERT_FILT("transpose", displaymatrix[3] > 0 ? "cclock_flip" : "clock");
|
||||
INSERT_FILT("transpose", "clock");
|
||||
} else if (fabs(theta - 180) < 1.0) {
|
||||
if (displaymatrix[0] < 0)
|
||||
INSERT_FILT("hflip", NULL);
|
||||
if (displaymatrix[4] < 0)
|
||||
INSERT_FILT("vflip", NULL);
|
||||
INSERT_FILT("hflip", NULL);
|
||||
INSERT_FILT("vflip", NULL);
|
||||
} else if (fabs(theta - 270) < 1.0) {
|
||||
INSERT_FILT("transpose", displaymatrix[3] < 0 ? "clock_flip" : "cclock");
|
||||
INSERT_FILT("transpose", "cclock");
|
||||
} else if (fabs(theta) > 1.0) {
|
||||
char rotate_buf[64];
|
||||
snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
|
||||
INSERT_FILT("rotate", rotate_buf);
|
||||
} else {
|
||||
if (displaymatrix && displaymatrix[4] < 0)
|
||||
INSERT_FILT("vflip", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1988,7 +1946,6 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
|
||||
is->out_video_filter = filt_out;
|
||||
|
||||
fail:
|
||||
av_freep(&par);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2592,37 +2549,6 @@ static int audio_open(void *opaque, AVChannelLayout *wanted_channel_layout, int
|
||||
return spec.size;
|
||||
}
|
||||
|
||||
static int create_hwaccel(AVBufferRef **device_ctx)
|
||||
{
|
||||
enum AVHWDeviceType type;
|
||||
int ret;
|
||||
AVBufferRef *vk_dev;
|
||||
|
||||
*device_ctx = NULL;
|
||||
|
||||
if (!hwaccel)
|
||||
return 0;
|
||||
|
||||
type = av_hwdevice_find_type_by_name(hwaccel);
|
||||
if (type == AV_HWDEVICE_TYPE_NONE)
|
||||
return AVERROR(ENOTSUP);
|
||||
|
||||
ret = vk_renderer_get_hw_dev(vk_renderer, &vk_dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = av_hwdevice_ctx_create_derived(device_ctx, type, vk_dev, 0);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
if (ret != AVERROR(ENOSYS))
|
||||
return ret;
|
||||
|
||||
av_log(NULL, AV_LOG_WARNING, "Derive %s from vulkan not supported.\n", hwaccel);
|
||||
ret = av_hwdevice_ctx_create(device_ctx, type, NULL, NULL, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* open a given stream. Return 0 if OK */
|
||||
static int stream_component_open(VideoState *is, int stream_index)
|
||||
{
|
||||
@@ -2631,6 +2557,7 @@ static int stream_component_open(VideoState *is, int stream_index)
|
||||
const AVCodec *codec;
|
||||
const char *forced_codec_name = NULL;
|
||||
AVDictionary *opts = NULL;
|
||||
const AVDictionaryEntry *t = NULL;
|
||||
int sample_rate;
|
||||
AVChannelLayout ch_layout = { 0 };
|
||||
int ret = 0;
|
||||
@@ -2678,7 +2605,7 @@ static int stream_component_open(VideoState *is, int stream_index)
|
||||
avctx->flags2 |= AV_CODEC_FLAG2_FAST;
|
||||
|
||||
ret = filter_codec_opts(codec_opts, avctx->codec_id, ic,
|
||||
ic->streams[stream_index], codec, &opts, NULL);
|
||||
ic->streams[stream_index], codec, &opts);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
@@ -2689,18 +2616,14 @@ static int stream_component_open(VideoState *is, int stream_index)
|
||||
|
||||
av_dict_set(&opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY);
|
||||
|
||||
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
ret = create_hwaccel(&avctx->hw_device_ctx);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
ret = check_avoptions(opts);
|
||||
if (ret < 0)
|
||||
if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
|
||||
ret = AVERROR_OPTION_NOT_FOUND;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
is->eof = 0;
|
||||
ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
|
||||
@@ -2863,11 +2786,12 @@ static int read_thread(void *arg)
|
||||
}
|
||||
if (scan_all_pmts_set)
|
||||
av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
|
||||
remove_avoptions(&format_opts, codec_opts);
|
||||
|
||||
ret = check_avoptions(format_opts);
|
||||
if (ret < 0)
|
||||
if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
|
||||
ret = AVERROR_OPTION_NOT_FOUND;
|
||||
goto fail;
|
||||
}
|
||||
is->ic = ic;
|
||||
|
||||
if (genpts)
|
||||
@@ -3526,8 +3450,6 @@ static void event_loop(VideoState *cur_stream)
|
||||
SDL_DestroyTexture(cur_stream->vis_texture);
|
||||
cur_stream->vis_texture = NULL;
|
||||
}
|
||||
if (vk_renderer)
|
||||
vk_renderer_resize(vk_renderer, screen_width, screen_height);
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
cur_stream->force_refresh = 1;
|
||||
}
|
||||
@@ -3545,7 +3467,7 @@ static void event_loop(VideoState *cur_stream)
|
||||
static int opt_width(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
double num;
|
||||
int ret = parse_number(opt, arg, OPT_TYPE_INT64, 1, INT_MAX, &num);
|
||||
int ret = parse_number(opt, arg, OPT_INT64, 1, INT_MAX, &num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -3556,7 +3478,7 @@ static int opt_width(void *optctx, const char *opt, const char *arg)
|
||||
static int opt_height(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
double num;
|
||||
int ret = parse_number(opt, arg, OPT_TYPE_INT64, 1, INT_MAX, &num);
|
||||
int ret = parse_number(opt, arg, OPT_INT64, 1, INT_MAX, &num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -3597,7 +3519,7 @@ static int opt_show_mode(void *optctx, const char *opt, const char *arg)
|
||||
|
||||
if (show_mode == SHOW_MODE_NONE) {
|
||||
double num;
|
||||
int ret = parse_number(opt, arg, OPT_TYPE_INT, 0, SHOW_MODE_NB-1, &num);
|
||||
int ret = parse_number(opt, arg, OPT_INT, 0, SHOW_MODE_NB-1, &num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
show_mode = num;
|
||||
@@ -3615,9 +3537,7 @@ static int opt_input_file(void *optctx, const char *filename)
|
||||
}
|
||||
if (!strcmp(filename, "-"))
|
||||
filename = "fd:";
|
||||
input_filename = av_strdup(filename);
|
||||
if (!input_filename)
|
||||
return AVERROR(ENOMEM);
|
||||
input_filename = filename;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3625,7 +3545,6 @@ static int opt_input_file(void *optctx, const char *filename)
|
||||
static int opt_codec(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
const char *spec = strchr(opt, ':');
|
||||
const char **name;
|
||||
if (!spec) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"No media specifier was specified in '%s' in option '%s'\n",
|
||||
@@ -3633,75 +3552,68 @@ static int opt_codec(void *optctx, const char *opt, const char *arg)
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
spec++;
|
||||
|
||||
switch (spec[0]) {
|
||||
case 'a' : name = &audio_codec_name; break;
|
||||
case 's' : name = &subtitle_codec_name; break;
|
||||
case 'v' : name = &video_codec_name; break;
|
||||
case 'a' : audio_codec_name = arg; break;
|
||||
case 's' : subtitle_codec_name = arg; break;
|
||||
case 'v' : video_codec_name = arg; break;
|
||||
default:
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Invalid media specifier '%s' in option '%s'\n", spec, opt);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
av_freep(name);
|
||||
*name = av_strdup(arg);
|
||||
return *name ? 0 : AVERROR(ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy;
|
||||
|
||||
static const OptionDef options[] = {
|
||||
CMDUTILS_COMMON_OPTIONS
|
||||
{ "x", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_width }, "force displayed width", "width" },
|
||||
{ "y", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_height }, "force displayed height", "height" },
|
||||
{ "fs", OPT_TYPE_BOOL, 0, { &is_full_screen }, "force full screen" },
|
||||
{ "an", OPT_TYPE_BOOL, 0, { &audio_disable }, "disable audio" },
|
||||
{ "vn", OPT_TYPE_BOOL, 0, { &video_disable }, "disable video" },
|
||||
{ "sn", OPT_TYPE_BOOL, 0, { &subtitle_disable }, "disable subtitling" },
|
||||
{ "ast", OPT_TYPE_STRING, OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_specifier" },
|
||||
{ "vst", OPT_TYPE_STRING, OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_specifier" },
|
||||
{ "sst", OPT_TYPE_STRING, OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_specifier" },
|
||||
{ "ss", OPT_TYPE_TIME, 0, { &start_time }, "seek to a given position in seconds", "pos" },
|
||||
{ "t", OPT_TYPE_TIME, 0, { &duration }, "play \"duration\" seconds of audio/video", "duration" },
|
||||
{ "bytes", OPT_TYPE_INT, 0, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },
|
||||
{ "seek_interval", OPT_TYPE_FLOAT, 0, { &seek_interval }, "set seek interval for left/right keys, in seconds", "seconds" },
|
||||
{ "nodisp", OPT_TYPE_BOOL, 0, { &display_disable }, "disable graphical display" },
|
||||
{ "noborder", OPT_TYPE_BOOL, 0, { &borderless }, "borderless window" },
|
||||
{ "alwaysontop", OPT_TYPE_BOOL, 0, { &alwaysontop }, "window always on top" },
|
||||
{ "volume", OPT_TYPE_INT, 0, { &startup_volume}, "set startup volume 0=min 100=max", "volume" },
|
||||
{ "f", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_format }, "force format", "fmt" },
|
||||
{ "stats", OPT_TYPE_BOOL, OPT_EXPERT, { &show_status }, "show status", "" },
|
||||
{ "fast", OPT_TYPE_BOOL, OPT_EXPERT, { &fast }, "non spec compliant optimizations", "" },
|
||||
{ "genpts", OPT_TYPE_BOOL, OPT_EXPERT, { &genpts }, "generate pts", "" },
|
||||
{ "drp", OPT_TYPE_INT, OPT_EXPERT, { &decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""},
|
||||
{ "lowres", OPT_TYPE_INT, OPT_EXPERT, { &lowres }, "", "" },
|
||||
{ "sync", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" },
|
||||
{ "autoexit", OPT_TYPE_BOOL, OPT_EXPERT, { &autoexit }, "exit at the end", "" },
|
||||
{ "exitonkeydown", OPT_TYPE_BOOL, OPT_EXPERT, { &exit_on_keydown }, "exit on key down", "" },
|
||||
{ "exitonmousedown", OPT_TYPE_BOOL, OPT_EXPERT, { &exit_on_mousedown }, "exit on mouse down", "" },
|
||||
{ "loop", OPT_TYPE_INT, OPT_EXPERT, { &loop }, "set number of times the playback shall be looped", "loop count" },
|
||||
{ "framedrop", OPT_TYPE_BOOL, OPT_EXPERT, { &framedrop }, "drop frames when cpu is too slow", "" },
|
||||
{ "infbuf", OPT_TYPE_BOOL, OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" },
|
||||
{ "window_title", OPT_TYPE_STRING, 0, { &window_title }, "set window title", "window title" },
|
||||
{ "left", OPT_TYPE_INT, OPT_EXPERT, { &screen_left }, "set the x position for the left of the window", "x pos" },
|
||||
{ "top", OPT_TYPE_INT, OPT_EXPERT, { &screen_top }, "set the y position for the top of the window", "y pos" },
|
||||
{ "vf", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_add_vfilter }, "set video filters", "filter_graph" },
|
||||
{ "af", OPT_TYPE_STRING, 0, { &afilters }, "set audio filters", "filter_graph" },
|
||||
{ "rdftspeed", OPT_TYPE_INT, OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
|
||||
{ "showmode", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
|
||||
{ "i", OPT_TYPE_BOOL, 0, { &dummy}, "read specified file", "input_file"},
|
||||
{ "codec", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_codec}, "force decoder", "decoder_name" },
|
||||
{ "acodec", OPT_TYPE_STRING, OPT_EXPERT, { &audio_codec_name }, "force audio decoder", "decoder_name" },
|
||||
{ "scodec", OPT_TYPE_STRING, OPT_EXPERT, { &subtitle_codec_name }, "force subtitle decoder", "decoder_name" },
|
||||
{ "vcodec", OPT_TYPE_STRING, OPT_EXPERT, { &video_codec_name }, "force video decoder", "decoder_name" },
|
||||
{ "autorotate", OPT_TYPE_BOOL, 0, { &autorotate }, "automatically rotate video", "" },
|
||||
{ "find_stream_info", OPT_TYPE_BOOL, OPT_INPUT | OPT_EXPERT, { &find_stream_info },
|
||||
{ "x", HAS_ARG, { .func_arg = opt_width }, "force displayed width", "width" },
|
||||
{ "y", HAS_ARG, { .func_arg = opt_height }, "force displayed height", "height" },
|
||||
{ "fs", OPT_BOOL, { &is_full_screen }, "force full screen" },
|
||||
{ "an", OPT_BOOL, { &audio_disable }, "disable audio" },
|
||||
{ "vn", OPT_BOOL, { &video_disable }, "disable video" },
|
||||
{ "sn", OPT_BOOL, { &subtitle_disable }, "disable subtitling" },
|
||||
{ "ast", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_specifier" },
|
||||
{ "vst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_specifier" },
|
||||
{ "sst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_specifier" },
|
||||
{ "ss", HAS_ARG | OPT_TIME, { &start_time }, "seek to a given position in seconds", "pos" },
|
||||
{ "t", HAS_ARG | OPT_TIME, { &duration }, "play \"duration\" seconds of audio/video", "duration" },
|
||||
{ "bytes", OPT_INT | HAS_ARG, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },
|
||||
{ "seek_interval", OPT_FLOAT | HAS_ARG, { &seek_interval }, "set seek interval for left/right keys, in seconds", "seconds" },
|
||||
{ "nodisp", OPT_BOOL, { &display_disable }, "disable graphical display" },
|
||||
{ "noborder", OPT_BOOL, { &borderless }, "borderless window" },
|
||||
{ "alwaysontop", OPT_BOOL, { &alwaysontop }, "window always on top" },
|
||||
{ "volume", OPT_INT | HAS_ARG, { &startup_volume}, "set startup volume 0=min 100=max", "volume" },
|
||||
{ "f", HAS_ARG, { .func_arg = opt_format }, "force format", "fmt" },
|
||||
{ "stats", OPT_BOOL | OPT_EXPERT, { &show_status }, "show status", "" },
|
||||
{ "fast", OPT_BOOL | OPT_EXPERT, { &fast }, "non spec compliant optimizations", "" },
|
||||
{ "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 }, "", "" },
|
||||
{ "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", "" },
|
||||
{ "exitonmousedown", OPT_BOOL | OPT_EXPERT, { &exit_on_mousedown }, "exit on mouse down", "" },
|
||||
{ "loop", OPT_INT | HAS_ARG | OPT_EXPERT, { &loop }, "set number of times the playback shall be looped", "loop count" },
|
||||
{ "framedrop", OPT_BOOL | OPT_EXPERT, { &framedrop }, "drop frames when cpu is too slow", "" },
|
||||
{ "infbuf", OPT_BOOL | OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" },
|
||||
{ "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" },
|
||||
{ "left", OPT_INT | HAS_ARG | OPT_EXPERT, { &screen_left }, "set the x position for the left of the window", "x pos" },
|
||||
{ "top", OPT_INT | HAS_ARG | OPT_EXPERT, { &screen_top }, "set the y position for the top of the window", "y pos" },
|
||||
{ "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" },
|
||||
{ "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
|
||||
{ "showmode", HAS_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
|
||||
{ "i", OPT_BOOL, { &dummy}, "read specified file", "input_file"},
|
||||
{ "codec", HAS_ARG, { .func_arg = opt_codec}, "force decoder", "decoder_name" },
|
||||
{ "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", "" },
|
||||
{ "find_stream_info", OPT_BOOL | OPT_INPUT | OPT_EXPERT, { &find_stream_info },
|
||||
"read and decode the streams to fill missing information with heuristics" },
|
||||
{ "filter_threads", OPT_TYPE_INT, OPT_EXPERT, { &filter_nbthreads }, "number of filter threads per graph" },
|
||||
{ "enable_vulkan", OPT_TYPE_BOOL, 0, { &enable_vulkan }, "enable vulkan renderer" },
|
||||
{ "vulkan_params", OPT_TYPE_STRING, OPT_EXPERT, { &vulkan_params }, "vulkan configuration using a list of key=value pairs separated by ':'" },
|
||||
{ "hwaccel", OPT_TYPE_STRING, OPT_EXPERT, { &hwaccel }, "use HW accelerated decoding" },
|
||||
{ "filter_threads", HAS_ARG | OPT_INT | OPT_EXPERT, { &filter_nbthreads }, "number of filter threads per graph" },
|
||||
{ NULL, },
|
||||
};
|
||||
|
||||
@@ -3716,8 +3628,8 @@ void show_help_default(const char *opt, const char *arg)
|
||||
{
|
||||
av_log_set_callback(log_callback_help);
|
||||
show_usage();
|
||||
show_help_options(options, "Main options:", 0, OPT_EXPERT);
|
||||
show_help_options(options, "Advanced options:", OPT_EXPERT, 0);
|
||||
show_help_options(options, "Main options:", 0, OPT_EXPERT, 0);
|
||||
show_help_options(options, "Advanced options:", OPT_EXPERT, 0, 0);
|
||||
printf("\n");
|
||||
show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM);
|
||||
show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
|
||||
@@ -3816,45 +3728,9 @@ int main(int argc, char **argv)
|
||||
#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
|
||||
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
|
||||
#endif
|
||||
if (hwaccel && !enable_vulkan) {
|
||||
av_log(NULL, AV_LOG_INFO, "Enable vulkan renderer to support hwaccel %s\n", hwaccel);
|
||||
enable_vulkan = 1;
|
||||
}
|
||||
if (enable_vulkan) {
|
||||
vk_renderer = vk_get_renderer();
|
||||
if (vk_renderer) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 6)
|
||||
flags |= SDL_WINDOW_VULKAN;
|
||||
#endif
|
||||
} else {
|
||||
av_log(NULL, AV_LOG_WARNING, "Doesn't support vulkan renderer, fallback to SDL renderer\n");
|
||||
enable_vulkan = 0;
|
||||
}
|
||||
}
|
||||
window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags);
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
|
||||
if (!window) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Failed to create window: %s", SDL_GetError());
|
||||
do_exit(NULL);
|
||||
}
|
||||
|
||||
if (vk_renderer) {
|
||||
AVDictionary *dict = NULL;
|
||||
|
||||
if (vulkan_params) {
|
||||
int ret = av_dict_parse_string(&dict, vulkan_params, "=", ":", 0);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Failed to parse, %s\n", vulkan_params);
|
||||
do_exit(NULL);
|
||||
}
|
||||
}
|
||||
ret = vk_renderer_create(vk_renderer, window, dict);
|
||||
av_dict_free(&dict);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Failed to create vulkan renderer, %s\n", av_err2str(ret));
|
||||
do_exit(NULL);
|
||||
}
|
||||
} else {
|
||||
if (window) {
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
if (!renderer) {
|
||||
av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError());
|
||||
@@ -3864,10 +3740,10 @@ int main(int argc, char **argv)
|
||||
if (!SDL_GetRendererInfo(renderer, &renderer_info))
|
||||
av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", renderer_info.name);
|
||||
}
|
||||
if (!renderer || !renderer_info.num_texture_formats) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError());
|
||||
do_exit(NULL);
|
||||
}
|
||||
}
|
||||
if (!window || !renderer || !renderer_info.num_texture_formats) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError());
|
||||
do_exit(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,836 +0,0 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General 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 VK_NO_PROTOTYPES
|
||||
#define VK_ENABLE_BETA_EXTENSIONS
|
||||
|
||||
#include "config.h"
|
||||
#include "ffplay_renderer.h"
|
||||
|
||||
#if (SDL_VERSION_ATLEAST(2, 0, 6) && CONFIG_LIBPLACEBO)
|
||||
/* Get PL_API_VER */
|
||||
#include <libplacebo/config.h>
|
||||
#define HAVE_VULKAN_RENDERER (PL_API_VER >= 278)
|
||||
#else
|
||||
#define HAVE_VULKAN_RENDERER 0
|
||||
#endif
|
||||
|
||||
#if HAVE_VULKAN_RENDERER
|
||||
|
||||
#if defined(_WIN32) && !defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||
#define VK_USE_PLATFORM_WIN32_KHR
|
||||
#endif
|
||||
|
||||
#include <libplacebo/vulkan.h>
|
||||
#include <libplacebo/utils/frame_queue.h>
|
||||
#include <libplacebo/utils/libav.h>
|
||||
#include <SDL_vulkan.h>
|
||||
|
||||
#include "libavutil/bprint.h"
|
||||
#include "libavutil/mem.h"
|
||||
|
||||
#endif
|
||||
|
||||
struct VkRenderer {
|
||||
const AVClass *class;
|
||||
|
||||
int (*create)(VkRenderer *renderer, SDL_Window *window, AVDictionary *dict);
|
||||
|
||||
int (*get_hw_dev)(VkRenderer *renderer, AVBufferRef **dev);
|
||||
|
||||
int (*display)(VkRenderer *renderer, AVFrame *frame);
|
||||
|
||||
int (*resize)(VkRenderer *renderer, int width, int height);
|
||||
|
||||
void (*destroy)(VkRenderer *renderer);
|
||||
};
|
||||
|
||||
#if HAVE_VULKAN_RENDERER
|
||||
|
||||
typedef struct RendererContext {
|
||||
VkRenderer api;
|
||||
|
||||
// Can be NULL when vulkan instance is created by avutil
|
||||
pl_vk_inst placebo_instance;
|
||||
pl_vulkan placebo_vulkan;
|
||||
pl_swapchain swapchain;
|
||||
VkSurfaceKHR vk_surface;
|
||||
pl_renderer renderer;
|
||||
pl_tex tex[4];
|
||||
|
||||
pl_log vk_log;
|
||||
|
||||
AVBufferRef *hw_device_ref;
|
||||
AVBufferRef *hw_frame_ref;
|
||||
enum AVPixelFormat *transfer_formats;
|
||||
AVHWFramesConstraints *constraints;
|
||||
|
||||
PFN_vkGetInstanceProcAddr get_proc_addr;
|
||||
// This field is a copy from pl_vk_inst->instance or hw_device_ref instance.
|
||||
VkInstance inst;
|
||||
|
||||
AVFrame *vk_frame;
|
||||
} RendererContext;
|
||||
|
||||
static void vk_log_cb(void *log_priv, enum pl_log_level level,
|
||||
const char *msg)
|
||||
{
|
||||
static const int level_map[] = {
|
||||
AV_LOG_QUIET,
|
||||
AV_LOG_FATAL,
|
||||
AV_LOG_ERROR,
|
||||
AV_LOG_WARNING,
|
||||
AV_LOG_INFO,
|
||||
AV_LOG_DEBUG,
|
||||
AV_LOG_TRACE,
|
||||
};
|
||||
|
||||
if (level > 0 && level < FF_ARRAY_ELEMS(level_map))
|
||||
av_log(log_priv, level_map[level], "%s\n", msg);
|
||||
}
|
||||
|
||||
// Should keep sync with optional_device_exts inside hwcontext_vulkan.c
|
||||
static const char *optional_device_exts[] = {
|
||||
/* Misc or required by other extensions */
|
||||
VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,
|
||||
VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,
|
||||
VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
|
||||
VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME,
|
||||
VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME,
|
||||
VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME,
|
||||
VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME,
|
||||
|
||||
/* Imports/exports */
|
||||
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
|
||||
VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME,
|
||||
VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME,
|
||||
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
|
||||
VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME,
|
||||
#ifdef _WIN32
|
||||
VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
|
||||
VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME,
|
||||
#endif
|
||||
|
||||
/* Video encoding/decoding */
|
||||
VK_KHR_VIDEO_QUEUE_EXTENSION_NAME,
|
||||
VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME,
|
||||
VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME,
|
||||
VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME,
|
||||
"VK_MESA_video_decode_av1",
|
||||
};
|
||||
|
||||
static inline int enable_debug(const AVDictionary *opt)
|
||||
{
|
||||
AVDictionaryEntry *entry = av_dict_get(opt, "debug", NULL, 0);
|
||||
int debug = entry && strtol(entry->value, NULL, 10);
|
||||
return debug;
|
||||
}
|
||||
|
||||
static void hwctx_lock_queue(void *priv, uint32_t qf, uint32_t qidx)
|
||||
{
|
||||
AVHWDeviceContext *avhwctx = priv;
|
||||
const AVVulkanDeviceContext *hwctx = avhwctx->hwctx;
|
||||
hwctx->lock_queue(avhwctx, qf, qidx);
|
||||
}
|
||||
|
||||
static void hwctx_unlock_queue(void *priv, uint32_t qf, uint32_t qidx)
|
||||
{
|
||||
AVHWDeviceContext *avhwctx = priv;
|
||||
const AVVulkanDeviceContext *hwctx = avhwctx->hwctx;
|
||||
hwctx->unlock_queue(avhwctx, qf, qidx);
|
||||
}
|
||||
|
||||
static int add_instance_extension(const char **ext, unsigned num_ext,
|
||||
const AVDictionary *opt,
|
||||
AVDictionary **dict)
|
||||
{
|
||||
const char *inst_ext_key = "instance_extensions";
|
||||
AVDictionaryEntry *entry;
|
||||
AVBPrint buf;
|
||||
char *ext_list = NULL;
|
||||
int ret;
|
||||
|
||||
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
|
||||
for (int i = 0; i < num_ext; i++) {
|
||||
if (i)
|
||||
av_bprintf(&buf, "+%s", ext[i]);
|
||||
else
|
||||
av_bprintf(&buf, "%s", ext[i]);
|
||||
}
|
||||
|
||||
entry = av_dict_get(opt, inst_ext_key, NULL, 0);
|
||||
if (entry && entry->value && entry->value[0]) {
|
||||
if (num_ext)
|
||||
av_bprintf(&buf, "+");
|
||||
av_bprintf(&buf, "%s", entry->value);
|
||||
}
|
||||
|
||||
ret = av_bprint_finalize(&buf, &ext_list);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return av_dict_set(dict, inst_ext_key, ext_list, AV_DICT_DONT_STRDUP_VAL);
|
||||
}
|
||||
|
||||
static int add_device_extension(const AVDictionary *opt,
|
||||
AVDictionary **dict)
|
||||
{
|
||||
const char *dev_ext_key = "device_extensions";
|
||||
AVDictionaryEntry *entry;
|
||||
AVBPrint buf;
|
||||
char *ext_list = NULL;
|
||||
int ret;
|
||||
|
||||
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
|
||||
av_bprintf(&buf, "%s", VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
for (int i = 0; i < pl_vulkan_num_recommended_extensions; i++)
|
||||
av_bprintf(&buf, "+%s", pl_vulkan_recommended_extensions[i]);
|
||||
|
||||
entry = av_dict_get(opt, dev_ext_key, NULL, 0);
|
||||
if (entry && entry->value && entry->value[0])
|
||||
av_bprintf(&buf, "+%s", entry->value);
|
||||
|
||||
ret = av_bprint_finalize(&buf, &ext_list);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return av_dict_set(dict, dev_ext_key, ext_list, AV_DICT_DONT_STRDUP_VAL);
|
||||
}
|
||||
|
||||
static const char *select_device(const AVDictionary *opt)
|
||||
{
|
||||
const AVDictionaryEntry *entry;
|
||||
|
||||
entry = av_dict_get(opt, "device", NULL, 0);
|
||||
if (entry)
|
||||
return entry->value;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int create_vk_by_hwcontext(VkRenderer *renderer,
|
||||
const char **ext, unsigned num_ext,
|
||||
const AVDictionary *opt)
|
||||
{
|
||||
RendererContext *ctx = (RendererContext *) renderer;
|
||||
AVHWDeviceContext *dev;
|
||||
AVVulkanDeviceContext *hwctx;
|
||||
AVDictionary *dict = NULL;
|
||||
int ret;
|
||||
|
||||
ret = add_instance_extension(ext, num_ext, opt, &dict);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = add_device_extension(opt, &dict);
|
||||
if (ret) {
|
||||
av_dict_free(&dict);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = av_hwdevice_ctx_create(&ctx->hw_device_ref, AV_HWDEVICE_TYPE_VULKAN,
|
||||
select_device(opt), dict, 0);
|
||||
av_dict_free(&dict);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev = (AVHWDeviceContext *) ctx->hw_device_ref->data;
|
||||
hwctx = dev->hwctx;
|
||||
|
||||
// There is no way to pass SDL GetInstanceProcAddr to hwdevice.
|
||||
// Check the result and return error if they don't match.
|
||||
if (hwctx->get_proc_addr != SDL_Vulkan_GetVkGetInstanceProcAddr()) {
|
||||
av_log(renderer, AV_LOG_ERROR,
|
||||
"hwdevice and SDL use different get_proc_addr. "
|
||||
"Try -vulkan_params create_by_placebo=1\n");
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
ctx->get_proc_addr = hwctx->get_proc_addr;
|
||||
ctx->inst = hwctx->inst;
|
||||
ctx->placebo_vulkan = pl_vulkan_import(ctx->vk_log,
|
||||
pl_vulkan_import_params(
|
||||
.instance = hwctx->inst,
|
||||
.get_proc_addr = hwctx->get_proc_addr,
|
||||
.phys_device = hwctx->phys_dev,
|
||||
.device = hwctx->act_dev,
|
||||
.extensions = hwctx->enabled_dev_extensions,
|
||||
.num_extensions = hwctx->nb_enabled_dev_extensions,
|
||||
.features = &hwctx->device_features,
|
||||
.lock_queue = hwctx_lock_queue,
|
||||
.unlock_queue = hwctx_unlock_queue,
|
||||
.queue_ctx = dev,
|
||||
.queue_graphics = {
|
||||
.index = hwctx->queue_family_index,
|
||||
.count = hwctx->nb_graphics_queues,
|
||||
},
|
||||
.queue_compute = {
|
||||
.index = hwctx->queue_family_comp_index,
|
||||
.count = hwctx->nb_comp_queues,
|
||||
},
|
||||
.queue_transfer = {
|
||||
.index = hwctx->queue_family_tx_index,
|
||||
.count = hwctx->nb_tx_queues,
|
||||
},
|
||||
));
|
||||
if (!ctx->placebo_vulkan)
|
||||
return AVERROR_EXTERNAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void placebo_lock_queue(struct AVHWDeviceContext *dev_ctx,
|
||||
uint32_t queue_family, uint32_t index)
|
||||
{
|
||||
RendererContext *ctx = dev_ctx->user_opaque;
|
||||
pl_vulkan vk = ctx->placebo_vulkan;
|
||||
vk->lock_queue(vk, queue_family, index);
|
||||
}
|
||||
|
||||
static void placebo_unlock_queue(struct AVHWDeviceContext *dev_ctx,
|
||||
uint32_t queue_family,
|
||||
uint32_t index)
|
||||
{
|
||||
RendererContext *ctx = dev_ctx->user_opaque;
|
||||
pl_vulkan vk = ctx->placebo_vulkan;
|
||||
vk->unlock_queue(vk, queue_family, index);
|
||||
}
|
||||
|
||||
static int get_decode_queue(VkRenderer *renderer, int *index, int *count)
|
||||
{
|
||||
RendererContext *ctx = (RendererContext *) renderer;
|
||||
VkQueueFamilyProperties *queue_family_prop = NULL;
|
||||
uint32_t num_queue_family_prop = 0;
|
||||
PFN_vkGetPhysicalDeviceQueueFamilyProperties get_queue_family_prop;
|
||||
PFN_vkGetInstanceProcAddr get_proc_addr = ctx->get_proc_addr;
|
||||
|
||||
*index = -1;
|
||||
*count = 0;
|
||||
get_queue_family_prop = (PFN_vkGetPhysicalDeviceQueueFamilyProperties)
|
||||
get_proc_addr(ctx->placebo_instance->instance,
|
||||
"vkGetPhysicalDeviceQueueFamilyProperties");
|
||||
get_queue_family_prop(ctx->placebo_vulkan->phys_device,
|
||||
&num_queue_family_prop, NULL);
|
||||
if (!num_queue_family_prop)
|
||||
return AVERROR_EXTERNAL;
|
||||
|
||||
queue_family_prop = av_calloc(num_queue_family_prop,
|
||||
sizeof(*queue_family_prop));
|
||||
if (!queue_family_prop)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
get_queue_family_prop(ctx->placebo_vulkan->phys_device,
|
||||
&num_queue_family_prop,
|
||||
queue_family_prop);
|
||||
|
||||
for (int i = 0; i < num_queue_family_prop; i++) {
|
||||
if (queue_family_prop[i].queueFlags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
|
||||
*index = i;
|
||||
*count = queue_family_prop[i].queueCount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
av_free(queue_family_prop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_vk_by_placebo(VkRenderer *renderer,
|
||||
const char **ext, unsigned num_ext,
|
||||
const AVDictionary *opt)
|
||||
{
|
||||
RendererContext *ctx = (RendererContext *) renderer;
|
||||
AVHWDeviceContext *device_ctx;
|
||||
AVVulkanDeviceContext *vk_dev_ctx;
|
||||
int decode_index;
|
||||
int decode_count;
|
||||
int ret;
|
||||
|
||||
ctx->get_proc_addr = SDL_Vulkan_GetVkGetInstanceProcAddr();
|
||||
|
||||
ctx->placebo_instance = pl_vk_inst_create(ctx->vk_log, pl_vk_inst_params(
|
||||
.get_proc_addr = ctx->get_proc_addr,
|
||||
.debug = enable_debug(opt),
|
||||
.extensions = ext,
|
||||
.num_extensions = num_ext
|
||||
));
|
||||
if (!ctx->placebo_instance) {
|
||||
return AVERROR_EXTERNAL;
|
||||
}
|
||||
ctx->inst = ctx->placebo_instance->instance;
|
||||
|
||||
ctx->placebo_vulkan = pl_vulkan_create(ctx->vk_log, pl_vulkan_params(
|
||||
.instance = ctx->placebo_instance->instance,
|
||||
.get_proc_addr = ctx->placebo_instance->get_proc_addr,
|
||||
.surface = ctx->vk_surface,
|
||||
.allow_software = false,
|
||||
.opt_extensions = optional_device_exts,
|
||||
.num_opt_extensions = FF_ARRAY_ELEMS(optional_device_exts),
|
||||
.extra_queues = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
|
||||
.device_name = select_device(opt),
|
||||
));
|
||||
if (!ctx->placebo_vulkan)
|
||||
return AVERROR_EXTERNAL;
|
||||
ctx->hw_device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VULKAN);
|
||||
if (!ctx->hw_device_ref) {
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
device_ctx = (AVHWDeviceContext *) ctx->hw_device_ref->data;
|
||||
device_ctx->user_opaque = ctx;
|
||||
|
||||
vk_dev_ctx = device_ctx->hwctx;
|
||||
vk_dev_ctx->lock_queue = placebo_lock_queue,
|
||||
vk_dev_ctx->unlock_queue = placebo_unlock_queue;
|
||||
|
||||
vk_dev_ctx->get_proc_addr = ctx->placebo_instance->get_proc_addr;
|
||||
|
||||
vk_dev_ctx->inst = ctx->placebo_instance->instance;
|
||||
vk_dev_ctx->phys_dev = ctx->placebo_vulkan->phys_device;
|
||||
vk_dev_ctx->act_dev = ctx->placebo_vulkan->device;
|
||||
|
||||
vk_dev_ctx->device_features = *ctx->placebo_vulkan->features;
|
||||
|
||||
vk_dev_ctx->enabled_inst_extensions = ctx->placebo_instance->extensions;
|
||||
vk_dev_ctx->nb_enabled_inst_extensions = ctx->placebo_instance->num_extensions;
|
||||
|
||||
vk_dev_ctx->enabled_dev_extensions = ctx->placebo_vulkan->extensions;
|
||||
vk_dev_ctx->nb_enabled_dev_extensions = ctx->placebo_vulkan->num_extensions;
|
||||
|
||||
vk_dev_ctx->queue_family_index = ctx->placebo_vulkan->queue_graphics.index;
|
||||
vk_dev_ctx->nb_graphics_queues = ctx->placebo_vulkan->queue_graphics.count;
|
||||
|
||||
vk_dev_ctx->queue_family_tx_index = ctx->placebo_vulkan->queue_transfer.index;
|
||||
vk_dev_ctx->nb_tx_queues = ctx->placebo_vulkan->queue_transfer.count;
|
||||
|
||||
vk_dev_ctx->queue_family_comp_index = ctx->placebo_vulkan->queue_compute.index;
|
||||
vk_dev_ctx->nb_comp_queues = ctx->placebo_vulkan->queue_compute.count;
|
||||
|
||||
ret = get_decode_queue(renderer, &decode_index, &decode_count);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
vk_dev_ctx->queue_family_decode_index = decode_index;
|
||||
vk_dev_ctx->nb_decode_queues = decode_count;
|
||||
|
||||
ret = av_hwdevice_ctx_init(ctx->hw_device_ref);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create(VkRenderer *renderer, SDL_Window *window, AVDictionary *opt)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned num_ext = 0;
|
||||
const char **ext = NULL;
|
||||
int w, h;
|
||||
struct pl_log_params vk_log_params = {
|
||||
.log_cb = vk_log_cb,
|
||||
.log_level = PL_LOG_DEBUG,
|
||||
.log_priv = renderer,
|
||||
};
|
||||
RendererContext *ctx = (RendererContext *) renderer;
|
||||
AVDictionaryEntry *entry;
|
||||
|
||||
ctx->vk_log = pl_log_create(PL_API_VER, &vk_log_params);
|
||||
|
||||
if (!SDL_Vulkan_GetInstanceExtensions(window, &num_ext, NULL)) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Failed to get vulkan extensions: %s\n",
|
||||
SDL_GetError());
|
||||
return AVERROR_EXTERNAL;
|
||||
}
|
||||
|
||||
ext = av_calloc(num_ext, sizeof(*ext));
|
||||
if (!ext) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
SDL_Vulkan_GetInstanceExtensions(window, &num_ext, ext);
|
||||
|
||||
entry = av_dict_get(opt, "create_by_placebo", NULL, 0);
|
||||
if (entry && strtol(entry->value, NULL, 10))
|
||||
ret = create_vk_by_placebo(renderer, ext, num_ext, opt);
|
||||
else
|
||||
ret = create_vk_by_hwcontext(renderer, ext, num_ext, opt);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (!SDL_Vulkan_CreateSurface(window, ctx->inst, &ctx->vk_surface)) {
|
||||
ret = AVERROR_EXTERNAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx->swapchain = pl_vulkan_create_swapchain(
|
||||
ctx->placebo_vulkan,
|
||||
pl_vulkan_swapchain_params(
|
||||
.surface = ctx->vk_surface,
|
||||
.present_mode = VK_PRESENT_MODE_FIFO_KHR));
|
||||
if (!ctx->swapchain) {
|
||||
ret = AVERROR_EXTERNAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
SDL_Vulkan_GetDrawableSize(window, &w, &h);
|
||||
pl_swapchain_resize(ctx->swapchain, &w, &h);
|
||||
|
||||
ctx->renderer = pl_renderer_create(ctx->vk_log, ctx->placebo_vulkan->gpu);
|
||||
if (!ctx->renderer) {
|
||||
ret = AVERROR_EXTERNAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx->vk_frame = av_frame_alloc();
|
||||
if (!ctx->vk_frame) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
av_free(ext);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_hw_dev(VkRenderer *renderer, AVBufferRef **dev)
|
||||
{
|
||||
RendererContext *ctx = (RendererContext *) renderer;
|
||||
|
||||
*dev = ctx->hw_device_ref;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_hw_frame(VkRenderer *renderer, AVFrame *frame)
|
||||
{
|
||||
RendererContext *ctx = (RendererContext *) renderer;
|
||||
AVHWFramesContext *src_hw_frame = (AVHWFramesContext *)
|
||||
frame->hw_frames_ctx->data;
|
||||
AVHWFramesContext *hw_frame;
|
||||
AVVulkanFramesContext *vk_frame_ctx;
|
||||
int ret;
|
||||
|
||||
if (ctx->hw_frame_ref) {
|
||||
hw_frame = (AVHWFramesContext *) ctx->hw_frame_ref->data;
|
||||
|
||||
if (hw_frame->width == frame->width &&
|
||||
hw_frame->height == frame->height &&
|
||||
hw_frame->sw_format == src_hw_frame->sw_format)
|
||||
return 0;
|
||||
|
||||
av_buffer_unref(&ctx->hw_frame_ref);
|
||||
}
|
||||
|
||||
if (!ctx->constraints) {
|
||||
ctx->constraints = av_hwdevice_get_hwframe_constraints(
|
||||
ctx->hw_device_ref, NULL);
|
||||
if (!ctx->constraints)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
// Check constraints and skip create hwframe. Don't take it as error since
|
||||
// we can fallback to memory copy from GPU to CPU.
|
||||
if ((ctx->constraints->max_width &&
|
||||
ctx->constraints->max_width < frame->width) ||
|
||||
(ctx->constraints->max_height &&
|
||||
ctx->constraints->max_height < frame->height) ||
|
||||
(ctx->constraints->min_width &&
|
||||
ctx->constraints->min_width > frame->width) ||
|
||||
(ctx->constraints->min_height &&
|
||||
ctx->constraints->min_height > frame->height))
|
||||
return 0;
|
||||
|
||||
if (ctx->constraints->valid_sw_formats) {
|
||||
enum AVPixelFormat *sw_formats = ctx->constraints->valid_sw_formats;
|
||||
while (*sw_formats != AV_PIX_FMT_NONE) {
|
||||
if (*sw_formats == src_hw_frame->sw_format)
|
||||
break;
|
||||
sw_formats++;
|
||||
}
|
||||
if (*sw_formats == AV_PIX_FMT_NONE)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->hw_frame_ref = av_hwframe_ctx_alloc(ctx->hw_device_ref);
|
||||
if (!ctx->hw_frame_ref)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
hw_frame = (AVHWFramesContext *) ctx->hw_frame_ref->data;
|
||||
hw_frame->format = AV_PIX_FMT_VULKAN;
|
||||
hw_frame->sw_format = src_hw_frame->sw_format;
|
||||
hw_frame->width = frame->width;
|
||||
hw_frame->height = frame->height;
|
||||
|
||||
if (frame->format == AV_PIX_FMT_CUDA) {
|
||||
vk_frame_ctx = hw_frame->hwctx;
|
||||
vk_frame_ctx->flags = AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE;
|
||||
}
|
||||
|
||||
ret = av_hwframe_ctx_init(ctx->hw_frame_ref);
|
||||
if (ret < 0) {
|
||||
av_log(renderer, AV_LOG_ERROR, "Create hwframe context failed, %s\n",
|
||||
av_err2str(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
av_hwframe_transfer_get_formats(ctx->hw_frame_ref,
|
||||
AV_HWFRAME_TRANSFER_DIRECTION_TO,
|
||||
&ctx->transfer_formats, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int check_hw_transfer(RendererContext *ctx, AVFrame *frame)
|
||||
{
|
||||
if (!ctx->hw_frame_ref || !ctx->transfer_formats)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; ctx->transfer_formats[i] != AV_PIX_FMT_NONE; i++)
|
||||
if (ctx->transfer_formats[i] == frame->format)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int move_to_output_frame(RendererContext *ctx, AVFrame *frame)
|
||||
{
|
||||
int ret = av_frame_copy_props(ctx->vk_frame, frame);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
av_frame_unref(frame);
|
||||
av_frame_move_ref(frame, ctx->vk_frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int map_frame(VkRenderer *renderer, AVFrame *frame, int use_hw_frame)
|
||||
{
|
||||
RendererContext *ctx = (RendererContext *) renderer;
|
||||
int ret;
|
||||
|
||||
if (use_hw_frame && !ctx->hw_frame_ref)
|
||||
return AVERROR(ENOSYS);
|
||||
|
||||
// Try map data first
|
||||
av_frame_unref(ctx->vk_frame);
|
||||
if (use_hw_frame) {
|
||||
ctx->vk_frame->hw_frames_ctx = av_buffer_ref(ctx->hw_frame_ref);
|
||||
ctx->vk_frame->format = AV_PIX_FMT_VULKAN;
|
||||
}
|
||||
ret = av_hwframe_map(ctx->vk_frame, frame, 0);
|
||||
if (!ret)
|
||||
return move_to_output_frame(ctx, frame);
|
||||
|
||||
if (ret != AVERROR(ENOSYS))
|
||||
av_log(NULL, AV_LOG_FATAL, "Map frame failed: %s\n", av_err2str(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int transfer_frame(VkRenderer *renderer, AVFrame *frame, int use_hw_frame)
|
||||
{
|
||||
RendererContext *ctx = (RendererContext *) renderer;
|
||||
int ret;
|
||||
|
||||
if (use_hw_frame && !check_hw_transfer(ctx, frame))
|
||||
return AVERROR(ENOSYS);
|
||||
|
||||
av_frame_unref(ctx->vk_frame);
|
||||
if (use_hw_frame)
|
||||
av_hwframe_get_buffer(ctx->hw_frame_ref, ctx->vk_frame, 0);
|
||||
ret = av_hwframe_transfer_data(ctx->vk_frame, frame, 1);
|
||||
if (!ret)
|
||||
return move_to_output_frame(ctx, frame);
|
||||
|
||||
if (ret != AVERROR(ENOSYS))
|
||||
av_log(NULL, AV_LOG_FATAL, "Transfer frame failed: %s\n",
|
||||
av_err2str(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int convert_frame(VkRenderer *renderer, AVFrame *frame)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!frame->hw_frames_ctx)
|
||||
return 0;
|
||||
|
||||
if (frame->format == AV_PIX_FMT_VULKAN)
|
||||
return 0;
|
||||
|
||||
ret = create_hw_frame(renderer, frame);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
for (int use_hw = 1; use_hw >=0; use_hw--) {
|
||||
ret = map_frame(renderer, frame, use_hw);
|
||||
if (!ret)
|
||||
return 0;
|
||||
if (ret != AVERROR(ENOSYS))
|
||||
return ret;
|
||||
|
||||
ret = transfer_frame(renderer, frame, use_hw);
|
||||
if (!ret)
|
||||
return 0;
|
||||
if (ret != AVERROR(ENOSYS))
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int display(VkRenderer *renderer, AVFrame *frame)
|
||||
{
|
||||
struct pl_swapchain_frame swap_frame = {0};
|
||||
struct pl_frame pl_frame = {0};
|
||||
struct pl_frame target = {0};
|
||||
RendererContext *ctx = (RendererContext *) renderer;
|
||||
int ret = 0;
|
||||
|
||||
ret = convert_frame(renderer, frame);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!pl_map_avframe_ex(ctx->placebo_vulkan->gpu, &pl_frame, pl_avframe_params(
|
||||
.frame = frame,
|
||||
.tex = ctx->tex))) {
|
||||
av_log(NULL, AV_LOG_ERROR, "pl_map_avframe_ex failed\n");
|
||||
return AVERROR_EXTERNAL;
|
||||
}
|
||||
|
||||
if (!pl_swapchain_start_frame(ctx->swapchain, &swap_frame)) {
|
||||
av_log(NULL, AV_LOG_ERROR, "start frame failed\n");
|
||||
ret = AVERROR_EXTERNAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pl_frame_from_swapchain(&target, &swap_frame);
|
||||
if (!pl_render_image(ctx->renderer, &pl_frame, &target,
|
||||
&pl_render_default_params)) {
|
||||
av_log(NULL, AV_LOG_ERROR, "pl_render_image failed\n");
|
||||
ret = AVERROR_EXTERNAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!pl_swapchain_submit_frame(ctx->swapchain)) {
|
||||
av_log(NULL, AV_LOG_ERROR, "pl_swapchain_submit_frame failed\n");
|
||||
ret = AVERROR_EXTERNAL;
|
||||
goto out;
|
||||
}
|
||||
pl_swapchain_swap_buffers(ctx->swapchain);
|
||||
|
||||
out:
|
||||
pl_unmap_avframe(ctx->placebo_vulkan->gpu, &pl_frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int resize(VkRenderer *renderer, int width, int height)
|
||||
{
|
||||
RendererContext *ctx = (RendererContext *) renderer;
|
||||
|
||||
if (!pl_swapchain_resize(ctx->swapchain, &width, &height))
|
||||
return AVERROR_EXTERNAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destroy(VkRenderer *renderer)
|
||||
{
|
||||
RendererContext *ctx = (RendererContext *) renderer;
|
||||
PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
|
||||
|
||||
av_frame_free(&ctx->vk_frame);
|
||||
av_freep(&ctx->transfer_formats);
|
||||
av_hwframe_constraints_free(&ctx->constraints);
|
||||
av_buffer_unref(&ctx->hw_frame_ref);
|
||||
|
||||
if (ctx->placebo_vulkan) {
|
||||
for (int i = 0; i < FF_ARRAY_ELEMS(ctx->tex); i++)
|
||||
pl_tex_destroy(ctx->placebo_vulkan->gpu, &ctx->tex[i]);
|
||||
pl_renderer_destroy(&ctx->renderer);
|
||||
pl_swapchain_destroy(&ctx->swapchain);
|
||||
pl_vulkan_destroy(&ctx->placebo_vulkan);
|
||||
}
|
||||
|
||||
if (ctx->vk_surface) {
|
||||
vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)
|
||||
ctx->get_proc_addr(ctx->inst, "vkDestroySurfaceKHR");
|
||||
vkDestroySurfaceKHR(ctx->inst, ctx->vk_surface, NULL);
|
||||
ctx->vk_surface = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
av_buffer_unref(&ctx->hw_device_ref);
|
||||
pl_vk_inst_destroy(&ctx->placebo_instance);
|
||||
|
||||
pl_log_destroy(&ctx->vk_log);
|
||||
}
|
||||
|
||||
static const AVClass vulkan_renderer_class = {
|
||||
.class_name = "Vulkan Renderer",
|
||||
.item_name = av_default_item_name,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
VkRenderer *vk_get_renderer(void)
|
||||
{
|
||||
RendererContext *ctx = av_mallocz(sizeof(*ctx));
|
||||
VkRenderer *renderer;
|
||||
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
renderer = &ctx->api;
|
||||
renderer->class = &vulkan_renderer_class;
|
||||
renderer->get_hw_dev = get_hw_dev;
|
||||
renderer->create = create;
|
||||
renderer->display = display;
|
||||
renderer->resize = resize;
|
||||
renderer->destroy = destroy;
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
VkRenderer *vk_get_renderer(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int vk_renderer_create(VkRenderer *renderer, SDL_Window *window,
|
||||
AVDictionary *opt)
|
||||
{
|
||||
return renderer->create(renderer, window, opt);
|
||||
}
|
||||
|
||||
int vk_renderer_get_hw_dev(VkRenderer *renderer, AVBufferRef **dev)
|
||||
{
|
||||
return renderer->get_hw_dev(renderer, dev);
|
||||
}
|
||||
|
||||
int vk_renderer_display(VkRenderer *renderer, AVFrame *frame)
|
||||
{
|
||||
return renderer->display(renderer, frame);
|
||||
}
|
||||
|
||||
int vk_renderer_resize(VkRenderer *renderer, int width, int height)
|
||||
{
|
||||
return renderer->resize(renderer, width, height);
|
||||
}
|
||||
|
||||
void vk_renderer_destroy(VkRenderer *renderer)
|
||||
{
|
||||
renderer->destroy(renderer);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef FFTOOLS_FFPLAY_RENDERER_H
|
||||
#define FFTOOLS_FFPLAY_RENDERER_H
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "libavutil/frame.h"
|
||||
|
||||
typedef struct VkRenderer VkRenderer;
|
||||
|
||||
VkRenderer *vk_get_renderer(void);
|
||||
|
||||
int vk_renderer_create(VkRenderer *renderer, SDL_Window *window,
|
||||
AVDictionary *opt);
|
||||
|
||||
int vk_renderer_get_hw_dev(VkRenderer *renderer, AVBufferRef **dev);
|
||||
|
||||
int vk_renderer_display(VkRenderer *renderer, AVFrame *frame);
|
||||
|
||||
int vk_renderer_resize(VkRenderer *renderer, int width, int height);
|
||||
|
||||
void vk_renderer_destroy(VkRenderer *renderer);
|
||||
|
||||
#endif /* FFTOOLS_FFPLAY_RENDERER_H */
|
||||
+139
-634
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,6 @@
|
||||
* CRT, and FILE* handles can't be shared across them.) */
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/wchar_filename.h"
|
||||
|
||||
static inline FILE *fopen_utf8(const char *path_utf8, const char *mode)
|
||||
|
||||
+49
-67
@@ -262,36 +262,22 @@ int show_buildconf(void *optctx, const char *opt, const char *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PRINT_CODEC_SUPPORTED(codec, config, type, name, elem, fmt, ...) \
|
||||
do { \
|
||||
int num = 0; \
|
||||
const type *elem = NULL; \
|
||||
avcodec_get_supported_config(NULL, codec, config, 0, \
|
||||
(const void **) &elem, &num); \
|
||||
if (elem) { \
|
||||
printf(" Supported " name ":"); \
|
||||
for (int i = 0; i < num; i++) { \
|
||||
printf(" " fmt, __VA_ARGS__); \
|
||||
elem++; \
|
||||
} \
|
||||
printf("\n"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static const char *get_channel_layout_desc(const AVChannelLayout *layout, AVBPrint *bp)
|
||||
{
|
||||
int ret;
|
||||
av_bprint_clear(bp);
|
||||
ret = av_channel_layout_describe_bprint(layout, bp);
|
||||
if (!av_bprint_is_complete(bp) || ret < 0)
|
||||
return "unknown/invalid";
|
||||
return bp->str;
|
||||
}
|
||||
#define PRINT_CODEC_SUPPORTED(codec, field, type, list_name, term, get_name) \
|
||||
if (codec->field) { \
|
||||
const type *p = codec->field; \
|
||||
\
|
||||
printf(" Supported " list_name ":"); \
|
||||
while (*p != term) { \
|
||||
get_name(*p); \
|
||||
printf(" %s", name); \
|
||||
p++; \
|
||||
} \
|
||||
printf("\n"); \
|
||||
} \
|
||||
|
||||
static void print_codec(const AVCodec *c)
|
||||
{
|
||||
int encoder = av_codec_is_encoder(c);
|
||||
AVBPrint desc;
|
||||
|
||||
printf("%s %s [%s]:\n", encoder ? "Encoder" : "Decoder", c->name,
|
||||
c->long_name ? c->long_name : "");
|
||||
@@ -357,20 +343,35 @@ static void print_codec(const AVCodec *c)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
PRINT_CODEC_SUPPORTED(c, AV_CODEC_CONFIG_FRAME_RATE, AVRational, "framerates",
|
||||
fps, "%d/%d", fps->num, fps->den);
|
||||
PRINT_CODEC_SUPPORTED(c, AV_CODEC_CONFIG_PIX_FORMAT, enum AVPixelFormat,
|
||||
"pixel formats", fmt, "%s", av_get_pix_fmt_name(*fmt));
|
||||
PRINT_CODEC_SUPPORTED(c, AV_CODEC_CONFIG_SAMPLE_RATE, int, "sample rates",
|
||||
rate, "%d", *rate);
|
||||
PRINT_CODEC_SUPPORTED(c, AV_CODEC_CONFIG_SAMPLE_FORMAT, enum AVSampleFormat,
|
||||
"sample formats", fmt, "%s", av_get_sample_fmt_name(*fmt));
|
||||
if (c->supported_framerates) {
|
||||
const AVRational *fps = c->supported_framerates;
|
||||
|
||||
av_bprint_init(&desc, 0, AV_BPRINT_SIZE_AUTOMATIC);
|
||||
PRINT_CODEC_SUPPORTED(c, AV_CODEC_CONFIG_CHANNEL_LAYOUT, AVChannelLayout,
|
||||
"channel layouts", layout, "%s",
|
||||
get_channel_layout_desc(layout, &desc));
|
||||
av_bprint_finalize(&desc, NULL);
|
||||
printf(" Supported framerates:");
|
||||
while (fps->num) {
|
||||
printf(" %d/%d", fps->num, fps->den);
|
||||
fps++;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
PRINT_CODEC_SUPPORTED(c, pix_fmts, enum AVPixelFormat, "pixel formats",
|
||||
AV_PIX_FMT_NONE, GET_PIX_FMT_NAME);
|
||||
PRINT_CODEC_SUPPORTED(c, supported_samplerates, int, "sample rates", 0,
|
||||
GET_SAMPLE_RATE_NAME);
|
||||
PRINT_CODEC_SUPPORTED(c, sample_fmts, enum AVSampleFormat, "sample formats",
|
||||
AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME);
|
||||
|
||||
if (c->ch_layouts) {
|
||||
const AVChannelLayout *p = c->ch_layouts;
|
||||
|
||||
printf(" Supported channel layouts:");
|
||||
while (p->nb_channels) {
|
||||
char name[128];
|
||||
av_channel_layout_describe(p, name, sizeof(name));
|
||||
printf(" %s", name);
|
||||
p++;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (c->priv_class) {
|
||||
show_help_children(c->priv_class,
|
||||
@@ -565,15 +566,8 @@ static void show_help_bsf(const char *name)
|
||||
}
|
||||
|
||||
printf("Bit stream filter %s\n", bsf->name);
|
||||
if (bsf->codec_ids) {
|
||||
const enum AVCodecID *id = bsf->codec_ids;
|
||||
printf(" Supported codecs:");
|
||||
while (*id != AV_CODEC_ID_NONE) {
|
||||
printf(" %s", avcodec_descriptor_get(*id)->name);
|
||||
id++;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
PRINT_CODEC_SUPPORTED(bsf, codec_ids, enum AVCodecID, "codecs",
|
||||
AV_CODEC_ID_NONE, GET_CODEC_NAME);
|
||||
if (bsf->priv_class)
|
||||
show_help_children(bsf->priv_class, AV_OPT_FLAG_BSF_PARAM);
|
||||
}
|
||||
@@ -860,22 +854,15 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg,
|
||||
const AVOutputFormat *ofmt = NULL;
|
||||
const char *last_name;
|
||||
int is_dev;
|
||||
const char *is_device_placeholder = device_only ? "" : ".";
|
||||
|
||||
printf("%s:\n"
|
||||
" D.%s = Demuxing supported\n"
|
||||
" .E%s = Muxing supported\n"
|
||||
"%s"
|
||||
" ---\n",
|
||||
device_only ? "Devices" : "Formats",
|
||||
is_device_placeholder, is_device_placeholder,
|
||||
device_only ? "": " ..d = Is a device\n");
|
||||
|
||||
printf("%s\n"
|
||||
" D. = Demuxing supported\n"
|
||||
" .E = Muxing supported\n"
|
||||
" --\n", device_only ? "Devices:" : "File formats:");
|
||||
last_name = "000";
|
||||
for (;;) {
|
||||
int decode = 0;
|
||||
int encode = 0;
|
||||
int device = 0;
|
||||
const char *name = NULL;
|
||||
const char *long_name = NULL;
|
||||
|
||||
@@ -890,7 +877,6 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg,
|
||||
name = ofmt->name;
|
||||
long_name = ofmt->long_name;
|
||||
encode = 1;
|
||||
device = is_dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -905,24 +891,20 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg,
|
||||
name = ifmt->name;
|
||||
long_name = ifmt->long_name;
|
||||
encode = 0;
|
||||
device = is_dev;
|
||||
}
|
||||
if (name && strcmp(ifmt->name, name) == 0) {
|
||||
if (name && strcmp(ifmt->name, name) == 0)
|
||||
decode = 1;
|
||||
device = is_dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!name)
|
||||
break;
|
||||
last_name = name;
|
||||
|
||||
printf(" %c%c%s %-15s %s\n",
|
||||
printf(" %c%c %-15s %s\n",
|
||||
decode ? 'D' : ' ',
|
||||
encode ? 'E' : ' ',
|
||||
device_only ? "" : (device ? "d" : " "),
|
||||
name,
|
||||
long_name ? long_name : " ");
|
||||
long_name ? long_name:" ");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+31
-31
@@ -41,9 +41,9 @@ int show_sources(void *optctx, const char *opt, const char *arg);
|
||||
|
||||
#if CONFIG_AVDEVICE
|
||||
#define CMDUTILS_COMMON_OPTIONS_AVDEVICE \
|
||||
{ "sources" , OPT_TYPE_FUNC, OPT_EXIT | OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = show_sources }, \
|
||||
{ "sources" , OPT_EXIT | HAS_ARG, { .func_arg = show_sources }, \
|
||||
"list sources of the input device", "device" }, \
|
||||
{ "sinks" , OPT_TYPE_FUNC, OPT_EXIT | OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = show_sinks }, \
|
||||
{ "sinks" , OPT_EXIT | HAS_ARG, { .func_arg = show_sinks }, \
|
||||
"list sinks of the output device", "device" }, \
|
||||
|
||||
#else
|
||||
@@ -197,35 +197,35 @@ int opt_cpuflags(void *optctx, const char *opt, const char *arg);
|
||||
int opt_cpucount(void *optctx, const char *opt, const char *arg);
|
||||
|
||||
#define CMDUTILS_COMMON_OPTIONS \
|
||||
{ "L", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_license }, "show license" }, \
|
||||
{ "h", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \
|
||||
{ "?", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_help }, "show help", "topic" }, \
|
||||
{ "help", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_help }, "show help", "topic" }, \
|
||||
{ "-help", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_help }, "show help", "topic" }, \
|
||||
{ "version", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_version }, "show version" }, \
|
||||
{ "buildconf", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_buildconf }, "show build configuration" }, \
|
||||
{ "formats", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_formats }, "show available formats" }, \
|
||||
{ "muxers", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_muxers }, "show available muxers" }, \
|
||||
{ "demuxers", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_demuxers }, "show available demuxers" }, \
|
||||
{ "devices", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_devices }, "show available devices" }, \
|
||||
{ "codecs", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_codecs }, "show available codecs" }, \
|
||||
{ "decoders", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_decoders }, "show available decoders" }, \
|
||||
{ "encoders", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_encoders }, "show available encoders" }, \
|
||||
{ "bsfs", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_bsfs }, "show available bit stream filters" }, \
|
||||
{ "protocols", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_protocols }, "show available protocols" }, \
|
||||
{ "filters", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_filters }, "show available filters" }, \
|
||||
{ "pix_fmts", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_pix_fmts }, "show available pixel formats" }, \
|
||||
{ "layouts", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_layouts }, "show standard channel layouts" }, \
|
||||
{ "sample_fmts", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_sample_fmts }, "show available audio sample formats" }, \
|
||||
{ "dispositions", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_dispositions}, "show available stream dispositions" }, \
|
||||
{ "colors", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_colors }, "show available color names" }, \
|
||||
{ "loglevel", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \
|
||||
{ "v", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \
|
||||
{ "report", OPT_TYPE_FUNC, OPT_EXPERT, { .func_arg = opt_report }, "generate a report" }, \
|
||||
{ "max_alloc", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_max_alloc }, "set maximum size of a single allocated block", "bytes" }, \
|
||||
{ "cpuflags", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" }, \
|
||||
{ "cpucount", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_cpucount }, "force specific cpu count", "count" }, \
|
||||
{ "hide_banner", OPT_TYPE_BOOL, OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, \
|
||||
{ "L", OPT_EXIT, { .func_arg = show_license }, "show license" }, \
|
||||
{ "h", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \
|
||||
{ "?", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \
|
||||
{ "help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \
|
||||
{ "-help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \
|
||||
{ "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" }, \
|
||||
{ "muxers", OPT_EXIT, { .func_arg = show_muxers }, "show available muxers" }, \
|
||||
{ "demuxers", OPT_EXIT, { .func_arg = show_demuxers }, "show available demuxers" }, \
|
||||
{ "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" }, \
|
||||
{ "bsfs", OPT_EXIT, { .func_arg = show_bsfs }, "show available bit stream filters" }, \
|
||||
{ "protocols", OPT_EXIT, { .func_arg = show_protocols }, "show available protocols" }, \
|
||||
{ "filters", OPT_EXIT, { .func_arg = show_filters }, "show available filters" }, \
|
||||
{ "pix_fmts", OPT_EXIT, { .func_arg = show_pix_fmts }, "show available pixel formats" }, \
|
||||
{ "layouts", OPT_EXIT, { .func_arg = show_layouts }, "show standard channel layouts" }, \
|
||||
{ "sample_fmts", OPT_EXIT, { .func_arg = show_sample_fmts }, "show available audio sample formats" }, \
|
||||
{ "dispositions", OPT_EXIT, { .func_arg = show_dispositions}, "show available stream dispositions" }, \
|
||||
{ "colors", OPT_EXIT, { .func_arg = show_colors }, "show available color names" }, \
|
||||
{ "loglevel", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \
|
||||
{ "v", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \
|
||||
{ "report", 0, { .func_arg = opt_report }, "generate a report" }, \
|
||||
{ "max_alloc", HAS_ARG, { .func_arg = opt_max_alloc }, "set maximum size of a single allocated block", "bytes" }, \
|
||||
{ "cpuflags", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" }, \
|
||||
{ "cpucount", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpucount }, "force specific cpu count", "count" }, \
|
||||
{ "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, \
|
||||
CMDUTILS_COMMON_OPTIONS_AVDEVICE \
|
||||
|
||||
#endif /* FFTOOLS_OPT_COMMON_H */
|
||||
|
||||
@@ -319,7 +319,7 @@ static int overflow_heartbeat(SyncQueue *sq, int stream_idx)
|
||||
/* signal a fake timestamp for all streams that prevent tail_ts from being output */
|
||||
tail_ts++;
|
||||
for (unsigned int i = 0; i < sq->nb_streams; i++) {
|
||||
const SyncQueueStream *st1 = &sq->streams[i];
|
||||
SyncQueueStream *st1 = &sq->streams[i];
|
||||
int64_t ts;
|
||||
|
||||
if (st == st1 || st1->finished ||
|
||||
@@ -524,8 +524,8 @@ fail:
|
||||
static int receive_for_stream(SyncQueue *sq, unsigned int stream_idx,
|
||||
SyncQueueFrame frame)
|
||||
{
|
||||
const SyncQueueStream *st_head = sq->head_stream >= 0 ?
|
||||
&sq->streams[sq->head_stream] : NULL;
|
||||
SyncQueueStream *st_head = sq->head_stream >= 0 ?
|
||||
&sq->streams[sq->head_stream] : NULL;
|
||||
SyncQueueStream *st;
|
||||
|
||||
av_assert0(stream_idx < sq->nb_streams);
|
||||
|
||||
+5
-14
@@ -164,12 +164,7 @@ static int receive_locked(ThreadQueue *tq, int *stream_idx,
|
||||
FifoElem elem;
|
||||
unsigned int nb_finished = 0;
|
||||
|
||||
while (av_fifo_read(tq->fifo, &elem, 1) >= 0) {
|
||||
if (tq->finished[elem.stream_idx] & FINISHED_RECV) {
|
||||
objpool_release(tq->obj_pool, &elem.obj);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (av_fifo_read(tq->fifo, &elem, 1) >= 0) {
|
||||
tq->obj_move(data, elem.obj);
|
||||
objpool_release(tq->obj_pool, &elem.obj);
|
||||
*stream_idx = elem.stream_idx;
|
||||
@@ -177,7 +172,7 @@ static int receive_locked(ThreadQueue *tq, int *stream_idx,
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < tq->nb_streams; i++) {
|
||||
if (!tq->finished[i])
|
||||
if (!(tq->finished[i] & FINISHED_SEND))
|
||||
continue;
|
||||
|
||||
/* return EOF to the consumer at most once for each stream */
|
||||
@@ -202,14 +197,7 @@ int tq_receive(ThreadQueue *tq, int *stream_idx, void *data)
|
||||
pthread_mutex_lock(&tq->lock);
|
||||
|
||||
while (1) {
|
||||
size_t can_read = av_fifo_can_read(tq->fifo);
|
||||
|
||||
ret = receive_locked(tq, stream_idx, data);
|
||||
|
||||
// signal other threads if the fifo state changed
|
||||
if (can_read != av_fifo_can_read(tq->fifo))
|
||||
pthread_cond_broadcast(&tq->cond);
|
||||
|
||||
if (ret == AVERROR(EAGAIN)) {
|
||||
pthread_cond_wait(&tq->cond, &tq->lock);
|
||||
continue;
|
||||
@@ -218,6 +206,9 @@ int tq_receive(ThreadQueue *tq, int *stream_idx, void *data)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
pthread_cond_broadcast(&tq->cond);
|
||||
|
||||
pthread_mutex_unlock(&tq->lock);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -64,6 +64,9 @@ static int zero12v_decode_frame(AVCodecContext *avctx, AVFrame *pic,
|
||||
if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
|
||||
return ret;
|
||||
|
||||
pic->pict_type = AV_PICTURE_TYPE_I;
|
||||
pic->flags |= AV_FRAME_FLAG_KEY;
|
||||
|
||||
line_end = avpkt->data + stride;
|
||||
for (line = 0; line < avctx->height; line++) {
|
||||
uint16_t y_temp[6] = {0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000};
|
||||
|
||||
+9
-8
@@ -30,7 +30,6 @@
|
||||
#include "libavutil/frame.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/mem_internal.h"
|
||||
#include "libavutil/thread.h"
|
||||
#include "avcodec.h"
|
||||
@@ -126,7 +125,7 @@ static const uint8_t dequant_table[64] = {
|
||||
20, 35, 34, 32, 31, 22, 15, 8,
|
||||
};
|
||||
|
||||
static VLCElem block_type_vlc[2][4][32];
|
||||
static VLC block_type_vlc[2][4];
|
||||
|
||||
|
||||
typedef struct CFrameBuffer {
|
||||
@@ -251,15 +250,17 @@ static void idct(int16_t block[64])
|
||||
|
||||
static av_cold void init_vlcs(void)
|
||||
{
|
||||
static VLCElem table[2][4][32];
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
ff_vlc_init_table_sparse(block_type_vlc[i][j], FF_ARRAY_ELEMS(block_type_vlc[i][j]),
|
||||
BLOCK_TYPE_VLC_BITS, 7,
|
||||
&block_type_tab[i][j][0][1], 2, 1,
|
||||
&block_type_tab[i][j][0][0], 2, 1,
|
||||
NULL, 0, 0, 0);
|
||||
block_type_vlc[i][j].table = table[i][j];
|
||||
block_type_vlc[i][j].table_allocated = 32;
|
||||
vlc_init(&block_type_vlc[i][j], BLOCK_TYPE_VLC_BITS, 7,
|
||||
&block_type_tab[i][j][0][1], 2, 1,
|
||||
&block_type_tab[i][j][0][0], 2, 1,
|
||||
VLC_INIT_USE_STATIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -356,7 +357,7 @@ static int decode_p_block(FourXContext *f, uint16_t *dst, const uint16_t *src,
|
||||
if (get_bits_left(&f->gb) < 1)
|
||||
return AVERROR_INVALIDDATA;
|
||||
h = 1 << log2h;
|
||||
code = get_vlc2(&f->gb, block_type_vlc[1 - (f->version > 1)][index],
|
||||
code = get_vlc2(&f->gb, block_type_vlc[1 - (f->version > 1)][index].table,
|
||||
BLOCK_TYPE_VLC_BITS, 1);
|
||||
av_assert0(code >= 0 && code <= 6);
|
||||
|
||||
|
||||
+1
-5
@@ -43,8 +43,6 @@ typedef struct EightBpsContext {
|
||||
|
||||
uint8_t planes;
|
||||
uint8_t planemap[4];
|
||||
|
||||
uint32_t pal[256];
|
||||
} EightBpsContext;
|
||||
|
||||
static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
|
||||
@@ -118,12 +116,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
|
||||
FF_DISABLE_DEPRECATION_WARNINGS
|
||||
frame->palette_has_changed =
|
||||
#endif
|
||||
ff_copy_palette(c->pal, avpkt, avctx);
|
||||
ff_copy_palette(frame->data[1], avpkt, avctx);
|
||||
#if FF_API_PALETTE_HAS_CHANGED
|
||||
FF_ENABLE_DEPRECATION_WARNINGS
|
||||
#endif
|
||||
|
||||
memcpy(frame->data[1], c->pal, AVPALETTE_SIZE);
|
||||
}
|
||||
|
||||
*got_frame = 1;
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
#include "config_components.h"
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "avcodec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "decode.h"
|
||||
|
||||
+89
-72
@@ -25,6 +25,7 @@ HEADERS = ac3_parser.h \
|
||||
version_major.h \
|
||||
videotoolbox.h \
|
||||
vorbis_parser.h \
|
||||
xvmc.h \
|
||||
|
||||
OBJS = ac3_parser.o \
|
||||
adts_parser.o \
|
||||
@@ -32,7 +33,7 @@ OBJS = ac3_parser.o \
|
||||
avcodec.o \
|
||||
avdct.o \
|
||||
avfft.o \
|
||||
packet.o \
|
||||
avpacket.o \
|
||||
bitstream.o \
|
||||
bitstream_filters.o \
|
||||
bsf.o \
|
||||
@@ -46,7 +47,6 @@ OBJS = ac3_parser.o \
|
||||
get_buffer.o \
|
||||
imgconvert.o \
|
||||
jni.o \
|
||||
lcevcdec.o \
|
||||
mathtables.o \
|
||||
mediacodec.o \
|
||||
mpeg12framerate.o \
|
||||
@@ -57,7 +57,6 @@ OBJS = ac3_parser.o \
|
||||
qsv_api.o \
|
||||
raw.o \
|
||||
refstruct.o \
|
||||
threadprogress.o \
|
||||
utils.o \
|
||||
version.o \
|
||||
vlc.o \
|
||||
@@ -65,11 +64,6 @@ OBJS = ac3_parser.o \
|
||||
xiph.o \
|
||||
|
||||
# subsystems
|
||||
include $(SRC_PATH)/libavcodec/aac/Makefile
|
||||
include $(SRC_PATH)/libavcodec/hevc/Makefile
|
||||
include $(SRC_PATH)/libavcodec/opus/Makefile
|
||||
include $(SRC_PATH)/libavcodec/vvc/Makefile
|
||||
-include $(SRC_PATH)/libavcodec/$(ARCH)/vvc/Makefile
|
||||
OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o
|
||||
OBJS-$(CONFIG_AC3DSP) += ac3dsp.o ac3.o ac3tab.o
|
||||
OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio_sample_rates.o
|
||||
@@ -87,12 +81,10 @@ OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o cbs_sei.o h2645_parse.o
|
||||
OBJS-$(CONFIG_CBS_H266) += cbs_h2645.o cbs_sei.o h2645_parse.o
|
||||
OBJS-$(CONFIG_CBS_JPEG) += cbs_jpeg.o
|
||||
OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o
|
||||
OBJS-$(CONFIG_CBS_VP8) += cbs_vp8.o vp8data.o
|
||||
OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o
|
||||
OBJS-$(CONFIG_D3D12VA_ENCODE) += d3d12va_encode.o hw_base_encode.o
|
||||
OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o
|
||||
OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o
|
||||
OBJS-$(CONFIG_DOVI_RPUDEC) += dovi_rpu.o dovi_rpudec.o
|
||||
OBJS-$(CONFIG_DOVI_RPUENC) += dovi_rpu.o dovi_rpuenc.o
|
||||
OBJS-$(CONFIG_DOVI_RPU) += dovi_rpu.o
|
||||
OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o
|
||||
OBJS-$(CONFIG_EVCPARSE) += evc_parse.o evc_ps.o
|
||||
OBJS-$(CONFIG_EXIF) += exif.o tiff_common.o
|
||||
@@ -104,13 +96,14 @@ OBJS-$(CONFIG_GOLOMB) += golomb.o
|
||||
OBJS-$(CONFIG_H263DSP) += h263dsp.o
|
||||
OBJS-$(CONFIG_H264CHROMA) += h264chroma.o
|
||||
OBJS-$(CONFIG_H264DSP) += h264dsp.o h264idct.o
|
||||
OBJS-$(CONFIG_H264PARSE) += h264_parse.o h264_ps.o h264data.o \
|
||||
h2645data.o h2645_parse.o h2645_vui.o
|
||||
OBJS-$(CONFIG_H264PARSE) += h264_parse.o h264_ps.o h2645data.o \
|
||||
h2645_parse.o h2645_vui.o
|
||||
OBJS-$(CONFIG_H264PRED) += h264pred.o
|
||||
OBJS-$(CONFIG_H264QPEL) += h264qpel.o
|
||||
OBJS-$(CONFIG_H264_SEI) += h264_sei.o h2645_sei.o
|
||||
OBJS-$(CONFIG_HEVCPARSE) += h2645data.o h2645_parse.o h2645_vui.o
|
||||
OBJS-$(CONFIG_HEVC_SEI) += h2645_sei.o aom_film_grain.o \
|
||||
OBJS-$(CONFIG_HEVCPARSE) += hevc_parse.o hevc_ps.o hevc_data.o \
|
||||
h2645data.o h2645_parse.o h2645_vui.o
|
||||
OBJS-$(CONFIG_HEVC_SEI) += hevc_sei.o h2645_sei.o \
|
||||
dynamic_hdr_vivid.o
|
||||
OBJS-$(CONFIG_HPELDSP) += hpeldsp.o
|
||||
OBJS-$(CONFIG_HUFFMAN) += huffman.o
|
||||
@@ -119,7 +112,7 @@ OBJS-$(CONFIG_HUFFYUVENCDSP) += huffyuvencdsp.o
|
||||
OBJS-$(CONFIG_IDCTDSP) += idctdsp.o simple_idct.o jrevdct.o
|
||||
OBJS-$(CONFIG_IIRFILTER) += iirfilter.o
|
||||
OBJS-$(CONFIG_INFLATE_WRAPPER) += zlib_wrapper.o
|
||||
OBJS-$(CONFIG_INTRAX8) += intrax8.o intrax8dsp.o msmpeg4_vc1_data.o
|
||||
OBJS-$(CONFIG_INTRAX8) += intrax8.o intrax8dsp.o msmpeg4data.o
|
||||
OBJS-$(CONFIG_IVIDSP) += ivi_dsp.o
|
||||
OBJS-$(CONFIG_JNI) += ffjni.o jni.o
|
||||
OBJS-$(CONFIG_JPEGTABLES) += jpegtables.o
|
||||
@@ -168,7 +161,7 @@ OBJS-$(CONFIG_STARTCODE) += startcode.o
|
||||
OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o
|
||||
OBJS-$(CONFIG_TEXTUREDSPENC) += texturedspenc.o
|
||||
OBJS-$(CONFIG_TPELDSP) += tpeldsp.o
|
||||
OBJS-$(CONFIG_VAAPI_ENCODE) += vaapi_encode.o hw_base_encode.o
|
||||
OBJS-$(CONFIG_VAAPI_ENCODE) += vaapi_encode.o
|
||||
OBJS-$(CONFIG_AV1_AMF_ENCODER) += amfenc_av1.o
|
||||
OBJS-$(CONFIG_VC1DSP) += vc1dsp.o
|
||||
OBJS-$(CONFIG_VIDEODSP) += videodsp.o
|
||||
@@ -183,12 +176,10 @@ OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o
|
||||
OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o
|
||||
OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o
|
||||
OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o
|
||||
OBJS-$(CONFIG_AAC_DECODER) += aactab.o \
|
||||
aacsbr.o aacps_common.o aacps_float.o \
|
||||
OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps_common.o aacps_float.o \
|
||||
kbdwin.o \
|
||||
sbrdsp.o aacpsdsp_float.o cbrt_data.o
|
||||
OBJS-$(CONFIG_AAC_FIXED_DECODER) += aactab.o \
|
||||
aacsbr_fixed.o aacps_common.o aacps_fixed.o \
|
||||
OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o aacsbr_fixed.o aacps_common.o aacps_fixed.o \
|
||||
kbdwin.o \
|
||||
sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o
|
||||
OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \
|
||||
@@ -199,7 +190,6 @@ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \
|
||||
aacenc_pred.o \
|
||||
psymodel.o kbdwin.o \
|
||||
mpeg4audio_sample_rates.o
|
||||
OBJS-$(CONFIG_AAC_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_AAC_MF_ENCODER) += mfenc.o mf_utils.o
|
||||
OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o
|
||||
OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o \
|
||||
@@ -226,8 +216,6 @@ OBJS-$(CONFIG_AMRWB_DECODER) += amrwbdec.o celp_filters.o \
|
||||
celp_math.o acelp_filters.o \
|
||||
acelp_vectors.o \
|
||||
acelp_pitch_delay.o
|
||||
OBJS-$(CONFIG_AMRNB_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_AMRWB_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_AMV_ENCODER) += mjpegenc.o mjpegenc_common.o
|
||||
OBJS-$(CONFIG_ANM_DECODER) += anm.o
|
||||
OBJS-$(CONFIG_ANULL_DECODER) += null.o
|
||||
@@ -261,7 +249,7 @@ OBJS-$(CONFIG_ATRAC3PAL_DECODER) += atrac3plusdec.o atrac3plus.o \
|
||||
OBJS-$(CONFIG_ATRAC9_DECODER) += atrac9dec.o
|
||||
OBJS-$(CONFIG_AURA_DECODER) += cyuv.o
|
||||
OBJS-$(CONFIG_AURA2_DECODER) += aura.o
|
||||
OBJS-$(CONFIG_AV1_DECODER) += av1dec.o av1_parse.o
|
||||
OBJS-$(CONFIG_AV1_DECODER) += av1dec.o
|
||||
OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_AV1_MEDIACODEC_ENCODER) += mediacodecenc.o
|
||||
@@ -274,6 +262,8 @@ OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o
|
||||
OBJS-$(CONFIG_AVS_DECODER) += avs.o
|
||||
OBJS-$(CONFIG_AVUI_DECODER) += avuidec.o
|
||||
OBJS-$(CONFIG_AVUI_ENCODER) += avuienc.o
|
||||
OBJS-$(CONFIG_AYUV_DECODER) += v408dec.o
|
||||
OBJS-$(CONFIG_AYUV_ENCODER) += v408enc.o
|
||||
OBJS-$(CONFIG_BETHSOFTVID_DECODER) += bethsoftvideo.o
|
||||
OBJS-$(CONFIG_BFI_DECODER) += bfi.o
|
||||
OBJS-$(CONFIG_BINK_DECODER) += bink.o binkdsp.o
|
||||
@@ -291,7 +281,7 @@ 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
|
||||
OBJS-$(CONFIG_CBD2_DPCM_DECODER) += dpcm.o
|
||||
OBJS-$(CONFIG_CBD2_DECODER) += dpcm.o
|
||||
OBJS-$(CONFIG_CCAPTION_DECODER) += ccaption_dec.o ass.o
|
||||
OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o
|
||||
OBJS-$(CONFIG_CDTOONS_DECODER) += cdtoons.o
|
||||
@@ -347,7 +337,6 @@ OBJS-$(CONFIG_DVVIDEO_ENCODER) += dvenc.o dv.o dvdata.o
|
||||
OBJS-$(CONFIG_DXA_DECODER) += dxa.o
|
||||
OBJS-$(CONFIG_DXTORY_DECODER) += dxtory.o
|
||||
OBJS-$(CONFIG_DXV_DECODER) += dxv.o
|
||||
OBJS-$(CONFIG_DXV_ENCODER) += dxvenc.o
|
||||
OBJS-$(CONFIG_EAC3_DECODER) += eac3_data.o
|
||||
OBJS-$(CONFIG_EAC3_ENCODER) += eac3enc.o eac3_data.o
|
||||
OBJS-$(CONFIG_EACMV_DECODER) += eacmv.o
|
||||
@@ -426,10 +415,7 @@ OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec.o
|
||||
OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o
|
||||
OBJS-$(CONFIG_H264_RKMPP_DECODER) += rkmppdec.o
|
||||
OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o h264_levels.o \
|
||||
h2645data.o hw_base_encode_h264.o
|
||||
OBJS-$(CONFIG_H264_VULKAN_ENCODER) += vulkan_encode.o vulkan_encode_h264.o \
|
||||
hw_base_encode.o hw_base_encode_h264.o \
|
||||
h264_levels.o h2645data.o
|
||||
h2645data.o
|
||||
OBJS-$(CONFIG_H264_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o
|
||||
OBJS-$(CONFIG_H264_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
||||
OBJS-$(CONFIG_H264_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
|
||||
@@ -439,28 +425,28 @@ OBJS-$(CONFIG_HCA_DECODER) += hcadec.o
|
||||
OBJS-$(CONFIG_HCOM_DECODER) += hcom.o
|
||||
OBJS-$(CONFIG_HDR_DECODER) += hdrdec.o
|
||||
OBJS-$(CONFIG_HDR_ENCODER) += hdrenc.o
|
||||
OBJS-$(CONFIG_HEVC_DECODER) += aom_film_grain.o h274.o container_fifo.o
|
||||
OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \
|
||||
hevc_cabac.o hevc_refs.o hevcpred.o \
|
||||
hevcdsp.o hevc_filter.o hevc_data.o \
|
||||
h274.o
|
||||
OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_HEVC_D3D12VA_ENCODER) += d3d12va_encode_hevc.o h265_profile_level.o \
|
||||
h2645data.o
|
||||
OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_HEVC_MEDIACODEC_ENCODER) += mediacodecenc.o
|
||||
OBJS-$(CONFIG_HEVC_MF_ENCODER) += mfenc.o mf_utils.o
|
||||
OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o nvenc.o
|
||||
OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec.o
|
||||
OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc/ps_enc.o
|
||||
OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \
|
||||
hevc_data.o
|
||||
OBJS-$(CONFIG_HEVC_RKMPP_DECODER) += rkmppdec.o
|
||||
OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o h265_profile_level.o \
|
||||
h2645data.o hw_base_encode_h265.o
|
||||
OBJS-$(CONFIG_HEVC_VULKAN_ENCODER) += vulkan_encode.o vulkan_encode_h265.o \
|
||||
hw_base_encode.o hw_base_encode_h265.o \
|
||||
h265_profile_level.o h2645data.o
|
||||
h2645data.o
|
||||
OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
||||
OBJS-$(CONFIG_HEVC_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
|
||||
OBJS-$(CONFIG_HEVC_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o
|
||||
OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o
|
||||
OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadsp.o canopus.o
|
||||
OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadata.o hq_hqadsp.o \
|
||||
canopus.o
|
||||
OBJS-$(CONFIG_HQX_DECODER) += hqx.o hqxvlc.o hqxdsp.o canopus.o
|
||||
OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o huffyuvdec.o
|
||||
OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o huffyuvenc.o
|
||||
@@ -491,7 +477,6 @@ 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_LEAD_DECODER) += leaddec.o jpegquanttables.o
|
||||
OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc_common.o
|
||||
OBJS-$(CONFIG_LOCO_DECODER) += loco.o
|
||||
OBJS-$(CONFIG_LSCR_DECODER) += lscrdec.o png.o pngdec.o pngdsp.o
|
||||
@@ -532,7 +517,6 @@ OBJS-$(CONFIG_MP2FIXED_ENCODER) += mpegaudioenc_fixed.o mpegaudio.o \
|
||||
mpegaudiotabs.o
|
||||
OBJS-$(CONFIG_MP2FLOAT_DECODER) += mpegaudiodec_float.o
|
||||
OBJS-$(CONFIG_MP3_DECODER) += mpegaudiodec_fixed.o
|
||||
OBJS-$(CONFIG_MP3_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_MP3_MF_ENCODER) += mfenc.o mf_utils.o
|
||||
OBJS-$(CONFIG_MP3ADU_DECODER) += mpegaudiodec_fixed.o
|
||||
OBJS-$(CONFIG_MP3ADUFLOAT_DECODER) += mpegaudiodec_float.o
|
||||
@@ -588,7 +572,11 @@ OBJS-$(CONFIG_NELLYMOSER_ENCODER) += nellymoserenc.o nellymoser.o
|
||||
OBJS-$(CONFIG_NOTCHLC_DECODER) += notchlc.o
|
||||
OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o jpegquanttables.o
|
||||
OBJS-$(CONFIG_ON2AVC_DECODER) += on2avc.o on2avcdata.o
|
||||
OBJS-$(CONFIG_OPUS_DECODER) += vorbis_data.o
|
||||
OBJS-$(CONFIG_OPUS_DECODER) += opusdec.o opusdec_celt.o opus_celt.o \
|
||||
opus_pvq.o opus_silk.o opustab.o vorbis_data.o \
|
||||
opusdsp.o opus_parse.o opus_rc.o
|
||||
OBJS-$(CONFIG_OPUS_ENCODER) += opusenc.o opusenc_psy.o opus_celt.o \
|
||||
opus_pvq.o opus_rc.o opustab.o
|
||||
OBJS-$(CONFIG_OSQ_DECODER) += osq.o
|
||||
OBJS-$(CONFIG_PAF_AUDIO_DECODER) += pafaudio.o
|
||||
OBJS-$(CONFIG_PAF_VIDEO_DECODER) += pafvideo.o
|
||||
@@ -617,7 +605,7 @@ OBJS-$(CONFIG_PNG_DECODER) += png.o pngdec.o pngdsp.o
|
||||
OBJS-$(CONFIG_PNG_ENCODER) += png.o pngenc.o
|
||||
OBJS-$(CONFIG_PPM_DECODER) += pnmdec.o pnm.o
|
||||
OBJS-$(CONFIG_PPM_ENCODER) += pnmenc.o
|
||||
OBJS-$(CONFIG_PRORES_DECODER) += proresdec.o proresdsp.o proresdata.o
|
||||
OBJS-$(CONFIG_PRORES_DECODER) += proresdec2.o proresdsp.o proresdata.o
|
||||
OBJS-$(CONFIG_PRORES_ENCODER) += proresenc_anatoliy.o proresdata.o
|
||||
OBJS-$(CONFIG_PRORES_AW_ENCODER) += proresenc_anatoliy.o proresdata.o
|
||||
OBJS-$(CONFIG_PRORES_KS_ENCODER) += proresenc_kostya.o proresdata.o
|
||||
@@ -631,7 +619,6 @@ OBJS-$(CONFIG_QCELP_DECODER) += qcelpdec.o \
|
||||
OBJS-$(CONFIG_QDM2_DECODER) += qdm2.o
|
||||
OBJS-$(CONFIG_QDMC_DECODER) += qdmc.o
|
||||
OBJS-$(CONFIG_QDRAW_DECODER) += qdrw.o
|
||||
OBJS-$(CONFIG_QOA_DECODER) += qoadec.o
|
||||
OBJS-$(CONFIG_QOI_DECODER) += qoidec.o
|
||||
OBJS-$(CONFIG_QOI_ENCODER) += qoienc.o
|
||||
OBJS-$(CONFIG_QPEG_DECODER) += qpeg.o
|
||||
@@ -994,7 +981,6 @@ OBJS-$(CONFIG_ADPCM_ZORK_DECODER) += adpcm.o adpcm_data.o
|
||||
|
||||
# hardware accelerators
|
||||
OBJS-$(CONFIG_D3D11VA) += dxva2.o
|
||||
OBJS-$(CONFIG_D3D12VA) += dxva2.o d3d12va_decode.o
|
||||
OBJS-$(CONFIG_DXVA2) += dxva2.o
|
||||
OBJS-$(CONFIG_NVDEC) += nvdec.o
|
||||
OBJS-$(CONFIG_VAAPI) += vaapi_decode.o
|
||||
@@ -1004,7 +990,6 @@ OBJS-$(CONFIG_VULKAN) += vulkan.o vulkan_video.o
|
||||
|
||||
OBJS-$(CONFIG_AV1_D3D11VA_HWACCEL) += dxva2_av1.o
|
||||
OBJS-$(CONFIG_AV1_DXVA2_HWACCEL) += dxva2_av1.o
|
||||
OBJS-$(CONFIG_AV1_D3D12VA_HWACCEL) += dxva2_av1.o d3d12va_av1.o
|
||||
OBJS-$(CONFIG_AV1_NVDEC_HWACCEL) += nvdec_av1.o
|
||||
OBJS-$(CONFIG_AV1_VAAPI_HWACCEL) += vaapi_av1.o
|
||||
OBJS-$(CONFIG_AV1_VDPAU_HWACCEL) += vdpau_av1.o
|
||||
@@ -1013,7 +998,6 @@ OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o
|
||||
OBJS-$(CONFIG_H263_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o
|
||||
OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
|
||||
OBJS-$(CONFIG_H264_D3D12VA_HWACCEL) += dxva2_h264.o d3d12va_h264.o
|
||||
OBJS-$(CONFIG_H264_NVDEC_HWACCEL) += nvdec_h264.o
|
||||
OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec.o
|
||||
OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
|
||||
@@ -1022,7 +1006,6 @@ OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_H264_VULKAN_HWACCEL) += vulkan_decode.o vulkan_h264.o
|
||||
OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_D3D12VA_HWACCEL) += dxva2_hevc.o d3d12va_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec.o
|
||||
OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o h265_profile_level.o
|
||||
@@ -1035,7 +1018,6 @@ OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o
|
||||
OBJS-$(CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o
|
||||
OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
|
||||
OBJS-$(CONFIG_MPEG2_D3D12VA_HWACCEL) += dxva2_mpeg2.o d3d12va_mpeg2.o
|
||||
OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o
|
||||
OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec.o
|
||||
OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
|
||||
@@ -1047,7 +1029,6 @@ OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL) += vdpau_mpeg4.o
|
||||
OBJS-$(CONFIG_MPEG4_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_VC1_D3D11VA_HWACCEL) += dxva2_vc1.o
|
||||
OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o
|
||||
OBJS-$(CONFIG_VC1_D3D12VA_HWACCEL) += dxva2_vc1.o d3d12va_vc1.o
|
||||
OBJS-$(CONFIG_VC1_NVDEC_HWACCEL) += nvdec_vc1.o
|
||||
OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec.o
|
||||
OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o
|
||||
@@ -1056,7 +1037,6 @@ OBJS-$(CONFIG_VP8_NVDEC_HWACCEL) += nvdec_vp8.o
|
||||
OBJS-$(CONFIG_VP8_VAAPI_HWACCEL) += vaapi_vp8.o
|
||||
OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o
|
||||
OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o
|
||||
OBJS-$(CONFIG_VP9_D3D12VA_HWACCEL) += dxva2_vp9.o d3d12va_vp9.o
|
||||
OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o
|
||||
OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o
|
||||
OBJS-$(CONFIG_VP9_VDPAU_HWACCEL) += vdpau_vp9.o
|
||||
@@ -1076,7 +1056,6 @@ STLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o
|
||||
STLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o
|
||||
STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o
|
||||
STLIBOBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += jpegxl_parse.o
|
||||
STLIBOBJS-$(CONFIG_JNI) += ffjni.o
|
||||
STLIBOBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_parse.o
|
||||
STLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o
|
||||
STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o
|
||||
@@ -1132,8 +1111,6 @@ OBJS-$(CONFIG_LIBILBC_ENCODER) += libilbc.o
|
||||
OBJS-$(CONFIG_LIBJXL_DECODER) += libjxldec.o libjxl.o
|
||||
OBJS-$(CONFIG_LIBJXL_ENCODER) += libjxlenc.o libjxl.o
|
||||
OBJS-$(CONFIG_LIBKVAZAAR_ENCODER) += libkvazaar.o
|
||||
OBJS-$(CONFIG_LIBLC3_ENCODER) += liblc3enc.o
|
||||
OBJS-$(CONFIG_LIBLC3_DECODER) += liblc3dec.o
|
||||
OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o
|
||||
OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o
|
||||
OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o
|
||||
@@ -1161,7 +1138,6 @@ OBJS-$(CONFIG_LIBVPX_VP8_DECODER) += libvpxdec.o
|
||||
OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o
|
||||
OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o
|
||||
OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o
|
||||
OBJS-$(CONFIG_LIBVVENC_ENCODER) += libvvenc.o
|
||||
OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.o libwebpenc.o
|
||||
OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER) += libwebpenc_common.o libwebpenc_animencoder.o
|
||||
OBJS-$(CONFIG_LIBX262_ENCODER) += libx264.o
|
||||
@@ -1169,8 +1145,6 @@ OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o
|
||||
OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o
|
||||
OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o
|
||||
OBJS-$(CONFIG_LIBXAVS2_ENCODER) += libxavs2.o
|
||||
OBJS-$(CONFIG_LIBXEVD_DECODER) += libxevd.o
|
||||
OBJS-$(CONFIG_LIBXEVE_ENCODER) += libxeve.o
|
||||
OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o
|
||||
OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o
|
||||
|
||||
@@ -1208,6 +1182,7 @@ 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 h264data.o
|
||||
OBJS-$(CONFIG_HEVC_PARSER) += hevc_parser.o hevc_data.o
|
||||
OBJS-$(CONFIG_HDR_PARSER) += hdr_parser.o
|
||||
OBJS-$(CONFIG_IPU_PARSER) += ipu_parser.o
|
||||
OBJS-$(CONFIG_JPEG2000_PARSER) += jpeg2000_parser.o
|
||||
@@ -1221,7 +1196,8 @@ OBJS-$(CONFIG_MPEG4VIDEO_PARSER) += mpeg4video_parser.o h263.o \
|
||||
OBJS-$(CONFIG_MPEGAUDIO_PARSER) += mpegaudio_parser.o
|
||||
OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o \
|
||||
mpeg12.o mpeg12data.o
|
||||
OBJS-$(CONFIG_OPUS_PARSER) += vorbis_data.o
|
||||
OBJS-$(CONFIG_OPUS_PARSER) += opus_parser.o opus_parse.o \
|
||||
vorbis_data.o
|
||||
OBJS-$(CONFIG_PNG_PARSER) += png_parser.o
|
||||
OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o
|
||||
OBJS-$(CONFIG_QOI_PARSER) += qoi_parser.o
|
||||
@@ -1241,14 +1217,54 @@ OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o
|
||||
OBJS-$(CONFIG_XWD_PARSER) += xwd_parser.o
|
||||
|
||||
# bitstream filters
|
||||
include $(SRC_PATH)/libavcodec/bsf/Makefile
|
||||
|
||||
OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += av1_parse.o h2645_parse.o
|
||||
OBJS-$(CONFIG_H264_METADATA_BSF) += h264_levels.o h2645data.o
|
||||
OBJS-$(CONFIG_HAPQA_EXTRACT_BSF) += hap.o
|
||||
OBJS-$(CONFIG_HEVC_METADATA_BSF) += h265_profile_level.o h2645data.o
|
||||
OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += av1_parse.o
|
||||
OBJS-$(CONFIG_TRUEHD_CORE_BSF) += mlp_parse.o mlp.o
|
||||
OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o
|
||||
OBJS-$(CONFIG_AV1_METADATA_BSF) += av1_metadata_bsf.o
|
||||
OBJS-$(CONFIG_AV1_FRAME_MERGE_BSF) += av1_frame_merge_bsf.o
|
||||
OBJS-$(CONFIG_AV1_FRAME_SPLIT_BSF) += av1_frame_split_bsf.o
|
||||
OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o
|
||||
OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o
|
||||
OBJS-$(CONFIG_DCA_CORE_BSF) += dca_core_bsf.o
|
||||
OBJS-$(CONFIG_DTS2PTS_BSF) += dts2pts_bsf.o
|
||||
OBJS-$(CONFIG_DV_ERROR_MARKER_BSF) += dv_error_marker_bsf.o
|
||||
OBJS-$(CONFIG_EAC3_CORE_BSF) += eac3_core_bsf.o
|
||||
OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \
|
||||
av1_parse.o h2645_parse.o
|
||||
OBJS-$(CONFIG_FILTER_UNITS_BSF) += filter_units_bsf.o
|
||||
OBJS-$(CONFIG_H264_METADATA_BSF) += h264_metadata_bsf.o h264_levels.o \
|
||||
h2645data.o
|
||||
OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o
|
||||
OBJS-$(CONFIG_H264_REDUNDANT_PPS_BSF) += h264_redundant_pps_bsf.o
|
||||
OBJS-$(CONFIG_HAPQA_EXTRACT_BSF) += hapqa_extract_bsf.o hap.o
|
||||
OBJS-$(CONFIG_HEVC_METADATA_BSF) += h265_metadata_bsf.o h265_profile_level.o \
|
||||
h2645data.o
|
||||
OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o
|
||||
OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o
|
||||
OBJS-$(CONFIG_MEDIA100_TO_MJPEGB_BSF) += media100_to_mjpegb_bsf.o
|
||||
OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o
|
||||
OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF) += mjpega_dump_header_bsf.o
|
||||
OBJS-$(CONFIG_MPEG4_UNPACK_BFRAMES_BSF) += mpeg4_unpack_bframes_bsf.o
|
||||
OBJS-$(CONFIG_MOV2TEXTSUB_BSF) += movsub_bsf.o
|
||||
OBJS-$(CONFIG_MP3_HEADER_DECOMPRESS_BSF) += mp3_header_decompress_bsf.o \
|
||||
mpegaudiotabs.o
|
||||
OBJS-$(CONFIG_MPEG2_METADATA_BSF) += mpeg2_metadata_bsf.o
|
||||
OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o
|
||||
OBJS-$(CONFIG_NULL_BSF) += null_bsf.o
|
||||
OBJS-$(CONFIG_OPUS_METADATA_BSF) += opus_metadata_bsf.o
|
||||
OBJS-$(CONFIG_PCM_RECHUNK_BSF) += pcm_rechunk_bsf.o
|
||||
OBJS-$(CONFIG_PGS_FRAME_MERGE_BSF) += pgs_frame_merge_bsf.o
|
||||
OBJS-$(CONFIG_PRORES_METADATA_BSF) += prores_metadata_bsf.o
|
||||
OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o av1_parse.o
|
||||
OBJS-$(CONFIG_SETTS_BSF) += setts_bsf.o
|
||||
OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o
|
||||
OBJS-$(CONFIG_TRACE_HEADERS_BSF) += trace_headers_bsf.o
|
||||
OBJS-$(CONFIG_TRUEHD_CORE_BSF) += truehd_core_bsf.o mlp_parse.o mlp.o
|
||||
OBJS-$(CONFIG_VP9_METADATA_BSF) += vp9_metadata_bsf.o
|
||||
OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o
|
||||
OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o
|
||||
OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o
|
||||
OBJS-$(CONFIG_VVC_METADATA_BSF) += h266_metadata_bsf.o
|
||||
OBJS-$(CONFIG_VVC_MP4TOANNEXB_BSF) += vvc_mp4toannexb_bsf.o
|
||||
OBJS-$(CONFIG_EVC_FRAME_MERGE_BSF) += evc_frame_merge_bsf.o
|
||||
|
||||
# thread libraries
|
||||
OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o
|
||||
@@ -1268,11 +1284,11 @@ SKIPHEADERS += %_tablegen.h \
|
||||
aacenc_quantization.h \
|
||||
aacenc_quantization_misc.h \
|
||||
bitstream_template.h \
|
||||
$(ARCH)/vpx_arith.h \
|
||||
vulkan_video_codec_av1std_mesa.h \
|
||||
$(ARCH)/vpx_arith.h \
|
||||
|
||||
SKIPHEADERS-$(CONFIG_AMF) += amfenc.h
|
||||
SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h
|
||||
SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h d3d12va_encode.h
|
||||
SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h
|
||||
SKIPHEADERS-$(CONFIG_JNI) += ffjni.h
|
||||
SKIPHEADERS-$(CONFIG_LCMS2) += fflcms2.h
|
||||
@@ -1286,10 +1302,11 @@ SKIPHEADERS-$(CONFIG_NVDEC) += nvdec.h
|
||||
SKIPHEADERS-$(CONFIG_NVENC) += nvenc.h
|
||||
SKIPHEADERS-$(CONFIG_QSV) += qsv.h qsv_internal.h
|
||||
SKIPHEADERS-$(CONFIG_QSVENC) += qsvenc.h
|
||||
SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h
|
||||
SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_decode.h vaapi_hevc.h vaapi_encode.h
|
||||
SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h vdpau_internal.h
|
||||
SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vt_internal.h
|
||||
SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_video.h vulkan_encode.h vulkan_decode.h
|
||||
SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_video.h vulkan_decode.h vulkan_video_codec_av1std_decode_mesa.h
|
||||
SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m.h
|
||||
SKIPHEADERS-$(CONFIG_ZLIB) += zlib_wrapper.h
|
||||
|
||||
@@ -1357,7 +1374,7 @@ $(GEN_HEADERS): $(SUBDIR)%_tables.h: $(SUBDIR)%_tablegen$(HOSTEXESUF)
|
||||
ifdef CONFIG_HARDCODED_TABLES
|
||||
$(SUBDIR)cbrt_data.o: $(SUBDIR)cbrt_tables.h
|
||||
$(SUBDIR)cbrt_data_fixed.o: $(SUBDIR)cbrt_fixed_tables.h
|
||||
$(SUBDIR)aac/aacdec_fixed.o: $(SUBDIR)sinewin_fixed_tables.h
|
||||
$(SUBDIR)aacdec_fixed.o: $(SUBDIR)sinewin_fixed_tables.h
|
||||
$(SUBDIR)aacps_float.o: $(SUBDIR)aacps_tables.h
|
||||
$(SUBDIR)aacps_fixed.o: $(SUBDIR)aacps_fixed_tables.h
|
||||
$(SUBDIR)dvenc.o: $(SUBDIR)dv_tables.h
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
#include "elbg.h"
|
||||
#include "encode.h"
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/common.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/mem.h"
|
||||
|
||||
#define DITHERSTEPS 8
|
||||
#define CHARSET_CHARS 256
|
||||
|
||||
+285
-16
@@ -30,12 +30,27 @@
|
||||
#ifndef AVCODEC_AAC_H
|
||||
#define AVCODEC_AAC_H
|
||||
|
||||
|
||||
#include "aac_defines.h"
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/float_dsp.h"
|
||||
#include "libavutil/fixed_dsp.h"
|
||||
#include "libavutil/mem_internal.h"
|
||||
#include "libavutil/tx.h"
|
||||
#include "avcodec.h"
|
||||
#include "mpeg4audio.h"
|
||||
#include "sbr.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAX_CHANNELS 64
|
||||
#define MAX_ELEM_ID 64
|
||||
#define MAX_ELEM_ID 16
|
||||
|
||||
#define TNS_MAX_ORDER 20
|
||||
#define MAX_LTP_LONG_SFB 40
|
||||
|
||||
#define CLIP_AVOIDANCE_FACTOR 0.95f
|
||||
|
||||
enum RawDataBlockType {
|
||||
TYPE_SCE,
|
||||
TYPE_CPE,
|
||||
@@ -73,6 +88,8 @@ enum BandType {
|
||||
INTENSITY_BT = 15, ///< Scalefactor data are intensity stereo positions (in phase).
|
||||
};
|
||||
|
||||
#define IS_CODEBOOK_UNSIGNED(x) (((x) - 1) & 10)
|
||||
|
||||
enum ChannelPosition {
|
||||
AAC_CHANNEL_OFF = 0,
|
||||
AAC_CHANNEL_FRONT = 1,
|
||||
@@ -82,6 +99,48 @@ enum ChannelPosition {
|
||||
AAC_CHANNEL_CC = 5,
|
||||
};
|
||||
|
||||
/**
|
||||
* The point during decoding at which channel coupling is applied.
|
||||
*/
|
||||
enum CouplingPoint {
|
||||
BEFORE_TNS,
|
||||
BETWEEN_TNS_AND_IMDCT,
|
||||
AFTER_IMDCT = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* Output configuration status
|
||||
*/
|
||||
enum OCStatus {
|
||||
OC_NONE, ///< Output unconfigured
|
||||
OC_TRIAL_PCE, ///< Output configuration under trial specified by an inband PCE
|
||||
OC_TRIAL_FRAME, ///< Output configuration under trial specified by a frame header
|
||||
OC_GLOBAL_HDR, ///< Output configuration set in a global header but not yet locked
|
||||
OC_LOCKED, ///< Output configuration locked in place
|
||||
};
|
||||
|
||||
typedef struct OutputConfiguration {
|
||||
MPEG4AudioConfig m4ac;
|
||||
uint8_t layout_map[MAX_ELEM_ID*4][3];
|
||||
int layout_map_tags;
|
||||
AVChannelLayout ch_layout;
|
||||
enum OCStatus status;
|
||||
} OutputConfiguration;
|
||||
|
||||
/**
|
||||
* Predictor State
|
||||
*/
|
||||
typedef struct PredictorState {
|
||||
AAC_FLOAT cor0;
|
||||
AAC_FLOAT cor1;
|
||||
AAC_FLOAT var0;
|
||||
AAC_FLOAT var1;
|
||||
AAC_FLOAT r0;
|
||||
AAC_FLOAT r1;
|
||||
AAC_FLOAT k1;
|
||||
AAC_FLOAT x_est;
|
||||
} PredictorState;
|
||||
|
||||
#define MAX_PREDICTORS 672
|
||||
|
||||
#define SCALE_DIV_512 36 ///< scalefactor difference that corresponds to scale difference in 512 times
|
||||
@@ -96,6 +155,70 @@ enum ChannelPosition {
|
||||
#define NOISE_PRE_BITS 9 ///< length of preamble
|
||||
#define NOISE_OFFSET 90 ///< subtracted from global gain, used as offset for the preamble
|
||||
|
||||
/**
|
||||
* Long Term Prediction
|
||||
*/
|
||||
typedef struct LongTermPrediction {
|
||||
int8_t present;
|
||||
int16_t lag;
|
||||
int coef_idx;
|
||||
INTFLOAT coef;
|
||||
int8_t used[MAX_LTP_LONG_SFB];
|
||||
} LongTermPrediction;
|
||||
|
||||
/**
|
||||
* Individual Channel Stream
|
||||
*/
|
||||
typedef struct IndividualChannelStream {
|
||||
uint8_t max_sfb; ///< number of scalefactor bands per group
|
||||
enum WindowSequence window_sequence[2];
|
||||
uint8_t use_kb_window[2]; ///< If set, use Kaiser-Bessel window, otherwise use a sine window.
|
||||
int num_window_groups;
|
||||
uint8_t group_len[8];
|
||||
LongTermPrediction ltp;
|
||||
const uint16_t *swb_offset; ///< table of offsets to the lowest spectral coefficient of a scalefactor band, sfb, for a particular window
|
||||
const uint8_t *swb_sizes; ///< table of scalefactor band sizes for a particular window
|
||||
int num_swb; ///< number of scalefactor window bands
|
||||
int num_windows;
|
||||
int tns_max_bands;
|
||||
int predictor_present;
|
||||
int predictor_initialized;
|
||||
int predictor_reset_group;
|
||||
int predictor_reset_count[31]; ///< used by encoder to count prediction resets
|
||||
uint8_t prediction_used[41];
|
||||
uint8_t window_clipping[8]; ///< set if a certain window is near clipping
|
||||
float clip_avoidance_factor; ///< set if any window is near clipping to the necessary atennuation factor to avoid it
|
||||
} IndividualChannelStream;
|
||||
|
||||
/**
|
||||
* Temporal Noise Shaping
|
||||
*/
|
||||
typedef struct TemporalNoiseShaping {
|
||||
int present;
|
||||
int n_filt[8];
|
||||
int length[8][4];
|
||||
int direction[8][4];
|
||||
int order[8][4];
|
||||
int coef_idx[8][4][TNS_MAX_ORDER];
|
||||
INTFLOAT coef[8][4][TNS_MAX_ORDER];
|
||||
} TemporalNoiseShaping;
|
||||
|
||||
/**
|
||||
* Dynamic Range Control - decoded from the bitstream but not processed further.
|
||||
*/
|
||||
typedef struct DynamicRangeControl {
|
||||
int pce_instance_tag; ///< Indicates with which program the DRC info is associated.
|
||||
int dyn_rng_sgn[17]; ///< DRC sign information; 0 - positive, 1 - negative
|
||||
int dyn_rng_ctl[17]; ///< DRC magnitude information
|
||||
int exclude_mask[MAX_CHANNELS]; ///< Channels to be excluded from DRC processing.
|
||||
int band_incr; ///< Number of DRC bands greater than 1 having DRC info.
|
||||
int interpolation_scheme; ///< Indicates the interpolation scheme used in the SBR QMF domain.
|
||||
int band_top[17]; ///< Indicates the top of the i-th DRC band in units of 4 spectral lines.
|
||||
int prog_ref_level; /**< A reference level for the long-term program audio level for all
|
||||
* channels combined.
|
||||
*/
|
||||
} DynamicRangeControl;
|
||||
|
||||
typedef struct Pulse {
|
||||
int num_pulse;
|
||||
int start;
|
||||
@@ -103,20 +226,166 @@ typedef struct Pulse {
|
||||
int amp[4];
|
||||
} Pulse;
|
||||
|
||||
static inline int ff_aac_sample_rate_idx(int rate)
|
||||
{
|
||||
if (92017 <= rate) return 0;
|
||||
else if (75132 <= rate) return 1;
|
||||
else if (55426 <= rate) return 2;
|
||||
else if (46009 <= rate) return 3;
|
||||
else if (37566 <= rate) return 4;
|
||||
else if (27713 <= rate) return 5;
|
||||
else if (23004 <= rate) return 6;
|
||||
else if (18783 <= rate) return 7;
|
||||
else if (13856 <= rate) return 8;
|
||||
else if (11502 <= rate) return 9;
|
||||
else if (9391 <= rate) return 10;
|
||||
else return 11;
|
||||
}
|
||||
/**
|
||||
* coupling parameters
|
||||
*/
|
||||
typedef struct ChannelCoupling {
|
||||
enum CouplingPoint coupling_point; ///< The point during decoding at which coupling is applied.
|
||||
int num_coupled; ///< number of target elements
|
||||
enum RawDataBlockType type[8]; ///< Type of channel element to be coupled - SCE or CPE.
|
||||
int id_select[8]; ///< element id
|
||||
int ch_select[8]; /**< [0] shared list of gains; [1] list of gains for right channel;
|
||||
* [2] list of gains for left channel; [3] lists of gains for both channels
|
||||
*/
|
||||
INTFLOAT gain[16][120];
|
||||
} ChannelCoupling;
|
||||
|
||||
/**
|
||||
* Single Channel Element - used for both SCE and LFE elements.
|
||||
*/
|
||||
typedef struct SingleChannelElement {
|
||||
IndividualChannelStream ics;
|
||||
TemporalNoiseShaping tns;
|
||||
Pulse pulse;
|
||||
enum BandType band_type[128]; ///< band types
|
||||
enum BandType band_alt[128]; ///< alternative band type (used by encoder)
|
||||
int band_type_run_end[120]; ///< band type run end points
|
||||
INTFLOAT sf[120]; ///< scalefactors
|
||||
int sf_idx[128]; ///< scalefactor indices (used by encoder)
|
||||
uint8_t zeroes[128]; ///< band is not coded (used by encoder)
|
||||
uint8_t can_pns[128]; ///< band is allowed to PNS (informative)
|
||||
float is_ener[128]; ///< Intensity stereo pos (used by encoder)
|
||||
float pns_ener[128]; ///< Noise energy values (used by encoder)
|
||||
DECLARE_ALIGNED(32, INTFLOAT, pcoeffs)[1024]; ///< coefficients for IMDCT, pristine
|
||||
DECLARE_ALIGNED(32, INTFLOAT, coeffs)[1024]; ///< coefficients for IMDCT, maybe processed
|
||||
DECLARE_ALIGNED(32, INTFLOAT, saved)[1536]; ///< overlap
|
||||
DECLARE_ALIGNED(32, INTFLOAT, ret_buf)[2048]; ///< PCM output buffer
|
||||
DECLARE_ALIGNED(16, INTFLOAT, ltp_state)[3072]; ///< time signal for LTP
|
||||
DECLARE_ALIGNED(32, AAC_FLOAT, lcoeffs)[1024]; ///< MDCT of LTP coefficients (used by encoder)
|
||||
DECLARE_ALIGNED(32, AAC_FLOAT, prcoeffs)[1024]; ///< Main prediction coefs (used by encoder)
|
||||
PredictorState predictor_state[MAX_PREDICTORS];
|
||||
INTFLOAT *ret; ///< PCM output
|
||||
} SingleChannelElement;
|
||||
|
||||
/**
|
||||
* channel element - generic struct for SCE/CPE/CCE/LFE
|
||||
*/
|
||||
typedef struct ChannelElement {
|
||||
int present;
|
||||
// CPE specific
|
||||
int common_window; ///< Set if channels share a common 'IndividualChannelStream' in bitstream.
|
||||
int ms_mode; ///< Signals mid/side stereo flags coding mode (used by encoder)
|
||||
uint8_t is_mode; ///< Set if any bands have been encoded using intensity stereo (used by encoder)
|
||||
uint8_t ms_mask[128]; ///< Set if mid/side stereo is used for each scalefactor window band
|
||||
uint8_t is_mask[128]; ///< Set if intensity stereo is used (used by encoder)
|
||||
// shared
|
||||
SingleChannelElement ch[2];
|
||||
// CCE specific
|
||||
ChannelCoupling coup;
|
||||
SpectralBandReplication sbr;
|
||||
} ChannelElement;
|
||||
|
||||
enum AACOutputChannelOrder {
|
||||
CHANNEL_ORDER_DEFAULT,
|
||||
CHANNEL_ORDER_CODED,
|
||||
};
|
||||
|
||||
/**
|
||||
* main AAC context
|
||||
*/
|
||||
struct AACContext {
|
||||
AVClass *class;
|
||||
AVCodecContext *avctx;
|
||||
AVFrame *frame;
|
||||
|
||||
int is_saved; ///< Set if elements have stored overlap from previous frame.
|
||||
DynamicRangeControl che_drc;
|
||||
|
||||
/**
|
||||
* @name Channel element related data
|
||||
* @{
|
||||
*/
|
||||
ChannelElement *che[4][MAX_ELEM_ID];
|
||||
ChannelElement *tag_che_map[4][MAX_ELEM_ID];
|
||||
int tags_mapped;
|
||||
int warned_remapping_once;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name temporary aligned temporary buffers
|
||||
* (We do not want to have these on the stack.)
|
||||
* @{
|
||||
*/
|
||||
DECLARE_ALIGNED(32, INTFLOAT, buf_mdct)[1024];
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Computed / set up during initialization
|
||||
* @{
|
||||
*/
|
||||
AVTXContext *mdct120;
|
||||
AVTXContext *mdct128;
|
||||
AVTXContext *mdct480;
|
||||
AVTXContext *mdct512;
|
||||
AVTXContext *mdct960;
|
||||
AVTXContext *mdct1024;
|
||||
AVTXContext *mdct_ltp;
|
||||
|
||||
av_tx_fn mdct120_fn;
|
||||
av_tx_fn mdct128_fn;
|
||||
av_tx_fn mdct480_fn;
|
||||
av_tx_fn mdct512_fn;
|
||||
av_tx_fn mdct960_fn;
|
||||
av_tx_fn mdct1024_fn;
|
||||
av_tx_fn mdct_ltp_fn;
|
||||
#if USE_FIXED
|
||||
AVFixedDSPContext *fdsp;
|
||||
#else
|
||||
AVFloatDSPContext *fdsp;
|
||||
#endif /* USE_FIXED */
|
||||
int random_state;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Members used for output
|
||||
* @{
|
||||
*/
|
||||
SingleChannelElement *output_element[MAX_CHANNELS]; ///< Points to each SingleChannelElement
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @name Japanese DTV specific extension
|
||||
* @{
|
||||
*/
|
||||
int force_dmono_mode;///< 0->not dmono, 1->use first channel, 2->use second channel
|
||||
int dmono_mode; ///< 0->not dmono, 1->use first channel, 2->use second channel
|
||||
/** @} */
|
||||
|
||||
enum AACOutputChannelOrder output_channel_order;
|
||||
|
||||
DECLARE_ALIGNED(32, INTFLOAT, temp)[128];
|
||||
|
||||
OutputConfiguration oc[2];
|
||||
int warned_num_aac_frames;
|
||||
int warned_960_sbr;
|
||||
unsigned warned_71_wide;
|
||||
int warned_gain_control;
|
||||
int warned_he_aac_mono;
|
||||
|
||||
/* aacdec functions pointers */
|
||||
void (*imdct_and_windowing)(AACContext *ac, SingleChannelElement *sce);
|
||||
void (*apply_ltp)(AACContext *ac, SingleChannelElement *sce);
|
||||
void (*apply_tns)(INTFLOAT coef[1024], TemporalNoiseShaping *tns,
|
||||
IndividualChannelStream *ics, int decode);
|
||||
void (*windowing_and_mdct_ltp)(AACContext *ac, INTFLOAT *out,
|
||||
INTFLOAT *in, IndividualChannelStream *ics);
|
||||
void (*update_ltp)(AACContext *ac, SingleChannelElement *sce);
|
||||
void (*vector_pow43)(int *coefs, int len);
|
||||
void (*subband_scale)(int *dst, int *src, int scale, int offset, int len, void *log_context);
|
||||
|
||||
};
|
||||
|
||||
void ff_aacdec_init_mips(AACContext *c);
|
||||
|
||||
#endif /* AVCODEC_AAC_H */
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
clean::
|
||||
$(RM) $(CLEANSUFFIXES:%=libavcodec/aac/%)
|
||||
|
||||
OBJS-$(CONFIG_AAC_DECODER) += aac/aacdec.o aac/aacdec_tab.o \
|
||||
aac/aacdec_float.o aac/aacdec_usac.o \
|
||||
aac/aacdec_ac.o aac/aacdec_lpd.o
|
||||
OBJS-$(CONFIG_AAC_FIXED_DECODER) += aac/aacdec.o aac/aacdec_tab.o \
|
||||
aac/aacdec_fixed.o
|
||||
@@ -1,562 +0,0 @@
|
||||
/*
|
||||
* AAC decoder definitions and structures
|
||||
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
|
||||
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* AAC decoder definitions and structures
|
||||
* @author Oded Shimon ( ods15 ods15 dyndns org )
|
||||
* @author Maxim Gavrilov ( maxim.gavrilov gmail com )
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_AAC_AACDEC_H
|
||||
#define AVCODEC_AAC_AACDEC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/float_dsp.h"
|
||||
#include "libavutil/fixed_dsp.h"
|
||||
#include "libavutil/mem_internal.h"
|
||||
#include "libavutil/tx.h"
|
||||
|
||||
#include "libavcodec/aac.h"
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavcodec/mpeg4audio.h"
|
||||
|
||||
#include "aacdec_ac.h"
|
||||
|
||||
typedef struct AACDecContext AACDecContext;
|
||||
|
||||
/**
|
||||
* Output configuration status
|
||||
*/
|
||||
enum OCStatus {
|
||||
OC_NONE, ///< Output unconfigured
|
||||
OC_TRIAL_PCE, ///< Output configuration under trial specified by an inband PCE
|
||||
OC_TRIAL_FRAME, ///< Output configuration under trial specified by a frame header
|
||||
OC_GLOBAL_HDR, ///< Output configuration set in a global header but not yet locked
|
||||
OC_LOCKED, ///< Output configuration locked in place
|
||||
};
|
||||
|
||||
enum AACOutputChannelOrder {
|
||||
CHANNEL_ORDER_DEFAULT,
|
||||
CHANNEL_ORDER_CODED,
|
||||
};
|
||||
|
||||
/**
|
||||
* The point during decoding at which channel coupling is applied.
|
||||
*/
|
||||
enum CouplingPoint {
|
||||
BEFORE_TNS,
|
||||
BETWEEN_TNS_AND_IMDCT,
|
||||
AFTER_IMDCT = 3,
|
||||
};
|
||||
|
||||
enum AACUsacElem {
|
||||
ID_USAC_SCE = 0,
|
||||
ID_USAC_CPE = 1,
|
||||
ID_USAC_LFE = 2,
|
||||
ID_USAC_EXT = 3,
|
||||
};
|
||||
|
||||
enum ExtensionHeaderType {
|
||||
ID_CONFIG_EXT_FILL = 0,
|
||||
ID_CONFIG_EXT_LOUDNESS_INFO = 2,
|
||||
ID_CONFIG_EXT_STREAM_ID = 7,
|
||||
};
|
||||
|
||||
enum AACUsacExtension {
|
||||
ID_EXT_ELE_FILL,
|
||||
ID_EXT_ELE_MPEGS,
|
||||
ID_EXT_ELE_SAOC,
|
||||
ID_EXT_ELE_AUDIOPREROLL,
|
||||
ID_EXT_ELE_UNI_DRC,
|
||||
};
|
||||
|
||||
enum AACUSACLoudnessExt {
|
||||
UNIDRCLOUDEXT_TERM = 0x0,
|
||||
UNIDRCLOUDEXT_EQ = 0x1,
|
||||
};
|
||||
|
||||
// Supposed to be equal to AAC_RENAME() in case of USE_FIXED.
|
||||
#define RENAME_FIXED(name) name ## _fixed
|
||||
|
||||
#define INTFLOAT_UNION(name, elems) \
|
||||
union { \
|
||||
int RENAME_FIXED(name) elems; \
|
||||
float name elems; \
|
||||
}
|
||||
|
||||
#define INTFLOAT_ALIGNED_UNION(alignment, name, nb_elems) \
|
||||
union { \
|
||||
DECLARE_ALIGNED(alignment, int, RENAME_FIXED(name))[nb_elems]; \
|
||||
DECLARE_ALIGNED(alignment, float, name)[nb_elems]; \
|
||||
}
|
||||
/**
|
||||
* Long Term Prediction
|
||||
*/
|
||||
typedef struct LongTermPrediction {
|
||||
int8_t present;
|
||||
int16_t lag;
|
||||
INTFLOAT_UNION(coef,);
|
||||
int8_t used[MAX_LTP_LONG_SFB];
|
||||
} LongTermPrediction;
|
||||
|
||||
/* Per channel core mode */
|
||||
typedef struct AACUsacElemData {
|
||||
uint8_t core_mode;
|
||||
uint8_t scale_factor_grouping;
|
||||
uint8_t tns_data_present;
|
||||
|
||||
/* Timewarping ratio */
|
||||
#define NUM_TW_NODES 16
|
||||
uint8_t tw_ratio[NUM_TW_NODES];
|
||||
|
||||
struct {
|
||||
uint8_t acelp_core_mode : 3;
|
||||
uint8_t lpd_mode : 5;
|
||||
|
||||
uint8_t bpf_control_info : 1;
|
||||
uint8_t core_mode_last : 1;
|
||||
uint8_t fac_data_present : 1;
|
||||
|
||||
int last_lpd_mode;
|
||||
} ldp;
|
||||
|
||||
struct {
|
||||
unsigned int seed;
|
||||
uint8_t level : 3;
|
||||
uint8_t offset : 5;
|
||||
} noise;
|
||||
|
||||
struct {
|
||||
uint8_t gain;
|
||||
uint32_t kv[8 /* (1024 / 16) / 8 */][8];
|
||||
} fac;
|
||||
|
||||
AACArithState ac;
|
||||
} AACUsacElemData;
|
||||
|
||||
/**
|
||||
* Individual Channel Stream
|
||||
*/
|
||||
typedef struct IndividualChannelStream {
|
||||
uint8_t max_sfb; ///< number of scalefactor bands per group
|
||||
enum WindowSequence window_sequence[2];
|
||||
uint8_t use_kb_window[2]; ///< If set, use Kaiser-Bessel window, otherwise use a sine window.
|
||||
int num_window_groups;
|
||||
int prev_num_window_groups; ///< Previous frame's number of window groups
|
||||
uint8_t group_len[8];
|
||||
LongTermPrediction ltp;
|
||||
const uint16_t *swb_offset; ///< table of offsets to the lowest spectral coefficient of a scalefactor band, sfb, for a particular window
|
||||
int num_swb; ///< number of scalefactor window bands
|
||||
int num_windows;
|
||||
int tns_max_bands;
|
||||
int predictor_present;
|
||||
int predictor_initialized;
|
||||
int predictor_reset_group;
|
||||
uint8_t prediction_used[41];
|
||||
uint8_t window_clipping[8]; ///< set if a certain window is near clipping
|
||||
} IndividualChannelStream;
|
||||
|
||||
/**
|
||||
* Temporal Noise Shaping
|
||||
*/
|
||||
typedef struct TemporalNoiseShaping {
|
||||
int present;
|
||||
int n_filt[8];
|
||||
int length[8][4];
|
||||
int direction[8][4];
|
||||
int order[8][4];
|
||||
INTFLOAT_UNION(coef, [8][4][TNS_MAX_ORDER]);
|
||||
} TemporalNoiseShaping;
|
||||
|
||||
/**
|
||||
* coupling parameters
|
||||
*/
|
||||
typedef struct ChannelCoupling {
|
||||
enum CouplingPoint coupling_point; ///< The point during decoding at which coupling is applied.
|
||||
int num_coupled; ///< number of target elements
|
||||
enum RawDataBlockType type[8]; ///< Type of channel element to be coupled - SCE or CPE.
|
||||
int id_select[8]; ///< element id
|
||||
int ch_select[8]; /**< [0] shared list of gains; [1] list of gains for right channel;
|
||||
* [2] list of gains for left channel; [3] lists of gains for both channels
|
||||
*/
|
||||
INTFLOAT_UNION(gain, [16][120]);
|
||||
} ChannelCoupling;
|
||||
|
||||
/**
|
||||
* Single Channel Element - used for both SCE and LFE elements.
|
||||
*/
|
||||
typedef struct SingleChannelElement {
|
||||
IndividualChannelStream ics;
|
||||
AACUsacElemData ue; ///< USAC element data
|
||||
TemporalNoiseShaping tns;
|
||||
enum BandType band_type[128]; ///< band types
|
||||
int sfo[128]; ///< scalefactor offsets
|
||||
INTFLOAT_UNION(sf, [128]); ///< scalefactors (8 windows * 16 sfb max)
|
||||
INTFLOAT_ALIGNED_UNION(32, coeffs, 1024); ///< coefficients for IMDCT, maybe processed
|
||||
INTFLOAT_ALIGNED_UNION(32, prev_coeffs, 1024); ///< unscaled previous contents of coeffs[] for USAC
|
||||
INTFLOAT_ALIGNED_UNION(32, saved, 1536); ///< overlap
|
||||
INTFLOAT_ALIGNED_UNION(32, ret_buf, 2048); ///< PCM output buffer
|
||||
INTFLOAT_ALIGNED_UNION(16, ltp_state, 3072); ///< time signal for LTP
|
||||
union {
|
||||
struct PredictorStateFixed *RENAME_FIXED(predictor_state);
|
||||
struct PredictorState *predictor_state;
|
||||
};
|
||||
union {
|
||||
float *output; ///< PCM output
|
||||
int *RENAME_FIXED(output); ///< PCM output
|
||||
};
|
||||
} SingleChannelElement;
|
||||
|
||||
typedef struct AACUsacStereo {
|
||||
uint8_t common_window;
|
||||
uint8_t common_tw;
|
||||
uint8_t tns_on_lr; ///< Apply TNS before M/S and stereo prediction
|
||||
|
||||
uint8_t ms_mask_mode;
|
||||
uint8_t config_idx;
|
||||
|
||||
/* Complex prediction */
|
||||
uint8_t use_prev_frame;
|
||||
uint8_t pred_dir;
|
||||
uint8_t complex_coef;
|
||||
|
||||
uint8_t pred_used[128];
|
||||
|
||||
INTFLOAT_ALIGNED_UNION(32, alpha_q_re, 1024);
|
||||
INTFLOAT_ALIGNED_UNION(32, alpha_q_im, 1024);
|
||||
INTFLOAT_ALIGNED_UNION(32, prev_alpha_q_re, 1024);
|
||||
INTFLOAT_ALIGNED_UNION(32, prev_alpha_q_im, 1024);
|
||||
|
||||
INTFLOAT_ALIGNED_UNION(32, dmix_re, 1024);
|
||||
INTFLOAT_ALIGNED_UNION(32, prev_dmix_re, 1024); /* Recalculated on every frame */
|
||||
INTFLOAT_ALIGNED_UNION(32, dmix_im, 1024); /* Final prediction data */
|
||||
} AACUsacStereo;
|
||||
|
||||
/**
|
||||
* channel element - generic struct for SCE/CPE/CCE/LFE
|
||||
*/
|
||||
typedef struct ChannelElement {
|
||||
int present;
|
||||
// CPE specific
|
||||
uint8_t max_sfb_ste; ///< (USAC) Maximum of both max_sfb values
|
||||
uint8_t ms_mask[128]; ///< Set if mid/side stereo is used for each scalefactor window band
|
||||
// shared
|
||||
SingleChannelElement ch[2];
|
||||
// CCE specific
|
||||
ChannelCoupling coup;
|
||||
// USAC stereo coupling data
|
||||
AACUsacStereo us;
|
||||
} ChannelElement;
|
||||
|
||||
typedef struct AACUSACLoudnessInfo {
|
||||
uint8_t drc_set_id : 6;
|
||||
uint8_t downmix_id : 7;
|
||||
struct {
|
||||
uint16_t lvl : 12;
|
||||
uint8_t present : 1;
|
||||
} sample_peak;
|
||||
|
||||
struct {
|
||||
uint16_t lvl : 12;
|
||||
uint8_t measurement : 4;
|
||||
uint8_t reliability : 2;
|
||||
uint8_t present : 1;
|
||||
} true_peak;
|
||||
|
||||
uint8_t nb_measurements : 4;
|
||||
struct {
|
||||
uint8_t method_def : 4;
|
||||
uint8_t method_val;
|
||||
uint8_t measurement : 4;
|
||||
uint8_t reliability : 2;
|
||||
} measurements[16];
|
||||
} AACUSACLoudnessInfo;
|
||||
|
||||
typedef struct AACUsacElemConfig {
|
||||
enum AACUsacElem type;
|
||||
|
||||
uint8_t tw_mdct : 1;
|
||||
uint8_t noise_fill : 1;
|
||||
|
||||
uint8_t stereo_config_index;
|
||||
|
||||
struct {
|
||||
int ratio;
|
||||
|
||||
uint8_t harmonic_sbr : 1; /* harmonicSBR */
|
||||
uint8_t bs_intertes : 1; /* bs_interTes */
|
||||
uint8_t bs_pvc : 1; /* bs_pvc */
|
||||
|
||||
struct {
|
||||
uint8_t start_freq; /* dflt_start_freq */
|
||||
uint8_t stop_freq; /* dflt_stop_freq */
|
||||
|
||||
uint8_t freq_scale; /* dflt_freq_scale */
|
||||
uint8_t alter_scale : 1; /* dflt_alter_scale */
|
||||
uint8_t noise_bands; /* dflt_noise_bands */
|
||||
|
||||
uint8_t limiter_bands; /* dflt_limiter_bands */
|
||||
uint8_t limiter_gains; /* dflt_limiter_gains */
|
||||
uint8_t interpol_freq : 1; /* dflt_interpol_freq */
|
||||
uint8_t smoothing_mode : 1; /* dflt_smoothing_mode */
|
||||
} dflt;
|
||||
} sbr;
|
||||
|
||||
struct {
|
||||
uint8_t freq_res; /* bsFreqRes */
|
||||
uint8_t fixed_gain; /* bsFixedGainDMX */
|
||||
uint8_t temp_shape_config; /* bsTempShapeConfig */
|
||||
uint8_t decorr_config; /* bsDecorrConfig */
|
||||
uint8_t high_rate_mode : 1; /* bsHighRateMode */
|
||||
uint8_t phase_coding : 1; /* bsPhaseCoding */
|
||||
|
||||
uint8_t otts_bands_phase; /* bsOttBandsPhase */
|
||||
uint8_t residual_coding; /* bsResidualCoding */
|
||||
uint8_t residual_bands; /* bsResidualBands */
|
||||
uint8_t pseudo_lr : 1; /* bsPseudoLr */
|
||||
uint8_t env_quant_mode : 1; /* bsEnvQuantMode */
|
||||
} mps;
|
||||
|
||||
struct {
|
||||
enum AACUsacExtension type;
|
||||
uint8_t payload_frag;
|
||||
uint32_t default_len;
|
||||
uint32_t pl_data_offset;
|
||||
uint8_t *pl_data;
|
||||
} ext;
|
||||
} AACUsacElemConfig;
|
||||
|
||||
typedef struct AACUSACConfig {
|
||||
uint8_t core_sbr_frame_len_idx; /* coreSbrFrameLengthIndex */
|
||||
uint16_t core_frame_len;
|
||||
uint16_t stream_identifier;
|
||||
|
||||
AACUsacElemConfig elems[64];
|
||||
int nb_elems;
|
||||
|
||||
struct {
|
||||
uint8_t nb_album;
|
||||
AACUSACLoudnessInfo album_info[64];
|
||||
uint8_t nb_info;
|
||||
AACUSACLoudnessInfo info[64];
|
||||
} loudness;
|
||||
} AACUSACConfig;
|
||||
|
||||
typedef struct OutputConfiguration {
|
||||
MPEG4AudioConfig m4ac;
|
||||
uint8_t layout_map[MAX_ELEM_ID*4][3];
|
||||
int layout_map_tags;
|
||||
AVChannelLayout ch_layout;
|
||||
enum OCStatus status;
|
||||
AACUSACConfig usac;
|
||||
} OutputConfiguration;
|
||||
|
||||
/**
|
||||
* Dynamic Range Control - decoded from the bitstream but not processed further.
|
||||
*/
|
||||
typedef struct DynamicRangeControl {
|
||||
int pce_instance_tag; ///< Indicates with which program the DRC info is associated.
|
||||
int dyn_rng_sgn[17]; ///< DRC sign information; 0 - positive, 1 - negative
|
||||
int dyn_rng_ctl[17]; ///< DRC magnitude information
|
||||
int exclude_mask[MAX_CHANNELS]; ///< Channels to be excluded from DRC processing.
|
||||
int band_incr; ///< Number of DRC bands greater than 1 having DRC info.
|
||||
int interpolation_scheme; ///< Indicates the interpolation scheme used in the SBR QMF domain.
|
||||
int band_top[17]; ///< Indicates the top of the i-th DRC band in units of 4 spectral lines.
|
||||
int prog_ref_level; /**< A reference level for the long-term program audio level for all
|
||||
* channels combined.
|
||||
*/
|
||||
} DynamicRangeControl;
|
||||
|
||||
/**
|
||||
* Decode-specific primitives
|
||||
*/
|
||||
typedef struct AACDecProc {
|
||||
int (*decode_spectrum_and_dequant)(AACDecContext *ac,
|
||||
GetBitContext *gb,
|
||||
const Pulse *pulse,
|
||||
SingleChannelElement *sce);
|
||||
|
||||
int (*decode_cce)(AACDecContext *ac, GetBitContext *gb, ChannelElement *che);
|
||||
|
||||
int (*sbr_ctx_alloc_init)(AACDecContext *ac, ChannelElement **che, int id_aac);
|
||||
int (*sbr_decode_extension)(AACDecContext *ac, ChannelElement *che,
|
||||
GetBitContext *gb, int crc, int cnt, int id_aac);
|
||||
void (*sbr_apply)(AACDecContext *ac, ChannelElement *che,
|
||||
int id_aac, void /* INTFLOAT */ *L, void /* INTFLOAT */ *R);
|
||||
void (*sbr_ctx_close)(ChannelElement *che);
|
||||
} AACDecProc;
|
||||
|
||||
/**
|
||||
* DSP-specific primitives
|
||||
*/
|
||||
typedef struct AACDecDSP {
|
||||
void (*dequant_scalefactors)(SingleChannelElement *sce);
|
||||
|
||||
void (*apply_mid_side_stereo)(AACDecContext *ac, ChannelElement *cpe);
|
||||
void (*apply_intensity_stereo)(AACDecContext *ac, ChannelElement *cpe,
|
||||
int ms_present);
|
||||
|
||||
void (*apply_tns)(void *_coef_param, TemporalNoiseShaping *tns,
|
||||
IndividualChannelStream *ics, int decode);
|
||||
|
||||
void (*apply_ltp)(AACDecContext *ac, SingleChannelElement *sce);
|
||||
void (*update_ltp)(AACDecContext *ac, SingleChannelElement *sce);
|
||||
|
||||
void (*apply_prediction)(AACDecContext *ac, SingleChannelElement *sce);
|
||||
|
||||
void (*apply_dependent_coupling)(AACDecContext *ac,
|
||||
SingleChannelElement *target,
|
||||
ChannelElement *cce, int index);
|
||||
void (*apply_independent_coupling)(AACDecContext *ac,
|
||||
SingleChannelElement *target,
|
||||
ChannelElement *cce, int index);
|
||||
|
||||
void (*imdct_and_windowing)(AACDecContext *ac, SingleChannelElement *sce);
|
||||
void (*imdct_and_windowing_768)(AACDecContext *ac, SingleChannelElement *sce);
|
||||
void (*imdct_and_windowing_960)(AACDecContext *ac, SingleChannelElement *sce);
|
||||
void (*imdct_and_windowing_ld)(AACDecContext *ac, SingleChannelElement *sce);
|
||||
void (*imdct_and_windowing_eld)(AACDecContext *ac, SingleChannelElement *sce);
|
||||
|
||||
void (*clip_output)(AACDecContext *ac, ChannelElement *che, int type, int samples);
|
||||
} AACDecDSP;
|
||||
|
||||
/**
|
||||
* main AAC decoding context
|
||||
*/
|
||||
struct AACDecContext {
|
||||
const struct AVClass *class;
|
||||
struct AVCodecContext *avctx;
|
||||
|
||||
AACDecDSP dsp;
|
||||
AACDecProc proc;
|
||||
|
||||
struct AVFrame *frame;
|
||||
|
||||
int is_saved; ///< Set if elements have stored overlap from previous frame.
|
||||
DynamicRangeControl che_drc;
|
||||
|
||||
/**
|
||||
* @name Channel element related data
|
||||
* @{
|
||||
*/
|
||||
ChannelElement *che[4][MAX_ELEM_ID];
|
||||
ChannelElement *tag_che_map[4][MAX_ELEM_ID];
|
||||
int tags_mapped;
|
||||
int warned_remapping_once;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name temporary aligned temporary buffers
|
||||
* (We do not want to have these on the stack.)
|
||||
* @{
|
||||
*/
|
||||
INTFLOAT_ALIGNED_UNION(32, buf_mdct, 1024);
|
||||
INTFLOAT_ALIGNED_UNION(32, temp, 128);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Computed / set up during initialization
|
||||
* @{
|
||||
*/
|
||||
AVTXContext *mdct96;
|
||||
AVTXContext *mdct120;
|
||||
AVTXContext *mdct128;
|
||||
AVTXContext *mdct480;
|
||||
AVTXContext *mdct512;
|
||||
AVTXContext *mdct768;
|
||||
AVTXContext *mdct960;
|
||||
AVTXContext *mdct1024;
|
||||
AVTXContext *mdct_ltp;
|
||||
|
||||
av_tx_fn mdct96_fn;
|
||||
av_tx_fn mdct120_fn;
|
||||
av_tx_fn mdct128_fn;
|
||||
av_tx_fn mdct480_fn;
|
||||
av_tx_fn mdct512_fn;
|
||||
av_tx_fn mdct768_fn;
|
||||
av_tx_fn mdct960_fn;
|
||||
av_tx_fn mdct1024_fn;
|
||||
av_tx_fn mdct_ltp_fn;
|
||||
union {
|
||||
AVFixedDSPContext *RENAME_FIXED(fdsp);
|
||||
AVFloatDSPContext *fdsp;
|
||||
};
|
||||
int random_state;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Members used for output
|
||||
* @{
|
||||
*/
|
||||
SingleChannelElement *output_element[MAX_CHANNELS]; ///< Points to each SingleChannelElement
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @name Japanese DTV specific extension
|
||||
* @{
|
||||
*/
|
||||
int force_dmono_mode;///< 0->not dmono, 1->use first channel, 2->use second channel
|
||||
int dmono_mode; ///< 0->not dmono, 1->use first channel, 2->use second channel
|
||||
/** @} */
|
||||
|
||||
enum AACOutputChannelOrder output_channel_order;
|
||||
|
||||
OutputConfiguration oc[2];
|
||||
int warned_num_aac_frames;
|
||||
int warned_960_sbr;
|
||||
unsigned warned_71_wide;
|
||||
int warned_gain_control;
|
||||
int warned_he_aac_mono;
|
||||
|
||||
int is_fixed;
|
||||
};
|
||||
|
||||
#if defined(USE_FIXED) && USE_FIXED
|
||||
#define fdsp RENAME_FIXED(fdsp)
|
||||
#endif
|
||||
|
||||
int ff_aac_decode_init(AVCodecContext *avctx);
|
||||
int ff_aac_decode_init_float(AVCodecContext *avctx);
|
||||
int ff_aac_decode_init_fixed(AVCodecContext *avctx);
|
||||
|
||||
int ff_aac_decode_ics(AACDecContext *ac, SingleChannelElement *sce,
|
||||
GetBitContext *gb, int common_window, int scale_flag);
|
||||
|
||||
int ff_aac_decode_tns(AACDecContext *ac, TemporalNoiseShaping *tns,
|
||||
GetBitContext *gb, const IndividualChannelStream *ics);
|
||||
|
||||
int ff_aac_set_default_channel_config(AACDecContext *ac, AVCodecContext *avctx,
|
||||
uint8_t (*layout_map)[3],
|
||||
int *tags,
|
||||
int channel_config);
|
||||
|
||||
int ff_aac_output_configure(AACDecContext *ac,
|
||||
uint8_t layout_map[MAX_ELEM_ID * 4][3], int tags,
|
||||
enum OCStatus oc_type, int get_new_frame);
|
||||
|
||||
ChannelElement *ff_aac_get_che(AACDecContext *ac, int type, int elem_id);
|
||||
|
||||
#endif /* AVCODEC_AAC_AACDEC_H */
|
||||
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
* AAC definitions and structures
|
||||
* Copyright (c) 2024 Lynne
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* 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/aactab.h"
|
||||
#include "aacdec_ac.h"
|
||||
|
||||
uint32_t ff_aac_ac_map_process(AACArithState *state, int reset, int N)
|
||||
{
|
||||
float ratio;
|
||||
if (reset) {
|
||||
memset(state->last, 0, sizeof(state->last));
|
||||
state->last_len = N;
|
||||
} else if (state->last_len != N) {
|
||||
int i;
|
||||
uint8_t last[512 /* 2048 / 4 */];
|
||||
memcpy(last, state->last, sizeof(last));
|
||||
|
||||
ratio = state->last_len / (float)N;
|
||||
for (i = 0; i < N/2; i++) {
|
||||
int k = (int)(i * ratio);
|
||||
state->last[i] = last[k];
|
||||
}
|
||||
|
||||
for (; i < FF_ARRAY_ELEMS(state->last); i++)
|
||||
state->last[i] = 0;
|
||||
|
||||
state->last_len = N;
|
||||
}
|
||||
|
||||
state->cur[3] = 0;
|
||||
state->cur[2] = 0;
|
||||
state->cur[1] = 0;
|
||||
state->cur[0] = 1;
|
||||
|
||||
state->state_pre = state->last[0] << 12;
|
||||
return state->last[0] << 12;
|
||||
}
|
||||
|
||||
uint32_t ff_aac_ac_get_context(AACArithState *state, uint32_t c, int i, int N)
|
||||
{
|
||||
c = state->state_pre >> 8;
|
||||
c = c + (state->last[i + 1] << 8);
|
||||
c = (c << 4);
|
||||
c += state->cur[1];
|
||||
|
||||
state->state_pre = c;
|
||||
|
||||
if (i > 3 &&
|
||||
((state->cur[3] + state->cur[2] + state->cur[1]) < 5))
|
||||
return c + 0x10000;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t ff_aac_ac_get_pk(uint32_t c)
|
||||
{
|
||||
int i_min = -1;
|
||||
int i, j;
|
||||
int i_max = FF_ARRAY_ELEMS(ff_aac_ac_lookup_m) - 1;
|
||||
while ((i_max - i_min) > 1) {
|
||||
i = i_min + ((i_max - i_min) / 2);
|
||||
j = ff_aac_ac_hash_m[i];
|
||||
if (c < (j >> 8))
|
||||
i_max = i;
|
||||
else if (c > (j >> 8))
|
||||
i_min = i;
|
||||
else
|
||||
return (j & 0xFF);
|
||||
}
|
||||
return ff_aac_ac_lookup_m[i_max];
|
||||
}
|
||||
|
||||
void ff_aac_ac_update_context(AACArithState *state, int idx,
|
||||
uint16_t a, uint16_t b)
|
||||
{
|
||||
state->cur[0] = a + b + 1;
|
||||
if (state->cur[0] > 0xF)
|
||||
state->cur[0] = 0xF;
|
||||
|
||||
state->cur[3] = state->cur[2];
|
||||
state->cur[2] = state->cur[1];
|
||||
state->cur[1] = state->cur[0];
|
||||
|
||||
state->last[idx] = state->cur[0];
|
||||
}
|
||||
|
||||
/* Initialize AC */
|
||||
void ff_aac_ac_init(AACArith *ac, GetBitContext *gb)
|
||||
{
|
||||
ac->low = 0;
|
||||
ac->high = UINT16_MAX;
|
||||
ac->val = get_bits(gb, 16);
|
||||
}
|
||||
|
||||
uint16_t ff_aac_ac_decode(AACArith *ac, GetBitContext *gb,
|
||||
const uint16_t *cdf, uint16_t cdf_len)
|
||||
{
|
||||
int val = ac->val;
|
||||
int low = ac->low;
|
||||
int high = ac->high;
|
||||
|
||||
int sym;
|
||||
int rng = high - low + 1;
|
||||
int c = ((((int)(val - low + 1)) << 14) - ((int)1));
|
||||
|
||||
const uint16_t *p = cdf - 1;
|
||||
|
||||
/* One for each possible CDF length in the spec */
|
||||
switch (cdf_len) {
|
||||
case 2:
|
||||
if ((p[1] * rng) > c)
|
||||
p += 1;
|
||||
break;
|
||||
case 4:
|
||||
if ((p[2] * rng) > c)
|
||||
p += 2;
|
||||
if ((p[1] * rng) > c)
|
||||
p += 1;
|
||||
break;
|
||||
case 17:
|
||||
/* First check if the current probability is even met at all */
|
||||
if ((p[1] * rng) <= c)
|
||||
break;
|
||||
p += 1;
|
||||
for (int i = 8; i >= 1; i >>= 1)
|
||||
if ((p[i] * rng) > c)
|
||||
p += i;
|
||||
break;
|
||||
case 27:
|
||||
if ((p[16] * rng) > c)
|
||||
p += 16;
|
||||
if ((p[8] * rng) > c)
|
||||
p += 8;
|
||||
if (p != (cdf - 1 + 24))
|
||||
if ((p[4] * rng) > c)
|
||||
p += 4;
|
||||
if ((p[2] * rng) > c)
|
||||
p += 2;
|
||||
|
||||
if (p != (cdf - 1 + 24 + 2))
|
||||
if ((p[1] * rng) > c)
|
||||
p += 1;
|
||||
break;
|
||||
default:
|
||||
/* This should never happen */
|
||||
av_assert2(0);
|
||||
}
|
||||
|
||||
sym = (int)((ptrdiff_t)(p - cdf)) + 1;
|
||||
if (sym)
|
||||
high = low + ((rng * cdf[sym - 1]) >> 14) - 1;
|
||||
low += (rng * cdf[sym]) >> 14;
|
||||
|
||||
/* This loop could be done faster */
|
||||
while (1) {
|
||||
if (high < 32768) {
|
||||
;
|
||||
} else if (low >= 32768) {
|
||||
val -= 32768;
|
||||
low -= 32768;
|
||||
high -= 32768;
|
||||
} else if (low >= 16384 && high < 49152) {
|
||||
val -= 16384;
|
||||
low -= 16384;
|
||||
high -= 16384;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
low += low;
|
||||
high += high + 1;
|
||||
val = (val << 1) | get_bits1(gb);
|
||||
};
|
||||
|
||||
ac->low = low;
|
||||
ac->high = high;
|
||||
ac->val = val;
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
void ff_aac_ac_finish(AACArithState *state, int offset, int N)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = offset; i < N/2; i++)
|
||||
state->last[i] = 1;
|
||||
|
||||
for (; i < FF_ARRAY_ELEMS(state->last); i++)
|
||||
state->last[i] = 0;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* AAC definitions and structures
|
||||
* Copyright (c) 2024 Lynne
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_AAC_AACDEC_AC_H
|
||||
#define AVCODEC_AAC_AACDEC_AC_H
|
||||
|
||||
#include "libavcodec/get_bits.h"
|
||||
|
||||
typedef struct AACArithState {
|
||||
uint8_t last[512 /* 2048 / 4 */ + 1];
|
||||
int last_len;
|
||||
uint8_t cur[4];
|
||||
uint16_t state_pre;
|
||||
} AACArithState;
|
||||
|
||||
typedef struct AACArith {
|
||||
uint16_t low;
|
||||
uint16_t high;
|
||||
uint16_t val;
|
||||
} AACArith;
|
||||
|
||||
#define FF_AAC_AC_ESCAPE 16
|
||||
|
||||
uint32_t ff_aac_ac_map_process(AACArithState *state, int reset, int len);
|
||||
uint32_t ff_aac_ac_get_context(AACArithState *state, uint32_t old_c, int idx, int len);
|
||||
uint32_t ff_aac_ac_get_pk(uint32_t c);
|
||||
|
||||
void ff_aac_ac_update_context(AACArithState *state, int idx, uint16_t a, uint16_t b);
|
||||
void ff_aac_ac_init(AACArith *ac, GetBitContext *gb);
|
||||
|
||||
uint16_t ff_aac_ac_decode(AACArith *ac, GetBitContext *gb,
|
||||
const uint16_t *cdf, uint16_t cdf_len);
|
||||
|
||||
void ff_aac_ac_finish(AACArithState *state, int offset, int nb);
|
||||
|
||||
#endif /* AVCODEC_AACDEC_AC_H */
|
||||
@@ -1,688 +0,0 @@
|
||||
/*
|
||||
* AAC decoder
|
||||
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
|
||||
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
|
||||
* Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
|
||||
*
|
||||
* AAC LATM decoder
|
||||
* Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
|
||||
* Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
|
||||
*
|
||||
* AAC decoder fixed-point implementation
|
||||
* Copyright (c) 2013
|
||||
* MIPS Technologies, Inc., California.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "aacdec.h"
|
||||
#include "libavcodec/lpc_functions.h"
|
||||
|
||||
#include "libavcodec/aactab.h"
|
||||
|
||||
/**
|
||||
* Convert integer scalefactors to the decoder's native expected
|
||||
* scalefactor values.
|
||||
*/
|
||||
static void AAC_RENAME(dequant_scalefactors)(SingleChannelElement *sce)
|
||||
{
|
||||
IndividualChannelStream *ics = &sce->ics;
|
||||
const int *sfo = sce->sfo;
|
||||
INTFLOAT *sf = sce->AAC_RENAME(sf);
|
||||
|
||||
int idx = 0;
|
||||
for (int g = 0; g < ics->num_window_groups; g++) {
|
||||
for (int sfb = 0; sfb < ics->max_sfb; sfb++, idx++) {
|
||||
switch (sce->band_type[g*ics->max_sfb + sfb]) {
|
||||
case ZERO_BT:
|
||||
sf[idx] = FIXR(0.);
|
||||
break;
|
||||
case INTENSITY_BT: /* fallthrough */
|
||||
case INTENSITY_BT2:
|
||||
#if USE_FIXED
|
||||
sf[idx] = 100 - (sfo[idx] + 100);
|
||||
#else
|
||||
sf[idx] = ff_aac_pow2sf_tab[-sfo[idx] - 100 + POW_SF2_ZERO];
|
||||
#endif /* USE_FIXED */
|
||||
break;
|
||||
case NOISE_BT:
|
||||
#if USE_FIXED
|
||||
sf[idx] = -(100 + sfo[idx]);
|
||||
#else
|
||||
sf[idx] = -ff_aac_pow2sf_tab[sfo[idx] + POW_SF2_ZERO];
|
||||
#endif /* USE_FIXED */
|
||||
break;
|
||||
default:
|
||||
#if USE_FIXED
|
||||
sf[idx] = -sfo[idx] - 100;
|
||||
#else
|
||||
sf[idx] = -ff_aac_pow2sf_tab[sfo[idx] + POW_SF2_ZERO];
|
||||
#endif /* USE_FIXED */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mid/Side stereo decoding; reference: 4.6.8.1.3.
|
||||
*/
|
||||
static void AAC_RENAME(apply_mid_side_stereo)(AACDecContext *ac, ChannelElement *cpe)
|
||||
{
|
||||
const IndividualChannelStream *ics = &cpe->ch[0].ics;
|
||||
INTFLOAT *ch0 = cpe->ch[0].AAC_RENAME(coeffs);
|
||||
INTFLOAT *ch1 = cpe->ch[1].AAC_RENAME(coeffs);
|
||||
const uint16_t *offsets = ics->swb_offset;
|
||||
for (int g = 0; g < ics->num_window_groups; g++) {
|
||||
for (int sfb = 0; sfb < cpe->max_sfb_ste; sfb++) {
|
||||
const int idx = g*cpe->max_sfb_ste + sfb;
|
||||
if (cpe->ms_mask[idx] &&
|
||||
cpe->ch[0].band_type[idx] < NOISE_BT &&
|
||||
cpe->ch[1].band_type[idx] < NOISE_BT) {
|
||||
for (int group = 0; group < ics->group_len[g]; group++)
|
||||
#if USE_FIXED
|
||||
ac->fdsp->butterflies_fixed(ch0 + group * 128 + offsets[sfb],
|
||||
ch1 + group * 128 + offsets[sfb],
|
||||
offsets[sfb+1] - offsets[sfb]);
|
||||
#else
|
||||
ac->fdsp->butterflies_float(ch0 + group * 128 + offsets[sfb],
|
||||
ch1 + group * 128 + offsets[sfb],
|
||||
offsets[sfb+1] - offsets[sfb]);
|
||||
#endif /* USE_FIXED */
|
||||
}
|
||||
}
|
||||
ch0 += ics->group_len[g] * 128;
|
||||
ch1 += ics->group_len[g] * 128;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* intensity stereo decoding; reference: 4.6.8.2.3
|
||||
*
|
||||
* @param ms_present Indicates mid/side stereo presence. [0] mask is all 0s;
|
||||
* [1] mask is decoded from bitstream; [2] mask is all 1s;
|
||||
* [3] reserved for scalable AAC
|
||||
*/
|
||||
static void AAC_RENAME(apply_intensity_stereo)(AACDecContext *ac,
|
||||
ChannelElement *cpe, int ms_present)
|
||||
{
|
||||
const IndividualChannelStream *ics = &cpe->ch[1].ics;
|
||||
SingleChannelElement *sce1 = &cpe->ch[1];
|
||||
INTFLOAT *coef0 = cpe->ch[0].AAC_RENAME(coeffs), *coef1 = cpe->ch[1].AAC_RENAME(coeffs);
|
||||
const uint16_t *offsets = ics->swb_offset;
|
||||
int c;
|
||||
INTFLOAT scale;
|
||||
for (int g = 0; g < ics->num_window_groups; g++) {
|
||||
for (int sfb = 0; sfb < ics->max_sfb; sfb++) {
|
||||
const int idx = g*ics->max_sfb + sfb;
|
||||
if (sce1->band_type[idx] == INTENSITY_BT ||
|
||||
sce1->band_type[idx] == INTENSITY_BT2) {
|
||||
c = -1 + 2 * (sce1->band_type[idx] - 14);
|
||||
if (ms_present)
|
||||
c *= 1 - 2 * cpe->ms_mask[idx];
|
||||
scale = c * sce1->AAC_RENAME(sf)[idx];
|
||||
for (int group = 0; group < ics->group_len[g]; group++)
|
||||
#if USE_FIXED
|
||||
subband_scale(coef1 + group * 128 + offsets[sfb],
|
||||
coef0 + group * 128 + offsets[sfb],
|
||||
scale,
|
||||
23,
|
||||
offsets[sfb + 1] - offsets[sfb], ac->avctx);
|
||||
#else
|
||||
ac->fdsp->vector_fmul_scalar(coef1 + group * 128 + offsets[sfb],
|
||||
coef0 + group * 128 + offsets[sfb],
|
||||
scale,
|
||||
offsets[sfb + 1] - offsets[sfb]);
|
||||
#endif /* USE_FIXED */
|
||||
}
|
||||
}
|
||||
coef0 += ics->group_len[g] * 128;
|
||||
coef1 += ics->group_len[g] * 128;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode Temporal Noise Shaping filter coefficients and apply all-pole filters; reference: 4.6.9.3.
|
||||
*
|
||||
* @param decode 1 if tool is used normally, 0 if tool is used in LTP.
|
||||
* @param coef spectral coefficients
|
||||
*/
|
||||
static void AAC_RENAME(apply_tns)(void *_coef_param, TemporalNoiseShaping *tns,
|
||||
IndividualChannelStream *ics, int decode)
|
||||
{
|
||||
const int mmm = FFMIN(ics->tns_max_bands, ics->max_sfb);
|
||||
int w, filt, m, i;
|
||||
int bottom, top, order, start, end, size, inc;
|
||||
INTFLOAT *coef_param = _coef_param;
|
||||
INTFLOAT lpc[TNS_MAX_ORDER];
|
||||
INTFLOAT tmp[TNS_MAX_ORDER+1];
|
||||
UINTFLOAT *coef = coef_param;
|
||||
|
||||
if(!mmm)
|
||||
return;
|
||||
|
||||
for (w = 0; w < ics->num_windows; w++) {
|
||||
bottom = ics->num_swb;
|
||||
for (filt = 0; filt < tns->n_filt[w]; filt++) {
|
||||
top = bottom;
|
||||
bottom = FFMAX(0, top - tns->length[w][filt]);
|
||||
order = tns->order[w][filt];
|
||||
if (order == 0)
|
||||
continue;
|
||||
|
||||
// tns_decode_coef
|
||||
compute_lpc_coefs(tns->AAC_RENAME(coef)[w][filt], order, lpc, 0, 0, 0);
|
||||
|
||||
start = ics->swb_offset[FFMIN(bottom, mmm)];
|
||||
end = ics->swb_offset[FFMIN( top, mmm)];
|
||||
if ((size = end - start) <= 0)
|
||||
continue;
|
||||
if (tns->direction[w][filt]) {
|
||||
inc = -1;
|
||||
start = end - 1;
|
||||
} else {
|
||||
inc = 1;
|
||||
}
|
||||
start += w * 128;
|
||||
|
||||
if (decode) {
|
||||
// ar filter
|
||||
for (m = 0; m < size; m++, start += inc)
|
||||
for (i = 1; i <= FFMIN(m, order); i++)
|
||||
coef[start] -= AAC_MUL26((INTFLOAT)coef[start - i * inc], lpc[i - 1]);
|
||||
} else {
|
||||
// ma filter
|
||||
for (m = 0; m < size; m++, start += inc) {
|
||||
tmp[0] = coef[start];
|
||||
for (i = 1; i <= FFMIN(m, order); i++)
|
||||
coef[start] += AAC_MUL26(tmp[i], lpc[i - 1]);
|
||||
for (i = order; i > 0; i--)
|
||||
tmp[i] = tmp[i - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply windowing and MDCT to obtain the spectral
|
||||
* coefficient from the predicted sample by LTP.
|
||||
*/
|
||||
static inline void AAC_RENAME(windowing_and_mdct_ltp)(AACDecContext *ac,
|
||||
INTFLOAT *out, INTFLOAT *in,
|
||||
IndividualChannelStream *ics)
|
||||
{
|
||||
const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
|
||||
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
|
||||
const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
|
||||
const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
|
||||
|
||||
if (ics->window_sequence[0] != LONG_STOP_SEQUENCE) {
|
||||
ac->fdsp->vector_fmul(in, in, lwindow_prev, 1024);
|
||||
} else {
|
||||
memset(in, 0, 448 * sizeof(*in));
|
||||
ac->fdsp->vector_fmul(in + 448, in + 448, swindow_prev, 128);
|
||||
}
|
||||
if (ics->window_sequence[0] != LONG_START_SEQUENCE) {
|
||||
ac->fdsp->vector_fmul_reverse(in + 1024, in + 1024, lwindow, 1024);
|
||||
} else {
|
||||
ac->fdsp->vector_fmul_reverse(in + 1024 + 448, in + 1024 + 448, swindow, 128);
|
||||
memset(in + 1024 + 576, 0, 448 * sizeof(*in));
|
||||
}
|
||||
ac->mdct_ltp_fn(ac->mdct_ltp, out, in, sizeof(INTFLOAT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the long term prediction
|
||||
*/
|
||||
static void AAC_RENAME(apply_ltp)(AACDecContext *ac, SingleChannelElement *sce)
|
||||
{
|
||||
const LongTermPrediction *ltp = &sce->ics.ltp;
|
||||
const uint16_t *offsets = sce->ics.swb_offset;
|
||||
int i, sfb;
|
||||
|
||||
if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
|
||||
INTFLOAT *predTime = sce->AAC_RENAME(output);
|
||||
INTFLOAT *predFreq = ac->AAC_RENAME(buf_mdct);
|
||||
int16_t num_samples = 2048;
|
||||
|
||||
if (ltp->lag < 1024)
|
||||
num_samples = ltp->lag + 1024;
|
||||
for (i = 0; i < num_samples; i++)
|
||||
predTime[i] = AAC_MUL30(sce->AAC_RENAME(ltp_state)[i + 2048 - ltp->lag], ltp->AAC_RENAME(coef));
|
||||
memset(&predTime[i], 0, (2048 - i) * sizeof(*predTime));
|
||||
|
||||
AAC_RENAME(windowing_and_mdct_ltp)(ac, predFreq, predTime, &sce->ics);
|
||||
|
||||
if (sce->tns.present)
|
||||
AAC_RENAME(apply_tns)(predFreq, &sce->tns, &sce->ics, 0);
|
||||
|
||||
for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++)
|
||||
if (ltp->used[sfb])
|
||||
for (i = offsets[sfb]; i < offsets[sfb + 1]; i++)
|
||||
sce->AAC_RENAME(coeffs)[i] += (UINTFLOAT)predFreq[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the LTP buffer for next frame
|
||||
*/
|
||||
static void AAC_RENAME(update_ltp)(AACDecContext *ac, SingleChannelElement *sce)
|
||||
{
|
||||
IndividualChannelStream *ics = &sce->ics;
|
||||
INTFLOAT *saved = sce->AAC_RENAME(saved);
|
||||
INTFLOAT *saved_ltp = sce->AAC_RENAME(coeffs);
|
||||
const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
|
||||
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
|
||||
int i;
|
||||
|
||||
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
||||
memcpy(saved_ltp, saved, 512 * sizeof(*saved_ltp));
|
||||
memset(saved_ltp + 576, 0, 448 * sizeof(*saved_ltp));
|
||||
ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->AAC_RENAME(buf_mdct) + 960, &swindow[64], 64);
|
||||
|
||||
for (i = 0; i < 64; i++)
|
||||
saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], swindow[63 - i]);
|
||||
} else if (1 && ics->window_sequence[0] == LONG_START_SEQUENCE) {
|
||||
memcpy(saved_ltp, ac->AAC_RENAME(buf_mdct) + 512, 448 * sizeof(*saved_ltp));
|
||||
memset(saved_ltp + 576, 0, 448 * sizeof(*saved_ltp));
|
||||
ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->AAC_RENAME(buf_mdct) + 960, &swindow[64], 64);
|
||||
|
||||
for (i = 0; i < 64; i++)
|
||||
saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], swindow[63 - i]);
|
||||
} else if (1) { // LONG_STOP or ONLY_LONG
|
||||
ac->fdsp->vector_fmul_reverse(saved_ltp, ac->AAC_RENAME(buf_mdct) + 512, &lwindow[512], 512);
|
||||
|
||||
for (i = 0; i < 512; i++)
|
||||
saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], lwindow[511 - i]);
|
||||
}
|
||||
|
||||
memcpy(sce->AAC_RENAME(ltp_state), sce->AAC_RENAME(ltp_state)+1024,
|
||||
1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
|
||||
memcpy(sce->AAC_RENAME(ltp_state) + 1024, sce->AAC_RENAME(output),
|
||||
1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
|
||||
memcpy(sce->AAC_RENAME(ltp_state) + 2048, saved_ltp,
|
||||
1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Conduct IMDCT and windowing.
|
||||
*/
|
||||
static void AAC_RENAME(imdct_and_windowing)(AACDecContext *ac, SingleChannelElement *sce)
|
||||
{
|
||||
IndividualChannelStream *ics = &sce->ics;
|
||||
INTFLOAT *in = sce->AAC_RENAME(coeffs);
|
||||
INTFLOAT *out = sce->AAC_RENAME(output);
|
||||
INTFLOAT *saved = sce->AAC_RENAME(saved);
|
||||
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
|
||||
const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
|
||||
const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
|
||||
INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
|
||||
INTFLOAT *temp = ac->AAC_RENAME(temp);
|
||||
int i;
|
||||
|
||||
// imdct
|
||||
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
||||
for (i = 0; i < 1024; i += 128)
|
||||
ac->mdct128_fn(ac->mdct128, buf + i, in + i, sizeof(INTFLOAT));
|
||||
} else {
|
||||
ac->mdct1024_fn(ac->mdct1024, buf, in, sizeof(INTFLOAT));
|
||||
}
|
||||
|
||||
/* window overlapping
|
||||
* NOTE: To simplify the overlapping code, all 'meaningless' short to long
|
||||
* and long to short transitions are considered to be short to short
|
||||
* transitions. This leaves just two cases (long to long and short to short)
|
||||
* with a little special sauce for EIGHT_SHORT_SEQUENCE.
|
||||
*/
|
||||
if ((ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE) &&
|
||||
(ics->window_sequence[0] == ONLY_LONG_SEQUENCE || ics->window_sequence[0] == LONG_START_SEQUENCE)) {
|
||||
ac->fdsp->vector_fmul_window( out, saved, buf, lwindow_prev, 512);
|
||||
} else {
|
||||
memcpy( out, saved, 448 * sizeof(*out));
|
||||
|
||||
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
||||
ac->fdsp->vector_fmul_window(out + 448 + 0*128, saved + 448, buf + 0*128, swindow_prev, 64);
|
||||
ac->fdsp->vector_fmul_window(out + 448 + 1*128, buf + 0*128 + 64, buf + 1*128, swindow, 64);
|
||||
ac->fdsp->vector_fmul_window(out + 448 + 2*128, buf + 1*128 + 64, buf + 2*128, swindow, 64);
|
||||
ac->fdsp->vector_fmul_window(out + 448 + 3*128, buf + 2*128 + 64, buf + 3*128, swindow, 64);
|
||||
ac->fdsp->vector_fmul_window(temp, buf + 3*128 + 64, buf + 4*128, swindow, 64);
|
||||
memcpy( out + 448 + 4*128, temp, 64 * sizeof(*out));
|
||||
} else {
|
||||
ac->fdsp->vector_fmul_window(out + 448, saved + 448, buf, swindow_prev, 64);
|
||||
memcpy( out + 576, buf + 64, 448 * sizeof(*out));
|
||||
}
|
||||
}
|
||||
|
||||
// buffer update
|
||||
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
||||
memcpy( saved, temp + 64, 64 * sizeof(*saved));
|
||||
ac->fdsp->vector_fmul_window(saved + 64, buf + 4*128 + 64, buf + 5*128, swindow, 64);
|
||||
ac->fdsp->vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 64);
|
||||
ac->fdsp->vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 64);
|
||||
memcpy( saved + 448, buf + 7*128 + 64, 64 * sizeof(*saved));
|
||||
} else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
|
||||
memcpy( saved, buf + 512, 448 * sizeof(*saved));
|
||||
memcpy( saved + 448, buf + 7*128 + 64, 64 * sizeof(*saved));
|
||||
} else { // LONG_STOP or ONLY_LONG
|
||||
memcpy( saved, buf + 512, 512 * sizeof(*saved));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Conduct IMDCT and windowing for 768-point frames.
|
||||
*/
|
||||
static void AAC_RENAME(imdct_and_windowing_768)(AACDecContext *ac, SingleChannelElement *sce)
|
||||
{
|
||||
IndividualChannelStream *ics = &sce->ics;
|
||||
INTFLOAT *in = sce->AAC_RENAME(coeffs);
|
||||
INTFLOAT *out = sce->AAC_RENAME(output);
|
||||
INTFLOAT *saved = sce->AAC_RENAME(saved);
|
||||
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME(aac_kbd_short_96) : AAC_RENAME(sine_96);
|
||||
const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_long_768) : AAC_RENAME(sine_768);
|
||||
const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_short_96) : AAC_RENAME(sine_96);
|
||||
INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
|
||||
INTFLOAT *temp = ac->AAC_RENAME(temp);
|
||||
int i;
|
||||
|
||||
// imdct
|
||||
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
||||
for (i = 0; i < 8; i++)
|
||||
ac->mdct96_fn(ac->mdct96, buf + i * 96, in + i * 96, sizeof(INTFLOAT));
|
||||
} else {
|
||||
ac->mdct768_fn(ac->mdct768, buf, in, sizeof(INTFLOAT));
|
||||
}
|
||||
|
||||
/* window overlapping
|
||||
* NOTE: To simplify the overlapping code, all 'meaningless' short to long
|
||||
* and long to short transitions are considered to be short to short
|
||||
* transitions. This leaves just two cases (long to long and short to short)
|
||||
* with a little special sauce for EIGHT_SHORT_SEQUENCE.
|
||||
*/
|
||||
|
||||
if ((ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE) &&
|
||||
(ics->window_sequence[0] == ONLY_LONG_SEQUENCE || ics->window_sequence[0] == LONG_START_SEQUENCE)) {
|
||||
ac->fdsp->vector_fmul_window( out, saved, buf, lwindow_prev, 384);
|
||||
} else {
|
||||
memcpy( out, saved, 336 * sizeof(*out));
|
||||
|
||||
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
||||
ac->fdsp->vector_fmul_window(out + 336 + 0*96, saved + 336, buf + 0*96, swindow_prev, 48);
|
||||
ac->fdsp->vector_fmul_window(out + 336 + 1*96, buf + 0*96 + 48, buf + 1*96, swindow, 48);
|
||||
ac->fdsp->vector_fmul_window(out + 336 + 2*96, buf + 1*96 + 48, buf + 2*96, swindow, 48);
|
||||
ac->fdsp->vector_fmul_window(out + 336 + 3*96, buf + 2*96 + 48, buf + 3*96, swindow, 48);
|
||||
ac->fdsp->vector_fmul_window(temp, buf + 3*96 + 48, buf + 4*96, swindow, 48);
|
||||
memcpy( out + 336 + 4*96, temp, 48 * sizeof(*out));
|
||||
} else {
|
||||
ac->fdsp->vector_fmul_window(out + 336, saved + 336, buf, swindow_prev, 48);
|
||||
memcpy( out + 432, buf + 48, 336 * sizeof(*out));
|
||||
}
|
||||
}
|
||||
|
||||
// buffer update
|
||||
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
||||
memcpy( saved, temp + 48, 48 * sizeof(*saved));
|
||||
ac->fdsp->vector_fmul_window(saved + 48, buf + 4*96 + 48, buf + 5*96, swindow, 48);
|
||||
ac->fdsp->vector_fmul_window(saved + 144, buf + 5*96 + 48, buf + 6*96, swindow, 48);
|
||||
ac->fdsp->vector_fmul_window(saved + 240, buf + 6*96 + 48, buf + 7*96, swindow, 48);
|
||||
memcpy( saved + 336, buf + 7*96 + 48, 48 * sizeof(*saved));
|
||||
} else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
|
||||
memcpy( saved, buf + 384, 336 * sizeof(*saved));
|
||||
memcpy( saved + 336, buf + 7*96 + 48, 48 * sizeof(*saved));
|
||||
} else { // LONG_STOP or ONLY_LONG
|
||||
memcpy( saved, buf + 384, 384 * sizeof(*saved));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Conduct IMDCT and windowing.
|
||||
*/
|
||||
static void AAC_RENAME(imdct_and_windowing_960)(AACDecContext *ac, SingleChannelElement *sce)
|
||||
{
|
||||
IndividualChannelStream *ics = &sce->ics;
|
||||
INTFLOAT *in = sce->AAC_RENAME(coeffs);
|
||||
INTFLOAT *out = sce->AAC_RENAME(output);
|
||||
INTFLOAT *saved = sce->AAC_RENAME(saved);
|
||||
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME(aac_kbd_short_120) : AAC_RENAME(sine_120);
|
||||
const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_long_960) : AAC_RENAME(sine_960);
|
||||
const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_short_120) : AAC_RENAME(sine_120);
|
||||
INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
|
||||
INTFLOAT *temp = ac->AAC_RENAME(temp);
|
||||
int i;
|
||||
|
||||
// imdct
|
||||
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
||||
for (i = 0; i < 8; i++)
|
||||
ac->mdct120_fn(ac->mdct120, buf + i * 120, in + i * 128, sizeof(INTFLOAT));
|
||||
} else {
|
||||
ac->mdct960_fn(ac->mdct960, buf, in, sizeof(INTFLOAT));
|
||||
}
|
||||
|
||||
/* window overlapping
|
||||
* NOTE: To simplify the overlapping code, all 'meaningless' short to long
|
||||
* and long to short transitions are considered to be short to short
|
||||
* transitions. This leaves just two cases (long to long and short to short)
|
||||
* with a little special sauce for EIGHT_SHORT_SEQUENCE.
|
||||
*/
|
||||
|
||||
if ((ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE) &&
|
||||
(ics->window_sequence[0] == ONLY_LONG_SEQUENCE || ics->window_sequence[0] == LONG_START_SEQUENCE)) {
|
||||
ac->fdsp->vector_fmul_window( out, saved, buf, lwindow_prev, 480);
|
||||
} else {
|
||||
memcpy( out, saved, 420 * sizeof(*out));
|
||||
|
||||
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
||||
ac->fdsp->vector_fmul_window(out + 420 + 0*120, saved + 420, buf + 0*120, swindow_prev, 60);
|
||||
ac->fdsp->vector_fmul_window(out + 420 + 1*120, buf + 0*120 + 60, buf + 1*120, swindow, 60);
|
||||
ac->fdsp->vector_fmul_window(out + 420 + 2*120, buf + 1*120 + 60, buf + 2*120, swindow, 60);
|
||||
ac->fdsp->vector_fmul_window(out + 420 + 3*120, buf + 2*120 + 60, buf + 3*120, swindow, 60);
|
||||
ac->fdsp->vector_fmul_window(temp, buf + 3*120 + 60, buf + 4*120, swindow, 60);
|
||||
memcpy( out + 420 + 4*120, temp, 60 * sizeof(*out));
|
||||
} else {
|
||||
ac->fdsp->vector_fmul_window(out + 420, saved + 420, buf, swindow_prev, 60);
|
||||
memcpy( out + 540, buf + 60, 420 * sizeof(*out));
|
||||
}
|
||||
}
|
||||
|
||||
// buffer update
|
||||
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
||||
memcpy( saved, temp + 60, 60 * sizeof(*saved));
|
||||
ac->fdsp->vector_fmul_window(saved + 60, buf + 4*120 + 60, buf + 5*120, swindow, 60);
|
||||
ac->fdsp->vector_fmul_window(saved + 180, buf + 5*120 + 60, buf + 6*120, swindow, 60);
|
||||
ac->fdsp->vector_fmul_window(saved + 300, buf + 6*120 + 60, buf + 7*120, swindow, 60);
|
||||
memcpy( saved + 420, buf + 7*120 + 60, 60 * sizeof(*saved));
|
||||
} else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
|
||||
memcpy( saved, buf + 480, 420 * sizeof(*saved));
|
||||
memcpy( saved + 420, buf + 7*120 + 60, 60 * sizeof(*saved));
|
||||
} else { // LONG_STOP or ONLY_LONG
|
||||
memcpy( saved, buf + 480, 480 * sizeof(*saved));
|
||||
}
|
||||
}
|
||||
|
||||
static void AAC_RENAME(imdct_and_windowing_ld)(AACDecContext *ac, SingleChannelElement *sce)
|
||||
{
|
||||
IndividualChannelStream *ics = &sce->ics;
|
||||
INTFLOAT *in = sce->AAC_RENAME(coeffs);
|
||||
INTFLOAT *out = sce->AAC_RENAME(output);
|
||||
INTFLOAT *saved = sce->AAC_RENAME(saved);
|
||||
INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
|
||||
|
||||
// imdct
|
||||
ac->mdct512_fn(ac->mdct512, buf, in, sizeof(INTFLOAT));
|
||||
|
||||
// window overlapping
|
||||
if (ics->use_kb_window[1]) {
|
||||
// AAC LD uses a low overlap sine window instead of a KBD window
|
||||
memcpy(out, saved, 192 * sizeof(*out));
|
||||
ac->fdsp->vector_fmul_window(out + 192, saved + 192, buf, AAC_RENAME2(sine_128), 64);
|
||||
memcpy( out + 320, buf + 64, 192 * sizeof(*out));
|
||||
} else {
|
||||
ac->fdsp->vector_fmul_window(out, saved, buf, AAC_RENAME2(sine_512), 256);
|
||||
}
|
||||
|
||||
// buffer update
|
||||
memcpy(saved, buf + 256, 256 * sizeof(*saved));
|
||||
}
|
||||
|
||||
static void AAC_RENAME(imdct_and_windowing_eld)(AACDecContext *ac, SingleChannelElement *sce)
|
||||
{
|
||||
UINTFLOAT *in = sce->AAC_RENAME(coeffs);
|
||||
INTFLOAT *out = sce->AAC_RENAME(output);
|
||||
INTFLOAT *saved = sce->AAC_RENAME(saved);
|
||||
INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
|
||||
int i;
|
||||
const int n = ac->oc[1].m4ac.frame_length_short ? 480 : 512;
|
||||
const int n2 = n >> 1;
|
||||
const int n4 = n >> 2;
|
||||
const INTFLOAT *const window = n == 480 ? AAC_RENAME(ff_aac_eld_window_480) :
|
||||
AAC_RENAME(ff_aac_eld_window_512);
|
||||
|
||||
// Inverse transform, mapped to the conventional IMDCT by
|
||||
// Chivukula, R.K.; Reznik, Y.A.; Devarajan, V.,
|
||||
// "Efficient algorithms for MPEG-4 AAC-ELD, AAC-LD and AAC-LC filterbanks,"
|
||||
// International Conference on Audio, Language and Image Processing, ICALIP 2008.
|
||||
// URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=4590245&isnumber=4589950
|
||||
for (i = 0; i < n2; i+=2) {
|
||||
INTFLOAT temp;
|
||||
temp = in[i ]; in[i ] = -in[n - 1 - i]; in[n - 1 - i] = temp;
|
||||
temp = -in[i + 1]; in[i + 1] = in[n - 2 - i]; in[n - 2 - i] = temp;
|
||||
}
|
||||
|
||||
if (n == 480)
|
||||
ac->mdct480_fn(ac->mdct480, buf, in, sizeof(INTFLOAT));
|
||||
else
|
||||
ac->mdct512_fn(ac->mdct512, buf, in, sizeof(INTFLOAT));
|
||||
|
||||
for (i = 0; i < n; i+=2) {
|
||||
buf[i + 0] = -(UINTFLOAT)(USE_FIXED + 1)*buf[i + 0];
|
||||
buf[i + 1] = (UINTFLOAT)(USE_FIXED + 1)*buf[i + 1];
|
||||
}
|
||||
// Like with the regular IMDCT at this point we still have the middle half
|
||||
// of a transform but with even symmetry on the left and odd symmetry on
|
||||
// the right
|
||||
|
||||
// window overlapping
|
||||
// The spec says to use samples [0..511] but the reference decoder uses
|
||||
// samples [128..639].
|
||||
for (i = n4; i < n2; i ++) {
|
||||
out[i - n4] = AAC_MUL31( buf[ n2 - 1 - i] , window[i - n4]) +
|
||||
AAC_MUL31( saved[ i + n2] , window[i + n - n4]) +
|
||||
AAC_MUL31(-saved[n + n2 - 1 - i] , window[i + 2*n - n4]) +
|
||||
AAC_MUL31(-saved[ 2*n + n2 + i] , window[i + 3*n - n4]);
|
||||
}
|
||||
for (i = 0; i < n2; i ++) {
|
||||
out[n4 + i] = AAC_MUL31( buf[ i] , window[i + n2 - n4]) +
|
||||
AAC_MUL31(-saved[ n - 1 - i] , window[i + n2 + n - n4]) +
|
||||
AAC_MUL31(-saved[ n + i] , window[i + n2 + 2*n - n4]) +
|
||||
AAC_MUL31( saved[2*n + n - 1 - i] , window[i + n2 + 3*n - n4]);
|
||||
}
|
||||
for (i = 0; i < n4; i ++) {
|
||||
out[n2 + n4 + i] = AAC_MUL31( buf[ i + n2] , window[i + n - n4]) +
|
||||
AAC_MUL31(-saved[n2 - 1 - i] , window[i + 2*n - n4]) +
|
||||
AAC_MUL31(-saved[n + n2 + i] , window[i + 3*n - n4]);
|
||||
}
|
||||
|
||||
// buffer update
|
||||
memmove(saved + n, saved, 2 * n * sizeof(*saved));
|
||||
memcpy( saved, buf, n * sizeof(*saved));
|
||||
}
|
||||
|
||||
static void AAC_RENAME(clip_output)(AACDecContext *ac, ChannelElement *che,
|
||||
int type, int samples)
|
||||
{
|
||||
#if USE_FIXED
|
||||
/* preparation for resampler */
|
||||
for (int j = 0; j < samples; j++){
|
||||
che->ch[0].output_fixed[j] = (int32_t)av_clip64((int64_t)che->ch[0].output_fixed[j]*128,
|
||||
INT32_MIN, INT32_MAX-0x8000)+0x8000;
|
||||
if (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))
|
||||
che->ch[1].output_fixed[j] = (int32_t)av_clip64((int64_t)che->ch[1].output_fixed[j]*128,
|
||||
INT32_MIN, INT32_MAX-0x8000)+0x8000;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void reset_all_predictors(PredictorState *ps)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_PREDICTORS; i++)
|
||||
reset_predict_state(&ps[i]);
|
||||
}
|
||||
|
||||
static inline void reset_predictor_group(PredictorState *ps, int group_num)
|
||||
{
|
||||
int i;
|
||||
for (i = group_num - 1; i < MAX_PREDICTORS; i += 30)
|
||||
reset_predict_state(&ps[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply AAC-Main style frequency domain prediction.
|
||||
*/
|
||||
static void AAC_RENAME(apply_prediction)(AACDecContext *ac, SingleChannelElement *sce)
|
||||
{
|
||||
int sfb, k;
|
||||
|
||||
if (!sce->ics.predictor_initialized) {
|
||||
reset_all_predictors(sce->AAC_RENAME(predictor_state));
|
||||
sce->ics.predictor_initialized = 1;
|
||||
}
|
||||
|
||||
if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
|
||||
for (sfb = 0;
|
||||
sfb < ff_aac_pred_sfb_max[ac->oc[1].m4ac.sampling_index];
|
||||
sfb++) {
|
||||
for (k = sce->ics.swb_offset[sfb];
|
||||
k < sce->ics.swb_offset[sfb + 1];
|
||||
k++) {
|
||||
predict(&sce->AAC_RENAME(predictor_state)[k],
|
||||
&sce->AAC_RENAME(coeffs)[k],
|
||||
sce->ics.predictor_present &&
|
||||
sce->ics.prediction_used[sfb]);
|
||||
}
|
||||
}
|
||||
if (sce->ics.predictor_reset_group)
|
||||
reset_predictor_group(sce->AAC_RENAME(predictor_state),
|
||||
sce->ics.predictor_reset_group);
|
||||
} else
|
||||
reset_all_predictors(sce->AAC_RENAME(predictor_state));
|
||||
}
|
||||
|
||||
static av_cold void AAC_RENAME(aac_dsp_init)(AACDecDSP *aac_dsp)
|
||||
{
|
||||
#define SET(member) aac_dsp->member = AAC_RENAME(member)
|
||||
SET(dequant_scalefactors);
|
||||
SET(apply_mid_side_stereo);
|
||||
SET(apply_intensity_stereo);
|
||||
SET(apply_tns);
|
||||
SET(apply_ltp);
|
||||
SET(update_ltp);
|
||||
|
||||
SET(apply_prediction);
|
||||
|
||||
SET(imdct_and_windowing);
|
||||
SET(imdct_and_windowing_768);
|
||||
SET(imdct_and_windowing_960);
|
||||
SET(imdct_and_windowing_ld);
|
||||
SET(imdct_and_windowing_eld);
|
||||
|
||||
SET(apply_dependent_coupling);
|
||||
SET(apply_independent_coupling);
|
||||
|
||||
SET(clip_output);
|
||||
#undef SET
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* AAC decoder
|
||||
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
|
||||
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
|
||||
* Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
|
||||
*
|
||||
* AAC LATM decoder
|
||||
* Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
|
||||
* Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
|
||||
*
|
||||
* AAC decoder fixed-point implementation
|
||||
* Copyright (c) 2013
|
||||
* MIPS Technologies, Inc., California.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General 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 USE_FIXED 1
|
||||
|
||||
#include "libavutil/thread.h"
|
||||
|
||||
#include "libavcodec/aac_defines.h"
|
||||
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "aacdec.h"
|
||||
#include "libavcodec/aactab.h"
|
||||
#include "libavcodec/sinewin_fixed_tablegen.h"
|
||||
#include "libavcodec/kbdwin.h"
|
||||
#include "libavcodec/cbrt_data.h"
|
||||
#include "libavcodec/aacsbr.h"
|
||||
|
||||
DECLARE_ALIGNED(32, static int, aac_kbd_long_1024_fixed)[1024];
|
||||
DECLARE_ALIGNED(32, static int, aac_kbd_short_128_fixed)[128];
|
||||
DECLARE_ALIGNED(32, static int, aac_kbd_long_960_fixed)[960];
|
||||
DECLARE_ALIGNED(32, static int, aac_kbd_short_120_fixed)[120];
|
||||
DECLARE_ALIGNED(32, static int, aac_kbd_long_768_fixed)[768];
|
||||
DECLARE_ALIGNED(32, static int, aac_kbd_short_96_fixed)[96];
|
||||
|
||||
static void init_tables_fixed_fn(void)
|
||||
{
|
||||
ff_cbrt_tableinit_fixed();
|
||||
|
||||
ff_kbd_window_init_fixed(aac_kbd_long_1024_fixed, 4.0, 1024);
|
||||
ff_kbd_window_init_fixed(aac_kbd_short_128_fixed, 6.0, 128);
|
||||
|
||||
ff_kbd_window_init_fixed(aac_kbd_long_960_fixed, 4.0, 960);
|
||||
ff_kbd_window_init_fixed(aac_kbd_short_120_fixed, 6.0, 120);
|
||||
|
||||
ff_aac_sbr_init_fixed();
|
||||
|
||||
init_sine_windows_fixed();
|
||||
}
|
||||
|
||||
static const int cce_scale_fixed[8] = {
|
||||
Q30(1.0), //2^(0/8)
|
||||
Q30(1.0905077327), //2^(1/8)
|
||||
Q30(1.1892071150), //2^(2/8)
|
||||
Q30(1.2968395547), //2^(3/8)
|
||||
Q30(1.4142135624), //2^(4/8)
|
||||
Q30(1.5422108254), //2^(5/8)
|
||||
Q30(1.6817928305), //2^(6/8)
|
||||
Q30(1.8340080864), //2^(7/8)
|
||||
};
|
||||
|
||||
/** Dequantization-related */
|
||||
#include "aacdec_fixed_dequant.h"
|
||||
|
||||
#include "aacdec_fixed_coupling.h"
|
||||
#include "aacdec_fixed_prediction.h"
|
||||
#include "aacdec_dsp_template.c"
|
||||
#include "aacdec_proc_template.c"
|
||||
|
||||
av_cold int ff_aac_decode_init_fixed(AVCodecContext *avctx)
|
||||
{
|
||||
static AVOnce init_fixed_once = AV_ONCE_INIT;
|
||||
AACDecContext *ac = avctx->priv_data;
|
||||
|
||||
ac->is_fixed = 1;
|
||||
avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
|
||||
|
||||
aac_dsp_init_fixed(&ac->dsp);
|
||||
aac_proc_init_fixed(&ac->proc);
|
||||
|
||||
ac->fdsp = avpriv_alloc_fixed_dsp(avctx->flags & AV_CODEC_FLAG_BITEXACT);
|
||||
if (!ac->fdsp)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
ff_thread_once(&init_fixed_once, init_tables_fixed_fn);
|
||||
|
||||
return ff_aac_decode_init(avctx);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user