pion / mediadevices

Go implementation of the MediaDevices API.
https://pion.ly/
MIT License
535 stars 122 forks source link

ForceKeyFrame #464

Open ghost opened 1 year ago

ghost commented 1 year ago

Is there an easy way to call ForceKeyFrame method ?

So far the only way i see reaching this is:

  1. Get senders & tracks from them
  2. Create TrackContext from the track
  3. Create encoder via NewRTPReader from the track and track context
  4. Create keyFrameControllerfrom the encoders controller
  5. Run ForceKeyFrame from the newly created keyFrameController

I'm not sure that this is going to do the trick though because of the manual creation of track context. Couldn't find any example in the repository with this. Has anyone used it before and has an easier way to access it ?

ghost commented 1 year ago

Actually i can't reach it even like that since some of the fields for TrackLocalContext are private and i can't recreate it.

Am i missing something or ForceKeyFrame function cannot be used ?

KW-M commented 1 year ago

I ran into the same issue initially. It would be nice if ForceKeyFrame and SetBitRate were more easily accessible when using the library outside of a WebRTC session or for more manual control generally.

That said, those functions are currently triggered in the library in response to RTCP messages when the track is used in a webrtc session. You can see the code that does that in track.go on line 236 and line 273 < Note these line links are code in my pull request fork but the changes will hopefully get merged soon.

One weird thing is the Pion examples suggest you also need to be reading the RTCP messages in your program to get Pion Mediadevices to handle them correctly (I'm assuming you are streaming with WebRTC in the first place). Many of the Pion examples have this code (in this case the videoTrack would be a track inside the stream from mediadevices GetUserMedia()):

rtpSender, videoTrackErr := peerConnection.AddTrack(videoTrack)
if videoTrackErr != nil {
    panic(videoTrackErr)
}

// Read incoming RTCP packets
// Before these packets are returned they are processed by interceptors. For things
// like NACK this needs to be called.
go func() {
    rtcpBuf := make([]byte, 1500)
    for {
        if _, _, rtcpErr := rtpSender.Read(rtcpBuf); rtcpErr != nil {
            return
        }
    }
}()
EmrysMyrddin commented 1 year ago

@Chimerax2 Do you have some context ? ForceKeyFrame is accessible on a any encoder implementing it. Since all encoders doesn't implement this yet, so you have to do a type conversion like this :

keyFrameController, ok := encodedReader.Controller().(codec.KeyFrameController)
if ok {
    keyFrameController.ForceKeyFrame()
}

@KW-M Yes, I don't think the examples have been reworked since PLI handling has been implemented. It is still better to do it, since the rtcp reading loop is started only if the used codec implements the Key Frame controller.