Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
29th May 2010, 10:28 | #1 | Link |
Registered User
Join Date: Nov 2008
Location: Sydney, Australia
Posts: 26
|
New Plugin - Sashimi (raw file access)
Hey there Doom9erinos!
History: Many an age ago, I wrote my own raw reading and writing plugins for AVISynth because RawReader didn't do quite what I wanted. Later, I needed to use raw reading of some files in a corporate environment, and software without clear licensing was banned from even being downloaded so I couldn't use RawReader! I dusted off my old plugins, made the first version of Sashimi, and made it GPLv2 (please note before commenting, that many business applications still have a big issue with GPLv3 because of the NAP clause, so I deliberately used v2 and for the next while at least I think that you should too if you'd like your software to be widely used and you don't plan to sue anyone). Finally and more recently, I cleaned it up a lot and added some features, so now I'm putting it out there. Actual Relevant Stuff: In combination with the included .avsi scripts, it can read and write a whole host of raw formats, and I've used it myself a lot so it's relatively well tested but I'm sure that some major issues will be found as soon as others start using it too. Let me know what you think! I'm keen to get feedback, and I plan to fix bugs if any are found, but I'm one of those people who sometimes takes ages to respond, so advance apologies if I'm slow answering any direct questions. See here for the latest version on my site: https://sites.google.com/site/ourenthusiasmsasham/soft But for simplicity, the plugin and source are also attached to this post. UPDATE: I've fixed bugs and extended the abilities since the original post. Even though discussion and development continues, these attached files are up to date, get sashimi here. Previous versions are available at my site and linked from within the documentation. See below for comments, and here for the files: Last edited by PitifulInsect; 11th June 2015 at 06:33. Reason: Updated URL to host site |
29th May 2010, 17:13 | #2 | Link |
Registered User
Join Date: Aug 2008
Location: The Land Of Dracula (Romania - EU)
Posts: 934
|
thanks a lot...
_
__________________
if you ask a question and somebody give you the correct answer don't forget to leave a "thank you" note... Visit The Land Of Dracula (Romania - EU)! |
29th May 2010, 22:39 | #3 | Link | |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
Quote:
The 147KB file is the source, the 123KB file is the release. |
|
5th June 2010, 19:24 | #5 | Link |
Registered User
Join Date: Nov 2008
Location: Sydney, Australia
Posts: 26
|
Cheers IanB, they were backwards, but I've changed them around to be the right way around while updating the version to 0.74.
Minor bugfix aside, what I did was add a massive pile of documentation and a heap of runnable examples. I'm going to brag here about what the plugin does in those examples, so that this thread can be found by anyone doing a text search for how to do those things:
Cheers for the comments so far! Last edited by PitifulInsect; 5th June 2010 at 19:46. Reason: I hate typos! Fixed. |
8th June 2010, 03:49 | #8 | Link |
ангел смерти
Join Date: Nov 2004
Location: Lost
Posts: 9,556
|
Just note that if you need to process YUV files in imagemagick, the 16-bit precision (Q16) version often crashes reading and writing them.
One minor bug I found: RawWriter(...,overwrite=true) will only open the file, write into it, and close, but it will not truncate it first. So you get a bunch of garbage at the end if the original file was longer than the new one. |
18th June 2010, 07:43 | #9 | Link |
Registered User
Join Date: Nov 2008
Location: Sydney, Australia
Posts: 26
|
I had to look it up - I hadn't come across it before.
Sorry Chikuzen, I wasn't planning to, but it should work just fine if you read the human-readable (as I understand it) headers and set the right offset, which would probably be good enough for a once-off solution. I would think that a half hour of hacking would make a Python script to parse the YUV4MPEG2 headers and write an appropriate AVISynth script (that sets the offset and dimensions, then calls the appropriate Sashimi function). If you (or anyone) should write such a Python script, post it here and I'll include it in the next Sashimi release. If there are any YUV4MPEG2 pixel formats that Sashimi doesn't support (but AVISynth could), then please let me know. I won't immediately offer to do it myself, since I'm unfamiliar with the format or its usage, but I might wander back to this sometime - I'm intrigued! I'm wondering if the headers could somehow be parsed directly from within a tricky AVISynth script without invoking anything else... |
18th June 2010, 08:45 | #10 | Link |
Registered User
Join Date: Nov 2008
Location: Sydney, Australia
Posts: 26
|
16 bits per channel? Yes, but then what to do in AVISynth which only supports 8-bit formats?
Off the top of my head without testing (someone please test, debug, and re-post if you've used it - At the minimum I'll include it in the next release): Code:
# # Pass your double-frame-width frames through this sucker # If you only want the low or high bits, then just use the appropriate # first lines from this function, otherwise set bitshift between 1 and 7 # function 16bit_to_8bit(clip c, int bitshift) { hibits = TurnLeft().SeparateFields().SelectEven().TurnRight() lobits = TurnLeft().SeparateFields().SelectOdd().TurnRight() hibits = hibits.Levels(0,1,255, 32*bitshift,255, false) lobits = lobits.Levels(0,1,255, 0,32*bitshift-1, false) return hibits.Overlay(lobits, mode="Add") } Thoughts or suggestions from someone with 16-bit experience? Is a bit-offset between 0 and 8 a sensible approach? Should it be a scaling factor between 1 and 255? Should it be a range (between 1 and 65535) to scale to 255? Is there some other common way to deal with this? 16-bit data is probably a common enough use-case scenario to warrant direct support. I'm tempted to throw in the towel on 12-bit data though - what a nuisance! |
18th June 2010, 08:58 | #11 | Link | ||
Registered User
Join Date: Nov 2008
Location: Sydney, Australia
Posts: 26
|
Quote:
If you spot a Sashimi problem though, let me know and I'll jump all over it. Quote:
Cheers for the comments! Last edited by PitifulInsect; 18th June 2010 at 09:03. Reason: just fixing a tired brainfart typo which made no sense into something that makes more sense, (I hope). |
||
18th June 2010, 10:48 | #12 | Link | |
͡҉҉ ̵̡̢̛̗̘̙̜̝̞̟̠͇̊̋̌̍̎̏̿̿
Join Date: Feb 2009
Location: No support in PM
Posts: 712
|
Quote:
|
|
18th June 2010, 13:45 | #13 | Link | |
Compiling Encoder
Join Date: Jan 2007
Posts: 1,348
|
Quote:
the format has a file header in addition to frame headers. so in addition to the initial offset for the file header, you'll need to offset more at the start of each of frame for the frame header. for avisynth 2.5.x you'd only need need to worry about 4:2:0. for 2.6.x you'd need to also support 4:1:1, 4:2:2, and 4:4:4. you could also refer to x264 and/or ffmpeg as they have some specific demuxer/muxer related code for yuv4mpeg. |
|
18th June 2010, 19:00 | #14 | Link |
Moderator
Join Date: Nov 2001
Location: Netherlands
Posts: 6,364
|
yuv4mpeg writing is supported in ImmaWrite too. Its format:
Code:
line terminator \n = 0x0A (in C/C++) yuv4mpeg.h in mjpegtools_1.9.0rc3.zip /************************************************************************ ************************************************************************ Description of the (new!, forever?) YUV4MPEG2 stream format: STREAM consists of o one '\n' terminated STREAM-HEADER o unlimited number of FRAMEs FRAME consists of o one '\n' terminated FRAME-HEADER o "length" octets of planar YCrCb 4:2:0 image data (if frame is interlaced, then the two fields are interleaved) STREAM-HEADER consists of o string "YUV4MPEG2" o unlimited number TAGGED-FIELDs, each preceded by ' ' separator o '\n' line terminator FRAME-HEADER consists of o string "FRAME" o unlimited number of TAGGED-FIELDs, each preceded by ' ' separator o '\n' line terminator TAGGED-FIELD consists of o single ascii character tag o VALUE (which does not contain whitespace) VALUE consists of o integer (base 10 ascii representation) or o RATIO or o single ascii character or o non-whitespace ascii string RATIO consists of o numerator (integer) o ':' (a colon) o denominator (integer) The currently supported tags for the STREAM-HEADER: W - [integer] frame width, pixels, should be > 0 H - [integer] frame height, pixels, should be > 0 C - [string] chroma-subsampling/data format 420jpeg (default) 420mpeg2 420paldv 411 422 444 - non-subsampled Y'CbCr 444alpha - Y'CbCr with alpha channel (with Y' black/white point) mono - Y' plane only I - [char] interlacing: p - progressive (none) t - top-field-first b - bottom-field-first m - mixed -- see 'I' tag in frame header ? - unknown F - [ratio] frame-rate, 0:0 == unknown A - [ratio] sample (pixel) aspect ratio, 0:0 == unknown X - [character string] 'metadata' (unparsed, but passed around) The currently supported tags for the FRAME-HEADER: Ixyz - framing/sampling (required if-and-only-if stream is "Im") x: t - top-field-first T - top-field-first and repeat b - bottom-field-first B - bottom-field-first and repeat 1 - single progressive frame 2 - double progressive frame (repeat) 3 - triple progressive frame (repeat twice) y: p - progressive: fields sampled at same time i - interlaced: fields sampled at different times z: p - progressive: subsampling over whole frame i - interlaced: each field subsampled independently ? - unknown (allowed only for non-4:2:0 subsampling) X - character string 'metadata' (unparsed, but passed around) ************************************************************************ ************************************************************************/ |
19th June 2010, 00:04 | #15 | Link | ||
ангел смерти
Join Date: Nov 2004
Location: Lost
Posts: 9,556
|
Quote:
Quote:
PitifulInsect: Avisynth 2.6 is supposed to get full support for a 16-bit format, but right now it's rudimentary and unusable. I wish I was good enough at optimization to help with that. |
||
3rd July 2010, 03:23 | #16 | Link | |
typo lover
Join Date: May 2009
Posts: 595
|
Quote:
Code:
#!/bin/env python import sys colorspace = None plugin = r'c:\avisynth 2.5\plugins_32bit\' print 'input y4m file path' y4mpath = raw_input() f=open(y4mpath,'r') line1 = f.readline() line2 = f.readline() f.close() header=line1.strip('\n').split(' ') if header[0] != 'YUV4MPEG2': print 'This file is not yuv4mpeg2. Please confirm and try again.' sys.exit() for param in header: if param[0] == 'C': colorspace = 'yuv' + param[1:4] if param[0] == 'W': width = param[1:] if param[0] == 'H': height = param[1:] if param[0] == 'F': fps = param.strip("F").split(":") fps_num = fps[0] fps_den = fps[1] if colorspace == None: colorspace = 'yuv420' filepath = y4mpath.replace('/','\\') filehead = str(len(line1)) framehead = str(len(line2)) loadPlugin = 'LoadPlugin(%(plugin)s+"Sashimi.dll")\n' % vars() importavs = 'Import(%(plugin)s+"PlanarConversions.avsi")\n' % vars() y4mreader = 'RawReadPlanar("%(filepath)s", "%(colorspace)s", %(width)s, %(height)s, %(filehead)s, %(framehead)s)\n' % vars() assumefps = 'AssumeFPS(%(fps_num)s, %(fps_den)s)\n' % vars() avs = open('./y4msource.avs','w') for makeavs in [loadPlugin, importavs, y4mreader, assumefps]: avs.write(makeavs) avs.close() Please teach me when a mistake is found. Last edited by Chikuzen; 10th January 2011 at 23:33. |
|
9th January 2011, 14:58 | #17 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
Pitiful,
Could you update to include v210 format? I've started here: UPDATED TO V0.5 Code:
#v210 Reader Ver 0.5 Feb/11 by jmac698 #Read v210 quicktime files with rawreader, by jmac698 #Requires Sashimi 0.75 http://sites.google.com/site/ourenthusiasmsasham/contributions/open-source-software#TOC-Sashimi #also http://forum.doom9.org/showthread.php?p=1403600 #Masktools 2a48 http://manao4.free.fr/masktools-v2.0a48.zip #In this experiment version, the QTSource is not used... #QTSource http://www.tateu.net/software/ tested wtih Version 0.1.1 2011-02-19 #Quicktime 7: http://www.free-codecs.com/download/QT_Lite.htm qtlite 4.1 with quicktime 7.69.80.9 #FFMpegSource: http://code.google.com/p/ffmpegsource/downloads/list 2.15 #Ver 0.5 - reads all test videos in .mov given the right headersize, fixed pixel order #Ver 0.4 - reads full image in 8bit greyscale, with 10bit easily accessible #Ver 0.3 - reads fully to 8bit greyscale, now requires masktools 2a48 #Ver 0.2 - fixed wrapping bug. 83 pixels *8=664, that would be the trailing bytes #Ver 0.1 - reads only greyscale, can only read 1/3 of the size, only reads upper 6 bits, wrapped by 83 pixels #Errors and what to do #Message: Unable to Initialize Quicktime Environment # to fix: install quicktime components Global deeplasthi=blankclip(pixel_type="YV12").tweak(bright=-255,coring=false).tweak(bright=16,coring=false) Global deeplastlo=blankclip(pixel_type="YV12").tweak(bright=-255,coring=false).tweak(bright=0,coring=false) Global format=0#0=YV12, 1=YUY2, 2=RGB fn="E:\project001a\deepcolor\v210 samples\" f1="radialramp_480p29.97_16bitRGB_v210.mov"#hdr=48, 1 frame f2="radialramp_576p25_16bitRGB_v210.mov"#hdr=48, 1 frame f3="radialramp_720p23.976_16bitRGB_v210.mov"#hdr=48, 1 frame f4="radialramp_1080p29.97_16bitRGB_v210.mov"#hdr=48, 1 frame f5="testchart720p29.97_v210.mov"#hdr=48, 2 frame f6="ArriAlexa.PR422.BT709.v210.mov"#hdr=1896, 121 frames f7="bm444-480p29.97_r210.avi"#can't be loaded by ffvideosource, but should be able to be read raw f8="v210.mov"#parkjoy standard test video, hdr=20528, 3 frames fn=fn+f5 #deepread(fn)#f3, f5, f7 don't work i.e. QTSource has compatibility problems #qtinput(fn,color=2,audio=2,mode=4)#mode 0,3 opens all but no video, mode4 couldn't find vfw codec but when enabled access violation readv210(fn) #ffvideosource(fn)#f7 don't work function every(clip v, int n, int offset) {#select every n bytes horizontally with offset, works on yv12 only v w=width h=height pointresize(v,w*2,h) crop(offset*2,0,0,0).addborders(0,0,offset*2,0)#shift left offset pixels pointresize(w/n,h) } function readv210(string fn) {#reads v210 file of a given dimensions, but need to provide a header size #How to find the right header size: try starting at 48, and then count how many lines of garbage are at the top. # then multiple rows of garbage by rowsize as calculated below (1920 for 480p/576p files, 5120 for 1080p files), and add this to headersize # finally count the number of garbage pixels or shift at the left, divide by 3 and times 4, add this to headersize # i.e. headersize=0. There were 36 pixels of garbage at the top left, so headersize=36/3*4=48 # you can also increment by byte until you see picture, after that you can increment by 4 at a time to shift left by 3 pixels video=ffvideosource(fn)#opens the video however only as 8 bit, so we'll use the proper video properties from this to read raw w=video.width h=video.height f=video.framecount multiple48=w%48==0#is width a multiple of 48? If false, there's some padding at the end of each row rowsize=ceil(w*8/3/128.0)*128#rows are padded to the nearest 48 pixels which is 128 bytes in v210 format hdr=w==1920?48:w==1280?48:w==720?48:48#These only work for some test files and can be considered the minimum header base=RawReader(fn, format="y8", width=rowsize, height=h, numframes=f, filehead=hdr, framehead=0) #a 1080p v210 (f8) file needed 5120*1080=5529600 bytes per frame, 3 frames, and header size=20528, trailer=664. Filesize was 16609992 #a 1080p v210 (f4) file needed 5120*1080=5529600 bytes per frame, 1 frame, and header size=48, trailer=15880. Filesize was 5545528 #a 720p v210 (f3) file needed 3456*720=2488320 bytes per frame, 1 frame, and header size=48, trailer=16762 Filesize was 2505130 #a 480p v210 (f1) file needed 1920*480=921600 bytes per frame, 1 frame, and header size=48, trailer=15880 Filesize was 937528 #byte3 byte2 byte1 byte0 #xx987654 32109876 54321098 76543210 # Cr0 Y0 Cb0 #byte3 byte2 byte1 byte0 #xx987654 32109876 54321098 76543210 # Y2 Cb1 Y1 high4=base.every(4,2).every(2,0)#byte2, first row in diagram above or 3rd byte every 8 (so every(8,2) would work too), Y0 high 4 bits (in low 4 bits) low6=base.every(4,1).every(2,0) mt_lutxy(low6,high4,yexpr="y 15 &u 4 << x 4 >> +")#x 4 >> y 4 << + y0=last high2=base.every(4,1).every(2,1) low8=base.every(4,0).every(2,1) mt_lutxy(low8,high2,yexpr="y 3 &u 6 << x 2 >> +")#x 4 >> y 4 << + y1=last high6=base.every(4,3).every(2,1)#The 3rd byte in every 32bit word, and the 2nd word every 2 words, which is Y2 and Y5 pixels low4=base.every(4,2).every(2,1) mt_lutxy(low4,high6,yexpr="x 6 >> y 2 << +") y2=last weave3h(y0,y1,y2) crop(0,0,-(last.width-w),0)#dimensions that are padded need to get cropped at the right, e.g. width=1280 is read at 1296 then cropped } function weave3h(clip a, clip b, clip c) {#horizontally weave 3 clips a=a.turnright b=b.turnright c=c.turnright interleave(a,b,a,c)#0 1 2 3->01 23->0213->213 or abc assumefieldbased assumetff weave assumefieldbased assumetff weave pointresize(width,height*3/4)#deletes every 4th line offset 0 turnleft } function getlowbyte(clip vround, clip vtrunc) {#vround may have some pixels +1 compared to vtrunc; put the difference in the high bit Overlay(vround,vtrunc, mode="Subtract", pc_range=true)#e.g. y:129-128=1, 128-128=0. u,v are 128 or 129 coloryuv(gain_y=127*256,off_u=-128,off_v=-128) coloryuv(gain_u=127*256,gain_v=127*256) } function deepread(string fn) { global deeplasthi=qtinput(fn,color=2,audio=2,mode=1,raw="v210") global format=IsYUY2(deeplasthi)?1:0 qtinput(fn,color=2,audio=2,mode=1,raw="v210",dither=1)#9th bit #low bit to high bit getlowbyte(last,deeplasthi) global deeplastlo=last deeplasthi } Last edited by jmac698; 25th February 2011 at 08:36. Reason: Updated to v0.5 |
24th February 2011, 14:39 | #18 | Link |
Registered User
Join Date: Nov 2008
Location: Sydney, Australia
Posts: 26
|
Hey all! Apologies for the extended absence.
A friend suggested directly reading gzipped files, since gzip is also GPLv2, and it sounded like a good idea - for some synthetic sequences, you can save a lot of diskspace working directly with compressed files. Unfortunately I found that the interface to gzip is more than a little hairy, I fought a tonne of compatibility problems, and when I got a debug-only version working I discovered that the caching performance was appalling since reading and seeking within the file requires decompressing big big chunks or even the whole thing to RAM! If that sounds like and exhasperatedly long sentence, there's a reason! So yeah, development stalled, and all of your wonderful comments went unanswered. Sorry! I'm putting the idea of live compression aside for now - just use XVid or AVC (.h264) lossless if you need something in your workflow :-) On to the updates!
Meantime: Version 0.75 posted! See top of page. Thanks all! More updates soon I hope. |
24th February 2011, 17:08 | #19 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
|
|
24th February 2011, 23:22 | #20 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
Yes, I've extracted the weave3, I've had to do this myself a few months ago, which also lead me to discover bug... err, issue with pointresize; the implementation is different for each colorspace, the point which is thrown away in downsizing is different.
Code:
w = width(Clip1) h = height(Clip1) Pair1 = Interleave(Clip1, Clip3).Weave Pair2 = Interleave(Clip2, Clip3).Weave QuadHeight = Interleave(Pair1, Pair2).Weave # Line sequence is Clip1, Clip2, Clip3, Clip3, repeating. TripleHeight = PointResize(QuadHeight, w, h*3) The full quicktime spec is huge; but getting a visible image is easy, just skip some bytes and interpret the packed pixel format. Some people posted samples in my other thread. http://forum.doom9.org/showthread.ph...07#post1467907 |
Thread Tools | Search this Thread |
Display Modes | |
|
|