Пример #1
0
    def test_audio_stop_source(self):
        source = AudioStreamTrack()
        relay = MediaRelay()
        proxy1 = relay.subscribe(source)
        proxy2 = relay.subscribe(source)

        # read some frames
        samples_per_frame = 160
        for pts in range(0, 2 * samples_per_frame, samples_per_frame):
            frame1, frame2 = run(asyncio.gather(proxy1.recv(), proxy2.recv()))

            self.assertEqual(frame1.format.name, "s16")
            self.assertEqual(frame1.layout.name, "mono")
            self.assertEqual(frame1.pts, pts)
            self.assertEqual(frame1.samples, samples_per_frame)

            self.assertEqual(frame2.format.name, "s16")
            self.assertEqual(frame2.layout.name, "mono")
            self.assertEqual(frame2.pts, pts)
            self.assertEqual(frame2.samples, samples_per_frame)

        # stop source track
        source.stop()

        # continue reading
        run(asyncio.gather(proxy1.recv(), proxy2.recv()))
        for i in range(2):
            exc1, exc2 = run(
                asyncio.gather(proxy1.recv(), proxy2.recv(), return_exceptions=True)
            )
            self.assertTrue(isinstance(exc1, MediaStreamError))
            self.assertTrue(isinstance(exc2, MediaStreamError))
Пример #2
0
    def test_track_ended(self):
        track = AudioStreamTrack()
        sender = RTCRtpSender(track, self.local_transport)
        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        track.stop()
        run(asyncio.sleep(0.5))
Пример #3
0
    def test_track_ended(self):
        track = AudioStreamTrack()
        sender = RTCRtpSender(track, self.local_transport)
        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # stop track and wait for RTP loop to exit
        track.stop()
        run(asyncio.sleep(0.1))
Пример #4
0
    async def test_track_ended(self):
        async with dummy_dtls_transport_pair() as (local_transport, _):
            track = AudioStreamTrack()
            sender = RTCRtpSender(track, local_transport)

            await sender.send(RTCRtpParameters(codecs=[PCMU_CODEC]))

            # stop track and wait for RTP loop to exit
            track.stop()
            await asyncio.sleep(0.1)
Пример #5
0
    def test_track_ended(self):
        transport, _ = dummy_dtls_transport_pair()

        track = AudioStreamTrack()
        sender = RTCRtpSender(track, transport)
        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        track.stop()
        run(asyncio.sleep(0.5))

        run(transport.stop())
Пример #6
0
    def test_audio_wav_ended(self):
        track = AudioStreamTrack()

        recorder = MediaRecorder(self.temporary_path("test.wav"))
        recorder.addTrack(track)
        run(recorder.start())
        run(asyncio.sleep(1))
        track.stop()
        run(asyncio.sleep(1))

        run(recorder.stop())
Пример #7
0
    def test_audio_ended(self):
        track = AudioStreamTrack()

        recorder = MediaBlackhole()
        recorder.addTrack(track)
        run(recorder.start())
        run(asyncio.sleep(1))
        track.stop()
        run(asyncio.sleep(1))

        run(recorder.stop())
Пример #8
0
    async def test_audio_slow_consumer(self):
        source = AudioStreamTrack()
        relay = MediaRelay()
        proxy1 = relay.subscribe(source, buffered=False)
        proxy2 = relay.subscribe(source, buffered=False)

        # read some frames
        samples_per_frame = 160
        for pts in range(0, 2 * samples_per_frame, samples_per_frame):
            frame1, frame2 = await asyncio.gather(proxy1.recv(), proxy2.recv())

            self.assertEqual(frame1.format.name, "s16")
            self.assertEqual(frame1.layout.name, "mono")
            self.assertEqual(frame1.pts, pts)
            self.assertEqual(frame1.samples, samples_per_frame)

            self.assertEqual(frame2.format.name, "s16")
            self.assertEqual(frame2.layout.name, "mono")
            self.assertEqual(frame2.pts, pts)
            self.assertEqual(frame2.samples, samples_per_frame)

        # skip some frames
        timestamp = 5 * samples_per_frame
        await asyncio.sleep(source._start + (timestamp / 8000) - time.time())

        frame1, frame2 = await asyncio.gather(proxy1.recv(), proxy2.recv())
        self.assertEqual(frame1.format.name, "s16")
        self.assertEqual(frame1.layout.name, "mono")
        self.assertEqual(frame1.pts, 5 * samples_per_frame)
        self.assertEqual(frame1.samples, samples_per_frame)

        self.assertEqual(frame2.format.name, "s16")
        self.assertEqual(frame2.layout.name, "mono")
        self.assertEqual(frame2.pts, 5 * samples_per_frame)
        self.assertEqual(frame2.samples, samples_per_frame)

        # stop a consumer
        proxy1.stop()

        # continue reading
        for i in range(2):
            exc1, frame2 = await asyncio.gather(proxy1.recv(),
                                                proxy2.recv(),
                                                return_exceptions=True)
            self.assertTrue(isinstance(exc1, MediaStreamError))
            self.assertTrue(isinstance(frame2, av.AudioFrame))

        # stop source track
        source.stop()
Пример #9
0
 def test_audio_and_video(self):
     recorder = MediaBlackhole()
     recorder.addTrack(AudioStreamTrack())
     recorder.addTrack(VideoStreamTrack())
     run(recorder.start())
     run(asyncio.sleep(2))
     run(recorder.stop())
Пример #10
0
    def test_addTrack_video(self):
        pc = RTCPeerConnection()

        # add video track
        video_track = VideoStreamTrack()
        video_sender = pc.addTrack(video_track)
        self.assertIsNotNone(video_sender)
        self.assertEqual(video_sender.track, video_track)
        self.assertEqual(pc.getSenders(), [video_sender])

        # try to add same track again
        with self.assertRaises(InvalidAccessError) as cm:
            pc.addTrack(video_track)
        self.assertEqual(str(cm.exception), 'Track already has a sender')

        # try adding another video track
        with self.assertRaises(InternalError) as cm:
            pc.addTrack(VideoStreamTrack())
        self.assertEqual(str(cm.exception),
                         'Only a single video track is supported for now')

        # add audio track
        audio_track = AudioStreamTrack()
        audio_sender = pc.addTrack(audio_track)
        self.assertIsNotNone(audio_sender)
        self.assertEqual(audio_sender.track, audio_track)
        self.assertEqual(pc.getSenders(), [video_sender, audio_sender])
Пример #11
0
    def __init__(self, uri, player=None, recorder=MediaBlackhole()):
        self._uri = uri
        self._player = player
        self._recorder = recorder
        # Save answers temporarily
        self._answers = {}
        self._websocket = None
        self._device = None

        self._tracks = []

        if player and player.audio:
            audioTrack = player.audio
        else:
            audioTrack = AudioStreamTrack()
        if player and player.video:
            videoTrack = player.video
        else:
            videoTrack = VideoStreamTrack()

        self._videoTrack = videoTrack
        self._audioTrack = audioTrack

        self._tracks.append(videoTrack)
        self._tracks.append(audioTrack)

        self._sendTransport: Optional[Transport] = None
        self._recvTransport: Optional[Transport] = None

        self._producers = []
        self._consumers = []
        self._tasks = []
        self._closed = False
Пример #12
0
    def test_stop(self):
        sender = RTCRtpSender(AudioStreamTrack(), self.local_transport)
        self.assertEqual(sender.kind, 'audio')

        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # clean shutdown
        run(sender.stop())
 def test_setRemoteDescription_unexpected_offer(self):
     pc = RTCPeerConnection()
     pc.addTrack(AudioStreamTrack())
     offer = run(pc.createOffer())
     run(pc.setLocalDescription(offer))
     with self.assertRaises(InvalidStateError) as cm:
         run(pc.setRemoteDescription(RTCSessionDescription(sdp='', type='offer')))
     self.assertEqual(str(cm.exception),
                      'Cannot handle offer in signaling state "have-local-offer"')
Пример #14
0
    async def test_stop(self):
        async with dummy_dtls_transport_pair() as (local_transport, _):
            sender = RTCRtpSender(AudioStreamTrack(), local_transport)
            self.assertEqual(sender.kind, "audio")

            await sender.send(RTCRtpParameters(codecs=[PCMU_CODEC]))

            # clean shutdown
            await sender.stop()
Пример #15
0
    def test_connection_error(self):
        """
        Close the underlying transport before the sender.
        """
        sender = RTCRtpSender(AudioStreamTrack(), self.local_transport)
        self.assertEqual(sender.kind, 'audio')

        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        run(self.local_transport.stop())
Пример #16
0
    async def test_connection_error(self):
        """
        Close the underlying transport before the sender.
        """
        async with dummy_dtls_transport_pair() as (local_transport, _):
            sender = RTCRtpSender(AudioStreamTrack(), local_transport)
            self.assertEqual(sender.kind, "audio")

            await sender.send(RTCRtpParameters(codecs=[PCMU_CODEC]))

            await local_transport.stop()
    def test_connection_error(self):
        transport, _ = dummy_transport_pair()
        encoder = PcmuEncoder()

        sender = RTCRtpSender(kind='audio')
        sender._track = AudioStreamTrack()
        run(
            asyncio.gather(
                sender._run(transport=transport,
                            encoder=encoder,
                            payload_type=0), transport.close()))
Пример #18
0
    def test_connection_error(self):
        """
        Close the underlying transport before the sender.
        """
        transport, _ = dummy_dtls_transport_pair()

        sender = RTCRtpSender(AudioStreamTrack(), transport)
        self.assertEqual(sender.kind, 'audio')
        self.assertEqual(sender.transport, transport)

        run(asyncio.gather(sender._run(codec=PCMU_CODEC), transport.close()))
Пример #19
0
    def test_stop(self):
        transport, _ = dummy_dtls_transport_pair()

        sender = RTCRtpSender(AudioStreamTrack(), transport)
        self.assertEqual(sender.kind, 'audio')
        self.assertEqual(sender.transport, transport)

        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # clean shutdown
        run(sender.stop())
Пример #20
0
    def test_addTrack_audio(self):
        pc = RTCPeerConnection()

        # add audio track
        track = AudioStreamTrack()
        sender = pc.addTrack(track)
        self.assertIsNotNone(sender)
        self.assertEqual(sender.track, track)
        self.assertEqual(pc.getSenders(), [sender])
        self.assertEqual(len(pc.getTransceivers()), 1)

        # try to add same track again
        with self.assertRaises(InvalidAccessError) as cm:
            pc.addTrack(track)
        self.assertEqual(str(cm.exception), 'Track already has a sender')

        # try adding another audio track
        with self.assertRaises(InternalError) as cm:
            pc.addTrack(AudioStreamTrack())
        self.assertEqual(str(cm.exception),
                         'Only a single audio track is supported for now')
Пример #21
0
    def test_connection_error(self):
        """
        Close the underlying transport before the sender.
        """
        transport, _ = dummy_dtls_transport_pair()

        sender = RTCRtpSender(AudioStreamTrack(), transport)
        self.assertEqual(sender.kind, 'audio')
        self.assertEqual(sender.transport, transport)

        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        run(transport.stop())
Пример #22
0
    def test_audio_wav(self):
        path = self.temporary_path("test.wav")
        recorder = MediaRecorder(path)
        recorder.addTrack(AudioStreamTrack())
        run(recorder.start())
        run(asyncio.sleep(2))
        run(recorder.stop())

        # check output media
        container = av.open(path, "r")
        self.assertEqual(len(container.streams), 1)
        self.assertEqual(container.streams[0].codec.name, "pcm_s16le")
        self.assertGreater(
            float(container.streams[0].duration * container.streams[0].time_base), 0
        )
Пример #23
0
    async def test_audio_mp3(self):
        path = self.temporary_path("test.mp3")
        recorder = MediaRecorder(path)
        recorder.addTrack(AudioStreamTrack())
        await recorder.start()
        await asyncio.sleep(2)
        await recorder.stop()

        # check output media
        container = av.open(path, "r")
        self.assertEqual(len(container.streams), 1)
        self.assertIn(container.streams[0].codec.name, ("mp3", "mp3float"))
        self.assertGreater(
            float(container.streams[0].duration *
                  container.streams[0].time_base), 0)
Пример #24
0
    def test_audio_and_video(self):
        path = self.temporary_path("test.mp4")
        recorder = MediaRecorder(path)
        recorder.addTrack(AudioStreamTrack())
        recorder.addTrack(VideoStreamTrack())
        run(recorder.start())
        run(asyncio.sleep(2))
        run(recorder.stop())

        # check output media
        container = av.open(path, "r")
        self.assertEqual(len(container.streams), 2)

        self.assertEqual(container.streams[0].codec.name, "aac")
        self.assertGreater(
            float(container.streams[0].duration * container.streams[0].time_base), 0
        )

        self.assertEqual(container.streams[1].codec.name, "h264")
        self.assertEqual(container.streams[1].width, 640)
        self.assertEqual(container.streams[1].height, 480)
        self.assertGreater(
            float(container.streams[1].duration * container.streams[1].time_base), 0
        )
Пример #25
0
from pymediasoup.rtp_parameters import RtpCapabilities, RtpParameters
from pymediasoup.sctp_parameters import SctpCapabilities, SctpStreamParameters
from pymediasoup.transport import Transport
from pymediasoup.models.transport import DtlsParameters
from pymediasoup.producer import Producer
from pymediasoup.data_producer import DataProducer
from pymediasoup.data_consumer import DataConsumer
from pymediasoup.errors import UnsupportedError
from pymediasoup.consumer import Consumer

from .fake_parameters import generateRouterRtpCapabilities, generateTransportRemoteParameters, generateConsumerRemoteParameters, generateDataProducerRemoteParameters, generateDataConsumerRemoteParameters
from .fake_handler import FakeHandler

logging.basicConfig(level=logging.DEBUG)

audioTrack = AudioStreamTrack()
videoTrack = VideoStreamTrack()
TRACKS = [videoTrack, audioTrack]


class TestMethods(unittest.IsolatedAsyncioTestCase):
    def test_create_device(self):
        device = Device(handlerFactory=AiortcHandler.createFactory(
            tracks=TRACKS))
        self.assertEqual(device.loaded, False)

    async def test_device_load(self):
        device = Device(handlerFactory=AiortcHandler.createFactory(
            tracks=TRACKS))
        await device.load(generateRouterRtpCapabilities())
        self.assertEqual(device.handlerName, 'aiortc')
Пример #26
0
 async def test_audio(self):
     recorder = MediaBlackhole()
     recorder.addTrack(AudioStreamTrack())
     await recorder.start()
     await asyncio.sleep(1)
     await recorder.stop()
Пример #27
0
 def test_addTrack_closed(self):
     pc = RTCPeerConnection()
     run(pc.close())
     with self.assertRaises(InvalidStateError) as cm:
         pc.addTrack(AudioStreamTrack())
     self.assertEqual(str(cm.exception), 'RTCPeerConnection is closed')
Пример #28
0
    def test_connect_audio_bidirectional(self):
        pc1 = RTCPeerConnection()
        pc1_states = track_states(pc1)

        pc2 = RTCPeerConnection()
        pc2_states = track_states(pc2)

        self.assertEqual(pc1.iceConnectionState, 'new')
        self.assertEqual(pc1.iceGatheringState, 'new')
        self.assertIsNone(pc1.localDescription)
        self.assertIsNone(pc1.remoteDescription)

        self.assertEqual(pc2.iceConnectionState, 'new')
        self.assertEqual(pc2.iceGatheringState, 'new')
        self.assertIsNone(pc2.localDescription)
        self.assertIsNone(pc2.remoteDescription)

        # create offer
        pc1.addTrack(AudioStreamTrack())
        offer = run(pc1.createOffer())
        self.assertEqual(offer.type, 'offer')
        self.assertTrue('m=audio ' in offer.sdp)
        self.assertFalse('a=candidate:' in offer.sdp)

        run(pc1.setLocalDescription(offer))
        self.assertEqual(pc1.iceConnectionState, 'new')
        self.assertEqual(pc1.iceGatheringState, 'complete')
        self.assertTrue('m=audio ' in pc1.localDescription.sdp)
        self.assertTrue('a=candidate:' in pc1.localDescription.sdp)
        self.assertTrue('a=sendrecv' in pc1.localDescription.sdp)
        self.assertTrue('a=fingerprint:sha-256' in pc1.localDescription.sdp)
        self.assertTrue('a=setup:actpass' in pc1.localDescription.sdp)

        # handle offer
        run(pc2.setRemoteDescription(pc1.localDescription))
        self.assertEqual(pc2.remoteDescription, pc1.localDescription)
        self.assertEqual(len(pc2.getReceivers()), 1)

        # create answer
        pc2.addTrack(AudioStreamTrack())
        answer = run(pc2.createAnswer())
        self.assertEqual(answer.type, 'answer')
        self.assertTrue('m=audio ' in answer.sdp)
        self.assertFalse('a=candidate:' in answer.sdp)

        run(pc2.setLocalDescription(answer))
        self.assertEqual(pc2.iceConnectionState, 'checking')
        self.assertEqual(pc2.iceGatheringState, 'complete')
        self.assertTrue('m=audio ' in pc2.localDescription.sdp)
        self.assertTrue('a=candidate:' in pc2.localDescription.sdp)
        self.assertTrue('a=sendrecv' in pc1.localDescription.sdp)
        self.assertTrue('a=fingerprint:sha-256' in pc2.localDescription.sdp)
        self.assertTrue('a=setup:active' in pc2.localDescription.sdp)

        # handle answer
        run(pc1.setRemoteDescription(pc2.localDescription))
        self.assertEqual(pc1.remoteDescription, pc2.localDescription)
        self.assertEqual(pc1.iceConnectionState, 'checking')

        # check outcome
        run(asyncio.sleep(1))
        self.assertEqual(pc1.iceConnectionState, 'completed')
        self.assertEqual(pc2.iceConnectionState, 'completed')

        # close
        run(pc1.close())
        run(pc2.close())
        self.assertEqual(pc1.iceConnectionState, 'closed')
        self.assertEqual(pc2.iceConnectionState, 'closed')

        # check state changes
        self.assertEqual(pc1_states['iceConnectionState'],
                         ['new', 'checking', 'completed', 'closed'])
        self.assertEqual(pc1_states['iceGatheringState'],
                         ['new', 'gathering', 'complete'])
        self.assertEqual(pc1_states['signalingState'],
                         ['stable', 'have-local-offer', 'stable', 'closed'])

        self.assertEqual(pc2_states['iceConnectionState'],
                         ['new', 'checking', 'completed', 'closed'])
        self.assertEqual(pc2_states['iceGatheringState'],
                         ['new', 'gathering', 'complete'])
        self.assertEqual(pc2_states['signalingState'],
                         ['stable', 'have-remote-offer', 'stable', 'closed'])
Пример #29
0
 def test_stop_before_send(self):
     transport, _ = dummy_dtls_transport_pair()
     sender = RTCRtpSender(AudioStreamTrack(), transport)
     run(sender.stop())
Пример #30
0
 def test_stop_before_send(self):
     sender = RTCRtpSender(AudioStreamTrack(), self.local_transport)
     run(sender.stop())