Custom I/O data support

Hi folks!

Today we are going to talk about the new feature of iOS VideoKit, released in version 2.7 : Custom I/O data support

Until version 2.7, VideoKit needed a file or network url to play audio/video stream. Starting from version 2.7, it’s possible to provide custom audio/video stream data to VideoKit without giving a url. That means VideoKit can now play any audio/video stream in memory with Custom I/O support.

We included a new ViewController(CustomIOViewController.m) in our sample project, in order to show how custom I/O feature is used.
To simulate a/v stream data in memory, we first read the video file’s a/v data into memory and play the data stream in memory not from the file url.

Let’s see how this feature is used with code samples:

if (!_player) {
   self.player = [[[VKPlayerController alloc] init] autorelease];
   [self.view addSubview:_player.view];
   UIView *playerView = _player.view; playerView.translatesAutoresizingMaskIntoConstraints = NO;
   // align playerView from the left
   [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-28-[playerView(==264)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(playerView)]];
   // align playerView from the top
   [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-38-[playerView(==167)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(playerView)]];
}
_player.decoderOptions = options;
_player.enableCustomIO = YES; // (1)
_player.customIODelegate = self; // (2)

The last two lines above are important to enable customIO usage (1) and provide data to VideoKit (2).

At least below required method must be implemented to make customIO feature work successfully:

/**
* Required delegate method, add this method to your viewcontroller to provide A/V stream data to ffmpe *
* @param player The player object that owns the notification
* @param data Indicates the data pointer to be filled
* @param size Indicates the size of the data pointer to be filled */
- (int)player:(VKPlayerControllerBase *)player ioStreamRead:(uint8_t *)data size:(int)size;

To make the usage easy, we have also implemented a special structure for customIO feature in the player:

typedef struct VKPlayerCustomIO {
    ///The customIO descriptor to hold custom IO data pointer.
   void *customIODescriptor;
    ///The customIO total size to be used for moving pointer on custom IO descriptor
   size_t customIOSize;
    ///The customIO last byte read index to be used for moving pointer on custom IO descriptor
   unsigned long lastByteIndex;
    ///The data used for passing argument to read_data method callback
   void *opaque;
} VKPlayerCustomIO ;

This way, it will be easy to fill data variable, hold the last read byte index of data in memory and return the read size.

- (int)player:(VKPlayerControllerBase *)player ioStreamRead:(uint8_t *)d ata size:(int)size {
    size_t lenFinal = 0;
    size_t bytesRemaining = player.customIO->customIOSize - player.customIO->lastByteIndex;
    if (size < bytesRemaining) {        lenFinal = size;     } else {        lenFinal = bytesRemaining;     }    void *customIOBuffer = (void *)player.customIO->customIODescriptor;
   memcpy( data , &customIOBuffer[player.customIO->lastByteIndex], lenFinal);
   player.customIO->lastByteIndex += (unsigned int)lenFinal;
   return (int)lenFinal;
}

If desired, other optional delegate methods can be implemented:

/**
* Optional delegate method, add this method to your viewcontroller to be able to seek in your A/V stream *
* @param player The player object that owns the notification
* @param offset Indicates the offset bytes of data
* @param whence Indicates the size of the data pointer to be filled
* Important : Even if You don't want to implement A/V stream seeking functionality, this method must be
implemented with a "-1" return value */
- (UInt64)player:(VKPlayerControllerBase *)player ioStreamSeek:(uint64_t)offset whence:(int)whence;
/**
* Optional delegate method, this method is a helper method and it's good for including the custom openi
socket/file etc. code and this method must return 0 for successful opening * @param player The player object that owns the notification
*/
- (VKError)ioStreamOpenForPlayer:(VKPlayerControllerBase *)player;
/**
* Optional delegate method, this method is a helper method and it's good for including the custom closin
socket/file etc. code
* @param player The player object that owns the notification */
- (void)ioStreamCloseForPlayer:(VKPlayerControllerBase *)player;

How to use these methods are already shown in CustomIOViewController.m file in our sample project.
You can checkout the source code for more information about the delegate methods.

Hope you enjoyed the new Custom I/O data support feature of iOS VideoKit 🙂
See you!

Posted in Blog and tagged , .