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

Using IMA VideoAdPlayer.VideoAdPlayerCallback for ad events gives wrong ad durations for Preroll and Postroll IMA ads #6249

Closed
rs146 opened this issue Jul 31, 2019 · 1 comment
Assignees
Labels

Comments

@rs146
Copy link

rs146 commented Jul 31, 2019

[REQUIRED] Searched documentation and issues

I already opened a question ticket (#5925) with regards to determining Pre-roll, Mid-roll and Postroll ads and since the answer(s) provided there are sufficient for that topic, I have decided to create a new general question.

I have had a look at Google's IMA documentation for getting the duration of an ad.

In addition, I have also looked at getting the duration of an ad by using player.getContentDuration() - however this gives the total duration of the media rather than the individual ad duration.

[REQUIRED] Question

As from my previous discussion, I am using IMA ads in my player. To know when an ad is being played, I am implementing the VideoAdPlayer.VideoAdPlayerCallback from Google's IMA library. For midroll ads in the sample app, when I call this:
(ImaAdsLoader) adsLoader).getAdProgress().getDuration();
I get a true duration of the ad (i.e. 10 seconds).

However, with both preroll and postroll ads when I call:
(ImaAdsLoader) adsLoader).getAdProgress().getDuration();
it returns with -0.001.

I have 2 questions:

  • Is there a way to get the correct duration of IMA ads for both preroll and postroll ads?
  • Why does calling player.isPlayingAd() return false for the postroll ad given that the VideoAdPlayer.VideoAdPlayerCallback#onPlay() callback has been fired?

A full log report captured from the device

07-31 16:09:52.079 20930-20930/com.google.android.exoplayer2.demo D/Player: Preroll onPlay
07-31 16:09:52.079 20930-20930/com.google.android.exoplayer2.demo D/Player: isPlayingAd: true
07-31 16:09:52.079 20930-20930/com.google.android.exoplayer2.demo D/Player: Ad duration: -0.001

07-31 16:10:18.466 20930-20930/com.google.android.exoplayer2.demo D/Player: Midroll onPlay
07-31 16:10:18.466 20930-20930/com.google.android.exoplayer2.demo D/Player: isPlayingAd: true
07-31 16:10:18.466 20930-20930/com.google.android.exoplayer2.demo D/Player: Ad duration: 10.0

07-31 16:25:44.622 20930-20930/com.google.android.exoplayer2.demo D/Player: Postroll onPlay
07-31 16:25:44.622 20930-20930/com.google.android.exoplayer2.demo D/Player: isPlayingAd: false
07-31 16:25:44.622 20930-20930/com.google.android.exoplayer2.demo D/Player: Ad duration: -0.001

Link to test content

For this test, I used the following code in my media.exolist.json:

{
        "name": "Single inline linear",
        "uri": "https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv",
        "ad_tag_uri": "https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpostpod&cmsid=496&vid=short_onecue&correlator="
}

I also changed the PlayerActivity in the demo app to implement the VideoAdPlayer.VideoAdPlayerCallback interface.

In the createAdsMediaSource() method, I have added the following line:

adsLoader.setPlayer(player); // exists from before
((ImaAdsLoader) adsLoader).addCallback(this); // new line

I have overridden the onPlay() method from the VideoAdPlayer.VideoAdPlayerCallback as follows within the updated PlayerActivity:

  @Override
  public void onPlay() {
    Log.d("Player", "onPlay");
    Log.d("Player", "isPlayingAd: " + player.isPlayingAd());
    Log.d("Player", "Ad duration: " + ((ImaAdsLoader) adsLoader).getAdProgress().getDuration());
  }

Tested on sample code versions 2.9.2 and 2.10.3

@andrewlewis
Copy link
Collaborator

andrewlewis commented Aug 2, 2019

It's probably easier and more reliable to use ExoPlayer's API rather than VideoAdPlayerCallback, by listening for onPositionDiscontinuity and onTimelineChanged like this:

@Override
public void onPositionDiscontinuity(@DiscontinuityReason int reason) {
  logAdStatus();
}

@Override
public void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {
  logAdStatus();
}

private void logAdStatus() {
  boolean isPlayingAd = player.isPlayingAd();
  if (isPlayingAd) {
    if (player.getDuration() == C.TIME_UNSET) {
      // We don't know the duration yet.
      return;
    }
    int adGroupIndex = player.getCurrentAdGroupIndex();
    long adGroupTimeUs = player.getCurrentTimeline()
        .getPeriod(player.getCurrentPeriodIndex(), new Period())
        .getAdGroupTimeUs(adGroupIndex);
    String adType = adGroupTimeUs == C.TIME_END_OF_SOURCE ? "postroll" 
        : adGroupTimeUs == 0 ? "preroll" : "midroll";
    Log.w("DEBUG", "Currently playing " + adType
        + " ad at index " + player.getCurrentAdIndexInAdGroup()
        + " in ad group with index " + player.getCurrentAdGroupIndex()
        + " with duration " + player.getDuration());
  } else {
    Log.w("DEBUG", "Currently playing content");
  }
}

If you want to trigger a single event when starting to play the ad once the duration is known you will need to store some state and de-duplicate the events.

The IMA callbacks and ExoPlayer state can't be perfectly synchronized I'm afraid, but we should be exposing the information you need via the player API. Please let me know if this is still a problem for something you need to do and we can investigate further.

@google google locked and limited conversation to collaborators Nov 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants