# CEInStreamAD

## Characteristics

* **Three types of in-stream video ads are supported: pre-roll, mid-roll and post-roll.**
  * **Pre-roll ads**

    Pre-roll ads are displayed before the content video. Ads are played once user starts the playback of content video.
  * **Post-roll ads**

    Post-roll ads are displayed after the content video finished playing. Ads are played once the content video finished playing.
  * **Mid-roll ads**

    Mid-roll ads are served in the middle of content video at each cue points. Multiple mid-roll ads can be arranged in single video.

    * Cue points at which to show ads are defined in 3 different policies, **Every N Seconds**, **Fixed Time** or **Fixed Percentage**.
    * Ad break at each cue point manages duration and number of video ad to be played in 3 different rules, **Single, Fixed time** or **Multi Ad.**

## Integration

#### Add Files for InStream Ad Integration

Add `CEInStreamAD.h` to app's build target.

#### Declare InStream Ad

* Import `CEInStreamAD.h`&#x20;
* Set up `CEInStreamADDelegate` and `CEContentProgressProvider` protocol in view controller's extension.
* Create a CEInStreamAD instance and keep its reference.

```
// MyViewController.m

#import "CEInStreamAD.h"
@interface MyViewController() <CEInStreamADDelegate, CEContentProgressProvider>

@property (nonatomic, strong) CEInStreamAD *inStreamAD;
@end
```

#### Initialize InStream Ad

* Initialize CEInStreamAD instance and necessary properties.

```
- (void)viewDidLoad {  
    // [NOTE]
    // It is recommended to initialize as early as possible.
    //
    CERequestInfo *info = [CERequestInfo new];
    info.placement = @“PUT_YOUR_PLACEMENT_ID_HERE”; 
    self.inStreamAD = [[CEInStreamAD alloc] initWithRequestInfo:info
                                                    adContainer:self.videoView
                                             videoViewProfile:CEVideoViewProfileInStreamDefaultProfile];
    // [NOTE]
    // To set up CERequestInfo for InStream AD, the only property required
    // is "placement". Setting up "place", "timeout", "localExtra",
    // "adWidth" are unnecessary.
    //
    // ***DEPRECATED*** //
    // self.inStreamAD = [[CEInStreamAD alloc] initWithPlacement:@"PUT_YOUR_PLACEMENT_ID_HERE"
    //                                              adContainer:self.videoView
    //                                         videoViewProfile:CEVideoViewProfileInStreamDefaultProfile];
    // **************** //
    self.inStreamAD.delegate = self;
    self.inStreamAD.progressProvider = self;
}
```

#### Request InStream Ad

* `startAutoRequestAD` **must be** called **after** CEInStreamAD instance is initialized
* `startAutoRequestAD` **shall be** called **before** video content is played, otherwise ad breaks in the beginning of the video, pre-roll ad especially, will be wasted
* \*\*Please call `startAutoRequestAD` for only one time for each CEInStreamAd instance.

  \*\*

```
- (void)viewDidAppear:(BOOL)animated{

    [self.inStreamAD startAutoRequestAD];
}
```

#### Implement CEInStreamADDelegate to handle InStream Ad Event

```
- (void)inStreamADDidFail:(CEInStreamAD *)inStreamAD 
                withError:(NSError *)error{
    // [NOTE]
    // Callback if fail to load an InStream ad from Intowow SDK
    //
}

-(void)inStreamADRequestContentPause:(CEInStreamAD *)inStreamAD 
                         adBreakType:(CEADBreakType)adBreakType 
                            cuePoint:(CEMilliSec)cuePoint{
    // [NOTE]
    // After inStreamADRequestContentPause, ad is ready
    // and can be played after video player is paused.
    //
    // [Pre-roll]
    // Pre-roll ad might be prepared later than video content start playing.
    // In this case, SDK will still callback to this function with
    // cuePoint equal to 0. Please mind this scenario and do not
    // start InStream ad if you only wish pre-roll ad to be played before
    // video content start playing.
    //
    [self.yourVideoPlayer pause];
    [self.inStreamAD play];
}

- (void)inStreamADRequestContentResume:(CEInStreamAD *)
                              duration:(CEMilliSec)totalDuration
               inStreamAD adRemainTime:(CEMilliSec)adRemainTime{
    // [NOTE]
    // Two scenario to trigger inStreamADRequestContentResume: 
    // (1) Video ad is finished (adRemainTime = 0)
    //    --> Please stop inStreamAD and resume Video Player
    // (2) Time requirement of ad break has been met (adRemainTime > 0)
    //    --> Resume Video Player or keep playing ad is up to you. 
    //        If you chose to complete playing video ad, inStreamADRequestContentResume
    //        will be called again once ad is finished(scenario (1)).
    //
    // [Best Practice]
    // inStreamADRequestContentResume is best for resume playing video
    // content if InStream ad finished playing.
    //
    [self.inStreamAD stop];
    [self.yourVideoPlayer play];
}

- (void)inStreamProgress:(CEInStreamAD *)inStreamAD 
                duration:(CEMilliSec)totalDuration
                position:(CEMilliSec)currentPosition{
    // [NOTE]
    // inStreamProgress is best for monitoring
    // e.g.
    // [self.inStreamAD getCurrentADNum];
    // [self.inStreamAD getTotalADNum];
    // [self.inStreamAD getADRemainTime];
    // [self.inStreamAD getADBreakRemainTime];
    //
}

- (void) inStreamADDidVideoStart:(nonnull CEInStreamAD *)inStreamAD{
}

- (void) inStreamADDidVideoEnd:(nonnull CEInStreamAD *)inStreamAD{
}

- (void) instreamADDidClick:(nonnull CEInStreamAD *)inStreamAD{
}

- (void) instreamADDidMute:(nonnull CEInStreamAD *)inStreamAD{
}

- (void) instreamADDidUnmute:(nonnull CEInStreamAD *)inStreamAD{
}

- (void) inStreamADWillTrackImpression:(nonnull CEInStreamAD *)inStreamAD{
}

- (void) inStreamADCuePointReady:(nonnull CEInStreamAD *)inStreamAD{
    // [NOTE]
    // getCuePoints shall be called after inStreamADCuePointReady
    // e.g.
    // [inStreamAD getCuePoints];
    //
}
```

#### Implement CEContentProgressProvider to update Video Content Status

* `isContentPlayerReady`, `getContentCurrentPosition` and `getContentTotalDuration` **must be** implemented otherwise InStream ad will not be served
* **Please read this carefully:** During the time user is seeking the video, app should always return the progress time that user start seeking instead of the current time that user has sought to. Once user stop seeking, please return the progress time that user stopped at.

  ![](/files/-LGU_zzn0i7SLU0L6zd7)

```
- (NSTimeInterval) getContentTotalDuration
{
    CMTime totalDuration = self.yourVideoPlayer.currentItem.asset.duration;
    return (NSTimeInterval)CMTimeGetSeconds(totalDuration);
}

- (NSTimeInterval) getContentCurrentPosition
{
    CMTime currentTime = self.yourVideoPlayer.currentItem.currentTime;
    if (!self.isPlayerSeeking) {
        self.lastCurrentPosition = currentTime;
    }

    return (NSTimeInterval)CMTimeGetSeconds(self.lastCurrentPosition);
}

- (BOOL) isContentPlayerReady
{
    return (self.yourVideoPlayer.status == PlayerStatusReadyToPlay);
}
```

#### Release InStream Ad

* InStream ad shall at least be released along with the life cycle of video content

```
- (void)viewWillDisappear:(BOOL)animated
{
    if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) {
        [self.inStreamAD destroy];
        self.yourVideoPlayer = nil;
    }
}
```

#### Advance Integration

* [`CEVideoViewProfileInStreamDefaultProfile`](/crystalexpress-documentation-v3-x/ios-sdk/api-reference/ceinstreamad.md#InitInStreamAd) can be configured base on your need on InStream ad:

```
CEVideoViewProfile videoViewProfile = 
    CEVideoViewProfileSpeaker |
    CEVideoViewProfileCountDown |
    CEVideoViewProfileSilentStart |
    CEVideoViewProfileAdIcon |
    CEVideoViewProfileSkipButton |
    CEVideoViewProfileAdCount;

self.inStreamAD = [[CEInStreamAD alloc] initWithPlacement:@"PUT_YOUR_PLACEMENT_ID_HERE"
                                              adContainer:self.videoView
                                         videoViewProfile:videoViewProfile];
```

![](/files/-LGUa-wu5DZczaPxTCFg)

* 7 properties in total for InStream ad. Properties in CEVideoViewProfile represent different elements on InStream ad UI. (Please refer to diagram above)
  * `CEVideoViewProfileInStreamDefaultProfile`:  All elements included and volume on when InStream ad start playing
  * `CEVideoViewProfileSilentStart`: Volume off when InStream ad start playing

    (A) `CEVideoViewProfileSpeaker`: Top left speaker

    (B) `CEVideoViewProfileAdCount`: Bottom left AdCount

    (C) `CEVideoViewProfileAdIcon`: Top right ad icon

    (D) `CEVideoViewProfileCountDown`: Top right count down timer

    (E) `CEVideoViewProfileSkipButton`: Bottom right skip button
* Customized Skip Button 1. Please exclude `CEVideoViewProfileSkipButton` from CEVideoViewProfile instance otherwise customized view will be overlapped by default Skip view. 2. Pass the customized view through[`registerViewForDismiss`](/crystalexpress-documentation-v3-x/ios-sdk/api-reference/ceinstreamad.md#registerViewForDismiss) to enable Skip function of customized view. Please call `registerViewForDismiss` before `startAutoRequestAD` in case Skip function did not work on InStream ad. 3. Customized view must be passed by `registerFriendlyObstruction` if it is on top of and overlap InStream ad. 4. **\[Recommended]** Mechanism to show and hide customized Skip button need to be handled by app. Default Skip button from Intowow SDk needs no effort from app and is recommended.

```
//Sample for Setting up Customized Skip button
CEVideoViewProfile videoViewProfile = 
    (CEVideoViewProfileInStreamDefaultProfile &= ~CEVideoViewProfileSkipButton);

self.inStreamAD = [[CEInStreamAD alloc] initWithPlacement:@"PUT_YOUR_PLACEMENT_ID_HERE"
                                              adContainer:self.videoView
                                         videoViewProfile:videoViewProfile];
[self.inStreamAD registerViewForDismiss:yourCustomizedView];
```

* Please pass any views that overlap ad view by [`registerFriendlyObstruction`](/crystalexpress-documentation-v3-x/ios-sdk/api-reference/ceinstreamad.md#registerFriendlyObstruction) for the completeness of viewability tracking

## API Reference

| Public constructors                                                                                                                                                                                                                                                      |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| <p><a href="/pages/-LGU_vTxfD08jXP2YooA#InitWithRequestInfo">initWithRequestInfo:(nonnull CERequestInfo <em>)requestInfo adContainer:(nonnull UIView</em>)adContainer videoViewProfile:(CEVideoViewProfile)videoViewProfile</a> <br> Instantiates a new InStream ad.</p> |
| <p><a href="/pages/-LGU_vTxfD08jXP2YooA#InitInStreamAd">initWithPlacement:(NSString <em>)placement adContainer:(UIView</em>)adContainer videoViewProfile:(CEVideoViewProfile)videoViewProfile</a> <br> (Deprecated) Instantiates a new InStream ad.</p>                  |

| Public methods                   |                                                                                                                                                                                                                                                                                                                                                                                  |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| void                             | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#registerViewForDismiss">registerViewForDismiss:(nonnull UIView \*)view</a> <br> Register view as Skip button.</p>                                                                                                                                                                                                                        |
| void                             | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#registerFriendlyObstruction">registerFriendlyObstruction:(nonnull NSArray\*)views</a> <br> Please pass any views that overlap ad view so that viewability tracking can be completed.</p>                                                                                                                                                 |
| void                             | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#startAutoRequestAD">startAutoRequestAD</a> <br> Request in-stream ads automatically.<br> It shall only be called after CEInStreamAd is intialized.<br><strong>Please call</strong> <code>startAutoRequestAD</code> <strong>for only one time for each CEInStreamAd instance.</strong></p>                                                |
| void                             | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#contentComplete">contentComplete</a> <br> Notification of the end of video content.<br><strong>It is critical to ensure Post-roll ad being served. If it is called in the middle of video content and there is ad to be served, post-roll ad will be served.</strong></p>                                                                |
| void                             | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#play">play</a> <br> Play InStream ad.</p>                                                                                                                                                                                                                                                                                                |
| void                             | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#stop">stop</a> <br> Stop InStream ad.<br><strong>Once certain  InStream video ad is stopped, it cannot resumes playing.</strong></p>                                                                                                                                                                                                     |
| void                             | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#destroy">destroy</a> <br> Release InStream ad.<br>InStream ad shall at least  be released along with video player.</p>                                                                                                                                                                                                                   |
| `nullable NSArray <NSNumber*> *` | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#getCuePoints">getCuePoints</a> <br> Return an array of cue points in NSNumber representing milli-second.<br>Return <code>nil</code> if total duration of content video is not available.</p>                                                                                                                                             |
| int                              | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#getCurrentADNum">getCurrentADNum</a> <br> Return the index(Start from 1) of InStream ad that is playing out of the number of ad should be served in current ad break.<br><strong>It should be called during ad break, otherwise it will return</strong> <code>kCECurrentADNumInvalid</code><strong>.</strong></p>                        |
| int                              | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#getTotalADNum">getTotalADNum</a> <br> Return the total number of InStream that is expected to be played within current ad break.<br><strong>If it is not called in ad break or it is called in ad break but the total number of ad is not predictable,</strong> <code>kCEToTalADNumInvalid</code> <strong>will be returned.</strong></p> |
| CEMilliSec                       | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#getADBreakRemainTime">getADBreakRemainTime</a> <br> Return the time left for current ad break.<br><strong>If it is not called in ad break or it is called in ad break but the remaining time of ad break cannot be calculated,</strong> <code>getADBreakRemainTime</code> <strong>will be returned.</strong></p>                         |
| CEMilliSec                       | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#getADRemainTime">getADRemainTime</a> <br> Return the time left for current playing InStream ad.<br><strong>It should be called during ad break, otherwise it will return</strong> <code>kCEADRemainTimeInvalid</code><strong>.</strong></p>                                                                                              |

| Public Properties |                                                                                                                                                                                                                                                                           |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| NSDictionary      | <p><a href="/pages/-LGU_vTxfD08jXP2YooA#customEventExtra">customEventExtra</a> <br> Extra info that is passed in third-party custom event when InStream Ad is loaded.<br><strong>It is a nullable value, null is expected to receive if no key-value is set.</strong></p> |

## Public Constructors

### initWithRequestInfo <a href="#initwithrequestinfo" id="initwithrequestinfo"></a>

```
initWithRequestInfo:(nonnull CERequestInfo *)requestInfo 
        adContainer:(nonnull UIView*)adContainer
    videoViewProfile:(CEVideoViewProfile)videoViewProfile
```

Instantiates a new InStream ad.

| Parameters       |                                                                                                                                                                                                                                                                                                                                                                     |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| info             | Request information                                                                                                                                                                                                                                                                                                                                                 |
| adContainer      | UIView that ad will be played on                                                                                                                                                                                                                                                                                                                                    |
| videoViewProfile | CEVideoViewProfile to define elements to be shown on Video ad. CEVideoViewProfileInStreamDefaultProfile will include all supporting elements with auto volume control. (Supporting MACRO: CEVideoViewProfileSpeaker, CEVideoViewProfileCountDown, CEVideoViewProfileSilentStart, CEVideoViewProfileAdIcon, CEVideoViewProfileSkipButton, CEVideoViewProfileAdCount) |

### (Deprecated)initWithPlacement <a href="#initinstreamad" id="initinstreamad"></a>

```
initWithPlacement:(NSString *)placement
      adContainer:(UIView*)adContainer
 videoViewProfile:(CEVideoViewProfile)videoViewProfile
```

Instantiates a new InStream ad.

| Parameters       |                                                                                                                                                                                                                                                                                                                                                                     |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| placement        | A specific group of ad units denoted in NSString, on which an advertiser can choose to place their ads using placement targeting                                                                                                                                                                                                                                    |
| adContainer      | UIView that ad will be played on                                                                                                                                                                                                                                                                                                                                    |
| videoViewProfile | CEVideoViewProfile to define elements to be shown on Video ad. CEVideoViewProfileInStreamDefaultProfile will include all supporting elements with auto volume control. (Supporting MACRO: CEVideoViewProfileSpeaker, CEVideoViewProfileCountDown, CEVideoViewProfileSilentStart, CEVideoViewProfileAdIcon, CEVideoViewProfileSkipButton, CEVideoViewProfileAdCount) |

## Public Methods

### registerViewForDismiss <a href="#registerviewfordismiss" id="registerviewfordismiss"></a>

```
- (void) registerViewForDismiss:(nonnull UIView *)view
```

Register view as Skip button.

| Parameters |                                         |
| ---------- | --------------------------------------- |
| view       | UIView to be registered for skip event. |

### registerFriendlyObstruction <a href="#registerfriendlyobstruction" id="registerfriendlyobstruction"></a>

```
- (void) registerFriendlyObstruction:(nonnull NSArray<UIView *>*)views
```

Please pass any views that overlap ad view so that viewability tracking can be completed.

| Parameters |                                                          |
| ---------- | -------------------------------------------------------- |
| views      | UIView NSArray storing all views overlapping InStream ad |

### startAutoRequestAD <a href="#startautorequestad" id="startautorequestad"></a>

```
- (void) startAutoRequestAD
```

Request in-stream ads automatically. It shall only be called after CEInStreamAd is intialized. **Please call** `startAutoRequestAD` **for only one time for each CEInStreamAd instance.**&#x20;

### contentComplete <a href="#contentcomplete" id="contentcomplete"></a>

```
- (void) contentComplete
```

Notification of the end of video content. **It is critical to ensure Post-roll ad being served. If it is called in the middle of video content and there is ad to be served, post-roll ad will be served.**

### play <a href="#play" id="play"></a>

```
- (void) play
```

Play InStream ad.

### stop <a href="#stop" id="stop"></a>

```
- (void) stop
```

Stop InStream ad. **Once certain InStream video ad is stopped, it cannot resume playing.**

### destroy <a href="#destroy" id="destroy"></a>

```
- (void) destroy
```

Release InStream ad. InStream ad shall at least be released along with the life cycle of video content.

### getCuePoints <a href="#getcuepoints" id="getcuepoints"></a>

```
- (nullable NSArray<NSNumber *>*) getCuePoints
```

Return an array of cue points in NSNumber representing milli-second. Return `nil` if total duration of content video is not available.

| Returns                |                                                                          |
| ---------------------- | ------------------------------------------------------------------------ |
| `NSArray<NSNumber *>*` | NSNumber array with all cue points in NSNumber representing milli-second |

### getCurrentADNum <a href="#getcurrentadnum" id="getcurrentadnum"></a>

```
- (int) getCurrentADNum
```

Return the index(Start from 1) of InStream ad that is playing out of the number of ad should be served in current ad break. **It should be called during ad break, otherwise it will return** `kCECurrentADNumInvalid`**.**

| Returns |                                                              |
| ------- | ------------------------------------------------------------ |
| int     | The index of InStream ad that is playing in current ad break |

### getTotalADNum <a href="#gettotaladnum" id="gettotaladnum"></a>

```
- (int) getTotalADNum
```

Return the total number of InStream ad that is expected to be played within current ad break. **If it is not called in ad break or it is called in ad break but the total number of ad is not predictable,** `kCEToTalADNumInvalid` **will be returned.**

| Returns |                                                                               |
| ------- | ----------------------------------------------------------------------------- |
| int     | Total number of InStream ad that is expected to be played in current ad break |

### getADBreakRemainTime <a href="#getadbreakremaintime" id="getadbreakremaintime"></a>

```
- (CEMilliSec) getADBreakRemainTime
```

Return the time left for current ad break. **If it is not called in ad break or it is called in ad break but the remaining time of ad break cannot be calculated,** `getADBreakRemainTime` **will be returned.**

| Returns    |                                    |
| ---------- | ---------------------------------- |
| CEMilliSec | The time left for current ad break |

### getADRemainTime <a href="#getadremaintime" id="getadremaintime"></a>

```
- (CEMilliSec) getADRemainTime
```

Return the time left for current playing InStream ad. **It should be called during ad break, otherwise it will return** `kCEADRemainTimeInvalid`**.**

| Returns    |                                               |
| ---------- | --------------------------------------------- |
| CEMilliSec | The time left for current playing InStream ad |

## Public Properties

### customEventExtra <a href="#customeventextra" id="customeventextra"></a>

```
@property (nonatomic, strong, readonly, nullable) NSDictionary * customEventExtra;
```

Extra info that is passed in third-party custom event when InStream Ad is loaded.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://intowow.gitbook.io/crystalexpress-documentation-v3-x/ios-sdk/api-reference/ceinstreamad.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
