mux: asf: unplayable by gstreamer due to malformed header
Describe your issue
ASF Files generated by VLC Player can not be demuxed by gstreamer's asfdemux
and hence be neither "discovered" nor played.
This is due to a wrong (off by +1) value of num_objects
(offset 0+24
) in the ASF header.
While the ASF spec of MS states that the header extension
counts as 1 regardless of objects it contains VLC increases the value for the metadata object
within.
Number of Header Objects
Specifies the number of objects contained within the Header Object, not including this one. In addition, the Header Extension Object (sections 3.4 and 4) is counted as exactly one object regardless of the number of subobjects contained within it.
In modules/mux/asf.c:928
asf_header_create
bo_addle_u32( &bo, 2 + vlc_array_count( &p_sys->tracks ) + 1 +
(i_cd_size ? 1 : 0) + (i_cm_size ? 1 : 0) );
So when gstreamer:asfdemux tries to analyze the last header part all bytes of the header are already consumed and it fails though everything else went well. FFmpeg still manages to play the file and gstreamer also when the correct value is written into the header.
Expected Behavior
Programs conforming to ASF spec should be able to play VLC generated ASF files
Observed Behavior
gst-discoverer-1.0 fails when demuxing
0:00:00.017035178 1689839 0x77fc18000d40 INFO asfdemux gstasfdemux.c:3715:gst_asf_demux_process_header:<asfdemux0> reading header part 4
0:00:00.017039992 1689839 0x77fc18000d40 WARN asfdemux gstasfdemux.c:3718:gst_asf_demux_process_header: process_object returned need-more-data
0:00:00.017046491 1689839 0x77fc18000d40 WARN asfdemux gstasfdemux.c:1253:gst_asf_demux_pull_headers:<asfdemux0> process_object: unknown
0:00:00.017051788 1689839 0x77fc18000d40 DEBUG asfdemux gstasfdemux.c:2203:gst_asf_demux_loop:<asfdemux0> pausing task, flow return: error
0:00:00.017061013 1689839 0x77fc18000d40 WARN asfdemux gstasfdemux.c:2214:gst_asf_demux_loop:<asfdemux0> error: Internal data stream error.
Setup
- Operating System:
Linux phoebe 6.9.8-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 05 Jul 2024 22:11:24 +0000 x86_64 GNU/Linux
- Device: Computer
- GStreamer Version:
GStreamer 1.24.5
- VLC Version:
VLC media player 3.0.21 Vetinari (revision 3.0.21-0-gdd8bfdbabe8)
VLC version 3.0.21 Vetinari (3.0.21-0-gdd8bfdbabe8)
Compiled by builduser on (Jun 16 2024 20:52:10)
- FFmpeg Version:
ffmpeg version n7.0.1 Copyright (c) 2000-2024 the FFmpeg developers
built with gcc 14.1.1 (GCC) 20240522
configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-amf --enable-avisynth --enable-cuda-llvm --enable-lto --enable-fontconfig --enable-frei0r --enable-gmp --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libdav1d --enable-libdrm --enable-libdvdnav --enable-libdvdread --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libharfbuzz --enable-libiec61883 --enable-libjack --enable-libjxl --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libplacebo --enable-libpulse --enable-librav1e --enable-librsvg --enable-librubberband --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpl --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-libzimg --enable-mbedtls --enable-nvdec --enable-nvenc --enable-opencl --enable-opengl --enable-shared --enable-vapoursynth --enable-version3 --enable-vulkan
libavutil 59. 8.100 / 59. 8.100
libavcodec 61. 3.100 / 61. 3.100
libavformat 61. 1.100 / 61. 1.100
libavdevice 61. 1.100 / 61. 1.100
libavfilter 10. 1.100 / 10. 1.100
libswscale 8. 1.100 / 8. 1.100
libswresample 5. 1.100 / 5. 1.100
libpostproc 58. 1.100 / 58. 1.100
- Command line:
GST_DEBUG=asfdemux:5 gst-discoverer-1.0 tmp.asf
Steps to reproduce the bug
The following script was used to reproduce and analyze the issue.
#!/bin/bash -x
SOURCE_VIDEO=tmp.avi
ASF_VIDEO=tmp.asf
# create small test video
ffmpeg \
-y \
-v error \
-f rawvideo \
-video_size 1280x720 \
-pixel_format yuv420p \
-i /dev/urandom \
-codec:v mpeg4 \
-t 5 \
${SOURCE_VIDEO} \
;
# convert with vlc
vlc \
-I dummy \
-v \
${SOURCE_VIDEO} \
"--sout=#transcode{vcodec=wmv2}:standard{access=file,mux=asf,dst=${ASF_VIDEO}}" \
vlc://quit \
;
# see the world explode
GST_DEBUG="asfdemux:5" gst-discoverer-1.0 ${ASF_VIDEO}
# repair
echo -ne "\x04" | dd of=${ASF_VIDEO} bs=1 count=1 seek=24 conv=notrunc
# all is fine
gst-discoverer-1.0 ${ASF_VIDEO}
How reproducible is the bug?
Always
Solutions you have tried
-
Correcting the num_objects
byte manually
echo -ne '\x04' | dd of=${ASF_VIDEO} bs=1 count=1 seek=24 conv=notrunc
-
Patching asfdemux to return GST_FLOW_OK
if size = 0 before processing next header
Additional Information
There is already a MR and issue over at the freedesktop/gstreamer gitlab that handles malformed headers more gracefully.
https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3684
https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7209