|
||
This document gives guidance on how the streaming player middleware, for example the DVB-H middleware,n uses Streaming CAF.
For background information on CAF Streaming Agents, see CAF Streaming Agent overview.
To access a particular broadcast, the CAF framework needs to find a CAF Streaming Agent that supports the standard with which the broadcast's data stream is protected, for example IPSec. The CAF Streaming Agent decrypts the short-term key message and this is used to decrypt the data. To do this, the streaming player middleware can initialise a key stream decoder.
Note that the streaming player middleware is implemented as a separate ECOM plug-in.
Please note that this diagram assumes a separation of application and multimedia processes. This separation is optional and may not be present in all cases. Without this separation, the application process would include components displayed in the multimedia process and would need to be trusted and to have DRM capability.
Important disclaimer: The process boundary between the Multimedia process and the CAF streaming agent server process is not enforced by Symbian. This is strongly recommended, since otherwise no DRM trusted path can be established for protected content.
The CKeyStreamDecoder
class provides an interface
for initialising key stream decoders.
Key stream decoders do the following:
Optionally, launch the streaming agent by initialising a keystream
decoder (CKeyStreamDecoder::NewLC()
is the interface for
initialising and returning key stream decoders.)
Provide integration with Session Description Protocol (SDP) by receiving relevant parameters as input.
Query attributes from the server
(CKeyStreamDecoder::GetStringAttributeL()
and
CKeyStreamDecoder::GetAttributeL()
are interfaces for
accessing stream-specific data and can be used to access information on whether
the rights are available to record and who is the broadcaster or content
provider. )
Get an import session handle and start recording, after checking
post-acquisition rights in the Rights Object
(CKeyStreamDecoder::CreateImportSessionLC()
method) (If
the Rights Object does not provide the correct rights for recording, the
request fails.)
The following code segment shows a key stream decoder being initialised and queries attributes from the server. Note that to process a key stream, the key stream decoder needs to remain active.
/* In this code sample, a key stream decoder is created to decode a key stream which
is protected by IPSec. Create a protected stream descriptor for IPSec.
serverAddr => source connection address (content distributor in real case).
This address can be extracted from the SDP (Session Descripton Protocol).
It is assumed that the client has already received this object.
clientAddr => target connection address (device in real case).
For more information about CProtectedStreamDesc, see protectedstreamdesc.h
and ipsecprotectedstreamdesc.cpp.
*/
CProtectedStreamDesc *protectedStreamDesc = CIpSecProtectedStreamDesc::NewLC(serverAddr, clientAddr);
/* The relevant media field for the key stream (CSdpMediaField* keyStreamSDPDesc) is
extracted from the SDP (CSdpDocument* sdpDocument).
......
Now create the key stream decoder by using the protected stream descriptor, the key stream media
field, and the whole SDP object. For more information please look at keystreamdecoder.h and
keystreamdecoder.cpp
*/
CKeyStreamDecoder *keyStreamDecoder = CKeyStreamDecoder::NewLC(protectedStreamDesc, keyStreamSDPDesc,
sdpDocument);
Cleanupstack::PopAndDestroy(protectedStreamDesc);
If the next section of code is reached, the key stream decoder has been initialized correctly, and if the user has rights to view the stream, it will be decrypted. During the initialization of the key stream decoder, the streaming agent which can handle the requested key stream is resolved and launched. If the user had already subscribed to the service (or program) and the RO has not expired yet, the streaming agent loads this key stream and the key stream decoder object is created successfully. After that, the streaming agent performs the new key processing task in the background to get the protected data stream decrypted. The key processing task for IPSec is to decrypt STKM (Short Term Key Message, being received as the key stream) and to extract the corresponding cryptographic context. This object must be kept alive while receiving the key stream and decrypting the protected streamed data. If the user doesn't have the rights to view the stream (e.g. no rights for a specific pay-per-view program), no cryptographic context will be set.
To get any information about the protected stream content, one can query the streaming agent by using the created key stream decoder object. For example, the playability of the protected content can be queried as follows:
TBool playable = EFalse;
keyStreamDecoder->GetAttributeL(ECanPlay, playable);
// All attributes that can be queried from the streaming agent are defined in streamcaftypes.h.
// When the protected key stream receiving has finished or stopped, the key decoder object is destroyed.
Cleanupstack::PopAndDestroy(keyStreamDecoder);
The following code segment shows an example of recording protected streamed content with post-acquisition rights.
// Generate a protected key stream description for IPSec
CProtectedStreamDesc *protectedStreamDesc = CIpSecProtectedStreamDesc::NewLC(serverAddr, clientAddr);
// Create a key stream decoder
CKeyStreamDecoder *keyStreamDecoder = CKeyStreamDecoder::NewLC(protectedStreamDesc, keyStreamSDPDesc,
sdpDocument);
//Check whether the content is recordable
TBool value = EFalse;
keyStreamDecoder->GetAttributeL(ECanExport, value);
if(!value)
{
User::Leave(KErrCANotSupported);
}
/* Get an import handle to record the protected streamed data in 3GPP video format
By using the import handle, the streamed content will be recorded as protected together
with its post-acquisition Rights Object. After importing, the recorded content is reached
according to the restrictions defined in the post-acquisition Rights Object.
*/
CImportFile* import = keyStreamDecoder->CreateImportSessionLC(_L8("video/3gpp"));
TPtr8 decryptedContent;
do
{
// Decrypt the protected streamed content and assign to decryptedContent pointer.
import->WriteData(decryptedContent);
} while (decryptedContent);
// Import has been completed.
TFileName fileName;
TInt err = import->WriteDataComplete();
while (err == KErrCANewFileHandleRequired)
{
err = ProvideNewOutputFileL(*import, fileName);
if(err == KErrNone)
{
err = import->WriteDataComplete();
}
}
User::LeaveIfError(err);
The streaming player middleware must be aware when a stream cannot be
played because of lack of rights. In the regular file DRM standard scenario,
this task is relatively easy, since the CAF agent can check during
instantiation of ContentAccess::CData
that corresponding
rights exist.
In the streaming scenario, this task is more complicated:
Pay-per-view. The user may have bought rights to view a particular programme, but not the rights for the programme that follows it on the same channel. Thus, even if the user had rights when the key stream decoder was instantiated, this may no longer be the case in 1-2 hours, and the same key stream can no longer be decoded.
Subscription expiry. The user may have subscribed to the channel, but while viewing the stream, the subscription expires. Again, the same key stream can no longer be decoded.
These limitations imply that CAF cannot report during instantiation of
key stream decoder whether the stream can actually be decoded. It can only
report that the specific standard is supported, and that there is a key stream
decoder which will attempt to decrypt the key stream. Until the actual key
messages start arriving, the key stream decoder cannot know whether it will be
able to decrypt the short-term keys. If no decrypted information arrives (or,
if for ISMACryp, it cannot be decrypted) the controller needs to poll to verify
this. The multimedia controller must use the
CKeyStreamDecoder::GetAttribute()
method with the
TAttribute
parameter ECanPlay
to do this. This way,
if the decryption process fails, and the multimedia controller does not have
any plaintext data available, it can query the key stream decoder whether it
fails to decrypt short-term keys. If key packets cannot be decrypted, the
decoder should drop them silently, and thus, it cannot push this information to
the multimedia controller.