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
Does AviSynth+ internally support P010? #146
Comments
P010 is supported through AviSource (see AviSource.cpp) But inside Avisynth and the filters solely the planar YUV formats are used. Formats mentioned above are only avaliable through VfW or Avisource interface. You can check Avihelper.cpp for conversions, e.g. |
Maybe 010 formats are not using 10 bits on LSB but rather on the MSB part. In Avisynth 10 bit data have to be between 0 and 1023. Filters should garantee that range and expect data using this rule. |
Here is what I did. I run the following commands to get an one-frame P010 video:
If I open the "test.yuv" with a hex editor, I can clearly see all WORDs are within the 0x3FF range (little-endian). However, when I play test.mp4 in MPC-HC, the data my filter gets from upstream (e.g. LAV video decoder) are exceeding 0x3FF range. I can confirm the input pin's media type FourCC is P010. Since this is one-frame video, I was expecting the decoded data should exactly match test.yuv. See the screenshots. What am I doing wrong? Are those bytes some sort of compressed data? Sorry if this does not seem to be very related to AviSynth at this point. I tried to search but can't find much information about what P010 decoded data should look like. |
P010 stores values left shifted 6 bits, as if the values were originally 16 bits. "When I send P010 data to AviSynth+, claiming it as VideoInfo::CS_YUV420P10" I don't know if it works: Or or Expr When I have put all these formats into AviSource, there is a technique when we are able to request a specific format during the negotiation phase. When I asked for P010 from the input provider I got it. If I asked for YV12 I got it (clearly the driver did the format conversion for me). I was playing with MagicYUV, and I could ask for a bunch of different formats even when the file itself had a propriatery MagicYUV FourCC. The driver was able to convert it to P010 whatever special MagicYUV FourCC I was using for the file generation originally. |
Does ffmpeg have pix format p010le? |
Thanks. I got it now. I misunderstood the picture from Microsoft Docs. Like you said, I just need to right shift every WORD by 6 bits. Also, the reason why faking as P016 works is because, like that Microsoft document says, P016 is just a more scaled P010 (by 2^6=64 times). Without right shift, P010 is P016. Also, no precision loss as it says. I'll just stick to faking P016. Feel free to close the issue. In short, P010 has MSB zero-padded, while AviSynth expects LSB zero-padded, correct? Still, it would be nice if AviSynth could take the 6-MSB-padded WORD as P010 input without asking every source plugin to do the convertion. |
My outputs:
|
Avisynth+ and all plugins (incl. source plugins) must follow and use only the supported formats defined in avisynth.h. Or else, how do you tell Avisynth that your format is special? If you write a source plugin then you can write methods and accept whatever exotic formats from an upper level, like AviSource does which accepts and converts a zillion formats on its interface (see: http://avisynth.nl/index.php/AviSource) |
It should have been:
P010 and YUV420P10 are not the same, pix_fmt wise. YUV420P10 is fully planar, P010 is not (planar luma, packed chroma). NV12 isn't supported internally for exactly the same reason. |
Was the format I'm sending (zero padding at MSB) the standard format or special? I thought that's the one the Microsoft page is describing. That's why when I re-read your comment Anyways, I'm not sure if this happens commonly. Since you've already have all the conversion logic done in AviSource, you could add something like I don't know much of the development philosophy of this project, so don't take me too seriously. |
I just tried the |
I'm not entirely up on the exact details, but my understanding is that P010, et. al, are largely interchange formats between software and the graphics display stack - meant for consumption by the GPU or the APIs dealing with them, like OpenGL. So on a certain level, they are equivalent, but at other points, they definitely aren't. And how you generate such a file may be silently correct, or silently incorrect based on assumptions the software is making about what it's being told to do; I doubt most formats you can pack into MP4 support P010 as-is, and ffmpeg automatically tries to convert back to yuv420p10, with something getting borked in that chain somewhere when the output is wrong. How does ConvertBits(10, truerange=false) inserted into the filterchain immediately after loading the video act in regard to the output? Because this sounds kind of like a reason why the truerange option exists, if forcing YUV420P16 works. You can see the actual difference in output if you use FFmpeg to generate unencapsulated rawvideo for yuv420p10le and p010le and then try to play it back in ffplay¹. If you don't get the pix_fmt value exact, it results in clearly wrong output. The CRC32s also don't match, even though the filesizes do. ¹with a script containing When playing them back with ffplay, you have to declare the resolution and pix_fmt, but it plays correctly if you use the correct pix_fmt, and incorrectly if you use the other.
|
Sorry took this long to reply. It looks like If this is not at any priority, I'm totally fine. If this request is remotely relevant, I can open a cleaner ticket if you want. |
The only formats we'll accept going forward¹ are fully planar. The few packed formats that do exist in the core are there because they were grandfathered in from classic AviSynth (RGB24, RGBA32, and YUY2), or were adjacent to the ones that were grandfathered in (RGB48, RGBA64). ¹'going forward' meaning since 2016, when the pixel format list was expanded, but effectively even before that, as the goal is to move to all the existing packed formats in the core to getting processed internally as planar. I suppose one course of action that wouldn't clutter avisynth{_c}.h with pixel formats filter authors will never use is to have a RawConvert() filter that can take arbitrary pixel formats and override them by doing the plane unpacking and bit shifting, via individual arguments or definition files that describe the input format. That way any exotic color format could be processed in/out of the core without any of the filters needing explicit support for them.
or the definition files idea:
And then give it to a program that expects P010, and basically just tell it to ignore the fact that AviSynth+ is still telling it that the format it's serving out is YUVA420P10. If that's even a necessity. |
I didn't know this is part of AviSynth's philosophy, partly because like you said you have RGB, and partly because http://avisynth.nl/index.php/Avisynthplus_color_formats didn't mention anything. The RawConvert() idea is clean on both end (source developer and core developer). The syntax is a bit too detailed for either, but I guess as long as it is not exposed to end users, it is fine. I mean, I can call |
If it works, yeah. |
So just FYI, recently I took some time to implement the "shift by 6 bit" change in my project. Basically, as mentioned earlier, I right shift every WORD by 6 bit of received p010le data to AviSynth+ as yuv420p10le, and left shift on the other end. Everything worked as expected. Still, since the process is relatively costly, and faking as p016 is lossless, I will just keep that change as POC. Still, again, if this kind of conversion is useful not only to my project but also potentially to other use cases of AviSynth+, you guys could add this small function to your conversion library. |
I don't think it is useful in general, there are a zillion of other formats, one would question, why not support P210, P216, P010, P016, v410, v308, v408, etc (I have done some of these conversions in AviSource), then why not big-endian and little-endian, I'd better not add more complexity to this part of Avisynth. |
Well, P010 and P210 both have exactly the same problem, so that logic solve both. P016 and P216 are exactly what the solution currently are, so there's no need. The others you mentioned might not be as popularly used as, but as a generic engine, I completely understand the position you guys take. So fair enough. Feel free to close the ticket. |
When I send P010 data to AviSynth+, claiming it as
VideoInfo::CS_YUV420P10
and then call some internal functions likeSubtitle()
orInfo()
, the text are blurry and green (which should be clear yellow text). However, if I claim it asVideoInfo::CS_YUV420P16
, everything works fine.I tried all
CS_YUV420P10
,CS_YUV420P12
,CS_YUV420P14
andCS_YUV420P16
. OnlyCS_YUV420P16
produces correct output. Other plugins like MVTools also only works when I'm claimingCS_YUV420P16
.Is this a bug or
CS_YUV420P10
has completely different meaning?The text was updated successfully, but these errors were encountered: