Log in

View Full Version : yuv422p10 AVISynth output


csdesigns
16th August 2016, 23:06
Hi guys, really hoping someone can provide some support here... Apologies if this has been answered elsewhere previously, but I have spent quite a bit of time researching the answer for this and either this does not appear to be possible, or the solution is simply alluding me:

Is there any method to achieve full 10bit 4:2:2 output direct from an AVISynth script? I have some UHD AVC High 4:2:2 Intra Profile files in a MXF wrapper that I need to ingest into another application which does not have native support for this type of file, and was hoping to use an AVISynth script as the intermediary as AVS scripts are directly supported by the application.

I have been able to use AVISynth 2.6 MT with both ffms2 (with enable10bithack=true) and LSMASHSource to successfully import the source(s) into AVISynth and properly decode them as 2x 8bit stacked frames (MSB + LSB). However, this is as far as I can get, as I am clueless as to how to then be able to merge or return those frames as true non-stacked 10bit to other 'basic' applications which can only handle the AVS script in its native output. Basically, at a minimum, I need to be able to output from AVISynth a script which directly produces the video in raw YUV422P10 (or YUV420P10) or v210 formats. No AVISynth processing or filtering is required for these files other than decode.

Any help that can be provided would be greatly appreciated! Thanks!!

qyot27
17th August 2016, 00:14
You're [kind of] in luck. AviSynth+ (http://avs-plus.net/) has been implementing high bit depth output over the last two months (https://github.com/AviSynth/AviSynthPlus/commits/MT), and a couple days ago the 10/12/14 support was committed (http://forum.doom9.org/showthread.php?p=1777057#post1777057). All you have to add is ConvertFromStacked(10) or ConvertFromDoubleWidth(10) based on whether the source filter (or f3kdb or Dither) is giving you stacked or interleaved. ConvertFromStacked/DoubleWidth defaults to 16 bits, so if the input into that plugin isn't 16, you do need to know what the source bit depth was and specify that - but that's usually going to be obvious to the user.

But there is a problem greater than simply being able to output it without hacks. The receiving application needs to know that AviSynth is outputting that pixel format as well.

csdesigns
17th August 2016, 05:39
Thanks for the fast response qyot27! Unfortunately, I seem to have hit a roadblock... Here is an example of my simple script I am trying to load in AvsPmod and AVISynth+ r2161:
LWLibavVideoSource("source.mxf", format="YUV422P10", stacked=true)
ConvertFromStacked(10)
or
ffvideosource("source.mxf", enable10bithack = true)
ConvertFromStacked(10)

Without the ConvertFromStacked(10) line, the source loads with both plugins into AvsPmod and defaults to YV16. But with this line, I get the following message:Script error: Invalid arguments to function 'ConvertFromStacked'
Am I doing something wrong? Does AvsPmod just not support 10bit display (what you alluded to at the end of your post – I am using AvsPmod included in the r2161 build btw)?

Thanks for the insight into AVISynth+ btw! I was unaware of this project until tonight but like what I have seen thus far...

poisondeathray
17th August 2016, 05:53
What is the other application? 99.99% won't accept a hacky 10bit avisynth script as-is

I think a proven, better workflow is just to encode to another intermediate like v210 directly which will be accepted. eg. use ffmpeg

Since you're not using avisynth for any other processes, just decoding, it makes more sense.

The only reason I can see using avisynth or vapoursynth is if you want to control the algorithm for the bit depth conversion if you're starting from 8bit. You only said "UHD AVC High 4:2:2 Intra Profile" , which can be 8bit or 10bit, but you're using "format="YUV422P10" in l-smash so that suggests 10bit

eg.
(Assuming you don't want audio)



ffmpeg -i input.mxf -c:v v210 -an output.mov

qyot27
17th August 2016, 06:49
Am I doing something wrong? Does AvsPmod just not support 10bit display (what you alluded to at the end of your post – I am using AvsPmod included in the r2161 build btw)?
My guess is that AvsPmod's support of parameters in plugins has to be updated manually. At one point ConvertFromStacked/DoubleWidth didn't have a parameter and always did 8bit hack->16bit real, but with the new pix_fmts it now has a bits= parameter and AvsPmod can't cope with that yet.

You could use f3kdb to fix it up if you want to test 16-bit:
sourcefilter()
f3kdb(input_depth=10, output_depth=16, output_mode=2) # mode 2 is interleaved, mode 1 is stacked
ConvertFromDoubleWidth() # or ConvertFromStacked()

Not that I know whether that'd work, but it's a thought.

sneaker_ger
17th August 2016, 11:41
Try VapourSynth with the virtual file server. v210 and ffms2 are supported.

csdesigns
17th August 2016, 15:37
I think a proven, better workflow is just to encode to another intermediate like v210 directly which will be accepted. eg. use ffmpeg

Since you're not using avisynth for any other processes, just decoding, it makes more sense.
Agreed. For one-off files, this would indeed make more sense and certainly be simpler, and has been my de facto method to date. But this would be a major workflow issue for multiple files and batch processing, not to mention the amount of temp disk space that would be required to store the uncompressed conversion, and the goal is to have as little user-interaction as possible.

You only said "UHD AVC High 4:2:2 Intra Profile" , which can be 8bit or 10bit, but you're using "format="YUV422P10" in l-smash so that suggests 10bit
Correct, the source is 10bit 422 AVC-I.

Not that I know whether that'd work, but it's a thought.
Still a no go unfortunately. Appears that your doubts were justified. :( The application I need to use (32bit Windows) with this source file can accept AVISynth scripts, and works well with standard uncompressed 10bit source files (though possibly not with AVISynth 10bit files; however, this could be managed by updating the application to then support AVISynth 10bit output if I can get at least get 10bit working initially).

If it would help, I have posted a very short example clip here (https://app.box.com/embed/preview/kn4x81i6jhmg3lj4w7a69x1w1e8040pe?theme=dark).

poisondeathray
17th August 2016, 15:57
But this would be a major workflow issue for multiple files and batch processing, not to mention the amount of temp disk space that would be required to store the uncompressed conversion, and the goal is to have as little user-interaction as possible.


It's the opposite - It would be easier to automate and batch process with ffmpeg, everything is automated with scripts, wildcards, watch folders. There is no user interaction. With avisynth, the user would have to generate an .avs per file, wait for your source filter to index it, then do something like mount or encode

Large storage space for v210, yes, but it's stable. You can look at sneaker's suggestion of virtual files with vsfs, but once you more than a few, they will crash most compositing/NLE software. avfs will only support 8bit

EDIT: I didn't see this

AVS scripts are directly supported by the application


What is your target application? No commercial program will "understand" the stacked avisynth format as a virtual file, there is no native 10bit support in avisynth; you have to use vapoursynth for 10bit. No commercial program will understand an .avs or .vpy, it needs to be virtualized

csdesigns
17th August 2016, 16:56
It's the opposite - It would be easier to automate and batch process with ffmpeg, everything is automated with scripts, wildcards, watch folders. There is no user interaction.
Yes, and I currently use ffmpeg for many other forms of single and batch video pre-processing; but for this workflow, ffmpeg would not be ideal, primarily because these are UHD source files and multiple files need to be processed simultaneously, which would basically destroy disk space and speed.

With avisynth, the user would have to generate an .avs per file, wait for your source filter to index it, then do something like mount or encode
Actually, the application I am using has support for source file name and directory macros within an AVISynth script, such that any file dropped into a watched folder will automatically be processed through AVISynth.

No commercial program will understand an .avs or .vpy, it needs to be virtualized
This application does understand AVS files directly, but probably not 10bit AVS. I have some influence over that with the developer however. I just need to prove that this AVISynth (or AVISynth+) approach can work (any other application showing 10bit support would suffice) before I can ask the dev to commit to it.

If there's no method to really get this working, that'd be unfortunate, but so be it. I could certainly get the ffmpeg method working by directly scripting that within the application, but would prefer to use a frame server versus a frame writer for this project.

Again, thanks for your time and thoughts on this thus far.

qyot27
17th August 2016, 19:13
there is no native 10bit support in avisynth
As I mentioned just a few posts ago, AviSynth+ does now, at least as far as output goes. The filters may not have been updated yet, but that's not what applications using AviSynth care about.

FFmpeg should have the patch that supports this committed soon, and after that, anything built against libavformat will too (provided it was built with --enable-avisynth). It may take a couple days for Zeranoe's ffmpeg builds and the mpv daily builds to get rolled out, but when that happens you'll be able to demonstrate that it works.

Mostly it's just a matter of using the AviSynth+ avisynth.h or avisynth_c.h header from the 'MT' branch and allowing the program to recognize the new pixel type constants (and there's a bunch of them that were just added). That is, if the program talks to AviSynth.dll directly and not through the Video for Windows interface (who knows how something that does it that way might support extra pixel formats).

qyot27
18th August 2016, 00:35
Using a build of AviSynth+ from my mingwfix branch, and a build of FFmpeg including my patches for it to support AviSynth+'s high bit depths, a script containing:
FFVideoSource("AVC-I_422_10bit_UHD_1f.mxf",enable10bithack=true)
ConvertFromStacked()
Outputs a proper image. For verification's sake, the output of the newest version of AVSMeter (since it can properly detect the new pixel types):
>avsmeter test.avs

AVSMeter 2.3.7 (x86) - Copyright (c) 2012-2016, Groucho2004
AviSynth+ 0.1 (r2183, mingwfix, i386) (0.1.0.0)

Number of frames: 5
Length (hh:mm:ss.ms): 00:00:00.100
Frame width: 3840
Frame height: 2160
Framerate: 50.000 (50/1)
Colorspace: YUV422P16

Frames processed: 5 (0 - 4)
FPS (min | max | average): 1.489 | 1.907 | 1.777
Memory usage (phys | virt): 390 | 430 MiB
Thread count: 17
CPU usage (average): 26%

Time (elapsed): 00:00:02.813
Or the image itself with Info() extracted with ffmpeg (http://i.imgur.com/Eh7pmTd.jpg):
ffmpeg -i test.avs -frames:v 1 -qscale:v 1 test.jpg
>ffmpeg -i test.avs
ffmpeg version r81319 git-8e8aff8 Copyright (c) 2000-2016 the FFmpeg developers
built on Aug 9 2016 23:50:26 with gcc 6.1.0 (GCC)
libavutil 55. 28.100 / 55. 28.100
libavcodec 57. 51.100 / 57. 51.100
libavformat 57. 46.100 / 57. 46.100
libavdevice 57. 0.102 / 57. 0.102
libavfilter 6. 50.100 / 6. 50.100
libavresample 3. 0. 0 / 3. 0. 0
libswscale 4. 1.100 / 4. 1.100
libswresample 2. 1.100 / 2. 1.100
libpostproc 54. 0.100 / 54. 0.100
Input #0, avisynth, from 'test.avs':
Duration: 00:00:00.10, start: 0.000000, bitrate: 7 kb/s
Stream #0:0: Video: rawvideo (Y3[10][16] / 0x100A3359), yuv422p16le, 3840x2160, 50 fps, 50 tbr, 50 tbn, 50 tbc
At least one output file must be specified
It would seem that the enable10bithack in FFMS2 is not actually outputting 10bit, but full 16bit (using ConvertFromStacked(10) outputs a hot pink and white incorrect image, the tell-tale sign that the bit depth provided by the user is incorrect). The output from LwLibavVideoSource (r903, the latest build available) is just solid green, no matter what options I pass to it. Honestly, I think it may not support the video file correctly.


That patch (https://github.com/qyot27/FFmpeg/commit/6e3cce6ef68f2abbb97d41ba2166dcbd06a6bfeb) is not yet in FFmpeg, though (and the one I linked to is slightly earlier from the one on FFmpeg-devel's mailing list; it lacks the USING_AVISYNTH ifdefs to protect FFmpeg from failing to compile on Linux; for Windows builds it doesn't affect anything).

If you want to try with an FFmpeg build that contains that patch, use this one:
http://www.mediafire.com/download/b588msbb584cp8e/ffmpeg_r81319.7z

The 7zip also has ffplay in there, so you can just watch the script. Remember, though, that's not yet in upstream FFmpeg, I'm just providing it so you can see it actually works.

Groucho2004
18th August 2016, 00:51
For verification's sake, the output of the newest version of AVSMeter (since it can properly detect the new pixel types):
>avsmeter test.avs

AVSMeter 2.3.7 (x86) - Copyright (c) 2012-2016, Groucho2004
AviSynth+ 0.1 (r2183, mingwfix, i386) (0.1.0.0)

Number of frames: 5
Length (hh:mm:ss.ms): 00:00:00.100
Frame width: 3840
Frame height: 2160
Framerate: 50.000 (50/1)
Colorspace: YUV422P16

Frames processed: 5 (0 - 4)
FPS (min | max | average): 1.489 | 1.907 | 1.777
Memory usage (phys | virt): 390 | 430 MiB
Thread count: 17
CPU usage (average): 26%

Time (elapsed): 00:00:02.813
FYI - "avsmeter test.avs -i" gives you just the clip properties without requesting any frames.

poisondeathray
18th August 2016, 04:35
As I mentioned just a few posts ago, AviSynth+ does now, at least as far as output goes.

Thanks for the info and testing! It looks promising

I tried a few older l-smash builds and they also get green frames.

csdesigns
18th August 2016, 05:54
Using a build of AviSynth+ from my mingwfix branch, and a build of FFmpeg including my patches for it to support AviSynth+'s high bit depths, a script containing:
FFVideoSource("AVC-I_422_10bit_UHD_1f.mxf",enable10bithack=true)
ConvertFromStacked()
Outputs a proper image.

It would seem that the enable10bithack in FFMS2 is not actually outputting 10bit, but full 16bit (using ConvertFromStacked(10) outputs a hot pink and white incorrect image, the tell-tale sign that the bit depth provided by the user is incorrect). The output from LwLibavVideoSource (r903, the latest build available) is just solid green, no matter what options I pass to it. Honestly, I think it may not support the video file correctly.

Thank you so much for your time looking into this! :thanks:

You also confirmed the exact same behavior I was seeing on my system with FFMS2 (only could get YV16 to output) and LwLibavVideoSource (solid green on all >8bit pixel formats). I was hoping that this may have been just a configuration error on my end, but glad to see it confirmed nonetheless.

If you want to try with an FFmpeg build that contains that patch, use this one:
http://www.mediafire.com/download/b588msbb584cp8e/ffmpeg_r81319.7z

The 7zip also has ffplay in there, so you can just watch the script. Remember, though, that's not yet in upstream FFmpeg, I'm just providing it so you can see it actually works.
Again, much appreciated!! I have been able to properly decode this script with your ffplay build now, and while the inability to output true 10bit from either ffms2 or LwLibavVideoSource for the time being may limit my options a bit, at least now I can see some progress being made on this front.

Amazing work here qyot27!!! I owe you a beer or something...

csdesigns
18th August 2016, 18:30
It would seem that the enable10bithack in FFMS2 is not actually outputting 10bit, but full 16bit (using ConvertFromStacked(10) outputs a hot pink and white incorrect image, the tell-tale sign that the bit depth provided by the user is incorrect).
So I looked a little bit further into if it would be possible to still get 10bit output through further scripting. I have been trying to get the Dither plugin to work,ffvideosource("source.mxf",enable10bithack=true)
ConvertFromStacked()
Dither_quantize(bitdepth=10)
Dither_out()
but am running against the following error: mt_lut : unsupported colorspace. masktools only support planar YUV colorspaces <YV12, YV16, YV24>
I have tried multiple ways to 'force' a conversion to YV16 before passing on to the Dither tools, but no go. So maybe the output from ffms2 isn't 'true' YV16?

qyot27
18th August 2016, 19:05
So I looked a little bit further into if it would be possible to still get 10bit output through further scripting. I have been trying to get the Dither plugin to work,ffvideosource("source.mxf",enable10bithack=true)
ConvertFromStacked()
Dither_quantize(bitdepth=10)
Dither_out()
but am running against the following error: mt_lut : unsupported colorspace. masktools only support planar YUV colorspaces <YV12, YV16, YV24>
I have tried multiple ways to 'force' a conversion to YV16 before passing on to the Dither tools, but no go. So maybe the output from ffms2 isn't 'true' YV16?
YV16 is 8-bit Planar 4:2:2. Since the hack formats store >8bit inside of 8bit, the stacked clip is YV16, but the reconstructed clip is YUV422P16.

And Dither currently only works on 8-bit input sources (which would include stacked format, although it might require passing an option to make it see it that way). Dither_out also only outputs in hack format, so you'd have to re-do ConvertFromStacked/DoubleWidth afterward anyway. I'd rather use flash3kyuu_deband (http://forum.doom9.org/showthread.php?t=161411):

ffvideosource("source.mxf", enable10bithack=true)
f3kdb(input_mode=1, output_depth=10, output_mode=2)
ConvertFromDoubleWidth(10)

input_mode=1 tells it that it's getting stacked format, output_depth=10 has it scale the clip down to 10bit, and output_mode=2 outputs it in interleaved format. ConvertFromDoubleWidth(10) then reconstructs it from the interleaved format into a YUV422P10 output stream.

csdesigns
18th August 2016, 20:01
I'd rather use flash3kyuu_deband (http://forum.doom9.org/showthread.php?t=161411):
Since the hack formats store >8bit inside of 8bit, the stacked clip is YV16, but the reconstructed clip is YUV422P16.
Thanks for the added detail – makes complete sense.

I'd rather use flash3kyuu_deband (http://forum.doom9.org/showthread.php?t=161411):

ffvideosource("source.mxf", enable10bithack=true)
f3kdb(input_mode=1, output_depth=10, output_mode=2)
ConvertFromDoubleWidth(10)

Can I ask what version/build of flash3kyuu_deband you are using? I tried this filter as well prior to my last post, and even though one of my scripts was very close to yours and another was a bit different, all I get on ffplay (using the binary build you linked to previously) is green output similar to LwLibavVideoSource. ffplay still reports the video as being yuv422p16le as well.

As always, thanks for your continued assistance! :thanks:

qyot27
18th August 2016, 21:02
flash3kyuu_deband 1.5.1

csdesigns
18th August 2016, 21:16
So it appears I did have an older version installed... but that did not resolve the issue. Also, whenever I try to use ConvertFromDoubleWidth(10) or ConvertFromStacked(10), I get Script error: Invalid arguments to function 'ConvertFrom...'
So I have to just use ConvertFromDoubleWidth() or ConvertFromStacked() in order to render any output, which I guess is why I am stuck at yuv422p16le output.

qyot27
19th August 2016, 03:46
You get that when you give the script to FFmpeg? Update AviSynth+ and its plugins (r2171 is the latest build available).