PDA

View Full Version : Behaviour of SelectRangeEvery(audio=false)


Gavino
28th August 2009, 18:03
According to the documentation, SelectRangeEvery (http://avisynth.org/mediawiki/SelectRangeEvery) should return the original audio when audio=false.

The code in SelectRangeEvery::GetAudio directly returns child->GetAudio() in this case, but does not take into account that the value of child has been altered in the constructor.
AVSValue trimargs[3] = { _child, _offset, 0};
PClip c = env->Invoke("Trim",AVSValue(trimargs,3)).AsClip();
child = c;
The result is that the first offset frames worth of audio are missing from the output.
Is this intentional? It doesn't seem right to me. :confused:

IanB
29th August 2009, 00:50
Yes, it is a bit borked, you also forgot to mention this as part of the borking ;)if (vi.HasAudio()) {
vi.num_audio_samples = vi.AudioSamplesFromFrames(vi.num_frames);
}Thus you also loose the end of the audio stream.

IanB
3rd February 2010, 22:13
Taking frames from a source filter in an irregular order can be problematic when the source filter struggles to be frame exact.

AviSource() uses brute force, returning to the prior keyframe, then reading forward to the requested frame. However some packing arrangements used with mpeg4 etc can still cause problems. All keyframe formats like DV or Huffyuv have no problem.

Mpeg2Source() has an index from DGDecode, so it has an easy ride. But there is a fairly large performance penalty for non-linear access due to state resetting at each seek.

DirectShowSource() uses the DirectShow timecodes and is entirely dependant on the behaviour of the media splitter and decoder. Very often non-linear access patterns just do not work. If desperate you can set SeekZero=True, this will brute force read all the frames when seeking forward and return to frame zero then brute force forwards when seeking backwards.

FFMpegSource() also creates an index, but not all the internal paths are cooperative when it comes to proper random access.

This is the algorithm mapping frame number in to frame number out.PVideoFrame __stdcall SelectRangeEvery::GetFrame(int n, IScriptEnvironment* env)
{
return child->GetFrame((n/length)*every+(n%length), env);
}
Abusing ChangeFPS(Last, True) as a limited linear order filter may provide enough protection for your source filter, but it only has a 10 frame window.