Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No public description #14

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 26 additions & 8 deletions Objective-C/BasicExample/app/ViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@
@import GoogleInteractiveMediaAds;

// [START_EXCLUDE]
typedef NS_ENUM(NSInteger, StreamType) {
/// Live stream.
StreamTypeLive,
/// VOD.
StreamTypeVOD,
};

/// Specifies the ad pod stream type; either `StreamTypeLive` or `StreamTypeVOD`.
///
/// Change to `StreamTypeVOD` to make a VOD request.
static StreamType const kStreamType = StreamTypeLive;
/// Live stream asset key.
static NSString *const kLiveStreamAssetKey = @"c-rArva4ShKVIAkNfy6HUQ";
/// VOD content source ID.
static NSString *const kVODContentSourceID = @"2548831";
/// VOD video ID.
static NSString *const kVODVideoID = @"tears-of-steel";
/// Network code.
static NSString *const kNetworkCode = @"21775744923";

/// The backup stream is only played when an error is detected during the stream creation.
static NSString *const kBackupContentUrl =
@"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8";
Expand Down Expand Up @@ -77,20 +97,18 @@ - (void)requestStream {
// Create a stream request. Use one of "Live stream request" or "VOD request", depending on your
// type of stream.
IMAStreamRequest *request;
// Switch this variable to NO to make a VOD request.
BOOL useLiveStream = YES;
if (useLiveStream) {
if (kStreamType == StreamTypeLive) {
// Live stream request. Replace the asset key with your value.
request = [[IMALiveStreamRequest alloc] initWithAssetKey:@"c-rArva4ShKVIAkNfy6HUQ"
networkCode:@"21775744923"
request = [[IMALiveStreamRequest alloc] initWithAssetKey:kLiveStreamAssetKey
networkCode:kNetworkCode
adDisplayContainer:self.adDisplayContainer
videoDisplay:self.imaVideoDisplay
userContext:nil];
} else {
// VOD request. Replace the content source ID and video ID with your values.
request = [[IMAVODStreamRequest alloc] initWithContentSourceID:@"2548831"
videoID:@"tears-of-steel"
networkCode:@"21775744923"
request = [[IMAVODStreamRequest alloc] initWithContentSourceID:kVODContentSourceID
videoID:kVODVideoID
networkCode:kNetworkCode
adDisplayContainer:self.adDisplayContainer
videoDisplay:self.imaVideoDisplay
userContext:nil];
Expand Down
175 changes: 87 additions & 88 deletions Objective-C/PodServingExample/app/ViewController.m
Original file line number Diff line number Diff line change
@@ -1,59 +1,63 @@
// Copyright 2024 Google LLC. All rights reserved.
//
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under
// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
// ANY KIND, either express or implied. See the License for the specific language governing
// permissions and limitations under the License.

#import "ViewController.h"

#import <AVFoundation/AVFoundation.h>

// [START import_ima_sdk]
@import GoogleInteractiveMediaAds;

typedef enum {liveStream, vodStream} streamType;
/// Specifies the ad pod stream type; either `liveStream` or `vodStream`.
static streamType const kRequestType = liveStream;
// [START_EXCLUDE]
typedef NS_ENUM(NSInteger, StreamType) {
/// Live stream.
StreamTypeLive,
/// VOD.
StreamTypeVOD,
};

/// Specifies the ad pod stream type; either `StreamTypeLive` or `StreamTypeVOD`.
///
/// Change to `StreamTypeVOD` to make a VOD request.
static StreamType const kStreamType = StreamTypeLive;
/// Google Ad Manager network code.
static NSString *const kNetworkCode = @"";
static NSString *const kNetworkCode = @"YOUR_NETWORK_CODE";
/// Livestream custom asset key.
static NSString *const kCustomAssetKey = @"";
static NSString *const kCustomAssetKey = @"YOUR_CUSTOM_ASSET_KEY";
// [START custom_vtp_handler]
/// Custom VTP Handler.
///
/// Returns the stream manifest URL from the video technical partner or manifest manipulator.
static NSString *(^gCustomVTPParser)(NSString *) = ^(NSString *streamID) {
static NSString *(^gCustomVTPHandler)(NSString *) = ^(NSString *streamID) {
// Insert synchronous code here to retrieve a stream manifest URL from your video tech partner
// or manifest manipulation server.
NSString *manifestUrl = @"";
return manifestUrl;
// This example uses a hardcoded URL template, containing a placeholder for the stream
// ID and replaces the placeholder with the stream ID.
NSString *manifestUrl = @"YOUR_MANIFEST_URL_TEMPLATE";
return [manifestUrl stringByReplacingOccurrencesOfString:@"[[STREAMID]]"
withString:streamID];
};

/// Fallback URL in case something goes wrong in loading the stream. If all goes well, this will not
/// be used.
static NSString *const kBackupStreamURLString = @"";
// [END custom_vtp_handler]
/// The backup stream is only played when an error is detected during the stream creation.
static NSString *const kBackupContentUrl =
@"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8";
// [END_EXCLUDE]

@interface ViewController () <IMAAdsLoaderDelegate, IMAStreamManagerDelegate>
/// The entry point for the IMA DAI SDK to make DAI stream requests.
@property(nonatomic, strong) IMAAdsLoader *adsLoader;
/// The container where the SDK renders each ad's user interface elements and companion slots.
@property(nonatomic, strong) IMAAdDisplayContainer *adDisplayContainer;
/// The reference of your video player for the IMA DAI SDK to monitor playback and handle timed
/// metadata.
@property(nonatomic, strong) IMAAVPlayerVideoDisplay *imaVideoDisplay;
/// References the stream manager from the IMA DAI SDK after successful stream loading.
@property(nonatomic, strong) IMAStreamManager *streamManager;

/// Content video player.
@property(nonatomic, strong) AVPlayer *contentPlayer;

// UI
// [START_EXCLUDE]
/// Play button.
@property(nonatomic, weak) IBOutlet UIButton *playButton;
/// UIView in which we will render our AVPlayer for content.
/// UIView for the video player.
@property(nonatomic, weak) IBOutlet UIView *videoView;

// SDK
/// Entry point for the SDK. Used to make ad requests.
@property(nonatomic, strong) IMAAdsLoader *adsLoader;
/// Main point of interaction with the SDK. Created by the SDK as the result of an ad request.
@property(nonatomic, strong) IMAStreamManager *streamManager;
/// Video display used by the SDK to play ads.
@property(nonatomic, strong) id<IMAVideoDisplay> videoDisplay;
/// Video player to play the DAI stream for both content and ads.
@property(nonatomic, strong) AVPlayer *videoPlayer;
// [END_EXCLUDE]

@end

Expand All @@ -62,104 +66,98 @@ @implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];

// [START_EXCLUDE]
self.playButton.layer.zPosition = MAXFLOAT;

[self setupAdsLoader];
[self setUpContentPlayer];
}

- (IBAction)onPlayButtonTouch:(id)sender {
[self requestStream];
self.playButton.hidden = YES;
}

#pragma mark Content Player Setup

- (void)setUpContentPlayer {
// Load AVPlayer with path to our content.
NSURL *contentURL = [NSURL URLWithString:kBackupStreamURLString];
self.contentPlayer = [AVPlayer playerWithURL:contentURL];
// Load AVPlayer with path to your content.
NSURL *contentURL = [NSURL URLWithString:kBackupContentUrl];
self.videoPlayer = [AVPlayer playerWithURL:contentURL];

// Create a player layer for the player.
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.contentPlayer];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.videoPlayer];

// Size, position, and display the AVPlayer.
playerLayer.frame = self.videoView.layer.bounds;
[self.videoView.layer addSublayer:playerLayer];
}
// [END_EXCLUDE]

#pragma mark SDK Setup

- (void)setupAdsLoader {
self.adsLoader = [[IMAAdsLoader alloc] initWithSettings:nil];
self.adsLoader.delegate = self;
}

- (void)requestStream {
// Create an ad display container for ad rendering.
IMAAdDisplayContainer *adDisplayContainer =
// Create an ad display container for rendering each ad's user interface elements and companion
// slots.
self.adDisplayContainer =
[[IMAAdDisplayContainer alloc] initWithAdContainer:self.videoView
viewController:self
companionSlots:nil];

// Create an IMAAVPlayerVideoDisplay to give the SDK access to your video player.
self.videoDisplay =
[[IMAAVPlayerVideoDisplay alloc] initWithAVPlayer:self.contentPlayer];
self.imaVideoDisplay = [[IMAAVPlayerVideoDisplay alloc] initWithAVPlayer:self.videoPlayer];
}
// [END import_ima_sdk]

// [START make_stream_request]
- (IBAction)onPlayButtonTouch:(id)sender {
[self requestStream];
self.playButton.hidden = YES;
}

- (void)requestStream {
// Create a stream request.
IMAStreamRequest *request;
if (kRequestType == liveStream) {
// Create a pod serving request for a livestream.
if (kStreamType == StreamTypeLive) {
// Live stream request. Replace the network code and custom asset key with your values.
request = [[IMAPodStreamRequest alloc] initWithNetworkCode:kNetworkCode
customAssetKey:kCustomAssetKey
adDisplayContainer:adDisplayContainer
videoDisplay:self.videoDisplay
pictureInPictureProxy:nil
userContext:nil];
} else {
// Create a pod serving request for a VOD stream.
request = [[IMAPodVODStreamRequest alloc] initWithNetworkCode:kNetworkCode
// VOD request. Replace the network code with your value.
request = [[IMAPodVODStreamRequest alloc] initWithNetworkCode:@kNetworkCode
adDisplayContainer:adDisplayContainer
videoDisplay:self.videoDisplay
pictureInPictureProxy:nil
userContext:nil];
}
[self.adsLoader requestStreamWithRequest:request];
}
// [END make_stream_request]

#pragma mark AdsLoader Delegates

// [START ads_loader_delegates]
- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
// Initialize and listen to stream manager's events.
NSLog(@"Stream created with: %@.", adsLoadedData.streamManager.streamId);
self.streamManager = adsLoadedData.streamManager;
// The stream manager must be initialized before playback for adsRenderingSettings to be
// respected.
[self.streamManager initializeWithAdsRenderingSettings:nil];
self.streamManager.delegate = self;

// Build the Pod serving Stream URL and load into AVPlayer
NSString *streamId = adsLoadedData.streamManager.streamId;
NSString *urlString = gCustomVTPParser(streamId);
// Build the Pod serving Stream URL.
NSString *streamID = adsLoadedData.streamManager.streamId;
// Your custom VTP handler takes the stream ID and returns the stream manifest URL.
NSString *urlString = gCustomVTPHandler(streamID);
NSURL *streamUrl = [NSURL URLWithString:urlString];
if (kRequestType == liveStream) {
if (kStreamType == StreamTypeLive) {
// Load live streams directly into the AVPlayer.
[self.videoDisplay loadStream:streamUrl withSubtitles:@[]];
[self.videoDisplay play];
} else {
// Load VOD streams using the `loadThirdPartyStream` method in IMA SDK's stream manager.
// The stream manager loads the stream, requests metadata, and starts playback.
[self.streamManager loadThirdPartyStream:streamUrl streamSubtitles:@[]];
// There is no need to trigger playback here.
// streamManager.loadThirdPartyStream will load the stream, request metadata, and play
}
NSLog(@"Stream created with: %@.", self.streamManager.streamId);
}

- (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData {
// Something went wrong loading ads. Log the error and play the content.
// Log the error and play the content.
NSLog(@"AdsLoader error, code:%ld, message: %@", adErrorData.adError.code,
adErrorData.adError.message);
[self.contentPlayer play];
[self.videoPlayer play];
}
// [END ads_loader_delegates]

#pragma mark StreamManager Delegates

// [START stream_manager_delegates]
- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdEvent:(IMAAdEvent *)event {
NSLog(@"StreamManager event (%@).", event.typeString);
NSLog(@"Ad event (%@).", event.typeString);
switch (event.type) {
case kIMAAdEvent_STARTED: {
// Log extended data.
Expand Down Expand Up @@ -199,7 +197,8 @@ - (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdEvent:(IMAAd
- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdError:(IMAAdError *)error {
NSLog(@"StreamManager error with type: %ld\ncode: %ld\nmessage: %@", error.type, error.code,
error.message);
[self.contentPlayer play];
[self.videoPlayer play];
}
// [END stream_manager_delegates]

@end
Loading
Loading