Compare commits
181 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0a155c57bd | |||
| 3ef38c414e | |||
| 40ed40902a | |||
| 0561cde128 | |||
| 670b565ba2 | |||
| 6b65f46673 | |||
| 052edeec55 | |||
| 48479937c3 | |||
| fd53179f4a | |||
| 5db47b3983 | |||
| 0981dfee7d | |||
| d8c4b2ae57 | |||
| fc92ca5b8e | |||
| 6d992a51c7 | |||
| 6f4b82cc3a | |||
| 37f505cc85 | |||
| a21703ca5d | |||
| a28ab09e2a | |||
| 4439d6aa69 | |||
| 3bf80c7b22 | |||
| 1361e4abb8 | |||
| 5fd1dce39a | |||
| de0a1d01ba | |||
| c4b23793d4 | |||
| e21e5c95c1 | |||
| 2b13c136c4 | |||
| d3536ce839 | |||
| 679d749eab | |||
| 7610538224 | |||
| 0003ace83b | |||
| 20c5fb9721 | |||
| 841e1399e6 | |||
| 9f76f0fab8 | |||
| bf3e331b76 | |||
| 21732c1adc | |||
| d00548f2c1 | |||
| 10e5302db4 | |||
| 84280dc7cf | |||
| 2c404cc11a | |||
| acb7907319 | |||
| 2c138c2d8c | |||
| b5106c5aa2 | |||
| 789bac72ed | |||
| 33fcbb4372 | |||
| a56eb4d56c | |||
| 70799fae35 | |||
| e049f7c24f | |||
| 83a737aa70 | |||
| 2deeb2eaef | |||
| 9eaf908897 | |||
| 1ca157b026 | |||
| f36128518b | |||
| 897524954b | |||
| f0e4bc61e3 | |||
| 36628bd215 | |||
| e42ab0115e | |||
| 10f68641ae | |||
| f0a10f6376 | |||
| 0b4d76d891 | |||
| 4fa2078217 | |||
| 081874a050 | |||
| 028a0c9148 | |||
| 9a53e8572a | |||
| 3aa3b05d64 | |||
| 7a5ddf731b | |||
| 4b12afccb2 | |||
| b55c824ee7 | |||
| a90497c183 | |||
| 65b2b0d98a | |||
| 0097cc0ea3 | |||
| 07767c704b | |||
| 2e7830e5ff | |||
| 4f644b2632 | |||
| 1d01a3b34c | |||
| 2742cb10c7 | |||
| 8229afc3a9 | |||
| 76f8c8cd05 | |||
| 786834a693 | |||
| f2c253f083 | |||
| e26be20a27 | |||
| 7b7c582c15 | |||
| 06b84f7271 | |||
| f974cc9830 | |||
| af0ba288e7 | |||
| c98d84e229 | |||
| b3d740263c | |||
| 6edf0ecab0 | |||
| b2aaf5de42 | |||
| 217367b5eb | |||
| c97f9ed53f | |||
| 05ac7fdeeb | |||
| c071618ba6 | |||
| b367c23da1 | |||
| 58a03420be | |||
| cbe442048f | |||
| 87e9f5e118 | |||
| 2cffce26a7 | |||
| c26e101654 | |||
| 60e408f252 | |||
| e61dcd2c86 | |||
| dd3914c5b5 | |||
| 90c4c076c7 | |||
| d976855c00 | |||
| 7bc5d49c60 | |||
| 36c4995428 | |||
| 57bb78d980 | |||
| b2cb42f1c3 | |||
| fe7f2a77c7 | |||
| 9dfe36616f | |||
| 4ace1597a2 | |||
| 6d2c5bb5d2 | |||
| a6d85a97d0 | |||
| 72a34d2332 | |||
| c8b57d4333 | |||
| da399903c7 | |||
| 8336a66270 | |||
| d1845e7f1a | |||
| 852f78443a | |||
| c343eabfb7 | |||
| 7ad163c258 | |||
| ef28571efe | |||
| 97aea63340 | |||
| bb6a34f237 | |||
| db5631e408 | |||
| df2c811b7c | |||
| 6f55a36be9 | |||
| 33042d632d | |||
| 3054e53ddc | |||
| 84bf631018 | |||
| 2884575d97 | |||
| 76716518a8 | |||
| e8caf67f56 | |||
| e40922c16c | |||
| ef9478d264 | |||
| 13d83899df | |||
| 61fed89ad4 | |||
| 7931e01540 | |||
| 93cee87b13 | |||
| 2a44f706aa | |||
| 61b673b1f1 | |||
| 8fde71acd9 | |||
| b32f865969 | |||
| d89eea3455 | |||
| 0a22e31fbb | |||
| 70a01aa490 | |||
| da6c519f6e | |||
| 29328d96b9 | |||
| 44cb647477 | |||
| a768c0a3e1 | |||
| 58569162c2 | |||
| 6b2fee19a7 | |||
| 8cd79c2e73 | |||
| 0502602d37 | |||
| ace829cb45 | |||
| b9b3ef4f5a | |||
| b2b7cb0f60 | |||
| 5cc6370a15 | |||
| 8b019be79b | |||
| e36830c695 | |||
| bc2ceeb3ac | |||
| 66bdf8f145 | |||
| bfe61bbd00 | |||
| 5888679ae3 | |||
| ecb375684d | |||
| df56bc18ef | |||
| ef99025603 | |||
| 860293a9a2 | |||
| 9b71114247 | |||
| 0b6de235b9 | |||
| a73b464118 | |||
| d9e9e97e5f | |||
| d52676da38 | |||
| ca85c3cd7d | |||
| de253343c1 | |||
| 9c787a21ce | |||
| 7e11a86175 | |||
| 9ef90ff0a2 | |||
| 6c95a26c1a | |||
| b6ec181240 | |||
| b42e135614 | |||
| 0564e8ee49 |
@@ -1,7 +1,163 @@
|
||||
Entries are sorted chronologically from oldest to youngest within each release,
|
||||
releases are sorted from youngest to oldest.
|
||||
|
||||
version <next>:
|
||||
version 4.0.2:
|
||||
- avcodec/dvdsub_parser: Allocate input padding
|
||||
- avcodec/dvdsub_parser: Init output buf/size
|
||||
- avcodec/dirac_dwt_template: Fix signedness regression in interleave()
|
||||
- avformat/mov: Simplify last element computation in mov_estimate_video_delay()
|
||||
- avformat/mov: Break out of inner loop early in mov_estimate_video_delay()
|
||||
- avformat/mov: Eliminate variable buf_size from mov_estimate_video_delay()
|
||||
- avformat/mov: remove modulo operations from mov_estimate_video_delay()
|
||||
- avformat/movenc: Write version 2 of audio atom if channels is not known
|
||||
- swresample/arm: rename labels to fix xcode build error
|
||||
- avformat/movenc: Check input sample count
|
||||
- avcodec/mjpegdec: Check for odd progressive RGB
|
||||
- avcodec/vp8_parser: Do not leave data/size uninitialized
|
||||
- avformat/mms: Add missing chunksize check
|
||||
- avformat/pva: Check for EOF before retrying in read_part_of_packet()
|
||||
- avformat/rmdec: Do not pass mime type in rm_read_multi() to ff_rm_read_mdpr_codecdata()
|
||||
- avformat/asfdec_o: Check size_bmp more fully
|
||||
- avformat/mxfdec: Fix av_log context
|
||||
- avcodec/mpeg4videodec: Check for bitstream end in read_quant_matrix_ext()
|
||||
- avcodec/indeo4: Check for end of bitstream in decode_mb_info()
|
||||
- avcodec/ac3dec: Check channel_map index
|
||||
- avcodec/mpeg4videodec: Remove use of FF_PROFILE_MPEG4_SIMPLE_STUDIO as indicator of studio profile
|
||||
- avcodec/shorten: Fix undefined addition in shorten_decode_frame()
|
||||
- avcodec/shorten: Fix undefined integer overflow
|
||||
- avcodec/jpeg2000dec: Fixes invalid shifts in jpeg2000_decode_packets_po_iteration()
|
||||
- avcodec/jpeg2000dec: Check that there are enough bytes for all tiles
|
||||
- avformat/movenc: Use mov->fc consistently for av_log()
|
||||
- avcodec/mpeg4videodec: Check read profile before setting it
|
||||
- avformat/movenc: Do not pass AVCodecParameters in avpriv_request_sample
|
||||
- avcodec/ac3_parser: Check init_get_bits8() for failure
|
||||
- avformat/movenc: Check that frame_types other than EAC3_FRAME_TYPE_INDEPENDENT have a supported substream id
|
||||
- avcodec/dpx: Check elements in 12bps planar path
|
||||
- avcodec/escape124: Fix spelling errors in comment
|
||||
- avcodec/ra144: Fix integer overflow in ff_eval_refl()
|
||||
- avcodec/cscd: Check output buffer size for lzo.
|
||||
- avcodec/escape124: Check buf_size against num_superblocks
|
||||
- avcodec/h264_parser: Reduce needed history for parsing mb index
|
||||
- avcodec/magicyuv: Check bits left in flags&1 branch
|
||||
- avcodec/mjpegdec: Check for end of bitstream in ljpeg_decode_rgb_scan()
|
||||
- ffmpeg: fix -stream_loop with multiple inputs
|
||||
- ffmpeg: factorize input thread creation and destruction
|
||||
- avformat/mpegts: parse large PMTs with multiple tables
|
||||
- Revert "avcodec/mediacodecdec: wait on first frame after input buffers are full"
|
||||
- avcodec/videotoolboxenc: fix invalid session on iOS
|
||||
- avcodec/videotoolboxenc: split initialization
|
||||
- avcodec/videotoolboxenc: fix mutex/cond leak in error path
|
||||
|
||||
version 4.0.1:
|
||||
- avcodec/aacdec_fixed: Fix undefined integer overflow in apply_independent_coupling_fixed()
|
||||
- avcodec/dirac_dwt_template: Fix undefined behavior in interleave()
|
||||
- avutil/common: Fix undefined behavior in av_clip_uintp2_c()
|
||||
- fftools/ffmpeg: Fallback to duration if sample rate is unavailable
|
||||
- avformat/mov: Only set pkt->duration to non negative values
|
||||
- avcodec/mpeg4videodec: Clear bits_per_raw_sample if it has originated from a previous instance
|
||||
- avformat/movenc: fix recognization of cover image streams
|
||||
- avformat/movenc: properly handle cover image codecs
|
||||
- avcodec/h264_slice: Fix overflow in recovery_frame computation
|
||||
- avcodec/h264_ps: Move MAX_LOG2_MAX_FRAME_NUM to header so it can be used in h264_sei
|
||||
- avcodec/h264_mc_template: Only prefetch motion if the list is used.
|
||||
- avcodec/xwddec: Use ff_set_dimensions()
|
||||
- avcodec/wavpack: Fix overflow in adding tail
|
||||
- avcodec/shorten: Fix multiple integer overflows
|
||||
- avcodec/shorten: Fix undefined shift in fix_bitshift()
|
||||
- avcodec/shorten: Fix a negative left shift in shorten_decode_frame()
|
||||
- avcodec/shorten: Sanity check nmeans
|
||||
- avcodec/shorten: Check non COMM chunk len before skip in decode_aiff_header()
|
||||
- avcodec/mjpegdec: Fix integer overflow in ljpeg_decode_rgb_scan()
|
||||
- avcodec/truemotion2: Fix overflow in tm2_apply_deltas()
|
||||
- avcodec/opus_silk: Change silk_lsf2lpc() slightly toward silk/NLSF2A.c
|
||||
- avcodec/amrwbdec: Fix division by 0 in find_hb_gain()
|
||||
- avcodec/h263dec: Reinitialize idct context if it has not been setup for the active profile
|
||||
- avcodec/idctdsp: Clear idct/idct_add for studio profile
|
||||
- avformat/mov: replace a value error by clipping into valid range in mov_read_stsc()
|
||||
- avformat/bintext: Reduce detection for random .bin files as it more likely is not a multimedia related file
|
||||
- avformat/mov: Break out early if chunk_count is 0 in mov_build_index()
|
||||
- avcodec/fic: Avoid some magic numbers related to cursors
|
||||
- avcodec/mpeg4video: Detect reference studio streams as studio streams
|
||||
- avcodec/mpeg4videodec: Do not corrupt bits_per_raw_sample
|
||||
- avcodec/mpeg4videode: Eliminate out of loop VOP startcode reading for studio profile
|
||||
- avcodec/g2meet: ask for sample with overflowing RGB
|
||||
- avcodec/idctdsp: Transmit studio_profile to init instead of using AVCodecContext profile
|
||||
- avcodec/ac3dec: Check that the number of channels with dependant streams is valid
|
||||
- avcodec/ac3dec: Fix null pointer dereference in ac3_decode_frame()
|
||||
- avcodec/aacdec_fixed: use 64bit to avoid overflow in rounding in apply_dependent_coupling_fixed()
|
||||
- oavcodec/aacpsdsp_template: Use unsigned for hs0X to prevent undefined behavior
|
||||
- avcodec/g723_1dec: Clip bits2 in both directions
|
||||
- avcodec/mpeg4videoenc: Use 64 bit for times in mpeg4_encode_gop_header()
|
||||
- avcodec/mlpdec: Only change noise_type if the related fields are valid
|
||||
- indeo4: Decode all or nothing of a band header.
|
||||
- avcodec/ac3dec: Use frame_size if superframe_size is 0
|
||||
- avformat/mov: Only fail for STCO/STSC contradictions if both exist
|
||||
- avcodec/dirac_dwt: Fix integer overflow in COMPOSE_DD97iH0 / COMPOSE_DD137iL0
|
||||
- avcodec/fic: Check available input space for cursor
|
||||
- avcodec/mpeg4videodec: Check bps (VOL header) before VOP for studio profile
|
||||
- avcodec/g2meet: Check RGB upper limit
|
||||
- avcodec/jpeg2000dec: Fix undefined shift in the jpeg2000_decode_packets_po_iteration() CPRL case
|
||||
- avcodec/jpeg2000dec: Skip init for component in CPRL if nothing is to be done
|
||||
- avcodec/g2meet: Change order of operations to avoid undefined behavior
|
||||
- avcodec/flac_parser: Fix infinite loop
|
||||
- avcodec/mpeg4videodec: Split decode_studio_vol_header() out of decode_studiovisualobject()
|
||||
- avcodec/mpeg4videodec: Move decode_studiovisualobject() parsing in the branch for visual object parsing
|
||||
- avcodec/mpeg4video_parser: Avoid litteral 0x1B6, use named constant instead
|
||||
- avcodec/mpeg4video_parser: Fix incorrect spliting of MPEG-4 studio frames
|
||||
- avformat/m4vdec: Use the same constant names as libavcodec
|
||||
- avformat/m4vdec: Fix detection of raw MPEG-4 ES Studio
|
||||
- avcodec/wavpack: Fix integer overflow in DEC_MED() / INC_MED()
|
||||
- avcodec/wavpack: Fix integer overflow in wv_unpack_stereo()
|
||||
- avcodec/error_resilience: Fix integer overflow in filter181()
|
||||
- avcodec/h263dec: Check slice_ret in mspeg4 slice loop
|
||||
- avcodec/elsdec: Fix memleaks
|
||||
- avcodec/vc1_block: simplify ac_val computation
|
||||
- avcodec/ffv1enc: Check that the crc + version combination is supported
|
||||
- configure: The eac3_core bitstream filter needs the ac3 parser.
|
||||
- configure: fix arm inline asm checks
|
||||
- lavf/libssh: translate a read of 0 to EOF
|
||||
- ffprobe: fix SEGV when new streams are added
|
||||
- avformat/mpegts: fix incorrect indentation
|
||||
- avformat/mpegts: initialize section_buf to fix valgrind test failure
|
||||
- avformat/mpegts: reindent after last change
|
||||
- avformat/mpegts: parse sections with multiple tables
|
||||
- avformat/mpegts: clean up whitespace
|
||||
- avformat/mpegts: use MAX_SECTION_SIZE instead of hardcoded value
|
||||
- avformat/mpegts: skip non-PMT tids earlier
|
||||
- avcodec/mediacodecdec: add workaround for buggy amlogic mpeg2 decoder
|
||||
- avcodec/mediacodecdec: wait on first frame after input buffers are full
|
||||
- avcodec/mediacodecdec: restructure mediacodec_receive_frame
|
||||
- avcodec/mediacodec_wrapper: add helper to fetch SDK_INT
|
||||
- avcodec/mediacodecdec: refactor pts handling
|
||||
- avcodec/mediacodecdec: use AV_TIME_BASE_Q
|
||||
- avcodec/mediacodecdec: clarify delay_flush specific code
|
||||
- avcodec/videotoolbox: fix decoding of some HEVC videos
|
||||
- avcodec/hevc: remove videotoolbox hack
|
||||
- avcodec/videotoolbox: split h264/hevc callbacks
|
||||
- avcodec/videotoolbox: cleanups
|
||||
- avcodec/videotoolbox: fix kVTCouldNotFindVideoDecoderErr trying to decode HEVC on iOS
|
||||
- avcodec/videotoolbox: improve logging of decoder errors
|
||||
- avcodec/xwddec: fix palette alpha
|
||||
- avformat/webm_chunk: always use a static buffer for get_chunk_filename
|
||||
- configure: fix configure check for lilv-0
|
||||
- avcodec/nvdec_hevc: fix scaling lists
|
||||
- avcodec/hevcdec: make ff_hevc_frame_nb_refs take a const pointer
|
||||
- lavf/bluray: translate a read of 0 to EOF
|
||||
- lavf/dashenc: don't call flush_init_segment before avformat_write_header
|
||||
- avdevice/decklink_dec: unref packets on avpacket_queue_put error
|
||||
- avcodec/hnm4video: fix palette alpha
|
||||
- avcodec/anm: fix palette alpha
|
||||
- avformat/qtpalette: parse color table according to the QuickTime file format specs
|
||||
- ffplay: Fix realloc_texture when input texture is NULL.
|
||||
- hwcontext_vaapi: Fix compilation with libva versions < 1.4.0
|
||||
- lavf/qsv: clone the frame which may be managed by framework
|
||||
- lavf: make overlay_qsv work based on framesync
|
||||
- avformat/segafilm - revert keyframe detection
|
||||
- avformat/utils: refactor upstream_stream_timings
|
||||
- avformat/utils: ignore outlier durations on subtitle/data streams as well
|
||||
|
||||
|
||||
version 4.0:
|
||||
- Bitstream filters for editing metadata in H.264, HEVC and MPEG-2 streams
|
||||
- Dropped support for OpenJPEG versions 2.0 and below. Using OpenJPEG now
|
||||
requires 2.1 (or later) and pkg-config.
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
┌───────────────────────────────────┐
|
||||
│ RELEASE NOTES for FFmpeg 4.0 "Wu" │
|
||||
└───────────────────────────────────┘
|
||||
|
||||
The FFmpeg Project proudly presents FFmpeg 4.0 "Wu", about 6
|
||||
months after the release of FFmpeg 3.4.
|
||||
|
||||
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.freenode.net) or ask
|
||||
on the mailing-lists.
|
||||
@@ -1036,7 +1036,7 @@ EOF
|
||||
|
||||
check_insn(){
|
||||
log check_insn "$@"
|
||||
check_inline_asm ${1}_inline "$2"
|
||||
check_inline_asm ${1}_inline "\"$2\""
|
||||
check_as ${1}_external "$2"
|
||||
}
|
||||
|
||||
@@ -2372,6 +2372,7 @@ CMDLINE_SET="
|
||||
malloc_prefix
|
||||
nm
|
||||
optflags
|
||||
nvcc
|
||||
nvccflags
|
||||
pkg_config
|
||||
pkg_config_flags
|
||||
@@ -2978,6 +2979,7 @@ vc1_parser_select="vc1dsp"
|
||||
|
||||
# bitstream_filters
|
||||
aac_adtstoasc_bsf_select="adts_header"
|
||||
eac3_core_bsf_select="ac3_parser"
|
||||
filter_units_bsf_select="cbs"
|
||||
h264_metadata_bsf_deps="const_nan"
|
||||
h264_metadata_bsf_select="cbs_h264"
|
||||
@@ -4410,7 +4412,7 @@ probe_cc(){
|
||||
_flags_filter=msvc_flags
|
||||
_ld_lib='lib%.a'
|
||||
_ld_path='-libpath:'
|
||||
elif $_cc -nologo- 2>&1 | grep -q Microsoft || $_cc -v 2>&1 | grep -q clang && $_cc -? > /dev/null 2>&1; then
|
||||
elif $_cc -nologo- 2>&1 | grep -q Microsoft || { $_cc -v 2>&1 | grep -q clang && $_cc -? > /dev/null 2>&1; }; then
|
||||
_type=msvc
|
||||
_ident=$($_cc 2>&1 | head -n1 | tr -d '\r')
|
||||
_DEPCMD='$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>&1 | awk '\''/including/ { sub(/^.*file: */, ""); gsub(/\\/, "/"); if (!match($$0, / /)) print "$@:", $$0 }'\'' > $(@:.o=.d)'
|
||||
@@ -5828,7 +5830,8 @@ check_header asm/types.h
|
||||
check_builtin stdatomic stdatomic.h "atomic_int foo, bar = ATOMIC_VAR_INIT(-1); atomic_store(&foo, 0); foo += bar"
|
||||
|
||||
check_lib advapi32 "windows.h" RegCloseKey -ladvapi32
|
||||
check_lib bcrypt "windows.h bcrypt.h" BCryptGenRandom -lbcrypt
|
||||
check_lib bcrypt "windows.h bcrypt.h" BCryptGenRandom -lbcrypt &&
|
||||
check_cpp_condition bcrypt bcrypt.h "defined BCRYPT_RNG_ALGORITHM"
|
||||
check_lib ole32 "windows.h" CoTaskMemFree -lole32
|
||||
check_lib shell32 "windows.h shellapi.h" CommandLineToArgvW -lshell32
|
||||
check_lib psapi "windows.h psapi.h" GetProcessMemoryInfo -lpsapi
|
||||
@@ -5960,7 +5963,7 @@ enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gn
|
||||
enabled jni && { [ $target_os = "android" ] && check_header jni.h && enabled pthreads || die "ERROR: jni not found"; }
|
||||
enabled ladspa && require_header ladspa.h
|
||||
enabled libaom && require_pkg_config libaom "aom >= 0.1.0" aom/aom_codec.h aom_codec_version
|
||||
enabled lv2 && require_pkg_config lv2 lilv-0 "lilv-0/lilv/lilv.h" lilv_world_new
|
||||
enabled lv2 && require_pkg_config lv2 lilv-0 "lilv/lilv.h" lilv_world_new
|
||||
enabled libiec61883 && require libiec61883 libiec61883/iec61883.h iec61883_cmp_connect -lraw1394 -lavc1394 -lrom1394 -liec61883
|
||||
enabled libass && require_pkg_config libass libass ass/ass.h ass_library_init
|
||||
enabled libbluray && require_pkg_config libbluray libbluray libbluray/bluray.h bd_open
|
||||
|
||||
+2
-2
@@ -889,7 +889,7 @@ API changes, most recent first:
|
||||
Add av_opt_get_dict_val/set_dict_val with AV_OPT_TYPE_DICT to support
|
||||
dictionary types being set as options.
|
||||
|
||||
2014-08-13 - afbd4b8 - lavf 56.01.0 - avformat.h
|
||||
2014-08-13 - afbd4b7e09 - lavf 56.01.0 - avformat.h
|
||||
Add AVFormatContext.event_flags and AVStream.event_flags for signaling to
|
||||
the user when events happen in the file/stream.
|
||||
|
||||
@@ -906,7 +906,7 @@ API changes, most recent first:
|
||||
2014-08-08 - 5c3c671 - lavf 55.53.100 - avio.h
|
||||
Add avio_feof() and deprecate url_feof().
|
||||
|
||||
2014-08-07 - bb78903 - lsws 2.1.3 - swscale.h
|
||||
2014-08-07 - bb789016d4 - lsws 2.1.3 - swscale.h
|
||||
sws_getContext is not going to be removed in the future.
|
||||
|
||||
2014-08-07 - a561662 / ad1ee5f - lavc 55.73.101 / 55.57.3 - avcodec.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 = 4.0.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
|
||||
|
||||
+55
-29
@@ -2696,8 +2696,12 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo
|
||||
ist->dts = ist->next_dts;
|
||||
switch (ist->dec_ctx->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
ist->next_dts += ((int64_t)AV_TIME_BASE * ist->dec_ctx->frame_size) /
|
||||
ist->dec_ctx->sample_rate;
|
||||
if (ist->dec_ctx->sample_rate) {
|
||||
ist->next_dts += ((int64_t)AV_TIME_BASE * ist->dec_ctx->frame_size) /
|
||||
ist->dec_ctx->sample_rate;
|
||||
} else {
|
||||
ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
|
||||
}
|
||||
break;
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
if (ist->framerate.num) {
|
||||
@@ -4011,49 +4015,63 @@ static void *input_thread(void *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void free_input_thread(int i)
|
||||
{
|
||||
InputFile *f = input_files[i];
|
||||
AVPacket pkt;
|
||||
|
||||
if (!f || !f->in_thread_queue)
|
||||
return;
|
||||
av_thread_message_queue_set_err_send(f->in_thread_queue, AVERROR_EOF);
|
||||
while (av_thread_message_queue_recv(f->in_thread_queue, &pkt, 0) >= 0)
|
||||
av_packet_unref(&pkt);
|
||||
|
||||
pthread_join(f->thread, NULL);
|
||||
f->joined = 1;
|
||||
av_thread_message_queue_free(&f->in_thread_queue);
|
||||
}
|
||||
|
||||
static void free_input_threads(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nb_input_files; i++) {
|
||||
InputFile *f = input_files[i];
|
||||
AVPacket pkt;
|
||||
for (i = 0; i < nb_input_files; i++)
|
||||
free_input_thread(i);
|
||||
}
|
||||
|
||||
if (!f || !f->in_thread_queue)
|
||||
continue;
|
||||
av_thread_message_queue_set_err_send(f->in_thread_queue, AVERROR_EOF);
|
||||
while (av_thread_message_queue_recv(f->in_thread_queue, &pkt, 0) >= 0)
|
||||
av_packet_unref(&pkt);
|
||||
static int init_input_thread(int i)
|
||||
{
|
||||
int ret;
|
||||
InputFile *f = input_files[i];
|
||||
|
||||
pthread_join(f->thread, NULL);
|
||||
f->joined = 1;
|
||||
if (nb_input_files == 1)
|
||||
return 0;
|
||||
|
||||
if (f->ctx->pb ? !f->ctx->pb->seekable :
|
||||
strcmp(f->ctx->iformat->name, "lavfi"))
|
||||
f->non_blocking = 1;
|
||||
ret = av_thread_message_queue_alloc(&f->in_thread_queue,
|
||||
f->thread_queue_size, sizeof(AVPacket));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret = pthread_create(&f->thread, NULL, input_thread, f))) {
|
||||
av_log(NULL, AV_LOG_ERROR, "pthread_create failed: %s. Try to increase `ulimit -v` or decrease `ulimit -s`.\n", strerror(ret));
|
||||
av_thread_message_queue_free(&f->in_thread_queue);
|
||||
return AVERROR(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_input_threads(void)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
if (nb_input_files == 1)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < nb_input_files; i++) {
|
||||
InputFile *f = input_files[i];
|
||||
|
||||
if (f->ctx->pb ? !f->ctx->pb->seekable :
|
||||
strcmp(f->ctx->iformat->name, "lavfi"))
|
||||
f->non_blocking = 1;
|
||||
ret = av_thread_message_queue_alloc(&f->in_thread_queue,
|
||||
f->thread_queue_size, sizeof(AVPacket));
|
||||
ret = init_input_thread(i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret = pthread_create(&f->thread, NULL, input_thread, f))) {
|
||||
av_log(NULL, AV_LOG_ERROR, "pthread_create failed: %s. Try to increase `ulimit -v` or decrease `ulimit -s`.\n", strerror(ret));
|
||||
av_thread_message_queue_free(&f->in_thread_queue);
|
||||
return AVERROR(ret);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -4195,7 +4213,7 @@ static int process_input(int file_index)
|
||||
AVFormatContext *is;
|
||||
InputStream *ist;
|
||||
AVPacket pkt;
|
||||
int ret, i, j;
|
||||
int ret, thread_ret, i, j;
|
||||
int64_t duration;
|
||||
int64_t pkt_dts;
|
||||
|
||||
@@ -4218,7 +4236,15 @@ static int process_input(int file_index)
|
||||
avcodec_flush_buffers(avctx);
|
||||
}
|
||||
}
|
||||
#if HAVE_THREADS
|
||||
free_input_thread(file_index);
|
||||
#endif
|
||||
ret = seek_to_start(ifile, is);
|
||||
#if HAVE_THREADS
|
||||
thread_ret = init_input_thread(file_index);
|
||||
if (thread_ret < 0)
|
||||
return thread_ret;
|
||||
#endif
|
||||
if (ret < 0)
|
||||
av_log(NULL, AV_LOG_WARNING, "Seek to start failed.\n");
|
||||
else
|
||||
|
||||
+3
-2
@@ -834,10 +834,11 @@ static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_wid
|
||||
{
|
||||
Uint32 format;
|
||||
int access, w, h;
|
||||
if (SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 || new_width != w || new_height != h || new_format != format) {
|
||||
if (!*texture || SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 || new_width != w || new_height != h || new_format != format) {
|
||||
void *pixels;
|
||||
int pitch;
|
||||
SDL_DestroyTexture(*texture);
|
||||
if (*texture)
|
||||
SDL_DestroyTexture(*texture);
|
||||
if (!(*texture = SDL_CreateTexture(renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height)))
|
||||
return -1;
|
||||
if (SDL_SetTextureBlendMode(*texture, blendmode) < 0)
|
||||
|
||||
+3
-3
@@ -2371,11 +2371,11 @@ static int read_interval_packets(WriterContext *w, InputFile *ifile,
|
||||
goto end;
|
||||
}
|
||||
while (!av_read_frame(fmt_ctx, &pkt)) {
|
||||
if (ifile->nb_streams > nb_streams) {
|
||||
if (fmt_ctx->nb_streams > nb_streams) {
|
||||
REALLOCZ_ARRAY_STREAM(nb_streams_frames, nb_streams, fmt_ctx->nb_streams);
|
||||
REALLOCZ_ARRAY_STREAM(nb_streams_packets, nb_streams, fmt_ctx->nb_streams);
|
||||
REALLOCZ_ARRAY_STREAM(selected_streams, nb_streams, fmt_ctx->nb_streams);
|
||||
nb_streams = ifile->nb_streams;
|
||||
nb_streams = fmt_ctx->nb_streams;
|
||||
}
|
||||
if (selected_streams[pkt.stream_index]) {
|
||||
AVRational tb = ifile->streams[pkt.stream_index].st->time_base;
|
||||
@@ -2521,7 +2521,7 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
|
||||
#endif
|
||||
print_int("has_b_frames", par->video_delay);
|
||||
sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL);
|
||||
if (sar.den) {
|
||||
if (sar.num) {
|
||||
print_q("sample_aspect_ratio", sar, ':');
|
||||
av_reduce(&dar.num, &dar.den,
|
||||
par->width * sar.num,
|
||||
|
||||
@@ -385,7 +385,7 @@ static void apply_dependent_coupling_fixed(AACContext *ac,
|
||||
for (k = offsets[i]; k < offsets[i + 1]; k++) {
|
||||
tmp = (int)(((int64_t)src[group * 128 + k] * c + \
|
||||
(int64_t)0x1000000000) >> 37);
|
||||
dest[group * 128 + k] += (tmp + round) >> shift;
|
||||
dest[group * 128 + k] += (tmp + (int64_t)round) >> shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -436,7 +436,7 @@ static void apply_independent_coupling_fixed(AACContext *ac,
|
||||
else {
|
||||
for (i = 0; i < len; i++) {
|
||||
tmp = (int)(((int64_t)src[i] * c + (int64_t)0x1000000000) >> 37);
|
||||
dest[i] += tmp * (1 << shift);
|
||||
dest[i] += tmp * (1U << shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,10 +181,10 @@ static void ps_stereo_interpolate_ipdopd_c(INTFLOAT (*l)[2], INTFLOAT (*r)[2],
|
||||
INTFLOAT h01 = h[0][1], h11 = h[1][1];
|
||||
INTFLOAT h02 = h[0][2], h12 = h[1][2];
|
||||
INTFLOAT h03 = h[0][3], h13 = h[1][3];
|
||||
INTFLOAT hs00 = h_step[0][0], hs10 = h_step[1][0];
|
||||
INTFLOAT hs01 = h_step[0][1], hs11 = h_step[1][1];
|
||||
INTFLOAT hs02 = h_step[0][2], hs12 = h_step[1][2];
|
||||
INTFLOAT hs03 = h_step[0][3], hs13 = h_step[1][3];
|
||||
UINTFLOAT hs00 = h_step[0][0], hs10 = h_step[1][0];
|
||||
UINTFLOAT hs01 = h_step[0][1], hs11 = h_step[1][1];
|
||||
UINTFLOAT hs02 = h_step[0][2], hs12 = h_step[1][2];
|
||||
UINTFLOAT hs03 = h_step[0][3], hs13 = h_step[1][3];
|
||||
int n;
|
||||
|
||||
for (n = 0; n < len; n++) {
|
||||
|
||||
@@ -162,7 +162,9 @@ int avpriv_ac3_parse_header(AC3HeaderInfo **phdr, const uint8_t *buf,
|
||||
return AVERROR(ENOMEM);
|
||||
hdr = *phdr;
|
||||
|
||||
init_get_bits8(&gb, buf, size);
|
||||
err = init_get_bits8(&gb, buf, size);
|
||||
if (err < 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
err = ff_ac3_parse_header(&gb, hdr);
|
||||
if (err < 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
+18
-1
@@ -1690,6 +1690,7 @@ dependent_frame:
|
||||
|
||||
if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) {
|
||||
uint64_t ich_layout = avpriv_ac3_channel_layout_tab[s->prev_output_mode & ~AC3_OUTPUT_LFEON];
|
||||
int channel_map_size = ff_ac3_channels_tab[s->output_mode & ~AC3_OUTPUT_LFEON] + s->lfe_on;
|
||||
uint64_t channel_layout;
|
||||
int extend = 0;
|
||||
|
||||
@@ -1702,6 +1703,11 @@ dependent_frame:
|
||||
channel_layout |= custom_channel_map_locations[ch][1];
|
||||
}
|
||||
}
|
||||
if (av_get_channel_layout_nb_channels(channel_layout) > EAC3_MAX_CHANNELS) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Too many channels (%d) coded\n",
|
||||
av_get_channel_layout_nb_channels(channel_layout));
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
avctx->channel_layout = channel_layout;
|
||||
avctx->channels = av_get_channel_layout_nb_channels(channel_layout);
|
||||
@@ -1713,6 +1719,9 @@ dependent_frame:
|
||||
custom_channel_map_locations[ch][1]);
|
||||
if (index < 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
if (extend >= channel_map_size)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
extended_channel_map[index] = offset + channel_map[extend++];
|
||||
} else {
|
||||
int i;
|
||||
@@ -1723,6 +1732,9 @@ dependent_frame:
|
||||
1LL << i);
|
||||
if (index < 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
if (extend >= channel_map_size)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
extended_channel_map[index] = offset + channel_map[extend++];
|
||||
}
|
||||
}
|
||||
@@ -1738,7 +1750,9 @@ dependent_frame:
|
||||
|
||||
for (ch = 0; ch < avctx->channels; ch++) {
|
||||
int map = extended_channel_map[ch];
|
||||
memcpy((SHORTFLOAT *)frame->data[ch], s->output_buffer[map],
|
||||
av_assert0(ch>=AV_NUM_DATA_POINTERS || frame->extended_data[ch] == frame->data[ch]);
|
||||
memcpy((SHORTFLOAT *)frame->extended_data[ch],
|
||||
s->output_buffer[map],
|
||||
s->num_blocks * AC3_BLOCK_SIZE * sizeof(SHORTFLOAT));
|
||||
}
|
||||
|
||||
@@ -1800,6 +1814,9 @@ dependent_frame:
|
||||
|
||||
*got_frame_ptr = 1;
|
||||
|
||||
if (!s->superframe_size)
|
||||
return FFMIN(full_buf_size, s->frame_size);
|
||||
|
||||
return FFMIN(full_buf_size, s->superframe_size);
|
||||
}
|
||||
|
||||
|
||||
@@ -862,15 +862,20 @@ static float find_hb_gain(AMRWBContext *ctx, const float *synth,
|
||||
{
|
||||
int wsp = (vad > 0);
|
||||
float tilt;
|
||||
float tmp;
|
||||
|
||||
if (ctx->fr_cur_mode == MODE_23k85)
|
||||
return qua_hb_gain[hb_idx] * (1.0f / (1 << 14));
|
||||
|
||||
tilt = ctx->celpm_ctx.dot_productf(synth, synth + 1, AMRWB_SFR_SIZE - 1) /
|
||||
ctx->celpm_ctx.dot_productf(synth, synth, AMRWB_SFR_SIZE);
|
||||
tmp = ctx->celpm_ctx.dot_productf(synth, synth + 1, AMRWB_SFR_SIZE - 1);
|
||||
|
||||
if (tmp > 0) {
|
||||
tilt = tmp / ctx->celpm_ctx.dot_productf(synth, synth, AMRWB_SFR_SIZE);
|
||||
} else
|
||||
tilt = 0;
|
||||
|
||||
/* return gain bounded by [0.1, 1.0] */
|
||||
return av_clipf((1.0 - FFMAX(0.0, tilt)) * (1.25 - 0.25 * wsp), 0.1, 1.0);
|
||||
return av_clipf((1.0 - tilt) * (1.25 - 0.25 * wsp), 0.1, 1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
|
||||
|
||||
bytestream2_skipu(&s->gb, 16 * 8);
|
||||
for (i = 0; i < 256; i++)
|
||||
s->palette[i] = bytestream2_get_le32u(&s->gb);
|
||||
s->palette[i] = (0xFFU << 24) | bytestream2_get_le32u(&s->gb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+29
-5
@@ -315,14 +315,11 @@ static int cinepak_decode_strip (CinepakContext *s,
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
static int cinepak_decode (CinepakContext *s)
|
||||
static int cinepak_predecode_check (CinepakContext *s)
|
||||
{
|
||||
const uint8_t *eod = (s->data + s->size);
|
||||
int i, result, strip_size, frame_flags, num_strips;
|
||||
int y0 = 0;
|
||||
int num_strips;
|
||||
int encoded_buf_size;
|
||||
|
||||
frame_flags = s->data[0];
|
||||
num_strips = AV_RB16 (&s->data[8]);
|
||||
encoded_buf_size = AV_RB24(&s->data[1]);
|
||||
|
||||
@@ -353,6 +350,21 @@ static int cinepak_decode (CinepakContext *s)
|
||||
s->sega_film_skip_bytes = 0;
|
||||
}
|
||||
|
||||
if (s->size < 10 + s->sega_film_skip_bytes + num_strips * 12)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cinepak_decode (CinepakContext *s)
|
||||
{
|
||||
const uint8_t *eod = (s->data + s->size);
|
||||
int i, result, strip_size, frame_flags, num_strips;
|
||||
int y0 = 0;
|
||||
|
||||
frame_flags = s->data[0];
|
||||
num_strips = AV_RB16 (&s->data[8]);
|
||||
|
||||
s->data += 10 + s->sega_film_skip_bytes;
|
||||
|
||||
num_strips = FFMIN(num_strips, MAX_STRIPS);
|
||||
@@ -432,6 +444,7 @@ static int cinepak_decode_frame(AVCodecContext *avctx,
|
||||
const uint8_t *buf = avpkt->data;
|
||||
int ret = 0, buf_size = avpkt->size;
|
||||
CinepakContext *s = avctx->priv_data;
|
||||
int num_strips;
|
||||
|
||||
s->data = buf;
|
||||
s->size = buf_size;
|
||||
@@ -439,6 +452,17 @@ static int cinepak_decode_frame(AVCodecContext *avctx,
|
||||
if (s->size < 10)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
num_strips = AV_RB16 (&s->data[8]);
|
||||
|
||||
//Empty frame, do not waste time
|
||||
if (!num_strips && (!s->palette_video || !av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL)))
|
||||
return buf_size;
|
||||
|
||||
if ((ret = cinepak_predecode_check(s)) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "cinepak_predecode_check failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
|
||||
return ret;
|
||||
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
switch ((buf[0] >> 1) & 7) {
|
||||
case 0: { // lzo compression
|
||||
int outlen = c->decomp_size, inlen = buf_size - 2;
|
||||
if (av_lzo1x_decode(c->decomp_buf, &outlen, &buf[2], &inlen)) {
|
||||
if (av_lzo1x_decode(c->decomp_buf, &outlen, &buf[2], &inlen) || outlen) {
|
||||
av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ static av_cold int dfa_decode_init(AVCodecContext *avctx)
|
||||
|
||||
avctx->pix_fmt = AV_PIX_FMT_PAL8;
|
||||
|
||||
if (!avctx->width || !avctx->height)
|
||||
if (!avctx->width || !avctx->height || FFMAX(avctx->width, avctx->height) >= (1<<16))
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
av_assert0(av_image_check_size(avctx->width, avctx->height, 0, avctx) >= 0);
|
||||
|
||||
@@ -99,10 +99,10 @@ void ff_spatial_idwt_slice2(DWTContext *d, int y);
|
||||
(b1 + (unsigned)((int)(b0 + (unsigned)(b2) + 1) >> 1))
|
||||
|
||||
#define COMPOSE_DD97iH0(b0, b1, b2, b3, b4)\
|
||||
(int)(((unsigned)(b2) + ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 8) >> 4)))
|
||||
(int)(((unsigned)(b2) + ((int)(9U*b1 + 9U*b3 - b4 - b0 + 8) >> 4)))
|
||||
|
||||
#define COMPOSE_DD137iL0(b0, b1, b2, b3, b4)\
|
||||
(int)(((unsigned)(b2) - ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 16) >> 5)))
|
||||
(int)(((unsigned)(b2) - ((int)(9U*b1 + 9U*b3 - b4 - b0 + 16) >> 5)))
|
||||
|
||||
#define COMPOSE_HAARiL0(b0, b1)\
|
||||
((int)(b0 - (unsigned)((int)(b1 + 1U) >> 1)))
|
||||
|
||||
@@ -57,8 +57,8 @@ static av_always_inline void RENAME(interleave)(TYPE *dst, TYPE *src0, TYPE *src
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < w2; i++) {
|
||||
dst[2*i ] = (src0[i] + add) >> shift;
|
||||
dst[2*i+1] = (src1[i] + add) >> shift;
|
||||
dst[2*i ] = ((int)(src0[i] + (unsigned)add)) >> shift;
|
||||
dst[2*i+1] = ((int)(src1[i] + (unsigned)add)) >> shift;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -408,12 +408,14 @@ static int decode_frame(AVCodecContext *avctx,
|
||||
if (elements == 4)
|
||||
*dst[3]++ = read16(&buf, endian) >> 4;
|
||||
} else {
|
||||
*dst[2]++ = read12in32(&buf, &rgbBuffer,
|
||||
&n_datum, endian);
|
||||
if (elements >= 3)
|
||||
*dst[2]++ = read12in32(&buf, &rgbBuffer,
|
||||
&n_datum, endian);
|
||||
*dst[0]++ = read12in32(&buf, &rgbBuffer,
|
||||
&n_datum, endian);
|
||||
*dst[1]++ = read12in32(&buf, &rgbBuffer,
|
||||
&n_datum, endian);
|
||||
if (elements >= 2)
|
||||
*dst[1]++ = read12in32(&buf, &rgbBuffer,
|
||||
&n_datum, endian);
|
||||
if (elements == 4)
|
||||
*dst[3]++ = read12in32(&buf, &rgbBuffer,
|
||||
&n_datum, endian);
|
||||
|
||||
@@ -158,6 +158,9 @@ static int cin_decode_lzss(const unsigned char *src, int src_size,
|
||||
}
|
||||
}
|
||||
|
||||
if (dst_end - dst > dst_size - dst_size/10)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -184,6 +187,10 @@ static int cin_decode_rle(const unsigned char *src, int src_size,
|
||||
}
|
||||
dst += len;
|
||||
}
|
||||
|
||||
if (dst_end - dst > dst_size - dst_size/10)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -226,27 +233,35 @@ static int cinvideo_decode_frame(AVCodecContext *avctx,
|
||||
* surface.width = surface.pitch */
|
||||
switch (bitmap_frame_type) {
|
||||
case 9:
|
||||
cin_decode_rle(buf, bitmap_frame_size,
|
||||
res = cin_decode_rle(buf, bitmap_frame_size,
|
||||
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
|
||||
if (res < 0)
|
||||
return res;
|
||||
break;
|
||||
case 34:
|
||||
cin_decode_rle(buf, bitmap_frame_size,
|
||||
res = cin_decode_rle(buf, bitmap_frame_size,
|
||||
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
|
||||
if (res < 0)
|
||||
return res;
|
||||
cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP],
|
||||
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
|
||||
break;
|
||||
case 35:
|
||||
bitmap_frame_size = cin_decode_huffman(buf, bitmap_frame_size,
|
||||
cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size);
|
||||
cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size,
|
||||
res = cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size,
|
||||
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
|
||||
if (res < 0)
|
||||
return res;
|
||||
break;
|
||||
case 36:
|
||||
bitmap_frame_size = cin_decode_huffman(buf, bitmap_frame_size,
|
||||
cin->bitmap_table[CIN_INT_BMP],
|
||||
cin->bitmap_size);
|
||||
cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size,
|
||||
res = cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size,
|
||||
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
|
||||
if (res < 0)
|
||||
return res;
|
||||
cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP],
|
||||
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
|
||||
break;
|
||||
|
||||
@@ -93,7 +93,7 @@ static const AVClass dump_extradata_class = {
|
||||
.class_name = "dump_extradata bsf",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVUTIL_VERSION_MAJOR,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
const AVBitStreamFilter ff_dump_extradata_bsf = {
|
||||
|
||||
@@ -44,6 +44,9 @@ static int dvdsub_parse(AVCodecParserContext *s,
|
||||
{
|
||||
DVDSubParseContext *pc = s->priv_data;
|
||||
|
||||
*poutbuf = buf;
|
||||
*poutbuf_size = buf_size;
|
||||
|
||||
if (pc->packet_index == 0) {
|
||||
if (buf_size < 2 || AV_RB16(buf) && buf_size < 6) {
|
||||
if (buf_size)
|
||||
@@ -54,7 +57,11 @@ static int dvdsub_parse(AVCodecParserContext *s,
|
||||
if (pc->packet_len == 0) /* HD-DVD subpicture packet */
|
||||
pc->packet_len = AV_RB32(buf+2);
|
||||
av_freep(&pc->packet);
|
||||
pc->packet = av_malloc(pc->packet_len);
|
||||
if ((unsigned)pc->packet_len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
|
||||
av_log(avctx, AV_LOG_ERROR, "packet length %d is invalid\n", pc->packet_len);
|
||||
return buf_size;
|
||||
}
|
||||
pc->packet = av_malloc(pc->packet_len + AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
}
|
||||
if (pc->packet) {
|
||||
if (pc->packet_index + buf_size <= pc->packet_len) {
|
||||
|
||||
+3
-5
@@ -271,7 +271,7 @@ void ff_els_decoder_init(ElsDecCtx *ctx, const uint8_t *in, size_t data_size)
|
||||
|
||||
void ff_els_decoder_uninit(ElsUnsignedRung *rung)
|
||||
{
|
||||
av_free(rung->rem_rung_list);
|
||||
av_freep(&rung->rem_rung_list);
|
||||
}
|
||||
|
||||
static int els_import_byte(ElsDecCtx *ctx)
|
||||
@@ -391,12 +391,10 @@ unsigned ff_els_decode_unsigned(ElsDecCtx *ctx, ElsUnsignedRung *ur)
|
||||
if (ur->rung_list_size <= (ur->avail_index + 2) * sizeof(ElsRungNode)) {
|
||||
// remember rung_node position
|
||||
ptrdiff_t pos = rung_node - ur->rem_rung_list;
|
||||
ur->rem_rung_list = av_realloc(ur->rem_rung_list,
|
||||
ctx->err = av_reallocp(&ur->rem_rung_list,
|
||||
ur->rung_list_size +
|
||||
RUNG_SPACE);
|
||||
if (!ur->rem_rung_list) {
|
||||
av_free(ur->rem_rung_list);
|
||||
ctx->err = AVERROR(ENOMEM);
|
||||
if (ctx->err < 0) {
|
||||
return 0;
|
||||
}
|
||||
memset((uint8_t *) ur->rem_rung_list + ur->rung_list_size, 0,
|
||||
|
||||
@@ -107,7 +107,7 @@ static void filter181(int16_t *data, int width, int height, ptrdiff_t stride)
|
||||
dc = -prev_dc +
|
||||
data[x + y * stride] * 8 -
|
||||
data[x + 1 + y * stride];
|
||||
dc = (dc * 10923 + 32768) >> 16;
|
||||
dc = (av_clip(dc, INT_MIN/10923, INT_MAX/10923 - 32768) * 10923 + 32768) >> 16;
|
||||
prev_dc = data[x + y * stride];
|
||||
data[x + y * stride] = dc;
|
||||
}
|
||||
@@ -123,7 +123,7 @@ static void filter181(int16_t *data, int width, int height, ptrdiff_t stride)
|
||||
dc = -prev_dc +
|
||||
data[x + y * stride] * 8 -
|
||||
data[x + (y + 1) * stride];
|
||||
dc = (dc * 10923 + 32768) >> 16;
|
||||
dc = (av_clip(dc, INT_MIN/10923, INT_MAX/10923 - 32768) * 10923 + 32768) >> 16;
|
||||
prev_dc = data[x + y * stride];
|
||||
data[x + y * stride] = dc;
|
||||
}
|
||||
@@ -814,8 +814,7 @@ static int er_supported(ERContext *s)
|
||||
{
|
||||
if(s->avctx->hwaccel && s->avctx->hwaccel->decode_slice ||
|
||||
!s->cur_pic.f ||
|
||||
s->cur_pic.field_picture ||
|
||||
s->avctx->profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO
|
||||
s->cur_pic.field_picture
|
||||
)
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
@@ -221,7 +221,11 @@ static int escape124_decode_frame(AVCodecContext *avctx,
|
||||
|
||||
// This call also guards the potential depth reads for the
|
||||
// codebook unpacking.
|
||||
if (get_bits_left(&gb) < 64)
|
||||
// Check if the amount we will read minimally is available on input.
|
||||
// The 64 represent the immediately next 2 frame_* elements read, the 23/4320
|
||||
// represent a lower bound of the space needed for skipped superblocks. Non
|
||||
// skipped SBs need more space.
|
||||
if (get_bits_left(&gb) < 64 + s->num_superblocks * 23LL / 4320)
|
||||
return -1;
|
||||
|
||||
frame_flags = get_bits_long(&gb, 32);
|
||||
|
||||
@@ -539,6 +539,10 @@ static av_cold int encode_init(AVCodecContext *avctx)
|
||||
s->ec = (s->version >= 3);
|
||||
}
|
||||
|
||||
// CRC requires version 3+
|
||||
if (s->ec)
|
||||
s->version = FFMAX(s->version, 3);
|
||||
|
||||
if ((s->version == 2 || s->version>3) && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Version 2 needed for requested features but version 2 is experimental and not enabled\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
+6
-1
@@ -82,6 +82,7 @@ static const uint8_t fic_qmat_lq[64] = {
|
||||
static const uint8_t fic_header[7] = { 0, 0, 1, 'F', 'I', 'C', 'V' };
|
||||
|
||||
#define FIC_HEADER_SIZE 27
|
||||
#define CURSOR_OFFSET 59
|
||||
|
||||
static av_always_inline void fic_idct(int16_t *blk, int step, int shift, int rnd)
|
||||
{
|
||||
@@ -337,6 +338,10 @@ static int fic_decode_frame(AVCodecContext *avctx, void *data,
|
||||
skip_cursor = 1;
|
||||
}
|
||||
|
||||
if (!skip_cursor && avpkt->size < CURSOR_OFFSET + sizeof(ctx->cursor_buf)) {
|
||||
skip_cursor = 1;
|
||||
}
|
||||
|
||||
/* Slice height for all but the last slice. */
|
||||
ctx->slice_h = 16 * (ctx->aligned_height >> 4) / nslices;
|
||||
if (ctx->slice_h % 16)
|
||||
@@ -416,7 +421,7 @@ static int fic_decode_frame(AVCodecContext *avctx, void *data,
|
||||
|
||||
/* Draw cursor. */
|
||||
if (!skip_cursor) {
|
||||
memcpy(ctx->cursor_buf, src + 59, 32 * 32 * 4);
|
||||
memcpy(ctx->cursor_buf, src + CURSOR_OFFSET, sizeof(ctx->cursor_buf));
|
||||
fic_draw_cursor(avctx, cur_x, cur_y);
|
||||
}
|
||||
|
||||
|
||||
@@ -686,12 +686,17 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
|
||||
}
|
||||
|
||||
for (curr = fpc->headers; curr; curr = curr->next) {
|
||||
if (curr->max_score > 0 &&
|
||||
(!fpc->best_header || curr->max_score > fpc->best_header->max_score)) {
|
||||
if (!fpc->best_header || curr->max_score > fpc->best_header->max_score) {
|
||||
fpc->best_header = curr;
|
||||
}
|
||||
}
|
||||
|
||||
if (fpc->best_header && fpc->best_header->max_score <= 0) {
|
||||
// Only accept a bad header if there is no other option to continue
|
||||
if (!buf_size || !buf || read_end != buf || fpc->nb_headers_buffered < FLAC_MIN_HEADERS)
|
||||
fpc->best_header = NULL;
|
||||
}
|
||||
|
||||
if (fpc->best_header) {
|
||||
fpc->best_header_valid = 1;
|
||||
if (fpc->best_header->offset > 0) {
|
||||
|
||||
+8
-5
@@ -556,8 +556,8 @@ static uint32_t epic_decode_pixel_pred(ePICContext *dc, int x, int y,
|
||||
B = ((pred >> B_shift) & 0xFF) - TOSIGNED(delta);
|
||||
}
|
||||
|
||||
if (R<0 || G<0 || B<0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "RGB %d %d %d is out of range\n", R, G, B);
|
||||
if (R<0 || G<0 || B<0 || R > 255 || G > 255 || B > 255) {
|
||||
avpriv_request_sample(NULL, "RGB %d %d %d is out of range\n", R, G, B);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -927,6 +927,7 @@ static int epic_jb_decode_tile(G2MContext *c, int tile_x, int tile_y,
|
||||
if (c->ec.els_ctx.err != 0) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"ePIC: couldn't decode transparency pixel!\n");
|
||||
ff_els_decoder_uninit(&c->ec.unsigned_rung);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
@@ -1355,14 +1356,16 @@ static void g2m_paint_cursor(G2MContext *c, uint8_t *dst, int stride)
|
||||
} else {
|
||||
dst += x * 3;
|
||||
}
|
||||
if (y < 0) {
|
||||
|
||||
if (y < 0)
|
||||
h += y;
|
||||
if (w < 0 || h < 0)
|
||||
return;
|
||||
if (y < 0) {
|
||||
cursor += -y * c->cursor_stride;
|
||||
} else {
|
||||
dst += y * stride;
|
||||
}
|
||||
if (w < 0 || h < 0)
|
||||
return;
|
||||
|
||||
for (j = 0; j < h; j++) {
|
||||
for (i = 0; i < w; i++) {
|
||||
|
||||
@@ -549,7 +549,7 @@ static void gain_scale(G723_1_Context *p, int16_t * buf, int energy)
|
||||
denom <<= bits2;
|
||||
|
||||
bits2 = 5 + bits1 - bits2;
|
||||
bits2 = FFMAX(0, bits2);
|
||||
bits2 = av_clip_uintp2(bits2, 5);
|
||||
|
||||
gain = (num >> 1) / (denom >> 16);
|
||||
gain = square_root(gain << 16 >> bits2);
|
||||
|
||||
@@ -47,9 +47,10 @@
|
||||
|
||||
static enum AVPixelFormat h263_get_format(AVCodecContext *avctx)
|
||||
{
|
||||
MpegEncContext *s = avctx->priv_data;
|
||||
/* MPEG-4 Studio Profile only, not supported by hardware */
|
||||
if (avctx->bits_per_raw_sample > 8) {
|
||||
av_assert1(avctx->profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO);
|
||||
av_assert1(s->studio_profile);
|
||||
return avctx->pix_fmt;
|
||||
}
|
||||
|
||||
@@ -545,6 +546,8 @@ retry:
|
||||
if (CONFIG_MPEG4_DECODER && avctx->codec_id == AV_CODEC_ID_MPEG4) {
|
||||
if (ff_mpeg4_workaround_bugs(avctx) == 1)
|
||||
goto retry;
|
||||
if (s->studio_profile != (s->idsp.idct == NULL))
|
||||
ff_mpv_idct_init(s);
|
||||
}
|
||||
|
||||
/* After H.263 & MPEG-4 header decode we have the height, width,
|
||||
@@ -641,7 +644,7 @@ retry:
|
||||
slice_ret = decode_slice(s);
|
||||
while (s->mb_y < s->mb_height) {
|
||||
if (s->msmpeg4_version) {
|
||||
if (s->slice_height == 0 || s->mb_x != 0 ||
|
||||
if (s->slice_height == 0 || s->mb_x != 0 || slice_ret < 0 ||
|
||||
(s->mb_y % s->slice_height) != 0 || get_bits_left(&s->gb) < 0)
|
||||
break;
|
||||
} else {
|
||||
@@ -667,7 +670,8 @@ retry:
|
||||
|
||||
av_assert1(s->bitstream_buffer_size == 0);
|
||||
frame_end:
|
||||
ff_er_frame_end(&s->er);
|
||||
if (!s->studio_profile)
|
||||
ff_er_frame_end(&s->er);
|
||||
|
||||
if (avctx->hwaccel) {
|
||||
ret = avctx->hwaccel->end_frame(avctx);
|
||||
|
||||
@@ -78,7 +78,8 @@ static void MCFUNC(hl_motion)(const H264Context *h, H264SliceContext *sl,
|
||||
|
||||
if (HAVE_THREADS && (h->avctx->active_thread_type & FF_THREAD_FRAME))
|
||||
await_references(h, sl);
|
||||
prefetch_motion(h, sl, 0, PIXEL_SHIFT, CHROMA_IDC);
|
||||
if (USES_LIST(mb_type, 0))
|
||||
prefetch_motion(h, sl, 0, PIXEL_SHIFT, CHROMA_IDC);
|
||||
|
||||
if (IS_16X16(mb_type)) {
|
||||
mc_part(h, sl, 0, 1, 16, 0, dest_y, dest_cb, dest_cr, 0, 0,
|
||||
|
||||
@@ -121,20 +121,23 @@ static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf,
|
||||
}
|
||||
state = 7;
|
||||
} else {
|
||||
unsigned int mb, last_mb = p->parse_last_mb;
|
||||
GetBitContext gb;
|
||||
p->parse_history[p->parse_history_count++] = buf[i];
|
||||
if (p->parse_history_count > 5) {
|
||||
unsigned int mb, last_mb = p->parse_last_mb;
|
||||
GetBitContext gb;
|
||||
|
||||
init_get_bits(&gb, p->parse_history, 8*p->parse_history_count);
|
||||
p->parse_history_count = 0;
|
||||
mb= get_ue_golomb_long(&gb);
|
||||
init_get_bits(&gb, p->parse_history, 8*p->parse_history_count);
|
||||
mb= get_ue_golomb_long(&gb);
|
||||
if (get_bits_left(&gb) > 0 || p->parse_history_count > 5) {
|
||||
p->parse_last_mb = mb;
|
||||
if (pc->frame_start_found) {
|
||||
if (mb <= last_mb)
|
||||
if (mb <= last_mb) {
|
||||
i -= p->parse_history_count - 1;
|
||||
p->parse_history_count = 0;
|
||||
goto found;
|
||||
}
|
||||
} else
|
||||
pc->frame_start_found = 1;
|
||||
p->parse_history_count = 0;
|
||||
state = 7;
|
||||
}
|
||||
}
|
||||
@@ -149,7 +152,7 @@ found:
|
||||
pc->frame_start_found = 0;
|
||||
if (p->is_avc)
|
||||
return next_avc;
|
||||
return i - (state & 5) - 5 * (state > 7);
|
||||
return i - (state & 5);
|
||||
}
|
||||
|
||||
static int scan_mmco_reset(AVCodecParserContext *s, GetBitContext *gb,
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include "h264_ps.h"
|
||||
#include "golomb.h"
|
||||
|
||||
#define MAX_LOG2_MAX_FRAME_NUM (12 + 4)
|
||||
#define MIN_LOG2_MAX_FRAME_NUM 4
|
||||
|
||||
#define EXTENDED_SAR 255
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#define MAX_SPS_COUNT 32
|
||||
#define MAX_PPS_COUNT 256
|
||||
#define MAX_LOG2_MAX_FRAME_NUM (12 + 4)
|
||||
|
||||
/**
|
||||
* Sequence parameter set
|
||||
|
||||
@@ -261,10 +261,16 @@ static int decode_unregistered_user_data(H264SEIUnregistered *h, GetBitContext *
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_recovery_point(H264SEIRecoveryPoint *h, GetBitContext *gb)
|
||||
static int decode_recovery_point(H264SEIRecoveryPoint *h, GetBitContext *gb, void *logctx)
|
||||
{
|
||||
h->recovery_frame_cnt = get_ue_golomb_long(gb);
|
||||
unsigned recovery_frame_cnt = get_ue_golomb_long(gb);
|
||||
|
||||
if (recovery_frame_cnt >= (1<<MAX_LOG2_MAX_FRAME_NUM)) {
|
||||
av_log(logctx, AV_LOG_ERROR, "recovery_frame_cnt %u is out of range\n", recovery_frame_cnt);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
h->recovery_frame_cnt = recovery_frame_cnt;
|
||||
/* 1b exact_match_flag,
|
||||
* 1b broken_link_flag,
|
||||
* 2b changing_slice_group_idc */
|
||||
@@ -429,7 +435,7 @@ int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb,
|
||||
ret = decode_unregistered_user_data(&h->unregistered, gb, logctx, size);
|
||||
break;
|
||||
case H264_SEI_TYPE_RECOVERY_POINT:
|
||||
ret = decode_recovery_point(&h->recovery_point, gb);
|
||||
ret = decode_recovery_point(&h->recovery_point, gb, logctx);
|
||||
break;
|
||||
case H264_SEI_TYPE_BUFFERING_PERIOD:
|
||||
ret = decode_buffering_period(&h->buffering_period, gb, ps, logctx);
|
||||
|
||||
@@ -122,7 +122,7 @@ static const AVClass hapqa_extract_class = {
|
||||
.class_name = "hapqa_extract_bsf",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVUTIL_VERSION_MAJOR,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
const AVBitStreamFilter ff_hapqa_extract_bsf = {
|
||||
|
||||
@@ -208,9 +208,6 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush)
|
||||
if (nb_output) {
|
||||
HEVCFrame *frame = &s->DPB[min_idx];
|
||||
|
||||
if (frame->frame->format == AV_PIX_FMT_VIDEOTOOLBOX && frame->frame->buf[0]->size == 1)
|
||||
return 0;
|
||||
|
||||
ret = av_frame_ref(out, frame->frame);
|
||||
if (frame->flags & HEVC_FRAME_FLAG_BUMPING)
|
||||
ff_hevc_unref_frame(s, frame, HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_BUMPING);
|
||||
@@ -511,12 +508,12 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ff_hevc_frame_nb_refs(HEVCContext *s)
|
||||
int ff_hevc_frame_nb_refs(const HEVCContext *s)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
const ShortTermRPS *rps = s->sh.short_term_rps;
|
||||
LongTermRPS *long_rps = &s->sh.long_term_rps;
|
||||
const LongTermRPS *long_rps = &s->sh.long_term_rps;
|
||||
|
||||
if (rps) {
|
||||
for (i = 0; i < rps->num_negative_pics; i++)
|
||||
|
||||
@@ -544,7 +544,7 @@ int ff_hevc_res_scale_sign_flag(HEVCContext *s, int idx);
|
||||
/**
|
||||
* Get the number of candidate references for the current frame.
|
||||
*/
|
||||
int ff_hevc_frame_nb_refs(HEVCContext *s);
|
||||
int ff_hevc_frame_nb_refs(const HEVCContext *s);
|
||||
|
||||
int ff_hevc_set_new_ref(HEVCContext *s, AVFrame **frame, int poc);
|
||||
|
||||
|
||||
@@ -375,6 +375,7 @@ static void hnm_update_palette(AVCodecContext *avctx, uint8_t *src,
|
||||
hnm->palette[writeoffset] = bytestream2_get_be24(&gb);
|
||||
if (!eight_bit_colors)
|
||||
hnm->palette[writeoffset] <<= 2;
|
||||
hnm->palette[writeoffset] |= (0xFFU << 24);
|
||||
count--;
|
||||
writeoffset++;
|
||||
}
|
||||
|
||||
@@ -258,9 +258,11 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx)
|
||||
if (avctx->bits_per_raw_sample == 10 || avctx->bits_per_raw_sample == 9) {
|
||||
/* 10-bit MPEG-4 Simple Studio Profile requires a higher precision IDCT
|
||||
However, it only uses idct_put */
|
||||
if (avctx->codec_id == AV_CODEC_ID_MPEG4 && avctx->profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO)
|
||||
if (c->mpeg4_studio_profile) {
|
||||
c->idct_put = ff_simple_idct_put_int32_10bit;
|
||||
else {
|
||||
c->idct_add = NULL;
|
||||
c->idct = NULL;
|
||||
} else {
|
||||
c->idct_put = ff_simple_idct_put_int16_10bit;
|
||||
c->idct_add = ff_simple_idct_add_int16_10bit;
|
||||
c->idct = ff_simple_idct_int16_10bit;
|
||||
|
||||
@@ -95,6 +95,8 @@ typedef struct IDCTDSPContext {
|
||||
*/
|
||||
uint8_t idct_permutation[64];
|
||||
enum idct_permutation_type perm_type;
|
||||
|
||||
int mpeg4_studio_profile;
|
||||
} IDCTDSPContext;
|
||||
|
||||
void ff_put_pixels_clamped_c(const int16_t *block, uint8_t *av_restrict pixels,
|
||||
|
||||
+13
-3
@@ -260,12 +260,14 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx)
|
||||
* @param[in] avctx pointer to the AVCodecContext
|
||||
* @return result code: 0 = OK, negative number = error
|
||||
*/
|
||||
static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *band,
|
||||
static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *arg_band,
|
||||
AVCodecContext *avctx)
|
||||
{
|
||||
int plane, band_num, indx, transform_id, scan_indx;
|
||||
int i;
|
||||
int quant_mat;
|
||||
IVIBandDesc temp_band, *band = &temp_band;
|
||||
memcpy(&temp_band, arg_band, sizeof(temp_band));
|
||||
|
||||
plane = get_bits(&ctx->gb, 2);
|
||||
band_num = get_bits(&ctx->gb, 4);
|
||||
@@ -395,10 +397,10 @@ static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *band,
|
||||
|
||||
/* decode block huffman codebook */
|
||||
if (!get_bits1(&ctx->gb))
|
||||
band->blk_vlc.tab = ctx->blk_vlc.tab;
|
||||
arg_band->blk_vlc.tab = ctx->blk_vlc.tab;
|
||||
else
|
||||
if (ff_ivi_dec_huff_desc(&ctx->gb, 1, IVI_BLK_HUFF,
|
||||
&band->blk_vlc, avctx))
|
||||
&arg_band->blk_vlc, avctx))
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
/* select appropriate rvmap table for this band */
|
||||
@@ -439,6 +441,9 @@ static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *band,
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
band->blk_vlc = arg_band->blk_vlc;
|
||||
memcpy(arg_band, band, sizeof(*arg_band));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -487,6 +492,11 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band,
|
||||
mb->b_mv_x =
|
||||
mb->b_mv_y = 0;
|
||||
|
||||
if (get_bits_left(&ctx->gb) < 1) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Insufficient input for mb info\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (get_bits1(&ctx->gb)) {
|
||||
if (ctx->frame_type == IVI4_FRAMETYPE_INTRA) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Empty macroblock in an INTRA picture!\n");
|
||||
|
||||
@@ -343,7 +343,10 @@ static int get_siz(Jpeg2000DecoderContext *s)
|
||||
s->numXtiles = ff_jpeg2000_ceildiv(s->width - s->tile_offset_x, s->tile_width);
|
||||
s->numYtiles = ff_jpeg2000_ceildiv(s->height - s->tile_offset_y, s->tile_height);
|
||||
|
||||
if (s->numXtiles * (uint64_t)s->numYtiles > INT_MAX/sizeof(*s->tile)) {
|
||||
// There must be at least a SOT and SOD per tile, their minimum size is 14
|
||||
if (s->numXtiles * (uint64_t)s->numYtiles > INT_MAX/sizeof(*s->tile) ||
|
||||
s->numXtiles * s->numYtiles * 14LL > bytestream2_size(&s->g)
|
||||
) {
|
||||
s->numXtiles = s->numYtiles = 0;
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
@@ -1156,6 +1159,9 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
|
||||
step_x = 32;
|
||||
step_y = 32;
|
||||
|
||||
if (RSpoc > FFMIN(codsty->nreslevels, REpoc))
|
||||
continue;
|
||||
|
||||
for (reslevelno = RSpoc; reslevelno < FFMIN(codsty->nreslevels, REpoc); reslevelno++) {
|
||||
uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r
|
||||
Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
|
||||
@@ -1175,10 +1181,10 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
|
||||
int xc = x / s->cdx[compno];
|
||||
int yc = y / s->cdy[compno];
|
||||
|
||||
if (yc % (1 << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check
|
||||
if (yc % (1LL << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check
|
||||
continue;
|
||||
|
||||
if (xc % (1 << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check
|
||||
if (xc % (1LL << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check
|
||||
continue;
|
||||
|
||||
// check if a precinct exists
|
||||
@@ -1245,10 +1251,10 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
|
||||
if (reslevelno >= codsty->nreslevels)
|
||||
continue;
|
||||
|
||||
if (yc % (1 << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check
|
||||
if (yc % (1LL << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check
|
||||
continue;
|
||||
|
||||
if (xc % (1 << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check
|
||||
if (xc % (1LL << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check
|
||||
continue;
|
||||
|
||||
// check if a precinct exists
|
||||
@@ -1316,10 +1322,10 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
|
||||
uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r
|
||||
Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
|
||||
|
||||
if (yc % (1 << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check
|
||||
if (yc % (1LL << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check
|
||||
continue;
|
||||
|
||||
if (xc % (1 << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check
|
||||
if (xc % (1LL << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check
|
||||
continue;
|
||||
|
||||
// check if a precinct exists
|
||||
|
||||
@@ -240,6 +240,8 @@ static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
|
||||
|
||||
dst = (uint16_t *)p->data[i] + j * sheight * stride;
|
||||
if (flags & 1) {
|
||||
if (get_bits_left(&gb) < bps * width * height)
|
||||
return AVERROR_INVALIDDATA;
|
||||
for (k = 0; k < height; k++) {
|
||||
for (x = 0; x < width; x++)
|
||||
dst[x] = get_bits(&gb, bps);
|
||||
@@ -368,6 +370,8 @@ static int magy_decode_slice(AVCodecContext *avctx, void *tdata,
|
||||
|
||||
dst = p->data[i] + j * sheight * stride;
|
||||
if (flags & 1) {
|
||||
if (get_bits_left(&gb) < 8* width * height)
|
||||
return AVERROR_INVALIDDATA;
|
||||
for (k = 0; k < height; k++) {
|
||||
for (x = 0; x < width; x++)
|
||||
dst[x] = get_bits(&gb, 8);
|
||||
|
||||
@@ -156,7 +156,7 @@ static const struct FFJniField jni_amediaformat_mapping[] = {
|
||||
static const AVClass amediaformat_class = {
|
||||
.class_name = "amediaformat",
|
||||
.item_name = av_default_item_name,
|
||||
.version = LIBAVCODEC_VERSION_INT,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
struct FFAMediaFormat {
|
||||
@@ -268,7 +268,7 @@ static const struct FFJniField jni_amediacodec_mapping[] = {
|
||||
static const AVClass amediacodec_class = {
|
||||
.class_name = "amediacodec",
|
||||
.item_name = av_default_item_name,
|
||||
.version = LIBAVCODEC_VERSION_INT,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
struct FFAMediaCodec {
|
||||
@@ -1687,3 +1687,18 @@ int ff_AMediaCodec_cleanOutputBuffers(FFAMediaCodec *codec)
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ff_Build_SDK_INT(AVCodecContext *avctx)
|
||||
{
|
||||
int ret = -1;
|
||||
JNIEnv *env = NULL;
|
||||
jclass versionClass;
|
||||
jfieldID sdkIntFieldID;
|
||||
JNI_GET_ENV_OR_RETURN(env, avctx, -1);
|
||||
|
||||
versionClass = (*env)->FindClass(env, "android/os/Build$VERSION");
|
||||
sdkIntFieldID = (*env)->GetStaticFieldID(env, versionClass, "SDK_INT", "I");
|
||||
ret = (*env)->GetStaticIntField(env, versionClass, sdkIntFieldID);
|
||||
(*env)->DeleteLocalRef(env, versionClass);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -124,4 +124,6 @@ int ff_AMediaCodec_getConfigureFlagEncode(FFAMediaCodec *codec);
|
||||
|
||||
int ff_AMediaCodec_cleanOutputBuffers(FFAMediaCodec *codec);
|
||||
|
||||
int ff_Build_SDK_INT(AVCodecContext *avctx);
|
||||
|
||||
#endif /* AVCODEC_MEDIACODEC_WRAPPER_H */
|
||||
|
||||
+62
-60
@@ -48,6 +48,7 @@ typedef struct MediaCodecH264DecContext {
|
||||
AVPacket buffered_pkt;
|
||||
|
||||
int delay_flush;
|
||||
int amlogic_mpeg2_api23_workaround;
|
||||
|
||||
} MediaCodecH264DecContext;
|
||||
|
||||
@@ -287,6 +288,7 @@ static int common_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format)
|
||||
static av_cold int mediacodec_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
int ret;
|
||||
int sdk_int;
|
||||
|
||||
const char *codec_mime = NULL;
|
||||
|
||||
@@ -377,7 +379,17 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx)
|
||||
goto done;
|
||||
}
|
||||
|
||||
av_log(avctx, AV_LOG_INFO, "MediaCodec started successfully, ret = %d\n", ret);
|
||||
av_log(avctx, AV_LOG_INFO,
|
||||
"MediaCodec started successfully: codec = %s, ret = %d\n",
|
||||
s->ctx->codec_name, ret);
|
||||
|
||||
sdk_int = ff_Build_SDK_INT(avctx);
|
||||
if (sdk_int <= 23 &&
|
||||
strcmp(s->ctx->codec_name, "OMX.amlogic.mpeg2.decoder.awesome") == 0) {
|
||||
av_log(avctx, AV_LOG_INFO, "Enabling workaround for %s on API=%d\n",
|
||||
s->ctx->codec_name, sdk_int);
|
||||
s->amlogic_mpeg2_api23_workaround = 1;
|
||||
}
|
||||
|
||||
done:
|
||||
if (format) {
|
||||
@@ -391,82 +403,72 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mediacodec_send_receive(AVCodecContext *avctx,
|
||||
MediaCodecH264DecContext *s,
|
||||
AVFrame *frame, bool wait)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* send any pending data from buffered packet */
|
||||
while (s->buffered_pkt.size) {
|
||||
ret = ff_mediacodec_dec_send(avctx, s->ctx, &s->buffered_pkt);
|
||||
if (ret == AVERROR(EAGAIN))
|
||||
break;
|
||||
else if (ret < 0)
|
||||
return ret;
|
||||
s->buffered_pkt.size -= ret;
|
||||
s->buffered_pkt.data += ret;
|
||||
if (s->buffered_pkt.size <= 0)
|
||||
av_packet_unref(&s->buffered_pkt);
|
||||
}
|
||||
|
||||
/* check for new frame */
|
||||
return ff_mediacodec_dec_receive(avctx, s->ctx, frame, wait);
|
||||
}
|
||||
|
||||
static int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
|
||||
{
|
||||
MediaCodecH264DecContext *s = avctx->priv_data;
|
||||
int ret;
|
||||
ssize_t index;
|
||||
|
||||
/*
|
||||
* MediaCodec.flush() discards both input and output buffers, thus we
|
||||
* need to delay the call to this function until the user has released or
|
||||
* renderered the frames he retains.
|
||||
*
|
||||
* After we have buffered an input packet, check if the codec is in the
|
||||
* flushing state. If it is, we need to call ff_mediacodec_dec_flush.
|
||||
*
|
||||
* ff_mediacodec_dec_flush returns 0 if the flush cannot be performed on
|
||||
* the codec (because the user retains frames). The codec stays in the
|
||||
* flushing state.
|
||||
*
|
||||
* ff_mediacodec_dec_flush returns 1 if the flush can actually be
|
||||
* performed on the codec. The codec leaves the flushing state and can
|
||||
* process again packets.
|
||||
*
|
||||
* ff_mediacodec_dec_flush returns a negative value if an error has
|
||||
* occurred.
|
||||
*
|
||||
*/
|
||||
if (ff_mediacodec_dec_is_flushing(avctx, s->ctx)) {
|
||||
/* In delay_flush mode, wait until the user has released or rendered
|
||||
all retained frames. */
|
||||
if (s->delay_flush && ff_mediacodec_dec_is_flushing(avctx, s->ctx)) {
|
||||
if (!ff_mediacodec_dec_flush(avctx, s->ctx)) {
|
||||
return AVERROR(EAGAIN);
|
||||
}
|
||||
}
|
||||
|
||||
/* flush buffered packet and check for new frame */
|
||||
ret = mediacodec_send_receive(avctx, s, frame, false);
|
||||
/* poll for new frame */
|
||||
ret = ff_mediacodec_dec_receive(avctx, s->ctx, frame, false);
|
||||
if (ret != AVERROR(EAGAIN))
|
||||
return ret;
|
||||
|
||||
/* skip fetching new packet if we still have one buffered */
|
||||
if (s->buffered_pkt.size > 0)
|
||||
return mediacodec_send_receive(avctx, s, frame, true);
|
||||
/* feed decoder */
|
||||
while (1) {
|
||||
if (s->ctx->current_input_buffer < 0) {
|
||||
/* poll for input space */
|
||||
index = ff_AMediaCodec_dequeueInputBuffer(s->ctx->codec, 0);
|
||||
if (index < 0) {
|
||||
/* no space, block for an output frame to appear */
|
||||
return ff_mediacodec_dec_receive(avctx, s->ctx, frame, true);
|
||||
}
|
||||
s->ctx->current_input_buffer = index;
|
||||
}
|
||||
|
||||
/* fetch new packet or eof */
|
||||
ret = ff_decode_get_packet(avctx, &s->buffered_pkt);
|
||||
if (ret == AVERROR_EOF) {
|
||||
AVPacket null_pkt = { 0 };
|
||||
ret = ff_mediacodec_dec_send(avctx, s->ctx, &null_pkt);
|
||||
if (ret < 0)
|
||||
/* try to flush any buffered packet data */
|
||||
if (s->buffered_pkt.size > 0) {
|
||||
ret = ff_mediacodec_dec_send(avctx, s->ctx, &s->buffered_pkt, false);
|
||||
if (ret >= 0) {
|
||||
s->buffered_pkt.size -= ret;
|
||||
s->buffered_pkt.data += ret;
|
||||
if (s->buffered_pkt.size <= 0)
|
||||
av_packet_unref(&s->buffered_pkt);
|
||||
} else if (ret < 0 && ret != AVERROR(EAGAIN)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (s->amlogic_mpeg2_api23_workaround && s->buffered_pkt.size <= 0) {
|
||||
/* fallthrough to fetch next packet regardless of input buffer space */
|
||||
} else {
|
||||
/* poll for space again */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* fetch new packet or eof */
|
||||
ret = ff_decode_get_packet(avctx, &s->buffered_pkt);
|
||||
if (ret == AVERROR_EOF) {
|
||||
AVPacket null_pkt = { 0 };
|
||||
ret = ff_mediacodec_dec_send(avctx, s->ctx, &null_pkt, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (ret == AVERROR(EAGAIN) && s->ctx->current_input_buffer < 0) {
|
||||
return ff_mediacodec_dec_receive(avctx, s->ctx, frame, true);
|
||||
} else if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* crank decoder with new packet */
|
||||
return mediacodec_send_receive(avctx, s, frame, true);
|
||||
return AVERROR(EAGAIN);
|
||||
}
|
||||
|
||||
static void mediacodec_decode_flush(AVCodecContext *avctx)
|
||||
|
||||
@@ -209,7 +209,7 @@ static int mediacodec_wrap_hw_buffer(AVCodecContext *avctx,
|
||||
|
||||
if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) {
|
||||
frame->pts = av_rescale_q(info->presentationTimeUs,
|
||||
av_make_q(1, 1000000),
|
||||
AV_TIME_BASE_Q,
|
||||
avctx->pkt_timebase);
|
||||
} else {
|
||||
frame->pts = info->presentationTimeUs;
|
||||
@@ -298,7 +298,7 @@ static int mediacodec_wrap_sw_buffer(AVCodecContext *avctx,
|
||||
* * 0-sized avpackets are pushed to flush remaining frames at EOS */
|
||||
if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) {
|
||||
frame->pts = av_rescale_q(info->presentationTimeUs,
|
||||
av_make_q(1, 1000000),
|
||||
AV_TIME_BASE_Q,
|
||||
avctx->pkt_timebase);
|
||||
} else {
|
||||
frame->pts = info->presentationTimeUs;
|
||||
@@ -385,10 +385,10 @@ static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecConte
|
||||
AMEDIAFORMAT_GET_INT32(s->width, "width", 1);
|
||||
AMEDIAFORMAT_GET_INT32(s->height, "height", 1);
|
||||
|
||||
AMEDIAFORMAT_GET_INT32(s->stride, "stride", 1);
|
||||
AMEDIAFORMAT_GET_INT32(s->stride, "stride", 0);
|
||||
s->stride = s->stride > 0 ? s->stride : s->width;
|
||||
|
||||
AMEDIAFORMAT_GET_INT32(s->slice_height, "slice-height", 1);
|
||||
AMEDIAFORMAT_GET_INT32(s->slice_height, "slice-height", 0);
|
||||
s->slice_height = s->slice_height > 0 ? s->slice_height : s->height;
|
||||
|
||||
if (strstr(s->codec_name, "OMX.Nvidia.")) {
|
||||
@@ -450,6 +450,7 @@ static int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecDecContex
|
||||
s->eos = 0;
|
||||
atomic_fetch_add(&s->serial, 1);
|
||||
atomic_init(&s->hw_buffer_count, 0);
|
||||
s->current_input_buffer = -1;
|
||||
|
||||
status = ff_AMediaCodec_flush(codec);
|
||||
if (status < 0) {
|
||||
@@ -477,6 +478,7 @@ int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s,
|
||||
atomic_init(&s->refcount, 1);
|
||||
atomic_init(&s->hw_buffer_count, 0);
|
||||
atomic_init(&s->serial, 1);
|
||||
s->current_input_buffer = -1;
|
||||
|
||||
pix_fmt = ff_get_format(avctx, pix_fmts);
|
||||
if (pix_fmt == AV_PIX_FMT_MEDIACODEC) {
|
||||
@@ -561,16 +563,17 @@ fail:
|
||||
}
|
||||
|
||||
int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s,
|
||||
AVPacket *pkt)
|
||||
AVPacket *pkt, bool wait)
|
||||
{
|
||||
int offset = 0;
|
||||
int need_draining = 0;
|
||||
uint8_t *data;
|
||||
ssize_t index;
|
||||
ssize_t index = s->current_input_buffer;
|
||||
size_t size;
|
||||
FFAMediaCodec *codec = s->codec;
|
||||
int status;
|
||||
int64_t input_dequeue_timeout_us = INPUT_DEQUEUE_TIMEOUT_US;
|
||||
int64_t input_dequeue_timeout_us = wait ? INPUT_DEQUEUE_TIMEOUT_US : 0;
|
||||
int64_t pts;
|
||||
|
||||
if (s->flushing) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Decoder is flushing and cannot accept new buffer "
|
||||
@@ -587,17 +590,19 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s,
|
||||
}
|
||||
|
||||
while (offset < pkt->size || (need_draining && !s->draining)) {
|
||||
|
||||
index = ff_AMediaCodec_dequeueInputBuffer(codec, input_dequeue_timeout_us);
|
||||
if (ff_AMediaCodec_infoTryAgainLater(codec, index)) {
|
||||
av_log(avctx, AV_LOG_TRACE, "No input buffer available, try again later\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (index < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Failed to dequeue input buffer (status=%zd)\n", index);
|
||||
return AVERROR_EXTERNAL;
|
||||
index = ff_AMediaCodec_dequeueInputBuffer(codec, input_dequeue_timeout_us);
|
||||
if (ff_AMediaCodec_infoTryAgainLater(codec, index)) {
|
||||
av_log(avctx, AV_LOG_TRACE, "No input buffer available, try again later\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (index < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Failed to dequeue input buffer (status=%zd)\n", index);
|
||||
return AVERROR_EXTERNAL;
|
||||
}
|
||||
}
|
||||
s->current_input_buffer = -1;
|
||||
|
||||
data = ff_AMediaCodec_getInputBuffer(codec, index, &size);
|
||||
if (!data) {
|
||||
@@ -605,13 +610,13 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s,
|
||||
return AVERROR_EXTERNAL;
|
||||
}
|
||||
|
||||
if (need_draining) {
|
||||
int64_t pts = pkt->pts;
|
||||
uint32_t flags = ff_AMediaCodec_getBufferFlagEndOfStream(codec);
|
||||
pts = pkt->pts;
|
||||
if (pts != AV_NOPTS_VALUE && avctx->pkt_timebase.num && avctx->pkt_timebase.den) {
|
||||
pts = av_rescale_q(pts, avctx->pkt_timebase, AV_TIME_BASE_Q);
|
||||
}
|
||||
|
||||
if (s->surface) {
|
||||
pts = av_rescale_q(pts, avctx->pkt_timebase, av_make_q(1, 1000000));
|
||||
}
|
||||
if (need_draining) {
|
||||
uint32_t flags = ff_AMediaCodec_getBufferFlagEndOfStream(codec);
|
||||
|
||||
av_log(avctx, AV_LOG_DEBUG, "Sending End Of Stream signal\n");
|
||||
|
||||
@@ -627,16 +632,10 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s,
|
||||
s->draining = 1;
|
||||
break;
|
||||
} else {
|
||||
int64_t pts = pkt->pts;
|
||||
|
||||
size = FFMIN(pkt->size - offset, size);
|
||||
memcpy(data, pkt->data + offset, size);
|
||||
offset += size;
|
||||
|
||||
if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) {
|
||||
pts = av_rescale_q(pts, avctx->pkt_timebase, av_make_q(1, 1000000));
|
||||
}
|
||||
|
||||
status = ff_AMediaCodec_queueInputBuffer(codec, index, 0, size, pts, 0);
|
||||
if (status < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Failed to queue input buffer (status = %d)\n", status);
|
||||
@@ -764,6 +763,18 @@ int ff_mediacodec_dec_receive(AVCodecContext *avctx, MediaCodecDecContext *s,
|
||||
return AVERROR(EAGAIN);
|
||||
}
|
||||
|
||||
/*
|
||||
* ff_mediacodec_dec_flush returns 0 if the flush cannot be performed on
|
||||
* the codec (because the user retains frames). The codec stays in the
|
||||
* flushing state.
|
||||
*
|
||||
* ff_mediacodec_dec_flush returns 1 if the flush can actually be
|
||||
* performed on the codec. The codec leaves the flushing state and can
|
||||
* process again packets.
|
||||
*
|
||||
* ff_mediacodec_dec_flush returns a negative value if an error has
|
||||
* occurred.
|
||||
*/
|
||||
int ff_mediacodec_dec_flush(AVCodecContext *avctx, MediaCodecDecContext *s)
|
||||
{
|
||||
if (!s->surface || atomic_load(&s->refcount) == 1) {
|
||||
|
||||
@@ -65,6 +65,7 @@ typedef struct MediaCodecDecContext {
|
||||
int display_height;
|
||||
|
||||
uint64_t output_buffer_count;
|
||||
ssize_t current_input_buffer;
|
||||
|
||||
bool delay_flush;
|
||||
atomic_int serial;
|
||||
@@ -78,7 +79,8 @@ int ff_mediacodec_dec_init(AVCodecContext *avctx,
|
||||
|
||||
int ff_mediacodec_dec_send(AVCodecContext *avctx,
|
||||
MediaCodecDecContext *s,
|
||||
AVPacket *pkt);
|
||||
AVPacket *pkt,
|
||||
bool wait);
|
||||
|
||||
int ff_mediacodec_dec_receive(AVCodecContext *avctx,
|
||||
MediaCodecDecContext *s,
|
||||
|
||||
+10
-1
@@ -626,6 +626,10 @@ unk_pixfmt:
|
||||
avpriv_report_missing_feature(s->avctx, "Lowres for weird subsampling");
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
if ((AV_RB32(s->upscale_h) || AV_RB32(s->upscale_v)) && s->progressive && s->avctx->pix_fmt == AV_PIX_FMT_GBRP) {
|
||||
avpriv_report_missing_feature(s->avctx, "progressive for weird subsampling");
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
if (s->ls) {
|
||||
memset(s->upscale_h, 0, sizeof(s->upscale_h));
|
||||
memset(s->upscale_v, 0, sizeof(s->upscale_v));
|
||||
@@ -1055,6 +1059,11 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p
|
||||
for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
|
||||
int modified_predictor = predictor;
|
||||
|
||||
if (get_bits_left(&s->gb) < 1) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "bitstream end in rgb_scan\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (s->restart_interval && !s->restart_count){
|
||||
s->restart_count = s->restart_interval;
|
||||
resync_mb_x = mb_x;
|
||||
@@ -1078,7 +1087,7 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p
|
||||
return -1;
|
||||
|
||||
left[i] = buffer[mb_x][i] =
|
||||
mask & (pred + (dc * (1 << point_transform)));
|
||||
mask & (pred + (unsigned)(dc * (1 << point_transform)));
|
||||
}
|
||||
|
||||
if (s->restart_interval && !--s->restart_count) {
|
||||
|
||||
+5
-4
@@ -479,7 +479,7 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp,
|
||||
uint8_t checksum;
|
||||
uint8_t lossless_check;
|
||||
int start_count = get_bits_count(gbp);
|
||||
int min_channel, max_channel, max_matrix_channel;
|
||||
int min_channel, max_channel, max_matrix_channel, noise_type;
|
||||
const int std_max_matrix_channel = m->avctx->codec_id == AV_CODEC_ID_MLP
|
||||
? MAX_MATRIX_CHANNEL_MLP
|
||||
: MAX_MATRIX_CHANNEL_TRUEHD;
|
||||
@@ -492,9 +492,9 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp,
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
s->noise_type = get_bits1(gbp);
|
||||
noise_type = get_bits1(gbp);
|
||||
|
||||
if (m->avctx->codec_id == AV_CODEC_ID_MLP && s->noise_type) {
|
||||
if (m->avctx->codec_id == AV_CODEC_ID_MLP && noise_type) {
|
||||
av_log(m->avctx, AV_LOG_ERROR, "MLP must have 0x31ea sync word.\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
@@ -520,7 +520,7 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp,
|
||||
|
||||
/* This should happen for TrueHD streams with >6 channels and MLP's noise
|
||||
* type. It is not yet known if this is allowed. */
|
||||
if (max_channel > MAX_MATRIX_CHANNEL_MLP && !s->noise_type) {
|
||||
if (max_channel > MAX_MATRIX_CHANNEL_MLP && !noise_type) {
|
||||
avpriv_request_sample(m->avctx,
|
||||
"%d channels (more than the "
|
||||
"maximum supported by the decoder)",
|
||||
@@ -537,6 +537,7 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp,
|
||||
s->min_channel = min_channel;
|
||||
s->max_channel = max_channel;
|
||||
s->max_matrix_channel = max_matrix_channel;
|
||||
s->noise_type = noise_type;
|
||||
|
||||
if (mlp_channel_layout_subset(m->avctx->request_channel_layout, s->mask) &&
|
||||
m->max_decoded_substream > substr) {
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#define NBIT_VO_TYPE 5
|
||||
#define ARTS_VO_TYPE 10
|
||||
#define ACE_VO_TYPE 12
|
||||
#define SIMPLE_STUDIO_VO_TYPE 14
|
||||
#define CORE_STUDIO_VO_TYPE 15
|
||||
#define ADV_SIMPLE_VO_TYPE 17
|
||||
|
||||
#define VOT_VIDEO_ID 1
|
||||
|
||||
@@ -46,7 +46,7 @@ int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size)
|
||||
if (!vop_found) {
|
||||
for (i = 0; i < buf_size; i++) {
|
||||
state = (state << 8) | buf[i];
|
||||
if (state == 0x1B6) {
|
||||
if (state == VOP_STARTCODE) {
|
||||
i++;
|
||||
vop_found = 1;
|
||||
break;
|
||||
@@ -61,6 +61,8 @@ int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size)
|
||||
for (; i < buf_size; i++) {
|
||||
state = (state << 8) | buf[i];
|
||||
if ((state & 0xFFFFFF00) == 0x100) {
|
||||
if (state == SLICE_STARTCODE || state == EXT_STARTCODE)
|
||||
continue;
|
||||
pc->frame_start_found = 0;
|
||||
pc->state = -1;
|
||||
return i - 3;
|
||||
|
||||
+80
-36
@@ -46,6 +46,8 @@
|
||||
#define MB_TYPE_B_VLC_BITS 4
|
||||
#define STUDIO_INTRA_BITS 9
|
||||
|
||||
static int decode_studio_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb);
|
||||
|
||||
static VLC dc_lum, dc_chrom;
|
||||
static VLC sprite_trajectory;
|
||||
static VLC mb_type_b_vlc;
|
||||
@@ -1978,15 +1980,15 @@ static int mpeg4_decode_gop_header(MpegEncContext *s, GetBitContext *gb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpeg4_decode_profile_level(MpegEncContext *s, GetBitContext *gb)
|
||||
static int mpeg4_decode_profile_level(MpegEncContext *s, GetBitContext *gb, int *profile, int *level)
|
||||
{
|
||||
|
||||
s->avctx->profile = get_bits(gb, 4);
|
||||
s->avctx->level = get_bits(gb, 4);
|
||||
*profile = get_bits(gb, 4);
|
||||
*level = get_bits(gb, 4);
|
||||
|
||||
// for Simple profile, level 0
|
||||
if (s->avctx->profile == 0 && s->avctx->level == 8) {
|
||||
s->avctx->level = 0;
|
||||
if (*profile == 0 && *level == 8) {
|
||||
*level = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2049,6 +2051,23 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
|
||||
/* vol header */
|
||||
skip_bits(gb, 1); /* random access */
|
||||
s->vo_type = get_bits(gb, 8);
|
||||
|
||||
/* If we are in studio profile (per vo_type), check if its all consistent
|
||||
* and if so continue pass control to decode_studio_vol_header().
|
||||
* elIf something is inconsistent, error out
|
||||
* else continue with (non studio) vol header decpoding.
|
||||
*/
|
||||
if (s->vo_type == CORE_STUDIO_VO_TYPE ||
|
||||
s->vo_type == SIMPLE_STUDIO_VO_TYPE) {
|
||||
if (s->avctx->profile != FF_PROFILE_UNKNOWN && s->avctx->profile != FF_PROFILE_MPEG4_SIMPLE_STUDIO)
|
||||
return AVERROR_INVALIDDATA;
|
||||
s->studio_profile = 1;
|
||||
s->avctx->profile = FF_PROFILE_MPEG4_SIMPLE_STUDIO;
|
||||
return decode_studio_vol_header(ctx, gb);
|
||||
} else if (s->studio_profile) {
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
if (get_bits1(gb) != 0) { /* is_ol_id */
|
||||
vo_ver_id = get_bits(gb, 4); /* vo_ver_id */
|
||||
skip_bits(gb, 3); /* vo_priority */
|
||||
@@ -2848,11 +2867,13 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void read_quant_matrix_ext(MpegEncContext *s, GetBitContext *gb)
|
||||
static int read_quant_matrix_ext(MpegEncContext *s, GetBitContext *gb)
|
||||
{
|
||||
int i, j, v;
|
||||
|
||||
if (get_bits1(gb)) {
|
||||
if (get_bits_left(gb) < 64*8)
|
||||
return AVERROR_INVALIDDATA;
|
||||
/* intra_quantiser_matrix */
|
||||
for (i = 0; i < 64; i++) {
|
||||
v = get_bits(gb, 8);
|
||||
@@ -2863,6 +2884,8 @@ static void read_quant_matrix_ext(MpegEncContext *s, GetBitContext *gb)
|
||||
}
|
||||
|
||||
if (get_bits1(gb)) {
|
||||
if (get_bits_left(gb) < 64*8)
|
||||
return AVERROR_INVALIDDATA;
|
||||
/* non_intra_quantiser_matrix */
|
||||
for (i = 0; i < 64; i++) {
|
||||
get_bits(gb, 8);
|
||||
@@ -2870,6 +2893,8 @@ static void read_quant_matrix_ext(MpegEncContext *s, GetBitContext *gb)
|
||||
}
|
||||
|
||||
if (get_bits1(gb)) {
|
||||
if (get_bits_left(gb) < 64*8)
|
||||
return AVERROR_INVALIDDATA;
|
||||
/* chroma_intra_quantiser_matrix */
|
||||
for (i = 0; i < 64; i++) {
|
||||
v = get_bits(gb, 8);
|
||||
@@ -2879,6 +2904,8 @@ static void read_quant_matrix_ext(MpegEncContext *s, GetBitContext *gb)
|
||||
}
|
||||
|
||||
if (get_bits1(gb)) {
|
||||
if (get_bits_left(gb) < 64*8)
|
||||
return AVERROR_INVALIDDATA;
|
||||
/* chroma_non_intra_quantiser_matrix */
|
||||
for (i = 0; i < 64; i++) {
|
||||
get_bits(gb, 8);
|
||||
@@ -2886,6 +2913,7 @@ static void read_quant_matrix_ext(MpegEncContext *s, GetBitContext *gb)
|
||||
}
|
||||
|
||||
next_start_code_studio(gb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void extension_and_user_data(MpegEncContext *s, GetBitContext *gb, int id)
|
||||
@@ -2931,9 +2959,6 @@ static int decode_studio_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
|
||||
if (get_bits_left(gb) <= 32)
|
||||
return 0;
|
||||
|
||||
if (get_bits_long(gb, 32) != VOP_STARTCODE)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
s->decode_mb = mpeg4_decode_studio_mb;
|
||||
|
||||
decode_smpte_tc(ctx, gb);
|
||||
@@ -2982,26 +3007,30 @@ static int decode_studio_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
|
||||
|
||||
static int decode_studiovisualobject(Mpeg4DecContext *ctx, GetBitContext *gb)
|
||||
{
|
||||
uint32_t startcode;
|
||||
MpegEncContext *s = &ctx->m;
|
||||
int visual_object_type, width, height;
|
||||
int visual_object_type;
|
||||
|
||||
startcode = get_bits_long(gb, 32);
|
||||
|
||||
/* StudioVisualObject() */
|
||||
if (startcode == VISUAL_OBJ_STARTCODE) {
|
||||
skip_bits(gb, 4); /* visual_object_verid */
|
||||
visual_object_type = get_bits(gb, 4);
|
||||
if (visual_object_type != VOT_VIDEO_ID) {
|
||||
avpriv_request_sample(s->avctx, "VO type %u", visual_object_type);
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
next_start_code_studio(gb);
|
||||
extension_and_user_data(s, gb, 1);
|
||||
|
||||
if (visual_object_type == VOT_VIDEO_ID) {
|
||||
/* StudioVideoObjectLayer */
|
||||
skip_bits_long(gb, 32); /* video_object_start_code */
|
||||
skip_bits_long(gb, 32); /* video_object_layer_start_code */
|
||||
skip_bits1(gb); /* random_accessible_vol */
|
||||
skip_bits(gb, 8); /* video_object_type_indication */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_studio_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
|
||||
{
|
||||
MpegEncContext *s = &ctx->m;
|
||||
int width, height;
|
||||
int bits_per_raw_sample;
|
||||
|
||||
// random_accessible_vol and video_object_type_indication have already
|
||||
// been read by the caller decode_vol_header()
|
||||
skip_bits(gb, 4); /* video_object_layer_verid */
|
||||
ctx->shape = get_bits(gb, 2); /* video_object_layer_shape */
|
||||
skip_bits(gb, 4); /* video_object_layer_shape_extension */
|
||||
@@ -3014,8 +3043,8 @@ static int decode_studiovisualobject(Mpeg4DecContext *ctx, GetBitContext *gb)
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
s->avctx->bits_per_raw_sample = get_bits(gb, 4); /* bit_depth */
|
||||
if (s->avctx->bits_per_raw_sample == 10) {
|
||||
bits_per_raw_sample = get_bits(gb, 4); /* bit_depth */
|
||||
if (bits_per_raw_sample == 10) {
|
||||
if (ctx->rgb) {
|
||||
s->avctx->pix_fmt = AV_PIX_FMT_GBRP10;
|
||||
}
|
||||
@@ -3024,9 +3053,10 @@ static int decode_studiovisualobject(Mpeg4DecContext *ctx, GetBitContext *gb)
|
||||
}
|
||||
}
|
||||
else {
|
||||
avpriv_request_sample(s->avctx, "MPEG-4 Studio profile bit-depth %u", s->avctx->bits_per_raw_sample);
|
||||
avpriv_request_sample(s->avctx, "MPEG-4 Studio profile bit-depth %u", bits_per_raw_sample);
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
s->avctx->bits_per_raw_sample = bits_per_raw_sample;
|
||||
}
|
||||
if (ctx->shape == RECT_SHAPE) {
|
||||
check_marker(s->avctx, gb, "before video_object_layer_width");
|
||||
@@ -3068,8 +3098,6 @@ static int decode_studiovisualobject(Mpeg4DecContext *ctx, GetBitContext *gb)
|
||||
|
||||
next_start_code_studio(gb);
|
||||
extension_and_user_data(s, gb, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3090,6 +3118,12 @@ int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb)
|
||||
/* search next start code */
|
||||
align_get_bits(gb);
|
||||
|
||||
// If we have not switched to studio profile than we also did not switch bps
|
||||
// that means something else (like a previous instance) outside set bps which
|
||||
// would be inconsistant with the currect state, thus reset it
|
||||
if (!s->studio_profile && s->avctx->bits_per_raw_sample != 8)
|
||||
s->avctx->bits_per_raw_sample = 0;
|
||||
|
||||
if (s->codec_tag == AV_RL32("WV1F") && show_bits(gb, 24) == 0x575630) {
|
||||
skip_bits(gb, 24);
|
||||
if (get_bits(gb, 8) == 0xF0)
|
||||
@@ -3186,19 +3220,25 @@ int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb)
|
||||
} else if (startcode == GOP_STARTCODE) {
|
||||
mpeg4_decode_gop_header(s, gb);
|
||||
} else if (startcode == VOS_STARTCODE) {
|
||||
mpeg4_decode_profile_level(s, gb);
|
||||
if (s->avctx->profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO &&
|
||||
(s->avctx->level > 0 && s->avctx->level < 9)) {
|
||||
int profile, level;
|
||||
mpeg4_decode_profile_level(s, gb, &profile, &level);
|
||||
if (profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO &&
|
||||
(level > 0 && level < 9)) {
|
||||
s->studio_profile = 1;
|
||||
next_start_code_studio(gb);
|
||||
extension_and_user_data(s, gb, 0);
|
||||
|
||||
} else if (s->studio_profile) {
|
||||
avpriv_request_sample(s->avctx, "Mixes studio and non studio profile\n");
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
s->avctx->profile = profile;
|
||||
s->avctx->level = level;
|
||||
} else if (startcode == VISUAL_OBJ_STARTCODE) {
|
||||
if (s->studio_profile) {
|
||||
if ((ret = decode_studiovisualobject(ctx, gb)) < 0)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
} else if (startcode == VISUAL_OBJ_STARTCODE) {
|
||||
mpeg4_decode_visual_object(s, gb);
|
||||
} else
|
||||
mpeg4_decode_visual_object(s, gb);
|
||||
} else if (startcode == VOP_STARTCODE) {
|
||||
break;
|
||||
}
|
||||
@@ -3212,9 +3252,13 @@ end:
|
||||
s->low_delay = 1;
|
||||
s->avctx->has_b_frames = !s->low_delay;
|
||||
|
||||
if (s->studio_profile)
|
||||
if (s->studio_profile) {
|
||||
if (!s->avctx->bits_per_raw_sample) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Missing VOL header\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
return decode_studio_vop_header(ctx, gb);
|
||||
else
|
||||
} else
|
||||
return decode_vop_header(ctx, gb);
|
||||
}
|
||||
|
||||
|
||||
@@ -882,7 +882,7 @@ void ff_set_mpeg4_time(MpegEncContext *s)
|
||||
|
||||
static void mpeg4_encode_gop_header(MpegEncContext *s)
|
||||
{
|
||||
int hours, minutes, seconds;
|
||||
int64_t hours, minutes, seconds;
|
||||
int64_t time;
|
||||
|
||||
put_bits(&s->pb, 16, 0);
|
||||
|
||||
@@ -329,6 +329,8 @@ static av_cold int dct_init(MpegEncContext *s)
|
||||
|
||||
av_cold void ff_mpv_idct_init(MpegEncContext *s)
|
||||
{
|
||||
if (s->codec_id == AV_CODEC_ID_MPEG4)
|
||||
s->idsp.mpeg4_studio_profile = s->studio_profile;
|
||||
ff_idctdsp_init(&s->idsp, s->avctx);
|
||||
|
||||
/* load & permutate scantables
|
||||
|
||||
@@ -58,12 +58,13 @@ static void fill_scaling_lists(CUVIDHEVCPICPARAMS *ppc, const HEVCContext *s)
|
||||
ppc->ScalingList16x16[i][j] = sl->sl[2][i][pos];
|
||||
|
||||
if (i < 2)
|
||||
ppc->ScalingList32x32[i][j] = sl->sl[3][i][pos];
|
||||
ppc->ScalingList32x32[i][j] = sl->sl[3][i * 3][pos];
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(ppc->ScalingListDCCoeff16x16, sl->sl_dc[0], sizeof(ppc->ScalingListDCCoeff16x16));
|
||||
memcpy(ppc->ScalingListDCCoeff32x32, sl->sl_dc[1], sizeof(ppc->ScalingListDCCoeff32x32));
|
||||
ppc->ScalingListDCCoeff16x16[i] = sl->sl_dc[0][i];
|
||||
if (i < 2)
|
||||
ppc->ScalingListDCCoeff32x32[i] = sl->sl_dc[1][i * 3];
|
||||
}
|
||||
}
|
||||
|
||||
static int nvdec_hevc_start_frame(AVCodecContext *avctx,
|
||||
@@ -166,8 +167,7 @@ static int nvdec_hevc_start_frame(AVCodecContext *avctx,
|
||||
|
||||
.NumBitsForShortTermRPSInSlice = s->sh.short_term_rps ? s->sh.short_term_ref_pic_set_size : 0,
|
||||
.NumDeltaPocsOfRefRpsIdx = s->sh.short_term_rps ? s->sh.short_term_rps->rps_idx_num_delta_pocs : 0,
|
||||
.NumPocTotalCurr = s->rps[ST_CURR_BEF].nb_refs + s->rps[ST_CURR_AFT].nb_refs +
|
||||
s->rps[LT_CURR].nb_refs,
|
||||
.NumPocTotalCurr = ff_hevc_frame_nb_refs(s),
|
||||
.NumPocStCurrBefore = s->rps[ST_CURR_BEF].nb_refs,
|
||||
.NumPocStCurrAfter = s->rps[ST_CURR_AFT].nb_refs,
|
||||
.NumPocLtCurr = s->rps[LT_CURR].nb_refs,
|
||||
|
||||
@@ -239,8 +239,10 @@ static void silk_lsf2lpc(const int16_t nlsf[16], float lpcf[16], int order)
|
||||
|
||||
/* reconstruct A(z) */
|
||||
for (k = 0; k < order>>1; k++) {
|
||||
lpc32[k] = -p[k + 1] - p[k] - q[k + 1] + q[k];
|
||||
lpc32[order-k-1] = -p[k + 1] - p[k] + q[k + 1] - q[k];
|
||||
int32_t p_tmp = p[k + 1] + p[k];
|
||||
int32_t q_tmp = q[k + 1] - q[k];
|
||||
lpc32[k] = -q_tmp - p_tmp;
|
||||
lpc32[order-k-1] = q_tmp - p_tmp;
|
||||
}
|
||||
|
||||
/* limit the range of the LPC coefficients to each fit within an int16_t */
|
||||
|
||||
@@ -399,13 +399,12 @@ static void celt_search_for_intensity(OpusPsyContext *s, CeltFrame *f)
|
||||
{
|
||||
int i, best_band = CELT_MAX_BANDS - 1;
|
||||
float dist, best_dist = FLT_MAX;
|
||||
/* TODO: fix, make some heuristic up here using the lambda value */
|
||||
float end_band = 0;
|
||||
|
||||
if (s->avctx->channels < 2)
|
||||
return;
|
||||
|
||||
/* TODO: fix, make some heuristic up here using the lambda value */
|
||||
float end_band = 0;
|
||||
|
||||
for (i = f->end_band; i >= end_band; i--) {
|
||||
f->intensity_stereo = i;
|
||||
bands_dist(s, f, &dist);
|
||||
|
||||
+2
-2
@@ -1569,11 +1569,11 @@ int ff_eval_refl(int *refl, const int16_t *coefs, AVCodecContext *avctx)
|
||||
b = 0x1000000 / b;
|
||||
for (j=0; j <= i; j++) {
|
||||
#if CONFIG_FTRAPV
|
||||
int a = bp2[j] - ((refl[i+1] * bp2[i-j]) >> 12);
|
||||
int a = bp2[j] - ((int)(refl[i+1] * (unsigned)bp2[i-j]) >> 12);
|
||||
if((int)(a*(unsigned)b) != a*(int64_t)b)
|
||||
return 1;
|
||||
#endif
|
||||
bp1[j] = (int)((bp2[j] - ((refl[i+1] * bp2[i-j]) >> 12)) * (unsigned)b) >> 12;
|
||||
bp1[j] = (int)((bp2[j] - ((int)(refl[i+1] * (unsigned)bp2[i-j]) >> 12)) * (unsigned)b) >> 12;
|
||||
}
|
||||
|
||||
if ((unsigned) bp1[i] + 0x1000 > 0x1fff)
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ static const int sbc_offset8[4][8] = {
|
||||
/*
|
||||
* Calculates the CRC-8 of the first len bits in data
|
||||
*/
|
||||
uint8_t sbc_crc8(const AVCRC *ctx, const uint8_t *data, size_t len)
|
||||
uint8_t ff_sbc_crc8(const AVCRC *ctx, const uint8_t *data, size_t len)
|
||||
{
|
||||
size_t byte_length = len >> 3;
|
||||
int bit_length = len & 7;
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ struct sbc_frame {
|
||||
const AVCRC *crc_ctx;
|
||||
};
|
||||
|
||||
uint8_t sbc_crc8(const AVCRC *crc_ctx, const uint8_t *data, size_t len);
|
||||
uint8_t ff_sbc_crc8(const AVCRC *crc_ctx, const uint8_t *data, size_t len);
|
||||
void ff_sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8]);
|
||||
|
||||
#endif /* AVCODEC_SBC_H */
|
||||
|
||||
+1
-1
@@ -147,7 +147,7 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame,
|
||||
}
|
||||
}
|
||||
|
||||
if (data[3] != sbc_crc8(frame->crc_ctx, crc_header, crc_pos))
|
||||
if (data[3] != ff_sbc_crc8(frame->crc_ctx, crc_header, crc_pos))
|
||||
return -3;
|
||||
|
||||
ff_sbc_calculate_bits(frame, bits);
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ static size_t sbc_pack_frame(AVPacket *avpkt, struct sbc_frame *frame,
|
||||
if (crc_pos % 8)
|
||||
crc_header[crc_pos >> 3] <<= 8 - (crc_pos % 8);
|
||||
|
||||
avpkt->data[3] = sbc_crc8(frame->crc_ctx, crc_header, crc_pos);
|
||||
avpkt->data[3] = ff_sbc_crc8(frame->crc_ctx, crc_header, crc_pos);
|
||||
|
||||
ff_sbc_calculate_bits(frame, bits);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#ifndef AVCODEC_SHEERVIDEODATA_H
|
||||
#define AVCODEC_SHEERVIDEODATA_H
|
||||
|
||||
#include <libavutil/common.h>
|
||||
#include "libavutil/common.h"
|
||||
|
||||
static const uint8_t l_r_rgb[256] = {
|
||||
3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8,
|
||||
|
||||
+11
-7
@@ -177,7 +177,7 @@ static void fix_bitshift(ShortenContext *s, int32_t *buffer)
|
||||
buffer[i] = 0;
|
||||
} else if (s->bitshift != 0) {
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
buffer[i] <<= s->bitshift;
|
||||
buffer[i] *= 1U << s->bitshift;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,11 +234,11 @@ static int decode_aiff_header(AVCodecContext *avctx, const uint8_t *header,
|
||||
|
||||
while (bytestream2_get_le32(&gb) != MKTAG('C', 'O', 'M', 'M')) {
|
||||
len = bytestream2_get_be32(&gb);
|
||||
bytestream2_skip(&gb, len + (len & 1));
|
||||
if (len < 0 || bytestream2_get_bytes_left(&gb) < 18) {
|
||||
if (len < 0 || bytestream2_get_bytes_left(&gb) < 18LL + len + (len&1)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "no COMM chunk found\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
bytestream2_skip(&gb, len + (len & 1));
|
||||
}
|
||||
len = bytestream2_get_be32(&gb);
|
||||
|
||||
@@ -389,7 +389,7 @@ static int decode_subframe_lpc(ShortenContext *s, int command, int channel,
|
||||
for (i = 0; i < s->blocksize; i++) {
|
||||
sum = init_sum;
|
||||
for (j = 0; j < pred_order; j++)
|
||||
sum += coeffs[j] * s->decoded[channel][i - j - 1];
|
||||
sum += coeffs[j] * (unsigned)s->decoded[channel][i - j - 1];
|
||||
s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) +
|
||||
(sum >> qshift);
|
||||
}
|
||||
@@ -450,6 +450,10 @@ static int read_header(ShortenContext *s)
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
s->nmean = get_uint(s, 0);
|
||||
if (s->nmean > 32768U) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "nmean is: %d\n", s->nmean);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
skip_bytes = get_uint(s, NSKIPSIZE);
|
||||
if ((unsigned)skip_bytes > get_bits_left(&s->gb)/8) {
|
||||
@@ -678,7 +682,7 @@ static int shorten_decode_frame(AVCodecContext *avctx, void *data,
|
||||
else {
|
||||
int32_t sum = (s->version < 2) ? 0 : s->nmean / 2;
|
||||
for (i = 0; i < s->nmean; i++)
|
||||
sum += s->offset[channel][i];
|
||||
sum += (unsigned)s->offset[channel][i];
|
||||
coffset = sum / s->nmean;
|
||||
if (s->version >= 2)
|
||||
coffset = s->bitshift == 0 ? coffset : coffset >> s->bitshift - 1 >> 1;
|
||||
@@ -696,7 +700,7 @@ static int shorten_decode_frame(AVCodecContext *avctx, void *data,
|
||||
|
||||
/* update means with info from the current block */
|
||||
if (s->nmean > 0) {
|
||||
int32_t sum = (s->version < 2) ? 0 : s->blocksize / 2;
|
||||
int64_t sum = (s->version < 2) ? 0 : s->blocksize / 2;
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
sum += s->decoded[channel][i];
|
||||
|
||||
@@ -706,7 +710,7 @@ static int shorten_decode_frame(AVCodecContext *avctx, void *data,
|
||||
if (s->version < 2)
|
||||
s->offset[channel][s->nmean - 1] = sum / s->blocksize;
|
||||
else
|
||||
s->offset[channel][s->nmean - 1] = s->bitshift == 32 ? 0 : (sum / s->blocksize) << s->bitshift;
|
||||
s->offset[channel][s->nmean - 1] = s->bitshift == 32 ? 0 : (sum / s->blocksize) * (1 << s->bitshift);
|
||||
}
|
||||
|
||||
/* copy wrap samples for use with next block */
|
||||
|
||||
@@ -451,7 +451,7 @@ static inline int GET_TOK(TM2Context *ctx,int type)
|
||||
/* common operations - add deltas to 4x4 block of luma or 2x2 blocks of chroma */
|
||||
static inline void tm2_apply_deltas(TM2Context *ctx, int* Y, int stride, int *deltas, int *last)
|
||||
{
|
||||
int ct, d;
|
||||
unsigned ct, d;
|
||||
int i, j;
|
||||
|
||||
for (j = 0; j < 4; j++){
|
||||
|
||||
@@ -594,7 +594,7 @@ static int vc1_decode_i_block(VC1Context *v, int16_t block[64], int n,
|
||||
scale = s->c_dc_scale;
|
||||
block[0] = dcdiff * scale;
|
||||
|
||||
ac_val = s->ac_val[0][0] + s->block_index[n] * 16;
|
||||
ac_val = s->ac_val[0][s->block_index[n]];
|
||||
ac_val2 = ac_val;
|
||||
if (dc_pred_dir) // left
|
||||
ac_val -= 16;
|
||||
@@ -745,7 +745,7 @@ static int vc1_decode_i_block_adv(VC1Context *v, int16_t block[64], int n,
|
||||
|
||||
scale = mquant * 2 + ((mquant == v->pq) ? v->halfpq : 0);
|
||||
|
||||
ac_val = s->ac_val[0][0] + s->block_index[n] * 16;
|
||||
ac_val = s->ac_val[0][s->block_index[n]];
|
||||
ac_val2 = ac_val;
|
||||
if (dc_pred_dir) // left
|
||||
ac_val -= 16;
|
||||
@@ -946,7 +946,7 @@ static int vc1_decode_intra_block(VC1Context *v, int16_t block[64], int n,
|
||||
if (!a_avail) dc_pred_dir = 1;
|
||||
if (!c_avail) dc_pred_dir = 0;
|
||||
if (!a_avail && !c_avail) use_pred = 0;
|
||||
ac_val = s->ac_val[0][0] + s->block_index[n] * 16;
|
||||
ac_val = s->ac_val[0][s->block_index[n]];
|
||||
ac_val2 = ac_val;
|
||||
|
||||
scale = mquant * 2 + v->halfpq;
|
||||
|
||||
+80
-48
@@ -36,6 +36,9 @@
|
||||
#ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder
|
||||
# define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder CFSTR("RequireHardwareAcceleratedVideoDecoder")
|
||||
#endif
|
||||
#ifndef kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder
|
||||
# define kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder CFSTR("EnableHardwareAcceleratedVideoDecoder")
|
||||
#endif
|
||||
|
||||
#if !HAVE_KCMVIDEOCODECTYPE_HEVC
|
||||
enum { kCMVideoCodecType_HEVC = 'hvc1' };
|
||||
@@ -43,10 +46,16 @@ enum { kCMVideoCodecType_HEVC = 'hvc1' };
|
||||
|
||||
#define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12
|
||||
|
||||
typedef struct VTHWFrame {
|
||||
CVPixelBufferRef pixbuf;
|
||||
AVBufferRef *hw_frames_ctx;
|
||||
} VTHWFrame;
|
||||
|
||||
static void videotoolbox_buffer_release(void *opaque, uint8_t *data)
|
||||
{
|
||||
CVPixelBufferRef cv_buffer = *(CVPixelBufferRef *)data;
|
||||
CVPixelBufferRelease(cv_buffer);
|
||||
VTHWFrame *ref = (VTHWFrame *)data;
|
||||
av_buffer_unref(&ref->hw_frames_ctx);
|
||||
CVPixelBufferRelease(ref->pixbuf);
|
||||
|
||||
av_free(data);
|
||||
}
|
||||
@@ -73,22 +82,29 @@ static int videotoolbox_buffer_copy(VTContext *vtctx,
|
||||
|
||||
static int videotoolbox_postproc_frame(void *avctx, AVFrame *frame)
|
||||
{
|
||||
CVPixelBufferRef ref = *(CVPixelBufferRef *)frame->buf[0]->data;
|
||||
VTHWFrame *ref = (VTHWFrame *)frame->buf[0]->data;
|
||||
|
||||
if (!ref) {
|
||||
if (!ref->pixbuf) {
|
||||
av_log(avctx, AV_LOG_ERROR, "No frame decoded?\n");
|
||||
av_frame_unref(frame);
|
||||
return AVERROR_EXTERNAL;
|
||||
}
|
||||
|
||||
frame->data[3] = (uint8_t*)ref;
|
||||
frame->data[3] = (uint8_t*)ref->pixbuf;
|
||||
|
||||
if (ref->hw_frames_ctx) {
|
||||
av_buffer_unref(&frame->hw_frames_ctx);
|
||||
frame->hw_frames_ctx = av_buffer_ref(ref->hw_frames_ctx);
|
||||
if (!frame->hw_frames_ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame)
|
||||
{
|
||||
size_t size = sizeof(CVPixelBufferRef);
|
||||
size_t size = sizeof(VTHWFrame);
|
||||
uint8_t *data = NULL;
|
||||
AVBufferRef *buf = NULL;
|
||||
int ret = ff_attach_decode_data(frame);
|
||||
@@ -315,32 +331,12 @@ CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx)
|
||||
return data;
|
||||
}
|
||||
|
||||
static int videotoolbox_set_frame(AVCodecContext *avctx, AVFrame *frame)
|
||||
{
|
||||
VTContext *vtctx = avctx->internal->hwaccel_priv_data;
|
||||
if (!frame->buf[0] || frame->data[3]) {
|
||||
av_log(avctx, AV_LOG_ERROR, "videotoolbox: invalid state\n");
|
||||
av_frame_unref(frame);
|
||||
return AVERROR_EXTERNAL;
|
||||
}
|
||||
|
||||
CVPixelBufferRef *ref = (CVPixelBufferRef *)frame->buf[0]->data;
|
||||
|
||||
if (*ref)
|
||||
CVPixelBufferRelease(*ref);
|
||||
|
||||
*ref = vtctx->frame;
|
||||
vtctx->frame = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx,
|
||||
const uint8_t *buffer,
|
||||
uint32_t size)
|
||||
{
|
||||
VTContext *vtctx = avctx->internal->hwaccel_priv_data;
|
||||
H264Context *h = avctx->priv_data;
|
||||
H264Context *h = avctx->priv_data;
|
||||
|
||||
if (h->is_avc == 1) {
|
||||
return videotoolbox_buffer_copy(vtctx, buffer, size);
|
||||
@@ -372,17 +368,13 @@ static int videotoolbox_h264_decode_params(AVCodecContext *avctx,
|
||||
return ff_videotoolbox_h264_decode_slice(avctx, buffer, size);
|
||||
}
|
||||
|
||||
int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx,
|
||||
const uint8_t *buffer,
|
||||
uint32_t size)
|
||||
static int videotoolbox_common_decode_slice(AVCodecContext *avctx,
|
||||
const uint8_t *buffer,
|
||||
uint32_t size)
|
||||
{
|
||||
VTContext *vtctx = avctx->internal->hwaccel_priv_data;
|
||||
H264Context *h = avctx->priv_data;
|
||||
void *tmp;
|
||||
|
||||
if (h->is_avc == 1)
|
||||
return 0;
|
||||
|
||||
tmp = av_fast_realloc(vtctx->bitstream,
|
||||
&vtctx->allocated_size,
|
||||
vtctx->bitstream_size+size+4);
|
||||
@@ -399,6 +391,18 @@ int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx,
|
||||
const uint8_t *buffer,
|
||||
uint32_t size)
|
||||
{
|
||||
H264Context *h = avctx->priv_data;
|
||||
|
||||
if (h->is_avc == 1)
|
||||
return 0;
|
||||
|
||||
return videotoolbox_common_decode_slice(avctx, buffer, size);
|
||||
}
|
||||
|
||||
int ff_videotoolbox_uninit(AVCodecContext *avctx)
|
||||
{
|
||||
VTContext *vtctx = avctx->internal->hwaccel_priv_data;
|
||||
@@ -435,11 +439,21 @@ static int videotoolbox_buffer_create(AVCodecContext *avctx, AVFrame *frame)
|
||||
int width = CVPixelBufferGetWidth(pixbuf);
|
||||
int height = CVPixelBufferGetHeight(pixbuf);
|
||||
AVHWFramesContext *cached_frames;
|
||||
VTHWFrame *ref;
|
||||
int ret;
|
||||
|
||||
ret = videotoolbox_set_frame(avctx, frame);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!frame->buf[0] || frame->data[3]) {
|
||||
av_log(avctx, AV_LOG_ERROR, "videotoolbox: invalid state\n");
|
||||
av_frame_unref(frame);
|
||||
return AVERROR_EXTERNAL;
|
||||
}
|
||||
|
||||
ref = (VTHWFrame *)frame->buf[0]->data;
|
||||
|
||||
if (ref->pixbuf)
|
||||
CVPixelBufferRelease(ref->pixbuf);
|
||||
ref->pixbuf = vtctx->frame;
|
||||
vtctx->frame = NULL;
|
||||
|
||||
// Old API code path.
|
||||
if (!vtctx->cached_hw_frames_ctx)
|
||||
@@ -471,9 +485,9 @@ static int videotoolbox_buffer_create(AVCodecContext *avctx, AVFrame *frame)
|
||||
vtctx->cached_hw_frames_ctx = hw_frames_ctx;
|
||||
}
|
||||
|
||||
av_buffer_unref(&frame->hw_frames_ctx);
|
||||
frame->hw_frames_ctx = av_buffer_ref(vtctx->cached_hw_frames_ctx);
|
||||
if (!frame->hw_frames_ctx)
|
||||
av_buffer_unref(&ref->hw_frames_ctx);
|
||||
ref->hw_frames_ctx = av_buffer_ref(vtctx->cached_hw_frames_ctx);
|
||||
if (!ref->hw_frames_ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
return 0;
|
||||
@@ -709,7 +723,9 @@ static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
CFDictionarySetValue(config_info,
|
||||
kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder,
|
||||
codec_type == kCMVideoCodecType_HEVC ?
|
||||
kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder :
|
||||
kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder,
|
||||
kCFBooleanTrue);
|
||||
|
||||
CFMutableDictionaryRef avc_info;
|
||||
@@ -833,6 +849,9 @@ static int videotoolbox_start(AVCodecContext *avctx)
|
||||
case kVTVideoDecoderUnsupportedDataFormatErr:
|
||||
av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox does not support this format.\n");
|
||||
return AVERROR(ENOSYS);
|
||||
case kVTCouldNotFindVideoDecoderErr:
|
||||
av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox decoder for this format not found.\n");
|
||||
return AVERROR(ENOSYS);
|
||||
case kVTVideoDecoderMalfunctionErr:
|
||||
av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox malfunction.\n");
|
||||
return AVERROR(EINVAL);
|
||||
@@ -842,7 +861,7 @@ static int videotoolbox_start(AVCodecContext *avctx)
|
||||
case 0:
|
||||
return 0;
|
||||
default:
|
||||
av_log(avctx, AV_LOG_VERBOSE, "Unknown VideoToolbox session creation error %u\n", (unsigned)status);
|
||||
av_log(avctx, AV_LOG_VERBOSE, "Unknown VideoToolbox session creation error %d\n", (int)status);
|
||||
return AVERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -922,12 +941,27 @@ static int videotoolbox_h264_end_frame(AVCodecContext *avctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int videotoolbox_hevc_start_frame(AVCodecContext *avctx,
|
||||
const uint8_t *buffer,
|
||||
uint32_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int videotoolbox_hevc_decode_slice(AVCodecContext *avctx,
|
||||
const uint8_t *buffer,
|
||||
uint32_t size)
|
||||
{
|
||||
return videotoolbox_common_decode_slice(avctx, buffer, size);
|
||||
}
|
||||
|
||||
|
||||
static int videotoolbox_hevc_decode_params(AVCodecContext *avctx,
|
||||
int type,
|
||||
const uint8_t *buffer,
|
||||
uint32_t size)
|
||||
{
|
||||
return ff_videotoolbox_h264_decode_slice(avctx, buffer, size);
|
||||
return videotoolbox_common_decode_slice(avctx, buffer, size);
|
||||
}
|
||||
|
||||
static int videotoolbox_hevc_end_frame(AVCodecContext *avctx)
|
||||
@@ -935,9 +969,7 @@ static int videotoolbox_hevc_end_frame(AVCodecContext *avctx)
|
||||
HEVCContext *h = avctx->priv_data;
|
||||
AVFrame *frame = h->ref->frame;
|
||||
VTContext *vtctx = avctx->internal->hwaccel_priv_data;
|
||||
int ret;
|
||||
|
||||
ret = videotoolbox_common_end_frame(avctx, frame);
|
||||
int ret = videotoolbox_common_end_frame(avctx, frame);
|
||||
vtctx->bitstream_size = 0;
|
||||
return ret;
|
||||
}
|
||||
@@ -1086,8 +1118,8 @@ const AVHWAccel ff_hevc_videotoolbox_hwaccel = {
|
||||
.id = AV_CODEC_ID_HEVC,
|
||||
.pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
|
||||
.alloc_frame = ff_videotoolbox_alloc_frame,
|
||||
.start_frame = ff_videotoolbox_h264_start_frame,
|
||||
.decode_slice = ff_videotoolbox_h264_decode_slice,
|
||||
.start_frame = videotoolbox_hevc_start_frame,
|
||||
.decode_slice = videotoolbox_hevc_decode_slice,
|
||||
.decode_params = videotoolbox_hevc_decode_params,
|
||||
.end_frame = videotoolbox_hevc_end_frame,
|
||||
.frame_params = videotoolbox_frame_params,
|
||||
|
||||
@@ -1262,19 +1262,16 @@ static int vtenc_create_encoder(AVCodecContext *avctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_cold int vtenc_init(AVCodecContext *avctx)
|
||||
static int vtenc_configure_encoder(AVCodecContext *avctx)
|
||||
{
|
||||
CFMutableDictionaryRef enc_info;
|
||||
CFMutableDictionaryRef pixel_buffer_info;
|
||||
CMVideoCodecType codec_type;
|
||||
VTEncContext *vtctx = avctx->priv_data;
|
||||
CFStringRef profile_level;
|
||||
CFBooleanRef has_b_frames_cfbool;
|
||||
CFNumberRef gamma_level = NULL;
|
||||
int status;
|
||||
|
||||
pthread_once(&once_ctrl, loadVTEncSymbols);
|
||||
|
||||
codec_type = get_cm_codec_type(avctx->codec_id);
|
||||
if (!codec_type) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Error: no mapping for AVCodecID %d\n", avctx->codec_id);
|
||||
@@ -1304,8 +1301,6 @@ static av_cold int vtenc_init(AVCodecContext *avctx)
|
||||
if (!get_vt_hevc_profile_level(avctx, &profile_level)) return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
vtctx->session = NULL;
|
||||
|
||||
enc_info = CFDictionaryCreateMutable(
|
||||
kCFAllocatorDefault,
|
||||
20,
|
||||
@@ -1335,8 +1330,6 @@ static av_cold int vtenc_init(AVCodecContext *avctx)
|
||||
pixel_buffer_info = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_init(&vtctx->lock, NULL);
|
||||
pthread_cond_init(&vtctx->cv_sample_sent, NULL);
|
||||
vtctx->dts_delta = vtctx->has_b_frames ? -1 : 0;
|
||||
|
||||
get_cv_transfer_function(avctx, &vtctx->transfer_function, &gamma_level);
|
||||
@@ -1363,8 +1356,32 @@ static av_cold int vtenc_init(AVCodecContext *avctx)
|
||||
pixel_buffer_info,
|
||||
&vtctx->session);
|
||||
|
||||
if (status < 0)
|
||||
goto init_cleanup;
|
||||
init_cleanup:
|
||||
if (gamma_level)
|
||||
CFRelease(gamma_level);
|
||||
|
||||
if (pixel_buffer_info)
|
||||
CFRelease(pixel_buffer_info);
|
||||
|
||||
CFRelease(enc_info);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static av_cold int vtenc_init(AVCodecContext *avctx)
|
||||
{
|
||||
VTEncContext *vtctx = avctx->priv_data;
|
||||
CFBooleanRef has_b_frames_cfbool;
|
||||
int status;
|
||||
|
||||
pthread_once(&once_ctrl, loadVTEncSymbols);
|
||||
|
||||
pthread_mutex_init(&vtctx->lock, NULL);
|
||||
pthread_cond_init(&vtctx->cv_sample_sent, NULL);
|
||||
|
||||
vtctx->session = NULL;
|
||||
status = vtenc_configure_encoder(avctx);
|
||||
if (status) return status;
|
||||
|
||||
status = VTSessionCopyProperty(vtctx->session,
|
||||
kVTCompressionPropertyKey_AllowFrameReordering,
|
||||
@@ -1378,16 +1395,7 @@ static av_cold int vtenc_init(AVCodecContext *avctx)
|
||||
}
|
||||
avctx->has_b_frames = vtctx->has_b_frames;
|
||||
|
||||
init_cleanup:
|
||||
if (gamma_level)
|
||||
CFRelease(gamma_level);
|
||||
|
||||
if (pixel_buffer_info)
|
||||
CFRelease(pixel_buffer_info);
|
||||
|
||||
CFRelease(enc_info);
|
||||
|
||||
return status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vtenc_get_frame_info(CMSampleBufferRef buffer, bool *is_key_frame)
|
||||
@@ -2167,8 +2175,27 @@ static int create_cv_pixel_buffer(AVCodecContext *avctx,
|
||||
#if TARGET_OS_IPHONE
|
||||
pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
|
||||
if (!pix_buf_pool) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Could not get pixel buffer pool.\n");
|
||||
return AVERROR_EXTERNAL;
|
||||
/* On iOS, the VT session is invalidated when the APP switches from
|
||||
* foreground to background and vice versa. Fetch the actual error code
|
||||
* of the VT session to detect that case and restart the VT session
|
||||
* accordingly. */
|
||||
OSStatus vtstatus;
|
||||
|
||||
vtstatus = VTCompressionSessionPrepareToEncodeFrames(vtctx->session);
|
||||
if (vtstatus == kVTInvalidSessionErr) {
|
||||
CFRelease(vtctx->session);
|
||||
vtctx->session = NULL;
|
||||
status = vtenc_configure_encoder(avctx);
|
||||
if (status == 0)
|
||||
pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
|
||||
}
|
||||
if (!pix_buf_pool) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Could not get pixel buffer pool.\n");
|
||||
return AVERROR_EXTERNAL;
|
||||
}
|
||||
else
|
||||
av_log(avctx, AV_LOG_WARNING, "VT session restarted because of a "
|
||||
"kVTInvalidSessionErr error.\n");
|
||||
}
|
||||
|
||||
status = CVPixelBufferPoolCreatePixelBuffer(NULL,
|
||||
@@ -2473,13 +2500,14 @@ static av_cold int vtenc_close(AVCodecContext *avctx)
|
||||
{
|
||||
VTEncContext *vtctx = avctx->priv_data;
|
||||
|
||||
pthread_cond_destroy(&vtctx->cv_sample_sent);
|
||||
pthread_mutex_destroy(&vtctx->lock);
|
||||
|
||||
if(!vtctx->session) return 0;
|
||||
|
||||
VTCompressionSessionCompleteFrames(vtctx->session,
|
||||
kCMTimeIndefinite);
|
||||
clear_frame_queue(vtctx);
|
||||
pthread_cond_destroy(&vtctx->cv_sample_sent);
|
||||
pthread_mutex_destroy(&vtctx->lock);
|
||||
CFRelease(vtctx->session);
|
||||
vtctx->session = NULL;
|
||||
|
||||
|
||||
@@ -28,6 +28,9 @@ static int parse(AVCodecParserContext *s,
|
||||
unsigned int frame_type;
|
||||
unsigned int profile;
|
||||
|
||||
*poutbuf = buf;
|
||||
*poutbuf_size = buf_size;
|
||||
|
||||
if (buf_size < 3)
|
||||
return buf_size;
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ typedef struct WavpackContext {
|
||||
|
||||
#define LEVEL_DECAY(a) (((a) + 0x80) >> 8)
|
||||
|
||||
static av_always_inline int get_tail(GetBitContext *gb, int k)
|
||||
static av_always_inline unsigned get_tail(GetBitContext *gb, int k)
|
||||
{
|
||||
int p, e, res;
|
||||
|
||||
@@ -452,7 +452,7 @@ static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb,
|
||||
if (type != AV_SAMPLE_FMT_S16P)
|
||||
R2 = R + ((s->decorr[i].weightB * (int64_t)L2 + 512) >> 10);
|
||||
else
|
||||
R2 = R + ((int)(s->decorr[i].weightB * (unsigned)L2 + 512) >> 10);
|
||||
R2 = R + (unsigned)((int)(s->decorr[i].weightB * (unsigned)L2 + 512) >> 10);
|
||||
UPDATE_WEIGHT_CLIP(s->decorr[i].weightB, s->decorr[i].delta, L2, R);
|
||||
R = R2;
|
||||
s->decorr[i].samplesA[0] = R;
|
||||
|
||||
@@ -99,8 +99,8 @@ typedef struct WvChannel {
|
||||
|
||||
// macros for manipulating median values
|
||||
#define GET_MED(n) ((c->median[n] >> 4) + 1)
|
||||
#define DEC_MED(n) c->median[n] -= ((c->median[n] + (128 >> (n)) - 2) / (128 >> (n))) * 2U
|
||||
#define INC_MED(n) c->median[n] += ((c->median[n] + (128 >> (n)) ) / (128 >> (n))) * 5U
|
||||
#define DEC_MED(n) c->median[n] -= ((int)(c->median[n] + (128U >> (n)) - 2) / (128 >> (n))) * 2U
|
||||
#define INC_MED(n) c->median[n] += ((int)(c->median[n] + (128U >> (n)) ) / (128 >> (n))) * 5U
|
||||
|
||||
// macros for applying weight
|
||||
#define UPDATE_WEIGHT_CLIP(weight, delta, samples, in) \
|
||||
|
||||
+7
-3
@@ -39,6 +39,7 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data,
|
||||
uint32_t pixformat, pixdepth, bunit, bitorder, bpad;
|
||||
uint32_t rgb[3];
|
||||
uint8_t *ptr;
|
||||
int width, height;
|
||||
GetByteContext gb;
|
||||
|
||||
if (buf_size < XWD_HEADER_SIZE)
|
||||
@@ -60,8 +61,8 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data,
|
||||
|
||||
pixformat = bytestream2_get_be32u(&gb);
|
||||
pixdepth = bytestream2_get_be32u(&gb);
|
||||
avctx->width = bytestream2_get_be32u(&gb);
|
||||
avctx->height = bytestream2_get_be32u(&gb);
|
||||
width = bytestream2_get_be32u(&gb);
|
||||
height = bytestream2_get_be32u(&gb);
|
||||
xoffset = bytestream2_get_be32u(&gb);
|
||||
be = bytestream2_get_be32u(&gb);
|
||||
bunit = bytestream2_get_be32u(&gb);
|
||||
@@ -77,6 +78,9 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data,
|
||||
ncolors = bytestream2_get_be32u(&gb);
|
||||
bytestream2_skipu(&gb, header_size - (XWD_HEADER_SIZE - 20));
|
||||
|
||||
if ((ret = ff_set_dimensions(avctx, width, height)) < 0)
|
||||
return ret;
|
||||
|
||||
av_log(avctx, AV_LOG_DEBUG,
|
||||
"pixformat %"PRIu32", pixdepth %"PRIu32", bunit %"PRIu32", bitorder %"PRIu32", bpad %"PRIu32"\n",
|
||||
pixformat, pixdepth, bunit, bitorder, bpad);
|
||||
@@ -227,7 +231,7 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data,
|
||||
blue = bytestream2_get_byteu(&gb);
|
||||
bytestream2_skipu(&gb, 3); // skip bitmask flag and padding
|
||||
|
||||
dst[i] = red << 16 | green << 8 | blue;
|
||||
dst[i] = 0xFFU << 24 | red << 16 | green << 8 | blue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -855,7 +855,7 @@ static const AVClass android_camera_class = {
|
||||
.class_name = "android_camera indev",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVDEVICE_VERSION_INT,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
.category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT,
|
||||
};
|
||||
|
||||
|
||||
@@ -467,16 +467,19 @@ static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt)
|
||||
|
||||
// Drop Packet if queue size is > maximum queue size
|
||||
if (avpacket_queue_size(q) > (uint64_t)q->max_q_size) {
|
||||
av_packet_unref(pkt);
|
||||
av_log(q->avctx, AV_LOG_WARNING, "Decklink input buffer overrun!\n");
|
||||
return -1;
|
||||
}
|
||||
/* ensure the packet is reference counted */
|
||||
if (av_packet_make_refcounted(pkt) < 0) {
|
||||
av_packet_unref(pkt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pkt1 = (AVPacketList *)av_malloc(sizeof(AVPacketList));
|
||||
if (!pkt1) {
|
||||
av_packet_unref(pkt);
|
||||
return -1;
|
||||
}
|
||||
av_packet_move_ref(&pkt1->pkt, pkt);
|
||||
|
||||
+14
-4
@@ -118,7 +118,7 @@ static int iec61883_callback(unsigned char *data, int length,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
packet->buf = av_malloc(length);
|
||||
packet->buf = av_malloc(length + AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!packet->buf) {
|
||||
av_free(packet);
|
||||
ret = -1;
|
||||
@@ -127,6 +127,7 @@ static int iec61883_callback(unsigned char *data, int length,
|
||||
packet->len = length;
|
||||
|
||||
memcpy(packet->buf, data, length);
|
||||
memset(packet->buf + length, 0, AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
|
||||
if (dv->queue_first) {
|
||||
dv->queue_last->next = packet;
|
||||
@@ -200,13 +201,21 @@ static int iec61883_parse_queue_dv(struct iec61883_data *dv, AVPacket *pkt)
|
||||
size = avpriv_dv_produce_packet(dv->dv_demux, pkt,
|
||||
packet->buf, packet->len, -1);
|
||||
dv->queue_first = packet->next;
|
||||
if (size < 0)
|
||||
av_free(packet->buf);
|
||||
av_free(packet);
|
||||
dv->packets--;
|
||||
|
||||
if (size > 0)
|
||||
return size;
|
||||
if (size < 0)
|
||||
return -1;
|
||||
|
||||
return -1;
|
||||
if (av_packet_from_data(pkt, pkt->data, pkt->size) < 0) {
|
||||
av_freep(&pkt->data);
|
||||
av_packet_unref(pkt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int iec61883_parse_queue_hdv(struct iec61883_data *dv, AVPacket *pkt)
|
||||
@@ -454,6 +463,7 @@ static int iec61883_close(AVFormatContext *context)
|
||||
} else {
|
||||
iec61883_dv_fb_stop(dv->iec61883_dv);
|
||||
iec61883_dv_fb_close(dv->iec61883_dv);
|
||||
av_freep(&dv->dv_demux);
|
||||
}
|
||||
while (dv->queue_first) {
|
||||
DVPacket *packet = dv->queue_first;
|
||||
|
||||
@@ -267,7 +267,7 @@ OBJS-$(CONFIG_OSCILLOSCOPE_FILTER) += vf_datascope.o
|
||||
OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o framesync.o
|
||||
OBJS-$(CONFIG_OVERLAY_OPENCL_FILTER) += vf_overlay_opencl.o opencl.o \
|
||||
opencl/overlay.o framesync.o
|
||||
OBJS-$(CONFIG_OVERLAY_QSV_FILTER) += vf_overlay_qsv.o
|
||||
OBJS-$(CONFIG_OVERLAY_QSV_FILTER) += vf_overlay_qsv.o framesync.o
|
||||
OBJS-$(CONFIG_OWDENOISE_FILTER) += vf_owdenoise.o
|
||||
OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o
|
||||
OBJS-$(CONFIG_PALETTEGEN_FILTER) += vf_palettegen.o
|
||||
|
||||
@@ -296,7 +296,7 @@ static QSVFrame *submit_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *p
|
||||
av_log(ctx, AV_LOG_ERROR, "QSVVPP gets a wrong frame.\n");
|
||||
return NULL;
|
||||
}
|
||||
qsv_frame->frame = picref;
|
||||
qsv_frame->frame = av_frame_clone(picref);
|
||||
qsv_frame->surface = (mfxFrameSurface1 *)qsv_frame->frame->data[3];
|
||||
} else {
|
||||
/* make a copy if the input is not padded as libmfx requires */
|
||||
@@ -318,7 +318,7 @@ static QSVFrame *submit_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *p
|
||||
av_frame_copy_props(qsv_frame->frame, picref);
|
||||
av_frame_free(&picref);
|
||||
} else
|
||||
qsv_frame->frame = picref;
|
||||
qsv_frame->frame = av_frame_clone(picref);
|
||||
|
||||
if (map_frame_to_surface(qsv_frame->frame,
|
||||
&qsv_frame->surface_internal) < 0) {
|
||||
|
||||
+78
-137
@@ -36,6 +36,7 @@
|
||||
#include "formats.h"
|
||||
#include "video.h"
|
||||
|
||||
#include "framesync.h"
|
||||
#include "qsvvpp.h"
|
||||
|
||||
#define MAIN 0
|
||||
@@ -56,14 +57,10 @@ enum var_name {
|
||||
VAR_VARS_NB
|
||||
};
|
||||
|
||||
enum EOFAction {
|
||||
EOF_ACTION_REPEAT,
|
||||
EOF_ACTION_ENDALL
|
||||
};
|
||||
|
||||
typedef struct QSVOverlayContext {
|
||||
const AVClass *class;
|
||||
|
||||
FFFrameSync fs;
|
||||
QSVVPPContext *qsv;
|
||||
QSVVPPParam qsv_param;
|
||||
mfxExtVPPComposite comp_conf;
|
||||
@@ -72,10 +69,6 @@ typedef struct QSVOverlayContext {
|
||||
char *overlay_ox, *overlay_oy, *overlay_ow, *overlay_oh;
|
||||
uint16_t overlay_alpha, overlay_pixel_alpha;
|
||||
|
||||
enum EOFAction eof_action; /* action to take on EOF from source */
|
||||
|
||||
AVFrame *main;
|
||||
AVFrame *over_prev, *over_next;
|
||||
} QSVOverlayContext;
|
||||
|
||||
static const char *const var_names[] = {
|
||||
@@ -90,20 +83,25 @@ static const char *const var_names[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static const AVOption options[] = {
|
||||
static const AVOption overlay_qsv_options[] = {
|
||||
{ "x", "Overlay x position", OFFSET(overlay_ox), AV_OPT_TYPE_STRING, { .str="0"}, 0, 255, .flags = FLAGS},
|
||||
{ "y", "Overlay y position", OFFSET(overlay_oy), AV_OPT_TYPE_STRING, { .str="0"}, 0, 255, .flags = FLAGS},
|
||||
{ "w", "Overlay width", OFFSET(overlay_ow), AV_OPT_TYPE_STRING, { .str="overlay_iw"}, 0, 255, .flags = FLAGS},
|
||||
{ "h", "Overlay height", OFFSET(overlay_oh), AV_OPT_TYPE_STRING, { .str="overlay_ih*w/overlay_iw"}, 0, 255, .flags = FLAGS},
|
||||
{ "alpha", "Overlay global alpha", OFFSET(overlay_alpha), AV_OPT_TYPE_INT, { .i64 = 255}, 0, 255, .flags = FLAGS},
|
||||
{ "eof_action", "Action to take when encountering EOF from secondary input ",
|
||||
OFFSET(eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT },
|
||||
EOF_ACTION_REPEAT, EOF_ACTION_ENDALL, .flags = FLAGS, "eof_action" },
|
||||
{ "repeat", "Repeat the previous frame.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_REPEAT }, .flags = FLAGS, "eof_action" },
|
||||
{ "endall", "End both streams.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_ENDALL }, .flags = FLAGS, "eof_action" },
|
||||
OFFSET(fs.opt_eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT },
|
||||
EOF_ACTION_REPEAT, EOF_ACTION_PASS, .flags = FLAGS, "eof_action" },
|
||||
{ "repeat", "Repeat the previous frame.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_REPEAT }, .flags = FLAGS, "eof_action" },
|
||||
{ "endall", "End both streams.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_ENDALL }, .flags = FLAGS, "eof_action" },
|
||||
{ "pass", "Pass through the main input.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_PASS }, .flags = FLAGS, "eof_action" },
|
||||
{ "shortest", "force termination when the shortest input terminates", OFFSET(fs.opt_shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
|
||||
{ "repeatlast", "repeat overlay of the last overlay frame", OFFSET(fs.opt_repeatlast), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
FRAMESYNC_DEFINE_CLASS(overlay_qsv, QSVOverlayContext, fs);
|
||||
|
||||
static int eval_expr(AVFilterContext *ctx)
|
||||
{
|
||||
QSVOverlayContext *vpp = ctx->priv;
|
||||
@@ -230,12 +228,53 @@ static int config_overlay_input(AVFilterLink *inlink)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_frame(FFFrameSync *fs)
|
||||
{
|
||||
AVFilterContext *ctx = fs->parent;
|
||||
QSVOverlayContext *s = fs->opaque;
|
||||
AVFrame *frame = NULL;
|
||||
int ret = 0, i;
|
||||
|
||||
for (i = 0; i < ctx->nb_inputs; i++) {
|
||||
ret = ff_framesync_get_frame(fs, i, &frame, 0);
|
||||
if (ret == 0)
|
||||
ret = ff_qsvvpp_filter_frame(s->qsv, ctx->inputs[i], frame);
|
||||
if (ret < 0 && ret != AVERROR(EAGAIN))
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int init_framesync(AVFilterContext *ctx)
|
||||
{
|
||||
QSVOverlayContext *s = ctx->priv;
|
||||
int ret, i;
|
||||
|
||||
s->fs.on_event = process_frame;
|
||||
s->fs.opaque = s;
|
||||
ret = ff_framesync_init(&s->fs, ctx, ctx->nb_inputs);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < ctx->nb_inputs; i++) {
|
||||
FFFrameSyncIn *in = &s->fs.in[i];
|
||||
in->before = EXT_STOP;
|
||||
in->after = EXT_INFINITY;
|
||||
in->sync = i ? 1 : 2;
|
||||
in->time_base = ctx->inputs[i]->time_base;
|
||||
}
|
||||
|
||||
return ff_framesync_configure(&s->fs);
|
||||
}
|
||||
|
||||
static int config_output(AVFilterLink *outlink)
|
||||
{
|
||||
AVFilterContext *ctx = outlink->src;
|
||||
QSVOverlayContext *vpp = ctx->priv;
|
||||
AVFilterLink *in0 = ctx->inputs[0];
|
||||
AVFilterLink *in1 = ctx->inputs[1];
|
||||
int ret;
|
||||
|
||||
av_log(ctx, AV_LOG_DEBUG, "Output is of %s.\n", av_get_pix_fmt_name(outlink->format));
|
||||
if ((in0->format == AV_PIX_FMT_QSV && in1->format != AV_PIX_FMT_QSV) ||
|
||||
@@ -257,121 +296,27 @@ static int config_output(AVFilterLink *outlink)
|
||||
outlink->frame_rate = in0->frame_rate;
|
||||
outlink->time_base = av_inv_q(outlink->frame_rate);
|
||||
|
||||
ret = init_framesync(ctx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ff_qsvvpp_create(ctx, &vpp->qsv, &vpp->qsv_param);
|
||||
}
|
||||
|
||||
static int blend_frame(AVFilterContext *ctx, AVFrame *mpic, AVFrame *opic)
|
||||
/*
|
||||
* Callback for qsvvpp
|
||||
* @Note: qsvvpp composition does not generate PTS for result frame.
|
||||
* so we assign the PTS from framesync to the output frame.
|
||||
*/
|
||||
|
||||
static int filter_callback(AVFilterLink *outlink, AVFrame *frame)
|
||||
{
|
||||
int ret = 0;
|
||||
QSVOverlayContext *vpp = ctx->priv;
|
||||
AVFrame *opic_copy = NULL;
|
||||
|
||||
ret = ff_qsvvpp_filter_frame(vpp->qsv, ctx->inputs[0], mpic);
|
||||
if (ret == 0 || ret == AVERROR(EAGAIN)) {
|
||||
/* Reference the overlay frame. Because:
|
||||
* 1. ff_qsvvpp_filter_frame will take control of the given frame
|
||||
* 2. We need to repeat the overlay frame when 2nd input goes into EOF
|
||||
*/
|
||||
opic_copy = av_frame_clone(opic);
|
||||
if (!opic_copy)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
ret = ff_qsvvpp_filter_frame(vpp->qsv, ctx->inputs[1], opic_copy);
|
||||
}
|
||||
|
||||
return ret;
|
||||
QSVOverlayContext *s = outlink->src->priv;
|
||||
frame->pts = av_rescale_q(s->fs.pts,
|
||||
s->fs.time_base, outlink->time_base);
|
||||
return ff_filter_frame(outlink, frame);
|
||||
}
|
||||
|
||||
static int handle_overlay_eof(AVFilterContext *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
QSVOverlayContext *s = ctx->priv;
|
||||
/* Repeat previous frame on secondary input */
|
||||
if (s->over_prev && s->eof_action == EOF_ACTION_REPEAT)
|
||||
ret = blend_frame(ctx, s->main, s->over_prev);
|
||||
/* End both streams */
|
||||
else if (s->eof_action == EOF_ACTION_ENDALL)
|
||||
return AVERROR_EOF;
|
||||
|
||||
s->main = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int request_frame(AVFilterLink *outlink)
|
||||
{
|
||||
AVFilterContext *ctx = outlink->src;
|
||||
QSVOverlayContext *s = ctx->priv;
|
||||
AVRational tb_main = ctx->inputs[MAIN]->time_base;
|
||||
AVRational tb_over = ctx->inputs[OVERLAY]->time_base;
|
||||
int ret = 0;
|
||||
|
||||
/* get a frame on the main input */
|
||||
if (!s->main) {
|
||||
ret = ff_request_frame(ctx->inputs[MAIN]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get a new frame on the overlay input, on EOF check setting 'eof_action' */
|
||||
if (!s->over_next) {
|
||||
ret = ff_request_frame(ctx->inputs[OVERLAY]);
|
||||
if (ret == AVERROR_EOF)
|
||||
return handle_overlay_eof(ctx);
|
||||
else if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (s->main->pts != AV_NOPTS_VALUE &&
|
||||
s->over_next->pts != AV_NOPTS_VALUE &&
|
||||
av_compare_ts(s->over_next->pts, tb_over, s->main->pts, tb_main) < 0) {
|
||||
av_frame_free(&s->over_prev);
|
||||
FFSWAP(AVFrame*, s->over_prev, s->over_next);
|
||||
|
||||
ret = ff_request_frame(ctx->inputs[OVERLAY]);
|
||||
if (ret == AVERROR_EOF)
|
||||
return handle_overlay_eof(ctx);
|
||||
else if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (s->main->pts == AV_NOPTS_VALUE ||
|
||||
s->over_next->pts == AV_NOPTS_VALUE ||
|
||||
!av_compare_ts(s->over_next->pts, tb_over, s->main->pts, tb_main)) {
|
||||
ret = blend_frame(ctx, s->main, s->over_next);
|
||||
av_frame_free(&s->over_prev);
|
||||
FFSWAP(AVFrame*, s->over_prev, s->over_next);
|
||||
} else if (s->over_prev) {
|
||||
ret = blend_frame(ctx, s->main, s->over_prev);
|
||||
} else {
|
||||
av_frame_free(&s->main);
|
||||
ret = AVERROR(EAGAIN);
|
||||
}
|
||||
|
||||
s->main = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int filter_frame_main(AVFilterLink *inlink, AVFrame *frame)
|
||||
{
|
||||
QSVOverlayContext *s = inlink->dst->priv;
|
||||
|
||||
av_assert0(!s->main);
|
||||
s->main = frame;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int filter_frame_overlay(AVFilterLink *inlink, AVFrame *frame)
|
||||
{
|
||||
QSVOverlayContext *s = inlink->dst->priv;
|
||||
|
||||
av_assert0(!s->over_next);
|
||||
s->over_next = frame;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int overlay_qsv_init(AVFilterContext *ctx)
|
||||
{
|
||||
@@ -387,7 +332,7 @@ static int overlay_qsv_init(AVFilterContext *ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
/* initialize QSVVPP params */
|
||||
vpp->qsv_param.filter_frame = NULL;
|
||||
vpp->qsv_param.filter_frame = filter_callback;
|
||||
vpp->qsv_param.ext_buf = av_mallocz(sizeof(*vpp->qsv_param.ext_buf));
|
||||
if (!vpp->qsv_param.ext_buf)
|
||||
return AVERROR(ENOMEM);
|
||||
@@ -404,14 +349,18 @@ static void overlay_qsv_uninit(AVFilterContext *ctx)
|
||||
{
|
||||
QSVOverlayContext *vpp = ctx->priv;
|
||||
|
||||
av_frame_free(&vpp->main);
|
||||
av_frame_free(&vpp->over_prev);
|
||||
av_frame_free(&vpp->over_next);
|
||||
ff_qsvvpp_free(&vpp->qsv);
|
||||
ff_framesync_uninit(&vpp->fs);
|
||||
av_freep(&vpp->comp_conf.InputStream);
|
||||
av_freep(&vpp->qsv_param.ext_buf);
|
||||
}
|
||||
|
||||
static int activate(AVFilterContext *ctx)
|
||||
{
|
||||
QSVOverlayContext *s = ctx->priv;
|
||||
return ff_framesync_activate(&s->fs);
|
||||
}
|
||||
|
||||
static int overlay_qsv_query_formats(AVFilterContext *ctx)
|
||||
{
|
||||
int i;
|
||||
@@ -444,25 +393,16 @@ static int overlay_qsv_query_formats(AVFilterContext *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const AVClass overlay_qsv_class = {
|
||||
.class_name = "overlay_qsv",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
static const AVFilterPad overlay_qsv_inputs[] = {
|
||||
{
|
||||
.name = "main",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.filter_frame = filter_frame_main,
|
||||
.config_props = config_main_input,
|
||||
.needs_fifo = 1,
|
||||
},
|
||||
{
|
||||
.name = "overlay",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.filter_frame = filter_frame_overlay,
|
||||
.config_props = config_overlay_input,
|
||||
.needs_fifo = 1,
|
||||
},
|
||||
@@ -474,7 +414,6 @@ static const AVFilterPad overlay_qsv_outputs[] = {
|
||||
.name = "default",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.config_props = config_output,
|
||||
.request_frame = request_frame,
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
@@ -484,8 +423,10 @@ AVFilter ff_vf_overlay_qsv = {
|
||||
.description = NULL_IF_CONFIG_SMALL("Quick Sync Video overlay."),
|
||||
.priv_size = sizeof(QSVOverlayContext),
|
||||
.query_formats = overlay_qsv_query_formats,
|
||||
.preinit = overlay_qsv_framesync_preinit,
|
||||
.init = overlay_qsv_init,
|
||||
.uninit = overlay_qsv_uninit,
|
||||
.activate = activate,
|
||||
.inputs = overlay_qsv_inputs,
|
||||
.outputs = overlay_qsv_outputs,
|
||||
.priv_class = &overlay_qsv_class,
|
||||
|
||||
@@ -341,9 +341,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
|
||||
VPPContext *vpp = inlink->dst->priv;
|
||||
AVFilterLink *outlink = ctx->outputs[0];
|
||||
|
||||
if (vpp->qsv)
|
||||
if (vpp->qsv) {
|
||||
ret = ff_qsvvpp_filter_frame(vpp->qsv, inlink, picref);
|
||||
else {
|
||||
av_frame_free(&picref);
|
||||
} else {
|
||||
if (picref->pts != AV_NOPTS_VALUE)
|
||||
picref->pts = av_rescale_q(picref->pts, inlink->time_base, outlink->time_base);
|
||||
ret = ff_filter_frame(outlink, picref);
|
||||
|
||||
@@ -706,7 +706,8 @@ static int parse_video_info(AVIOContext *pb, AVStream *st)
|
||||
st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag);
|
||||
size_bmp = FFMAX(size_asf, size_bmp);
|
||||
|
||||
if (size_bmp > BMP_HEADER_SIZE) {
|
||||
if (size_bmp > BMP_HEADER_SIZE &&
|
||||
size_bmp < INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
|
||||
int ret;
|
||||
st->codecpar->extradata_size = size_bmp - BMP_HEADER_SIZE;
|
||||
if (!(st->codecpar->extradata = av_malloc(st->codecpar->extradata_size +
|
||||
|
||||
@@ -163,7 +163,7 @@ static int bin_probe(AVProbeData *p)
|
||||
|
||||
if (par.width * par.height * 2 / (8*16) == p->buf_size)
|
||||
return AVPROBE_SCORE_MAX / 2;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sauce)
|
||||
|
||||
@@ -198,7 +198,7 @@ static int bluray_read(URLContext *h, unsigned char *buf, int size)
|
||||
|
||||
len = bd_read(bd->bd, buf, size);
|
||||
|
||||
return len;
|
||||
return len == 0 ? AVERROR_EOF : len;
|
||||
}
|
||||
|
||||
static int64_t bluray_seek(URLContext *h, int64_t pos, int whence)
|
||||
|
||||
@@ -988,13 +988,6 @@ static int dash_init(AVFormatContext *s)
|
||||
|
||||
av_log(s, AV_LOG_VERBOSE, "Representation %d init segment will be written to: %s\n", i, filename);
|
||||
|
||||
// Flush init segment
|
||||
// except for mp4, since delay_moov is set and the init segment
|
||||
// is then flushed after the first packets
|
||||
if (strcmp(os->format_name, "mp4")) {
|
||||
flush_init_segment(s, os);
|
||||
}
|
||||
|
||||
s->streams[i]->time_base = st->time_base;
|
||||
// If the muxer wants to shift timestamps, request to have them shifted
|
||||
// already before being handed to this muxer, so we don't have mismatches
|
||||
@@ -1035,6 +1028,12 @@ static int dash_write_header(AVFormatContext *s)
|
||||
OutputStream *os = &c->streams[i];
|
||||
if ((ret = avformat_write_header(os->ctx, NULL)) < 0)
|
||||
return ret;
|
||||
// Flush init segment
|
||||
// Only for WebM segment, since for mp4 delay_moov is set and
|
||||
// the init segment is thus flushed after the first packets.
|
||||
if (strcmp(os->format_name, "mp4") &&
|
||||
(ret = flush_init_segment(s, os)) < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = write_manifest(s, 0);
|
||||
if (!ret)
|
||||
|
||||
+252
-36
@@ -21,10 +21,13 @@
|
||||
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "libavutil/pixdesc.h"
|
||||
#include "libavcodec/flac.h"
|
||||
#include "avformat.h"
|
||||
#include "avio_internal.h"
|
||||
#include "flacenc.h"
|
||||
#include "id3v2.h"
|
||||
#include "internal.h"
|
||||
#include "vorbiscomment.h"
|
||||
#include "libavcodec/bytestream.h"
|
||||
|
||||
@@ -33,8 +36,15 @@ typedef struct FlacMuxerContext {
|
||||
const AVClass *class;
|
||||
int write_header;
|
||||
|
||||
int audio_stream_idx;
|
||||
int waiting_pics;
|
||||
/* audio packets are queued here until we get all the attached pictures */
|
||||
AVPacketList *queue, *queue_end;
|
||||
|
||||
/* updated streaminfo sent by the encoder at the end */
|
||||
uint8_t *streaminfo;
|
||||
|
||||
unsigned attached_types;
|
||||
} FlacMuxerContext;
|
||||
|
||||
static int flac_write_block_padding(AVIOContext *pb, unsigned int n_padding_bytes,
|
||||
@@ -74,36 +84,160 @@ static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flac_write_header(struct AVFormatContext *s)
|
||||
static int flac_write_picture(struct AVFormatContext *s, AVPacket *pkt)
|
||||
{
|
||||
int ret;
|
||||
int padding = s->metadata_header_padding;
|
||||
AVCodecParameters *par = s->streams[0]->codecpar;
|
||||
FlacMuxerContext *c = s->priv_data;
|
||||
FlacMuxerContext *c = s->priv_data;
|
||||
AVIOContext *pb = s->pb;
|
||||
const AVPixFmtDescriptor *pixdesc;
|
||||
const CodecMime *mime = ff_id3v2_mime_tags;
|
||||
AVDictionaryEntry *e;
|
||||
const char *mimetype = NULL, *desc = "";
|
||||
const AVStream *st = s->streams[pkt->stream_index];
|
||||
int i, mimelen, desclen, type = 0;
|
||||
|
||||
if (!c->write_header)
|
||||
if (!pkt->data)
|
||||
return 0;
|
||||
|
||||
if (s->nb_streams > 1) {
|
||||
av_log(s, AV_LOG_ERROR, "only one stream is supported\n");
|
||||
while (mime->id != AV_CODEC_ID_NONE) {
|
||||
if (mime->id == st->codecpar->codec_id) {
|
||||
mimetype = mime->str;
|
||||
break;
|
||||
}
|
||||
mime++;
|
||||
}
|
||||
if (!mimetype) {
|
||||
av_log(s, AV_LOG_ERROR, "No mimetype is known for stream %d, cannot "
|
||||
"write an attached picture.\n", st->index);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
if (par->codec_id != AV_CODEC_ID_FLAC) {
|
||||
av_log(s, AV_LOG_ERROR, "unsupported codec\n");
|
||||
mimelen = strlen(mimetype);
|
||||
|
||||
/* get the picture type */
|
||||
e = av_dict_get(st->metadata, "comment", NULL, 0);
|
||||
for (i = 0; e && i < FF_ARRAY_ELEMS(ff_id3v2_picture_types); i++) {
|
||||
if (!av_strcasecmp(e->value, ff_id3v2_picture_types[i])) {
|
||||
type = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((c->attached_types & (1 << type)) & 0x6) {
|
||||
av_log(s, AV_LOG_ERROR, "Duplicate attachment for type '%s'\n", ff_id3v2_picture_types[type]);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
if (type == 1 && (st->codecpar->codec_id != AV_CODEC_ID_PNG ||
|
||||
st->codecpar->width != 32 ||
|
||||
st->codecpar->height != 32)) {
|
||||
av_log(s, AV_LOG_ERROR, "File icon attachment must be a 32x32 PNG");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
c->attached_types |= (1 << type);
|
||||
|
||||
/* get the description */
|
||||
if ((e = av_dict_get(st->metadata, "title", NULL, 0)))
|
||||
desc = e->value;
|
||||
desclen = strlen(desc);
|
||||
|
||||
avio_w8(pb, 0x06);
|
||||
avio_wb24(pb, 4 + 4 + mimelen + 4 + desclen + 4 + 4 + 4 + 4 + 4 + pkt->size);
|
||||
|
||||
avio_wb32(pb, type);
|
||||
|
||||
avio_wb32(pb, mimelen);
|
||||
avio_write(pb, mimetype, mimelen);
|
||||
|
||||
avio_wb32(pb, desclen);
|
||||
avio_write(pb, desc, desclen);
|
||||
|
||||
avio_wb32(pb, st->codecpar->width);
|
||||
avio_wb32(pb, st->codecpar->height);
|
||||
if ((pixdesc = av_pix_fmt_desc_get(st->codecpar->format)))
|
||||
avio_wb32(pb, av_get_bits_per_pixel(pixdesc));
|
||||
else
|
||||
avio_wb32(pb, 0);
|
||||
avio_wb32(pb, 0);
|
||||
|
||||
avio_wb32(pb, pkt->size);
|
||||
avio_write(pb, pkt->data, pkt->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flac_finish_header(struct AVFormatContext *s)
|
||||
{
|
||||
int i, ret, padding = s->metadata_header_padding;
|
||||
if (padding < 0)
|
||||
padding = 8192;
|
||||
/* The FLAC specification states that 24 bits are used to represent the
|
||||
* size of a metadata block so we must clip this value to 2^24-1. */
|
||||
padding = av_clip_uintp2(padding, 24);
|
||||
|
||||
ret = ff_flac_write_header(s->pb, par->extradata,
|
||||
par->extradata_size, 0);
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
AVPacket *pkt = st->priv_data;
|
||||
if (!pkt)
|
||||
continue;
|
||||
ret = flac_write_picture(s, pkt);
|
||||
av_packet_unref(pkt);
|
||||
if (ret < 0 && (s->error_recognition & AV_EF_EXPLODE))
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = flac_write_block_comment(s->pb, &s->metadata, !padding,
|
||||
s->flags & AVFMT_FLAG_BITEXACT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* The command line flac encoder defaults to placing a seekpoint
|
||||
* every 10s. So one might add padding to allow that later
|
||||
* but there seems to be no simple way to get the duration here.
|
||||
* So just add the amount requested by the user. */
|
||||
if (padding)
|
||||
flac_write_block_padding(s->pb, padding, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flac_init(struct AVFormatContext *s)
|
||||
{
|
||||
AVCodecParameters *par;
|
||||
FlacMuxerContext *c = s->priv_data;
|
||||
int i;
|
||||
|
||||
c->audio_stream_idx = -1;
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
if (c->audio_stream_idx >= 0 || st->codecpar->codec_id != AV_CODEC_ID_FLAC) {
|
||||
av_log(s, AV_LOG_ERROR, "Invalid audio stream. Exactly one FLAC "
|
||||
"audio stream is required.\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
par = s->streams[i]->codecpar;
|
||||
c->audio_stream_idx = i;
|
||||
} else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
if (!(st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
|
||||
av_log(s, AV_LOG_WARNING, "Video stream #%d is not an attached picture. Ignoring\n", i);
|
||||
continue;
|
||||
} else if (st->codecpar->codec_id == AV_CODEC_ID_GIF) {
|
||||
av_log(s, AV_LOG_ERROR, "GIF image support is not implemented.\n");
|
||||
return AVERROR_PATCHWELCOME;
|
||||
} else if (!c->write_header) {
|
||||
av_log(s, AV_LOG_ERROR, "Can't write attached pictures without a header.\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
c->waiting_pics++;
|
||||
} else {
|
||||
av_log(s, AV_LOG_ERROR, "Only audio streams and pictures are allowed in FLAC.\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
}
|
||||
if (c->audio_stream_idx < 0) {
|
||||
av_log(s, AV_LOG_ERROR, "No audio stream present.\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
/* add the channel layout tag */
|
||||
if (par->channel_layout &&
|
||||
!(par->channel_layout & ~0x3ffffULL) &&
|
||||
@@ -121,28 +255,84 @@ static int flac_write_header(struct AVFormatContext *s)
|
||||
}
|
||||
}
|
||||
|
||||
ret = flac_write_block_comment(s->pb, &s->metadata, !padding,
|
||||
s->flags & AVFMT_FLAG_BITEXACT);
|
||||
if (ret)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flac_write_header(struct AVFormatContext *s)
|
||||
{
|
||||
FlacMuxerContext *c = s->priv_data;
|
||||
AVCodecParameters *par = s->streams[c->audio_stream_idx]->codecpar;
|
||||
int ret;
|
||||
|
||||
if (!c->write_header)
|
||||
return 0;
|
||||
|
||||
ret = ff_flac_write_header(s->pb, par->extradata,
|
||||
par->extradata_size, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* The command line flac encoder defaults to placing a seekpoint
|
||||
* every 10s. So one might add padding to allow that later
|
||||
* but there seems to be no simple way to get the duration here.
|
||||
* So just add the amount requested by the user. */
|
||||
if (padding)
|
||||
flac_write_block_padding(s->pb, padding, 1);
|
||||
if (!c->waiting_pics)
|
||||
ret = flac_finish_header(s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int flac_write_audio_packet(struct AVFormatContext *s, AVPacket *pkt)
|
||||
{
|
||||
FlacMuxerContext *c = s->priv_data;
|
||||
uint8_t *streaminfo;
|
||||
int streaminfo_size;
|
||||
|
||||
/* check for updated streaminfo */
|
||||
streaminfo = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
|
||||
&streaminfo_size);
|
||||
if (streaminfo && streaminfo_size == FLAC_STREAMINFO_SIZE) {
|
||||
av_freep(&c->streaminfo);
|
||||
|
||||
c->streaminfo = av_malloc(FLAC_STREAMINFO_SIZE);
|
||||
if (!c->streaminfo)
|
||||
return AVERROR(ENOMEM);
|
||||
memcpy(c->streaminfo, streaminfo, FLAC_STREAMINFO_SIZE);
|
||||
}
|
||||
|
||||
if (pkt->size)
|
||||
avio_write(s->pb, pkt->data, pkt->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flac_queue_flush(AVFormatContext *s)
|
||||
{
|
||||
FlacMuxerContext *c = s->priv_data;
|
||||
AVPacket pkt;
|
||||
int ret, write = 1;
|
||||
|
||||
ret = flac_finish_header(s);
|
||||
if (ret < 0)
|
||||
write = 0;
|
||||
|
||||
while (c->queue) {
|
||||
ff_packet_list_get(&c->queue, &c->queue_end, &pkt);
|
||||
if (write && (ret = flac_write_audio_packet(s, &pkt)) < 0)
|
||||
write = 0;
|
||||
av_packet_unref(&pkt);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int flac_write_trailer(struct AVFormatContext *s)
|
||||
{
|
||||
AVIOContext *pb = s->pb;
|
||||
int64_t file_size;
|
||||
FlacMuxerContext *c = s->priv_data;
|
||||
uint8_t *streaminfo = c->streaminfo ? c->streaminfo :
|
||||
s->streams[0]->codecpar->extradata;
|
||||
s->streams[c->audio_stream_idx]->codecpar->extradata;
|
||||
|
||||
if (c->waiting_pics) {
|
||||
av_log(s, AV_LOG_WARNING, "No packets were sent for some of the "
|
||||
"attached pictures.\n");
|
||||
flac_queue_flush(s);
|
||||
}
|
||||
|
||||
if (!c->write_header || !streaminfo)
|
||||
return 0;
|
||||
@@ -166,23 +356,48 @@ static int flac_write_trailer(struct AVFormatContext *s)
|
||||
static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt)
|
||||
{
|
||||
FlacMuxerContext *c = s->priv_data;
|
||||
uint8_t *streaminfo;
|
||||
int streaminfo_size;
|
||||
int ret;
|
||||
|
||||
/* check for updated streaminfo */
|
||||
streaminfo = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
|
||||
&streaminfo_size);
|
||||
if (streaminfo && streaminfo_size == FLAC_STREAMINFO_SIZE) {
|
||||
av_freep(&c->streaminfo);
|
||||
if (pkt->stream_index == c->audio_stream_idx) {
|
||||
if (c->waiting_pics) {
|
||||
/* buffer audio packets until we get all the pictures */
|
||||
ret = ff_packet_list_put(&c->queue, &c->queue_end, pkt, FF_PACKETLIST_FLAG_REF_PACKET);
|
||||
if (ret < 0) {
|
||||
av_log(s, AV_LOG_ERROR, "Out of memory in packet queue; skipping attached pictures\n");
|
||||
c->waiting_pics = 0;
|
||||
ret = flac_queue_flush(s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return flac_write_audio_packet(s, pkt);
|
||||
}
|
||||
} else
|
||||
return flac_write_audio_packet(s, pkt);
|
||||
} else {
|
||||
AVStream *st = s->streams[pkt->stream_index];
|
||||
|
||||
c->streaminfo = av_malloc(FLAC_STREAMINFO_SIZE);
|
||||
if (!c->streaminfo)
|
||||
return AVERROR(ENOMEM);
|
||||
memcpy(c->streaminfo, streaminfo, FLAC_STREAMINFO_SIZE);
|
||||
if (!c->waiting_pics ||
|
||||
!(st->disposition & AV_DISPOSITION_ATTACHED_PIC))
|
||||
return 0;
|
||||
|
||||
/* warn only once for each stream */
|
||||
if (st->nb_frames == 1) {
|
||||
av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
|
||||
" ignoring.\n", pkt->stream_index);
|
||||
}
|
||||
if (st->nb_frames >= 1)
|
||||
return 0;
|
||||
|
||||
st->priv_data = av_packet_clone(pkt);
|
||||
if (!st->priv_data)
|
||||
av_log(s, AV_LOG_ERROR, "Out of memory queueing an attached picture; skipping\n");
|
||||
c->waiting_pics--;
|
||||
|
||||
/* flush the buffered audio packets */
|
||||
if (!c->waiting_pics &&
|
||||
(ret = flac_queue_flush(s)) < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pkt->size)
|
||||
avio_write(s->pb, pkt->data, pkt->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -205,7 +420,8 @@ AVOutputFormat ff_flac_muxer = {
|
||||
.mime_type = "audio/x-flac",
|
||||
.extensions = "flac",
|
||||
.audio_codec = AV_CODEC_ID_FLAC,
|
||||
.video_codec = AV_CODEC_ID_NONE,
|
||||
.video_codec = AV_CODEC_ID_PNG,
|
||||
.init = flac_init,
|
||||
.write_header = flac_write_header,
|
||||
.write_packet = flac_write_packet,
|
||||
.write_trailer = flac_write_trailer,
|
||||
|
||||
@@ -576,7 +576,11 @@ static int http_accept(URLContext *s, URLContext **c)
|
||||
goto fail;
|
||||
cc->hd = cl;
|
||||
cc->is_multi_client = 1;
|
||||
return 0;
|
||||
fail:
|
||||
if (c) {
|
||||
ffurl_closep(c);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -295,7 +295,7 @@ static int libssh_read(URLContext *h, unsigned char *buf, int size)
|
||||
av_log(libssh, AV_LOG_ERROR, "Read error.\n");
|
||||
return AVERROR(EIO);
|
||||
}
|
||||
return bytes_read;
|
||||
return bytes_read ? bytes_read : AVERROR_EOF;
|
||||
}
|
||||
|
||||
static int libssh_write(URLContext *h, const unsigned char *buf, int size)
|
||||
|
||||
+18
-4
@@ -22,13 +22,19 @@
|
||||
#include "avformat.h"
|
||||
#include "rawdec.h"
|
||||
|
||||
#define VISUAL_OBJECT_START_CODE 0x000001b5
|
||||
#define VOP_START_CODE 0x000001b6
|
||||
#define VOS_STARTCODE 0x1B0
|
||||
#define USER_DATA_STARTCODE 0x1B2
|
||||
#define GOP_STARTCODE 0x1B3
|
||||
#define VISUAL_OBJ_STARTCODE 0x1B5
|
||||
#define VOP_STARTCODE 0x1B6
|
||||
#define SLICE_STARTCODE 0x1B7
|
||||
#define EXT_STARTCODE 0x1B8
|
||||
|
||||
static int mpeg4video_probe(AVProbeData *probe_packet)
|
||||
{
|
||||
uint32_t temp_buffer = -1;
|
||||
int VO = 0, VOL = 0, VOP = 0, VISO = 0, res = 0;
|
||||
int res_main = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < probe_packet->buf_size; i++) {
|
||||
@@ -38,19 +44,27 @@ static int mpeg4video_probe(AVProbeData *probe_packet)
|
||||
if (temp_buffer < 2)
|
||||
continue;
|
||||
|
||||
if (temp_buffer == VOP_START_CODE)
|
||||
if (temp_buffer == VOP_STARTCODE)
|
||||
VOP++;
|
||||
else if (temp_buffer == VISUAL_OBJECT_START_CODE)
|
||||
else if (temp_buffer == VISUAL_OBJ_STARTCODE)
|
||||
VISO++;
|
||||
else if (temp_buffer >= 0x100 && temp_buffer < 0x120)
|
||||
VO++;
|
||||
else if (temp_buffer >= 0x120 && temp_buffer < 0x130)
|
||||
VOL++;
|
||||
else if (temp_buffer == SLICE_STARTCODE || temp_buffer == EXT_STARTCODE)
|
||||
res_main++;
|
||||
else if (!(0x1AF < temp_buffer && temp_buffer < 0x1B7) &&
|
||||
!(0x1B9 < temp_buffer && temp_buffer < 0x1C4))
|
||||
res++;
|
||||
}
|
||||
|
||||
// res_main repesents the reserved codes within the "main" profile, they are
|
||||
// added to the reserved ones if it appears that this is a "main" profile
|
||||
// stream
|
||||
if (res_main && 2*res_main < VOP)
|
||||
res += res_main;
|
||||
|
||||
if (VOP >= VISO && VOP >= VOL && VO >= VOL && VOL > 0 && res == 0)
|
||||
return VOP+VO > 4 ? AVPROBE_SCORE_EXTENSION : AVPROBE_SCORE_EXTENSION/2;
|
||||
|
||||
|
||||
+26
-18
@@ -94,24 +94,26 @@ int ff_mms_asf_header_parser(MMSContext *mms)
|
||||
}
|
||||
}
|
||||
} else if (!memcmp(p, ff_asf_stream_header, sizeof(ff_asf_guid))) {
|
||||
flags = AV_RL16(p + sizeof(ff_asf_guid)*3 + 24);
|
||||
stream_id = flags & 0x7F;
|
||||
//The second condition is for checking CS_PKT_STREAM_ID_REQUEST packet size,
|
||||
//we can calculate the packet size by stream_num.
|
||||
//Please see function send_stream_selection_request().
|
||||
if (mms->stream_num < MMS_MAX_STREAMS &&
|
||||
46 + mms->stream_num * 6 < sizeof(mms->out_buffer)) {
|
||||
mms->streams = av_fast_realloc(mms->streams,
|
||||
&mms->nb_streams_allocated,
|
||||
(mms->stream_num + 1) * sizeof(MMSStream));
|
||||
if (!mms->streams)
|
||||
return AVERROR(ENOMEM);
|
||||
mms->streams[mms->stream_num].id = stream_id;
|
||||
mms->stream_num++;
|
||||
} else {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Corrupt stream (too many A/V streams)\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
if (end - p >= (sizeof(ff_asf_guid) * 3 + 26)) {
|
||||
flags = AV_RL16(p + sizeof(ff_asf_guid)*3 + 24);
|
||||
stream_id = flags & 0x7F;
|
||||
//The second condition is for checking CS_PKT_STREAM_ID_REQUEST packet size,
|
||||
//we can calculate the packet size by stream_num.
|
||||
//Please see function send_stream_selection_request().
|
||||
if (mms->stream_num < MMS_MAX_STREAMS &&
|
||||
46 + mms->stream_num * 6 < sizeof(mms->out_buffer)) {
|
||||
mms->streams = av_fast_realloc(mms->streams,
|
||||
&mms->nb_streams_allocated,
|
||||
(mms->stream_num + 1) * sizeof(MMSStream));
|
||||
if (!mms->streams)
|
||||
return AVERROR(ENOMEM);
|
||||
mms->streams[mms->stream_num].id = stream_id;
|
||||
mms->stream_num++;
|
||||
} else {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Corrupt stream (too many A/V streams)\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
}
|
||||
} else if (!memcmp(p, ff_asf_ext_stream_header, sizeof(ff_asf_guid))) {
|
||||
if (end - p >= 88) {
|
||||
@@ -143,6 +145,12 @@ int ff_mms_asf_header_parser(MMSContext *mms)
|
||||
}
|
||||
} else if (!memcmp(p, ff_asf_head1_guid, sizeof(ff_asf_guid))) {
|
||||
chunksize = 46; // see references [2] section 3.4. This should be set 46.
|
||||
if (chunksize > end - p) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Corrupt stream (header chunksize %"PRId64" is invalid)\n",
|
||||
chunksize);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
}
|
||||
p += chunksize;
|
||||
}
|
||||
|
||||
+30
-15
@@ -2641,14 +2641,22 @@ static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
|
||||
sc->stsc_count = i;
|
||||
for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
|
||||
int64_t first_min = i + 1;
|
||||
if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
|
||||
(i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
|
||||
sc->stsc_data[i].first < 1 ||
|
||||
sc->stsc_data[i].first < first_min ||
|
||||
sc->stsc_data[i].count < 1 ||
|
||||
sc->stsc_data[i].id < 1) {
|
||||
av_log(c->fc, AV_LOG_WARNING, "STSC entry %d is invalid (first=%d count=%d id=%d)\n", i, sc->stsc_data[i].first, sc->stsc_data[i].count, sc->stsc_data[i].id);
|
||||
if (i+1 >= sc->stsc_count || sc->stsc_data[i+1].first < 2)
|
||||
return AVERROR_INVALIDDATA;
|
||||
if (i+1 >= sc->stsc_count) {
|
||||
sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
|
||||
if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
|
||||
sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
|
||||
sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
|
||||
sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
|
||||
continue;
|
||||
}
|
||||
av_assert0(sc->stsc_data[i+1].first >= 2);
|
||||
// We replace this entry by the next valid
|
||||
sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
|
||||
sc->stsc_data[i].count = sc->stsc_data[i+1].count;
|
||||
@@ -3291,22 +3299,21 @@ static void mov_estimate_video_delay(MOVContext *c, AVStream* st) {
|
||||
int ctts_sample = 0;
|
||||
int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
|
||||
int buf_start = 0;
|
||||
int buf_size = 0;
|
||||
int j, r, num_swaps;
|
||||
|
||||
for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
|
||||
pts_buf[j] = INT64_MIN;
|
||||
|
||||
if (st->codecpar->video_delay <= 0 && msc->ctts_data &&
|
||||
st->codecpar->codec_id == AV_CODEC_ID_H264) {
|
||||
st->codecpar->video_delay = 0;
|
||||
for(ind = 0; ind < st->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) {
|
||||
if (buf_size == (MAX_REORDER_DELAY + 1)) {
|
||||
// If circular buffer is full, then move the first element forward.
|
||||
buf_start = (buf_start + 1) % buf_size;
|
||||
} else {
|
||||
++buf_size;
|
||||
}
|
||||
|
||||
// Point j to the last elem of the buffer and insert the current pts there.
|
||||
j = (buf_start + buf_size - 1) % buf_size;
|
||||
j = buf_start;
|
||||
buf_start = (buf_start + 1);
|
||||
if (buf_start == MAX_REORDER_DELAY + 1)
|
||||
buf_start = 0;
|
||||
|
||||
pts_buf[j] = st->index_entries[ind].timestamp + msc->ctts_data[ctts_ind].duration;
|
||||
|
||||
// The timestamps that are already in the sorted buffer, and are greater than the
|
||||
@@ -3317,10 +3324,13 @@ static void mov_estimate_video_delay(MOVContext *c, AVStream* st) {
|
||||
// go through, to keep this buffer in sorted order.
|
||||
num_swaps = 0;
|
||||
while (j != buf_start) {
|
||||
r = (j - 1 + buf_size) % buf_size;
|
||||
r = j - 1;
|
||||
if (r < 0) r = MAX_REORDER_DELAY;
|
||||
if (pts_buf[j] < pts_buf[r]) {
|
||||
FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
|
||||
++num_swaps;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
j = r;
|
||||
}
|
||||
@@ -3899,6 +3909,9 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
|
||||
} else {
|
||||
unsigned chunk_samples, total = 0;
|
||||
|
||||
if (!sc->chunk_count)
|
||||
return;
|
||||
|
||||
// compute total chunk count
|
||||
for (i = 0; i < sc->stsc_count; i++) {
|
||||
unsigned count, chunk_count;
|
||||
@@ -4144,7 +4157,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
st->index);
|
||||
return 0;
|
||||
}
|
||||
if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
|
||||
if (sc->chunk_count && sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
|
||||
av_log(c->fc, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
|
||||
st->index);
|
||||
return AVERROR_INVALIDDATA;
|
||||
@@ -7136,7 +7149,9 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
} else {
|
||||
int64_t next_dts = (sc->current_sample < st->nb_index_entries) ?
|
||||
st->index_entries[sc->current_sample].timestamp : st->duration;
|
||||
pkt->duration = next_dts - pkt->dts;
|
||||
|
||||
if (next_dts >= pkt->dts)
|
||||
pkt->duration = next_dts - pkt->dts;
|
||||
pkt->pts = pkt->dts;
|
||||
}
|
||||
if (st->discard == AVDISCARD_ALL)
|
||||
|
||||
+96
-9
@@ -140,9 +140,18 @@ static int co64_required(const MOVTrack *track)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_cover_image(const AVStream *st)
|
||||
{
|
||||
/* Eg. AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS
|
||||
* is encoded as sparse video track */
|
||||
return st && st->disposition == AV_DISPOSITION_ATTACHED_PIC;
|
||||
}
|
||||
|
||||
static int rtp_hinting_needed(const AVStream *st)
|
||||
{
|
||||
/* Add hint tracks for each audio and video stream */
|
||||
/* Add hint tracks for each real audio and video stream */
|
||||
if (is_cover_image(st))
|
||||
return 0;
|
||||
return st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
|
||||
st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO;
|
||||
}
|
||||
@@ -388,7 +397,7 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
|
||||
if (avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size) < 0) {
|
||||
/* drop the packets until we see a good one */
|
||||
if (!track->entry) {
|
||||
av_log(mov, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n");
|
||||
av_log(mov->fc, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n");
|
||||
ret = 0;
|
||||
} else
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
@@ -416,7 +425,7 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
|
||||
|
||||
if (hdr->substreamid == info->num_ind_sub + 1) {
|
||||
//info->num_ind_sub++;
|
||||
avpriv_request_sample(track->par, "Multiple independent substreams");
|
||||
avpriv_request_sample(mov->fc, "Multiple independent substreams");
|
||||
ret = AVERROR_PATCHWELCOME;
|
||||
goto end;
|
||||
} else if (hdr->substreamid < info->num_ind_sub ||
|
||||
@@ -424,6 +433,12 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
|
||||
info->ec3_done = 1;
|
||||
goto concatenate;
|
||||
}
|
||||
} else {
|
||||
if (hdr->substreamid != 0) {
|
||||
avpriv_request_sample(mov->fc, "Multiple non EAC3 independent substreams");
|
||||
ret = AVERROR_PATCHWELCOME;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* fill the info needed for the "dec3" atom */
|
||||
@@ -1003,7 +1018,7 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex
|
||||
uint32_t tag = track->tag;
|
||||
|
||||
if (track->mode == MODE_MOV) {
|
||||
if (track->timescale > UINT16_MAX) {
|
||||
if (track->timescale > UINT16_MAX || !track->par->channels) {
|
||||
if (mov_get_lpcm_flags(track->par->codec_id))
|
||||
tag = AV_RL32("lpcm");
|
||||
version = 2;
|
||||
@@ -1552,10 +1567,20 @@ static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
|
||||
return tag;
|
||||
}
|
||||
|
||||
static const AVCodecTag codec_cover_image_tags[] = {
|
||||
{ AV_CODEC_ID_MJPEG, 0xD },
|
||||
{ AV_CODEC_ID_PNG, 0xE },
|
||||
{ AV_CODEC_ID_BMP, 0x1B },
|
||||
{ AV_CODEC_ID_NONE, 0 },
|
||||
};
|
||||
|
||||
static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
|
||||
{
|
||||
int tag;
|
||||
|
||||
if (is_cover_image(track->st))
|
||||
return ff_codec_get_tag(codec_cover_image_tags, track->par->codec_id);
|
||||
|
||||
if (track->mode == MODE_MP4 || track->mode == MODE_PSP)
|
||||
tag = track->par->codec_tag;
|
||||
else if (track->mode == MODE_ISM)
|
||||
@@ -3420,6 +3445,33 @@ static int mov_write_int8_metadata(AVFormatContext *s, AVIOContext *pb,
|
||||
return size;
|
||||
}
|
||||
|
||||
static int mov_write_covr(AVIOContext *pb, AVFormatContext *s)
|
||||
{
|
||||
MOVMuxContext *mov = s->priv_data;
|
||||
int64_t pos = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
MOVTrack *trk = &mov->tracks[i];
|
||||
|
||||
if (!is_cover_image(trk->st) || trk->cover_image.size <= 0)
|
||||
continue;
|
||||
|
||||
if (!pos) {
|
||||
pos = avio_tell(pb);
|
||||
avio_wb32(pb, 0);
|
||||
ffio_wfourcc(pb, "covr");
|
||||
}
|
||||
avio_wb32(pb, 16 + trk->cover_image.size);
|
||||
ffio_wfourcc(pb, "data");
|
||||
avio_wb32(pb, trk->tag);
|
||||
avio_wb32(pb , 0);
|
||||
avio_write(pb, trk->cover_image.data, trk->cover_image.size);
|
||||
}
|
||||
|
||||
return pos ? update_size(pb, pos) : 0;
|
||||
}
|
||||
|
||||
/* iTunes meta data list */
|
||||
static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
|
||||
AVFormatContext *s)
|
||||
@@ -3454,6 +3506,7 @@ static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
|
||||
mov_write_int8_metadata (s, pb, "hdvd", "hd_video", 1);
|
||||
mov_write_int8_metadata (s, pb, "pgap", "gapless_playback",1);
|
||||
mov_write_int8_metadata (s, pb, "cpil", "compilation", 1);
|
||||
mov_write_covr(pb, s);
|
||||
mov_write_trkn_tag(pb, mov, s, 0); // track number
|
||||
mov_write_trkn_tag(pb, mov, s, 1); // disc number
|
||||
mov_write_tmpo_tag(pb, s);
|
||||
@@ -3944,7 +3997,7 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormat
|
||||
AVStream *st = track->st;
|
||||
AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
|
||||
|
||||
if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && !is_cover_image(st)) {
|
||||
type = "video";
|
||||
} else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
type = "audio";
|
||||
@@ -4564,6 +4617,8 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
|
||||
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
if (is_cover_image(st))
|
||||
continue;
|
||||
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
has_video = 1;
|
||||
if (st->codecpar->codec_id == AV_CODEC_ID_H264)
|
||||
@@ -4712,6 +4767,8 @@ static int mov_write_identification(AVIOContext *pb, AVFormatContext *s)
|
||||
int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0;
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
if (is_cover_image(st))
|
||||
continue;
|
||||
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
video_streams_nb++;
|
||||
else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||
@@ -4901,7 +4958,7 @@ static int mov_flush_fragment(AVFormatContext *s, int force)
|
||||
int buf_size, moov_size;
|
||||
|
||||
for (i = 0; i < mov->nb_streams; i++)
|
||||
if (!mov->tracks[i].entry)
|
||||
if (!mov->tracks[i].entry && !is_cover_image(mov->tracks[i].st))
|
||||
break;
|
||||
/* Don't write the initial moov unless all tracks have data */
|
||||
if (i < mov->nb_streams && !force)
|
||||
@@ -5158,6 +5215,11 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
else
|
||||
samples_in_chunk = 1;
|
||||
|
||||
if (samples_in_chunk < 1) {
|
||||
av_log(s, AV_LOG_ERROR, "fatal error, input packet contains no samples\n");
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
/* copy extradata if it exists */
|
||||
if (trk->vos_len == 0 && par->extradata_size > 0 &&
|
||||
!TAG_IS_AVCI(trk->tag) &&
|
||||
@@ -5480,13 +5542,32 @@ static int mov_write_subtitle_end_packet(AVFormatContext *s,
|
||||
|
||||
static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
{
|
||||
MOVMuxContext *mov = s->priv_data;
|
||||
MOVTrack *trk;
|
||||
|
||||
if (!pkt) {
|
||||
mov_flush_fragment(s, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
trk = &mov->tracks[pkt->stream_index];
|
||||
|
||||
if (is_cover_image(trk->st)) {
|
||||
int ret;
|
||||
|
||||
if (trk->st->nb_frames >= 1) {
|
||||
if (trk->st->nb_frames == 1)
|
||||
av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
|
||||
" ignoring.\n", pkt->stream_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ret = av_packet_ref(&trk->cover_image, pkt)) < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
int i;
|
||||
MOVMuxContext *mov = s->priv_data;
|
||||
MOVTrack *trk = &mov->tracks[pkt->stream_index];
|
||||
|
||||
if (!pkt->size)
|
||||
return mov_write_single_packet(s, pkt); /* Passthrough. */
|
||||
@@ -5733,7 +5814,8 @@ static void enable_tracks(AVFormatContext *s)
|
||||
AVStream *st = s->streams[i];
|
||||
|
||||
if (st->codecpar->codec_type <= AVMEDIA_TYPE_UNKNOWN ||
|
||||
st->codecpar->codec_type >= AVMEDIA_TYPE_NB)
|
||||
st->codecpar->codec_type >= AVMEDIA_TYPE_NB ||
|
||||
is_cover_image(st))
|
||||
continue;
|
||||
|
||||
if (first[st->codecpar->codec_type] < 0)
|
||||
@@ -5776,6 +5858,7 @@ static void mov_free(AVFormatContext *s)
|
||||
av_freep(&mov->tracks[i].par);
|
||||
av_freep(&mov->tracks[i].cluster);
|
||||
av_freep(&mov->tracks[i].frag_info);
|
||||
av_packet_unref(&mov->tracks[i].cover_image);
|
||||
|
||||
if (mov->tracks[i].vos_len)
|
||||
av_freep(&mov->tracks[i].vos_data);
|
||||
@@ -6081,6 +6164,10 @@ static int mov_init(AVFormatContext *s)
|
||||
av_log(s, AV_LOG_ERROR, "VP9 only supported in MP4.\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
} else if (track->par->codec_id == AV_CODEC_ID_AV1) {
|
||||
/* spec is not finished, so forbid for now */
|
||||
av_log(s, AV_LOG_ERROR, "AV1 muxing is currently not supported.\n");
|
||||
return AVERROR_PATCHWELCOME;
|
||||
} else if (track->par->codec_id == AV_CODEC_ID_VP8) {
|
||||
/* altref frames handling is not defined in the spec as of version v1.0,
|
||||
* so just forbid muxing VP8 streams altogether until a new version does */
|
||||
|
||||
@@ -132,6 +132,7 @@ typedef struct MOVTrack {
|
||||
uint32_t default_size;
|
||||
|
||||
HintSampleQueue sample_queue;
|
||||
AVPacket cover_image;
|
||||
|
||||
AVIOContext *mdat_buf;
|
||||
int64_t data_offset;
|
||||
|
||||
+51
-38
@@ -170,8 +170,8 @@ static const AVOption options[] = {
|
||||
{.i64 = 1}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
|
||||
{"ts_packetsize", "output option carrying the raw packet size", offsetof(MpegTSContext, raw_packet_size), AV_OPT_TYPE_INT,
|
||||
{.i64 = 0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
|
||||
{"scan_all_pmts", "scan and combine all PMTs", offsetof(MpegTSContext, scan_all_pmts), AV_OPT_TYPE_BOOL,
|
||||
{ .i64 = -1}, -1, 1, AV_OPT_FLAG_DECODING_PARAM },
|
||||
{"scan_all_pmts", "scan and combine all PMTs", offsetof(MpegTSContext, scan_all_pmts), AV_OPT_TYPE_BOOL,
|
||||
{.i64 = -1}, -1, 1, AV_OPT_FLAG_DECODING_PARAM },
|
||||
{"skip_changes", "skip changing / adding streams / programs", offsetof(MpegTSContext, skip_changes), AV_OPT_TYPE_BOOL,
|
||||
{.i64 = 0}, 0, 1, 0 },
|
||||
{"skip_clear", "skip clearing programs", offsetof(MpegTSContext, skip_clear), AV_OPT_TYPE_BOOL,
|
||||
@@ -391,7 +391,8 @@ static void write_section_data(MpegTSContext *ts, MpegTSFilter *tss1,
|
||||
const uint8_t *buf, int buf_size, int is_start)
|
||||
{
|
||||
MpegTSSectionFilter *tss = &tss1->u.section_filter;
|
||||
int len;
|
||||
uint8_t *cur_section_buf = NULL;
|
||||
int len, offset;
|
||||
|
||||
if (is_start) {
|
||||
memcpy(tss->section_buf, buf, buf_size);
|
||||
@@ -401,42 +402,54 @@ static void write_section_data(MpegTSContext *ts, MpegTSFilter *tss1,
|
||||
} else {
|
||||
if (tss->end_of_section_reached)
|
||||
return;
|
||||
len = 4096 - tss->section_index;
|
||||
len = MAX_SECTION_SIZE - tss->section_index;
|
||||
if (buf_size < len)
|
||||
len = buf_size;
|
||||
memcpy(tss->section_buf + tss->section_index, buf, len);
|
||||
tss->section_index += len;
|
||||
}
|
||||
|
||||
/* compute section length if possible */
|
||||
if (tss->section_h_size == -1 && tss->section_index >= 3) {
|
||||
len = (AV_RB16(tss->section_buf + 1) & 0xfff) + 3;
|
||||
if (len > 4096)
|
||||
return;
|
||||
tss->section_h_size = len;
|
||||
}
|
||||
|
||||
if (tss->section_h_size != -1 &&
|
||||
tss->section_index >= tss->section_h_size) {
|
||||
int crc_valid = 1;
|
||||
tss->end_of_section_reached = 1;
|
||||
|
||||
if (tss->check_crc) {
|
||||
crc_valid = !av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, tss->section_buf, tss->section_h_size);
|
||||
if (tss->section_h_size >= 4)
|
||||
tss->crc = AV_RB32(tss->section_buf + tss->section_h_size - 4);
|
||||
|
||||
if (crc_valid) {
|
||||
ts->crc_validity[ tss1->pid ] = 100;
|
||||
}else if (ts->crc_validity[ tss1->pid ] > -10) {
|
||||
ts->crc_validity[ tss1->pid ]--;
|
||||
}else
|
||||
crc_valid = 2;
|
||||
offset = 0;
|
||||
cur_section_buf = tss->section_buf;
|
||||
while (cur_section_buf - tss->section_buf < MAX_SECTION_SIZE && cur_section_buf[0] != 0xff) {
|
||||
/* compute section length if possible */
|
||||
if (tss->section_h_size == -1 && tss->section_index - offset >= 3) {
|
||||
len = (AV_RB16(cur_section_buf + 1) & 0xfff) + 3;
|
||||
if (len > MAX_SECTION_SIZE)
|
||||
return;
|
||||
tss->section_h_size = len;
|
||||
}
|
||||
if (crc_valid) {
|
||||
tss->section_cb(tss1, tss->section_buf, tss->section_h_size);
|
||||
if (crc_valid != 1)
|
||||
tss->last_ver = -1;
|
||||
|
||||
if (tss->section_h_size != -1 &&
|
||||
tss->section_index >= offset + tss->section_h_size) {
|
||||
int crc_valid = 1;
|
||||
tss->end_of_section_reached = 1;
|
||||
|
||||
if (tss->check_crc) {
|
||||
crc_valid = !av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, cur_section_buf, tss->section_h_size);
|
||||
if (tss->section_h_size >= 4)
|
||||
tss->crc = AV_RB32(cur_section_buf + tss->section_h_size - 4);
|
||||
|
||||
if (crc_valid) {
|
||||
ts->crc_validity[ tss1->pid ] = 100;
|
||||
}else if (ts->crc_validity[ tss1->pid ] > -10) {
|
||||
ts->crc_validity[ tss1->pid ]--;
|
||||
}else
|
||||
crc_valid = 2;
|
||||
}
|
||||
if (crc_valid) {
|
||||
tss->section_cb(tss1, cur_section_buf, tss->section_h_size);
|
||||
if (crc_valid != 1)
|
||||
tss->last_ver = -1;
|
||||
}
|
||||
|
||||
cur_section_buf += tss->section_h_size;
|
||||
offset += tss->section_h_size;
|
||||
tss->section_h_size = -1;
|
||||
} else {
|
||||
tss->section_h_size = -1;
|
||||
tss->end_of_section_reached = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -478,7 +491,7 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts,
|
||||
sec = &filter->u.section_filter;
|
||||
sec->section_cb = section_cb;
|
||||
sec->opaque = opaque;
|
||||
sec->section_buf = av_malloc(MAX_SECTION_SIZE);
|
||||
sec->section_buf = av_mallocz(MAX_SECTION_SIZE);
|
||||
sec->check_crc = check_crc;
|
||||
sec->last_ver = -1;
|
||||
|
||||
@@ -1733,10 +1746,10 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
|
||||
}
|
||||
}
|
||||
|
||||
if (st->codecpar->extradata_size < language_count * 2)
|
||||
return AVERROR_INVALIDDATA;
|
||||
if (st->codecpar->extradata_size < language_count * 2)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
extradata = st->codecpar->extradata;
|
||||
extradata = st->codecpar->extradata;
|
||||
|
||||
for (i = 0; i < language_count; i++) {
|
||||
language[i * 4 + 0] = get8(pp, desc_end);
|
||||
@@ -1970,14 +1983,14 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
|
||||
p = section;
|
||||
if (parse_section_header(h, &p, p_end) < 0)
|
||||
return;
|
||||
if (h->tid != PMT_TID)
|
||||
return;
|
||||
if (skip_identical(h, tssf))
|
||||
return;
|
||||
|
||||
av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x sec_num=%d/%d version=%d tid=%d\n",
|
||||
h->id, h->sec_num, h->last_sec_num, h->version, h->tid);
|
||||
|
||||
if (h->tid != PMT_TID)
|
||||
return;
|
||||
if (!ts->scan_all_pmts && ts->skip_changes)
|
||||
return;
|
||||
|
||||
|
||||
@@ -2085,7 +2085,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
|
||||
MXFEssenceContainerData *essence_data;
|
||||
|
||||
if (!(essence_data = mxf_resolve_strong_ref(mxf, &mxf->essence_container_data_refs[k], EssenceContainerData))) {
|
||||
av_log(mxf, AV_LOG_TRACE, "could not resolve essence container data strong ref\n");
|
||||
av_log(mxf->fc, AV_LOG_TRACE, "could not resolve essence container data strong ref\n");
|
||||
continue;
|
||||
}
|
||||
if (!memcmp(component->source_package_ul, essence_data->package_ul, sizeof(UID)) && !memcmp(component->source_package_uid, essence_data->package_uid, sizeof(UID))) {
|
||||
|
||||
@@ -134,6 +134,10 @@ recover:
|
||||
pes_flags = avio_rb16(pb);
|
||||
pes_header_data_length = avio_r8(pb);
|
||||
|
||||
if (avio_feof(pb)) {
|
||||
return AVERROR_EOF;
|
||||
}
|
||||
|
||||
if (pes_signal != 1 || pes_header_data_length == 0) {
|
||||
pva_log(s, AV_LOG_WARNING, "expected non empty signaled PES packet, "
|
||||
"trying to recover\n");
|
||||
|
||||
@@ -49,7 +49,7 @@ int ff_get_qtpalette(int codec_id, AVIOContext *pb, uint32_t *palette)
|
||||
/* If the depth is 1, 2, 4, or 8 bpp, file is palettized. */
|
||||
if ((bit_depth == 1 || bit_depth == 2 || bit_depth == 4 || bit_depth == 8)) {
|
||||
uint32_t color_count, color_start, color_end;
|
||||
uint32_t a, r, g, b;
|
||||
uint32_t r, g, b;
|
||||
|
||||
/* Ignore the greyscale bit for 1-bit video and sample
|
||||
* descriptions containing a color table. */
|
||||
@@ -94,17 +94,17 @@ int ff_get_qtpalette(int codec_id, AVIOContext *pb, uint32_t *palette)
|
||||
color_end = avio_rb16(pb);
|
||||
if ((color_start <= 255) && (color_end <= 255)) {
|
||||
for (i = color_start; i <= color_end; i++) {
|
||||
/* each A, R, G, or B component is 16 bits;
|
||||
* only use the top 8 bits */
|
||||
a = avio_r8(pb);
|
||||
avio_r8(pb);
|
||||
/* Each color is made of four unsigned 16 bit integers. The
|
||||
* first integer is 0, the remaining integers are the red,
|
||||
* the green and the blue values. We only use the top 8 bit. */
|
||||
avio_skip(pb, 2);
|
||||
r = avio_r8(pb);
|
||||
avio_r8(pb);
|
||||
g = avio_r8(pb);
|
||||
avio_r8(pb);
|
||||
b = avio_r8(pb);
|
||||
avio_r8(pb);
|
||||
palette[i] = (a << 24 ) | (r << 16) | (g << 8) | (b);
|
||||
palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user