Sure,
sorry for the delay - I just forgot to post it here.
You have to update the FMX.Media.Mac resp. IOS in the following way:
constructor TMacMedia.Create(const AFileName: string);
var
LURL: NSUrl;
LAbsoluteFileName: string;
LAsset: AVURLAsset;
begin
inherited Create(AFileName);
AVMediaTypeAudio; // Force load the framework
if FileExists(FileName) then
begin
if ExtractFilePath(FileName).IsEmpty then
LAbsoluteFileName := TPath.Combine(TPath.GetHomePath, FileName)
else
LAbsoluteFileName := FileName;
LURL := TNSUrl.Wrap(TNSUrl.OCClass.fileURLWithPath(StrToNSStr(LAbsoluteFileName)));
end
else
LURL := StrToNSUrl(FileName);
if LURL = nil then
raise EFileNotFoundException.Create(SSpecifiedFileNotFound);
FPixelBufferBitmap := TBitmap.Create;
LAsset := TAVURLAsset.Wrap(TAVURLAsset.OCClass.URLAssetWithURL(LURL, nil));
if LAsset.hasProtectedContent then
ContentKeyManager.addContentKeyRecipient(LAsset);
FPlayerItem := TAVPlayerItem.Wrap(TAVPlayerItem.OCClass.playerItemWithAsset(LAsset));
FPlayerItem.retain;
FPlayer := TAVPlayer.Wrap(TAVPlayer.OCClass.playerWithPlayerItem(FPlayerItem));
FPlayer.retain;
FPlayerLayer := TAVPlayerLayer.Wrap(TAVPlayerLayer.OCClass.playerLayerWithPlayer(FPlayer));
FPlayerLayer.retain;
FPlayerLayer.setVideoGravity(CocoaNSStringConst(libAVFoundation, 'AVLayerVideoGravityResizeAspectFill'));
FPlayerLayer.setAutoresizingMask(kCALayerWidthSizable or kCALayerHeightSizable);
FVideoView := TNSView.Create;
FVideoView.retain;
FVideoView.setWantsLayer(True);
FVideoView.layer.addSublayer(FPlayerLayer);
SetupVideoOutput;
end;
The ContentKeyManager needs two callbacks which could look like this:
procedure TfrmMain.DoGetCertificate(Sender: TObject; ACert: TMemoryStream);
var
http: THTTPClient;
begin
http := THTTPClient.create;
try
http.ContentType := 'application/octet-stream';
http.Get(FAIRLPLAY_SERVER_URL, ACert);
finally
http.Free;
end;
end;
procedure TfrmMain.DoRequestContentKey(Sender: TObject;
ARequest, AResponse: TMemoryStream);
var
http: THTTPClient;
begin
http := THTTPClient.create;
try
ARequest.Position := 0;
http.ContentType := 'application/octet-stream';
http.Post(LS_SERVER_URL, ARequest, AResponse);
finally
http.Free;
end;
end;
First Fairplay asks for the certificate and returns a request to the license server which should be send as post command. In return it delivers some binary data which is the key to decode the stream.
I made an "example" screenshot with a test server here. The annoying thing is that DRM content does not allow to play the video in a texture. If you start to use copyPixelBufferForItemTime in order to get the video content audio and video playback stops (without any notification). I was thinking about how to put some alpha blended NSView or UIView on top which contain the buttons and other things. One of my projects involves a media player on Android, iOS and MacOS (using Metal). It heavily uses Metal and OpenGL for the output and the video view is drawn over it (using regular firemonkey controls). Maybe you have an idea?
By default the video is shown on the top right and some ui is drawn above. In fullscreen the video is in the background and the rest of the context is shown in front. You can imagine what happen if DRM is involved. You only see the image, but the ui is hidden.
Christian
UFairplay.pas.zip