Giter Club home page Giter Club logo

srgmediaplayer-apple's Introduction

SRG Media Player logo

GitHub releases platform SPM compatible GitHub license

About

The SRG Media Player library provides a simple way to add universal audio / video playback support to any application. It provides:

  • A controller with precise playback state information and and a simple but powerful playback API.
  • Automatic integration with AVPlayerViewController.
  • A set of overlays which can be combined to create custom player user interfaces.
  • Support for subdivision of medias in (non-overlapping) sequences, which can provide am additional finer-grained playback structure or block playback to parts of the content.
  • Support for on-demand, live and DVR streams.
  • Support for 360° and cardboard playback.
  • Ability to use several instances of the player at the same time.

Compatibility

The library is suitable for applications running on iOS 12, tvOS 12 and above. The project is meant to be compiled with the latest Xcode version.

Contributing

If you want to contribute to the project, have a look at our contributing guide.

Integration

The library must be integrated using Swift Package Manager directly within Xcode. You can also declare the library as a dependency of another one directly in the associated Package.swift manifest.

Usage

When you want to use classes or functions provided by the library in your code, you must import it from your source files first. In Objective-C:

@import SRGMediaPlayer;

or in Swift:

import SRGMediaPlayer

Working with the library

To learn about how the library can be used, have a look at the getting started guide.

Logging

The library internally uses the SRG Logger library for logging, within the ch.srgssr.mediaplayer subsystem. This logger either automatically integrates with your own logger, or can be easily integrated with it. Refer to the SRG Logger documentation for more information.

Control preview in Interface Builder

Interface Builder can render custom controls dropped onto a storyboard or a xib. If you want to enable this feature for SRG Media Player controls, copy the SRGMediaPlayerDesignables.m file available from the Swift Package Manager checkout to your project and add it to your target.

When dropping a media player control (e.g. SRGPictureInPictureButton) onto a storyboard or xib, Xcode will now build your project in the background and render the view when it is done.

Remark

Since the SRGMediaPlayerDesignables.m must be copied to your project, you should update this file when updating the SRG Media Player library.

Demo project

To test what the library is capable of, run the associated demo.

License

See the LICENSE file for more information.

srgmediaplayer-apple's People

Contributors

defagos avatar onekiloparsec avatar pyby avatar tooolbox avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

srgmediaplayer-apple's Issues

playerDestructionBlock documentation is misleading

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Description of the problem

Per the documentation, playerDestructionBlock is called before the player is nil'd out, as an opportunity to remove observers:

Three kinds of observers can be set on a player to observe its playback:

  • Usual boundary time and periodic time observers, which you define on the AVPlayer instance directly by accessing the player property. You should use the player creation and destruction blocks to install and remove them reliably.
/**
 *  Optional block which gets called right before player destruction (player changes from not `nil` to `nil`).
 */
@property (nonatomic, copy, nullable) void (^playerDestructionBlock)(void);

However, the player destruction block is called after the player has been replaced:

- (void)setPlayer:(AVPlayer *)player
{
    BOOL hadPlayer = (_player != nil);
    
    if (_player) {
        // un-register internal observers
    }
    
    _player = player; // player replaced

    if (player) {
        if (! hadPlayer) {
            self.playerCreationBlock ? self.playerCreationBlock(player) : nil;
        }

        // various stuff

    }
    else if (hadPlayer) {
        self.playerDestructionBlock ? self.playerDestructionBlock() : nil; // destruction block called
    }
}

Since the player isn't passed as an argument in the destruction block, and it's un-set by the time the block is called, a consumer of the library must create his own reference to that player in the creation block and use that reference to remove observers in the destruction block.

let mediaPlayer = SRGMediaPlayerController()
var timeObserver: Any?
mediaPlayer.playerCreationBlock = { player in
    timeObserver = player.addPeriodicTimeObserver(...)
}
mediaPlayer.playerDestructionBlock = { // no player available
    if let obs = timeObserver {
        mediaPlayer.player?.removePeriodicTimeObserver(obs) // <-- doesn't work, player is nil here
    }
}

You have to do this:

let mediaPlayer = SRGMediaPlayerController()
var timeObserver: Any?
var savedPlayer: AVPlayer?
mediaPlayer.playerCreationBlock = { player in 
    timeObserver = player.addPeriodicTimeObserver(...)
    savedPlayer = player
}
mediaPlayer.playerDestructionBlock = {
    if let obs = timeObserver {
        savedPlayer?.removePeriodicTimeObserver(obs)
    }
    savedPlayer = nil
}

Reproducibility

  • Always reproducible
  • Difficult to reproduce

Suggested Handling

Call the playerDestructionBlock just before reassigning that value, and include the old player as an argument in the block. This will allow someone using SRGMediaPlayer to add & remove observers from the AVPlayer reliably and in a straightforward fashion.

Like so:

let mediaPlayer = SRGMediaPlayerController()
var timeObserver: Any?
mediaPlayer.playerCreationBlock = { player in 
    timeObserver = player.addPeriodicTimeObserver(...)
}
mediaPlayer.playerDestructionBlock = { player in
    if let obs = timeObserver {
        player.removePeriodicTimeObserver(obs)
    }
}

Tracks popover too tall

The tracks popover displayed when tapping on the tracks button is too tall. It should better match the size of the contents within it.

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Environment information

  • Library version: 2.0
  • iOS version: Any
  • Device: Any

Steps to reproduce

  1. Open one of the Apple demo videos
  2. Tap on the tracks button

SRGAirplayView must not hide the video when playing with an airport express

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Description of the problem

When using an airport express, the video must not be hidden by the SRGAirplayView.

Environment information

  • use an airport express. (only audio is broadcasting).
  • Library version: 2.0.1
  • iOS version: All
  • Device: All

Reproducibility

  • Always reproducible
  • Difficult to reproduce

Leak on AVFAudio -[AVAudioSessionPortDescription initWithPortType:]

Issue overview

When calling -[AVAudioSession currentRoute], little leaks appear. (16 to 192 bytes).

Check the correct option below

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Description of the problem

Using Instruments and the demo applications. Use the "Leak checks" tool, we can find those little leak.
From AudioToolbox or AVFAudio libraries.

Environment information

  • Library version: 2.0

Reproducibility

  • Always reproducible
  • Difficult to reproduce

Links

http://stackoverflow.com/questions/41529859/instruments-show-leak-in-avaudiosessionportdescription-initwithporttype-xcod

Provide a way to start playing a segment at a specific time

We currently provide methods to play a given segment, or to switch to another segment. We could add a time parameter to both methods. For API consistency, this parameter must be clamped to the range of the segment. The minimum admissible value, zero, corresponds to the segment beginning, and is the default. The maximum start time is the segment duration.

This way, the API provides more flexibility, and stays consistent. Since playing a segment is different from playing at some time (see SRGMediaPlayerSelectedKey), we cannot namely let selection playback start outside the selected segment time range.

Layout issues after rotation

When pushing a view controller into the navigation, rotating just afterwards breaks the layout.

Hint: This is not a side navigation component bug (this also affects the standard navigation controller). Maybe this is an iOS bug.

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Environment information

Device supporting rotation.

Reproducibility

  • Always reproducible
  • Difficult to reproduce

Steps to reproduce

  1. Open the application
  2. Tap on a topic details button
  3. Immediately rotate the device
  4. The layout is now broken

Add tolerances for playback methods with start time

Specifying an exact start time makes playback startup slower, which is not always what we want. We should add tolerance parameters (like for seeks) to let applications decide whether they want playback startup to be precise (at the expense of startup time) or it the startup position can be less precise (improving startup time).

There is only one specific requirement which needs to be taken into account: No matter the precision, starting playback within a segment must ensure that the initial playback position stays within the segment. The tolerance must therefore be adjusted depending on the initial target position within a segment.

Some unit tests need to be written as well to cover these specific cases.

Crash when closing the player

On some test devices (iPad Mini, iOS 9), we encounter crashes when closing the media player. Those seem to be related to picture in picture.

The problem is probably related to the device (a slow one) or the iOS version. I could not reproduce it with an iPad Air 2 running on iOS 10.

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Description of the problem

The stack trace is entirely made of internal system calls and does not involve SRG media player library or the demo in any way:

* thread #1: tid = 0x344a2, 0x0000000181f76b40 CoreFoundation`___forwarding___ + 700, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x181f76b40)
  * frame #0: 0x0000000181f76b40 CoreFoundation`___forwarding___ + 700
    frame #1: 0x0000000181e74c5c CoreFoundation`_CF_forwarding_prep_0 + 92
    frame #2: 0x0000000181e589b4 CoreFoundation`-[__NSArrayM dealloc] + 152
    frame #3: 0x00000001815f1ae8 libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 508
    frame #4: 0x0000000181e509fc CoreFoundation`_CFAutoreleasePoolPop + 28
    frame #5: 0x00000001873889e4 UIKit`_prepareForCAFlush + 352
    frame #6: 0x000000018738e320 UIKit`_beforeCACommitHandler + 16
    frame #7: 0x0000000181f28728 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
    frame #8: 0x0000000181f264cc CoreFoundation`__CFRunLoopDoObservers + 372
    frame #9: 0x0000000181f268fc CoreFoundation`__CFRunLoopRun + 928
    frame #10: 0x0000000181e50c50 CoreFoundation`CFRunLoopRunSpecific + 384
    frame #11: 0x0000000183738088 GraphicsServices`GSEventRunModal + 180
    frame #12: 0x0000000187132088 UIKit`UIApplicationMain + 204
    frame #13: 0x00000001000c4bd4 SRGMediaPlayer-demo`main(argc=1, argv=0x000000016fd4ba98) + 124 at main.m:14
    frame #14: 0x00000001819ee8b8 libdyld.dylib`start + 4

If enabling zombies, the following information is logged to the console when the crash is encountered:

2017-03-17 08:53:42.170 SRGMediaPlayer-demo[916:214178] *** -[PGHostedWindow release]: message sent to deallocated instance 0x13fe58600

The PGHostedWindow class belongs to Pegasus.framework, a private framework intended for picture in picture. This seems plausible, as the crash does not happen on non PiP enabled devices.

Environment information

  • Library version: 2.0
  • iOS version: 9.3.4
  • Device: iPad Mini

Reproducibility

  • Always reproducible
  • Difficult to reproduce

Steps to reproduce

  1. Open the media player demo on a device (not all devices will suffer the crash, see above)
  2. Play with the custom timeshift / segment demos, opening and dismissing them in a row, until the crash occurs

Popover issues when rotating

When subtitles or Airplay popovers are opened, rotating the device leads to issues (broken layout and lost anchors).

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Modernize standard player layout

The player layout, mostly inspired by MPMoviePlayerViewController, is now outdated. We should now more closely match AVPlayerViewController appearance.

Stream information debugging overlay

For debugging purposes, we should create a debug overlay component, providing various information about the stream (bitrate, available qualities, etc.)

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

The player starts to play if the stop method is called when the playback state is still idle or preparing

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Description of the problem

When we play a media and call the "stop" method while the player is still idle or preparing, the player starts to play anyway

CALL STOP WHILE STILL IDLE AFTER PLAY METHOD IS CALLED

2017-07-27 11:20:41.406371+0200  [4698:1757814] WILL PLAY - PLAYBACKSTATE = 1
2017-07-27 11:20:41.409107+0200  [4698:1757814] DID PLAY - PLAYBACKSTATE =  1
2017-07-27 11:20:41.441540+0200  [4698:1757814] ...
2017-07-27 11:20:42.723282+0200  [4698:1757814] WILL ASK FOR STOP - PLAYBACKSTATE =  1
2017-07-27 11:20:42.723391+0200  [4698:1757814] DID ASK FOR STOP
2017-07-27 11:20:44.635106+0200  [4698:1757814] [Controller] Playing
2017-07-27 11:20:44.635328+0200  [4698:1757814] self.mediaPlayerController.playbackState 2
2017-07-27 11:20:44.639759+0200  [4698:1757814] [Controller] Playback state did change to preparing with info {
    SRGMediaPlayerPlaybackStateKey = 2;
    SRGMediaPlayerPreviousPlaybackStateKey = 1;
    SRGMediaPlayerSelectionKey = 0;
}
2017-07-27 11:20:48.002316+0200  [4698:1757814] self.mediaPlayerController.playbackState 3
2017-07-27 11:20:48.014082+0200  [4698:1757814] [Controller] Playback state did change to playing with info {
    SRGMediaPlayerPlaybackStateKey = 3;
    SRGMediaPlayerPreviousPlaybackStateKey = 2;
    SRGMediaPlayerSelectionKey = 0;
}

CALL STOP WHEN PREPARING

2017-07-27 11:22:35.166238+0200  [4702:1758624] WILL PLAY - PLAYBACKSTATE =  1
2017-07-27 11:22:35.169096+0200  [4702:1758624] DID PLAY - PLAYBACKSTATE =  1
2017-07-27 11:22:38.416480+0200  [4702:1758624] [Controller] Playing 
2017-07-27 11:22:38.416945+0200  [4702:1758624] self.mediaPlayerController.playbackState 2
2017-07-27 11:22:38.417005+0200  [4702:1758624] WILL ASK FOR STOP - PLAYBACKSTATE =  2
2017-07-27 11:22:38.417188+0200  [4702:1758624] self.mediaPlayerController.playbackState 1
2017-07-27 11:22:38.425274+0200  [4702:1758624] [Controller] Playback state did change to idle with info {
    SRGMediaPlayerPlaybackStateKey = 1;
    SRGMediaPlayerPreviousPlaybackStateKey = 2;
    SRGMediaPlayerSelectionKey = 0;
}
2017-07-27 11:22:38.425337+0200  [4702:1758624] DID ASK FOR STOP
2017-07-27 11:22:38.429552+0200  [4702:1758624] [Controller] Playback state did change to preparing with info {
    SRGMediaPlayerPlaybackStateKey = 2;
    SRGMediaPlayerPreviousPlaybackStateKey = 1;
    SRGMediaPlayerSelectionKey = 0;
}
2017-07-27 11:22:41.804323+0200  [4702:1758624] self.mediaPlayerController.playbackState 3
2017-07-27 11:22:41.807534+0200  [4702:1758624] [Controller] Playback state did change to playing with info {
    SRGMediaPlayerPlaybackStateKey = 3;
    SRGMediaPlayerPreviousPlaybackStateKey = 1;
    SRGMediaPlayerSelectionKey = 0;
}

Environment information

  • Library version: 2.0.3
  • iOS version: ANY
  • Device: ANY

Reproducibility

  • Always reproducible
  • Difficult to reproduce

Code sample

- (void)playMedia
{
    NSLog(@" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WILL PLAY  - PLAYBACKSTATE = %tu", self.mediaPlayerController.playbackState);
    [self.mediaPlayerController playURL:[NSURL URLWithString:@"..."]];
    NSLog(@" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DID PLAY  - PLAYBACKSTATE = %tu", self.mediaPlayerController.playbackState);
}


- (IBAction)stopPlayer:(id)sender
{
    NSLog(@"WILL ASK FOR STOP - PLAYBACKSTATE =  %tu", self.mediaPlayerController.playbackState);
    [self.mediaPlayerController stop];
    NSLog(@"DID ASK FOR STOP");
}

- (void)playbackStateDidChange:(NSNotification *)notification
{
    if (self.mediaPlayerController.playbackState == SRGMediaPlayerPlaybackStatePreparing) {
        [self stopPlayer:nil];
    }
}

Steps to reproduce

  1. Setup Network link conditionner to High latency or slow network (easier to reproduce)
  2. Start playing a media
  3. Immediately call stop when player is still preparing or idle
  4. Wait a little while... the media will start to play

Add accurate date support for streams with date information

For streams containing date information, we should rely on this specific information instead.

For information, AVPlayer and AVPlayerItem provide seek to date methods. Moreover, AVPlayerItem provides a currentDate property, which probably not nil when date information is available from the stream.

Sharing Streaming between Players

Hey guys, impressive library!

Issue overview

I would like to be able to share a stream between multiple players, i.e., have a "preview" going in an inline player, and then seamlessly transfer to a main player upon a certain condition.

Check the correct option below

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Description of the problem

As above. With the stock AVPlayerViewController, since it directly uses AVPlayer and you are managing the lifecycle of it, you can start an AVPlayer going, and pass it around to one more AVPlayerViewControllers, or create multiple AVPlayerLayers that all mirror the same AVPlayer. By this mechanism you have the power to have one stream playing in multiple windows or parts of your app that are totally separated from each other, in different View Controller hierarchies, etc.

Since the AVPlayer in this library has a managed lifecycle, how would I go about sharing a given stream between multiple screens/player-views?

Player behavior changes with iOS 11

Starting with iOS 11, some AVPlayer behaviors have slightly changed. Some might be regressions, but in the meantime we should deal with them as best as we can:

  • For a livestream, the loadedTimeRanges and seekableTimeRanges properties return nil right after the player has reached the ready state, and start returning non-nil information slightly afterwards. On iOS 10 and earlier, these properties were returning correct information as soon the player was ready. The two concepts are orthogonal in our implementation (the AVPlayer state is ultimately reflected in the controller playbackState property, whereas timerange and derived properties are transient). But still, the live properties unit test does not work anymore.
  • Seeking outside the media timerange was previously working (resuming at the end), but starting with iOS 11 the media restarts at the beginning. At the controller level, this change impacts playback start, as well as usual seeks.

No read stream MPEG H.264

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Description of the problem

2018-02-26 15:18:43.275921+0500 iosplayer.srgmediaplayer[51620:2563223] [] <<<< AVOutputContext (FigEndpointPicker) >>>> +[AVFigEndpointPickerOutputContextImpl sharedAudioPresentationOutputContext]: Audio presentation output context not supported by FigEndpointPicker
2018-02-26 15:18:43.276114+0500 iosplayer.srgmediaplayer[51620:2563223] [MediaRemote] [AVOutputContext] WARNING: AVF context unavailable for sharedAudioPresentationContext
2018-02-26 15:18:43.276298+0500 iosplayer.srgmediaplayer[51620:2563223] [] <<<< AVOutputContext (FigEndpointPicker) >>>> +[AVFigEndpointPickerOutputContextImpl sharedAudioPresentationOutputContext]: Audio presentation output context not supported by FigEndpointPicker
2018-02-26 15:18:43.276402+0500 iosplayer.srgmediaplayer[51620:2563223] [MediaRemote] [AVOutputContext] WARNING: AVF context unavailable for +[MRAVOutputContext createOutputContextWithUniqueIdentifier:]
2018-02-26 15:18:43.380956+0500 iosplayer.srgmediaplayer[51620:2563310] [] <<<< AVOutputContext (FigEndpointPicker) >>>> +[AVFigEndpointPickerOutputContextImpl sharedAudioPresentationOutputContext]: Audio presentation output context not supported by FigEndpointPicker
2018-02-26 15:18:43.381087+0500 iosplayer.srgmediaplayer[51620:2563310] [MediaRemote] [AVOutputContext] WARNING: AVF context unavailable for +[MRAVOutputContext createOutputContextWithUniqueIdentifier:]
2018-02-26 15:18:44.460652+0500 iosplayer.srgmediaplayer[51620:2563223] [Controller] Playing http://str1.iptvportal.ru:8080/ort/index.m3u8
2018-02-26 15:18:44.468286+0500 iosplayer.srgmediaplayer[51620:2563223] [Controller] Playback state did change to preparing with info {
    SRGMediaPlayerPlaybackStateKey = 2;
    SRGMediaPlayerPreviousPlaybackStateKey = 1;
    SRGMediaPlayerSelectionKey = 0;
}
2018-02-26 15:18:44.478082+0500 iosplayer.srgmediaplayer[51620:2563312] [] <<<< AVOutputContext (FigEndpointPicker) >>>> +[AVFigEndpointPickerOutputContextImpl sharedAudioPresentationOutputContext]: Audio presentation output context not supported by FigEndpointPicker
2018-02-26 15:18:44.478245+0500 iosplayer.srgmediaplayer[51620:2563312] [MediaRemote] [AVOutputContext] WARNING: AVF context unavailable for +[MRAVOutputContext createOutputContextWithUniqueIdentifier:]
2018-02-26 15:18:44.520629+0500 iosplayer.srgmediaplayer[51620:2563310] [] <<<< AVOutputContext (FigEndpointPicker) >>>> +[AVFigEndpointPickerOutputContextImpl sharedAudioPresentationOutputContext]: Audio presentation output context not supported by FigEndpointPicker
2018-02-26 15:18:44.520774+0500 iosplayer.srgmediaplayer[51620:2563310] [MediaRemote] [AVOutputContext] WARNING: AVF context unavailable for +[MRAVOutputContext createOutputContextWithUniqueIdentifier:]
2018-02-26 15:18:44.529859+0500 iosplayer.srgmediaplayer[51620:2563223] <CATransformLayer: 0x6000002205c0> - changing property cornerRadius in transform-only layer, will have no effect
2018-02-26 15:18:44.529998+0500 iosplayer.srgmediaplayer[51620:2563223] <CATransformLayer: 0x6000002205c0> - changing property masksToBounds in transform-only layer, will have no effect
2018-02-26 15:18:44.630913+0500 iosplayer.srgmediaplayer[51620:2563312] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:44.631280+0500 iosplayer.srgmediaplayer[51620:2563312] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:44.631547+0500 iosplayer.srgmediaplayer[51620:2563312] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:44.631831+0500 iosplayer.srgmediaplayer[51620:2563312] [] <<<< FigStreamPlayer >>>> fpfs_EstablishTimebase: Failed to create an AudioDeviceClock, err = -12746, use HostTimeClock instead
2018-02-26 15:18:44.634646+0500 iosplayer.srgmediaplayer[51620:2563312] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:44.635565+0500 iosplayer.srgmediaplayer[51620:2563312] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:44.636278+0500 iosplayer.srgmediaplayer[51620:2563312] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:44.636941+0500 iosplayer.srgmediaplayer[51620:2563312] [] <<<< FigStreamPlayer >>>> fpfs_EstablishTimebase: Failed to create an AudioDeviceClock, err = -12746, use HostTimeClock instead
2018-02-26 15:18:44.639559+0500 iosplayer.srgmediaplayer[51620:2563344] [] <<<< Async >>>> playerasync_runAsynchronousCommandOnQueue: Command 23 returned -12784; this async error will be discarded
2018-02-26 15:18:44.970870+0500 iosplayer.srgmediaplayer[51620:2563312] [] <<<< FigStreamPlayer >>>> fpfs_MakeDolbyChoiceBasedOnAvailableAlternates: [0x7f83c060b4f0]: player can not found a playable alternative for this playback item[0x7f83c1051600]. hwPreferredChannels = [2/0], canDecodeAC3 = 1, canDecodeEC3 = 1, canAC3PassThrough = 0
2018-02-26 15:18:45.622051+0500 iosplayer.srgmediaplayer[51620:2563312] Task <8585BBC1-9167-4B1B-975C-7AC6A90BB33B>.<3> finished with error - code: -999
2018-02-26 15:18:52.062572+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.062717+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.062808+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.062931+0500 iosplayer.srgmediaplayer[51620:2563355] [] <<<< FigStreamPlayer >>>> fpfs_EstablishTimebase: Failed to create an AudioDeviceClock, err = -12746, use HostTimeClock instead
2018-02-26 15:18:52.063497+0500 iosplayer.srgmediaplayer[51620:2563355] [] subaq_findRichestDecodableLayout signalled err=1718449215 (kAudioFormatUnsupportedDataFormatError) (FigAudioFormatDescriptionGetRichestDecodableFormat returned NULL) at /BuildRoot/Library/Caches/com.apple.xbs/Sources/EmbeddedCoreMedia_Sim/EmbeddedCoreMedia-2275.27.3/Prototypes/MediaConverter/FigAudioQueue.c:6946
2018-02-26 15:18:52.063693+0500 iosplayer.srgmediaplayer[51620:2563355] [] faqrp_buildAudioQueue signalled err=1718449215 (err) (FigAudioQueueCreate failed) at /BuildRoot/Library/Caches/com.apple.xbs/Sources/EmbeddedCoreMedia_Sim/EmbeddedCoreMedia-2275.27.3/Prototypes/RenderPipelines/FigAudioQueueRenderPipeline.c:894
2018-02-26 15:18:52.064364+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.064454+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.064577+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.064682+0500 iosplayer.srgmediaplayer[51620:2563355] [] <<<< FigStreamPlayer >>>> fpfs_EstablishTimebase: Failed to create an AudioDeviceClock, err = -12746, use HostTimeClock instead
2018-02-26 15:18:52.065559+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.065653+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.065750+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.065857+0500 iosplayer.srgmediaplayer[51620:2563355] [] <<<< FigStreamPlayer >>>> fpfs_EstablishTimebase: Failed to create an AudioDeviceClock, err = -12746, use HostTimeClock instead
2018-02-26 15:18:52.066107+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.066192+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.066284+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.066419+0500 iosplayer.srgmediaplayer[51620:2563355] [] <<<< FigStreamPlayer >>>> fpfs_EstablishTimebase: Failed to create an AudioDeviceClock, err = -12746, use HostTimeClock instead
2018-02-26 15:18:52.066712+0500 iosplayer.srgmediaplayer[51620:2563355] [] <<<< FigStreamPlayer >>>> fpfs_BytePumpFn: <0x7f83c1051600> error 1718449215 from manifold-substream 0
2018-02-26 15:18:52.066860+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.066952+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.067069+0500 iosplayer.srgmediaplayer[51620:2563355] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.067192+0500 iosplayer.srgmediaplayer[51620:2563355] [] <<<< FigStreamPlayer >>>> fpfs_EstablishTimebase: Failed to create an AudioDeviceClock, err = -12746, use HostTimeClock instead
2018-02-26 15:18:52.071608+0500 iosplayer.srgmediaplayer[51620:2563223] [Controller] Playback state did change to idle with info {
    SRGMediaPlayerLastPlaybackTimeKey = "CMTime: {503999/90000 = 5.600}";
    SRGMediaPlayerPlaybackStateKey = 1;
    SRGMediaPlayerPreviousMediaTypeKey = 1;
    SRGMediaPlayerPreviousPlaybackStateKey = 2;
    SRGMediaPlayerPreviousStreamTypeKey = 3;
    SRGMediaPlayerPreviousTimeRangeKey = "CMTimeRange: {{5600/1000 = 5.600}, {4799/1000 = 4.799, rounded}}";
    SRGMediaPlayerSelectionKey = 0;
}
2018-02-26 15:18:52.071979+0500 iosplayer.srgmediaplayer[51620:2563223] [Controller] Playback did fail with error: Error Domain=ch.srgssr.mediaplayer Code=0 "The media cannot be played" UserInfo={NSLocalizedDescription=The media cannot be played, NSUnderlyingError=0x60000024a6e0 {Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (1718449215), NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x60c000451220 {Error Domain=NSOSStatusErrorDomain Code=1718449215 "(null)" UserInfo={AVErrorFourCharCode='fmt?'}}}}}
2018-02-26 15:18:52.075524+0500 iosplayer.srgmediaplayer[51620:2563344] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.075650+0500 iosplayer.srgmediaplayer[51620:2563344] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.075736+0500 iosplayer.srgmediaplayer[51620:2563344] [AudioHAL_Client] AudioHardware.cpp:1200:AudioObjectRemovePropertyListener:  AudioObjectRemovePropertyListener: no object with given ID 0
2018-02-26 15:18:52.075842+0500 iosplayer.srgmediaplayer[51620:2563344] [] <<<< FigStreamPlayer >>>> fpfs_EstablishTimebase: Failed to create an AudioDeviceClock, err = -12746, use HostTimeClock instead

Environment information

  • Library version: 2.2.2
  • iOS version: simulator target 10.0

Reproducibility

  • Always reproducible
  • Difficult to reproduce

Code sample

let mrl1 = URL(string:"http://str1.iptvportal.ru:8080/ort/index.m3u8")!
let player = SRGMediaPlayerViewController()
player.controller.play(mrl1)

navigationController?.present(player, animated: true, completion: nil)
player.view.frame = self.view.bounds
self.addChildViewController(player)
self.view.addSubview(player.view)

Steps to reproduce

  1. This stream http://str1.iptvportal.ru:8080/ort/index.m3u8 correct read VLC Player
    2018-02-26_15-12-03

  2. SRGMediaPlayer no read this stream

  3. No documentation about supporting codecs

  4. In debug information not present description codec reading current stream

URL with RTSMediaPlayerViewController issue.

Hi there.

I have my own ViewController where I use AVAudioRecorder and AVAudioPlayer to record and play sound.
Both recorder and player is set to nil and stopped when leaving my ViewController, not even sure if this is necessary.

Then in another ViewController I try to play that sound from before, which is stored at Amazon with the following:

let vc = RTSMediaPlayerViewController(contentURL: url);
self.presentViewController(vc, animated: true, completion: nil);

This works fine if I haven't visited the ViewController with the AVAudioRecorder and AVAudioPlayer first.
But if I record a sound in my controller, sends it to Amazon, leave my controller, open another controller and try to open the URL with your RTSMediaPlayerViewController it doesn't work.

It shows the correct time, so if the file is 10 seconds your controller shows the 00.00 to -00:10, but it wont play the sound.

If I recompile my app/forcequit and I go straight to the controller with your RTSMediaPlayerViewController it works fine, so is there something I should release in my controller containing the AVAudioRecorder and AVAudioPlayer?

My log gives me the following:

[RTSMediaPlayer] Invalid Transition: An attempt was made to fire the 'Pause' event while in the 'Paused' state, but the event can only be fired from the following states: Ready, Playing, Seeking

  • When I click play.

AVPlayer 0x14888af80 deallocated while a pending preroll is still in progress; leaking completion handler. Use -cancelPendingPrerolls to deallocate an AVPlayer safely while a preroll is still pending.

  • Sometimes when i leave the RTSMediaPlayerViewController.

iOS 12 issues

On iOS 12, there are playback start issues, leading to failing unit tests and glitches when starting a video (try e.g. playing the Apple advanced stream a few times).

The standard iOS player does not seem affected, which means something has changed (as always with each iOS major release...), but that a fix is possible on our side.

Add test for notification vs. controller property consistency

To ensure both notifications and view controller properties can be used in equivalent ways (which should readily be the case), we should add a test showing that all properties available both if state change notifications and as controller properties are consistent.

This way, there is no need to test such consistency elsewhere, and either notification user information or controller properties can be used indifferently when writing other tests.

SRGTimeSliderDelegate should tell if isMovingToPlaybackTime is passive or not

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Description of the request

When seeking with -seekToTime:withToleranceBefore:toleranceAfter:completionHandler: several times, the SRGTimeSliderDelegate called each time on -timeSlider:isMovingToPlaybackTime:withValue:interactive:, but we don't know if this call is from a normal playback, or with a coded seek.

It could be great to have this informations.
-timeSlider:isMovingToPlaybackTime:withValue:interactive:forced: ?

  • Library version: current develop branch 2.0

  • Always reproducible

  • Difficult to reproduce

Code sample

On our private project SRGLetterbox

Muting video stops system wide audio

A user of the library reports this issue: once a video is muted, the audio is muted globally.

Steps to reproduce:

  1. Start music e.g. in Spotity or the music app
  2. Run app that uses SRGMediaPlayer and programatically mute the sound ( playerController.muted = YES )

What happens:
All sounds are muted, incl. the sound of other apps.

Expected:
Sound of media player is muted, but Spotify continues to play

Tested with version:
SRGMediaPlayer 1.9.9
OS: iOS9.3.2

How play a muted video without impacting other audio apps?

Thanks

Imprecise seeks in AirPlay or when a bluetooth headset is used

When using AirPlay or a bluetooth headset, the player does not seek precisely to the correct location immediately (but in its vicinity). We could probably mitigate this issue somehow.

To reproduce, run the unit tests with a headset plugged in. Tests require precise seeking will fail.

Interstitial Implementation

Issue overview

AVPlayerViewController offers a feature for interstitial content, whereby you can mark certain time ranges in your content. A delegate object will then be notified when the player hits those ranges, and this can be used to halt scrubbing and/or disable player controls. This feature is covered here in the documentation, and is currently only available for tvOS.

Interstitial Content. Some content might be unrelated to the main content presented in your player view controller, or have different presentation requirements. For example, you might not allow the user to skip over advertisements when scrubbing through the playback timeline, or require that the user not skip mandatory legal notices.

Use the AVInterstitialTimeRange class to describe interstitial content, and the interstitialTimeRanges property to associate those time ranges with the AVPlayerItem object presented in the player view controller. Then, you can use the player view controller’s delegate object to be notified when interstitial content plays, and change playback options such as the requiresLinearPlayback property accordingly.

You guys have something called "segments", which I don't fully understand and haven't seen in any other players, and you can "block" them and so forth. At first I thought this might be your own terminology or solution for the subject of interstitials, but after reviewing the methods it doesn't seem related.

Couple questions and points:

  • I'm going to need to implement this functionality, one way or another, because I need to prevent people from scrubbing past interstitials in my content.
  • I'm using SRGMediaPlayer in my app, so whatever implementation I do, it will be with your player.
  • Any suggestions on the best way to go about this, architecturally? <-- most important question ^_^
  • Would you be interested in this as a contribution to your library?
  • Would I need to write it in Objective-C to contribute it to your library?
  • Any other thoughts?

Check the correct option below

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: coordination

Xcode 8 can't build SRGMediaPlayer module

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: Build issue

Description of the problem

I’m encountering an issue during the migration to Xcode 8. After removing all other dependencies, it seems to problem might lie in the Podfile/Configuration of the player. I’ve created a new sample swift project in Xcode 8 and added a bridging header. When I try to bridge SRGMediaPlayer to use with swift, I get the following error:

Could not build module ‚SRGMediaPlayer’

Environment information

Xcode 8
CocoaPods 1.0.1

Reproducibility

  • Always reproducible
  • Difficult to reproduce

Code sample

See attached.

Steps to reproduce

  1. Open the sample workspace in Xcode 8. The project should compile fine.
  2. Now open up the bridging header (PlayerTest-Bridging-Header.h) and uncomment the import of the SRGMediaPlayer.

=> You should now get the error mentioned above.

It seems the problem is specific to the project, since adding and bridging another one works fine. I’ve added FXReachability as a counter example of a podspec that works.

Seek bar use is not smooth for some medias

When playing Big Buck Bunny with SRG MediaPlayer, using the slider during playback is cumbersome. This is not the case with the iOS built-in AVPlayerViewController.

The problem disappears after the media has been entirely buffered.

This is due to seeking happening while tracking (if seekingDuringTracking is set to NO, this issue disappears). We could probably implement a smarter way of triggering seeking while tracking.

EXC_BAD_INSTRUCTION when running tests with Xcode 8.3

When running tests with Xcode 8.3, seek tests consistently crash with an EXC_BAD_INSTRUCTION. This is probably an XCTest framework regression. Create a radar.

No issues were encountered with previous Xcode versions. Tests all successfully pass on Xcode 8.2.1.

Improve performance in scrollable views

When using in a scrollable view (table, collection), media starts lead to hiccups on some devices. Several strategies could be investigated to improve the situation:

  • Improve asynchronous AVPlayer resource loading, maybe use a custom AVAssetResourceLoader
  • Use AsyncDisplayKit
  • Hack something else

Add FairPlay streaming support

FairPlay streaming is not so difficult to add. We only need a way to provide a custom AVAssetResourceLoaderDelegate to the AVPlayer to perform the license acquisition for DRM-protected contents.

An optional delegate can probably be supplied at SRGMediaPlayerController initialialization, since it should not have to change during controller use (and should support protected as well as non-protected content).

There are a few limitations with FairPlay streaming:

  1. FairPlay streaming only works with applications and does not work with Safari. This is not related to SRG Media Player, but still needs to be kept in mind.
  2. FairPlay streaming does not work with mirroring (usesExternalPlaybackWhileExternalScreenIsActive set to NO). Only the sound is played. This is quite surprising as we could think the device acquires the licenses and is only mirrored as is on the Airplay receiver, but it seems this is part of FairPlay over Airplay implementation:

See the FairPlay Overview document Figure 1-3 (https://developer.apple.com/services-account/download?path=/Documentation/FairPlay_Streaming_Overview/FairPlayStreaming_Overview.pdf) which describes FPS streaming over AirPlay. In an AirPlay scenario, the FPS request is always routed through the app. The AppleTV never talks to the Key Server directly to get keys. To do this, the app must set the usesExternalPlaybackWhileExternalScreenIsActive property of the AVPlayer object to TRUE with code like this:

// create AVPlayer object
player = [AVPlayer playerWithURL:movieURL];
// set the property to TRUE
player.usesExternalPlaybackWhileExternalScreenIsActive = TRUE;

This is discussed in the FairPlay Streaming Programming Guide section titled “Configuring AirPlay Mode” (https://developer.apple.com/services-account/download?path=/Developer_Tools/FairPlay_Streaming_SDK/FairPlay_Streaming_Server_SDK.zip).

In other words, your app will receive the callback with the SPC just like in the local playback case. The behavior you are seeing is expected. You should expect your app to make the FPS request even in the case of AirPlay streaming.

This does not surprise me entirely, though, as even some apparently non-protected streams won't play correctly when mirroring with Quicktime or using a Lightning to VGA adapter.

Write Apple bug report for resilience against broken playlists

If one of the qualities available in the HLS playlist is broken for some reason, and especially if this quality is the start one, AVPlayer fails. ExoPlayer or other implementations are smarter and use other available qualities.

Write an Apple bug report about such issues.

Incorrect state when disconnecting Airplay while the player is seeking

If Airplay is disconnected when the player is seeking, playback does not correctly resume on the device.

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Description of the problem

If Airplay is disconnected when the player is seeking, playback does not correctly resume on the device. The loading indicator spins endlessly. Seeking to an arbitrary location fixes the issue, though.

Environment information

  • Library version: 2.0
  • iOS version: Any
  • Device: Any

Reproducibility

  • Always reproducible
  • Difficult to reproduce

Steps to reproduce

  1. Open the media player demo
  2. Play Apple Advanced Stream using the SRG media player
  3. Enable Airplay
  4. Seek and disconnect Airplay before seeking ends
  5. The player is now in an inconsistent state

Incorrect player state after stall for some medias

For some medias (e.g. SWI helicopter video: https://srgplayerswivod-vh.akamaihd.net/i/41981254/,video,.mp4.csmil/master.m3u8), resuming after the player stalled does not happen well, and the playback state notification to playing is not received. Accordingly, clients will not reflect the current player state.

How to reproduce

  1. Play the above URL with the demo
  2. When the media is playing, use Airplane mode to disconnect the network, then seek to a non-buffered location. The player stalls
  3. Restore the connection. The sound resumes (even subtitles if available), but the video does not. If you wait sufficiently long, video will restart, but not in sync with the audio

If you try the same with the standard iOS player in the demo, the player restarts at the beginning.

For other medias (e.g. Apple demo streams), the behavior for both players is correct, i.e. playback resumes where it was stuck.

Playback statistics debug overlay

We should add a playback statistics overlay for debugging purposes or for non-release builds, mostly. This overlay could for example display:

  • The bit rate
  • The stream variant used (if possible)
  • etc.

Accessibility element vs. opacity?

Currently, the time slider declares itself as an accessibility element.

It appears that such elements with opacity equal to 0 are still accessible. At the very least the -isAccessibility method could probably return self.alpha != 0.f, but it seems strange to me that VoiceOver works does not exclude such elements.

Once we have a good answer, we should update the time slider and check other accessible elements in all our projects.

360° playback possible improvements

We now support 360 video playback directly in SRG Media Player. There are still a few ideas which could be implemented:

  • Limit motions to +pi/2 and -pi/2 when moving up and down.
  • Disable pan gesture with cardboard and re-center.
  • Add inertia to pan gestures.
  • Implement camera reset to face the content.
  • Have camera orientation stable under device rotation.

None of those have been discussed or are mandatory, I just wanted to keep track of what could be possible if we want to go further.

Player dont stop buffering ui state (statusbar)

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Description of the problem

The Player don't stop the buffering (maybe only ui state) anymore again.
You could see this in the statusbar.

Environment information

  • Library version: newest
  • iOS version: 9.3.5
  • Device: All

Reproducibility

Check the correct option below

  • Always reproducible
  • Difficult to reproduce

Code sample

I allocate the players like that:

//----------------------------------------------------------------------------------------------
-(RTSMediaPlayerController_)mediaplayerWithUrl:(NSURL_)url
//----------------------------------------------------------------------------------------------
{
if (!url) { return nil; }
[self.mediaplayer pause];
self.mediaplayer = nil;
return [[RTSMediaPlayerController alloc] initWithContentURL:url];
}

i stop like that :

[self.mediaplayer pause];

Steps to reproduce

  1. Play a realtime audio (for example radio stream: https://www.crowdradio.de/kunden/puls_br/puls_hifi.m3u )
  2. stop it
  3. the statusbar spinning wheel never stop again (but on cpu load i cant see something interesting, its around 0-2% load)

iOS 11 end-of-stream issues

Starting with iOS 11, a few weird issues affect end-of-stream playback:

  • Attempting to seek to the end of a some medias fails. The controller never leaves the seeking state.
  • For some medias (e.g. 19h30 of the demo project), after playback normally ends, the playback button must be tapped twice to restart playback.

These problems do not occur on iOS 10 or below.

We initially hid these iOS 11 regressions under the rug (most notably failing tests, see 264668a), thinking they might be ironed out with iOS 11 minor releases. This is not the case with iOS 11.2, and I think we now must address those issues, as the probability they get fixed in a near future diminishes.

Incorrect livestream behavior starting with iOS 11.3

Livestreams are not immediately identified as being live starting with iOS 11.3. During an initial period, the stream is namely reported as DVR, and buffering can be observed.

The iOS standard player seems affected as well (but the initial period is very short). The issue can probably be mitigated somehow.

Issue type

Incorrect behavior

Environment information

  • Library version: Any
  • iOS version: 11.3
  • Device: Any

Reproducibility

Always reproducible

Steps to reproduce

  1. Open the demo on an iOS 11.3 device (or within the simulator).
  2. Play the livestream example.
  3. Observe the slider and user interface behavior.

Play method using AVPlayerItem

Issue overview

  • Incorrect behavior
  • Feature request
  • Crash
  • Help / documentation
  • Other: classification

Description of the problem

Using SRG Media Player, there is no way to handle authentication issues on a stream. Because the API only exposes playing URLs, options like this one for setting auth headers on the AVURLAsset are unavailable.

Environment information

  • Library version: 2.2.2
  • iOS version: 11.0
  • Device: All

Reproducibility

  • Always reproducible
  • Difficult to reproduce

Code sample

All of the playing methods seem to trace down to this:

- (void)prepareToPlayURL:(NSURL *)URL
                  atTime:(CMTime)time
            withSegments:(NSArray<id<SRGSegment>> *)segments
           targetSegment:(id<SRGSegment>)targetSegment
                userInfo:(NSDictionary *)userInfo
       completionHandler:(void (^)(void))completionHandler
{
    ...
    AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:URL];
    self.player = [AVPlayer playerWithPlayerItem:playerItem];
    ...
}

Suggestions

Refactor the API to expose play methods that deal directly with the AVPlayerItem, giving users of the library a way to controls headers on requests.

...I would probably attempt a PR but my Objective-C is rusty, and for the moment, all I need is HTTP Basic Auth so I can hack it into the URL, so to speak.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.