Связь между Webrtc Android и Webrtc C # не работает - PullRequest
0 голосов
/ 17 декабря 2018

Я пытаюсь отправить аудио-видео с Android на код в c #, для этого я использовал 2 примера Интернета:

WebRtc.NET: WebRTC для C # & C ++ /CLI: https://github.com/radioman/WebRtc.NET

Y

WebRTC android: https://github.com/NG-Studio-Development/vidiochat-rtc/blob/master/app/src/main/java/fr/pchab/androidrtc/RtcActivity.java

Чтобы это работало, я изменил очень мало элементарных строк на Android Webrtc, оставив что-то вроде этого:

    package fr.pchab.webrtcclient;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
import org.webrtc.*;

public class WebRtcClient {
    private final static String TAG = WebRtcClient.class.getCanonicalName();
    private final static int MAX_PEER = 2;
    private boolean[] endPoints = new boolean[MAX_PEER];
    private PeerConnectionFactory factory;
    private HashMap<String, Peer> peers = new HashMap<>();
    private LinkedList<PeerConnection.IceServer> iceServers = new LinkedList<>();
    private PeerConnectionParameters pcParams;
    private MediaConstraints pcConstraints = new MediaConstraints();
    private MediaStream localMS;
    private VideoSource videoSource;
    private AudioSource audioSource;
    private RtcListener mListener;

    URI url = new URI("ws://192.168.1.8:9000");
    Map<String, Command> commandMap = new HashMap<String, Command>();
    WebSocketClient mWebSocketClient = new WebSocketClient(url) {

        @Override
        public void onOpen(ServerHandshake handshakedata) {
        }
        @Override
        public void onMessage(String message) {
            String from = null;

            commandMap.put("init", new CreateOfferCommand());
            commandMap.put("offer", new CreateAnswerCommand());
            commandMap.put("OnSuccessAnswer", new SetRemoteSDPCommand());
            commandMap.put("OnIceCandidate", new AddIceCandidateCommand());

            JSONObject payload = null;
            JSONObject data = null;
            try {
                data = new JSONObject(message);
            } catch (JSONException e) {
                e.printStackTrace();
            }

            try {
                String type = data.getString("command");
                if(type.equals("init")) {mListener.onCallReady("43343");
                    from = data.getString("from");
                }
                if(!peers.containsKey(from)) {
                    int endPoint = findEndPoint();
                    if(endPoint != MAX_PEER) {
                        try {
                            Peer peer = addPeer(from, endPoint);
                            peer.pc.addStream(localMS);
                            commandMap.get(type).execute(from, null);
                        }catch (Exception e) {
                        }
                    }
                } else {
                    commandMap.get(type).execute(from, data);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onClose(int code, String reason, boolean remote) {

        }

        @Override
        public void onError(Exception ex) {

        }
};

    public interface RtcListener {
        void onCallReady(String callId);

        void onStatusChanged(String newStatus);

        void onLocalStream(MediaStream localStream);

        void onAddRemoteStream(MediaStream remoteStream, int endPoint);

        void onRemoveRemoteStream(int endPoint);
    }

    private interface Command {
        void execute(String peerId, JSONObject payload) throws JSONException;
    }

    private class CreateOfferCommand implements Command {
        public void execute(String peerId, JSONObject payload) {
            Log.d(TAG, "CreateOfferCommand");
            Peer peer = peers.get(peerId);
            peer.pc.createOffer(peer, pcConstraints);
        }
    }

    private class CreateAnswerCommand implements Command {
        public void execute(String peerId, JSONObject payload) throws JSONException {
            Log.d(TAG, "CreateAnswerCommand");
            Peer peer = peers.get(peerId);
            SessionDescription sdp = new SessionDescription(
                    SessionDescription.Type.fromCanonicalForm(payload.getString("type")),
                    payload.getString("sdp")
            );
            peer.pc.setRemoteDescription(peer, sdp);

            peer.pc.createAnswer(peer, pcConstraints);

        }
    }

    private class SetRemoteSDPCommand implements Command {
        public void execute(String peerId, JSONObject payload) throws JSONException {
            Log.d(TAG, "SetRemoteSDPCommand");
            Peer peer = peers.get(peerId);
            SessionDescription sdp = new SessionDescription(
                    SessionDescription.Type.fromCanonicalForm(payload.getString("type")),
                    payload.getString("sdp")
            );
            peer.pc.setRemoteDescription(peer, sdp);
        }
    }

    private class AddIceCandidateCommand implements Command {
        public void execute(String peerId, JSONObject payload) throws JSONException {
            Log.d(TAG, "AddIceCandidateCommand");
            PeerConnection pc = peers.get(peerId).pc;
            if (pc.getRemoteDescription() != null) {
                IceCandidate candidate = new IceCandidate(
                        payload.getString("sdp_mid"),
                        payload.getInt("sdp_mline_index"),
                        payload.getString("sdp")
                );
                pc.addIceCandidate(candidate);
            }
        }
    }

    /**
     * Send a message through the signaling server
     *
     * @param to      id of recipient
     * @param type    type of message
     * @param payload payload of message
     * @throws JSONException
     */
    public void sendMessage(String to, String type, JSONObject payload) throws JSONException {
        JSONObject message = new JSONObject();
        message.put("command", type);
        if (type.equals("OnIceCandidate")) {
            message.put("candidate", payload);
        } else {
            message.put("desc", payload);
        }
        mWebSocketClient.send(String.valueOf(message));
    }


    private class Peer implements SdpObserver, PeerConnection.Observer {
        public PeerConnection pc;
        private PeerConnection pcss;
        private String id;
        private int endPoint;


        @Override
        public void onCreateSuccess(final SessionDescription sdp) {
            // TODO: modify sdp to use pcParams prefered codecs
            try {
                JSONObject payload = new JSONObject();
                payload.put("type", sdp.type.canonicalForm());
                payload.put("sdp", sdp.description);

                sendMessage(id, sdp.type.canonicalForm(), payload);
                pc.setLocalDescription(Peer.this, sdp);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onSetSuccess() {
        }

        @Override
        public void onCreateFailure(String s) {
        }

        @Override
        public void onSetFailure(String s) {

        }

        @Override
        public void onSignalingChange(PeerConnection.SignalingState signalingState) {
        }

        @Override
        public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
            if (iceConnectionState == PeerConnection.IceConnectionState.DISCONNECTED) {
                removePeer(id);
                mListener.onStatusChanged("DISCONNECTED");
            }
        }

        @Override
        public void onIceConnectionReceivingChange(boolean b) {

        }

        @Override
        public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {

        }

        @Override
        public void onIceCandidate(final IceCandidate candidate) {
            try {
                JSONObject payload = new JSONObject();
                payload.put("sdpMLineIndex", candidate.sdpMLineIndex);
                payload.put("sdpMid", candidate.sdpMid);
                payload.put("candidate", candidate.sdp);
                sendMessage(id,"OnIceCandidate",payload);

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onAddStream(MediaStream mediaStream) {
            Log.d(TAG, "onAddStream " + mediaStream.label());
            mListener.onAddRemoteStream(mediaStream, endPoint + 1);
        }

        @Override
        public void onRemoveStream(MediaStream mediaStream) {
            Log.d(TAG, "onRemoveStream " + mediaStream.label());
            removePeer(id);
        }

        @Override
        public void onDataChannel(DataChannel dataChannel) {
        }

        @Override
        public void onRenegotiationNeeded() {

        }

        public Peer(String id, int endPoint) {
            Log.d(TAG, "new Peer: " + id + " " + endPoint);


            this.pc = factory.createPeerConnection(iceServers, pcConstraints, this);
            this.id = id;
            this.endPoint = endPoint;
            pc.addStream(localMS); //, new MediaConstraints()

            mListener.onStatusChanged("CONNECTING");
        }

    }

    private Peer addPeer(String id, int endPoint) {
            Peer peer = new Peer(id, endPoint);
            peers.put(id, peer);

            endPoints[endPoint] = true;
            return peer;
    }

    private void removePeer(String id) {
            Peer peer = peers.get(id);
            mListener.onRemoveRemoteStream(peer.endPoint);
            peer.pc.close();
            peers.remove(peer.id);
            endPoints[peer.endPoint] = false;
    }

    public WebRtcClient(RtcListener listener, PeerConnectionParameters params, EglBase.Context mEGLcontext) throws URISyntaxException {
            mListener = listener;
            pcParams = params;
            PeerConnectionFactory.initializeAndroidGlobals(listener, true, true,
                    params.videoCodecHwAcceleration);
            factory = new PeerConnectionFactory();

            mWebSocketClient.connect();


        iceServers.add(new PeerConnection.IceServer("stun:stun.stunprotocol.org:3478"));
            iceServers.add(new PeerConnection.IceServer("stun:23.21.150.121"));iceServers.add(new PeerConnection.IceServer("stun:stun.anyfirewall.com:3478"));
            iceServers.add(new PeerConnection.IceServer("stun:stun.l.google.com:19302"));
            pcConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
            pcConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"));
            pcConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));



    }

        /**
         * Call this method in Activity.onPause()
         */
    public void onPause() {
            if (videoSource != null) videoSource.stop();

    }

        /**
         * Call this method in Activity.onResume()
         */
        public void onResume() {
            if (videoSource != null) videoSource.restart();
        }

        /**
         * Call this method in Activity.onDestroy()
         */
        public void onDestroy() {
            for (Peer peer : peers.values()) {
                peer.pc.close();
            }
            factory.dispose();
             mWebSocketClient.close();

        }

        private int findEndPoint() {
            for (int i = 0; i < MAX_PEER; i++) if (!endPoints[i]) return i;
            return MAX_PEER;
        }

        /**
         * Start the client.
         * <p>
         * Set up the local stream and notify the signaling server.
         * Call this method after onCallReady.
         *
         * @param
         */
        public void start() {
            setCamera();
        }

        private void setCamera() {
            localMS = factory.createLocalMediaStream("ARDAMS");
            if (pcParams.videoCallEnabled) {
                MediaConstraints videoConstraints = new MediaConstraints();
                videoConstraints.mandatory.add(new MediaConstraints.KeyValuePair("maxHeight", Integer.toString(pcParams.videoHeight)));
                videoConstraints.mandatory.add(new MediaConstraints.KeyValuePair("maxWidth", Integer.toString(pcParams.videoWidth)));
                videoConstraints.mandatory.add(new MediaConstraints.KeyValuePair("maxFrameRate", Integer.toString(pcParams.videoFps)));
                videoConstraints.mandatory.add(new MediaConstraints.KeyValuePair("minFrameRate", Integer.toString(pcParams.videoFps)));

                videoSource = factory.createVideoSource(getVideoCapturer(), videoConstraints);
                localMS.addTrack(factory.createVideoTrack("ARDAMSv0", videoSource));
            }

            audioSource = factory.createAudioSource(new MediaConstraints());
            localMS.addTrack(factory.createAudioTrack("ARDAMSa0", audioSource));
            mListener.onLocalStream(localMS);
        }

        private VideoCapturerAndroid getVideoCapturer() {
            int numberOfCameras = CameraEnumerationAndroid.getDeviceCount();
            if (numberOfCameras == 0) {
                if (BuildConfig.DEBUG) {
                    Log.w(TAG, "Failed to open camera.");
                }
                return null;
            } else {
                String deviceName = null;
                deviceName = CameraEnumerationAndroid.getNameOfFrontFacingDevice();
                if (deviceName == null) {
                    deviceName = CameraEnumerationAndroid.getDeviceName(0);
                }
                VideoCapturerAndroid videoCapturer = VideoCapturerAndroid.create(deviceName, new VideoCapturerAndroid.CameraEventsHandler() {

                    @Override
                    public void onCameraError(String s) {
                        if (BuildConfig.DEBUG) {
                            Log.d(TAG, "onCameraError: " + s);
                        }
                    }

                    @Override
                    public void onCameraFreezed(String s) {
                        if (BuildConfig.DEBUG) {
                            Log.d(TAG, "onCameraFreezed: " + s);
                        }
                    }

                    @Override
                    public void onCameraOpening(int i) {
                        if (BuildConfig.DEBUG) {
                            Log.d(TAG, "onCameraOpening: " + i);
                        }
                    }

                    @Override
                    public void onFirstFrameAvailable() {
                        if (BuildConfig.DEBUG) {
                            Log.d(TAG, "onFirstFrameAvailable: ");
                        }
                    }

                    @Override
                    public void onCameraClosed() {
                        if (BuildConfig.DEBUG) {
                            Log.d(TAG, "onCameraClosed: ");
                        }
                    }
                });
                return videoCapturer;
            }
        }
    }

И в коде C # я добавил только несколько строк:

WebRTCServer.cs:

>  server = new WebSocketServer(URL);
>             server.Start(socket =>
>             {
>                 socket.OnOpen = () =>
>                 {
>                     try
>                     {
>                         OnConnected(socket);
>                         JsonData j = new JsonData();
>                         j["command"] = "init";
>                         j["payload"] = "null";
>                         j["from"] = "dssdd";
>                         socket.Send(j.ToJson());
>                     }
>                     catch (Exception ex)
>                     {
>                         Debug.WriteLine($"OnConnected: {ex}");
>                     }
>                 };
>                 socket.OnMessage = message =>

Все работает:

Android подключается к C #, и это отправляет идентификатор, Android создает предложение, C # отвечает "ответ", Android отправляет кандидатов "OniceCandidate" и C # отправляет их, но я не могусмотрите видео андроида в c # ...

В чем ошибка?

Это SDP примера, который включен в проект c # webrtc, отправляемый браузером, когда все работает:

{"command": "offer", "desc": {"type": "offer", "sdp": "v = 0 \ r \ no = - 3749671025623748892 2 В IP4127.0.0.1 \ г \ нс= - \ r \ nt = 0 0 \ r \ na = группа: аудио-видео данные BUNDLE \ r \ na = семантическая семантика: WMS 95wgyGJiiigDyFS5umgHbvIDNV8tXSnuaJvw \ r \ nm = аудио 9 UDP / TLS / RTP / SAVPF 111 103 104 9 08 110 112 113 126 \ r \ nc = IN IP4 0.0.0.0 \ r \ na = rtcp: 9 IN IP4 0.0.0.0 \ r \ na = ice-ufrag: Qu5t \ r \ na = ice-pwd: GR / 7nOSN3iX6a +/ zijGFnAJm \ r \ na = варианты льда: струйка \ r \ na = отпечаток пальца: sha-256 C2: B6: 71: 98: 54: B1: 7F: 8C: 36: 18: 67: 24: 91: C0:E3: 04: D6: EC: B3: 59: 6E: D0: 17: D3: 45: 67: C5: 9F: D0: B0: BC: 1D \ г \ па = настройка: actpass \ г \ па = середина:audio \ r \ na = extmap: 1 urn: ietf: params: rtp-hdrext: ssrc-audio-level \ r \ na = recvonly \ r \ na = rtcp-mux \ r \ na = rtpmap: 111 opus / 48000 /2 \ r \ na = rtcp-fb: 111 transport-cc \ r \ na = fmtp: 111 minptime = 10; useinbandfec = 1 \ r \ na = rtpmap: 103 ISAC / 16000 \ r \ na = rtpmap: 104 ISAC /32000 \ r \ na = rtpmap: 9 G722 / 8000 \ r \ na = rtpmap: 0 PCMU / 8000 \ r \ na = rtpmap: 8 PCMA / 8000 \ r \ na = rtpmap: 110 телефонных событий / 48000 \ r \na = rtpmap: 112 телефонных событий / 32000 \ r \ na = rtpmap: 113 телефонных событий / 16000 \ r \ na = rtpmap: 126 телефонных событий / 8000 \ r \ nm = видео 9 UDP / TLS / RTP / SAVPF96 97 98 99 100 101 102 122 127 121 125 107 108109 124 120 123 119 114 \ r \ nc = IN IP4 0.0.0.0 \ r \ na = rtcp: 9 IN IP4 0.0.0.0 \ r \ na = ice-ufrag: Qu5t \ r \ na = ice-pwd: GR /7nOSN3iX6a + / zijGFnAJm \ r \ na = параметры льда: струйка \ r \ na = отпечаток пальца: sha-256 C2: B6: 71: 98: 54: B1: 7F: 8C: 36: 18: 67: 24: 91: C0: E3: 04: D6: EC: B3: 59: 6E: D0: 17: D3: 45: 67: C5: 9F: D0: B0: BC: 1D \ г \ па = настройка: actpass \ г \ па = середина: video \ r \ na = extmap: 2 urn: ietf: params: rtp-hdrext: toffset \ r \ na = extmap: 3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:4 urn: 3gpp: видео-ориентация \ r \ na = extmap: 5http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type\r\na=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/video-timing\r\na=sendrecv\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=rtpmap:96 VP8 / 90000 \ r \ na = rtcp-fb: 96 Гуг-Ремб \ r \ na = rtcp-fb: 96transport-cc \ r \ na = rtcp-fb: 96 см3 пихты \ r \ na = rtcp-fb: 96 nack \ r \ na = rtcp-fb: 96 nack pli \ r \ na = rtpmap: 97 rtx / 90000 \r \ na = fmtp: 97 apt = 96 \ r \ na = rtpmap: 98 VP9 / 90000 \ r \ na = rtcp-fb: 98 goog-remb \ r \ na = rtcp-fb: 98 transport-cc \ r \na = rtcp-fb: 98 см3 ели \ r \ na = rtcp-fb: 98 nack \ r \ na = rtcp-fb: 98 nack pli \ r \ na = fmtp: 98 x-google-profile-id = 0 \r \ na = rtpmap: 99 rtx / 90000 \ r \ na = fmtp: 99 apt = 98 \ r \ na = rtpmap: 100 H264 / 90000 \ r \ na = rtcp-fb: 100 Гуг-Ремб \ r \ na =rtcp-fb: 100 транспорт-cc \ r \ na = rtcp-fb: 100 см 3-ой \ r \ na = rtcp-fb: 100 nack \ r \ na = rtcp-fb: 100 nack pli \ r \ na = fmtp: 100 допускается асимметрия уровня = 1; режим пакетирования = 1; идентификатор уровня профиля = 42001f \r \ na = rtpmap: 101 rtx / 90000 \ r \ na = fmtp: 101 apt = 100 \ r \ na = rtpmap: 102 H264 / 90000 \ r \ na = rtcp-fb: 102 Гуг-Ремб \ r \ na =rtcp-fb: 102 transport-cc \ r \ na = rtcp-fb: 102 куб. см ель \ r \ na = rtcp-fb: 102 nack \ r \ na = rtcp-fb: 102 nack pli \ r \ na = fmtp:102 level-асимметрия-разрешено = 1; режим пакетирования = 0; ID-уровня профиля = 42001f \ r \ na = rtpmap: 122 rtx / 90000 \ r \ na = fmtp: 122 apt = 102 \ r \ na = rtpmap: 127 H264 / 90000 \ r \ na = rtcp-fb: 127 Гуг-Ремб \ r \ na = rtcp-fb: 127 transport-cc \ r \ na = rtcp-fb: 127 куб.см пихты \ r \ na = rtcp-fb: 127 nack \ r \ na = rtcp-fb: 127 nack pli \ r \ na = fmtp: 127 level-асимметрия разрешена = 1; режим пакетирования = 1; идентификатор уровня профиля = 42e01f \ r \ na =rtpmap: 121 rtx / 90000 \ r \ na = fmtp: 121 apt = 127 \ r \ na = rtpmap: 125 H264 / 90000 \ r \ na = rtcp-fb: 125 goog-remb \ r \ na = rtcp-fb:125transport-cc \ r \ na = rtcp-fb: 125 см 3 ели \ r \ na = rtcp-fb: 125 nack \ r \ na = rtcp-fb: 125 nack pli \ r \ na = fmtp: 125 асимметрия уровняразрешено = 1; режим пакетирования = 0; идентификатор уровня профиля = 42e01f \ r \ na = rtpmap: 107 rtx / 90000 \ r \ na = fmtp: 107 apt = 125 \ r \ na = rtpmap: 108 H264 / 90000\ r \ na = rtcp-fb: 108 goog-remb \ r \ na = rtcp-fb: 108 transport-cc \ r \ na = rtcp-fb: 108 см3 пихты \ r \ na = rtcp-fb: 108 nack \r \ na = rtcp-fb: 108 nack pli \ r \ na = fmtp: 108 уровень-асимметрия-разрешено = 1; режим пакетирования = 1; идентификатор уровня профиля = 4d0032 \ r \ na = rtpmap: 109 RTX /90000 \ r \ na = fmtp: 109 apt = 108 \ r \ na = rtpmap: 124 H264 / 90000 \ r \ na = rtcp-fb: 124 Гуг-Ремб \ r \ na = rtcp-fb: 124 transport-cc \r \ na = rtcp-fb: 124 см3 пихты \ r \ na = rtcp-fb: 124 nack \ r \ na = rtcp-fb: 124 nack pli \ r \ na = fmtp: 124 допускается асимметрия уровней = 1;режим пакетирования = 1; идентификатор уровня профиля = 640032 \ r \ na = rtpmap: 120 rtx / 90000 \ r \ na = fmtp: 120 apt = 124 \ r \ na = rtpmap: 123 красный / 90000 \ r \ na= rtpmap: 119 rtx / 90000 \ r \ na = fmtp: 119 apt = 123 \ r \ na = rtpmap: 114 ulpfec / 90000 \ r \ na = ssrc-group: FID 4194873059 100873727 \ r \ na = ssrc: 4194873059 cname: Ni0yVpvQbRjE7vuV \ г \ па = SSRC: 4194873059 MSID: 95wgyGJiiigDyFS5umgHbvIDNV8tXSnuaJvw 74489e91-cf6f-4b77-bad0-877ae827e956 \ г \ па = SSRC: 4194873059 mslabel: 95wgyGJiiigDyFS5umgHbvIDNV8tXSnuaJvw \ г \ па = SSRC: 4194873059 этикетки: 74489e91-cf6f-4b77-bad0-877ae827e956 \ г \ па = SSRC:100873727 CNAME: Ni0yVpvQbRjE7vuV \ г \ па = SSRC: 100873727 MSID: 95wgyGJiiigDyFS5umgHbvIDNV8tXSnuaJvw 74489e91-cf6f-4b77-bad0-877ae827e956 \ г \ па = SSRC: 100873727 mslabel: 95wgyGJiiigDyFS5umgHbvIDNV8tXSnuaJvw \ г \ па = SSRC: 100873727 этикетки: 74489e91-cf6f-4b77-bad0-877ae827e956 \ r \ nm = приложение 9 DTLS / SCTP 5000 \ r \ nc = IN IP4 0.0.0.0 \ r \ na = ice-ufrag: Qu5t \ r \ na = ice-pwd: GR / 7nOSN3iX6a + / zijGFnAJm \r \ na = варианты льда: струйка \ r \ na = отпечаток пальца: sha-256 C2: B6: 71: 98: 54: B1: 7F: 8C: 36: 18: 67: 24: 91: C0: E3: 04: D6: EC: B3: 59: 6E: D0: 17: D3: 45: 67: С5: 9F: D0: В0: БК: 1D \ г \ па = настройка: actpass \ г \ па = середина: данные \ г\ na = sctpmap: 5000 webrtc-datachannel 1024 \ r \ n "}}

И он отправляется Android, когда он не работает:

{" команда":" offer "," desc ": {" type ":" offer "," sdp ":" v = 0 \ r \ no = - 3249596690369492550 2 IN IP4 127.0.0.1 \ r \ ns = - \ r \ nt = 0 0 \ r \ na = группа: BUNDLE аудио-видео \ r \ na = msid-семантическая: WMS ARDAMS \ r \ nm = аудио 9 UDP / TLS / RTP/ SAVPF 111 103 9 102 0 8 106 105 13 127 126 \ r \ nc = IN IP4 0.0.0.0 \ r \ na = rtcp: 9 IN IP4 0.0.0.0 \ r \ na = ice-ufrag: jPCWe7 + gO1oQqWy4 \ r\ na = ice-pwd: w4wHHFbcmRUO9RfUeu6pMpaZ \ r \ na = отпечаток пальца: sha-256 88: 8E: 42: C5: 1E: A2: CE: CA: 61: 84: DD: F6: D8: 0B: CD: 84:83: 88: 62: 26: 46: 9D: С6: 1F: АВ: 47: 1A: 08: С2: FF: 99: 93 \ г \ па = настройка: actpass \ г \ па = середина: аудио \ г \na = extmap: 1 urn: ietf: params: rtp-hdrext: ssrc-audio-level \ r \ na = extmap: 3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:111 opus / 48000/2 \ r \ na = fmtp: 111 minptime = 10;useinbandfec = 1 \ r \ na = rtpmap: 103 ISAC / 16000 \ r \ na = rtpmap: 9 G722 / 8000 \ r \ na = rtpmap: 102 ILBC / 8000 \ r \ na = rtpmap: 0 PCMU / 8000 \ r \na = rtpmap: 8 PCMA / 8000 \ r \ na = rtpmap: 106 CN / 32000 \ r \ na = rtpmap: 105 CN / 16000 \ r \ na = rtpmap: 13 CN / 8000 \ r \ na = rtpmap: 127 красный/ 8000 \ r \ na = rtpmap: 126 телефонных событий / 8000 \ r \ na = maxptime: 60 \ r \ na = ssrc: 3529019873 cname: mOSyu2KsIeUHPgGT \ r \ na = ssrc: 3529019873 msid: ARDAMS ARDAMSa0 \ r \ na= ssrc: 3529019873 mslabel: ARDAMS \ r \ na = ssrc: 3529019873 метка: ARDAMSa0 \ r \ nm = видео 9 UDP / TLS / RTP / SAVPF 100 101 116 117 96 \ r \ nc = IN IP4 0.0.0.0 \ r \na = rtcp: 9 IN IP4 0.0.0.0 \ r \ na = ice-ufrag: jPCWe7 + gO1oQqWy4 \ r \ na = ice-pwd: w4wHHFbcmRUO9RfUeu6pMpaZ \ r \ na = отпечаток пальца: sha-256 88: 8E: 42: C5:1E: A2: CE: CA: 61: 84: DD: F6: D8: 0B: CD: 84: 83: 88: 62: 26: 46: 9D: С6: 1F: АВ: 47: 1A: 08: С2:FF: 99: 93 \ r \ na = setup: actpass \ r \ na = mid: video \ r \ na = extmap: 2 urn: ietf: params: rtp-hdrext: toffset \ r \ na = extmap: 3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:4 urn: 3gpp: видео-ориентация \ r \ na = sendrecv \ r \ na = rtcp-mux \ r \ na = rtpmap: 100 VP8 / 90000 \ r \ na = rtcp-fb: 100 см 3 ели \ r \ na =rtcp-fb: 100 nack \ r \ na = rtcp-fb: 100 nack pli \ r \ na= rtcp-fb: 100 goog-remb \ r \ na = rtcp-fb: 100 transport-cc \ r \ na = rtpmap: 101 VP9 / 90000 \ r \ na = rtcp-fb: 101 см 3 ели \ r \ na =rtcp-fb: 101 nack \ r \ na = rtcp-fb: 101 nack pli \ r \ na = rtcp-fb: 101 goog-remb \ r \ na = rtcp-fb: 101 transport-cc \ r \ na = rtpmap: 116 красных / 90000 \ r \ na = rtpmap: 117 ulpfec / 90000 \ r \ na = rtpmap: 96RTX / 90000 \ r \ na = fmtp: 96 apt = 100 \ r \ na = ssrc-группа: FID 628832251 3674354975 \ r \ na = ssrc: 628832251 cname: mOSyu2KsIeUHPgGT \ r \ na = ssrc: 628832SMS1r \ na = ssrc: 628832251 mslabel: ARDAMS \ r \ na = ssrc: 628832251 метка: ARDAMSv0 \ r \ na = ssrc: 3674354975 cname: mOSyu2KsIeUHPgGT \ r \ na = ssrc: 3674SRMS MSRSRSID ms: ssrc: rsdSrc: rsdSrc: rsdSrc: msgrr:: 3674354975 mslabel: ARDAMS \ r \ na = ssrc: 3674354975 метка: ARDAMSv0 \ r \ n "}}

Я обнаружил, что разница между ними:

Первыйговорит "recvonly", а второй (android) говорит: "recvsend" Это будет проблемой, несовместимы ли кодеки?

Моя цель - отправить видео с Android на c #.

Это «ответ» c #, когда он работает с браузером:

URL: i.stack.imgur.com/0gcNn.jpg

И это «ответ», когда онНЕ работает с android:

URL: i.stack.imgur.com/2nc65.jpg

Как мне это решить?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...