9 Replies Latest reply: Aug 10, 2011 11:59 AM by Kimi (Catalin Dobre) RSS

    How to send authenticate token in OSMF player

    larryzzl Community Member

      Hi everyone


      I'm new to Flash Access and trying to setup a basic player with OSMF (1.5). I read "Understanding the protected content workflow" and find it is for flv & flv.metadata. From that document, I can only send authenticate token after the DRMContentData is created. So this is the recommend workflow:

       

      1. Load .metadata file
      2. new DRMContentData with the loaded data
      3. set authenticate token by drmManager.setAuthenticationToken
      4. load voucher


      But when I try F4M file with OSMF player, things are changed. After the .f4m file is loaded by mediaFactory.createMediaElement(new URLResource(URL)), OSMF starts to do the authenticate by itself without give me a chance to set my token. The first event from DRMEvent.DRM_STATE_CHANGE I received is DRMState.AUTHENTICATION_ERROR, and there is no DRMContentData anywhere I can use to send my token.


      I can see one request has been sent out to license server from Fiddler but the return value has limited readle words, some of them are:

       

      en_US�=0;  com.adobe.flashaccess.errors  e�   Cannot decrypt request�� �0� �0� ��      k�օ����:cs�N��0

       

      The code to create a simple OSMF player is realy simple:

           [SWF(backgroundColor="0x000000", frameRate="25", width="640", height="380")]
           public class ASWebPlayer extends Sprite
           {
                private var mediaPlayer:MediaPlayer;
                private var mediaContainer:MediaContainer;
                private var mediaFactory:DefaultMediaFactory;
                private var drmManager:DRMManager;
                
                public function ASWebPlayer()
                {
                     mediaPlayer = new MediaPlayer;
                     mediaPlayer.autoPlay = true;
                     mediaPlayer.autoDynamicStreamSwitch = true;
                     mediaPlayer.addEventListener(DRMEvent.DRM_STATE_CHANGE, onDRMChange, false, 0, true);
                     
                     mediaFactory = new DefaultMediaFactory;
                     mediaContainer = new MediaContainer;
                     addChild(mediaContainer);
                     
                     var mediaElement:MediaElement = mediaFactory.createMediaElement(new URLResource(F4M_URL));
                     mediaContainer.addMediaElement(mediaElement);
                     mediaPlayer.media = mediaElement;
                }
                
                protected function onDRMChange(event:DRMEvent):void
                {
                     trace(event.drmState);
                }
           }
      

        • 1. Re: How to send authenticate token in OSMF player
          Eric.H Adobe Employee

          Hi,

           

          Are you attempting to set a custom authentication token?    "drmManager.setAuthenticationToken()" is only used if you want to manually set your own custom token, or if you want to change the authentication token that is issued to a client.

           

          Normally, here is the workflow:

          1. Create DRMContentData from metadata

          2. Set your user credentials with drmManager.authenticate()

          3. Flash Access will talk to the server, and then retrieve an authentication token. 

          4. Now, every time the client talks to the server (like during drmManager.loadVoucher()), the authentication token from step #4 will automatically be attached to the license request.  You do not have to ever call .setAuthenticationToken() unless you want to override this token.

           

           

          cheers,

          /Eric.

          • 2. Re: How to send authenticate token in OSMF player
            larryzzl Community Member

            Hi Eric

             

            Thanks for the reply. The workflow you mentioned is documented in the link I provided and I read it before. The issue I have now is I'm now trying to load a .f4m file (generated by f4mpackage to support http dynamic streaming), I don't have a .metadata file so I can't greate the DRMContentData for doing the authenticate. With OSMF, I pass the url of .f4m file to MediaElement and it handles all the rest.

             

            Do you mean even we package a f4m file, we can generate the .metadata file at the same time?

             

            Thanks.

            • 3. Re: How to send authenticate token in OSMF player
              Eric.H Adobe Employee

              Hi,

               

              The .f4m file is actually a manifest file.  Within that file (if you open it in a web browser), you'll see that it actually references a DRM Metadata.  OSMF automatically parses this manifest and extracts the metadata present in the <drmAdditionalHeader> tag.  If you need access to that metadata, it is available via:

               

              • resource.drmContentData (for single bitrate scenarios)
              • In the resource DRM metadata namespace (for multi-bitrate scenarios)

               

              Here is a helper function that'll return the extracted content metadata for a specified resource.  When the media element is ready, you have access to the drmContentData and can start any custom authorization/authentication workflow. Otherwise once the playback has been started, OSMF will follow the default workflow.

               

              /**
               * @private
               * 
               * Checks for DMR metadata both in SBR and MBR cases. In SBR case, the DRM metadata is 
               * saved in drmContentData property. In MBR case, the DRM metadata can  
               * also be present as stream-based metadata in DRM namespace. In this case, we will 
               * return the medatata for the specified stream.
               */
              private function getDRMContentData(resource:MediaResourceBase, streamName:String):ByteArray
              {
                   if (streamName == null)
                   {
                        return null;
                   }
                   
                   var streamingResource:StreamingURLResource = resource as StreamingURLResource;
                   if (streamingResource != null)
                   {
                        // [CASE 1] We are in SBR or MBR case where the DRM metadata is
                        // present in drmContentData property so we just return it.
                        if (streamingResource.drmContentData != null)
                        {
                             return streamingResource.drmContentData;
                        }
                        
                        // [CASE 2] We have a DRM namespace associated with this resource
                        // which may contain the actual drmData. 
                        var drmMetadata:Metadata = resource.getMetadataValue(MetadataNamespaces.DRM_METADATA) as Metadata;
                        if (drmMetadata != null && drmMetadata.keys.length > 0)
                        {
                             return drmMetadata.getValue(streamName) as ByteArray;
                        }
                   }
                   
                   return null;
              }
               
              
              
              

               

              But, if you would like access to the DRM metadata before starting playback, below is sample code which will wait for the READY state in the player before trying to get the metadata.

               

              package
              {
                   import flash.display.Sprite;
                   import flash.utils.ByteArray;
                   
                   import org.osmf.elements.ProxyElement;
                   import org.osmf.events.MediaPlayerStateChangeEvent;
                   import org.osmf.media.DefaultMediaFactory;
                   import org.osmf.media.MediaElement;
                   import org.osmf.media.MediaPlayer;
                   import org.osmf.media.MediaPlayerState;
                   import org.osmf.media.MediaResourceBase;
                   import org.osmf.media.URLResource;
                   import org.osmf.metadata.Metadata;
                   import org.osmf.metadata.MetadataNamespaces;
                   import org.osmf.net.StreamingURLResource;
                   import org.osmf.traits.DRMTrait;
                   import org.osmf.traits.MediaTraitType;
              
                   public class HelloWorld10 extends Sprite
                   {
                        public function HelloWorld10()
                        {
                             var protectedF4M:String = "http://10.131.237.107/vod/mbr/drm/sample1_drm_700kbps.f4m";
                             
                             var factory:DefaultMediaFactory = new DefaultMediaFactory();
                             var mediaElement:MediaElement = factory.createMediaElement(new URLResource(protectedF4M));
                             
                             player = new MediaPlayer();
                             player.addEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, onMediaPlayerState);
                             player.autoPlay = false;
                             player.media = mediaElement;
                        }
                        
                        /**
                         * @private
                         * 
                         * Event handler for MediaPlayer state change. On READY/PLAYING state 
                         * we should have access both to the DRMTrait or to the real resource.
                         */
                        protected function onMediaPlayerState(event:MediaPlayerStateChangeEvent):void
                        {
                             if (event.state == MediaPlayerState.READY)
                             {
                                  var actualMediaElement:MediaElement = getActualMediaElement(player.media as ProxyElement);
                                  var resource:StreamingURLResource = actualMediaElement.resource as StreamingURLResource;
                                  
                                  // this the actual DRM content metadata 
                                  var drmProtectedContent:ByteArray = getDRMContentData(resource, null);
                                  
                                  var drmTrait:DRMTrait = player.media.getTrait(MediaTraitType.DRM) as DRMTrait;
                                  if (drmTrait != null)
                                  {
                                       // create the token or do some other custom workfows
                                       var token:Object = null;
                                       
                                       // do something with the drm content metadata
                                       // and with the drm trait
                                       drmTrait.authenticateWithToken(token);
                                  }
                             }
                        }
                        
                        /**
                         * @private
                         * 
                         * Gets the actual media element. When working with F4M files, the OSMF will
                         * usually create a proxy element containing the actual video element.
                         */
                        private function getActualMediaElement(media:MediaElement):MediaElement
                        {
                             var iterator:MediaElement = media;
                             while (iterator != null && iterator is ProxyElement)
                             {
                                  iterator = ProxyElement(iterator).proxiedElement;
                             }
                             
                             return iterator;
                        }
                        
                        /**
                         * @private
                         * 
                         * Checks for DMR metadata both in SBR and MBR cases. In SBR case, the DRM metadata is 
                         * saved in <code>drmContentData</code> property. In MBR case, the DRM metadata can  
                         * also be present as stream-based metadata in DRM namespace. In this case, we will 
                         * return the medatata for the specified stream.
                         */
                        private function getDRMContentData(resource:MediaResourceBase, streamName:String):ByteArray
                        {
                             var streamingResource:StreamingURLResource = resource as StreamingURLResource;
                             if (streamingResource != null)
                             {
                                  // [CASE 1] We are in SBR or MBR case where the DRM metadata is
                                  // present in drmContentData property so we just return it.
                                  if (streamingResource.drmContentData != null)
                                  {
                                       return streamingResource.drmContentData;
                                  }
                                  
                                  // [CASE 2] We have a DRM namespace associated with this resource
                                  // which may contain the actual drmData. 
                                  var drmMetadata:Metadata = resource.getMetadataValue(MetadataNamespaces.DRM_METADATA) as Metadata;
                                  if (drmMetadata != null && drmMetadata.keys.length > 0)
                                  {
                                       if (streamName == null)
                                       {
                                            // maybe we should look for the first child
                                            // and return that value
                                            return null;
                                       }
              
                                       return drmMetadata.getValue(streamName) as ByteArray;
                                  }
                             }
                             
                             return null;
                        }
                        
                        private var player:MediaPlayer = null;
                   }
              }
              

              • 4. Re: How to send authenticate token in OSMF player
                larryzzl Community Member

                Hi Eric

                 

                Thanks for the demo code. I think you showed me the workflow I want. But there is one problem with the code. The package "org.osmf.metadata.MetadataNamespaces" can not be found neither in OSMF 1.5 nor 1.6. So I can not use "MetadataNamespaces.DRM_METADATA". And searching on Adobe doesn't return me useful results. Is there anything I can do with this?

                 

                Thanks.

                • 5. Re: How to send authenticate token in OSMF player
                  Kimi (Catalin Dobre)

                  Usually this kind of error indicates that the player is linking with the wrong version of the OSMF.swc ( probably version 1.0 which is delivered with the Flex SDK).  The recommended way is to update the project setting to link with a specific version of OSMF.swc and not with version 1.0

                   

                  If you are using Flash Builder then:

                  1. go to project properties page of the player

                  2. go to "ActionScript Build Path" section

                  3. make sure that "Library path" tab is selected

                  4. in the "Build path libraries" tree expand "Flex SDK" node

                  5. it should list a bunch of swc which will be linked with your project

                  6. select the osmf.swc and click "Remove"

                  7a. if you want to use the compile SWC, then press "Add SWC..." and select the OSMF.swc version 1.5 or version 1.6 downloaded on your system

                  7b. if you want to use the project, the press "Add Project..." and select the OSMF project imported from the sources in your workspace.

                  8. press "OK" to save the changes

                   

                  Clean and compile. It should work.

                   

                  You may also copy the osmf.swc vversion 1.5 or 1.6 over the osmf.swc in the Flex SDK directory.

                   

                  Hope it helps,

                  Kimi

                  • 6. Re: How to send authenticate token in OSMF player
                    larryzzl Community Member

                    Hi Kimi

                     

                    I removed the osmf.swc inside the sdk and link to a new 1.5 version. I checked the source code and found the org.osmf.metadata.MetadataNamespaces is marked [Internal] so no ourside link is allowed. But since I can access the source, I know the string value and I can use it directly.

                    • 7. Re: How to send authenticate token in OSMF player
                      Kimi (Catalin Dobre) Community Member

                      The MetadataNamespaces class is only excluded from ASDoc generation process through [ExcludeClass] metadata ( kind of ironic i know ) but it should be available for using if imported directly. The code provided above should compile without warning or errors related to MetadataNamespaces class.

                      • 8. Re: How to send authenticate token in OSMF player
                        larryzzl Community Member

                        Hi Eric

                         

                        I find the getDRMContentData doesn't work for my test content (the url I sent you by private email). It's a MBR content so it goes to case 2. But drmMetadata returns null after run the code and so the getDRMContentData returns null. I call this right after the DRMTrait is loaded. My purpose is to send custom data to server by using setAuthenticationToken which requires a drmContentData.

                         

                        Could you help me on this?

                         

                        var video:MediaElement = osmf.factory.createMediaElement(resource);
                        video.addEventListener(MediaElementEvent.TRAIT_ADD, onTraitAdd, false, 0, true);
                        osmf.player.media = video;
                        osmf.container.addMediaElement(video);
                        
                        private function onTraitAdd(event:MediaElementEvent):void
                        {
                             switch (event.traitType)
                             {
                                  case MediaTraitType.DRM:
                                       var drmTrait:DRMTrait = osmf.player.media.getTrait(MediaTraitType.DRM) as DRMTrait;
                                       
                                       var actualMediaElement:MediaElement = getActualMediaElement(osmf.player.media as ProxyElement);
                                       var resource:StreamingURLResource = actualMediaElement.resource as StreamingURLResource;
                                       
                                       // this the actual DRM content metadata 
                                       var drmProtectedContent:ByteArray = getDRMContentData(resource, null);
                                       
                                       break;
                             }
                        }
                        

                        • 9. Re: How to send authenticate token in OSMF player
                          Kimi (Catalin Dobre) Community Member

                          If you need to authenticate using a token, then the following workflow should work:

                           

                          var video:MediaElement = osmf.factory.createMediaElement(resource);
                          osmf.player.media = video;
                          player.addEventListener(DRMEvent.DRM_STATE_CHANGE, onDRMStateChange);
                          osmf.container.addMediaElement(video);
                           
                          protected function onDRMStateChange(event:DRMEvent):void
                          {
                               if (event.drmState == DRMState.AUTHENTICATING)
                               {
                                    // here we can call authenticateWithToken method as drmTrait is fully initialized
                                    // we don't need to manually load the drmContentData because it was already loaded 
                                          // and it will be associated automatically with our token
                                    var drmTrait:DRMTrait = event.target as DRMTrait;
                                    drmTrait.authenticateWithToken("token");
                               }
                          }
                          
                           
                          

                           

                          A similar workflow can be implemented using traits, but in that case you'll need to take in consideration the following:

                          - traits are transient so they can be added and removed at any time, it is not recommended to keep a reference to a trait

                          - when a DRMTrait is added to an existing media element, is not necessary initialized

                          - you'll also need to listen for DRMEvent.DRM_STATE_CHANGE event on that trait and when the drmState == DRMState.AUTHENTICATING, then it is a good time to authenticateWithToken

                           

                          Hope it helps,

                          Kimi