Log in

View Full Version : x264 seeking problem


raymod2
5th January 2006, 08:12
I can't seek past 7 minutes in the video files I create using the method described in the following thread:

http://forum.doom9.org/showthread.php?t=104478

The mp4dump output is as follows (most of it is from a terse dump but I cut and pasted the table entries for the stts box from a verbose dump):

$ mp4dump video.mp4
C:\msys\1.0\home\dan\bin\mp4dump.exe version 1.4.1
Dumping video.mp4 meta-information...
type ftyp
majorBrand = avc1
minorVersion = 0 (0x00000000)
<table entries suppressed>
type mdat
type free
type moov
type mvhd
version = 0 (0x00)
flags = 0 (0x000000)
creationTime = 3219038696 (0xbfdea1e8)
modificationTime = 3219038696 (0xbfdea1e8)
timeScale = 600 (0x00000258)
duration = 766086 (0x000bb086)
rate = 1.000000
volume = 1.000000
reserved1 = <70 bytes>
00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00
00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00
nextTrackId = 2 (0x00000002)
type iods
version = 0 (0x00)
flags = 0 (0x000000)
objectDescriptorId = 1 (0x001) <10 bits>
URLFlag = 0 (0x0) <1 bits>
includeInlineProfileLevelFlag = 0 (0x0) <1 bits>
reserved = 15 (0xf) <4 bits>
ODProfileLevelId = 255 (0xff)
sceneProfileLevelId = 255 (0xff)
audioProfileLevelId = 255 (0xff)
visualProfileLevelId = 21 (0x15)
graphicsProfileLevelId = 255 (0xff)
esIds
ociDescr
ipmpDescrPtr
extDescr
type trak
type tkhd
version = 0 (0x00)
flags = 1 (0x000001)
creationTime = 3219038696 (0xbfdea1e8)
modificationTime = 3219050920 (0xbfded1a8)
trackId = 1 (0x00000001)
reserved1 = <4 bytes> 00 00 00 00
duration = 766086 (0x000bb086)
reserved2 = <12 bytes> 00 00 00 00 00 00 00 00 00 00 00 00
volume = 0.000000
reserved3 = <38 bytes>
00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
00 00 40 00 00 00
width = 720.000000
height = 400.000000
type mdia
type mdhd
version = 1 (0x01)
flags = 0 (0x000000)
creationTime = 3219038696 (0x00000000bfdea1e8)
modificationTime = 3219050920 (0x00000000bfded1a8)
timeScale = 10000000 (0x00989680)
duration = 12768101422 (0x00000002f909c42e)
language = 21956 (0x55c4)
reserved = <2 bytes> 00 00
type hdlr
version = 0 (0x00)
flags = 0 (0x000000)
reserved1 = <4 bytes> 00 00 00 00
handlerType = vide
reserved2 = <12 bytes> 00 00 00 00 00 00 00 00 00 00 00 00
name = GPAC ISO Video Handler
type minf
type vmhd
version = 0 (0x00)
flags = 1 (0x000001)
reserved = <8 bytes> 00 00 00 00 00 00 00 00
type dinf
type dref
version = 0 (0x00)
flags = 0 (0x000000)
entryCount = 1 (0x00000001)
type url
version = 0 (0x00)
flags = 1 (0x000001)
location = (null)
type stbl
type stsd
version = 0 (0x00)
flags = 0 (0x000000)
entryCount = 1 (0x00000001)
type avc1
reserved1 = <6 bytes> 00 00 00 00 00 00
dataReferenceIndex = 1 (0x0001)
reserved2 = <16 bytes> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
width = 720 (0x02d0)
height = 400 (0x0190)
reserved3 = <14 bytes> 00 48 00 00 00 48 00 00 00 00 00 00 00 01
compressorName =
reserved4 = <4 bytes> 00 18 ff ff
type avcC
configurationVersion = 1 (0x01)
AVCProfileIndication = 100 (0x64)
profile_compatibility = 0 (0x00)
AVCLevelIndication = 51 (0x33)
reserved = 63 (0x3f) <6 bits>
lengthSizeMinusOne = 3 (0x3) <2 bits>
reserved1 = 7 (0x7) <3 bits>
numOfSequenceParameterSets = 1 (0x01) <5 bits>
<table entries suppressed>
numOfPictureParameterSets = 1 (0x01)
<table entries suppressed>
type btrt
bufferSizeDB = 40699 (0x00009efb)
avgBitrate = 1848088 (0x001c3318)
maxBitrate = 750048 (0x000b71e0)
type stts
version = 0 (0x00)
flags = 0 (0x000000)
entryCount = 1 (0x00000001)
sampleCount = 38266 (0x0000957a)
sampleDelta = 333667 (0x00051763)
type ctts
version = 0 (0x00)
flags = 0 (0x000000)
entryCount = 12006 (0x00002ee6)
<table entries suppressed>
type stss
version = 0 (0x00)
flags = 0 (0x000000)
entryCount = 188 (0x000000bc)
<table entries suppressed>
type stsc
version = 0 (0x00)
flags = 0 (0x000000)
entryCount = 2 (0x00000002)
<table entries suppressed>
type stsz
version = 0 (0x00)
flags = 0 (0x000000)
sampleSize = 0 (0x00000000)
sampleCount = 38266 (0x0000957a)
<table entries suppressed>
type stco
version = 0 (0x00)
flags = 0 (0x000000)
entryCount = 3827 (0x00000ef3)
<table entries suppressed>
$
There doesn't appear to be anything wrong with this file but it does use a large media timeScale (10,000,000 ticks per second) and a correspondingly large sampleDelta (333,667 ticks per sample). 10,000,000 / 333,667 seems to be an inefficient way of approximating the NTSC frame rate which is 30000 / 1001. Because of the large time scale I am guessing that my seeking problem is caused by an integer overflow somewhere. With 10,000,000 ticks per second you can only represent 429 seconds (a little over 7 minutes) in a 32-bit integer.

The seeking problem occurs during playback in BSPlayer v1.37 and Media Player Classic v6.4.8.4. However there is no problem during playback in VLC media player 0.8.4.a. Since VLC doesn't use DirectShow I'm wondering if the problem is with Haali Media Splitter? Is that where seeking is handled for DirectShow?

bond
5th January 2006, 08:27
The seeking problem occurs during playback in BSPlayer v1.37 and Media Player Classic v6.4.8.4. However there is no problem during playback in VLC media player 0.8.4.a. Since VLC doesn't use DirectShow I'm wondering if the problem is with Haali Media Splitter? Is that where seeking is handled for DirectShow? the file uses 64bit times
maybe haali has some problem with seeking on that files?

There doesn't appear to be anything wrong with this file but it does use a large media timeScale (10,000,000 ticks per second) and a correspondingly large sampleDelta (333,667 ticks per sample). 10,000,000 / 333,667 seems to be an inefficient way of approximating the NTSC frame rate which is 30000 / 1001. Because of the large time scale I am guessing that my seeking problem is caused by an integer overflow somewhere. With 10,000,000 ticks per second you can only represent 429 seconds (a little over 7 minutes) in a 32-bit integer.10000000/333667 is more accurately representing 29.97 than 30000/1001

raymod2
6th January 2006, 08:32
I'm confused about what the exact frame rate should be. I did a hex dump of the source AVI file (DV Type-2) and found the following:

dwScale = 333666 (0x00051762)
dwRate = 10000000 (0x00989680)

The output from mp4dump shows:

sampleDelta = 333667 (0x00051763)
timeScale = 10000000 (0x00989680)

How did 333666 become 333667? Who changed it? DirectShowSource? AviSynth? x264? And what about the frame rate defined by NTSC? Which of the following is correct?


fps in avi = 10000000/333666 = 29.97009
fps in NTSC = 30000/1001 = 29.97003
fps in mp4 = 10000000/333667 = 29.97000

bond
6th January 2006, 14:56
propably some rounding thingie?

edit: post your .avs script too plz

bond
6th January 2006, 15:20
ok i reproduced this crash with haali on 64bit files
gabest's mp4 splitter doesnt crash but simply seems to freeze after seeking
videolan seeks fine, but it takes little bit long
tcpmp handles it fine
mplayer doesnt support 64bit files...

DarkZell666
6th January 2006, 15:39
I also have a seeking problem but it doesn't seem to be the same problem at all ...

Lately, all the encodes I make can't be seeked in by MPC+ffdshow.

It's 23.976fps 60mb anime in mp4 container (with no audio).
I used MeGUI-x264 edition and quality-based QP22 (--crf).

Even after waiting for the next keyframe, the video playback doesn't resume, no matter what frame I seek to. I'll be able to give you more details in a couple of hours when I get home (encoding settings, ffdshow/mpc version, etc) ..

Anyone got an idea ?

ps: I don't have haali's splitter installed, I use MPC's internal one.

Sharktooth
6th January 2006, 15:53
bond already answered. wtf! read before posting!

bond
6th January 2006, 16:14
bond already answered. wtf! read before posting!moo, cool down ;)
my post maybe wasnt shown when he started to write his answer :)

DarkZell666
6th January 2006, 16:20
actually I can't see the link between raymod2's problem and mine :/

bond stated that the problem was due to "64-bit files" ...
If I understood rightely raymod2's file has a wierd fps settings in it (dwRate, dwScale, etc...). The REAL question I think is "what is causing this ?"

Since I'm using MeGUI, there are many things that can be taken into account (the version of mp4box, the version of x264, etc).

After re-reading the hole thread I can agree that the files generated when I do my encodes might suffer the same problem ... but what is the cause and/or solution to the problem ?

(Note : downloading mp4dump just to check)

I do admit the question was a bit silly in itself but how can the problem be fixed ?

edit : in fact the problem is only new, some of my older encodes didn't suffer this problem

bond
6th January 2006, 16:29
actually I can't see the link between raymod2's problem and mine :/than why did you post here?

well i guess your problem is the same as raymonds

bond stated that the problem was due to "64-bit files" ...
If I understood rightely raymod2's file has a wierd fps settings in it (dwRate, dwScale, etc...). The REAL question I think is "what is causing this ?"you would need to ask the one who created that .avi. raymond noticed "directshowsource()", so i assume he passed that avi via directshowsource to x264, which means avisynth is to blame for that wierd values (as you need to define the fps in directshowsource)
i also assume that the .avi has been created via avisynth...

After re-reading the hole thread I can agree that the files generated when I do my encodes might suffer the same problem ... but what is the cause and/or solution to the problem ?the problem is that avisynth passes these very high values for the framerate to x264 and x264 is forced to use 64bit timestamps because of that
now, altough the mp4 files are fine, some players seem to have problems with these 64bit timestamps

for fixing this you can:
- ask the avisynth devs to change this behaviour here (http://forum.doom9.org/showthread.php?t=104681)
- use assumefps(23976,1000) at the end of your avisynth script

Sharktooth
6th January 2006, 16:40
or still use the NiceFPS() filter.

bond
6th January 2006, 16:42
or still use the NiceFPS() filter.why use an external filter, if you can also do it via assumefps()?

Sharktooth
6th January 2006, 16:47
Coz you dont need to check the source fps... you can add it to every script until avisynth gets fixed.

bond
6th January 2006, 16:56
:p ;)

DarkZell666
6th January 2006, 16:57
ok I got the principle more clearly now, thx a lot !

do I get it that adding assumefps(23976,1000) at the end of the script
will result in having dwRate=23976 and dwScale=1000 in the final mp4 file,
and avoiding the 64bit problem ?

in the end, adding assumefps() (edit: or NiceFPS() ;)) will have to become a habit I guess, since
this also solves other problems from what i've read in the AVC forum.



actually I can't see the link between raymod2's problem and mine :/

than why did you post here?

well i guess your problem is the same as raymonds


>> heh, yeah it was a x264 seeking problem ... XD

thx a lot anyway ! ;)

Sharktooth
6th January 2006, 17:00
ok I got the principle more clearly now, thx a lot !

do I get it that adding assumefps(23976,1000) at the end of the script
will result in having dwRate=23976 and dwScale=1000 in the final mp4 file,
and avoiding the 64bit problem ?
Yes.
in the end, adding assumefps() will have to become a habit I guess, since
this also solves other problems from what i've read in the AVC forum.



>> heh, yeah it was a x264 seeking problem ... XD

thx a lot anyway ! ;)
you can add NiceFPS() (use search to find it) as well so you dont have to check the exact source FPS and you can add it to every script.

bond
6th January 2006, 17:01
do I get it that adding assumefps(23976,1000) at the end of the script
will result in having dwRate=23976 and dwScale=1000 in the final mp4 file,
and avoiding the 64bit problem ?using this should make x264 write 32bit timestamps and avoid issues with players having problems with 64bit

raymod2
6th January 2006, 20:19
Just to clarify, MP4 files do not have timestamps. The only timing information for the video stream is contained in the timeScale and sampleDelta fields which are always 32-bit fields.

@bond: I provided a link to my avisynth script in the first post of this thread. I am using DirectShowSource() but I am not supplying the frame rate myself. I am letting DirectShow report it.

@Sharktooth: Does x264 simply copy dwRate and dwScale to timeScale and sampleDelta, respectively? It appears so but that doesn't explain how 333666 gets changed to 333667.

bond
7th January 2006, 03:15
Just to clarify, MP4 files do not have timestamps. The only timing information for the video stream is contained in the timeScale and sampleDelta fields which are always 32-bit fields.still, the derived dts and cts values can be 64bit...

@bond: I provided a link to my avisynth script in the first post of this thread. I am using DirectShowSource() but I am not supplying the frame rate myself. I am letting DirectShow report it.i dont think its that easy, after all there is a reason why you normally have to specify the framerate with directshowsource

raymod2
8th January 2006, 03:34
i dont think its that easy, after all there is a reason why you normally have to specify the framerate with directshowsource

The documentation for DirectShowSource() does not indicate that the user should "normally" specify the frame rate. It says this is only necessary for ASF and MOV files. Unnecessarily overriding the framerate seems like an invitation for desynched audio.

foxyshadis
8th January 2006, 05:08
It needs updating then. Any format which can drop frames needs the framerate specified, if it actually does drop frames. That's asf & mov, but also mp4, mkv, wmv, and others. Avi is safe since null frames are required to be included. Some splitters just plain report the wrong framerate, too, even though they use the correct one internally. Hybrid is just another monkey wrench, though it isn't that common.

raymod2
8th January 2006, 05:58
So the framerate reported by DirectShowSource is 30000/1001 = 29.97002997. The user overrides this by specifying 29.97 which gets converted to 15712911/524288 = 29.96999931. Other than producing a small audio desynch how does this fix the problem of dropped frames?

foxyshadis
8th January 2006, 06:23
Well, I wasn't entirely specific. If the splitter gives bad values it's obviously required, but when you use convertfps=true it repeats null/skipped frames to keep a/v in sync. Normally it just skips them, and a/v sync obviously gets off in a hurry if you don't have something to match frames to timecodes at the end.

(Oh, and mp4, like mkv, does have timecodes, but both only use them for skipped frames (or any frames that don't fit the framerate cleanly) as an optimization.)

Isochroma
8th January 2006, 06:46
Maybe I'm just dumb, but would it work if the user specified 2997/100 for 29.97 fps and 23976/1000 for 23.976 fps? Neither of these two framerates seems to need large double-precision numbers.

Software which uses these fractions can just use a simple algorithm to find the lowest common numerator/denominator, can't it?

raymod2
8th January 2006, 07:53
@Isochroma: Yes, if the user wants to specify the framerate himself then using 2997/100 or 30000/1001 is the best way. The problem with avisynth producing large dwRate and dwScale occurs when the user specifies a string such as 29.97. This string gets converted into a float which cannot represent 29.97 exactly. Then that float gets converted into the ratio of two integers (dwRate and dwScale). Due to the error produced in the first conversion the second conversion produces 15712911/524288 instead of 2997/100.

But I guess we've gotten a little off topic. Large dwRate and dwScale values should not be a problem. I was hoping Haali would comment on whether the seeking problem is being caused by an integer overflow in Haali Media Splitter.

foxyshadis
8th January 2006, 08:11
That's what nicefps does, it'll hopefully be part of the main fps functions in coming versions. (There's a thread about it in avisynth dev.)

Manao
8th January 2006, 09:37
When you open a video via directshowsource, the framerate is read from the directshow graph. That framerate isn't given by a dwRate / dwScale, but by an avgTimePerframe, in 1/10000000 seconds ( ie, it forces dwScale to be 10000000 ). So it creates rounding errors.

bond
8th January 2006, 13:38
gabest has now fixed this seeking error in his mp4 splitter

The documentation for DirectShowSource() does not indicate that the user should "normally" specify the frame rate. It says this is only necessary for ASF and MOV files. Unnecessarily overriding the framerate seems like an invitation for desynched audio..mov files are very similar to .mp4 files, so i would say that statement also refers to .mp4

i guess the reason for this is that in mov/mp4 there is no explicit framerate value stored?

raymod2
8th January 2006, 21:13
When you open a video via directshowsource, the framerate is read from the directshow graph. That framerate isn't given by a dwRate / dwScale, but by an avgTimePerframe, in 1/10000000 seconds ( ie, it forces dwScale to be 10000000 ). So it creates rounding errors.

I think you mean it forces dwRate (not dwScale) to be 10000000. So it was a coincidence that dwRate was 10000000 in my source AVI. To test this I changed dwRate and dwScale to 2997/125 (23.976) in the source AVI and I *still* got 10000000/333667 (29.97) in the MP4 file. I guess it *is* dangerous to let DirectShowSource() choose your frame rate for you.

By the way, do you know why I am unable to use AviSource()? The source file is DV Type-2 and the documentation for DirectShowSource() says it is only needed for DV Type-1. When I try using AviSource(), however, I get the following error:

Avisynth open failure:
AVISource: couldn't locate a decompressor for fourcc dvsd

Manao
8th January 2006, 21:17
You need a dv vfw decoder. FFDshow contains ffvfw which can decode dv, and which supports the fourCC "dvsd". However, it isn't enabled by default, so you have to enable it.

raymod2
8th January 2006, 21:50
Thanks, Manao, I tried using AviSource() with ffdshow and now the dwRate and dwScale from the source AVI are being passed through. Also, the encodes are running 11% faster. However, I did notice something strange. 2997/125 got passed through unchanged but 10000000/333666 got converted to 2000000/66733 (which is an approximation). Any idea what caused this?

Manao
8th January 2006, 21:58
None at all. But the framerates get converted so many times during the loading that is would be a miracle that along the loading, nobody convert it to a float, losing all the accuracy...

bond
15th January 2006, 13:18
haali has now fixed seeking on mp4 files with 64bit mdhd atom in his latest mp4 splitter

so support for 64bit mdhd is still not here in
- quicktime
- mplayer

its buggy in
- ffmpeg

works in
- videolan
- gabest
- haali
- elecard
- nero
- tcpmp

edit: uhm seems i have been to fast, haali still has problems