Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Windows] Frameprops cause segfault for 32-bit build #276

Closed
qyot27 opened this issue Mar 14, 2022 · 11 comments
Closed

[Windows] Frameprops cause segfault for 32-bit build #276

qyot27 opened this issue Mar 14, 2022 · 11 comments

Comments

@qyot27
Copy link
Member

qyot27 commented Mar 14, 2022

I've been trying to find the source of this for a while, but the best I've been able to do is narrow it down to FFmpeg calling the frameprop-related API functions (the line in libavformat/avisynth.c where avs_get_frame_props_ro is used is what gdb points to). Under 64-bit, it's fine (else the patch wouldn't have landed in FFmpeg), but with 32-bit, it immediately segfaults.

For good measure, I had a fairly recent build of FFmpeg that worked - latest git for AviSynth+ loaded in it just fine, but the FFmpeg was from December, a good month and a half before the frameprop patches were integrated. So I rebuilt from the same commit, just with libavformat/avisynth.c checked out from FFmpeg's HEAD, and it could no longer load. The only difference between libavformat/avisynth.c from then to now are the frameprop changes.

It is specific to Windows, though. I have a VM of Debian i686, and both AviSynth+ and FFmpeg are perfectly fine.

A full backtrace using a non-stripped version of FFmpeg and a debug build of AviSynth+ r3651 (ec22279):

(gdb) r -i test.avs
Starting program: /e/Documents/ffmpeg_build/32bit-debug/bin/ffmpeg32.exe -i test.avs
[New Thread 7052.0x1fcc]
[New Thread 7052.0x354c]
[New Thread 7052.0x3b0c]
ffmpeg version N-105026-g2497a45562 Copyright (c) 2000-2021 the FFmpeg developers
  built with gcc 11.2.0 (GCC)
  configuration: --prefix=/home/qyot27/ffmpeg_build/32bit-debug --cross-prefix=x86_64-w64-mingw32- --progs-suffix=32 --enable-gpl --enable-version3 --disable-w32threads --disable-doc --disable-stripping --enable-avisynth --disable-optimizations --extra-cflags=-m32 --extra-ldflags='-m32 -L/usr/i686-w64-mingw32/lib' --target-os=mingw32 --arch=x86
  libavutil      57. 13.100 / 57. 13.100
  libavcodec     59. 15.100 / 59. 15.100
  libavformat    59. 10.100 / 59. 10.100
  libavdevice    59.  1.100 / 59.  1.100
  libavfilter     8. 20.100 /  8. 20.100
  libswscale      6.  1.102 /  6.  1.102
  libswresample   4.  0.100 /  4.  0.100
  libpostproc    56.  0.100 / 56.  0.100
warning: DllMain: hModule=0x72110000, ulReason=1, lpReserved=0x00000000, gRefCnt = 0
[New Thread 7052.0x764]
[New Thread 7052.0x382c]
[New Thread 7052.0x1f84]
[New Thread 7052.0x21f8]
warning: DllMain: hModule=0x72110000, ulReason=2, lpReserved=0x00000000, gRefCnt = 0
[New Thread 7052.0x3adc]
warning: DllMain: hModule=0x72110000, ulReason=2, lpReserved=0x00000000, gRefCnt = 0
[New Thread 7052.0x8fc]
warning: StringDump: Allocating new stringblock.
warning: DllMain: hModule=0x72110000, ulReason=2, lpReserved=0x00000000, gRefCnt = 0
warning: DllMain: hModule=0x72110000, ulReason=2, lpReserved=0x00000000, gRefCnt = 0
warning: DllMain: hModule=0x72110000, ulReason=2, lpReserved=0x00000000, gRefCnt = 0
warning: DllMain: hModule=0x72110000, ulReason=2, lpReserved=0x00000000, gRefCnt = 0
warning: ScriptEnvironment::Invoke after funcCtor make unique Import
warning: ScriptEnvironment::Invoke after funcCtor make unique Eval
warning: ScriptEnvironment::Invoke after funcCtor make unique Version
warning: ScriptEnvironment::GetNewFrame, no free entry in FrameRegistry. Requested vfb size=119808 memused=0 memmax=1073741824
warning: ScriptEnvironment::Invoke.AddChainedFilter OnCPU thread 2320 this->DefaultMtMode=2
warning: ScriptEnvironment::Invoke after funcCtor make unique OnCPU
warning: CacheGuard::SetCacheHints called. cache=06EB45C8 hint=602 frame_range=0
warning: ScriptEnvironment::Invoke done Cache::Create OnCPU
warning: CacheGuard::SetCacheHints called. cache=06EB45C8 hint=601 frame_range=0
warning: ScriptEnvironment::Invoke done Cache::Create Version
warning: ScriptEnvironment::Invoke done funcCtor->InstantiateFilter Eval
warning: ScriptEnvironment::Invoke done funcCtor->InstantiateFilter Import
warning: Cache::Cache registered. cache_id=06E7E420 child=06EB4370 w=376 h=104 VideoCacheSize=0
warning: Cache::GetFrame <Before GetFrame> LRU_LOOKUP_NO_CACHE: [] n=     0 child=06EB4370
warning: Cache::GetFrame <After GetFrame> LRU_LOOKUP_NO_CACHE: [] n=     0 child=06EB4370 frame=06E8B228 vfb=06E81BA0 videoCacheSize=0 SeekTime            :0.000587

Thread 1 received signal SIGSEGV, Segmentation fault.
0x00000000 in ?? ()

(gdb) bt
#0  0x00000000 in ?? ()
#1  0x0064b0fa in avisynth_create_stream_video (s=0x7813600, st=0x8f49280) at src/libavformat/avisynth.c:513
#2  0x0064ba9a in avisynth_create_stream (s=0x7813600) at src/libavformat/avisynth.c:793
#3  0x0064bd46 in avisynth_open_file (s=0x7813600) at src/libavformat/avisynth.c:858
#4  0x0064c426 in avisynth_read_header (s=0x7813600) at src/libavformat/avisynth.c:1031
#5  0x00664d62 in avformat_open_input (ps=0x6dff70c, filename=0x781348a "test.avs", fmt=0x0, options=0x7813594)
    at src/libavformat/demux.c:297
#6  0x0024634f in open_input_file (o=0x6dff7c0, filename=0x781348a "test.avs") at src/fftools/ffmpeg_opt.c:1178
#7  0x00252afc in open_files (l=0x781350c, inout=0x189fc3f <groups+215> "input", open_file=0x245b25 <open_input_file>)
    at src/fftools/ffmpeg_opt.c:3423
#8  0x00252c5a in ffmpeg_parse_options (argc=3, argv=0x7813300) at src/fftools/ffmpeg_opt.c:3463
#9  0x0026e4f7 in main (argc=3, argv=0x7813300) at src/fftools/ffmpeg.c:4872

(gdb) bt full
#0  0x00000000 in ?? ()
No symbol table info available.
#1  0x0064b0fa in avisynth_create_stream_video (s=0x7813600, st=0x8f49280) at src/libavformat/avisynth.c:513
        avs = 0x8f48140
        avsmap = 0x8f49280
        frame = 0x6e8b228
        error = 125908480
        planar = 0
#2  0x0064ba9a in avisynth_create_stream (s=0x7813600) at src/libavformat/avisynth.c:793
        avs = 0x8f48140
        st = 0x8f49280
        ret = 115337644
        id = 1
#3  0x0064bd46 in avisynth_open_file (s=0x7813600) at src/libavformat/avisynth.c:858
        avs = 0x8f48140
        arg = {type = 115, array_size = 0, d = {clip = 0x6dff208, boolean = 8 '\b', integer = 115339784,
            floating_pt = 8.42389098e-35, string = 0x6dff208 "test.avs", array = 0x6dff208, function = 0x6dff208}}
        val = {type = 99, array_size = 0, d = {clip = 0x6e90a58, boolean = 88 'X', integer = 115935832,
            floating_pt = 8.76600576e-35, string = 0x6e90a58 "l\214\247r\001", array = 0x6e90a58,
            function = 0x6e90a58}}
        ret = 0
        filename_ansi = "test.avs\000\003\000\000\070\363\337\006@\255\061w\347\031\325\307\376\377\377\377\270\362\337\006<n.w\024\000\000\000\060\000\000\000\000\000\000\000\210\362\337\006c\001\000P\000\000\201\a\000\000\000\000\230\362\337\006c\001\000P\000\000\201\aDy2w\004\000\000\000\000\000\201\a\f\000\000\000\000\000\201\ap\000\000\000 \000\000\000T\000\000\000\000\000\201\a", '\000' <repeats 12 times>, "\264\362\337\006\004\000\000\000\000\000\000\000\004\000\000\000\000\000\201\a\004\000\000\000c\001\000P\024\000\000\000\000\000\201\a\000\000\000\000\000\000\201\a\000\000\201\a\344\362\337\006\330\362\337\006\336].w\240\201\364\b\000\000\201\a\000\000\000\000\000\000\000\000\000\000"...
        filename_wc = L"test.avs", '\000' <repeats 590 times>...
#4  0x0064c426 in avisynth_read_header (s=0x7813600) at src/libavformat/avisynth.c:1031
--Type <RET> for more, q to quit, c to continue without paging--
        ret = 0
#5  0x00664d62 in avformat_open_input (ps=0x6dff70c, filename=0x781348a "test.avs", fmt=0x0, options=0x7813594)
    at src/libavformat/demux.c:297
        s = 0x7813600
        si = 0x7813600
        tmp = 0x7814000
        id3v2_extra_meta = 0x0
        ret = 50
#6  0x0024634f in open_input_file (o=0x6dff7c0, filename=0x781348a "test.avs") at src/fftools/ffmpeg_opt.c:1178
        f = 0x0
        ic = 0x7813600
        file_iformat = 0x0
        err = 22587074
        i = 560
        ret = 125907724
        timestamp = 115341248
        unused_opts = 0x0
        e = 0x0
        video_codec_name = 0x0
        audio_codec_name = 0x0
        subtitle_codec_name = 0x0
        data_codec_name = 0x0
        scan_all_pmts_set = 1
#7  0x00252afc in open_files (l=0x781350c, inout=0x189fc3f <groups+215> "input", open_file=0x245b25 <open_input_file>)
    at src/fftools/ffmpeg_opt.c:3423
        g = 0x7813580
        o = {g = 0x7813580, start_time = -9223372036854775808, start_time_eof = -9223372036854775808,
          seek_timestamp = 0, format = 0x0, codec_names = 0x0, nb_codec_names = 0, audio_channels = 0x0,
          nb_audio_channels = 0, audio_sample_rate = 0x0, nb_audio_sample_rate = 0, frame_rates = 0x0,
--Type <RET> for more, q to quit, c to continue without paging--
          nb_frame_rates = 0, max_frame_rates = 0x0, nb_max_frame_rates = 0, frame_sizes = 0x0, nb_frame_sizes = 0,
          frame_pix_fmts = 0x0, nb_frame_pix_fmts = 0, input_ts_offset = 0, loop = 0, rate_emu = 0, readrate = 0,
          accurate_seek = 1, thread_queue_size = -1, ts_scale = 0x0, nb_ts_scale = 0, dump_attachment = 0x0,
          nb_dump_attachment = 0, hwaccels = 0x0, nb_hwaccels = 0, hwaccel_devices = 0x0, nb_hwaccel_devices = 0,
          hwaccel_output_formats = 0x0, nb_hwaccel_output_formats = 0, autorotate = 0x0, nb_autorotate = 0,
          stream_maps = 0x0, nb_stream_maps = 0, audio_channel_maps = 0x0, nb_audio_channel_maps = 0,
          metadata_global_manual = 0, metadata_streams_manual = 0, metadata_chapters_manual = 0, attachments = 0x0,
          nb_attachments = 0, chapters_input_file = 2147483647, recording_time = 9223372036854775807,
          stop_time = 9223372036854775807, limit_filesize = 18446744073709551615, mux_preload = 0,
          mux_max_delay = 0.699999988, shortest = 0, bitexact = 0, video_disable = 0, audio_disable = 0,
          subtitle_disable = 0, data_disable = 0, streamid_map = 0x0, nb_streamid_map = 0, metadata = 0x0,
          nb_metadata = 0, max_frames = 0x0, nb_max_frames = 0, bitstream_filters = 0x0, nb_bitstream_filters = 0,
          codec_tags = 0x0, nb_codec_tags = 0, sample_fmts = 0x0, nb_sample_fmts = 0, qscale = 0x0, nb_qscale = 0,
          forced_key_frames = 0x0, nb_forced_key_frames = 0, force_fps = 0x0, nb_force_fps = 0,
          frame_aspect_ratios = 0x0, nb_frame_aspect_ratios = 0, rc_overrides = 0x0, nb_rc_overrides = 0,
          intra_matrices = 0x0, nb_intra_matrices = 0, inter_matrices = 0x0, nb_inter_matrices = 0,
          chroma_intra_matrices = 0x0, nb_chroma_intra_matrices = 0, top_field_first = 0x0, nb_top_field_first = 0,
          metadata_map = 0x0, nb_metadata_map = 0, presets = 0x0, nb_presets = 0, copy_initial_nonkeyframes = 0x0,
          nb_copy_initial_nonkeyframes = 0, copy_prior_start = 0x0, nb_copy_prior_start = 0, filters = 0x0,
          nb_filters = 0, filter_scripts = 0x0, nb_filter_scripts = 0, reinit_filters = 0x0, nb_reinit_filters = 0,
          fix_sub_duration = 0x0, nb_fix_sub_duration = 0, canvas_sizes = 0x0, nb_canvas_sizes = 0, pass = 0x0,
          nb_pass = 0, passlogfiles = 0x0, nb_passlogfiles = 0, max_muxing_queue_size = 0x0,
          nb_max_muxing_queue_size = 0, muxing_queue_data_threshold = 0x0, nb_muxing_queue_data_threshold = 0,
          guess_layout_max = 0x0, nb_guess_layout_max = 0, apad = 0x0, nb_apad = 0, discard = 0x0, nb_discard = 0,
          disposition = 0x0, nb_disposition = 0, program = 0x0, nb_program = 0, time_bases = 0x0, nb_time_bases = 0,
          enc_time_bases = 0x0, nb_enc_time_bases = 0, autoscale = 0x0, nb_autoscale = 0, bits_per_raw_sample = 0x0,
          nb_bits_per_raw_sample = 0}
        i = 0
        ret = 0
--Type <RET> for more, q to quit, c to continue without paging--
#8  0x00252c5a in ffmpeg_parse_options (argc=3, argv=0x7813300) at src/fftools/ffmpeg_opt.c:3463
        octx = {global_opts = {group_def = 0x18a53dc <global_group>, arg = 0x18a3780 <mjpeg_formats+1052> "",
            opts = 0x0, nb_opts = 0, codec_opts = 0x0, format_opts = 0x0, sws_dict = 0x0, swr_opts = 0x0},
          groups = 0x7813500, nb_groups = 2, cur_group = {group_def = 0x0, arg = 0x0, opts = 0x0, nb_opts = 0,
            codec_opts = 0x0, format_opts = 0x0, sws_dict = 0x0, swr_opts = 0x0}}
        error = "l3\201\a\330\372\337\006\002\253%\000\000\000\000\000 \000\000\000x?\212\001l?\212\001hA\212\001\070\000\000\000\000\000\000\000d\000\000\000\070\000\000\000\000\000\000\000d\000\000\000\373\245X\001d\256\306\001d\000\070\000l?\212\001\344\331\306\001d\000\004\000l?\212\001@\005\307\001f\001\006\000l?\212\001\004\217\213\001d\024\b\000l?\212\001\020{\212\001d\001;\000l?\212\001仚\001d\n;"
        ret = 0
#9  0x0026e4f7 in main (argc=3, argv=0x7813300) at src/fftools/ffmpeg.c:4872
        i = 125907820
        ret = 9
        ti = {real_usec = 10156047287188552, user_usec = 8587904747529285984, sys_usec = 0}
(gdb)
@pinterf
Copy link

pinterf commented Mar 15, 2022

For good measure, I had a fairly recent build of FFmpeg that worked - latest git for AviSynth+ loaded in it just fine, but the FFmpeg was from December, a good month and a half before the frameprop patches were integrated

This is not clear for me; the fairly recent that worked is a new version and what did not work is the December version?

If I understand then this is needed to reproduce:
Windows 32 bit
an up-to-date Avisynth
ffmpeg from last December or current ffmpeg but with avisynth.c from December (?)

@pinterf
Copy link

pinterf commented Mar 15, 2022

Grabbed current ffmpeg git (https://git.ffmpeg.org/ffmpeg.git), now just inspecting the code.
Though probably not related to the crash, this line is surely missing from avisynth_create_stream_video:
avs_library.avs_release_video_frame(frame);
Each avs_get_frame must have a release_video_frame counterpart.

@pinterf
Copy link

pinterf commented Mar 15, 2022

Have you checked AVSC_WIN32_GCC32 usage whether it is set or not?
If I understand the comments on this topic well, this must be set on FFMPEG side only when we'd like to use a gcc built 32 bit Avisynth+.

@qyot27
Copy link
Member Author

qyot27 commented Mar 15, 2022

Commit FFmpeg/FFmpeg@2497a45562 (from December) works. FFmpeg HEAD does not. The frame property reading patches were committed in mid-February.

To figure out if it was something in the rest of FFmpeg that might have broken it, I checked out commit (FFmpeg/FFmpeg@2497a45562), and then git checkout master libavformat/avisynth.c to update only that file to its current state. That modified build also fails like the new builds, so the breaking change was in the AviSynth demuxer, and the only thing that changed in the AviSynth demuxer between December and now were the frameprop reading commits.

32-bit Windows isn't necessary, only 32-bit FFmpeg. I wasn't testing with GCC builds of AviSynth, so I wasn't using the AVSC_WIN32_GCC32 compat in the FFmpeg build. Normal 32-bit MSVC builds, like the release build of 3.7.1 or the 3.7.2 test builds.

@pinterf
Copy link

pinterf commented Mar 16, 2022

Hi, I'm sorry to say but I'd need a short help how to build this ffmpeg monster for win32. If it's not a short one I'm gonna figure it out. I fetched the master git so far and have a mingw environment which I usually use for gcc+win syntax check for Avisynth+ but I think it's x64 as well.

@qyot27
Copy link
Member Author

qyot27 commented Mar 16, 2022

I normally cross-compile FFmpeg under Linux, so the best I can really do there is point to the tedious build guide. Assuming zlib, bzip2, and AviSynth+'s headers are already installed, the basic configuration options for FFmpeg for 32-bit are here: https://github.com/qyot27/mpv/blob/extra-new/DOCS/crosscompile-mingw-tedious.txt#L4658

https://www.mediafire.com/file/1gz6azqot6ngdp8/ffmpeg_2497a45562.7z/file

That contains two different debug builds of FFmpeg git-2497a45562: the regular commit as it was back in December, as well as with the frameprop changes applied.

I also just tested with AviSynth+GCC 3.7.1a and the AVSC_WIN32_GCC32 FFmpeg 32-bit build. It works as expected. So the problem with avs_get_frame_props_ro (and _rw) is specific to 32-bit MSVC builds of AviSynth+ when accessed through at least the C interface.

@pinterf
Copy link

pinterf commented Mar 16, 2022

Strange. It seems that this function pointer did not resolved in ffmpeg.
There is no such string like avs_get_frame_props_ro in the executable.
Function avs_get_frame_props_rw does exist however.
Looking into the downloaded git code I can see only avs_get_frame_props_ro and no
avs_get_frame_props_rw. Are you sure you have _ro ending and not _rw in your repo?

@qyot27
Copy link
Member Author

qyot27 commented Mar 16, 2022

I only mentioned _rw because I was thinking it might have only been a problem with _ro, so I tested whether _rw was also affected by it (it was). That was all local.

I thought maybe it had something to do with the fact _ro is using consts, and something about how MSVC compiles for 32-bit might be affecting that somehow?

@pinterf
Copy link

pinterf commented Mar 16, 2022

Thanks. All V8+ functions were missing in avisynth.def.
I think this effects function decorations which is different for 32 bit msvc and others.
Without these entries function names are decorated as

_avs_get_frame_props_ro@8
_avs_get_frame_props_rw@8

instead of

avs_get_frame_props_ro 
avs_get_frame_props_rw

This is the list which I appended to avisynth.def, interestingly two older functions were missing as well (rgb48,64)
All the others are V8,V9 additions.

I suppose this implies that the IF version must jump again, and ffmpeg 32 bit build should require 9.1?

  avs_is_rgb48
  avs_is_rgb64
  avs_subframe_planar_a
  avs_copy_frame_props
  avs_get_frame_props_ro
  avs_get_frame_props_rw
  avs_prop_num_keys
  avs_prop_get_key
  avs_prop_num_elements
  avs_prop_get_type
  avs_prop_get_int
  avs_prop_get_float
  avs_prop_get_data
  avs_prop_get_data_size
  avs_prop_get_clip
  avs_prop_get_frame
  avs_prop_delete_key
  avs_prop_set_int
  avs_prop_set_float
  avs_prop_set_data
  avs_prop_set_clip
  avs_prop_set_frame
  avs_prop_get_int_array
  avs_prop_get_float_array
  avs_prop_set_int_array
  avs_prop_set_float_array
  avs_clear_map
  avs_new_video_frame_p
  avs_new_video_frame_p_a
  avs_get_env_property
  avs_pool_allocate
  avs_pool_free
  avs_get_var_try
  avs_get_var_bool
  avs_get_var_int
  avs_get_var_double
  avs_get_var_string
  avs_get_var_long
  avs_is_property_writable
  avs_make_property_writable

@qyot27
Copy link
Member Author

qyot27 commented Mar 16, 2022

Those functions missing in the .def file makes sense. It also makes sense why the GCC build would work while the 32-bit MSVC build wouldn't, as GCC has the visibility attribute to control this sort of thing and probably just has all of them visible all the time. I'm not sure why it would be fine for 64-bit MSVC, unless Microsoft decided to do something similar when dealing with that issue on 64-bit, like the calling convention stuff on 64-bit being simpler too.

I don't think this requires an interface bump, or to play with the detection logic in FFmpeg (I found out that I couldn't be clever about that and still be able to work with pre-3.7.1 versions of AviSynth+, so the frameprop patch just uses avs_get_version to check for version 9), since we're not messing with any headers or the implementation in avisynth_c.cpp. It's more of a compiler fix that only applies to 32-bit MSVC and nowhere else.

Though it might warrant actually doing the release of 3.7.2, so users have an easy fixed version to point to. Is there currently anything in the other recent issues that should get in before then?

@pinterf
Copy link

pinterf commented Mar 17, 2022

Things to do - nothing important is in my queue
Def addition - EDIT: done
Bump to 3.7.2 on git as well
Change log to rst and my readme - EDIT: done
Check why 32bit avspmod works now - EDIT: don't know, but tried and it can read frame properties just fine both before and after the .def additions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants