Log in

View Full Version : TWriteAVI (Update Concluded).


StainlessS
18th October 2015, 07:34
Hi guys.

I've been playing with TWriteAVI and managed to get it writing audio despite not having much Idea what I'm doing.
Will only write 1 or 2 channel 16 bits audio.

I have also implemented a function to try to force output without playing clip all the way through, but (as I sort of anticipated), I am hitting some kind of threading problem (I think, I know next to nothing about windows programming and even less about thread related issues).

Here is the function to force output:

AVSValue __cdecl TWA_ForceProcess(AVSValue args, void* user_data, IScriptEnvironment* env) {
char *myName="TWA_ForceProcess: ";
if(!args[0].IsClip()) env->ThrowError("%sMust have a clip",myName);
PClip child = args[0].AsClip(); // Clip
const VideoInfo &vi = child->GetVideoInfo();
const int bfsz = int(vi.AudioSamplesFromFrames(1) + 16); // BUG BUG BUG
BYTE *bf = new BYTE[bfsz];
if(bf==NULL) env->ThrowError("%sCannot allocate audio buffer",myName);
const int frames= vi.num_frames;
const int start = min(max(args[1].AsInt(0),0),frames-1);
const int end = max(min(args[2].AsInt(frames-1),frames-1),start);
for(int n=start;n<=end;++n) {
__int64 s = vi.AudioSamplesFromFrames(n);
__int64 e = vi.AudioSamplesFromFrames(n+1)-1;
child->GetAudio((void*)bf, s, e-s+1, env); // Force 1 video frame worth of audio
PVideoFrame src = child->GetFrame(n,env); // Force decoding. MUST assign to PVideoFrame
}
delete [] bf;
return 0;
}


It produces a Audio Samples 0-1763 could not be read in the source. The file may be corrupted.
message on the first frame.

I suspect that the message is bogus and down to the suspected threading type problem, but have exactly no idea where to go next.

Here is the hacked TWriteAVI source together with full VS 2008 project files. EDIT: LINK REMOVED

Any assistance greatly appreciated.

Update now posted here:- http://forum.doom9.org/showthread.php?t=172837

StainlessS
18th October 2015, 08:04
OK guys, I'de made a boo-boo

Problem was actually in the force function


AVSValue __cdecl TWA_ForceProcess(AVSValue args, void* user_data, IScriptEnvironment* env) {
char *myName="TWA_ForceProcess: ";
if(!args[0].IsClip()) env->ThrowError("%sMust have a clip",myName);
PClip child = args[0].AsClip(); // Clip
const VideoInfo &vi = child->GetVideoInfo();
const int frames= vi.num_frames;
const int start = min(max(args[1].AsInt(0),0),frames-1);
const int end = max(min(args[2].AsInt(frames-1),frames-1),start);
int bfsz = 0;
BYTE *bf = NULL;
bool HasAudio =vi.HasAudio();
if(HasAudio) {
bfsz = int(vi.BytesFromAudioSamples(vi.AudioSamplesFromFrames(1))+16);
bf = new BYTE[bfsz];
if(bf==NULL) env->ThrowError("%sCannot allocate audio buffer",myName);
}
for(int n=start;n<=end;++n) {
if(HasAudio) {
__int64 s = vi.AudioSamplesFromFrames(n);
__int64 e = vi.AudioSamplesFromFrames(n+1)-1;
child->GetAudio((void*)bf, s, e-s+1, env); // Force 1 video frame worth of audio
}
PVideoFrame src = child->GetFrame(n,env); // Force decoding. MUST assign to PVideoFrame
}
if(bf!=NULL) {delete [] bf;}
return 0;
}


Fixed line in BLUE (EDIT: Added HasAudio guard, zip updated).

Working properley now, Fixed source + VS2008 project files here:- EDIT: LINK REMOVED

Guess I can get some sleep now [08:09AM], PROBLEM SOLVED.

EDIT: Can be used like so:

Avisource("E:\V\StarWars.avi").Trim(0,-1000)

# TWriteAvi", "c[fname]s[overwrite]b[showAll]b[fourcc]s"
FN="OUT.AVI"
#FourCC = "ULY0"
FourCC = ""
TwriteAvi(Last,FN,Overwrite=true,FourCC=FourCC)
TWA_ForceProcess(Last)

Return MessageClip("DONE")

vampiredom
19th October 2015, 18:09
Thank you so much for this, StainlessS.

StainlessS
19th October 2015, 19:05
You're welcome you old blood sucker :)

I'll try to implement Float audio too but have no idea what to do about more than two channels, and cannot test as I have only
stereo equipment (and as hinted at in PM, have no interest in cluttering up the place with multi-speaker system).

StainlessS
20th October 2015, 08:58
Hey Count AlucarD,

Can you get your teeth into this:-EDIT: LINK REMOVED

I think I've pretty much implemented OK for all format audio, 8 -> Float.
Will output a little info to debugview.

tw.avs

Avisource("E:\V\StarWars.avi").Trim(0,-1000)

# TWriteAvi, "c[fname]s[overwrite]b[showAll]b[fourcc]s[dwChannelMask]i"
FN="OUT.AVI"
FourCC = "ULY0"
#FourCC = ""
dwChannelMask=-1 # DEFAULT = -1 (No Override, Use standard mapping as for v2.6 OPT_dwChannelMask)
# 0 = Non Located ie multiple MONAURAL channels.
# Otherwise, need 1 bit set for each valid channel, see dwChannelMask flags at below link.
# https://msdn.microsoft.com/en-us/library/windows/desktop/dd390971%28v=vs.85%29.aspx
# EDIT: Or in brief defaults here on Wiki:- http://avisynth.nl/index.php/Internal_functions#OPT_dwChannelMask

ConvertAudioToFloat
#ConvertAudioTo32Bit
#ConvertAudioTo8Bit

TwriteAvi(Last,FN,Overwrite=true,FourCC=FourCC,dwChannelMask=dwChannelMask)
TWA_ForceProcess(Last)

#return Last.ConvertAudioTo16bit() # If NOT using TWA_ForceProcess : Avoid problems in player
Return MessageClip("DONE")


Source + VS 2008 project files in zip.

EDIT: If you get the chance can you check it out with everything up to eg 7.1 surround Float.
EDIT: I removed the index arg (or whatever it was called), no real point in it as HCEnc does its own lossless rendering
since just after it was implemented (unless someone else uses it ?, I could put it back [or rename plug].)
EDIT: Removed TWA_ForceProcess start and end frame args, would interfere with format written by TWriteAVI (header info).
EDIT: More dwChannelMask stuff here:- https://msdn.microsoft.com/en-us/library/windows/hardware/dn653308%28v=vs.85%29.aspx

EDIT: dwChannelMask stuff

Default channel Mappings:-
0x00004, // 1 -- -- Cf
0x00003, // 2 Lf Rf
0x00007, // 3 Lf Rf Cf
0x00033, // 4 Lf Rf -- -- Lr Rr
0x00037, // 5 Lf Rf Cf -- Lr Rr
0x0003F, // 5.1 Lf Rf Cf Sw Lr Rr
0x0013F, // 6.1 Lf Rf Cf Sw Lr Rr -- -- Cr
0x0063F, // 7.1 Lf Rf Cf Sw Lr Rr -- -- -- Ls Rs

Speaker_Location:-
SPEAKER_FRONT_LEFT 0x1
SPEAKER_FRONT_RIGHT 0x2
SPEAKER_FRONT_CENTER 0x4
SPEAKER_LOW_FREQUENCY 0x8 # EDIT: shown above as Sw (Sub Woofer)
SPEAKER_BACK_LEFT 0x10
SPEAKER_BACK_RIGHT 0x20
SPEAKER_FRONT_LEFT_OF_CENTER 0x40
SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
SPEAKER_BACK_CENTER 0x100
SPEAKER_SIDE_LEFT 0x200
SPEAKER_SIDE_RIGHT 0x400

Not used by Default Mappings:
SPEAKER_TOP_CENTER 0x800
SPEAKER_TOP_FRONT_LEFT 0x1000
SPEAKER_TOP_FRONT_CENTER 0x2000
SPEAKER_TOP_FRONT_RIGHT 0x4000
SPEAKER_TOP_BACK_LEFT 0x8000
SPEAKER_TOP_BACK_CENTER 0x10000
SPEAKER_TOP_BACK_RIGHT 0x20000

StainlessS
22nd October 2015, 01:08
Bit of an update here (Avisynth v2.6 only):-

Added support for all colorspaces except for YV411 (will not be supported).
EDIT: No-one else seems to support YV411 either, no standard FOURCC (that works) found.

Zip for Avisynth v2.6 only, will add 2.5 dll when its nearer completion.

Usage

Function TWriteAvi(clip c,String filename,bool "overwrite"=false,bool "showall"=false,string "fourcc"="",int "dwChannelMask"=-1)

c, Video clip with optional audio. ALL valid colorspaces with exception of YV411.
Filename: NOT optional. Output filename.
Overwrite: Fails on existing unless overwrite==True.
Showall: Default false. Shows all codecs, not just ones supporting your clip colorspace.
Fourcc: Default "". Characters UPPER case fourCC code for codec, eg "ULY0" for YV12 UT_Video rec601.
dwChannelMask: Default -1.
-1 = No Override, Use standard mapping as for v2.6 OPT_dwChannelMask.
0 = Non Located ie multiple MONAURAL channels.
Otherwise, need 1 bit set for each valid channel, see dwChannelMask flags at below link.
https://msdn.microsoft.com/en-us/library/windows/desktop/dd390971%28v=vs.85%29.aspx
Or in brief defaults here on Wiki:- http://avisynth.nl/index.php/Internal_functions#OPT_dwChannelMask
Or in full, https://msdn.microsoft.com/en-us/library/windows/hardware/dn653308%28v=vs.85%29.aspx

Removed old Idxname arg.
Writes clip to filename returning original clip.
Audio 8, 16, 24 and 32 bit, also Float. Up to 8 channels (7.1), written as uncompressed PCM or IEEE 32 bit Float format.

TWA_ForceProcess(clip c)
Force Process clip c, ie read from first to last frame, for TWriteAVI writes the AVI file (Video + Audio) without having to play clip.

minor edits:

tw.avs

Avisource("E:\V\StarWars.avi").Trim(35000,-1000)
################### YV411 NOT SUPPORTED IN TWriteAVI
#ConvertToRGB24
#ConvertToRGB32
#ConvertToYUY2
#ConvertToYV12
#ConvertToY8
#ConvertToYV16
ConvertToYV24
###################
# TWriteAvi(clip c,String filename,bool "overwrite"=false,bool "showall"=false,string "fourcc"="",int "dwChannelMask"=-1)
FN="OUT.AVI"
#FourCC = "ULY0" # UT_Video YV12 rec601
FourCC = ""
dwChannelMask=-1 # DEFAULT = -1 (No Override, Use standard mapping as for v2.6 OPT_dwChannelMask)
# 0 = Non Located ie multiple MONAURAL channels.
# Otherwise, need 1 bit set for each valid channel, see dwChannelMask flags at below link.
# https://msdn.microsoft.com/en-us/library/windows/desktop/dd390971%28v=vs.85%29.aspx
# Or in brief defaults here on Wiki:- http://avisynth.nl/index.php/Internal_functions#OPT_dwChannelMask
# Or in full, https://msdn.microsoft.com/en-us/library/windows/hardware/dn653308%28v=vs.85%29.aspx

#ConvertAudioTo8Bit
#ConvertAudioTo16Bit
#ConvertAudioTo24Bit
#ConvertAudioTo32Bit
ConvertAudioToFloat

TwriteAvi(Last,FN,Overwrite=true,FourCC=FourCC,dwChannelMask=dwChannelMask)
TWA_ForceProcess(Last)
Last=0 # Call clip destructor and close input and output clips, (else will be in-use when attempt re-open)
Avisource(FN) # Open force written clip
Return Last.Info.ConvertToRGB32.ConvertAudioTo16bit() # Avoid problems in player
Return MessageClip("DONE") # Without view clip, only TWA_ForceProcess usage.

minor edits:

EDIT: LINK REMOVED

v2.6 dll, + source + VS 2008 project files.

EDIT: See previous post edit for audio channel mappings.

StainlessS
23rd October 2015, 13:36
You can use this script to verify the output AVI with MPC-HC player.

Global OPT_UseWaveExtensible = true # If more than 2 channels set true. TWiteAVI always uses WaveExtensible for FLOAT audio
Global OPT_AllowFloatAudio = true # Must be set true to play FLOAT in eg Media Player Classic - Home Cinema

FN="OUT.AVI" # Written by TWriteAVI script YV24 and Float audio
#Avisource(FN)
DirectShowSource(FN,Pixel_Type="YV24")
Return Last.Info #.ConvertToRGB32 #.ConvertAudioTo16bit() # MPC-HC (recent versions) play YV24 and Float Audio OK.

# See properties in MPC-HC to verify what it is playing



EDIT: By the way, VirtualDub recent, dont play Float audio.

EDIT: Strangely, OPT_AllowFloatAudio dont seem to affect MPC-HC it always get float, but it does affect Vdub which gets 16 bit when false.
Also, I was going to try to output just standard WAVEFORMEX for 24 and 32 bit and float where channels <= 2, but VDUB cannot
play 24 and 32 bit PCM in that mode, it loads but gets stuck on frame 0 when trying to play, so I'm leaving it as it was, when bits >16 or float, or
channels > 2 then will use WAVE_FORMAT_EXTENSIBLE, where VDub can at least play 24 and 32 bit PCM (but still not FLOAT).

Wilbert
23rd October 2015, 22:42
EDIT: Strangely, OPT_AllowFloatAudio dont seem to affect MPC-HC it always get float
How/where do you see that it gets float?

StainlessS
23rd October 2015, 23:32
Wilbert, have reverted to uploaded dll for this test.
Using scripts almost identical to already posted ones

Script to create OUT.AVI in current directory (changed to YV12)

Avisource("E:\V\StarWars.avi").Trim(35000,-1000)
################### YV411 NOT SUPPORTED IN TWriteAVI
#ConvertToRGB24
#ConvertToRGB32
#ConvertToYUY2
ConvertToYV12
#ConvertToY8
#ConvertToYV16
#ConvertToYV24
###################
# TWriteAvi(clip c,String filename,bool "overwrite"=false,bool "showall"=false,string "fourcc"="",int "dwChannelMask"=-1)
FN="OUT.AVI"
#FourCC = "ULY0" # UT_Video YV12 rec601
FourCC = ""
dwChannelMask=-1 # DEFAULT = -1 (No Override, Use standard mapping as for v2.6 OPT_dwChannelMask)
# 0 = Non Located ie multiple MONAURAL channels.
# Otherwise, need 1 bit set for each valid channel, see dwChannelMask flags at below link.
# https://msdn.microsoft.com/en-us/library/windows/desktop/dd390971%28v=vs.85%29.aspx
# Or in brief defaults here on Wiki:- http://avisynth.nl/index.php/Internal_functions#OPT_dwChannelMask
# Or in full, https://msdn.microsoft.com/en-us/library/windows/hardware/dn653308%28v=vs.85%29.aspx

#ConvertAudioTo8Bit
#ConvertAudioTo16Bit
#ConvertAudioTo24Bit
#ConvertAudioTo32Bit
ConvertAudioToFloat

TwriteAvi(Last,FN,Overwrite=true,FourCC=FourCC,dwChannelMask=dwChannelMask)
TWA_ForceProcess(Last)
Last=0 # Call clip destructor and close input and output clips, (else will be in-use when attempt re-open)
Avisource(FN) # Open force written clip
Return Last.Info.ConvertToRGB32.ConvertAudioTo16bit() # Avoid problems in player
Return MessageClip("DONE")


Script to play the OUT.AVI in current directory (set both OPT_ options to false)

Global OPT_UseWaveExtensible = False
Global OPT_AllowFloatAudio = False

FN="OUT.AVI" # Written by TWriteAVI script YV12 and Float audio
Avisource(FN)
#DirectShowSource(FN,Pixel_Type="YV12")
Return Last.Info #.ConvertToRGB32 #.ConvertAudioTo16bit() # MPC-HC (recent versions) play YV24 and Float Audio OK.

# See properties in MPC-HC to verify what it is playing


Play in MPC-HC and right click on window and select Properties.

Load same script into VDub (current) and it shows 16 bit.

EDIT: For first script just click on No Recompression in dialog box.

EDIT: By the way, ignore the info on frame, that is of course rendered on-frame within Avisynth and before being
delivered to MPC-HC or VDub (where it says is Float).

EDIT: No idea why, but PotPlayer and GOM Player both show 16 bit, maybe MPC-HC does some scanning of original
clip or something, very curious.

StainlessS
31st October 2015, 18:22
Update, TAKE 4: EDIT: Moved link to current version to bottom of first post.
Zip contains v2.6 dll, + source.

Now added TWriteWAV().



Function TWriteAvi(clip c,String filename,bool "overwrite"=false,bool "showall"=false,string "fourcc"="",int "dwChannelMask"=-1)

c, Video clip with optional audio. ALL valid colorspaces with exception of YV411.
Filename: NOT optional. Output filename.
Overwrite: Fails on existing unless overwrite==True.
Showall: Default false. Shows all codecs, not just ones supporting your clip colorspace.
Fourcc: Default "". Characters UPPER case (usually) fourCC code for codec, eg "ULY0" for YV12 UT_Video rec601.
dwChannelMask: Default -1.
-1 = No Override, Use standard mapping as for v2.6 OPT_dwChannelMask.
0 = Non Located ie multiple MONAURAL channels.
Otherwise, need 1 bit set for each valid channel, see dwChannelMask flags at below link.
https://msdn.microsoft.com/en-us/library/windows/desktop/dd390971%28v=vs.85%29.aspx
Or in brief defaults here on Wiki:- http://avisynth.nl/index.php/Internal_functions#OPT_dwChannelMask
Or in full, https://msdn.microsoft.com/en-us/library/windows/hardware/dn653308%28v=vs.85%29.aspx

Removed old Idxname arg.
Writes clip to filename returning original clip.
Audio 8, 16, 24 and 32 bit, also Float. Up to 8 channels (7.1), written as uncompressed PCM or IEEE 32 bit Float format.
Will auto close on last frame, will write only strictly sequential frames (ie no jumping about).

#######

ForceProcessAVI(clip c)
Force Process clip c, ie read from first to last frame, for TWriteAVI writes the AVI file (Video + Audio) without having to play clip.

##############

Function TWriteWAV(clip c,String filename,bool "overwrite"=false,int "dwChannelMask"=-1)
c, clip with audio.
Filename: NOT optional. Output filename.
Overwrite: Fails on existing unless overwrite==True.
dwChannelMask: Default -1.
-1 = No Override, Use standard mapping as for v2.6 OPT_dwChannelMask.
0 = Non Located ie multiple MONAURAL channels.
Otherwise, need 1 bit set for each valid channel.

Writes audio from clip to filename returning original clip.
Audio 8, 16, 24 and 32 bit, also Float. Up to 8 channels (7.1), written as uncompressed PCM or IEEE 32 bit Float format.
Will auto close on last frame (EDIT: sample), will write only strictly sequential audio samples (ie no jumping about).

#######

ForceProcessWAV(clip c)
Force Process clip c audio only, ie read from first to last audio sample, for TWriteWAV writes the WAV file (Audio) without having to play clip.


TWriteAVI.avs

Avisource("E:\V\StarWars.avi").Trim(35000,-(60*25))
################### YV411 NOT SUPPORTED IN TWriteAVI
#ConvertToRGB24
#ConvertToRGB32
#ConvertToYUY2
#ConvertToYV12
#ConvertToY8
#ConvertToYV16
ConvertToYV24
###################
# TWriteAvi(clip c,String filename,bool "overwrite"=false,bool "showall"=false,string "fourcc"="",int "dwChannelMask"=-1)
FN="OUT.AVI"
#FourCC = "ULY0" # UT_Video YV12 rec601
FourCC = ""
dwChannelMask=-1 # DEFAULT = -1 (No Override, Use standard mapping as for v2.6 OPT_dwChannelMask)
# 0 = Non Located ie multiple MONAURAL channels.
# Otherwise, need 1 bit set for each valid channel, see dwChannelMask flags at below link.
# https://msdn.microsoft.com/en-us/library/windows/desktop/dd390971%28v=vs.85%29.aspx
# Or in brief defaults here on Wiki:- http://avisynth.nl/index.php/Internal_functions#OPT_dwChannelMask
# Or in full, https://msdn.microsoft.com/en-us/library/windows/hardware/dn653308%28v=vs.85%29.aspx

#ConvertAudioTo8Bit
#ConvertAudioTo16Bit
ConvertAudioTo24Bit
#ConvertAudioTo32Bit
#ConvertAudioToFloat
#return last
TwriteAvi(Last,FN,Overwrite=true,FourCC=FourCC,dwChannelMask=dwChannelMask) # will auto close on last frame, will write only striclty sequetial frames
ForceProcessAVI(Last)
Avisource(FN) # Open force written clip
Return Last.Info.ConvertToRGB32.ConvertAudioTo16bit() # Avoid problems in player
Return MessageClip("DONE") # Without view clip, only TWA_ForceProcess usage.


TWriteWAV.avs

Avisource("E:\V\StarWars.avi").Trim(35000,-(60*25))
################### YV411 NOT SUPPORTED IN TWriteAVI
#ConvertToRGB24
#ConvertToRGB32
#ConvertToYUY2
ConvertToYV12
#ConvertToY8
#ConvertToYV16
#ConvertToYV24
###################
# TWriteWAV(clip c,String filename,bool "overwrite"=false,int "dwChannelMask"=-1)
FN="OUT.WAV"
dwChannelMask=-1 # DEFAULT = -1 (No Override, Use standard mapping as for v2.6 OPT_dwChannelMask)
# 0 = Non Located ie multiple MONAURAL channels.
# Otherwise, need 1 bit set for each valid channel, see dwChannelMask flags at below link.
# https://msdn.microsoft.com/en-us/library/windows/desktop/dd390971%28v=vs.85%29.aspx
# Or in brief defaults here on Wiki:- http://avisynth.nl/index.php/Internal_functions#OPT_dwChannelMask
# Or in full, https://msdn.microsoft.com/en-us/library/windows/hardware/dn653308%28v=vs.85%29.aspx

#ConvertAudioTo8Bit
#ConvertAudioTo16Bit
ConvertAudioTo24Bit
#ConvertAudioTo32Bit
#ConvertAudioToFloat
#return last
Video=Last
TwriteWAV(Last,FN,Overwrite=true,dwChannelMask=dwChannelMask)
ForceProcessWAV(Last)
AUD=Wavsource(FN) # Open force written audio
AudioDub(Video,AUD) # Use written Audio
Return Last.Info.ConvertToRGB32.ConvertAudioTo16bit() # Avoid problems in player
Return MessageClip("DONE") # Without view clip, only TWA_ForceProcess usage.


PlayAVI.avs

FN="OUT.AVI" # Written by TWriteAVI script YV24 and Float audio
Avisource(FN)
#DirectShowSource(FN,Pixel_Type="YV24")
STAT=true
Global OPT_UseWaveExtensible = STAT # If more than 2 channels set true. TWiteAVI always uses WaveExtensible for FLOAT audio
Global OPT_AllowFloatAudio = STAT # Must be set true to play in eg Media Player Classic - Home Cinema

Return Last #.Info.ConvertToRGB32.ConvertAudioTo16bit() # MPC-HC (recent versions) play YV24 and Float Audio OK.

# See properties in MPC-HC to verify what it is playing

vampiredom
1st November 2015, 07:54
You rock, StainlessS.

StainlessS
7th November 2015, 22:54
Work concluded, and posted in Usage, here:- http://forum.doom9.org/showthread.php?t=172837