Mobile: video stops after backgrounding

On iOS especially, when the app goes to the background the system suspends the camera, the renderer surface, and the audio session. Returning to the foreground does not always restore the video pipeline by itself; the user typically sees a frozen or black remote view (and may also lose local preview) until the call is torn down.

Recovery on returning to the foreground:

  1. Re-attach the capture device to the active call. Call pjsua_call_set_vid_strm() with PJSUA_CALL_VID_STRM_CHANGE_CAP_DEV to re-bind the camera. This is a local-only operation; no SDP renegotiation is needed.

  2. Request a keyframe from the peer. When the decoder pipeline has been suspended and resumed, the previous decoder context is typically invalid; the peer needs to send a fresh IDR. The library will issue a PLI/FIR automatically when the decoder reports a missing keyframe (subject to pjsua_call_setting::req_keyframe_method). You can also force the peer’s response by toggling the stream direction or sending a re-INVITE with the same call settings.

  3. Force a fresh outgoing keyframe so the peer’s decoder recovers quickly: pjsua_call_set_vid_strm() with PJSUA_CALL_VID_STRM_SEND_KEYFRAME.

  4. Verify the iOS audio session and background modes. Configure microphone, audio, and voip background modes in Info.plist. With these set, audio survives backgrounding even when video is suspended; without them, audio stops too.

  5. Check Android camera service preemption. Other apps (e.g. the Camera app) can preempt the camera service mid-call. Watch logcat for Camera / Camera2 errors and listen for PJMEDIA_EVENT_VID_DEV_ERROR media events; on receiving one, prompt the user to grant the camera back to your app.

For mid-call capture-device changes (foreground recovery), see the Modifying video during a call section of Working with video media.