Skip to content

Commit 052e4ae

Browse files
authored
Allow callback for H264 codec not support for Android Devices (#596)
* support checking h264 and notifying user * add boolean to toggle enableH264Encoding and add docs * address commas and semicolons in failing test * remove unnecessary comma * pass encodingParameters * remove spacing * address comments * move map builder * be more explicit in comment * move it to a different place * Change to return a list of supported codecs
1 parent 4e69622 commit 052e4ae

File tree

5 files changed

+87
-9
lines changed

5 files changed

+87
-9
lines changed

android/src/main/java/com/twiliorn/library/CustomTwilioVideoView.java

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,16 @@
7171
import com.twilio.video.Video;
7272
import com.twilio.video.VideoDimensions;
7373
import com.twilio.video.VideoFormat;
74+
import com.twilio.video.VideoCodec;
7475

7576
import org.webrtc.voiceengine.WebRtcAudioManager;
7677

7778
import tvi.webrtc.Camera1Enumerator;
79+
import tvi.webrtc.HardwareVideoEncoderFactory;
80+
import tvi.webrtc.HardwareVideoDecoderFactory;
81+
import tvi.webrtc.VideoCodecInfo;
82+
import com.twilio.video.H264Codec;
83+
import com.twilio.video.Vp8Codec;
7884

7985
import java.lang.annotation.Retention;
8086
import java.lang.annotation.RetentionPolicy;
@@ -103,6 +109,7 @@
103109
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_STATS_RECEIVED;
104110
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_VIDEO_CHANGED;
105111
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_DOMINANT_SPEAKER_CHANGED;
112+
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_LOCAL_PARTICIPANT_SUPPORTED_CODECS;
106113

107114
public class CustomTwilioVideoView extends View implements LifecycleEventListener, AudioManager.OnAudioFocusChangeListener {
108115
private static final String TAG = "CustomTwilioVideoView";
@@ -117,6 +124,7 @@ public class CustomTwilioVideoView extends View implements LifecycleEventListene
117124
private static String backFacingDevice;
118125
private boolean maintainVideoTrackInBackground = false;
119126
private String cameraType = "";
127+
private boolean enableH264Codec = false;
120128

121129
@Retention(RetentionPolicy.SOURCE)
122130
@StringDef({Events.ON_CAMERA_SWITCHED,
@@ -140,7 +148,8 @@ public class CustomTwilioVideoView extends View implements LifecycleEventListene
140148
Events.ON_PARTICIPANT_DISABLED_AUDIO_TRACK,
141149
Events.ON_STATS_RECEIVED,
142150
Events.ON_NETWORK_QUALITY_LEVELS_CHANGED,
143-
Events.ON_DOMINANT_SPEAKER_CHANGED
151+
Events.ON_DOMINANT_SPEAKER_CHANGED,
152+
Events.ON_LOCAL_PARTICIPANT_SUPPORTED_CODECS,
144153
})
145154
public @interface Events {
146155
String ON_CAMERA_SWITCHED = "onCameraSwitched";
@@ -165,6 +174,7 @@ public class CustomTwilioVideoView extends View implements LifecycleEventListene
165174
String ON_STATS_RECEIVED = "onStatsReceived";
166175
String ON_NETWORK_QUALITY_LEVELS_CHANGED = "onNetworkQualityLevelsChanged";
167176
String ON_DOMINANT_SPEAKER_CHANGED = "onDominantSpeakerDidChange";
177+
String ON_LOCAL_PARTICIPANT_SUPPORTED_CODECS = "onLocalParticipantSupportedCodecs";
168178
}
169179

170180
private final ThemedReactContext themedReactContext;
@@ -435,7 +445,8 @@ public void connectToRoomWrapper(
435445
boolean enableNetworkQualityReporting,
436446
boolean dominantSpeakerEnabled,
437447
boolean maintainVideoTrackInBackground,
438-
String cameraType
448+
String cameraType,
449+
boolean enableH264Codec
439450
) {
440451
this.roomName = roomName;
441452
this.accessToken = accessToken;
@@ -444,6 +455,7 @@ public void connectToRoomWrapper(
444455
this.dominantSpeakerEnabled = dominantSpeakerEnabled;
445456
this.maintainVideoTrackInBackground = maintainVideoTrackInBackground;
446457
this.cameraType = cameraType;
458+
this.enableH264Codec = enableH264Codec;
447459

448460
// Share your microphone
449461
localAudioTrack = LocalAudioTrack.create(getContext(), enableAudio);
@@ -487,6 +499,48 @@ public void connectToRoom() {
487499
connectOptionsBuilder.dataTracks(Collections.singletonList(localDataTrack));
488500
}
489501

502+
// H264 Codec Support Detection: https://www.twilio.com/docs/video/managing-codecs
503+
HardwareVideoEncoderFactory hardwareVideoEncoderFactory = new HardwareVideoEncoderFactory(null, true, true);
504+
HardwareVideoDecoderFactory hardwareVideoDecoderFactory = new HardwareVideoDecoderFactory(null);
505+
506+
boolean h264EncoderSupported = false;
507+
for (VideoCodecInfo videoCodecInfo : hardwareVideoEncoderFactory.getSupportedCodecs()) {
508+
if (videoCodecInfo.name.equalsIgnoreCase("h264")) {
509+
h264EncoderSupported = true;
510+
break;
511+
}
512+
}
513+
boolean h264DecoderSupported = false;
514+
for (VideoCodecInfo videoCodecInfo : hardwareVideoDecoderFactory.getSupportedCodecs()) {
515+
if (videoCodecInfo.name.equalsIgnoreCase("h264")) {
516+
h264DecoderSupported = true;
517+
break;
518+
}
519+
}
520+
521+
boolean isH264Supported = h264EncoderSupported && h264DecoderSupported;
522+
523+
Log.d("RNTwilioVideo", "H264 supported by hardware: " + isH264Supported);
524+
525+
WritableArray supportedCodecs = new WritableNativeArray();
526+
527+
VideoCodec videoCodec = new Vp8Codec();
528+
// VP8 is supported on all android devices by default
529+
supportedCodecs.pushString(videoCodec.toString());
530+
531+
if (isH264Supported && this.enableH264Codec) {
532+
videoCodec = new H264Codec();
533+
supportedCodecs.pushString(videoCodec.toString());
534+
}
535+
536+
WritableMap event = new WritableNativeMap();
537+
538+
event.putArray("supportedCodecs", supportedCodecs);
539+
540+
pushEvent(CustomTwilioVideoView.this, ON_LOCAL_PARTICIPANT_SUPPORTED_CODECS, event);
541+
542+
connectOptionsBuilder.preferVideoCodecs(Collections.singletonList(videoCodec));
543+
490544
connectOptionsBuilder.enableDominantSpeaker(this.dominantSpeakerEnabled);
491545

492546
if (enableNetworkQualityReporting) {

android/src/main/java/com/twiliorn/library/CustomTwilioVideoViewManager.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import android.support.annotation.Nullable;
1212

1313
import com.facebook.react.bridge.ReadableArray;
14+
import com.facebook.react.bridge.ReadableMap;
1415
import com.facebook.react.common.MapBuilder;
1516
import com.facebook.react.uimanager.SimpleViewManager;
1617
import com.facebook.react.uimanager.ThemedReactContext;
@@ -40,7 +41,7 @@
4041
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_STATS_RECEIVED;
4142
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_NETWORK_QUALITY_LEVELS_CHANGED;
4243
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_DOMINANT_SPEAKER_CHANGED;
43-
44+
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_LOCAL_PARTICIPANT_SUPPORTED_CODECS;
4445

4546
public class CustomTwilioVideoViewManager extends SimpleViewManager<CustomTwilioVideoView> {
4647
public static final String REACT_CLASS = "RNCustomTwilioVideoView";
@@ -83,6 +84,8 @@ public void receiveCommand(CustomTwilioVideoView view, int commandId, @Nullable
8384
boolean dominantSpeakerEnabled = args.getBoolean(6);
8485
boolean maintainVideoTrackInBackground = args.getBoolean(7);
8586
String cameraType = args.getString(8);
87+
ReadableMap encodingParameters = args.getMap(9);
88+
boolean enableH264Codec = encodingParameters.getBoolean("enableH264Codec");
8689
view.connectToRoomWrapper(
8790
roomName,
8891
accessToken,
@@ -92,7 +95,8 @@ public void receiveCommand(CustomTwilioVideoView view, int commandId, @Nullable
9295
enableNetworkQualityReporting,
9396
dominantSpeakerEnabled,
9497
maintainVideoTrackInBackground,
95-
cameraType
98+
cameraType,
99+
enableH264Codec
96100
);
97101
break;
98102
case DISCONNECT:
@@ -166,7 +170,8 @@ public Map getExportedCustomDirectEventTypeConstants() {
166170
));
167171

168172
map.putAll(MapBuilder.of(
169-
ON_PARTICIPANT_REMOVED_DATA_TRACK, MapBuilder.of("registrationName", ON_PARTICIPANT_REMOVED_DATA_TRACK)
173+
ON_PARTICIPANT_REMOVED_DATA_TRACK, MapBuilder.of("registrationName", ON_PARTICIPANT_REMOVED_DATA_TRACK),
174+
ON_LOCAL_PARTICIPANT_SUPPORTED_CODECS, MapBuilder.of("registrationName", ON_LOCAL_PARTICIPANT_SUPPORTED_CODECS)
170175
));
171176

172177
map.putAll(MapBuilder.of(

docs/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ onCameraDidStopRunning | func | no | | Called when the camera has stopped runin
7070
onStatsReceived | func | no | | Called when stats are received (after calling getStats)
7171
onNetworkQualityLevelsChanged | func | no | | Called when the network quality levels of a participant have changed (only if enableNetworkQualityReporting is set to True when connecting)
7272
onDominantSpeakerDidChange | func | no | | Called when dominant speaker changes @param {{ participant, room }} dominant participant
73+
onLocalParticipantSupportedCodecs | func | no | | Always called on android with @param {{ supportedCodecs }} after connecting to the room
74+
7375
-----
7476

7577
**src/TwilioVideoLocalView.android.js**

index.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ declare module "react-native-twilio-video-webrtc" {
8484

8585
export type DominantSpeakerChangedCb = (d: DominantSpeakerChangedEventArgs) => void;
8686

87+
export type LocalParticipantSupportedCodecsCbEventArgs = {
88+
supportedCodecs: Array<string>;
89+
}
90+
91+
export type LocalParticipantSupportedCodecsCb = (d: LocalParticipantSupportedCodecsCbEventArgs) => void;
92+
8793
export type TwilioVideoProps = ViewProps & {
8894
onCameraDidStart?: () => void;
8995
onCameraDidStopRunning?: (err: any) => void;
@@ -105,6 +111,7 @@ declare module "react-native-twilio-video-webrtc" {
105111
onRoomParticipantDidConnect?: ParticipantEventCb;
106112
onRoomParticipantDidDisconnect?: ParticipantEventCb;
107113
onNetworkQualityLevelsChanged?: NetworkLevelChangeEventCb;
114+
onLocalParticipantSupportedCodecs?: LocalParticipantSupportedCodecsCb;
108115

109116
onStatsReceived?: (data: any) => void;
110117
onDataTrackMessageReceived?: DataTrackEventCb;
@@ -137,6 +144,9 @@ declare module "react-native-twilio-video-webrtc" {
137144
enableAudio?: boolean;
138145
enableVideo?: boolean;
139146
enableRemoteAudio?: boolean;
147+
encodingParameters?: {
148+
enableH264Codec?: boolean;
149+
};
140150
enableNetworkQualityReporting?: boolean;
141151
maintainVideoTrackInBackground?: boolean;
142152
};

src/TwilioVideo.android.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,11 @@ const propTypes = {
144144
* Called when dominant speaker changes
145145
* @param {{ participant, room }} dominant participant and room
146146
*/
147-
onDominantSpeakerDidChange: PropTypes.func
147+
onDominantSpeakerDidChange: PropTypes.func,
148+
/**
149+
* Callback that is called after determining what codecs are supported
150+
*/
151+
onLocalParticipantSupportedCodecs: PropTypes.func
148152
}
149153

150154
const nativeEvents = {
@@ -174,7 +178,8 @@ class CustomTwilioVideoView extends Component {
174178
enableRemoteAudio = true,
175179
enableNetworkQualityReporting = false,
176180
dominantSpeakerEnabled = false,
177-
maintainVideoTrackInBackground = false
181+
maintainVideoTrackInBackground = false,
182+
encodingParameters = {}
178183
}) {
179184
this.runCommand(nativeEvents.connectToRoom, [
180185
roomName,
@@ -185,7 +190,8 @@ class CustomTwilioVideoView extends Component {
185190
enableNetworkQualityReporting,
186191
dominantSpeakerEnabled,
187192
maintainVideoTrackInBackground,
188-
cameraType
193+
cameraType,
194+
encodingParameters
189195
])
190196
}
191197

@@ -292,7 +298,8 @@ class CustomTwilioVideoView extends Component {
292298
'onParticipantDisabledAudioTrack',
293299
'onStatsReceived',
294300
'onNetworkQualityLevelsChanged',
295-
'onDominantSpeakerDidChange'
301+
'onDominantSpeakerDidChange',
302+
'onLocalParticipantSupportedCodecs'
296303
].reduce((wrappedEvents, eventName) => {
297304
if (this.props[eventName]) {
298305
return {

0 commit comments

Comments
 (0)