Log in

View Full Version : LAV Filters - DirectShow Media Splitter and Decoders


Pages : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 [33] 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508

Plutotype
13th April 2011, 18:32
Hi Nev,
0.22/ 0.51 madVR.

If open a VC-1 video, pause it and then jump to 30th minute, 60 minute etc. , the pictured frames do not represent correct frame of the movie, but ..I dont know. The image gets corrupted too.

more here http://forum.doom9.org/showthread.php?p=1492038#post1492038

Thanks

Pluto

CruNcher
13th April 2011, 18:48
Plutotype frame accuracy is a complex thing don't expect that from ffmpeg for everything especially when using another Decoder, does it at least recovers correctly ? ;)

Plutotype
13th April 2011, 19:00
MPC-HC internal splitter does this job correctly, I think Nev will find out how to fix it.

Midzuki
13th April 2011, 19:00
@Plutotype:

That's normal :) , happens with MPC-HC's Mpeg Splitter as well
(on my PC at least, bien entendu).
And speaking of the libavcodec/ffmpeg bugs :devil:, their VC-1 decoder seems to misunderstand the pixel-aspect-ratio flags in non-standard resolutions / frame sizes -.-

nevcairiel
13th April 2011, 19:01
I'm really not too worried about some weird behaviour in pause mode, you're supposed to play it, not pause it. :)

This seems to be decoder specific, works fine with ffdshow - maybe the mpc decoder doesnt like getting a flush, or something.

Plutotype
13th April 2011, 19:35
Thanks guys, I found the cause for the issue - wmv9 decoder - switching to libavcodec in ffdshow resolved it. Does anybody know any cons of using livacodec instead of wmv9? Should I care?

nevcairiel
13th April 2011, 19:43
libavcodec cannot decode interlaced VC-1.

SamuriHL
14th April 2011, 01:00
I tried to load several wtv files using your last commits but MPC-HC uses MS filters to split them. Is it because wtv files extension registers his own filters ?

Anyway, thanks for your work.

I got this when I just tried a wtv file:



Media Type 0:
--------------------------
Unknown

AM_MEDIA_TYPE:
majortype: MEDIATYPE_MSTVCaption {B88B8A89-B049-4C80-ADCF-5898985E22C1}
subtype: MEDIASUBTYPE_DtvCcData {F52ADDAA-36F0-43F5-95EA-6D866484262A}
formattype: FORMAT_None {0F6417D6-C318-11D0-A43F-00A0C9223196}
bFixedSizeSamples: 1
bTemporalCompression: 0
lSampleSize: 1
cbFormat: 0


EDIT: Media Info for the file:


Format : MPEG Video
Format version : Version 2
File size : 6.67 GiB
Duration : 367ms
Overall bit rate : 156160680806

Video
Format : MPEG Video
Format version : Version 2
Format profile : Main@High
Format settings, BVOP : Yes
Format settings, Matrix : Default
Duration : 367ms
Bit rate mode : Variable
Bit rate : 38.8 Mbps
Width : 1 920 pixels
Height : 1 080 pixels
Display aspect ratio : 16:9
Frame rate : 29.970 fps
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Scan type : Interlaced
Scan order : Top Field First
Bits/(Pixel*Frame) : 0.625
Stream size : 1.70 MiB (0%)



But yea, LAVF Splitter isn't in the chain that MPC-HC comes up with at all. In my case they're MPEG2 HD tv recordings. WTV is an ANNOYING format, Nev. It took the VRD guys months to get their support written for it.

jmone
14th April 2011, 02:59
libavcodec cannot decode interlaced VC-1.

OT - Do you know if there are any plans to add interlaced VC-1 support to libavcodec?

Midzuki
14th April 2011, 03:24
Does anybody know any cons of using livacodec instead of wmv9? Should I care?

Well, the M$ DMO Decoder for VC-1 really is ASF-centric and "VfW-biased", so that you may experience some "B-frame decoding lag" by using it... :confused: Also, if you create VC-1 elementary streams through AVS2ASF, or through MainConcept Reference, these files will be properly decompressed by the Dmo DLL IF you remux them in a (m2)ts container --- otherwise, if you remux them into MKV, AVI, or even ASF, the Dmo decoder will show you only a sequence of black frames :eek:
++++++
OVERDUE UPDATE

After some additional tests, I've concluded the DMO decoder is just very-picky :mad: about the way the VC-1 stream was muxed into the container :angry:

nevcairiel
14th April 2011, 06:58
OT - Do you know if there are any plans to add interlaced VC-1 support to libavcodec?

I think there is a GSoC project for it, we'll see how that turns out.

Man i wish i was still a student, getting a ffmpeg GSoC project and being paid by google for it ... hooray. Oh well, that time has long since past.


But yea, LAVF Splitter isn't in the chain that MPC-HC comes up with at all. In my case they're MPEG2 HD tv recordings. WTV is an ANNOYING format, Nev. It took the VRD guys months to get their support written for it.

ffmpeg supports it (how good is anohter question), and if you want to play a file outside of the usual MS player tools, it might potentially even work better then their own splitter.

If you guys could supply some .wtv samples, i could run some tests on that.

Kurtnoise
14th April 2011, 08:30
If you guys could supply some .wtv samples, i could run some tests on that.
http://kurtnoise.free.fr/samples/

This file contains H264+EAC3 streams...more samples later.

The splitter works well inside GraphStudio/GraphEdit within those files.

robpdotcom
14th April 2011, 09:38
Here's a 1080i MPEG-2 wtv file.

http://www.megaupload.com/?d=RK1TUVDX

jmone
14th April 2011, 11:47
Anyone having issues with audio slowly drifting out of syn on BD playback? After about an hour I did a pause/play cycle but no joy. A short RWD however brought it back into sync.

nevcairiel
14th April 2011, 12:01
The splitter should always output the same timestamps, no matter if you seek back and forth or just watch it from the start - if the time is drifting, it must be some other component doing weird things.

The audio decoder however might drift if for some reason a audio frame could not be decoded properly, or for some other reason the continous audio stream is interrupted. Sadly its hard to reproduce, but i'll keep an eye out, and maybe sync timestamps more often.

If anything, i will add logging to see what the hell is going on.

One thing is to note, however. When i sync timestamps, i do break the continous PCM stream, which is otherwise 100% complete and has no holes. Now that you mention it, the Jitter correction that i removed a while ago didn't actually correct jitter - it resynced timestamps, making sure they stay in check - this would sometimes show as jitter to the renderers, but it isn't - its there to keep A/V sync in check.

jmone
14th April 2011, 12:21
FYI - the disc was Galxay Quest (no jokes please) - AVC1, TrueHD using LAVSplitter, FFDSHOW (ffmpeg-mt h264) for Video, LAVAudio for Audio, madVR and Reclock as the renderers.

Edit -

Player was JRiver MC.

I did not see any dropped frames or visual issues just a gradual loss of audio sycn.

Please Let me know if there is any further info or any test you would like me to do.

Skinleech
14th April 2011, 12:28
Apologies if this has been asked before, it probably has and I missed it. Does LAV splitter need to be used in order for LAV audio to be called?

I use DVB Viewer to capture Freeview HD stream heare in the UK which use AAC LATM LOAS for the audio. The MS DTV decoder seems pretty crappy as it's currently dropping the live audio (recorded content is fine on playback with LAV though) probably at the points where the soundtrack switches from 5.1 to 2.0 or vice versa. I've not had much luck with other AAC decoders, so wanted to try LAV which is working perfectly for pre-recorded streams. However, setting it up in DVB doesn't work, it just uses the System default which is the MS DTV codec.

Also, I can easily provide some 1440x1080i/25 h.264 with AAC wtv samples if they're required.

Thanks!

nevcairiel
14th April 2011, 12:37
I use DVB Viewer to capture Freeview HD stream heare in the UK which use AAC LATM LOAS for the audio. The MS DTV decoder seems pretty crappy as it's currently dropping the live audio (recorded content is fine on playback with LAV though) probably at the points where the soundtrack switches from 5.1 to 2.0 or vice versa. I've not had much luck with other AAC decoders, so wanted to try LAV which is working perfectly for pre-recorded streams. However, setting it up in DVB doesn't work, it just uses the System default which is the MS DTV codec.

It should work with other sources, however there are some limitations that usually apply to DVB sources. For one, DVB source filters sometime output MEDIATYPE_MPEG2_PES instead of MEDIATYPE_Audio, and this mode is not currently supported by LAV Audio.

I just recently got me a DVB-T/DVB-C USB doohickey, and i'll test with that in due time, and allow it to be used with DVB content.

FYI - the disc was Galxay Quest (no jokes please) - AVC1, TrueHD using LAVSplitter, FFDSHOW (ffmpeg-mt h264) for Video, LAVAudio for Audio, madVR and Reclock as the renderers.

I added some code that'll try to resync timestamps after a decoding fluke, and added logging when it detects sync offsets over 10ms (pretty drastic logging, the old code only acted on 100ms offsets).

I will also add some things that make redirecting logs into a file much easier for you guys to use.

jmone
14th April 2011, 12:46
Thanks - when the updated version is out I'll re-run on the same system and report back.

Skinleech
14th April 2011, 13:17
It should work with other sources, however there are some limitations that usually apply to DVB sources. For one, DVB source filters sometime output MEDIATYPE_MPEG2_PES instead of MEDIATYPE_Audio, and this mode is not currently supported by LAV Audio.

I just recently got me a DVB-T/DVB-C USB doohickey, and i'll test with that in due time, and allow it to be used with DVB content.

Awesome, thank you. I don't tend to watch the streams live, but it's pretty annoying when they cut out.

SamuriHL
14th April 2011, 13:55
ffmpeg supports it (how good is anohter question), and if you want to play a file outside of the usual MS player tools, it might potentially even work better then their own splitter.

If you guys could supply some .wtv samples, i could run some tests on that.

That would rock. If you need another sample, let me know. Mine's 1080i mpeg2/ac3.

nevcairiel
14th April 2011, 15:43
Thanks - when the updated version is out I'll re-run on the same system and report back.

I think i figured it out. It actually happened because TrueHD has so small samples (for the 48kHz file i had, 40 samples in one audio frame, thats 0.833333ms (going on periodically)).
Due to that periodic number, i couldn't accurately store those numbers in an integer, so eventually the error would sum up, and the value would slowly drift apart, one millisecond at a time.

Now, i changed it to store those numbers in a double precision floating point - which reduces integer precision from 64-bit to 52-bit (still big enough for around ~20 years of timestamps), but gives me the ability to store a timestamp like 0.8333ms much more accurately.

Dogway
14th April 2011, 16:37
Will you add support for asf,wmv3 or real media?
I also had problems with files with chapters like .mkv or .asf. There was sound but image was black. Maybe is this (http://forum.doom9.org/showthread.php?p=1463711#post1463711)?
I also had a problem with a .mov file (not the uploaded one), there's a point where I can't playback further. Graphstudio had problems too, x264 too (I couldn't encode the whole video), funny thing is I installed itunes and quicktime had no problems with it.

Midzuki
14th April 2011, 17:10
Will you add support for asf,wmv3 or real media?

Good questions. :) RealMedia should not be difficult (source-code from Gabest). FYI, ".ASF = .WMV" ;) (too bad the M$ marketers don't want to know the difference between codecs and containers), and ready-made source-code for that is available as well ( http://www.gdcl.co.uk/ ). As long as the splitter allows us to open Xvid-in-ASF :) and VP6-in-RMVB :D , it will have my official approval. :rolleyes: :p

Dogway
14th April 2011, 18:11
FYI, ".ASF = .WMV"

I meant wmv3 (http://en.wikipedia.org/wiki/VC-1), the codec. .asf is a container.

nevcairiel
14th April 2011, 18:16
Both WMV3 and ASF should be supported, to some extend.
To get .asf working, you need to manually hook it up, though.

Dogway
14th April 2011, 18:25
So these 2 should work?
3Mb each
http://www.mediafire.com/?drcnjcv1johy99f
http://www.mediafire.com/?kro2dqwee1kj0aw
Its wmv1, but well any wmv except wvc1

edit: manual hook=merit?

nevcairiel
14th April 2011, 18:39
These work just fine. The next version will have an installer that'll let you directly open them without manual registry editing.

I also tested some of the wtv samples, and they seem to play just perfectly - after i managed to disable the original MS source filter. :)

jmone
14th April 2011, 22:06
I think i figured it out. It actually happened because TrueHD has so small samples (for the 48kHz file i had, 40 samples in one audio frame, thats 0.833333ms (going on periodically)).
Due to that periodic number, i couldn't accurately store those numbers in an integer, so eventually the error would sum up, and the value would slowly drift apart, one millisecond at a time.

Now, i changed it to store those numbers in a double precision floating point - which reduces integer precision from 64-bit to 52-bit (still big enough for around ~20 years of timestamps), but gives me the ability to store a timestamp like 0.8333ms much more accurately.

Thanks! I'll test in the next public build release and report back. Appart from that the playback looked and sounded terrific.

yesgrey
14th April 2011, 22:27
I decided to join the crowd and installed LAV Splitter v0.22. :)

I've been testing LAV CUVID with madVR and noticed a strange thing. With a 1080i 60/1.001 fps file (music concert), the LAV splitter says the source is a 59.92fps, and madVR reports that the source filter says it's 59.917fps. That's not correct. 60/1.001 is ~59.940.

I've tested the file with eac3to and it correctly reports the file as 60/1.001. Tested with Haali splitter it says is a 29.97 fps file (the usual error of halving the interlaced frame rates).

It's the "Mettalica - Français pour une nuit" Blu-ray. If you need a sample let me know.

nevcairiel
15th April 2011, 06:35
The framerate in the media type is not important, its just a hint for the filters what to expect - the real fps is only defined through the timestamps of the actual frames.
What kind of container was this? On some containers (most notable mkv), ffmpeg doesn't trust the container defined framerate, and starts reading frames to "guess" the framerate. Sadly it usually doesn't read enough frames to get an accurate framerate (if the container timestamps are not of high enough precision, like MKV), so this happens.

Its really nothing to worry about.
The only place this would be used would be refresh rate switching, and i hope any tool that does that would be smart enough to switch to 59.940 when it sees 59.917. :)

madshi
15th April 2011, 06:56
The only place this would be used would be refresh rate switching, and i hope any tool that does that would be smart enough to switch to 59.940 when it sees 59.917. :)
What happens if the deviation is to the up-side and not the down-side? 59.940 - 59.917 = 0.027 deviation. 59.940 + 0.027 = 59.967. That's almost exactly in the middle between 59.940 and 60.000. How's an automatic refresh rate switcher expected to know whether to switch to 59.940 or 60.000Hz in that case?

nevcairiel
15th April 2011, 07:01
Make an educated guess and prefer 59.94, i would say. Its really more common then actual 60.0 fps movies.

But yeah, its not optimal - there was some talk on the ffmpeg list about the whole problem (it even used to misdetect 23.976 as 24.000 at some point), but the discussion somehow died when the whole fork etc happend. Maybe i can find and bump it.

But thats not the only problem a refresh rate switcher faces. What happens if i tell you its 59.94, but in fact, its telecined and ends up being 23.976 in the end? Or even 50i -> 25p for PAL FILM content, even without telecine.

Edit:
I guess 50i->25p isn't too bad, using 50Hz works for both - doh. :)

madshi
15th April 2011, 07:29
Make an educated guess and prefer 59.94, i would say. Its really more common then actual 60.0 fps movies.
Yeah, but what if the deviation is even bigger than in yesgrey's case and the guessed number gets very near to 60.000? Then an automatic refresh rate changer would most definitely switch to 60.000. If it wouldn't do that there would be bug reports by users who have true 60.000 content.

But thats not the only problem a refresh rate switcher faces. What happens if i tell you its 59.94, but in fact, its telecined and ends up being 23.976 in the end?
Yeah, a good refresh rate switcher should constantly check the framerate and adjust itself accordingly. However, that's only possible once playback has started. The refresh rate changer needs to start with the best guessed refresh rate right at the start. So it's kind of important that the media type information is accurate. Otherwise a stupid refresh rate changer would run the whole movie with a wrong refresh rate. A clever refresh rate changer would have to switch to the correct refresh rate after a couple of seconds of playback. The latter solution isn't too bad, but it's still not nice for users.

yesgrey
15th April 2011, 09:47
What kind of container was this?
It's mkv.

Thanks for the explanation. So, it's not exactly a bug with LAV Splitter.

The interesting thing is this is the only file where this happens. I have a bunch of others that are OK. Well, to be honest, I think they might not be OK too, because they're reported as 29.97, when in reality it should be 59.94 due to being interlaced sources. Do you know why this happens?

nevcairiel
15th April 2011, 09:55
It's mkv.

Yeah figures. MKV (by default) only has millisecond precision for timestamps, which is the root cause for all these issues.

60fps is 16.66667ms per frame, 59.94 is 16.683333ms.

Timestamps probably look something like this:

0, 17, 33, 50, 67, 83, 100, ...

From this short sequence, the average time per frame is 16,6ms (60,24fps)

I'll leave it as an excercise for the reader to determine how many frames will have to be read to calculate a 100% accurate framerate.

Currently its reading 30 frames, which gives us 16,68965ms average time per frame, which is 59,91735fps
If it would be reading 31 frames, we would actually end up at 60fps exactly. *Vastly* increasing the number is no good either, as it would take much longer to open the file then.

It would probably be smarter if ffmpeg would just trust the container defined framerate -- i'll try to find the thread on the mailing list and inquire on any status update.

Edit:
I found the old thread, and there is some code that marks the timebase of H264 streams as unreliable for some reason, sadly it was never fully explained why. I have some files myself that probably show this problem, going to turn that unreliable check off (which should make it trust the container headers or the H264 headers) and see what happens.

yesgrey
15th April 2011, 10:24
MKV (by default) only has millisecond precision for timestamps, which is the root cause for all these issues.

60fps is 16.66667ms per frame, 59.94 is 16.683333ms.

Timestamps probably look something like this:

0, 17, 33, 50, 67, 83, 100, ...
So, I presume that the video renderers should not rely on the file timestamps, right? Or then the rendering might end up flawed...

I have some files myself that probably show this problem, going to turn that unreliable check off (which should make it trust the container headers or the H264 headers) and see what happens.
Thanks for taking the time to look into this.

nevcairiel
15th April 2011, 10:37
So, I presume that the video renderers should not rely on the file timestamps, right? Or then the rendering might end up flawed...

Right. For perfect rendering, it would probably have to smooth out the timestamps, of if its rendering into vsyncs anyway, that problem probably solves itself. madshi can probably answer that much better.

Here is a quick debugging output which perfectly shows the problem (MKV, H264 23.976 file)
DirectShow uses 100ns granularity for timestamps, yet the frame duration is always rounded to 41ms (ideally, it would be 41.7083).
To keep A/V sync, there are actually small "gaps" of 1ms between every other frame.


LAVSplitter.ax(tid d6c) 2733 : Packet: rtStart: 0; rtStop: 410000; duration: 410000; diff-to-prev: 0
LAVSplitter.ax(tid d6c) 2739 : Packet: rtStart: 420000; rtStop: 830000; duration: 410000; diff-to-prev: 420000
LAVSplitter.ax(tid d6c) 2764 : Packet: rtStart: 830000; rtStop: 1240000; duration: 410000; diff-to-prev: 410000
LAVSplitter.ax(tid d6c) 2764 : Packet: rtStart: 1250000; rtStop: 1660000; duration: 410000; diff-to-prev: 420000
LAVSplitter.ax(tid d6c) 2765 : Packet: rtStart: 1670000; rtStop: 2080000; duration: 410000; diff-to-prev: 420000
LAVSplitter.ax(tid d6c) 2766 : Packet: rtStart: 2090000; rtStop: 2500000; duration: 410000; diff-to-prev: 420000
LAVSplitter.ax(tid d6c) 2766 : Packet: rtStart: 2500000; rtStop: 2910000; duration: 410000; diff-to-prev: 410000
LAVSplitter.ax(tid d6c) 2771 : Packet: rtStart: 2920000; rtStop: 3330000; duration: 410000; diff-to-prev: 420000
LAVSplitter.ax(tid d6c) 2771 : Packet: rtStart: 3340000; rtStop: 3750000; duration: 410000; diff-to-prev: 420000
LAVSplitter.ax(tid d6c) 2771 : Packet: rtStart: 3750000; rtStop: 4160000; duration: 410000; diff-to-prev: 410000
LAVSplitter.ax(tid d6c) 2813 : Packet: rtStart: 4170000; rtStop: 4580000; duration: 410000; diff-to-prev: 420000
LAVSplitter.ax(tid d6c) 2813 : Packet: rtStart: 4590000; rtStop: 5000000; duration: 410000; diff-to-prev: 420000
LAVSplitter.ax(tid d6c) 2814 : Packet: rtStart: 5000000; rtStop: 5410000; duration: 410000; diff-to-prev: 410000
LAVSplitter.ax(tid d6c) 2814 : Packet: rtStart: 5420000; rtStop: 5830000; duration: 410000; diff-to-prev: 420000
LAVSplitter.ax(tid d6c) 2815 : Packet: rtStart: 5840000; rtStop: 6250000; duration: 410000; diff-to-prev: 420000


The "best" matchign results i've seen are MPEG-TS actually, were frame durations for 23.976 are typically 41.7111ms (23.974 fps), pretty close to the real deal (of course occasionally a frame comes along that is shorter then that to fix sync)
Again, its most likely limited by the MPEG-TS timebase of 1/90000.

I believe you *can* increase the granularity of timestamps in MKV, but apparently not many files are like that.

You're file was actually H264, yes?
I already have some code to fix up H264 23.976 wrongly detected as 24.000, could easily extend it to do the same for 59.94 detected as 60.

madshi
15th April 2011, 10:48
Right. For perfect rendering, it would probably have to smooth out the timestamps, of if its rendering into vsyncs anyway, that problem probably solves itself. madshi can probably answer that much better.
Yeah, as you say, a (good) renderer matches frames to vsyncs. And vsyncs are much wider apart than the small inaccurateness in MKV timestamps. So usually not really a problem for a renderer.

yesgrey
15th April 2011, 11:36
I'll leave it as an excercise for the reader to determine how many frames will have to be read to calculate a 100% accurate framerate.
I decided to take the challenge. :)

I wrote a small matlab program and the results were pretty interesting...

For all integer frame rates (24, 30, 60) we need to read a number of frames that's a multiple of 3, and we get a 100% exact frame rate.

For all non-integer frame rates (24.0/1.001, 30.0/1.001, 60.0/1.001) we need to read a number of frames equal to the frame rate rounded to the nearest integer. To the rates above we would need to read 24, 30 and 60, respectively. This will not give a 100% exact frame rate, but I guess we could live with an error < 1.0e-13. ;)

So, considering that 24, 30 and 60 are multiples of 3, a way of solving this would be always reading 24, 30 and 60 frames, calculate the three possible frame rates, and then select the one which value would be close to the number of readings.

Let's see an example for a 60/1.001 fps file:
Exact frame rate: 59.9400599400599
The 24 readings frame rate would be: 60.0
The 30 readings frame rate would be: 60.0
The 60 readings frame rate would be: 59.9400599400599

60.0 is much higher than 24 and 30, so the accurate one would be the 60 readings one.

Even better, considering that 60 is a multiple of 30, we could simply go with 2 readings, 24 and 60. Then, we would go always with the 60 readings value except for values close to 24. I think this might be pretty simple to implement.

Edit:
All the above is without reading the first frame, whose time stamp is 0ms. If we include the reading of the first frame then we should make 25 and 61 readings, and compare the results with (25-1) and (61-1).

I forgot to include 25 and 50 frame rates. For these ones 1 reading (2, if we include the first frame reading), or any multiple of 1, are enough, so the above method should work too, it's just using the 60 readings value.

nevcairiel
15th April 2011, 12:35
Reading 60 frames does not actually hurt 23.976 content, or does it?
Note that the fps guessing code will adapt the framerate to one of the standard rates (24,25,30,50,60, and the same /1.001) when it finds one very close to that, so minor errors are ok.

I knew that 24 frames was the sweet spot, it was mentioned in the ffmpeg list some time back. Reading 60 frames does not sound too bad, i guess i could even increase the parsing to that amount, but since there is no frame rate information at the point where that code is executed, i cannot make it conditional.

I double checked the code, and right now its 20 frames "normally", and double that amount for coarse timebases, like MKV. I can easily just make that triple instead of double.

Going to play with that tonight.

Oh the other problem, with interlaced files being detected as 29.97 - i cannot comment with any certainty.
What codec is in those files? Only H264 and MPEG2 currently do timestamp guessing (I'm unsure what makes them so special), all other codecs rely on the container defined frame rate, and the container may have them as 29.97 - you could check with Mediainfo or some MKV header editor to check that.

yesgrey
15th April 2011, 12:41
I've just edited my previous post. It wasn't entirely correct. Please take a look into it.

yesgrey
15th April 2011, 13:02
Reading 60 frames does not actually hurt 23.976 content, or does it?
If you would use only the 60 readings it might.

My suggestion is to do always two readings: 25 and 61.
And to use always the 61 readings value except when it's close to 24. Like this:
GetFPSReadings(fpsRead25)
GetFPSReadings(fpsRead61)
fpsFile = fpsRead61
if (abs(fpsFile-24.0) < 0.1) fpsFile = fpsRead25

I knew that 24 frames was the sweet spot, it was mentioned in the ffmpeg list some time back.
It isn't. It's good only for 24 and 24/1.001 sources.

but since there is no frame rate information at the point where that code is executed, i cannot make it conditional.
You don't need any frame rate information. See above my code suggestion.

I double checked the code, and right now its 20 frames "normally", and double that amount for coarse timebases, like MKV. I can easily just make that triple instead of double.
That won't work. It has to be 25 and 61. Other values the errors are too big, and if we can get 100% why go with less? ;)

What codec is in those files? Only H264 and MPEG2 currently do timestamp guessing (I'm unsure what makes them so special), all other codecs rely on the container defined frame rate, and the container may have them as 29.97 - you could check with Mediainfo or some MKV header editor to check that.
Two of the files are WVC1 and the other is AVC. So the WVC1 are explained but the AVC one isn't...

The AVC one is "Metallica - Orgullo Pasion y Gloria" Blu-ray.

OK, I admit, I'm a Metallica fan. :D

nevcairiel
15th April 2011, 13:30
It isn't. It's good only for 24 and 24/1.001 sources.

Yeah, i meant sweet spot for the 24/23,976 distinction.


That won't work. It has to be 25 and 61. Other values the errors are too big, and if we can get 100% why go with less? ;)

It does actually read the duration of 60 frames, not the timestamps, so it has 60 data points to compare.


The problem with the code is that its not mine, but ffmpegs. Now i have no problem applying a custom patch to my builds, but the way the code works, i cannot simply do as you suggests (and i would prefer to keep the changes small and simple for future upgradability)

I can try to outline how it works right now (as good as i understand it), in pseudo code


while #frames < maximum
get duration of frame
for all standard framerates: (1-60, 23.976, 29.970, 59.940)
get framerate (scaled * 1001 * 12, for 59.94 = 720000)
calculate ticks (duration * framerate / (1001 * 12))
calculate error (duration - round(ticks) * (1001*12) / framerate)
sum error^2 per fps
end
end

best_error = INT_MAX
for all standard framerates:
if error < best_error
best_error = error
best_fps = fps
end
end


Oh, what is to note is that the standard fps actually include more then just the integer entrys - they include 12 values for every integer, so thats where your FPS comes from, the value for 59 + 11/12 just fits better then 59.940 after 40 frames. If we can get it close enough to the real value, it'll be a perfect match, we don't have to get it to match 100% - it'll do that afterwards by itself.

Some quick tests show that reading 60 frames will not break 23.976, 23.976 will still be the closest match (the calculated frame rate would be 23.980, surrounding possible values are 23.9167 (23+11/12), 23.976, 24.000)

Like i said before, it just needs to have the least error to the correct FPS, and then it'll use the 100% correct one - it doesn't have to calculate the 100% correct framerate - so, reading 60 frames will give us the correct result in any case, and while reading those frames potentially slows down opening of the file (minimally), they are actually internally buffered and then send to me once i start requesting frames.

nevcairiel
15th April 2011, 16:51
I looked into it some, and it looks like it won't be easy to do it perfectly. I even rewrote it completely one time, which then caused it to work on some files, but broke on others that had screwed up timestamps in the first 2 frames.

I'll just disable the whole guessing logic for H264 and go with the container or header specified frame rate. This does however mean that it'll show 29.970. Technically, this would even be correct, since its the frame rate, not the field rate. :P
If a deinterlacer combines that back to 60 full progressive frames, it should indicate as such in the media type - thats not the source filters job.

In any case, 29.97 does perfectly fit into 59.94, so a refresh rate changer shouldn't have problems either. (Is there any reason to set the screen to 29.97, rather then 59.94?)

I'll also write to the ffmpeg list and see if they have some smart idea. I found some sample that can easily be used to demo the behaviour.

madshi
15th April 2011, 17:05
I don't expect problems with 29.970. I don't even know if there's any display that supports such a refresh rate. A refresh rate changer should treat 29.970 as 59.940, IMHO. So all should be fine with 29.970.

SamuriHL
15th April 2011, 17:43
Ok, well, since we (and by that I mean Nev and madshi! :D) got things working so well, I figure now would be a good time to throw out a nice challenge for you. :D I use MakeMKV to backup my movies to MKV format so I can play them with MPC-HC/LAVF Splitter/ffdshow(audio bitstreaming only)/a Video decoder (LAVF CUVID or Cyberlink HAM)/madVR. What an amazing environment and absolutely awesome playback capability! Now for the challenge. Subtitles from HD DVD in an MKV no workie. They claim to be DVD vobsub subtitles (codec id: S_VOBSUB). However, when I enable the subtitle track I don't see any subs being displayed. On a DVD converted to MKV using MakeMKV, I am able to turn on the subtitles and it works fine. So clearly there's something unique about HD DVD's version of subtitles that's causing it to not work. madshi/Nev....any ideas? :)

nevcairiel
15th April 2011, 17:59
I think HD DVD uses extended vob subs (with 8-bit colors, in contrast to the 4-bit for DVD vob subs), maybe those are just not supported by the different vob renderers. Do they work from the .evo files?

SamuriHL
15th April 2011, 18:04
They aren't even DETECTED in the EVO files. :)

nevcairiel
15th April 2011, 18:07
I have some .evo sample files, and LAV Splitter shows the streams just fine in there, but they dont show any subs. I blame the subtitle renderer, not the splitter or anything.