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

Creating Custom Media Source, to Mimic the performance of AdMediaSource with Custom Ad Servers #3967

Closed
ram992 opened this issue Mar 9, 2018 · 12 comments
Assignees
Labels

Comments

@ram992
Copy link

ram992 commented Mar 9, 2018

Hello Andrew,
I am opening this as a quesstion only and also as a last resort(tried stackOverFlow and Medium)
I need to implement a Custom MediaSource that Mimics the performance of AdMediaSource that has been created for IMA integration.
I read the code, but got few questions:
How do you manage creating MediaSource placeholders and populate them dynamically,(In between Main Content).
How do you decide when to clip the MainSource(as I saw in the Google I/O 17, that the player only buffers till the adBreakPoint).
Also if you can give me a skeleton of how things work in th AdMediaSource, that would be a lot helpful.
Also Andre, as Suggested by you in medium, I have tried the AdsLoader interface, but there is no method where I can pass a Url of the Ad.My ad Server is a different one than IMA but does the same thing(tell's me when to play ad, but provides Url at the time of playBackOnly(I will teel the server when the position comes, to get the Url)).

@andrewlewis andrewlewis self-assigned this Mar 9, 2018
@andrewlewis
Copy link
Collaborator

The player will pass an AdsLoader.EventListener to attachPlayer on your custom AdsLoader. You can then call eventListener.onAdPlaybackState to provide information about ads, including the number of ad groups, the number of ads in each ad group, the ad media URIs and the "state" of each ad (loaded, played, failed to load). You need to call this method each time the ad playback state changes, for example, when you get a new ad media URI.

Please take a look at ImaAdsLoader for an example implementation that updates the ad playback state in this way, and also tracks the player position. Perhaps a good approach is to make a copy of ImaAdsLoader and strip out the functionality that is specific to the IMA SDK, replacing it with your own ad server integration code.

If you can get things to work using the provided AdsMediaSource and a custom AdsLoader, that will probably save a lot of time compared with implementing the media source functionality from scratch. You won't need write code to create deferred media periods, for example.

@ram992
Copy link
Author

ram992 commented Mar 9, 2018

Thanks, Andrew, for this quick update, I will read the code at ImaAdsLoader and will give it a try.
Can this thread be maintained for some time, like if I have anymore questions/blockers I can ask here directly.

@ram992
Copy link
Author

ram992 commented Mar 9, 2018

Hello Andrew, I read the ImaAdsLoader class, and your mention of AdGroups and Indexes, approach is very different from my Ad Server,
My need is simple, I have a mainContent and need to play Ads in between the MainContent seemLessly(As my current approach is causing a lot of buffering).
I saw that in your IMA implementation and wanted to try that.
All I need to know is how do you define MediaPeriods in between the MainContent(Dummy I expect ) and load them once you get a url I also got the logic of creating a MediaSource once you get a url (Which you are doing in the PlayerActivity that has AdMediaSource implemtation ). I understood about tracking player events from ImaAdsLoader class, thanks for the info.
Also, how do you trigger pre-buffering for both content and ad to give the illusion of no buffer playback.
Sorry once again to bother you by this simple thing, and even an outline of the implementation is enough for me to go on.

@andrewlewis
Copy link
Collaborator

andrewlewis commented Mar 9, 2018

Could you describe a typical playback timeline? Or, could you give a more precise description and/or example of what you mean by 'play ads in between the main content'?

For example, a typical playback might have a a preroll ad, content from 0 to 60 seconds and a midroll ad, followed by content from 60 seconds to the end. That would map onto an ad playback state with two ad groups (at 0 and 60 seconds) with one ad each, and the relevant ad media URIs.

If it's impossible to implement an AdsLoader for your use case, it would be useful to know what limitations cause this.

@ram992
Copy link
Author

ram992 commented Mar 9, 2018

Ok, here is one use case
Let's say I have a movie which is 2 hr long, and also has around 4 ads at predefined positions(I will send these to server).Like at 3min, 7min, 45min, 80min. Currently I keep track of the contentPlayback using a thread and when the time comes, tell my server the same and request for an AdUrl.
Once I get that I use natviePlayer to play the ad and switchback to ExoPlayer once done. And this is causing a lot of Buffering time.
The limitations I see is the group definition, I never did that, and If I have to use AdsLoader I need to use AdsMediaSource to whose constructor I need to send an AdTagUrl which I won't have at any Instance.
You can think this process as though using a DynamicConcatenation at a specific Time Instance of MainContent.

@andrewlewis
Copy link
Collaborator

  • To take advantage of ExoPlayer's buffer-free playback you'll need to play both the ads and content with ExoPlayer (you can't use a different player for content).
  • You don't need to pass an ad tag URI to AdsMediaSource (here's the constructor on the dev branch). If you don't want to overlay any ad URI in your ad loader you can just pass null for adUiViewGroup.
  • In the timeline you describe, you need to make an ad playback state with four ad groups at the times you've given, each with only one ad. Each time you find out an ad URI, update the ad playback state including the new URI. See ImaAdsLoader.loadAd for an example. It's important to do this before playback reaches the ad group time, otherwise the player will buffer until it gets the ad URI.
  • AdsLoader.attachPlayer takes the ExoPlayer instance so you can use this to attach event listeners if you need to handle player events. It sounds like you have a thread polling the player position, so you can do this in your custom ads loader too.

@ram992
Copy link
Author

ram992 commented Mar 9, 2018

Thanks Andrew,
I will try this one out right away and update you.
I was using a diff player cause Moto X Play and Moto G3 devices are force rebooting as soon as I finish ad playback, release the player and then prepare it again with content. I think it has some issue with securePath stuff as the content is DRM protected.

@ram992
Copy link
Author

ram992 commented Mar 12, 2018

Hello Andrew,
Thanks for helping me out.
I tried what you said, and have few questions:
I saw that onAdEvent(an Interface) is triggered by some sdk, cause there is no usage of it.
I am attaching the player as soon as creating the ImaAdsLoader object and in that method calling startPlayback method where I am adding the cue points like this,
// Set up the ad playback state, skipping ads based on the start position as required.
List adTimes = new ArrayList<>();
adTimes.add(10.0f);
adTimes.add(15.0f);
long[] adGroupTimesUs = getAdGroupTimesUs(adTimes);
adPlaybackState = new AdPlaybackState(adGroupTimesUs);
I am doing it correctly ? cause I cannot see any ad Mark on the time line
Also to just test the code I am using a thread that triggers this
adsLoader.loadAd("https://html5demos.com/assets/dizzy.mp4"); in the PlayerActivity
but that is printing an error
java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
at com.google.android.exoplayer2.ext.ima.ImaAdsLoader.getAdIndexInAdGroupToLoad(ImaAdsLoader.java:1069)
at com.google.android.exoplayer2.ext.ima.ImaAdsLoader.loadAd(ImaAdsLoader.java:595)
at example.com.adsdemo.PlayerActivity$1.run(PlayerActivity.java:215)
So, where am I doing wrong ??

@andrewlewis
Copy link
Collaborator

Yes, onAdEvent is called by the IMA SDK.

Are you calling eventListener.onAdPlaybackState(adPlaybackState); to update the media source's ad playback state? Each time you need to update the state (e.g., to add an ad URI or mark an ad as played), the pattern is to call adPlaybackState = adPlaybackState.withSomeChange(...); then invoke eventListener.onAdPlaybackState to update the ad media source to take into account the new information. Please make sure you are setting the number of ads in each ad group by calling withAdCount and setting the content duration in onTimelineChanged by calling withContentDurationUs.

A lot of the code in ImaAdsLoader is specific to the IMA integration so you'll probably need to go through the code and carefully pick out the bits of functionality you need and remove the ones you don't. For example, in loadAd you may well know exactly what ad index is being loaded already, and in that case you wouldn't need getAdIndexInAdGroupToLoad.

@ram992
Copy link
Author

ram992 commented Mar 12, 2018

Sure Andrew, then I will try to spend some time reading the code, will update you.

@ram992
Copy link
Author

ram992 commented Mar 22, 2018

Hello Andrew,
I am closing this issue for now, as I need to concentrate on Actions for Google Assistant. Once I do that will get back to this. Please do not lock the conversation.
Thanks for the Help.

@ram992 ram992 closed this as completed Mar 22, 2018
@andrewlewis
Copy link
Collaborator

The issue may be locked automatically if it's closed for a certain period, but please feel free to file a new issue linking back to this one if you need to. Thanks!

@google google locked and limited conversation to collaborators Aug 10, 2018
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