Opened 6 years ago
Last modified 6 years ago
#8644 new enhancement
Demux multi-image TIFF beyond first image
| Reported by: | adaerr | Owned by: | |
|---|---|---|---|
| Priority: | wish | Component: | undetermined |
| Version: | git-master | Keywords: | tif |
| Cc: | Blocked By: | ||
| Blocking: | Reproduced by developer: | no | |
| Analyzed by developer: | no |
Description
I would like to create a video from a TIFF file containing a sequence
of images of the same size. However currently ffmpeg decodes only the first image from the TIFF input.
TIFF files containing multiple images are indeed possible, and used as
native format by software ranging from scan software to scientific
image processing software like ImageJ. It would be convenient if
ffmpeg could decode/demux/process the sequence of images as a video input
just as it can for a collection of image files. In other words, I
would expect
ffmpeg -i all-frames.tif video-from-tif.webm
to produce the same video as that obtained by splitting the TIFF into
separate files and running
ffmpeg -i single-frame-%03d.png video-from-png.webm
The observed behaviour (see full output below) is that ffmpeg only
reads a single image from TIFF input, so that video-from-tif.webm
contains only one frame, where video-from-png.webm contains the same
number of frames as there are PNG files in the input.
To reproduce, I attach[*] a sample TIFF with 20 frames:
20-frame-stack_416x160_grayscale-8bpp.tif
[*] Sorry, I failed to connect and upload the sample to the ftp server as specified in the instructions at http://www.ffmpeg.org/bugreports.html
A test stack can also easily be generated by the convert tool from the
ImageMagick software. The following command line for example produces
a TIFF containing 30 256x256 grayscale (8bpp) images showing a
gradient in varying orientation.
convert -size 256x256 gradient: -duplicate 29 -distort SRT '%[fx:360*t/n]' -depth 8 30-frame-stack_256x256_grayscale-8pp.tif
Here is the full log produced by a recent build from git sources:
Log level: 48
Command line:
/home/adrian/.local/bin/ffmpeg -report -i 20-frame-stack_416x160_grayscale-8bpp.tif -y out.webm
ffmpeg version N-97504-g1128aa8753 Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 9 (Debian 9.3.0-10)
configuration: --prefix=/home/adrian/.local --enable-gpl --enable-version3 --enable-nonfree --enable-shared --enable-pthreads --enable-libfreetype --enable-fontconfig --enable-libass --enable-gnutls --enable-librtmp --enable-libxcb --enable-libmp3lame --enable-libvorbis --enable-libspeex --enable-libopus --enable-libgsm --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvo-amrwbenc --enable-libx264 --enable-libxvid --enable-libtheora --enable-libvpx --enable-libopenjpeg --enable-frei0r --enable-libmodplug --enable-libzmq --enable-ladspa --enable-libssh --enable-libzvbi --enable-libgme --enable-libwavpack --enable-libwebp --enable-libx265 --enable-opengl --enable-librubberband --enable-libxml2
libavutil 56. 43.100 / 56. 43.100
libavcodec 58. 82.100 / 58. 82.100
libavformat 58. 42.101 / 58. 42.101
libavdevice 58. 9.103 / 58. 9.103
libavfilter 7. 79.100 / 7. 79.100
libswscale 5. 6.101 / 5. 6.101
libswresample 3. 6.100 / 3. 6.100
libpostproc 55. 6.100 / 55. 6.100
Splitting the commandline.
Reading option '-report' ... matched as option 'report' (generate a report) with argument '1'.
Reading option '-i' ... matched as input url with argument '20-frame-stack_416x160_grayscale-8bpp.tif'.
Reading option '-y' ... matched as option 'y' (overwrite output files) with argument '1'.
Reading option 'out.webm' ... matched as output url.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option report (generate a report) with argument 1.
Applying option y (overwrite output files) with argument 1.
Successfully parsed a group of options.
Parsing a group of options: input url 20-frame-stack_416x160_grayscale-8bpp.tif.
Successfully parsed a group of options.
Opening an input file: 20-frame-stack_416x160_grayscale-8bpp.tif.
[NULL @ 0x562105205440] Opening '20-frame-stack_416x160_grayscale-8bpp.tif' for reading
[file @ 0x562105205f00] Setting default whitelist 'file,crypto,data'
[tiff_pipe @ 0x562105205440] Format tiff_pipe probed with size=2048 and score=51
[tiff_pipe @ 0x562105205440] Before avformat_find_stream_info() pos: 0 bytes read:32768 seeks:0 nb_streams:1
[tiff_pipe @ 0x562105205440] parser not found for codec tiff, packets or times may be invalid.
[tiff_pipe @ 0x562105205440] parser not found for codec tiff, packets or times may be invalid.
[tiff_pipe @ 0x562105205440] After avformat_find_stream_info() pos: 1334978 bytes read:1334978 seeks:0 frames:1
Input #0, tiff_pipe, from '20-frame-stack_416x160_grayscale-8bpp.tif':
Duration: N/A, bitrate: N/A
Stream #0:0, 1, 1/25: Video: tiff, gray, 416x160 [SAR 1:1 DAR 13:5], 25 tbr, 25 tbn, 25 tbc
Successfully opened the file.
Parsing a group of options: output url out.webm.
Successfully parsed a group of options.
Opening an output file: out.webm.
[file @ 0x562105218540] Setting default whitelist 'file,crypto,data'
Successfully opened the file.
detected 4 logical cores
Stream mapping:
Stream #0:0 -> #0:0 (tiff (native) -> vp9 (libvpx-vp9))
Press [q] to stop, [?] for help
cur_dts is invalid st:0 (0) [init:0 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
cur_dts is invalid st:0 (0) [init:0 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
[graph 0 input from stream 0:0 @ 0x562105355900] Setting 'video_size' to value '416x160'
[graph 0 input from stream 0:0 @ 0x562105355900] Setting 'pix_fmt' to value '8'
[graph 0 input from stream 0:0 @ 0x562105355900] Setting 'time_base' to value '1/25'
[graph 0 input from stream 0:0 @ 0x562105355900] Setting 'pixel_aspect' to value '1/1'
[graph 0 input from stream 0:0 @ 0x562105355900] Setting 'frame_rate' to value '25/1'
[graph 0 input from stream 0:0 @ 0x562105355900] w:416 h:160 pixfmt:gray tb:1/25 fr:25/1 sar:1/1
[format @ 0x562105355d00] Setting 'pix_fmts' to value 'yuv420p|yuva420p|yuv422p|yuv440p|yuv444p|gbrp'
[auto_scaler_0 @ 0x56210535de00] Setting 'flags' to value 'bicubic'
[auto_scaler_0 @ 0x56210535de00] w:iw h:ih flags:'bicubic' interl:0
[format @ 0x562105355d00] auto-inserting filter 'auto_scaler_0' between the filter 'Parsed_null_0' and the filter 'format'
[AVFilterGraph @ 0x56210532d440] query_formats: 4 queried, 2 merged, 1 already done, 0 delayed
[auto_scaler_0 @ 0x56210535de00] picking gbrp out of 6 ref:gray alpha:0
[swscaler @ 0x56210535f300] Forcing full internal H chroma due to input having non subsampled chroma
[auto_scaler_0 @ 0x56210535de00] w:416 h:160 fmt:gray sar:1/1 -> w:416 h:160 fmt:gbrp sar:1/1 flags:0x4
[libvpx-vp9 @ 0x56210521ac40] v1.8.2
[libvpx-vp9 @ 0x56210521ac40] --prefix=/usr --enable-pic --enable-shared --disable-install-bins --disable-install-srcs --size-limit=16384x16384 --enable-postproc --enable-multi-res-encoding --enable-temporal-denoising --enable-vp9-temporal-denoising --enable-vp9-postproc --target=x86_64-linux-gcc
[libvpx-vp9 @ 0x56210521ac40] vpx_codec_enc_cfg
[libvpx-vp9 @ 0x56210521ac40] generic settings
g_usage: 0
g_threads: 8
g_profile: 1
g_w: 320
g_h: 240
g_bit_depth: 8
g_input_bit_depth: 8
g_timebase: {1/30}
g_error_resilient: 0
g_pass: 0
g_lag_in_frames: 25
[libvpx-vp9 @ 0x56210521ac40] rate control settings
rc_dropframe_thresh: 0
rc_resize_allowed: 0
rc_resize_up_thresh: 60
rc_resize_down_thresh: 30
rc_end_usage: 0
rc_twopass_stats_in: (nil)(0)
rc_target_bitrate: 256
[libvpx-vp9 @ 0x56210521ac40] quantizer settings
rc_min_quantizer: 0
rc_max_quantizer: 63
[libvpx-vp9 @ 0x56210521ac40] bitrate tolerance
rc_undershoot_pct: 25
rc_overshoot_pct: 25
[libvpx-vp9 @ 0x56210521ac40] temporal layering settings
ts_number_layers: 1
[libvpx-vp9 @ 0x56210521ac40]
layer_target_bitrate: 0 0 0 0 0
[libvpx-vp9 @ 0x56210521ac40]
ts_rate_decimator: 0 0 0 0 0
[libvpx-vp9 @ 0x56210521ac40]
ts_periodicity: 0
[libvpx-vp9 @ 0x56210521ac40]
ts_layer_id: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[libvpx-vp9 @ 0x56210521ac40] decoder buffer model
rc_buf_sz: 6000
rc_buf_initial_sz: 4000
rc_buf_optimal_sz: 5000
[libvpx-vp9 @ 0x56210521ac40] 2 pass rate control settings
rc_2pass_vbr_bias_pct: 50
rc_2pass_vbr_minsection_pct: 0
rc_2pass_vbr_maxsection_pct: 2000
[libvpx-vp9 @ 0x56210521ac40] rc_2pass_vbr_corpus_complexity:0
[libvpx-vp9 @ 0x56210521ac40] keyframing settings
kf_mode: 1
kf_min_dist: 0
kf_max_dist: 128
[libvpx-vp9 @ 0x56210521ac40]
[libvpx-vp9 @ 0x56210521ac40] Neither bitrate nor constrained quality specified, using default CRF of 32
[libvpx-vp9 @ 0x56210521ac40] vpx_codec_enc_cfg
[libvpx-vp9 @ 0x56210521ac40] generic settings
g_usage: 0
g_threads: 4
g_profile: 1
g_w: 416
g_h: 160
g_bit_depth: 8
g_input_bit_depth: 8
g_timebase: {1/25}
g_error_resilient: 0
g_pass: 0
g_lag_in_frames: 25
[libvpx-vp9 @ 0x56210521ac40] rate control settings
rc_dropframe_thresh: 0
rc_resize_allowed: 0
rc_resize_up_thresh: 60
rc_resize_down_thresh: 30
rc_end_usage: 3
rc_twopass_stats_in: (nil)(0)
rc_target_bitrate: 256
[libvpx-vp9 @ 0x56210521ac40] quantizer settings
rc_min_quantizer: 0
rc_max_quantizer: 63
[libvpx-vp9 @ 0x56210521ac40] bitrate tolerance
rc_undershoot_pct: 25
rc_overshoot_pct: 25
[libvpx-vp9 @ 0x56210521ac40] temporal layering settings
ts_number_layers: 1
[libvpx-vp9 @ 0x56210521ac40]
layer_target_bitrate: 0 0 0 0 0
[libvpx-vp9 @ 0x56210521ac40]
ts_rate_decimator: 0 0 0 0 0
[libvpx-vp9 @ 0x56210521ac40]
ts_periodicity: 0
[libvpx-vp9 @ 0x56210521ac40]
ts_layer_id: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[libvpx-vp9 @ 0x56210521ac40] decoder buffer model
rc_buf_sz: 6000
rc_buf_initial_sz: 4000
rc_buf_optimal_sz: 5000
[libvpx-vp9 @ 0x56210521ac40] 2 pass rate control settings
rc_2pass_vbr_bias_pct: 50
rc_2pass_vbr_minsection_pct: 0
rc_2pass_vbr_maxsection_pct: 2000
[libvpx-vp9 @ 0x56210521ac40] rc_2pass_vbr_corpus_complexity:0
[libvpx-vp9 @ 0x56210521ac40] keyframing settings
kf_mode: 1
kf_min_dist: 0
kf_max_dist: 128
[libvpx-vp9 @ 0x56210521ac40]
[libvpx-vp9 @ 0x56210521ac40] vpx_codec_control
[libvpx-vp9 @ 0x56210521ac40] VP8E_SET_CPUUSED: 1
[libvpx-vp9 @ 0x56210521ac40] VP8E_SET_ARNR_MAXFRAMES: 0
[libvpx-vp9 @ 0x56210521ac40] VP8E_SET_ARNR_STRENGTH: 3
[libvpx-vp9 @ 0x56210521ac40] VP8E_SET_ARNR_TYPE: 3
[libvpx-vp9 @ 0x56210521ac40] VP8E_SET_STATIC_THRESHOLD: 0
[libvpx-vp9 @ 0x56210521ac40] VP8E_SET_CQ_LEVEL: 32
[libvpx-vp9 @ 0x56210521ac40] VP9E_SET_COLOR_SPACE: 7
[libvpx-vp9 @ 0x56210521ac40] VP9E_SET_COLOR_RANGE: 0
[libvpx-vp9 @ 0x56210521ac40] VP9E_SET_TARGET_LEVEL: 255
[libvpx-vp9 @ 0x56210521ac40] Using deadline: 1000000
[webm @ 0x562105216480] get_metadata_duration returned: 0
Output #0, webm, to 'out.webm':
Metadata:
encoder : Lavf58.42.101
Stream #0:0, 0, 1/1000: Video: vp9 (libvpx-vp9), gbrp, 416x160 [SAR 1:1 DAR 13:5], q=-1--1, 25 fps, 1k tbn, 25 tbc
Metadata:
encoder : Lavc58.82.100 libvpx-vp9
Side data:
cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A
Clipping frame in rate conversion by 0.000008
cur_dts is invalid st:0 (0) [init:1 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
cur_dts is invalid st:0 (0) [init:1 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
[out_0_0 @ 0x56210535bb00] EOF on sink link out_0_0:default.
No more output streams to write to, finishing.
Automatically inserted bitstream filter 'vp9_superframe'; args=''
[webm @ 0x562105216480] Starting new cluster with timestamp 0 at offset 478 bytes
[webm @ 0x562105216480] Writing block of size 8070 with pts 0, dts 0, duration 40 at relative offset 3 in cluster at offset 478. TrackNumber 1, keyframe 1
[webm @ 0x562105216480] end duration = 40
[webm @ 0x562105216480] stream 0 end duration = 40
frame= 1 fps=0.0 q=0.0 Lsize= 8kB time=00:00:00.00 bitrate=68688.0kbits/s speed=0.0109x
video:8kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 6.394052%
Input file #0 (20-frame-stack_416x160_grayscale-8bpp.tif):
Input stream #0:0 (video): 1 packets read (1334978 bytes); 1 frames decoded;
Total: 1 packets (1334978 bytes) demuxed
Output file #0 (out.webm):
Output stream #0:0 (video): 1 frames encoded; 1 packets muxed (8070 bytes);
Total: 1 packets (8070 bytes) muxed
1 frames successfully decoded, 0 decoding errors
[AVIOContext @ 0x56210521b380] Statistics: 0 seeks, 1 writeouts
[AVIOContext @ 0x56210520e2c0] Statistics: 1334978 bytes read, 0 seeks
Attachments (2)
Change History (6)
by , 6 years ago
| Attachment: | 20-frame-stack_416x160_grayscale-8bpp.tif added |
|---|
by , 6 years ago
| Attachment: | 20-frame-stack_416x160_grayscale-8bpp_README.md added |
|---|
Description for the attached TIFF file
comment:1 by , 6 years ago
| Keywords: | tif added; tiff removed |
|---|---|
| Priority: | normal → wish |
comment:2 by , 6 years ago
A workaround is to pipe ImageMagick to FFmpeg
eg. 10fps FFV1, MKV container
"convert" "20-frame-stack_416x160_grayscale-8bpp.tif" gray:- | ffmpeg -f rawvideo -s 416x160 -pix_fmt gray -r 10 -i - -c:v ffv1 -an im_pipe_to_ffmpeg_ffv1.mkv
comment:3 by , 6 years ago
Thanks for the comment. Although using ImageMagick to pipe the images into ffmpeg is indeed a workaround I should have mentioned, it works only for not too large files. The variant I use is
convert foo.tif ppm:- | ffmpeg -f image2pipe -framerate 15 -i - [...]
ImageMagick was not designed for processing long image sequences - though it has some animation support for gif etc - so this is slow and fails for large files: convert loads images into memory (can be extended by use of tmp dir and tuning magick's configuration to some extent) before outputting data, so memory usage increases with file size. Note that the limit file size is a fraction of the available cache size: the internal representation of images may have 16bit depth per channel, so 8bit gray is stored as 64bpp RGBA in memory/cache.
comment:4 by , 6 years ago
And while we're mentionning workarounds: for large files that I cannot process via ImageMagick, my workaround consists in opening the TIFF in ImageJ and saving it as uncompressed AVI, that works like a charm with ffmpeg.
Still it would be more convenient if ffmpeg, which already has a TIFF decoder, could properly demux multiple images from a TIFF file. Whence this ticket.



TIFF file containing a sequence of (416x160 8bpp grayscale) images.