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.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Development

Reply
 
Thread Tools Search this Thread Display Modes
Old 12th August 2003, 08:24   #1  |  Link
zettai
Fascinated Lurker
 
zettai's Avatar
 
Join Date: Feb 2002
Location: Durham, UK
Posts: 243
New Function Request - Telecine()

Hi All,

Currently it is very simple to do a 23,976fps to 29.97fps conversion using seperatefields, selectevery and weave.

24 FPS with the field shuffle will make a 30 FPS video...
However, what if we want 29.97 but don't want to touch our audio stream and don't want a desynch?


every 100 seconds there is 2997 frames (29.97fps)
or every 100 seconds there is 3000 frames (30fps)
so... every 3000 frames, we have to remove 3... or in 1000 remove 1

so we have a 999 frame block of stuff... or a 995 + 4 block (this will be important in a second)

when we go from 24-30 we are going from 4-5 (995 is devisable by 5 ^_^)

so if we Telecine 796 frames, and leave 4 frames alone... 800 frames, which normally would translate to 1000 frames, instead translates to 999 frames... perfect....

now how to do this smoothly (the easy method would just to Telecine the first 796, then copy the last 4)

the longer than you can smooth over the frame transitions... the better the Telecine process is going to be
(which is why AA AB BC CD DD is better than AA BB BC CD DD )
So... what if the "solid" frames were 197, 398, 599, 800 out of every 800 frame block...?

So, in short the idea is to telecine every 196 frames, then copy one, then telecine 196, then copy one, then telecine 196, then copy one... etc...

the "solid" frames as i refered to them are the copied frames...

so technically this could be accomplished with

AssumeFrameBased()
SeparateFields()
a very long SelectEvery command ^_^ with 246 field settings
Weave()
AssumeFPS(29.97) [not sure if it would be required with selectevery]

However, a selectevery that big will get thrown out by avisynth.



A better option would be to have a plugin such as

Telecine(clip,fieldorder,outputframerate)

where possible output framerates are 25, 29.97 and 30 [and have a conditional telecine pattern for each common mapping]


Thoughts?
zettai is offline   Reply With Quote
Old 12th August 2003, 09:10   #2  |  Link
stickboy
AviSynth Enthusiast
 
Join Date: Jul 2002
Location: California, U.S.
Posts: 1,267
Is ChangeFPS insufficient for duplicating frames as needed to adjust the framerate?
stickboy is offline   Reply With Quote
Old 12th August 2003, 09:19   #3  |  Link
zettai
Fascinated Lurker
 
zettai's Avatar
 
Join Date: Feb 2002
Location: Durham, UK
Posts: 243
ChangeFPS isn't what we want here.

The aim is to telecine the footage so that it ends up being 29.97fps - ChangeFPS would reduce 30fps to 29.97fps by removing frames which is what we want to avoid.... especially with telecinied footage. You could change to 23.976 at the beginning but again that's losing a frame where you honestly don't need to.

We're not doing any frame duplication either, we're just choosing to NOT telecine 4 frames in every 800.

It's a pretty simple idea but can't be done as far as I can tell with avisynth scripting at the moment (or at least, can't be done with one script that will work for every video file... you can do it with trim but it's nasty).
zettai is offline   Reply With Quote
Old 12th August 2003, 10:24   #4  |  Link
stickboy
AviSynth Enthusiast
 
Join Date: Jul 2002
Location: California, U.S.
Posts: 1,267
Ah, sorry, I misread. I think I see what you mean now.

How did you come up with the 197, 398, 500, and 800 values? (Is that right? If you're counting from 0, frame 800 is the 801st frame and isn't part of the 800-frame block...)

Hmm... if only there were an ApplyRangeEvery function...

Last edited by stickboy; 12th August 2003 at 10:28.
stickboy is offline   Reply With Quote
Old 12th August 2003, 10:43   #5  |  Link
zettai
Fascinated Lurker
 
zettai's Avatar
 
Join Date: Feb 2002
Location: Durham, UK
Posts: 243
Now it's morning I'm not sure how I came to that number.

Maybe it's 199 frames not 196.... why would I think it was 196?

Hmm, way to confuse myself
zettai is offline   Reply With Quote
Old 12th August 2003, 10:52   #6  |  Link
zettai
Fascinated Lurker
 
zettai's Avatar
 
Join Date: Feb 2002
Location: Durham, UK
Posts: 243
AH! Yes, I know where I got 196.

It's because you generally take 4 frames and make them into 5 when you telecine, so you have to work in 4 frame sections.

199 isn't divisable by 4.

so you do

1-4 Telecine to 1-5
4-8 Telecine to 6-10
9-12.....
192-196 Telecine to 240-245
197 copy to 246


you repeat this 4 times. When you've done it 4 times you get to frame 985. You then add on the next 3 sequences of 5 telecined frames to get to 999.

Then you reset and start again.

So, yeah, complicated ^_^
zettai is offline   Reply With Quote
Old 12th August 2003, 12:12   #7  |  Link
stickboy
AviSynth Enthusiast
 
Join Date: Jul 2002
Location: California, U.S.
Posts: 1,267
I believe your math is a little off... if you remove every 196th frame, you'll remove 5 frames of every 800. (If you neglect to remove the fifth frame, one of the segments will not be a multiple of 4.)

I think it should be:
Code:
keep     telecine
   0     [  1, 200]
 201     [202, 401]
 402     [403, 602]
 603     [604, 799]
Anyhow, here's a function I whipped up that I believe does what you want (24 -> 29.97). I'm really sleepy, so the code is rather crude, isn't well-tested, and doesn't perform any error-checking:
Code:
function min(int m, int n)
{
    return (m < n) ? m : n
}


function Telecine(clip c)
{
    assert(c.IsFrameBased(), "Telecine: clip must be frame-based")

    # we need to handle the case of a null-clip manually;
    # otherwise, SelectEvery(...) will generate unwanted blank frames
    return (c.FrameCount() == 0)
    \      ? c.AssumeFPS(c.FrameRate() * 5.0 / 4.0)
    \      : c.ComplementParity().DoubleWeave().SelectEvery(8, 0, 2, 3, 5, 6)
}


function NewTelecineHelper(clip c, int iterLeft)
{
    assert(iterLeft > 0, "NewTelecineHelper: invalid <iterLeft> value")
    iterLeft = iterLeft - 1

    start = iterLeft * 800
    end = min(c.FrameCount(), (iterLeft + 1) * 800)

    seg = c.Trim2(start, length=800)

    seg1 = seg.Trim2(  0, length=1) + seg.Trim2(  1, 201).Telecine()
    seg2 = seg.Trim2(201, length=1) + seg.Trim2(202, 402).Telecine()
    seg3 = seg.Trim2(402, length=1) + seg.Trim2(403, 603).Telecine()
    seg4 = seg.Trim2(603, length=1) + seg.Trim2(604     ).Telecine()

    c = c.Trim2(0, start) + seg1 + seg2 + seg3 + seg4 + c.Trim2(end)

    return (iterLeft == 0)
    \      ? c
    \      : NewTelecineHelper(c, iterLeft)
}


function NewTelecine(clip c)
{
    assert(c.FrameCount() > 0, "NewTelecine: input clip must have at least one frame")
    c.NewTelecineHelper(Ceil(c.FrameCount() / 800.0)).AssumeFPS(29.97)
    return AudioDub(last, c)
}
(See also: Trim2)

Edit:
The code should no longer add blank frames to the end when the framecount of the input clip is not a multiple of 800.

Last edited by stickboy; 13th August 2003 at 09:54.
stickboy is offline   Reply With Quote
Old 12th August 2003, 13:45   #8  |  Link
zettai
Fascinated Lurker
 
zettai's Avatar
 
Join Date: Feb 2002
Location: Durham, UK
Posts: 243
Quote:
I believe your math is a little off... if you remove every 196th frame, you'll remove 5 frames of every 800. (If you neglect to remove the fifth frame, one of the segments will not be a multiple of 4.)
But I'm not removing any frames... nor do I want to. It's a case of some frames are telecinied and some frames are copied directly from the source to the "telecined" version.

You telecine 196 frames and then copy fram 197 and then telecine the next 196 frames until you've reached frame 800 then you start the cycle again.

196*4 = 784
1*4 = 4

total 788, continue cycles of 4 until frame 800.


If you do things your way (from what I can understand of your code) then you will have frame 200 being the 199th frame being telecinied which would happen in the middle of a normal telecine pattern and that wouldn't be a good thing, I don't think, as you really want to keep the cycle of 4 frames being telecinied at once.


However, I think I can adapt your script to what I need it to do. Please check my reasoning behind 196 again and how it would work. It's the same principle but it's making sure that you are always doing telecine on sections of 4 frames with the last frames being the exception.




EDIT: OK, yes, I see the flaw in the 196 model now.

I would prefer to not have to have telecine stop mid sequence (as it could end on one frame being represented by only one field.

Perhaps then I could telecine 196 frames then just copy the other 4 directly and then repeat.

Hmm, not sure... I want this telecine process to be as smooth as possible, you see.

Last edited by zettai; 12th August 2003 at 14:00.
zettai is offline   Reply With Quote
Old 12th August 2003, 17:24   #9  |  Link
stickboy
AviSynth Enthusiast
 
Join Date: Jul 2002
Location: California, U.S.
Posts: 1,267
Quote:
Originally posted by zettai
But I'm not removing any frames... nor do I want to. It's a case of some frames are telecinied and some frames are copied directly from the source to the "telecined" version.
Er, I didn't mean "remove". I meant to say "not telecined".
Quote:
If you do things your way (from what I can understand of your code) then you will have frame 200 being the 199th frame
Frame number 200 is the 201st frame in the clip, since frame numbers start at 0.
Quote:
I would prefer to not have to have telecine stop mid sequence (as it could end on one frame being represented by only one field.
In my code, Telecine() is always called on a range of frames that's a multiple of 4 (except at very end of the original clip); in every 800 frames, it leaves one frame alone, telecines 200 frames, leaves one alone, telecines another 200, leaves one alone, telecines another 200, leaves one alone, and then telecines the remaining 196. That's 200 + 200 + 200 + 196 = 796 frames telecined and 4 left alone, which is what you wanted, right?

Last edited by stickboy; 12th August 2003 at 19:23.
stickboy is offline   Reply With Quote
Old 12th August 2003, 18:54   #10  |  Link
zettai
Fascinated Lurker
 
zettai's Avatar
 
Join Date: Feb 2002
Location: Durham, UK
Posts: 243
Yes, sorry - I've had a good chance to really play around with it and it's perfect! Sorry for doubting you

Thank you ever so much for working out how to use trim like that and helping me with the script. It's exactly what I need!
zettai is offline   Reply With Quote
Old 12th August 2003, 19:20   #11  |  Link
stickboy
AviSynth Enthusiast
 
Join Date: Jul 2002
Location: California, U.S.
Posts: 1,267
BTW, the code above is sort of meant as proof-of-concept, not for production use or anything...

If the framecount of the original clip is not a multiple of 800, you might end up with some extra frames at the very end, because if you call Trim with a start frame past the end of the clip, it returns the last frame of the clip instead of a 0-frame clip.

I really should use my Trim2 function instead, but currently its bounds-checking is too strict to be used in this case easily. I will relax the checks and post an updated version later today.
Quote:
Originally posted by stickboy:
I believe your math is a little off... if you remove every 196th frame, you'll remove 5 frames of every 800. (If you neglect to remove the fifth frame, one of the segments will not be a multiple of 4.)
Ack, I must have been really sleepy when I wrote that. You're right, leaving every 196th frame untelecined works too. I don't know why I thought the last segment (196 + 12 = 208 frames) would not be a multiple of 4.

OTOH, using intervals of 200 should be a little bit smoother, since the discrepancy at the end is smaller.

Last edited by stickboy; 12th August 2003 at 19:58.
stickboy is offline   Reply With Quote
Old 13th August 2003, 09:55   #12  |  Link
stickboy
AviSynth Enthusiast
 
Join Date: Jul 2002
Location: California, U.S.
Posts: 1,267
I made some minor edits to the code above. Extra blank frames no longer should be appended to the end...

(Requires an updated version of Trim2.)
stickboy is offline   Reply With Quote
Old 13th August 2003, 10:33   #13  |  Link
zettai
Fascinated Lurker
 
zettai's Avatar
 
Join Date: Feb 2002
Location: Durham, UK
Posts: 243
Sounds great - one question though... what is your max function? I've put in what I think it probably is but I thought I'd ask just to be sure
zettai is offline   Reply With Quote
Old 13th August 2003, 10:41   #14  |  Link
stickboy
AviSynth Enthusiast
 
Join Date: Jul 2002
Location: California, U.S.
Posts: 1,267
Whoops again. Fixed now.
stickboy is offline   Reply With Quote
Old 13th August 2003, 16:50   #15  |  Link
Xesdeeni
Registered User
 
Join Date: Aug 2002
Posts: 467
A question: Where did you get actual 24 fps content? PAL is 25 fps, so if you convert to 24 fps, then why not just convert to 23.976 fps? IVTC'd NTSC is 23.976.

Anyway, you can always just:
Code:
ChangeFPS(59.94)
SeparateFields()
SelectEvery(4,0,3)
Weave() # or not
If your input is a progressive 24 fps, then ChangeFPS(59.94) will replicate frames to give you a progressive sequence that does a frame-based 3:2 pulldown (that's what 720p HDTV does), with the rounding when necessary. If the input is a progressive 23.976 fps, then ChangeFPS(59.94) will give you a pure frame-based 3:2 pulldown. In either case, you just pick off one field from each frame and voila!

Xesdeeni
Xesdeeni is offline   Reply With Quote
Old 13th August 2003, 17:38   #16  |  Link
zettai
Fascinated Lurker
 
zettai's Avatar
 
Join Date: Feb 2002
Location: Durham, UK
Posts: 243
Well, it's a long story


One of the annoying bugs of Adobe Premiere is that it can't deal with 23.976fps footage. Upon export it will make it 23.98fps which is no use to man nor beast.

What I used to do to get around this was to:

a) take my audio stream and do a rate change on it

b) assuemfps(24) on all 23.976 source footage

c) edit at 24fps, export at 24fps

d) Assumefps(23.976) on exported video

e) Re-attach original unchanged audio stream.



But once upon a time, I didn't think about doing things this way - I just edited at 24fps so I wouldnt have frame drift because of premiere being dumb. Then I realised that to make things 29.97fps I'd have to either change the audio stream or remove frames... neither of which I wanted to do. This is where the idea came from.


I'll look into changefps, but I figured doing it in the telecine would smooth out the transition as much as possible.
zettai is offline   Reply With Quote
Old 15th October 2006, 21:42   #17  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
Stickboy, thanks a lot! I've wanted this exact function for a while. Changefps(), has a phase problem. Example, 24p->30i starting at 0 you get clean, laced, laced, clean, clean but changefps() gives me laced,laced,laced,clean,clean... I wanted precise control to be able to label each field and frame for a test video, one counter runs at 24fps, another at 60i, another at 30p, so I could see the exact effects of doubleweave, deint, pulldown, and other functions.
Thanks stickboy again, for explaining doubleweave on your page!
My other problem has been deint's picking the wrong duplicate because of B frame causing a ghosting with the next frame, but that's another topic...
jmac698 is offline   Reply With Quote
Old 18th October 2006, 02:40   #18  |  Link
Trixter
Registered User
 
Join Date: Oct 2003
Posts: 209
Quote:
Originally Posted by zettai View Post
One of the annoying bugs of Adobe Premiere is that it can't deal with 23.976fps footage. Upon export it will make it 23.98fps which is no use to man nor beast.
Hate to break this to you, but Premiere Pro (I tested 1.5, 2.0 is now the current version) works with it just fine. It only rounds to 23.98 when *displaying* the framerate -- internally, it is properly represented at 23.976 and I've never had a frame drop/desynch when working with 23.976p footage.
Trixter is offline   Reply With Quote
Old 18th October 2006, 19:33   #19  |  Link
Zarxrax
Registered User
 
Join Date: Dec 2001
Posts: 1,219
Quote:
Originally Posted by Trixter View Post
Hate to break this to you, but Premiere Pro (I tested 1.5, 2.0 is now the current version) works with it just fine. It only rounds to 23.98 when *displaying* the framerate -- internally, it is properly represented at 23.976 and I've never had a frame drop/desynch when working with 23.976p footage.
You realize the post you replied to was written 3 years ago?
On that note though, I think I have seen premiere pro (1.5 at least, maybe 2.0 as well) drop a frame or 2 with 23.976 footage. I believe it relates to the rational framerate value that is stored in the avi.
Zarxrax is offline   Reply With Quote
Old 19th October 2006, 04:37   #20  |  Link
Trixter
Registered User
 
Join Date: Oct 2003
Posts: 209
Quote:
Originally Posted by Zarxrax View Post
You realize the post you replied to was written 3 years ago?
Would I have replied if I had realized that?
Trixter is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 18:57.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.