TvInputService Implementation : Displaying Video from Connected HDMI Device
As we know Android Tv Input Framework, a data source or Tv Input like IP-TV, Tuner, HDMI etc. is nothing else but the implementation of TvInputService. So if any of these datasource/device need KeyEvents, that should be implemented in TvInputService.As in the post we implemented a TvInputService for HDMI input source. In order to get the video from device connected to HDMI input, we need to override following method from TvInputService correctly.
public boolean onSetSurface(Surface surface) { }
Let's see the call flow from application and implement this method.
An application uses TvView and calls it's setSurface() method to show content from selected TvInput source.
TvView.java
surfaceCreated(SurfaceHolder holder) {
mSurface = holder.getSurface();
setSessionSurface(mSurface);
}
private void setSessionSurface(Surface surface) {
mSession.setSurface(surface);
}
TvInputManager.java
setSurface(Surface surface) {
mService.setSurface(mToken, surface, mUserId);
}
TvInputManagerService.java
setSurface(IBinder sessionToken, Surface surface, int userId) {
getSessionLocked(sessionState.hardwareSessionToken,
Process.SYSTEM_UID, resolvedUserId).setSurface(surface);
}
TvInputService.java
setSurface(Surface surface) {
onSetSurface(surface);
}
Now we this need to be overriden. For HDMI-Input, or any other Hardware device, it can be done like below.
private final TvInputManager.HardwareCallback mHardwareCallback = new TvInputManager.HardwareCallback() {
@Override
public void onReleased()
{
}
@Override
public void onStreamConfigChanged(TvStreamConfig[] configs)
{
mTvStreamConfig = configs;
}
};
mHardware = mTvInputManager.acquireTvInputHardware(mDeviceId, mHardwareCallback, mTvInputInfo);
onSetSurface(Surface surface)
{
mHardware.setSurface(mSurface, mTvStreamConfig[0]);
return true;
}
Now this call will be directed to
TvInputManager.java
setSurface(Surface surface, TvStreamConfig config) {
return mInterface.setSurface(surface, config);
}
TvInputHardwareManager.java
A TvInputHardwareImpl object holds only one active session. Therefore, if a client
attempts to call setSurface with different TvStreamConfig objects, the last call will prevail.
setSurface(Surface surface, TvStreamConfig config)
if (surface == null) {
result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig);
mActiveConfig = null;
} else {
result = mHal.addStream(mInfo.getDeviceId(), surface, config);
}
TvInputHal.java
addStream(int deviceId, Surface surface, TvStreamConfig streamConfig) {
if (nativeAddStream(mPtr, deviceId, streamConfig.getStreamId(), surface) == 0) {
return SUCCESS;
}
jni/com_android_server_tv_TvInputHal.cpp
JTvInputHal::addStream(int deviceId, int streamId, const sp<Surface>& surface) {
if (mDevice->get_stream_configurations(
mDevice, deviceId, &numConfigs, &configs) != 0) {
return UNKNOWN_ERROR;
}
if (mDevice->open_stream(mDevice, deviceId, &stream) != 0) {
ALOGE("Couldn't add stream");
return UNKNOWN_ERROR;
}
}
And finally in tv_input HAL implementation, here put your code for HDMI kernel driver calls to get the video stream.
tv_input_open_stream(struct tv_input_device*, int device id , tv_stream_t* stream)
{
//This is the place, the HDMI driver functions call related to opening stream should be made.
return 0;
}
Similarly if surface is null, then close_stream will be called,
tv_input_close_stream(struct tv_input_device*, int device id , int)
{
//This is the place, the HDMI driver functions call related to closing stream should be made.
return 0;
}
For a dummy tv_input HAL implementation, refer to post.
No comments:
Post a Comment