gen2brain / mpeg

MPEG-1 Video decoder, MP2 Audio decoder and MPEG-PS Demuxer in pure Go
MIT License
129 stars 11 forks source link

`Audio().Time()` sometimes breaks on exact seeks #5

Open tinne26 opened 1 year ago

tinne26 commented 1 year ago

Seems to only happen when the video time doesn't perfectly match the mpeg time. For example, the following program works fine if the seek position is 3000*time.Milliseconds, but breaks at 3001 (requires passing the path to the mpeg file as an argument):

package main
import ( "os" ; "log" ; "time" )
import "github.com/gen2brain/mpeg"

func main() {
    // open file and initialize mpeg
    file, err := os.Open(os.Args[1])
    if err != nil { log.Fatal(err) }
    mpg, err := mpeg.New(file)
    if err != nil { log.Fatal(err) }
    mpg.SetAudioCallback(func(_ *mpeg.MPEG, _ *mpeg.Samples) {})
    mpg.SetVideoCallback(func(_ *mpeg.MPEG, _ *mpeg.Frame) {})

    // seek and print times
    ok := mpg.Seek(3001*time.Millisecond, true)
    if !ok { log.Fatal("seek not ok") }
    log.Printf("mpeg.Time()  = %v", mpg.Time())
    log.Printf("video.Time() = %v", mpg.Video().Time())
    log.Printf("audio.Time() = %v", mpg.Audio().Time())
}

Example output with test.mpg:

2022/11/10 16:53:17 mpeg.Time()  = 3.033333333s
2022/11/10 16:53:17 video.Time() = 3.066666666666667
2022/11/10 16:53:17 audio.Time() = 5.758644444444444
tinne26 commented 1 year ago

Something else is off:

package main
import ( "os" ; "log" ; "time" )
import "github.com/gen2brain/mpeg"

func main() {
    // open file and initialize mpeg
    file, err := os.Open(os.Args[1])
    if err != nil { log.Fatal(err) }
    mpg, err := mpeg.New(file)
    if err != nil { log.Fatal(err) }
    mpg.SetAudioCallback(func(_ *mpeg.MPEG, _ *mpeg.Samples) {})
    mpg.SetVideoCallback(func(_ *mpeg.MPEG, _ *mpeg.Frame) { log.Print("callback") })

    // seek and print times
    ok := mpg.Seek(3*time.Second, false)
    if !ok { log.Fatal("seek not ok") }
}

This calls the callback not once as stated in the documentation, but more than 30 times. In this case, this only happens when seek exact = false. It could probably be a separate issue, but I think the two are closely related as something must be wrong with the seeking code, and any fix should probably attempt to correct all these issues at once. I'll look into it myself if I can next week, but I'll leave it here in the meantime in case someone else also encounters the issue or is motivated to try to fix it.

Curiously, 1 or 2 second seeks do not seem to trigger this.

gen2brain commented 1 year ago

@tinne26 Thanks for filling in the issues. I don't have time right now to check all this.

tinne26 commented 1 year ago

Don't worry, I also have other priorities at the moment, but if I get back to it and make any progress I'll contribute as I can.