2 * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.samsung.android.modules.rtsp;
18 import android.net.Uri;
19 import android.util.Log;
21 import androidx.annotation.NonNull;
23 import com.alexvas.rtsp.RtspClient;
24 import com.alexvas.utils.NetUtils;
26 import org.jetbrains.annotations.NotNull;
27 import org.jetbrains.annotations.Nullable;
29 import java.net.Socket;
30 import java.util.concurrent.atomic.AtomicBoolean;
33 * RTSPClient class to implement RTSP client side functionalities
35 public class RTSPClient {
36 private static final String TAG = "RTSPClient";
37 private static volatile Socket clientSocket;
38 // TODO: Set sdpInfoSize properly without a hard-coded value.
39 private static final int sdpInfoSize = 35;
40 private static final int socketTimeout = 10000;
41 private String rtspUrl = null;
44 private final AtomicBoolean exitFlag;
45 private final ReceiveDataCallback streamCb;
46 private RtspClient mRtspClient;
47 private H264Decoder decoder;
52 * Interface to implement DataCallback from RTSP module to RTSP stream
54 public interface ReceiveDataCallback {
55 void pushData(byte[] frame);
59 * Interface to implement socket connection callback
61 public interface SocketConnectCallback {
62 void socketConnect(Boolean bool);
66 * RTSPClient class constructor
68 * @param exitFlag AtomicBoolean flag to exit execution
69 * @param cb callback object to send data to upper layer
71 public RTSPClient(AtomicBoolean exitFlag, ReceiveDataCallback cb) {
72 this.exitFlag = exitFlag;
77 * Method to create a client socket for RTSP connection with RTSP server
79 * @param socketCB socket connection callback to notify success/failure of socket creation
81 public void createClientSocket(SocketConnectCallback socketCB) {
82 if (rtspUrl == null || rtspUrl.isEmpty()) {
83 Log.e(TAG, "Failed create client socket: Invalid RTSP URL");
87 Uri uri = Uri.parse(rtspUrl);
89 Thread thread = new Thread(() -> {
91 clientSocket = NetUtils.createSocketAndConnect(uri.getHost(), uri.getPort(), socketTimeout);
92 if (clientSocket != null)
93 socketCB.socketConnect(true);
94 } catch (Exception e) {
95 socketCB.socketConnect(false);
96 Log.e(TAG, "Exception in RTSP client socket creation");
102 } catch (Exception e) {
103 Log.e(TAG, "Exception in RTSP client socket creation");
108 * Method to create RtspClient object to access RTSP lib from dependency
110 public void initRtspClient(String id, String password) {
112 RtspClient.RtspClientListener clientListener = new RtspClient.RtspClientListener() {
114 public void onRtspConnecting() {
115 Log.d(TAG, "Connecting to RTSP server");
119 public void onRtspConnected(@NonNull @NotNull RtspClient.SdpInfo sdpInfo) {
120 Log.d(TAG, "Connected to RTSP server");
121 if (sdpInfo.videoTrack != null) {
122 sps = sdpInfo.videoTrack.sps;
123 pps = sdpInfo.videoTrack.pps;
128 public void onRtspVideoNalUnitReceived(@NonNull @NotNull byte[] bytes, int i, int i1, long l) {
129 Log.i(TAG, "RTSP video stream callback -- video NAL units received. bytes.length = " + bytes.length + ", sdpInfoSize = " + sdpInfoSize);
130 if (bytes.length < sdpInfoSize)
131 decoder.initH264Decoder(sps, pps);
133 decoder.setRawH264Data(bytes);
137 public void onRtspAudioSampleReceived(@NonNull @NotNull byte[] bytes, int i, int i1, long l) {
138 //TODO : Decode the Audio Nal units (AAC encoded) received using audio decoder
139 Log.d(TAG, "RTSP audio stream callback");
143 public void onRtspDisconnected() {
144 decoder.stopDecoder();
145 Log.d(TAG, "Disconnected from RTSP server");
149 public void onRtspFailedUnauthorized() {
150 Log.d(TAG, "onRtspFailedUnauthorized");
154 public void onRtspFailed(@androidx.annotation.Nullable @Nullable String s) {
155 Log.d(TAG, "onRtspFailed");
159 Uri uri = Uri.parse(rtspUrl);
161 decoder = new H264Decoder(streamCb, height, width);
162 if ("".equalsIgnoreCase(id)) {
163 mRtspClient = new RtspClient.Builder(clientSocket, uri.toString(), exitFlag, clientListener)
167 .withUserAgent("RTSP sample Client")
170 mRtspClient = new RtspClient.Builder(clientSocket, uri.toString(), exitFlag, clientListener)
173 .withCredentials(id, password)
175 .withUserAgent("RTSP sample Client")
181 * Method to start RTSP streaming
183 public void start() {
184 mRtspClient.execute();
188 * Method to stop RTSP streaming
192 NetUtils.closeSocket(clientSocket);
193 decoder.stopDecoder();
194 } catch (Exception E) {
195 Log.e(TAG, "Error closing socket");
200 * Method to set RTSP URL
202 * @param url String for RTSP URL
204 public void setRtspUrl(String url) {
209 * Method to set RTSP frame resolution
211 * @param height Height of the RTSP stream
212 * @param width Width of the RTSP stream
214 public void setResolution(int height, int width) {
215 this.height = height;