Skip to content

Commit b36a3ca

Browse files
committed
fix: reconnect pause after clean close, SDP control URL parsing, stale volatile comment
1 parent c5bb3af commit b36a3ca

1 file changed

Lines changed: 29 additions & 4 deletions

File tree

app/src/main/java/com/openipc/decoder/Decoder.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ public class Decoder extends Activity {
7373
private final BlockingQueue<Frame> pcmQueue = new ArrayBlockingQueue<>(32);
7474
private final byte[] nalBuffer = new byte[1024 * 1024];
7575

76-
// volatile: these fields are read/written from multiple threads
7776
private int nalSize; // only touched on the network thread — no volatile needed
7877
private volatile MediaCodec mDecoder;
7978
private SurfaceView mSurface;
@@ -855,6 +854,27 @@ private void parseSdpAudioRate(String sdp) {
855854
}
856855
}
857856

857+
/**
858+
* Parses per-track Control URLs from an SDP body (RFC 2326 §C.1.1).
859+
* Returns a 2-element array: [videoControlUrl, audioControlUrl].
860+
* Absolute "a=control:" values are used as-is; relative values are resolved
861+
* against {@code baseUrl}. Falls back to "{@code baseUrl}/trackID=N" if absent.
862+
*/
863+
private static String[] parseSdpControls(String sdp, String baseUrl) {
864+
String[] controls = { baseUrl + "/trackID=0", baseUrl + "/trackID=1" };
865+
int track = -1;
866+
for (String line : sdp.split("[\r\n]+")) {
867+
if (line.startsWith("m=video")) track = 0;
868+
else if (line.startsWith("m=audio")) track = 1;
869+
else if (line.startsWith("a=control:") && track >= 0) {
870+
String ctrl = line.substring("a=control:".length()).trim();
871+
// absolute URL used as-is; relative URL appended to base
872+
controls[track] = ctrl.startsWith("rtsp://") ? ctrl : baseUrl + "/" + ctrl;
873+
}
874+
}
875+
return controls;
876+
}
877+
858878
private void rtspConnect() throws Exception {
859879
nalSize = 0; // discard any partial NAL fragment from the previous session
860880
Uri uri = Uri.parse(mHost);
@@ -910,11 +930,13 @@ private void rtspConnect() throws Exception {
910930
sdpBodyLen -= n;
911931
}
912932
parseSdpAudioRate(sdp.toString());
933+
// parse per-track Control URLs; used for SETUP requests below
934+
String[] trackUrls = parseSdpControls(sdp.toString(), rtspUrl);
913935

914936
seq++;
915937
String type = mType ? "RTP/AVP/UDP;unicast;client_port=5000"
916938
: "RTP/AVP/TCP;unicast;interleaved=0-1";
917-
String video = "SETUP " + rtspUrl + "/trackID=0 RTSP/1.0\r\n" +
939+
String video = "SETUP " + trackUrls[0] + " RTSP/1.0\r\n" +
918940
"CSeq: " + seq + "\r\n" + auth + UA + "Transport: " + type + "\r\n\r\n";
919941
w.write(video.getBytes(StandardCharsets.UTF_8));
920942
w.flush();
@@ -930,7 +952,7 @@ private void rtspConnect() throws Exception {
930952
seq++;
931953
type = mType ? "RTP/AVP/UDP;unicast;client_port=5002"
932954
: "RTP/AVP/TCP;unicast;interleaved=2-3";
933-
String audio = "SETUP " + rtspUrl + "/trackID=1 RTSP/1.0\r\n" +
955+
String audio = "SETUP " + trackUrls[1] + " RTSP/1.0\r\n" +
934956
"CSeq: " + seq + "\r\n" + auth + UA + "Transport: " + type + "\r\n" +
935957
"Session: " + session + "\r\n\r\n";
936958
w.write(audio.getBytes(StandardCharsets.UTF_8));
@@ -1107,7 +1129,10 @@ private void startListener() {
11071129
if (!activeStream) {
11081130
runOnUiThread(() -> mConnect.setVisibility(View.VISIBLE));
11091131
rtspConnect();
1110-
retryDelay = 1000; // reset on successful connection
1132+
retryDelay = 1000; // reset backoff after any successful session
1133+
// brief pause before reconnecting after a clean server-side close;
1134+
// without this the loop hammers the camera with no delay
1135+
SystemClock.sleep(1000);
11111136
}
11121137
} catch (Exception e) {
11131138
Log.w(TAG, "Cannot connect rtsp: " + e.getMessage());

0 commit comments

Comments
 (0)