@bits-innovate/react-native-vstarcam 1.0.18 → 1.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/libs/player_extract/AndroidManifest.xml +9 -0
- package/android/libs/player_extract/META-INF/com/android/build/gradle/aar-metadata.properties +4 -0
- package/android/libs/player_extract/R.txt +229 -0
- package/android/libs/player_extract/classes.jar +0 -0
- package/android/libs/player_extract/jni/arm64-v8a/libOKSMARTPLAY.so +0 -0
- package/android/libs/player_extract/jni/arm64-v8a/libc++_shared.so +0 -0
- package/android/libs/player_extract/jni/arm64-v8a/libyuv.so +0 -0
- package/android/libs/player_extract/jni/armeabi-v7a/libOKSMARTPLAY.so +0 -0
- package/android/libs/player_extract/jni/armeabi-v7a/libc++_shared.so +0 -0
- package/android/libs/player_extract/jni/armeabi-v7a/libyuv.so +0 -0
- package/android/src/main/java/com/reactnativevstarcam/VStarCamModule.java +85 -7
- package/android/src/main/java/com/reactnativevstarcam/VStarCamVideoView.java +250 -91
- package/package.json +1 -1
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
int attr activityAction 0x0
|
|
2
|
+
int attr activityName 0x0
|
|
3
|
+
int attr alpha 0x0
|
|
4
|
+
int attr alwaysExpand 0x0
|
|
5
|
+
int attr clearTop 0x0
|
|
6
|
+
int attr finishPrimaryWithSecondary 0x0
|
|
7
|
+
int attr finishSecondaryWithPrimary 0x0
|
|
8
|
+
int attr font 0x0
|
|
9
|
+
int attr fontProviderAuthority 0x0
|
|
10
|
+
int attr fontProviderCerts 0x0
|
|
11
|
+
int attr fontProviderFetchStrategy 0x0
|
|
12
|
+
int attr fontProviderFetchTimeout 0x0
|
|
13
|
+
int attr fontProviderPackage 0x0
|
|
14
|
+
int attr fontProviderQuery 0x0
|
|
15
|
+
int attr fontProviderSystemFontFamily 0x0
|
|
16
|
+
int attr fontStyle 0x0
|
|
17
|
+
int attr fontVariationSettings 0x0
|
|
18
|
+
int attr fontWeight 0x0
|
|
19
|
+
int attr nestedScrollViewStyle 0x0
|
|
20
|
+
int attr placeholderActivityName 0x0
|
|
21
|
+
int attr primaryActivityName 0x0
|
|
22
|
+
int attr queryPatterns 0x0
|
|
23
|
+
int attr secondaryActivityAction 0x0
|
|
24
|
+
int attr secondaryActivityName 0x0
|
|
25
|
+
int attr shortcutMatchRequired 0x0
|
|
26
|
+
int attr splitLayoutDirection 0x0
|
|
27
|
+
int attr splitMinSmallestWidth 0x0
|
|
28
|
+
int attr splitMinWidth 0x0
|
|
29
|
+
int attr splitRatio 0x0
|
|
30
|
+
int attr ttcIndex 0x0
|
|
31
|
+
int color androidx_core_ripple_material_light 0x0
|
|
32
|
+
int color androidx_core_secondary_text_default_material_light 0x0
|
|
33
|
+
int color notification_action_color_filter 0x0
|
|
34
|
+
int color notification_icon_bg_color 0x0
|
|
35
|
+
int color ripple_material_light 0x0
|
|
36
|
+
int color secondary_text_default_material_light 0x0
|
|
37
|
+
int dimen compat_button_inset_horizontal_material 0x0
|
|
38
|
+
int dimen compat_button_inset_vertical_material 0x0
|
|
39
|
+
int dimen compat_button_padding_horizontal_material 0x0
|
|
40
|
+
int dimen compat_button_padding_vertical_material 0x0
|
|
41
|
+
int dimen compat_control_corner_material 0x0
|
|
42
|
+
int dimen compat_notification_large_icon_max_height 0x0
|
|
43
|
+
int dimen compat_notification_large_icon_max_width 0x0
|
|
44
|
+
int dimen notification_action_icon_size 0x0
|
|
45
|
+
int dimen notification_action_text_size 0x0
|
|
46
|
+
int dimen notification_big_circle_margin 0x0
|
|
47
|
+
int dimen notification_content_margin_start 0x0
|
|
48
|
+
int dimen notification_large_icon_height 0x0
|
|
49
|
+
int dimen notification_large_icon_width 0x0
|
|
50
|
+
int dimen notification_main_column_padding_top 0x0
|
|
51
|
+
int dimen notification_media_narrow_margin 0x0
|
|
52
|
+
int dimen notification_right_icon_size 0x0
|
|
53
|
+
int dimen notification_right_side_padding_top 0x0
|
|
54
|
+
int dimen notification_small_icon_background_padding 0x0
|
|
55
|
+
int dimen notification_small_icon_size_as_large 0x0
|
|
56
|
+
int dimen notification_subtext_size 0x0
|
|
57
|
+
int dimen notification_top_pad 0x0
|
|
58
|
+
int dimen notification_top_pad_large_text 0x0
|
|
59
|
+
int drawable launch_background 0x0
|
|
60
|
+
int drawable notification_action_background 0x0
|
|
61
|
+
int drawable notification_bg 0x0
|
|
62
|
+
int drawable notification_bg_low 0x0
|
|
63
|
+
int drawable notification_bg_low_normal 0x0
|
|
64
|
+
int drawable notification_bg_low_pressed 0x0
|
|
65
|
+
int drawable notification_bg_normal 0x0
|
|
66
|
+
int drawable notification_bg_normal_pressed 0x0
|
|
67
|
+
int drawable notification_icon_background 0x0
|
|
68
|
+
int drawable notification_template_icon_bg 0x0
|
|
69
|
+
int drawable notification_template_icon_low_bg 0x0
|
|
70
|
+
int drawable notification_tile_bg 0x0
|
|
71
|
+
int drawable notify_panel_notification_icon_bg 0x0
|
|
72
|
+
int id accessibility_action_clickable_span 0x0
|
|
73
|
+
int id accessibility_custom_action_0 0x0
|
|
74
|
+
int id accessibility_custom_action_1 0x0
|
|
75
|
+
int id accessibility_custom_action_10 0x0
|
|
76
|
+
int id accessibility_custom_action_11 0x0
|
|
77
|
+
int id accessibility_custom_action_12 0x0
|
|
78
|
+
int id accessibility_custom_action_13 0x0
|
|
79
|
+
int id accessibility_custom_action_14 0x0
|
|
80
|
+
int id accessibility_custom_action_15 0x0
|
|
81
|
+
int id accessibility_custom_action_16 0x0
|
|
82
|
+
int id accessibility_custom_action_17 0x0
|
|
83
|
+
int id accessibility_custom_action_18 0x0
|
|
84
|
+
int id accessibility_custom_action_19 0x0
|
|
85
|
+
int id accessibility_custom_action_2 0x0
|
|
86
|
+
int id accessibility_custom_action_20 0x0
|
|
87
|
+
int id accessibility_custom_action_21 0x0
|
|
88
|
+
int id accessibility_custom_action_22 0x0
|
|
89
|
+
int id accessibility_custom_action_23 0x0
|
|
90
|
+
int id accessibility_custom_action_24 0x0
|
|
91
|
+
int id accessibility_custom_action_25 0x0
|
|
92
|
+
int id accessibility_custom_action_26 0x0
|
|
93
|
+
int id accessibility_custom_action_27 0x0
|
|
94
|
+
int id accessibility_custom_action_28 0x0
|
|
95
|
+
int id accessibility_custom_action_29 0x0
|
|
96
|
+
int id accessibility_custom_action_3 0x0
|
|
97
|
+
int id accessibility_custom_action_30 0x0
|
|
98
|
+
int id accessibility_custom_action_31 0x0
|
|
99
|
+
int id accessibility_custom_action_4 0x0
|
|
100
|
+
int id accessibility_custom_action_5 0x0
|
|
101
|
+
int id accessibility_custom_action_6 0x0
|
|
102
|
+
int id accessibility_custom_action_7 0x0
|
|
103
|
+
int id accessibility_custom_action_8 0x0
|
|
104
|
+
int id accessibility_custom_action_9 0x0
|
|
105
|
+
int id action_container 0x0
|
|
106
|
+
int id action_divider 0x0
|
|
107
|
+
int id action_image 0x0
|
|
108
|
+
int id action_text 0x0
|
|
109
|
+
int id actions 0x0
|
|
110
|
+
int id androidx_window_activity_scope 0x0
|
|
111
|
+
int id async 0x0
|
|
112
|
+
int id blocking 0x0
|
|
113
|
+
int id chronometer 0x0
|
|
114
|
+
int id dialog_button 0x0
|
|
115
|
+
int id forever 0x0
|
|
116
|
+
int id icon 0x0
|
|
117
|
+
int id icon_group 0x0
|
|
118
|
+
int id info 0x0
|
|
119
|
+
int id italic 0x0
|
|
120
|
+
int id line1 0x0
|
|
121
|
+
int id line3 0x0
|
|
122
|
+
int id locale 0x0
|
|
123
|
+
int id ltr 0x0
|
|
124
|
+
int id normal 0x0
|
|
125
|
+
int id notification_background 0x0
|
|
126
|
+
int id notification_main_column 0x0
|
|
127
|
+
int id notification_main_column_container 0x0
|
|
128
|
+
int id right_icon 0x0
|
|
129
|
+
int id right_side 0x0
|
|
130
|
+
int id rtl 0x0
|
|
131
|
+
int id tag_accessibility_actions 0x0
|
|
132
|
+
int id tag_accessibility_clickable_spans 0x0
|
|
133
|
+
int id tag_accessibility_heading 0x0
|
|
134
|
+
int id tag_accessibility_pane_title 0x0
|
|
135
|
+
int id tag_on_apply_window_listener 0x0
|
|
136
|
+
int id tag_on_receive_content_listener 0x0
|
|
137
|
+
int id tag_on_receive_content_mime_types 0x0
|
|
138
|
+
int id tag_screen_reader_focusable 0x0
|
|
139
|
+
int id tag_state_description 0x0
|
|
140
|
+
int id tag_transition_group 0x0
|
|
141
|
+
int id tag_unhandled_key_event_manager 0x0
|
|
142
|
+
int id tag_unhandled_key_listeners 0x0
|
|
143
|
+
int id tag_window_insets_animation_callback 0x0
|
|
144
|
+
int id text 0x0
|
|
145
|
+
int id text2 0x0
|
|
146
|
+
int id time 0x0
|
|
147
|
+
int id title 0x0
|
|
148
|
+
int integer status_bar_notification_info_maxnum 0x0
|
|
149
|
+
int layout custom_dialog 0x0
|
|
150
|
+
int layout notification_action 0x0
|
|
151
|
+
int layout notification_action_tombstone 0x0
|
|
152
|
+
int layout notification_template_custom_big 0x0
|
|
153
|
+
int layout notification_template_icon_group 0x0
|
|
154
|
+
int layout notification_template_part_chronometer 0x0
|
|
155
|
+
int layout notification_template_part_time 0x0
|
|
156
|
+
int string status_bar_notification_info_overflow 0x0
|
|
157
|
+
int style LaunchTheme 0x0
|
|
158
|
+
int style TextAppearance_Compat_Notification 0x0
|
|
159
|
+
int style TextAppearance_Compat_Notification_Info 0x0
|
|
160
|
+
int style TextAppearance_Compat_Notification_Line2 0x0
|
|
161
|
+
int style TextAppearance_Compat_Notification_Time 0x0
|
|
162
|
+
int style TextAppearance_Compat_Notification_Title 0x0
|
|
163
|
+
int style Widget_Compat_NotificationActionContainer 0x0
|
|
164
|
+
int style Widget_Compat_NotificationActionText 0x0
|
|
165
|
+
int[] styleable ActivityFilter { 0x0, 0x0 }
|
|
166
|
+
int styleable ActivityFilter_activityAction 0
|
|
167
|
+
int styleable ActivityFilter_activityName 1
|
|
168
|
+
int[] styleable ActivityRule { 0x0 }
|
|
169
|
+
int styleable ActivityRule_alwaysExpand 0
|
|
170
|
+
int[] styleable Capability { 0x0, 0x0 }
|
|
171
|
+
int styleable Capability_queryPatterns 0
|
|
172
|
+
int styleable Capability_shortcutMatchRequired 1
|
|
173
|
+
int[] styleable ColorStateListItem { 0x0, 0x101031f, 0x10101a5 }
|
|
174
|
+
int styleable ColorStateListItem_alpha 0
|
|
175
|
+
int styleable ColorStateListItem_android_alpha 1
|
|
176
|
+
int styleable ColorStateListItem_android_color 2
|
|
177
|
+
int[] styleable FontFamily { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }
|
|
178
|
+
int styleable FontFamily_fontProviderAuthority 0
|
|
179
|
+
int styleable FontFamily_fontProviderCerts 1
|
|
180
|
+
int styleable FontFamily_fontProviderFetchStrategy 2
|
|
181
|
+
int styleable FontFamily_fontProviderFetchTimeout 3
|
|
182
|
+
int styleable FontFamily_fontProviderPackage 4
|
|
183
|
+
int styleable FontFamily_fontProviderQuery 5
|
|
184
|
+
int styleable FontFamily_fontProviderSystemFontFamily 6
|
|
185
|
+
int[] styleable FontFamilyFont { 0x1010532, 0x101053f, 0x1010570, 0x1010533, 0x101056f, 0x0, 0x0, 0x0, 0x0, 0x0 }
|
|
186
|
+
int styleable FontFamilyFont_android_font 0
|
|
187
|
+
int styleable FontFamilyFont_android_fontStyle 1
|
|
188
|
+
int styleable FontFamilyFont_android_fontVariationSettings 2
|
|
189
|
+
int styleable FontFamilyFont_android_fontWeight 3
|
|
190
|
+
int styleable FontFamilyFont_android_ttcIndex 4
|
|
191
|
+
int styleable FontFamilyFont_font 5
|
|
192
|
+
int styleable FontFamilyFont_fontStyle 6
|
|
193
|
+
int styleable FontFamilyFont_fontVariationSettings 7
|
|
194
|
+
int styleable FontFamilyFont_fontWeight 8
|
|
195
|
+
int styleable FontFamilyFont_ttcIndex 9
|
|
196
|
+
int[] styleable GradientColor { 0x101020b, 0x10101a2, 0x10101a3, 0x101019e, 0x1010512, 0x1010513, 0x10101a4, 0x101019d, 0x1010510, 0x1010511, 0x1010201, 0x10101a1 }
|
|
197
|
+
int styleable GradientColor_android_centerColor 0
|
|
198
|
+
int styleable GradientColor_android_centerX 1
|
|
199
|
+
int styleable GradientColor_android_centerY 2
|
|
200
|
+
int styleable GradientColor_android_endColor 3
|
|
201
|
+
int styleable GradientColor_android_endX 4
|
|
202
|
+
int styleable GradientColor_android_endY 5
|
|
203
|
+
int styleable GradientColor_android_gradientRadius 6
|
|
204
|
+
int styleable GradientColor_android_startColor 7
|
|
205
|
+
int styleable GradientColor_android_startX 8
|
|
206
|
+
int styleable GradientColor_android_startY 9
|
|
207
|
+
int styleable GradientColor_android_tileMode 10
|
|
208
|
+
int styleable GradientColor_android_type 11
|
|
209
|
+
int[] styleable GradientColorItem { 0x10101a5, 0x1010514 }
|
|
210
|
+
int styleable GradientColorItem_android_color 0
|
|
211
|
+
int styleable GradientColorItem_android_offset 1
|
|
212
|
+
int[] styleable SplitPairFilter { 0x0, 0x0, 0x0 }
|
|
213
|
+
int styleable SplitPairFilter_primaryActivityName 0
|
|
214
|
+
int styleable SplitPairFilter_secondaryActivityAction 1
|
|
215
|
+
int styleable SplitPairFilter_secondaryActivityName 2
|
|
216
|
+
int[] styleable SplitPairRule { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }
|
|
217
|
+
int styleable SplitPairRule_clearTop 0
|
|
218
|
+
int styleable SplitPairRule_finishPrimaryWithSecondary 1
|
|
219
|
+
int styleable SplitPairRule_finishSecondaryWithPrimary 2
|
|
220
|
+
int styleable SplitPairRule_splitLayoutDirection 3
|
|
221
|
+
int styleable SplitPairRule_splitMinSmallestWidth 4
|
|
222
|
+
int styleable SplitPairRule_splitMinWidth 5
|
|
223
|
+
int styleable SplitPairRule_splitRatio 6
|
|
224
|
+
int[] styleable SplitPlaceholderRule { 0x0, 0x0, 0x0, 0x0, 0x0 }
|
|
225
|
+
int styleable SplitPlaceholderRule_placeholderActivityName 0
|
|
226
|
+
int styleable SplitPlaceholderRule_splitLayoutDirection 1
|
|
227
|
+
int styleable SplitPlaceholderRule_splitMinSmallestWidth 2
|
|
228
|
+
int styleable SplitPlaceholderRule_splitMinWidth 3
|
|
229
|
+
int styleable SplitPlaceholderRule_splitRatio 4
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -140,7 +140,8 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
140
140
|
private final ExecutorService executor;
|
|
141
141
|
|
|
142
142
|
// Client tracking - maps our clientPtr to actual SDK client handle
|
|
143
|
-
|
|
143
|
+
// Made static so VStarCamVideoView can access SDK pointers
|
|
144
|
+
private static Map<Integer, ClientInfo> clients = new HashMap<>();
|
|
144
145
|
private boolean isNativeLibraryLoaded = false;
|
|
145
146
|
private boolean isP2PInitialized = false;
|
|
146
147
|
|
|
@@ -156,8 +157,21 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
156
157
|
long sdkClientPtr = 0; // Actual SDK client pointer (long)
|
|
157
158
|
boolean isConnected = false;
|
|
158
159
|
boolean isLoggedIn = false;
|
|
160
|
+
String username; // Login username for CGI commands
|
|
161
|
+
String password; // Login password for CGI commands
|
|
159
162
|
}
|
|
160
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Get the actual SDK client pointer for a given internal client ID.
|
|
166
|
+
* This is needed by VStarCamVideoView to connect to the player.
|
|
167
|
+
*/
|
|
168
|
+
public static long getSdkClientPtr(int clientPtr) {
|
|
169
|
+
ClientInfo info = clients.get(clientPtr);
|
|
170
|
+
if (info != null) {
|
|
171
|
+
return info.sdkClientPtr;
|
|
172
|
+
}
|
|
173
|
+
return 0;
|
|
174
|
+
}
|
|
161
175
|
|
|
162
176
|
public VStarCamModule(ReactApplicationContext reactContext) {
|
|
163
177
|
super(reactContext);
|
|
@@ -552,6 +566,8 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
552
566
|
}
|
|
553
567
|
|
|
554
568
|
clientInfo.isLoggedIn = true;
|
|
569
|
+
clientInfo.username = username;
|
|
570
|
+
clientInfo.password = password;
|
|
555
571
|
Log.d(TAG, "JNIApi.login called successfully");
|
|
556
572
|
|
|
557
573
|
promise.resolve(true);
|
|
@@ -680,13 +696,45 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
680
696
|
}
|
|
681
697
|
|
|
682
698
|
/**
|
|
683
|
-
* Start video stream
|
|
699
|
+
* Start video stream by sending livestream.cgi command
|
|
700
|
+
* Resolution: 1=high, 2=general, 4=low, 100=superHD
|
|
684
701
|
*/
|
|
685
702
|
@ReactMethod
|
|
686
703
|
public void startVideoStream(int clientPtr, int streamType, Promise promise) {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
704
|
+
Log.d(TAG, "startVideoStream called with type: " + streamType);
|
|
705
|
+
try {
|
|
706
|
+
ClientInfo clientInfo = clients.get(clientPtr);
|
|
707
|
+
if (clientInfo == null || clientInfo.sdkClientPtr == 0) {
|
|
708
|
+
promise.reject("E_NOT_CONNECTED", "Client not connected");
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// Send livestream.cgi command to start streaming
|
|
713
|
+
// streamid=10 starts the stream, substream is the resolution
|
|
714
|
+
String cgi = String.format(
|
|
715
|
+
"livestream.cgi?streamid=10&substream=%d&loginuse=%s&loginpas=%s",
|
|
716
|
+
streamType,
|
|
717
|
+
clientInfo.username != null ? clientInfo.username : "admin",
|
|
718
|
+
clientInfo.password != null ? clientInfo.password : ""
|
|
719
|
+
);
|
|
720
|
+
|
|
721
|
+
Log.d(TAG, "Sending livestream start command: " + cgi);
|
|
722
|
+
|
|
723
|
+
Method writeCgiMethod = jniApiClass.getMethod("writeCgi", long.class, String.class, int.class);
|
|
724
|
+
Object result = writeCgiMethod.invoke(null, clientInfo.sdkClientPtr, cgi, 5);
|
|
725
|
+
|
|
726
|
+
Log.d(TAG, "livestream start command sent, result: " + result);
|
|
727
|
+
|
|
728
|
+
WritableMap response = Arguments.createMap();
|
|
729
|
+
response.putBoolean("success", true);
|
|
730
|
+
response.putString("message", "Video stream started");
|
|
731
|
+
response.putInt("resolution", streamType);
|
|
732
|
+
promise.resolve(response);
|
|
733
|
+
|
|
734
|
+
} catch (Exception e) {
|
|
735
|
+
Log.e(TAG, "startVideoStream error", e);
|
|
736
|
+
promise.reject("E_VIDEO_START_FAILED", e.getMessage(), e);
|
|
737
|
+
}
|
|
690
738
|
}
|
|
691
739
|
|
|
692
740
|
/**
|
|
@@ -695,7 +743,37 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
695
743
|
@ReactMethod
|
|
696
744
|
public void stopVideoStream(int clientPtr, Promise promise) {
|
|
697
745
|
Log.d(TAG, "stopVideoStream called");
|
|
698
|
-
|
|
746
|
+
try {
|
|
747
|
+
ClientInfo clientInfo = clients.get(clientPtr);
|
|
748
|
+
if (clientInfo == null || clientInfo.sdkClientPtr == 0) {
|
|
749
|
+
promise.reject("E_NOT_CONNECTED", "Client not connected");
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
// Send livestream.cgi command to stop streaming
|
|
754
|
+
// streamid=16 stops the stream
|
|
755
|
+
String cgi = String.format(
|
|
756
|
+
"livestream.cgi?streamid=16&substream=0&loginuse=%s&loginpas=%s",
|
|
757
|
+
clientInfo.username != null ? clientInfo.username : "admin",
|
|
758
|
+
clientInfo.password != null ? clientInfo.password : ""
|
|
759
|
+
);
|
|
760
|
+
|
|
761
|
+
Log.d(TAG, "Sending livestream stop command: " + cgi);
|
|
762
|
+
|
|
763
|
+
Method writeCgiMethod = jniApiClass.getMethod("writeCgi", long.class, String.class, int.class);
|
|
764
|
+
Object result = writeCgiMethod.invoke(null, clientInfo.sdkClientPtr, cgi, 5);
|
|
765
|
+
|
|
766
|
+
Log.d(TAG, "livestream stop command sent, result: " + result);
|
|
767
|
+
|
|
768
|
+
WritableMap response = Arguments.createMap();
|
|
769
|
+
response.putBoolean("success", true);
|
|
770
|
+
response.putString("message", "Video stream stopped");
|
|
771
|
+
promise.resolve(response);
|
|
772
|
+
|
|
773
|
+
} catch (Exception e) {
|
|
774
|
+
Log.e(TAG, "stopVideoStream error", e);
|
|
775
|
+
promise.reject("E_VIDEO_STOP_FAILED", e.getMessage(), e);
|
|
776
|
+
}
|
|
699
777
|
}
|
|
700
778
|
|
|
701
779
|
/**
|
|
@@ -757,7 +835,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
757
835
|
@ReactMethod
|
|
758
836
|
public void getSdkVersion(Promise promise) {
|
|
759
837
|
WritableMap result = Arguments.createMap();
|
|
760
|
-
result.putString("version", "1.0.
|
|
838
|
+
result.putString("version", "1.0.20");
|
|
761
839
|
result.putBoolean("nativeLoaded", isNativeLibraryLoaded);
|
|
762
840
|
result.putString("nativeLib", "OKSMARTPPCS");
|
|
763
841
|
result.putBoolean("p2pInitialized", isP2PInitialized);
|
|
@@ -4,6 +4,7 @@ import android.content.Context;
|
|
|
4
4
|
import android.graphics.Color;
|
|
5
5
|
import android.graphics.SurfaceTexture;
|
|
6
6
|
import android.util.Log;
|
|
7
|
+
import android.view.Surface;
|
|
7
8
|
import android.view.TextureView;
|
|
8
9
|
import android.view.Gravity;
|
|
9
10
|
import android.widget.FrameLayout;
|
|
@@ -13,39 +14,46 @@ import java.lang.reflect.Method;
|
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Native video view for VStarCam camera streaming.
|
|
16
|
-
* Uses TextureView for video rendering with the native
|
|
17
|
+
* Uses TextureView for video rendering with the native AppPlayer SDK.
|
|
17
18
|
*/
|
|
18
|
-
public class VStarCamVideoView extends FrameLayout
|
|
19
|
+
public class VStarCamVideoView extends FrameLayout
|
|
20
|
+
implements TextureView.SurfaceTextureListener {
|
|
21
|
+
|
|
19
22
|
private static final String TAG = "VStarCamVideoView";
|
|
20
|
-
|
|
23
|
+
|
|
21
24
|
private TextureView textureView;
|
|
22
25
|
private TextView statusView;
|
|
26
|
+
private Surface surface;
|
|
27
|
+
|
|
28
|
+
// Client info
|
|
23
29
|
private long clientPtr = 0;
|
|
30
|
+
private long sdkClientPtr = 0; // Actual SDK pointer from VStarCamModule
|
|
31
|
+
private int resolution = 2;
|
|
32
|
+
|
|
33
|
+
// Player info
|
|
24
34
|
private long playerPtr = 0;
|
|
25
35
|
private boolean isStreaming = false;
|
|
26
|
-
private
|
|
27
|
-
|
|
28
|
-
// Player
|
|
36
|
+
private boolean playerInitialized = false;
|
|
37
|
+
|
|
38
|
+
// Player class (from AAR)
|
|
29
39
|
private Class<?> appPlayerClass;
|
|
30
|
-
|
|
31
|
-
private boolean playerLibLoaded = false;
|
|
32
|
-
|
|
40
|
+
|
|
33
41
|
public VStarCamVideoView(Context context) {
|
|
34
42
|
super(context);
|
|
35
43
|
init(context);
|
|
36
44
|
}
|
|
37
|
-
|
|
45
|
+
|
|
38
46
|
private void init(Context context) {
|
|
39
47
|
setBackgroundColor(Color.BLACK);
|
|
40
|
-
|
|
41
|
-
// Create
|
|
48
|
+
|
|
49
|
+
// Create TextureView for video rendering
|
|
42
50
|
textureView = new TextureView(context);
|
|
43
51
|
textureView.setSurfaceTextureListener(this);
|
|
44
52
|
addView(textureView, new LayoutParams(
|
|
45
|
-
LayoutParams.MATCH_PARENT,
|
|
53
|
+
LayoutParams.MATCH_PARENT,
|
|
46
54
|
LayoutParams.MATCH_PARENT
|
|
47
55
|
));
|
|
48
|
-
|
|
56
|
+
|
|
49
57
|
// Status overlay
|
|
50
58
|
statusView = new TextView(context);
|
|
51
59
|
statusView.setTextColor(Color.WHITE);
|
|
@@ -58,140 +66,291 @@ public class VStarCamVideoView extends FrameLayout implements TextureView.Surfac
|
|
|
58
66
|
);
|
|
59
67
|
statusParams.gravity = Gravity.CENTER;
|
|
60
68
|
addView(statusView, statusParams);
|
|
61
|
-
|
|
62
|
-
//
|
|
69
|
+
|
|
70
|
+
// Load player library and find class
|
|
63
71
|
loadPlayerLibrary();
|
|
64
72
|
}
|
|
65
|
-
|
|
73
|
+
|
|
66
74
|
private void loadPlayerLibrary() {
|
|
67
75
|
try {
|
|
76
|
+
// Load the player native lib
|
|
68
77
|
System.loadLibrary("OKSMARTPLAY");
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
Log.d(TAG, "OKSMARTPLAY library loaded");
|
|
79
|
+
|
|
80
|
+
// Find AppPlayer class - try multiple possible package names
|
|
81
|
+
// Based on decompiling app_player-5.0.0.aar classes.jar
|
|
82
|
+
String[] classNames = {
|
|
83
|
+
"com.veepai.AppPlayerApi", // Main API class from AAR
|
|
84
|
+
"com.veepai.app_player.AppPlayerPlugin", // Flutter plugin wrapper
|
|
85
|
+
"com.vstarcam.player.AppPlayer",
|
|
86
|
+
"com.vstarcam.AppPlayer",
|
|
87
|
+
"com.oksmartplay.AppPlayer"
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
for (String className : classNames) {
|
|
78
91
|
try {
|
|
79
|
-
appPlayerClass = Class.forName(
|
|
80
|
-
Log.d(TAG, "
|
|
81
|
-
|
|
82
|
-
Log
|
|
92
|
+
appPlayerClass = Class.forName(className);
|
|
93
|
+
Log.d(TAG, "Found player class: " + className);
|
|
94
|
+
|
|
95
|
+
// Log available methods for debugging
|
|
96
|
+
logPlayerMethods();
|
|
97
|
+
break;
|
|
98
|
+
} catch (ClassNotFoundException ignored) {
|
|
99
|
+
Log.d(TAG, "Class not found: " + className);
|
|
83
100
|
}
|
|
84
101
|
}
|
|
102
|
+
|
|
103
|
+
if (appPlayerClass == null) {
|
|
104
|
+
Log.e(TAG, "Could not find AppPlayer class in AAR");
|
|
105
|
+
}
|
|
106
|
+
|
|
85
107
|
} catch (UnsatisfiedLinkError e) {
|
|
86
|
-
Log.e(TAG, "Failed to load
|
|
87
|
-
playerLibLoaded = false;
|
|
108
|
+
Log.e(TAG, "Failed to load OKSMARTPLAY: " + e.getMessage());
|
|
88
109
|
}
|
|
89
110
|
}
|
|
90
|
-
|
|
111
|
+
|
|
112
|
+
private void logPlayerMethods() {
|
|
113
|
+
if (appPlayerClass == null) return;
|
|
114
|
+
|
|
115
|
+
Log.d(TAG, "=== AppPlayer Methods ===");
|
|
116
|
+
for (Method m : appPlayerClass.getDeclaredMethods()) {
|
|
117
|
+
StringBuilder params = new StringBuilder();
|
|
118
|
+
for (Class<?> p : m.getParameterTypes()) {
|
|
119
|
+
if (params.length() > 0) params.append(", ");
|
|
120
|
+
params.append(p.getSimpleName());
|
|
121
|
+
}
|
|
122
|
+
Log.d(TAG, " " + m.getName() + "(" + params + ") -> " +
|
|
123
|
+
m.getReturnType().getSimpleName());
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
91
127
|
/**
|
|
92
|
-
* Set the client pointer
|
|
128
|
+
* Set the client pointer from VStarCamModule.
|
|
129
|
+
* This is our internal pointer ID, not the SDK pointer.
|
|
93
130
|
*/
|
|
94
131
|
public void setClientPtr(long ptr) {
|
|
95
132
|
this.clientPtr = ptr;
|
|
96
133
|
Log.d(TAG, "Client pointer set: " + ptr);
|
|
97
|
-
|
|
98
|
-
|
|
134
|
+
|
|
135
|
+
// Lookup the actual SDK pointer from VStarCamModule
|
|
136
|
+
this.sdkClientPtr = VStarCamModule.getSdkClientPtr((int) ptr);
|
|
137
|
+
Log.d(TAG, "SDK client pointer: " + sdkClientPtr);
|
|
138
|
+
|
|
139
|
+
if (sdkClientPtr != 0) {
|
|
99
140
|
statusView.setText("Ready to stream");
|
|
141
|
+
} else {
|
|
142
|
+
statusView.setText("Waiting for connection...");
|
|
100
143
|
}
|
|
101
144
|
}
|
|
102
|
-
|
|
145
|
+
|
|
103
146
|
/**
|
|
104
|
-
* Set video resolution
|
|
147
|
+
* Set video resolution.
|
|
148
|
+
* 1=high, 2=general, 4=low, 100=superHD
|
|
105
149
|
*/
|
|
106
150
|
public void setResolution(int res) {
|
|
107
151
|
this.resolution = res;
|
|
108
152
|
Log.d(TAG, "Resolution set: " + res);
|
|
109
153
|
}
|
|
110
|
-
|
|
154
|
+
|
|
111
155
|
/**
|
|
112
|
-
* Start video streaming
|
|
156
|
+
* Start video streaming.
|
|
113
157
|
*/
|
|
114
158
|
public void startStream() {
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
|
|
159
|
+
if (sdkClientPtr == 0) {
|
|
160
|
+
// Try to get SDK pointer again in case it was set after setClientPtr
|
|
161
|
+
this.sdkClientPtr = VStarCamModule.getSdkClientPtr((int) clientPtr);
|
|
162
|
+
if (sdkClientPtr == 0) {
|
|
163
|
+
Log.e(TAG, "Cannot start: no SDK client pointer");
|
|
164
|
+
statusView.setText("Not connected");
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (surface == null) {
|
|
170
|
+
Log.e(TAG, "Cannot start: no surface available");
|
|
171
|
+
statusView.setText("No surface");
|
|
118
172
|
return;
|
|
119
173
|
}
|
|
120
|
-
|
|
121
|
-
if (
|
|
122
|
-
Log.e(TAG, "Cannot start
|
|
123
|
-
statusView.setText("Player
|
|
174
|
+
|
|
175
|
+
if (appPlayerClass == null) {
|
|
176
|
+
Log.e(TAG, "Cannot start: player class not found");
|
|
177
|
+
statusView.setText("Player unavailable");
|
|
124
178
|
return;
|
|
125
179
|
}
|
|
126
|
-
|
|
127
|
-
Log.d(TAG, "Starting video stream...");
|
|
180
|
+
|
|
128
181
|
statusView.setText("Starting stream...");
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
// 1. Create player instance if needed
|
|
185
|
+
if (playerPtr == 0) {
|
|
186
|
+
Method createMethod = appPlayerClass.getMethod("create");
|
|
187
|
+
Object result = createMethod.invoke(null);
|
|
188
|
+
playerPtr = (Long) result;
|
|
189
|
+
Log.d(TAG, "Player created: " + playerPtr);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// 2. Set the video source (P2P client)
|
|
193
|
+
try {
|
|
194
|
+
Method setSourceMethod = appPlayerClass.getMethod(
|
|
195
|
+
"setSource", long.class, long.class);
|
|
196
|
+
setSourceMethod.invoke(null, playerPtr, sdkClientPtr);
|
|
197
|
+
Log.d(TAG, "Source set to client: " + sdkClientPtr);
|
|
198
|
+
} catch (NoSuchMethodException e) {
|
|
199
|
+
Log.w(TAG, "setSource method not found, trying alternative...");
|
|
200
|
+
// Try alternative method signatures if the main one doesn't exist
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// 3. Set the render surface
|
|
204
|
+
try {
|
|
205
|
+
Method setSurfaceMethod = appPlayerClass.getMethod(
|
|
206
|
+
"setSurface", long.class, Surface.class);
|
|
207
|
+
setSurfaceMethod.invoke(null, playerPtr, surface);
|
|
208
|
+
Log.d(TAG, "Surface set");
|
|
209
|
+
} catch (NoSuchMethodException e) {
|
|
210
|
+
Log.w(TAG, "setSurface method not found, trying alternative...");
|
|
211
|
+
// Try with Object parameter
|
|
212
|
+
try {
|
|
213
|
+
Method setSurfaceMethod = appPlayerClass.getMethod(
|
|
214
|
+
"setSurface", long.class, Object.class);
|
|
215
|
+
setSurfaceMethod.invoke(null, playerPtr, surface);
|
|
216
|
+
Log.d(TAG, "Surface set (via Object)");
|
|
217
|
+
} catch (NoSuchMethodException e2) {
|
|
218
|
+
Log.e(TAG, "No setSurface method found");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// 4. Start playback
|
|
223
|
+
try {
|
|
224
|
+
Method startMethod = appPlayerClass.getMethod("start", long.class);
|
|
225
|
+
startMethod.invoke(null, playerPtr);
|
|
226
|
+
Log.d(TAG, "Playback started");
|
|
227
|
+
} catch (NoSuchMethodException e) {
|
|
228
|
+
// Try play() instead of start()
|
|
229
|
+
try {
|
|
230
|
+
Method playMethod = appPlayerClass.getMethod("play", long.class);
|
|
231
|
+
playMethod.invoke(null, playerPtr);
|
|
232
|
+
Log.d(TAG, "Playback started (via play)");
|
|
233
|
+
} catch (NoSuchMethodException e2) {
|
|
234
|
+
Log.e(TAG, "No start/play method found");
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
isStreaming = true;
|
|
239
|
+
statusView.setVisibility(GONE);
|
|
240
|
+
|
|
241
|
+
} catch (Exception e) {
|
|
242
|
+
Log.e(TAG, "Failed to start stream", e);
|
|
243
|
+
statusView.setText("Start failed: " + e.getMessage());
|
|
244
|
+
}
|
|
136
245
|
}
|
|
137
|
-
|
|
246
|
+
|
|
138
247
|
/**
|
|
139
|
-
* Stop video streaming
|
|
248
|
+
* Stop video streaming.
|
|
140
249
|
*/
|
|
141
250
|
public void stopStream() {
|
|
142
|
-
if (!isStreaming) return;
|
|
143
|
-
|
|
144
|
-
Log.d(TAG, "Stopping
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
251
|
+
if (!isStreaming || playerPtr == 0) return;
|
|
252
|
+
|
|
253
|
+
Log.d(TAG, "Stopping stream...");
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
try {
|
|
257
|
+
Method stopMethod = appPlayerClass.getMethod("stop", long.class);
|
|
258
|
+
stopMethod.invoke(null, playerPtr);
|
|
259
|
+
Log.d(TAG, "Playback stopped");
|
|
260
|
+
} catch (NoSuchMethodException e) {
|
|
261
|
+
// Try pause() instead
|
|
262
|
+
try {
|
|
263
|
+
Method pauseMethod = appPlayerClass.getMethod("pause", long.class);
|
|
264
|
+
pauseMethod.invoke(null, playerPtr);
|
|
265
|
+
Log.d(TAG, "Playback paused");
|
|
266
|
+
} catch (NoSuchMethodException e2) {
|
|
267
|
+
Log.w(TAG, "No stop/pause method found");
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
isStreaming = false;
|
|
272
|
+
statusView.setVisibility(VISIBLE);
|
|
273
|
+
statusView.setText("Stream stopped");
|
|
274
|
+
|
|
275
|
+
} catch (Exception e) {
|
|
276
|
+
Log.e(TAG, "Failed to stop stream", e);
|
|
277
|
+
}
|
|
148
278
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
279
|
+
|
|
280
|
+
private void releasePlayer() {
|
|
281
|
+
if (playerPtr == 0) return;
|
|
282
|
+
|
|
283
|
+
try {
|
|
284
|
+
stopStream();
|
|
285
|
+
|
|
286
|
+
try {
|
|
287
|
+
Method releaseMethod = appPlayerClass.getMethod("release", long.class);
|
|
288
|
+
releaseMethod.invoke(null, playerPtr);
|
|
289
|
+
Log.d(TAG, "Player released");
|
|
290
|
+
} catch (NoSuchMethodException e) {
|
|
291
|
+
// Try destroy() instead
|
|
292
|
+
try {
|
|
293
|
+
Method destroyMethod = appPlayerClass.getMethod("destroy", long.class);
|
|
294
|
+
destroyMethod.invoke(null, playerPtr);
|
|
295
|
+
Log.d(TAG, "Player destroyed");
|
|
296
|
+
} catch (NoSuchMethodException e2) {
|
|
297
|
+
Log.w(TAG, "No release/destroy method found");
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
playerPtr = 0;
|
|
302
|
+
|
|
303
|
+
} catch (Exception e) {
|
|
304
|
+
Log.e(TAG, "Failed to release player", e);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// TextureView.SurfaceTextureListener
|
|
309
|
+
|
|
152
310
|
@Override
|
|
153
|
-
public void onSurfaceTextureAvailable(
|
|
311
|
+
public void onSurfaceTextureAvailable(
|
|
312
|
+
SurfaceTexture surfaceTexture, int width, int height) {
|
|
154
313
|
Log.d(TAG, "Surface available: " + width + "x" + height);
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
314
|
+
this.surface = new Surface(surfaceTexture);
|
|
315
|
+
|
|
316
|
+
// If already supposed to be streaming, try to update surface
|
|
317
|
+
if (isStreaming && playerPtr != 0 && appPlayerClass != null) {
|
|
318
|
+
try {
|
|
319
|
+
Method setSurfaceMethod = appPlayerClass.getMethod(
|
|
320
|
+
"setSurface", long.class, Surface.class);
|
|
321
|
+
setSurfaceMethod.invoke(null, playerPtr, surface);
|
|
322
|
+
Log.d(TAG, "Surface updated on existing player");
|
|
323
|
+
} catch (Exception e) {
|
|
324
|
+
Log.e(TAG, "Failed to update surface", e);
|
|
325
|
+
}
|
|
158
326
|
}
|
|
159
327
|
}
|
|
160
|
-
|
|
328
|
+
|
|
161
329
|
@Override
|
|
162
|
-
public void onSurfaceTextureSizeChanged(
|
|
330
|
+
public void onSurfaceTextureSizeChanged(
|
|
331
|
+
SurfaceTexture surface, int width, int height) {
|
|
163
332
|
Log.d(TAG, "Surface size changed: " + width + "x" + height);
|
|
164
333
|
}
|
|
165
|
-
|
|
334
|
+
|
|
166
335
|
@Override
|
|
167
336
|
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
|
|
168
337
|
Log.d(TAG, "Surface destroyed");
|
|
169
338
|
stopStream();
|
|
170
|
-
|
|
339
|
+
if (this.surface != null) {
|
|
340
|
+
this.surface.release();
|
|
341
|
+
this.surface = null;
|
|
342
|
+
}
|
|
171
343
|
return true;
|
|
172
344
|
}
|
|
173
|
-
|
|
345
|
+
|
|
174
346
|
@Override
|
|
175
347
|
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
|
|
176
|
-
//
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
private void initializePlayer(SurfaceTexture surface, int width, int height) {
|
|
180
|
-
// Native player initialization will be implemented based on SDK API
|
|
181
|
-
Log.d(TAG, "Initializing player for surface");
|
|
348
|
+
// Frame rendered - nothing to do
|
|
182
349
|
}
|
|
183
|
-
|
|
184
|
-
private void releasePlayer() {
|
|
185
|
-
if (playerPtr != 0) {
|
|
186
|
-
// Release native player resources
|
|
187
|
-
playerPtr = 0;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
350
|
+
|
|
191
351
|
@Override
|
|
192
352
|
protected void onDetachedFromWindow() {
|
|
193
353
|
super.onDetachedFromWindow();
|
|
194
|
-
stopStream();
|
|
195
354
|
releasePlayer();
|
|
196
355
|
}
|
|
197
356
|
}
|