diff --git a/Android.mk b/Android.mk index dc6f6293..5053e7d6 100644 --- a/Android.mk +++ b/Android.mk @@ -1,23 +1 @@ -LOCAL_PATH:= $(call my-dir) - -ifeq ($(TARGET_ARCH),arm) - -include $(CLEAR_VARS) -LOCAL_MODULE := libwvm.so -LOCAL_SRC_FILES := $(LOCAL_MODULE) -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_CLASS := SHARED_LIBRARIES -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) -OVERRIDE_BUILT_MODULE_PATH := $(TARGET_OUT_INTERMEDIATE_LIBRARIES) -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_MODULE := libdrmwvmplugin.so -LOCAL_SRC_FILES := $(LOCAL_MODULE) -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_CLASS := SHARED_LIBRARIES -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/drm -OVERRIDE_BUILT_MODULE_PATH := $(TARGET_OUT_INTERMEDIATE_LIBRARIES) -include $(BUILD_PREBUILT) - -endif +include $(call all-subdir-makefiles) diff --git a/debuglibs.sh b/debuglibs.sh new file mode 100755 index 00000000..d048c026 --- /dev/null +++ b/debuglibs.sh @@ -0,0 +1,6 @@ +# Run this script to install the Widevine shared libs (use debug libs) into the symbols path so +# vendor/google/tools/stack can find them. +# +#!/bin/bash +cp /master/vendor/widevine/proprietary/lib/libWVStreamControlAPI.so /master/out/target/product/stingray/symbols/system/lib/libWVStreamControlAPI.so +cp /master/vendor/widevine/proprietary/lib/libwvdrm.so /master/out/target/product/stingray/symbols/system/lib/libwvdrm.so diff --git a/mkall.sh b/mkall.sh new file mode 100644 index 00000000..03bb9fa4 --- /dev/null +++ b/mkall.sh @@ -0,0 +1,14 @@ +#!/bin/sh +cd /master/vendor/widevine +mm . +cd /master/frameworks/base/drm/libdrmframework/plugins/widevine +mm . +cd /master/frameworks/base/drm/libdrmframework/plugins/widevine/test +mm . +cd /master/frameworks/base/media/libwvm +mm . +cd /master/frameworks/base/media/libwvm/test +mm . +cd /master/vendor/widevine +adb sync + diff --git a/proprietary/Android.mk b/proprietary/Android.mk new file mode 100644 index 00000000..5053e7d6 --- /dev/null +++ b/proprietary/Android.mk @@ -0,0 +1 @@ +include $(call all-subdir-makefiles) diff --git a/proprietary/include/AndroidHooks.h b/proprietary/include/AndroidHooks.h new file mode 100644 index 00000000..d775e1e5 --- /dev/null +++ b/proprietary/include/AndroidHooks.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HOOKS_H +#define ANDROID_HOOKS_H + +typedef void (*AndroidEcmCallout)(char* ecm, unsigned long size); + +void AndroidSetEcmCallout(AndroidEcmCallout callout); +void AndroidProcessEcm(char* ecm, unsigned long size); + +typedef int (*AndroidDecryptCallout)(char *in, char *out, int length, char *iv); + +void AndroidSetDecryptCallout(AndroidDecryptCallout callout); +int AndroidDecrypt(char *in, char *out, int length, char *iv); +bool AndroidHaveKey(); + +typedef void (*AndroidLogCallout)(const char *msg); +void AndroidSetLogCallout(AndroidLogCallout callout); +void AndroidLogDebug(const char *msg); + +#endif // ANDROID_HOOKS_H diff --git a/proprietary/include/WVDRMPluginAPI.h b/proprietary/include/WVDRMPluginAPI.h new file mode 100644 index 00000000..74ce0388 --- /dev/null +++ b/proprietary/include/WVDRMPluginAPI.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __WVMDRMPLUGIN_API_H__ +#define __WVMDRMPLUGIN_API_H__ + +#include +#include "WVStreamControlAPI.h" + +class WVDRMPluginAPI { + public: + virtual ~WVDRMPluginAPI() {} + + enum { + RIGHTS_VALID, + RIGHTS_INVALID, + RIGHTS_EXPIRED, + RIGHTS_NOT_ACQUIRED + }; + + enum { + PLAYBACK_START, + PLAYBACK_STOP, + PLAYBACK_PAUSE, + PLAYBACK_INVALID + }; + + static WVDRMPluginAPI *create(); + static void destroy(WVDRMPluginAPI *plugin); + + virtual void OpenSession() = 0; + virtual void CloseSession() = 0; + + virtual bool AcquireDrmInfo(std::string &assetPath, WVCredentials &credentials, + std::string &dsPath, + const std::string &assetIdStr, const std::string &systemIdStr, + const std::string &keyIdStr, + uint32_t *assetId, uint32_t *systemId, uint32_t *keyId) = 0; + virtual bool ProcessDrmInfo(std::string &assetPath) = 0; + virtual int CheckRightsStatus(std::string &path) = 0; + virtual bool GetConstraints(std::string &path, uint32_t *timeSincePlayback, uint32_t *timeRemaining, uint32_t *licenseDuration) = 0; + virtual bool SetPlaybackStatus(int playbackStatus, off64_t position) = 0; + virtual bool RemoveRights(std::string &path) = 0; + virtual bool RemoveAllRights() = 0; + virtual bool Prepare(char *data, int len) = 0; + virtual bool Operate(char *in, char *out, int len, char *iv) = 0; + +protected: + // use create factory method, don't construct directly + WVDRMPluginAPI() {} +}; + +#endif diff --git a/proprietary/include/WVStreamControlAPI.h b/proprietary/include/WVStreamControlAPI.h new file mode 100644 index 00000000..08effa43 --- /dev/null +++ b/proprietary/include/WVStreamControlAPI.h @@ -0,0 +1,1254 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __WV_STREAM_CONTROL_API_H__ +#define __WV_STREAM_CONTROL_API_H__ + +#include +#include + +#if OS_WIN +#ifdef CLIENTAPI_EXPORTS +#define CLIENT_API __declspec(dllexport) +#elif !defined(CLIENT_API_STATIC) +#define CLIENT_API __declspec(dllimport) +#else +#define CLIENT_API +#endif +#else +#define CLIENT_API +#endif + +typedef enum WVLogging { + WV_Logging_HTTP = 1, + WV_Logging_ParseOutput = 2, +} WVLogging; + +typedef enum WVStatus { + WV_Status_OK = 200, + WV_Status_Bad_Request = 400, + WV_Status_Unauthorized = 401, + WV_Status_Not_Found = 404, + WV_Status_Method_Not_Allowed = 405, + WV_Status_Request_Timeout = 408, + WV_Status_Unsupported_Media_Type = 415, + WV_Status_Requested_Range_Not_Satisfiable = 416, + WV_Status_Invalid_Parameter = 451, + WV_Status_Session_Not_Found = 454, + WV_Status_Method_Not_Valid_In_This_State = 455, + WV_Status_Invalid_Range = 457, + WV_Status_Unsupported_Transport = 461, + WV_Status_Destination_Unreachable = 462, + WV_Status_Terminate_Requested = 463, + WV_Status_Internal_Server_Error = 500, + WV_Status_Not_Implemented = 501, + WV_Status_Service_Unavailable = 503, + WV_Status_Service_Response_Error = 504, + WV_Status_Min_TP_Error = 512, // Error codes 512-768 are reserved for + WV_Status_Max_TP_Error = 768, // Third Party apps (Cinema Now) + WV_Status_End_Of_Media = 1000, + WV_Status_Invalid_Data_Format = 1001, + WV_Status_Invalid_Data_Version = 1002, + WV_Status_Parse_Error = 1003, + WV_Status_Tamper_Detected = 1004, + WV_Status_Truncated_Media = 1005, + WV_Status_WVMK_Internal_Error = 1006, + WV_Status_Entitlement_Error = 1007, + WV_Status_Key_Error = 1008, + WV_Status_Value_Out_Of_Range = 1009, + WV_Status_System_Error = 1010, + WV_Status_Invalid_Response = 1011, + WV_Status_Unsupported_Transport_Type = 1012, + WV_Status_FileSystem_Error = 1013, + WV_Status_User_Cancel = 1014, + WV_Status_InvalidState = 1015, + WV_Status_InvalidPiggybackFile = 1016, + WV_Status_Configuration_Error= 1017, + WV_Status_Warning_Download_Stalled = 2000, + WV_Status_Warning_Need_Key = 2001, + WV_Status_Warning_Not_Available = 2002, + WV_Status_Checking_Bandwidth = 2003, + WV_Status_Error_Download_Stalled = 2004, + WV_Status_Error_Need_Key = 2005, + WV_Status_Error_Out_Of_Memory = 2006, + WV_Status_Uninitialized = 2007, + WV_Status_Internal_Error = 2008, + WV_Status_Error_Invalid_Chapter = 2009, + WV_Status_Heartbeat_Configuration_Error = 2010, + WV_Status_Invalid_Keybox = 2011, + WV_Status_Error_NoAdaptiveTracks = 2012 +} WVStatus; + + +typedef enum WVOutputFormat { + WV_OutputFormat_PS = 0, // Generic program stream + WV_OutputFormat_DVD_Video = 1, // DVD-Video program stream + WV_OutputFormat_TS = 2, // Transport Stream + WV_OutputFormat_ES = 3 // Elementary Streams +} WVOutputFormat; + + +// ES selectors for WV_GetEsData +typedef enum WVEsSelector { + WV_EsSelector_Audio = 0, // Audio ES data + WV_EsSelector_Video = 1 // Video ES data +} WVEsSelector; + + +struct WVCredentials { + std::string deviceID; // unique player device ID from CinemaNow + std::string streamID; // unique streamID from CinemaNow + std::string clientIP; // IP address of client + std::string drmServerURL; // URL for DRM server + std::string userData; // Additional optional user data, TBD + std::string portal; // Identifies the operator + std::string storefront; // Identifies store run by operator + std::string drmAckServerURL; // URL for server that receives + // entitlement confirmations + std::string heartbeatURL; // URL to receive client heartbeats + unsigned int heartbeatPeriod;// Duration between consecutive heartbeats in + // seconds. 0 indicates no heatbeats requested + unsigned int cnDeviceType; // device type identifier defined by CinemaNow +}; + +struct WVProxySettings { + bool enable; // If true, proxy use is enable, otherwise disabled + std::string ipAddr; // IP address of proxy server, e.g. "1.2.3.4" or host name + unsigned short ipPort; // IP port number + std::string userId; // User ID if authentication is needed, otherwise "" to disable authentication + std::string password; // Password if userID is not "" +}; + + +class WVSession; + +// +// Callbacks used for RTSP direct function call implementation and/or +// direct function call push data model. +// Also buffer allocation routines for using an external allocator +// +struct WVCallbacks { + void (*pushData)(unsigned short port, void *buffer, size_t length); + void (*response)(WVSession *session, const std::string &response); + void *(*allocBuffer)(size_t); + void (*freeBuffer)(void *); + + // Get unique device ID. Return number of bytes inserted into buffer not to exceed size + int (*getDeviceID)(char *buffer, size_t size); + + int (*getKeyboxPath)(char* path, size_t size); +}; + +// +// METHOD: WV_Initialize +// +// Initialize Widevine stream control API. Must be called before any other +// WV API functions. +// +// Parameters: +// [in] callbacks - Specifies callback functions in client +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// +CLIENT_API WVStatus +WV_Initialize(const WVCallbacks *callbacks); + +// +// METHOD: WV_Terminate +// +// Terminate Widevine stream control API and release all resources. No other +// WV API functions may be called after calling WV_Terminate. +// +// Parameters: +// N/A +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// +CLIENT_API WVStatus +WV_Terminate(); + + +// +// METHOD: WV_SetWarningToErrorMS +// +// Set time to return warnings before returning error +// +// Parameters: +// [in] warningToErrorMS - number of milliseconds after which warning +// returns from WV_GetData turn to errors +// +// Returns: +// N/A +// +CLIENT_API void +WV_SetWarningToErrorMS(long warningToErrorMS); + +// +// METHOD: WV_SetLogging +// +// Set various run time logging and checking options +// +// +// Parameters: +// [in] flags - facilities to enable. See WVLogging for details +// +// +// Returns: +// N/A +// +CLIENT_API void +WV_SetLogging(unsigned long flags); + + +// METHOD: WV_AddMediaFilter +// +// Add filtering options to specify which kind of media formats the device is able to play, +// or should be able to play based on other considerations. This function should +// be called after WV_Initialize, but before WV_Setup. This function may be called multiple +// times to specify multiple filters. +// +// Parameters: +// [in] selector - Specifies the encoding parameter to which the filter applies. The same +// selector may be used in multiple calls to WV_AddMediaFilter, in which case +// media matching any of the filters for that selector will pass. If a particular +// selector is not used in any calls to WV_AddMediaFilter, this is akin to an +// pass for all values for that selector. +// +// [in] operator - Specifies the comparison operator which will be applied to the value for +// the specified selector. +// +// [in] value - Specifies the value for comparsion. +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + +typedef enum WVMediaFilterSelector { + WV_MediaFilterSelector_Null = 0, // NULL selector + WV_MediaFilterSelector_Bandwidth = 1, // Any operator for comparison. Value is bits/sec + WV_MediaFilterSelector_VideoType = 2, // Only Operator_EQ for comparison. Value is WVVideoType + WV_MediaFilterSelector_VideoWidth = 3, // Any operator for comparison. Value is width, in pixels + WV_MediaFilterSelector_VideoHeight = 4, // Any operator for comparison. Value is height, in lines + WV_MediaFilterSelector_VideoAspectRatio = 5, // Any operator for comparison. Value is width/height, adjusted for pixel aspect ratio + WV_MediaFilterSelector_AudioType = 6, // Only Operator_EQ for comparsion. Value is WVAudioType + WV_MediaFilterSelector_AudioChannels = 7, // Any operator for comparison. Value is number of audio channels + WV_MediaFilterSelector_H264Profile = 8, // Any operator for comparison. Value is profile_idc + WV_MediaFilterSelector_H264Level = 9, // Any operator for comparison. Value is level_idc + WV_MediaFilterSelector_AACProfile = 10 // Any operator for comparison. Value is Object Profile ID +} WVMediaFilterSelector; + +typedef enum WVMediaFilterOperator { + WV_MediaFilterOperator_Null = 0, // NULL operator + WV_MediaFilterOperator_LT = 1, // Media value is Less Than specified value + WV_MediaFilterOperator_LE = 2, // Media value is Less than or Equal to specified value + WV_MediaFilterOperator_EQ = 3, // Media value EQuals specified value + WV_MediaFilterOperator_GE = 4, // Media value is Greater than or Equal to specified value + WV_MediaFilterOperator_GT = 5 // Media value is Greater Than specified value +} WVMediaFilterOperator; + +CLIENT_API WVStatus +WV_AddMediaFilter(WVMediaFilterSelector sel, WVMediaFilterOperator op, double value); + + +// METHOD: WV_ResetMediaFilter +// +// Resets media filters set up with WV_AddMediaFilter +// +// Parameters: +// none +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + +CLIENT_API WVStatus +WV_ResetMediaFilter(); + + +// +// METHOD: WV_StartBandwidthCheck +// +// Initiate a bandwidth check on the network connection. This function starts +// a background thread that will perform the bandwidth check and returns +// immediately. The bandwidth measurement is performed by downloading a portion +// of the test file specified by the URL parameter. WV_StartBandwidthCheck may be +// used prior to WV_Setup/WV_Play to determine if the connection has sufficient +// minimum bandwidth for the service. A bandwidth check should be performed +// prior to any WV_Setup requests playback to allow an appropriate initial +// asset bitrate to be selected. It is an error to call WV_StartBandwidthCheck +// while a check is already in progress. If WV_Setup, WV_Play are called before +// the bandwidth check completes, playback will start up at the lowest bitrate +// and there may not be sufficient bandwidth for playback, so it is recommended +// that the bandwidth check is allowed to complete before starting playback. +// WV_Terminate will cancel a bandwidth check that is in progress. +// +// Parameters: +// [in] url - The URL of a test file. The test file should be located on the +// same server/CDN as the actual content to be streamed. +// +// [in] proxy - A structure of proxy settings if a proxy server is to be used +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + +// version without proxy +CLIENT_API WVStatus +WV_StartBandwidthCheck(const std::string &url); + +// version with proxy +CLIENT_API WVStatus +WV_StartBandwidthCheck(const std::string &url, WVProxySettings &proxy); + +// +// METHOD: WV_GetBandwidthCheckStatus +// +// Test the status of a bandwidth check that was initiated by a previous call to +// WV_StartBandwidthCheck. The status value returned from this function will +// indicate one of the following cases: (1) Bandwidth check in progress the +// check has not yet completed, no bandwidth value is returned and the return +// status is WV_Status_Checking_Bandwidth (2) An error occurred during bandwidth +// checking. The return status is the error code representing the error condition +// (3) Bandwidth check complete. In this case, *bandwidth is set to the detected +// connection bandwidth and WV_Status_OK is returned. Once a bandwidth check has +// completed, subsequent calls to WV_GetBandwidthCheckStatus will return the +// previously calculated bandwidth value until a new bandwidth check is initiated +// with WV_StartBandwidthCheck(). +// +CLIENT_API WVStatus +WV_GetBandwidthCheckStatus(unsigned long *bandwidth); + + +// +// METHOD: WV_CheckBandwidth +// +// Perform a bandwidth check on the network connection. The bandwidth measurement +// is performed by downloading a portion of the test file specified by the URL +// parameter. WV_CheckBandwidth may be used prior to WV_Setup/WV_Play to determine +// if the connection has sufficient minimum bandwidth for the service. +// +// Parameters: +// [in] url - The URL of a test file. The test file should be located on the +// same server/CDN as the actual content to be streamed. +// +// [out] bandwidth - The connection bandwidth in bits per second +// +// +// [in] proxy - A structure of proxy settings if a proxy server is to be used +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + +// version without proxy +CLIENT_API WVStatus +WV_CheckBandwidth(const std::string &url, unsigned long *bandwidth); + +//version with proxy +CLIENT_API WVStatus +WV_CheckBandwidth(const std::string &url, unsigned long *bandwidth, const WVProxySettings& proxy); + + +// +// METHOD: WV_Setup +// +// Initiate a session between the Widevine stream control API and a client. +// Allocates resources for a stream. +// +// Parameters: +// [out] session - The supplied pointer to session parameter will be assigned +// a newly constructed session object. The caller needs to +// dispose of this object with WV_Teardown +// +// [in] url - The URL of the media asset to setup +// +// [in] transport - Indicates which transport protocol is to be used and +// configures its parameters such as destination address and destination +// port for a single stream. +// +// [in] credentials - A structure of information that is used to authenticate +// the user's stream request. +// +// The syntax for the transport specifier is +// +// transport/profile/lower-transport. +// +// [in] proxy - A structure of proxy settings if a proxy server is to be used +// +// [in] outputFormat - Indicates the format of the output to be fed into the +// decoder. +// +// Below are the allowed configuration parameters associated with transport: +// +// destination: +// The destination to which a stream will be sent. For the direct +// function call data pull model, use "destination=getdata". +// For the direct function call data push model use +// "destination=callback" +// +// client_port: +// This parameter provides the unicast RTP port on which the client +// has chosen to receive media data. Note that RTCP is not used in this +// localhost implementation, so the client_port takes a single value not +// a range. When using the direct function call data push model, you +// should specify a port value that will be returned with the callback +// data such that the client can associate the data with a specified +// session. +// +// Examples: +// RTP/AVP/UDP;unicast;client_port=3456 +// RAW/RAW/UDP;unicast;client_port=3456 +// RAW/RAW/RAW;destination=callback;client_port=3456 +// RAW/RAW/RAW;destination=getdata +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + +// Setup without a proxy (backward compatible). +//This form is deprecated and may be removed in a future release +CLIENT_API WVStatus +WV_Setup(WVSession *&session, const std::string &url, + const std::string &transport, WVCredentials &credentials, + WVOutputFormat outputFormat = WV_OutputFormat_PS, + unsigned long bufferSize = 10 * 1024 * 1024); + +// Setup using a proxy +CLIENT_API WVStatus +WV_Setup(WVSession *&session, const std::string &url, + const std::string &transport, WVCredentials &credentials, + WVProxySettings &proxy, WVOutputFormat outputFormat = WV_OutputFormat_PS, + unsigned long bufferSize = 10 * 1024 * 1024); + +// +// An alternate form of WV_Setup that receives data from a file source instead of accessing +// directly via a URI. This method of accessing the source data has limitations, it should +// only be used in specific cases where the URI is not available. +// + +class WVFileSource { +public: + virtual unsigned long long GetSize() = 0; + virtual unsigned long long GetOffset() = 0; + + virtual void Seek(unsigned long long offset) = 0; + virtual size_t Read(size_t amount, unsigned char *buffer) = 0; + virtual ~WVFileSource() {} +}; + +CLIENT_API WVStatus +WV_Setup(WVSession *&session, WVFileSource *source, const std::string &transport, + WVCredentials &credentials, WVOutputFormat outputFormat = WV_OutputFormat_PS, + unsigned long bufferSize = 10 * 1024 * 1024); + +// +// METHOD: WV_IsWidevineMedia +// +// Given a buffer of data, determine if the media in the buffer is Widevine +// content (.wvm format) +// +// Parameters: +// [in] buffer - a buffer containing the leading segment of the media +// +// [in] length - the number of bytes in the buffer +// +// Returns: +// true if content is widevine encrypted, false otherwise +// +CLIENT_API bool +WV_IsWidevineMedia(const char *buffer, size_t length); + +// +// METHOD: WV_Teardown +// +// Teardown a session and release all associated resources. The session +// object will be deleted and the pointer set to NULL. +// +// Parameters: +// [in] session - The session to be torn down. The object pointed to +// by session will be deleted. +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// +CLIENT_API WVStatus +WV_Teardown(WVSession *&session); + +// +// METHOD: WV_Play +// +// Initiate playback for a session. +// +// The WV_Play method tells the server to start sending data via the +// mechanism specified in WV_Setup. A client MUST NOT issue a WV_Play +// request until any outstanding WV_Setup requests have been +// acknowledged as successful. +// +// The WV_Play method positions the normal play time to the beginning +// of the range specified and delivers stream data until the end of the +// range is reached. +// +// Parameters: +// [in] session - The session for which to initiate playback +// +// [in] scale_requested - A scale value of 1 indicates normal play or record +// at the normal forward viewing rate. If not 1, the value corresponds +// to the rate with respect to normal viewing rate. For example, a +// ratio of 2 indicates twice the normal viewing rate ("fast forward") +// and a ratio of 0.5 indicates half the normal viewing rate. In other +// words, a ratio of 2 has normal play time increase at twice the +// wallclock rate. For every second of elapsed (wallclock) time, 2 +// seconds of content will be delivered. A negative value indicates +// reverse direction. +// +// [out] scale_used - The server will try to approximate the requested +// scale in scale_requested, but may restrict the range of scale +// values that it supports. On exit, the scale actually used will be +// returned in the variable pointed to by this parameter. +// +// [in] range - The time range that playback is to start/stop. Valid time +// values are according to the RTSP npt-range header, e.g.: +// +// npt-range = ( npt-time "-" [ npt-time ] ) | ( "-" npt-time ) +// npt-time = "now" | npt-sec | npt-hhmmss +// npt-sec = 1*DIGIT [ "." *DIGIT ] +// npt-hhmmss = npt-hh ":" npt-mm ":" npt-ss [ "." *DIGIT ] +// npt-hh = 1*DIGIT ; any positive number +// npt-mm = 1*2DIGIT ; 0-59 +// npt-ss = 1*2DIGIT ; 0-59 +// +// Examples: +// npt=123.45-125 +// npt=12:05:35.3- +// npt=now- +// +// The syntax conforms to ISO 8601. The npt-sec notation is optimized +// for automatic generation, the ntp-hhmmss notation for consumption +// by human readers. The "now" constant allows clients to request to +// receive the live feed rather than the stored or time-delayed +// version. This is needed since neither absolute time nor zero time +// are appropriate for this case. +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// +CLIENT_API WVStatus +WV_Play(WVSession *session, float scale_requested, float *scale_used, const std::string &range); + +// +// METHOD: WV_Pause +// +// The WV_Pause method causes the stream delivery to be interrupted +// (halted) temporarily. Any server resources are kept. +// +// The PAUSE request may contain a time parameter specifying when the +// stream is to be halted. We refer to this point as the "pause point". +// The time must contain exactly one value rather than a time range. The +// normal play time for the stream is set to the pause point. The pause +// request becomes effective the first time the server is encountering +// the time point specified in any of the currently pending PLAY requests. +// If a time outside the currently pending PLAY request is specified, the +// error "457 Invalid Range" is returned. If a media unit (such as an audio +// or video frame) starts presentation at exactly the pause point, it is +// not played. If the time parameter is the empty string "", stream +// delivery is interrupted immediately on receipt of the message and the +// pause point is set to the current normal play time. +// +// A subsequent WV_Play method with "now-" range value resumes from the +// pause point. +// +// Parameters: +// [in] session - The session to pause +// +// [in] time - The pause point, as described above. See WV_Play for a +// description of time formats. +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// +CLIENT_API WVStatus +WV_Pause(WVSession *session, const std::string &time); + +// +// METHOD: WV_Info_GetTime +// +// The WV_Info_GetTime method returns the current play time of the specified +// session. +// +// Parameters: +// [in] session - The session to query +// +// [in] format - "npt" or "smpte". npt is the default. +// +// Returns: +// The current time as a std::string in the requested format +// +// +CLIENT_API std::string +WV_Info_GetTime(WVSession *session, const std::string &format = "npt"); + + +// METHOD: WV_TimestampToMediaTime +// +// This method is used to determine media timestamps (SCR or PTS) from media time, +// automatically compenstaing for trick play. +// +// Parameters: +// [in] session - The session from which data is requested +// +// [in] timestamp - Media timestamp (SCR or PTS). Up to +// 300 seconds (real time) in the past +// +// [in] type - The type of the first paramter (SCR or PTS). +// +// [in] format - "npt" or "smpte". npt is the default. +// +// Returns: +// The media time corresponding to the timestamp if available, or an empty +// string otherwise +// +typedef enum { + SCR = 0, + PTS = 1 +} TimestampType; +CLIENT_API std::string +WV_TimestampToMediaTime(WVSession* session, unsigned long long timestamp, + TimestampType type = PTS, const std::string &format = "npt"); + + +// +// METHOD: WV_GetData +// +// This method is used when the client chooses to receive multiplexed stream data directly via +// function call using a pull data model. In this case, the transport parameter to the +// WV_Setup method should include destination configuration of "destination=getdata" +// +// Parameters: +// [in] session - The session from which data is requested +// +// [in] buffer - A pointer to the memory buffer to receive the data +// +// [in] request_size - Number of bytes requested. It is the caller's responsibility to +// make sure the buffer is large enough to receive this many bytes. +// +// [out] return_size - On return, set to the number of bytes written into the buffer +// +// [in] timeout_sec - Unused, set to 0 +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// +CLIENT_API WVStatus +WV_GetData(WVSession *session, unsigned char *buffer, size_t request_size, + size_t *return_size, unsigned long timeout_sec); + + +// +// METHOD: WV_GetEsData +// +// This method is used when the client chooses to receive elementary stream data directly via +// function call using a pull data model. This method always returns data corresponding to +// at most one single access unit. + +// +// Parameters: +// [in] session - The session from which data is requested +// +// [in] es_selector - Selector specifying which elementary stream data to receive. +// +// [in] buffer - A pointer to the memory buffer to receive the data +// +// [in] request_size - Number of bytes requested. It is the caller's responsibility to +// make sure the buffer is large enough to receive this many bytes. +// +// [out] return_size - On return, set to the number of bytes written into the buffer +// +// [out] au_start - On return, indicates whether the data belongs to the next access unit. +// +// [out] dts - On return, set to MPEG-2 access unit decoding timestamp (DTS) +// +// [out] pts - On return, set to MPEG-2 access unit presentation timestamp (PTS) +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// +CLIENT_API WVStatus +WV_GetEsData(WVSession *session, WVEsSelector es_selector, + unsigned char *buffer, size_t request_size, size_t& return_size, + bool& au_start, unsigned long long& dts, unsigned long long& pts); + + +// +// METHOD: WV_Info_GetDuration +// +// The WV_Info_GetDuration method returns the length of the current media file +// that was set up for the session. The length is returned in either npt or smpte +// time format, as desired. +// +// Parameters: +// [in] session - The session to query +// +// [in] format - "npt" or "smpte". npt is the default. +// +// Returns: +// The media file duration as a std::string in the requested format +// If the duration of the asset is not yet available, the empty string "" is returned. +// +// +CLIENT_API std::string +WV_Info_GetDuration(WVSession *session, const std::string &format = "npt"); + +// +// METHOD: WV_Info_GetSystemType +// +// The WV_Info_GetSystemType method returns the container format type +// for the specified session. +// +// Parameters: +// [in] session - The session to query +// +// Returns: +// The container format of the media stream +// +typedef enum WVSystemType { + WV_System_Unknown = 0x00000000, + WV_System_MPEG1_System = 0x00010000, + WV_System_MPEG2_TS = 0x00020000, + WV_System_MPEG2_PS = 0x00030000, + WV_System_MP4 = 0x00040000, + WV_System_AVI = 0x00050000, + WV_System_GIF = 0x00060000, + WV_System_JPG = 0x00070000, + WV_System_MP3 = 0x00080000, + WV_System_DAT = 0x00090000, + WV_System_SVCD = 0x000a0000, + WV_System_VOB = 0x000b0000, + WV_System_None = 0x00ff0000 +} WVSystemType; + +CLIENT_API WVSystemType +WV_Info_GetSystemType(WVSession *session); + + +// +// METHOD: WV_Info_GetAudioConfiguration +// +// The WV_Info_GetAudioConfiguration method returns information pertinent to the audio stream +// within the current asset. +// +// Parameters: +// [in] session - the session to query +// [out] streamType - The type of audio stream (NULL if not queried) +// [out] streamID - The stream PES stream_id (NULL if not queried) +// [out] profile - The audio encoding profile, if applicable (NULL if not queried) +// [out] numChannels - The audio channel configuration (NULL if not queried) +// [out] sampleFrequency - The audio sampling frequency (NULL if not queried) +// [out] bitRate - The audio bit rate (NULL if not queried) +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values indicating the specific error. +// + +typedef enum WVAudioType { + WV_AudioType_None = 0x00000000, + WV_AudioType_AAC = 0x00000001, + WV_AudioType_EAC3 = 0x00000002, + WV_AudioType_Unknown = 0x000000ff +} WVAudioType; + +CLIENT_API WVStatus +WV_Info_GetAudioConfiguration(WVSession *session, + WVAudioType *streamType, + unsigned short *streamID, + unsigned short *profile, + unsigned short *numChannels, + unsigned long *sampleFrequency, + unsigned long *bitRate); + + +// +// METHOD: WV_Info_GetVideoConfiguration +// +// The WV_Info_GetVideoConfiguration method returns information pertinent +// to the video stream within the current asset. +// +// Parameters: +// [out] streamType - The type of video stream (NULL if not queried) +// [out] streamID - The stream PES stream_id (NULL if not queried) +// [out] profile - The video encoding profile, if applicable (NULL if not queried) +// [out] level - The video encoding profile level, if applicable (NULL if not queried) +// [out] width - The video horizontal resolution (NULL if not queried) +// [out] height - The video vertical resolution (NULL ifnot queried) +// [out] pixelAspectRatio - The Aspect ratio (w/h) for the video samples (NULL if not required) +// May be 0 if not available +// [out] frameRate - The video frame rate (NULL if not queried) +// [out] bitRate - The audio bit rate (NULL if not queried) +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values indicating the specific error. +// + +typedef enum WVVideoType { + WV_VideoType_None = 0x000000000, + WV_VideoType_H264 = 0x000000001, + WV_VideoType_Unknown = 0x0000000ff +} WVVideoType; + +CLIENT_API WVStatus +WV_Info_GetVideoConfiguration(WVSession *session, + WVVideoType *streamType, + unsigned short *streamID, + unsigned short *profile, + unsigned short *level, + unsigned short *width, + unsigned short *height, + float *pixelAspectRatio, + float *frameRate, + unsigned long *bitRate); + + +// +// METHOD: WV_Info_GetCodecConfig +// +// The WV_Info_GetCodecConfig method returns the 'avcC' or 'esds' configuration data. +// +// Parameters: +// [in] configType - Either WV_CodecConfigType_AVCC or WV_CodecConfigType_ESDS +// [out] config - A reference to a pointer that will receive the address of the data +// [out] size - The number of bytes of data in config, or 0 if no data is available +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values indicating the specific error. +// If the requested codec configuration data is not available, WV_Status_Warning_Not_Available +// is returned. +// + +typedef enum WVCodecConfigType { + WV_CodecConfigType_AVCC = 0x00000000, + WV_CodecConfigType_ESDS = 0x00000001 +} WVCodecConfigType; + +CLIENT_API WVStatus +WV_Info_GetCodecConfig(WVSession *session, WVCodecConfigType configType, + unsigned char const *& config, unsigned long &size); + + + +// +// METHOD: WV_Info_GetNumberOfStreams +// +// Note: This method is now obsolete. Please use WV_Info_GetAudioConfiguration and +// WV_Info_GetVideoConfiguration instead. +// +// The WV_Info_GetNumberOfStreams method returns the number of streams +// (audio or video) in the multiplex that was set up for the specified +// session. +// +// Parameters: +// [in] session - The session to query +// +// Returns: +// The number of streams +// +CLIENT_API unsigned short +WV_Info_GetNumberOfStreams(WVSession *session); + +// +// METHOD: WV_Info_GetStreamInfo +// +// Note: This method is now obsolete. Please use WV_Info_GetAudioConfiguration and +// WV_Info_GetVideoConfiguration instead. +// +// The WV_Info_GetStreamInfo method retrieves the type and stream ID of +// a selected stream in the multiplex that was set up for the specified +// session. +// +// Parameters: +// [in] session - The session to query +// +// [in] streamNumber - The number of the stream. Valid stream numbers +// range from 0..WV_Info_GetNumberOfStreams() - 1 +// +// [out] streamType - A pointer to a variable that will be set to the +// type of the stream selected by streamNumber +// +// [out] streamID - A pointer to a variable that will be set to the +// stream ID selected by streamNumber +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + +// +// Note: WVStreamType is now obsolete. Please use WVAudioType and WVVideoType instead. +// +typedef enum WVStreamType { + WV_StreamType_Unknown = 0x00000000, + WV_StreamType_Audio_MPEG1 = 0x00000001, + WV_StreamType_Audio_MPEG2 = 0x00000002, + WV_StreamType_Audio_AAC = 0x00000003, + WV_StreamType_Audio_AC3 = 0x00000004, + WV_StreamType_Audio_ADS = 0x00000005, + WV_StreamType_Audio_MPEG2_AAC = 0x00000006, + WV_StreamType_Audio_MPEG4_AAC = 0x00000007, + WV_StreamType_Audio_DTS = 0x00000008, + WV_StreamType_Audio_EAC3 = 0x00000009, + WV_StreamType_Audio_None = 0x000000ff, + + WV_StreamType_Video_Unknown = 0x00000000, + WV_StreamType_Video_MPEG1 = 0x00000100, + WV_StreamType_Video_MPEG2 = 0x00000200, + WV_StreamType_Video_MPEG4 = 0x00000300, + WV_StreamType_Video_H264 = 0x00000400, + WV_StreamType_Video_VC1 = 0x00000500, + WV_StreamType_Video_None = 0x0000ff00 +} WVStreamType; + +CLIENT_API WVStatus +WV_Info_GetStreamInfo(WVSession *session, unsigned short streamNumber, + WVStreamType *streamType, unsigned short *streamID); + +// +// METHOD: WV_Info_GetAudioSampleRate +// +// Note: This method is now obsolete. Please use WV_Info_GetAudioConfiguration instead. +// +// The WV_Info_GetAudioSampleRate method retrieves the audio sample rate +// of the current stream in the multiplex that was set up for the specified +// session. +// +// Parameters: +// [in] session - The session to query +// +// [out] sampleRate The audio sample rate for the specified stream, in Hz +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + +CLIENT_API WVStatus +WV_Info_GetAudioSampleRate(WVSession *session, unsigned long *sampleRate); + + +// +// METHOD: WV_Info_GetAudioBitrate +// +// Note: This method is now obsolete. Please use WV_Info_GetAudioConfiguration instead. +// +// The WV_Info_GetAudioBitRate method retrieves the average audio bit rate +// of the current stream in the multiplex that was set up for the specified +// session. +// +// Parameters: +// [in] session - The session to query +// +// [out] bitRate - The average encoded audio bit rate for the specified +// stream, in bits per second +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + +CLIENT_API WVStatus +WV_Info_GetAudioBitrate(WVSession *session, unsigned long *bitRate); + + +// +// METHOD: WV_Info_GetCurrentBandwidth +// +// This method retrieves information about the adaptive streaming bandwidth. +// for the media stream that was setup on the specified session. +// +// Parameters: +// [in] session - The session to query +// +// [out] bandwidth - The currently observered average network throughput +// in bits per second +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + +CLIENT_API WVStatus +WV_Info_CurrentBandwidth(WVSession *session, unsigned long *bandwidth); + +// +// METHOD: WV_Info_GetAdaptiveBitrates +// +// This method provides adaptive streaming metrics for the media stream +// that was set up on the specified session. This information may be used, for +// example, to display bit rate metering information on the UI to indicate +// quality of service. +// +// Example: if the multi-rate file contains low, mid and high rate encoded +// streams at 700kb, 1.5Mb and 2.5Mb respectively and the lowest bit rate file +// is currently being streamed, then on return, encodedRates[] = {700000, +// 1500000, 2500000}, ratesReturned = 3 and currentIndex = 0. +// +// Parameters: +// [in] session - The session to query +// +// [out] encodedRates - The bit rate of each separate encoding of the asset +// in the multi-rate encoded file, in bits per second. +// +// [in] ratesRequested - The maximum number of encoded rates that may be +// returned in encodedRates, as determined by the number of elements +// allocated in the array. +// +// [out] ratesReturned The number of encoded rates written to the encodedRates +// array. +// +// [out] currentIndex The index of the rate in encodedRates that is currently +// streaming. If none, currentIndex == ratesReturned +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// +CLIENT_API WVStatus +WV_Info_GetAdaptiveBitrates(WVSession *session, + unsigned long *encodedRates, + size_t ratesRequested, + size_t *ratesReturned, + size_t *currentIndex); + +// +// METHOD: WV_Info_GetCopyProtection +// +// This method retrieves information about the current copy protection settings +// as determined from the DRM license for the content. The copy protection +// in the decoder (APS/Macrovision and/or HDCP) MUST be configured based on the +// information returned from this function. +// +// Parameters: +// [in] session - The session to query +// +// [out] macrovisionLevel - The requested macrovision settings +// +// [out] enableHDCP - If true, HDCP should be enabled on the HDMI output +// +// [out] CIT : If true, Image Constraint is required. +// +// GetCopyProtection without CGMS-A (backward compatible). This form is +// deprecated and may be removed in a future release +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + +typedef enum WVMacrovision { + WV_MacroVision_Type_None = 0, + WV_MacroVision_Type_AGC_Only = 1, + WV_MacroVision_Type_AGC_2Lines = 2, + WV_MacroVision_Type_AGC_4Lines = 3 +} WVMacrovision; + +CLIENT_API WVStatus +WV_Info_GetCopyProtection(WVSession *session, WVMacrovision *macrovision, bool *enableHDCP, bool *CIT); + +// +// METHOD: WV_Info_GetCopyProtection +// +// This method retrieves information about the current copy protection settings +// as determined from the DRM license for the content. The copy protection +// in the decoder (APS/Macrovision and/or HDCP) MUST be configured based on the +// information returned from this function. +// +// Parameters: +// [in] session - The session to query +// +// [out] macrovisionLevel - The requested macrovision settings +// +// [out] emi - The requested EMI settings (use for digital or +// analog copy generation control, e.g. CGMS-A, CGMS-D, etc.) +// +// [out] enableHDCP - If true, HDCP should be enabled on the HDMI output +// +// [out] CIT : If true, Image Constraint is required. +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// +typedef enum WVEMI { + WV_EMI_Copy_Freely = 0, + WV_EMI_Copy_No_More = 1, + WV_EMI_Copy_Once = 2, + WV_EMI_Copy_Prohibited = 3 +} WVEMI; + +CLIENT_API WVStatus +WV_Info_GetCopyProtection(WVSession *session, WVMacrovision *macrovision, + WVEMI *emi, bool *enableHDCP, bool *CIT); + + +// +// METHOD: WV_Info_GetNumChapters +// +// This method retrieves the number of chapters encoded into the media. +// +// Parameters: +// [in] session - The session to query +// +// [out] numChapters - The number of chapters encoded in the media +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + +CLIENT_API WVStatus +WV_Info_GetNumChapters(WVSession *session, unsigned long& numChapters); + + + +// +// METHOD: WV_Info_GetChapterData +// +// This method retrieves information about chapters encoded in the media. +// +// Parameters: +// [in] session - The session to query +// +// [in] startSeqNum - The sequence number of the first chapter to query (0 start) +// +// [in] endSeqNum - The sequence number of the last chapter to query (0 start) +// +// [out] chapterData - An STL vector containing information about each chapter +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + +struct WVChapterData { + unsigned long seqNum; // Sequence number for this chapter + std::string timeIndex; // The time index for the chapter in npt format + std::string title; // The title for the chapter, if any + std::vector thumbnail; // The JPEG thumnail data for the chapter +}; + +CLIENT_API WVStatus +WV_Info_GetChapterData(WVSession *session, unsigned long startSeqNum, + unsigned long endSeqNum, std::vector& chapterData); + + +// +// METHOD: WV_Info_GetChapterSeqNum +// +// This method retrieves the sequence number of the chapter containing a specified +// time index. +// +// Parameters: +// [in] session - The session to query +// +// [in] timeIndex - The time index for the query, in npt format +// +// [out] chapterSeqNum - The sequence number (0 start) of the chapter +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + + +CLIENT_API WVStatus +WV_Info_GetChapterSeqNum(WVSession *session, std::string currentTime, + unsigned long& chapterSeqNum); + + +// +// METHOD: WV_Info_Unique_ID +// +// This method retrieves the device's persistent unique identifier. +// For CE devices, this will be from the Widevine Keybox. +// For Desktop platforms, it will be a persistent GUID generated by Widevine. +// For iPhone, it will be the unit's serial number. +// +// Parameters: +// [in] buffer - empty string buffer to hold the unique ID string. +// buffer must be caller-allocated, 64 bytes. +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + + +CLIENT_API WVStatus +WV_Info_Unique_ID(char* buffer); + +// +// METHOD: WV_SkipChapters +// +// This method causes the stream to skip a number of chapters in any direction +// +// Parameters: +// [in] session - The session to control +// +// [in] timeIndex - The current playback time, in npt format +// +// [in] chapters - The number of chapters to skip. Negative to skip to previous chapters +// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + + +CLIENT_API WVStatus +WV_SkipChapters(WVSession *session, std::string currentTime, long chapters); + + +// +// METHOD: WV_SkipToChapter +// +// This method causes the stream to skip to a specified chapter. +// +// Parameters: +// [in] session - The session to control +// +// [in] chapterSeqNum - The sequence number (0 based) of the target to skip to +//// +// Returns: +// WV_Status_OK on success, otherwise one of the WVStatus values +// indicating the specific error. +// + + +CLIENT_API WVStatus +WV_GoToChapter(WVSession *session, unsigned long chapterSeqNum); + +#endif // __WV_STREAM_CONTROL_API_H__ diff --git a/proprietary/lib/Android.mk b/proprietary/lib/Android.mk new file mode 100644 index 00000000..bf1f1028 --- /dev/null +++ b/proprietary/lib/Android.mk @@ -0,0 +1,34 @@ +LOCAL_PATH := $(call my-dir) + +define _add-wv-shared-lib +include $$(CLEAR_VARS) +$(if $(word 2,$1),$(error Invalid WV module name $1)) +LOCAL_MODULE := $(basename $(notdir $1)) +LOCAL_SRC_FILES := $1 +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := $(suffix $1) +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_MODULE_PATH := $$(TARGET_OUT)$(abspath /lib/$(dir $1)) +OVERRIDE_BUILT_MODULE_PATH := $$(TARGET_OUT_INTERMEDIATE_LIBRARIES) +include $$(BUILD_PREBUILT) +endef + +include $(CLEAR_VARS) + +prebuilt_wv_shared_libs := \ + libwvdrm.so \ + libWVStreamControlAPI.so + +prebuilt_wv_modules := \ + $(foreach _file,$(prebuilt_wv_shared_libs),\ + $(notdir $(basename $(_file)))) + +LOCAL_MODULE := widevine_proprietary_libs +LOCAL_MODULE_TAGS := optional +LOCAL_REQUIRED_MODULES := $(prebuilt_wv_modules) +include $(BUILD_PHONY_PACKAGE) + +$(foreach _file,$(prebuilt_wv_shared_libs),\ + $(eval $(call _add-wv-shared-lib,$(_file)))) + + diff --git a/proprietary/lib/libWVStreamControlAPI.so b/proprietary/lib/libWVStreamControlAPI.so new file mode 100644 index 00000000..78cae747 Binary files /dev/null and b/proprietary/lib/libWVStreamControlAPI.so differ diff --git a/proprietary/lib/libwvdrm.so b/proprietary/lib/libwvdrm.so new file mode 100644 index 00000000..13818f13 Binary files /dev/null and b/proprietary/lib/libwvdrm.so differ diff --git a/proprietary/test/Android.mk b/proprietary/test/Android.mk new file mode 100644 index 00000000..5dd11b29 --- /dev/null +++ b/proprietary/test/Android.mk @@ -0,0 +1,27 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + TestPlayer.cpp + +LOCAL_C_INCLUDES+= \ + bionic \ + vendor/widevine/proprietary/include \ + external/stlport/stlport \ + frameworks/base/media/libwvm/include + +LOCAL_SHARED_LIBRARIES := \ + libstlport \ + libWVStreamControlAPI \ + libdrmframework \ + libwvdrm \ + liblog \ + libutils \ + libz + +LOCAL_MODULE:=test-wvplayer + +LOCAL_MODULE_TAGS := tests + +include $(BUILD_EXECUTABLE) + diff --git a/proprietary/test/TestPlayer.cpp b/proprietary/test/TestPlayer.cpp new file mode 100644 index 00000000..69083a60 --- /dev/null +++ b/proprietary/test/TestPlayer.cpp @@ -0,0 +1,590 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "WVDRMPluginAPI.h" +#include "WVStreamControlAPI.h" +#include "AndroidHooks.h" + +#define AES_BLOCK_SIZE 16 + +using namespace std; + +#define DEFAULT_BLOCK_SIZE 16*1024 +#define DEFAULT_PLAYBACK_BUFFER_SIZE 0*1024*1024 +#define DEFAULT_START_TIME "now" +#define DEFAULT_DRM_URL "http://wstfcps005.shibboleth.tv/widevine/cypherpc/cgi-bin/GetEMMs.cgi" +#define DEFAULT_DRM_ACK_URL "http://wstfcps005.shibboleth.tv/widevine/cypherpc/cgi-bin/Ack.cgi" + +#define SHOW_BITRATE 1 + +/** + * Print command line options + */ +void PrintUsage(char *prog) +{ + printf("Usage: %s url\n", prog); + printf(" -o output_file\n"); + printf(" -b block_size (default: %d)\n", DEFAULT_BLOCK_SIZE); + printf(" -p playback_buffer_size (default: %d)\n", (int)DEFAULT_PLAYBACK_BUFFER_SIZE); + printf(" -m print PTS -> media time\n"); + printf(" -s start_time (default: %s)\n", DEFAULT_START_TIME); + printf(" -d drm_url\n"); + exit(-1); +} + +static WVDRMPluginAPI *sDrmPlugin = NULL; + +static struct termios termattr, save_termattr; +static int ttysavefd = -1; +static enum +{ + RESET, RAW, CBREAK +} ttystate = RESET; + + +/** + *************************************************************************** + * + * set_tty_raw(), put the user's TTY in one-character-at-a-time mode. + * + * @returns 0 on success, -1 on failure. + * + *************************************************************************** */ +int set_tty_raw(void) +{ + int i; + + i = tcgetattr(STDIN_FILENO, &termattr); + if (i < 0) + { + printf("tcgetattr() returned %d for fildes=%d\n",i,STDIN_FILENO); + perror(""); + return -1; + } + save_termattr = termattr; + + termattr.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + termattr.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON); /* | BRKINT */ + termattr.c_cflag &= ~(CSIZE | PARENB); + termattr.c_cflag |= CS8; + /* termattr.c_oflag &= ~(OPOST); */ + + termattr.c_cc[VMIN] = 0; /* or 0 for some Unices; see note 1 */ + termattr.c_cc[VTIME] = 0; + + i = tcsetattr(STDIN_FILENO, TCSANOW, &termattr); + if (i < 0) + { + printf("tcsetattr() returned %d for fildes=%d\n",i,STDIN_FILENO); + perror(""); + return -1; + } + + ttystate = RAW; + ttysavefd = STDIN_FILENO; + + return 0; +} + +/** + * @return time of day in milliseconds + */ +static uint64_t get_time_in_ms() +{ + uint64_t ms; + timeval t; + gettimeofday(&t, NULL); + ms = (uint64_t)(t.tv_sec) * 1000; + ms +=(uint64_t)(t.tv_usec) / 1000; + return ms; +} + +/** + *************************************************************************** + * + * set_tty_cooked(), restore normal TTY mode. Very important to call + * the function before exiting else the TTY won't be too usable. + * + * @returns 0 on success, -1 on failure. + * + *************************************************************************** */ +int set_tty_cooked(void) +{ + int i; + + if (ttystate != CBREAK && ttystate != RAW) + { + return 0; + } + i = tcsetattr(STDIN_FILENO, TCSAFLUSH, &save_termattr); + if (i < 0) + { + return -1; + } + ttystate = RESET; + return 0; +} + +/** + *************************************************************************** + * + * kb_getc(), if there's a typed character waiting to be read, + * + * @return character; else return 0. + * + *************************************************************************** */ +unsigned char kb_getc(void) +{ + unsigned char ch; + ssize_t size; + + size = read(STDIN_FILENO, &ch, 1); + if (size == 0) + { + return 0; + } + else + { + return ch; + } +} + +static void Terminate() +{ + WV_Terminate(); + exit(-1); +} + + +static void PrintMessage(const char *msg) +{ + printf("%s", msg); +} + + +/** + * Program entry pointer + * + * @return 0 for success, -1 for error + */ +int main( int argc, char *argv[] ) +{ + int option; + + string url, outputFile, startTime = DEFAULT_START_TIME; + unsigned long blockSize = DEFAULT_BLOCK_SIZE; + unsigned long playbackBufferSize = DEFAULT_PLAYBACK_BUFFER_SIZE; + bool ptsToMediaTime = false; + string drmUrl = DEFAULT_DRM_URL; + + // Set up callouts + AndroidSetLogCallout(PrintMessage); + + // Create DRM plugin object + sDrmPlugin = WVDRMPluginAPI::create(); + if (sDrmPlugin == NULL) { + fprintf(stderr, "FATAL: failed to construct WVMDRMPluginAPI instance\n"); + exit(-1); + } + + while ((option = getopt(argc, argv, "o:b:p:s:mD:d:")) != -1) { + switch (option) { + case 'o': + outputFile = optarg; + break; + + case 'b': + if (sscanf(optarg, "%lu", &blockSize) != 1) + PrintUsage(argv[0]); + break; + + case 'p': + if (sscanf(optarg, "%lu", &playbackBufferSize) != 1) + PrintUsage(argv[0]); + break; + + case 's': + startTime = optarg; + break; + + case 'm': + ptsToMediaTime = true; + break; + + case 'd': + drmUrl = optarg; + break; + + default: + printf("unknown option: '%c'\n", option); + PrintUsage(argv[0]); + } + } + + if ((argc - optind) != 1) + PrintUsage(argv[0]); + + url = argv[optind]; + + FILE *output = NULL; + if (outputFile.size()) { + output = fopen(outputFile.c_str(), "wb"); + if (!output) { + fprintf(stderr, "unable to open output file %s for writing\n", argv[2]); + exit(-1); + } + } + + // This turns off some verbose printing + setenv("WV_SILENT", "true", 1); + + WVStatus status = WV_Initialize( NULL ); + + if (status != WV_Status_OK) { + fprintf(stderr, "ERROR: WV_Initialize returned status %d\n", (int)status); + Terminate(); + } + + // enable HTTP logging if you want to debug + //WV_SetLogging(WV_Logging_HTTP); + + /* + status = WV_StartBandwidthCheck( url.c_str() ); + if (status != WV_Status_OK) { + fprintf(stderr, "ERROR: WV_CheckBandwidth returned status %d\n", (int)status); + Terminate(); + } + + unsigned long bandwidth; + do { + usleep(100000); + + // The idea here is the bandwidth check is done in the background while the GUI/OSD is + // doing other things. In this example, we just wait for the result. + + status = WV_GetBandwidthCheckStatus(&bandwidth); + } while (status == WV_Status_Checking_Bandwidth); + + if (status == WV_Status_OK) + cout << "Bandwidth check " << bandwidth << endl; + else + cout << "Bandwidth check failed: " << status << endl; +*/ + WVSession *session = 0; + WVCredentials credentials; + credentials.deviceID="SN12345ABC"; + credentials.streamID="0123456789"; + credentials.portal = "YouTube"; + credentials.clientIP="1.1.1.1"; + credentials.drmServerURL= drmUrl; + credentials.userData=""; + credentials.drmAckServerURL=DEFAULT_DRM_ACK_URL; + + string dsPath = ""; + string assetIdStr = ""; + string systemIdStr = ""; + string keyIdStr = ""; + uint_t assetId, systemId, keyId; + + if (!sDrmPlugin->AcquireDrmInfo(url, credentials, dsPath, + assetIdStr, systemIdStr, keyIdStr, + &assetId, &systemId, &keyId)) { + fprintf(stderr, "ERROR: AcquireDrmInfo failed\n"); + Terminate(); + } + + if (!sDrmPlugin->ProcessDrmInfo(url)) { + fprintf(stderr, "ERROR: ProcessDrmInfo failed\n"); + Terminate(); + } + + status = WV_Setup( session, url.c_str(), "RAW/RAW/RAW;destination=getdata", credentials); + if (status != WV_Status_OK) { + fprintf(stderr, "ERROR: WV_Setup returned status %d\n", (int)status); + if (status == 408) + fprintf(stderr, "TIMEOUT: Make sure your device is powered on and has a network connection\n"); + else if (status == 404) + fprintf(stderr, "ASSET NOT FOUND: Make sure the URL you provided is correct\n"); + + Terminate(); + } + + WVMacrovision macrovision; + bool hdcp, cit; + status = WV_Info_GetCopyProtection(session, ¯ovision, &hdcp, &cit); + switch (status) { + case WV_Status_OK: + printf("Copy protection: macrovison = %d, hdcp = %d, cit = %d\n", (int)macrovision, (int)hdcp, (int)cit); + break; + case WV_Status_Warning_Not_Available: + printf("Warning: Copy protection info not yet available\n"); + status = WV_Status_OK; + break; + default: + fprintf(stderr, "ERROR: WV_Info_GetCopyProtection returned status %d\n", (int)status); + Terminate(); + } + + // Get audio and video config options + WVAudioType audioType; + unsigned short streamId; + unsigned short profile; + unsigned short numChannels; + unsigned long sampleFrequency; + unsigned long bitRate; + WVVideoType videoType; + unsigned short level; + unsigned short width; + unsigned short height; + float pixelAspectRatio; + float frameRate; + + WV_Info_GetAudioConfiguration(session, &audioType, &streamId, &profile, &numChannels, &sampleFrequency, &bitRate); + printf("Audio type: %hu\n", audioType); + printf("Audio stream ID: %hu\n", streamId); + printf("Audio profile: %hu\n", profile); + printf("Audio channels: %hu\n", numChannels); + printf("Audio sampling freq: %lu\n", sampleFrequency); + printf("Audio bit rate: %lu\n", bitRate); + + WV_Info_GetVideoConfiguration(session, &videoType, &streamId, &profile, &level, &width, &height, & pixelAspectRatio, &frameRate, &bitRate); + printf("Video type: %hu\n", videoType); + printf("Video stream ID: %hu\n", streamId); + printf("Video profile: %hu\n", profile); + printf("Video profile level: %hu\n", level); + printf("Video width: %hu\n", width); + printf("Video height: %hu\n", height); + printf("Video pixel aspect ratio: %f\n", pixelAspectRatio); + printf("Video frame rate: %f\n", frameRate); + printf("Video bit rate: %lu\n", bitRate); + + float scale_used; + startTime += "-"; + status = WV_Play( session, 1.0, &scale_used, startTime.c_str() ); + if (status != WV_Status_OK) { + fprintf(stderr, "ERROR: WV_Play returned status %d\n", (int)status); + Terminate(); + } + + auto_ptr buffer(new uint8_t[blockSize]); + size_t numBytes; + + // fill playback buffer as quickly as possible + uint64_t bytesRead = 0; + while (bytesRead < playbackBufferSize) { + status = WV_GetData( session, buffer.get(), blockSize, &numBytes, 0 ); + switch (status) { + case WV_Status_OK: + break; + case WV_Status_Warning_Download_Stalled: + case WV_Status_Warning_Need_Key: + fprintf(stderr, "WARNING: WV_GetData returned status %d\n", (int)status); + usleep(100000); + break; + default: + fprintf(stderr, "ERROR: WV_GetData returned status %d\n", (int)status); + Terminate(); + break; + } + if (numBytes > 0) { + if (output) + fwrite(buffer.get(), numBytes, 1, output); + bytesRead += numBytes; + cout << "Read " << numBytes << "/" << bytesRead << " out of " << playbackBufferSize << endl; + } + } + + set_tty_raw(); + +#if SHOW_BITRATE + unsigned long bitRates[32]; + size_t numBitRates; + size_t curBitRate; + if (WV_Info_GetAdaptiveBitrates(session, bitRates, sizeof(bitRates)/sizeof(uint32_t), + &numBitRates, &curBitRate) == WV_Status_OK) { + printf("Bit Rates: "); + for (uint32_t idx = 0; idx < numBitRates; ++idx) { + if (idx == curBitRate) + printf("*%lu* ", bitRates[idx]); + else + printf("%lu ", bitRates[idx]); + } + printf("\n"); + } +#endif + + string nptTime = WV_Info_GetTime(session); + int hh, mm; + float ss; + sscanf(nptTime.c_str(), "%d:%d:%f", &hh, &mm, &ss); + uint64_t startMs = (uint64_t)((hh * 3600000) + (mm * 60000) + (ss * 1000)); + uint64_t curMs = startMs; + uint64_t lastMs = curMs; + uint64_t baseTime = get_time_in_ms(); + int trickPlayRate = 1; + + bool quit = false; + while (!quit) { + uint64_t curTime = get_time_in_ms(); + uint64_t streamTimeRef = (trickPlayRate >= 0) ? (curMs - startMs) : (startMs - curMs); + uint64_t clockRef = get_time_in_ms() - baseTime; + if (trickPlayRate) + clockRef *= trickPlayRate > 0 ? trickPlayRate : -trickPlayRate; + if (clockRef > streamTimeRef) { + // time for another pull + status = WV_GetData( session, buffer.get(), blockSize, &numBytes, 0 ); + switch (status) { + case WV_Status_OK: + break; + case WV_Status_End_Of_Media: + printf("END OF MEDIA %d\n", trickPlayRate); + break; + if (trickPlayRate < 0) { + WV_Play( session, 1.0, &scale_used, "00:00:00-" ); + trickPlayRate = 1; + startMs = curMs; + baseTime = curTime; + } else + quit = true; + break; + case 1001: + fprintf(stderr, "ERROR: WV_GetData returned status %d\n", (int)status); + break; + case WV_Status_Warning_Download_Stalled: + case WV_Status_Warning_Need_Key: + fprintf(stderr, "WARNING: WV_GetData returned status %d\n", (int)status); + usleep(100000); + break; + default: + fprintf(stderr, "ERROR: WV_GetData returned status %d\n", (int)status); + Terminate(); + break; + } + if (numBytes > 0) { + if (output) + fwrite(buffer.get(), numBytes, 1, output); + bytesRead += numBytes; + nptTime = WV_Info_GetTime(session); + sscanf(nptTime.c_str(), "%d:%d:%f", &hh, &mm, &ss); + curMs = (uint64_t)((hh * 3600000) + (mm * 60000) + (ss * 1000)); + if (curMs != lastMs) { + int64_t msDif = (trickPlayRate >= 0) ? (curMs - lastMs) : (lastMs - curMs); + if ((msDif < 0) || (msDif > 60000)) { + // discontinuity + startMs = curMs; + baseTime = curTime; + printf("Current time (skip): %s\n", nptTime.c_str()); + } else if ((curMs / 1000) != (lastMs / 1000)) { + printf("Current time: %s\n", nptTime.c_str()); +#if SHOW_BITRATE + if (WV_Info_GetAdaptiveBitrates(session, bitRates, sizeof(bitRates)/sizeof(uint32_t), + &numBitRates, &curBitRate) == WV_Status_OK) { + printf("Bit Rates: "); + for (uint32_t idx = 0; idx < numBitRates; ++idx) { + if (idx == curBitRate) + printf("*%lu* ", bitRates[idx]); + else + printf("%lu ", bitRates[idx]); + } + printf("\n"); + } +#endif + } + lastMs = curMs; + } + } + } + + unsigned char kbhit = kb_getc(); + switch (kbhit) { + case 'g': + char seekTime[256]; + set_tty_cooked(); + printf("Go to time: "); + if ((scanf("%s", seekTime) == 1) && (sscanf(seekTime, "%d:%d:%f", &hh, &mm, &ss) == 3)) { + status = WV_Play(session, 1, &scale_used, string(seekTime) + "-"); + if (status != WV_Status_OK) { + fprintf(stderr, "ERROR: WV_Play returned status %d\n", (int)status); + Terminate(); + } + startMs = curMs; + baseTime = curTime; + } + set_tty_raw(); + break; + + case 't': + set_tty_cooked(); + printf("Trick-play rate (now): "); + if (scanf("%d", &trickPlayRate) == 1) { + printf( "Got a trick play value of %d\n", trickPlayRate ); + if (trickPlayRate == 0) + trickPlayRate = 1; + status = WV_Play(session, trickPlayRate, &scale_used, "now-"); + if (status != WV_Status_OK) { + fprintf(stderr, "ERROR: WV_Play returned status %d\n", (int)status); + Terminate(); + } + startMs = curMs; + baseTime = curTime; + } else { + printf( "did not get a rate\n" ); + } + set_tty_raw(); + break; + + case 'p': + set_tty_cooked(); + printf("PTS: "); + uint64_t pts; + if (scanf("%llu", (long long unsigned int*)& pts) == 1) { + string mediaTime = WV_TimestampToMediaTime(session, pts, PTS); + printf("Media Time: \"%s\"\n", mediaTime.c_str()); + } + set_tty_raw(); + break; + + case 'x': + quit = true; + break; + + default: + break; + } + + usleep(1000); + }; + + WV_Teardown( session ); + WV_Terminate(); + + if (output) + fclose(output); + + set_tty_cooked(); + + return(0); +} diff --git a/proprietary/test/kill.sh b/proprietary/test/kill.sh new file mode 100755 index 00000000..7734c3bf --- /dev/null +++ b/proprietary/test/kill.sh @@ -0,0 +1,3 @@ +#!/bin/sh +PID=`adb shell ps | grep test-wvplayer | awk '{print $2}'` +adb shell kill -9 $PID diff --git a/putlibs.sh b/putlibs.sh new file mode 100755 index 00000000..e6d2e7ed --- /dev/null +++ b/putlibs.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# This is a script to install the original DRM plugins (first working stingray libs) +# on the device. You shouldn't need to use it except for troubleshooting/debugging. + +adb root +sleep 2 +adb remount +sleep 2 +adb push libwvm.so /system/lib +adb shell mkdir -p /system/lib/drm/plugins/native +adb push libdrmwvmplugin.so /system/lib/drm/plugins/native +adb reboot diff --git a/test/WidevineDemo DRM framework.apk b/test/WidevineDemo DRM framework.apk index 84971383..0af066eb 100644 Binary files a/test/WidevineDemo DRM framework.apk and b/test/WidevineDemo DRM framework.apk differ